int softing_chip_poweron(struct softing *card) { int ret; /* sync */ ret = _softing_fct_cmd(card, 99, 0x55, "sync-a"); if (ret < 0) goto failed; ret = _softing_fct_cmd(card, 99, 0xaa, "sync-b"); if (ret < 0) goto failed; ret = softing_reset_chip(card); if (ret < 0) goto failed; /* get_serial */ ret = softing_fct_cmd(card, 43, "get_serial_number"); if (ret < 0) goto failed; card->id.serial = ioread32(&card->dpram[DPRAM_FCT_PARAM]); /* get_version */ ret = softing_fct_cmd(card, 12, "get_version"); if (ret < 0) goto failed; card->id.fw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 2]); card->id.hw_version = ioread16(&card->dpram[DPRAM_FCT_PARAM + 4]); card->id.license = ioread16(&card->dpram[DPRAM_FCT_PARAM + 6]); card->id.chip[0] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 8]); card->id.chip[1] = ioread16(&card->dpram[DPRAM_FCT_PARAM + 10]); return 0; failed: return ret; }
int softing_startstop(struct net_device *dev, int up) { int ret; struct softing *card; struct softing_priv *priv; struct net_device *netdev; int bus_bitmask_start; int j, error_reporting; struct can_frame msg; const struct can_bittiming *bt; priv = netdev_priv(dev); card = priv->card; if (!card->fw.up) return -EIO; ret = mutex_lock_interruptible(&card->fw.lock); if (ret) return ret; bus_bitmask_start = 0; if (dev && up) /* prepare to start this bus as well */ bus_bitmask_start |= (1 << priv->index); /* bring netdevs down */ for (j = 0; j < ARRAY_SIZE(card->net); ++j) { netdev = card->net[j]; if (!netdev) continue; priv = netdev_priv(netdev); if (dev != netdev) netif_stop_queue(netdev); if (netif_running(netdev)) { if (dev != netdev) bus_bitmask_start |= (1 << j); priv->tx.pending = 0; priv->tx.echo_put = 0; priv->tx.echo_get = 0; /* * this bus' may just have called open_candev() * which is rather stupid to call close_candev() * already * but we may come here from busoff recovery too * in which case the echo_skb _needs_ flushing too. * just be sure to call open_candev() again */ close_candev(netdev); } priv->can.state = CAN_STATE_STOPPED; } card->tx.pending = 0; softing_enable_irq(card, 0); ret = softing_reset_chip(card); if (ret) goto failed; if (!bus_bitmask_start) /* no busses to be brought up */ goto card_done; if ((bus_bitmask_start & 1) && (bus_bitmask_start & 2) && (softing_error_reporting(card->net[0]) != softing_error_reporting(card->net[1]))) { dev_alert(&card->pdev->dev, "err_reporting flag differs for busses\n"); goto invalid; } error_reporting = 0; if (bus_bitmask_start & 1) { netdev = card->net[0]; priv = netdev_priv(netdev); error_reporting += softing_error_reporting(netdev); /* init chip 1 */ bt = &priv->can.bittiming; iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]); iowrite16(bt->phase_seg1 + bt->prop_seg, &card->dpram[DPRAM_FCT_PARAM + 6]); iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]); iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0, &card->dpram[DPRAM_FCT_PARAM + 10]); ret = softing_fct_cmd(card, 1, "initialize_chip[0]"); if (ret < 0) goto failed; /* set mode */ iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]); ret = softing_fct_cmd(card, 3, "set_mode[0]"); if (ret < 0) goto failed; /* set filter */ /* 11bit id & mask */ iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]); /* 29bit id.lo & mask.lo & id.hi & mask.hi */ iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]); iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]); iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]); iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]); ret = softing_fct_cmd(card, 7, "set_filter[0]"); if (ret < 0) goto failed; /* set output control */ iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]); ret = softing_fct_cmd(card, 5, "set_output[0]"); if (ret < 0) goto failed; } if (bus_bitmask_start & 2) { netdev = card->net[1]; priv = netdev_priv(netdev); error_reporting += softing_error_reporting(netdev); /* init chip2 */ bt = &priv->can.bittiming; iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]); iowrite16(bt->phase_seg1 + bt->prop_seg, &card->dpram[DPRAM_FCT_PARAM + 6]); iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]); iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0, &card->dpram[DPRAM_FCT_PARAM + 10]); ret = softing_fct_cmd(card, 2, "initialize_chip[1]"); if (ret < 0) goto failed; /* set mode2 */ iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]); ret = softing_fct_cmd(card, 4, "set_mode[1]"); if (ret < 0) goto failed; /* set filter2 */ /* 11bit id & mask */ iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]); /* 29bit id.lo & mask.lo & id.hi & mask.hi */ iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]); iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]); iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]); iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]); ret = softing_fct_cmd(card, 8, "set_filter[1]"); if (ret < 0) goto failed; /* set output control2 */ iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]); ret = softing_fct_cmd(card, 6, "set_output[1]"); if (ret < 0) goto failed; } /* enable_error_frame */ /* * Error reporting is switched off at the moment since * the receiving of them is not yet 100% verified * This should be enabled sooner or later * if (error_reporting) { ret = softing_fct_cmd(card, 51, "enable_error_frame"); if (ret < 0) goto failed; } */ /* initialize interface */ iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 6]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 8]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 10]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 12]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 14]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 16]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 18]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 20]); ret = softing_fct_cmd(card, 17, "initialize_interface"); if (ret < 0) goto failed; /* enable_fifo */ ret = softing_fct_cmd(card, 36, "enable_fifo"); if (ret < 0) goto failed; /* enable fifo tx ack */ ret = softing_fct_cmd(card, 13, "fifo_tx_ack[0]"); if (ret < 0) goto failed; /* enable fifo tx ack2 */ ret = softing_fct_cmd(card, 14, "fifo_tx_ack[1]"); if (ret < 0) goto failed; /* start_chip */ ret = softing_fct_cmd(card, 11, "start_chip"); if (ret < 0) goto failed; iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE]); iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE2]); if (card->pdat->generation < 2) { iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]); /* flush the DPRAM caches */ wmb(); } softing_initialize_timestamp(card); /* * do socketcan notifications/status changes * from here, no errors should occur, or the failed: part * must be reviewed */ memset(&msg, 0, sizeof(msg)); msg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; msg.can_dlc = CAN_ERR_DLC; for (j = 0; j < ARRAY_SIZE(card->net); ++j) { if (!(bus_bitmask_start & (1 << j))) continue; netdev = card->net[j]; if (!netdev) continue; priv = netdev_priv(netdev); priv->can.state = CAN_STATE_ERROR_ACTIVE; open_candev(netdev); if (dev != netdev) { /* notify other busses on the restart */ softing_netdev_rx(netdev, &msg, ktime_set(0, 0)); ++priv->can.can_stats.restarts; } netif_wake_queue(netdev); } /* enable interrupts */ ret = softing_enable_irq(card, 1); if (ret) goto failed; card_done: mutex_unlock(&card->fw.lock); return 0; invalid: ret = -EINVAL; failed: softing_enable_irq(card, 0); softing_reset_chip(card); mutex_unlock(&card->fw.lock); /* bring all other interfaces down */ for (j = 0; j < ARRAY_SIZE(card->net); ++j) { netdev = card->net[j]; if (!netdev) continue; dev_close(netdev); } return ret; }
int softing_startstop(struct net_device *dev, int up) { int ret; struct softing *card; struct softing_priv *priv; struct net_device *netdev; int bus_bitmask_start; int j, error_reporting; struct can_frame msg; const struct can_bittiming *bt; priv = netdev_priv(dev); card = priv->card; if (!card->fw.up) return -EIO; ret = mutex_lock_interruptible(&card->fw.lock); if (ret) return ret; bus_bitmask_start = 0; if (dev && up) bus_bitmask_start |= (1 << priv->index); for (j = 0; j < ARRAY_SIZE(card->net); ++j) { netdev = card->net[j]; if (!netdev) continue; priv = netdev_priv(netdev); if (dev != netdev) netif_stop_queue(netdev); if (netif_running(netdev)) { if (dev != netdev) bus_bitmask_start |= (1 << j); priv->tx.pending = 0; priv->tx.echo_put = 0; priv->tx.echo_get = 0; close_candev(netdev); } priv->can.state = CAN_STATE_STOPPED; } card->tx.pending = 0; softing_enable_irq(card, 0); ret = softing_reset_chip(card); if (ret) goto failed; if (!bus_bitmask_start) goto card_done; if ((bus_bitmask_start & 1) && (bus_bitmask_start & 2) && (softing_error_reporting(card->net[0]) != softing_error_reporting(card->net[1]))) { dev_alert(&card->pdev->dev, "err_reporting flag differs for busses\n"); goto invalid; } error_reporting = 0; if (bus_bitmask_start & 1) { netdev = card->net[0]; priv = netdev_priv(netdev); error_reporting += softing_error_reporting(netdev); bt = &priv->can.bittiming; iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]); iowrite16(bt->phase_seg1 + bt->prop_seg, &card->dpram[DPRAM_FCT_PARAM + 6]); iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]); iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0, &card->dpram[DPRAM_FCT_PARAM + 10]); ret = softing_fct_cmd(card, 1, "initialize_chip[0]"); if (ret < 0) goto failed; iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]); ret = softing_fct_cmd(card, 3, "set_mode[0]"); if (ret < 0) goto failed; iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]); iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]); iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]); iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]); iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]); ret = softing_fct_cmd(card, 7, "set_filter[0]"); if (ret < 0) goto failed; iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]); ret = softing_fct_cmd(card, 5, "set_output[0]"); if (ret < 0) goto failed; } if (bus_bitmask_start & 2) { netdev = card->net[1]; priv = netdev_priv(netdev); error_reporting += softing_error_reporting(netdev); bt = &priv->can.bittiming; iowrite16(bt->brp, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(bt->sjw, &card->dpram[DPRAM_FCT_PARAM + 4]); iowrite16(bt->phase_seg1 + bt->prop_seg, &card->dpram[DPRAM_FCT_PARAM + 6]); iowrite16(bt->phase_seg2, &card->dpram[DPRAM_FCT_PARAM + 8]); iowrite16((priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES) ? 1 : 0, &card->dpram[DPRAM_FCT_PARAM + 10]); ret = softing_fct_cmd(card, 2, "initialize_chip[1]"); if (ret < 0) goto failed; iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(0, &card->dpram[DPRAM_FCT_PARAM + 4]); ret = softing_fct_cmd(card, 4, "set_mode[1]"); if (ret < 0) goto failed; iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(0x07ff, &card->dpram[DPRAM_FCT_PARAM + 4]); iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 6]); iowrite16(0xffff, &card->dpram[DPRAM_FCT_PARAM + 8]); iowrite16(0x0000, &card->dpram[DPRAM_FCT_PARAM + 10]); iowrite16(0x1fff, &card->dpram[DPRAM_FCT_PARAM + 12]); ret = softing_fct_cmd(card, 8, "set_filter[1]"); if (ret < 0) goto failed; iowrite16(priv->output, &card->dpram[DPRAM_FCT_PARAM + 2]); ret = softing_fct_cmd(card, 6, "set_output[1]"); if (ret < 0) goto failed; } iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 2]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 4]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 6]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 8]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 10]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 12]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 14]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 16]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 18]); iowrite16(1, &card->dpram[DPRAM_FCT_PARAM + 20]); ret = softing_fct_cmd(card, 17, "initialize_interface"); if (ret < 0) goto failed; ret = softing_fct_cmd(card, 36, "enable_fifo"); if (ret < 0) goto failed; ret = softing_fct_cmd(card, 13, "fifo_tx_ack[0]"); if (ret < 0) goto failed; ret = softing_fct_cmd(card, 14, "fifo_tx_ack[1]"); if (ret < 0) goto failed; ret = softing_fct_cmd(card, 11, "start_chip"); if (ret < 0) goto failed; iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE]); iowrite8(0, &card->dpram[DPRAM_INFO_BUSSTATE2]); if (card->pdat->generation < 2) { iowrite8(0, &card->dpram[DPRAM_V2_IRQ_TOHOST]); wmb(); } softing_initialize_timestamp(card); memset(&msg, 0, sizeof(msg)); msg.can_id = CAN_ERR_FLAG | CAN_ERR_RESTARTED; msg.can_dlc = CAN_ERR_DLC; for (j = 0; j < ARRAY_SIZE(card->net); ++j) { if (!(bus_bitmask_start & (1 << j))) continue; netdev = card->net[j]; if (!netdev) continue; priv = netdev_priv(netdev); priv->can.state = CAN_STATE_ERROR_ACTIVE; open_candev(netdev); if (dev != netdev) { softing_netdev_rx(netdev, &msg, ktime_set(0, 0)); ++priv->can.can_stats.restarts; } netif_wake_queue(netdev); } ret = softing_enable_irq(card, 1); if (ret) goto failed; card_done: mutex_unlock(&card->fw.lock); return 0; invalid: ret = -EINVAL; failed: softing_enable_irq(card, 0); softing_reset_chip(card); mutex_unlock(&card->fw.lock); for (j = 0; j < ARRAY_SIZE(card->net); ++j) { netdev = card->net[j]; if (!netdev) continue; dev_close(netdev); } return ret; }