Commit de09c43bbfeeae767a8561d2810df55675e8b1a4

Authored by Peng Fan
Committed by Stefano Babic
1 parent 613e01065a

imx: imx-common: introduce Resource Domain Controller support

Introduce Resource Domain Controller support for i.MX.
Now i.MX6SX and i.MX7D supports this feature to assign masters
and peripherals to different domains.

Signed-off-by: Ye.Li <ye.li@nxp.com>
Signed-off-by: Peng Fan <peng.fan@nxp.com>

Showing 5 changed files with 304 additions and 0 deletions Side-by-side Diff

arch/arm/imx-common/Kconfig
... ... @@ -3,4 +3,12 @@
3 3  
4 4 config ROM_UNIFIED_SECTIONS
5 5 bool
  6 +
  7 +config IMX_RDC
  8 + bool "i.MX Resource domain controller driver"
  9 + depends on ARCH_MX6 || ARCH_MX7
  10 + help
  11 + i.MX Resource domain controller is used to assign masters
  12 + and peripherals to differet domains. This can be used to
  13 + isolate resources.
arch/arm/imx-common/Makefile
... ... @@ -27,6 +27,7 @@
27 27 obj-y += cache.o init.o
28 28 obj-$(CONFIG_CMD_SATA) += sata.o
29 29 obj-$(CONFIG_IMX_VIDEO_SKIP) += video.o
  30 +obj-$(CONFIG_IMX_RDC) += rdc-sema.o
30 31 obj-$(CONFIG_SECURE_BOOT) += hab.o
31 32 endif
32 33 ifeq ($(SOC),$(filter $(SOC),vf610))
arch/arm/imx-common/rdc-sema.c
  1 +/*
  2 + * Copyright (C) 2016 Freescale Semiconductor, Inc.
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +#include <common.h>
  7 +#include <asm/io.h>
  8 +#include <asm/arch/imx-regs.h>
  9 +#include <asm/imx-common/rdc-sema.h>
  10 +#include <asm/arch/imx-rdc.h>
  11 +#include <asm-generic/errno.h>
  12 +
  13 +/*
  14 + * Check if the RDC Semaphore is required for this peripheral.
  15 + */
  16 +static inline int imx_rdc_check_sema_required(int per_id)
  17 +{
  18 + struct rdc_regs *imx_rdc = (struct rdc_regs *)RDC_BASE_ADDR;
  19 + u32 reg;
  20 +
  21 + reg = readl(&imx_rdc->pdap[per_id]);
  22 + /*
  23 + * No semaphore:
  24 + * Intial value or this peripheral is assigned to only one domain
  25 + */
  26 + if (!(reg & RDC_PDAP_SREQ_MASK))
  27 + return -ENOENT;
  28 +
  29 + return 0;
  30 +}
  31 +
  32 +/*
  33 + * Check the peripheral read / write access permission on Domain [dom_id].
  34 + */
  35 +int imx_rdc_check_permission(int per_id, int dom_id)
  36 +{
  37 + struct rdc_regs *imx_rdc = (struct rdc_regs *)RDC_BASE_ADDR;
  38 + u32 reg;
  39 +
  40 + reg = readl(&imx_rdc->pdap[per_id]);
  41 + if (!(reg & RDC_PDAP_DRW_MASK(dom_id)))
  42 + return -EACCES; /*No access*/
  43 +
  44 + return 0;
  45 +}
  46 +
  47 +/*
  48 + * Lock up the RDC semaphore for this peripheral if semaphore is required.
  49 + */
  50 +int imx_rdc_sema_lock(int per_id)
  51 +{
  52 + struct rdc_sema_regs *imx_rdc_sema;
  53 + int ret;
  54 + u8 reg;
  55 +
  56 + ret = imx_rdc_check_sema_required(per_id);
  57 + if (ret)
  58 + return ret;
  59 +
  60 + if (per_id < SEMA_GATES_NUM)
  61 + imx_rdc_sema = (struct rdc_sema_regs *)SEMAPHORE1_BASE_ADDR;
  62 + else
  63 + imx_rdc_sema = (struct rdc_sema_regs *)SEMAPHORE2_BASE_ADDR;
  64 +
  65 + do {
  66 + writeb(RDC_SEMA_PROC_ID,
  67 + &imx_rdc_sema->gate[per_id % SEMA_GATES_NUM]);
  68 + reg = readb(&imx_rdc_sema->gate[per_id % SEMA_GATES_NUM]);
  69 + if ((reg & RDC_SEMA_GATE_GTFSM_MASK) == RDC_SEMA_PROC_ID)
  70 + break; /* Get the Semaphore*/
  71 + } while (1);
  72 +
  73 + return 0;
  74 +}
  75 +
  76 +/*
  77 + * Unlock the RDC semaphore for this peripheral if main CPU is the
  78 + * semaphore owner.
  79 + */
  80 +int imx_rdc_sema_unlock(int per_id)
  81 +{
  82 + struct rdc_sema_regs *imx_rdc_sema;
  83 + int ret;
  84 + u8 reg;
  85 +
  86 + ret = imx_rdc_check_sema_required(per_id);
  87 + if (ret)
  88 + return ret;
  89 +
  90 + if (per_id < SEMA_GATES_NUM)
  91 + imx_rdc_sema = (struct rdc_sema_regs *)SEMAPHORE1_BASE_ADDR;
  92 + else
  93 + imx_rdc_sema = (struct rdc_sema_regs *)SEMAPHORE2_BASE_ADDR;
  94 +
  95 + reg = readb(&imx_rdc_sema->gate[per_id % SEMA_GATES_NUM]);
  96 + if ((reg & RDC_SEMA_GATE_GTFSM_MASK) != RDC_SEMA_PROC_ID)
  97 + return 1; /*Not the semaphore owner */
  98 +
  99 + writeb(0x0, &imx_rdc_sema->gate[per_id % SEMA_GATES_NUM]);
  100 +
  101 + return 0;
  102 +}
  103 +
  104 +/*
  105 + * Setup RDC setting for one peripheral
  106 + */
  107 +int imx_rdc_setup_peri(rdc_peri_cfg_t p)
  108 +{
  109 + struct rdc_regs *imx_rdc = (struct rdc_regs *)RDC_BASE_ADDR;
  110 + u32 reg = 0;
  111 + u32 share_count = 0;
  112 + u32 peri_id = p & RDC_PERI_MASK;
  113 + u32 domain = (p & RDC_DOMAIN_MASK) >> RDC_DOMAIN_SHIFT_BASE;
  114 +
  115 + /* No domain assigned */
  116 + if (domain == 0)
  117 + return -EINVAL;
  118 +
  119 + reg |= domain;
  120 +
  121 + share_count = (domain & 0x3)
  122 + + ((domain >> 2) & 0x3)
  123 + + ((domain >> 4) & 0x3)
  124 + + ((domain >> 6) & 0x3);
  125 +
  126 + if (share_count > 0x3)
  127 + reg |= RDC_PDAP_SREQ_MASK;
  128 +
  129 + writel(reg, &imx_rdc->pdap[peri_id]);
  130 +
  131 + return 0;
  132 +}
  133 +
  134 +/*
  135 + * Setup RDC settings for multiple peripherals
  136 + */
  137 +int imx_rdc_setup_peripherals(rdc_peri_cfg_t const *peripherals_list,
  138 + unsigned count)
  139 +{
  140 + rdc_peri_cfg_t const *p = peripherals_list;
  141 + int i, ret;
  142 +
  143 + for (i = 0; i < count; i++) {
  144 + ret = imx_rdc_setup_peri(*p);
  145 + if (ret)
  146 + return ret;
  147 + p++;
  148 + }
  149 +
  150 + return 0;
  151 +}
  152 +
  153 +/*
  154 + * Setup RDC setting for one master
  155 + */
  156 +int imx_rdc_setup_ma(rdc_ma_cfg_t p)
  157 +{
  158 + struct rdc_regs *imx_rdc = (struct rdc_regs *)RDC_BASE_ADDR;
  159 + u32 master_id = (p & RDC_MASTER_MASK) >> RDC_MASTER_SHIFT;
  160 + u32 domain = (p & RDC_DOMAIN_MASK) >> RDC_DOMAIN_SHIFT_BASE;
  161 +
  162 + writel((domain & RDC_MDA_DID_MASK), &imx_rdc->mda[master_id]);
  163 +
  164 + return 0;
  165 +}
  166 +
  167 +/*
  168 + * Setup RDC settings for multiple masters
  169 + */
  170 +int imx_rdc_setup_masters(rdc_ma_cfg_t const *masters_list, unsigned count)
  171 +{
  172 + rdc_ma_cfg_t const *p = masters_list;
  173 + int i, ret;
  174 +
  175 + for (i = 0; i < count; i++) {
  176 + ret = imx_rdc_setup_ma(*p);
  177 + if (ret)
  178 + return ret;
  179 + p++;
  180 + }
  181 +
  182 + return 0;
  183 +}
arch/arm/include/asm/arch-mx6/imx-rdc.h
  1 +/*
  2 + * Copyright (C) 2016 Freescale Semiconductor, Inc.
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#ifndef __IMX_RDC_H__
  8 +#define __IMX_RDC_H__
  9 +
  10 +#error "Please select cpu"
  11 +
  12 +#endif /* __IMX_RDC_H__*/
arch/arm/include/asm/imx-common/rdc-sema.h
  1 +/*
  2 + * Copyright (C) 2016 Freescale Semiconductor, Inc.
  3 + *
  4 + * SPDX-License-Identifier: GPL-2.0+
  5 + */
  6 +
  7 +#ifndef __RDC_SEMA_H__
  8 +#define __RDC_SEMA_H__
  9 +
  10 +/*
  11 + * rdc_peri_cfg_t and rdc_ma_cft_t use the same layout.
  12 + *
  13 + * [ 23 22 | 21 20 | 19 18 | 17 16 ] | [ 15 - 8 ] | [ 7 - 0 ]
  14 + * d3 d2 d1 d0 | master id | peri id
  15 + * d[x] means domain[x], x can be [3 - 0].
  16 + */
  17 +typedef u32 rdc_peri_cfg_t;
  18 +typedef u32 rdc_ma_cfg_t;
  19 +
  20 +#define RDC_PERI_SHIFT 0
  21 +#define RDC_PERI_MASK 0xFF
  22 +
  23 +#define RDC_DOMAIN_SHIFT_BASE 16
  24 +#define RDC_DOMAIN_MASK 0xFF0000
  25 +#define RDC_DOMAIN_SHIFT(x) (RDC_DOMAIN_SHIFT_BASE + ((x << 1)))
  26 +#define RDC_DOMAIN(x) ((rdc_peri_cfg_t)(0x3 << RDC_DOMAIN_SHIFT(x)))
  27 +
  28 +#define RDC_MASTER_SHIFT 8
  29 +#define RDC_MASTER_MASK 0xFF00
  30 +#define RDC_MASTER_CFG(master_id, domain_id) (rdc_ma_cfg_t)((master_id << 8) | \
  31 + (domain_id << RDC_DOMAIN_SHIFT_BASE))
  32 +
  33 +/* The Following macro definitions are common to i.MX6SX and i.MX7D */
  34 +#define SEMA_GATES_NUM 64
  35 +
  36 +#define RDC_MDA_DID_SHIFT 0
  37 +#define RDC_MDA_DID_MASK (0x3 << RDC_MDA_DID_SHIFT)
  38 +#define RDC_MDA_LCK_SHIFT 31
  39 +#define RDC_MDA_LCK_MASK (0x1 << RDC_MDA_LCK_SHIFT)
  40 +
  41 +#define RDC_PDAP_DW_SHIFT(domain) ((domain) << 1)
  42 +#define RDC_PDAP_DR_SHIFT(domain) (1 + RDC_PDAP_DW_SHIFT(domain))
  43 +#define RDC_PDAP_DW_MASK(domain) (1 << RDC_PDAP_DW_SHIFT(domain))
  44 +#define RDC_PDAP_DR_MASK(domain) (1 << RDC_PDAP_DR_SHIFT(domain))
  45 +#define RDC_PDAP_DRW_MASK(domain) (RDC_PDAP_DW_MASK(domain) | \
  46 + RDC_PDAP_DR_MASK(domain))
  47 +
  48 +#define RDC_PDAP_SREQ_SHIFT 30
  49 +#define RDC_PDAP_SREQ_MASK (0x1 << RDC_PDAP_SREQ_SHIFT)
  50 +#define RDC_PDAP_LCK_SHIFT 31
  51 +#define RDC_PDAP_LCK_MASK (0x1 << RDC_PDAP_LCK_SHIFT)
  52 +
  53 +#define RDC_MRSA_SADR_SHIFT 7
  54 +#define RDC_MRSA_SADR_MASK (0x1ffffff << RDC_MRSA_SADR_SHIFT)
  55 +
  56 +#define RDC_MREA_EADR_SHIFT 7
  57 +#define RDC_MREA_EADR_MASK (0x1ffffff << RDC_MREA_EADR_SHIFT)
  58 +
  59 +#define RDC_MRC_DW_SHIFT(domain) (domain)
  60 +#define RDC_MRC_DR_SHIFT(domain) (1 + RDC_MRC_DW_SHIFT(domain))
  61 +#define RDC_MRC_DW_MASK(domain) (1 << RDC_MRC_DW_SHIFT(domain))
  62 +#define RDC_MRC_DR_MASK(domain) (1 << RDC_MRC_DR_SHIFT(domain))
  63 +#define RDC_MRC_DRW_MASK(domain) (RDC_MRC_DW_MASK(domain) | \
  64 + RDC_MRC_DR_MASK(domain))
  65 +#define RDC_MRC_ENA_SHIFT 30
  66 +#define RDC_MRC_ENA_MASK (0x1 << RDC_MRC_ENA_SHIFT)
  67 +#define RDC_MRC_LCK_SHIFT 31
  68 +#define RDC_MRC_LCK_MASK (0x1 << RDC_MRC_LCK_SHIFT)
  69 +
  70 +#define RDC_MRVS_VDID_SHIFT 0
  71 +#define RDC_MRVS_VDID_MASK (0x3 << RDC_MRVS_VDID_SHIFT)
  72 +#define RDC_MRVS_AD_SHIFT 4
  73 +#define RDC_MRVS_AD_MASK (0x1 << RDC_MRVS_AD_SHIFT)
  74 +#define RDC_MRVS_VADDR_SHIFT 5
  75 +#define RDC_MRVS_VADDR_MASK (0x7ffffff << RDC_MRVS_VADDR_SHIFT)
  76 +
  77 +#define RDC_SEMA_GATE_GTFSM_SHIFT 0
  78 +#define RDC_SEMA_GATE_GTFSM_MASK (0xf << RDC_SEMA_GATE_GTFSM_SHIFT)
  79 +#define RDC_SEMA_GATE_LDOM_SHIFT 5
  80 +#define RDC_SEMA_GATE_LDOM_MASK (0x3 << RDC_SEMA_GATE_LDOM_SHIFT)
  81 +
  82 +#define RDC_SEMA_RSTGT_RSTGDP_SHIFT 0
  83 +#define RDC_SEMA_RSTGT_RSTGDP_MASK (0xff << RDC_SEMA_RSTGT_RSTGDP_SHIFT)
  84 +#define RDC_SEMA_RSTGT_RSTGSM_SHIFT 2
  85 +#define RDC_SEMA_RSTGT_RSTGSM_MASK (0x3 << RDC_SEMA_RSTGT_RSTGSM_SHIFT)
  86 +#define RDC_SEMA_RSTGT_RSTGMS_SHIFT 4
  87 +#define RDC_SEMA_RSTGT_RSTGMS_MASK (0xf << RDC_SEMA_RSTGT_RSTGMS_SHIFT)
  88 +#define RDC_SEMA_RSTGT_RSTGTN_SHIFT 8
  89 +#define RDC_SEMA_RSTGT_RSTGTN_MASK (0xff << RDC_SEMA_RSTGT_RSTGTN_SHIFT)
  90 +
  91 +int imx_rdc_check_permission(int per_id, int dom_id);
  92 +int imx_rdc_sema_lock(int per_id);
  93 +int imx_rdc_sema_unlock(int per_id);
  94 +int imx_rdc_setup_peri(rdc_peri_cfg_t p);
  95 +int imx_rdc_setup_peripherals(rdc_peri_cfg_t const *peripherals_list,
  96 + unsigned count);
  97 +int imx_rdc_setup_ma(rdc_ma_cfg_t p);
  98 +int imx_rdc_setup_masters(rdc_ma_cfg_t const *masters_list, unsigned count);
  99 +
  100 +#endif /* __RDC_SEMA_H__*/