motor-control-sdk/source/position_sense/bissc/driver/bissc_drv.c

564 lines
22 KiB
C
Raw Normal View History

/*
* Copyright (C) 2023 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/bissc/include/bissc_drv.h>
#include <kernel/dpl/ClockP.h>
#include <drivers/hw_include/tistdtypes.h>
#include <drivers/hw_include/hw_types.h>
static struct bissc_priv bissc_priv;
void bissc_command_send(struct bissc_priv *priv)
{
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
if(priv->load_share)
{
pruicss_xchg->cycle_trigger[0] = (pruicss_xchg->channel & 0x1)?0x1:0;
pruicss_xchg->cycle_trigger[1] = (pruicss_xchg->channel & 0x2)?0x1:0;
pruicss_xchg->cycle_trigger[2] = (pruicss_xchg->channel & 0x4)?0x1:0;
}
else
{
pruicss_xchg->cycle_trigger[0] = 0x1;
}
}
int32_t bissc_command_wait(struct bissc_priv *priv)
{
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
uint32_t timeout;
/* Minimum and Maximum BiSSC cycle time depends on various params as below:
TCycle_min = TMA (5 + DLEN + CRCLEN) + tLineDelay + tbusy_max + busy_s_max + tTO
Instead wait for max of 5 ms as this can vary for different encoders and for daisy chain
*/
timeout = BISSC_MAX_CYCLE_TIMEOUT;
while(1)
{
if(priv->load_share)
{
if((pruicss_xchg->cycle_trigger[0] == 0 ) && (pruicss_xchg->cycle_trigger[1] == 0) && (pruicss_xchg->cycle_trigger[2] == 0))
{
break;
}
}
else if(pruicss_xchg->cycle_trigger[0] == 0)
{
break;
}
ClockP_usleep(1000);
timeout--;
if(timeout == 0)
{
return SystemP_FAILURE;
}
}
return SystemP_SUCCESS;
}
int32_t bissc_command_process(struct bissc_priv *priv)
{
int32_t ret = SystemP_FAILURE;
bissc_command_send(priv);
ret = bissc_command_wait(priv);
return ret;
}
void bissc_enable_load_share_mode(struct bissc_priv *priv)
{
void *pruss_cfg = priv->pruicss_cfg;
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 bissc_config_primary_core_mask(struct bissc_priv *priv, uint8_t mask)
{
switch (mask)
{
case 1: /*only channel0 connected*/
priv->pruicss_xchg->primary_core_mask=0x1;
break;
case 2: /*channel1 connected*/
priv->pruicss_xchg->primary_core_mask=0x2;
break;
case 3: /*channel0 and channel1 connected*/
priv->pruicss_xchg->primary_core_mask=0x1;
break;
case 4: /*channel2 connected*/
priv->pruicss_xchg->primary_core_mask=0x4;
break;
case 5: /*channel0 and channel2 connnected*/
priv->pruicss_xchg->primary_core_mask=0x4;
break;
case 6: /*channel1 and channel2 connected*/
priv->pruicss_xchg->primary_core_mask=0X4;
break;
case 7: /*all three channel connected*/
priv->pruicss_xchg->primary_core_mask=0x4;
break;
}
}
int32_t bissc_get_pos(struct bissc_priv *priv)
{
uint32_t raw_data0, raw_data1, shift, sl_num, max, ch_num, numencoders, ls_ch;
int32_t ch = 0;
if(bissc_command_process(priv) < 0)
{
return SystemP_FAILURE;
}
for(ch_num = 0; ch_num < priv->totalchannels; ch_num++)
{
ch = priv->channel[ch_num];
if(priv->load_share)
{
numencoders = priv->num_encoders[ch];
ls_ch = ch;
}
else
{
numencoders = priv->num_encoders[0];
ls_ch = 0;
}
for(sl_num = 0; sl_num < numencoders; sl_num++)
{
raw_data0 = priv->pruicss_xchg->pos_data_res[sl_num].raw_data[ch].pos_data_word0;
raw_data1 = priv->pruicss_xchg->pos_data_res[sl_num].raw_data[ch].pos_data_word1;
max = pow(2, priv->single_turn_len[ls_ch][sl_num]);
if((priv->data_len[ls_ch][sl_num] + BISSC_POS_CRC_LEN + BISSC_EW_LEN) <= 32)
{
priv->raw_data = (uint64_t) raw_data0;
priv->enc_pos_data[ch].position[sl_num] = (uint64_t) (raw_data0 >> (BISSC_POS_CRC_LEN + BISSC_EW_LEN));
priv->enc_pos_data[ch].ew[sl_num] = ((raw_data0 >> (BISSC_POS_CRC_LEN )) & 0x03);
priv->enc_pos_data[ch].num_of_turns[sl_num] = priv->enc_pos_data[ch].position[sl_num] >> priv->single_turn_len[ls_ch][sl_num];
priv->enc_pos_data[ch].angle[sl_num] = (float)(priv->enc_pos_data[ch].position[sl_num] & (max - 1)) / max * (float)360;
priv->enc_pos_data[ch].rcv_crc[sl_num] = raw_data0 & 0x3F;
priv->enc_pos_data[ch].otf_crc[sl_num] = priv->pruicss_xchg->pos_data_res[sl_num].pos_data_otf_crc[ch];
priv->pd_crc_err_cnt[ch][sl_num] = priv->pruicss_xchg->pos_data_res[sl_num].pd_crc_err_cnt[ch];
}
else
{
shift = ((priv->data_len[ls_ch][sl_num] + BISSC_POS_CRC_LEN + BISSC_EW_LEN) - 32);
priv->raw_data = (uint64_t) raw_data0 << shift | raw_data1;
priv->enc_pos_data[ch].position[sl_num] = (uint64_t) (priv->raw_data >> (BISSC_POS_CRC_LEN + BISSC_EW_LEN));
priv->enc_pos_data[ch].ew[sl_num] = ((priv->raw_data >> (BISSC_POS_CRC_LEN )) & 0x03);
priv->enc_pos_data[ch].num_of_turns[sl_num] = priv->enc_pos_data[ch].position[sl_num] >> priv->single_turn_len[ls_ch][sl_num];
priv->enc_pos_data[ch].angle[sl_num] = (float)(priv->enc_pos_data[ch].position[sl_num] & (max - 1)) / max * (float)360;
priv->enc_pos_data[ch].rcv_crc[sl_num] = priv->raw_data & 0x3F;
priv->enc_pos_data[ch].otf_crc[sl_num] = priv->pruicss_xchg->pos_data_res[sl_num].pos_data_otf_crc[ch];
priv->pd_crc_err_cnt[ch][sl_num] = priv->pruicss_xchg->pos_data_res[sl_num].pd_crc_err_cnt[ch];
}
}
}
return SystemP_SUCCESS;
}
void bissc_config_clock(struct bissc_priv *priv,
struct bissc_clk_cfg *clk_cfg)
{
void *pruicss_cfg = priv->pruicss_cfg;
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
/* Set PRU1_ED_RX_SB_POL polarity bit to 0 for bissc, required for ICSSG (don't care for ICSSM) */
if(priv->pruicss_slicex)
{
HW_WR_REG32((uint8_t *)pruicss_cfg + CSL_ICSSCFG_EDPRU1RXCFGREGISTER, ((clk_cfg->rx_div << 16) |
(clk_cfg->is_core_clk << 4) | (clk_cfg->rx_div_attr)));
HW_WR_REG32((uint8_t *)pruicss_cfg + CSL_ICSSCFG_EDPRU1TXCFGREGISTER, clk_cfg->tx_div << 16 |
(clk_cfg->is_core_clk << 4));
}
else
{
HW_WR_REG32((uint8_t *)pruicss_cfg + CSL_ICSSCFG_EDPRU0RXCFGREGISTER, ((clk_cfg->rx_div << 16) |
(clk_cfg->is_core_clk << 4) | (clk_cfg->rx_div_attr)));
HW_WR_REG32((uint8_t *)pruicss_cfg + CSL_ICSSCFG_EDPRU0TXCFGREGISTER, clk_cfg->tx_div << 16 |
(clk_cfg->is_core_clk << 4));
}
if(priv->load_share)
bissc_enable_load_share_mode(priv);
/* Clock configuration has changed - Indicate fw to measure the delay again */
pruicss_xchg->measure_proc_delay = 1;
}
void bissc_config_channel(struct bissc_priv *priv, int32_t mask, int32_t totalch)
{
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
int32_t ch_num;
pruicss_xchg->channel = mask;
priv->totalchannels = totalch;
/* Below for loop iterates for enabled channel number of times.
Updates channel in this manner:
if ch0 only selected --> priv->channel[0] = 0;
if ch1 only selected --> priv->channel[0] = 1;
if ch2 only selected --> priv->channel[0] = 2;
if ch0 & ch1 are selected --> priv->channel[0] = 0, priv->channel[1] = 1;
if ch0 & ch2 are selected --> priv->channel[0] = 0, priv->channel[1] = 2;
if ch1 & ch2 are selected --> priv->channel[0] = 1, priv->channel[1] = 2;
if ch0, ch1 & ch2 are selected --> priv->channel[0] = 0, priv->channel[1] = 1, priv->channel[1] = 2;
*/
for(ch_num = 0; ch_num < totalch; ch_num++)
{
if((mask & 1) && ch_num == 0)
priv->channel[ch_num] = 0;
else if((mask & 2) && (ch_num == 0 || ch_num == 1))
priv->channel[ch_num] = 1;
else if((mask & 4))
priv->channel[ch_num] = 2;
}
}
void bissc_config_load_share(struct bissc_priv *priv, int32_t mask)
{
priv->load_share = 1; /*Enable load-share*/
bissc_config_primary_core_mask(priv, mask);
bissc_enable_load_share_mode(priv);
}
int32_t bissc_wait_for_fw_initialization(struct bissc_priv *priv, uint32_t timeout, uint8_t mask)
{
int32_t i;
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
for(i = 0; i < timeout; i++)
{
if(priv->load_share) /* for loadshare mode*/
{
switch (mask) {
case 1: /*channel 0 connected*/
if((pruicss_xchg->status[0] & 1))
return SystemP_SUCCESS;
break;
case 2: /*channel 1 connected*/
if((pruicss_xchg->status[1] & 1))
return SystemP_SUCCESS;
break;
case 3: /*channel 0 and 1 connected*/
if((pruicss_xchg->status[0] & 1) && (pruicss_xchg->status[1] & 1))
return SystemP_SUCCESS;
break;
case 4: /*channel 2 connected*/
if((pruicss_xchg->status[2] & 1))
return SystemP_SUCCESS;
break;
case 5: /*channel 0 and 2 connnected*/
if((pruicss_xchg->status[0] & 1) && (pruicss_xchg->status[2] & 1))
return SystemP_SUCCESS;
break;
case 6: /*channel 1 and 2 connected*/
if((pruicss_xchg->status[1] & 1) && (pruicss_xchg->status[2] & 1))
return SystemP_SUCCESS;
break;
case 7: /*all three channel connected*/
if((pruicss_xchg->status[0] & 1) && (pruicss_xchg->status[1] & 1) && ( pruicss_xchg->status[2] & 1))
return SystemP_SUCCESS;
break;
}
ClockP_usleep(1000 * 1);
}
else if(pruicss_xchg->status[0] & 1)
{
break;
}
else
{
ClockP_usleep(1000 * 1);
}
}
if(i == timeout)
{
return SystemP_FAILURE;
}
return SystemP_SUCCESS;
}
void bissc_get_enc_proc_delay(struct bissc_priv *priv)
{
int32_t i;
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
for(i = 0; i < NUM_ED_CH_MAX; i++)
{
priv->proc_delay[i] = pruicss_xchg->proc_delay[i];
}
}
void bissc_config_clr_cfg0(struct bissc_priv *priv)
{
void *pruicss_cfg = priv->pruicss_cfg;
if(priv->pruicss_slicex)
{
HW_WR_REG32((uint8_t *)pruicss_cfg + CSL_ICSSCFG_EDPRU1CH0CFG0REGISTER, 0);
HW_WR_REG32((uint8_t *)pruicss_cfg + CSL_ICSSCFG_EDPRU1CH1CFG0REGISTER, 0);
HW_WR_REG32((uint8_t *)pruicss_cfg + CSL_ICSSCFG_EDPRU1CH2CFG0REGISTER, 0);
}
else
{
HW_WR_REG32((uint8_t *)pruicss_cfg + CSL_ICSSCFG_EDPRU0CH0CFG0REGISTER, 0);
HW_WR_REG32((uint8_t *)pruicss_cfg + CSL_ICSSCFG_EDPRU0CH1CFG0REGISTER, 0);
HW_WR_REG32((uint8_t *)pruicss_cfg + CSL_ICSSCFG_EDPRU0CH2CFG0REGISTER, 0);
}
}
void bissc_config_endat_mode(struct bissc_priv *priv)
{
void *pruicss_cfg = priv->pruicss_cfg;
if(priv->pruicss_slicex)
{
HW_WR_REG8((uint8_t *)pruicss_cfg + CSL_ICSSCFG_GPCFG1 + 3, 4);
}
else
{
HW_WR_REG8((uint8_t *)pruicss_cfg + CSL_ICSSCFG_GPCFG0 + 3, 4);
}
}
int32_t bissc_calc_clock(struct bissc_priv *priv, struct bissc_clk_cfg *clk_cfg)
{
uint32_t freq = priv->baud_rate;
clk_cfg->rx_div_attr = BISSC_RX_SAMPLE_SIZE;
if((freq == BISSC_FREQ_1MHZ) || (freq == BISSC_FREQ_5MHZ))
{
freq = freq * 1000 * 1000;
clk_cfg->tx_div = (priv->core_clk_freq / freq) - 1;
clk_cfg->rx_div = (priv->core_clk_freq / (freq * 8)) - 1;
clk_cfg->is_core_clk = 1;
}
else if((freq == BISSC_FREQ_2MHZ) || (freq == BISSC_FREQ_8MHZ))
{
freq = freq * 1000 * 1000;
clk_cfg->tx_div = (priv->uart_clk_freq / freq) - 1;
clk_cfg->rx_div = (priv->uart_clk_freq / (freq * 8)) - 1;
clk_cfg->is_core_clk = 0;
}
else if(freq == BISSC_FREQ_10MHZ)
{
freq = freq* 1000 * 1000;
clk_cfg->tx_div = (priv->core_clk_freq / freq) - 1;
clk_cfg->rx_div = (priv->core_clk_freq / (freq * 4)) - 1;
clk_cfg->is_core_clk = 1;
clk_cfg->rx_div_attr = BISSC_RX_SAMPLE_SIZE_10MHZ;
}
else
{
return SystemP_FAILURE;
}
return SystemP_SUCCESS;
}
void bissc_hw_init(struct bissc_priv *priv)
{
struct bissc_clk_cfg clk_cfg;
bissc_calc_clock(priv, &clk_cfg);
bissc_config_endat_mode(priv);
bissc_config_clock(priv, &clk_cfg);
bissc_config_clr_cfg0(priv);
}
struct bissc_priv *bissc_init(PRUICSS_Handle gPruIcssXHandle,
int32_t slice,
uint32_t frequency,
uint32_t core_clk_freq,
uint32_t uart_clk_freq)
{
struct bissc_pruicss_xchg *pruicss_xchg;
void *pruicss_cfg;
pruicss_cfg = (void *)(((PRUICSS_HwAttrs *)(gPruIcssXHandle->hwAttrs))->cfgRegBase);
if(slice)
pruicss_xchg = (struct bissc_pruicss_xchg *)((PRUICSS_HwAttrs *)(gPruIcssXHandle->hwAttrs))->pru1DramBase;
else
pruicss_xchg = (struct bissc_pruicss_xchg *)((PRUICSS_HwAttrs *)(gPruIcssXHandle->hwAttrs))->pru0DramBase;
bissc_priv.pruicss_xchg = pruicss_xchg;
bissc_priv.pruicss_cfg = pruicss_cfg;
bissc_priv.pruicss_slicex = slice;
bissc_priv.baud_rate = frequency;
bissc_priv.core_clk_freq = core_clk_freq;
bissc_priv.uart_clk_freq = uart_clk_freq;
bissc_hw_init(&bissc_priv);
return &bissc_priv;
}
void bissc_update_max_proc_delay(struct bissc_priv *priv)
{
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
pruicss_xchg->fifo_bit_idx = 4; /* 8x over clock - middle bit*/
if(priv->baud_rate == BISSC_FREQ_1MHZ)
pruicss_xchg->max_proc_delay = BISSC_MAX_PROC_DELAY_1MHZ;
else if(priv->baud_rate == BISSC_FREQ_2MHZ)
pruicss_xchg->max_proc_delay = BISSC_MAX_PROC_DELAY_2MHZ;
else if(priv->baud_rate == BISSC_FREQ_5MHZ)
pruicss_xchg->max_proc_delay = BISSC_MAX_PROC_DELAY_5MHZ;
else if(priv->baud_rate == BISSC_FREQ_8MHZ)
pruicss_xchg->max_proc_delay = BISSC_MAX_PROC_DELAY_8MHZ;
else if(priv->baud_rate == BISSC_FREQ_10MHZ)
{
pruicss_xchg->max_proc_delay = BISSC_MAX_PROC_DELAY_10MHZ;
pruicss_xchg->fifo_bit_idx = 2; /* 4x over clock - middle bit*/
}
}
int32_t bissc_wait_measure_proc_delay(struct bissc_priv *priv, uint32_t timeout)
{
int32_t i;
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
for(i = 0; i < timeout; i++)
{
if(pruicss_xchg->measure_proc_delay & 1)
{
break;
}
else
{
ClockP_usleep(1000);
}
}
if(i == timeout)
{
return SystemP_FAILURE;
}
return SystemP_SUCCESS;
}
void bissc_set_default_initialization(struct bissc_priv *priv, uint64_t icssgclk)
{
int8_t pru_num, totalprus, ls_ch;
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
/* Initialize parameters to default values */
if(priv->load_share)
totalprus = priv->totalchannels;
else
totalprus = 1;
for( pru_num = 0; pru_num < totalprus; pru_num++)
{
if(priv->load_share)
ls_ch = priv->channel[pru_num];
else
ls_ch = 0;
pruicss_xchg->enc_len[ls_ch].data_len[0] = BISSC_POS_DATA_LEN_DEFAULT;
priv->data_len[ls_ch][0] = BISSC_POS_DATA_LEN_DEFAULT;
priv->single_turn_len[ls_ch][0] = BISSC_POS_DATA_LEN_DEFAULT;
pruicss_xchg->enc_len[ls_ch].num_encoders = 1;
priv->num_encoders[ls_ch] = 1;
priv->multi_turn_len[ls_ch][0] = 0;
pruicss_xchg->ctrl_cmd[ls_ch] = 0;
}
pruicss_xchg->pos_crc_len = BISSC_POS_CRC_LEN;
pruicss_xchg->ctrl_cmd_crc_len = BISSC_CTRL_CMD_CRC_LEN;
pruicss_xchg->rx_clk_freq = priv->baud_rate;
bissc_update_max_proc_delay(priv);
pruicss_xchg->delay_40us = ((icssgclk*40)/1000000);
pruicss_xchg->delay_100ms = (icssgclk / 10); /*((icssgclk*100000) / 1000000)*/
pruicss_xchg->icssg_clk = icssgclk;
pruicss_xchg->valid_bit_idx = 24;
pruicss_xchg->measure_proc_delay = 1;
pruicss_xchg->execution_state[0] = 0;
pruicss_xchg->execution_state[1] = 0;
pruicss_xchg->execution_state[2] = 0;
}
void bissc_update_data_len(struct bissc_priv *priv, uint32_t single_turn_len[], uint32_t multi_turn_len[], int32_t pru_num)
{
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
uint32_t sl_num, ls_ch;
if(priv->load_share)
ls_ch = priv->channel[pru_num];
else
ls_ch = 0;
for( sl_num = 0; sl_num < NUM_ENCODERS_MAX; sl_num++)
{
if(single_turn_len[sl_num])
{
priv->single_turn_len[ls_ch][sl_num] = single_turn_len[sl_num];
priv->multi_turn_len[ls_ch][sl_num] = multi_turn_len[sl_num];
priv->data_len[ls_ch][sl_num] = single_turn_len[sl_num] + multi_turn_len[sl_num];
pruicss_xchg->enc_len[ls_ch].data_len[sl_num] = single_turn_len[sl_num] + multi_turn_len[sl_num];
priv->num_encoders[ls_ch]++;
}
}
pruicss_xchg->enc_len[0].num_encoders = priv->num_encoders[0];
pruicss_xchg->enc_len[1].num_encoders = priv->num_encoders[1];
pruicss_xchg->enc_len[2].num_encoders = priv->num_encoders[2];
}
int32_t bissc_set_ctrl_cmd_and_process(struct bissc_priv *priv, uint32_t ctrl_cmd[])
{
struct bissc_pruicss_xchg *pruicss_xchg = priv->pruicss_xchg;
pruicss_xchg->ctrl_cmd[0] = ctrl_cmd[0];
pruicss_xchg->ctrl_cmd[1] = ctrl_cmd[1];
pruicss_xchg->ctrl_cmd[2] = ctrl_cmd[2];
int32_t ch = 0, ch_num;
if(priv->load_share)
{
pruicss_xchg->ctrl_cmd_status[0] = (pruicss_xchg->channel & 0x1)?1:0;
pruicss_xchg->ctrl_cmd_status[1] = (pruicss_xchg->channel & 0x2)?1:0;
pruicss_xchg->ctrl_cmd_status[2] = (pruicss_xchg->channel & 0x4)?1:0;
while(pruicss_xchg->ctrl_cmd_status[0] + pruicss_xchg->ctrl_cmd_status[1] + pruicss_xchg->ctrl_cmd_status[2])
{
if(bissc_command_process(priv) < 0)
{
return SystemP_FAILURE;
}
ClockP_usleep(1000);
}
}
else
{
pruicss_xchg->ctrl_cmd_status[0] = 1;
while(pruicss_xchg->ctrl_cmd_status[0] & 1)
{
if(bissc_command_process(priv) < 0)
{
return SystemP_FAILURE;
}
ClockP_usleep(1000);
}
}
/*supplying 2 extra cycles for ctrl communication stop bit */
bissc_command_process(priv);
ClockP_usleep(1000);
bissc_command_process(priv);
ClockP_usleep(1000);
for(ch_num = 0; ch_num < priv->totalchannels; ch_num++)
{
ch = priv->channel[ch_num];
priv->enc_ctrl_data[ch].cmd_result = pruicss_xchg->ctrl_res[ch].ctrl_cds_res;
priv->enc_ctrl_data[ch].cmd_rcv_crc = pruicss_xchg->ctrl_res[ch].ctrl_rcvd_crc;
priv->enc_ctrl_data[ch].cmd_otf_crc = pruicss_xchg->ctrl_res[ch].ctrl_otf_crc;
priv->ctrl_crc_err_cnt[ch] = pruicss_xchg->ctrl_res[ch].ctrl_crc_err_cnt;
}
return SystemP_SUCCESS;
}