blob: a1ac08245e9f6822bb81db8c2d6177ab0abfab08 [file] [log] [blame]
/*
* Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved.
*
* SPDX-License-Identifier: GPL-2.0+ and/or BSD-3-Clause
* The GPL-2.0+ license for this file can be found in the COPYING.GPL file
* included with this distribution or at
* http://www.gnu.org/licenses/gpl-2.0.html
* The BSD-3-Clause License for this file can be found in the COPYING.BSD file
* included with this distribution or at
* http://opensource.org/licenses/BSD-3-Clause
*/
#include <linux/delay.h>
#include <linux/err.h>
#include <linux/io.h>
#include <linux/regmap.h>
#include <linux/mcc_config_linux.h>
#include <linux/mcc_common.h>
#include <linux/mcc_imx6sx.h>
#include <linux/mcc_linux.h>
#include "mcc_config.h"
/*!
* \brief This function returns the core number
*
* \return int
*/
unsigned int _psp_core_num(void)
{
#if (MCC_OS_USED == MCC_MQX)
return 1;
#elif (MCC_OS_USED == MCC_LINUX)
return 0;
#endif
}
/*!
* \brief This function returns the node number
*
* \return unsigned int
*/
unsigned int _psp_node_num(void)
{
#if (MCC_OS_USED == MCC_MQX)
return MCC_MQX_NODE_NUMBER ;
#elif (MCC_OS_USED == MCC_LINUX)
return MCC_LINUX_NODE_NUMBER;
#endif
}
/*
* This field contains CPU-to-CPU interrupt vector numbers
* for all device cores.
*/
static const unsigned int mcc_cpu_to_cpu_vectors[] = {INT_CPU_TO_CPU_MU_A2M,
INT_CPU_TO_CPU_MU_M2A};
/*!
* \brief This function gets the CPU-to-CPU vector num for the particular core.
*
* Platform-specific inter-CPU vector numbers for each core are defined in the
* mcc_cpu_to_cpu_vectors[] field.
*
* \param[in] core Core number.
*
* \return vector number for the particular core
* \return MCC_VECTOR_NUMBER_INVALID (vector number for the particular core
* number not found)
*/
unsigned int mcc_get_cpu_to_cpu_vector(unsigned int core)
{
u32 val;
val = sizeof(mcc_cpu_to_cpu_vectors)/sizeof(mcc_cpu_to_cpu_vectors[0]);
if (core < val)
return mcc_cpu_to_cpu_vectors[core];
return MCC_VECTOR_NUMBER_INVALID;
}
unsigned int mcc_get_mu_irq(void)
{
u32 val;
regmap_read(imx_mu_reg, MU_ASR, &val);
return val;
}
void mcc_enable_receive_irq(unsigned int enable)
{
u32 val = enable ? BIT(27) : 0;
regmap_update_bits(imx_mu_reg, MU_ACR, BIT(27), val);
}
void mcc_send_via_mu_buffer(unsigned int index, unsigned int data)
{
u32 val;
unsigned long timeout = jiffies + msecs_to_jiffies(500);
/* wait for transfer buffer empty */
do {
regmap_read(imx_mu_reg, MU_ASR, &val);
if (time_after(jiffies, timeout)) {
pr_err("Waiting MU transmit buffer empty timeout!\n");
break;
}
} while ((val & (1 << (20 + index))) == 0);
regmap_write(imx_mu_reg, index * 0x4 + MU_ATR0_OFFSET, data);
}
void mcc_receive_from_mu_buffer(unsigned int index, unsigned int *data)
{
regmap_read(imx_mu_reg, index * 0x4 + MU_ARR0_OFFSET, data);
}
unsigned int mcc_handle_mu_receive_irq(void)
{
u32 val;
/* disable receive irq until last message is handled */
mcc_enable_receive_irq(0);
regmap_read(imx_mu_reg, MU_ARR0_OFFSET, &val);
return val;
}
/*!
* \brief This function clears the CPU-to-CPU int flag for the particular core.
*
* Implementation is platform-specific.
*
* \param[in] core Core number.
*/
void mcc_clear_cpu_to_cpu_interrupt(unsigned int core)
{
u32 val;
regmap_read(imx_mu_reg, MU_ASR, &val);
/* write 1 to BIT31 to clear the bit31(GIP3) of MU_ASR */
val = val | (1 << 31);
regmap_write(imx_mu_reg, MU_ASR, val);
}
/*!
* \brief This function triggers the CPU-to-CPU interrupt.
*
* Platform-specific software triggering the inter-CPU interrupts.
*/
int mcc_triger_cpu_to_cpu_interrupt(void)
{
int i = 0;
u32 val;
regmap_read(imx_mu_reg, MU_ACR, &val);
if ((val & BIT(19)) != 0) {
do {
regmap_read(imx_mu_reg, MU_ACR, &val);
msleep(1);
} while (((val & BIT(19)) > 0) && (i++ < 100));
}
if ((val & BIT(19)) == 0) {
/* Enable the bit19(GIR3) of MU_ACR */
regmap_update_bits(imx_mu_reg, MU_ACR, BIT(19), BIT(19));
return 0;
} else {
pr_info("mcc int still be triggered after %d ms polling!\n", i);
return -EIO;
}
}
/*!
* \brief This function disable the CPU-to-CPU interrupt.
*
* Platform-specific software disable the inter-CPU interrupts.
*/
int imx_mcc_bsp_int_disable(unsigned int vector_number)
{
u32 val;
if (vector_number == INT_CPU_TO_CPU_MU_A2M) {
/* Disable the bit31(GIE3) of MU_ACR */
regmap_update_bits(imx_mu_reg, MU_ACR, BIT(31) | BIT(27), 0);
/* flush */
regmap_read(imx_mu_reg, MU_ACR, &val);
} else
pr_err("ERR:wrong vector number in mcc.\n");
return 0;
}
/*!
* \brief This function enable the CPU-to-CPU interrupt.
*
* Platform-specific software enable the inter-CPU interrupts.
*/
int imx_mcc_bsp_int_enable(unsigned int vector_number)
{
u32 val;
if (vector_number == INT_CPU_TO_CPU_MU_A2M) {
/* Enable the bit31(GIE3) of MU_ACR */
regmap_update_bits(imx_mu_reg, MU_ACR,
BIT(31) | BIT(27), BIT(31) | BIT(27));
/* flush */
regmap_read(imx_mu_reg, MU_ACR, &val);
return 0;
} else {
pr_err("ERR:wrong vector number in mcc.\n");
return -EINVAL;
}
}