Files
linux-nv-oot/drivers/net/can/mttcan/hal/m_ttcan_tt.c
Manish Bhardwaj 0e0d2f2c07 nvidia-oot: add support for mttcan driver
Using this patch we are adding support for
mttcan driver in oot kernel.

JIRA ESLC-6885

Signed-off-by: Manish Bhardwaj <mbhardwaj@nvidia.com>
Change-Id: I83a6d43aa99278a546778cf1700e2bd106ec42a9
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/2785360
Reviewed-by: Bitan Biswas <bbiswas@nvidia.com>
GVS: Gerrit_Virtual_Submit <buildbot_gerritrpt@nvidia.com>
2022-10-03 21:31:05 -07:00

202 lines
5.1 KiB
C

/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2022, NVIDIA CORPORATION & AFFILIATES. All rights reserved.
*/
#include "../include/m_ttcan.h"
/* TT Reference Message Config */
#define TTRMC_REF_PAYLOAD (0x1 << 31)
#define TTRMC_EXT_ID (0x1 << 30)
#define TTRMC_STD_ID_SHIFT 0x12
/* TT Operation Config */
#define TTOCF_MODE_0 0x3
#define TTOCF_MODE_1 0x2
#define TTCOF_MODE_2 0x1
#define TTOCF_EVT_TRIG 0x0
#define TTOCF_GAP 0x4
#define TTOCF_POTENTIAL_TM 0x8
#define TTOCF_LDSDL_SHIFT 0x5
#define TTOCF_IRTO_SHIFT 0x8
#define TTOCF_EXT_CLK_SYNC 0x8000
#define TTOCF_AWL_SHIFT 0x10
#define TTOCF_GBL_TIME_FLT (0x1 << 24)
#define TTOCF_CLK_CALIB (0x1 << 25)
#define TTOCF_EVT_POLARITY (0x1 << 26)
enum time_master_info {
TM_MASTER = 0,
TM_POTENTIAL,
TM_SLAVE,
};
inline void ttcan_clean_tt_intr(struct ttcan_controller *ttcan)
{
ttcan_write32(ttcan, ADR_MTTCAN_TTIR, 0xFFFFFFFF);
}
void ttcan_set_ref_mesg(struct ttcan_controller *ttcan,
u32 id, u32 rmps, u32 xtd)
{
u32 rid;
u32 ttrmc = (xtd << MTT_TTRMC_XTD_SHIFT) &
MTT_TTRMC_XTD_MASK;
ttrmc |= (rmps << MTT_TTRMC_RMPS_SHIFT) &
MTT_TTRMC_RMPS_MASK;
if (xtd)
rid = (id & 0x1FFFFFFF);
else
rid = ((id & 0x7FF) << TTRMC_STD_ID_SHIFT);
ttrmc |= (rid << MTT_TTRMC_RID_SHIFT) & MTT_TTRMC_RID_MASK;
ttcan_write32(ttcan, ADR_MTTCAN_TTRMC, ttrmc);
}
void ttcan_set_tt_config(struct ttcan_controller *ttcan, u32 evtp,
u32 ecc, u32 egtf, u32 awl, u32 eecs,
u32 irto, u32 ldsdl, u32 tm, u32 gen, u32 om)
{
u32 ttocf = 0;
ttocf = (evtp << MTT_TTOCF_EVTP_SHIFT) & MTT_TTOCF_EVTP_MASK;
ttocf |= (ecc << MTT_TTOCF_ECC_SHIFT) & MTT_TTOCF_ECC_MASK;
ttocf |= (egtf << MTT_TTOCF_EGTF_SHIFT) & MTT_TTOCF_EGTF_MASK;
ttocf |= (awl << MTT_TTOCF_AWL_SHIFT) & MTT_TTOCF_AWL_MASK;
ttocf |= (eecs << MTT_TTOCF_EECS_SHIFT) & MTT_TTOCF_EECS_MASK;
ttocf |= (irto << MTT_TTOCF_IRTO_SHIFT) & MTT_TTOCF_IRTO_MASK;
ttocf |= (ldsdl << MTT_TTOCF_LDSDL_SHIFT) &
MTT_TTOCF_LDSDL_MASK;
ttocf |= (tm << MTT_TTOCF_TM_SHIFT) & MTT_TTOCF_TM_MASK;
ttocf |= (gen << MTT_TTOCF_GEN_SHIFT) & MTT_TTOCF_GEN_MASK;
ttocf |= (om << MTT_TTOCF_OM_SHIFT) & MTT_TTOCF_OM_MASK;
ttcan_write32(ttcan, ADR_MTTCAN_TTOCF, ttocf);
}
inline u32 ttcan_get_ttocf(struct ttcan_controller *ttcan)
{
return ttcan_read32(ttcan, ADR_MTTCAN_TTOCF);
}
inline void ttcan_set_tttmc(struct ttcan_controller *ttcan, u32 value)
{
ttcan_write32(ttcan, ADR_MTTCAN_TTTMC, value);
}
inline u32 ttcan_get_tttmc(struct ttcan_controller *ttcan)
{
return ttcan_read32(ttcan, ADR_MTTCAN_TTTMC);
}
inline void ttcan_set_txbar(struct ttcan_controller *ttcan, u32 value)
{
ttcan_write32(ttcan, ADR_MTTCAN_TXBAR, value);
}
inline u32 ttcan_get_ttmlm(struct ttcan_controller *ttcan)
{
return ttcan_read32(ttcan, ADR_MTTCAN_TTMLM);
}
inline u32 ttcan_get_cccr(struct ttcan_controller *ttcan)
{
return ttcan_read32(ttcan, ADR_MTTCAN_CCCR);
}
inline u32 ttcan_get_ttost(struct ttcan_controller *ttcan)
{
return ttcan_read32(ttcan, ADR_MTTCAN_TTOST);
}
static bool validate_matrix_cyc_cnt(u32 cyc_num)
{
if (cyc_num && ((cyc_num + 1) & cyc_num))
return false;
return true;
}
int ttcan_set_matrix_limits(struct ttcan_controller *ttcan,
u32 entt, u32 txew, u32 css, u32 ccm)
{
u32 ttmlm = 0;
if (!validate_matrix_cyc_cnt(ccm) ||
(txew > 15) || (css > 2) || (entt > 4095)) {
pr_err("%s: Invalid parameters\n", __func__);
return -1;
}
ttmlm = (entt << MTT_TTMLM_ENTT_SHIFT) & MTT_TTMLM_ENTT_MASK;
ttmlm |= (txew << MTT_TTMLM_TXEW_SHIFT) & MTT_TTMLM_TXEW_MASK;
ttmlm |= (css << MTT_TTMLM_CSS_SHIFT) & MTT_TTMLM_CSS_MASK;
ttmlm |= (ccm << MTT_TTMLM_CCM_SHIFT) & MTT_TTMLM_CCM_MASK;
ttcan_write32(ttcan, ADR_MTTCAN_TTMLM, ttmlm);
return 0;
}
#define MTTCAN_TT_TIMEOUT 1000
int ttcan_set_tur_config(struct ttcan_controller *ttcan, u16 denominator,
u16 numerator, int local_timing_enable)
{
int timeout = MTTCAN_TT_TIMEOUT;
u32 turcf = ttcan_read32(ttcan, ADR_MTTCAN_TURCF);
if (!denominator && local_timing_enable) {
pr_err("%s: Invalid Denominator value\n", __func__);
return -1;
}
if (turcf & MTT_TURCF_ELT_MASK) {
turcf &= ~(MTT_TURCF_ELT_MASK);
ttcan_write32(ttcan, ADR_MTTCAN_TURCF, turcf);
}
if (!local_timing_enable)
return 0;
if (turcf & MTT_TURCF_ELT_MASK) {
while ((turcf & MTT_TURCF_ELT_MASK) && timeout) {
udelay(1);
timeout--;
turcf = ttcan_read32(ttcan, ADR_MTTCAN_TURCF);
}
if (!timeout) {
pr_err("%s: TURCF access is locked\n", __func__);
return -1;
}
}
/* TBD: Take care when the DEN or NUM is programmed
* outside TT Conf mode
*/
turcf = (numerator << MTT_TURCF_NCL_SHIFT) & MTT_TURCF_NCL_MASK;
turcf |= (denominator << MTT_TURCF_DC_SHIFT) & MTT_TURCF_DC_MASK;
turcf |= MTT_TURCF_ELT_MASK;
ttcan_write32(ttcan, ADR_MTTCAN_TURCF, turcf);
return 0;
}
void ttcan_set_trigger_mem_conf(struct ttcan_controller *ttcan)
{
u32 tttmc = 0;
u32 rel_start_addr = ttcan->mram_cfg[MRAM_TMC].off >> 2;
u8 elem_num = ttcan->mram_cfg[MRAM_TMC].num;
if (elem_num > 64)
elem_num = 64;
tttmc = (elem_num << MTT_TTTMC_TME_SHIFT) & MTT_TTTMC_TME_MASK;
tttmc |= (rel_start_addr << MTT_TTTMC_TMSA_SHIFT) &
MTT_TTTMC_TMSA_MASK;
ttcan_write32(ttcan, ADR_MTTCAN_TTTMC, tttmc);
}