static int cc770_get_berr_counter(const struct net_device *dev, struct can_berr_counter *bec) { struct cc770_priv *priv = netdev_priv(dev); bec->txerr = cc770_read_reg(priv, tx_error_counter); bec->rxerr = cc770_read_reg(priv, rx_error_counter); return 0; }
static int cc770_probe_chip(struct net_device *dev) { struct cc770_priv *priv = netdev_priv(dev); /* Enable configuration, put chip in bus-off, disable ints */ cc770_write_reg(priv, control, CTRL_CCE | CTRL_EAF | CTRL_INI); /* Configure cpu interface / CLKOUT disable */ cc770_write_reg(priv, cpu_interface, priv->cpu_interface); /* * Check if hardware reset is still inactive or maybe there * is no chip in this address space */ if (cc770_read_reg(priv, cpu_interface) & CPUIF_RST) { netdev_info(dev, "probing @0x%p failed (reset)\n", priv->reg_base); return -ENODEV; } /* Write and read back test pattern (some arbitrary values) */ cc770_write_reg(priv, msgobj[1].data[1], 0x25); cc770_write_reg(priv, msgobj[2].data[3], 0x52); cc770_write_reg(priv, msgobj[10].data[6], 0xc3); if ((cc770_read_reg(priv, msgobj[1].data[1]) != 0x25) || (cc770_read_reg(priv, msgobj[2].data[3]) != 0x52) || (cc770_read_reg(priv, msgobj[10].data[6]) != 0xc3)) { netdev_info(dev, "probing @0x%p failed (pattern)\n", priv->reg_base); return -ENODEV; } /* Check if this chip is a CC770 supporting additional functions */ if (cc770_read_reg(priv, control) & CTRL_EAF) priv->control_normal_mode |= CTRL_EAF; return 0; }
static int cc770_probe_chip(struct net_device *dev) { struct cc770_priv *priv = netdev_priv(dev); /* */ cc770_write_reg(priv, control, CTRL_CCE | CTRL_EAF | CTRL_INI); /* */ cc770_write_reg(priv, cpu_interface, priv->cpu_interface); /* */ if (cc770_read_reg(priv, cpu_interface) & CPUIF_RST) { netdev_info(dev, "probing @0x%p failed (reset)\n", priv->reg_base); return -ENODEV; } /* */ cc770_write_reg(priv, msgobj[1].data[1], 0x25); cc770_write_reg(priv, msgobj[2].data[3], 0x52); cc770_write_reg(priv, msgobj[10].data[6], 0xc3); if ((cc770_read_reg(priv, msgobj[1].data[1]) != 0x25) || (cc770_read_reg(priv, msgobj[2].data[3]) != 0x52) || (cc770_read_reg(priv, msgobj[10].data[6]) != 0xc3)) { netdev_info(dev, "probing @0x%p failed (pattern)\n", priv->reg_base); return -ENODEV; } /* */ if (cc770_read_reg(priv, control) & CTRL_EAF) priv->control_normal_mode |= CTRL_EAF; return 0; }
static void chipset_init(struct cc770_priv *priv) { int mo, id, data; /* Enable configuration and put chip in bus-off, disable interrupts */ cc770_write_reg(priv, control, (CTRL_CCE | CTRL_INI)); /* Set CLKOUT divider and slew rates */ cc770_write_reg(priv, clkout, priv->clkout); /* Configure CPU interface / CLKOUT enable */ cc770_write_reg(priv, cpu_interface, priv->cpu_interface); /* Set bus configuration */ cc770_write_reg(priv, bus_config, priv->bus_config); /* Clear interrupts */ cc770_read_reg(priv, interrupt); /* Clear status register */ cc770_write_reg(priv, status, 0); /* Clear and invalidate message objects */ for (mo = MSGOBJ_FIRST; mo <= MSGOBJ_LAST; mo++) { cc770_write_reg(priv, msgobj[mo].ctrl0, INTPND_UNC | RXIE_RES | TXIE_RES | MSGVAL_RES); cc770_write_reg(priv, msgobj[mo].ctrl0, INTPND_RES | RXIE_RES | TXIE_RES | MSGVAL_RES); cc770_write_reg(priv, msgobj[mo].ctrl1, NEWDAT_RES | MSGLST_RES | TXRQST_RES | RMTPND_RES); for (data = 0; data < 8; data++) cc770_write_reg(priv, msgobj[mo].data[data], 0); for (id = 0; id < 4; id++) cc770_write_reg(priv, msgobj[mo].id[id], 0); cc770_write_reg(priv, msgobj[mo].config, 0); } /* Set all global ID masks to "don't care" */ cc770_write_reg(priv, global_mask_std[0], 0); cc770_write_reg(priv, global_mask_std[1], 0); cc770_write_reg(priv, global_mask_ext[0], 0); cc770_write_reg(priv, global_mask_ext[1], 0); cc770_write_reg(priv, global_mask_ext[2], 0); cc770_write_reg(priv, global_mask_ext[3], 0); }
static void chipset_init(struct cc770_priv *priv) { int mo, id, data; /* */ cc770_write_reg(priv, control, (CTRL_CCE | CTRL_INI)); /* */ cc770_write_reg(priv, clkout, priv->clkout); /* */ cc770_write_reg(priv, cpu_interface, priv->cpu_interface); /* */ cc770_write_reg(priv, bus_config, priv->bus_config); /* */ cc770_read_reg(priv, interrupt); /* */ cc770_write_reg(priv, status, 0); /* */ for (mo = MSGOBJ_FIRST; mo <= MSGOBJ_LAST; mo++) { cc770_write_reg(priv, msgobj[mo].ctrl0, INTPND_UNC | RXIE_RES | TXIE_RES | MSGVAL_RES); cc770_write_reg(priv, msgobj[mo].ctrl0, INTPND_RES | RXIE_RES | TXIE_RES | MSGVAL_RES); cc770_write_reg(priv, msgobj[mo].ctrl1, NEWDAT_RES | MSGLST_RES | TXRQST_RES | RMTPND_RES); for (data = 0; data < 8; data++) cc770_write_reg(priv, msgobj[mo].data[data], 0); for (id = 0; id < 4; id++) cc770_write_reg(priv, msgobj[mo].id[id], 0); cc770_write_reg(priv, msgobj[mo].config, 0); } /* */ cc770_write_reg(priv, global_mask_std[0], 0); cc770_write_reg(priv, global_mask_std[1], 0); cc770_write_reg(priv, global_mask_ext[0], 0); cc770_write_reg(priv, global_mask_ext[1], 0); cc770_write_reg(priv, global_mask_ext[2], 0); cc770_write_reg(priv, global_mask_ext[3], 0); }
static void set_reset_mode(struct net_device *dev) { struct cc770_priv *priv = netdev_priv(dev); /* Enable configuration and puts chip in bus-off, disable interrupts */ cc770_write_reg(priv, control, CTRL_CCE | CTRL_INI); priv->can.state = CAN_STATE_STOPPED; /* Clear interrupts */ cc770_read_reg(priv, interrupt); /* Clear status register */ cc770_write_reg(priv, status, 0); /* Disable all used message objects */ disable_all_objs(priv); }
static void set_reset_mode(struct net_device *dev) { struct cc770_priv *priv = netdev_priv(dev); /* */ cc770_write_reg(priv, control, CTRL_CCE | CTRL_INI); priv->can.state = CAN_STATE_STOPPED; /* */ cc770_read_reg(priv, interrupt); /* */ cc770_write_reg(priv, status, 0); /* */ disable_all_objs(priv); }
static void set_normal_mode(struct net_device *dev) { struct cc770_priv *priv = netdev_priv(dev); /* Clear interrupts */ cc770_read_reg(priv, interrupt); /* Clear status register and pre-set last error code */ cc770_write_reg(priv, status, STAT_LEC_MASK); /* Enable all used message objects*/ enable_all_objs(dev); /* * Clear bus-off, interrupts only for errors, * not for status change */ cc770_write_reg(priv, control, priv->control_normal_mode); priv->can.state = CAN_STATE_ERROR_ACTIVE; }
static void set_normal_mode(struct net_device *dev) { struct cc770_priv *priv = netdev_priv(dev); /* */ cc770_read_reg(priv, interrupt); /* */ cc770_write_reg(priv, status, STAT_LEC_MASK); /* */ enable_all_objs(dev); /* */ cc770_write_reg(priv, control, priv->control_normal_mode); priv->can.state = CAN_STATE_ERROR_ACTIVE; }
static netdev_tx_t cc770_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct cc770_priv *priv = netdev_priv(dev); struct net_device_stats *stats = &dev->stats; struct can_frame *cf = (struct can_frame *)skb->data; unsigned int mo = obj2msgobj(CC770_OBJ_TX); u8 dlc, rtr; u32 id; int i; if (can_dropped_invalid_skb(dev, skb)) return NETDEV_TX_OK; if ((cc770_read_reg(priv, msgobj[mo].ctrl1) & TXRQST_UNC) == TXRQST_SET) { netdev_err(dev, "TX register is still occupied!\n"); return NETDEV_TX_BUSY; } netif_stop_queue(dev); dlc = cf->can_dlc; id = cf->can_id; if (cf->can_id & CAN_RTR_FLAG) rtr = 0; else rtr = MSGCFG_DIR; cc770_write_reg(priv, msgobj[mo].ctrl1, RMTPND_RES | TXRQST_RES | CPUUPD_SET | NEWDAT_RES); cc770_write_reg(priv, msgobj[mo].ctrl0, MSGVAL_SET | TXIE_SET | RXIE_RES | INTPND_RES); if (id & CAN_EFF_FLAG) { id &= CAN_EFF_MASK; cc770_write_reg(priv, msgobj[mo].config, (dlc << 4) | rtr | MSGCFG_XTD); cc770_write_reg(priv, msgobj[mo].id[3], id << 3); cc770_write_reg(priv, msgobj[mo].id[2], id >> 5); cc770_write_reg(priv, msgobj[mo].id[1], id >> 13); cc770_write_reg(priv, msgobj[mo].id[0], id >> 21); } else {