mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-08-23 09:19:51 +00:00
![Russell King](/assets/img/avatar_default.png)
When testing Lubbock, it was noticed that the sa1111 pcmcia driver bound but was not functional due to no sockets being registered. This is because the return code from the lowlevel board initialisation was not being propagated out of the probe function. Fix this. Tested-by: Robert Jarzmik <robert.jarzmik@free.fr> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
123 lines
3 KiB
C
123 lines
3 KiB
C
/*
|
|
* linux/drivers/pcmcia/sa1100_neponset.c
|
|
*
|
|
* Neponset PCMCIA specific routines
|
|
*/
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/device.h>
|
|
#include <linux/errno.h>
|
|
#include <linux/init.h>
|
|
|
|
#include <mach/hardware.h>
|
|
#include <asm/mach-types.h>
|
|
#include <mach/neponset.h>
|
|
#include <asm/hardware/sa1111.h>
|
|
|
|
#include "sa1111_generic.h"
|
|
|
|
/*
|
|
* Neponset uses the Maxim MAX1600, with the following connections:
|
|
*
|
|
* MAX1600 Neponset
|
|
*
|
|
* A0VCC SA-1111 GPIO A<1>
|
|
* A1VCC SA-1111 GPIO A<0>
|
|
* A0VPP CPLD NCR A0VPP
|
|
* A1VPP CPLD NCR A1VPP
|
|
* B0VCC SA-1111 GPIO A<2>
|
|
* B1VCC SA-1111 GPIO A<3>
|
|
* B0VPP ground (slot B is CF)
|
|
* B1VPP ground (slot B is CF)
|
|
*
|
|
* VX VCC (5V)
|
|
* VY VCC3_3 (3.3V)
|
|
* 12INA 12V
|
|
* 12INB ground (slot B is CF)
|
|
*
|
|
* The MAX1600 CODE pin is tied to ground, placing the device in
|
|
* "Standard Intel code" mode. Refer to the Maxim data sheet for
|
|
* the corresponding truth table.
|
|
*/
|
|
|
|
static int
|
|
neponset_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state)
|
|
{
|
|
struct sa1111_pcmcia_socket *s = to_skt(skt);
|
|
unsigned int ncr_mask, ncr_set, pa_dwr_mask, pa_dwr_set;
|
|
int ret;
|
|
|
|
switch (skt->nr) {
|
|
case 0:
|
|
pa_dwr_mask = GPIO_A0 | GPIO_A1;
|
|
ncr_mask = NCR_A0VPP | NCR_A1VPP;
|
|
|
|
if (state->Vpp == 0)
|
|
ncr_set = 0;
|
|
else if (state->Vpp == 120)
|
|
ncr_set = NCR_A1VPP;
|
|
else if (state->Vpp == state->Vcc)
|
|
ncr_set = NCR_A0VPP;
|
|
else {
|
|
printk(KERN_ERR "%s(): unrecognized VPP %u\n",
|
|
__func__, state->Vpp);
|
|
return -1;
|
|
}
|
|
break;
|
|
|
|
case 1:
|
|
pa_dwr_mask = GPIO_A2 | GPIO_A3;
|
|
ncr_mask = 0;
|
|
ncr_set = 0;
|
|
|
|
if (state->Vpp != state->Vcc && state->Vpp != 0) {
|
|
printk(KERN_ERR "%s(): CF slot cannot support VPP %u\n",
|
|
__func__, state->Vpp);
|
|
return -1;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return -1;
|
|
}
|
|
|
|
/*
|
|
* pa_dwr_set is the mask for selecting Vcc on both sockets.
|
|
* pa_dwr_mask selects which bits (and therefore socket) we change.
|
|
*/
|
|
switch (state->Vcc) {
|
|
default:
|
|
case 0: pa_dwr_set = 0; break;
|
|
case 33: pa_dwr_set = GPIO_A1|GPIO_A2; break;
|
|
case 50: pa_dwr_set = GPIO_A0|GPIO_A3; break;
|
|
}
|
|
|
|
ret = sa1111_pcmcia_configure_socket(skt, state);
|
|
if (ret == 0) {
|
|
neponset_ncr_frob(ncr_mask, ncr_set);
|
|
sa1111_set_io(s->dev, pa_dwr_mask, pa_dwr_set);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static struct pcmcia_low_level neponset_pcmcia_ops = {
|
|
.owner = THIS_MODULE,
|
|
.configure_socket = neponset_pcmcia_configure_socket,
|
|
.first = 0,
|
|
.nr = 2,
|
|
};
|
|
|
|
int pcmcia_neponset_init(struct sa1111_dev *sadev)
|
|
{
|
|
/*
|
|
* Set GPIO_A<3:0> to be outputs for the MAX1600,
|
|
* and switch to standby mode.
|
|
*/
|
|
sa1111_set_io_dir(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0, 0);
|
|
sa1111_set_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
|
|
sa1111_set_sleep_io(sadev, GPIO_A0|GPIO_A1|GPIO_A2|GPIO_A3, 0);
|
|
sa11xx_drv_pcmcia_ops(&neponset_pcmcia_ops);
|
|
return sa1111_pcmcia_add(sadev, &neponset_pcmcia_ops,
|
|
sa11xx_drv_pcmcia_add_one);
|
|
}
|