diff options
| -rw-r--r-- | drivers/net/can/flexcan.c | 50 |
1 files changed, 38 insertions, 12 deletions
diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 30af702a07ad..5af60ab23e6f 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c | |||
| @@ -144,6 +144,8 @@ | |||
| 144 | 144 | ||
| 145 | #define FLEXCAN_MB_CODE_MASK (0xf0ffffff) | 145 | #define FLEXCAN_MB_CODE_MASK (0xf0ffffff) |
| 146 | 146 | ||
| 147 | #define FLEXCAN_TIMEOUT_US (50) | ||
| 148 | |||
| 147 | /* | 149 | /* |
| 148 | * FLEXCAN hardware feature flags | 150 | * FLEXCAN hardware feature flags |
| 149 | * | 151 | * |
| @@ -269,26 +271,42 @@ static inline int flexcan_has_and_handle_berr(const struct flexcan_priv *priv, | |||
| 269 | (reg_esr & FLEXCAN_ESR_ERR_BUS); | 271 | (reg_esr & FLEXCAN_ESR_ERR_BUS); |
| 270 | } | 272 | } |
| 271 | 273 | ||
| 272 | static inline void flexcan_chip_enable(struct flexcan_priv *priv) | 274 | static int flexcan_chip_enable(struct flexcan_priv *priv) |
| 273 | { | 275 | { |
| 274 | struct flexcan_regs __iomem *regs = priv->base; | 276 | struct flexcan_regs __iomem *regs = priv->base; |
| 277 | unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; | ||
| 275 | u32 reg; | 278 | u32 reg; |
| 276 | 279 | ||
| 277 | reg = flexcan_read(®s->mcr); | 280 | reg = flexcan_read(®s->mcr); |
| 278 | reg &= ~FLEXCAN_MCR_MDIS; | 281 | reg &= ~FLEXCAN_MCR_MDIS; |
| 279 | flexcan_write(reg, ®s->mcr); | 282 | flexcan_write(reg, ®s->mcr); |
| 280 | 283 | ||
| 281 | udelay(10); | 284 | while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) |
| 285 | usleep_range(10, 20); | ||
| 286 | |||
| 287 | if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK) | ||
| 288 | return -ETIMEDOUT; | ||
| 289 | |||
| 290 | return 0; | ||
| 282 | } | 291 | } |
| 283 | 292 | ||
| 284 | static inline void flexcan_chip_disable(struct flexcan_priv *priv) | 293 | static int flexcan_chip_disable(struct flexcan_priv *priv) |
| 285 | { | 294 | { |
| 286 | struct flexcan_regs __iomem *regs = priv->base; | 295 | struct flexcan_regs __iomem *regs = priv->base; |
| 296 | unsigned int timeout = FLEXCAN_TIMEOUT_US / 10; | ||
| 287 | u32 reg; | 297 | u32 reg; |
| 288 | 298 | ||
| 289 | reg = flexcan_read(®s->mcr); | 299 | reg = flexcan_read(®s->mcr); |
| 290 | reg |= FLEXCAN_MCR_MDIS; | 300 | reg |= FLEXCAN_MCR_MDIS; |
| 291 | flexcan_write(reg, ®s->mcr); | 301 | flexcan_write(reg, ®s->mcr); |
| 302 | |||
| 303 | while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) | ||
| 304 | usleep_range(10, 20); | ||
| 305 | |||
| 306 | if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) | ||
| 307 | return -ETIMEDOUT; | ||
| 308 | |||
| 309 | return 0; | ||
| 292 | } | 310 | } |
| 293 | 311 | ||
| 294 | static int flexcan_get_berr_counter(const struct net_device *dev, | 312 | static int flexcan_get_berr_counter(const struct net_device *dev, |
| @@ -709,7 +727,9 @@ static int flexcan_chip_start(struct net_device *dev) | |||
| 709 | u32 reg_mcr, reg_ctrl; | 727 | u32 reg_mcr, reg_ctrl; |
| 710 | 728 | ||
| 711 | /* enable module */ | 729 | /* enable module */ |
| 712 | flexcan_chip_enable(priv); | 730 | err = flexcan_chip_enable(priv); |
| 731 | if (err) | ||
| 732 | return err; | ||
| 713 | 733 | ||
| 714 | /* soft reset */ | 734 | /* soft reset */ |
| 715 | flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); | 735 | flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); |
| @@ -949,12 +969,16 @@ static int register_flexcandev(struct net_device *dev) | |||
| 949 | goto out_disable_ipg; | 969 | goto out_disable_ipg; |
| 950 | 970 | ||
| 951 | /* select "bus clock", chip must be disabled */ | 971 | /* select "bus clock", chip must be disabled */ |
| 952 | flexcan_chip_disable(priv); | 972 | err = flexcan_chip_disable(priv); |
| 973 | if (err) | ||
| 974 | goto out_disable_per; | ||
| 953 | reg = flexcan_read(®s->ctrl); | 975 | reg = flexcan_read(®s->ctrl); |
| 954 | reg |= FLEXCAN_CTRL_CLK_SRC; | 976 | reg |= FLEXCAN_CTRL_CLK_SRC; |
| 955 | flexcan_write(reg, ®s->ctrl); | 977 | flexcan_write(reg, ®s->ctrl); |
| 956 | 978 | ||
| 957 | flexcan_chip_enable(priv); | 979 | err = flexcan_chip_enable(priv); |
| 980 | if (err) | ||
| 981 | goto out_chip_disable; | ||
| 958 | 982 | ||
| 959 | /* set freeze, halt and activate FIFO, restrict register access */ | 983 | /* set freeze, halt and activate FIFO, restrict register access */ |
| 960 | reg = flexcan_read(®s->mcr); | 984 | reg = flexcan_read(®s->mcr); |
| @@ -971,14 +995,15 @@ static int register_flexcandev(struct net_device *dev) | |||
| 971 | if (!(reg & FLEXCAN_MCR_FEN)) { | 995 | if (!(reg & FLEXCAN_MCR_FEN)) { |
| 972 | netdev_err(dev, "Could not enable RX FIFO, unsupported core\n"); | 996 | netdev_err(dev, "Could not enable RX FIFO, unsupported core\n"); |
| 973 | err = -ENODEV; | 997 | err = -ENODEV; |
| 974 | goto out_disable_per; | 998 | goto out_chip_disable; |
| 975 | } | 999 | } |
| 976 | 1000 | ||
| 977 | err = register_candev(dev); | 1001 | err = register_candev(dev); |
| 978 | 1002 | ||
| 979 | out_disable_per: | ||
| 980 | /* disable core and turn off clocks */ | 1003 | /* disable core and turn off clocks */ |
| 1004 | out_chip_disable: | ||
| 981 | flexcan_chip_disable(priv); | 1005 | flexcan_chip_disable(priv); |
| 1006 | out_disable_per: | ||
| 982 | clk_disable_unprepare(priv->clk_per); | 1007 | clk_disable_unprepare(priv->clk_per); |
| 983 | out_disable_ipg: | 1008 | out_disable_ipg: |
| 984 | clk_disable_unprepare(priv->clk_ipg); | 1009 | clk_disable_unprepare(priv->clk_ipg); |
| @@ -1121,8 +1146,11 @@ static int flexcan_suspend(struct device *device) | |||
| 1121 | { | 1146 | { |
| 1122 | struct net_device *dev = dev_get_drvdata(device); | 1147 | struct net_device *dev = dev_get_drvdata(device); |
| 1123 | struct flexcan_priv *priv = netdev_priv(dev); | 1148 | struct flexcan_priv *priv = netdev_priv(dev); |
| 1149 | int err; | ||
| 1124 | 1150 | ||
| 1125 | flexcan_chip_disable(priv); | 1151 | err = flexcan_chip_disable(priv); |
| 1152 | if (err) | ||
| 1153 | return err; | ||
| 1126 | 1154 | ||
| 1127 | if (netif_running(dev)) { | 1155 | if (netif_running(dev)) { |
| 1128 | netif_stop_queue(dev); | 1156 | netif_stop_queue(dev); |
| @@ -1143,9 +1171,7 @@ static int flexcan_resume(struct device *device) | |||
| 1143 | netif_device_attach(dev); | 1171 | netif_device_attach(dev); |
| 1144 | netif_start_queue(dev); | 1172 | netif_start_queue(dev); |
| 1145 | } | 1173 | } |
| 1146 | flexcan_chip_enable(priv); | 1174 | return flexcan_chip_enable(priv); |
| 1147 | |||
| 1148 | return 0; | ||
| 1149 | } | 1175 | } |
| 1150 | #endif /* CONFIG_PM_SLEEP */ | 1176 | #endif /* CONFIG_PM_SLEEP */ |
| 1151 | 1177 | ||
