mttcan: tegra: Add new prod setting support

Add new prod setting support which is the
property based on device tree. The prod
setting of each register field are new property
in DT and prod configurations are configured
via these new properties.

Bug 4097475

Change-Id: I86adc7b72a28802d73fee8a085db2bccf0d6d1cc
Signed-off-by: Laxman Dewangan <ldewangan@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2996771
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Laxman Dewangan
2023-10-13 08:11:59 +00:00
committed by mobile promotions
parent 1e8bd7b606
commit 9a65689ba2
5 changed files with 75 additions and 27 deletions

View File

@@ -9,10 +9,8 @@
#define MTTCAN_INIT_TIMEOUT 1000 #define MTTCAN_INIT_TIMEOUT 1000
#if KERNEL_VERSION(5, 16, 0) >= LINUX_VERSION_CODE
#define MTTCAN_SPEED_5MBPS 5000000 #define MTTCAN_SPEED_5MBPS 5000000
#define MTTCAN_SPEED_8MBPS 8333333 #define MTTCAN_SPEED_8MBPS 8333333
#endif
void ttcan_print_version(struct ttcan_controller *ttcan) void ttcan_print_version(struct ttcan_controller *ttcan)
{ {
@@ -293,7 +291,7 @@ inline u32 ttcan_read_ecr(struct ttcan_controller *ttcan)
return ttcan_read32(ttcan, ADR_MTTCAN_ECR); return ttcan_read32(ttcan, ADR_MTTCAN_ECR);
} }
#if KERNEL_VERSION(5, 16, 0) >= LINUX_VERSION_CODE #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
static void tegra_mttcan_config_prod_settings(struct mttcan_priv *priv) static void tegra_mttcan_config_prod_settings(struct mttcan_priv *priv)
{ {
struct ttcan_controller *ttcan = priv->ttcan; struct ttcan_controller *ttcan = priv->ttcan;
@@ -317,6 +315,47 @@ static void tegra_mttcan_config_prod_settings(struct mttcan_priv *priv)
if (ret == 0) if (ret == 0)
dev_dbg(priv->device, "setting prod: %s\n", prod_name); dev_dbg(priv->device, "setting prod: %s\n", prod_name);
} }
#else
static void tegra_mttcan_write_prod_settings(struct mttcan_priv *priv, const char *prod_name)
{
struct ttcan_controller *ttcan = priv->ttcan;
struct tegra_prod_reg_info *reg_info;
struct tegra_prod_cfg_info *prod_cfg;
u32 rval;
int i;
prod_cfg = tegra_prod_get_by_name_from_list(priv->device, ttcan->prod_list, prod_name);
if (prod_cfg == NULL)
return;
reg_info = prod_cfg->reg_info;
for (i = 0; i < prod_cfg->num_reg_info; ++i) {
rval = ttcan_read32(ttcan, reg_info[i].reg_offset);
rval &= ~reg_info[i].reg_mask;
rval |= reg_info[i].reg_value;
ttcan_write32(ttcan, reg_info[i].reg_offset, rval);
}
}
static void tegra_mttcan_config_prod_settings(struct mttcan_priv *priv)
{
struct ttcan_controller *ttcan = priv->ttcan;
char *prod_name;
switch (ttcan->bt_config.data.bitrate) {
case MTTCAN_SPEED_5MBPS:
prod_name = "prod_c_can_5m";
break;
case MTTCAN_SPEED_8MBPS:
prod_name = "prod_c_can_8m";
break;
default:
prod_name = "prod_c_can_2m_1m";
break;
}
tegra_mttcan_write_prod_settings(priv, prod_name);
}
#endif #endif
int ttcan_set_bitrate(struct mttcan_priv *priv) int ttcan_set_bitrate(struct mttcan_priv *priv)
@@ -327,9 +366,6 @@ int ttcan_set_bitrate(struct mttcan_priv *priv)
u32 cccr_reg; u32 cccr_reg;
u32 nbtp_reg; u32 nbtp_reg;
u32 dbtp_reg; u32 dbtp_reg;
#if KERNEL_VERSION(5, 16, 0) < LINUX_VERSION_CODE
u32 tdcr_reg;
#endif
nbtp_reg = ((ttcan->bt_config.nominal.phase_seg2 - 1) << nbtp_reg = ((ttcan->bt_config.nominal.phase_seg2 - 1) <<
MTT_NBTP_NTSEG2_SHIFT) & MTT_NBTP_NTSEG2_MASK; MTT_NBTP_NTSEG2_SHIFT) & MTT_NBTP_NTSEG2_MASK;
@@ -366,12 +402,6 @@ int ttcan_set_bitrate(struct mttcan_priv *priv)
dbtp_reg |= (ttcan->bt_config.data.tdc << MTT_DBTP_TDC_SHIFT) & dbtp_reg |= (ttcan->bt_config.data.tdc << MTT_DBTP_TDC_SHIFT) &
MTT_DBTP_TDC_MASK; MTT_DBTP_TDC_MASK;
#if KERNEL_VERSION(5, 16, 0) < LINUX_VERSION_CODE
tdcr_reg = (ttcan->bt_config.data.tdc_offset <<
MTT_TDCR_TDCO_SHIFT) & MTT_TDCR_TDCO_MASK;
tdcr_reg |= ttcan->tdc_offset;
#endif
dev_dbg(priv->device, "%s DBTP(0x%x) value (0x%x)\n", __func__, dev_dbg(priv->device, "%s DBTP(0x%x) value (0x%x)\n", __func__,
ADR_MTTCAN_DBTP, dbtp_reg); ADR_MTTCAN_DBTP, dbtp_reg);
ret = ttcan_write32_check(ttcan, ADR_MTTCAN_DBTP, ret = ttcan_write32_check(ttcan, ADR_MTTCAN_DBTP,
@@ -381,18 +411,8 @@ int ttcan_set_bitrate(struct mttcan_priv *priv)
return ret; return ret;
} }
#if KERNEL_VERSION(5, 16, 0) >= LINUX_VERSION_CODE
if (ttcan->prod_list) if (ttcan->prod_list)
tegra_mttcan_config_prod_settings(priv); tegra_mttcan_config_prod_settings(priv);
#else
ret = ttcan_write32_check(ttcan, ADR_MTTCAN_TDCR,
tdcr_reg, MTTCAN_TDCR_MSK);
if (ret) {
dev_err(priv->device, "%s: Fast bitrate configuration failed\n",
__func__);
return ret;
}
#endif
temp_reg = cccr_reg = ttcan_read32(ttcan, ADR_MTTCAN_CCCR); temp_reg = cccr_reg = ttcan_read32(ttcan, ADR_MTTCAN_CCCR);
if (ttcan->bt_config.fd_flags & CAN_FD_FLAG) if (ttcan->bt_config.fd_flags & CAN_FD_FLAG)

View File

@@ -287,8 +287,10 @@ struct ttcan_controller {
struct list_head rx_q1; struct list_head rx_q1;
struct list_head rx_b; struct list_head rx_b;
struct list_head tx_evt; struct list_head tx_evt;
#if KERNEL_VERSION(5, 16, 0) >= LINUX_VERSION_CODE #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
struct tegra_prod *prod_list; struct tegra_prod *prod_list;
#else
struct tegra_prod_cfg_list *prod_list;
#endif #endif
void __iomem *base; /* controller regs space should be remapped. */ void __iomem *base; /* controller regs space should be remapped. */
void __iomem *xbase; /* extra registers are mapped */ void __iomem *xbase; /* extra registers are mapped */

View File

@@ -31,9 +31,7 @@
#include <linux/net_tstamp.h> #include <linux/net_tstamp.h>
#include <linux/spinlock.h> #include <linux/spinlock.h>
#include <linux/clocksource.h> #include <linux/clocksource.h>
#if KERNEL_VERSION(5, 16, 0) >= LINUX_VERSION_CODE
#include <linux/tegra-oot-prod.h> #include <linux/tegra-oot-prod.h>
#endif
#include <linux/platform/tegra/ptp-notifier.h> #include <linux/platform/tegra/ptp-notifier.h>
#include <linux/mailbox_client.h> #include <linux/mailbox_client.h>
#ifdef CONFIG_CLK_SRC_TEGRA18_US_TIMER #ifdef CONFIG_CLK_SRC_TEGRA18_US_TIMER

View File

@@ -14,6 +14,8 @@
#define ADR_MTTCAN_DBTP 0x00C #define ADR_MTTCAN_DBTP 0x00C
#define DEF_MTTCAN_DBTP 0x00000A33 #define DEF_MTTCAN_DBTP 0x00000A33
#define MTTCAN_DBTP_MSK 0x009F1FFF #define MTTCAN_DBTP_MSK 0x009F1FFF
#define MTTCAN_CORE_DBTP_TDC_FIELD_START 23
#define MTTCAN_CORE_DBTP_TDC_FIELD_WIDTH 1
#define ADR_MTTCAN_TEST 0x010 #define ADR_MTTCAN_TEST 0x010
#define DEF_MTTCAN_TEST 0x00000080 #define DEF_MTTCAN_TEST 0x00000080
@@ -51,6 +53,8 @@
#define ADR_MTTCAN_TDCR 0x048 #define ADR_MTTCAN_TDCR 0x048
#define DEF_MTTCAN_TDCR 0x00000000 #define DEF_MTTCAN_TDCR 0x00000000
#define MTTCAN_TDCR_MSK 0x00007F7F #define MTTCAN_TDCR_MSK 0x00007F7F
#define MTTCAN_CORE_TDCR_TDCO_FIELD_START 8
#define MTTCAN_CORE_TDCR_TDCO_FIELD_WIDTH 7
#define ADR_MTTCAN_IR 0x050 #define ADR_MTTCAN_IR 0x050
#define DEF_MTTCAN_IR 0x00000000 #define DEF_MTTCAN_IR 0x00000000

View File

@@ -12,6 +12,28 @@
#define CAN_MSG_FLUSH_TIMEOUT 100 #define CAN_MSG_FLUSH_TIMEOUT 100
static void mttcan_start(struct net_device *dev); static void mttcan_start(struct net_device *dev);
#if LINUX_VERSION_CODE > KERNEL_VERSION(5, 16, 0)
#define MTTCAN_PROD_FIELD(name, rindex, roffset, fname) \
{ \
.field_name = name, \
.reg_index = rindex, \
.reg_offset = roffset, \
.field_start = fname##_FIELD_START, \
.field_len = fname##_FIELD_WIDTH, \
}
static const struct tegra_prod_dev_reg_field mttcan_prod_dev_reg_field[] = {
MTTCAN_PROD_FIELD("nvidia,can-enable-tdc-dbtp", 0, ADR_MTTCAN_DBTP, MTTCAN_CORE_DBTP_TDC),
MTTCAN_PROD_FIELD("nvidia,can-tdco-value-tdcr", 0, ADR_MTTCAN_TDCR, MTTCAN_CORE_TDCR_TDCO),
};
static const struct tegra_prod_dev_info mttcan_prod_dev_info = {
.num_total_dev_reg = 2,
.num_dev_reg_field = ARRAY_SIZE(mttcan_prod_dev_reg_field),
.dev_reg_field = mttcan_prod_dev_reg_field,
};
#endif
/* We are reading cntvct_el0 for TSC time. We are not issuing ISB /* We are reading cntvct_el0 for TSC time. We are not issuing ISB
* before reading the counter as by the time CAN irq comes and * before reading the counter as by the time CAN irq comes and
* CAN softirq is executed, we would have lot of instruction executed. * CAN softirq is executed, we would have lot of instruction executed.
@@ -1855,13 +1877,15 @@ static int mttcan_probe(struct platform_device *pdev)
if (ret) if (ret)
goto exit_free_device; goto exit_free_device;
#if KERNEL_VERSION(5, 16, 0) >= LINUX_VERSION_CODE #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 16, 0)
priv->ttcan->prod_list = devm_tegra_prod_get(&pdev->dev); priv->ttcan->prod_list = devm_tegra_prod_get(&pdev->dev);
#else
priv->ttcan->prod_list = devm_tegra_prod_get_list(&pdev->dev, &mttcan_prod_dev_info);
#endif
if (IS_ERR_OR_NULL(priv->ttcan->prod_list)) { if (IS_ERR_OR_NULL(priv->ttcan->prod_list)) {
dev_dbg(&pdev->dev, "Prod-setting not available\n"); dev_dbg(&pdev->dev, "Prod-setting not available\n");
priv->ttcan->prod_list = NULL; priv->ttcan->prod_list = NULL;
} }
#endif
ret = register_mttcan_dev(dev); ret = register_mttcan_dev(dev);
if (ret) { if (ret) {