xref: /openbmc/linux/arch/powerpc/sysdev/cpm2.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b5677d84SJochen Friedrich /*
2b5677d84SJochen Friedrich  * General Purpose functions for the global management of the
3b5677d84SJochen Friedrich  * 8260 Communication Processor Module.
4b5677d84SJochen Friedrich  * Copyright (c) 1999-2001 Dan Malek <dan@embeddedalley.com>
5b5677d84SJochen Friedrich  * Copyright (c) 2000 MontaVista Software, Inc (source@mvista.com)
6b5677d84SJochen Friedrich  *	2.3.99 Updates
7b5677d84SJochen Friedrich  *
8b5677d84SJochen Friedrich  * 2006 (c) MontaVista Software, Inc.
9b5677d84SJochen Friedrich  * Vitaly Bordug <vbordug@ru.mvista.com>
10b5677d84SJochen Friedrich  * 	Merged to arch/powerpc from arch/ppc/syslib/cpm2_common.c
11b5677d84SJochen Friedrich  *
12b5677d84SJochen Friedrich  * This file is licensed under the terms of the GNU General Public License
13b5677d84SJochen Friedrich  * version 2. This program is licensed "as is" without any warranty of any
14b5677d84SJochen Friedrich  * kind, whether express or implied.
15b5677d84SJochen Friedrich  */
16b5677d84SJochen Friedrich 
17b5677d84SJochen Friedrich /*
18b5677d84SJochen Friedrich  *
19b5677d84SJochen Friedrich  * In addition to the individual control of the communication
20b5677d84SJochen Friedrich  * channels, there are a few functions that globally affect the
21b5677d84SJochen Friedrich  * communication processor.
22b5677d84SJochen Friedrich  *
23b5677d84SJochen Friedrich  * Buffer descriptors must be allocated from the dual ported memory
24b5677d84SJochen Friedrich  * space.  The allocator for that is here.  When the communication
25b5677d84SJochen Friedrich  * process is reset, we reclaim the memory available.  There is
26b5677d84SJochen Friedrich  * currently no deallocator for this memory.
27b5677d84SJochen Friedrich  */
28b5677d84SJochen Friedrich #include <linux/errno.h>
29b5677d84SJochen Friedrich #include <linux/sched.h>
30b5677d84SJochen Friedrich #include <linux/kernel.h>
31b5677d84SJochen Friedrich #include <linux/param.h>
32b5677d84SJochen Friedrich #include <linux/string.h>
33b5677d84SJochen Friedrich #include <linux/mm.h>
34b5677d84SJochen Friedrich #include <linux/interrupt.h>
35b5677d84SJochen Friedrich #include <linux/module.h>
36b5677d84SJochen Friedrich #include <linux/of.h>
37b5677d84SJochen Friedrich 
38b5677d84SJochen Friedrich #include <asm/io.h>
39b5677d84SJochen Friedrich #include <asm/irq.h>
40b5677d84SJochen Friedrich #include <asm/page.h>
41b5677d84SJochen Friedrich #include <asm/cpm2.h>
42b5677d84SJochen Friedrich #include <asm/rheap.h>
43b5677d84SJochen Friedrich 
44b5677d84SJochen Friedrich #include <sysdev/fsl_soc.h>
45b5677d84SJochen Friedrich 
46b5677d84SJochen Friedrich cpm_cpm2_t __iomem *cpmp; /* Pointer to comm processor space */
47b5677d84SJochen Friedrich 
48b5677d84SJochen Friedrich /* We allocate this here because it is used almost exclusively for
49b5677d84SJochen Friedrich  * the communication processor devices.
50b5677d84SJochen Friedrich  */
51b5677d84SJochen Friedrich cpm2_map_t __iomem *cpm2_immr;
526e27cca9SGrant Likely EXPORT_SYMBOL(cpm2_immr);
53b5677d84SJochen Friedrich 
54b5677d84SJochen Friedrich #define CPM_MAP_SIZE	(0x40000)	/* 256k - the PQ3 reserve this amount
55b5677d84SJochen Friedrich 					   of space for CPM as it is larger
56b5677d84SJochen Friedrich 					   than on PQ2 */
57b5677d84SJochen Friedrich 
cpm2_reset(void)58b5677d84SJochen Friedrich void __init cpm2_reset(void)
59b5677d84SJochen Friedrich {
60b5677d84SJochen Friedrich #ifdef CONFIG_PPC_85xx
61ca851c78SKumar Gala 	cpm2_immr = ioremap(get_immrbase() + 0x80000, CPM_MAP_SIZE);
62b5677d84SJochen Friedrich #else
63b5677d84SJochen Friedrich 	cpm2_immr = ioremap(get_immrbase(), CPM_MAP_SIZE);
64b5677d84SJochen Friedrich #endif
65b5677d84SJochen Friedrich 
66b5677d84SJochen Friedrich 	/* Tell everyone where the comm processor resides.
67b5677d84SJochen Friedrich 	 */
68b5677d84SJochen Friedrich 	cpmp = &cpm2_immr->im_cpm;
69872a15deSLaurent Pinchart 
70872a15deSLaurent Pinchart #ifndef CONFIG_PPC_EARLY_DEBUG_CPM
71872a15deSLaurent Pinchart 	/* Reset the CPM.
72872a15deSLaurent Pinchart 	 */
73872a15deSLaurent Pinchart 	cpm_command(CPM_CR_RST, 0);
74872a15deSLaurent Pinchart #endif
75b5677d84SJochen Friedrich }
76b5677d84SJochen Friedrich 
77b5677d84SJochen Friedrich static DEFINE_SPINLOCK(cmd_lock);
78b5677d84SJochen Friedrich 
79b5677d84SJochen Friedrich #define MAX_CR_CMD_LOOPS        10000
80b5677d84SJochen Friedrich 
cpm_command(u32 command,u8 opcode)81b5677d84SJochen Friedrich int cpm_command(u32 command, u8 opcode)
82b5677d84SJochen Friedrich {
83b5677d84SJochen Friedrich 	int i, ret;
84b5677d84SJochen Friedrich 	unsigned long flags;
85b5677d84SJochen Friedrich 
86b5677d84SJochen Friedrich 	spin_lock_irqsave(&cmd_lock, flags);
87b5677d84SJochen Friedrich 
88b5677d84SJochen Friedrich 	ret = 0;
89b5677d84SJochen Friedrich 	out_be32(&cpmp->cp_cpcr, command | opcode | CPM_CR_FLG);
90b5677d84SJochen Friedrich 	for (i = 0; i < MAX_CR_CMD_LOOPS; i++)
91b5677d84SJochen Friedrich 		if ((in_be32(&cpmp->cp_cpcr) & CPM_CR_FLG) == 0)
92b5677d84SJochen Friedrich 			goto out;
93b5677d84SJochen Friedrich 
94e48b1b45SHarvey Harrison 	printk(KERN_ERR "%s(): Not able to issue CPM command\n", __func__);
95b5677d84SJochen Friedrich 	ret = -EIO;
96b5677d84SJochen Friedrich out:
97b5677d84SJochen Friedrich 	spin_unlock_irqrestore(&cmd_lock, flags);
98b5677d84SJochen Friedrich 	return ret;
99b5677d84SJochen Friedrich }
100b5677d84SJochen Friedrich EXPORT_SYMBOL(cpm_command);
101b5677d84SJochen Friedrich 
102b5677d84SJochen Friedrich /* Set a baud rate generator.  This needs lots of work.  There are
103b5677d84SJochen Friedrich  * eight BRGs, which can be connected to the CPM channels or output
104b5677d84SJochen Friedrich  * as clocks.  The BRGs are in two different block of internal
105b5677d84SJochen Friedrich  * memory mapped space.
106b5677d84SJochen Friedrich  * The baud rate clock is the system clock divided by something.
107b5677d84SJochen Friedrich  * It was set up long ago during the initial boot phase and is
108738f9dcaSJason Wang  * given to us.
109b5677d84SJochen Friedrich  * Baud rate clocks are zero-based in the driver code (as that maps
110b5677d84SJochen Friedrich  * to port numbers).  Documentation uses 1-based numbering.
111b5677d84SJochen Friedrich  */
__cpm2_setbrg(uint brg,uint rate,uint clk,int div16,int src)112dddb8d31SLaurent Pinchart void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src)
113b5677d84SJochen Friedrich {
114b5677d84SJochen Friedrich 	u32 __iomem *bp;
115dddb8d31SLaurent Pinchart 	u32 val;
116b5677d84SJochen Friedrich 
117b5677d84SJochen Friedrich 	/* This is good enough to get SMCs running.....
118b5677d84SJochen Friedrich 	*/
119b5677d84SJochen Friedrich 	if (brg < 4) {
120*7768716dSChristophe Leroy 		bp = &cpm2_immr->im_brgc1;
121b5677d84SJochen Friedrich 	} else {
122*7768716dSChristophe Leroy 		bp = &cpm2_immr->im_brgc5;
123b5677d84SJochen Friedrich 		brg -= 4;
124b5677d84SJochen Friedrich 	}
125b5677d84SJochen Friedrich 	bp += brg;
1267b890994SLaurent Pinchart 	/* Round the clock divider to the nearest integer. */
1277b890994SLaurent Pinchart 	val = (((clk * 2 / rate) - 1) & ~1) | CPM_BRG_EN | src;
128b5677d84SJochen Friedrich 	if (div16)
129b5677d84SJochen Friedrich 		val |= CPM_BRG_DIV16;
130b5677d84SJochen Friedrich 
131b5677d84SJochen Friedrich 	out_be32(bp, val);
132b5677d84SJochen Friedrich }
133dddb8d31SLaurent Pinchart EXPORT_SYMBOL(__cpm2_setbrg);
134b5677d84SJochen Friedrich 
cpm2_clk_setup(enum cpm_clk_target target,int clock,int mode)1356c552983SNick Child int __init cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode)
136b5677d84SJochen Friedrich {
137b5677d84SJochen Friedrich 	int ret = 0;
138b5677d84SJochen Friedrich 	int shift;
139b5677d84SJochen Friedrich 	int i, bits = 0;
140b5677d84SJochen Friedrich 	u32 __iomem *reg;
141b5677d84SJochen Friedrich 	u32 mask = 7;
142b5677d84SJochen Friedrich 
143b5677d84SJochen Friedrich 	u8 clk_map[][3] = {
144b5677d84SJochen Friedrich 		{CPM_CLK_FCC1, CPM_BRG5, 0},
145b5677d84SJochen Friedrich 		{CPM_CLK_FCC1, CPM_BRG6, 1},
146b5677d84SJochen Friedrich 		{CPM_CLK_FCC1, CPM_BRG7, 2},
147b5677d84SJochen Friedrich 		{CPM_CLK_FCC1, CPM_BRG8, 3},
148b5677d84SJochen Friedrich 		{CPM_CLK_FCC1, CPM_CLK9, 4},
149b5677d84SJochen Friedrich 		{CPM_CLK_FCC1, CPM_CLK10, 5},
150b5677d84SJochen Friedrich 		{CPM_CLK_FCC1, CPM_CLK11, 6},
151b5677d84SJochen Friedrich 		{CPM_CLK_FCC1, CPM_CLK12, 7},
152b5677d84SJochen Friedrich 		{CPM_CLK_FCC2, CPM_BRG5, 0},
153b5677d84SJochen Friedrich 		{CPM_CLK_FCC2, CPM_BRG6, 1},
154b5677d84SJochen Friedrich 		{CPM_CLK_FCC2, CPM_BRG7, 2},
155b5677d84SJochen Friedrich 		{CPM_CLK_FCC2, CPM_BRG8, 3},
156b5677d84SJochen Friedrich 		{CPM_CLK_FCC2, CPM_CLK13, 4},
157b5677d84SJochen Friedrich 		{CPM_CLK_FCC2, CPM_CLK14, 5},
158b5677d84SJochen Friedrich 		{CPM_CLK_FCC2, CPM_CLK15, 6},
159b5677d84SJochen Friedrich 		{CPM_CLK_FCC2, CPM_CLK16, 7},
160b5677d84SJochen Friedrich 		{CPM_CLK_FCC3, CPM_BRG5, 0},
161b5677d84SJochen Friedrich 		{CPM_CLK_FCC3, CPM_BRG6, 1},
162b5677d84SJochen Friedrich 		{CPM_CLK_FCC3, CPM_BRG7, 2},
163b5677d84SJochen Friedrich 		{CPM_CLK_FCC3, CPM_BRG8, 3},
164b5677d84SJochen Friedrich 		{CPM_CLK_FCC3, CPM_CLK13, 4},
165b5677d84SJochen Friedrich 		{CPM_CLK_FCC3, CPM_CLK14, 5},
166b5677d84SJochen Friedrich 		{CPM_CLK_FCC3, CPM_CLK15, 6},
167b5677d84SJochen Friedrich 		{CPM_CLK_FCC3, CPM_CLK16, 7},
168b5677d84SJochen Friedrich 		{CPM_CLK_SCC1, CPM_BRG1, 0},
169b5677d84SJochen Friedrich 		{CPM_CLK_SCC1, CPM_BRG2, 1},
170b5677d84SJochen Friedrich 		{CPM_CLK_SCC1, CPM_BRG3, 2},
171b5677d84SJochen Friedrich 		{CPM_CLK_SCC1, CPM_BRG4, 3},
172b5677d84SJochen Friedrich 		{CPM_CLK_SCC1, CPM_CLK11, 4},
173b5677d84SJochen Friedrich 		{CPM_CLK_SCC1, CPM_CLK12, 5},
174b5677d84SJochen Friedrich 		{CPM_CLK_SCC1, CPM_CLK3, 6},
175b5677d84SJochen Friedrich 		{CPM_CLK_SCC1, CPM_CLK4, 7},
176b5677d84SJochen Friedrich 		{CPM_CLK_SCC2, CPM_BRG1, 0},
177b5677d84SJochen Friedrich 		{CPM_CLK_SCC2, CPM_BRG2, 1},
178b5677d84SJochen Friedrich 		{CPM_CLK_SCC2, CPM_BRG3, 2},
179b5677d84SJochen Friedrich 		{CPM_CLK_SCC2, CPM_BRG4, 3},
180b5677d84SJochen Friedrich 		{CPM_CLK_SCC2, CPM_CLK11, 4},
181b5677d84SJochen Friedrich 		{CPM_CLK_SCC2, CPM_CLK12, 5},
182b5677d84SJochen Friedrich 		{CPM_CLK_SCC2, CPM_CLK3, 6},
183b5677d84SJochen Friedrich 		{CPM_CLK_SCC2, CPM_CLK4, 7},
184b5677d84SJochen Friedrich 		{CPM_CLK_SCC3, CPM_BRG1, 0},
185b5677d84SJochen Friedrich 		{CPM_CLK_SCC3, CPM_BRG2, 1},
186b5677d84SJochen Friedrich 		{CPM_CLK_SCC3, CPM_BRG3, 2},
187b5677d84SJochen Friedrich 		{CPM_CLK_SCC3, CPM_BRG4, 3},
188b5677d84SJochen Friedrich 		{CPM_CLK_SCC3, CPM_CLK5, 4},
189b5677d84SJochen Friedrich 		{CPM_CLK_SCC3, CPM_CLK6, 5},
190b5677d84SJochen Friedrich 		{CPM_CLK_SCC3, CPM_CLK7, 6},
191b5677d84SJochen Friedrich 		{CPM_CLK_SCC3, CPM_CLK8, 7},
192b5677d84SJochen Friedrich 		{CPM_CLK_SCC4, CPM_BRG1, 0},
193b5677d84SJochen Friedrich 		{CPM_CLK_SCC4, CPM_BRG2, 1},
194b5677d84SJochen Friedrich 		{CPM_CLK_SCC4, CPM_BRG3, 2},
195b5677d84SJochen Friedrich 		{CPM_CLK_SCC4, CPM_BRG4, 3},
196b5677d84SJochen Friedrich 		{CPM_CLK_SCC4, CPM_CLK5, 4},
197b5677d84SJochen Friedrich 		{CPM_CLK_SCC4, CPM_CLK6, 5},
198b5677d84SJochen Friedrich 		{CPM_CLK_SCC4, CPM_CLK7, 6},
199b5677d84SJochen Friedrich 		{CPM_CLK_SCC4, CPM_CLK8, 7},
200b5677d84SJochen Friedrich 	};
201b5677d84SJochen Friedrich 
202b5677d84SJochen Friedrich 	switch (target) {
203b5677d84SJochen Friedrich 	case CPM_CLK_SCC1:
204*7768716dSChristophe Leroy 		reg = &cpm2_immr->im_cpmux.cmx_scr;
205b5677d84SJochen Friedrich 		shift = 24;
206025306f3SLaurent Pinchart 		break;
207b5677d84SJochen Friedrich 	case CPM_CLK_SCC2:
208*7768716dSChristophe Leroy 		reg = &cpm2_immr->im_cpmux.cmx_scr;
209b5677d84SJochen Friedrich 		shift = 16;
210b5677d84SJochen Friedrich 		break;
211b5677d84SJochen Friedrich 	case CPM_CLK_SCC3:
212*7768716dSChristophe Leroy 		reg = &cpm2_immr->im_cpmux.cmx_scr;
213b5677d84SJochen Friedrich 		shift = 8;
214b5677d84SJochen Friedrich 		break;
215b5677d84SJochen Friedrich 	case CPM_CLK_SCC4:
216*7768716dSChristophe Leroy 		reg = &cpm2_immr->im_cpmux.cmx_scr;
217b5677d84SJochen Friedrich 		shift = 0;
218b5677d84SJochen Friedrich 		break;
219b5677d84SJochen Friedrich 	case CPM_CLK_FCC1:
220*7768716dSChristophe Leroy 		reg = &cpm2_immr->im_cpmux.cmx_fcr;
221b5677d84SJochen Friedrich 		shift = 24;
222b5677d84SJochen Friedrich 		break;
223b5677d84SJochen Friedrich 	case CPM_CLK_FCC2:
224*7768716dSChristophe Leroy 		reg = &cpm2_immr->im_cpmux.cmx_fcr;
225b5677d84SJochen Friedrich 		shift = 16;
226b5677d84SJochen Friedrich 		break;
227b5677d84SJochen Friedrich 	case CPM_CLK_FCC3:
228*7768716dSChristophe Leroy 		reg = &cpm2_immr->im_cpmux.cmx_fcr;
229b5677d84SJochen Friedrich 		shift = 8;
230b5677d84SJochen Friedrich 		break;
231b5677d84SJochen Friedrich 	default:
232b5677d84SJochen Friedrich 		printk(KERN_ERR "cpm2_clock_setup: invalid clock target\n");
233b5677d84SJochen Friedrich 		return -EINVAL;
234b5677d84SJochen Friedrich 	}
235b5677d84SJochen Friedrich 
236b5677d84SJochen Friedrich 	for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
237b5677d84SJochen Friedrich 		if (clk_map[i][0] == target && clk_map[i][1] == clock) {
238b5677d84SJochen Friedrich 			bits = clk_map[i][2];
239b5677d84SJochen Friedrich 			break;
240b5677d84SJochen Friedrich 		}
241b5677d84SJochen Friedrich 	}
242b5677d84SJochen Friedrich 	if (i == ARRAY_SIZE(clk_map))
243b5677d84SJochen Friedrich 	    ret = -EINVAL;
244b5677d84SJochen Friedrich 
245b5677d84SJochen Friedrich 	bits <<= shift;
246b5677d84SJochen Friedrich 	mask <<= shift;
247b5677d84SJochen Friedrich 
2481cca2d2bSWolfgang Ocker 	if (mode == CPM_CLK_RTX) {
2491cca2d2bSWolfgang Ocker 		bits |= bits << 3;
2501cca2d2bSWolfgang Ocker 		mask |= mask << 3;
2511cca2d2bSWolfgang Ocker 	} else if (mode == CPM_CLK_RX) {
2521cca2d2bSWolfgang Ocker 		bits <<= 3;
2531cca2d2bSWolfgang Ocker 		mask <<= 3;
2541cca2d2bSWolfgang Ocker 	}
2551cca2d2bSWolfgang Ocker 
256b5677d84SJochen Friedrich 	out_be32(reg, (in_be32(reg) & ~mask) | bits);
257b5677d84SJochen Friedrich 
258b5677d84SJochen Friedrich 	return ret;
259b5677d84SJochen Friedrich }
260b5677d84SJochen Friedrich 
cpm2_smc_clk_setup(enum cpm_clk_target target,int clock)2616c552983SNick Child int __init cpm2_smc_clk_setup(enum cpm_clk_target target, int clock)
262b5677d84SJochen Friedrich {
263b5677d84SJochen Friedrich 	int ret = 0;
264b5677d84SJochen Friedrich 	int shift;
265b5677d84SJochen Friedrich 	int i, bits = 0;
266b5677d84SJochen Friedrich 	u8 __iomem *reg;
267b5677d84SJochen Friedrich 	u8 mask = 3;
268b5677d84SJochen Friedrich 
269b5677d84SJochen Friedrich 	u8 clk_map[][3] = {
270b5677d84SJochen Friedrich 		{CPM_CLK_SMC1, CPM_BRG1, 0},
271b5677d84SJochen Friedrich 		{CPM_CLK_SMC1, CPM_BRG7, 1},
272b5677d84SJochen Friedrich 		{CPM_CLK_SMC1, CPM_CLK7, 2},
273b5677d84SJochen Friedrich 		{CPM_CLK_SMC1, CPM_CLK9, 3},
274b5677d84SJochen Friedrich 		{CPM_CLK_SMC2, CPM_BRG2, 0},
275b5677d84SJochen Friedrich 		{CPM_CLK_SMC2, CPM_BRG8, 1},
276b5677d84SJochen Friedrich 		{CPM_CLK_SMC2, CPM_CLK4, 2},
277b5677d84SJochen Friedrich 		{CPM_CLK_SMC2, CPM_CLK15, 3},
278b5677d84SJochen Friedrich 	};
279b5677d84SJochen Friedrich 
280b5677d84SJochen Friedrich 	switch (target) {
281b5677d84SJochen Friedrich 	case CPM_CLK_SMC1:
282*7768716dSChristophe Leroy 		reg = &cpm2_immr->im_cpmux.cmx_smr;
283b5677d84SJochen Friedrich 		mask = 3;
284b5677d84SJochen Friedrich 		shift = 4;
285b5677d84SJochen Friedrich 		break;
286b5677d84SJochen Friedrich 	case CPM_CLK_SMC2:
287*7768716dSChristophe Leroy 		reg = &cpm2_immr->im_cpmux.cmx_smr;
288b5677d84SJochen Friedrich 		mask = 3;
289b5677d84SJochen Friedrich 		shift = 0;
290b5677d84SJochen Friedrich 		break;
291b5677d84SJochen Friedrich 	default:
292b5677d84SJochen Friedrich 		printk(KERN_ERR "cpm2_smc_clock_setup: invalid clock target\n");
293b5677d84SJochen Friedrich 		return -EINVAL;
294b5677d84SJochen Friedrich 	}
295b5677d84SJochen Friedrich 
296b5677d84SJochen Friedrich 	for (i = 0; i < ARRAY_SIZE(clk_map); i++) {
297b5677d84SJochen Friedrich 		if (clk_map[i][0] == target && clk_map[i][1] == clock) {
298b5677d84SJochen Friedrich 			bits = clk_map[i][2];
299b5677d84SJochen Friedrich 			break;
300b5677d84SJochen Friedrich 		}
301b5677d84SJochen Friedrich 	}
302b5677d84SJochen Friedrich 	if (i == ARRAY_SIZE(clk_map))
303b5677d84SJochen Friedrich 	    ret = -EINVAL;
304b5677d84SJochen Friedrich 
305b5677d84SJochen Friedrich 	bits <<= shift;
306b5677d84SJochen Friedrich 	mask <<= shift;
307b5677d84SJochen Friedrich 
308b5677d84SJochen Friedrich 	out_8(reg, (in_8(reg) & ~mask) | bits);
309b5677d84SJochen Friedrich 
310b5677d84SJochen Friedrich 	return ret;
311b5677d84SJochen Friedrich }
312b5677d84SJochen Friedrich 
313b5677d84SJochen Friedrich struct cpm2_ioports {
314b5677d84SJochen Friedrich 	u32 dir, par, sor, odr, dat;
315b5677d84SJochen Friedrich 	u32 res[3];
316b5677d84SJochen Friedrich };
317b5677d84SJochen Friedrich 
cpm2_set_pin(int port,int pin,int flags)3186c552983SNick Child void __init cpm2_set_pin(int port, int pin, int flags)
319b5677d84SJochen Friedrich {
320b5677d84SJochen Friedrich 	struct cpm2_ioports __iomem *iop =
321b5677d84SJochen Friedrich 		(struct cpm2_ioports __iomem *)&cpm2_immr->im_ioport;
322b5677d84SJochen Friedrich 
323b5677d84SJochen Friedrich 	pin = 1 << (31 - pin);
324b5677d84SJochen Friedrich 
325b5677d84SJochen Friedrich 	if (flags & CPM_PIN_OUTPUT)
326b5677d84SJochen Friedrich 		setbits32(&iop[port].dir, pin);
327b5677d84SJochen Friedrich 	else
328b5677d84SJochen Friedrich 		clrbits32(&iop[port].dir, pin);
329b5677d84SJochen Friedrich 
330b5677d84SJochen Friedrich 	if (!(flags & CPM_PIN_GPIO))
331b5677d84SJochen Friedrich 		setbits32(&iop[port].par, pin);
332b5677d84SJochen Friedrich 	else
333b5677d84SJochen Friedrich 		clrbits32(&iop[port].par, pin);
334b5677d84SJochen Friedrich 
335b5677d84SJochen Friedrich 	if (flags & CPM_PIN_SECONDARY)
336b5677d84SJochen Friedrich 		setbits32(&iop[port].sor, pin);
337b5677d84SJochen Friedrich 	else
338b5677d84SJochen Friedrich 		clrbits32(&iop[port].sor, pin);
339b5677d84SJochen Friedrich 
340b5677d84SJochen Friedrich 	if (flags & CPM_PIN_OPENDRAIN)
341b5677d84SJochen Friedrich 		setbits32(&iop[port].odr, pin);
342b5677d84SJochen Friedrich 	else
343b5677d84SJochen Friedrich 		clrbits32(&iop[port].odr, pin);
344b5677d84SJochen Friedrich }
345