Commit 01bb4dcc authored by Dario Binacchi's avatar Dario Binacchi Committed by Marc Kleine-Budde

can: flexcan: allow to change quirks at runtime

This is a preparation patch for the upcoming support to change the
rx-rtr capability via the ethtool API.

Link: https://lore.kernel.org/all/20220107193105.1699523-3-mkl@pengutronix.deSigned-off-by: default avatarDario Binacchi <dario.binacchi@amarulasolutions.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent bfd00e02
...@@ -369,7 +369,7 @@ struct flexcan_priv { ...@@ -369,7 +369,7 @@ struct flexcan_priv {
struct clk *clk_ipg; struct clk *clk_ipg;
struct clk *clk_per; struct clk *clk_per;
const struct flexcan_devtype_data *devtype_data; struct flexcan_devtype_data devtype_data;
struct regulator *reg_xceiver; struct regulator *reg_xceiver;
struct flexcan_stop_mode stm; struct flexcan_stop_mode stm;
...@@ -600,7 +600,7 @@ static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv) ...@@ -600,7 +600,7 @@ static inline int flexcan_enter_stop_mode(struct flexcan_priv *priv)
priv->write(reg_mcr, &regs->mcr); priv->write(reg_mcr, &regs->mcr);
/* enable stop request */ /* enable stop request */
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) {
ret = flexcan_stop_mode_enable_scfw(priv, true); ret = flexcan_stop_mode_enable_scfw(priv, true);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -619,7 +619,7 @@ static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv) ...@@ -619,7 +619,7 @@ static inline int flexcan_exit_stop_mode(struct flexcan_priv *priv)
int ret; int ret;
/* remove stop request */ /* remove stop request */
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) {
ret = flexcan_stop_mode_enable_scfw(priv, false); ret = flexcan_stop_mode_enable_scfw(priv, false);
if (ret < 0) if (ret < 0)
return ret; return ret;
...@@ -1022,7 +1022,7 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload, ...@@ -1022,7 +1022,7 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
mb = flexcan_get_mb(priv, n); mb = flexcan_get_mb(priv, n);
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
u32 code; u32 code;
do { do {
...@@ -1087,7 +1087,7 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload, ...@@ -1087,7 +1087,7 @@ static struct sk_buff *flexcan_mailbox_read(struct can_rx_offload *offload,
} }
mark_as_read: mark_as_read:
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
flexcan_write64(priv, FLEXCAN_IFLAG_MB(n), &regs->iflag1); flexcan_write64(priv, FLEXCAN_IFLAG_MB(n), &regs->iflag1);
else else
priv->write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1); priv->write(FLEXCAN_IFLAG_RX_FIFO_AVAILABLE, &regs->iflag1);
...@@ -1113,7 +1113,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) ...@@ -1113,7 +1113,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
enum can_state last_state = priv->can.state; enum can_state last_state = priv->can.state;
/* reception interrupt */ /* reception interrupt */
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
u64 reg_iflag_rx; u64 reg_iflag_rx;
int ret; int ret;
...@@ -1173,7 +1173,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) ...@@ -1173,7 +1173,7 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
/* state change interrupt or broken error state quirk fix is enabled */ /* state change interrupt or broken error state quirk fix is enabled */
if ((reg_esr & FLEXCAN_ESR_ERR_STATE) || if ((reg_esr & FLEXCAN_ESR_ERR_STATE) ||
(priv->devtype_data->quirks & (FLEXCAN_QUIRK_BROKEN_WERR_STATE | (priv->devtype_data.quirks & (FLEXCAN_QUIRK_BROKEN_WERR_STATE |
FLEXCAN_QUIRK_BROKEN_PERR_STATE))) FLEXCAN_QUIRK_BROKEN_PERR_STATE)))
flexcan_irq_state(dev, reg_esr); flexcan_irq_state(dev, reg_esr);
...@@ -1195,11 +1195,11 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) ...@@ -1195,11 +1195,11 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id)
* (1): enabled if FLEXCAN_QUIRK_BROKEN_WERR_STATE is enabled * (1): enabled if FLEXCAN_QUIRK_BROKEN_WERR_STATE is enabled
*/ */
if ((last_state != priv->can.state) && if ((last_state != priv->can.state) &&
(priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE) && (priv->devtype_data.quirks & FLEXCAN_QUIRK_BROKEN_PERR_STATE) &&
!(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) { !(priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)) {
switch (priv->can.state) { switch (priv->can.state) {
case CAN_STATE_ERROR_ACTIVE: case CAN_STATE_ERROR_ACTIVE:
if (priv->devtype_data->quirks & if (priv->devtype_data.quirks &
FLEXCAN_QUIRK_BROKEN_WERR_STATE) FLEXCAN_QUIRK_BROKEN_WERR_STATE)
flexcan_error_irq_enable(priv); flexcan_error_irq_enable(priv);
else else
...@@ -1423,13 +1423,13 @@ static int flexcan_rx_offload_setup(struct net_device *dev) ...@@ -1423,13 +1423,13 @@ static int flexcan_rx_offload_setup(struct net_device *dev)
else else
priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN; priv->mb_size = sizeof(struct flexcan_mb) + CAN_MAX_DLEN;
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_MB_16) if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_MB_16)
priv->mb_count = 16; priv->mb_count = 16;
else else
priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) + priv->mb_count = (sizeof(priv->regs->mb[0]) / priv->mb_size) +
(sizeof(priv->regs->mb[1]) / priv->mb_size); (sizeof(priv->regs->mb[1]) / priv->mb_size);
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
priv->tx_mb_reserved = priv->tx_mb_reserved =
flexcan_get_mb(priv, FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP); flexcan_get_mb(priv, FLEXCAN_TX_MB_RESERVED_OFF_TIMESTAMP);
else else
...@@ -1441,7 +1441,7 @@ static int flexcan_rx_offload_setup(struct net_device *dev) ...@@ -1441,7 +1441,7 @@ static int flexcan_rx_offload_setup(struct net_device *dev)
priv->offload.mailbox_read = flexcan_mailbox_read; priv->offload.mailbox_read = flexcan_mailbox_read;
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
priv->offload.mb_first = FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST; priv->offload.mb_first = FLEXCAN_RX_MB_OFF_TIMESTAMP_FIRST;
priv->offload.mb_last = priv->mb_count - 2; priv->offload.mb_last = priv->mb_count - 2;
...@@ -1506,7 +1506,7 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -1506,7 +1506,7 @@ static int flexcan_chip_start(struct net_device *dev)
if (err) if (err)
goto out_chip_disable; goto out_chip_disable;
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_ECC) if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SUPPORT_ECC)
flexcan_ram_init(dev); flexcan_ram_init(dev);
flexcan_set_bittiming(dev); flexcan_set_bittiming(dev);
...@@ -1535,7 +1535,7 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -1535,7 +1535,7 @@ static int flexcan_chip_start(struct net_device *dev)
* - disable for timestamp mode * - disable for timestamp mode
* - enable for FIFO mode * - enable for FIFO mode
*/ */
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP)
reg_mcr &= ~FLEXCAN_MCR_FEN; reg_mcr &= ~FLEXCAN_MCR_FEN;
else else
reg_mcr |= FLEXCAN_MCR_FEN; reg_mcr |= FLEXCAN_MCR_FEN;
...@@ -1586,7 +1586,7 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -1586,7 +1586,7 @@ static int flexcan_chip_start(struct net_device *dev)
* on most Flexcan cores, too. Otherwise we don't get * on most Flexcan cores, too. Otherwise we don't get
* any error warning or passive interrupts. * any error warning or passive interrupts.
*/ */
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_BROKEN_WERR_STATE || if (priv->devtype_data.quirks & FLEXCAN_QUIRK_BROKEN_WERR_STATE ||
priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING)
reg_ctrl |= FLEXCAN_CTRL_ERR_MSK; reg_ctrl |= FLEXCAN_CTRL_ERR_MSK;
else else
...@@ -1599,7 +1599,7 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -1599,7 +1599,7 @@ static int flexcan_chip_start(struct net_device *dev)
netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl);
priv->write(reg_ctrl, &regs->ctrl); priv->write(reg_ctrl, &regs->ctrl);
if ((priv->devtype_data->quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) { if ((priv->devtype_data.quirks & FLEXCAN_QUIRK_ENABLE_EACEN_RRS)) {
reg_ctrl2 = priv->read(&regs->ctrl2); reg_ctrl2 = priv->read(&regs->ctrl2);
reg_ctrl2 |= FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS; reg_ctrl2 |= FLEXCAN_CTRL2_EACEN | FLEXCAN_CTRL2_RRS;
priv->write(reg_ctrl2, &regs->ctrl2); priv->write(reg_ctrl2, &regs->ctrl2);
...@@ -1631,7 +1631,7 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -1631,7 +1631,7 @@ static int flexcan_chip_start(struct net_device *dev)
priv->write(reg_fdctrl, &regs->fdctrl); priv->write(reg_fdctrl, &regs->fdctrl);
} }
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_USE_OFF_TIMESTAMP) {
for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) { for (i = priv->offload.mb_first; i <= priv->offload.mb_last; i++) {
mb = flexcan_get_mb(priv, i); mb = flexcan_get_mb(priv, i);
priv->write(FLEXCAN_MB_CODE_RX_EMPTY, priv->write(FLEXCAN_MB_CODE_RX_EMPTY,
...@@ -1659,7 +1659,7 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -1659,7 +1659,7 @@ static int flexcan_chip_start(struct net_device *dev)
priv->write(0x0, &regs->rx14mask); priv->write(0x0, &regs->rx14mask);
priv->write(0x0, &regs->rx15mask); priv->write(0x0, &regs->rx15mask);
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_RXFG) if (priv->devtype_data.quirks & FLEXCAN_QUIRK_DISABLE_RXFG)
priv->write(0x0, &regs->rxfgmask); priv->write(0x0, &regs->rxfgmask);
/* clear acceptance filters */ /* clear acceptance filters */
...@@ -1673,7 +1673,7 @@ static int flexcan_chip_start(struct net_device *dev) ...@@ -1673,7 +1673,7 @@ static int flexcan_chip_start(struct net_device *dev)
* This also works around errata e5295 which generates false * This also works around errata e5295 which generates false
* positive memory errors and put the device in freeze mode. * positive memory errors and put the device in freeze mode.
*/ */
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_DISABLE_MECR) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_DISABLE_MECR) {
/* Follow the protocol as described in "Detection /* Follow the protocol as described in "Detection
* and Correction of Memory Errors" to write to * and Correction of Memory Errors" to write to
* MECR register (step 1 - 5) * MECR register (step 1 - 5)
...@@ -1799,7 +1799,7 @@ static int flexcan_open(struct net_device *dev) ...@@ -1799,7 +1799,7 @@ static int flexcan_open(struct net_device *dev)
if (err) if (err)
goto out_can_rx_offload_disable; goto out_can_rx_offload_disable;
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
err = request_irq(priv->irq_boff, err = request_irq(priv->irq_boff,
flexcan_irq, IRQF_SHARED, dev->name, dev); flexcan_irq, IRQF_SHARED, dev->name, dev);
if (err) if (err)
...@@ -1845,7 +1845,7 @@ static int flexcan_close(struct net_device *dev) ...@@ -1845,7 +1845,7 @@ static int flexcan_close(struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
flexcan_chip_interrupts_disable(dev); flexcan_chip_interrupts_disable(dev);
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
free_irq(priv->irq_err, dev); free_irq(priv->irq_err, dev);
free_irq(priv->irq_boff, dev); free_irq(priv->irq_boff, dev);
} }
...@@ -2051,9 +2051,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev) ...@@ -2051,9 +2051,9 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
priv = netdev_priv(dev); priv = netdev_priv(dev);
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW) if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_SCFW)
ret = flexcan_setup_stop_mode_scfw(pdev); ret = flexcan_setup_stop_mode_scfw(pdev);
else if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR) else if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SETUP_STOP_MODE_GPR)
ret = flexcan_setup_stop_mode_gpr(pdev); ret = flexcan_setup_stop_mode_gpr(pdev);
else else
/* return 0 directly if doesn't support stop mode feature */ /* return 0 directly if doesn't support stop mode feature */
...@@ -2181,9 +2181,10 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -2181,9 +2181,10 @@ static int flexcan_probe(struct platform_device *pdev)
dev->flags |= IFF_ECHO; dev->flags |= IFF_ECHO;
priv = netdev_priv(dev); priv = netdev_priv(dev);
priv->devtype_data = *devtype_data;
if (of_property_read_bool(pdev->dev.of_node, "big-endian") || if (of_property_read_bool(pdev->dev.of_node, "big-endian") ||
devtype_data->quirks & FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN) { priv->devtype_data.quirks & FLEXCAN_QUIRK_DEFAULT_BIG_ENDIAN) {
priv->read = flexcan_read_be; priv->read = flexcan_read_be;
priv->write = flexcan_write_be; priv->write = flexcan_write_be;
} else { } else {
...@@ -2202,10 +2203,9 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -2202,10 +2203,9 @@ static int flexcan_probe(struct platform_device *pdev)
priv->clk_ipg = clk_ipg; priv->clk_ipg = clk_ipg;
priv->clk_per = clk_per; priv->clk_per = clk_per;
priv->clk_src = clk_src; priv->clk_src = clk_src;
priv->devtype_data = devtype_data;
priv->reg_xceiver = reg_xceiver; priv->reg_xceiver = reg_xceiver;
if (devtype_data->quirks & FLEXCAN_QUIRK_NR_IRQ_3) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_NR_IRQ_3) {
priv->irq_boff = platform_get_irq(pdev, 1); priv->irq_boff = platform_get_irq(pdev, 1);
if (priv->irq_boff <= 0) { if (priv->irq_boff <= 0) {
err = -ENODEV; err = -ENODEV;
...@@ -2218,7 +2218,7 @@ static int flexcan_probe(struct platform_device *pdev) ...@@ -2218,7 +2218,7 @@ static int flexcan_probe(struct platform_device *pdev)
} }
} }
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_FD) { if (priv->devtype_data.quirks & FLEXCAN_QUIRK_SUPPORT_FD) {
priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD | priv->can.ctrlmode_supported |= CAN_CTRLMODE_FD |
CAN_CTRLMODE_FD_NON_ISO; CAN_CTRLMODE_FD_NON_ISO;
priv->can.bittiming_const = &flexcan_fd_bittiming_const; priv->can.bittiming_const = &flexcan_fd_bittiming_const;
......
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