Commit de09c43bbfeeae767a8561d2810df55675e8b1a4
Committed by
Stefano Babic
1 parent
613e01065a
Exists in
v2017.01-smarct4x
and in
30 other branches
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
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
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__*/ |