Skip to content

Commit c08e240

Browse files
Merge patch series "can: bxcan: add support for single peripheral configuration"
Dario Binacchi <[email protected]> says: The series adds support for managing bxCAN controllers in single peripheral configuration. Unlike stm32f4 SOCs, where bxCAN controllers are only in dual peripheral configuration, stm32f7 SOCs contain three CAN peripherals, CAN1 and CAN2 in dual peripheral configuration and CAN3 in single peripheral configuration: - Dual CAN peripheral configuration: * CAN1: Primary bxCAN for managing the communication between a secondary bxCAN and the 512-byte SRAM memory. * CAN2: Secondary bxCAN with no direct access to the SRAM memory. This means that the two bxCAN cells share the 512-byte SRAM memory and CAN2 can't be used without enabling CAN1. - Single CAN peripheral configuration: * CAN3: Primary bxCAN with dedicated Memory Access Controller unit and 512-byte SRAM memory. The driver has been tested on the stm32f769i-discovery board with a kernel version 5.19.0-rc2 in loopback + silent mode: | ip link set can[0-2] type can bitrate 125000 loopback on listen-only on | ip link set up can[0-2] | candump can[0-2] -L & | cansend can[0-2] 300#AC.AB.AD.AE.75.49.AD.D1 Changes in v2: - s/fiter/filter/ in the commit message - Replace struct bxcan_mb::primary with struct bxcan_mb::cfg. - Move after the patch "can: bxcan: add support for single peripheral configuration". - Add node gcan3. - Rename gcan as gcan1. - Add property "st,can-secondary" to can2 node. - Drop patch "dt-bindings: mfd: stm32f7: add binding definition for CAN3" because it has been accepted. - Add patch "ARM: dts: stm32f429: put can2 in secondary mode". - Add patch "dt-bindings: net: can: add "st,can-secondary" property". v1: https://lore.kernel.org/all/[email protected] Link: https://lore.kernel.org/all/[email protected] Signed-off-by: Marc Kleine-Budde <[email protected]>
2 parents 4920bde + 0920ccd commit c08e240

File tree

5 files changed

+168
-15
lines changed

5 files changed

+168
-15
lines changed

Documentation/devicetree/bindings/net/can/st,stm32-bxcan.yaml

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,11 +21,22 @@ properties:
2121

2222
st,can-primary:
2323
description:
24-
Primary and secondary mode of the bxCAN peripheral is only relevant
25-
if the chip has two CAN peripherals. In that case they share some
26-
of the required logic.
24+
Primary mode of the bxCAN peripheral is only relevant if the chip has
25+
two CAN peripherals in dual CAN configuration. In that case they share
26+
some of the required logic.
27+
Not to be used if the peripheral is in single CAN configuration.
2728
To avoid misunderstandings, it should be noted that ST documentation
28-
uses the terms master/slave instead of primary/secondary.
29+
uses the terms master instead of primary.
30+
type: boolean
31+
32+
st,can-secondary:
33+
description:
34+
Secondary mode of the bxCAN peripheral is only relevant if the chip
35+
has two CAN peripherals in dual CAN configuration. In that case they
36+
share some of the required logic.
37+
Not to be used if the peripheral is in single CAN configuration.
38+
To avoid misunderstandings, it should be noted that ST documentation
39+
uses the terms slave instead of secondary.
2940
type: boolean
3041

3142
reg:

arch/arm/boot/dts/stm32f429.dtsi

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,7 @@
387387
interrupt-names = "tx", "rx0", "rx1", "sce";
388388
resets = <&rcc STM32F4_APB1_RESET(CAN2)>;
389389
clocks = <&rcc 0 STM32F4_APB1_CLOCK(CAN2)>;
390+
st,can-secondary;
390391
st,gcan = <&gcan>;
391392
status = "disabled";
392393
};

arch/arm/boot/dts/stm32f7-pinctrl.dtsi

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,88 @@
283283
slew-rate = <2>;
284284
};
285285
};
286+
287+
can1_pins_a: can1-0 {
288+
pins1 {
289+
pinmux = <STM32_PINMUX('A', 12, AF9)>; /* CAN1_TX */
290+
};
291+
pins2 {
292+
pinmux = <STM32_PINMUX('A', 11, AF9)>; /* CAN1_RX */
293+
bias-pull-up;
294+
};
295+
};
296+
297+
can1_pins_b: can1-1 {
298+
pins1 {
299+
pinmux = <STM32_PINMUX('B', 9, AF9)>; /* CAN1_TX */
300+
};
301+
pins2 {
302+
pinmux = <STM32_PINMUX('B', 8, AF9)>; /* CAN1_RX */
303+
bias-pull-up;
304+
};
305+
};
306+
307+
can1_pins_c: can1-2 {
308+
pins1 {
309+
pinmux = <STM32_PINMUX('D', 1, AF9)>; /* CAN1_TX */
310+
};
311+
pins2 {
312+
pinmux = <STM32_PINMUX('D', 0, AF9)>; /* CAN1_RX */
313+
bias-pull-up;
314+
315+
};
316+
};
317+
318+
can1_pins_d: can1-3 {
319+
pins1 {
320+
pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
321+
};
322+
pins2 {
323+
pinmux = <STM32_PINMUX('H', 14, AF9)>; /* CAN1_RX */
324+
bias-pull-up;
325+
326+
};
327+
};
328+
329+
can2_pins_a: can2-0 {
330+
pins1 {
331+
pinmux = <STM32_PINMUX('B', 6, AF9)>; /* CAN2_TX */
332+
};
333+
pins2 {
334+
pinmux = <STM32_PINMUX('B', 5, AF9)>; /* CAN2_RX */
335+
bias-pull-up;
336+
};
337+
};
338+
339+
can2_pins_b: can2-1 {
340+
pins1 {
341+
pinmux = <STM32_PINMUX('B', 13, AF9)>; /* CAN2_TX */
342+
};
343+
pins2 {
344+
pinmux = <STM32_PINMUX('B', 12, AF9)>; /* CAN2_RX */
345+
bias-pull-up;
346+
};
347+
};
348+
349+
can3_pins_a: can3-0 {
350+
pins1 {
351+
pinmux = <STM32_PINMUX('A', 15, AF11)>; /* CAN3_TX */
352+
};
353+
pins2 {
354+
pinmux = <STM32_PINMUX('A', 8, AF11)>; /* CAN3_RX */
355+
bias-pull-up;
356+
};
357+
};
358+
359+
can3_pins_b: can3-1 {
360+
pins1 {
361+
pinmux = <STM32_PINMUX('B', 4, AF11)>; /* CAN3_TX */
362+
};
363+
pins2 {
364+
pinmux = <STM32_PINMUX('B', 3, AF11)>; /* CAN3_RX */
365+
bias-pull-up;
366+
};
367+
};
286368
};
287369
};
288370
};

arch/arm/boot/dts/stm32f746.dtsi

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -257,6 +257,23 @@
257257
status = "disabled";
258258
};
259259

260+
can3: can@40003400 {
261+
compatible = "st,stm32f4-bxcan";
262+
reg = <0x40003400 0x200>;
263+
interrupts = <104>, <105>, <106>, <107>;
264+
interrupt-names = "tx", "rx0", "rx1", "sce";
265+
resets = <&rcc STM32F7_APB1_RESET(CAN3)>;
266+
clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN3)>;
267+
st,gcan = <&gcan3>;
268+
status = "disabled";
269+
};
270+
271+
gcan3: gcan@40003600 {
272+
compatible = "st,stm32f4-gcan", "syscon";
273+
reg = <0x40003600 0x200>;
274+
clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN3)>;
275+
};
276+
260277
usart2: serial@40004400 {
261278
compatible = "st,stm32f7-uart";
262279
reg = <0x40004400 0x400>;
@@ -337,6 +354,36 @@
337354
status = "disabled";
338355
};
339356

357+
can1: can@40006400 {
358+
compatible = "st,stm32f4-bxcan";
359+
reg = <0x40006400 0x200>;
360+
interrupts = <19>, <20>, <21>, <22>;
361+
interrupt-names = "tx", "rx0", "rx1", "sce";
362+
resets = <&rcc STM32F7_APB1_RESET(CAN1)>;
363+
clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN1)>;
364+
st,can-primary;
365+
st,gcan = <&gcan1>;
366+
status = "disabled";
367+
};
368+
369+
gcan1: gcan@40006600 {
370+
compatible = "st,stm32f4-gcan", "syscon";
371+
reg = <0x40006600 0x200>;
372+
clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN1)>;
373+
};
374+
375+
can2: can@40006800 {
376+
compatible = "st,stm32f4-bxcan";
377+
reg = <0x40006800 0x200>;
378+
interrupts = <63>, <64>, <65>, <66>;
379+
interrupt-names = "tx", "rx0", "rx1", "sce";
380+
resets = <&rcc STM32F7_APB1_RESET(CAN2)>;
381+
clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN2)>;
382+
st,can-secondary;
383+
st,gcan = <&gcan1>;
384+
status = "disabled";
385+
};
386+
340387
cec: cec@40006c00 {
341388
compatible = "st,stm32-cec";
342389
reg = <0x40006C00 0x400>;

drivers/net/can/bxcan.c

Lines changed: 23 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@
118118
#define BXCAN_FiR1_REG(b) (0x40 + (b) * 8)
119119
#define BXCAN_FiR2_REG(b) (0x44 + (b) * 8)
120120

121-
#define BXCAN_FILTER_ID(primary) (primary ? 0 : 14)
121+
#define BXCAN_FILTER_ID(cfg) ((cfg) == BXCAN_CFG_DUAL_SECONDARY ? 14 : 0)
122122

123123
/* Filter primary register (FMR) bits */
124124
#define BXCAN_FMR_CANSB_MASK GENMASK(13, 8)
@@ -135,6 +135,12 @@ enum bxcan_lec_code {
135135
BXCAN_LEC_UNUSED
136136
};
137137

138+
enum bxcan_cfg {
139+
BXCAN_CFG_SINGLE = 0,
140+
BXCAN_CFG_DUAL_PRIMARY,
141+
BXCAN_CFG_DUAL_SECONDARY
142+
};
143+
138144
/* Structure of the message buffer */
139145
struct bxcan_mb {
140146
u32 id; /* can identifier */
@@ -167,7 +173,7 @@ struct bxcan_priv {
167173
struct regmap *gcan;
168174
int tx_irq;
169175
int sce_irq;
170-
bool primary;
176+
enum bxcan_cfg cfg;
171177
struct clk *clk;
172178
spinlock_t rmw_lock; /* lock for read-modify-write operations */
173179
unsigned int tx_head;
@@ -202,17 +208,17 @@ static inline void bxcan_rmw(struct bxcan_priv *priv, void __iomem *addr,
202208
spin_unlock_irqrestore(&priv->rmw_lock, flags);
203209
}
204210

205-
static void bxcan_disable_filters(struct bxcan_priv *priv, bool primary)
211+
static void bxcan_disable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg)
206212
{
207-
unsigned int fid = BXCAN_FILTER_ID(primary);
213+
unsigned int fid = BXCAN_FILTER_ID(cfg);
208214
u32 fmask = BIT(fid);
209215

210216
regmap_update_bits(priv->gcan, BXCAN_FA1R_REG, fmask, 0);
211217
}
212218

213-
static void bxcan_enable_filters(struct bxcan_priv *priv, bool primary)
219+
static void bxcan_enable_filters(struct bxcan_priv *priv, enum bxcan_cfg cfg)
214220
{
215-
unsigned int fid = BXCAN_FILTER_ID(primary);
221+
unsigned int fid = BXCAN_FILTER_ID(cfg);
216222
u32 fmask = BIT(fid);
217223

218224
/* Filter settings:
@@ -680,7 +686,7 @@ static int bxcan_chip_start(struct net_device *ndev)
680686
BXCAN_BTR_BRP_MASK | BXCAN_BTR_TS1_MASK | BXCAN_BTR_TS2_MASK |
681687
BXCAN_BTR_SJW_MASK, set);
682688

683-
bxcan_enable_filters(priv, priv->primary);
689+
bxcan_enable_filters(priv, priv->cfg);
684690

685691
/* Clear all internal status */
686692
priv->tx_head = 0;
@@ -806,7 +812,7 @@ static void bxcan_chip_stop(struct net_device *ndev)
806812
BXCAN_IER_EPVIE | BXCAN_IER_EWGIE | BXCAN_IER_FOVIE1 |
807813
BXCAN_IER_FFIE1 | BXCAN_IER_FMPIE1 | BXCAN_IER_FOVIE0 |
808814
BXCAN_IER_FFIE0 | BXCAN_IER_FMPIE0 | BXCAN_IER_TMEIE, 0);
809-
bxcan_disable_filters(priv, priv->primary);
815+
bxcan_disable_filters(priv, priv->cfg);
810816
bxcan_enter_sleep_mode(priv);
811817
priv->can.state = CAN_STATE_STOPPED;
812818
}
@@ -931,7 +937,7 @@ static int bxcan_probe(struct platform_device *pdev)
931937
struct clk *clk = NULL;
932938
void __iomem *regs;
933939
struct regmap *gcan;
934-
bool primary;
940+
enum bxcan_cfg cfg;
935941
int err, rx_irq, tx_irq, sce_irq;
936942

937943
regs = devm_platform_ioremap_resource(pdev, 0);
@@ -946,7 +952,13 @@ static int bxcan_probe(struct platform_device *pdev)
946952
return PTR_ERR(gcan);
947953
}
948954

949-
primary = of_property_read_bool(np, "st,can-primary");
955+
if (of_property_read_bool(np, "st,can-primary"))
956+
cfg = BXCAN_CFG_DUAL_PRIMARY;
957+
else if (of_property_read_bool(np, "st,can-secondary"))
958+
cfg = BXCAN_CFG_DUAL_SECONDARY;
959+
else
960+
cfg = BXCAN_CFG_SINGLE;
961+
950962
clk = devm_clk_get(dev, NULL);
951963
if (IS_ERR(clk)) {
952964
dev_err(dev, "failed to get clock\n");
@@ -992,7 +1004,7 @@ static int bxcan_probe(struct platform_device *pdev)
9921004
priv->clk = clk;
9931005
priv->tx_irq = tx_irq;
9941006
priv->sce_irq = sce_irq;
995-
priv->primary = primary;
1007+
priv->cfg = cfg;
9961008
priv->can.clock.freq = clk_get_rate(clk);
9971009
spin_lock_init(&priv->rmw_lock);
9981010
priv->tx_head = 0;

0 commit comments

Comments
 (0)