Blame view

drivers/pcmcia/pcmcia_resource.c 24.1 KB
d2912cb15   Thomas Gleixner   treewide: Replace...
1
  // SPDX-License-Identifier: GPL-2.0-only
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
2
3
4
5
6
7
8
9
  /*
   * PCMCIA 16-bit resource management functions
   *
   * The initial developer of the original code is David A. Hinds
   * <dahinds@users.sourceforge.net>.  Portions created by David A. Hinds
   * are Copyright (C) 1999 David A. Hinds.  All Rights Reserved.
   *
   * Copyright (C) 1999	     David A. Hinds
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
10
   * Copyright (C) 2004-2010   Dominik Brodowski
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
11
   */
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
12
13
14
15
16
17
  #include <linux/module.h>
  #include <linux/kernel.h>
  #include <linux/interrupt.h>
  #include <linux/delay.h>
  #include <linux/pci.h>
  #include <linux/device.h>
91284224d   Dominik Brodowski   pcmcia: add new C...
18
  #include <linux/netdevice.h>
5a0e3ad6a   Tejun Heo   include cleanup: ...
19
  #include <linux/slab.h>
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
20

6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
21
  #include <asm/irq.h>
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
22
  #include <pcmcia/ss.h>
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
23
24
25
26
27
  #include <pcmcia/cistpl.h>
  #include <pcmcia/cisreg.h>
  #include <pcmcia/ds.h>
  
  #include "cs_internal.h"
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
28

1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
29
  /* Access speed for IO windows */
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
30
  static int io_speed;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
31
  module_param(io_speed, int, 0444);
a3ac9af56   Dominik Brodowski   pcmcia: remove re...
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
  int pcmcia_validate_mem(struct pcmcia_socket *s)
  {
  	if (s->resource_ops->validate_mem)
  		return s->resource_ops->validate_mem(s);
  	/* if there is no callback, we can assume that everything is OK */
  	return 0;
  }
  
  struct resource *pcmcia_find_mem_region(u_long base, u_long num, u_long align,
  				 int low, struct pcmcia_socket *s)
  {
  	if (s->resource_ops->find_mem)
  		return s->resource_ops->find_mem(base, num, align, low, s);
  	return NULL;
  }
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
47

9485ee14e   Dominik Brodowski   pcmcia: Documenta...
48
49
50
51
52
53
  /**
   * release_io_space() - release IO ports allocated with alloc_io_space()
   * @s: pcmcia socket
   * @res: resource to release
   *
   */
ad0c7be28   Dominik Brodowski   pcmcia: insert PC...
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
  static void release_io_space(struct pcmcia_socket *s, struct resource *res)
  {
  	resource_size_t num = resource_size(res);
  	int i;
  
  	dev_dbg(&s->dev, "release_io_space for %pR
  ", res);
  
  	for (i = 0; i < MAX_IO_WIN; i++) {
  		if (!s->io[i].res)
  			continue;
  		if ((s->io[i].res->start <= res->start) &&
  		    (s->io[i].res->end >= res->end)) {
  			s->io[i].InUse -= num;
  			if (res->parent)
  				release_resource(res);
  			res->start = res->end = 0;
  			res->flags = IORESOURCE_IO;
  			/* Free the window if no one else is using it */
  			if (s->io[i].InUse == 0) {
  				release_resource(s->io[i].res);
  				kfree(s->io[i].res);
  				s->io[i].res = NULL;
  			}
  		}
  	}
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
80
  }
ad0c7be28   Dominik Brodowski   pcmcia: insert PC...
81

9485ee14e   Dominik Brodowski   pcmcia: Documenta...
82
83
84
85
86
  /**
   * alloc_io_space() - allocate IO ports for use by a PCMCIA device
   * @s: pcmcia socket
   * @res: resource to allocate (begin: begin, end: size)
   * @lines: number of IO lines decoded by the PCMCIA card
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
87
88
89
   *
   * Special stuff for managing IO windows, because they are scarce
   */
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
90
91
  static int alloc_io_space(struct pcmcia_socket *s, struct resource *res,
  			unsigned int lines)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
92
  {
b19a7275d   Dominik Brodowski   pcmcia: clarify a...
93
  	unsigned int align;
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
94
95
96
97
98
  	unsigned int base = res->start;
  	unsigned int num = res->end;
  	int ret;
  
  	res->flags |= IORESOURCE_IO;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
99

90abdc3b9   Dominik Brodowski   pcmcia: do not us...
100
101
102
  	dev_dbg(&s->dev, "alloc_io_space request for %pR, %d lines
  ",
  		res, lines);
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
103
104
  
  	align = base ? (lines ? 1<<lines : 0) : 1;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
105
  	if (align && (align < num)) {
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
106
107
108
  		if (base) {
  			dev_dbg(&s->dev, "odd IO request
  ");
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
109
110
  			align = 0;
  		} else
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
111
112
  			while (align && (align < num))
  				align <<= 1;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
113
  	}
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
114
115
116
  	if (base & ~(align-1)) {
  		dev_dbg(&s->dev, "odd IO request
  ");
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
117
118
  		align = 0;
  	}
b19a7275d   Dominik Brodowski   pcmcia: clarify a...
119

ad0c7be28   Dominik Brodowski   pcmcia: insert PC...
120
121
  	ret = s->resource_ops->find_io(s, res->flags, &base, num, align,
  				&res->parent);
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
122
  	if (ret) {
ad0c7be28   Dominik Brodowski   pcmcia: insert PC...
123
124
  		dev_dbg(&s->dev, "alloc_io_space request failed (%d)
  ", ret);
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
125
126
127
128
129
  		return -EINVAL;
  	}
  
  	res->start = base;
  	res->end = res->start + num - 1;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
130

ad0c7be28   Dominik Brodowski   pcmcia: insert PC...
131
132
133
134
135
136
137
138
  	if (res->parent) {
  		ret = request_resource(res->parent, res);
  		if (ret) {
  			dev_warn(&s->dev,
  				"request_resource %pR failed: %d
  ", res, ret);
  			res->parent = NULL;
  			release_io_space(s, res);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
139
140
  		}
  	}
ad0c7be28   Dominik Brodowski   pcmcia: insert PC...
141
142
143
  	dev_dbg(&s->dev, "alloc_io_space request result %d: %pR
  ", ret, res);
  	return ret;
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
144
  }
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
145

1d5cc192d   Dominik Brodowski   pcmcia: use pcmic...
146
147
  /**
   * pcmcia_access_config() - read or write card configuration registers
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
148
   *
1d5cc192d   Dominik Brodowski   pcmcia: use pcmic...
149
150
151
152
   * pcmcia_access_config() reads and writes configuration registers in
   * attribute memory.  Memory window 0 is reserved for this and the tuple
   * reading services. Drivers must use pcmcia_read_config_byte() or
   * pcmcia_write_config_byte().
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
153
   */
1d5cc192d   Dominik Brodowski   pcmcia: use pcmic...
154
155
156
157
158
  static int pcmcia_access_config(struct pcmcia_device *p_dev,
  				off_t where, u8 *val,
  				int (*accessf) (struct pcmcia_socket *s,
  						int attr, unsigned int addr,
  						unsigned int len, void *ptr))
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
159
  {
855cdf134   Dominik Brodowski   [PATCH] pcmcia: a...
160
  	struct pcmcia_socket *s;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
161
162
  	config_t *c;
  	int addr;
059f667d9   Dominik Brodowski   pcmcia: call pcmc...
163
  	int ret = 0;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
164

855cdf134   Dominik Brodowski   [PATCH] pcmcia: a...
165
  	s = p_dev->socket;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
166
167
  
  	mutex_lock(&s->ops_mutex);
855cdf134   Dominik Brodowski   [PATCH] pcmcia: a...
168
  	c = p_dev->function_config;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
169

6d9a299f6   Dominik Brodowski   pcmcia: extend er...
170
  	if (!(c->state & CONFIG_LOCKED)) {
e9c549998   Lucas De Marchi   Revert wrong fixe...
171
172
  		dev_dbg(&p_dev->dev, "Configuration isn't locked
  ");
94a819f80   Dominik Brodowski   pcmcia: assert lo...
173
  		mutex_unlock(&s->ops_mutex);
943f70f1b   Dominik Brodowski   pcmcia: deprecate...
174
  		return -EACCES;
6d9a299f6   Dominik Brodowski   pcmcia: extend er...
175
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
176

7feabb641   Dominik Brodowski   pcmcia: move conf...
177
  	addr = (p_dev->config_base + where) >> 1;
1d5cc192d   Dominik Brodowski   pcmcia: use pcmic...
178
179
  
  	ret = accessf(s, 1, addr, 1, val);
059f667d9   Dominik Brodowski   pcmcia: call pcmc...
180
  	mutex_unlock(&s->ops_mutex);
1d5cc192d   Dominik Brodowski   pcmcia: use pcmic...
181

059f667d9   Dominik Brodowski   pcmcia: call pcmc...
182
  	return ret;
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
183
  }
1d5cc192d   Dominik Brodowski   pcmcia: use pcmic...
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
  
  
  /**
   * pcmcia_read_config_byte() - read a byte from a card configuration register
   *
   * pcmcia_read_config_byte() reads a byte from a configuration register in
   * attribute memory.
   */
  int pcmcia_read_config_byte(struct pcmcia_device *p_dev, off_t where, u8 *val)
  {
  	return pcmcia_access_config(p_dev, where, val, pcmcia_read_cis_mem);
  }
  EXPORT_SYMBOL(pcmcia_read_config_byte);
  
  
  /**
   * pcmcia_write_config_byte() - write a byte to a card configuration register
   *
   * pcmcia_write_config_byte() writes a byte to a configuration register in
   * attribute memory.
   */
  int pcmcia_write_config_byte(struct pcmcia_device *p_dev, off_t where, u8 val)
  {
  	return pcmcia_access_config(p_dev, where, &val, pcmcia_write_cis_mem);
  }
  EXPORT_SYMBOL(pcmcia_write_config_byte);
3448139b4   Dominik Brodowski   [PATCH] pcmcia: d...
210

1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
211

9485ee14e   Dominik Brodowski   pcmcia: Documenta...
212
213
214
215
216
217
218
219
220
221
  /**
   * pcmcia_map_mem_page() - modify iomem window to point to a different offset
   * @p_dev: pcmcia device
   * @res: iomem resource already enabled by pcmcia_request_window()
   * @offset: card_offset to map
   *
   * pcmcia_map_mem_page() modifies what can be read and written by accessing
   * an iomem range previously enabled by pcmcia_request_window(), by setting
   * the card_offset value to @offset.
   */
cdb138080   Dominik Brodowski   pcmcia: do not us...
222
  int pcmcia_map_mem_page(struct pcmcia_device *p_dev, struct resource *res,
b5cb259e7   Dominik Brodowski   pcmcia: remove me...
223
  			unsigned int offset)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
224
  {
0bdf9b3dd   Magnus Damm   pcmcia: Change wi...
225
  	struct pcmcia_socket *s = p_dev->socket;
0ca724d37   Dominik Brodowski   pcmcia: use struc...
226
  	unsigned int w;
6b8e087b8   Dominik Brodowski   pcmcia: add locki...
227
  	int ret;
868575d1e   Magnus Damm   pcmcia: Pass stru...
228

0ca724d37   Dominik Brodowski   pcmcia: use struc...
229
230
  	w = ((res->flags & IORESOURCE_BITS & WIN_FLAGS_REQ) >> 2) - 1;
  	if (w >= MAX_WIN)
ffb8da202   Dominik Brodowski   pcmcia: deprecate...
231
  		return -EINVAL;
b5cb259e7   Dominik Brodowski   pcmcia: remove me...
232

6b8e087b8   Dominik Brodowski   pcmcia: add locki...
233
  	mutex_lock(&s->ops_mutex);
0ca724d37   Dominik Brodowski   pcmcia: use struc...
234
235
  	s->win[w].card_start = offset;
  	ret = s->ops->set_mem_map(s, &s->win[w]);
6b8e087b8   Dominik Brodowski   pcmcia: add locki...
236
  	if (ret)
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
237
238
  		dev_warn(&p_dev->dev, "failed to set_mem_map
  ");
6b8e087b8   Dominik Brodowski   pcmcia: add locki...
239
240
  	mutex_unlock(&s->ops_mutex);
  	return ret;
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
241
  }
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
242
  EXPORT_SYMBOL(pcmcia_map_mem_page);
fb49fa533   Dominik Brodowski   pcmcia: split up ...
243
244
  /**
   * pcmcia_fixup_iowidth() - reduce io width to 8bit
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
245
   * @p_dev: pcmcia device
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
246
   *
fb49fa533   Dominik Brodowski   pcmcia: split up ...
247
   * pcmcia_fixup_iowidth() allows a PCMCIA device driver to reduce the
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
248
   * IO width to 8bit after having called pcmcia_enable_device()
fb49fa533   Dominik Brodowski   pcmcia: split up ...
249
   * previously.
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
250
   */
fb49fa533   Dominik Brodowski   pcmcia: split up ...
251
  int pcmcia_fixup_iowidth(struct pcmcia_device *p_dev)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
252
  {
fb49fa533   Dominik Brodowski   pcmcia: split up ...
253
254
255
256
  	struct pcmcia_socket *s = p_dev->socket;
  	pccard_io_map io_off = { 0, 0, 0, 0, 1 };
  	pccard_io_map io_on;
  	int i, ret = 0;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
257
258
  
  	mutex_lock(&s->ops_mutex);
dbb22f0d6   Dominik Brodowski   [PATCH] pcmcia: a...
259

fb49fa533   Dominik Brodowski   pcmcia: split up ...
260
261
262
263
264
265
266
  	dev_dbg(&p_dev->dev, "fixup iowidth to 8bit
  ");
  
  	if (!(s->state & SOCKET_PRESENT) ||
  		!(p_dev->function_config->state & CONFIG_LOCKED)) {
  		dev_dbg(&p_dev->dev, "No card? Config not locked?
  ");
4e06e240d   Jiri Slaby   PCMCIA: resource,...
267
268
  		ret = -EACCES;
  		goto unlock;
6d9a299f6   Dominik Brodowski   pcmcia: extend er...
269
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
270

fb49fa533   Dominik Brodowski   pcmcia: split up ...
271
272
273
274
275
276
277
278
279
280
281
282
  	io_on.speed = io_speed;
  	for (i = 0; i < MAX_IO_WIN; i++) {
  		if (!s->io[i].res)
  			continue;
  		io_off.map = i;
  		io_on.map = i;
  
  		io_on.flags = MAP_ACTIVE | IO_DATA_PATH_WIDTH_8;
  		io_on.start = s->io[i].res->start;
  		io_on.stop = s->io[i].res->end;
  
  		s->ops->set_io_map(s, &io_off);
1b22dcf6b   Jia-Ju Bai   pcmcia: pcmcia_re...
283
  		msleep(40);
fb49fa533   Dominik Brodowski   pcmcia: split up ...
284
  		s->ops->set_io_map(s, &io_on);
d8b0a49da   Dominik Brodowski   pcmcia: deprecate...
285
  	}
fb49fa533   Dominik Brodowski   pcmcia: split up ...
286
287
  unlock:
  	mutex_unlock(&s->ops_mutex);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
288

fb49fa533   Dominik Brodowski   pcmcia: split up ...
289
290
291
292
293
294
295
  	return ret;
  }
  EXPORT_SYMBOL(pcmcia_fixup_iowidth);
  
  
  /**
   * pcmcia_fixup_vpp() - set Vpp to a new voltage level
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
296
297
   * @p_dev: pcmcia device
   * @new_vpp: new Vpp voltage
fb49fa533   Dominik Brodowski   pcmcia: split up ...
298
299
   *
   * pcmcia_fixup_vpp() allows a PCMCIA device driver to set Vpp to
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
300
   * a new voltage level between calls to pcmcia_enable_device()
fb49fa533   Dominik Brodowski   pcmcia: split up ...
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
   * and pcmcia_disable_device().
   */
  int pcmcia_fixup_vpp(struct pcmcia_device *p_dev, unsigned char new_vpp)
  {
  	struct pcmcia_socket *s = p_dev->socket;
  	int ret = 0;
  
  	mutex_lock(&s->ops_mutex);
  
  	dev_dbg(&p_dev->dev, "fixup Vpp to %d
  ", new_vpp);
  
  	if (!(s->state & SOCKET_PRESENT) ||
  		!(p_dev->function_config->state & CONFIG_LOCKED)) {
  		dev_dbg(&p_dev->dev, "No card? Config not locked?
  ");
  		ret = -EACCES;
4e06e240d   Jiri Slaby   PCMCIA: resource,...
318
  		goto unlock;
d8b0a49da   Dominik Brodowski   pcmcia: deprecate...
319
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
320

fb49fa533   Dominik Brodowski   pcmcia: split up ...
321
322
323
324
325
326
  	s->socket.Vpp = new_vpp;
  	if (s->ops->set_socket(s, &s->socket)) {
  		dev_warn(&p_dev->dev, "Unable to set VPP
  ");
  		ret = -EIO;
  		goto unlock;
4bbed5231   Dominik Brodowski   [PATCH] pcmcia: r...
327
  	}
e8405f0f6   Dominik Brodowski   pcmcia: move Vpp ...
328
  	p_dev->vpp = new_vpp;
fb49fa533   Dominik Brodowski   pcmcia: split up ...
329

4e06e240d   Jiri Slaby   PCMCIA: resource,...
330
  unlock:
94a819f80   Dominik Brodowski   pcmcia: assert lo...
331
  	mutex_unlock(&s->ops_mutex);
4bbed5231   Dominik Brodowski   [PATCH] pcmcia: r...
332

4e06e240d   Jiri Slaby   PCMCIA: resource,...
333
  	return ret;
fb49fa533   Dominik Brodowski   pcmcia: split up ...
334
335
  }
  EXPORT_SYMBOL(pcmcia_fixup_vpp);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
336

9485ee14e   Dominik Brodowski   pcmcia: Documenta...
337
338
339
340
341
342
343
344
345
346
347
  /**
   * pcmcia_release_configuration() - physically disable a PCMCIA device
   * @p_dev: pcmcia device
   *
   * pcmcia_release_configuration() is the 1:1 counterpart to
   * pcmcia_enable_device(): If a PCMCIA device is no longer used by any
   * driver, the Vpp voltage is set to 0, IRQs will no longer be generated,
   * and I/O ranges will be disabled. As pcmcia_release_io() and
   * pcmcia_release_window() still need to be called, device drivers are
   * expected to call pcmcia_disable_device() instead.
   */
2bc5a9bdc   Dominik Brodowski   [PATCH] pcmcia: r...
348
  int pcmcia_release_configuration(struct pcmcia_device *p_dev)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
349
350
  {
  	pccard_io_map io = { 0, 0, 0, 0, 1 };
2bc5a9bdc   Dominik Brodowski   [PATCH] pcmcia: r...
351
  	struct pcmcia_socket *s = p_dev->socket;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
352
  	config_t *c;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
353
  	int i;
9e86749cf   Dominik Brodowski   pcmcia: lock ops-...
354
  	mutex_lock(&s->ops_mutex);
94a819f80   Dominik Brodowski   pcmcia: assert lo...
355
  	c = p_dev->function_config;
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
356
357
  	if (p_dev->_locked) {
  		p_dev->_locked = 0;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
358
  		if (--(s->lock_count) == 0) {
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
359
  			s->socket.flags = SS_OUTPUT_ENA; /* Is this correct? */
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
360
361
362
363
  			s->socket.Vpp = 0;
  			s->socket.io_irq = 0;
  			s->ops->set_socket(s, &s->socket);
  		}
5f2a71fcb   Dominik Brodowski   [PATCH] pcmcia: a...
364
365
366
  	}
  	if (c->state & CONFIG_LOCKED) {
  		c->state &= ~CONFIG_LOCKED;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
367
368
  		if (c->state & CONFIG_IO_REQ)
  			for (i = 0; i < MAX_IO_WIN; i++) {
c7d006935   Dominik Brodowski   [PATCH] pcmcia: r...
369
  				if (!s->io[i].res)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
370
371
372
373
374
375
376
  					continue;
  				s->io[i].Config--;
  				if (s->io[i].Config != 0)
  					continue;
  				io.map = i;
  				s->ops->set_io_map(s, &io);
  			}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
377
  	}
9e86749cf   Dominik Brodowski   pcmcia: lock ops-...
378
  	mutex_unlock(&s->ops_mutex);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
379

4c89e88bf   Dominik Brodowski   pcmcia: deprecate...
380
  	return 0;
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
381
  }
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
382

9485ee14e   Dominik Brodowski   pcmcia: Documenta...
383
384
385
  /**
   * pcmcia_release_io() - release I/O allocated by a PCMCIA device
   * @p_dev: pcmcia device
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
386
   *
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
387
388
389
390
391
   * pcmcia_release_io() releases the I/O ranges allocated by a PCMCIA
   * device.  This may be invoked some time after a card ejection has
   * already dumped the actual socket configuration, so if the client is
   * "stale", we don't bother checking the port ranges against the
   * current socket values.
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
392
   */
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
393
  static int pcmcia_release_io(struct pcmcia_device *p_dev)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
394
  {
2bc5a9bdc   Dominik Brodowski   [PATCH] pcmcia: r...
395
  	struct pcmcia_socket *s = p_dev->socket;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
396
397
398
399
  	int ret = -EINVAL;
  	config_t *c;
  
  	mutex_lock(&s->ops_mutex);
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
400
  	if (!p_dev->_io)
94a819f80   Dominik Brodowski   pcmcia: assert lo...
401
  		goto out;
5f2a71fcb   Dominik Brodowski   [PATCH] pcmcia: a...
402

2ce4905e4   Dominik Brodowski   pcmcia: use struc...
403
  	c = p_dev->function_config;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
404

2ce4905e4   Dominik Brodowski   pcmcia: use struc...
405
  	release_io_space(s, &c->io[0]);
5f2a71fcb   Dominik Brodowski   [PATCH] pcmcia: a...
406

2ce4905e4   Dominik Brodowski   pcmcia: use struc...
407
408
  	if (c->io[1].end)
  		release_io_space(s, &c->io[1]);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
409

2ce4905e4   Dominik Brodowski   pcmcia: use struc...
410
411
  	p_dev->_io = 0;
  	c->state &= ~CONFIG_IO_REQ;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
412

94a819f80   Dominik Brodowski   pcmcia: assert lo...
413
414
415
416
  out:
  	mutex_unlock(&s->ops_mutex);
  
  	return ret;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
417
  } /* pcmcia_release_io */
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
418

9485ee14e   Dominik Brodowski   pcmcia: Documenta...
419

cdb138080   Dominik Brodowski   pcmcia: do not us...
420
421
  /**
   * pcmcia_release_window() - release reserved iomem for PCMCIA devices
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
422
423
   * @p_dev: pcmcia device
   * @res: iomem resource to release
cdb138080   Dominik Brodowski   pcmcia: do not us...
424
   *
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
425
   * pcmcia_release_window() releases &struct resource *res which was
cdb138080   Dominik Brodowski   pcmcia: do not us...
426
427
   * previously reserved by calling pcmcia_request_window().
   */
0ca724d37   Dominik Brodowski   pcmcia: use struc...
428
  int pcmcia_release_window(struct pcmcia_device *p_dev, struct resource *res)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
429
  {
0bdf9b3dd   Magnus Damm   pcmcia: Change wi...
430
  	struct pcmcia_socket *s = p_dev->socket;
82f88e360   Dominik Brodowski   pcmcia: remove un...
431
  	pccard_mem_map *win;
0ca724d37   Dominik Brodowski   pcmcia: use struc...
432
  	unsigned int w;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
433

0ca724d37   Dominik Brodowski   pcmcia: use struc...
434
435
436
437
438
  	dev_dbg(&p_dev->dev, "releasing window %pR
  ", res);
  
  	w = ((res->flags & IORESOURCE_BITS & WIN_FLAGS_REQ) >> 2) - 1;
  	if (w >= MAX_WIN)
ffb8da202   Dominik Brodowski   pcmcia: deprecate...
439
  		return -EINVAL;
0bdf9b3dd   Magnus Damm   pcmcia: Change wi...
440

6b8e087b8   Dominik Brodowski   pcmcia: add locki...
441
  	mutex_lock(&s->ops_mutex);
0ca724d37   Dominik Brodowski   pcmcia: use struc...
442
  	win = &s->win[w];
0bdf9b3dd   Magnus Damm   pcmcia: Change wi...
443

0ca724d37   Dominik Brodowski   pcmcia: use struc...
444
  	if (!(p_dev->_win & CLIENT_WIN_REQ(w))) {
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
445
446
  		dev_dbg(&p_dev->dev, "not releasing unknown window
  ");
6b8e087b8   Dominik Brodowski   pcmcia: add locki...
447
  		mutex_unlock(&s->ops_mutex);
ffb8da202   Dominik Brodowski   pcmcia: deprecate...
448
  		return -EINVAL;
6d9a299f6   Dominik Brodowski   pcmcia: extend er...
449
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
450
451
  
  	/* Shut down memory window */
82f88e360   Dominik Brodowski   pcmcia: remove un...
452
453
  	win->flags &= ~MAP_ACTIVE;
  	s->ops->set_mem_map(s, win);
0ca724d37   Dominik Brodowski   pcmcia: use struc...
454
  	s->state &= ~SOCKET_WIN_REQ(w);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
455
456
  
  	/* Release system memory */
82f88e360   Dominik Brodowski   pcmcia: remove un...
457
  	if (win->res) {
ad0c7be28   Dominik Brodowski   pcmcia: insert PC...
458
  		release_resource(res);
82f88e360   Dominik Brodowski   pcmcia: remove un...
459
460
461
  		release_resource(win->res);
  		kfree(win->res);
  		win->res = NULL;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
462
  	}
cdb138080   Dominik Brodowski   pcmcia: do not us...
463
464
  	res->start = res->end = 0;
  	res->flags = IORESOURCE_MEM;
0ca724d37   Dominik Brodowski   pcmcia: use struc...
465
  	p_dev->_win &= ~CLIENT_WIN_REQ(w);
6b8e087b8   Dominik Brodowski   pcmcia: add locki...
466
  	mutex_unlock(&s->ops_mutex);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
467

4c89e88bf   Dominik Brodowski   pcmcia: deprecate...
468
  	return 0;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
469
470
  } /* pcmcia_release_window */
  EXPORT_SYMBOL(pcmcia_release_window);
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
471

1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
472
473
  /**
   * pcmcia_enable_device() - set up and activate a PCMCIA device
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
474
   * @p_dev: the associated PCMCIA device
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
475
   *
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
476
477
478
479
   * pcmcia_enable_device() physically enables a PCMCIA device. It parses
   * the flags passed to in @flags and stored in @p_dev->flags and sets up
   * the Vpp voltage, enables the speaker line, I/O ports and store proper
   * values to configuration registers.
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
480
481
   */
  int pcmcia_enable_device(struct pcmcia_device *p_dev)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
482
483
  {
  	int i;
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
484
  	unsigned int base;
2bc5a9bdc   Dominik Brodowski   [PATCH] pcmcia: r...
485
  	struct pcmcia_socket *s = p_dev->socket;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
486
487
  	config_t *c;
  	pccard_io_map iomap;
fc3011010   Dominik Brodowski   pcmcia: simplify ...
488
489
  	unsigned char status = 0;
  	unsigned char ext_status = 0;
7feabb641   Dominik Brodowski   pcmcia: move conf...
490
  	unsigned char option = 0;
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
491
  	unsigned int flags = p_dev->config_flags;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
492

1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
493
  	if (!(s->state & SOCKET_PRESENT))
d598de021   Joe Perches   pcmcia: drivers/p...
494
  		return -ENODEV;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
495

94a819f80   Dominik Brodowski   pcmcia: assert lo...
496
  	mutex_lock(&s->ops_mutex);
dbb22f0d6   Dominik Brodowski   [PATCH] pcmcia: a...
497
  	c = p_dev->function_config;
6d9a299f6   Dominik Brodowski   pcmcia: extend er...
498
  	if (c->state & CONFIG_LOCKED) {
94a819f80   Dominik Brodowski   pcmcia: assert lo...
499
  		mutex_unlock(&s->ops_mutex);
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
500
501
  		dev_dbg(&p_dev->dev, "Configuration is locked
  ");
943f70f1b   Dominik Brodowski   pcmcia: deprecate...
502
  		return -EACCES;
6d9a299f6   Dominik Brodowski   pcmcia: extend er...
503
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
504
505
  
  	/* Do power control.  We don't allow changes in Vcc. */
e8405f0f6   Dominik Brodowski   pcmcia: move Vpp ...
506
  	s->socket.Vpp = p_dev->vpp;
d8b0a49da   Dominik Brodowski   pcmcia: deprecate...
507
  	if (s->ops->set_socket(s, &s->socket)) {
9e86749cf   Dominik Brodowski   pcmcia: lock ops-...
508
  		mutex_unlock(&s->ops_mutex);
f2e6cf767   Joe Perches   pcmcia: Convert d...
509
510
  		dev_warn(&p_dev->dev, "Unable to set socket state
  ");
d8b0a49da   Dominik Brodowski   pcmcia: deprecate...
511
512
  		return -EINVAL;
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
513

1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
514
  	/* Pick memory or I/O card, DMA mode, interrupt */
ff10fca5c   Dominik Brodowski   pcmcia: IOCARD is...
515
516
517
  	if (p_dev->_io || flags & CONF_ENABLE_IRQ)
  		flags |= CONF_ENABLE_IOCARD;
  	if (flags & CONF_ENABLE_IOCARD)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
518
  		s->socket.flags |= SS_IOCARD;
33619f0d3   Dominik Brodowski   pcmcia: re-enable...
519
520
  	if (flags & CONF_ENABLE_ZVCARD)
  		s->socket.flags |= SS_ZVCARD | SS_IOCARD;
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
521
  	if (flags & CONF_ENABLE_SPKR) {
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
522
  		s->socket.flags |= SS_SPKR_ENA;
fc3011010   Dominik Brodowski   pcmcia: simplify ...
523
  		status = CCSR_AUDIO_ENA;
7feabb641   Dominik Brodowski   pcmcia: move conf...
524
  		if (!(p_dev->config_regs & PRESENT_STATUS))
fc3011010   Dominik Brodowski   pcmcia: simplify ...
525
526
527
528
  			dev_warn(&p_dev->dev, "speaker requested, but "
  					      "PRESENT_STATUS not set!
  ");
  	}
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
529
  	if (flags & CONF_ENABLE_IRQ)
6f840afb4   Dominik Brodowski   pcmcia: replace s...
530
  		s->socket.io_irq = s->pcmcia_irq;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
531
532
  	else
  		s->socket.io_irq = 0;
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
533
  	if (flags & CONF_ENABLE_ESR) {
7feabb641   Dominik Brodowski   pcmcia: move conf...
534
  		p_dev->config_regs |= PRESENT_EXT_STATUS;
fc3011010   Dominik Brodowski   pcmcia: simplify ...
535
536
  		ext_status = ESR_REQ_ATTN_ENA;
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
537
538
  	s->ops->set_socket(s, &s->socket);
  	s->lock_count++;
1c4a77bf5   Dominik Brodowski   pcmcia: add a few...
539
540
541
542
543
  	dev_dbg(&p_dev->dev,
  		"enable_device: V %d, flags %x, base %x, regs %x, idx %x
  ",
  		p_dev->vpp, flags, p_dev->config_base, p_dev->config_regs,
  		p_dev->config_index);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
544
  	/* Set up CIS configuration registers */
7feabb641   Dominik Brodowski   pcmcia: move conf...
545
546
  	base = p_dev->config_base;
  	if (p_dev->config_regs & PRESENT_COPY) {
1a4a04603   Dominik Brodowski   pcmcia: remove Pi...
547
548
549
550
551
  		u16 tmp = 0;
  		dev_dbg(&p_dev->dev, "clearing CISREG_SCR
  ");
  		pcmcia_write_cis_mem(s, 1, (base + CISREG_SCR)>>1, 1, &tmp);
  	}
7feabb641   Dominik Brodowski   pcmcia: move conf...
552
  	if (p_dev->config_regs & PRESENT_PIN_REPLACE) {
1a4a04603   Dominik Brodowski   pcmcia: remove Pi...
553
554
555
556
  		u16 tmp = 0;
  		dev_dbg(&p_dev->dev, "clearing CISREG_PRR
  ");
  		pcmcia_write_cis_mem(s, 1, (base + CISREG_PRR)>>1, 1, &tmp);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
557
  	}
7feabb641   Dominik Brodowski   pcmcia: move conf...
558
  	if (p_dev->config_regs & PRESENT_OPTION) {
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
559
  		if (s->functions == 1) {
7feabb641   Dominik Brodowski   pcmcia: move conf...
560
  			option = p_dev->config_index & COR_CONFIG_MASK;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
561
  		} else {
7feabb641   Dominik Brodowski   pcmcia: move conf...
562
563
564
565
  			option = p_dev->config_index & COR_MFC_CONFIG_MASK;
  			option |= COR_FUNC_ENA|COR_IREQ_ENA;
  			if (p_dev->config_regs & PRESENT_IOBASE_0)
  				option |= COR_ADDR_DECODE;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
566
  		}
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
567
568
  		if ((flags & CONF_ENABLE_IRQ) &&
  			!(flags & CONF_ENABLE_PULSE_IRQ))
7feabb641   Dominik Brodowski   pcmcia: move conf...
569
570
  			option |= COR_LEVEL_REQ;
  		pcmcia_write_cis_mem(s, 1, (base + CISREG_COR)>>1, 1, &option);
1b22dcf6b   Jia-Ju Bai   pcmcia: pcmcia_re...
571
  		msleep(40);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
572
  	}
7feabb641   Dominik Brodowski   pcmcia: move conf...
573
  	if (p_dev->config_regs & PRESENT_STATUS)
fc3011010   Dominik Brodowski   pcmcia: simplify ...
574
  		pcmcia_write_cis_mem(s, 1, (base + CISREG_CCSR)>>1, 1, &status);
7feabb641   Dominik Brodowski   pcmcia: move conf...
575
  	if (p_dev->config_regs & PRESENT_EXT_STATUS)
fc3011010   Dominik Brodowski   pcmcia: simplify ...
576
577
  		pcmcia_write_cis_mem(s, 1, (base + CISREG_ESR)>>1, 1,
  					&ext_status);
7feabb641   Dominik Brodowski   pcmcia: move conf...
578
  	if (p_dev->config_regs & PRESENT_IOBASE_0) {
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
579
  		u8 b = c->io[0].start & 0xff;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
580
  		pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_0)>>1, 1, &b);
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
581
  		b = (c->io[0].start >> 8) & 0xff;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
582
583
  		pcmcia_write_cis_mem(s, 1, (base + CISREG_IOBASE_1)>>1, 1, &b);
  	}
7feabb641   Dominik Brodowski   pcmcia: move conf...
584
  	if (p_dev->config_regs & PRESENT_IOSIZE) {
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
585
  		u8 b = resource_size(&c->io[0]) + resource_size(&c->io[1]) - 1;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
586
587
588
589
590
591
592
  		pcmcia_write_cis_mem(s, 1, (base + CISREG_IOSIZE)>>1, 1, &b);
  	}
  
  	/* Configure I/O windows */
  	if (c->state & CONFIG_IO_REQ) {
  		iomap.speed = io_speed;
  		for (i = 0; i < MAX_IO_WIN; i++)
c7d006935   Dominik Brodowski   [PATCH] pcmcia: r...
593
  			if (s->io[i].res) {
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
594
595
  				iomap.map = i;
  				iomap.flags = MAP_ACTIVE;
c7d006935   Dominik Brodowski   [PATCH] pcmcia: r...
596
  				switch (s->io[i].res->flags & IO_DATA_PATH_WIDTH) {
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
597
598
599
600
601
602
603
  				case IO_DATA_PATH_WIDTH_16:
  					iomap.flags |= MAP_16BIT; break;
  				case IO_DATA_PATH_WIDTH_AUTO:
  					iomap.flags |= MAP_AUTOSZ; break;
  				default:
  					break;
  				}
c7d006935   Dominik Brodowski   [PATCH] pcmcia: r...
604
605
  				iomap.start = s->io[i].res->start;
  				iomap.stop = s->io[i].res->end;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
606
607
608
609
610
611
  				s->ops->set_io_map(s, &iomap);
  				s->io[i].Config++;
  			}
  	}
  
  	c->state |= CONFIG_LOCKED;
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
612
  	p_dev->_locked = 1;
059f667d9   Dominik Brodowski   pcmcia: call pcmc...
613
  	mutex_unlock(&s->ops_mutex);
4c89e88bf   Dominik Brodowski   pcmcia: deprecate...
614
  	return 0;
1ac71e5a3   Dominik Brodowski   pcmcia: convert p...
615
616
  } /* pcmcia_enable_device */
  EXPORT_SYMBOL(pcmcia_enable_device);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
617

2ce4905e4   Dominik Brodowski   pcmcia: use struc...
618
619
  /**
   * pcmcia_request_io() - attempt to reserve port ranges for PCMCIA devices
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
620
   * @p_dev: the associated PCMCIA device
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
621
   *
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
622
   * pcmcia_request_io() attempts to reserve the IO port ranges specified in
90abdc3b9   Dominik Brodowski   pcmcia: do not us...
623
   * &struct pcmcia_device @p_dev->resource[0] and @p_dev->resource[1]. The
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
624
   * "start" value is the requested start of the IO port resource; "end"
90abdc3b9   Dominik Brodowski   pcmcia: do not us...
625
626
   * reflects the number of ports requested. The number of IO lines requested
   * is specified in &struct pcmcia_device @p_dev->io_lines.
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
627
   */
90abdc3b9   Dominik Brodowski   pcmcia: do not us...
628
  int pcmcia_request_io(struct pcmcia_device *p_dev)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
629
  {
2bc5a9bdc   Dominik Brodowski   [PATCH] pcmcia: r...
630
  	struct pcmcia_socket *s = p_dev->socket;
90abdc3b9   Dominik Brodowski   pcmcia: do not us...
631
  	config_t *c = p_dev->function_config;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
632
633
634
  	int ret = -EINVAL;
  
  	mutex_lock(&s->ops_mutex);
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
635
636
  	dev_dbg(&p_dev->dev, "pcmcia_request_io: %pR , %pR",
  		&c->io[0], &c->io[1]);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
637

6d9a299f6   Dominik Brodowski   pcmcia: extend er...
638
  	if (!(s->state & SOCKET_PRESENT)) {
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
639
640
  		dev_dbg(&p_dev->dev, "pcmcia_request_io: No card present
  ");
94a819f80   Dominik Brodowski   pcmcia: assert lo...
641
  		goto out;
6d9a299f6   Dominik Brodowski   pcmcia: extend er...
642
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
643

6d9a299f6   Dominik Brodowski   pcmcia: extend er...
644
  	if (c->state & CONFIG_LOCKED) {
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
645
646
  		dev_dbg(&p_dev->dev, "Configuration is locked
  ");
94a819f80   Dominik Brodowski   pcmcia: assert lo...
647
  		goto out;
6d9a299f6   Dominik Brodowski   pcmcia: extend er...
648
  	}
f958095ef   Dominik Brodowski   pcmcia: deprecate...
649
  	if (c->state & CONFIG_IO_REQ) {
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
650
651
  		dev_dbg(&p_dev->dev, "IO already configured
  ");
94a819f80   Dominik Brodowski   pcmcia: assert lo...
652
  		goto out;
f958095ef   Dominik Brodowski   pcmcia: deprecate...
653
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
654

90abdc3b9   Dominik Brodowski   pcmcia: do not us...
655
  	ret = alloc_io_space(s, &c->io[0], p_dev->io_lines);
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
656
  	if (ret)
94a819f80   Dominik Brodowski   pcmcia: assert lo...
657
  		goto out;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
658

2ce4905e4   Dominik Brodowski   pcmcia: use struc...
659
  	if (c->io[1].end) {
90abdc3b9   Dominik Brodowski   pcmcia: do not us...
660
  		ret = alloc_io_space(s, &c->io[1], p_dev->io_lines);
94a819f80   Dominik Brodowski   pcmcia: assert lo...
661
  		if (ret) {
7cdffc865   Dominik Brodowski   pcmcia: preserve ...
662
663
  			struct resource tmp = c->io[0];
  			/* release the previously allocated resource */
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
664
  			release_io_space(s, &c->io[0]);
7cdffc865   Dominik Brodowski   pcmcia: preserve ...
665
666
667
668
  			/* but preserve the settings, for they worked... */
  			c->io[0].end = resource_size(&tmp);
  			c->io[0].start = tmp.start;
  			c->io[0].flags = tmp.flags;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
669
  			goto out;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
670
  		}
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
671
672
  	} else
  		c->io[1].start = 0;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
673

1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
674
  	c->state |= CONFIG_IO_REQ;
e2d409636   Dominik Brodowski   [PATCH] pcmcia: u...
675
  	p_dev->_io = 1;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
676

eb838fe10   Dominik Brodowski   pcmcia: per-devic...
677
  	dev_dbg(&p_dev->dev, "pcmcia_request_io succeeded: %pR , %pR",
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
678
  		&c->io[0], &c->io[1]);
94a819f80   Dominik Brodowski   pcmcia: assert lo...
679
680
681
682
  out:
  	mutex_unlock(&s->ops_mutex);
  
  	return ret;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
683
684
  } /* pcmcia_request_io */
  EXPORT_SYMBOL(pcmcia_request_io);
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
685
686
  /**
   * pcmcia_request_irq() - attempt to request a IRQ for a PCMCIA device
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
687
688
   * @p_dev: the associated PCMCIA device
   * @handler: IRQ handler to register
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
689
   *
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
690
   * pcmcia_request_irq() is a wrapper around request_irq() which allows
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
691
692
   * the PCMCIA core to clean up the registration in pcmcia_disable_device().
   * Drivers are free to use request_irq() directly, but then they need to
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
693
   * call free_irq() themselfves, too. Also, only %IRQF_SHARED capable IRQ
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
694
   * handlers are allowed.
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
695
   */
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
696
697
  int __must_check pcmcia_request_irq(struct pcmcia_device *p_dev,
  				    irq_handler_t handler)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
698
  {
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
699
  	int ret;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
700

eb14120f7   Dominik Brodowski   pcmcia: re-work p...
701
702
  	if (!p_dev->irq)
  		return -EINVAL;
94a819f80   Dominik Brodowski   pcmcia: assert lo...
703

eb14120f7   Dominik Brodowski   pcmcia: re-work p...
704
705
706
707
  	ret = request_irq(p_dev->irq, handler, IRQF_SHARED,
  			p_dev->devname, p_dev->priv);
  	if (!ret)
  		p_dev->_irq = 1;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
708

eb14120f7   Dominik Brodowski   pcmcia: re-work p...
709
710
711
  	return ret;
  }
  EXPORT_SYMBOL(pcmcia_request_irq);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
712

6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
713
714
715
  #ifdef CONFIG_PCMCIA_PROBE
  
  /* mask of IRQs already reserved by other cards, we should avoid using them */
127c03cdb   Dominik Brodowski   pcmcia: avoid buf...
716
  static u8 pcmcia_used_irq[32];
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
  
  static irqreturn_t test_action(int cpl, void *dev_id)
  {
  	return IRQ_NONE;
  }
  
  /**
   * pcmcia_setup_isa_irq() - determine whether an ISA IRQ can be used
   * @p_dev - the associated PCMCIA device
   *
   * locking note: must be called with ops_mutex locked.
   */
  static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type)
  {
  	struct pcmcia_socket *s = p_dev->socket;
  	unsigned int try, irq;
  	u32 mask = s->irq_mask;
  	int ret = -ENODEV;
  
  	for (try = 0; try < 64; try++) {
  		irq = try % 32;
127c03cdb   Dominik Brodowski   pcmcia: avoid buf...
738
739
  		if (irq > NR_IRQS)
  			continue;
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
  		/* marked as available by driver, not blocked by userspace? */
  		if (!((mask >> irq) & 1))
  			continue;
  
  		/* avoid an IRQ which is already used by another PCMCIA card */
  		if ((try < 32) && pcmcia_used_irq[irq])
  			continue;
  
  		/* register the correct driver, if possible, to check whether
  		 * registering a dummy handle works, i.e. if the IRQ isn't
  		 * marked as used by the kernel resource management core */
  		ret = request_irq(irq, test_action, type, p_dev->devname,
  				  p_dev);
  		if (!ret) {
  			free_irq(irq, p_dev);
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
755
  			p_dev->irq = s->pcmcia_irq = irq;
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
756
757
758
759
760
761
762
763
764
765
  			pcmcia_used_irq[irq]++;
  			break;
  		}
  	}
  
  	return ret;
  }
  
  void pcmcia_cleanup_irq(struct pcmcia_socket *s)
  {
6f840afb4   Dominik Brodowski   pcmcia: replace s...
766
767
  	pcmcia_used_irq[s->pcmcia_irq]--;
  	s->pcmcia_irq = 0;
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
768
769
770
771
772
773
774
775
776
777
778
  }
  
  #else /* CONFIG_PCMCIA_PROBE */
  
  static int pcmcia_setup_isa_irq(struct pcmcia_device *p_dev, int type)
  {
  	return -EINVAL;
  }
  
  void pcmcia_cleanup_irq(struct pcmcia_socket *s)
  {
6f840afb4   Dominik Brodowski   pcmcia: replace s...
779
  	s->pcmcia_irq = 0;
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
  	return;
  }
  
  #endif  /* CONFIG_PCMCIA_PROBE */
  
  
  /**
   * pcmcia_setup_irq() - determine IRQ to be used for device
   * @p_dev - the associated PCMCIA device
   *
   * locking note: must be called with ops_mutex locked.
   */
  int pcmcia_setup_irq(struct pcmcia_device *p_dev)
  {
  	struct pcmcia_socket *s = p_dev->socket;
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
795
  	if (p_dev->irq)
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
796
797
798
  		return 0;
  
  	/* already assigned? */
6f840afb4   Dominik Brodowski   pcmcia: replace s...
799
  	if (s->pcmcia_irq) {
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
800
  		p_dev->irq = s->pcmcia_irq;
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
801
802
803
804
805
806
807
808
809
810
811
812
813
  		return 0;
  	}
  
  	/* prefer an exclusive ISA irq */
  	if (!pcmcia_setup_isa_irq(p_dev, 0))
  		return 0;
  
  	/* but accept a shared ISA irq */
  	if (!pcmcia_setup_isa_irq(p_dev, IRQF_SHARED))
  		return 0;
  
  	/* but use the PCI irq otherwise */
  	if (s->pci_irq) {
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
814
  		p_dev->irq = s->pcmcia_irq = s->pci_irq;
6f0f38c45   Dominik Brodowski   pcmcia: setup IRQ...
815
816
817
818
819
  		return 0;
  	}
  
  	return -EINVAL;
  }
cdb138080   Dominik Brodowski   pcmcia: do not us...
820
821
  /**
   * pcmcia_request_window() - attempt to reserve iomem for PCMCIA devices
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
822
823
824
   * @p_dev: the associated PCMCIA device
   * @res: &struct resource pointing to p_dev->resource[2..5]
   * @speed: access speed
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
825
   *
cdb138080   Dominik Brodowski   pcmcia: do not us...
826
   * pcmcia_request_window() attepts to reserve an iomem ranges specified in
9485ee14e   Dominik Brodowski   pcmcia: Documenta...
827
828
   * &struct resource @res pointing to one of the entries in
   * &struct pcmcia_device @p_dev->resource[2..5]. The "start" value is the
cdb138080   Dominik Brodowski   pcmcia: do not us...
829
830
   * requested start of the IO mem resource; "end" reflects the size
   * requested.
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
831
   */
cdb138080   Dominik Brodowski   pcmcia: do not us...
832
833
  int pcmcia_request_window(struct pcmcia_device *p_dev, struct resource *res,
  			unsigned int speed)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
834
  {
6838b03fc   Dominik Brodowski   pcmcia: pcmcia_re...
835
  	struct pcmcia_socket *s = p_dev->socket;
82f88e360   Dominik Brodowski   pcmcia: remove un...
836
  	pccard_mem_map *win;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
837
838
  	u_long align;
  	int w;
1c4a77bf5   Dominik Brodowski   pcmcia: add a few...
839
840
  	dev_dbg(&p_dev->dev, "request_window %pR %d
  ", res, speed);
6d9a299f6   Dominik Brodowski   pcmcia: extend er...
841
  	if (!(s->state & SOCKET_PRESENT)) {
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
842
843
  		dev_dbg(&p_dev->dev, "No card present
  ");
3939c1ef1   Dominik Brodowski   pcmcia: deprecate...
844
  		return -ENODEV;
6d9a299f6   Dominik Brodowski   pcmcia: extend er...
845
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
846
847
  
  	/* Window size defaults to smallest available */
cdb138080   Dominik Brodowski   pcmcia: do not us...
848
849
850
851
  	if (res->end == 0)
  		res->end = s->map_size;
  	align = (s->features & SS_CAP_MEM_ALIGN) ? res->end : s->map_size;
  	if (res->end & (s->map_size-1)) {
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
852
853
  		dev_dbg(&p_dev->dev, "invalid map size
  ");
69ba44331   Dominik Brodowski   pcmcia: deprecate...
854
855
  		return -EINVAL;
  	}
cdb138080   Dominik Brodowski   pcmcia: do not us...
856
857
  	if ((res->start && (s->features & SS_CAP_STATIC_MAP)) ||
  	    (res->start & (align-1))) {
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
858
859
  		dev_dbg(&p_dev->dev, "invalid base address
  ");
69ba44331   Dominik Brodowski   pcmcia: deprecate...
860
861
  		return -EINVAL;
  	}
cdb138080   Dominik Brodowski   pcmcia: do not us...
862
  	if (res->start)
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
863
864
865
  		align = 0;
  
  	/* Allocate system memory window */
0ca724d37   Dominik Brodowski   pcmcia: use struc...
866
  	mutex_lock(&s->ops_mutex);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
867
  	for (w = 0; w < MAX_WIN; w++)
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
868
869
  		if (!(s->state & SOCKET_WIN_REQ(w)))
  			break;
f958095ef   Dominik Brodowski   pcmcia: deprecate...
870
  	if (w == MAX_WIN) {
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
871
872
  		dev_dbg(&p_dev->dev, "all windows are used already
  ");
0ca724d37   Dominik Brodowski   pcmcia: use struc...
873
  		mutex_unlock(&s->ops_mutex);
f958095ef   Dominik Brodowski   pcmcia: deprecate...
874
875
  		return -EINVAL;
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
876
877
  
  	win = &s->win[w];
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
878
879
  
  	if (!(s->features & SS_CAP_STATIC_MAP)) {
cdb138080   Dominik Brodowski   pcmcia: do not us...
880
  		win->res = pcmcia_find_mem_region(res->start, res->end, align,
0ca724d37   Dominik Brodowski   pcmcia: use struc...
881
  						0, s);
82f88e360   Dominik Brodowski   pcmcia: remove un...
882
  		if (!win->res) {
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
883
884
  			dev_dbg(&p_dev->dev, "allocating mem region failed
  ");
6b8e087b8   Dominik Brodowski   pcmcia: add locki...
885
  			mutex_unlock(&s->ops_mutex);
f958095ef   Dominik Brodowski   pcmcia: deprecate...
886
887
  			return -EINVAL;
  		}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
888
  	}
6838b03fc   Dominik Brodowski   pcmcia: pcmcia_re...
889
  	p_dev->_win |= CLIENT_WIN_REQ(w);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
890
891
  
  	/* Configure the socket controller */
82f88e360   Dominik Brodowski   pcmcia: remove un...
892
  	win->map = w+1;
cdb138080   Dominik Brodowski   pcmcia: do not us...
893
894
  	win->flags = res->flags & WIN_FLAGS_MAP;
  	win->speed = speed;
82f88e360   Dominik Brodowski   pcmcia: remove un...
895
  	win->card_start = 0;
6b8e087b8   Dominik Brodowski   pcmcia: add locki...
896

82f88e360   Dominik Brodowski   pcmcia: remove un...
897
  	if (s->ops->set_mem_map(s, win) != 0) {
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
898
899
  		dev_dbg(&p_dev->dev, "failed to set memory mapping
  ");
6b8e087b8   Dominik Brodowski   pcmcia: add locki...
900
  		mutex_unlock(&s->ops_mutex);
926c5402c   Dominik Brodowski   pcmcia: deprecate...
901
902
  		return -EIO;
  	}
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
903
904
905
  	s->state |= SOCKET_WIN_REQ(w);
  
  	/* Return window handle */
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
906
  	if (s->features & SS_CAP_STATIC_MAP)
cdb138080   Dominik Brodowski   pcmcia: do not us...
907
  		res->start = win->static_start;
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
908
  	else
cdb138080   Dominik Brodowski   pcmcia: do not us...
909
  		res->start = win->res->start;
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
910

0ca724d37   Dominik Brodowski   pcmcia: use struc...
911
  	/* convert to new-style resources */
cdb138080   Dominik Brodowski   pcmcia: do not us...
912
913
914
  	res->end += res->start - 1;
  	res->flags &= ~WIN_FLAGS_REQ;
  	res->flags |= (win->map << 2) | IORESOURCE_MEM;
ad0c7be28   Dominik Brodowski   pcmcia: insert PC...
915
916
917
  	res->parent = win->res;
  	if (win->res)
  		request_resource(&iomem_resource, res);
eb838fe10   Dominik Brodowski   pcmcia: per-devic...
918
919
  	dev_dbg(&p_dev->dev, "request_window results in %pR
  ", res);
0ca724d37   Dominik Brodowski   pcmcia: use struc...
920

6b8e087b8   Dominik Brodowski   pcmcia: add locki...
921
  	mutex_unlock(&s->ops_mutex);
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
922

4c89e88bf   Dominik Brodowski   pcmcia: deprecate...
923
  	return 0;
1a8d46631   Dominik Brodowski   [PATCH] pcmcia: m...
924
925
  } /* pcmcia_request_window */
  EXPORT_SYMBOL(pcmcia_request_window);
5f2a71fcb   Dominik Brodowski   [PATCH] pcmcia: a...
926

9485ee14e   Dominik Brodowski   pcmcia: Documenta...
927
928
929
930
931
932
933
934
935
936
937
938
939
  
  /**
   * pcmcia_disable_device() - disable and clean up a PCMCIA device
   * @p_dev: the associated PCMCIA device
   *
   * pcmcia_disable_device() is the driver-callable counterpart to
   * pcmcia_enable_device(): If a PCMCIA device is no longer used,
   * drivers are expected to clean up and disable the device by calling
   * this function. Any I/O ranges (iomem and ioports) will be released,
   * the Vpp voltage will be set to 0, and IRQs will no longer be
   * generated -- at least if there is no other card function (of
   * multifunction devices) being used.
   */
9fea84f46   Dominik Brodowski   pcmcia: CodingSty...
940
941
  void pcmcia_disable_device(struct pcmcia_device *p_dev)
  {
0ca724d37   Dominik Brodowski   pcmcia: use struc...
942
  	int i;
1c4a77bf5   Dominik Brodowski   pcmcia: add a few...
943
944
945
  
  	dev_dbg(&p_dev->dev, "disabling device
  ");
0ca724d37   Dominik Brodowski   pcmcia: use struc...
946
947
948
949
950
  	for (i = 0; i < MAX_WIN; i++) {
  		struct resource *res = p_dev->resource[MAX_IO_WIN + i];
  		if (res->flags & WIN_FLAGS_REQ)
  			pcmcia_release_window(p_dev, res);
  	}
5f2a71fcb   Dominik Brodowski   [PATCH] pcmcia: a...
951
  	pcmcia_release_configuration(p_dev);
2ce4905e4   Dominik Brodowski   pcmcia: use struc...
952
  	pcmcia_release_io(p_dev);
418c52787   Patrick McHardy   pcmcia: fix 'driv...
953
  	if (p_dev->_irq) {
eb14120f7   Dominik Brodowski   pcmcia: re-work p...
954
  		free_irq(p_dev->irq, p_dev->priv);
418c52787   Patrick McHardy   pcmcia: fix 'driv...
955
956
  		p_dev->_irq = 0;
  	}
5f2a71fcb   Dominik Brodowski   [PATCH] pcmcia: a...
957
958
  }
  EXPORT_SYMBOL(pcmcia_disable_device);