motor-control-sdk/source/position_sense/endat/driver/endat_drv.c
Naresh A 206f344bd1 am64x/am243x/am263x : remove motor_control folder from the repository
remove motor_control folder from the repository

Fixes: PINDSW-5635

Signed-off-by: Naresh A <nareshk@ti.com>
2023-07-13 15:23:20 +05:30

2061 lines
72 KiB
C

/*
* Copyright (C) 2021-23 Texas Instruments Incorporated
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the
* distribution.
*
* Neither the name of Texas Instruments Incorporated nor the names of
* its contributors may be used to endorse or promote products derived
* from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPgResS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
* OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <position_sense/endat/include/endat_drv.h>
#include <kernel/dpl/ClockP.h>
#include <drivers/hw_include/tistdtypes.h>
#include <drivers/hw_include/hw_types.h>
static struct endat_priv endat_priv;
/*
* check 2.2 command case with 2.2 capability in encoder, can live w/o as endat_get_command
* will handle and it is assumed that functions,
* endat_recvd_organize()
* endat_recvd_format()
* endat_recvd_validate()
* endat_recvd_print()
* will normally be called after endat_get_command
*/
static int32_t endat_recvd_organize(int32_t cmd, struct endat_priv *priv,
struct endat_data *endat_data)
{
uint32_t word0, word1, word2, word3;
uint32_t pos_bits, shift;
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
memset(endat_data, 0, sizeof(*endat_data));
word0 = pruss_xchg->ch[priv->channel].pos_word0;
word1 = pruss_xchg->ch[priv->channel].pos_word1;
word2 = pruss_xchg->ch[priv->channel].pos_word2;
word3 = pruss_xchg->ch[priv->channel].pos_word3;
switch(cmd)
{
case 2:
case 3:
case 4:
case 5:
case 7:
case 14:
endat_data->recvd1 = word0;
break;
case 6:
shift = ENDAT_RX_46BITS % (sizeof(unsigned) * 8);
endat_data->recvd1 = (uint64_t) word0 << shift | word1;
break;
case 1:
pos_bits = priv->pos_res + ENDAT_NUM_BITS_POSITION_CRC + ENDAT_NUM_BITS_F1;
if(pos_bits <= sizeof(unsigned) * 8)
{
endat_data->recvd1 = word0;
}
else
{
shift = pos_bits % (sizeof(unsigned) * 8);
endat_data->recvd1 = (uint64_t) word0 << shift | word1;
}
break;
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
pos_bits = priv->pos_res + ENDAT_NUM_BITS_POSITION_CRC + ENDAT_NUM_BITS_F1 +
ENDAT_NUM_BITS_F2;
if(pos_bits <= sizeof(unsigned) * 8)
{
endat_data->recvd1 = word0;
}
else
{
shift = pos_bits % (sizeof(unsigned) * 8);
endat_data->recvd1 = (uint64_t) word0 << shift | word1;
}
if(priv->flags.info1 || priv->flags.info2)
{
endat_data->recvd2 = word2;
}
if(priv->flags.info1 && priv->flags.info2)
{
endat_data->recvd3 = word3;
}
break;
default:
return -EINVAL;
break;
}
return 0;
}
/* value to be reflected should be aligned to lsb, relected value would be aligned to lsb */
static uint64_t endat_reflect_ull_nbits(uint64_t input,
uint32_t n)
{
uint32_t i;
uint64_t val = 0;
/* val initialized to 0 above to handle n = 0 case, otherwise garbage would be returned */
for(i = 0; i < n; i++)
{
val <<= 1;
if(input & ((uint64_t) 1 << i))
{
val |= 1;
}
}
return val;
}
static int64_t endat_recvd_format(int32_t cmd, struct endat_priv *priv,
struct endat_data *endat_data, union endat_format_data *u)
{
uint64_t pos, rev;
switch(cmd)
{
case 2:
case 3:
case 4:
case 5:
case 7:
case 14:
u->addr_params.params = (endat_data->recvd1 >> ENDAT_NUM_BITS_POSITION_CRC)
& ((1 << ENDAT_NUM_BITS_PARAMETER) - 1);
u->addr_params.address = (endat_data->recvd1 >> (ENDAT_NUM_BITS_POSITION_CRC +
ENDAT_NUM_BITS_PARAMETER)) &
((1 << ENDAT_NUM_BITS_ADDRESS) - 1);
u->addr_params.crc = endat_data->recvd1 & ((1 << ENDAT_NUM_BITS_POSITION_CRC)
- 1);
break;
case 6:
u->test.value = (endat_data->recvd1 >> ENDAT_NUM_BITS_POSITION_CRC) & (((
uint64_t)1 << 40) - 1);
u->test.f1 = (endat_data->recvd1 >> (ENDAT_NUM_BITS_POSITION_CRC + 40)) & 1;
u->test.crc = endat_data->recvd1 & ((1 << ENDAT_NUM_BITS_POSITION_CRC) - 1);
break;
case 1:
pos = endat_data->recvd1 >> ENDAT_NUM_BITS_POSITION_CRC;
pos = pos & (((uint64_t) 1 << priv->pos_res) - 1); /* mask F1 */
pos = endat_reflect_ull_nbits(pos, priv->pos_res);
rev = (pos & (((uint64_t) 1 << priv->pos_res) - 1)) >>
priv->single_turn_res;
pos = pos & (((uint64_t) 1 << priv->single_turn_res) - 1);
u->position_addinfo.position.position = pos;
u->position_addinfo.position.revolution = rev;
u->position_addinfo.position.f1 = (endat_data->recvd1 >>
(ENDAT_NUM_BITS_POSITION_CRC + priv->pos_res)) & 1;
u->position_addinfo.position.crc = endat_data->recvd1 & ((
1 << ENDAT_NUM_BITS_POSITION_CRC) - 1);
break;
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
pos = endat_data->recvd1 >> ENDAT_NUM_BITS_POSITION_CRC;
pos = pos & (((uint64_t) 1 << priv->pos_res) -
1); /* mask F1/F2 */
pos = endat_reflect_ull_nbits(pos, priv->pos_res);
rev = (pos & (((uint64_t) 1 << priv->pos_res) - 1)) >>
priv->single_turn_res;
pos = pos & (((uint64_t) 1 << priv->single_turn_res) - 1);
u->position_addinfo.position.position = pos;
u->position_addinfo.position.revolution = rev;
u->position_addinfo.position.f1 = (endat_data->recvd1 >>
(ENDAT_NUM_BITS_POSITION_CRC + priv->pos_res + 1)) & 1;
u->position_addinfo.position.f2 = (endat_data->recvd1 >>
(ENDAT_NUM_BITS_POSITION_CRC + priv->pos_res)) & 1;
u->position_addinfo.position.crc = endat_data->recvd1 & ((
1 << ENDAT_NUM_BITS_POSITION_CRC) - 1);
if(priv->flags.info1 || priv->flags.info2)
{
if(endat_priv.flags.info2)
{
u->position_addinfo.addinfo2.addinfo = (endat_data->recvd2 >>
ENDAT_NUM_BITS_POSITION_CRC) & ((1 << 24) - 1);
u->position_addinfo.addinfo2.crc = endat_data->recvd2 & ((
1 << ENDAT_NUM_BITS_POSITION_CRC) - 1);
}
else
{
u->position_addinfo.addinfo1.addinfo = (endat_data->recvd2 >>
ENDAT_NUM_BITS_POSITION_CRC) & ((1 << 24) - 1);
u->position_addinfo.addinfo1.crc = endat_data->recvd2 & ((
1 << ENDAT_NUM_BITS_POSITION_CRC) - 1);
}
}
if(priv->flags.info1 && priv->flags.info2)
{
u->position_addinfo.addinfo1.addinfo = (endat_data->recvd3 >>
ENDAT_NUM_BITS_POSITION_CRC) & ((1 << 24) - 1);
u->position_addinfo.addinfo1.crc = endat_data->recvd3 & ((
1 << ENDAT_NUM_BITS_POSITION_CRC) - 1);
}
break;
default:
return -EINVAL;
break;
}
return 0;
}
int32_t endat_recvd_process(struct endat_priv *priv, int32_t cmd,
union endat_format_data *u)
{
struct endat_data endat_data;
int32_t ret;
ret = endat_recvd_organize(cmd, priv, &endat_data);
if(ret < 0)
{
return ret;
}
return endat_recvd_format(cmd, priv, &endat_data, u);
}
#define ENDAT_USE_OTF_CRC_STATUS
#ifndef ENDAT_USE_OTF_CRC_STATUS
static uint32_t make_crc_norm(uint32_t param8, uint32_t param16)
{
/* state of the 5 flip-flops */
uint32_t ff[5];
/* data bit array */
uint32_t code[24];
/* Auxiliary variable */
uint32_t ex;
/* dtetermined CRC code */
uint32_t crc = 0;
/* controlled variable for looping */
int32_t i;
/* set all flip-flops to 1 */
for(i = 0; i < 5; i++)
{
ff[i] = 1;
}
/* read 8 bit parameter into code array and convert bit sequence */
for(i = 0; i < 8; i++)
{
code[i] = (param8 & 0x0080) ? 1 : 0;
param8 <<= 1;
}
/* read 16 bit parameter into code array and convert bit sequence */
for(i = 8; i < 24; i++)
{
code[i] = (param16 & 0x8000) ? 1 : 0;
param16 <<= 1;
}
/* calculate crc analog to described h/w generator */
for(i = 0; i < 24; i++)
{
ex = ff[4] ^ code[i];
ff[4] = ff[3];
ff[3] = ff[2] ^ ex;
ff[2] = ff[1];
ff[1] = ff[0] ^ ex;
ff[0] = ex;
}
/* store crc in variable */
for(i = 4; i >= 0; i--)
{
ff[i] = ff[i] ? 0 : 1;
crc <<= 1;
crc |= ff[i];
}
return crc;
}
static uint32_t make_crc_pos(uint32_t clocks, uint32_t error1,
uint32_t error2, uint32_t endat22,
uint64_t highpos, uint64_t lowpos)
{
/* state of the 5 flip-flops */
uint32_t ff[5];
/* data bit array */
uint32_t code[66];
/* Auxiliary variable */
uint32_t ex;
/* dtetermined CRC code */
uint32_t crc = 0;
/* controlled variable for looping */
int32_t i;
/* set all flip-flops to 1 */
for(i = 0; i < 5; i++)
{
ff[i] = 1;
}
/* transfer alarm bits to code array */
if(endat22)
{
code[0] = error1;
code[1] = error2;
}
else
{
code[1] = error1;
}
/* transfer low pos bits to array */
for(i = 2; i < 34; i++)
{
code[i] = (lowpos & 0x00000001L) ? 1 : 0;
lowpos >>= 1;
}
/* transfer high pos bits to array */
for(i = 34; i < 66; i++)
{
code[i] = (highpos & 0x00000001L) ? 1 : 0;
highpos >>= 1;
}
/* calculate crc analog to described h/w generator */
for(i = (endat22 ? 0 : 1); i <= (clocks + 1); i++)
{
ex = ff[4] ^ code[i];
ff[4] = ff[3];
ff[3] = ff[2] ^ ex;
ff[2] = ff[1];
ff[1] = ff[0] ^ ex;
ff[0] = ex;
}
/* store crc in variable */
for(i = 4; i >= 0; i--)
{
ff[i] = ff[i] ? 0 : 1;
crc <<= 1;
crc |= ff[i];
}
return crc;
}
#endif
/* return crc status: bit0 - position/address params/test, bit1 - additional info1, bit2 - additional info2. return -EINVAL on failure */
uint32_t endat_recvd_validate(struct endat_priv *priv, int32_t cmd,
union endat_format_data *u)
{
uint32_t status = 0;
#ifdef ENDAT_USE_OTF_CRC_STATUS
uint8_t val;
#else
uint32_t crc;
uint64_t highpos, lowpos;
uint64_t test;
#endif
#ifdef ENDAT_USE_OTF_CRC_STATUS
val = priv->pruss_xchg->ch[priv->channel].crc.status;
if(priv->flags.info2)
{
status = val & 0x1;
/* move bit 1 to bit 2 */
status |= (val & 0x2) << 1;
if(priv->flags.info1)
{
/* move bit 2 to bit 1 */
status |= (val & 0x4) >> 1;
}
}
else
{
/* either additional info1 only present or no additional info present */
status = val & 0x3;
}
#else
switch(cmd)
{
case 1:
lowpos = (u->position_addinfo.position.revolution << priv->single_turn_res |
u->position_addinfo.position.position) & 0xFFFFFFFF;
highpos = (u->position_addinfo.position.revolution << priv->single_turn_res |
u->position_addinfo.position.position) >> 32;
crc = make_crc_pos(priv->pos_res, u->position_addinfo.position.f1, 0, 0,
highpos, lowpos);
if(u->position_addinfo.position.crc == crc)
{
status = 0x1;
}
break;
case 6:
test = endat_reflect_ull_nbits(u->test.value, 40);
lowpos = test & 0xFFFFFFFF;
highpos = test >> 32;
crc = make_crc_pos(40, u->position_addinfo.position.f1, 0, 0, highpos,
lowpos);
if(u->test.crc == crc)
{
status = 0x1;
}
break;
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
lowpos = (u->position_addinfo.position.revolution << priv->single_turn_res |
u->position_addinfo.position.position) & 0xFFFFFFFF;
highpos = (u->position_addinfo.position.revolution << priv->single_turn_res |
u->position_addinfo.position.position) >> 32;
crc = make_crc_pos(priv->pos_res, u->position_addinfo.position.f1,
u->position_addinfo.position.f2, 1, highpos, lowpos);
if(u->position_addinfo.position.crc == crc)
{
status = 0x1;
}
if(priv->flags.info1)
{
crc = make_crc_norm((u->position_addinfo.addinfo1.addinfo >> 16) & 0xFF,
u->position_addinfo.addinfo1.addinfo & 0xFFFF);
if(u->position_addinfo.addinfo1.crc == crc)
{
status |= 0x1 << 1;
}
}
if(priv->flags.info2)
{
crc = make_crc_norm((u->position_addinfo.addinfo2.addinfo >> 16) & 0xFF,
u->position_addinfo.addinfo2.addinfo & 0xFFFF);
if(u->position_addinfo.addinfo2.crc == crc)
{
status |= 0x1 << 2;
}
}
break;
case 2:
case 3:
case 4:
case 5:
case 7:
crc = make_crc_norm(u->addr_params.address, u->addr_params.params);
if(u->addr_params.crc == crc)
{
status = 0x1;
}
break;
default:
break;
}
#endif
return status;
}
/*
* XXX: check 2.2 command case with 2.2 capability in encoder, can live w/o as endat_get_command
* will handle and it is assumed that this function will be called either after endat_get_command
* or by diagnostic initialization code where it is only 2.1 commands used
*/
int32_t endat_command_build(struct endat_priv *priv, int32_t cmd,
struct cmd_supplement *cmd_supplement)
{
uint32_t info;
struct endat_pruss_xchg *endat_pruss_xchg = priv->pruss_xchg;
info = 0, priv->flags.info1 ? info++ : 0, priv->flags.info2 ? info++ : 0 ;
/*first clear command parameters to be safe */
memset(&endat_pruss_xchg->cmd, 0, sizeof(endat_pruss_xchg->cmd));
switch(cmd)
{
case 1:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_SEND_POSITION_VALUES;
endat_pruss_xchg->cmd[0].word1 = priv->pos_rx_bits_21_RTUPRU | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_NO_SUPPLEMENT | ENDAT_CMDTYP_POSITION) << 16);
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_SEND_POSITION_VALUES;
endat_pruss_xchg->cmd[1].word1 = priv->pos_rx_bits_21_PRU | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_NO_SUPPLEMENT | ENDAT_CMDTYP_POSITION) << 16);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_SEND_POSITION_VALUES;
endat_pruss_xchg->cmd[2].word1 = priv->pos_rx_bits_21_TXPRU | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_NO_SUPPLEMENT | ENDAT_CMDTYP_POSITION) << 16);
} /* command build for ch1 and ch2 in load share mode*/
break;
case 2:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_SEL_MEM_AREA;
endat_pruss_xchg->cmd[0].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[0].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
/*build separate command for all three channel in loadshare mode*/
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_SEL_MEM_AREA;
endat_pruss_xchg->cmd[1].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[1].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_SEL_MEM_AREA;
endat_pruss_xchg->cmd[2].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[2].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
}
break;
case 3:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_RECEIVE_PARAMETERS;
endat_pruss_xchg->cmd[0].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[0].word0 |= ((cmd_supplement->data & 0x8000) >> 7)
| (((cmd_supplement->data << 1) & 0xFF00) << 8) |
(((cmd_supplement->data << 9) & 0xFE00) << 16);
endat_pruss_xchg->cmd[0].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
/*build separate command for all three channel in loadshare mode*/
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_RECEIVE_PARAMETERS;
endat_pruss_xchg->cmd[1].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[1].word0 |= ((cmd_supplement->data & 0x8000) >> 7)
| (((cmd_supplement->data << 1) & 0xFF00) << 8) |
(((cmd_supplement->data << 9) & 0xFE00) << 16);
endat_pruss_xchg->cmd[1].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_RECEIVE_PARAMETERS;
endat_pruss_xchg->cmd[2].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[2].word0 |= ((cmd_supplement->data & 0x8000) >> 7)
| (((cmd_supplement->data << 1) & 0xFF00) << 8) |
(((cmd_supplement->data << 9) & 0xFE00) << 16);
endat_pruss_xchg->cmd[2].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
}
break;
case 4:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_SEND_PARAMETERS;
endat_pruss_xchg->cmd[0].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[0].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
/*build separate command for all three channel in loadshare mode */
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_SEND_PARAMETERS;
endat_pruss_xchg->cmd[1].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[1].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_SEND_PARAMETERS;
endat_pruss_xchg->cmd[2].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[2].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
}
break;
case 5:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_RECEIVE_RESET;
endat_pruss_xchg->cmd[0].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
/*build separate command for all three channel in loadshare mode*/
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_RECEIVE_RESET;
endat_pruss_xchg->cmd[1].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_RECEIVE_RESET;
endat_pruss_xchg->cmd[2].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
}
break;
case 6:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_SEND_TEST_VALUES;
endat_pruss_xchg->cmd[0].word1 = ENDAT_RX_46BITS | (ENDAT_TX_6BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
/*build separate command for all three channel in loadshare mode*/
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_SEND_TEST_VALUES;
endat_pruss_xchg->cmd[1].word1 = ENDAT_RX_46BITS | (ENDAT_TX_6BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_SEND_TEST_VALUES;
endat_pruss_xchg->cmd[2].word1 = ENDAT_RX_46BITS | (ENDAT_TX_6BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
}
break;
case 7:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_RECEIVE_TEST_COMMAND;
endat_pruss_xchg->cmd[0].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[0].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
/*build separate command for all three channel in loadshare mode*/
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_RECEIVE_TEST_COMMAND;
endat_pruss_xchg->cmd[1].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[1].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_RECEIVE_TEST_COMMAND;
endat_pruss_xchg->cmd[2].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[2].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
(ENDAT_CMDTYP_NO_SUPPLEMENT << 16);
}
break;
case 8:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_SEND_POSVAL_WITH_DATA;
/*
* Though this is not 2.1 command, fw expects it to be ENDAT_CMDTYP_2_1. Ideally macro should
* have been named ENDAT_CMDTYPE_HAVE_2_2_SUPPLEMENT instead of ENDAT_CMDTYP_2_[12] for readability
*/
endat_pruss_xchg->cmd[0].word1 = (priv->pos_rx_bits_22_RTUPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_NO_SUPPLEMENT | ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22)
<< 16);
/*build separate command for all three channel in loadshare mode*/
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_SEND_POSVAL_WITH_DATA;
/*
* Though this is not 2.1 command, fw expects it to be ENDAT_CMDTYP_2_1. Ideally macro should
* have been named ENDAT_CMDTYPE_HAVE_2_2_SUPPLEMENT instead of ENDAT_CMDTYP_2_[12] for readability
*/
endat_pruss_xchg->cmd[1].word1 = (priv->pos_rx_bits_22_PRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_NO_SUPPLEMENT | ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22)
<< 16);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_SEND_POSVAL_WITH_DATA;
/*
* Though this is not 2.1 command, fw expects it to be ENDAT_CMDTYP_2_1. Ideally macro should
* have been named ENDAT_CMDTYPE_HAVE_2_2_SUPPLEMENT instead of ENDAT_CMDTYP_2_[12] for readability
*/
endat_pruss_xchg->cmd[2].word1 = (priv->pos_rx_bits_22_TXPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_NO_SUPPLEMENT | ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22)
<< 16);
}
if(priv->flags.info1)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
}
}
if(priv->flags.info2)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
}
}
break;
case 9:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_MEMSEL;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_MEMSEL;
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_MEMSEL;
}
if(cmd_supplement->has_block_address)
{
endat_pruss_xchg->cmd[0].word1 = (priv->pos_rx_bits_22_RTUPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) |
(ENDAT_TX_6BITS << 8) | ((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) <<
16) | (1 << 24);
endat_pruss_xchg->cmd[0].word2 = cmd_supplement->address |
(cmd_supplement->block << 24);
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 = (priv->pos_rx_bits_22_PRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) |
(ENDAT_TX_6BITS << 8) | ((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) <<
16) | (1 << 24);
endat_pruss_xchg->cmd[1].word2 = cmd_supplement->address |
(cmd_supplement->block << 24);
endat_pruss_xchg->cmd[2].word1 = (priv->pos_rx_bits_22_TXPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) |
(ENDAT_TX_6BITS << 8) | ((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) <<
16) | (1 << 24);
endat_pruss_xchg->cmd[2].word2 = cmd_supplement->address |
(cmd_supplement->block << 24);
}
}
else
{
endat_pruss_xchg->cmd[0].word1 = (priv->pos_rx_bits_22_RTUPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) |
(ENDAT_TX_6BITS << 8) | ((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) <<
16);
endat_pruss_xchg->cmd[0].word2 = cmd_supplement->address;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 = (priv->pos_rx_bits_22_PRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) |
(ENDAT_TX_6BITS << 8) | ((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) <<
16);
endat_pruss_xchg->cmd[1].word2 = cmd_supplement->address;
endat_pruss_xchg->cmd[2].word1 = (priv->pos_rx_bits_22_TXPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) |
(ENDAT_TX_6BITS << 8) | ((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) <<
16);
endat_pruss_xchg->cmd[2].word2 = cmd_supplement->address;
}
}
if(priv->flags.info1)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
}
}
if(priv->flags.info2)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
}
}
break;
case 10:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_PARAM;
endat_pruss_xchg->cmd[0].word1 = (priv->pos_rx_bits_22_RTUPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[0].word2 = cmd_supplement->address;
/* data MSByte should be @((char *)word2 + 1) and LSByte @((char *)word2 + 2) */
endat_pruss_xchg->cmd[0].word2 |= ((cmd_supplement->data & 0xFF) << 16) |
(cmd_supplement->data & 0xFF00);
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_PARAM;
endat_pruss_xchg->cmd[1].word1 = (priv->pos_rx_bits_22_PRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[1].word2 = cmd_supplement->address;
/* data MSByte should be @((char *)word2 + 1) and LSByte @((char *)word2 + 2) */
endat_pruss_xchg->cmd[1].word2 |= ((cmd_supplement->data & 0xFF) << 16) |
(cmd_supplement->data & 0xFF00);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_PARAM;
endat_pruss_xchg->cmd[2].word1 = (priv->pos_rx_bits_22_TXPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[2].word2 = cmd_supplement->address;
/* data MSByte should be @((char *)word2 + 1) and LSByte @((char *)word2 + 2) */
endat_pruss_xchg->cmd[2].word2 |= ((cmd_supplement->data & 0xFF) << 16) |
(cmd_supplement->data & 0xFF00);
}
if(priv->flags.info1)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
}
}
if(priv->flags.info2)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
}
}
break;
case 11:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_SEND_POSVAL_SEND_PARAM;
endat_pruss_xchg->cmd[0].word1 = (priv->pos_rx_bits_22_RTUPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[0].word2 = cmd_supplement->address;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_SEND_POSVAL_SEND_PARAM;
endat_pruss_xchg->cmd[1].word1 = (priv->pos_rx_bits_22_PRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[1].word2 = cmd_supplement->address;
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_SEND_POSVAL_SEND_PARAM;
endat_pruss_xchg->cmd[2].word1 = (priv->pos_rx_bits_22_TXPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[2].word2 = cmd_supplement->address;
}
if(priv->flags.info1)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
}
}
if(priv->flags.info2)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
}
}
break;
case 12:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_ERR_RST;
endat_pruss_xchg->cmd[0].word1 = (priv->pos_rx_bits_22_RTUPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_ERR_RST;
endat_pruss_xchg->cmd[1].word1 = (priv->pos_rx_bits_22_PRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_ERR_RST;
endat_pruss_xchg->cmd[2].word1 = (priv->pos_rx_bits_22_TXPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
}
if(priv->flags.info1)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
}
}
if(priv->flags.info2)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
}
}
break;
case 13:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_TESTCMD;
endat_pruss_xchg->cmd[0].word1 = (priv->pos_rx_bits_22_RTUPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[0].word2 = cmd_supplement->address;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_TESTCMD;
endat_pruss_xchg->cmd[1].word1 = (priv->pos_rx_bits_22_PRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[1].word2 = cmd_supplement->address;
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_SEND_POSVAL_RECEIVE_TESTCMD;
endat_pruss_xchg->cmd[2].word1 = (priv->pos_rx_bits_22_TXPRU + info *
ENDAT_ADDITIONAL_INFO_RX_BITS) | (ENDAT_TX_6BITS << 8) |
((ENDAT_CMDTYP_POSITION | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[2].word2 = cmd_supplement->address;
}
if(priv->flags.info1)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO1) << 16;
}
}
if(priv->flags.info2)
{
endat_pruss_xchg->cmd[0].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
endat_pruss_xchg->cmd[2].word1 |= (ENDAT_CMDTYP_HAS_ADDINFO2) << 16;
}
}
break;
case 14:
endat_pruss_xchg->cmd[0].word0 = ENDAT_CMD_RECEIVE_COMMUNICATION_CMD;
endat_pruss_xchg->cmd[0].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[0].word0 |= ((cmd_supplement->data & 0x8000) >> 7)
| (((cmd_supplement->data << 1) & 0xFF00) << 8) |
(((cmd_supplement->data << 9) & 0xFE00) << 16);
endat_pruss_xchg->cmd[0].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
((ENDAT_CMDTYP_NO_SUPPLEMENT | ENDAT_CMDTYP_ENDAT22) << 16);
if(priv->load_share)
{
endat_pruss_xchg->cmd[1].word0 = ENDAT_CMD_RECEIVE_COMMUNICATION_CMD;
endat_pruss_xchg->cmd[1].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[1].word0 |= ((cmd_supplement->data & 0x8000) >> 7)
| (((cmd_supplement->data << 1) & 0xFF00) << 8) |
(((cmd_supplement->data << 9) & 0xFE00) << 16);
endat_pruss_xchg->cmd[1].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
((ENDAT_CMDTYP_NO_SUPPLEMENT | ENDAT_CMDTYP_ENDAT22) << 16);
endat_pruss_xchg->cmd[2].word0 = ENDAT_CMD_RECEIVE_COMMUNICATION_CMD;
endat_pruss_xchg->cmd[2].word0 |= ((cmd_supplement->address & 0x80) >> 7)
| (((cmd_supplement->address << 1) & 0xFE) << 8);
endat_pruss_xchg->cmd[2].word0 |= ((cmd_supplement->data & 0x8000) >> 7)
| (((cmd_supplement->data << 1) & 0xFF00) << 8) |
(((cmd_supplement->data << 9) & 0xFE00) << 16);
endat_pruss_xchg->cmd[2].word1 = ENDAT_RX_29BITS | (ENDAT_TX_30BITS << 8) |
((ENDAT_CMDTYP_NO_SUPPLEMENT | ENDAT_CMDTYP_ENDAT22) << 16);
}
break;
default:
cmd = -EINVAL;
break;
}
return cmd;
}
void endat_command_send(struct endat_priv *priv)
{
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
/*for load share mode set mask for all connected channels*/
if(priv->load_share)
{
pruss_xchg->config[0].trigger = pruss_xchg->config[0].channel==1?0x1:0;
pruss_xchg->config[1].trigger = pruss_xchg->config[1].channel==2?0x1:0;
pruss_xchg->config[2].trigger = pruss_xchg->config[2].channel==4?0x1:0;
}
else
{
pruss_xchg->config[0].trigger = 0x1;
}
}
void endat_command_wait(struct endat_priv *priv)
{
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
if(priv->load_share)
{ /*waiting till host trigger bits has not clear for all enabled channels*/
while((pruss_xchg->config[0].trigger&0x1) || (pruss_xchg->config[1].trigger &0x1) || (pruss_xchg->config[2].trigger&0x1))
;
}
else
{
while(pruss_xchg->config[0].trigger & 0x1)
;
}
}
void endat_recovery_time_conversion(struct endat_priv *priv)
{
/* RT: convert cycle to ns */
priv->pruss_xchg->endat_ch0_rt = priv->pruss_xchg->endat_ch0_rt * ((float)(1000000000)/priv->pruss_xchg->icssg_clk);
priv->pruss_xchg->endat_ch1_rt = priv->pruss_xchg->endat_ch1_rt * ((float)(1000000000)/priv->pruss_xchg->icssg_clk);
priv->pruss_xchg->endat_ch2_rt = priv->pruss_xchg->endat_ch2_rt * ((float)(1000000000)/priv->pruss_xchg->icssg_clk);
}
int32_t endat_command_process(struct endat_priv *priv, int32_t cmd,
struct cmd_supplement *cmd_supplement)
{
cmd = endat_command_build(priv, cmd, cmd_supplement);
if(cmd < 0)
{
return cmd;
}
endat_command_send(priv);
endat_command_wait(priv);
/* RT configuration(convert cycle to ns time ) for command 2.2*/
if( cmd > 7 && cmd < 15 )
{
endat_recovery_time_conversion(priv);
}
return cmd;
}
int32_t endat_get_2_2_angle(struct endat_priv *priv)
{
int32_t pos;
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
int32_t ch = priv->channel;
if(!(pruss_xchg->ch[ch].crc.status & ENDAT_CRC_DATA))
{
return -1;
}
pos = pruss_xchg->ch[ch].pos_word0;
#ifdef __TI_ARM__
pos = __rbit(pos);
#else
asm("rbit %0,%1" : "=r"(pos) : "r"(pos));
#endif
/* verify F1 = 0 & F2 = 1 */
if((pos & 0x3) != 0x2)
{
return -1;
}
/* discard F1, F2 */
pos >>= 2;
/* mask non-angular bits */
pos &= (1 << priv->single_turn_res) - 1;
return pos;
}
static int32_t endat_get_pos_res(struct endat_priv *priv)
{
int32_t cmd;
struct cmd_supplement cmd_supplement;
uint32_t word;
int32_t ch = priv->channel;
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
/* select memory area encoder manufacturer page 0 */
cmd = 2, cmd_supplement.address = MRS_CODE_PARAM_ENCODER_MANUFACTURER_PAGE0;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw, absence of delay here resulted in wrong values for pos_res */
ClockP_usleep(1000 * 12);
/* send parameter for word13 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_13;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 2);
word = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC)) & ((
1 << ENDAT_NUM_BITS_PARAMETER) - 1);
return word &= (1 << ENDAT_NUM_BITS_VALID_PAGE0_WORD13) - 1;
}
static int32_t endat_get_multi_turn_res(struct endat_priv *priv)
{
int32_t cmd;
struct cmd_supplement cmd_supplement;
uint32_t word;
int32_t ch = priv->channel;
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
/* select memory area encoder manufacturer page 0 */
cmd = 2, cmd_supplement.address = MRS_CODE_PARAM_ENCODER_MANUFACTURER_PAGE1;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 12);
/* send parameter for word1 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_1;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 2);
word = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC)) & ((
1 << ENDAT_NUM_BITS_PARAMETER) - 1);
return word &= (1 << ENDAT_NUM_BITS_VALID_PAGE1_WORD1) - 1;
}
static int32_t endat_get_id(struct endat_priv *priv)
{
int32_t cmd;
struct cmd_supplement cmd_supplement;
uint32_t word0, word1, word2;
int32_t ch = priv->channel;
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
/* select memory area encoder manufacturer page 1 */
cmd = 2, cmd_supplement.address = MRS_CODE_PARAM_ENCODER_MANUFACTURER_PAGE1;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 12);
/* send parameter for word8 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_8;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
word0 = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC))
& ((1 << ENDAT_NUM_BITS_PARAMETER) - 1);
/* delay copied from fw */
ClockP_usleep(1000 * 2);
/* send parameter for word9 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_9;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
word1 = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC))
& ((1 << ENDAT_NUM_BITS_PARAMETER) - 1);
/* delay copied from fw */
ClockP_usleep(1000 * 2);
/* send parameter for word10 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_10;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
word2 = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC))
& ((1 << ENDAT_NUM_BITS_PARAMETER) - 1);
/* delay copied from fw */
ClockP_usleep(1000 * 2);
priv->id.binary = word1 | word2 << 16;
/* swap the two ascii's so that printing as string will give what is required */
priv->id.ascii = ((word0 & 0xFF) << 8) | ((word0 & 0xFF00) >> 8);
return 0;
}
static int32_t endat_get_sn(struct endat_priv *priv)
{
int32_t cmd;
struct cmd_supplement cmd_supplement;
uint32_t word0, word1, word2;
int32_t ch = priv->channel;
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
/* select memory area encoder manufacturer page 1 */
cmd = 2, cmd_supplement.address = MRS_CODE_PARAM_ENCODER_MANUFACTURER_PAGE1;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 12);
/* send parameter for word11 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_11;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
word0 = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC))
& ((1 << ENDAT_NUM_BITS_PARAMETER) - 1);
/* delay copied from fw */
ClockP_usleep(1000 * 2);
/* send parameter for word12 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_12;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
word1 = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC))
& ((1 << ENDAT_NUM_BITS_PARAMETER) - 1);
/* delay copied from fw */
ClockP_usleep(1000 * 2);
/* send parameter for word13 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_13;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
word2 = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC))
& ((1 << ENDAT_NUM_BITS_PARAMETER) - 1);
/* delay copied from fw */
ClockP_usleep(1000 * 2);
priv->sn.ascii_lsb = word0 & 0xFF;
priv->sn.binary = ((word0 & 0xFF00) >> 8) | (word1 << 8) | ((
word2 & 0xFF) << 24);
priv->sn.ascii_msb = (word2 & 0xFF00) >> 8;
return 0;
}
static int32_t endat_get_command_set(struct endat_priv *priv)
{
int32_t cmd;
struct cmd_supplement cmd_supplement;
uint32_t word;
int32_t ch = priv->channel;
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
/* select memory area encoder manufacturer page 2 */
cmd = 2, cmd_supplement.address = MRS_CODE_PARAM_ENCODER_MANUFACTURER_PAGE2;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 12);
/* send parameter for word5 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_5;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 2);
word = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC)) & ((
1 << ENDAT_NUM_BITS_PARAMETER) - 1);
priv->cmd_set_2_2 = (word & 0x1) && !(word & 0x2);
priv->has_safety = (word & 0x4) && !(word & 0x8);
return 0;
}
static int32_t endat_get_type(struct endat_priv *priv)
{
int32_t cmd;
struct cmd_supplement cmd_supplement;
uint32_t word;
int32_t ch = priv->channel;
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
/* select memory area encoder manufacturer page 0 */
cmd = 2, cmd_supplement.address = MRS_CODE_PARAM_ENCODER_MANUFACTURER_PAGE0;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw, absence of delay here resulted in wrong values for pos_res */
ClockP_usleep(1000 * 12);
/* send parameter for word13 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_14;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 2);
word = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC)) & ((
1 << ENDAT_NUM_BITS_PARAMETER) - 1);
priv->type = (word & (1 << 15)) ? rotary : linear;
return 0;
}
static int32_t endat_get_step(struct endat_priv *priv)
{
int32_t cmd;
struct cmd_supplement cmd_supplement;
uint32_t word;
int32_t ch = priv->channel;
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
/* select memory area encoder manufacturer page 0 */
cmd = 2, cmd_supplement.address = MRS_CODE_PARAM_ENCODER_MANUFACTURER_PAGE1;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 12);
/* send parameter for word4 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_4;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 2);
word = (pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC)) & ((
1 << ENDAT_NUM_BITS_PARAMETER) - 1);
/* send parameter for word5 */
cmd = 4, cmd_supplement.address = APP_ENDAT_WORD_5;
if(endat_command_process(priv, cmd, &cmd_supplement) < 0)
{
return -EINVAL;
}
/* delay copied from fw */
ClockP_usleep(1000 * 2);
word |= ((pruss_xchg->ch[ch].pos_word0 >> (ENDAT_NUM_BITS_POSITION_CRC))
& ((1 << ENDAT_NUM_BITS_PARAMETER) - 1)) << 16;
return word;
}
int32_t endat_get_encoder_info(struct endat_priv *priv)
{
int32_t ret;
priv->pos_res = endat_get_pos_res(priv);
if(priv->pos_res < 0)
{
return priv->pos_res;
}
priv->multi_turn_res = endat_get_multi_turn_res(priv);
if(priv->multi_turn_res < 0)
{
return priv->multi_turn_res;
}
else if(!priv->multi_turn_res)
{
priv->single_turn_res = priv->pos_res;
}
else
{
priv->multi_turn_res = log2(priv->multi_turn_res);
priv->single_turn_res = priv->pos_res - priv->multi_turn_res;
}
priv->step = endat_get_step(priv);
if(priv->step < 0)
{
return priv->step;
}
/*calaculate rx frame size for all three channels and store in different variables*/
if(!priv->load_share)
{
priv->pos_rx_bits_21_RTUPRU = priv->pos_res + ENDAT_NUM_BITS_POSITION_CRC +
ENDAT_NUM_BITS_F1;
priv->pos_rx_bits_22_RTUPRU = priv->pos_rx_bits_21_RTUPRU + ENDAT_NUM_BITS_F2;
}
else if(priv->channel==0) /*ch0*/
{
priv->pos_rx_bits_21_RTUPRU = priv->pos_res + ENDAT_NUM_BITS_POSITION_CRC +
ENDAT_NUM_BITS_F1;
priv->pos_rx_bits_22_RTUPRU = priv->pos_rx_bits_21_RTUPRU + ENDAT_NUM_BITS_F2;
}
else if(priv->channel==1) /*ch1*/
{
priv->pos_rx_bits_21_PRU = priv->pos_res + ENDAT_NUM_BITS_POSITION_CRC +
ENDAT_NUM_BITS_F1;
priv->pos_rx_bits_22_PRU = priv->pos_rx_bits_21_PRU + ENDAT_NUM_BITS_F2;}
else
{
priv->pos_rx_bits_21_TXPRU = priv->pos_res + ENDAT_NUM_BITS_POSITION_CRC +
ENDAT_NUM_BITS_F1;
priv->pos_rx_bits_22_TXPRU = priv->pos_rx_bits_21_TXPRU + ENDAT_NUM_BITS_F2;
} /*ch2*/
ret = endat_get_id(priv);
if(ret)
{
return ret;
}
ret = endat_get_sn(priv);
if(ret)
{
return ret;
}
ret = endat_get_type(priv);
if(ret)
{
return ret;
}
ret = endat_get_command_set(priv);
if(ret)
{
return ret;
}
return 0;
}
uint32_t endat_get_prop_delay(struct endat_priv *priv)
{
return priv->pruss_xchg->ch[priv->channel].prop_delay;
}
void endat_addinfo_track(struct endat_priv *priv, int32_t cmd,
struct cmd_supplement *cmd_supplement)
{
int32_t c7_c4, c3_c0;
/* reset stops additional info's */
if(cmd == 5)
{
priv->flags.info1 = FALSE, priv->flags.info2 = FALSE;
}
if(cmd != 9)
{
return;
}
c7_c4 = (cmd_supplement->address & ENDAT_MRS_MASK_SELECT_ADDITIONAL_INFO) >>
ENDAT_MRS_SHIFT_C7_C4;
c3_c0 = cmd_supplement->address & ENDAT_MRS_MASK_STOP_ADDITIONAL_INFO;
if(c7_c4 == ENDAT_MRS_VAL_C7_C4_SELECT_ADDITIONAL_INFO1)
{
if(c3_c0 == ENDAT_MRS_VAL_STOP_ADDITIONAL_INFO)
{
priv->flags.info1 = FALSE;
}
else
{
priv->flags.info1 = TRUE;
}
}
c7_c4 = (cmd_supplement->address & ENDAT_MRS_MASK_SELECT_ADDITIONAL_INFO) >>
ENDAT_MRS_SHIFT_C7_C4;
c3_c0 = cmd_supplement->address & ENDAT_MRS_MASK_STOP_ADDITIONAL_INFO;
if(c7_c4 == ENDAT_MRS_VAL_C7_C4_SELECT_ADDITIONAL_INFO2)
{
if(c3_c0 == ENDAT_MRS_VAL_STOP_ADDITIONAL_INFO)
{
priv->flags.info2 = FALSE;
}
else
{
priv->flags.info2 = TRUE;
}
}
}
static void endat_config_global_rx_arm_cnt(struct endat_priv *priv,
uint16_t val)
{
void *pruss_cfg = priv->pruss_cfg;
if(priv->pruicss_slicex)
{
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1CH0CFG1REGISTER + 2, val);
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1CH1CFG1REGISTER + 2, val);
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1CH2CFG1REGISTER + 2, val);
}
else
{
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0CH0CFG1REGISTER + 2, val);
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0CH1CFG1REGISTER + 2, val);
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0CH2CFG1REGISTER + 2, val);
}
}
void endat_config_rx_arm_cnt(struct endat_priv *priv, uint16_t val)
{
void *pruss_cfg = priv->pruss_cfg;
int32_t ch = priv->channel;
if(priv->pruicss_slicex)
{
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1CH0CFG1REGISTER + ch * 8 + 2, val);
}
else
{
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0CH0CFG1REGISTER + ch * 8 + 2, val);
}
}
void endat_config_wire_delay(struct endat_priv *priv, uint16_t val)
{
void *pruss_cfg = priv->pruss_cfg;
int32_t ch = priv->channel;
uint16_t regval;
if(priv->pruicss_slicex)
{
regval = HW_RD_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1CH0CFG0REGISTER + ch *
8);
}
else
{
regval = HW_RD_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0CH0CFG0REGISTER + ch *
8);
}
/* clear wire delay bits, keep other bits as is */
regval &= 0xF800;
/* restrict wire delay to wire delay bits only */
val &= 0x7FF;
regval |= val;
if(priv->pruicss_slicex)
{
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1CH0CFG0REGISTER + ch * 8, regval);
}
else
{
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0CH0CFG0REGISTER + ch * 8, regval);
}
}
void endat_config_clock(struct endat_priv *priv,
struct endat_clk_cfg *clk_cfg)
{
void *pruss_cfg = priv->pruss_cfg;
/* Set PRU1_ED_RX_SB_POL polarity bit, required for ICSSG (don't care for ICSSM) */
if(priv->pruicss_slicex)
{
HW_WR_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1RXCFGREGISTER, clk_cfg->rx_div << 16 | 0x8 |
clk_cfg->rx_div_attr);
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1TXCFGREGISTER + 2, clk_cfg->tx_div);
}
else
{
HW_WR_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0RXCFGREGISTER, clk_cfg->rx_div << 16 | 0x8 |
clk_cfg->rx_div_attr);
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0TXCFGREGISTER + 2, clk_cfg->tx_div);
}
}
void endat_config_tst_delay(struct endat_priv *priv, uint16_t delay)
{
void *pruss_cfg = priv->pruss_cfg;
int32_t ch = priv->channel;
if(priv->pruicss_slicex==1)
{
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1CH0CFG1REGISTER + ch * 8, delay);
}
else
{
HW_WR_REG16((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0CH0CFG1REGISTER + ch * 8, delay);
}
}
void endat_config_rx_clock_disable(struct endat_priv *priv,
uint16_t val)
{
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
int32_t ch = priv->channel;
pruss_xchg->ch[ch].rx_clk_less = val;
}
static void endat_set_continuous_mode(struct endat_priv *priv)
{
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
pruss_xchg->config[0].trigger |= (0x1 << 7 | 0x1);
}
static void endat_clear_continuous_mode(struct endat_priv *priv)
{
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
pruss_xchg->config[0].trigger &= ~(0x1 << 7);
}
int32_t endat_start_continuous_mode(struct endat_priv *priv)
{
int32_t cmd;
cmd = endat_command_build(priv, 1, NULL);
if(cmd < 0)
{
return cmd;
}
endat_set_continuous_mode(priv);
return cmd;
}
void endat_stop_continuous_mode(struct endat_priv *priv)
{
endat_clear_continuous_mode(priv);
endat_command_wait(priv);
}
void endat_config_host_trigger(struct endat_priv *priv)
{
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
/*for loadshare mode trigger set based on connected channels*/
if(priv->load_share)
{
pruss_xchg->config[0].opmode=(pruss_xchg->config[0].channel&(1<<0))?0x1:0;
pruss_xchg->config[1].opmode=(pruss_xchg->config[1].channel&(1<<1))?0x1:0;
pruss_xchg->config[2].opmode=(pruss_xchg->config[2].channel&(1<<2))?0x1:0;
}
else
{
pruss_xchg->config[0].opmode = 0x1;
}
}
void endat_config_periodic_trigger(struct endat_priv *priv)
{
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
pruss_xchg->config[0].opmode = 0;
}
void endat_config_channel(struct endat_priv *priv, int32_t ch)
{
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
pruss_xchg->config[0].channel = 1 << ch;
priv->channel = ch;
}
void endat_config_multi_channel_mask(struct endat_priv *priv,
uint8_t mask,
uint8_t loadshare)
{
priv->load_share = loadshare;
if(loadshare)
{
priv->pruss_xchg->config[0].channel = mask&(1<<0);
priv->pruss_xchg->config[1].channel = mask&(1<<1);
priv->pruss_xchg->config[2].channel = mask&(1<<2);
endat_config_primary_core_mask(priv, mask);/*select primary core for global configuration*/
endat_config_syn_bits(priv, mask); /* configure syn bits for synchronization before any global config*/
endat_enable_load_share_mode(priv); /*ENABLE SHARE MODE*/
}
else
{
priv->pruss_xchg->config[0].channel = mask;
}
}
void endat_config_syn_bits(struct endat_priv *priv, uint8_t mask)
{
priv->pruss_xchg->endat_ch0_syn_bit=mask&(1<<0)?0x1:0;
priv->pruss_xchg->endat_ch1_syn_bit=mask&(1<<1)?0x2:0;
priv->pruss_xchg->endat_ch2_syn_bit=mask&(1<<2)?0x4:0;
}
void endat_enable_load_share_mode(struct endat_priv *priv)
{
void *pruss_cfg = priv->pruss_cfg;
//HW_WR_REG32(0x30026104) |= 0x0800;
uint32_t rgval;
if(priv->pruicss_slicex)
{
rgval = HW_RD_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1TXCFGREGISTER);
rgval |= CSL_ICSSCFG_EDPRU1TXCFGREGISTER_PRU1_ENDAT_SHARE_EN_MASK;
HW_WR_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1TXCFGREGISTER, rgval);
}
else
{
rgval = HW_RD_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0TXCFGREGISTER);
rgval |= CSL_ICSSCFG_EDPRU0TXCFGREGISTER_PRU0_ENDAT_SHARE_EN_MASK;
HW_WR_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0TXCFGREGISTER, rgval);
}
}
void endat_config_primary_core_mask(struct endat_priv *priv, uint8_t mask)
{
switch (mask)
{
case 1: /*only channel0 connected*/
priv->pruss_xchg->endat_primary_core_mask=0x1;
break;
case 2: /*channel1 connected*/
priv->pruss_xchg->endat_primary_core_mask=0x2;
break;
case 3: /*channel0 and channel1 connected*/
priv->pruss_xchg->endat_primary_core_mask=0x1;
break;
case 4: /*channel2 connected*/
priv->pruss_xchg->endat_primary_core_mask=0x4;
break;
case 5: /*channel0 and channel2 connnected*/
priv->pruss_xchg->endat_primary_core_mask=0x4;
break;
case 6: /*channel1 and channel2 connected*/
priv->pruss_xchg->endat_primary_core_mask=0X4;
break;
case 7: /*all three channel connected*/
priv->pruss_xchg->endat_primary_core_mask=0x4;
break;
}
}
uint8_t endat_multi_channel_detected(struct endat_priv *priv)
{ if(priv->load_share)
return (priv->pruss_xchg->config[0].channel|priv->pruss_xchg->config[1].channel|priv->pruss_xchg->config[2].channel);
else
return priv->pruss_xchg->config[0].channel;
}
void endat_multi_channel_set_cur(struct endat_priv *priv, int32_t ch)
{
priv->channel = ch;
}
int32_t endat_wait_initialization(struct endat_priv *priv, uint32_t timeout, uint8_t mask)
{
int32_t i;
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
for(i = 0; i < timeout; i++)
{
if(priv->load_share) /* for loadshare mode*/
{
switch (mask) {
case 1: /*channel 0 connected*/
if((pruss_xchg->config[0].status & 1))
return 0;
break;
case 2: /*channel 1 connected*/
if((pruss_xchg->config[1].status & 1))
return 0;
break;
case 3: /*channel 0 and 1 connected*/
if((pruss_xchg->config[0].status & 1)&&(pruss_xchg->config[1].status & 1))
return 0;
break;
case 4: /*channel 2 connected*/
if((pruss_xchg->config[2].status & 1))
return 0;
break;
case 5: /*channel 0 and 2 connnected*/
if((pruss_xchg->config[0].status & 1)&&(pruss_xchg->config[2].status & 1))
return 0;
break;
case 6: /*channel 1 and 2 connected*/
if((pruss_xchg->config[1].status & 1)&&(pruss_xchg->config[2].status & 1))
return 0;
break;
case 7: /*all three channel connected*/
if((pruss_xchg->config[0].status & 1)&&(pruss_xchg->config[1].status & 1)&&( pruss_xchg->config[2].status & 1))
return 0;
break;
}
ClockP_usleep(1000 * 1);
}
else if(pruss_xchg->config[0].status & 1)
{
break;
}
else
{
ClockP_usleep(1000 * 1);
}
}
if(i == timeout)
{
return -1;
}
return 0;
}
static inline void endat_config_clr_cfg0(struct endat_priv *priv)
{
void *pruss_cfg = priv->pruss_cfg;
if(priv->pruicss_slicex)
{
HW_WR_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1CH0CFG0REGISTER, 0);
HW_WR_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1CH1CFG0REGISTER, 0);
HW_WR_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU1CH2CFG0REGISTER, 0);
}
else
{
HW_WR_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0CH0CFG0REGISTER, 0);
HW_WR_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0CH1CFG0REGISTER, 0);
HW_WR_REG32((uint8_t *)pruss_cfg + CSL_ICSSCFG_EDPRU0CH2CFG0REGISTER, 0);
}
}
static inline void endat_config_endat_mode(struct endat_priv *priv)
{
void *pruss_cfg = priv->pruss_cfg;
if(priv->pruicss_slicex)
{
HW_WR_REG8((uint8_t *)pruss_cfg + CSL_ICSSCFG_GPCFG1 + 3, 4);
}
else
{
HW_WR_REG8((uint8_t *)pruss_cfg + CSL_ICSSCFG_GPCFG0 + 3, 4);
}
}
static void endat_hw_init(struct endat_priv *priv)
{
struct endat_clk_cfg clk_cfg;
/* set initial clock to 200KHz */
/* 192MHz / 200KHz - 1 */
clk_cfg.tx_div = 959;
/* 192MHz / 200KHz / 8 - 1 */
clk_cfg.rx_div = 119;
/* 2T */
clk_cfg.rx_en_cnt = 10000;
/* sample size 8 */
clk_cfg.rx_div_attr = 7;
endat_config_endat_mode(priv);
endat_config_clock(priv, &clk_cfg);
endat_config_global_rx_arm_cnt(priv, clk_cfg.rx_en_cnt);
endat_config_clr_cfg0(priv);
}
struct endat_priv *endat_init(struct endat_pruss_xchg *pruss_xchg,
void *pruss_cfg, int32_t slice)
{
endat_priv.pruss_xchg = pruss_xchg;
endat_priv.pruss_cfg = pruss_cfg;
endat_priv.pruicss_slicex = slice;
endat_hw_init(&endat_priv);
return &endat_priv;
}
uint32_t endat_get_recovery_time(struct endat_priv *priv)
{
if(priv->channel == 0)
{
return priv->pruss_xchg->endat_ch0_rt;
}
else if (priv->channel == 1)
{
return priv->pruss_xchg->endat_ch1_rt;
}
else
{
return priv->pruss_xchg->endat_ch2_rt;
}
}