1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) 2016 Freescale Semiconductor, Inc.
4  */
5 #include <asm/io.h>
6 #include <asm/arch/imx-regs.h>
7 #include <asm/mach-imx/rdc-sema.h>
8 #include <asm/arch/imx-rdc.h>
9 #include <linux/errno.h>
10 
11 /*
12  * Check if the RDC Semaphore is required for this peripheral.
13  */
imx_rdc_check_sema_required(int per_id)14 static 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  */
imx_rdc_check_permission(int per_id,int dom_id)33 int 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  */
imx_rdc_sema_lock(int per_id)48 int 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  */
imx_rdc_sema_unlock(int per_id)78 int 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)
95 		return -EACCES;	/*Not the semaphore owner */
96 
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  */
imx_rdc_setup_peri(rdc_peri_cfg_t p)105 int 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  */
imx_rdc_setup_peripherals(rdc_peri_cfg_t const * peripherals_list,unsigned count)135 int 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  */
imx_rdc_setup_ma(rdc_ma_cfg_t p)154 int 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  */
imx_rdc_setup_masters(rdc_ma_cfg_t const * masters_list,unsigned count)168 int 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 }
182