Commit e3938177 authored by Matt Kline's avatar Matt Kline Committed by Marc Kleine-Budde

can: m_can: Disable IRQs on FIFO bus errors

If FIFO reads or writes fail due to the underlying regmap (e.g., SPI)
I/O, propagate that up to the m_can driver, log an error, and disable
interrupts, similar to the mcp251xfd driver.

While reworking the FIFO functions to add this error handling,
add support for bulk reads and writes of multiple registers.

Link: https://lore.kernel.org/r/20210817050853.14875-2-matt@bitbashing.ioSigned-off-by: default avatarMatt Kline <matt@bitbashing.io>
[mkl: re-wrap long lines, remove WARN_ON, convert to netdev block comments]
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 5020ced4
This diff is collapsed.
......@@ -65,9 +65,9 @@ struct m_can_ops {
int (*clear_interrupts)(struct m_can_classdev *cdev);
u32 (*read_reg)(struct m_can_classdev *cdev, int reg);
int (*write_reg)(struct m_can_classdev *cdev, int reg, int val);
u32 (*read_fifo)(struct m_can_classdev *cdev, int addr_offset);
int (*read_fifo)(struct m_can_classdev *cdev, int addr_offset, void *val, size_t val_count);
int (*write_fifo)(struct m_can_classdev *cdev, int addr_offset,
int val);
const void *val, size_t val_count);
int (*init)(struct m_can_classdev *cdev);
};
......@@ -101,7 +101,7 @@ void m_can_class_free_dev(struct net_device *net);
int m_can_class_register(struct m_can_classdev *cdev);
void m_can_class_unregister(struct m_can_classdev *cdev);
int m_can_class_get_clocks(struct m_can_classdev *cdev);
void m_can_init_ram(struct m_can_classdev *priv);
int m_can_init_ram(struct m_can_classdev *priv);
int m_can_class_suspend(struct device *dev);
int m_can_class_resume(struct device *dev);
......
......@@ -39,11 +39,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
return readl(priv->base + reg);
}
static u32 iomap_read_fifo(struct m_can_classdev *cdev, int offset)
static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count)
{
struct m_can_pci_priv *priv = cdev_to_priv(cdev);
return readl(priv->base + offset);
ioread32_rep(priv->base + offset, val, val_count);
return 0;
}
static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
......@@ -55,11 +57,12 @@ static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
return 0;
}
static int iomap_write_fifo(struct m_can_classdev *cdev, int offset, int val)
static int iomap_write_fifo(struct m_can_classdev *cdev, int offset,
const void *val, size_t val_count)
{
struct m_can_pci_priv *priv = cdev_to_priv(cdev);
writel(val, priv->base + offset);
iowrite32_rep(priv->base + offset, val, val_count);
return 0;
}
......
......@@ -29,11 +29,13 @@ static u32 iomap_read_reg(struct m_can_classdev *cdev, int reg)
return readl(priv->base + reg);
}
static u32 iomap_read_fifo(struct m_can_classdev *cdev, int offset)
static int iomap_read_fifo(struct m_can_classdev *cdev, int offset, void *val, size_t val_count)
{
struct m_can_plat_priv *priv = cdev_to_priv(cdev);
return readl(priv->mram_base + offset);
ioread32_rep(priv->mram_base + offset, val, val_count);
return 0;
}
static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
......@@ -45,11 +47,12 @@ static int iomap_write_reg(struct m_can_classdev *cdev, int reg, int val)
return 0;
}
static int iomap_write_fifo(struct m_can_classdev *cdev, int offset, int val)
static int iomap_write_fifo(struct m_can_classdev *cdev, int offset,
const void *val, size_t val_count)
{
struct m_can_plat_priv *priv = cdev_to_priv(cdev);
writel(val, priv->mram_base + offset);
iowrite32_rep(priv->base + offset, val, val_count);
return 0;
}
......@@ -127,7 +130,9 @@ static int m_can_plat_probe(struct platform_device *pdev)
platform_set_drvdata(pdev, mcan_class);
m_can_init_ram(mcan_class);
ret = m_can_init_ram(mcan_class);
if (ret)
goto probe_fail;
pm_runtime_enable(mcan_class->dev);
ret = m_can_class_register(mcan_class);
......
......@@ -153,14 +153,12 @@ static u32 tcan4x5x_read_reg(struct m_can_classdev *cdev, int reg)
return val;
}
static u32 tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset)
static int tcan4x5x_read_fifo(struct m_can_classdev *cdev, int addr_offset,
void *val, size_t val_count)
{
struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
u32 val;
regmap_read(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, &val);
return val;
return regmap_bulk_read(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count);
}
static int tcan4x5x_write_reg(struct m_can_classdev *cdev, int reg, int val)
......@@ -171,11 +169,11 @@ static int tcan4x5x_write_reg(struct m_can_classdev *cdev, int reg, int val)
}
static int tcan4x5x_write_fifo(struct m_can_classdev *cdev,
int addr_offset, int val)
int addr_offset, const void *val, size_t val_count)
{
struct tcan4x5x_priv *priv = cdev_to_priv(cdev);
return regmap_write(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val);
return regmap_bulk_write(priv->regmap, TCAN4X5X_MRAM_START + addr_offset, val, val_count);
}
static int tcan4x5x_power_enable(struct regulator *reg, int enable)
......@@ -237,7 +235,9 @@ static int tcan4x5x_init(struct m_can_classdev *cdev)
return ret;
/* Zero out the MCAN buffers */
m_can_init_ram(cdev);
ret = m_can_init_ram(cdev);
if (ret)
return ret;
ret = regmap_update_bits(tcan4x5x->regmap, TCAN4X5X_CONFIG,
TCAN4X5X_MODE_SEL_MASK, TCAN4X5X_MODE_NORMAL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment