]>
Commit | Line | Data |
---|---|---|
de09c43b PF |
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> | |
552a848e | 9 | #include <asm/mach-imx/rdc-sema.h> |
de09c43b | 10 | #include <asm/arch/imx-rdc.h> |
5d97dff0 | 11 | #include <linux/errno.h> |
de09c43b PF |
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) | |
354fa867 | 97 | return -EACCES; /*Not the semaphore owner */ |
de09c43b PF |
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 | } |