- Add configurable memory support for encoder info Fixes: PINDSW-7015 Signed-off-by: Achala Ram <a-ram@ti.com>
2098 lines
74 KiB
C
2098 lines
74 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 EXPRESS 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 endatChRxInfo *endatChRxInfo = priv->endatChRxInfo;
|
|
memset(endat_data, 0, sizeof(*endat_data));
|
|
|
|
word0 = endatChRxInfo->ch[priv->channel].posWord0;
|
|
word1 = endatChRxInfo->ch[priv->channel].posWord1;
|
|
word2 = endatChRxInfo->ch[priv->channel].posWord2;
|
|
word3 = endatChRxInfo->ch[priv->channel].posWord3;
|
|
|
|
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->endatChRxInfo->ch[priv->channel].crcStatus;
|
|
|
|
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->endatChRxInfo->ch[0].recoveryTime = priv->endatChRxInfo->ch[0].recoveryTime * ((float)(1000000000)/priv->pruss_xchg->icssg_clk);
|
|
priv->endatChRxInfo->ch[1].recoveryTime = priv->endatChRxInfo->ch[1].recoveryTime * ((float)(1000000000)/priv->pruss_xchg->icssg_clk);
|
|
priv->endatChRxInfo->ch[2].recoveryTime = priv->endatChRxInfo->ch[2].recoveryTime * ((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 endatChRxInfo *endatChRxInfo = priv->endatChRxInfo;
|
|
int32_t ch = priv->channel;
|
|
|
|
|
|
if(!(endatChRxInfo->ch[ch].crcStatus & ENDAT_CRC_DATA))
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
pos = endatChRxInfo->ch[ch].posWord0;
|
|
|
|
#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 endatChRxInfo *endatChRxInfo = priv->endatChRxInfo;
|
|
|
|
/* 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 = (endatChRxInfo->ch[ch].posWord0 >> (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 endatChRxInfo *endatChRxInfo = priv->endatChRxInfo;
|
|
|
|
/* 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 = (endatChRxInfo->ch[ch].posWord0 >> (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 endatChRxInfo *endatChRxInfo = priv->endatChRxInfo;
|
|
|
|
/* 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 = (endatChRxInfo->ch[ch].posWord0 >> (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 = (endatChRxInfo->ch[ch].posWord0 >> (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 = (endatChRxInfo->ch[ch].posWord0 >> (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 endatChRxInfo *endatChRxInfo = priv->endatChRxInfo;
|
|
|
|
/* 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 = (endatChRxInfo->ch[ch].posWord0 >> (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 = (endatChRxInfo->ch[ch].posWord0 >> (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 = (endatChRxInfo->ch[ch].posWord0 >> (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 endatChRxInfo *endatChRxInfo = priv->endatChRxInfo;
|
|
|
|
/* 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 = (endatChRxInfo->ch[ch].posWord0 >> (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 endatChRxInfo *endatChRxInfo = priv->endatChRxInfo;
|
|
|
|
/* 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 = (endatChRxInfo->ch[ch].posWord0 >> (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 endatChRxInfo *endatChRxInfo = priv->endatChRxInfo;
|
|
|
|
/* 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 = (endatChRxInfo->ch[ch].posWord0 >> (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 |= ((endatChRxInfo->ch[ch].posWord0 >> (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].propDelay;
|
|
}
|
|
|
|
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].rxClkLess = val;
|
|
}
|
|
|
|
static void endat_set_continuous_mode(struct endat_priv *priv)
|
|
{
|
|
struct endat_pruss_xchg *pruss_xchg = priv->pruss_xchg;
|
|
if(priv->load_share)
|
|
{
|
|
pruss_xchg->config[0].trigger |= pruss_xchg->config[0].channel==1?(0x1 << 7 | 0x1):0;
|
|
pruss_xchg->config[1].trigger |= pruss_xchg->config[1].channel==2?(0x1 << 7 | 0x1):0;
|
|
pruss_xchg->config[2].trigger |= pruss_xchg->config[2].channel==4?(0x1 << 7 | 0x1):0;
|
|
}
|
|
else
|
|
{
|
|
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;
|
|
|
|
if(priv->load_share)
|
|
{
|
|
pruss_xchg->config[0].trigger &= ~(0x1 << 7);
|
|
pruss_xchg->config[1].trigger &= ~(0x1 << 7);
|
|
pruss_xchg->config[2].trigger &= ~(0x1 << 7);
|
|
}
|
|
else
|
|
{
|
|
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;
|
|
/*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))?0x0:pruss_xchg->config[0].opmode;
|
|
pruss_xchg->config[1].opmode=(pruss_xchg->config[1].channel&(1<<1))?0x0:pruss_xchg->config[0].opmode;
|
|
pruss_xchg->config[2].opmode=(pruss_xchg->config[2].channel&(1<<2))?0x0:pruss_xchg->config[0].opmode;
|
|
}
|
|
else
|
|
{
|
|
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;
|
|
if(priv->load_share)
|
|
{
|
|
if(priv->channel == 0)
|
|
{
|
|
priv->pos_res = priv->pos_rx_bits_21_RTUPRU - (ENDAT_NUM_BITS_POSITION_CRC + ENDAT_NUM_BITS_F1);
|
|
}
|
|
else if(priv->channel == 1)
|
|
{
|
|
priv->pos_res = priv->pos_rx_bits_21_PRU - (ENDAT_NUM_BITS_POSITION_CRC + ENDAT_NUM_BITS_F1);
|
|
}
|
|
else
|
|
{
|
|
priv->pos_res = priv->pos_rx_bits_21_TXPRU - (ENDAT_NUM_BITS_POSITION_CRC + ENDAT_NUM_BITS_F1);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
priv->pos_res = priv->pos_rx_bits_21_RTUPRU - (ENDAT_NUM_BITS_POSITION_CRC + ENDAT_NUM_BITS_F1);
|
|
}
|
|
}
|
|
|
|
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, struct endatChRxInfo *endatRxInfo, uint64_t endatChInfoGlobalAddr,
|
|
void *pruss_cfg, void* pruss_iep, int32_t slice)
|
|
{
|
|
endat_priv.pruss_xchg = pruss_xchg;
|
|
endat_priv.pruss_cfg = pruss_cfg;
|
|
endat_priv.pruicss_slicex = slice;
|
|
endat_priv.pruss_iep = pruss_iep;
|
|
endat_priv.endatChRxInfo = endatRxInfo;
|
|
/*Write Configured memory address to DMEM */
|
|
endat_priv.pruss_xchg->endatChInfoMemoryAdd = endatChInfoGlobalAddr;
|
|
endat_hw_init(&endat_priv);
|
|
return &endat_priv;
|
|
}
|
|
|
|
uint32_t endat_get_recovery_time(struct endat_priv *priv)
|
|
{
|
|
return priv->endatChRxInfo->ch[priv->channel].recoveryTime;
|
|
}
|