aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-mx3/iomux.c
diff options
context:
space:
mode:
authorValentin Longchamp <valentin.longchamp@epfl.ch>2009-01-28 09:13:50 -0500
committerSascha Hauer <s.hauer@pengutronix.de>2009-03-13 05:34:00 -0400
commitb7222631c3d0fd26e6d85dd78b1d0aa10dc64929 (patch)
tree7b2469bb834187e7a4386eb7455cfc17605acef5 /arch/arm/mach-mx3/iomux.c
parent41a1d91e7e7b08a13d78e03e67dcd7634f2d5cca (diff)
mx31: rework of iomux support
This new implemenatation avoids that two physical pins are claimed by the same driver (also with the the gpr hardware modes). The gpio kernel lib is also called when a capable gpio pin is assigned its gpio function. The mxc_iomux_mode function is still here for backward compatibility but should not be used anymore. V2: In the precendent revision, the iomux code was claiming a pin when its hardware mode was changed. This was uncorrect: when the hardware mode is changed, the pin must still be claimed through the iomux. In order to have a pin working in mode hw2, we must fist issue the mxc_iomux_set_gpr call and then the corresponding mxc_iomux_mode calls with the FUNC mode (usually done with mxc_iomux_setup_multiple_pins). The reverse calls must be done to fee the pins. Signed-off-by: Valentin Longchamp <valentin.longchamp@epfl.ch> Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'arch/arm/mach-mx3/iomux.c')
-rw-r--r--arch/arm/mach-mx3/iomux.c88
1 files changed, 84 insertions, 4 deletions
diff --git a/arch/arm/mach-mx3/iomux.c b/arch/arm/mach-mx3/iomux.c
index 7a5088b519a8..40ffc5a664d9 100644
--- a/arch/arm/mach-mx3/iomux.c
+++ b/arch/arm/mach-mx3/iomux.c
@@ -1,6 +1,7 @@
1/* 1/*
2 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved. 2 * Copyright 2004-2006 Freescale Semiconductor, Inc. All Rights Reserved.
3 * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de> 3 * Copyright (C) 2008 by Sascha Hauer <kernel@pengutronix.de>
4 * Copyright (C) 2009 by Valentin Longchamp <valentin.longchamp@epfl.ch>
4 * 5 *
5 * This program is free software; you can redistribute it and/or 6 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License 7 * modify it under the terms of the GNU General Public License
@@ -21,6 +22,7 @@
21#include <linux/spinlock.h> 22#include <linux/spinlock.h>
22#include <linux/io.h> 23#include <linux/io.h>
23#include <linux/gpio.h> 24#include <linux/gpio.h>
25#include <linux/kernel.h>
24#include <mach/hardware.h> 26#include <mach/hardware.h>
25#include <mach/gpio.h> 27#include <mach/gpio.h>
26#include <mach/iomux-mx3.h> 28#include <mach/iomux-mx3.h>
@@ -38,6 +40,8 @@
38static DEFINE_SPINLOCK(gpio_mux_lock); 40static DEFINE_SPINLOCK(gpio_mux_lock);
39 41
40#define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3) 42#define IOMUX_REG_MASK (IOMUX_PADNUM_MASK & ~0x3)
43
44unsigned long mxc_pin_alloc_map[NB_PORTS * 32 / BITS_PER_LONG];
41/* 45/*
42 * set the mode for a IOMUX pin. 46 * set the mode for a IOMUX pin.
43 */ 47 */
@@ -50,9 +54,6 @@ int mxc_iomux_mode(unsigned int pin_mode)
50 field = pin_mode & 0x3; 54 field = pin_mode & 0x3;
51 mode = (pin_mode & IOMUX_MODE_MASK) >> IOMUX_MODE_SHIFT; 55 mode = (pin_mode & IOMUX_MODE_MASK) >> IOMUX_MODE_SHIFT;
52 56
53 pr_debug("%s: reg offset = 0x%x field = %d mode = 0x%02x\n",
54 __func__, (pin_mode & IOMUX_REG_MASK), field, mode);
55
56 spin_lock(&gpio_mux_lock); 57 spin_lock(&gpio_mux_lock);
57 58
58 l = __raw_readl(reg); 59 l = __raw_readl(reg);
@@ -93,6 +94,86 @@ void mxc_iomux_set_pad(enum iomux_pins pin, u32 config)
93EXPORT_SYMBOL(mxc_iomux_set_pad); 94EXPORT_SYMBOL(mxc_iomux_set_pad);
94 95
95/* 96/*
97 * setups a single pin:
98 * - reserves the pin so that it is not claimed by another driver
99 * - setups the iomux according to the configuration
100 * - if the pin is configured as a GPIO, we claim it through kernel gpiolib
101 */
102int mxc_iomux_setup_pin(const unsigned int pin, const char *label)
103{
104 unsigned pad = pin & IOMUX_PADNUM_MASK;
105 unsigned gpio;
106
107 if (pad >= (PIN_MAX + 1)) {
108 printk(KERN_ERR "mxc_iomux: Attempt to request nonexistant pin %u for \"%s\"\n",
109 pad, label ? label : "?");
110 return -EINVAL;
111 }
112
113 if (test_and_set_bit(pad, mxc_pin_alloc_map)) {
114 printk(KERN_ERR "mxc_iomux: pin %u already used. Allocation for \"%s\" failed\n",
115 pad, label ? label : "?");
116 return -EINVAL;
117 }
118 mxc_iomux_mode(pin);
119
120 /* if we have a gpio, we can allocate it */
121 gpio = (pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT;
122 if (gpio < (GPIO_PORT_MAX + 1) * 32)
123 if (gpio_request(gpio, label))
124 return -EINVAL;
125
126 return 0;
127}
128EXPORT_SYMBOL(mxc_iomux_setup_pin);
129
130int mxc_iomux_setup_multiple_pins(unsigned int *pin_list, unsigned count,
131 const char *label)
132{
133 unsigned int *p = pin_list;
134 int i;
135 int ret = -EINVAL;
136
137 for (i = 0; i < count; i++) {
138 if (mxc_iomux_setup_pin(*p, label))
139 goto setup_error;
140 p++;
141 }
142 return 0;
143
144setup_error:
145 mxc_iomux_release_multiple_pins(pin_list, i);
146 return ret;
147}
148EXPORT_SYMBOL(mxc_iomux_setup_multiple_pins);
149
150void mxc_iomux_release_pin(const unsigned int pin)
151{
152 unsigned pad = pin & IOMUX_PADNUM_MASK;
153 unsigned gpio;
154
155 if (pad < (PIN_MAX + 1))
156 clear_bit(pad, mxc_pin_alloc_map);
157
158 gpio = (pin & IOMUX_GPIONUM_MASK) >> IOMUX_GPIONUM_SHIFT;
159 if (gpio < (GPIO_PORT_MAX + 1) * 32)
160 gpio_free(gpio);
161}
162EXPORT_SYMBOL(mxc_iomux_release_pin);
163
164void mxc_iomux_release_multiple_pins(unsigned int *pin_list, int count)
165{
166 unsigned int *p = pin_list;
167 int i;
168
169 for (i = 0; i < count; i++) {
170 mxc_iomux_release_pin(*p);
171 p++;
172 }
173}
174EXPORT_SYMBOL(mxc_iomux_release_multiple_pins);
175
176/*
96 * This function enables/disables the general purpose function for a particular 177 * This function enables/disables the general purpose function for a particular
97 * signal. 178 * signal.
98 */ 179 */
@@ -111,4 +192,3 @@ void mxc_iomux_set_gpr(enum iomux_gp_func gp, bool en)
111 spin_unlock(&gpio_mux_lock); 192 spin_unlock(&gpio_mux_lock);
112} 193}
113EXPORT_SYMBOL(mxc_iomux_set_gpr); 194EXPORT_SYMBOL(mxc_iomux_set_gpr);
114