Commit 61fd4d43 authored by Sean Nyekjaer's avatar Sean Nyekjaer Committed by Kleber Sacilotto de Souza

can: mcp251x: add support for mcp25625

BugLink: https://bugs.launchpad.net/bugs/1838467

[ Upstream commit 35b7fa4d ]

Fully compatible with mcp2515, the mcp25625 have integrated transceiver.

This patch adds support for the mcp25625 to the existing mcp251x driver.
Signed-off-by: default avatarSean Nyekjaer <sean@geanix.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
Signed-off-by: default avatarSasha Levin <sashal@kernel.org>
Signed-off-by: default avatarConnor Kuehl <connor.kuehl@canonical.com>
Signed-off-by: default avatarKhalid Elmously <khalid.elmously@canonical.com>
parent 8e6d6e07
...@@ -2,9 +2,10 @@ menu "CAN SPI interfaces" ...@@ -2,9 +2,10 @@ menu "CAN SPI interfaces"
depends on SPI depends on SPI
config CAN_MCP251X config CAN_MCP251X
tristate "Microchip MCP251x SPI CAN controllers" tristate "Microchip MCP251x and MCP25625 SPI CAN controllers"
depends on HAS_DMA depends on HAS_DMA
---help--- ---help---
Driver for the Microchip MCP251x SPI CAN controllers. Driver for the Microchip MCP251x and MCP25625 SPI CAN
controllers.
endmenu endmenu
/* /*
* CAN bus driver for Microchip 251x CAN Controller with SPI Interface * CAN bus driver for Microchip 251x/25625 CAN Controller with SPI Interface
* *
* MCP2510 support and bug fixes by Christian Pellegrin * MCP2510 support and bug fixes by Christian Pellegrin
* <chripell@evolware.org> * <chripell@evolware.org>
...@@ -41,7 +41,7 @@ ...@@ -41,7 +41,7 @@
* static struct spi_board_info spi_board_info[] = { * static struct spi_board_info spi_board_info[] = {
* { * {
* .modalias = "mcp2510", * .modalias = "mcp2510",
* // or "mcp2515" depending on your controller * // "mcp2515" or "mcp25625" depending on your controller
* .platform_data = &mcp251x_info, * .platform_data = &mcp251x_info,
* .irq = IRQ_EINT13, * .irq = IRQ_EINT13,
* .max_speed_hz = 2*1000*1000, * .max_speed_hz = 2*1000*1000,
...@@ -238,6 +238,7 @@ static const struct can_bittiming_const mcp251x_bittiming_const = { ...@@ -238,6 +238,7 @@ static const struct can_bittiming_const mcp251x_bittiming_const = {
enum mcp251x_model { enum mcp251x_model {
CAN_MCP251X_MCP2510 = 0x2510, CAN_MCP251X_MCP2510 = 0x2510,
CAN_MCP251X_MCP2515 = 0x2515, CAN_MCP251X_MCP2515 = 0x2515,
CAN_MCP251X_MCP25625 = 0x25625,
}; };
struct mcp251x_priv { struct mcp251x_priv {
...@@ -280,7 +281,6 @@ static inline int mcp251x_is_##_model(struct spi_device *spi) \ ...@@ -280,7 +281,6 @@ static inline int mcp251x_is_##_model(struct spi_device *spi) \
} }
MCP251X_IS(2510); MCP251X_IS(2510);
MCP251X_IS(2515);
static void mcp251x_clean(struct net_device *net) static void mcp251x_clean(struct net_device *net)
{ {
...@@ -640,7 +640,7 @@ static int mcp251x_hw_reset(struct spi_device *spi) ...@@ -640,7 +640,7 @@ static int mcp251x_hw_reset(struct spi_device *spi)
/* Wait for oscillator startup timer after reset */ /* Wait for oscillator startup timer after reset */
mdelay(MCP251X_OST_DELAY_MS); mdelay(MCP251X_OST_DELAY_MS);
reg = mcp251x_read_reg(spi, CANSTAT); reg = mcp251x_read_reg(spi, CANSTAT);
if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF) if ((reg & CANCTRL_REQOP_MASK) != CANCTRL_REQOP_CONF)
return -ENODEV; return -ENODEV;
...@@ -821,9 +821,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) ...@@ -821,9 +821,8 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
/* receive buffer 0 */ /* receive buffer 0 */
if (intf & CANINTF_RX0IF) { if (intf & CANINTF_RX0IF) {
mcp251x_hw_rx(spi, 0); mcp251x_hw_rx(spi, 0);
/* /* Free one buffer ASAP
* Free one buffer ASAP * (The MCP2515/25625 does this automatically.)
* (The MCP2515 does this automatically.)
*/ */
if (mcp251x_is_2510(spi)) if (mcp251x_is_2510(spi))
mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00); mcp251x_write_bits(spi, CANINTF, CANINTF_RX0IF, 0x00);
...@@ -832,7 +831,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id) ...@@ -832,7 +831,7 @@ static irqreturn_t mcp251x_can_ist(int irq, void *dev_id)
/* receive buffer 1 */ /* receive buffer 1 */
if (intf & CANINTF_RX1IF) { if (intf & CANINTF_RX1IF) {
mcp251x_hw_rx(spi, 1); mcp251x_hw_rx(spi, 1);
/* the MCP2515 does this automatically */ /* The MCP2515/25625 does this automatically. */
if (mcp251x_is_2510(spi)) if (mcp251x_is_2510(spi))
clear_intf |= CANINTF_RX1IF; clear_intf |= CANINTF_RX1IF;
} }
...@@ -1006,6 +1005,10 @@ static const struct of_device_id mcp251x_of_match[] = { ...@@ -1006,6 +1005,10 @@ static const struct of_device_id mcp251x_of_match[] = {
.compatible = "microchip,mcp2515", .compatible = "microchip,mcp2515",
.data = (void *)CAN_MCP251X_MCP2515, .data = (void *)CAN_MCP251X_MCP2515,
}, },
{
.compatible = "microchip,mcp25625",
.data = (void *)CAN_MCP251X_MCP25625,
},
{ } { }
}; };
MODULE_DEVICE_TABLE(of, mcp251x_of_match); MODULE_DEVICE_TABLE(of, mcp251x_of_match);
...@@ -1019,6 +1022,10 @@ static const struct spi_device_id mcp251x_id_table[] = { ...@@ -1019,6 +1022,10 @@ static const struct spi_device_id mcp251x_id_table[] = {
.name = "mcp2515", .name = "mcp2515",
.driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515, .driver_data = (kernel_ulong_t)CAN_MCP251X_MCP2515,
}, },
{
.name = "mcp25625",
.driver_data = (kernel_ulong_t)CAN_MCP251X_MCP25625,
},
{ } { }
}; };
MODULE_DEVICE_TABLE(spi, mcp251x_id_table); MODULE_DEVICE_TABLE(spi, mcp251x_id_table);
...@@ -1254,5 +1261,5 @@ module_spi_driver(mcp251x_can_driver); ...@@ -1254,5 +1261,5 @@ module_spi_driver(mcp251x_can_driver);
MODULE_AUTHOR("Chris Elston <celston@katalix.com>, " MODULE_AUTHOR("Chris Elston <celston@katalix.com>, "
"Christian Pellegrin <chripell@evolware.org>"); "Christian Pellegrin <chripell@evolware.org>");
MODULE_DESCRIPTION("Microchip 251x CAN driver"); MODULE_DESCRIPTION("Microchip 251x/25625 CAN driver");
MODULE_LICENSE("GPL v2"); MODULE_LICENSE("GPL v2");
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