Blame view

drivers/firewire/init_ohci1394_dma.c 9.61 KB
f212ec4b7   Bernhard Kaindl   x86: early boot d...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
  /*
   * init_ohci1394_dma.c - Initializes physical DMA on all OHCI 1394 controllers
   *
   * Copyright (C) 2006-2007      Bernhard Kaindl <bk@suse.de>
   *
   * Derived from drivers/ieee1394/ohci1394.c and arch/x86/kernel/early-quirks.c
   * this file has functions to:
   * - scan the PCI very early on boot for all OHCI 1394-compliant controllers
   * - reset and initialize them and make them join the IEEE1394 bus and
   * - enable physical DMA on them to allow remote debugging
   *
   * All code and data is marked as __init and __initdata, respective as
   * during boot, all OHCI1394 controllers may be claimed by the firewire
   * stack and at this point, this code should not touch them anymore.
   *
   * To use physical DMA after the initialization of the firewire stack,
   * be sure that the stack enables it and (re-)attach after the bus reset
   * which may be caused by the firewire stack initialization.
   *
   * This program is free software; you can redistribute it and/or modify
   * it under the terms of the GNU General Public License as published by
   * the Free Software Foundation; either version 2 of the License, or
   * (at your option) any later version.
   *
   * This program is distributed in the hope that it will be useful,
   * but WITHOUT ANY WARRANTY; without even the implied warranty of
   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   * GNU General Public License for more details.
   *
   * You should have received a copy of the GNU General Public License
   * along with this program; if not, write to the Free Software Foundation,
   * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
   */
f212ec4b7   Bernhard Kaindl   x86: early boot d...
34
  #include <linux/delay.h>
1ef5b816c   Stefan Richter   ieee1394: move in...
35
36
  #include <linux/io.h>
  #include <linux/kernel.h>
f212ec4b7   Bernhard Kaindl   x86: early boot d...
37
  #include <linux/pci.h>		/* for PCI defines */
1ef5b816c   Stefan Richter   ieee1394: move in...
38
  #include <linux/string.h>
f212ec4b7   Bernhard Kaindl   x86: early boot d...
39
40
  #include <asm/pci-direct.h>	/* for direct PCI config space access */
  #include <asm/fixmap.h>
1ef5b816c   Stefan Richter   ieee1394: move in...
41
42
  #include <linux/init_ohci1394_dma.h>
  #include "ohci.h"
f212ec4b7   Bernhard Kaindl   x86: early boot d...
43
44
  
  int __initdata init_ohci1394_dma_early;
1ef5b816c   Stefan Richter   ieee1394: move in...
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
  struct ohci {
  	void __iomem *registers;
  };
  
  static inline void reg_write(const struct ohci *ohci, int offset, u32 data)
  {
  	writel(data, ohci->registers + offset);
  }
  
  static inline u32 reg_read(const struct ohci *ohci, int offset)
  {
  	return readl(ohci->registers + offset);
  }
  
  #define OHCI_LOOP_COUNT		100	/* Number of loops for reg read waits */
f212ec4b7   Bernhard Kaindl   x86: early boot d...
60
  /* Reads a PHY register of an OHCI-1394 controller */
1ef5b816c   Stefan Richter   ieee1394: move in...
61
  static inline u8 __init get_phy_reg(struct ohci *ohci, u8 addr)
f212ec4b7   Bernhard Kaindl   x86: early boot d...
62
63
  {
  	int i;
1ef5b816c   Stefan Richter   ieee1394: move in...
64
  	u32 r;
f212ec4b7   Bernhard Kaindl   x86: early boot d...
65
66
67
68
69
70
71
72
73
74
75
76
77
78
  
  	reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | 0x00008000);
  
  	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
  		if (reg_read(ohci, OHCI1394_PhyControl) & 0x80000000)
  			break;
  		mdelay(1);
  	}
  	r = reg_read(ohci, OHCI1394_PhyControl);
  
  	return (r & 0x00ff0000) >> 16;
  }
  
  /* Writes to a PHY register of an OHCI-1394 controller */
1ef5b816c   Stefan Richter   ieee1394: move in...
79
  static inline void __init set_phy_reg(struct ohci *ohci, u8 addr, u8 data)
f212ec4b7   Bernhard Kaindl   x86: early boot d...
80
81
82
83
84
85
  {
  	int i;
  
  	reg_write(ohci, OHCI1394_PhyControl, (addr << 8) | data | 0x00004000);
  
  	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
1ef5b816c   Stefan Richter   ieee1394: move in...
86
  		if (!(reg_read(ohci, OHCI1394_PhyControl) & 0x00004000))
f212ec4b7   Bernhard Kaindl   x86: early boot d...
87
88
89
90
91
92
  			break;
  		mdelay(1);
  	}
  }
  
  /* Resets an OHCI-1394 controller (for sane state before initialization) */
1ef5b816c   Stefan Richter   ieee1394: move in...
93
94
  static inline void __init init_ohci1394_soft_reset(struct ohci *ohci)
  {
f212ec4b7   Bernhard Kaindl   x86: early boot d...
95
96
97
98
99
100
101
102
103
104
105
  	int i;
  
  	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_softReset);
  
  	for (i = 0; i < OHCI_LOOP_COUNT; i++) {
  		if (!(reg_read(ohci, OHCI1394_HCControlSet)
  				   & OHCI1394_HCControl_softReset))
  			break;
  		mdelay(1);
  	}
  }
1ef5b816c   Stefan Richter   ieee1394: move in...
106
107
108
  #define OHCI1394_MAX_AT_REQ_RETRIES	0xf
  #define OHCI1394_MAX_AT_RESP_RETRIES	0x2
  #define OHCI1394_MAX_PHYS_RESP_RETRIES	0x8
f212ec4b7   Bernhard Kaindl   x86: early boot d...
109
  /* Basic OHCI-1394 register and port inititalization */
1ef5b816c   Stefan Richter   ieee1394: move in...
110
  static inline void __init init_ohci1394_initialize(struct ohci *ohci)
f212ec4b7   Bernhard Kaindl   x86: early boot d...
111
  {
1ef5b816c   Stefan Richter   ieee1394: move in...
112
  	u32 bus_options;
f212ec4b7   Bernhard Kaindl   x86: early boot d...
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
  	int num_ports, i;
  
  	/* Put some defaults to these undefined bus options */
  	bus_options = reg_read(ohci, OHCI1394_BusOptions);
  	bus_options |=  0x60000000; /* Enable CMC and ISC */
  	bus_options &= ~0x00ff0000; /* XXX: Set cyc_clk_acc to zero for now */
  	bus_options &= ~0x18000000; /* Disable PMC and BMC */
  	reg_write(ohci, OHCI1394_BusOptions, bus_options);
  
  	/* Set the bus number */
  	reg_write(ohci, OHCI1394_NodeID, 0x0000ffc0);
  
  	/* Enable posted writes */
  	reg_write(ohci, OHCI1394_HCControlSet,
  			OHCI1394_HCControl_postedWriteEnable);
  
  	/* Clear link control register */
  	reg_write(ohci, OHCI1394_LinkControlClear, 0xffffffff);
  
  	/* enable phys */
  	reg_write(ohci, OHCI1394_LinkControlSet,
1ef5b816c   Stefan Richter   ieee1394: move in...
134
  			OHCI1394_LinkControl_rcvPhyPkt);
f212ec4b7   Bernhard Kaindl   x86: early boot d...
135
136
137
138
139
140
141
142
143
  
  	/* Don't accept phy packets into AR request context */
  	reg_write(ohci, OHCI1394_LinkControlClear, 0x00000400);
  
  	/* Clear the Isochonouys interrupt masks */
  	reg_write(ohci, OHCI1394_IsoRecvIntMaskClear, 0xffffffff);
  	reg_write(ohci, OHCI1394_IsoRecvIntEventClear, 0xffffffff);
  	reg_write(ohci, OHCI1394_IsoXmitIntMaskClear, 0xffffffff);
  	reg_write(ohci, OHCI1394_IsoXmitIntEventClear, 0xffffffff);
b3834be5c   Adam Buchbinder   various: Fix spel...
144
  	/* Accept asynchronous transfer requests from all nodes for now */
1ef5b816c   Stefan Richter   ieee1394: move in...
145
  	reg_write(ohci, OHCI1394_AsReqFilterHiSet, 0x80000000);
f212ec4b7   Bernhard Kaindl   x86: early boot d...
146

b3834be5c   Adam Buchbinder   various: Fix spel...
147
  	/* Specify asynchronous transfer retries */
f212ec4b7   Bernhard Kaindl   x86: early boot d...
148
149
150
151
152
153
  	reg_write(ohci, OHCI1394_ATRetries,
  		  OHCI1394_MAX_AT_REQ_RETRIES |
  		  (OHCI1394_MAX_AT_RESP_RETRIES<<4) |
  		  (OHCI1394_MAX_PHYS_RESP_RETRIES<<8));
  
  	/* We don't want hardware swapping */
1ef5b816c   Stefan Richter   ieee1394: move in...
154
155
  	reg_write(ohci, OHCI1394_HCControlClear,
  		  OHCI1394_HCControl_noByteSwapData);
f212ec4b7   Bernhard Kaindl   x86: early boot d...
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
  
  	/* Enable link */
  	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_linkEnable);
  
  	/* If anything is connected to a port, make sure it is enabled */
  	num_ports = get_phy_reg(ohci, 2) & 0xf;
  	for (i = 0; i < num_ports; i++) {
  		unsigned int status;
  
  		set_phy_reg(ohci, 7, i);
  		status = get_phy_reg(ohci, 8);
  
  		if (status & 0x20)
  			set_phy_reg(ohci, 8, status & ~1);
  	}
  }
  
  /**
   * init_ohci1394_wait_for_busresets - wait until bus resets are completed
   *
   * OHCI1394 initialization itself and any device going on- or offline
   * and any cable issue cause a IEEE1394 bus reset. The OHCI1394 spec
   * specifies that physical DMA is disabled on each bus reset and it
   * has to be enabled after each bus reset when needed. We resort
   * to polling here because on early boot, we have no interrupts.
   */
1ef5b816c   Stefan Richter   ieee1394: move in...
182
  static inline void __init init_ohci1394_wait_for_busresets(struct ohci *ohci)
f212ec4b7   Bernhard Kaindl   x86: early boot d...
183
184
  {
  	int i, events;
1ef5b816c   Stefan Richter   ieee1394: move in...
185
  	for (i = 0; i < 9; i++) {
f212ec4b7   Bernhard Kaindl   x86: early boot d...
186
187
188
189
190
191
192
193
194
195
196
197
198
  		mdelay(200);
  		events = reg_read(ohci, OHCI1394_IntEventSet);
  		if (events & OHCI1394_busReset)
  			reg_write(ohci, OHCI1394_IntEventClear,
  					OHCI1394_busReset);
  	}
  }
  
  /**
   * init_ohci1394_enable_physical_dma - Enable physical DMA for remote debugging
   * This enables remote DMA access over IEEE1394 from every host for the low
   * 4GB of address space. DMA accesses above 4GB are not available currently.
   */
1ef5b816c   Stefan Richter   ieee1394: move in...
199
  static inline void __init init_ohci1394_enable_physical_dma(struct ohci *ohci)
f212ec4b7   Bernhard Kaindl   x86: early boot d...
200
  {
1ef5b816c   Stefan Richter   ieee1394: move in...
201
202
203
  	reg_write(ohci, OHCI1394_PhyReqFilterHiSet, 0xffffffff);
  	reg_write(ohci, OHCI1394_PhyReqFilterLoSet, 0xffffffff);
  	reg_write(ohci, OHCI1394_PhyUpperBound, 0xffff0000);
f212ec4b7   Bernhard Kaindl   x86: early boot d...
204
205
206
207
208
209
  }
  
  /**
   * init_ohci1394_reset_and_init_dma - init controller and enable DMA
   * This initializes the given controller and enables physical DMA engine in it.
   */
1ef5b816c   Stefan Richter   ieee1394: move in...
210
  static inline void __init init_ohci1394_reset_and_init_dma(struct ohci *ohci)
f212ec4b7   Bernhard Kaindl   x86: early boot d...
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
  {
  	/* Start off with a soft reset, clears everything to a sane state. */
  	init_ohci1394_soft_reset(ohci);
  
  	/* Accessing some registers without LPS enabled may cause lock up */
  	reg_write(ohci, OHCI1394_HCControlSet, OHCI1394_HCControl_LPS);
  
  	/* Disable and clear interrupts */
  	reg_write(ohci, OHCI1394_IntEventClear, 0xffffffff);
  	reg_write(ohci, OHCI1394_IntMaskClear, 0xffffffff);
  
  	mdelay(50); /* Wait 50msec to make sure we have full link enabled */
  
  	init_ohci1394_initialize(ohci);
  	/*
  	 * The initialization causes at least one IEEE1394 bus reset. Enabling
  	 * physical DMA only works *after* *all* bus resets have calmed down:
  	 */
  	init_ohci1394_wait_for_busresets(ohci);
  
  	/* We had to wait and do this now if we want to debug early problems */
  	init_ohci1394_enable_physical_dma(ohci);
  }
  
  /**
   * init_ohci1394_controller - Map the registers of the controller and init DMA
   * This maps the registers of the specified controller and initializes it
   */
  static inline void __init init_ohci1394_controller(int num, int slot, int func)
  {
  	unsigned long ohci_base;
1ef5b816c   Stefan Richter   ieee1394: move in...
242
  	struct ohci ohci;
f212ec4b7   Bernhard Kaindl   x86: early boot d...
243
244
245
246
247
248
249
250
251
  
  	printk(KERN_INFO "init_ohci1394_dma: initializing OHCI-1394"
  			 " at %02x:%02x.%x
  ", num, slot, func);
  
  	ohci_base = read_pci_config(num, slot, func, PCI_BASE_ADDRESS_0+(0<<2))
  						   & PCI_BASE_ADDRESS_MEM_MASK;
  
  	set_fixmap_nocache(FIX_OHCI1394_BASE, ohci_base);
1ef5b816c   Stefan Richter   ieee1394: move in...
252
  	ohci.registers = (void __iomem *)fix_to_virt(FIX_OHCI1394_BASE);
f212ec4b7   Bernhard Kaindl   x86: early boot d...
253
254
255
256
257
258
259
260
261
262
263
  
  	init_ohci1394_reset_and_init_dma(&ohci);
  }
  
  /**
   * debug_init_ohci1394_dma - scan for OHCI1394 controllers and init DMA on them
   * Scans the whole PCI space for OHCI1394 controllers and inits DMA on them
   */
  void __init init_ohci1394_dma_on_all_controllers(void)
  {
  	int num, slot, func;
1ef5b816c   Stefan Richter   ieee1394: move in...
264
  	u32 class;
f212ec4b7   Bernhard Kaindl   x86: early boot d...
265
266
267
268
269
270
271
272
  
  	if (!early_pci_allowed())
  		return;
  
  	/* Poor man's PCI discovery, the only thing we can do at early boot */
  	for (num = 0; num < 32; num++) {
  		for (slot = 0; slot < 32; slot++) {
  			for (func = 0; func < 8; func++) {
1ef5b816c   Stefan Richter   ieee1394: move in...
273
  				class = read_pci_config(num, slot, func,
f212ec4b7   Bernhard Kaindl   x86: early boot d...
274
  							PCI_CLASS_REVISION);
1ef5b816c   Stefan Richter   ieee1394: move in...
275
  				if (class == 0xffffffff)
f212ec4b7   Bernhard Kaindl   x86: early boot d...
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
  					continue; /* No device at this func */
  
  				if (class>>8 != PCI_CLASS_SERIAL_FIREWIRE_OHCI)
  					continue; /* Not an OHCI-1394 device */
  
  				init_ohci1394_controller(num, slot, func);
  				break; /* Assume one controller per device */
  			}
  		}
  	}
  	printk(KERN_INFO "init_ohci1394_dma: finished initializing OHCI DMA
  ");
  }
  
  /**
   * setup_init_ohci1394_early - enables early OHCI1394 DMA initialization
   */
  static int __init setup_ohci1394_dma(char *opt)
  {
  	if (!strcmp(opt, "early"))
  		init_ohci1394_dma_early = 1;
  	return 0;
  }
  
  /* passing ohci1394_dma=early on boot causes early OHCI1394 DMA initialization */
  early_param("ohci1394_dma", setup_ohci1394_dma);