ctu_can_fd.c 27.7 KB
Newer Older
1
// SPDX-License-Identifier: GPL-2.0+
2
/*******************************************************************************
Martin Jeřábek's avatar
Martin Jeřábek committed
3
 *
4
 * CTU CAN FD IP Core
5
 * Copyright (C) 2015-2018
Martin Jeřábek's avatar
Martin Jeřábek committed
6
 *
7 8
 * Authors:
 *     Ondrej Ille <ondrej.ille@gmail.com>
Ille, Ondrej, Ing.'s avatar
Ille, Ondrej, Ing. committed
9
 *     Martin Jerabek <martin.jerabek01@gmail.com>
Martin Jeřábek's avatar
Martin Jeřábek committed
10 11
 *
 * Project advisors:
12 13
 *     Jiri Novak <jnovak@fel.cvut.cz>
 *     Pavel Pisa <pisa@cmp.felk.cvut.cz>
Martin Jeřábek's avatar
Martin Jeřábek committed
14
 *
15 16 17
 * Department of Measurement         (http://meas.fel.cvut.cz/)
 * Faculty of Electrical Engineering (http://www.fel.cvut.cz)
 * Czech Technical University        (http://www.cvut.cz/)
Martin Jeřábek's avatar
Martin Jeřábek committed
18
 *
19 20 21 22
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
Martin Jeřábek's avatar
Martin Jeřábek committed
23
 *
24 25 26 27
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
28
 ******************************************************************************/
29

Martin Jeřábek's avatar
Martin Jeřábek committed
30 31 32 33 34 35 36 37 38 39 40 41 42
#include <linux/clk.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/skbuff.h>
#include <linux/string.h>
#include <linux/types.h>
#include <linux/can/error.h>
#include <linux/can/led.h>
#include <linux/pm_runtime.h>
43

44
#include "ctu_can_fd.h"
Martin Jeřábek's avatar
Martin Jeřábek committed
45
#include "ctu_can_fd_regs.h"
46

47 48 49 50 51 52
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Martin Jerabek");
MODULE_DESCRIPTION("CTU CAN FD interface");

#define DRV_NAME "ctucanfd"

53
static const char * const ctucan_state_strings[] = {
54 55 56 57 58 59
	"CAN_STATE_ERROR_ACTIVE",
	"CAN_STATE_ERROR_WARNING",
	"CAN_STATE_ERROR_PASSIVE",
	"CAN_STATE_BUS_OFF",
	"CAN_STATE_STOPPED",
	"CAN_STATE_SLEEPING"
60 61
};

62
/* TX buffer rotation:
Martin Jeřábek's avatar
Martin Jeřábek committed
63
 * - when a buffer transitions to empty state, rotate order and priorities
64 65 66 67 68 69
 * - if more buffers seem to transition at the same time, rotate
 *   by the number of buffers
 * - it may be assumed that buffers transition to empty state in FIFO order
 *   (because we manage priorities that way)
 * - at frame filling, do not rotate anything, just increment buffer modulo
 *   counter
Martin Jeřábek's avatar
Martin Jeřábek committed
70 71 72
 */


73
#define CTUCAN_FLAG_RX_FFW_BUFFERED	1
74

Martin Jeřábek's avatar
Martin Jeřábek committed
75 76
static int ctucan_reset(struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
77
	int i;
Martin Jeřábek's avatar
Martin Jeřábek committed
78
	struct ctucan_priv *priv = netdev_priv(ndev);
79

80
	netdev_dbg(ndev, "ctucan_reset");
Martin Jeřábek's avatar
Martin Jeřábek committed
81

82
	ctucan_hw_reset(&priv->p);
83
	for (i = 0; i < 100; ++i) {
84
		if (ctucan_hw_check_access(&priv->p))
Martin Jeřábek's avatar
Martin Jeřábek committed
85
			return 0;
86
		usleep_range(100, 200);
Martin Jeřábek's avatar
Martin Jeřábek committed
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101
	}

	netdev_warn(ndev, "device did not leave reset\n");
	return -ETIMEDOUT;
}

/**
 * ctucan_set_bittiming - CAN set bit timing routine
 * @ndev:	Pointer to net_device structure
 *
 * This is the driver set bittiming routine.
 * Return: 0 on success and failure value on error
 */
static int ctucan_set_bittiming(struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
102
	struct ctucan_priv *priv = netdev_priv(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
103
	struct can_bittiming *bt = &priv->can.bittiming;
104

105
	netdev_dbg(ndev, "ctucan_set_bittiming");
Martin Jeřábek's avatar
Martin Jeřábek committed
106

107
	if (ctucan_hw_is_enabled(&priv->p)) {
Martin Jeřábek's avatar
Martin Jeřábek committed
108
		netdev_alert(ndev,
109
			     "BUG! Cannot set bittiming - CAN is enabled\n");
Martin Jeřábek's avatar
Martin Jeřábek committed
110 111 112
		return -EPERM;
	}

Martin Jeřábek's avatar
Martin Jeřábek committed
113
	/* Note that bt may be modified here */
114
	ctucan_hw_set_nom_bittiming(&priv->p, bt);
Martin Jeřábek's avatar
Martin Jeřábek committed
115 116 117 118 119 120 121 122 123 124 125 126 127

	return 0;
}

/**
 * ctucan_set_data_bittiming - CAN set data bit timing routine
 * @ndev:	Pointer to net_device structure
 *
 * This is the driver set data bittiming routine.
 * Return: 0 on success and failure value on error
 */
static int ctucan_set_data_bittiming(struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
128
	struct ctucan_priv *priv = netdev_priv(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
129
	struct can_bittiming *dbt = &priv->can.data_bittiming;
130

131
	netdev_dbg(ndev, "ctucan_set_data_bittiming");
Martin Jeřábek's avatar
Martin Jeřábek committed
132

133
	if (ctucan_hw_is_enabled(&priv->p)) {
Martin Jeřábek's avatar
Martin Jeřábek committed
134
		netdev_alert(ndev,
135
			     "BUG! Cannot set bittiming - CAN is enabled\n");
Martin Jeřábek's avatar
Martin Jeřábek committed
136 137 138
		return -EPERM;
	}

Martin Jeřábek's avatar
Martin Jeřábek committed
139
	/* Note that dbt may be modified here */
140
	ctucan_hw_set_data_bittiming(&priv->p, dbt);
Martin Jeřábek's avatar
Martin Jeřábek committed
141 142 143 144

	return 0;
}

145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166
/**
 * ctucan_set_secondary_sample_point - CAN set secondary sample point routine
 * @ndev:	Pointer to net_device structure
 *
 * Return: 0 on success and failure value on error
 */
static int ctucan_set_secondary_sample_point(struct net_device *ndev)
{
	struct ctucan_priv *priv = netdev_priv(ndev);
	struct can_bittiming *dbt = &priv->can.data_bittiming;
	int ssp_offset = 0;
	bool ssp_ena;

	netdev_dbg(ndev, "ctucan_set_secondary_sample_point");

	if (ctucan_hw_is_enabled(&priv->p)) {
		netdev_alert(ndev,
			     "BUG! Cannot set SSP - CAN is enabled\n");
		return -EPERM;
	}

	// Use for bit-rates above 1 Mbits/s
167
	if (dbt->bitrate > 1000000) {
168 169 170 171 172 173
		ssp_ena = true;

		// Calculate SSP in minimal time quanta
		ssp_offset = (priv->can.clock.freq / 1000) *
			      dbt->sample_point / dbt->bitrate;

174
		if (ssp_offset > 127) {
175 176 177 178 179 180 181 182 183 184 185
			netdev_warn(ndev, "SSP offset saturated to 127\n");
			ssp_offset = 127;
		}
	} else
		ssp_ena = false;

	ctucan_hw_configure_ssp(&priv->p, ssp_ena, true, ssp_offset);

	return 0;
}

Martin Jeřábek's avatar
Martin Jeřábek committed
186 187 188 189 190 191 192 193 194 195
/**
 * ctucan_chip_start - This the drivers start routine
 * @ndev:	Pointer to net_device structure
 *
 * This is the drivers start routine.
 *
 * Return: 0 on success and failure value on error
 */
static int ctucan_chip_start(struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
196
	struct ctucan_priv *priv = netdev_priv(ndev);
197
	union ctu_can_fd_int_stat int_ena, int_msk, int_enamask_mask;
Martin Jeřábek's avatar
Martin Jeřábek committed
198 199
	int err;
	struct can_ctrlmode mode;
200

201
	netdev_dbg(ndev, "ctucan_chip_start");
Martin Jeřábek's avatar
Martin Jeřábek committed
202 203 204 205 206 207 208 209

	err = ctucan_reset(ndev);
	if (err < 0)
		return err;

	priv->txb_prio = 0x01234567;
	priv->txb_head = 0;
	priv->txb_tail = 0;
210
	priv->p.write_reg(&priv->p, CTU_CAN_FD_TX_PRIORITY, priv->txb_prio);
Martin Jeřábek's avatar
Martin Jeřábek committed
211

Martin Jeřábek's avatar
Martin Jeřábek committed
212
	err = ctucan_set_bittiming(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
213 214 215 216 217 218 219
	if (err < 0)
		return err;

	err = ctucan_set_data_bittiming(ndev);
	if (err < 0)
		return err;

220 221 222 223
	err = ctucan_set_secondary_sample_point(ndev);
	if (err < 0)
		return err;

Martin Jeřábek's avatar
Martin Jeřábek committed
224 225 226 227
	/* Enable interrupts */
	int_ena.u32 = 0;
	int_ena.s.rbnei = 1;
	int_ena.s.txbhci = 1;
228

Martin Jeřábek's avatar
Martin Jeřábek committed
229
	int_ena.s.ewli = 1;
230
	int_ena.s.fcsi = 1;
231

232
	int_enamask_mask.u32 = 0xFFFFFFFF;
Martin Jeřábek's avatar
Martin Jeřábek committed
233 234 235

	mode.flags = priv->can.ctrlmode;
	mode.mask = 0xFFFFFFFF;
236
	ctucan_hw_set_mode_reg(&priv->p, &mode);
Martin Jeřábek's avatar
Martin Jeřábek committed
237 238 239

	/* One shot mode supported indirectly via Retransmit limit */
	if (priv->can.ctrlmode & CAN_CTRLMODE_ONE_SHOT)
240
		ctucan_hw_set_ret_limit(&priv->p, true, 0);
Martin Jeřábek's avatar
Martin Jeřábek committed
241 242 243 244 245 246 247

	/* Bus error reporting -> Allow Error interrupt */
	if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) {
		int_ena.s.ali = 1;
		int_ena.s.bei = 1;
	}

248 249
	int_msk.u32 = ~int_ena.u32; /* mask all disabled interrupts */

250
	/* It's after reset, so there is no need to clear anything */
251 252
	ctucan_hw_int_mask_set(&priv->p, int_msk);
	ctucan_hw_int_ena_set(&priv->p, int_ena);
Martin Jeřábek's avatar
Martin Jeřábek committed
253

254 255
	/* Controller enters ERROR_ACTIVE on initial FCSI */
	priv->can.state = CAN_STATE_STOPPED;
Martin Jeřábek's avatar
Martin Jeřábek committed
256 257

	/* Enable the controller */
258
	ctucan_hw_enable(&priv->p, true);
Martin Jeřábek's avatar
Martin Jeřábek committed
259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274

	return 0;
}

/**
 * ctucan_do_set_mode - This sets the mode of the driver
 * @ndev:	Pointer to net_device structure
 * @mode:	Tells the mode of the driver
 *
 * This check the drivers state and calls the
 * the corresponding modes to set.
 *
 * Return: 0 on success and failure value on error
 */
static int ctucan_do_set_mode(struct net_device *ndev, enum can_mode mode)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
275
	int ret;
276

277
	netdev_dbg(ndev, "ctucan_do_set_mode");
Martin Jeřábek's avatar
Martin Jeřábek committed
278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308

	switch (mode) {
	case CAN_MODE_START:
		ret = ctucan_chip_start(ndev);
		if (ret < 0) {
			netdev_err(ndev, "ctucan_chip_start failed!\n");
			return ret;
		}
		netif_wake_queue(ndev);
		break;
	default:
		ret = -EOPNOTSUPP;
		break;
	}

	return ret;
}

/**
 * ctucan_start_xmit - Starts the transmission
 * @skb:	sk_buff pointer that contains data to be Txed
 * @ndev:	Pointer to net_device structure
 *
 * This function is invoked from upper layers to initiate transmission. This
 * function uses the next available free txbuf and populates their fields to
 * start the transmission.
 *
 * Return: 0 on success and failure value on error
 */
static int ctucan_start_xmit(struct sk_buff *skb, struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
309
	struct ctucan_priv *priv = netdev_priv(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
310 311 312 313
	struct net_device_stats *stats = &ndev->stats;
	struct canfd_frame *cf = (struct canfd_frame *)skb->data;
	u32 txb_id;
	bool ok;
314
	unsigned long flags;
Martin Jeřábek's avatar
Martin Jeřábek committed
315 316 317 318 319

	if (can_dropped_invalid_skb(ndev, skb))
		return NETDEV_TX_OK;

	/* Check if the TX buffer is full */
320
	if (unlikely(!CTU_CAN_FD_TXTNF(ctu_can_get_status(&priv->p)))) {
Martin Jeřábek's avatar
Martin Jeřábek committed
321 322 323 324 325 326
		netif_stop_queue(ndev);
		netdev_err(ndev, "BUG!, no TXB free when queue awake!\n");
		return NETDEV_TX_BUSY;
	}

	txb_id = priv->txb_head & priv->txb_mask;
327
	netdev_dbg(ndev, "%s: using TXB#%u", __func__, txb_id);
328
	ok = ctucan_hw_insert_frame(&priv->p, cf, 0, txb_id,
329 330
				     can_is_canfd_skb(skb));

Martin Jeřábek's avatar
Martin Jeřábek committed
331
	if (!ok) {
332
		netdev_err(ndev,
333
		    "BUG! TXNF set but cannot insert frame into TXTB! HW Bug?");
334
		return NETDEV_TX_BUSY;
Martin Jeřábek's avatar
Martin Jeřábek committed
335 336 337
	}
	can_put_echo_skb(skb, ndev, txb_id);

338
	if (!(cf->can_id & CAN_RTR_FLAG))
Martin Jeřábek's avatar
Martin Jeřábek committed
339 340
		stats->tx_bytes += cf->len;

341 342
	spin_lock_irqsave(&priv->tx_lock, flags);

343
	ctucan_hw_txt_set_rdy(&priv->p, txb_id);
344

345 346
	priv->txb_head++;

Martin Jeřábek's avatar
Martin Jeřábek committed
347
	/* Check if all TX buffers are full */
348
	if (!CTU_CAN_FD_TXTNF(ctu_can_get_status(&priv->p)))
Martin Jeřábek's avatar
Martin Jeřábek committed
349 350
		netif_stop_queue(ndev);

351 352
	spin_unlock_irqrestore(&priv->tx_lock, flags);

Martin Jeřábek's avatar
Martin Jeřábek committed
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367
	return NETDEV_TX_OK;
}

/**
 * xcan_rx -  Is called from CAN isr to complete the received
 *		frame  processing
 * @ndev:	Pointer to net_device structure
 *
 * This function is invoked from the CAN isr(poll) to process the Rx frames. It
 * does minimal processing and invokes "netif_receive_skb" to complete further
 * processing.
 * Return: 1 on success and 0 on failure.
 */
static int ctucan_rx(struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
368
	struct ctucan_priv *priv = netdev_priv(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
369 370 371 372 373 374
	struct net_device_stats *stats = &ndev->stats;
	struct canfd_frame *cf;
	struct sk_buff *skb;
	u64 ts;
	union ctu_can_fd_frame_form_w ffw;

375 376 377 378 379 380
	if (test_bit(CTUCAN_FLAG_RX_FFW_BUFFERED, &priv->drv_flags)) {
		ffw = priv->rxfrm_first_word;
		clear_bit(CTUCAN_FLAG_RX_FFW_BUFFERED, &priv->drv_flags);
	} else {
		ffw = ctu_can_fd_read_rx_ffw(&priv->p);
	}
Martin Jeřábek's avatar
Martin Jeřábek committed
381

Martin Jeřábek's avatar
Martin Jeřábek committed
382
	if (ffw.s.fdf == FD_CAN)
383 384
		skb = alloc_canfd_skb(ndev, &cf);
	else
385
		skb = alloc_can_skb(ndev, (struct can_frame **)&cf);
386

Martin Jeřábek's avatar
Martin Jeřábek committed
387
	if (unlikely(!skb)) {
388 389
		priv->rxfrm_first_word = ffw;
		set_bit(CTUCAN_FLAG_RX_FFW_BUFFERED, &priv->drv_flags);
Martin Jeřábek's avatar
Martin Jeřábek committed
390 391 392
		return 0;
	}

393
	ctucan_hw_read_rx_frame_ffw(&priv->p, cf, &ts, ffw);
Martin Jeřábek's avatar
Martin Jeřábek committed
394 395 396 397 398 399 400 401

	stats->rx_bytes += cf->len;
	stats->rx_packets++;
	netif_receive_skb(skb);

	return 1;
}

402 403 404 405 406 407 408 409

static const char *ctucan_state_to_str(enum can_state state)
{
	if (state >= CAN_STATE_MAX)
		return "UNKNOWN";
	return ctucan_state_strings[state];
}

Martin Jeřábek's avatar
Martin Jeřábek committed
410
/**
411
 * ctucan_err_interrupt - error frame Isr
Martin Jeřábek's avatar
Martin Jeřábek committed
412 413 414 415 416 417 418
 * @ndev:	net_device pointer
 * @isr:	interrupt status register value
 *
 * This is the CAN error interrupt and it will
 * check the the type of error and forward the error
 * frame to upper layers.
 */
419 420
static void ctucan_err_interrupt(struct net_device *ndev,
				 union ctu_can_fd_int_stat isr)
Martin Jeřábek's avatar
Martin Jeřábek committed
421
{
422
	struct ctucan_priv *priv = netdev_priv(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
423 424 425
	struct net_device_stats *stats = &ndev->stats;
	struct can_frame *cf;
	struct sk_buff *skb;
426
	enum can_state state;
427
	struct can_berr_counter berr;
428
	union ctu_can_fd_err_capt_alc err_capt_alc;
429
	int dologerr = net_ratelimit();
430

431 432
	ctucan_hw_read_err_ctrs(&priv->p, &berr);
	state = ctucan_hw_read_error_state(&priv->p);
433 434
	err_capt_alc = ctu_can_fd_read_err_capt_alc(&priv->p);

435 436 437 438 439 440
	if (dologerr)
		netdev_info(ndev, "%s: ISR = 0x%08x, rxerr %d, txerr %d,"
			" error type %u, pos %u, ALC id_field %u, bit %u\n",
			__func__, isr.u32, berr.rxerr, berr.txerr,
			err_capt_alc.s.err_type, err_capt_alc.s.err_pos,
			err_capt_alc.s.alc_id_field, err_capt_alc.s.alc_bit);
Martin Jeřábek's avatar
Martin Jeřábek committed
441 442 443

	skb = alloc_can_err_skb(ndev, &cf);

444
	/* EWLI:  error warning limit condition met
445 446 447
	 * FCSI: Fault confinement State changed
	 * ALI:  arbitration lost (just informative)
	 * BEI:  bus error interrupt
448
	 */
449

450 451 452 453 454 455 456 457 458 459
	if (isr.s.fcsi || isr.s.ewli) {

		netdev_info(ndev, "  state changes from %s to %s",
				ctucan_state_to_str(priv->can.state),
				ctucan_state_to_str(state));

		if (priv->can.state == state)
			netdev_warn(ndev, "   current and previous state is the same!"
					" (missed interrupt?)");

460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475
		priv->can.state = state;
		if (state == CAN_STATE_BUS_OFF) {
			priv->can.can_stats.bus_off++;
			can_bus_off(ndev);
			if (skb)
				cf->can_id |= CAN_ERR_BUSOFF;
		} else if (state == CAN_STATE_ERROR_PASSIVE) {
			priv->can.can_stats.error_passive++;
			if (skb) {
				cf->can_id |= CAN_ERR_CRTL;
				cf->data[1] = (berr.rxerr > 127) ?
						CAN_ERR_CRTL_RX_PASSIVE :
						CAN_ERR_CRTL_TX_PASSIVE;
				cf->data[6] = berr.txerr;
				cf->data[7] = berr.rxerr;
			}
476
		} else if (state == CAN_STATE_ERROR_WARNING) {
477 478 479 480 481 482 483 484 485
			priv->can.can_stats.error_warning++;
			if (skb) {
				cf->can_id |= CAN_ERR_CRTL;
				cf->data[1] |= (berr.txerr > berr.rxerr) ?
					CAN_ERR_CRTL_TX_WARNING :
					CAN_ERR_CRTL_RX_WARNING;
				cf->data[6] = berr.txerr;
				cf->data[7] = berr.rxerr;
			}
486 487 488 489
		} else if (state == CAN_STATE_ERROR_ACTIVE) {
			cf->data[1] = CAN_ERR_CRTL_ACTIVE;
			cf->data[6] = berr.txerr;
			cf->data[7] = berr.rxerr;
490
		} else {
491 492
			netdev_warn(ndev, "    unhandled error state (%d:%s)!",
				    state, ctucan_state_to_str(state));
Martin Jeřábek's avatar
Martin Jeřábek committed
493 494 495
		}
	}

496 497
	/* Check for Arbitration Lost interrupt */
	if (isr.s.ali) {
498 499
		if (dologerr)
			netdev_info(ndev, "  arbitration lost");
Martin Jeřábek's avatar
Martin Jeřábek committed
500 501 502 503 504 505 506
		priv->can.can_stats.arbitration_lost++;
		if (skb) {
			cf->can_id |= CAN_ERR_LOSTARB;
			cf->data[0] = CAN_ERR_LOSTARB_UNSPEC;
		}
	}

507 508
	/* Check for Bus Error interrupt */
	if (isr.s.bei) {
509
		netdev_info(ndev, "  bus error");
510 511 512
		priv->can.can_stats.bus_error++;
		stats->tx_errors++; // TODO: really?
		if (skb) {
Martin Jeřábek's avatar
Martin Jeřábek committed
513
			cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
514 515
			cf->data[2] = CAN_ERR_PROT_UNSPEC;
			cf->data[3] = CAN_ERR_PROT_LOC_UNSPEC;
Martin Jeřábek's avatar
Martin Jeřábek committed
516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537
		}
	}

	if (skb) {
		stats->rx_packets++;
		stats->rx_bytes += cf->can_dlc;
		netif_rx(skb);
	}
}

/**
 * ctucan_rx_poll - Poll routine for rx packets (NAPI)
 * @napi:	napi structure pointer
 * @quota:	Max number of rx packets to be processed.
 *
 * This is the poll routine for rx part.
 * It will process the packets maximux quota value.
 *
 * Return: number of packets received
 */
static int ctucan_rx_poll(struct napi_struct *napi, int quota)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
538
	struct net_device *ndev = napi->dev;
Martin Jeřábek's avatar
Martin Jeřábek committed
539 540
	struct ctucan_priv *priv = netdev_priv(ndev);
	int work_done = 0;
541 542
	union ctu_can_fd_status status;
	u32 framecnt;
Martin Jeřábek's avatar
Martin Jeřábek committed
543

544
	framecnt = ctucan_hw_get_rx_frame_count(&priv->p);
545
	netdev_dbg(ndev, "rx_poll: %d frames in RX FIFO", framecnt);
546
	while (framecnt && work_done < quota) {
547 548
		ctucan_rx(ndev);
		work_done++;
549
		framecnt = ctucan_hw_get_rx_frame_count(&priv->p);
550
	}
Martin Jeřábek's avatar
Martin Jeřábek committed
551

552 553 554 555 556 557
	/* Check for RX FIFO Overflow */
	status = ctu_can_get_status(&priv->p);
	if (status.s.dor) {
		struct net_device_stats *stats = &ndev->stats;
		struct can_frame *cf;
		struct sk_buff *skb;
558

559 560 561 562 563 564 565 566 567 568
		netdev_info(ndev, "  rx fifo overflow");
		stats->rx_over_errors++;
		stats->rx_errors++;
		skb = alloc_can_err_skb(ndev, &cf);
		if (skb) {
			cf->can_id |= CAN_ERR_CRTL;
			cf->data[1] |= CAN_ERR_CRTL_RX_OVERFLOW;
			stats->rx_packets++;
			stats->rx_bytes += cf->can_dlc;
			netif_rx(skb);
569 570
		}

571
		/* Clear Data Overrun */
572
		ctucan_hw_clr_overrun_flag(&priv->p);
Martin Jeřábek's avatar
Martin Jeřábek committed
573 574 575 576 577
	}

	if (work_done)
		can_led_event(ndev, CAN_LED_EVENT_RX);

578
	if (!framecnt) {
579
		if (napi_complete_done(napi, work_done)) {
580 581 582 583 584 585
			union ctu_can_fd_int_stat iec;
			/* Clear and enable RBNEI. It is level-triggered, so
			 * there is no race condition.
			 */
			iec.u32 = 0;
			iec.s.rbnei = 1;
586 587
			ctucan_hw_int_clr(&priv->p, iec);
			ctucan_hw_int_mask_clr(&priv->p, iec);
588
		}
Martin Jeřábek's avatar
Martin Jeřábek committed
589 590 591 592 593 594 595
	}

	return work_done;
}

static void ctucan_rotate_txb_prio(struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
596
	struct ctucan_priv *priv = netdev_priv(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
597
	u32 prio = priv->txb_prio;
598
	u32 nbuffersm1 = priv->txb_mask; /* nbuffers - 1 */
Martin Jeřábek's avatar
Martin Jeřábek committed
599

600
	prio = (prio << 4) | ((prio >> (nbuffersm1 * 4)) & 0xF);
601 602
	netdev_dbg(ndev, "%s: from 0x%08x to 0x%08x",
		   __func__, priv->txb_prio, prio);
Martin Jeřábek's avatar
Martin Jeřábek committed
603
	priv->txb_prio = prio;
604
	priv->p.write_reg(&priv->p, CTU_CAN_FD_TX_PRIORITY, prio);
Martin Jeřábek's avatar
Martin Jeřábek committed
605 606 607 608 609 610 611 612
}

/**
 * xcan_tx_interrupt - Tx Done Isr
 * @ndev:	net_device pointer
 */
static void ctucan_tx_interrupt(struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
613
	struct ctucan_priv *priv = netdev_priv(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
614
	struct net_device_stats *stats = &ndev->stats;
615 616 617
	bool first = true;
	union ctu_can_fd_int_stat icr;
	bool some_buffers_processed;
618
	unsigned long flags;
619

620
	netdev_dbg(ndev, "%s", __func__);
Martin Jeřábek's avatar
Martin Jeřábek committed
621

622
	/*  read tx_status
623 624 625 626 627
	 *  if txb[n].finished (bit 2)
	 *	if ok -> echo
	 *	if error / aborted -> ?? (find how to handle oneshot mode)
	 *	txb_tail++
	 */
Martin Jeřábek's avatar
Martin Jeřábek committed
628

629 630 631
	icr.u32 = 0;
	icr.s.txbhci = 1;
	do {
632 633
		spin_lock_irqsave(&priv->tx_lock, flags);

634 635 636
		some_buffers_processed = false;
		while ((int)(priv->txb_head - priv->txb_tail) > 0) {
			u32 txb_idx = priv->txb_tail & priv->txb_mask;
637
			u32 status = ctucan_hw_get_tx_status(&priv->p, txb_idx);
638

639 640 641
			netdev_dbg(ndev, "TXI: TXB#%u: status 0x%x",
				   txb_idx, status);

642 643 644 645 646
			switch (status) {
			case TXT_TOK:
				netdev_dbg(ndev, "TXT_OK");
				can_get_echo_skb(ndev, txb_idx);
				stats->tx_packets++;
647
				break;
648
			case TXT_ERR:
649 650
				/* This indicated that retransmit limit has been
				 * reached. Obviously we should not echo the
651 652 653 654
				 * frame, but also not indicate any kind
				 * of error. If desired, it was already reported
				 * (possible multiple times) on each arbitration
				 * lost.
655
				 */
656 657
				netdev_warn(ndev, "TXB in Error state");
				can_free_echo_skb(ndev, txb_idx);
658
				stats->tx_dropped++;
659
				break;
660
			case TXT_ABT:
661 662 663 664
				/* Same as for TXT_ERR, only with different
				 * cause. We *could* re-queue the frame, but
				 * multiqueue/abort is not supported yet anyway.
				 */
665 666
				netdev_warn(ndev, "TXB in Aborted state");
				can_free_echo_skb(ndev, txb_idx);
667
				stats->tx_dropped++;
668
				break;
669 670 671 672 673
			default:
				/* Bug only if the first buffer is not finished,
				 * otherwise it is pretty much expected
				 */
				if (first) {
674 675
					netdev_err(ndev, "BUG: TXB#%u not in a finished state (0x%x)!",
						   txb_idx, status);
676
					spin_unlock_irqrestore(&priv->tx_lock, flags);
677 678 679 680 681 682 683 684
					/* do not clear nor wake */
					return;
				}
				goto clear;
			}
			priv->txb_tail++;
			first = false;
			some_buffers_processed = true;
685 686 687
			/* Adjust priorities *before* marking the buffer
			 * as empty.
			 */
688
			ctucan_rotate_txb_prio(ndev);
689
			ctucan_hw_txt_set_empty(&priv->p, txb_idx);
Martin Jeřábek's avatar
Martin Jeřábek committed
690
		}
691
clear:
692 693
		spin_unlock_irqrestore(&priv->tx_lock, flags);

694
		/* If no buffers were processed this time, wa cannot
695 696
		 * clear - that would introduce a race condition.
		 */
697 698 699
		if (some_buffers_processed) {
			/* Clear the interrupt again as not to receive it again
			 * for a buffer we already handled (possibly causing
700 701
			 * the bug log)
			 */
702
			ctucan_hw_int_clr(&priv->p, icr);
703
		}
704
	} while (some_buffers_processed);
705

Martin Jeřábek's avatar
Martin Jeřábek committed
706
	can_led_event(ndev, CAN_LED_EVENT_TX);
707 708 709 710 711 712 713 714

	spin_lock_irqsave(&priv->tx_lock, flags);

	/* Check if at least one TX buffer is free */
	if (CTU_CAN_FD_TXTNF(ctu_can_get_status(&priv->p)))
		netif_wake_queue(ndev);

	spin_unlock_irqrestore(&priv->tx_lock, flags);
Martin Jeřábek's avatar
Martin Jeřábek committed
715 716 717 718 719 720 721
}

/**
 * xcan_interrupt - CAN Isr
 * @irq:	irq number
 * @dev_id:	device id poniter
 *
722
 * This is the CTU CAN FD ISR. It checks for the type of interrupt
Martin Jeřábek's avatar
Martin Jeřábek committed
723 724 725 726 727 728 729
 * and invokes the corresponding ISR.
 *
 * Return:
 * IRQ_NONE - If CAN device is in sleep mode, IRQ_HANDLED otherwise
 */
static irqreturn_t ctucan_interrupt(int irq, void *dev_id)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
730
	struct net_device *ndev = (struct net_device *)dev_id;
Martin Jeřábek's avatar
Martin Jeřábek committed
731 732
	struct ctucan_priv *priv = netdev_priv(ndev);
	union ctu_can_fd_int_stat isr, icr;
733 734
	int irq_loops = 0;

735
	netdev_dbg(ndev, "ctucan_interrupt");
Martin Jeřábek's avatar
Martin Jeřábek committed
736

737 738 739
	do {
		/* Get the interrupt status */
		isr = ctu_can_fd_int_sts(&priv->p);
Martin Jeřábek's avatar
Martin Jeřábek committed
740

741
		if (!isr.u32)
742
			return irq_loops ? IRQ_HANDLED : IRQ_NONE;
743

744 745 746 747 748
		/* Receive Buffer Not Empty Interrupt */
		if (isr.s.rbnei) {
			netdev_dbg(ndev, "RXBNEI");
			icr.u32 = 0;
			icr.s.rbnei = 1;
749 750 751 752
			/* Mask RXBNEI the first then clear interrupt,
			 * then schedule NAPI. Even if another IRQ fires,
			 * isr.s.rbnei will always be 0 (masked).
			 */
753 754
			ctucan_hw_int_mask_set(&priv->p, icr);
			ctucan_hw_int_clr(&priv->p, icr);
755 756
			napi_schedule(&priv->napi);
		}
Martin Jeřábek's avatar
Martin Jeřábek committed
757

758 759 760
		/* TX Buffer HW Command Interrupt */
		if (isr.s.txbhci) {
			netdev_dbg(ndev, "TXBHCI");
761
			/* Cleared inside */
762 763 764 765
			ctucan_tx_interrupt(ndev);
		}

		/* Error interrupts */
766
		if (isr.s.ewli || isr.s.fcsi || isr.s.ali) {
767
			union ctu_can_fd_int_stat ierrmask = { .s = {
768
				  .ewli = 1, .fcsi = 1, .ali = 1, .bei = 1 } };
769 770
			icr.u32 = isr.u32 & ierrmask.u32;

771 772
			netdev_dbg(ndev, "some ERR interrupt: clearing 0x%08x",
				   icr.u32);
773
			ctucan_hw_int_clr(&priv->p, icr);
774 775 776 777 778
			ctucan_err_interrupt(ndev, isr);
		}
		/* Ignore RI, TI, LFI, RFI, BSI */
	} while (irq_loops++ < 10000);

779 780
	netdev_err(ndev, "%s: stuck interrupt (isr=0x%08x), stopping\n",
		   __func__, isr.u32);
781

782 783
	if (isr.s.txbhci) {
		int i;
784

785 786
		netdev_err(ndev, "txb_head=0x%08x txb_tail=0x%08x\n",
			priv->txb_head, priv->txb_tail);
787
		for (i = 0; i <= priv->txb_mask; i++) {
788
			u32 status = ctucan_hw_get_tx_status(&priv->p, i);
789

790 791 792 793 794
			netdev_err(ndev, "txb[%d] txb status=0x%08x\n",
				i, status);
		}
	}

795
	{
796
		union ctu_can_fd_int_stat imask;
797

798
		imask.u32 = 0xffffffff;
799 800
		ctucan_hw_int_ena_clr(&priv->p, imask);
		ctucan_hw_int_mask_set(&priv->p, imask);
801
	}
Martin Jeřábek's avatar
Martin Jeřábek committed
802 803 804 805 806 807 808 809 810 811 812 813 814

	return IRQ_HANDLED;
}

/**
 * ctucan_chip_stop - Driver stop routine
 * @ndev:	Pointer to net_device structure
 *
 * This is the drivers stop routine. It will disable the
 * interrupts and disable the controller.
 */
static void ctucan_chip_stop(struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
815
	struct ctucan_priv *priv = netdev_priv(ndev);
816
	union ctu_can_fd_int_stat mask;
817

818
	netdev_dbg(ndev, "ctucan_chip_stop");
Martin Jeřábek's avatar
Martin Jeřábek committed
819

820
	mask.u32 = 0xffffffff;
Martin Jeřábek's avatar
Martin Jeřábek committed
821 822

	/* Disable interrupts and disable can */
823 824
	ctucan_hw_int_mask_set(&priv->p, mask);
	ctucan_hw_enable(&priv->p, false);
Martin Jeřábek's avatar
Martin Jeřábek committed
825 826 827 828 829 830 831 832 833 834 835 836
	priv->can.state = CAN_STATE_STOPPED;
}

/**
 * ctucan_open - Driver open routine
 * @ndev:	Pointer to net_device structure
 *
 * This is the driver open routine.
 * Return: 0 on success and failure value on error
 */
static int ctucan_open(struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
837
	struct ctucan_priv *priv = netdev_priv(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
838
	int ret;
839

840
	netdev_dbg(ndev, "ctucan_open");
Martin Jeřábek's avatar
Martin Jeřábek committed
841 842 843 844

	ret = pm_runtime_get_sync(priv->dev);
	if (ret < 0) {
		netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
845
			   __func__, ret);
Martin Jeřábek's avatar
Martin Jeřábek committed
846 847 848
		return ret;
	}

849
	ret = request_irq(ndev->irq, ctucan_interrupt, priv->irq_flags,
850
			  ndev->name, ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
851 852 853 854 855 856 857 858
	if (ret < 0) {
		netdev_err(ndev, "irq allocation for CAN failed\n");
		goto err;
	}

	/* Common open */
	ret = open_candev(ndev);
	if (ret) {
Martin Jeřábek's avatar
Martin Jeřábek committed
859 860 861
		netdev_warn(ndev, "open_candev failed!\n");
		goto err_irq;
	}
Martin Jeřábek's avatar
Martin Jeřábek committed
862

Martin Jeřábek's avatar
Martin Jeřábek committed
863
	ret = ctucan_chip_start(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
864 865 866 867 868
	if (ret < 0) {
		netdev_err(ndev, "ctucan_chip_start failed!\n");
		goto err_candev;
	}

869
	netdev_info(ndev, "ctu_can_fd device registered");
Martin Jeřábek's avatar
Martin Jeřábek committed
870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893
	can_led_event(ndev, CAN_LED_EVENT_OPEN);
	napi_enable(&priv->napi);
	netif_start_queue(ndev);

	return 0;

err_candev:
	close_candev(ndev);
err_irq:
	free_irq(ndev->irq, ndev);
err:
	pm_runtime_put(priv->dev);

	return ret;
}

/**
 * ctucan_close - Driver close routine
 * @ndev:	Pointer to net_device structure
 *
 * Return: 0 always
 */
static int ctucan_close(struct net_device *ndev)
{
Martin Jeřábek's avatar
Martin Jeřábek committed
894
	struct ctucan_priv *priv = netdev_priv(ndev);
895

896
	netdev_dbg(ndev, "ctucan_close");
Martin Jeřábek's avatar
Martin Jeřábek committed
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918

	netif_stop_queue(ndev);
	napi_disable(&priv->napi);
	ctucan_chip_stop(ndev);
	free_irq(ndev->irq, ndev);
	close_candev(ndev);

	can_led_event(ndev, CAN_LED_EVENT_STOP);
	pm_runtime_put(priv->dev);

	return 0;
}

/**
 * ctucan_get_berr_counter - error counter routine
 * @ndev:	Pointer to net_device structure
 * @bec:	Pointer to can_berr_counter structure
 *
 * This is the driver error counter routine.
 * Return: 0 on success and failure value on error
 */
static int ctucan_get_berr_counter(const struct net_device *ndev,
919
				   struct can_berr_counter *bec)
Martin Jeřábek's avatar
Martin Jeřábek committed
920
{
Martin Jeřábek's avatar
Martin Jeřábek committed
921
	struct ctucan_priv *priv = netdev_priv(ndev);
Martin Jeřábek's avatar
Martin Jeřábek committed
922
	int ret;
923

924
	netdev_dbg(ndev, "ctucan_get_berr_counter");
Martin Jeřábek's avatar
Martin Jeřábek committed
925 926 927 928

	ret = pm_runtime_get_sync(priv->dev);
	if (ret < 0) {
		netdev_err(ndev, "%s: pm_runtime_get failed(%d)\n",
929
			   __func__, ret);
Martin Jeřábek's avatar
Martin Jeřábek committed
930 931 932
		return ret;
	}

933
	ctucan_hw_read_err_ctrs(&priv->p, bec);
Martin Jeřábek's avatar
Martin Jeřábek committed
934 935 936 937 938 939 940 941 942 943 944 945 946

	pm_runtime_put(priv->dev);

	return 0;
}

static const struct net_device_ops ctucan_netdev_ops = {
	.ndo_open	= ctucan_open,
	.ndo_stop	= ctucan_close,
	.ndo_start_xmit	= ctucan_start_xmit,
	.ndo_change_mtu	= can_change_mtu,
};

947
int ctucan_suspend(struct device *dev)
Martin Jeřábek's avatar
Martin Jeřábek committed
948
{
Martin Jeřábek's avatar
Martin Jeřábek committed
949
	struct net_device *ndev = dev_get_drvdata(dev);
Martin Jeřábek's avatar
Martin Jeřábek committed
950
	struct ctucan_priv *priv = netdev_priv(ndev);
951