Re: [PATCH V7 RESEND 04/10] can: mcp25xxfd: Add Microchip mcp25xxfd CAN FD driver

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On 4/19/19 7:14 AM, kernel@xxxxxxxxxxxxxxxx wrote:
> From: Martin Sperl <kernel@xxxxxxxxxxxxxxxx>
> 
> Add un-optimized Can2.0 and CanFD support.
> 
> CAN-Transmission and Optimizations and are separate patches
> 
> On a Rasperry pi 3 it is already able to process Can2.0 Frames
> with DLC=0 on a CAN bus with 1MHz. without losing any packets
> on the SPI side. Packets still get lost inside the network stack.
> 
> Signed-off-by: Martin Sperl <kernel@xxxxxxxxxxxxxxxx>

[..]

> diff --git a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.c b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.c
> index f98b02ff057b..eabd7ca50645 100644
> --- a/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.c
> +++ b/drivers/net/can/spi/mcp25xxfd/mcp25xxfd_can.c
> @@ -38,23 +38,162 @@
>   * for timestamping of RX frames as well as for TEF entries.
>   */
> 
> -/* Implementation notes:
> - *
> - * Right now we only use the CAN controller block to put us into deep sleep
> - * this means that the oscillator clock is turned off.
> - * So this is the only thing that we implement here right now
> - */
> -
> +#include <linux/can/core.h>
> +#include <linux/can/dev.h>
>  #include <linux/device.h>
> +#include <linux/interrupt.h>
>  #include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/regulator/consumer.h>
>  #include <linux/spi/spi.h>
> 
> +#include "mcp25xxfd_base.h"
> +#include "mcp25xxfd_can_debugfs.h"
> +#include "mcp25xxfd_can_fifo.h"
> +#include "mcp25xxfd_can_int.h"
> +#include "mcp25xxfd_can_priv.h"
>  #include "mcp25xxfd_clock.h"
>  #include "mcp25xxfd_cmd.h"
> +#include "mcp25xxfd_int.h"
>  #include "mcp25xxfd_priv.h"
>  #include "mcp25xxfd_regs.h"
> 
> -static int mcp25xxfd_can_get_mode(struct mcp25xxfd_priv *priv, u32 *reg)
> +#include <uapi/linux/can/netlink.h>
> +
> +/* module parameters */
> +unsigned int bw_sharing_log2bits;
> +module_param(bw_sharing_log2bits, uint, 0664);
> +MODULE_PARM_DESC(bw_sharing_log2bits,
> +		 "Delay between 2 transmissions in number of arbitration bit times\n");
> +bool enable_edge_filter;
> +module_param(enable_edge_filter, bool, 0664);
> +MODULE_PARM_DESC(enable_edge_filter,
> +		 "Enable ISO11898-1:2015 edge_filtering");
> +unsigned int tdc_mode = 2;
> +module_param(tdc_mode, uint, 0664);
> +MODULE_PARM_DESC(tdc_mode,
> +		 "Transmitter Delay Mode - 0 = disabled, 1 = fixed, 2 = auto\n");
> +unsigned int tdc_value;
> +module_param(tdc_value, uint, 0664);
> +MODULE_PARM_DESC(tdc_value,
> +		 "Transmission Delay Value - range: [0:63] SCLK");
> +int tdc_offset = 64; /* outside of range to use computed values */
> +module_param(tdc_offset, int, 0664);
> +MODULE_PARM_DESC(tdc_offset,
> +		 "Transmission Delay offset - range: [-64:63] SCLK");
> +
> +/* everything related to bit timing */
> +static
> +const struct can_bittiming_const mcp25xxfd_can_nominal_bittiming_const = {
> +	.name           = DEVICE_NAME,
> +	.tseg1_min      = 2,
> +	.tseg1_max      = BIT(MCP25XXFD_CAN_NBTCFG_TSEG1_BITS),
> +	.tseg2_min      = 1,
> +	.tseg2_max      = BIT(MCP25XXFD_CAN_NBTCFG_TSEG2_BITS),
> +	.sjw_max        = BIT(MCP25XXFD_CAN_NBTCFG_SJW_BITS),
> +	.brp_min        = 1,
> +	.brp_max        = BIT(MCP25XXFD_CAN_NBTCFG_BRP_BITS),
> +	.brp_inc        = 1,
> +};
> +
> +static
> +const struct can_bittiming_const mcp25xxfd_can_data_bittiming_const = {
> +	.name           = DEVICE_NAME,
> +	.tseg1_min      = 1,
> +	.tseg1_max      = BIT(MCP25XXFD_CAN_DBTCFG_TSEG1_BITS),
> +	.tseg2_min      = 1,
> +	.tseg2_max      = BIT(MCP25XXFD_CAN_DBTCFG_TSEG2_BITS),
> +	.sjw_max        = BIT(MCP25XXFD_CAN_DBTCFG_SJW_BITS),
> +	.brp_min        = 1,
> +	.brp_max        = BIT(MCP25XXFD_CAN_DBTCFG_BRP_BITS),
> +	.brp_inc        = 1,
> +};
> +
> +static int mcp25xxfd_can_do_set_nominal_bittiming(struct net_device *net)
> +{
> +	struct mcp25xxfd_can_priv *cpriv = netdev_priv(net);
> +	struct can_bittiming *bt = &cpriv->can.bittiming;
> +
> +	int sjw = bt->sjw;
> +	int pseg2 = bt->phase_seg2;
> +	int pseg1 = bt->phase_seg1;
> +	int propseg = bt->prop_seg;
> +	int brp = bt->brp;
> +
> +	int tseg1 = propseg + pseg1;
> +	int tseg2 = pseg2;
> +
> +	/* calculate nominal bit timing */
> +	cpriv->regs.nbtcfg = ((sjw - 1) << MCP25XXFD_CAN_NBTCFG_SJW_SHIFT) |
> +		((tseg2 - 1) << MCP25XXFD_CAN_NBTCFG_TSEG2_SHIFT) |
> +		((tseg1 - 1) << MCP25XXFD_CAN_NBTCFG_TSEG1_SHIFT) |
> +		((brp - 1) << MCP25XXFD_CAN_NBTCFG_BRP_SHIFT);
> +
> +	return mcp25xxfd_cmd_write(cpriv->priv->spi, MCP25XXFD_CAN_NBTCFG,
> +				   cpriv->regs.nbtcfg);
> +}
> +
> +static int mcp25xxfd_can_do_set_data_bittiming(struct net_device *net)
> +{
> +	struct mcp25xxfd_can_priv *cpriv = netdev_priv(net);
> +	struct mcp25xxfd_priv *priv = cpriv->priv;
> +	struct can_bittiming *bt = &cpriv->can.data_bittiming;
> +	struct spi_device *spi = priv->spi;
> +
> +	int sjw = bt->sjw;
> +	int pseg2 = bt->phase_seg2;
> +	int pseg1 = bt->phase_seg1;
> +	int propseg = bt->prop_seg;
> +	int brp = bt->brp;
> +
> +	int tseg1 = propseg + pseg1;
> +	int tseg2 = pseg2;
> +
> +	int tdco;
> +	int ret;
> +
> +	/* set up Transmitter delay compensation */
> +	cpriv->regs.tdc = 0;
> +	/* configure TDC mode */
> +	if (tdc_mode < 4)
> +		cpriv->regs.tdc = tdc_mode << MCP25XXFD_CAN_TDC_TDCMOD_SHIFT;
> +	else
> +		cpriv->regs.tdc = MCP25XXFD_CAN_TDC_TDCMOD_AUTO <<
> +			MCP25XXFD_CAN_TDC_TDCMOD_SHIFT;
> +
> +	/* configure TDC offsets */
> +	if ((tdc_offset >= -64) && tdc_offset < 64)
> +		tdco = tdc_offset;
> +	else
> +		tdco = clamp_t(int, bt->brp * tseg1, -64, 63);
> +	cpriv->regs.tdc |= (tdco << MCP25XXFD_CAN_TDC_TDCO_SHIFT) &
> +		MCP25XXFD_CAN_TDC_TDCO_MASK;
> +
> +	/* configure TDC value */
> +	if (tdc_value < 64)
> +		cpriv->regs.tdc |= tdc_value << MCP25XXFD_CAN_TDC_TDCV_SHIFT;
> +
> +	/* enable edge filtering */
> +	if (enable_edge_filter)
> +		cpriv->regs.tdc |= MCP25XXFD_CAN_TDC_EDGFLTEN;
> +
> +	/* set TDC */
> +	ret = mcp25xxfd_cmd_write(spi, MCP25XXFD_CAN_TDC, cpriv->regs.tdc);
> +	if (ret)
> +		return ret;
> +
> +	/* calculate data bit timing */
> +	cpriv->regs.dbtcfg = ((sjw - 1) << MCP25XXFD_CAN_DBTCFG_SJW_SHIFT) |
> +		((tseg2 - 1) << MCP25XXFD_CAN_DBTCFG_TSEG2_SHIFT) |
> +		((tseg1 - 1) << MCP25XXFD_CAN_DBTCFG_TSEG1_SHIFT) |
> +		((brp - 1) << MCP25XXFD_CAN_DBTCFG_BRP_SHIFT);
> +
> +	return mcp25xxfd_cmd_write(spi, MCP25XXFD_CAN_DBTCFG,
> +				   cpriv->regs.dbtcfg);
> +}
> +
> +int mcp25xxfd_can_get_mode(struct mcp25xxfd_priv *priv, u32 *reg)
>  {
>  	int ret;
> 
> @@ -66,11 +205,11 @@ static int mcp25xxfd_can_get_mode(struct mcp25xxfd_priv *priv, u32 *reg)
>  		MCP25XXFD_CAN_CON_OPMOD_SHIFT;
>  }
> 
> -static int mcp25xxfd_can_switch_mode(struct mcp25xxfd_priv *priv,
> -				     u32 *reg, int mode)
> +int mcp25xxfd_can_switch_mode_no_wait(struct mcp25xxfd_priv *priv,
> +				      u32 *reg, int mode)
>  {
>  	u32 dummy;
> -	int ret, i;
> +	int ret;
> 
>  	/* get the current mode/register - if reg is NULL
>  	 * when the can controller is not setup yet
> @@ -78,9 +217,11 @@ static int mcp25xxfd_can_switch_mode(struct mcp25xxfd_priv *priv,
>  	 * (this only happens during initialization phase)
>  	 */
>  	if (reg) {
> -		ret = mcp25xxfd_can_get_mode(priv, reg);
> -		if (ret < 0)
> -			return ret;
> +		if (!reg) {
> +			ret = mcp25xxfd_can_get_mode(priv, reg);
> +			if (ret < 0)
> +				return ret;
> +		}

After this patch the function reads:

> static int mcp25xxfd_can_switch_mode_no_wait(struct mcp25xxfd_priv *priv,
> 					     u32 *reg, int mode)
> {
> 	u32 dummy;
> 	int ret;
> 
> 	/* get the current mode/register - if reg is NULL
> 	 * when the can controller is not setup yet
> 	 * typically by calling mcp25xxfd_can_sleep_mode
> 	 * (this only happens during initialization phase)
> 	 */
> 	if (reg) {
> 		if (!reg) {

This looks wrong.

> 			ret = mcp25xxfd_can_get_mode(priv, reg);
> 			if (ret < 0)
> 				return ret;
> 		}
> 	} else {
> 		/* alternatively use dummy */
> 		dummy = 0;
> 		reg = &dummy;
> 	}
> 

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |

Attachment: signature.asc
Description: OpenPGP digital signature


[Index of Archives]     [Automotive Discussions]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]     [CAN Bus]

  Powered by Linux