Lines Matching +full:sun8i +full:- +full:r40 +full:- +full:can

2  * sun4i_can.c - CAN bus controller driver for Allwinner SUN4I&SUN7I based SoCs
11 * Copyright (C) 2002-2007 Volkswagen Group Electronic Research
51 #include <linux/can.h>
52 #include <linux/can/dev.h>
53 #include <linux/can/error.h>
68 #define SUN4I_REG_MSEL_ADDR 0x0000 /* CAN Mode Select */
69 #define SUN4I_REG_CMD_ADDR 0x0004 /* CAN Command */
70 #define SUN4I_REG_STA_ADDR 0x0008 /* CAN Status */
71 #define SUN4I_REG_INT_ADDR 0x000c /* CAN Interrupt Flag */
72 #define SUN4I_REG_INTEN_ADDR 0x0010 /* CAN Interrupt Enable */
73 #define SUN4I_REG_BTIME_ADDR 0x0014 /* CAN Bus Timing 0 */
74 #define SUN4I_REG_TEWL_ADDR 0x0018 /* CAN Tx Error Warning Limit */
75 #define SUN4I_REG_ERRC_ADDR 0x001c /* CAN Error Counter */
76 #define SUN4I_REG_RMCNT_ADDR 0x0020 /* CAN Receive Message Counter */
77 #define SUN4I_REG_RBUFSA_ADDR 0x0024 /* CAN Receive Buffer Start Address */
78 #define SUN4I_REG_BUF0_ADDR 0x0040 /* CAN Tx/Rx Buffer 0 */
79 #define SUN4I_REG_BUF1_ADDR 0x0044 /* CAN Tx/Rx Buffer 1 */
80 #define SUN4I_REG_BUF2_ADDR 0x0048 /* CAN Tx/Rx Buffer 2 */
81 #define SUN4I_REG_BUF3_ADDR 0x004c /* CAN Tx/Rx Buffer 3 */
82 #define SUN4I_REG_BUF4_ADDR 0x0050 /* CAN Tx/Rx Buffer 4 */
83 #define SUN4I_REG_BUF5_ADDR 0x0054 /* CAN Tx/Rx Buffer 5 */
84 #define SUN4I_REG_BUF6_ADDR 0x0058 /* CAN Tx/Rx Buffer 6 */
85 #define SUN4I_REG_BUF7_ADDR 0x005c /* CAN Tx/Rx Buffer 7 */
86 #define SUN4I_REG_BUF8_ADDR 0x0060 /* CAN Tx/Rx Buffer 8 */
87 #define SUN4I_REG_BUF9_ADDR 0x0064 /* CAN Tx/Rx Buffer 9 */
88 #define SUN4I_REG_BUF10_ADDR 0x0068 /* CAN Tx/Rx Buffer 10 */
89 #define SUN4I_REG_BUF11_ADDR 0x006c /* CAN Tx/Rx Buffer 11 */
90 #define SUN4I_REG_BUF12_ADDR 0x0070 /* CAN Tx/Rx Buffer 12 */
91 #define SUN4I_REG_ACPC_ADDR 0x0040 /* CAN Acceptance Code 0 */
92 #define SUN4I_REG_ACPM_ADDR 0x0044 /* CAN Acceptance Mask 0 */
93 #define SUN4I_REG_ACPC_ADDR_D1 0x0028 /* CAN Acceptance Code 0 on the D1 */
94 #define SUN4I_REG_ACPM_ADDR_D1 0x002C /* CAN Acceptance Mask 0 on the D1 */
95 #define SUN4I_REG_RBUF_RBACK_START_ADDR 0x0180 /* CAN transmit buffer start */
96 #define SUN4I_REG_RBUF_RBACK_END_ADDR 0x01b0 /* CAN transmit buffer end */
206 * struct sun4ican_quirks - Differences between SoC variants.
217 struct can_priv can; member
241 spin_lock_irqsave(&priv->cmdreg_lock, flags); in sun4i_can_write_cmdreg()
242 writel(val, priv->base + SUN4I_REG_CMD_ADDR); in sun4i_can_write_cmdreg()
243 spin_unlock_irqrestore(&priv->cmdreg_lock, flags); in sun4i_can_write_cmdreg()
253 mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR); in set_normal_mode()
255 writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR); in set_normal_mode()
256 } while (retry-- && (mod_reg_val & SUN4I_MSEL_RESET_MODE)); in set_normal_mode()
258 if (readl(priv->base + SUN4I_REG_MSEL_ADDR) & SUN4I_MSEL_RESET_MODE) { in set_normal_mode()
261 return -ETIMEDOUT; in set_normal_mode()
274 mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR); in set_reset_mode()
276 writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR); in set_reset_mode()
277 } while (retry-- && !(mod_reg_val & SUN4I_MSEL_RESET_MODE)); in set_reset_mode()
279 if (!(readl(priv->base + SUN4I_REG_MSEL_ADDR) & in set_reset_mode()
282 return -ETIMEDOUT; in set_reset_mode()
292 struct can_bittiming *bt = &priv->can.bittiming; in sun4ican_set_bittiming()
295 cfg = ((bt->brp - 1) & 0x3FF) | in sun4ican_set_bittiming()
296 (((bt->sjw - 1) & 0x3) << 14) | in sun4ican_set_bittiming()
297 (((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) << 16) | in sun4ican_set_bittiming()
298 (((bt->phase_seg2 - 1) & 0x7) << 20); in sun4ican_set_bittiming()
299 if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) in sun4ican_set_bittiming()
303 writel(cfg, priv->base + SUN4I_REG_BTIME_ADDR); in sun4ican_set_bittiming()
315 err = clk_prepare_enable(priv->clk); in sun4ican_get_berr_counter()
321 errors = readl(priv->base + SUN4I_REG_ERRC_ADDR); in sun4ican_get_berr_counter()
323 bec->txerr = errors & 0xFF; in sun4ican_get_berr_counter()
324 bec->rxerr = (errors >> 16) & 0xFF; in sun4ican_get_berr_counter()
326 clk_disable_unprepare(priv->clk); in sun4ican_get_berr_counter()
344 /* set filters - we accept all */ in sun4i_can_start()
345 writel(0x00000000, priv->base + SUN4I_REG_ACPC_ADDR + priv->acp_offset); in sun4i_can_start()
346 writel(0xFFFFFFFF, priv->base + SUN4I_REG_ACPM_ADDR + priv->acp_offset); in sun4i_can_start()
349 writel(0, priv->base + SUN4I_REG_ERRC_ADDR); in sun4i_can_start()
352 if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) in sun4i_can_start()
353 writel(0xFF, priv->base + SUN4I_REG_INTEN_ADDR); in sun4i_can_start()
356 priv->base + SUN4I_REG_INTEN_ADDR); in sun4i_can_start()
359 mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR); in sun4i_can_start()
360 if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) in sun4i_can_start()
362 else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) in sun4i_can_start()
364 writel(mod_reg_val, priv->base + SUN4I_REG_MSEL_ADDR); in sun4i_can_start()
377 priv->can.state = CAN_STATE_ERROR_ACTIVE; in sun4i_can_start()
387 priv->can.state = CAN_STATE_STOPPED; in sun4i_can_stop()
396 writel(0, priv->base + SUN4I_REG_INTEN_ADDR); in sun4i_can_stop()
409 netdev_err(dev, "starting CAN controller failed!\n"); in sun4ican_set_mode()
417 return -EOPNOTSUPP; in sun4ican_set_mode()
422 /* transmit a CAN message
425 * [ can_id ] [flags] [len] [can data (up to 8 bytes]
430 struct can_frame *cf = (struct can_frame *)skb->data; in sun4ican_start_xmit()
441 id = cf->can_id; in sun4ican_start_xmit()
442 dlc = cf->len; in sun4ican_start_xmit()
451 writel((id >> 21) & 0xFF, priv->base + SUN4I_REG_BUF1_ADDR); in sun4ican_start_xmit()
452 writel((id >> 13) & 0xFF, priv->base + SUN4I_REG_BUF2_ADDR); in sun4ican_start_xmit()
453 writel((id >> 5) & 0xFF, priv->base + SUN4I_REG_BUF3_ADDR); in sun4ican_start_xmit()
454 writel((id << 3) & 0xF8, priv->base + SUN4I_REG_BUF4_ADDR); in sun4ican_start_xmit()
457 writel((id >> 3) & 0xFF, priv->base + SUN4I_REG_BUF1_ADDR); in sun4ican_start_xmit()
458 writel((id << 5) & 0xE0, priv->base + SUN4I_REG_BUF2_ADDR); in sun4ican_start_xmit()
462 writel(cf->data[i], priv->base + (dreg + i * 4)); in sun4ican_start_xmit()
464 writel(msg_flag_n, priv->base + SUN4I_REG_BUF0_ADDR); in sun4ican_start_xmit()
468 if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) in sun4ican_start_xmit()
479 struct net_device_stats *stats = &dev->stats; in sun4i_can_rx()
487 /* create zero'ed CAN frame buffer */ in sun4i_can_rx()
492 fi = readl(priv->base + SUN4I_REG_BUF0_ADDR); in sun4i_can_rx()
493 cf->len = can_cc_dlc2len(fi & 0x0F); in sun4i_can_rx()
496 id = (readl(priv->base + SUN4I_REG_BUF1_ADDR) << 21) | in sun4i_can_rx()
497 (readl(priv->base + SUN4I_REG_BUF2_ADDR) << 13) | in sun4i_can_rx()
498 (readl(priv->base + SUN4I_REG_BUF3_ADDR) << 5) | in sun4i_can_rx()
499 ((readl(priv->base + SUN4I_REG_BUF4_ADDR) >> 3) & 0x1f); in sun4i_can_rx()
503 id = (readl(priv->base + SUN4I_REG_BUF1_ADDR) << 3) | in sun4i_can_rx()
504 ((readl(priv->base + SUN4I_REG_BUF2_ADDR) >> 5) & 0x7); in sun4i_can_rx()
511 for (i = 0; i < cf->len; i++) in sun4i_can_rx()
512 cf->data[i] = readl(priv->base + dreg + i * 4); in sun4i_can_rx()
514 stats->rx_bytes += cf->len; in sun4i_can_rx()
516 stats->rx_packets++; in sun4i_can_rx()
518 cf->can_id = id; in sun4i_can_rx()
528 struct net_device_stats *stats = &dev->stats; in sun4i_can_err()
531 enum can_state state = priv->can.state; in sun4i_can_err()
539 errc = readl(priv->base + SUN4I_REG_ERRC_ADDR); in sun4i_can_err()
547 cf->can_id |= CAN_ERR_CRTL; in sun4i_can_err()
548 cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW; in sun4i_can_err()
550 stats->rx_over_errors++; in sun4i_can_err()
551 stats->rx_errors++; in sun4i_can_err()
553 /* reset the CAN IP by entering reset mode in sun4i_can_err()
574 cf->can_id |= CAN_ERR_CNT; in sun4i_can_err()
575 cf->data[6] = txerr; in sun4i_can_err()
576 cf->data[7] = rxerr; in sun4i_can_err()
581 priv->can.can_stats.bus_error++; in sun4i_can_err()
582 ecc = readl(priv->base + SUN4I_REG_STA_ADDR); in sun4i_can_err()
585 cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR; in sun4i_can_err()
589 cf->data[2] |= CAN_ERR_PROT_BIT; in sun4i_can_err()
592 cf->data[2] |= CAN_ERR_PROT_FORM; in sun4i_can_err()
595 cf->data[2] |= CAN_ERR_PROT_STUFF; in sun4i_can_err()
598 cf->data[3] = (ecc & SUN4I_STA_ERR_SEG_CODE) in sun4i_can_err()
607 cf->data[2] |= CAN_ERR_PROT_TX; in sun4i_can_err()
608 stats->tx_errors++; in sun4i_can_err()
610 stats->rx_errors++; in sun4i_can_err()
624 alc = readl(priv->base + SUN4I_REG_STA_ADDR); in sun4i_can_err()
625 priv->can.can_stats.arbitration_lost++; in sun4i_can_err()
627 cf->can_id |= CAN_ERR_LOSTARB; in sun4i_can_err()
628 cf->data[0] = (alc >> 8) & 0x1f; in sun4i_can_err()
632 if (state != priv->can.state) { in sun4i_can_err()
647 return -ENOMEM; in sun4i_can_err()
656 struct net_device_stats *stats = &dev->stats; in sun4i_can_interrupt()
660 while ((isrc = readl(priv->base + SUN4I_REG_INT_ADDR)) && in sun4i_can_interrupt()
663 status = readl(priv->base + SUN4I_REG_STA_ADDR); in sun4i_can_interrupt()
670 stats->tx_bytes += can_get_echo_skb(dev, 0, NULL); in sun4i_can_interrupt()
671 stats->tx_packets++; in sun4i_can_interrupt()
676 /* receive interrupt - don't read if overrun occurred */ in sun4i_can_interrupt()
680 status = readl(priv->base + SUN4I_REG_STA_ADDR); in sun4i_can_interrupt()
688 netdev_err(dev, "can't allocate buffer - clearing pending interrupts\n"); in sun4i_can_interrupt()
691 writel(isrc, priv->base + SUN4I_REG_INT_ADDR); in sun4i_can_interrupt()
692 readl(priv->base + SUN4I_REG_INT_ADDR); in sun4i_can_interrupt()
711 err = request_irq(dev->irq, sun4i_can_interrupt, 0, dev->name, dev); in sun4ican_open()
718 err = reset_control_deassert(priv->reset); in sun4ican_open()
720 netdev_err(dev, "could not deassert CAN reset\n"); in sun4ican_open()
724 /* turn on clocking for CAN peripheral block */ in sun4ican_open()
725 err = clk_prepare_enable(priv->clk); in sun4ican_open()
727 netdev_err(dev, "could not enable CAN peripheral clock\n"); in sun4ican_open()
733 netdev_err(dev, "could not start CAN peripheral\n"); in sun4ican_open()
742 clk_disable_unprepare(priv->clk); in sun4ican_open()
744 reset_control_assert(priv->reset); in sun4ican_open()
746 free_irq(dev->irq, dev); in sun4ican_open()
758 clk_disable_unprepare(priv->clk); in sun4ican_close()
759 reset_control_assert(priv->reset); in sun4ican_close()
761 free_irq(dev->irq, dev); in sun4ican_close()
789 .acp_offset = (SUN4I_REG_ACPC_ADDR_D1 - SUN4I_REG_ACPC_ADDR),
794 .compatible = "allwinner,sun4i-a10-can",
797 .compatible = "allwinner,sun7i-a20-can",
800 .compatible = "allwinner,sun8i-r40-can",
803 .compatible = "allwinner,sun20i-d1-can",
822 struct device_node *np = pdev->dev.of_node; in sun4ican_probe()
831 quirks = of_device_get_match_data(&pdev->dev); in sun4ican_probe()
833 dev_err(&pdev->dev, "failed to determine the quirks to use\n"); in sun4ican_probe()
834 err = -ENODEV; in sun4ican_probe()
838 if (quirks->has_reset) { in sun4ican_probe()
839 reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); in sun4ican_probe()
841 dev_err(&pdev->dev, "unable to request reset\n"); in sun4ican_probe()
849 dev_err(&pdev->dev, "unable to request clock\n"); in sun4ican_probe()
850 err = -ENODEV; in sun4ican_probe()
856 err = -ENODEV; in sun4ican_probe()
868 dev_err(&pdev->dev, in sun4ican_probe()
869 "could not allocate memory for CAN device\n"); in sun4ican_probe()
870 err = -ENOMEM; in sun4ican_probe()
874 dev->netdev_ops = &sun4ican_netdev_ops; in sun4ican_probe()
875 dev->ethtool_ops = &sun4ican_ethtool_ops; in sun4ican_probe()
876 dev->irq = irq; in sun4ican_probe()
877 dev->flags |= IFF_ECHO; in sun4ican_probe()
880 priv->can.clock.freq = clk_get_rate(clk); in sun4ican_probe()
881 priv->can.bittiming_const = &sun4ican_bittiming_const; in sun4ican_probe()
882 priv->can.do_set_mode = sun4ican_set_mode; in sun4ican_probe()
883 priv->can.do_get_berr_counter = sun4ican_get_berr_counter; in sun4ican_probe()
884 priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING | in sun4ican_probe()
888 priv->base = addr; in sun4ican_probe()
889 priv->clk = clk; in sun4ican_probe()
890 priv->reset = reset; in sun4ican_probe()
891 priv->acp_offset = quirks->acp_offset; in sun4ican_probe()
892 spin_lock_init(&priv->cmdreg_lock); in sun4ican_probe()
895 SET_NETDEV_DEV(dev, &pdev->dev); in sun4ican_probe()
899 dev_err(&pdev->dev, "registering %s failed (err=%d)\n", in sun4ican_probe()
904 dev_info(&pdev->dev, "device registered (base=%p, irq=%d)\n", in sun4ican_probe()
905 priv->base, dev->irq); in sun4ican_probe()
927 MODULE_AUTHOR("Gerhard Bertelsmann <info@gerhard-bertelsmann.de>");
929 MODULE_DESCRIPTION("CAN driver for Allwinner SoCs (A10/A20/D1)");