// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/pcmcia/pxa2xx_lubbock.c * * Author: George Davis * Created: Jan 10, 2002 * Copyright: MontaVista Software Inc. * * Originally based upon linux/drivers/pcmcia/sa1100_neponset.c * * Lubbock PCMCIA specific routines. */ #include #include #include #include #include #include #include #include #include #include "sa1111_generic.h" #include "max1600.h" static int lubbock_pcmcia_hw_init(struct soc_pcmcia_socket *skt) { struct max1600 *m; int ret; ret = max1600_init(skt->socket.dev.parent, &m, skt->nr ? MAX1600_CHAN_B : MAX1600_CHAN_A, MAX1600_CODE_HIGH); if (ret == 0) skt->driver_data = m; return ret; } static int lubbock_pcmcia_configure_socket(struct soc_pcmcia_socket *skt, const socket_state_t *state) { struct max1600 *m = skt->driver_data; int ret = 0; /* Lubbock uses the Maxim MAX1602, with the following connections: * * Socket 0 (PCMCIA): * MAX1602 Lubbock Register * Pin Signal * ----- ------- ---------------------- * A0VPP S0_PWR0 SA-1111 GPIO A<0> * A1VPP S0_PWR1 SA-1111 GPIO A<1> * A0VCC S0_PWR2 SA-1111 GPIO A<2> * A1VCC S0_PWR3 SA-1111 GPIO A<3> * VX VCC * VY +3.3V * 12IN +12V * CODE +3.3V Cirrus Code, CODE = High (VY) * * Socket 1 (CF): * MAX1602 Lubbock Register * Pin Signal * ----- ------- ---------------------- * A0VPP GND VPP is not connected * A1VPP GND VPP is not connected * A0VCC S1_PWR0 MISC_WR<14> * A1VCC S1_PWR1 MISC_WR<15> * VX VCC * VY +3.3V * 12IN GND VPP is not connected * CODE +3.3V Cirrus Code, CODE = High (VY) * */ again: switch (skt->nr) { case 0: case 1: break; default: ret = -1; } if (ret == 0) ret = sa1111_pcmcia_configure_socket(skt, state); if (ret == 0) ret = max1600_configure(m, state->Vcc, state->Vpp); #if 1 if (ret == 0 && state->Vcc == 33) { struct pcmcia_state new_state; /* * HACK ALERT: * We can't sense the voltage properly on Lubbock before * actually applying some power to the socket (catch 22). * Resense the socket Voltage Sense pins after applying * socket power. * * Note: It takes about 2.5ms for the MAX1602 VCC output * to rise. */ mdelay(3); sa1111_pcmcia_socket_state(skt, &new_state); if (!new_state.vs_3v && !new_state.vs_Xv) { /* * Switch to 5V, Configure socket with 5V voltage */ max1600_configure(m, 0, 0); /* * It takes about 100ms to turn off Vcc. */ mdelay(100); /* * We need to hack around the const qualifier as * well to keep this ugly workaround localized and * not force it to the rest of the code. Barf bags * available in the seat pocket in front of you! */ ((socket_state_t *)state)->Vcc = 50; ((socket_state_t *)state)->Vpp = 50; goto again; } } #endif return ret; } static struct pcmcia_low_level lubbock_pcmcia_ops = { .owner = THIS_MODULE, .hw_init = lubbock_pcmcia_hw_init, .configure_socket = lubbock_pcmcia_configure_socket, .first = 0, .nr = 2, }; #include "pxa2xx_base.h" int pcmcia_lubbock_init(struct sa1111_dev *sadev) { pxa2xx_drv_pcmcia_ops(&lubbock_pcmcia_ops); pxa2xx_configure_sockets(&sadev->dev, &lubbock_pcmcia_ops); return sa1111_pcmcia_add(sadev, &lubbock_pcmcia_ops, pxa2xx_drv_pcmcia_add_one); } MODULE_LICENSE("GPL");