11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * drivers/pcmcia/sa1100_simpad.c
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds * PCMCIA implementation routines for simpad
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/device.h>
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
12a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/hardware.h>
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/mach-types.h>
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/irq.h>
15a09e64fbc0094e3073dbb09c3b4bfe4ab669244bRussell King#include <mach/simpad.h>
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "sa1100_generic.h"
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int simpad_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
21de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich	simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
23b1d8a5f91796179f33de9cd7fb26052fcc47b4faRussell King	skt->stat[SOC_STAT_CD].gpio = GPIO_CF_CD;
24b1d8a5f91796179f33de9cd7fb26052fcc47b4faRussell King	skt->stat[SOC_STAT_CD].name = "CF_CD";
25b1d8a5f91796179f33de9cd7fb26052fcc47b4faRussell King	skt->stat[SOC_STAT_RDY].gpio = GPIO_CF_IRQ;
26b1d8a5f91796179f33de9cd7fb26052fcc47b4faRussell King	skt->stat[SOC_STAT_RDY].name = "CF_RDY";
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
28b1d8a5f91796179f33de9cd7fb26052fcc47b4faRussell King	return 0;
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void simpad_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Disable CF bus: */
34de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich	/*simpad_set_cs3_bit(PCMCIA_BUFF_DIS);*/
35de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich	simpad_clear_cs3_bit(PCMCIA_RESET);
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssimpad_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			   struct pcmcia_state *state)
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
42de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich	long cs3reg = simpad_get_cs3_ro();
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
44b1d8a5f91796179f33de9cd7fb26052fcc47b4faRussell King	/* the detect signal is inverted - fix that up here */
45b1d8a5f91796179f33de9cd7fb26052fcc47b4faRussell King	state->detect = !state->detect;
46b1d8a5f91796179f33de9cd7fb26052fcc47b4faRussell King
47de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich	state->bvd1 = 1; /* Might be cs3reg & PCMCIA_BVD1 */
48de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich	state->bvd2 = 1; /* Might be cs3reg & PCMCIA_BVD2 */
49de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich
50de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich	if ((cs3reg & (PCMCIA_VS1|PCMCIA_VS2)) ==
51de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich			(PCMCIA_VS1|PCMCIA_VS2)) {
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		state->vs_3v=0;
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		state->vs_Xv=0;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	} else {
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		state->vs_3v=1;
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		state->vs_Xv=0;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldssimpad_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			       const socket_state_t *state)
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	unsigned long flags;
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_save(flags);
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* Murphy: see table of MIC2562a-1 */
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (state->Vcc) {
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 0:
71de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich		simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 33:
75de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich		simpad_clear_cs3_bit(VCC_3V_EN|EN1);
76de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich		simpad_set_cs3_bit(VCC_5V_EN|EN0);
771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case 50:
80de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich		simpad_clear_cs3_bit(VCC_5V_EN|EN1);
81de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich		simpad_set_cs3_bit(VCC_3V_EN|EN0);
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		break;
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	default:
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		printk(KERN_ERR "%s(): unrecognized Vcc %u\n",
862e11cb4c52ffbadab4844b28803577ba7272b221Harvey Harrison			__func__, state->Vcc);
87de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich		simpad_clear_cs3_bit(VCC_3V_EN|VCC_5V_EN|EN0|EN1);
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		local_irq_restore(flags);
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		return -1;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	local_irq_restore(flags);
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 0;
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void simpad_pcmcia_socket_suspend(struct soc_pcmcia_socket *skt)
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
100de0bc0d1b008d1240c03a0bac4f5534f995ab802Jochen Friedrich	simpad_set_cs3_bit(PCMCIA_RESET);
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct pcmcia_low_level simpad_pcmcia_ops = {
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner			= THIS_MODULE,
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.hw_init		= simpad_pcmcia_hw_init,
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.hw_shutdown		= simpad_pcmcia_hw_shutdown,
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.socket_state		= simpad_pcmcia_socket_state,
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.configure_socket	= simpad_pcmcia_configure_socket,
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.socket_suspend		= simpad_pcmcia_socket_suspend,
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1125b85e04e93f9a2963e88156cae8629ee72efd890Uwe Kleine-Königint __devinit pcmcia_simpad_init(struct device *dev)
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int ret = -ENODEV;
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (machine_is_simpad())
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		ret = sa11xx_drv_pcmcia_probe(dev, &simpad_pcmcia_ops, 1, 1);
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return ret;
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
121