Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 69927fcc authored by AnilKumar Ch's avatar AnilKumar Ch Committed by Marc Kleine-Budde
Browse files

can: c_can: Add support for Bosch D_CAN controller

This patch adds the support for D_CAN controller driver to the existing
C_CAN driver.

Bosch D_CAN controller is a full-CAN implementation which is compliant
to CAN protocol version 2.0 part A and B. Bosch D_CAN user manual can be
obtained from: http://www.semiconductors.bosch.de/media/en/pdf/


ipmodules_1/can/d_can_users_manual_111.pdf

A new array is added for accessing the d_can registers, according to d_can
controller register space.

Current D_CAN implementation has following limitations, this is done
to avoid large changes to the C_CAN driver.
1. Message objects are limited to 32, 16 for RX and 16 for TX. C_CAN IP
   supports upto 32 message objects but in case of D_CAN we can configure
   upto 128 message objects.
2. Using two 16bit reads/writes for accessing the 32bit D_CAN registers.
3. These patches have been tested on little endian machine, there might
   be some hidden endian-related issues due to the nature of the accesses
   (32-bit registers accessed as 2 16-bit registers). However, I do not
   have a big-endian D_CAN implementation to confirm.

Signed-off-by: default avatarAnilKumar Ch <anilkumar@ti.com>
Signed-off-by: default avatarMarc Kleine-Budde <mkl@pengutronix.de>
parent 33f81009
Loading
Loading
Loading
Loading
+7 −6
Original line number Original line Diff line number Diff line
menuconfig CAN_C_CAN
menuconfig CAN_C_CAN
	tristate "Bosch C_CAN devices"
	tristate "Bosch C_CAN/D_CAN devices"
	depends on CAN_DEV && HAS_IOMEM
	depends on CAN_DEV && HAS_IOMEM


if CAN_C_CAN
if CAN_C_CAN


config CAN_C_CAN_PLATFORM
config CAN_C_CAN_PLATFORM
	tristate "Generic Platform Bus based C_CAN driver"
	tristate "Generic Platform Bus based C_CAN/D_CAN driver"
	---help---
	---help---
	  This driver adds support for the C_CAN chips connected to
	  This driver adds support for the C_CAN/D_CAN chips connected
	  the "platform bus" (Linux abstraction for directly to the
	  to the "platform bus" (Linux abstraction for directly to the
	  processor attached devices) which can be found on various
	  processor attached devices) which can be found on various
	  boards from ST Microelectronics (http://www.st.com)
	  boards from ST Microelectronics (http://www.st.com) like the
	  like the SPEAr1310 and SPEAr320 evaluation boards.
	  SPEAr1310 and SPEAr320 evaluation boards & TI (www.ti.com)
	  boards like am335x, dm814x, dm813x and dm811x.
endif
endif
+45 −0
Original line number Original line Diff line number Diff line
@@ -102,6 +102,51 @@ static const u16 reg_map_c_can[] = {
	[C_CAN_MSGVAL2_REG]	= 0xB2,
	[C_CAN_MSGVAL2_REG]	= 0xB2,
};
};


static const u16 reg_map_d_can[] = {
	[C_CAN_CTRL_REG]	= 0x00,
	[C_CAN_STS_REG]		= 0x04,
	[C_CAN_ERR_CNT_REG]	= 0x08,
	[C_CAN_BTR_REG]		= 0x0C,
	[C_CAN_BRPEXT_REG]	= 0x0E,
	[C_CAN_INT_REG]		= 0x10,
	[C_CAN_TEST_REG]	= 0x14,
	[C_CAN_TXRQST1_REG]	= 0x88,
	[C_CAN_TXRQST2_REG]	= 0x8A,
	[C_CAN_NEWDAT1_REG]	= 0x9C,
	[C_CAN_NEWDAT2_REG]	= 0x9E,
	[C_CAN_INTPND1_REG]	= 0xB0,
	[C_CAN_INTPND2_REG]	= 0xB2,
	[C_CAN_MSGVAL1_REG]	= 0xC4,
	[C_CAN_MSGVAL2_REG]	= 0xC6,
	[C_CAN_IF1_COMREQ_REG]	= 0x100,
	[C_CAN_IF1_COMMSK_REG]	= 0x102,
	[C_CAN_IF1_MASK1_REG]	= 0x104,
	[C_CAN_IF1_MASK2_REG]	= 0x106,
	[C_CAN_IF1_ARB1_REG]	= 0x108,
	[C_CAN_IF1_ARB2_REG]	= 0x10A,
	[C_CAN_IF1_MSGCTRL_REG]	= 0x10C,
	[C_CAN_IF1_DATA1_REG]	= 0x110,
	[C_CAN_IF1_DATA2_REG]	= 0x112,
	[C_CAN_IF1_DATA3_REG]	= 0x114,
	[C_CAN_IF1_DATA4_REG]	= 0x116,
	[C_CAN_IF2_COMREQ_REG]	= 0x120,
	[C_CAN_IF2_COMMSK_REG]	= 0x122,
	[C_CAN_IF2_MASK1_REG]	= 0x124,
	[C_CAN_IF2_MASK2_REG]	= 0x126,
	[C_CAN_IF2_ARB1_REG]	= 0x128,
	[C_CAN_IF2_ARB2_REG]	= 0x12A,
	[C_CAN_IF2_MSGCTRL_REG]	= 0x12C,
	[C_CAN_IF2_DATA1_REG]	= 0x130,
	[C_CAN_IF2_DATA2_REG]	= 0x132,
	[C_CAN_IF2_DATA3_REG]	= 0x134,
	[C_CAN_IF2_DATA4_REG]	= 0x136,
};

enum c_can_dev_id {
	C_CAN_DEVTYPE,
	D_CAN_DEVTYPE,
};

/* c_can private data structure */
/* c_can private data structure */
struct c_can_priv {
struct c_can_priv {
	struct can_priv can;	/* must be the first member */
	struct can_priv can;	/* must be the first member */
+42 −13
Original line number Original line Diff line number Diff line
@@ -71,6 +71,7 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
	void __iomem *addr;
	void __iomem *addr;
	struct net_device *dev;
	struct net_device *dev;
	struct c_can_priv *priv;
	struct c_can_priv *priv;
	const struct platform_device_id *id;
	struct resource *mem;
	struct resource *mem;
	int irq;
	int irq;
#ifdef CONFIG_HAVE_CLK
#ifdef CONFIG_HAVE_CLK
@@ -115,15 +116,10 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
	}
	}


	priv = netdev_priv(dev);
	priv = netdev_priv(dev);
	id = platform_get_device_id(pdev);
	switch (id->driver_data) {
	case C_CAN_DEVTYPE:
		priv->regs = reg_map_c_can;
		priv->regs = reg_map_c_can;

	dev->irq = irq;
	priv->base = addr;
#ifdef CONFIG_HAVE_CLK
	priv->can.clock.freq = clk_get_rate(clk);
	priv->priv = clk;
#endif

		switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
		switch (mem->flags & IORESOURCE_MEM_TYPE_MASK) {
		case IORESOURCE_MEM_32BIT:
		case IORESOURCE_MEM_32BIT:
			priv->read_reg = c_can_plat_read_reg_aligned_to_32bit;
			priv->read_reg = c_can_plat_read_reg_aligned_to_32bit;
@@ -135,6 +131,24 @@ static int __devinit c_can_plat_probe(struct platform_device *pdev)
			priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
			priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
			break;
			break;
		}
		}
		break;
	case D_CAN_DEVTYPE:
		priv->regs = reg_map_d_can;
		priv->can.ctrlmode_supported |= CAN_CTRLMODE_3_SAMPLES;
		priv->read_reg = c_can_plat_read_reg_aligned_to_16bit;
		priv->write_reg = c_can_plat_write_reg_aligned_to_16bit;
		break;
	default:
		ret = -EINVAL;
		goto exit_free_device;
	}

	dev->irq = irq;
	priv->base = addr;
#ifdef CONFIG_HAVE_CLK
	priv->can.clock.freq = clk_get_rate(clk);
	priv->priv = clk;
#endif


	platform_set_drvdata(pdev, dev);
	platform_set_drvdata(pdev, dev);
	SET_NETDEV_DEV(dev, &pdev->dev);
	SET_NETDEV_DEV(dev, &pdev->dev);
@@ -189,6 +203,20 @@ static int __devexit c_can_plat_remove(struct platform_device *pdev)
	return 0;
	return 0;
}
}


static const struct platform_device_id c_can_id_table[] = {
	{
		.name = KBUILD_MODNAME,
		.driver_data = C_CAN_DEVTYPE,
	}, {
		.name = "c_can",
		.driver_data = C_CAN_DEVTYPE,
	}, {
		.name = "d_can",
		.driver_data = D_CAN_DEVTYPE,
	}, {
	}
};

static struct platform_driver c_can_plat_driver = {
static struct platform_driver c_can_plat_driver = {
	.driver = {
	.driver = {
		.name = KBUILD_MODNAME,
		.name = KBUILD_MODNAME,
@@ -196,6 +224,7 @@ static struct platform_driver c_can_plat_driver = {
	},
	},
	.probe = c_can_plat_probe,
	.probe = c_can_plat_probe,
	.remove = __devexit_p(c_can_plat_remove),
	.remove = __devexit_p(c_can_plat_remove),
	.id_table = c_can_id_table,
};
};


module_platform_driver(c_can_plat_driver);
module_platform_driver(c_can_plat_driver);