Blame view

drivers/pcmcia/pxa2xx_viper.c 4.08 KB
20f18ff32   Marc Zyngier   Add support for t...
1
  /*
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
2
   * Viper/Zeus PCMCIA support
20f18ff32   Marc Zyngier   Add support for t...
3
4
5
   *   Copyright 2004 Arcom Control Systems
   *
   * Maintained by Marc Zyngier <maz@misterjones.org>
20f18ff32   Marc Zyngier   Add support for t...
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
   *
   * Based on:
   *   iPAQ h2200 PCMCIA support
   *   Copyright 2004 Koen Kooi <koen@vestingbar.nl>
   *
   * This file is subject to the terms and conditions of the GNU General Public
   * License.  See the file COPYING in the main directory of this archive for
   * more details.
   */
  
  #include <linux/module.h>
  #include <linux/init.h>
  #include <linux/kernel.h>
  #include <linux/errno.h>
  #include <linux/interrupt.h>
  #include <linux/platform_device.h>
  #include <linux/gpio.h>
  
  #include <pcmcia/ss.h>
  
  #include <asm/irq.h>
293b2da1b   Arnd Bergmann   ARM: pxa: move pl...
27
  #include <linux/platform_data/pcmcia-pxa2xx_viper.h>
20f18ff32   Marc Zyngier   Add support for t...
28
29
30
  
  #include "soc_common.h"
  #include "pxa2xx_base.h"
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
31
  static struct platform_device *arcom_pcmcia_dev;
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
32
33
34
35
  static inline struct arcom_pcmcia_pdata *viper_get_pdata(void)
  {
  	return arcom_pcmcia_dev->dev.platform_data;
  }
20f18ff32   Marc Zyngier   Add support for t...
36
37
  static int viper_pcmcia_hw_init(struct soc_pcmcia_socket *skt)
  {
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
38
  	struct arcom_pcmcia_pdata *pdata = viper_get_pdata();
20f18ff32   Marc Zyngier   Add support for t...
39
  	unsigned long flags;
a9bb5a4bf   Russell King   PCMCIA: pxa: conv...
40
41
42
43
  	skt->stat[SOC_STAT_CD].gpio = pdata->cd_gpio;
  	skt->stat[SOC_STAT_CD].name = "PCMCIA_CD";
  	skt->stat[SOC_STAT_RDY].gpio = pdata->rdy_gpio;
  	skt->stat[SOC_STAT_RDY].name = "CF ready";
20f18ff32   Marc Zyngier   Add support for t...
44

c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
45
  	if (gpio_request(pdata->pwr_gpio, "CF power"))
20f18ff32   Marc Zyngier   Add support for t...
46
47
48
  		goto err_request_pwr;
  
  	local_irq_save(flags);
a9bb5a4bf   Russell King   PCMCIA: pxa: conv...
49
  	if (gpio_direction_output(pdata->pwr_gpio, 0)) {
20f18ff32   Marc Zyngier   Add support for t...
50
51
52
53
54
  		local_irq_restore(flags);
  		goto err_dir;
  	}
  
  	local_irq_restore(flags);
a9bb5a4bf   Russell King   PCMCIA: pxa: conv...
55
  	return 0;
20f18ff32   Marc Zyngier   Add support for t...
56
57
  
  err_dir:
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
58
  	gpio_free(pdata->pwr_gpio);
20f18ff32   Marc Zyngier   Add support for t...
59
  err_request_pwr:
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
60
61
  	dev_err(&arcom_pcmcia_dev->dev, "Failed to setup PCMCIA GPIOs
  ");
20f18ff32   Marc Zyngier   Add support for t...
62
63
64
65
66
67
68
69
  	return -1;
  }
  
  /*
   * Release all resources.
   */
  static void viper_pcmcia_hw_shutdown(struct soc_pcmcia_socket *skt)
  {
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
70
  	struct arcom_pcmcia_pdata *pdata = viper_get_pdata();
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
71
  	gpio_free(pdata->pwr_gpio);
20f18ff32   Marc Zyngier   Add support for t...
72
73
74
75
76
  }
  
  static void viper_pcmcia_socket_state(struct soc_pcmcia_socket *skt,
  				      struct pcmcia_state *state)
  {
20f18ff32   Marc Zyngier   Add support for t...
77
78
79
80
81
82
83
  	state->vs_3v  = 1; /* Can only apply 3.3V */
  	state->vs_Xv  = 0;
  }
  
  static int viper_pcmcia_configure_socket(struct soc_pcmcia_socket *skt,
  					 const socket_state_t *state)
  {
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
84
  	struct arcom_pcmcia_pdata *pdata = viper_get_pdata();
20f18ff32   Marc Zyngier   Add support for t...
85
  	/* Silently ignore Vpp, output enable, speaker enable. */
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
86
  	pdata->reset(state->flags & SS_RESET);
20f18ff32   Marc Zyngier   Add support for t...
87
88
89
90
  
  	/* Apply socket voltage */
  	switch (state->Vcc) {
  	case 0:
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
91
  		gpio_set_value(pdata->pwr_gpio, 0);
20f18ff32   Marc Zyngier   Add support for t...
92
93
  		break;
  	case 33:
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
94
  		gpio_set_value(pdata->pwr_gpio, 1);
20f18ff32   Marc Zyngier   Add support for t...
95
96
  		break;
  	default:
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
97
98
  		dev_err(&arcom_pcmcia_dev->dev, "Unsupported Vcc:%d
  ", state->Vcc);
20f18ff32   Marc Zyngier   Add support for t...
99
100
101
102
103
  		return -1;
  	}
  
  	return 0;
  }
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
104
  static struct pcmcia_low_level viper_pcmcia_ops = {
20f18ff32   Marc Zyngier   Add support for t...
105
106
107
108
109
  	.owner          	= THIS_MODULE,
  	.hw_init        	= viper_pcmcia_hw_init,
  	.hw_shutdown		= viper_pcmcia_hw_shutdown,
  	.socket_state		= viper_pcmcia_socket_state,
  	.configure_socket	= viper_pcmcia_configure_socket,
20f18ff32   Marc Zyngier   Add support for t...
110
111
112
113
  	.nr         		= 1,
  };
  
  static struct platform_device *viper_pcmcia_device;
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
114
  static int viper_pcmcia_probe(struct platform_device *pdev)
20f18ff32   Marc Zyngier   Add support for t...
115
116
  {
  	int ret;
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
117
118
119
120
121
122
  	/* I can't imagine more than one device, but you never know... */
  	if (arcom_pcmcia_dev)
  		return -EEXIST;
  
  	if (!pdev->dev.platform_data)
  		return -EINVAL;
20f18ff32   Marc Zyngier   Add support for t...
123
124
125
126
  
  	viper_pcmcia_device = platform_device_alloc("pxa2xx-pcmcia", -1);
  	if (!viper_pcmcia_device)
  		return -ENOMEM;
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
127
128
129
  	arcom_pcmcia_dev = pdev;
  
  	viper_pcmcia_device->dev.parent = &pdev->dev;
20f18ff32   Marc Zyngier   Add support for t...
130
131
132
133
134
135
  	ret = platform_device_add_data(viper_pcmcia_device,
  				       &viper_pcmcia_ops,
  				       sizeof(viper_pcmcia_ops));
  
  	if (!ret)
  		ret = platform_device_add(viper_pcmcia_device);
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
136
  	if (ret) {
20f18ff32   Marc Zyngier   Add support for t...
137
  		platform_device_put(viper_pcmcia_device);
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
138
139
  		arcom_pcmcia_dev = NULL;
  	}
20f18ff32   Marc Zyngier   Add support for t...
140
141
142
  
  	return ret;
  }
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
143
  static int viper_pcmcia_remove(struct platform_device *pdev)
20f18ff32   Marc Zyngier   Add support for t...
144
145
  {
  	platform_device_unregister(viper_pcmcia_device);
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
  	arcom_pcmcia_dev = NULL;
  	return 0;
  }
  
  static struct platform_device_id viper_pcmcia_id_table[] = {
  	{ .name = "viper-pcmcia", },
  	{ .name = "zeus-pcmcia",  },
  	{ },
  };
  
  static struct platform_driver viper_pcmcia_driver = {
  	.probe		= viper_pcmcia_probe,
  	.remove		= viper_pcmcia_remove,
  	.driver		= {
  		.name	= "arcom-pcmcia",
c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
161
162
163
  	},
  	.id_table	= viper_pcmcia_id_table,
  };
5d95f8e2d   Axel Lin   pcmcia: convert d...
164
  module_platform_driver(viper_pcmcia_driver);
20f18ff32   Marc Zyngier   Add support for t...
165

c2de1c382   Marc Zyngier   [ARM] pxa/zeus: m...
166
  MODULE_DEVICE_TABLE(platform, viper_pcmcia_id_table);
20f18ff32   Marc Zyngier   Add support for t...
167
  MODULE_LICENSE("GPL");