mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 02:50:43 +00:00
![Andrew Lunn](/assets/img/avatar_default.png)
Patchset "ARM: orion: Refactor the MPP code common in the orion platform" broke at least Orion5x based platforms. These platforms have pins configured as GPIO when the selector is not 0x0. However the common code assumes the selector is always 0x0 for a GPIO lines. It then ignores the GPIO bits in the MPP definitions, resulting in that Orion5x machines cannot correctly configure there GPIO lines. The Fix removes the assumption that the selector is always 0x0. In order that none GPIO configurations are correctly blocked, Kirkwood and mv78xx0 MPP definitions are corrected to only set the GPIO bits for GPIO configurations. This third version, which does not contain any whitespace changes, and is rebased on v3.3-rc2. Signed-off-by: Andrew Lunn <andrew@lunn.ch> Acked-by: Nicolas Pitre <nico@linaro.org> Signed-off-by: Olof Johansson <olof@lixom.net>
77 lines
1.9 KiB
C
77 lines
1.9 KiB
C
/*
|
|
* arch/arm/plat-orion/mpp.c
|
|
*
|
|
* MPP functions for Marvell orion SoCs
|
|
*
|
|
* This file is licensed under the terms of the GNU General Public
|
|
* License version 2. This program is licensed "as is" without any
|
|
* warranty of any kind, whether express or implied.
|
|
*/
|
|
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
#include <linux/mbus.h>
|
|
#include <linux/io.h>
|
|
#include <linux/gpio.h>
|
|
#include <mach/hardware.h>
|
|
#include <plat/mpp.h>
|
|
|
|
/* Address of the ith MPP control register */
|
|
static __init unsigned long mpp_ctrl_addr(unsigned int i,
|
|
unsigned long dev_bus)
|
|
{
|
|
return dev_bus + (i) * 4;
|
|
}
|
|
|
|
|
|
void __init orion_mpp_conf(unsigned int *mpp_list, unsigned int variant_mask,
|
|
unsigned int mpp_max, unsigned int dev_bus)
|
|
{
|
|
unsigned int mpp_nr_regs = (1 + mpp_max/8);
|
|
u32 mpp_ctrl[mpp_nr_regs];
|
|
int i;
|
|
|
|
printk(KERN_DEBUG "initial MPP regs:");
|
|
for (i = 0; i < mpp_nr_regs; i++) {
|
|
mpp_ctrl[i] = readl(mpp_ctrl_addr(i, dev_bus));
|
|
printk(" %08x", mpp_ctrl[i]);
|
|
}
|
|
printk("\n");
|
|
|
|
for ( ; *mpp_list; mpp_list++) {
|
|
unsigned int num = MPP_NUM(*mpp_list);
|
|
unsigned int sel = MPP_SEL(*mpp_list);
|
|
int shift, gpio_mode;
|
|
|
|
if (num > mpp_max) {
|
|
printk(KERN_ERR "orion_mpp_conf: invalid MPP "
|
|
"number (%u)\n", num);
|
|
continue;
|
|
}
|
|
if (variant_mask & !(*mpp_list & variant_mask)) {
|
|
printk(KERN_WARNING
|
|
"orion_mpp_conf: requested MPP%u config "
|
|
"unavailable on this hardware\n", num);
|
|
continue;
|
|
}
|
|
|
|
shift = (num & 7) << 2;
|
|
mpp_ctrl[num / 8] &= ~(0xf << shift);
|
|
mpp_ctrl[num / 8] |= sel << shift;
|
|
|
|
gpio_mode = 0;
|
|
if (*mpp_list & MPP_INPUT_MASK)
|
|
gpio_mode |= GPIO_INPUT_OK;
|
|
if (*mpp_list & MPP_OUTPUT_MASK)
|
|
gpio_mode |= GPIO_OUTPUT_OK;
|
|
|
|
orion_gpio_set_valid(num, gpio_mode);
|
|
}
|
|
|
|
printk(KERN_DEBUG " final MPP regs:");
|
|
for (i = 0; i < mpp_nr_regs; i++) {
|
|
writel(mpp_ctrl[i], mpp_ctrl_addr(i, dev_bus));
|
|
printk(" %08x", mpp_ctrl[i]);
|
|
}
|
|
printk("\n");
|
|
}
|