Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
awilliam
GitHub Repository: awilliam/linux-vfio
Path: blob/master/arch/arm/mach-imx/iomux-imx31.c
10817 views
1
/*
2
* Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
3
* Copyright (C) 2008 by Sascha Hauer <[email protected]>
4
* Copyright (C) 2009 by Valentin Longchamp <[email protected]>
5
*
6
* This program is free software; you can redistribute it and/or
7
* modify it under the terms of the GNU General Public License
8
* as published by the Free Software Foundation; either version 2
9
* of the License, or (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18
* MA 02110-1301, USA.
19
*/
20
21
#include <linux/module.h>
22
#include <linux/spinlock.h>
23
#include <linux/io.h>
24
#include <linux/kernel.h>
25
#include <mach/hardware.h>
26
#include <mach/gpio.h>
27
#include <mach/iomux-mx3.h>
28
29
/*
30
* IOMUX register (base) addresses
31
*/
32
#define IOMUX_BASE MX31_IO_ADDRESS(MX31_IOMUXC_BASE_ADDR)
33
#define IOMUXINT_OBS1 (IOMUX_BASE + 0x000)
34
#define IOMUXINT_OBS2 (IOMUX_BASE + 0x004)
35
#define IOMUXGPR (IOMUX_BASE + 0x008)
36
#define IOMUXSW_MUX_CTL (IOMUX_BASE + 0x00C)
37
#define IOMUXSW_PAD_CTL (IOMUX_BASE + 0x154)
38
39
static DEFINE_SPINLOCK(gpio_mux_lock);
40
41
#define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
42
43
unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
44
/*
45
* set the mode for a IOMUX pin.
46
*/
47
int mxc_iomux_mode(unsigned int pin_mode)
48
{
49
u32 field, l, mode, ret = 0;
50
void __iomem *reg;
51
52
reg = IOMUXSW_MUX_CTL + (pin_mode & IOMUX_REG_MASK);
53
field = pin_mode & 0x3;
54
mode = (pin_mode & IOMUX_MODE_MASK) >> IOMUX_MODE_SHIFT;
55
56
spin_lock(&gpio_mux_lock);
57
58
l = __raw_readl(reg);
59
l &= ~(0xff << (field * 8));
60
l |= mode << (field * 8);
61
__raw_writel(l, reg);
62
63
spin_unlock(&gpio_mux_lock);
64
65
return ret;
66
}
67
EXPORT_SYMBOL(mxc_iomux_mode);
68
69
/*
70
* This function configures the pad value for a IOMUX pin.
71
*/
72
void mxc_iomux_set_pad(enum iomux_pins pin, u32 config)
73
{
74
u32 field, l;
75
void __iomem *reg;
76
77
pin &= IOMUX_PADNUM_MASK;
78
reg = IOMUXSW_PAD_CTL + (pin + 2) / 3 * 4;
79
field = (pin + 2) % 3;
80
81
pr_debug("%s: reg offset = 0x%x, field = %d\n",
82
__func__, (pin + 2) / 3, field);
83
84
spin_lock(&gpio_mux_lock);
85
86
l = __raw_readl(reg);
87
l &= ~(0x1ff << (field * 10));
88
l |= config << (field * 10);
89
__raw_writel(l, reg);
90
91
spin_unlock(&gpio_mux_lock);
92
}
93
EXPORT_SYMBOL(mxc_iomux_set_pad);
94
95
/*
96
* allocs a single pin:
97
* - reserves the pin so that it is not claimed by another driver
98
* - setups the iomux according to the configuration
99
*/
100
int mxc_iomux_alloc_pin(unsigned int pin, const char *label)
101
{
102
unsigned pad = pin & IOMUX_PADNUM_MASK;
103
104
if (pad >= (PIN_MAX + 1)) {
105
printk(KERN_ERR "mxc_iomux: Attempt to request nonexistant pin %u for \"%s\"\n",
106
pad, label ? label : "?");
107
return -EINVAL;
108
}
109
110
if (test_and_set_bit(pad, mxc_pin_alloc_map)) {
111
printk(KERN_ERR "mxc_iomux: pin %u already used. Allocation for \"%s\" failed\n",
112
pad, label ? label : "?");
113
return -EBUSY;
114
}
115
mxc_iomux_mode(pin);
116
117
return 0;
118
}
119
EXPORT_SYMBOL(mxc_iomux_alloc_pin);
120
121
int mxc_iomux_setup_multiple_pins(const unsigned int *pin_list, unsigned count,
122
const char *label)
123
{
124
const unsigned int *p = pin_list;
125
int i;
126
int ret = -EINVAL;
127
128
for (i = 0; i < count; i++) {
129
ret = mxc_iomux_alloc_pin(*p, label);
130
if (ret)
131
goto setup_error;
132
p++;
133
}
134
return 0;
135
136
setup_error:
137
mxc_iomux_release_multiple_pins(pin_list, i);
138
return ret;
139
}
140
EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins);
141
142
void mxc_iomux_release_pin(unsigned int pin)
143
{
144
unsigned pad = pin & IOMUX_PADNUM_MASK;
145
146
if (pad < (PIN_MAX + 1))
147
clear_bit(pad, mxc_pin_alloc_map);
148
}
149
EXPORT_SYMBOL(mxc_iomux_release_pin);
150
151
void mxc_iomux_release_multiple_pins(const unsigned int *pin_list, int count)
152
{
153
const unsigned int *p = pin_list;
154
int i;
155
156
for (i = 0; i < count; i++) {
157
mxc_iomux_release_pin(*p);
158
p++;
159
}
160
}
161
EXPORT_SYMBOL(mxc_iomux_release_multiple_pins);
162
163
/*
164
* This function enables/disables the general purpose function for a particular
165
* signal.
166
*/
167
void mxc_iomux_set_gpr(enum iomux_gp_func gp, bool en)
168
{
169
u32 l;
170
171
spin_lock(&gpio_mux_lock);
172
l = __raw_readl(IOMUXGPR);
173
if (en)
174
l |= gp;
175
else
176
l &= ~gp;
177
178
__raw_writel(l, IOMUXGPR);
179
spin_unlock(&gpio_mux_lock);
180
}
181
EXPORT_SYMBOL(mxc_iomux_set_gpr);
182
183