int c_can_power_up(struct net_device *dev) { u32 val; unsigned long time_out; struct c_can_priv *priv = netdev_priv(dev); if (!(dev->flags & IFF_UP)) return 0; WARN_ON(priv->type != BOSCH_D_CAN); c_can_pm_runtime_get_sync(priv); c_can_reset_ram(priv, true); /* Clear PDR and INIT bits */ val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); val &= ~CONTROL_EX_PDR; priv->write_reg(priv, C_CAN_CTRL_EX_REG, val); val = priv->read_reg(priv, C_CAN_CTRL_REG); val &= ~CONTROL_INIT; priv->write_reg(priv, C_CAN_CTRL_REG, val); /* Wait for the PDA bit to get clear */ time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); while ((priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) && time_after(time_out, jiffies)) cpu_relax(); if (time_after(jiffies, time_out)) return -ETIMEDOUT; c_can_start(dev); return 0; }
int c_can_power_down(struct net_device *dev) { u32 val; unsigned long time_out; struct c_can_priv *priv = netdev_priv(dev); if (!(dev->flags & IFF_UP)) return 0; WARN_ON(priv->type != BOSCH_D_CAN); /* set PDR value so the device goes to power down mode */ val = priv->read_reg(priv, C_CAN_CTRL_EX_REG); val |= CONTROL_EX_PDR; priv->write_reg(priv, C_CAN_CTRL_EX_REG, val); /* Wait for the PDA bit to get set */ time_out = jiffies + msecs_to_jiffies(INIT_WAIT_MS); while (!(priv->read_reg(priv, C_CAN_STS_REG) & STATUS_PDA) && time_after(time_out, jiffies)) cpu_relax(); if (time_after(jiffies, time_out)) return -ETIMEDOUT; c_can_stop(dev); c_can_reset_ram(priv, false); c_can_pm_runtime_put_sync(priv); return 0; }
static int c_can_open(struct net_device *dev) { int err; struct c_can_priv *priv = netdev_priv(dev); c_can_pm_runtime_get_sync(priv); c_can_reset_ram(priv, true); /* open the can device */ err = open_candev(dev); if (err) { netdev_err(dev, "failed to open can device\n"); goto exit_open_fail; } /* register interrupt handler */ err = request_irq(dev->irq, &c_can_isr, IRQF_SHARED, dev->name, dev); if (err < 0) { netdev_err(dev, "failed to request interrupt\n"); goto exit_irq_fail; } /* start the c_can controller */ err = c_can_start(dev); if (err) goto exit_start_fail; can_led_event(dev, CAN_LED_EVENT_OPEN); napi_enable(&priv->napi); /* enable status change, error and module interrupts */ c_can_irq_control(priv, true); netif_start_queue(dev); return 0; exit_start_fail: free_irq(dev->irq, dev); exit_irq_fail: close_candev(dev); exit_open_fail: c_can_reset_ram(priv, false); c_can_pm_runtime_put_sync(priv); return err; }
static int c_can_close(struct net_device *dev) { struct c_can_priv *priv = netdev_priv(dev); netif_stop_queue(dev); napi_disable(&priv->napi); c_can_stop(dev); free_irq(dev->irq, dev); close_candev(dev); c_can_reset_ram(priv, false); c_can_pm_runtime_put_sync(priv); can_led_event(dev, CAN_LED_EVENT_STOP); return 0; }