/* * Copyright 2017 NXP * * SPDX-License-Identifier: BSD-3-Clause */ #include #include #include #include #include #include #include #include /* * 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