Commit 85a79b97 authored by Dario Binacchi's avatar Dario Binacchi Committed by Marc Kleine-Budde

can: bxcan: add support for single peripheral configuration

Add support for bxCAN controller in single peripheral configuration:
- primary bxCAN
- dedicated Memory Access Controller unit
- 512-byte SRAM memory
- 14 filter banks
Signed-off-by: default avatarDario Binacchi <dario.binacchi@amarulasolutions.com>
Link: https://lore.kernel.org/all/20230427204540.3126234-5-dario.binacchi@amarulasolutions.comSigned-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 01164424
...@@ -118,7 +118,7 @@ ...@@ -118,7 +118,7 @@
#define BXCAN_FiR1_REG(b) (0x40 + (b) * 8) #define BXCAN_FiR1_REG(b) (0x40 + (b) * 8)
#define BXCAN_FiR2_REG(b) (0x44 + (b) * 8) #define BXCAN_FiR2_REG(b) (0x44 + (b) * 8)
#define BXCAN_FILTER_ID(primary) (primary ? 0 : 14) #define BXCAN_FILTER_ID(cfg) ((cfg) == BXCAN_CFG_DUAL_SECONDARY ? 14 : 0)
/* Filter primary register (FMR) bits */ /* Filter primary register (FMR) bits */
#define BXCAN_FMR_CANSB_MASK GENMASK(13, 8) #define BXCAN_FMR_CANSB_MASK GENMASK(13, 8)
...@@ -135,6 +135,12 @@ enum bxcan_lec_code { ...@@ -135,6 +135,12 @@ enum bxcan_lec_code {
BXCAN_LEC_UNUSED BXCAN_LEC_UNUSED
}; };
enum bxcan_cfg {
BXCAN_CFG_SINGLE = 0,
BXCAN_CFG_DUAL_PRIMARY,
BXCAN_CFG_DUAL_SECONDARY
};
/* Structure of the message buffer */ /* Structure of the message buffer */
struct bxcan_mb { struct bxcan_mb {
u32 id; /* can identifier */ u32 id; /* can identifier */
...@@ -167,7 +173,7 @@ struct bxcan_priv { ...@@ -167,7 +173,7 @@ struct bxcan_priv {
struct regmap *gcan; struct regmap *gcan;
int tx_irq; int tx_irq;
int sce_irq; int sce_irq;
bool primary; enum bxcan_cfg cfg;
struct clk *clk; struct clk *clk;
spinlock_t rmw_lock; /* lock for read-modify-write operations */ spinlock_t rmw_lock; /* lock for read-modify-write operations */
unsigned int tx_head; unsigned int tx_head;
...@@ -202,17 +208,17 @@ static inline void bxcan_rmw(struct bxcan_priv *priv, void __iomem *addr, ...@@ -202,17 +208,17 @@ static inline void bxcan_rmw(struct bxcan_priv *priv, void __iomem *addr,
spin_unlock_irqrestore(&priv->rmw_lock, flags); spin_unlock_irqrestore(&priv->rmw_lock, flags);
} }
static void bxcan_disable_filters(struct bxcan_priv *priv, bool primary) static void bxcan_disable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg)
{ {
unsigned int fid = BXCAN_FILTER_ID(primary); unsigned int fid = BXCAN_FILTER_ID(cfg);
u32 fmask = BIT(fid); u32 fmask = BIT(fid);
regmap_update_bits(priv->gcan, BXCAN_FA1R_REG, fmask, 0); regmap_update_bits(priv->gcan, BXCAN_FA1R_REG, fmask, 0);
} }
static void bxcan_enable_filters(struct bxcan_priv *priv, bool primary) static void bxcan_enable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg)
{ {
unsigned int fid = BXCAN_FILTER_ID(primary); unsigned int fid = BXCAN_FILTER_ID(cfg);
u32 fmask = BIT(fid); u32 fmask = BIT(fid);
/* Filter settings: /* Filter settings:
...@@ -680,7 +686,7 @@ static int bxcan_chip_start(struct net_device *ndev) ...@@ -680,7 +686,7 @@ static int bxcan_chip_start(struct net_device *ndev)
BXCAN_BTR_BRP_MASK | BXCAN_BTR_TS1_MASK | BXCAN_BTR_TS2_MASK | BXCAN_BTR_BRP_MASK | BXCAN_BTR_TS1_MASK | BXCAN_BTR_TS2_MASK |
BXCAN_BTR_SJW_MASK, set); BXCAN_BTR_SJW_MASK, set);
bxcan_enable_filters(priv, priv->primary); bxcan_enable_filters(priv, priv->cfg);
/* Clear all internal status */ /* Clear all internal status */
priv->tx_head = 0; priv->tx_head = 0;
...@@ -806,7 +812,7 @@ static void bxcan_chip_stop(struct net_device *ndev) ...@@ -806,7 +812,7 @@ static void bxcan_chip_stop(struct net_device *ndev)
BXCAN_IER_EPVIE | BXCAN_IER_EWGIE | BXCAN_IER_FOVIE1 | BXCAN_IER_EPVIE | BXCAN_IER_EWGIE | BXCAN_IER_FOVIE1 |
BXCAN_IER_FFIE1 | BXCAN_IER_FMPIE1 | BXCAN_IER_FOVIE0 | BXCAN_IER_FFIE1 | BXCAN_IER_FMPIE1 | BXCAN_IER_FOVIE0 |
BXCAN_IER_FFIE0 | BXCAN_IER_FMPIE0 | BXCAN_IER_TMEIE, 0); BXCAN_IER_FFIE0 | BXCAN_IER_FMPIE0 | BXCAN_IER_TMEIE, 0);
bxcan_disable_filters(priv, priv->primary); bxcan_disable_filters(priv, priv->cfg);
bxcan_enter_sleep_mode(priv); bxcan_enter_sleep_mode(priv);
priv->can.state = CAN_STATE_STOPPED; priv->can.state = CAN_STATE_STOPPED;
} }
...@@ -931,7 +937,7 @@ static int bxcan_probe(struct platform_device *pdev) ...@@ -931,7 +937,7 @@ static int bxcan_probe(struct platform_device *pdev)
struct clk *clk = NULL; struct clk *clk = NULL;
void __iomem *regs; void __iomem *regs;
struct regmap *gcan; struct regmap *gcan;
bool primary; enum bxcan_cfg cfg;
int err, rx_irq, tx_irq, sce_irq; int err, rx_irq, tx_irq, sce_irq;
regs = devm_platform_ioremap_resource(pdev, 0); regs = devm_platform_ioremap_resource(pdev, 0);
...@@ -946,7 +952,13 @@ static int bxcan_probe(struct platform_device *pdev) ...@@ -946,7 +952,13 @@ static int bxcan_probe(struct platform_device *pdev)
return PTR_ERR(gcan); return PTR_ERR(gcan);
} }
primary = of_property_read_bool(np, "st,can-primary"); if (of_property_read_bool(np, "st,can-primary"))
cfg = BXCAN_CFG_DUAL_PRIMARY;
else if (of_property_read_bool(np, "st,can-secondary"))
cfg = BXCAN_CFG_DUAL_SECONDARY;
else
cfg = BXCAN_CFG_SINGLE;
clk = devm_clk_get(dev, NULL); clk = devm_clk_get(dev, NULL);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(dev, "failed to get clock\n"); dev_err(dev, "failed to get clock\n");
...@@ -992,7 +1004,7 @@ static int bxcan_probe(struct platform_device *pdev) ...@@ -992,7 +1004,7 @@ static int bxcan_probe(struct platform_device *pdev)
priv->clk = clk; priv->clk = clk;
priv->tx_irq = tx_irq; priv->tx_irq = tx_irq;
priv->sce_irq = sce_irq; priv->sce_irq = sce_irq;
priv->primary = primary; priv->cfg = cfg;
priv->can.clock.freq = clk_get_rate(clk); priv->can.clock.freq = clk_get_rate(clk);
spin_lock_init(&priv->rmw_lock); spin_lock_init(&priv->rmw_lock);
priv->tx_head = 0; priv->tx_head = 0;
......
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