Commit 47d55c62 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'linux-can-fixes-for-6.4-20230515' of...

Merge tag 'linux-can-fixes-for-6.4-20230515' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can

Marc Kleine-Budde says:

====================
pull-request: can 2023-05-15

The first 2 patches are by Oliver Hartkopp and allow the
MSG_CMSG_COMPAT flag for isotp and j1939.

The next patch is by Oliver Hartkopp, too and adds missing CAN XL
support in can_put_echo_skb().

Geert Uytterhoeven's patch let's the bxcan driver depend on
ARCH_STM32.

The last 5 patches are from Dario Binacchi and also affect the bxcan
driver. The bxcan driver hit mainline with v6.4-rc1 and was originally
written for IP cores containing 2 CAN interfaces with shared
resources. Dario's series updates the DT bindings and driver to
support IP cores with a single CAN interface instance as well as
adding the bxcan to the stm32f746's device tree.

* tag 'linux-can-fixes-for-6.4-20230515' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can:
  ARM: dts: stm32: add CAN support on stm32f746
  can: bxcan: add support for single peripheral configuration
  ARM: dts: stm32: add pin map for CAN controller on stm32f7
  ARM: dts: stm32f429: put can2 in secondary mode
  dt-bindings: net: can: add "st,can-secondary" property
  can: CAN_BXCAN should depend on ARCH_STM32
  can: dev: fix missing CAN XL support in can_put_echo_skb()
  can: j1939: recvmsg(): allow MSG_CMSG_COMPAT flag
  can: isotp: recvmsg(): allow MSG_CMSG_COMPAT flag
====================

Link: https://lore.kernel.org/r/20230515204722.1000957-1-mkl@pengutronix.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents d6352dae c08e2401
...@@ -21,11 +21,22 @@ properties: ...@@ -21,11 +21,22 @@ properties:
st,can-primary: st,can-primary:
description: description:
Primary and secondary mode of the bxCAN peripheral is only relevant Primary mode of the bxCAN peripheral is only relevant if the chip has
if the chip has two CAN peripherals. In that case they share some two CAN peripherals in dual CAN configuration. In that case they share
of the required logic. some of the required logic.
Not to be used if the peripheral is in single CAN configuration.
To avoid misunderstandings, it should be noted that ST documentation To avoid misunderstandings, it should be noted that ST documentation
uses the terms master/slave instead of primary/secondary. uses the terms master instead of primary.
type: boolean
st,can-secondary:
description:
Secondary mode of the bxCAN peripheral is only relevant if the chip
has two CAN peripherals in dual CAN configuration. In that case they
share some of the required logic.
Not to be used if the peripheral is in single CAN configuration.
To avoid misunderstandings, it should be noted that ST documentation
uses the terms slave instead of secondary.
type: boolean type: boolean
reg: reg:
......
...@@ -387,6 +387,7 @@ can2: can@40006800 { ...@@ -387,6 +387,7 @@ can2: can@40006800 {
interrupt-names = "tx", "rx0", "rx1", "sce"; interrupt-names = "tx", "rx0", "rx1", "sce";
resets = <&rcc STM32F4_APB1_RESET(CAN2)>; resets = <&rcc STM32F4_APB1_RESET(CAN2)>;
clocks = <&rcc 0 STM32F4_APB1_CLOCK(CAN2)>; clocks = <&rcc 0 STM32F4_APB1_CLOCK(CAN2)>;
st,can-secondary;
st,gcan = <&gcan>; st,gcan = <&gcan>;
status = "disabled"; status = "disabled";
}; };
......
...@@ -283,6 +283,88 @@ pins2 { ...@@ -283,6 +283,88 @@ pins2 {
slew-rate = <2>; slew-rate = <2>;
}; };
}; };
can1_pins_a: can1-0 {
pins1 {
pinmux = <STM32_PINMUX('A', 12, AF9)>; /* CAN1_TX */
};
pins2 {
pinmux = <STM32_PINMUX('A', 11, AF9)>; /* CAN1_RX */
bias-pull-up;
};
};
can1_pins_b: can1-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 9, AF9)>; /* CAN1_TX */
};
pins2 {
pinmux = <STM32_PINMUX('B', 8, AF9)>; /* CAN1_RX */
bias-pull-up;
};
};
can1_pins_c: can1-2 {
pins1 {
pinmux = <STM32_PINMUX('D', 1, AF9)>; /* CAN1_TX */
};
pins2 {
pinmux = <STM32_PINMUX('D', 0, AF9)>; /* CAN1_RX */
bias-pull-up;
};
};
can1_pins_d: can1-3 {
pins1 {
pinmux = <STM32_PINMUX('H', 13, AF9)>; /* CAN1_TX */
};
pins2 {
pinmux = <STM32_PINMUX('H', 14, AF9)>; /* CAN1_RX */
bias-pull-up;
};
};
can2_pins_a: can2-0 {
pins1 {
pinmux = <STM32_PINMUX('B', 6, AF9)>; /* CAN2_TX */
};
pins2 {
pinmux = <STM32_PINMUX('B', 5, AF9)>; /* CAN2_RX */
bias-pull-up;
};
};
can2_pins_b: can2-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 13, AF9)>; /* CAN2_TX */
};
pins2 {
pinmux = <STM32_PINMUX('B', 12, AF9)>; /* CAN2_RX */
bias-pull-up;
};
};
can3_pins_a: can3-0 {
pins1 {
pinmux = <STM32_PINMUX('A', 15, AF11)>; /* CAN3_TX */
};
pins2 {
pinmux = <STM32_PINMUX('A', 8, AF11)>; /* CAN3_RX */
bias-pull-up;
};
};
can3_pins_b: can3-1 {
pins1 {
pinmux = <STM32_PINMUX('B', 4, AF11)>; /* CAN3_TX */
};
pins2 {
pinmux = <STM32_PINMUX('B', 3, AF11)>; /* CAN3_RX */
bias-pull-up;
};
};
}; };
}; };
}; };
...@@ -257,6 +257,23 @@ rtc: rtc@40002800 { ...@@ -257,6 +257,23 @@ rtc: rtc@40002800 {
status = "disabled"; status = "disabled";
}; };
can3: can@40003400 {
compatible = "st,stm32f4-bxcan";
reg = <0x40003400 0x200>;
interrupts = <104>, <105>, <106>, <107>;
interrupt-names = "tx", "rx0", "rx1", "sce";
resets = <&rcc STM32F7_APB1_RESET(CAN3)>;
clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN3)>;
st,gcan = <&gcan3>;
status = "disabled";
};
gcan3: gcan@40003600 {
compatible = "st,stm32f4-gcan", "syscon";
reg = <0x40003600 0x200>;
clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN3)>;
};
usart2: serial@40004400 { usart2: serial@40004400 {
compatible = "st,stm32f7-uart"; compatible = "st,stm32f7-uart";
reg = <0x40004400 0x400>; reg = <0x40004400 0x400>;
...@@ -337,6 +354,36 @@ i2c4: i2c@40006000 { ...@@ -337,6 +354,36 @@ i2c4: i2c@40006000 {
status = "disabled"; status = "disabled";
}; };
can1: can@40006400 {
compatible = "st,stm32f4-bxcan";
reg = <0x40006400 0x200>;
interrupts = <19>, <20>, <21>, <22>;
interrupt-names = "tx", "rx0", "rx1", "sce";
resets = <&rcc STM32F7_APB1_RESET(CAN1)>;
clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN1)>;
st,can-primary;
st,gcan = <&gcan1>;
status = "disabled";
};
gcan1: gcan@40006600 {
compatible = "st,stm32f4-gcan", "syscon";
reg = <0x40006600 0x200>;
clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN1)>;
};
can2: can@40006800 {
compatible = "st,stm32f4-bxcan";
reg = <0x40006800 0x200>;
interrupts = <63>, <64>, <65>, <66>;
interrupt-names = "tx", "rx0", "rx1", "sce";
resets = <&rcc STM32F7_APB1_RESET(CAN2)>;
clocks = <&rcc 0 STM32F7_APB1_CLOCK(CAN2)>;
st,can-secondary;
st,gcan = <&gcan1>;
status = "disabled";
};
cec: cec@40006c00 { cec: cec@40006c00 {
compatible = "st,stm32-cec"; compatible = "st,stm32-cec";
reg = <0x40006C00 0x400>; reg = <0x40006C00 0x400>;
......
...@@ -95,7 +95,7 @@ config CAN_AT91 ...@@ -95,7 +95,7 @@ config CAN_AT91
config CAN_BXCAN config CAN_BXCAN
tristate "STM32 Basic Extended CAN (bxCAN) devices" tristate "STM32 Basic Extended CAN (bxCAN) devices"
depends on OF || ARCH_STM32 || COMPILE_TEST depends on ARCH_STM32 || COMPILE_TEST
depends on HAS_IOMEM depends on HAS_IOMEM
select CAN_RX_OFFLOAD select CAN_RX_OFFLOAD
help help
......
...@@ -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;
......
...@@ -54,7 +54,8 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev, ...@@ -54,7 +54,8 @@ int can_put_echo_skb(struct sk_buff *skb, struct net_device *dev,
/* check flag whether this packet has to be looped back */ /* check flag whether this packet has to be looped back */
if (!(dev->flags & IFF_ECHO) || if (!(dev->flags & IFF_ECHO) ||
(skb->protocol != htons(ETH_P_CAN) && (skb->protocol != htons(ETH_P_CAN) &&
skb->protocol != htons(ETH_P_CANFD))) { skb->protocol != htons(ETH_P_CANFD) &&
skb->protocol != htons(ETH_P_CANXL))) {
kfree_skb(skb); kfree_skb(skb);
return 0; return 0;
} }
......
...@@ -1139,7 +1139,7 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, ...@@ -1139,7 +1139,7 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size,
struct isotp_sock *so = isotp_sk(sk); struct isotp_sock *so = isotp_sk(sk);
int ret = 0; int ret = 0;
if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK)) if (flags & ~(MSG_DONTWAIT | MSG_TRUNC | MSG_PEEK | MSG_CMSG_COMPAT))
return -EINVAL; return -EINVAL;
if (!so->bound) if (!so->bound)
......
...@@ -798,7 +798,7 @@ static int j1939_sk_recvmsg(struct socket *sock, struct msghdr *msg, ...@@ -798,7 +798,7 @@ static int j1939_sk_recvmsg(struct socket *sock, struct msghdr *msg,
struct j1939_sk_buff_cb *skcb; struct j1939_sk_buff_cb *skcb;
int ret = 0; int ret = 0;
if (flags & ~(MSG_DONTWAIT | MSG_ERRQUEUE)) if (flags & ~(MSG_DONTWAIT | MSG_ERRQUEUE | MSG_CMSG_COMPAT))
return -EINVAL; return -EINVAL;
if (flags & MSG_ERRQUEUE) if (flags & MSG_ERRQUEUE)
......
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