blob: 1a21cd318afc595fcb42f614ebac99f48d1d508e [file] [log] [blame]
/*
* Copyright 2017 NXP
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#include <debug.h>
#include <errno.h>
#include <stdlib.h>
#include <stdint.h>
#include <platform_def.h>
#include <utils_def.h>
#include <imx_rdc.h>
#include <mmio.h>
/*
* Read RDC settings for one peripheral
* read the given domains field and lock bit
* for the given PDAP index [0..118]
*/
int imx_rdc_get_pdap(struct rdc_pdap_conf *p)
{
struct imx_rdc_regs *imx_rdc = (struct imx_rdc_regs *)IMX_RDC_BASE;
uint32_t reg = 0;
reg = mmio_read_32((uintptr_t)&imx_rdc->pdap[p->index]);
p->lock = (reg & RDC_PDAP_LCK_MASK) >> RDC_PDAP_LCK_SHIFT;
p->domains = reg & 0xFF;
return 0;
}
/*
* Write RDC settings for one peripheral
* Check before write if is already locked then skip
*/
int imx_rdc_set_pdap(struct rdc_pdap_conf *p)
{
struct imx_rdc_regs *imx_rdc = (struct imx_rdc_regs *)IMX_RDC_BASE;
struct rdc_pdap_conf r;
uint32_t i, reg = 0;
uint8_t multi_domain = 0;
/* Check if locked */
r.index = p->index;
imx_rdc_get_pdap(&r);
if (r.lock) {
WARN("RDC_PDAPn %d is already locked \n", p->index);
return -ENOENT;
}
/* Check if no domain assigned */
if (p->domains == 0)
return -EINVAL;
reg |= p->domains;
/* Check if SREQ is needed */
for (i = 0; i < 7; i += 2)
multi_domain += ((p->domains >> i) & 0x3) ? 1 : 0;
if (multi_domain > 1)
reg |= RDC_PDAP_SREQ_MASK;
/* Setup Lock from input */
reg |= p->lock << RDC_PDAP_LCK_SHIFT;
NOTICE("imx_rdc_set_pdap(): write addr=0x%p, reg=0x%x\n",
&imx_rdc->pdap[p->index], reg);
mmio_write_32((uintptr_t)&imx_rdc->pdap[p->index], reg);
return 0;
}
/*
* Setup RDC settings for multiple peripherals
*/
int imx_rdc_set_peripherals(struct rdc_pdap_conf *peripherals_list,
uint32_t count)
{
int i, ret;
for (i = 0; i < count; i++) {
ret = imx_rdc_set_pdap(&peripherals_list[i]);
if (ret)
return ret;
}
return 0;
}
/*
* Read RDC setting for one master
* For the given index in p.index it returns the lock bit
* and the domain field into p structure.
*/
int imx_rdc_get_mda(struct rdc_mda_conf *p)
{
struct imx_rdc_regs *imx_rdc = (struct imx_rdc_regs *)IMX_RDC_BASE;
uint32_t reg = 0;
reg = mmio_read_32((uintptr_t)&imx_rdc->mda[p->index]);
p->domain = reg & RDC_MDA_DID_MASK;
p->lock = (reg & RDC_MDA_LCK_MASK) >> RDC_MDA_LCK_SHIFT;
return 0;
}
/*
* Write RDC setting for one master
*/
int imx_rdc_set_mda(struct rdc_mda_conf *p)
{
struct imx_rdc_regs *imx_rdc = (struct imx_rdc_regs *)IMX_RDC_BASE;
struct rdc_mda_conf r;
uint32_t reg = 0;
int ret = 0;
/* Check if it is locked */
r.index = p->index;
imx_rdc_get_mda(&r);
if (!r.lock) {
reg = (p->domain & RDC_MDA_DID_MASK)
| ((p->lock << RDC_MDA_LCK_SHIFT) & RDC_MDA_LCK_MASK);
NOTICE("imx_rdc_setup_mda(): write addr=%p, reg=0x%x\n",
&imx_rdc->mda[p->index], reg);
mmio_write_32((uintptr_t)&imx_rdc->mda[p->index], reg);
} else {
WARN("RDC_MDAn %d is already locked \n", p->index);
ret = -ENOENT;
}
return ret;
}
/*
* Setup RDC settings for multiple masters
*/
int imx_rdc_set_masters(struct rdc_mda_conf *masters_list, uint32_t count)
{
int i, ret;
for (i = 0; i < count; i++) {
ret = imx_rdc_set_mda(&masters_list[i]);
if (ret)
break;
}
return ret;
}
#if defined (CSU_RDC_TEST)
/* Default peripherals settings as an example */
static struct rdc_pdap_conf periph_config[] = {
{RDC_PDAP_CSU, 0x30, 0},
};
/* Default masters settings as an example */
static struct rdc_mda_conf masters_config[] = {
{RDC_MDA_A53, 0, 0},
};
#else
/* Default peripherals settings as an example */
static struct rdc_pdap_conf periph_config[] = {
{RDC_PDAP_GPIO1, 0x3, 0},
{RDC_PDAP_GPIO2, 0x3, 0},
{RDC_PDAP_GPIO3, 0x3, 0},
{RDC_PDAP_GPIO4, 0x3, 0},
{RDC_PDAP_GPIO5, 0x3, 0},
};
/* Default masters settings as an example */
static struct rdc_mda_conf masters_config[] = {
{RDC_MDA_A53, 0, 0},
{RDC_MDA_CAAM, 0, 0},
};
#endif
void imx_rdc_set_peripherals_default(void)
{
imx_rdc_set_peripherals(periph_config, ARRAY_SIZE(periph_config));
}
void imx_rdc_set_masters_default(void)
{
imx_rdc_set_masters(masters_config, ARRAY_SIZE(masters_config));
}
#if defined (CSU_RDC_TEST)
void rdc_test(void)
{
imx_rdc_set_peripherals_default();
imx_rdc_set_masters_default();
}
#endif