static int pcan_add_channels(struct pcan_pccard *card) { struct pcmcia_device *pdev = card->pdev; int i, err = 0; u8 ccr = PCC_CCR_INIT; /* init common registers (reset channels and leds off) */ card->ccr = ~ccr; pcan_write_reg(card, PCC_CCR, ccr); /* wait 2ms before unresetting channels */ mdelay(2); ccr &= ~PCC_CCR_RST_ALL; pcan_write_reg(card, PCC_CCR, ccr); /* create one network device per channel detected */ for (i = 0; i < ARRAY_SIZE(card->channel); i++) { struct net_device *netdev; struct sja1000_priv *priv; netdev = alloc_sja1000dev(0); if (!netdev) { err = -ENOMEM; break; } /* update linkages */ priv = netdev_priv(netdev); priv->priv = card; SET_NETDEV_DEV(netdev, &pdev->dev); priv->irq_flags = IRQF_SHARED; netdev->irq = pdev->irq; priv->reg_base = card->ioport_addr + PCC_CHAN_OFF(i); /* check if channel is present */ if (!pcan_channel_present(priv)) { dev_err(&pdev->dev, "channel %d not present\n", i); free_sja1000dev(netdev); continue; } priv->read_reg = pcan_read_canreg; priv->write_reg = pcan_write_canreg; priv->can.clock.freq = PCC_CAN_CLOCK; priv->ocr = PCC_OCR; priv->cdr = PCC_CDR; /* Neither a slave device distributes the clock */ if (i > 0) priv->cdr |= CDR_CLK_OFF; priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER; /* register SJA1000 device */ err = register_sja1000dev(netdev); if (err) { free_sja1000dev(netdev); continue; } card->channel[i].netdev = netdev; card->chan_count++; /* set corresponding led on in the new ccr */ ccr &= ~PCC_CCR_LED_OFF_CHAN(i); dev_info(&pdev->dev, "%s on channel %d at 0x%p irq %d\n", netdev->name, i, priv->reg_base, pdev->irq); } /* write new ccr (change leds state) */ pcan_write_reg(card, PCC_CCR, ccr); return err; }
static int pcan_add_channels(struct pcan_pccard *card) { struct pcmcia_device *pdev = card->pdev; int i, err = 0; u8 ccr = PCC_CCR_INIT; card->ccr = ~ccr; pcan_write_reg(card, PCC_CCR, ccr); mdelay(2); ccr &= ~PCC_CCR_RST_ALL; pcan_write_reg(card, PCC_CCR, ccr); for (i = 0; i < ARRAY_SIZE(card->channel); i++) { struct net_device *netdev; struct sja1000_priv *priv; netdev = alloc_sja1000dev(0); if (!netdev) { err = -ENOMEM; break; } priv = netdev_priv(netdev); priv->priv = card; SET_NETDEV_DEV(netdev, &pdev->dev); priv->irq_flags = IRQF_SHARED; netdev->irq = pdev->irq; priv->reg_base = card->ioport_addr + PCC_CHAN_OFF(i); if (!pcan_channel_present(priv)) { dev_err(&pdev->dev, "channel %d not present\n", i); free_sja1000dev(netdev); continue; } priv->read_reg = pcan_read_canreg; priv->write_reg = pcan_write_canreg; priv->can.clock.freq = PCC_CAN_CLOCK; priv->ocr = PCC_OCR; priv->cdr = PCC_CDR; if (i > 0) priv->cdr |= CDR_CLK_OFF; priv->flags |= SJA1000_CUSTOM_IRQ_HANDLER; err = register_sja1000dev(netdev); if (err) { free_sja1000dev(netdev); continue; } card->channel[i].netdev = netdev; card->chan_count++; ccr &= ~PCC_CCR_LED_OFF_CHAN(i); dev_info(&pdev->dev, "%s on channel %d at 0x%p irq %d\n", netdev->name, i, priv->reg_base, pdev->irq); } pcan_write_reg(card, PCC_CCR, ccr); return err; }