xref: /openbmc/u-boot/arch/arm/cpu/arm926ejs/mxs/iomux.c (revision 5675b509)
1 /*
2  * Copyright 2004-2006,2010 Freescale Semiconductor, Inc. All Rights Reserved.
3  * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
4  * Copyright (C) 2009 by Jan Weitzel Phytec Messtechnik GmbH,
5  *                       <armlinux@phytec.de>
6  *
7  * This program is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU General Public License
9  * as published by the Free Software Foundation; either version 2
10  * of the License, or (at your option) any later version.
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19  * MA 02110-1301, USA.
20  */
21 
22 #include <common.h>
23 #include <asm/errno.h>
24 #include <asm/io.h>
25 #include <asm/arch/clock.h>
26 #include <asm/arch/iomux.h>
27 #include <asm/arch/imx-regs.h>
28 
29 #if	defined(CONFIG_MX23)
30 #define	DRIVE_OFFSET	0x200
31 #define	PULL_OFFSET	0x400
32 #elif	defined(CONFIG_MX28)
33 #define	DRIVE_OFFSET	0x300
34 #define	PULL_OFFSET	0x600
35 #else
36 #error "Please select CONFIG_MX23 or CONFIG_MX28"
37 #endif
38 
39 /*
40  * configures a single pad in the iomuxer
41  */
42 int mxs_iomux_setup_pad(iomux_cfg_t pad)
43 {
44 	u32 reg, ofs, bp, bm;
45 	void *iomux_base = (void *)MXS_PINCTRL_BASE;
46 	struct mxs_register_32 *mxs_reg;
47 
48 	/* muxsel */
49 	ofs = 0x100;
50 	ofs += PAD_BANK(pad) * 0x20 + PAD_PIN(pad) / 16 * 0x10;
51 	bp = PAD_PIN(pad) % 16 * 2;
52 	bm = 0x3 << bp;
53 	reg = readl(iomux_base + ofs);
54 	reg &= ~bm;
55 	reg |= PAD_MUXSEL(pad) << bp;
56 	writel(reg, iomux_base + ofs);
57 
58 	/* drive */
59 	ofs = DRIVE_OFFSET;
60 	ofs += PAD_BANK(pad) * 0x40 + PAD_PIN(pad) / 8 * 0x10;
61 	/* mA */
62 	if (PAD_MA_VALID(pad)) {
63 		bp = PAD_PIN(pad) % 8 * 4;
64 		bm = 0x3 << bp;
65 		reg = readl(iomux_base + ofs);
66 		reg &= ~bm;
67 		reg |= PAD_MA(pad) << bp;
68 		writel(reg, iomux_base + ofs);
69 	}
70 	/* vol */
71 	if (PAD_VOL_VALID(pad)) {
72 		bp = PAD_PIN(pad) % 8 * 4 + 2;
73 		mxs_reg = (struct mxs_register_32 *)(iomux_base + ofs);
74 		if (PAD_VOL(pad))
75 			writel(1 << bp, &mxs_reg->reg_set);
76 		else
77 			writel(1 << bp, &mxs_reg->reg_clr);
78 	}
79 
80 	/* pull */
81 	if (PAD_PULL_VALID(pad)) {
82 		ofs = PULL_OFFSET;
83 		ofs += PAD_BANK(pad) * 0x10;
84 		bp = PAD_PIN(pad);
85 		mxs_reg = (struct mxs_register_32 *)(iomux_base + ofs);
86 		if (PAD_PULL(pad))
87 			writel(1 << bp, &mxs_reg->reg_set);
88 		else
89 			writel(1 << bp, &mxs_reg->reg_clr);
90 	}
91 
92 	return 0;
93 }
94 
95 int mxs_iomux_setup_multiple_pads(const iomux_cfg_t *pad_list, unsigned count)
96 {
97 	const iomux_cfg_t *p = pad_list;
98 	int i;
99 	int ret;
100 
101 	for (i = 0; i < count; i++) {
102 		ret = mxs_iomux_setup_pad(*p);
103 		if (ret)
104 			return ret;
105 		p++;
106 	}
107 
108 	return 0;
109 }
110