提交 8333c1c4 编写于 作者: D David S. Miller

Merge tag 'linux-can-next-for-5.10-20200930' of...

Merge tag 'linux-can-next-for-5.10-20200930' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
pull-request: can-next 2020-09-30

this is a pull request of 13 patches for net-next.

The first 10 target the mcp25xxfd driver (which is renamed to mcp251xfd during
this series).

The first two patches are by Thomas Kopp, which adds reference to the just
related errata and updates the documentation and log messages.

Dan Carpenter's patch fixes a resource leak during ifdown.

A patch by me adds the missing initialization of a variable.

Oleksij Rempel updates the DT binding documentation as requested by Rob
Herring.

The next 5 patches are by Thomas Kopp and me. During review Geert Uytterhoeven
suggested to use "microchip,mcp251xfd" instead of "microchip,mcp25xxfd" as the
DT autodetection compatible to avoid clashes with future but incompatible
devices. We decided not only to rename the compatible but the whole driver from
"mcp25xxfd" to "mcp251xfd". This is done in several patches.

Joakim Zhang contributes three patches for the flexcan driver. The first one
adds support for the ECC feature, which is implemented on some modern IP cores,
by initializing the controller's memory during ifup. The next patch adds
support for the i.MX8MP (which supports ECC) and the last patch properly
disables the runtime PM if device registration fails.
====================
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
%YAML 1.2
---
$id: http://devicetree.org/schemas/net/can/microchip,mcp25xxfd.yaml#
$id: http://devicetree.org/schemas/net/can/microchip,mcp251xfd.yaml#
$schema: http://devicetree.org/meta-schemas/core.yaml#
title:
......@@ -18,13 +18,13 @@ properties:
description: for MCP2517FD
- const: microchip,mcp2518fd
description: for MCP2518FD
- const: microchip,mcp25xxfd
- const: microchip,mcp251xfd
description: to autodetect chip variant
reg:
maxItems: 1
interrupts-extended:
interrupts:
maxItems: 1
clocks:
......@@ -32,15 +32,13 @@ properties:
vdd-supply:
description: Regulator that powers the CAN controller.
maxItems: 1
xceiver-supply:
description: Regulator that powers the CAN transceiver.
maxItems: 1
microchip,rx-int-gpios:
description:
GPIO phandle of GPIO connected to to INT1 pin of the MCP25XXFD, which
GPIO phandle of GPIO connected to to INT1 pin of the MCP251XFD, which
signals a pending RX interrupt.
maxItems: 1
......@@ -52,9 +50,11 @@ properties:
required:
- compatible
- reg
- interrupts-extended
- interrupts
- clocks
additionalProperties: false
examples:
- |
#include <dt-bindings/gpio/gpio.h>
......@@ -65,7 +65,7 @@ examples:
#size-cells = <0>;
can@0 {
compatible = "microchip,mcp25xxfd";
compatible = "microchip,mcp251xfd";
reg = <0>;
clocks = <&can0_osc>;
pinctrl-names = "default";
......
......@@ -214,6 +214,7 @@
* MX53 FlexCAN2 03.00.00.00 yes no no no no no
* MX6s FlexCAN3 10.00.12.00 yes yes no no yes no
* MX8QM FlexCAN3 03.00.23.00 yes yes no no yes yes
* MX8MP FlexCAN3 03.00.17.01 yes yes no yes yes yes
* VF610 FlexCAN3 ? no yes no yes yes? no
* LS1021A FlexCAN2 03.00.04.00 no yes no no yes no
* LX2160A FlexCAN3 03.00.23.00 no yes no no yes yes
......@@ -239,6 +240,8 @@
#define FLEXCAN_QUIRK_SETUP_STOP_MODE BIT(8)
/* Support CAN-FD mode */
#define FLEXCAN_QUIRK_SUPPORT_FD BIT(9)
/* support memory detection and correction */
#define FLEXCAN_QUIRK_SUPPORT_ECC BIT(10)
/* Structure of the message buffer */
struct flexcan_mb {
......@@ -292,7 +295,16 @@ struct flexcan_regs {
u32 rximr[64]; /* 0x880 - Not affected by Soft Reset */
u32 _reserved5[24]; /* 0x980 */
u32 gfwr_mx6; /* 0x9e0 - MX6 */
u32 _reserved6[63]; /* 0x9e4 */
u32 _reserved6[39]; /* 0x9e4 */
u32 _rxfir[6]; /* 0xa80 */
u32 _reserved8[2]; /* 0xa98 */
u32 _rxmgmask; /* 0xaa0 */
u32 _rxfgmask; /* 0xaa4 */
u32 _rx14mask; /* 0xaa8 */
u32 _rx15mask; /* 0xaac */
u32 tx_smb[4]; /* 0xab0 */
u32 rx_smb0[4]; /* 0xac0 */
u32 rx_smb1[4]; /* 0xad0 */
u32 mecr; /* 0xae0 */
u32 erriar; /* 0xae4 */
u32 erridpr; /* 0xae8 */
......@@ -305,9 +317,13 @@ struct flexcan_regs {
u32 fdctrl; /* 0xc00 - Not affected by Soft Reset */
u32 fdcbt; /* 0xc04 - Not affected by Soft Reset */
u32 fdcrc; /* 0xc08 */
u32 _reserved9[199]; /* 0xc0c */
u32 tx_smb_fd[18]; /* 0xf28 */
u32 rx_smb0_fd[18]; /* 0xf70 */
u32 rx_smb1_fd[18]; /* 0xfb8 */
};
static_assert(sizeof(struct flexcan_regs) == 0x4 + 0xc08);
static_assert(sizeof(struct flexcan_regs) == 0x4 * 18 + 0xfb8);
struct flexcan_devtype_data {
u32 quirks; /* quirks needed for different IP cores */
......@@ -376,6 +392,13 @@ static const struct flexcan_devtype_data fsl_imx8qm_devtype_data = {
FLEXCAN_QUIRK_SUPPORT_FD,
};
static struct flexcan_devtype_data fsl_imx8mp_devtype_data = {
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP |
FLEXCAN_QUIRK_BROKEN_PERR_STATE | FLEXCAN_QUIRK_SETUP_STOP_MODE |
FLEXCAN_QUIRK_SUPPORT_FD | FLEXCAN_QUIRK_SUPPORT_ECC,
};
static const struct flexcan_devtype_data fsl_vf610_devtype_data = {
.quirks = FLEXCAN_QUIRK_DISABLE_RXFG | FLEXCAN_QUIRK_ENABLE_EACEN_RRS |
FLEXCAN_QUIRK_DISABLE_MECR | FLEXCAN_QUIRK_USE_OFF_TIMESTAMP |
......@@ -1292,6 +1315,37 @@ static void flexcan_set_bittiming(struct net_device *dev)
return flexcan_set_bittiming_ctrl(dev);
}
static void flexcan_ram_init(struct net_device *dev)
{
struct flexcan_priv *priv = netdev_priv(dev);
struct flexcan_regs __iomem *regs = priv->regs;
u32 reg_ctrl2;
/* 11.8.3.13 Detection and correction of memory errors:
* CTRL2[WRMFRZ] grants write access to all memory positions
* that require initialization, ranging from 0x080 to 0xADF
* and from 0xF28 to 0xFFF when the CAN FD feature is enabled.
* The RXMGMASK, RX14MASK, RX15MASK, and RXFGMASK registers
* need to be initialized as well. MCR[RFEN] must not be set
* during memory initialization.
*/
reg_ctrl2 = priv->read(&regs->ctrl2);
reg_ctrl2 |= FLEXCAN_CTRL2_WRMFRZ;
priv->write(reg_ctrl2, &regs->ctrl2);
memset_io(&regs->mb[0][0], 0,
offsetof(struct flexcan_regs, rx_smb1[3]) -
offsetof(struct flexcan_regs, mb[0][0]) + 0x4);
if (priv->can.ctrlmode & CAN_CTRLMODE_FD)
memset_io(&regs->tx_smb_fd[0], 0,
offsetof(struct flexcan_regs, rx_smb1_fd[17]) -
offsetof(struct flexcan_regs, tx_smb_fd[0]) + 0x4);
reg_ctrl2 &= ~FLEXCAN_CTRL2_WRMFRZ;
priv->write(reg_ctrl2, &regs->ctrl2);
}
/* flexcan_chip_start
*
* this functions is entered with clocks enabled
......@@ -1316,6 +1370,9 @@ static int flexcan_chip_start(struct net_device *dev)
if (err)
goto out_chip_disable;
if (priv->devtype_data->quirks & FLEXCAN_QUIRK_SUPPORT_ECC)
flexcan_ram_init(dev);
flexcan_set_bittiming(dev);
/* MCR
......@@ -1845,6 +1902,7 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
static const struct of_device_id flexcan_of_match[] = {
{ .compatible = "fsl,imx8qm-flexcan", .data = &fsl_imx8qm_devtype_data, },
{ .compatible = "fsl,imx8mp-flexcan", .data = &fsl_imx8mp_devtype_data, },
{ .compatible = "fsl,imx6q-flexcan", .data = &fsl_imx6q_devtype_data, },
{ .compatible = "fsl,imx28-flexcan", .data = &fsl_imx28_devtype_data, },
{ .compatible = "fsl,imx53-flexcan", .data = &fsl_imx25_devtype_data, },
......@@ -1999,6 +2057,8 @@ static int flexcan_probe(struct platform_device *pdev)
return 0;
failed_register:
pm_runtime_put_noidle(&pdev->dev);
pm_runtime_disable(&pdev->dev);
free_candev(dev);
return err;
}
......
......@@ -13,6 +13,6 @@ config CAN_MCP251X
Driver for the Microchip MCP251x and MCP25625 SPI CAN
controllers.
source "drivers/net/can/spi/mcp25xxfd/Kconfig"
source "drivers/net/can/spi/mcp251xfd/Kconfig"
endmenu
......@@ -6,4 +6,4 @@
obj-$(CONFIG_CAN_HI311X) += hi311x.o
obj-$(CONFIG_CAN_MCP251X) += mcp251x.o
obj-y += mcp25xxfd/
obj-y += mcp251xfd/
# SPDX-License-Identifier: GPL-2.0-only
config CAN_MCP25XXFD
tristate "Microchip MCP25xxFD SPI CAN controllers"
config CAN_MCP251XFD
tristate "Microchip MCP251xFD SPI CAN controllers"
select REGMAP
help
Driver for the Microchip MCP25XXFD SPI FD-CAN controller
Driver for the Microchip MCP251XFD SPI FD-CAN controller
family.
config CAN_MCP25XXFD_SANITY
depends on CAN_MCP25XXFD
config CAN_MCP251XFD_SANITY
depends on CAN_MCP251XFD
bool "Additional Sanity Checks"
help
This option enables additional sanity checks in the driver,
......
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CAN_MCP251XFD) += mcp251xfd.o
mcp251xfd-objs :=
mcp251xfd-objs += mcp251xfd-core.o
mcp251xfd-objs += mcp251xfd-crc16.o
mcp251xfd-objs += mcp251xfd-regmap.o
// SPDX-License-Identifier: GPL-2.0
//
// mcp25xxfd - Microchip MCP25xxFD Family CAN controller driver
// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
//
// Copyright (c) 2020 Pengutronix,
// Marc Kleine-Budde <kernel@pengutronix.de>
......@@ -12,7 +12,7 @@
// Copyright (c) 2019 Martin Sperl <kernel@martin.sperl.org>
//
#include "mcp25xxfd.h"
#include "mcp251xfd.h"
/* The standard crc16 in linux/crc16.h is unfortunately not computing
* the correct results (left shift vs. right shift). So here an
......@@ -20,7 +20,7 @@
*
* http://lkml.iu.edu/hypermail/linux/kernel/0508.1/1085.html
*/
static const u16 mcp25xxfd_crc16_table[] = {
static const u16 mcp251xfd_crc16_table[] = {
0x0000, 0x8005, 0x800f, 0x000a, 0x801b, 0x001e, 0x0014, 0x8011,
0x8033, 0x0036, 0x003c, 0x8039, 0x0028, 0x802d, 0x8027, 0x0022,
0x8063, 0x0066, 0x006c, 0x8069, 0x0078, 0x807d, 0x8077, 0x0072,
......@@ -55,35 +55,35 @@ static const u16 mcp25xxfd_crc16_table[] = {
0x8213, 0x0216, 0x021c, 0x8219, 0x0208, 0x820d, 0x8207, 0x0202
};
static inline u16 mcp25xxfd_crc16_byte(u16 crc, const u8 data)
static inline u16 mcp251xfd_crc16_byte(u16 crc, const u8 data)
{
u8 index = (crc >> 8) ^ data;
return (crc << 8) ^ mcp25xxfd_crc16_table[index];
return (crc << 8) ^ mcp251xfd_crc16_table[index];
}
static u16 mcp25xxfd_crc16(u16 crc, u8 const *buffer, size_t len)
static u16 mcp251xfd_crc16(u16 crc, u8 const *buffer, size_t len)
{
while (len--)
crc = mcp25xxfd_crc16_byte(crc, *buffer++);
crc = mcp251xfd_crc16_byte(crc, *buffer++);
return crc;
}
u16 mcp25xxfd_crc16_compute(const void *data, size_t data_size)
u16 mcp251xfd_crc16_compute(const void *data, size_t data_size)
{
u16 crc = 0xffff;
return mcp25xxfd_crc16(crc, data, data_size);
return mcp251xfd_crc16(crc, data, data_size);
}
u16 mcp25xxfd_crc16_compute2(const void *cmd, size_t cmd_size,
u16 mcp251xfd_crc16_compute2(const void *cmd, size_t cmd_size,
const void *data, size_t data_size)
{
u16 crc;
crc = mcp25xxfd_crc16_compute(cmd, cmd_size);
crc = mcp25xxfd_crc16(crc, data, data_size);
crc = mcp251xfd_crc16_compute(cmd, cmd_size);
crc = mcp251xfd_crc16(crc, data, data_size);
return crc;
}
// SPDX-License-Identifier: GPL-2.0
//
// mcp25xxfd - Microchip MCP25xxFD Family CAN controller driver
// mcp251xfd - Microchip MCP251xFD Family CAN controller driver
//
// Copyright (c) 2019, 2020 Pengutronix,
// Marc Kleine-Budde <kernel@pengutronix.de>
//
#include "mcp25xxfd.h"
#include "mcp251xfd.h"
#include <asm/unaligned.h>
static const struct regmap_config mcp25xxfd_regmap_crc;
static const struct regmap_config mcp251xfd_regmap_crc;
static int
mcp25xxfd_regmap_nocrc_write(void *context, const void *data, size_t count)
mcp251xfd_regmap_nocrc_write(void *context, const void *data, size_t count)
{
struct spi_device *spi = context;
......@@ -21,13 +21,13 @@ mcp25xxfd_regmap_nocrc_write(void *context, const void *data, size_t count)
}
static int
mcp25xxfd_regmap_nocrc_gather_write(void *context,
mcp251xfd_regmap_nocrc_gather_write(void *context,
const void *reg, size_t reg_len,
const void *val, size_t val_len)
{
struct spi_device *spi = context;
struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
struct mcp25xxfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
struct spi_transfer xfer[] = {
{
.tx_buf = buf_tx,
......@@ -37,7 +37,7 @@ mcp25xxfd_regmap_nocrc_gather_write(void *context,
BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16));
if (IS_ENABLED(CONFIG_CAN_MCP25XXFD_SANITY) &&
if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
reg_len != sizeof(buf_tx->cmd.cmd))
return -EINVAL;
......@@ -47,20 +47,20 @@ mcp25xxfd_regmap_nocrc_gather_write(void *context,
return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
}
static inline bool mcp25xxfd_update_bits_read_reg(unsigned int reg)
static inline bool mcp251xfd_update_bits_read_reg(unsigned int reg)
{
switch (reg) {
case MCP25XXFD_REG_INT:
case MCP25XXFD_REG_TEFCON:
case MCP25XXFD_REG_FIFOCON(MCP25XXFD_RX_FIFO(0)):
case MCP25XXFD_REG_FLTCON(0):
case MCP25XXFD_REG_ECCSTAT:
case MCP25XXFD_REG_CRC:
case MCP251XFD_REG_INT:
case MCP251XFD_REG_TEFCON:
case MCP251XFD_REG_FIFOCON(MCP251XFD_RX_FIFO(0)):
case MCP251XFD_REG_FLTCON(0):
case MCP251XFD_REG_ECCSTAT:
case MCP251XFD_REG_CRC:
return false;
case MCP25XXFD_REG_CON:
case MCP25XXFD_REG_FIFOSTA(MCP25XXFD_RX_FIFO(0)):
case MCP25XXFD_REG_OSC:
case MCP25XXFD_REG_ECCCON:
case MCP251XFD_REG_CON:
case MCP251XFD_REG_FIFOSTA(MCP251XFD_RX_FIFO(0)):
case MCP251XFD_REG_OSC:
case MCP251XFD_REG_ECCCON:
return true;
default:
WARN(1, "Status of reg 0x%04x unknown.\n", reg);
......@@ -70,13 +70,13 @@ static inline bool mcp25xxfd_update_bits_read_reg(unsigned int reg)
}
static int
mcp25xxfd_regmap_nocrc_update_bits(void *context, unsigned int reg,
mcp251xfd_regmap_nocrc_update_bits(void *context, unsigned int reg,
unsigned int mask, unsigned int val)
{
struct spi_device *spi = context;
struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
struct mcp25xxfd_map_buf_nocrc *buf_rx = priv->map_buf_nocrc_rx;
struct mcp25xxfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
struct mcp251xfd_map_buf_nocrc *buf_rx = priv->map_buf_nocrc_rx;
struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
__le32 orig_le32 = 0, mask_le32, val_le32, tmp_le32;
u8 first_byte, last_byte, len;
int err;
......@@ -84,22 +84,22 @@ mcp25xxfd_regmap_nocrc_update_bits(void *context, unsigned int reg,
BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16));
BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16));
if (IS_ENABLED(CONFIG_CAN_MCP25XXFD_SANITY) &&
if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
mask == 0)
return -EINVAL;
first_byte = mcp25xxfd_first_byte_set(mask);
last_byte = mcp25xxfd_last_byte_set(mask);
first_byte = mcp251xfd_first_byte_set(mask);
last_byte = mcp251xfd_last_byte_set(mask);
len = last_byte - first_byte + 1;
if (mcp25xxfd_update_bits_read_reg(reg)) {
if (mcp251xfd_update_bits_read_reg(reg)) {
struct spi_transfer xfer[2] = { };
struct spi_message msg;
spi_message_init(&msg);
spi_message_add_tail(&xfer[0], &msg);
if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_HALF_DUPLEX) {
if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) {
xfer[0].tx_buf = buf_tx;
xfer[0].len = sizeof(buf_tx->cmd);
......@@ -111,11 +111,11 @@ mcp25xxfd_regmap_nocrc_update_bits(void *context, unsigned int reg,
xfer[0].rx_buf = buf_rx;
xfer[0].len = sizeof(buf_tx->cmd) + len;
if (MCP25XXFD_SANITIZE_SPI)
if (MCP251XFD_SANITIZE_SPI)
memset(buf_tx->data, 0x0, len);
}
mcp25xxfd_spi_cmd_read_nocrc(&buf_tx->cmd, reg + first_byte);
mcp251xfd_spi_cmd_read_nocrc(&buf_tx->cmd, reg + first_byte);
err = spi_sync(spi, &msg);
if (err)
return err;
......@@ -129,21 +129,21 @@ mcp25xxfd_regmap_nocrc_update_bits(void *context, unsigned int reg,
tmp_le32 = orig_le32 & ~mask_le32;
tmp_le32 |= val_le32 & mask_le32;
mcp25xxfd_spi_cmd_write_nocrc(&buf_tx->cmd, reg + first_byte);
mcp251xfd_spi_cmd_write_nocrc(&buf_tx->cmd, reg + first_byte);
memcpy(buf_tx->data, &tmp_le32, len);
return spi_write(spi, buf_tx, sizeof(buf_tx->cmd) + len);
}
static int
mcp25xxfd_regmap_nocrc_read(void *context,
mcp251xfd_regmap_nocrc_read(void *context,
const void *reg, size_t reg_len,
void *val_buf, size_t val_len)
{
struct spi_device *spi = context;
struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
struct mcp25xxfd_map_buf_nocrc *buf_rx = priv->map_buf_nocrc_rx;
struct mcp25xxfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
struct mcp251xfd_map_buf_nocrc *buf_rx = priv->map_buf_nocrc_rx;
struct mcp251xfd_map_buf_nocrc *buf_tx = priv->map_buf_nocrc_tx;
struct spi_transfer xfer[2] = { };
struct spi_message msg;
int err;
......@@ -151,14 +151,14 @@ mcp25xxfd_regmap_nocrc_read(void *context,
BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16));
BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16));
if (IS_ENABLED(CONFIG_CAN_MCP25XXFD_SANITY) &&
if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
reg_len != sizeof(buf_tx->cmd.cmd))
return -EINVAL;
spi_message_init(&msg);
spi_message_add_tail(&xfer[0], &msg);
if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_HALF_DUPLEX) {
if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) {
xfer[0].tx_buf = reg;
xfer[0].len = sizeof(buf_tx->cmd);
......@@ -171,7 +171,7 @@ mcp25xxfd_regmap_nocrc_read(void *context,
xfer[0].len = sizeof(buf_tx->cmd) + val_len;
memcpy(&buf_tx->cmd, reg, sizeof(buf_tx->cmd));
if (MCP25XXFD_SANITIZE_SPI)
if (MCP251XFD_SANITIZE_SPI)
memset(buf_tx->data, 0x0, val_len);
};
......@@ -179,20 +179,20 @@ mcp25xxfd_regmap_nocrc_read(void *context,
if (err)
return err;
if (!(priv->devtype_data.quirks & MCP25XXFD_QUIRK_HALF_DUPLEX))
if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX))
memcpy(val_buf, buf_rx->data, val_len);
return 0;
}
static int
mcp25xxfd_regmap_crc_gather_write(void *context,
mcp251xfd_regmap_crc_gather_write(void *context,
const void *reg_p, size_t reg_len,
const void *val, size_t val_len)
{
struct spi_device *spi = context;
struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
struct mcp25xxfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
struct mcp251xfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx;
struct spi_transfer xfer[] = {
{
.tx_buf = buf_tx,
......@@ -205,39 +205,39 @@ mcp25xxfd_regmap_crc_gather_write(void *context,
BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16) + sizeof(u8));
if (IS_ENABLED(CONFIG_CAN_MCP25XXFD_SANITY) &&
if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
reg_len != sizeof(buf_tx->cmd.cmd) +
mcp25xxfd_regmap_crc.pad_bits / BITS_PER_BYTE)
mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE)
return -EINVAL;
mcp25xxfd_spi_cmd_write_crc(&buf_tx->cmd, reg, val_len);
mcp251xfd_spi_cmd_write_crc(&buf_tx->cmd, reg, val_len);
memcpy(buf_tx->data, val, val_len);
crc = mcp25xxfd_crc16_compute(buf_tx, sizeof(buf_tx->cmd) + val_len);
crc = mcp251xfd_crc16_compute(buf_tx, sizeof(buf_tx->cmd) + val_len);
put_unaligned_be16(crc, buf_tx->data + val_len);
return spi_sync_transfer(spi, xfer, ARRAY_SIZE(xfer));
}
static int
mcp25xxfd_regmap_crc_write(void *context,
mcp251xfd_regmap_crc_write(void *context,
const void *data, size_t count)
{
const size_t data_offset = sizeof(__be16) +
mcp25xxfd_regmap_crc.pad_bits / BITS_PER_BYTE;
mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE;
return mcp25xxfd_regmap_crc_gather_write(context,
return mcp251xfd_regmap_crc_gather_write(context,
data, data_offset,
data + data_offset,
count - data_offset);
}
static int
mcp25xxfd_regmap_crc_read_one(struct mcp25xxfd_priv *priv,
mcp251xfd_regmap_crc_read_one(struct mcp251xfd_priv *priv,
struct spi_message *msg, unsigned int data_len)
{
const struct mcp25xxfd_map_buf_crc *buf_rx = priv->map_buf_crc_rx;
const struct mcp25xxfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx;
const struct mcp251xfd_map_buf_crc *buf_rx = priv->map_buf_crc_rx;
const struct mcp251xfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx;
u16 crc_received, crc_calculated;
int err;
......@@ -249,7 +249,7 @@ mcp25xxfd_regmap_crc_read_one(struct mcp25xxfd_priv *priv,
return err;
crc_received = get_unaligned_be16(buf_rx->data + data_len);
crc_calculated = mcp25xxfd_crc16_compute2(&buf_tx->cmd,
crc_calculated = mcp251xfd_crc16_compute2(&buf_tx->cmd,
sizeof(buf_tx->cmd),
buf_rx->data,
data_len);
......@@ -260,14 +260,14 @@ mcp25xxfd_regmap_crc_read_one(struct mcp25xxfd_priv *priv,
}
static int
mcp25xxfd_regmap_crc_read(void *context,
mcp251xfd_regmap_crc_read(void *context,
const void *reg_p, size_t reg_len,
void *val_buf, size_t val_len)
{
struct spi_device *spi = context;
struct mcp25xxfd_priv *priv = spi_get_drvdata(spi);
struct mcp25xxfd_map_buf_crc *buf_rx = priv->map_buf_crc_rx;
struct mcp25xxfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx;
struct mcp251xfd_priv *priv = spi_get_drvdata(spi);
struct mcp251xfd_map_buf_crc *buf_rx = priv->map_buf_crc_rx;
struct mcp251xfd_map_buf_crc *buf_tx = priv->map_buf_crc_tx;
struct spi_transfer xfer[2] = { };
struct spi_message msg;
u16 reg = *(u16 *)reg_p;
......@@ -276,15 +276,15 @@ mcp25xxfd_regmap_crc_read(void *context,
BUILD_BUG_ON(sizeof(buf_rx->cmd) != sizeof(__be16) + sizeof(u8));
BUILD_BUG_ON(sizeof(buf_tx->cmd) != sizeof(__be16) + sizeof(u8));
if (IS_ENABLED(CONFIG_CAN_MCP25XXFD_SANITY) &&
if (IS_ENABLED(CONFIG_CAN_MCP251XFD_SANITY) &&
reg_len != sizeof(buf_tx->cmd.cmd) +
mcp25xxfd_regmap_crc.pad_bits / BITS_PER_BYTE)
mcp251xfd_regmap_crc.pad_bits / BITS_PER_BYTE)
return -EINVAL;
spi_message_init(&msg);
spi_message_add_tail(&xfer[0], &msg);
if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_HALF_DUPLEX) {
if (priv->devtype_data.quirks & MCP251XFD_QUIRK_HALF_DUPLEX) {
xfer[0].tx_buf = buf_tx;
xfer[0].len = sizeof(buf_tx->cmd);
......@@ -297,21 +297,21 @@ mcp25xxfd_regmap_crc_read(void *context,
xfer[0].len = sizeof(buf_tx->cmd) + val_len +
sizeof(buf_tx->crc);
if (MCP25XXFD_SANITIZE_SPI)
if (MCP251XFD_SANITIZE_SPI)
memset(buf_tx->data, 0x0, val_len +
sizeof(buf_tx->crc));
}
mcp25xxfd_spi_cmd_read_crc(&buf_tx->cmd, reg, val_len);
mcp251xfd_spi_cmd_read_crc(&buf_tx->cmd, reg, val_len);
for (i = 0; i < MCP25XXFD_READ_CRC_RETRIES_MAX; i++) {
err = mcp25xxfd_regmap_crc_read_one(priv, &msg, val_len);
for (i = 0; i < MCP251XFD_READ_CRC_RETRIES_MAX; i++) {
err = mcp251xfd_regmap_crc_read_one(priv, &msg, val_len);
if (!err)
goto out;
if (err != -EBADMSG)
return err;
/* MCP25XXFD_REG_OSC is the first ever reg we read from.
/* MCP251XFD_REG_OSC is the first ever reg we read from.
*
* The chip may be in deep sleep and this SPI transfer
* (i.e. the assertion of the CS) will wake the chip
......@@ -325,7 +325,7 @@ mcp25xxfd_regmap_crc_read(void *context,
* to the caller. It will take care of both cases.
*
*/
if (reg == MCP25XXFD_REG_OSC) {
if (reg == MCP251XFD_REG_OSC) {
err = 0;
goto out;
}
......@@ -350,88 +350,88 @@ mcp25xxfd_regmap_crc_read(void *context,
return 0;
}
static const struct regmap_range mcp25xxfd_reg_table_yes_range[] = {
static const struct regmap_range mcp251xfd_reg_table_yes_range[] = {
regmap_reg_range(0x000, 0x2ec), /* CAN FD Controller Module SFR */
regmap_reg_range(0x400, 0xbfc), /* RAM */
regmap_reg_range(0xe00, 0xe14), /* MCP2517/18FD SFR */
};
static const struct regmap_access_table mcp25xxfd_reg_table = {
.yes_ranges = mcp25xxfd_reg_table_yes_range,
.n_yes_ranges = ARRAY_SIZE(mcp25xxfd_reg_table_yes_range),
static const struct regmap_access_table mcp251xfd_reg_table = {
.yes_ranges = mcp251xfd_reg_table_yes_range,
.n_yes_ranges = ARRAY_SIZE(mcp251xfd_reg_table_yes_range),
};
static const struct regmap_config mcp25xxfd_regmap_nocrc = {
static const struct regmap_config mcp251xfd_regmap_nocrc = {
.name = "nocrc",
.reg_bits = 16,
.reg_stride = 4,
.pad_bits = 0,
.val_bits = 32,
.max_register = 0xffc,
.wr_table = &mcp25xxfd_reg_table,
.rd_table = &mcp25xxfd_reg_table,
.wr_table = &mcp251xfd_reg_table,
.rd_table = &mcp251xfd_reg_table,
.cache_type = REGCACHE_NONE,
.read_flag_mask = (__force unsigned long)
cpu_to_be16(MCP25XXFD_SPI_INSTRUCTION_READ),
cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_READ),
.write_flag_mask = (__force unsigned long)
cpu_to_be16(MCP25XXFD_SPI_INSTRUCTION_WRITE),
cpu_to_be16(MCP251XFD_SPI_INSTRUCTION_WRITE),
};
static const struct regmap_bus mcp25xxfd_bus_nocrc = {
.write = mcp25xxfd_regmap_nocrc_write,
.gather_write = mcp25xxfd_regmap_nocrc_gather_write,
.reg_update_bits = mcp25xxfd_regmap_nocrc_update_bits,
.read = mcp25xxfd_regmap_nocrc_read,
static const struct regmap_bus mcp251xfd_bus_nocrc = {
.write = mcp251xfd_regmap_nocrc_write,
.gather_write = mcp251xfd_regmap_nocrc_gather_write,
.reg_update_bits = mcp251xfd_regmap_nocrc_update_bits,
.read = mcp251xfd_regmap_nocrc_read,
.reg_format_endian_default = REGMAP_ENDIAN_BIG,
.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
.max_raw_read = sizeof_field(struct mcp25xxfd_map_buf_nocrc, data),
.max_raw_write = sizeof_field(struct mcp25xxfd_map_buf_nocrc, data),
.max_raw_read = sizeof_field(struct mcp251xfd_map_buf_nocrc, data),
.max_raw_write = sizeof_field(struct mcp251xfd_map_buf_nocrc, data),
};
static const struct regmap_config mcp25xxfd_regmap_crc = {
static const struct regmap_config mcp251xfd_regmap_crc = {
.name = "crc",
.reg_bits = 16,
.reg_stride = 4,
.pad_bits = 16, /* keep data bits aligned */
.val_bits = 32,
.max_register = 0xffc,
.wr_table = &mcp25xxfd_reg_table,
.rd_table = &mcp25xxfd_reg_table,
.wr_table = &mcp251xfd_reg_table,
.rd_table = &mcp251xfd_reg_table,
.cache_type = REGCACHE_NONE,
};
static const struct regmap_bus mcp25xxfd_bus_crc = {
.write = mcp25xxfd_regmap_crc_write,
.gather_write = mcp25xxfd_regmap_crc_gather_write,
.read = mcp25xxfd_regmap_crc_read,
static const struct regmap_bus mcp251xfd_bus_crc = {
.write = mcp251xfd_regmap_crc_write,
.gather_write = mcp251xfd_regmap_crc_gather_write,
.read = mcp251xfd_regmap_crc_read,
.reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
.val_format_endian_default = REGMAP_ENDIAN_LITTLE,
.max_raw_read = sizeof_field(struct mcp25xxfd_map_buf_crc, data),
.max_raw_write = sizeof_field(struct mcp25xxfd_map_buf_crc, data),
.max_raw_read = sizeof_field(struct mcp251xfd_map_buf_crc, data),
.max_raw_write = sizeof_field(struct mcp251xfd_map_buf_crc, data),
};
static inline bool
mcp25xxfd_regmap_use_nocrc(struct mcp25xxfd_priv *priv)
mcp251xfd_regmap_use_nocrc(struct mcp251xfd_priv *priv)
{
return (!(priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_REG)) ||
(!(priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_RX));
return (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)) ||
(!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX));
}
static inline bool
mcp25xxfd_regmap_use_crc(struct mcp25xxfd_priv *priv)
mcp251xfd_regmap_use_crc(struct mcp251xfd_priv *priv)
{
return (priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_REG) ||
(priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_RX);
return (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG) ||
(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX);
}
static int
mcp25xxfd_regmap_init_nocrc(struct mcp25xxfd_priv *priv)
mcp251xfd_regmap_init_nocrc(struct mcp251xfd_priv *priv)
{
if (!priv->map_nocrc) {
struct regmap *map;
map = devm_regmap_init(&priv->spi->dev, &mcp25xxfd_bus_nocrc,
priv->spi, &mcp25xxfd_regmap_nocrc);
map = devm_regmap_init(&priv->spi->dev, &mcp251xfd_bus_nocrc,
priv->spi, &mcp251xfd_regmap_nocrc);
if (IS_ERR(map))
return PTR_ERR(map);
......@@ -456,16 +456,16 @@ mcp25xxfd_regmap_init_nocrc(struct mcp25xxfd_priv *priv)
return -ENOMEM;
}
if (!(priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_REG))
if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG))
priv->map_reg = priv->map_nocrc;
if (!(priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_RX))
if (!(priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX))
priv->map_rx = priv->map_nocrc;
return 0;
}
static void mcp25xxfd_regmap_destroy_nocrc(struct mcp25xxfd_priv *priv)
static void mcp251xfd_regmap_destroy_nocrc(struct mcp251xfd_priv *priv)
{
if (priv->map_buf_nocrc_rx) {
devm_kfree(&priv->spi->dev, priv->map_buf_nocrc_rx);
......@@ -478,13 +478,13 @@ static void mcp25xxfd_regmap_destroy_nocrc(struct mcp25xxfd_priv *priv)
}
static int
mcp25xxfd_regmap_init_crc(struct mcp25xxfd_priv *priv)
mcp251xfd_regmap_init_crc(struct mcp251xfd_priv *priv)
{
if (!priv->map_crc) {
struct regmap *map;
map = devm_regmap_init(&priv->spi->dev, &mcp25xxfd_bus_crc,
priv->spi, &mcp25xxfd_regmap_crc);
map = devm_regmap_init(&priv->spi->dev, &mcp251xfd_bus_crc,
priv->spi, &mcp251xfd_regmap_crc);
if (IS_ERR(map))
return PTR_ERR(map);
......@@ -509,16 +509,16 @@ mcp25xxfd_regmap_init_crc(struct mcp25xxfd_priv *priv)
return -ENOMEM;
}
if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_REG)
if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_REG)
priv->map_reg = priv->map_crc;
if (priv->devtype_data.quirks & MCP25XXFD_QUIRK_CRC_RX)
if (priv->devtype_data.quirks & MCP251XFD_QUIRK_CRC_RX)
priv->map_rx = priv->map_crc;
return 0;
}
static void mcp25xxfd_regmap_destroy_crc(struct mcp25xxfd_priv *priv)
static void mcp251xfd_regmap_destroy_crc(struct mcp251xfd_priv *priv)
{
if (priv->map_buf_crc_rx) {
devm_kfree(&priv->spi->dev, priv->map_buf_crc_rx);
......@@ -530,26 +530,26 @@ static void mcp25xxfd_regmap_destroy_crc(struct mcp25xxfd_priv *priv)
}
}
int mcp25xxfd_regmap_init(struct mcp25xxfd_priv *priv)
int mcp251xfd_regmap_init(struct mcp251xfd_priv *priv)
{
int err;
if (mcp25xxfd_regmap_use_nocrc(priv)) {
err = mcp25xxfd_regmap_init_nocrc(priv);
if (mcp251xfd_regmap_use_nocrc(priv)) {
err = mcp251xfd_regmap_init_nocrc(priv);
if (err)
return err;
} else {
mcp25xxfd_regmap_destroy_nocrc(priv);
mcp251xfd_regmap_destroy_nocrc(priv);
}
if (mcp25xxfd_regmap_use_crc(priv)) {
err = mcp25xxfd_regmap_init_crc(priv);
if (mcp251xfd_regmap_use_crc(priv)) {
err = mcp251xfd_regmap_init_crc(priv);
if (err)
return err;
} else {
mcp25xxfd_regmap_destroy_crc(priv);
mcp251xfd_regmap_destroy_crc(priv);
}
return 0;
......
此差异已折叠。
# SPDX-License-Identifier: GPL-2.0-only
obj-$(CONFIG_CAN_MCP25XXFD) += mcp25xxfd.o
mcp25xxfd-objs :=
mcp25xxfd-objs += mcp25xxfd-core.o
mcp25xxfd-objs += mcp25xxfd-crc16.o
mcp25xxfd-objs += mcp25xxfd-regmap.o
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册