blob: 56725cc109f0cae07a34e170b04fb95ed6f89362 [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Peng Fan1b64ffa2016-01-28 16:55:00 +08002/*
3 * Copyright (C) 2016 Freescale Semiconductor, Inc.
Peng Fan1b64ffa2016-01-28 16:55:00 +08004 */
Peng Fan1b64ffa2016-01-28 16:55:00 +08005#include <asm/io.h>
6#include <asm/arch/imx-regs.h>
Stefano Babic33731bc2017-06-29 10:16:06 +02007#include <asm/mach-imx/rdc-sema.h>
Peng Fan1b64ffa2016-01-28 16:55:00 +08008#include <asm/arch/imx-rdc.h>
Masahiro Yamada64e4f7f2016-09-21 11:28:57 +09009#include <linux/errno.h>
Peng Fan1b64ffa2016-01-28 16:55:00 +080010
11/*
12 * Check if the RDC Semaphore is required for this peripheral.
13 */
14static inline int imx_rdc_check_sema_required(int per_id)
15{
16 struct rdc_regs *imx_rdc = (struct rdc_regs *)RDC_BASE_ADDR;
17 u32 reg;
18
19 reg = readl(&imx_rdc->pdap[per_id]);
20 /*
21 * No semaphore:
22 * Intial value or this peripheral is assigned to only one domain
23 */
24 if (!(reg & RDC_PDAP_SREQ_MASK))
25 return -ENOENT;
26
27 return 0;
28}
29
30/*
31 * Check the peripheral read / write access permission on Domain [dom_id].
32 */
33int imx_rdc_check_permission(int per_id, int dom_id)
34{
35 struct rdc_regs *imx_rdc = (struct rdc_regs *)RDC_BASE_ADDR;
36 u32 reg;
37
38 reg = readl(&imx_rdc->pdap[per_id]);
39 if (!(reg & RDC_PDAP_DRW_MASK(dom_id)))
40 return -EACCES; /*No access*/
41
42 return 0;
43}
44
45/*
46 * Lock up the RDC semaphore for this peripheral if semaphore is required.
47 */
48int imx_rdc_sema_lock(int per_id)
49{
50 struct rdc_sema_regs *imx_rdc_sema;
51 int ret;
52 u8 reg;
53
54 ret = imx_rdc_check_sema_required(per_id);
55 if (ret)
56 return ret;
57
58 if (per_id < SEMA_GATES_NUM)
59 imx_rdc_sema = (struct rdc_sema_regs *)SEMAPHORE1_BASE_ADDR;
60 else
61 imx_rdc_sema = (struct rdc_sema_regs *)SEMAPHORE2_BASE_ADDR;
62
63 do {
64 writeb(RDC_SEMA_PROC_ID,
65 &imx_rdc_sema->gate[per_id % SEMA_GATES_NUM]);
66 reg = readb(&imx_rdc_sema->gate[per_id % SEMA_GATES_NUM]);
67 if ((reg & RDC_SEMA_GATE_GTFSM_MASK) == RDC_SEMA_PROC_ID)
68 break; /* Get the Semaphore*/
69 } while (1);
70
71 return 0;
72}
73
74/*
75 * Unlock the RDC semaphore for this peripheral if main CPU is the
76 * semaphore owner.
77 */
78int imx_rdc_sema_unlock(int per_id)
79{
80 struct rdc_sema_regs *imx_rdc_sema;
81 int ret;
82 u8 reg;
83
84 ret = imx_rdc_check_sema_required(per_id);
85 if (ret)
86 return ret;
87
88 if (per_id < SEMA_GATES_NUM)
89 imx_rdc_sema = (struct rdc_sema_regs *)SEMAPHORE1_BASE_ADDR;
90 else
91 imx_rdc_sema = (struct rdc_sema_regs *)SEMAPHORE2_BASE_ADDR;
92
93 reg = readb(&imx_rdc_sema->gate[per_id % SEMA_GATES_NUM]);
94 if ((reg & RDC_SEMA_GATE_GTFSM_MASK) != RDC_SEMA_PROC_ID)
Peng Fana8317a42017-04-21 16:56:50 +080095 return -EACCES; /*Not the semaphore owner */
Peng Fan1b64ffa2016-01-28 16:55:00 +080096
97 writeb(0x0, &imx_rdc_sema->gate[per_id % SEMA_GATES_NUM]);
98
99 return 0;
100}
101
102/*
103 * Setup RDC setting for one peripheral
104 */
105int imx_rdc_setup_peri(rdc_peri_cfg_t p)
106{
107 struct rdc_regs *imx_rdc = (struct rdc_regs *)RDC_BASE_ADDR;
108 u32 reg = 0;
109 u32 share_count = 0;
110 u32 peri_id = p & RDC_PERI_MASK;
111 u32 domain = (p & RDC_DOMAIN_MASK) >> RDC_DOMAIN_SHIFT_BASE;
112
113 /* No domain assigned */
114 if (domain == 0)
115 return -EINVAL;
116
117 reg |= domain;
118
119 share_count = (domain & 0x3)
120 + ((domain >> 2) & 0x3)
121 + ((domain >> 4) & 0x3)
122 + ((domain >> 6) & 0x3);
123
124 if (share_count > 0x3)
125 reg |= RDC_PDAP_SREQ_MASK;
126
127 writel(reg, &imx_rdc->pdap[peri_id]);
128
129 return 0;
130}
131
132/*
133 * Setup RDC settings for multiple peripherals
134 */
135int imx_rdc_setup_peripherals(rdc_peri_cfg_t const *peripherals_list,
136 unsigned count)
137{
138 rdc_peri_cfg_t const *p = peripherals_list;
139 int i, ret;
140
141 for (i = 0; i < count; i++) {
142 ret = imx_rdc_setup_peri(*p);
143 if (ret)
144 return ret;
145 p++;
146 }
147
148 return 0;
149}
150
151/*
152 * Setup RDC setting for one master
153 */
154int imx_rdc_setup_ma(rdc_ma_cfg_t p)
155{
156 struct rdc_regs *imx_rdc = (struct rdc_regs *)RDC_BASE_ADDR;
157 u32 master_id = (p & RDC_MASTER_MASK) >> RDC_MASTER_SHIFT;
158 u32 domain = (p & RDC_DOMAIN_MASK) >> RDC_DOMAIN_SHIFT_BASE;
159
160 writel((domain & RDC_MDA_DID_MASK), &imx_rdc->mda[master_id]);
161
162 return 0;
163}
164
165/*
166 * Setup RDC settings for multiple masters
167 */
168int imx_rdc_setup_masters(rdc_ma_cfg_t const *masters_list, unsigned count)
169{
170 rdc_ma_cfg_t const *p = masters_list;
171 int i, ret;
172
173 for (i = 0; i < count; i++) {
174 ret = imx_rdc_setup_ma(*p);
175 if (ret)
176 return ret;
177 p++;
178 }
179
180 return 0;
181}