diff options
285 files changed, 12314 insertions, 16080 deletions
diff --git a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl index b54cb5048dfa..87a7c07ab658 100644 --- a/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl +++ b/Documentation/sound/alsa/DocBook/writing-an-alsa-driver.tmpl | |||
@@ -5073,8 +5073,7 @@ struct _snd_pcm_runtime { | |||
5073 | with <constant>SNDRV_DMA_TYPE_CONTINUOUS</constant> type and the | 5073 | with <constant>SNDRV_DMA_TYPE_CONTINUOUS</constant> type and the |
5074 | <function>snd_dma_continuous_data(GFP_KERNEL)</function> device pointer, | 5074 | <function>snd_dma_continuous_data(GFP_KERNEL)</function> device pointer, |
5075 | where <constant>GFP_KERNEL</constant> is the kernel allocation flag to | 5075 | where <constant>GFP_KERNEL</constant> is the kernel allocation flag to |
5076 | use. For the SBUS, <constant>SNDRV_DMA_TYPE_SBUS</constant> and | 5076 | use. |
5077 | <function>snd_dma_sbus_data(sbus_dev)</function> are used instead. | ||
5078 | For the PCI scatter-gather buffers, use | 5077 | For the PCI scatter-gather buffers, use |
5079 | <constant>SNDRV_DMA_TYPE_DEV_SG</constant> with | 5078 | <constant>SNDRV_DMA_TYPE_DEV_SG</constant> with |
5080 | <function>snd_dma_pci_data(pci)</function> | 5079 | <function>snd_dma_pci_data(pci)</function> |
diff --git a/Documentation/sparc/sbus_drivers.txt b/Documentation/sparc/sbus_drivers.txt deleted file mode 100644 index eb1e28ad8822..000000000000 --- a/Documentation/sparc/sbus_drivers.txt +++ /dev/null | |||
@@ -1,309 +0,0 @@ | |||
1 | |||
2 | Writing SBUS Drivers | ||
3 | |||
4 | David S. Miller (davem@redhat.com) | ||
5 | |||
6 | The SBUS driver interfaces of the Linux kernel have been | ||
7 | revamped completely for 2.4.x for several reasons. Foremost were | ||
8 | performance and complexity concerns. This document details these | ||
9 | new interfaces and how they are used to write an SBUS device driver. | ||
10 | |||
11 | SBUS drivers need to include <asm/sbus.h> to get access | ||
12 | to functions and structures described here. | ||
13 | |||
14 | Probing and Detection | ||
15 | |||
16 | Each SBUS device inside the machine is described by a | ||
17 | structure called "struct sbus_dev". Likewise, each SBUS bus | ||
18 | found in the system is described by a "struct sbus_bus". For | ||
19 | each SBUS bus, the devices underneath are hung in a tree-like | ||
20 | fashion off of the bus structure. | ||
21 | |||
22 | The SBUS device structure contains enough information | ||
23 | for you to implement your device probing algorithm and obtain | ||
24 | the bits necessary to run your device. The most commonly | ||
25 | used members of this structure, and their typical usage, | ||
26 | will be detailed below. | ||
27 | |||
28 | Here is a piece of skeleton code for performing a device | ||
29 | probe in an SBUS driver under Linux: | ||
30 | |||
31 | static int __devinit mydevice_probe_one(struct sbus_dev *sdev) | ||
32 | { | ||
33 | struct mysdevice *mp = kzalloc(sizeof(*mp), GFP_KERNEL); | ||
34 | |||
35 | if (!mp) | ||
36 | return -ENODEV; | ||
37 | |||
38 | ... | ||
39 | dev_set_drvdata(&sdev->ofdev.dev, mp); | ||
40 | return 0; | ||
41 | ... | ||
42 | } | ||
43 | |||
44 | static int __devinit mydevice_probe(struct of_device *dev, | ||
45 | const struct of_device_id *match) | ||
46 | { | ||
47 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
48 | |||
49 | return mydevice_probe_one(sdev); | ||
50 | } | ||
51 | |||
52 | static int __devexit mydevice_remove(struct of_device *dev) | ||
53 | { | ||
54 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
55 | struct mydevice *mp = dev_get_drvdata(&dev->dev); | ||
56 | |||
57 | return mydevice_remove_one(sdev, mp); | ||
58 | } | ||
59 | |||
60 | static struct of_device_id mydevice_match[] = { | ||
61 | { | ||
62 | .name = "mydevice", | ||
63 | }, | ||
64 | {}, | ||
65 | }; | ||
66 | |||
67 | MODULE_DEVICE_TABLE(of, mydevice_match); | ||
68 | |||
69 | static struct of_platform_driver mydevice_driver = { | ||
70 | .match_table = mydevice_match, | ||
71 | .probe = mydevice_probe, | ||
72 | .remove = __devexit_p(mydevice_remove), | ||
73 | .driver = { | ||
74 | .name = "mydevice", | ||
75 | }, | ||
76 | }; | ||
77 | |||
78 | static int __init mydevice_init(void) | ||
79 | { | ||
80 | return of_register_driver(&mydevice_driver, &sbus_bus_type); | ||
81 | } | ||
82 | |||
83 | static void __exit mydevice_exit(void) | ||
84 | { | ||
85 | of_unregister_driver(&mydevice_driver); | ||
86 | } | ||
87 | |||
88 | module_init(mydevice_init); | ||
89 | module_exit(mydevice_exit); | ||
90 | |||
91 | The mydevice_match table is a series of entries which | ||
92 | describes what SBUS devices your driver is meant for. In the | ||
93 | simplest case you specify a string for the 'name' field. Every | ||
94 | SBUS device with a 'name' property matching your string will | ||
95 | be passed one-by-one to your .probe method. | ||
96 | |||
97 | You should store away your device private state structure | ||
98 | pointer in the drvdata area so that you can retrieve it later on | ||
99 | in your .remove method. | ||
100 | |||
101 | Any memory allocated, registers mapped, IRQs registered, | ||
102 | etc. must be undone by your .remove method so that all resources | ||
103 | of your device are released by the time it returns. | ||
104 | |||
105 | You should _NOT_ use the for_each_sbus(), for_each_sbusdev(), | ||
106 | and for_all_sbusdev() interfaces. They are deprecated, will be | ||
107 | removed, and no new driver should reference them ever. | ||
108 | |||
109 | Mapping and Accessing I/O Registers | ||
110 | |||
111 | Each SBUS device structure contains an array of descriptors | ||
112 | which describe each register set. We abuse struct resource for that. | ||
113 | They each correspond to the "reg" properties provided by the OBP firmware. | ||
114 | |||
115 | Before you can access your device's registers you must map | ||
116 | them. And later if you wish to shutdown your driver (for module | ||
117 | unload or similar) you must unmap them. You must treat them as | ||
118 | a resource, which you allocate (map) before using and free up | ||
119 | (unmap) when you are done with it. | ||
120 | |||
121 | The mapping information is stored in an opaque value | ||
122 | typed as an "unsigned long". This is the type of the return value | ||
123 | of the mapping interface, and the arguments to the unmapping | ||
124 | interface. Let's say you want to map the first set of registers. | ||
125 | Perhaps part of your driver software state structure looks like: | ||
126 | |||
127 | struct mydevice { | ||
128 | unsigned long control_regs; | ||
129 | ... | ||
130 | struct sbus_dev *sdev; | ||
131 | ... | ||
132 | }; | ||
133 | |||
134 | At initialization time you then use the sbus_ioremap | ||
135 | interface to map in your registers, like so: | ||
136 | |||
137 | static void init_one_mydevice(struct sbus_dev *sdev) | ||
138 | { | ||
139 | struct mydevice *mp; | ||
140 | ... | ||
141 | |||
142 | mp->control_regs = sbus_ioremap(&sdev->resource[0], 0, | ||
143 | CONTROL_REGS_SIZE, "mydevice regs"); | ||
144 | if (!mp->control_regs) { | ||
145 | /* Failure, cleanup and return. */ | ||
146 | } | ||
147 | } | ||
148 | |||
149 | Second argument to sbus_ioremap is an offset for | ||
150 | cranky devices with broken OBP PROM. The sbus_ioremap uses only | ||
151 | a start address and flags from the resource structure. | ||
152 | Therefore it is possible to use the same resource to map | ||
153 | several sets of registers or even to fabricate a resource | ||
154 | structure if driver gets physical address from some private place. | ||
155 | This practice is discouraged though. Use whatever OBP PROM | ||
156 | provided to you. | ||
157 | |||
158 | And here is how you might unmap these registers later at | ||
159 | driver shutdown or module unload time, using the sbus_iounmap | ||
160 | interface: | ||
161 | |||
162 | static void mydevice_unmap_regs(struct mydevice *mp) | ||
163 | { | ||
164 | sbus_iounmap(mp->control_regs, CONTROL_REGS_SIZE); | ||
165 | } | ||
166 | |||
167 | Finally, to actually access your registers there are 6 | ||
168 | interface routines at your disposal. Accesses are byte (8 bit), | ||
169 | word (16 bit), or longword (32 bit) sized. Here they are: | ||
170 | |||
171 | u8 sbus_readb(unsigned long reg) /* read byte */ | ||
172 | u16 sbus_readw(unsigned long reg) /* read word */ | ||
173 | u32 sbus_readl(unsigned long reg) /* read longword */ | ||
174 | void sbus_writeb(u8 value, unsigned long reg) /* write byte */ | ||
175 | void sbus_writew(u16 value, unsigned long reg) /* write word */ | ||
176 | void sbus_writel(u32 value, unsigned long reg) /* write longword */ | ||
177 | |||
178 | So, let's say your device has a control register of some sort | ||
179 | at offset zero. The following might implement resetting your device: | ||
180 | |||
181 | #define CONTROL 0x00UL | ||
182 | |||
183 | #define CONTROL_RESET 0x00000001 /* Reset hardware */ | ||
184 | |||
185 | static void mydevice_reset(struct mydevice *mp) | ||
186 | { | ||
187 | sbus_writel(CONTROL_RESET, mp->regs + CONTROL); | ||
188 | } | ||
189 | |||
190 | Or perhaps there is a data port register at an offset of | ||
191 | 16 bytes which allows you to read bytes from a fifo in the device: | ||
192 | |||
193 | #define DATA 0x10UL | ||
194 | |||
195 | static u8 mydevice_get_byte(struct mydevice *mp) | ||
196 | { | ||
197 | return sbus_readb(mp->regs + DATA); | ||
198 | } | ||
199 | |||
200 | It's pretty straightforward, and clueful readers may have | ||
201 | noticed that these interfaces mimick the PCI interfaces of the | ||
202 | Linux kernel. This was not by accident. | ||
203 | |||
204 | WARNING: | ||
205 | |||
206 | DO NOT try to treat these opaque register mapping | ||
207 | values as a memory mapped pointer to some structure | ||
208 | which you can dereference. | ||
209 | |||
210 | It may be memory mapped, it may not be. In fact it | ||
211 | could be a physical address, or it could be the time | ||
212 | of day xor'd with 0xdeadbeef. :-) | ||
213 | |||
214 | Whatever it is, it's an implementation detail. The | ||
215 | interface was done this way to shield the driver | ||
216 | author from such complexities. | ||
217 | |||
218 | Doing DVMA | ||
219 | |||
220 | SBUS devices can perform DMA transactions in a way similar | ||
221 | to PCI but dissimilar to ISA, e.g. DMA masters supply address. | ||
222 | In contrast to PCI, however, that address (a bus address) is | ||
223 | translated by IOMMU before a memory access is performed and therefore | ||
224 | it is virtual. Sun calls this procedure DVMA. | ||
225 | |||
226 | Linux supports two styles of using SBUS DVMA: "consistent memory" | ||
227 | and "streaming DVMA". CPU view of consistent memory chunk is, well, | ||
228 | consistent with a view of a device. Think of it as an uncached memory. | ||
229 | Typically this way of doing DVMA is not very fast and drivers use it | ||
230 | mostly for control blocks or queues. On some CPUs we cannot flush or | ||
231 | invalidate individual pages or cache lines and doing explicit flushing | ||
232 | over ever little byte in every control block would be wasteful. | ||
233 | |||
234 | Streaming DVMA is a preferred way to transfer large amounts of data. | ||
235 | This process works in the following way: | ||
236 | 1. a CPU stops accessing a certain part of memory, | ||
237 | flushes its caches covering that memory; | ||
238 | 2. a device does DVMA accesses, then posts an interrupt; | ||
239 | 3. CPU invalidates its caches and starts to access the memory. | ||
240 | |||
241 | A single streaming DVMA operation can touch several discontiguous | ||
242 | regions of a virtual bus address space. This is called a scatter-gather | ||
243 | DVMA. | ||
244 | |||
245 | [TBD: Why do not we neither Solaris attempt to map disjoint pages | ||
246 | into a single virtual chunk with the help of IOMMU, so that non SG | ||
247 | DVMA masters would do SG? It'd be very helpful for RAID.] | ||
248 | |||
249 | In order to perform a consistent DVMA a driver does something | ||
250 | like the following: | ||
251 | |||
252 | char *mem; /* Address in the CPU space */ | ||
253 | u32 busa; /* Address in the SBus space */ | ||
254 | |||
255 | mem = (char *) sbus_alloc_consistent(sdev, MYMEMSIZE, &busa); | ||
256 | |||
257 | Then mem is used when CPU accesses this memory and u32 | ||
258 | is fed to the device so that it can do DVMA. This is typically | ||
259 | done with an sbus_writel() into some device register. | ||
260 | |||
261 | Do not forget to free the DVMA resources once you are done: | ||
262 | |||
263 | sbus_free_consistent(sdev, MYMEMSIZE, mem, busa); | ||
264 | |||
265 | Streaming DVMA is more interesting. First you allocate some | ||
266 | memory suitable for it or pin down some user pages. Then it all works | ||
267 | like this: | ||
268 | |||
269 | char *mem = argumen1; | ||
270 | unsigned int size = argument2; | ||
271 | u32 busa; /* Address in the SBus space */ | ||
272 | |||
273 | *mem = 1; /* CPU can access */ | ||
274 | busa = sbus_map_single(sdev, mem, size); | ||
275 | if (busa == 0) ....... | ||
276 | |||
277 | /* Tell the device to use busa here */ | ||
278 | /* CPU cannot access the memory without sbus_dma_sync_single() */ | ||
279 | |||
280 | sbus_unmap_single(sdev, busa, size); | ||
281 | if (*mem == 0) .... /* CPU can access again */ | ||
282 | |||
283 | It is possible to retain mappings and ask the device to | ||
284 | access data again and again without calling sbus_unmap_single. | ||
285 | However, CPU caches must be invalidated with sbus_dma_sync_single | ||
286 | before such access. | ||
287 | |||
288 | [TBD but what about writeback caches here... do we have any?] | ||
289 | |||
290 | There is an equivalent set of functions doing the same thing | ||
291 | only with several memory segments at once for devices capable of | ||
292 | scatter-gather transfers. Use the Source, Luke. | ||
293 | |||
294 | Examples | ||
295 | |||
296 | drivers/net/sunhme.c | ||
297 | This is a complicated driver which illustrates many concepts | ||
298 | discussed above and plus it handles both PCI and SBUS boards. | ||
299 | |||
300 | drivers/scsi/esp.c | ||
301 | Check it out for scatter-gather DVMA. | ||
302 | |||
303 | drivers/sbus/char/bpp.c | ||
304 | A non-DVMA device. | ||
305 | |||
306 | drivers/net/sunlance.c | ||
307 | Lance driver abuses consistent mappings for data transfer. | ||
308 | It is a nifty trick which we do not particularly recommend... | ||
309 | Just check it out and know that it's legal. | ||
diff --git a/arch/arm/mach-orion5x/include/mach/orion5x.h b/arch/arm/mach-orion5x/include/mach/orion5x.h index e67c843baa02..9f5ce1ce5840 100644 --- a/arch/arm/mach-orion5x/include/mach/orion5x.h +++ b/arch/arm/mach-orion5x/include/mach/orion5x.h | |||
@@ -157,9 +157,11 @@ | |||
157 | #define CPU_CONF ORION5X_BRIDGE_REG(0x100) | 157 | #define CPU_CONF ORION5X_BRIDGE_REG(0x100) |
158 | #define CPU_CTRL ORION5X_BRIDGE_REG(0x104) | 158 | #define CPU_CTRL ORION5X_BRIDGE_REG(0x104) |
159 | #define CPU_RESET_MASK ORION5X_BRIDGE_REG(0x108) | 159 | #define CPU_RESET_MASK ORION5X_BRIDGE_REG(0x108) |
160 | #define WDT_RESET 0x0002 | ||
160 | #define CPU_SOFT_RESET ORION5X_BRIDGE_REG(0x10c) | 161 | #define CPU_SOFT_RESET ORION5X_BRIDGE_REG(0x10c) |
161 | #define POWER_MNG_CTRL_REG ORION5X_BRIDGE_REG(0x11C) | 162 | #define POWER_MNG_CTRL_REG ORION5X_BRIDGE_REG(0x11C) |
162 | #define BRIDGE_CAUSE ORION5X_BRIDGE_REG(0x110) | 163 | #define BRIDGE_CAUSE ORION5X_BRIDGE_REG(0x110) |
164 | #define WDT_INT_REQ 0x0008 | ||
163 | #define BRIDGE_MASK ORION5X_BRIDGE_REG(0x114) | 165 | #define BRIDGE_MASK ORION5X_BRIDGE_REG(0x114) |
164 | #define BRIDGE_INT_TIMER0 0x0002 | 166 | #define BRIDGE_INT_TIMER0 0x0002 |
165 | #define BRIDGE_INT_TIMER1 0x0004 | 167 | #define BRIDGE_INT_TIMER1 0x0004 |
diff --git a/arch/arm/plat-omap/devices.c b/arch/arm/plat-omap/devices.c index a716ecd1db27..97187fa0ae52 100644 --- a/arch/arm/plat-omap/devices.c +++ b/arch/arm/plat-omap/devices.c | |||
@@ -441,16 +441,8 @@ static inline void omap_init_uwire(void) {} | |||
441 | 441 | ||
442 | #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) | 442 | #if defined(CONFIG_OMAP_WATCHDOG) || defined(CONFIG_OMAP_WATCHDOG_MODULE) |
443 | 443 | ||
444 | #ifdef CONFIG_ARCH_OMAP24XX | ||
445 | #define OMAP_WDT_BASE 0x48022000 | ||
446 | #else | ||
447 | #define OMAP_WDT_BASE 0xfffeb000 | ||
448 | #endif | ||
449 | |||
450 | static struct resource wdt_resources[] = { | 444 | static struct resource wdt_resources[] = { |
451 | { | 445 | { |
452 | .start = OMAP_WDT_BASE, | ||
453 | .end = OMAP_WDT_BASE + 0x4f, | ||
454 | .flags = IORESOURCE_MEM, | 446 | .flags = IORESOURCE_MEM, |
455 | }, | 447 | }, |
456 | }; | 448 | }; |
@@ -464,6 +456,19 @@ static struct platform_device omap_wdt_device = { | |||
464 | 456 | ||
465 | static void omap_init_wdt(void) | 457 | static void omap_init_wdt(void) |
466 | { | 458 | { |
459 | if (cpu_is_omap16xx()) | ||
460 | wdt_resources[0].start = 0xfffeb000; | ||
461 | else if (cpu_is_omap2420()) | ||
462 | wdt_resources[0].start = 0x48022000; /* WDT2 */ | ||
463 | else if (cpu_is_omap2430()) | ||
464 | wdt_resources[0].start = 0x49016000; /* WDT2 */ | ||
465 | else if (cpu_is_omap343x()) | ||
466 | wdt_resources[0].start = 0x48314000; /* WDT2 */ | ||
467 | else | ||
468 | return; | ||
469 | |||
470 | wdt_resources[0].end = wdt_resources[0].start + 0x4f; | ||
471 | |||
467 | (void) platform_device_register(&omap_wdt_device); | 472 | (void) platform_device_register(&omap_wdt_device); |
468 | } | 473 | } |
469 | #else | 474 | #else |
diff --git a/arch/avr32/boards/atngw100/setup.c b/arch/avr32/boards/atngw100/setup.c index b8286f1ce854..6c54580a66df 100644 --- a/arch/avr32/boards/atngw100/setup.c +++ b/arch/avr32/boards/atngw100/setup.c | |||
@@ -9,6 +9,7 @@ | |||
9 | */ | 9 | */ |
10 | #include <linux/clk.h> | 10 | #include <linux/clk.h> |
11 | #include <linux/etherdevice.h> | 11 | #include <linux/etherdevice.h> |
12 | #include <linux/gpio.h> | ||
12 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
13 | #include <linux/i2c.h> | 14 | #include <linux/i2c.h> |
14 | #include <linux/i2c-gpio.h> | 15 | #include <linux/i2c-gpio.h> |
@@ -53,8 +54,11 @@ static struct spi_board_info spi0_board_info[] __initdata = { | |||
53 | }; | 54 | }; |
54 | 55 | ||
55 | static struct mci_platform_data __initdata mci0_data = { | 56 | static struct mci_platform_data __initdata mci0_data = { |
56 | .detect_pin = GPIO_PIN_PC(25), | 57 | .slot[0] = { |
57 | .wp_pin = GPIO_PIN_PE(0), | 58 | .bus_width = 4, |
59 | .detect_pin = GPIO_PIN_PC(25), | ||
60 | .wp_pin = GPIO_PIN_PE(0), | ||
61 | }, | ||
58 | }; | 62 | }; |
59 | 63 | ||
60 | /* | 64 | /* |
@@ -190,7 +194,7 @@ static int __init atngw100_init(void) | |||
190 | * PB28/EXTINT3 doesn't; it should be SMBALERT# (for PMBus), | 194 | * PB28/EXTINT3 doesn't; it should be SMBALERT# (for PMBus), |
191 | * but it's not available off-board. | 195 | * but it's not available off-board. |
192 | */ | 196 | */ |
193 | at32_select_periph(GPIO_PIN_PB(28), 0, AT32_GPIOF_PULLUP); | 197 | at32_select_periph(GPIO_PIOB_BASE, 1 << 28, 0, AT32_GPIOF_PULLUP); |
194 | at32_select_gpio(i2c_gpio_data.sda_pin, | 198 | at32_select_gpio(i2c_gpio_data.sda_pin, |
195 | AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); | 199 | AT32_GPIOF_MULTIDRV | AT32_GPIOF_OUTPUT | AT32_GPIOF_HIGH); |
196 | at32_select_gpio(i2c_gpio_data.scl_pin, | 200 | at32_select_gpio(i2c_gpio_data.scl_pin, |
@@ -204,6 +208,15 @@ postcore_initcall(atngw100_init); | |||
204 | 208 | ||
205 | static int __init atngw100_arch_init(void) | 209 | static int __init atngw100_arch_init(void) |
206 | { | 210 | { |
211 | /* PB30 is the otherwise unused jumper on the mainboard, with an | ||
212 | * external pullup; the jumper grounds it. Use it however you | ||
213 | * like, including letting U-Boot or Linux tweak boot sequences. | ||
214 | */ | ||
215 | at32_select_gpio(GPIO_PIN_PB(30), 0); | ||
216 | gpio_request(GPIO_PIN_PB(30), "j15"); | ||
217 | gpio_direction_input(GPIO_PIN_PB(30)); | ||
218 | gpio_export(GPIO_PIN_PB(30), false); | ||
219 | |||
207 | /* set_irq_type() after the arch_initcall for EIC has run, and | 220 | /* set_irq_type() after the arch_initcall for EIC has run, and |
208 | * before the I2C subsystem could try using this IRQ. | 221 | * before the I2C subsystem could try using this IRQ. |
209 | */ | 222 | */ |
diff --git a/arch/avr32/boards/atstk1000/atstk1002.c b/arch/avr32/boards/atstk1000/atstk1002.c index dfc3443e23aa..29e5b51a7fd2 100644 --- a/arch/avr32/boards/atstk1000/atstk1002.c +++ b/arch/avr32/boards/atstk1000/atstk1002.c | |||
@@ -232,7 +232,7 @@ static void __init atstk1002_setup_extdac(void) | |||
232 | goto err_set_clk; | 232 | goto err_set_clk; |
233 | } | 233 | } |
234 | 234 | ||
235 | at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); | 235 | at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); |
236 | at73c213_data.dac_clk = gclk; | 236 | at73c213_data.dac_clk = gclk; |
237 | 237 | ||
238 | err_set_clk: | 238 | err_set_clk: |
@@ -264,16 +264,20 @@ void __init setup_board(void) | |||
264 | 264 | ||
265 | #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM | 265 | #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM |
266 | 266 | ||
267 | static struct mci_platform_data __initdata mci0_data = { | ||
268 | .slot[0] = { | ||
269 | .bus_width = 4, | ||
270 | |||
267 | /* MMC card detect requires MACB0 *NOT* be used */ | 271 | /* MMC card detect requires MACB0 *NOT* be used */ |
268 | #ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM | 272 | #ifdef CONFIG_BOARD_ATSTK1002_SW6_CUSTOM |
269 | static struct mci_platform_data __initdata mci0_data = { | 273 | .detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */ |
270 | .detect_pin = GPIO_PIN_PC(14), /* gpio30/sdcd */ | 274 | .wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */ |
271 | .wp_pin = GPIO_PIN_PC(15), /* gpio31/sdwp */ | ||
272 | }; | ||
273 | #define MCI_PDATA &mci0_data | ||
274 | #else | 275 | #else |
275 | #define MCI_PDATA NULL | 276 | .detect_pin = -ENODEV, |
277 | .wp_pin = -ENODEV, | ||
276 | #endif /* SW6 for sd{cd,wp} routing */ | 278 | #endif /* SW6 for sd{cd,wp} routing */ |
279 | }, | ||
280 | }; | ||
277 | 281 | ||
278 | #endif /* SW2 for MMC signal routing */ | 282 | #endif /* SW2 for MMC signal routing */ |
279 | 283 | ||
@@ -326,13 +330,14 @@ static int __init atstk1002_init(void) | |||
326 | at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); | 330 | at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); |
327 | #endif | 331 | #endif |
328 | #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM | 332 | #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM |
329 | at32_add_device_mci(0, MCI_PDATA); | 333 | at32_add_device_mci(0, &mci0_data); |
330 | #endif | 334 | #endif |
331 | #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM | 335 | #ifdef CONFIG_BOARD_ATSTK1002_SW5_CUSTOM |
332 | set_hw_addr(at32_add_device_eth(1, ð_data[1])); | 336 | set_hw_addr(at32_add_device_eth(1, ð_data[1])); |
333 | #else | 337 | #else |
334 | at32_add_device_lcdc(0, &atstk1000_lcdc_data, | 338 | at32_add_device_lcdc(0, &atstk1000_lcdc_data, |
335 | fbmem_start, fbmem_size, 0); | 339 | fbmem_start, fbmem_size, |
340 | ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL); | ||
336 | #endif | 341 | #endif |
337 | at32_add_device_usba(0, NULL); | 342 | at32_add_device_usba(0, NULL); |
338 | #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM | 343 | #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM |
diff --git a/arch/avr32/boards/atstk1000/atstk1003.c b/arch/avr32/boards/atstk1000/atstk1003.c index 0cf664174c17..be089d7f37eb 100644 --- a/arch/avr32/boards/atstk1000/atstk1003.c +++ b/arch/avr32/boards/atstk1000/atstk1003.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/spi/spi.h> | 19 | #include <linux/spi/spi.h> |
20 | 20 | ||
21 | #include <asm/setup.h> | 21 | #include <asm/setup.h> |
22 | #include <asm/atmel-mci.h> | ||
22 | 23 | ||
23 | #include <mach/at32ap700x.h> | 24 | #include <mach/at32ap700x.h> |
24 | #include <mach/board.h> | 25 | #include <mach/board.h> |
@@ -66,6 +67,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { { | |||
66 | } }; | 67 | } }; |
67 | #endif | 68 | #endif |
68 | 69 | ||
70 | #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM | ||
71 | static struct mci_platform_data __initdata mci0_data = { | ||
72 | .slot[0] = { | ||
73 | .bus_width = 4, | ||
74 | .detect_pin = -ENODEV, | ||
75 | .wp_pin = -ENODEV, | ||
76 | }, | ||
77 | }; | ||
78 | #endif | ||
79 | |||
69 | #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC | 80 | #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC |
70 | static void __init atstk1003_setup_extdac(void) | 81 | static void __init atstk1003_setup_extdac(void) |
71 | { | 82 | { |
@@ -84,7 +95,7 @@ static void __init atstk1003_setup_extdac(void) | |||
84 | goto err_set_clk; | 95 | goto err_set_clk; |
85 | } | 96 | } |
86 | 97 | ||
87 | at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); | 98 | at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); |
88 | at73c213_data.dac_clk = gclk; | 99 | at73c213_data.dac_clk = gclk; |
89 | 100 | ||
90 | err_set_clk: | 101 | err_set_clk: |
@@ -154,7 +165,7 @@ static int __init atstk1003_init(void) | |||
154 | at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); | 165 | at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); |
155 | #endif | 166 | #endif |
156 | #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM | 167 | #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM |
157 | at32_add_device_mci(0, NULL); | 168 | at32_add_device_mci(0, &mci0_data); |
158 | #endif | 169 | #endif |
159 | at32_add_device_usba(0, NULL); | 170 | at32_add_device_usba(0, NULL); |
160 | #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM | 171 | #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM |
diff --git a/arch/avr32/boards/atstk1000/atstk1004.c b/arch/avr32/boards/atstk1000/atstk1004.c index 50a5273e5916..248ef237c167 100644 --- a/arch/avr32/boards/atstk1000/atstk1004.c +++ b/arch/avr32/boards/atstk1000/atstk1004.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <video/atmel_lcdc.h> | 21 | #include <video/atmel_lcdc.h> |
22 | 22 | ||
23 | #include <asm/setup.h> | 23 | #include <asm/setup.h> |
24 | #include <asm/atmel-mci.h> | ||
24 | 25 | ||
25 | #include <mach/at32ap700x.h> | 26 | #include <mach/at32ap700x.h> |
26 | #include <mach/board.h> | 27 | #include <mach/board.h> |
@@ -71,6 +72,16 @@ static struct spi_board_info spi1_board_info[] __initdata = { { | |||
71 | } }; | 72 | } }; |
72 | #endif | 73 | #endif |
73 | 74 | ||
75 | #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM | ||
76 | static struct mci_platform_data __initdata mci0_data = { | ||
77 | .slot[0] = { | ||
78 | .bus_width = 4, | ||
79 | .detect_pin = -ENODEV, | ||
80 | .wp_pin = -ENODEV, | ||
81 | }, | ||
82 | }; | ||
83 | #endif | ||
84 | |||
74 | #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC | 85 | #ifdef CONFIG_BOARD_ATSTK1000_EXTDAC |
75 | static void __init atstk1004_setup_extdac(void) | 86 | static void __init atstk1004_setup_extdac(void) |
76 | { | 87 | { |
@@ -89,7 +100,7 @@ static void __init atstk1004_setup_extdac(void) | |||
89 | goto err_set_clk; | 100 | goto err_set_clk; |
90 | } | 101 | } |
91 | 102 | ||
92 | at32_select_periph(GPIO_PIN_PA(30), GPIO_PERIPH_A, 0); | 103 | at32_select_periph(GPIO_PIOA_BASE, (1 << 30), GPIO_PERIPH_A, 0); |
93 | at73c213_data.dac_clk = gclk; | 104 | at73c213_data.dac_clk = gclk; |
94 | 105 | ||
95 | err_set_clk: | 106 | err_set_clk: |
@@ -137,10 +148,11 @@ static int __init atstk1004_init(void) | |||
137 | at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); | 148 | at32_add_device_spi(1, spi1_board_info, ARRAY_SIZE(spi1_board_info)); |
138 | #endif | 149 | #endif |
139 | #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM | 150 | #ifndef CONFIG_BOARD_ATSTK100X_SW2_CUSTOM |
140 | at32_add_device_mci(0, NULL); | 151 | at32_add_device_mci(0, &mci0_data); |
141 | #endif | 152 | #endif |
142 | at32_add_device_lcdc(0, &atstk1000_lcdc_data, | 153 | at32_add_device_lcdc(0, &atstk1000_lcdc_data, |
143 | fbmem_start, fbmem_size, 0); | 154 | fbmem_start, fbmem_size, |
155 | ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL); | ||
144 | at32_add_device_usba(0, NULL); | 156 | at32_add_device_usba(0, NULL); |
145 | #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM | 157 | #ifndef CONFIG_BOARD_ATSTK100X_SW3_CUSTOM |
146 | at32_add_device_ssc(0, ATMEL_SSC_TX); | 158 | at32_add_device_ssc(0, ATMEL_SSC_TX); |
diff --git a/arch/avr32/include/asm/atmel-mci.h b/arch/avr32/include/asm/atmel-mci.h index c2ea6e1c9aa1..59f3fadd0b68 100644 --- a/arch/avr32/include/asm/atmel-mci.h +++ b/arch/avr32/include/asm/atmel-mci.h | |||
@@ -1,9 +1,39 @@ | |||
1 | #ifndef __ASM_AVR32_ATMEL_MCI_H | 1 | #ifndef __ASM_AVR32_ATMEL_MCI_H |
2 | #define __ASM_AVR32_ATMEL_MCI_H | 2 | #define __ASM_AVR32_ATMEL_MCI_H |
3 | 3 | ||
4 | struct mci_platform_data { | 4 | #define ATMEL_MCI_MAX_NR_SLOTS 2 |
5 | |||
6 | struct dma_slave; | ||
7 | |||
8 | /** | ||
9 | * struct mci_slot_pdata - board-specific per-slot configuration | ||
10 | * @bus_width: Number of data lines wired up the slot | ||
11 | * @detect_pin: GPIO pin wired to the card detect switch | ||
12 | * @wp_pin: GPIO pin wired to the write protect sensor | ||
13 | * | ||
14 | * If a given slot is not present on the board, @bus_width should be | ||
15 | * set to 0. The other fields are ignored in this case. | ||
16 | * | ||
17 | * Any pins that aren't available should be set to a negative value. | ||
18 | * | ||
19 | * Note that support for multiple slots is experimental -- some cards | ||
20 | * might get upset if we don't get the clock management exactly right. | ||
21 | * But in most cases, it should work just fine. | ||
22 | */ | ||
23 | struct mci_slot_pdata { | ||
24 | unsigned int bus_width; | ||
5 | int detect_pin; | 25 | int detect_pin; |
6 | int wp_pin; | 26 | int wp_pin; |
7 | }; | 27 | }; |
8 | 28 | ||
29 | /** | ||
30 | * struct mci_platform_data - board-specific MMC/SDcard configuration | ||
31 | * @dma_slave: DMA slave interface to use in data transfers, or NULL. | ||
32 | * @slot: Per-slot configuration data. | ||
33 | */ | ||
34 | struct mci_platform_data { | ||
35 | struct dma_slave *dma_slave; | ||
36 | struct mci_slot_pdata slot[ATMEL_MCI_MAX_NR_SLOTS]; | ||
37 | }; | ||
38 | |||
9 | #endif /* __ASM_AVR32_ATMEL_MCI_H */ | 39 | #endif /* __ASM_AVR32_ATMEL_MCI_H */ |
diff --git a/arch/avr32/include/asm/byteorder.h b/arch/avr32/include/asm/byteorder.h index d77b48ba7338..8e3af02076dd 100644 --- a/arch/avr32/include/asm/byteorder.h +++ b/arch/avr32/include/asm/byteorder.h | |||
@@ -7,6 +7,9 @@ | |||
7 | #include <asm/types.h> | 7 | #include <asm/types.h> |
8 | #include <linux/compiler.h> | 8 | #include <linux/compiler.h> |
9 | 9 | ||
10 | #define __BIG_ENDIAN | ||
11 | #define __SWAB_64_THRU_32__ | ||
12 | |||
10 | #ifdef __CHECKER__ | 13 | #ifdef __CHECKER__ |
11 | extern unsigned long __builtin_bswap_32(unsigned long x); | 14 | extern unsigned long __builtin_bswap_32(unsigned long x); |
12 | extern unsigned short __builtin_bswap_16(unsigned short x); | 15 | extern unsigned short __builtin_bswap_16(unsigned short x); |
@@ -17,15 +20,18 @@ extern unsigned short __builtin_bswap_16(unsigned short x); | |||
17 | * the result. | 20 | * the result. |
18 | */ | 21 | */ |
19 | #if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2) | 22 | #if !(__GNUC__ == 4 && __GNUC_MINOR__ < 2) |
20 | #define __arch__swab32(x) __builtin_bswap_32(x) | 23 | static inline __attribute_const__ __u16 __arch_swab16(__u16 val) |
21 | #define __arch__swab16(x) __builtin_bswap_16(x) | 24 | { |
22 | #endif | 25 | return __builtin_bswap_16(val); |
26 | } | ||
27 | #define __arch_swab16 __arch_swab16 | ||
23 | 28 | ||
24 | #if !defined(__STRICT_ANSI__) || defined(__KERNEL__) | 29 | static inline __attribute_const__ __u32 __arch_swab32(__u32 val) |
25 | # define __BYTEORDER_HAS_U64__ | 30 | { |
26 | # define __SWAB_64_THRU_32__ | 31 | return __builtin_bswap_32(val); |
32 | } | ||
33 | #define __arch_swab32 __arch_swab32 | ||
27 | #endif | 34 | #endif |
28 | 35 | ||
29 | #include <linux/byteorder/big_endian.h> | 36 | #include <linux/byteorder.h> |
30 | |||
31 | #endif /* __ASM_AVR32_BYTEORDER_H */ | 37 | #endif /* __ASM_AVR32_BYTEORDER_H */ |
diff --git a/arch/avr32/include/asm/io.h b/arch/avr32/include/asm/io.h index a520f77ead96..22c97ef92201 100644 --- a/arch/avr32/include/asm/io.h +++ b/arch/avr32/include/asm/io.h | |||
@@ -160,6 +160,14 @@ BUILDIO_IOPORT(l, u32) | |||
160 | #define readw_relaxed readw | 160 | #define readw_relaxed readw |
161 | #define readl_relaxed readl | 161 | #define readl_relaxed readl |
162 | 162 | ||
163 | #define readb_be __raw_readb | ||
164 | #define readw_be __raw_readw | ||
165 | #define readl_be __raw_readl | ||
166 | |||
167 | #define writeb_be __raw_writeb | ||
168 | #define writew_be __raw_writew | ||
169 | #define writel_be __raw_writel | ||
170 | |||
163 | #define __BUILD_MEMORY_STRING(bwl, type) \ | 171 | #define __BUILD_MEMORY_STRING(bwl, type) \ |
164 | static inline void writes##bwl(volatile void __iomem *addr, \ | 172 | static inline void writes##bwl(volatile void __iomem *addr, \ |
165 | const void *data, unsigned int count) \ | 173 | const void *data, unsigned int count) \ |
diff --git a/arch/avr32/kernel/process.c b/arch/avr32/kernel/process.c index 2c08ac992ac3..134d5302b6dd 100644 --- a/arch/avr32/kernel/process.c +++ b/arch/avr32/kernel/process.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/kallsyms.h> | 10 | #include <linux/kallsyms.h> |
11 | #include <linux/fs.h> | 11 | #include <linux/fs.h> |
12 | #include <linux/pm.h> | ||
12 | #include <linux/ptrace.h> | 13 | #include <linux/ptrace.h> |
13 | #include <linux/reboot.h> | 14 | #include <linux/reboot.h> |
14 | #include <linux/tick.h> | 15 | #include <linux/tick.h> |
@@ -20,7 +21,7 @@ | |||
20 | 21 | ||
21 | #include <mach/pm.h> | 22 | #include <mach/pm.h> |
22 | 23 | ||
23 | void (*pm_power_off)(void) = NULL; | 24 | void (*pm_power_off)(void); |
24 | EXPORT_SYMBOL(pm_power_off); | 25 | EXPORT_SYMBOL(pm_power_off); |
25 | 26 | ||
26 | /* | 27 | /* |
diff --git a/arch/avr32/kernel/setup.c b/arch/avr32/kernel/setup.c index d8e623c426c1..5c7083916c33 100644 --- a/arch/avr32/kernel/setup.c +++ b/arch/avr32/kernel/setup.c | |||
@@ -283,6 +283,25 @@ static int __init early_parse_fbmem(char *p) | |||
283 | } | 283 | } |
284 | early_param("fbmem", early_parse_fbmem); | 284 | early_param("fbmem", early_parse_fbmem); |
285 | 285 | ||
286 | /* | ||
287 | * Pick out the memory size. We look for mem=size@start, | ||
288 | * where start and size are "size[KkMmGg]" | ||
289 | */ | ||
290 | static int __init early_mem(char *p) | ||
291 | { | ||
292 | resource_size_t size, start; | ||
293 | |||
294 | start = system_ram->start; | ||
295 | size = memparse(p, &p); | ||
296 | if (*p == '@') | ||
297 | start = memparse(p + 1, &p); | ||
298 | |||
299 | system_ram->start = start; | ||
300 | system_ram->end = system_ram->start + size - 1; | ||
301 | return 0; | ||
302 | } | ||
303 | early_param("mem", early_mem); | ||
304 | |||
286 | static int __init parse_tag_core(struct tag *tag) | 305 | static int __init parse_tag_core(struct tag *tag) |
287 | { | 306 | { |
288 | if (tag->hdr.size > 2) { | 307 | if (tag->hdr.size > 2) { |
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index e01dbe4ebb40..813b6844cdf6 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c | |||
@@ -82,8 +82,9 @@ static struct platform_device _name##_id##_device = { \ | |||
82 | .num_resources = ARRAY_SIZE(_name##_id##_resource), \ | 82 | .num_resources = ARRAY_SIZE(_name##_id##_resource), \ |
83 | } | 83 | } |
84 | 84 | ||
85 | #define select_peripheral(pin, periph, flags) \ | 85 | #define select_peripheral(port, pin_mask, periph, flags) \ |
86 | at32_select_periph(GPIO_PIN_##pin, GPIO_##periph, flags) | 86 | at32_select_periph(GPIO_##port##_BASE, pin_mask, \ |
87 | GPIO_##periph, flags) | ||
87 | 88 | ||
88 | #define DEV_CLK(_name, devname, bus, _index) \ | 89 | #define DEV_CLK(_name, devname, bus, _index) \ |
89 | static struct clk devname##_##_name = { \ | 90 | static struct clk devname##_##_name = { \ |
@@ -871,6 +872,7 @@ static struct clk atmel_psif1_pclk = { | |||
871 | struct platform_device *__init at32_add_device_psif(unsigned int id) | 872 | struct platform_device *__init at32_add_device_psif(unsigned int id) |
872 | { | 873 | { |
873 | struct platform_device *pdev; | 874 | struct platform_device *pdev; |
875 | u32 pin_mask; | ||
874 | 876 | ||
875 | if (!(id == 0 || id == 1)) | 877 | if (!(id == 0 || id == 1)) |
876 | return NULL; | 878 | return NULL; |
@@ -881,20 +883,22 @@ struct platform_device *__init at32_add_device_psif(unsigned int id) | |||
881 | 883 | ||
882 | switch (id) { | 884 | switch (id) { |
883 | case 0: | 885 | case 0: |
886 | pin_mask = (1 << 8) | (1 << 9); /* CLOCK & DATA */ | ||
887 | |||
884 | if (platform_device_add_resources(pdev, atmel_psif0_resource, | 888 | if (platform_device_add_resources(pdev, atmel_psif0_resource, |
885 | ARRAY_SIZE(atmel_psif0_resource))) | 889 | ARRAY_SIZE(atmel_psif0_resource))) |
886 | goto err_add_resources; | 890 | goto err_add_resources; |
887 | atmel_psif0_pclk.dev = &pdev->dev; | 891 | atmel_psif0_pclk.dev = &pdev->dev; |
888 | select_peripheral(PA(8), PERIPH_A, 0); /* CLOCK */ | 892 | select_peripheral(PIOA, pin_mask, PERIPH_A, 0); |
889 | select_peripheral(PA(9), PERIPH_A, 0); /* DATA */ | ||
890 | break; | 893 | break; |
891 | case 1: | 894 | case 1: |
895 | pin_mask = (1 << 11) | (1 << 12); /* CLOCK & DATA */ | ||
896 | |||
892 | if (platform_device_add_resources(pdev, atmel_psif1_resource, | 897 | if (platform_device_add_resources(pdev, atmel_psif1_resource, |
893 | ARRAY_SIZE(atmel_psif1_resource))) | 898 | ARRAY_SIZE(atmel_psif1_resource))) |
894 | goto err_add_resources; | 899 | goto err_add_resources; |
895 | atmel_psif1_pclk.dev = &pdev->dev; | 900 | atmel_psif1_pclk.dev = &pdev->dev; |
896 | select_peripheral(PB(11), PERIPH_A, 0); /* CLOCK */ | 901 | select_peripheral(PIOB, pin_mask, PERIPH_A, 0); |
897 | select_peripheral(PB(12), PERIPH_A, 0); /* DATA */ | ||
898 | break; | 902 | break; |
899 | default: | 903 | default: |
900 | return NULL; | 904 | return NULL; |
@@ -958,26 +962,30 @@ DEV_CLK(usart, atmel_usart3, pba, 6); | |||
958 | 962 | ||
959 | static inline void configure_usart0_pins(void) | 963 | static inline void configure_usart0_pins(void) |
960 | { | 964 | { |
961 | select_peripheral(PA(8), PERIPH_B, 0); /* RXD */ | 965 | u32 pin_mask = (1 << 8) | (1 << 9); /* RXD & TXD */ |
962 | select_peripheral(PA(9), PERIPH_B, 0); /* TXD */ | 966 | |
967 | select_peripheral(PIOA, pin_mask, PERIPH_B, 0); | ||
963 | } | 968 | } |
964 | 969 | ||
965 | static inline void configure_usart1_pins(void) | 970 | static inline void configure_usart1_pins(void) |
966 | { | 971 | { |
967 | select_peripheral(PA(17), PERIPH_A, 0); /* RXD */ | 972 | u32 pin_mask = (1 << 17) | (1 << 18); /* RXD & TXD */ |
968 | select_peripheral(PA(18), PERIPH_A, 0); /* TXD */ | 973 | |
974 | select_peripheral(PIOA, pin_mask, PERIPH_A, 0); | ||
969 | } | 975 | } |
970 | 976 | ||
971 | static inline void configure_usart2_pins(void) | 977 | static inline void configure_usart2_pins(void) |
972 | { | 978 | { |
973 | select_peripheral(PB(26), PERIPH_B, 0); /* RXD */ | 979 | u32 pin_mask = (1 << 26) | (1 << 27); /* RXD & TXD */ |
974 | select_peripheral(PB(27), PERIPH_B, 0); /* TXD */ | 980 | |
981 | select_peripheral(PIOB, pin_mask, PERIPH_B, 0); | ||
975 | } | 982 | } |
976 | 983 | ||
977 | static inline void configure_usart3_pins(void) | 984 | static inline void configure_usart3_pins(void) |
978 | { | 985 | { |
979 | select_peripheral(PB(18), PERIPH_B, 0); /* RXD */ | 986 | u32 pin_mask = (1 << 18) | (1 << 17); /* RXD & TXD */ |
980 | select_peripheral(PB(17), PERIPH_B, 0); /* TXD */ | 987 | |
988 | select_peripheral(PIOB, pin_mask, PERIPH_B, 0); | ||
981 | } | 989 | } |
982 | 990 | ||
983 | static struct platform_device *__initdata at32_usarts[4]; | 991 | static struct platform_device *__initdata at32_usarts[4]; |
@@ -1057,59 +1065,69 @@ struct platform_device *__init | |||
1057 | at32_add_device_eth(unsigned int id, struct eth_platform_data *data) | 1065 | at32_add_device_eth(unsigned int id, struct eth_platform_data *data) |
1058 | { | 1066 | { |
1059 | struct platform_device *pdev; | 1067 | struct platform_device *pdev; |
1068 | u32 pin_mask; | ||
1060 | 1069 | ||
1061 | switch (id) { | 1070 | switch (id) { |
1062 | case 0: | 1071 | case 0: |
1063 | pdev = &macb0_device; | 1072 | pdev = &macb0_device; |
1064 | 1073 | ||
1065 | select_peripheral(PC(3), PERIPH_A, 0); /* TXD0 */ | 1074 | pin_mask = (1 << 3); /* TXD0 */ |
1066 | select_peripheral(PC(4), PERIPH_A, 0); /* TXD1 */ | 1075 | pin_mask |= (1 << 4); /* TXD1 */ |
1067 | select_peripheral(PC(7), PERIPH_A, 0); /* TXEN */ | 1076 | pin_mask |= (1 << 7); /* TXEN */ |
1068 | select_peripheral(PC(8), PERIPH_A, 0); /* TXCK */ | 1077 | pin_mask |= (1 << 8); /* TXCK */ |
1069 | select_peripheral(PC(9), PERIPH_A, 0); /* RXD0 */ | 1078 | pin_mask |= (1 << 9); /* RXD0 */ |
1070 | select_peripheral(PC(10), PERIPH_A, 0); /* RXD1 */ | 1079 | pin_mask |= (1 << 10); /* RXD1 */ |
1071 | select_peripheral(PC(13), PERIPH_A, 0); /* RXER */ | 1080 | pin_mask |= (1 << 13); /* RXER */ |
1072 | select_peripheral(PC(15), PERIPH_A, 0); /* RXDV */ | 1081 | pin_mask |= (1 << 15); /* RXDV */ |
1073 | select_peripheral(PC(16), PERIPH_A, 0); /* MDC */ | 1082 | pin_mask |= (1 << 16); /* MDC */ |
1074 | select_peripheral(PC(17), PERIPH_A, 0); /* MDIO */ | 1083 | pin_mask |= (1 << 17); /* MDIO */ |
1075 | 1084 | ||
1076 | if (!data->is_rmii) { | 1085 | if (!data->is_rmii) { |
1077 | select_peripheral(PC(0), PERIPH_A, 0); /* COL */ | 1086 | pin_mask |= (1 << 0); /* COL */ |
1078 | select_peripheral(PC(1), PERIPH_A, 0); /* CRS */ | 1087 | pin_mask |= (1 << 1); /* CRS */ |
1079 | select_peripheral(PC(2), PERIPH_A, 0); /* TXER */ | 1088 | pin_mask |= (1 << 2); /* TXER */ |
1080 | select_peripheral(PC(5), PERIPH_A, 0); /* TXD2 */ | 1089 | pin_mask |= (1 << 5); /* TXD2 */ |
1081 | select_peripheral(PC(6), PERIPH_A, 0); /* TXD3 */ | 1090 | pin_mask |= (1 << 6); /* TXD3 */ |
1082 | select_peripheral(PC(11), PERIPH_A, 0); /* RXD2 */ | 1091 | pin_mask |= (1 << 11); /* RXD2 */ |
1083 | select_peripheral(PC(12), PERIPH_A, 0); /* RXD3 */ | 1092 | pin_mask |= (1 << 12); /* RXD3 */ |
1084 | select_peripheral(PC(14), PERIPH_A, 0); /* RXCK */ | 1093 | pin_mask |= (1 << 14); /* RXCK */ |
1085 | select_peripheral(PC(18), PERIPH_A, 0); /* SPD */ | 1094 | pin_mask |= (1 << 18); /* SPD */ |
1086 | } | 1095 | } |
1096 | |||
1097 | select_peripheral(PIOC, pin_mask, PERIPH_A, 0); | ||
1098 | |||
1087 | break; | 1099 | break; |
1088 | 1100 | ||
1089 | case 1: | 1101 | case 1: |
1090 | pdev = &macb1_device; | 1102 | pdev = &macb1_device; |
1091 | 1103 | ||
1092 | select_peripheral(PD(13), PERIPH_B, 0); /* TXD0 */ | 1104 | pin_mask = (1 << 13); /* TXD0 */ |
1093 | select_peripheral(PD(14), PERIPH_B, 0); /* TXD1 */ | 1105 | pin_mask |= (1 << 14); /* TXD1 */ |
1094 | select_peripheral(PD(11), PERIPH_B, 0); /* TXEN */ | 1106 | pin_mask |= (1 << 11); /* TXEN */ |
1095 | select_peripheral(PD(12), PERIPH_B, 0); /* TXCK */ | 1107 | pin_mask |= (1 << 12); /* TXCK */ |
1096 | select_peripheral(PD(10), PERIPH_B, 0); /* RXD0 */ | 1108 | pin_mask |= (1 << 10); /* RXD0 */ |
1097 | select_peripheral(PD(6), PERIPH_B, 0); /* RXD1 */ | 1109 | pin_mask |= (1 << 6); /* RXD1 */ |
1098 | select_peripheral(PD(5), PERIPH_B, 0); /* RXER */ | 1110 | pin_mask |= (1 << 5); /* RXER */ |
1099 | select_peripheral(PD(4), PERIPH_B, 0); /* RXDV */ | 1111 | pin_mask |= (1 << 4); /* RXDV */ |
1100 | select_peripheral(PD(3), PERIPH_B, 0); /* MDC */ | 1112 | pin_mask |= (1 << 3); /* MDC */ |
1101 | select_peripheral(PD(2), PERIPH_B, 0); /* MDIO */ | 1113 | pin_mask |= (1 << 2); /* MDIO */ |
1114 | |||
1115 | if (!data->is_rmii) | ||
1116 | pin_mask |= (1 << 15); /* SPD */ | ||
1117 | |||
1118 | select_peripheral(PIOD, pin_mask, PERIPH_B, 0); | ||
1102 | 1119 | ||
1103 | if (!data->is_rmii) { | 1120 | if (!data->is_rmii) { |
1104 | select_peripheral(PC(19), PERIPH_B, 0); /* COL */ | 1121 | pin_mask = (1 << 19); /* COL */ |
1105 | select_peripheral(PC(23), PERIPH_B, 0); /* CRS */ | 1122 | pin_mask |= (1 << 23); /* CRS */ |
1106 | select_peripheral(PC(26), PERIPH_B, 0); /* TXER */ | 1123 | pin_mask |= (1 << 26); /* TXER */ |
1107 | select_peripheral(PC(27), PERIPH_B, 0); /* TXD2 */ | 1124 | pin_mask |= (1 << 27); /* TXD2 */ |
1108 | select_peripheral(PC(28), PERIPH_B, 0); /* TXD3 */ | 1125 | pin_mask |= (1 << 28); /* TXD3 */ |
1109 | select_peripheral(PC(29), PERIPH_B, 0); /* RXD2 */ | 1126 | pin_mask |= (1 << 29); /* RXD2 */ |
1110 | select_peripheral(PC(30), PERIPH_B, 0); /* RXD3 */ | 1127 | pin_mask |= (1 << 30); /* RXD3 */ |
1111 | select_peripheral(PC(24), PERIPH_B, 0); /* RXCK */ | 1128 | pin_mask |= (1 << 24); /* RXCK */ |
1112 | select_peripheral(PD(15), PERIPH_B, 0); /* SPD */ | 1129 | |
1130 | select_peripheral(PIOC, pin_mask, PERIPH_B, 0); | ||
1113 | } | 1131 | } |
1114 | break; | 1132 | break; |
1115 | 1133 | ||
@@ -1177,23 +1195,28 @@ at32_add_device_spi(unsigned int id, struct spi_board_info *b, unsigned int n) | |||
1177 | { GPIO_PIN_PB(2), GPIO_PIN_PB(3), | 1195 | { GPIO_PIN_PB(2), GPIO_PIN_PB(3), |
1178 | GPIO_PIN_PB(4), GPIO_PIN_PA(27), }; | 1196 | GPIO_PIN_PB(4), GPIO_PIN_PA(27), }; |
1179 | struct platform_device *pdev; | 1197 | struct platform_device *pdev; |
1198 | u32 pin_mask; | ||
1180 | 1199 | ||
1181 | switch (id) { | 1200 | switch (id) { |
1182 | case 0: | 1201 | case 0: |
1183 | pdev = &atmel_spi0_device; | 1202 | pdev = &atmel_spi0_device; |
1203 | pin_mask = (1 << 1) | (1 << 2); /* MOSI & SCK */ | ||
1204 | |||
1184 | /* pullup MISO so a level is always defined */ | 1205 | /* pullup MISO so a level is always defined */ |
1185 | select_peripheral(PA(0), PERIPH_A, AT32_GPIOF_PULLUP); | 1206 | select_peripheral(PIOA, (1 << 0), PERIPH_A, AT32_GPIOF_PULLUP); |
1186 | select_peripheral(PA(1), PERIPH_A, 0); /* MOSI */ | 1207 | select_peripheral(PIOA, pin_mask, PERIPH_A, 0); |
1187 | select_peripheral(PA(2), PERIPH_A, 0); /* SCK */ | 1208 | |
1188 | at32_spi_setup_slaves(0, b, n, spi0_pins); | 1209 | at32_spi_setup_slaves(0, b, n, spi0_pins); |
1189 | break; | 1210 | break; |
1190 | 1211 | ||
1191 | case 1: | 1212 | case 1: |
1192 | pdev = &atmel_spi1_device; | 1213 | pdev = &atmel_spi1_device; |
1214 | pin_mask = (1 << 1) | (1 << 5); /* MOSI */ | ||
1215 | |||
1193 | /* pullup MISO so a level is always defined */ | 1216 | /* pullup MISO so a level is always defined */ |
1194 | select_peripheral(PB(0), PERIPH_B, AT32_GPIOF_PULLUP); | 1217 | select_peripheral(PIOB, (1 << 0), PERIPH_B, AT32_GPIOF_PULLUP); |
1195 | select_peripheral(PB(1), PERIPH_B, 0); /* MOSI */ | 1218 | select_peripheral(PIOB, pin_mask, PERIPH_B, 0); |
1196 | select_peripheral(PB(5), PERIPH_B, 0); /* SCK */ | 1219 | |
1197 | at32_spi_setup_slaves(1, b, n, spi1_pins); | 1220 | at32_spi_setup_slaves(1, b, n, spi1_pins); |
1198 | break; | 1221 | break; |
1199 | 1222 | ||
@@ -1226,6 +1249,7 @@ struct platform_device *__init at32_add_device_twi(unsigned int id, | |||
1226 | unsigned int n) | 1249 | unsigned int n) |
1227 | { | 1250 | { |
1228 | struct platform_device *pdev; | 1251 | struct platform_device *pdev; |
1252 | u32 pin_mask; | ||
1229 | 1253 | ||
1230 | if (id != 0) | 1254 | if (id != 0) |
1231 | return NULL; | 1255 | return NULL; |
@@ -1238,8 +1262,9 @@ struct platform_device *__init at32_add_device_twi(unsigned int id, | |||
1238 | ARRAY_SIZE(atmel_twi0_resource))) | 1262 | ARRAY_SIZE(atmel_twi0_resource))) |
1239 | goto err_add_resources; | 1263 | goto err_add_resources; |
1240 | 1264 | ||
1241 | select_peripheral(PA(6), PERIPH_A, 0); /* SDA */ | 1265 | pin_mask = (1 << 6) | (1 << 7); /* SDA & SDL */ |
1242 | select_peripheral(PA(7), PERIPH_A, 0); /* SDL */ | 1266 | |
1267 | select_peripheral(PIOA, pin_mask, PERIPH_A, 0); | ||
1243 | 1268 | ||
1244 | atmel_twi0_pclk.dev = &pdev->dev; | 1269 | atmel_twi0_pclk.dev = &pdev->dev; |
1245 | 1270 | ||
@@ -1272,10 +1297,16 @@ static struct clk atmel_mci0_pclk = { | |||
1272 | struct platform_device *__init | 1297 | struct platform_device *__init |
1273 | at32_add_device_mci(unsigned int id, struct mci_platform_data *data) | 1298 | at32_add_device_mci(unsigned int id, struct mci_platform_data *data) |
1274 | { | 1299 | { |
1275 | struct mci_platform_data _data; | ||
1276 | struct platform_device *pdev; | 1300 | struct platform_device *pdev; |
1301 | struct dw_dma_slave *dws; | ||
1302 | u32 pioa_mask; | ||
1303 | u32 piob_mask; | ||
1277 | 1304 | ||
1278 | if (id != 0) | 1305 | if (id != 0 || !data) |
1306 | return NULL; | ||
1307 | |||
1308 | /* Must have at least one usable slot */ | ||
1309 | if (!data->slot[0].bus_width && !data->slot[1].bus_width) | ||
1279 | return NULL; | 1310 | return NULL; |
1280 | 1311 | ||
1281 | pdev = platform_device_alloc("atmel_mci", id); | 1312 | pdev = platform_device_alloc("atmel_mci", id); |
@@ -1286,28 +1317,80 @@ at32_add_device_mci(unsigned int id, struct mci_platform_data *data) | |||
1286 | ARRAY_SIZE(atmel_mci0_resource))) | 1317 | ARRAY_SIZE(atmel_mci0_resource))) |
1287 | goto fail; | 1318 | goto fail; |
1288 | 1319 | ||
1289 | if (!data) { | 1320 | if (data->dma_slave) |
1290 | data = &_data; | 1321 | dws = kmemdup(to_dw_dma_slave(data->dma_slave), |
1291 | memset(data, -1, sizeof(struct mci_platform_data)); | 1322 | sizeof(struct dw_dma_slave), GFP_KERNEL); |
1292 | data->detect_pin = GPIO_PIN_NONE; | 1323 | else |
1293 | data->wp_pin = GPIO_PIN_NONE; | 1324 | dws = kzalloc(sizeof(struct dw_dma_slave), GFP_KERNEL); |
1294 | } | 1325 | |
1326 | dws->slave.dev = &pdev->dev; | ||
1327 | dws->slave.dma_dev = &dw_dmac0_device.dev; | ||
1328 | dws->slave.reg_width = DMA_SLAVE_WIDTH_32BIT; | ||
1329 | dws->cfg_hi = (DWC_CFGH_SRC_PER(0) | ||
1330 | | DWC_CFGH_DST_PER(1)); | ||
1331 | dws->cfg_lo &= ~(DWC_CFGL_HS_DST_POL | ||
1332 | | DWC_CFGL_HS_SRC_POL); | ||
1333 | |||
1334 | data->dma_slave = &dws->slave; | ||
1295 | 1335 | ||
1296 | if (platform_device_add_data(pdev, data, | 1336 | if (platform_device_add_data(pdev, data, |
1297 | sizeof(struct mci_platform_data))) | 1337 | sizeof(struct mci_platform_data))) |
1298 | goto fail; | 1338 | goto fail; |
1299 | 1339 | ||
1300 | select_peripheral(PA(10), PERIPH_A, 0); /* CLK */ | 1340 | /* CLK line is common to both slots */ |
1301 | select_peripheral(PA(11), PERIPH_A, 0); /* CMD */ | 1341 | pioa_mask = 1 << 10; |
1302 | select_peripheral(PA(12), PERIPH_A, 0); /* DATA0 */ | ||
1303 | select_peripheral(PA(13), PERIPH_A, 0); /* DATA1 */ | ||
1304 | select_peripheral(PA(14), PERIPH_A, 0); /* DATA2 */ | ||
1305 | select_peripheral(PA(15), PERIPH_A, 0); /* DATA3 */ | ||
1306 | 1342 | ||
1307 | if (gpio_is_valid(data->detect_pin)) | 1343 | switch (data->slot[0].bus_width) { |
1308 | at32_select_gpio(data->detect_pin, 0); | 1344 | case 4: |
1309 | if (gpio_is_valid(data->wp_pin)) | 1345 | pioa_mask |= 1 << 13; /* DATA1 */ |
1310 | at32_select_gpio(data->wp_pin, 0); | 1346 | pioa_mask |= 1 << 14; /* DATA2 */ |
1347 | pioa_mask |= 1 << 15; /* DATA3 */ | ||
1348 | /* fall through */ | ||
1349 | case 1: | ||
1350 | pioa_mask |= 1 << 11; /* CMD */ | ||
1351 | pioa_mask |= 1 << 12; /* DATA0 */ | ||
1352 | |||
1353 | if (gpio_is_valid(data->slot[0].detect_pin)) | ||
1354 | at32_select_gpio(data->slot[0].detect_pin, 0); | ||
1355 | if (gpio_is_valid(data->slot[0].wp_pin)) | ||
1356 | at32_select_gpio(data->slot[0].wp_pin, 0); | ||
1357 | break; | ||
1358 | case 0: | ||
1359 | /* Slot is unused */ | ||
1360 | break; | ||
1361 | default: | ||
1362 | goto fail; | ||
1363 | } | ||
1364 | |||
1365 | select_peripheral(PIOA, pioa_mask, PERIPH_A, 0); | ||
1366 | piob_mask = 0; | ||
1367 | |||
1368 | switch (data->slot[1].bus_width) { | ||
1369 | case 4: | ||
1370 | piob_mask |= 1 << 8; /* DATA1 */ | ||
1371 | piob_mask |= 1 << 9; /* DATA2 */ | ||
1372 | piob_mask |= 1 << 10; /* DATA3 */ | ||
1373 | /* fall through */ | ||
1374 | case 1: | ||
1375 | piob_mask |= 1 << 6; /* CMD */ | ||
1376 | piob_mask |= 1 << 7; /* DATA0 */ | ||
1377 | select_peripheral(PIOB, piob_mask, PERIPH_B, 0); | ||
1378 | |||
1379 | if (gpio_is_valid(data->slot[1].detect_pin)) | ||
1380 | at32_select_gpio(data->slot[1].detect_pin, 0); | ||
1381 | if (gpio_is_valid(data->slot[1].wp_pin)) | ||
1382 | at32_select_gpio(data->slot[1].wp_pin, 0); | ||
1383 | break; | ||
1384 | case 0: | ||
1385 | /* Slot is unused */ | ||
1386 | break; | ||
1387 | default: | ||
1388 | if (!data->slot[0].bus_width) | ||
1389 | goto fail; | ||
1390 | |||
1391 | data->slot[1].bus_width = 0; | ||
1392 | break; | ||
1393 | } | ||
1311 | 1394 | ||
1312 | atmel_mci0_pclk.dev = &pdev->dev; | 1395 | atmel_mci0_pclk.dev = &pdev->dev; |
1313 | 1396 | ||
@@ -1353,13 +1436,14 @@ static struct clk atmel_lcdfb0_pixclk = { | |||
1353 | struct platform_device *__init | 1436 | struct platform_device *__init |
1354 | at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, | 1437 | at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, |
1355 | unsigned long fbmem_start, unsigned long fbmem_len, | 1438 | unsigned long fbmem_start, unsigned long fbmem_len, |
1356 | unsigned int pin_config) | 1439 | u64 pin_mask) |
1357 | { | 1440 | { |
1358 | struct platform_device *pdev; | 1441 | struct platform_device *pdev; |
1359 | struct atmel_lcdfb_info *info; | 1442 | struct atmel_lcdfb_info *info; |
1360 | struct fb_monspecs *monspecs; | 1443 | struct fb_monspecs *monspecs; |
1361 | struct fb_videomode *modedb; | 1444 | struct fb_videomode *modedb; |
1362 | unsigned int modedb_size; | 1445 | unsigned int modedb_size; |
1446 | u32 portc_mask, portd_mask, porte_mask; | ||
1363 | 1447 | ||
1364 | /* | 1448 | /* |
1365 | * Do a deep copy of the fb data, monspecs and modedb. Make | 1449 | * Do a deep copy of the fb data, monspecs and modedb. Make |
@@ -1381,76 +1465,21 @@ at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, | |||
1381 | case 0: | 1465 | case 0: |
1382 | pdev = &atmel_lcdfb0_device; | 1466 | pdev = &atmel_lcdfb0_device; |
1383 | 1467 | ||
1384 | switch (pin_config) { | 1468 | if (pin_mask == 0ULL) |
1385 | case 0: | 1469 | /* Default to "full" lcdc control signals and 24bit */ |
1386 | select_peripheral(PC(19), PERIPH_A, 0); /* CC */ | 1470 | pin_mask = ATMEL_LCDC_PRI_24BIT | ATMEL_LCDC_PRI_CONTROL; |
1387 | select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ | 1471 | |
1388 | select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ | 1472 | /* LCDC on port C */ |
1389 | select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */ | 1473 | portc_mask = (pin_mask & 0xfff80000) >> 19; |
1390 | select_peripheral(PC(23), PERIPH_A, 0); /* DVAL */ | 1474 | select_peripheral(PIOC, portc_mask, PERIPH_A, 0); |
1391 | select_peripheral(PC(24), PERIPH_A, 0); /* MODE */ | 1475 | |
1392 | select_peripheral(PC(25), PERIPH_A, 0); /* PWR */ | 1476 | /* LCDC on port D */ |
1393 | select_peripheral(PC(26), PERIPH_A, 0); /* DATA0 */ | 1477 | portd_mask = pin_mask & 0x0003ffff; |
1394 | select_peripheral(PC(27), PERIPH_A, 0); /* DATA1 */ | 1478 | select_peripheral(PIOD, portd_mask, PERIPH_A, 0); |
1395 | select_peripheral(PC(28), PERIPH_A, 0); /* DATA2 */ | 1479 | |
1396 | select_peripheral(PC(29), PERIPH_A, 0); /* DATA3 */ | 1480 | /* LCDC on port E */ |
1397 | select_peripheral(PC(30), PERIPH_A, 0); /* DATA4 */ | 1481 | porte_mask = (pin_mask >> 32) & 0x0007ffff; |
1398 | select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */ | 1482 | select_peripheral(PIOE, porte_mask, PERIPH_B, 0); |
1399 | select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */ | ||
1400 | select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */ | ||
1401 | select_peripheral(PD(2), PERIPH_A, 0); /* DATA8 */ | ||
1402 | select_peripheral(PD(3), PERIPH_A, 0); /* DATA9 */ | ||
1403 | select_peripheral(PD(4), PERIPH_A, 0); /* DATA10 */ | ||
1404 | select_peripheral(PD(5), PERIPH_A, 0); /* DATA11 */ | ||
1405 | select_peripheral(PD(6), PERIPH_A, 0); /* DATA12 */ | ||
1406 | select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */ | ||
1407 | select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */ | ||
1408 | select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */ | ||
1409 | select_peripheral(PD(10), PERIPH_A, 0); /* DATA16 */ | ||
1410 | select_peripheral(PD(11), PERIPH_A, 0); /* DATA17 */ | ||
1411 | select_peripheral(PD(12), PERIPH_A, 0); /* DATA18 */ | ||
1412 | select_peripheral(PD(13), PERIPH_A, 0); /* DATA19 */ | ||
1413 | select_peripheral(PD(14), PERIPH_A, 0); /* DATA20 */ | ||
1414 | select_peripheral(PD(15), PERIPH_A, 0); /* DATA21 */ | ||
1415 | select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ | ||
1416 | select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ | ||
1417 | break; | ||
1418 | case 1: | ||
1419 | select_peripheral(PE(0), PERIPH_B, 0); /* CC */ | ||
1420 | select_peripheral(PC(20), PERIPH_A, 0); /* HSYNC */ | ||
1421 | select_peripheral(PC(21), PERIPH_A, 0); /* PCLK */ | ||
1422 | select_peripheral(PC(22), PERIPH_A, 0); /* VSYNC */ | ||
1423 | select_peripheral(PE(1), PERIPH_B, 0); /* DVAL */ | ||
1424 | select_peripheral(PE(2), PERIPH_B, 0); /* MODE */ | ||
1425 | select_peripheral(PC(25), PERIPH_A, 0); /* PWR */ | ||
1426 | select_peripheral(PE(3), PERIPH_B, 0); /* DATA0 */ | ||
1427 | select_peripheral(PE(4), PERIPH_B, 0); /* DATA1 */ | ||
1428 | select_peripheral(PE(5), PERIPH_B, 0); /* DATA2 */ | ||
1429 | select_peripheral(PE(6), PERIPH_B, 0); /* DATA3 */ | ||
1430 | select_peripheral(PE(7), PERIPH_B, 0); /* DATA4 */ | ||
1431 | select_peripheral(PC(31), PERIPH_A, 0); /* DATA5 */ | ||
1432 | select_peripheral(PD(0), PERIPH_A, 0); /* DATA6 */ | ||
1433 | select_peripheral(PD(1), PERIPH_A, 0); /* DATA7 */ | ||
1434 | select_peripheral(PE(8), PERIPH_B, 0); /* DATA8 */ | ||
1435 | select_peripheral(PE(9), PERIPH_B, 0); /* DATA9 */ | ||
1436 | select_peripheral(PE(10), PERIPH_B, 0); /* DATA10 */ | ||
1437 | select_peripheral(PE(11), PERIPH_B, 0); /* DATA11 */ | ||
1438 | select_peripheral(PE(12), PERIPH_B, 0); /* DATA12 */ | ||
1439 | select_peripheral(PD(7), PERIPH_A, 0); /* DATA13 */ | ||
1440 | select_peripheral(PD(8), PERIPH_A, 0); /* DATA14 */ | ||
1441 | select_peripheral(PD(9), PERIPH_A, 0); /* DATA15 */ | ||
1442 | select_peripheral(PE(13), PERIPH_B, 0); /* DATA16 */ | ||
1443 | select_peripheral(PE(14), PERIPH_B, 0); /* DATA17 */ | ||
1444 | select_peripheral(PE(15), PERIPH_B, 0); /* DATA18 */ | ||
1445 | select_peripheral(PE(16), PERIPH_B, 0); /* DATA19 */ | ||
1446 | select_peripheral(PE(17), PERIPH_B, 0); /* DATA20 */ | ||
1447 | select_peripheral(PE(18), PERIPH_B, 0); /* DATA21 */ | ||
1448 | select_peripheral(PD(16), PERIPH_A, 0); /* DATA22 */ | ||
1449 | select_peripheral(PD(17), PERIPH_A, 0); /* DATA23 */ | ||
1450 | break; | ||
1451 | default: | ||
1452 | goto err_invalid_id; | ||
1453 | } | ||
1454 | 1483 | ||
1455 | clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); | 1484 | clk_set_parent(&atmel_lcdfb0_pixclk, &pll0); |
1456 | clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); | 1485 | clk_set_rate(&atmel_lcdfb0_pixclk, clk_get_rate(&pll0)); |
@@ -1499,6 +1528,7 @@ static struct clk atmel_pwm0_mck = { | |||
1499 | struct platform_device *__init at32_add_device_pwm(u32 mask) | 1528 | struct platform_device *__init at32_add_device_pwm(u32 mask) |
1500 | { | 1529 | { |
1501 | struct platform_device *pdev; | 1530 | struct platform_device *pdev; |
1531 | u32 pin_mask; | ||
1502 | 1532 | ||
1503 | if (!mask) | 1533 | if (!mask) |
1504 | return NULL; | 1534 | return NULL; |
@@ -1514,14 +1544,21 @@ struct platform_device *__init at32_add_device_pwm(u32 mask) | |||
1514 | if (platform_device_add_data(pdev, &mask, sizeof(mask))) | 1544 | if (platform_device_add_data(pdev, &mask, sizeof(mask))) |
1515 | goto out_free_pdev; | 1545 | goto out_free_pdev; |
1516 | 1546 | ||
1547 | pin_mask = 0; | ||
1517 | if (mask & (1 << 0)) | 1548 | if (mask & (1 << 0)) |
1518 | select_peripheral(PA(28), PERIPH_A, 0); | 1549 | pin_mask |= (1 << 28); |
1519 | if (mask & (1 << 1)) | 1550 | if (mask & (1 << 1)) |
1520 | select_peripheral(PA(29), PERIPH_A, 0); | 1551 | pin_mask |= (1 << 29); |
1552 | if (pin_mask > 0) | ||
1553 | select_peripheral(PIOA, pin_mask, PERIPH_A, 0); | ||
1554 | |||
1555 | pin_mask = 0; | ||
1521 | if (mask & (1 << 2)) | 1556 | if (mask & (1 << 2)) |
1522 | select_peripheral(PA(21), PERIPH_B, 0); | 1557 | pin_mask |= (1 << 21); |
1523 | if (mask & (1 << 3)) | 1558 | if (mask & (1 << 3)) |
1524 | select_peripheral(PA(22), PERIPH_B, 0); | 1559 | pin_mask |= (1 << 22); |
1560 | if (pin_mask > 0) | ||
1561 | select_peripheral(PIOA, pin_mask, PERIPH_B, 0); | ||
1525 | 1562 | ||
1526 | atmel_pwm0_mck.dev = &pdev->dev; | 1563 | atmel_pwm0_mck.dev = &pdev->dev; |
1527 | 1564 | ||
@@ -1562,52 +1599,65 @@ struct platform_device *__init | |||
1562 | at32_add_device_ssc(unsigned int id, unsigned int flags) | 1599 | at32_add_device_ssc(unsigned int id, unsigned int flags) |
1563 | { | 1600 | { |
1564 | struct platform_device *pdev; | 1601 | struct platform_device *pdev; |
1602 | u32 pin_mask = 0; | ||
1565 | 1603 | ||
1566 | switch (id) { | 1604 | switch (id) { |
1567 | case 0: | 1605 | case 0: |
1568 | pdev = &ssc0_device; | 1606 | pdev = &ssc0_device; |
1569 | if (flags & ATMEL_SSC_RF) | 1607 | if (flags & ATMEL_SSC_RF) |
1570 | select_peripheral(PA(21), PERIPH_A, 0); /* RF */ | 1608 | pin_mask |= (1 << 21); /* RF */ |
1571 | if (flags & ATMEL_SSC_RK) | 1609 | if (flags & ATMEL_SSC_RK) |
1572 | select_peripheral(PA(22), PERIPH_A, 0); /* RK */ | 1610 | pin_mask |= (1 << 22); /* RK */ |
1573 | if (flags & ATMEL_SSC_TK) | 1611 | if (flags & ATMEL_SSC_TK) |
1574 | select_peripheral(PA(23), PERIPH_A, 0); /* TK */ | 1612 | pin_mask |= (1 << 23); /* TK */ |
1575 | if (flags & ATMEL_SSC_TF) | 1613 | if (flags & ATMEL_SSC_TF) |
1576 | select_peripheral(PA(24), PERIPH_A, 0); /* TF */ | 1614 | pin_mask |= (1 << 24); /* TF */ |
1577 | if (flags & ATMEL_SSC_TD) | 1615 | if (flags & ATMEL_SSC_TD) |
1578 | select_peripheral(PA(25), PERIPH_A, 0); /* TD */ | 1616 | pin_mask |= (1 << 25); /* TD */ |
1579 | if (flags & ATMEL_SSC_RD) | 1617 | if (flags & ATMEL_SSC_RD) |
1580 | select_peripheral(PA(26), PERIPH_A, 0); /* RD */ | 1618 | pin_mask |= (1 << 26); /* RD */ |
1619 | |||
1620 | if (pin_mask > 0) | ||
1621 | select_peripheral(PIOA, pin_mask, PERIPH_A, 0); | ||
1622 | |||
1581 | break; | 1623 | break; |
1582 | case 1: | 1624 | case 1: |
1583 | pdev = &ssc1_device; | 1625 | pdev = &ssc1_device; |
1584 | if (flags & ATMEL_SSC_RF) | 1626 | if (flags & ATMEL_SSC_RF) |
1585 | select_peripheral(PA(0), PERIPH_B, 0); /* RF */ | 1627 | pin_mask |= (1 << 0); /* RF */ |
1586 | if (flags & ATMEL_SSC_RK) | 1628 | if (flags & ATMEL_SSC_RK) |
1587 | select_peripheral(PA(1), PERIPH_B, 0); /* RK */ | 1629 | pin_mask |= (1 << 1); /* RK */ |
1588 | if (flags & ATMEL_SSC_TK) | 1630 | if (flags & ATMEL_SSC_TK) |
1589 | select_peripheral(PA(2), PERIPH_B, 0); /* TK */ | 1631 | pin_mask |= (1 << 2); /* TK */ |
1590 | if (flags & ATMEL_SSC_TF) | 1632 | if (flags & ATMEL_SSC_TF) |
1591 | select_peripheral(PA(3), PERIPH_B, 0); /* TF */ | 1633 | pin_mask |= (1 << 3); /* TF */ |
1592 | if (flags & ATMEL_SSC_TD) | 1634 | if (flags & ATMEL_SSC_TD) |
1593 | select_peripheral(PA(4), PERIPH_B, 0); /* TD */ | 1635 | pin_mask |= (1 << 4); /* TD */ |
1594 | if (flags & ATMEL_SSC_RD) | 1636 | if (flags & ATMEL_SSC_RD) |
1595 | select_peripheral(PA(5), PERIPH_B, 0); /* RD */ | 1637 | pin_mask |= (1 << 5); /* RD */ |
1638 | |||
1639 | if (pin_mask > 0) | ||
1640 | select_peripheral(PIOA, pin_mask, PERIPH_B, 0); | ||
1641 | |||
1596 | break; | 1642 | break; |
1597 | case 2: | 1643 | case 2: |
1598 | pdev = &ssc2_device; | 1644 | pdev = &ssc2_device; |
1599 | if (flags & ATMEL_SSC_TD) | 1645 | if (flags & ATMEL_SSC_TD) |
1600 | select_peripheral(PB(13), PERIPH_A, 0); /* TD */ | 1646 | pin_mask |= (1 << 13); /* TD */ |
1601 | if (flags & ATMEL_SSC_RD) | 1647 | if (flags & ATMEL_SSC_RD) |
1602 | select_peripheral(PB(14), PERIPH_A, 0); /* RD */ | 1648 | pin_mask |= (1 << 14); /* RD */ |
1603 | if (flags & ATMEL_SSC_TK) | 1649 | if (flags & ATMEL_SSC_TK) |
1604 | select_peripheral(PB(15), PERIPH_A, 0); /* TK */ | 1650 | pin_mask |= (1 << 15); /* TK */ |
1605 | if (flags & ATMEL_SSC_TF) | 1651 | if (flags & ATMEL_SSC_TF) |
1606 | select_peripheral(PB(16), PERIPH_A, 0); /* TF */ | 1652 | pin_mask |= (1 << 16); /* TF */ |
1607 | if (flags & ATMEL_SSC_RF) | 1653 | if (flags & ATMEL_SSC_RF) |
1608 | select_peripheral(PB(17), PERIPH_A, 0); /* RF */ | 1654 | pin_mask |= (1 << 17); /* RF */ |
1609 | if (flags & ATMEL_SSC_RK) | 1655 | if (flags & ATMEL_SSC_RK) |
1610 | select_peripheral(PB(18), PERIPH_A, 0); /* RK */ | 1656 | pin_mask |= (1 << 18); /* RK */ |
1657 | |||
1658 | if (pin_mask > 0) | ||
1659 | select_peripheral(PIOB, pin_mask, PERIPH_A, 0); | ||
1660 | |||
1611 | break; | 1661 | break; |
1612 | default: | 1662 | default: |
1613 | return NULL; | 1663 | return NULL; |
@@ -1745,14 +1795,15 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, | |||
1745 | unsigned int cs, unsigned int extint) | 1795 | unsigned int cs, unsigned int extint) |
1746 | { | 1796 | { |
1747 | static unsigned int extint_pin_map[4] __initdata = { | 1797 | static unsigned int extint_pin_map[4] __initdata = { |
1748 | GPIO_PIN_PB(25), | 1798 | (1 << 25), |
1749 | GPIO_PIN_PB(26), | 1799 | (1 << 26), |
1750 | GPIO_PIN_PB(27), | 1800 | (1 << 27), |
1751 | GPIO_PIN_PB(28), | 1801 | (1 << 28), |
1752 | }; | 1802 | }; |
1753 | static bool common_pins_initialized __initdata = false; | 1803 | static bool common_pins_initialized __initdata = false; |
1754 | unsigned int extint_pin; | 1804 | unsigned int extint_pin; |
1755 | int ret; | 1805 | int ret; |
1806 | u32 pin_mask; | ||
1756 | 1807 | ||
1757 | if (extint >= ARRAY_SIZE(extint_pin_map)) | 1808 | if (extint >= ARRAY_SIZE(extint_pin_map)) |
1758 | return -EINVAL; | 1809 | return -EINVAL; |
@@ -1766,7 +1817,8 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, | |||
1766 | if (ret) | 1817 | if (ret) |
1767 | return ret; | 1818 | return ret; |
1768 | 1819 | ||
1769 | select_peripheral(PE(21), PERIPH_A, 0); /* NCS4 -> OE_N */ | 1820 | /* NCS4 -> OE_N */ |
1821 | select_peripheral(PIOE, (1 << 21), PERIPH_A, 0); | ||
1770 | hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF0_ENABLE); | 1822 | hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF0_ENABLE); |
1771 | break; | 1823 | break; |
1772 | case 5: | 1824 | case 5: |
@@ -1776,7 +1828,8 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, | |||
1776 | if (ret) | 1828 | if (ret) |
1777 | return ret; | 1829 | return ret; |
1778 | 1830 | ||
1779 | select_peripheral(PE(22), PERIPH_A, 0); /* NCS5 -> OE_N */ | 1831 | /* NCS5 -> OE_N */ |
1832 | select_peripheral(PIOE, (1 << 22), PERIPH_A, 0); | ||
1780 | hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF1_ENABLE); | 1833 | hmatrix_sfr_set_bits(HMATRIX_SLAVE_EBI, HMATRIX_EBI_CF1_ENABLE); |
1781 | break; | 1834 | break; |
1782 | default: | 1835 | default: |
@@ -1784,14 +1837,17 @@ static int __init at32_init_ide_or_cf(struct platform_device *pdev, | |||
1784 | } | 1837 | } |
1785 | 1838 | ||
1786 | if (!common_pins_initialized) { | 1839 | if (!common_pins_initialized) { |
1787 | select_peripheral(PE(19), PERIPH_A, 0); /* CFCE1 -> CS0_N */ | 1840 | pin_mask = (1 << 19); /* CFCE1 -> CS0_N */ |
1788 | select_peripheral(PE(20), PERIPH_A, 0); /* CFCE2 -> CS1_N */ | 1841 | pin_mask |= (1 << 20); /* CFCE2 -> CS1_N */ |
1789 | select_peripheral(PE(23), PERIPH_A, 0); /* CFRNW -> DIR */ | 1842 | pin_mask |= (1 << 23); /* CFRNW -> DIR */ |
1790 | select_peripheral(PE(24), PERIPH_A, 0); /* NWAIT <- IORDY */ | 1843 | pin_mask |= (1 << 24); /* NWAIT <- IORDY */ |
1844 | |||
1845 | select_peripheral(PIOE, pin_mask, PERIPH_A, 0); | ||
1846 | |||
1791 | common_pins_initialized = true; | 1847 | common_pins_initialized = true; |
1792 | } | 1848 | } |
1793 | 1849 | ||
1794 | at32_select_periph(extint_pin, GPIO_PERIPH_A, AT32_GPIOF_DEGLITCH); | 1850 | select_peripheral(PIOB, extint_pin, PERIPH_A, AT32_GPIOF_DEGLITCH); |
1795 | 1851 | ||
1796 | pdev->resource[1].start = EIM_IRQ_BASE + extint; | 1852 | pdev->resource[1].start = EIM_IRQ_BASE + extint; |
1797 | pdev->resource[1].end = pdev->resource[1].start; | 1853 | pdev->resource[1].end = pdev->resource[1].start; |
@@ -1930,6 +1986,7 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data) | |||
1930 | { | 1986 | { |
1931 | struct platform_device *pdev; | 1987 | struct platform_device *pdev; |
1932 | struct ac97c_platform_data _data; | 1988 | struct ac97c_platform_data _data; |
1989 | u32 pin_mask; | ||
1933 | 1990 | ||
1934 | if (id != 0) | 1991 | if (id != 0) |
1935 | return NULL; | 1992 | return NULL; |
@@ -1956,10 +2013,10 @@ at32_add_device_ac97c(unsigned int id, struct ac97c_platform_data *data) | |||
1956 | sizeof(struct ac97c_platform_data))) | 2013 | sizeof(struct ac97c_platform_data))) |
1957 | goto fail; | 2014 | goto fail; |
1958 | 2015 | ||
1959 | select_peripheral(PB(20), PERIPH_B, 0); /* SDO */ | 2016 | pin_mask = (1 << 20) | (1 << 21); /* SDO & SYNC */ |
1960 | select_peripheral(PB(21), PERIPH_B, 0); /* SYNC */ | 2017 | pin_mask |= (1 << 22) | (1 << 23); /* SCLK & SDI */ |
1961 | select_peripheral(PB(22), PERIPH_B, 0); /* SCLK */ | 2018 | |
1962 | select_peripheral(PB(23), PERIPH_B, 0); /* SDI */ | 2019 | select_peripheral(PIOB, pin_mask, PERIPH_B, 0); |
1963 | 2020 | ||
1964 | /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */ | 2021 | /* TODO: gpio_is_valid(data->reset_pin) with kernel 2.6.26. */ |
1965 | if (data->reset_pin != GPIO_PIN_NONE) | 2022 | if (data->reset_pin != GPIO_PIN_NONE) |
@@ -2001,6 +2058,7 @@ static struct clk abdac0_sample_clk = { | |||
2001 | struct platform_device *__init at32_add_device_abdac(unsigned int id) | 2058 | struct platform_device *__init at32_add_device_abdac(unsigned int id) |
2002 | { | 2059 | { |
2003 | struct platform_device *pdev; | 2060 | struct platform_device *pdev; |
2061 | u32 pin_mask; | ||
2004 | 2062 | ||
2005 | if (id != 0) | 2063 | if (id != 0) |
2006 | return NULL; | 2064 | return NULL; |
@@ -2013,10 +2071,10 @@ struct platform_device *__init at32_add_device_abdac(unsigned int id) | |||
2013 | ARRAY_SIZE(abdac0_resource))) | 2071 | ARRAY_SIZE(abdac0_resource))) |
2014 | goto err_add_resources; | 2072 | goto err_add_resources; |
2015 | 2073 | ||
2016 | select_peripheral(PB(20), PERIPH_A, 0); /* DATA1 */ | 2074 | pin_mask = (1 << 20) | (1 << 22); /* DATA1 & DATAN1 */ |
2017 | select_peripheral(PB(21), PERIPH_A, 0); /* DATA0 */ | 2075 | pin_mask |= (1 << 21) | (1 << 23); /* DATA0 & DATAN0 */ |
2018 | select_peripheral(PB(22), PERIPH_A, 0); /* DATAN1 */ | 2076 | |
2019 | select_peripheral(PB(23), PERIPH_A, 0); /* DATAN0 */ | 2077 | select_peripheral(PIOB, pin_mask, PERIPH_A, 0); |
2020 | 2078 | ||
2021 | abdac0_pclk.dev = &pdev->dev; | 2079 | abdac0_pclk.dev = &pdev->dev; |
2022 | abdac0_sample_clk.dev = &pdev->dev; | 2080 | abdac0_sample_clk.dev = &pdev->dev; |
@@ -2073,7 +2131,7 @@ static struct clk gclk4 = { | |||
2073 | .index = 4, | 2131 | .index = 4, |
2074 | }; | 2132 | }; |
2075 | 2133 | ||
2076 | struct clk *at32_clock_list[] = { | 2134 | static __initdata struct clk *init_clocks[] = { |
2077 | &osc32k, | 2135 | &osc32k, |
2078 | &osc0, | 2136 | &osc0, |
2079 | &osc1, | 2137 | &osc1, |
@@ -2137,7 +2195,6 @@ struct clk *at32_clock_list[] = { | |||
2137 | &gclk3, | 2195 | &gclk3, |
2138 | &gclk4, | 2196 | &gclk4, |
2139 | }; | 2197 | }; |
2140 | unsigned int at32_nr_clocks = ARRAY_SIZE(at32_clock_list); | ||
2141 | 2198 | ||
2142 | void __init setup_platform(void) | 2199 | void __init setup_platform(void) |
2143 | { | 2200 | { |
@@ -2168,14 +2225,19 @@ void __init setup_platform(void) | |||
2168 | genclk_init_parent(&abdac0_sample_clk); | 2225 | genclk_init_parent(&abdac0_sample_clk); |
2169 | 2226 | ||
2170 | /* | 2227 | /* |
2171 | * Turn on all clocks that have at least one user already, and | 2228 | * Build initial dynamic clock list by registering all clocks |
2172 | * turn off everything else. We only do this for module | 2229 | * from the array. |
2173 | * clocks, and even though it isn't particularly pretty to | 2230 | * At the same time, turn on all clocks that have at least one |
2174 | * check the address of the mode function, it should do the | 2231 | * user already, and turn off everything else. We only do this |
2175 | * trick... | 2232 | * for module clocks, and even though it isn't particularly |
2233 | * pretty to check the address of the mode function, it should | ||
2234 | * do the trick... | ||
2176 | */ | 2235 | */ |
2177 | for (i = 0; i < ARRAY_SIZE(at32_clock_list); i++) { | 2236 | for (i = 0; i < ARRAY_SIZE(init_clocks); i++) { |
2178 | struct clk *clk = at32_clock_list[i]; | 2237 | struct clk *clk = init_clocks[i]; |
2238 | |||
2239 | /* first, register clock */ | ||
2240 | at32_clk_register(clk); | ||
2179 | 2241 | ||
2180 | if (clk->users == 0) | 2242 | if (clk->users == 0) |
2181 | continue; | 2243 | continue; |
diff --git a/arch/avr32/mach-at32ap/clock.c b/arch/avr32/mach-at32ap/clock.c index 6c27ddac5adf..138a00a2a2d0 100644 --- a/arch/avr32/mach-at32ap/clock.c +++ b/arch/avr32/mach-at32ap/clock.c | |||
@@ -15,24 +15,40 @@ | |||
15 | #include <linux/err.h> | 15 | #include <linux/err.h> |
16 | #include <linux/device.h> | 16 | #include <linux/device.h> |
17 | #include <linux/string.h> | 17 | #include <linux/string.h> |
18 | #include <linux/list.h> | ||
18 | 19 | ||
19 | #include <mach/chip.h> | 20 | #include <mach/chip.h> |
20 | 21 | ||
21 | #include "clock.h" | 22 | #include "clock.h" |
22 | 23 | ||
24 | /* at32 clock list */ | ||
25 | static LIST_HEAD(at32_clock_list); | ||
26 | |||
23 | static DEFINE_SPINLOCK(clk_lock); | 27 | static DEFINE_SPINLOCK(clk_lock); |
28 | static DEFINE_SPINLOCK(clk_list_lock); | ||
29 | |||
30 | void at32_clk_register(struct clk *clk) | ||
31 | { | ||
32 | spin_lock(&clk_list_lock); | ||
33 | /* add the new item to the end of the list */ | ||
34 | list_add_tail(&clk->list, &at32_clock_list); | ||
35 | spin_unlock(&clk_list_lock); | ||
36 | } | ||
24 | 37 | ||
25 | struct clk *clk_get(struct device *dev, const char *id) | 38 | struct clk *clk_get(struct device *dev, const char *id) |
26 | { | 39 | { |
27 | int i; | 40 | struct clk *clk; |
28 | 41 | ||
29 | for (i = 0; i < at32_nr_clocks; i++) { | 42 | spin_lock(&clk_list_lock); |
30 | struct clk *clk = at32_clock_list[i]; | ||
31 | 43 | ||
32 | if (clk->dev == dev && strcmp(id, clk->name) == 0) | 44 | list_for_each_entry(clk, &at32_clock_list, list) { |
45 | if (clk->dev == dev && strcmp(id, clk->name) == 0) { | ||
46 | spin_unlock(&clk_list_lock); | ||
33 | return clk; | 47 | return clk; |
48 | } | ||
34 | } | 49 | } |
35 | 50 | ||
51 | spin_unlock(&clk_list_lock); | ||
36 | return ERR_PTR(-ENOENT); | 52 | return ERR_PTR(-ENOENT); |
37 | } | 53 | } |
38 | EXPORT_SYMBOL(clk_get); | 54 | EXPORT_SYMBOL(clk_get); |
@@ -203,8 +219,8 @@ dump_clock(struct clk *parent, struct clkinf *r) | |||
203 | 219 | ||
204 | /* cost of this scan is small, but not linear... */ | 220 | /* cost of this scan is small, but not linear... */ |
205 | r->nest = nest + NEST_DELTA; | 221 | r->nest = nest + NEST_DELTA; |
206 | for (i = 3; i < at32_nr_clocks; i++) { | 222 | |
207 | clk = at32_clock_list[i]; | 223 | list_for_each_entry(clk, &at32_clock_list, list) { |
208 | if (clk->parent == parent) | 224 | if (clk->parent == parent) |
209 | dump_clock(clk, r); | 225 | dump_clock(clk, r); |
210 | } | 226 | } |
@@ -215,6 +231,7 @@ static int clk_show(struct seq_file *s, void *unused) | |||
215 | { | 231 | { |
216 | struct clkinf r; | 232 | struct clkinf r; |
217 | int i; | 233 | int i; |
234 | struct clk *clk; | ||
218 | 235 | ||
219 | /* show all the power manager registers */ | 236 | /* show all the power manager registers */ |
220 | seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL)); | 237 | seq_printf(s, "MCCTRL = %8x\n", pm_readl(MCCTRL)); |
@@ -234,14 +251,25 @@ static int clk_show(struct seq_file *s, void *unused) | |||
234 | 251 | ||
235 | seq_printf(s, "\n"); | 252 | seq_printf(s, "\n"); |
236 | 253 | ||
237 | /* show clock tree as derived from the three oscillators | ||
238 | * we "know" are at the head of the list | ||
239 | */ | ||
240 | r.s = s; | 254 | r.s = s; |
241 | r.nest = 0; | 255 | r.nest = 0; |
242 | dump_clock(at32_clock_list[0], &r); | 256 | /* protected from changes on the list while dumping */ |
243 | dump_clock(at32_clock_list[1], &r); | 257 | spin_lock(&clk_list_lock); |
244 | dump_clock(at32_clock_list[2], &r); | 258 | |
259 | /* show clock tree as derived from the three oscillators */ | ||
260 | clk = clk_get(NULL, "osc32k"); | ||
261 | dump_clock(clk, &r); | ||
262 | clk_put(clk); | ||
263 | |||
264 | clk = clk_get(NULL, "osc0"); | ||
265 | dump_clock(clk, &r); | ||
266 | clk_put(clk); | ||
267 | |||
268 | clk = clk_get(NULL, "osc1"); | ||
269 | dump_clock(clk, &r); | ||
270 | clk_put(clk); | ||
271 | |||
272 | spin_unlock(&clk_list_lock); | ||
245 | 273 | ||
246 | return 0; | 274 | return 0; |
247 | } | 275 | } |
diff --git a/arch/avr32/mach-at32ap/clock.h b/arch/avr32/mach-at32ap/clock.h index bb8e1f295835..623bf0e9a1e7 100644 --- a/arch/avr32/mach-at32ap/clock.h +++ b/arch/avr32/mach-at32ap/clock.h | |||
@@ -12,8 +12,13 @@ | |||
12 | * published by the Free Software Foundation. | 12 | * published by the Free Software Foundation. |
13 | */ | 13 | */ |
14 | #include <linux/clk.h> | 14 | #include <linux/clk.h> |
15 | #include <linux/list.h> | ||
16 | |||
17 | |||
18 | void at32_clk_register(struct clk *clk); | ||
15 | 19 | ||
16 | struct clk { | 20 | struct clk { |
21 | struct list_head list; /* linking element */ | ||
17 | const char *name; /* Clock name/function */ | 22 | const char *name; /* Clock name/function */ |
18 | struct device *dev; /* Device the clock is used by */ | 23 | struct device *dev; /* Device the clock is used by */ |
19 | struct clk *parent; /* Parent clock, if any */ | 24 | struct clk *parent; /* Parent clock, if any */ |
@@ -25,6 +30,3 @@ struct clk { | |||
25 | u16 users; /* Enabled if non-zero */ | 30 | u16 users; /* Enabled if non-zero */ |
26 | u16 index; /* Sibling index */ | 31 | u16 index; /* Sibling index */ |
27 | }; | 32 | }; |
28 | |||
29 | extern struct clk *at32_clock_list[]; | ||
30 | extern unsigned int at32_nr_clocks; | ||
diff --git a/arch/avr32/mach-at32ap/include/mach/at32ap700x.h b/arch/avr32/mach-at32ap/include/mach/at32ap700x.h index 1e9852d65cca..a77d372f6f3e 100644 --- a/arch/avr32/mach-at32ap/include/mach/at32ap700x.h +++ b/arch/avr32/mach-at32ap/include/mach/at32ap700x.h | |||
@@ -83,4 +83,132 @@ | |||
83 | #define HMATRIX_BASE 0xfff00800 | 83 | #define HMATRIX_BASE 0xfff00800 |
84 | #define SDRAMC_BASE 0xfff03800 | 84 | #define SDRAMC_BASE 0xfff03800 |
85 | 85 | ||
86 | /* LCDC on port C */ | ||
87 | #define ATMEL_LCDC_PC_CC (1ULL << 19) | ||
88 | #define ATMEL_LCDC_PC_HSYNC (1ULL << 20) | ||
89 | #define ATMEL_LCDC_PC_PCLK (1ULL << 21) | ||
90 | #define ATMEL_LCDC_PC_VSYNC (1ULL << 22) | ||
91 | #define ATMEL_LCDC_PC_DVAL (1ULL << 23) | ||
92 | #define ATMEL_LCDC_PC_MODE (1ULL << 24) | ||
93 | #define ATMEL_LCDC_PC_PWR (1ULL << 25) | ||
94 | #define ATMEL_LCDC_PC_DATA0 (1ULL << 26) | ||
95 | #define ATMEL_LCDC_PC_DATA1 (1ULL << 27) | ||
96 | #define ATMEL_LCDC_PC_DATA2 (1ULL << 28) | ||
97 | #define ATMEL_LCDC_PC_DATA3 (1ULL << 29) | ||
98 | #define ATMEL_LCDC_PC_DATA4 (1ULL << 30) | ||
99 | #define ATMEL_LCDC_PC_DATA5 (1ULL << 31) | ||
100 | |||
101 | /* LCDC on port D */ | ||
102 | #define ATMEL_LCDC_PD_DATA6 (1ULL << 0) | ||
103 | #define ATMEL_LCDC_PD_DATA7 (1ULL << 1) | ||
104 | #define ATMEL_LCDC_PD_DATA8 (1ULL << 2) | ||
105 | #define ATMEL_LCDC_PD_DATA9 (1ULL << 3) | ||
106 | #define ATMEL_LCDC_PD_DATA10 (1ULL << 4) | ||
107 | #define ATMEL_LCDC_PD_DATA11 (1ULL << 5) | ||
108 | #define ATMEL_LCDC_PD_DATA12 (1ULL << 6) | ||
109 | #define ATMEL_LCDC_PD_DATA13 (1ULL << 7) | ||
110 | #define ATMEL_LCDC_PD_DATA14 (1ULL << 8) | ||
111 | #define ATMEL_LCDC_PD_DATA15 (1ULL << 9) | ||
112 | #define ATMEL_LCDC_PD_DATA16 (1ULL << 10) | ||
113 | #define ATMEL_LCDC_PD_DATA17 (1ULL << 11) | ||
114 | #define ATMEL_LCDC_PD_DATA18 (1ULL << 12) | ||
115 | #define ATMEL_LCDC_PD_DATA19 (1ULL << 13) | ||
116 | #define ATMEL_LCDC_PD_DATA20 (1ULL << 14) | ||
117 | #define ATMEL_LCDC_PD_DATA21 (1ULL << 15) | ||
118 | #define ATMEL_LCDC_PD_DATA22 (1ULL << 16) | ||
119 | #define ATMEL_LCDC_PD_DATA23 (1ULL << 17) | ||
120 | |||
121 | /* LCDC on port E */ | ||
122 | #define ATMEL_LCDC_PE_CC (1ULL << (32 + 0)) | ||
123 | #define ATMEL_LCDC_PE_DVAL (1ULL << (32 + 1)) | ||
124 | #define ATMEL_LCDC_PE_MODE (1ULL << (32 + 2)) | ||
125 | #define ATMEL_LCDC_PE_DATA0 (1ULL << (32 + 3)) | ||
126 | #define ATMEL_LCDC_PE_DATA1 (1ULL << (32 + 4)) | ||
127 | #define ATMEL_LCDC_PE_DATA2 (1ULL << (32 + 5)) | ||
128 | #define ATMEL_LCDC_PE_DATA3 (1ULL << (32 + 6)) | ||
129 | #define ATMEL_LCDC_PE_DATA4 (1ULL << (32 + 7)) | ||
130 | #define ATMEL_LCDC_PE_DATA8 (1ULL << (32 + 8)) | ||
131 | #define ATMEL_LCDC_PE_DATA9 (1ULL << (32 + 9)) | ||
132 | #define ATMEL_LCDC_PE_DATA10 (1ULL << (32 + 10)) | ||
133 | #define ATMEL_LCDC_PE_DATA11 (1ULL << (32 + 11)) | ||
134 | #define ATMEL_LCDC_PE_DATA12 (1ULL << (32 + 12)) | ||
135 | #define ATMEL_LCDC_PE_DATA16 (1ULL << (32 + 13)) | ||
136 | #define ATMEL_LCDC_PE_DATA17 (1ULL << (32 + 14)) | ||
137 | #define ATMEL_LCDC_PE_DATA18 (1ULL << (32 + 15)) | ||
138 | #define ATMEL_LCDC_PE_DATA19 (1ULL << (32 + 16)) | ||
139 | #define ATMEL_LCDC_PE_DATA20 (1ULL << (32 + 17)) | ||
140 | #define ATMEL_LCDC_PE_DATA21 (1ULL << (32 + 18)) | ||
141 | |||
142 | |||
143 | #define ATMEL_LCDC(PORT, PIN) (ATMEL_LCDC_##PORT##_##PIN) | ||
144 | |||
145 | |||
146 | #define ATMEL_LCDC_PRI_24B_DATA ( \ | ||
147 | ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \ | ||
148 | ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \ | ||
149 | ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \ | ||
150 | ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \ | ||
151 | ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \ | ||
152 | ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \ | ||
153 | ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA13) | \ | ||
154 | ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \ | ||
155 | ATMEL_LCDC(PD, DATA16) | ATMEL_LCDC(PD, DATA17) | \ | ||
156 | ATMEL_LCDC(PD, DATA18) | ATMEL_LCDC(PD, DATA19) | \ | ||
157 | ATMEL_LCDC(PD, DATA20) | ATMEL_LCDC(PD, DATA21) | \ | ||
158 | ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23)) | ||
159 | |||
160 | #define ATMEL_LCDC_ALT_24B_DATA ( \ | ||
161 | ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \ | ||
162 | ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \ | ||
163 | ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \ | ||
164 | ATMEL_LCDC(PD, DATA6) | ATMEL_LCDC(PD, DATA7) | \ | ||
165 | ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \ | ||
166 | ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \ | ||
167 | ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PD, DATA13) | \ | ||
168 | ATMEL_LCDC(PD, DATA14) | ATMEL_LCDC(PD, DATA15) | \ | ||
169 | ATMEL_LCDC(PE, DATA16) | ATMEL_LCDC(PE, DATA17) | \ | ||
170 | ATMEL_LCDC(PE, DATA18) | ATMEL_LCDC(PE, DATA19) | \ | ||
171 | ATMEL_LCDC(PE, DATA20) | ATMEL_LCDC(PE, DATA21) | \ | ||
172 | ATMEL_LCDC(PD, DATA22) | ATMEL_LCDC(PD, DATA23)) | ||
173 | |||
174 | #define ATMEL_LCDC_PRI_15B_DATA ( \ | ||
175 | ATMEL_LCDC(PC, DATA0) | ATMEL_LCDC(PC, DATA1) | \ | ||
176 | ATMEL_LCDC(PC, DATA2) | ATMEL_LCDC(PC, DATA3) | \ | ||
177 | ATMEL_LCDC(PC, DATA4) | ATMEL_LCDC(PC, DATA5) | \ | ||
178 | ATMEL_LCDC(PD, DATA8) | ATMEL_LCDC(PD, DATA9) | \ | ||
179 | ATMEL_LCDC(PD, DATA10) | ATMEL_LCDC(PD, DATA11) | \ | ||
180 | ATMEL_LCDC(PD, DATA12) | ATMEL_LCDC(PD, DATA16) | \ | ||
181 | ATMEL_LCDC(PD, DATA17) | ATMEL_LCDC(PD, DATA18) | \ | ||
182 | ATMEL_LCDC(PD, DATA19) | ATMEL_LCDC(PD, DATA20)) | ||
183 | |||
184 | #define ATMEL_LCDC_ALT_15B_DATA ( \ | ||
185 | ATMEL_LCDC(PE, DATA0) | ATMEL_LCDC(PE, DATA1) | \ | ||
186 | ATMEL_LCDC(PE, DATA2) | ATMEL_LCDC(PE, DATA3) | \ | ||
187 | ATMEL_LCDC(PE, DATA4) | ATMEL_LCDC(PC, DATA5) | \ | ||
188 | ATMEL_LCDC(PE, DATA8) | ATMEL_LCDC(PE, DATA9) | \ | ||
189 | ATMEL_LCDC(PE, DATA10) | ATMEL_LCDC(PE, DATA11) | \ | ||
190 | ATMEL_LCDC(PE, DATA12) | ATMEL_LCDC(PE, DATA16) | \ | ||
191 | ATMEL_LCDC(PE, DATA17) | ATMEL_LCDC(PE, DATA18) | \ | ||
192 | ATMEL_LCDC(PE, DATA19) | ATMEL_LCDC(PE, DATA20)) | ||
193 | |||
194 | #define ATMEL_LCDC_PRI_CONTROL ( \ | ||
195 | ATMEL_LCDC(PC, CC) | ATMEL_LCDC(PC, DVAL) | \ | ||
196 | ATMEL_LCDC(PC, MODE) | ATMEL_LCDC(PC, PWR)) | ||
197 | |||
198 | #define ATMEL_LCDC_ALT_CONTROL ( \ | ||
199 | ATMEL_LCDC(PE, CC) | ATMEL_LCDC(PE, DVAL) | \ | ||
200 | ATMEL_LCDC(PE, MODE) | ATMEL_LCDC(PC, PWR)) | ||
201 | |||
202 | #define ATMEL_LCDC_CONTROL ( \ | ||
203 | ATMEL_LCDC(PC, HSYNC) | ATMEL_LCDC(PC, VSYNC) | \ | ||
204 | ATMEL_LCDC(PC, PCLK)) | ||
205 | |||
206 | #define ATMEL_LCDC_PRI_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_24B_DATA) | ||
207 | |||
208 | #define ATMEL_LCDC_ALT_24BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_24B_DATA) | ||
209 | |||
210 | #define ATMEL_LCDC_PRI_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_PRI_15B_DATA) | ||
211 | |||
212 | #define ATMEL_LCDC_ALT_15BIT (ATMEL_LCDC_CONTROL | ATMEL_LCDC_ALT_15B_DATA) | ||
213 | |||
86 | #endif /* __ASM_ARCH_AT32AP700X_H__ */ | 214 | #endif /* __ASM_ARCH_AT32AP700X_H__ */ |
diff --git a/arch/avr32/mach-at32ap/include/mach/board.h b/arch/avr32/mach-at32ap/include/mach/board.h index e60e9076544d..c48386d66bc3 100644 --- a/arch/avr32/mach-at32ap/include/mach/board.h +++ b/arch/avr32/mach-at32ap/include/mach/board.h | |||
@@ -43,7 +43,7 @@ struct atmel_lcdfb_info; | |||
43 | struct platform_device * | 43 | struct platform_device * |
44 | at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, | 44 | at32_add_device_lcdc(unsigned int id, struct atmel_lcdfb_info *data, |
45 | unsigned long fbmem_start, unsigned long fbmem_len, | 45 | unsigned long fbmem_start, unsigned long fbmem_len, |
46 | unsigned int pin_config); | 46 | u64 pin_mask); |
47 | 47 | ||
48 | struct usba_platform_data; | 48 | struct usba_platform_data; |
49 | struct platform_device * | 49 | struct platform_device * |
diff --git a/arch/avr32/mach-at32ap/include/mach/io.h b/arch/avr32/mach-at32ap/include/mach/io.h index 4ec6abc68ea3..22ea79b74052 100644 --- a/arch/avr32/mach-at32ap/include/mach/io.h +++ b/arch/avr32/mach-at32ap/include/mach/io.h | |||
@@ -1,8 +1,7 @@ | |||
1 | #ifndef __ASM_AVR32_ARCH_AT32AP_IO_H | 1 | #ifndef __ASM_AVR32_ARCH_AT32AP_IO_H |
2 | #define __ASM_AVR32_ARCH_AT32AP_IO_H | 2 | #define __ASM_AVR32_ARCH_AT32AP_IO_H |
3 | 3 | ||
4 | /* For "bizarre" halfword swapping */ | 4 | #include <linux/swab.h> |
5 | #include <linux/byteorder/swabb.h> | ||
6 | 5 | ||
7 | #if defined(CONFIG_AP700X_32_BIT_SMC) | 6 | #if defined(CONFIG_AP700X_32_BIT_SMC) |
8 | # define __swizzle_addr_b(addr) (addr ^ 3UL) | 7 | # define __swizzle_addr_b(addr) (addr ^ 3UL) |
diff --git a/arch/avr32/mach-at32ap/include/mach/portmux.h b/arch/avr32/mach-at32ap/include/mach/portmux.h index b1abe6b4e4ef..21c79373b53f 100644 --- a/arch/avr32/mach-at32ap/include/mach/portmux.h +++ b/arch/avr32/mach-at32ap/include/mach/portmux.h | |||
@@ -21,9 +21,10 @@ | |||
21 | #define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */ | 21 | #define AT32_GPIOF_DEGLITCH 0x00000008 /* (IN) Filter glitches */ |
22 | #define AT32_GPIOF_MULTIDRV 0x00000010 /* Enable multidriver option */ | 22 | #define AT32_GPIOF_MULTIDRV 0x00000010 /* Enable multidriver option */ |
23 | 23 | ||
24 | void at32_select_periph(unsigned int pin, unsigned int periph, | 24 | void at32_select_periph(unsigned int port, unsigned int pin, |
25 | unsigned long flags); | 25 | unsigned int periph, unsigned long flags); |
26 | void at32_select_gpio(unsigned int pin, unsigned long flags); | 26 | void at32_select_gpio(unsigned int pin, unsigned long flags); |
27 | void at32_deselect_pin(unsigned int pin); | ||
27 | void at32_reserve_pin(unsigned int pin); | 28 | void at32_reserve_pin(unsigned int pin); |
28 | 29 | ||
29 | #endif /* __ASM_ARCH_PORTMUX_H__ */ | 30 | #endif /* __ASM_ARCH_PORTMUX_H__ */ |
diff --git a/arch/avr32/mach-at32ap/pdc.c b/arch/avr32/mach-at32ap/pdc.c index 1040bda4fda7..61ab15aae970 100644 --- a/arch/avr32/mach-at32ap/pdc.c +++ b/arch/avr32/mach-at32ap/pdc.c | |||
@@ -35,7 +35,6 @@ static int __init pdc_probe(struct platform_device *pdev) | |||
35 | } | 35 | } |
36 | 36 | ||
37 | static struct platform_driver pdc_driver = { | 37 | static struct platform_driver pdc_driver = { |
38 | .probe = pdc_probe, | ||
39 | .driver = { | 38 | .driver = { |
40 | .name = "pdc", | 39 | .name = "pdc", |
41 | }, | 40 | }, |
@@ -43,6 +42,6 @@ static struct platform_driver pdc_driver = { | |||
43 | 42 | ||
44 | static int __init pdc_init(void) | 43 | static int __init pdc_init(void) |
45 | { | 44 | { |
46 | return platform_driver_register(&pdc_driver); | 45 | return platform_driver_probe(&pdc_driver, pdc_probe); |
47 | } | 46 | } |
48 | arch_initcall(pdc_init); | 47 | arch_initcall(pdc_init); |
diff --git a/arch/avr32/mach-at32ap/pio.c b/arch/avr32/mach-at32ap/pio.c index 405ee6bad4ce..ed81a8bcb22d 100644 --- a/arch/avr32/mach-at32ap/pio.c +++ b/arch/avr32/mach-at32ap/pio.c | |||
@@ -50,35 +50,48 @@ static struct pio_device *gpio_to_pio(unsigned int gpio) | |||
50 | } | 50 | } |
51 | 51 | ||
52 | /* Pin multiplexing API */ | 52 | /* Pin multiplexing API */ |
53 | static DEFINE_SPINLOCK(pio_lock); | ||
53 | 54 | ||
54 | void __init at32_select_periph(unsigned int pin, unsigned int periph, | 55 | void __init at32_select_periph(unsigned int port, u32 pin_mask, |
55 | unsigned long flags) | 56 | unsigned int periph, unsigned long flags) |
56 | { | 57 | { |
57 | struct pio_device *pio; | 58 | struct pio_device *pio; |
58 | unsigned int pin_index = pin & 0x1f; | ||
59 | u32 mask = 1 << pin_index; | ||
60 | 59 | ||
61 | pio = gpio_to_pio(pin); | 60 | /* assign and verify pio */ |
61 | pio = gpio_to_pio(port); | ||
62 | if (unlikely(!pio)) { | 62 | if (unlikely(!pio)) { |
63 | printk("pio: invalid pin %u\n", pin); | 63 | printk(KERN_WARNING "pio: invalid port %u\n", port); |
64 | goto fail; | 64 | goto fail; |
65 | } | 65 | } |
66 | 66 | ||
67 | if (unlikely(test_and_set_bit(pin_index, &pio->pinmux_mask) | 67 | /* Test if any of the requested pins is already muxed */ |
68 | || gpiochip_is_requested(&pio->chip, pin_index))) { | 68 | spin_lock(&pio_lock); |
69 | printk("%s: pin %u is busy\n", pio->name, pin_index); | 69 | if (unlikely(pio->pinmux_mask & pin_mask)) { |
70 | printk(KERN_WARNING "%s: pin(s) busy (requested 0x%x, busy 0x%x)\n", | ||
71 | pio->name, pin_mask, pio->pinmux_mask & pin_mask); | ||
72 | spin_unlock(&pio_lock); | ||
70 | goto fail; | 73 | goto fail; |
71 | } | 74 | } |
72 | 75 | ||
73 | pio_writel(pio, PUER, mask); | 76 | pio->pinmux_mask |= pin_mask; |
77 | |||
78 | /* enable pull ups */ | ||
79 | pio_writel(pio, PUER, pin_mask); | ||
80 | |||
81 | /* select either peripheral A or B */ | ||
74 | if (periph) | 82 | if (periph) |
75 | pio_writel(pio, BSR, mask); | 83 | pio_writel(pio, BSR, pin_mask); |
76 | else | 84 | else |
77 | pio_writel(pio, ASR, mask); | 85 | pio_writel(pio, ASR, pin_mask); |
86 | |||
87 | /* enable peripheral control */ | ||
88 | pio_writel(pio, PDR, pin_mask); | ||
78 | 89 | ||
79 | pio_writel(pio, PDR, mask); | 90 | /* Disable pull ups if not requested. */ |
80 | if (!(flags & AT32_GPIOF_PULLUP)) | 91 | if (!(flags & AT32_GPIOF_PULLUP)) |
81 | pio_writel(pio, PUDR, mask); | 92 | pio_writel(pio, PUDR, pin_mask); |
93 | |||
94 | spin_unlock(&pio_lock); | ||
82 | 95 | ||
83 | return; | 96 | return; |
84 | 97 | ||
@@ -134,6 +147,25 @@ fail: | |||
134 | dump_stack(); | 147 | dump_stack(); |
135 | } | 148 | } |
136 | 149 | ||
150 | /* | ||
151 | * Undo a previous pin reservation. Will not affect the hardware | ||
152 | * configuration. | ||
153 | */ | ||
154 | void at32_deselect_pin(unsigned int pin) | ||
155 | { | ||
156 | struct pio_device *pio; | ||
157 | unsigned int pin_index = pin & 0x1f; | ||
158 | |||
159 | pio = gpio_to_pio(pin); | ||
160 | if (unlikely(!pio)) { | ||
161 | printk("pio: invalid pin %u\n", pin); | ||
162 | dump_stack(); | ||
163 | return; | ||
164 | } | ||
165 | |||
166 | clear_bit(pin_index, &pio->pinmux_mask); | ||
167 | } | ||
168 | |||
137 | /* Reserve a pin, preventing anyone else from changing its configuration. */ | 169 | /* Reserve a pin, preventing anyone else from changing its configuration. */ |
138 | void __init at32_reserve_pin(unsigned int pin) | 170 | void __init at32_reserve_pin(unsigned int pin) |
139 | { | 171 | { |
@@ -382,7 +414,6 @@ static int __init pio_probe(struct platform_device *pdev) | |||
382 | } | 414 | } |
383 | 415 | ||
384 | static struct platform_driver pio_driver = { | 416 | static struct platform_driver pio_driver = { |
385 | .probe = pio_probe, | ||
386 | .driver = { | 417 | .driver = { |
387 | .name = "pio", | 418 | .name = "pio", |
388 | }, | 419 | }, |
@@ -390,7 +421,7 @@ static struct platform_driver pio_driver = { | |||
390 | 421 | ||
391 | static int __init pio_init(void) | 422 | static int __init pio_init(void) |
392 | { | 423 | { |
393 | return platform_driver_register(&pio_driver); | 424 | return platform_driver_probe(&pio_driver, pio_probe); |
394 | } | 425 | } |
395 | postcore_initcall(pio_init); | 426 | postcore_initcall(pio_init); |
396 | 427 | ||
diff --git a/arch/avr32/oprofile/Makefile b/arch/avr32/oprofile/Makefile index 1fe81c3c1e86..e0eb520e0287 100644 --- a/arch/avr32/oprofile/Makefile +++ b/arch/avr32/oprofile/Makefile | |||
@@ -5,4 +5,4 @@ oprofile-y := $(addprefix ../../../drivers/oprofile/, \ | |||
5 | event_buffer.o oprofile_files.o \ | 5 | event_buffer.o oprofile_files.o \ |
6 | oprofilefs.o oprofile_stats.o \ | 6 | oprofilefs.o oprofile_stats.o \ |
7 | timer_int.o) | 7 | timer_int.o) |
8 | oprofile-y += op_model_avr32.o | 8 | oprofile-y += op_model_avr32.o backtrace.o |
diff --git a/arch/avr32/oprofile/backtrace.c b/arch/avr32/oprofile/backtrace.c new file mode 100644 index 000000000000..75d9ad6f99cf --- /dev/null +++ b/arch/avr32/oprofile/backtrace.c | |||
@@ -0,0 +1,81 @@ | |||
1 | /* | ||
2 | * AVR32 specific backtracing code for oprofile | ||
3 | * | ||
4 | * Copyright 2008 Weinmann GmbH | ||
5 | * | ||
6 | * Author: Nikolaus Voss <n.voss@weinmann.de> | ||
7 | * | ||
8 | * Based on i386 oprofile backtrace code by John Levon and David Smith | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | * | ||
14 | */ | ||
15 | |||
16 | #include <linux/oprofile.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/uaccess.h> | ||
19 | |||
20 | /* The first two words of each frame on the stack look like this if we have | ||
21 | * frame pointers */ | ||
22 | struct frame_head { | ||
23 | unsigned long lr; | ||
24 | struct frame_head *fp; | ||
25 | }; | ||
26 | |||
27 | /* copied from arch/avr32/kernel/process.c */ | ||
28 | static inline int valid_stack_ptr(struct thread_info *tinfo, unsigned long p) | ||
29 | { | ||
30 | return (p > (unsigned long)tinfo) | ||
31 | && (p < (unsigned long)tinfo + THREAD_SIZE - 3); | ||
32 | } | ||
33 | |||
34 | /* copied from arch/x86/oprofile/backtrace.c */ | ||
35 | static struct frame_head *dump_user_backtrace(struct frame_head *head) | ||
36 | { | ||
37 | struct frame_head bufhead[2]; | ||
38 | |||
39 | /* Also check accessibility of one struct frame_head beyond */ | ||
40 | if (!access_ok(VERIFY_READ, head, sizeof(bufhead))) | ||
41 | return NULL; | ||
42 | if (__copy_from_user_inatomic(bufhead, head, sizeof(bufhead))) | ||
43 | return NULL; | ||
44 | |||
45 | oprofile_add_trace(bufhead[0].lr); | ||
46 | |||
47 | /* frame pointers should strictly progress back up the stack | ||
48 | * (towards higher addresses) */ | ||
49 | if (bufhead[0].fp <= head) | ||
50 | return NULL; | ||
51 | |||
52 | return bufhead[0].fp; | ||
53 | } | ||
54 | |||
55 | void avr32_backtrace(struct pt_regs * const regs, unsigned int depth) | ||
56 | { | ||
57 | /* Get first frame pointer */ | ||
58 | struct frame_head *head = (struct frame_head *)(regs->r7); | ||
59 | |||
60 | if (!user_mode(regs)) { | ||
61 | #ifdef CONFIG_FRAME_POINTER | ||
62 | /* | ||
63 | * Traverse the kernel stack from frame to frame up to | ||
64 | * "depth" steps. | ||
65 | */ | ||
66 | while (depth-- && valid_stack_ptr(task_thread_info(current), | ||
67 | (unsigned long)head)) { | ||
68 | oprofile_add_trace(head->lr); | ||
69 | if (head->fp <= head) | ||
70 | break; | ||
71 | head = head->fp; | ||
72 | } | ||
73 | #endif | ||
74 | } else { | ||
75 | /* Assume we have frame pointers in user mode process */ | ||
76 | while (depth-- && head) | ||
77 | head = dump_user_backtrace(head); | ||
78 | } | ||
79 | } | ||
80 | |||
81 | |||
diff --git a/arch/avr32/oprofile/op_model_avr32.c b/arch/avr32/oprofile/op_model_avr32.c index df42325c7f81..a3e9b3c4845a 100644 --- a/arch/avr32/oprofile/op_model_avr32.c +++ b/arch/avr32/oprofile/op_model_avr32.c | |||
@@ -22,6 +22,8 @@ | |||
22 | #define AVR32_PERFCTR_IRQ_GROUP 0 | 22 | #define AVR32_PERFCTR_IRQ_GROUP 0 |
23 | #define AVR32_PERFCTR_IRQ_LINE 1 | 23 | #define AVR32_PERFCTR_IRQ_LINE 1 |
24 | 24 | ||
25 | void avr32_backtrace(struct pt_regs * const regs, unsigned int depth); | ||
26 | |||
25 | enum { PCCNT, PCNT0, PCNT1, NR_counter }; | 27 | enum { PCCNT, PCNT0, PCNT1, NR_counter }; |
26 | 28 | ||
27 | struct avr32_perf_counter { | 29 | struct avr32_perf_counter { |
@@ -223,6 +225,8 @@ int __init oprofile_arch_init(struct oprofile_operations *ops) | |||
223 | memcpy(ops, &avr32_perf_counter_ops, | 225 | memcpy(ops, &avr32_perf_counter_ops, |
224 | sizeof(struct oprofile_operations)); | 226 | sizeof(struct oprofile_operations)); |
225 | 227 | ||
228 | ops->backtrace = avr32_backtrace; | ||
229 | |||
226 | printk(KERN_INFO "oprofile: using AVR32 performance monitoring.\n"); | 230 | printk(KERN_INFO "oprofile: using AVR32 performance monitoring.\n"); |
227 | 231 | ||
228 | return 0; | 232 | return 0; |
diff --git a/arch/sparc/Kconfig b/arch/sparc/Kconfig index a214002114ed..97671dac12a6 100644 --- a/arch/sparc/Kconfig +++ b/arch/sparc/Kconfig | |||
@@ -20,6 +20,11 @@ config GENERIC_ISA_DMA | |||
20 | bool | 20 | bool |
21 | default y | 21 | default y |
22 | 22 | ||
23 | config GENERIC_GPIO | ||
24 | bool | ||
25 | help | ||
26 | Generic GPIO API support | ||
27 | |||
23 | config ARCH_NO_VIRT_TO_BUS | 28 | config ARCH_NO_VIRT_TO_BUS |
24 | def_bool y | 29 | def_bool y |
25 | 30 | ||
@@ -69,6 +74,9 @@ config SPARC | |||
69 | select HAVE_OPROFILE | 74 | select HAVE_OPROFILE |
70 | select HAVE_ARCH_KGDB if !SMP | 75 | select HAVE_ARCH_KGDB if !SMP |
71 | select HAVE_ARCH_TRACEHOOK | 76 | select HAVE_ARCH_TRACEHOOK |
77 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
78 | select RTC_CLASS | ||
79 | select RTC_DRV_M48T59 | ||
72 | 80 | ||
73 | # Identify this as a Sparc32 build | 81 | # Identify this as a Sparc32 build |
74 | config SPARC32 | 82 | config SPARC32 |
@@ -204,17 +212,6 @@ config SUN_PM | |||
204 | Enable power management and CPU standby features on supported | 212 | Enable power management and CPU standby features on supported |
205 | SPARC platforms. | 213 | SPARC platforms. |
206 | 214 | ||
207 | config SUN4 | ||
208 | bool "Support for SUN4 machines (disables SUN4[CDM] support)" | ||
209 | depends on !SMP | ||
210 | default n | ||
211 | help | ||
212 | Say Y here if, and only if, your machine is a sun4. Note that | ||
213 | a kernel compiled with this option will run only on sun4. | ||
214 | (And the current version will probably work only on sun4/330.) | ||
215 | |||
216 | if !SUN4 | ||
217 | |||
218 | config PCI | 215 | config PCI |
219 | bool "Support for PCI and PS/2 keyboard/mouse" | 216 | bool "Support for PCI and PS/2 keyboard/mouse" |
220 | help | 217 | help |
@@ -227,11 +224,6 @@ config PCI_SYSCALL | |||
227 | 224 | ||
228 | source "drivers/pci/Kconfig" | 225 | source "drivers/pci/Kconfig" |
229 | 226 | ||
230 | endif | ||
231 | |||
232 | config NO_DMA | ||
233 | def_bool !PCI | ||
234 | |||
235 | config SUN_OPENPROMFS | 227 | config SUN_OPENPROMFS |
236 | tristate "Openprom tree appears in /proc/openprom" | 228 | tristate "Openprom tree appears in /proc/openprom" |
237 | help | 229 | help |
@@ -263,9 +255,7 @@ source "net/Kconfig" | |||
263 | 255 | ||
264 | source "drivers/Kconfig" | 256 | source "drivers/Kconfig" |
265 | 257 | ||
266 | if !SUN4 | ||
267 | source "drivers/sbus/char/Kconfig" | 258 | source "drivers/sbus/char/Kconfig" |
268 | endif | ||
269 | 259 | ||
270 | # This one must be before the filesystem configs. -DaveM | 260 | # This one must be before the filesystem configs. -DaveM |
271 | 261 | ||
diff --git a/arch/sparc/include/asm/Kbuild b/arch/sparc/include/asm/Kbuild index a5f0ce734ff7..2ba7183bc1f0 100644 --- a/arch/sparc/include/asm/Kbuild +++ b/arch/sparc/include/asm/Kbuild | |||
@@ -22,7 +22,6 @@ header-y += unistd_64.h | |||
22 | 22 | ||
23 | header-y += apc.h | 23 | header-y += apc.h |
24 | header-y += asi.h | 24 | header-y += asi.h |
25 | header-y += bpp.h | ||
26 | header-y += display7seg.h | 25 | header-y += display7seg.h |
27 | header-y += envctrl.h | 26 | header-y += envctrl.h |
28 | header-y += fbio.h | 27 | header-y += fbio.h |
@@ -41,5 +40,4 @@ header-y += reg_64.h | |||
41 | header-y += traps.h | 40 | header-y += traps.h |
42 | header-y += uctx.h | 41 | header-y += uctx.h |
43 | header-y += utrap.h | 42 | header-y += utrap.h |
44 | header-y += vfc_ioctls.h | ||
45 | header-y += watchdog.h | 43 | header-y += watchdog.h |
diff --git a/arch/sparc/include/asm/asmmacro.h b/arch/sparc/include/asm/asmmacro.h index a619a4d97aae..a995bf8aba3f 100644 --- a/arch/sparc/include/asm/asmmacro.h +++ b/arch/sparc/include/asm/asmmacro.h | |||
@@ -34,12 +34,7 @@ | |||
34 | /* sun4 probably wants half word accesses to ASI_SEGMAP, while sun4c+ | 34 | /* sun4 probably wants half word accesses to ASI_SEGMAP, while sun4c+ |
35 | likes byte accesses. These are to avoid ifdef mania. */ | 35 | likes byte accesses. These are to avoid ifdef mania. */ |
36 | 36 | ||
37 | #ifdef CONFIG_SUN4 | ||
38 | #define lduXa lduha | ||
39 | #define stXa stha | ||
40 | #else | ||
41 | #define lduXa lduba | 37 | #define lduXa lduba |
42 | #define stXa stba | 38 | #define stXa stba |
43 | #endif | ||
44 | 39 | ||
45 | #endif /* !(_SPARC_ASMMACRO_H) */ | 40 | #endif /* !(_SPARC_ASMMACRO_H) */ |
diff --git a/arch/sparc/include/asm/bpp.h b/arch/sparc/include/asm/bpp.h deleted file mode 100644 index 31f515e499a7..000000000000 --- a/arch/sparc/include/asm/bpp.h +++ /dev/null | |||
@@ -1,73 +0,0 @@ | |||
1 | #ifndef _SPARC_BPP_H | ||
2 | #define _SPARC_BPP_H | ||
3 | |||
4 | /* | ||
5 | * Copyright (c) 1995 Picture Elements | ||
6 | * Stephen Williams | ||
7 | * Gus Baldauf | ||
8 | * | ||
9 | * Linux/SPARC port by Peter Zaitcev. | ||
10 | * Integration into SPARC tree by Tom Dyas. | ||
11 | */ | ||
12 | |||
13 | #include <linux/ioctl.h> | ||
14 | |||
15 | /* | ||
16 | * This is a driver that supports IEEE Std 1284-1994 communications | ||
17 | * with compliant or compatible devices. It will use whatever features | ||
18 | * the device supports, prefering those that are typically faster. | ||
19 | * | ||
20 | * When the device is opened, it is left in COMPATIBILITY mode, and | ||
21 | * writes work like any printer device. The driver only attempt to | ||
22 | * negotiate 1284 modes when needed so that plugs can be pulled, | ||
23 | * switch boxes switched, etc., without disrupting things. It will | ||
24 | * also leave the device in compatibility mode when closed. | ||
25 | */ | ||
26 | |||
27 | |||
28 | |||
29 | /* | ||
30 | * This driver also supplies ioctls to manually manipulate the | ||
31 | * pins. This is great for testing devices, or writing code to deal | ||
32 | * with bizzarro-mode of the ACME Special TurboThingy Plus. | ||
33 | * | ||
34 | * NOTE: These ioctl currently do not interact well with | ||
35 | * read/write. Caveat emptor. | ||
36 | * | ||
37 | * PUT_PINS allows us to assign the sense of all the pins, including | ||
38 | * the data pins if being driven by the host. The GET_PINS returns the | ||
39 | * pins that the peripheral drives, including data if appropriate. | ||
40 | */ | ||
41 | |||
42 | # define BPP_PUT_PINS _IOW('B', 1, int) | ||
43 | # define BPP_GET_PINS _IOR('B', 2, char) /* that's bogus - should've been _IO */ | ||
44 | # define BPP_PUT_DATA _IOW('B', 3, int) | ||
45 | # define BPP_GET_DATA _IOR('B', 4, char) /* ditto */ | ||
46 | |||
47 | /* | ||
48 | * Set the data bus to input mode. Disengage the data bin driver and | ||
49 | * be prepared to read values from the peripheral. If the arg is 0, | ||
50 | * then revert the bus to output mode. | ||
51 | */ | ||
52 | # define BPP_SET_INPUT _IOW('B', 5, int) | ||
53 | |||
54 | /* | ||
55 | * These bits apply to the PUT operation... | ||
56 | */ | ||
57 | # define BPP_PP_nStrobe 0x0001 | ||
58 | # define BPP_PP_nAutoFd 0x0002 | ||
59 | # define BPP_PP_nInit 0x0004 | ||
60 | # define BPP_PP_nSelectIn 0x0008 | ||
61 | |||
62 | /* | ||
63 | * These apply to the GET operation, which also reads the current value | ||
64 | * of the previously put values. A bit mask of these will be returned | ||
65 | * as a bit mask in the return code of the ioctl(). | ||
66 | */ | ||
67 | # define BPP_GP_nAck 0x0100 | ||
68 | # define BPP_GP_Busy 0x0200 | ||
69 | # define BPP_GP_PError 0x0400 | ||
70 | # define BPP_GP_Select 0x0800 | ||
71 | # define BPP_GP_nFault 0x1000 | ||
72 | |||
73 | #endif | ||
diff --git a/arch/sparc/include/asm/bugs.h b/arch/sparc/include/asm/bugs.h index e179bc12f64a..61d86bbbe2b2 100644 --- a/arch/sparc/include/asm/bugs.h +++ b/arch/sparc/include/asm/bugs.h | |||
@@ -7,10 +7,6 @@ | |||
7 | #include <asm/cpudata.h> | 7 | #include <asm/cpudata.h> |
8 | #endif | 8 | #endif |
9 | 9 | ||
10 | #ifdef CONFIG_SPARC64 | ||
11 | #include <asm/sstate.h> | ||
12 | #endif | ||
13 | |||
14 | extern unsigned long loops_per_jiffy; | 10 | extern unsigned long loops_per_jiffy; |
15 | 11 | ||
16 | static void __init check_bugs(void) | 12 | static void __init check_bugs(void) |
@@ -18,7 +14,4 @@ static void __init check_bugs(void) | |||
18 | #if defined(CONFIG_SPARC32) && !defined(CONFIG_SMP) | 14 | #if defined(CONFIG_SPARC32) && !defined(CONFIG_SMP) |
19 | cpu_data(0).udelay_val = loops_per_jiffy; | 15 | cpu_data(0).udelay_val = loops_per_jiffy; |
20 | #endif | 16 | #endif |
21 | #ifdef CONFIG_SPARC64 | ||
22 | sstate_running(); | ||
23 | #endif | ||
24 | } | 17 | } |
diff --git a/arch/sparc/include/asm/cpudata_64.h b/arch/sparc/include/asm/cpudata_64.h index 532975ecfe10..7da7c13d23c4 100644 --- a/arch/sparc/include/asm/cpudata_64.h +++ b/arch/sparc/include/asm/cpudata_64.h | |||
@@ -86,7 +86,6 @@ extern struct trap_per_cpu trap_block[NR_CPUS]; | |||
86 | extern void init_cur_cpu_trap(struct thread_info *); | 86 | extern void init_cur_cpu_trap(struct thread_info *); |
87 | extern void setup_tba(void); | 87 | extern void setup_tba(void); |
88 | extern int ncpus_probed; | 88 | extern int ncpus_probed; |
89 | extern void __init cpu_probe(void); | ||
90 | extern const struct seq_operations cpuinfo_op; | 89 | extern const struct seq_operations cpuinfo_op; |
91 | 90 | ||
92 | extern unsigned long real_hard_smp_processor_id(void); | 91 | extern unsigned long real_hard_smp_processor_id(void); |
diff --git a/arch/sparc/include/asm/dma-mapping_32.h b/arch/sparc/include/asm/dma-mapping_32.h index f3a641e6b2c8..8a57ea0573e6 100644 --- a/arch/sparc/include/asm/dma-mapping_32.h +++ b/arch/sparc/include/asm/dma-mapping_32.h | |||
@@ -1,11 +1,60 @@ | |||
1 | #ifndef _ASM_SPARC_DMA_MAPPING_H | 1 | #ifndef _ASM_SPARC_DMA_MAPPING_H |
2 | #define _ASM_SPARC_DMA_MAPPING_H | 2 | #define _ASM_SPARC_DMA_MAPPING_H |
3 | 3 | ||
4 | #include <linux/types.h> | ||
4 | 5 | ||
5 | #ifdef CONFIG_PCI | 6 | struct device; |
6 | #include <asm-generic/dma-mapping.h> | 7 | struct scatterlist; |
7 | #else | 8 | struct page; |
8 | #include <asm-generic/dma-mapping-broken.h> | 9 | |
9 | #endif /* PCI */ | 10 | #define DMA_ERROR_CODE (~(dma_addr_t)0x0) |
11 | |||
12 | extern int dma_supported(struct device *dev, u64 mask); | ||
13 | extern int dma_set_mask(struct device *dev, u64 dma_mask); | ||
14 | extern void *dma_alloc_coherent(struct device *dev, size_t size, | ||
15 | dma_addr_t *dma_handle, gfp_t flag); | ||
16 | extern void dma_free_coherent(struct device *dev, size_t size, | ||
17 | void *cpu_addr, dma_addr_t dma_handle); | ||
18 | extern dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | ||
19 | size_t size, | ||
20 | enum dma_data_direction direction); | ||
21 | extern void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, | ||
22 | size_t size, | ||
23 | enum dma_data_direction direction); | ||
24 | extern dma_addr_t dma_map_page(struct device *dev, struct page *page, | ||
25 | unsigned long offset, size_t size, | ||
26 | enum dma_data_direction direction); | ||
27 | extern void dma_unmap_page(struct device *dev, dma_addr_t dma_address, | ||
28 | size_t size, enum dma_data_direction direction); | ||
29 | extern int dma_map_sg(struct device *dev, struct scatterlist *sg, | ||
30 | int nents, enum dma_data_direction direction); | ||
31 | extern void dma_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
32 | int nents, enum dma_data_direction direction); | ||
33 | extern void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
34 | size_t size, | ||
35 | enum dma_data_direction direction); | ||
36 | extern void dma_sync_single_for_device(struct device *dev, | ||
37 | dma_addr_t dma_handle, | ||
38 | size_t size, | ||
39 | enum dma_data_direction direction); | ||
40 | extern void dma_sync_single_range_for_cpu(struct device *dev, | ||
41 | dma_addr_t dma_handle, | ||
42 | unsigned long offset, | ||
43 | size_t size, | ||
44 | enum dma_data_direction direction); | ||
45 | extern void dma_sync_single_range_for_device(struct device *dev, | ||
46 | dma_addr_t dma_handle, | ||
47 | unsigned long offset, size_t size, | ||
48 | enum dma_data_direction direction); | ||
49 | extern void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | ||
50 | int nelems, enum dma_data_direction direction); | ||
51 | extern void dma_sync_sg_for_device(struct device *dev, | ||
52 | struct scatterlist *sg, int nelems, | ||
53 | enum dma_data_direction direction); | ||
54 | extern int dma_mapping_error(struct device *dev, dma_addr_t dma_addr); | ||
55 | extern int dma_get_cache_alignment(void); | ||
56 | |||
57 | #define dma_alloc_noncoherent dma_alloc_coherent | ||
58 | #define dma_free_noncoherent dma_free_coherent | ||
10 | 59 | ||
11 | #endif /* _ASM_SPARC_DMA_MAPPING_H */ | 60 | #endif /* _ASM_SPARC_DMA_MAPPING_H */ |
diff --git a/arch/sparc/include/asm/dma.h b/arch/sparc/include/asm/dma.h index aa1d90ac04c5..b554927bbaf6 100644 --- a/arch/sparc/include/asm/dma.h +++ b/arch/sparc/include/asm/dma.h | |||
@@ -1,8 +1,139 @@ | |||
1 | #ifndef ___ASM_SPARC_DMA_H | 1 | #ifndef _ASM_SPARC_DMA_H |
2 | #define ___ASM_SPARC_DMA_H | 2 | #define _ASM_SPARC_DMA_H |
3 | #if defined(__sparc__) && defined(__arch64__) | 3 | |
4 | #include <asm/dma_64.h> | 4 | /* These are irrelevant for Sparc DMA, but we leave it in so that |
5 | * things can compile. | ||
6 | */ | ||
7 | #define MAX_DMA_CHANNELS 8 | ||
8 | #define DMA_MODE_READ 1 | ||
9 | #define DMA_MODE_WRITE 2 | ||
10 | #define MAX_DMA_ADDRESS (~0UL) | ||
11 | |||
12 | /* Useful constants */ | ||
13 | #define SIZE_16MB (16*1024*1024) | ||
14 | #define SIZE_64K (64*1024) | ||
15 | |||
16 | /* SBUS DMA controller reg offsets */ | ||
17 | #define DMA_CSR 0x00UL /* rw DMA control/status register 0x00 */ | ||
18 | #define DMA_ADDR 0x04UL /* rw DMA transfer address register 0x04 */ | ||
19 | #define DMA_COUNT 0x08UL /* rw DMA transfer count register 0x08 */ | ||
20 | #define DMA_TEST 0x0cUL /* rw DMA test/debug register 0x0c */ | ||
21 | |||
22 | /* Fields in the cond_reg register */ | ||
23 | /* First, the version identification bits */ | ||
24 | #define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */ | ||
25 | #define DMA_VERS0 0x00000000 /* Sunray DMA version */ | ||
26 | #define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */ | ||
27 | #define DMA_VERS1 0x80000000 /* DMA rev 1 */ | ||
28 | #define DMA_VERS2 0xa0000000 /* DMA rev 2 */ | ||
29 | #define DMA_VERHME 0xb0000000 /* DMA hme gate array */ | ||
30 | #define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */ | ||
31 | |||
32 | #define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */ | ||
33 | #define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */ | ||
34 | #define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */ | ||
35 | #define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */ | ||
36 | #define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */ | ||
37 | #define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */ | ||
38 | #define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */ | ||
39 | #define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */ | ||
40 | #define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */ | ||
41 | #define DMA_ST_WRITE 0x00000100 /* write from device to memory */ | ||
42 | #define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */ | ||
43 | #define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */ | ||
44 | #define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */ | ||
45 | #define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */ | ||
46 | #define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */ | ||
47 | #define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */ | ||
48 | #define DMA_TERM_CNTR 0x00004000 /* Terminal counter */ | ||
49 | #define DMA_SCSI_SBUS64 0x00008000 /* HME: Enable 64-bit SBUS mode. */ | ||
50 | #define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */ | ||
51 | #define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */ | ||
52 | #define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */ | ||
53 | #define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */ | ||
54 | #define DMA_E_BURSTS 0x000c0000 /* ENET: SBUS r/w burst mask */ | ||
55 | #define DMA_E_BURST32 0x00040000 /* ENET: SBUS 32 byte r/w burst */ | ||
56 | #define DMA_E_BURST16 0x00000000 /* ENET: SBUS 16 byte r/w burst */ | ||
57 | #define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */ | ||
58 | #define DMA_BRST64 0x000c0000 /* SCSI: 64byte bursts (HME on UltraSparc only) */ | ||
59 | #define DMA_BRST32 0x00040000 /* SCSI: 32byte bursts */ | ||
60 | #define DMA_BRST16 0x00000000 /* SCSI: 16byte bursts */ | ||
61 | #define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */ | ||
62 | #define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */ | ||
63 | #define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */ | ||
64 | #define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */ | ||
65 | #define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */ | ||
66 | #define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */ | ||
67 | #define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */ | ||
68 | #define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */ | ||
69 | #define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */ | ||
70 | #define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */ | ||
71 | #define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */ | ||
72 | #define DMA_RESET_FAS366 0x08000000 /* HME: Assert RESET to FAS366 */ | ||
73 | |||
74 | /* Values describing the burst-size property from the PROM */ | ||
75 | #define DMA_BURST1 0x01 | ||
76 | #define DMA_BURST2 0x02 | ||
77 | #define DMA_BURST4 0x04 | ||
78 | #define DMA_BURST8 0x08 | ||
79 | #define DMA_BURST16 0x10 | ||
80 | #define DMA_BURST32 0x20 | ||
81 | #define DMA_BURST64 0x40 | ||
82 | #define DMA_BURSTBITS 0x7f | ||
83 | |||
84 | /* From PCI */ | ||
85 | |||
86 | #ifdef CONFIG_PCI | ||
87 | extern int isa_dma_bridge_buggy; | ||
5 | #else | 88 | #else |
6 | #include <asm/dma_32.h> | 89 | #define isa_dma_bridge_buggy (0) |
7 | #endif | 90 | #endif |
91 | |||
92 | #ifdef CONFIG_SPARC32 | ||
93 | |||
94 | /* Routines for data transfer buffers. */ | ||
95 | BTFIXUPDEF_CALL(char *, mmu_lockarea, char *, unsigned long) | ||
96 | BTFIXUPDEF_CALL(void, mmu_unlockarea, char *, unsigned long) | ||
97 | |||
98 | #define mmu_lockarea(vaddr,len) BTFIXUP_CALL(mmu_lockarea)(vaddr,len) | ||
99 | #define mmu_unlockarea(vaddr,len) BTFIXUP_CALL(mmu_unlockarea)(vaddr,len) | ||
100 | |||
101 | struct page; | ||
102 | struct device; | ||
103 | struct scatterlist; | ||
104 | |||
105 | /* These are implementations for sbus_map_sg/sbus_unmap_sg... collapse later */ | ||
106 | BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, struct device *, char *, unsigned long) | ||
107 | BTFIXUPDEF_CALL(void, mmu_get_scsi_sgl, struct device *, struct scatterlist *, int) | ||
108 | BTFIXUPDEF_CALL(void, mmu_release_scsi_one, struct device *, __u32, unsigned long) | ||
109 | BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct device *, struct scatterlist *, int) | ||
110 | |||
111 | #define mmu_get_scsi_one(dev,vaddr,len) BTFIXUP_CALL(mmu_get_scsi_one)(dev,vaddr,len) | ||
112 | #define mmu_get_scsi_sgl(dev,sg,sz) BTFIXUP_CALL(mmu_get_scsi_sgl)(dev,sg,sz) | ||
113 | #define mmu_release_scsi_one(dev,vaddr,len) BTFIXUP_CALL(mmu_release_scsi_one)(dev,vaddr,len) | ||
114 | #define mmu_release_scsi_sgl(dev,sg,sz) BTFIXUP_CALL(mmu_release_scsi_sgl)(dev,sg,sz) | ||
115 | |||
116 | /* | ||
117 | * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep. | ||
118 | * | ||
119 | * The mmu_map_dma_area establishes two mappings in one go. | ||
120 | * These mappings point to pages normally mapped at 'va' (linear address). | ||
121 | * First mapping is for CPU visible address at 'a', uncached. | ||
122 | * This is an alias, but it works because it is an uncached mapping. | ||
123 | * Second mapping is for device visible address, or "bus" address. | ||
124 | * The bus address is returned at '*pba'. | ||
125 | * | ||
126 | * These functions seem distinct, but are hard to split. On sun4c, | ||
127 | * at least for now, 'a' is equal to bus address, and retured in *pba. | ||
128 | * On sun4m, page attributes depend on the CPU type, so we have to | ||
129 | * know if we are mapping RAM or I/O, so it has to be an additional argument | ||
130 | * to a separate mapping function for CPU visible mappings. | ||
131 | */ | ||
132 | BTFIXUPDEF_CALL(int, mmu_map_dma_area, struct device *, dma_addr_t *, unsigned long, unsigned long, int len) | ||
133 | BTFIXUPDEF_CALL(void, mmu_unmap_dma_area, struct device *, unsigned long busa, int len) | ||
134 | |||
135 | #define mmu_map_dma_area(dev,pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(dev,pba,va,a,len) | ||
136 | #define mmu_unmap_dma_area(dev,ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(dev,ba,len) | ||
8 | #endif | 137 | #endif |
138 | |||
139 | #endif /* !(_ASM_SPARC_DMA_H) */ | ||
diff --git a/arch/sparc/include/asm/dma_32.h b/arch/sparc/include/asm/dma_32.h deleted file mode 100644 index cf7189c0079b..000000000000 --- a/arch/sparc/include/asm/dma_32.h +++ /dev/null | |||
@@ -1,288 +0,0 @@ | |||
1 | /* include/asm/dma.h | ||
2 | * | ||
3 | * Copyright 1995 (C) David S. Miller (davem@davemloft.net) | ||
4 | */ | ||
5 | |||
6 | #ifndef _ASM_SPARC_DMA_H | ||
7 | #define _ASM_SPARC_DMA_H | ||
8 | |||
9 | #include <linux/kernel.h> | ||
10 | #include <linux/types.h> | ||
11 | |||
12 | #include <asm/vac-ops.h> /* for invalidate's, etc. */ | ||
13 | #include <asm/sbus.h> | ||
14 | #include <asm/delay.h> | ||
15 | #include <asm/oplib.h> | ||
16 | #include <asm/system.h> | ||
17 | #include <asm/io.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | |||
20 | struct page; | ||
21 | extern spinlock_t dma_spin_lock; | ||
22 | |||
23 | static inline unsigned long claim_dma_lock(void) | ||
24 | { | ||
25 | unsigned long flags; | ||
26 | spin_lock_irqsave(&dma_spin_lock, flags); | ||
27 | return flags; | ||
28 | } | ||
29 | |||
30 | static inline void release_dma_lock(unsigned long flags) | ||
31 | { | ||
32 | spin_unlock_irqrestore(&dma_spin_lock, flags); | ||
33 | } | ||
34 | |||
35 | /* These are irrelevant for Sparc DMA, but we leave it in so that | ||
36 | * things can compile. | ||
37 | */ | ||
38 | #define MAX_DMA_CHANNELS 8 | ||
39 | #define MAX_DMA_ADDRESS (~0UL) | ||
40 | #define DMA_MODE_READ 1 | ||
41 | #define DMA_MODE_WRITE 2 | ||
42 | |||
43 | /* Useful constants */ | ||
44 | #define SIZE_16MB (16*1024*1024) | ||
45 | #define SIZE_64K (64*1024) | ||
46 | |||
47 | /* SBUS DMA controller reg offsets */ | ||
48 | #define DMA_CSR 0x00UL /* rw DMA control/status register 0x00 */ | ||
49 | #define DMA_ADDR 0x04UL /* rw DMA transfer address register 0x04 */ | ||
50 | #define DMA_COUNT 0x08UL /* rw DMA transfer count register 0x08 */ | ||
51 | #define DMA_TEST 0x0cUL /* rw DMA test/debug register 0x0c */ | ||
52 | |||
53 | /* DVMA chip revisions */ | ||
54 | enum dvma_rev { | ||
55 | dvmarev0, | ||
56 | dvmaesc1, | ||
57 | dvmarev1, | ||
58 | dvmarev2, | ||
59 | dvmarev3, | ||
60 | dvmarevplus, | ||
61 | dvmahme | ||
62 | }; | ||
63 | |||
64 | #define DMA_HASCOUNT(rev) ((rev)==dvmaesc1) | ||
65 | |||
66 | /* Linux DMA information structure, filled during probe. */ | ||
67 | struct sbus_dma { | ||
68 | struct sbus_dma *next; | ||
69 | struct sbus_dev *sdev; | ||
70 | void __iomem *regs; | ||
71 | |||
72 | /* Status, misc info */ | ||
73 | int node; /* Prom node for this DMA device */ | ||
74 | int running; /* Are we doing DMA now? */ | ||
75 | int allocated; /* Are we "owned" by anyone yet? */ | ||
76 | |||
77 | /* Transfer information. */ | ||
78 | unsigned long addr; /* Start address of current transfer */ | ||
79 | int nbytes; /* Size of current transfer */ | ||
80 | int realbytes; /* For splitting up large transfers, etc. */ | ||
81 | |||
82 | /* DMA revision */ | ||
83 | enum dvma_rev revision; | ||
84 | }; | ||
85 | |||
86 | extern struct sbus_dma *dma_chain; | ||
87 | |||
88 | /* Broken hardware... */ | ||
89 | #ifdef CONFIG_SUN4 | ||
90 | /* Have to sort this out. Does rev0 work fine on sun4[cmd] without isbroken? | ||
91 | * Or is rev0 present only on sun4 boxes? -jj */ | ||
92 | #define DMA_ISBROKEN(dma) ((dma)->revision == dvmarev0 || (dma)->revision == dvmarev1) | ||
93 | #else | ||
94 | #define DMA_ISBROKEN(dma) ((dma)->revision == dvmarev1) | ||
95 | #endif | ||
96 | #define DMA_ISESC1(dma) ((dma)->revision == dvmaesc1) | ||
97 | |||
98 | /* Main routines in dma.c */ | ||
99 | extern void dvma_init(struct sbus_bus *); | ||
100 | |||
101 | /* Fields in the cond_reg register */ | ||
102 | /* First, the version identification bits */ | ||
103 | #define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */ | ||
104 | #define DMA_VERS0 0x00000000 /* Sunray DMA version */ | ||
105 | #define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */ | ||
106 | #define DMA_VERS1 0x80000000 /* DMA rev 1 */ | ||
107 | #define DMA_VERS2 0xa0000000 /* DMA rev 2 */ | ||
108 | #define DMA_VERHME 0xb0000000 /* DMA hme gate array */ | ||
109 | #define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */ | ||
110 | |||
111 | #define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */ | ||
112 | #define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */ | ||
113 | #define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */ | ||
114 | #define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */ | ||
115 | #define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */ | ||
116 | #define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */ | ||
117 | #define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */ | ||
118 | #define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */ | ||
119 | #define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */ | ||
120 | #define DMA_RST_BPP DMA_RST_SCSI /* Reset the BPP controller */ | ||
121 | #define DMA_ST_WRITE 0x00000100 /* write from device to memory */ | ||
122 | #define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */ | ||
123 | #define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */ | ||
124 | #define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */ | ||
125 | #define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */ | ||
126 | #define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */ | ||
127 | #define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */ | ||
128 | #define DMA_TERM_CNTR 0x00004000 /* Terminal counter */ | ||
129 | #define DMA_SCSI_SBUS64 0x00008000 /* HME: Enable 64-bit SBUS mode. */ | ||
130 | #define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */ | ||
131 | #define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */ | ||
132 | #define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */ | ||
133 | #define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */ | ||
134 | #define DMA_E_BURSTS 0x000c0000 /* ENET: SBUS r/w burst mask */ | ||
135 | #define DMA_E_BURST32 0x00040000 /* ENET: SBUS 32 byte r/w burst */ | ||
136 | #define DMA_E_BURST16 0x00000000 /* ENET: SBUS 16 byte r/w burst */ | ||
137 | #define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */ | ||
138 | #define DMA_BRST64 0x00080000 /* SCSI: 64byte bursts (HME on UltraSparc only) */ | ||
139 | #define DMA_BRST32 0x00040000 /* SCSI/BPP: 32byte bursts */ | ||
140 | #define DMA_BRST16 0x00000000 /* SCSI/BPP: 16byte bursts */ | ||
141 | #define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */ | ||
142 | #define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */ | ||
143 | #define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */ | ||
144 | #define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */ | ||
145 | #define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */ | ||
146 | #define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */ | ||
147 | #define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */ | ||
148 | #define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */ | ||
149 | #define DMA_BPP_ON DMA_SCSI_ON /* Enable BPP dma */ | ||
150 | #define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */ | ||
151 | #define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */ | ||
152 | #define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */ | ||
153 | #define DMA_RESET_FAS366 0x08000000 /* HME: Assert RESET to FAS366 */ | ||
154 | |||
155 | /* Values describing the burst-size property from the PROM */ | ||
156 | #define DMA_BURST1 0x01 | ||
157 | #define DMA_BURST2 0x02 | ||
158 | #define DMA_BURST4 0x04 | ||
159 | #define DMA_BURST8 0x08 | ||
160 | #define DMA_BURST16 0x10 | ||
161 | #define DMA_BURST32 0x20 | ||
162 | #define DMA_BURST64 0x40 | ||
163 | #define DMA_BURSTBITS 0x7f | ||
164 | |||
165 | /* Determine highest possible final transfer address given a base */ | ||
166 | #define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL)) | ||
167 | |||
168 | /* Yes, I hack a lot of elisp in my spare time... */ | ||
169 | #define DMA_ERROR_P(regs) ((((regs)->cond_reg) & DMA_HNDL_ERROR)) | ||
170 | #define DMA_IRQ_P(regs) ((((regs)->cond_reg) & (DMA_HNDL_INTR | DMA_HNDL_ERROR))) | ||
171 | #define DMA_WRITE_P(regs) ((((regs)->cond_reg) & DMA_ST_WRITE)) | ||
172 | #define DMA_OFF(regs) ((((regs)->cond_reg) &= (~DMA_ENABLE))) | ||
173 | #define DMA_INTSOFF(regs) ((((regs)->cond_reg) &= (~DMA_INT_ENAB))) | ||
174 | #define DMA_INTSON(regs) ((((regs)->cond_reg) |= (DMA_INT_ENAB))) | ||
175 | #define DMA_PUNTFIFO(regs) ((((regs)->cond_reg) |= DMA_FIFO_INV)) | ||
176 | #define DMA_SETSTART(regs, addr) ((((regs)->st_addr) = (char *) addr)) | ||
177 | #define DMA_BEGINDMA_W(regs) \ | ||
178 | ((((regs)->cond_reg |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB)))) | ||
179 | #define DMA_BEGINDMA_R(regs) \ | ||
180 | ((((regs)->cond_reg |= ((DMA_ENABLE|DMA_INT_ENAB)&(~DMA_ST_WRITE))))) | ||
181 | |||
182 | /* For certain DMA chips, we need to disable ints upon irq entry | ||
183 | * and turn them back on when we are done. So in any ESP interrupt | ||
184 | * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT | ||
185 | * when leaving the handler. You have been warned... | ||
186 | */ | ||
187 | #define DMA_IRQ_ENTRY(dma, dregs) do { \ | ||
188 | if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \ | ||
189 | } while (0) | ||
190 | |||
191 | #define DMA_IRQ_EXIT(dma, dregs) do { \ | ||
192 | if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \ | ||
193 | } while(0) | ||
194 | |||
195 | #if 0 /* P3 this stuff is inline in ledma.c:init_restart_ledma() */ | ||
196 | /* Pause until counter runs out or BIT isn't set in the DMA condition | ||
197 | * register. | ||
198 | */ | ||
199 | static inline void sparc_dma_pause(struct sparc_dma_registers *regs, | ||
200 | unsigned long bit) | ||
201 | { | ||
202 | int ctr = 50000; /* Let's find some bugs ;) */ | ||
203 | |||
204 | /* Busy wait until the bit is not set any more */ | ||
205 | while((regs->cond_reg&bit) && (ctr>0)) { | ||
206 | ctr--; | ||
207 | __delay(5); | ||
208 | } | ||
209 | |||
210 | /* Check for bogus outcome. */ | ||
211 | if(!ctr) | ||
212 | panic("DMA timeout"); | ||
213 | } | ||
214 | |||
215 | /* Reset the friggin' thing... */ | ||
216 | #define DMA_RESET(dma) do { \ | ||
217 | struct sparc_dma_registers *regs = dma->regs; \ | ||
218 | /* Let the current FIFO drain itself */ \ | ||
219 | sparc_dma_pause(regs, (DMA_FIFO_ISDRAIN)); \ | ||
220 | /* Reset the logic */ \ | ||
221 | regs->cond_reg |= (DMA_RST_SCSI); /* assert */ \ | ||
222 | __delay(400); /* let the bits set ;) */ \ | ||
223 | regs->cond_reg &= ~(DMA_RST_SCSI); /* de-assert */ \ | ||
224 | sparc_dma_enable_interrupts(regs); /* Re-enable interrupts */ \ | ||
225 | /* Enable FAST transfers if available */ \ | ||
226 | if(dma->revision>dvmarev1) regs->cond_reg |= DMA_3CLKS; \ | ||
227 | dma->running = 0; \ | ||
228 | } while(0) | ||
229 | #endif | ||
230 | |||
231 | #define for_each_dvma(dma) \ | ||
232 | for((dma) = dma_chain; (dma); (dma) = (dma)->next) | ||
233 | |||
234 | extern int get_dma_list(char *); | ||
235 | extern int request_dma(unsigned int, __const__ char *); | ||
236 | extern void free_dma(unsigned int); | ||
237 | |||
238 | /* From PCI */ | ||
239 | |||
240 | #ifdef CONFIG_PCI | ||
241 | extern int isa_dma_bridge_buggy; | ||
242 | #else | ||
243 | #define isa_dma_bridge_buggy (0) | ||
244 | #endif | ||
245 | |||
246 | /* Routines for data transfer buffers. */ | ||
247 | BTFIXUPDEF_CALL(char *, mmu_lockarea, char *, unsigned long) | ||
248 | BTFIXUPDEF_CALL(void, mmu_unlockarea, char *, unsigned long) | ||
249 | |||
250 | #define mmu_lockarea(vaddr,len) BTFIXUP_CALL(mmu_lockarea)(vaddr,len) | ||
251 | #define mmu_unlockarea(vaddr,len) BTFIXUP_CALL(mmu_unlockarea)(vaddr,len) | ||
252 | |||
253 | /* These are implementations for sbus_map_sg/sbus_unmap_sg... collapse later */ | ||
254 | BTFIXUPDEF_CALL(__u32, mmu_get_scsi_one, char *, unsigned long, struct sbus_bus *sbus) | ||
255 | BTFIXUPDEF_CALL(void, mmu_get_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) | ||
256 | BTFIXUPDEF_CALL(void, mmu_release_scsi_one, __u32, unsigned long, struct sbus_bus *sbus) | ||
257 | BTFIXUPDEF_CALL(void, mmu_release_scsi_sgl, struct scatterlist *, int, struct sbus_bus *sbus) | ||
258 | |||
259 | #define mmu_get_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_get_scsi_one)(vaddr,len,sbus) | ||
260 | #define mmu_get_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_get_scsi_sgl)(sg,sz,sbus) | ||
261 | #define mmu_release_scsi_one(vaddr,len,sbus) BTFIXUP_CALL(mmu_release_scsi_one)(vaddr,len,sbus) | ||
262 | #define mmu_release_scsi_sgl(sg,sz,sbus) BTFIXUP_CALL(mmu_release_scsi_sgl)(sg,sz,sbus) | ||
263 | |||
264 | /* | ||
265 | * mmu_map/unmap are provided by iommu/iounit; Invalid to call on IIep. | ||
266 | * | ||
267 | * The mmu_map_dma_area establishes two mappings in one go. | ||
268 | * These mappings point to pages normally mapped at 'va' (linear address). | ||
269 | * First mapping is for CPU visible address at 'a', uncached. | ||
270 | * This is an alias, but it works because it is an uncached mapping. | ||
271 | * Second mapping is for device visible address, or "bus" address. | ||
272 | * The bus address is returned at '*pba'. | ||
273 | * | ||
274 | * These functions seem distinct, but are hard to split. On sun4c, | ||
275 | * at least for now, 'a' is equal to bus address, and retured in *pba. | ||
276 | * On sun4m, page attributes depend on the CPU type, so we have to | ||
277 | * know if we are mapping RAM or I/O, so it has to be an additional argument | ||
278 | * to a separate mapping function for CPU visible mappings. | ||
279 | */ | ||
280 | BTFIXUPDEF_CALL(int, mmu_map_dma_area, dma_addr_t *, unsigned long, unsigned long, int len) | ||
281 | BTFIXUPDEF_CALL(struct page *, mmu_translate_dvma, unsigned long busa) | ||
282 | BTFIXUPDEF_CALL(void, mmu_unmap_dma_area, unsigned long busa, int len) | ||
283 | |||
284 | #define mmu_map_dma_area(pba,va,a,len) BTFIXUP_CALL(mmu_map_dma_area)(pba,va,a,len) | ||
285 | #define mmu_unmap_dma_area(ba,len) BTFIXUP_CALL(mmu_unmap_dma_area)(ba,len) | ||
286 | #define mmu_translate_dvma(ba) BTFIXUP_CALL(mmu_translate_dvma)(ba) | ||
287 | |||
288 | #endif /* !(_ASM_SPARC_DMA_H) */ | ||
diff --git a/arch/sparc/include/asm/dma_64.h b/arch/sparc/include/asm/dma_64.h deleted file mode 100644 index 46a8aecffc02..000000000000 --- a/arch/sparc/include/asm/dma_64.h +++ /dev/null | |||
@@ -1,205 +0,0 @@ | |||
1 | /* | ||
2 | * include/asm/dma.h | ||
3 | * | ||
4 | * Copyright 1996 (C) David S. Miller (davem@caip.rutgers.edu) | ||
5 | */ | ||
6 | |||
7 | #ifndef _ASM_SPARC64_DMA_H | ||
8 | #define _ASM_SPARC64_DMA_H | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/spinlock.h> | ||
13 | |||
14 | #include <asm/sbus.h> | ||
15 | #include <asm/delay.h> | ||
16 | #include <asm/oplib.h> | ||
17 | |||
18 | /* These are irrelevant for Sparc DMA, but we leave it in so that | ||
19 | * things can compile. | ||
20 | */ | ||
21 | #define MAX_DMA_CHANNELS 8 | ||
22 | #define DMA_MODE_READ 1 | ||
23 | #define DMA_MODE_WRITE 2 | ||
24 | #define MAX_DMA_ADDRESS (~0UL) | ||
25 | |||
26 | /* Useful constants */ | ||
27 | #define SIZE_16MB (16*1024*1024) | ||
28 | #define SIZE_64K (64*1024) | ||
29 | |||
30 | /* SBUS DMA controller reg offsets */ | ||
31 | #define DMA_CSR 0x00UL /* rw DMA control/status register 0x00 */ | ||
32 | #define DMA_ADDR 0x04UL /* rw DMA transfer address register 0x04 */ | ||
33 | #define DMA_COUNT 0x08UL /* rw DMA transfer count register 0x08 */ | ||
34 | #define DMA_TEST 0x0cUL /* rw DMA test/debug register 0x0c */ | ||
35 | |||
36 | /* DVMA chip revisions */ | ||
37 | enum dvma_rev { | ||
38 | dvmarev0, | ||
39 | dvmaesc1, | ||
40 | dvmarev1, | ||
41 | dvmarev2, | ||
42 | dvmarev3, | ||
43 | dvmarevplus, | ||
44 | dvmahme | ||
45 | }; | ||
46 | |||
47 | #define DMA_HASCOUNT(rev) ((rev)==dvmaesc1) | ||
48 | |||
49 | /* Linux DMA information structure, filled during probe. */ | ||
50 | struct sbus_dma { | ||
51 | struct sbus_dma *next; | ||
52 | struct sbus_dev *sdev; | ||
53 | void __iomem *regs; | ||
54 | |||
55 | /* Status, misc info */ | ||
56 | int node; /* Prom node for this DMA device */ | ||
57 | int running; /* Are we doing DMA now? */ | ||
58 | int allocated; /* Are we "owned" by anyone yet? */ | ||
59 | |||
60 | /* Transfer information. */ | ||
61 | u32 addr; /* Start address of current transfer */ | ||
62 | int nbytes; /* Size of current transfer */ | ||
63 | int realbytes; /* For splitting up large transfers, etc. */ | ||
64 | |||
65 | /* DMA revision */ | ||
66 | enum dvma_rev revision; | ||
67 | }; | ||
68 | |||
69 | extern struct sbus_dma *dma_chain; | ||
70 | |||
71 | /* Broken hardware... */ | ||
72 | #define DMA_ISBROKEN(dma) ((dma)->revision == dvmarev1) | ||
73 | #define DMA_ISESC1(dma) ((dma)->revision == dvmaesc1) | ||
74 | |||
75 | /* Main routines in dma.c */ | ||
76 | extern void dvma_init(struct sbus_bus *); | ||
77 | |||
78 | /* Fields in the cond_reg register */ | ||
79 | /* First, the version identification bits */ | ||
80 | #define DMA_DEVICE_ID 0xf0000000 /* Device identification bits */ | ||
81 | #define DMA_VERS0 0x00000000 /* Sunray DMA version */ | ||
82 | #define DMA_ESCV1 0x40000000 /* DMA ESC Version 1 */ | ||
83 | #define DMA_VERS1 0x80000000 /* DMA rev 1 */ | ||
84 | #define DMA_VERS2 0xa0000000 /* DMA rev 2 */ | ||
85 | #define DMA_VERHME 0xb0000000 /* DMA hme gate array */ | ||
86 | #define DMA_VERSPLUS 0x90000000 /* DMA rev 1 PLUS */ | ||
87 | |||
88 | #define DMA_HNDL_INTR 0x00000001 /* An IRQ needs to be handled */ | ||
89 | #define DMA_HNDL_ERROR 0x00000002 /* We need to take an error */ | ||
90 | #define DMA_FIFO_ISDRAIN 0x0000000c /* The DMA FIFO is draining */ | ||
91 | #define DMA_INT_ENAB 0x00000010 /* Turn on interrupts */ | ||
92 | #define DMA_FIFO_INV 0x00000020 /* Invalidate the FIFO */ | ||
93 | #define DMA_ACC_SZ_ERR 0x00000040 /* The access size was bad */ | ||
94 | #define DMA_FIFO_STDRAIN 0x00000040 /* DMA_VERS1 Drain the FIFO */ | ||
95 | #define DMA_RST_SCSI 0x00000080 /* Reset the SCSI controller */ | ||
96 | #define DMA_RST_ENET DMA_RST_SCSI /* Reset the ENET controller */ | ||
97 | #define DMA_ST_WRITE 0x00000100 /* write from device to memory */ | ||
98 | #define DMA_ENABLE 0x00000200 /* Fire up DMA, handle requests */ | ||
99 | #define DMA_PEND_READ 0x00000400 /* DMA_VERS1/0/PLUS Pending Read */ | ||
100 | #define DMA_ESC_BURST 0x00000800 /* 1=16byte 0=32byte */ | ||
101 | #define DMA_READ_AHEAD 0x00001800 /* DMA read ahead partial longword */ | ||
102 | #define DMA_DSBL_RD_DRN 0x00001000 /* No EC drain on slave reads */ | ||
103 | #define DMA_BCNT_ENAB 0x00002000 /* If on, use the byte counter */ | ||
104 | #define DMA_TERM_CNTR 0x00004000 /* Terminal counter */ | ||
105 | #define DMA_SCSI_SBUS64 0x00008000 /* HME: Enable 64-bit SBUS mode. */ | ||
106 | #define DMA_CSR_DISAB 0x00010000 /* No FIFO drains during csr */ | ||
107 | #define DMA_SCSI_DISAB 0x00020000 /* No FIFO drains during reg */ | ||
108 | #define DMA_DSBL_WR_INV 0x00020000 /* No EC inval. on slave writes */ | ||
109 | #define DMA_ADD_ENABLE 0x00040000 /* Special ESC DVMA optimization */ | ||
110 | #define DMA_E_BURSTS 0x000c0000 /* ENET: SBUS r/w burst mask */ | ||
111 | #define DMA_E_BURST32 0x00040000 /* ENET: SBUS 32 byte r/w burst */ | ||
112 | #define DMA_E_BURST16 0x00000000 /* ENET: SBUS 16 byte r/w burst */ | ||
113 | #define DMA_BRST_SZ 0x000c0000 /* SCSI: SBUS r/w burst size */ | ||
114 | #define DMA_BRST64 0x000c0000 /* SCSI: 64byte bursts (HME on UltraSparc only) */ | ||
115 | #define DMA_BRST32 0x00040000 /* SCSI: 32byte bursts */ | ||
116 | #define DMA_BRST16 0x00000000 /* SCSI: 16byte bursts */ | ||
117 | #define DMA_BRST0 0x00080000 /* SCSI: no bursts (non-HME gate arrays) */ | ||
118 | #define DMA_ADDR_DISAB 0x00100000 /* No FIFO drains during addr */ | ||
119 | #define DMA_2CLKS 0x00200000 /* Each transfer = 2 clock ticks */ | ||
120 | #define DMA_3CLKS 0x00400000 /* Each transfer = 3 clock ticks */ | ||
121 | #define DMA_EN_ENETAUI DMA_3CLKS /* Put lance into AUI-cable mode */ | ||
122 | #define DMA_CNTR_DISAB 0x00800000 /* No IRQ when DMA_TERM_CNTR set */ | ||
123 | #define DMA_AUTO_NADDR 0x01000000 /* Use "auto nxt addr" feature */ | ||
124 | #define DMA_SCSI_ON 0x02000000 /* Enable SCSI dma */ | ||
125 | #define DMA_PARITY_OFF 0x02000000 /* HME: disable parity checking */ | ||
126 | #define DMA_LOADED_ADDR 0x04000000 /* Address has been loaded */ | ||
127 | #define DMA_LOADED_NADDR 0x08000000 /* Next address has been loaded */ | ||
128 | #define DMA_RESET_FAS366 0x08000000 /* HME: Assert RESET to FAS366 */ | ||
129 | |||
130 | /* Values describing the burst-size property from the PROM */ | ||
131 | #define DMA_BURST1 0x01 | ||
132 | #define DMA_BURST2 0x02 | ||
133 | #define DMA_BURST4 0x04 | ||
134 | #define DMA_BURST8 0x08 | ||
135 | #define DMA_BURST16 0x10 | ||
136 | #define DMA_BURST32 0x20 | ||
137 | #define DMA_BURST64 0x40 | ||
138 | #define DMA_BURSTBITS 0x7f | ||
139 | |||
140 | /* Determine highest possible final transfer address given a base */ | ||
141 | #define DMA_MAXEND(addr) (0x01000000UL-(((unsigned long)(addr))&0x00ffffffUL)) | ||
142 | |||
143 | /* Yes, I hack a lot of elisp in my spare time... */ | ||
144 | #define DMA_ERROR_P(regs) ((sbus_readl((regs) + DMA_CSR) & DMA_HNDL_ERROR)) | ||
145 | #define DMA_IRQ_P(regs) ((sbus_readl((regs) + DMA_CSR)) & (DMA_HNDL_INTR | DMA_HNDL_ERROR)) | ||
146 | #define DMA_WRITE_P(regs) ((sbus_readl((regs) + DMA_CSR) & DMA_ST_WRITE)) | ||
147 | #define DMA_OFF(__regs) \ | ||
148 | do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ | ||
149 | tmp &= ~DMA_ENABLE; \ | ||
150 | sbus_writel(tmp, (__regs) + DMA_CSR); \ | ||
151 | } while(0) | ||
152 | #define DMA_INTSOFF(__regs) \ | ||
153 | do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ | ||
154 | tmp &= ~DMA_INT_ENAB; \ | ||
155 | sbus_writel(tmp, (__regs) + DMA_CSR); \ | ||
156 | } while(0) | ||
157 | #define DMA_INTSON(__regs) \ | ||
158 | do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ | ||
159 | tmp |= DMA_INT_ENAB; \ | ||
160 | sbus_writel(tmp, (__regs) + DMA_CSR); \ | ||
161 | } while(0) | ||
162 | #define DMA_PUNTFIFO(__regs) \ | ||
163 | do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ | ||
164 | tmp |= DMA_FIFO_INV; \ | ||
165 | sbus_writel(tmp, (__regs) + DMA_CSR); \ | ||
166 | } while(0) | ||
167 | #define DMA_SETSTART(__regs, __addr) \ | ||
168 | sbus_writel((u32)(__addr), (__regs) + DMA_ADDR); | ||
169 | #define DMA_BEGINDMA_W(__regs) \ | ||
170 | do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ | ||
171 | tmp |= (DMA_ST_WRITE|DMA_ENABLE|DMA_INT_ENAB); \ | ||
172 | sbus_writel(tmp, (__regs) + DMA_CSR); \ | ||
173 | } while(0) | ||
174 | #define DMA_BEGINDMA_R(__regs) \ | ||
175 | do { u32 tmp = sbus_readl((__regs) + DMA_CSR); \ | ||
176 | tmp |= (DMA_ENABLE|DMA_INT_ENAB); \ | ||
177 | tmp &= ~DMA_ST_WRITE; \ | ||
178 | sbus_writel(tmp, (__regs) + DMA_CSR); \ | ||
179 | } while(0) | ||
180 | |||
181 | /* For certain DMA chips, we need to disable ints upon irq entry | ||
182 | * and turn them back on when we are done. So in any ESP interrupt | ||
183 | * handler you *must* call DMA_IRQ_ENTRY upon entry and DMA_IRQ_EXIT | ||
184 | * when leaving the handler. You have been warned... | ||
185 | */ | ||
186 | #define DMA_IRQ_ENTRY(dma, dregs) do { \ | ||
187 | if(DMA_ISBROKEN(dma)) DMA_INTSOFF(dregs); \ | ||
188 | } while (0) | ||
189 | |||
190 | #define DMA_IRQ_EXIT(dma, dregs) do { \ | ||
191 | if(DMA_ISBROKEN(dma)) DMA_INTSON(dregs); \ | ||
192 | } while(0) | ||
193 | |||
194 | #define for_each_dvma(dma) \ | ||
195 | for((dma) = dma_chain; (dma); (dma) = (dma)->next) | ||
196 | |||
197 | /* From PCI */ | ||
198 | |||
199 | #ifdef CONFIG_PCI | ||
200 | extern int isa_dma_bridge_buggy; | ||
201 | #else | ||
202 | #define isa_dma_bridge_buggy (0) | ||
203 | #endif | ||
204 | |||
205 | #endif /* !(_ASM_SPARC64_DMA_H) */ | ||
diff --git a/arch/sparc/include/asm/ebus.h b/arch/sparc/include/asm/ebus.h deleted file mode 100644 index 83a6d16c22e6..000000000000 --- a/arch/sparc/include/asm/ebus.h +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | #ifndef ___ASM_SPARC_EBUS_H | ||
2 | #define ___ASM_SPARC_EBUS_H | ||
3 | #if defined(__sparc__) && defined(__arch64__) | ||
4 | #include <asm/ebus_64.h> | ||
5 | #else | ||
6 | #include <asm/ebus_32.h> | ||
7 | #endif | ||
8 | #endif | ||
diff --git a/arch/sparc/include/asm/ebus_32.h b/arch/sparc/include/asm/ebus_32.h deleted file mode 100644 index f91f0b267ce1..000000000000 --- a/arch/sparc/include/asm/ebus_32.h +++ /dev/null | |||
@@ -1,99 +0,0 @@ | |||
1 | /* | ||
2 | * ebus.h: PCI to Ebus pseudo driver software state. | ||
3 | * | ||
4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | ||
5 | * | ||
6 | * Adopted for sparc by V. Roganov and G. Raiko. | ||
7 | */ | ||
8 | |||
9 | #ifndef __SPARC_EBUS_H | ||
10 | #define __SPARC_EBUS_H | ||
11 | |||
12 | #ifndef _LINUX_IOPORT_H | ||
13 | #include <linux/ioport.h> | ||
14 | #endif | ||
15 | #include <linux/of_device.h> | ||
16 | #include <asm/oplib.h> | ||
17 | #include <asm/prom.h> | ||
18 | |||
19 | struct linux_ebus_child { | ||
20 | struct linux_ebus_child *next; | ||
21 | struct linux_ebus_device *parent; | ||
22 | struct linux_ebus *bus; | ||
23 | struct device_node *prom_node; | ||
24 | struct resource resource[PROMREG_MAX]; | ||
25 | int num_addrs; | ||
26 | unsigned int irqs[PROMINTR_MAX]; | ||
27 | int num_irqs; | ||
28 | }; | ||
29 | |||
30 | struct linux_ebus_device { | ||
31 | struct of_device ofdev; | ||
32 | struct linux_ebus_device *next; | ||
33 | struct linux_ebus_child *children; | ||
34 | struct linux_ebus *bus; | ||
35 | struct device_node *prom_node; | ||
36 | struct resource resource[PROMREG_MAX]; | ||
37 | int num_addrs; | ||
38 | unsigned int irqs[PROMINTR_MAX]; | ||
39 | int num_irqs; | ||
40 | }; | ||
41 | #define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev) | ||
42 | |||
43 | struct linux_ebus { | ||
44 | struct of_device ofdev; | ||
45 | struct linux_ebus *next; | ||
46 | struct linux_ebus_device *devices; | ||
47 | struct linux_pbm_info *parent; | ||
48 | struct pci_dev *self; | ||
49 | struct device_node *prom_node; | ||
50 | }; | ||
51 | #define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev) | ||
52 | |||
53 | struct linux_ebus_dma { | ||
54 | unsigned int dcsr; | ||
55 | unsigned int dacr; | ||
56 | unsigned int dbcr; | ||
57 | }; | ||
58 | |||
59 | #define EBUS_DCSR_INT_PEND 0x00000001 | ||
60 | #define EBUS_DCSR_ERR_PEND 0x00000002 | ||
61 | #define EBUS_DCSR_DRAIN 0x00000004 | ||
62 | #define EBUS_DCSR_INT_EN 0x00000010 | ||
63 | #define EBUS_DCSR_RESET 0x00000080 | ||
64 | #define EBUS_DCSR_WRITE 0x00000100 | ||
65 | #define EBUS_DCSR_EN_DMA 0x00000200 | ||
66 | #define EBUS_DCSR_CYC_PEND 0x00000400 | ||
67 | #define EBUS_DCSR_DIAG_RD_DONE 0x00000800 | ||
68 | #define EBUS_DCSR_DIAG_WR_DONE 0x00001000 | ||
69 | #define EBUS_DCSR_EN_CNT 0x00002000 | ||
70 | #define EBUS_DCSR_TC 0x00004000 | ||
71 | #define EBUS_DCSR_DIS_CSR_DRN 0x00010000 | ||
72 | #define EBUS_DCSR_BURST_SZ_MASK 0x000c0000 | ||
73 | #define EBUS_DCSR_BURST_SZ_1 0x00080000 | ||
74 | #define EBUS_DCSR_BURST_SZ_4 0x00000000 | ||
75 | #define EBUS_DCSR_BURST_SZ_8 0x00040000 | ||
76 | #define EBUS_DCSR_BURST_SZ_16 0x000c0000 | ||
77 | #define EBUS_DCSR_DIAG_EN 0x00100000 | ||
78 | #define EBUS_DCSR_DIS_ERR_PEND 0x00400000 | ||
79 | #define EBUS_DCSR_TCI_DIS 0x00800000 | ||
80 | #define EBUS_DCSR_EN_NEXT 0x01000000 | ||
81 | #define EBUS_DCSR_DMA_ON 0x02000000 | ||
82 | #define EBUS_DCSR_A_LOADED 0x04000000 | ||
83 | #define EBUS_DCSR_NA_LOADED 0x08000000 | ||
84 | #define EBUS_DCSR_DEV_ID_MASK 0xf0000000 | ||
85 | |||
86 | extern struct linux_ebus *ebus_chain; | ||
87 | |||
88 | extern void ebus_init(void); | ||
89 | |||
90 | #define for_each_ebus(bus) \ | ||
91 | for((bus) = ebus_chain; (bus); (bus) = (bus)->next) | ||
92 | |||
93 | #define for_each_ebusdev(dev, bus) \ | ||
94 | for((dev) = (bus)->devices; (dev); (dev) = (dev)->next) | ||
95 | |||
96 | #define for_each_edevchild(dev, child) \ | ||
97 | for((child) = (dev)->children; (child); (child) = (child)->next) | ||
98 | |||
99 | #endif /* !(__SPARC_EBUS_H) */ | ||
diff --git a/arch/sparc/include/asm/ebus_64.h b/arch/sparc/include/asm/ebus_64.h deleted file mode 100644 index 14c6a111f60c..000000000000 --- a/arch/sparc/include/asm/ebus_64.h +++ /dev/null | |||
@@ -1,95 +0,0 @@ | |||
1 | /* | ||
2 | * ebus.h: PCI to Ebus pseudo driver software state. | ||
3 | * | ||
4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | ||
5 | * Copyright (C) 1999 David S. Miller (davem@redhat.com) | ||
6 | */ | ||
7 | |||
8 | #ifndef __SPARC64_EBUS_H | ||
9 | #define __SPARC64_EBUS_H | ||
10 | |||
11 | #include <linux/of_device.h> | ||
12 | |||
13 | #include <asm/oplib.h> | ||
14 | #include <asm/prom.h> | ||
15 | |||
16 | struct linux_ebus_child { | ||
17 | struct linux_ebus_child *next; | ||
18 | struct linux_ebus_device *parent; | ||
19 | struct linux_ebus *bus; | ||
20 | struct device_node *prom_node; | ||
21 | struct resource resource[PROMREG_MAX]; | ||
22 | int num_addrs; | ||
23 | unsigned int irqs[PROMINTR_MAX]; | ||
24 | int num_irqs; | ||
25 | }; | ||
26 | |||
27 | struct linux_ebus_device { | ||
28 | struct of_device ofdev; | ||
29 | struct linux_ebus_device *next; | ||
30 | struct linux_ebus_child *children; | ||
31 | struct linux_ebus *bus; | ||
32 | struct device_node *prom_node; | ||
33 | struct resource resource[PROMREG_MAX]; | ||
34 | int num_addrs; | ||
35 | unsigned int irqs[PROMINTR_MAX]; | ||
36 | int num_irqs; | ||
37 | }; | ||
38 | #define to_ebus_device(d) container_of(d, struct linux_ebus_device, ofdev.dev) | ||
39 | |||
40 | struct linux_ebus { | ||
41 | struct of_device ofdev; | ||
42 | struct linux_ebus *next; | ||
43 | struct linux_ebus_device *devices; | ||
44 | struct pci_dev *self; | ||
45 | int index; | ||
46 | int is_rio; | ||
47 | struct device_node *prom_node; | ||
48 | }; | ||
49 | #define to_ebus(d) container_of(d, struct linux_ebus, ofdev.dev) | ||
50 | |||
51 | struct ebus_dma_info { | ||
52 | spinlock_t lock; | ||
53 | void __iomem *regs; | ||
54 | |||
55 | unsigned int flags; | ||
56 | #define EBUS_DMA_FLAG_USE_EBDMA_HANDLER 0x00000001 | ||
57 | #define EBUS_DMA_FLAG_TCI_DISABLE 0x00000002 | ||
58 | |||
59 | /* These are only valid is EBUS_DMA_FLAG_USE_EBDMA_HANDLER is | ||
60 | * set. | ||
61 | */ | ||
62 | void (*callback)(struct ebus_dma_info *p, int event, void *cookie); | ||
63 | void *client_cookie; | ||
64 | unsigned int irq; | ||
65 | #define EBUS_DMA_EVENT_ERROR 1 | ||
66 | #define EBUS_DMA_EVENT_DMA 2 | ||
67 | #define EBUS_DMA_EVENT_DEVICE 4 | ||
68 | |||
69 | unsigned char name[64]; | ||
70 | }; | ||
71 | |||
72 | extern int ebus_dma_register(struct ebus_dma_info *p); | ||
73 | extern int ebus_dma_irq_enable(struct ebus_dma_info *p, int on); | ||
74 | extern void ebus_dma_unregister(struct ebus_dma_info *p); | ||
75 | extern int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr, | ||
76 | size_t len); | ||
77 | extern void ebus_dma_prepare(struct ebus_dma_info *p, int write); | ||
78 | extern unsigned int ebus_dma_residue(struct ebus_dma_info *p); | ||
79 | extern unsigned int ebus_dma_addr(struct ebus_dma_info *p); | ||
80 | extern void ebus_dma_enable(struct ebus_dma_info *p, int on); | ||
81 | |||
82 | extern struct linux_ebus *ebus_chain; | ||
83 | |||
84 | extern void ebus_init(void); | ||
85 | |||
86 | #define for_each_ebus(bus) \ | ||
87 | for((bus) = ebus_chain; (bus); (bus) = (bus)->next) | ||
88 | |||
89 | #define for_each_ebusdev(dev, bus) \ | ||
90 | for((dev) = (bus)->devices; (dev); (dev) = (dev)->next) | ||
91 | |||
92 | #define for_each_edevchild(dev, child) \ | ||
93 | for((child) = (dev)->children; (child); (child) = (child)->next) | ||
94 | |||
95 | #endif /* !(__SPARC64_EBUS_H) */ | ||
diff --git a/arch/sparc/include/asm/ebus_dma.h b/arch/sparc/include/asm/ebus_dma.h new file mode 100644 index 000000000000..f07a5b541c98 --- /dev/null +++ b/arch/sparc/include/asm/ebus_dma.h | |||
@@ -0,0 +1,35 @@ | |||
1 | #ifndef __ASM_SPARC_EBUS_DMA_H | ||
2 | #define __ASM_SPARC_EBUS_DMA_H | ||
3 | |||
4 | struct ebus_dma_info { | ||
5 | spinlock_t lock; | ||
6 | void __iomem *regs; | ||
7 | |||
8 | unsigned int flags; | ||
9 | #define EBUS_DMA_FLAG_USE_EBDMA_HANDLER 0x00000001 | ||
10 | #define EBUS_DMA_FLAG_TCI_DISABLE 0x00000002 | ||
11 | |||
12 | /* These are only valid is EBUS_DMA_FLAG_USE_EBDMA_HANDLER is | ||
13 | * set. | ||
14 | */ | ||
15 | void (*callback)(struct ebus_dma_info *p, int event, void *cookie); | ||
16 | void *client_cookie; | ||
17 | unsigned int irq; | ||
18 | #define EBUS_DMA_EVENT_ERROR 1 | ||
19 | #define EBUS_DMA_EVENT_DMA 2 | ||
20 | #define EBUS_DMA_EVENT_DEVICE 4 | ||
21 | |||
22 | unsigned char name[64]; | ||
23 | }; | ||
24 | |||
25 | extern int ebus_dma_register(struct ebus_dma_info *p); | ||
26 | extern int ebus_dma_irq_enable(struct ebus_dma_info *p, int on); | ||
27 | extern void ebus_dma_unregister(struct ebus_dma_info *p); | ||
28 | extern int ebus_dma_request(struct ebus_dma_info *p, dma_addr_t bus_addr, | ||
29 | size_t len); | ||
30 | extern void ebus_dma_prepare(struct ebus_dma_info *p, int write); | ||
31 | extern unsigned int ebus_dma_residue(struct ebus_dma_info *p); | ||
32 | extern unsigned int ebus_dma_addr(struct ebus_dma_info *p); | ||
33 | extern void ebus_dma_enable(struct ebus_dma_info *p, int on); | ||
34 | |||
35 | #endif /* __ASM_SPARC_EBUS_DMA_H */ | ||
diff --git a/arch/sparc/include/asm/elf_32.h b/arch/sparc/include/asm/elf_32.h index d043f80bc2fd..b7ab60547827 100644 --- a/arch/sparc/include/asm/elf_32.h +++ b/arch/sparc/include/asm/elf_32.h | |||
@@ -105,11 +105,8 @@ typedef struct { | |||
105 | #define ELF_DATA ELFDATA2MSB | 105 | #define ELF_DATA ELFDATA2MSB |
106 | 106 | ||
107 | #define USE_ELF_CORE_DUMP | 107 | #define USE_ELF_CORE_DUMP |
108 | #ifndef CONFIG_SUN4 | 108 | |
109 | #define ELF_EXEC_PAGESIZE 4096 | 109 | #define ELF_EXEC_PAGESIZE 4096 |
110 | #else | ||
111 | #define ELF_EXEC_PAGESIZE 8192 | ||
112 | #endif | ||
113 | 110 | ||
114 | 111 | ||
115 | /* This is the location that an ET_DYN program is loaded if exec'ed. Typical | 112 | /* This is the location that an ET_DYN program is loaded if exec'ed. Typical |
@@ -126,7 +123,7 @@ typedef struct { | |||
126 | /* Sun4c has none of the capabilities, most sun4m's have them all. | 123 | /* Sun4c has none of the capabilities, most sun4m's have them all. |
127 | * XXX This is gross, set some global variable at boot time. -DaveM | 124 | * XXX This is gross, set some global variable at boot time. -DaveM |
128 | */ | 125 | */ |
129 | #define ELF_HWCAP ((ARCH_SUN4C_SUN4) ? 0 : \ | 126 | #define ELF_HWCAP ((ARCH_SUN4C) ? 0 : \ |
130 | (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \ | 127 | (HWCAP_SPARC_FLUSH | HWCAP_SPARC_STBAR | \ |
131 | HWCAP_SPARC_SWAP | \ | 128 | HWCAP_SPARC_SWAP | \ |
132 | ((srmmu_modtype != Cypress && \ | 129 | ((srmmu_modtype != Cypress && \ |
diff --git a/arch/sparc/include/asm/fhc.h b/arch/sparc/include/asm/fhc.h index 788cbc46a116..57f1b303ad54 100644 --- a/arch/sparc/include/asm/fhc.h +++ b/arch/sparc/include/asm/fhc.h | |||
@@ -1,5 +1,4 @@ | |||
1 | /* | 1 | /* fhc.h: FHC and Clock board register definitions. |
2 | * fhc.h: Structures for central/fhc pseudo driver on Sunfire/Starfire/Wildfire. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 1997, 1999 David S. Miller (davem@redhat.com) |
5 | */ | 4 | */ |
@@ -7,14 +6,6 @@ | |||
7 | #ifndef _SPARC64_FHC_H | 6 | #ifndef _SPARC64_FHC_H |
8 | #define _SPARC64_FHC_H | 7 | #define _SPARC64_FHC_H |
9 | 8 | ||
10 | #include <linux/timer.h> | ||
11 | |||
12 | #include <asm/oplib.h> | ||
13 | #include <asm/prom.h> | ||
14 | #include <asm/upa.h> | ||
15 | |||
16 | struct linux_fhc; | ||
17 | |||
18 | /* Clock board register offsets. */ | 9 | /* Clock board register offsets. */ |
19 | #define CLOCK_CTRL 0x00UL /* Main control */ | 10 | #define CLOCK_CTRL 0x00UL /* Main control */ |
20 | #define CLOCK_STAT1 0x10UL /* Status one */ | 11 | #define CLOCK_STAT1 0x10UL /* Status one */ |
@@ -29,21 +20,7 @@ struct linux_fhc; | |||
29 | #define CLOCK_CTRL_MLED 0x02 /* Mid LED, 1 == on */ | 20 | #define CLOCK_CTRL_MLED 0x02 /* Mid LED, 1 == on */ |
30 | #define CLOCK_CTRL_RLED 0x01 /* RIght LED, 1 == on */ | 21 | #define CLOCK_CTRL_RLED 0x01 /* RIght LED, 1 == on */ |
31 | 22 | ||
32 | struct linux_central { | ||
33 | struct linux_fhc *child; | ||
34 | unsigned long cfreg; | ||
35 | unsigned long clkregs; | ||
36 | unsigned long clkver; | ||
37 | int slots; | ||
38 | struct device_node *prom_node; | ||
39 | |||
40 | struct linux_prom_ranges central_ranges[PROMREG_MAX]; | ||
41 | int num_central_ranges; | ||
42 | }; | ||
43 | |||
44 | /* Firehose controller register offsets */ | 23 | /* Firehose controller register offsets */ |
45 | struct fhc_regs { | ||
46 | unsigned long pregs; /* FHC internal regs */ | ||
47 | #define FHC_PREGS_ID 0x00UL /* FHC ID */ | 24 | #define FHC_PREGS_ID 0x00UL /* FHC ID */ |
48 | #define FHC_ID_VERS 0xf0000000 /* Version of this FHC */ | 25 | #define FHC_ID_VERS 0xf0000000 /* Version of this FHC */ |
49 | #define FHC_ID_PARTID 0x0ffff000 /* Part ID code (0x0f9f == FHC) */ | 26 | #define FHC_ID_PARTID 0x0ffff000 /* Part ID code (0x0f9f == FHC) */ |
@@ -90,32 +67,14 @@ struct fhc_regs { | |||
90 | #define FHC_JTAG_CTRL_MENAB 0x80000000 /* Indicates this is JTAG Master */ | 67 | #define FHC_JTAG_CTRL_MENAB 0x80000000 /* Indicates this is JTAG Master */ |
91 | #define FHC_JTAG_CTRL_MNONE 0x40000000 /* Indicates no JTAG Master present */ | 68 | #define FHC_JTAG_CTRL_MNONE 0x40000000 /* Indicates no JTAG Master present */ |
92 | #define FHC_PREGS_JCMD 0x100UL /* FHC JTAG Command Register */ | 69 | #define FHC_PREGS_JCMD 0x100UL /* FHC JTAG Command Register */ |
93 | unsigned long ireg; /* FHC IGN reg */ | ||
94 | #define FHC_IREG_IGN 0x00UL /* This FHC's IGN */ | 70 | #define FHC_IREG_IGN 0x00UL /* This FHC's IGN */ |
95 | unsigned long ffregs; /* FHC fanfail regs */ | ||
96 | #define FHC_FFREGS_IMAP 0x00UL /* FHC Fanfail IMAP */ | 71 | #define FHC_FFREGS_IMAP 0x00UL /* FHC Fanfail IMAP */ |
97 | #define FHC_FFREGS_ICLR 0x10UL /* FHC Fanfail ICLR */ | 72 | #define FHC_FFREGS_ICLR 0x10UL /* FHC Fanfail ICLR */ |
98 | unsigned long sregs; /* FHC system regs */ | ||
99 | #define FHC_SREGS_IMAP 0x00UL /* FHC System IMAP */ | 73 | #define FHC_SREGS_IMAP 0x00UL /* FHC System IMAP */ |
100 | #define FHC_SREGS_ICLR 0x10UL /* FHC System ICLR */ | 74 | #define FHC_SREGS_ICLR 0x10UL /* FHC System ICLR */ |
101 | unsigned long uregs; /* FHC uart regs */ | ||
102 | #define FHC_UREGS_IMAP 0x00UL /* FHC Uart IMAP */ | 75 | #define FHC_UREGS_IMAP 0x00UL /* FHC Uart IMAP */ |
103 | #define FHC_UREGS_ICLR 0x10UL /* FHC Uart ICLR */ | 76 | #define FHC_UREGS_ICLR 0x10UL /* FHC Uart ICLR */ |
104 | unsigned long tregs; /* FHC TOD regs */ | ||
105 | #define FHC_TREGS_IMAP 0x00UL /* FHC TOD IMAP */ | 77 | #define FHC_TREGS_IMAP 0x00UL /* FHC TOD IMAP */ |
106 | #define FHC_TREGS_ICLR 0x10UL /* FHC TOD ICLR */ | 78 | #define FHC_TREGS_ICLR 0x10UL /* FHC TOD ICLR */ |
107 | }; | ||
108 | |||
109 | struct linux_fhc { | ||
110 | struct linux_fhc *next; | ||
111 | struct linux_central *parent; /* NULL if not central FHC */ | ||
112 | struct fhc_regs fhc_regs; | ||
113 | int board; | ||
114 | int jtag_master; | ||
115 | struct device_node *prom_node; | ||
116 | |||
117 | struct linux_prom_ranges fhc_ranges[PROMREG_MAX]; | ||
118 | int num_fhc_ranges; | ||
119 | }; | ||
120 | 79 | ||
121 | #endif /* !(_SPARC64_FHC_H) */ | 80 | #endif /* !(_SPARC64_FHC_H) */ |
diff --git a/arch/sparc/include/asm/floppy_32.h b/arch/sparc/include/asm/floppy_32.h index ae3f00bf22ff..c792830636de 100644 --- a/arch/sparc/include/asm/floppy_32.h +++ b/arch/sparc/include/asm/floppy_32.h | |||
@@ -6,6 +6,9 @@ | |||
6 | #ifndef __ASM_SPARC_FLOPPY_H | 6 | #ifndef __ASM_SPARC_FLOPPY_H |
7 | #define __ASM_SPARC_FLOPPY_H | 7 | #define __ASM_SPARC_FLOPPY_H |
8 | 8 | ||
9 | #include <linux/of.h> | ||
10 | #include <linux/of_device.h> | ||
11 | |||
9 | #include <asm/page.h> | 12 | #include <asm/page.h> |
10 | #include <asm/pgtable.h> | 13 | #include <asm/pgtable.h> |
11 | #include <asm/system.h> | 14 | #include <asm/system.h> |
@@ -343,7 +346,7 @@ static int sun_floppy_init(void) | |||
343 | r.flags = fd_regs[0].which_io; | 346 | r.flags = fd_regs[0].which_io; |
344 | r.start = fd_regs[0].phys_addr; | 347 | r.start = fd_regs[0].phys_addr; |
345 | sun_fdc = (struct sun_flpy_controller *) | 348 | sun_fdc = (struct sun_flpy_controller *) |
346 | sbus_ioremap(&r, 0, fd_regs[0].reg_size, "floppy"); | 349 | of_ioremap(&r, 0, fd_regs[0].reg_size, "floppy"); |
347 | 350 | ||
348 | /* Last minute sanity check... */ | 351 | /* Last minute sanity check... */ |
349 | if(sun_fdc->status_82072 == 0xff) { | 352 | if(sun_fdc->status_82072 == 0xff) { |
@@ -385,4 +388,15 @@ static int sparc_eject(void) | |||
385 | 388 | ||
386 | #define EXTRA_FLOPPY_PARAMS | 389 | #define EXTRA_FLOPPY_PARAMS |
387 | 390 | ||
391 | static DEFINE_SPINLOCK(dma_spin_lock); | ||
392 | |||
393 | #define claim_dma_lock() \ | ||
394 | ({ unsigned long flags; \ | ||
395 | spin_lock_irqsave(&dma_spin_lock, flags); \ | ||
396 | flags; \ | ||
397 | }) | ||
398 | |||
399 | #define release_dma_lock(__flags) \ | ||
400 | spin_unlock_irqrestore(&dma_spin_lock, __flags); | ||
401 | |||
388 | #endif /* !(__ASM_SPARC_FLOPPY_H) */ | 402 | #endif /* !(__ASM_SPARC_FLOPPY_H) */ |
diff --git a/arch/sparc/include/asm/floppy_64.h b/arch/sparc/include/asm/floppy_64.h index c39db1060bc7..36439d67ad71 100644 --- a/arch/sparc/include/asm/floppy_64.h +++ b/arch/sparc/include/asm/floppy_64.h | |||
@@ -1,6 +1,6 @@ | |||
1 | /* floppy.h: Sparc specific parts of the Floppy driver. | 1 | /* floppy.h: Sparc specific parts of the Floppy driver. |
2 | * | 2 | * |
3 | * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net) |
4 | * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | 4 | * Copyright (C) 1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) |
5 | * | 5 | * |
6 | * Ultra/PCI support added: Sep 1997 Eddie C. Dost (ecd@skynet.be) | 6 | * Ultra/PCI support added: Sep 1997 Eddie C. Dost (ecd@skynet.be) |
@@ -9,18 +9,11 @@ | |||
9 | #ifndef __ASM_SPARC64_FLOPPY_H | 9 | #ifndef __ASM_SPARC64_FLOPPY_H |
10 | #define __ASM_SPARC64_FLOPPY_H | 10 | #define __ASM_SPARC64_FLOPPY_H |
11 | 11 | ||
12 | #include <linux/init.h> | 12 | #include <linux/of.h> |
13 | #include <linux/pci.h> | 13 | #include <linux/of_device.h> |
14 | #include <linux/dma-mapping.h> | ||
14 | 15 | ||
15 | #include <asm/page.h> | ||
16 | #include <asm/pgtable.h> | ||
17 | #include <asm/system.h> | ||
18 | #include <asm/idprom.h> | ||
19 | #include <asm/oplib.h> | ||
20 | #include <asm/auxio.h> | 16 | #include <asm/auxio.h> |
21 | #include <asm/sbus.h> | ||
22 | #include <asm/irq.h> | ||
23 | |||
24 | 17 | ||
25 | /* | 18 | /* |
26 | * Define this to enable exchanging drive 0 and 1 if only drive 1 is | 19 | * Define this to enable exchanging drive 0 and 1 if only drive 1 is |
@@ -50,7 +43,7 @@ struct sun_flpy_controller { | |||
50 | /* You'll only ever find one controller on an Ultra anyways. */ | 43 | /* You'll only ever find one controller on an Ultra anyways. */ |
51 | static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1; | 44 | static struct sun_flpy_controller *sun_fdc = (struct sun_flpy_controller *)-1; |
52 | unsigned long fdc_status; | 45 | unsigned long fdc_status; |
53 | static struct sbus_dev *floppy_sdev = NULL; | 46 | static struct of_device *floppy_op = NULL; |
54 | 47 | ||
55 | struct sun_floppy_ops { | 48 | struct sun_floppy_ops { |
56 | unsigned char (*fd_inb) (unsigned long port); | 49 | unsigned char (*fd_inb) (unsigned long port); |
@@ -291,12 +284,11 @@ static int sun_fd_eject(int drive) | |||
291 | return 0; | 284 | return 0; |
292 | } | 285 | } |
293 | 286 | ||
294 | #ifdef CONFIG_PCI | 287 | #include <asm/ebus_dma.h> |
295 | #include <asm/ebus.h> | ||
296 | #include <asm/ns87303.h> | 288 | #include <asm/ns87303.h> |
297 | 289 | ||
298 | static struct ebus_dma_info sun_pci_fd_ebus_dma; | 290 | static struct ebus_dma_info sun_pci_fd_ebus_dma; |
299 | static struct pci_dev *sun_pci_ebus_dev; | 291 | static struct device *sun_floppy_dev; |
300 | static int sun_pci_broken_drive = -1; | 292 | static int sun_pci_broken_drive = -1; |
301 | 293 | ||
302 | struct sun_pci_dma_op { | 294 | struct sun_pci_dma_op { |
@@ -377,7 +369,7 @@ static void sun_pci_fd_enable_dma(void) | |||
377 | sun_pci_dma_pending.addr = -1U; | 369 | sun_pci_dma_pending.addr = -1U; |
378 | 370 | ||
379 | sun_pci_dma_current.addr = | 371 | sun_pci_dma_current.addr = |
380 | pci_map_single(sun_pci_ebus_dev, | 372 | dma_map_single(sun_floppy_dev, |
381 | sun_pci_dma_current.buf, | 373 | sun_pci_dma_current.buf, |
382 | sun_pci_dma_current.len, | 374 | sun_pci_dma_current.len, |
383 | sun_pci_dma_current.direction); | 375 | sun_pci_dma_current.direction); |
@@ -394,7 +386,7 @@ static void sun_pci_fd_disable_dma(void) | |||
394 | { | 386 | { |
395 | ebus_dma_enable(&sun_pci_fd_ebus_dma, 0); | 387 | ebus_dma_enable(&sun_pci_fd_ebus_dma, 0); |
396 | if (sun_pci_dma_current.addr != -1U) | 388 | if (sun_pci_dma_current.addr != -1U) |
397 | pci_unmap_single(sun_pci_ebus_dev, | 389 | dma_unmap_single(sun_floppy_dev, |
398 | sun_pci_dma_current.addr, | 390 | sun_pci_dma_current.addr, |
399 | sun_pci_dma_current.len, | 391 | sun_pci_dma_current.len, |
400 | sun_pci_dma_current.direction); | 392 | sun_pci_dma_current.direction); |
@@ -404,9 +396,9 @@ static void sun_pci_fd_disable_dma(void) | |||
404 | static void sun_pci_fd_set_dma_mode(int mode) | 396 | static void sun_pci_fd_set_dma_mode(int mode) |
405 | { | 397 | { |
406 | if (mode == DMA_MODE_WRITE) | 398 | if (mode == DMA_MODE_WRITE) |
407 | sun_pci_dma_pending.direction = PCI_DMA_TODEVICE; | 399 | sun_pci_dma_pending.direction = DMA_TO_DEVICE; |
408 | else | 400 | else |
409 | sun_pci_dma_pending.direction = PCI_DMA_FROMDEVICE; | 401 | sun_pci_dma_pending.direction = DMA_FROM_DEVICE; |
410 | 402 | ||
411 | ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE); | 403 | ebus_dma_prepare(&sun_pci_fd_ebus_dma, mode != DMA_MODE_WRITE); |
412 | } | 404 | } |
@@ -538,80 +530,84 @@ static int sun_pci_fd_test_drive(unsigned long port, int drive) | |||
538 | #undef MSR | 530 | #undef MSR |
539 | #undef DOR | 531 | #undef DOR |
540 | 532 | ||
541 | #endif /* CONFIG_PCI */ | 533 | static int __init ebus_fdthree_p(struct device_node *dp) |
542 | |||
543 | #ifdef CONFIG_PCI | ||
544 | static int __init ebus_fdthree_p(struct linux_ebus_device *edev) | ||
545 | { | 534 | { |
546 | if (!strcmp(edev->prom_node->name, "fdthree")) | 535 | if (!strcmp(dp->name, "fdthree")) |
547 | return 1; | 536 | return 1; |
548 | if (!strcmp(edev->prom_node->name, "floppy")) { | 537 | if (!strcmp(dp->name, "floppy")) { |
549 | const char *compat; | 538 | const char *compat; |
550 | 539 | ||
551 | compat = of_get_property(edev->prom_node, | 540 | compat = of_get_property(dp, "compatible", NULL); |
552 | "compatible", NULL); | ||
553 | if (compat && !strcmp(compat, "fdthree")) | 541 | if (compat && !strcmp(compat, "fdthree")) |
554 | return 1; | 542 | return 1; |
555 | } | 543 | } |
556 | return 0; | 544 | return 0; |
557 | } | 545 | } |
558 | #endif | ||
559 | 546 | ||
560 | static unsigned long __init sun_floppy_init(void) | 547 | static unsigned long __init sun_floppy_init(void) |
561 | { | 548 | { |
562 | char state[128]; | ||
563 | struct sbus_bus *bus; | ||
564 | struct sbus_dev *sdev = NULL; | ||
565 | static int initialized = 0; | 549 | static int initialized = 0; |
550 | struct device_node *dp; | ||
551 | struct of_device *op; | ||
552 | const char *prop; | ||
553 | char state[128]; | ||
566 | 554 | ||
567 | if (initialized) | 555 | if (initialized) |
568 | return sun_floppy_types[0]; | 556 | return sun_floppy_types[0]; |
569 | initialized = 1; | 557 | initialized = 1; |
570 | 558 | ||
571 | for_all_sbusdev (sdev, bus) { | 559 | op = NULL; |
572 | if (!strcmp(sdev->prom_name, "SUNW,fdtwo")) | 560 | |
561 | for_each_node_by_name(dp, "SUNW,fdtwo") { | ||
562 | if (strcmp(dp->parent->name, "sbus")) | ||
563 | continue; | ||
564 | op = of_find_device_by_node(dp); | ||
565 | if (op) | ||
573 | break; | 566 | break; |
574 | } | 567 | } |
575 | if(sdev) { | 568 | if (op) { |
576 | floppy_sdev = sdev; | 569 | floppy_op = op; |
577 | FLOPPY_IRQ = sdev->irqs[0]; | 570 | FLOPPY_IRQ = op->irqs[0]; |
578 | } else { | 571 | } else { |
579 | #ifdef CONFIG_PCI | 572 | struct device_node *ebus_dp; |
580 | struct linux_ebus *ebus; | ||
581 | struct linux_ebus_device *edev = NULL; | ||
582 | unsigned long config = 0; | ||
583 | void __iomem *auxio_reg; | 573 | void __iomem *auxio_reg; |
584 | const char *state_prop; | 574 | const char *state_prop; |
575 | unsigned long config; | ||
585 | 576 | ||
586 | for_each_ebus(ebus) { | 577 | dp = NULL; |
587 | for_each_ebusdev(edev, ebus) { | 578 | for_each_node_by_name(ebus_dp, "ebus") { |
588 | if (ebus_fdthree_p(edev)) | 579 | for (dp = ebus_dp->child; dp; dp = dp->sibling) { |
589 | goto ebus_done; | 580 | if (ebus_fdthree_p(dp)) |
581 | goto found_fdthree; | ||
590 | } | 582 | } |
591 | } | 583 | } |
592 | ebus_done: | 584 | found_fdthree: |
593 | if (!edev) | 585 | if (!dp) |
586 | return 0; | ||
587 | |||
588 | op = of_find_device_by_node(dp); | ||
589 | if (!op) | ||
594 | return 0; | 590 | return 0; |
595 | 591 | ||
596 | state_prop = of_get_property(edev->prom_node, "status", NULL); | 592 | state_prop = of_get_property(op->node, "status", NULL); |
597 | if (state_prop && !strncmp(state_prop, "disabled", 8)) | 593 | if (state_prop && !strncmp(state_prop, "disabled", 8)) |
598 | return 0; | 594 | return 0; |
599 | 595 | ||
600 | FLOPPY_IRQ = edev->irqs[0]; | 596 | FLOPPY_IRQ = op->irqs[0]; |
601 | 597 | ||
602 | /* Make sure the high density bit is set, some systems | 598 | /* Make sure the high density bit is set, some systems |
603 | * (most notably Ultra5/Ultra10) come up with it clear. | 599 | * (most notably Ultra5/Ultra10) come up with it clear. |
604 | */ | 600 | */ |
605 | auxio_reg = (void __iomem *) edev->resource[2].start; | 601 | auxio_reg = (void __iomem *) op->resource[2].start; |
606 | writel(readl(auxio_reg)|0x2, auxio_reg); | 602 | writel(readl(auxio_reg)|0x2, auxio_reg); |
607 | 603 | ||
608 | sun_pci_ebus_dev = ebus->self; | 604 | sun_floppy_dev = &op->dev; |
609 | 605 | ||
610 | spin_lock_init(&sun_pci_fd_ebus_dma.lock); | 606 | spin_lock_init(&sun_pci_fd_ebus_dma.lock); |
611 | 607 | ||
612 | /* XXX ioremap */ | 608 | /* XXX ioremap */ |
613 | sun_pci_fd_ebus_dma.regs = (void __iomem *) | 609 | sun_pci_fd_ebus_dma.regs = (void __iomem *) |
614 | edev->resource[1].start; | 610 | op->resource[1].start; |
615 | if (!sun_pci_fd_ebus_dma.regs) | 611 | if (!sun_pci_fd_ebus_dma.regs) |
616 | return 0; | 612 | return 0; |
617 | 613 | ||
@@ -625,7 +621,7 @@ static unsigned long __init sun_floppy_init(void) | |||
625 | return 0; | 621 | return 0; |
626 | 622 | ||
627 | /* XXX ioremap */ | 623 | /* XXX ioremap */ |
628 | sun_fdc = (struct sun_flpy_controller *)edev->resource[0].start; | 624 | sun_fdc = (struct sun_flpy_controller *) op->resource[0].start; |
629 | 625 | ||
630 | sun_fdops.fd_inb = sun_pci_fd_inb; | 626 | sun_fdops.fd_inb = sun_pci_fd_inb; |
631 | sun_fdops.fd_outb = sun_pci_fd_outb; | 627 | sun_fdops.fd_outb = sun_pci_fd_outb; |
@@ -662,12 +658,15 @@ static unsigned long __init sun_floppy_init(void) | |||
662 | /* | 658 | /* |
663 | * Find NS87303 SuperIO config registers (through ecpp). | 659 | * Find NS87303 SuperIO config registers (through ecpp). |
664 | */ | 660 | */ |
665 | for_each_ebus(ebus) { | 661 | config = 0; |
666 | for_each_ebusdev(edev, ebus) { | 662 | for (dp = ebus_dp->child; dp; dp = dp->sibling) { |
667 | if (!strcmp(edev->prom_node->name, "ecpp")) { | 663 | if (!strcmp(dp->name, "ecpp")) { |
668 | config = edev->resource[1].start; | 664 | struct of_device *ecpp_op; |
669 | goto config_done; | 665 | |
670 | } | 666 | ecpp_op = of_find_device_by_node(dp); |
667 | if (ecpp_op) | ||
668 | config = ecpp_op->resource[1].start; | ||
669 | goto config_done; | ||
671 | } | 670 | } |
672 | } | 671 | } |
673 | config_done: | 672 | config_done: |
@@ -716,26 +715,23 @@ static unsigned long __init sun_floppy_init(void) | |||
716 | #endif /* PCI_FDC_SWAP_DRIVES */ | 715 | #endif /* PCI_FDC_SWAP_DRIVES */ |
717 | 716 | ||
718 | return sun_floppy_types[0]; | 717 | return sun_floppy_types[0]; |
719 | #else | ||
720 | return 0; | ||
721 | #endif | ||
722 | } | 718 | } |
723 | prom_getproperty(sdev->prom_node, "status", state, sizeof(state)); | 719 | prop = of_get_property(op->node, "status", NULL); |
724 | if(!strncmp(state, "disabled", 8)) | 720 | if (prop && !strncmp(state, "disabled", 8)) |
725 | return 0; | 721 | return 0; |
726 | 722 | ||
727 | /* | 723 | /* |
728 | * We cannot do sbus_ioremap here: it does request_region, | 724 | * We cannot do of_ioremap here: it does request_region, |
729 | * which the generic floppy driver tries to do once again. | 725 | * which the generic floppy driver tries to do once again. |
730 | * But we must use the sdev resource values as they have | 726 | * But we must use the sdev resource values as they have |
731 | * had parent ranges applied. | 727 | * had parent ranges applied. |
732 | */ | 728 | */ |
733 | sun_fdc = (struct sun_flpy_controller *) | 729 | sun_fdc = (struct sun_flpy_controller *) |
734 | (sdev->resource[0].start + | 730 | (op->resource[0].start + |
735 | ((sdev->resource[0].flags & 0x1ffUL) << 32UL)); | 731 | ((op->resource[0].flags & 0x1ffUL) << 32UL)); |
736 | 732 | ||
737 | /* Last minute sanity check... */ | 733 | /* Last minute sanity check... */ |
738 | if(sbus_readb(&sun_fdc->status1_82077) == 0xff) { | 734 | if (sbus_readb(&sun_fdc->status1_82077) == 0xff) { |
739 | sun_fdc = (struct sun_flpy_controller *)-1; | 735 | sun_fdc = (struct sun_flpy_controller *)-1; |
740 | return 0; | 736 | return 0; |
741 | } | 737 | } |
diff --git a/arch/sparc/include/asm/gpio.h b/arch/sparc/include/asm/gpio.h new file mode 100644 index 000000000000..a0e3ac0af599 --- /dev/null +++ b/arch/sparc/include/asm/gpio.h | |||
@@ -0,0 +1,36 @@ | |||
1 | #ifndef __ASM_SPARC_GPIO_H | ||
2 | #define __ASM_SPARC_GPIO_H | ||
3 | |||
4 | #include <linux/errno.h> | ||
5 | #include <asm-generic/gpio.h> | ||
6 | |||
7 | #ifdef CONFIG_GPIOLIB | ||
8 | |||
9 | static inline int gpio_get_value(unsigned int gpio) | ||
10 | { | ||
11 | return __gpio_get_value(gpio); | ||
12 | } | ||
13 | |||
14 | static inline void gpio_set_value(unsigned int gpio, int value) | ||
15 | { | ||
16 | __gpio_set_value(gpio, value); | ||
17 | } | ||
18 | |||
19 | static inline int gpio_cansleep(unsigned int gpio) | ||
20 | { | ||
21 | return __gpio_cansleep(gpio); | ||
22 | } | ||
23 | |||
24 | static inline int gpio_to_irq(unsigned int gpio) | ||
25 | { | ||
26 | return -ENOSYS; | ||
27 | } | ||
28 | |||
29 | static inline int irq_to_gpio(unsigned int irq) | ||
30 | { | ||
31 | return -EINVAL; | ||
32 | } | ||
33 | |||
34 | #endif /* CONFIG_GPIOLIB */ | ||
35 | |||
36 | #endif /* __ASM_SPARC_GPIO_H */ | ||
diff --git a/arch/sparc/include/asm/io-unit.h b/arch/sparc/include/asm/io-unit.h index 96823b47fd45..01ab2f613e91 100644 --- a/arch/sparc/include/asm/io-unit.h +++ b/arch/sparc/include/asm/io-unit.h | |||
@@ -55,8 +55,4 @@ struct iounit_struct { | |||
55 | #define IOUNIT_BMAPM_START IOUNIT_BMAP2_END | 55 | #define IOUNIT_BMAPM_START IOUNIT_BMAP2_END |
56 | #define IOUNIT_BMAPM_END ((IOUNIT_DMA_SIZE - IOUNIT_DVMA_SIZE) >> PAGE_SHIFT) | 56 | #define IOUNIT_BMAPM_END ((IOUNIT_DMA_SIZE - IOUNIT_DVMA_SIZE) >> PAGE_SHIFT) |
57 | 57 | ||
58 | extern __u32 iounit_map_dma_init(struct sbus_bus *, int); | ||
59 | #define iounit_map_dma_finish(sbus, addr, len) mmu_release_scsi_one(addr, len, sbus) | ||
60 | extern __u32 iounit_map_dma_page(__u32, void *, struct sbus_bus *); | ||
61 | |||
62 | #endif /* !(_SPARC_IO_UNIT_H) */ | 58 | #endif /* !(_SPARC_IO_UNIT_H) */ |
diff --git a/arch/sparc/include/asm/io_32.h b/arch/sparc/include/asm/io_32.h index 10d7da450070..93fe21e02c86 100644 --- a/arch/sparc/include/asm/io_32.h +++ b/arch/sparc/include/asm/io_32.h | |||
@@ -293,14 +293,6 @@ extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); | |||
293 | extern void pci_iounmap(struct pci_dev *dev, void __iomem *); | 293 | extern void pci_iounmap(struct pci_dev *dev, void __iomem *); |
294 | 294 | ||
295 | /* | 295 | /* |
296 | * Bus number may be in res->flags... somewhere. | ||
297 | */ | ||
298 | extern void __iomem *sbus_ioremap(struct resource *res, unsigned long offset, | ||
299 | unsigned long size, char *name); | ||
300 | extern void sbus_iounmap(volatile void __iomem *vaddr, unsigned long size); | ||
301 | |||
302 | |||
303 | /* | ||
304 | * At the moment, we do not use CMOS_READ anywhere outside of rtc.c, | 296 | * At the moment, we do not use CMOS_READ anywhere outside of rtc.c, |
305 | * so rtc_port is static in it. This should not change unless a new | 297 | * so rtc_port is static in it. This should not change unless a new |
306 | * hardware pops up. | 298 | * hardware pops up. |
@@ -308,6 +300,17 @@ extern void sbus_iounmap(volatile void __iomem *vaddr, unsigned long size); | |||
308 | #define RTC_PORT(x) (rtc_port + (x)) | 300 | #define RTC_PORT(x) (rtc_port + (x)) |
309 | #define RTC_ALWAYS_BCD 0 | 301 | #define RTC_ALWAYS_BCD 0 |
310 | 302 | ||
303 | static inline int sbus_can_dma_64bit(void) | ||
304 | { | ||
305 | return 0; /* actually, sparc_cpu_model==sun4d */ | ||
306 | } | ||
307 | static inline int sbus_can_burst64(void) | ||
308 | { | ||
309 | return 0; /* actually, sparc_cpu_model==sun4d */ | ||
310 | } | ||
311 | struct device; | ||
312 | extern void sbus_set_sbus64(struct device *, int); | ||
313 | |||
311 | #endif | 314 | #endif |
312 | 315 | ||
313 | #define __ARCH_HAS_NO_PAGE_ZERO_MAPPED 1 | 316 | #define __ARCH_HAS_NO_PAGE_ZERO_MAPPED 1 |
diff --git a/arch/sparc/include/asm/io_64.h b/arch/sparc/include/asm/io_64.h index 0bff078ffdd0..4aee21dc9c6f 100644 --- a/arch/sparc/include/asm/io_64.h +++ b/arch/sparc/include/asm/io_64.h | |||
@@ -482,18 +482,16 @@ struct pci_dev; | |||
482 | extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); | 482 | extern void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long max); |
483 | extern void pci_iounmap(struct pci_dev *dev, void __iomem *); | 483 | extern void pci_iounmap(struct pci_dev *dev, void __iomem *); |
484 | 484 | ||
485 | /* Similarly for SBUS. */ | 485 | static inline int sbus_can_dma_64bit(void) |
486 | #define sbus_ioremap(__res, __offset, __size, __name) \ | 486 | { |
487 | ({ unsigned long __ret; \ | 487 | return 1; |
488 | __ret = (__res)->start + (((__res)->flags & 0x1ffUL) << 32UL); \ | 488 | } |
489 | __ret += (unsigned long) (__offset); \ | 489 | static inline int sbus_can_burst64(void) |
490 | if (! request_region((__ret), (__size), (__name))) \ | 490 | { |
491 | __ret = 0UL; \ | 491 | return 1; |
492 | (void __iomem *) __ret; \ | 492 | } |
493 | }) | 493 | struct device; |
494 | 494 | extern void sbus_set_sbus64(struct device *, int); | |
495 | #define sbus_iounmap(__addr, __size) \ | ||
496 | release_region((unsigned long)(__addr), (__size)) | ||
497 | 495 | ||
498 | /* | 496 | /* |
499 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem | 497 | * Convert a physical pointer to a virtual kernel pointer for /dev/mem |
diff --git a/arch/sparc/include/asm/iommu_64.h b/arch/sparc/include/asm/iommu_64.h index d7b9afcba08b..caf798b56191 100644 --- a/arch/sparc/include/asm/iommu_64.h +++ b/arch/sparc/include/asm/iommu_64.h | |||
@@ -48,6 +48,9 @@ struct strbuf { | |||
48 | unsigned long strbuf_control; | 48 | unsigned long strbuf_control; |
49 | unsigned long strbuf_pflush; | 49 | unsigned long strbuf_pflush; |
50 | unsigned long strbuf_fsync; | 50 | unsigned long strbuf_fsync; |
51 | unsigned long strbuf_err_stat; | ||
52 | unsigned long strbuf_tag_diag; | ||
53 | unsigned long strbuf_line_diag; | ||
51 | unsigned long strbuf_ctxflush; | 54 | unsigned long strbuf_ctxflush; |
52 | unsigned long strbuf_ctxmatch_base; | 55 | unsigned long strbuf_ctxmatch_base; |
53 | unsigned long strbuf_flushflag_pa; | 56 | unsigned long strbuf_flushflag_pa; |
diff --git a/arch/sparc/include/asm/irq_64.h b/arch/sparc/include/asm/irq_64.h index e3dd9303643d..71673eca3660 100644 --- a/arch/sparc/include/asm/irq_64.h +++ b/arch/sparc/include/asm/irq_64.h | |||
@@ -56,7 +56,6 @@ extern unsigned int sun4u_build_msi(u32 portid, unsigned int *virt_irq_p, | |||
56 | unsigned long imap_base, | 56 | unsigned long imap_base, |
57 | unsigned long iclr_base); | 57 | unsigned long iclr_base); |
58 | extern void sun4u_destroy_msi(unsigned int virt_irq); | 58 | extern void sun4u_destroy_msi(unsigned int virt_irq); |
59 | extern unsigned int sbus_build_irq(void *sbus, unsigned int ino); | ||
60 | 59 | ||
61 | extern unsigned char virt_irq_alloc(unsigned int dev_handle, | 60 | extern unsigned char virt_irq_alloc(unsigned int dev_handle, |
62 | unsigned int dev_ino); | 61 | unsigned int dev_ino); |
diff --git a/arch/sparc/include/asm/mc146818rtc_64.h b/arch/sparc/include/asm/mc146818rtc_64.h index e9c0fcc25c6f..7238d174e0e3 100644 --- a/arch/sparc/include/asm/mc146818rtc_64.h +++ b/arch/sparc/include/asm/mc146818rtc_64.h | |||
@@ -7,12 +7,8 @@ | |||
7 | #include <asm/io.h> | 7 | #include <asm/io.h> |
8 | 8 | ||
9 | #ifndef RTC_PORT | 9 | #ifndef RTC_PORT |
10 | #ifdef CONFIG_PCI | 10 | extern unsigned long cmos_regs; |
11 | extern unsigned long ds1287_regs; | 11 | #define RTC_PORT(x) (cmos_regs + (x)) |
12 | #else | ||
13 | #define ds1287_regs (0UL) | ||
14 | #endif | ||
15 | #define RTC_PORT(x) (ds1287_regs + (x)) | ||
16 | #define RTC_ALWAYS_BCD 0 | 12 | #define RTC_ALWAYS_BCD 0 |
17 | #endif | 13 | #endif |
18 | 14 | ||
@@ -29,6 +25,4 @@ outb_p((addr),RTC_PORT(0)); \ | |||
29 | outb_p((val),RTC_PORT(1)); \ | 25 | outb_p((val),RTC_PORT(1)); \ |
30 | }) | 26 | }) |
31 | 27 | ||
32 | #define RTC_IRQ 8 | ||
33 | |||
34 | #endif /* __ASM_SPARC64_MC146818RTC_H */ | 28 | #endif /* __ASM_SPARC64_MC146818RTC_H */ |
diff --git a/arch/sparc/include/asm/memctrl.h b/arch/sparc/include/asm/memctrl.h new file mode 100644 index 000000000000..4065c56af7b6 --- /dev/null +++ b/arch/sparc/include/asm/memctrl.h | |||
@@ -0,0 +1,9 @@ | |||
1 | #ifndef _SPARC_MEMCTRL_H | ||
2 | #define _SPARC_MEMCTRL_H | ||
3 | |||
4 | typedef int (*dimm_printer_t)(int synd_code, unsigned long paddr, char *buf, int buflen); | ||
5 | |||
6 | int register_dimm_printer(dimm_printer_t func); | ||
7 | void unregister_dimm_printer(dimm_printer_t func); | ||
8 | |||
9 | #endif /* _SPARC_MEMCTRL_H */ | ||
diff --git a/arch/sparc/include/asm/mostek.h b/arch/sparc/include/asm/mostek.h deleted file mode 100644 index 433be3e0a69b..000000000000 --- a/arch/sparc/include/asm/mostek.h +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | #ifndef ___ASM_SPARC_MOSTEK_H | ||
2 | #define ___ASM_SPARC_MOSTEK_H | ||
3 | #if defined(__sparc__) && defined(__arch64__) | ||
4 | #include <asm/mostek_64.h> | ||
5 | #else | ||
6 | #include <asm/mostek_32.h> | ||
7 | #endif | ||
8 | #endif | ||
diff --git a/arch/sparc/include/asm/mostek_32.h b/arch/sparc/include/asm/mostek_32.h deleted file mode 100644 index a99590c4c507..000000000000 --- a/arch/sparc/include/asm/mostek_32.h +++ /dev/null | |||
@@ -1,171 +0,0 @@ | |||
1 | /* | ||
2 | * mostek.h: Describes the various Mostek time of day clock registers. | ||
3 | * | ||
4 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
5 | * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) | ||
6 | * Added intersil code 05/25/98 Chris Davis (cdavis@cois.on.ca) | ||
7 | */ | ||
8 | |||
9 | #ifndef _SPARC_MOSTEK_H | ||
10 | #define _SPARC_MOSTEK_H | ||
11 | |||
12 | #include <asm/idprom.h> | ||
13 | #include <asm/io.h> | ||
14 | |||
15 | /* M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ) | ||
16 | * | ||
17 | * Data | ||
18 | * Address Function | ||
19 | * Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0 | ||
20 | * 7ff - - - - - - - - Year 00-99 | ||
21 | * 7fe 0 0 0 - - - - - Month 01-12 | ||
22 | * 7fd 0 0 - - - - - - Date 01-31 | ||
23 | * 7fc 0 FT 0 0 0 - - - Day 01-07 | ||
24 | * 7fb KS 0 - - - - - - Hours 00-23 | ||
25 | * 7fa 0 - - - - - - - Minutes 00-59 | ||
26 | * 7f9 ST - - - - - - - Seconds 00-59 | ||
27 | * 7f8 W R S - - - - - Control | ||
28 | * | ||
29 | * * ST is STOP BIT | ||
30 | * * W is WRITE BIT | ||
31 | * * R is READ BIT | ||
32 | * * S is SIGN BIT | ||
33 | * * FT is FREQ TEST BIT | ||
34 | * * KS is KICK START BIT | ||
35 | */ | ||
36 | |||
37 | /* The Mostek 48t02 real time clock and NVRAM chip. The registers | ||
38 | * other than the control register are in binary coded decimal. Some | ||
39 | * control bits also live outside the control register. | ||
40 | */ | ||
41 | #define mostek_read(_addr) readb(_addr) | ||
42 | #define mostek_write(_addr,_val) writeb(_val, _addr) | ||
43 | #define MOSTEK_EEPROM 0x0000UL | ||
44 | #define MOSTEK_IDPROM 0x07d8UL | ||
45 | #define MOSTEK_CREG 0x07f8UL | ||
46 | #define MOSTEK_SEC 0x07f9UL | ||
47 | #define MOSTEK_MIN 0x07faUL | ||
48 | #define MOSTEK_HOUR 0x07fbUL | ||
49 | #define MOSTEK_DOW 0x07fcUL | ||
50 | #define MOSTEK_DOM 0x07fdUL | ||
51 | #define MOSTEK_MONTH 0x07feUL | ||
52 | #define MOSTEK_YEAR 0x07ffUL | ||
53 | |||
54 | struct mostek48t02 { | ||
55 | volatile char eeprom[2008]; /* This is the eeprom, don't touch! */ | ||
56 | struct idprom idprom; /* The idprom lives here. */ | ||
57 | volatile unsigned char creg; /* Control register */ | ||
58 | volatile unsigned char sec; /* Seconds (0-59) */ | ||
59 | volatile unsigned char min; /* Minutes (0-59) */ | ||
60 | volatile unsigned char hour; /* Hour (0-23) */ | ||
61 | volatile unsigned char dow; /* Day of the week (1-7) */ | ||
62 | volatile unsigned char dom; /* Day of the month (1-31) */ | ||
63 | volatile unsigned char month; /* Month of year (1-12) */ | ||
64 | volatile unsigned char year; /* Year (0-99) */ | ||
65 | }; | ||
66 | |||
67 | extern spinlock_t mostek_lock; | ||
68 | extern void __iomem *mstk48t02_regs; | ||
69 | |||
70 | /* Control register values. */ | ||
71 | #define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */ | ||
72 | #define MSTK_CREG_READ 0x40 /* Stop updates to allow a clean read. */ | ||
73 | #define MSTK_CREG_SIGN 0x20 /* Slow/speed clock in calibration mode. */ | ||
74 | |||
75 | /* Control bits that live in the other registers. */ | ||
76 | #define MSTK_STOP 0x80 /* Stop the clock oscillator. (sec) */ | ||
77 | #define MSTK_KICK_START 0x80 /* Kick start the clock chip. (hour) */ | ||
78 | #define MSTK_FREQ_TEST 0x40 /* Frequency test mode. (day) */ | ||
79 | |||
80 | #define MSTK_YEAR_ZERO 1968 /* If year reg has zero, it is 1968. */ | ||
81 | #define MSTK_CVT_YEAR(yr) ((yr) + MSTK_YEAR_ZERO) | ||
82 | |||
83 | /* Masks that define how much space each value takes up. */ | ||
84 | #define MSTK_SEC_MASK 0x7f | ||
85 | #define MSTK_MIN_MASK 0x7f | ||
86 | #define MSTK_HOUR_MASK 0x3f | ||
87 | #define MSTK_DOW_MASK 0x07 | ||
88 | #define MSTK_DOM_MASK 0x3f | ||
89 | #define MSTK_MONTH_MASK 0x1f | ||
90 | #define MSTK_YEAR_MASK 0xffU | ||
91 | |||
92 | /* Binary coded decimal conversion macros. */ | ||
93 | #define MSTK_REGVAL_TO_DECIMAL(x) (((x) & 0x0F) + 0x0A * ((x) >> 0x04)) | ||
94 | #define MSTK_DECIMAL_TO_REGVAL(x) ((((x) / 0x0A) << 0x04) + ((x) % 0x0A)) | ||
95 | |||
96 | /* Generic register set and get macros for internal use. */ | ||
97 | #define MSTK_GET(regs,var,mask) (MSTK_REGVAL_TO_DECIMAL(((struct mostek48t02 *)regs)->var & MSTK_ ## mask ## _MASK)) | ||
98 | #define MSTK_SET(regs,var,value,mask) do { ((struct mostek48t02 *)regs)->var &= ~(MSTK_ ## mask ## _MASK); ((struct mostek48t02 *)regs)->var |= MSTK_DECIMAL_TO_REGVAL(value) & (MSTK_ ## mask ## _MASK); } while (0) | ||
99 | |||
100 | /* Macros to make register access easier on our fingers. These give you | ||
101 | * the decimal value of the register requested if applicable. You pass | ||
102 | * the a pointer to a 'struct mostek48t02'. | ||
103 | */ | ||
104 | #define MSTK_REG_CREG(regs) (((struct mostek48t02 *)regs)->creg) | ||
105 | #define MSTK_REG_SEC(regs) MSTK_GET(regs,sec,SEC) | ||
106 | #define MSTK_REG_MIN(regs) MSTK_GET(regs,min,MIN) | ||
107 | #define MSTK_REG_HOUR(regs) MSTK_GET(regs,hour,HOUR) | ||
108 | #define MSTK_REG_DOW(regs) MSTK_GET(regs,dow,DOW) | ||
109 | #define MSTK_REG_DOM(regs) MSTK_GET(regs,dom,DOM) | ||
110 | #define MSTK_REG_MONTH(regs) MSTK_GET(regs,month,MONTH) | ||
111 | #define MSTK_REG_YEAR(regs) MSTK_GET(regs,year,YEAR) | ||
112 | |||
113 | #define MSTK_SET_REG_SEC(regs,value) MSTK_SET(regs,sec,value,SEC) | ||
114 | #define MSTK_SET_REG_MIN(regs,value) MSTK_SET(regs,min,value,MIN) | ||
115 | #define MSTK_SET_REG_HOUR(regs,value) MSTK_SET(regs,hour,value,HOUR) | ||
116 | #define MSTK_SET_REG_DOW(regs,value) MSTK_SET(regs,dow,value,DOW) | ||
117 | #define MSTK_SET_REG_DOM(regs,value) MSTK_SET(regs,dom,value,DOM) | ||
118 | #define MSTK_SET_REG_MONTH(regs,value) MSTK_SET(regs,month,value,MONTH) | ||
119 | #define MSTK_SET_REG_YEAR(regs,value) MSTK_SET(regs,year,value,YEAR) | ||
120 | |||
121 | |||
122 | /* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the | ||
123 | * same (basically) layout of the 48t02 chip except for the extra | ||
124 | * NVRAM on board (8 KB against the 48t02's 2 KB). | ||
125 | */ | ||
126 | struct mostek48t08 { | ||
127 | char offset[6*1024]; /* Magic things may be here, who knows? */ | ||
128 | struct mostek48t02 regs; /* Here is what we are interested in. */ | ||
129 | }; | ||
130 | |||
131 | #ifdef CONFIG_SUN4 | ||
132 | enum sparc_clock_type { MSTK48T02, MSTK48T08, \ | ||
133 | INTERSIL, MSTK_INVALID }; | ||
134 | #else | ||
135 | enum sparc_clock_type { MSTK48T02, MSTK48T08, \ | ||
136 | MSTK_INVALID }; | ||
137 | #endif | ||
138 | |||
139 | #ifdef CONFIG_SUN4 | ||
140 | /* intersil on a sun 4/260 code data from harris doc */ | ||
141 | struct intersil_dt { | ||
142 | volatile unsigned char int_csec; | ||
143 | volatile unsigned char int_hour; | ||
144 | volatile unsigned char int_min; | ||
145 | volatile unsigned char int_sec; | ||
146 | volatile unsigned char int_month; | ||
147 | volatile unsigned char int_day; | ||
148 | volatile unsigned char int_year; | ||
149 | volatile unsigned char int_dow; | ||
150 | }; | ||
151 | |||
152 | struct intersil { | ||
153 | struct intersil_dt clk; | ||
154 | struct intersil_dt cmp; | ||
155 | volatile unsigned char int_intr_reg; | ||
156 | volatile unsigned char int_cmd_reg; | ||
157 | }; | ||
158 | |||
159 | #define INTERSIL_STOP 0x0 | ||
160 | #define INTERSIL_START 0x8 | ||
161 | #define INTERSIL_INTR_DISABLE 0x0 | ||
162 | #define INTERSIL_INTR_ENABLE 0x10 | ||
163 | #define INTERSIL_32K 0x0 | ||
164 | #define INTERSIL_NORMAL 0x0 | ||
165 | #define INTERSIL_24H 0x4 | ||
166 | #define INTERSIL_INT_100HZ 0x2 | ||
167 | |||
168 | /* end of intersil info */ | ||
169 | #endif | ||
170 | |||
171 | #endif /* !(_SPARC_MOSTEK_H) */ | ||
diff --git a/arch/sparc/include/asm/mostek_64.h b/arch/sparc/include/asm/mostek_64.h deleted file mode 100644 index c5652de2ace2..000000000000 --- a/arch/sparc/include/asm/mostek_64.h +++ /dev/null | |||
@@ -1,143 +0,0 @@ | |||
1 | /* mostek.h: Describes the various Mostek time of day clock registers. | ||
2 | * | ||
3 | * Copyright (C) 1995 David S. Miller (davem@davemloft.net) | ||
4 | * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) | ||
5 | */ | ||
6 | |||
7 | #ifndef _SPARC64_MOSTEK_H | ||
8 | #define _SPARC64_MOSTEK_H | ||
9 | |||
10 | #include <asm/idprom.h> | ||
11 | |||
12 | /* M48T02 Register Map (adapted from Sun NVRAM/Hostid FAQ) | ||
13 | * | ||
14 | * Data | ||
15 | * Address Function | ||
16 | * Bit 7 Bit 6 Bit 5 Bit 4Bit 3 Bit 2 Bit 1 Bit 0 | ||
17 | * 7ff - - - - - - - - Year 00-99 | ||
18 | * 7fe 0 0 0 - - - - - Month 01-12 | ||
19 | * 7fd 0 0 - - - - - - Date 01-31 | ||
20 | * 7fc 0 FT 0 0 0 - - - Day 01-07 | ||
21 | * 7fb KS 0 - - - - - - Hours 00-23 | ||
22 | * 7fa 0 - - - - - - - Minutes 00-59 | ||
23 | * 7f9 ST - - - - - - - Seconds 00-59 | ||
24 | * 7f8 W R S - - - - - Control | ||
25 | * | ||
26 | * * ST is STOP BIT | ||
27 | * * W is WRITE BIT | ||
28 | * * R is READ BIT | ||
29 | * * S is SIGN BIT | ||
30 | * * FT is FREQ TEST BIT | ||
31 | * * KS is KICK START BIT | ||
32 | */ | ||
33 | |||
34 | /* The Mostek 48t02 real time clock and NVRAM chip. The registers | ||
35 | * other than the control register are in binary coded decimal. Some | ||
36 | * control bits also live outside the control register. | ||
37 | * | ||
38 | * We now deal with physical addresses for I/O to the chip. -DaveM | ||
39 | */ | ||
40 | static inline u8 mostek_read(void __iomem *addr) | ||
41 | { | ||
42 | u8 ret; | ||
43 | |||
44 | __asm__ __volatile__("lduba [%1] %2, %0" | ||
45 | : "=r" (ret) | ||
46 | : "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)); | ||
47 | return ret; | ||
48 | } | ||
49 | |||
50 | static inline void mostek_write(void __iomem *addr, u8 val) | ||
51 | { | ||
52 | __asm__ __volatile__("stba %0, [%1] %2" | ||
53 | : /* no outputs */ | ||
54 | : "r" (val), "r" (addr), "i" (ASI_PHYS_BYPASS_EC_E)); | ||
55 | } | ||
56 | |||
57 | #define MOSTEK_EEPROM 0x0000UL | ||
58 | #define MOSTEK_IDPROM 0x07d8UL | ||
59 | #define MOSTEK_CREG 0x07f8UL | ||
60 | #define MOSTEK_SEC 0x07f9UL | ||
61 | #define MOSTEK_MIN 0x07faUL | ||
62 | #define MOSTEK_HOUR 0x07fbUL | ||
63 | #define MOSTEK_DOW 0x07fcUL | ||
64 | #define MOSTEK_DOM 0x07fdUL | ||
65 | #define MOSTEK_MONTH 0x07feUL | ||
66 | #define MOSTEK_YEAR 0x07ffUL | ||
67 | |||
68 | extern spinlock_t mostek_lock; | ||
69 | extern void __iomem *mstk48t02_regs; | ||
70 | |||
71 | /* Control register values. */ | ||
72 | #define MSTK_CREG_WRITE 0x80 /* Must set this before placing values. */ | ||
73 | #define MSTK_CREG_READ 0x40 /* Stop updates to allow a clean read. */ | ||
74 | #define MSTK_CREG_SIGN 0x20 /* Slow/speed clock in calibration mode. */ | ||
75 | |||
76 | /* Control bits that live in the other registers. */ | ||
77 | #define MSTK_STOP 0x80 /* Stop the clock oscillator. (sec) */ | ||
78 | #define MSTK_KICK_START 0x80 /* Kick start the clock chip. (hour) */ | ||
79 | #define MSTK_FREQ_TEST 0x40 /* Frequency test mode. (day) */ | ||
80 | |||
81 | #define MSTK_YEAR_ZERO 1968 /* If year reg has zero, it is 1968. */ | ||
82 | #define MSTK_CVT_YEAR(yr) ((yr) + MSTK_YEAR_ZERO) | ||
83 | |||
84 | /* Masks that define how much space each value takes up. */ | ||
85 | #define MSTK_SEC_MASK 0x7f | ||
86 | #define MSTK_MIN_MASK 0x7f | ||
87 | #define MSTK_HOUR_MASK 0x3f | ||
88 | #define MSTK_DOW_MASK 0x07 | ||
89 | #define MSTK_DOM_MASK 0x3f | ||
90 | #define MSTK_MONTH_MASK 0x1f | ||
91 | #define MSTK_YEAR_MASK 0xffU | ||
92 | |||
93 | /* Binary coded decimal conversion macros. */ | ||
94 | #define MSTK_REGVAL_TO_DECIMAL(x) (((x) & 0x0F) + 0x0A * ((x) >> 0x04)) | ||
95 | #define MSTK_DECIMAL_TO_REGVAL(x) ((((x) / 0x0A) << 0x04) + ((x) % 0x0A)) | ||
96 | |||
97 | /* Generic register set and get macros for internal use. */ | ||
98 | #define MSTK_GET(regs,name) \ | ||
99 | (MSTK_REGVAL_TO_DECIMAL(mostek_read(regs + MOSTEK_ ## name) & MSTK_ ## name ## _MASK)) | ||
100 | #define MSTK_SET(regs,name,value) \ | ||
101 | do { u8 __val = mostek_read(regs + MOSTEK_ ## name); \ | ||
102 | __val &= ~(MSTK_ ## name ## _MASK); \ | ||
103 | __val |= (MSTK_DECIMAL_TO_REGVAL(value) & \ | ||
104 | (MSTK_ ## name ## _MASK)); \ | ||
105 | mostek_write(regs + MOSTEK_ ## name, __val); \ | ||
106 | } while(0) | ||
107 | |||
108 | /* Macros to make register access easier on our fingers. These give you | ||
109 | * the decimal value of the register requested if applicable. You pass | ||
110 | * the a pointer to a 'struct mostek48t02'. | ||
111 | */ | ||
112 | #define MSTK_REG_CREG(regs) (mostek_read((regs) + MOSTEK_CREG)) | ||
113 | #define MSTK_REG_SEC(regs) MSTK_GET(regs,SEC) | ||
114 | #define MSTK_REG_MIN(regs) MSTK_GET(regs,MIN) | ||
115 | #define MSTK_REG_HOUR(regs) MSTK_GET(regs,HOUR) | ||
116 | #define MSTK_REG_DOW(regs) MSTK_GET(regs,DOW) | ||
117 | #define MSTK_REG_DOM(regs) MSTK_GET(regs,DOM) | ||
118 | #define MSTK_REG_MONTH(regs) MSTK_GET(regs,MONTH) | ||
119 | #define MSTK_REG_YEAR(regs) MSTK_GET(regs,YEAR) | ||
120 | |||
121 | #define MSTK_SET_REG_SEC(regs,value) MSTK_SET(regs,SEC,value) | ||
122 | #define MSTK_SET_REG_MIN(regs,value) MSTK_SET(regs,MIN,value) | ||
123 | #define MSTK_SET_REG_HOUR(regs,value) MSTK_SET(regs,HOUR,value) | ||
124 | #define MSTK_SET_REG_DOW(regs,value) MSTK_SET(regs,DOW,value) | ||
125 | #define MSTK_SET_REG_DOM(regs,value) MSTK_SET(regs,DOM,value) | ||
126 | #define MSTK_SET_REG_MONTH(regs,value) MSTK_SET(regs,MONTH,value) | ||
127 | #define MSTK_SET_REG_YEAR(regs,value) MSTK_SET(regs,YEAR,value) | ||
128 | |||
129 | |||
130 | /* The Mostek 48t08 clock chip. Found on Sun4m's I think. It has the | ||
131 | * same (basically) layout of the 48t02 chip except for the extra | ||
132 | * NVRAM on board (8 KB against the 48t02's 2 KB). | ||
133 | */ | ||
134 | #define MOSTEK_48T08_OFFSET 0x0000UL /* Lower NVRAM portions */ | ||
135 | #define MOSTEK_48T08_48T02 0x1800UL /* Offset to 48T02 chip */ | ||
136 | |||
137 | /* SUN5 systems usually have 48t59 model clock chipsets. But we keep the older | ||
138 | * clock chip definitions around just in case. | ||
139 | */ | ||
140 | #define MOSTEK_48T59_OFFSET 0x0000UL /* Lower NVRAM portions */ | ||
141 | #define MOSTEK_48T59_48T02 0x1800UL /* Offset to 48T02 chip */ | ||
142 | |||
143 | #endif /* !(_SPARC64_MOSTEK_H) */ | ||
diff --git a/arch/sparc/include/asm/obio.h b/arch/sparc/include/asm/obio.h index 1a7544ceb574..4ade0c8a2c79 100644 --- a/arch/sparc/include/asm/obio.h +++ b/arch/sparc/include/asm/obio.h | |||
@@ -155,17 +155,6 @@ static inline void bw_set_ctrl(int cpu, unsigned ctrl) | |||
155 | "i" (ASI_M_CTL)); | 155 | "i" (ASI_M_CTL)); |
156 | } | 156 | } |
157 | 157 | ||
158 | extern unsigned char cpu_leds[32]; | ||
159 | |||
160 | static inline void show_leds(int cpuid) | ||
161 | { | ||
162 | cpuid &= 0x1e; | ||
163 | __asm__ __volatile__ ("stba %0, [%1] %2" : : | ||
164 | "r" ((cpu_leds[cpuid] << 4) | cpu_leds[cpuid+1]), | ||
165 | "r" (ECSR_BASE(cpuid) | BB_LEDS), | ||
166 | "i" (ASI_M_CTL)); | ||
167 | } | ||
168 | |||
169 | static inline unsigned cc_get_ipen(void) | 158 | static inline unsigned cc_get_ipen(void) |
170 | { | 159 | { |
171 | unsigned pending; | 160 | unsigned pending; |
diff --git a/arch/sparc/include/asm/of_device.h b/arch/sparc/include/asm/of_device.h index bba777a416d3..a5d9811f9697 100644 --- a/arch/sparc/include/asm/of_device.h +++ b/arch/sparc/include/asm/of_device.h | |||
@@ -30,6 +30,8 @@ struct of_device | |||
30 | extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); | 30 | extern void __iomem *of_ioremap(struct resource *res, unsigned long offset, unsigned long size, char *name); |
31 | extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size); | 31 | extern void of_iounmap(struct resource *res, void __iomem *base, unsigned long size); |
32 | 32 | ||
33 | extern void of_propagate_archdata(struct of_device *bus); | ||
34 | |||
33 | /* This is just here during the transition */ | 35 | /* This is just here during the transition */ |
34 | #include <linux/of_platform.h> | 36 | #include <linux/of_platform.h> |
35 | 37 | ||
diff --git a/arch/sparc/include/asm/of_platform.h b/arch/sparc/include/asm/of_platform.h index 2348ab90a57c..90da99059f83 100644 --- a/arch/sparc/include/asm/of_platform.h +++ b/arch/sparc/include/asm/of_platform.h | |||
@@ -13,9 +13,6 @@ | |||
13 | * | 13 | * |
14 | */ | 14 | */ |
15 | 15 | ||
16 | extern struct bus_type ebus_bus_type; | ||
17 | extern struct bus_type sbus_bus_type; | ||
18 | |||
19 | #define of_bus_type of_platform_bus_type /* for compatibility */ | 16 | #define of_bus_type of_platform_bus_type /* for compatibility */ |
20 | 17 | ||
21 | #endif | 18 | #endif |
diff --git a/arch/sparc/include/asm/oplib_32.h b/arch/sparc/include/asm/oplib_32.h index b2631da259e0..699da05235c8 100644 --- a/arch/sparc/include/asm/oplib_32.h +++ b/arch/sparc/include/asm/oplib_32.h | |||
@@ -21,7 +21,6 @@ enum prom_major_version { | |||
21 | PROM_V2, /* sun4c and early sun4m V2 prom */ | 21 | PROM_V2, /* sun4c and early sun4m V2 prom */ |
22 | PROM_V3, /* sun4m and later, up to sun4d/sun4e machines V3 */ | 22 | PROM_V3, /* sun4m and later, up to sun4d/sun4e machines V3 */ |
23 | PROM_P1275, /* IEEE compliant ISA based Sun PROM, only sun4u */ | 23 | PROM_P1275, /* IEEE compliant ISA based Sun PROM, only sun4u */ |
24 | PROM_SUN4, /* Old sun4 proms are totally different, but we'll shoehorn it to make it fit */ | ||
25 | }; | 24 | }; |
26 | 25 | ||
27 | extern enum prom_major_version prom_vers; | 26 | extern enum prom_major_version prom_vers; |
diff --git a/arch/sparc/include/asm/page_32.h b/arch/sparc/include/asm/page_32.h index cf5fb70ca1c1..d1806edc0958 100644 --- a/arch/sparc/include/asm/page_32.h +++ b/arch/sparc/include/asm/page_32.h | |||
@@ -8,11 +8,8 @@ | |||
8 | #ifndef _SPARC_PAGE_H | 8 | #ifndef _SPARC_PAGE_H |
9 | #define _SPARC_PAGE_H | 9 | #define _SPARC_PAGE_H |
10 | 10 | ||
11 | #ifdef CONFIG_SUN4 | ||
12 | #define PAGE_SHIFT 13 | ||
13 | #else | ||
14 | #define PAGE_SHIFT 12 | 11 | #define PAGE_SHIFT 12 |
15 | #endif | 12 | |
16 | #ifndef __ASSEMBLY__ | 13 | #ifndef __ASSEMBLY__ |
17 | /* I have my suspicions... -DaveM */ | 14 | /* I have my suspicions... -DaveM */ |
18 | #define PAGE_SIZE (1UL << PAGE_SHIFT) | 15 | #define PAGE_SIZE (1UL << PAGE_SHIFT) |
diff --git a/arch/sparc/include/asm/page_64.h b/arch/sparc/include/asm/page_64.h index b579b910ef51..4274ed13ddb2 100644 --- a/arch/sparc/include/asm/page_64.h +++ b/arch/sparc/include/asm/page_64.h | |||
@@ -38,6 +38,8 @@ | |||
38 | 38 | ||
39 | #ifndef __ASSEMBLY__ | 39 | #ifndef __ASSEMBLY__ |
40 | 40 | ||
41 | #define WANT_PAGE_VIRTUAL | ||
42 | |||
41 | extern void _clear_page(void *page); | 43 | extern void _clear_page(void *page); |
42 | #define clear_page(X) _clear_page((void *)(X)) | 44 | #define clear_page(X) _clear_page((void *)(X)) |
43 | struct page; | 45 | struct page; |
diff --git a/arch/sparc/include/asm/parport.h b/arch/sparc/include/asm/parport.h index d9830621c906..dff3f0253aa8 100644 --- a/arch/sparc/include/asm/parport.h +++ b/arch/sparc/include/asm/parport.h | |||
@@ -8,7 +8,7 @@ | |||
8 | 8 | ||
9 | #include <linux/of_device.h> | 9 | #include <linux/of_device.h> |
10 | 10 | ||
11 | #include <asm/ebus.h> | 11 | #include <asm/ebus_dma.h> |
12 | #include <asm/ns87303.h> | 12 | #include <asm/ns87303.h> |
13 | #include <asm/prom.h> | 13 | #include <asm/prom.h> |
14 | 14 | ||
@@ -215,7 +215,7 @@ static int __devexit ecpp_remove(struct of_device *op) | |||
215 | return 0; | 215 | return 0; |
216 | } | 216 | } |
217 | 217 | ||
218 | static struct of_device_id ecpp_match[] = { | 218 | static const struct of_device_id ecpp_match[] = { |
219 | { | 219 | { |
220 | .name = "ecpp", | 220 | .name = "ecpp", |
221 | }, | 221 | }, |
diff --git a/arch/sparc/include/asm/pci_32.h b/arch/sparc/include/asm/pci_32.h index 0ee949d220c0..b41c4c198159 100644 --- a/arch/sparc/include/asm/pci_32.h +++ b/arch/sparc/include/asm/pci_32.h | |||
@@ -3,6 +3,8 @@ | |||
3 | 3 | ||
4 | #ifdef __KERNEL__ | 4 | #ifdef __KERNEL__ |
5 | 5 | ||
6 | #include <linux/dma-mapping.h> | ||
7 | |||
6 | /* Can be used to override the logic in pci_scan_bus for skipping | 8 | /* Can be used to override the logic in pci_scan_bus for skipping |
7 | * already-configured bus numbers - to be used for buggy BIOSes | 9 | * already-configured bus numbers - to be used for buggy BIOSes |
8 | * or architectures with incomplete PCI setup by the loader. | 10 | * or architectures with incomplete PCI setup by the loader. |
diff --git a/arch/sparc/include/asm/pgtable_32.h b/arch/sparc/include/asm/pgtable_32.h index 08237fda8874..e0cabe790ec1 100644 --- a/arch/sparc/include/asm/pgtable_32.h +++ b/arch/sparc/include/asm/pgtable_32.h | |||
@@ -14,11 +14,7 @@ | |||
14 | #include <linux/spinlock.h> | 14 | #include <linux/spinlock.h> |
15 | #include <linux/swap.h> | 15 | #include <linux/swap.h> |
16 | #include <asm/types.h> | 16 | #include <asm/types.h> |
17 | #ifdef CONFIG_SUN4 | ||
18 | #include <asm/pgtsun4.h> | ||
19 | #else | ||
20 | #include <asm/pgtsun4c.h> | 17 | #include <asm/pgtsun4c.h> |
21 | #endif | ||
22 | #include <asm/pgtsrmmu.h> | 18 | #include <asm/pgtsrmmu.h> |
23 | #include <asm/vac-ops.h> | 19 | #include <asm/vac-ops.h> |
24 | #include <asm/oplib.h> | 20 | #include <asm/oplib.h> |
diff --git a/arch/sparc/include/asm/pgtable_64.h b/arch/sparc/include/asm/pgtable_64.h index bb9ec2cce355..b049abf9902f 100644 --- a/arch/sparc/include/asm/pgtable_64.h +++ b/arch/sparc/include/asm/pgtable_64.h | |||
@@ -770,6 +770,8 @@ extern void sun4v_patch_tlb_handlers(void); | |||
770 | 770 | ||
771 | extern unsigned long cmdline_memory_size; | 771 | extern unsigned long cmdline_memory_size; |
772 | 772 | ||
773 | extern asmlinkage void do_sparc64_fault(struct pt_regs *regs); | ||
774 | |||
773 | #endif /* !(__ASSEMBLY__) */ | 775 | #endif /* !(__ASSEMBLY__) */ |
774 | 776 | ||
775 | #endif /* !(_SPARC64_PGTABLE_H) */ | 777 | #endif /* !(_SPARC64_PGTABLE_H) */ |
diff --git a/arch/sparc/include/asm/prom.h b/arch/sparc/include/asm/prom.h index fd55522481cd..900d44714f8d 100644 --- a/arch/sparc/include/asm/prom.h +++ b/arch/sparc/include/asm/prom.h | |||
@@ -18,6 +18,7 @@ | |||
18 | */ | 18 | */ |
19 | #include <linux/types.h> | 19 | #include <linux/types.h> |
20 | #include <linux/proc_fs.h> | 20 | #include <linux/proc_fs.h> |
21 | #include <linux/mutex.h> | ||
21 | #include <asm/atomic.h> | 22 | #include <asm/atomic.h> |
22 | 23 | ||
23 | #define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 2 | 24 | #define OF_ROOT_NODE_ADDR_CELLS_DEFAULT 2 |
@@ -73,6 +74,7 @@ struct of_irq_controller { | |||
73 | 74 | ||
74 | extern struct device_node *of_find_node_by_cpuid(int cpuid); | 75 | extern struct device_node *of_find_node_by_cpuid(int cpuid); |
75 | extern int of_set_property(struct device_node *node, const char *name, void *val, int len); | 76 | extern int of_set_property(struct device_node *node, const char *name, void *val, int len); |
77 | extern struct mutex of_set_property_mutex; | ||
76 | extern int of_getintprop_default(struct device_node *np, | 78 | extern int of_getintprop_default(struct device_node *np, |
77 | const char *name, | 79 | const char *name, |
78 | int def); | 80 | int def); |
@@ -94,6 +96,16 @@ static inline void of_node_put(struct device_node *node) | |||
94 | { | 96 | { |
95 | } | 97 | } |
96 | 98 | ||
99 | /* These routines are here to provide compatibility with how powerpc | ||
100 | * handles IRQ mapping for OF device nodes. We precompute and permanently | ||
101 | * register them in the of_device objects, whereas powerpc computes them | ||
102 | * on request. | ||
103 | */ | ||
104 | extern unsigned int irq_of_parse_and_map(struct device_node *node, int index); | ||
105 | static inline void irq_dispose_mapping(unsigned int virq) | ||
106 | { | ||
107 | } | ||
108 | |||
97 | /* | 109 | /* |
98 | * NB: This is here while we transition from using asm/prom.h | 110 | * NB: This is here while we transition from using asm/prom.h |
99 | * to linux/of.h | 111 | * to linux/of.h |
diff --git a/arch/sparc/include/asm/ptrace_64.h b/arch/sparc/include/asm/ptrace_64.h index 06e4914c13f4..3d3e9c161d8b 100644 --- a/arch/sparc/include/asm/ptrace_64.h +++ b/arch/sparc/include/asm/ptrace_64.h | |||
@@ -113,6 +113,8 @@ struct sparc_trapf { | |||
113 | 113 | ||
114 | #ifdef __KERNEL__ | 114 | #ifdef __KERNEL__ |
115 | 115 | ||
116 | #include <linux/threads.h> | ||
117 | |||
116 | static inline int pt_regs_trap_type(struct pt_regs *regs) | 118 | static inline int pt_regs_trap_type(struct pt_regs *regs) |
117 | { | 119 | { |
118 | return regs->magic & 0x1ff; | 120 | return regs->magic & 0x1ff; |
@@ -138,6 +140,7 @@ struct global_reg_snapshot { | |||
138 | struct thread_info *thread; | 140 | struct thread_info *thread; |
139 | unsigned long pad1; | 141 | unsigned long pad1; |
140 | }; | 142 | }; |
143 | extern struct global_reg_snapshot global_reg_snapshot[NR_CPUS]; | ||
141 | 144 | ||
142 | #define __ARCH_WANT_COMPAT_SYS_PTRACE | 145 | #define __ARCH_WANT_COMPAT_SYS_PTRACE |
143 | 146 | ||
diff --git a/arch/sparc/include/asm/reboot.h b/arch/sparc/include/asm/reboot.h deleted file mode 100644 index 3f3f43f5be5e..000000000000 --- a/arch/sparc/include/asm/reboot.h +++ /dev/null | |||
@@ -1,6 +0,0 @@ | |||
1 | #ifndef _SPARC64_REBOOT_H | ||
2 | #define _SPARC64_REBOOT_H | ||
3 | |||
4 | extern void machine_alt_power_off(void); | ||
5 | |||
6 | #endif /* _SPARC64_REBOOT_H */ | ||
diff --git a/arch/sparc/include/asm/rtc.h b/arch/sparc/include/asm/rtc.h deleted file mode 100644 index f9ecb1fe2ecd..000000000000 --- a/arch/sparc/include/asm/rtc.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * rtc.h: Definitions for access to the Mostek real time clock | ||
3 | * | ||
4 | * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) | ||
5 | */ | ||
6 | |||
7 | #ifndef _RTC_H | ||
8 | #define _RTC_H | ||
9 | |||
10 | #include <linux/ioctl.h> | ||
11 | |||
12 | struct rtc_time | ||
13 | { | ||
14 | int sec; /* Seconds (0-59) */ | ||
15 | int min; /* Minutes (0-59) */ | ||
16 | int hour; /* Hour (0-23) */ | ||
17 | int dow; /* Day of the week (1-7) */ | ||
18 | int dom; /* Day of the month (1-31) */ | ||
19 | int month; /* Month of year (1-12) */ | ||
20 | int year; /* Year (0-99) */ | ||
21 | }; | ||
22 | |||
23 | #define RTCGET _IOR('p', 20, struct rtc_time) | ||
24 | #define RTCSET _IOW('p', 21, struct rtc_time) | ||
25 | |||
26 | #endif | ||
diff --git a/arch/sparc/include/asm/sbus.h b/arch/sparc/include/asm/sbus.h deleted file mode 100644 index f82481ab44db..000000000000 --- a/arch/sparc/include/asm/sbus.h +++ /dev/null | |||
@@ -1,8 +0,0 @@ | |||
1 | #ifndef ___ASM_SPARC_SBUS_H | ||
2 | #define ___ASM_SPARC_SBUS_H | ||
3 | #if defined(__sparc__) && defined(__arch64__) | ||
4 | #include <asm/sbus_64.h> | ||
5 | #else | ||
6 | #include <asm/sbus_32.h> | ||
7 | #endif | ||
8 | #endif | ||
diff --git a/arch/sparc/include/asm/sbus_32.h b/arch/sparc/include/asm/sbus_32.h deleted file mode 100644 index a7b4fa21931d..000000000000 --- a/arch/sparc/include/asm/sbus_32.h +++ /dev/null | |||
@@ -1,153 +0,0 @@ | |||
1 | /* | ||
2 | * sbus.h: Defines for the Sun SBus. | ||
3 | * | ||
4 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
5 | */ | ||
6 | |||
7 | #ifndef _SPARC_SBUS_H | ||
8 | #define _SPARC_SBUS_H | ||
9 | |||
10 | #include <linux/dma-mapping.h> | ||
11 | #include <linux/ioport.h> | ||
12 | #include <linux/of_device.h> | ||
13 | |||
14 | #include <asm/oplib.h> | ||
15 | #include <asm/prom.h> | ||
16 | #include <asm/scatterlist.h> | ||
17 | |||
18 | /* We scan which devices are on the SBus using the PROM node device | ||
19 | * tree. SBus devices are described in two different ways. You can | ||
20 | * either get an absolute address at which to access the device, or | ||
21 | * you can get a SBus 'slot' number and an offset within that slot. | ||
22 | */ | ||
23 | |||
24 | /* The base address at which to calculate device OBIO addresses. */ | ||
25 | #define SUN_SBUS_BVADDR 0xf8000000 | ||
26 | #define SBUS_OFF_MASK 0x01ffffff | ||
27 | |||
28 | /* These routines are used to calculate device address from slot | ||
29 | * numbers + offsets, and vice versa. | ||
30 | */ | ||
31 | |||
32 | static inline unsigned long sbus_devaddr(int slotnum, unsigned long offset) | ||
33 | { | ||
34 | return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<25)+(offset)); | ||
35 | } | ||
36 | |||
37 | static inline int sbus_dev_slot(unsigned long dev_addr) | ||
38 | { | ||
39 | return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>25); | ||
40 | } | ||
41 | |||
42 | struct sbus_bus; | ||
43 | |||
44 | /* Linux SBUS device tables */ | ||
45 | struct sbus_dev { | ||
46 | struct of_device ofdev; | ||
47 | struct sbus_bus *bus; | ||
48 | struct sbus_dev *next; | ||
49 | struct sbus_dev *child; | ||
50 | struct sbus_dev *parent; | ||
51 | int prom_node; | ||
52 | char prom_name[64]; | ||
53 | int slot; | ||
54 | |||
55 | struct resource resource[PROMREG_MAX]; | ||
56 | |||
57 | struct linux_prom_registers reg_addrs[PROMREG_MAX]; | ||
58 | int num_registers; | ||
59 | |||
60 | struct linux_prom_ranges device_ranges[PROMREG_MAX]; | ||
61 | int num_device_ranges; | ||
62 | |||
63 | unsigned int irqs[4]; | ||
64 | int num_irqs; | ||
65 | }; | ||
66 | #define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) | ||
67 | |||
68 | /* This struct describes the SBus(s) found on this machine. */ | ||
69 | struct sbus_bus { | ||
70 | struct of_device ofdev; | ||
71 | struct sbus_dev *devices; /* Link to devices on this SBus */ | ||
72 | struct sbus_bus *next; /* next SBus, if more than one SBus */ | ||
73 | int prom_node; /* PROM device tree node for this SBus */ | ||
74 | char prom_name[64]; /* Usually "sbus" or "sbi" */ | ||
75 | int clock_freq; | ||
76 | |||
77 | struct linux_prom_ranges sbus_ranges[PROMREG_MAX]; | ||
78 | int num_sbus_ranges; | ||
79 | |||
80 | int devid; | ||
81 | int board; | ||
82 | }; | ||
83 | #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) | ||
84 | |||
85 | extern struct sbus_bus *sbus_root; | ||
86 | |||
87 | static inline int | ||
88 | sbus_is_slave(struct sbus_dev *dev) | ||
89 | { | ||
90 | /* XXX Have to write this for sun4c's */ | ||
91 | return 0; | ||
92 | } | ||
93 | |||
94 | /* Device probing routines could find these handy */ | ||
95 | #define for_each_sbus(bus) \ | ||
96 | for((bus) = sbus_root; (bus); (bus)=(bus)->next) | ||
97 | |||
98 | #define for_each_sbusdev(device, bus) \ | ||
99 | for((device) = (bus)->devices; (device); (device)=(device)->next) | ||
100 | |||
101 | #define for_all_sbusdev(device, bus) \ | ||
102 | for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \ | ||
103 | for ((device) = (bus)->devices; (device); (device) = (device)->next) | ||
104 | |||
105 | /* Driver DVMA interfaces. */ | ||
106 | #define sbus_can_dma_64bit(sdev) (0) /* actually, sparc_cpu_model==sun4d */ | ||
107 | #define sbus_can_burst64(sdev) (0) /* actually, sparc_cpu_model==sun4d */ | ||
108 | extern void sbus_set_sbus64(struct sbus_dev *, int); | ||
109 | extern void sbus_fill_device_irq(struct sbus_dev *); | ||
110 | |||
111 | /* These yield IOMMU mappings in consistent mode. */ | ||
112 | extern void *sbus_alloc_consistent(struct sbus_dev *, long, u32 *dma_addrp); | ||
113 | extern void sbus_free_consistent(struct sbus_dev *, long, void *, u32); | ||
114 | void prom_adjust_ranges(struct linux_prom_ranges *, int, | ||
115 | struct linux_prom_ranges *, int); | ||
116 | |||
117 | #define SBUS_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL | ||
118 | #define SBUS_DMA_TODEVICE DMA_TO_DEVICE | ||
119 | #define SBUS_DMA_FROMDEVICE DMA_FROM_DEVICE | ||
120 | #define SBUS_DMA_NONE DMA_NONE | ||
121 | |||
122 | /* All the rest use streaming mode mappings. */ | ||
123 | extern dma_addr_t sbus_map_single(struct sbus_dev *, void *, size_t, int); | ||
124 | extern void sbus_unmap_single(struct sbus_dev *, dma_addr_t, size_t, int); | ||
125 | extern int sbus_map_sg(struct sbus_dev *, struct scatterlist *, int, int); | ||
126 | extern void sbus_unmap_sg(struct sbus_dev *, struct scatterlist *, int, int); | ||
127 | |||
128 | /* Finally, allow explicit synchronization of streamable mappings. */ | ||
129 | extern void sbus_dma_sync_single_for_cpu(struct sbus_dev *, dma_addr_t, size_t, int); | ||
130 | #define sbus_dma_sync_single sbus_dma_sync_single_for_cpu | ||
131 | extern void sbus_dma_sync_single_for_device(struct sbus_dev *, dma_addr_t, size_t, int); | ||
132 | extern void sbus_dma_sync_sg_for_cpu(struct sbus_dev *, struct scatterlist *, int, int); | ||
133 | #define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu | ||
134 | extern void sbus_dma_sync_sg_for_device(struct sbus_dev *, struct scatterlist *, int, int); | ||
135 | |||
136 | /* Eric Brower (ebrower@usa.net) | ||
137 | * Translate SBus interrupt levels to ino values-- | ||
138 | * this is used when converting sbus "interrupts" OBP | ||
139 | * node values to "intr" node values, and is platform | ||
140 | * dependent. If only we could call OBP with | ||
141 | * "sbus-intr>cpu (sbint -- ino)" from kernel... | ||
142 | * See .../drivers/sbus/sbus.c for details. | ||
143 | */ | ||
144 | BTFIXUPDEF_CALL(unsigned int, sbint_to_irq, struct sbus_dev *sdev, unsigned int) | ||
145 | #define sbint_to_irq(sdev, sbint) BTFIXUP_CALL(sbint_to_irq)(sdev, sbint) | ||
146 | |||
147 | extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); | ||
148 | extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); | ||
149 | extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *); | ||
150 | extern int sbus_arch_preinit(void); | ||
151 | extern void sbus_arch_postinit(void); | ||
152 | |||
153 | #endif /* !(_SPARC_SBUS_H) */ | ||
diff --git a/arch/sparc/include/asm/sbus_64.h b/arch/sparc/include/asm/sbus_64.h deleted file mode 100644 index b606c14343fb..000000000000 --- a/arch/sparc/include/asm/sbus_64.h +++ /dev/null | |||
@@ -1,190 +0,0 @@ | |||
1 | /* sbus.h: Defines for the Sun SBus. | ||
2 | * | ||
3 | * Copyright (C) 1996, 1999, 2007 David S. Miller (davem@davemloft.net) | ||
4 | */ | ||
5 | |||
6 | #ifndef _SPARC64_SBUS_H | ||
7 | #define _SPARC64_SBUS_H | ||
8 | |||
9 | #include <linux/dma-mapping.h> | ||
10 | #include <linux/ioport.h> | ||
11 | #include <linux/of_device.h> | ||
12 | |||
13 | #include <asm/oplib.h> | ||
14 | #include <asm/prom.h> | ||
15 | #include <asm/iommu.h> | ||
16 | #include <asm/scatterlist.h> | ||
17 | |||
18 | /* We scan which devices are on the SBus using the PROM node device | ||
19 | * tree. SBus devices are described in two different ways. You can | ||
20 | * either get an absolute address at which to access the device, or | ||
21 | * you can get a SBus 'slot' number and an offset within that slot. | ||
22 | */ | ||
23 | |||
24 | /* The base address at which to calculate device OBIO addresses. */ | ||
25 | #define SUN_SBUS_BVADDR 0x00000000 | ||
26 | #define SBUS_OFF_MASK 0x0fffffff | ||
27 | |||
28 | /* These routines are used to calculate device address from slot | ||
29 | * numbers + offsets, and vice versa. | ||
30 | */ | ||
31 | |||
32 | static inline unsigned long sbus_devaddr(int slotnum, unsigned long offset) | ||
33 | { | ||
34 | return (unsigned long) (SUN_SBUS_BVADDR+((slotnum)<<28)+(offset)); | ||
35 | } | ||
36 | |||
37 | static inline int sbus_dev_slot(unsigned long dev_addr) | ||
38 | { | ||
39 | return (int) (((dev_addr)-SUN_SBUS_BVADDR)>>28); | ||
40 | } | ||
41 | |||
42 | struct sbus_bus; | ||
43 | |||
44 | /* Linux SBUS device tables */ | ||
45 | struct sbus_dev { | ||
46 | struct of_device ofdev; | ||
47 | struct sbus_bus *bus; | ||
48 | struct sbus_dev *next; | ||
49 | struct sbus_dev *child; | ||
50 | struct sbus_dev *parent; | ||
51 | int prom_node; | ||
52 | char prom_name[64]; | ||
53 | int slot; | ||
54 | |||
55 | struct resource resource[PROMREG_MAX]; | ||
56 | |||
57 | struct linux_prom_registers reg_addrs[PROMREG_MAX]; | ||
58 | int num_registers; | ||
59 | |||
60 | struct linux_prom_ranges device_ranges[PROMREG_MAX]; | ||
61 | int num_device_ranges; | ||
62 | |||
63 | unsigned int irqs[4]; | ||
64 | int num_irqs; | ||
65 | }; | ||
66 | #define to_sbus_device(d) container_of(d, struct sbus_dev, ofdev.dev) | ||
67 | |||
68 | /* This struct describes the SBus(s) found on this machine. */ | ||
69 | struct sbus_bus { | ||
70 | struct of_device ofdev; | ||
71 | struct sbus_dev *devices; /* Tree of SBUS devices */ | ||
72 | struct sbus_bus *next; /* Next SBUS in system */ | ||
73 | int prom_node; /* OBP node of SBUS */ | ||
74 | char prom_name[64]; /* Usually "sbus" or "sbi" */ | ||
75 | int clock_freq; | ||
76 | |||
77 | struct linux_prom_ranges sbus_ranges[PROMREG_MAX]; | ||
78 | int num_sbus_ranges; | ||
79 | |||
80 | int portid; | ||
81 | }; | ||
82 | #define to_sbus(d) container_of(d, struct sbus_bus, ofdev.dev) | ||
83 | |||
84 | extern struct sbus_bus *sbus_root; | ||
85 | |||
86 | /* Device probing routines could find these handy */ | ||
87 | #define for_each_sbus(bus) \ | ||
88 | for((bus) = sbus_root; (bus); (bus)=(bus)->next) | ||
89 | |||
90 | #define for_each_sbusdev(device, bus) \ | ||
91 | for((device) = (bus)->devices; (device); (device)=(device)->next) | ||
92 | |||
93 | #define for_all_sbusdev(device, bus) \ | ||
94 | for ((bus) = sbus_root; (bus); (bus) = (bus)->next) \ | ||
95 | for ((device) = (bus)->devices; (device); (device) = (device)->next) | ||
96 | |||
97 | /* Driver DVMA interfaces. */ | ||
98 | #define sbus_can_dma_64bit(sdev) (1) | ||
99 | #define sbus_can_burst64(sdev) (1) | ||
100 | extern void sbus_set_sbus64(struct sbus_dev *, int); | ||
101 | extern void sbus_fill_device_irq(struct sbus_dev *); | ||
102 | |||
103 | static inline void *sbus_alloc_consistent(struct sbus_dev *sdev , size_t size, | ||
104 | dma_addr_t *dma_handle) | ||
105 | { | ||
106 | return dma_alloc_coherent(&sdev->ofdev.dev, size, | ||
107 | dma_handle, GFP_ATOMIC); | ||
108 | } | ||
109 | |||
110 | static inline void sbus_free_consistent(struct sbus_dev *sdev, size_t size, | ||
111 | void *vaddr, dma_addr_t dma_handle) | ||
112 | { | ||
113 | return dma_free_coherent(&sdev->ofdev.dev, size, vaddr, dma_handle); | ||
114 | } | ||
115 | |||
116 | #define SBUS_DMA_BIDIRECTIONAL DMA_BIDIRECTIONAL | ||
117 | #define SBUS_DMA_TODEVICE DMA_TO_DEVICE | ||
118 | #define SBUS_DMA_FROMDEVICE DMA_FROM_DEVICE | ||
119 | #define SBUS_DMA_NONE DMA_NONE | ||
120 | |||
121 | /* All the rest use streaming mode mappings. */ | ||
122 | static inline dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *ptr, | ||
123 | size_t size, int direction) | ||
124 | { | ||
125 | return dma_map_single(&sdev->ofdev.dev, ptr, size, | ||
126 | (enum dma_data_direction) direction); | ||
127 | } | ||
128 | |||
129 | static inline void sbus_unmap_single(struct sbus_dev *sdev, | ||
130 | dma_addr_t dma_addr, size_t size, | ||
131 | int direction) | ||
132 | { | ||
133 | dma_unmap_single(&sdev->ofdev.dev, dma_addr, size, | ||
134 | (enum dma_data_direction) direction); | ||
135 | } | ||
136 | |||
137 | static inline int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, | ||
138 | int nents, int direction) | ||
139 | { | ||
140 | return dma_map_sg(&sdev->ofdev.dev, sg, nents, | ||
141 | (enum dma_data_direction) direction); | ||
142 | } | ||
143 | |||
144 | static inline void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, | ||
145 | int nents, int direction) | ||
146 | { | ||
147 | dma_unmap_sg(&sdev->ofdev.dev, sg, nents, | ||
148 | (enum dma_data_direction) direction); | ||
149 | } | ||
150 | |||
151 | /* Finally, allow explicit synchronization of streamable mappings. */ | ||
152 | static inline void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, | ||
153 | dma_addr_t dma_handle, | ||
154 | size_t size, int direction) | ||
155 | { | ||
156 | dma_sync_single_for_cpu(&sdev->ofdev.dev, dma_handle, size, | ||
157 | (enum dma_data_direction) direction); | ||
158 | } | ||
159 | #define sbus_dma_sync_single sbus_dma_sync_single_for_cpu | ||
160 | |||
161 | static inline void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, | ||
162 | dma_addr_t dma_handle, | ||
163 | size_t size, int direction) | ||
164 | { | ||
165 | /* No flushing needed to sync cpu writes to the device. */ | ||
166 | } | ||
167 | |||
168 | static inline void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, | ||
169 | struct scatterlist *sg, | ||
170 | int nents, int direction) | ||
171 | { | ||
172 | dma_sync_sg_for_cpu(&sdev->ofdev.dev, sg, nents, | ||
173 | (enum dma_data_direction) direction); | ||
174 | } | ||
175 | #define sbus_dma_sync_sg sbus_dma_sync_sg_for_cpu | ||
176 | |||
177 | static inline void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, | ||
178 | struct scatterlist *sg, | ||
179 | int nents, int direction) | ||
180 | { | ||
181 | /* No flushing needed to sync cpu writes to the device. */ | ||
182 | } | ||
183 | |||
184 | extern void sbus_arch_bus_ranges_init(struct device_node *, struct sbus_bus *); | ||
185 | extern void sbus_setup_iommu(struct sbus_bus *, struct device_node *); | ||
186 | extern void sbus_setup_arch_props(struct sbus_bus *, struct device_node *); | ||
187 | extern int sbus_arch_preinit(void); | ||
188 | extern void sbus_arch_postinit(void); | ||
189 | |||
190 | #endif /* !(_SPARC64_SBUS_H) */ | ||
diff --git a/arch/sparc/include/asm/spinlock_32.h b/arch/sparc/include/asm/spinlock_32.h index de2249b267c6..bf2d532593e3 100644 --- a/arch/sparc/include/asm/spinlock_32.h +++ b/arch/sparc/include/asm/spinlock_32.h | |||
@@ -6,8 +6,6 @@ | |||
6 | #ifndef __SPARC_SPINLOCK_H | 6 | #ifndef __SPARC_SPINLOCK_H |
7 | #define __SPARC_SPINLOCK_H | 7 | #define __SPARC_SPINLOCK_H |
8 | 8 | ||
9 | #include <linux/threads.h> /* For NR_CPUS */ | ||
10 | |||
11 | #ifndef __ASSEMBLY__ | 9 | #ifndef __ASSEMBLY__ |
12 | 10 | ||
13 | #include <asm/psr.h> | 11 | #include <asm/psr.h> |
diff --git a/arch/sparc/include/asm/spinlock_64.h b/arch/sparc/include/asm/spinlock_64.h index 0006fe9f8c7a..120cfe4577c7 100644 --- a/arch/sparc/include/asm/spinlock_64.h +++ b/arch/sparc/include/asm/spinlock_64.h | |||
@@ -6,8 +6,6 @@ | |||
6 | #ifndef __SPARC64_SPINLOCK_H | 6 | #ifndef __SPARC64_SPINLOCK_H |
7 | #define __SPARC64_SPINLOCK_H | 7 | #define __SPARC64_SPINLOCK_H |
8 | 8 | ||
9 | #include <linux/threads.h> /* For NR_CPUS */ | ||
10 | |||
11 | #ifndef __ASSEMBLY__ | 9 | #ifndef __ASSEMBLY__ |
12 | 10 | ||
13 | /* To get debugging spinlocks which detect and catch | 11 | /* To get debugging spinlocks which detect and catch |
diff --git a/arch/sparc/include/asm/sstate.h b/arch/sparc/include/asm/sstate.h deleted file mode 100644 index a7c35dbcb281..000000000000 --- a/arch/sparc/include/asm/sstate.h +++ /dev/null | |||
@@ -1,13 +0,0 @@ | |||
1 | #ifndef _SPARC64_SSTATE_H | ||
2 | #define _SPARC64_SSTATE_H | ||
3 | |||
4 | extern void sstate_booting(void); | ||
5 | extern void sstate_running(void); | ||
6 | extern void sstate_halt(void); | ||
7 | extern void sstate_poweroff(void); | ||
8 | extern void sstate_panic(void); | ||
9 | extern void sstate_reboot(void); | ||
10 | |||
11 | extern void sun4v_sstate_init(void); | ||
12 | |||
13 | #endif /* _SPARC64_SSTATE_H */ | ||
diff --git a/arch/sparc/include/asm/starfire.h b/arch/sparc/include/asm/starfire.h index 07bafd31e33c..d56ce60a5992 100644 --- a/arch/sparc/include/asm/starfire.h +++ b/arch/sparc/include/asm/starfire.h | |||
@@ -12,7 +12,6 @@ | |||
12 | extern int this_is_starfire; | 12 | extern int this_is_starfire; |
13 | 13 | ||
14 | extern void check_if_starfire(void); | 14 | extern void check_if_starfire(void); |
15 | extern void starfire_cpu_setup(void); | ||
16 | extern int starfire_hard_smp_processor_id(void); | 15 | extern int starfire_hard_smp_processor_id(void); |
17 | extern void starfire_hookup(int); | 16 | extern void starfire_hookup(int); |
18 | extern unsigned int starfire_translate(unsigned long imap, unsigned int upaid); | 17 | extern unsigned int starfire_translate(unsigned long imap, unsigned int upaid); |
diff --git a/arch/sparc/include/asm/sun4paddr.h b/arch/sparc/include/asm/sun4paddr.h deleted file mode 100644 index d52985f19f42..000000000000 --- a/arch/sparc/include/asm/sun4paddr.h +++ /dev/null | |||
@@ -1,56 +0,0 @@ | |||
1 | /* | ||
2 | * sun4paddr.h: Various physical addresses on sun4 machines | ||
3 | * | ||
4 | * Copyright (C) 1997 Anton Blanchard (anton@progsoc.uts.edu.au) | ||
5 | * Copyright (C) 1998 Chris Davis (cdavis@cois.on.ca) | ||
6 | * | ||
7 | * Now supports more sun4's | ||
8 | */ | ||
9 | |||
10 | #ifndef _SPARC_SUN4PADDR_H | ||
11 | #define _SPARC_SUN4PADDR_H | ||
12 | |||
13 | #define SUN4_IE_PHYSADDR 0xf5000000 | ||
14 | #define SUN4_UNUSED_PHYSADDR 0 | ||
15 | |||
16 | /* these work for me */ | ||
17 | #define SUN4_200_MEMREG_PHYSADDR 0xf4000000 | ||
18 | #define SUN4_200_CLOCK_PHYSADDR 0xf3000000 | ||
19 | #define SUN4_200_BWTWO_PHYSADDR 0xfd000000 | ||
20 | #define SUN4_200_ETH_PHYSADDR 0xf6000000 | ||
21 | #define SUN4_200_SI_PHYSADDR 0xff200000 | ||
22 | |||
23 | /* these were here before */ | ||
24 | #define SUN4_300_MEMREG_PHYSADDR 0xf4000000 | ||
25 | #define SUN4_300_CLOCK_PHYSADDR 0xf2000000 | ||
26 | #define SUN4_300_TIMER_PHYSADDR 0xef000000 | ||
27 | #define SUN4_300_ETH_PHYSADDR 0xf9000000 | ||
28 | #define SUN4_300_BWTWO_PHYSADDR 0xfb400000 | ||
29 | #define SUN4_300_DMA_PHYSADDR 0xfa001000 | ||
30 | #define SUN4_300_ESP_PHYSADDR 0xfa000000 | ||
31 | |||
32 | /* Are these right? */ | ||
33 | #define SUN4_400_MEMREG_PHYSADDR 0xf4000000 | ||
34 | #define SUN4_400_CLOCK_PHYSADDR 0xf2000000 | ||
35 | #define SUN4_400_TIMER_PHYSADDR 0xef000000 | ||
36 | #define SUN4_400_ETH_PHYSADDR 0xf9000000 | ||
37 | #define SUN4_400_BWTWO_PHYSADDR 0xfb400000 | ||
38 | #define SUN4_400_DMA_PHYSADDR 0xfa001000 | ||
39 | #define SUN4_400_ESP_PHYSADDR 0xfa000000 | ||
40 | |||
41 | /* | ||
42 | these are the actual values set and used in the code. Unused items set | ||
43 | to SUN_UNUSED_PHYSADDR | ||
44 | */ | ||
45 | |||
46 | extern int sun4_memreg_physaddr; /* memory register (ecc?) */ | ||
47 | extern int sun4_clock_physaddr; /* system clock */ | ||
48 | extern int sun4_timer_physaddr; /* timer, where applicable */ | ||
49 | extern int sun4_eth_physaddr; /* onboard ethernet (ie/le) */ | ||
50 | extern int sun4_si_physaddr; /* sun3 scsi adapter */ | ||
51 | extern int sun4_bwtwo_physaddr; /* onboard bw2 */ | ||
52 | extern int sun4_dma_physaddr; /* scsi dma */ | ||
53 | extern int sun4_esp_physaddr; /* esp scsi */ | ||
54 | extern int sun4_ie_physaddr; /* interrupt enable */ | ||
55 | |||
56 | #endif /* !(_SPARC_SUN4PADDR_H) */ | ||
diff --git a/arch/sparc/include/asm/sun4prom.h b/arch/sparc/include/asm/sun4prom.h deleted file mode 100644 index 9c8b4cbf629a..000000000000 --- a/arch/sparc/include/asm/sun4prom.h +++ /dev/null | |||
@@ -1,83 +0,0 @@ | |||
1 | /* | ||
2 | * sun4prom.h -- interface to sun4 PROM monitor. We don't use most of this, | ||
3 | * so most of these are just placeholders. | ||
4 | */ | ||
5 | |||
6 | #ifndef _SUN4PROM_H_ | ||
7 | #define _SUN4PROM_H_ | ||
8 | |||
9 | /* | ||
10 | * Although this looks similar to an romvec for a OpenProm machine, it is | ||
11 | * actually closer to what was used in the Sun2 and Sun3. | ||
12 | * | ||
13 | * V2 entries exist only in version 2 PROMs and later, V3 in version 3 and later. | ||
14 | * | ||
15 | * Many of the function prototypes are guesses. Some are certainly wrong. | ||
16 | * Use with care. | ||
17 | */ | ||
18 | |||
19 | typedef struct { | ||
20 | char *initSP; /* Initial system stack ptr */ | ||
21 | void (*startmon)(void); /* Initial PC for hardware */ | ||
22 | int *diagberr; /* Bus err handler for diags */ | ||
23 | struct linux_arguments_v0 **bootParam; /* Info for bootstrapped pgm */ | ||
24 | unsigned int *memorysize; /* Usable memory in bytes */ | ||
25 | unsigned char (*getchar)(void); /* Get char from input device */ | ||
26 | void (*putchar)(char); /* Put char to output device */ | ||
27 | int (*mayget)(void); /* Maybe get char, or -1 */ | ||
28 | int (*mayput)(int); /* Maybe put char, or -1 */ | ||
29 | unsigned char *echo; /* Should getchar echo? */ | ||
30 | unsigned char *insource; /* Input source selector */ | ||
31 | unsigned char *outsink; /* Output sink selector */ | ||
32 | int (*getkey)(void); /* Get next key if one exists */ | ||
33 | void (*initgetkey)(void); /* Initialize get key */ | ||
34 | unsigned int *translation; /* Kbd translation selector */ | ||
35 | unsigned char *keybid; /* Keyboard ID byte */ | ||
36 | int *screen_x; /* V2: Screen x pos (r/o) */ | ||
37 | int *screen_y; /* V2: Screen y pos (r/o) */ | ||
38 | struct keybuf *keybuf; /* Up/down keycode buffer */ | ||
39 | char *monid; /* Monitor version ID */ | ||
40 | void (*fbwritechar)(char); /* Write a character to FB */ | ||
41 | int *fbAddr; /* Address of frame buffer */ | ||
42 | char **font; /* Font table for FB */ | ||
43 | void (*fbwritestr)(char *); /* Write string to FB */ | ||
44 | void (*reboot)(char *); /* e.g. reboot("sd()vmlinux") */ | ||
45 | unsigned char *linebuf; /* The line input buffer */ | ||
46 | unsigned char **lineptr; /* Cur pointer into linebuf */ | ||
47 | int *linesize; /* length of line in linebuf */ | ||
48 | void (*getline)(char *); /* Get line from user */ | ||
49 | unsigned char (*getnextchar)(void); /* Get next char from linebuf */ | ||
50 | unsigned char (*peeknextchar)(void); /* Peek at next char */ | ||
51 | int *fbthere; /* =1 if frame buffer there */ | ||
52 | int (*getnum)(void); /* Grab hex num from line */ | ||
53 | int (*printf)(char *, ...); /* See prom_printf() instead */ | ||
54 | void (*printhex)(int); /* Format N digits in hex */ | ||
55 | unsigned char *leds; /* RAM copy of LED register */ | ||
56 | void (*setLEDs)(unsigned char *); /* Sets LED's and RAM copy */ | ||
57 | void (*NMIaddr)(void *); /* Addr for level 7 vector */ | ||
58 | void (*abortentry)(void); /* Entry for keyboard abort */ | ||
59 | int *nmiclock; /* Counts up in msec */ | ||
60 | int *FBtype; /* Frame buffer type */ | ||
61 | unsigned int romvecversion; /* Version number for this romvec */ | ||
62 | struct globram *globram; /* monitor global variables ??? */ | ||
63 | void * kbdaddr; /* Addr of keyboard in use */ | ||
64 | int *keyrinit; /* ms before kbd repeat */ | ||
65 | unsigned char *keyrtick; /* ms between repetitions */ | ||
66 | unsigned int *memoryavail; /* V1: Main mem usable size */ | ||
67 | long *resetaddr; /* where to jump on a reset */ | ||
68 | long *resetmap; /* pgmap entry for resetaddr */ | ||
69 | void (*exittomon)(void); /* Exit from user program */ | ||
70 | unsigned char **memorybitmap; /* V1: &{0 or &bits} */ | ||
71 | void (*setcxsegmap)(int ctxt, char *va, int pmeg); /* Set seg in any context */ | ||
72 | void (**vector_cmd)(void *); /* V2: Handler for 'v' cmd */ | ||
73 | unsigned long *expectedtrapsig; /* V3: Location of the expected trap signal */ | ||
74 | unsigned long *trapvectorbasetable; /* V3: Address of the trap vector table */ | ||
75 | int unused1; | ||
76 | int unused2; | ||
77 | int unused3; | ||
78 | int unused4; | ||
79 | } linux_sun4_romvec; | ||
80 | |||
81 | extern linux_sun4_romvec *sun4_romvec; | ||
82 | |||
83 | #endif /* _SUN4PROM_H_ */ | ||
diff --git a/arch/sparc/include/asm/system_32.h b/arch/sparc/include/asm/system_32.h index b4b024445fc9..8623fc48fe24 100644 --- a/arch/sparc/include/asm/system_32.h +++ b/arch/sparc/include/asm/system_32.h | |||
@@ -34,13 +34,7 @@ enum sparc_cpu { | |||
34 | 34 | ||
35 | extern enum sparc_cpu sparc_cpu_model; | 35 | extern enum sparc_cpu sparc_cpu_model; |
36 | 36 | ||
37 | #ifndef CONFIG_SUN4 | 37 | #define ARCH_SUN4C (sparc_cpu_model==sun4c) |
38 | #define ARCH_SUN4C_SUN4 (sparc_cpu_model==sun4c) | ||
39 | #define ARCH_SUN4 0 | ||
40 | #else | ||
41 | #define ARCH_SUN4C_SUN4 1 | ||
42 | #define ARCH_SUN4 1 | ||
43 | #endif | ||
44 | 38 | ||
45 | #define SUN4M_NCPUS 4 /* Architectural limit of sun4m. */ | 39 | #define SUN4M_NCPUS 4 /* Architectural limit of sun4m. */ |
46 | 40 | ||
@@ -55,6 +49,7 @@ extern unsigned long empty_zero_page; | |||
55 | extern void sun_do_break(void); | 49 | extern void sun_do_break(void); |
56 | extern int serial_console; | 50 | extern int serial_console; |
57 | extern int stop_a_enabled; | 51 | extern int stop_a_enabled; |
52 | extern int scons_pwroff; | ||
58 | 53 | ||
59 | static inline int con_is_present(void) | 54 | static inline int con_is_present(void) |
60 | { | 55 | { |
diff --git a/arch/sparc/include/asm/system_64.h b/arch/sparc/include/asm/system_64.h index db9e742a406a..8759f2a1b837 100644 --- a/arch/sparc/include/asm/system_64.h +++ b/arch/sparc/include/asm/system_64.h | |||
@@ -26,9 +26,8 @@ enum sparc_cpu { | |||
26 | 26 | ||
27 | #define sparc_cpu_model sun4u | 27 | #define sparc_cpu_model sun4u |
28 | 28 | ||
29 | /* This cannot ever be a sun4c nor sun4 :) That's just history. */ | 29 | /* This cannot ever be a sun4c :) That's just history. */ |
30 | #define ARCH_SUN4C_SUN4 0 | 30 | #define ARCH_SUN4C 0 |
31 | #define ARCH_SUN4 0 | ||
32 | 31 | ||
33 | extern char reboot_command[]; | 32 | extern char reboot_command[]; |
34 | 33 | ||
@@ -118,6 +117,7 @@ do { __asm__ __volatile__("ba,pt %%xcc, 1f\n\t" \ | |||
118 | 117 | ||
119 | extern void sun_do_break(void); | 118 | extern void sun_do_break(void); |
120 | extern int stop_a_enabled; | 119 | extern int stop_a_enabled; |
120 | extern int scons_pwroff; | ||
121 | 121 | ||
122 | extern void fault_in_user_windows(void); | 122 | extern void fault_in_user_windows(void); |
123 | extern void synchronize_user_stack(void); | 123 | extern void synchronize_user_stack(void); |
diff --git a/arch/sparc/include/asm/thread_info_32.h b/arch/sparc/include/asm/thread_info_32.h index cbb892d0dff0..29899fd5b1b2 100644 --- a/arch/sparc/include/asm/thread_info_32.h +++ b/arch/sparc/include/asm/thread_info_32.h | |||
@@ -80,11 +80,7 @@ register struct thread_info *current_thread_info_reg asm("g6"); | |||
80 | /* | 80 | /* |
81 | * thread information allocation | 81 | * thread information allocation |
82 | */ | 82 | */ |
83 | #if PAGE_SHIFT == 13 | ||
84 | #define THREAD_INFO_ORDER 0 | ||
85 | #else /* PAGE_SHIFT */ | ||
86 | #define THREAD_INFO_ORDER 1 | 83 | #define THREAD_INFO_ORDER 1 |
87 | #endif | ||
88 | 84 | ||
89 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR | 85 | #define __HAVE_ARCH_THREAD_INFO_ALLOCATOR |
90 | 86 | ||
diff --git a/arch/sparc/include/asm/timer_32.h b/arch/sparc/include/asm/timer_32.h index 361e53898dd7..2ec030ef3810 100644 --- a/arch/sparc/include/asm/timer_32.h +++ b/arch/sparc/include/asm/timer_32.h | |||
@@ -9,96 +9,9 @@ | |||
9 | #define _SPARC_TIMER_H | 9 | #define _SPARC_TIMER_H |
10 | 10 | ||
11 | #include <asm/system.h> /* For SUN4M_NCPUS */ | 11 | #include <asm/system.h> /* For SUN4M_NCPUS */ |
12 | #include <asm/sun4paddr.h> | ||
13 | #include <asm/btfixup.h> | 12 | #include <asm/btfixup.h> |
14 | 13 | ||
15 | /* Timer structures. The interrupt timer has two properties which | ||
16 | * are the counter (which is handled in do_timer in sched.c) and the limit. | ||
17 | * This limit is where the timer's counter 'wraps' around. Oddly enough, | ||
18 | * the sun4c timer when it hits the limit wraps back to 1 and not zero | ||
19 | * thus when calculating the value at which it will fire a microsecond you | ||
20 | * must adjust by one. Thanks SUN for designing such great hardware ;( | ||
21 | */ | ||
22 | |||
23 | /* Note that I am only going to use the timer that interrupts at | ||
24 | * Sparc IRQ 10. There is another one available that can fire at | ||
25 | * IRQ 14. Currently it is left untouched, we keep the PROM's limit | ||
26 | * register value and let the prom take these interrupts. This allows | ||
27 | * L1-A to work. | ||
28 | */ | ||
29 | |||
30 | struct sun4c_timer_info { | ||
31 | __volatile__ unsigned int cur_count10; | ||
32 | __volatile__ unsigned int timer_limit10; | ||
33 | __volatile__ unsigned int cur_count14; | ||
34 | __volatile__ unsigned int timer_limit14; | ||
35 | }; | ||
36 | |||
37 | #define SUN4C_TIMER_PHYSADDR 0xf3000000 | ||
38 | #ifdef CONFIG_SUN4 | ||
39 | #define SUN_TIMER_PHYSADDR SUN4_300_TIMER_PHYSADDR | ||
40 | #else | ||
41 | #define SUN_TIMER_PHYSADDR SUN4C_TIMER_PHYSADDR | ||
42 | #endif | ||
43 | |||
44 | /* A sun4m has two blocks of registers which are probably of the same | ||
45 | * structure. LSI Logic's L64851 is told to _decrement_ from the limit | ||
46 | * value. Aurora behaves similarly but its limit value is compacted in | ||
47 | * other fashion (it's wider). Documented fields are defined here. | ||
48 | */ | ||
49 | |||
50 | /* As with the interrupt register, we have two classes of timer registers | ||
51 | * which are per-cpu and master. Per-cpu timers only hit that cpu and are | ||
52 | * only level 14 ticks, master timer hits all cpus and is level 10. | ||
53 | */ | ||
54 | |||
55 | #define SUN4M_PRM_CNT_L 0x80000000 | ||
56 | #define SUN4M_PRM_CNT_LVALUE 0x7FFFFC00 | ||
57 | |||
58 | struct sun4m_timer_percpu_info { | ||
59 | __volatile__ unsigned int l14_timer_limit; /* Initial value is 0x009c4000 */ | ||
60 | __volatile__ unsigned int l14_cur_count; | ||
61 | |||
62 | /* This register appears to be write only and/or inaccessible | ||
63 | * on Uni-Processor sun4m machines. | ||
64 | */ | ||
65 | __volatile__ unsigned int l14_limit_noclear; /* Data access error is here */ | ||
66 | |||
67 | __volatile__ unsigned int cntrl; /* =1 after POST on Aurora */ | ||
68 | __volatile__ unsigned char space[PAGE_SIZE - 16]; | ||
69 | }; | ||
70 | |||
71 | struct sun4m_timer_regs { | ||
72 | struct sun4m_timer_percpu_info cpu_timers[SUN4M_NCPUS]; | ||
73 | volatile unsigned int l10_timer_limit; | ||
74 | volatile unsigned int l10_cur_count; | ||
75 | |||
76 | /* Again, this appears to be write only and/or inaccessible | ||
77 | * on uni-processor sun4m machines. | ||
78 | */ | ||
79 | volatile unsigned int l10_limit_noclear; | ||
80 | |||
81 | /* This register too, it must be magic. */ | ||
82 | volatile unsigned int foobar; | ||
83 | |||
84 | volatile unsigned int cfg; /* equals zero at boot time... */ | ||
85 | }; | ||
86 | |||
87 | #define SUN4D_PRM_CNT_L 0x80000000 | ||
88 | #define SUN4D_PRM_CNT_LVALUE 0x7FFFFC00 | ||
89 | |||
90 | struct sun4d_timer_regs { | ||
91 | volatile unsigned int l10_timer_limit; | ||
92 | volatile unsigned int l10_cur_countx; | ||
93 | volatile unsigned int l10_limit_noclear; | ||
94 | volatile unsigned int ctrl; | ||
95 | volatile unsigned int l10_cur_count; | ||
96 | }; | ||
97 | |||
98 | extern struct sun4d_timer_regs *sun4d_timers; | ||
99 | |||
100 | extern __volatile__ unsigned int *master_l10_counter; | 14 | extern __volatile__ unsigned int *master_l10_counter; |
101 | extern __volatile__ unsigned int *master_l10_limit; | ||
102 | 15 | ||
103 | /* FIXME: Make do_[gs]ettimeofday btfixup calls */ | 16 | /* FIXME: Make do_[gs]ettimeofday btfixup calls */ |
104 | BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv) | 17 | BTFIXUPDEF_CALL(int, bus_do_settimeofday, struct timespec *tv) |
diff --git a/arch/sparc/include/asm/vac-ops.h b/arch/sparc/include/asm/vac-ops.h index d10527611f11..a63e88ef0426 100644 --- a/arch/sparc/include/asm/vac-ops.h +++ b/arch/sparc/include/asm/vac-ops.h | |||
@@ -76,11 +76,7 @@ | |||
76 | * cacheable bit in the pte's of all such pages. | 76 | * cacheable bit in the pte's of all such pages. |
77 | */ | 77 | */ |
78 | 78 | ||
79 | #ifdef CONFIG_SUN4 | ||
80 | #define S4CVAC_BADBITS 0x0001e000 | ||
81 | #else | ||
82 | #define S4CVAC_BADBITS 0x0000f000 | 79 | #define S4CVAC_BADBITS 0x0000f000 |
83 | #endif | ||
84 | 80 | ||
85 | /* The following is true if vaddr1 and vaddr2 would cause | 81 | /* The following is true if vaddr1 and vaddr2 would cause |
86 | * a 'bad alias'. | 82 | * a 'bad alias'. |
@@ -94,10 +90,7 @@ | |||
94 | */ | 90 | */ |
95 | struct sun4c_vac_props { | 91 | struct sun4c_vac_props { |
96 | unsigned int num_bytes; /* Size of the cache */ | 92 | unsigned int num_bytes; /* Size of the cache */ |
97 | unsigned int num_lines; /* Number of cache lines */ | ||
98 | unsigned int do_hwflushes; /* Hardware flushing available? */ | 93 | unsigned int do_hwflushes; /* Hardware flushing available? */ |
99 | enum { VAC_NONE, VAC_WRITE_THROUGH, | ||
100 | VAC_WRITE_BACK } type; /* What type of VAC? */ | ||
101 | unsigned int linesize; /* Size of each line in bytes */ | 94 | unsigned int linesize; /* Size of each line in bytes */ |
102 | unsigned int log2lsize; /* log2(linesize) */ | 95 | unsigned int log2lsize; /* log2(linesize) */ |
103 | unsigned int on; /* VAC is enabled */ | 96 | unsigned int on; /* VAC is enabled */ |
diff --git a/arch/sparc/include/asm/vfc_ioctls.h b/arch/sparc/include/asm/vfc_ioctls.h deleted file mode 100644 index af8b69007b22..000000000000 --- a/arch/sparc/include/asm/vfc_ioctls.h +++ /dev/null | |||
@@ -1,58 +0,0 @@ | |||
1 | /* Copyright (c) 1996 by Manish Vachharajani */ | ||
2 | |||
3 | #ifndef _LINUX_VFC_IOCTLS_H_ | ||
4 | #define _LINUX_VFC_IOCTLS_H_ | ||
5 | |||
6 | /* IOCTLs */ | ||
7 | #define VFC_IOCTL(a) (('j' << 8) | a) | ||
8 | #define VFCGCTRL (VFC_IOCTL (0)) /* get vfc attributes */ | ||
9 | #define VFCSCTRL (VFC_IOCTL (1)) /* set vfc attributes */ | ||
10 | #define VFCGVID (VFC_IOCTL (2)) /* get video decoder attributes */ | ||
11 | #define VFCSVID (VFC_IOCTL (3)) /* set video decoder attributes */ | ||
12 | #define VFCHUE (VFC_IOCTL (4)) /* set hue */ | ||
13 | #define VFCPORTCHG (VFC_IOCTL (5)) /* change port */ | ||
14 | #define VFCRDINFO (VFC_IOCTL (6)) /* read info */ | ||
15 | |||
16 | /* Options for setting the vfc attributes and status */ | ||
17 | #define MEMPRST 0x1 /* reset FIFO ptr. */ | ||
18 | #define CAPTRCMD 0x2 /* start capture and wait */ | ||
19 | #define DIAGMODE 0x3 /* diag mode */ | ||
20 | #define NORMMODE 0x4 /* normal mode */ | ||
21 | #define CAPTRSTR 0x5 /* start capture */ | ||
22 | #define CAPTRWAIT 0x6 /* wait for capture to finish */ | ||
23 | |||
24 | |||
25 | /* Options for the decoder */ | ||
26 | #define STD_NTSC 0x1 /* NTSC mode */ | ||
27 | #define STD_PAL 0x2 /* PAL mode */ | ||
28 | #define COLOR_ON 0x3 /* force color ON */ | ||
29 | #define MONO 0x4 /* force color OFF */ | ||
30 | |||
31 | /* Values returned by ioctl 2 */ | ||
32 | |||
33 | #define NO_LOCK 1 | ||
34 | #define NTSC_COLOR 2 | ||
35 | #define NTSC_NOCOLOR 3 | ||
36 | #define PAL_COLOR 4 | ||
37 | #define PAL_NOCOLOR 5 | ||
38 | |||
39 | /* Not too sure what this does yet */ | ||
40 | /* Options for setting Field number */ | ||
41 | #define ODD_FIELD 0x1 | ||
42 | #define EVEN_FIELD 0x0 | ||
43 | #define ACTIVE_ONLY 0x2 | ||
44 | #define NON_ACTIVE 0x0 | ||
45 | |||
46 | /* Debug options */ | ||
47 | #define VFC_I2C_SEND 0 | ||
48 | #define VFC_I2C_RECV 1 | ||
49 | |||
50 | struct vfc_debug_inout | ||
51 | { | ||
52 | unsigned long addr; | ||
53 | unsigned long ret; | ||
54 | unsigned long len; | ||
55 | unsigned char __user *buffer; | ||
56 | }; | ||
57 | |||
58 | #endif /* _LINUX_VFC_IOCTLS_H_ */ | ||
diff --git a/arch/sparc/include/asm/visasm.h b/arch/sparc/include/asm/visasm.h index de797b9bf552..39ca301920db 100644 --- a/arch/sparc/include/asm/visasm.h +++ b/arch/sparc/include/asm/visasm.h | |||
@@ -57,6 +57,7 @@ static inline void save_and_clear_fpu(void) { | |||
57 | " " : : "i" (FPRS_FEF|FPRS_DU) : | 57 | " " : : "i" (FPRS_FEF|FPRS_DU) : |
58 | "o5", "g1", "g2", "g3", "g7", "cc"); | 58 | "o5", "g1", "g2", "g3", "g7", "cc"); |
59 | } | 59 | } |
60 | extern int vis_emul(struct pt_regs *, unsigned int); | ||
60 | #endif | 61 | #endif |
61 | 62 | ||
62 | #endif /* _SPARC64_ASI_H */ | 63 | #endif /* _SPARC64_ASI_H */ |
diff --git a/arch/sparc/kernel/Makefile b/arch/sparc/kernel/Makefile index 6e03a2a7863c..2d6582095099 100644 --- a/arch/sparc/kernel/Makefile +++ b/arch/sparc/kernel/Makefile | |||
@@ -13,15 +13,13 @@ obj-y := entry.o wof.o wuf.o etrap.o rtrap.o traps.o $(IRQ_OBJS) \ | |||
13 | time.o windows.o cpu.o devices.o \ | 13 | time.o windows.o cpu.o devices.o \ |
14 | tadpole.o tick14.o ptrace.o \ | 14 | tadpole.o tick14.o ptrace.o \ |
15 | unaligned.o una_asm.o muldiv.o \ | 15 | unaligned.o una_asm.o muldiv.o \ |
16 | prom.o of_device.o devres.o | 16 | prom.o of_device.o devres.o dma.o |
17 | 17 | ||
18 | devres-y = ../../../kernel/irq/devres.o | 18 | devres-y = ../../../kernel/irq/devres.o |
19 | 19 | ||
20 | obj-$(CONFIG_PCI) += pcic.o | 20 | obj-$(CONFIG_PCI) += pcic.o |
21 | obj-$(CONFIG_SUN4) += sun4setup.o | ||
22 | obj-$(CONFIG_SMP) += trampoline.o smp.o sun4m_smp.o sun4d_smp.o | 21 | obj-$(CONFIG_SMP) += trampoline.o smp.o sun4m_smp.o sun4d_smp.o |
23 | obj-$(CONFIG_SUN_AUXIO) += auxio.o | 22 | obj-$(CONFIG_SUN_AUXIO) += auxio.o |
24 | obj-$(CONFIG_PCI) += ebus.o | ||
25 | obj-$(CONFIG_SUN_PM) += apc.o pmc.o | 23 | obj-$(CONFIG_SUN_PM) += apc.o pmc.o |
26 | obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o | 24 | obj-$(CONFIG_MODULES) += module.o sparc_ksyms.o |
27 | obj-$(CONFIG_SPARC_LED) += led.o | 25 | obj-$(CONFIG_SPARC_LED) += led.o |
diff --git a/arch/sparc/kernel/apc.c b/arch/sparc/kernel/apc.c index 5267d48fb2c6..4dd1ba752ce6 100644 --- a/arch/sparc/kernel/apc.c +++ b/arch/sparc/kernel/apc.c | |||
@@ -12,9 +12,10 @@ | |||
12 | #include <linux/miscdevice.h> | 12 | #include <linux/miscdevice.h> |
13 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
14 | #include <linux/pm.h> | 14 | #include <linux/pm.h> |
15 | #include <linux/of.h> | ||
16 | #include <linux/of_device.h> | ||
15 | 17 | ||
16 | #include <asm/io.h> | 18 | #include <asm/io.h> |
17 | #include <asm/sbus.h> | ||
18 | #include <asm/oplib.h> | 19 | #include <asm/oplib.h> |
19 | #include <asm/uaccess.h> | 20 | #include <asm/uaccess.h> |
20 | #include <asm/auxio.h> | 21 | #include <asm/auxio.h> |
@@ -29,11 +30,10 @@ | |||
29 | #define APC_OBPNAME "power-management" | 30 | #define APC_OBPNAME "power-management" |
30 | #define APC_DEVNAME "apc" | 31 | #define APC_DEVNAME "apc" |
31 | 32 | ||
32 | volatile static u8 __iomem *regs; | 33 | static u8 __iomem *regs; |
33 | static int apc_regsize; | ||
34 | static int apc_no_idle __initdata = 0; | 34 | static int apc_no_idle __initdata = 0; |
35 | 35 | ||
36 | #define apc_readb(offs) (sbus_readb(regs+offs)) | 36 | #define apc_readb(offs) (sbus_readb(regs+offs)) |
37 | #define apc_writeb(val, offs) (sbus_writeb(val, regs+offs)) | 37 | #define apc_writeb(val, offs) (sbus_writeb(val, regs+offs)) |
38 | 38 | ||
39 | /* Specify "apc=noidle" on the kernel command line to | 39 | /* Specify "apc=noidle" on the kernel command line to |
@@ -69,9 +69,9 @@ static void apc_swift_idle(void) | |||
69 | #endif | 69 | #endif |
70 | } | 70 | } |
71 | 71 | ||
72 | static inline void apc_free(void) | 72 | static inline void apc_free(struct of_device *op) |
73 | { | 73 | { |
74 | sbus_iounmap(regs, apc_regsize); | 74 | of_iounmap(&op->resource[0], regs, resource_size(&op->resource[0])); |
75 | } | 75 | } |
76 | 76 | ||
77 | static int apc_open(struct inode *inode, struct file *f) | 77 | static int apc_open(struct inode *inode, struct file *f) |
@@ -153,52 +153,56 @@ static const struct file_operations apc_fops = { | |||
153 | 153 | ||
154 | static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops }; | 154 | static struct miscdevice apc_miscdev = { APC_MINOR, APC_DEVNAME, &apc_fops }; |
155 | 155 | ||
156 | static int __init apc_probe(void) | 156 | static int __devinit apc_probe(struct of_device *op, |
157 | const struct of_device_id *match) | ||
157 | { | 158 | { |
158 | struct sbus_bus *sbus = NULL; | 159 | int err; |
159 | struct sbus_dev *sdev = NULL; | ||
160 | int iTmp = 0; | ||
161 | |||
162 | for_each_sbus(sbus) { | ||
163 | for_each_sbusdev(sdev, sbus) { | ||
164 | if (!strcmp(sdev->prom_name, APC_OBPNAME)) { | ||
165 | goto sbus_done; | ||
166 | } | ||
167 | } | ||
168 | } | ||
169 | 160 | ||
170 | sbus_done: | 161 | regs = of_ioremap(&op->resource[0], 0, |
171 | if (!sdev) { | 162 | resource_size(&op->resource[0]), APC_OBPNAME); |
172 | return -ENODEV; | 163 | if (!regs) { |
173 | } | ||
174 | |||
175 | apc_regsize = sdev->reg_addrs[0].reg_size; | ||
176 | regs = sbus_ioremap(&sdev->resource[0], 0, | ||
177 | apc_regsize, APC_OBPNAME); | ||
178 | if(!regs) { | ||
179 | printk(KERN_ERR "%s: unable to map registers\n", APC_DEVNAME); | 164 | printk(KERN_ERR "%s: unable to map registers\n", APC_DEVNAME); |
180 | return -ENODEV; | 165 | return -ENODEV; |
181 | } | 166 | } |
182 | 167 | ||
183 | iTmp = misc_register(&apc_miscdev); | 168 | err = misc_register(&apc_miscdev); |
184 | if (iTmp != 0) { | 169 | if (err) { |
185 | printk(KERN_ERR "%s: unable to register device\n", APC_DEVNAME); | 170 | printk(KERN_ERR "%s: unable to register device\n", APC_DEVNAME); |
186 | apc_free(); | 171 | apc_free(op); |
187 | return -ENODEV; | 172 | return -ENODEV; |
188 | } | 173 | } |
189 | 174 | ||
190 | /* Assign power management IDLE handler */ | 175 | /* Assign power management IDLE handler */ |
191 | if(!apc_no_idle) | 176 | if (!apc_no_idle) |
192 | pm_idle = apc_swift_idle; | 177 | pm_idle = apc_swift_idle; |
193 | 178 | ||
194 | printk(KERN_INFO "%s: power management initialized%s\n", | 179 | printk(KERN_INFO "%s: power management initialized%s\n", |
195 | APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : ""); | 180 | APC_DEVNAME, apc_no_idle ? " (CPU idle disabled)" : ""); |
181 | |||
196 | return 0; | 182 | return 0; |
197 | } | 183 | } |
198 | 184 | ||
185 | static struct of_device_id __initdata apc_match[] = { | ||
186 | { | ||
187 | .name = APC_OBPNAME, | ||
188 | }, | ||
189 | {}, | ||
190 | }; | ||
191 | MODULE_DEVICE_TABLE(of, apc_match); | ||
192 | |||
193 | static struct of_platform_driver apc_driver = { | ||
194 | .name = "apc", | ||
195 | .match_table = apc_match, | ||
196 | .probe = apc_probe, | ||
197 | }; | ||
198 | |||
199 | static int __init apc_init(void) | ||
200 | { | ||
201 | return of_register_driver(&apc_driver, &of_bus_type); | ||
202 | } | ||
203 | |||
199 | /* This driver is not critical to the boot process | 204 | /* This driver is not critical to the boot process |
200 | * and is easiest to ioremap when SBus is already | 205 | * and is easiest to ioremap when SBus is already |
201 | * initialized, so we install ourselves thusly: | 206 | * initialized, so we install ourselves thusly: |
202 | */ | 207 | */ |
203 | __initcall(apc_probe); | 208 | __initcall(apc_init); |
204 | |||
diff --git a/arch/sparc/kernel/auxio.c b/arch/sparc/kernel/auxio.c index baf4ed3fb0f3..09c857215a52 100644 --- a/arch/sparc/kernel/auxio.c +++ b/arch/sparc/kernel/auxio.c | |||
@@ -6,6 +6,8 @@ | |||
6 | #include <linux/stddef.h> | 6 | #include <linux/stddef.h> |
7 | #include <linux/init.h> | 7 | #include <linux/init.h> |
8 | #include <linux/spinlock.h> | 8 | #include <linux/spinlock.h> |
9 | #include <linux/of.h> | ||
10 | #include <linux/of_device.h> | ||
9 | #include <asm/oplib.h> | 11 | #include <asm/oplib.h> |
10 | #include <asm/io.h> | 12 | #include <asm/io.h> |
11 | #include <asm/auxio.h> | 13 | #include <asm/auxio.h> |
@@ -59,7 +61,7 @@ void __init auxio_probe(void) | |||
59 | r.flags = auxregs[0].which_io & 0xF; | 61 | r.flags = auxregs[0].which_io & 0xF; |
60 | r.start = auxregs[0].phys_addr; | 62 | r.start = auxregs[0].phys_addr; |
61 | r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1; | 63 | r.end = auxregs[0].phys_addr + auxregs[0].reg_size - 1; |
62 | auxio_register = sbus_ioremap(&r, 0, auxregs[0].reg_size, "auxio"); | 64 | auxio_register = of_ioremap(&r, 0, auxregs[0].reg_size, "auxio"); |
63 | /* Fix the address on sun4m and sun4c. */ | 65 | /* Fix the address on sun4m and sun4c. */ |
64 | if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 || | 66 | if((((unsigned long) auxregs[0].phys_addr) & 3) == 3 || |
65 | sparc_cpu_model == sun4c) | 67 | sparc_cpu_model == sun4c) |
@@ -128,7 +130,7 @@ void __init auxio_power_probe(void) | |||
128 | r.flags = regs.which_io & 0xF; | 130 | r.flags = regs.which_io & 0xF; |
129 | r.start = regs.phys_addr; | 131 | r.start = regs.phys_addr; |
130 | r.end = regs.phys_addr + regs.reg_size - 1; | 132 | r.end = regs.phys_addr + regs.reg_size - 1; |
131 | auxio_power_register = (unsigned char *) sbus_ioremap(&r, 0, | 133 | auxio_power_register = (unsigned char *) of_ioremap(&r, 0, |
132 | regs.reg_size, "auxpower"); | 134 | regs.reg_size, "auxpower"); |
133 | 135 | ||
134 | /* Display a quick message on the console. */ | 136 | /* Display a quick message on the console. */ |
diff --git a/arch/sparc/kernel/devices.c b/arch/sparc/kernel/devices.c index b240b8863fd0..ad656b044b8c 100644 --- a/arch/sparc/kernel/devices.c +++ b/arch/sparc/kernel/devices.c | |||
@@ -143,7 +143,7 @@ void __init device_scan(void) | |||
143 | #endif | 143 | #endif |
144 | clock_stop_probe(); | 144 | clock_stop_probe(); |
145 | 145 | ||
146 | if (ARCH_SUN4C_SUN4) | 146 | if (ARCH_SUN4C) |
147 | sun4c_probe_memerr_reg(); | 147 | sun4c_probe_memerr_reg(); |
148 | 148 | ||
149 | return; | 149 | return; |
diff --git a/arch/sparc/kernel/dma.c b/arch/sparc/kernel/dma.c new file mode 100644 index 000000000000..ebc8403b035e --- /dev/null +++ b/arch/sparc/kernel/dma.c | |||
@@ -0,0 +1,227 @@ | |||
1 | /* dma.c: PCI and SBUS DMA accessors for 32-bit sparc. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/dma-mapping.h> | ||
9 | #include <linux/scatterlist.h> | ||
10 | #include <linux/mm.h> | ||
11 | |||
12 | #ifdef CONFIG_PCI | ||
13 | #include <linux/pci.h> | ||
14 | #endif | ||
15 | |||
16 | #include "dma.h" | ||
17 | |||
18 | int dma_supported(struct device *dev, u64 mask) | ||
19 | { | ||
20 | #ifdef CONFIG_PCI | ||
21 | if (dev->bus == &pci_bus_type) | ||
22 | return pci_dma_supported(to_pci_dev(dev), mask); | ||
23 | #endif | ||
24 | return 0; | ||
25 | } | ||
26 | EXPORT_SYMBOL(dma_supported); | ||
27 | |||
28 | int dma_set_mask(struct device *dev, u64 dma_mask) | ||
29 | { | ||
30 | #ifdef CONFIG_PCI | ||
31 | if (dev->bus == &pci_bus_type) | ||
32 | return pci_set_dma_mask(to_pci_dev(dev), dma_mask); | ||
33 | #endif | ||
34 | return -EOPNOTSUPP; | ||
35 | } | ||
36 | EXPORT_SYMBOL(dma_set_mask); | ||
37 | |||
38 | void *dma_alloc_coherent(struct device *dev, size_t size, | ||
39 | dma_addr_t *dma_handle, gfp_t flag) | ||
40 | { | ||
41 | #ifdef CONFIG_PCI | ||
42 | if (dev->bus == &pci_bus_type) | ||
43 | return pci_alloc_consistent(to_pci_dev(dev), size, dma_handle); | ||
44 | #endif | ||
45 | return sbus_alloc_consistent(dev, size, dma_handle); | ||
46 | } | ||
47 | EXPORT_SYMBOL(dma_alloc_coherent); | ||
48 | |||
49 | void dma_free_coherent(struct device *dev, size_t size, | ||
50 | void *cpu_addr, dma_addr_t dma_handle) | ||
51 | { | ||
52 | #ifdef CONFIG_PCI | ||
53 | if (dev->bus == &pci_bus_type) { | ||
54 | pci_free_consistent(to_pci_dev(dev), size, | ||
55 | cpu_addr, dma_handle); | ||
56 | return; | ||
57 | } | ||
58 | #endif | ||
59 | sbus_free_consistent(dev, size, cpu_addr, dma_handle); | ||
60 | } | ||
61 | EXPORT_SYMBOL(dma_free_coherent); | ||
62 | |||
63 | dma_addr_t dma_map_single(struct device *dev, void *cpu_addr, | ||
64 | size_t size, enum dma_data_direction direction) | ||
65 | { | ||
66 | #ifdef CONFIG_PCI | ||
67 | if (dev->bus == &pci_bus_type) | ||
68 | return pci_map_single(to_pci_dev(dev), cpu_addr, | ||
69 | size, (int)direction); | ||
70 | #endif | ||
71 | return sbus_map_single(dev, cpu_addr, size, (int)direction); | ||
72 | } | ||
73 | EXPORT_SYMBOL(dma_map_single); | ||
74 | |||
75 | void dma_unmap_single(struct device *dev, dma_addr_t dma_addr, | ||
76 | size_t size, | ||
77 | enum dma_data_direction direction) | ||
78 | { | ||
79 | #ifdef CONFIG_PCI | ||
80 | if (dev->bus == &pci_bus_type) { | ||
81 | pci_unmap_single(to_pci_dev(dev), dma_addr, | ||
82 | size, (int)direction); | ||
83 | return; | ||
84 | } | ||
85 | #endif | ||
86 | sbus_unmap_single(dev, dma_addr, size, (int)direction); | ||
87 | } | ||
88 | EXPORT_SYMBOL(dma_unmap_single); | ||
89 | |||
90 | dma_addr_t dma_map_page(struct device *dev, struct page *page, | ||
91 | unsigned long offset, size_t size, | ||
92 | enum dma_data_direction direction) | ||
93 | { | ||
94 | #ifdef CONFIG_PCI | ||
95 | if (dev->bus == &pci_bus_type) | ||
96 | return pci_map_page(to_pci_dev(dev), page, offset, | ||
97 | size, (int)direction); | ||
98 | #endif | ||
99 | return sbus_map_single(dev, page_address(page) + offset, | ||
100 | size, (int)direction); | ||
101 | } | ||
102 | EXPORT_SYMBOL(dma_map_page); | ||
103 | |||
104 | void dma_unmap_page(struct device *dev, dma_addr_t dma_address, | ||
105 | size_t size, enum dma_data_direction direction) | ||
106 | { | ||
107 | #ifdef CONFIG_PCI | ||
108 | if (dev->bus == &pci_bus_type) { | ||
109 | pci_unmap_page(to_pci_dev(dev), dma_address, | ||
110 | size, (int)direction); | ||
111 | return; | ||
112 | } | ||
113 | #endif | ||
114 | sbus_unmap_single(dev, dma_address, size, (int)direction); | ||
115 | } | ||
116 | EXPORT_SYMBOL(dma_unmap_page); | ||
117 | |||
118 | int dma_map_sg(struct device *dev, struct scatterlist *sg, | ||
119 | int nents, enum dma_data_direction direction) | ||
120 | { | ||
121 | #ifdef CONFIG_PCI | ||
122 | if (dev->bus == &pci_bus_type) | ||
123 | return pci_map_sg(to_pci_dev(dev), sg, nents, (int)direction); | ||
124 | #endif | ||
125 | return sbus_map_sg(dev, sg, nents, direction); | ||
126 | } | ||
127 | EXPORT_SYMBOL(dma_map_sg); | ||
128 | |||
129 | void dma_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
130 | int nents, enum dma_data_direction direction) | ||
131 | { | ||
132 | #ifdef CONFIG_PCI | ||
133 | if (dev->bus == &pci_bus_type) { | ||
134 | pci_unmap_sg(to_pci_dev(dev), sg, nents, (int)direction); | ||
135 | return; | ||
136 | } | ||
137 | #endif | ||
138 | sbus_unmap_sg(dev, sg, nents, (int)direction); | ||
139 | } | ||
140 | EXPORT_SYMBOL(dma_unmap_sg); | ||
141 | |||
142 | void dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, | ||
143 | size_t size, enum dma_data_direction direction) | ||
144 | { | ||
145 | #ifdef CONFIG_PCI | ||
146 | if (dev->bus == &pci_bus_type) { | ||
147 | pci_dma_sync_single_for_cpu(to_pci_dev(dev), dma_handle, | ||
148 | size, (int)direction); | ||
149 | return; | ||
150 | } | ||
151 | #endif | ||
152 | sbus_dma_sync_single_for_cpu(dev, dma_handle, size, (int) direction); | ||
153 | } | ||
154 | EXPORT_SYMBOL(dma_sync_single_for_cpu); | ||
155 | |||
156 | void dma_sync_single_for_device(struct device *dev, dma_addr_t dma_handle, | ||
157 | size_t size, enum dma_data_direction direction) | ||
158 | { | ||
159 | #ifdef CONFIG_PCI | ||
160 | if (dev->bus == &pci_bus_type) { | ||
161 | pci_dma_sync_single_for_device(to_pci_dev(dev), dma_handle, | ||
162 | size, (int)direction); | ||
163 | return; | ||
164 | } | ||
165 | #endif | ||
166 | sbus_dma_sync_single_for_device(dev, dma_handle, size, (int) direction); | ||
167 | } | ||
168 | EXPORT_SYMBOL(dma_sync_single_for_device); | ||
169 | |||
170 | void dma_sync_single_range_for_cpu(struct device *dev, | ||
171 | dma_addr_t dma_handle, | ||
172 | unsigned long offset, | ||
173 | size_t size, | ||
174 | enum dma_data_direction direction) | ||
175 | { | ||
176 | dma_sync_single_for_cpu(dev, dma_handle+offset, size, direction); | ||
177 | } | ||
178 | EXPORT_SYMBOL(dma_sync_single_range_for_cpu); | ||
179 | |||
180 | void dma_sync_single_range_for_device(struct device *dev, dma_addr_t dma_handle, | ||
181 | unsigned long offset, size_t size, | ||
182 | enum dma_data_direction direction) | ||
183 | { | ||
184 | dma_sync_single_for_device(dev, dma_handle+offset, size, direction); | ||
185 | } | ||
186 | EXPORT_SYMBOL(dma_sync_single_range_for_device); | ||
187 | |||
188 | void dma_sync_sg_for_cpu(struct device *dev, struct scatterlist *sg, | ||
189 | int nelems, enum dma_data_direction direction) | ||
190 | { | ||
191 | #ifdef CONFIG_PCI | ||
192 | if (dev->bus == &pci_bus_type) { | ||
193 | pci_dma_sync_sg_for_cpu(to_pci_dev(dev), sg, | ||
194 | nelems, (int)direction); | ||
195 | return; | ||
196 | } | ||
197 | #endif | ||
198 | BUG(); | ||
199 | } | ||
200 | EXPORT_SYMBOL(dma_sync_sg_for_cpu); | ||
201 | |||
202 | void dma_sync_sg_for_device(struct device *dev, | ||
203 | struct scatterlist *sg, int nelems, | ||
204 | enum dma_data_direction direction) | ||
205 | { | ||
206 | #ifdef CONFIG_PCI | ||
207 | if (dev->bus == &pci_bus_type) { | ||
208 | pci_dma_sync_sg_for_device(to_pci_dev(dev), sg, | ||
209 | nelems, (int)direction); | ||
210 | return; | ||
211 | } | ||
212 | #endif | ||
213 | BUG(); | ||
214 | } | ||
215 | EXPORT_SYMBOL(dma_sync_sg_for_device); | ||
216 | |||
217 | int dma_mapping_error(struct device *dev, dma_addr_t dma_addr) | ||
218 | { | ||
219 | return (dma_addr == DMA_ERROR_CODE); | ||
220 | } | ||
221 | EXPORT_SYMBOL(dma_mapping_error); | ||
222 | |||
223 | int dma_get_cache_alignment(void) | ||
224 | { | ||
225 | return 32; | ||
226 | } | ||
227 | EXPORT_SYMBOL(dma_get_cache_alignment); | ||
diff --git a/arch/sparc/kernel/dma.h b/arch/sparc/kernel/dma.h new file mode 100644 index 000000000000..f8d8951adb53 --- /dev/null +++ b/arch/sparc/kernel/dma.h | |||
@@ -0,0 +1,14 @@ | |||
1 | void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp); | ||
2 | void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba); | ||
3 | dma_addr_t sbus_map_single(struct device *dev, void *va, | ||
4 | size_t len, int direction); | ||
5 | void sbus_unmap_single(struct device *dev, dma_addr_t ba, | ||
6 | size_t n, int direction); | ||
7 | int sbus_map_sg(struct device *dev, struct scatterlist *sg, | ||
8 | int n, int direction); | ||
9 | void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, | ||
10 | int n, int direction); | ||
11 | void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, | ||
12 | size_t size, int direction); | ||
13 | void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, | ||
14 | size_t size, int direction); | ||
diff --git a/arch/sparc/kernel/ebus.c b/arch/sparc/kernel/ebus.c deleted file mode 100644 index 97294232259c..000000000000 --- a/arch/sparc/kernel/ebus.c +++ /dev/null | |||
@@ -1,393 +0,0 @@ | |||
1 | /* | ||
2 | * ebus.c: PCI to EBus bridge device. | ||
3 | * | ||
4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | ||
5 | * | ||
6 | * Adopted for sparc by V. Roganov and G. Raiko. | ||
7 | * Fixes for different platforms by Pete Zaitcev. | ||
8 | */ | ||
9 | |||
10 | #include <linux/kernel.h> | ||
11 | #include <linux/types.h> | ||
12 | #include <linux/init.h> | ||
13 | #include <linux/slab.h> | ||
14 | #include <linux/string.h> | ||
15 | |||
16 | #include <asm/system.h> | ||
17 | #include <asm/page.h> | ||
18 | #include <asm/pbm.h> | ||
19 | #include <asm/ebus.h> | ||
20 | #include <asm/io.h> | ||
21 | #include <asm/oplib.h> | ||
22 | #include <asm/prom.h> | ||
23 | #include <asm/bpp.h> | ||
24 | |||
25 | struct linux_ebus *ebus_chain = NULL; | ||
26 | |||
27 | /* We are together with pcic.c under CONFIG_PCI. */ | ||
28 | extern unsigned int pcic_pin_to_irq(unsigned int, const char *name); | ||
29 | |||
30 | /* | ||
31 | * IRQ Blacklist | ||
32 | * Here we list PROMs and systems that are known to supply crap as IRQ numbers. | ||
33 | */ | ||
34 | struct ebus_device_irq { | ||
35 | char *name; | ||
36 | unsigned int pin; | ||
37 | }; | ||
38 | |||
39 | struct ebus_system_entry { | ||
40 | char *esname; | ||
41 | struct ebus_device_irq *ipt; | ||
42 | }; | ||
43 | |||
44 | static struct ebus_device_irq je1_1[] = { | ||
45 | { "8042", 3 }, | ||
46 | { "SUNW,CS4231", 0 }, | ||
47 | { "parallel", 0 }, | ||
48 | { "se", 2 }, | ||
49 | { NULL, 0 } | ||
50 | }; | ||
51 | |||
52 | /* | ||
53 | * Gleb's JE1 supplied reasonable pin numbers, but mine did not (OBP 2.32). | ||
54 | * Blacklist the sucker... Note that Gleb's system will work. | ||
55 | */ | ||
56 | static struct ebus_system_entry ebus_blacklist[] = { | ||
57 | { "SUNW,JavaEngine1", je1_1 }, | ||
58 | { NULL, NULL } | ||
59 | }; | ||
60 | |||
61 | static struct ebus_device_irq *ebus_blackp = NULL; | ||
62 | |||
63 | /* | ||
64 | */ | ||
65 | static inline unsigned long ebus_alloc(size_t size) | ||
66 | { | ||
67 | return (unsigned long)kmalloc(size, GFP_ATOMIC); | ||
68 | } | ||
69 | |||
70 | /* | ||
71 | */ | ||
72 | static int __init ebus_blacklist_irq(const char *name) | ||
73 | { | ||
74 | struct ebus_device_irq *dp; | ||
75 | |||
76 | if ((dp = ebus_blackp) != NULL) { | ||
77 | for (; dp->name != NULL; dp++) { | ||
78 | if (strcmp(name, dp->name) == 0) { | ||
79 | return pcic_pin_to_irq(dp->pin, name); | ||
80 | } | ||
81 | } | ||
82 | } | ||
83 | return 0; | ||
84 | } | ||
85 | |||
86 | static void __init fill_ebus_child(struct device_node *dp, | ||
87 | struct linux_ebus_child *dev) | ||
88 | { | ||
89 | const int *regs; | ||
90 | const int *irqs; | ||
91 | int i, len; | ||
92 | |||
93 | dev->prom_node = dp; | ||
94 | regs = of_get_property(dp, "reg", &len); | ||
95 | if (!regs) | ||
96 | len = 0; | ||
97 | dev->num_addrs = len / sizeof(regs[0]); | ||
98 | |||
99 | for (i = 0; i < dev->num_addrs; i++) { | ||
100 | if (regs[i] >= dev->parent->num_addrs) { | ||
101 | prom_printf("UGH: property for %s was %d, need < %d\n", | ||
102 | dev->prom_node->name, len, | ||
103 | dev->parent->num_addrs); | ||
104 | panic(__func__); | ||
105 | } | ||
106 | |||
107 | /* XXX resource */ | ||
108 | dev->resource[i].start = | ||
109 | dev->parent->resource[regs[i]].start; | ||
110 | } | ||
111 | |||
112 | for (i = 0; i < PROMINTR_MAX; i++) | ||
113 | dev->irqs[i] = PCI_IRQ_NONE; | ||
114 | |||
115 | if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) { | ||
116 | dev->num_irqs = 1; | ||
117 | } else { | ||
118 | irqs = of_get_property(dp, "interrupts", &len); | ||
119 | if (!irqs) { | ||
120 | dev->num_irqs = 0; | ||
121 | dev->irqs[0] = 0; | ||
122 | if (dev->parent->num_irqs != 0) { | ||
123 | dev->num_irqs = 1; | ||
124 | dev->irqs[0] = dev->parent->irqs[0]; | ||
125 | } | ||
126 | } else { | ||
127 | dev->num_irqs = len / sizeof(irqs[0]); | ||
128 | if (irqs[0] == 0 || irqs[0] >= 8) { | ||
129 | /* | ||
130 | * XXX Zero is a valid pin number... | ||
131 | * This works as long as Ebus is not wired | ||
132 | * to INTA#. | ||
133 | */ | ||
134 | printk("EBUS: %s got bad irq %d from PROM\n", | ||
135 | dev->prom_node->name, irqs[0]); | ||
136 | dev->num_irqs = 0; | ||
137 | dev->irqs[0] = 0; | ||
138 | } else { | ||
139 | dev->irqs[0] = | ||
140 | pcic_pin_to_irq(irqs[0], | ||
141 | dev->prom_node->name); | ||
142 | } | ||
143 | } | ||
144 | } | ||
145 | } | ||
146 | |||
147 | static void __init fill_ebus_device(struct device_node *dp, | ||
148 | struct linux_ebus_device *dev) | ||
149 | { | ||
150 | const struct linux_prom_registers *regs; | ||
151 | struct linux_ebus_child *child; | ||
152 | struct dev_archdata *sd; | ||
153 | const int *irqs; | ||
154 | int i, n, len; | ||
155 | unsigned long baseaddr; | ||
156 | |||
157 | dev->prom_node = dp; | ||
158 | |||
159 | regs = of_get_property(dp, "reg", &len); | ||
160 | if (!regs) | ||
161 | len = 0; | ||
162 | if (len % sizeof(struct linux_prom_registers)) { | ||
163 | prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", | ||
164 | dev->prom_node->name, len, | ||
165 | (int)sizeof(struct linux_prom_registers)); | ||
166 | panic(__func__); | ||
167 | } | ||
168 | dev->num_addrs = len / sizeof(struct linux_prom_registers); | ||
169 | |||
170 | for (i = 0; i < dev->num_addrs; i++) { | ||
171 | /* | ||
172 | * XXX Collect JE-1 PROM | ||
173 | * | ||
174 | * Example - JS-E with 3.11: | ||
175 | * /ebus | ||
176 | * regs | ||
177 | * 0x00000000, 0x0, 0x00000000, 0x0, 0x00000000, | ||
178 | * 0x82000010, 0x0, 0xf0000000, 0x0, 0x01000000, | ||
179 | * 0x82000014, 0x0, 0x38800000, 0x0, 0x00800000, | ||
180 | * ranges | ||
181 | * 0x00, 0x00000000, 0x02000010, 0x0, 0x0, 0x01000000, | ||
182 | * 0x01, 0x01000000, 0x02000014, 0x0, 0x0, 0x00800000, | ||
183 | * /ebus/8042 | ||
184 | * regs | ||
185 | * 0x00000001, 0x00300060, 0x00000008, | ||
186 | * 0x00000001, 0x00300060, 0x00000008, | ||
187 | */ | ||
188 | n = regs[i].which_io; | ||
189 | if (n >= 4) { | ||
190 | /* XXX This is copied from old JE-1 by Gleb. */ | ||
191 | n = (regs[i].which_io - 0x10) >> 2; | ||
192 | } else { | ||
193 | ; | ||
194 | } | ||
195 | |||
196 | /* | ||
197 | * XXX Now as we have regions, why don't we make an on-demand allocation... | ||
198 | */ | ||
199 | dev->resource[i].start = 0; | ||
200 | if ((baseaddr = dev->bus->self->resource[n].start + | ||
201 | regs[i].phys_addr) != 0) { | ||
202 | /* dev->resource[i].name = dev->prom_name; */ | ||
203 | if ((baseaddr = (unsigned long) ioremap(baseaddr, | ||
204 | regs[i].reg_size)) == 0) { | ||
205 | panic("ebus: unable to remap dev %s", | ||
206 | dev->prom_node->name); | ||
207 | } | ||
208 | } | ||
209 | dev->resource[i].start = baseaddr; /* XXX Unaligned */ | ||
210 | } | ||
211 | |||
212 | for (i = 0; i < PROMINTR_MAX; i++) | ||
213 | dev->irqs[i] = PCI_IRQ_NONE; | ||
214 | |||
215 | if ((dev->irqs[0] = ebus_blacklist_irq(dev->prom_node->name)) != 0) { | ||
216 | dev->num_irqs = 1; | ||
217 | } else { | ||
218 | irqs = of_get_property(dp, "interrupts", &len); | ||
219 | if (!irqs) { | ||
220 | dev->num_irqs = 0; | ||
221 | if ((dev->irqs[0] = dev->bus->self->irq) != 0) { | ||
222 | dev->num_irqs = 1; | ||
223 | /* P3 */ /* printk("EBUS: child %s irq %d from parent\n", dev->prom_name, dev->irqs[0]); */ | ||
224 | } | ||
225 | } else { | ||
226 | dev->num_irqs = 1; /* dev->num_irqs = len / sizeof(irqs[0]); */ | ||
227 | if (irqs[0] == 0 || irqs[0] >= 8) { | ||
228 | /* See above for the parent. XXX */ | ||
229 | printk("EBUS: %s got bad irq %d from PROM\n", | ||
230 | dev->prom_node->name, irqs[0]); | ||
231 | dev->num_irqs = 0; | ||
232 | dev->irqs[0] = 0; | ||
233 | } else { | ||
234 | dev->irqs[0] = | ||
235 | pcic_pin_to_irq(irqs[0], | ||
236 | dev->prom_node->name); | ||
237 | } | ||
238 | } | ||
239 | } | ||
240 | |||
241 | sd = &dev->ofdev.dev.archdata; | ||
242 | sd->prom_node = dp; | ||
243 | sd->op = &dev->ofdev; | ||
244 | sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; | ||
245 | |||
246 | dev->ofdev.node = dp; | ||
247 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; | ||
248 | dev->ofdev.dev.bus = &ebus_bus_type; | ||
249 | sprintf(dev->ofdev.dev.bus_id, "ebus[%08x]", dp->node); | ||
250 | |||
251 | /* Register with core */ | ||
252 | if (of_device_register(&dev->ofdev) != 0) | ||
253 | printk(KERN_DEBUG "ebus: device registration error for %s!\n", | ||
254 | dp->path_component_name); | ||
255 | |||
256 | if ((dp = dp->child) != NULL) { | ||
257 | dev->children = (struct linux_ebus_child *) | ||
258 | ebus_alloc(sizeof(struct linux_ebus_child)); | ||
259 | |||
260 | child = dev->children; | ||
261 | child->next = NULL; | ||
262 | child->parent = dev; | ||
263 | child->bus = dev->bus; | ||
264 | fill_ebus_child(dp, child); | ||
265 | |||
266 | while ((dp = dp->sibling) != NULL) { | ||
267 | child->next = (struct linux_ebus_child *) | ||
268 | ebus_alloc(sizeof(struct linux_ebus_child)); | ||
269 | |||
270 | child = child->next; | ||
271 | child->next = NULL; | ||
272 | child->parent = dev; | ||
273 | child->bus = dev->bus; | ||
274 | fill_ebus_child(dp, child); | ||
275 | } | ||
276 | } | ||
277 | } | ||
278 | |||
279 | void __init ebus_init(void) | ||
280 | { | ||
281 | const struct linux_prom_pci_registers *regs; | ||
282 | struct linux_pbm_info *pbm; | ||
283 | struct linux_ebus_device *dev; | ||
284 | struct linux_ebus *ebus; | ||
285 | struct ebus_system_entry *sp; | ||
286 | struct pci_dev *pdev; | ||
287 | struct pcidev_cookie *cookie; | ||
288 | struct device_node *dp; | ||
289 | struct resource *p; | ||
290 | unsigned short pci_command; | ||
291 | int len, reg, nreg; | ||
292 | int num_ebus = 0; | ||
293 | |||
294 | dp = of_find_node_by_path("/"); | ||
295 | for (sp = ebus_blacklist; sp->esname != NULL; sp++) { | ||
296 | if (strcmp(dp->name, sp->esname) == 0) { | ||
297 | ebus_blackp = sp->ipt; | ||
298 | break; | ||
299 | } | ||
300 | } | ||
301 | |||
302 | pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_DEVICE_ID_SUN_EBUS, NULL); | ||
303 | if (!pdev) | ||
304 | return; | ||
305 | |||
306 | cookie = pdev->sysdata; | ||
307 | dp = cookie->prom_node; | ||
308 | |||
309 | ebus_chain = ebus = (struct linux_ebus *) | ||
310 | ebus_alloc(sizeof(struct linux_ebus)); | ||
311 | ebus->next = NULL; | ||
312 | |||
313 | while (dp) { | ||
314 | struct device_node *nd; | ||
315 | |||
316 | ebus->prom_node = dp; | ||
317 | ebus->self = pdev; | ||
318 | ebus->parent = pbm = cookie->pbm; | ||
319 | |||
320 | /* Enable BUS Master. */ | ||
321 | pci_read_config_word(pdev, PCI_COMMAND, &pci_command); | ||
322 | pci_command |= PCI_COMMAND_MASTER; | ||
323 | pci_write_config_word(pdev, PCI_COMMAND, pci_command); | ||
324 | |||
325 | regs = of_get_property(dp, "reg", &len); | ||
326 | if (!regs) { | ||
327 | prom_printf("%s: can't find reg property\n", | ||
328 | __func__); | ||
329 | prom_halt(); | ||
330 | } | ||
331 | nreg = len / sizeof(struct linux_prom_pci_registers); | ||
332 | |||
333 | p = &ebus->self->resource[0]; | ||
334 | for (reg = 0; reg < nreg; reg++) { | ||
335 | if (!(regs[reg].which_io & 0x03000000)) | ||
336 | continue; | ||
337 | |||
338 | (p++)->start = regs[reg].phys_lo; | ||
339 | } | ||
340 | |||
341 | ebus->ofdev.node = dp; | ||
342 | ebus->ofdev.dev.parent = &pdev->dev; | ||
343 | ebus->ofdev.dev.bus = &ebus_bus_type; | ||
344 | sprintf(ebus->ofdev.dev.bus_id, "ebus%d", num_ebus); | ||
345 | |||
346 | /* Register with core */ | ||
347 | if (of_device_register(&ebus->ofdev) != 0) | ||
348 | printk(KERN_DEBUG "ebus: device registration error for %s!\n", | ||
349 | dp->path_component_name); | ||
350 | |||
351 | |||
352 | nd = dp->child; | ||
353 | if (!nd) | ||
354 | goto next_ebus; | ||
355 | |||
356 | ebus->devices = (struct linux_ebus_device *) | ||
357 | ebus_alloc(sizeof(struct linux_ebus_device)); | ||
358 | |||
359 | dev = ebus->devices; | ||
360 | dev->next = NULL; | ||
361 | dev->children = NULL; | ||
362 | dev->bus = ebus; | ||
363 | fill_ebus_device(nd, dev); | ||
364 | |||
365 | while ((nd = nd->sibling) != NULL) { | ||
366 | dev->next = (struct linux_ebus_device *) | ||
367 | ebus_alloc(sizeof(struct linux_ebus_device)); | ||
368 | |||
369 | dev = dev->next; | ||
370 | dev->next = NULL; | ||
371 | dev->children = NULL; | ||
372 | dev->bus = ebus; | ||
373 | fill_ebus_device(nd, dev); | ||
374 | } | ||
375 | |||
376 | next_ebus: | ||
377 | pdev = pci_get_device(PCI_VENDOR_ID_SUN, | ||
378 | PCI_DEVICE_ID_SUN_EBUS, pdev); | ||
379 | if (!pdev) | ||
380 | break; | ||
381 | |||
382 | cookie = pdev->sysdata; | ||
383 | dp = cookie->prom_node; | ||
384 | |||
385 | ebus->next = (struct linux_ebus *) | ||
386 | ebus_alloc(sizeof(struct linux_ebus)); | ||
387 | ebus = ebus->next; | ||
388 | ebus->next = NULL; | ||
389 | ++num_ebus; | ||
390 | } | ||
391 | if (pdev) | ||
392 | pci_dev_put(pdev); | ||
393 | } | ||
diff --git a/arch/sparc/kernel/entry.S b/arch/sparc/kernel/entry.S index e8cdf715a546..faf9ccd9ef5d 100644 --- a/arch/sparc/kernel/entry.S +++ b/arch/sparc/kernel/entry.S | |||
@@ -20,11 +20,7 @@ | |||
20 | #include <asm/memreg.h> | 20 | #include <asm/memreg.h> |
21 | #include <asm/page.h> | 21 | #include <asm/page.h> |
22 | #include <asm/pgtable.h> | 22 | #include <asm/pgtable.h> |
23 | #ifdef CONFIG_SUN4 | ||
24 | #include <asm/pgtsun4.h> | ||
25 | #else | ||
26 | #include <asm/pgtsun4c.h> | 23 | #include <asm/pgtsun4c.h> |
27 | #endif | ||
28 | #include <asm/winmacro.h> | 24 | #include <asm/winmacro.h> |
29 | #include <asm/signal.h> | 25 | #include <asm/signal.h> |
30 | #include <asm/obio.h> | 26 | #include <asm/obio.h> |
@@ -276,17 +272,18 @@ smp4m_ticker: | |||
276 | */ | 272 | */ |
277 | maybe_smp4m_msg: | 273 | maybe_smp4m_msg: |
278 | GET_PROCESSOR4M_ID(o3) | 274 | GET_PROCESSOR4M_ID(o3) |
279 | set sun4m_interrupts, %l5 | 275 | sethi %hi(sun4m_irq_percpu), %l5 |
280 | ld [%l5], %o5 | 276 | sll %o3, 2, %o3 |
277 | or %l5, %lo(sun4m_irq_percpu), %o5 | ||
281 | sethi %hi(0x40000000), %o2 | 278 | sethi %hi(0x40000000), %o2 |
282 | sll %o3, 12, %o3 | ||
283 | ld [%o5 + %o3], %o1 | 279 | ld [%o5 + %o3], %o1 |
284 | andcc %o1, %o2, %g0 | 280 | ld [%o1 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending |
281 | andcc %o3, %o2, %g0 | ||
285 | be,a smp4m_ticker | 282 | be,a smp4m_ticker |
286 | cmp %l7, 14 | 283 | cmp %l7, 14 |
287 | st %o2, [%o5 + 0x4] | 284 | st %o2, [%o1 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x40000000 |
288 | WRITE_PAUSE | 285 | WRITE_PAUSE |
289 | ld [%o5], %g0 | 286 | ld [%o1 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending |
290 | WRITE_PAUSE | 287 | WRITE_PAUSE |
291 | or %l0, PSR_PIL, %l4 | 288 | or %l0, PSR_PIL, %l4 |
292 | wr %l4, 0x0, %psr | 289 | wr %l4, 0x0, %psr |
@@ -304,16 +301,16 @@ linux_trap_ipi15_sun4m: | |||
304 | SAVE_ALL | 301 | SAVE_ALL |
305 | sethi %hi(0x80000000), %o2 | 302 | sethi %hi(0x80000000), %o2 |
306 | GET_PROCESSOR4M_ID(o0) | 303 | GET_PROCESSOR4M_ID(o0) |
307 | set sun4m_interrupts, %l5 | 304 | sethi %hi(sun4m_irq_percpu), %l5 |
308 | ld [%l5], %o5 | 305 | or %l5, %lo(sun4m_irq_percpu), %o5 |
309 | sll %o0, 12, %o0 | 306 | sll %o0, 2, %o0 |
310 | add %o5, %o0, %o5 | 307 | ld [%o5 + %o0], %o5 |
311 | ld [%o5], %o3 | 308 | ld [%o5 + 0x00], %o3 ! sun4m_irq_percpu[cpu]->pending |
312 | andcc %o3, %o2, %g0 | 309 | andcc %o3, %o2, %g0 |
313 | be 1f ! Must be an NMI async memory error | 310 | be 1f ! Must be an NMI async memory error |
314 | st %o2, [%o5 + 4] | 311 | st %o2, [%o5 + 0x04] ! sun4m_irq_percpu[cpu]->clear=0x80000000 |
315 | WRITE_PAUSE | 312 | WRITE_PAUSE |
316 | ld [%o5], %g0 | 313 | ld [%o5 + 0x00], %g0 ! sun4m_irq_percpu[cpu]->pending |
317 | WRITE_PAUSE | 314 | WRITE_PAUSE |
318 | or %l0, PSR_PIL, %l4 | 315 | or %l0, PSR_PIL, %l4 |
319 | wr %l4, 0x0, %psr | 316 | wr %l4, 0x0, %psr |
@@ -327,12 +324,11 @@ linux_trap_ipi15_sun4m: | |||
327 | 1: | 324 | 1: |
328 | /* NMI async memory error handling. */ | 325 | /* NMI async memory error handling. */ |
329 | sethi %hi(0x80000000), %l4 | 326 | sethi %hi(0x80000000), %l4 |
330 | sethi %hi(0x4000), %o3 | 327 | sethi %hi(sun4m_irq_global), %o5 |
331 | sub %o5, %o0, %o5 | 328 | ld [%o5 + %lo(sun4m_irq_global)], %l5 |
332 | add %o5, %o3, %l5 | 329 | st %l4, [%l5 + 0x0c] ! sun4m_irq_global->mask_set=0x80000000 |
333 | st %l4, [%l5 + 0xc] | ||
334 | WRITE_PAUSE | 330 | WRITE_PAUSE |
335 | ld [%l5], %g0 | 331 | ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending |
336 | WRITE_PAUSE | 332 | WRITE_PAUSE |
337 | or %l0, PSR_PIL, %l4 | 333 | or %l0, PSR_PIL, %l4 |
338 | wr %l4, 0x0, %psr | 334 | wr %l4, 0x0, %psr |
@@ -341,9 +337,9 @@ linux_trap_ipi15_sun4m: | |||
341 | WRITE_PAUSE | 337 | WRITE_PAUSE |
342 | call sun4m_nmi | 338 | call sun4m_nmi |
343 | nop | 339 | nop |
344 | st %l4, [%l5 + 0x8] | 340 | st %l4, [%l5 + 0x08] ! sun4m_irq_global->mask_clear=0x80000000 |
345 | WRITE_PAUSE | 341 | WRITE_PAUSE |
346 | ld [%l5], %g0 | 342 | ld [%l5 + 0x00], %g0 ! sun4m_irq_global->pending |
347 | WRITE_PAUSE | 343 | WRITE_PAUSE |
348 | RESTORE_ALL | 344 | RESTORE_ALL |
349 | 345 | ||
@@ -775,11 +771,7 @@ vac_linesize_patch_32: subcc %l7, 32, %l7 | |||
775 | * Ugly, but we cant use hardware flushing on the sun4 and we'd require | 771 | * Ugly, but we cant use hardware flushing on the sun4 and we'd require |
776 | * two instructions (Anton) | 772 | * two instructions (Anton) |
777 | */ | 773 | */ |
778 | #ifdef CONFIG_SUN4 | ||
779 | vac_hwflush_patch1_on: nop | ||
780 | #else | ||
781 | vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 | 774 | vac_hwflush_patch1_on: addcc %l7, -PAGE_SIZE, %l7 |
782 | #endif | ||
783 | 775 | ||
784 | vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG | 776 | vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG |
785 | 777 | ||
@@ -798,42 +790,10 @@ vac_hwflush_patch2_on: sta %g0, [%l3 + %l7] ASI_HWFLUSHSEG | |||
798 | ! %l7 = 1 for textfault | 790 | ! %l7 = 1 for textfault |
799 | ! We want error in %l5, vaddr in %l6 | 791 | ! We want error in %l5, vaddr in %l6 |
800 | sun4c_fault: | 792 | sun4c_fault: |
801 | #ifdef CONFIG_SUN4 | ||
802 | sethi %hi(sun4c_memerr_reg), %l4 | ||
803 | ld [%l4+%lo(sun4c_memerr_reg)], %l4 ! memerr ctrl reg addr | ||
804 | ld [%l4], %l6 ! memerr ctrl reg | ||
805 | ld [%l4 + 4], %l5 ! memerr vaddr reg | ||
806 | andcc %l6, 0x80, %g0 ! check for error type | ||
807 | st %g0, [%l4 + 4] ! clear the error | ||
808 | be 0f ! normal error | ||
809 | sethi %hi(AC_BUS_ERROR), %l4 ! bus err reg addr | ||
810 | |||
811 | call prom_halt ! something weird happened | ||
812 | ! what exactly did happen? | ||
813 | ! what should we do here? | ||
814 | |||
815 | 0: or %l4, %lo(AC_BUS_ERROR), %l4 ! bus err reg addr | ||
816 | lduba [%l4] ASI_CONTROL, %l6 ! bus err reg | ||
817 | |||
818 | cmp %l7, 1 ! text fault? | ||
819 | be 1f ! yes | ||
820 | nop | ||
821 | |||
822 | ld [%l1], %l4 ! load instruction that caused fault | ||
823 | srl %l4, 21, %l4 | ||
824 | andcc %l4, 1, %g0 ! store instruction? | ||
825 | |||
826 | be 1f ! no | ||
827 | sethi %hi(SUN4C_SYNC_BADWRITE), %l4 ! yep | ||
828 | ! %lo(SUN4C_SYNC_BADWRITE) = 0 | ||
829 | or %l4, %l6, %l6 ! set write bit to emulate sun4c | ||
830 | 1: | ||
831 | #else | ||
832 | sethi %hi(AC_SYNC_ERR), %l4 | 793 | sethi %hi(AC_SYNC_ERR), %l4 |
833 | add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6 | 794 | add %l4, 0x4, %l6 ! AC_SYNC_VA in %l6 |
834 | lda [%l6] ASI_CONTROL, %l5 ! Address | 795 | lda [%l6] ASI_CONTROL, %l5 ! Address |
835 | lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit | 796 | lda [%l4] ASI_CONTROL, %l6 ! Error, retained for a bit |
836 | #endif | ||
837 | 797 | ||
838 | andn %l5, 0xfff, %l5 ! Encode all info into l7 | 798 | andn %l5, 0xfff, %l5 ! Encode all info into l7 |
839 | srl %l6, 14, %l4 | 799 | srl %l6, 14, %l4 |
@@ -880,12 +840,7 @@ sun4c_fault: | |||
880 | or %l4, %lo(swapper_pg_dir), %l4 | 840 | or %l4, %lo(swapper_pg_dir), %l4 |
881 | sll %l6, 2, %l6 | 841 | sll %l6, 2, %l6 |
882 | ld [%l4 + %l6], %l4 | 842 | ld [%l4 + %l6], %l4 |
883 | #ifdef CONFIG_SUN4 | ||
884 | sethi %hi(PAGE_MASK), %l6 | ||
885 | andcc %l4, %l6, %g0 | ||
886 | #else | ||
887 | andcc %l4, PAGE_MASK, %g0 | 843 | andcc %l4, PAGE_MASK, %g0 |
888 | #endif | ||
889 | be sun4c_fault_fromuser | 844 | be sun4c_fault_fromuser |
890 | lduXa [%l5] ASI_SEGMAP, %l4 | 845 | lduXa [%l5] ASI_SEGMAP, %l4 |
891 | 846 | ||
@@ -937,11 +892,7 @@ invalid_segment_patch1: | |||
937 | ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr | 892 | ld [%l6 + 0x08], %l3 ! tmp = entry->vaddr |
938 | 893 | ||
939 | ! Flush segment from the cache. | 894 | ! Flush segment from the cache. |
940 | #ifdef CONFIG_SUN4 | ||
941 | sethi %hi((128 * 1024)), %l7 | ||
942 | #else | ||
943 | sethi %hi((64 * 1024)), %l7 | 895 | sethi %hi((64 * 1024)), %l7 |
944 | #endif | ||
945 | 9: | 896 | 9: |
946 | vac_hwflush_patch1: | 897 | vac_hwflush_patch1: |
947 | vac_linesize_patch: | 898 | vac_linesize_patch: |
@@ -1029,12 +980,7 @@ invalid_segment_patch2: | |||
1029 | or %l4, %lo(swapper_pg_dir), %l4 | 980 | or %l4, %lo(swapper_pg_dir), %l4 |
1030 | sll %l3, 2, %l3 | 981 | sll %l3, 2, %l3 |
1031 | ld [%l4 + %l3], %l4 | 982 | ld [%l4 + %l3], %l4 |
1032 | #ifndef CONFIG_SUN4 | ||
1033 | and %l4, PAGE_MASK, %l4 | 983 | and %l4, PAGE_MASK, %l4 |
1034 | #else | ||
1035 | sethi %hi(PAGE_MASK), %l6 | ||
1036 | and %l4, %l6, %l4 | ||
1037 | #endif | ||
1038 | 984 | ||
1039 | srl %l5, (PAGE_SHIFT - 2), %l6 | 985 | srl %l5, (PAGE_SHIFT - 2), %l6 |
1040 | and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6 | 986 | and %l6, ((SUN4C_PTRS_PER_PTE - 1) << 2), %l6 |
diff --git a/arch/sparc/kernel/head.S b/arch/sparc/kernel/head.S index 50d9a16af795..2d325fd84579 100644 --- a/arch/sparc/kernel/head.S +++ b/arch/sparc/kernel/head.S | |||
@@ -63,15 +63,9 @@ cputypvar_sun4m: | |||
63 | 63 | ||
64 | .align 4 | 64 | .align 4 |
65 | 65 | ||
66 | #ifndef CONFIG_SUN4 | ||
67 | sun4_notsup: | 66 | sun4_notsup: |
68 | .asciz "Sparc-Linux sun4 needs a specially compiled kernel, turn CONFIG_SUN4 on.\n\n" | 67 | .asciz "Sparc-Linux sun4 support does no longer exist.\n\n" |
69 | .align 4 | 68 | .align 4 |
70 | #else | ||
71 | sun4cdm_notsup: | ||
72 | .asciz "Kernel compiled with CONFIG_SUN4 cannot run on SUN4C/SUN4M/SUN4D\nTurn CONFIG_SUN4 off.\n\n" | ||
73 | .align 4 | ||
74 | #endif | ||
75 | 69 | ||
76 | sun4e_notsup: | 70 | sun4e_notsup: |
77 | .asciz "Sparc-Linux sun4e support does not exist\n\n" | 71 | .asciz "Sparc-Linux sun4e support does not exist\n\n" |
@@ -780,15 +774,6 @@ execute_in_high_mem: | |||
780 | nop | 774 | nop |
781 | 775 | ||
782 | found_version: | 776 | found_version: |
783 | #ifdef CONFIG_SUN4 | ||
784 | /* For people who try sun4 kernels, even if Configure.help advises them. */ | ||
785 | ld [%g7 + 0x68], %o1 | ||
786 | set sun4cdm_notsup, %o0 | ||
787 | call %o1 | ||
788 | nop | ||
789 | b halt_me | ||
790 | nop | ||
791 | #endif | ||
792 | /* Get the machine type via the mysterious romvec node operations. */ | 777 | /* Get the machine type via the mysterious romvec node operations. */ |
793 | 778 | ||
794 | add %g7, 0x1c, %l1 | 779 | add %g7, 0x1c, %l1 |
@@ -1150,15 +1135,6 @@ sun4c_continue_boot: | |||
1150 | nop | 1135 | nop |
1151 | 1136 | ||
1152 | sun4_init: | 1137 | sun4_init: |
1153 | #ifdef CONFIG_SUN4 | ||
1154 | /* There, happy now Adrian? */ | ||
1155 | set cputypval, %o2 ! Let everyone know we | ||
1156 | set ' ', %o0 ! are a "sun4 " architecture | ||
1157 | stb %o0, [%o2 + 0x4] | ||
1158 | |||
1159 | b got_prop | ||
1160 | nop | ||
1161 | #else | ||
1162 | sethi %hi(SUN4_PROM_VECTOR+0x84), %o1 | 1138 | sethi %hi(SUN4_PROM_VECTOR+0x84), %o1 |
1163 | ld [%o1 + %lo(SUN4_PROM_VECTOR+0x84)], %o1 | 1139 | ld [%o1 + %lo(SUN4_PROM_VECTOR+0x84)], %o1 |
1164 | set sun4_notsup, %o0 | 1140 | set sun4_notsup, %o0 |
@@ -1170,7 +1146,7 @@ sun4_init: | |||
1170 | nop | 1146 | nop |
1171 | 1: ba 1b ! Cannot exit into KMON | 1147 | 1: ba 1b ! Cannot exit into KMON |
1172 | nop | 1148 | nop |
1173 | #endif | 1149 | |
1174 | no_sun4e_here: | 1150 | no_sun4e_here: |
1175 | ld [%g7 + 0x68], %o1 | 1151 | ld [%g7 + 0x68], %o1 |
1176 | set sun4e_notsup, %o0 | 1152 | set sun4e_notsup, %o0 |
diff --git a/arch/sparc/kernel/idprom.c b/arch/sparc/kernel/idprom.c index fc511f3c4c18..223a6582e1e2 100644 --- a/arch/sparc/kernel/idprom.c +++ b/arch/sparc/kernel/idprom.c | |||
@@ -12,10 +12,6 @@ | |||
12 | #include <asm/oplib.h> | 12 | #include <asm/oplib.h> |
13 | #include <asm/idprom.h> | 13 | #include <asm/idprom.h> |
14 | #include <asm/machines.h> /* Fun with Sun released architectures. */ | 14 | #include <asm/machines.h> /* Fun with Sun released architectures. */ |
15 | #ifdef CONFIG_SUN4 | ||
16 | #include <asm/sun4paddr.h> | ||
17 | extern void sun4setup(void); | ||
18 | #endif | ||
19 | 15 | ||
20 | struct idprom *idprom; | 16 | struct idprom *idprom; |
21 | static struct idprom idprom_buffer; | 17 | static struct idprom idprom_buffer; |
@@ -101,7 +97,4 @@ void __init idprom_init(void) | |||
101 | idprom->id_ethaddr[0], idprom->id_ethaddr[1], | 97 | idprom->id_ethaddr[0], idprom->id_ethaddr[1], |
102 | idprom->id_ethaddr[2], idprom->id_ethaddr[3], | 98 | idprom->id_ethaddr[2], idprom->id_ethaddr[3], |
103 | idprom->id_ethaddr[4], idprom->id_ethaddr[5]); | 99 | idprom->id_ethaddr[4], idprom->id_ethaddr[5]); |
104 | #ifdef CONFIG_SUN4 | ||
105 | sun4setup(); | ||
106 | #endif | ||
107 | } | 100 | } |
diff --git a/arch/sparc/kernel/ioport.c b/arch/sparc/kernel/ioport.c index 2a8a847764d8..4f025b36934b 100644 --- a/arch/sparc/kernel/ioport.c +++ b/arch/sparc/kernel/ioport.c | |||
@@ -42,10 +42,13 @@ | |||
42 | #include <asm/vaddrs.h> | 42 | #include <asm/vaddrs.h> |
43 | #include <asm/oplib.h> | 43 | #include <asm/oplib.h> |
44 | #include <asm/prom.h> | 44 | #include <asm/prom.h> |
45 | #include <asm/sbus.h> | ||
46 | #include <asm/page.h> | 45 | #include <asm/page.h> |
47 | #include <asm/pgalloc.h> | 46 | #include <asm/pgalloc.h> |
48 | #include <asm/dma.h> | 47 | #include <asm/dma.h> |
48 | #include <asm/iommu.h> | ||
49 | #include <asm/io-unit.h> | ||
50 | |||
51 | #include "dma.h" | ||
49 | 52 | ||
50 | #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ | 53 | #define mmu_inval_dma_area(p, l) /* Anton pulled it out for 2.4.0-xx */ |
51 | 54 | ||
@@ -139,15 +142,6 @@ void iounmap(volatile void __iomem *virtual) | |||
139 | } | 142 | } |
140 | } | 143 | } |
141 | 144 | ||
142 | /* | ||
143 | */ | ||
144 | void __iomem *sbus_ioremap(struct resource *phyres, unsigned long offset, | ||
145 | unsigned long size, char *name) | ||
146 | { | ||
147 | return _sparc_alloc_io(phyres->flags & 0xF, | ||
148 | phyres->start + offset, size, name); | ||
149 | } | ||
150 | |||
151 | void __iomem *of_ioremap(struct resource *res, unsigned long offset, | 145 | void __iomem *of_ioremap(struct resource *res, unsigned long offset, |
152 | unsigned long size, char *name) | 146 | unsigned long size, char *name) |
153 | { | 147 | { |
@@ -164,13 +158,6 @@ void of_iounmap(struct resource *res, void __iomem *base, unsigned long size) | |||
164 | EXPORT_SYMBOL(of_iounmap); | 158 | EXPORT_SYMBOL(of_iounmap); |
165 | 159 | ||
166 | /* | 160 | /* |
167 | */ | ||
168 | void sbus_iounmap(volatile void __iomem *addr, unsigned long size) | ||
169 | { | ||
170 | iounmap(addr); | ||
171 | } | ||
172 | |||
173 | /* | ||
174 | * Meat of mapping | 161 | * Meat of mapping |
175 | */ | 162 | */ |
176 | static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, | 163 | static void __iomem *_sparc_alloc_io(unsigned int busno, unsigned long phys, |
@@ -246,63 +233,19 @@ static void _sparc_free_io(struct resource *res) | |||
246 | 233 | ||
247 | #ifdef CONFIG_SBUS | 234 | #ifdef CONFIG_SBUS |
248 | 235 | ||
249 | void sbus_set_sbus64(struct sbus_dev *sdev, int x) | 236 | void sbus_set_sbus64(struct device *dev, int x) |
250 | { | 237 | { |
251 | printk("sbus_set_sbus64: unsupported\n"); | 238 | printk("sbus_set_sbus64: unsupported\n"); |
252 | } | 239 | } |
253 | 240 | ||
254 | extern unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq); | ||
255 | void __init sbus_fill_device_irq(struct sbus_dev *sdev) | ||
256 | { | ||
257 | struct linux_prom_irqs irqs[PROMINTR_MAX]; | ||
258 | int len; | ||
259 | |||
260 | len = prom_getproperty(sdev->prom_node, "intr", | ||
261 | (char *)irqs, sizeof(irqs)); | ||
262 | if (len != -1) { | ||
263 | sdev->num_irqs = len / 8; | ||
264 | if (sdev->num_irqs == 0) { | ||
265 | sdev->irqs[0] = 0; | ||
266 | } else if (sparc_cpu_model == sun4d) { | ||
267 | for (len = 0; len < sdev->num_irqs; len++) | ||
268 | sdev->irqs[len] = | ||
269 | sun4d_build_irq(sdev, irqs[len].pri); | ||
270 | } else { | ||
271 | for (len = 0; len < sdev->num_irqs; len++) | ||
272 | sdev->irqs[len] = irqs[len].pri; | ||
273 | } | ||
274 | } else { | ||
275 | int interrupts[PROMINTR_MAX]; | ||
276 | |||
277 | /* No "intr" node found-- check for "interrupts" node. | ||
278 | * This node contains SBus interrupt levels, not IPLs | ||
279 | * as in "intr", and no vector values. We convert | ||
280 | * SBus interrupt levels to PILs (platform specific). | ||
281 | */ | ||
282 | len = prom_getproperty(sdev->prom_node, "interrupts", | ||
283 | (char *)interrupts, sizeof(interrupts)); | ||
284 | if (len == -1) { | ||
285 | sdev->irqs[0] = 0; | ||
286 | sdev->num_irqs = 0; | ||
287 | } else { | ||
288 | sdev->num_irqs = len / sizeof(int); | ||
289 | for (len = 0; len < sdev->num_irqs; len++) { | ||
290 | sdev->irqs[len] = | ||
291 | sbint_to_irq(sdev, interrupts[len]); | ||
292 | } | ||
293 | } | ||
294 | } | ||
295 | } | ||
296 | |||
297 | /* | 241 | /* |
298 | * Allocate a chunk of memory suitable for DMA. | 242 | * Allocate a chunk of memory suitable for DMA. |
299 | * Typically devices use them for control blocks. | 243 | * Typically devices use them for control blocks. |
300 | * CPU may access them without any explicit flushing. | 244 | * CPU may access them without any explicit flushing. |
301 | * | ||
302 | * XXX Some clever people know that sdev is not used and supply NULL. Watch. | ||
303 | */ | 245 | */ |
304 | void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp) | 246 | void *sbus_alloc_consistent(struct device *dev, long len, u32 *dma_addrp) |
305 | { | 247 | { |
248 | struct of_device *op = to_of_device(dev); | ||
306 | unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; | 249 | unsigned long len_total = (len + PAGE_SIZE-1) & PAGE_MASK; |
307 | unsigned long va; | 250 | unsigned long va; |
308 | struct resource *res; | 251 | struct resource *res; |
@@ -336,13 +279,10 @@ void *sbus_alloc_consistent(struct sbus_dev *sdev, long len, u32 *dma_addrp) | |||
336 | * XXX That's where sdev would be used. Currently we load | 279 | * XXX That's where sdev would be used. Currently we load |
337 | * all iommu tables with the same translations. | 280 | * all iommu tables with the same translations. |
338 | */ | 281 | */ |
339 | if (mmu_map_dma_area(dma_addrp, va, res->start, len_total) != 0) | 282 | if (mmu_map_dma_area(dev, dma_addrp, va, res->start, len_total) != 0) |
340 | goto err_noiommu; | 283 | goto err_noiommu; |
341 | 284 | ||
342 | /* Set the resource name, if known. */ | 285 | res->name = op->node->name; |
343 | if (sdev) { | ||
344 | res->name = sdev->prom_name; | ||
345 | } | ||
346 | 286 | ||
347 | return (void *)(unsigned long)res->start; | 287 | return (void *)(unsigned long)res->start; |
348 | 288 | ||
@@ -356,7 +296,7 @@ err_nopages: | |||
356 | return NULL; | 296 | return NULL; |
357 | } | 297 | } |
358 | 298 | ||
359 | void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba) | 299 | void sbus_free_consistent(struct device *dev, long n, void *p, u32 ba) |
360 | { | 300 | { |
361 | struct resource *res; | 301 | struct resource *res; |
362 | struct page *pgv; | 302 | struct page *pgv; |
@@ -383,8 +323,8 @@ void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba) | |||
383 | kfree(res); | 323 | kfree(res); |
384 | 324 | ||
385 | /* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */ | 325 | /* mmu_inval_dma_area(va, n); */ /* it's consistent, isn't it */ |
386 | pgv = mmu_translate_dvma(ba); | 326 | pgv = virt_to_page(p); |
387 | mmu_unmap_dma_area(ba, n); | 327 | mmu_unmap_dma_area(dev, ba, n); |
388 | 328 | ||
389 | __free_pages(pgv, get_order(n)); | 329 | __free_pages(pgv, get_order(n)); |
390 | } | 330 | } |
@@ -394,7 +334,7 @@ void sbus_free_consistent(struct sbus_dev *sdev, long n, void *p, u32 ba) | |||
394 | * CPU view of this memory may be inconsistent with | 334 | * CPU view of this memory may be inconsistent with |
395 | * a device view and explicit flushing is necessary. | 335 | * a device view and explicit flushing is necessary. |
396 | */ | 336 | */ |
397 | dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *va, size_t len, int direction) | 337 | dma_addr_t sbus_map_single(struct device *dev, void *va, size_t len, int direction) |
398 | { | 338 | { |
399 | /* XXX why are some lengths signed, others unsigned? */ | 339 | /* XXX why are some lengths signed, others unsigned? */ |
400 | if (len <= 0) { | 340 | if (len <= 0) { |
@@ -404,17 +344,17 @@ dma_addr_t sbus_map_single(struct sbus_dev *sdev, void *va, size_t len, int dire | |||
404 | if (len > 256*1024) { /* __get_free_pages() limit */ | 344 | if (len > 256*1024) { /* __get_free_pages() limit */ |
405 | return 0; | 345 | return 0; |
406 | } | 346 | } |
407 | return mmu_get_scsi_one(va, len, sdev->bus); | 347 | return mmu_get_scsi_one(dev, va, len); |
408 | } | 348 | } |
409 | 349 | ||
410 | void sbus_unmap_single(struct sbus_dev *sdev, dma_addr_t ba, size_t n, int direction) | 350 | void sbus_unmap_single(struct device *dev, dma_addr_t ba, size_t n, int direction) |
411 | { | 351 | { |
412 | mmu_release_scsi_one(ba, n, sdev->bus); | 352 | mmu_release_scsi_one(dev, ba, n); |
413 | } | 353 | } |
414 | 354 | ||
415 | int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) | 355 | int sbus_map_sg(struct device *dev, struct scatterlist *sg, int n, int direction) |
416 | { | 356 | { |
417 | mmu_get_scsi_sgl(sg, n, sdev->bus); | 357 | mmu_get_scsi_sgl(dev, sg, n); |
418 | 358 | ||
419 | /* | 359 | /* |
420 | * XXX sparc64 can return a partial length here. sun4c should do this | 360 | * XXX sparc64 can return a partial length here. sun4c should do this |
@@ -423,145 +363,28 @@ int sbus_map_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direct | |||
423 | return n; | 363 | return n; |
424 | } | 364 | } |
425 | 365 | ||
426 | void sbus_unmap_sg(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) | 366 | void sbus_unmap_sg(struct device *dev, struct scatterlist *sg, int n, int direction) |
427 | { | ||
428 | mmu_release_scsi_sgl(sg, n, sdev->bus); | ||
429 | } | ||
430 | |||
431 | /* | ||
432 | */ | ||
433 | void sbus_dma_sync_single_for_cpu(struct sbus_dev *sdev, dma_addr_t ba, size_t size, int direction) | ||
434 | { | ||
435 | #if 0 | ||
436 | unsigned long va; | ||
437 | struct resource *res; | ||
438 | |||
439 | /* We do not need the resource, just print a message if invalid. */ | ||
440 | res = _sparc_find_resource(&_sparc_dvma, ba); | ||
441 | if (res == NULL) | ||
442 | panic("sbus_dma_sync_single: 0x%x\n", ba); | ||
443 | |||
444 | va = page_address(mmu_translate_dvma(ba)); /* XXX higmem */ | ||
445 | /* | ||
446 | * XXX This bogosity will be fixed with the iommu rewrite coming soon | ||
447 | * to a kernel near you. - Anton | ||
448 | */ | ||
449 | /* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */ | ||
450 | #endif | ||
451 | } | ||
452 | |||
453 | void sbus_dma_sync_single_for_device(struct sbus_dev *sdev, dma_addr_t ba, size_t size, int direction) | ||
454 | { | 367 | { |
455 | #if 0 | 368 | mmu_release_scsi_sgl(dev, sg, n); |
456 | unsigned long va; | ||
457 | struct resource *res; | ||
458 | |||
459 | /* We do not need the resource, just print a message if invalid. */ | ||
460 | res = _sparc_find_resource(&_sparc_dvma, ba); | ||
461 | if (res == NULL) | ||
462 | panic("sbus_dma_sync_single: 0x%x\n", ba); | ||
463 | |||
464 | va = page_address(mmu_translate_dvma(ba)); /* XXX higmem */ | ||
465 | /* | ||
466 | * XXX This bogosity will be fixed with the iommu rewrite coming soon | ||
467 | * to a kernel near you. - Anton | ||
468 | */ | ||
469 | /* mmu_inval_dma_area(va, (size + PAGE_SIZE-1) & PAGE_MASK); */ | ||
470 | #endif | ||
471 | } | 369 | } |
472 | 370 | ||
473 | void sbus_dma_sync_sg_for_cpu(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) | 371 | void sbus_dma_sync_single_for_cpu(struct device *dev, dma_addr_t ba, size_t size, int direction) |
474 | { | 372 | { |
475 | printk("sbus_dma_sync_sg_for_cpu: not implemented yet\n"); | ||
476 | } | 373 | } |
477 | 374 | ||
478 | void sbus_dma_sync_sg_for_device(struct sbus_dev *sdev, struct scatterlist *sg, int n, int direction) | 375 | void sbus_dma_sync_single_for_device(struct device *dev, dma_addr_t ba, size_t size, int direction) |
479 | { | 376 | { |
480 | printk("sbus_dma_sync_sg_for_device: not implemented yet\n"); | ||
481 | } | ||
482 | |||
483 | /* Support code for sbus_init(). */ | ||
484 | /* | ||
485 | * XXX This functions appears to be a distorted version of | ||
486 | * prom_sbus_ranges_init(), with all sun4d stuff cut away. | ||
487 | * Ask DaveM what is going on here, how is sun4d supposed to work... XXX | ||
488 | */ | ||
489 | /* added back sun4d patch from Thomas Bogendoerfer - should be OK (crn) */ | ||
490 | void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) | ||
491 | { | ||
492 | int parent_node = pn->node; | ||
493 | |||
494 | if (sparc_cpu_model == sun4d) { | ||
495 | struct linux_prom_ranges iounit_ranges[PROMREG_MAX]; | ||
496 | int num_iounit_ranges, len; | ||
497 | |||
498 | len = prom_getproperty(parent_node, "ranges", | ||
499 | (char *) iounit_ranges, | ||
500 | sizeof (iounit_ranges)); | ||
501 | if (len != -1) { | ||
502 | num_iounit_ranges = | ||
503 | (len / sizeof(struct linux_prom_ranges)); | ||
504 | prom_adjust_ranges(sbus->sbus_ranges, | ||
505 | sbus->num_sbus_ranges, | ||
506 | iounit_ranges, num_iounit_ranges); | ||
507 | } | ||
508 | } | ||
509 | } | 377 | } |
510 | 378 | ||
511 | void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) | 379 | static int __init sparc_register_ioport(void) |
512 | { | ||
513 | #ifndef CONFIG_SUN4 | ||
514 | struct device_node *parent = dp->parent; | ||
515 | |||
516 | if (sparc_cpu_model != sun4d && | ||
517 | parent != NULL && | ||
518 | !strcmp(parent->name, "iommu")) { | ||
519 | extern void iommu_init(int iommu_node, struct sbus_bus *sbus); | ||
520 | |||
521 | iommu_init(parent->node, sbus); | ||
522 | } | ||
523 | |||
524 | if (sparc_cpu_model == sun4d) { | ||
525 | extern void iounit_init(int sbi_node, int iounit_node, | ||
526 | struct sbus_bus *sbus); | ||
527 | |||
528 | iounit_init(dp->node, parent->node, sbus); | ||
529 | } | ||
530 | #endif | ||
531 | } | ||
532 | |||
533 | void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) | ||
534 | { | ||
535 | if (sparc_cpu_model == sun4d) { | ||
536 | struct device_node *parent = dp->parent; | ||
537 | |||
538 | sbus->devid = of_getintprop_default(parent, "device-id", 0); | ||
539 | sbus->board = of_getintprop_default(parent, "board#", 0); | ||
540 | } | ||
541 | } | ||
542 | |||
543 | int __init sbus_arch_preinit(void) | ||
544 | { | 380 | { |
545 | register_proc_sparc_ioport(); | 381 | register_proc_sparc_ioport(); |
546 | 382 | ||
547 | #ifdef CONFIG_SUN4 | ||
548 | { | ||
549 | extern void sun4_dvma_init(void); | ||
550 | sun4_dvma_init(); | ||
551 | } | ||
552 | return 1; | ||
553 | #else | ||
554 | return 0; | 383 | return 0; |
555 | #endif | ||
556 | } | 384 | } |
557 | 385 | ||
558 | void __init sbus_arch_postinit(void) | 386 | arch_initcall(sparc_register_ioport); |
559 | { | 387 | |
560 | if (sparc_cpu_model == sun4d) { | ||
561 | extern void sun4d_init_sbi_irq(void); | ||
562 | sun4d_init_sbi_irq(); | ||
563 | } | ||
564 | } | ||
565 | #endif /* CONFIG_SBUS */ | 388 | #endif /* CONFIG_SBUS */ |
566 | 389 | ||
567 | #ifdef CONFIG_PCI | 390 | #ifdef CONFIG_PCI |
diff --git a/arch/sparc/kernel/irq.h b/arch/sparc/kernel/irq.h index 32ef3ebd0a88..db7513881530 100644 --- a/arch/sparc/kernel/irq.h +++ b/arch/sparc/kernel/irq.h | |||
@@ -13,7 +13,6 @@ BTFIXUPDEF_CALL(void, enable_irq, unsigned int) | |||
13 | BTFIXUPDEF_CALL(void, disable_pil_irq, unsigned int) | 13 | BTFIXUPDEF_CALL(void, disable_pil_irq, unsigned int) |
14 | BTFIXUPDEF_CALL(void, enable_pil_irq, unsigned int) | 14 | BTFIXUPDEF_CALL(void, enable_pil_irq, unsigned int) |
15 | BTFIXUPDEF_CALL(void, clear_clock_irq, void) | 15 | BTFIXUPDEF_CALL(void, clear_clock_irq, void) |
16 | BTFIXUPDEF_CALL(void, clear_profile_irq, int) | ||
17 | BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) | 16 | BTFIXUPDEF_CALL(void, load_profile_irq, int, unsigned int) |
18 | 17 | ||
19 | static inline void __disable_irq(unsigned int irq) | 18 | static inline void __disable_irq(unsigned int irq) |
@@ -41,11 +40,6 @@ static inline void clear_clock_irq(void) | |||
41 | BTFIXUP_CALL(clear_clock_irq)(); | 40 | BTFIXUP_CALL(clear_clock_irq)(); |
42 | } | 41 | } |
43 | 42 | ||
44 | static inline void clear_profile_irq(int irq) | ||
45 | { | ||
46 | BTFIXUP_CALL(clear_profile_irq)(irq); | ||
47 | } | ||
48 | |||
49 | static inline void load_profile_irq(int cpu, int limit) | 43 | static inline void load_profile_irq(int cpu, int limit) |
50 | { | 44 | { |
51 | BTFIXUP_CALL(load_profile_irq)(cpu, limit); | 45 | BTFIXUP_CALL(load_profile_irq)(cpu, limit); |
diff --git a/arch/sparc/kernel/of_device.c b/arch/sparc/kernel/of_device.c index f58c537446a8..0837bd52e28f 100644 --- a/arch/sparc/kernel/of_device.c +++ b/arch/sparc/kernel/of_device.c | |||
@@ -29,15 +29,38 @@ struct of_device *of_find_device_by_node(struct device_node *dp) | |||
29 | } | 29 | } |
30 | EXPORT_SYMBOL(of_find_device_by_node); | 30 | EXPORT_SYMBOL(of_find_device_by_node); |
31 | 31 | ||
32 | #ifdef CONFIG_PCI | 32 | unsigned int irq_of_parse_and_map(struct device_node *node, int index) |
33 | struct bus_type ebus_bus_type; | 33 | { |
34 | EXPORT_SYMBOL(ebus_bus_type); | 34 | struct of_device *op = of_find_device_by_node(node); |
35 | #endif | 35 | |
36 | if (!op || index >= op->num_irqs) | ||
37 | return 0; | ||
38 | |||
39 | return op->irqs[index]; | ||
40 | } | ||
41 | EXPORT_SYMBOL(irq_of_parse_and_map); | ||
42 | |||
43 | /* Take the archdata values for IOMMU, STC, and HOSTDATA found in | ||
44 | * BUS and propagate to all child of_device objects. | ||
45 | */ | ||
46 | void of_propagate_archdata(struct of_device *bus) | ||
47 | { | ||
48 | struct dev_archdata *bus_sd = &bus->dev.archdata; | ||
49 | struct device_node *bus_dp = bus->node; | ||
50 | struct device_node *dp; | ||
51 | |||
52 | for (dp = bus_dp->child; dp; dp = dp->sibling) { | ||
53 | struct of_device *op = of_find_device_by_node(dp); | ||
36 | 54 | ||
37 | #ifdef CONFIG_SBUS | 55 | op->dev.archdata.iommu = bus_sd->iommu; |
38 | struct bus_type sbus_bus_type; | 56 | op->dev.archdata.stc = bus_sd->stc; |
39 | EXPORT_SYMBOL(sbus_bus_type); | 57 | op->dev.archdata.host_controller = bus_sd->host_controller; |
40 | #endif | 58 | op->dev.archdata.numa_node = bus_sd->numa_node; |
59 | |||
60 | if (dp->child) | ||
61 | of_propagate_archdata(op); | ||
62 | } | ||
63 | } | ||
41 | 64 | ||
42 | struct bus_type of_platform_bus_type; | 65 | struct bus_type of_platform_bus_type; |
43 | EXPORT_SYMBOL(of_platform_bus_type); | 66 | EXPORT_SYMBOL(of_platform_bus_type); |
@@ -327,6 +350,27 @@ static int __init build_one_resource(struct device_node *parent, | |||
327 | return 1; | 350 | return 1; |
328 | } | 351 | } |
329 | 352 | ||
353 | static int __init use_1to1_mapping(struct device_node *pp) | ||
354 | { | ||
355 | /* If we have a ranges property in the parent, use it. */ | ||
356 | if (of_find_property(pp, "ranges", NULL) != NULL) | ||
357 | return 0; | ||
358 | |||
359 | /* Some SBUS devices use intermediate nodes to express | ||
360 | * hierarchy within the device itself. These aren't | ||
361 | * real bus nodes, and don't have a 'ranges' property. | ||
362 | * But, we should still pass the translation work up | ||
363 | * to the SBUS itself. | ||
364 | */ | ||
365 | if (!strcmp(pp->name, "dma") || | ||
366 | !strcmp(pp->name, "espdma") || | ||
367 | !strcmp(pp->name, "ledma") || | ||
368 | !strcmp(pp->name, "lebuffer")) | ||
369 | return 0; | ||
370 | |||
371 | return 1; | ||
372 | } | ||
373 | |||
330 | static int of_resource_verbose; | 374 | static int of_resource_verbose; |
331 | 375 | ||
332 | static void __init build_device_resources(struct of_device *op, | 376 | static void __init build_device_resources(struct of_device *op, |
@@ -373,10 +417,7 @@ static void __init build_device_resources(struct of_device *op, | |||
373 | 417 | ||
374 | flags = bus->get_flags(reg, 0); | 418 | flags = bus->get_flags(reg, 0); |
375 | 419 | ||
376 | /* If the immediate parent has no ranges property to apply, | 420 | if (use_1to1_mapping(pp)) { |
377 | * just use a 1<->1 mapping. | ||
378 | */ | ||
379 | if (of_find_property(pp, "ranges", NULL) == NULL) { | ||
380 | result = of_read_addr(addr, na); | 421 | result = of_read_addr(addr, na); |
381 | goto build_res; | 422 | goto build_res; |
382 | } | 423 | } |
@@ -565,15 +606,6 @@ static int __init of_bus_driver_init(void) | |||
565 | int err; | 606 | int err; |
566 | 607 | ||
567 | err = of_bus_type_init(&of_platform_bus_type, "of"); | 608 | err = of_bus_type_init(&of_platform_bus_type, "of"); |
568 | #ifdef CONFIG_PCI | ||
569 | if (!err) | ||
570 | err = of_bus_type_init(&ebus_bus_type, "ebus"); | ||
571 | #endif | ||
572 | #ifdef CONFIG_SBUS | ||
573 | if (!err) | ||
574 | err = of_bus_type_init(&sbus_bus_type, "sbus"); | ||
575 | #endif | ||
576 | |||
577 | if (!err) | 609 | if (!err) |
578 | scan_of_devices(); | 610 | scan_of_devices(); |
579 | 611 | ||
diff --git a/arch/sparc/kernel/pcic.c b/arch/sparc/kernel/pcic.c index a6a6f9823370..462584e55fba 100644 --- a/arch/sparc/kernel/pcic.c +++ b/arch/sparc/kernel/pcic.c | |||
@@ -17,8 +17,6 @@ | |||
17 | #include <linux/slab.h> | 17 | #include <linux/slab.h> |
18 | #include <linux/jiffies.h> | 18 | #include <linux/jiffies.h> |
19 | 19 | ||
20 | #include <asm/ebus.h> | ||
21 | #include <asm/sbus.h> /* for sanity check... */ | ||
22 | #include <asm/swift.h> /* for cache flushing. */ | 20 | #include <asm/swift.h> /* for cache flushing. */ |
23 | #include <asm/io.h> | 21 | #include <asm/io.h> |
24 | 22 | ||
@@ -430,7 +428,6 @@ static int __init pcic_init(void) | |||
430 | 428 | ||
431 | pcic_pbm_scan_bus(pcic); | 429 | pcic_pbm_scan_bus(pcic); |
432 | 430 | ||
433 | ebus_init(); | ||
434 | return 0; | 431 | return 0; |
435 | } | 432 | } |
436 | 433 | ||
@@ -493,10 +490,6 @@ static void pcic_map_pci_device(struct linux_pcic *pcic, | |||
493 | * do ioremap() before accessing PC-style I/O, | 490 | * do ioremap() before accessing PC-style I/O, |
494 | * we supply virtual, ready to access address. | 491 | * we supply virtual, ready to access address. |
495 | * | 492 | * |
496 | * Ebus devices do not come here even if | ||
497 | * CheerIO makes a similar conversion. | ||
498 | * See ebus.c for details. | ||
499 | * | ||
500 | * Note that request_region() | 493 | * Note that request_region() |
501 | * works for these devices. | 494 | * works for these devices. |
502 | * | 495 | * |
@@ -677,7 +670,7 @@ void __devinit pcibios_fixup_bus(struct pci_bus *bus) | |||
677 | } | 670 | } |
678 | 671 | ||
679 | /* | 672 | /* |
680 | * pcic_pin_to_irq() is exported to ebus.c. | 673 | * pcic_pin_to_irq() is exported to bus probing code |
681 | */ | 674 | */ |
682 | unsigned int | 675 | unsigned int |
683 | pcic_pin_to_irq(unsigned int pin, const char *name) | 676 | pcic_pin_to_irq(unsigned int pin, const char *name) |
@@ -904,11 +897,6 @@ static void pcic_enable_irq(unsigned int irq_nr) | |||
904 | local_irq_restore(flags); | 897 | local_irq_restore(flags); |
905 | } | 898 | } |
906 | 899 | ||
907 | static void pcic_clear_profile_irq(int cpu) | ||
908 | { | ||
909 | printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); | ||
910 | } | ||
911 | |||
912 | static void pcic_load_profile_irq(int cpu, unsigned int limit) | 900 | static void pcic_load_profile_irq(int cpu, unsigned int limit) |
913 | { | 901 | { |
914 | printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); | 902 | printk("PCIC: unimplemented code: FILE=%s LINE=%d", __FILE__, __LINE__); |
@@ -934,7 +922,6 @@ void __init sun4m_pci_init_IRQ(void) | |||
934 | BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM); | 922 | BTFIXUPSET_CALL(enable_pil_irq, pcic_enable_pil_irq, BTFIXUPCALL_NORM); |
935 | BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM); | 923 | BTFIXUPSET_CALL(disable_pil_irq, pcic_disable_pil_irq, BTFIXUPCALL_NORM); |
936 | BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); | 924 | BTFIXUPSET_CALL(clear_clock_irq, pcic_clear_clock_irq, BTFIXUPCALL_NORM); |
937 | BTFIXUPSET_CALL(clear_profile_irq, pcic_clear_profile_irq, BTFIXUPCALL_NORM); | ||
938 | BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); | 925 | BTFIXUPSET_CALL(load_profile_irq, pcic_load_profile_irq, BTFIXUPCALL_NORM); |
939 | } | 926 | } |
940 | 927 | ||
diff --git a/arch/sparc/kernel/pmc.c b/arch/sparc/kernel/pmc.c index 7eca8871ff47..2afcfab4f11c 100644 --- a/arch/sparc/kernel/pmc.c +++ b/arch/sparc/kernel/pmc.c | |||
@@ -8,11 +8,11 @@ | |||
8 | #include <linux/fs.h> | 8 | #include <linux/fs.h> |
9 | #include <linux/errno.h> | 9 | #include <linux/errno.h> |
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | #include <linux/miscdevice.h> | ||
12 | #include <linux/pm.h> | 11 | #include <linux/pm.h> |
12 | #include <linux/of.h> | ||
13 | #include <linux/of_device.h> | ||
13 | 14 | ||
14 | #include <asm/io.h> | 15 | #include <asm/io.h> |
15 | #include <asm/sbus.h> | ||
16 | #include <asm/oplib.h> | 16 | #include <asm/oplib.h> |
17 | #include <asm/uaccess.h> | 17 | #include <asm/uaccess.h> |
18 | #include <asm/auxio.h> | 18 | #include <asm/auxio.h> |
@@ -23,17 +23,15 @@ | |||
23 | * #define PMC_NO_IDLE | 23 | * #define PMC_NO_IDLE |
24 | */ | 24 | */ |
25 | 25 | ||
26 | #define PMC_MINOR MISC_DYNAMIC_MINOR | ||
27 | #define PMC_OBPNAME "SUNW,pmc" | 26 | #define PMC_OBPNAME "SUNW,pmc" |
28 | #define PMC_DEVNAME "pmc" | 27 | #define PMC_DEVNAME "pmc" |
29 | 28 | ||
30 | #define PMC_IDLE_REG 0x00 | 29 | #define PMC_IDLE_REG 0x00 |
31 | #define PMC_IDLE_ON 0x01 | 30 | #define PMC_IDLE_ON 0x01 |
32 | 31 | ||
33 | volatile static u8 __iomem *regs; | 32 | static u8 __iomem *regs; |
34 | static int pmc_regsize; | ||
35 | 33 | ||
36 | #define pmc_readb(offs) (sbus_readb(regs+offs)) | 34 | #define pmc_readb(offs) (sbus_readb(regs+offs)) |
37 | #define pmc_writeb(val, offs) (sbus_writeb(val, regs+offs)) | 35 | #define pmc_writeb(val, offs) (sbus_writeb(val, regs+offs)) |
38 | 36 | ||
39 | /* | 37 | /* |
@@ -53,31 +51,11 @@ void pmc_swift_idle(void) | |||
53 | #endif | 51 | #endif |
54 | } | 52 | } |
55 | 53 | ||
56 | static inline void pmc_free(void) | 54 | static int __devinit pmc_probe(struct of_device *op, |
55 | const struct of_device_id *match) | ||
57 | { | 56 | { |
58 | sbus_iounmap(regs, pmc_regsize); | 57 | regs = of_ioremap(&op->resource[0], 0, |
59 | } | 58 | resource_size(&op->resource[0]), PMC_OBPNAME); |
60 | |||
61 | static int __init pmc_probe(void) | ||
62 | { | ||
63 | struct sbus_bus *sbus = NULL; | ||
64 | struct sbus_dev *sdev = NULL; | ||
65 | for_each_sbus(sbus) { | ||
66 | for_each_sbusdev(sdev, sbus) { | ||
67 | if (!strcmp(sdev->prom_name, PMC_OBPNAME)) { | ||
68 | goto sbus_done; | ||
69 | } | ||
70 | } | ||
71 | } | ||
72 | |||
73 | sbus_done: | ||
74 | if (!sdev) { | ||
75 | return -ENODEV; | ||
76 | } | ||
77 | |||
78 | pmc_regsize = sdev->reg_addrs[0].reg_size; | ||
79 | regs = sbus_ioremap(&sdev->resource[0], 0, | ||
80 | pmc_regsize, PMC_OBPNAME); | ||
81 | if (!regs) { | 59 | if (!regs) { |
82 | printk(KERN_ERR "%s: unable to map registers\n", PMC_DEVNAME); | 60 | printk(KERN_ERR "%s: unable to map registers\n", PMC_DEVNAME); |
83 | return -ENODEV; | 61 | return -ENODEV; |
@@ -92,8 +70,27 @@ sbus_done: | |||
92 | return 0; | 70 | return 0; |
93 | } | 71 | } |
94 | 72 | ||
73 | static struct of_device_id __initdata pmc_match[] = { | ||
74 | { | ||
75 | .name = PMC_OBPNAME, | ||
76 | }, | ||
77 | {}, | ||
78 | }; | ||
79 | MODULE_DEVICE_TABLE(of, pmc_match); | ||
80 | |||
81 | static struct of_platform_driver pmc_driver = { | ||
82 | .name = "pmc", | ||
83 | .match_table = pmc_match, | ||
84 | .probe = pmc_probe, | ||
85 | }; | ||
86 | |||
87 | static int __init pmc_init(void) | ||
88 | { | ||
89 | return of_register_driver(&pmc_driver, &of_bus_type); | ||
90 | } | ||
91 | |||
95 | /* This driver is not critical to the boot process | 92 | /* This driver is not critical to the boot process |
96 | * and is easiest to ioremap when SBus is already | 93 | * and is easiest to ioremap when SBus is already |
97 | * initialized, so we install ourselves thusly: | 94 | * initialized, so we install ourselves thusly: |
98 | */ | 95 | */ |
99 | __initcall(pmc_probe); | 96 | __initcall(pmc_init); |
diff --git a/arch/sparc/kernel/process.c b/arch/sparc/kernel/process.c index 4bb430940a61..e8c43ffe317e 100644 --- a/arch/sparc/kernel/process.c +++ b/arch/sparc/kernel/process.c | |||
@@ -75,7 +75,7 @@ void cpu_idle(void) | |||
75 | { | 75 | { |
76 | /* endless idle loop with no priority at all */ | 76 | /* endless idle loop with no priority at all */ |
77 | for (;;) { | 77 | for (;;) { |
78 | if (ARCH_SUN4C_SUN4) { | 78 | if (ARCH_SUN4C) { |
79 | static int count = HZ; | 79 | static int count = HZ; |
80 | static unsigned long last_jiffies; | 80 | static unsigned long last_jiffies; |
81 | static unsigned long last_faults; | 81 | static unsigned long last_faults; |
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index cd4fb79aa3a8..eee5efcfe50e 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c | |||
@@ -54,6 +54,9 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) | |||
54 | } | 54 | } |
55 | EXPORT_SYMBOL(of_getintprop_default); | 55 | EXPORT_SYMBOL(of_getintprop_default); |
56 | 56 | ||
57 | DEFINE_MUTEX(of_set_property_mutex); | ||
58 | EXPORT_SYMBOL(of_set_property_mutex); | ||
59 | |||
57 | int of_set_property(struct device_node *dp, const char *name, void *val, int len) | 60 | int of_set_property(struct device_node *dp, const char *name, void *val, int len) |
58 | { | 61 | { |
59 | struct property **prevp; | 62 | struct property **prevp; |
@@ -77,7 +80,10 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len | |||
77 | void *old_val = prop->value; | 80 | void *old_val = prop->value; |
78 | int ret; | 81 | int ret; |
79 | 82 | ||
83 | mutex_lock(&of_set_property_mutex); | ||
80 | ret = prom_setprop(dp->node, (char *) name, val, len); | 84 | ret = prom_setprop(dp->node, (char *) name, val, len); |
85 | mutex_unlock(&of_set_property_mutex); | ||
86 | |||
81 | err = -EINVAL; | 87 | err = -EINVAL; |
82 | if (ret >= 0) { | 88 | if (ret >= 0) { |
83 | prop->value = new_val; | 89 | prop->value = new_val; |
@@ -436,7 +442,6 @@ static void __init of_console_init(void) | |||
436 | 442 | ||
437 | switch (prom_vers) { | 443 | switch (prom_vers) { |
438 | case PROM_V0: | 444 | case PROM_V0: |
439 | case PROM_SUN4: | ||
440 | skip = 0; | 445 | skip = 0; |
441 | switch (*romvec->pv_stdout) { | 446 | switch (*romvec->pv_stdout) { |
442 | case PROMDEV_SCREEN: | 447 | case PROMDEV_SCREEN: |
diff --git a/arch/sparc/kernel/setup.c b/arch/sparc/kernel/setup.c index 9e451b21202e..24fe3078bd4b 100644 --- a/arch/sparc/kernel/setup.c +++ b/arch/sparc/kernel/setup.c | |||
@@ -213,23 +213,25 @@ void __init setup_arch(char **cmdline_p) | |||
213 | /* Initialize PROM console and command line. */ | 213 | /* Initialize PROM console and command line. */ |
214 | *cmdline_p = prom_getbootargs(); | 214 | *cmdline_p = prom_getbootargs(); |
215 | strcpy(boot_command_line, *cmdline_p); | 215 | strcpy(boot_command_line, *cmdline_p); |
216 | parse_early_param(); | ||
216 | 217 | ||
217 | /* Set sparc_cpu_model */ | 218 | /* Set sparc_cpu_model */ |
218 | sparc_cpu_model = sun_unknown; | 219 | sparc_cpu_model = sun_unknown; |
219 | if(!strcmp(&cputypval,"sun4 ")) { sparc_cpu_model=sun4; } | 220 | if (!strcmp(&cputypval,"sun4 ")) |
220 | if(!strcmp(&cputypval,"sun4c")) { sparc_cpu_model=sun4c; } | 221 | sparc_cpu_model = sun4; |
221 | if(!strcmp(&cputypval,"sun4m")) { sparc_cpu_model=sun4m; } | 222 | if (!strcmp(&cputypval,"sun4c")) |
222 | if(!strcmp(&cputypval,"sun4s")) { sparc_cpu_model=sun4m; } /* CP-1200 with PROM 2.30 -E */ | 223 | sparc_cpu_model = sun4c; |
223 | if(!strcmp(&cputypval,"sun4d")) { sparc_cpu_model=sun4d; } | 224 | if (!strcmp(&cputypval,"sun4m")) |
224 | if(!strcmp(&cputypval,"sun4e")) { sparc_cpu_model=sun4e; } | 225 | sparc_cpu_model = sun4m; |
225 | if(!strcmp(&cputypval,"sun4u")) { sparc_cpu_model=sun4u; } | 226 | if (!strcmp(&cputypval,"sun4s")) |
226 | 227 | sparc_cpu_model = sun4m; /* CP-1200 with PROM 2.30 -E */ | |
227 | #ifdef CONFIG_SUN4 | 228 | if (!strcmp(&cputypval,"sun4d")) |
228 | if (sparc_cpu_model != sun4) { | 229 | sparc_cpu_model = sun4d; |
229 | prom_printf("This kernel is for Sun4 architecture only.\n"); | 230 | if (!strcmp(&cputypval,"sun4e")) |
230 | prom_halt(); | 231 | sparc_cpu_model = sun4e; |
231 | } | 232 | if (!strcmp(&cputypval,"sun4u")) |
232 | #endif | 233 | sparc_cpu_model = sun4u; |
234 | |||
233 | printk("ARCH: "); | 235 | printk("ARCH: "); |
234 | switch(sparc_cpu_model) { | 236 | switch(sparc_cpu_model) { |
235 | case sun4: | 237 | case sun4: |
@@ -263,7 +265,7 @@ void __init setup_arch(char **cmdline_p) | |||
263 | boot_flags_init(*cmdline_p); | 265 | boot_flags_init(*cmdline_p); |
264 | 266 | ||
265 | idprom_init(); | 267 | idprom_init(); |
266 | if (ARCH_SUN4C_SUN4) | 268 | if (ARCH_SUN4C) |
267 | sun4c_probe_vac(); | 269 | sun4c_probe_vac(); |
268 | load_mmu(); | 270 | load_mmu(); |
269 | 271 | ||
diff --git a/arch/sparc/kernel/sparc_ksyms.c b/arch/sparc/kernel/sparc_ksyms.c index b23cea5ca5d1..b0dfff848653 100644 --- a/arch/sparc/kernel/sparc_ksyms.c +++ b/arch/sparc/kernel/sparc_ksyms.c | |||
@@ -38,17 +38,12 @@ | |||
38 | #include <asm/idprom.h> | 38 | #include <asm/idprom.h> |
39 | #include <asm/head.h> | 39 | #include <asm/head.h> |
40 | #include <asm/smp.h> | 40 | #include <asm/smp.h> |
41 | #include <asm/mostek.h> | ||
42 | #include <asm/ptrace.h> | 41 | #include <asm/ptrace.h> |
43 | #include <asm/uaccess.h> | 42 | #include <asm/uaccess.h> |
44 | #include <asm/checksum.h> | 43 | #include <asm/checksum.h> |
45 | #ifdef CONFIG_SBUS | 44 | #ifdef CONFIG_SBUS |
46 | #include <asm/sbus.h> | ||
47 | #include <asm/dma.h> | 45 | #include <asm/dma.h> |
48 | #endif | 46 | #endif |
49 | #ifdef CONFIG_PCI | ||
50 | #include <asm/ebus.h> | ||
51 | #endif | ||
52 | #include <asm/io-unit.h> | 47 | #include <asm/io-unit.h> |
53 | #include <asm/bug.h> | 48 | #include <asm/bug.h> |
54 | 49 | ||
@@ -127,16 +122,11 @@ EXPORT_SYMBOL(phys_cpu_present_map); | |||
127 | EXPORT_SYMBOL(__udelay); | 122 | EXPORT_SYMBOL(__udelay); |
128 | EXPORT_SYMBOL(__ndelay); | 123 | EXPORT_SYMBOL(__ndelay); |
129 | EXPORT_SYMBOL(rtc_lock); | 124 | EXPORT_SYMBOL(rtc_lock); |
130 | EXPORT_SYMBOL(mostek_lock); | ||
131 | EXPORT_SYMBOL(mstk48t02_regs); | ||
132 | #ifdef CONFIG_SUN_AUXIO | 125 | #ifdef CONFIG_SUN_AUXIO |
133 | EXPORT_SYMBOL(set_auxio); | 126 | EXPORT_SYMBOL(set_auxio); |
134 | EXPORT_SYMBOL(get_auxio); | 127 | EXPORT_SYMBOL(get_auxio); |
135 | #endif | 128 | #endif |
136 | EXPORT_SYMBOL(io_remap_pfn_range); | 129 | EXPORT_SYMBOL(io_remap_pfn_range); |
137 | /* P3: iounit_xxx may be needed, sun4d users */ | ||
138 | /* EXPORT_SYMBOL(iounit_map_dma_init); */ | ||
139 | /* EXPORT_SYMBOL(iounit_map_dma_page); */ | ||
140 | 130 | ||
141 | #ifndef CONFIG_SMP | 131 | #ifndef CONFIG_SMP |
142 | EXPORT_SYMBOL(BTFIXUP_CALL(___xchg32)); | 132 | EXPORT_SYMBOL(BTFIXUP_CALL(___xchg32)); |
@@ -153,24 +143,9 @@ EXPORT_SYMBOL(BTFIXUP_CALL(mmu_release_scsi_one)); | |||
153 | EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached)); | 143 | EXPORT_SYMBOL(BTFIXUP_CALL(pgprot_noncached)); |
154 | 144 | ||
155 | #ifdef CONFIG_SBUS | 145 | #ifdef CONFIG_SBUS |
156 | EXPORT_SYMBOL(sbus_root); | ||
157 | EXPORT_SYMBOL(dma_chain); | ||
158 | EXPORT_SYMBOL(sbus_set_sbus64); | 146 | EXPORT_SYMBOL(sbus_set_sbus64); |
159 | EXPORT_SYMBOL(sbus_alloc_consistent); | ||
160 | EXPORT_SYMBOL(sbus_free_consistent); | ||
161 | EXPORT_SYMBOL(sbus_map_single); | ||
162 | EXPORT_SYMBOL(sbus_unmap_single); | ||
163 | EXPORT_SYMBOL(sbus_map_sg); | ||
164 | EXPORT_SYMBOL(sbus_unmap_sg); | ||
165 | EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); | ||
166 | EXPORT_SYMBOL(sbus_dma_sync_single_for_device); | ||
167 | EXPORT_SYMBOL(sbus_dma_sync_sg_for_cpu); | ||
168 | EXPORT_SYMBOL(sbus_dma_sync_sg_for_device); | ||
169 | EXPORT_SYMBOL(sbus_iounmap); | ||
170 | EXPORT_SYMBOL(sbus_ioremap); | ||
171 | #endif | 147 | #endif |
172 | #ifdef CONFIG_PCI | 148 | #ifdef CONFIG_PCI |
173 | EXPORT_SYMBOL(ebus_chain); | ||
174 | EXPORT_SYMBOL(insb); | 149 | EXPORT_SYMBOL(insb); |
175 | EXPORT_SYMBOL(outsb); | 150 | EXPORT_SYMBOL(outsb); |
176 | EXPORT_SYMBOL(insw); | 151 | EXPORT_SYMBOL(insw); |
diff --git a/arch/sparc/kernel/sun4c_irq.c b/arch/sparc/kernel/sun4c_irq.c index 340fc395fe2d..5dc8a5769489 100644 --- a/arch/sparc/kernel/sun4c_irq.c +++ b/arch/sparc/kernel/sun4c_irq.c | |||
@@ -18,6 +18,8 @@ | |||
18 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
19 | #include <linux/slab.h> | 19 | #include <linux/slab.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/of.h> | ||
22 | #include <linux/of_device.h> | ||
21 | #include "irq.h" | 23 | #include "irq.h" |
22 | 24 | ||
23 | #include <asm/ptrace.h> | 25 | #include <asm/ptrace.h> |
@@ -31,15 +33,8 @@ | |||
31 | #include <asm/traps.h> | 33 | #include <asm/traps.h> |
32 | #include <asm/irq.h> | 34 | #include <asm/irq.h> |
33 | #include <asm/io.h> | 35 | #include <asm/io.h> |
34 | #include <asm/sun4paddr.h> | ||
35 | #include <asm/idprom.h> | 36 | #include <asm/idprom.h> |
36 | #include <asm/machines.h> | 37 | #include <asm/machines.h> |
37 | #include <asm/sbus.h> | ||
38 | |||
39 | #if 0 | ||
40 | static struct resource sun4c_timer_eb = { "sun4c_timer" }; | ||
41 | static struct resource sun4c_intr_eb = { "sun4c_intr" }; | ||
42 | #endif | ||
43 | 38 | ||
44 | /* | 39 | /* |
45 | * Bit field defines for the interrupt registers on various | 40 | * Bit field defines for the interrupt registers on various |
@@ -64,19 +59,7 @@ static struct resource sun4c_intr_eb = { "sun4c_intr" }; | |||
64 | * | 59 | * |
65 | * so don't go making it static, like I tried. sigh. | 60 | * so don't go making it static, like I tried. sigh. |
66 | */ | 61 | */ |
67 | unsigned char *interrupt_enable = NULL; | 62 | unsigned char __iomem *interrupt_enable = NULL; |
68 | |||
69 | static int sun4c_pil_map[] = { 0, 1, 2, 3, 5, 7, 8, 9 }; | ||
70 | |||
71 | static unsigned int sun4c_sbint_to_irq(struct sbus_dev *sdev, | ||
72 | unsigned int sbint) | ||
73 | { | ||
74 | if (sbint >= sizeof(sun4c_pil_map)) { | ||
75 | printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint); | ||
76 | BUG(); | ||
77 | } | ||
78 | return sun4c_pil_map[sbint]; | ||
79 | } | ||
80 | 63 | ||
81 | static void sun4c_disable_irq(unsigned int irq_nr) | 64 | static void sun4c_disable_irq(unsigned int irq_nr) |
82 | { | 65 | { |
@@ -85,7 +68,7 @@ static void sun4c_disable_irq(unsigned int irq_nr) | |||
85 | 68 | ||
86 | local_irq_save(flags); | 69 | local_irq_save(flags); |
87 | irq_nr &= (NR_IRQS - 1); | 70 | irq_nr &= (NR_IRQS - 1); |
88 | current_mask = *interrupt_enable; | 71 | current_mask = sbus_readb(interrupt_enable); |
89 | switch(irq_nr) { | 72 | switch(irq_nr) { |
90 | case 1: | 73 | case 1: |
91 | new_mask = ((current_mask) & (~(SUN4C_INT_E1))); | 74 | new_mask = ((current_mask) & (~(SUN4C_INT_E1))); |
@@ -103,7 +86,7 @@ static void sun4c_disable_irq(unsigned int irq_nr) | |||
103 | local_irq_restore(flags); | 86 | local_irq_restore(flags); |
104 | return; | 87 | return; |
105 | } | 88 | } |
106 | *interrupt_enable = new_mask; | 89 | sbus_writeb(new_mask, interrupt_enable); |
107 | local_irq_restore(flags); | 90 | local_irq_restore(flags); |
108 | } | 91 | } |
109 | 92 | ||
@@ -114,7 +97,7 @@ static void sun4c_enable_irq(unsigned int irq_nr) | |||
114 | 97 | ||
115 | local_irq_save(flags); | 98 | local_irq_save(flags); |
116 | irq_nr &= (NR_IRQS - 1); | 99 | irq_nr &= (NR_IRQS - 1); |
117 | current_mask = *interrupt_enable; | 100 | current_mask = sbus_readb(interrupt_enable); |
118 | switch(irq_nr) { | 101 | switch(irq_nr) { |
119 | case 1: | 102 | case 1: |
120 | new_mask = ((current_mask) | SUN4C_INT_E1); | 103 | new_mask = ((current_mask) | SUN4C_INT_E1); |
@@ -132,37 +115,22 @@ static void sun4c_enable_irq(unsigned int irq_nr) | |||
132 | local_irq_restore(flags); | 115 | local_irq_restore(flags); |
133 | return; | 116 | return; |
134 | } | 117 | } |
135 | *interrupt_enable = new_mask; | 118 | sbus_writeb(new_mask, interrupt_enable); |
136 | local_irq_restore(flags); | 119 | local_irq_restore(flags); |
137 | } | 120 | } |
138 | 121 | ||
139 | #define TIMER_IRQ 10 /* Also at level 14, but we ignore that one. */ | 122 | struct sun4c_timer_info { |
140 | #define PROFILE_IRQ 14 /* Level14 ticker.. used by OBP for polling */ | 123 | u32 l10_count; |
141 | 124 | u32 l10_limit; | |
142 | volatile struct sun4c_timer_info *sun4c_timers; | 125 | u32 l14_count; |
126 | u32 l14_limit; | ||
127 | }; | ||
143 | 128 | ||
144 | #ifdef CONFIG_SUN4 | 129 | static struct sun4c_timer_info __iomem *sun4c_timers; |
145 | /* This is an ugly hack to work around the | ||
146 | current timer code, and make it work with | ||
147 | the sun4/260 intersil | ||
148 | */ | ||
149 | volatile struct sun4c_timer_info sun4_timer; | ||
150 | #endif | ||
151 | 130 | ||
152 | static void sun4c_clear_clock_irq(void) | 131 | static void sun4c_clear_clock_irq(void) |
153 | { | 132 | { |
154 | volatile unsigned int clear_intr; | 133 | sbus_readl(&sun4c_timers->l10_limit); |
155 | #ifdef CONFIG_SUN4 | ||
156 | if (idprom->id_machtype == (SM_SUN4 | SM_4_260)) | ||
157 | clear_intr = sun4_timer.timer_limit10; | ||
158 | else | ||
159 | #endif | ||
160 | clear_intr = sun4c_timers->timer_limit10; | ||
161 | } | ||
162 | |||
163 | static void sun4c_clear_profile_irq(int cpu) | ||
164 | { | ||
165 | /* Errm.. not sure how to do this.. */ | ||
166 | } | 134 | } |
167 | 135 | ||
168 | static void sun4c_load_profile_irq(int cpu, unsigned int limit) | 136 | static void sun4c_load_profile_irq(int cpu, unsigned int limit) |
@@ -172,41 +140,48 @@ static void sun4c_load_profile_irq(int cpu, unsigned int limit) | |||
172 | 140 | ||
173 | static void __init sun4c_init_timers(irq_handler_t counter_fn) | 141 | static void __init sun4c_init_timers(irq_handler_t counter_fn) |
174 | { | 142 | { |
175 | int irq; | 143 | const struct linux_prom_irqs *irq; |
144 | struct device_node *dp; | ||
145 | const u32 *addr; | ||
146 | int err; | ||
147 | |||
148 | dp = of_find_node_by_name(NULL, "counter-timer"); | ||
149 | if (!dp) { | ||
150 | prom_printf("sun4c_init_timers: Unable to find counter-timer\n"); | ||
151 | prom_halt(); | ||
152 | } | ||
176 | 153 | ||
177 | /* Map the Timer chip, this is implemented in hardware inside | 154 | addr = of_get_property(dp, "address", NULL); |
178 | * the cache chip on the sun4c. | 155 | if (!addr) { |
179 | */ | 156 | prom_printf("sun4c_init_timers: No address property\n"); |
180 | #ifdef CONFIG_SUN4 | 157 | prom_halt(); |
181 | if (idprom->id_machtype == (SM_SUN4 | SM_4_260)) | 158 | } |
182 | sun4c_timers = &sun4_timer; | 159 | |
183 | else | 160 | sun4c_timers = (void __iomem *) (unsigned long) addr[0]; |
184 | #endif | 161 | |
185 | sun4c_timers = ioremap(SUN_TIMER_PHYSADDR, | 162 | irq = of_get_property(dp, "intr", NULL); |
186 | sizeof(struct sun4c_timer_info)); | 163 | if (!irq) { |
164 | prom_printf("sun4c_init_timers: No intr property\n"); | ||
165 | prom_halt(); | ||
166 | } | ||
187 | 167 | ||
188 | /* Have the level 10 timer tick at 100HZ. We don't touch the | 168 | /* Have the level 10 timer tick at 100HZ. We don't touch the |
189 | * level 14 timer limit since we are letting the prom handle | 169 | * level 14 timer limit since we are letting the prom handle |
190 | * them until we have a real console driver so L1-A works. | 170 | * them until we have a real console driver so L1-A works. |
191 | */ | 171 | */ |
192 | sun4c_timers->timer_limit10 = (((1000000/HZ) + 1) << 10); | 172 | sbus_writel((((1000000/HZ) + 1) << 10), &sun4c_timers->l10_limit); |
193 | master_l10_counter = &sun4c_timers->cur_count10; | ||
194 | master_l10_limit = &sun4c_timers->timer_limit10; | ||
195 | 173 | ||
196 | irq = request_irq(TIMER_IRQ, | 174 | master_l10_counter = &sun4c_timers->l10_count; |
197 | counter_fn, | 175 | |
176 | err = request_irq(irq[0].pri, counter_fn, | ||
198 | (IRQF_DISABLED | SA_STATIC_ALLOC), | 177 | (IRQF_DISABLED | SA_STATIC_ALLOC), |
199 | "timer", NULL); | 178 | "timer", NULL); |
200 | if (irq) { | 179 | if (err) { |
201 | prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); | 180 | prom_printf("sun4c_init_timers: request_irq() fails with %d\n", err); |
202 | prom_halt(); | 181 | prom_halt(); |
203 | } | 182 | } |
204 | 183 | ||
205 | #if 0 | 184 | sun4c_disable_irq(irq[1].pri); |
206 | /* This does not work on 4/330 */ | ||
207 | sun4c_enable_irq(10); | ||
208 | #endif | ||
209 | claim_ticker14(NULL, PROFILE_IRQ, 0); | ||
210 | } | 185 | } |
211 | 186 | ||
212 | #ifdef CONFIG_SMP | 187 | #ifdef CONFIG_SMP |
@@ -215,41 +190,28 @@ static void sun4c_nop(void) {} | |||
215 | 190 | ||
216 | void __init sun4c_init_IRQ(void) | 191 | void __init sun4c_init_IRQ(void) |
217 | { | 192 | { |
218 | struct linux_prom_registers int_regs[2]; | 193 | struct device_node *dp; |
219 | int ie_node; | 194 | const u32 *addr; |
220 | 195 | ||
221 | if (ARCH_SUN4) { | 196 | dp = of_find_node_by_name(NULL, "interrupt-enable"); |
222 | interrupt_enable = (char *) | 197 | if (!dp) { |
223 | ioremap(sun4_ie_physaddr, PAGE_SIZE); | 198 | prom_printf("sun4c_init_IRQ: Unable to find interrupt-enable\n"); |
224 | } else { | 199 | prom_halt(); |
225 | struct resource phyres; | 200 | } |
226 | |||
227 | ie_node = prom_searchsiblings (prom_getchild(prom_root_node), | ||
228 | "interrupt-enable"); | ||
229 | if(ie_node == 0) | ||
230 | panic("Cannot find /interrupt-enable node"); | ||
231 | 201 | ||
232 | /* Depending on the "address" property is bad news... */ | 202 | addr = of_get_property(dp, "address", NULL); |
233 | interrupt_enable = NULL; | 203 | if (!addr) { |
234 | if (prom_getproperty(ie_node, "reg", (char *) int_regs, | 204 | prom_printf("sun4c_init_IRQ: No address property\n"); |
235 | sizeof(int_regs)) != -1) { | 205 | prom_halt(); |
236 | memset(&phyres, 0, sizeof(struct resource)); | ||
237 | phyres.flags = int_regs[0].which_io; | ||
238 | phyres.start = int_regs[0].phys_addr; | ||
239 | interrupt_enable = (char *) sbus_ioremap(&phyres, 0, | ||
240 | int_regs[0].reg_size, "sun4c_intr"); | ||
241 | } | ||
242 | } | 206 | } |
243 | if (!interrupt_enable) | ||
244 | panic("Cannot map interrupt_enable"); | ||
245 | 207 | ||
246 | BTFIXUPSET_CALL(sbint_to_irq, sun4c_sbint_to_irq, BTFIXUPCALL_NORM); | 208 | interrupt_enable = (void __iomem *) (unsigned long) addr[0]; |
209 | |||
247 | BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); | 210 | BTFIXUPSET_CALL(enable_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); |
248 | BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); | 211 | BTFIXUPSET_CALL(disable_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); |
249 | BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); | 212 | BTFIXUPSET_CALL(enable_pil_irq, sun4c_enable_irq, BTFIXUPCALL_NORM); |
250 | BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); | 213 | BTFIXUPSET_CALL(disable_pil_irq, sun4c_disable_irq, BTFIXUPCALL_NORM); |
251 | BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); | 214 | BTFIXUPSET_CALL(clear_clock_irq, sun4c_clear_clock_irq, BTFIXUPCALL_NORM); |
252 | BTFIXUPSET_CALL(clear_profile_irq, sun4c_clear_profile_irq, BTFIXUPCALL_NOP); | ||
253 | BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); | 215 | BTFIXUPSET_CALL(load_profile_irq, sun4c_load_profile_irq, BTFIXUPCALL_NOP); |
254 | sparc_init_timers = sun4c_init_timers; | 216 | sparc_init_timers = sun4c_init_timers; |
255 | #ifdef CONFIG_SMP | 217 | #ifdef CONFIG_SMP |
@@ -257,6 +219,6 @@ void __init sun4c_init_IRQ(void) | |||
257 | BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); | 219 | BTFIXUPSET_CALL(clear_cpu_int, sun4c_nop, BTFIXUPCALL_NOP); |
258 | BTFIXUPSET_CALL(set_irq_udt, sun4c_nop, BTFIXUPCALL_NOP); | 220 | BTFIXUPSET_CALL(set_irq_udt, sun4c_nop, BTFIXUPCALL_NOP); |
259 | #endif | 221 | #endif |
260 | *interrupt_enable = (SUN4C_INT_ENABLE); | 222 | sbus_writeb(SUN4C_INT_ENABLE, interrupt_enable); |
261 | /* Cannot enable interrupts until OBP ticker is disabled. */ | 223 | /* Cannot enable interrupts until OBP ticker is disabled. */ |
262 | } | 224 | } |
diff --git a/arch/sparc/kernel/sun4d_irq.c b/arch/sparc/kernel/sun4d_irq.c index 1290b5998f83..d3cb76ce418b 100644 --- a/arch/sparc/kernel/sun4d_irq.c +++ b/arch/sparc/kernel/sun4d_irq.c | |||
@@ -19,6 +19,8 @@ | |||
19 | #include <linux/smp.h> | 19 | #include <linux/smp.h> |
20 | #include <linux/spinlock.h> | 20 | #include <linux/spinlock.h> |
21 | #include <linux/seq_file.h> | 21 | #include <linux/seq_file.h> |
22 | #include <linux/of.h> | ||
23 | #include <linux/of_device.h> | ||
22 | 24 | ||
23 | #include <asm/ptrace.h> | 25 | #include <asm/ptrace.h> |
24 | #include <asm/processor.h> | 26 | #include <asm/processor.h> |
@@ -34,7 +36,6 @@ | |||
34 | #include <asm/io.h> | 36 | #include <asm/io.h> |
35 | #include <asm/pgalloc.h> | 37 | #include <asm/pgalloc.h> |
36 | #include <asm/pgtable.h> | 38 | #include <asm/pgtable.h> |
37 | #include <asm/sbus.h> | ||
38 | #include <asm/sbi.h> | 39 | #include <asm/sbi.h> |
39 | #include <asm/cacheflush.h> | 40 | #include <asm/cacheflush.h> |
40 | #include <asm/irq_regs.h> | 41 | #include <asm/irq_regs.h> |
@@ -44,16 +45,22 @@ | |||
44 | /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */ | 45 | /* If you trust current SCSI layer to handle different SCSI IRQs, enable this. I don't trust it... -jj */ |
45 | /* #define DISTRIBUTE_IRQS */ | 46 | /* #define DISTRIBUTE_IRQS */ |
46 | 47 | ||
47 | struct sun4d_timer_regs *sun4d_timers; | 48 | struct sun4d_timer_regs { |
49 | u32 l10_timer_limit; | ||
50 | u32 l10_cur_countx; | ||
51 | u32 l10_limit_noclear; | ||
52 | u32 ctrl; | ||
53 | u32 l10_cur_count; | ||
54 | }; | ||
55 | |||
56 | static struct sun4d_timer_regs __iomem *sun4d_timers; | ||
57 | |||
48 | #define TIMER_IRQ 10 | 58 | #define TIMER_IRQ 10 |
49 | 59 | ||
50 | #define MAX_STATIC_ALLOC 4 | 60 | #define MAX_STATIC_ALLOC 4 |
51 | extern struct irqaction static_irqaction[MAX_STATIC_ALLOC]; | 61 | extern struct irqaction static_irqaction[MAX_STATIC_ALLOC]; |
52 | extern int static_irq_count; | 62 | extern int static_irq_count; |
53 | unsigned char cpu_leds[32]; | ||
54 | #ifdef CONFIG_SMP | ||
55 | static unsigned char sbus_tid[32]; | 63 | static unsigned char sbus_tid[32]; |
56 | #endif | ||
57 | 64 | ||
58 | static struct irqaction *irq_action[NR_IRQS]; | 65 | static struct irqaction *irq_action[NR_IRQS]; |
59 | extern spinlock_t irq_action_lock; | 66 | extern spinlock_t irq_action_lock; |
@@ -72,9 +79,9 @@ static int sbus_to_pil[] = { | |||
72 | }; | 79 | }; |
73 | 80 | ||
74 | static int nsbi; | 81 | static int nsbi; |
75 | #ifdef CONFIG_SMP | 82 | |
83 | /* Exported for sun4d_smp.c */ | ||
76 | DEFINE_SPINLOCK(sun4d_imsk_lock); | 84 | DEFINE_SPINLOCK(sun4d_imsk_lock); |
77 | #endif | ||
78 | 85 | ||
79 | int show_sun4d_interrupts(struct seq_file *p, void *v) | 86 | int show_sun4d_interrupts(struct seq_file *p, void *v) |
80 | { | 87 | { |
@@ -257,26 +264,6 @@ void sun4d_handler_irq(int irq, struct pt_regs * regs) | |||
257 | set_irq_regs(old_regs); | 264 | set_irq_regs(old_regs); |
258 | } | 265 | } |
259 | 266 | ||
260 | unsigned int sun4d_build_irq(struct sbus_dev *sdev, int irq) | ||
261 | { | ||
262 | int sbusl = pil_to_sbus[irq]; | ||
263 | |||
264 | if (sbusl) | ||
265 | return ((sdev->bus->board + 1) << 5) + (sbusl << 2) + sdev->slot; | ||
266 | else | ||
267 | return irq; | ||
268 | } | ||
269 | |||
270 | static unsigned int sun4d_sbint_to_irq(struct sbus_dev *sdev, | ||
271 | unsigned int sbint) | ||
272 | { | ||
273 | if (sbint >= sizeof(sbus_to_pil)) { | ||
274 | printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint); | ||
275 | BUG(); | ||
276 | } | ||
277 | return sun4d_build_irq(sdev, sbus_to_pil[sbint]); | ||
278 | } | ||
279 | |||
280 | int sun4d_request_irq(unsigned int irq, | 267 | int sun4d_request_irq(unsigned int irq, |
281 | irq_handler_t handler, | 268 | irq_handler_t handler, |
282 | unsigned long irqflags, const char * devname, void *dev_id) | 269 | unsigned long irqflags, const char * devname, void *dev_id) |
@@ -360,36 +347,28 @@ out: | |||
360 | 347 | ||
361 | static void sun4d_disable_irq(unsigned int irq) | 348 | static void sun4d_disable_irq(unsigned int irq) |
362 | { | 349 | { |
363 | #ifdef CONFIG_SMP | ||
364 | int tid = sbus_tid[(irq >> 5) - 1]; | 350 | int tid = sbus_tid[(irq >> 5) - 1]; |
365 | unsigned long flags; | 351 | unsigned long flags; |
366 | #endif | ||
367 | 352 | ||
368 | if (irq < NR_IRQS) return; | 353 | if (irq < NR_IRQS) |
369 | #ifdef CONFIG_SMP | 354 | return; |
355 | |||
370 | spin_lock_irqsave(&sun4d_imsk_lock, flags); | 356 | spin_lock_irqsave(&sun4d_imsk_lock, flags); |
371 | cc_set_imsk_other(tid, cc_get_imsk_other(tid) | (1 << sbus_to_pil[(irq >> 2) & 7])); | 357 | cc_set_imsk_other(tid, cc_get_imsk_other(tid) | (1 << sbus_to_pil[(irq >> 2) & 7])); |
372 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); | 358 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); |
373 | #else | ||
374 | cc_set_imsk(cc_get_imsk() | (1 << sbus_to_pil[(irq >> 2) & 7])); | ||
375 | #endif | ||
376 | } | 359 | } |
377 | 360 | ||
378 | static void sun4d_enable_irq(unsigned int irq) | 361 | static void sun4d_enable_irq(unsigned int irq) |
379 | { | 362 | { |
380 | #ifdef CONFIG_SMP | ||
381 | int tid = sbus_tid[(irq >> 5) - 1]; | 363 | int tid = sbus_tid[(irq >> 5) - 1]; |
382 | unsigned long flags; | 364 | unsigned long flags; |
383 | #endif | ||
384 | 365 | ||
385 | if (irq < NR_IRQS) return; | 366 | if (irq < NR_IRQS) |
386 | #ifdef CONFIG_SMP | 367 | return; |
368 | |||
387 | spin_lock_irqsave(&sun4d_imsk_lock, flags); | 369 | spin_lock_irqsave(&sun4d_imsk_lock, flags); |
388 | cc_set_imsk_other(tid, cc_get_imsk_other(tid) & ~(1 << sbus_to_pil[(irq >> 2) & 7])); | 370 | cc_set_imsk_other(tid, cc_get_imsk_other(tid) & ~(1 << sbus_to_pil[(irq >> 2) & 7])); |
389 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); | 371 | spin_unlock_irqrestore(&sun4d_imsk_lock, flags); |
390 | #else | ||
391 | cc_set_imsk(cc_get_imsk() & ~(1 << sbus_to_pil[(irq >> 2) & 7])); | ||
392 | #endif | ||
393 | } | 372 | } |
394 | 373 | ||
395 | #ifdef CONFIG_SMP | 374 | #ifdef CONFIG_SMP |
@@ -409,47 +388,55 @@ static void sun4d_set_udt(int cpu) | |||
409 | /* Setup IRQ distribution scheme. */ | 388 | /* Setup IRQ distribution scheme. */ |
410 | void __init sun4d_distribute_irqs(void) | 389 | void __init sun4d_distribute_irqs(void) |
411 | { | 390 | { |
391 | struct device_node *dp; | ||
392 | |||
412 | #ifdef DISTRIBUTE_IRQS | 393 | #ifdef DISTRIBUTE_IRQS |
413 | struct sbus_bus *sbus; | 394 | cpumask_t sbus_serving_map; |
414 | unsigned long sbus_serving_map; | ||
415 | 395 | ||
416 | sbus_serving_map = cpu_present_map; | 396 | sbus_serving_map = cpu_present_map; |
417 | for_each_sbus(sbus) { | 397 | for_each_node_by_name(dp, "sbi") { |
418 | if ((sbus->board * 2) == boot_cpu_id && (cpu_present_map & (1 << (sbus->board * 2 + 1)))) | 398 | int board = of_getintprop_default(dp, "board#", 0); |
419 | sbus_tid[sbus->board] = (sbus->board * 2 + 1); | 399 | |
420 | else if (cpu_present_map & (1 << (sbus->board * 2))) | 400 | if ((board * 2) == boot_cpu_id && cpu_isset(board * 2 + 1, cpu_present_map)) |
421 | sbus_tid[sbus->board] = (sbus->board * 2); | 401 | sbus_tid[board] = (board * 2 + 1); |
422 | else if (cpu_present_map & (1 << (sbus->board * 2 + 1))) | 402 | else if (cpu_isset(board * 2, cpu_present_map)) |
423 | sbus_tid[sbus->board] = (sbus->board * 2 + 1); | 403 | sbus_tid[board] = (board * 2); |
404 | else if (cpu_isset(board * 2 + 1, cpu_present_map)) | ||
405 | sbus_tid[board] = (board * 2 + 1); | ||
424 | else | 406 | else |
425 | sbus_tid[sbus->board] = 0xff; | 407 | sbus_tid[board] = 0xff; |
426 | if (sbus_tid[sbus->board] != 0xff) | 408 | if (sbus_tid[board] != 0xff) |
427 | sbus_serving_map &= ~(1 << sbus_tid[sbus->board]); | 409 | cpu_clear(sbus_tid[board], sbus_serving_map); |
428 | } | 410 | } |
429 | for_each_sbus(sbus) | 411 | for_each_node_by_name(dp, "sbi") { |
430 | if (sbus_tid[sbus->board] == 0xff) { | 412 | int board = of_getintprop_default(dp, "board#", 0); |
413 | if (sbus_tid[board] == 0xff) { | ||
431 | int i = 31; | 414 | int i = 31; |
432 | 415 | ||
433 | if (!sbus_serving_map) | 416 | if (cpus_empty(sbus_serving_map)) |
434 | sbus_serving_map = cpu_present_map; | 417 | sbus_serving_map = cpu_present_map; |
435 | while (!(sbus_serving_map & (1 << i))) | 418 | while (cpu_isset(i, sbus_serving_map)) |
436 | i--; | 419 | i--; |
437 | sbus_tid[sbus->board] = i; | 420 | sbus_tid[board] = i; |
438 | sbus_serving_map &= ~(1 << i); | 421 | cpu_clear(i, sbus_serving_map); |
439 | } | 422 | } |
440 | for_each_sbus(sbus) { | 423 | } |
441 | printk("sbus%d IRQs directed to CPU%d\n", sbus->board, sbus_tid[sbus->board]); | 424 | for_each_node_by_name(dp, "sbi") { |
442 | set_sbi_tid(sbus->devid, sbus_tid[sbus->board] << 3); | 425 | int devid = of_getintprop_default(dp, "device-id", 0); |
426 | int board = of_getintprop_default(dp, "board#", 0); | ||
427 | printk("sbus%d IRQs directed to CPU%d\n", board, sbus_tid[board]); | ||
428 | set_sbi_tid(devid, sbus_tid[board] << 3); | ||
443 | } | 429 | } |
444 | #else | 430 | #else |
445 | struct sbus_bus *sbus; | ||
446 | int cpuid = cpu_logical_map(1); | 431 | int cpuid = cpu_logical_map(1); |
447 | 432 | ||
448 | if (cpuid == -1) | 433 | if (cpuid == -1) |
449 | cpuid = cpu_logical_map(0); | 434 | cpuid = cpu_logical_map(0); |
450 | for_each_sbus(sbus) { | 435 | for_each_node_by_name(dp, "sbi") { |
451 | sbus_tid[sbus->board] = cpuid; | 436 | int devid = of_getintprop_default(dp, "device-id", 0); |
452 | set_sbi_tid(sbus->devid, cpuid << 3); | 437 | int board = of_getintprop_default(dp, "board#", 0); |
438 | sbus_tid[board] = cpuid; | ||
439 | set_sbi_tid(devid, cpuid << 3); | ||
453 | } | 440 | } |
454 | printk("All sbus IRQs directed to CPU%d\n", cpuid); | 441 | printk("All sbus IRQs directed to CPU%d\n", cpuid); |
455 | #endif | 442 | #endif |
@@ -458,13 +445,7 @@ void __init sun4d_distribute_irqs(void) | |||
458 | 445 | ||
459 | static void sun4d_clear_clock_irq(void) | 446 | static void sun4d_clear_clock_irq(void) |
460 | { | 447 | { |
461 | volatile unsigned int clear_intr; | 448 | sbus_readl(&sun4d_timers->l10_timer_limit); |
462 | clear_intr = sun4d_timers->l10_timer_limit; | ||
463 | } | ||
464 | |||
465 | static void sun4d_clear_profile_irq(int cpu) | ||
466 | { | ||
467 | bw_get_prof_limit(cpu); | ||
468 | } | 449 | } |
469 | 450 | ||
470 | static void sun4d_load_profile_irq(int cpu, unsigned int limit) | 451 | static void sun4d_load_profile_irq(int cpu, unsigned int limit) |
@@ -472,98 +453,121 @@ static void sun4d_load_profile_irq(int cpu, unsigned int limit) | |||
472 | bw_set_prof_limit(cpu, limit); | 453 | bw_set_prof_limit(cpu, limit); |
473 | } | 454 | } |
474 | 455 | ||
475 | static void __init sun4d_init_timers(irq_handler_t counter_fn) | 456 | static void __init sun4d_load_profile_irqs(void) |
476 | { | 457 | { |
477 | int irq; | 458 | int cpu = 0, mid; |
478 | int cpu; | ||
479 | struct resource r; | ||
480 | int mid; | ||
481 | 459 | ||
482 | /* Map the User Timer registers. */ | 460 | while (!cpu_find_by_instance(cpu, NULL, &mid)) { |
483 | memset(&r, 0, sizeof(r)); | 461 | sun4d_load_profile_irq(mid >> 3, 0); |
462 | cpu++; | ||
463 | } | ||
464 | } | ||
465 | |||
466 | static void __init sun4d_fixup_trap_table(void) | ||
467 | { | ||
484 | #ifdef CONFIG_SMP | 468 | #ifdef CONFIG_SMP |
485 | r.start = CSR_BASE(boot_cpu_id)+BW_TIMER_LIMIT; | 469 | unsigned long flags; |
486 | #else | 470 | extern unsigned long lvl14_save[4]; |
487 | r.start = CSR_BASE(0)+BW_TIMER_LIMIT; | 471 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; |
472 | extern unsigned int real_irq_entry[], smp4d_ticker[]; | ||
473 | extern unsigned int patchme_maybe_smp_msg[]; | ||
474 | |||
475 | /* Adjust so that we jump directly to smp4d_ticker */ | ||
476 | lvl14_save[2] += smp4d_ticker - real_irq_entry; | ||
477 | |||
478 | /* For SMP we use the level 14 ticker, however the bootup code | ||
479 | * has copied the firmware's level 14 vector into the boot cpu's | ||
480 | * trap table, we must fix this now or we get squashed. | ||
481 | */ | ||
482 | local_irq_save(flags); | ||
483 | patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ | ||
484 | trap_table->inst_one = lvl14_save[0]; | ||
485 | trap_table->inst_two = lvl14_save[1]; | ||
486 | trap_table->inst_three = lvl14_save[2]; | ||
487 | trap_table->inst_four = lvl14_save[3]; | ||
488 | local_flush_cache_all(); | ||
489 | local_irq_restore(flags); | ||
488 | #endif | 490 | #endif |
489 | r.flags = 0xf; | 491 | } |
490 | sun4d_timers = (struct sun4d_timer_regs *) sbus_ioremap(&r, 0, | ||
491 | PAGE_SIZE, "user timer"); | ||
492 | 492 | ||
493 | sun4d_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); | 493 | static void __init sun4d_init_timers(irq_handler_t counter_fn) |
494 | master_l10_counter = &sun4d_timers->l10_cur_count; | 494 | { |
495 | master_l10_limit = &sun4d_timers->l10_timer_limit; | 495 | struct device_node *dp; |
496 | struct resource res; | ||
497 | const u32 *reg; | ||
498 | int err; | ||
499 | |||
500 | dp = of_find_node_by_name(NULL, "cpu-unit"); | ||
501 | if (!dp) { | ||
502 | prom_printf("sun4d_init_timers: Unable to find cpu-unit\n"); | ||
503 | prom_halt(); | ||
504 | } | ||
496 | 505 | ||
497 | irq = request_irq(TIMER_IRQ, | 506 | /* Which cpu-unit we use is arbitrary, we can view the bootbus timer |
498 | counter_fn, | 507 | * registers via any cpu's mapping. The first 'reg' property is the |
499 | (IRQF_DISABLED | SA_STATIC_ALLOC), | 508 | * bootbus. |
500 | "timer", NULL); | 509 | */ |
501 | if (irq) { | 510 | reg = of_get_property(dp, "reg", NULL); |
502 | prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); | 511 | if (!reg) { |
512 | prom_printf("sun4d_init_timers: No reg property\n"); | ||
503 | prom_halt(); | 513 | prom_halt(); |
504 | } | 514 | } |
505 | |||
506 | /* Enable user timer free run for CPU 0 in BW */ | ||
507 | /* bw_set_ctrl(0, bw_get_ctrl(0) | BW_CTRL_USER_TIMER); */ | ||
508 | 515 | ||
509 | cpu = 0; | 516 | res.start = reg[1]; |
510 | while (!cpu_find_by_instance(cpu, NULL, &mid)) { | 517 | res.end = reg[2] - 1; |
511 | sun4d_load_profile_irq(mid >> 3, 0); | 518 | res.flags = reg[0] & 0xff; |
512 | cpu++; | 519 | sun4d_timers = of_ioremap(&res, BW_TIMER_LIMIT, |
520 | sizeof(struct sun4d_timer_regs), "user timer"); | ||
521 | if (!sun4d_timers) { | ||
522 | prom_printf("sun4d_init_timers: Can't map timer regs\n"); | ||
523 | prom_halt(); | ||
513 | } | 524 | } |
514 | 525 | ||
515 | #ifdef CONFIG_SMP | 526 | sbus_writel((((1000000/HZ) + 1) << 10), &sun4d_timers->l10_timer_limit); |
516 | { | 527 | |
517 | unsigned long flags; | 528 | master_l10_counter = &sun4d_timers->l10_cur_count; |
518 | extern unsigned long lvl14_save[4]; | 529 | |
519 | struct tt_entry *trap_table = &sparc_ttable[SP_TRAP_IRQ1 + (14 - 1)]; | 530 | err = request_irq(TIMER_IRQ, counter_fn, |
520 | extern unsigned int real_irq_entry[], smp4d_ticker[]; | 531 | (IRQF_DISABLED | SA_STATIC_ALLOC), |
521 | extern unsigned int patchme_maybe_smp_msg[]; | 532 | "timer", NULL); |
522 | 533 | if (err) { | |
523 | /* Adjust so that we jump directly to smp4d_ticker */ | 534 | prom_printf("sun4d_init_timers: request_irq() failed with %d\n", err); |
524 | lvl14_save[2] += smp4d_ticker - real_irq_entry; | 535 | prom_halt(); |
525 | |||
526 | /* For SMP we use the level 14 ticker, however the bootup code | ||
527 | * has copied the firmware's level 14 vector into the boot cpu's | ||
528 | * trap table, we must fix this now or we get squashed. | ||
529 | */ | ||
530 | local_irq_save(flags); | ||
531 | patchme_maybe_smp_msg[0] = 0x01000000; /* NOP out the branch */ | ||
532 | trap_table->inst_one = lvl14_save[0]; | ||
533 | trap_table->inst_two = lvl14_save[1]; | ||
534 | trap_table->inst_three = lvl14_save[2]; | ||
535 | trap_table->inst_four = lvl14_save[3]; | ||
536 | local_flush_cache_all(); | ||
537 | local_irq_restore(flags); | ||
538 | } | 536 | } |
539 | #endif | 537 | sun4d_load_profile_irqs(); |
538 | sun4d_fixup_trap_table(); | ||
540 | } | 539 | } |
541 | 540 | ||
542 | void __init sun4d_init_sbi_irq(void) | 541 | void __init sun4d_init_sbi_irq(void) |
543 | { | 542 | { |
544 | struct sbus_bus *sbus; | 543 | struct device_node *dp; |
545 | unsigned mask; | 544 | int target_cpu = 0; |
545 | |||
546 | #ifdef CONFIG_SMP | ||
547 | target_cpu = boot_cpu_id; | ||
548 | #endif | ||
546 | 549 | ||
547 | nsbi = 0; | 550 | nsbi = 0; |
548 | for_each_sbus(sbus) | 551 | for_each_node_by_name(dp, "sbi") |
549 | nsbi++; | 552 | nsbi++; |
550 | sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC); | 553 | sbus_actions = kzalloc (nsbi * 8 * 4 * sizeof(struct sbus_action), GFP_ATOMIC); |
551 | if (!sbus_actions) { | 554 | if (!sbus_actions) { |
552 | prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n"); | 555 | prom_printf("SUN4D: Cannot allocate sbus_actions, halting.\n"); |
553 | prom_halt(); | 556 | prom_halt(); |
554 | } | 557 | } |
555 | for_each_sbus(sbus) { | 558 | for_each_node_by_name(dp, "sbi") { |
556 | #ifdef CONFIG_SMP | 559 | int devid = of_getintprop_default(dp, "device-id", 0); |
557 | extern unsigned char boot_cpu_id; | 560 | int board = of_getintprop_default(dp, "board#", 0); |
558 | 561 | unsigned int mask; | |
559 | set_sbi_tid(sbus->devid, boot_cpu_id << 3); | 562 | |
560 | sbus_tid[sbus->board] = boot_cpu_id; | 563 | set_sbi_tid(devid, target_cpu << 3); |
561 | #endif | 564 | sbus_tid[board] = target_cpu; |
565 | |||
562 | /* Get rid of pending irqs from PROM */ | 566 | /* Get rid of pending irqs from PROM */ |
563 | mask = acquire_sbi(sbus->devid, 0xffffffff); | 567 | mask = acquire_sbi(devid, 0xffffffff); |
564 | if (mask) { | 568 | if (mask) { |
565 | printk ("Clearing pending IRQs %08x on SBI %d\n", mask, sbus->board); | 569 | printk ("Clearing pending IRQs %08x on SBI %d\n", mask, board); |
566 | release_sbi(sbus->devid, mask); | 570 | release_sbi(devid, mask); |
567 | } | 571 | } |
568 | } | 572 | } |
569 | } | 573 | } |
@@ -572,11 +576,9 @@ void __init sun4d_init_IRQ(void) | |||
572 | { | 576 | { |
573 | local_irq_disable(); | 577 | local_irq_disable(); |
574 | 578 | ||
575 | BTFIXUPSET_CALL(sbint_to_irq, sun4d_sbint_to_irq, BTFIXUPCALL_NORM); | ||
576 | BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM); | 579 | BTFIXUPSET_CALL(enable_irq, sun4d_enable_irq, BTFIXUPCALL_NORM); |
577 | BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM); | 580 | BTFIXUPSET_CALL(disable_irq, sun4d_disable_irq, BTFIXUPCALL_NORM); |
578 | BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); | 581 | BTFIXUPSET_CALL(clear_clock_irq, sun4d_clear_clock_irq, BTFIXUPCALL_NORM); |
579 | BTFIXUPSET_CALL(clear_profile_irq, sun4d_clear_profile_irq, BTFIXUPCALL_NORM); | ||
580 | BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); | 582 | BTFIXUPSET_CALL(load_profile_irq, sun4d_load_profile_irq, BTFIXUPCALL_NORM); |
581 | sparc_init_timers = sun4d_init_timers; | 583 | sparc_init_timers = sun4d_init_timers; |
582 | #ifdef CONFIG_SMP | 584 | #ifdef CONFIG_SMP |
diff --git a/arch/sparc/kernel/sun4d_smp.c b/arch/sparc/kernel/sun4d_smp.c index 446767e8f569..ce3d45db94e9 100644 --- a/arch/sparc/kernel/sun4d_smp.c +++ b/arch/sparc/kernel/sun4d_smp.c | |||
@@ -30,7 +30,6 @@ | |||
30 | #include <asm/pgalloc.h> | 30 | #include <asm/pgalloc.h> |
31 | #include <asm/pgtable.h> | 31 | #include <asm/pgtable.h> |
32 | #include <asm/oplib.h> | 32 | #include <asm/oplib.h> |
33 | #include <asm/sbus.h> | ||
34 | #include <asm/sbi.h> | 33 | #include <asm/sbi.h> |
35 | #include <asm/tlbflush.h> | 34 | #include <asm/tlbflush.h> |
36 | #include <asm/cacheflush.h> | 35 | #include <asm/cacheflush.h> |
@@ -72,6 +71,17 @@ static void smp_setup_percpu_timer(void); | |||
72 | extern void cpu_probe(void); | 71 | extern void cpu_probe(void); |
73 | extern void sun4d_distribute_irqs(void); | 72 | extern void sun4d_distribute_irqs(void); |
74 | 73 | ||
74 | static unsigned char cpu_leds[32]; | ||
75 | |||
76 | static inline void show_leds(int cpuid) | ||
77 | { | ||
78 | cpuid &= 0x1e; | ||
79 | __asm__ __volatile__ ("stba %0, [%1] %2" : : | ||
80 | "r" ((cpu_leds[cpuid] << 4) | cpu_leds[cpuid+1]), | ||
81 | "r" (ECSR_BASE(cpuid) | BB_LEDS), | ||
82 | "i" (ASI_M_CTL)); | ||
83 | } | ||
84 | |||
75 | void __init smp4d_callin(void) | 85 | void __init smp4d_callin(void) |
76 | { | 86 | { |
77 | int cpuid = hard_smp4d_processor_id(); | 87 | int cpuid = hard_smp4d_processor_id(); |
diff --git a/arch/sparc/kernel/sun4m_irq.c b/arch/sparc/kernel/sun4m_irq.c index 94e02de960ea..f10317179ee6 100644 --- a/arch/sparc/kernel/sun4m_irq.c +++ b/arch/sparc/kernel/sun4m_irq.c | |||
@@ -20,6 +20,8 @@ | |||
20 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/init.h> | 21 | #include <linux/init.h> |
22 | #include <linux/ioport.h> | 22 | #include <linux/ioport.h> |
23 | #include <linux/of.h> | ||
24 | #include <linux/of_device.h> | ||
23 | 25 | ||
24 | #include <asm/ptrace.h> | 26 | #include <asm/ptrace.h> |
25 | #include <asm/processor.h> | 27 | #include <asm/processor.h> |
@@ -35,59 +37,27 @@ | |||
35 | #include <asm/smp.h> | 37 | #include <asm/smp.h> |
36 | #include <asm/irq.h> | 38 | #include <asm/irq.h> |
37 | #include <asm/io.h> | 39 | #include <asm/io.h> |
38 | #include <asm/sbus.h> | ||
39 | #include <asm/cacheflush.h> | 40 | #include <asm/cacheflush.h> |
40 | 41 | ||
41 | #include "irq.h" | 42 | #include "irq.h" |
42 | 43 | ||
43 | /* On the sun4m, just like the timers, we have both per-cpu and master | 44 | struct sun4m_irq_percpu { |
44 | * interrupt registers. | 45 | u32 pending; |
45 | */ | 46 | u32 clear; |
46 | 47 | u32 set; | |
47 | /* These registers are used for sending/receiving irqs from/to | ||
48 | * different cpu's. | ||
49 | */ | ||
50 | struct sun4m_intreg_percpu { | ||
51 | unsigned int tbt; /* Interrupts still pending for this cpu. */ | ||
52 | |||
53 | /* These next two registers are WRITE-ONLY and are only | ||
54 | * "on bit" sensitive, "off bits" written have NO affect. | ||
55 | */ | ||
56 | unsigned int clear; /* Clear this cpus irqs here. */ | ||
57 | unsigned int set; /* Set this cpus irqs here. */ | ||
58 | unsigned char space[PAGE_SIZE - 12]; | ||
59 | }; | 48 | }; |
60 | 49 | ||
61 | /* | 50 | struct sun4m_irq_global { |
62 | * djhr | 51 | u32 pending; |
63 | * Actually the clear and set fields in this struct are misleading.. | 52 | u32 mask; |
64 | * according to the SLAVIO manual (and the same applies for the SEC) | 53 | u32 mask_clear; |
65 | * the clear field clears bits in the mask which will ENABLE that IRQ | 54 | u32 mask_set; |
66 | * the set field sets bits in the mask to DISABLE the IRQ. | 55 | u32 interrupt_target; |
67 | * | ||
68 | * Also the undirected_xx address in the SLAVIO is defined as | ||
69 | * RESERVED and write only.. | ||
70 | * | ||
71 | * DAVEM_NOTE: The SLAVIO only specifies behavior on uniprocessor | ||
72 | * sun4m machines, for MP the layout makes more sense. | ||
73 | */ | ||
74 | struct sun4m_intregs { | ||
75 | struct sun4m_intreg_percpu cpu_intregs[SUN4M_NCPUS]; | ||
76 | unsigned int tbt; /* IRQ's that are still pending. */ | ||
77 | unsigned int irqs; /* Master IRQ bits. */ | ||
78 | |||
79 | /* Again, like the above, two these registers are WRITE-ONLY. */ | ||
80 | unsigned int clear; /* Clear master IRQ's by setting bits here. */ | ||
81 | unsigned int set; /* Set master IRQ's by setting bits here. */ | ||
82 | |||
83 | /* This register is both READ and WRITE. */ | ||
84 | unsigned int undirected_target; /* Which cpu gets undirected irqs. */ | ||
85 | }; | 56 | }; |
86 | 57 | ||
87 | static unsigned long dummy; | 58 | /* Code in entry.S needs to get at these register mappings. */ |
88 | 59 | struct sun4m_irq_percpu __iomem *sun4m_irq_percpu[SUN4M_NCPUS]; | |
89 | struct sun4m_intregs *sun4m_interrupts; | 60 | struct sun4m_irq_global __iomem *sun4m_irq_global; |
90 | unsigned long *irq_rcvreg = &dummy; | ||
91 | 61 | ||
92 | /* Dave Redman (djhr@tadpole.co.uk) | 62 | /* Dave Redman (djhr@tadpole.co.uk) |
93 | * The sun4m interrupt registers. | 63 | * The sun4m interrupt registers. |
@@ -101,8 +71,9 @@ unsigned long *irq_rcvreg = &dummy; | |||
101 | 71 | ||
102 | #define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ | 72 | #define SUN4M_INT_MASKALL 0x80000000 /* mask all interrupts */ |
103 | #define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ | 73 | #define SUN4M_INT_MODULE_ERR 0x40000000 /* module error */ |
104 | #define SUN4M_INT_M2S_WRITE 0x20000000 /* write buffer error */ | 74 | #define SUN4M_INT_M2S_WRITE_ERR 0x20000000 /* write buffer error */ |
105 | #define SUN4M_INT_ECC 0x10000000 /* ecc memory error */ | 75 | #define SUN4M_INT_ECC_ERR 0x10000000 /* ecc memory error */ |
76 | #define SUN4M_INT_VME_ERR 0x08000000 /* vme async error */ | ||
106 | #define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ | 77 | #define SUN4M_INT_FLOPPY 0x00400000 /* floppy disk */ |
107 | #define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ | 78 | #define SUN4M_INT_MODULE 0x00200000 /* module interrupt */ |
108 | #define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ | 79 | #define SUN4M_INT_VIDEO 0x00100000 /* onboard video */ |
@@ -113,75 +84,126 @@ unsigned long *irq_rcvreg = &dummy; | |||
113 | #define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ | 84 | #define SUN4M_INT_SERIAL 0x00008000 /* serial ports */ |
114 | #define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ | 85 | #define SUN4M_INT_KBDMS 0x00004000 /* keyboard/mouse */ |
115 | #define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ | 86 | #define SUN4M_INT_SBUSBITS 0x00003F80 /* sbus int bits */ |
87 | #define SUN4M_INT_VMEBITS 0x0000007F /* vme int bits */ | ||
88 | |||
89 | #define SUN4M_INT_ERROR (SUN4M_INT_MODULE_ERR | \ | ||
90 | SUN4M_INT_M2S_WRITE_ERR | \ | ||
91 | SUN4M_INT_ECC_ERR | \ | ||
92 | SUN4M_INT_VME_ERR) | ||
116 | 93 | ||
117 | #define SUN4M_INT_SBUS(x) (1 << (x+7)) | 94 | #define SUN4M_INT_SBUS(x) (1 << (x+7)) |
118 | #define SUN4M_INT_VME(x) (1 << (x)) | 95 | #define SUN4M_INT_VME(x) (1 << (x)) |
119 | 96 | ||
120 | /* These tables only apply for interrupts greater than 15.. | 97 | /* Interrupt levels used by OBP */ |
121 | * | 98 | #define OBP_INT_LEVEL_SOFT 0x10 |
122 | * any intr value below 0x10 is considered to be a soft-int | 99 | #define OBP_INT_LEVEL_ONBOARD 0x20 |
123 | * this may be useful or it may not.. but that's how I've done it. | 100 | #define OBP_INT_LEVEL_SBUS 0x30 |
124 | * and it won't clash with what OBP is telling us about devices. | 101 | #define OBP_INT_LEVEL_VME 0x40 |
102 | |||
103 | /* Interrupt level assignment on sun4m: | ||
104 | * | ||
105 | * level source | ||
106 | * ------------------------------------------------------------ | ||
107 | * 1 softint-1 | ||
108 | * 2 softint-2, VME/SBUS level 1 | ||
109 | * 3 softint-3, VME/SBUS level 2 | ||
110 | * 4 softint-4, onboard SCSI | ||
111 | * 5 softint-5, VME/SBUS level 3 | ||
112 | * 6 softint-6, onboard ETHERNET | ||
113 | * 7 softint-7, VME/SBUS level 4 | ||
114 | * 8 softint-8, onboard VIDEO | ||
115 | * 9 softint-9, VME/SBUS level 5, Module Interrupt | ||
116 | * 10 softint-10, system counter/timer | ||
117 | * 11 softint-11, VME/SBUS level 6, Floppy | ||
118 | * 12 softint-12, Keyboard/Mouse, Serial | ||
119 | * 13 softint-13, VME/SBUS level 7, ISDN Audio | ||
120 | * 14 softint-14, per-processor counter/timer | ||
121 | * 15 softint-15, Asynchronous Errors (broadcast) | ||
125 | * | 122 | * |
126 | * take an encoded intr value and lookup if it's valid | 123 | * Each interrupt source is masked distinctly in the sun4m interrupt |
127 | * then get the mask bits that match from irq_mask | 124 | * registers. The PIL level alone is therefore ambiguous, since multiple |
125 | * interrupt sources map to a single PIL. | ||
128 | * | 126 | * |
129 | * P3: Translation from irq 0x0d to mask 0x2000 is for MrCoffee. | 127 | * This ambiguity is resolved in the 'intr' property for device nodes |
128 | * in the OF device tree. Each 'intr' property entry is composed of | ||
129 | * two 32-bit words. The first word is the IRQ priority value, which | ||
130 | * is what we're intersted in. The second word is the IRQ vector, which | ||
131 | * is unused. | ||
132 | * | ||
133 | * The low 4 bits of the IRQ priority indicate the PIL, and the upper | ||
134 | * 4 bits indicate onboard vs. SBUS leveled vs. VME leveled. 0x20 | ||
135 | * means onboard, 0x30 means SBUS leveled, and 0x40 means VME leveled. | ||
136 | * | ||
137 | * For example, an 'intr' IRQ priority value of 0x24 is onboard SCSI | ||
138 | * whereas a value of 0x33 is SBUS level 2. Here are some sample | ||
139 | * 'intr' property IRQ priority values from ss4, ss5, ss10, ss20, and | ||
140 | * Tadpole S3 GX systems. | ||
141 | * | ||
142 | * esp: 0x24 onboard ESP SCSI | ||
143 | * le: 0x26 onboard Lance ETHERNET | ||
144 | * p9100: 0x32 SBUS level 1 P9100 video | ||
145 | * bpp: 0x33 SBUS level 2 BPP parallel port device | ||
146 | * DBRI: 0x39 SBUS level 5 DBRI ISDN audio | ||
147 | * SUNW,leo: 0x39 SBUS level 5 LEO video | ||
148 | * pcmcia: 0x3b SBUS level 6 PCMCIA controller | ||
149 | * uctrl: 0x3b SBUS level 6 UCTRL device | ||
150 | * modem: 0x3d SBUS level 7 MODEM | ||
151 | * zs: 0x2c onboard keyboard/mouse/serial | ||
152 | * floppy: 0x2b onboard Floppy | ||
153 | * power: 0x22 onboard power device (XXX unknown mask bit XXX) | ||
130 | */ | 154 | */ |
131 | static unsigned char irq_xlate[32] = { | ||
132 | /* 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, a, b, c, d, e, f */ | ||
133 | 0, 0, 0, 0, 1, 0, 2, 0, 3, 0, 4, 5, 6, 14, 0, 7, | ||
134 | 0, 0, 8, 9, 0, 10, 0, 11, 0, 12, 0, 13, 0, 14, 0, 0 | ||
135 | }; | ||
136 | 155 | ||
137 | static unsigned long irq_mask[] = { | 156 | static unsigned long irq_mask[0x50] = { |
138 | 0, /* illegal index */ | 157 | /* SMP */ |
139 | SUN4M_INT_SCSI, /* 1 irq 4 */ | 158 | 0, SUN4M_SOFT_INT(1), |
140 | SUN4M_INT_ETHERNET, /* 2 irq 6 */ | 159 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), |
141 | SUN4M_INT_VIDEO, /* 3 irq 8 */ | 160 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), |
142 | SUN4M_INT_REALTIME, /* 4 irq 10 */ | 161 | SUN4M_SOFT_INT(6), SUN4M_SOFT_INT(7), |
143 | SUN4M_INT_FLOPPY, /* 5 irq 11 */ | 162 | SUN4M_SOFT_INT(8), SUN4M_SOFT_INT(9), |
144 | (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), /* 6 irq 12 */ | 163 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), |
145 | SUN4M_INT_MODULE_ERR, /* 7 irq 15 */ | 164 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), |
146 | SUN4M_INT_SBUS(0), /* 8 irq 2 */ | 165 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), |
147 | SUN4M_INT_SBUS(1), /* 9 irq 3 */ | 166 | /* soft */ |
148 | SUN4M_INT_SBUS(2), /* 10 irq 5 */ | 167 | 0, SUN4M_SOFT_INT(1), |
149 | SUN4M_INT_SBUS(3), /* 11 irq 7 */ | 168 | SUN4M_SOFT_INT(2), SUN4M_SOFT_INT(3), |
150 | SUN4M_INT_SBUS(4), /* 12 irq 9 */ | 169 | SUN4M_SOFT_INT(4), SUN4M_SOFT_INT(5), |
151 | SUN4M_INT_SBUS(5), /* 13 irq 11 */ | 170 | SUN4M_SOFT_INT(6), SUN4M_SOFT_INT(7), |
152 | SUN4M_INT_SBUS(6) /* 14 irq 13 */ | 171 | SUN4M_SOFT_INT(8), SUN4M_SOFT_INT(9), |
172 | SUN4M_SOFT_INT(10), SUN4M_SOFT_INT(11), | ||
173 | SUN4M_SOFT_INT(12), SUN4M_SOFT_INT(13), | ||
174 | SUN4M_SOFT_INT(14), SUN4M_SOFT_INT(15), | ||
175 | /* onboard */ | ||
176 | 0, 0, 0, 0, | ||
177 | SUN4M_INT_SCSI, 0, SUN4M_INT_ETHERNET, 0, | ||
178 | SUN4M_INT_VIDEO, SUN4M_INT_MODULE, | ||
179 | SUN4M_INT_REALTIME, SUN4M_INT_FLOPPY, | ||
180 | (SUN4M_INT_SERIAL | SUN4M_INT_KBDMS), | ||
181 | SUN4M_INT_AUDIO, 0, SUN4M_INT_MODULE_ERR, | ||
182 | /* sbus */ | ||
183 | 0, 0, SUN4M_INT_SBUS(0), SUN4M_INT_SBUS(1), | ||
184 | 0, SUN4M_INT_SBUS(2), 0, SUN4M_INT_SBUS(3), | ||
185 | 0, SUN4M_INT_SBUS(4), 0, SUN4M_INT_SBUS(5), | ||
186 | 0, SUN4M_INT_SBUS(6), 0, 0, | ||
187 | /* vme */ | ||
188 | 0, 0, SUN4M_INT_VME(0), SUN4M_INT_VME(1), | ||
189 | 0, SUN4M_INT_VME(2), 0, SUN4M_INT_VME(3), | ||
190 | 0, SUN4M_INT_VME(4), 0, SUN4M_INT_VME(5), | ||
191 | 0, SUN4M_INT_VME(6), 0, 0 | ||
153 | }; | 192 | }; |
154 | 193 | ||
155 | static int sun4m_pil_map[] = { 0, 2, 3, 5, 7, 9, 11, 13 }; | ||
156 | |||
157 | static unsigned int sun4m_sbint_to_irq(struct sbus_dev *sdev, | ||
158 | unsigned int sbint) | ||
159 | { | ||
160 | if (sbint >= sizeof(sun4m_pil_map)) { | ||
161 | printk(KERN_ERR "%s: bogus SBINT %d\n", sdev->prom_name, sbint); | ||
162 | BUG(); | ||
163 | } | ||
164 | return sun4m_pil_map[sbint] | 0x30; | ||
165 | } | ||
166 | |||
167 | static unsigned long sun4m_get_irqmask(unsigned int irq) | 194 | static unsigned long sun4m_get_irqmask(unsigned int irq) |
168 | { | 195 | { |
169 | unsigned long mask; | 196 | unsigned long mask; |
170 | 197 | ||
171 | if (irq > 0x20) { | 198 | if (irq < 0x50) |
172 | /* OBIO/SBUS interrupts */ | 199 | mask = irq_mask[irq]; |
173 | irq &= 0x1f; | 200 | else |
174 | mask = irq_mask[irq_xlate[irq]]; | 201 | mask = 0; |
175 | if (!mask) | 202 | |
176 | printk("sun4m_get_irqmask: IRQ%d has no valid mask!\n",irq); | 203 | if (!mask) |
177 | } else { | 204 | printk(KERN_ERR "sun4m_get_irqmask: IRQ%d has no valid mask!\n", |
178 | /* Soft Interrupts will come here. | 205 | irq); |
179 | * Currently there is no way to trigger them but I'm sure | 206 | |
180 | * something could be cooked up. | ||
181 | */ | ||
182 | irq &= 0xf; | ||
183 | mask = SUN4M_SOFT_INT(irq); | ||
184 | } | ||
185 | return mask; | 207 | return mask; |
186 | } | 208 | } |
187 | 209 | ||
@@ -193,9 +215,9 @@ static void sun4m_disable_irq(unsigned int irq_nr) | |||
193 | mask = sun4m_get_irqmask(irq_nr); | 215 | mask = sun4m_get_irqmask(irq_nr); |
194 | local_irq_save(flags); | 216 | local_irq_save(flags); |
195 | if (irq_nr > 15) | 217 | if (irq_nr > 15) |
196 | sun4m_interrupts->set = mask; | 218 | sbus_writel(mask, &sun4m_irq_global->mask_set); |
197 | else | 219 | else |
198 | sun4m_interrupts->cpu_intregs[cpu].set = mask; | 220 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); |
199 | local_irq_restore(flags); | 221 | local_irq_restore(flags); |
200 | } | 222 | } |
201 | 223 | ||
@@ -212,13 +234,13 @@ static void sun4m_enable_irq(unsigned int irq_nr) | |||
212 | mask = sun4m_get_irqmask(irq_nr); | 234 | mask = sun4m_get_irqmask(irq_nr); |
213 | local_irq_save(flags); | 235 | local_irq_save(flags); |
214 | if (irq_nr > 15) | 236 | if (irq_nr > 15) |
215 | sun4m_interrupts->clear = mask; | 237 | sbus_writel(mask, &sun4m_irq_global->mask_clear); |
216 | else | 238 | else |
217 | sun4m_interrupts->cpu_intregs[cpu].clear = mask; | 239 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); |
218 | local_irq_restore(flags); | 240 | local_irq_restore(flags); |
219 | } else { | 241 | } else { |
220 | local_irq_save(flags); | 242 | local_irq_save(flags); |
221 | sun4m_interrupts->clear = SUN4M_INT_FLOPPY; | 243 | sbus_writel(SUN4M_INT_FLOPPY, &sun4m_irq_global->mask_clear); |
222 | local_irq_restore(flags); | 244 | local_irq_restore(flags); |
223 | } | 245 | } |
224 | } | 246 | } |
@@ -236,10 +258,10 @@ static unsigned long cpu_pil_to_imask[16] = { | |||
236 | /*9*/ SUN4M_INT_SBUS(4) | SUN4M_INT_VME(4) | SUN4M_INT_MODULE_ERR, | 258 | /*9*/ SUN4M_INT_SBUS(4) | SUN4M_INT_VME(4) | SUN4M_INT_MODULE_ERR, |
237 | /*10*/ SUN4M_INT_REALTIME, | 259 | /*10*/ SUN4M_INT_REALTIME, |
238 | /*11*/ SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY, | 260 | /*11*/ SUN4M_INT_SBUS(5) | SUN4M_INT_VME(5) | SUN4M_INT_FLOPPY, |
239 | /*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, | 261 | /*12*/ SUN4M_INT_SERIAL | SUN4M_INT_KBDMS, |
240 | /*13*/ SUN4M_INT_AUDIO, | 262 | /*13*/ SUN4M_INT_SBUS(6) | SUN4M_INT_VME(6) | SUN4M_INT_AUDIO, |
241 | /*14*/ SUN4M_INT_E14, | 263 | /*14*/ SUN4M_INT_E14, |
242 | /*15*/ 0x00000000 | 264 | /*15*/ SUN4M_INT_ERROR |
243 | }; | 265 | }; |
244 | 266 | ||
245 | /* We assume the caller has disabled local interrupts when these are called, | 267 | /* We assume the caller has disabled local interrupts when these are called, |
@@ -247,126 +269,141 @@ static unsigned long cpu_pil_to_imask[16] = { | |||
247 | */ | 269 | */ |
248 | static void sun4m_disable_pil_irq(unsigned int pil) | 270 | static void sun4m_disable_pil_irq(unsigned int pil) |
249 | { | 271 | { |
250 | sun4m_interrupts->set = cpu_pil_to_imask[pil]; | 272 | sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_set); |
251 | } | 273 | } |
252 | 274 | ||
253 | static void sun4m_enable_pil_irq(unsigned int pil) | 275 | static void sun4m_enable_pil_irq(unsigned int pil) |
254 | { | 276 | { |
255 | sun4m_interrupts->clear = cpu_pil_to_imask[pil]; | 277 | sbus_writel(cpu_pil_to_imask[pil], &sun4m_irq_global->mask_clear); |
256 | } | 278 | } |
257 | 279 | ||
258 | #ifdef CONFIG_SMP | 280 | #ifdef CONFIG_SMP |
259 | static void sun4m_send_ipi(int cpu, int level) | 281 | static void sun4m_send_ipi(int cpu, int level) |
260 | { | 282 | { |
261 | unsigned long mask; | 283 | unsigned long mask = sun4m_get_irqmask(level); |
262 | 284 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->set); | |
263 | mask = sun4m_get_irqmask(level); | ||
264 | sun4m_interrupts->cpu_intregs[cpu].set = mask; | ||
265 | } | 285 | } |
266 | 286 | ||
267 | static void sun4m_clear_ipi(int cpu, int level) | 287 | static void sun4m_clear_ipi(int cpu, int level) |
268 | { | 288 | { |
269 | unsigned long mask; | 289 | unsigned long mask = sun4m_get_irqmask(level); |
270 | 290 | sbus_writel(mask, &sun4m_irq_percpu[cpu]->clear); | |
271 | mask = sun4m_get_irqmask(level); | ||
272 | sun4m_interrupts->cpu_intregs[cpu].clear = mask; | ||
273 | } | 291 | } |
274 | 292 | ||
275 | static void sun4m_set_udt(int cpu) | 293 | static void sun4m_set_udt(int cpu) |
276 | { | 294 | { |
277 | sun4m_interrupts->undirected_target = cpu; | 295 | sbus_writel(cpu, &sun4m_irq_global->interrupt_target); |
278 | } | 296 | } |
279 | #endif | 297 | #endif |
280 | 298 | ||
281 | #define OBIO_INTR 0x20 | 299 | struct sun4m_timer_percpu { |
282 | #define TIMER_IRQ (OBIO_INTR | 10) | 300 | u32 l14_limit; |
283 | #define PROFILE_IRQ (OBIO_INTR | 14) | 301 | u32 l14_count; |
302 | u32 l14_limit_noclear; | ||
303 | u32 user_timer_start_stop; | ||
304 | }; | ||
305 | |||
306 | static struct sun4m_timer_percpu __iomem *timers_percpu[SUN4M_NCPUS]; | ||
307 | |||
308 | struct sun4m_timer_global { | ||
309 | u32 l10_limit; | ||
310 | u32 l10_count; | ||
311 | u32 l10_limit_noclear; | ||
312 | u32 reserved; | ||
313 | u32 timer_config; | ||
314 | }; | ||
315 | |||
316 | static struct sun4m_timer_global __iomem *timers_global; | ||
317 | |||
318 | #define TIMER_IRQ (OBP_INT_LEVEL_ONBOARD | 10) | ||
284 | 319 | ||
285 | static struct sun4m_timer_regs *sun4m_timers; | ||
286 | unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); | 320 | unsigned int lvl14_resolution = (((1000000/HZ) + 1) << 10); |
287 | 321 | ||
288 | static void sun4m_clear_clock_irq(void) | 322 | static void sun4m_clear_clock_irq(void) |
289 | { | 323 | { |
290 | volatile unsigned int clear_intr; | 324 | sbus_readl(&timers_global->l10_limit); |
291 | clear_intr = sun4m_timers->l10_timer_limit; | ||
292 | } | 325 | } |
293 | 326 | ||
294 | static void sun4m_clear_profile_irq(int cpu) | 327 | void sun4m_nmi(struct pt_regs *regs) |
295 | { | 328 | { |
296 | volatile unsigned int clear; | 329 | unsigned long afsr, afar, si; |
297 | 330 | ||
298 | clear = sun4m_timers->cpu_timers[cpu].l14_timer_limit; | 331 | printk(KERN_ERR "Aieee: sun4m NMI received!\n"); |
332 | /* XXX HyperSparc hack XXX */ | ||
333 | __asm__ __volatile__("mov 0x500, %%g1\n\t" | ||
334 | "lda [%%g1] 0x4, %0\n\t" | ||
335 | "mov 0x600, %%g1\n\t" | ||
336 | "lda [%%g1] 0x4, %1\n\t" : | ||
337 | "=r" (afsr), "=r" (afar)); | ||
338 | printk(KERN_ERR "afsr=%08lx afar=%08lx\n", afsr, afar); | ||
339 | si = sbus_readl(&sun4m_irq_global->pending); | ||
340 | printk(KERN_ERR "si=%08lx\n", si); | ||
341 | if (si & SUN4M_INT_MODULE_ERR) | ||
342 | printk(KERN_ERR "Module async error\n"); | ||
343 | if (si & SUN4M_INT_M2S_WRITE_ERR) | ||
344 | printk(KERN_ERR "MBus/SBus async error\n"); | ||
345 | if (si & SUN4M_INT_ECC_ERR) | ||
346 | printk(KERN_ERR "ECC memory error\n"); | ||
347 | if (si & SUN4M_INT_VME_ERR) | ||
348 | printk(KERN_ERR "VME async error\n"); | ||
349 | printk(KERN_ERR "you lose buddy boy...\n"); | ||
350 | show_regs(regs); | ||
351 | prom_halt(); | ||
352 | } | ||
353 | |||
354 | /* Exported for sun4m_smp.c */ | ||
355 | void sun4m_clear_profile_irq(int cpu) | ||
356 | { | ||
357 | sbus_readl(&timers_percpu[cpu]->l14_limit); | ||
299 | } | 358 | } |
300 | 359 | ||
301 | static void sun4m_load_profile_irq(int cpu, unsigned int limit) | 360 | static void sun4m_load_profile_irq(int cpu, unsigned int limit) |
302 | { | 361 | { |
303 | sun4m_timers->cpu_timers[cpu].l14_timer_limit = limit; | 362 | sbus_writel(limit, &timers_percpu[cpu]->l14_limit); |
304 | } | 363 | } |
305 | 364 | ||
306 | static void __init sun4m_init_timers(irq_handler_t counter_fn) | 365 | static void __init sun4m_init_timers(irq_handler_t counter_fn) |
307 | { | 366 | { |
308 | int reg_count, irq, cpu; | 367 | struct device_node *dp = of_find_node_by_name(NULL, "counter"); |
309 | struct linux_prom_registers cnt_regs[PROMREG_MAX]; | 368 | int i, err, len, num_cpu_timers; |
310 | int obio_node, cnt_node; | 369 | const u32 *addr; |
311 | struct resource r; | 370 | |
312 | 371 | if (!dp) { | |
313 | cnt_node = 0; | 372 | printk(KERN_ERR "sun4m_init_timers: No 'counter' node.\n"); |
314 | if((obio_node = | 373 | return; |
315 | prom_searchsiblings (prom_getchild(prom_root_node), "obio")) == 0 || | ||
316 | (obio_node = prom_getchild (obio_node)) == 0 || | ||
317 | (cnt_node = prom_searchsiblings (obio_node, "counter")) == 0) { | ||
318 | prom_printf("Cannot find /obio/counter node\n"); | ||
319 | prom_halt(); | ||
320 | } | 374 | } |
321 | reg_count = prom_getproperty(cnt_node, "reg", | 375 | |
322 | (void *) cnt_regs, sizeof(cnt_regs)); | 376 | addr = of_get_property(dp, "address", &len); |
323 | reg_count = (reg_count/sizeof(struct linux_prom_registers)); | 377 | if (!addr) { |
324 | 378 | printk(KERN_ERR "sun4m_init_timers: No 'address' prop.\n"); | |
325 | /* Apply the obio ranges to the timer registers. */ | 379 | return; |
326 | prom_apply_obio_ranges(cnt_regs, reg_count); | ||
327 | |||
328 | cnt_regs[4].phys_addr = cnt_regs[reg_count-1].phys_addr; | ||
329 | cnt_regs[4].reg_size = cnt_regs[reg_count-1].reg_size; | ||
330 | cnt_regs[4].which_io = cnt_regs[reg_count-1].which_io; | ||
331 | for(obio_node = 1; obio_node < 4; obio_node++) { | ||
332 | cnt_regs[obio_node].phys_addr = | ||
333 | cnt_regs[obio_node-1].phys_addr + PAGE_SIZE; | ||
334 | cnt_regs[obio_node].reg_size = cnt_regs[obio_node-1].reg_size; | ||
335 | cnt_regs[obio_node].which_io = cnt_regs[obio_node-1].which_io; | ||
336 | } | 380 | } |
337 | 381 | ||
338 | memset((char*)&r, 0, sizeof(struct resource)); | 382 | num_cpu_timers = (len / sizeof(u32)) - 1; |
339 | /* Map the per-cpu Counter registers. */ | 383 | for (i = 0; i < num_cpu_timers; i++) { |
340 | r.flags = cnt_regs[0].which_io; | 384 | timers_percpu[i] = (void __iomem *) |
341 | r.start = cnt_regs[0].phys_addr; | 385 | (unsigned long) addr[i]; |
342 | sun4m_timers = (struct sun4m_timer_regs *) sbus_ioremap(&r, 0, | ||
343 | PAGE_SIZE*SUN4M_NCPUS, "sun4m_cpu_cnt"); | ||
344 | /* Map the system Counter register. */ | ||
345 | /* XXX Here we expect consequent calls to yeld adjusent maps. */ | ||
346 | r.flags = cnt_regs[4].which_io; | ||
347 | r.start = cnt_regs[4].phys_addr; | ||
348 | sbus_ioremap(&r, 0, cnt_regs[4].reg_size, "sun4m_sys_cnt"); | ||
349 | |||
350 | sun4m_timers->l10_timer_limit = (((1000000/HZ) + 1) << 10); | ||
351 | master_l10_counter = &sun4m_timers->l10_cur_count; | ||
352 | master_l10_limit = &sun4m_timers->l10_timer_limit; | ||
353 | |||
354 | irq = request_irq(TIMER_IRQ, | ||
355 | counter_fn, | ||
356 | (IRQF_DISABLED | SA_STATIC_ALLOC), | ||
357 | "timer", NULL); | ||
358 | if (irq) { | ||
359 | prom_printf("time_init: unable to attach IRQ%d\n",TIMER_IRQ); | ||
360 | prom_halt(); | ||
361 | } | 386 | } |
362 | 387 | timers_global = (void __iomem *) | |
363 | if (!cpu_find_by_instance(1, NULL, NULL)) { | 388 | (unsigned long) addr[num_cpu_timers]; |
364 | for(cpu = 0; cpu < 4; cpu++) | 389 | |
365 | sun4m_timers->cpu_timers[cpu].l14_timer_limit = 0; | 390 | sbus_writel((((1000000/HZ) + 1) << 10), &timers_global->l10_limit); |
366 | sun4m_interrupts->set = SUN4M_INT_E14; | 391 | |
367 | } else { | 392 | master_l10_counter = &timers_global->l10_count; |
368 | sun4m_timers->cpu_timers[0].l14_timer_limit = 0; | 393 | |
394 | err = request_irq(TIMER_IRQ, counter_fn, | ||
395 | (IRQF_DISABLED | SA_STATIC_ALLOC), "timer", NULL); | ||
396 | if (err) { | ||
397 | printk(KERN_ERR "sun4m_init_timers: Register IRQ error %d.\n", | ||
398 | err); | ||
399 | return; | ||
369 | } | 400 | } |
401 | |||
402 | for (i = 0; i < num_cpu_timers; i++) | ||
403 | sbus_writel(0, &timers_percpu[i]->l14_limit); | ||
404 | if (num_cpu_timers == 4) | ||
405 | sbus_writel(SUN4M_INT_E14, &sun4m_irq_global->mask_set); | ||
406 | |||
370 | #ifdef CONFIG_SMP | 407 | #ifdef CONFIG_SMP |
371 | { | 408 | { |
372 | unsigned long flags; | 409 | unsigned long flags; |
@@ -390,70 +427,43 @@ static void __init sun4m_init_timers(irq_handler_t counter_fn) | |||
390 | 427 | ||
391 | void __init sun4m_init_IRQ(void) | 428 | void __init sun4m_init_IRQ(void) |
392 | { | 429 | { |
393 | int ie_node,i; | 430 | struct device_node *dp = of_find_node_by_name(NULL, "interrupt"); |
394 | struct linux_prom_registers int_regs[PROMREG_MAX]; | 431 | int len, i, mid, num_cpu_iregs; |
395 | int num_regs; | 432 | const u32 *addr; |
396 | struct resource r; | 433 | |
397 | int mid; | 434 | if (!dp) { |
398 | 435 | printk(KERN_ERR "sun4m_init_IRQ: No 'interrupt' node.\n"); | |
399 | local_irq_disable(); | 436 | return; |
400 | if((ie_node = prom_searchsiblings(prom_getchild(prom_root_node), "obio")) == 0 || | ||
401 | (ie_node = prom_getchild (ie_node)) == 0 || | ||
402 | (ie_node = prom_searchsiblings (ie_node, "interrupt")) == 0) { | ||
403 | prom_printf("Cannot find /obio/interrupt node\n"); | ||
404 | prom_halt(); | ||
405 | } | 437 | } |
406 | num_regs = prom_getproperty(ie_node, "reg", (char *) int_regs, | 438 | |
407 | sizeof(int_regs)); | 439 | addr = of_get_property(dp, "address", &len); |
408 | num_regs = (num_regs/sizeof(struct linux_prom_registers)); | 440 | if (!addr) { |
409 | 441 | printk(KERN_ERR "sun4m_init_IRQ: No 'address' prop.\n"); | |
410 | /* Apply the obio ranges to these registers. */ | 442 | return; |
411 | prom_apply_obio_ranges(int_regs, num_regs); | ||
412 | |||
413 | int_regs[4].phys_addr = int_regs[num_regs-1].phys_addr; | ||
414 | int_regs[4].reg_size = int_regs[num_regs-1].reg_size; | ||
415 | int_regs[4].which_io = int_regs[num_regs-1].which_io; | ||
416 | for(ie_node = 1; ie_node < 4; ie_node++) { | ||
417 | int_regs[ie_node].phys_addr = int_regs[ie_node-1].phys_addr + PAGE_SIZE; | ||
418 | int_regs[ie_node].reg_size = int_regs[ie_node-1].reg_size; | ||
419 | int_regs[ie_node].which_io = int_regs[ie_node-1].which_io; | ||
420 | } | 443 | } |
421 | 444 | ||
422 | memset((char *)&r, 0, sizeof(struct resource)); | 445 | num_cpu_iregs = (len / sizeof(u32)) - 1; |
423 | /* Map the interrupt registers for all possible cpus. */ | 446 | for (i = 0; i < num_cpu_iregs; i++) { |
424 | r.flags = int_regs[0].which_io; | 447 | sun4m_irq_percpu[i] = (void __iomem *) |
425 | r.start = int_regs[0].phys_addr; | 448 | (unsigned long) addr[i]; |
426 | sun4m_interrupts = (struct sun4m_intregs *) sbus_ioremap(&r, 0, | 449 | } |
427 | PAGE_SIZE*SUN4M_NCPUS, "interrupts_percpu"); | 450 | sun4m_irq_global = (void __iomem *) |
451 | (unsigned long) addr[num_cpu_iregs]; | ||
428 | 452 | ||
429 | /* Map the system interrupt control registers. */ | 453 | local_irq_disable(); |
430 | r.flags = int_regs[4].which_io; | ||
431 | r.start = int_regs[4].phys_addr; | ||
432 | sbus_ioremap(&r, 0, int_regs[4].reg_size, "interrupts_system"); | ||
433 | 454 | ||
434 | sun4m_interrupts->set = ~SUN4M_INT_MASKALL; | 455 | sbus_writel(~SUN4M_INT_MASKALL, &sun4m_irq_global->mask_set); |
435 | for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) | 456 | for (i = 0; !cpu_find_by_instance(i, NULL, &mid); i++) |
436 | sun4m_interrupts->cpu_intregs[mid].clear = ~0x17fff; | 457 | sbus_writel(~0x17fff, &sun4m_irq_percpu[mid]->clear); |
437 | 458 | ||
438 | if (!cpu_find_by_instance(1, NULL, NULL)) { | 459 | if (num_cpu_iregs == 4) |
439 | /* system wide interrupts go to cpu 0, this should always | 460 | sbus_writel(0, &sun4m_irq_global->interrupt_target); |
440 | * be safe because it is guaranteed to be fitted or OBP doesn't | 461 | |
441 | * come up | ||
442 | * | ||
443 | * Not sure, but writing here on SLAVIO systems may puke | ||
444 | * so I don't do it unless there is more than 1 cpu. | ||
445 | */ | ||
446 | irq_rcvreg = (unsigned long *) | ||
447 | &sun4m_interrupts->undirected_target; | ||
448 | sun4m_interrupts->undirected_target = 0; | ||
449 | } | ||
450 | BTFIXUPSET_CALL(sbint_to_irq, sun4m_sbint_to_irq, BTFIXUPCALL_NORM); | ||
451 | BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); | 462 | BTFIXUPSET_CALL(enable_irq, sun4m_enable_irq, BTFIXUPCALL_NORM); |
452 | BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); | 463 | BTFIXUPSET_CALL(disable_irq, sun4m_disable_irq, BTFIXUPCALL_NORM); |
453 | BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); | 464 | BTFIXUPSET_CALL(enable_pil_irq, sun4m_enable_pil_irq, BTFIXUPCALL_NORM); |
454 | BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM); | 465 | BTFIXUPSET_CALL(disable_pil_irq, sun4m_disable_pil_irq, BTFIXUPCALL_NORM); |
455 | BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); | 466 | BTFIXUPSET_CALL(clear_clock_irq, sun4m_clear_clock_irq, BTFIXUPCALL_NORM); |
456 | BTFIXUPSET_CALL(clear_profile_irq, sun4m_clear_profile_irq, BTFIXUPCALL_NORM); | ||
457 | BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); | 467 | BTFIXUPSET_CALL(load_profile_irq, sun4m_load_profile_irq, BTFIXUPCALL_NORM); |
458 | sparc_init_timers = sun4m_init_timers; | 468 | sparc_init_timers = sun4m_init_timers; |
459 | #ifdef CONFIG_SMP | 469 | #ifdef CONFIG_SMP |
@@ -461,5 +471,6 @@ void __init sun4m_init_IRQ(void) | |||
461 | BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); | 471 | BTFIXUPSET_CALL(clear_cpu_int, sun4m_clear_ipi, BTFIXUPCALL_NORM); |
462 | BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM); | 472 | BTFIXUPSET_CALL(set_irq_udt, sun4m_set_udt, BTFIXUPCALL_NORM); |
463 | #endif | 473 | #endif |
474 | |||
464 | /* Cannot enable interrupts until OBP ticker is disabled. */ | 475 | /* Cannot enable interrupts until OBP ticker is disabled. */ |
465 | } | 476 | } |
diff --git a/arch/sparc/kernel/sun4m_smp.c b/arch/sparc/kernel/sun4m_smp.c index 9964890dc1db..0c564ba9e709 100644 --- a/arch/sparc/kernel/sun4m_smp.c +++ b/arch/sparc/kernel/sun4m_smp.c | |||
@@ -315,6 +315,8 @@ void smp4m_cross_call_irq(void) | |||
315 | ccall_info.processors_out[i] = 1; | 315 | ccall_info.processors_out[i] = 1; |
316 | } | 316 | } |
317 | 317 | ||
318 | extern void sun4m_clear_profile_irq(int cpu); | ||
319 | |||
318 | void smp4m_percpu_timer_interrupt(struct pt_regs *regs) | 320 | void smp4m_percpu_timer_interrupt(struct pt_regs *regs) |
319 | { | 321 | { |
320 | struct pt_regs *old_regs; | 322 | struct pt_regs *old_regs; |
@@ -322,7 +324,7 @@ void smp4m_percpu_timer_interrupt(struct pt_regs *regs) | |||
322 | 324 | ||
323 | old_regs = set_irq_regs(regs); | 325 | old_regs = set_irq_regs(regs); |
324 | 326 | ||
325 | clear_profile_irq(cpu); | 327 | sun4m_clear_profile_irq(cpu); |
326 | 328 | ||
327 | profile_tick(CPU_PROFILING); | 329 | profile_tick(CPU_PROFILING); |
328 | 330 | ||
diff --git a/arch/sparc/kernel/sun4setup.c b/arch/sparc/kernel/sun4setup.c deleted file mode 100644 index 229a52f55f16..000000000000 --- a/arch/sparc/kernel/sun4setup.c +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | /* sun4setup.c: Setup the hardware address of various items in the sun4 | ||
2 | * architecture. Called from idprom_init | ||
3 | * | ||
4 | * Copyright (C) 1998 Chris G. Davis (cdavis@cois.on.ca) | ||
5 | */ | ||
6 | |||
7 | #include <asm/page.h> | ||
8 | #include <asm/oplib.h> | ||
9 | #include <asm/idprom.h> | ||
10 | #include <asm/sun4paddr.h> | ||
11 | #include <asm/machines.h> | ||
12 | |||
13 | int sun4_memreg_physaddr; | ||
14 | int sun4_ie_physaddr; | ||
15 | int sun4_clock_physaddr; | ||
16 | int sun4_timer_physaddr; | ||
17 | int sun4_eth_physaddr; | ||
18 | int sun4_si_physaddr; | ||
19 | int sun4_bwtwo_physaddr; | ||
20 | int sun4_zs0_physaddr; | ||
21 | int sun4_zs1_physaddr; | ||
22 | int sun4_dma_physaddr; | ||
23 | int sun4_esp_physaddr; | ||
24 | int sun4_ie_physaddr; | ||
25 | |||
26 | void __init sun4setup(void) | ||
27 | { | ||
28 | printk("Sun4 Hardware Setup v1.0 18/May/98 Chris Davis (cdavis@cois.on.ca). "); | ||
29 | /* | ||
30 | setup standard sun4 info | ||
31 | */ | ||
32 | sun4_ie_physaddr=SUN4_IE_PHYSADDR; | ||
33 | |||
34 | /* | ||
35 | setup model specific info | ||
36 | */ | ||
37 | switch(idprom->id_machtype) { | ||
38 | case (SM_SUN4 | SM_4_260 ): | ||
39 | printk("Setup for a SUN4/260\n"); | ||
40 | sun4_memreg_physaddr=SUN4_200_MEMREG_PHYSADDR; | ||
41 | sun4_clock_physaddr=SUN4_200_CLOCK_PHYSADDR; | ||
42 | sun4_timer_physaddr=SUN4_UNUSED_PHYSADDR; | ||
43 | sun4_eth_physaddr=SUN4_200_ETH_PHYSADDR; | ||
44 | sun4_si_physaddr=SUN4_200_SI_PHYSADDR; | ||
45 | sun4_bwtwo_physaddr=SUN4_200_BWTWO_PHYSADDR; | ||
46 | sun4_dma_physaddr=SUN4_UNUSED_PHYSADDR; | ||
47 | sun4_esp_physaddr=SUN4_UNUSED_PHYSADDR; | ||
48 | break; | ||
49 | case (SM_SUN4 | SM_4_330 ): | ||
50 | printk("Setup for a SUN4/330\n"); | ||
51 | sun4_memreg_physaddr=SUN4_300_MEMREG_PHYSADDR; | ||
52 | sun4_clock_physaddr=SUN4_300_CLOCK_PHYSADDR; | ||
53 | sun4_timer_physaddr=SUN4_300_TIMER_PHYSADDR; | ||
54 | sun4_eth_physaddr=SUN4_300_ETH_PHYSADDR; | ||
55 | sun4_si_physaddr=SUN4_UNUSED_PHYSADDR; | ||
56 | sun4_bwtwo_physaddr=SUN4_300_BWTWO_PHYSADDR; | ||
57 | sun4_dma_physaddr=SUN4_300_DMA_PHYSADDR; | ||
58 | sun4_esp_physaddr=SUN4_300_ESP_PHYSADDR; | ||
59 | break; | ||
60 | case (SM_SUN4 | SM_4_470 ): | ||
61 | printk("Setup for a SUN4/470\n"); | ||
62 | sun4_memreg_physaddr=SUN4_400_MEMREG_PHYSADDR; | ||
63 | sun4_clock_physaddr=SUN4_400_CLOCK_PHYSADDR; | ||
64 | sun4_timer_physaddr=SUN4_400_TIMER_PHYSADDR; | ||
65 | sun4_eth_physaddr=SUN4_400_ETH_PHYSADDR; | ||
66 | sun4_si_physaddr=SUN4_UNUSED_PHYSADDR; | ||
67 | sun4_bwtwo_physaddr=SUN4_400_BWTWO_PHYSADDR; | ||
68 | sun4_dma_physaddr=SUN4_400_DMA_PHYSADDR; | ||
69 | sun4_esp_physaddr=SUN4_400_ESP_PHYSADDR; | ||
70 | break; | ||
71 | default: | ||
72 | ; | ||
73 | } | ||
74 | } | ||
75 | |||
diff --git a/arch/sparc/kernel/sys_sparc.c b/arch/sparc/kernel/sys_sparc.c index 4d73421559c3..03035c852a43 100644 --- a/arch/sparc/kernel/sys_sparc.c +++ b/arch/sparc/kernel/sys_sparc.c | |||
@@ -53,7 +53,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi | |||
53 | /* See asm-sparc/uaccess.h */ | 53 | /* See asm-sparc/uaccess.h */ |
54 | if (len > TASK_SIZE - PAGE_SIZE) | 54 | if (len > TASK_SIZE - PAGE_SIZE) |
55 | return -ENOMEM; | 55 | return -ENOMEM; |
56 | if (ARCH_SUN4C_SUN4 && len > 0x20000000) | 56 | if (ARCH_SUN4C && len > 0x20000000) |
57 | return -ENOMEM; | 57 | return -ENOMEM; |
58 | if (!addr) | 58 | if (!addr) |
59 | addr = TASK_UNMAPPED_BASE; | 59 | addr = TASK_UNMAPPED_BASE; |
@@ -65,7 +65,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi | |||
65 | 65 | ||
66 | for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { | 66 | for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) { |
67 | /* At this point: (!vmm || addr < vmm->vm_end). */ | 67 | /* At this point: (!vmm || addr < vmm->vm_end). */ |
68 | if (ARCH_SUN4C_SUN4 && addr < 0xe0000000 && 0x20000000 - len < addr) { | 68 | if (ARCH_SUN4C && addr < 0xe0000000 && 0x20000000 - len < addr) { |
69 | addr = PAGE_OFFSET; | 69 | addr = PAGE_OFFSET; |
70 | vmm = find_vma(current->mm, PAGE_OFFSET); | 70 | vmm = find_vma(current->mm, PAGE_OFFSET); |
71 | } | 71 | } |
@@ -81,7 +81,7 @@ unsigned long arch_get_unmapped_area(struct file *filp, unsigned long addr, unsi | |||
81 | 81 | ||
82 | asmlinkage unsigned long sparc_brk(unsigned long brk) | 82 | asmlinkage unsigned long sparc_brk(unsigned long brk) |
83 | { | 83 | { |
84 | if(ARCH_SUN4C_SUN4) { | 84 | if(ARCH_SUN4C) { |
85 | if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000)) | 85 | if ((brk & 0xe0000000) != (current->mm->brk & 0xe0000000)) |
86 | return current->mm->brk; | 86 | return current->mm->brk; |
87 | } | 87 | } |
@@ -221,7 +221,7 @@ out: | |||
221 | 221 | ||
222 | int sparc_mmap_check(unsigned long addr, unsigned long len) | 222 | int sparc_mmap_check(unsigned long addr, unsigned long len) |
223 | { | 223 | { |
224 | if (ARCH_SUN4C_SUN4 && | 224 | if (ARCH_SUN4C && |
225 | (len > 0x20000000 || | 225 | (len > 0x20000000 || |
226 | (addr < 0xe0000000 && addr + len > 0x20000000))) | 226 | (addr < 0xe0000000 && addr + len > 0x20000000))) |
227 | return -EINVAL; | 227 | return -EINVAL; |
diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c index 707bfda86570..138bbf5f8724 100644 --- a/arch/sparc/kernel/tick14.c +++ b/arch/sparc/kernel/tick14.c | |||
@@ -1,31 +1,12 @@ | |||
1 | /* tick14.c | 1 | /* tick14.c |
2 | * linux/arch/sparc/kernel/tick14.c | ||
3 | * | 2 | * |
4 | * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk) | 3 | * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk) |
5 | * | 4 | * |
6 | * This file handles the Sparc specific level14 ticker | 5 | * This file handles the Sparc specific level14 ticker |
7 | * This is really useful for profiling OBP uses it for keyboard | 6 | * This is really useful for profiling OBP uses it for keyboard |
8 | * aborts and other stuff. | 7 | * aborts and other stuff. |
9 | * | ||
10 | * | ||
11 | */ | 8 | */ |
12 | #include <linux/errno.h> | ||
13 | #include <linux/sched.h> | ||
14 | #include <linux/kernel.h> | 9 | #include <linux/kernel.h> |
15 | #include <linux/param.h> | ||
16 | #include <linux/string.h> | ||
17 | #include <linux/mm.h> | ||
18 | #include <linux/timex.h> | ||
19 | #include <linux/interrupt.h> | ||
20 | |||
21 | #include <asm/oplib.h> | ||
22 | #include <asm/timer.h> | ||
23 | #include <asm/mostek.h> | ||
24 | #include <asm/system.h> | ||
25 | #include <asm/irq.h> | ||
26 | #include <asm/io.h> | ||
27 | |||
28 | #include "irq.h" | ||
29 | 10 | ||
30 | extern unsigned long lvl14_save[5]; | 11 | extern unsigned long lvl14_save[5]; |
31 | static unsigned long *linux_lvl14 = NULL; | 12 | static unsigned long *linux_lvl14 = NULL; |
@@ -56,31 +37,3 @@ void install_obp_ticker(void) | |||
56 | linux_lvl14[2] = obp_lvl14[2]; | 37 | linux_lvl14[2] = obp_lvl14[2]; |
57 | linux_lvl14[3] = obp_lvl14[3]; | 38 | linux_lvl14[3] = obp_lvl14[3]; |
58 | } | 39 | } |
59 | |||
60 | void claim_ticker14(irq_handler_t handler, | ||
61 | int irq_nr, unsigned int timeout ) | ||
62 | { | ||
63 | int cpu = smp_processor_id(); | ||
64 | |||
65 | /* first we copy the obp handler instructions | ||
66 | */ | ||
67 | __disable_irq(irq_nr); | ||
68 | if (!handler) | ||
69 | return; | ||
70 | |||
71 | linux_lvl14 = (unsigned long *)lvl14_save[4]; | ||
72 | obp_lvl14[0] = linux_lvl14[0]; | ||
73 | obp_lvl14[1] = linux_lvl14[1]; | ||
74 | obp_lvl14[2] = linux_lvl14[2]; | ||
75 | obp_lvl14[3] = linux_lvl14[3]; | ||
76 | |||
77 | if (!request_irq(irq_nr, | ||
78 | handler, | ||
79 | (IRQF_DISABLED | SA_STATIC_ALLOC), | ||
80 | "counter14", | ||
81 | NULL)) { | ||
82 | install_linux_ticker(); | ||
83 | load_profile_irq(cpu, timeout); | ||
84 | __enable_irq(irq_nr); | ||
85 | } | ||
86 | } | ||
diff --git a/arch/sparc/kernel/time.c b/arch/sparc/kernel/time.c index 0762f5db1924..62c1d94cb434 100644 --- a/arch/sparc/kernel/time.c +++ b/arch/sparc/kernel/time.c | |||
@@ -23,22 +23,24 @@ | |||
23 | #include <linux/mm.h> | 23 | #include <linux/mm.h> |
24 | #include <linux/interrupt.h> | 24 | #include <linux/interrupt.h> |
25 | #include <linux/time.h> | 25 | #include <linux/time.h> |
26 | #include <linux/rtc.h> | ||
27 | #include <linux/rtc/m48t59.h> | ||
26 | #include <linux/timex.h> | 28 | #include <linux/timex.h> |
27 | #include <linux/init.h> | 29 | #include <linux/init.h> |
28 | #include <linux/pci.h> | 30 | #include <linux/pci.h> |
29 | #include <linux/ioport.h> | 31 | #include <linux/ioport.h> |
30 | #include <linux/profile.h> | 32 | #include <linux/profile.h> |
33 | #include <linux/of.h> | ||
31 | #include <linux/of_device.h> | 34 | #include <linux/of_device.h> |
35 | #include <linux/platform_device.h> | ||
32 | 36 | ||
33 | #include <asm/oplib.h> | 37 | #include <asm/oplib.h> |
34 | #include <asm/timer.h> | 38 | #include <asm/timer.h> |
35 | #include <asm/mostek.h> | ||
36 | #include <asm/system.h> | 39 | #include <asm/system.h> |
37 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
38 | #include <asm/io.h> | 41 | #include <asm/io.h> |
39 | #include <asm/idprom.h> | 42 | #include <asm/idprom.h> |
40 | #include <asm/machines.h> | 43 | #include <asm/machines.h> |
41 | #include <asm/sun4paddr.h> | ||
42 | #include <asm/page.h> | 44 | #include <asm/page.h> |
43 | #include <asm/pcic.h> | 45 | #include <asm/pcic.h> |
44 | #include <asm/irq_regs.h> | 46 | #include <asm/irq_regs.h> |
@@ -46,34 +48,9 @@ | |||
46 | #include "irq.h" | 48 | #include "irq.h" |
47 | 49 | ||
48 | DEFINE_SPINLOCK(rtc_lock); | 50 | DEFINE_SPINLOCK(rtc_lock); |
49 | static enum sparc_clock_type sp_clock_typ; | ||
50 | DEFINE_SPINLOCK(mostek_lock); | ||
51 | void __iomem *mstk48t02_regs = NULL; | ||
52 | static struct mostek48t08 __iomem *mstk48t08_regs = NULL; | ||
53 | static int set_rtc_mmss(unsigned long); | 51 | static int set_rtc_mmss(unsigned long); |
54 | static int sbus_do_settimeofday(struct timespec *tv); | 52 | static int sbus_do_settimeofday(struct timespec *tv); |
55 | 53 | ||
56 | #ifdef CONFIG_SUN4 | ||
57 | struct intersil *intersil_clock; | ||
58 | #define intersil_cmd(intersil_reg, intsil_cmd) intersil_reg->int_cmd_reg = \ | ||
59 | (intsil_cmd) | ||
60 | |||
61 | #define intersil_intr(intersil_reg, intsil_cmd) intersil_reg->int_intr_reg = \ | ||
62 | (intsil_cmd) | ||
63 | |||
64 | #define intersil_start(intersil_reg) intersil_cmd(intersil_reg, \ | ||
65 | ( INTERSIL_START | INTERSIL_32K | INTERSIL_NORMAL | INTERSIL_24H |\ | ||
66 | INTERSIL_INTR_ENABLE)) | ||
67 | |||
68 | #define intersil_stop(intersil_reg) intersil_cmd(intersil_reg, \ | ||
69 | ( INTERSIL_STOP | INTERSIL_32K | INTERSIL_NORMAL | INTERSIL_24H |\ | ||
70 | INTERSIL_INTR_ENABLE)) | ||
71 | |||
72 | #define intersil_read_intr(intersil_reg, towhere) towhere = \ | ||
73 | intersil_reg->int_intr_reg | ||
74 | |||
75 | #endif | ||
76 | |||
77 | unsigned long profile_pc(struct pt_regs *regs) | 54 | unsigned long profile_pc(struct pt_regs *regs) |
78 | { | 55 | { |
79 | extern char __copy_user_begin[], __copy_user_end[]; | 56 | extern char __copy_user_begin[], __copy_user_end[]; |
@@ -96,7 +73,6 @@ unsigned long profile_pc(struct pt_regs *regs) | |||
96 | EXPORT_SYMBOL(profile_pc); | 73 | EXPORT_SYMBOL(profile_pc); |
97 | 74 | ||
98 | __volatile__ unsigned int *master_l10_counter; | 75 | __volatile__ unsigned int *master_l10_counter; |
99 | __volatile__ unsigned int *master_l10_limit; | ||
100 | 76 | ||
101 | /* | 77 | /* |
102 | * timer_interrupt() needs to keep up the real-time clock, | 78 | * timer_interrupt() needs to keep up the real-time clock, |
@@ -116,15 +92,7 @@ static irqreturn_t timer_interrupt(int dummy, void *dev_id) | |||
116 | 92 | ||
117 | /* Protect counter clear so that do_gettimeoffset works */ | 93 | /* Protect counter clear so that do_gettimeoffset works */ |
118 | write_seqlock(&xtime_lock); | 94 | write_seqlock(&xtime_lock); |
119 | #ifdef CONFIG_SUN4 | 95 | |
120 | if((idprom->id_machtype == (SM_SUN4 | SM_4_260)) || | ||
121 | (idprom->id_machtype == (SM_SUN4 | SM_4_110))) { | ||
122 | int temp; | ||
123 | intersil_read_intr(intersil_clock, temp); | ||
124 | /* re-enable the irq */ | ||
125 | enable_pil_irq(10); | ||
126 | } | ||
127 | #endif | ||
128 | clear_clock_irq(); | 96 | clear_clock_irq(); |
129 | 97 | ||
130 | do_timer(1); | 98 | do_timer(1); |
@@ -147,157 +115,56 @@ static irqreturn_t timer_interrupt(int dummy, void *dev_id) | |||
147 | return IRQ_HANDLED; | 115 | return IRQ_HANDLED; |
148 | } | 116 | } |
149 | 117 | ||
150 | /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ | 118 | static unsigned char mostek_read_byte(struct device *dev, u32 ofs) |
151 | static void __devinit kick_start_clock(void) | ||
152 | { | 119 | { |
153 | struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; | 120 | struct platform_device *pdev = to_platform_device(dev); |
154 | unsigned char sec; | 121 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; |
155 | int i, count; | 122 | void __iomem *regs = pdata->ioaddr; |
156 | 123 | unsigned char val = readb(regs + ofs); | |
157 | prom_printf("CLOCK: Clock was stopped. Kick start "); | 124 | |
158 | 125 | /* the year 0 is 1968 */ | |
159 | spin_lock_irq(&mostek_lock); | 126 | if (ofs == pdata->offset + M48T59_YEAR) { |
160 | 127 | val += 0x68; | |
161 | /* Turn on the kick start bit to start the oscillator. */ | 128 | if ((val & 0xf) > 9) |
162 | regs->creg |= MSTK_CREG_WRITE; | 129 | val += 6; |
163 | regs->sec &= ~MSTK_STOP; | ||
164 | regs->hour |= MSTK_KICK_START; | ||
165 | regs->creg &= ~MSTK_CREG_WRITE; | ||
166 | |||
167 | spin_unlock_irq(&mostek_lock); | ||
168 | |||
169 | /* Delay to allow the clock oscillator to start. */ | ||
170 | sec = MSTK_REG_SEC(regs); | ||
171 | for (i = 0; i < 3; i++) { | ||
172 | while (sec == MSTK_REG_SEC(regs)) | ||
173 | for (count = 0; count < 100000; count++) | ||
174 | /* nothing */ ; | ||
175 | prom_printf("."); | ||
176 | sec = regs->sec; | ||
177 | } | ||
178 | prom_printf("\n"); | ||
179 | |||
180 | spin_lock_irq(&mostek_lock); | ||
181 | |||
182 | /* Turn off kick start and set a "valid" time and date. */ | ||
183 | regs->creg |= MSTK_CREG_WRITE; | ||
184 | regs->hour &= ~MSTK_KICK_START; | ||
185 | MSTK_SET_REG_SEC(regs,0); | ||
186 | MSTK_SET_REG_MIN(regs,0); | ||
187 | MSTK_SET_REG_HOUR(regs,0); | ||
188 | MSTK_SET_REG_DOW(regs,5); | ||
189 | MSTK_SET_REG_DOM(regs,1); | ||
190 | MSTK_SET_REG_MONTH(regs,8); | ||
191 | MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO); | ||
192 | regs->creg &= ~MSTK_CREG_WRITE; | ||
193 | |||
194 | spin_unlock_irq(&mostek_lock); | ||
195 | |||
196 | /* Ensure the kick start bit is off. If it isn't, turn it off. */ | ||
197 | while (regs->hour & MSTK_KICK_START) { | ||
198 | prom_printf("CLOCK: Kick start still on!\n"); | ||
199 | |||
200 | spin_lock_irq(&mostek_lock); | ||
201 | regs->creg |= MSTK_CREG_WRITE; | ||
202 | regs->hour &= ~MSTK_KICK_START; | ||
203 | regs->creg &= ~MSTK_CREG_WRITE; | ||
204 | spin_unlock_irq(&mostek_lock); | ||
205 | } | 130 | } |
206 | 131 | return val; | |
207 | prom_printf("CLOCK: Kick start procedure successful.\n"); | ||
208 | } | ||
209 | |||
210 | /* Return nonzero if the clock chip battery is low. */ | ||
211 | static inline int has_low_battery(void) | ||
212 | { | ||
213 | struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; | ||
214 | unsigned char data1, data2; | ||
215 | |||
216 | spin_lock_irq(&mostek_lock); | ||
217 | data1 = regs->eeprom[0]; /* Read some data. */ | ||
218 | regs->eeprom[0] = ~data1; /* Write back the complement. */ | ||
219 | data2 = regs->eeprom[0]; /* Read back the complement. */ | ||
220 | regs->eeprom[0] = data1; /* Restore the original value. */ | ||
221 | spin_unlock_irq(&mostek_lock); | ||
222 | |||
223 | return (data1 == data2); /* Was the write blocked? */ | ||
224 | } | 132 | } |
225 | 133 | ||
226 | static void __devinit mostek_set_system_time(void) | 134 | static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) |
227 | { | 135 | { |
228 | unsigned int year, mon, day, hour, min, sec; | 136 | struct platform_device *pdev = to_platform_device(dev); |
229 | struct mostek48t02 *mregs; | 137 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; |
230 | 138 | void __iomem *regs = pdata->ioaddr; | |
231 | mregs = (struct mostek48t02 *)mstk48t02_regs; | 139 | |
232 | if(!mregs) { | 140 | if (ofs == pdata->offset + M48T59_YEAR) { |
233 | prom_printf("Something wrong, clock regs not mapped yet.\n"); | 141 | if (val < 0x68) |
234 | prom_halt(); | 142 | val += 0x32; |
235 | } | 143 | else |
236 | spin_lock_irq(&mostek_lock); | 144 | val -= 0x68; |
237 | mregs->creg |= MSTK_CREG_READ; | 145 | if ((val & 0xf) > 9) |
238 | sec = MSTK_REG_SEC(mregs); | 146 | val += 6; |
239 | min = MSTK_REG_MIN(mregs); | 147 | if ((val & 0xf0) > 0x9A) |
240 | hour = MSTK_REG_HOUR(mregs); | 148 | val += 0x60; |
241 | day = MSTK_REG_DOM(mregs); | 149 | } |
242 | mon = MSTK_REG_MONTH(mregs); | 150 | writeb(val, regs + ofs); |
243 | year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); | ||
244 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | ||
245 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | ||
246 | set_normalized_timespec(&wall_to_monotonic, | ||
247 | -xtime.tv_sec, -xtime.tv_nsec); | ||
248 | mregs->creg &= ~MSTK_CREG_READ; | ||
249 | spin_unlock_irq(&mostek_lock); | ||
250 | } | 151 | } |
251 | 152 | ||
252 | /* Probe for the real time clock chip on Sun4 */ | 153 | static struct m48t59_plat_data m48t59_data = { |
253 | static inline void sun4_clock_probe(void) | 154 | .read_byte = mostek_read_byte, |
254 | { | 155 | .write_byte = mostek_write_byte, |
255 | #ifdef CONFIG_SUN4 | 156 | }; |
256 | int temp; | ||
257 | struct resource r; | ||
258 | |||
259 | memset(&r, 0, sizeof(r)); | ||
260 | if( idprom->id_machtype == (SM_SUN4 | SM_4_330) ) { | ||
261 | sp_clock_typ = MSTK48T02; | ||
262 | r.start = sun4_clock_physaddr; | ||
263 | mstk48t02_regs = sbus_ioremap(&r, 0, | ||
264 | sizeof(struct mostek48t02), NULL); | ||
265 | mstk48t08_regs = NULL; /* To catch weirdness */ | ||
266 | intersil_clock = NULL; /* just in case */ | ||
267 | |||
268 | /* Kick start the clock if it is completely stopped. */ | ||
269 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) | ||
270 | kick_start_clock(); | ||
271 | } else if( idprom->id_machtype == (SM_SUN4 | SM_4_260)) { | ||
272 | /* intersil setup code */ | ||
273 | printk("Clock: INTERSIL at %8x ",sun4_clock_physaddr); | ||
274 | sp_clock_typ = INTERSIL; | ||
275 | r.start = sun4_clock_physaddr; | ||
276 | intersil_clock = (struct intersil *) | ||
277 | sbus_ioremap(&r, 0, sizeof(*intersil_clock), "intersil"); | ||
278 | mstk48t02_regs = 0; /* just be sure */ | ||
279 | mstk48t08_regs = NULL; /* ditto */ | ||
280 | /* initialise the clock */ | ||
281 | |||
282 | intersil_intr(intersil_clock,INTERSIL_INT_100HZ); | ||
283 | |||
284 | intersil_start(intersil_clock); | ||
285 | |||
286 | intersil_read_intr(intersil_clock, temp); | ||
287 | while (!(temp & 0x80)) | ||
288 | intersil_read_intr(intersil_clock, temp); | ||
289 | |||
290 | intersil_read_intr(intersil_clock, temp); | ||
291 | while (!(temp & 0x80)) | ||
292 | intersil_read_intr(intersil_clock, temp); | ||
293 | |||
294 | intersil_stop(intersil_clock); | ||
295 | 157 | ||
296 | } | 158 | /* resource is set at runtime */ |
297 | #endif | 159 | static struct platform_device m48t59_rtc = { |
298 | } | 160 | .name = "rtc-m48t59", |
161 | .id = 0, | ||
162 | .num_resources = 1, | ||
163 | .dev = { | ||
164 | .platform_data = &m48t59_data, | ||
165 | }, | ||
166 | }; | ||
299 | 167 | ||
300 | #ifndef CONFIG_SUN4 | ||
301 | static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) | 168 | static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) |
302 | { | 169 | { |
303 | struct device_node *dp = op->node; | 170 | struct device_node *dp = op->node; |
@@ -306,38 +173,26 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id | |||
306 | if (!model) | 173 | if (!model) |
307 | return -ENODEV; | 174 | return -ENODEV; |
308 | 175 | ||
176 | m48t59_rtc.resource = &op->resource[0]; | ||
309 | if (!strcmp(model, "mk48t02")) { | 177 | if (!strcmp(model, "mk48t02")) { |
310 | sp_clock_typ = MSTK48T02; | ||
311 | |||
312 | /* Map the clock register io area read-only */ | 178 | /* Map the clock register io area read-only */ |
313 | mstk48t02_regs = of_ioremap(&op->resource[0], 0, | 179 | m48t59_data.ioaddr = of_ioremap(&op->resource[0], 0, |
314 | sizeof(struct mostek48t02), | 180 | 2048, "rtc-m48t59"); |
315 | "mk48t02"); | 181 | m48t59_data.type = M48T59RTC_TYPE_M48T02; |
316 | mstk48t08_regs = NULL; /* To catch weirdness */ | ||
317 | } else if (!strcmp(model, "mk48t08")) { | 182 | } else if (!strcmp(model, "mk48t08")) { |
318 | sp_clock_typ = MSTK48T08; | 183 | m48t59_data.ioaddr = of_ioremap(&op->resource[0], 0, |
319 | mstk48t08_regs = of_ioremap(&op->resource[0], 0, | 184 | 8192, "rtc-m48t59"); |
320 | sizeof(struct mostek48t08), | 185 | m48t59_data.type = M48T59RTC_TYPE_M48T08; |
321 | "mk48t08"); | ||
322 | |||
323 | mstk48t02_regs = &mstk48t08_regs->regs; | ||
324 | } else | 186 | } else |
325 | return -ENODEV; | 187 | return -ENODEV; |
326 | 188 | ||
327 | /* Report a low battery voltage condition. */ | 189 | if (platform_device_register(&m48t59_rtc) < 0) |
328 | if (has_low_battery()) | 190 | printk(KERN_ERR "Registering RTC device failed\n"); |
329 | printk(KERN_CRIT "NVRAM: Low battery voltage!\n"); | ||
330 | |||
331 | /* Kick start the clock if it is completely stopped. */ | ||
332 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) | ||
333 | kick_start_clock(); | ||
334 | |||
335 | mostek_set_system_time(); | ||
336 | 191 | ||
337 | return 0; | 192 | return 0; |
338 | } | 193 | } |
339 | 194 | ||
340 | static struct of_device_id clock_match[] = { | 195 | static struct of_device_id __initdata clock_match[] = { |
341 | { | 196 | { |
342 | .name = "eeprom", | 197 | .name = "eeprom", |
343 | }, | 198 | }, |
@@ -348,7 +203,7 @@ static struct of_platform_driver clock_driver = { | |||
348 | .match_table = clock_match, | 203 | .match_table = clock_match, |
349 | .probe = clock_probe, | 204 | .probe = clock_probe, |
350 | .driver = { | 205 | .driver = { |
351 | .name = "clock", | 206 | .name = "rtc", |
352 | }, | 207 | }, |
353 | }; | 208 | }; |
354 | 209 | ||
@@ -364,7 +219,6 @@ static int __init clock_init(void) | |||
364 | * need to see the clock registers. | 219 | * need to see the clock registers. |
365 | */ | 220 | */ |
366 | fs_initcall(clock_init); | 221 | fs_initcall(clock_init); |
367 | #endif /* !CONFIG_SUN4 */ | ||
368 | 222 | ||
369 | static void __init sbus_time_init(void) | 223 | static void __init sbus_time_init(void) |
370 | { | 224 | { |
@@ -372,51 +226,8 @@ static void __init sbus_time_init(void) | |||
372 | BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); | 226 | BTFIXUPSET_CALL(bus_do_settimeofday, sbus_do_settimeofday, BTFIXUPCALL_NORM); |
373 | btfixup(); | 227 | btfixup(); |
374 | 228 | ||
375 | if (ARCH_SUN4) | ||
376 | sun4_clock_probe(); | ||
377 | |||
378 | sparc_init_timers(timer_interrupt); | 229 | sparc_init_timers(timer_interrupt); |
379 | 230 | ||
380 | #ifdef CONFIG_SUN4 | ||
381 | if(idprom->id_machtype == (SM_SUN4 | SM_4_330)) { | ||
382 | mostek_set_system_time(); | ||
383 | } else if(idprom->id_machtype == (SM_SUN4 | SM_4_260) ) { | ||
384 | /* initialise the intersil on sun4 */ | ||
385 | unsigned int year, mon, day, hour, min, sec; | ||
386 | int temp; | ||
387 | struct intersil *iregs; | ||
388 | |||
389 | iregs=intersil_clock; | ||
390 | if(!iregs) { | ||
391 | prom_printf("Something wrong, clock regs not mapped yet.\n"); | ||
392 | prom_halt(); | ||
393 | } | ||
394 | |||
395 | intersil_intr(intersil_clock,INTERSIL_INT_100HZ); | ||
396 | disable_pil_irq(10); | ||
397 | intersil_stop(iregs); | ||
398 | intersil_read_intr(intersil_clock, temp); | ||
399 | |||
400 | temp = iregs->clk.int_csec; | ||
401 | |||
402 | sec = iregs->clk.int_sec; | ||
403 | min = iregs->clk.int_min; | ||
404 | hour = iregs->clk.int_hour; | ||
405 | day = iregs->clk.int_day; | ||
406 | mon = iregs->clk.int_month; | ||
407 | year = MSTK_CVT_YEAR(iregs->clk.int_year); | ||
408 | |||
409 | enable_pil_irq(10); | ||
410 | intersil_start(iregs); | ||
411 | |||
412 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | ||
413 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | ||
414 | set_normalized_timespec(&wall_to_monotonic, | ||
415 | -xtime.tv_sec, -xtime.tv_nsec); | ||
416 | printk("%u/%u/%u %u:%u:%u\n",day,mon,year,hour,min,sec); | ||
417 | } | ||
418 | #endif | ||
419 | |||
420 | /* Now that OBP ticker has been silenced, it is safe to enable IRQ. */ | 231 | /* Now that OBP ticker has been silenced, it is safe to enable IRQ. */ |
421 | local_irq_enable(); | 232 | local_irq_enable(); |
422 | } | 233 | } |
@@ -522,80 +333,15 @@ static int sbus_do_settimeofday(struct timespec *tv) | |||
522 | return 0; | 333 | return 0; |
523 | } | 334 | } |
524 | 335 | ||
525 | /* | 336 | static int set_rtc_mmss(unsigned long secs) |
526 | * BUG: This routine does not handle hour overflow properly; it just | ||
527 | * sets the minutes. Usually you won't notice until after reboot! | ||
528 | */ | ||
529 | static int set_rtc_mmss(unsigned long nowtime) | ||
530 | { | 337 | { |
531 | int real_seconds, real_minutes, mostek_minutes; | 338 | struct rtc_device *rtc = rtc_class_open("rtc0"); |
532 | struct mostek48t02 *regs = (struct mostek48t02 *)mstk48t02_regs; | 339 | int err = -1; |
533 | unsigned long flags; | ||
534 | #ifdef CONFIG_SUN4 | ||
535 | struct intersil *iregs = intersil_clock; | ||
536 | int temp; | ||
537 | #endif | ||
538 | 340 | ||
539 | /* Not having a register set can lead to trouble. */ | 341 | if (rtc) { |
540 | if (!regs) { | 342 | err = rtc_set_mmss(rtc, secs); |
541 | #ifdef CONFIG_SUN4 | 343 | rtc_class_close(rtc); |
542 | if(!iregs) | ||
543 | return -1; | ||
544 | else { | ||
545 | temp = iregs->clk.int_csec; | ||
546 | |||
547 | mostek_minutes = iregs->clk.int_min; | ||
548 | |||
549 | real_seconds = nowtime % 60; | ||
550 | real_minutes = nowtime / 60; | ||
551 | if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1) | ||
552 | real_minutes += 30; /* correct for half hour time zone */ | ||
553 | real_minutes %= 60; | ||
554 | |||
555 | if (abs(real_minutes - mostek_minutes) < 30) { | ||
556 | intersil_stop(iregs); | ||
557 | iregs->clk.int_sec=real_seconds; | ||
558 | iregs->clk.int_min=real_minutes; | ||
559 | intersil_start(iregs); | ||
560 | } else { | ||
561 | printk(KERN_WARNING | ||
562 | "set_rtc_mmss: can't update from %d to %d\n", | ||
563 | mostek_minutes, real_minutes); | ||
564 | return -1; | ||
565 | } | ||
566 | |||
567 | return 0; | ||
568 | } | ||
569 | #endif | ||
570 | } | 344 | } |
571 | 345 | ||
572 | spin_lock_irqsave(&mostek_lock, flags); | 346 | return err; |
573 | /* Read the current RTC minutes. */ | ||
574 | regs->creg |= MSTK_CREG_READ; | ||
575 | mostek_minutes = MSTK_REG_MIN(regs); | ||
576 | regs->creg &= ~MSTK_CREG_READ; | ||
577 | |||
578 | /* | ||
579 | * since we're only adjusting minutes and seconds, | ||
580 | * don't interfere with hour overflow. This avoids | ||
581 | * messing with unknown time zones but requires your | ||
582 | * RTC not to be off by more than 15 minutes | ||
583 | */ | ||
584 | real_seconds = nowtime % 60; | ||
585 | real_minutes = nowtime / 60; | ||
586 | if (((abs(real_minutes - mostek_minutes) + 15)/30) & 1) | ||
587 | real_minutes += 30; /* correct for half hour time zone */ | ||
588 | real_minutes %= 60; | ||
589 | |||
590 | if (abs(real_minutes - mostek_minutes) < 30) { | ||
591 | regs->creg |= MSTK_CREG_WRITE; | ||
592 | MSTK_SET_REG_SEC(regs,real_seconds); | ||
593 | MSTK_SET_REG_MIN(regs,real_minutes); | ||
594 | regs->creg &= ~MSTK_CREG_WRITE; | ||
595 | spin_unlock_irqrestore(&mostek_lock, flags); | ||
596 | return 0; | ||
597 | } else { | ||
598 | spin_unlock_irqrestore(&mostek_lock, flags); | ||
599 | return -1; | ||
600 | } | ||
601 | } | 347 | } |
diff --git a/arch/sparc/kernel/traps.c b/arch/sparc/kernel/traps.c index 5d45d5fd8c99..2b7d50659036 100644 --- a/arch/sparc/kernel/traps.c +++ b/arch/sparc/kernel/traps.c | |||
@@ -43,23 +43,6 @@ void syscall_trace_exit(struct pt_regs *regs) | |||
43 | { | 43 | { |
44 | } | 44 | } |
45 | 45 | ||
46 | void sun4m_nmi(struct pt_regs *regs) | ||
47 | { | ||
48 | unsigned long afsr, afar; | ||
49 | |||
50 | printk("Aieee: sun4m NMI received!\n"); | ||
51 | /* XXX HyperSparc hack XXX */ | ||
52 | __asm__ __volatile__("mov 0x500, %%g1\n\t" | ||
53 | "lda [%%g1] 0x4, %0\n\t" | ||
54 | "mov 0x600, %%g1\n\t" | ||
55 | "lda [%%g1] 0x4, %1\n\t" : | ||
56 | "=r" (afsr), "=r" (afar)); | ||
57 | printk("afsr=%08lx afar=%08lx\n", afsr, afar); | ||
58 | printk("you lose buddy boy...\n"); | ||
59 | show_regs(regs); | ||
60 | prom_halt(); | ||
61 | } | ||
62 | |||
63 | void sun4d_nmi(struct pt_regs *regs) | 46 | void sun4d_nmi(struct pt_regs *regs) |
64 | { | 47 | { |
65 | printk("Aieee: sun4d NMI received!\n"); | 48 | printk("Aieee: sun4d NMI received!\n"); |
diff --git a/arch/sparc/mm/Makefile b/arch/sparc/mm/Makefile index 109c8b22cb38..ea88955d97ff 100644 --- a/arch/sparc/mm/Makefile +++ b/arch/sparc/mm/Makefile | |||
@@ -3,13 +3,8 @@ | |||
3 | 3 | ||
4 | EXTRA_AFLAGS := -ansi | 4 | EXTRA_AFLAGS := -ansi |
5 | 5 | ||
6 | obj-y := fault.o init.o loadmmu.o generic.o extable.o btfixup.o | 6 | obj-y := fault.o init.o loadmmu.o generic.o extable.o btfixup.o \ |
7 | 7 | srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o swift.o | |
8 | ifeq ($(CONFIG_SUN4),y) | ||
9 | obj-y += nosrmmu.o | ||
10 | else | ||
11 | obj-y += srmmu.o iommu.o io-unit.o hypersparc.o viking.o tsunami.o swift.o | ||
12 | endif | ||
13 | 8 | ||
14 | ifdef CONFIG_HIGHMEM | 9 | ifdef CONFIG_HIGHMEM |
15 | obj-y += highmem.o | 10 | obj-y += highmem.o |
diff --git a/arch/sparc/mm/btfixup.c b/arch/sparc/mm/btfixup.c index a312d127d47a..5175ac2f4820 100644 --- a/arch/sparc/mm/btfixup.c +++ b/arch/sparc/mm/btfixup.c | |||
@@ -20,11 +20,7 @@ | |||
20 | 20 | ||
21 | extern char *srmmu_name; | 21 | extern char *srmmu_name; |
22 | static char version[] __initdata = "Boot time fixup v1.6. 4/Mar/98 Jakub Jelinek (jj@ultra.linux.cz). Patching kernel for "; | 22 | static char version[] __initdata = "Boot time fixup v1.6. 4/Mar/98 Jakub Jelinek (jj@ultra.linux.cz). Patching kernel for "; |
23 | #ifdef CONFIG_SUN4 | ||
24 | static char str_sun4c[] __initdata = "sun4\n"; | ||
25 | #else | ||
26 | static char str_sun4c[] __initdata = "sun4c\n"; | 23 | static char str_sun4c[] __initdata = "sun4c\n"; |
27 | #endif | ||
28 | static char str_srmmu[] __initdata = "srmmu[%s]/"; | 24 | static char str_srmmu[] __initdata = "srmmu[%s]/"; |
29 | static char str_iommu[] __initdata = "iommu\n"; | 25 | static char str_iommu[] __initdata = "iommu\n"; |
30 | static char str_iounit[] __initdata = "io-unit\n"; | 26 | static char str_iounit[] __initdata = "io-unit\n"; |
@@ -86,7 +82,7 @@ void __init btfixup(void) | |||
86 | if (!visited) { | 82 | if (!visited) { |
87 | visited++; | 83 | visited++; |
88 | printk(version); | 84 | printk(version); |
89 | if (ARCH_SUN4C_SUN4) | 85 | if (ARCH_SUN4C) |
90 | printk(str_sun4c); | 86 | printk(str_sun4c); |
91 | else { | 87 | else { |
92 | printk(str_srmmu, srmmu_name); | 88 | printk(str_srmmu, srmmu_name); |
diff --git a/arch/sparc/mm/fault.c b/arch/sparc/mm/fault.c index 3604c2e86709..a507e1174662 100644 --- a/arch/sparc/mm/fault.c +++ b/arch/sparc/mm/fault.c | |||
@@ -191,7 +191,7 @@ asmlinkage void do_sparc_fault(struct pt_regs *regs, int text_fault, int write, | |||
191 | * only copy the information from the master page table, | 191 | * only copy the information from the master page table, |
192 | * nothing more. | 192 | * nothing more. |
193 | */ | 193 | */ |
194 | if (!ARCH_SUN4C_SUN4 && address >= TASK_SIZE) | 194 | if (!ARCH_SUN4C && address >= TASK_SIZE) |
195 | goto vmalloc_fault; | 195 | goto vmalloc_fault; |
196 | 196 | ||
197 | info.si_code = SEGV_MAPERR; | 197 | info.si_code = SEGV_MAPERR; |
diff --git a/arch/sparc/mm/init.c b/arch/sparc/mm/init.c index e103f1bb3777..677c1e187a23 100644 --- a/arch/sparc/mm/init.c +++ b/arch/sparc/mm/init.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/highmem.h> | 23 | #include <linux/highmem.h> |
24 | #include <linux/bootmem.h> | 24 | #include <linux/bootmem.h> |
25 | #include <linux/pagemap.h> | 25 | #include <linux/pagemap.h> |
26 | #include <linux/poison.h> | ||
26 | 27 | ||
27 | #include <asm/system.h> | 28 | #include <asm/system.h> |
28 | #include <asm/vac-ops.h> | 29 | #include <asm/vac-ops.h> |
@@ -480,6 +481,7 @@ void free_initmem (void) | |||
480 | for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { | 481 | for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) { |
481 | struct page *p; | 482 | struct page *p; |
482 | 483 | ||
484 | memset((void *)addr, POISON_FREE_INITMEM, PAGE_SIZE); | ||
483 | p = virt_to_page(addr); | 485 | p = virt_to_page(addr); |
484 | 486 | ||
485 | ClearPageReserved(p); | 487 | ClearPageReserved(p); |
@@ -488,20 +490,26 @@ void free_initmem (void) | |||
488 | totalram_pages++; | 490 | totalram_pages++; |
489 | num_physpages++; | 491 | num_physpages++; |
490 | } | 492 | } |
491 | printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10); | 493 | printk(KERN_INFO "Freeing unused kernel memory: %dk freed\n", |
494 | (&__init_end - &__init_begin) >> 10); | ||
492 | } | 495 | } |
493 | 496 | ||
494 | #ifdef CONFIG_BLK_DEV_INITRD | 497 | #ifdef CONFIG_BLK_DEV_INITRD |
495 | void free_initrd_mem(unsigned long start, unsigned long end) | 498 | void free_initrd_mem(unsigned long start, unsigned long end) |
496 | { | 499 | { |
497 | if (start < end) | 500 | if (start < end) |
498 | printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10); | 501 | printk(KERN_INFO "Freeing initrd memory: %ldk freed\n", |
502 | (end - start) >> 10); | ||
499 | for (; start < end; start += PAGE_SIZE) { | 503 | for (; start < end; start += PAGE_SIZE) { |
500 | struct page *p = virt_to_page(start); | 504 | struct page *p; |
505 | |||
506 | memset((void *)start, POISON_FREE_INITMEM, PAGE_SIZE); | ||
507 | p = virt_to_page(start); | ||
501 | 508 | ||
502 | ClearPageReserved(p); | 509 | ClearPageReserved(p); |
503 | init_page_count(p); | 510 | init_page_count(p); |
504 | __free_page(p); | 511 | __free_page(p); |
512 | totalram_pages++; | ||
505 | num_physpages++; | 513 | num_physpages++; |
506 | } | 514 | } |
507 | } | 515 | } |
diff --git a/arch/sparc/mm/io-unit.c b/arch/sparc/mm/io-unit.c index f167835db3df..daadf5f88050 100644 --- a/arch/sparc/mm/io-unit.c +++ b/arch/sparc/mm/io-unit.c | |||
@@ -12,10 +12,11 @@ | |||
12 | #include <linux/highmem.h> /* pte_offset_map => kmap_atomic */ | 12 | #include <linux/highmem.h> /* pte_offset_map => kmap_atomic */ |
13 | #include <linux/bitops.h> | 13 | #include <linux/bitops.h> |
14 | #include <linux/scatterlist.h> | 14 | #include <linux/scatterlist.h> |
15 | #include <linux/of.h> | ||
16 | #include <linux/of_device.h> | ||
15 | 17 | ||
16 | #include <asm/pgalloc.h> | 18 | #include <asm/pgalloc.h> |
17 | #include <asm/pgtable.h> | 19 | #include <asm/pgtable.h> |
18 | #include <asm/sbus.h> | ||
19 | #include <asm/io.h> | 20 | #include <asm/io.h> |
20 | #include <asm/io-unit.h> | 21 | #include <asm/io-unit.h> |
21 | #include <asm/mxcc.h> | 22 | #include <asm/mxcc.h> |
@@ -34,13 +35,10 @@ | |||
34 | #define IOPERM (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID) | 35 | #define IOPERM (IOUPTE_CACHE | IOUPTE_WRITE | IOUPTE_VALID) |
35 | #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM) | 36 | #define MKIOPTE(phys) __iopte((((phys)>>4) & IOUPTE_PAGE) | IOPERM) |
36 | 37 | ||
37 | void __init | 38 | static void __init iounit_iommu_init(struct of_device *op) |
38 | iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus) | ||
39 | { | 39 | { |
40 | iopte_t *xpt, *xptend; | ||
41 | struct iounit_struct *iounit; | 40 | struct iounit_struct *iounit; |
42 | struct linux_prom_registers iommu_promregs[PROMREG_MAX]; | 41 | iopte_t *xpt, *xptend; |
43 | struct resource r; | ||
44 | 42 | ||
45 | iounit = kzalloc(sizeof(struct iounit_struct), GFP_ATOMIC); | 43 | iounit = kzalloc(sizeof(struct iounit_struct), GFP_ATOMIC); |
46 | if (!iounit) { | 44 | if (!iounit) { |
@@ -55,18 +53,13 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus) | |||
55 | iounit->rotor[1] = IOUNIT_BMAP2_START; | 53 | iounit->rotor[1] = IOUNIT_BMAP2_START; |
56 | iounit->rotor[2] = IOUNIT_BMAPM_START; | 54 | iounit->rotor[2] = IOUNIT_BMAPM_START; |
57 | 55 | ||
58 | xpt = NULL; | 56 | xpt = of_ioremap(&op->resource[2], 0, PAGE_SIZE * 16, "XPT"); |
59 | if(prom_getproperty(sbi_node, "reg", (void *) iommu_promregs, | 57 | if (!xpt) { |
60 | sizeof(iommu_promregs)) != -1) { | 58 | prom_printf("SUN4D: Cannot map External Page Table."); |
61 | prom_apply_generic_ranges(io_node, 0, iommu_promregs, 3); | 59 | prom_halt(); |
62 | memset(&r, 0, sizeof(r)); | ||
63 | r.flags = iommu_promregs[2].which_io; | ||
64 | r.start = iommu_promregs[2].phys_addr; | ||
65 | xpt = (iopte_t *) sbus_ioremap(&r, 0, PAGE_SIZE * 16, "XPT"); | ||
66 | } | 60 | } |
67 | if(!xpt) panic("Cannot map External Page Table."); | ||
68 | 61 | ||
69 | sbus->ofdev.dev.archdata.iommu = iounit; | 62 | op->dev.archdata.iommu = iounit; |
70 | iounit->page_table = xpt; | 63 | iounit->page_table = xpt; |
71 | spin_lock_init(&iounit->lock); | 64 | spin_lock_init(&iounit->lock); |
72 | 65 | ||
@@ -75,6 +68,25 @@ iounit_init(int sbi_node, int io_node, struct sbus_bus *sbus) | |||
75 | iopte_val(*xpt++) = 0; | 68 | iopte_val(*xpt++) = 0; |
76 | } | 69 | } |
77 | 70 | ||
71 | static int __init iounit_init(void) | ||
72 | { | ||
73 | extern void sun4d_init_sbi_irq(void); | ||
74 | struct device_node *dp; | ||
75 | |||
76 | for_each_node_by_name(dp, "sbi") { | ||
77 | struct of_device *op = of_find_device_by_node(dp); | ||
78 | |||
79 | iounit_iommu_init(op); | ||
80 | of_propagate_archdata(op); | ||
81 | } | ||
82 | |||
83 | sun4d_init_sbi_irq(); | ||
84 | |||
85 | return 0; | ||
86 | } | ||
87 | |||
88 | subsys_initcall(iounit_init); | ||
89 | |||
78 | /* One has to hold iounit->lock to call this */ | 90 | /* One has to hold iounit->lock to call this */ |
79 | static unsigned long iounit_get_area(struct iounit_struct *iounit, unsigned long vaddr, int size) | 91 | static unsigned long iounit_get_area(struct iounit_struct *iounit, unsigned long vaddr, int size) |
80 | { | 92 | { |
@@ -124,10 +136,10 @@ nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan); | |||
124 | return vaddr; | 136 | return vaddr; |
125 | } | 137 | } |
126 | 138 | ||
127 | static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus *sbus) | 139 | static __u32 iounit_get_scsi_one(struct device *dev, char *vaddr, unsigned long len) |
128 | { | 140 | { |
141 | struct iounit_struct *iounit = dev->archdata.iommu; | ||
129 | unsigned long ret, flags; | 142 | unsigned long ret, flags; |
130 | struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; | ||
131 | 143 | ||
132 | spin_lock_irqsave(&iounit->lock, flags); | 144 | spin_lock_irqsave(&iounit->lock, flags); |
133 | ret = iounit_get_area(iounit, (unsigned long)vaddr, len); | 145 | ret = iounit_get_area(iounit, (unsigned long)vaddr, len); |
@@ -135,10 +147,10 @@ static __u32 iounit_get_scsi_one(char *vaddr, unsigned long len, struct sbus_bus | |||
135 | return ret; | 147 | return ret; |
136 | } | 148 | } |
137 | 149 | ||
138 | static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) | 150 | static void iounit_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz) |
139 | { | 151 | { |
152 | struct iounit_struct *iounit = dev->archdata.iommu; | ||
140 | unsigned long flags; | 153 | unsigned long flags; |
141 | struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; | ||
142 | 154 | ||
143 | /* FIXME: Cache some resolved pages - often several sg entries are to the same page */ | 155 | /* FIXME: Cache some resolved pages - often several sg entries are to the same page */ |
144 | spin_lock_irqsave(&iounit->lock, flags); | 156 | spin_lock_irqsave(&iounit->lock, flags); |
@@ -151,10 +163,10 @@ static void iounit_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus | |||
151 | spin_unlock_irqrestore(&iounit->lock, flags); | 163 | spin_unlock_irqrestore(&iounit->lock, flags); |
152 | } | 164 | } |
153 | 165 | ||
154 | static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus) | 166 | static void iounit_release_scsi_one(struct device *dev, __u32 vaddr, unsigned long len) |
155 | { | 167 | { |
168 | struct iounit_struct *iounit = dev->archdata.iommu; | ||
156 | unsigned long flags; | 169 | unsigned long flags; |
157 | struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; | ||
158 | 170 | ||
159 | spin_lock_irqsave(&iounit->lock, flags); | 171 | spin_lock_irqsave(&iounit->lock, flags); |
160 | len = ((vaddr & ~PAGE_MASK) + len + (PAGE_SIZE-1)) >> PAGE_SHIFT; | 172 | len = ((vaddr & ~PAGE_MASK) + len + (PAGE_SIZE-1)) >> PAGE_SHIFT; |
@@ -165,11 +177,11 @@ static void iounit_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_ | |||
165 | spin_unlock_irqrestore(&iounit->lock, flags); | 177 | spin_unlock_irqrestore(&iounit->lock, flags); |
166 | } | 178 | } |
167 | 179 | ||
168 | static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) | 180 | static void iounit_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz) |
169 | { | 181 | { |
182 | struct iounit_struct *iounit = dev->archdata.iommu; | ||
170 | unsigned long flags; | 183 | unsigned long flags; |
171 | unsigned long vaddr, len; | 184 | unsigned long vaddr, len; |
172 | struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; | ||
173 | 185 | ||
174 | spin_lock_irqsave(&iounit->lock, flags); | 186 | spin_lock_irqsave(&iounit->lock, flags); |
175 | while (sz != 0) { | 187 | while (sz != 0) { |
@@ -185,12 +197,12 @@ static void iounit_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_ | |||
185 | } | 197 | } |
186 | 198 | ||
187 | #ifdef CONFIG_SBUS | 199 | #ifdef CONFIG_SBUS |
188 | static int iounit_map_dma_area(dma_addr_t *pba, unsigned long va, __u32 addr, int len) | 200 | static int iounit_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, __u32 addr, int len) |
189 | { | 201 | { |
202 | struct iounit_struct *iounit = dev->archdata.iommu; | ||
190 | unsigned long page, end; | 203 | unsigned long page, end; |
191 | pgprot_t dvma_prot; | 204 | pgprot_t dvma_prot; |
192 | iopte_t *iopte; | 205 | iopte_t *iopte; |
193 | struct sbus_bus *sbus; | ||
194 | 206 | ||
195 | *pba = addr; | 207 | *pba = addr; |
196 | 208 | ||
@@ -212,12 +224,8 @@ static int iounit_map_dma_area(dma_addr_t *pba, unsigned long va, __u32 addr, in | |||
212 | 224 | ||
213 | i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT); | 225 | i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT); |
214 | 226 | ||
215 | for_each_sbus(sbus) { | 227 | iopte = (iopte_t *)(iounit->page_table + i); |
216 | struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; | 228 | *iopte = MKIOPTE(__pa(page)); |
217 | |||
218 | iopte = (iopte_t *)(iounit->page_table + i); | ||
219 | *iopte = MKIOPTE(__pa(page)); | ||
220 | } | ||
221 | } | 229 | } |
222 | addr += PAGE_SIZE; | 230 | addr += PAGE_SIZE; |
223 | va += PAGE_SIZE; | 231 | va += PAGE_SIZE; |
@@ -228,23 +236,10 @@ static int iounit_map_dma_area(dma_addr_t *pba, unsigned long va, __u32 addr, in | |||
228 | return 0; | 236 | return 0; |
229 | } | 237 | } |
230 | 238 | ||
231 | static void iounit_unmap_dma_area(unsigned long addr, int len) | 239 | static void iounit_unmap_dma_area(struct device *dev, unsigned long addr, int len) |
232 | { | 240 | { |
233 | /* XXX Somebody please fill this in */ | 241 | /* XXX Somebody please fill this in */ |
234 | } | 242 | } |
235 | |||
236 | /* XXX We do not pass sbus device here, bad. */ | ||
237 | static struct page *iounit_translate_dvma(unsigned long addr) | ||
238 | { | ||
239 | struct sbus_bus *sbus = sbus_root; /* They are all the same */ | ||
240 | struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; | ||
241 | int i; | ||
242 | iopte_t *iopte; | ||
243 | |||
244 | i = ((addr - IOUNIT_DMA_BASE) >> PAGE_SHIFT); | ||
245 | iopte = (iopte_t *)(iounit->page_table + i); | ||
246 | return pfn_to_page(iopte_val(*iopte) >> (PAGE_SHIFT-4)); /* XXX sun4d guru, help */ | ||
247 | } | ||
248 | #endif | 243 | #endif |
249 | 244 | ||
250 | static char *iounit_lockarea(char *vaddr, unsigned long len) | 245 | static char *iounit_lockarea(char *vaddr, unsigned long len) |
@@ -271,54 +266,5 @@ void __init ld_mmu_iounit(void) | |||
271 | #ifdef CONFIG_SBUS | 266 | #ifdef CONFIG_SBUS |
272 | BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM); | 267 | BTFIXUPSET_CALL(mmu_map_dma_area, iounit_map_dma_area, BTFIXUPCALL_NORM); |
273 | BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM); | 268 | BTFIXUPSET_CALL(mmu_unmap_dma_area, iounit_unmap_dma_area, BTFIXUPCALL_NORM); |
274 | BTFIXUPSET_CALL(mmu_translate_dvma, iounit_translate_dvma, BTFIXUPCALL_NORM); | ||
275 | #endif | 269 | #endif |
276 | } | 270 | } |
277 | |||
278 | __u32 iounit_map_dma_init(struct sbus_bus *sbus, int size) | ||
279 | { | ||
280 | int i, j, k, npages; | ||
281 | unsigned long rotor, scan, limit; | ||
282 | unsigned long flags; | ||
283 | __u32 ret; | ||
284 | struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; | ||
285 | |||
286 | npages = (size + (PAGE_SIZE-1)) >> PAGE_SHIFT; | ||
287 | i = 0x0213; | ||
288 | spin_lock_irqsave(&iounit->lock, flags); | ||
289 | next: j = (i & 15); | ||
290 | rotor = iounit->rotor[j - 1]; | ||
291 | limit = iounit->limit[j]; | ||
292 | scan = rotor; | ||
293 | nexti: scan = find_next_zero_bit(iounit->bmap, limit, scan); | ||
294 | if (scan + npages > limit) { | ||
295 | if (limit != rotor) { | ||
296 | limit = rotor; | ||
297 | scan = iounit->limit[j - 1]; | ||
298 | goto nexti; | ||
299 | } | ||
300 | i >>= 4; | ||
301 | if (!(i & 15)) | ||
302 | panic("iounit_map_dma_init: Couldn't find free iopte slots for %d bytes\n", size); | ||
303 | goto next; | ||
304 | } | ||
305 | for (k = 1, scan++; k < npages; k++) | ||
306 | if (test_bit(scan++, iounit->bmap)) | ||
307 | goto nexti; | ||
308 | iounit->rotor[j - 1] = (scan < limit) ? scan : iounit->limit[j - 1]; | ||
309 | scan -= npages; | ||
310 | ret = IOUNIT_DMA_BASE + (scan << PAGE_SHIFT); | ||
311 | for (k = 0; k < npages; k++, scan++) | ||
312 | set_bit(scan, iounit->bmap); | ||
313 | spin_unlock_irqrestore(&iounit->lock, flags); | ||
314 | return ret; | ||
315 | } | ||
316 | |||
317 | __u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus) | ||
318 | { | ||
319 | int scan = (vaddr - IOUNIT_DMA_BASE) >> PAGE_SHIFT; | ||
320 | struct iounit_struct *iounit = sbus->ofdev.dev.archdata.iommu; | ||
321 | |||
322 | iounit->page_table[scan] = MKIOPTE(__pa(((unsigned long)addr) & PAGE_MASK)); | ||
323 | return vaddr + (((unsigned long)addr) & ~PAGE_MASK); | ||
324 | } | ||
diff --git a/arch/sparc/mm/iommu.c b/arch/sparc/mm/iommu.c index 4b934270f05e..e7a499e3aa3c 100644 --- a/arch/sparc/mm/iommu.c +++ b/arch/sparc/mm/iommu.c | |||
@@ -13,10 +13,11 @@ | |||
13 | #include <linux/slab.h> | 13 | #include <linux/slab.h> |
14 | #include <linux/highmem.h> /* pte_offset_map => kmap_atomic */ | 14 | #include <linux/highmem.h> /* pte_offset_map => kmap_atomic */ |
15 | #include <linux/scatterlist.h> | 15 | #include <linux/scatterlist.h> |
16 | #include <linux/of.h> | ||
17 | #include <linux/of_device.h> | ||
16 | 18 | ||
17 | #include <asm/pgalloc.h> | 19 | #include <asm/pgalloc.h> |
18 | #include <asm/pgtable.h> | 20 | #include <asm/pgtable.h> |
19 | #include <asm/sbus.h> | ||
20 | #include <asm/io.h> | 21 | #include <asm/io.h> |
21 | #include <asm/mxcc.h> | 22 | #include <asm/mxcc.h> |
22 | #include <asm/mbus.h> | 23 | #include <asm/mbus.h> |
@@ -55,30 +56,21 @@ static pgprot_t dvma_prot; /* Consistent mapping pte flags */ | |||
55 | #define IOPERM (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID) | 56 | #define IOPERM (IOPTE_CACHE | IOPTE_WRITE | IOPTE_VALID) |
56 | #define MKIOPTE(pfn, perm) (((((pfn)<<8) & IOPTE_PAGE) | (perm)) & ~IOPTE_WAZ) | 57 | #define MKIOPTE(pfn, perm) (((((pfn)<<8) & IOPTE_PAGE) | (perm)) & ~IOPTE_WAZ) |
57 | 58 | ||
58 | void __init | 59 | static void __init sbus_iommu_init(struct of_device *op) |
59 | iommu_init(int iommund, struct sbus_bus *sbus) | ||
60 | { | 60 | { |
61 | unsigned int impl, vers; | ||
62 | unsigned long tmp; | ||
63 | struct iommu_struct *iommu; | 61 | struct iommu_struct *iommu; |
64 | struct linux_prom_registers iommu_promregs[PROMREG_MAX]; | 62 | unsigned int impl, vers; |
65 | struct resource r; | ||
66 | unsigned long *bitmap; | 63 | unsigned long *bitmap; |
64 | unsigned long tmp; | ||
67 | 65 | ||
68 | iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC); | 66 | iommu = kmalloc(sizeof(struct iommu_struct), GFP_ATOMIC); |
69 | if (!iommu) { | 67 | if (!iommu) { |
70 | prom_printf("Unable to allocate iommu structure\n"); | 68 | prom_printf("Unable to allocate iommu structure\n"); |
71 | prom_halt(); | 69 | prom_halt(); |
72 | } | 70 | } |
73 | iommu->regs = NULL; | 71 | |
74 | if (prom_getproperty(iommund, "reg", (void *) iommu_promregs, | 72 | iommu->regs = of_ioremap(&op->resource[0], 0, PAGE_SIZE * 3, |
75 | sizeof(iommu_promregs)) != -1) { | 73 | "iommu_regs"); |
76 | memset(&r, 0, sizeof(r)); | ||
77 | r.flags = iommu_promregs[0].which_io; | ||
78 | r.start = iommu_promregs[0].phys_addr; | ||
79 | iommu->regs = (struct iommu_regs *) | ||
80 | sbus_ioremap(&r, 0, PAGE_SIZE * 3, "iommu_regs"); | ||
81 | } | ||
82 | if (!iommu->regs) { | 74 | if (!iommu->regs) { |
83 | prom_printf("Cannot map IOMMU registers\n"); | 75 | prom_printf("Cannot map IOMMU registers\n"); |
84 | prom_halt(); | 76 | prom_halt(); |
@@ -128,13 +120,29 @@ iommu_init(int iommund, struct sbus_bus *sbus) | |||
128 | else | 120 | else |
129 | iommu->usemap.num_colors = 1; | 121 | iommu->usemap.num_colors = 1; |
130 | 122 | ||
131 | printk("IOMMU: impl %d vers %d table 0x%p[%d B] map [%d b]\n", | 123 | printk(KERN_INFO "IOMMU: impl %d vers %d table 0x%p[%d B] map [%d b]\n", |
132 | impl, vers, iommu->page_table, | 124 | impl, vers, iommu->page_table, |
133 | (int)(IOMMU_NPTES*sizeof(iopte_t)), (int)IOMMU_NPTES); | 125 | (int)(IOMMU_NPTES*sizeof(iopte_t)), (int)IOMMU_NPTES); |
126 | |||
127 | op->dev.archdata.iommu = iommu; | ||
128 | } | ||
129 | |||
130 | static int __init iommu_init(void) | ||
131 | { | ||
132 | struct device_node *dp; | ||
133 | |||
134 | for_each_node_by_name(dp, "iommu") { | ||
135 | struct of_device *op = of_find_device_by_node(dp); | ||
136 | |||
137 | sbus_iommu_init(op); | ||
138 | of_propagate_archdata(op); | ||
139 | } | ||
134 | 140 | ||
135 | sbus->ofdev.dev.archdata.iommu = iommu; | 141 | return 0; |
136 | } | 142 | } |
137 | 143 | ||
144 | subsys_initcall(iommu_init); | ||
145 | |||
138 | /* This begs to be btfixup-ed by srmmu. */ | 146 | /* This begs to be btfixup-ed by srmmu. */ |
139 | /* Flush the iotlb entries to ram. */ | 147 | /* Flush the iotlb entries to ram. */ |
140 | /* This could be better if we didn't have to flush whole pages. */ | 148 | /* This could be better if we didn't have to flush whole pages. */ |
@@ -164,9 +172,9 @@ static void iommu_flush_iotlb(iopte_t *iopte, unsigned int niopte) | |||
164 | } | 172 | } |
165 | } | 173 | } |
166 | 174 | ||
167 | static u32 iommu_get_one(struct page *page, int npages, struct sbus_bus *sbus) | 175 | static u32 iommu_get_one(struct device *dev, struct page *page, int npages) |
168 | { | 176 | { |
169 | struct iommu_struct *iommu = sbus->ofdev.dev.archdata.iommu; | 177 | struct iommu_struct *iommu = dev->archdata.iommu; |
170 | int ioptex; | 178 | int ioptex; |
171 | iopte_t *iopte, *iopte0; | 179 | iopte_t *iopte, *iopte0; |
172 | unsigned int busa, busa0; | 180 | unsigned int busa, busa0; |
@@ -194,8 +202,7 @@ static u32 iommu_get_one(struct page *page, int npages, struct sbus_bus *sbus) | |||
194 | return busa0; | 202 | return busa0; |
195 | } | 203 | } |
196 | 204 | ||
197 | static u32 iommu_get_scsi_one(char *vaddr, unsigned int len, | 205 | static u32 iommu_get_scsi_one(struct device *dev, char *vaddr, unsigned int len) |
198 | struct sbus_bus *sbus) | ||
199 | { | 206 | { |
200 | unsigned long off; | 207 | unsigned long off; |
201 | int npages; | 208 | int npages; |
@@ -205,22 +212,22 @@ static u32 iommu_get_scsi_one(char *vaddr, unsigned int len, | |||
205 | off = (unsigned long)vaddr & ~PAGE_MASK; | 212 | off = (unsigned long)vaddr & ~PAGE_MASK; |
206 | npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT; | 213 | npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT; |
207 | page = virt_to_page((unsigned long)vaddr & PAGE_MASK); | 214 | page = virt_to_page((unsigned long)vaddr & PAGE_MASK); |
208 | busa = iommu_get_one(page, npages, sbus); | 215 | busa = iommu_get_one(dev, page, npages); |
209 | return busa + off; | 216 | return busa + off; |
210 | } | 217 | } |
211 | 218 | ||
212 | static __u32 iommu_get_scsi_one_noflush(char *vaddr, unsigned long len, struct sbus_bus *sbus) | 219 | static __u32 iommu_get_scsi_one_noflush(struct device *dev, char *vaddr, unsigned long len) |
213 | { | 220 | { |
214 | return iommu_get_scsi_one(vaddr, len, sbus); | 221 | return iommu_get_scsi_one(dev, vaddr, len); |
215 | } | 222 | } |
216 | 223 | ||
217 | static __u32 iommu_get_scsi_one_gflush(char *vaddr, unsigned long len, struct sbus_bus *sbus) | 224 | static __u32 iommu_get_scsi_one_gflush(struct device *dev, char *vaddr, unsigned long len) |
218 | { | 225 | { |
219 | flush_page_for_dma(0); | 226 | flush_page_for_dma(0); |
220 | return iommu_get_scsi_one(vaddr, len, sbus); | 227 | return iommu_get_scsi_one(dev, vaddr, len); |
221 | } | 228 | } |
222 | 229 | ||
223 | static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct sbus_bus *sbus) | 230 | static __u32 iommu_get_scsi_one_pflush(struct device *dev, char *vaddr, unsigned long len) |
224 | { | 231 | { |
225 | unsigned long page = ((unsigned long) vaddr) & PAGE_MASK; | 232 | unsigned long page = ((unsigned long) vaddr) & PAGE_MASK; |
226 | 233 | ||
@@ -228,23 +235,23 @@ static __u32 iommu_get_scsi_one_pflush(char *vaddr, unsigned long len, struct sb | |||
228 | flush_page_for_dma(page); | 235 | flush_page_for_dma(page); |
229 | page += PAGE_SIZE; | 236 | page += PAGE_SIZE; |
230 | } | 237 | } |
231 | return iommu_get_scsi_one(vaddr, len, sbus); | 238 | return iommu_get_scsi_one(dev, vaddr, len); |
232 | } | 239 | } |
233 | 240 | ||
234 | static void iommu_get_scsi_sgl_noflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) | 241 | static void iommu_get_scsi_sgl_noflush(struct device *dev, struct scatterlist *sg, int sz) |
235 | { | 242 | { |
236 | int n; | 243 | int n; |
237 | 244 | ||
238 | while (sz != 0) { | 245 | while (sz != 0) { |
239 | --sz; | 246 | --sz; |
240 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; | 247 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; |
241 | sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset; | 248 | sg->dvma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; |
242 | sg->dvma_length = (__u32) sg->length; | 249 | sg->dvma_length = (__u32) sg->length; |
243 | sg = sg_next(sg); | 250 | sg = sg_next(sg); |
244 | } | 251 | } |
245 | } | 252 | } |
246 | 253 | ||
247 | static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) | 254 | static void iommu_get_scsi_sgl_gflush(struct device *dev, struct scatterlist *sg, int sz) |
248 | { | 255 | { |
249 | int n; | 256 | int n; |
250 | 257 | ||
@@ -252,13 +259,13 @@ static void iommu_get_scsi_sgl_gflush(struct scatterlist *sg, int sz, struct sbu | |||
252 | while (sz != 0) { | 259 | while (sz != 0) { |
253 | --sz; | 260 | --sz; |
254 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; | 261 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; |
255 | sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset; | 262 | sg->dvma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; |
256 | sg->dvma_length = (__u32) sg->length; | 263 | sg->dvma_length = (__u32) sg->length; |
257 | sg = sg_next(sg); | 264 | sg = sg_next(sg); |
258 | } | 265 | } |
259 | } | 266 | } |
260 | 267 | ||
261 | static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbus_bus *sbus) | 268 | static void iommu_get_scsi_sgl_pflush(struct device *dev, struct scatterlist *sg, int sz) |
262 | { | 269 | { |
263 | unsigned long page, oldpage = 0; | 270 | unsigned long page, oldpage = 0; |
264 | int n, i; | 271 | int n, i; |
@@ -283,15 +290,15 @@ static void iommu_get_scsi_sgl_pflush(struct scatterlist *sg, int sz, struct sbu | |||
283 | } | 290 | } |
284 | } | 291 | } |
285 | 292 | ||
286 | sg->dvma_address = iommu_get_one(sg_page(sg), n, sbus) + sg->offset; | 293 | sg->dvma_address = iommu_get_one(dev, sg_page(sg), n) + sg->offset; |
287 | sg->dvma_length = (__u32) sg->length; | 294 | sg->dvma_length = (__u32) sg->length; |
288 | sg = sg_next(sg); | 295 | sg = sg_next(sg); |
289 | } | 296 | } |
290 | } | 297 | } |
291 | 298 | ||
292 | static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus) | 299 | static void iommu_release_one(struct device *dev, u32 busa, int npages) |
293 | { | 300 | { |
294 | struct iommu_struct *iommu = sbus->ofdev.dev.archdata.iommu; | 301 | struct iommu_struct *iommu = dev->archdata.iommu; |
295 | int ioptex; | 302 | int ioptex; |
296 | int i; | 303 | int i; |
297 | 304 | ||
@@ -305,17 +312,17 @@ static void iommu_release_one(u32 busa, int npages, struct sbus_bus *sbus) | |||
305 | bit_map_clear(&iommu->usemap, ioptex, npages); | 312 | bit_map_clear(&iommu->usemap, ioptex, npages); |
306 | } | 313 | } |
307 | 314 | ||
308 | static void iommu_release_scsi_one(__u32 vaddr, unsigned long len, struct sbus_bus *sbus) | 315 | static void iommu_release_scsi_one(struct device *dev, __u32 vaddr, unsigned long len) |
309 | { | 316 | { |
310 | unsigned long off; | 317 | unsigned long off; |
311 | int npages; | 318 | int npages; |
312 | 319 | ||
313 | off = vaddr & ~PAGE_MASK; | 320 | off = vaddr & ~PAGE_MASK; |
314 | npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT; | 321 | npages = (off + len + PAGE_SIZE-1) >> PAGE_SHIFT; |
315 | iommu_release_one(vaddr & PAGE_MASK, npages, sbus); | 322 | iommu_release_one(dev, vaddr & PAGE_MASK, npages); |
316 | } | 323 | } |
317 | 324 | ||
318 | static void iommu_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) | 325 | static void iommu_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz) |
319 | { | 326 | { |
320 | int n; | 327 | int n; |
321 | 328 | ||
@@ -323,18 +330,18 @@ static void iommu_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_b | |||
323 | --sz; | 330 | --sz; |
324 | 331 | ||
325 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; | 332 | n = (sg->length + sg->offset + PAGE_SIZE-1) >> PAGE_SHIFT; |
326 | iommu_release_one(sg->dvma_address & PAGE_MASK, n, sbus); | 333 | iommu_release_one(dev, sg->dvma_address & PAGE_MASK, n); |
327 | sg->dvma_address = 0x21212121; | 334 | sg->dvma_address = 0x21212121; |
328 | sg = sg_next(sg); | 335 | sg = sg_next(sg); |
329 | } | 336 | } |
330 | } | 337 | } |
331 | 338 | ||
332 | #ifdef CONFIG_SBUS | 339 | #ifdef CONFIG_SBUS |
333 | static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va, | 340 | static int iommu_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, |
334 | unsigned long addr, int len) | 341 | unsigned long addr, int len) |
335 | { | 342 | { |
343 | struct iommu_struct *iommu = dev->archdata.iommu; | ||
336 | unsigned long page, end; | 344 | unsigned long page, end; |
337 | struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu; | ||
338 | iopte_t *iopte = iommu->page_table; | 345 | iopte_t *iopte = iommu->page_table; |
339 | iopte_t *first; | 346 | iopte_t *first; |
340 | int ioptex; | 347 | int ioptex; |
@@ -397,9 +404,9 @@ static int iommu_map_dma_area(dma_addr_t *pba, unsigned long va, | |||
397 | return 0; | 404 | return 0; |
398 | } | 405 | } |
399 | 406 | ||
400 | static void iommu_unmap_dma_area(unsigned long busa, int len) | 407 | static void iommu_unmap_dma_area(struct device *dev, unsigned long busa, int len) |
401 | { | 408 | { |
402 | struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu; | 409 | struct iommu_struct *iommu = dev->archdata.iommu; |
403 | iopte_t *iopte = iommu->page_table; | 410 | iopte_t *iopte = iommu->page_table; |
404 | unsigned long end; | 411 | unsigned long end; |
405 | int ioptex = (busa - iommu->start) >> PAGE_SHIFT; | 412 | int ioptex = (busa - iommu->start) >> PAGE_SHIFT; |
@@ -417,15 +424,6 @@ static void iommu_unmap_dma_area(unsigned long busa, int len) | |||
417 | iommu_invalidate(iommu->regs); | 424 | iommu_invalidate(iommu->regs); |
418 | bit_map_clear(&iommu->usemap, ioptex, len >> PAGE_SHIFT); | 425 | bit_map_clear(&iommu->usemap, ioptex, len >> PAGE_SHIFT); |
419 | } | 426 | } |
420 | |||
421 | static struct page *iommu_translate_dvma(unsigned long busa) | ||
422 | { | ||
423 | struct iommu_struct *iommu = sbus_root->ofdev.dev.archdata.iommu; | ||
424 | iopte_t *iopte = iommu->page_table; | ||
425 | |||
426 | iopte += ((busa - iommu->start) >> PAGE_SHIFT); | ||
427 | return pfn_to_page((iopte_val(*iopte) & IOPTE_PAGE) >> (PAGE_SHIFT-4)); | ||
428 | } | ||
429 | #endif | 427 | #endif |
430 | 428 | ||
431 | static char *iommu_lockarea(char *vaddr, unsigned long len) | 429 | static char *iommu_lockarea(char *vaddr, unsigned long len) |
@@ -461,7 +459,6 @@ void __init ld_mmu_iommu(void) | |||
461 | #ifdef CONFIG_SBUS | 459 | #ifdef CONFIG_SBUS |
462 | BTFIXUPSET_CALL(mmu_map_dma_area, iommu_map_dma_area, BTFIXUPCALL_NORM); | 460 | BTFIXUPSET_CALL(mmu_map_dma_area, iommu_map_dma_area, BTFIXUPCALL_NORM); |
463 | BTFIXUPSET_CALL(mmu_unmap_dma_area, iommu_unmap_dma_area, BTFIXUPCALL_NORM); | 461 | BTFIXUPSET_CALL(mmu_unmap_dma_area, iommu_unmap_dma_area, BTFIXUPCALL_NORM); |
464 | BTFIXUPSET_CALL(mmu_translate_dvma, iommu_translate_dvma, BTFIXUPCALL_NORM); | ||
465 | #endif | 462 | #endif |
466 | 463 | ||
467 | if (viking_mxcc_present || srmmu_modtype == HyperSparc) { | 464 | if (viking_mxcc_present || srmmu_modtype == HyperSparc) { |
diff --git a/arch/sparc/mm/nosrmmu.c b/arch/sparc/mm/nosrmmu.c deleted file mode 100644 index 3701f70fc30a..000000000000 --- a/arch/sparc/mm/nosrmmu.c +++ /dev/null | |||
@@ -1,59 +0,0 @@ | |||
1 | /* | ||
2 | * nosrmmu.c: This file is a bunch of dummies for sun4 compiles, | ||
3 | * so that it does not need srmmu and avoid ifdefs. | ||
4 | * | ||
5 | * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | ||
6 | */ | ||
7 | |||
8 | #include <linux/kernel.h> | ||
9 | #include <linux/mm.h> | ||
10 | #include <linux/init.h> | ||
11 | #include <asm/mbus.h> | ||
12 | #include <asm/sbus.h> | ||
13 | |||
14 | static char shouldnothappen[] __initdata = "SUN4 kernel can only run on SUN4\n"; | ||
15 | |||
16 | enum mbus_module srmmu_modtype; | ||
17 | void *srmmu_nocache_pool; | ||
18 | |||
19 | int vac_cache_size = 0; | ||
20 | |||
21 | static void __init should_not_happen(void) | ||
22 | { | ||
23 | prom_printf(shouldnothappen); | ||
24 | prom_halt(); | ||
25 | } | ||
26 | |||
27 | void __init srmmu_frob_mem_map(unsigned long start_mem) | ||
28 | { | ||
29 | should_not_happen(); | ||
30 | } | ||
31 | |||
32 | unsigned long __init srmmu_paging_init(unsigned long start_mem, unsigned long end_mem) | ||
33 | { | ||
34 | should_not_happen(); | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | void __init ld_mmu_srmmu(void) | ||
39 | { | ||
40 | should_not_happen(); | ||
41 | } | ||
42 | |||
43 | void srmmu_mapioaddr(unsigned long physaddr, unsigned long virt_addr, int bus_type, int rdonly) | ||
44 | { | ||
45 | } | ||
46 | |||
47 | void srmmu_unmapioaddr(unsigned long virt_addr) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | __u32 iounit_map_dma_init(struct sbus_bus *sbus, int size) | ||
52 | { | ||
53 | return 0; | ||
54 | } | ||
55 | |||
56 | __u32 iounit_map_dma_page(__u32 vaddr, void *addr, struct sbus_bus *sbus) | ||
57 | { | ||
58 | return 0; | ||
59 | } | ||
diff --git a/arch/sparc/mm/srmmu.c b/arch/sparc/mm/srmmu.c index ee30462598fc..6a5d7cabc044 100644 --- a/arch/sparc/mm/srmmu.c +++ b/arch/sparc/mm/srmmu.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <asm/mbus.h> | 31 | #include <asm/mbus.h> |
32 | #include <asm/cache.h> | 32 | #include <asm/cache.h> |
33 | #include <asm/oplib.h> | 33 | #include <asm/oplib.h> |
34 | #include <asm/sbus.h> | ||
35 | #include <asm/asi.h> | 34 | #include <asm/asi.h> |
36 | #include <asm/msi.h> | 35 | #include <asm/msi.h> |
37 | #include <asm/mmu_context.h> | 36 | #include <asm/mmu_context.h> |
diff --git a/arch/sparc/mm/sun4c.c b/arch/sparc/mm/sun4c.c index d1782f6368be..fe65aeeb3947 100644 --- a/arch/sparc/mm/sun4c.c +++ b/arch/sparc/mm/sun4c.c | |||
@@ -31,7 +31,6 @@ | |||
31 | #include <asm/oplib.h> | 31 | #include <asm/oplib.h> |
32 | #include <asm/openprom.h> | 32 | #include <asm/openprom.h> |
33 | #include <asm/mmu_context.h> | 33 | #include <asm/mmu_context.h> |
34 | #include <asm/sun4paddr.h> | ||
35 | #include <asm/highmem.h> | 34 | #include <asm/highmem.h> |
36 | #include <asm/btfixup.h> | 35 | #include <asm/btfixup.h> |
37 | #include <asm/cacheflush.h> | 36 | #include <asm/cacheflush.h> |
@@ -52,15 +51,11 @@ extern int num_segmaps, num_contexts; | |||
52 | 51 | ||
53 | extern unsigned long page_kernel; | 52 | extern unsigned long page_kernel; |
54 | 53 | ||
55 | #ifdef CONFIG_SUN4 | ||
56 | #define SUN4C_VAC_SIZE sun4c_vacinfo.num_bytes | ||
57 | #else | ||
58 | /* That's it, we prom_halt() on sun4c if the cache size is something other than 65536. | 54 | /* That's it, we prom_halt() on sun4c if the cache size is something other than 65536. |
59 | * So let's save some cycles and just use that everywhere except for that bootup | 55 | * So let's save some cycles and just use that everywhere except for that bootup |
60 | * sanity check. | 56 | * sanity check. |
61 | */ | 57 | */ |
62 | #define SUN4C_VAC_SIZE 65536 | 58 | #define SUN4C_VAC_SIZE 65536 |
63 | #endif | ||
64 | 59 | ||
65 | #define SUN4C_KERNEL_BUCKETS 32 | 60 | #define SUN4C_KERNEL_BUCKETS 32 |
66 | 61 | ||
@@ -285,75 +280,32 @@ void __init sun4c_probe_vac(void) | |||
285 | { | 280 | { |
286 | sun4c_disable_vac(); | 281 | sun4c_disable_vac(); |
287 | 282 | ||
288 | if (ARCH_SUN4) { | 283 | if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || |
289 | switch (idprom->id_machtype) { | 284 | (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { |
290 | 285 | /* PROM on SS1 lacks this info, to be super safe we | |
291 | case (SM_SUN4|SM_4_110): | 286 | * hard code it here since this arch is cast in stone. |
292 | sun4c_vacinfo.type = VAC_NONE; | 287 | */ |
293 | sun4c_vacinfo.num_bytes = 0; | 288 | sun4c_vacinfo.num_bytes = 65536; |
294 | sun4c_vacinfo.linesize = 0; | 289 | sun4c_vacinfo.linesize = 16; |
295 | sun4c_vacinfo.do_hwflushes = 0; | ||
296 | prom_printf("No VAC. Get some bucks and buy a real computer."); | ||
297 | prom_halt(); | ||
298 | break; | ||
299 | |||
300 | case (SM_SUN4|SM_4_260): | ||
301 | sun4c_vacinfo.type = VAC_WRITE_BACK; | ||
302 | sun4c_vacinfo.num_bytes = 128 * 1024; | ||
303 | sun4c_vacinfo.linesize = 16; | ||
304 | sun4c_vacinfo.do_hwflushes = 0; | ||
305 | break; | ||
306 | |||
307 | case (SM_SUN4|SM_4_330): | ||
308 | sun4c_vacinfo.type = VAC_WRITE_THROUGH; | ||
309 | sun4c_vacinfo.num_bytes = 128 * 1024; | ||
310 | sun4c_vacinfo.linesize = 16; | ||
311 | sun4c_vacinfo.do_hwflushes = 0; | ||
312 | break; | ||
313 | |||
314 | case (SM_SUN4|SM_4_470): | ||
315 | sun4c_vacinfo.type = VAC_WRITE_BACK; | ||
316 | sun4c_vacinfo.num_bytes = 128 * 1024; | ||
317 | sun4c_vacinfo.linesize = 32; | ||
318 | sun4c_vacinfo.do_hwflushes = 0; | ||
319 | break; | ||
320 | |||
321 | default: | ||
322 | prom_printf("Cannot initialize VAC - weird sun4 model idprom->id_machtype = %d", idprom->id_machtype); | ||
323 | prom_halt(); | ||
324 | }; | ||
325 | } else { | 290 | } else { |
326 | sun4c_vacinfo.type = VAC_WRITE_THROUGH; | 291 | sun4c_vacinfo.num_bytes = |
292 | prom_getintdefault(prom_root_node, "vac-size", 65536); | ||
293 | sun4c_vacinfo.linesize = | ||
294 | prom_getintdefault(prom_root_node, "vac-linesize", 16); | ||
295 | } | ||
296 | sun4c_vacinfo.do_hwflushes = | ||
297 | prom_getintdefault(prom_root_node, "vac-hwflush", 0); | ||
327 | 298 | ||
328 | if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || | 299 | if (sun4c_vacinfo.do_hwflushes == 0) |
329 | (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { | ||
330 | /* PROM on SS1 lacks this info, to be super safe we | ||
331 | * hard code it here since this arch is cast in stone. | ||
332 | */ | ||
333 | sun4c_vacinfo.num_bytes = 65536; | ||
334 | sun4c_vacinfo.linesize = 16; | ||
335 | } else { | ||
336 | sun4c_vacinfo.num_bytes = | ||
337 | prom_getintdefault(prom_root_node, "vac-size", 65536); | ||
338 | sun4c_vacinfo.linesize = | ||
339 | prom_getintdefault(prom_root_node, "vac-linesize", 16); | ||
340 | } | ||
341 | sun4c_vacinfo.do_hwflushes = | 300 | sun4c_vacinfo.do_hwflushes = |
342 | prom_getintdefault(prom_root_node, "vac-hwflush", 0); | 301 | prom_getintdefault(prom_root_node, "vac_hwflush", 0); |
343 | |||
344 | if (sun4c_vacinfo.do_hwflushes == 0) | ||
345 | sun4c_vacinfo.do_hwflushes = | ||
346 | prom_getintdefault(prom_root_node, "vac_hwflush", 0); | ||
347 | 302 | ||
348 | if (sun4c_vacinfo.num_bytes != 65536) { | 303 | if (sun4c_vacinfo.num_bytes != 65536) { |
349 | prom_printf("WEIRD Sun4C VAC cache size, " | 304 | prom_printf("WEIRD Sun4C VAC cache size, " |
350 | "tell sparclinux@vger.kernel.org"); | 305 | "tell sparclinux@vger.kernel.org"); |
351 | prom_halt(); | 306 | prom_halt(); |
352 | } | ||
353 | } | 307 | } |
354 | 308 | ||
355 | sun4c_vacinfo.num_lines = | ||
356 | (sun4c_vacinfo.num_bytes / sun4c_vacinfo.linesize); | ||
357 | switch (sun4c_vacinfo.linesize) { | 309 | switch (sun4c_vacinfo.linesize) { |
358 | case 16: | 310 | case 16: |
359 | sun4c_vacinfo.log2lsize = 4; | 311 | sun4c_vacinfo.log2lsize = 4; |
@@ -447,49 +399,18 @@ static void __init patch_kernel_fault_handler(void) | |||
447 | 399 | ||
448 | static void __init sun4c_probe_mmu(void) | 400 | static void __init sun4c_probe_mmu(void) |
449 | { | 401 | { |
450 | if (ARCH_SUN4) { | 402 | if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || |
451 | switch (idprom->id_machtype) { | 403 | (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { |
452 | case (SM_SUN4|SM_4_110): | 404 | /* Hardcode these just to be safe, PROM on SS1 does |
453 | prom_printf("No support for 4100 yet\n"); | 405 | * not have this info available in the root node. |
454 | prom_halt(); | 406 | */ |
455 | num_segmaps = 256; | 407 | num_segmaps = 128; |
456 | num_contexts = 8; | 408 | num_contexts = 8; |
457 | break; | ||
458 | |||
459 | case (SM_SUN4|SM_4_260): | ||
460 | /* should be 512 segmaps. when it get fixed */ | ||
461 | num_segmaps = 256; | ||
462 | num_contexts = 16; | ||
463 | break; | ||
464 | |||
465 | case (SM_SUN4|SM_4_330): | ||
466 | num_segmaps = 256; | ||
467 | num_contexts = 16; | ||
468 | break; | ||
469 | |||
470 | case (SM_SUN4|SM_4_470): | ||
471 | /* should be 1024 segmaps. when it get fixed */ | ||
472 | num_segmaps = 256; | ||
473 | num_contexts = 64; | ||
474 | break; | ||
475 | default: | ||
476 | prom_printf("Invalid SUN4 model\n"); | ||
477 | prom_halt(); | ||
478 | }; | ||
479 | } else { | 409 | } else { |
480 | if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS1)) || | 410 | num_segmaps = |
481 | (idprom->id_machtype == (SM_SUN4C | SM_4C_SS1PLUS))) { | 411 | prom_getintdefault(prom_root_node, "mmu-npmg", 128); |
482 | /* Hardcode these just to be safe, PROM on SS1 does | 412 | num_contexts = |
483 | * not have this info available in the root node. | 413 | prom_getintdefault(prom_root_node, "mmu-nctx", 0x8); |
484 | */ | ||
485 | num_segmaps = 128; | ||
486 | num_contexts = 8; | ||
487 | } else { | ||
488 | num_segmaps = | ||
489 | prom_getintdefault(prom_root_node, "mmu-npmg", 128); | ||
490 | num_contexts = | ||
491 | prom_getintdefault(prom_root_node, "mmu-nctx", 0x8); | ||
492 | } | ||
493 | } | 414 | } |
494 | patch_kernel_fault_handler(); | 415 | patch_kernel_fault_handler(); |
495 | } | 416 | } |
@@ -501,18 +422,14 @@ void __init sun4c_probe_memerr_reg(void) | |||
501 | int node; | 422 | int node; |
502 | struct linux_prom_registers regs[1]; | 423 | struct linux_prom_registers regs[1]; |
503 | 424 | ||
504 | if (ARCH_SUN4) { | 425 | node = prom_getchild(prom_root_node); |
505 | sun4c_memerr_reg = ioremap(sun4_memreg_physaddr, PAGE_SIZE); | 426 | node = prom_searchsiblings(prom_root_node, "memory-error"); |
506 | } else { | 427 | if (!node) |
507 | node = prom_getchild(prom_root_node); | 428 | return; |
508 | node = prom_searchsiblings(prom_root_node, "memory-error"); | 429 | if (prom_getproperty(node, "reg", (char *)regs, sizeof(regs)) <= 0) |
509 | if (!node) | 430 | return; |
510 | return; | 431 | /* hmm I think regs[0].which_io is zero here anyways */ |
511 | if (prom_getproperty(node, "reg", (char *)regs, sizeof(regs)) <= 0) | 432 | sun4c_memerr_reg = ioremap(regs[0].phys_addr, regs[0].reg_size); |
512 | return; | ||
513 | /* hmm I think regs[0].which_io is zero here anyways */ | ||
514 | sun4c_memerr_reg = ioremap(regs[0].phys_addr, regs[0].reg_size); | ||
515 | } | ||
516 | } | 433 | } |
517 | 434 | ||
518 | static inline void sun4c_init_ss2_cache_bug(void) | 435 | static inline void sun4c_init_ss2_cache_bug(void) |
@@ -521,7 +438,6 @@ static inline void sun4c_init_ss2_cache_bug(void) | |||
521 | 438 | ||
522 | if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) || | 439 | if ((idprom->id_machtype == (SM_SUN4C | SM_4C_SS2)) || |
523 | (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) || | 440 | (idprom->id_machtype == (SM_SUN4C | SM_4C_IPX)) || |
524 | (idprom->id_machtype == (SM_SUN4 | SM_4_330)) || | ||
525 | (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) { | 441 | (idprom->id_machtype == (SM_SUN4C | SM_4C_ELC))) { |
526 | /* Whee.. */ | 442 | /* Whee.. */ |
527 | printk("SS2 cache bug detected, uncaching trap table page\n"); | 443 | printk("SS2 cache bug detected, uncaching trap table page\n"); |
@@ -532,8 +448,8 @@ static inline void sun4c_init_ss2_cache_bug(void) | |||
532 | } | 448 | } |
533 | 449 | ||
534 | /* Addr is always aligned on a page boundary for us already. */ | 450 | /* Addr is always aligned on a page boundary for us already. */ |
535 | static int sun4c_map_dma_area(dma_addr_t *pba, unsigned long va, | 451 | static int sun4c_map_dma_area(struct device *dev, dma_addr_t *pba, unsigned long va, |
536 | unsigned long addr, int len) | 452 | unsigned long addr, int len) |
537 | { | 453 | { |
538 | unsigned long page, end; | 454 | unsigned long page, end; |
539 | 455 | ||
@@ -555,14 +471,7 @@ static int sun4c_map_dma_area(dma_addr_t *pba, unsigned long va, | |||
555 | return 0; | 471 | return 0; |
556 | } | 472 | } |
557 | 473 | ||
558 | static struct page *sun4c_translate_dvma(unsigned long busa) | 474 | static void sun4c_unmap_dma_area(struct device *dev, unsigned long busa, int len) |
559 | { | ||
560 | /* Fortunately for us, bus_addr == uncached_virt in sun4c. */ | ||
561 | unsigned long pte = sun4c_get_pte(busa); | ||
562 | return pfn_to_page(pte & SUN4C_PFN_MASK); | ||
563 | } | ||
564 | |||
565 | static void sun4c_unmap_dma_area(unsigned long busa, int len) | ||
566 | { | 475 | { |
567 | /* Fortunately for us, bus_addr == uncached_virt in sun4c. */ | 476 | /* Fortunately for us, bus_addr == uncached_virt in sun4c. */ |
568 | /* XXX Implement this */ | 477 | /* XXX Implement this */ |
@@ -624,11 +533,7 @@ static inline void sun4c_init_map_kernelprom(unsigned long kernel_end) | |||
624 | { | 533 | { |
625 | unsigned long vaddr; | 534 | unsigned long vaddr; |
626 | unsigned char pseg, ctx; | 535 | unsigned char pseg, ctx; |
627 | #ifdef CONFIG_SUN4 | 536 | |
628 | /* sun4/110 and 260 have no kadb. */ | ||
629 | if ((idprom->id_machtype != (SM_SUN4 | SM_4_260)) && | ||
630 | (idprom->id_machtype != (SM_SUN4 | SM_4_110))) { | ||
631 | #endif | ||
632 | for (vaddr = KADB_DEBUGGER_BEGVM; | 537 | for (vaddr = KADB_DEBUGGER_BEGVM; |
633 | vaddr < LINUX_OPPROM_ENDVM; | 538 | vaddr < LINUX_OPPROM_ENDVM; |
634 | vaddr += SUN4C_REAL_PGDIR_SIZE) { | 539 | vaddr += SUN4C_REAL_PGDIR_SIZE) { |
@@ -640,9 +545,7 @@ static inline void sun4c_init_map_kernelprom(unsigned long kernel_end) | |||
640 | fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0); | 545 | fix_permissions(vaddr, _SUN4C_PAGE_PRIV, 0); |
641 | } | 546 | } |
642 | } | 547 | } |
643 | #ifdef CONFIG_SUN4 | 548 | |
644 | } | ||
645 | #endif | ||
646 | for (vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) { | 549 | for (vaddr = KERNBASE; vaddr < kernel_end; vaddr += SUN4C_REAL_PGDIR_SIZE) { |
647 | pseg = sun4c_get_segmap(vaddr); | 550 | pseg = sun4c_get_segmap(vaddr); |
648 | mmu_entry_pool[pseg].locked = 1; | 551 | mmu_entry_pool[pseg].locked = 1; |
@@ -1048,14 +951,10 @@ static struct thread_info *sun4c_alloc_thread_info(void) | |||
1048 | * so we must flush the cache to guarantee consistency. | 951 | * so we must flush the cache to guarantee consistency. |
1049 | */ | 952 | */ |
1050 | sun4c_flush_page(pages); | 953 | sun4c_flush_page(pages); |
1051 | #ifndef CONFIG_SUN4 | ||
1052 | sun4c_flush_page(pages + PAGE_SIZE); | 954 | sun4c_flush_page(pages + PAGE_SIZE); |
1053 | #endif | ||
1054 | 955 | ||
1055 | sun4c_put_pte(addr, BUCKET_PTE(pages)); | 956 | sun4c_put_pte(addr, BUCKET_PTE(pages)); |
1056 | #ifndef CONFIG_SUN4 | ||
1057 | sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE)); | 957 | sun4c_put_pte(addr + PAGE_SIZE, BUCKET_PTE(pages + PAGE_SIZE)); |
1058 | #endif | ||
1059 | 958 | ||
1060 | #ifdef CONFIG_DEBUG_STACK_USAGE | 959 | #ifdef CONFIG_DEBUG_STACK_USAGE |
1061 | memset((void *)addr, 0, PAGE_SIZE << THREAD_INFO_ORDER); | 960 | memset((void *)addr, 0, PAGE_SIZE << THREAD_INFO_ORDER); |
@@ -1072,13 +971,11 @@ static void sun4c_free_thread_info(struct thread_info *ti) | |||
1072 | 971 | ||
1073 | /* We are deleting a mapping, so the flush here is mandatory. */ | 972 | /* We are deleting a mapping, so the flush here is mandatory. */ |
1074 | sun4c_flush_page(tiaddr); | 973 | sun4c_flush_page(tiaddr); |
1075 | #ifndef CONFIG_SUN4 | ||
1076 | sun4c_flush_page(tiaddr + PAGE_SIZE); | 974 | sun4c_flush_page(tiaddr + PAGE_SIZE); |
1077 | #endif | 975 | |
1078 | sun4c_put_pte(tiaddr, 0); | 976 | sun4c_put_pte(tiaddr, 0); |
1079 | #ifndef CONFIG_SUN4 | ||
1080 | sun4c_put_pte(tiaddr + PAGE_SIZE, 0); | 977 | sun4c_put_pte(tiaddr + PAGE_SIZE, 0); |
1081 | #endif | 978 | |
1082 | sun4c_bucket[entry] = BUCKET_EMPTY; | 979 | sun4c_bucket[entry] = BUCKET_EMPTY; |
1083 | if (entry < sun4c_lowbucket_avail) | 980 | if (entry < sun4c_lowbucket_avail) |
1084 | sun4c_lowbucket_avail = entry; | 981 | sun4c_lowbucket_avail = entry; |
@@ -1211,7 +1108,7 @@ static void sun4c_unlockarea(char *vaddr, unsigned long size) | |||
1211 | * by implication and fool the page locking code above | 1108 | * by implication and fool the page locking code above |
1212 | * if passed to by mistake. | 1109 | * if passed to by mistake. |
1213 | */ | 1110 | */ |
1214 | static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct sbus_bus *sbus) | 1111 | static __u32 sun4c_get_scsi_one(struct device *dev, char *bufptr, unsigned long len) |
1215 | { | 1112 | { |
1216 | unsigned long page; | 1113 | unsigned long page; |
1217 | 1114 | ||
@@ -1223,7 +1120,7 @@ static __u32 sun4c_get_scsi_one(char *bufptr, unsigned long len, struct sbus_bus | |||
1223 | return (__u32)sun4c_lockarea(bufptr, len); | 1120 | return (__u32)sun4c_lockarea(bufptr, len); |
1224 | } | 1121 | } |
1225 | 1122 | ||
1226 | static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) | 1123 | static void sun4c_get_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz) |
1227 | { | 1124 | { |
1228 | while (sz != 0) { | 1125 | while (sz != 0) { |
1229 | --sz; | 1126 | --sz; |
@@ -1233,14 +1130,14 @@ static void sun4c_get_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus * | |||
1233 | } | 1130 | } |
1234 | } | 1131 | } |
1235 | 1132 | ||
1236 | static void sun4c_release_scsi_one(__u32 bufptr, unsigned long len, struct sbus_bus *sbus) | 1133 | static void sun4c_release_scsi_one(struct device *dev, __u32 bufptr, unsigned long len) |
1237 | { | 1134 | { |
1238 | if (bufptr < sun4c_iobuffer_start) | 1135 | if (bufptr < sun4c_iobuffer_start) |
1239 | return; /* On kernel stack or similar, see above */ | 1136 | return; /* On kernel stack or similar, see above */ |
1240 | sun4c_unlockarea((char *)bufptr, len); | 1137 | sun4c_unlockarea((char *)bufptr, len); |
1241 | } | 1138 | } |
1242 | 1139 | ||
1243 | static void sun4c_release_scsi_sgl(struct scatterlist *sg, int sz, struct sbus_bus *sbus) | 1140 | static void sun4c_release_scsi_sgl(struct device *dev, struct scatterlist *sg, int sz) |
1244 | { | 1141 | { |
1245 | while (sz != 0) { | 1142 | while (sz != 0) { |
1246 | --sz; | 1143 | --sz; |
@@ -2263,7 +2160,6 @@ void __init ld_mmu_sun4c(void) | |||
2263 | 2160 | ||
2264 | BTFIXUPSET_CALL(mmu_map_dma_area, sun4c_map_dma_area, BTFIXUPCALL_NORM); | 2161 | BTFIXUPSET_CALL(mmu_map_dma_area, sun4c_map_dma_area, BTFIXUPCALL_NORM); |
2265 | BTFIXUPSET_CALL(mmu_unmap_dma_area, sun4c_unmap_dma_area, BTFIXUPCALL_NORM); | 2162 | BTFIXUPSET_CALL(mmu_unmap_dma_area, sun4c_unmap_dma_area, BTFIXUPCALL_NORM); |
2266 | BTFIXUPSET_CALL(mmu_translate_dvma, sun4c_translate_dvma, BTFIXUPCALL_NORM); | ||
2267 | 2163 | ||
2268 | BTFIXUPSET_CALL(sparc_mapiorange, sun4c_mapiorange, BTFIXUPCALL_NORM); | 2164 | BTFIXUPSET_CALL(sparc_mapiorange, sun4c_mapiorange, BTFIXUPCALL_NORM); |
2269 | BTFIXUPSET_CALL(sparc_unmapiorange, sun4c_unmapiorange, BTFIXUPCALL_NORM); | 2165 | BTFIXUPSET_CALL(sparc_unmapiorange, sun4c_unmapiorange, BTFIXUPCALL_NORM); |
diff --git a/arch/sparc/prom/Makefile b/arch/sparc/prom/Makefile index 7f5eacfcfbcf..8f7e18546c97 100644 --- a/arch/sparc/prom/Makefile +++ b/arch/sparc/prom/Makefile | |||
@@ -4,5 +4,3 @@ | |||
4 | 4 | ||
5 | lib-y := bootstr.o devmap.o devops.o init.o memory.o misc.o mp.o \ | 5 | lib-y := bootstr.o devmap.o devops.o init.o memory.o misc.o mp.o \ |
6 | palloc.o ranges.o segment.o console.o printf.o tree.o | 6 | palloc.o ranges.o segment.o console.o printf.o tree.o |
7 | |||
8 | lib-$(CONFIG_SUN4) += sun4prom.o | ||
diff --git a/arch/sparc/prom/bootstr.c b/arch/sparc/prom/bootstr.c index 5a35c768ff7c..916831da7e67 100644 --- a/arch/sparc/prom/bootstr.c +++ b/arch/sparc/prom/bootstr.c | |||
@@ -6,15 +6,12 @@ | |||
6 | 6 | ||
7 | #include <linux/string.h> | 7 | #include <linux/string.h> |
8 | #include <asm/oplib.h> | 8 | #include <asm/oplib.h> |
9 | #include <asm/sun4prom.h> | ||
10 | #include <linux/init.h> | 9 | #include <linux/init.h> |
11 | 10 | ||
12 | #define BARG_LEN 256 | 11 | #define BARG_LEN 256 |
13 | static char barg_buf[BARG_LEN] = { 0 }; | 12 | static char barg_buf[BARG_LEN] = { 0 }; |
14 | static char fetched __initdata = 0; | 13 | static char fetched __initdata = 0; |
15 | 14 | ||
16 | extern linux_sun4_romvec *sun4_romvec; | ||
17 | |||
18 | char * __init | 15 | char * __init |
19 | prom_getbootargs(void) | 16 | prom_getbootargs(void) |
20 | { | 17 | { |
@@ -28,7 +25,6 @@ prom_getbootargs(void) | |||
28 | 25 | ||
29 | switch(prom_vers) { | 26 | switch(prom_vers) { |
30 | case PROM_V0: | 27 | case PROM_V0: |
31 | case PROM_SUN4: | ||
32 | cp = barg_buf; | 28 | cp = barg_buf; |
33 | /* Start from 1 and go over fd(0,0,0)kernel */ | 29 | /* Start from 1 and go over fd(0,0,0)kernel */ |
34 | for(iter = 1; iter < 8; iter++) { | 30 | for(iter = 1; iter < 8; iter++) { |
diff --git a/arch/sparc/prom/console.c b/arch/sparc/prom/console.c index 790057a34616..b3075d73fc19 100644 --- a/arch/sparc/prom/console.c +++ b/arch/sparc/prom/console.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
11 | #include <linux/sched.h> | 11 | #include <linux/sched.h> |
12 | #include <asm/openprom.h> | 12 | #include <asm/openprom.h> |
13 | #include <asm/sun4prom.h> | ||
14 | #include <asm/oplib.h> | 13 | #include <asm/oplib.h> |
15 | #include <asm/system.h> | 14 | #include <asm/system.h> |
16 | #include <linux/string.h> | 15 | #include <linux/string.h> |
@@ -30,7 +29,6 @@ prom_nbgetchar(void) | |||
30 | spin_lock_irqsave(&prom_lock, flags); | 29 | spin_lock_irqsave(&prom_lock, flags); |
31 | switch(prom_vers) { | 30 | switch(prom_vers) { |
32 | case PROM_V0: | 31 | case PROM_V0: |
33 | case PROM_SUN4: | ||
34 | i = (*(romvec->pv_nbgetchar))(); | 32 | i = (*(romvec->pv_nbgetchar))(); |
35 | break; | 33 | break; |
36 | case PROM_V2: | 34 | case PROM_V2: |
@@ -63,7 +61,6 @@ prom_nbputchar(char c) | |||
63 | spin_lock_irqsave(&prom_lock, flags); | 61 | spin_lock_irqsave(&prom_lock, flags); |
64 | switch(prom_vers) { | 62 | switch(prom_vers) { |
65 | case PROM_V0: | 63 | case PROM_V0: |
66 | case PROM_SUN4: | ||
67 | i = (*(romvec->pv_nbputchar))(c); | 64 | i = (*(romvec->pv_nbputchar))(c); |
68 | break; | 65 | break; |
69 | case PROM_V2: | 66 | case PROM_V2: |
diff --git a/arch/sparc/prom/init.c b/arch/sparc/prom/init.c index 729f87066945..873217c6d823 100644 --- a/arch/sparc/prom/init.c +++ b/arch/sparc/prom/init.c | |||
@@ -11,12 +11,10 @@ | |||
11 | 11 | ||
12 | #include <asm/openprom.h> | 12 | #include <asm/openprom.h> |
13 | #include <asm/oplib.h> | 13 | #include <asm/oplib.h> |
14 | #include <asm/sun4prom.h> | ||
15 | 14 | ||
16 | struct linux_romvec *romvec; | 15 | struct linux_romvec *romvec; |
17 | enum prom_major_version prom_vers; | 16 | enum prom_major_version prom_vers; |
18 | unsigned int prom_rev, prom_prev; | 17 | unsigned int prom_rev, prom_prev; |
19 | linux_sun4_romvec *sun4_romvec; | ||
20 | 18 | ||
21 | /* The root node of the prom device tree. */ | 19 | /* The root node of the prom device tree. */ |
22 | int prom_root_node; | 20 | int prom_root_node; |
@@ -34,10 +32,6 @@ extern void prom_ranges_init(void); | |||
34 | 32 | ||
35 | void __init prom_init(struct linux_romvec *rp) | 33 | void __init prom_init(struct linux_romvec *rp) |
36 | { | 34 | { |
37 | #ifdef CONFIG_SUN4 | ||
38 | extern struct linux_romvec *sun4_prom_init(void); | ||
39 | rp = sun4_prom_init(); | ||
40 | #endif | ||
41 | romvec = rp; | 35 | romvec = rp; |
42 | 36 | ||
43 | switch(romvec->pv_romvers) { | 37 | switch(romvec->pv_romvers) { |
@@ -50,9 +44,6 @@ void __init prom_init(struct linux_romvec *rp) | |||
50 | case 3: | 44 | case 3: |
51 | prom_vers = PROM_V3; | 45 | prom_vers = PROM_V3; |
52 | break; | 46 | break; |
53 | case 40: | ||
54 | prom_vers = PROM_SUN4; | ||
55 | break; | ||
56 | default: | 47 | default: |
57 | prom_printf("PROMLIB: Bad PROM version %d\n", | 48 | prom_printf("PROMLIB: Bad PROM version %d\n", |
58 | romvec->pv_romvers); | 49 | romvec->pv_romvers); |
@@ -76,11 +67,8 @@ void __init prom_init(struct linux_romvec *rp) | |||
76 | 67 | ||
77 | prom_ranges_init(); | 68 | prom_ranges_init(); |
78 | 69 | ||
79 | #ifndef CONFIG_SUN4 | ||
80 | /* SUN4 prints this in sun4_prom_init */ | ||
81 | printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n", | 70 | printk("PROMLIB: Sun Boot Prom Version %d Revision %d\n", |
82 | romvec->pv_romvers, prom_rev); | 71 | romvec->pv_romvers, prom_rev); |
83 | #endif | ||
84 | 72 | ||
85 | /* Initialization successful. */ | 73 | /* Initialization successful. */ |
86 | return; | 74 | return; |
diff --git a/arch/sparc/prom/memory.c b/arch/sparc/prom/memory.c index 947f047dc95a..fac7899a29c3 100644 --- a/arch/sparc/prom/memory.c +++ b/arch/sparc/prom/memory.c | |||
@@ -10,7 +10,6 @@ | |||
10 | #include <linux/init.h> | 10 | #include <linux/init.h> |
11 | 11 | ||
12 | #include <asm/openprom.h> | 12 | #include <asm/openprom.h> |
13 | #include <asm/sun4prom.h> | ||
14 | #include <asm/oplib.h> | 13 | #include <asm/oplib.h> |
15 | #include <asm/page.h> | 14 | #include <asm/page.h> |
16 | 15 | ||
@@ -46,15 +45,6 @@ static int __init prom_meminit_v2(void) | |||
46 | return num_ents; | 45 | return num_ents; |
47 | } | 46 | } |
48 | 47 | ||
49 | static int __init prom_meminit_sun4(void) | ||
50 | { | ||
51 | #ifdef CONFIG_SUN4 | ||
52 | sp_banks[0].base_addr = 0; | ||
53 | sp_banks[0].num_bytes = *(sun4_romvec->memoryavail); | ||
54 | #endif | ||
55 | return 1; | ||
56 | } | ||
57 | |||
58 | static int sp_banks_cmp(const void *a, const void *b) | 48 | static int sp_banks_cmp(const void *a, const void *b) |
59 | { | 49 | { |
60 | const struct sparc_phys_banks *x = a, *y = b; | 50 | const struct sparc_phys_banks *x = a, *y = b; |
@@ -81,10 +71,6 @@ void __init prom_meminit(void) | |||
81 | num_ents = prom_meminit_v2(); | 71 | num_ents = prom_meminit_v2(); |
82 | break; | 72 | break; |
83 | 73 | ||
84 | case PROM_SUN4: | ||
85 | num_ents = prom_meminit_sun4(); | ||
86 | break; | ||
87 | |||
88 | default: | 74 | default: |
89 | break; | 75 | break; |
90 | } | 76 | } |
diff --git a/arch/sparc/prom/ranges.c b/arch/sparc/prom/ranges.c index f9b7def35f6e..64579a376419 100644 --- a/arch/sparc/prom/ranges.c +++ b/arch/sparc/prom/ranges.c | |||
@@ -9,7 +9,6 @@ | |||
9 | #include <asm/openprom.h> | 9 | #include <asm/openprom.h> |
10 | #include <asm/oplib.h> | 10 | #include <asm/oplib.h> |
11 | #include <asm/types.h> | 11 | #include <asm/types.h> |
12 | #include <asm/sbus.h> | ||
13 | #include <asm/system.h> | 12 | #include <asm/system.h> |
14 | 13 | ||
15 | struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; | 14 | struct linux_prom_ranges promlib_obio_ranges[PROMREG_MAX]; |
diff --git a/arch/sparc/prom/sun4prom.c b/arch/sparc/prom/sun4prom.c deleted file mode 100644 index 00390a2652aa..000000000000 --- a/arch/sparc/prom/sun4prom.c +++ /dev/null | |||
@@ -1,161 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 1996 The Australian National University. | ||
3 | * Copyright (C) 1996 Fujitsu Laboratories Limited | ||
4 | * Copyright (C) 1997 Michael A. Griffith (grif@acm.org) | ||
5 | * Copyright (C) 1997 Sun Weenie (ko@ko.reno.nv.us) | ||
6 | * Copyright (C) 1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) | ||
7 | * | ||
8 | * This software may be distributed under the terms of the Gnu | ||
9 | * Public License version 2 or later | ||
10 | * | ||
11 | * fake a really simple Sun prom for the SUN4 | ||
12 | */ | ||
13 | |||
14 | #include <linux/kernel.h> | ||
15 | #include <linux/string.h> | ||
16 | #include <asm/oplib.h> | ||
17 | #include <asm/idprom.h> | ||
18 | #include <asm/machines.h> | ||
19 | #include <asm/sun4prom.h> | ||
20 | #include <asm/asi.h> | ||
21 | #include <asm/contregs.h> | ||
22 | #include <linux/init.h> | ||
23 | |||
24 | static struct linux_romvec sun4romvec; | ||
25 | static struct idprom sun4_idprom; | ||
26 | |||
27 | struct property { | ||
28 | char *name; | ||
29 | char *value; | ||
30 | int length; | ||
31 | }; | ||
32 | |||
33 | struct node { | ||
34 | int level; | ||
35 | struct property *properties; | ||
36 | }; | ||
37 | |||
38 | struct property null_properties = { NULL, NULL, -1 }; | ||
39 | |||
40 | struct property root_properties[] = { | ||
41 | {"device_type", "cpu", 4}, | ||
42 | {"idprom", (char *)&sun4_idprom, sizeof(struct idprom)}, | ||
43 | {NULL, NULL, -1} | ||
44 | }; | ||
45 | |||
46 | struct node nodes[] = { | ||
47 | { 0, &null_properties }, | ||
48 | { 0, root_properties }, | ||
49 | { -1,&null_properties } | ||
50 | }; | ||
51 | |||
52 | |||
53 | static int no_nextnode(int node) | ||
54 | { | ||
55 | if (nodes[node].level == nodes[node+1].level) | ||
56 | return node+1; | ||
57 | return -1; | ||
58 | } | ||
59 | |||
60 | static int no_child(int node) | ||
61 | { | ||
62 | if (nodes[node].level == nodes[node+1].level-1) | ||
63 | return node+1; | ||
64 | return -1; | ||
65 | } | ||
66 | |||
67 | static struct property *find_property(int node,char *name) | ||
68 | { | ||
69 | struct property *prop = &nodes[node].properties[0]; | ||
70 | while (prop && prop->name) { | ||
71 | if (strcmp(prop->name,name) == 0) return prop; | ||
72 | prop++; | ||
73 | } | ||
74 | return NULL; | ||
75 | } | ||
76 | |||
77 | static int no_proplen(int node,char *name) | ||
78 | { | ||
79 | struct property *prop = find_property(node,name); | ||
80 | if (prop) return prop->length; | ||
81 | return -1; | ||
82 | } | ||
83 | |||
84 | static int no_getprop(int node,char *name,char *value) | ||
85 | { | ||
86 | struct property *prop = find_property(node,name); | ||
87 | if (prop) { | ||
88 | memcpy(value,prop->value,prop->length); | ||
89 | return 1; | ||
90 | } | ||
91 | return -1; | ||
92 | } | ||
93 | |||
94 | static int no_setprop(int node,char *name,char *value,int len) | ||
95 | { | ||
96 | return -1; | ||
97 | } | ||
98 | |||
99 | static char *no_nextprop(int node,char *name) | ||
100 | { | ||
101 | struct property *prop = find_property(node,name); | ||
102 | if (prop) return prop[1].name; | ||
103 | return NULL; | ||
104 | } | ||
105 | |||
106 | static struct linux_nodeops sun4_nodeops = { | ||
107 | no_nextnode, | ||
108 | no_child, | ||
109 | no_proplen, | ||
110 | no_getprop, | ||
111 | no_setprop, | ||
112 | no_nextprop | ||
113 | }; | ||
114 | |||
115 | static int synch_hook; | ||
116 | |||
117 | struct linux_romvec * __init sun4_prom_init(void) | ||
118 | { | ||
119 | int i; | ||
120 | unsigned char x; | ||
121 | char *p; | ||
122 | |||
123 | p = (char *)&sun4_idprom; | ||
124 | for (i = 0; i < sizeof(sun4_idprom); i++) { | ||
125 | __asm__ __volatile__ ("lduba [%1] %2, %0" : "=r" (x) : | ||
126 | "r" (AC_IDPROM + i), "i" (ASI_CONTROL)); | ||
127 | *p++ = x; | ||
128 | } | ||
129 | |||
130 | memset(&sun4romvec,0,sizeof(sun4romvec)); | ||
131 | |||
132 | sun4_romvec = (linux_sun4_romvec *) SUN4_PROM_VECTOR; | ||
133 | |||
134 | sun4romvec.pv_romvers = 40; | ||
135 | sun4romvec.pv_nodeops = &sun4_nodeops; | ||
136 | sun4romvec.pv_reboot = sun4_romvec->reboot; | ||
137 | sun4romvec.pv_abort = sun4_romvec->abortentry; | ||
138 | sun4romvec.pv_halt = sun4_romvec->exittomon; | ||
139 | sun4romvec.pv_synchook = (void (**)(void))&synch_hook; | ||
140 | sun4romvec.pv_setctxt = sun4_romvec->setcxsegmap; | ||
141 | sun4romvec.pv_v0bootargs = sun4_romvec->bootParam; | ||
142 | sun4romvec.pv_nbgetchar = sun4_romvec->mayget; | ||
143 | sun4romvec.pv_nbputchar = sun4_romvec->mayput; | ||
144 | sun4romvec.pv_stdin = sun4_romvec->insource; | ||
145 | sun4romvec.pv_stdout = sun4_romvec->outsink; | ||
146 | |||
147 | /* | ||
148 | * We turn on the LEDs to let folks without monitors or | ||
149 | * terminals know we booted. Nothing too fancy now. They | ||
150 | * are all on, except for LED 5, which blinks. When we | ||
151 | * have more time, we can teach the penguin to say "By your | ||
152 | * command" or "Activating turbo boost, Michael". :-) | ||
153 | */ | ||
154 | sun4_romvec->setLEDs(NULL); | ||
155 | |||
156 | printk("PROMLIB: Old Sun4 boot PROM monitor %s, romvec version %d\n", | ||
157 | sun4_romvec->monid, | ||
158 | sun4_romvec->romvecversion); | ||
159 | |||
160 | return &sun4romvec; | ||
161 | } | ||
diff --git a/arch/sparc64/Kconfig b/arch/sparc64/Kconfig index 36b4b7ab9cfb..5446e2a499b1 100644 --- a/arch/sparc64/Kconfig +++ b/arch/sparc64/Kconfig | |||
@@ -18,6 +18,13 @@ config SPARC64 | |||
18 | select HAVE_ARCH_KGDB | 18 | select HAVE_ARCH_KGDB |
19 | select USE_GENERIC_SMP_HELPERS if SMP | 19 | select USE_GENERIC_SMP_HELPERS if SMP |
20 | select HAVE_ARCH_TRACEHOOK | 20 | select HAVE_ARCH_TRACEHOOK |
21 | select ARCH_WANT_OPTIONAL_GPIOLIB | ||
22 | select RTC_CLASS | ||
23 | select RTC_DRV_M48T59 | ||
24 | select RTC_DRV_CMOS | ||
25 | select RTC_DRV_BQ4802 | ||
26 | select RTC_DRV_SUN4V | ||
27 | select RTC_DRV_STARFIRE | ||
21 | 28 | ||
22 | config GENERIC_TIME | 29 | config GENERIC_TIME |
23 | bool | 30 | bool |
@@ -31,6 +38,11 @@ config GENERIC_CLOCKEVENTS | |||
31 | bool | 38 | bool |
32 | default y | 39 | default y |
33 | 40 | ||
41 | config GENERIC_GPIO | ||
42 | bool | ||
43 | help | ||
44 | Generic GPIO API support | ||
45 | |||
34 | config 64BIT | 46 | config 64BIT |
35 | def_bool y | 47 | def_bool y |
36 | 48 | ||
@@ -185,6 +197,17 @@ config US2E_FREQ | |||
185 | 197 | ||
186 | If in doubt, say N. | 198 | If in doubt, say N. |
187 | 199 | ||
200 | config US3_MC | ||
201 | tristate "UltraSPARC-III Memory Controller driver" | ||
202 | default y | ||
203 | help | ||
204 | This adds a driver for the UltraSPARC-III memory controller. | ||
205 | Loading this driver allows exact mnemonic strings to be | ||
206 | printed in the event of a memory error, so that the faulty DIMM | ||
207 | on the motherboard can be matched to the error. | ||
208 | |||
209 | If in doubt, say Y, as this information can be very useful. | ||
210 | |||
188 | # Global things across all Sun machines. | 211 | # Global things across all Sun machines. |
189 | config GENERIC_LOCKBREAK | 212 | config GENERIC_LOCKBREAK |
190 | bool | 213 | bool |
diff --git a/arch/sparc64/Makefile b/arch/sparc64/Makefile index b785a395b12f..c7214abc0d84 100644 --- a/arch/sparc64/Makefile +++ b/arch/sparc64/Makefile | |||
@@ -7,7 +7,7 @@ | |||
7 | # Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) | 7 | # Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz) |
8 | # | 8 | # |
9 | 9 | ||
10 | CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -m64 | 10 | CHECKFLAGS += -D__sparc__ -D__sparc_v9__ -D__arch64__ -m64 |
11 | 11 | ||
12 | # Undefine sparc when processing vmlinux.lds - it is used | 12 | # Undefine sparc when processing vmlinux.lds - it is used |
13 | # And teach CPP we are doing 64 bit builds (for this case) | 13 | # And teach CPP we are doing 64 bit builds (for this case) |
diff --git a/arch/sparc64/kernel/Makefile b/arch/sparc64/kernel/Makefile index 418b5782096e..c0b8009ab196 100644 --- a/arch/sparc64/kernel/Makefile +++ b/arch/sparc64/kernel/Makefile | |||
@@ -7,16 +7,16 @@ EXTRA_CFLAGS := -Werror | |||
7 | 7 | ||
8 | extra-y := head.o init_task.o vmlinux.lds | 8 | extra-y := head.o init_task.o vmlinux.lds |
9 | 9 | ||
10 | obj-y := process.o setup.o cpu.o idprom.o \ | 10 | obj-y := process.o setup.o cpu.o idprom.o reboot.o \ |
11 | traps.o auxio.o una_asm.o sysfs.o iommu.o \ | 11 | traps.o auxio.o una_asm.o sysfs.o iommu.o \ |
12 | irq.o ptrace.o time.o sys_sparc.o signal.o \ | 12 | irq.o ptrace.o time.o sys_sparc.o signal.o \ |
13 | unaligned.o central.o pci.o starfire.o \ | 13 | unaligned.o central.o starfire.o \ |
14 | power.o sbus.o sparc64_ksyms.o chmc.o \ | 14 | power.o sbus.o sparc64_ksyms.o ebus.o \ |
15 | visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o | 15 | visemul.o prom.o of_device.o hvapi.o sstate.o mdesc.o |
16 | 16 | ||
17 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o | 17 | obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o |
18 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | 18 | obj-$(CONFIG_STACKTRACE) += stacktrace.o |
19 | obj-$(CONFIG_PCI) += ebus.o pci_common.o \ | 19 | obj-$(CONFIG_PCI) += pci.o pci_common.o psycho_common.o \ |
20 | pci_psycho.o pci_sabre.o pci_schizo.o \ | 20 | pci_psycho.o pci_sabre.o pci_schizo.o \ |
21 | pci_sun4v.o pci_sun4v_asm.o pci_fire.o | 21 | pci_sun4v.o pci_sun4v_asm.o pci_fire.o |
22 | obj-$(CONFIG_PCI_MSI) += pci_msi.o | 22 | obj-$(CONFIG_PCI_MSI) += pci_msi.o |
@@ -25,6 +25,7 @@ obj-$(CONFIG_COMPAT) += sys32.o sys_sparc32.o signal32.o | |||
25 | obj-$(CONFIG_MODULES) += module.o | 25 | obj-$(CONFIG_MODULES) += module.o |
26 | obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o | 26 | obj-$(CONFIG_US3_FREQ) += us3_cpufreq.o |
27 | obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o | 27 | obj-$(CONFIG_US2E_FREQ) += us2e_cpufreq.o |
28 | obj-$(CONFIG_US3_MC) += chmc.o | ||
28 | obj-$(CONFIG_KPROBES) += kprobes.o | 29 | obj-$(CONFIG_KPROBES) += kprobes.o |
29 | obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o | 30 | obj-$(CONFIG_SUN_LDOMS) += ldc.o vio.o viohs.o ds.o |
30 | obj-$(CONFIG_AUDIT) += audit.o | 31 | obj-$(CONFIG_AUDIT) += audit.o |
diff --git a/arch/sparc64/kernel/auxio.c b/arch/sparc64/kernel/auxio.c index dd5c7bf87619..858beda86524 100644 --- a/arch/sparc64/kernel/auxio.c +++ b/arch/sparc64/kernel/auxio.c | |||
@@ -109,7 +109,7 @@ void auxio_set_lte(int on) | |||
109 | } | 109 | } |
110 | } | 110 | } |
111 | 111 | ||
112 | static struct of_device_id auxio_match[] = { | 112 | static struct of_device_id __initdata auxio_match[] = { |
113 | { | 113 | { |
114 | .name = "auxio", | 114 | .name = "auxio", |
115 | }, | 115 | }, |
diff --git a/arch/sparc64/kernel/central.c b/arch/sparc64/kernel/central.c index f2e87d0d7e1d..05f1c916db06 100644 --- a/arch/sparc64/kernel/central.c +++ b/arch/sparc64/kernel/central.c | |||
@@ -1,461 +1,268 @@ | |||
1 | /* central.c: Central FHC driver for Sunfire/Starfire/Wildfire. | 1 | /* central.c: Central FHC driver for Sunfire/Starfire/Wildfire. |
2 | * | 2 | * |
3 | * Copyright (C) 1997, 1999 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 1997, 1999, 2008 David S. Miller (davem@davemloft.net) |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/types.h> | 7 | #include <linux/types.h> |
8 | #include <linux/string.h> | 8 | #include <linux/string.h> |
9 | #include <linux/timer.h> | ||
10 | #include <linux/sched.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/init.h> | 9 | #include <linux/init.h> |
13 | #include <linux/bootmem.h> | 10 | #include <linux/of_device.h> |
11 | #include <linux/platform_device.h> | ||
14 | 12 | ||
15 | #include <asm/page.h> | ||
16 | #include <asm/fhc.h> | 13 | #include <asm/fhc.h> |
17 | #include <asm/starfire.h> | 14 | #include <asm/upa.h> |
18 | 15 | ||
19 | static struct linux_central *central_bus = NULL; | 16 | struct clock_board { |
20 | static struct linux_fhc *fhc_list = NULL; | 17 | void __iomem *clock_freq_regs; |
18 | void __iomem *clock_regs; | ||
19 | void __iomem *clock_ver_reg; | ||
20 | int num_slots; | ||
21 | struct resource leds_resource; | ||
22 | struct platform_device leds_pdev; | ||
23 | }; | ||
24 | |||
25 | struct fhc { | ||
26 | void __iomem *pregs; | ||
27 | bool central; | ||
28 | bool jtag_master; | ||
29 | int board_num; | ||
30 | struct resource leds_resource; | ||
31 | struct platform_device leds_pdev; | ||
32 | }; | ||
33 | |||
34 | static int __devinit clock_board_calc_nslots(struct clock_board *p) | ||
35 | { | ||
36 | u8 reg = upa_readb(p->clock_regs + CLOCK_STAT1) & 0xc0; | ||
21 | 37 | ||
22 | #define IS_CENTRAL_FHC(__fhc) ((__fhc) == central_bus->child) | 38 | switch (reg) { |
39 | case 0x40: | ||
40 | return 16; | ||
23 | 41 | ||
24 | static void central_probe_failure(int line) | 42 | case 0xc0: |
25 | { | 43 | return 8; |
26 | prom_printf("CENTRAL: Critical device probe failure at central.c:%d\n", | ||
27 | line); | ||
28 | prom_halt(); | ||
29 | } | ||
30 | 44 | ||
31 | static void central_ranges_init(struct linux_central *central) | 45 | case 0x80: |
32 | { | 46 | reg = 0; |
33 | struct device_node *dp = central->prom_node; | 47 | if (p->clock_ver_reg) |
34 | const void *pval; | 48 | reg = upa_readb(p->clock_ver_reg); |
35 | int len; | 49 | if (reg) { |
36 | 50 | if (reg & 0x80) | |
37 | central->num_central_ranges = 0; | 51 | return 4; |
38 | pval = of_get_property(dp, "ranges", &len); | 52 | else |
39 | if (pval) { | 53 | return 5; |
40 | memcpy(central->central_ranges, pval, len); | 54 | } |
41 | central->num_central_ranges = | 55 | /* Fallthrough */ |
42 | (len / sizeof(struct linux_prom_ranges)); | 56 | default: |
57 | return 4; | ||
43 | } | 58 | } |
44 | } | 59 | } |
45 | 60 | ||
46 | static void fhc_ranges_init(struct linux_fhc *fhc) | 61 | static int __devinit clock_board_probe(struct of_device *op, |
62 | const struct of_device_id *match) | ||
47 | { | 63 | { |
48 | struct device_node *dp = fhc->prom_node; | 64 | struct clock_board *p = kzalloc(sizeof(*p), GFP_KERNEL); |
49 | const void *pval; | 65 | int err = -ENOMEM; |
50 | int len; | ||
51 | |||
52 | fhc->num_fhc_ranges = 0; | ||
53 | pval = of_get_property(dp, "ranges", &len); | ||
54 | if (pval) { | ||
55 | memcpy(fhc->fhc_ranges, pval, len); | ||
56 | fhc->num_fhc_ranges = | ||
57 | (len / sizeof(struct linux_prom_ranges)); | ||
58 | } | ||
59 | } | ||
60 | 66 | ||
61 | /* Range application routines are exported to various drivers, | 67 | if (!p) { |
62 | * so do not __init this. | 68 | printk(KERN_ERR "clock_board: Cannot allocate struct clock_board\n"); |
63 | */ | 69 | goto out; |
64 | static void adjust_regs(struct linux_prom_registers *regp, int nregs, | ||
65 | struct linux_prom_ranges *rangep, int nranges) | ||
66 | { | ||
67 | int regc, rngc; | ||
68 | |||
69 | for (regc = 0; regc < nregs; regc++) { | ||
70 | for (rngc = 0; rngc < nranges; rngc++) | ||
71 | if (regp[regc].which_io == rangep[rngc].ot_child_space) | ||
72 | break; /* Fount it */ | ||
73 | if (rngc == nranges) /* oops */ | ||
74 | central_probe_failure(__LINE__); | ||
75 | regp[regc].which_io = rangep[rngc].ot_parent_space; | ||
76 | regp[regc].phys_addr -= rangep[rngc].ot_child_base; | ||
77 | regp[regc].phys_addr += rangep[rngc].ot_parent_base; | ||
78 | } | 70 | } |
79 | } | ||
80 | 71 | ||
81 | /* Apply probed fhc ranges to registers passed, if no ranges return. */ | 72 | p->clock_freq_regs = of_ioremap(&op->resource[0], 0, |
82 | static void apply_fhc_ranges(struct linux_fhc *fhc, | 73 | resource_size(&op->resource[0]), |
83 | struct linux_prom_registers *regs, | 74 | "clock_board_freq"); |
84 | int nregs) | 75 | if (!p->clock_freq_regs) { |
85 | { | 76 | printk(KERN_ERR "clock_board: Cannot map clock_freq_regs\n"); |
86 | if (fhc->num_fhc_ranges) | 77 | goto out_free; |
87 | adjust_regs(regs, nregs, fhc->fhc_ranges, | 78 | } |
88 | fhc->num_fhc_ranges); | ||
89 | } | ||
90 | 79 | ||
91 | /* Apply probed central ranges to registers passed, if no ranges return. */ | 80 | p->clock_regs = of_ioremap(&op->resource[1], 0, |
92 | static void apply_central_ranges(struct linux_central *central, | 81 | resource_size(&op->resource[1]), |
93 | struct linux_prom_registers *regs, int nregs) | 82 | "clock_board_regs"); |
94 | { | 83 | if (!p->clock_regs) { |
95 | if (central->num_central_ranges) | 84 | printk(KERN_ERR "clock_board: Cannot map clock_regs\n"); |
96 | adjust_regs(regs, nregs, central->central_ranges, | 85 | goto out_unmap_clock_freq_regs; |
97 | central->num_central_ranges); | 86 | } |
98 | } | ||
99 | 87 | ||
100 | static void * __init central_alloc_bootmem(unsigned long size) | 88 | if (op->resource[2].flags) { |
101 | { | 89 | p->clock_ver_reg = of_ioremap(&op->resource[2], 0, |
102 | void *ret; | 90 | resource_size(&op->resource[2]), |
91 | "clock_ver_reg"); | ||
92 | if (!p->clock_ver_reg) { | ||
93 | printk(KERN_ERR "clock_board: Cannot map clock_ver_reg\n"); | ||
94 | goto out_unmap_clock_regs; | ||
95 | } | ||
96 | } | ||
103 | 97 | ||
104 | ret = __alloc_bootmem(size, SMP_CACHE_BYTES, 0UL); | 98 | p->num_slots = clock_board_calc_nslots(p); |
105 | if (ret != NULL) | ||
106 | memset(ret, 0, size); | ||
107 | 99 | ||
108 | return ret; | 100 | p->leds_resource.start = (unsigned long) |
109 | } | 101 | (p->clock_regs + CLOCK_CTRL); |
102 | p->leds_resource.end = p->leds_resource.end; | ||
103 | p->leds_resource.name = "leds"; | ||
110 | 104 | ||
111 | static unsigned long prom_reg_to_paddr(struct linux_prom_registers *r) | 105 | p->leds_pdev.name = "sunfire-clockboard-leds"; |
112 | { | 106 | p->leds_pdev.resource = &p->leds_resource; |
113 | unsigned long ret = ((unsigned long) r->which_io) << 32; | 107 | p->leds_pdev.num_resources = 1; |
108 | p->leds_pdev.dev.parent = &op->dev; | ||
114 | 109 | ||
115 | return ret | (unsigned long) r->phys_addr; | 110 | err = platform_device_register(&p->leds_pdev); |
116 | } | 111 | if (err) { |
117 | 112 | printk(KERN_ERR "clock_board: Could not register LEDS " | |
118 | static void __init probe_other_fhcs(void) | 113 | "platform device\n"); |
119 | { | 114 | goto out_unmap_clock_ver_reg; |
120 | struct device_node *dp; | ||
121 | const struct linux_prom64_registers *fpregs; | ||
122 | |||
123 | for_each_node_by_name(dp, "fhc") { | ||
124 | struct linux_fhc *fhc; | ||
125 | int board; | ||
126 | u32 tmp; | ||
127 | |||
128 | if (dp->parent && | ||
129 | dp->parent->parent != NULL) | ||
130 | continue; | ||
131 | |||
132 | fhc = (struct linux_fhc *) | ||
133 | central_alloc_bootmem(sizeof(struct linux_fhc)); | ||
134 | if (fhc == NULL) | ||
135 | central_probe_failure(__LINE__); | ||
136 | |||
137 | /* Link it into the FHC chain. */ | ||
138 | fhc->next = fhc_list; | ||
139 | fhc_list = fhc; | ||
140 | |||
141 | /* Toplevel FHCs have no parent. */ | ||
142 | fhc->parent = NULL; | ||
143 | |||
144 | fhc->prom_node = dp; | ||
145 | fhc_ranges_init(fhc); | ||
146 | |||
147 | /* Non-central FHC's have 64-bit OBP format registers. */ | ||
148 | fpregs = of_get_property(dp, "reg", NULL); | ||
149 | if (!fpregs) | ||
150 | central_probe_failure(__LINE__); | ||
151 | |||
152 | /* Only central FHC needs special ranges applied. */ | ||
153 | fhc->fhc_regs.pregs = fpregs[0].phys_addr; | ||
154 | fhc->fhc_regs.ireg = fpregs[1].phys_addr; | ||
155 | fhc->fhc_regs.ffregs = fpregs[2].phys_addr; | ||
156 | fhc->fhc_regs.sregs = fpregs[3].phys_addr; | ||
157 | fhc->fhc_regs.uregs = fpregs[4].phys_addr; | ||
158 | fhc->fhc_regs.tregs = fpregs[5].phys_addr; | ||
159 | |||
160 | board = of_getintprop_default(dp, "board#", -1); | ||
161 | fhc->board = board; | ||
162 | |||
163 | tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_JCTRL); | ||
164 | if ((tmp & FHC_JTAG_CTRL_MENAB) != 0) | ||
165 | fhc->jtag_master = 1; | ||
166 | else | ||
167 | fhc->jtag_master = 0; | ||
168 | |||
169 | tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); | ||
170 | printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] %s\n", | ||
171 | board, | ||
172 | (tmp & FHC_ID_VERS) >> 28, | ||
173 | (tmp & FHC_ID_PARTID) >> 12, | ||
174 | (tmp & FHC_ID_MANUF) >> 1, | ||
175 | (fhc->jtag_master ? "(JTAG Master)" : "")); | ||
176 | |||
177 | /* This bit must be set in all non-central FHC's in | ||
178 | * the system. When it is clear, this identifies | ||
179 | * the central board. | ||
180 | */ | ||
181 | tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | ||
182 | tmp |= FHC_CONTROL_IXIST; | ||
183 | upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | ||
184 | } | 115 | } |
185 | } | ||
186 | 116 | ||
187 | static void probe_clock_board(struct linux_central *central, | 117 | printk(KERN_INFO "clock_board: Detected %d slot Enterprise system.\n", |
188 | struct linux_fhc *fhc, | 118 | p->num_slots); |
189 | struct device_node *fp) | ||
190 | { | ||
191 | struct device_node *dp; | ||
192 | struct linux_prom_registers cregs[3]; | ||
193 | const struct linux_prom_registers *pr; | ||
194 | int nslots, tmp, nregs; | ||
195 | |||
196 | dp = fp->child; | ||
197 | while (dp) { | ||
198 | if (!strcmp(dp->name, "clock-board")) | ||
199 | break; | ||
200 | dp = dp->sibling; | ||
201 | } | ||
202 | if (!dp) | ||
203 | central_probe_failure(__LINE__); | ||
204 | 119 | ||
205 | pr = of_get_property(dp, "reg", &nregs); | 120 | err = 0; |
206 | if (!pr) | 121 | out: |
207 | central_probe_failure(__LINE__); | 122 | return err; |
208 | 123 | ||
209 | memcpy(cregs, pr, nregs); | 124 | out_unmap_clock_ver_reg: |
210 | nregs /= sizeof(struct linux_prom_registers); | 125 | if (p->clock_ver_reg) |
126 | of_iounmap(&op->resource[2], p->clock_ver_reg, | ||
127 | resource_size(&op->resource[2])); | ||
211 | 128 | ||
212 | apply_fhc_ranges(fhc, &cregs[0], nregs); | 129 | out_unmap_clock_regs: |
213 | apply_central_ranges(central, &cregs[0], nregs); | 130 | of_iounmap(&op->resource[1], p->clock_regs, |
214 | central->cfreg = prom_reg_to_paddr(&cregs[0]); | 131 | resource_size(&op->resource[1])); |
215 | central->clkregs = prom_reg_to_paddr(&cregs[1]); | ||
216 | 132 | ||
217 | if (nregs == 2) | 133 | out_unmap_clock_freq_regs: |
218 | central->clkver = 0UL; | 134 | of_iounmap(&op->resource[0], p->clock_freq_regs, |
219 | else | 135 | resource_size(&op->resource[0])); |
220 | central->clkver = prom_reg_to_paddr(&cregs[2]); | ||
221 | 136 | ||
222 | tmp = upa_readb(central->clkregs + CLOCK_STAT1); | 137 | out_free: |
223 | tmp &= 0xc0; | 138 | kfree(p); |
224 | switch(tmp) { | 139 | goto out; |
225 | case 0x40: | ||
226 | nslots = 16; | ||
227 | break; | ||
228 | case 0xc0: | ||
229 | nslots = 8; | ||
230 | break; | ||
231 | case 0x80: | ||
232 | if (central->clkver != 0UL && | ||
233 | upa_readb(central->clkver) != 0) { | ||
234 | if ((upa_readb(central->clkver) & 0x80) != 0) | ||
235 | nslots = 4; | ||
236 | else | ||
237 | nslots = 5; | ||
238 | break; | ||
239 | } | ||
240 | default: | ||
241 | nslots = 4; | ||
242 | break; | ||
243 | }; | ||
244 | central->slots = nslots; | ||
245 | printk("CENTRAL: Detected %d slot Enterprise system. cfreg[%02x] cver[%02x]\n", | ||
246 | central->slots, upa_readb(central->cfreg), | ||
247 | (central->clkver ? upa_readb(central->clkver) : 0x00)); | ||
248 | } | 140 | } |
249 | 141 | ||
250 | static void ZAP(unsigned long iclr, unsigned long imap) | 142 | static struct of_device_id __initdata clock_board_match[] = { |
143 | { | ||
144 | .name = "clock-board", | ||
145 | }, | ||
146 | {}, | ||
147 | }; | ||
148 | |||
149 | static struct of_platform_driver clock_board_driver = { | ||
150 | .match_table = clock_board_match, | ||
151 | .probe = clock_board_probe, | ||
152 | .driver = { | ||
153 | .name = "clock_board", | ||
154 | }, | ||
155 | }; | ||
156 | |||
157 | static int __devinit fhc_probe(struct of_device *op, | ||
158 | const struct of_device_id *match) | ||
251 | { | 159 | { |
252 | u32 imap_tmp; | 160 | struct fhc *p = kzalloc(sizeof(*p), GFP_KERNEL); |
253 | 161 | int err = -ENOMEM; | |
254 | upa_writel(0, iclr); | 162 | u32 reg; |
255 | upa_readl(iclr); | ||
256 | imap_tmp = upa_readl(imap); | ||
257 | imap_tmp &= ~(0x80000000); | ||
258 | upa_writel(imap_tmp, imap); | ||
259 | upa_readl(imap); | ||
260 | } | ||
261 | 163 | ||
262 | static void init_all_fhc_hw(void) | 164 | if (!p) { |
263 | { | 165 | printk(KERN_ERR "fhc: Cannot allocate struct fhc\n"); |
264 | struct linux_fhc *fhc; | 166 | goto out; |
265 | |||
266 | for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) { | ||
267 | u32 tmp; | ||
268 | |||
269 | /* Clear all of the interrupt mapping registers | ||
270 | * just in case OBP left them in a foul state. | ||
271 | */ | ||
272 | ZAP(fhc->fhc_regs.ffregs + FHC_FFREGS_ICLR, | ||
273 | fhc->fhc_regs.ffregs + FHC_FFREGS_IMAP); | ||
274 | ZAP(fhc->fhc_regs.sregs + FHC_SREGS_ICLR, | ||
275 | fhc->fhc_regs.sregs + FHC_SREGS_IMAP); | ||
276 | ZAP(fhc->fhc_regs.uregs + FHC_UREGS_ICLR, | ||
277 | fhc->fhc_regs.uregs + FHC_UREGS_IMAP); | ||
278 | ZAP(fhc->fhc_regs.tregs + FHC_TREGS_ICLR, | ||
279 | fhc->fhc_regs.tregs + FHC_TREGS_IMAP); | ||
280 | |||
281 | /* Setup FHC control register. */ | ||
282 | tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | ||
283 | |||
284 | /* All non-central boards have this bit set. */ | ||
285 | if (! IS_CENTRAL_FHC(fhc)) | ||
286 | tmp |= FHC_CONTROL_IXIST; | ||
287 | |||
288 | /* For all FHCs, clear the firmware synchronization | ||
289 | * line and both low power mode enables. | ||
290 | */ | ||
291 | tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | | ||
292 | FHC_CONTROL_SLINE); | ||
293 | |||
294 | upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | ||
295 | upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | ||
296 | } | 167 | } |
297 | 168 | ||
298 | } | 169 | if (!strcmp(op->node->parent->name, "central")) |
170 | p->central = true; | ||
299 | 171 | ||
300 | void __init central_probe(void) | 172 | p->pregs = of_ioremap(&op->resource[0], 0, |
301 | { | 173 | resource_size(&op->resource[0]), |
302 | struct linux_prom_registers fpregs[6]; | 174 | "fhc_pregs"); |
303 | const struct linux_prom_registers *pr; | 175 | if (!p->pregs) { |
304 | struct linux_fhc *fhc; | 176 | printk(KERN_ERR "fhc: Cannot map pregs\n"); |
305 | struct device_node *dp, *fp; | 177 | goto out_free; |
306 | int err; | ||
307 | |||
308 | dp = of_find_node_by_name(NULL, "central"); | ||
309 | if (!dp) { | ||
310 | if (this_is_starfire) | ||
311 | starfire_cpu_setup(); | ||
312 | return; | ||
313 | } | 178 | } |
314 | 179 | ||
315 | /* Ok we got one, grab some memory for software state. */ | 180 | if (p->central) { |
316 | central_bus = (struct linux_central *) | 181 | reg = upa_readl(p->pregs + FHC_PREGS_BSR); |
317 | central_alloc_bootmem(sizeof(struct linux_central)); | 182 | p->board_num = ((reg >> 16) & 1) | ((reg >> 12) & 0x0e); |
318 | if (central_bus == NULL) | 183 | } else { |
319 | central_probe_failure(__LINE__); | 184 | p->board_num = of_getintprop_default(op->node, "board#", -1); |
320 | 185 | if (p->board_num == -1) { | |
321 | fhc = (struct linux_fhc *) | 186 | printk(KERN_ERR "fhc: No board# property\n"); |
322 | central_alloc_bootmem(sizeof(struct linux_fhc)); | 187 | goto out_unmap_pregs; |
323 | if (fhc == NULL) | 188 | } |
324 | central_probe_failure(__LINE__); | 189 | if (upa_readl(p->pregs + FHC_PREGS_JCTRL) & FHC_JTAG_CTRL_MENAB) |
325 | 190 | p->jtag_master = true; | |
326 | /* First init central. */ | ||
327 | central_bus->child = fhc; | ||
328 | central_bus->prom_node = dp; | ||
329 | central_ranges_init(central_bus); | ||
330 | |||
331 | /* And then central's FHC. */ | ||
332 | fhc->next = fhc_list; | ||
333 | fhc_list = fhc; | ||
334 | |||
335 | fhc->parent = central_bus; | ||
336 | fp = dp->child; | ||
337 | while (fp) { | ||
338 | if (!strcmp(fp->name, "fhc")) | ||
339 | break; | ||
340 | fp = fp->sibling; | ||
341 | } | 191 | } |
342 | if (!fp) | ||
343 | central_probe_failure(__LINE__); | ||
344 | |||
345 | fhc->prom_node = fp; | ||
346 | fhc_ranges_init(fhc); | ||
347 | |||
348 | /* Now, map in FHC register set. */ | ||
349 | pr = of_get_property(fp, "reg", NULL); | ||
350 | if (!pr) | ||
351 | central_probe_failure(__LINE__); | ||
352 | memcpy(fpregs, pr, sizeof(fpregs)); | ||
353 | |||
354 | apply_central_ranges(central_bus, &fpregs[0], 6); | ||
355 | |||
356 | fhc->fhc_regs.pregs = prom_reg_to_paddr(&fpregs[0]); | ||
357 | fhc->fhc_regs.ireg = prom_reg_to_paddr(&fpregs[1]); | ||
358 | fhc->fhc_regs.ffregs = prom_reg_to_paddr(&fpregs[2]); | ||
359 | fhc->fhc_regs.sregs = prom_reg_to_paddr(&fpregs[3]); | ||
360 | fhc->fhc_regs.uregs = prom_reg_to_paddr(&fpregs[4]); | ||
361 | fhc->fhc_regs.tregs = prom_reg_to_paddr(&fpregs[5]); | ||
362 | |||
363 | /* Obtain board number from board status register, Central's | ||
364 | * FHC lacks "board#" property. | ||
365 | */ | ||
366 | err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_BSR); | ||
367 | fhc->board = (((err >> 16) & 0x01) | | ||
368 | ((err >> 12) & 0x0e)); | ||
369 | |||
370 | fhc->jtag_master = 0; | ||
371 | |||
372 | /* Attach the clock board registers for CENTRAL. */ | ||
373 | probe_clock_board(central_bus, fhc, fp); | ||
374 | |||
375 | err = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_ID); | ||
376 | printk("FHC(board %d): Version[%x] PartID[%x] Manuf[%x] (CENTRAL)\n", | ||
377 | fhc->board, | ||
378 | ((err & FHC_ID_VERS) >> 28), | ||
379 | ((err & FHC_ID_PARTID) >> 12), | ||
380 | ((err & FHC_ID_MANUF) >> 1)); | ||
381 | |||
382 | probe_other_fhcs(); | ||
383 | |||
384 | init_all_fhc_hw(); | ||
385 | } | ||
386 | 192 | ||
387 | static inline void fhc_ledblink(struct linux_fhc *fhc, int on) | 193 | if (!p->central) { |
388 | { | 194 | p->leds_resource.start = (unsigned long) |
389 | u32 tmp; | 195 | (p->pregs + FHC_PREGS_CTRL); |
196 | p->leds_resource.end = p->leds_resource.end; | ||
197 | p->leds_resource.name = "leds"; | ||
198 | |||
199 | p->leds_pdev.name = "sunfire-fhc-leds"; | ||
200 | p->leds_pdev.resource = &p->leds_resource; | ||
201 | p->leds_pdev.num_resources = 1; | ||
202 | p->leds_pdev.dev.parent = &op->dev; | ||
203 | |||
204 | err = platform_device_register(&p->leds_pdev); | ||
205 | if (err) { | ||
206 | printk(KERN_ERR "fhc: Could not register LEDS " | ||
207 | "platform device\n"); | ||
208 | goto out_unmap_pregs; | ||
209 | } | ||
210 | } | ||
211 | reg = upa_readl(p->pregs + FHC_PREGS_CTRL); | ||
390 | 212 | ||
391 | tmp = upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | 213 | if (!p->central) |
214 | reg |= FHC_CONTROL_IXIST; | ||
392 | 215 | ||
393 | /* NOTE: reverse logic on this bit */ | 216 | reg &= ~(FHC_CONTROL_AOFF | |
394 | if (on) | 217 | FHC_CONTROL_BOFF | |
395 | tmp &= ~(FHC_CONTROL_RLED); | 218 | FHC_CONTROL_SLINE); |
396 | else | ||
397 | tmp |= FHC_CONTROL_RLED; | ||
398 | tmp &= ~(FHC_CONTROL_AOFF | FHC_CONTROL_BOFF | FHC_CONTROL_SLINE); | ||
399 | 219 | ||
400 | upa_writel(tmp, fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | 220 | upa_writel(reg, p->pregs + FHC_PREGS_CTRL); |
401 | upa_readl(fhc->fhc_regs.pregs + FHC_PREGS_CTRL); | 221 | upa_readl(p->pregs + FHC_PREGS_CTRL); |
402 | } | ||
403 | 222 | ||
404 | static inline void central_ledblink(struct linux_central *central, int on) | 223 | reg = upa_readl(p->pregs + FHC_PREGS_ID); |
405 | { | 224 | printk(KERN_INFO "fhc: Board #%d, Version[%x] PartID[%x] Manuf[%x] %s\n", |
406 | u8 tmp; | 225 | p->board_num, |
407 | 226 | (reg & FHC_ID_VERS) >> 28, | |
408 | tmp = upa_readb(central->clkregs + CLOCK_CTRL); | 227 | (reg & FHC_ID_PARTID) >> 12, |
228 | (reg & FHC_ID_MANUF) >> 1, | ||
229 | (p->jtag_master ? | ||
230 | "(JTAG Master)" : | ||
231 | (p->central ? "(Central)" : ""))); | ||
409 | 232 | ||
410 | /* NOTE: reverse logic on this bit */ | 233 | err = 0; |
411 | if (on) | ||
412 | tmp &= ~(CLOCK_CTRL_RLED); | ||
413 | else | ||
414 | tmp |= CLOCK_CTRL_RLED; | ||
415 | 234 | ||
416 | upa_writeb(tmp, central->clkregs + CLOCK_CTRL); | 235 | out: |
417 | upa_readb(central->clkregs + CLOCK_CTRL); | 236 | return err; |
418 | } | ||
419 | 237 | ||
420 | static struct timer_list sftimer; | 238 | out_unmap_pregs: |
421 | static int led_state; | 239 | of_iounmap(&op->resource[0], p->pregs, resource_size(&op->resource[0])); |
422 | 240 | ||
423 | static void sunfire_timer(unsigned long __ignored) | 241 | out_free: |
424 | { | 242 | kfree(p); |
425 | struct linux_fhc *fhc; | 243 | goto out; |
426 | |||
427 | central_ledblink(central_bus, led_state); | ||
428 | for (fhc = fhc_list; fhc != NULL; fhc = fhc->next) | ||
429 | if (! IS_CENTRAL_FHC(fhc)) | ||
430 | fhc_ledblink(fhc, led_state); | ||
431 | led_state = ! led_state; | ||
432 | sftimer.expires = jiffies + (HZ >> 1); | ||
433 | add_timer(&sftimer); | ||
434 | } | 244 | } |
435 | 245 | ||
436 | /* After PCI/SBUS busses have been probed, this is called to perform | 246 | static struct of_device_id __initdata fhc_match[] = { |
437 | * final initialization of all FireHose Controllers in the system. | 247 | { |
438 | */ | 248 | .name = "fhc", |
439 | void firetruck_init(void) | 249 | }, |
250 | {}, | ||
251 | }; | ||
252 | |||
253 | static struct of_platform_driver fhc_driver = { | ||
254 | .match_table = fhc_match, | ||
255 | .probe = fhc_probe, | ||
256 | .driver = { | ||
257 | .name = "fhc", | ||
258 | }, | ||
259 | }; | ||
260 | |||
261 | static int __init sunfire_init(void) | ||
440 | { | 262 | { |
441 | struct linux_central *central = central_bus; | 263 | (void) of_register_driver(&fhc_driver, &of_platform_bus_type); |
442 | u8 ctrl; | 264 | (void) of_register_driver(&clock_board_driver, &of_platform_bus_type); |
443 | 265 | return 0; | |
444 | /* No central bus, nothing to do. */ | ||
445 | if (central == NULL) | ||
446 | return; | ||
447 | |||
448 | /* OBP leaves it on, turn it off so clock board timer LED | ||
449 | * is in sync with FHC ones. | ||
450 | */ | ||
451 | ctrl = upa_readb(central->clkregs + CLOCK_CTRL); | ||
452 | ctrl &= ~(CLOCK_CTRL_RLED); | ||
453 | upa_writeb(ctrl, central->clkregs + CLOCK_CTRL); | ||
454 | |||
455 | led_state = 0; | ||
456 | init_timer(&sftimer); | ||
457 | sftimer.data = 0; | ||
458 | sftimer.function = &sunfire_timer; | ||
459 | sftimer.expires = jiffies + (HZ >> 1); | ||
460 | add_timer(&sftimer); | ||
461 | } | 266 | } |
267 | |||
268 | subsys_initcall(sunfire_init); | ||
diff --git a/arch/sparc64/kernel/chmc.c b/arch/sparc64/kernel/chmc.c index 6d4f02e8a4cf..967b04886822 100644 --- a/arch/sparc64/kernel/chmc.c +++ b/arch/sparc64/kernel/chmc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* memctrlr.c: Driver for UltraSPARC-III memory controller. | 1 | /* chmc.c: Driver for UltraSPARC-III memory controller. |
2 | * | 2 | * |
3 | * Copyright (C) 2001, 2007 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 2001, 2007, 2008 David S. Miller (davem@davemloft.net) |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/module.h> | 6 | #include <linux/module.h> |
@@ -13,45 +13,64 @@ | |||
13 | #include <linux/smp.h> | 13 | #include <linux/smp.h> |
14 | #include <linux/errno.h> | 14 | #include <linux/errno.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/of.h> | ||
17 | #include <linux/of_device.h> | ||
16 | #include <asm/spitfire.h> | 18 | #include <asm/spitfire.h> |
17 | #include <asm/chmctrl.h> | 19 | #include <asm/chmctrl.h> |
18 | #include <asm/cpudata.h> | 20 | #include <asm/cpudata.h> |
19 | #include <asm/oplib.h> | 21 | #include <asm/oplib.h> |
20 | #include <asm/prom.h> | 22 | #include <asm/prom.h> |
23 | #include <asm/head.h> | ||
21 | #include <asm/io.h> | 24 | #include <asm/io.h> |
25 | #include <asm/memctrl.h> | ||
26 | |||
27 | #define DRV_MODULE_NAME "chmc" | ||
28 | #define PFX DRV_MODULE_NAME ": " | ||
29 | #define DRV_MODULE_VERSION "0.2" | ||
30 | |||
31 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | ||
32 | MODULE_DESCRIPTION("UltraSPARC-III memory controller driver"); | ||
33 | MODULE_LICENSE("GPL"); | ||
34 | MODULE_VERSION(DRV_MODULE_VERSION); | ||
35 | |||
36 | static int mc_type; | ||
37 | #define MC_TYPE_SAFARI 1 | ||
38 | #define MC_TYPE_JBUS 2 | ||
39 | |||
40 | static dimm_printer_t us3mc_dimm_printer; | ||
22 | 41 | ||
23 | #define CHMCTRL_NDGRPS 2 | 42 | #define CHMCTRL_NDGRPS 2 |
24 | #define CHMCTRL_NDIMMS 4 | 43 | #define CHMCTRL_NDIMMS 4 |
25 | 44 | ||
26 | #define DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) | 45 | #define CHMC_DIMMS_PER_MC (CHMCTRL_NDGRPS * CHMCTRL_NDIMMS) |
27 | 46 | ||
28 | /* OBP memory-layout property format. */ | 47 | /* OBP memory-layout property format. */ |
29 | struct obp_map { | 48 | struct chmc_obp_map { |
30 | unsigned char dimm_map[144]; | 49 | unsigned char dimm_map[144]; |
31 | unsigned char pin_map[576]; | 50 | unsigned char pin_map[576]; |
32 | }; | 51 | }; |
33 | 52 | ||
34 | #define DIMM_LABEL_SZ 8 | 53 | #define DIMM_LABEL_SZ 8 |
35 | 54 | ||
36 | struct obp_mem_layout { | 55 | struct chmc_obp_mem_layout { |
37 | /* One max 8-byte string label per DIMM. Usually | 56 | /* One max 8-byte string label per DIMM. Usually |
38 | * this matches the label on the motherboard where | 57 | * this matches the label on the motherboard where |
39 | * that DIMM resides. | 58 | * that DIMM resides. |
40 | */ | 59 | */ |
41 | char dimm_labels[DIMMS_PER_MC][DIMM_LABEL_SZ]; | 60 | char dimm_labels[CHMC_DIMMS_PER_MC][DIMM_LABEL_SZ]; |
42 | 61 | ||
43 | /* If symmetric use map[0], else it is | 62 | /* If symmetric use map[0], else it is |
44 | * asymmetric and map[1] should be used. | 63 | * asymmetric and map[1] should be used. |
45 | */ | 64 | */ |
46 | char symmetric; | 65 | char symmetric; |
47 | 66 | ||
48 | struct obp_map map[2]; | 67 | struct chmc_obp_map map[2]; |
49 | }; | 68 | }; |
50 | 69 | ||
51 | #define CHMCTRL_NBANKS 4 | 70 | #define CHMCTRL_NBANKS 4 |
52 | 71 | ||
53 | struct bank_info { | 72 | struct chmc_bank_info { |
54 | struct mctrl_info *mp; | 73 | struct chmc *p; |
55 | int bank_id; | 74 | int bank_id; |
56 | 75 | ||
57 | u64 raw_reg; | 76 | u64 raw_reg; |
@@ -65,28 +84,406 @@ struct bank_info { | |||
65 | unsigned long size; | 84 | unsigned long size; |
66 | }; | 85 | }; |
67 | 86 | ||
68 | struct mctrl_info { | 87 | struct chmc { |
69 | struct list_head list; | 88 | struct list_head list; |
70 | int portid; | 89 | int portid; |
90 | |||
91 | struct chmc_obp_mem_layout layout_prop; | ||
92 | int layout_size; | ||
93 | |||
94 | void __iomem *regs; | ||
71 | 95 | ||
72 | struct obp_mem_layout layout_prop; | 96 | u64 timing_control1; |
73 | int layout_size; | 97 | u64 timing_control2; |
98 | u64 timing_control3; | ||
99 | u64 timing_control4; | ||
100 | u64 memaddr_control; | ||
74 | 101 | ||
75 | void __iomem *regs; | 102 | struct chmc_bank_info logical_banks[CHMCTRL_NBANKS]; |
103 | }; | ||
104 | |||
105 | #define JBUSMC_REGS_SIZE 8 | ||
106 | |||
107 | #define JB_MC_REG1_DIMM2_BANK3 0x8000000000000000UL | ||
108 | #define JB_MC_REG1_DIMM1_BANK1 0x4000000000000000UL | ||
109 | #define JB_MC_REG1_DIMM2_BANK2 0x2000000000000000UL | ||
110 | #define JB_MC_REG1_DIMM1_BANK0 0x1000000000000000UL | ||
111 | #define JB_MC_REG1_XOR 0x0000010000000000UL | ||
112 | #define JB_MC_REG1_ADDR_GEN_2 0x000000e000000000UL | ||
113 | #define JB_MC_REG1_ADDR_GEN_2_SHIFT 37 | ||
114 | #define JB_MC_REG1_ADDR_GEN_1 0x0000001c00000000UL | ||
115 | #define JB_MC_REG1_ADDR_GEN_1_SHIFT 34 | ||
116 | #define JB_MC_REG1_INTERLEAVE 0x0000000001800000UL | ||
117 | #define JB_MC_REG1_INTERLEAVE_SHIFT 23 | ||
118 | #define JB_MC_REG1_DIMM2_PTYPE 0x0000000000200000UL | ||
119 | #define JB_MC_REG1_DIMM2_PTYPE_SHIFT 21 | ||
120 | #define JB_MC_REG1_DIMM1_PTYPE 0x0000000000100000UL | ||
121 | #define JB_MC_REG1_DIMM1_PTYPE_SHIFT 20 | ||
122 | |||
123 | #define PART_TYPE_X8 0 | ||
124 | #define PART_TYPE_X4 1 | ||
125 | |||
126 | #define INTERLEAVE_NONE 0 | ||
127 | #define INTERLEAVE_SAME 1 | ||
128 | #define INTERLEAVE_INTERNAL 2 | ||
129 | #define INTERLEAVE_BOTH 3 | ||
130 | |||
131 | #define ADDR_GEN_128MB 0 | ||
132 | #define ADDR_GEN_256MB 1 | ||
133 | #define ADDR_GEN_512MB 2 | ||
134 | #define ADDR_GEN_1GB 3 | ||
135 | |||
136 | #define JB_NUM_DIMM_GROUPS 2 | ||
137 | #define JB_NUM_DIMMS_PER_GROUP 2 | ||
138 | #define JB_NUM_DIMMS (JB_NUM_DIMM_GROUPS * JB_NUM_DIMMS_PER_GROUP) | ||
139 | |||
140 | struct jbusmc_obp_map { | ||
141 | unsigned char dimm_map[18]; | ||
142 | unsigned char pin_map[144]; | ||
143 | }; | ||
144 | |||
145 | struct jbusmc_obp_mem_layout { | ||
146 | /* One max 8-byte string label per DIMM. Usually | ||
147 | * this matches the label on the motherboard where | ||
148 | * that DIMM resides. | ||
149 | */ | ||
150 | char dimm_labels[JB_NUM_DIMMS][DIMM_LABEL_SZ]; | ||
151 | |||
152 | /* If symmetric use map[0], else it is | ||
153 | * asymmetric and map[1] should be used. | ||
154 | */ | ||
155 | char symmetric; | ||
156 | |||
157 | struct jbusmc_obp_map map; | ||
158 | |||
159 | char _pad; | ||
160 | }; | ||
76 | 161 | ||
77 | u64 timing_control1; | 162 | struct jbusmc_dimm_group { |
78 | u64 timing_control2; | 163 | struct jbusmc *controller; |
79 | u64 timing_control3; | 164 | int index; |
80 | u64 timing_control4; | 165 | u64 base_addr; |
81 | u64 memaddr_control; | 166 | u64 size; |
167 | }; | ||
82 | 168 | ||
83 | struct bank_info logical_banks[CHMCTRL_NBANKS]; | 169 | struct jbusmc { |
170 | void __iomem *regs; | ||
171 | u64 mc_reg_1; | ||
172 | u32 portid; | ||
173 | struct jbusmc_obp_mem_layout layout; | ||
174 | int layout_len; | ||
175 | int num_dimm_groups; | ||
176 | struct jbusmc_dimm_group dimm_groups[JB_NUM_DIMM_GROUPS]; | ||
177 | struct list_head list; | ||
84 | }; | 178 | }; |
85 | 179 | ||
180 | static DEFINE_SPINLOCK(mctrl_list_lock); | ||
86 | static LIST_HEAD(mctrl_list); | 181 | static LIST_HEAD(mctrl_list); |
87 | 182 | ||
183 | static void mc_list_add(struct list_head *list) | ||
184 | { | ||
185 | spin_lock(&mctrl_list_lock); | ||
186 | list_add(list, &mctrl_list); | ||
187 | spin_unlock(&mctrl_list_lock); | ||
188 | } | ||
189 | |||
190 | static void mc_list_del(struct list_head *list) | ||
191 | { | ||
192 | spin_lock(&mctrl_list_lock); | ||
193 | list_del_init(list); | ||
194 | spin_unlock(&mctrl_list_lock); | ||
195 | } | ||
196 | |||
197 | #define SYNDROME_MIN -1 | ||
198 | #define SYNDROME_MAX 144 | ||
199 | |||
200 | /* Covert syndrome code into the way the bits are positioned | ||
201 | * on the bus. | ||
202 | */ | ||
203 | static int syndrome_to_qword_code(int syndrome_code) | ||
204 | { | ||
205 | if (syndrome_code < 128) | ||
206 | syndrome_code += 16; | ||
207 | else if (syndrome_code < 128 + 9) | ||
208 | syndrome_code -= (128 - 7); | ||
209 | else if (syndrome_code < (128 + 9 + 3)) | ||
210 | syndrome_code -= (128 + 9 - 4); | ||
211 | else | ||
212 | syndrome_code -= (128 + 9 + 3); | ||
213 | return syndrome_code; | ||
214 | } | ||
215 | |||
216 | /* All this magic has to do with how a cache line comes over the wire | ||
217 | * on Safari and JBUS. A 64-bit line comes over in 1 or more quadword | ||
218 | * cycles, each of which transmit ECC/MTAG info as well as the actual | ||
219 | * data. | ||
220 | */ | ||
221 | #define L2_LINE_SIZE 64 | ||
222 | #define L2_LINE_ADDR_MSK (L2_LINE_SIZE - 1) | ||
223 | #define QW_PER_LINE 4 | ||
224 | #define QW_BYTES (L2_LINE_SIZE / QW_PER_LINE) | ||
225 | #define QW_BITS 144 | ||
226 | #define SAFARI_LAST_BIT (576 - 1) | ||
227 | #define JBUS_LAST_BIT (144 - 1) | ||
228 | |||
229 | static void get_pin_and_dimm_str(int syndrome_code, unsigned long paddr, | ||
230 | int *pin_p, char **dimm_str_p, void *_prop, | ||
231 | int base_dimm_offset) | ||
232 | { | ||
233 | int qword_code = syndrome_to_qword_code(syndrome_code); | ||
234 | int cache_line_offset; | ||
235 | int offset_inverse; | ||
236 | int dimm_map_index; | ||
237 | int map_val; | ||
238 | |||
239 | if (mc_type == MC_TYPE_JBUS) { | ||
240 | struct jbusmc_obp_mem_layout *p = _prop; | ||
241 | |||
242 | /* JBUS */ | ||
243 | cache_line_offset = qword_code; | ||
244 | offset_inverse = (JBUS_LAST_BIT - cache_line_offset); | ||
245 | dimm_map_index = offset_inverse / 8; | ||
246 | map_val = p->map.dimm_map[dimm_map_index]; | ||
247 | map_val = ((map_val >> ((7 - (offset_inverse & 7)))) & 1); | ||
248 | *dimm_str_p = p->dimm_labels[base_dimm_offset + map_val]; | ||
249 | *pin_p = p->map.pin_map[cache_line_offset]; | ||
250 | } else { | ||
251 | struct chmc_obp_mem_layout *p = _prop; | ||
252 | struct chmc_obp_map *mp; | ||
253 | int qword; | ||
254 | |||
255 | /* Safari */ | ||
256 | if (p->symmetric) | ||
257 | mp = &p->map[0]; | ||
258 | else | ||
259 | mp = &p->map[1]; | ||
260 | |||
261 | qword = (paddr & L2_LINE_ADDR_MSK) / QW_BYTES; | ||
262 | cache_line_offset = ((3 - qword) * QW_BITS) + qword_code; | ||
263 | offset_inverse = (SAFARI_LAST_BIT - cache_line_offset); | ||
264 | dimm_map_index = offset_inverse >> 2; | ||
265 | map_val = mp->dimm_map[dimm_map_index]; | ||
266 | map_val = ((map_val >> ((3 - (offset_inverse & 3)) << 1)) & 0x3); | ||
267 | *dimm_str_p = p->dimm_labels[base_dimm_offset + map_val]; | ||
268 | *pin_p = mp->pin_map[cache_line_offset]; | ||
269 | } | ||
270 | } | ||
271 | |||
272 | static struct jbusmc_dimm_group *jbusmc_find_dimm_group(unsigned long phys_addr) | ||
273 | { | ||
274 | struct jbusmc *p; | ||
275 | |||
276 | list_for_each_entry(p, &mctrl_list, list) { | ||
277 | int i; | ||
278 | |||
279 | for (i = 0; i < p->num_dimm_groups; i++) { | ||
280 | struct jbusmc_dimm_group *dp = &p->dimm_groups[i]; | ||
281 | |||
282 | if (phys_addr < dp->base_addr || | ||
283 | (dp->base_addr + dp->size) <= phys_addr) | ||
284 | continue; | ||
285 | |||
286 | return dp; | ||
287 | } | ||
288 | } | ||
289 | return NULL; | ||
290 | } | ||
291 | |||
292 | static int jbusmc_print_dimm(int syndrome_code, | ||
293 | unsigned long phys_addr, | ||
294 | char *buf, int buflen) | ||
295 | { | ||
296 | struct jbusmc_obp_mem_layout *prop; | ||
297 | struct jbusmc_dimm_group *dp; | ||
298 | struct jbusmc *p; | ||
299 | int first_dimm; | ||
300 | |||
301 | dp = jbusmc_find_dimm_group(phys_addr); | ||
302 | if (dp == NULL || | ||
303 | syndrome_code < SYNDROME_MIN || | ||
304 | syndrome_code > SYNDROME_MAX) { | ||
305 | buf[0] = '?'; | ||
306 | buf[1] = '?'; | ||
307 | buf[2] = '?'; | ||
308 | buf[3] = '\0'; | ||
309 | } | ||
310 | p = dp->controller; | ||
311 | prop = &p->layout; | ||
312 | |||
313 | first_dimm = dp->index * JB_NUM_DIMMS_PER_GROUP; | ||
314 | |||
315 | if (syndrome_code != SYNDROME_MIN) { | ||
316 | char *dimm_str; | ||
317 | int pin; | ||
318 | |||
319 | get_pin_and_dimm_str(syndrome_code, phys_addr, &pin, | ||
320 | &dimm_str, prop, first_dimm); | ||
321 | sprintf(buf, "%s, pin %3d", dimm_str, pin); | ||
322 | } else { | ||
323 | int dimm; | ||
324 | |||
325 | /* Multi-bit error, we just dump out all the | ||
326 | * dimm labels associated with this dimm group. | ||
327 | */ | ||
328 | for (dimm = 0; dimm < JB_NUM_DIMMS_PER_GROUP; dimm++) { | ||
329 | sprintf(buf, "%s ", | ||
330 | prop->dimm_labels[first_dimm + dimm]); | ||
331 | buf += strlen(buf); | ||
332 | } | ||
333 | } | ||
334 | |||
335 | return 0; | ||
336 | } | ||
337 | |||
338 | static u64 __devinit jbusmc_dimm_group_size(u64 base, | ||
339 | const struct linux_prom64_registers *mem_regs, | ||
340 | int num_mem_regs) | ||
341 | { | ||
342 | u64 max = base + (8UL * 1024 * 1024 * 1024); | ||
343 | u64 max_seen = base; | ||
344 | int i; | ||
345 | |||
346 | for (i = 0; i < num_mem_regs; i++) { | ||
347 | const struct linux_prom64_registers *ent; | ||
348 | u64 this_base; | ||
349 | u64 this_end; | ||
350 | |||
351 | ent = &mem_regs[i]; | ||
352 | this_base = ent->phys_addr; | ||
353 | this_end = this_base + ent->reg_size; | ||
354 | if (base < this_base || base >= this_end) | ||
355 | continue; | ||
356 | if (this_end > max) | ||
357 | this_end = max; | ||
358 | if (this_end > max_seen) | ||
359 | max_seen = this_end; | ||
360 | } | ||
361 | |||
362 | return max_seen - base; | ||
363 | } | ||
364 | |||
365 | static void __devinit jbusmc_construct_one_dimm_group(struct jbusmc *p, | ||
366 | unsigned long index, | ||
367 | const struct linux_prom64_registers *mem_regs, | ||
368 | int num_mem_regs) | ||
369 | { | ||
370 | struct jbusmc_dimm_group *dp = &p->dimm_groups[index]; | ||
371 | |||
372 | dp->controller = p; | ||
373 | dp->index = index; | ||
374 | |||
375 | dp->base_addr = (p->portid * (64UL * 1024 * 1024 * 1024)); | ||
376 | dp->base_addr += (index * (8UL * 1024 * 1024 * 1024)); | ||
377 | dp->size = jbusmc_dimm_group_size(dp->base_addr, mem_regs, num_mem_regs); | ||
378 | } | ||
379 | |||
380 | static void __devinit jbusmc_construct_dimm_groups(struct jbusmc *p, | ||
381 | const struct linux_prom64_registers *mem_regs, | ||
382 | int num_mem_regs) | ||
383 | { | ||
384 | if (p->mc_reg_1 & JB_MC_REG1_DIMM1_BANK0) { | ||
385 | jbusmc_construct_one_dimm_group(p, 0, mem_regs, num_mem_regs); | ||
386 | p->num_dimm_groups++; | ||
387 | } | ||
388 | if (p->mc_reg_1 & JB_MC_REG1_DIMM2_BANK2) { | ||
389 | jbusmc_construct_one_dimm_group(p, 1, mem_regs, num_mem_regs); | ||
390 | p->num_dimm_groups++; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | static int __devinit jbusmc_probe(struct of_device *op, | ||
395 | const struct of_device_id *match) | ||
396 | { | ||
397 | const struct linux_prom64_registers *mem_regs; | ||
398 | struct device_node *mem_node; | ||
399 | int err, len, num_mem_regs; | ||
400 | struct jbusmc *p; | ||
401 | const u32 *prop; | ||
402 | const void *ml; | ||
403 | |||
404 | err = -ENODEV; | ||
405 | mem_node = of_find_node_by_path("/memory"); | ||
406 | if (!mem_node) { | ||
407 | printk(KERN_ERR PFX "Cannot find /memory node.\n"); | ||
408 | goto out; | ||
409 | } | ||
410 | mem_regs = of_get_property(mem_node, "reg", &len); | ||
411 | if (!mem_regs) { | ||
412 | printk(KERN_ERR PFX "Cannot get reg property of /memory node.\n"); | ||
413 | goto out; | ||
414 | } | ||
415 | num_mem_regs = len / sizeof(*mem_regs); | ||
416 | |||
417 | err = -ENOMEM; | ||
418 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
419 | if (!p) { | ||
420 | printk(KERN_ERR PFX "Cannot allocate struct jbusmc.\n"); | ||
421 | goto out; | ||
422 | } | ||
423 | |||
424 | INIT_LIST_HEAD(&p->list); | ||
425 | |||
426 | err = -ENODEV; | ||
427 | prop = of_get_property(op->node, "portid", &len); | ||
428 | if (!prop || len != 4) { | ||
429 | printk(KERN_ERR PFX "Cannot find portid.\n"); | ||
430 | goto out_free; | ||
431 | } | ||
432 | |||
433 | p->portid = *prop; | ||
434 | |||
435 | prop = of_get_property(op->node, "memory-control-register-1", &len); | ||
436 | if (!prop || len != 8) { | ||
437 | printk(KERN_ERR PFX "Cannot get memory control register 1.\n"); | ||
438 | goto out_free; | ||
439 | } | ||
440 | |||
441 | p->mc_reg_1 = ((u64)prop[0] << 32) | (u64) prop[1]; | ||
442 | |||
443 | err = -ENOMEM; | ||
444 | p->regs = of_ioremap(&op->resource[0], 0, JBUSMC_REGS_SIZE, "jbusmc"); | ||
445 | if (!p->regs) { | ||
446 | printk(KERN_ERR PFX "Cannot map jbusmc regs.\n"); | ||
447 | goto out_free; | ||
448 | } | ||
449 | |||
450 | err = -ENODEV; | ||
451 | ml = of_get_property(op->node, "memory-layout", &p->layout_len); | ||
452 | if (!ml) { | ||
453 | printk(KERN_ERR PFX "Cannot get memory layout property.\n"); | ||
454 | goto out_iounmap; | ||
455 | } | ||
456 | if (p->layout_len > sizeof(p->layout)) { | ||
457 | printk(KERN_ERR PFX "Unexpected memory-layout size %d\n", | ||
458 | p->layout_len); | ||
459 | goto out_iounmap; | ||
460 | } | ||
461 | memcpy(&p->layout, ml, p->layout_len); | ||
462 | |||
463 | jbusmc_construct_dimm_groups(p, mem_regs, num_mem_regs); | ||
464 | |||
465 | mc_list_add(&p->list); | ||
466 | |||
467 | printk(KERN_INFO PFX "UltraSPARC-IIIi memory controller at %s\n", | ||
468 | op->node->full_name); | ||
469 | |||
470 | dev_set_drvdata(&op->dev, p); | ||
471 | |||
472 | err = 0; | ||
473 | |||
474 | out: | ||
475 | return err; | ||
476 | |||
477 | out_iounmap: | ||
478 | of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE); | ||
479 | |||
480 | out_free: | ||
481 | kfree(p); | ||
482 | goto out; | ||
483 | } | ||
484 | |||
88 | /* Does BANK decode PHYS_ADDR? */ | 485 | /* Does BANK decode PHYS_ADDR? */ |
89 | static int bank_match(struct bank_info *bp, unsigned long phys_addr) | 486 | static int chmc_bank_match(struct chmc_bank_info *bp, unsigned long phys_addr) |
90 | { | 487 | { |
91 | unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT; | 488 | unsigned long upper_bits = (phys_addr & PA_UPPER_BITS) >> PA_UPPER_BITS_SHIFT; |
92 | unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT; | 489 | unsigned long lower_bits = (phys_addr & PA_LOWER_BITS) >> PA_LOWER_BITS_SHIFT; |
@@ -118,25 +515,18 @@ static int bank_match(struct bank_info *bp, unsigned long phys_addr) | |||
118 | } | 515 | } |
119 | 516 | ||
120 | /* Given PHYS_ADDR, search memory controller banks for a match. */ | 517 | /* Given PHYS_ADDR, search memory controller banks for a match. */ |
121 | static struct bank_info *find_bank(unsigned long phys_addr) | 518 | static struct chmc_bank_info *chmc_find_bank(unsigned long phys_addr) |
122 | { | 519 | { |
123 | struct list_head *mctrl_head = &mctrl_list; | 520 | struct chmc *p; |
124 | struct list_head *mctrl_entry = mctrl_head->next; | ||
125 | 521 | ||
126 | for (;;) { | 522 | list_for_each_entry(p, &mctrl_list, list) { |
127 | struct mctrl_info *mp = | ||
128 | list_entry(mctrl_entry, struct mctrl_info, list); | ||
129 | int bank_no; | 523 | int bank_no; |
130 | 524 | ||
131 | if (mctrl_entry == mctrl_head) | ||
132 | break; | ||
133 | mctrl_entry = mctrl_entry->next; | ||
134 | |||
135 | for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { | 525 | for (bank_no = 0; bank_no < CHMCTRL_NBANKS; bank_no++) { |
136 | struct bank_info *bp; | 526 | struct chmc_bank_info *bp; |
137 | 527 | ||
138 | bp = &mp->logical_banks[bank_no]; | 528 | bp = &p->logical_banks[bank_no]; |
139 | if (bank_match(bp, phys_addr)) | 529 | if (chmc_bank_match(bp, phys_addr)) |
140 | return bp; | 530 | return bp; |
141 | } | 531 | } |
142 | } | 532 | } |
@@ -145,17 +535,15 @@ static struct bank_info *find_bank(unsigned long phys_addr) | |||
145 | } | 535 | } |
146 | 536 | ||
147 | /* This is the main purpose of this driver. */ | 537 | /* This is the main purpose of this driver. */ |
148 | #define SYNDROME_MIN -1 | 538 | static int chmc_print_dimm(int syndrome_code, |
149 | #define SYNDROME_MAX 144 | 539 | unsigned long phys_addr, |
150 | int chmc_getunumber(int syndrome_code, | 540 | char *buf, int buflen) |
151 | unsigned long phys_addr, | ||
152 | char *buf, int buflen) | ||
153 | { | 541 | { |
154 | struct bank_info *bp; | 542 | struct chmc_bank_info *bp; |
155 | struct obp_mem_layout *prop; | 543 | struct chmc_obp_mem_layout *prop; |
156 | int bank_in_controller, first_dimm; | 544 | int bank_in_controller, first_dimm; |
157 | 545 | ||
158 | bp = find_bank(phys_addr); | 546 | bp = chmc_find_bank(phys_addr); |
159 | if (bp == NULL || | 547 | if (bp == NULL || |
160 | syndrome_code < SYNDROME_MIN || | 548 | syndrome_code < SYNDROME_MIN || |
161 | syndrome_code > SYNDROME_MAX) { | 549 | syndrome_code > SYNDROME_MAX) { |
@@ -166,60 +554,18 @@ int chmc_getunumber(int syndrome_code, | |||
166 | return 0; | 554 | return 0; |
167 | } | 555 | } |
168 | 556 | ||
169 | prop = &bp->mp->layout_prop; | 557 | prop = &bp->p->layout_prop; |
170 | bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1); | 558 | bank_in_controller = bp->bank_id & (CHMCTRL_NBANKS - 1); |
171 | first_dimm = (bank_in_controller & (CHMCTRL_NDGRPS - 1)); | 559 | first_dimm = (bank_in_controller & (CHMCTRL_NDGRPS - 1)); |
172 | first_dimm *= CHMCTRL_NDIMMS; | 560 | first_dimm *= CHMCTRL_NDIMMS; |
173 | 561 | ||
174 | if (syndrome_code != SYNDROME_MIN) { | 562 | if (syndrome_code != SYNDROME_MIN) { |
175 | struct obp_map *map; | 563 | char *dimm_str; |
176 | int qword, where_in_line, where, map_index, map_offset; | 564 | int pin; |
177 | unsigned int map_val; | ||
178 | 565 | ||
179 | /* Yaay, single bit error so we can figure out | 566 | get_pin_and_dimm_str(syndrome_code, phys_addr, &pin, |
180 | * the exact dimm. | 567 | &dimm_str, prop, first_dimm); |
181 | */ | 568 | sprintf(buf, "%s, pin %3d", dimm_str, pin); |
182 | if (prop->symmetric) | ||
183 | map = &prop->map[0]; | ||
184 | else | ||
185 | map = &prop->map[1]; | ||
186 | |||
187 | /* Covert syndrome code into the way the bits are | ||
188 | * positioned on the bus. | ||
189 | */ | ||
190 | if (syndrome_code < 144 - 16) | ||
191 | syndrome_code += 16; | ||
192 | else if (syndrome_code < 144) | ||
193 | syndrome_code -= (144 - 7); | ||
194 | else if (syndrome_code < (144 + 3)) | ||
195 | syndrome_code -= (144 + 3 - 4); | ||
196 | else | ||
197 | syndrome_code -= 144 + 3; | ||
198 | |||
199 | /* All this magic has to do with how a cache line | ||
200 | * comes over the wire on Safari. A 64-bit line | ||
201 | * comes over in 4 quadword cycles, each of which | ||
202 | * transmit ECC/MTAG info as well as the actual | ||
203 | * data. 144 bits per quadword, 576 total. | ||
204 | */ | ||
205 | #define LINE_SIZE 64 | ||
206 | #define LINE_ADDR_MSK (LINE_SIZE - 1) | ||
207 | #define QW_PER_LINE 4 | ||
208 | #define QW_BYTES (LINE_SIZE / QW_PER_LINE) | ||
209 | #define QW_BITS 144 | ||
210 | #define LAST_BIT (576 - 1) | ||
211 | |||
212 | qword = (phys_addr & LINE_ADDR_MSK) / QW_BYTES; | ||
213 | where_in_line = ((3 - qword) * QW_BITS) + syndrome_code; | ||
214 | where = (LAST_BIT - where_in_line); | ||
215 | map_index = where >> 2; | ||
216 | map_offset = where & 0x3; | ||
217 | map_val = map->dimm_map[map_index]; | ||
218 | map_val = ((map_val >> ((3 - map_offset) << 1)) & (2 - 1)); | ||
219 | |||
220 | sprintf(buf, "%s, pin %3d", | ||
221 | prop->dimm_labels[first_dimm + map_val], | ||
222 | map->pin_map[where_in_line]); | ||
223 | } else { | 569 | } else { |
224 | int dimm; | 570 | int dimm; |
225 | 571 | ||
@@ -240,7 +586,7 @@ int chmc_getunumber(int syndrome_code, | |||
240 | * the code is executing, you must use special ASI load/store else | 586 | * the code is executing, you must use special ASI load/store else |
241 | * you go through the global mapping. | 587 | * you go through the global mapping. |
242 | */ | 588 | */ |
243 | static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) | 589 | static u64 chmc_read_mcreg(struct chmc *p, unsigned long offset) |
244 | { | 590 | { |
245 | unsigned long ret, this_cpu; | 591 | unsigned long ret, this_cpu; |
246 | 592 | ||
@@ -248,14 +594,14 @@ static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) | |||
248 | 594 | ||
249 | this_cpu = real_hard_smp_processor_id(); | 595 | this_cpu = real_hard_smp_processor_id(); |
250 | 596 | ||
251 | if (mp->portid == this_cpu) { | 597 | if (p->portid == this_cpu) { |
252 | __asm__ __volatile__("ldxa [%1] %2, %0" | 598 | __asm__ __volatile__("ldxa [%1] %2, %0" |
253 | : "=r" (ret) | 599 | : "=r" (ret) |
254 | : "r" (offset), "i" (ASI_MCU_CTRL_REG)); | 600 | : "r" (offset), "i" (ASI_MCU_CTRL_REG)); |
255 | } else { | 601 | } else { |
256 | __asm__ __volatile__("ldxa [%1] %2, %0" | 602 | __asm__ __volatile__("ldxa [%1] %2, %0" |
257 | : "=r" (ret) | 603 | : "=r" (ret) |
258 | : "r" (mp->regs + offset), | 604 | : "r" (p->regs + offset), |
259 | "i" (ASI_PHYS_BYPASS_EC_E)); | 605 | "i" (ASI_PHYS_BYPASS_EC_E)); |
260 | } | 606 | } |
261 | 607 | ||
@@ -265,178 +611,253 @@ static u64 read_mcreg(struct mctrl_info *mp, unsigned long offset) | |||
265 | } | 611 | } |
266 | 612 | ||
267 | #if 0 /* currently unused */ | 613 | #if 0 /* currently unused */ |
268 | static void write_mcreg(struct mctrl_info *mp, unsigned long offset, u64 val) | 614 | static void chmc_write_mcreg(struct chmc *p, unsigned long offset, u64 val) |
269 | { | 615 | { |
270 | if (mp->portid == smp_processor_id()) { | 616 | if (p->portid == smp_processor_id()) { |
271 | __asm__ __volatile__("stxa %0, [%1] %2" | 617 | __asm__ __volatile__("stxa %0, [%1] %2" |
272 | : : "r" (val), | 618 | : : "r" (val), |
273 | "r" (offset), "i" (ASI_MCU_CTRL_REG)); | 619 | "r" (offset), "i" (ASI_MCU_CTRL_REG)); |
274 | } else { | 620 | } else { |
275 | __asm__ __volatile__("ldxa %0, [%1] %2" | 621 | __asm__ __volatile__("ldxa %0, [%1] %2" |
276 | : : "r" (val), | 622 | : : "r" (val), |
277 | "r" (mp->regs + offset), | 623 | "r" (p->regs + offset), |
278 | "i" (ASI_PHYS_BYPASS_EC_E)); | 624 | "i" (ASI_PHYS_BYPASS_EC_E)); |
279 | } | 625 | } |
280 | } | 626 | } |
281 | #endif | 627 | #endif |
282 | 628 | ||
283 | static void interpret_one_decode_reg(struct mctrl_info *mp, int which_bank, u64 val) | 629 | static void chmc_interpret_one_decode_reg(struct chmc *p, int which_bank, u64 val) |
284 | { | 630 | { |
285 | struct bank_info *p = &mp->logical_banks[which_bank]; | 631 | struct chmc_bank_info *bp = &p->logical_banks[which_bank]; |
286 | 632 | ||
287 | p->mp = mp; | 633 | bp->p = p; |
288 | p->bank_id = (CHMCTRL_NBANKS * mp->portid) + which_bank; | 634 | bp->bank_id = (CHMCTRL_NBANKS * p->portid) + which_bank; |
289 | p->raw_reg = val; | 635 | bp->raw_reg = val; |
290 | p->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; | 636 | bp->valid = (val & MEM_DECODE_VALID) >> MEM_DECODE_VALID_SHIFT; |
291 | p->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; | 637 | bp->uk = (val & MEM_DECODE_UK) >> MEM_DECODE_UK_SHIFT; |
292 | p->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; | 638 | bp->um = (val & MEM_DECODE_UM) >> MEM_DECODE_UM_SHIFT; |
293 | p->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; | 639 | bp->lk = (val & MEM_DECODE_LK) >> MEM_DECODE_LK_SHIFT; |
294 | p->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; | 640 | bp->lm = (val & MEM_DECODE_LM) >> MEM_DECODE_LM_SHIFT; |
295 | 641 | ||
296 | p->base = (p->um); | 642 | bp->base = (bp->um); |
297 | p->base &= ~(p->uk); | 643 | bp->base &= ~(bp->uk); |
298 | p->base <<= PA_UPPER_BITS_SHIFT; | 644 | bp->base <<= PA_UPPER_BITS_SHIFT; |
299 | 645 | ||
300 | switch(p->lk) { | 646 | switch(bp->lk) { |
301 | case 0xf: | 647 | case 0xf: |
302 | default: | 648 | default: |
303 | p->interleave = 1; | 649 | bp->interleave = 1; |
304 | break; | 650 | break; |
305 | 651 | ||
306 | case 0xe: | 652 | case 0xe: |
307 | p->interleave = 2; | 653 | bp->interleave = 2; |
308 | break; | 654 | break; |
309 | 655 | ||
310 | case 0xc: | 656 | case 0xc: |
311 | p->interleave = 4; | 657 | bp->interleave = 4; |
312 | break; | 658 | break; |
313 | 659 | ||
314 | case 0x8: | 660 | case 0x8: |
315 | p->interleave = 8; | 661 | bp->interleave = 8; |
316 | break; | 662 | break; |
317 | 663 | ||
318 | case 0x0: | 664 | case 0x0: |
319 | p->interleave = 16; | 665 | bp->interleave = 16; |
320 | break; | 666 | break; |
321 | }; | 667 | }; |
322 | 668 | ||
323 | /* UK[10] is reserved, and UK[11] is not set for the SDRAM | 669 | /* UK[10] is reserved, and UK[11] is not set for the SDRAM |
324 | * bank size definition. | 670 | * bank size definition. |
325 | */ | 671 | */ |
326 | p->size = (((unsigned long)p->uk & | 672 | bp->size = (((unsigned long)bp->uk & |
327 | ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; | 673 | ((1UL << 10UL) - 1UL)) + 1UL) << PA_UPPER_BITS_SHIFT; |
328 | p->size /= p->interleave; | 674 | bp->size /= bp->interleave; |
329 | } | 675 | } |
330 | 676 | ||
331 | static void fetch_decode_regs(struct mctrl_info *mp) | 677 | static void chmc_fetch_decode_regs(struct chmc *p) |
332 | { | 678 | { |
333 | if (mp->layout_size == 0) | 679 | if (p->layout_size == 0) |
334 | return; | 680 | return; |
335 | 681 | ||
336 | interpret_one_decode_reg(mp, 0, | 682 | chmc_interpret_one_decode_reg(p, 0, |
337 | read_mcreg(mp, CHMCTRL_DECODE1)); | 683 | chmc_read_mcreg(p, CHMCTRL_DECODE1)); |
338 | interpret_one_decode_reg(mp, 1, | 684 | chmc_interpret_one_decode_reg(p, 1, |
339 | read_mcreg(mp, CHMCTRL_DECODE2)); | 685 | chmc_read_mcreg(p, CHMCTRL_DECODE2)); |
340 | interpret_one_decode_reg(mp, 2, | 686 | chmc_interpret_one_decode_reg(p, 2, |
341 | read_mcreg(mp, CHMCTRL_DECODE3)); | 687 | chmc_read_mcreg(p, CHMCTRL_DECODE3)); |
342 | interpret_one_decode_reg(mp, 3, | 688 | chmc_interpret_one_decode_reg(p, 3, |
343 | read_mcreg(mp, CHMCTRL_DECODE4)); | 689 | chmc_read_mcreg(p, CHMCTRL_DECODE4)); |
344 | } | 690 | } |
345 | 691 | ||
346 | static int init_one_mctrl(struct device_node *dp) | 692 | static int __devinit chmc_probe(struct of_device *op, |
693 | const struct of_device_id *match) | ||
347 | { | 694 | { |
348 | struct mctrl_info *mp = kzalloc(sizeof(*mp), GFP_KERNEL); | 695 | struct device_node *dp = op->node; |
349 | int portid = of_getintprop_default(dp, "portid", -1); | 696 | unsigned long ver; |
350 | const struct linux_prom64_registers *regs; | ||
351 | const void *pval; | 697 | const void *pval; |
352 | int len; | 698 | int len, portid; |
699 | struct chmc *p; | ||
700 | int err; | ||
701 | |||
702 | err = -ENODEV; | ||
703 | __asm__ ("rdpr %%ver, %0" : "=r" (ver)); | ||
704 | if ((ver >> 32UL) == __JALAPENO_ID || | ||
705 | (ver >> 32UL) == __SERRANO_ID) | ||
706 | goto out; | ||
353 | 707 | ||
354 | if (!mp) | 708 | portid = of_getintprop_default(dp, "portid", -1); |
355 | return -1; | ||
356 | if (portid == -1) | 709 | if (portid == -1) |
357 | goto fail; | 710 | goto out; |
358 | 711 | ||
359 | mp->portid = portid; | ||
360 | pval = of_get_property(dp, "memory-layout", &len); | 712 | pval = of_get_property(dp, "memory-layout", &len); |
361 | mp->layout_size = len; | 713 | if (pval && len > sizeof(p->layout_prop)) { |
362 | if (!pval) | 714 | printk(KERN_ERR PFX "Unexpected memory-layout property " |
363 | mp->layout_size = 0; | 715 | "size %d.\n", len); |
364 | else { | 716 | goto out; |
365 | if (mp->layout_size > sizeof(mp->layout_prop)) | ||
366 | goto fail; | ||
367 | memcpy(&mp->layout_prop, pval, len); | ||
368 | } | 717 | } |
369 | 718 | ||
370 | regs = of_get_property(dp, "reg", NULL); | 719 | err = -ENOMEM; |
371 | if (!regs || regs->reg_size != 0x48) | 720 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
372 | goto fail; | 721 | if (!p) { |
722 | printk(KERN_ERR PFX "Could not allocate struct chmc.\n"); | ||
723 | goto out; | ||
724 | } | ||
373 | 725 | ||
374 | mp->regs = ioremap(regs->phys_addr, regs->reg_size); | 726 | p->portid = portid; |
375 | if (mp->regs == NULL) | 727 | p->layout_size = len; |
376 | goto fail; | 728 | if (!pval) |
729 | p->layout_size = 0; | ||
730 | else | ||
731 | memcpy(&p->layout_prop, pval, len); | ||
732 | |||
733 | p->regs = of_ioremap(&op->resource[0], 0, 0x48, "chmc"); | ||
734 | if (!p->regs) { | ||
735 | printk(KERN_ERR PFX "Could not map registers.\n"); | ||
736 | goto out_free; | ||
737 | } | ||
377 | 738 | ||
378 | if (mp->layout_size != 0UL) { | 739 | if (p->layout_size != 0UL) { |
379 | mp->timing_control1 = read_mcreg(mp, CHMCTRL_TCTRL1); | 740 | p->timing_control1 = chmc_read_mcreg(p, CHMCTRL_TCTRL1); |
380 | mp->timing_control2 = read_mcreg(mp, CHMCTRL_TCTRL2); | 741 | p->timing_control2 = chmc_read_mcreg(p, CHMCTRL_TCTRL2); |
381 | mp->timing_control3 = read_mcreg(mp, CHMCTRL_TCTRL3); | 742 | p->timing_control3 = chmc_read_mcreg(p, CHMCTRL_TCTRL3); |
382 | mp->timing_control4 = read_mcreg(mp, CHMCTRL_TCTRL4); | 743 | p->timing_control4 = chmc_read_mcreg(p, CHMCTRL_TCTRL4); |
383 | mp->memaddr_control = read_mcreg(mp, CHMCTRL_MACTRL); | 744 | p->memaddr_control = chmc_read_mcreg(p, CHMCTRL_MACTRL); |
384 | } | 745 | } |
385 | 746 | ||
386 | fetch_decode_regs(mp); | 747 | chmc_fetch_decode_regs(p); |
387 | 748 | ||
388 | list_add(&mp->list, &mctrl_list); | 749 | mc_list_add(&p->list); |
389 | 750 | ||
390 | /* Report the device. */ | 751 | printk(KERN_INFO PFX "UltraSPARC-III memory controller at %s [%s]\n", |
391 | printk(KERN_INFO "%s: US3 memory controller at %p [%s]\n", | ||
392 | dp->full_name, | 752 | dp->full_name, |
393 | mp->regs, (mp->layout_size ? "ACTIVE" : "INACTIVE")); | 753 | (p->layout_size ? "ACTIVE" : "INACTIVE")); |
394 | 754 | ||
395 | return 0; | 755 | dev_set_drvdata(&op->dev, p); |
756 | |||
757 | err = 0; | ||
758 | |||
759 | out: | ||
760 | return err; | ||
761 | |||
762 | out_free: | ||
763 | kfree(p); | ||
764 | goto out; | ||
765 | } | ||
396 | 766 | ||
397 | fail: | 767 | static int __devinit us3mc_probe(struct of_device *op, |
398 | if (mp) { | 768 | const struct of_device_id *match) |
399 | if (mp->regs != NULL) | 769 | { |
400 | iounmap(mp->regs); | 770 | if (mc_type == MC_TYPE_SAFARI) |
401 | kfree(mp); | 771 | return chmc_probe(op, match); |
772 | else if (mc_type == MC_TYPE_JBUS) | ||
773 | return jbusmc_probe(op, match); | ||
774 | return -ENODEV; | ||
775 | } | ||
776 | |||
777 | static void __devexit chmc_destroy(struct of_device *op, struct chmc *p) | ||
778 | { | ||
779 | list_del(&p->list); | ||
780 | of_iounmap(&op->resource[0], p->regs, 0x48); | ||
781 | kfree(p); | ||
782 | } | ||
783 | |||
784 | static void __devexit jbusmc_destroy(struct of_device *op, struct jbusmc *p) | ||
785 | { | ||
786 | mc_list_del(&p->list); | ||
787 | of_iounmap(&op->resource[0], p->regs, JBUSMC_REGS_SIZE); | ||
788 | kfree(p); | ||
789 | } | ||
790 | |||
791 | static int __devexit us3mc_remove(struct of_device *op) | ||
792 | { | ||
793 | void *p = dev_get_drvdata(&op->dev); | ||
794 | |||
795 | if (p) { | ||
796 | if (mc_type == MC_TYPE_SAFARI) | ||
797 | chmc_destroy(op, p); | ||
798 | else if (mc_type == MC_TYPE_JBUS) | ||
799 | jbusmc_destroy(op, p); | ||
402 | } | 800 | } |
403 | return -1; | 801 | return 0; |
802 | } | ||
803 | |||
804 | static const struct of_device_id us3mc_match[] = { | ||
805 | { | ||
806 | .name = "memory-controller", | ||
807 | }, | ||
808 | {}, | ||
809 | }; | ||
810 | MODULE_DEVICE_TABLE(of, us3mc_match); | ||
811 | |||
812 | static struct of_platform_driver us3mc_driver = { | ||
813 | .name = "us3mc", | ||
814 | .match_table = us3mc_match, | ||
815 | .probe = us3mc_probe, | ||
816 | .remove = __devexit_p(us3mc_remove), | ||
817 | }; | ||
818 | |||
819 | static inline bool us3mc_platform(void) | ||
820 | { | ||
821 | if (tlb_type == cheetah || tlb_type == cheetah_plus) | ||
822 | return true; | ||
823 | return false; | ||
404 | } | 824 | } |
405 | 825 | ||
406 | static int __init chmc_init(void) | 826 | static int __init us3mc_init(void) |
407 | { | 827 | { |
408 | struct device_node *dp; | 828 | unsigned long ver; |
829 | int ret; | ||
409 | 830 | ||
410 | /* This driver is only for cheetah platforms. */ | 831 | if (!us3mc_platform()) |
411 | if (tlb_type != cheetah && tlb_type != cheetah_plus) | ||
412 | return -ENODEV; | 832 | return -ENODEV; |
413 | 833 | ||
414 | for_each_node_by_name(dp, "memory-controller") | 834 | __asm__ ("rdpr %%ver, %0" : "=r" (ver)); |
415 | init_one_mctrl(dp); | 835 | if ((ver >> 32UL) == __JALAPENO_ID || |
836 | (ver >> 32UL) == __SERRANO_ID) { | ||
837 | mc_type = MC_TYPE_JBUS; | ||
838 | us3mc_dimm_printer = jbusmc_print_dimm; | ||
839 | } else { | ||
840 | mc_type = MC_TYPE_SAFARI; | ||
841 | us3mc_dimm_printer = chmc_print_dimm; | ||
842 | } | ||
416 | 843 | ||
417 | for_each_node_by_name(dp, "mc-us3") | 844 | ret = register_dimm_printer(us3mc_dimm_printer); |
418 | init_one_mctrl(dp); | ||
419 | 845 | ||
420 | return 0; | 846 | if (!ret) { |
847 | ret = of_register_driver(&us3mc_driver, &of_bus_type); | ||
848 | if (ret) | ||
849 | unregister_dimm_printer(us3mc_dimm_printer); | ||
850 | } | ||
851 | return ret; | ||
421 | } | 852 | } |
422 | 853 | ||
423 | static void __exit chmc_cleanup(void) | 854 | static void __exit us3mc_cleanup(void) |
424 | { | 855 | { |
425 | struct list_head *head = &mctrl_list; | 856 | if (us3mc_platform()) { |
426 | struct list_head *tmp = head->next; | 857 | unregister_dimm_printer(us3mc_dimm_printer); |
427 | 858 | of_unregister_driver(&us3mc_driver); | |
428 | for (;;) { | ||
429 | struct mctrl_info *p = | ||
430 | list_entry(tmp, struct mctrl_info, list); | ||
431 | if (tmp == head) | ||
432 | break; | ||
433 | tmp = tmp->next; | ||
434 | |||
435 | list_del(&p->list); | ||
436 | iounmap(p->regs); | ||
437 | kfree(p); | ||
438 | } | 859 | } |
439 | } | 860 | } |
440 | 861 | ||
441 | module_init(chmc_init); | 862 | module_init(us3mc_init); |
442 | module_exit(chmc_cleanup); | 863 | module_exit(us3mc_cleanup); |
diff --git a/arch/sparc64/kernel/cpu.c b/arch/sparc64/kernel/cpu.c index 0097c08dc600..0c9ac83ed0a8 100644 --- a/arch/sparc64/kernel/cpu.c +++ b/arch/sparc64/kernel/cpu.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* cpu.c: Dinky routines to look for the kind of Sparc cpu | 1 | /* cpu.c: Dinky routines to look for the kind of Sparc cpu |
2 | * we are on. | 2 | * we are on. |
3 | * | 3 | * |
4 | * Copyright (C) 1996, 2007 David S. Miller (davem@davemloft.net) | 4 | * Copyright (C) 1996, 2007, 2008 David S. Miller (davem@davemloft.net) |
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
@@ -19,53 +19,86 @@ | |||
19 | 19 | ||
20 | DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; | 20 | DEFINE_PER_CPU(cpuinfo_sparc, __cpu_data) = { 0 }; |
21 | 21 | ||
22 | struct cpu_iu_info { | 22 | struct cpu_chip_info { |
23 | short manuf; | 23 | unsigned short manuf; |
24 | short impl; | 24 | unsigned short impl; |
25 | char* cpu_name; /* should be enough I hope... */ | 25 | const char *cpu_name; |
26 | const char *fp_name; | ||
26 | }; | 27 | }; |
27 | 28 | ||
28 | struct cpu_fp_info { | 29 | static const struct cpu_chip_info cpu_chips[] = { |
29 | short manuf; | 30 | { |
30 | short impl; | 31 | .manuf = 0x17, |
31 | char fpu_vers; | 32 | .impl = 0x10, |
32 | char* fp_name; | 33 | .cpu_name = "TI UltraSparc I (SpitFire)", |
34 | .fp_name = "UltraSparc I integrated FPU", | ||
35 | }, | ||
36 | { | ||
37 | .manuf = 0x22, | ||
38 | .impl = 0x10, | ||
39 | .cpu_name = "TI UltraSparc I (SpitFire)", | ||
40 | .fp_name = "UltraSparc I integrated FPU", | ||
41 | }, | ||
42 | { | ||
43 | .manuf = 0x17, | ||
44 | .impl = 0x11, | ||
45 | .cpu_name = "TI UltraSparc II (BlackBird)", | ||
46 | .fp_name = "UltraSparc II integrated FPU", | ||
47 | }, | ||
48 | { | ||
49 | .manuf = 0x17, | ||
50 | .impl = 0x12, | ||
51 | .cpu_name = "TI UltraSparc IIi (Sabre)", | ||
52 | .fp_name = "UltraSparc IIi integrated FPU", | ||
53 | }, | ||
54 | { | ||
55 | .manuf = 0x17, | ||
56 | .impl = 0x13, | ||
57 | .cpu_name = "TI UltraSparc IIe (Hummingbird)", | ||
58 | .fp_name = "UltraSparc IIe integrated FPU", | ||
59 | }, | ||
60 | { | ||
61 | .manuf = 0x3e, | ||
62 | .impl = 0x14, | ||
63 | .cpu_name = "TI UltraSparc III (Cheetah)", | ||
64 | .fp_name = "UltraSparc III integrated FPU", | ||
65 | }, | ||
66 | { | ||
67 | .manuf = 0x3e, | ||
68 | .impl = 0x15, | ||
69 | .cpu_name = "TI UltraSparc III+ (Cheetah+)", | ||
70 | .fp_name = "UltraSparc III+ integrated FPU", | ||
71 | }, | ||
72 | { | ||
73 | .manuf = 0x3e, | ||
74 | .impl = 0x16, | ||
75 | .cpu_name = "TI UltraSparc IIIi (Jalapeno)", | ||
76 | .fp_name = "UltraSparc IIIi integrated FPU", | ||
77 | }, | ||
78 | { | ||
79 | .manuf = 0x3e, | ||
80 | .impl = 0x18, | ||
81 | .cpu_name = "TI UltraSparc IV (Jaguar)", | ||
82 | .fp_name = "UltraSparc IV integrated FPU", | ||
83 | }, | ||
84 | { | ||
85 | .manuf = 0x3e, | ||
86 | .impl = 0x19, | ||
87 | .cpu_name = "TI UltraSparc IV+ (Panther)", | ||
88 | .fp_name = "UltraSparc IV+ integrated FPU", | ||
89 | }, | ||
90 | { | ||
91 | .manuf = 0x3e, | ||
92 | .impl = 0x22, | ||
93 | .cpu_name = "TI UltraSparc IIIi+ (Serrano)", | ||
94 | .fp_name = "UltraSparc IIIi+ integrated FPU", | ||
95 | }, | ||
33 | }; | 96 | }; |
34 | 97 | ||
35 | static struct cpu_fp_info linux_sparc_fpu[] = { | 98 | #define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) |
36 | { 0x17, 0x10, 0, "UltraSparc I integrated FPU"}, | ||
37 | { 0x22, 0x10, 0, "UltraSparc I integrated FPU"}, | ||
38 | { 0x17, 0x11, 0, "UltraSparc II integrated FPU"}, | ||
39 | { 0x17, 0x12, 0, "UltraSparc IIi integrated FPU"}, | ||
40 | { 0x17, 0x13, 0, "UltraSparc IIe integrated FPU"}, | ||
41 | { 0x3e, 0x14, 0, "UltraSparc III integrated FPU"}, | ||
42 | { 0x3e, 0x15, 0, "UltraSparc III+ integrated FPU"}, | ||
43 | { 0x3e, 0x16, 0, "UltraSparc IIIi integrated FPU"}, | ||
44 | { 0x3e, 0x18, 0, "UltraSparc IV integrated FPU"}, | ||
45 | { 0x3e, 0x19, 0, "UltraSparc IV+ integrated FPU"}, | ||
46 | { 0x3e, 0x22, 0, "UltraSparc IIIi+ integrated FPU"}, | ||
47 | }; | ||
48 | |||
49 | #define NSPARCFPU ARRAY_SIZE(linux_sparc_fpu) | ||
50 | |||
51 | static struct cpu_iu_info linux_sparc_chips[] = { | ||
52 | { 0x17, 0x10, "TI UltraSparc I (SpitFire)"}, | ||
53 | { 0x22, 0x10, "TI UltraSparc I (SpitFire)"}, | ||
54 | { 0x17, 0x11, "TI UltraSparc II (BlackBird)"}, | ||
55 | { 0x17, 0x12, "TI UltraSparc IIi (Sabre)"}, | ||
56 | { 0x17, 0x13, "TI UltraSparc IIe (Hummingbird)"}, | ||
57 | { 0x3e, 0x14, "TI UltraSparc III (Cheetah)"}, | ||
58 | { 0x3e, 0x15, "TI UltraSparc III+ (Cheetah+)"}, | ||
59 | { 0x3e, 0x16, "TI UltraSparc IIIi (Jalapeno)"}, | ||
60 | { 0x3e, 0x18, "TI UltraSparc IV (Jaguar)"}, | ||
61 | { 0x3e, 0x19, "TI UltraSparc IV+ (Panther)"}, | ||
62 | { 0x3e, 0x22, "TI UltraSparc IIIi+ (Serrano)"}, | ||
63 | }; | ||
64 | 99 | ||
65 | #define NSPARCCHIPS ARRAY_SIZE(linux_sparc_chips) | 100 | const char *sparc_cpu_type; |
66 | 101 | const char *sparc_fpu_type; | |
67 | char *sparc_cpu_type; | ||
68 | char *sparc_fpu_type; | ||
69 | 102 | ||
70 | static void __init sun4v_cpu_probe(void) | 103 | static void __init sun4v_cpu_probe(void) |
71 | { | 104 | { |
@@ -89,68 +122,45 @@ static void __init sun4v_cpu_probe(void) | |||
89 | } | 122 | } |
90 | } | 123 | } |
91 | 124 | ||
92 | void __init cpu_probe(void) | 125 | static const struct cpu_chip_info * __init find_cpu_chip(unsigned short manuf, |
126 | unsigned short impl) | ||
93 | { | 127 | { |
94 | unsigned long ver, fpu_vers, manuf, impl, fprs; | ||
95 | int i; | 128 | int i; |
96 | |||
97 | if (tlb_type == hypervisor) { | ||
98 | sun4v_cpu_probe(); | ||
99 | return; | ||
100 | } | ||
101 | 129 | ||
102 | fprs = fprs_read(); | 130 | for (i = 0; i < ARRAY_SIZE(cpu_chips); i++) { |
103 | fprs_write(FPRS_FEF); | 131 | const struct cpu_chip_info *p = &cpu_chips[i]; |
104 | __asm__ __volatile__ ("rdpr %%ver, %0; stx %%fsr, [%1]" | ||
105 | : "=&r" (ver) | ||
106 | : "r" (&fpu_vers)); | ||
107 | fprs_write(fprs); | ||
108 | |||
109 | manuf = ((ver >> 48) & 0xffff); | ||
110 | impl = ((ver >> 32) & 0xffff); | ||
111 | |||
112 | fpu_vers = ((fpu_vers >> 17) & 0x7); | ||
113 | |||
114 | retry: | ||
115 | for (i = 0; i < NSPARCCHIPS; i++) { | ||
116 | if (linux_sparc_chips[i].manuf == manuf) { | ||
117 | if (linux_sparc_chips[i].impl == impl) { | ||
118 | sparc_cpu_type = | ||
119 | linux_sparc_chips[i].cpu_name; | ||
120 | break; | ||
121 | } | ||
122 | } | ||
123 | } | ||
124 | 132 | ||
125 | if (i == NSPARCCHIPS) { | 133 | if (p->manuf == manuf && p->impl == impl) |
126 | /* Maybe it is a cheetah+ derivative, report it as cheetah+ | 134 | return p; |
127 | * in that case until we learn the real names. | ||
128 | */ | ||
129 | if (manuf == 0x3e && | ||
130 | impl > 0x15) { | ||
131 | impl = 0x15; | ||
132 | goto retry; | ||
133 | } else { | ||
134 | printk("DEBUG: manuf[%lx] impl[%lx]\n", | ||
135 | manuf, impl); | ||
136 | } | ||
137 | sparc_cpu_type = "Unknown CPU"; | ||
138 | } | 135 | } |
136 | return NULL; | ||
137 | } | ||
139 | 138 | ||
140 | for (i = 0; i < NSPARCFPU; i++) { | 139 | static int __init cpu_type_probe(void) |
141 | if (linux_sparc_fpu[i].manuf == manuf && | 140 | { |
142 | linux_sparc_fpu[i].impl == impl) { | 141 | if (tlb_type == hypervisor) { |
143 | if (linux_sparc_fpu[i].fpu_vers == fpu_vers) { | 142 | sun4v_cpu_probe(); |
144 | sparc_fpu_type = | 143 | } else { |
145 | linux_sparc_fpu[i].fp_name; | 144 | unsigned long ver, manuf, impl; |
146 | break; | 145 | const struct cpu_chip_info *p; |
147 | } | 146 | |
147 | __asm__ __volatile__("rdpr %%ver, %0" : "=r" (ver)); | ||
148 | |||
149 | manuf = ((ver >> 48) & 0xffff); | ||
150 | impl = ((ver >> 32) & 0xffff); | ||
151 | |||
152 | p = find_cpu_chip(manuf, impl); | ||
153 | if (p) { | ||
154 | sparc_cpu_type = p->cpu_name; | ||
155 | sparc_fpu_type = p->fp_name; | ||
156 | } else { | ||
157 | printk(KERN_ERR "CPU: Unknown chip, manuf[%lx] impl[%lx]\n", | ||
158 | manuf, impl); | ||
159 | sparc_cpu_type = "Unknown CPU"; | ||
160 | sparc_fpu_type = "Unknown FPU"; | ||
148 | } | 161 | } |
149 | } | 162 | } |
150 | 163 | return 0; | |
151 | if (i == NSPARCFPU) { | ||
152 | printk("DEBUG: manuf[%lx] impl[%lx] fsr.vers[%lx]\n", | ||
153 | manuf, impl, fpu_vers); | ||
154 | sparc_fpu_type = "Unknown FPU"; | ||
155 | } | ||
156 | } | 164 | } |
165 | |||
166 | arch_initcall(cpu_type_probe); | ||
diff --git a/arch/sparc64/kernel/ds.c b/arch/sparc64/kernel/ds.c index d0fa5aa38934..f52e0534d91d 100644 --- a/arch/sparc64/kernel/ds.c +++ b/arch/sparc64/kernel/ds.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* ds.c: Domain Services driver for Logical Domains | 1 | /* ds.c: Domain Services driver for Logical Domains |
2 | * | 2 | * |
3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
@@ -1217,7 +1217,7 @@ static int ds_remove(struct vio_dev *vdev) | |||
1217 | return 0; | 1217 | return 0; |
1218 | } | 1218 | } |
1219 | 1219 | ||
1220 | static struct vio_device_id ds_match[] = { | 1220 | static struct vio_device_id __initdata ds_match[] = { |
1221 | { | 1221 | { |
1222 | .type = "domain-services-port", | 1222 | .type = "domain-services-port", |
1223 | }, | 1223 | }, |
diff --git a/arch/sparc64/kernel/ebus.c b/arch/sparc64/kernel/ebus.c index 60d36d142559..77dbf6d45faf 100644 --- a/arch/sparc64/kernel/ebus.c +++ b/arch/sparc64/kernel/ebus.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* | 1 | /* ebus.c: EBUS DMA library code. |
2 | * ebus.c: PCI to EBus bridge device. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | 3 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) |
5 | * Copyright (C) 1999 David S. Miller (davem@redhat.com) | 4 | * Copyright (C) 1999 David S. Miller (davem@redhat.com) |
@@ -9,23 +8,11 @@ | |||
9 | #include <linux/kernel.h> | 8 | #include <linux/kernel.h> |
10 | #include <linux/types.h> | 9 | #include <linux/types.h> |
11 | #include <linux/init.h> | 10 | #include <linux/init.h> |
12 | #include <linux/slab.h> | ||
13 | #include <linux/string.h> | ||
14 | #include <linux/interrupt.h> | 11 | #include <linux/interrupt.h> |
15 | #include <linux/delay.h> | 12 | #include <linux/delay.h> |
16 | #include <linux/pci.h> | ||
17 | #include <linux/of_device.h> | ||
18 | |||
19 | #include <asm/system.h> | ||
20 | #include <asm/page.h> | ||
21 | #include <asm/ebus.h> | ||
22 | #include <asm/oplib.h> | ||
23 | #include <asm/prom.h> | ||
24 | #include <asm/bpp.h> | ||
25 | #include <asm/irq.h> | ||
26 | #include <asm/io.h> | ||
27 | 13 | ||
28 | /* EBUS dma library. */ | 14 | #include <asm/ebus_dma.h> |
15 | #include <asm/io.h> | ||
29 | 16 | ||
30 | #define EBDMA_CSR 0x00UL /* Control/Status */ | 17 | #define EBDMA_CSR 0x00UL /* Control/Status */ |
31 | #define EBDMA_ADDR 0x04UL /* DMA Address */ | 18 | #define EBDMA_ADDR 0x04UL /* DMA Address */ |
@@ -268,283 +255,3 @@ void ebus_dma_enable(struct ebus_dma_info *p, int on) | |||
268 | spin_unlock_irqrestore(&p->lock, flags); | 255 | spin_unlock_irqrestore(&p->lock, flags); |
269 | } | 256 | } |
270 | EXPORT_SYMBOL(ebus_dma_enable); | 257 | EXPORT_SYMBOL(ebus_dma_enable); |
271 | |||
272 | struct linux_ebus *ebus_chain = NULL; | ||
273 | |||
274 | static inline void *ebus_alloc(size_t size) | ||
275 | { | ||
276 | void *mem; | ||
277 | |||
278 | mem = kzalloc(size, GFP_ATOMIC); | ||
279 | if (!mem) | ||
280 | panic("ebus_alloc: out of memory"); | ||
281 | return mem; | ||
282 | } | ||
283 | |||
284 | static void __init fill_ebus_child(struct device_node *dp, | ||
285 | struct linux_ebus_child *dev, | ||
286 | int non_standard_regs) | ||
287 | { | ||
288 | struct of_device *op; | ||
289 | const int *regs; | ||
290 | int i, len; | ||
291 | |||
292 | dev->prom_node = dp; | ||
293 | printk(" (%s)", dp->name); | ||
294 | |||
295 | regs = of_get_property(dp, "reg", &len); | ||
296 | if (!regs) | ||
297 | dev->num_addrs = 0; | ||
298 | else | ||
299 | dev->num_addrs = len / sizeof(regs[0]); | ||
300 | |||
301 | if (non_standard_regs) { | ||
302 | /* This is to handle reg properties which are not | ||
303 | * in the parent relative format. One example are | ||
304 | * children of the i2c device on CompactPCI systems. | ||
305 | * | ||
306 | * So, for such devices we just record the property | ||
307 | * raw in the child resources. | ||
308 | */ | ||
309 | for (i = 0; i < dev->num_addrs; i++) | ||
310 | dev->resource[i].start = regs[i]; | ||
311 | } else { | ||
312 | for (i = 0; i < dev->num_addrs; i++) { | ||
313 | int rnum = regs[i]; | ||
314 | if (rnum >= dev->parent->num_addrs) { | ||
315 | prom_printf("UGH: property for %s was %d, need < %d\n", | ||
316 | dp->name, len, dev->parent->num_addrs); | ||
317 | prom_halt(); | ||
318 | } | ||
319 | dev->resource[i].start = dev->parent->resource[i].start; | ||
320 | dev->resource[i].end = dev->parent->resource[i].end; | ||
321 | dev->resource[i].flags = IORESOURCE_MEM; | ||
322 | dev->resource[i].name = dp->name; | ||
323 | } | ||
324 | } | ||
325 | |||
326 | op = of_find_device_by_node(dp); | ||
327 | if (!op) { | ||
328 | dev->num_irqs = 0; | ||
329 | } else { | ||
330 | dev->num_irqs = op->num_irqs; | ||
331 | for (i = 0; i < dev->num_irqs; i++) | ||
332 | dev->irqs[i] = op->irqs[i]; | ||
333 | } | ||
334 | |||
335 | if (!dev->num_irqs) { | ||
336 | /* | ||
337 | * Oh, well, some PROMs don't export interrupts | ||
338 | * property to children of EBus devices... | ||
339 | * | ||
340 | * Be smart about PS/2 keyboard and mouse. | ||
341 | */ | ||
342 | if (!strcmp(dev->parent->prom_node->name, "8042")) { | ||
343 | if (!strcmp(dev->prom_node->name, "kb_ps2")) { | ||
344 | dev->num_irqs = 1; | ||
345 | dev->irqs[0] = dev->parent->irqs[0]; | ||
346 | } else { | ||
347 | dev->num_irqs = 1; | ||
348 | dev->irqs[0] = dev->parent->irqs[1]; | ||
349 | } | ||
350 | } | ||
351 | } | ||
352 | } | ||
353 | |||
354 | static int __init child_regs_nonstandard(struct linux_ebus_device *dev) | ||
355 | { | ||
356 | if (!strcmp(dev->prom_node->name, "i2c") || | ||
357 | !strcmp(dev->prom_node->name, "SUNW,lombus")) | ||
358 | return 1; | ||
359 | return 0; | ||
360 | } | ||
361 | |||
362 | static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) | ||
363 | { | ||
364 | struct linux_ebus_child *child; | ||
365 | struct dev_archdata *sd; | ||
366 | struct of_device *op; | ||
367 | int i, len; | ||
368 | |||
369 | dev->prom_node = dp; | ||
370 | |||
371 | printk(" [%s", dp->name); | ||
372 | |||
373 | op = of_find_device_by_node(dp); | ||
374 | if (!op) { | ||
375 | dev->num_addrs = 0; | ||
376 | dev->num_irqs = 0; | ||
377 | } else { | ||
378 | const int *regs = of_get_property(dp, "reg", &len); | ||
379 | |||
380 | if (!regs) | ||
381 | len = 0; | ||
382 | dev->num_addrs = len / sizeof(struct linux_prom_registers); | ||
383 | |||
384 | for (i = 0; i < dev->num_addrs; i++) | ||
385 | memcpy(&dev->resource[i], | ||
386 | &op->resource[i], | ||
387 | sizeof(struct resource)); | ||
388 | |||
389 | dev->num_irqs = op->num_irqs; | ||
390 | for (i = 0; i < dev->num_irqs; i++) | ||
391 | dev->irqs[i] = op->irqs[i]; | ||
392 | } | ||
393 | |||
394 | sd = &dev->ofdev.dev.archdata; | ||
395 | sd->prom_node = dp; | ||
396 | sd->op = &dev->ofdev; | ||
397 | sd->iommu = dev->bus->ofdev.dev.parent->archdata.iommu; | ||
398 | sd->stc = dev->bus->ofdev.dev.parent->archdata.stc; | ||
399 | sd->numa_node = dev->bus->ofdev.dev.parent->archdata.numa_node; | ||
400 | |||
401 | dev->ofdev.node = dp; | ||
402 | dev->ofdev.dev.parent = &dev->bus->ofdev.dev; | ||
403 | dev->ofdev.dev.bus = &ebus_bus_type; | ||
404 | dev_set_name(&dev->ofdev.dev, "ebus[%08x]", dp->node); | ||
405 | |||
406 | /* Register with core */ | ||
407 | if (of_device_register(&dev->ofdev) != 0) | ||
408 | printk(KERN_DEBUG "ebus: device registration error for %s!\n", | ||
409 | dp->path_component_name); | ||
410 | |||
411 | dp = dp->child; | ||
412 | if (dp) { | ||
413 | printk(" ->"); | ||
414 | dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); | ||
415 | |||
416 | child = dev->children; | ||
417 | child->next = NULL; | ||
418 | child->parent = dev; | ||
419 | child->bus = dev->bus; | ||
420 | fill_ebus_child(dp, child, | ||
421 | child_regs_nonstandard(dev)); | ||
422 | |||
423 | while ((dp = dp->sibling) != NULL) { | ||
424 | child->next = ebus_alloc(sizeof(struct linux_ebus_child)); | ||
425 | |||
426 | child = child->next; | ||
427 | child->next = NULL; | ||
428 | child->parent = dev; | ||
429 | child->bus = dev->bus; | ||
430 | fill_ebus_child(dp, child, | ||
431 | child_regs_nonstandard(dev)); | ||
432 | } | ||
433 | } | ||
434 | printk("]"); | ||
435 | } | ||
436 | |||
437 | static struct pci_dev *find_next_ebus(struct pci_dev *start, int *is_rio_p) | ||
438 | { | ||
439 | struct pci_dev *pdev = start; | ||
440 | |||
441 | while ((pdev = pci_get_device(PCI_VENDOR_ID_SUN, PCI_ANY_ID, pdev))) | ||
442 | if (pdev->device == PCI_DEVICE_ID_SUN_EBUS || | ||
443 | pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS) | ||
444 | break; | ||
445 | |||
446 | *is_rio_p = !!(pdev && (pdev->device == PCI_DEVICE_ID_SUN_RIO_EBUS)); | ||
447 | |||
448 | return pdev; | ||
449 | } | ||
450 | |||
451 | void __init ebus_init(void) | ||
452 | { | ||
453 | struct linux_ebus_device *dev; | ||
454 | struct linux_ebus *ebus; | ||
455 | struct pci_dev *pdev; | ||
456 | struct device_node *dp; | ||
457 | int is_rio; | ||
458 | int num_ebus = 0; | ||
459 | |||
460 | pdev = find_next_ebus(NULL, &is_rio); | ||
461 | if (!pdev) { | ||
462 | printk("ebus: No EBus's found.\n"); | ||
463 | return; | ||
464 | } | ||
465 | |||
466 | dp = pci_device_to_OF_node(pdev); | ||
467 | |||
468 | ebus_chain = ebus = ebus_alloc(sizeof(struct linux_ebus)); | ||
469 | ebus->next = NULL; | ||
470 | ebus->is_rio = is_rio; | ||
471 | |||
472 | while (dp) { | ||
473 | struct device_node *child; | ||
474 | |||
475 | /* SUNW,pci-qfe uses four empty ebuses on it. | ||
476 | I think we should not consider them here, | ||
477 | as they have half of the properties this | ||
478 | code expects and once we do PCI hot-plug, | ||
479 | we'd have to tweak with the ebus_chain | ||
480 | in the runtime after initialization. -jj */ | ||
481 | if (!dp->child) { | ||
482 | pdev = find_next_ebus(pdev, &is_rio); | ||
483 | if (!pdev) { | ||
484 | if (ebus == ebus_chain) { | ||
485 | ebus_chain = NULL; | ||
486 | printk("ebus: No EBus's found.\n"); | ||
487 | return; | ||
488 | } | ||
489 | break; | ||
490 | } | ||
491 | ebus->is_rio = is_rio; | ||
492 | dp = pci_device_to_OF_node(pdev); | ||
493 | continue; | ||
494 | } | ||
495 | printk("ebus%d:", num_ebus); | ||
496 | |||
497 | ebus->index = num_ebus; | ||
498 | ebus->prom_node = dp; | ||
499 | ebus->self = pdev; | ||
500 | |||
501 | ebus->ofdev.node = dp; | ||
502 | ebus->ofdev.dev.parent = &pdev->dev; | ||
503 | ebus->ofdev.dev.bus = &ebus_bus_type; | ||
504 | dev_set_name(&ebus->ofdev.dev, "ebus%d", num_ebus); | ||
505 | |||
506 | /* Register with core */ | ||
507 | if (of_device_register(&ebus->ofdev) != 0) | ||
508 | printk(KERN_DEBUG "ebus: device registration error for %s!\n", | ||
509 | dp->path_component_name); | ||
510 | |||
511 | |||
512 | child = dp->child; | ||
513 | if (!child) | ||
514 | goto next_ebus; | ||
515 | |||
516 | ebus->devices = ebus_alloc(sizeof(struct linux_ebus_device)); | ||
517 | |||
518 | dev = ebus->devices; | ||
519 | dev->next = NULL; | ||
520 | dev->children = NULL; | ||
521 | dev->bus = ebus; | ||
522 | fill_ebus_device(child, dev); | ||
523 | |||
524 | while ((child = child->sibling) != NULL) { | ||
525 | dev->next = ebus_alloc(sizeof(struct linux_ebus_device)); | ||
526 | |||
527 | dev = dev->next; | ||
528 | dev->next = NULL; | ||
529 | dev->children = NULL; | ||
530 | dev->bus = ebus; | ||
531 | fill_ebus_device(child, dev); | ||
532 | } | ||
533 | |||
534 | next_ebus: | ||
535 | printk("\n"); | ||
536 | |||
537 | pdev = find_next_ebus(pdev, &is_rio); | ||
538 | if (!pdev) | ||
539 | break; | ||
540 | |||
541 | dp = pci_device_to_OF_node(pdev); | ||
542 | |||
543 | ebus->next = ebus_alloc(sizeof(struct linux_ebus)); | ||
544 | ebus = ebus->next; | ||
545 | ebus->next = NULL; | ||
546 | ebus->is_rio = is_rio; | ||
547 | ++num_ebus; | ||
548 | } | ||
549 | pci_dev_put(pdev); /* XXX for the case, when ebusnd is 0, is it OK? */ | ||
550 | } | ||
diff --git a/arch/sparc64/kernel/entry.h b/arch/sparc64/kernel/entry.h index fc294a292899..34d7ab5e10d2 100644 --- a/arch/sparc64/kernel/entry.h +++ b/arch/sparc64/kernel/entry.h | |||
@@ -5,8 +5,8 @@ | |||
5 | #include <linux/types.h> | 5 | #include <linux/types.h> |
6 | #include <linux/init.h> | 6 | #include <linux/init.h> |
7 | 7 | ||
8 | extern char *sparc_cpu_type; | 8 | extern const char *sparc_cpu_type; |
9 | extern char *sparc_fpu_type; | 9 | extern const char *sparc_fpu_type; |
10 | 10 | ||
11 | extern void __init per_cpu_patch(void); | 11 | extern void __init per_cpu_patch(void); |
12 | extern void __init sun4v_patch(void); | 12 | extern void __init sun4v_patch(void); |
@@ -22,7 +22,8 @@ extern void do_notify_resume(struct pt_regs *regs, | |||
22 | unsigned long orig_i0, | 22 | unsigned long orig_i0, |
23 | unsigned long thread_info_flags); | 23 | unsigned long thread_info_flags); |
24 | 24 | ||
25 | extern asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p); | 25 | extern asmlinkage int syscall_trace_enter(struct pt_regs *regs); |
26 | extern asmlinkage void syscall_trace_leave(struct pt_regs *regs); | ||
26 | 27 | ||
27 | extern void bad_trap_tl1(struct pt_regs *regs, long lvl); | 28 | extern void bad_trap_tl1(struct pt_regs *regs, long lvl); |
28 | 29 | ||
diff --git a/arch/sparc64/kernel/head.S b/arch/sparc64/kernel/head.S index c9afef093d51..353226fa0239 100644 --- a/arch/sparc64/kernel/head.S +++ b/arch/sparc64/kernel/head.S | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/errno.h> | 10 | #include <linux/errno.h> |
11 | #include <linux/threads.h> | 11 | #include <linux/threads.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/linkage.h> | ||
13 | #include <asm/thread_info.h> | 14 | #include <asm/thread_info.h> |
14 | #include <asm/asi.h> | 15 | #include <asm/asi.h> |
15 | #include <asm/pstate.h> | 16 | #include <asm/pstate.h> |
diff --git a/arch/sparc64/kernel/hvapi.c b/arch/sparc64/kernel/hvapi.c index 691760b5b012..1d272c3b5740 100644 --- a/arch/sparc64/kernel/hvapi.c +++ b/arch/sparc64/kernel/hvapi.c | |||
@@ -9,7 +9,6 @@ | |||
9 | 9 | ||
10 | #include <asm/hypervisor.h> | 10 | #include <asm/hypervisor.h> |
11 | #include <asm/oplib.h> | 11 | #include <asm/oplib.h> |
12 | #include <asm/sstate.h> | ||
13 | 12 | ||
14 | /* If the hypervisor indicates that the API setting | 13 | /* If the hypervisor indicates that the API setting |
15 | * calls are unsupported, by returning HV_EBADTRAP or | 14 | * calls are unsupported, by returning HV_EBADTRAP or |
@@ -184,8 +183,6 @@ void __init sun4v_hvapi_init(void) | |||
184 | if (sun4v_hvapi_register(group, major, &minor)) | 183 | if (sun4v_hvapi_register(group, major, &minor)) |
185 | goto bad; | 184 | goto bad; |
186 | 185 | ||
187 | sun4v_sstate_init(); | ||
188 | |||
189 | return; | 186 | return; |
190 | 187 | ||
191 | bad: | 188 | bad: |
diff --git a/arch/sparc64/kernel/hvcalls.S b/arch/sparc64/kernel/hvcalls.S index a2810f3ac70f..e066269d1594 100644 --- a/arch/sparc64/kernel/hvcalls.S +++ b/arch/sparc64/kernel/hvcalls.S | |||
@@ -3,89 +3,75 @@ | |||
3 | * | 3 | * |
4 | * returns %o0: sysino | 4 | * returns %o0: sysino |
5 | */ | 5 | */ |
6 | .globl sun4v_devino_to_sysino | 6 | ENTRY(sun4v_devino_to_sysino) |
7 | .type sun4v_devino_to_sysino,#function | ||
8 | sun4v_devino_to_sysino: | ||
9 | mov HV_FAST_INTR_DEVINO2SYSINO, %o5 | 7 | mov HV_FAST_INTR_DEVINO2SYSINO, %o5 |
10 | ta HV_FAST_TRAP | 8 | ta HV_FAST_TRAP |
11 | retl | 9 | retl |
12 | mov %o1, %o0 | 10 | mov %o1, %o0 |
13 | .size sun4v_devino_to_sysino, .-sun4v_devino_to_sysino | 11 | ENDPROC(sun4v_devino_to_sysino) |
14 | 12 | ||
15 | /* %o0: sysino | 13 | /* %o0: sysino |
16 | * | 14 | * |
17 | * returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED}) | 15 | * returns %o0: intr_enabled (HV_INTR_{DISABLED,ENABLED}) |
18 | */ | 16 | */ |
19 | .globl sun4v_intr_getenabled | 17 | ENTRY(sun4v_intr_getenabled) |
20 | .type sun4v_intr_getenabled,#function | ||
21 | sun4v_intr_getenabled: | ||
22 | mov HV_FAST_INTR_GETENABLED, %o5 | 18 | mov HV_FAST_INTR_GETENABLED, %o5 |
23 | ta HV_FAST_TRAP | 19 | ta HV_FAST_TRAP |
24 | retl | 20 | retl |
25 | mov %o1, %o0 | 21 | mov %o1, %o0 |
26 | .size sun4v_intr_getenabled, .-sun4v_intr_getenabled | 22 | ENDPROC(sun4v_intr_getenabled) |
27 | 23 | ||
28 | /* %o0: sysino | 24 | /* %o0: sysino |
29 | * %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED}) | 25 | * %o1: intr_enabled (HV_INTR_{DISABLED,ENABLED}) |
30 | */ | 26 | */ |
31 | .globl sun4v_intr_setenabled | 27 | ENTRY(sun4v_intr_setenabled) |
32 | .type sun4v_intr_setenabled,#function | ||
33 | sun4v_intr_setenabled: | ||
34 | mov HV_FAST_INTR_SETENABLED, %o5 | 28 | mov HV_FAST_INTR_SETENABLED, %o5 |
35 | ta HV_FAST_TRAP | 29 | ta HV_FAST_TRAP |
36 | retl | 30 | retl |
37 | nop | 31 | nop |
38 | .size sun4v_intr_setenabled, .-sun4v_intr_setenabled | 32 | ENDPROC(sun4v_intr_setenabled) |
39 | 33 | ||
40 | /* %o0: sysino | 34 | /* %o0: sysino |
41 | * | 35 | * |
42 | * returns %o0: intr_state (HV_INTR_STATE_*) | 36 | * returns %o0: intr_state (HV_INTR_STATE_*) |
43 | */ | 37 | */ |
44 | .globl sun4v_intr_getstate | 38 | ENTRY(sun4v_intr_getstate) |
45 | .type sun4v_intr_getstate,#function | ||
46 | sun4v_intr_getstate: | ||
47 | mov HV_FAST_INTR_GETSTATE, %o5 | 39 | mov HV_FAST_INTR_GETSTATE, %o5 |
48 | ta HV_FAST_TRAP | 40 | ta HV_FAST_TRAP |
49 | retl | 41 | retl |
50 | mov %o1, %o0 | 42 | mov %o1, %o0 |
51 | .size sun4v_intr_getstate, .-sun4v_intr_getstate | 43 | ENDPROC(sun4v_intr_getstate) |
52 | 44 | ||
53 | /* %o0: sysino | 45 | /* %o0: sysino |
54 | * %o1: intr_state (HV_INTR_STATE_*) | 46 | * %o1: intr_state (HV_INTR_STATE_*) |
55 | */ | 47 | */ |
56 | .globl sun4v_intr_setstate | 48 | ENTRY(sun4v_intr_setstate) |
57 | .type sun4v_intr_setstate,#function | ||
58 | sun4v_intr_setstate: | ||
59 | mov HV_FAST_INTR_SETSTATE, %o5 | 49 | mov HV_FAST_INTR_SETSTATE, %o5 |
60 | ta HV_FAST_TRAP | 50 | ta HV_FAST_TRAP |
61 | retl | 51 | retl |
62 | nop | 52 | nop |
63 | .size sun4v_intr_setstate, .-sun4v_intr_setstate | 53 | ENDPROC(sun4v_intr_setstate) |
64 | 54 | ||
65 | /* %o0: sysino | 55 | /* %o0: sysino |
66 | * | 56 | * |
67 | * returns %o0: cpuid | 57 | * returns %o0: cpuid |
68 | */ | 58 | */ |
69 | .globl sun4v_intr_gettarget | 59 | ENTRY(sun4v_intr_gettarget) |
70 | .type sun4v_intr_gettarget,#function | ||
71 | sun4v_intr_gettarget: | ||
72 | mov HV_FAST_INTR_GETTARGET, %o5 | 60 | mov HV_FAST_INTR_GETTARGET, %o5 |
73 | ta HV_FAST_TRAP | 61 | ta HV_FAST_TRAP |
74 | retl | 62 | retl |
75 | mov %o1, %o0 | 63 | mov %o1, %o0 |
76 | .size sun4v_intr_gettarget, .-sun4v_intr_gettarget | 64 | ENDPROC(sun4v_intr_gettarget) |
77 | 65 | ||
78 | /* %o0: sysino | 66 | /* %o0: sysino |
79 | * %o1: cpuid | 67 | * %o1: cpuid |
80 | */ | 68 | */ |
81 | .globl sun4v_intr_settarget | 69 | ENTRY(sun4v_intr_settarget) |
82 | .type sun4v_intr_settarget,#function | ||
83 | sun4v_intr_settarget: | ||
84 | mov HV_FAST_INTR_SETTARGET, %o5 | 70 | mov HV_FAST_INTR_SETTARGET, %o5 |
85 | ta HV_FAST_TRAP | 71 | ta HV_FAST_TRAP |
86 | retl | 72 | retl |
87 | nop | 73 | nop |
88 | .size sun4v_intr_settarget, .-sun4v_intr_settarget | 74 | ENDPROC(sun4v_intr_settarget) |
89 | 75 | ||
90 | /* %o0: cpuid | 76 | /* %o0: cpuid |
91 | * %o1: pc | 77 | * %o1: pc |
@@ -94,37 +80,31 @@ sun4v_intr_settarget: | |||
94 | * | 80 | * |
95 | * returns %o0: status | 81 | * returns %o0: status |
96 | */ | 82 | */ |
97 | .globl sun4v_cpu_start | 83 | ENTRY(sun4v_cpu_start) |
98 | .type sun4v_cpu_start,#function | ||
99 | sun4v_cpu_start: | ||
100 | mov HV_FAST_CPU_START, %o5 | 84 | mov HV_FAST_CPU_START, %o5 |
101 | ta HV_FAST_TRAP | 85 | ta HV_FAST_TRAP |
102 | retl | 86 | retl |
103 | nop | 87 | nop |
104 | .size sun4v_cpu_start, .-sun4v_cpu_start | 88 | ENDPROC(sun4v_cpu_start) |
105 | 89 | ||
106 | /* %o0: cpuid | 90 | /* %o0: cpuid |
107 | * | 91 | * |
108 | * returns %o0: status | 92 | * returns %o0: status |
109 | */ | 93 | */ |
110 | .globl sun4v_cpu_stop | 94 | ENTRY(sun4v_cpu_stop) |
111 | .type sun4v_cpu_stop,#function | ||
112 | sun4v_cpu_stop: | ||
113 | mov HV_FAST_CPU_STOP, %o5 | 95 | mov HV_FAST_CPU_STOP, %o5 |
114 | ta HV_FAST_TRAP | 96 | ta HV_FAST_TRAP |
115 | retl | 97 | retl |
116 | nop | 98 | nop |
117 | .size sun4v_cpu_stop, .-sun4v_cpu_stop | 99 | ENDPROC(sun4v_cpu_stop) |
118 | 100 | ||
119 | /* returns %o0: status */ | 101 | /* returns %o0: status */ |
120 | .globl sun4v_cpu_yield | 102 | ENTRY(sun4v_cpu_yield) |
121 | .type sun4v_cpu_yield, #function | ||
122 | sun4v_cpu_yield: | ||
123 | mov HV_FAST_CPU_YIELD, %o5 | 103 | mov HV_FAST_CPU_YIELD, %o5 |
124 | ta HV_FAST_TRAP | 104 | ta HV_FAST_TRAP |
125 | retl | 105 | retl |
126 | nop | 106 | nop |
127 | .size sun4v_cpu_yield, .-sun4v_cpu_yield | 107 | ENDPROC(sun4v_cpu_yield) |
128 | 108 | ||
129 | /* %o0: type | 109 | /* %o0: type |
130 | * %o1: queue paddr | 110 | * %o1: queue paddr |
@@ -132,14 +112,12 @@ sun4v_cpu_yield: | |||
132 | * | 112 | * |
133 | * returns %o0: status | 113 | * returns %o0: status |
134 | */ | 114 | */ |
135 | .globl sun4v_cpu_qconf | 115 | ENTRY(sun4v_cpu_qconf) |
136 | .type sun4v_cpu_qconf,#function | ||
137 | sun4v_cpu_qconf: | ||
138 | mov HV_FAST_CPU_QCONF, %o5 | 116 | mov HV_FAST_CPU_QCONF, %o5 |
139 | ta HV_FAST_TRAP | 117 | ta HV_FAST_TRAP |
140 | retl | 118 | retl |
141 | nop | 119 | nop |
142 | .size sun4v_cpu_qconf, .-sun4v_cpu_qconf | 120 | ENDPROC(sun4v_cpu_qconf) |
143 | 121 | ||
144 | /* %o0: num cpus in cpu list | 122 | /* %o0: num cpus in cpu list |
145 | * %o1: cpu list paddr | 123 | * %o1: cpu list paddr |
@@ -147,23 +125,19 @@ sun4v_cpu_qconf: | |||
147 | * | 125 | * |
148 | * returns %o0: status | 126 | * returns %o0: status |
149 | */ | 127 | */ |
150 | .globl sun4v_cpu_mondo_send | 128 | ENTRY(sun4v_cpu_mondo_send) |
151 | .type sun4v_cpu_mondo_send,#function | ||
152 | sun4v_cpu_mondo_send: | ||
153 | mov HV_FAST_CPU_MONDO_SEND, %o5 | 129 | mov HV_FAST_CPU_MONDO_SEND, %o5 |
154 | ta HV_FAST_TRAP | 130 | ta HV_FAST_TRAP |
155 | retl | 131 | retl |
156 | nop | 132 | nop |
157 | .size sun4v_cpu_mondo_send, .-sun4v_cpu_mondo_send | 133 | ENDPROC(sun4v_cpu_mondo_send) |
158 | 134 | ||
159 | /* %o0: CPU ID | 135 | /* %o0: CPU ID |
160 | * | 136 | * |
161 | * returns %o0: -status if status non-zero, else | 137 | * returns %o0: -status if status non-zero, else |
162 | * %o0: cpu state as HV_CPU_STATE_* | 138 | * %o0: cpu state as HV_CPU_STATE_* |
163 | */ | 139 | */ |
164 | .globl sun4v_cpu_state | 140 | ENTRY(sun4v_cpu_state) |
165 | .type sun4v_cpu_state,#function | ||
166 | sun4v_cpu_state: | ||
167 | mov HV_FAST_CPU_STATE, %o5 | 141 | mov HV_FAST_CPU_STATE, %o5 |
168 | ta HV_FAST_TRAP | 142 | ta HV_FAST_TRAP |
169 | brnz,pn %o0, 1f | 143 | brnz,pn %o0, 1f |
@@ -171,7 +145,7 @@ sun4v_cpu_state: | |||
171 | mov %o1, %o0 | 145 | mov %o1, %o0 |
172 | 1: retl | 146 | 1: retl |
173 | nop | 147 | nop |
174 | .size sun4v_cpu_state, .-sun4v_cpu_state | 148 | ENDPROC(sun4v_cpu_state) |
175 | 149 | ||
176 | /* %o0: virtual address | 150 | /* %o0: virtual address |
177 | * %o1: must be zero | 151 | * %o1: must be zero |
@@ -180,28 +154,24 @@ sun4v_cpu_state: | |||
180 | * | 154 | * |
181 | * returns %o0: status | 155 | * returns %o0: status |
182 | */ | 156 | */ |
183 | .globl sun4v_mmu_map_perm_addr | 157 | ENTRY(sun4v_mmu_map_perm_addr) |
184 | .type sun4v_mmu_map_perm_addr,#function | ||
185 | sun4v_mmu_map_perm_addr: | ||
186 | mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 | 158 | mov HV_FAST_MMU_MAP_PERM_ADDR, %o5 |
187 | ta HV_FAST_TRAP | 159 | ta HV_FAST_TRAP |
188 | retl | 160 | retl |
189 | nop | 161 | nop |
190 | .size sun4v_mmu_map_perm_addr, .-sun4v_mmu_map_perm_addr | 162 | ENDPROC(sun4v_mmu_map_perm_addr) |
191 | 163 | ||
192 | /* %o0: number of TSB descriptions | 164 | /* %o0: number of TSB descriptions |
193 | * %o1: TSB descriptions real address | 165 | * %o1: TSB descriptions real address |
194 | * | 166 | * |
195 | * returns %o0: status | 167 | * returns %o0: status |
196 | */ | 168 | */ |
197 | .globl sun4v_mmu_tsb_ctx0 | 169 | ENTRY(sun4v_mmu_tsb_ctx0) |
198 | .type sun4v_mmu_tsb_ctx0,#function | ||
199 | sun4v_mmu_tsb_ctx0: | ||
200 | mov HV_FAST_MMU_TSB_CTX0, %o5 | 170 | mov HV_FAST_MMU_TSB_CTX0, %o5 |
201 | ta HV_FAST_TRAP | 171 | ta HV_FAST_TRAP |
202 | retl | 172 | retl |
203 | nop | 173 | nop |
204 | .size sun4v_mmu_tsb_ctx0, .-sun4v_mmu_tsb_ctx0 | 174 | ENDPROC(sun4v_mmu_tsb_ctx0) |
205 | 175 | ||
206 | /* %o0: API group number | 176 | /* %o0: API group number |
207 | * %o1: pointer to unsigned long major number storage | 177 | * %o1: pointer to unsigned long major number storage |
@@ -209,9 +179,7 @@ sun4v_mmu_tsb_ctx0: | |||
209 | * | 179 | * |
210 | * returns %o0: status | 180 | * returns %o0: status |
211 | */ | 181 | */ |
212 | .globl sun4v_get_version | 182 | ENTRY(sun4v_get_version) |
213 | .type sun4v_get_version,#function | ||
214 | sun4v_get_version: | ||
215 | mov HV_CORE_GET_VER, %o5 | 183 | mov HV_CORE_GET_VER, %o5 |
216 | mov %o1, %o3 | 184 | mov %o1, %o3 |
217 | mov %o2, %o4 | 185 | mov %o2, %o4 |
@@ -219,7 +187,7 @@ sun4v_get_version: | |||
219 | stx %o1, [%o3] | 187 | stx %o1, [%o3] |
220 | retl | 188 | retl |
221 | stx %o2, [%o4] | 189 | stx %o2, [%o4] |
222 | .size sun4v_get_version, .-sun4v_get_version | 190 | ENDPROC(sun4v_get_version) |
223 | 191 | ||
224 | /* %o0: API group number | 192 | /* %o0: API group number |
225 | * %o1: desired major number | 193 | * %o1: desired major number |
@@ -228,51 +196,43 @@ sun4v_get_version: | |||
228 | * | 196 | * |
229 | * returns %o0: status | 197 | * returns %o0: status |
230 | */ | 198 | */ |
231 | .globl sun4v_set_version | 199 | ENTRY(sun4v_set_version) |
232 | .type sun4v_set_version,#function | ||
233 | sun4v_set_version: | ||
234 | mov HV_CORE_SET_VER, %o5 | 200 | mov HV_CORE_SET_VER, %o5 |
235 | mov %o3, %o4 | 201 | mov %o3, %o4 |
236 | ta HV_CORE_TRAP | 202 | ta HV_CORE_TRAP |
237 | retl | 203 | retl |
238 | stx %o1, [%o4] | 204 | stx %o1, [%o4] |
239 | .size sun4v_set_version, .-sun4v_set_version | 205 | ENDPROC(sun4v_set_version) |
240 | 206 | ||
241 | /* %o0: pointer to unsigned long time | 207 | /* %o0: pointer to unsigned long time |
242 | * | 208 | * |
243 | * returns %o0: status | 209 | * returns %o0: status |
244 | */ | 210 | */ |
245 | .globl sun4v_tod_get | 211 | ENTRY(sun4v_tod_get) |
246 | .type sun4v_tod_get,#function | ||
247 | sun4v_tod_get: | ||
248 | mov %o0, %o4 | 212 | mov %o0, %o4 |
249 | mov HV_FAST_TOD_GET, %o5 | 213 | mov HV_FAST_TOD_GET, %o5 |
250 | ta HV_FAST_TRAP | 214 | ta HV_FAST_TRAP |
251 | stx %o1, [%o4] | 215 | stx %o1, [%o4] |
252 | retl | 216 | retl |
253 | nop | 217 | nop |
254 | .size sun4v_tod_get, .-sun4v_tod_get | 218 | ENDPROC(sun4v_tod_get) |
255 | 219 | ||
256 | /* %o0: time | 220 | /* %o0: time |
257 | * | 221 | * |
258 | * returns %o0: status | 222 | * returns %o0: status |
259 | */ | 223 | */ |
260 | .globl sun4v_tod_set | 224 | ENTRY(sun4v_tod_set) |
261 | .type sun4v_tod_set,#function | ||
262 | sun4v_tod_set: | ||
263 | mov HV_FAST_TOD_SET, %o5 | 225 | mov HV_FAST_TOD_SET, %o5 |
264 | ta HV_FAST_TRAP | 226 | ta HV_FAST_TRAP |
265 | retl | 227 | retl |
266 | nop | 228 | nop |
267 | .size sun4v_tod_set, .-sun4v_tod_set | 229 | ENDPROC(sun4v_tod_set) |
268 | 230 | ||
269 | /* %o0: pointer to unsigned long status | 231 | /* %o0: pointer to unsigned long status |
270 | * | 232 | * |
271 | * returns %o0: signed character | 233 | * returns %o0: signed character |
272 | */ | 234 | */ |
273 | .globl sun4v_con_getchar | 235 | ENTRY(sun4v_con_getchar) |
274 | .type sun4v_con_getchar,#function | ||
275 | sun4v_con_getchar: | ||
276 | mov %o0, %o4 | 236 | mov %o0, %o4 |
277 | mov HV_FAST_CONS_GETCHAR, %o5 | 237 | mov HV_FAST_CONS_GETCHAR, %o5 |
278 | clr %o0 | 238 | clr %o0 |
@@ -281,20 +241,18 @@ sun4v_con_getchar: | |||
281 | stx %o0, [%o4] | 241 | stx %o0, [%o4] |
282 | retl | 242 | retl |
283 | sra %o1, 0, %o0 | 243 | sra %o1, 0, %o0 |
284 | .size sun4v_con_getchar, .-sun4v_con_getchar | 244 | ENDPROC(sun4v_con_getchar) |
285 | 245 | ||
286 | /* %o0: signed long character | 246 | /* %o0: signed long character |
287 | * | 247 | * |
288 | * returns %o0: status | 248 | * returns %o0: status |
289 | */ | 249 | */ |
290 | .globl sun4v_con_putchar | 250 | ENTRY(sun4v_con_putchar) |
291 | .type sun4v_con_putchar,#function | ||
292 | sun4v_con_putchar: | ||
293 | mov HV_FAST_CONS_PUTCHAR, %o5 | 251 | mov HV_FAST_CONS_PUTCHAR, %o5 |
294 | ta HV_FAST_TRAP | 252 | ta HV_FAST_TRAP |
295 | retl | 253 | retl |
296 | sra %o0, 0, %o0 | 254 | sra %o0, 0, %o0 |
297 | .size sun4v_con_putchar, .-sun4v_con_putchar | 255 | ENDPROC(sun4v_con_putchar) |
298 | 256 | ||
299 | /* %o0: buffer real address | 257 | /* %o0: buffer real address |
300 | * %o1: buffer size | 258 | * %o1: buffer size |
@@ -302,9 +260,7 @@ sun4v_con_putchar: | |||
302 | * | 260 | * |
303 | * returns %o0: status | 261 | * returns %o0: status |
304 | */ | 262 | */ |
305 | .globl sun4v_con_read | 263 | ENTRY(sun4v_con_read) |
306 | .type sun4v_con_read,#function | ||
307 | sun4v_con_read: | ||
308 | mov %o2, %o4 | 264 | mov %o2, %o4 |
309 | mov HV_FAST_CONS_READ, %o5 | 265 | mov HV_FAST_CONS_READ, %o5 |
310 | ta HV_FAST_TRAP | 266 | ta HV_FAST_TRAP |
@@ -318,7 +274,7 @@ sun4v_con_read: | |||
318 | stx %o1, [%o4] | 274 | stx %o1, [%o4] |
319 | 1: retl | 275 | 1: retl |
320 | nop | 276 | nop |
321 | .size sun4v_con_read, .-sun4v_con_read | 277 | ENDPROC(sun4v_con_read) |
322 | 278 | ||
323 | /* %o0: buffer real address | 279 | /* %o0: buffer real address |
324 | * %o1: buffer size | 280 | * %o1: buffer size |
@@ -326,43 +282,37 @@ sun4v_con_read: | |||
326 | * | 282 | * |
327 | * returns %o0: status | 283 | * returns %o0: status |
328 | */ | 284 | */ |
329 | .globl sun4v_con_write | 285 | ENTRY(sun4v_con_write) |
330 | .type sun4v_con_write,#function | ||
331 | sun4v_con_write: | ||
332 | mov %o2, %o4 | 286 | mov %o2, %o4 |
333 | mov HV_FAST_CONS_WRITE, %o5 | 287 | mov HV_FAST_CONS_WRITE, %o5 |
334 | ta HV_FAST_TRAP | 288 | ta HV_FAST_TRAP |
335 | stx %o1, [%o4] | 289 | stx %o1, [%o4] |
336 | retl | 290 | retl |
337 | nop | 291 | nop |
338 | .size sun4v_con_write, .-sun4v_con_write | 292 | ENDPROC(sun4v_con_write) |
339 | 293 | ||
340 | /* %o0: soft state | 294 | /* %o0: soft state |
341 | * %o1: address of description string | 295 | * %o1: address of description string |
342 | * | 296 | * |
343 | * returns %o0: status | 297 | * returns %o0: status |
344 | */ | 298 | */ |
345 | .globl sun4v_mach_set_soft_state | 299 | ENTRY(sun4v_mach_set_soft_state) |
346 | .type sun4v_mach_set_soft_state,#function | ||
347 | sun4v_mach_set_soft_state: | ||
348 | mov HV_FAST_MACH_SET_SOFT_STATE, %o5 | 300 | mov HV_FAST_MACH_SET_SOFT_STATE, %o5 |
349 | ta HV_FAST_TRAP | 301 | ta HV_FAST_TRAP |
350 | retl | 302 | retl |
351 | nop | 303 | nop |
352 | .size sun4v_mach_set_soft_state, .-sun4v_mach_set_soft_state | 304 | ENDPROC(sun4v_mach_set_soft_state) |
353 | 305 | ||
354 | /* %o0: exit code | 306 | /* %o0: exit code |
355 | * | 307 | * |
356 | * Does not return. | 308 | * Does not return. |
357 | */ | 309 | */ |
358 | .globl sun4v_mach_exit | 310 | ENTRY(sun4v_mach_exit) |
359 | .type sun4v_mach_exit,#function | ||
360 | sun4v_mach_exit: | ||
361 | mov HV_FAST_MACH_EXIT, %o5 | 311 | mov HV_FAST_MACH_EXIT, %o5 |
362 | ta HV_FAST_TRAP | 312 | ta HV_FAST_TRAP |
363 | retl | 313 | retl |
364 | nop | 314 | nop |
365 | .size sun4v_mach_exit, .-sun4v_mach_exit | 315 | ENDPROC(sun4v_mach_exit) |
366 | 316 | ||
367 | /* %o0: buffer real address | 317 | /* %o0: buffer real address |
368 | * %o1: buffer length | 318 | * %o1: buffer length |
@@ -370,44 +320,38 @@ sun4v_mach_exit: | |||
370 | * | 320 | * |
371 | * returns %o0: status | 321 | * returns %o0: status |
372 | */ | 322 | */ |
373 | .globl sun4v_mach_desc | 323 | ENTRY(sun4v_mach_desc) |
374 | .type sun4v_mach_desc,#function | ||
375 | sun4v_mach_desc: | ||
376 | mov %o2, %o4 | 324 | mov %o2, %o4 |
377 | mov HV_FAST_MACH_DESC, %o5 | 325 | mov HV_FAST_MACH_DESC, %o5 |
378 | ta HV_FAST_TRAP | 326 | ta HV_FAST_TRAP |
379 | stx %o1, [%o4] | 327 | stx %o1, [%o4] |
380 | retl | 328 | retl |
381 | nop | 329 | nop |
382 | .size sun4v_mach_desc, .-sun4v_mach_desc | 330 | ENDPROC(sun4v_mach_desc) |
383 | 331 | ||
384 | /* %o0: new timeout in milliseconds | 332 | /* %o0: new timeout in milliseconds |
385 | * %o1: pointer to unsigned long orig_timeout | 333 | * %o1: pointer to unsigned long orig_timeout |
386 | * | 334 | * |
387 | * returns %o0: status | 335 | * returns %o0: status |
388 | */ | 336 | */ |
389 | .globl sun4v_mach_set_watchdog | 337 | ENTRY(sun4v_mach_set_watchdog) |
390 | .type sun4v_mach_set_watchdog,#function | ||
391 | sun4v_mach_set_watchdog: | ||
392 | mov %o1, %o4 | 338 | mov %o1, %o4 |
393 | mov HV_FAST_MACH_SET_WATCHDOG, %o5 | 339 | mov HV_FAST_MACH_SET_WATCHDOG, %o5 |
394 | ta HV_FAST_TRAP | 340 | ta HV_FAST_TRAP |
395 | stx %o1, [%o4] | 341 | stx %o1, [%o4] |
396 | retl | 342 | retl |
397 | nop | 343 | nop |
398 | .size sun4v_mach_set_watchdog, .-sun4v_mach_set_watchdog | 344 | ENDPROC(sun4v_mach_set_watchdog) |
399 | 345 | ||
400 | /* No inputs and does not return. */ | 346 | /* No inputs and does not return. */ |
401 | .globl sun4v_mach_sir | 347 | ENTRY(sun4v_mach_sir) |
402 | .type sun4v_mach_sir,#function | ||
403 | sun4v_mach_sir: | ||
404 | mov %o1, %o4 | 348 | mov %o1, %o4 |
405 | mov HV_FAST_MACH_SIR, %o5 | 349 | mov HV_FAST_MACH_SIR, %o5 |
406 | ta HV_FAST_TRAP | 350 | ta HV_FAST_TRAP |
407 | stx %o1, [%o4] | 351 | stx %o1, [%o4] |
408 | retl | 352 | retl |
409 | nop | 353 | nop |
410 | .size sun4v_mach_sir, .-sun4v_mach_sir | 354 | ENDPROC(sun4v_mach_sir) |
411 | 355 | ||
412 | /* %o0: channel | 356 | /* %o0: channel |
413 | * %o1: ra | 357 | * %o1: ra |
@@ -415,14 +359,12 @@ sun4v_mach_sir: | |||
415 | * | 359 | * |
416 | * returns %o0: status | 360 | * returns %o0: status |
417 | */ | 361 | */ |
418 | .globl sun4v_ldc_tx_qconf | 362 | ENTRY(sun4v_ldc_tx_qconf) |
419 | .type sun4v_ldc_tx_qconf,#function | ||
420 | sun4v_ldc_tx_qconf: | ||
421 | mov HV_FAST_LDC_TX_QCONF, %o5 | 363 | mov HV_FAST_LDC_TX_QCONF, %o5 |
422 | ta HV_FAST_TRAP | 364 | ta HV_FAST_TRAP |
423 | retl | 365 | retl |
424 | nop | 366 | nop |
425 | .size sun4v_ldc_tx_qconf, .-sun4v_ldc_tx_qconf | 367 | ENDPROC(sun4v_ldc_tx_qconf) |
426 | 368 | ||
427 | /* %o0: channel | 369 | /* %o0: channel |
428 | * %o1: pointer to unsigned long ra | 370 | * %o1: pointer to unsigned long ra |
@@ -430,9 +372,7 @@ sun4v_ldc_tx_qconf: | |||
430 | * | 372 | * |
431 | * returns %o0: status | 373 | * returns %o0: status |
432 | */ | 374 | */ |
433 | .globl sun4v_ldc_tx_qinfo | 375 | ENTRY(sun4v_ldc_tx_qinfo) |
434 | .type sun4v_ldc_tx_qinfo,#function | ||
435 | sun4v_ldc_tx_qinfo: | ||
436 | mov %o1, %g1 | 376 | mov %o1, %g1 |
437 | mov %o2, %g2 | 377 | mov %o2, %g2 |
438 | mov HV_FAST_LDC_TX_QINFO, %o5 | 378 | mov HV_FAST_LDC_TX_QINFO, %o5 |
@@ -441,7 +381,7 @@ sun4v_ldc_tx_qinfo: | |||
441 | stx %o2, [%g2] | 381 | stx %o2, [%g2] |
442 | retl | 382 | retl |
443 | nop | 383 | nop |
444 | .size sun4v_ldc_tx_qinfo, .-sun4v_ldc_tx_qinfo | 384 | ENDPROC(sun4v_ldc_tx_qinfo) |
445 | 385 | ||
446 | /* %o0: channel | 386 | /* %o0: channel |
447 | * %o1: pointer to unsigned long head_off | 387 | * %o1: pointer to unsigned long head_off |
@@ -450,9 +390,7 @@ sun4v_ldc_tx_qinfo: | |||
450 | * | 390 | * |
451 | * returns %o0: status | 391 | * returns %o0: status |
452 | */ | 392 | */ |
453 | .globl sun4v_ldc_tx_get_state | 393 | ENTRY(sun4v_ldc_tx_get_state) |
454 | .type sun4v_ldc_tx_get_state,#function | ||
455 | sun4v_ldc_tx_get_state: | ||
456 | mov %o1, %g1 | 394 | mov %o1, %g1 |
457 | mov %o2, %g2 | 395 | mov %o2, %g2 |
458 | mov %o3, %g3 | 396 | mov %o3, %g3 |
@@ -463,21 +401,19 @@ sun4v_ldc_tx_get_state: | |||
463 | stx %o3, [%g3] | 401 | stx %o3, [%g3] |
464 | retl | 402 | retl |
465 | nop | 403 | nop |
466 | .size sun4v_ldc_tx_get_state, .-sun4v_ldc_tx_get_state | 404 | ENDPROC(sun4v_ldc_tx_get_state) |
467 | 405 | ||
468 | /* %o0: channel | 406 | /* %o0: channel |
469 | * %o1: tail_off | 407 | * %o1: tail_off |
470 | * | 408 | * |
471 | * returns %o0: status | 409 | * returns %o0: status |
472 | */ | 410 | */ |
473 | .globl sun4v_ldc_tx_set_qtail | 411 | ENTRY(sun4v_ldc_tx_set_qtail) |
474 | .type sun4v_ldc_tx_set_qtail,#function | ||
475 | sun4v_ldc_tx_set_qtail: | ||
476 | mov HV_FAST_LDC_TX_SET_QTAIL, %o5 | 412 | mov HV_FAST_LDC_TX_SET_QTAIL, %o5 |
477 | ta HV_FAST_TRAP | 413 | ta HV_FAST_TRAP |
478 | retl | 414 | retl |
479 | nop | 415 | nop |
480 | .size sun4v_ldc_tx_set_qtail, .-sun4v_ldc_tx_set_qtail | 416 | ENDPROC(sun4v_ldc_tx_set_qtail) |
481 | 417 | ||
482 | /* %o0: channel | 418 | /* %o0: channel |
483 | * %o1: ra | 419 | * %o1: ra |
@@ -485,14 +421,12 @@ sun4v_ldc_tx_set_qtail: | |||
485 | * | 421 | * |
486 | * returns %o0: status | 422 | * returns %o0: status |
487 | */ | 423 | */ |
488 | .globl sun4v_ldc_rx_qconf | 424 | ENTRY(sun4v_ldc_rx_qconf) |
489 | .type sun4v_ldc_rx_qconf,#function | ||
490 | sun4v_ldc_rx_qconf: | ||
491 | mov HV_FAST_LDC_RX_QCONF, %o5 | 425 | mov HV_FAST_LDC_RX_QCONF, %o5 |
492 | ta HV_FAST_TRAP | 426 | ta HV_FAST_TRAP |
493 | retl | 427 | retl |
494 | nop | 428 | nop |
495 | .size sun4v_ldc_rx_qconf, .-sun4v_ldc_rx_qconf | 429 | ENDPROC(sun4v_ldc_rx_qconf) |
496 | 430 | ||
497 | /* %o0: channel | 431 | /* %o0: channel |
498 | * %o1: pointer to unsigned long ra | 432 | * %o1: pointer to unsigned long ra |
@@ -500,9 +434,7 @@ sun4v_ldc_rx_qconf: | |||
500 | * | 434 | * |
501 | * returns %o0: status | 435 | * returns %o0: status |
502 | */ | 436 | */ |
503 | .globl sun4v_ldc_rx_qinfo | 437 | ENTRY(sun4v_ldc_rx_qinfo) |
504 | .type sun4v_ldc_rx_qinfo,#function | ||
505 | sun4v_ldc_rx_qinfo: | ||
506 | mov %o1, %g1 | 438 | mov %o1, %g1 |
507 | mov %o2, %g2 | 439 | mov %o2, %g2 |
508 | mov HV_FAST_LDC_RX_QINFO, %o5 | 440 | mov HV_FAST_LDC_RX_QINFO, %o5 |
@@ -511,7 +443,7 @@ sun4v_ldc_rx_qinfo: | |||
511 | stx %o2, [%g2] | 443 | stx %o2, [%g2] |
512 | retl | 444 | retl |
513 | nop | 445 | nop |
514 | .size sun4v_ldc_rx_qinfo, .-sun4v_ldc_rx_qinfo | 446 | ENDPROC(sun4v_ldc_rx_qinfo) |
515 | 447 | ||
516 | /* %o0: channel | 448 | /* %o0: channel |
517 | * %o1: pointer to unsigned long head_off | 449 | * %o1: pointer to unsigned long head_off |
@@ -520,9 +452,7 @@ sun4v_ldc_rx_qinfo: | |||
520 | * | 452 | * |
521 | * returns %o0: status | 453 | * returns %o0: status |
522 | */ | 454 | */ |
523 | .globl sun4v_ldc_rx_get_state | 455 | ENTRY(sun4v_ldc_rx_get_state) |
524 | .type sun4v_ldc_rx_get_state,#function | ||
525 | sun4v_ldc_rx_get_state: | ||
526 | mov %o1, %g1 | 456 | mov %o1, %g1 |
527 | mov %o2, %g2 | 457 | mov %o2, %g2 |
528 | mov %o3, %g3 | 458 | mov %o3, %g3 |
@@ -533,21 +463,19 @@ sun4v_ldc_rx_get_state: | |||
533 | stx %o3, [%g3] | 463 | stx %o3, [%g3] |
534 | retl | 464 | retl |
535 | nop | 465 | nop |
536 | .size sun4v_ldc_rx_get_state, .-sun4v_ldc_rx_get_state | 466 | ENDPROC(sun4v_ldc_rx_get_state) |
537 | 467 | ||
538 | /* %o0: channel | 468 | /* %o0: channel |
539 | * %o1: head_off | 469 | * %o1: head_off |
540 | * | 470 | * |
541 | * returns %o0: status | 471 | * returns %o0: status |
542 | */ | 472 | */ |
543 | .globl sun4v_ldc_rx_set_qhead | 473 | ENTRY(sun4v_ldc_rx_set_qhead) |
544 | .type sun4v_ldc_rx_set_qhead,#function | ||
545 | sun4v_ldc_rx_set_qhead: | ||
546 | mov HV_FAST_LDC_RX_SET_QHEAD, %o5 | 474 | mov HV_FAST_LDC_RX_SET_QHEAD, %o5 |
547 | ta HV_FAST_TRAP | 475 | ta HV_FAST_TRAP |
548 | retl | 476 | retl |
549 | nop | 477 | nop |
550 | .size sun4v_ldc_rx_set_qhead, .-sun4v_ldc_rx_set_qhead | 478 | ENDPROC(sun4v_ldc_rx_set_qhead) |
551 | 479 | ||
552 | /* %o0: channel | 480 | /* %o0: channel |
553 | * %o1: ra | 481 | * %o1: ra |
@@ -555,14 +483,12 @@ sun4v_ldc_rx_set_qhead: | |||
555 | * | 483 | * |
556 | * returns %o0: status | 484 | * returns %o0: status |
557 | */ | 485 | */ |
558 | .globl sun4v_ldc_set_map_table | 486 | ENTRY(sun4v_ldc_set_map_table) |
559 | .type sun4v_ldc_set_map_table,#function | ||
560 | sun4v_ldc_set_map_table: | ||
561 | mov HV_FAST_LDC_SET_MAP_TABLE, %o5 | 487 | mov HV_FAST_LDC_SET_MAP_TABLE, %o5 |
562 | ta HV_FAST_TRAP | 488 | ta HV_FAST_TRAP |
563 | retl | 489 | retl |
564 | nop | 490 | nop |
565 | .size sun4v_ldc_set_map_table, .-sun4v_ldc_set_map_table | 491 | ENDPROC(sun4v_ldc_set_map_table) |
566 | 492 | ||
567 | /* %o0: channel | 493 | /* %o0: channel |
568 | * %o1: pointer to unsigned long ra | 494 | * %o1: pointer to unsigned long ra |
@@ -570,9 +496,7 @@ sun4v_ldc_set_map_table: | |||
570 | * | 496 | * |
571 | * returns %o0: status | 497 | * returns %o0: status |
572 | */ | 498 | */ |
573 | .globl sun4v_ldc_get_map_table | 499 | ENTRY(sun4v_ldc_get_map_table) |
574 | .type sun4v_ldc_get_map_table,#function | ||
575 | sun4v_ldc_get_map_table: | ||
576 | mov %o1, %g1 | 500 | mov %o1, %g1 |
577 | mov %o2, %g2 | 501 | mov %o2, %g2 |
578 | mov HV_FAST_LDC_GET_MAP_TABLE, %o5 | 502 | mov HV_FAST_LDC_GET_MAP_TABLE, %o5 |
@@ -581,7 +505,7 @@ sun4v_ldc_get_map_table: | |||
581 | stx %o2, [%g2] | 505 | stx %o2, [%g2] |
582 | retl | 506 | retl |
583 | nop | 507 | nop |
584 | .size sun4v_ldc_get_map_table, .-sun4v_ldc_get_map_table | 508 | ENDPROC(sun4v_ldc_get_map_table) |
585 | 509 | ||
586 | /* %o0: channel | 510 | /* %o0: channel |
587 | * %o1: dir_code | 511 | * %o1: dir_code |
@@ -592,16 +516,14 @@ sun4v_ldc_get_map_table: | |||
592 | * | 516 | * |
593 | * returns %o0: status | 517 | * returns %o0: status |
594 | */ | 518 | */ |
595 | .globl sun4v_ldc_copy | 519 | ENTRY(sun4v_ldc_copy) |
596 | .type sun4v_ldc_copy,#function | ||
597 | sun4v_ldc_copy: | ||
598 | mov %o5, %g1 | 520 | mov %o5, %g1 |
599 | mov HV_FAST_LDC_COPY, %o5 | 521 | mov HV_FAST_LDC_COPY, %o5 |
600 | ta HV_FAST_TRAP | 522 | ta HV_FAST_TRAP |
601 | stx %o1, [%g1] | 523 | stx %o1, [%g1] |
602 | retl | 524 | retl |
603 | nop | 525 | nop |
604 | .size sun4v_ldc_copy, .-sun4v_ldc_copy | 526 | ENDPROC(sun4v_ldc_copy) |
605 | 527 | ||
606 | /* %o0: channel | 528 | /* %o0: channel |
607 | * %o1: cookie | 529 | * %o1: cookie |
@@ -610,9 +532,7 @@ sun4v_ldc_copy: | |||
610 | * | 532 | * |
611 | * returns %o0: status | 533 | * returns %o0: status |
612 | */ | 534 | */ |
613 | .globl sun4v_ldc_mapin | 535 | ENTRY(sun4v_ldc_mapin) |
614 | .type sun4v_ldc_mapin,#function | ||
615 | sun4v_ldc_mapin: | ||
616 | mov %o2, %g1 | 536 | mov %o2, %g1 |
617 | mov %o3, %g2 | 537 | mov %o3, %g2 |
618 | mov HV_FAST_LDC_MAPIN, %o5 | 538 | mov HV_FAST_LDC_MAPIN, %o5 |
@@ -621,20 +541,18 @@ sun4v_ldc_mapin: | |||
621 | stx %o2, [%g2] | 541 | stx %o2, [%g2] |
622 | retl | 542 | retl |
623 | nop | 543 | nop |
624 | .size sun4v_ldc_mapin, .-sun4v_ldc_mapin | 544 | ENDPROC(sun4v_ldc_mapin) |
625 | 545 | ||
626 | /* %o0: ra | 546 | /* %o0: ra |
627 | * | 547 | * |
628 | * returns %o0: status | 548 | * returns %o0: status |
629 | */ | 549 | */ |
630 | .globl sun4v_ldc_unmap | 550 | ENTRY(sun4v_ldc_unmap) |
631 | .type sun4v_ldc_unmap,#function | ||
632 | sun4v_ldc_unmap: | ||
633 | mov HV_FAST_LDC_UNMAP, %o5 | 551 | mov HV_FAST_LDC_UNMAP, %o5 |
634 | ta HV_FAST_TRAP | 552 | ta HV_FAST_TRAP |
635 | retl | 553 | retl |
636 | nop | 554 | nop |
637 | .size sun4v_ldc_unmap, .-sun4v_ldc_unmap | 555 | ENDPROC(sun4v_ldc_unmap) |
638 | 556 | ||
639 | /* %o0: channel | 557 | /* %o0: channel |
640 | * %o1: cookie | 558 | * %o1: cookie |
@@ -642,14 +560,12 @@ sun4v_ldc_unmap: | |||
642 | * | 560 | * |
643 | * returns %o0: status | 561 | * returns %o0: status |
644 | */ | 562 | */ |
645 | .globl sun4v_ldc_revoke | 563 | ENTRY(sun4v_ldc_revoke) |
646 | .type sun4v_ldc_revoke,#function | ||
647 | sun4v_ldc_revoke: | ||
648 | mov HV_FAST_LDC_REVOKE, %o5 | 564 | mov HV_FAST_LDC_REVOKE, %o5 |
649 | ta HV_FAST_TRAP | 565 | ta HV_FAST_TRAP |
650 | retl | 566 | retl |
651 | nop | 567 | nop |
652 | .size sun4v_ldc_revoke, .-sun4v_ldc_revoke | 568 | ENDPROC(sun4v_ldc_revoke) |
653 | 569 | ||
654 | /* %o0: device handle | 570 | /* %o0: device handle |
655 | * %o1: device INO | 571 | * %o1: device INO |
@@ -657,16 +573,14 @@ sun4v_ldc_revoke: | |||
657 | * | 573 | * |
658 | * returns %o0: status | 574 | * returns %o0: status |
659 | */ | 575 | */ |
660 | .globl sun4v_vintr_get_cookie | 576 | ENTRY(sun4v_vintr_get_cookie) |
661 | .type sun4v_vintr_get_cookie,#function | ||
662 | sun4v_vintr_get_cookie: | ||
663 | mov %o2, %g1 | 577 | mov %o2, %g1 |
664 | mov HV_FAST_VINTR_GET_COOKIE, %o5 | 578 | mov HV_FAST_VINTR_GET_COOKIE, %o5 |
665 | ta HV_FAST_TRAP | 579 | ta HV_FAST_TRAP |
666 | stx %o1, [%g1] | 580 | stx %o1, [%g1] |
667 | retl | 581 | retl |
668 | nop | 582 | nop |
669 | .size sun4v_vintr_get_cookie, .-sun4v_vintr_get_cookie | 583 | ENDPROC(sun4v_vintr_get_cookie) |
670 | 584 | ||
671 | /* %o0: device handle | 585 | /* %o0: device handle |
672 | * %o1: device INO | 586 | * %o1: device INO |
@@ -674,14 +588,12 @@ sun4v_vintr_get_cookie: | |||
674 | * | 588 | * |
675 | * returns %o0: status | 589 | * returns %o0: status |
676 | */ | 590 | */ |
677 | .globl sun4v_vintr_set_cookie | 591 | ENTRY(sun4v_vintr_set_cookie) |
678 | .type sun4v_vintr_set_cookie,#function | ||
679 | sun4v_vintr_set_cookie: | ||
680 | mov HV_FAST_VINTR_SET_COOKIE, %o5 | 592 | mov HV_FAST_VINTR_SET_COOKIE, %o5 |
681 | ta HV_FAST_TRAP | 593 | ta HV_FAST_TRAP |
682 | retl | 594 | retl |
683 | nop | 595 | nop |
684 | .size sun4v_vintr_set_cookie, .-sun4v_vintr_set_cookie | 596 | ENDPROC(sun4v_vintr_set_cookie) |
685 | 597 | ||
686 | /* %o0: device handle | 598 | /* %o0: device handle |
687 | * %o1: device INO | 599 | * %o1: device INO |
@@ -689,16 +601,14 @@ sun4v_vintr_set_cookie: | |||
689 | * | 601 | * |
690 | * returns %o0: status | 602 | * returns %o0: status |
691 | */ | 603 | */ |
692 | .globl sun4v_vintr_get_valid | 604 | ENTRY(sun4v_vintr_get_valid) |
693 | .type sun4v_vintr_get_valid,#function | ||
694 | sun4v_vintr_get_valid: | ||
695 | mov %o2, %g1 | 605 | mov %o2, %g1 |
696 | mov HV_FAST_VINTR_GET_VALID, %o5 | 606 | mov HV_FAST_VINTR_GET_VALID, %o5 |
697 | ta HV_FAST_TRAP | 607 | ta HV_FAST_TRAP |
698 | stx %o1, [%g1] | 608 | stx %o1, [%g1] |
699 | retl | 609 | retl |
700 | nop | 610 | nop |
701 | .size sun4v_vintr_get_valid, .-sun4v_vintr_get_valid | 611 | ENDPROC(sun4v_vintr_get_valid) |
702 | 612 | ||
703 | /* %o0: device handle | 613 | /* %o0: device handle |
704 | * %o1: device INO | 614 | * %o1: device INO |
@@ -706,14 +616,12 @@ sun4v_vintr_get_valid: | |||
706 | * | 616 | * |
707 | * returns %o0: status | 617 | * returns %o0: status |
708 | */ | 618 | */ |
709 | .globl sun4v_vintr_set_valid | 619 | ENTRY(sun4v_vintr_set_valid) |
710 | .type sun4v_vintr_set_valid,#function | ||
711 | sun4v_vintr_set_valid: | ||
712 | mov HV_FAST_VINTR_SET_VALID, %o5 | 620 | mov HV_FAST_VINTR_SET_VALID, %o5 |
713 | ta HV_FAST_TRAP | 621 | ta HV_FAST_TRAP |
714 | retl | 622 | retl |
715 | nop | 623 | nop |
716 | .size sun4v_vintr_set_valid, .-sun4v_vintr_set_valid | 624 | ENDPROC(sun4v_vintr_set_valid) |
717 | 625 | ||
718 | /* %o0: device handle | 626 | /* %o0: device handle |
719 | * %o1: device INO | 627 | * %o1: device INO |
@@ -721,16 +629,14 @@ sun4v_vintr_set_valid: | |||
721 | * | 629 | * |
722 | * returns %o0: status | 630 | * returns %o0: status |
723 | */ | 631 | */ |
724 | .globl sun4v_vintr_get_state | 632 | ENTRY(sun4v_vintr_get_state) |
725 | .type sun4v_vintr_get_state,#function | ||
726 | sun4v_vintr_get_state: | ||
727 | mov %o2, %g1 | 633 | mov %o2, %g1 |
728 | mov HV_FAST_VINTR_GET_STATE, %o5 | 634 | mov HV_FAST_VINTR_GET_STATE, %o5 |
729 | ta HV_FAST_TRAP | 635 | ta HV_FAST_TRAP |
730 | stx %o1, [%g1] | 636 | stx %o1, [%g1] |
731 | retl | 637 | retl |
732 | nop | 638 | nop |
733 | .size sun4v_vintr_get_state, .-sun4v_vintr_get_state | 639 | ENDPROC(sun4v_vintr_get_state) |
734 | 640 | ||
735 | /* %o0: device handle | 641 | /* %o0: device handle |
736 | * %o1: device INO | 642 | * %o1: device INO |
@@ -738,14 +644,12 @@ sun4v_vintr_get_state: | |||
738 | * | 644 | * |
739 | * returns %o0: status | 645 | * returns %o0: status |
740 | */ | 646 | */ |
741 | .globl sun4v_vintr_set_state | 647 | ENTRY(sun4v_vintr_set_state) |
742 | .type sun4v_vintr_set_state,#function | ||
743 | sun4v_vintr_set_state: | ||
744 | mov HV_FAST_VINTR_SET_STATE, %o5 | 648 | mov HV_FAST_VINTR_SET_STATE, %o5 |
745 | ta HV_FAST_TRAP | 649 | ta HV_FAST_TRAP |
746 | retl | 650 | retl |
747 | nop | 651 | nop |
748 | .size sun4v_vintr_set_state, .-sun4v_vintr_set_state | 652 | ENDPROC(sun4v_vintr_set_state) |
749 | 653 | ||
750 | /* %o0: device handle | 654 | /* %o0: device handle |
751 | * %o1: device INO | 655 | * %o1: device INO |
@@ -753,16 +657,14 @@ sun4v_vintr_set_state: | |||
753 | * | 657 | * |
754 | * returns %o0: status | 658 | * returns %o0: status |
755 | */ | 659 | */ |
756 | .globl sun4v_vintr_get_target | 660 | ENTRY(sun4v_vintr_get_target) |
757 | .type sun4v_vintr_get_target,#function | ||
758 | sun4v_vintr_get_target: | ||
759 | mov %o2, %g1 | 661 | mov %o2, %g1 |
760 | mov HV_FAST_VINTR_GET_TARGET, %o5 | 662 | mov HV_FAST_VINTR_GET_TARGET, %o5 |
761 | ta HV_FAST_TRAP | 663 | ta HV_FAST_TRAP |
762 | stx %o1, [%g1] | 664 | stx %o1, [%g1] |
763 | retl | 665 | retl |
764 | nop | 666 | nop |
765 | .size sun4v_vintr_get_target, .-sun4v_vintr_get_target | 667 | ENDPROC(sun4v_vintr_get_target) |
766 | 668 | ||
767 | /* %o0: device handle | 669 | /* %o0: device handle |
768 | * %o1: device INO | 670 | * %o1: device INO |
@@ -770,14 +672,12 @@ sun4v_vintr_get_target: | |||
770 | * | 672 | * |
771 | * returns %o0: status | 673 | * returns %o0: status |
772 | */ | 674 | */ |
773 | .globl sun4v_vintr_set_target | 675 | ENTRY(sun4v_vintr_set_target) |
774 | .type sun4v_vintr_set_target,#function | ||
775 | sun4v_vintr_set_target: | ||
776 | mov HV_FAST_VINTR_SET_TARGET, %o5 | 676 | mov HV_FAST_VINTR_SET_TARGET, %o5 |
777 | ta HV_FAST_TRAP | 677 | ta HV_FAST_TRAP |
778 | retl | 678 | retl |
779 | nop | 679 | nop |
780 | .size sun4v_vintr_set_target, .-sun4v_vintr_set_target | 680 | ENDPROC(sun4v_vintr_set_target) |
781 | 681 | ||
782 | /* %o0: NCS sub-function | 682 | /* %o0: NCS sub-function |
783 | * %o1: sub-function arg real-address | 683 | * %o1: sub-function arg real-address |
@@ -785,18 +685,14 @@ sun4v_vintr_set_target: | |||
785 | * | 685 | * |
786 | * returns %o0: status | 686 | * returns %o0: status |
787 | */ | 687 | */ |
788 | .globl sun4v_ncs_request | 688 | ENTRY(sun4v_ncs_request) |
789 | .type sun4v_ncs_request,#function | ||
790 | sun4v_ncs_request: | ||
791 | mov HV_FAST_NCS_REQUEST, %o5 | 689 | mov HV_FAST_NCS_REQUEST, %o5 |
792 | ta HV_FAST_TRAP | 690 | ta HV_FAST_TRAP |
793 | retl | 691 | retl |
794 | nop | 692 | nop |
795 | .size sun4v_ncs_request, .-sun4v_ncs_request | 693 | ENDPROC(sun4v_ncs_request) |
796 | 694 | ||
797 | .globl sun4v_svc_send | 695 | ENTRY(sun4v_svc_send) |
798 | .type sun4v_svc_send,#function | ||
799 | sun4v_svc_send: | ||
800 | save %sp, -192, %sp | 696 | save %sp, -192, %sp |
801 | mov %i0, %o0 | 697 | mov %i0, %o0 |
802 | mov %i1, %o1 | 698 | mov %i1, %o1 |
@@ -806,11 +702,9 @@ sun4v_svc_send: | |||
806 | stx %o1, [%i3] | 702 | stx %o1, [%i3] |
807 | ret | 703 | ret |
808 | restore | 704 | restore |
809 | .size sun4v_svc_send, .-sun4v_svc_send | 705 | ENDPROC(sun4v_svc_send) |
810 | 706 | ||
811 | .globl sun4v_svc_recv | 707 | ENTRY(sun4v_svc_recv) |
812 | .type sun4v_svc_recv,#function | ||
813 | sun4v_svc_recv: | ||
814 | save %sp, -192, %sp | 708 | save %sp, -192, %sp |
815 | mov %i0, %o0 | 709 | mov %i0, %o0 |
816 | mov %i1, %o1 | 710 | mov %i1, %o1 |
@@ -820,62 +714,50 @@ sun4v_svc_recv: | |||
820 | stx %o1, [%i3] | 714 | stx %o1, [%i3] |
821 | ret | 715 | ret |
822 | restore | 716 | restore |
823 | .size sun4v_svc_recv, .-sun4v_svc_recv | 717 | ENDPROC(sun4v_svc_recv) |
824 | 718 | ||
825 | .globl sun4v_svc_getstatus | 719 | ENTRY(sun4v_svc_getstatus) |
826 | .type sun4v_svc_getstatus,#function | ||
827 | sun4v_svc_getstatus: | ||
828 | mov HV_FAST_SVC_GETSTATUS, %o5 | 720 | mov HV_FAST_SVC_GETSTATUS, %o5 |
829 | mov %o1, %o4 | 721 | mov %o1, %o4 |
830 | ta HV_FAST_TRAP | 722 | ta HV_FAST_TRAP |
831 | stx %o1, [%o4] | 723 | stx %o1, [%o4] |
832 | retl | 724 | retl |
833 | nop | 725 | nop |
834 | .size sun4v_svc_getstatus, .-sun4v_svc_getstatus | 726 | ENDPROC(sun4v_svc_getstatus) |
835 | 727 | ||
836 | .globl sun4v_svc_setstatus | 728 | ENTRY(sun4v_svc_setstatus) |
837 | .type sun4v_svc_setstatus,#function | ||
838 | sun4v_svc_setstatus: | ||
839 | mov HV_FAST_SVC_SETSTATUS, %o5 | 729 | mov HV_FAST_SVC_SETSTATUS, %o5 |
840 | ta HV_FAST_TRAP | 730 | ta HV_FAST_TRAP |
841 | retl | 731 | retl |
842 | nop | 732 | nop |
843 | .size sun4v_svc_setstatus, .-sun4v_svc_setstatus | 733 | ENDPROC(sun4v_svc_setstatus) |
844 | 734 | ||
845 | .globl sun4v_svc_clrstatus | 735 | ENTRY(sun4v_svc_clrstatus) |
846 | .type sun4v_svc_clrstatus,#function | ||
847 | sun4v_svc_clrstatus: | ||
848 | mov HV_FAST_SVC_CLRSTATUS, %o5 | 736 | mov HV_FAST_SVC_CLRSTATUS, %o5 |
849 | ta HV_FAST_TRAP | 737 | ta HV_FAST_TRAP |
850 | retl | 738 | retl |
851 | nop | 739 | nop |
852 | .size sun4v_svc_clrstatus, .-sun4v_svc_clrstatus | 740 | ENDPROC(sun4v_svc_clrstatus) |
853 | 741 | ||
854 | .globl sun4v_mmustat_conf | 742 | ENTRY(sun4v_mmustat_conf) |
855 | .type sun4v_mmustat_conf,#function | ||
856 | sun4v_mmustat_conf: | ||
857 | mov %o1, %o4 | 743 | mov %o1, %o4 |
858 | mov HV_FAST_MMUSTAT_CONF, %o5 | 744 | mov HV_FAST_MMUSTAT_CONF, %o5 |
859 | ta HV_FAST_TRAP | 745 | ta HV_FAST_TRAP |
860 | stx %o1, [%o4] | 746 | stx %o1, [%o4] |
861 | retl | 747 | retl |
862 | nop | 748 | nop |
863 | .size sun4v_mmustat_conf, .-sun4v_mmustat_conf | 749 | ENDPROC(sun4v_mmustat_conf) |
864 | 750 | ||
865 | .globl sun4v_mmustat_info | 751 | ENTRY(sun4v_mmustat_info) |
866 | .type sun4v_mmustat_info,#function | ||
867 | sun4v_mmustat_info: | ||
868 | mov %o0, %o4 | 752 | mov %o0, %o4 |
869 | mov HV_FAST_MMUSTAT_INFO, %o5 | 753 | mov HV_FAST_MMUSTAT_INFO, %o5 |
870 | ta HV_FAST_TRAP | 754 | ta HV_FAST_TRAP |
871 | stx %o1, [%o4] | 755 | stx %o1, [%o4] |
872 | retl | 756 | retl |
873 | nop | 757 | nop |
874 | .size sun4v_mmustat_info, .-sun4v_mmustat_info | 758 | ENDPROC(sun4v_mmustat_info) |
875 | 759 | ||
876 | .globl sun4v_mmu_demap_all | 760 | ENTRY(sun4v_mmu_demap_all) |
877 | .type sun4v_mmu_demap_all,#function | ||
878 | sun4v_mmu_demap_all: | ||
879 | clr %o0 | 761 | clr %o0 |
880 | clr %o1 | 762 | clr %o1 |
881 | mov HV_MMU_ALL, %o2 | 763 | mov HV_MMU_ALL, %o2 |
@@ -883,4 +765,4 @@ sun4v_mmu_demap_all: | |||
883 | ta HV_FAST_TRAP | 765 | ta HV_FAST_TRAP |
884 | retl | 766 | retl |
885 | nop | 767 | nop |
886 | .size sun4v_mmu_demap_all, .-sun4v_mmu_demap_all | 768 | ENDPROC(sun4v_mmu_demap_all) |
diff --git a/arch/sparc64/kernel/irq.c b/arch/sparc64/kernel/irq.c index 7495bc774685..52fc836f464d 100644 --- a/arch/sparc64/kernel/irq.c +++ b/arch/sparc64/kernel/irq.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <asm/system.h> | 29 | #include <asm/system.h> |
30 | #include <asm/irq.h> | 30 | #include <asm/irq.h> |
31 | #include <asm/io.h> | 31 | #include <asm/io.h> |
32 | #include <asm/sbus.h> | ||
33 | #include <asm/iommu.h> | 32 | #include <asm/iommu.h> |
34 | #include <asm/upa.h> | 33 | #include <asm/upa.h> |
35 | #include <asm/oplib.h> | 34 | #include <asm/oplib.h> |
diff --git a/arch/sparc64/kernel/of_device.c b/arch/sparc64/kernel/of_device.c index 100ebd527499..0f616ae3246c 100644 --- a/arch/sparc64/kernel/of_device.c +++ b/arch/sparc64/kernel/of_device.c | |||
@@ -55,15 +55,38 @@ struct of_device *of_find_device_by_node(struct device_node *dp) | |||
55 | } | 55 | } |
56 | EXPORT_SYMBOL(of_find_device_by_node); | 56 | EXPORT_SYMBOL(of_find_device_by_node); |
57 | 57 | ||
58 | #ifdef CONFIG_PCI | 58 | unsigned int irq_of_parse_and_map(struct device_node *node, int index) |
59 | struct bus_type ebus_bus_type; | 59 | { |
60 | EXPORT_SYMBOL(ebus_bus_type); | 60 | struct of_device *op = of_find_device_by_node(node); |
61 | #endif | 61 | |
62 | if (!op || index >= op->num_irqs) | ||
63 | return 0; | ||
64 | |||
65 | return op->irqs[index]; | ||
66 | } | ||
67 | EXPORT_SYMBOL(irq_of_parse_and_map); | ||
68 | |||
69 | /* Take the archdata values for IOMMU, STC, and HOSTDATA found in | ||
70 | * BUS and propagate to all child of_device objects. | ||
71 | */ | ||
72 | void of_propagate_archdata(struct of_device *bus) | ||
73 | { | ||
74 | struct dev_archdata *bus_sd = &bus->dev.archdata; | ||
75 | struct device_node *bus_dp = bus->node; | ||
76 | struct device_node *dp; | ||
62 | 77 | ||
63 | #ifdef CONFIG_SBUS | 78 | for (dp = bus_dp->child; dp; dp = dp->sibling) { |
64 | struct bus_type sbus_bus_type; | 79 | struct of_device *op = of_find_device_by_node(dp); |
65 | EXPORT_SYMBOL(sbus_bus_type); | 80 | |
66 | #endif | 81 | op->dev.archdata.iommu = bus_sd->iommu; |
82 | op->dev.archdata.stc = bus_sd->stc; | ||
83 | op->dev.archdata.host_controller = bus_sd->host_controller; | ||
84 | op->dev.archdata.numa_node = bus_sd->numa_node; | ||
85 | |||
86 | if (dp->child) | ||
87 | of_propagate_archdata(op); | ||
88 | } | ||
89 | } | ||
67 | 90 | ||
68 | struct bus_type of_platform_bus_type; | 91 | struct bus_type of_platform_bus_type; |
69 | EXPORT_SYMBOL(of_platform_bus_type); | 92 | EXPORT_SYMBOL(of_platform_bus_type); |
@@ -378,8 +401,7 @@ static int __init build_one_resource(struct device_node *parent, | |||
378 | int na, int ns, int pna) | 401 | int na, int ns, int pna) |
379 | { | 402 | { |
380 | const u32 *ranges; | 403 | const u32 *ranges; |
381 | unsigned int rlen; | 404 | int rone, rlen; |
382 | int rone; | ||
383 | 405 | ||
384 | ranges = of_get_property(parent, "ranges", &rlen); | 406 | ranges = of_get_property(parent, "ranges", &rlen); |
385 | if (ranges == NULL || rlen == 0) { | 407 | if (ranges == NULL || rlen == 0) { |
@@ -421,8 +443,17 @@ static int __init use_1to1_mapping(struct device_node *pp) | |||
421 | 443 | ||
422 | /* If the parent is the dma node of an ISA bus, pass | 444 | /* If the parent is the dma node of an ISA bus, pass |
423 | * the translation up to the root. | 445 | * the translation up to the root. |
446 | * | ||
447 | * Some SBUS devices use intermediate nodes to express | ||
448 | * hierarchy within the device itself. These aren't | ||
449 | * real bus nodes, and don't have a 'ranges' property. | ||
450 | * But, we should still pass the translation work up | ||
451 | * to the SBUS itself. | ||
424 | */ | 452 | */ |
425 | if (!strcmp(pp->name, "dma")) | 453 | if (!strcmp(pp->name, "dma") || |
454 | !strcmp(pp->name, "espdma") || | ||
455 | !strcmp(pp->name, "ledma") || | ||
456 | !strcmp(pp->name, "lebuffer")) | ||
426 | return 0; | 457 | return 0; |
427 | 458 | ||
428 | /* Similarly for all PCI bridges, if we get this far | 459 | /* Similarly for all PCI bridges, if we get this far |
@@ -844,15 +875,6 @@ static int __init of_bus_driver_init(void) | |||
844 | int err; | 875 | int err; |
845 | 876 | ||
846 | err = of_bus_type_init(&of_platform_bus_type, "of"); | 877 | err = of_bus_type_init(&of_platform_bus_type, "of"); |
847 | #ifdef CONFIG_PCI | ||
848 | if (!err) | ||
849 | err = of_bus_type_init(&ebus_bus_type, "ebus"); | ||
850 | #endif | ||
851 | #ifdef CONFIG_SBUS | ||
852 | if (!err) | ||
853 | err = of_bus_type_init(&sbus_bus_type, "sbus"); | ||
854 | #endif | ||
855 | |||
856 | if (!err) | 878 | if (!err) |
857 | scan_of_devices(); | 879 | scan_of_devices(); |
858 | 880 | ||
diff --git a/arch/sparc64/kernel/pci.c b/arch/sparc64/kernel/pci.c index 80dad76f8b81..242ac1ccae7d 100644 --- a/arch/sparc64/kernel/pci.c +++ b/arch/sparc64/kernel/pci.c | |||
@@ -18,32 +18,17 @@ | |||
18 | #include <linux/msi.h> | 18 | #include <linux/msi.h> |
19 | #include <linux/irq.h> | 19 | #include <linux/irq.h> |
20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
21 | #include <linux/of.h> | ||
22 | #include <linux/of_device.h> | ||
21 | 23 | ||
22 | #include <asm/uaccess.h> | 24 | #include <asm/uaccess.h> |
23 | #include <asm/pgtable.h> | 25 | #include <asm/pgtable.h> |
24 | #include <asm/irq.h> | 26 | #include <asm/irq.h> |
25 | #include <asm/ebus.h> | ||
26 | #include <asm/prom.h> | 27 | #include <asm/prom.h> |
27 | #include <asm/apb.h> | 28 | #include <asm/apb.h> |
28 | 29 | ||
29 | #include "pci_impl.h" | 30 | #include "pci_impl.h" |
30 | 31 | ||
31 | #ifndef CONFIG_PCI | ||
32 | /* A "nop" PCI implementation. */ | ||
33 | asmlinkage int sys_pciconfig_read(unsigned long bus, unsigned long dfn, | ||
34 | unsigned long off, unsigned long len, | ||
35 | unsigned char *buf) | ||
36 | { | ||
37 | return 0; | ||
38 | } | ||
39 | asmlinkage int sys_pciconfig_write(unsigned long bus, unsigned long dfn, | ||
40 | unsigned long off, unsigned long len, | ||
41 | unsigned char *buf) | ||
42 | { | ||
43 | return 0; | ||
44 | } | ||
45 | #else | ||
46 | |||
47 | /* List of all PCI controllers found in the system. */ | 32 | /* List of all PCI controllers found in the system. */ |
48 | struct pci_pbm_info *pci_pbm_root = NULL; | 33 | struct pci_pbm_info *pci_pbm_root = NULL; |
49 | 34 | ||
@@ -179,97 +164,6 @@ void pci_config_write32(u32 *addr, u32 val) | |||
179 | spin_unlock_irqrestore(&pci_poke_lock, flags); | 164 | spin_unlock_irqrestore(&pci_poke_lock, flags); |
180 | } | 165 | } |
181 | 166 | ||
182 | /* Probe for all PCI controllers in the system. */ | ||
183 | extern void sabre_init(struct device_node *, const char *); | ||
184 | extern void psycho_init(struct device_node *, const char *); | ||
185 | extern void schizo_init(struct device_node *, const char *); | ||
186 | extern void schizo_plus_init(struct device_node *, const char *); | ||
187 | extern void tomatillo_init(struct device_node *, const char *); | ||
188 | extern void sun4v_pci_init(struct device_node *, const char *); | ||
189 | extern void fire_pci_init(struct device_node *, const char *); | ||
190 | |||
191 | static struct { | ||
192 | char *model_name; | ||
193 | void (*init)(struct device_node *, const char *); | ||
194 | } pci_controller_table[] __initdata = { | ||
195 | { "SUNW,sabre", sabre_init }, | ||
196 | { "pci108e,a000", sabre_init }, | ||
197 | { "pci108e,a001", sabre_init }, | ||
198 | { "SUNW,psycho", psycho_init }, | ||
199 | { "pci108e,8000", psycho_init }, | ||
200 | { "SUNW,schizo", schizo_init }, | ||
201 | { "pci108e,8001", schizo_init }, | ||
202 | { "SUNW,schizo+", schizo_plus_init }, | ||
203 | { "pci108e,8002", schizo_plus_init }, | ||
204 | { "SUNW,tomatillo", tomatillo_init }, | ||
205 | { "pci108e,a801", tomatillo_init }, | ||
206 | { "SUNW,sun4v-pci", sun4v_pci_init }, | ||
207 | { "pciex108e,80f0", fire_pci_init }, | ||
208 | }; | ||
209 | #define PCI_NUM_CONTROLLER_TYPES ARRAY_SIZE(pci_controller_table) | ||
210 | |||
211 | static int __init pci_controller_init(const char *model_name, int namelen, struct device_node *dp) | ||
212 | { | ||
213 | int i; | ||
214 | |||
215 | for (i = 0; i < PCI_NUM_CONTROLLER_TYPES; i++) { | ||
216 | if (!strncmp(model_name, | ||
217 | pci_controller_table[i].model_name, | ||
218 | namelen)) { | ||
219 | pci_controller_table[i].init(dp, model_name); | ||
220 | return 1; | ||
221 | } | ||
222 | } | ||
223 | |||
224 | return 0; | ||
225 | } | ||
226 | |||
227 | static int __init pci_controller_scan(int (*handler)(const char *, int, struct device_node *)) | ||
228 | { | ||
229 | struct device_node *dp; | ||
230 | int count = 0; | ||
231 | |||
232 | for_each_node_by_name(dp, "pci") { | ||
233 | struct property *prop; | ||
234 | int len; | ||
235 | |||
236 | prop = of_find_property(dp, "model", &len); | ||
237 | if (!prop) | ||
238 | prop = of_find_property(dp, "compatible", &len); | ||
239 | |||
240 | if (prop) { | ||
241 | const char *model = prop->value; | ||
242 | int item_len = 0; | ||
243 | |||
244 | /* Our value may be a multi-valued string in the | ||
245 | * case of some compatible properties. For sanity, | ||
246 | * only try the first one. | ||
247 | */ | ||
248 | while (model[item_len] && len) { | ||
249 | len--; | ||
250 | item_len++; | ||
251 | } | ||
252 | |||
253 | if (handler(model, item_len, dp)) | ||
254 | count++; | ||
255 | } | ||
256 | } | ||
257 | |||
258 | return count; | ||
259 | } | ||
260 | |||
261 | /* Find each controller in the system, attach and initialize | ||
262 | * software state structure for each and link into the | ||
263 | * pci_pbm_root. Setup the controller enough such | ||
264 | * that bus scanning can be done. | ||
265 | */ | ||
266 | static void __init pci_controller_probe(void) | ||
267 | { | ||
268 | printk("PCI: Probing for controllers.\n"); | ||
269 | |||
270 | pci_controller_scan(pci_controller_init); | ||
271 | } | ||
272 | |||
273 | static int ofpci_verbose; | 167 | static int ofpci_verbose; |
274 | 168 | ||
275 | static int __init ofpci_debug(char *str) | 169 | static int __init ofpci_debug(char *str) |
@@ -348,11 +242,12 @@ static void pci_parse_of_addrs(struct of_device *op, | |||
348 | } | 242 | } |
349 | } | 243 | } |
350 | 244 | ||
351 | struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | 245 | static struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, |
352 | struct device_node *node, | 246 | struct device_node *node, |
353 | struct pci_bus *bus, int devfn) | 247 | struct pci_bus *bus, int devfn) |
354 | { | 248 | { |
355 | struct dev_archdata *sd; | 249 | struct dev_archdata *sd; |
250 | struct of_device *op; | ||
356 | struct pci_dev *dev; | 251 | struct pci_dev *dev; |
357 | const char *type; | 252 | const char *type; |
358 | u32 class; | 253 | u32 class; |
@@ -366,14 +261,17 @@ struct pci_dev *of_create_pci_dev(struct pci_pbm_info *pbm, | |||
366 | sd->stc = &pbm->stc; | 261 | sd->stc = &pbm->stc; |
367 | sd->host_controller = pbm; | 262 | sd->host_controller = pbm; |
368 | sd->prom_node = node; | 263 | sd->prom_node = node; |
369 | sd->op = of_find_device_by_node(node); | 264 | sd->op = op = of_find_device_by_node(node); |
370 | sd->numa_node = pbm->numa_node; | 265 | sd->numa_node = pbm->numa_node; |
371 | 266 | ||
372 | sd = &sd->op->dev.archdata; | 267 | sd = &op->dev.archdata; |
373 | sd->iommu = pbm->iommu; | 268 | sd->iommu = pbm->iommu; |
374 | sd->stc = &pbm->stc; | 269 | sd->stc = &pbm->stc; |
375 | sd->numa_node = pbm->numa_node; | 270 | sd->numa_node = pbm->numa_node; |
376 | 271 | ||
272 | if (!strcmp(node->name, "ebus")) | ||
273 | of_propagate_archdata(op); | ||
274 | |||
377 | type = of_get_property(node, "device_type", NULL); | 275 | type = of_get_property(node, "device_type", NULL); |
378 | if (type == NULL) | 276 | if (type == NULL) |
379 | type = ""; | 277 | type = ""; |
@@ -775,15 +673,15 @@ static void __devinit pci_bus_register_of_sysfs(struct pci_bus *bus) | |||
775 | pci_bus_register_of_sysfs(child_bus); | 673 | pci_bus_register_of_sysfs(child_bus); |
776 | } | 674 | } |
777 | 675 | ||
778 | struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) | 676 | struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm, |
677 | struct device *parent) | ||
779 | { | 678 | { |
780 | struct device_node *node = pbm->prom_node; | 679 | struct device_node *node = pbm->op->node; |
781 | struct pci_bus *bus; | 680 | struct pci_bus *bus; |
782 | 681 | ||
783 | printk("PCI: Scanning PBM %s\n", node->full_name); | 682 | printk("PCI: Scanning PBM %s\n", node->full_name); |
784 | 683 | ||
785 | /* XXX parent device? XXX */ | 684 | bus = pci_create_bus(parent, pbm->pci_first_busno, pbm->pci_ops, pbm); |
786 | bus = pci_create_bus(NULL, pbm->pci_first_busno, pbm->pci_ops, pbm); | ||
787 | if (!bus) { | 685 | if (!bus) { |
788 | printk(KERN_ERR "Failed to create bus for %s\n", | 686 | printk(KERN_ERR "Failed to create bus for %s\n", |
789 | node->full_name); | 687 | node->full_name); |
@@ -802,32 +700,6 @@ struct pci_bus * __devinit pci_scan_one_pbm(struct pci_pbm_info *pbm) | |||
802 | return bus; | 700 | return bus; |
803 | } | 701 | } |
804 | 702 | ||
805 | static void __init pci_scan_each_controller_bus(void) | ||
806 | { | ||
807 | struct pci_pbm_info *pbm; | ||
808 | |||
809 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) | ||
810 | pbm->scan_bus(pbm); | ||
811 | } | ||
812 | |||
813 | extern void power_init(void); | ||
814 | |||
815 | static int __init pcibios_init(void) | ||
816 | { | ||
817 | pci_controller_probe(); | ||
818 | if (pci_pbm_root == NULL) | ||
819 | return 0; | ||
820 | |||
821 | pci_scan_each_controller_bus(); | ||
822 | |||
823 | ebus_init(); | ||
824 | power_init(); | ||
825 | |||
826 | return 0; | ||
827 | } | ||
828 | |||
829 | subsys_initcall(pcibios_init); | ||
830 | |||
831 | void __devinit pcibios_fixup_bus(struct pci_bus *pbus) | 703 | void __devinit pcibios_fixup_bus(struct pci_bus *pbus) |
832 | { | 704 | { |
833 | struct pci_pbm_info *pbm = pbus->sysdata; | 705 | struct pci_pbm_info *pbm = pbus->sysdata; |
@@ -1105,14 +977,14 @@ int pcibus_to_node(struct pci_bus *pbus) | |||
1105 | EXPORT_SYMBOL(pcibus_to_node); | 977 | EXPORT_SYMBOL(pcibus_to_node); |
1106 | #endif | 978 | #endif |
1107 | 979 | ||
1108 | /* Return the domain nuber for this pci bus */ | 980 | /* Return the domain number for this pci bus */ |
1109 | 981 | ||
1110 | int pci_domain_nr(struct pci_bus *pbus) | 982 | int pci_domain_nr(struct pci_bus *pbus) |
1111 | { | 983 | { |
1112 | struct pci_pbm_info *pbm = pbus->sysdata; | 984 | struct pci_pbm_info *pbm = pbus->sysdata; |
1113 | int ret; | 985 | int ret; |
1114 | 986 | ||
1115 | if (pbm == NULL || pbm->parent == NULL) { | 987 | if (!pbm) { |
1116 | ret = -ENXIO; | 988 | ret = -ENXIO; |
1117 | } else { | 989 | } else { |
1118 | ret = pbm->index; | 990 | ret = pbm->index; |
@@ -1126,7 +998,7 @@ EXPORT_SYMBOL(pci_domain_nr); | |||
1126 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) | 998 | int arch_setup_msi_irq(struct pci_dev *pdev, struct msi_desc *desc) |
1127 | { | 999 | { |
1128 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; | 1000 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
1129 | int virt_irq; | 1001 | unsigned int virt_irq; |
1130 | 1002 | ||
1131 | if (!pbm->setup_msi_irq) | 1003 | if (!pbm->setup_msi_irq) |
1132 | return -EINVAL; | 1004 | return -EINVAL; |
@@ -1140,10 +1012,8 @@ void arch_teardown_msi_irq(unsigned int virt_irq) | |||
1140 | struct pci_dev *pdev = entry->dev; | 1012 | struct pci_dev *pdev = entry->dev; |
1141 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; | 1013 | struct pci_pbm_info *pbm = pdev->dev.archdata.host_controller; |
1142 | 1014 | ||
1143 | if (!pbm->teardown_msi_irq) | 1015 | if (pbm->teardown_msi_irq) |
1144 | return; | 1016 | pbm->teardown_msi_irq(virt_irq, pdev); |
1145 | |||
1146 | return pbm->teardown_msi_irq(virt_irq, pdev); | ||
1147 | } | 1017 | } |
1148 | #endif /* !(CONFIG_PCI_MSI) */ | 1018 | #endif /* !(CONFIG_PCI_MSI) */ |
1149 | 1019 | ||
@@ -1215,5 +1085,3 @@ void pci_resource_to_user(const struct pci_dev *pdev, int bar, | |||
1215 | *start = rp->start - offset; | 1085 | *start = rp->start - offset; |
1216 | *end = rp->end - offset; | 1086 | *end = rp->end - offset; |
1217 | } | 1087 | } |
1218 | |||
1219 | #endif /* !(CONFIG_PCI) */ | ||
diff --git a/arch/sparc64/kernel/pci_common.c b/arch/sparc64/kernel/pci_common.c index 09a5ec200c61..23b88082d0b2 100644 --- a/arch/sparc64/kernel/pci_common.c +++ b/arch/sparc64/kernel/pci_common.c | |||
@@ -314,12 +314,12 @@ struct pci_ops sun4v_pci_ops = { | |||
314 | 314 | ||
315 | void pci_get_pbm_props(struct pci_pbm_info *pbm) | 315 | void pci_get_pbm_props(struct pci_pbm_info *pbm) |
316 | { | 316 | { |
317 | const u32 *val = of_get_property(pbm->prom_node, "bus-range", NULL); | 317 | const u32 *val = of_get_property(pbm->op->node, "bus-range", NULL); |
318 | 318 | ||
319 | pbm->pci_first_busno = val[0]; | 319 | pbm->pci_first_busno = val[0]; |
320 | pbm->pci_last_busno = val[1]; | 320 | pbm->pci_last_busno = val[1]; |
321 | 321 | ||
322 | val = of_get_property(pbm->prom_node, "ino-bitmap", NULL); | 322 | val = of_get_property(pbm->op->node, "ino-bitmap", NULL); |
323 | if (val) { | 323 | if (val) { |
324 | pbm->ino_bitmap = (((u64)val[1] << 32UL) | | 324 | pbm->ino_bitmap = (((u64)val[1] << 32UL) | |
325 | ((u64)val[0] << 0UL)); | 325 | ((u64)val[0] << 0UL)); |
@@ -365,7 +365,7 @@ static void pci_register_legacy_regions(struct resource *io_res, | |||
365 | 365 | ||
366 | static void pci_register_iommu_region(struct pci_pbm_info *pbm) | 366 | static void pci_register_iommu_region(struct pci_pbm_info *pbm) |
367 | { | 367 | { |
368 | const u32 *vdma = of_get_property(pbm->prom_node, "virtual-dma", NULL); | 368 | const u32 *vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); |
369 | 369 | ||
370 | if (vdma) { | 370 | if (vdma) { |
371 | struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL); | 371 | struct resource *rp = kmalloc(sizeof(*rp), GFP_KERNEL); |
@@ -389,7 +389,7 @@ void pci_determine_mem_io_space(struct pci_pbm_info *pbm) | |||
389 | int num_pbm_ranges; | 389 | int num_pbm_ranges; |
390 | 390 | ||
391 | saw_mem = saw_io = 0; | 391 | saw_mem = saw_io = 0; |
392 | pbm_ranges = of_get_property(pbm->prom_node, "ranges", &i); | 392 | pbm_ranges = of_get_property(pbm->op->node, "ranges", &i); |
393 | if (!pbm_ranges) { | 393 | if (!pbm_ranges) { |
394 | prom_printf("PCI: Fatal error, missing PBM ranges property " | 394 | prom_printf("PCI: Fatal error, missing PBM ranges property " |
395 | " for %s\n", | 395 | " for %s\n", |
diff --git a/arch/sparc64/kernel/pci_fire.c b/arch/sparc64/kernel/pci_fire.c index d23bb6f53cda..9462b68f4894 100644 --- a/arch/sparc64/kernel/pci_fire.c +++ b/arch/sparc64/kernel/pci_fire.c | |||
@@ -8,34 +8,16 @@ | |||
8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
9 | #include <linux/msi.h> | 9 | #include <linux/msi.h> |
10 | #include <linux/irq.h> | 10 | #include <linux/irq.h> |
11 | #include <linux/of_device.h> | ||
11 | 12 | ||
12 | #include <asm/oplib.h> | ||
13 | #include <asm/prom.h> | 13 | #include <asm/prom.h> |
14 | #include <asm/irq.h> | 14 | #include <asm/irq.h> |
15 | #include <asm/upa.h> | ||
15 | 16 | ||
16 | #include "pci_impl.h" | 17 | #include "pci_impl.h" |
17 | 18 | ||
18 | #define fire_read(__reg) \ | 19 | #define DRIVER_NAME "fire" |
19 | ({ u64 __ret; \ | 20 | #define PFX DRIVER_NAME ": " |
20 | __asm__ __volatile__("ldxa [%1] %2, %0" \ | ||
21 | : "=r" (__ret) \ | ||
22 | : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
23 | : "memory"); \ | ||
24 | __ret; \ | ||
25 | }) | ||
26 | #define fire_write(__reg, __val) \ | ||
27 | __asm__ __volatile__("stxa %0, [%1] %2" \ | ||
28 | : /* no outputs */ \ | ||
29 | : "r" (__val), "r" (__reg), \ | ||
30 | "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
31 | : "memory") | ||
32 | |||
33 | static void __init pci_fire_scan_bus(struct pci_pbm_info *pbm) | ||
34 | { | ||
35 | pbm->pci_bus = pci_scan_one_pbm(pbm); | ||
36 | |||
37 | /* XXX register error interrupt handlers XXX */ | ||
38 | } | ||
39 | 21 | ||
40 | #define FIRE_IOMMU_CONTROL 0x40000UL | 22 | #define FIRE_IOMMU_CONTROL 0x40000UL |
41 | #define FIRE_IOMMU_TSBBASE 0x40008UL | 23 | #define FIRE_IOMMU_TSBBASE 0x40008UL |
@@ -69,21 +51,21 @@ static int pci_fire_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
69 | /* | 51 | /* |
70 | * Invalidate TLB Entries. | 52 | * Invalidate TLB Entries. |
71 | */ | 53 | */ |
72 | fire_write(iommu->iommu_flushinv, ~(u64)0); | 54 | upa_writeq(~(u64)0, iommu->iommu_flushinv); |
73 | 55 | ||
74 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, | 56 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, |
75 | pbm->numa_node); | 57 | pbm->numa_node); |
76 | if (err) | 58 | if (err) |
77 | return err; | 59 | return err; |
78 | 60 | ||
79 | fire_write(iommu->iommu_tsbbase, __pa(iommu->page_table) | 0x7UL); | 61 | upa_writeq(__pa(iommu->page_table) | 0x7UL, iommu->iommu_tsbbase); |
80 | 62 | ||
81 | control = fire_read(iommu->iommu_control); | 63 | control = upa_readq(iommu->iommu_control); |
82 | control |= (0x00000400 /* TSB cache snoop enable */ | | 64 | control |= (0x00000400 /* TSB cache snoop enable */ | |
83 | 0x00000300 /* Cache mode */ | | 65 | 0x00000300 /* Cache mode */ | |
84 | 0x00000002 /* Bypass enable */ | | 66 | 0x00000002 /* Bypass enable */ | |
85 | 0x00000001 /* Translation enable */); | 67 | 0x00000001 /* Translation enable */); |
86 | fire_write(iommu->iommu_control, control); | 68 | upa_writeq(control, iommu->iommu_control); |
87 | 69 | ||
88 | return 0; | 70 | return 0; |
89 | } | 71 | } |
@@ -165,7 +147,7 @@ struct pci_msiq_entry { | |||
165 | static int pci_fire_get_head(struct pci_pbm_info *pbm, unsigned long msiqid, | 147 | static int pci_fire_get_head(struct pci_pbm_info *pbm, unsigned long msiqid, |
166 | unsigned long *head) | 148 | unsigned long *head) |
167 | { | 149 | { |
168 | *head = fire_read(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); | 150 | *head = upa_readq(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); |
169 | return 0; | 151 | return 0; |
170 | } | 152 | } |
171 | 153 | ||
@@ -191,8 +173,7 @@ static int pci_fire_dequeue_msi(struct pci_pbm_info *pbm, unsigned long msiqid, | |||
191 | *msi = msi_num = ((ep->word0 & MSIQ_WORD0_DATA0) >> | 173 | *msi = msi_num = ((ep->word0 & MSIQ_WORD0_DATA0) >> |
192 | MSIQ_WORD0_DATA0_SHIFT); | 174 | MSIQ_WORD0_DATA0_SHIFT); |
193 | 175 | ||
194 | fire_write(pbm->pbm_regs + MSI_CLEAR(msi_num), | 176 | upa_writeq(MSI_CLEAR_EQWR_N, pbm->pbm_regs + MSI_CLEAR(msi_num)); |
195 | MSI_CLEAR_EQWR_N); | ||
196 | 177 | ||
197 | /* Clear the entry. */ | 178 | /* Clear the entry. */ |
198 | ep->word0 &= ~MSIQ_WORD0_FMT_TYPE; | 179 | ep->word0 &= ~MSIQ_WORD0_FMT_TYPE; |
@@ -208,7 +189,7 @@ static int pci_fire_dequeue_msi(struct pci_pbm_info *pbm, unsigned long msiqid, | |||
208 | static int pci_fire_set_head(struct pci_pbm_info *pbm, unsigned long msiqid, | 189 | static int pci_fire_set_head(struct pci_pbm_info *pbm, unsigned long msiqid, |
209 | unsigned long head) | 190 | unsigned long head) |
210 | { | 191 | { |
211 | fire_write(pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid), head); | 192 | upa_writeq(head, pbm->pbm_regs + EVENT_QUEUE_HEAD(msiqid)); |
212 | return 0; | 193 | return 0; |
213 | } | 194 | } |
214 | 195 | ||
@@ -217,17 +198,16 @@ static int pci_fire_msi_setup(struct pci_pbm_info *pbm, unsigned long msiqid, | |||
217 | { | 198 | { |
218 | u64 val; | 199 | u64 val; |
219 | 200 | ||
220 | val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); | 201 | val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); |
221 | val &= ~(MSI_MAP_EQNUM); | 202 | val &= ~(MSI_MAP_EQNUM); |
222 | val |= msiqid; | 203 | val |= msiqid; |
223 | fire_write(pbm->pbm_regs + MSI_MAP(msi), val); | 204 | upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); |
224 | 205 | ||
225 | fire_write(pbm->pbm_regs + MSI_CLEAR(msi), | 206 | upa_writeq(MSI_CLEAR_EQWR_N, pbm->pbm_regs + MSI_CLEAR(msi)); |
226 | MSI_CLEAR_EQWR_N); | ||
227 | 207 | ||
228 | val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); | 208 | val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); |
229 | val |= MSI_MAP_VALID; | 209 | val |= MSI_MAP_VALID; |
230 | fire_write(pbm->pbm_regs + MSI_MAP(msi), val); | 210 | upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); |
231 | 211 | ||
232 | return 0; | 212 | return 0; |
233 | } | 213 | } |
@@ -237,12 +217,12 @@ static int pci_fire_msi_teardown(struct pci_pbm_info *pbm, unsigned long msi) | |||
237 | unsigned long msiqid; | 217 | unsigned long msiqid; |
238 | u64 val; | 218 | u64 val; |
239 | 219 | ||
240 | val = fire_read(pbm->pbm_regs + MSI_MAP(msi)); | 220 | val = upa_readq(pbm->pbm_regs + MSI_MAP(msi)); |
241 | msiqid = (val & MSI_MAP_EQNUM); | 221 | msiqid = (val & MSI_MAP_EQNUM); |
242 | 222 | ||
243 | val &= ~MSI_MAP_VALID; | 223 | val &= ~MSI_MAP_VALID; |
244 | 224 | ||
245 | fire_write(pbm->pbm_regs + MSI_MAP(msi), val); | 225 | upa_writeq(val, pbm->pbm_regs + MSI_MAP(msi)); |
246 | 226 | ||
247 | return 0; | 227 | return 0; |
248 | } | 228 | } |
@@ -261,22 +241,19 @@ static int pci_fire_msiq_alloc(struct pci_pbm_info *pbm) | |||
261 | memset((char *)pages, 0, PAGE_SIZE << order); | 241 | memset((char *)pages, 0, PAGE_SIZE << order); |
262 | pbm->msi_queues = (void *) pages; | 242 | pbm->msi_queues = (void *) pages; |
263 | 243 | ||
264 | fire_write(pbm->pbm_regs + EVENT_QUEUE_BASE_ADDR_REG, | 244 | upa_writeq((EVENT_QUEUE_BASE_ADDR_ALL_ONES | |
265 | (EVENT_QUEUE_BASE_ADDR_ALL_ONES | | 245 | __pa(pbm->msi_queues)), |
266 | __pa(pbm->msi_queues))); | 246 | pbm->pbm_regs + EVENT_QUEUE_BASE_ADDR_REG); |
267 | 247 | ||
268 | fire_write(pbm->pbm_regs + IMONDO_DATA0, | 248 | upa_writeq(pbm->portid << 6, pbm->pbm_regs + IMONDO_DATA0); |
269 | pbm->portid << 6); | 249 | upa_writeq(0, pbm->pbm_regs + IMONDO_DATA1); |
270 | fire_write(pbm->pbm_regs + IMONDO_DATA1, 0); | ||
271 | 250 | ||
272 | fire_write(pbm->pbm_regs + MSI_32BIT_ADDR, | 251 | upa_writeq(pbm->msi32_start, pbm->pbm_regs + MSI_32BIT_ADDR); |
273 | pbm->msi32_start); | 252 | upa_writeq(pbm->msi64_start, pbm->pbm_regs + MSI_64BIT_ADDR); |
274 | fire_write(pbm->pbm_regs + MSI_64BIT_ADDR, | ||
275 | pbm->msi64_start); | ||
276 | 253 | ||
277 | for (i = 0; i < pbm->msiq_num; i++) { | 254 | for (i = 0; i < pbm->msiq_num; i++) { |
278 | fire_write(pbm->pbm_regs + EVENT_QUEUE_HEAD(i), 0); | 255 | upa_writeq(0, pbm->pbm_regs + EVENT_QUEUE_HEAD(i)); |
279 | fire_write(pbm->pbm_regs + EVENT_QUEUE_TAIL(i), 0); | 256 | upa_writeq(0, pbm->pbm_regs + EVENT_QUEUE_TAIL(i)); |
280 | } | 257 | } |
281 | 258 | ||
282 | return 0; | 259 | return 0; |
@@ -310,9 +287,9 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, | |||
310 | /* XXX iterate amongst the 4 IRQ controllers XXX */ | 287 | /* XXX iterate amongst the 4 IRQ controllers XXX */ |
311 | int_ctrlr = (1UL << 6); | 288 | int_ctrlr = (1UL << 6); |
312 | 289 | ||
313 | val = fire_read(imap_reg); | 290 | val = upa_readq(imap_reg); |
314 | val |= (1UL << 63) | int_ctrlr; | 291 | val |= (1UL << 63) | int_ctrlr; |
315 | fire_write(imap_reg, val); | 292 | upa_writeq(val, imap_reg); |
316 | 293 | ||
317 | fixup = ((pbm->portid << 6) | devino) - int_ctrlr; | 294 | fixup = ((pbm->portid << 6) | devino) - int_ctrlr; |
318 | 295 | ||
@@ -320,9 +297,8 @@ static int pci_fire_msiq_build_irq(struct pci_pbm_info *pbm, | |||
320 | if (!virt_irq) | 297 | if (!virt_irq) |
321 | return -ENOMEM; | 298 | return -ENOMEM; |
322 | 299 | ||
323 | fire_write(pbm->pbm_regs + | 300 | upa_writeq(EVENT_QUEUE_CONTROL_SET_EN, |
324 | EVENT_QUEUE_CONTROL_SET(msiqid), | 301 | pbm->pbm_regs + EVENT_QUEUE_CONTROL_SET(msiqid)); |
325 | EVENT_QUEUE_CONTROL_SET_EN); | ||
326 | 302 | ||
327 | return virt_irq; | 303 | return virt_irq; |
328 | } | 304 | } |
@@ -390,77 +366,65 @@ static void pci_fire_hw_init(struct pci_pbm_info *pbm) | |||
390 | { | 366 | { |
391 | u64 val; | 367 | u64 val; |
392 | 368 | ||
393 | fire_write(pbm->controller_regs + FIRE_PARITY_CONTROL, | 369 | upa_writeq(FIRE_PARITY_ENAB, |
394 | FIRE_PARITY_ENAB); | 370 | pbm->controller_regs + FIRE_PARITY_CONTROL); |
395 | 371 | ||
396 | fire_write(pbm->controller_regs + FIRE_FATAL_RESET_CTL, | 372 | upa_writeq((FIRE_FATAL_RESET_SPARE | |
397 | (FIRE_FATAL_RESET_SPARE | | ||
398 | FIRE_FATAL_RESET_MB | | 373 | FIRE_FATAL_RESET_MB | |
399 | FIRE_FATAL_RESET_CPE | | 374 | FIRE_FATAL_RESET_CPE | |
400 | FIRE_FATAL_RESET_APE | | 375 | FIRE_FATAL_RESET_APE | |
401 | FIRE_FATAL_RESET_PIO | | 376 | FIRE_FATAL_RESET_PIO | |
402 | FIRE_FATAL_RESET_JW | | 377 | FIRE_FATAL_RESET_JW | |
403 | FIRE_FATAL_RESET_JI | | 378 | FIRE_FATAL_RESET_JI | |
404 | FIRE_FATAL_RESET_JR)); | 379 | FIRE_FATAL_RESET_JR), |
380 | pbm->controller_regs + FIRE_FATAL_RESET_CTL); | ||
405 | 381 | ||
406 | fire_write(pbm->controller_regs + FIRE_CORE_INTR_ENABLE, ~(u64)0); | 382 | upa_writeq(~(u64)0, pbm->controller_regs + FIRE_CORE_INTR_ENABLE); |
407 | 383 | ||
408 | val = fire_read(pbm->pbm_regs + FIRE_TLU_CTRL); | 384 | val = upa_readq(pbm->pbm_regs + FIRE_TLU_CTRL); |
409 | val |= (FIRE_TLU_CTRL_TIM | | 385 | val |= (FIRE_TLU_CTRL_TIM | |
410 | FIRE_TLU_CTRL_QDET | | 386 | FIRE_TLU_CTRL_QDET | |
411 | FIRE_TLU_CTRL_CFG); | 387 | FIRE_TLU_CTRL_CFG); |
412 | fire_write(pbm->pbm_regs + FIRE_TLU_CTRL, val); | 388 | upa_writeq(val, pbm->pbm_regs + FIRE_TLU_CTRL); |
413 | fire_write(pbm->pbm_regs + FIRE_TLU_DEV_CTRL, 0); | 389 | upa_writeq(0, pbm->pbm_regs + FIRE_TLU_DEV_CTRL); |
414 | fire_write(pbm->pbm_regs + FIRE_TLU_LINK_CTRL, | 390 | upa_writeq(FIRE_TLU_LINK_CTRL_CLK, |
415 | FIRE_TLU_LINK_CTRL_CLK); | 391 | pbm->pbm_regs + FIRE_TLU_LINK_CTRL); |
416 | 392 | ||
417 | fire_write(pbm->pbm_regs + FIRE_LPU_RESET, 0); | 393 | upa_writeq(0, pbm->pbm_regs + FIRE_LPU_RESET); |
418 | fire_write(pbm->pbm_regs + FIRE_LPU_LLCFG, | 394 | upa_writeq(FIRE_LPU_LLCFG_VC0, pbm->pbm_regs + FIRE_LPU_LLCFG); |
419 | FIRE_LPU_LLCFG_VC0); | 395 | upa_writeq((FIRE_LPU_FCTRL_UCTRL_N | FIRE_LPU_FCTRL_UCTRL_P), |
420 | fire_write(pbm->pbm_regs + FIRE_LPU_FCTRL_UCTRL, | 396 | pbm->pbm_regs + FIRE_LPU_FCTRL_UCTRL); |
421 | (FIRE_LPU_FCTRL_UCTRL_N | | 397 | upa_writeq(((0xffff << 16) | (0x0000 << 0)), |
422 | FIRE_LPU_FCTRL_UCTRL_P)); | 398 | pbm->pbm_regs + FIRE_LPU_TXL_FIFOP); |
423 | fire_write(pbm->pbm_regs + FIRE_LPU_TXL_FIFOP, | 399 | upa_writeq(3000000, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG2); |
424 | ((0xffff << 16) | (0x0000 << 0))); | 400 | upa_writeq(500000, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG3); |
425 | fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG2, 3000000); | 401 | upa_writeq((2 << 16) | (140 << 8), |
426 | fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG3, 500000); | 402 | pbm->pbm_regs + FIRE_LPU_LTSSM_CFG4); |
427 | fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG4, | 403 | upa_writeq(0, pbm->pbm_regs + FIRE_LPU_LTSSM_CFG5); |
428 | (2 << 16) | (140 << 8)); | 404 | |
429 | fire_write(pbm->pbm_regs + FIRE_LPU_LTSSM_CFG5, 0); | 405 | upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_DMC_IENAB); |
430 | 406 | upa_writeq(0, pbm->pbm_regs + FIRE_DMC_DBG_SEL_A); | |
431 | fire_write(pbm->pbm_regs + FIRE_DMC_IENAB, ~(u64)0); | 407 | upa_writeq(0, pbm->pbm_regs + FIRE_DMC_DBG_SEL_B); |
432 | fire_write(pbm->pbm_regs + FIRE_DMC_DBG_SEL_A, 0); | 408 | |
433 | fire_write(pbm->pbm_regs + FIRE_DMC_DBG_SEL_B, 0); | 409 | upa_writeq(~(u64)0, pbm->pbm_regs + FIRE_PEC_IENAB); |
434 | |||
435 | fire_write(pbm->pbm_regs + FIRE_PEC_IENAB, ~(u64)0); | ||
436 | } | 410 | } |
437 | 411 | ||
438 | static int __init pci_fire_pbm_init(struct pci_controller_info *p, | 412 | static int __init pci_fire_pbm_init(struct pci_pbm_info *pbm, |
439 | struct device_node *dp, u32 portid) | 413 | struct of_device *op, u32 portid) |
440 | { | 414 | { |
441 | const struct linux_prom64_registers *regs; | 415 | const struct linux_prom64_registers *regs; |
442 | struct pci_pbm_info *pbm; | 416 | struct device_node *dp = op->node; |
443 | int err; | 417 | int err; |
444 | 418 | ||
445 | if ((portid & 1) == 0) | ||
446 | pbm = &p->pbm_A; | ||
447 | else | ||
448 | pbm = &p->pbm_B; | ||
449 | |||
450 | pbm->next = pci_pbm_root; | ||
451 | pci_pbm_root = pbm; | ||
452 | |||
453 | pbm->numa_node = -1; | 419 | pbm->numa_node = -1; |
454 | 420 | ||
455 | pbm->scan_bus = pci_fire_scan_bus; | ||
456 | pbm->pci_ops = &sun4u_pci_ops; | 421 | pbm->pci_ops = &sun4u_pci_ops; |
457 | pbm->config_space_reg_bits = 12; | 422 | pbm->config_space_reg_bits = 12; |
458 | 423 | ||
459 | pbm->index = pci_num_pbms++; | 424 | pbm->index = pci_num_pbms++; |
460 | 425 | ||
461 | pbm->portid = portid; | 426 | pbm->portid = portid; |
462 | pbm->parent = p; | 427 | pbm->op = op; |
463 | pbm->prom_node = dp; | ||
464 | pbm->name = dp->full_name; | 428 | pbm->name = dp->full_name; |
465 | 429 | ||
466 | regs = of_get_property(dp, "reg", NULL); | 430 | regs = of_get_property(dp, "reg", NULL); |
@@ -481,53 +445,77 @@ static int __init pci_fire_pbm_init(struct pci_controller_info *p, | |||
481 | 445 | ||
482 | pci_fire_msi_init(pbm); | 446 | pci_fire_msi_init(pbm); |
483 | 447 | ||
484 | return 0; | 448 | pbm->pci_bus = pci_scan_one_pbm(pbm, &op->dev); |
485 | } | 449 | |
450 | /* XXX register error interrupt handlers XXX */ | ||
451 | |||
452 | pbm->next = pci_pbm_root; | ||
453 | pci_pbm_root = pbm; | ||
486 | 454 | ||
487 | static inline int portid_compare(u32 x, u32 y) | ||
488 | { | ||
489 | if (x == (y ^ 1)) | ||
490 | return 1; | ||
491 | return 0; | 455 | return 0; |
492 | } | 456 | } |
493 | 457 | ||
494 | void __init fire_pci_init(struct device_node *dp, const char *model_name) | 458 | static int __devinit fire_probe(struct of_device *op, |
459 | const struct of_device_id *match) | ||
495 | { | 460 | { |
496 | struct pci_controller_info *p; | 461 | struct device_node *dp = op->node; |
497 | u32 portid = of_getintprop_default(dp, "portid", 0xff); | ||
498 | struct iommu *iommu; | ||
499 | struct pci_pbm_info *pbm; | 462 | struct pci_pbm_info *pbm; |
463 | struct iommu *iommu; | ||
464 | u32 portid; | ||
465 | int err; | ||
500 | 466 | ||
501 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 467 | portid = of_getintprop_default(dp, "portid", 0xff); |
502 | if (portid_compare(pbm->portid, portid)) { | 468 | |
503 | if (pci_fire_pbm_init(pbm->parent, dp, portid)) | 469 | err = -ENOMEM; |
504 | goto fatal_memory_error; | 470 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
505 | return; | 471 | if (!pbm) { |
506 | } | 472 | printk(KERN_ERR PFX "Cannot allocate pci_pbminfo.\n"); |
473 | goto out_err; | ||
507 | } | 474 | } |
508 | 475 | ||
509 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); | 476 | iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); |
510 | if (!p) | 477 | if (!iommu) { |
511 | goto fatal_memory_error; | 478 | printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); |
479 | goto out_free_controller; | ||
480 | } | ||
512 | 481 | ||
513 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 482 | pbm->iommu = iommu; |
514 | if (!iommu) | ||
515 | goto fatal_memory_error; | ||
516 | 483 | ||
517 | p->pbm_A.iommu = iommu; | 484 | err = pci_fire_pbm_init(pbm, op, portid); |
485 | if (err) | ||
486 | goto out_free_iommu; | ||
518 | 487 | ||
519 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 488 | dev_set_drvdata(&op->dev, pbm); |
520 | if (!iommu) | ||
521 | goto fatal_memory_error; | ||
522 | 489 | ||
523 | p->pbm_B.iommu = iommu; | 490 | return 0; |
524 | 491 | ||
525 | if (pci_fire_pbm_init(p, dp, portid)) | 492 | out_free_iommu: |
526 | goto fatal_memory_error; | 493 | kfree(pbm->iommu); |
494 | |||
495 | out_free_controller: | ||
496 | kfree(pbm); | ||
527 | 497 | ||
528 | return; | 498 | out_err: |
499 | return err; | ||
500 | } | ||
501 | |||
502 | static struct of_device_id __initdata fire_match[] = { | ||
503 | { | ||
504 | .name = "pci", | ||
505 | .compatible = "pciex108e,80f0", | ||
506 | }, | ||
507 | {}, | ||
508 | }; | ||
529 | 509 | ||
530 | fatal_memory_error: | 510 | static struct of_platform_driver fire_driver = { |
531 | prom_printf("PCI_FIRE: Fatal memory allocation error.\n"); | 511 | .name = DRIVER_NAME, |
532 | prom_halt(); | 512 | .match_table = fire_match, |
513 | .probe = fire_probe, | ||
514 | }; | ||
515 | |||
516 | static int __init fire_init(void) | ||
517 | { | ||
518 | return of_register_driver(&fire_driver, &of_bus_type); | ||
533 | } | 519 | } |
520 | |||
521 | subsys_initcall(fire_init); | ||
diff --git a/arch/sparc64/kernel/pci_impl.h b/arch/sparc64/kernel/pci_impl.h index c385d126be11..03186824327e 100644 --- a/arch/sparc64/kernel/pci_impl.h +++ b/arch/sparc64/kernel/pci_impl.h | |||
@@ -10,6 +10,7 @@ | |||
10 | #include <linux/spinlock.h> | 10 | #include <linux/spinlock.h> |
11 | #include <linux/pci.h> | 11 | #include <linux/pci.h> |
12 | #include <linux/msi.h> | 12 | #include <linux/msi.h> |
13 | #include <linux/of_device.h> | ||
13 | #include <asm/io.h> | 14 | #include <asm/io.h> |
14 | #include <asm/prom.h> | 15 | #include <asm/prom.h> |
15 | #include <asm/iommu.h> | 16 | #include <asm/iommu.h> |
@@ -56,15 +57,11 @@ struct sparc64_msiq_cookie { | |||
56 | }; | 57 | }; |
57 | #endif | 58 | #endif |
58 | 59 | ||
59 | struct pci_controller_info; | ||
60 | |||
61 | struct pci_pbm_info { | 60 | struct pci_pbm_info { |
62 | struct pci_pbm_info *next; | 61 | struct pci_pbm_info *next; |
62 | struct pci_pbm_info *sibling; | ||
63 | int index; | 63 | int index; |
64 | 64 | ||
65 | /* PCI controller we sit under. */ | ||
66 | struct pci_controller_info *parent; | ||
67 | |||
68 | /* Physical address base of controller registers. */ | 65 | /* Physical address base of controller registers. */ |
69 | unsigned long controller_regs; | 66 | unsigned long controller_regs; |
70 | 67 | ||
@@ -94,7 +91,7 @@ struct pci_pbm_info { | |||
94 | char *name; | 91 | char *name; |
95 | 92 | ||
96 | /* OBP specific information. */ | 93 | /* OBP specific information. */ |
97 | struct device_node *prom_node; | 94 | struct of_device *op; |
98 | u64 ino_bitmap; | 95 | u64 ino_bitmap; |
99 | 96 | ||
100 | /* PBM I/O and Memory space resources. */ | 97 | /* PBM I/O and Memory space resources. */ |
@@ -107,6 +104,10 @@ struct pci_pbm_info { | |||
107 | /* This will be 12 on PCI-E controllers, 8 elsewhere. */ | 104 | /* This will be 12 on PCI-E controllers, 8 elsewhere. */ |
108 | unsigned long config_space_reg_bits; | 105 | unsigned long config_space_reg_bits; |
109 | 106 | ||
107 | unsigned long pci_afsr; | ||
108 | unsigned long pci_afar; | ||
109 | unsigned long pci_csr; | ||
110 | |||
110 | /* State of 66MHz capabilities on this PBM. */ | 111 | /* State of 66MHz capabilities on this PBM. */ |
111 | int is_66mhz_capable; | 112 | int is_66mhz_capable; |
112 | int all_devs_66mhz; | 113 | int all_devs_66mhz; |
@@ -146,25 +147,19 @@ struct pci_pbm_info { | |||
146 | unsigned int pci_first_busno; | 147 | unsigned int pci_first_busno; |
147 | unsigned int pci_last_busno; | 148 | unsigned int pci_last_busno; |
148 | struct pci_bus *pci_bus; | 149 | struct pci_bus *pci_bus; |
149 | void (*scan_bus)(struct pci_pbm_info *); | ||
150 | struct pci_ops *pci_ops; | 150 | struct pci_ops *pci_ops; |
151 | 151 | ||
152 | int numa_node; | 152 | int numa_node; |
153 | }; | 153 | }; |
154 | 154 | ||
155 | struct pci_controller_info { | ||
156 | /* The PCI bus modules controlled by us. */ | ||
157 | struct pci_pbm_info pbm_A; | ||
158 | struct pci_pbm_info pbm_B; | ||
159 | }; | ||
160 | |||
161 | extern struct pci_pbm_info *pci_pbm_root; | 155 | extern struct pci_pbm_info *pci_pbm_root; |
162 | 156 | ||
163 | extern int pci_num_pbms; | 157 | extern int pci_num_pbms; |
164 | 158 | ||
165 | /* PCI bus scanning and fixup support. */ | 159 | /* PCI bus scanning and fixup support. */ |
166 | extern void pci_get_pbm_props(struct pci_pbm_info *pbm); | 160 | extern void pci_get_pbm_props(struct pci_pbm_info *pbm); |
167 | extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm); | 161 | extern struct pci_bus *pci_scan_one_pbm(struct pci_pbm_info *pbm, |
162 | struct device *parent); | ||
168 | extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); | 163 | extern void pci_determine_mem_io_space(struct pci_pbm_info *pbm); |
169 | 164 | ||
170 | /* Error reporting support. */ | 165 | /* Error reporting support. */ |
@@ -183,4 +178,8 @@ extern void pci_config_write32(u32 *addr, u32 val); | |||
183 | extern struct pci_ops sun4u_pci_ops; | 178 | extern struct pci_ops sun4u_pci_ops; |
184 | extern struct pci_ops sun4v_pci_ops; | 179 | extern struct pci_ops sun4v_pci_ops; |
185 | 180 | ||
181 | extern volatile int pci_poke_in_progress; | ||
182 | extern volatile int pci_poke_cpu; | ||
183 | extern volatile int pci_poke_faulted; | ||
184 | |||
186 | #endif /* !(PCI_IMPL_H) */ | 185 | #endif /* !(PCI_IMPL_H) */ |
diff --git a/arch/sparc64/kernel/pci_msi.c b/arch/sparc64/kernel/pci_msi.c index 60c71e350212..2e680f34f727 100644 --- a/arch/sparc64/kernel/pci_msi.c +++ b/arch/sparc64/kernel/pci_msi.c | |||
@@ -323,7 +323,7 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, | |||
323 | const u32 *val; | 323 | const u32 *val; |
324 | int len; | 324 | int len; |
325 | 325 | ||
326 | val = of_get_property(pbm->prom_node, "#msi-eqs", &len); | 326 | val = of_get_property(pbm->op->node, "#msi-eqs", &len); |
327 | if (!val || len != 4) | 327 | if (!val || len != 4) |
328 | goto no_msi; | 328 | goto no_msi; |
329 | pbm->msiq_num = *val; | 329 | pbm->msiq_num = *val; |
@@ -346,16 +346,16 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, | |||
346 | u32 msi64_len; | 346 | u32 msi64_len; |
347 | } *arng; | 347 | } *arng; |
348 | 348 | ||
349 | val = of_get_property(pbm->prom_node, "msi-eq-size", &len); | 349 | val = of_get_property(pbm->op->node, "msi-eq-size", &len); |
350 | if (!val || len != 4) | 350 | if (!val || len != 4) |
351 | goto no_msi; | 351 | goto no_msi; |
352 | 352 | ||
353 | pbm->msiq_ent_count = *val; | 353 | pbm->msiq_ent_count = *val; |
354 | 354 | ||
355 | mqp = of_get_property(pbm->prom_node, | 355 | mqp = of_get_property(pbm->op->node, |
356 | "msi-eq-to-devino", &len); | 356 | "msi-eq-to-devino", &len); |
357 | if (!mqp) | 357 | if (!mqp) |
358 | mqp = of_get_property(pbm->prom_node, | 358 | mqp = of_get_property(pbm->op->node, |
359 | "msi-eq-devino", &len); | 359 | "msi-eq-devino", &len); |
360 | if (!mqp || len != sizeof(struct msiq_prop)) | 360 | if (!mqp || len != sizeof(struct msiq_prop)) |
361 | goto no_msi; | 361 | goto no_msi; |
@@ -363,27 +363,27 @@ void sparc64_pbm_msi_init(struct pci_pbm_info *pbm, | |||
363 | pbm->msiq_first = mqp->first_msiq; | 363 | pbm->msiq_first = mqp->first_msiq; |
364 | pbm->msiq_first_devino = mqp->first_devino; | 364 | pbm->msiq_first_devino = mqp->first_devino; |
365 | 365 | ||
366 | val = of_get_property(pbm->prom_node, "#msi", &len); | 366 | val = of_get_property(pbm->op->node, "#msi", &len); |
367 | if (!val || len != 4) | 367 | if (!val || len != 4) |
368 | goto no_msi; | 368 | goto no_msi; |
369 | pbm->msi_num = *val; | 369 | pbm->msi_num = *val; |
370 | 370 | ||
371 | mrng = of_get_property(pbm->prom_node, "msi-ranges", &len); | 371 | mrng = of_get_property(pbm->op->node, "msi-ranges", &len); |
372 | if (!mrng || len != sizeof(struct msi_range_prop)) | 372 | if (!mrng || len != sizeof(struct msi_range_prop)) |
373 | goto no_msi; | 373 | goto no_msi; |
374 | pbm->msi_first = mrng->first_msi; | 374 | pbm->msi_first = mrng->first_msi; |
375 | 375 | ||
376 | val = of_get_property(pbm->prom_node, "msi-data-mask", &len); | 376 | val = of_get_property(pbm->op->node, "msi-data-mask", &len); |
377 | if (!val || len != 4) | 377 | if (!val || len != 4) |
378 | goto no_msi; | 378 | goto no_msi; |
379 | pbm->msi_data_mask = *val; | 379 | pbm->msi_data_mask = *val; |
380 | 380 | ||
381 | val = of_get_property(pbm->prom_node, "msix-data-width", &len); | 381 | val = of_get_property(pbm->op->node, "msix-data-width", &len); |
382 | if (!val || len != 4) | 382 | if (!val || len != 4) |
383 | goto no_msi; | 383 | goto no_msi; |
384 | pbm->msix_data_width = *val; | 384 | pbm->msix_data_width = *val; |
385 | 385 | ||
386 | arng = of_get_property(pbm->prom_node, "msi-address-ranges", | 386 | arng = of_get_property(pbm->op->node, "msi-address-ranges", |
387 | &len); | 387 | &len); |
388 | if (!arng || len != sizeof(struct addr_range_prop)) | 388 | if (!arng || len != sizeof(struct addr_range_prop)) |
389 | goto no_msi; | 389 | goto no_msi; |
diff --git a/arch/sparc64/kernel/pci_psycho.c b/arch/sparc64/kernel/pci_psycho.c index f85b6bebb0be..dfb3ec892987 100644 --- a/arch/sparc64/kernel/pci_psycho.c +++ b/arch/sparc64/kernel/pci_psycho.c | |||
@@ -17,29 +17,14 @@ | |||
17 | #include <asm/irq.h> | 17 | #include <asm/irq.h> |
18 | #include <asm/starfire.h> | 18 | #include <asm/starfire.h> |
19 | #include <asm/prom.h> | 19 | #include <asm/prom.h> |
20 | #include <asm/oplib.h> | 20 | #include <asm/upa.h> |
21 | 21 | ||
22 | #include "pci_impl.h" | 22 | #include "pci_impl.h" |
23 | #include "iommu_common.h" | 23 | #include "iommu_common.h" |
24 | #include "psycho_common.h" | ||
24 | 25 | ||
25 | /* All PSYCHO registers are 64-bits. The following accessor | 26 | #define DRIVER_NAME "psycho" |
26 | * routines are how they are accessed. The REG parameter | 27 | #define PFX DRIVER_NAME ": " |
27 | * is a physical address. | ||
28 | */ | ||
29 | #define psycho_read(__reg) \ | ||
30 | ({ u64 __ret; \ | ||
31 | __asm__ __volatile__("ldxa [%1] %2, %0" \ | ||
32 | : "=r" (__ret) \ | ||
33 | : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
34 | : "memory"); \ | ||
35 | __ret; \ | ||
36 | }) | ||
37 | #define psycho_write(__reg, __val) \ | ||
38 | __asm__ __volatile__("stxa %0, [%1] %2" \ | ||
39 | : /* no outputs */ \ | ||
40 | : "r" (__val), "r" (__reg), \ | ||
41 | "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
42 | : "memory") | ||
43 | 28 | ||
44 | /* Misc. PSYCHO PCI controller register offsets and definitions. */ | 29 | /* Misc. PSYCHO PCI controller register offsets and definitions. */ |
45 | #define PSYCHO_CONTROL 0x0010UL | 30 | #define PSYCHO_CONTROL 0x0010UL |
@@ -67,37 +52,7 @@ | |||
67 | #define PSYCHO_PCICTRL_RESV4 0x00000000000000c0UL /* Reserved */ | 52 | #define PSYCHO_PCICTRL_RESV4 0x00000000000000c0UL /* Reserved */ |
68 | #define PSYCHO_PCICTRL_AEN 0x000000000000003fUL /* PCI DVMA Arbitration Enable */ | 53 | #define PSYCHO_PCICTRL_AEN 0x000000000000003fUL /* PCI DVMA Arbitration Enable */ |
69 | 54 | ||
70 | /* U2P Programmer's Manual, page 13-55, configuration space | ||
71 | * address format: | ||
72 | * | ||
73 | * 32 24 23 16 15 11 10 8 7 2 1 0 | ||
74 | * --------------------------------------------------------- | ||
75 | * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 | | ||
76 | * --------------------------------------------------------- | ||
77 | */ | ||
78 | #define PSYCHO_CONFIG_BASE(PBM) \ | ||
79 | ((PBM)->config_space | (1UL << 24)) | ||
80 | #define PSYCHO_CONFIG_ENCODE(BUS, DEVFN, REG) \ | ||
81 | (((unsigned long)(BUS) << 16) | \ | ||
82 | ((unsigned long)(DEVFN) << 8) | \ | ||
83 | ((unsigned long)(REG))) | ||
84 | |||
85 | static void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm, | ||
86 | unsigned char bus, | ||
87 | unsigned int devfn, | ||
88 | int where) | ||
89 | { | ||
90 | if (!pbm) | ||
91 | return NULL; | ||
92 | return (void *) | ||
93 | (PSYCHO_CONFIG_BASE(pbm) | | ||
94 | PSYCHO_CONFIG_ENCODE(bus, devfn, where)); | ||
95 | } | ||
96 | |||
97 | /* PSYCHO error handling support. */ | 55 | /* PSYCHO error handling support. */ |
98 | enum psycho_error_type { | ||
99 | UE_ERR, CE_ERR, PCI_ERR | ||
100 | }; | ||
101 | 56 | ||
102 | /* Helper function of IOMMU error checking, which checks out | 57 | /* Helper function of IOMMU error checking, which checks out |
103 | * the state of the streaming buffers. The IOMMU lock is | 58 | * the state of the streaming buffers. The IOMMU lock is |
@@ -122,129 +77,10 @@ enum psycho_error_type { | |||
122 | #define PSYCHO_STC_DATA_B 0xc000UL | 77 | #define PSYCHO_STC_DATA_B 0xc000UL |
123 | #define PSYCHO_STC_ERR_A 0xb400UL | 78 | #define PSYCHO_STC_ERR_A 0xb400UL |
124 | #define PSYCHO_STC_ERR_B 0xc400UL | 79 | #define PSYCHO_STC_ERR_B 0xc400UL |
125 | #define PSYCHO_STCERR_WRITE 0x0000000000000002UL /* Write Error */ | ||
126 | #define PSYCHO_STCERR_READ 0x0000000000000001UL /* Read Error */ | ||
127 | #define PSYCHO_STC_TAG_A 0xb800UL | 80 | #define PSYCHO_STC_TAG_A 0xb800UL |
128 | #define PSYCHO_STC_TAG_B 0xc800UL | 81 | #define PSYCHO_STC_TAG_B 0xc800UL |
129 | #define PSYCHO_STCTAG_PPN 0x0fffffff00000000UL /* Physical Page Number */ | ||
130 | #define PSYCHO_STCTAG_VPN 0x00000000ffffe000UL /* Virtual Page Number */ | ||
131 | #define PSYCHO_STCTAG_VALID 0x0000000000000002UL /* Valid */ | ||
132 | #define PSYCHO_STCTAG_WRITE 0x0000000000000001UL /* Writable */ | ||
133 | #define PSYCHO_STC_LINE_A 0xb900UL | 82 | #define PSYCHO_STC_LINE_A 0xb900UL |
134 | #define PSYCHO_STC_LINE_B 0xc900UL | 83 | #define PSYCHO_STC_LINE_B 0xc900UL |
135 | #define PSYCHO_STCLINE_LINDX 0x0000000001e00000UL /* LRU Index */ | ||
136 | #define PSYCHO_STCLINE_SPTR 0x00000000001f8000UL /* Dirty Data Start Pointer */ | ||
137 | #define PSYCHO_STCLINE_LADDR 0x0000000000007f00UL /* Line Address */ | ||
138 | #define PSYCHO_STCLINE_EPTR 0x00000000000000fcUL /* Dirty Data End Pointer */ | ||
139 | #define PSYCHO_STCLINE_VALID 0x0000000000000002UL /* Valid */ | ||
140 | #define PSYCHO_STCLINE_FOFN 0x0000000000000001UL /* Fetch Outstanding / Flush Necessary */ | ||
141 | |||
142 | static DEFINE_SPINLOCK(stc_buf_lock); | ||
143 | static unsigned long stc_error_buf[128]; | ||
144 | static unsigned long stc_tag_buf[16]; | ||
145 | static unsigned long stc_line_buf[16]; | ||
146 | |||
147 | static void __psycho_check_one_stc(struct pci_pbm_info *pbm, | ||
148 | int is_pbm_a) | ||
149 | { | ||
150 | struct strbuf *strbuf = &pbm->stc; | ||
151 | unsigned long regbase = pbm->controller_regs; | ||
152 | unsigned long err_base, tag_base, line_base; | ||
153 | u64 control; | ||
154 | int i; | ||
155 | |||
156 | if (is_pbm_a) { | ||
157 | err_base = regbase + PSYCHO_STC_ERR_A; | ||
158 | tag_base = regbase + PSYCHO_STC_TAG_A; | ||
159 | line_base = regbase + PSYCHO_STC_LINE_A; | ||
160 | } else { | ||
161 | err_base = regbase + PSYCHO_STC_ERR_B; | ||
162 | tag_base = regbase + PSYCHO_STC_TAG_B; | ||
163 | line_base = regbase + PSYCHO_STC_LINE_B; | ||
164 | } | ||
165 | |||
166 | spin_lock(&stc_buf_lock); | ||
167 | |||
168 | /* This is __REALLY__ dangerous. When we put the | ||
169 | * streaming buffer into diagnostic mode to probe | ||
170 | * it's tags and error status, we _must_ clear all | ||
171 | * of the line tag valid bits before re-enabling | ||
172 | * the streaming buffer. If any dirty data lives | ||
173 | * in the STC when we do this, we will end up | ||
174 | * invalidating it before it has a chance to reach | ||
175 | * main memory. | ||
176 | */ | ||
177 | control = psycho_read(strbuf->strbuf_control); | ||
178 | psycho_write(strbuf->strbuf_control, | ||
179 | (control | PSYCHO_STRBUF_CTRL_DENAB)); | ||
180 | for (i = 0; i < 128; i++) { | ||
181 | unsigned long val; | ||
182 | |||
183 | val = psycho_read(err_base + (i * 8UL)); | ||
184 | psycho_write(err_base + (i * 8UL), 0UL); | ||
185 | stc_error_buf[i] = val; | ||
186 | } | ||
187 | for (i = 0; i < 16; i++) { | ||
188 | stc_tag_buf[i] = psycho_read(tag_base + (i * 8UL)); | ||
189 | stc_line_buf[i] = psycho_read(line_base + (i * 8UL)); | ||
190 | psycho_write(tag_base + (i * 8UL), 0UL); | ||
191 | psycho_write(line_base + (i * 8UL), 0UL); | ||
192 | } | ||
193 | |||
194 | /* OK, state is logged, exit diagnostic mode. */ | ||
195 | psycho_write(strbuf->strbuf_control, control); | ||
196 | |||
197 | for (i = 0; i < 16; i++) { | ||
198 | int j, saw_error, first, last; | ||
199 | |||
200 | saw_error = 0; | ||
201 | first = i * 8; | ||
202 | last = first + 8; | ||
203 | for (j = first; j < last; j++) { | ||
204 | unsigned long errval = stc_error_buf[j]; | ||
205 | if (errval != 0) { | ||
206 | saw_error++; | ||
207 | printk("%s: STC_ERR(%d)[wr(%d)rd(%d)]\n", | ||
208 | pbm->name, | ||
209 | j, | ||
210 | (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, | ||
211 | (errval & PSYCHO_STCERR_READ) ? 1 : 0); | ||
212 | } | ||
213 | } | ||
214 | if (saw_error != 0) { | ||
215 | unsigned long tagval = stc_tag_buf[i]; | ||
216 | unsigned long lineval = stc_line_buf[i]; | ||
217 | printk("%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)V(%d)W(%d)]\n", | ||
218 | pbm->name, | ||
219 | i, | ||
220 | ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), | ||
221 | (tagval & PSYCHO_STCTAG_VPN), | ||
222 | ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), | ||
223 | ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); | ||
224 | printk("%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)LADDR(%lx)EP(%lx)" | ||
225 | "V(%d)FOFN(%d)]\n", | ||
226 | pbm->name, | ||
227 | i, | ||
228 | ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), | ||
229 | ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), | ||
230 | ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL), | ||
231 | ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL), | ||
232 | ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0), | ||
233 | ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0)); | ||
234 | } | ||
235 | } | ||
236 | |||
237 | spin_unlock(&stc_buf_lock); | ||
238 | } | ||
239 | |||
240 | static void __psycho_check_stc_error(struct pci_pbm_info *pbm, | ||
241 | unsigned long afsr, | ||
242 | unsigned long afar, | ||
243 | enum psycho_error_type type) | ||
244 | { | ||
245 | __psycho_check_one_stc(pbm, | ||
246 | (pbm == &pbm->parent->pbm_A)); | ||
247 | } | ||
248 | 84 | ||
249 | /* When an Uncorrectable Error or a PCI Error happens, we | 85 | /* When an Uncorrectable Error or a PCI Error happens, we |
250 | * interrogate the IOMMU state to see if it is the cause. | 86 | * interrogate the IOMMU state to see if it is the cause. |
@@ -271,122 +107,7 @@ static void __psycho_check_stc_error(struct pci_pbm_info *pbm, | |||
271 | #define PSYCHO_IOMMU_TSBBASE 0x0208UL | 107 | #define PSYCHO_IOMMU_TSBBASE 0x0208UL |
272 | #define PSYCHO_IOMMU_FLUSH 0x0210UL | 108 | #define PSYCHO_IOMMU_FLUSH 0x0210UL |
273 | #define PSYCHO_IOMMU_TAG 0xa580UL | 109 | #define PSYCHO_IOMMU_TAG 0xa580UL |
274 | #define PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL) | ||
275 | #define PSYCHO_IOMMU_TAG_ERR (0x1UL << 22UL) | ||
276 | #define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL) | ||
277 | #define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL) | ||
278 | #define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL) | ||
279 | #define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL | ||
280 | #define PSYCHO_IOMMU_DATA 0xa600UL | 110 | #define PSYCHO_IOMMU_DATA 0xa600UL |
281 | #define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) | ||
282 | #define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) | ||
283 | #define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL | ||
284 | static void psycho_check_iommu_error(struct pci_pbm_info *pbm, | ||
285 | unsigned long afsr, | ||
286 | unsigned long afar, | ||
287 | enum psycho_error_type type) | ||
288 | { | ||
289 | struct iommu *iommu = pbm->iommu; | ||
290 | unsigned long iommu_tag[16]; | ||
291 | unsigned long iommu_data[16]; | ||
292 | unsigned long flags; | ||
293 | u64 control; | ||
294 | int i; | ||
295 | |||
296 | spin_lock_irqsave(&iommu->lock, flags); | ||
297 | control = psycho_read(iommu->iommu_control); | ||
298 | if (control & PSYCHO_IOMMU_CTRL_XLTEERR) { | ||
299 | char *type_string; | ||
300 | |||
301 | /* Clear the error encountered bit. */ | ||
302 | control &= ~PSYCHO_IOMMU_CTRL_XLTEERR; | ||
303 | psycho_write(iommu->iommu_control, control); | ||
304 | |||
305 | switch((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) { | ||
306 | case 0: | ||
307 | type_string = "Protection Error"; | ||
308 | break; | ||
309 | case 1: | ||
310 | type_string = "Invalid Error"; | ||
311 | break; | ||
312 | case 2: | ||
313 | type_string = "TimeOut Error"; | ||
314 | break; | ||
315 | case 3: | ||
316 | default: | ||
317 | type_string = "ECC Error"; | ||
318 | break; | ||
319 | }; | ||
320 | printk("%s: IOMMU Error, type[%s]\n", | ||
321 | pbm->name, type_string); | ||
322 | |||
323 | /* Put the IOMMU into diagnostic mode and probe | ||
324 | * it's TLB for entries with error status. | ||
325 | * | ||
326 | * It is very possible for another DVMA to occur | ||
327 | * while we do this probe, and corrupt the system | ||
328 | * further. But we are so screwed at this point | ||
329 | * that we are likely to crash hard anyways, so | ||
330 | * get as much diagnostic information to the | ||
331 | * console as we can. | ||
332 | */ | ||
333 | psycho_write(iommu->iommu_control, | ||
334 | control | PSYCHO_IOMMU_CTRL_DENAB); | ||
335 | for (i = 0; i < 16; i++) { | ||
336 | unsigned long base = pbm->controller_regs; | ||
337 | |||
338 | iommu_tag[i] = | ||
339 | psycho_read(base + PSYCHO_IOMMU_TAG + (i * 8UL)); | ||
340 | iommu_data[i] = | ||
341 | psycho_read(base + PSYCHO_IOMMU_DATA + (i * 8UL)); | ||
342 | |||
343 | /* Now clear out the entry. */ | ||
344 | psycho_write(base + PSYCHO_IOMMU_TAG + (i * 8UL), 0); | ||
345 | psycho_write(base + PSYCHO_IOMMU_DATA + (i * 8UL), 0); | ||
346 | } | ||
347 | |||
348 | /* Leave diagnostic mode. */ | ||
349 | psycho_write(iommu->iommu_control, control); | ||
350 | |||
351 | for (i = 0; i < 16; i++) { | ||
352 | unsigned long tag, data; | ||
353 | |||
354 | tag = iommu_tag[i]; | ||
355 | if (!(tag & PSYCHO_IOMMU_TAG_ERR)) | ||
356 | continue; | ||
357 | |||
358 | data = iommu_data[i]; | ||
359 | switch((tag & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) { | ||
360 | case 0: | ||
361 | type_string = "Protection Error"; | ||
362 | break; | ||
363 | case 1: | ||
364 | type_string = "Invalid Error"; | ||
365 | break; | ||
366 | case 2: | ||
367 | type_string = "TimeOut Error"; | ||
368 | break; | ||
369 | case 3: | ||
370 | default: | ||
371 | type_string = "ECC Error"; | ||
372 | break; | ||
373 | }; | ||
374 | printk("%s: IOMMU TAG(%d)[error(%s) wr(%d) str(%d) sz(%dK) vpg(%08lx)]\n", | ||
375 | pbm->name, i, type_string, | ||
376 | ((tag & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), | ||
377 | ((tag & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), | ||
378 | ((tag & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), | ||
379 | (tag & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); | ||
380 | printk("%s: IOMMU DATA(%d)[valid(%d) cache(%d) ppg(%016lx)]\n", | ||
381 | pbm->name, i, | ||
382 | ((data & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), | ||
383 | ((data & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), | ||
384 | (data & PSYCHO_IOMMU_DATA_PPAGE) << IOMMU_PAGE_SHIFT); | ||
385 | } | ||
386 | } | ||
387 | __psycho_check_stc_error(pbm, afsr, afar, type); | ||
388 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
389 | } | ||
390 | 111 | ||
391 | /* Uncorrectable Errors. Cause of the error and the address are | 112 | /* Uncorrectable Errors. Cause of the error and the address are |
392 | * recorded in the UE_AFSR and UE_AFAR of PSYCHO. They are errors | 113 | * recorded in the UE_AFSR and UE_AFAR of PSYCHO. They are errors |
@@ -410,15 +131,14 @@ static void psycho_check_iommu_error(struct pci_pbm_info *pbm, | |||
410 | static irqreturn_t psycho_ue_intr(int irq, void *dev_id) | 131 | static irqreturn_t psycho_ue_intr(int irq, void *dev_id) |
411 | { | 132 | { |
412 | struct pci_pbm_info *pbm = dev_id; | 133 | struct pci_pbm_info *pbm = dev_id; |
413 | struct pci_controller_info *p = pbm->parent; | ||
414 | unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR; | 134 | unsigned long afsr_reg = pbm->controller_regs + PSYCHO_UE_AFSR; |
415 | unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR; | 135 | unsigned long afar_reg = pbm->controller_regs + PSYCHO_UE_AFAR; |
416 | unsigned long afsr, afar, error_bits; | 136 | unsigned long afsr, afar, error_bits; |
417 | int reported; | 137 | int reported; |
418 | 138 | ||
419 | /* Latch uncorrectable error status. */ | 139 | /* Latch uncorrectable error status. */ |
420 | afar = psycho_read(afar_reg); | 140 | afar = upa_readq(afar_reg); |
421 | afsr = psycho_read(afsr_reg); | 141 | afsr = upa_readq(afsr_reg); |
422 | 142 | ||
423 | /* Clear the primary/secondary error status bits. */ | 143 | /* Clear the primary/secondary error status bits. */ |
424 | error_bits = afsr & | 144 | error_bits = afsr & |
@@ -426,7 +146,7 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) | |||
426 | PSYCHO_UEAFSR_SPIO | PSYCHO_UEAFSR_SDRD | PSYCHO_UEAFSR_SDWR); | 146 | PSYCHO_UEAFSR_SPIO | PSYCHO_UEAFSR_SDRD | PSYCHO_UEAFSR_SDWR); |
427 | if (!error_bits) | 147 | if (!error_bits) |
428 | return IRQ_NONE; | 148 | return IRQ_NONE; |
429 | psycho_write(afsr_reg, error_bits); | 149 | upa_writeq(error_bits, afsr_reg); |
430 | 150 | ||
431 | /* Log the error. */ | 151 | /* Log the error. */ |
432 | printk("%s: Uncorrectable Error, primary error type[%s]\n", | 152 | printk("%s: Uncorrectable Error, primary error type[%s]\n", |
@@ -463,8 +183,9 @@ static irqreturn_t psycho_ue_intr(int irq, void *dev_id) | |||
463 | printk("]\n"); | 183 | printk("]\n"); |
464 | 184 | ||
465 | /* Interrogate both IOMMUs for error status. */ | 185 | /* Interrogate both IOMMUs for error status. */ |
466 | psycho_check_iommu_error(&p->pbm_A, afsr, afar, UE_ERR); | 186 | psycho_check_iommu_error(pbm, afsr, afar, UE_ERR); |
467 | psycho_check_iommu_error(&p->pbm_B, afsr, afar, UE_ERR); | 187 | if (pbm->sibling) |
188 | psycho_check_iommu_error(pbm->sibling, afsr, afar, UE_ERR); | ||
468 | 189 | ||
469 | return IRQ_HANDLED; | 190 | return IRQ_HANDLED; |
470 | } | 191 | } |
@@ -495,8 +216,8 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) | |||
495 | int reported; | 216 | int reported; |
496 | 217 | ||
497 | /* Latch error status. */ | 218 | /* Latch error status. */ |
498 | afar = psycho_read(afar_reg); | 219 | afar = upa_readq(afar_reg); |
499 | afsr = psycho_read(afsr_reg); | 220 | afsr = upa_readq(afsr_reg); |
500 | 221 | ||
501 | /* Clear primary/secondary error status bits. */ | 222 | /* Clear primary/secondary error status bits. */ |
502 | error_bits = afsr & | 223 | error_bits = afsr & |
@@ -504,7 +225,7 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) | |||
504 | PSYCHO_CEAFSR_SPIO | PSYCHO_CEAFSR_SDRD | PSYCHO_CEAFSR_SDWR); | 225 | PSYCHO_CEAFSR_SPIO | PSYCHO_CEAFSR_SDRD | PSYCHO_CEAFSR_SDWR); |
505 | if (!error_bits) | 226 | if (!error_bits) |
506 | return IRQ_NONE; | 227 | return IRQ_NONE; |
507 | psycho_write(afsr_reg, error_bits); | 228 | upa_writeq(error_bits, afsr_reg); |
508 | 229 | ||
509 | /* Log the error. */ | 230 | /* Log the error. */ |
510 | printk("%s: Correctable Error, primary error type[%s]\n", | 231 | printk("%s: Correctable Error, primary error type[%s]\n", |
@@ -554,164 +275,9 @@ static irqreturn_t psycho_ce_intr(int irq, void *dev_id) | |||
554 | */ | 275 | */ |
555 | #define PSYCHO_PCI_AFSR_A 0x2010UL | 276 | #define PSYCHO_PCI_AFSR_A 0x2010UL |
556 | #define PSYCHO_PCI_AFSR_B 0x4010UL | 277 | #define PSYCHO_PCI_AFSR_B 0x4010UL |
557 | #define PSYCHO_PCIAFSR_PMA 0x8000000000000000UL /* Primary Master Abort Error */ | ||
558 | #define PSYCHO_PCIAFSR_PTA 0x4000000000000000UL /* Primary Target Abort Error */ | ||
559 | #define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000UL /* Primary Excessive Retries */ | ||
560 | #define PSYCHO_PCIAFSR_PPERR 0x1000000000000000UL /* Primary Parity Error */ | ||
561 | #define PSYCHO_PCIAFSR_SMA 0x0800000000000000UL /* Secondary Master Abort Error */ | ||
562 | #define PSYCHO_PCIAFSR_STA 0x0400000000000000UL /* Secondary Target Abort Error */ | ||
563 | #define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000UL /* Secondary Excessive Retries */ | ||
564 | #define PSYCHO_PCIAFSR_SPERR 0x0100000000000000UL /* Secondary Parity Error */ | ||
565 | #define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000UL /* Reserved */ | ||
566 | #define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000UL /* Bytemask of failed transfer */ | ||
567 | #define PSYCHO_PCIAFSR_BLK 0x0000000080000000UL /* Trans was block operation */ | ||
568 | #define PSYCHO_PCIAFSR_RESV2 0x0000000040000000UL /* Reserved */ | ||
569 | #define PSYCHO_PCIAFSR_MID 0x000000003e000000UL /* MID causing the error */ | ||
570 | #define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffUL /* Reserved */ | ||
571 | #define PSYCHO_PCI_AFAR_A 0x2018UL | 278 | #define PSYCHO_PCI_AFAR_A 0x2018UL |
572 | #define PSYCHO_PCI_AFAR_B 0x4018UL | 279 | #define PSYCHO_PCI_AFAR_B 0x4018UL |
573 | 280 | ||
574 | static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm, int is_pbm_a) | ||
575 | { | ||
576 | unsigned long csr_reg, csr, csr_error_bits; | ||
577 | irqreturn_t ret = IRQ_NONE; | ||
578 | u16 stat, *addr; | ||
579 | |||
580 | if (is_pbm_a) { | ||
581 | csr_reg = pbm->controller_regs + PSYCHO_PCIA_CTRL; | ||
582 | } else { | ||
583 | csr_reg = pbm->controller_regs + PSYCHO_PCIB_CTRL; | ||
584 | } | ||
585 | csr = psycho_read(csr_reg); | ||
586 | csr_error_bits = | ||
587 | csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); | ||
588 | if (csr_error_bits) { | ||
589 | /* Clear the errors. */ | ||
590 | psycho_write(csr_reg, csr); | ||
591 | |||
592 | /* Log 'em. */ | ||
593 | if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) | ||
594 | printk("%s: PCI streaming byte hole error asserted.\n", | ||
595 | pbm->name); | ||
596 | if (csr_error_bits & PSYCHO_PCICTRL_SERR) | ||
597 | printk("%s: PCI SERR signal asserted.\n", pbm->name); | ||
598 | ret = IRQ_HANDLED; | ||
599 | } | ||
600 | addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, | ||
601 | 0, PCI_STATUS); | ||
602 | pci_config_read16(addr, &stat); | ||
603 | if (stat & (PCI_STATUS_PARITY | | ||
604 | PCI_STATUS_SIG_TARGET_ABORT | | ||
605 | PCI_STATUS_REC_TARGET_ABORT | | ||
606 | PCI_STATUS_REC_MASTER_ABORT | | ||
607 | PCI_STATUS_SIG_SYSTEM_ERROR)) { | ||
608 | printk("%s: PCI bus error, PCI_STATUS[%04x]\n", | ||
609 | pbm->name, stat); | ||
610 | pci_config_write16(addr, 0xffff); | ||
611 | ret = IRQ_HANDLED; | ||
612 | } | ||
613 | return ret; | ||
614 | } | ||
615 | |||
616 | static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) | ||
617 | { | ||
618 | struct pci_pbm_info *pbm = dev_id; | ||
619 | struct pci_controller_info *p = pbm->parent; | ||
620 | unsigned long afsr_reg, afar_reg; | ||
621 | unsigned long afsr, afar, error_bits; | ||
622 | int is_pbm_a, reported; | ||
623 | |||
624 | is_pbm_a = (pbm == &pbm->parent->pbm_A); | ||
625 | if (is_pbm_a) { | ||
626 | afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_A; | ||
627 | afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_A; | ||
628 | } else { | ||
629 | afsr_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFSR_B; | ||
630 | afar_reg = p->pbm_A.controller_regs + PSYCHO_PCI_AFAR_B; | ||
631 | } | ||
632 | |||
633 | /* Latch error status. */ | ||
634 | afar = psycho_read(afar_reg); | ||
635 | afsr = psycho_read(afsr_reg); | ||
636 | |||
637 | /* Clear primary/secondary error status bits. */ | ||
638 | error_bits = afsr & | ||
639 | (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA | | ||
640 | PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR | | ||
641 | PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | | ||
642 | PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); | ||
643 | if (!error_bits) | ||
644 | return psycho_pcierr_intr_other(pbm, is_pbm_a); | ||
645 | psycho_write(afsr_reg, error_bits); | ||
646 | |||
647 | /* Log the error. */ | ||
648 | printk("%s: PCI Error, primary error type[%s]\n", | ||
649 | pbm->name, | ||
650 | (((error_bits & PSYCHO_PCIAFSR_PMA) ? | ||
651 | "Master Abort" : | ||
652 | ((error_bits & PSYCHO_PCIAFSR_PTA) ? | ||
653 | "Target Abort" : | ||
654 | ((error_bits & PSYCHO_PCIAFSR_PRTRY) ? | ||
655 | "Excessive Retries" : | ||
656 | ((error_bits & PSYCHO_PCIAFSR_PPERR) ? | ||
657 | "Parity Error" : "???")))))); | ||
658 | printk("%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", | ||
659 | pbm->name, | ||
660 | (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, | ||
661 | (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, | ||
662 | (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); | ||
663 | printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); | ||
664 | printk("%s: PCI Secondary errors [", pbm->name); | ||
665 | reported = 0; | ||
666 | if (afsr & PSYCHO_PCIAFSR_SMA) { | ||
667 | reported++; | ||
668 | printk("(Master Abort)"); | ||
669 | } | ||
670 | if (afsr & PSYCHO_PCIAFSR_STA) { | ||
671 | reported++; | ||
672 | printk("(Target Abort)"); | ||
673 | } | ||
674 | if (afsr & PSYCHO_PCIAFSR_SRTRY) { | ||
675 | reported++; | ||
676 | printk("(Excessive Retries)"); | ||
677 | } | ||
678 | if (afsr & PSYCHO_PCIAFSR_SPERR) { | ||
679 | reported++; | ||
680 | printk("(Parity Error)"); | ||
681 | } | ||
682 | if (!reported) | ||
683 | printk("(none)"); | ||
684 | printk("]\n"); | ||
685 | |||
686 | /* For the error types shown, scan PBM's PCI bus for devices | ||
687 | * which have logged that error type. | ||
688 | */ | ||
689 | |||
690 | /* If we see a Target Abort, this could be the result of an | ||
691 | * IOMMU translation error of some sort. It is extremely | ||
692 | * useful to log this information as usually it indicates | ||
693 | * a bug in the IOMMU support code or a PCI device driver. | ||
694 | */ | ||
695 | if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { | ||
696 | psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); | ||
697 | pci_scan_for_target_abort(pbm, pbm->pci_bus); | ||
698 | } | ||
699 | if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) | ||
700 | pci_scan_for_master_abort(pbm, pbm->pci_bus); | ||
701 | |||
702 | /* For excessive retries, PSYCHO/PBM will abort the device | ||
703 | * and there is no way to specifically check for excessive | ||
704 | * retries in the config space status registers. So what | ||
705 | * we hope is that we'll catch it via the master/target | ||
706 | * abort events. | ||
707 | */ | ||
708 | |||
709 | if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) | ||
710 | pci_scan_for_parity_error(pbm, pbm->pci_bus); | ||
711 | |||
712 | return IRQ_HANDLED; | ||
713 | } | ||
714 | |||
715 | /* XXX What about PowerFail/PowerManagement??? -DaveM */ | 281 | /* XXX What about PowerFail/PowerManagement??? -DaveM */ |
716 | #define PSYCHO_ECC_CTRL 0x0020 | 282 | #define PSYCHO_ECC_CTRL 0x0020 |
717 | #define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ | 283 | #define PSYCHO_ECCCTRL_EE 0x8000000000000000UL /* Enable ECC Checking */ |
@@ -719,7 +285,7 @@ static irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) | |||
719 | #define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ | 285 | #define PSYCHO_ECCCTRL_CE 0x2000000000000000UL /* Enable CE INterrupts */ |
720 | static void psycho_register_error_handlers(struct pci_pbm_info *pbm) | 286 | static void psycho_register_error_handlers(struct pci_pbm_info *pbm) |
721 | { | 287 | { |
722 | struct of_device *op = of_find_device_by_node(pbm->prom_node); | 288 | struct of_device *op = of_find_device_by_node(pbm->op->node); |
723 | unsigned long base = pbm->controller_regs; | 289 | unsigned long base = pbm->controller_regs; |
724 | u64 tmp; | 290 | u64 tmp; |
725 | int err; | 291 | int err; |
@@ -762,27 +328,26 @@ static void psycho_register_error_handlers(struct pci_pbm_info *pbm) | |||
762 | "err=%d\n", pbm->name, err); | 328 | "err=%d\n", pbm->name, err); |
763 | 329 | ||
764 | /* Enable UE and CE interrupts for controller. */ | 330 | /* Enable UE and CE interrupts for controller. */ |
765 | psycho_write(base + PSYCHO_ECC_CTRL, | 331 | upa_writeq((PSYCHO_ECCCTRL_EE | |
766 | (PSYCHO_ECCCTRL_EE | | 332 | PSYCHO_ECCCTRL_UE | |
767 | PSYCHO_ECCCTRL_UE | | 333 | PSYCHO_ECCCTRL_CE), base + PSYCHO_ECC_CTRL); |
768 | PSYCHO_ECCCTRL_CE)); | ||
769 | 334 | ||
770 | /* Enable PCI Error interrupts and clear error | 335 | /* Enable PCI Error interrupts and clear error |
771 | * bits for each PBM. | 336 | * bits for each PBM. |
772 | */ | 337 | */ |
773 | tmp = psycho_read(base + PSYCHO_PCIA_CTRL); | 338 | tmp = upa_readq(base + PSYCHO_PCIA_CTRL); |
774 | tmp |= (PSYCHO_PCICTRL_SERR | | 339 | tmp |= (PSYCHO_PCICTRL_SERR | |
775 | PSYCHO_PCICTRL_SBH_ERR | | 340 | PSYCHO_PCICTRL_SBH_ERR | |
776 | PSYCHO_PCICTRL_EEN); | 341 | PSYCHO_PCICTRL_EEN); |
777 | tmp &= ~(PSYCHO_PCICTRL_SBH_INT); | 342 | tmp &= ~(PSYCHO_PCICTRL_SBH_INT); |
778 | psycho_write(base + PSYCHO_PCIA_CTRL, tmp); | 343 | upa_writeq(tmp, base + PSYCHO_PCIA_CTRL); |
779 | 344 | ||
780 | tmp = psycho_read(base + PSYCHO_PCIB_CTRL); | 345 | tmp = upa_readq(base + PSYCHO_PCIB_CTRL); |
781 | tmp |= (PSYCHO_PCICTRL_SERR | | 346 | tmp |= (PSYCHO_PCICTRL_SERR | |
782 | PSYCHO_PCICTRL_SBH_ERR | | 347 | PSYCHO_PCICTRL_SBH_ERR | |
783 | PSYCHO_PCICTRL_EEN); | 348 | PSYCHO_PCICTRL_EEN); |
784 | tmp &= ~(PSYCHO_PCICTRL_SBH_INT); | 349 | tmp &= ~(PSYCHO_PCICTRL_SBH_INT); |
785 | psycho_write(base + PSYCHO_PCIB_CTRL, tmp); | 350 | upa_writeq(tmp, base + PSYCHO_PCIB_CTRL); |
786 | } | 351 | } |
787 | 352 | ||
788 | /* PSYCHO boot time probing and initialization. */ | 353 | /* PSYCHO boot time probing and initialization. */ |
@@ -803,11 +368,12 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) | |||
803 | pci_config_write8(addr, 64); | 368 | pci_config_write8(addr, 64); |
804 | } | 369 | } |
805 | 370 | ||
806 | static void __init psycho_scan_bus(struct pci_pbm_info *pbm) | 371 | static void __init psycho_scan_bus(struct pci_pbm_info *pbm, |
372 | struct device *parent) | ||
807 | { | 373 | { |
808 | pbm_config_busmastering(pbm); | 374 | pbm_config_busmastering(pbm); |
809 | pbm->is_66mhz_capable = 0; | 375 | pbm->is_66mhz_capable = 0; |
810 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 376 | pbm->pci_bus = pci_scan_one_pbm(pbm, parent); |
811 | 377 | ||
812 | /* After the PCI bus scan is complete, we can register | 378 | /* After the PCI bus scan is complete, we can register |
813 | * the error interrupt handlers. | 379 | * the error interrupt handlers. |
@@ -815,61 +381,6 @@ static void __init psycho_scan_bus(struct pci_pbm_info *pbm) | |||
815 | psycho_register_error_handlers(pbm); | 381 | psycho_register_error_handlers(pbm); |
816 | } | 382 | } |
817 | 383 | ||
818 | static int psycho_iommu_init(struct pci_pbm_info *pbm) | ||
819 | { | ||
820 | struct iommu *iommu = pbm->iommu; | ||
821 | unsigned long i; | ||
822 | u64 control; | ||
823 | int err; | ||
824 | |||
825 | /* Register addresses. */ | ||
826 | iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL; | ||
827 | iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE; | ||
828 | iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH; | ||
829 | iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL); | ||
830 | |||
831 | /* PSYCHO's IOMMU lacks ctx flushing. */ | ||
832 | iommu->iommu_ctxflush = 0; | ||
833 | |||
834 | /* We use the main control register of PSYCHO as the write | ||
835 | * completion register. | ||
836 | */ | ||
837 | iommu->write_complete_reg = pbm->controller_regs + PSYCHO_CONTROL; | ||
838 | |||
839 | /* | ||
840 | * Invalidate TLB Entries. | ||
841 | */ | ||
842 | control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); | ||
843 | control |= PSYCHO_IOMMU_CTRL_DENAB; | ||
844 | psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); | ||
845 | for(i = 0; i < 16; i++) { | ||
846 | psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TAG + (i * 8UL), 0); | ||
847 | psycho_write(pbm->controller_regs + PSYCHO_IOMMU_DATA + (i * 8UL), 0); | ||
848 | } | ||
849 | |||
850 | /* Leave diag mode enabled for full-flushing done | ||
851 | * in pci_iommu.c | ||
852 | */ | ||
853 | err = iommu_table_init(iommu, IO_TSB_SIZE, 0xc0000000, 0xffffffff, | ||
854 | pbm->numa_node); | ||
855 | if (err) | ||
856 | return err; | ||
857 | |||
858 | psycho_write(pbm->controller_regs + PSYCHO_IOMMU_TSBBASE, | ||
859 | __pa(iommu->page_table)); | ||
860 | |||
861 | control = psycho_read(pbm->controller_regs + PSYCHO_IOMMU_CONTROL); | ||
862 | control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); | ||
863 | control |= (PSYCHO_IOMMU_TSBSZ_128K | PSYCHO_IOMMU_CTRL_ENAB); | ||
864 | psycho_write(pbm->controller_regs + PSYCHO_IOMMU_CONTROL, control); | ||
865 | |||
866 | /* If necessary, hook us up for starfire IRQ translations. */ | ||
867 | if (this_is_starfire) | ||
868 | starfire_hookup(pbm->portid); | ||
869 | |||
870 | return 0; | ||
871 | } | ||
872 | |||
873 | #define PSYCHO_IRQ_RETRY 0x1a00UL | 384 | #define PSYCHO_IRQ_RETRY 0x1a00UL |
874 | #define PSYCHO_PCIA_DIAG 0x2020UL | 385 | #define PSYCHO_PCIA_DIAG 0x2020UL |
875 | #define PSYCHO_PCIB_DIAG 0x4020UL | 386 | #define PSYCHO_PCIB_DIAG 0x4020UL |
@@ -886,28 +397,28 @@ static void psycho_controller_hwinit(struct pci_pbm_info *pbm) | |||
886 | { | 397 | { |
887 | u64 tmp; | 398 | u64 tmp; |
888 | 399 | ||
889 | psycho_write(pbm->controller_regs + PSYCHO_IRQ_RETRY, 5); | 400 | upa_writeq(5, pbm->controller_regs + PSYCHO_IRQ_RETRY); |
890 | 401 | ||
891 | /* Enable arbiter for all PCI slots. */ | 402 | /* Enable arbiter for all PCI slots. */ |
892 | tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_CTRL); | 403 | tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIA_CTRL); |
893 | tmp |= PSYCHO_PCICTRL_AEN; | 404 | tmp |= PSYCHO_PCICTRL_AEN; |
894 | psycho_write(pbm->controller_regs + PSYCHO_PCIA_CTRL, tmp); | 405 | upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIA_CTRL); |
895 | 406 | ||
896 | tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_CTRL); | 407 | tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIB_CTRL); |
897 | tmp |= PSYCHO_PCICTRL_AEN; | 408 | tmp |= PSYCHO_PCICTRL_AEN; |
898 | psycho_write(pbm->controller_regs + PSYCHO_PCIB_CTRL, tmp); | 409 | upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIB_CTRL); |
899 | 410 | ||
900 | /* Disable DMA write / PIO read synchronization on | 411 | /* Disable DMA write / PIO read synchronization on |
901 | * both PCI bus segments. | 412 | * both PCI bus segments. |
902 | * [ U2P Erratum 1243770, STP2223BGA data sheet ] | 413 | * [ U2P Erratum 1243770, STP2223BGA data sheet ] |
903 | */ | 414 | */ |
904 | tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIA_DIAG); | 415 | tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIA_DIAG); |
905 | tmp |= PSYCHO_PCIDIAG_DDWSYNC; | 416 | tmp |= PSYCHO_PCIDIAG_DDWSYNC; |
906 | psycho_write(pbm->controller_regs + PSYCHO_PCIA_DIAG, tmp); | 417 | upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIA_DIAG); |
907 | 418 | ||
908 | tmp = psycho_read(pbm->controller_regs + PSYCHO_PCIB_DIAG); | 419 | tmp = upa_readq(pbm->controller_regs + PSYCHO_PCIB_DIAG); |
909 | tmp |= PSYCHO_PCIDIAG_DDWSYNC; | 420 | tmp |= PSYCHO_PCIDIAG_DDWSYNC; |
910 | psycho_write(pbm->controller_regs + PSYCHO_PCIB_DIAG, tmp); | 421 | upa_writeq(tmp, pbm->controller_regs + PSYCHO_PCIB_DIAG); |
911 | } | 422 | } |
912 | 423 | ||
913 | static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, | 424 | static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, |
@@ -920,10 +431,16 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, | |||
920 | pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A; | 431 | pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_A; |
921 | pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A; | 432 | pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_A; |
922 | pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_A; | 433 | pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_A; |
434 | pbm->stc.strbuf_err_stat = base + PSYCHO_STC_ERR_A; | ||
435 | pbm->stc.strbuf_tag_diag = base + PSYCHO_STC_TAG_A; | ||
436 | pbm->stc.strbuf_line_diag= base + PSYCHO_STC_LINE_A; | ||
923 | } else { | 437 | } else { |
924 | pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_B; | 438 | pbm->stc.strbuf_control = base + PSYCHO_STRBUF_CONTROL_B; |
925 | pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B; | 439 | pbm->stc.strbuf_pflush = base + PSYCHO_STRBUF_FLUSH_B; |
926 | pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B; | 440 | pbm->stc.strbuf_fsync = base + PSYCHO_STRBUF_FSYNC_B; |
441 | pbm->stc.strbuf_err_stat = base + PSYCHO_STC_ERR_B; | ||
442 | pbm->stc.strbuf_tag_diag = base + PSYCHO_STC_TAG_B; | ||
443 | pbm->stc.strbuf_line_diag= base + PSYCHO_STC_LINE_B; | ||
927 | } | 444 | } |
928 | /* PSYCHO's streaming buffer lacks ctx flushing. */ | 445 | /* PSYCHO's streaming buffer lacks ctx flushing. */ |
929 | pbm->stc.strbuf_ctxflush = 0; | 446 | pbm->stc.strbuf_ctxflush = 0; |
@@ -946,7 +463,7 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, | |||
946 | */ | 463 | */ |
947 | #undef PSYCHO_STRBUF_RERUN_ENABLE | 464 | #undef PSYCHO_STRBUF_RERUN_ENABLE |
948 | #undef PSYCHO_STRBUF_RERUN_DISABLE | 465 | #undef PSYCHO_STRBUF_RERUN_DISABLE |
949 | control = psycho_read(pbm->stc.strbuf_control); | 466 | control = upa_readq(pbm->stc.strbuf_control); |
950 | control |= PSYCHO_STRBUF_CTRL_ENAB; | 467 | control |= PSYCHO_STRBUF_CTRL_ENAB; |
951 | control &= ~(PSYCHO_STRBUF_CTRL_LENAB | PSYCHO_STRBUF_CTRL_LPTR); | 468 | control &= ~(PSYCHO_STRBUF_CTRL_LENAB | PSYCHO_STRBUF_CTRL_LPTR); |
952 | #ifdef PSYCHO_STRBUF_RERUN_ENABLE | 469 | #ifdef PSYCHO_STRBUF_RERUN_ENABLE |
@@ -956,7 +473,7 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, | |||
956 | control |= PSYCHO_STRBUF_CTRL_RRDIS; | 473 | control |= PSYCHO_STRBUF_CTRL_RRDIS; |
957 | #endif | 474 | #endif |
958 | #endif | 475 | #endif |
959 | psycho_write(pbm->stc.strbuf_control, control); | 476 | upa_writeq(control, pbm->stc.strbuf_control); |
960 | 477 | ||
961 | pbm->stc.strbuf_enabled = 1; | 478 | pbm->stc.strbuf_enabled = 1; |
962 | } | 479 | } |
@@ -968,111 +485,134 @@ static void psycho_pbm_strbuf_init(struct pci_pbm_info *pbm, | |||
968 | #define PSYCHO_MEMSPACE_B 0x180000000UL | 485 | #define PSYCHO_MEMSPACE_B 0x180000000UL |
969 | #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL | 486 | #define PSYCHO_MEMSPACE_SIZE 0x07fffffffUL |
970 | 487 | ||
971 | static void __init psycho_pbm_init(struct pci_controller_info *p, | 488 | static void __init psycho_pbm_init(struct pci_pbm_info *pbm, |
972 | struct device_node *dp, int is_pbm_a) | 489 | struct of_device *op, int is_pbm_a) |
973 | { | 490 | { |
974 | struct property *prop; | 491 | psycho_pbm_init_common(pbm, op, "PSYCHO", PBM_CHIP_TYPE_PSYCHO); |
975 | struct pci_pbm_info *pbm; | 492 | psycho_pbm_strbuf_init(pbm, is_pbm_a); |
976 | 493 | psycho_scan_bus(pbm, &op->dev); | |
977 | if (is_pbm_a) | 494 | } |
978 | pbm = &p->pbm_A; | ||
979 | else | ||
980 | pbm = &p->pbm_B; | ||
981 | |||
982 | pbm->next = pci_pbm_root; | ||
983 | pci_pbm_root = pbm; | ||
984 | |||
985 | pbm->numa_node = -1; | ||
986 | |||
987 | pbm->scan_bus = psycho_scan_bus; | ||
988 | pbm->pci_ops = &sun4u_pci_ops; | ||
989 | pbm->config_space_reg_bits = 8; | ||
990 | |||
991 | pbm->index = pci_num_pbms++; | ||
992 | |||
993 | pbm->chip_type = PBM_CHIP_TYPE_PSYCHO; | ||
994 | pbm->chip_version = 0; | ||
995 | prop = of_find_property(dp, "version#", NULL); | ||
996 | if (prop) | ||
997 | pbm->chip_version = *(int *) prop->value; | ||
998 | pbm->chip_revision = 0; | ||
999 | prop = of_find_property(dp, "module-revision#", NULL); | ||
1000 | if (prop) | ||
1001 | pbm->chip_revision = *(int *) prop->value; | ||
1002 | |||
1003 | pbm->parent = p; | ||
1004 | pbm->prom_node = dp; | ||
1005 | pbm->name = dp->full_name; | ||
1006 | |||
1007 | printk("%s: PSYCHO PCI Bus Module ver[%x:%x]\n", | ||
1008 | pbm->name, | ||
1009 | pbm->chip_version, pbm->chip_revision); | ||
1010 | |||
1011 | pci_determine_mem_io_space(pbm); | ||
1012 | 495 | ||
1013 | pci_get_pbm_props(pbm); | 496 | static struct pci_pbm_info * __devinit psycho_find_sibling(u32 upa_portid) |
497 | { | ||
498 | struct pci_pbm_info *pbm; | ||
1014 | 499 | ||
1015 | psycho_pbm_strbuf_init(pbm, is_pbm_a); | 500 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { |
501 | if (pbm->portid == upa_portid) | ||
502 | return pbm; | ||
503 | } | ||
504 | return NULL; | ||
1016 | } | 505 | } |
1017 | 506 | ||
1018 | #define PSYCHO_CONFIGSPACE 0x001000000UL | 507 | #define PSYCHO_CONFIGSPACE 0x001000000UL |
1019 | 508 | ||
1020 | void __init psycho_init(struct device_node *dp, char *model_name) | 509 | static int __devinit psycho_probe(struct of_device *op, |
510 | const struct of_device_id *match) | ||
1021 | { | 511 | { |
1022 | struct linux_prom64_registers *pr_regs; | 512 | const struct linux_prom64_registers *pr_regs; |
1023 | struct pci_controller_info *p; | 513 | struct device_node *dp = op->node; |
1024 | struct pci_pbm_info *pbm; | 514 | struct pci_pbm_info *pbm; |
1025 | struct iommu *iommu; | 515 | struct iommu *iommu; |
1026 | struct property *prop; | 516 | int is_pbm_a, err; |
1027 | u32 upa_portid; | 517 | u32 upa_portid; |
1028 | int is_pbm_a; | ||
1029 | 518 | ||
1030 | upa_portid = 0xff; | 519 | upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); |
1031 | prop = of_find_property(dp, "upa-portid", NULL); | ||
1032 | if (prop) | ||
1033 | upa_portid = *(u32 *) prop->value; | ||
1034 | 520 | ||
1035 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 521 | err = -ENOMEM; |
1036 | struct pci_controller_info *p = pbm->parent; | 522 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
523 | if (!pbm) { | ||
524 | printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); | ||
525 | goto out_err; | ||
526 | } | ||
1037 | 527 | ||
1038 | if (p->pbm_A.portid == upa_portid) { | 528 | pbm->sibling = psycho_find_sibling(upa_portid); |
1039 | is_pbm_a = (p->pbm_A.prom_node == NULL); | 529 | if (pbm->sibling) { |
1040 | psycho_pbm_init(p, dp, is_pbm_a); | 530 | iommu = pbm->sibling->iommu; |
1041 | return; | 531 | } else { |
532 | iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); | ||
533 | if (!iommu) { | ||
534 | printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); | ||
535 | goto out_free_controller; | ||
1042 | } | 536 | } |
1043 | } | 537 | } |
1044 | 538 | ||
1045 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); | 539 | pbm->iommu = iommu; |
1046 | if (!p) | 540 | pbm->portid = upa_portid; |
1047 | goto fatal_memory_error; | ||
1048 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | ||
1049 | if (!iommu) | ||
1050 | goto fatal_memory_error; | ||
1051 | 541 | ||
1052 | p->pbm_A.iommu = p->pbm_B.iommu = iommu; | 542 | pr_regs = of_get_property(dp, "reg", NULL); |
543 | err = -ENODEV; | ||
544 | if (!pr_regs) { | ||
545 | printk(KERN_ERR PFX "No reg property.\n"); | ||
546 | goto out_free_iommu; | ||
547 | } | ||
1053 | 548 | ||
1054 | p->pbm_A.portid = upa_portid; | 549 | is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); |
1055 | p->pbm_B.portid = upa_portid; | ||
1056 | 550 | ||
1057 | prop = of_find_property(dp, "reg", NULL); | 551 | pbm->controller_regs = pr_regs[2].phys_addr; |
1058 | pr_regs = prop->value; | 552 | pbm->config_space = (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); |
1059 | 553 | ||
1060 | p->pbm_A.controller_regs = pr_regs[2].phys_addr; | 554 | if (is_pbm_a) { |
1061 | p->pbm_B.controller_regs = pr_regs[2].phys_addr; | 555 | pbm->pci_afsr = pbm->controller_regs + PSYCHO_PCI_AFSR_A; |
556 | pbm->pci_afar = pbm->controller_regs + PSYCHO_PCI_AFAR_A; | ||
557 | pbm->pci_csr = pbm->controller_regs + PSYCHO_PCIA_CTRL; | ||
558 | } else { | ||
559 | pbm->pci_afsr = pbm->controller_regs + PSYCHO_PCI_AFSR_B; | ||
560 | pbm->pci_afar = pbm->controller_regs + PSYCHO_PCI_AFAR_B; | ||
561 | pbm->pci_csr = pbm->controller_regs + PSYCHO_PCIB_CTRL; | ||
562 | } | ||
1062 | 563 | ||
1063 | p->pbm_A.config_space = p->pbm_B.config_space = | 564 | psycho_controller_hwinit(pbm); |
1064 | (pr_regs[2].phys_addr + PSYCHO_CONFIGSPACE); | 565 | if (!pbm->sibling) { |
566 | err = psycho_iommu_init(pbm, 128, 0xc0000000, | ||
567 | 0xffffffff, PSYCHO_CONTROL); | ||
568 | if (err) | ||
569 | goto out_free_iommu; | ||
1065 | 570 | ||
1066 | psycho_controller_hwinit(&p->pbm_A); | 571 | /* If necessary, hook us up for starfire IRQ translations. */ |
572 | if (this_is_starfire) | ||
573 | starfire_hookup(pbm->portid); | ||
574 | } | ||
1067 | 575 | ||
1068 | if (psycho_iommu_init(&p->pbm_A)) | 576 | psycho_pbm_init(pbm, op, is_pbm_a); |
1069 | goto fatal_memory_error; | ||
1070 | 577 | ||
1071 | is_pbm_a = ((pr_regs[0].phys_addr & 0x6000) == 0x2000); | 578 | pbm->next = pci_pbm_root; |
1072 | psycho_pbm_init(p, dp, is_pbm_a); | 579 | pci_pbm_root = pbm; |
1073 | return; | 580 | |
581 | if (pbm->sibling) | ||
582 | pbm->sibling->sibling = pbm; | ||
583 | |||
584 | dev_set_drvdata(&op->dev, pbm); | ||
585 | |||
586 | return 0; | ||
587 | |||
588 | out_free_iommu: | ||
589 | if (!pbm->sibling) | ||
590 | kfree(pbm->iommu); | ||
1074 | 591 | ||
1075 | fatal_memory_error: | 592 | out_free_controller: |
1076 | prom_printf("PSYCHO: Fatal memory allocation error.\n"); | 593 | kfree(pbm); |
1077 | prom_halt(); | 594 | |
595 | out_err: | ||
596 | return err; | ||
1078 | } | 597 | } |
598 | |||
599 | static struct of_device_id __initdata psycho_match[] = { | ||
600 | { | ||
601 | .name = "pci", | ||
602 | .compatible = "pci108e,8000", | ||
603 | }, | ||
604 | {}, | ||
605 | }; | ||
606 | |||
607 | static struct of_platform_driver psycho_driver = { | ||
608 | .name = DRIVER_NAME, | ||
609 | .match_table = psycho_match, | ||
610 | .probe = psycho_probe, | ||
611 | }; | ||
612 | |||
613 | static int __init psycho_init(void) | ||
614 | { | ||
615 | return of_register_driver(&psycho_driver, &of_bus_type); | ||
616 | } | ||
617 | |||
618 | subsys_initcall(psycho_init); | ||
diff --git a/arch/sparc64/kernel/pci_sabre.c b/arch/sparc64/kernel/pci_sabre.c index ade5184e75d1..713257b6963c 100644 --- a/arch/sparc64/kernel/pci_sabre.c +++ b/arch/sparc64/kernel/pci_sabre.c | |||
@@ -16,31 +16,15 @@ | |||
16 | #include <asm/apb.h> | 16 | #include <asm/apb.h> |
17 | #include <asm/iommu.h> | 17 | #include <asm/iommu.h> |
18 | #include <asm/irq.h> | 18 | #include <asm/irq.h> |
19 | #include <asm/smp.h> | ||
20 | #include <asm/oplib.h> | ||
21 | #include <asm/prom.h> | 19 | #include <asm/prom.h> |
20 | #include <asm/upa.h> | ||
22 | 21 | ||
23 | #include "pci_impl.h" | 22 | #include "pci_impl.h" |
24 | #include "iommu_common.h" | 23 | #include "iommu_common.h" |
24 | #include "psycho_common.h" | ||
25 | 25 | ||
26 | /* All SABRE registers are 64-bits. The following accessor | 26 | #define DRIVER_NAME "sabre" |
27 | * routines are how they are accessed. The REG parameter | 27 | #define PFX DRIVER_NAME ": " |
28 | * is a physical address. | ||
29 | */ | ||
30 | #define sabre_read(__reg) \ | ||
31 | ({ u64 __ret; \ | ||
32 | __asm__ __volatile__("ldxa [%1] %2, %0" \ | ||
33 | : "=r" (__ret) \ | ||
34 | : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
35 | : "memory"); \ | ||
36 | __ret; \ | ||
37 | }) | ||
38 | #define sabre_write(__reg, __val) \ | ||
39 | __asm__ __volatile__("stxa %0, [%1] %2" \ | ||
40 | : /* no outputs */ \ | ||
41 | : "r" (__val), "r" (__reg), \ | ||
42 | "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
43 | : "memory") | ||
44 | 28 | ||
45 | /* SABRE PCI controller register offsets and definitions. */ | 29 | /* SABRE PCI controller register offsets and definitions. */ |
46 | #define SABRE_UE_AFSR 0x0030UL | 30 | #define SABRE_UE_AFSR 0x0030UL |
@@ -208,95 +192,6 @@ | |||
208 | static int hummingbird_p; | 192 | static int hummingbird_p; |
209 | static struct pci_bus *sabre_root_bus; | 193 | static struct pci_bus *sabre_root_bus; |
210 | 194 | ||
211 | /* SABRE error handling support. */ | ||
212 | static void sabre_check_iommu_error(struct pci_pbm_info *pbm, | ||
213 | unsigned long afsr, | ||
214 | unsigned long afar) | ||
215 | { | ||
216 | struct iommu *iommu = pbm->iommu; | ||
217 | unsigned long iommu_tag[16]; | ||
218 | unsigned long iommu_data[16]; | ||
219 | unsigned long flags; | ||
220 | u64 control; | ||
221 | int i; | ||
222 | |||
223 | spin_lock_irqsave(&iommu->lock, flags); | ||
224 | control = sabre_read(iommu->iommu_control); | ||
225 | if (control & SABRE_IOMMUCTRL_ERR) { | ||
226 | char *type_string; | ||
227 | |||
228 | /* Clear the error encountered bit. | ||
229 | * NOTE: On Sabre this is write 1 to clear, | ||
230 | * which is different from Psycho. | ||
231 | */ | ||
232 | sabre_write(iommu->iommu_control, control); | ||
233 | switch((control & SABRE_IOMMUCTRL_ERRSTS) >> 25UL) { | ||
234 | case 1: | ||
235 | type_string = "Invalid Error"; | ||
236 | break; | ||
237 | case 3: | ||
238 | type_string = "ECC Error"; | ||
239 | break; | ||
240 | default: | ||
241 | type_string = "Unknown"; | ||
242 | break; | ||
243 | }; | ||
244 | printk("%s: IOMMU Error, type[%s]\n", | ||
245 | pbm->name, type_string); | ||
246 | |||
247 | /* Enter diagnostic mode and probe for error'd | ||
248 | * entries in the IOTLB. | ||
249 | */ | ||
250 | control &= ~(SABRE_IOMMUCTRL_ERRSTS | SABRE_IOMMUCTRL_ERR); | ||
251 | sabre_write(iommu->iommu_control, | ||
252 | (control | SABRE_IOMMUCTRL_DENAB)); | ||
253 | for (i = 0; i < 16; i++) { | ||
254 | unsigned long base = pbm->controller_regs; | ||
255 | |||
256 | iommu_tag[i] = | ||
257 | sabre_read(base + SABRE_IOMMU_TAG + (i * 8UL)); | ||
258 | iommu_data[i] = | ||
259 | sabre_read(base + SABRE_IOMMU_DATA + (i * 8UL)); | ||
260 | sabre_write(base + SABRE_IOMMU_TAG + (i * 8UL), 0); | ||
261 | sabre_write(base + SABRE_IOMMU_DATA + (i * 8UL), 0); | ||
262 | } | ||
263 | sabre_write(iommu->iommu_control, control); | ||
264 | |||
265 | for (i = 0; i < 16; i++) { | ||
266 | unsigned long tag, data; | ||
267 | |||
268 | tag = iommu_tag[i]; | ||
269 | if (!(tag & SABRE_IOMMUTAG_ERR)) | ||
270 | continue; | ||
271 | |||
272 | data = iommu_data[i]; | ||
273 | switch((tag & SABRE_IOMMUTAG_ERRSTS) >> 23UL) { | ||
274 | case 1: | ||
275 | type_string = "Invalid Error"; | ||
276 | break; | ||
277 | case 3: | ||
278 | type_string = "ECC Error"; | ||
279 | break; | ||
280 | default: | ||
281 | type_string = "Unknown"; | ||
282 | break; | ||
283 | }; | ||
284 | printk("%s: IOMMU TAG(%d)[RAW(%016lx)error(%s)wr(%d)sz(%dK)vpg(%08lx)]\n", | ||
285 | pbm->name, i, tag, type_string, | ||
286 | ((tag & SABRE_IOMMUTAG_WRITE) ? 1 : 0), | ||
287 | ((tag & SABRE_IOMMUTAG_SIZE) ? 64 : 8), | ||
288 | ((tag & SABRE_IOMMUTAG_VPN) << IOMMU_PAGE_SHIFT)); | ||
289 | printk("%s: IOMMU DATA(%d)[RAW(%016lx)valid(%d)used(%d)cache(%d)ppg(%016lx)\n", | ||
290 | pbm->name, i, data, | ||
291 | ((data & SABRE_IOMMUDATA_VALID) ? 1 : 0), | ||
292 | ((data & SABRE_IOMMUDATA_USED) ? 1 : 0), | ||
293 | ((data & SABRE_IOMMUDATA_CACHE) ? 1 : 0), | ||
294 | ((data & SABRE_IOMMUDATA_PPN) << IOMMU_PAGE_SHIFT)); | ||
295 | } | ||
296 | } | ||
297 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
298 | } | ||
299 | |||
300 | static irqreturn_t sabre_ue_intr(int irq, void *dev_id) | 195 | static irqreturn_t sabre_ue_intr(int irq, void *dev_id) |
301 | { | 196 | { |
302 | struct pci_pbm_info *pbm = dev_id; | 197 | struct pci_pbm_info *pbm = dev_id; |
@@ -306,8 +201,8 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) | |||
306 | int reported; | 201 | int reported; |
307 | 202 | ||
308 | /* Latch uncorrectable error status. */ | 203 | /* Latch uncorrectable error status. */ |
309 | afar = sabre_read(afar_reg); | 204 | afar = upa_readq(afar_reg); |
310 | afsr = sabre_read(afsr_reg); | 205 | afsr = upa_readq(afsr_reg); |
311 | 206 | ||
312 | /* Clear the primary/secondary error status bits. */ | 207 | /* Clear the primary/secondary error status bits. */ |
313 | error_bits = afsr & | 208 | error_bits = afsr & |
@@ -316,7 +211,7 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) | |||
316 | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE); | 211 | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE); |
317 | if (!error_bits) | 212 | if (!error_bits) |
318 | return IRQ_NONE; | 213 | return IRQ_NONE; |
319 | sabre_write(afsr_reg, error_bits); | 214 | upa_writeq(error_bits, afsr_reg); |
320 | 215 | ||
321 | /* Log the error. */ | 216 | /* Log the error. */ |
322 | printk("%s: Uncorrectable Error, primary error type[%s%s]\n", | 217 | printk("%s: Uncorrectable Error, primary error type[%s%s]\n", |
@@ -352,7 +247,7 @@ static irqreturn_t sabre_ue_intr(int irq, void *dev_id) | |||
352 | printk("]\n"); | 247 | printk("]\n"); |
353 | 248 | ||
354 | /* Interrogate IOMMU for error status. */ | 249 | /* Interrogate IOMMU for error status. */ |
355 | sabre_check_iommu_error(pbm, afsr, afar); | 250 | psycho_check_iommu_error(pbm, afsr, afar, UE_ERR); |
356 | 251 | ||
357 | return IRQ_HANDLED; | 252 | return IRQ_HANDLED; |
358 | } | 253 | } |
@@ -366,8 +261,8 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) | |||
366 | int reported; | 261 | int reported; |
367 | 262 | ||
368 | /* Latch error status. */ | 263 | /* Latch error status. */ |
369 | afar = sabre_read(afar_reg); | 264 | afar = upa_readq(afar_reg); |
370 | afsr = sabre_read(afsr_reg); | 265 | afsr = upa_readq(afsr_reg); |
371 | 266 | ||
372 | /* Clear primary/secondary error status bits. */ | 267 | /* Clear primary/secondary error status bits. */ |
373 | error_bits = afsr & | 268 | error_bits = afsr & |
@@ -375,7 +270,7 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) | |||
375 | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR); | 270 | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR); |
376 | if (!error_bits) | 271 | if (!error_bits) |
377 | return IRQ_NONE; | 272 | return IRQ_NONE; |
378 | sabre_write(afsr_reg, error_bits); | 273 | upa_writeq(error_bits, afsr_reg); |
379 | 274 | ||
380 | /* Log the error. */ | 275 | /* Log the error. */ |
381 | printk("%s: Correctable Error, primary error type[%s]\n", | 276 | printk("%s: Correctable Error, primary error type[%s]\n", |
@@ -413,136 +308,9 @@ static irqreturn_t sabre_ce_intr(int irq, void *dev_id) | |||
413 | return IRQ_HANDLED; | 308 | return IRQ_HANDLED; |
414 | } | 309 | } |
415 | 310 | ||
416 | static irqreturn_t sabre_pcierr_intr_other(struct pci_pbm_info *pbm) | ||
417 | { | ||
418 | unsigned long csr_reg, csr, csr_error_bits; | ||
419 | irqreturn_t ret = IRQ_NONE; | ||
420 | u16 stat; | ||
421 | |||
422 | csr_reg = pbm->controller_regs + SABRE_PCICTRL; | ||
423 | csr = sabre_read(csr_reg); | ||
424 | csr_error_bits = | ||
425 | csr & SABRE_PCICTRL_SERR; | ||
426 | if (csr_error_bits) { | ||
427 | /* Clear the errors. */ | ||
428 | sabre_write(csr_reg, csr); | ||
429 | |||
430 | /* Log 'em. */ | ||
431 | if (csr_error_bits & SABRE_PCICTRL_SERR) | ||
432 | printk("%s: PCI SERR signal asserted.\n", | ||
433 | pbm->name); | ||
434 | ret = IRQ_HANDLED; | ||
435 | } | ||
436 | pci_bus_read_config_word(sabre_root_bus, 0, | ||
437 | PCI_STATUS, &stat); | ||
438 | if (stat & (PCI_STATUS_PARITY | | ||
439 | PCI_STATUS_SIG_TARGET_ABORT | | ||
440 | PCI_STATUS_REC_TARGET_ABORT | | ||
441 | PCI_STATUS_REC_MASTER_ABORT | | ||
442 | PCI_STATUS_SIG_SYSTEM_ERROR)) { | ||
443 | printk("%s: PCI bus error, PCI_STATUS[%04x]\n", | ||
444 | pbm->name, stat); | ||
445 | pci_bus_write_config_word(sabre_root_bus, 0, | ||
446 | PCI_STATUS, 0xffff); | ||
447 | ret = IRQ_HANDLED; | ||
448 | } | ||
449 | return ret; | ||
450 | } | ||
451 | |||
452 | static irqreturn_t sabre_pcierr_intr(int irq, void *dev_id) | ||
453 | { | ||
454 | struct pci_pbm_info *pbm = dev_id; | ||
455 | unsigned long afsr_reg, afar_reg; | ||
456 | unsigned long afsr, afar, error_bits; | ||
457 | int reported; | ||
458 | |||
459 | afsr_reg = pbm->controller_regs + SABRE_PIOAFSR; | ||
460 | afar_reg = pbm->controller_regs + SABRE_PIOAFAR; | ||
461 | |||
462 | /* Latch error status. */ | ||
463 | afar = sabre_read(afar_reg); | ||
464 | afsr = sabre_read(afsr_reg); | ||
465 | |||
466 | /* Clear primary/secondary error status bits. */ | ||
467 | error_bits = afsr & | ||
468 | (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_PTA | | ||
469 | SABRE_PIOAFSR_PRTRY | SABRE_PIOAFSR_PPERR | | ||
470 | SABRE_PIOAFSR_SMA | SABRE_PIOAFSR_STA | | ||
471 | SABRE_PIOAFSR_SRTRY | SABRE_PIOAFSR_SPERR); | ||
472 | if (!error_bits) | ||
473 | return sabre_pcierr_intr_other(pbm); | ||
474 | sabre_write(afsr_reg, error_bits); | ||
475 | |||
476 | /* Log the error. */ | ||
477 | printk("%s: PCI Error, primary error type[%s]\n", | ||
478 | pbm->name, | ||
479 | (((error_bits & SABRE_PIOAFSR_PMA) ? | ||
480 | "Master Abort" : | ||
481 | ((error_bits & SABRE_PIOAFSR_PTA) ? | ||
482 | "Target Abort" : | ||
483 | ((error_bits & SABRE_PIOAFSR_PRTRY) ? | ||
484 | "Excessive Retries" : | ||
485 | ((error_bits & SABRE_PIOAFSR_PPERR) ? | ||
486 | "Parity Error" : "???")))))); | ||
487 | printk("%s: bytemask[%04lx] was_block(%d)\n", | ||
488 | pbm->name, | ||
489 | (afsr & SABRE_PIOAFSR_BMSK) >> 32UL, | ||
490 | (afsr & SABRE_PIOAFSR_BLK) ? 1 : 0); | ||
491 | printk("%s: PCI AFAR [%016lx]\n", pbm->name, afar); | ||
492 | printk("%s: PCI Secondary errors [", pbm->name); | ||
493 | reported = 0; | ||
494 | if (afsr & SABRE_PIOAFSR_SMA) { | ||
495 | reported++; | ||
496 | printk("(Master Abort)"); | ||
497 | } | ||
498 | if (afsr & SABRE_PIOAFSR_STA) { | ||
499 | reported++; | ||
500 | printk("(Target Abort)"); | ||
501 | } | ||
502 | if (afsr & SABRE_PIOAFSR_SRTRY) { | ||
503 | reported++; | ||
504 | printk("(Excessive Retries)"); | ||
505 | } | ||
506 | if (afsr & SABRE_PIOAFSR_SPERR) { | ||
507 | reported++; | ||
508 | printk("(Parity Error)"); | ||
509 | } | ||
510 | if (!reported) | ||
511 | printk("(none)"); | ||
512 | printk("]\n"); | ||
513 | |||
514 | /* For the error types shown, scan both PCI buses for devices | ||
515 | * which have logged that error type. | ||
516 | */ | ||
517 | |||
518 | /* If we see a Target Abort, this could be the result of an | ||
519 | * IOMMU translation error of some sort. It is extremely | ||
520 | * useful to log this information as usually it indicates | ||
521 | * a bug in the IOMMU support code or a PCI device driver. | ||
522 | */ | ||
523 | if (error_bits & (SABRE_PIOAFSR_PTA | SABRE_PIOAFSR_STA)) { | ||
524 | sabre_check_iommu_error(pbm, afsr, afar); | ||
525 | pci_scan_for_target_abort(pbm, pbm->pci_bus); | ||
526 | } | ||
527 | if (error_bits & (SABRE_PIOAFSR_PMA | SABRE_PIOAFSR_SMA)) | ||
528 | pci_scan_for_master_abort(pbm, pbm->pci_bus); | ||
529 | |||
530 | /* For excessive retries, SABRE/PBM will abort the device | ||
531 | * and there is no way to specifically check for excessive | ||
532 | * retries in the config space status registers. So what | ||
533 | * we hope is that we'll catch it via the master/target | ||
534 | * abort events. | ||
535 | */ | ||
536 | |||
537 | if (error_bits & (SABRE_PIOAFSR_PPERR | SABRE_PIOAFSR_SPERR)) | ||
538 | pci_scan_for_parity_error(pbm, pbm->pci_bus); | ||
539 | |||
540 | return IRQ_HANDLED; | ||
541 | } | ||
542 | |||
543 | static void sabre_register_error_handlers(struct pci_pbm_info *pbm) | 311 | static void sabre_register_error_handlers(struct pci_pbm_info *pbm) |
544 | { | 312 | { |
545 | struct device_node *dp = pbm->prom_node; | 313 | struct device_node *dp = pbm->op->node; |
546 | struct of_device *op; | 314 | struct of_device *op; |
547 | unsigned long base = pbm->controller_regs; | 315 | unsigned long base = pbm->controller_regs; |
548 | u64 tmp; | 316 | u64 tmp; |
@@ -568,33 +336,34 @@ static void sabre_register_error_handlers(struct pci_pbm_info *pbm) | |||
568 | * registering the handler so that we don't get spurious | 336 | * registering the handler so that we don't get spurious |
569 | * interrupts. | 337 | * interrupts. |
570 | */ | 338 | */ |
571 | sabre_write(base + SABRE_UE_AFSR, | 339 | upa_writeq((SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | |
572 | (SABRE_UEAFSR_PDRD | SABRE_UEAFSR_PDWR | | 340 | SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | |
573 | SABRE_UEAFSR_SDRD | SABRE_UEAFSR_SDWR | | 341 | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE), |
574 | SABRE_UEAFSR_SDTE | SABRE_UEAFSR_PDTE)); | 342 | base + SABRE_UE_AFSR); |
575 | 343 | ||
576 | err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); | 344 | err = request_irq(op->irqs[1], sabre_ue_intr, 0, "SABRE_UE", pbm); |
577 | if (err) | 345 | if (err) |
578 | printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n", | 346 | printk(KERN_WARNING "%s: Couldn't register UE, err=%d.\n", |
579 | pbm->name, err); | 347 | pbm->name, err); |
580 | 348 | ||
581 | sabre_write(base + SABRE_CE_AFSR, | 349 | upa_writeq((SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | |
582 | (SABRE_CEAFSR_PDRD | SABRE_CEAFSR_PDWR | | 350 | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR), |
583 | SABRE_CEAFSR_SDRD | SABRE_CEAFSR_SDWR)); | 351 | base + SABRE_CE_AFSR); |
352 | |||
584 | 353 | ||
585 | err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); | 354 | err = request_irq(op->irqs[2], sabre_ce_intr, 0, "SABRE_CE", pbm); |
586 | if (err) | 355 | if (err) |
587 | printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n", | 356 | printk(KERN_WARNING "%s: Couldn't register CE, err=%d.\n", |
588 | pbm->name, err); | 357 | pbm->name, err); |
589 | err = request_irq(op->irqs[0], sabre_pcierr_intr, 0, | 358 | err = request_irq(op->irqs[0], psycho_pcierr_intr, 0, |
590 | "SABRE_PCIERR", pbm); | 359 | "SABRE_PCIERR", pbm); |
591 | if (err) | 360 | if (err) |
592 | printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", | 361 | printk(KERN_WARNING "%s: Couldn't register PCIERR, err=%d.\n", |
593 | pbm->name, err); | 362 | pbm->name, err); |
594 | 363 | ||
595 | tmp = sabre_read(base + SABRE_PCICTRL); | 364 | tmp = upa_readq(base + SABRE_PCICTRL); |
596 | tmp |= SABRE_PCICTRL_ERREN; | 365 | tmp |= SABRE_PCICTRL_ERREN; |
597 | sabre_write(base + SABRE_PCICTRL, tmp); | 366 | upa_writeq(tmp, base + SABRE_PCICTRL); |
598 | } | 367 | } |
599 | 368 | ||
600 | static void apb_init(struct pci_bus *sabre_bus) | 369 | static void apb_init(struct pci_bus *sabre_bus) |
@@ -633,7 +402,8 @@ static void apb_init(struct pci_bus *sabre_bus) | |||
633 | } | 402 | } |
634 | } | 403 | } |
635 | 404 | ||
636 | static void __init sabre_scan_bus(struct pci_pbm_info *pbm) | 405 | static void __init sabre_scan_bus(struct pci_pbm_info *pbm, |
406 | struct device *parent) | ||
637 | { | 407 | { |
638 | static int once; | 408 | static int once; |
639 | 409 | ||
@@ -656,12 +426,12 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm) | |||
656 | * to live at bus 0. | 426 | * to live at bus 0. |
657 | */ | 427 | */ |
658 | if (once != 0) { | 428 | if (once != 0) { |
659 | prom_printf("SABRE: Multiple controllers unsupported.\n"); | 429 | printk(KERN_ERR PFX "Multiple controllers unsupported.\n"); |
660 | prom_halt(); | 430 | return; |
661 | } | 431 | } |
662 | once++; | 432 | once++; |
663 | 433 | ||
664 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 434 | pbm->pci_bus = pci_scan_one_pbm(pbm, parent); |
665 | if (!pbm->pci_bus) | 435 | if (!pbm->pci_bus) |
666 | return; | 436 | return; |
667 | 437 | ||
@@ -672,133 +442,58 @@ static void __init sabre_scan_bus(struct pci_pbm_info *pbm) | |||
672 | sabre_register_error_handlers(pbm); | 442 | sabre_register_error_handlers(pbm); |
673 | } | 443 | } |
674 | 444 | ||
675 | static int sabre_iommu_init(struct pci_pbm_info *pbm, | 445 | static void __init sabre_pbm_init(struct pci_pbm_info *pbm, |
676 | int tsbsize, unsigned long dvma_offset, | 446 | struct of_device *op) |
677 | u32 dma_mask) | ||
678 | { | ||
679 | struct iommu *iommu = pbm->iommu; | ||
680 | unsigned long i; | ||
681 | u64 control; | ||
682 | int err; | ||
683 | |||
684 | /* Register addresses. */ | ||
685 | iommu->iommu_control = pbm->controller_regs + SABRE_IOMMU_CONTROL; | ||
686 | iommu->iommu_tsbbase = pbm->controller_regs + SABRE_IOMMU_TSBBASE; | ||
687 | iommu->iommu_flush = pbm->controller_regs + SABRE_IOMMU_FLUSH; | ||
688 | iommu->iommu_tags = iommu->iommu_flush + (0xa580UL - 0x0210UL); | ||
689 | iommu->write_complete_reg = pbm->controller_regs + SABRE_WRSYNC; | ||
690 | /* Sabre's IOMMU lacks ctx flushing. */ | ||
691 | iommu->iommu_ctxflush = 0; | ||
692 | |||
693 | /* Invalidate TLB Entries. */ | ||
694 | control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); | ||
695 | control |= SABRE_IOMMUCTRL_DENAB; | ||
696 | sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); | ||
697 | |||
698 | for(i = 0; i < 16; i++) { | ||
699 | sabre_write(pbm->controller_regs + SABRE_IOMMU_TAG + (i * 8UL), 0); | ||
700 | sabre_write(pbm->controller_regs + SABRE_IOMMU_DATA + (i * 8UL), 0); | ||
701 | } | ||
702 | |||
703 | /* Leave diag mode enabled for full-flushing done | ||
704 | * in pci_iommu.c | ||
705 | */ | ||
706 | err = iommu_table_init(iommu, tsbsize * 1024 * 8, | ||
707 | dvma_offset, dma_mask, pbm->numa_node); | ||
708 | if (err) | ||
709 | return err; | ||
710 | |||
711 | sabre_write(pbm->controller_regs + SABRE_IOMMU_TSBBASE, | ||
712 | __pa(iommu->page_table)); | ||
713 | |||
714 | control = sabre_read(pbm->controller_regs + SABRE_IOMMU_CONTROL); | ||
715 | control &= ~(SABRE_IOMMUCTRL_TSBSZ | SABRE_IOMMUCTRL_TBWSZ); | ||
716 | control |= SABRE_IOMMUCTRL_ENAB; | ||
717 | switch(tsbsize) { | ||
718 | case 64: | ||
719 | control |= SABRE_IOMMU_TSBSZ_64K; | ||
720 | break; | ||
721 | case 128: | ||
722 | control |= SABRE_IOMMU_TSBSZ_128K; | ||
723 | break; | ||
724 | default: | ||
725 | prom_printf("iommu_init: Illegal TSB size %d\n", tsbsize); | ||
726 | prom_halt(); | ||
727 | break; | ||
728 | } | ||
729 | sabre_write(pbm->controller_regs + SABRE_IOMMU_CONTROL, control); | ||
730 | |||
731 | return 0; | ||
732 | } | ||
733 | |||
734 | static void __init sabre_pbm_init(struct pci_controller_info *p, | ||
735 | struct pci_pbm_info *pbm, struct device_node *dp) | ||
736 | { | 447 | { |
737 | pbm->name = dp->full_name; | 448 | psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE); |
738 | printk("%s: SABRE PCI Bus Module\n", pbm->name); | 449 | pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR; |
739 | 450 | pbm->pci_afar = pbm->controller_regs + SABRE_PIOAFAR; | |
740 | pbm->numa_node = -1; | 451 | pbm->pci_csr = pbm->controller_regs + SABRE_PCICTRL; |
741 | 452 | sabre_scan_bus(pbm, &op->dev); | |
742 | pbm->scan_bus = sabre_scan_bus; | ||
743 | pbm->pci_ops = &sun4u_pci_ops; | ||
744 | pbm->config_space_reg_bits = 8; | ||
745 | |||
746 | pbm->index = pci_num_pbms++; | ||
747 | |||
748 | pbm->chip_type = PBM_CHIP_TYPE_SABRE; | ||
749 | pbm->parent = p; | ||
750 | pbm->prom_node = dp; | ||
751 | pci_get_pbm_props(pbm); | ||
752 | |||
753 | pci_determine_mem_io_space(pbm); | ||
754 | } | 453 | } |
755 | 454 | ||
756 | void __init sabre_init(struct device_node *dp, char *model_name) | 455 | static int __devinit sabre_probe(struct of_device *op, |
456 | const struct of_device_id *match) | ||
757 | { | 457 | { |
758 | const struct linux_prom64_registers *pr_regs; | 458 | const struct linux_prom64_registers *pr_regs; |
759 | struct pci_controller_info *p; | 459 | struct device_node *dp = op->node; |
760 | struct pci_pbm_info *pbm; | 460 | struct pci_pbm_info *pbm; |
461 | u32 upa_portid, dma_mask; | ||
761 | struct iommu *iommu; | 462 | struct iommu *iommu; |
762 | int tsbsize; | 463 | int tsbsize, err; |
763 | const u32 *vdma; | 464 | const u32 *vdma; |
764 | u32 upa_portid, dma_mask; | ||
765 | u64 clear_irq; | 465 | u64 clear_irq; |
766 | 466 | ||
767 | hummingbird_p = 0; | 467 | hummingbird_p = (match->data != NULL); |
768 | if (!strcmp(model_name, "pci108e,a001")) | 468 | if (!hummingbird_p) { |
769 | hummingbird_p = 1; | 469 | struct device_node *cpu_dp; |
770 | else if (!strcmp(model_name, "SUNW,sabre")) { | 470 | |
771 | const char *compat = of_get_property(dp, "compatible", NULL); | 471 | /* Of course, Sun has to encode things a thousand |
772 | if (compat && !strcmp(compat, "pci108e,a001")) | 472 | * different ways, inconsistently. |
773 | hummingbird_p = 1; | 473 | */ |
774 | if (!hummingbird_p) { | 474 | for_each_node_by_type(cpu_dp, "cpu") { |
775 | struct device_node *dp; | 475 | if (!strcmp(cpu_dp->name, "SUNW,UltraSPARC-IIe")) |
776 | 476 | hummingbird_p = 1; | |
777 | /* Of course, Sun has to encode things a thousand | ||
778 | * different ways, inconsistently. | ||
779 | */ | ||
780 | for_each_node_by_type(dp, "cpu") { | ||
781 | if (!strcmp(dp->name, "SUNW,UltraSPARC-IIe")) | ||
782 | hummingbird_p = 1; | ||
783 | } | ||
784 | } | 477 | } |
785 | } | 478 | } |
786 | 479 | ||
787 | p = kzalloc(sizeof(*p), GFP_ATOMIC); | 480 | err = -ENOMEM; |
788 | if (!p) | 481 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
789 | goto fatal_memory_error; | 482 | if (!pbm) { |
483 | printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); | ||
484 | goto out_err; | ||
485 | } | ||
486 | |||
487 | iommu = kzalloc(sizeof(*iommu), GFP_KERNEL); | ||
488 | if (!iommu) { | ||
489 | printk(KERN_ERR PFX "Cannot allocate PBM iommu.\n"); | ||
490 | goto out_free_controller; | ||
491 | } | ||
790 | 492 | ||
791 | iommu = kzalloc(sizeof(*iommu), GFP_ATOMIC); | ||
792 | if (!iommu) | ||
793 | goto fatal_memory_error; | ||
794 | pbm = &p->pbm_A; | ||
795 | pbm->iommu = iommu; | 493 | pbm->iommu = iommu; |
796 | 494 | ||
797 | upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); | 495 | upa_portid = of_getintprop_default(dp, "upa-portid", 0xff); |
798 | 496 | ||
799 | pbm->next = pci_pbm_root; | ||
800 | pci_pbm_root = pbm; | ||
801 | |||
802 | pbm->portid = upa_portid; | 497 | pbm->portid = upa_portid; |
803 | 498 | ||
804 | /* | 499 | /* |
@@ -806,6 +501,11 @@ void __init sabre_init(struct device_node *dp, char *model_name) | |||
806 | */ | 501 | */ |
807 | 502 | ||
808 | pr_regs = of_get_property(dp, "reg", NULL); | 503 | pr_regs = of_get_property(dp, "reg", NULL); |
504 | err = -ENODEV; | ||
505 | if (!pr_regs) { | ||
506 | printk(KERN_ERR PFX "No reg property\n"); | ||
507 | goto out_free_iommu; | ||
508 | } | ||
809 | 509 | ||
810 | /* | 510 | /* |
811 | * First REG in property is base of entire SABRE register space. | 511 | * First REG in property is base of entire SABRE register space. |
@@ -816,22 +516,25 @@ void __init sabre_init(struct device_node *dp, char *model_name) | |||
816 | 516 | ||
817 | /* PCI first */ | 517 | /* PCI first */ |
818 | for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) | 518 | for (clear_irq = SABRE_ICLR_A_SLOT0; clear_irq < SABRE_ICLR_B_SLOT0 + 0x80; clear_irq += 8) |
819 | sabre_write(pbm->controller_regs + clear_irq, 0x0UL); | 519 | upa_writeq(0x0UL, pbm->controller_regs + clear_irq); |
820 | 520 | ||
821 | /* Then OBIO */ | 521 | /* Then OBIO */ |
822 | for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) | 522 | for (clear_irq = SABRE_ICLR_SCSI; clear_irq < SABRE_ICLR_SCSI + 0x80; clear_irq += 8) |
823 | sabre_write(pbm->controller_regs + clear_irq, 0x0UL); | 523 | upa_writeq(0x0UL, pbm->controller_regs + clear_irq); |
824 | 524 | ||
825 | /* Error interrupts are enabled later after the bus scan. */ | 525 | /* Error interrupts are enabled later after the bus scan. */ |
826 | sabre_write(pbm->controller_regs + SABRE_PCICTRL, | 526 | upa_writeq((SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | |
827 | (SABRE_PCICTRL_MRLEN | SABRE_PCICTRL_SERR | | 527 | SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN), |
828 | SABRE_PCICTRL_ARBPARK | SABRE_PCICTRL_AEN)); | 528 | pbm->controller_regs + SABRE_PCICTRL); |
829 | 529 | ||
830 | /* Now map in PCI config space for entire SABRE. */ | 530 | /* Now map in PCI config space for entire SABRE. */ |
831 | pbm->config_space = | 531 | pbm->config_space = pbm->controller_regs + SABRE_CONFIGSPACE; |
832 | (pbm->controller_regs + SABRE_CONFIGSPACE); | ||
833 | 532 | ||
834 | vdma = of_get_property(dp, "virtual-dma", NULL); | 533 | vdma = of_get_property(dp, "virtual-dma", NULL); |
534 | if (!vdma) { | ||
535 | printk(KERN_ERR PFX "No virtual-dma property\n"); | ||
536 | goto out_free_iommu; | ||
537 | } | ||
835 | 538 | ||
836 | dma_mask = vdma[0]; | 539 | dma_mask = vdma[0]; |
837 | switch(vdma[1]) { | 540 | switch(vdma[1]) { |
@@ -849,20 +552,58 @@ void __init sabre_init(struct device_node *dp, char *model_name) | |||
849 | tsbsize = 128; | 552 | tsbsize = 128; |
850 | break; | 553 | break; |
851 | default: | 554 | default: |
852 | prom_printf("SABRE: strange virtual-dma size.\n"); | 555 | printk(KERN_ERR PFX "Strange virtual-dma size.\n"); |
853 | prom_halt(); | 556 | goto out_free_iommu; |
854 | } | 557 | } |
855 | 558 | ||
856 | if (sabre_iommu_init(pbm, tsbsize, vdma[0], dma_mask)) | 559 | err = psycho_iommu_init(pbm, tsbsize, vdma[0], dma_mask, SABRE_WRSYNC); |
857 | goto fatal_memory_error; | 560 | if (err) |
561 | goto out_free_iommu; | ||
858 | 562 | ||
859 | /* | 563 | /* |
860 | * Look for APB underneath. | 564 | * Look for APB underneath. |
861 | */ | 565 | */ |
862 | sabre_pbm_init(p, pbm, dp); | 566 | sabre_pbm_init(pbm, op); |
863 | return; | ||
864 | 567 | ||
865 | fatal_memory_error: | 568 | pbm->next = pci_pbm_root; |
866 | prom_printf("SABRE: Fatal memory allocation error.\n"); | 569 | pci_pbm_root = pbm; |
867 | prom_halt(); | 570 | |
571 | dev_set_drvdata(&op->dev, pbm); | ||
572 | |||
573 | return 0; | ||
574 | |||
575 | out_free_iommu: | ||
576 | kfree(pbm->iommu); | ||
577 | |||
578 | out_free_controller: | ||
579 | kfree(pbm); | ||
580 | |||
581 | out_err: | ||
582 | return err; | ||
583 | } | ||
584 | |||
585 | static struct of_device_id __initdata sabre_match[] = { | ||
586 | { | ||
587 | .name = "pci", | ||
588 | .compatible = "pci108e,a001", | ||
589 | .data = (void *) 1, | ||
590 | }, | ||
591 | { | ||
592 | .name = "pci", | ||
593 | .compatible = "pci108e,a000", | ||
594 | }, | ||
595 | {}, | ||
596 | }; | ||
597 | |||
598 | static struct of_platform_driver sabre_driver = { | ||
599 | .name = DRIVER_NAME, | ||
600 | .match_table = sabre_match, | ||
601 | .probe = sabre_probe, | ||
602 | }; | ||
603 | |||
604 | static int __init sabre_init(void) | ||
605 | { | ||
606 | return of_register_driver(&sabre_driver, &of_bus_type); | ||
868 | } | 607 | } |
608 | |||
609 | subsys_initcall(sabre_init); | ||
diff --git a/arch/sparc64/kernel/pci_schizo.c b/arch/sparc64/kernel/pci_schizo.c index 9248c6737f0e..45d9dba1ba11 100644 --- a/arch/sparc64/kernel/pci_schizo.c +++ b/arch/sparc64/kernel/pci_schizo.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support. | 1 | /* pci_schizo.c: SCHIZO/TOMATILLO specific PCI controller support. |
2 | * | 2 | * |
3 | * Copyright (C) 2001, 2002, 2003, 2007 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 2001, 2002, 2003, 2007, 2008 David S. Miller (davem@davemloft.net) |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
@@ -13,32 +13,15 @@ | |||
13 | 13 | ||
14 | #include <asm/iommu.h> | 14 | #include <asm/iommu.h> |
15 | #include <asm/irq.h> | 15 | #include <asm/irq.h> |
16 | #include <asm/upa.h> | ||
17 | #include <asm/pstate.h> | 16 | #include <asm/pstate.h> |
18 | #include <asm/prom.h> | 17 | #include <asm/prom.h> |
19 | #include <asm/oplib.h> | 18 | #include <asm/upa.h> |
20 | 19 | ||
21 | #include "pci_impl.h" | 20 | #include "pci_impl.h" |
22 | #include "iommu_common.h" | 21 | #include "iommu_common.h" |
23 | 22 | ||
24 | /* All SCHIZO registers are 64-bits. The following accessor | 23 | #define DRIVER_NAME "schizo" |
25 | * routines are how they are accessed. The REG parameter | 24 | #define PFX DRIVER_NAME ": " |
26 | * is a physical address. | ||
27 | */ | ||
28 | #define schizo_read(__reg) \ | ||
29 | ({ u64 __ret; \ | ||
30 | __asm__ __volatile__("ldxa [%1] %2, %0" \ | ||
31 | : "=r" (__ret) \ | ||
32 | : "r" (__reg), "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
33 | : "memory"); \ | ||
34 | __ret; \ | ||
35 | }) | ||
36 | #define schizo_write(__reg, __val) \ | ||
37 | __asm__ __volatile__("stxa %0, [%1] %2" \ | ||
38 | : /* no outputs */ \ | ||
39 | : "r" (__val), "r" (__reg), \ | ||
40 | "i" (ASI_PHYS_BYPASS_EC_E) \ | ||
41 | : "memory") | ||
42 | 25 | ||
43 | /* This is a convention that at least Excalibur and Merlin | 26 | /* This is a convention that at least Excalibur and Merlin |
44 | * follow. I suppose the SCHIZO used in Starcat and friends | 27 | * follow. I suppose the SCHIZO used in Starcat and friends |
@@ -163,25 +146,25 @@ static void __schizo_check_stc_error_pbm(struct pci_pbm_info *pbm, | |||
163 | * invalidating it before it has a chance to reach | 146 | * invalidating it before it has a chance to reach |
164 | * main memory. | 147 | * main memory. |
165 | */ | 148 | */ |
166 | control = schizo_read(strbuf->strbuf_control); | 149 | control = upa_readq(strbuf->strbuf_control); |
167 | schizo_write(strbuf->strbuf_control, | 150 | upa_writeq((control | SCHIZO_STRBUF_CTRL_DENAB), |
168 | (control | SCHIZO_STRBUF_CTRL_DENAB)); | 151 | strbuf->strbuf_control); |
169 | for (i = 0; i < 128; i++) { | 152 | for (i = 0; i < 128; i++) { |
170 | unsigned long val; | 153 | unsigned long val; |
171 | 154 | ||
172 | val = schizo_read(err_base + (i * 8UL)); | 155 | val = upa_readq(err_base + (i * 8UL)); |
173 | schizo_write(err_base + (i * 8UL), 0UL); | 156 | upa_writeq(0UL, err_base + (i * 8UL)); |
174 | stc_error_buf[i] = val; | 157 | stc_error_buf[i] = val; |
175 | } | 158 | } |
176 | for (i = 0; i < 16; i++) { | 159 | for (i = 0; i < 16; i++) { |
177 | stc_tag_buf[i] = schizo_read(tag_base + (i * 8UL)); | 160 | stc_tag_buf[i] = upa_readq(tag_base + (i * 8UL)); |
178 | stc_line_buf[i] = schizo_read(line_base + (i * 8UL)); | 161 | stc_line_buf[i] = upa_readq(line_base + (i * 8UL)); |
179 | schizo_write(tag_base + (i * 8UL), 0UL); | 162 | upa_writeq(0UL, tag_base + (i * 8UL)); |
180 | schizo_write(line_base + (i * 8UL), 0UL); | 163 | upa_writeq(0UL, line_base + (i * 8UL)); |
181 | } | 164 | } |
182 | 165 | ||
183 | /* OK, state is logged, exit diagnostic mode. */ | 166 | /* OK, state is logged, exit diagnostic mode. */ |
184 | schizo_write(strbuf->strbuf_control, control); | 167 | upa_writeq(control, strbuf->strbuf_control); |
185 | 168 | ||
186 | for (i = 0; i < 16; i++) { | 169 | for (i = 0; i < 16; i++) { |
187 | int j, saw_error, first, last; | 170 | int j, saw_error, first, last; |
@@ -258,14 +241,14 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, | |||
258 | int i; | 241 | int i; |
259 | 242 | ||
260 | spin_lock_irqsave(&iommu->lock, flags); | 243 | spin_lock_irqsave(&iommu->lock, flags); |
261 | control = schizo_read(iommu->iommu_control); | 244 | control = upa_readq(iommu->iommu_control); |
262 | if (control & SCHIZO_IOMMU_CTRL_XLTEERR) { | 245 | if (control & SCHIZO_IOMMU_CTRL_XLTEERR) { |
263 | unsigned long base; | 246 | unsigned long base; |
264 | char *type_string; | 247 | char *type_string; |
265 | 248 | ||
266 | /* Clear the error encountered bit. */ | 249 | /* Clear the error encountered bit. */ |
267 | control &= ~SCHIZO_IOMMU_CTRL_XLTEERR; | 250 | control &= ~SCHIZO_IOMMU_CTRL_XLTEERR; |
268 | schizo_write(iommu->iommu_control, control); | 251 | upa_writeq(control, iommu->iommu_control); |
269 | 252 | ||
270 | switch((control & SCHIZO_IOMMU_CTRL_XLTESTAT) >> 25UL) { | 253 | switch((control & SCHIZO_IOMMU_CTRL_XLTESTAT) >> 25UL) { |
271 | case 0: | 254 | case 0: |
@@ -295,24 +278,24 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, | |||
295 | * get as much diagnostic information to the | 278 | * get as much diagnostic information to the |
296 | * console as we can. | 279 | * console as we can. |
297 | */ | 280 | */ |
298 | schizo_write(iommu->iommu_control, | 281 | upa_writeq(control | SCHIZO_IOMMU_CTRL_DENAB, |
299 | control | SCHIZO_IOMMU_CTRL_DENAB); | 282 | iommu->iommu_control); |
300 | 283 | ||
301 | base = pbm->pbm_regs; | 284 | base = pbm->pbm_regs; |
302 | 285 | ||
303 | for (i = 0; i < 16; i++) { | 286 | for (i = 0; i < 16; i++) { |
304 | iommu_tag[i] = | 287 | iommu_tag[i] = |
305 | schizo_read(base + SCHIZO_IOMMU_TAG + (i * 8UL)); | 288 | upa_readq(base + SCHIZO_IOMMU_TAG + (i * 8UL)); |
306 | iommu_data[i] = | 289 | iommu_data[i] = |
307 | schizo_read(base + SCHIZO_IOMMU_DATA + (i * 8UL)); | 290 | upa_readq(base + SCHIZO_IOMMU_DATA + (i * 8UL)); |
308 | 291 | ||
309 | /* Now clear out the entry. */ | 292 | /* Now clear out the entry. */ |
310 | schizo_write(base + SCHIZO_IOMMU_TAG + (i * 8UL), 0); | 293 | upa_writeq(0, base + SCHIZO_IOMMU_TAG + (i * 8UL)); |
311 | schizo_write(base + SCHIZO_IOMMU_DATA + (i * 8UL), 0); | 294 | upa_writeq(0, base + SCHIZO_IOMMU_DATA + (i * 8UL)); |
312 | } | 295 | } |
313 | 296 | ||
314 | /* Leave diagnostic mode. */ | 297 | /* Leave diagnostic mode. */ |
315 | schizo_write(iommu->iommu_control, control); | 298 | upa_writeq(control, iommu->iommu_control); |
316 | 299 | ||
317 | for (i = 0; i < 16; i++) { | 300 | for (i = 0; i < 16; i++) { |
318 | unsigned long tag, data; | 301 | unsigned long tag, data; |
@@ -357,11 +340,12 @@ static void schizo_check_iommu_error_pbm(struct pci_pbm_info *pbm, | |||
357 | spin_unlock_irqrestore(&iommu->lock, flags); | 340 | spin_unlock_irqrestore(&iommu->lock, flags); |
358 | } | 341 | } |
359 | 342 | ||
360 | static void schizo_check_iommu_error(struct pci_controller_info *p, | 343 | static void schizo_check_iommu_error(struct pci_pbm_info *pbm, |
361 | enum schizo_error_type type) | 344 | enum schizo_error_type type) |
362 | { | 345 | { |
363 | schizo_check_iommu_error_pbm(&p->pbm_A, type); | 346 | schizo_check_iommu_error_pbm(pbm, type); |
364 | schizo_check_iommu_error_pbm(&p->pbm_B, type); | 347 | if (pbm->sibling) |
348 | schizo_check_iommu_error_pbm(pbm->sibling, type); | ||
365 | } | 349 | } |
366 | 350 | ||
367 | /* Uncorrectable ECC error status gathering. */ | 351 | /* Uncorrectable ECC error status gathering. */ |
@@ -386,14 +370,13 @@ static void schizo_check_iommu_error(struct pci_controller_info *p, | |||
386 | static irqreturn_t schizo_ue_intr(int irq, void *dev_id) | 370 | static irqreturn_t schizo_ue_intr(int irq, void *dev_id) |
387 | { | 371 | { |
388 | struct pci_pbm_info *pbm = dev_id; | 372 | struct pci_pbm_info *pbm = dev_id; |
389 | struct pci_controller_info *p = pbm->parent; | ||
390 | unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR; | 373 | unsigned long afsr_reg = pbm->controller_regs + SCHIZO_UE_AFSR; |
391 | unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR; | 374 | unsigned long afar_reg = pbm->controller_regs + SCHIZO_UE_AFAR; |
392 | unsigned long afsr, afar, error_bits; | 375 | unsigned long afsr, afar, error_bits; |
393 | int reported, limit; | 376 | int reported, limit; |
394 | 377 | ||
395 | /* Latch uncorrectable error status. */ | 378 | /* Latch uncorrectable error status. */ |
396 | afar = schizo_read(afar_reg); | 379 | afar = upa_readq(afar_reg); |
397 | 380 | ||
398 | /* If either of the error pending bits are set in the | 381 | /* If either of the error pending bits are set in the |
399 | * AFSR, the error status is being actively updated by | 382 | * AFSR, the error status is being actively updated by |
@@ -401,7 +384,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) | |||
401 | */ | 384 | */ |
402 | limit = 1000; | 385 | limit = 1000; |
403 | do { | 386 | do { |
404 | afsr = schizo_read(afsr_reg); | 387 | afsr = upa_readq(afsr_reg); |
405 | } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); | 388 | } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); |
406 | 389 | ||
407 | /* Clear the primary/secondary error status bits. */ | 390 | /* Clear the primary/secondary error status bits. */ |
@@ -410,7 +393,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) | |||
410 | SCHIZO_UEAFSR_SPIO | SCHIZO_UEAFSR_SDMA); | 393 | SCHIZO_UEAFSR_SPIO | SCHIZO_UEAFSR_SDMA); |
411 | if (!error_bits) | 394 | if (!error_bits) |
412 | return IRQ_NONE; | 395 | return IRQ_NONE; |
413 | schizo_write(afsr_reg, error_bits); | 396 | upa_writeq(error_bits, afsr_reg); |
414 | 397 | ||
415 | /* Log the error. */ | 398 | /* Log the error. */ |
416 | printk("%s: Uncorrectable Error, primary error type[%s]\n", | 399 | printk("%s: Uncorrectable Error, primary error type[%s]\n", |
@@ -449,7 +432,7 @@ static irqreturn_t schizo_ue_intr(int irq, void *dev_id) | |||
449 | printk("]\n"); | 432 | printk("]\n"); |
450 | 433 | ||
451 | /* Interrogate IOMMU for error status. */ | 434 | /* Interrogate IOMMU for error status. */ |
452 | schizo_check_iommu_error(p, UE_ERR); | 435 | schizo_check_iommu_error(pbm, UE_ERR); |
453 | 436 | ||
454 | return IRQ_HANDLED; | 437 | return IRQ_HANDLED; |
455 | } | 438 | } |
@@ -481,7 +464,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) | |||
481 | int reported, limit; | 464 | int reported, limit; |
482 | 465 | ||
483 | /* Latch error status. */ | 466 | /* Latch error status. */ |
484 | afar = schizo_read(afar_reg); | 467 | afar = upa_readq(afar_reg); |
485 | 468 | ||
486 | /* If either of the error pending bits are set in the | 469 | /* If either of the error pending bits are set in the |
487 | * AFSR, the error status is being actively updated by | 470 | * AFSR, the error status is being actively updated by |
@@ -489,7 +472,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) | |||
489 | */ | 472 | */ |
490 | limit = 1000; | 473 | limit = 1000; |
491 | do { | 474 | do { |
492 | afsr = schizo_read(afsr_reg); | 475 | afsr = upa_readq(afsr_reg); |
493 | } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); | 476 | } while ((afsr & SCHIZO_UEAFSR_ERRPNDG) != 0 && --limit); |
494 | 477 | ||
495 | /* Clear primary/secondary error status bits. */ | 478 | /* Clear primary/secondary error status bits. */ |
@@ -498,7 +481,7 @@ static irqreturn_t schizo_ce_intr(int irq, void *dev_id) | |||
498 | SCHIZO_CEAFSR_SPIO | SCHIZO_CEAFSR_SDMA); | 481 | SCHIZO_CEAFSR_SPIO | SCHIZO_CEAFSR_SDMA); |
499 | if (!error_bits) | 482 | if (!error_bits) |
500 | return IRQ_NONE; | 483 | return IRQ_NONE; |
501 | schizo_write(afsr_reg, error_bits); | 484 | upa_writeq(error_bits, afsr_reg); |
502 | 485 | ||
503 | /* Log the error. */ | 486 | /* Log the error. */ |
504 | printk("%s: Correctable Error, primary error type[%s]\n", | 487 | printk("%s: Correctable Error, primary error type[%s]\n", |
@@ -600,7 +583,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) | |||
600 | u16 stat; | 583 | u16 stat; |
601 | 584 | ||
602 | csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; | 585 | csr_reg = pbm->pbm_regs + SCHIZO_PCI_CTRL; |
603 | csr = schizo_read(csr_reg); | 586 | csr = upa_readq(csr_reg); |
604 | csr_error_bits = | 587 | csr_error_bits = |
605 | csr & (SCHIZO_PCICTRL_BUS_UNUS | | 588 | csr & (SCHIZO_PCICTRL_BUS_UNUS | |
606 | SCHIZO_PCICTRL_TTO_ERR | | 589 | SCHIZO_PCICTRL_TTO_ERR | |
@@ -610,7 +593,7 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) | |||
610 | SCHIZO_PCICTRL_SERR); | 593 | SCHIZO_PCICTRL_SERR); |
611 | if (csr_error_bits) { | 594 | if (csr_error_bits) { |
612 | /* Clear the errors. */ | 595 | /* Clear the errors. */ |
613 | schizo_write(csr_reg, csr); | 596 | upa_writeq(csr, csr_reg); |
614 | 597 | ||
615 | /* Log 'em. */ | 598 | /* Log 'em. */ |
616 | if (csr_error_bits & SCHIZO_PCICTRL_BUS_UNUS) | 599 | if (csr_error_bits & SCHIZO_PCICTRL_BUS_UNUS) |
@@ -650,7 +633,6 @@ static irqreturn_t schizo_pcierr_intr_other(struct pci_pbm_info *pbm) | |||
650 | static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | 633 | static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) |
651 | { | 634 | { |
652 | struct pci_pbm_info *pbm = dev_id; | 635 | struct pci_pbm_info *pbm = dev_id; |
653 | struct pci_controller_info *p = pbm->parent; | ||
654 | unsigned long afsr_reg, afar_reg, base; | 636 | unsigned long afsr_reg, afar_reg, base; |
655 | unsigned long afsr, afar, error_bits; | 637 | unsigned long afsr, afar, error_bits; |
656 | int reported; | 638 | int reported; |
@@ -661,8 +643,8 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | |||
661 | afar_reg = base + SCHIZO_PCI_AFAR; | 643 | afar_reg = base + SCHIZO_PCI_AFAR; |
662 | 644 | ||
663 | /* Latch error status. */ | 645 | /* Latch error status. */ |
664 | afar = schizo_read(afar_reg); | 646 | afar = upa_readq(afar_reg); |
665 | afsr = schizo_read(afsr_reg); | 647 | afsr = upa_readq(afsr_reg); |
666 | 648 | ||
667 | /* Clear primary/secondary error status bits. */ | 649 | /* Clear primary/secondary error status bits. */ |
668 | error_bits = afsr & | 650 | error_bits = afsr & |
@@ -674,7 +656,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | |||
674 | SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS); | 656 | SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS); |
675 | if (!error_bits) | 657 | if (!error_bits) |
676 | return schizo_pcierr_intr_other(pbm); | 658 | return schizo_pcierr_intr_other(pbm); |
677 | schizo_write(afsr_reg, error_bits); | 659 | upa_writeq(error_bits, afsr_reg); |
678 | 660 | ||
679 | /* Log the error. */ | 661 | /* Log the error. */ |
680 | printk("%s: PCI Error, primary error type[%s]\n", | 662 | printk("%s: PCI Error, primary error type[%s]\n", |
@@ -744,7 +726,7 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | |||
744 | * a bug in the IOMMU support code or a PCI device driver. | 726 | * a bug in the IOMMU support code or a PCI device driver. |
745 | */ | 727 | */ |
746 | if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { | 728 | if (error_bits & (SCHIZO_PCIAFSR_PTA | SCHIZO_PCIAFSR_STA)) { |
747 | schizo_check_iommu_error(p, PCI_ERR); | 729 | schizo_check_iommu_error(pbm, PCI_ERR); |
748 | pci_scan_for_target_abort(pbm, pbm->pci_bus); | 730 | pci_scan_for_target_abort(pbm, pbm->pci_bus); |
749 | } | 731 | } |
750 | if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) | 732 | if (error_bits & (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_SMA)) |
@@ -805,12 +787,11 @@ static irqreturn_t schizo_pcierr_intr(int irq, void *dev_id) | |||
805 | static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) | 787 | static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) |
806 | { | 788 | { |
807 | struct pci_pbm_info *pbm = dev_id; | 789 | struct pci_pbm_info *pbm = dev_id; |
808 | struct pci_controller_info *p = pbm->parent; | ||
809 | u64 errlog; | 790 | u64 errlog; |
810 | 791 | ||
811 | errlog = schizo_read(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); | 792 | errlog = upa_readq(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); |
812 | schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRLOG, | 793 | upa_writeq(errlog & ~(SAFARI_ERRLOG_ERROUT), |
813 | errlog & ~(SAFARI_ERRLOG_ERROUT)); | 794 | pbm->controller_regs + SCHIZO_SAFARI_ERRLOG); |
814 | 795 | ||
815 | if (!(errlog & BUS_ERROR_UNMAP)) { | 796 | if (!(errlog & BUS_ERROR_UNMAP)) { |
816 | printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", | 797 | printk("%s: Unexpected Safari/JBUS error interrupt, errlog[%016lx]\n", |
@@ -821,7 +802,7 @@ static irqreturn_t schizo_safarierr_intr(int irq, void *dev_id) | |||
821 | 802 | ||
822 | printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", | 803 | printk("%s: Safari/JBUS interrupt, UNMAPPED error, interrogating IOMMUs.\n", |
823 | pbm->name); | 804 | pbm->name); |
824 | schizo_check_iommu_error(p, SAFARI_ERR); | 805 | schizo_check_iommu_error(pbm, SAFARI_ERR); |
825 | 806 | ||
826 | return IRQ_HANDLED; | 807 | return IRQ_HANDLED; |
827 | } | 808 | } |
@@ -863,7 +844,7 @@ static int pbm_routes_this_ino(struct pci_pbm_info *pbm, u32 ino) | |||
863 | */ | 844 | */ |
864 | static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) | 845 | static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) |
865 | { | 846 | { |
866 | struct of_device *op = of_find_device_by_node(pbm->prom_node); | 847 | struct of_device *op = of_find_device_by_node(pbm->op->node); |
867 | u64 tmp, err_mask, err_no_mask; | 848 | u64 tmp, err_mask, err_no_mask; |
868 | int err; | 849 | int err; |
869 | 850 | ||
@@ -910,10 +891,9 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) | |||
910 | } | 891 | } |
911 | 892 | ||
912 | /* Enable UE and CE interrupts for controller. */ | 893 | /* Enable UE and CE interrupts for controller. */ |
913 | schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, | 894 | upa_writeq((SCHIZO_ECCCTRL_EE | |
914 | (SCHIZO_ECCCTRL_EE | | 895 | SCHIZO_ECCCTRL_UE | |
915 | SCHIZO_ECCCTRL_UE | | 896 | SCHIZO_ECCCTRL_CE), pbm->controller_regs + SCHIZO_ECC_CTRL); |
916 | SCHIZO_ECCCTRL_CE)); | ||
917 | 897 | ||
918 | /* Enable PCI Error interrupts and clear error | 898 | /* Enable PCI Error interrupts and clear error |
919 | * bits. | 899 | * bits. |
@@ -926,10 +906,10 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) | |||
926 | 906 | ||
927 | err_no_mask = SCHIZO_PCICTRL_DTO_ERR; | 907 | err_no_mask = SCHIZO_PCICTRL_DTO_ERR; |
928 | 908 | ||
929 | tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); | 909 | tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); |
930 | tmp |= err_mask; | 910 | tmp |= err_mask; |
931 | tmp &= ~err_no_mask; | 911 | tmp &= ~err_no_mask; |
932 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); | 912 | upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); |
933 | 913 | ||
934 | err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | | 914 | err_mask = (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | |
935 | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | | 915 | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | |
@@ -938,7 +918,7 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) | |||
938 | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | | 918 | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | |
939 | SCHIZO_PCIAFSR_STTO); | 919 | SCHIZO_PCIAFSR_STTO); |
940 | 920 | ||
941 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, err_mask); | 921 | upa_writeq(err_mask, pbm->pbm_regs + SCHIZO_PCI_AFSR); |
942 | 922 | ||
943 | err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR | | 923 | err_mask = (BUS_ERROR_BADCMD | BUS_ERROR_SNOOP_GR | |
944 | BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD | | 924 | BUS_ERROR_SNOOP_PCI | BUS_ERROR_SNOOP_RD | |
@@ -950,16 +930,16 @@ static void tomatillo_register_error_handlers(struct pci_pbm_info *pbm) | |||
950 | BUS_ERROR_APERR | BUS_ERROR_UNMAP | | 930 | BUS_ERROR_APERR | BUS_ERROR_UNMAP | |
951 | BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT); | 931 | BUS_ERROR_BUSERR | BUS_ERROR_TIMEOUT); |
952 | 932 | ||
953 | schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, | 933 | upa_writeq((SCHIZO_SAFERRCTRL_EN | err_mask), |
954 | (SCHIZO_SAFERRCTRL_EN | err_mask)); | 934 | pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL); |
955 | 935 | ||
956 | schizo_write(pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL, | 936 | upa_writeq((SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP)), |
957 | (SCHIZO_SAFIRQCTRL_EN | (BUS_ERROR_UNMAP))); | 937 | pbm->controller_regs + SCHIZO_SAFARI_IRQCTRL); |
958 | } | 938 | } |
959 | 939 | ||
960 | static void schizo_register_error_handlers(struct pci_pbm_info *pbm) | 940 | static void schizo_register_error_handlers(struct pci_pbm_info *pbm) |
961 | { | 941 | { |
962 | struct of_device *op = of_find_device_by_node(pbm->prom_node); | 942 | struct of_device *op = of_find_device_by_node(pbm->op->node); |
963 | u64 tmp, err_mask, err_no_mask; | 943 | u64 tmp, err_mask, err_no_mask; |
964 | int err; | 944 | int err; |
965 | 945 | ||
@@ -1006,10 +986,9 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) | |||
1006 | } | 986 | } |
1007 | 987 | ||
1008 | /* Enable UE and CE interrupts for controller. */ | 988 | /* Enable UE and CE interrupts for controller. */ |
1009 | schizo_write(pbm->controller_regs + SCHIZO_ECC_CTRL, | 989 | upa_writeq((SCHIZO_ECCCTRL_EE | |
1010 | (SCHIZO_ECCCTRL_EE | | 990 | SCHIZO_ECCCTRL_UE | |
1011 | SCHIZO_ECCCTRL_UE | | 991 | SCHIZO_ECCCTRL_CE), pbm->controller_regs + SCHIZO_ECC_CTRL); |
1012 | SCHIZO_ECCCTRL_CE)); | ||
1013 | 992 | ||
1014 | err_mask = (SCHIZO_PCICTRL_BUS_UNUS | | 993 | err_mask = (SCHIZO_PCICTRL_BUS_UNUS | |
1015 | SCHIZO_PCICTRL_ESLCK | | 994 | SCHIZO_PCICTRL_ESLCK | |
@@ -1025,18 +1004,18 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) | |||
1025 | /* Enable PCI Error interrupts and clear error | 1004 | /* Enable PCI Error interrupts and clear error |
1026 | * bits for each PBM. | 1005 | * bits for each PBM. |
1027 | */ | 1006 | */ |
1028 | tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); | 1007 | tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); |
1029 | tmp |= err_mask; | 1008 | tmp |= err_mask; |
1030 | tmp &= ~err_no_mask; | 1009 | tmp &= ~err_no_mask; |
1031 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); | 1010 | upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); |
1032 | 1011 | ||
1033 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_AFSR, | 1012 | upa_writeq((SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | |
1034 | (SCHIZO_PCIAFSR_PMA | SCHIZO_PCIAFSR_PTA | | 1013 | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | |
1035 | SCHIZO_PCIAFSR_PRTRY | SCHIZO_PCIAFSR_PPERR | | 1014 | SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | |
1036 | SCHIZO_PCIAFSR_PTTO | SCHIZO_PCIAFSR_PUNUS | | 1015 | SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | |
1037 | SCHIZO_PCIAFSR_SMA | SCHIZO_PCIAFSR_STA | | 1016 | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | |
1038 | SCHIZO_PCIAFSR_SRTRY | SCHIZO_PCIAFSR_SPERR | | 1017 | SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS), |
1039 | SCHIZO_PCIAFSR_STTO | SCHIZO_PCIAFSR_SUNUS)); | 1018 | pbm->pbm_regs + SCHIZO_PCI_AFSR); |
1040 | 1019 | ||
1041 | /* Make all Safari error conditions fatal except unmapped | 1020 | /* Make all Safari error conditions fatal except unmapped |
1042 | * errors which we make generate interrupts. | 1021 | * errors which we make generate interrupts. |
@@ -1063,8 +1042,8 @@ static void schizo_register_error_handlers(struct pci_pbm_info *pbm) | |||
1063 | BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB); | 1042 | BUS_ERROR_CPU0PS | BUS_ERROR_CPU0PB); |
1064 | #endif | 1043 | #endif |
1065 | 1044 | ||
1066 | schizo_write(pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL, | 1045 | upa_writeq((SCHIZO_SAFERRCTRL_EN | err_mask), |
1067 | (SCHIZO_SAFERRCTRL_EN | err_mask)); | 1046 | pbm->controller_regs + SCHIZO_SAFARI_ERRCTRL); |
1068 | } | 1047 | } |
1069 | 1048 | ||
1070 | static void pbm_config_busmastering(struct pci_pbm_info *pbm) | 1049 | static void pbm_config_busmastering(struct pci_pbm_info *pbm) |
@@ -1084,14 +1063,15 @@ static void pbm_config_busmastering(struct pci_pbm_info *pbm) | |||
1084 | pci_config_write8(addr, 64); | 1063 | pci_config_write8(addr, 64); |
1085 | } | 1064 | } |
1086 | 1065 | ||
1087 | static void __init schizo_scan_bus(struct pci_pbm_info *pbm) | 1066 | static void __devinit schizo_scan_bus(struct pci_pbm_info *pbm, |
1067 | struct device *parent) | ||
1088 | { | 1068 | { |
1089 | pbm_config_busmastering(pbm); | 1069 | pbm_config_busmastering(pbm); |
1090 | pbm->is_66mhz_capable = | 1070 | pbm->is_66mhz_capable = |
1091 | (of_find_property(pbm->prom_node, "66mhz-capable", NULL) | 1071 | (of_find_property(pbm->op->node, "66mhz-capable", NULL) |
1092 | != NULL); | 1072 | != NULL); |
1093 | 1073 | ||
1094 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 1074 | pbm->pci_bus = pci_scan_one_pbm(pbm, parent); |
1095 | 1075 | ||
1096 | if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) | 1076 | if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) |
1097 | tomatillo_register_error_handlers(pbm); | 1077 | tomatillo_register_error_handlers(pbm); |
@@ -1133,12 +1113,12 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) | |||
1133 | * streaming buffer and leave the rerun-disable | 1113 | * streaming buffer and leave the rerun-disable |
1134 | * setting however OBP set it. | 1114 | * setting however OBP set it. |
1135 | */ | 1115 | */ |
1136 | control = schizo_read(pbm->stc.strbuf_control); | 1116 | control = upa_readq(pbm->stc.strbuf_control); |
1137 | control &= ~(SCHIZO_STRBUF_CTRL_LPTR | | 1117 | control &= ~(SCHIZO_STRBUF_CTRL_LPTR | |
1138 | SCHIZO_STRBUF_CTRL_LENAB | | 1118 | SCHIZO_STRBUF_CTRL_LENAB | |
1139 | SCHIZO_STRBUF_CTRL_DENAB); | 1119 | SCHIZO_STRBUF_CTRL_DENAB); |
1140 | control |= SCHIZO_STRBUF_CTRL_ENAB; | 1120 | control |= SCHIZO_STRBUF_CTRL_ENAB; |
1141 | schizo_write(pbm->stc.strbuf_control, control); | 1121 | upa_writeq(control, pbm->stc.strbuf_control); |
1142 | 1122 | ||
1143 | pbm->stc.strbuf_enabled = 1; | 1123 | pbm->stc.strbuf_enabled = 1; |
1144 | } | 1124 | } |
@@ -1150,24 +1130,17 @@ static void schizo_pbm_strbuf_init(struct pci_pbm_info *pbm) | |||
1150 | 1130 | ||
1151 | static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | 1131 | static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) |
1152 | { | 1132 | { |
1153 | struct iommu *iommu = pbm->iommu; | 1133 | static const u32 vdma_default[] = { 0xc0000000, 0x40000000 }; |
1154 | unsigned long i, tagbase, database; | 1134 | unsigned long i, tagbase, database; |
1155 | struct property *prop; | 1135 | struct iommu *iommu = pbm->iommu; |
1156 | u32 vdma[2], dma_mask; | ||
1157 | int tsbsize, err; | 1136 | int tsbsize, err; |
1137 | const u32 *vdma; | ||
1138 | u32 dma_mask; | ||
1158 | u64 control; | 1139 | u64 control; |
1159 | 1140 | ||
1160 | prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); | 1141 | vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); |
1161 | if (prop) { | 1142 | if (!vdma) |
1162 | u32 *val = prop->value; | 1143 | vdma = vdma_default; |
1163 | |||
1164 | vdma[0] = val[0]; | ||
1165 | vdma[1] = val[1]; | ||
1166 | } else { | ||
1167 | /* No property, use default values. */ | ||
1168 | vdma[0] = 0xc0000000; | ||
1169 | vdma[1] = 0x40000000; | ||
1170 | } | ||
1171 | 1144 | ||
1172 | dma_mask = vdma[0]; | 1145 | dma_mask = vdma[0]; |
1173 | switch (vdma[1]) { | 1146 | switch (vdma[1]) { |
@@ -1187,9 +1160,9 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
1187 | break; | 1160 | break; |
1188 | 1161 | ||
1189 | default: | 1162 | default: |
1190 | prom_printf("SCHIZO: strange virtual-dma size.\n"); | 1163 | printk(KERN_ERR PFX "Strange virtual-dma size.\n"); |
1191 | prom_halt(); | 1164 | return -EINVAL; |
1192 | }; | 1165 | } |
1193 | 1166 | ||
1194 | /* Register addresses, SCHIZO has iommu ctx flushing. */ | 1167 | /* Register addresses, SCHIZO has iommu ctx flushing. */ |
1195 | iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; | 1168 | iommu->iommu_control = pbm->pbm_regs + SCHIZO_IOMMU_CONTROL; |
@@ -1206,15 +1179,15 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
1206 | /* | 1179 | /* |
1207 | * Invalidate TLB Entries. | 1180 | * Invalidate TLB Entries. |
1208 | */ | 1181 | */ |
1209 | control = schizo_read(iommu->iommu_control); | 1182 | control = upa_readq(iommu->iommu_control); |
1210 | control |= SCHIZO_IOMMU_CTRL_DENAB; | 1183 | control |= SCHIZO_IOMMU_CTRL_DENAB; |
1211 | schizo_write(iommu->iommu_control, control); | 1184 | upa_writeq(control, iommu->iommu_control); |
1212 | 1185 | ||
1213 | tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA; | 1186 | tagbase = SCHIZO_IOMMU_TAG, database = SCHIZO_IOMMU_DATA; |
1214 | 1187 | ||
1215 | for(i = 0; i < 16; i++) { | 1188 | for (i = 0; i < 16; i++) { |
1216 | schizo_write(pbm->pbm_regs + tagbase + (i * 8UL), 0); | 1189 | upa_writeq(0, pbm->pbm_regs + tagbase + (i * 8UL)); |
1217 | schizo_write(pbm->pbm_regs + database + (i * 8UL), 0); | 1190 | upa_writeq(0, pbm->pbm_regs + database + (i * 8UL)); |
1218 | } | 1191 | } |
1219 | 1192 | ||
1220 | /* Leave diag mode enabled for full-flushing done | 1193 | /* Leave diag mode enabled for full-flushing done |
@@ -1222,12 +1195,14 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
1222 | */ | 1195 | */ |
1223 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, | 1196 | err = iommu_table_init(iommu, tsbsize * 8 * 1024, vdma[0], dma_mask, |
1224 | pbm->numa_node); | 1197 | pbm->numa_node); |
1225 | if (err) | 1198 | if (err) { |
1199 | printk(KERN_ERR PFX "iommu_table_init() fails with %d\n", err); | ||
1226 | return err; | 1200 | return err; |
1201 | } | ||
1227 | 1202 | ||
1228 | schizo_write(iommu->iommu_tsbbase, __pa(iommu->page_table)); | 1203 | upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase); |
1229 | 1204 | ||
1230 | control = schizo_read(iommu->iommu_control); | 1205 | control = upa_readq(iommu->iommu_control); |
1231 | control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); | 1206 | control &= ~(SCHIZO_IOMMU_CTRL_TSBSZ | SCHIZO_IOMMU_CTRL_TBWSZ); |
1232 | switch (tsbsize) { | 1207 | switch (tsbsize) { |
1233 | case 64: | 1208 | case 64: |
@@ -1236,10 +1211,10 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
1236 | case 128: | 1211 | case 128: |
1237 | control |= SCHIZO_IOMMU_TSBSZ_128K; | 1212 | control |= SCHIZO_IOMMU_TSBSZ_128K; |
1238 | break; | 1213 | break; |
1239 | }; | 1214 | } |
1240 | 1215 | ||
1241 | control |= SCHIZO_IOMMU_CTRL_ENAB; | 1216 | control |= SCHIZO_IOMMU_CTRL_ENAB; |
1242 | schizo_write(iommu->iommu_control, control); | 1217 | upa_writeq(control, iommu->iommu_control); |
1243 | 1218 | ||
1244 | return 0; | 1219 | return 0; |
1245 | } | 1220 | } |
@@ -1280,12 +1255,11 @@ static int schizo_pbm_iommu_init(struct pci_pbm_info *pbm) | |||
1280 | 1255 | ||
1281 | static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) | 1256 | static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) |
1282 | { | 1257 | { |
1283 | struct property *prop; | ||
1284 | u64 tmp; | 1258 | u64 tmp; |
1285 | 1259 | ||
1286 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY, 5); | 1260 | upa_writeq(5, pbm->pbm_regs + SCHIZO_PCI_IRQ_RETRY); |
1287 | 1261 | ||
1288 | tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_CTRL); | 1262 | tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_CTRL); |
1289 | 1263 | ||
1290 | /* Enable arbiter for all PCI slots. */ | 1264 | /* Enable arbiter for all PCI slots. */ |
1291 | tmp |= 0xff; | 1265 | tmp |= 0xff; |
@@ -1294,8 +1268,7 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) | |||
1294 | pbm->chip_version >= 0x2) | 1268 | pbm->chip_version >= 0x2) |
1295 | tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; | 1269 | tmp |= 0x3UL << SCHIZO_PCICTRL_PTO_SHIFT; |
1296 | 1270 | ||
1297 | prop = of_find_property(pbm->prom_node, "no-bus-parking", NULL); | 1271 | if (!of_find_property(pbm->op->node, "no-bus-parking", NULL)) |
1298 | if (!prop) | ||
1299 | tmp |= SCHIZO_PCICTRL_PARK; | 1272 | tmp |= SCHIZO_PCICTRL_PARK; |
1300 | else | 1273 | else |
1301 | tmp &= ~SCHIZO_PCICTRL_PARK; | 1274 | tmp &= ~SCHIZO_PCICTRL_PARK; |
@@ -1311,13 +1284,13 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) | |||
1311 | SCHIZO_PCICTRL_RDO_PREF | | 1284 | SCHIZO_PCICTRL_RDO_PREF | |
1312 | SCHIZO_PCICTRL_RDL_PREF); | 1285 | SCHIZO_PCICTRL_RDL_PREF); |
1313 | 1286 | ||
1314 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_CTRL, tmp); | 1287 | upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_CTRL); |
1315 | 1288 | ||
1316 | tmp = schizo_read(pbm->pbm_regs + SCHIZO_PCI_DIAG); | 1289 | tmp = upa_readq(pbm->pbm_regs + SCHIZO_PCI_DIAG); |
1317 | tmp &= ~(SCHIZO_PCIDIAG_D_RTRYARB | | 1290 | tmp &= ~(SCHIZO_PCIDIAG_D_RTRYARB | |
1318 | SCHIZO_PCIDIAG_D_RETRY | | 1291 | SCHIZO_PCIDIAG_D_RETRY | |
1319 | SCHIZO_PCIDIAG_D_INTSYNC); | 1292 | SCHIZO_PCIDIAG_D_INTSYNC); |
1320 | schizo_write(pbm->pbm_regs + SCHIZO_PCI_DIAG, tmp); | 1293 | upa_writeq(tmp, pbm->pbm_regs + SCHIZO_PCI_DIAG); |
1321 | 1294 | ||
1322 | if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { | 1295 | if (pbm->chip_type == PBM_CHIP_TYPE_TOMATILLO) { |
1323 | /* Clear prefetch lengths to workaround a bug in | 1296 | /* Clear prefetch lengths to workaround a bug in |
@@ -1329,17 +1302,16 @@ static void schizo_pbm_hw_init(struct pci_pbm_info *pbm) | |||
1329 | TOMATILLO_IOC_RDONE_CPENAB | | 1302 | TOMATILLO_IOC_RDONE_CPENAB | |
1330 | TOMATILLO_IOC_RDLINE_CPENAB); | 1303 | TOMATILLO_IOC_RDLINE_CPENAB); |
1331 | 1304 | ||
1332 | schizo_write(pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR, | 1305 | upa_writeq(tmp, pbm->pbm_regs + TOMATILLO_PCI_IOC_CSR); |
1333 | tmp); | ||
1334 | } | 1306 | } |
1335 | } | 1307 | } |
1336 | 1308 | ||
1337 | static int __init schizo_pbm_init(struct pci_controller_info *p, | 1309 | static int __devinit schizo_pbm_init(struct pci_pbm_info *pbm, |
1338 | struct device_node *dp, u32 portid, | 1310 | struct of_device *op, u32 portid, |
1339 | int chip_type) | 1311 | int chip_type) |
1340 | { | 1312 | { |
1341 | const struct linux_prom64_registers *regs; | 1313 | const struct linux_prom64_registers *regs; |
1342 | struct pci_pbm_info *pbm; | 1314 | struct device_node *dp = op->node; |
1343 | const char *chipset_name; | 1315 | const char *chipset_name; |
1344 | int is_pbm_a, err; | 1316 | int is_pbm_a, err; |
1345 | 1317 | ||
@@ -1372,25 +1344,19 @@ static int __init schizo_pbm_init(struct pci_controller_info *p, | |||
1372 | regs = of_get_property(dp, "reg", NULL); | 1344 | regs = of_get_property(dp, "reg", NULL); |
1373 | 1345 | ||
1374 | is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); | 1346 | is_pbm_a = ((regs[0].phys_addr & 0x00700000) == 0x00600000); |
1375 | if (is_pbm_a) | ||
1376 | pbm = &p->pbm_A; | ||
1377 | else | ||
1378 | pbm = &p->pbm_B; | ||
1379 | 1347 | ||
1380 | pbm->next = pci_pbm_root; | 1348 | pbm->next = pci_pbm_root; |
1381 | pci_pbm_root = pbm; | 1349 | pci_pbm_root = pbm; |
1382 | 1350 | ||
1383 | pbm->numa_node = -1; | 1351 | pbm->numa_node = -1; |
1384 | 1352 | ||
1385 | pbm->scan_bus = schizo_scan_bus; | ||
1386 | pbm->pci_ops = &sun4u_pci_ops; | 1353 | pbm->pci_ops = &sun4u_pci_ops; |
1387 | pbm->config_space_reg_bits = 8; | 1354 | pbm->config_space_reg_bits = 8; |
1388 | 1355 | ||
1389 | pbm->index = pci_num_pbms++; | 1356 | pbm->index = pci_num_pbms++; |
1390 | 1357 | ||
1391 | pbm->portid = portid; | 1358 | pbm->portid = portid; |
1392 | pbm->parent = p; | 1359 | pbm->op = op; |
1393 | pbm->prom_node = dp; | ||
1394 | 1360 | ||
1395 | pbm->chip_type = chip_type; | 1361 | pbm->chip_type = chip_type; |
1396 | pbm->chip_version = of_getintprop_default(dp, "version#", 0); | 1362 | pbm->chip_version = of_getintprop_default(dp, "version#", 0); |
@@ -1420,6 +1386,8 @@ static int __init schizo_pbm_init(struct pci_controller_info *p, | |||
1420 | 1386 | ||
1421 | schizo_pbm_strbuf_init(pbm); | 1387 | schizo_pbm_strbuf_init(pbm); |
1422 | 1388 | ||
1389 | schizo_scan_bus(pbm, &op->dev); | ||
1390 | |||
1423 | return 0; | 1391 | return 0; |
1424 | } | 1392 | } |
1425 | 1393 | ||
@@ -1433,62 +1401,104 @@ static inline int portid_compare(u32 x, u32 y, int chip_type) | |||
1433 | return (x == y); | 1401 | return (x == y); |
1434 | } | 1402 | } |
1435 | 1403 | ||
1436 | static void __init __schizo_init(struct device_node *dp, char *model_name, | 1404 | static struct pci_pbm_info * __devinit schizo_find_sibling(u32 portid, |
1437 | int chip_type) | 1405 | int chip_type) |
1438 | { | 1406 | { |
1439 | struct pci_controller_info *p; | 1407 | struct pci_pbm_info *pbm; |
1408 | |||
1409 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | ||
1410 | if (portid_compare(pbm->portid, portid, chip_type)) | ||
1411 | return pbm; | ||
1412 | } | ||
1413 | return NULL; | ||
1414 | } | ||
1415 | |||
1416 | static int __devinit __schizo_init(struct of_device *op, unsigned long chip_type) | ||
1417 | { | ||
1418 | struct device_node *dp = op->node; | ||
1440 | struct pci_pbm_info *pbm; | 1419 | struct pci_pbm_info *pbm; |
1441 | struct iommu *iommu; | 1420 | struct iommu *iommu; |
1442 | u32 portid; | 1421 | u32 portid; |
1422 | int err; | ||
1443 | 1423 | ||
1444 | portid = of_getintprop_default(dp, "portid", 0xff); | 1424 | portid = of_getintprop_default(dp, "portid", 0xff); |
1445 | 1425 | ||
1446 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 1426 | err = -ENOMEM; |
1447 | if (portid_compare(pbm->portid, portid, chip_type)) { | 1427 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
1448 | if (schizo_pbm_init(pbm->parent, dp, | 1428 | if (!pbm) { |
1449 | portid, chip_type)) | 1429 | printk(KERN_ERR PFX "Cannot allocate pci_pbm_info.\n"); |
1450 | goto fatal_memory_error; | 1430 | goto out_err; |
1451 | return; | 1431 | } |
1452 | } | 1432 | |
1433 | pbm->sibling = schizo_find_sibling(portid, chip_type); | ||
1434 | |||
1435 | iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); | ||
1436 | if (!iommu) { | ||
1437 | printk(KERN_ERR PFX "Cannot allocate PBM A iommu.\n"); | ||
1438 | goto out_free_pbm; | ||
1453 | } | 1439 | } |
1454 | 1440 | ||
1455 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); | 1441 | pbm->iommu = iommu; |
1456 | if (!p) | ||
1457 | goto fatal_memory_error; | ||
1458 | 1442 | ||
1459 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 1443 | if (schizo_pbm_init(pbm, op, portid, chip_type)) |
1460 | if (!iommu) | 1444 | goto out_free_iommu; |
1461 | goto fatal_memory_error; | ||
1462 | 1445 | ||
1463 | p->pbm_A.iommu = iommu; | 1446 | if (pbm->sibling) |
1447 | pbm->sibling->sibling = pbm; | ||
1464 | 1448 | ||
1465 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 1449 | dev_set_drvdata(&op->dev, pbm); |
1466 | if (!iommu) | ||
1467 | goto fatal_memory_error; | ||
1468 | 1450 | ||
1469 | p->pbm_B.iommu = iommu; | 1451 | return 0; |
1470 | 1452 | ||
1471 | if (schizo_pbm_init(p, dp, portid, chip_type)) | 1453 | out_free_iommu: |
1472 | goto fatal_memory_error; | 1454 | kfree(pbm->iommu); |
1473 | 1455 | ||
1474 | return; | 1456 | out_free_pbm: |
1457 | kfree(pbm); | ||
1475 | 1458 | ||
1476 | fatal_memory_error: | 1459 | out_err: |
1477 | prom_printf("SCHIZO: Fatal memory allocation error.\n"); | 1460 | return err; |
1478 | prom_halt(); | ||
1479 | } | 1461 | } |
1480 | 1462 | ||
1481 | void __init schizo_init(struct device_node *dp, char *model_name) | 1463 | static int __devinit schizo_probe(struct of_device *op, |
1464 | const struct of_device_id *match) | ||
1482 | { | 1465 | { |
1483 | __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO); | 1466 | return __schizo_init(op, (unsigned long) match->data); |
1484 | } | 1467 | } |
1485 | 1468 | ||
1486 | void __init schizo_plus_init(struct device_node *dp, char *model_name) | 1469 | /* The ordering of this table is very important. Some Tomatillo |
1487 | { | 1470 | * nodes announce that they are compatible with both pci108e,a801 |
1488 | __schizo_init(dp, model_name, PBM_CHIP_TYPE_SCHIZO_PLUS); | 1471 | * and pci108e,8001. So list the chips in reverse chronological |
1489 | } | 1472 | * order. |
1473 | */ | ||
1474 | static struct of_device_id __initdata schizo_match[] = { | ||
1475 | { | ||
1476 | .name = "pci", | ||
1477 | .compatible = "pci108e,a801", | ||
1478 | .data = (void *) PBM_CHIP_TYPE_TOMATILLO, | ||
1479 | }, | ||
1480 | { | ||
1481 | .name = "pci", | ||
1482 | .compatible = "pci108e,8002", | ||
1483 | .data = (void *) PBM_CHIP_TYPE_SCHIZO_PLUS, | ||
1484 | }, | ||
1485 | { | ||
1486 | .name = "pci", | ||
1487 | .compatible = "pci108e,8001", | ||
1488 | .data = (void *) PBM_CHIP_TYPE_SCHIZO, | ||
1489 | }, | ||
1490 | {}, | ||
1491 | }; | ||
1490 | 1492 | ||
1491 | void __init tomatillo_init(struct device_node *dp, char *model_name) | 1493 | static struct of_platform_driver schizo_driver = { |
1494 | .name = DRIVER_NAME, | ||
1495 | .match_table = schizo_match, | ||
1496 | .probe = schizo_probe, | ||
1497 | }; | ||
1498 | |||
1499 | static int __init schizo_init(void) | ||
1492 | { | 1500 | { |
1493 | __schizo_init(dp, model_name, PBM_CHIP_TYPE_TOMATILLO); | 1501 | return of_register_driver(&schizo_driver, &of_bus_type); |
1494 | } | 1502 | } |
1503 | |||
1504 | subsys_initcall(schizo_init); | ||
diff --git a/arch/sparc64/kernel/pci_sun4v.c b/arch/sparc64/kernel/pci_sun4v.c index a104c80d319d..e86c73ec167b 100644 --- a/arch/sparc64/kernel/pci_sun4v.c +++ b/arch/sparc64/kernel/pci_sun4v.c | |||
@@ -13,12 +13,10 @@ | |||
13 | #include <linux/irq.h> | 13 | #include <linux/irq.h> |
14 | #include <linux/msi.h> | 14 | #include <linux/msi.h> |
15 | #include <linux/log2.h> | 15 | #include <linux/log2.h> |
16 | #include <linux/of_device.h> | ||
16 | 17 | ||
17 | #include <asm/iommu.h> | 18 | #include <asm/iommu.h> |
18 | #include <asm/irq.h> | 19 | #include <asm/irq.h> |
19 | #include <asm/upa.h> | ||
20 | #include <asm/pstate.h> | ||
21 | #include <asm/oplib.h> | ||
22 | #include <asm/hypervisor.h> | 20 | #include <asm/hypervisor.h> |
23 | #include <asm/prom.h> | 21 | #include <asm/prom.h> |
24 | 22 | ||
@@ -27,6 +25,9 @@ | |||
27 | 25 | ||
28 | #include "pci_sun4v.h" | 26 | #include "pci_sun4v.h" |
29 | 27 | ||
28 | #define DRIVER_NAME "pci_sun4v" | ||
29 | #define PFX DRIVER_NAME ": " | ||
30 | |||
30 | static unsigned long vpci_major = 1; | 31 | static unsigned long vpci_major = 1; |
31 | static unsigned long vpci_minor = 1; | 32 | static unsigned long vpci_minor = 1; |
32 | 33 | ||
@@ -41,6 +42,7 @@ struct iommu_batch { | |||
41 | }; | 42 | }; |
42 | 43 | ||
43 | static DEFINE_PER_CPU(struct iommu_batch, iommu_batch); | 44 | static DEFINE_PER_CPU(struct iommu_batch, iommu_batch); |
45 | static int iommu_batch_initialized; | ||
44 | 46 | ||
45 | /* Interrupts must be disabled. */ | 47 | /* Interrupts must be disabled. */ |
46 | static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry) | 48 | static inline void iommu_batch_start(struct device *dev, unsigned long prot, unsigned long entry) |
@@ -542,15 +544,16 @@ static const struct dma_ops sun4v_dma_ops = { | |||
542 | .sync_sg_for_cpu = dma_4v_sync_sg_for_cpu, | 544 | .sync_sg_for_cpu = dma_4v_sync_sg_for_cpu, |
543 | }; | 545 | }; |
544 | 546 | ||
545 | static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm) | 547 | static void __init pci_sun4v_scan_bus(struct pci_pbm_info *pbm, |
548 | struct device *parent) | ||
546 | { | 549 | { |
547 | struct property *prop; | 550 | struct property *prop; |
548 | struct device_node *dp; | 551 | struct device_node *dp; |
549 | 552 | ||
550 | dp = pbm->prom_node; | 553 | dp = pbm->op->node; |
551 | prop = of_find_property(dp, "66mhz-capable", NULL); | 554 | prop = of_find_property(dp, "66mhz-capable", NULL); |
552 | pbm->is_66mhz_capable = (prop != NULL); | 555 | pbm->is_66mhz_capable = (prop != NULL); |
553 | pbm->pci_bus = pci_scan_one_pbm(pbm); | 556 | pbm->pci_bus = pci_scan_one_pbm(pbm, parent); |
554 | 557 | ||
555 | /* XXX register error interrupt handlers XXX */ | 558 | /* XXX register error interrupt handlers XXX */ |
556 | } | 559 | } |
@@ -583,29 +586,22 @@ static unsigned long __init probe_existing_entries(struct pci_pbm_info *pbm, | |||
583 | return cnt; | 586 | return cnt; |
584 | } | 587 | } |
585 | 588 | ||
586 | static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | 589 | static int __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) |
587 | { | 590 | { |
591 | static const u32 vdma_default[] = { 0x80000000, 0x80000000 }; | ||
588 | struct iommu *iommu = pbm->iommu; | 592 | struct iommu *iommu = pbm->iommu; |
589 | struct property *prop; | ||
590 | unsigned long num_tsb_entries, sz, tsbsize; | 593 | unsigned long num_tsb_entries, sz, tsbsize; |
591 | u32 vdma[2], dma_mask, dma_offset; | 594 | u32 dma_mask, dma_offset; |
592 | 595 | const u32 *vdma; | |
593 | prop = of_find_property(pbm->prom_node, "virtual-dma", NULL); | 596 | |
594 | if (prop) { | 597 | vdma = of_get_property(pbm->op->node, "virtual-dma", NULL); |
595 | u32 *val = prop->value; | 598 | if (!vdma) |
596 | 599 | vdma = vdma_default; | |
597 | vdma[0] = val[0]; | ||
598 | vdma[1] = val[1]; | ||
599 | } else { | ||
600 | /* No property, use default values. */ | ||
601 | vdma[0] = 0x80000000; | ||
602 | vdma[1] = 0x80000000; | ||
603 | } | ||
604 | 600 | ||
605 | if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) { | 601 | if ((vdma[0] | vdma[1]) & ~IO_PAGE_MASK) { |
606 | prom_printf("PCI-SUN4V: strange virtual-dma[%08x:%08x].\n", | 602 | printk(KERN_ERR PFX "Strange virtual-dma[%08x:%08x].\n", |
607 | vdma[0], vdma[1]); | 603 | vdma[0], vdma[1]); |
608 | prom_halt(); | 604 | return -EINVAL; |
609 | }; | 605 | }; |
610 | 606 | ||
611 | dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); | 607 | dma_mask = (roundup_pow_of_two(vdma[1]) - 1UL); |
@@ -625,8 +621,8 @@ static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
625 | sz = (sz + 7UL) & ~7UL; | 621 | sz = (sz + 7UL) & ~7UL; |
626 | iommu->arena.map = kzalloc(sz, GFP_KERNEL); | 622 | iommu->arena.map = kzalloc(sz, GFP_KERNEL); |
627 | if (!iommu->arena.map) { | 623 | if (!iommu->arena.map) { |
628 | prom_printf("PCI_IOMMU: Error, kmalloc(arena.map) failed.\n"); | 624 | printk(KERN_ERR PFX "Error, kmalloc(arena.map) failed.\n"); |
629 | prom_halt(); | 625 | return -ENOMEM; |
630 | } | 626 | } |
631 | iommu->arena.limit = num_tsb_entries; | 627 | iommu->arena.limit = num_tsb_entries; |
632 | 628 | ||
@@ -634,6 +630,8 @@ static void __init pci_sun4v_iommu_init(struct pci_pbm_info *pbm) | |||
634 | if (sz) | 630 | if (sz) |
635 | printk("%s: Imported %lu TSB entries from OBP\n", | 631 | printk("%s: Imported %lu TSB entries from OBP\n", |
636 | pbm->name, sz); | 632 | pbm->name, sz); |
633 | |||
634 | return 0; | ||
637 | } | 635 | } |
638 | 636 | ||
639 | #ifdef CONFIG_PCI_MSI | 637 | #ifdef CONFIG_PCI_MSI |
@@ -890,29 +888,20 @@ static void pci_sun4v_msi_init(struct pci_pbm_info *pbm) | |||
890 | } | 888 | } |
891 | #endif /* !(CONFIG_PCI_MSI) */ | 889 | #endif /* !(CONFIG_PCI_MSI) */ |
892 | 890 | ||
893 | static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, | 891 | static int __init pci_sun4v_pbm_init(struct pci_pbm_info *pbm, |
894 | struct device_node *dp, u32 devhandle) | 892 | struct of_device *op, u32 devhandle) |
895 | { | 893 | { |
896 | struct pci_pbm_info *pbm; | 894 | struct device_node *dp = op->node; |
897 | 895 | int err; | |
898 | if (devhandle & 0x40) | ||
899 | pbm = &p->pbm_B; | ||
900 | else | ||
901 | pbm = &p->pbm_A; | ||
902 | |||
903 | pbm->next = pci_pbm_root; | ||
904 | pci_pbm_root = pbm; | ||
905 | 896 | ||
906 | pbm->numa_node = of_node_to_nid(dp); | 897 | pbm->numa_node = of_node_to_nid(dp); |
907 | 898 | ||
908 | pbm->scan_bus = pci_sun4v_scan_bus; | ||
909 | pbm->pci_ops = &sun4v_pci_ops; | 899 | pbm->pci_ops = &sun4v_pci_ops; |
910 | pbm->config_space_reg_bits = 12; | 900 | pbm->config_space_reg_bits = 12; |
911 | 901 | ||
912 | pbm->index = pci_num_pbms++; | 902 | pbm->index = pci_num_pbms++; |
913 | 903 | ||
914 | pbm->parent = p; | 904 | pbm->op = op; |
915 | pbm->prom_node = dp; | ||
916 | 905 | ||
917 | pbm->devhandle = devhandle; | 906 | pbm->devhandle = devhandle; |
918 | 907 | ||
@@ -924,82 +913,120 @@ static void __init pci_sun4v_pbm_init(struct pci_controller_info *p, | |||
924 | pci_determine_mem_io_space(pbm); | 913 | pci_determine_mem_io_space(pbm); |
925 | 914 | ||
926 | pci_get_pbm_props(pbm); | 915 | pci_get_pbm_props(pbm); |
927 | pci_sun4v_iommu_init(pbm); | 916 | |
917 | err = pci_sun4v_iommu_init(pbm); | ||
918 | if (err) | ||
919 | return err; | ||
920 | |||
928 | pci_sun4v_msi_init(pbm); | 921 | pci_sun4v_msi_init(pbm); |
922 | |||
923 | pci_sun4v_scan_bus(pbm, &op->dev); | ||
924 | |||
925 | pbm->next = pci_pbm_root; | ||
926 | pci_pbm_root = pbm; | ||
927 | |||
928 | return 0; | ||
929 | } | 929 | } |
930 | 930 | ||
931 | void __init sun4v_pci_init(struct device_node *dp, char *model_name) | 931 | static int __devinit pci_sun4v_probe(struct of_device *op, |
932 | const struct of_device_id *match) | ||
932 | { | 933 | { |
934 | const struct linux_prom64_registers *regs; | ||
933 | static int hvapi_negotiated = 0; | 935 | static int hvapi_negotiated = 0; |
934 | struct pci_controller_info *p; | ||
935 | struct pci_pbm_info *pbm; | 936 | struct pci_pbm_info *pbm; |
937 | struct device_node *dp; | ||
936 | struct iommu *iommu; | 938 | struct iommu *iommu; |
937 | struct property *prop; | ||
938 | struct linux_prom64_registers *regs; | ||
939 | u32 devhandle; | 939 | u32 devhandle; |
940 | int i; | 940 | int i, err; |
941 | |||
942 | dp = op->node; | ||
941 | 943 | ||
942 | if (!hvapi_negotiated++) { | 944 | if (!hvapi_negotiated++) { |
943 | int err = sun4v_hvapi_register(HV_GRP_PCI, | 945 | err = sun4v_hvapi_register(HV_GRP_PCI, |
944 | vpci_major, | 946 | vpci_major, |
945 | &vpci_minor); | 947 | &vpci_minor); |
946 | 948 | ||
947 | if (err) { | 949 | if (err) { |
948 | prom_printf("SUN4V_PCI: Could not register hvapi, " | 950 | printk(KERN_ERR PFX "Could not register hvapi, " |
949 | "err=%d\n", err); | 951 | "err=%d\n", err); |
950 | prom_halt(); | 952 | return err; |
951 | } | 953 | } |
952 | printk("SUN4V_PCI: Registered hvapi major[%lu] minor[%lu]\n", | 954 | printk(KERN_INFO PFX "Registered hvapi major[%lu] minor[%lu]\n", |
953 | vpci_major, vpci_minor); | 955 | vpci_major, vpci_minor); |
954 | 956 | ||
955 | dma_ops = &sun4v_dma_ops; | 957 | dma_ops = &sun4v_dma_ops; |
956 | } | 958 | } |
957 | 959 | ||
958 | prop = of_find_property(dp, "reg", NULL); | 960 | regs = of_get_property(dp, "reg", NULL); |
959 | if (!prop) { | 961 | err = -ENODEV; |
960 | prom_printf("SUN4V_PCI: Could not find config registers\n"); | 962 | if (!regs) { |
961 | prom_halt(); | 963 | printk(KERN_ERR PFX "Could not find config registers\n"); |
964 | goto out_err; | ||
962 | } | 965 | } |
963 | regs = prop->value; | ||
964 | |||
965 | devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; | 966 | devhandle = (regs->phys_addr >> 32UL) & 0x0fffffff; |
966 | 967 | ||
967 | for (pbm = pci_pbm_root; pbm; pbm = pbm->next) { | 968 | err = -ENOMEM; |
968 | if (pbm->devhandle == (devhandle ^ 0x40)) { | 969 | if (!iommu_batch_initialized) { |
969 | pci_sun4v_pbm_init(pbm->parent, dp, devhandle); | 970 | for_each_possible_cpu(i) { |
970 | return; | 971 | unsigned long page = get_zeroed_page(GFP_KERNEL); |
972 | |||
973 | if (!page) | ||
974 | goto out_err; | ||
975 | |||
976 | per_cpu(iommu_batch, i).pglist = (u64 *) page; | ||
971 | } | 977 | } |
978 | iommu_batch_initialized = 1; | ||
972 | } | 979 | } |
973 | 980 | ||
974 | for_each_possible_cpu(i) { | 981 | pbm = kzalloc(sizeof(*pbm), GFP_KERNEL); |
975 | unsigned long page = get_zeroed_page(GFP_ATOMIC); | 982 | if (!pbm) { |
976 | 983 | printk(KERN_ERR PFX "Could not allocate pci_pbm_info\n"); | |
977 | if (!page) | 984 | goto out_err; |
978 | goto fatal_memory_error; | 985 | } |
979 | 986 | ||
980 | per_cpu(iommu_batch, i).pglist = (u64 *) page; | 987 | iommu = kzalloc(sizeof(struct iommu), GFP_KERNEL); |
988 | if (!iommu) { | ||
989 | printk(KERN_ERR PFX "Could not allocate pbm iommu\n"); | ||
990 | goto out_free_controller; | ||
981 | } | 991 | } |
982 | 992 | ||
983 | p = kzalloc(sizeof(struct pci_controller_info), GFP_ATOMIC); | 993 | pbm->iommu = iommu; |
984 | if (!p) | ||
985 | goto fatal_memory_error; | ||
986 | 994 | ||
987 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 995 | err = pci_sun4v_pbm_init(pbm, op, devhandle); |
988 | if (!iommu) | 996 | if (err) |
989 | goto fatal_memory_error; | 997 | goto out_free_iommu; |
998 | |||
999 | dev_set_drvdata(&op->dev, pbm); | ||
1000 | |||
1001 | return 0; | ||
1002 | |||
1003 | out_free_iommu: | ||
1004 | kfree(pbm->iommu); | ||
990 | 1005 | ||
991 | p->pbm_A.iommu = iommu; | 1006 | out_free_controller: |
1007 | kfree(pbm); | ||
992 | 1008 | ||
993 | iommu = kzalloc(sizeof(struct iommu), GFP_ATOMIC); | 1009 | out_err: |
994 | if (!iommu) | 1010 | return err; |
995 | goto fatal_memory_error; | 1011 | } |
996 | 1012 | ||
997 | p->pbm_B.iommu = iommu; | 1013 | static struct of_device_id __initdata pci_sun4v_match[] = { |
1014 | { | ||
1015 | .name = "pci", | ||
1016 | .compatible = "SUNW,sun4v-pci", | ||
1017 | }, | ||
1018 | {}, | ||
1019 | }; | ||
998 | 1020 | ||
999 | pci_sun4v_pbm_init(p, dp, devhandle); | 1021 | static struct of_platform_driver pci_sun4v_driver = { |
1000 | return; | 1022 | .name = DRIVER_NAME, |
1023 | .match_table = pci_sun4v_match, | ||
1024 | .probe = pci_sun4v_probe, | ||
1025 | }; | ||
1001 | 1026 | ||
1002 | fatal_memory_error: | 1027 | static int __init pci_sun4v_init(void) |
1003 | prom_printf("SUN4V_PCI: Fatal memory allocation error.\n"); | 1028 | { |
1004 | prom_halt(); | 1029 | return of_register_driver(&pci_sun4v_driver, &of_bus_type); |
1005 | } | 1030 | } |
1031 | |||
1032 | subsys_initcall(pci_sun4v_init); | ||
diff --git a/arch/sparc64/kernel/pci_sun4v_asm.S b/arch/sparc64/kernel/pci_sun4v_asm.S index ecb81f389b06..e606d46c6815 100644 --- a/arch/sparc64/kernel/pci_sun4v_asm.S +++ b/arch/sparc64/kernel/pci_sun4v_asm.S | |||
@@ -1,8 +1,9 @@ | |||
1 | /* pci_sun4v_asm: Hypervisor calls for PCI support. | 1 | /* pci_sun4v_asm: Hypervisor calls for PCI support. |
2 | * | 2 | * |
3 | * Copyright (C) 2006 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2006, 2008 David S. Miller <davem@davemloft.net> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/linkage.h> | ||
6 | #include <asm/hypervisor.h> | 7 | #include <asm/hypervisor.h> |
7 | 8 | ||
8 | /* %o0: devhandle | 9 | /* %o0: devhandle |
@@ -14,8 +15,7 @@ | |||
14 | * returns %o0: -status if status was non-zero, else | 15 | * returns %o0: -status if status was non-zero, else |
15 | * %o0: num pages mapped | 16 | * %o0: num pages mapped |
16 | */ | 17 | */ |
17 | .globl pci_sun4v_iommu_map | 18 | ENTRY(pci_sun4v_iommu_map) |
18 | pci_sun4v_iommu_map: | ||
19 | mov %o5, %g1 | 19 | mov %o5, %g1 |
20 | mov HV_FAST_PCI_IOMMU_MAP, %o5 | 20 | mov HV_FAST_PCI_IOMMU_MAP, %o5 |
21 | ta HV_FAST_TRAP | 21 | ta HV_FAST_TRAP |
@@ -24,6 +24,7 @@ pci_sun4v_iommu_map: | |||
24 | mov %o1, %o0 | 24 | mov %o1, %o0 |
25 | 1: retl | 25 | 1: retl |
26 | nop | 26 | nop |
27 | ENDPROC(pci_sun4v_iommu_map) | ||
27 | 28 | ||
28 | /* %o0: devhandle | 29 | /* %o0: devhandle |
29 | * %o1: tsbid | 30 | * %o1: tsbid |
@@ -31,12 +32,12 @@ pci_sun4v_iommu_map: | |||
31 | * | 32 | * |
32 | * returns %o0: num ttes demapped | 33 | * returns %o0: num ttes demapped |
33 | */ | 34 | */ |
34 | .globl pci_sun4v_iommu_demap | 35 | ENTRY(pci_sun4v_iommu_demap) |
35 | pci_sun4v_iommu_demap: | ||
36 | mov HV_FAST_PCI_IOMMU_DEMAP, %o5 | 36 | mov HV_FAST_PCI_IOMMU_DEMAP, %o5 |
37 | ta HV_FAST_TRAP | 37 | ta HV_FAST_TRAP |
38 | retl | 38 | retl |
39 | mov %o1, %o0 | 39 | mov %o1, %o0 |
40 | ENDPROC(pci_sun4v_iommu_demap) | ||
40 | 41 | ||
41 | /* %o0: devhandle | 42 | /* %o0: devhandle |
42 | * %o1: tsbid | 43 | * %o1: tsbid |
@@ -45,8 +46,7 @@ pci_sun4v_iommu_demap: | |||
45 | * | 46 | * |
46 | * returns %o0: status | 47 | * returns %o0: status |
47 | */ | 48 | */ |
48 | .globl pci_sun4v_iommu_getmap | 49 | ENTRY(pci_sun4v_iommu_getmap) |
49 | pci_sun4v_iommu_getmap: | ||
50 | mov %o2, %o4 | 50 | mov %o2, %o4 |
51 | mov HV_FAST_PCI_IOMMU_GETMAP, %o5 | 51 | mov HV_FAST_PCI_IOMMU_GETMAP, %o5 |
52 | ta HV_FAST_TRAP | 52 | ta HV_FAST_TRAP |
@@ -54,6 +54,7 @@ pci_sun4v_iommu_getmap: | |||
54 | stx %o2, [%o3] | 54 | stx %o2, [%o3] |
55 | retl | 55 | retl |
56 | mov %o0, %o0 | 56 | mov %o0, %o0 |
57 | ENDPROC(pci_sun4v_iommu_getmap) | ||
57 | 58 | ||
58 | /* %o0: devhandle | 59 | /* %o0: devhandle |
59 | * %o1: pci_device | 60 | * %o1: pci_device |
@@ -65,14 +66,14 @@ pci_sun4v_iommu_getmap: | |||
65 | * If there is an error, the data will be returned | 66 | * If there is an error, the data will be returned |
66 | * as all 1's. | 67 | * as all 1's. |
67 | */ | 68 | */ |
68 | .globl pci_sun4v_config_get | 69 | ENTRY(pci_sun4v_config_get) |
69 | pci_sun4v_config_get: | ||
70 | mov HV_FAST_PCI_CONFIG_GET, %o5 | 70 | mov HV_FAST_PCI_CONFIG_GET, %o5 |
71 | ta HV_FAST_TRAP | 71 | ta HV_FAST_TRAP |
72 | brnz,a,pn %o1, 1f | 72 | brnz,a,pn %o1, 1f |
73 | mov -1, %o2 | 73 | mov -1, %o2 |
74 | 1: retl | 74 | 1: retl |
75 | mov %o2, %o0 | 75 | mov %o2, %o0 |
76 | ENDPROC(pci_sun4v_config_get) | ||
76 | 77 | ||
77 | /* %o0: devhandle | 78 | /* %o0: devhandle |
78 | * %o1: pci_device | 79 | * %o1: pci_device |
@@ -85,14 +86,14 @@ pci_sun4v_config_get: | |||
85 | * status will be zero if the operation completed | 86 | * status will be zero if the operation completed |
86 | * successfully, else -1 if not | 87 | * successfully, else -1 if not |
87 | */ | 88 | */ |
88 | .globl pci_sun4v_config_put | 89 | ENTRY(pci_sun4v_config_put) |
89 | pci_sun4v_config_put: | ||
90 | mov HV_FAST_PCI_CONFIG_PUT, %o5 | 90 | mov HV_FAST_PCI_CONFIG_PUT, %o5 |
91 | ta HV_FAST_TRAP | 91 | ta HV_FAST_TRAP |
92 | brnz,a,pn %o1, 1f | 92 | brnz,a,pn %o1, 1f |
93 | mov -1, %o1 | 93 | mov -1, %o1 |
94 | 1: retl | 94 | 1: retl |
95 | mov %o1, %o0 | 95 | mov %o1, %o0 |
96 | ENDPROC(pci_sun4v_config_put) | ||
96 | 97 | ||
97 | /* %o0: devhandle | 98 | /* %o0: devhandle |
98 | * %o1: msiqid | 99 | * %o1: msiqid |
@@ -104,12 +105,12 @@ pci_sun4v_config_put: | |||
104 | * status will be zero if the operation completed | 105 | * status will be zero if the operation completed |
105 | * successfully, else -1 if not | 106 | * successfully, else -1 if not |
106 | */ | 107 | */ |
107 | .globl pci_sun4v_msiq_conf | 108 | ENTRY(pci_sun4v_msiq_conf) |
108 | pci_sun4v_msiq_conf: | ||
109 | mov HV_FAST_PCI_MSIQ_CONF, %o5 | 109 | mov HV_FAST_PCI_MSIQ_CONF, %o5 |
110 | ta HV_FAST_TRAP | 110 | ta HV_FAST_TRAP |
111 | retl | 111 | retl |
112 | mov %o0, %o0 | 112 | mov %o0, %o0 |
113 | ENDPROC(pci_sun4v_msiq_conf) | ||
113 | 114 | ||
114 | /* %o0: devhandle | 115 | /* %o0: devhandle |
115 | * %o1: msiqid | 116 | * %o1: msiqid |
@@ -118,8 +119,7 @@ pci_sun4v_msiq_conf: | |||
118 | * | 119 | * |
119 | * returns %o0: status | 120 | * returns %o0: status |
120 | */ | 121 | */ |
121 | .globl pci_sun4v_msiq_info | 122 | ENTRY(pci_sun4v_msiq_info) |
122 | pci_sun4v_msiq_info: | ||
123 | mov %o2, %o4 | 123 | mov %o2, %o4 |
124 | mov HV_FAST_PCI_MSIQ_INFO, %o5 | 124 | mov HV_FAST_PCI_MSIQ_INFO, %o5 |
125 | ta HV_FAST_TRAP | 125 | ta HV_FAST_TRAP |
@@ -127,6 +127,7 @@ pci_sun4v_msiq_info: | |||
127 | stx %o2, [%o3] | 127 | stx %o2, [%o3] |
128 | retl | 128 | retl |
129 | mov %o0, %o0 | 129 | mov %o0, %o0 |
130 | ENDPROC(pci_sun4v_msiq_info) | ||
130 | 131 | ||
131 | /* %o0: devhandle | 132 | /* %o0: devhandle |
132 | * %o1: msiqid | 133 | * %o1: msiqid |
@@ -134,13 +135,13 @@ pci_sun4v_msiq_info: | |||
134 | * | 135 | * |
135 | * returns %o0: status | 136 | * returns %o0: status |
136 | */ | 137 | */ |
137 | .globl pci_sun4v_msiq_getvalid | 138 | ENTRY(pci_sun4v_msiq_getvalid) |
138 | pci_sun4v_msiq_getvalid: | ||
139 | mov HV_FAST_PCI_MSIQ_GETVALID, %o5 | 139 | mov HV_FAST_PCI_MSIQ_GETVALID, %o5 |
140 | ta HV_FAST_TRAP | 140 | ta HV_FAST_TRAP |
141 | stx %o1, [%o2] | 141 | stx %o1, [%o2] |
142 | retl | 142 | retl |
143 | mov %o0, %o0 | 143 | mov %o0, %o0 |
144 | ENDPROC(pci_sun4v_msiq_getvalid) | ||
144 | 145 | ||
145 | /* %o0: devhandle | 146 | /* %o0: devhandle |
146 | * %o1: msiqid | 147 | * %o1: msiqid |
@@ -148,12 +149,12 @@ pci_sun4v_msiq_getvalid: | |||
148 | * | 149 | * |
149 | * returns %o0: status | 150 | * returns %o0: status |
150 | */ | 151 | */ |
151 | .globl pci_sun4v_msiq_setvalid | 152 | ENTRY(pci_sun4v_msiq_setvalid) |
152 | pci_sun4v_msiq_setvalid: | ||
153 | mov HV_FAST_PCI_MSIQ_SETVALID, %o5 | 153 | mov HV_FAST_PCI_MSIQ_SETVALID, %o5 |
154 | ta HV_FAST_TRAP | 154 | ta HV_FAST_TRAP |
155 | retl | 155 | retl |
156 | mov %o0, %o0 | 156 | mov %o0, %o0 |
157 | ENDPROC(pci_sun4v_msiq_setvalid) | ||
157 | 158 | ||
158 | /* %o0: devhandle | 159 | /* %o0: devhandle |
159 | * %o1: msiqid | 160 | * %o1: msiqid |
@@ -161,13 +162,13 @@ pci_sun4v_msiq_setvalid: | |||
161 | * | 162 | * |
162 | * returns %o0: status | 163 | * returns %o0: status |
163 | */ | 164 | */ |
164 | .globl pci_sun4v_msiq_getstate | 165 | ENTRY(pci_sun4v_msiq_getstate) |
165 | pci_sun4v_msiq_getstate: | ||
166 | mov HV_FAST_PCI_MSIQ_GETSTATE, %o5 | 166 | mov HV_FAST_PCI_MSIQ_GETSTATE, %o5 |
167 | ta HV_FAST_TRAP | 167 | ta HV_FAST_TRAP |
168 | stx %o1, [%o2] | 168 | stx %o1, [%o2] |
169 | retl | 169 | retl |
170 | mov %o0, %o0 | 170 | mov %o0, %o0 |
171 | ENDPROC(pci_sun4v_msiq_getstate) | ||
171 | 172 | ||
172 | /* %o0: devhandle | 173 | /* %o0: devhandle |
173 | * %o1: msiqid | 174 | * %o1: msiqid |
@@ -175,12 +176,12 @@ pci_sun4v_msiq_getstate: | |||
175 | * | 176 | * |
176 | * returns %o0: status | 177 | * returns %o0: status |
177 | */ | 178 | */ |
178 | .globl pci_sun4v_msiq_setstate | 179 | ENTRY(pci_sun4v_msiq_setstate) |
179 | pci_sun4v_msiq_setstate: | ||
180 | mov HV_FAST_PCI_MSIQ_SETSTATE, %o5 | 180 | mov HV_FAST_PCI_MSIQ_SETSTATE, %o5 |
181 | ta HV_FAST_TRAP | 181 | ta HV_FAST_TRAP |
182 | retl | 182 | retl |
183 | mov %o0, %o0 | 183 | mov %o0, %o0 |
184 | ENDPROC(pci_sun4v_msiq_setstate) | ||
184 | 185 | ||
185 | /* %o0: devhandle | 186 | /* %o0: devhandle |
186 | * %o1: msiqid | 187 | * %o1: msiqid |
@@ -188,13 +189,13 @@ pci_sun4v_msiq_setstate: | |||
188 | * | 189 | * |
189 | * returns %o0: status | 190 | * returns %o0: status |
190 | */ | 191 | */ |
191 | .globl pci_sun4v_msiq_gethead | 192 | ENTRY(pci_sun4v_msiq_gethead) |
192 | pci_sun4v_msiq_gethead: | ||
193 | mov HV_FAST_PCI_MSIQ_GETHEAD, %o5 | 193 | mov HV_FAST_PCI_MSIQ_GETHEAD, %o5 |
194 | ta HV_FAST_TRAP | 194 | ta HV_FAST_TRAP |
195 | stx %o1, [%o2] | 195 | stx %o1, [%o2] |
196 | retl | 196 | retl |
197 | mov %o0, %o0 | 197 | mov %o0, %o0 |
198 | ENDPROC(pci_sun4v_msiq_gethead) | ||
198 | 199 | ||
199 | /* %o0: devhandle | 200 | /* %o0: devhandle |
200 | * %o1: msiqid | 201 | * %o1: msiqid |
@@ -202,12 +203,12 @@ pci_sun4v_msiq_gethead: | |||
202 | * | 203 | * |
203 | * returns %o0: status | 204 | * returns %o0: status |
204 | */ | 205 | */ |
205 | .globl pci_sun4v_msiq_sethead | 206 | ENTRY(pci_sun4v_msiq_sethead) |
206 | pci_sun4v_msiq_sethead: | ||
207 | mov HV_FAST_PCI_MSIQ_SETHEAD, %o5 | 207 | mov HV_FAST_PCI_MSIQ_SETHEAD, %o5 |
208 | ta HV_FAST_TRAP | 208 | ta HV_FAST_TRAP |
209 | retl | 209 | retl |
210 | mov %o0, %o0 | 210 | mov %o0, %o0 |
211 | ENDPROC(pci_sun4v_msiq_sethead) | ||
211 | 212 | ||
212 | /* %o0: devhandle | 213 | /* %o0: devhandle |
213 | * %o1: msiqid | 214 | * %o1: msiqid |
@@ -215,13 +216,13 @@ pci_sun4v_msiq_sethead: | |||
215 | * | 216 | * |
216 | * returns %o0: status | 217 | * returns %o0: status |
217 | */ | 218 | */ |
218 | .globl pci_sun4v_msiq_gettail | 219 | ENTRY(pci_sun4v_msiq_gettail) |
219 | pci_sun4v_msiq_gettail: | ||
220 | mov HV_FAST_PCI_MSIQ_GETTAIL, %o5 | 220 | mov HV_FAST_PCI_MSIQ_GETTAIL, %o5 |
221 | ta HV_FAST_TRAP | 221 | ta HV_FAST_TRAP |
222 | stx %o1, [%o2] | 222 | stx %o1, [%o2] |
223 | retl | 223 | retl |
224 | mov %o0, %o0 | 224 | mov %o0, %o0 |
225 | ENDPROC(pci_sun4v_msiq_gettail) | ||
225 | 226 | ||
226 | /* %o0: devhandle | 227 | /* %o0: devhandle |
227 | * %o1: msinum | 228 | * %o1: msinum |
@@ -229,13 +230,13 @@ pci_sun4v_msiq_gettail: | |||
229 | * | 230 | * |
230 | * returns %o0: status | 231 | * returns %o0: status |
231 | */ | 232 | */ |
232 | .globl pci_sun4v_msi_getvalid | 233 | ENTRY(pci_sun4v_msi_getvalid) |
233 | pci_sun4v_msi_getvalid: | ||
234 | mov HV_FAST_PCI_MSI_GETVALID, %o5 | 234 | mov HV_FAST_PCI_MSI_GETVALID, %o5 |
235 | ta HV_FAST_TRAP | 235 | ta HV_FAST_TRAP |
236 | stx %o1, [%o2] | 236 | stx %o1, [%o2] |
237 | retl | 237 | retl |
238 | mov %o0, %o0 | 238 | mov %o0, %o0 |
239 | ENDPROC(pci_sun4v_msi_getvalid) | ||
239 | 240 | ||
240 | /* %o0: devhandle | 241 | /* %o0: devhandle |
241 | * %o1: msinum | 242 | * %o1: msinum |
@@ -243,12 +244,12 @@ pci_sun4v_msi_getvalid: | |||
243 | * | 244 | * |
244 | * returns %o0: status | 245 | * returns %o0: status |
245 | */ | 246 | */ |
246 | .globl pci_sun4v_msi_setvalid | 247 | ENTRY(pci_sun4v_msi_setvalid) |
247 | pci_sun4v_msi_setvalid: | ||
248 | mov HV_FAST_PCI_MSI_SETVALID, %o5 | 248 | mov HV_FAST_PCI_MSI_SETVALID, %o5 |
249 | ta HV_FAST_TRAP | 249 | ta HV_FAST_TRAP |
250 | retl | 250 | retl |
251 | mov %o0, %o0 | 251 | mov %o0, %o0 |
252 | ENDPROC(pci_sun4v_msi_setvalid) | ||
252 | 253 | ||
253 | /* %o0: devhandle | 254 | /* %o0: devhandle |
254 | * %o1: msinum | 255 | * %o1: msinum |
@@ -256,13 +257,13 @@ pci_sun4v_msi_setvalid: | |||
256 | * | 257 | * |
257 | * returns %o0: status | 258 | * returns %o0: status |
258 | */ | 259 | */ |
259 | .globl pci_sun4v_msi_getmsiq | 260 | ENTRY(pci_sun4v_msi_getmsiq) |
260 | pci_sun4v_msi_getmsiq: | ||
261 | mov HV_FAST_PCI_MSI_GETMSIQ, %o5 | 261 | mov HV_FAST_PCI_MSI_GETMSIQ, %o5 |
262 | ta HV_FAST_TRAP | 262 | ta HV_FAST_TRAP |
263 | stx %o1, [%o2] | 263 | stx %o1, [%o2] |
264 | retl | 264 | retl |
265 | mov %o0, %o0 | 265 | mov %o0, %o0 |
266 | ENDPROC(pci_sun4v_msi_getmsiq) | ||
266 | 267 | ||
267 | /* %o0: devhandle | 268 | /* %o0: devhandle |
268 | * %o1: msinum | 269 | * %o1: msinum |
@@ -271,12 +272,12 @@ pci_sun4v_msi_getmsiq: | |||
271 | * | 272 | * |
272 | * returns %o0: status | 273 | * returns %o0: status |
273 | */ | 274 | */ |
274 | .globl pci_sun4v_msi_setmsiq | 275 | ENTRY(pci_sun4v_msi_setmsiq) |
275 | pci_sun4v_msi_setmsiq: | ||
276 | mov HV_FAST_PCI_MSI_SETMSIQ, %o5 | 276 | mov HV_FAST_PCI_MSI_SETMSIQ, %o5 |
277 | ta HV_FAST_TRAP | 277 | ta HV_FAST_TRAP |
278 | retl | 278 | retl |
279 | mov %o0, %o0 | 279 | mov %o0, %o0 |
280 | ENDPROC(pci_sun4v_msi_setmsiq) | ||
280 | 281 | ||
281 | /* %o0: devhandle | 282 | /* %o0: devhandle |
282 | * %o1: msinum | 283 | * %o1: msinum |
@@ -284,13 +285,13 @@ pci_sun4v_msi_setmsiq: | |||
284 | * | 285 | * |
285 | * returns %o0: status | 286 | * returns %o0: status |
286 | */ | 287 | */ |
287 | .globl pci_sun4v_msi_getstate | 288 | ENTRY(pci_sun4v_msi_getstate) |
288 | pci_sun4v_msi_getstate: | ||
289 | mov HV_FAST_PCI_MSI_GETSTATE, %o5 | 289 | mov HV_FAST_PCI_MSI_GETSTATE, %o5 |
290 | ta HV_FAST_TRAP | 290 | ta HV_FAST_TRAP |
291 | stx %o1, [%o2] | 291 | stx %o1, [%o2] |
292 | retl | 292 | retl |
293 | mov %o0, %o0 | 293 | mov %o0, %o0 |
294 | ENDPROC(pci_sun4v_msi_getstate) | ||
294 | 295 | ||
295 | /* %o0: devhandle | 296 | /* %o0: devhandle |
296 | * %o1: msinum | 297 | * %o1: msinum |
@@ -298,12 +299,12 @@ pci_sun4v_msi_getstate: | |||
298 | * | 299 | * |
299 | * returns %o0: status | 300 | * returns %o0: status |
300 | */ | 301 | */ |
301 | .globl pci_sun4v_msi_setstate | 302 | ENTRY(pci_sun4v_msi_setstate) |
302 | pci_sun4v_msi_setstate: | ||
303 | mov HV_FAST_PCI_MSI_SETSTATE, %o5 | 303 | mov HV_FAST_PCI_MSI_SETSTATE, %o5 |
304 | ta HV_FAST_TRAP | 304 | ta HV_FAST_TRAP |
305 | retl | 305 | retl |
306 | mov %o0, %o0 | 306 | mov %o0, %o0 |
307 | ENDPROC(pci_sun4v_msi_setstate) | ||
307 | 308 | ||
308 | /* %o0: devhandle | 309 | /* %o0: devhandle |
309 | * %o1: msinum | 310 | * %o1: msinum |
@@ -311,13 +312,13 @@ pci_sun4v_msi_setstate: | |||
311 | * | 312 | * |
312 | * returns %o0: status | 313 | * returns %o0: status |
313 | */ | 314 | */ |
314 | .globl pci_sun4v_msg_getmsiq | 315 | ENTRY(pci_sun4v_msg_getmsiq) |
315 | pci_sun4v_msg_getmsiq: | ||
316 | mov HV_FAST_PCI_MSG_GETMSIQ, %o5 | 316 | mov HV_FAST_PCI_MSG_GETMSIQ, %o5 |
317 | ta HV_FAST_TRAP | 317 | ta HV_FAST_TRAP |
318 | stx %o1, [%o2] | 318 | stx %o1, [%o2] |
319 | retl | 319 | retl |
320 | mov %o0, %o0 | 320 | mov %o0, %o0 |
321 | ENDPROC(pci_sun4v_msg_getmsiq) | ||
321 | 322 | ||
322 | /* %o0: devhandle | 323 | /* %o0: devhandle |
323 | * %o1: msinum | 324 | * %o1: msinum |
@@ -325,12 +326,12 @@ pci_sun4v_msg_getmsiq: | |||
325 | * | 326 | * |
326 | * returns %o0: status | 327 | * returns %o0: status |
327 | */ | 328 | */ |
328 | .globl pci_sun4v_msg_setmsiq | 329 | ENTRY(pci_sun4v_msg_setmsiq) |
329 | pci_sun4v_msg_setmsiq: | ||
330 | mov HV_FAST_PCI_MSG_SETMSIQ, %o5 | 330 | mov HV_FAST_PCI_MSG_SETMSIQ, %o5 |
331 | ta HV_FAST_TRAP | 331 | ta HV_FAST_TRAP |
332 | retl | 332 | retl |
333 | mov %o0, %o0 | 333 | mov %o0, %o0 |
334 | ENDPROC(pci_sun4v_msg_setmsiq) | ||
334 | 335 | ||
335 | /* %o0: devhandle | 336 | /* %o0: devhandle |
336 | * %o1: msinum | 337 | * %o1: msinum |
@@ -338,13 +339,13 @@ pci_sun4v_msg_setmsiq: | |||
338 | * | 339 | * |
339 | * returns %o0: status | 340 | * returns %o0: status |
340 | */ | 341 | */ |
341 | .globl pci_sun4v_msg_getvalid | 342 | ENTRY(pci_sun4v_msg_getvalid) |
342 | pci_sun4v_msg_getvalid: | ||
343 | mov HV_FAST_PCI_MSG_GETVALID, %o5 | 343 | mov HV_FAST_PCI_MSG_GETVALID, %o5 |
344 | ta HV_FAST_TRAP | 344 | ta HV_FAST_TRAP |
345 | stx %o1, [%o2] | 345 | stx %o1, [%o2] |
346 | retl | 346 | retl |
347 | mov %o0, %o0 | 347 | mov %o0, %o0 |
348 | ENDPROC(pci_sun4v_msg_getvalid) | ||
348 | 349 | ||
349 | /* %o0: devhandle | 350 | /* %o0: devhandle |
350 | * %o1: msinum | 351 | * %o1: msinum |
@@ -352,10 +353,10 @@ pci_sun4v_msg_getvalid: | |||
352 | * | 353 | * |
353 | * returns %o0: status | 354 | * returns %o0: status |
354 | */ | 355 | */ |
355 | .globl pci_sun4v_msg_setvalid | 356 | ENTRY(pci_sun4v_msg_setvalid) |
356 | pci_sun4v_msg_setvalid: | ||
357 | mov HV_FAST_PCI_MSG_SETVALID, %o5 | 357 | mov HV_FAST_PCI_MSG_SETVALID, %o5 |
358 | ta HV_FAST_TRAP | 358 | ta HV_FAST_TRAP |
359 | retl | 359 | retl |
360 | mov %o0, %o0 | 360 | mov %o0, %o0 |
361 | ENDPROC(pci_sun4v_msg_setvalid) | ||
361 | 362 | ||
diff --git a/arch/sparc64/kernel/power.c b/arch/sparc64/kernel/power.c index 3bb987a6d03c..076cad7f9757 100644 --- a/arch/sparc64/kernel/power.c +++ b/arch/sparc64/kernel/power.c | |||
@@ -1,34 +1,17 @@ | |||
1 | /* power.c: Power management driver. | 1 | /* power.c: Power management driver. |
2 | * | 2 | * |
3 | * Copyright (C) 1999, 2007 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 1999, 2007, 2008 David S. Miller (davem@davemloft.net) |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
8 | #include <linux/init.h> | 8 | #include <linux/init.h> |
9 | #include <linux/sched.h> | ||
10 | #include <linux/signal.h> | ||
11 | #include <linux/delay.h> | ||
12 | #include <linux/interrupt.h> | 9 | #include <linux/interrupt.h> |
13 | #include <linux/pm.h> | ||
14 | #include <linux/syscalls.h> | ||
15 | #include <linux/reboot.h> | 10 | #include <linux/reboot.h> |
16 | #include <linux/of_device.h> | 11 | #include <linux/of_device.h> |
17 | 12 | ||
18 | #include <asm/system.h> | ||
19 | #include <asm/auxio.h> | ||
20 | #include <asm/prom.h> | 13 | #include <asm/prom.h> |
21 | #include <asm/io.h> | 14 | #include <asm/io.h> |
22 | #include <asm/sstate.h> | ||
23 | #include <asm/reboot.h> | ||
24 | |||
25 | #include <linux/unistd.h> | ||
26 | |||
27 | /* | ||
28 | * sysctl - toggle power-off restriction for serial console | ||
29 | * systems in machine_power_off() | ||
30 | */ | ||
31 | int scons_pwroff = 1; | ||
32 | 15 | ||
33 | static void __iomem *power_reg; | 16 | static void __iomem *power_reg; |
34 | 17 | ||
@@ -40,31 +23,6 @@ static irqreturn_t power_handler(int irq, void *dev_id) | |||
40 | return IRQ_HANDLED; | 23 | return IRQ_HANDLED; |
41 | } | 24 | } |
42 | 25 | ||
43 | static void (*poweroff_method)(void) = machine_alt_power_off; | ||
44 | |||
45 | void machine_power_off(void) | ||
46 | { | ||
47 | sstate_poweroff(); | ||
48 | if (strcmp(of_console_device->type, "serial") || scons_pwroff) { | ||
49 | if (power_reg) { | ||
50 | /* Both register bits seem to have the | ||
51 | * same effect, so until I figure out | ||
52 | * what the difference is... | ||
53 | */ | ||
54 | writel(AUXIO_PCIO_CPWR_OFF | AUXIO_PCIO_SPWR_OFF, power_reg); | ||
55 | } else { | ||
56 | if (poweroff_method != NULL) { | ||
57 | poweroff_method(); | ||
58 | /* not reached */ | ||
59 | } | ||
60 | } | ||
61 | } | ||
62 | machine_halt(); | ||
63 | } | ||
64 | |||
65 | void (*pm_power_off)(void) = machine_power_off; | ||
66 | EXPORT_SYMBOL(pm_power_off); | ||
67 | |||
68 | static int __init has_button_interrupt(unsigned int irq, struct device_node *dp) | 26 | static int __init has_button_interrupt(unsigned int irq, struct device_node *dp) |
69 | { | 27 | { |
70 | if (irq == 0xffffffff) | 28 | if (irq == 0xffffffff) |
@@ -85,8 +43,6 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id | |||
85 | printk(KERN_INFO "%s: Control reg at %lx\n", | 43 | printk(KERN_INFO "%s: Control reg at %lx\n", |
86 | op->node->name, res->start); | 44 | op->node->name, res->start); |
87 | 45 | ||
88 | poweroff_method = machine_halt; /* able to use the standard halt */ | ||
89 | |||
90 | if (has_button_interrupt(irq, op->node)) { | 46 | if (has_button_interrupt(irq, op->node)) { |
91 | if (request_irq(irq, | 47 | if (request_irq(irq, |
92 | power_handler, 0, "power", NULL) < 0) | 48 | power_handler, 0, "power", NULL) < 0) |
@@ -96,7 +52,7 @@ static int __devinit power_probe(struct of_device *op, const struct of_device_id | |||
96 | return 0; | 52 | return 0; |
97 | } | 53 | } |
98 | 54 | ||
99 | static struct of_device_id power_match[] = { | 55 | static struct of_device_id __initdata power_match[] = { |
100 | { | 56 | { |
101 | .name = "power", | 57 | .name = "power", |
102 | }, | 58 | }, |
@@ -111,8 +67,9 @@ static struct of_platform_driver power_driver = { | |||
111 | }, | 67 | }, |
112 | }; | 68 | }; |
113 | 69 | ||
114 | void __init power_init(void) | 70 | static int __init power_init(void) |
115 | { | 71 | { |
116 | of_register_driver(&power_driver, &of_platform_bus_type); | 72 | return of_register_driver(&power_driver, &of_platform_bus_type); |
117 | return; | ||
118 | } | 73 | } |
74 | |||
75 | device_initcall(power_init); | ||
diff --git a/arch/sparc64/kernel/process.c b/arch/sparc64/kernel/process.c index 15f4178592e7..d5e2acef9877 100644 --- a/arch/sparc64/kernel/process.c +++ b/arch/sparc64/kernel/process.c | |||
@@ -22,7 +22,6 @@ | |||
22 | #include <linux/ptrace.h> | 22 | #include <linux/ptrace.h> |
23 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/user.h> | 24 | #include <linux/user.h> |
25 | #include <linux/reboot.h> | ||
26 | #include <linux/delay.h> | 25 | #include <linux/delay.h> |
27 | #include <linux/compat.h> | 26 | #include <linux/compat.h> |
28 | #include <linux/tick.h> | 27 | #include <linux/tick.h> |
@@ -31,7 +30,6 @@ | |||
31 | #include <linux/elfcore.h> | 30 | #include <linux/elfcore.h> |
32 | #include <linux/sysrq.h> | 31 | #include <linux/sysrq.h> |
33 | 32 | ||
34 | #include <asm/oplib.h> | ||
35 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
36 | #include <asm/system.h> | 34 | #include <asm/system.h> |
37 | #include <asm/page.h> | 35 | #include <asm/page.h> |
@@ -46,8 +44,6 @@ | |||
46 | #include <asm/mmu_context.h> | 44 | #include <asm/mmu_context.h> |
47 | #include <asm/unistd.h> | 45 | #include <asm/unistd.h> |
48 | #include <asm/hypervisor.h> | 46 | #include <asm/hypervisor.h> |
49 | #include <asm/sstate.h> | ||
50 | #include <asm/reboot.h> | ||
51 | #include <asm/syscalls.h> | 47 | #include <asm/syscalls.h> |
52 | #include <asm/irq_regs.h> | 48 | #include <asm/irq_regs.h> |
53 | #include <asm/smp.h> | 49 | #include <asm/smp.h> |
@@ -115,35 +111,6 @@ void cpu_idle(void) | |||
115 | } | 111 | } |
116 | } | 112 | } |
117 | 113 | ||
118 | void machine_halt(void) | ||
119 | { | ||
120 | sstate_halt(); | ||
121 | prom_halt(); | ||
122 | panic("Halt failed!"); | ||
123 | } | ||
124 | |||
125 | void machine_alt_power_off(void) | ||
126 | { | ||
127 | sstate_poweroff(); | ||
128 | prom_halt_power_off(); | ||
129 | panic("Power-off failed!"); | ||
130 | } | ||
131 | |||
132 | void machine_restart(char * cmd) | ||
133 | { | ||
134 | char *p; | ||
135 | |||
136 | sstate_reboot(); | ||
137 | p = strchr (reboot_command, '\n'); | ||
138 | if (p) *p = 0; | ||
139 | if (cmd) | ||
140 | prom_reboot(cmd); | ||
141 | if (*reboot_command) | ||
142 | prom_reboot(reboot_command); | ||
143 | prom_reboot(""); | ||
144 | panic("Reboot failed!"); | ||
145 | } | ||
146 | |||
147 | #ifdef CONFIG_COMPAT | 114 | #ifdef CONFIG_COMPAT |
148 | static void show_regwindow32(struct pt_regs *regs) | 115 | static void show_regwindow32(struct pt_regs *regs) |
149 | { | 116 | { |
@@ -248,7 +215,6 @@ static void __global_reg_self(struct thread_info *tp, struct pt_regs *regs, | |||
248 | global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; | 215 | global_reg_snapshot[this_cpu].o7 = regs->u_regs[UREG_I7]; |
249 | 216 | ||
250 | if (regs->tstate & TSTATE_PRIV) { | 217 | if (regs->tstate & TSTATE_PRIV) { |
251 | struct thread_info *tp = current_thread_info(); | ||
252 | struct reg_window *rw; | 218 | struct reg_window *rw; |
253 | 219 | ||
254 | rw = (struct reg_window *) | 220 | rw = (struct reg_window *) |
@@ -304,7 +270,6 @@ void __trigger_all_cpu_backtrace(void) | |||
304 | 270 | ||
305 | for_each_online_cpu(cpu) { | 271 | for_each_online_cpu(cpu) { |
306 | struct global_reg_snapshot *gp = &global_reg_snapshot[cpu]; | 272 | struct global_reg_snapshot *gp = &global_reg_snapshot[cpu]; |
307 | struct thread_info *tp; | ||
308 | 273 | ||
309 | __global_reg_poll(gp); | 274 | __global_reg_poll(gp); |
310 | 275 | ||
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index 7151513f156e..dbba82f9b142 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c | |||
@@ -38,7 +38,7 @@ struct device_node *of_find_node_by_phandle(phandle handle) | |||
38 | { | 38 | { |
39 | struct device_node *np; | 39 | struct device_node *np; |
40 | 40 | ||
41 | for (np = allnodes; np != 0; np = np->allnext) | 41 | for (np = allnodes; np; np = np->allnext) |
42 | if (np->node == handle) | 42 | if (np->node == handle) |
43 | break; | 43 | break; |
44 | 44 | ||
@@ -59,6 +59,9 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) | |||
59 | } | 59 | } |
60 | EXPORT_SYMBOL(of_getintprop_default); | 60 | EXPORT_SYMBOL(of_getintprop_default); |
61 | 61 | ||
62 | DEFINE_MUTEX(of_set_property_mutex); | ||
63 | EXPORT_SYMBOL(of_set_property_mutex); | ||
64 | |||
62 | int of_set_property(struct device_node *dp, const char *name, void *val, int len) | 65 | int of_set_property(struct device_node *dp, const char *name, void *val, int len) |
63 | { | 66 | { |
64 | struct property **prevp; | 67 | struct property **prevp; |
@@ -82,7 +85,10 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len | |||
82 | void *old_val = prop->value; | 85 | void *old_val = prop->value; |
83 | int ret; | 86 | int ret; |
84 | 87 | ||
88 | mutex_lock(&of_set_property_mutex); | ||
85 | ret = prom_setprop(dp->node, name, val, len); | 89 | ret = prom_setprop(dp->node, name, val, len); |
90 | mutex_unlock(&of_set_property_mutex); | ||
91 | |||
86 | err = -EINVAL; | 92 | err = -EINVAL; |
87 | if (ret >= 0) { | 93 | if (ret >= 0) { |
88 | prop->value = new_val; | 94 | prop->value = new_val; |
@@ -945,22 +951,30 @@ static void __init irq_trans_init(struct device_node *dp) | |||
945 | for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { | 951 | for (i = 0; i < ARRAY_SIZE(pci_irq_trans_table); i++) { |
946 | struct irq_trans *t = &pci_irq_trans_table[i]; | 952 | struct irq_trans *t = &pci_irq_trans_table[i]; |
947 | 953 | ||
948 | if (!strcmp(model, t->name)) | 954 | if (!strcmp(model, t->name)) { |
949 | return t->init(dp); | 955 | t->init(dp); |
956 | return; | ||
957 | } | ||
950 | } | 958 | } |
951 | } | 959 | } |
952 | #endif | 960 | #endif |
953 | #ifdef CONFIG_SBUS | 961 | #ifdef CONFIG_SBUS |
954 | if (!strcmp(dp->name, "sbus") || | 962 | if (!strcmp(dp->name, "sbus") || |
955 | !strcmp(dp->name, "sbi")) | 963 | !strcmp(dp->name, "sbi")) { |
956 | return sbus_irq_trans_init(dp); | 964 | sbus_irq_trans_init(dp); |
965 | return; | ||
966 | } | ||
957 | #endif | 967 | #endif |
958 | if (!strcmp(dp->name, "fhc") && | 968 | if (!strcmp(dp->name, "fhc") && |
959 | !strcmp(dp->parent->name, "central")) | 969 | !strcmp(dp->parent->name, "central")) { |
960 | return central_irq_trans_init(dp); | 970 | central_irq_trans_init(dp); |
971 | return; | ||
972 | } | ||
961 | if (!strcmp(dp->name, "virtual-devices") || | 973 | if (!strcmp(dp->name, "virtual-devices") || |
962 | !strcmp(dp->name, "niu")) | 974 | !strcmp(dp->name, "niu")) { |
963 | return sun4v_vdev_irq_trans_init(dp); | 975 | sun4v_vdev_irq_trans_init(dp); |
976 | return; | ||
977 | } | ||
964 | } | 978 | } |
965 | 979 | ||
966 | static int is_root_node(const struct device_node *dp) | 980 | static int is_root_node(const struct device_node *dp) |
@@ -1231,32 +1245,49 @@ static void __init __build_path_component(struct device_node *dp, char *tmp_buf) | |||
1231 | 1245 | ||
1232 | if (parent != NULL) { | 1246 | if (parent != NULL) { |
1233 | if (!strcmp(parent->type, "pci") || | 1247 | if (!strcmp(parent->type, "pci") || |
1234 | !strcmp(parent->type, "pciex")) | 1248 | !strcmp(parent->type, "pciex")) { |
1235 | return pci_path_component(dp, tmp_buf); | 1249 | pci_path_component(dp, tmp_buf); |
1236 | if (!strcmp(parent->type, "sbus")) | 1250 | return; |
1237 | return sbus_path_component(dp, tmp_buf); | 1251 | } |
1238 | if (!strcmp(parent->type, "upa")) | 1252 | if (!strcmp(parent->type, "sbus")) { |
1239 | return upa_path_component(dp, tmp_buf); | 1253 | sbus_path_component(dp, tmp_buf); |
1240 | if (!strcmp(parent->type, "ebus")) | 1254 | return; |
1241 | return ebus_path_component(dp, tmp_buf); | 1255 | } |
1256 | if (!strcmp(parent->type, "upa")) { | ||
1257 | upa_path_component(dp, tmp_buf); | ||
1258 | return; | ||
1259 | } | ||
1260 | if (!strcmp(parent->type, "ebus")) { | ||
1261 | ebus_path_component(dp, tmp_buf); | ||
1262 | return; | ||
1263 | } | ||
1242 | if (!strcmp(parent->name, "usb") || | 1264 | if (!strcmp(parent->name, "usb") || |
1243 | !strcmp(parent->name, "hub")) | 1265 | !strcmp(parent->name, "hub")) { |
1244 | return usb_path_component(dp, tmp_buf); | 1266 | usb_path_component(dp, tmp_buf); |
1245 | if (!strcmp(parent->type, "i2c")) | 1267 | return; |
1246 | return i2c_path_component(dp, tmp_buf); | 1268 | } |
1247 | if (!strcmp(parent->type, "firewire")) | 1269 | if (!strcmp(parent->type, "i2c")) { |
1248 | return ieee1394_path_component(dp, tmp_buf); | 1270 | i2c_path_component(dp, tmp_buf); |
1249 | if (!strcmp(parent->type, "virtual-devices")) | 1271 | return; |
1250 | return vdev_path_component(dp, tmp_buf); | 1272 | } |
1251 | 1273 | if (!strcmp(parent->type, "firewire")) { | |
1274 | ieee1394_path_component(dp, tmp_buf); | ||
1275 | return; | ||
1276 | } | ||
1277 | if (!strcmp(parent->type, "virtual-devices")) { | ||
1278 | vdev_path_component(dp, tmp_buf); | ||
1279 | return; | ||
1280 | } | ||
1252 | /* "isa" is handled with platform naming */ | 1281 | /* "isa" is handled with platform naming */ |
1253 | } | 1282 | } |
1254 | 1283 | ||
1255 | /* Use platform naming convention. */ | 1284 | /* Use platform naming convention. */ |
1256 | if (tlb_type == hypervisor) | 1285 | if (tlb_type == hypervisor) { |
1257 | return sun4v_path_component(dp, tmp_buf); | 1286 | sun4v_path_component(dp, tmp_buf); |
1258 | else | 1287 | return; |
1259 | return sun4u_path_component(dp, tmp_buf); | 1288 | } else { |
1289 | sun4u_path_component(dp, tmp_buf); | ||
1290 | } | ||
1260 | } | 1291 | } |
1261 | 1292 | ||
1262 | static char * __init build_path_component(struct device_node *dp) | 1293 | static char * __init build_path_component(struct device_node *dp) |
diff --git a/arch/sparc64/kernel/psycho_common.c b/arch/sparc64/kernel/psycho_common.c new file mode 100644 index 000000000000..790996428c14 --- /dev/null +++ b/arch/sparc64/kernel/psycho_common.c | |||
@@ -0,0 +1,470 @@ | |||
1 | /* psycho_common.c: Code common to PSYCHO and derivative PCI controllers. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/interrupt.h> | ||
7 | |||
8 | #include <asm/upa.h> | ||
9 | |||
10 | #include "pci_impl.h" | ||
11 | #include "iommu_common.h" | ||
12 | #include "psycho_common.h" | ||
13 | |||
14 | #define PSYCHO_STRBUF_CTRL_DENAB 0x0000000000000002UL | ||
15 | #define PSYCHO_STCERR_WRITE 0x0000000000000002UL | ||
16 | #define PSYCHO_STCERR_READ 0x0000000000000001UL | ||
17 | #define PSYCHO_STCTAG_PPN 0x0fffffff00000000UL | ||
18 | #define PSYCHO_STCTAG_VPN 0x00000000ffffe000UL | ||
19 | #define PSYCHO_STCTAG_VALID 0x0000000000000002UL | ||
20 | #define PSYCHO_STCTAG_WRITE 0x0000000000000001UL | ||
21 | #define PSYCHO_STCLINE_LINDX 0x0000000001e00000UL | ||
22 | #define PSYCHO_STCLINE_SPTR 0x00000000001f8000UL | ||
23 | #define PSYCHO_STCLINE_LADDR 0x0000000000007f00UL | ||
24 | #define PSYCHO_STCLINE_EPTR 0x00000000000000fcUL | ||
25 | #define PSYCHO_STCLINE_VALID 0x0000000000000002UL | ||
26 | #define PSYCHO_STCLINE_FOFN 0x0000000000000001UL | ||
27 | |||
28 | static DEFINE_SPINLOCK(stc_buf_lock); | ||
29 | static unsigned long stc_error_buf[128]; | ||
30 | static unsigned long stc_tag_buf[16]; | ||
31 | static unsigned long stc_line_buf[16]; | ||
32 | |||
33 | static void psycho_check_stc_error(struct pci_pbm_info *pbm) | ||
34 | { | ||
35 | unsigned long err_base, tag_base, line_base; | ||
36 | struct strbuf *strbuf = &pbm->stc; | ||
37 | u64 control; | ||
38 | int i; | ||
39 | |||
40 | if (!strbuf->strbuf_control) | ||
41 | return; | ||
42 | |||
43 | err_base = strbuf->strbuf_err_stat; | ||
44 | tag_base = strbuf->strbuf_tag_diag; | ||
45 | line_base = strbuf->strbuf_line_diag; | ||
46 | |||
47 | spin_lock(&stc_buf_lock); | ||
48 | |||
49 | /* This is __REALLY__ dangerous. When we put the streaming | ||
50 | * buffer into diagnostic mode to probe it's tags and error | ||
51 | * status, we _must_ clear all of the line tag valid bits | ||
52 | * before re-enabling the streaming buffer. If any dirty data | ||
53 | * lives in the STC when we do this, we will end up | ||
54 | * invalidating it before it has a chance to reach main | ||
55 | * memory. | ||
56 | */ | ||
57 | control = upa_readq(strbuf->strbuf_control); | ||
58 | upa_writeq(control | PSYCHO_STRBUF_CTRL_DENAB, strbuf->strbuf_control); | ||
59 | for (i = 0; i < 128; i++) { | ||
60 | u64 val; | ||
61 | |||
62 | val = upa_readq(err_base + (i * 8UL)); | ||
63 | upa_writeq(0UL, err_base + (i * 8UL)); | ||
64 | stc_error_buf[i] = val; | ||
65 | } | ||
66 | for (i = 0; i < 16; i++) { | ||
67 | stc_tag_buf[i] = upa_readq(tag_base + (i * 8UL)); | ||
68 | stc_line_buf[i] = upa_readq(line_base + (i * 8UL)); | ||
69 | upa_writeq(0UL, tag_base + (i * 8UL)); | ||
70 | upa_writeq(0UL, line_base + (i * 8UL)); | ||
71 | } | ||
72 | |||
73 | /* OK, state is logged, exit diagnostic mode. */ | ||
74 | upa_writeq(control, strbuf->strbuf_control); | ||
75 | |||
76 | for (i = 0; i < 16; i++) { | ||
77 | int j, saw_error, first, last; | ||
78 | |||
79 | saw_error = 0; | ||
80 | first = i * 8; | ||
81 | last = first + 8; | ||
82 | for (j = first; j < last; j++) { | ||
83 | u64 errval = stc_error_buf[j]; | ||
84 | if (errval != 0) { | ||
85 | saw_error++; | ||
86 | printk(KERN_ERR "%s: STC_ERR(%d)[wr(%d)" | ||
87 | "rd(%d)]\n", | ||
88 | pbm->name, | ||
89 | j, | ||
90 | (errval & PSYCHO_STCERR_WRITE) ? 1 : 0, | ||
91 | (errval & PSYCHO_STCERR_READ) ? 1 : 0); | ||
92 | } | ||
93 | } | ||
94 | if (saw_error != 0) { | ||
95 | u64 tagval = stc_tag_buf[i]; | ||
96 | u64 lineval = stc_line_buf[i]; | ||
97 | printk(KERN_ERR "%s: STC_TAG(%d)[PA(%016lx)VA(%08lx)" | ||
98 | "V(%d)W(%d)]\n", | ||
99 | pbm->name, | ||
100 | i, | ||
101 | ((tagval & PSYCHO_STCTAG_PPN) >> 19UL), | ||
102 | (tagval & PSYCHO_STCTAG_VPN), | ||
103 | ((tagval & PSYCHO_STCTAG_VALID) ? 1 : 0), | ||
104 | ((tagval & PSYCHO_STCTAG_WRITE) ? 1 : 0)); | ||
105 | printk(KERN_ERR "%s: STC_LINE(%d)[LIDX(%lx)SP(%lx)" | ||
106 | "LADDR(%lx)EP(%lx)V(%d)FOFN(%d)]\n", | ||
107 | pbm->name, | ||
108 | i, | ||
109 | ((lineval & PSYCHO_STCLINE_LINDX) >> 21UL), | ||
110 | ((lineval & PSYCHO_STCLINE_SPTR) >> 15UL), | ||
111 | ((lineval & PSYCHO_STCLINE_LADDR) >> 8UL), | ||
112 | ((lineval & PSYCHO_STCLINE_EPTR) >> 2UL), | ||
113 | ((lineval & PSYCHO_STCLINE_VALID) ? 1 : 0), | ||
114 | ((lineval & PSYCHO_STCLINE_FOFN) ? 1 : 0)); | ||
115 | } | ||
116 | } | ||
117 | |||
118 | spin_unlock(&stc_buf_lock); | ||
119 | } | ||
120 | |||
121 | #define PSYCHO_IOMMU_TAG 0xa580UL | ||
122 | #define PSYCHO_IOMMU_DATA 0xa600UL | ||
123 | |||
124 | static void psycho_record_iommu_tags_and_data(struct pci_pbm_info *pbm, | ||
125 | u64 *tag, u64 *data) | ||
126 | { | ||
127 | int i; | ||
128 | |||
129 | for (i = 0; i < 16; i++) { | ||
130 | unsigned long base = pbm->controller_regs; | ||
131 | unsigned long off = i * 8UL; | ||
132 | |||
133 | tag[i] = upa_readq(base + PSYCHO_IOMMU_TAG+off); | ||
134 | data[i] = upa_readq(base + PSYCHO_IOMMU_DATA+off); | ||
135 | |||
136 | /* Now clear out the entry. */ | ||
137 | upa_writeq(0, base + PSYCHO_IOMMU_TAG + off); | ||
138 | upa_writeq(0, base + PSYCHO_IOMMU_DATA + off); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | #define PSYCHO_IOMMU_TAG_ERRSTS (0x3UL << 23UL) | ||
143 | #define PSYCHO_IOMMU_TAG_ERR (0x1UL << 22UL) | ||
144 | #define PSYCHO_IOMMU_TAG_WRITE (0x1UL << 21UL) | ||
145 | #define PSYCHO_IOMMU_TAG_STREAM (0x1UL << 20UL) | ||
146 | #define PSYCHO_IOMMU_TAG_SIZE (0x1UL << 19UL) | ||
147 | #define PSYCHO_IOMMU_TAG_VPAGE 0x7ffffUL | ||
148 | #define PSYCHO_IOMMU_DATA_VALID (1UL << 30UL) | ||
149 | #define PSYCHO_IOMMU_DATA_CACHE (1UL << 28UL) | ||
150 | #define PSYCHO_IOMMU_DATA_PPAGE 0xfffffffUL | ||
151 | |||
152 | static void psycho_dump_iommu_tags_and_data(struct pci_pbm_info *pbm, | ||
153 | u64 *tag, u64 *data) | ||
154 | { | ||
155 | int i; | ||
156 | |||
157 | for (i = 0; i < 16; i++) { | ||
158 | u64 tag_val, data_val; | ||
159 | const char *type_str; | ||
160 | tag_val = tag[i]; | ||
161 | if (!(tag_val & PSYCHO_IOMMU_TAG_ERR)) | ||
162 | continue; | ||
163 | |||
164 | data_val = data[i]; | ||
165 | switch((tag_val & PSYCHO_IOMMU_TAG_ERRSTS) >> 23UL) { | ||
166 | case 0: | ||
167 | type_str = "Protection Error"; | ||
168 | break; | ||
169 | case 1: | ||
170 | type_str = "Invalid Error"; | ||
171 | break; | ||
172 | case 2: | ||
173 | type_str = "TimeOut Error"; | ||
174 | break; | ||
175 | case 3: | ||
176 | default: | ||
177 | type_str = "ECC Error"; | ||
178 | break; | ||
179 | } | ||
180 | |||
181 | printk(KERN_ERR "%s: IOMMU TAG(%d)[error(%s) wr(%d) " | ||
182 | "str(%d) sz(%dK) vpg(%08lx)]\n", | ||
183 | pbm->name, i, type_str, | ||
184 | ((tag_val & PSYCHO_IOMMU_TAG_WRITE) ? 1 : 0), | ||
185 | ((tag_val & PSYCHO_IOMMU_TAG_STREAM) ? 1 : 0), | ||
186 | ((tag_val & PSYCHO_IOMMU_TAG_SIZE) ? 64 : 8), | ||
187 | (tag_val & PSYCHO_IOMMU_TAG_VPAGE) << IOMMU_PAGE_SHIFT); | ||
188 | printk(KERN_ERR "%s: IOMMU DATA(%d)[valid(%d) cache(%d) " | ||
189 | "ppg(%016lx)]\n", | ||
190 | pbm->name, i, | ||
191 | ((data_val & PSYCHO_IOMMU_DATA_VALID) ? 1 : 0), | ||
192 | ((data_val & PSYCHO_IOMMU_DATA_CACHE) ? 1 : 0), | ||
193 | (data_val & PSYCHO_IOMMU_DATA_PPAGE)<<IOMMU_PAGE_SHIFT); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | #define PSYCHO_IOMMU_CTRL_XLTESTAT 0x0000000006000000UL | ||
198 | #define PSYCHO_IOMMU_CTRL_XLTEERR 0x0000000001000000UL | ||
199 | |||
200 | void psycho_check_iommu_error(struct pci_pbm_info *pbm, | ||
201 | unsigned long afsr, | ||
202 | unsigned long afar, | ||
203 | enum psycho_error_type type) | ||
204 | { | ||
205 | u64 control, iommu_tag[16], iommu_data[16]; | ||
206 | struct iommu *iommu = pbm->iommu; | ||
207 | unsigned long flags; | ||
208 | |||
209 | spin_lock_irqsave(&iommu->lock, flags); | ||
210 | control = upa_readq(iommu->iommu_control); | ||
211 | if (control & PSYCHO_IOMMU_CTRL_XLTEERR) { | ||
212 | const char *type_str; | ||
213 | |||
214 | control &= ~PSYCHO_IOMMU_CTRL_XLTEERR; | ||
215 | upa_writeq(control, iommu->iommu_control); | ||
216 | |||
217 | switch ((control & PSYCHO_IOMMU_CTRL_XLTESTAT) >> 25UL) { | ||
218 | case 0: | ||
219 | type_str = "Protection Error"; | ||
220 | break; | ||
221 | case 1: | ||
222 | type_str = "Invalid Error"; | ||
223 | break; | ||
224 | case 2: | ||
225 | type_str = "TimeOut Error"; | ||
226 | break; | ||
227 | case 3: | ||
228 | default: | ||
229 | type_str = "ECC Error"; | ||
230 | break; | ||
231 | }; | ||
232 | printk(KERN_ERR "%s: IOMMU Error, type[%s]\n", | ||
233 | pbm->name, type_str); | ||
234 | |||
235 | /* It is very possible for another DVMA to occur while | ||
236 | * we do this probe, and corrupt the system further. | ||
237 | * But we are so screwed at this point that we are | ||
238 | * likely to crash hard anyways, so get as much | ||
239 | * diagnostic information to the console as we can. | ||
240 | */ | ||
241 | psycho_record_iommu_tags_and_data(pbm, iommu_tag, iommu_data); | ||
242 | psycho_dump_iommu_tags_and_data(pbm, iommu_tag, iommu_data); | ||
243 | } | ||
244 | psycho_check_stc_error(pbm); | ||
245 | spin_unlock_irqrestore(&iommu->lock, flags); | ||
246 | } | ||
247 | |||
248 | #define PSYCHO_PCICTRL_SBH_ERR 0x0000000800000000UL | ||
249 | #define PSYCHO_PCICTRL_SERR 0x0000000400000000UL | ||
250 | |||
251 | static irqreturn_t psycho_pcierr_intr_other(struct pci_pbm_info *pbm) | ||
252 | { | ||
253 | irqreturn_t ret = IRQ_NONE; | ||
254 | u64 csr, csr_error_bits; | ||
255 | u16 stat, *addr; | ||
256 | |||
257 | csr = upa_readq(pbm->pci_csr); | ||
258 | csr_error_bits = csr & (PSYCHO_PCICTRL_SBH_ERR | PSYCHO_PCICTRL_SERR); | ||
259 | if (csr_error_bits) { | ||
260 | /* Clear the errors. */ | ||
261 | upa_writeq(csr, pbm->pci_csr); | ||
262 | |||
263 | /* Log 'em. */ | ||
264 | if (csr_error_bits & PSYCHO_PCICTRL_SBH_ERR) | ||
265 | printk(KERN_ERR "%s: PCI streaming byte hole " | ||
266 | "error asserted.\n", pbm->name); | ||
267 | if (csr_error_bits & PSYCHO_PCICTRL_SERR) | ||
268 | printk(KERN_ERR "%s: PCI SERR signal asserted.\n", | ||
269 | pbm->name); | ||
270 | ret = IRQ_HANDLED; | ||
271 | } | ||
272 | addr = psycho_pci_config_mkaddr(pbm, pbm->pci_first_busno, | ||
273 | 0, PCI_STATUS); | ||
274 | pci_config_read16(addr, &stat); | ||
275 | if (stat & (PCI_STATUS_PARITY | | ||
276 | PCI_STATUS_SIG_TARGET_ABORT | | ||
277 | PCI_STATUS_REC_TARGET_ABORT | | ||
278 | PCI_STATUS_REC_MASTER_ABORT | | ||
279 | PCI_STATUS_SIG_SYSTEM_ERROR)) { | ||
280 | printk(KERN_ERR "%s: PCI bus error, PCI_STATUS[%04x]\n", | ||
281 | pbm->name, stat); | ||
282 | pci_config_write16(addr, 0xffff); | ||
283 | ret = IRQ_HANDLED; | ||
284 | } | ||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | #define PSYCHO_PCIAFSR_PMA 0x8000000000000000UL | ||
289 | #define PSYCHO_PCIAFSR_PTA 0x4000000000000000UL | ||
290 | #define PSYCHO_PCIAFSR_PRTRY 0x2000000000000000UL | ||
291 | #define PSYCHO_PCIAFSR_PPERR 0x1000000000000000UL | ||
292 | #define PSYCHO_PCIAFSR_SMA 0x0800000000000000UL | ||
293 | #define PSYCHO_PCIAFSR_STA 0x0400000000000000UL | ||
294 | #define PSYCHO_PCIAFSR_SRTRY 0x0200000000000000UL | ||
295 | #define PSYCHO_PCIAFSR_SPERR 0x0100000000000000UL | ||
296 | #define PSYCHO_PCIAFSR_RESV1 0x00ff000000000000UL | ||
297 | #define PSYCHO_PCIAFSR_BMSK 0x0000ffff00000000UL | ||
298 | #define PSYCHO_PCIAFSR_BLK 0x0000000080000000UL | ||
299 | #define PSYCHO_PCIAFSR_RESV2 0x0000000040000000UL | ||
300 | #define PSYCHO_PCIAFSR_MID 0x000000003e000000UL | ||
301 | #define PSYCHO_PCIAFSR_RESV3 0x0000000001ffffffUL | ||
302 | |||
303 | irqreturn_t psycho_pcierr_intr(int irq, void *dev_id) | ||
304 | { | ||
305 | struct pci_pbm_info *pbm = dev_id; | ||
306 | u64 afsr, afar, error_bits; | ||
307 | int reported; | ||
308 | |||
309 | afsr = upa_readq(pbm->pci_afsr); | ||
310 | afar = upa_readq(pbm->pci_afar); | ||
311 | error_bits = afsr & | ||
312 | (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_PTA | | ||
313 | PSYCHO_PCIAFSR_PRTRY | PSYCHO_PCIAFSR_PPERR | | ||
314 | PSYCHO_PCIAFSR_SMA | PSYCHO_PCIAFSR_STA | | ||
315 | PSYCHO_PCIAFSR_SRTRY | PSYCHO_PCIAFSR_SPERR); | ||
316 | if (!error_bits) | ||
317 | return psycho_pcierr_intr_other(pbm); | ||
318 | upa_writeq(error_bits, pbm->pci_afsr); | ||
319 | printk(KERN_ERR "%s: PCI Error, primary error type[%s]\n", | ||
320 | pbm->name, | ||
321 | (((error_bits & PSYCHO_PCIAFSR_PMA) ? | ||
322 | "Master Abort" : | ||
323 | ((error_bits & PSYCHO_PCIAFSR_PTA) ? | ||
324 | "Target Abort" : | ||
325 | ((error_bits & PSYCHO_PCIAFSR_PRTRY) ? | ||
326 | "Excessive Retries" : | ||
327 | ((error_bits & PSYCHO_PCIAFSR_PPERR) ? | ||
328 | "Parity Error" : "???")))))); | ||
329 | printk(KERN_ERR "%s: bytemask[%04lx] UPA_MID[%02lx] was_block(%d)\n", | ||
330 | pbm->name, | ||
331 | (afsr & PSYCHO_PCIAFSR_BMSK) >> 32UL, | ||
332 | (afsr & PSYCHO_PCIAFSR_MID) >> 25UL, | ||
333 | (afsr & PSYCHO_PCIAFSR_BLK) ? 1 : 0); | ||
334 | printk(KERN_ERR "%s: PCI AFAR [%016lx]\n", pbm->name, afar); | ||
335 | printk(KERN_ERR "%s: PCI Secondary errors [", pbm->name); | ||
336 | reported = 0; | ||
337 | if (afsr & PSYCHO_PCIAFSR_SMA) { | ||
338 | reported++; | ||
339 | printk("(Master Abort)"); | ||
340 | } | ||
341 | if (afsr & PSYCHO_PCIAFSR_STA) { | ||
342 | reported++; | ||
343 | printk("(Target Abort)"); | ||
344 | } | ||
345 | if (afsr & PSYCHO_PCIAFSR_SRTRY) { | ||
346 | reported++; | ||
347 | printk("(Excessive Retries)"); | ||
348 | } | ||
349 | if (afsr & PSYCHO_PCIAFSR_SPERR) { | ||
350 | reported++; | ||
351 | printk("(Parity Error)"); | ||
352 | } | ||
353 | if (!reported) | ||
354 | printk("(none)"); | ||
355 | printk("]\n"); | ||
356 | |||
357 | if (error_bits & (PSYCHO_PCIAFSR_PTA | PSYCHO_PCIAFSR_STA)) { | ||
358 | psycho_check_iommu_error(pbm, afsr, afar, PCI_ERR); | ||
359 | pci_scan_for_target_abort(pbm, pbm->pci_bus); | ||
360 | } | ||
361 | if (error_bits & (PSYCHO_PCIAFSR_PMA | PSYCHO_PCIAFSR_SMA)) | ||
362 | pci_scan_for_master_abort(pbm, pbm->pci_bus); | ||
363 | |||
364 | if (error_bits & (PSYCHO_PCIAFSR_PPERR | PSYCHO_PCIAFSR_SPERR)) | ||
365 | pci_scan_for_parity_error(pbm, pbm->pci_bus); | ||
366 | |||
367 | return IRQ_HANDLED; | ||
368 | } | ||
369 | |||
370 | static void psycho_iommu_flush(struct pci_pbm_info *pbm) | ||
371 | { | ||
372 | int i; | ||
373 | |||
374 | for (i = 0; i < 16; i++) { | ||
375 | unsigned long off = i * 8; | ||
376 | |||
377 | upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_TAG + off); | ||
378 | upa_writeq(0, pbm->controller_regs + PSYCHO_IOMMU_DATA + off); | ||
379 | } | ||
380 | } | ||
381 | |||
382 | #define PSYCHO_IOMMU_CONTROL 0x0200UL | ||
383 | #define PSYCHO_IOMMU_CTRL_TSBSZ 0x0000000000070000UL | ||
384 | #define PSYCHO_IOMMU_TSBSZ_1K 0x0000000000000000UL | ||
385 | #define PSYCHO_IOMMU_TSBSZ_2K 0x0000000000010000UL | ||
386 | #define PSYCHO_IOMMU_TSBSZ_4K 0x0000000000020000UL | ||
387 | #define PSYCHO_IOMMU_TSBSZ_8K 0x0000000000030000UL | ||
388 | #define PSYCHO_IOMMU_TSBSZ_16K 0x0000000000040000UL | ||
389 | #define PSYCHO_IOMMU_TSBSZ_32K 0x0000000000050000UL | ||
390 | #define PSYCHO_IOMMU_TSBSZ_64K 0x0000000000060000UL | ||
391 | #define PSYCHO_IOMMU_TSBSZ_128K 0x0000000000070000UL | ||
392 | #define PSYCHO_IOMMU_CTRL_TBWSZ 0x0000000000000004UL | ||
393 | #define PSYCHO_IOMMU_CTRL_DENAB 0x0000000000000002UL | ||
394 | #define PSYCHO_IOMMU_CTRL_ENAB 0x0000000000000001UL | ||
395 | #define PSYCHO_IOMMU_FLUSH 0x0210UL | ||
396 | #define PSYCHO_IOMMU_TSBBASE 0x0208UL | ||
397 | |||
398 | int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, | ||
399 | u32 dvma_offset, u32 dma_mask, | ||
400 | unsigned long write_complete_offset) | ||
401 | { | ||
402 | struct iommu *iommu = pbm->iommu; | ||
403 | u64 control; | ||
404 | int err; | ||
405 | |||
406 | iommu->iommu_control = pbm->controller_regs + PSYCHO_IOMMU_CONTROL; | ||
407 | iommu->iommu_tsbbase = pbm->controller_regs + PSYCHO_IOMMU_TSBBASE; | ||
408 | iommu->iommu_flush = pbm->controller_regs + PSYCHO_IOMMU_FLUSH; | ||
409 | iommu->iommu_tags = pbm->controller_regs + PSYCHO_IOMMU_TAG; | ||
410 | iommu->write_complete_reg = (pbm->controller_regs + | ||
411 | write_complete_offset); | ||
412 | |||
413 | iommu->iommu_ctxflush = 0; | ||
414 | |||
415 | control = upa_readq(iommu->iommu_control); | ||
416 | control |= PSYCHO_IOMMU_CTRL_DENAB; | ||
417 | upa_writeq(control, iommu->iommu_control); | ||
418 | |||
419 | psycho_iommu_flush(pbm); | ||
420 | |||
421 | /* Leave diag mode enabled for full-flushing done in pci_iommu.c */ | ||
422 | err = iommu_table_init(iommu, tsbsize * 1024 * 8, | ||
423 | dvma_offset, dma_mask, pbm->numa_node); | ||
424 | if (err) | ||
425 | return err; | ||
426 | |||
427 | upa_writeq(__pa(iommu->page_table), iommu->iommu_tsbbase); | ||
428 | |||
429 | control = upa_readq(iommu->iommu_control); | ||
430 | control &= ~(PSYCHO_IOMMU_CTRL_TSBSZ | PSYCHO_IOMMU_CTRL_TBWSZ); | ||
431 | control |= PSYCHO_IOMMU_CTRL_ENAB; | ||
432 | |||
433 | switch (tsbsize) { | ||
434 | case 64: | ||
435 | control |= PSYCHO_IOMMU_TSBSZ_64K; | ||
436 | break; | ||
437 | case 128: | ||
438 | control |= PSYCHO_IOMMU_TSBSZ_128K; | ||
439 | break; | ||
440 | default: | ||
441 | return -EINVAL; | ||
442 | } | ||
443 | |||
444 | upa_writeq(control, iommu->iommu_control); | ||
445 | |||
446 | return 0; | ||
447 | |||
448 | } | ||
449 | |||
450 | void psycho_pbm_init_common(struct pci_pbm_info *pbm, struct of_device *op, | ||
451 | const char *chip_name, int chip_type) | ||
452 | { | ||
453 | struct device_node *dp = op->node; | ||
454 | |||
455 | pbm->name = dp->full_name; | ||
456 | pbm->numa_node = -1; | ||
457 | pbm->chip_type = chip_type; | ||
458 | pbm->chip_version = of_getintprop_default(dp, "version#", 0); | ||
459 | pbm->chip_revision = of_getintprop_default(dp, "module-revision#", 0); | ||
460 | pbm->op = op; | ||
461 | pbm->pci_ops = &sun4u_pci_ops; | ||
462 | pbm->config_space_reg_bits = 8; | ||
463 | pbm->index = pci_num_pbms++; | ||
464 | pci_get_pbm_props(pbm); | ||
465 | pci_determine_mem_io_space(pbm); | ||
466 | |||
467 | printk(KERN_INFO "%s: %s PCI Bus Module ver[%x:%x]\n", | ||
468 | pbm->name, chip_name, | ||
469 | pbm->chip_version, pbm->chip_revision); | ||
470 | } | ||
diff --git a/arch/sparc64/kernel/psycho_common.h b/arch/sparc64/kernel/psycho_common.h new file mode 100644 index 000000000000..092c278ef28d --- /dev/null +++ b/arch/sparc64/kernel/psycho_common.h | |||
@@ -0,0 +1,48 @@ | |||
1 | #ifndef _PSYCHO_COMMON_H | ||
2 | #define _PSYCHO_COMMON_H | ||
3 | |||
4 | /* U2P Programmer's Manual, page 13-55, configuration space | ||
5 | * address format: | ||
6 | * | ||
7 | * 32 24 23 16 15 11 10 8 7 2 1 0 | ||
8 | * --------------------------------------------------------- | ||
9 | * |0 0 0 0 0 0 0 0 1| bus | device | function | reg | 0 0 | | ||
10 | * --------------------------------------------------------- | ||
11 | */ | ||
12 | #define PSYCHO_CONFIG_BASE(PBM) \ | ||
13 | ((PBM)->config_space | (1UL << 24)) | ||
14 | #define PSYCHO_CONFIG_ENCODE(BUS, DEVFN, REG) \ | ||
15 | (((unsigned long)(BUS) << 16) | \ | ||
16 | ((unsigned long)(DEVFN) << 8) | \ | ||
17 | ((unsigned long)(REG))) | ||
18 | |||
19 | static inline void *psycho_pci_config_mkaddr(struct pci_pbm_info *pbm, | ||
20 | unsigned char bus, | ||
21 | unsigned int devfn, | ||
22 | int where) | ||
23 | { | ||
24 | return (void *) | ||
25 | (PSYCHO_CONFIG_BASE(pbm) | | ||
26 | PSYCHO_CONFIG_ENCODE(bus, devfn, where)); | ||
27 | } | ||
28 | |||
29 | enum psycho_error_type { | ||
30 | UE_ERR, CE_ERR, PCI_ERR | ||
31 | }; | ||
32 | |||
33 | extern void psycho_check_iommu_error(struct pci_pbm_info *pbm, | ||
34 | unsigned long afsr, | ||
35 | unsigned long afar, | ||
36 | enum psycho_error_type type); | ||
37 | |||
38 | extern irqreturn_t psycho_pcierr_intr(int irq, void *dev_id); | ||
39 | |||
40 | extern int psycho_iommu_init(struct pci_pbm_info *pbm, int tsbsize, | ||
41 | u32 dvma_offset, u32 dma_mask, | ||
42 | unsigned long write_complete_offset); | ||
43 | |||
44 | extern void psycho_pbm_init_common(struct pci_pbm_info *pbm, | ||
45 | struct of_device *op, | ||
46 | const char *chip_name, int chip_type); | ||
47 | |||
48 | #endif /* _PSYCHO_COMMON_H */ | ||
diff --git a/arch/sparc64/kernel/ptrace.c b/arch/sparc64/kernel/ptrace.c index 10306e476e38..f43adbc773ca 100644 --- a/arch/sparc64/kernel/ptrace.c +++ b/arch/sparc64/kernel/ptrace.c | |||
@@ -1050,31 +1050,17 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
1050 | return ret; | 1050 | return ret; |
1051 | } | 1051 | } |
1052 | 1052 | ||
1053 | asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p) | 1053 | asmlinkage int syscall_trace_enter(struct pt_regs *regs) |
1054 | { | 1054 | { |
1055 | int ret = 0; | 1055 | int ret = 0; |
1056 | 1056 | ||
1057 | /* do the secure computing check first */ | 1057 | /* do the secure computing check first */ |
1058 | secure_computing(regs->u_regs[UREG_G1]); | 1058 | secure_computing(regs->u_regs[UREG_G1]); |
1059 | 1059 | ||
1060 | if (unlikely(current->audit_context) && syscall_exit_p) { | 1060 | if (test_thread_flag(TIF_SYSCALL_TRACE)) |
1061 | unsigned long tstate = regs->tstate; | 1061 | ret = tracehook_report_syscall_entry(regs); |
1062 | int result = AUDITSC_SUCCESS; | ||
1063 | |||
1064 | if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) | ||
1065 | result = AUDITSC_FAILURE; | ||
1066 | |||
1067 | audit_syscall_exit(result, regs->u_regs[UREG_I0]); | ||
1068 | } | ||
1069 | |||
1070 | if (test_thread_flag(TIF_SYSCALL_TRACE)) { | ||
1071 | if (syscall_exit_p) | ||
1072 | tracehook_report_syscall_exit(regs, 0); | ||
1073 | else | ||
1074 | ret = tracehook_report_syscall_entry(regs); | ||
1075 | } | ||
1076 | 1062 | ||
1077 | if (unlikely(current->audit_context) && !syscall_exit_p && !ret) | 1063 | if (unlikely(current->audit_context) && !ret) |
1078 | audit_syscall_entry((test_thread_flag(TIF_32BIT) ? | 1064 | audit_syscall_entry((test_thread_flag(TIF_32BIT) ? |
1079 | AUDIT_ARCH_SPARC : | 1065 | AUDIT_ARCH_SPARC : |
1080 | AUDIT_ARCH_SPARC64), | 1066 | AUDIT_ARCH_SPARC64), |
@@ -1086,3 +1072,19 @@ asmlinkage int syscall_trace(struct pt_regs *regs, int syscall_exit_p) | |||
1086 | 1072 | ||
1087 | return ret; | 1073 | return ret; |
1088 | } | 1074 | } |
1075 | |||
1076 | asmlinkage void syscall_trace_leave(struct pt_regs *regs) | ||
1077 | { | ||
1078 | if (unlikely(current->audit_context)) { | ||
1079 | unsigned long tstate = regs->tstate; | ||
1080 | int result = AUDITSC_SUCCESS; | ||
1081 | |||
1082 | if (unlikely(tstate & (TSTATE_XCARRY | TSTATE_ICARRY))) | ||
1083 | result = AUDITSC_FAILURE; | ||
1084 | |||
1085 | audit_syscall_exit(result, regs->u_regs[UREG_I0]); | ||
1086 | } | ||
1087 | |||
1088 | if (test_thread_flag(TIF_SYSCALL_TRACE)) | ||
1089 | tracehook_report_syscall_exit(regs, 0); | ||
1090 | } | ||
diff --git a/arch/sparc64/kernel/reboot.c b/arch/sparc64/kernel/reboot.c new file mode 100644 index 000000000000..ef89d3d69748 --- /dev/null +++ b/arch/sparc64/kernel/reboot.c | |||
@@ -0,0 +1,53 @@ | |||
1 | /* reboot.c: reboot/shutdown/halt/poweroff handling | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | #include <linux/kernel.h> | ||
6 | #include <linux/reboot.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/pm.h> | ||
9 | |||
10 | #include <asm/system.h> | ||
11 | #include <asm/oplib.h> | ||
12 | #include <asm/prom.h> | ||
13 | |||
14 | /* sysctl - toggle power-off restriction for serial console | ||
15 | * systems in machine_power_off() | ||
16 | */ | ||
17 | int scons_pwroff = 1; | ||
18 | |||
19 | /* This isn't actually used, it exists merely to satisfy the | ||
20 | * reference in kernel/sys.c | ||
21 | */ | ||
22 | void (*pm_power_off)(void) = machine_power_off; | ||
23 | EXPORT_SYMBOL(pm_power_off); | ||
24 | |||
25 | void machine_power_off(void) | ||
26 | { | ||
27 | if (strcmp(of_console_device->type, "serial") || scons_pwroff) | ||
28 | prom_halt_power_off(); | ||
29 | |||
30 | prom_halt(); | ||
31 | } | ||
32 | |||
33 | void machine_halt(void) | ||
34 | { | ||
35 | prom_halt(); | ||
36 | panic("Halt failed!"); | ||
37 | } | ||
38 | |||
39 | void machine_restart(char *cmd) | ||
40 | { | ||
41 | char *p; | ||
42 | |||
43 | p = strchr(reboot_command, '\n'); | ||
44 | if (p) | ||
45 | *p = 0; | ||
46 | if (cmd) | ||
47 | prom_reboot(cmd); | ||
48 | if (*reboot_command) | ||
49 | prom_reboot(reboot_command); | ||
50 | prom_reboot(""); | ||
51 | panic("Reboot failed!"); | ||
52 | } | ||
53 | |||
diff --git a/arch/sparc64/kernel/sbus.c b/arch/sparc64/kernel/sbus.c index e33a8a660e9e..2ead310066d1 100644 --- a/arch/sparc64/kernel/sbus.c +++ b/arch/sparc64/kernel/sbus.c | |||
@@ -11,15 +11,17 @@ | |||
11 | #include <linux/slab.h> | 11 | #include <linux/slab.h> |
12 | #include <linux/init.h> | 12 | #include <linux/init.h> |
13 | #include <linux/interrupt.h> | 13 | #include <linux/interrupt.h> |
14 | #include <linux/of.h> | ||
15 | #include <linux/of_device.h> | ||
14 | 16 | ||
15 | #include <asm/page.h> | 17 | #include <asm/page.h> |
16 | #include <asm/sbus.h> | ||
17 | #include <asm/io.h> | 18 | #include <asm/io.h> |
18 | #include <asm/upa.h> | 19 | #include <asm/upa.h> |
19 | #include <asm/cache.h> | 20 | #include <asm/cache.h> |
20 | #include <asm/dma.h> | 21 | #include <asm/dma.h> |
21 | #include <asm/irq.h> | 22 | #include <asm/irq.h> |
22 | #include <asm/prom.h> | 23 | #include <asm/prom.h> |
24 | #include <asm/oplib.h> | ||
23 | #include <asm/starfire.h> | 25 | #include <asm/starfire.h> |
24 | 26 | ||
25 | #include "iommu_common.h" | 27 | #include "iommu_common.h" |
@@ -52,13 +54,23 @@ | |||
52 | #define STRBUF_TAG_VALID 0x02UL | 54 | #define STRBUF_TAG_VALID 0x02UL |
53 | 55 | ||
54 | /* Enable 64-bit DVMA mode for the given device. */ | 56 | /* Enable 64-bit DVMA mode for the given device. */ |
55 | void sbus_set_sbus64(struct sbus_dev *sdev, int bursts) | 57 | void sbus_set_sbus64(struct device *dev, int bursts) |
56 | { | 58 | { |
57 | struct iommu *iommu = sdev->ofdev.dev.archdata.iommu; | 59 | struct iommu *iommu = dev->archdata.iommu; |
58 | int slot = sdev->slot; | 60 | struct of_device *op = to_of_device(dev); |
61 | const struct linux_prom_registers *regs; | ||
59 | unsigned long cfg_reg; | 62 | unsigned long cfg_reg; |
63 | int slot; | ||
60 | u64 val; | 64 | u64 val; |
61 | 65 | ||
66 | regs = of_get_property(op->node, "reg", NULL); | ||
67 | if (!regs) { | ||
68 | printk(KERN_ERR "sbus_set_sbus64: Cannot find regs for %s\n", | ||
69 | op->node->full_name); | ||
70 | return; | ||
71 | } | ||
72 | slot = regs->which_io; | ||
73 | |||
62 | cfg_reg = iommu->write_complete_reg; | 74 | cfg_reg = iommu->write_complete_reg; |
63 | switch (slot) { | 75 | switch (slot) { |
64 | case 0: | 76 | case 0: |
@@ -191,10 +203,9 @@ static unsigned long sysio_imap_to_iclr(unsigned long imap) | |||
191 | return imap + diff; | 203 | return imap + diff; |
192 | } | 204 | } |
193 | 205 | ||
194 | unsigned int sbus_build_irq(void *buscookie, unsigned int ino) | 206 | static unsigned int sbus_build_irq(struct of_device *op, unsigned int ino) |
195 | { | 207 | { |
196 | struct sbus_bus *sbus = (struct sbus_bus *)buscookie; | 208 | struct iommu *iommu = op->dev.archdata.iommu; |
197 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | ||
198 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 209 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
199 | unsigned long imap, iclr; | 210 | unsigned long imap, iclr; |
200 | int sbus_level = 0; | 211 | int sbus_level = 0; |
@@ -255,12 +266,12 @@ unsigned int sbus_build_irq(void *buscookie, unsigned int ino) | |||
255 | #define SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ | 266 | #define SYSIO_UEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ |
256 | static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | 267 | static irqreturn_t sysio_ue_handler(int irq, void *dev_id) |
257 | { | 268 | { |
258 | struct sbus_bus *sbus = dev_id; | 269 | struct of_device *op = dev_id; |
259 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 270 | struct iommu *iommu = op->dev.archdata.iommu; |
260 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 271 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
261 | unsigned long afsr_reg, afar_reg; | 272 | unsigned long afsr_reg, afar_reg; |
262 | unsigned long afsr, afar, error_bits; | 273 | unsigned long afsr, afar, error_bits; |
263 | int reported; | 274 | int reported, portid; |
264 | 275 | ||
265 | afsr_reg = reg_base + SYSIO_UE_AFSR; | 276 | afsr_reg = reg_base + SYSIO_UE_AFSR; |
266 | afar_reg = reg_base + SYSIO_UE_AFAR; | 277 | afar_reg = reg_base + SYSIO_UE_AFAR; |
@@ -275,9 +286,11 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | |||
275 | SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR); | 286 | SYSIO_UEAFSR_SPIO | SYSIO_UEAFSR_SDRD | SYSIO_UEAFSR_SDWR); |
276 | upa_writeq(error_bits, afsr_reg); | 287 | upa_writeq(error_bits, afsr_reg); |
277 | 288 | ||
289 | portid = of_getintprop_default(op->node, "portid", -1); | ||
290 | |||
278 | /* Log the error. */ | 291 | /* Log the error. */ |
279 | printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n", | 292 | printk("SYSIO[%x]: Uncorrectable ECC Error, primary error type[%s]\n", |
280 | sbus->portid, | 293 | portid, |
281 | (((error_bits & SYSIO_UEAFSR_PPIO) ? | 294 | (((error_bits & SYSIO_UEAFSR_PPIO) ? |
282 | "PIO" : | 295 | "PIO" : |
283 | ((error_bits & SYSIO_UEAFSR_PDRD) ? | 296 | ((error_bits & SYSIO_UEAFSR_PDRD) ? |
@@ -285,12 +298,12 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | |||
285 | ((error_bits & SYSIO_UEAFSR_PDWR) ? | 298 | ((error_bits & SYSIO_UEAFSR_PDWR) ? |
286 | "DVMA Write" : "???"))))); | 299 | "DVMA Write" : "???"))))); |
287 | printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n", | 300 | printk("SYSIO[%x]: DOFF[%lx] SIZE[%lx] MID[%lx]\n", |
288 | sbus->portid, | 301 | portid, |
289 | (afsr & SYSIO_UEAFSR_DOFF) >> 45UL, | 302 | (afsr & SYSIO_UEAFSR_DOFF) >> 45UL, |
290 | (afsr & SYSIO_UEAFSR_SIZE) >> 42UL, | 303 | (afsr & SYSIO_UEAFSR_SIZE) >> 42UL, |
291 | (afsr & SYSIO_UEAFSR_MID) >> 37UL); | 304 | (afsr & SYSIO_UEAFSR_MID) >> 37UL); |
292 | printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); | 305 | printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); |
293 | printk("SYSIO[%x]: Secondary UE errors [", sbus->portid); | 306 | printk("SYSIO[%x]: Secondary UE errors [", portid); |
294 | reported = 0; | 307 | reported = 0; |
295 | if (afsr & SYSIO_UEAFSR_SPIO) { | 308 | if (afsr & SYSIO_UEAFSR_SPIO) { |
296 | reported++; | 309 | reported++; |
@@ -327,12 +340,12 @@ static irqreturn_t sysio_ue_handler(int irq, void *dev_id) | |||
327 | #define SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ | 340 | #define SYSIO_CEAFSR_RESV2 0x0000001fffffffffUL /* Reserved */ |
328 | static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | 341 | static irqreturn_t sysio_ce_handler(int irq, void *dev_id) |
329 | { | 342 | { |
330 | struct sbus_bus *sbus = dev_id; | 343 | struct of_device *op = dev_id; |
331 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 344 | struct iommu *iommu = op->dev.archdata.iommu; |
332 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 345 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
333 | unsigned long afsr_reg, afar_reg; | 346 | unsigned long afsr_reg, afar_reg; |
334 | unsigned long afsr, afar, error_bits; | 347 | unsigned long afsr, afar, error_bits; |
335 | int reported; | 348 | int reported, portid; |
336 | 349 | ||
337 | afsr_reg = reg_base + SYSIO_CE_AFSR; | 350 | afsr_reg = reg_base + SYSIO_CE_AFSR; |
338 | afar_reg = reg_base + SYSIO_CE_AFAR; | 351 | afar_reg = reg_base + SYSIO_CE_AFAR; |
@@ -347,8 +360,10 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | |||
347 | SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR); | 360 | SYSIO_CEAFSR_SPIO | SYSIO_CEAFSR_SDRD | SYSIO_CEAFSR_SDWR); |
348 | upa_writeq(error_bits, afsr_reg); | 361 | upa_writeq(error_bits, afsr_reg); |
349 | 362 | ||
363 | portid = of_getintprop_default(op->node, "portid", -1); | ||
364 | |||
350 | printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n", | 365 | printk("SYSIO[%x]: Correctable ECC Error, primary error type[%s]\n", |
351 | sbus->portid, | 366 | portid, |
352 | (((error_bits & SYSIO_CEAFSR_PPIO) ? | 367 | (((error_bits & SYSIO_CEAFSR_PPIO) ? |
353 | "PIO" : | 368 | "PIO" : |
354 | ((error_bits & SYSIO_CEAFSR_PDRD) ? | 369 | ((error_bits & SYSIO_CEAFSR_PDRD) ? |
@@ -360,14 +375,14 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | |||
360 | * XXX UDB CE trap handler does... -DaveM | 375 | * XXX UDB CE trap handler does... -DaveM |
361 | */ | 376 | */ |
362 | printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n", | 377 | printk("SYSIO[%x]: DOFF[%lx] ECC Syndrome[%lx] Size[%lx] MID[%lx]\n", |
363 | sbus->portid, | 378 | portid, |
364 | (afsr & SYSIO_CEAFSR_DOFF) >> 45UL, | 379 | (afsr & SYSIO_CEAFSR_DOFF) >> 45UL, |
365 | (afsr & SYSIO_CEAFSR_ESYND) >> 48UL, | 380 | (afsr & SYSIO_CEAFSR_ESYND) >> 48UL, |
366 | (afsr & SYSIO_CEAFSR_SIZE) >> 42UL, | 381 | (afsr & SYSIO_CEAFSR_SIZE) >> 42UL, |
367 | (afsr & SYSIO_CEAFSR_MID) >> 37UL); | 382 | (afsr & SYSIO_CEAFSR_MID) >> 37UL); |
368 | printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); | 383 | printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); |
369 | 384 | ||
370 | printk("SYSIO[%x]: Secondary CE errors [", sbus->portid); | 385 | printk("SYSIO[%x]: Secondary CE errors [", portid); |
371 | reported = 0; | 386 | reported = 0; |
372 | if (afsr & SYSIO_CEAFSR_SPIO) { | 387 | if (afsr & SYSIO_CEAFSR_SPIO) { |
373 | reported++; | 388 | reported++; |
@@ -404,11 +419,11 @@ static irqreturn_t sysio_ce_handler(int irq, void *dev_id) | |||
404 | #define SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved */ | 419 | #define SYSIO_SBAFSR_RESV3 0x0000001fffffffffUL /* Reserved */ |
405 | static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | 420 | static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) |
406 | { | 421 | { |
407 | struct sbus_bus *sbus = dev_id; | 422 | struct of_device *op = dev_id; |
408 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 423 | struct iommu *iommu = op->dev.archdata.iommu; |
409 | unsigned long afsr_reg, afar_reg, reg_base; | 424 | unsigned long afsr_reg, afar_reg, reg_base; |
410 | unsigned long afsr, afar, error_bits; | 425 | unsigned long afsr, afar, error_bits; |
411 | int reported; | 426 | int reported, portid; |
412 | 427 | ||
413 | reg_base = iommu->write_complete_reg - 0x2000UL; | 428 | reg_base = iommu->write_complete_reg - 0x2000UL; |
414 | afsr_reg = reg_base + SYSIO_SBUS_AFSR; | 429 | afsr_reg = reg_base + SYSIO_SBUS_AFSR; |
@@ -423,9 +438,11 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | |||
423 | SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR); | 438 | SYSIO_SBAFSR_SLE | SYSIO_SBAFSR_STO | SYSIO_SBAFSR_SBERR); |
424 | upa_writeq(error_bits, afsr_reg); | 439 | upa_writeq(error_bits, afsr_reg); |
425 | 440 | ||
441 | portid = of_getintprop_default(op->node, "portid", -1); | ||
442 | |||
426 | /* Log the error. */ | 443 | /* Log the error. */ |
427 | printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n", | 444 | printk("SYSIO[%x]: SBUS Error, primary error type[%s] read(%d)\n", |
428 | sbus->portid, | 445 | portid, |
429 | (((error_bits & SYSIO_SBAFSR_PLE) ? | 446 | (((error_bits & SYSIO_SBAFSR_PLE) ? |
430 | "Late PIO Error" : | 447 | "Late PIO Error" : |
431 | ((error_bits & SYSIO_SBAFSR_PTO) ? | 448 | ((error_bits & SYSIO_SBAFSR_PTO) ? |
@@ -434,11 +451,11 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | |||
434 | "Error Ack" : "???")))), | 451 | "Error Ack" : "???")))), |
435 | (afsr & SYSIO_SBAFSR_RD) ? 1 : 0); | 452 | (afsr & SYSIO_SBAFSR_RD) ? 1 : 0); |
436 | printk("SYSIO[%x]: size[%lx] MID[%lx]\n", | 453 | printk("SYSIO[%x]: size[%lx] MID[%lx]\n", |
437 | sbus->portid, | 454 | portid, |
438 | (afsr & SYSIO_SBAFSR_SIZE) >> 42UL, | 455 | (afsr & SYSIO_SBAFSR_SIZE) >> 42UL, |
439 | (afsr & SYSIO_SBAFSR_MID) >> 37UL); | 456 | (afsr & SYSIO_SBAFSR_MID) >> 37UL); |
440 | printk("SYSIO[%x]: AFAR[%016lx]\n", sbus->portid, afar); | 457 | printk("SYSIO[%x]: AFAR[%016lx]\n", portid, afar); |
441 | printk("SYSIO[%x]: Secondary SBUS errors [", sbus->portid); | 458 | printk("SYSIO[%x]: Secondary SBUS errors [", portid); |
442 | reported = 0; | 459 | reported = 0; |
443 | if (afsr & SYSIO_SBAFSR_SLE) { | 460 | if (afsr & SYSIO_SBAFSR_SLE) { |
444 | reported++; | 461 | reported++; |
@@ -470,34 +487,37 @@ static irqreturn_t sysio_sbus_error_handler(int irq, void *dev_id) | |||
470 | #define SYSIO_CE_INO 0x35 | 487 | #define SYSIO_CE_INO 0x35 |
471 | #define SYSIO_SBUSERR_INO 0x36 | 488 | #define SYSIO_SBUSERR_INO 0x36 |
472 | 489 | ||
473 | static void __init sysio_register_error_handlers(struct sbus_bus *sbus) | 490 | static void __init sysio_register_error_handlers(struct of_device *op) |
474 | { | 491 | { |
475 | struct iommu *iommu = sbus->ofdev.dev.archdata.iommu; | 492 | struct iommu *iommu = op->dev.archdata.iommu; |
476 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; | 493 | unsigned long reg_base = iommu->write_complete_reg - 0x2000UL; |
477 | unsigned int irq; | 494 | unsigned int irq; |
478 | u64 control; | 495 | u64 control; |
496 | int portid; | ||
497 | |||
498 | portid = of_getintprop_default(op->node, "portid", -1); | ||
479 | 499 | ||
480 | irq = sbus_build_irq(sbus, SYSIO_UE_INO); | 500 | irq = sbus_build_irq(op, SYSIO_UE_INO); |
481 | if (request_irq(irq, sysio_ue_handler, 0, | 501 | if (request_irq(irq, sysio_ue_handler, 0, |
482 | "SYSIO_UE", sbus) < 0) { | 502 | "SYSIO_UE", op) < 0) { |
483 | prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", | 503 | prom_printf("SYSIO[%x]: Cannot register UE interrupt.\n", |
484 | sbus->portid); | 504 | portid); |
485 | prom_halt(); | 505 | prom_halt(); |
486 | } | 506 | } |
487 | 507 | ||
488 | irq = sbus_build_irq(sbus, SYSIO_CE_INO); | 508 | irq = sbus_build_irq(op, SYSIO_CE_INO); |
489 | if (request_irq(irq, sysio_ce_handler, 0, | 509 | if (request_irq(irq, sysio_ce_handler, 0, |
490 | "SYSIO_CE", sbus) < 0) { | 510 | "SYSIO_CE", op) < 0) { |
491 | prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", | 511 | prom_printf("SYSIO[%x]: Cannot register CE interrupt.\n", |
492 | sbus->portid); | 512 | portid); |
493 | prom_halt(); | 513 | prom_halt(); |
494 | } | 514 | } |
495 | 515 | ||
496 | irq = sbus_build_irq(sbus, SYSIO_SBUSERR_INO); | 516 | irq = sbus_build_irq(op, SYSIO_SBUSERR_INO); |
497 | if (request_irq(irq, sysio_sbus_error_handler, 0, | 517 | if (request_irq(irq, sysio_sbus_error_handler, 0, |
498 | "SYSIO_SBERR", sbus) < 0) { | 518 | "SYSIO_SBERR", op) < 0) { |
499 | prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", | 519 | prom_printf("SYSIO[%x]: Cannot register SBUS Error interrupt.\n", |
500 | sbus->portid); | 520 | portid); |
501 | prom_halt(); | 521 | prom_halt(); |
502 | } | 522 | } |
503 | 523 | ||
@@ -513,19 +533,15 @@ static void __init sysio_register_error_handlers(struct sbus_bus *sbus) | |||
513 | } | 533 | } |
514 | 534 | ||
515 | /* Boot time initialization. */ | 535 | /* Boot time initialization. */ |
516 | static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | 536 | static void __init sbus_iommu_init(struct of_device *op) |
517 | { | 537 | { |
518 | const struct linux_prom64_registers *pr; | 538 | const struct linux_prom64_registers *pr; |
519 | struct device_node *dp; | 539 | struct device_node *dp = op->node; |
520 | struct iommu *iommu; | 540 | struct iommu *iommu; |
521 | struct strbuf *strbuf; | 541 | struct strbuf *strbuf; |
522 | unsigned long regs, reg_base; | 542 | unsigned long regs, reg_base; |
543 | int i, portid; | ||
523 | u64 control; | 544 | u64 control; |
524 | int i; | ||
525 | |||
526 | dp = of_find_node_by_phandle(__node); | ||
527 | |||
528 | sbus->portid = of_getintprop_default(dp, "upa-portid", -1); | ||
529 | 545 | ||
530 | pr = of_get_property(dp, "reg", NULL); | 546 | pr = of_get_property(dp, "reg", NULL); |
531 | if (!pr) { | 547 | if (!pr) { |
@@ -542,9 +558,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
542 | if (!strbuf) | 558 | if (!strbuf) |
543 | goto fatal_memory_error; | 559 | goto fatal_memory_error; |
544 | 560 | ||
545 | sbus->ofdev.dev.archdata.iommu = iommu; | 561 | op->dev.archdata.iommu = iommu; |
546 | sbus->ofdev.dev.archdata.stc = strbuf; | 562 | op->dev.archdata.stc = strbuf; |
547 | sbus->ofdev.dev.archdata.numa_node = -1; | 563 | op->dev.archdata.numa_node = -1; |
548 | 564 | ||
549 | reg_base = regs + SYSIO_IOMMUREG_BASE; | 565 | reg_base = regs + SYSIO_IOMMUREG_BASE; |
550 | iommu->iommu_control = reg_base + IOMMU_CONTROL; | 566 | iommu->iommu_control = reg_base + IOMMU_CONTROL; |
@@ -572,8 +588,9 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
572 | */ | 588 | */ |
573 | iommu->write_complete_reg = regs + 0x2000UL; | 589 | iommu->write_complete_reg = regs + 0x2000UL; |
574 | 590 | ||
575 | printk("SYSIO: UPA portID %x, at %016lx\n", | 591 | portid = of_getintprop_default(op->node, "portid", -1); |
576 | sbus->portid, regs); | 592 | printk(KERN_INFO "SYSIO: UPA portID %x, at %016lx\n", |
593 | portid, regs); | ||
577 | 594 | ||
578 | /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ | 595 | /* Setup for TSB_SIZE=7, TBW_SIZE=0, MMU_DE=1, MMU_EN=1 */ |
579 | if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1)) | 596 | if (iommu_table_init(iommu, IO_TSB_SIZE, MAP_BASE, 0xffffffff, -1)) |
@@ -631,56 +648,27 @@ static void __init sbus_iommu_init(int __node, struct sbus_bus *sbus) | |||
631 | 648 | ||
632 | /* Now some Xfire specific grot... */ | 649 | /* Now some Xfire specific grot... */ |
633 | if (this_is_starfire) | 650 | if (this_is_starfire) |
634 | starfire_hookup(sbus->portid); | 651 | starfire_hookup(portid); |
635 | 652 | ||
636 | sysio_register_error_handlers(sbus); | 653 | sysio_register_error_handlers(op); |
637 | return; | 654 | return; |
638 | 655 | ||
639 | fatal_memory_error: | 656 | fatal_memory_error: |
640 | prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); | 657 | prom_printf("sbus_iommu_init: Fatal memory allocation error.\n"); |
641 | } | 658 | } |
642 | 659 | ||
643 | void sbus_fill_device_irq(struct sbus_dev *sdev) | 660 | static int __init sbus_init(void) |
644 | { | 661 | { |
645 | struct device_node *dp = of_find_node_by_phandle(sdev->prom_node); | 662 | struct device_node *dp; |
646 | const struct linux_prom_irqs *irqs; | ||
647 | |||
648 | irqs = of_get_property(dp, "interrupts", NULL); | ||
649 | if (!irqs) { | ||
650 | sdev->irqs[0] = 0; | ||
651 | sdev->num_irqs = 0; | ||
652 | } else { | ||
653 | unsigned int pri = irqs[0].pri; | ||
654 | 663 | ||
655 | sdev->num_irqs = 1; | 664 | for_each_node_by_name(dp, "sbus") { |
656 | if (pri < 0x20) | 665 | struct of_device *op = of_find_device_by_node(dp); |
657 | pri += sdev->slot * 8; | ||
658 | 666 | ||
659 | sdev->irqs[0] = sbus_build_irq(sdev->bus, pri); | 667 | sbus_iommu_init(op); |
668 | of_propagate_archdata(op); | ||
660 | } | 669 | } |
661 | } | ||
662 | 670 | ||
663 | void __init sbus_arch_bus_ranges_init(struct device_node *pn, struct sbus_bus *sbus) | ||
664 | { | ||
665 | } | ||
666 | |||
667 | void __init sbus_setup_iommu(struct sbus_bus *sbus, struct device_node *dp) | ||
668 | { | ||
669 | sbus_iommu_init(dp->node, sbus); | ||
670 | } | ||
671 | |||
672 | void __init sbus_setup_arch_props(struct sbus_bus *sbus, struct device_node *dp) | ||
673 | { | ||
674 | } | ||
675 | |||
676 | int __init sbus_arch_preinit(void) | ||
677 | { | ||
678 | return 0; | 671 | return 0; |
679 | } | 672 | } |
680 | 673 | ||
681 | void __init sbus_arch_postinit(void) | 674 | subsys_initcall(sbus_init); |
682 | { | ||
683 | extern void firetruck_init(void); | ||
684 | |||
685 | firetruck_init(); | ||
686 | } | ||
diff --git a/arch/sparc64/kernel/sparc64_ksyms.c b/arch/sparc64/kernel/sparc64_ksyms.c index 0804f71df6cb..30bba8b0a3b0 100644 --- a/arch/sparc64/kernel/sparc64_ksyms.c +++ b/arch/sparc64/kernel/sparc64_ksyms.c | |||
@@ -36,7 +36,6 @@ | |||
36 | #include <asm/elf.h> | 36 | #include <asm/elf.h> |
37 | #include <asm/head.h> | 37 | #include <asm/head.h> |
38 | #include <asm/smp.h> | 38 | #include <asm/smp.h> |
39 | #include <asm/mostek.h> | ||
40 | #include <asm/ptrace.h> | 39 | #include <asm/ptrace.h> |
41 | #include <asm/uaccess.h> | 40 | #include <asm/uaccess.h> |
42 | #include <asm/checksum.h> | 41 | #include <asm/checksum.h> |
@@ -44,12 +43,8 @@ | |||
44 | #include <asm/pgalloc.h> | 43 | #include <asm/pgalloc.h> |
45 | #include <asm/cacheflush.h> | 44 | #include <asm/cacheflush.h> |
46 | #ifdef CONFIG_SBUS | 45 | #ifdef CONFIG_SBUS |
47 | #include <asm/sbus.h> | ||
48 | #include <asm/dma.h> | 46 | #include <asm/dma.h> |
49 | #endif | 47 | #endif |
50 | #ifdef CONFIG_PCI | ||
51 | #include <asm/ebus.h> | ||
52 | #endif | ||
53 | #include <asm/ns87303.h> | 48 | #include <asm/ns87303.h> |
54 | #include <asm/timer.h> | 49 | #include <asm/timer.h> |
55 | #include <asm/cpudata.h> | 50 | #include <asm/cpudata.h> |
@@ -68,7 +63,6 @@ extern void *__memscan_zero(void *, size_t); | |||
68 | extern void *__memscan_generic(void *, int, size_t); | 63 | extern void *__memscan_generic(void *, int, size_t); |
69 | extern int __memcmp(const void *, const void *, __kernel_size_t); | 64 | extern int __memcmp(const void *, const void *, __kernel_size_t); |
70 | extern __kernel_size_t strlen(const char *); | 65 | extern __kernel_size_t strlen(const char *); |
71 | extern void syscall_trace(struct pt_regs *, int); | ||
72 | extern void sys_sigsuspend(void); | 66 | extern void sys_sigsuspend(void); |
73 | extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); | 67 | extern int compat_sys_ioctl(unsigned int fd, unsigned int cmd, u32 arg); |
74 | extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); | 68 | extern int (*handle_mathemu)(struct pt_regs *, struct fpustate *); |
@@ -154,26 +148,12 @@ EXPORT_SYMBOL(flush_dcache_page); | |||
154 | EXPORT_SYMBOL(__flush_dcache_range); | 148 | EXPORT_SYMBOL(__flush_dcache_range); |
155 | #endif | 149 | #endif |
156 | 150 | ||
157 | EXPORT_SYMBOL(mostek_lock); | ||
158 | EXPORT_SYMBOL(mstk48t02_regs); | ||
159 | #ifdef CONFIG_SUN_AUXIO | 151 | #ifdef CONFIG_SUN_AUXIO |
160 | EXPORT_SYMBOL(auxio_set_led); | 152 | EXPORT_SYMBOL(auxio_set_led); |
161 | EXPORT_SYMBOL(auxio_set_lte); | 153 | EXPORT_SYMBOL(auxio_set_lte); |
162 | #endif | 154 | #endif |
163 | #ifdef CONFIG_SBUS | 155 | #ifdef CONFIG_SBUS |
164 | EXPORT_SYMBOL(sbus_root); | ||
165 | EXPORT_SYMBOL(dma_chain); | ||
166 | EXPORT_SYMBOL(sbus_set_sbus64); | 156 | EXPORT_SYMBOL(sbus_set_sbus64); |
167 | EXPORT_SYMBOL(sbus_alloc_consistent); | ||
168 | EXPORT_SYMBOL(sbus_free_consistent); | ||
169 | EXPORT_SYMBOL(sbus_map_single); | ||
170 | EXPORT_SYMBOL(sbus_unmap_single); | ||
171 | EXPORT_SYMBOL(sbus_map_sg); | ||
172 | EXPORT_SYMBOL(sbus_unmap_sg); | ||
173 | EXPORT_SYMBOL(sbus_dma_sync_single_for_cpu); | ||
174 | EXPORT_SYMBOL(sbus_dma_sync_single_for_device); | ||
175 | EXPORT_SYMBOL(sbus_dma_sync_sg_for_cpu); | ||
176 | EXPORT_SYMBOL(sbus_dma_sync_sg_for_device); | ||
177 | #endif | 157 | #endif |
178 | EXPORT_SYMBOL(outsb); | 158 | EXPORT_SYMBOL(outsb); |
179 | EXPORT_SYMBOL(outsw); | 159 | EXPORT_SYMBOL(outsw); |
@@ -182,7 +162,6 @@ EXPORT_SYMBOL(insb); | |||
182 | EXPORT_SYMBOL(insw); | 162 | EXPORT_SYMBOL(insw); |
183 | EXPORT_SYMBOL(insl); | 163 | EXPORT_SYMBOL(insl); |
184 | #ifdef CONFIG_PCI | 164 | #ifdef CONFIG_PCI |
185 | EXPORT_SYMBOL(ebus_chain); | ||
186 | EXPORT_SYMBOL(pci_alloc_consistent); | 165 | EXPORT_SYMBOL(pci_alloc_consistent); |
187 | EXPORT_SYMBOL(pci_free_consistent); | 166 | EXPORT_SYMBOL(pci_free_consistent); |
188 | EXPORT_SYMBOL(pci_map_single); | 167 | EXPORT_SYMBOL(pci_map_single); |
@@ -300,3 +279,5 @@ EXPORT_SYMBOL(xor_niagara_2); | |||
300 | EXPORT_SYMBOL(xor_niagara_3); | 279 | EXPORT_SYMBOL(xor_niagara_3); |
301 | EXPORT_SYMBOL(xor_niagara_4); | 280 | EXPORT_SYMBOL(xor_niagara_4); |
302 | EXPORT_SYMBOL(xor_niagara_5); | 281 | EXPORT_SYMBOL(xor_niagara_5); |
282 | |||
283 | EXPORT_SYMBOL_GPL(real_hard_smp_processor_id); | ||
diff --git a/arch/sparc64/kernel/sstate.c b/arch/sparc64/kernel/sstate.c index 5b6e75b7f052..8cdbe5946b43 100644 --- a/arch/sparc64/kernel/sstate.c +++ b/arch/sparc64/kernel/sstate.c | |||
@@ -1,14 +1,15 @@ | |||
1 | /* sstate.c: System soft state support. | 1 | /* sstate.c: System soft state support. |
2 | * | 2 | * |
3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
7 | #include <linux/notifier.h> | 7 | #include <linux/notifier.h> |
8 | #include <linux/reboot.h> | ||
8 | #include <linux/init.h> | 9 | #include <linux/init.h> |
9 | 10 | ||
10 | #include <asm/hypervisor.h> | 11 | #include <asm/hypervisor.h> |
11 | #include <asm/sstate.h> | 12 | #include <asm/spitfire.h> |
12 | #include <asm/oplib.h> | 13 | #include <asm/oplib.h> |
13 | #include <asm/head.h> | 14 | #include <asm/head.h> |
14 | #include <asm/io.h> | 15 | #include <asm/io.h> |
@@ -50,31 +51,34 @@ static const char rebooting_msg[32] __attribute__((aligned(32))) = | |||
50 | static const char panicing_msg[32] __attribute__((aligned(32))) = | 51 | static const char panicing_msg[32] __attribute__((aligned(32))) = |
51 | "Linux panicing"; | 52 | "Linux panicing"; |
52 | 53 | ||
53 | void sstate_booting(void) | 54 | static int sstate_reboot_call(struct notifier_block *np, unsigned long type, void *_unused) |
54 | { | 55 | { |
55 | do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg); | 56 | const char *msg; |
56 | } | ||
57 | 57 | ||
58 | void sstate_running(void) | 58 | switch (type) { |
59 | { | 59 | case SYS_DOWN: |
60 | do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg); | 60 | default: |
61 | } | 61 | msg = rebooting_msg; |
62 | break; | ||
62 | 63 | ||
63 | void sstate_halt(void) | 64 | case SYS_HALT: |
64 | { | 65 | msg = halting_msg; |
65 | do_set_sstate(HV_SOFT_STATE_TRANSITION, halting_msg); | 66 | break; |
66 | } | ||
67 | 67 | ||
68 | void sstate_poweroff(void) | 68 | case SYS_POWER_OFF: |
69 | { | 69 | msg = poweroff_msg; |
70 | do_set_sstate(HV_SOFT_STATE_TRANSITION, poweroff_msg); | 70 | break; |
71 | } | 71 | } |
72 | 72 | ||
73 | void sstate_reboot(void) | 73 | do_set_sstate(HV_SOFT_STATE_TRANSITION, msg); |
74 | { | 74 | |
75 | do_set_sstate(HV_SOFT_STATE_TRANSITION, rebooting_msg); | 75 | return NOTIFY_OK; |
76 | } | 76 | } |
77 | 77 | ||
78 | static struct notifier_block sstate_reboot_notifier = { | ||
79 | .notifier_call = sstate_reboot_call, | ||
80 | }; | ||
81 | |||
78 | static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr) | 82 | static int sstate_panic_event(struct notifier_block *n, unsigned long event, void *ptr) |
79 | { | 83 | { |
80 | do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg); | 84 | do_set_sstate(HV_SOFT_STATE_TRANSITION, panicing_msg); |
@@ -87,18 +91,37 @@ static struct notifier_block sstate_panic_block = { | |||
87 | .priority = INT_MAX, | 91 | .priority = INT_MAX, |
88 | }; | 92 | }; |
89 | 93 | ||
90 | void __init sun4v_sstate_init(void) | 94 | static int __init sstate_init(void) |
91 | { | 95 | { |
92 | unsigned long major, minor; | 96 | unsigned long major, minor; |
93 | 97 | ||
98 | if (tlb_type != hypervisor) | ||
99 | return 0; | ||
100 | |||
94 | major = 1; | 101 | major = 1; |
95 | minor = 0; | 102 | minor = 0; |
96 | if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor)) | 103 | if (sun4v_hvapi_register(HV_GRP_SOFT_STATE, major, &minor)) |
97 | return; | 104 | return 0; |
98 | 105 | ||
99 | hv_supports_soft_state = 1; | 106 | hv_supports_soft_state = 1; |
100 | 107 | ||
101 | prom_sun4v_guest_soft_state(); | 108 | prom_sun4v_guest_soft_state(); |
109 | |||
110 | do_set_sstate(HV_SOFT_STATE_TRANSITION, booting_msg); | ||
111 | |||
102 | atomic_notifier_chain_register(&panic_notifier_list, | 112 | atomic_notifier_chain_register(&panic_notifier_list, |
103 | &sstate_panic_block); | 113 | &sstate_panic_block); |
114 | register_reboot_notifier(&sstate_reboot_notifier); | ||
115 | |||
116 | return 0; | ||
104 | } | 117 | } |
118 | |||
119 | core_initcall(sstate_init); | ||
120 | |||
121 | static int __init sstate_running(void) | ||
122 | { | ||
123 | do_set_sstate(HV_SOFT_STATE_NORMAL, running_msg); | ||
124 | return 0; | ||
125 | } | ||
126 | |||
127 | late_initcall(sstate_running); | ||
diff --git a/arch/sparc64/kernel/starfire.c b/arch/sparc64/kernel/starfire.c index 7461581b3bb9..060d0f3a6151 100644 --- a/arch/sparc64/kernel/starfire.c +++ b/arch/sparc64/kernel/starfire.c | |||
@@ -28,11 +28,6 @@ void check_if_starfire(void) | |||
28 | this_is_starfire = 1; | 28 | this_is_starfire = 1; |
29 | } | 29 | } |
30 | 30 | ||
31 | void starfire_cpu_setup(void) | ||
32 | { | ||
33 | /* Currently, nothing to do. */ | ||
34 | } | ||
35 | |||
36 | int starfire_hard_smp_processor_id(void) | 31 | int starfire_hard_smp_processor_id(void) |
37 | { | 32 | { |
38 | return upa_readl(0x1fff40000d0UL); | 33 | return upa_readl(0x1fff40000d0UL); |
diff --git a/arch/sparc64/kernel/sys_sparc32.c b/arch/sparc64/kernel/sys_sparc32.c index 3d118531baff..3320c9d0075f 100644 --- a/arch/sparc64/kernel/sys_sparc32.c +++ b/arch/sparc64/kernel/sys_sparc32.c | |||
@@ -575,14 +575,6 @@ asmlinkage long sys32_settimeofday(struct compat_timeval __user *tv, | |||
575 | return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); | 575 | return do_sys_settimeofday(tv ? &kts : NULL, tz ? &ktz : NULL); |
576 | } | 576 | } |
577 | 577 | ||
578 | /* These are here just in case some old sparc32 binary calls it. */ | ||
579 | asmlinkage long sys32_pause(void) | ||
580 | { | ||
581 | current->state = TASK_INTERRUPTIBLE; | ||
582 | schedule(); | ||
583 | return -ERESTARTNOHAND; | ||
584 | } | ||
585 | |||
586 | asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, | 578 | asmlinkage compat_ssize_t sys32_pread64(unsigned int fd, |
587 | char __user *ubuf, | 579 | char __user *ubuf, |
588 | compat_size_t count, | 580 | compat_size_t count, |
diff --git a/arch/sparc64/kernel/syscalls.S b/arch/sparc64/kernel/syscalls.S index a2f24270ed8a..7a6786a71363 100644 --- a/arch/sparc64/kernel/syscalls.S +++ b/arch/sparc64/kernel/syscalls.S | |||
@@ -65,9 +65,8 @@ sys32_rt_sigreturn: | |||
65 | andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 | 65 | andcc %l5, (_TIF_SYSCALL_TRACE|_TIF_SECCOMP|_TIF_SYSCALL_AUDIT), %g0 |
66 | be,pt %icc, rtrap | 66 | be,pt %icc, rtrap |
67 | nop | 67 | nop |
68 | add %sp, PTREGS_OFF, %o0 | 68 | call syscall_trace_leave |
69 | call syscall_trace | 69 | add %sp, PTREGS_OFF, %o0 |
70 | mov 1, %o1 | ||
71 | ba,pt %xcc, rtrap | 70 | ba,pt %xcc, rtrap |
72 | nop | 71 | nop |
73 | 72 | ||
@@ -159,9 +158,8 @@ linux_sparc_ni_syscall: | |||
159 | or %l7, %lo(sys_ni_syscall), %l7 | 158 | or %l7, %lo(sys_ni_syscall), %l7 |
160 | 159 | ||
161 | linux_syscall_trace32: | 160 | linux_syscall_trace32: |
162 | add %sp, PTREGS_OFF, %o0 | 161 | call syscall_trace_enter |
163 | call syscall_trace | 162 | add %sp, PTREGS_OFF, %o0 |
164 | clr %o1 | ||
165 | brnz,pn %o0, 3f | 163 | brnz,pn %o0, 3f |
166 | mov -ENOSYS, %o0 | 164 | mov -ENOSYS, %o0 |
167 | srl %i0, 0, %o0 | 165 | srl %i0, 0, %o0 |
@@ -172,9 +170,8 @@ linux_syscall_trace32: | |||
172 | srl %i3, 0, %o3 | 170 | srl %i3, 0, %o3 |
173 | 171 | ||
174 | linux_syscall_trace: | 172 | linux_syscall_trace: |
175 | add %sp, PTREGS_OFF, %o0 | 173 | call syscall_trace_enter |
176 | call syscall_trace | 174 | add %sp, PTREGS_OFF, %o0 |
177 | clr %o1 | ||
178 | brnz,pn %o0, 3f | 175 | brnz,pn %o0, 3f |
179 | mov -ENOSYS, %o0 | 176 | mov -ENOSYS, %o0 |
180 | mov %i0, %o0 | 177 | mov %i0, %o0 |
@@ -275,9 +272,8 @@ ret_sys_call: | |||
275 | b,pt %xcc, rtrap | 272 | b,pt %xcc, rtrap |
276 | stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] | 273 | stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] |
277 | linux_syscall_trace2: | 274 | linux_syscall_trace2: |
278 | add %sp, PTREGS_OFF, %o0 | 275 | call syscall_trace_leave |
279 | call syscall_trace | 276 | add %sp, PTREGS_OFF, %o0 |
280 | mov 1, %o1 | ||
281 | stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] | 277 | stx %l1, [%sp + PTREGS_OFF + PT_V9_TPC] |
282 | ba,pt %xcc, rtrap | 278 | ba,pt %xcc, rtrap |
283 | stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] | 279 | stx %l2, [%sp + PTREGS_OFF + PT_V9_TNPC] |
diff --git a/arch/sparc64/kernel/systbls.S b/arch/sparc64/kernel/systbls.S index 0fdbf3ba956e..5daee4b04dd5 100644 --- a/arch/sparc64/kernel/systbls.S +++ b/arch/sparc64/kernel/systbls.S | |||
@@ -23,7 +23,7 @@ sys_call_table32: | |||
23 | /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod | 23 | /*10*/ .word sys_unlink, sunos_execv, sys_chdir, sys_chown16, sys32_mknod |
24 | /*15*/ .word sys_chmod, sys_lchown16, sparc_brk, sys32_perfctr, sys32_lseek | 24 | /*15*/ .word sys_chmod, sys_lchown16, sparc_brk, sys32_perfctr, sys32_lseek |
25 | /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 | 25 | /*20*/ .word sys_getpid, sys_capget, sys_capset, sys_setuid16, sys_getuid16 |
26 | /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys32_pause | 26 | /*25*/ .word sys32_vmsplice, compat_sys_ptrace, sys_alarm, sys32_sigaltstack, sys_pause |
27 | /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice | 27 | /*30*/ .word compat_sys_utime, sys_lchown, sys_fchown, sys32_access, sys32_nice |
28 | .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile | 28 | .word sys_chown, sys_sync, sys32_kill, compat_sys_newstat, sys32_sendfile |
29 | /*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid | 29 | /*40*/ .word compat_sys_newlstat, sys_dup, sys_pipe, compat_sys_times, sys_getuid |
diff --git a/arch/sparc64/kernel/time.c b/arch/sparc64/kernel/time.c index cc16fdcf98af..80d71a5ce1e3 100644 --- a/arch/sparc64/kernel/time.c +++ b/arch/sparc64/kernel/time.c | |||
@@ -30,13 +30,14 @@ | |||
30 | #include <linux/percpu.h> | 30 | #include <linux/percpu.h> |
31 | #include <linux/miscdevice.h> | 31 | #include <linux/miscdevice.h> |
32 | #include <linux/rtc.h> | 32 | #include <linux/rtc.h> |
33 | #include <linux/rtc/m48t59.h> | ||
33 | #include <linux/kernel_stat.h> | 34 | #include <linux/kernel_stat.h> |
34 | #include <linux/clockchips.h> | 35 | #include <linux/clockchips.h> |
35 | #include <linux/clocksource.h> | 36 | #include <linux/clocksource.h> |
36 | #include <linux/of_device.h> | 37 | #include <linux/of_device.h> |
38 | #include <linux/platform_device.h> | ||
37 | 39 | ||
38 | #include <asm/oplib.h> | 40 | #include <asm/oplib.h> |
39 | #include <asm/mostek.h> | ||
40 | #include <asm/timer.h> | 41 | #include <asm/timer.h> |
41 | #include <asm/irq.h> | 42 | #include <asm/irq.h> |
42 | #include <asm/io.h> | 43 | #include <asm/io.h> |
@@ -50,18 +51,7 @@ | |||
50 | 51 | ||
51 | #include "entry.h" | 52 | #include "entry.h" |
52 | 53 | ||
53 | DEFINE_SPINLOCK(mostek_lock); | ||
54 | DEFINE_SPINLOCK(rtc_lock); | 54 | DEFINE_SPINLOCK(rtc_lock); |
55 | void __iomem *mstk48t02_regs = NULL; | ||
56 | #ifdef CONFIG_PCI | ||
57 | unsigned long ds1287_regs = 0UL; | ||
58 | static void __iomem *bq4802_regs; | ||
59 | #endif | ||
60 | |||
61 | static void __iomem *mstk48t08_regs; | ||
62 | static void __iomem *mstk48t59_regs; | ||
63 | |||
64 | static int set_rtc_mmss(unsigned long); | ||
65 | 55 | ||
66 | #define TICK_PRIV_BIT (1UL << 63) | 56 | #define TICK_PRIV_BIT (1UL << 63) |
67 | #define TICKCMP_IRQ_BIT (1UL << 63) | 57 | #define TICKCMP_IRQ_BIT (1UL << 63) |
@@ -405,313 +395,167 @@ static unsigned long timer_ticks_per_nsec_quotient __read_mostly; | |||
405 | 395 | ||
406 | int update_persistent_clock(struct timespec now) | 396 | int update_persistent_clock(struct timespec now) |
407 | { | 397 | { |
408 | return set_rtc_mmss(now.tv_sec); | 398 | struct rtc_device *rtc = rtc_class_open("rtc0"); |
409 | } | 399 | int err = -1; |
410 | 400 | ||
411 | /* Kick start a stopped clock (procedure from the Sun NVRAM/hostid FAQ). */ | 401 | if (rtc) { |
412 | static void __init kick_start_clock(void) | 402 | err = rtc_set_mmss(rtc, now.tv_sec); |
413 | { | 403 | rtc_class_close(rtc); |
414 | void __iomem *regs = mstk48t02_regs; | ||
415 | u8 sec, tmp; | ||
416 | int i, count; | ||
417 | |||
418 | prom_printf("CLOCK: Clock was stopped. Kick start "); | ||
419 | |||
420 | spin_lock_irq(&mostek_lock); | ||
421 | |||
422 | /* Turn on the kick start bit to start the oscillator. */ | ||
423 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
424 | tmp |= MSTK_CREG_WRITE; | ||
425 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
426 | tmp = mostek_read(regs + MOSTEK_SEC); | ||
427 | tmp &= ~MSTK_STOP; | ||
428 | mostek_write(regs + MOSTEK_SEC, tmp); | ||
429 | tmp = mostek_read(regs + MOSTEK_HOUR); | ||
430 | tmp |= MSTK_KICK_START; | ||
431 | mostek_write(regs + MOSTEK_HOUR, tmp); | ||
432 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
433 | tmp &= ~MSTK_CREG_WRITE; | ||
434 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
435 | |||
436 | spin_unlock_irq(&mostek_lock); | ||
437 | |||
438 | /* Delay to allow the clock oscillator to start. */ | ||
439 | sec = MSTK_REG_SEC(regs); | ||
440 | for (i = 0; i < 3; i++) { | ||
441 | while (sec == MSTK_REG_SEC(regs)) | ||
442 | for (count = 0; count < 100000; count++) | ||
443 | /* nothing */ ; | ||
444 | prom_printf("."); | ||
445 | sec = MSTK_REG_SEC(regs); | ||
446 | } | ||
447 | prom_printf("\n"); | ||
448 | |||
449 | spin_lock_irq(&mostek_lock); | ||
450 | |||
451 | /* Turn off kick start and set a "valid" time and date. */ | ||
452 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
453 | tmp |= MSTK_CREG_WRITE; | ||
454 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
455 | tmp = mostek_read(regs + MOSTEK_HOUR); | ||
456 | tmp &= ~MSTK_KICK_START; | ||
457 | mostek_write(regs + MOSTEK_HOUR, tmp); | ||
458 | MSTK_SET_REG_SEC(regs,0); | ||
459 | MSTK_SET_REG_MIN(regs,0); | ||
460 | MSTK_SET_REG_HOUR(regs,0); | ||
461 | MSTK_SET_REG_DOW(regs,5); | ||
462 | MSTK_SET_REG_DOM(regs,1); | ||
463 | MSTK_SET_REG_MONTH(regs,8); | ||
464 | MSTK_SET_REG_YEAR(regs,1996 - MSTK_YEAR_ZERO); | ||
465 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
466 | tmp &= ~MSTK_CREG_WRITE; | ||
467 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
468 | |||
469 | spin_unlock_irq(&mostek_lock); | ||
470 | |||
471 | /* Ensure the kick start bit is off. If it isn't, turn it off. */ | ||
472 | while (mostek_read(regs + MOSTEK_HOUR) & MSTK_KICK_START) { | ||
473 | prom_printf("CLOCK: Kick start still on!\n"); | ||
474 | |||
475 | spin_lock_irq(&mostek_lock); | ||
476 | |||
477 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
478 | tmp |= MSTK_CREG_WRITE; | ||
479 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
480 | |||
481 | tmp = mostek_read(regs + MOSTEK_HOUR); | ||
482 | tmp &= ~MSTK_KICK_START; | ||
483 | mostek_write(regs + MOSTEK_HOUR, tmp); | ||
484 | |||
485 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
486 | tmp &= ~MSTK_CREG_WRITE; | ||
487 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
488 | |||
489 | spin_unlock_irq(&mostek_lock); | ||
490 | } | 404 | } |
491 | 405 | ||
492 | prom_printf("CLOCK: Kick start procedure successful.\n"); | 406 | return err; |
493 | } | 407 | } |
494 | 408 | ||
495 | /* Return nonzero if the clock chip battery is low. */ | 409 | unsigned long cmos_regs; |
496 | static int __init has_low_battery(void) | 410 | EXPORT_SYMBOL(cmos_regs); |
497 | { | ||
498 | void __iomem *regs = mstk48t02_regs; | ||
499 | u8 data1, data2; | ||
500 | |||
501 | spin_lock_irq(&mostek_lock); | ||
502 | 411 | ||
503 | data1 = mostek_read(regs + MOSTEK_EEPROM); /* Read some data. */ | 412 | static struct resource rtc_cmos_resource; |
504 | mostek_write(regs + MOSTEK_EEPROM, ~data1); /* Write back the complement. */ | ||
505 | data2 = mostek_read(regs + MOSTEK_EEPROM); /* Read back the complement. */ | ||
506 | mostek_write(regs + MOSTEK_EEPROM, data1); /* Restore original value. */ | ||
507 | 413 | ||
508 | spin_unlock_irq(&mostek_lock); | 414 | static struct platform_device rtc_cmos_device = { |
509 | 415 | .name = "rtc_cmos", | |
510 | return (data1 == data2); /* Was the write blocked? */ | 416 | .id = -1, |
511 | } | 417 | .resource = &rtc_cmos_resource, |
418 | .num_resources = 1, | ||
419 | }; | ||
512 | 420 | ||
513 | static void __init mostek_set_system_time(void __iomem *mregs) | 421 | static int __devinit rtc_probe(struct of_device *op, const struct of_device_id *match) |
514 | { | 422 | { |
515 | unsigned int year, mon, day, hour, min, sec; | 423 | struct resource *r; |
516 | u8 tmp; | ||
517 | |||
518 | spin_lock_irq(&mostek_lock); | ||
519 | 424 | ||
520 | /* Traditional Mostek chip. */ | 425 | printk(KERN_INFO "%s: RTC regs at 0x%lx\n", |
521 | tmp = mostek_read(mregs + MOSTEK_CREG); | 426 | op->node->full_name, op->resource[0].start); |
522 | tmp |= MSTK_CREG_READ; | ||
523 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
524 | 427 | ||
525 | sec = MSTK_REG_SEC(mregs); | 428 | /* The CMOS RTC driver only accepts IORESOURCE_IO, so cons |
526 | min = MSTK_REG_MIN(mregs); | 429 | * up a fake resource so that the probe works for all cases. |
527 | hour = MSTK_REG_HOUR(mregs); | 430 | * When the RTC is behind an ISA bus it will have IORESOURCE_IO |
528 | day = MSTK_REG_DOM(mregs); | 431 | * already, whereas when it's behind EBUS is will be IORESOURCE_MEM. |
529 | mon = MSTK_REG_MONTH(mregs); | 432 | */ |
530 | year = MSTK_CVT_YEAR( MSTK_REG_YEAR(mregs) ); | ||
531 | |||
532 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | ||
533 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | ||
534 | set_normalized_timespec(&wall_to_monotonic, | ||
535 | -xtime.tv_sec, -xtime.tv_nsec); | ||
536 | 433 | ||
537 | tmp = mostek_read(mregs + MOSTEK_CREG); | 434 | r = &rtc_cmos_resource; |
538 | tmp &= ~MSTK_CREG_READ; | 435 | r->flags = IORESOURCE_IO; |
539 | mostek_write(mregs + MOSTEK_CREG, tmp); | 436 | r->name = op->resource[0].name; |
437 | r->start = op->resource[0].start; | ||
438 | r->end = op->resource[0].end; | ||
540 | 439 | ||
541 | spin_unlock_irq(&mostek_lock); | 440 | cmos_regs = op->resource[0].start; |
441 | return platform_device_register(&rtc_cmos_device); | ||
542 | } | 442 | } |
543 | 443 | ||
544 | /* Probe for the real time clock chip. */ | 444 | static struct of_device_id __initdata rtc_match[] = { |
545 | static void __init set_system_time(void) | 445 | { |
546 | { | 446 | .name = "rtc", |
547 | unsigned int year, mon, day, hour, min, sec; | 447 | .compatible = "m5819", |
548 | void __iomem *mregs = mstk48t02_regs; | 448 | }, |
549 | #ifdef CONFIG_PCI | 449 | { |
550 | unsigned long dregs = ds1287_regs; | 450 | .name = "rtc", |
551 | void __iomem *bregs = bq4802_regs; | 451 | .compatible = "isa-m5819p", |
552 | #else | 452 | }, |
553 | unsigned long dregs = 0UL; | 453 | { |
554 | void __iomem *bregs = 0UL; | 454 | .name = "rtc", |
555 | #endif | 455 | .compatible = "isa-m5823p", |
556 | 456 | }, | |
557 | if (!mregs && !dregs && !bregs) { | 457 | { |
558 | prom_printf("Something wrong, clock regs not mapped yet.\n"); | 458 | .name = "rtc", |
559 | prom_halt(); | 459 | .compatible = "ds1287", |
560 | } | 460 | }, |
561 | 461 | {}, | |
562 | if (mregs) { | 462 | }; |
563 | mostek_set_system_time(mregs); | ||
564 | return; | ||
565 | } | ||
566 | |||
567 | if (bregs) { | ||
568 | unsigned char val = readb(bregs + 0x0e); | ||
569 | unsigned int century; | ||
570 | 463 | ||
571 | /* BQ4802 RTC chip. */ | 464 | static struct of_platform_driver rtc_driver = { |
465 | .match_table = rtc_match, | ||
466 | .probe = rtc_probe, | ||
467 | .driver = { | ||
468 | .name = "rtc", | ||
469 | }, | ||
470 | }; | ||
572 | 471 | ||
573 | writeb(val | 0x08, bregs + 0x0e); | 472 | static struct platform_device rtc_bq4802_device = { |
473 | .name = "rtc-bq4802", | ||
474 | .id = -1, | ||
475 | .num_resources = 1, | ||
476 | }; | ||
574 | 477 | ||
575 | sec = readb(bregs + 0x00); | 478 | static int __devinit bq4802_probe(struct of_device *op, const struct of_device_id *match) |
576 | min = readb(bregs + 0x02); | 479 | { |
577 | hour = readb(bregs + 0x04); | ||
578 | day = readb(bregs + 0x06); | ||
579 | mon = readb(bregs + 0x09); | ||
580 | year = readb(bregs + 0x0a); | ||
581 | century = readb(bregs + 0x0f); | ||
582 | 480 | ||
583 | writeb(val, bregs + 0x0e); | 481 | printk(KERN_INFO "%s: BQ4802 regs at 0x%lx\n", |
482 | op->node->full_name, op->resource[0].start); | ||
584 | 483 | ||
585 | BCD_TO_BIN(sec); | 484 | rtc_bq4802_device.resource = &op->resource[0]; |
586 | BCD_TO_BIN(min); | 485 | return platform_device_register(&rtc_bq4802_device); |
587 | BCD_TO_BIN(hour); | 486 | } |
588 | BCD_TO_BIN(day); | ||
589 | BCD_TO_BIN(mon); | ||
590 | BCD_TO_BIN(year); | ||
591 | BCD_TO_BIN(century); | ||
592 | 487 | ||
593 | year += (century * 100); | 488 | static struct of_device_id __initdata bq4802_match[] = { |
594 | } else { | 489 | { |
595 | /* Dallas 12887 RTC chip. */ | 490 | .name = "rtc", |
596 | 491 | .compatible = "bq4802", | |
597 | do { | 492 | }, |
598 | sec = CMOS_READ(RTC_SECONDS); | 493 | }; |
599 | min = CMOS_READ(RTC_MINUTES); | ||
600 | hour = CMOS_READ(RTC_HOURS); | ||
601 | day = CMOS_READ(RTC_DAY_OF_MONTH); | ||
602 | mon = CMOS_READ(RTC_MONTH); | ||
603 | year = CMOS_READ(RTC_YEAR); | ||
604 | } while (sec != CMOS_READ(RTC_SECONDS)); | ||
605 | |||
606 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
607 | BCD_TO_BIN(sec); | ||
608 | BCD_TO_BIN(min); | ||
609 | BCD_TO_BIN(hour); | ||
610 | BCD_TO_BIN(day); | ||
611 | BCD_TO_BIN(mon); | ||
612 | BCD_TO_BIN(year); | ||
613 | } | ||
614 | if ((year += 1900) < 1970) | ||
615 | year += 100; | ||
616 | } | ||
617 | 494 | ||
618 | xtime.tv_sec = mktime(year, mon, day, hour, min, sec); | 495 | static struct of_platform_driver bq4802_driver = { |
619 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | 496 | .match_table = bq4802_match, |
620 | set_normalized_timespec(&wall_to_monotonic, | 497 | .probe = bq4802_probe, |
621 | -xtime.tv_sec, -xtime.tv_nsec); | 498 | .driver = { |
622 | } | 499 | .name = "bq4802", |
500 | }, | ||
501 | }; | ||
623 | 502 | ||
624 | /* davem suggests we keep this within the 4M locked kernel image */ | 503 | static unsigned char mostek_read_byte(struct device *dev, u32 ofs) |
625 | static u32 starfire_get_time(void) | ||
626 | { | 504 | { |
627 | static char obp_gettod[32]; | 505 | struct platform_device *pdev = to_platform_device(dev); |
628 | static u32 unix_tod; | 506 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; |
507 | void __iomem *regs; | ||
508 | unsigned char val; | ||
629 | 509 | ||
630 | sprintf(obp_gettod, "h# %08x unix-gettod", | 510 | regs = (void __iomem *) pdev->resource[0].start; |
631 | (unsigned int) (long) &unix_tod); | 511 | val = readb(regs + ofs); |
632 | prom_feval(obp_gettod); | ||
633 | 512 | ||
634 | return unix_tod; | 513 | /* the year 0 is 1968 */ |
514 | if (ofs == pdata->offset + M48T59_YEAR) { | ||
515 | val += 0x68; | ||
516 | if ((val & 0xf) > 9) | ||
517 | val += 6; | ||
518 | } | ||
519 | return val; | ||
635 | } | 520 | } |
636 | 521 | ||
637 | static int starfire_set_time(u32 val) | 522 | static void mostek_write_byte(struct device *dev, u32 ofs, u8 val) |
638 | { | 523 | { |
639 | /* Do nothing, time is set using the service processor | 524 | struct platform_device *pdev = to_platform_device(dev); |
640 | * console on this platform. | 525 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; |
641 | */ | 526 | void __iomem *regs; |
642 | return 0; | ||
643 | } | ||
644 | 527 | ||
645 | static u32 hypervisor_get_time(void) | 528 | regs = (void __iomem *) pdev->resource[0].start; |
646 | { | 529 | if (ofs == pdata->offset + M48T59_YEAR) { |
647 | unsigned long ret, time; | 530 | if (val < 0x68) |
648 | int retries = 10000; | 531 | val += 0x32; |
649 | 532 | else | |
650 | retry: | 533 | val -= 0x68; |
651 | ret = sun4v_tod_get(&time); | 534 | if ((val & 0xf) > 9) |
652 | if (ret == HV_EOK) | 535 | val += 6; |
653 | return time; | 536 | if ((val & 0xf0) > 0x9A) |
654 | if (ret == HV_EWOULDBLOCK) { | 537 | val += 0x60; |
655 | if (--retries > 0) { | ||
656 | udelay(100); | ||
657 | goto retry; | ||
658 | } | ||
659 | printk(KERN_WARNING "SUN4V: tod_get() timed out.\n"); | ||
660 | return 0; | ||
661 | } | 538 | } |
662 | printk(KERN_WARNING "SUN4V: tod_get() not supported.\n"); | 539 | writeb(val, regs + ofs); |
663 | return 0; | ||
664 | } | 540 | } |
665 | 541 | ||
666 | static int hypervisor_set_time(u32 secs) | 542 | static struct m48t59_plat_data m48t59_data = { |
667 | { | 543 | .read_byte = mostek_read_byte, |
668 | unsigned long ret; | 544 | .write_byte = mostek_write_byte, |
669 | int retries = 10000; | 545 | }; |
670 | |||
671 | retry: | ||
672 | ret = sun4v_tod_set(secs); | ||
673 | if (ret == HV_EOK) | ||
674 | return 0; | ||
675 | if (ret == HV_EWOULDBLOCK) { | ||
676 | if (--retries > 0) { | ||
677 | udelay(100); | ||
678 | goto retry; | ||
679 | } | ||
680 | printk(KERN_WARNING "SUN4V: tod_set() timed out.\n"); | ||
681 | return -EAGAIN; | ||
682 | } | ||
683 | printk(KERN_WARNING "SUN4V: tod_set() not supported.\n"); | ||
684 | return -EOPNOTSUPP; | ||
685 | } | ||
686 | 546 | ||
687 | static int __init clock_model_matches(const char *model) | 547 | static struct platform_device m48t59_rtc = { |
688 | { | 548 | .name = "rtc-m48t59", |
689 | if (strcmp(model, "mk48t02") && | 549 | .id = 0, |
690 | strcmp(model, "mk48t08") && | 550 | .num_resources = 1, |
691 | strcmp(model, "mk48t59") && | 551 | .dev = { |
692 | strcmp(model, "m5819") && | 552 | .platform_data = &m48t59_data, |
693 | strcmp(model, "m5819p") && | 553 | }, |
694 | strcmp(model, "m5823") && | 554 | }; |
695 | strcmp(model, "ds1287") && | ||
696 | strcmp(model, "bq4802")) | ||
697 | return 0; | ||
698 | |||
699 | return 1; | ||
700 | } | ||
701 | 555 | ||
702 | static int __devinit clock_probe(struct of_device *op, const struct of_device_id *match) | 556 | static int __devinit mostek_probe(struct of_device *op, const struct of_device_id *match) |
703 | { | 557 | { |
704 | struct device_node *dp = op->node; | 558 | struct device_node *dp = op->node; |
705 | const char *model = of_get_property(dp, "model", NULL); | ||
706 | const char *compat = of_get_property(dp, "compatible", NULL); | ||
707 | unsigned long size, flags; | ||
708 | void __iomem *regs; | ||
709 | |||
710 | if (!model) | ||
711 | model = compat; | ||
712 | |||
713 | if (!model || !clock_model_matches(model)) | ||
714 | return -ENODEV; | ||
715 | 559 | ||
716 | /* On an Enterprise system there can be multiple mostek clocks. | 560 | /* On an Enterprise system there can be multiple mostek clocks. |
717 | * We should only match the one that is on the central FHC bus. | 561 | * We should only match the one that is on the central FHC bus. |
@@ -720,88 +564,51 @@ static int __devinit clock_probe(struct of_device *op, const struct of_device_id | |||
720 | strcmp(dp->parent->parent->name, "central") != 0) | 564 | strcmp(dp->parent->parent->name, "central") != 0) |
721 | return -ENODEV; | 565 | return -ENODEV; |
722 | 566 | ||
723 | size = (op->resource[0].end - op->resource[0].start) + 1; | 567 | printk(KERN_INFO "%s: Mostek regs at 0x%lx\n", |
724 | regs = of_ioremap(&op->resource[0], 0, size, "clock"); | 568 | dp->full_name, op->resource[0].start); |
725 | if (!regs) | ||
726 | return -ENOMEM; | ||
727 | |||
728 | #ifdef CONFIG_PCI | ||
729 | if (!strcmp(model, "ds1287") || | ||
730 | !strcmp(model, "m5819") || | ||
731 | !strcmp(model, "m5819p") || | ||
732 | !strcmp(model, "m5823")) { | ||
733 | ds1287_regs = (unsigned long) regs; | ||
734 | } else if (!strcmp(model, "bq4802")) { | ||
735 | bq4802_regs = regs; | ||
736 | } else | ||
737 | #endif | ||
738 | if (model[5] == '0' && model[6] == '2') { | ||
739 | mstk48t02_regs = regs; | ||
740 | } else if(model[5] == '0' && model[6] == '8') { | ||
741 | mstk48t08_regs = regs; | ||
742 | mstk48t02_regs = mstk48t08_regs + MOSTEK_48T08_48T02; | ||
743 | } else { | ||
744 | mstk48t59_regs = regs; | ||
745 | mstk48t02_regs = mstk48t59_regs + MOSTEK_48T59_48T02; | ||
746 | } | ||
747 | |||
748 | printk(KERN_INFO "%s: Clock regs at %p\n", dp->full_name, regs); | ||
749 | |||
750 | local_irq_save(flags); | ||
751 | |||
752 | if (mstk48t02_regs != NULL) { | ||
753 | /* Report a low battery voltage condition. */ | ||
754 | if (has_low_battery()) | ||
755 | prom_printf("NVRAM: Low battery voltage!\n"); | ||
756 | |||
757 | /* Kick start the clock if it is completely stopped. */ | ||
758 | if (mostek_read(mstk48t02_regs + MOSTEK_SEC) & MSTK_STOP) | ||
759 | kick_start_clock(); | ||
760 | } | ||
761 | |||
762 | set_system_time(); | ||
763 | |||
764 | local_irq_restore(flags); | ||
765 | 569 | ||
766 | return 0; | 570 | m48t59_rtc.resource = &op->resource[0]; |
571 | return platform_device_register(&m48t59_rtc); | ||
767 | } | 572 | } |
768 | 573 | ||
769 | static struct of_device_id clock_match[] = { | 574 | static struct of_device_id __initdata mostek_match[] = { |
770 | { | 575 | { |
771 | .name = "eeprom", | 576 | .name = "eeprom", |
772 | }, | 577 | }, |
773 | { | ||
774 | .name = "rtc", | ||
775 | }, | ||
776 | {}, | 578 | {}, |
777 | }; | 579 | }; |
778 | 580 | ||
779 | static struct of_platform_driver clock_driver = { | 581 | static struct of_platform_driver mostek_driver = { |
780 | .match_table = clock_match, | 582 | .match_table = mostek_match, |
781 | .probe = clock_probe, | 583 | .probe = mostek_probe, |
782 | .driver = { | 584 | .driver = { |
783 | .name = "clock", | 585 | .name = "mostek", |
784 | }, | 586 | }, |
785 | }; | 587 | }; |
786 | 588 | ||
589 | static struct platform_device rtc_sun4v_device = { | ||
590 | .name = "rtc-sun4v", | ||
591 | .id = -1, | ||
592 | }; | ||
593 | |||
594 | static struct platform_device rtc_starfire_device = { | ||
595 | .name = "rtc-starfire", | ||
596 | .id = -1, | ||
597 | }; | ||
598 | |||
787 | static int __init clock_init(void) | 599 | static int __init clock_init(void) |
788 | { | 600 | { |
789 | if (this_is_starfire) { | 601 | if (this_is_starfire) |
790 | xtime.tv_sec = starfire_get_time(); | 602 | return platform_device_register(&rtc_starfire_device); |
791 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | 603 | |
792 | set_normalized_timespec(&wall_to_monotonic, | 604 | if (tlb_type == hypervisor) |
793 | -xtime.tv_sec, -xtime.tv_nsec); | 605 | return platform_device_register(&rtc_sun4v_device); |
794 | return 0; | 606 | |
795 | } | 607 | (void) of_register_driver(&rtc_driver, &of_platform_bus_type); |
796 | if (tlb_type == hypervisor) { | 608 | (void) of_register_driver(&mostek_driver, &of_platform_bus_type); |
797 | xtime.tv_sec = hypervisor_get_time(); | 609 | (void) of_register_driver(&bq4802_driver, &of_platform_bus_type); |
798 | xtime.tv_nsec = (INITIAL_JIFFIES % HZ) * (NSEC_PER_SEC / HZ); | ||
799 | set_normalized_timespec(&wall_to_monotonic, | ||
800 | -xtime.tv_sec, -xtime.tv_nsec); | ||
801 | return 0; | ||
802 | } | ||
803 | 610 | ||
804 | return of_register_driver(&clock_driver, &of_platform_bus_type); | 611 | return 0; |
805 | } | 612 | } |
806 | 613 | ||
807 | /* Must be after subsys_initcall() so that busses are probed. Must | 614 | /* Must be after subsys_initcall() so that busses are probed. Must |
@@ -814,7 +621,7 @@ fs_initcall(clock_init); | |||
814 | static unsigned long sparc64_init_timers(void) | 621 | static unsigned long sparc64_init_timers(void) |
815 | { | 622 | { |
816 | struct device_node *dp; | 623 | struct device_node *dp; |
817 | unsigned long clock; | 624 | unsigned long freq; |
818 | 625 | ||
819 | dp = of_find_node_by_path("/"); | 626 | dp = of_find_node_by_path("/"); |
820 | if (tlb_type == spitfire) { | 627 | if (tlb_type == spitfire) { |
@@ -827,17 +634,17 @@ static unsigned long sparc64_init_timers(void) | |||
827 | if (manuf == 0x17 && impl == 0x13) { | 634 | if (manuf == 0x17 && impl == 0x13) { |
828 | /* Hummingbird, aka Ultra-IIe */ | 635 | /* Hummingbird, aka Ultra-IIe */ |
829 | tick_ops = &hbtick_operations; | 636 | tick_ops = &hbtick_operations; |
830 | clock = of_getintprop_default(dp, "stick-frequency", 0); | 637 | freq = of_getintprop_default(dp, "stick-frequency", 0); |
831 | } else { | 638 | } else { |
832 | tick_ops = &tick_operations; | 639 | tick_ops = &tick_operations; |
833 | clock = local_cpu_data().clock_tick; | 640 | freq = local_cpu_data().clock_tick; |
834 | } | 641 | } |
835 | } else { | 642 | } else { |
836 | tick_ops = &stick_operations; | 643 | tick_ops = &stick_operations; |
837 | clock = of_getintprop_default(dp, "stick-frequency", 0); | 644 | freq = of_getintprop_default(dp, "stick-frequency", 0); |
838 | } | 645 | } |
839 | 646 | ||
840 | return clock; | 647 | return freq; |
841 | } | 648 | } |
842 | 649 | ||
843 | struct freq_table { | 650 | struct freq_table { |
@@ -1029,16 +836,16 @@ EXPORT_SYMBOL(udelay); | |||
1029 | 836 | ||
1030 | void __init time_init(void) | 837 | void __init time_init(void) |
1031 | { | 838 | { |
1032 | unsigned long clock = sparc64_init_timers(); | 839 | unsigned long freq = sparc64_init_timers(); |
1033 | 840 | ||
1034 | tb_ticks_per_usec = clock / USEC_PER_SEC; | 841 | tb_ticks_per_usec = freq / USEC_PER_SEC; |
1035 | 842 | ||
1036 | timer_ticks_per_nsec_quotient = | 843 | timer_ticks_per_nsec_quotient = |
1037 | clocksource_hz2mult(clock, SPARC64_NSEC_PER_CYC_SHIFT); | 844 | clocksource_hz2mult(freq, SPARC64_NSEC_PER_CYC_SHIFT); |
1038 | 845 | ||
1039 | clocksource_tick.name = tick_ops->name; | 846 | clocksource_tick.name = tick_ops->name; |
1040 | clocksource_tick.mult = | 847 | clocksource_tick.mult = |
1041 | clocksource_hz2mult(clock, | 848 | clocksource_hz2mult(freq, |
1042 | clocksource_tick.shift); | 849 | clocksource_tick.shift); |
1043 | clocksource_tick.read = tick_ops->get_tick; | 850 | clocksource_tick.read = tick_ops->get_tick; |
1044 | 851 | ||
@@ -1049,7 +856,7 @@ void __init time_init(void) | |||
1049 | 856 | ||
1050 | sparc64_clockevent.name = tick_ops->name; | 857 | sparc64_clockevent.name = tick_ops->name; |
1051 | 858 | ||
1052 | setup_clockevent_multiplier(clock); | 859 | setup_clockevent_multiplier(freq); |
1053 | 860 | ||
1054 | sparc64_clockevent.max_delta_ns = | 861 | sparc64_clockevent.max_delta_ns = |
1055 | clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); | 862 | clockevent_delta2ns(0x7fffffffffffffffUL, &sparc64_clockevent); |
@@ -1070,672 +877,8 @@ unsigned long long sched_clock(void) | |||
1070 | >> SPARC64_NSEC_PER_CYC_SHIFT; | 877 | >> SPARC64_NSEC_PER_CYC_SHIFT; |
1071 | } | 878 | } |
1072 | 879 | ||
1073 | static int set_rtc_mmss(unsigned long nowtime) | ||
1074 | { | ||
1075 | int real_seconds, real_minutes, chip_minutes; | ||
1076 | void __iomem *mregs = mstk48t02_regs; | ||
1077 | #ifdef CONFIG_PCI | ||
1078 | unsigned long dregs = ds1287_regs; | ||
1079 | void __iomem *bregs = bq4802_regs; | ||
1080 | #else | ||
1081 | unsigned long dregs = 0UL; | ||
1082 | void __iomem *bregs = 0UL; | ||
1083 | #endif | ||
1084 | unsigned long flags; | ||
1085 | u8 tmp; | ||
1086 | |||
1087 | /* | ||
1088 | * Not having a register set can lead to trouble. | ||
1089 | * Also starfire doesn't have a tod clock. | ||
1090 | */ | ||
1091 | if (!mregs && !dregs && !bregs) | ||
1092 | return -1; | ||
1093 | |||
1094 | if (mregs) { | ||
1095 | spin_lock_irqsave(&mostek_lock, flags); | ||
1096 | |||
1097 | /* Read the current RTC minutes. */ | ||
1098 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
1099 | tmp |= MSTK_CREG_READ; | ||
1100 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
1101 | |||
1102 | chip_minutes = MSTK_REG_MIN(mregs); | ||
1103 | |||
1104 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
1105 | tmp &= ~MSTK_CREG_READ; | ||
1106 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
1107 | |||
1108 | /* | ||
1109 | * since we're only adjusting minutes and seconds, | ||
1110 | * don't interfere with hour overflow. This avoids | ||
1111 | * messing with unknown time zones but requires your | ||
1112 | * RTC not to be off by more than 15 minutes | ||
1113 | */ | ||
1114 | real_seconds = nowtime % 60; | ||
1115 | real_minutes = nowtime / 60; | ||
1116 | if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) | ||
1117 | real_minutes += 30; /* correct for half hour time zone */ | ||
1118 | real_minutes %= 60; | ||
1119 | |||
1120 | if (abs(real_minutes - chip_minutes) < 30) { | ||
1121 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
1122 | tmp |= MSTK_CREG_WRITE; | ||
1123 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
1124 | |||
1125 | MSTK_SET_REG_SEC(mregs,real_seconds); | ||
1126 | MSTK_SET_REG_MIN(mregs,real_minutes); | ||
1127 | |||
1128 | tmp = mostek_read(mregs + MOSTEK_CREG); | ||
1129 | tmp &= ~MSTK_CREG_WRITE; | ||
1130 | mostek_write(mregs + MOSTEK_CREG, tmp); | ||
1131 | |||
1132 | spin_unlock_irqrestore(&mostek_lock, flags); | ||
1133 | |||
1134 | return 0; | ||
1135 | } else { | ||
1136 | spin_unlock_irqrestore(&mostek_lock, flags); | ||
1137 | |||
1138 | return -1; | ||
1139 | } | ||
1140 | } else if (bregs) { | ||
1141 | int retval = 0; | ||
1142 | unsigned char val = readb(bregs + 0x0e); | ||
1143 | |||
1144 | /* BQ4802 RTC chip. */ | ||
1145 | |||
1146 | writeb(val | 0x08, bregs + 0x0e); | ||
1147 | |||
1148 | chip_minutes = readb(bregs + 0x02); | ||
1149 | BCD_TO_BIN(chip_minutes); | ||
1150 | real_seconds = nowtime % 60; | ||
1151 | real_minutes = nowtime / 60; | ||
1152 | if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) | ||
1153 | real_minutes += 30; | ||
1154 | real_minutes %= 60; | ||
1155 | |||
1156 | if (abs(real_minutes - chip_minutes) < 30) { | ||
1157 | BIN_TO_BCD(real_seconds); | ||
1158 | BIN_TO_BCD(real_minutes); | ||
1159 | writeb(real_seconds, bregs + 0x00); | ||
1160 | writeb(real_minutes, bregs + 0x02); | ||
1161 | } else { | ||
1162 | printk(KERN_WARNING | ||
1163 | "set_rtc_mmss: can't update from %d to %d\n", | ||
1164 | chip_minutes, real_minutes); | ||
1165 | retval = -1; | ||
1166 | } | ||
1167 | |||
1168 | writeb(val, bregs + 0x0e); | ||
1169 | |||
1170 | return retval; | ||
1171 | } else { | ||
1172 | int retval = 0; | ||
1173 | unsigned char save_control, save_freq_select; | ||
1174 | |||
1175 | /* Stolen from arch/i386/kernel/time.c, see there for | ||
1176 | * credits and descriptive comments. | ||
1177 | */ | ||
1178 | spin_lock_irqsave(&rtc_lock, flags); | ||
1179 | save_control = CMOS_READ(RTC_CONTROL); /* tell the clock it's being set */ | ||
1180 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | ||
1181 | |||
1182 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); /* stop and reset prescaler */ | ||
1183 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
1184 | |||
1185 | chip_minutes = CMOS_READ(RTC_MINUTES); | ||
1186 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) | ||
1187 | BCD_TO_BIN(chip_minutes); | ||
1188 | real_seconds = nowtime % 60; | ||
1189 | real_minutes = nowtime / 60; | ||
1190 | if (((abs(real_minutes - chip_minutes) + 15)/30) & 1) | ||
1191 | real_minutes += 30; | ||
1192 | real_minutes %= 60; | ||
1193 | |||
1194 | if (abs(real_minutes - chip_minutes) < 30) { | ||
1195 | if (!(save_control & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
1196 | BIN_TO_BCD(real_seconds); | ||
1197 | BIN_TO_BCD(real_minutes); | ||
1198 | } | ||
1199 | CMOS_WRITE(real_seconds,RTC_SECONDS); | ||
1200 | CMOS_WRITE(real_minutes,RTC_MINUTES); | ||
1201 | } else { | ||
1202 | printk(KERN_WARNING | ||
1203 | "set_rtc_mmss: can't update from %d to %d\n", | ||
1204 | chip_minutes, real_minutes); | ||
1205 | retval = -1; | ||
1206 | } | ||
1207 | |||
1208 | CMOS_WRITE(save_control, RTC_CONTROL); | ||
1209 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | ||
1210 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
1211 | |||
1212 | return retval; | ||
1213 | } | ||
1214 | } | ||
1215 | |||
1216 | #define RTC_IS_OPEN 0x01 /* means /dev/rtc is in use */ | ||
1217 | static unsigned char mini_rtc_status; /* bitmapped status byte. */ | ||
1218 | |||
1219 | #define FEBRUARY 2 | ||
1220 | #define STARTOFTIME 1970 | ||
1221 | #define SECDAY 86400L | ||
1222 | #define SECYR (SECDAY * 365) | ||
1223 | #define leapyear(year) ((year) % 4 == 0 && \ | ||
1224 | ((year) % 100 != 0 || (year) % 400 == 0)) | ||
1225 | #define days_in_year(a) (leapyear(a) ? 366 : 365) | ||
1226 | #define days_in_month(a) (month_days[(a) - 1]) | ||
1227 | |||
1228 | static int month_days[12] = { | ||
1229 | 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 | ||
1230 | }; | ||
1231 | |||
1232 | /* | ||
1233 | * This only works for the Gregorian calendar - i.e. after 1752 (in the UK) | ||
1234 | */ | ||
1235 | static void GregorianDay(struct rtc_time * tm) | ||
1236 | { | ||
1237 | int leapsToDate; | ||
1238 | int lastYear; | ||
1239 | int day; | ||
1240 | int MonthOffset[] = { 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 }; | ||
1241 | |||
1242 | lastYear = tm->tm_year - 1; | ||
1243 | |||
1244 | /* | ||
1245 | * Number of leap corrections to apply up to end of last year | ||
1246 | */ | ||
1247 | leapsToDate = lastYear / 4 - lastYear / 100 + lastYear / 400; | ||
1248 | |||
1249 | /* | ||
1250 | * This year is a leap year if it is divisible by 4 except when it is | ||
1251 | * divisible by 100 unless it is divisible by 400 | ||
1252 | * | ||
1253 | * e.g. 1904 was a leap year, 1900 was not, 1996 is, and 2000 was | ||
1254 | */ | ||
1255 | day = tm->tm_mon > 2 && leapyear(tm->tm_year); | ||
1256 | |||
1257 | day += lastYear*365 + leapsToDate + MonthOffset[tm->tm_mon-1] + | ||
1258 | tm->tm_mday; | ||
1259 | |||
1260 | tm->tm_wday = day % 7; | ||
1261 | } | ||
1262 | |||
1263 | static void to_tm(int tim, struct rtc_time *tm) | ||
1264 | { | ||
1265 | register int i; | ||
1266 | register long hms, day; | ||
1267 | |||
1268 | day = tim / SECDAY; | ||
1269 | hms = tim % SECDAY; | ||
1270 | |||
1271 | /* Hours, minutes, seconds are easy */ | ||
1272 | tm->tm_hour = hms / 3600; | ||
1273 | tm->tm_min = (hms % 3600) / 60; | ||
1274 | tm->tm_sec = (hms % 3600) % 60; | ||
1275 | |||
1276 | /* Number of years in days */ | ||
1277 | for (i = STARTOFTIME; day >= days_in_year(i); i++) | ||
1278 | day -= days_in_year(i); | ||
1279 | tm->tm_year = i; | ||
1280 | |||
1281 | /* Number of months in days left */ | ||
1282 | if (leapyear(tm->tm_year)) | ||
1283 | days_in_month(FEBRUARY) = 29; | ||
1284 | for (i = 1; day >= days_in_month(i); i++) | ||
1285 | day -= days_in_month(i); | ||
1286 | days_in_month(FEBRUARY) = 28; | ||
1287 | tm->tm_mon = i; | ||
1288 | |||
1289 | /* Days are what is left over (+1) from all that. */ | ||
1290 | tm->tm_mday = day + 1; | ||
1291 | |||
1292 | /* | ||
1293 | * Determine the day of week | ||
1294 | */ | ||
1295 | GregorianDay(tm); | ||
1296 | } | ||
1297 | |||
1298 | /* Both Starfire and SUN4V give us seconds since Jan 1st, 1970, | ||
1299 | * aka Unix time. So we have to convert to/from rtc_time. | ||
1300 | */ | ||
1301 | static void starfire_get_rtc_time(struct rtc_time *time) | ||
1302 | { | ||
1303 | u32 seconds = starfire_get_time(); | ||
1304 | |||
1305 | to_tm(seconds, time); | ||
1306 | time->tm_year -= 1900; | ||
1307 | time->tm_mon -= 1; | ||
1308 | } | ||
1309 | |||
1310 | static int starfire_set_rtc_time(struct rtc_time *time) | ||
1311 | { | ||
1312 | u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, | ||
1313 | time->tm_mday, time->tm_hour, | ||
1314 | time->tm_min, time->tm_sec); | ||
1315 | |||
1316 | return starfire_set_time(seconds); | ||
1317 | } | ||
1318 | |||
1319 | static void hypervisor_get_rtc_time(struct rtc_time *time) | ||
1320 | { | ||
1321 | u32 seconds = hypervisor_get_time(); | ||
1322 | |||
1323 | to_tm(seconds, time); | ||
1324 | time->tm_year -= 1900; | ||
1325 | time->tm_mon -= 1; | ||
1326 | } | ||
1327 | |||
1328 | static int hypervisor_set_rtc_time(struct rtc_time *time) | ||
1329 | { | ||
1330 | u32 seconds = mktime(time->tm_year + 1900, time->tm_mon + 1, | ||
1331 | time->tm_mday, time->tm_hour, | ||
1332 | time->tm_min, time->tm_sec); | ||
1333 | |||
1334 | return hypervisor_set_time(seconds); | ||
1335 | } | ||
1336 | |||
1337 | #ifdef CONFIG_PCI | ||
1338 | static void bq4802_get_rtc_time(struct rtc_time *time) | ||
1339 | { | ||
1340 | unsigned char val = readb(bq4802_regs + 0x0e); | ||
1341 | unsigned int century; | ||
1342 | |||
1343 | writeb(val | 0x08, bq4802_regs + 0x0e); | ||
1344 | |||
1345 | time->tm_sec = readb(bq4802_regs + 0x00); | ||
1346 | time->tm_min = readb(bq4802_regs + 0x02); | ||
1347 | time->tm_hour = readb(bq4802_regs + 0x04); | ||
1348 | time->tm_mday = readb(bq4802_regs + 0x06); | ||
1349 | time->tm_mon = readb(bq4802_regs + 0x09); | ||
1350 | time->tm_year = readb(bq4802_regs + 0x0a); | ||
1351 | time->tm_wday = readb(bq4802_regs + 0x08); | ||
1352 | century = readb(bq4802_regs + 0x0f); | ||
1353 | |||
1354 | writeb(val, bq4802_regs + 0x0e); | ||
1355 | |||
1356 | BCD_TO_BIN(time->tm_sec); | ||
1357 | BCD_TO_BIN(time->tm_min); | ||
1358 | BCD_TO_BIN(time->tm_hour); | ||
1359 | BCD_TO_BIN(time->tm_mday); | ||
1360 | BCD_TO_BIN(time->tm_mon); | ||
1361 | BCD_TO_BIN(time->tm_year); | ||
1362 | BCD_TO_BIN(time->tm_wday); | ||
1363 | BCD_TO_BIN(century); | ||
1364 | |||
1365 | time->tm_year += (century * 100); | ||
1366 | time->tm_year -= 1900; | ||
1367 | |||
1368 | time->tm_mon--; | ||
1369 | } | ||
1370 | |||
1371 | static int bq4802_set_rtc_time(struct rtc_time *time) | ||
1372 | { | ||
1373 | unsigned char val = readb(bq4802_regs + 0x0e); | ||
1374 | unsigned char sec, min, hrs, day, mon, yrs, century; | ||
1375 | unsigned int year; | ||
1376 | |||
1377 | year = time->tm_year + 1900; | ||
1378 | century = year / 100; | ||
1379 | yrs = year % 100; | ||
1380 | |||
1381 | mon = time->tm_mon + 1; /* tm_mon starts at zero */ | ||
1382 | day = time->tm_mday; | ||
1383 | hrs = time->tm_hour; | ||
1384 | min = time->tm_min; | ||
1385 | sec = time->tm_sec; | ||
1386 | |||
1387 | BIN_TO_BCD(sec); | ||
1388 | BIN_TO_BCD(min); | ||
1389 | BIN_TO_BCD(hrs); | ||
1390 | BIN_TO_BCD(day); | ||
1391 | BIN_TO_BCD(mon); | ||
1392 | BIN_TO_BCD(yrs); | ||
1393 | BIN_TO_BCD(century); | ||
1394 | |||
1395 | writeb(val | 0x08, bq4802_regs + 0x0e); | ||
1396 | |||
1397 | writeb(sec, bq4802_regs + 0x00); | ||
1398 | writeb(min, bq4802_regs + 0x02); | ||
1399 | writeb(hrs, bq4802_regs + 0x04); | ||
1400 | writeb(day, bq4802_regs + 0x06); | ||
1401 | writeb(mon, bq4802_regs + 0x09); | ||
1402 | writeb(yrs, bq4802_regs + 0x0a); | ||
1403 | writeb(century, bq4802_regs + 0x0f); | ||
1404 | |||
1405 | writeb(val, bq4802_regs + 0x0e); | ||
1406 | |||
1407 | return 0; | ||
1408 | } | ||
1409 | |||
1410 | static void cmos_get_rtc_time(struct rtc_time *rtc_tm) | ||
1411 | { | ||
1412 | unsigned char ctrl; | ||
1413 | |||
1414 | rtc_tm->tm_sec = CMOS_READ(RTC_SECONDS); | ||
1415 | rtc_tm->tm_min = CMOS_READ(RTC_MINUTES); | ||
1416 | rtc_tm->tm_hour = CMOS_READ(RTC_HOURS); | ||
1417 | rtc_tm->tm_mday = CMOS_READ(RTC_DAY_OF_MONTH); | ||
1418 | rtc_tm->tm_mon = CMOS_READ(RTC_MONTH); | ||
1419 | rtc_tm->tm_year = CMOS_READ(RTC_YEAR); | ||
1420 | rtc_tm->tm_wday = CMOS_READ(RTC_DAY_OF_WEEK); | ||
1421 | |||
1422 | ctrl = CMOS_READ(RTC_CONTROL); | ||
1423 | if (!(ctrl & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
1424 | BCD_TO_BIN(rtc_tm->tm_sec); | ||
1425 | BCD_TO_BIN(rtc_tm->tm_min); | ||
1426 | BCD_TO_BIN(rtc_tm->tm_hour); | ||
1427 | BCD_TO_BIN(rtc_tm->tm_mday); | ||
1428 | BCD_TO_BIN(rtc_tm->tm_mon); | ||
1429 | BCD_TO_BIN(rtc_tm->tm_year); | ||
1430 | BCD_TO_BIN(rtc_tm->tm_wday); | ||
1431 | } | ||
1432 | |||
1433 | if (rtc_tm->tm_year <= 69) | ||
1434 | rtc_tm->tm_year += 100; | ||
1435 | |||
1436 | rtc_tm->tm_mon--; | ||
1437 | } | ||
1438 | |||
1439 | static int cmos_set_rtc_time(struct rtc_time *rtc_tm) | ||
1440 | { | ||
1441 | unsigned char mon, day, hrs, min, sec; | ||
1442 | unsigned char save_control, save_freq_select; | ||
1443 | unsigned int yrs; | ||
1444 | |||
1445 | yrs = rtc_tm->tm_year; | ||
1446 | mon = rtc_tm->tm_mon + 1; | ||
1447 | day = rtc_tm->tm_mday; | ||
1448 | hrs = rtc_tm->tm_hour; | ||
1449 | min = rtc_tm->tm_min; | ||
1450 | sec = rtc_tm->tm_sec; | ||
1451 | |||
1452 | if (yrs >= 100) | ||
1453 | yrs -= 100; | ||
1454 | |||
1455 | if (!(CMOS_READ(RTC_CONTROL) & RTC_DM_BINARY) || RTC_ALWAYS_BCD) { | ||
1456 | BIN_TO_BCD(sec); | ||
1457 | BIN_TO_BCD(min); | ||
1458 | BIN_TO_BCD(hrs); | ||
1459 | BIN_TO_BCD(day); | ||
1460 | BIN_TO_BCD(mon); | ||
1461 | BIN_TO_BCD(yrs); | ||
1462 | } | ||
1463 | |||
1464 | save_control = CMOS_READ(RTC_CONTROL); | ||
1465 | CMOS_WRITE((save_control|RTC_SET), RTC_CONTROL); | ||
1466 | save_freq_select = CMOS_READ(RTC_FREQ_SELECT); | ||
1467 | CMOS_WRITE((save_freq_select|RTC_DIV_RESET2), RTC_FREQ_SELECT); | ||
1468 | |||
1469 | CMOS_WRITE(yrs, RTC_YEAR); | ||
1470 | CMOS_WRITE(mon, RTC_MONTH); | ||
1471 | CMOS_WRITE(day, RTC_DAY_OF_MONTH); | ||
1472 | CMOS_WRITE(hrs, RTC_HOURS); | ||
1473 | CMOS_WRITE(min, RTC_MINUTES); | ||
1474 | CMOS_WRITE(sec, RTC_SECONDS); | ||
1475 | |||
1476 | CMOS_WRITE(save_control, RTC_CONTROL); | ||
1477 | CMOS_WRITE(save_freq_select, RTC_FREQ_SELECT); | ||
1478 | |||
1479 | return 0; | ||
1480 | } | ||
1481 | #endif /* CONFIG_PCI */ | ||
1482 | |||
1483 | static void mostek_get_rtc_time(struct rtc_time *rtc_tm) | ||
1484 | { | ||
1485 | void __iomem *regs = mstk48t02_regs; | ||
1486 | u8 tmp; | ||
1487 | |||
1488 | spin_lock_irq(&mostek_lock); | ||
1489 | |||
1490 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
1491 | tmp |= MSTK_CREG_READ; | ||
1492 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
1493 | |||
1494 | rtc_tm->tm_sec = MSTK_REG_SEC(regs); | ||
1495 | rtc_tm->tm_min = MSTK_REG_MIN(regs); | ||
1496 | rtc_tm->tm_hour = MSTK_REG_HOUR(regs); | ||
1497 | rtc_tm->tm_mday = MSTK_REG_DOM(regs); | ||
1498 | rtc_tm->tm_mon = MSTK_REG_MONTH(regs); | ||
1499 | rtc_tm->tm_year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); | ||
1500 | rtc_tm->tm_wday = MSTK_REG_DOW(regs); | ||
1501 | |||
1502 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
1503 | tmp &= ~MSTK_CREG_READ; | ||
1504 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
1505 | |||
1506 | spin_unlock_irq(&mostek_lock); | ||
1507 | |||
1508 | rtc_tm->tm_mon--; | ||
1509 | rtc_tm->tm_wday--; | ||
1510 | rtc_tm->tm_year -= 1900; | ||
1511 | } | ||
1512 | |||
1513 | static int mostek_set_rtc_time(struct rtc_time *rtc_tm) | ||
1514 | { | ||
1515 | unsigned char mon, day, hrs, min, sec, wday; | ||
1516 | void __iomem *regs = mstk48t02_regs; | ||
1517 | unsigned int yrs; | ||
1518 | u8 tmp; | ||
1519 | |||
1520 | yrs = rtc_tm->tm_year + 1900; | ||
1521 | mon = rtc_tm->tm_mon + 1; | ||
1522 | day = rtc_tm->tm_mday; | ||
1523 | wday = rtc_tm->tm_wday + 1; | ||
1524 | hrs = rtc_tm->tm_hour; | ||
1525 | min = rtc_tm->tm_min; | ||
1526 | sec = rtc_tm->tm_sec; | ||
1527 | |||
1528 | spin_lock_irq(&mostek_lock); | ||
1529 | |||
1530 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
1531 | tmp |= MSTK_CREG_WRITE; | ||
1532 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
1533 | |||
1534 | MSTK_SET_REG_SEC(regs, sec); | ||
1535 | MSTK_SET_REG_MIN(regs, min); | ||
1536 | MSTK_SET_REG_HOUR(regs, hrs); | ||
1537 | MSTK_SET_REG_DOW(regs, wday); | ||
1538 | MSTK_SET_REG_DOM(regs, day); | ||
1539 | MSTK_SET_REG_MONTH(regs, mon); | ||
1540 | MSTK_SET_REG_YEAR(regs, yrs - MSTK_YEAR_ZERO); | ||
1541 | |||
1542 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
1543 | tmp &= ~MSTK_CREG_WRITE; | ||
1544 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
1545 | |||
1546 | spin_unlock_irq(&mostek_lock); | ||
1547 | |||
1548 | return 0; | ||
1549 | } | ||
1550 | |||
1551 | struct mini_rtc_ops { | ||
1552 | void (*get_rtc_time)(struct rtc_time *); | ||
1553 | int (*set_rtc_time)(struct rtc_time *); | ||
1554 | }; | ||
1555 | |||
1556 | static struct mini_rtc_ops starfire_rtc_ops = { | ||
1557 | .get_rtc_time = starfire_get_rtc_time, | ||
1558 | .set_rtc_time = starfire_set_rtc_time, | ||
1559 | }; | ||
1560 | |||
1561 | static struct mini_rtc_ops hypervisor_rtc_ops = { | ||
1562 | .get_rtc_time = hypervisor_get_rtc_time, | ||
1563 | .set_rtc_time = hypervisor_set_rtc_time, | ||
1564 | }; | ||
1565 | |||
1566 | #ifdef CONFIG_PCI | ||
1567 | static struct mini_rtc_ops bq4802_rtc_ops = { | ||
1568 | .get_rtc_time = bq4802_get_rtc_time, | ||
1569 | .set_rtc_time = bq4802_set_rtc_time, | ||
1570 | }; | ||
1571 | |||
1572 | static struct mini_rtc_ops cmos_rtc_ops = { | ||
1573 | .get_rtc_time = cmos_get_rtc_time, | ||
1574 | .set_rtc_time = cmos_set_rtc_time, | ||
1575 | }; | ||
1576 | #endif /* CONFIG_PCI */ | ||
1577 | |||
1578 | static struct mini_rtc_ops mostek_rtc_ops = { | ||
1579 | .get_rtc_time = mostek_get_rtc_time, | ||
1580 | .set_rtc_time = mostek_set_rtc_time, | ||
1581 | }; | ||
1582 | |||
1583 | static struct mini_rtc_ops *mini_rtc_ops; | ||
1584 | |||
1585 | static inline void mini_get_rtc_time(struct rtc_time *time) | ||
1586 | { | ||
1587 | unsigned long flags; | ||
1588 | |||
1589 | spin_lock_irqsave(&rtc_lock, flags); | ||
1590 | mini_rtc_ops->get_rtc_time(time); | ||
1591 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
1592 | } | ||
1593 | |||
1594 | static inline int mini_set_rtc_time(struct rtc_time *time) | ||
1595 | { | ||
1596 | unsigned long flags; | ||
1597 | int err; | ||
1598 | |||
1599 | spin_lock_irqsave(&rtc_lock, flags); | ||
1600 | err = mini_rtc_ops->set_rtc_time(time); | ||
1601 | spin_unlock_irqrestore(&rtc_lock, flags); | ||
1602 | |||
1603 | return err; | ||
1604 | } | ||
1605 | |||
1606 | static int mini_rtc_ioctl(struct inode *inode, struct file *file, | ||
1607 | unsigned int cmd, unsigned long arg) | ||
1608 | { | ||
1609 | struct rtc_time wtime; | ||
1610 | void __user *argp = (void __user *)arg; | ||
1611 | |||
1612 | switch (cmd) { | ||
1613 | |||
1614 | case RTC_PLL_GET: | ||
1615 | return -EINVAL; | ||
1616 | |||
1617 | case RTC_PLL_SET: | ||
1618 | return -EINVAL; | ||
1619 | |||
1620 | case RTC_UIE_OFF: /* disable ints from RTC updates. */ | ||
1621 | return 0; | ||
1622 | |||
1623 | case RTC_UIE_ON: /* enable ints for RTC updates. */ | ||
1624 | return -EINVAL; | ||
1625 | |||
1626 | case RTC_RD_TIME: /* Read the time/date from RTC */ | ||
1627 | /* this doesn't get week-day, who cares */ | ||
1628 | memset(&wtime, 0, sizeof(wtime)); | ||
1629 | mini_get_rtc_time(&wtime); | ||
1630 | |||
1631 | return copy_to_user(argp, &wtime, sizeof(wtime)) ? -EFAULT : 0; | ||
1632 | |||
1633 | case RTC_SET_TIME: /* Set the RTC */ | ||
1634 | { | ||
1635 | int year, days; | ||
1636 | |||
1637 | if (!capable(CAP_SYS_TIME)) | ||
1638 | return -EACCES; | ||
1639 | |||
1640 | if (copy_from_user(&wtime, argp, sizeof(wtime))) | ||
1641 | return -EFAULT; | ||
1642 | |||
1643 | year = wtime.tm_year + 1900; | ||
1644 | days = month_days[wtime.tm_mon] + | ||
1645 | ((wtime.tm_mon == 1) && leapyear(year)); | ||
1646 | |||
1647 | if ((wtime.tm_mon < 0 || wtime.tm_mon > 11) || | ||
1648 | (wtime.tm_mday < 1)) | ||
1649 | return -EINVAL; | ||
1650 | |||
1651 | if (wtime.tm_mday < 0 || wtime.tm_mday > days) | ||
1652 | return -EINVAL; | ||
1653 | |||
1654 | if (wtime.tm_hour < 0 || wtime.tm_hour >= 24 || | ||
1655 | wtime.tm_min < 0 || wtime.tm_min >= 60 || | ||
1656 | wtime.tm_sec < 0 || wtime.tm_sec >= 60) | ||
1657 | return -EINVAL; | ||
1658 | |||
1659 | return mini_set_rtc_time(&wtime); | ||
1660 | } | ||
1661 | } | ||
1662 | |||
1663 | return -EINVAL; | ||
1664 | } | ||
1665 | |||
1666 | static int mini_rtc_open(struct inode *inode, struct file *file) | ||
1667 | { | ||
1668 | lock_kernel(); | ||
1669 | if (mini_rtc_status & RTC_IS_OPEN) { | ||
1670 | unlock_kernel(); | ||
1671 | return -EBUSY; | ||
1672 | } | ||
1673 | |||
1674 | mini_rtc_status |= RTC_IS_OPEN; | ||
1675 | unlock_kernel(); | ||
1676 | |||
1677 | return 0; | ||
1678 | } | ||
1679 | |||
1680 | static int mini_rtc_release(struct inode *inode, struct file *file) | ||
1681 | { | ||
1682 | mini_rtc_status &= ~RTC_IS_OPEN; | ||
1683 | return 0; | ||
1684 | } | ||
1685 | |||
1686 | |||
1687 | static const struct file_operations mini_rtc_fops = { | ||
1688 | .owner = THIS_MODULE, | ||
1689 | .ioctl = mini_rtc_ioctl, | ||
1690 | .open = mini_rtc_open, | ||
1691 | .release = mini_rtc_release, | ||
1692 | }; | ||
1693 | |||
1694 | static struct miscdevice rtc_mini_dev = | ||
1695 | { | ||
1696 | .minor = RTC_MINOR, | ||
1697 | .name = "rtc", | ||
1698 | .fops = &mini_rtc_fops, | ||
1699 | }; | ||
1700 | |||
1701 | static int __init rtc_mini_init(void) | ||
1702 | { | ||
1703 | int retval; | ||
1704 | |||
1705 | if (tlb_type == hypervisor) | ||
1706 | mini_rtc_ops = &hypervisor_rtc_ops; | ||
1707 | else if (this_is_starfire) | ||
1708 | mini_rtc_ops = &starfire_rtc_ops; | ||
1709 | #ifdef CONFIG_PCI | ||
1710 | else if (bq4802_regs) | ||
1711 | mini_rtc_ops = &bq4802_rtc_ops; | ||
1712 | else if (ds1287_regs) | ||
1713 | mini_rtc_ops = &cmos_rtc_ops; | ||
1714 | #endif /* CONFIG_PCI */ | ||
1715 | else if (mstk48t02_regs) | ||
1716 | mini_rtc_ops = &mostek_rtc_ops; | ||
1717 | else | ||
1718 | return -ENODEV; | ||
1719 | |||
1720 | printk(KERN_INFO "Mini RTC Driver\n"); | ||
1721 | |||
1722 | retval = misc_register(&rtc_mini_dev); | ||
1723 | if (retval < 0) | ||
1724 | return retval; | ||
1725 | |||
1726 | return 0; | ||
1727 | } | ||
1728 | |||
1729 | static void __exit rtc_mini_exit(void) | ||
1730 | { | ||
1731 | misc_deregister(&rtc_mini_dev); | ||
1732 | } | ||
1733 | |||
1734 | int __devinit read_current_timer(unsigned long *timer_val) | 880 | int __devinit read_current_timer(unsigned long *timer_val) |
1735 | { | 881 | { |
1736 | *timer_val = tick_ops->get_tick(); | 882 | *timer_val = tick_ops->get_tick(); |
1737 | return 0; | 883 | return 0; |
1738 | } | 884 | } |
1739 | |||
1740 | module_init(rtc_mini_init); | ||
1741 | module_exit(rtc_mini_exit); | ||
diff --git a/arch/sparc64/kernel/traps.c b/arch/sparc64/kernel/traps.c index c824df13f589..81ccd22e78d4 100644 --- a/arch/sparc64/kernel/traps.c +++ b/arch/sparc64/kernel/traps.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <asm/timer.h> | 38 | #include <asm/timer.h> |
39 | #include <asm/head.h> | 39 | #include <asm/head.h> |
40 | #include <asm/prom.h> | 40 | #include <asm/prom.h> |
41 | #include <asm/memctrl.h> | ||
41 | 42 | ||
42 | #include "entry.h" | 43 | #include "entry.h" |
43 | #include "kstack.h" | 44 | #include "kstack.h" |
@@ -129,6 +130,56 @@ void do_BUG(const char *file, int line) | |||
129 | } | 130 | } |
130 | #endif | 131 | #endif |
131 | 132 | ||
133 | static DEFINE_SPINLOCK(dimm_handler_lock); | ||
134 | static dimm_printer_t dimm_handler; | ||
135 | |||
136 | static int sprintf_dimm(int synd_code, unsigned long paddr, char *buf, int buflen) | ||
137 | { | ||
138 | unsigned long flags; | ||
139 | int ret = -ENODEV; | ||
140 | |||
141 | spin_lock_irqsave(&dimm_handler_lock, flags); | ||
142 | if (dimm_handler) { | ||
143 | ret = dimm_handler(synd_code, paddr, buf, buflen); | ||
144 | } else if (tlb_type == spitfire) { | ||
145 | if (prom_getunumber(synd_code, paddr, buf, buflen) == -1) | ||
146 | ret = -EINVAL; | ||
147 | else | ||
148 | ret = 0; | ||
149 | } else | ||
150 | ret = -ENODEV; | ||
151 | spin_unlock_irqrestore(&dimm_handler_lock, flags); | ||
152 | |||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | int register_dimm_printer(dimm_printer_t func) | ||
157 | { | ||
158 | unsigned long flags; | ||
159 | int ret = 0; | ||
160 | |||
161 | spin_lock_irqsave(&dimm_handler_lock, flags); | ||
162 | if (!dimm_handler) | ||
163 | dimm_handler = func; | ||
164 | else | ||
165 | ret = -EEXIST; | ||
166 | spin_unlock_irqrestore(&dimm_handler_lock, flags); | ||
167 | |||
168 | return ret; | ||
169 | } | ||
170 | EXPORT_SYMBOL_GPL(register_dimm_printer); | ||
171 | |||
172 | void unregister_dimm_printer(dimm_printer_t func) | ||
173 | { | ||
174 | unsigned long flags; | ||
175 | |||
176 | spin_lock_irqsave(&dimm_handler_lock, flags); | ||
177 | if (dimm_handler == func) | ||
178 | dimm_handler = NULL; | ||
179 | spin_unlock_irqrestore(&dimm_handler_lock, flags); | ||
180 | } | ||
181 | EXPORT_SYMBOL_GPL(unregister_dimm_printer); | ||
182 | |||
132 | void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) | 183 | void spitfire_insn_access_exception(struct pt_regs *regs, unsigned long sfsr, unsigned long sfar) |
133 | { | 184 | { |
134 | siginfo_t info; | 185 | siginfo_t info; |
@@ -291,10 +342,7 @@ void sun4v_data_access_exception_tl1(struct pt_regs *regs, unsigned long addr, u | |||
291 | } | 342 | } |
292 | 343 | ||
293 | #ifdef CONFIG_PCI | 344 | #ifdef CONFIG_PCI |
294 | /* This is really pathetic... */ | 345 | #include "pci_impl.h" |
295 | extern volatile int pci_poke_in_progress; | ||
296 | extern volatile int pci_poke_cpu; | ||
297 | extern volatile int pci_poke_faulted; | ||
298 | #endif | 346 | #endif |
299 | 347 | ||
300 | /* When access exceptions happen, we must do this. */ | 348 | /* When access exceptions happen, we must do this. */ |
@@ -376,8 +424,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un | |||
376 | 424 | ||
377 | if (udbl & bit) { | 425 | if (udbl & bit) { |
378 | scode = ecc_syndrome_table[udbl & 0xff]; | 426 | scode = ecc_syndrome_table[udbl & 0xff]; |
379 | if (prom_getunumber(scode, afar, | 427 | if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0) |
380 | memmod_str, sizeof(memmod_str)) == -1) | ||
381 | p = syndrome_unknown; | 428 | p = syndrome_unknown; |
382 | else | 429 | else |
383 | p = memmod_str; | 430 | p = memmod_str; |
@@ -388,8 +435,7 @@ static void spitfire_log_udb_syndrome(unsigned long afar, unsigned long udbh, un | |||
388 | 435 | ||
389 | if (udbh & bit) { | 436 | if (udbh & bit) { |
390 | scode = ecc_syndrome_table[udbh & 0xff]; | 437 | scode = ecc_syndrome_table[udbh & 0xff]; |
391 | if (prom_getunumber(scode, afar, | 438 | if (sprintf_dimm(scode, afar, memmod_str, sizeof(memmod_str)) < 0) |
392 | memmod_str, sizeof(memmod_str)) == -1) | ||
393 | p = syndrome_unknown; | 439 | p = syndrome_unknown; |
394 | else | 440 | else |
395 | p = memmod_str; | 441 | p = memmod_str; |
@@ -1062,8 +1108,6 @@ static const char *cheetah_get_string(unsigned long bit) | |||
1062 | return "???"; | 1108 | return "???"; |
1063 | } | 1109 | } |
1064 | 1110 | ||
1065 | extern int chmc_getunumber(int, unsigned long, char *, int); | ||
1066 | |||
1067 | static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, | 1111 | static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *info, |
1068 | unsigned long afsr, unsigned long afar, int recoverable) | 1112 | unsigned long afsr, unsigned long afar, int recoverable) |
1069 | { | 1113 | { |
@@ -1105,7 +1149,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in | |||
1105 | 1149 | ||
1106 | syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; | 1150 | syndrome = (afsr & CHAFSR_E_SYNDROME) >> CHAFSR_E_SYNDROME_SHIFT; |
1107 | syndrome = cheetah_ecc_syntab[syndrome]; | 1151 | syndrome = cheetah_ecc_syntab[syndrome]; |
1108 | ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); | 1152 | ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum)); |
1109 | if (ret != -1) | 1153 | if (ret != -1) |
1110 | printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", | 1154 | printk("%s" "ERROR(%d): AFAR E-syndrome [%s]\n", |
1111 | (recoverable ? KERN_WARNING : KERN_CRIT), | 1155 | (recoverable ? KERN_WARNING : KERN_CRIT), |
@@ -1116,7 +1160,7 @@ static void cheetah_log_errors(struct pt_regs *regs, struct cheetah_err_info *in | |||
1116 | 1160 | ||
1117 | syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; | 1161 | syndrome = (afsr & CHAFSR_M_SYNDROME) >> CHAFSR_M_SYNDROME_SHIFT; |
1118 | syndrome = cheetah_mtag_syntab[syndrome]; | 1162 | syndrome = cheetah_mtag_syntab[syndrome]; |
1119 | ret = chmc_getunumber(syndrome, afar, unum, sizeof(unum)); | 1163 | ret = sprintf_dimm(syndrome, afar, unum, sizeof(unum)); |
1120 | if (ret != -1) | 1164 | if (ret != -1) |
1121 | printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", | 1165 | printk("%s" "ERROR(%d): AFAR M-syndrome [%s]\n", |
1122 | (recoverable ? KERN_WARNING : KERN_CRIT), | 1166 | (recoverable ? KERN_WARNING : KERN_CRIT), |
@@ -2224,7 +2268,6 @@ void die_if_kernel(char *str, struct pt_regs *regs) | |||
2224 | 2268 | ||
2225 | extern int handle_popc(u32 insn, struct pt_regs *regs); | 2269 | extern int handle_popc(u32 insn, struct pt_regs *regs); |
2226 | extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); | 2270 | extern int handle_ldf_stq(u32 insn, struct pt_regs *regs); |
2227 | extern int vis_emul(struct pt_regs *, unsigned int); | ||
2228 | 2271 | ||
2229 | void do_illegal_instruction(struct pt_regs *regs) | 2272 | void do_illegal_instruction(struct pt_regs *regs) |
2230 | { | 2273 | { |
diff --git a/arch/sparc64/kernel/vio.c b/arch/sparc64/kernel/vio.c index a490077891a4..92b1f8ec01de 100644 --- a/arch/sparc64/kernel/vio.c +++ b/arch/sparc64/kernel/vio.c | |||
@@ -152,7 +152,7 @@ show_pciobppath_attr(struct device *dev, struct device_attribute *attr, | |||
152 | static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, | 152 | static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, |
153 | show_pciobppath_attr, NULL); | 153 | show_pciobppath_attr, NULL); |
154 | 154 | ||
155 | struct device_node *cdev_node; | 155 | static struct device_node *cdev_node; |
156 | 156 | ||
157 | static struct vio_dev *root_vdev; | 157 | static struct vio_dev *root_vdev; |
158 | static u64 cdev_cfg_handle; | 158 | static u64 cdev_cfg_handle; |
@@ -371,9 +371,9 @@ static struct mdesc_notifier_client vio_ds_notifier = { | |||
371 | .node_name = "domain-services-port", | 371 | .node_name = "domain-services-port", |
372 | }; | 372 | }; |
373 | 373 | ||
374 | const char *channel_devices_node = "channel-devices"; | 374 | static const char *channel_devices_node = "channel-devices"; |
375 | const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; | 375 | static const char *channel_devices_compat = "SUNW,sun4v-channel-devices"; |
376 | const char *cfg_handle_prop = "cfg-handle"; | 376 | static const char *cfg_handle_prop = "cfg-handle"; |
377 | 377 | ||
378 | static int __init vio_init(void) | 378 | static int __init vio_init(void) |
379 | { | 379 | { |
diff --git a/arch/sparc64/kernel/visemul.c b/arch/sparc64/kernel/visemul.c index c3fd64706b53..9e05cb5cb855 100644 --- a/arch/sparc64/kernel/visemul.c +++ b/arch/sparc64/kernel/visemul.c | |||
@@ -243,7 +243,7 @@ static inline unsigned int *fps_regaddr(struct fpustate *f, | |||
243 | struct edge_tab { | 243 | struct edge_tab { |
244 | u16 left, right; | 244 | u16 left, right; |
245 | }; | 245 | }; |
246 | struct edge_tab edge8_tab[8] = { | 246 | static struct edge_tab edge8_tab[8] = { |
247 | { 0xff, 0x80 }, | 247 | { 0xff, 0x80 }, |
248 | { 0x7f, 0xc0 }, | 248 | { 0x7f, 0xc0 }, |
249 | { 0x3f, 0xe0 }, | 249 | { 0x3f, 0xe0 }, |
@@ -253,7 +253,7 @@ struct edge_tab edge8_tab[8] = { | |||
253 | { 0x03, 0xfe }, | 253 | { 0x03, 0xfe }, |
254 | { 0x01, 0xff }, | 254 | { 0x01, 0xff }, |
255 | }; | 255 | }; |
256 | struct edge_tab edge8_tab_l[8] = { | 256 | static struct edge_tab edge8_tab_l[8] = { |
257 | { 0xff, 0x01 }, | 257 | { 0xff, 0x01 }, |
258 | { 0xfe, 0x03 }, | 258 | { 0xfe, 0x03 }, |
259 | { 0xfc, 0x07 }, | 259 | { 0xfc, 0x07 }, |
@@ -263,23 +263,23 @@ struct edge_tab edge8_tab_l[8] = { | |||
263 | { 0xc0, 0x7f }, | 263 | { 0xc0, 0x7f }, |
264 | { 0x80, 0xff }, | 264 | { 0x80, 0xff }, |
265 | }; | 265 | }; |
266 | struct edge_tab edge16_tab[4] = { | 266 | static struct edge_tab edge16_tab[4] = { |
267 | { 0xf, 0x8 }, | 267 | { 0xf, 0x8 }, |
268 | { 0x7, 0xc }, | 268 | { 0x7, 0xc }, |
269 | { 0x3, 0xe }, | 269 | { 0x3, 0xe }, |
270 | { 0x1, 0xf }, | 270 | { 0x1, 0xf }, |
271 | }; | 271 | }; |
272 | struct edge_tab edge16_tab_l[4] = { | 272 | static struct edge_tab edge16_tab_l[4] = { |
273 | { 0xf, 0x1 }, | 273 | { 0xf, 0x1 }, |
274 | { 0xe, 0x3 }, | 274 | { 0xe, 0x3 }, |
275 | { 0xc, 0x7 }, | 275 | { 0xc, 0x7 }, |
276 | { 0x8, 0xf }, | 276 | { 0x8, 0xf }, |
277 | }; | 277 | }; |
278 | struct edge_tab edge32_tab[2] = { | 278 | static struct edge_tab edge32_tab[2] = { |
279 | { 0x3, 0x2 }, | 279 | { 0x3, 0x2 }, |
280 | { 0x1, 0x3 }, | 280 | { 0x1, 0x3 }, |
281 | }; | 281 | }; |
282 | struct edge_tab edge32_tab_l[2] = { | 282 | static struct edge_tab edge32_tab_l[2] = { |
283 | { 0x3, 0x1 }, | 283 | { 0x3, 0x1 }, |
284 | { 0x2, 0x3 }, | 284 | { 0x2, 0x3 }, |
285 | }; | 285 | }; |
diff --git a/arch/sparc64/mm/fault.c b/arch/sparc64/mm/fault.c index ea7d7ae76bc2..a9e474bf6385 100644 --- a/arch/sparc64/mm/fault.c +++ b/arch/sparc64/mm/fault.c | |||
@@ -51,43 +51,6 @@ static inline int notify_page_fault(struct pt_regs *regs) | |||
51 | } | 51 | } |
52 | #endif | 52 | #endif |
53 | 53 | ||
54 | /* | ||
55 | * To debug kernel to catch accesses to certain virtual/physical addresses. | ||
56 | * Mode = 0 selects physical watchpoints, mode = 1 selects virtual watchpoints. | ||
57 | * flags = VM_READ watches memread accesses, flags = VM_WRITE watches memwrite accesses. | ||
58 | * Caller passes in a 64bit aligned addr, with mask set to the bytes that need to be | ||
59 | * watched. This is only useful on a single cpu machine for now. After the watchpoint | ||
60 | * is detected, the process causing it will be killed, thus preventing an infinite loop. | ||
61 | */ | ||
62 | void set_brkpt(unsigned long addr, unsigned char mask, int flags, int mode) | ||
63 | { | ||
64 | unsigned long lsubits; | ||
65 | |||
66 | __asm__ __volatile__("ldxa [%%g0] %1, %0" | ||
67 | : "=r" (lsubits) | ||
68 | : "i" (ASI_LSU_CONTROL)); | ||
69 | lsubits &= ~(LSU_CONTROL_PM | LSU_CONTROL_VM | | ||
70 | LSU_CONTROL_PR | LSU_CONTROL_VR | | ||
71 | LSU_CONTROL_PW | LSU_CONTROL_VW); | ||
72 | |||
73 | __asm__ __volatile__("stxa %0, [%1] %2\n\t" | ||
74 | "membar #Sync" | ||
75 | : /* no outputs */ | ||
76 | : "r" (addr), "r" (mode ? VIRT_WATCHPOINT : PHYS_WATCHPOINT), | ||
77 | "i" (ASI_DMMU)); | ||
78 | |||
79 | lsubits |= ((unsigned long)mask << (mode ? 25 : 33)); | ||
80 | if (flags & VM_READ) | ||
81 | lsubits |= (mode ? LSU_CONTROL_VR : LSU_CONTROL_PR); | ||
82 | if (flags & VM_WRITE) | ||
83 | lsubits |= (mode ? LSU_CONTROL_VW : LSU_CONTROL_PW); | ||
84 | __asm__ __volatile__("stxa %0, [%%g0] %1\n\t" | ||
85 | "membar #Sync" | ||
86 | : /* no outputs */ | ||
87 | : "r" (lsubits), "i" (ASI_LSU_CONTROL) | ||
88 | : "memory"); | ||
89 | } | ||
90 | |||
91 | static void __kprobes unhandled_fault(unsigned long address, | 54 | static void __kprobes unhandled_fault(unsigned long address, |
92 | struct task_struct *tsk, | 55 | struct task_struct *tsk, |
93 | struct pt_regs *regs) | 56 | struct pt_regs *regs) |
diff --git a/arch/sparc64/mm/init.c b/arch/sparc64/mm/init.c index a41df7bef035..3c10daf8fc01 100644 --- a/arch/sparc64/mm/init.c +++ b/arch/sparc64/mm/init.c | |||
@@ -46,15 +46,11 @@ | |||
46 | #include <asm/tsb.h> | 46 | #include <asm/tsb.h> |
47 | #include <asm/hypervisor.h> | 47 | #include <asm/hypervisor.h> |
48 | #include <asm/prom.h> | 48 | #include <asm/prom.h> |
49 | #include <asm/sstate.h> | ||
50 | #include <asm/mdesc.h> | 49 | #include <asm/mdesc.h> |
51 | #include <asm/cpudata.h> | 50 | #include <asm/cpudata.h> |
52 | #include <asm/irq.h> | 51 | #include <asm/irq.h> |
53 | 52 | ||
54 | #define MAX_PHYS_ADDRESS (1UL << 42UL) | 53 | #include "init.h" |
55 | #define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) | ||
56 | #define KPTE_BITMAP_BYTES \ | ||
57 | ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8) | ||
58 | 54 | ||
59 | unsigned long kern_linear_pte_xor[2] __read_mostly; | 55 | unsigned long kern_linear_pte_xor[2] __read_mostly; |
60 | 56 | ||
@@ -416,17 +412,9 @@ void mmu_info(struct seq_file *m) | |||
416 | #endif /* CONFIG_DEBUG_DCFLUSH */ | 412 | #endif /* CONFIG_DEBUG_DCFLUSH */ |
417 | } | 413 | } |
418 | 414 | ||
419 | struct linux_prom_translation { | ||
420 | unsigned long virt; | ||
421 | unsigned long size; | ||
422 | unsigned long data; | ||
423 | }; | ||
424 | |||
425 | /* Exported for kernel TLB miss handling in ktlb.S */ | ||
426 | struct linux_prom_translation prom_trans[512] __read_mostly; | 415 | struct linux_prom_translation prom_trans[512] __read_mostly; |
427 | unsigned int prom_trans_ents __read_mostly; | 416 | unsigned int prom_trans_ents __read_mostly; |
428 | 417 | ||
429 | /* Exported for SMP bootup purposes. */ | ||
430 | unsigned long kern_locked_tte_data; | 418 | unsigned long kern_locked_tte_data; |
431 | 419 | ||
432 | /* The obp translations are saved based on 8k pagesize, since obp can | 420 | /* The obp translations are saved based on 8k pagesize, since obp can |
@@ -938,6 +926,10 @@ int of_node_to_nid(struct device_node *dp) | |||
938 | int count, nid; | 926 | int count, nid; |
939 | u64 grp; | 927 | u64 grp; |
940 | 928 | ||
929 | /* This is the right thing to do on currently supported | ||
930 | * SUN4U NUMA platforms as well, as the PCI controller does | ||
931 | * not sit behind any particular memory controller. | ||
932 | */ | ||
941 | if (!mlgroups) | 933 | if (!mlgroups) |
942 | return -1; | 934 | return -1; |
943 | 935 | ||
@@ -1206,8 +1198,44 @@ out: | |||
1206 | return err; | 1198 | return err; |
1207 | } | 1199 | } |
1208 | 1200 | ||
1201 | static int __init numa_parse_jbus(void) | ||
1202 | { | ||
1203 | unsigned long cpu, index; | ||
1204 | |||
1205 | /* NUMA node id is encoded in bits 36 and higher, and there is | ||
1206 | * a 1-to-1 mapping from CPU ID to NUMA node ID. | ||
1207 | */ | ||
1208 | index = 0; | ||
1209 | for_each_present_cpu(cpu) { | ||
1210 | numa_cpu_lookup_table[cpu] = index; | ||
1211 | numa_cpumask_lookup_table[index] = cpumask_of_cpu(cpu); | ||
1212 | node_masks[index].mask = ~((1UL << 36UL) - 1UL); | ||
1213 | node_masks[index].val = cpu << 36UL; | ||
1214 | |||
1215 | index++; | ||
1216 | } | ||
1217 | num_node_masks = index; | ||
1218 | |||
1219 | add_node_ranges(); | ||
1220 | |||
1221 | for (index = 0; index < num_node_masks; index++) { | ||
1222 | allocate_node_data(index); | ||
1223 | node_set_online(index); | ||
1224 | } | ||
1225 | |||
1226 | return 0; | ||
1227 | } | ||
1228 | |||
1209 | static int __init numa_parse_sun4u(void) | 1229 | static int __init numa_parse_sun4u(void) |
1210 | { | 1230 | { |
1231 | if (tlb_type == cheetah || tlb_type == cheetah_plus) { | ||
1232 | unsigned long ver; | ||
1233 | |||
1234 | __asm__ ("rdpr %%ver, %0" : "=r" (ver)); | ||
1235 | if ((ver >> 32UL) == __JALAPENO_ID || | ||
1236 | (ver >> 32UL) == __SERRANO_ID) | ||
1237 | return numa_parse_jbus(); | ||
1238 | } | ||
1211 | return -1; | 1239 | return -1; |
1212 | } | 1240 | } |
1213 | 1241 | ||
@@ -1633,8 +1661,6 @@ void __cpuinit sun4v_ktsb_register(void) | |||
1633 | 1661 | ||
1634 | /* paging_init() sets up the page tables */ | 1662 | /* paging_init() sets up the page tables */ |
1635 | 1663 | ||
1636 | extern void central_probe(void); | ||
1637 | |||
1638 | static unsigned long last_valid_pfn; | 1664 | static unsigned long last_valid_pfn; |
1639 | pgd_t swapper_pg_dir[2048]; | 1665 | pgd_t swapper_pg_dir[2048]; |
1640 | 1666 | ||
@@ -1679,8 +1705,6 @@ void __init paging_init(void) | |||
1679 | kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; | 1705 | kern_base = (prom_boot_mapping_phys_low >> 22UL) << 22UL; |
1680 | kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; | 1706 | kern_size = (unsigned long)&_end - (unsigned long)KERNBASE; |
1681 | 1707 | ||
1682 | sstate_booting(); | ||
1683 | |||
1684 | /* Invalidate both kernel TSBs. */ | 1708 | /* Invalidate both kernel TSBs. */ |
1685 | memset(swapper_tsb, 0x40, sizeof(swapper_tsb)); | 1709 | memset(swapper_tsb, 0x40, sizeof(swapper_tsb)); |
1686 | #ifndef CONFIG_DEBUG_PAGEALLOC | 1710 | #ifndef CONFIG_DEBUG_PAGEALLOC |
@@ -1803,9 +1827,6 @@ void __init paging_init(void) | |||
1803 | } | 1827 | } |
1804 | 1828 | ||
1805 | printk("Booting Linux...\n"); | 1829 | printk("Booting Linux...\n"); |
1806 | |||
1807 | central_probe(); | ||
1808 | cpu_probe(); | ||
1809 | } | 1830 | } |
1810 | 1831 | ||
1811 | int __init page_in_phys_avail(unsigned long paddr) | 1832 | int __init page_in_phys_avail(unsigned long paddr) |
@@ -2032,7 +2053,6 @@ pgprot_t PAGE_COPY __read_mostly; | |||
2032 | pgprot_t PAGE_SHARED __read_mostly; | 2053 | pgprot_t PAGE_SHARED __read_mostly; |
2033 | EXPORT_SYMBOL(PAGE_SHARED); | 2054 | EXPORT_SYMBOL(PAGE_SHARED); |
2034 | 2055 | ||
2035 | pgprot_t PAGE_EXEC __read_mostly; | ||
2036 | unsigned long pg_iobits __read_mostly; | 2056 | unsigned long pg_iobits __read_mostly; |
2037 | 2057 | ||
2038 | unsigned long _PAGE_IE __read_mostly; | 2058 | unsigned long _PAGE_IE __read_mostly; |
@@ -2045,14 +2065,6 @@ unsigned long _PAGE_CACHE __read_mostly; | |||
2045 | EXPORT_SYMBOL(_PAGE_CACHE); | 2065 | EXPORT_SYMBOL(_PAGE_CACHE); |
2046 | 2066 | ||
2047 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | 2067 | #ifdef CONFIG_SPARSEMEM_VMEMMAP |
2048 | |||
2049 | #define VMEMMAP_CHUNK_SHIFT 22 | ||
2050 | #define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) | ||
2051 | #define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL) | ||
2052 | #define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK) | ||
2053 | |||
2054 | #define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \ | ||
2055 | sizeof(struct page *)) >> VMEMMAP_CHUNK_SHIFT) | ||
2056 | unsigned long vmemmap_table[VMEMMAP_SIZE]; | 2068 | unsigned long vmemmap_table[VMEMMAP_SIZE]; |
2057 | 2069 | ||
2058 | int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) | 2070 | int __meminit vmemmap_populate(struct page *start, unsigned long nr, int node) |
@@ -2136,7 +2148,6 @@ static void __init sun4u_pgprot_init(void) | |||
2136 | _PAGE_CACHE_4U | _PAGE_P_4U | | 2148 | _PAGE_CACHE_4U | _PAGE_P_4U | |
2137 | __ACCESS_BITS_4U | __DIRTY_BITS_4U | | 2149 | __ACCESS_BITS_4U | __DIRTY_BITS_4U | |
2138 | _PAGE_EXEC_4U | _PAGE_L_4U); | 2150 | _PAGE_EXEC_4U | _PAGE_L_4U); |
2139 | PAGE_EXEC = __pgprot(_PAGE_EXEC_4U); | ||
2140 | 2151 | ||
2141 | _PAGE_IE = _PAGE_IE_4U; | 2152 | _PAGE_IE = _PAGE_IE_4U; |
2142 | _PAGE_E = _PAGE_E_4U; | 2153 | _PAGE_E = _PAGE_E_4U; |
@@ -2147,10 +2158,10 @@ static void __init sun4u_pgprot_init(void) | |||
2147 | 2158 | ||
2148 | #ifdef CONFIG_DEBUG_PAGEALLOC | 2159 | #ifdef CONFIG_DEBUG_PAGEALLOC |
2149 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4U) ^ | 2160 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4U) ^ |
2150 | 0xfffff80000000000; | 2161 | 0xfffff80000000000UL; |
2151 | #else | 2162 | #else |
2152 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4U) ^ | 2163 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4U) ^ |
2153 | 0xfffff80000000000; | 2164 | 0xfffff80000000000UL; |
2154 | #endif | 2165 | #endif |
2155 | kern_linear_pte_xor[0] |= (_PAGE_CP_4U | _PAGE_CV_4U | | 2166 | kern_linear_pte_xor[0] |= (_PAGE_CP_4U | _PAGE_CV_4U | |
2156 | _PAGE_P_4U | _PAGE_W_4U); | 2167 | _PAGE_P_4U | _PAGE_W_4U); |
@@ -2188,7 +2199,6 @@ static void __init sun4v_pgprot_init(void) | |||
2188 | __ACCESS_BITS_4V | __DIRTY_BITS_4V | | 2199 | __ACCESS_BITS_4V | __DIRTY_BITS_4V | |
2189 | _PAGE_EXEC_4V); | 2200 | _PAGE_EXEC_4V); |
2190 | PAGE_KERNEL_LOCKED = PAGE_KERNEL; | 2201 | PAGE_KERNEL_LOCKED = PAGE_KERNEL; |
2191 | PAGE_EXEC = __pgprot(_PAGE_EXEC_4V); | ||
2192 | 2202 | ||
2193 | _PAGE_IE = _PAGE_IE_4V; | 2203 | _PAGE_IE = _PAGE_IE_4V; |
2194 | _PAGE_E = _PAGE_E_4V; | 2204 | _PAGE_E = _PAGE_E_4V; |
@@ -2196,20 +2206,20 @@ static void __init sun4v_pgprot_init(void) | |||
2196 | 2206 | ||
2197 | #ifdef CONFIG_DEBUG_PAGEALLOC | 2207 | #ifdef CONFIG_DEBUG_PAGEALLOC |
2198 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ | 2208 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ |
2199 | 0xfffff80000000000; | 2209 | 0xfffff80000000000UL; |
2200 | #else | 2210 | #else |
2201 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^ | 2211 | kern_linear_pte_xor[0] = (_PAGE_VALID | _PAGE_SZ4MB_4V) ^ |
2202 | 0xfffff80000000000; | 2212 | 0xfffff80000000000UL; |
2203 | #endif | 2213 | #endif |
2204 | kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V | | 2214 | kern_linear_pte_xor[0] |= (_PAGE_CP_4V | _PAGE_CV_4V | |
2205 | _PAGE_P_4V | _PAGE_W_4V); | 2215 | _PAGE_P_4V | _PAGE_W_4V); |
2206 | 2216 | ||
2207 | #ifdef CONFIG_DEBUG_PAGEALLOC | 2217 | #ifdef CONFIG_DEBUG_PAGEALLOC |
2208 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ | 2218 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZBITS_4V) ^ |
2209 | 0xfffff80000000000; | 2219 | 0xfffff80000000000UL; |
2210 | #else | 2220 | #else |
2211 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^ | 2221 | kern_linear_pte_xor[1] = (_PAGE_VALID | _PAGE_SZ256MB_4V) ^ |
2212 | 0xfffff80000000000; | 2222 | 0xfffff80000000000UL; |
2213 | #endif | 2223 | #endif |
2214 | kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V | | 2224 | kern_linear_pte_xor[1] |= (_PAGE_CP_4V | _PAGE_CV_4V | |
2215 | _PAGE_P_4V | _PAGE_W_4V); | 2225 | _PAGE_P_4V | _PAGE_W_4V); |
diff --git a/arch/sparc64/mm/init.h b/arch/sparc64/mm/init.h new file mode 100644 index 000000000000..16063870a489 --- /dev/null +++ b/arch/sparc64/mm/init.h | |||
@@ -0,0 +1,49 @@ | |||
1 | #ifndef _SPARC64_MM_INIT_H | ||
2 | #define _SPARC64_MM_INIT_H | ||
3 | |||
4 | /* Most of the symbols in this file are defined in init.c and | ||
5 | * marked non-static so that assembler code can get at them. | ||
6 | */ | ||
7 | |||
8 | #define MAX_PHYS_ADDRESS (1UL << 42UL) | ||
9 | #define KPTE_BITMAP_CHUNK_SZ (256UL * 1024UL * 1024UL) | ||
10 | #define KPTE_BITMAP_BYTES \ | ||
11 | ((MAX_PHYS_ADDRESS / KPTE_BITMAP_CHUNK_SZ) / 8) | ||
12 | |||
13 | extern unsigned long kern_linear_pte_xor[2]; | ||
14 | extern unsigned long kpte_linear_bitmap[KPTE_BITMAP_BYTES / sizeof(unsigned long)]; | ||
15 | extern unsigned int sparc64_highest_unlocked_tlb_ent; | ||
16 | extern unsigned long sparc64_kern_pri_context; | ||
17 | extern unsigned long sparc64_kern_pri_nuc_bits; | ||
18 | extern unsigned long sparc64_kern_sec_context; | ||
19 | extern void mmu_info(struct seq_file *m); | ||
20 | |||
21 | struct linux_prom_translation { | ||
22 | unsigned long virt; | ||
23 | unsigned long size; | ||
24 | unsigned long data; | ||
25 | }; | ||
26 | |||
27 | /* Exported for kernel TLB miss handling in ktlb.S */ | ||
28 | extern struct linux_prom_translation prom_trans[512]; | ||
29 | extern unsigned int prom_trans_ents; | ||
30 | |||
31 | /* Exported for SMP bootup purposes. */ | ||
32 | extern unsigned long kern_locked_tte_data; | ||
33 | |||
34 | extern void prom_world(int enter); | ||
35 | |||
36 | extern void free_initmem(void); | ||
37 | |||
38 | #ifdef CONFIG_SPARSEMEM_VMEMMAP | ||
39 | #define VMEMMAP_CHUNK_SHIFT 22 | ||
40 | #define VMEMMAP_CHUNK (1UL << VMEMMAP_CHUNK_SHIFT) | ||
41 | #define VMEMMAP_CHUNK_MASK ~(VMEMMAP_CHUNK - 1UL) | ||
42 | #define VMEMMAP_ALIGN(x) (((x)+VMEMMAP_CHUNK-1UL)&VMEMMAP_CHUNK_MASK) | ||
43 | |||
44 | #define VMEMMAP_SIZE ((((1UL << MAX_PHYSADDR_BITS) >> PAGE_SHIFT) * \ | ||
45 | sizeof(struct page *)) >> VMEMMAP_CHUNK_SHIFT) | ||
46 | extern unsigned long vmemmap_table[VMEMMAP_SIZE]; | ||
47 | #endif | ||
48 | |||
49 | #endif /* _SPARC64_MM_INIT_H */ | ||
diff --git a/arch/sparc64/mm/tlb.c b/arch/sparc64/mm/tlb.c index ae24919cba7c..d8f21e24a82f 100644 --- a/arch/sparc64/mm/tlb.c +++ b/arch/sparc64/mm/tlb.c | |||
@@ -19,7 +19,7 @@ | |||
19 | 19 | ||
20 | /* Heavily inspired by the ppc64 code. */ | 20 | /* Heavily inspired by the ppc64 code. */ |
21 | 21 | ||
22 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers) = { 0, }; | 22 | DEFINE_PER_CPU(struct mmu_gather, mmu_gathers); |
23 | 23 | ||
24 | void flush_tlb_pending(void) | 24 | void flush_tlb_pending(void) |
25 | { | 25 | { |
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c index 8dd3336efd7e..3c578ef78c48 100644 --- a/drivers/acpi/glue.c +++ b/drivers/acpi/glue.c | |||
@@ -369,7 +369,6 @@ static int __init acpi_rtc_init(void) | |||
369 | DBG("RTC unavailable?\n"); | 369 | DBG("RTC unavailable?\n"); |
370 | return 0; | 370 | return 0; |
371 | } | 371 | } |
372 | /* do this between RTC subsys_initcall() and rtc_cmos driver_initcall() */ | 372 | module_init(acpi_rtc_init); |
373 | fs_initcall(acpi_rtc_init); | ||
374 | 373 | ||
375 | #endif | 374 | #endif |
diff --git a/drivers/ata/Kconfig b/drivers/ata/Kconfig index f17cd4b572f8..78fbec8ceda0 100644 --- a/drivers/ata/Kconfig +++ b/drivers/ata/Kconfig | |||
@@ -7,7 +7,6 @@ menuconfig ATA | |||
7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
8 | depends on BLOCK | 8 | depends on BLOCK |
9 | depends on !(M32R || M68K) || BROKEN | 9 | depends on !(M32R || M68K) || BROKEN |
10 | depends on !SUN4 || BROKEN | ||
11 | select SCSI | 10 | select SCSI |
12 | ---help--- | 11 | ---help--- |
13 | If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or | 12 | If you want to use a ATA hard disk, ATA tape drive, ATA CD-ROM or |
diff --git a/drivers/atm/fore200e.c b/drivers/atm/fore200e.c index 73338d231db9..937c9c0ef4c9 100644 --- a/drivers/atm/fore200e.c +++ b/drivers/atm/fore200e.c | |||
@@ -47,8 +47,9 @@ | |||
47 | #include <asm/atomic.h> | 47 | #include <asm/atomic.h> |
48 | 48 | ||
49 | #ifdef CONFIG_SBUS | 49 | #ifdef CONFIG_SBUS |
50 | #include <linux/of.h> | ||
51 | #include <linux/of_device.h> | ||
50 | #include <asm/idprom.h> | 52 | #include <asm/idprom.h> |
51 | #include <asm/sbus.h> | ||
52 | #include <asm/openprom.h> | 53 | #include <asm/openprom.h> |
53 | #include <asm/oplib.h> | 54 | #include <asm/oplib.h> |
54 | #include <asm/pgtable.h> | 55 | #include <asm/pgtable.h> |
@@ -661,249 +662,189 @@ fore200e_pca_proc_read(struct fore200e* fore200e, char *page) | |||
661 | 662 | ||
662 | #ifdef CONFIG_SBUS | 663 | #ifdef CONFIG_SBUS |
663 | 664 | ||
664 | static u32 | 665 | static u32 fore200e_sba_read(volatile u32 __iomem *addr) |
665 | fore200e_sba_read(volatile u32 __iomem *addr) | ||
666 | { | 666 | { |
667 | return sbus_readl(addr); | 667 | return sbus_readl(addr); |
668 | } | 668 | } |
669 | 669 | ||
670 | 670 | static void fore200e_sba_write(u32 val, volatile u32 __iomem *addr) | |
671 | static void | ||
672 | fore200e_sba_write(u32 val, volatile u32 __iomem *addr) | ||
673 | { | 671 | { |
674 | sbus_writel(val, addr); | 672 | sbus_writel(val, addr); |
675 | } | 673 | } |
676 | 674 | ||
677 | 675 | static u32 fore200e_sba_dma_map(struct fore200e *fore200e, void* virt_addr, int size, int direction) | |
678 | static u32 | ||
679 | fore200e_sba_dma_map(struct fore200e* fore200e, void* virt_addr, int size, int direction) | ||
680 | { | 676 | { |
681 | u32 dma_addr = sbus_map_single((struct sbus_dev*)fore200e->bus_dev, virt_addr, size, direction); | 677 | struct of_device *op = fore200e->bus_dev; |
678 | u32 dma_addr; | ||
682 | 679 | ||
683 | DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n", | 680 | dma_addr = dma_map_single(&op->dev, virt_addr, size, direction); |
684 | virt_addr, size, direction, dma_addr); | 681 | |
682 | DPRINTK(3, "SBUS DVMA mapping: virt_addr = 0x%p, size = %d, direction = %d --> dma_addr = 0x%08x\n", | ||
683 | virt_addr, size, direction, dma_addr); | ||
685 | 684 | ||
686 | return dma_addr; | 685 | return dma_addr; |
687 | } | 686 | } |
688 | 687 | ||
689 | 688 | static void fore200e_sba_dma_unmap(struct fore200e *fore200e, u32 dma_addr, int size, int direction) | |
690 | static void | ||
691 | fore200e_sba_dma_unmap(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
692 | { | 689 | { |
693 | DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", | 690 | struct of_device *op = fore200e->bus_dev; |
694 | dma_addr, size, direction); | ||
695 | 691 | ||
696 | sbus_unmap_single((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); | 692 | DPRINTK(3, "SBUS DVMA unmapping: dma_addr = 0x%08x, size = %d, direction = %d,\n", |
697 | } | 693 | dma_addr, size, direction); |
698 | 694 | ||
695 | dma_unmap_single(&op->dev, dma_addr, size, direction); | ||
696 | } | ||
699 | 697 | ||
700 | static void | 698 | static void fore200e_sba_dma_sync_for_cpu(struct fore200e *fore200e, u32 dma_addr, int size, int direction) |
701 | fore200e_sba_dma_sync_for_cpu(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
702 | { | 699 | { |
703 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | 700 | struct of_device *op = fore200e->bus_dev; |
701 | |||
702 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | ||
704 | 703 | ||
705 | sbus_dma_sync_single_for_cpu((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); | 704 | dma_sync_single_for_cpu(&op->dev, dma_addr, size, direction); |
706 | } | 705 | } |
707 | 706 | ||
708 | static void | 707 | static void fore200e_sba_dma_sync_for_device(struct fore200e *fore200e, u32 dma_addr, int size, int direction) |
709 | fore200e_sba_dma_sync_for_device(struct fore200e* fore200e, u32 dma_addr, int size, int direction) | ||
710 | { | 708 | { |
711 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | 709 | struct of_device *op = fore200e->bus_dev; |
712 | |||
713 | sbus_dma_sync_single_for_device((struct sbus_dev*)fore200e->bus_dev, dma_addr, size, direction); | ||
714 | } | ||
715 | 710 | ||
711 | DPRINTK(3, "SBUS DVMA sync: dma_addr = 0x%08x, size = %d, direction = %d\n", dma_addr, size, direction); | ||
716 | 712 | ||
717 | /* allocate a DVMA consistent chunk of memory intended to act as a communication mechanism | 713 | dma_sync_single_for_device(&op->dev, dma_addr, size, direction); |
718 | (to hold descriptors, status, queues, etc.) shared by the driver and the adapter */ | 714 | } |
719 | 715 | ||
720 | static int | 716 | /* Allocate a DVMA consistent chunk of memory intended to act as a communication mechanism |
721 | fore200e_sba_dma_chunk_alloc(struct fore200e* fore200e, struct chunk* chunk, | 717 | * (to hold descriptors, status, queues, etc.) shared by the driver and the adapter. |
722 | int size, int nbr, int alignment) | 718 | */ |
719 | static int fore200e_sba_dma_chunk_alloc(struct fore200e *fore200e, struct chunk *chunk, | ||
720 | int size, int nbr, int alignment) | ||
723 | { | 721 | { |
724 | chunk->alloc_size = chunk->align_size = size * nbr; | 722 | struct of_device *op = fore200e->bus_dev; |
725 | 723 | ||
726 | /* returned chunks are page-aligned */ | 724 | chunk->alloc_size = chunk->align_size = size * nbr; |
727 | chunk->alloc_addr = sbus_alloc_consistent((struct sbus_dev*)fore200e->bus_dev, | ||
728 | chunk->alloc_size, | ||
729 | &chunk->dma_addr); | ||
730 | 725 | ||
731 | if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0)) | 726 | /* returned chunks are page-aligned */ |
732 | return -ENOMEM; | 727 | chunk->alloc_addr = dma_alloc_coherent(&op->dev, chunk->alloc_size, |
728 | &chunk->dma_addr, GFP_ATOMIC); | ||
733 | 729 | ||
734 | chunk->align_addr = chunk->alloc_addr; | 730 | if ((chunk->alloc_addr == NULL) || (chunk->dma_addr == 0)) |
731 | return -ENOMEM; | ||
732 | |||
733 | chunk->align_addr = chunk->alloc_addr; | ||
735 | 734 | ||
736 | return 0; | 735 | return 0; |
737 | } | 736 | } |
738 | 737 | ||
739 | |||
740 | /* free a DVMA consistent chunk of memory */ | 738 | /* free a DVMA consistent chunk of memory */ |
741 | 739 | static void fore200e_sba_dma_chunk_free(struct fore200e *fore200e, struct chunk *chunk) | |
742 | static void | ||
743 | fore200e_sba_dma_chunk_free(struct fore200e* fore200e, struct chunk* chunk) | ||
744 | { | 740 | { |
745 | sbus_free_consistent((struct sbus_dev*)fore200e->bus_dev, | 741 | struct of_device *op = fore200e->bus_dev; |
746 | chunk->alloc_size, | ||
747 | chunk->alloc_addr, | ||
748 | chunk->dma_addr); | ||
749 | } | ||
750 | 742 | ||
743 | dma_free_coherent(&op->dev, chunk->alloc_size, | ||
744 | chunk->alloc_addr, chunk->dma_addr); | ||
745 | } | ||
751 | 746 | ||
752 | static void | 747 | static void fore200e_sba_irq_enable(struct fore200e *fore200e) |
753 | fore200e_sba_irq_enable(struct fore200e* fore200e) | ||
754 | { | 748 | { |
755 | u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; | 749 | u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; |
756 | fore200e->bus->write(hcr | SBA200E_HCR_INTR_ENA, fore200e->regs.sba.hcr); | 750 | fore200e->bus->write(hcr | SBA200E_HCR_INTR_ENA, fore200e->regs.sba.hcr); |
757 | } | 751 | } |
758 | 752 | ||
759 | 753 | static int fore200e_sba_irq_check(struct fore200e *fore200e) | |
760 | static int | ||
761 | fore200e_sba_irq_check(struct fore200e* fore200e) | ||
762 | { | 754 | { |
763 | return fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_INTR_REQ; | 755 | return fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_INTR_REQ; |
764 | } | 756 | } |
765 | 757 | ||
766 | 758 | static void fore200e_sba_irq_ack(struct fore200e *fore200e) | |
767 | static void | ||
768 | fore200e_sba_irq_ack(struct fore200e* fore200e) | ||
769 | { | 759 | { |
770 | u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; | 760 | u32 hcr = fore200e->bus->read(fore200e->regs.sba.hcr) & SBA200E_HCR_STICKY; |
771 | fore200e->bus->write(hcr | SBA200E_HCR_INTR_CLR, fore200e->regs.sba.hcr); | 761 | fore200e->bus->write(hcr | SBA200E_HCR_INTR_CLR, fore200e->regs.sba.hcr); |
772 | } | 762 | } |
773 | 763 | ||
774 | 764 | static void fore200e_sba_reset(struct fore200e *fore200e) | |
775 | static void | ||
776 | fore200e_sba_reset(struct fore200e* fore200e) | ||
777 | { | 765 | { |
778 | fore200e->bus->write(SBA200E_HCR_RESET, fore200e->regs.sba.hcr); | 766 | fore200e->bus->write(SBA200E_HCR_RESET, fore200e->regs.sba.hcr); |
779 | fore200e_spin(10); | 767 | fore200e_spin(10); |
780 | fore200e->bus->write(0, fore200e->regs.sba.hcr); | 768 | fore200e->bus->write(0, fore200e->regs.sba.hcr); |
781 | } | 769 | } |
782 | 770 | ||
783 | 771 | static int __init fore200e_sba_map(struct fore200e *fore200e) | |
784 | static int __init | ||
785 | fore200e_sba_map(struct fore200e* fore200e) | ||
786 | { | 772 | { |
787 | struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev; | 773 | struct of_device *op = fore200e->bus_dev; |
788 | unsigned int bursts; | 774 | unsigned int bursts; |
789 | 775 | ||
790 | /* gain access to the SBA specific registers */ | 776 | /* gain access to the SBA specific registers */ |
791 | fore200e->regs.sba.hcr = sbus_ioremap(&sbus_dev->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR"); | 777 | fore200e->regs.sba.hcr = of_ioremap(&op->resource[0], 0, SBA200E_HCR_LENGTH, "SBA HCR"); |
792 | fore200e->regs.sba.bsr = sbus_ioremap(&sbus_dev->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR"); | 778 | fore200e->regs.sba.bsr = of_ioremap(&op->resource[1], 0, SBA200E_BSR_LENGTH, "SBA BSR"); |
793 | fore200e->regs.sba.isr = sbus_ioremap(&sbus_dev->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR"); | 779 | fore200e->regs.sba.isr = of_ioremap(&op->resource[2], 0, SBA200E_ISR_LENGTH, "SBA ISR"); |
794 | fore200e->virt_base = sbus_ioremap(&sbus_dev->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM"); | 780 | fore200e->virt_base = of_ioremap(&op->resource[3], 0, SBA200E_RAM_LENGTH, "SBA RAM"); |
795 | 781 | ||
796 | if (fore200e->virt_base == NULL) { | 782 | if (!fore200e->virt_base) { |
797 | printk(FORE200E "unable to map RAM of device %s\n", fore200e->name); | 783 | printk(FORE200E "unable to map RAM of device %s\n", fore200e->name); |
798 | return -EFAULT; | 784 | return -EFAULT; |
799 | } | 785 | } |
800 | 786 | ||
801 | DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base); | 787 | DPRINTK(1, "device %s mapped to 0x%p\n", fore200e->name, fore200e->virt_base); |
802 | 788 | ||
803 | fore200e->bus->write(0x02, fore200e->regs.sba.isr); /* XXX hardwired interrupt level */ | 789 | fore200e->bus->write(0x02, fore200e->regs.sba.isr); /* XXX hardwired interrupt level */ |
804 | 790 | ||
805 | /* get the supported DVMA burst sizes */ | 791 | /* get the supported DVMA burst sizes */ |
806 | bursts = prom_getintdefault(sbus_dev->bus->prom_node, "burst-sizes", 0x00); | 792 | bursts = of_getintprop_default(op->node->parent, "burst-sizes", 0x00); |
807 | 793 | ||
808 | if (sbus_can_dma_64bit(sbus_dev)) | 794 | if (sbus_can_dma_64bit()) |
809 | sbus_set_sbus64(sbus_dev, bursts); | 795 | sbus_set_sbus64(&op->dev, bursts); |
810 | 796 | ||
811 | fore200e->state = FORE200E_STATE_MAP; | 797 | fore200e->state = FORE200E_STATE_MAP; |
812 | return 0; | 798 | return 0; |
813 | } | 799 | } |
814 | 800 | ||
815 | 801 | static void fore200e_sba_unmap(struct fore200e *fore200e) | |
816 | static void | ||
817 | fore200e_sba_unmap(struct fore200e* fore200e) | ||
818 | { | 802 | { |
819 | sbus_iounmap(fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); | 803 | struct of_device *op = fore200e->bus_dev; |
820 | sbus_iounmap(fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); | ||
821 | sbus_iounmap(fore200e->regs.sba.isr, SBA200E_ISR_LENGTH); | ||
822 | sbus_iounmap(fore200e->virt_base, SBA200E_RAM_LENGTH); | ||
823 | } | ||
824 | 804 | ||
805 | of_iounmap(&op->resource[0], fore200e->regs.sba.hcr, SBA200E_HCR_LENGTH); | ||
806 | of_iounmap(&op->resource[1], fore200e->regs.sba.bsr, SBA200E_BSR_LENGTH); | ||
807 | of_iounmap(&op->resource[2], fore200e->regs.sba.isr, SBA200E_ISR_LENGTH); | ||
808 | of_iounmap(&op->resource[3], fore200e->virt_base, SBA200E_RAM_LENGTH); | ||
809 | } | ||
825 | 810 | ||
826 | static int __init | 811 | static int __init fore200e_sba_configure(struct fore200e *fore200e) |
827 | fore200e_sba_configure(struct fore200e* fore200e) | ||
828 | { | 812 | { |
829 | fore200e->state = FORE200E_STATE_CONFIGURE; | 813 | fore200e->state = FORE200E_STATE_CONFIGURE; |
830 | return 0; | 814 | return 0; |
831 | } | 815 | } |
832 | 816 | ||
833 | 817 | static int __init fore200e_sba_prom_read(struct fore200e *fore200e, struct prom_data *prom) | |
834 | static struct fore200e* __init | ||
835 | fore200e_sba_detect(const struct fore200e_bus* bus, int index) | ||
836 | { | 818 | { |
837 | struct fore200e* fore200e; | 819 | struct of_device *op = fore200e->bus_dev; |
838 | struct sbus_bus* sbus_bus; | 820 | const u8 *prop; |
839 | struct sbus_dev* sbus_dev = NULL; | 821 | int len; |
840 | |||
841 | unsigned int count = 0; | ||
842 | |||
843 | for_each_sbus (sbus_bus) { | ||
844 | for_each_sbusdev (sbus_dev, sbus_bus) { | ||
845 | if (strcmp(sbus_dev->prom_name, SBA200E_PROM_NAME) == 0) { | ||
846 | if (count >= index) | ||
847 | goto found; | ||
848 | count++; | ||
849 | } | ||
850 | } | ||
851 | } | ||
852 | return NULL; | ||
853 | |||
854 | found: | ||
855 | if (sbus_dev->num_registers != 4) { | ||
856 | printk(FORE200E "this %s device has %d instead of 4 registers\n", | ||
857 | bus->model_name, sbus_dev->num_registers); | ||
858 | return NULL; | ||
859 | } | ||
860 | |||
861 | fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL); | ||
862 | if (fore200e == NULL) | ||
863 | return NULL; | ||
864 | 822 | ||
865 | fore200e->bus = bus; | 823 | prop = of_get_property(op->node, "madaddrlo2", &len); |
866 | fore200e->bus_dev = sbus_dev; | 824 | if (!prop) |
867 | fore200e->irq = sbus_dev->irqs[ 0 ]; | 825 | return -ENODEV; |
826 | memcpy(&prom->mac_addr[4], prop, 4); | ||
868 | 827 | ||
869 | fore200e->phys_base = (unsigned long)sbus_dev; | 828 | prop = of_get_property(op->node, "madaddrhi4", &len); |
829 | if (!prop) | ||
830 | return -ENODEV; | ||
831 | memcpy(&prom->mac_addr[2], prop, 4); | ||
870 | 832 | ||
871 | sprintf(fore200e->name, "%s-%d", bus->model_name, index - 1); | 833 | prom->serial_number = of_getintprop_default(op->node, "serialnumber", 0); |
834 | prom->hw_revision = of_getintprop_default(op->node, "promversion", 0); | ||
872 | 835 | ||
873 | return fore200e; | 836 | return 0; |
874 | } | 837 | } |
875 | 838 | ||
876 | 839 | static int fore200e_sba_proc_read(struct fore200e *fore200e, char *page) | |
877 | static int __init | ||
878 | fore200e_sba_prom_read(struct fore200e* fore200e, struct prom_data* prom) | ||
879 | { | 840 | { |
880 | struct sbus_dev* sbus_dev = (struct sbus_dev*) fore200e->bus_dev; | 841 | struct of_device *op = fore200e->bus_dev; |
881 | int len; | 842 | const struct linux_prom_registers *regs; |
882 | |||
883 | len = prom_getproperty(sbus_dev->prom_node, "macaddrlo2", &prom->mac_addr[ 4 ], 4); | ||
884 | if (len < 0) | ||
885 | return -EBUSY; | ||
886 | |||
887 | len = prom_getproperty(sbus_dev->prom_node, "macaddrhi4", &prom->mac_addr[ 2 ], 4); | ||
888 | if (len < 0) | ||
889 | return -EBUSY; | ||
890 | |||
891 | prom_getproperty(sbus_dev->prom_node, "serialnumber", | ||
892 | (char*)&prom->serial_number, sizeof(prom->serial_number)); | ||
893 | |||
894 | prom_getproperty(sbus_dev->prom_node, "promversion", | ||
895 | (char*)&prom->hw_revision, sizeof(prom->hw_revision)); | ||
896 | |||
897 | return 0; | ||
898 | } | ||
899 | 843 | ||
844 | regs = of_get_property(op->node, "reg", NULL); | ||
900 | 845 | ||
901 | static int | 846 | return sprintf(page, " SBUS slot/device:\t\t%d/'%s'\n", |
902 | fore200e_sba_proc_read(struct fore200e* fore200e, char *page) | 847 | (regs ? regs->which_io : 0), op->node->name); |
903 | { | ||
904 | struct sbus_dev* sbus_dev = (struct sbus_dev*)fore200e->bus_dev; | ||
905 | |||
906 | return sprintf(page, " SBUS slot/device:\t\t%d/'%s'\n", sbus_dev->slot, sbus_dev->prom_name); | ||
907 | } | 848 | } |
908 | #endif /* CONFIG_SBUS */ | 849 | #endif /* CONFIG_SBUS */ |
909 | 850 | ||
@@ -2572,7 +2513,7 @@ fore200e_load_and_start_fw(struct fore200e* fore200e) | |||
2572 | device = &((struct pci_dev *) fore200e->bus_dev)->dev; | 2513 | device = &((struct pci_dev *) fore200e->bus_dev)->dev; |
2573 | #ifdef CONFIG_SBUS | 2514 | #ifdef CONFIG_SBUS |
2574 | else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) | 2515 | else if (strcmp(fore200e->bus->model_name, "SBA-200E") == 0) |
2575 | device = &((struct sbus_dev *) fore200e->bus_dev)->ofdev.dev; | 2516 | device = &((struct of_device *) fore200e->bus_dev)->dev; |
2576 | #endif | 2517 | #endif |
2577 | else | 2518 | else |
2578 | return err; | 2519 | return err; |
@@ -2701,6 +2642,66 @@ fore200e_init(struct fore200e* fore200e) | |||
2701 | return 0; | 2642 | return 0; |
2702 | } | 2643 | } |
2703 | 2644 | ||
2645 | #ifdef CONFIG_SBUS | ||
2646 | static int __devinit fore200e_sba_probe(struct of_device *op, | ||
2647 | const struct of_device_id *match) | ||
2648 | { | ||
2649 | const struct fore200e_bus *bus = match->data; | ||
2650 | struct fore200e *fore200e; | ||
2651 | static int index = 0; | ||
2652 | int err; | ||
2653 | |||
2654 | fore200e = kzalloc(sizeof(struct fore200e), GFP_KERNEL); | ||
2655 | if (!fore200e) | ||
2656 | return -ENOMEM; | ||
2657 | |||
2658 | fore200e->bus = bus; | ||
2659 | fore200e->bus_dev = op; | ||
2660 | fore200e->irq = op->irqs[0]; | ||
2661 | fore200e->phys_base = op->resource[0].start; | ||
2662 | |||
2663 | sprintf(fore200e->name, "%s-%d", bus->model_name, index); | ||
2664 | |||
2665 | err = fore200e_init(fore200e); | ||
2666 | if (err < 0) { | ||
2667 | fore200e_shutdown(fore200e); | ||
2668 | kfree(fore200e); | ||
2669 | return err; | ||
2670 | } | ||
2671 | |||
2672 | index++; | ||
2673 | dev_set_drvdata(&op->dev, fore200e); | ||
2674 | |||
2675 | return 0; | ||
2676 | } | ||
2677 | |||
2678 | static int __devexit fore200e_sba_remove(struct of_device *op) | ||
2679 | { | ||
2680 | struct fore200e *fore200e = dev_get_drvdata(&op->dev); | ||
2681 | |||
2682 | fore200e_shutdown(fore200e); | ||
2683 | kfree(fore200e); | ||
2684 | |||
2685 | return 0; | ||
2686 | } | ||
2687 | |||
2688 | static const struct of_device_id fore200e_sba_match[] = { | ||
2689 | { | ||
2690 | .name = SBA200E_PROM_NAME, | ||
2691 | .data = (void *) &fore200e_bus[1], | ||
2692 | }, | ||
2693 | {}, | ||
2694 | }; | ||
2695 | MODULE_DEVICE_TABLE(of, fore200e_sba_match); | ||
2696 | |||
2697 | static struct of_platform_driver fore200e_sba_driver = { | ||
2698 | .name = "fore_200e", | ||
2699 | .match_table = fore200e_sba_match, | ||
2700 | .probe = fore200e_sba_probe, | ||
2701 | .remove = __devexit_p(fore200e_sba_remove), | ||
2702 | }; | ||
2703 | #endif | ||
2704 | |||
2704 | #ifdef CONFIG_PCI | 2705 | #ifdef CONFIG_PCI |
2705 | static int __devinit | 2706 | static int __devinit |
2706 | fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) | 2707 | fore200e_pca_detect(struct pci_dev *pci_dev, const struct pci_device_id *pci_ent) |
@@ -2784,67 +2785,40 @@ static struct pci_driver fore200e_pca_driver = { | |||
2784 | }; | 2785 | }; |
2785 | #endif | 2786 | #endif |
2786 | 2787 | ||
2787 | 2788 | static int __init fore200e_module_init(void) | |
2788 | static int __init | ||
2789 | fore200e_module_init(void) | ||
2790 | { | 2789 | { |
2791 | const struct fore200e_bus* bus; | 2790 | int err; |
2792 | struct fore200e* fore200e; | ||
2793 | int index; | ||
2794 | |||
2795 | printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n"); | ||
2796 | 2791 | ||
2797 | /* for each configured bus interface */ | 2792 | printk(FORE200E "FORE Systems 200E-series ATM driver - version " FORE200E_VERSION "\n"); |
2798 | for (bus = fore200e_bus; bus->model_name; bus++) { | ||
2799 | 2793 | ||
2800 | /* detect all boards present on that bus */ | 2794 | #ifdef CONFIG_SBUS |
2801 | for (index = 0; bus->detect && (fore200e = bus->detect(bus, index)); index++) { | 2795 | err = of_register_driver(&fore200e_sba_driver, &of_bus_type); |
2802 | 2796 | if (err) | |
2803 | printk(FORE200E "device %s found at 0x%lx, IRQ %s\n", | 2797 | return err; |
2804 | fore200e->bus->model_name, | 2798 | #endif |
2805 | fore200e->phys_base, fore200e_irq_itoa(fore200e->irq)); | ||
2806 | |||
2807 | sprintf(fore200e->name, "%s-%d", bus->model_name, index); | ||
2808 | |||
2809 | if (fore200e_init(fore200e) < 0) { | ||
2810 | |||
2811 | fore200e_shutdown(fore200e); | ||
2812 | break; | ||
2813 | } | ||
2814 | |||
2815 | list_add(&fore200e->entry, &fore200e_boards); | ||
2816 | } | ||
2817 | } | ||
2818 | 2799 | ||
2819 | #ifdef CONFIG_PCI | 2800 | #ifdef CONFIG_PCI |
2820 | if (!pci_register_driver(&fore200e_pca_driver)) | 2801 | err = pci_register_driver(&fore200e_pca_driver); |
2821 | return 0; | ||
2822 | #endif | 2802 | #endif |
2823 | 2803 | ||
2824 | if (!list_empty(&fore200e_boards)) | 2804 | #ifdef CONFIG_SBUS |
2825 | return 0; | 2805 | if (err) |
2806 | of_unregister_driver(&fore200e_sba_driver); | ||
2807 | #endif | ||
2826 | 2808 | ||
2827 | return -ENODEV; | 2809 | return err; |
2828 | } | 2810 | } |
2829 | 2811 | ||
2830 | 2812 | static void __exit fore200e_module_cleanup(void) | |
2831 | static void __exit | ||
2832 | fore200e_module_cleanup(void) | ||
2833 | { | 2813 | { |
2834 | struct fore200e *fore200e, *next; | ||
2835 | |||
2836 | #ifdef CONFIG_PCI | 2814 | #ifdef CONFIG_PCI |
2837 | pci_unregister_driver(&fore200e_pca_driver); | 2815 | pci_unregister_driver(&fore200e_pca_driver); |
2816 | #endif | ||
2817 | #ifdef CONFIG_SBUS | ||
2818 | of_unregister_driver(&fore200e_sba_driver); | ||
2838 | #endif | 2819 | #endif |
2839 | |||
2840 | list_for_each_entry_safe(fore200e, next, &fore200e_boards, entry) { | ||
2841 | fore200e_shutdown(fore200e); | ||
2842 | kfree(fore200e); | ||
2843 | } | ||
2844 | DPRINTK(1, "module being removed\n"); | ||
2845 | } | 2820 | } |
2846 | 2821 | ||
2847 | |||
2848 | static int | 2822 | static int |
2849 | fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page) | 2823 | fore200e_proc_read(struct atm_dev *dev, loff_t* pos, char* page) |
2850 | { | 2824 | { |
@@ -3163,7 +3137,6 @@ static const struct fore200e_bus fore200e_bus[] = { | |||
3163 | fore200e_pca_dma_sync_for_device, | 3137 | fore200e_pca_dma_sync_for_device, |
3164 | fore200e_pca_dma_chunk_alloc, | 3138 | fore200e_pca_dma_chunk_alloc, |
3165 | fore200e_pca_dma_chunk_free, | 3139 | fore200e_pca_dma_chunk_free, |
3166 | NULL, | ||
3167 | fore200e_pca_configure, | 3140 | fore200e_pca_configure, |
3168 | fore200e_pca_map, | 3141 | fore200e_pca_map, |
3169 | fore200e_pca_reset, | 3142 | fore200e_pca_reset, |
@@ -3185,7 +3158,6 @@ static const struct fore200e_bus fore200e_bus[] = { | |||
3185 | fore200e_sba_dma_sync_for_device, | 3158 | fore200e_sba_dma_sync_for_device, |
3186 | fore200e_sba_dma_chunk_alloc, | 3159 | fore200e_sba_dma_chunk_alloc, |
3187 | fore200e_sba_dma_chunk_free, | 3160 | fore200e_sba_dma_chunk_free, |
3188 | fore200e_sba_detect, | ||
3189 | fore200e_sba_configure, | 3161 | fore200e_sba_configure, |
3190 | fore200e_sba_map, | 3162 | fore200e_sba_map, |
3191 | fore200e_sba_reset, | 3163 | fore200e_sba_reset, |
diff --git a/drivers/atm/fore200e.h b/drivers/atm/fore200e.h index 5c6e7adcb19c..7f97c09aaea5 100644 --- a/drivers/atm/fore200e.h +++ b/drivers/atm/fore200e.h | |||
@@ -778,9 +778,9 @@ typedef struct fore200e_pca_regs { | |||
778 | /* SBA-200E registers */ | 778 | /* SBA-200E registers */ |
779 | 779 | ||
780 | typedef struct fore200e_sba_regs { | 780 | typedef struct fore200e_sba_regs { |
781 | volatile u32 __iomem *hcr; /* address of host control register */ | 781 | u32 __iomem *hcr; /* address of host control register */ |
782 | volatile u32 __iomem *bsr; /* address of burst transfer size register */ | 782 | u32 __iomem *bsr; /* address of burst transfer size register */ |
783 | volatile u32 __iomem *isr; /* address of interrupt level selection register */ | 783 | u32 __iomem *isr; /* address of interrupt level selection register */ |
784 | } fore200e_sba_regs_t; | 784 | } fore200e_sba_regs_t; |
785 | 785 | ||
786 | 786 | ||
@@ -810,7 +810,6 @@ typedef struct fore200e_bus { | |||
810 | void (*dma_sync_for_device)(struct fore200e*, u32, int, int); | 810 | void (*dma_sync_for_device)(struct fore200e*, u32, int, int); |
811 | int (*dma_chunk_alloc)(struct fore200e*, struct chunk*, int, int, int); | 811 | int (*dma_chunk_alloc)(struct fore200e*, struct chunk*, int, int, int); |
812 | void (*dma_chunk_free)(struct fore200e*, struct chunk*); | 812 | void (*dma_chunk_free)(struct fore200e*, struct chunk*); |
813 | struct fore200e* (*detect)(const struct fore200e_bus*, int); | ||
814 | int (*configure)(struct fore200e*); | 813 | int (*configure)(struct fore200e*); |
815 | int (*map)(struct fore200e*); | 814 | int (*map)(struct fore200e*); |
816 | void (*reset)(struct fore200e*); | 815 | void (*reset)(struct fore200e*); |
diff --git a/drivers/block/sunvdc.c b/drivers/block/sunvdc.c index a8de037ecd4a..953c0b83d758 100644 --- a/drivers/block/sunvdc.c +++ b/drivers/block/sunvdc.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* sunvdc.c: Sun LDOM Virtual Disk Client. | 1 | /* sunvdc.c: Sun LDOM Virtual Disk Client. |
2 | * | 2 | * |
3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/module.h> | 6 | #include <linux/module.h> |
@@ -834,7 +834,7 @@ static int vdc_port_remove(struct vio_dev *vdev) | |||
834 | return 0; | 834 | return 0; |
835 | } | 835 | } |
836 | 836 | ||
837 | static struct vio_device_id vdc_port_match[] = { | 837 | static const struct vio_device_id vdc_port_match[] = { |
838 | { | 838 | { |
839 | .type = "vdc-port", | 839 | .type = "vdc-port", |
840 | }, | 840 | }, |
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c index 5220f541df25..8859aeac2d25 100644 --- a/drivers/char/hw_random/n2-drv.c +++ b/drivers/char/hw_random/n2-drv.c | |||
@@ -736,7 +736,7 @@ static int __devexit n2rng_remove(struct of_device *op) | |||
736 | return 0; | 736 | return 0; |
737 | } | 737 | } |
738 | 738 | ||
739 | static struct of_device_id n2rng_match[] = { | 739 | static const struct of_device_id n2rng_match[] = { |
740 | { | 740 | { |
741 | .name = "random-number-generator", | 741 | .name = "random-number-generator", |
742 | .compatible = "SUNW,n2-rng", | 742 | .compatible = "SUNW,n2-rng", |
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c index f53d4d00faf0..b47710c17885 100644 --- a/drivers/char/rtc.c +++ b/drivers/char/rtc.c | |||
@@ -88,12 +88,12 @@ | |||
88 | #endif | 88 | #endif |
89 | 89 | ||
90 | #ifdef CONFIG_SPARC32 | 90 | #ifdef CONFIG_SPARC32 |
91 | #include <linux/pci.h> | 91 | #include <linux/of.h> |
92 | #include <linux/jiffies.h> | 92 | #include <linux/of_device.h> |
93 | #include <asm/ebus.h> | 93 | #include <asm/io.h> |
94 | 94 | ||
95 | static unsigned long rtc_port; | 95 | static unsigned long rtc_port; |
96 | static int rtc_irq = PCI_IRQ_NONE; | 96 | static int rtc_irq; |
97 | #endif | 97 | #endif |
98 | 98 | ||
99 | #ifdef CONFIG_HPET_RTC_IRQ | 99 | #ifdef CONFIG_HPET_RTC_IRQ |
@@ -973,8 +973,8 @@ static int __init rtc_init(void) | |||
973 | char *guess = NULL; | 973 | char *guess = NULL; |
974 | #endif | 974 | #endif |
975 | #ifdef CONFIG_SPARC32 | 975 | #ifdef CONFIG_SPARC32 |
976 | struct linux_ebus *ebus; | 976 | struct device_node *ebus_dp; |
977 | struct linux_ebus_device *edev; | 977 | struct of_device *op; |
978 | #else | 978 | #else |
979 | void *r; | 979 | void *r; |
980 | #ifdef RTC_IRQ | 980 | #ifdef RTC_IRQ |
@@ -983,12 +983,16 @@ static int __init rtc_init(void) | |||
983 | #endif | 983 | #endif |
984 | 984 | ||
985 | #ifdef CONFIG_SPARC32 | 985 | #ifdef CONFIG_SPARC32 |
986 | for_each_ebus(ebus) { | 986 | for_each_node_by_name(ebus_dp, "ebus") { |
987 | for_each_ebusdev(edev, ebus) { | 987 | struct device_node *dp; |
988 | if (strcmp(edev->prom_node->name, "rtc") == 0) { | 988 | for (dp = ebus_dp; dp; dp = dp->sibling) { |
989 | rtc_port = edev->resource[0].start; | 989 | if (!strcmp(dp->name, "rtc")) { |
990 | rtc_irq = edev->irqs[0]; | 990 | op = of_find_device_by_node(dp); |
991 | goto found; | 991 | if (op) { |
992 | rtc_port = op->resource[0].start; | ||
993 | rtc_irq = op->irqs[0]; | ||
994 | goto found; | ||
995 | } | ||
992 | } | 996 | } |
993 | } | 997 | } |
994 | } | 998 | } |
@@ -997,7 +1001,7 @@ static int __init rtc_init(void) | |||
997 | return -EIO; | 1001 | return -EIO; |
998 | 1002 | ||
999 | found: | 1003 | found: |
1000 | if (rtc_irq == PCI_IRQ_NONE) { | 1004 | if (!rtc_irq) { |
1001 | rtc_has_irq = 0; | 1005 | rtc_has_irq = 0; |
1002 | goto no_irq; | 1006 | goto no_irq; |
1003 | } | 1007 | } |
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig index 3309e862f317..ebacc0af40fe 100644 --- a/drivers/hwmon/Kconfig +++ b/drivers/hwmon/Kconfig | |||
@@ -800,6 +800,13 @@ config SENSORS_W83627EHF | |||
800 | This driver can also be built as a module. If so, the module | 800 | This driver can also be built as a module. If so, the module |
801 | will be called w83627ehf. | 801 | will be called w83627ehf. |
802 | 802 | ||
803 | config SENSORS_ULTRA45 | ||
804 | tristate "Sun Ultra45 PIC16F747" | ||
805 | depends on SPARC64 | ||
806 | help | ||
807 | This driver provides support for the Ultra45 workstation environmental | ||
808 | sensors. | ||
809 | |||
803 | config SENSORS_HDAPS | 810 | config SENSORS_HDAPS |
804 | tristate "IBM Hard Drive Active Protection System (hdaps)" | 811 | tristate "IBM Hard Drive Active Protection System (hdaps)" |
805 | depends on INPUT && X86 | 812 | depends on INPUT && X86 |
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 6babc801b348..042d5a78622e 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile | |||
@@ -41,6 +41,7 @@ obj-$(CONFIG_SENSORS_FSCHMD) += fschmd.o | |||
41 | obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o | 41 | obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o |
42 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o | 42 | obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o |
43 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o | 43 | obj-$(CONFIG_SENSORS_GL520SM) += gl520sm.o |
44 | obj-$(CONFIG_SENSORS_ULTRA45) += ultra45_env.o | ||
44 | obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o | 45 | obj-$(CONFIG_SENSORS_HDAPS) += hdaps.o |
45 | obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o | 46 | obj-$(CONFIG_SENSORS_I5K_AMB) += i5k_amb.o |
46 | obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o | 47 | obj-$(CONFIG_SENSORS_IBMAEM) += ibmaem.o |
diff --git a/drivers/hwmon/ultra45_env.c b/drivers/hwmon/ultra45_env.c new file mode 100644 index 000000000000..68e90abeba96 --- /dev/null +++ b/drivers/hwmon/ultra45_env.c | |||
@@ -0,0 +1,320 @@ | |||
1 | /* ultra45_env.c: Driver for Ultra45 PIC16F747 environmental monitor. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/types.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <linux/of_device.h> | ||
10 | #include <linux/io.h> | ||
11 | #include <linux/hwmon.h> | ||
12 | #include <linux/hwmon-sysfs.h> | ||
13 | |||
14 | #define DRV_MODULE_VERSION "0.1" | ||
15 | |||
16 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | ||
17 | MODULE_DESCRIPTION("Ultra45 environmental monitor driver"); | ||
18 | MODULE_LICENSE("GPL"); | ||
19 | MODULE_VERSION(DRV_MODULE_VERSION); | ||
20 | |||
21 | /* PIC device registers */ | ||
22 | #define REG_CMD 0x00UL | ||
23 | #define REG_CMD_RESET 0x80 | ||
24 | #define REG_CMD_ESTAR 0x01 | ||
25 | #define REG_STAT 0x01UL | ||
26 | #define REG_STAT_FWVER 0xf0 | ||
27 | #define REG_STAT_TGOOD 0x08 | ||
28 | #define REG_STAT_STALE 0x04 | ||
29 | #define REG_STAT_BUSY 0x02 | ||
30 | #define REG_STAT_FAULT 0x01 | ||
31 | #define REG_DATA 0x40UL | ||
32 | #define REG_ADDR 0x41UL | ||
33 | #define REG_SIZE 0x42UL | ||
34 | |||
35 | /* Registers accessed indirectly via REG_DATA/REG_ADDR */ | ||
36 | #define IREG_FAN0 0x00 | ||
37 | #define IREG_FAN1 0x01 | ||
38 | #define IREG_FAN2 0x02 | ||
39 | #define IREG_FAN3 0x03 | ||
40 | #define IREG_FAN4 0x04 | ||
41 | #define IREG_FAN5 0x05 | ||
42 | #define IREG_LCL_TEMP 0x06 | ||
43 | #define IREG_RMT1_TEMP 0x07 | ||
44 | #define IREG_RMT2_TEMP 0x08 | ||
45 | #define IREG_RMT3_TEMP 0x09 | ||
46 | #define IREG_LM95221_TEMP 0x0a | ||
47 | #define IREG_FIRE_TEMP 0x0b | ||
48 | #define IREG_LSI1064_TEMP 0x0c | ||
49 | #define IREG_FRONT_TEMP 0x0d | ||
50 | #define IREG_FAN_STAT 0x0e | ||
51 | #define IREG_VCORE0 0x0f | ||
52 | #define IREG_VCORE1 0x10 | ||
53 | #define IREG_VMEM0 0x11 | ||
54 | #define IREG_VMEM1 0x12 | ||
55 | #define IREG_PSU_TEMP 0x13 | ||
56 | |||
57 | struct env { | ||
58 | void __iomem *regs; | ||
59 | spinlock_t lock; | ||
60 | |||
61 | struct device *hwmon_dev; | ||
62 | }; | ||
63 | |||
64 | static u8 env_read(struct env *p, u8 ireg) | ||
65 | { | ||
66 | u8 ret; | ||
67 | |||
68 | spin_lock(&p->lock); | ||
69 | writeb(ireg, p->regs + REG_ADDR); | ||
70 | ret = readb(p->regs + REG_DATA); | ||
71 | spin_unlock(&p->lock); | ||
72 | |||
73 | return ret; | ||
74 | } | ||
75 | |||
76 | static void env_write(struct env *p, u8 ireg, u8 val) | ||
77 | { | ||
78 | spin_lock(&p->lock); | ||
79 | writeb(ireg, p->regs + REG_ADDR); | ||
80 | writeb(val, p->regs + REG_DATA); | ||
81 | spin_unlock(&p->lock); | ||
82 | } | ||
83 | |||
84 | /* There seems to be a adr7462 providing these values, thus a lot | ||
85 | * of these calculations are borrowed from the adt7470 driver. | ||
86 | */ | ||
87 | #define FAN_PERIOD_TO_RPM(x) ((90000 * 60) / (x)) | ||
88 | #define FAN_RPM_TO_PERIOD FAN_PERIOD_TO_RPM | ||
89 | #define FAN_PERIOD_INVALID (0xff << 8) | ||
90 | #define FAN_DATA_VALID(x) ((x) && (x) != FAN_PERIOD_INVALID) | ||
91 | |||
92 | static ssize_t show_fan_speed(struct device *dev, struct device_attribute *attr, char *buf) | ||
93 | { | ||
94 | int fan_nr = to_sensor_dev_attr(attr)->index; | ||
95 | struct env *p = dev_get_drvdata(dev); | ||
96 | int rpm, period; | ||
97 | u8 val; | ||
98 | |||
99 | val = env_read(p, IREG_FAN0 + fan_nr); | ||
100 | period = (int) val << 8; | ||
101 | if (FAN_DATA_VALID(period)) | ||
102 | rpm = FAN_PERIOD_TO_RPM(period); | ||
103 | else | ||
104 | rpm = 0; | ||
105 | |||
106 | return sprintf(buf, "%d\n", rpm); | ||
107 | } | ||
108 | |||
109 | static ssize_t set_fan_speed(struct device *dev, struct device_attribute *attr, | ||
110 | const char *buf, size_t count) | ||
111 | { | ||
112 | int fan_nr = to_sensor_dev_attr(attr)->index; | ||
113 | int rpm = simple_strtol(buf, NULL, 10); | ||
114 | struct env *p = dev_get_drvdata(dev); | ||
115 | int period; | ||
116 | u8 val; | ||
117 | |||
118 | if (!rpm) | ||
119 | return -EINVAL; | ||
120 | |||
121 | period = FAN_RPM_TO_PERIOD(rpm); | ||
122 | val = period >> 8; | ||
123 | env_write(p, IREG_FAN0 + fan_nr, val); | ||
124 | |||
125 | return count; | ||
126 | } | ||
127 | |||
128 | static ssize_t show_fan_fault(struct device *dev, struct device_attribute *attr, char *buf) | ||
129 | { | ||
130 | int fan_nr = to_sensor_dev_attr(attr)->index; | ||
131 | struct env *p = dev_get_drvdata(dev); | ||
132 | u8 val = env_read(p, IREG_FAN_STAT); | ||
133 | return sprintf(buf, "%d\n", (val & (1 << fan_nr)) ? 1 : 0); | ||
134 | } | ||
135 | |||
136 | #define fan(index) \ | ||
137 | static SENSOR_DEVICE_ATTR(fan##index##_speed, S_IRUGO | S_IWUSR, \ | ||
138 | show_fan_speed, set_fan_speed, index); \ | ||
139 | static SENSOR_DEVICE_ATTR(fan##index##_fault, S_IRUGO, \ | ||
140 | show_fan_fault, NULL, index) | ||
141 | |||
142 | fan(0); | ||
143 | fan(1); | ||
144 | fan(2); | ||
145 | fan(3); | ||
146 | fan(4); | ||
147 | |||
148 | static SENSOR_DEVICE_ATTR(psu_fan_fault, S_IRUGO, show_fan_fault, NULL, 6); | ||
149 | |||
150 | static ssize_t show_temp(struct device *dev, struct device_attribute *attr, char *buf) | ||
151 | { | ||
152 | int temp_nr = to_sensor_dev_attr(attr)->index; | ||
153 | struct env *p = dev_get_drvdata(dev); | ||
154 | s8 val; | ||
155 | |||
156 | val = env_read(p, IREG_LCL_TEMP + temp_nr); | ||
157 | return sprintf(buf, "%d\n", ((int) val) - 64); | ||
158 | } | ||
159 | |||
160 | static SENSOR_DEVICE_ATTR(adt7462_local_temp, S_IRUGO, show_temp, NULL, 0); | ||
161 | static SENSOR_DEVICE_ATTR(cpu0_temp, S_IRUGO, show_temp, NULL, 1); | ||
162 | static SENSOR_DEVICE_ATTR(cpu1_temp, S_IRUGO, show_temp, NULL, 2); | ||
163 | static SENSOR_DEVICE_ATTR(motherboard_temp, S_IRUGO, show_temp, NULL, 3); | ||
164 | static SENSOR_DEVICE_ATTR(lm95221_local_temp, S_IRUGO, show_temp, NULL, 4); | ||
165 | static SENSOR_DEVICE_ATTR(fire_temp, S_IRUGO, show_temp, NULL, 5); | ||
166 | static SENSOR_DEVICE_ATTR(lsi1064_local_temp, S_IRUGO, show_temp, NULL, 6); | ||
167 | static SENSOR_DEVICE_ATTR(front_panel_temp, S_IRUGO, show_temp, NULL, 7); | ||
168 | static SENSOR_DEVICE_ATTR(psu_temp, S_IRUGO, show_temp, NULL, 13); | ||
169 | |||
170 | static ssize_t show_stat_bit(struct device *dev, struct device_attribute *attr, char *buf) | ||
171 | { | ||
172 | int index = to_sensor_dev_attr(attr)->index; | ||
173 | struct env *p = dev_get_drvdata(dev); | ||
174 | u8 val; | ||
175 | |||
176 | val = readb(p->regs + REG_STAT); | ||
177 | return sprintf(buf, "%d\n", (val & (1 << index)) ? 1 : 0); | ||
178 | } | ||
179 | |||
180 | static SENSOR_DEVICE_ATTR(fan_failure, S_IRUGO, show_stat_bit, NULL, 0); | ||
181 | static SENSOR_DEVICE_ATTR(env_bus_busy, S_IRUGO, show_stat_bit, NULL, 1); | ||
182 | static SENSOR_DEVICE_ATTR(env_data_stale, S_IRUGO, show_stat_bit, NULL, 2); | ||
183 | static SENSOR_DEVICE_ATTR(tpm_self_test_passed, S_IRUGO, show_stat_bit, NULL, 3); | ||
184 | |||
185 | static ssize_t show_fwver(struct device *dev, struct device_attribute *attr, char *buf) | ||
186 | { | ||
187 | struct env *p = dev_get_drvdata(dev); | ||
188 | u8 val; | ||
189 | |||
190 | val = readb(p->regs + REG_STAT); | ||
191 | return sprintf(buf, "%d\n", val >> 4); | ||
192 | } | ||
193 | |||
194 | static SENSOR_DEVICE_ATTR(firmware_version, S_IRUGO, show_fwver, NULL, 0); | ||
195 | |||
196 | static ssize_t show_name(struct device *dev, struct device_attribute *attr, char *buf) | ||
197 | { | ||
198 | return sprintf(buf, "ultra45\n"); | ||
199 | } | ||
200 | |||
201 | static SENSOR_DEVICE_ATTR(name, S_IRUGO, show_name, NULL, 0); | ||
202 | |||
203 | static struct attribute *env_attributes[] = { | ||
204 | &sensor_dev_attr_fan0_speed.dev_attr.attr, | ||
205 | &sensor_dev_attr_fan0_fault.dev_attr.attr, | ||
206 | &sensor_dev_attr_fan1_speed.dev_attr.attr, | ||
207 | &sensor_dev_attr_fan1_fault.dev_attr.attr, | ||
208 | &sensor_dev_attr_fan2_speed.dev_attr.attr, | ||
209 | &sensor_dev_attr_fan2_fault.dev_attr.attr, | ||
210 | &sensor_dev_attr_fan3_speed.dev_attr.attr, | ||
211 | &sensor_dev_attr_fan3_fault.dev_attr.attr, | ||
212 | &sensor_dev_attr_fan4_speed.dev_attr.attr, | ||
213 | &sensor_dev_attr_fan4_fault.dev_attr.attr, | ||
214 | &sensor_dev_attr_psu_fan_fault.dev_attr.attr, | ||
215 | &sensor_dev_attr_adt7462_local_temp.dev_attr.attr, | ||
216 | &sensor_dev_attr_cpu0_temp.dev_attr.attr, | ||
217 | &sensor_dev_attr_cpu1_temp.dev_attr.attr, | ||
218 | &sensor_dev_attr_motherboard_temp.dev_attr.attr, | ||
219 | &sensor_dev_attr_lm95221_local_temp.dev_attr.attr, | ||
220 | &sensor_dev_attr_fire_temp.dev_attr.attr, | ||
221 | &sensor_dev_attr_lsi1064_local_temp.dev_attr.attr, | ||
222 | &sensor_dev_attr_front_panel_temp.dev_attr.attr, | ||
223 | &sensor_dev_attr_psu_temp.dev_attr.attr, | ||
224 | &sensor_dev_attr_fan_failure.dev_attr.attr, | ||
225 | &sensor_dev_attr_env_bus_busy.dev_attr.attr, | ||
226 | &sensor_dev_attr_env_data_stale.dev_attr.attr, | ||
227 | &sensor_dev_attr_tpm_self_test_passed.dev_attr.attr, | ||
228 | &sensor_dev_attr_firmware_version.dev_attr.attr, | ||
229 | &sensor_dev_attr_name.dev_attr.attr, | ||
230 | NULL, | ||
231 | }; | ||
232 | |||
233 | static const struct attribute_group env_group = { | ||
234 | .attrs = env_attributes, | ||
235 | }; | ||
236 | |||
237 | static int __devinit env_probe(struct of_device *op, | ||
238 | const struct of_device_id *match) | ||
239 | { | ||
240 | struct env *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
241 | int err = -ENOMEM; | ||
242 | |||
243 | if (!p) | ||
244 | goto out; | ||
245 | |||
246 | spin_lock_init(&p->lock); | ||
247 | |||
248 | p->regs = of_ioremap(&op->resource[0], 0, REG_SIZE, "pic16f747"); | ||
249 | if (!p->regs) | ||
250 | goto out_free; | ||
251 | |||
252 | err = sysfs_create_group(&op->dev.kobj, &env_group); | ||
253 | if (err) | ||
254 | goto out_iounmap; | ||
255 | |||
256 | p->hwmon_dev = hwmon_device_register(&op->dev); | ||
257 | if (IS_ERR(p->hwmon_dev)) { | ||
258 | err = PTR_ERR(p->hwmon_dev); | ||
259 | goto out_sysfs_remove_group; | ||
260 | } | ||
261 | |||
262 | dev_set_drvdata(&op->dev, p); | ||
263 | err = 0; | ||
264 | |||
265 | out: | ||
266 | return err; | ||
267 | |||
268 | out_sysfs_remove_group: | ||
269 | sysfs_remove_group(&op->dev.kobj, &env_group); | ||
270 | |||
271 | out_iounmap: | ||
272 | of_iounmap(&op->resource[0], p->regs, REG_SIZE); | ||
273 | |||
274 | out_free: | ||
275 | kfree(p); | ||
276 | goto out; | ||
277 | } | ||
278 | |||
279 | static int __devexit env_remove(struct of_device *op) | ||
280 | { | ||
281 | struct env *p = dev_get_drvdata(&op->dev); | ||
282 | |||
283 | if (p) { | ||
284 | sysfs_remove_group(&op->dev.kobj, &env_group); | ||
285 | hwmon_device_unregister(p->hwmon_dev); | ||
286 | of_iounmap(&op->resource[0], p->regs, REG_SIZE); | ||
287 | kfree(p); | ||
288 | } | ||
289 | |||
290 | return 0; | ||
291 | } | ||
292 | |||
293 | static const struct of_device_id env_match[] = { | ||
294 | { | ||
295 | .name = "env-monitor", | ||
296 | .compatible = "SUNW,ebus-pic16f747-env", | ||
297 | }, | ||
298 | {}, | ||
299 | }; | ||
300 | MODULE_DEVICE_TABLE(of, env_match); | ||
301 | |||
302 | static struct of_platform_driver env_driver = { | ||
303 | .name = "ultra45_env", | ||
304 | .match_table = env_match, | ||
305 | .probe = env_probe, | ||
306 | .remove = __devexit_p(env_remove), | ||
307 | }; | ||
308 | |||
309 | static int __init env_init(void) | ||
310 | { | ||
311 | return of_register_driver(&env_driver, &of_bus_type); | ||
312 | } | ||
313 | |||
314 | static void __exit env_exit(void) | ||
315 | { | ||
316 | of_unregister_driver(&env_driver); | ||
317 | } | ||
318 | |||
319 | module_init(env_init); | ||
320 | module_exit(env_exit); | ||
diff --git a/drivers/input/misc/sparcspkr.c b/drivers/input/misc/sparcspkr.c index d8765cc93d27..c4f42311fdec 100644 --- a/drivers/input/misc/sparcspkr.c +++ b/drivers/input/misc/sparcspkr.c | |||
@@ -249,7 +249,7 @@ static int bbc_remove(struct of_device *op) | |||
249 | return 0; | 249 | return 0; |
250 | } | 250 | } |
251 | 251 | ||
252 | static struct of_device_id bbc_beep_match[] = { | 252 | static const struct of_device_id bbc_beep_match[] = { |
253 | { | 253 | { |
254 | .name = "beep", | 254 | .name = "beep", |
255 | .compatible = "SUNW,bbc-beep", | 255 | .compatible = "SUNW,bbc-beep", |
@@ -328,7 +328,7 @@ static int grover_remove(struct of_device *op) | |||
328 | return 0; | 328 | return 0; |
329 | } | 329 | } |
330 | 330 | ||
331 | static struct of_device_id grover_beep_match[] = { | 331 | static const struct of_device_id grover_beep_match[] = { |
332 | { | 332 | { |
333 | .name = "beep", | 333 | .name = "beep", |
334 | .compatible = "SUNW,smbus-beep", | 334 | .compatible = "SUNW,smbus-beep", |
diff --git a/drivers/input/serio/i8042-sparcio.h b/drivers/input/serio/i8042-sparcio.h index 692a79ec2a22..5071af2c0604 100644 --- a/drivers/input/serio/i8042-sparcio.h +++ b/drivers/input/serio/i8042-sparcio.h | |||
@@ -87,7 +87,7 @@ static int __devexit sparc_i8042_remove(struct of_device *op) | |||
87 | return 0; | 87 | return 0; |
88 | } | 88 | } |
89 | 89 | ||
90 | static struct of_device_id sparc_i8042_match[] = { | 90 | static const struct of_device_id sparc_i8042_match[] = { |
91 | { | 91 | { |
92 | .name = "8042", | 92 | .name = "8042", |
93 | }, | 93 | }, |
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig index 5b14262af017..e3e40427e00e 100644 --- a/drivers/leds/Kconfig +++ b/drivers/leds/Kconfig | |||
@@ -82,6 +82,14 @@ config LEDS_COBALT_RAQ | |||
82 | help | 82 | help |
83 | This option enables support for the Cobalt Raq series LEDs. | 83 | This option enables support for the Cobalt Raq series LEDs. |
84 | 84 | ||
85 | config LEDS_SUNFIRE | ||
86 | tristate "LED support for SunFire servers." | ||
87 | depends on LEDS_CLASS && SPARC64 | ||
88 | select LEDS_TRIGGERS | ||
89 | help | ||
90 | This option enables support for the Left, Middle, and Right | ||
91 | LEDs on the I/O and CPU boards of SunFire UltraSPARC servers. | ||
92 | |||
85 | config LEDS_HP6XX | 93 | config LEDS_HP6XX |
86 | tristate "LED Support for the HP Jornada 6xx" | 94 | tristate "LED Support for the HP Jornada 6xx" |
87 | depends on LEDS_CLASS && SH_HP6XX | 95 | depends on LEDS_CLASS && SH_HP6XX |
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile index 3a8e6a04363c..eb186c351a1c 100644 --- a/drivers/leds/Makefile +++ b/drivers/leds/Makefile | |||
@@ -14,6 +14,7 @@ obj-$(CONFIG_LEDS_WRAP) += leds-wrap.o | |||
14 | obj-$(CONFIG_LEDS_H1940) += leds-h1940.o | 14 | obj-$(CONFIG_LEDS_H1940) += leds-h1940.o |
15 | obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o | 15 | obj-$(CONFIG_LEDS_COBALT_QUBE) += leds-cobalt-qube.o |
16 | obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o | 16 | obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-cobalt-raq.o |
17 | obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o | ||
17 | obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o | 18 | obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o |
18 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o | 19 | obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o |
19 | obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o | 20 | obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o |
diff --git a/drivers/leds/leds-sunfire.c b/drivers/leds/leds-sunfire.c new file mode 100644 index 000000000000..6b008f0c3f62 --- /dev/null +++ b/drivers/leds/leds-sunfire.c | |||
@@ -0,0 +1,273 @@ | |||
1 | /* leds-sunfire.c: SUNW,Ultra-Enterprise LED driver. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/leds.h> | ||
10 | #include <linux/io.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | |||
13 | #include <asm/fhc.h> | ||
14 | #include <asm/upa.h> | ||
15 | |||
16 | #define DRIVER_NAME "leds-sunfire" | ||
17 | #define PFX DRIVER_NAME ": " | ||
18 | |||
19 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | ||
20 | MODULE_DESCRIPTION("Sun Fire LED driver"); | ||
21 | MODULE_LICENSE("GPL"); | ||
22 | |||
23 | struct sunfire_led { | ||
24 | struct led_classdev led_cdev; | ||
25 | void __iomem *reg; | ||
26 | }; | ||
27 | #define to_sunfire_led(d) container_of(d, struct sunfire_led, led_cdev) | ||
28 | |||
29 | static void __clockboard_set(struct led_classdev *led_cdev, | ||
30 | enum led_brightness led_val, u8 bit) | ||
31 | { | ||
32 | struct sunfire_led *p = to_sunfire_led(led_cdev); | ||
33 | u8 reg = upa_readb(p->reg); | ||
34 | |||
35 | switch (bit) { | ||
36 | case CLOCK_CTRL_LLED: | ||
37 | if (led_val) | ||
38 | reg &= ~bit; | ||
39 | else | ||
40 | reg |= bit; | ||
41 | break; | ||
42 | |||
43 | default: | ||
44 | if (led_val) | ||
45 | reg |= bit; | ||
46 | else | ||
47 | reg &= ~bit; | ||
48 | break; | ||
49 | } | ||
50 | upa_writeb(reg, p->reg); | ||
51 | } | ||
52 | |||
53 | static void clockboard_left_set(struct led_classdev *led_cdev, | ||
54 | enum led_brightness led_val) | ||
55 | { | ||
56 | __clockboard_set(led_cdev, led_val, CLOCK_CTRL_LLED); | ||
57 | } | ||
58 | |||
59 | static void clockboard_middle_set(struct led_classdev *led_cdev, | ||
60 | enum led_brightness led_val) | ||
61 | { | ||
62 | __clockboard_set(led_cdev, led_val, CLOCK_CTRL_MLED); | ||
63 | } | ||
64 | |||
65 | static void clockboard_right_set(struct led_classdev *led_cdev, | ||
66 | enum led_brightness led_val) | ||
67 | { | ||
68 | __clockboard_set(led_cdev, led_val, CLOCK_CTRL_RLED); | ||
69 | } | ||
70 | |||
71 | static void __fhc_set(struct led_classdev *led_cdev, | ||
72 | enum led_brightness led_val, u32 bit) | ||
73 | { | ||
74 | struct sunfire_led *p = to_sunfire_led(led_cdev); | ||
75 | u32 reg = upa_readl(p->reg); | ||
76 | |||
77 | switch (bit) { | ||
78 | case FHC_CONTROL_LLED: | ||
79 | if (led_val) | ||
80 | reg &= ~bit; | ||
81 | else | ||
82 | reg |= bit; | ||
83 | break; | ||
84 | |||
85 | default: | ||
86 | if (led_val) | ||
87 | reg |= bit; | ||
88 | else | ||
89 | reg &= ~bit; | ||
90 | break; | ||
91 | } | ||
92 | upa_writel(reg, p->reg); | ||
93 | } | ||
94 | |||
95 | static void fhc_left_set(struct led_classdev *led_cdev, | ||
96 | enum led_brightness led_val) | ||
97 | { | ||
98 | __fhc_set(led_cdev, led_val, FHC_CONTROL_LLED); | ||
99 | } | ||
100 | |||
101 | static void fhc_middle_set(struct led_classdev *led_cdev, | ||
102 | enum led_brightness led_val) | ||
103 | { | ||
104 | __fhc_set(led_cdev, led_val, FHC_CONTROL_MLED); | ||
105 | } | ||
106 | |||
107 | static void fhc_right_set(struct led_classdev *led_cdev, | ||
108 | enum led_brightness led_val) | ||
109 | { | ||
110 | __fhc_set(led_cdev, led_val, FHC_CONTROL_RLED); | ||
111 | } | ||
112 | |||
113 | typedef void (*set_handler)(struct led_classdev *, enum led_brightness); | ||
114 | struct led_type { | ||
115 | const char *name; | ||
116 | set_handler handler; | ||
117 | const char *default_trigger; | ||
118 | }; | ||
119 | |||
120 | #define NUM_LEDS_PER_BOARD 3 | ||
121 | struct sunfire_drvdata { | ||
122 | struct sunfire_led leds[NUM_LEDS_PER_BOARD]; | ||
123 | }; | ||
124 | |||
125 | static int __devinit sunfire_led_generic_probe(struct platform_device *pdev, | ||
126 | struct led_type *types) | ||
127 | { | ||
128 | struct sunfire_drvdata *p; | ||
129 | int i, err = -EINVAL; | ||
130 | |||
131 | if (pdev->num_resources != 1) { | ||
132 | printk(KERN_ERR PFX "Wrong number of resources %d, should be 1\n", | ||
133 | pdev->num_resources); | ||
134 | goto out; | ||
135 | } | ||
136 | |||
137 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
138 | if (!p) { | ||
139 | printk(KERN_ERR PFX "Could not allocate struct sunfire_drvdata\n"); | ||
140 | goto out; | ||
141 | } | ||
142 | |||
143 | for (i = 0; i < NUM_LEDS_PER_BOARD; i++) { | ||
144 | struct led_classdev *lp = &p->leds[i].led_cdev; | ||
145 | |||
146 | p->leds[i].reg = (void __iomem *) pdev->resource[0].start; | ||
147 | lp->name = types[i].name; | ||
148 | lp->brightness = LED_FULL; | ||
149 | lp->brightness_set = types[i].handler; | ||
150 | lp->default_trigger = types[i].default_trigger; | ||
151 | |||
152 | err = led_classdev_register(&pdev->dev, lp); | ||
153 | if (err) { | ||
154 | printk(KERN_ERR PFX "Could not register %s LED\n", | ||
155 | lp->name); | ||
156 | goto out_unregister_led_cdevs; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | dev_set_drvdata(&pdev->dev, p); | ||
161 | |||
162 | err = 0; | ||
163 | out: | ||
164 | return err; | ||
165 | |||
166 | out_unregister_led_cdevs: | ||
167 | for (i--; i >= 0; i--) | ||
168 | led_classdev_unregister(&p->leds[i].led_cdev); | ||
169 | goto out; | ||
170 | } | ||
171 | |||
172 | static int __devexit sunfire_led_generic_remove(struct platform_device *pdev) | ||
173 | { | ||
174 | struct sunfire_drvdata *p = dev_get_drvdata(&pdev->dev); | ||
175 | int i; | ||
176 | |||
177 | for (i = 0; i < NUM_LEDS_PER_BOARD; i++) | ||
178 | led_classdev_unregister(&p->leds[i].led_cdev); | ||
179 | |||
180 | kfree(p); | ||
181 | |||
182 | return 0; | ||
183 | } | ||
184 | |||
185 | static struct led_type clockboard_led_types[NUM_LEDS_PER_BOARD] = { | ||
186 | { | ||
187 | .name = "clockboard-left", | ||
188 | .handler = clockboard_left_set, | ||
189 | }, | ||
190 | { | ||
191 | .name = "clockboard-middle", | ||
192 | .handler = clockboard_middle_set, | ||
193 | }, | ||
194 | { | ||
195 | .name = "clockboard-right", | ||
196 | .handler = clockboard_right_set, | ||
197 | .default_trigger= "heartbeat", | ||
198 | }, | ||
199 | }; | ||
200 | |||
201 | static int __devinit sunfire_clockboard_led_probe(struct platform_device *pdev) | ||
202 | { | ||
203 | return sunfire_led_generic_probe(pdev, clockboard_led_types); | ||
204 | } | ||
205 | |||
206 | static struct led_type fhc_led_types[NUM_LEDS_PER_BOARD] = { | ||
207 | { | ||
208 | .name = "fhc-left", | ||
209 | .handler = fhc_left_set, | ||
210 | }, | ||
211 | { | ||
212 | .name = "fhc-middle", | ||
213 | .handler = fhc_middle_set, | ||
214 | }, | ||
215 | { | ||
216 | .name = "fhc-right", | ||
217 | .handler = fhc_right_set, | ||
218 | .default_trigger= "heartbeat", | ||
219 | }, | ||
220 | }; | ||
221 | |||
222 | static int __devinit sunfire_fhc_led_probe(struct platform_device *pdev) | ||
223 | { | ||
224 | return sunfire_led_generic_probe(pdev, fhc_led_types); | ||
225 | } | ||
226 | |||
227 | MODULE_ALIAS("platform:sunfire-clockboard-leds"); | ||
228 | MODULE_ALIAS("platform:sunfire-fhc-leds"); | ||
229 | |||
230 | static struct platform_driver sunfire_clockboard_led_driver = { | ||
231 | .probe = sunfire_clockboard_led_probe, | ||
232 | .remove = __devexit_p(sunfire_led_generic_remove), | ||
233 | .driver = { | ||
234 | .name = "sunfire-clockboard-leds", | ||
235 | .owner = THIS_MODULE, | ||
236 | }, | ||
237 | }; | ||
238 | |||
239 | static struct platform_driver sunfire_fhc_led_driver = { | ||
240 | .probe = sunfire_fhc_led_probe, | ||
241 | .remove = __devexit_p(sunfire_led_generic_remove), | ||
242 | .driver = { | ||
243 | .name = "sunfire-fhc-leds", | ||
244 | .owner = THIS_MODULE, | ||
245 | }, | ||
246 | }; | ||
247 | |||
248 | static int __init sunfire_leds_init(void) | ||
249 | { | ||
250 | int err = platform_driver_register(&sunfire_clockboard_led_driver); | ||
251 | |||
252 | if (err) { | ||
253 | printk(KERN_ERR PFX "Could not register clock board LED driver\n"); | ||
254 | return err; | ||
255 | } | ||
256 | |||
257 | err = platform_driver_register(&sunfire_fhc_led_driver); | ||
258 | if (err) { | ||
259 | printk(KERN_ERR PFX "Could not register FHC LED driver\n"); | ||
260 | platform_driver_unregister(&sunfire_clockboard_led_driver); | ||
261 | } | ||
262 | |||
263 | return err; | ||
264 | } | ||
265 | |||
266 | static void __exit sunfire_leds_exit(void) | ||
267 | { | ||
268 | platform_driver_unregister(&sunfire_clockboard_led_driver); | ||
269 | platform_driver_unregister(&sunfire_fhc_led_driver); | ||
270 | } | ||
271 | |||
272 | module_init(sunfire_leds_init); | ||
273 | module_exit(sunfire_leds_exit); | ||
diff --git a/drivers/mmc/Kconfig b/drivers/mmc/Kconfig index c0b41e8bcd9d..f2eeb38efa65 100644 --- a/drivers/mmc/Kconfig +++ b/drivers/mmc/Kconfig | |||
@@ -3,13 +3,14 @@ | |||
3 | # | 3 | # |
4 | 4 | ||
5 | menuconfig MMC | 5 | menuconfig MMC |
6 | tristate "MMC/SD card support" | 6 | tristate "MMC/SD/SDIO card support" |
7 | depends on HAS_IOMEM | 7 | depends on HAS_IOMEM |
8 | help | 8 | help |
9 | MMC is the "multi-media card" bus protocol. | 9 | This selects MultiMediaCard, Secure Digital and Secure |
10 | Digital I/O support. | ||
10 | 11 | ||
11 | If you want MMC support, you should say Y here and also | 12 | If you want MMC/SD/SDIO support, you should say Y here and |
12 | to the specific driver for your MMC interface. | 13 | also to your specific host controller driver. |
13 | 14 | ||
14 | config MMC_DEBUG | 15 | config MMC_DEBUG |
15 | bool "MMC debugging" | 16 | bool "MMC debugging" |
diff --git a/drivers/mmc/card/Kconfig b/drivers/mmc/card/Kconfig index dd0f398ee2f5..3f2a912659af 100644 --- a/drivers/mmc/card/Kconfig +++ b/drivers/mmc/card/Kconfig | |||
@@ -2,7 +2,7 @@ | |||
2 | # MMC/SD card drivers | 2 | # MMC/SD card drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | comment "MMC/SD Card Drivers" | 5 | comment "MMC/SD/SDIO Card Drivers" |
6 | 6 | ||
7 | config MMC_BLOCK | 7 | config MMC_BLOCK |
8 | tristate "MMC block device driver" | 8 | tristate "MMC block device driver" |
@@ -34,7 +34,6 @@ config MMC_BLOCK_BOUNCE | |||
34 | 34 | ||
35 | config SDIO_UART | 35 | config SDIO_UART |
36 | tristate "SDIO UART/GPS class support" | 36 | tristate "SDIO UART/GPS class support" |
37 | depends on MMC | ||
38 | help | 37 | help |
39 | SDIO function driver for SDIO cards that implements the UART | 38 | SDIO function driver for SDIO cards that implements the UART |
40 | class, as well as the GPS class which appears like a UART. | 39 | class, as well as the GPS class which appears like a UART. |
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c index efacee0404a0..24c97d3d16bb 100644 --- a/drivers/mmc/card/block.c +++ b/drivers/mmc/card/block.c | |||
@@ -58,7 +58,6 @@ struct mmc_blk_data { | |||
58 | struct mmc_queue queue; | 58 | struct mmc_queue queue; |
59 | 59 | ||
60 | unsigned int usage; | 60 | unsigned int usage; |
61 | unsigned int block_bits; | ||
62 | unsigned int read_only; | 61 | unsigned int read_only; |
63 | }; | 62 | }; |
64 | 63 | ||
@@ -216,8 +215,7 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
216 | struct mmc_blk_data *md = mq->data; | 215 | struct mmc_blk_data *md = mq->data; |
217 | struct mmc_card *card = md->queue.card; | 216 | struct mmc_card *card = md->queue.card; |
218 | struct mmc_blk_request brq; | 217 | struct mmc_blk_request brq; |
219 | int ret = 1, data_size, i; | 218 | int ret = 1; |
220 | struct scatterlist *sg; | ||
221 | 219 | ||
222 | mmc_claim_host(card->host); | 220 | mmc_claim_host(card->host); |
223 | 221 | ||
@@ -233,13 +231,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
233 | if (!mmc_card_blockaddr(card)) | 231 | if (!mmc_card_blockaddr(card)) |
234 | brq.cmd.arg <<= 9; | 232 | brq.cmd.arg <<= 9; |
235 | brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; | 233 | brq.cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_ADTC; |
236 | brq.data.blksz = 1 << md->block_bits; | 234 | brq.data.blksz = 512; |
237 | brq.stop.opcode = MMC_STOP_TRANSMISSION; | 235 | brq.stop.opcode = MMC_STOP_TRANSMISSION; |
238 | brq.stop.arg = 0; | 236 | brq.stop.arg = 0; |
239 | brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; | 237 | brq.stop.flags = MMC_RSP_SPI_R1B | MMC_RSP_R1B | MMC_CMD_AC; |
240 | brq.data.blocks = req->nr_sectors >> (md->block_bits - 9); | 238 | brq.data.blocks = req->nr_sectors; |
241 | if (brq.data.blocks > card->host->max_blk_count) | ||
242 | brq.data.blocks = card->host->max_blk_count; | ||
243 | 239 | ||
244 | if (brq.data.blocks > 1) { | 240 | if (brq.data.blocks > 1) { |
245 | /* SPI multiblock writes terminate using a special | 241 | /* SPI multiblock writes terminate using a special |
@@ -271,24 +267,6 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
271 | 267 | ||
272 | mmc_queue_bounce_pre(mq); | 268 | mmc_queue_bounce_pre(mq); |
273 | 269 | ||
274 | /* | ||
275 | * Adjust the sg list so it is the same size as the | ||
276 | * request. | ||
277 | */ | ||
278 | if (brq.data.blocks != | ||
279 | (req->nr_sectors >> (md->block_bits - 9))) { | ||
280 | data_size = brq.data.blocks * brq.data.blksz; | ||
281 | for_each_sg(brq.data.sg, sg, brq.data.sg_len, i) { | ||
282 | data_size -= sg->length; | ||
283 | if (data_size <= 0) { | ||
284 | sg->length += data_size; | ||
285 | i++; | ||
286 | break; | ||
287 | } | ||
288 | } | ||
289 | brq.data.sg_len = i; | ||
290 | } | ||
291 | |||
292 | mmc_wait_for_req(card->host, &brq.mrq); | 270 | mmc_wait_for_req(card->host, &brq.mrq); |
293 | 271 | ||
294 | mmc_queue_bounce_post(mq); | 272 | mmc_queue_bounce_post(mq); |
@@ -373,16 +351,11 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req) | |||
373 | if (rq_data_dir(req) != READ) { | 351 | if (rq_data_dir(req) != READ) { |
374 | if (mmc_card_sd(card)) { | 352 | if (mmc_card_sd(card)) { |
375 | u32 blocks; | 353 | u32 blocks; |
376 | unsigned int bytes; | ||
377 | 354 | ||
378 | blocks = mmc_sd_num_wr_blocks(card); | 355 | blocks = mmc_sd_num_wr_blocks(card); |
379 | if (blocks != (u32)-1) { | 356 | if (blocks != (u32)-1) { |
380 | if (card->csd.write_partial) | ||
381 | bytes = blocks << md->block_bits; | ||
382 | else | ||
383 | bytes = blocks << 9; | ||
384 | spin_lock_irq(&md->lock); | 357 | spin_lock_irq(&md->lock); |
385 | ret = __blk_end_request(req, 0, bytes); | 358 | ret = __blk_end_request(req, 0, blocks << 9); |
386 | spin_unlock_irq(&md->lock); | 359 | spin_unlock_irq(&md->lock); |
387 | } | 360 | } |
388 | } else { | 361 | } else { |
@@ -432,13 +405,6 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
432 | */ | 405 | */ |
433 | md->read_only = mmc_blk_readonly(card); | 406 | md->read_only = mmc_blk_readonly(card); |
434 | 407 | ||
435 | /* | ||
436 | * Both SD and MMC specifications state (although a bit | ||
437 | * unclearly in the MMC case) that a block size of 512 | ||
438 | * bytes must always be supported by the card. | ||
439 | */ | ||
440 | md->block_bits = 9; | ||
441 | |||
442 | md->disk = alloc_disk(1 << MMC_SHIFT); | 408 | md->disk = alloc_disk(1 << MMC_SHIFT); |
443 | if (md->disk == NULL) { | 409 | if (md->disk == NULL) { |
444 | ret = -ENOMEM; | 410 | ret = -ENOMEM; |
@@ -476,7 +442,7 @@ static struct mmc_blk_data *mmc_blk_alloc(struct mmc_card *card) | |||
476 | 442 | ||
477 | sprintf(md->disk->disk_name, "mmcblk%d", devidx); | 443 | sprintf(md->disk->disk_name, "mmcblk%d", devidx); |
478 | 444 | ||
479 | blk_queue_hardsect_size(md->queue.queue, 1 << md->block_bits); | 445 | blk_queue_hardsect_size(md->queue.queue, 512); |
480 | 446 | ||
481 | if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { | 447 | if (!mmc_card_sd(card) && mmc_card_blockaddr(card)) { |
482 | /* | 448 | /* |
@@ -514,7 +480,7 @@ mmc_blk_set_blksize(struct mmc_blk_data *md, struct mmc_card *card) | |||
514 | 480 | ||
515 | mmc_claim_host(card->host); | 481 | mmc_claim_host(card->host); |
516 | cmd.opcode = MMC_SET_BLOCKLEN; | 482 | cmd.opcode = MMC_SET_BLOCKLEN; |
517 | cmd.arg = 1 << md->block_bits; | 483 | cmd.arg = 512; |
518 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; | 484 | cmd.flags = MMC_RSP_SPI_R1 | MMC_RSP_R1 | MMC_CMD_AC; |
519 | err = mmc_wait_for_cmd(card->host, &cmd, 5); | 485 | err = mmc_wait_for_cmd(card->host, &cmd, 5); |
520 | mmc_release_host(card->host); | 486 | mmc_release_host(card->host); |
diff --git a/drivers/mmc/card/queue.c b/drivers/mmc/card/queue.c index 3dee97e7d165..406989e992ba 100644 --- a/drivers/mmc/card/queue.c +++ b/drivers/mmc/card/queue.c | |||
@@ -31,7 +31,7 @@ static int mmc_prep_request(struct request_queue *q, struct request *req) | |||
31 | /* | 31 | /* |
32 | * We only like normal block requests. | 32 | * We only like normal block requests. |
33 | */ | 33 | */ |
34 | if (!blk_fs_request(req) && !blk_pc_request(req)) { | 34 | if (!blk_fs_request(req)) { |
35 | blk_dump_rq_flags(req, "MMC bad request"); | 35 | blk_dump_rq_flags(req, "MMC bad request"); |
36 | return BLKPREP_KILL; | 36 | return BLKPREP_KILL; |
37 | } | 37 | } |
@@ -131,6 +131,7 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
131 | mq->req = NULL; | 131 | mq->req = NULL; |
132 | 132 | ||
133 | blk_queue_prep_rq(mq->queue, mmc_prep_request); | 133 | blk_queue_prep_rq(mq->queue, mmc_prep_request); |
134 | blk_queue_ordered(mq->queue, QUEUE_ORDERED_DRAIN, NULL); | ||
134 | 135 | ||
135 | #ifdef CONFIG_MMC_BLOCK_BOUNCE | 136 | #ifdef CONFIG_MMC_BLOCK_BOUNCE |
136 | if (host->max_hw_segs == 1) { | 137 | if (host->max_hw_segs == 1) { |
@@ -142,12 +143,19 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
142 | bouncesz = host->max_req_size; | 143 | bouncesz = host->max_req_size; |
143 | if (bouncesz > host->max_seg_size) | 144 | if (bouncesz > host->max_seg_size) |
144 | bouncesz = host->max_seg_size; | 145 | bouncesz = host->max_seg_size; |
146 | if (bouncesz > (host->max_blk_count * 512)) | ||
147 | bouncesz = host->max_blk_count * 512; | ||
148 | |||
149 | if (bouncesz > 512) { | ||
150 | mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL); | ||
151 | if (!mq->bounce_buf) { | ||
152 | printk(KERN_WARNING "%s: unable to " | ||
153 | "allocate bounce buffer\n", | ||
154 | mmc_card_name(card)); | ||
155 | } | ||
156 | } | ||
145 | 157 | ||
146 | mq->bounce_buf = kmalloc(bouncesz, GFP_KERNEL); | 158 | if (mq->bounce_buf) { |
147 | if (!mq->bounce_buf) { | ||
148 | printk(KERN_WARNING "%s: unable to allocate " | ||
149 | "bounce buffer\n", mmc_card_name(card)); | ||
150 | } else { | ||
151 | blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); | 159 | blk_queue_bounce_limit(mq->queue, BLK_BOUNCE_ANY); |
152 | blk_queue_max_sectors(mq->queue, bouncesz / 512); | 160 | blk_queue_max_sectors(mq->queue, bouncesz / 512); |
153 | blk_queue_max_phys_segments(mq->queue, bouncesz / 512); | 161 | blk_queue_max_phys_segments(mq->queue, bouncesz / 512); |
@@ -175,7 +183,8 @@ int mmc_init_queue(struct mmc_queue *mq, struct mmc_card *card, spinlock_t *lock | |||
175 | 183 | ||
176 | if (!mq->bounce_buf) { | 184 | if (!mq->bounce_buf) { |
177 | blk_queue_bounce_limit(mq->queue, limit); | 185 | blk_queue_bounce_limit(mq->queue, limit); |
178 | blk_queue_max_sectors(mq->queue, host->max_req_size / 512); | 186 | blk_queue_max_sectors(mq->queue, |
187 | min(host->max_blk_count, host->max_req_size / 512)); | ||
179 | blk_queue_max_phys_segments(mq->queue, host->max_phys_segs); | 188 | blk_queue_max_phys_segments(mq->queue, host->max_phys_segs); |
180 | blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); | 189 | blk_queue_max_hw_segments(mq->queue, host->max_hw_segs); |
181 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); | 190 | blk_queue_max_segment_size(mq->queue, host->max_seg_size); |
diff --git a/drivers/mmc/core/mmc_ops.c b/drivers/mmc/core/mmc_ops.c index 64b05c6270f2..9c50e6f1c236 100644 --- a/drivers/mmc/core/mmc_ops.c +++ b/drivers/mmc/core/mmc_ops.c | |||
@@ -248,8 +248,12 @@ mmc_send_cxd_data(struct mmc_card *card, struct mmc_host *host, | |||
248 | 248 | ||
249 | sg_init_one(&sg, data_buf, len); | 249 | sg_init_one(&sg, data_buf, len); |
250 | 250 | ||
251 | if (card) | 251 | /* |
252 | mmc_set_data_timeout(&data, card); | 252 | * The spec states that CSR and CID accesses have a timeout |
253 | * of 64 clock cycles. | ||
254 | */ | ||
255 | data.timeout_ns = 0; | ||
256 | data.timeout_clks = 64; | ||
253 | 257 | ||
254 | mmc_wait_for_req(host, &mrq); | 258 | mmc_wait_for_req(host, &mrq); |
255 | 259 | ||
diff --git a/drivers/mmc/core/sdio.c b/drivers/mmc/core/sdio.c index 4eab79e09ccc..fb99ccff9080 100644 --- a/drivers/mmc/core/sdio.c +++ b/drivers/mmc/core/sdio.c | |||
@@ -165,6 +165,36 @@ static int sdio_enable_wide(struct mmc_card *card) | |||
165 | } | 165 | } |
166 | 166 | ||
167 | /* | 167 | /* |
168 | * Test if the card supports high-speed mode and, if so, switch to it. | ||
169 | */ | ||
170 | static int sdio_enable_hs(struct mmc_card *card) | ||
171 | { | ||
172 | int ret; | ||
173 | u8 speed; | ||
174 | |||
175 | if (!(card->host->caps & MMC_CAP_SD_HIGHSPEED)) | ||
176 | return 0; | ||
177 | |||
178 | if (!card->cccr.high_speed) | ||
179 | return 0; | ||
180 | |||
181 | ret = mmc_io_rw_direct(card, 0, 0, SDIO_CCCR_SPEED, 0, &speed); | ||
182 | if (ret) | ||
183 | return ret; | ||
184 | |||
185 | speed |= SDIO_SPEED_EHS; | ||
186 | |||
187 | ret = mmc_io_rw_direct(card, 1, 0, SDIO_CCCR_SPEED, speed, NULL); | ||
188 | if (ret) | ||
189 | return ret; | ||
190 | |||
191 | mmc_card_set_highspeed(card); | ||
192 | mmc_set_timing(card->host, MMC_TIMING_SD_HS); | ||
193 | |||
194 | return 0; | ||
195 | } | ||
196 | |||
197 | /* | ||
168 | * Host is being removed. Free up the current card. | 198 | * Host is being removed. Free up the current card. |
169 | */ | 199 | */ |
170 | static void mmc_sdio_remove(struct mmc_host *host) | 200 | static void mmc_sdio_remove(struct mmc_host *host) |
@@ -333,10 +363,26 @@ int mmc_attach_sdio(struct mmc_host *host, u32 ocr) | |||
333 | goto remove; | 363 | goto remove; |
334 | 364 | ||
335 | /* | 365 | /* |
336 | * No support for high-speed yet, so just set | 366 | * Switch to high-speed (if supported). |
337 | * the card's maximum speed. | ||
338 | */ | 367 | */ |
339 | mmc_set_clock(host, card->cis.max_dtr); | 368 | err = sdio_enable_hs(card); |
369 | if (err) | ||
370 | goto remove; | ||
371 | |||
372 | /* | ||
373 | * Change to the card's maximum speed. | ||
374 | */ | ||
375 | if (mmc_card_highspeed(card)) { | ||
376 | /* | ||
377 | * The SDIO specification doesn't mention how | ||
378 | * the CIS transfer speed register relates to | ||
379 | * high-speed, but it seems that 50 MHz is | ||
380 | * mandatory. | ||
381 | */ | ||
382 | mmc_set_clock(host, 50000000); | ||
383 | } else { | ||
384 | mmc_set_clock(host, card->cis.max_dtr); | ||
385 | } | ||
340 | 386 | ||
341 | /* | 387 | /* |
342 | * Switch to wider bus (if supported). | 388 | * Switch to wider bus (if supported). |
diff --git a/drivers/mmc/core/sdio_irq.c b/drivers/mmc/core/sdio_irq.c index c292e124107a..bb192f90e8e9 100644 --- a/drivers/mmc/core/sdio_irq.c +++ b/drivers/mmc/core/sdio_irq.c | |||
@@ -5,6 +5,8 @@ | |||
5 | * Created: June 18, 2007 | 5 | * Created: June 18, 2007 |
6 | * Copyright: MontaVista Software Inc. | 6 | * Copyright: MontaVista Software Inc. |
7 | * | 7 | * |
8 | * Copyright 2008 Pierre Ossman | ||
9 | * | ||
8 | * This program is free software; you can redistribute it and/or modify | 10 | * This program is free software; you can redistribute it and/or modify |
9 | * it under the terms of the GNU General Public License as published by | 11 | * it under the terms of the GNU General Public License as published by |
10 | * the Free Software Foundation; either version 2 of the License, or (at | 12 | * the Free Software Foundation; either version 2 of the License, or (at |
@@ -107,11 +109,14 @@ static int sdio_irq_thread(void *_host) | |||
107 | 109 | ||
108 | /* | 110 | /* |
109 | * Give other threads a chance to run in the presence of | 111 | * Give other threads a chance to run in the presence of |
110 | * errors. FIXME: determine if due to card removal and | 112 | * errors. |
111 | * possibly exit this thread if so. | ||
112 | */ | 113 | */ |
113 | if (ret < 0) | 114 | if (ret < 0) { |
114 | ssleep(1); | 115 | set_current_state(TASK_INTERRUPTIBLE); |
116 | if (!kthread_should_stop()) | ||
117 | schedule_timeout(HZ); | ||
118 | set_current_state(TASK_RUNNING); | ||
119 | } | ||
115 | 120 | ||
116 | /* | 121 | /* |
117 | * Adaptive polling frequency based on the assumption | 122 | * Adaptive polling frequency based on the assumption |
@@ -154,7 +159,8 @@ static int sdio_card_irq_get(struct mmc_card *card) | |||
154 | if (!host->sdio_irqs++) { | 159 | if (!host->sdio_irqs++) { |
155 | atomic_set(&host->sdio_irq_thread_abort, 0); | 160 | atomic_set(&host->sdio_irq_thread_abort, 0); |
156 | host->sdio_irq_thread = | 161 | host->sdio_irq_thread = |
157 | kthread_run(sdio_irq_thread, host, "ksdiorqd"); | 162 | kthread_run(sdio_irq_thread, host, "ksdioirqd/%s", |
163 | mmc_hostname(host)); | ||
158 | if (IS_ERR(host->sdio_irq_thread)) { | 164 | if (IS_ERR(host->sdio_irq_thread)) { |
159 | int err = PTR_ERR(host->sdio_irq_thread); | 165 | int err = PTR_ERR(host->sdio_irq_thread); |
160 | host->sdio_irqs--; | 166 | host->sdio_irqs--; |
diff --git a/drivers/mmc/host/Kconfig b/drivers/mmc/host/Kconfig index ea8d7a3490d9..dfa585f7feaf 100644 --- a/drivers/mmc/host/Kconfig +++ b/drivers/mmc/host/Kconfig | |||
@@ -2,7 +2,7 @@ | |||
2 | # MMC/SD host controller drivers | 2 | # MMC/SD host controller drivers |
3 | # | 3 | # |
4 | 4 | ||
5 | comment "MMC/SD Host Controller Drivers" | 5 | comment "MMC/SD/SDIO Host Controller Drivers" |
6 | 6 | ||
7 | config MMC_ARMMMCI | 7 | config MMC_ARMMMCI |
8 | tristate "ARM AMBA Multimedia Card Interface support" | 8 | tristate "ARM AMBA Multimedia Card Interface support" |
@@ -114,6 +114,17 @@ config MMC_ATMELMCI | |||
114 | 114 | ||
115 | If unsure, say N. | 115 | If unsure, say N. |
116 | 116 | ||
117 | config MMC_ATMELMCI_DMA | ||
118 | bool "Atmel MCI DMA support (EXPERIMENTAL)" | ||
119 | depends on MMC_ATMELMCI && DMA_ENGINE && EXPERIMENTAL | ||
120 | help | ||
121 | Say Y here to have the Atmel MCI driver use a DMA engine to | ||
122 | do data transfers and thus increase the throughput and | ||
123 | reduce the CPU utilization. Note that this is highly | ||
124 | experimental and may cause the driver to lock up. | ||
125 | |||
126 | If unsure, say N. | ||
127 | |||
117 | config MMC_IMX | 128 | config MMC_IMX |
118 | tristate "Motorola i.MX Multimedia Card Interface support" | 129 | tristate "Motorola i.MX Multimedia Card Interface support" |
119 | depends on ARCH_IMX | 130 | depends on ARCH_IMX |
@@ -141,21 +152,22 @@ config MMC_TIFM_SD | |||
141 | module will be called tifm_sd. | 152 | module will be called tifm_sd. |
142 | 153 | ||
143 | config MMC_SPI | 154 | config MMC_SPI |
144 | tristate "MMC/SD over SPI" | 155 | tristate "MMC/SD/SDIO over SPI" |
145 | depends on MMC && SPI_MASTER && !HIGHMEM && HAS_DMA | 156 | depends on SPI_MASTER && !HIGHMEM && HAS_DMA |
146 | select CRC7 | 157 | select CRC7 |
147 | select CRC_ITU_T | 158 | select CRC_ITU_T |
148 | help | 159 | help |
149 | Some systems accss MMC/SD cards using a SPI controller instead of | 160 | Some systems accss MMC/SD/SDIO cards using a SPI controller |
150 | using a "native" MMC/SD controller. This has a disadvantage of | 161 | instead of using a "native" MMC/SD/SDIO controller. This has a |
151 | being relatively high overhead, but a compensating advantage of | 162 | disadvantage of being relatively high overhead, but a compensating |
152 | working on many systems without dedicated MMC/SD controllers. | 163 | advantage of working on many systems without dedicated MMC/SD/SDIO |
164 | controllers. | ||
153 | 165 | ||
154 | If unsure, or if your system has no SPI master driver, say N. | 166 | If unsure, or if your system has no SPI master driver, say N. |
155 | 167 | ||
156 | config MMC_S3C | 168 | config MMC_S3C |
157 | tristate "Samsung S3C SD/MMC Card Interface support" | 169 | tristate "Samsung S3C SD/MMC Card Interface support" |
158 | depends on ARCH_S3C2410 && MMC | 170 | depends on ARCH_S3C2410 |
159 | help | 171 | help |
160 | This selects a driver for the MCI interface found in | 172 | This selects a driver for the MCI interface found in |
161 | Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs. | 173 | Samsung's S3C2410, S3C2412, S3C2440, S3C2442 CPUs. |
@@ -166,7 +178,7 @@ config MMC_S3C | |||
166 | 178 | ||
167 | config MMC_SDRICOH_CS | 179 | config MMC_SDRICOH_CS |
168 | tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)" | 180 | tristate "MMC/SD driver for Ricoh Bay1Controllers (EXPERIMENTAL)" |
169 | depends on EXPERIMENTAL && MMC && PCI && PCMCIA | 181 | depends on EXPERIMENTAL && PCI && PCMCIA |
170 | help | 182 | help |
171 | Say Y here if your Notebook reports a Ricoh Bay1Controller PCMCIA | 183 | Say Y here if your Notebook reports a Ricoh Bay1Controller PCMCIA |
172 | card whenever you insert a MMC or SD card into the card slot. | 184 | card whenever you insert a MMC or SD card into the card slot. |
diff --git a/drivers/mmc/host/atmel-mci-regs.h b/drivers/mmc/host/atmel-mci-regs.h index 26bd80e65031..b58364ed6bba 100644 --- a/drivers/mmc/host/atmel-mci-regs.h +++ b/drivers/mmc/host/atmel-mci-regs.h | |||
@@ -25,8 +25,10 @@ | |||
25 | #define MCI_SDCR 0x000c /* SD Card / SDIO */ | 25 | #define MCI_SDCR 0x000c /* SD Card / SDIO */ |
26 | # define MCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */ | 26 | # define MCI_SDCSEL_SLOT_A ( 0 << 0) /* Select SD slot A */ |
27 | # define MCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */ | 27 | # define MCI_SDCSEL_SLOT_B ( 1 << 0) /* Select SD slot A */ |
28 | # define MCI_SDCBUS_1BIT ( 0 << 7) /* 1-bit data bus */ | 28 | # define MCI_SDCSEL_MASK ( 3 << 0) |
29 | # define MCI_SDCBUS_4BIT ( 1 << 7) /* 4-bit data bus */ | 29 | # define MCI_SDCBUS_1BIT ( 0 << 6) /* 1-bit data bus */ |
30 | # define MCI_SDCBUS_4BIT ( 2 << 6) /* 4-bit data bus */ | ||
31 | # define MCI_SDCBUS_MASK ( 3 << 6) | ||
30 | #define MCI_ARGR 0x0010 /* Command Argument */ | 32 | #define MCI_ARGR 0x0010 /* Command Argument */ |
31 | #define MCI_CMDR 0x0014 /* Command */ | 33 | #define MCI_CMDR 0x0014 /* Command */ |
32 | # define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */ | 34 | # define MCI_CMDR_CMDNB(x) ((x) << 0) /* Command Opcode */ |
diff --git a/drivers/mmc/host/atmel-mci.c b/drivers/mmc/host/atmel-mci.c index 00008967ef7a..7a3f2436b011 100644 --- a/drivers/mmc/host/atmel-mci.c +++ b/drivers/mmc/host/atmel-mci.c | |||
@@ -11,6 +11,8 @@ | |||
11 | #include <linux/clk.h> | 11 | #include <linux/clk.h> |
12 | #include <linux/debugfs.h> | 12 | #include <linux/debugfs.h> |
13 | #include <linux/device.h> | 13 | #include <linux/device.h> |
14 | #include <linux/dmaengine.h> | ||
15 | #include <linux/dma-mapping.h> | ||
14 | #include <linux/err.h> | 16 | #include <linux/err.h> |
15 | #include <linux/gpio.h> | 17 | #include <linux/gpio.h> |
16 | #include <linux/init.h> | 18 | #include <linux/init.h> |
@@ -33,64 +35,178 @@ | |||
33 | #include "atmel-mci-regs.h" | 35 | #include "atmel-mci-regs.h" |
34 | 36 | ||
35 | #define ATMCI_DATA_ERROR_FLAGS (MCI_DCRCE | MCI_DTOE | MCI_OVRE | MCI_UNRE) | 37 | #define ATMCI_DATA_ERROR_FLAGS (MCI_DCRCE | MCI_DTOE | MCI_OVRE | MCI_UNRE) |
38 | #define ATMCI_DMA_THRESHOLD 16 | ||
36 | 39 | ||
37 | enum { | 40 | enum { |
38 | EVENT_CMD_COMPLETE = 0, | 41 | EVENT_CMD_COMPLETE = 0, |
39 | EVENT_DATA_ERROR, | ||
40 | EVENT_DATA_COMPLETE, | ||
41 | EVENT_STOP_SENT, | ||
42 | EVENT_STOP_COMPLETE, | ||
43 | EVENT_XFER_COMPLETE, | 42 | EVENT_XFER_COMPLETE, |
43 | EVENT_DATA_COMPLETE, | ||
44 | EVENT_DATA_ERROR, | ||
45 | }; | ||
46 | |||
47 | enum atmel_mci_state { | ||
48 | STATE_IDLE = 0, | ||
49 | STATE_SENDING_CMD, | ||
50 | STATE_SENDING_DATA, | ||
51 | STATE_DATA_BUSY, | ||
52 | STATE_SENDING_STOP, | ||
53 | STATE_DATA_ERROR, | ||
54 | }; | ||
55 | |||
56 | struct atmel_mci_dma { | ||
57 | #ifdef CONFIG_MMC_ATMELMCI_DMA | ||
58 | struct dma_client client; | ||
59 | struct dma_chan *chan; | ||
60 | struct dma_async_tx_descriptor *data_desc; | ||
61 | #endif | ||
44 | }; | 62 | }; |
45 | 63 | ||
64 | /** | ||
65 | * struct atmel_mci - MMC controller state shared between all slots | ||
66 | * @lock: Spinlock protecting the queue and associated data. | ||
67 | * @regs: Pointer to MMIO registers. | ||
68 | * @sg: Scatterlist entry currently being processed by PIO code, if any. | ||
69 | * @pio_offset: Offset into the current scatterlist entry. | ||
70 | * @cur_slot: The slot which is currently using the controller. | ||
71 | * @mrq: The request currently being processed on @cur_slot, | ||
72 | * or NULL if the controller is idle. | ||
73 | * @cmd: The command currently being sent to the card, or NULL. | ||
74 | * @data: The data currently being transferred, or NULL if no data | ||
75 | * transfer is in progress. | ||
76 | * @dma: DMA client state. | ||
77 | * @data_chan: DMA channel being used for the current data transfer. | ||
78 | * @cmd_status: Snapshot of SR taken upon completion of the current | ||
79 | * command. Only valid when EVENT_CMD_COMPLETE is pending. | ||
80 | * @data_status: Snapshot of SR taken upon completion of the current | ||
81 | * data transfer. Only valid when EVENT_DATA_COMPLETE or | ||
82 | * EVENT_DATA_ERROR is pending. | ||
83 | * @stop_cmdr: Value to be loaded into CMDR when the stop command is | ||
84 | * to be sent. | ||
85 | * @tasklet: Tasklet running the request state machine. | ||
86 | * @pending_events: Bitmask of events flagged by the interrupt handler | ||
87 | * to be processed by the tasklet. | ||
88 | * @completed_events: Bitmask of events which the state machine has | ||
89 | * processed. | ||
90 | * @state: Tasklet state. | ||
91 | * @queue: List of slots waiting for access to the controller. | ||
92 | * @need_clock_update: Update the clock rate before the next request. | ||
93 | * @need_reset: Reset controller before next request. | ||
94 | * @mode_reg: Value of the MR register. | ||
95 | * @bus_hz: The rate of @mck in Hz. This forms the basis for MMC bus | ||
96 | * rate and timeout calculations. | ||
97 | * @mapbase: Physical address of the MMIO registers. | ||
98 | * @mck: The peripheral bus clock hooked up to the MMC controller. | ||
99 | * @pdev: Platform device associated with the MMC controller. | ||
100 | * @slot: Slots sharing this MMC controller. | ||
101 | * | ||
102 | * Locking | ||
103 | * ======= | ||
104 | * | ||
105 | * @lock is a softirq-safe spinlock protecting @queue as well as | ||
106 | * @cur_slot, @mrq and @state. These must always be updated | ||
107 | * at the same time while holding @lock. | ||
108 | * | ||
109 | * @lock also protects mode_reg and need_clock_update since these are | ||
110 | * used to synchronize mode register updates with the queue | ||
111 | * processing. | ||
112 | * | ||
113 | * The @mrq field of struct atmel_mci_slot is also protected by @lock, | ||
114 | * and must always be written at the same time as the slot is added to | ||
115 | * @queue. | ||
116 | * | ||
117 | * @pending_events and @completed_events are accessed using atomic bit | ||
118 | * operations, so they don't need any locking. | ||
119 | * | ||
120 | * None of the fields touched by the interrupt handler need any | ||
121 | * locking. However, ordering is important: Before EVENT_DATA_ERROR or | ||
122 | * EVENT_DATA_COMPLETE is set in @pending_events, all data-related | ||
123 | * interrupts must be disabled and @data_status updated with a | ||
124 | * snapshot of SR. Similarly, before EVENT_CMD_COMPLETE is set, the | ||
125 | * CMDRDY interupt must be disabled and @cmd_status updated with a | ||
126 | * snapshot of SR, and before EVENT_XFER_COMPLETE can be set, the | ||
127 | * bytes_xfered field of @data must be written. This is ensured by | ||
128 | * using barriers. | ||
129 | */ | ||
46 | struct atmel_mci { | 130 | struct atmel_mci { |
47 | struct mmc_host *mmc; | 131 | spinlock_t lock; |
48 | void __iomem *regs; | 132 | void __iomem *regs; |
49 | 133 | ||
50 | struct scatterlist *sg; | 134 | struct scatterlist *sg; |
51 | unsigned int pio_offset; | 135 | unsigned int pio_offset; |
52 | 136 | ||
137 | struct atmel_mci_slot *cur_slot; | ||
53 | struct mmc_request *mrq; | 138 | struct mmc_request *mrq; |
54 | struct mmc_command *cmd; | 139 | struct mmc_command *cmd; |
55 | struct mmc_data *data; | 140 | struct mmc_data *data; |
56 | 141 | ||
142 | struct atmel_mci_dma dma; | ||
143 | struct dma_chan *data_chan; | ||
144 | |||
57 | u32 cmd_status; | 145 | u32 cmd_status; |
58 | u32 data_status; | 146 | u32 data_status; |
59 | u32 stop_status; | ||
60 | u32 stop_cmdr; | 147 | u32 stop_cmdr; |
61 | 148 | ||
62 | u32 mode_reg; | ||
63 | u32 sdc_reg; | ||
64 | |||
65 | struct tasklet_struct tasklet; | 149 | struct tasklet_struct tasklet; |
66 | unsigned long pending_events; | 150 | unsigned long pending_events; |
67 | unsigned long completed_events; | 151 | unsigned long completed_events; |
152 | enum atmel_mci_state state; | ||
153 | struct list_head queue; | ||
68 | 154 | ||
69 | int present; | 155 | bool need_clock_update; |
70 | int detect_pin; | 156 | bool need_reset; |
71 | int wp_pin; | 157 | u32 mode_reg; |
72 | |||
73 | /* For detect pin debouncing */ | ||
74 | struct timer_list detect_timer; | ||
75 | |||
76 | unsigned long bus_hz; | 158 | unsigned long bus_hz; |
77 | unsigned long mapbase; | 159 | unsigned long mapbase; |
78 | struct clk *mck; | 160 | struct clk *mck; |
79 | struct platform_device *pdev; | 161 | struct platform_device *pdev; |
162 | |||
163 | struct atmel_mci_slot *slot[ATMEL_MCI_MAX_NR_SLOTS]; | ||
164 | }; | ||
165 | |||
166 | /** | ||
167 | * struct atmel_mci_slot - MMC slot state | ||
168 | * @mmc: The mmc_host representing this slot. | ||
169 | * @host: The MMC controller this slot is using. | ||
170 | * @sdc_reg: Value of SDCR to be written before using this slot. | ||
171 | * @mrq: mmc_request currently being processed or waiting to be | ||
172 | * processed, or NULL when the slot is idle. | ||
173 | * @queue_node: List node for placing this node in the @queue list of | ||
174 | * &struct atmel_mci. | ||
175 | * @clock: Clock rate configured by set_ios(). Protected by host->lock. | ||
176 | * @flags: Random state bits associated with the slot. | ||
177 | * @detect_pin: GPIO pin used for card detection, or negative if not | ||
178 | * available. | ||
179 | * @wp_pin: GPIO pin used for card write protect sending, or negative | ||
180 | * if not available. | ||
181 | * @detect_timer: Timer used for debouncing @detect_pin interrupts. | ||
182 | */ | ||
183 | struct atmel_mci_slot { | ||
184 | struct mmc_host *mmc; | ||
185 | struct atmel_mci *host; | ||
186 | |||
187 | u32 sdc_reg; | ||
188 | |||
189 | struct mmc_request *mrq; | ||
190 | struct list_head queue_node; | ||
191 | |||
192 | unsigned int clock; | ||
193 | unsigned long flags; | ||
194 | #define ATMCI_CARD_PRESENT 0 | ||
195 | #define ATMCI_CARD_NEED_INIT 1 | ||
196 | #define ATMCI_SHUTDOWN 2 | ||
197 | |||
198 | int detect_pin; | ||
199 | int wp_pin; | ||
200 | |||
201 | struct timer_list detect_timer; | ||
80 | }; | 202 | }; |
81 | 203 | ||
82 | #define atmci_is_completed(host, event) \ | ||
83 | test_bit(event, &host->completed_events) | ||
84 | #define atmci_test_and_clear_pending(host, event) \ | 204 | #define atmci_test_and_clear_pending(host, event) \ |
85 | test_and_clear_bit(event, &host->pending_events) | 205 | test_and_clear_bit(event, &host->pending_events) |
86 | #define atmci_test_and_set_completed(host, event) \ | ||
87 | test_and_set_bit(event, &host->completed_events) | ||
88 | #define atmci_set_completed(host, event) \ | 206 | #define atmci_set_completed(host, event) \ |
89 | set_bit(event, &host->completed_events) | 207 | set_bit(event, &host->completed_events) |
90 | #define atmci_set_pending(host, event) \ | 208 | #define atmci_set_pending(host, event) \ |
91 | set_bit(event, &host->pending_events) | 209 | set_bit(event, &host->pending_events) |
92 | #define atmci_clear_pending(host, event) \ | ||
93 | clear_bit(event, &host->pending_events) | ||
94 | 210 | ||
95 | /* | 211 | /* |
96 | * The debugfs stuff below is mostly optimized away when | 212 | * The debugfs stuff below is mostly optimized away when |
@@ -98,14 +214,15 @@ struct atmel_mci { | |||
98 | */ | 214 | */ |
99 | static int atmci_req_show(struct seq_file *s, void *v) | 215 | static int atmci_req_show(struct seq_file *s, void *v) |
100 | { | 216 | { |
101 | struct atmel_mci *host = s->private; | 217 | struct atmel_mci_slot *slot = s->private; |
102 | struct mmc_request *mrq = host->mrq; | 218 | struct mmc_request *mrq; |
103 | struct mmc_command *cmd; | 219 | struct mmc_command *cmd; |
104 | struct mmc_command *stop; | 220 | struct mmc_command *stop; |
105 | struct mmc_data *data; | 221 | struct mmc_data *data; |
106 | 222 | ||
107 | /* Make sure we get a consistent snapshot */ | 223 | /* Make sure we get a consistent snapshot */ |
108 | spin_lock_irq(&host->mmc->lock); | 224 | spin_lock_bh(&slot->host->lock); |
225 | mrq = slot->mrq; | ||
109 | 226 | ||
110 | if (mrq) { | 227 | if (mrq) { |
111 | cmd = mrq->cmd; | 228 | cmd = mrq->cmd; |
@@ -130,7 +247,7 @@ static int atmci_req_show(struct seq_file *s, void *v) | |||
130 | stop->resp[2], stop->error); | 247 | stop->resp[2], stop->error); |
131 | } | 248 | } |
132 | 249 | ||
133 | spin_unlock_irq(&host->mmc->lock); | 250 | spin_unlock_bh(&slot->host->lock); |
134 | 251 | ||
135 | return 0; | 252 | return 0; |
136 | } | 253 | } |
@@ -193,12 +310,16 @@ static int atmci_regs_show(struct seq_file *s, void *v) | |||
193 | if (!buf) | 310 | if (!buf) |
194 | return -ENOMEM; | 311 | return -ENOMEM; |
195 | 312 | ||
196 | /* Grab a more or less consistent snapshot */ | 313 | /* |
197 | spin_lock_irq(&host->mmc->lock); | 314 | * Grab a more or less consistent snapshot. Note that we're |
315 | * not disabling interrupts, so IMR and SR may not be | ||
316 | * consistent. | ||
317 | */ | ||
318 | spin_lock_bh(&host->lock); | ||
198 | clk_enable(host->mck); | 319 | clk_enable(host->mck); |
199 | memcpy_fromio(buf, host->regs, MCI_REGS_SIZE); | 320 | memcpy_fromio(buf, host->regs, MCI_REGS_SIZE); |
200 | clk_disable(host->mck); | 321 | clk_disable(host->mck); |
201 | spin_unlock_irq(&host->mmc->lock); | 322 | spin_unlock_bh(&host->lock); |
202 | 323 | ||
203 | seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n", | 324 | seq_printf(s, "MR:\t0x%08x%s%s CLKDIV=%u\n", |
204 | buf[MCI_MR / 4], | 325 | buf[MCI_MR / 4], |
@@ -236,13 +357,13 @@ static const struct file_operations atmci_regs_fops = { | |||
236 | .release = single_release, | 357 | .release = single_release, |
237 | }; | 358 | }; |
238 | 359 | ||
239 | static void atmci_init_debugfs(struct atmel_mci *host) | 360 | static void atmci_init_debugfs(struct atmel_mci_slot *slot) |
240 | { | 361 | { |
241 | struct mmc_host *mmc; | 362 | struct mmc_host *mmc = slot->mmc; |
242 | struct dentry *root; | 363 | struct atmel_mci *host = slot->host; |
243 | struct dentry *node; | 364 | struct dentry *root; |
365 | struct dentry *node; | ||
244 | 366 | ||
245 | mmc = host->mmc; | ||
246 | root = mmc->debugfs_root; | 367 | root = mmc->debugfs_root; |
247 | if (!root) | 368 | if (!root) |
248 | return; | 369 | return; |
@@ -254,7 +375,11 @@ static void atmci_init_debugfs(struct atmel_mci *host) | |||
254 | if (!node) | 375 | if (!node) |
255 | goto err; | 376 | goto err; |
256 | 377 | ||
257 | node = debugfs_create_file("req", S_IRUSR, root, host, &atmci_req_fops); | 378 | node = debugfs_create_file("req", S_IRUSR, root, slot, &atmci_req_fops); |
379 | if (!node) | ||
380 | goto err; | ||
381 | |||
382 | node = debugfs_create_u32("state", S_IRUSR, root, (u32 *)&host->state); | ||
258 | if (!node) | 383 | if (!node) |
259 | goto err; | 384 | goto err; |
260 | 385 | ||
@@ -271,25 +396,7 @@ static void atmci_init_debugfs(struct atmel_mci *host) | |||
271 | return; | 396 | return; |
272 | 397 | ||
273 | err: | 398 | err: |
274 | dev_err(&host->pdev->dev, | 399 | dev_err(&mmc->class_dev, "failed to initialize debugfs for slot\n"); |
275 | "failed to initialize debugfs for controller\n"); | ||
276 | } | ||
277 | |||
278 | static void atmci_enable(struct atmel_mci *host) | ||
279 | { | ||
280 | clk_enable(host->mck); | ||
281 | mci_writel(host, CR, MCI_CR_MCIEN); | ||
282 | mci_writel(host, MR, host->mode_reg); | ||
283 | mci_writel(host, SDCR, host->sdc_reg); | ||
284 | } | ||
285 | |||
286 | static void atmci_disable(struct atmel_mci *host) | ||
287 | { | ||
288 | mci_writel(host, CR, MCI_CR_SWRST); | ||
289 | |||
290 | /* Stall until write is complete, then disable the bus clock */ | ||
291 | mci_readl(host, SR); | ||
292 | clk_disable(host->mck); | ||
293 | } | 400 | } |
294 | 401 | ||
295 | static inline unsigned int ns_to_clocks(struct atmel_mci *host, | 402 | static inline unsigned int ns_to_clocks(struct atmel_mci *host, |
@@ -299,7 +406,7 @@ static inline unsigned int ns_to_clocks(struct atmel_mci *host, | |||
299 | } | 406 | } |
300 | 407 | ||
301 | static void atmci_set_timeout(struct atmel_mci *host, | 408 | static void atmci_set_timeout(struct atmel_mci *host, |
302 | struct mmc_data *data) | 409 | struct atmel_mci_slot *slot, struct mmc_data *data) |
303 | { | 410 | { |
304 | static unsigned dtomul_to_shift[] = { | 411 | static unsigned dtomul_to_shift[] = { |
305 | 0, 4, 7, 8, 10, 12, 16, 20 | 412 | 0, 4, 7, 8, 10, 12, 16, 20 |
@@ -322,7 +429,7 @@ static void atmci_set_timeout(struct atmel_mci *host, | |||
322 | dtocyc = 15; | 429 | dtocyc = 15; |
323 | } | 430 | } |
324 | 431 | ||
325 | dev_vdbg(&host->mmc->class_dev, "setting timeout to %u cycles\n", | 432 | dev_vdbg(&slot->mmc->class_dev, "setting timeout to %u cycles\n", |
326 | dtocyc << dtomul_to_shift[dtomul]); | 433 | dtocyc << dtomul_to_shift[dtomul]); |
327 | mci_writel(host, DTOR, (MCI_DTOMUL(dtomul) | MCI_DTOCYC(dtocyc))); | 434 | mci_writel(host, DTOR, (MCI_DTOMUL(dtomul) | MCI_DTOCYC(dtocyc))); |
328 | } | 435 | } |
@@ -375,15 +482,12 @@ static u32 atmci_prepare_command(struct mmc_host *mmc, | |||
375 | } | 482 | } |
376 | 483 | ||
377 | static void atmci_start_command(struct atmel_mci *host, | 484 | static void atmci_start_command(struct atmel_mci *host, |
378 | struct mmc_command *cmd, | 485 | struct mmc_command *cmd, u32 cmd_flags) |
379 | u32 cmd_flags) | ||
380 | { | 486 | { |
381 | /* Must read host->cmd after testing event flags */ | ||
382 | smp_rmb(); | ||
383 | WARN_ON(host->cmd); | 487 | WARN_ON(host->cmd); |
384 | host->cmd = cmd; | 488 | host->cmd = cmd; |
385 | 489 | ||
386 | dev_vdbg(&host->mmc->class_dev, | 490 | dev_vdbg(&host->pdev->dev, |
387 | "start command: ARGR=0x%08x CMDR=0x%08x\n", | 491 | "start command: ARGR=0x%08x CMDR=0x%08x\n", |
388 | cmd->arg, cmd_flags); | 492 | cmd->arg, cmd_flags); |
389 | 493 | ||
@@ -391,34 +495,157 @@ static void atmci_start_command(struct atmel_mci *host, | |||
391 | mci_writel(host, CMDR, cmd_flags); | 495 | mci_writel(host, CMDR, cmd_flags); |
392 | } | 496 | } |
393 | 497 | ||
394 | static void send_stop_cmd(struct mmc_host *mmc, struct mmc_data *data) | 498 | static void send_stop_cmd(struct atmel_mci *host, struct mmc_data *data) |
395 | { | 499 | { |
396 | struct atmel_mci *host = mmc_priv(mmc); | ||
397 | |||
398 | atmci_start_command(host, data->stop, host->stop_cmdr); | 500 | atmci_start_command(host, data->stop, host->stop_cmdr); |
399 | mci_writel(host, IER, MCI_CMDRDY); | 501 | mci_writel(host, IER, MCI_CMDRDY); |
400 | } | 502 | } |
401 | 503 | ||
402 | static void atmci_request_end(struct mmc_host *mmc, struct mmc_request *mrq) | 504 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
505 | static void atmci_dma_cleanup(struct atmel_mci *host) | ||
403 | { | 506 | { |
404 | struct atmel_mci *host = mmc_priv(mmc); | 507 | struct mmc_data *data = host->data; |
405 | 508 | ||
406 | WARN_ON(host->cmd || host->data); | 509 | dma_unmap_sg(&host->pdev->dev, data->sg, data->sg_len, |
407 | host->mrq = NULL; | 510 | ((data->flags & MMC_DATA_WRITE) |
511 | ? DMA_TO_DEVICE : DMA_FROM_DEVICE)); | ||
512 | } | ||
513 | |||
514 | static void atmci_stop_dma(struct atmel_mci *host) | ||
515 | { | ||
516 | struct dma_chan *chan = host->data_chan; | ||
517 | |||
518 | if (chan) { | ||
519 | chan->device->device_terminate_all(chan); | ||
520 | atmci_dma_cleanup(host); | ||
521 | } else { | ||
522 | /* Data transfer was stopped by the interrupt handler */ | ||
523 | atmci_set_pending(host, EVENT_XFER_COMPLETE); | ||
524 | mci_writel(host, IER, MCI_NOTBUSY); | ||
525 | } | ||
526 | } | ||
527 | |||
528 | /* This function is called by the DMA driver from tasklet context. */ | ||
529 | static void atmci_dma_complete(void *arg) | ||
530 | { | ||
531 | struct atmel_mci *host = arg; | ||
532 | struct mmc_data *data = host->data; | ||
533 | |||
534 | dev_vdbg(&host->pdev->dev, "DMA complete\n"); | ||
535 | |||
536 | atmci_dma_cleanup(host); | ||
537 | |||
538 | /* | ||
539 | * If the card was removed, data will be NULL. No point trying | ||
540 | * to send the stop command or waiting for NBUSY in this case. | ||
541 | */ | ||
542 | if (data) { | ||
543 | atmci_set_pending(host, EVENT_XFER_COMPLETE); | ||
544 | tasklet_schedule(&host->tasklet); | ||
545 | |||
546 | /* | ||
547 | * Regardless of what the documentation says, we have | ||
548 | * to wait for NOTBUSY even after block read | ||
549 | * operations. | ||
550 | * | ||
551 | * When the DMA transfer is complete, the controller | ||
552 | * may still be reading the CRC from the card, i.e. | ||
553 | * the data transfer is still in progress and we | ||
554 | * haven't seen all the potential error bits yet. | ||
555 | * | ||
556 | * The interrupt handler will schedule a different | ||
557 | * tasklet to finish things up when the data transfer | ||
558 | * is completely done. | ||
559 | * | ||
560 | * We may not complete the mmc request here anyway | ||
561 | * because the mmc layer may call back and cause us to | ||
562 | * violate the "don't submit new operations from the | ||
563 | * completion callback" rule of the dma engine | ||
564 | * framework. | ||
565 | */ | ||
566 | mci_writel(host, IER, MCI_NOTBUSY); | ||
567 | } | ||
568 | } | ||
569 | |||
570 | static int | ||
571 | atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) | ||
572 | { | ||
573 | struct dma_chan *chan; | ||
574 | struct dma_async_tx_descriptor *desc; | ||
575 | struct scatterlist *sg; | ||
576 | unsigned int i; | ||
577 | enum dma_data_direction direction; | ||
578 | |||
579 | /* | ||
580 | * We don't do DMA on "complex" transfers, i.e. with | ||
581 | * non-word-aligned buffers or lengths. Also, we don't bother | ||
582 | * with all the DMA setup overhead for short transfers. | ||
583 | */ | ||
584 | if (data->blocks * data->blksz < ATMCI_DMA_THRESHOLD) | ||
585 | return -EINVAL; | ||
586 | if (data->blksz & 3) | ||
587 | return -EINVAL; | ||
588 | |||
589 | for_each_sg(data->sg, sg, data->sg_len, i) { | ||
590 | if (sg->offset & 3 || sg->length & 3) | ||
591 | return -EINVAL; | ||
592 | } | ||
593 | |||
594 | /* If we don't have a channel, we can't do DMA */ | ||
595 | chan = host->dma.chan; | ||
596 | if (chan) { | ||
597 | dma_chan_get(chan); | ||
598 | host->data_chan = chan; | ||
599 | } | ||
600 | |||
601 | if (!chan) | ||
602 | return -ENODEV; | ||
603 | |||
604 | if (data->flags & MMC_DATA_READ) | ||
605 | direction = DMA_FROM_DEVICE; | ||
606 | else | ||
607 | direction = DMA_TO_DEVICE; | ||
608 | |||
609 | desc = chan->device->device_prep_slave_sg(chan, | ||
610 | data->sg, data->sg_len, direction, | ||
611 | DMA_PREP_INTERRUPT | DMA_CTRL_ACK); | ||
612 | if (!desc) | ||
613 | return -ENOMEM; | ||
408 | 614 | ||
409 | atmci_disable(host); | 615 | host->dma.data_desc = desc; |
616 | desc->callback = atmci_dma_complete; | ||
617 | desc->callback_param = host; | ||
618 | desc->tx_submit(desc); | ||
410 | 619 | ||
411 | mmc_request_done(mmc, mrq); | 620 | /* Go! */ |
621 | chan->device->device_issue_pending(chan); | ||
622 | |||
623 | return 0; | ||
624 | } | ||
625 | |||
626 | #else /* CONFIG_MMC_ATMELMCI_DMA */ | ||
627 | |||
628 | static int atmci_submit_data_dma(struct atmel_mci *host, struct mmc_data *data) | ||
629 | { | ||
630 | return -ENOSYS; | ||
412 | } | 631 | } |
413 | 632 | ||
633 | static void atmci_stop_dma(struct atmel_mci *host) | ||
634 | { | ||
635 | /* Data transfer was stopped by the interrupt handler */ | ||
636 | atmci_set_pending(host, EVENT_XFER_COMPLETE); | ||
637 | mci_writel(host, IER, MCI_NOTBUSY); | ||
638 | } | ||
639 | |||
640 | #endif /* CONFIG_MMC_ATMELMCI_DMA */ | ||
641 | |||
414 | /* | 642 | /* |
415 | * Returns a mask of interrupt flags to be enabled after the whole | 643 | * Returns a mask of interrupt flags to be enabled after the whole |
416 | * request has been prepared. | 644 | * request has been prepared. |
417 | */ | 645 | */ |
418 | static u32 atmci_submit_data(struct mmc_host *mmc, struct mmc_data *data) | 646 | static u32 atmci_submit_data(struct atmel_mci *host, struct mmc_data *data) |
419 | { | 647 | { |
420 | struct atmel_mci *host = mmc_priv(mmc); | 648 | u32 iflags; |
421 | u32 iflags; | ||
422 | 649 | ||
423 | data->error = -EINPROGRESS; | 650 | data->error = -EINPROGRESS; |
424 | 651 | ||
@@ -426,77 +653,89 @@ static u32 atmci_submit_data(struct mmc_host *mmc, struct mmc_data *data) | |||
426 | host->sg = NULL; | 653 | host->sg = NULL; |
427 | host->data = data; | 654 | host->data = data; |
428 | 655 | ||
429 | dev_vdbg(&mmc->class_dev, "BLKR=0x%08x\n", | ||
430 | MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz)); | ||
431 | |||
432 | iflags = ATMCI_DATA_ERROR_FLAGS; | 656 | iflags = ATMCI_DATA_ERROR_FLAGS; |
433 | host->sg = data->sg; | 657 | if (atmci_submit_data_dma(host, data)) { |
434 | host->pio_offset = 0; | 658 | host->data_chan = NULL; |
435 | if (data->flags & MMC_DATA_READ) | 659 | |
436 | iflags |= MCI_RXRDY; | 660 | /* |
437 | else | 661 | * Errata: MMC data write operation with less than 12 |
438 | iflags |= MCI_TXRDY; | 662 | * bytes is impossible. |
663 | * | ||
664 | * Errata: MCI Transmit Data Register (TDR) FIFO | ||
665 | * corruption when length is not multiple of 4. | ||
666 | */ | ||
667 | if (data->blocks * data->blksz < 12 | ||
668 | || (data->blocks * data->blksz) & 3) | ||
669 | host->need_reset = true; | ||
670 | |||
671 | host->sg = data->sg; | ||
672 | host->pio_offset = 0; | ||
673 | if (data->flags & MMC_DATA_READ) | ||
674 | iflags |= MCI_RXRDY; | ||
675 | else | ||
676 | iflags |= MCI_TXRDY; | ||
677 | } | ||
439 | 678 | ||
440 | return iflags; | 679 | return iflags; |
441 | } | 680 | } |
442 | 681 | ||
443 | static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq) | 682 | static void atmci_start_request(struct atmel_mci *host, |
683 | struct atmel_mci_slot *slot) | ||
444 | { | 684 | { |
445 | struct atmel_mci *host = mmc_priv(mmc); | 685 | struct mmc_request *mrq; |
446 | struct mmc_data *data; | ||
447 | struct mmc_command *cmd; | 686 | struct mmc_command *cmd; |
687 | struct mmc_data *data; | ||
448 | u32 iflags; | 688 | u32 iflags; |
449 | u32 cmdflags = 0; | 689 | u32 cmdflags; |
450 | |||
451 | iflags = mci_readl(host, IMR); | ||
452 | if (iflags) | ||
453 | dev_warn(&mmc->class_dev, "WARNING: IMR=0x%08x\n", | ||
454 | mci_readl(host, IMR)); | ||
455 | |||
456 | WARN_ON(host->mrq != NULL); | ||
457 | |||
458 | /* | ||
459 | * We may "know" the card is gone even though there's still an | ||
460 | * electrical connection. If so, we really need to communicate | ||
461 | * this to the MMC core since there won't be any more | ||
462 | * interrupts as the card is completely removed. Otherwise, | ||
463 | * the MMC core might believe the card is still there even | ||
464 | * though the card was just removed very slowly. | ||
465 | */ | ||
466 | if (!host->present) { | ||
467 | mrq->cmd->error = -ENOMEDIUM; | ||
468 | mmc_request_done(mmc, mrq); | ||
469 | return; | ||
470 | } | ||
471 | 690 | ||
691 | mrq = slot->mrq; | ||
692 | host->cur_slot = slot; | ||
472 | host->mrq = mrq; | 693 | host->mrq = mrq; |
694 | |||
473 | host->pending_events = 0; | 695 | host->pending_events = 0; |
474 | host->completed_events = 0; | 696 | host->completed_events = 0; |
697 | host->data_status = 0; | ||
475 | 698 | ||
476 | atmci_enable(host); | 699 | if (host->need_reset) { |
700 | mci_writel(host, CR, MCI_CR_SWRST); | ||
701 | mci_writel(host, CR, MCI_CR_MCIEN); | ||
702 | mci_writel(host, MR, host->mode_reg); | ||
703 | host->need_reset = false; | ||
704 | } | ||
705 | mci_writel(host, SDCR, slot->sdc_reg); | ||
477 | 706 | ||
478 | /* We don't support multiple blocks of weird lengths. */ | 707 | iflags = mci_readl(host, IMR); |
708 | if (iflags) | ||
709 | dev_warn(&slot->mmc->class_dev, "WARNING: IMR=0x%08x\n", | ||
710 | iflags); | ||
711 | |||
712 | if (unlikely(test_and_clear_bit(ATMCI_CARD_NEED_INIT, &slot->flags))) { | ||
713 | /* Send init sequence (74 clock cycles) */ | ||
714 | mci_writel(host, CMDR, MCI_CMDR_SPCMD_INIT); | ||
715 | while (!(mci_readl(host, SR) & MCI_CMDRDY)) | ||
716 | cpu_relax(); | ||
717 | } | ||
479 | data = mrq->data; | 718 | data = mrq->data; |
480 | if (data) { | 719 | if (data) { |
481 | if (data->blocks > 1 && data->blksz & 3) | 720 | atmci_set_timeout(host, slot, data); |
482 | goto fail; | ||
483 | atmci_set_timeout(host, data); | ||
484 | 721 | ||
485 | /* Must set block count/size before sending command */ | 722 | /* Must set block count/size before sending command */ |
486 | mci_writel(host, BLKR, MCI_BCNT(data->blocks) | 723 | mci_writel(host, BLKR, MCI_BCNT(data->blocks) |
487 | | MCI_BLKLEN(data->blksz)); | 724 | | MCI_BLKLEN(data->blksz)); |
725 | dev_vdbg(&slot->mmc->class_dev, "BLKR=0x%08x\n", | ||
726 | MCI_BCNT(data->blocks) | MCI_BLKLEN(data->blksz)); | ||
488 | } | 727 | } |
489 | 728 | ||
490 | iflags = MCI_CMDRDY; | 729 | iflags = MCI_CMDRDY; |
491 | cmd = mrq->cmd; | 730 | cmd = mrq->cmd; |
492 | cmdflags = atmci_prepare_command(mmc, cmd); | 731 | cmdflags = atmci_prepare_command(slot->mmc, cmd); |
493 | atmci_start_command(host, cmd, cmdflags); | 732 | atmci_start_command(host, cmd, cmdflags); |
494 | 733 | ||
495 | if (data) | 734 | if (data) |
496 | iflags |= atmci_submit_data(mmc, data); | 735 | iflags |= atmci_submit_data(host, data); |
497 | 736 | ||
498 | if (mrq->stop) { | 737 | if (mrq->stop) { |
499 | host->stop_cmdr = atmci_prepare_command(mmc, mrq->stop); | 738 | host->stop_cmdr = atmci_prepare_command(slot->mmc, mrq->stop); |
500 | host->stop_cmdr |= MCI_CMDR_STOP_XFER; | 739 | host->stop_cmdr |= MCI_CMDR_STOP_XFER; |
501 | if (!(data->flags & MMC_DATA_WRITE)) | 740 | if (!(data->flags & MMC_DATA_WRITE)) |
502 | host->stop_cmdr |= MCI_CMDR_TRDIR_READ; | 741 | host->stop_cmdr |= MCI_CMDR_TRDIR_READ; |
@@ -513,59 +752,156 @@ static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq) | |||
513 | * prepared yet.) | 752 | * prepared yet.) |
514 | */ | 753 | */ |
515 | mci_writel(host, IER, iflags); | 754 | mci_writel(host, IER, iflags); |
755 | } | ||
516 | 756 | ||
517 | return; | 757 | static void atmci_queue_request(struct atmel_mci *host, |
758 | struct atmel_mci_slot *slot, struct mmc_request *mrq) | ||
759 | { | ||
760 | dev_vdbg(&slot->mmc->class_dev, "queue request: state=%d\n", | ||
761 | host->state); | ||
762 | |||
763 | spin_lock_bh(&host->lock); | ||
764 | slot->mrq = mrq; | ||
765 | if (host->state == STATE_IDLE) { | ||
766 | host->state = STATE_SENDING_CMD; | ||
767 | atmci_start_request(host, slot); | ||
768 | } else { | ||
769 | list_add_tail(&slot->queue_node, &host->queue); | ||
770 | } | ||
771 | spin_unlock_bh(&host->lock); | ||
772 | } | ||
518 | 773 | ||
519 | fail: | 774 | static void atmci_request(struct mmc_host *mmc, struct mmc_request *mrq) |
520 | atmci_disable(host); | 775 | { |
521 | host->mrq = NULL; | 776 | struct atmel_mci_slot *slot = mmc_priv(mmc); |
522 | mrq->cmd->error = -EINVAL; | 777 | struct atmel_mci *host = slot->host; |
523 | mmc_request_done(mmc, mrq); | 778 | struct mmc_data *data; |
779 | |||
780 | WARN_ON(slot->mrq); | ||
781 | |||
782 | /* | ||
783 | * We may "know" the card is gone even though there's still an | ||
784 | * electrical connection. If so, we really need to communicate | ||
785 | * this to the MMC core since there won't be any more | ||
786 | * interrupts as the card is completely removed. Otherwise, | ||
787 | * the MMC core might believe the card is still there even | ||
788 | * though the card was just removed very slowly. | ||
789 | */ | ||
790 | if (!test_bit(ATMCI_CARD_PRESENT, &slot->flags)) { | ||
791 | mrq->cmd->error = -ENOMEDIUM; | ||
792 | mmc_request_done(mmc, mrq); | ||
793 | return; | ||
794 | } | ||
795 | |||
796 | /* We don't support multiple blocks of weird lengths. */ | ||
797 | data = mrq->data; | ||
798 | if (data && data->blocks > 1 && data->blksz & 3) { | ||
799 | mrq->cmd->error = -EINVAL; | ||
800 | mmc_request_done(mmc, mrq); | ||
801 | } | ||
802 | |||
803 | atmci_queue_request(host, slot, mrq); | ||
524 | } | 804 | } |
525 | 805 | ||
526 | static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | 806 | static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) |
527 | { | 807 | { |
528 | struct atmel_mci *host = mmc_priv(mmc); | 808 | struct atmel_mci_slot *slot = mmc_priv(mmc); |
809 | struct atmel_mci *host = slot->host; | ||
810 | unsigned int i; | ||
811 | |||
812 | slot->sdc_reg &= ~MCI_SDCBUS_MASK; | ||
813 | switch (ios->bus_width) { | ||
814 | case MMC_BUS_WIDTH_1: | ||
815 | slot->sdc_reg |= MCI_SDCBUS_1BIT; | ||
816 | break; | ||
817 | case MMC_BUS_WIDTH_4: | ||
818 | slot->sdc_reg = MCI_SDCBUS_4BIT; | ||
819 | break; | ||
820 | } | ||
529 | 821 | ||
530 | if (ios->clock) { | 822 | if (ios->clock) { |
823 | unsigned int clock_min = ~0U; | ||
531 | u32 clkdiv; | 824 | u32 clkdiv; |
532 | 825 | ||
533 | /* Set clock rate */ | 826 | spin_lock_bh(&host->lock); |
534 | clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * ios->clock) - 1; | 827 | if (!host->mode_reg) { |
828 | clk_enable(host->mck); | ||
829 | mci_writel(host, CR, MCI_CR_SWRST); | ||
830 | mci_writel(host, CR, MCI_CR_MCIEN); | ||
831 | } | ||
832 | |||
833 | /* | ||
834 | * Use mirror of ios->clock to prevent race with mmc | ||
835 | * core ios update when finding the minimum. | ||
836 | */ | ||
837 | slot->clock = ios->clock; | ||
838 | for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { | ||
839 | if (host->slot[i] && host->slot[i]->clock | ||
840 | && host->slot[i]->clock < clock_min) | ||
841 | clock_min = host->slot[i]->clock; | ||
842 | } | ||
843 | |||
844 | /* Calculate clock divider */ | ||
845 | clkdiv = DIV_ROUND_UP(host->bus_hz, 2 * clock_min) - 1; | ||
535 | if (clkdiv > 255) { | 846 | if (clkdiv > 255) { |
536 | dev_warn(&mmc->class_dev, | 847 | dev_warn(&mmc->class_dev, |
537 | "clock %u too slow; using %lu\n", | 848 | "clock %u too slow; using %lu\n", |
538 | ios->clock, host->bus_hz / (2 * 256)); | 849 | clock_min, host->bus_hz / (2 * 256)); |
539 | clkdiv = 255; | 850 | clkdiv = 255; |
540 | } | 851 | } |
541 | 852 | ||
853 | /* | ||
854 | * WRPROOF and RDPROOF prevent overruns/underruns by | ||
855 | * stopping the clock when the FIFO is full/empty. | ||
856 | * This state is not expected to last for long. | ||
857 | */ | ||
542 | host->mode_reg = MCI_MR_CLKDIV(clkdiv) | MCI_MR_WRPROOF | 858 | host->mode_reg = MCI_MR_CLKDIV(clkdiv) | MCI_MR_WRPROOF |
543 | | MCI_MR_RDPROOF; | 859 | | MCI_MR_RDPROOF; |
544 | } | ||
545 | 860 | ||
546 | switch (ios->bus_width) { | 861 | if (list_empty(&host->queue)) |
547 | case MMC_BUS_WIDTH_1: | 862 | mci_writel(host, MR, host->mode_reg); |
548 | host->sdc_reg = 0; | 863 | else |
549 | break; | 864 | host->need_clock_update = true; |
550 | case MMC_BUS_WIDTH_4: | 865 | |
551 | host->sdc_reg = MCI_SDCBUS_4BIT; | 866 | spin_unlock_bh(&host->lock); |
552 | break; | 867 | } else { |
868 | bool any_slot_active = false; | ||
869 | |||
870 | spin_lock_bh(&host->lock); | ||
871 | slot->clock = 0; | ||
872 | for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { | ||
873 | if (host->slot[i] && host->slot[i]->clock) { | ||
874 | any_slot_active = true; | ||
875 | break; | ||
876 | } | ||
877 | } | ||
878 | if (!any_slot_active) { | ||
879 | mci_writel(host, CR, MCI_CR_MCIDIS); | ||
880 | if (host->mode_reg) { | ||
881 | mci_readl(host, MR); | ||
882 | clk_disable(host->mck); | ||
883 | } | ||
884 | host->mode_reg = 0; | ||
885 | } | ||
886 | spin_unlock_bh(&host->lock); | ||
553 | } | 887 | } |
554 | 888 | ||
555 | switch (ios->power_mode) { | 889 | switch (ios->power_mode) { |
556 | case MMC_POWER_ON: | 890 | case MMC_POWER_UP: |
557 | /* Send init sequence (74 clock cycles) */ | 891 | set_bit(ATMCI_CARD_NEED_INIT, &slot->flags); |
558 | atmci_enable(host); | ||
559 | mci_writel(host, CMDR, MCI_CMDR_SPCMD_INIT); | ||
560 | while (!(mci_readl(host, SR) & MCI_CMDRDY)) | ||
561 | cpu_relax(); | ||
562 | atmci_disable(host); | ||
563 | break; | 892 | break; |
564 | default: | 893 | default: |
565 | /* | 894 | /* |
566 | * TODO: None of the currently available AVR32-based | 895 | * TODO: None of the currently available AVR32-based |
567 | * boards allow MMC power to be turned off. Implement | 896 | * boards allow MMC power to be turned off. Implement |
568 | * power control when this can be tested properly. | 897 | * power control when this can be tested properly. |
898 | * | ||
899 | * We also need to hook this into the clock management | ||
900 | * somehow so that newly inserted cards aren't | ||
901 | * subjected to a fast clock before we have a chance | ||
902 | * to figure out what the maximum rate is. Currently, | ||
903 | * there's no way to avoid this, and there never will | ||
904 | * be for boards that don't support power control. | ||
569 | */ | 905 | */ |
570 | break; | 906 | break; |
571 | } | 907 | } |
@@ -573,31 +909,82 @@ static void atmci_set_ios(struct mmc_host *mmc, struct mmc_ios *ios) | |||
573 | 909 | ||
574 | static int atmci_get_ro(struct mmc_host *mmc) | 910 | static int atmci_get_ro(struct mmc_host *mmc) |
575 | { | 911 | { |
576 | int read_only = 0; | 912 | int read_only = -ENOSYS; |
577 | struct atmel_mci *host = mmc_priv(mmc); | 913 | struct atmel_mci_slot *slot = mmc_priv(mmc); |
578 | 914 | ||
579 | if (gpio_is_valid(host->wp_pin)) { | 915 | if (gpio_is_valid(slot->wp_pin)) { |
580 | read_only = gpio_get_value(host->wp_pin); | 916 | read_only = gpio_get_value(slot->wp_pin); |
581 | dev_dbg(&mmc->class_dev, "card is %s\n", | 917 | dev_dbg(&mmc->class_dev, "card is %s\n", |
582 | read_only ? "read-only" : "read-write"); | 918 | read_only ? "read-only" : "read-write"); |
583 | } else { | ||
584 | dev_dbg(&mmc->class_dev, | ||
585 | "no pin for checking read-only switch." | ||
586 | " Assuming write-enable.\n"); | ||
587 | } | 919 | } |
588 | 920 | ||
589 | return read_only; | 921 | return read_only; |
590 | } | 922 | } |
591 | 923 | ||
592 | static struct mmc_host_ops atmci_ops = { | 924 | static int atmci_get_cd(struct mmc_host *mmc) |
925 | { | ||
926 | int present = -ENOSYS; | ||
927 | struct atmel_mci_slot *slot = mmc_priv(mmc); | ||
928 | |||
929 | if (gpio_is_valid(slot->detect_pin)) { | ||
930 | present = !gpio_get_value(slot->detect_pin); | ||
931 | dev_dbg(&mmc->class_dev, "card is %spresent\n", | ||
932 | present ? "" : "not "); | ||
933 | } | ||
934 | |||
935 | return present; | ||
936 | } | ||
937 | |||
938 | static const struct mmc_host_ops atmci_ops = { | ||
593 | .request = atmci_request, | 939 | .request = atmci_request, |
594 | .set_ios = atmci_set_ios, | 940 | .set_ios = atmci_set_ios, |
595 | .get_ro = atmci_get_ro, | 941 | .get_ro = atmci_get_ro, |
942 | .get_cd = atmci_get_cd, | ||
596 | }; | 943 | }; |
597 | 944 | ||
945 | /* Called with host->lock held */ | ||
946 | static void atmci_request_end(struct atmel_mci *host, struct mmc_request *mrq) | ||
947 | __releases(&host->lock) | ||
948 | __acquires(&host->lock) | ||
949 | { | ||
950 | struct atmel_mci_slot *slot = NULL; | ||
951 | struct mmc_host *prev_mmc = host->cur_slot->mmc; | ||
952 | |||
953 | WARN_ON(host->cmd || host->data); | ||
954 | |||
955 | /* | ||
956 | * Update the MMC clock rate if necessary. This may be | ||
957 | * necessary if set_ios() is called when a different slot is | ||
958 | * busy transfering data. | ||
959 | */ | ||
960 | if (host->need_clock_update) | ||
961 | mci_writel(host, MR, host->mode_reg); | ||
962 | |||
963 | host->cur_slot->mrq = NULL; | ||
964 | host->mrq = NULL; | ||
965 | if (!list_empty(&host->queue)) { | ||
966 | slot = list_entry(host->queue.next, | ||
967 | struct atmel_mci_slot, queue_node); | ||
968 | list_del(&slot->queue_node); | ||
969 | dev_vdbg(&host->pdev->dev, "list not empty: %s is next\n", | ||
970 | mmc_hostname(slot->mmc)); | ||
971 | host->state = STATE_SENDING_CMD; | ||
972 | atmci_start_request(host, slot); | ||
973 | } else { | ||
974 | dev_vdbg(&host->pdev->dev, "list empty\n"); | ||
975 | host->state = STATE_IDLE; | ||
976 | } | ||
977 | |||
978 | spin_unlock(&host->lock); | ||
979 | mmc_request_done(prev_mmc, mrq); | ||
980 | spin_lock(&host->lock); | ||
981 | } | ||
982 | |||
598 | static void atmci_command_complete(struct atmel_mci *host, | 983 | static void atmci_command_complete(struct atmel_mci *host, |
599 | struct mmc_command *cmd, u32 status) | 984 | struct mmc_command *cmd) |
600 | { | 985 | { |
986 | u32 status = host->cmd_status; | ||
987 | |||
601 | /* Read the response from the card (up to 16 bytes) */ | 988 | /* Read the response from the card (up to 16 bytes) */ |
602 | cmd->resp[0] = mci_readl(host, RSPR); | 989 | cmd->resp[0] = mci_readl(host, RSPR); |
603 | cmd->resp[1] = mci_readl(host, RSPR); | 990 | cmd->resp[1] = mci_readl(host, RSPR); |
@@ -614,11 +1001,12 @@ static void atmci_command_complete(struct atmel_mci *host, | |||
614 | cmd->error = 0; | 1001 | cmd->error = 0; |
615 | 1002 | ||
616 | if (cmd->error) { | 1003 | if (cmd->error) { |
617 | dev_dbg(&host->mmc->class_dev, | 1004 | dev_dbg(&host->pdev->dev, |
618 | "command error: status=0x%08x\n", status); | 1005 | "command error: status=0x%08x\n", status); |
619 | 1006 | ||
620 | if (cmd->data) { | 1007 | if (cmd->data) { |
621 | host->data = NULL; | 1008 | host->data = NULL; |
1009 | atmci_stop_dma(host); | ||
622 | mci_writel(host, IDR, MCI_NOTBUSY | 1010 | mci_writel(host, IDR, MCI_NOTBUSY |
623 | | MCI_TXRDY | MCI_RXRDY | 1011 | | MCI_TXRDY | MCI_RXRDY |
624 | | ATMCI_DATA_ERROR_FLAGS); | 1012 | | ATMCI_DATA_ERROR_FLAGS); |
@@ -628,146 +1016,222 @@ static void atmci_command_complete(struct atmel_mci *host, | |||
628 | 1016 | ||
629 | static void atmci_detect_change(unsigned long data) | 1017 | static void atmci_detect_change(unsigned long data) |
630 | { | 1018 | { |
631 | struct atmel_mci *host = (struct atmel_mci *)data; | 1019 | struct atmel_mci_slot *slot = (struct atmel_mci_slot *)data; |
632 | struct mmc_request *mrq = host->mrq; | 1020 | bool present; |
633 | int present; | 1021 | bool present_old; |
634 | 1022 | ||
635 | /* | 1023 | /* |
636 | * atmci_remove() sets detect_pin to -1 before freeing the | 1024 | * atmci_cleanup_slot() sets the ATMCI_SHUTDOWN flag before |
637 | * interrupt. We must not re-enable the interrupt if it has | 1025 | * freeing the interrupt. We must not re-enable the interrupt |
638 | * been freed. | 1026 | * if it has been freed, and if we're shutting down, it |
1027 | * doesn't really matter whether the card is present or not. | ||
639 | */ | 1028 | */ |
640 | smp_rmb(); | 1029 | smp_rmb(); |
641 | if (!gpio_is_valid(host->detect_pin)) | 1030 | if (test_bit(ATMCI_SHUTDOWN, &slot->flags)) |
642 | return; | 1031 | return; |
643 | 1032 | ||
644 | enable_irq(gpio_to_irq(host->detect_pin)); | 1033 | enable_irq(gpio_to_irq(slot->detect_pin)); |
645 | present = !gpio_get_value(host->detect_pin); | 1034 | present = !gpio_get_value(slot->detect_pin); |
1035 | present_old = test_bit(ATMCI_CARD_PRESENT, &slot->flags); | ||
1036 | |||
1037 | dev_vdbg(&slot->mmc->class_dev, "detect change: %d (was %d)\n", | ||
1038 | present, present_old); | ||
646 | 1039 | ||
647 | dev_vdbg(&host->pdev->dev, "detect change: %d (was %d)\n", | 1040 | if (present != present_old) { |
648 | present, host->present); | 1041 | struct atmel_mci *host = slot->host; |
1042 | struct mmc_request *mrq; | ||
649 | 1043 | ||
650 | if (present != host->present) { | 1044 | dev_dbg(&slot->mmc->class_dev, "card %s\n", |
651 | dev_dbg(&host->mmc->class_dev, "card %s\n", | ||
652 | present ? "inserted" : "removed"); | 1045 | present ? "inserted" : "removed"); |
653 | host->present = present; | ||
654 | 1046 | ||
655 | /* Reset controller if card is gone */ | 1047 | spin_lock(&host->lock); |
656 | if (!present) { | 1048 | |
657 | mci_writel(host, CR, MCI_CR_SWRST); | 1049 | if (!present) |
658 | mci_writel(host, IDR, ~0UL); | 1050 | clear_bit(ATMCI_CARD_PRESENT, &slot->flags); |
659 | mci_writel(host, CR, MCI_CR_MCIEN); | 1051 | else |
660 | } | 1052 | set_bit(ATMCI_CARD_PRESENT, &slot->flags); |
661 | 1053 | ||
662 | /* Clean up queue if present */ | 1054 | /* Clean up queue if present */ |
1055 | mrq = slot->mrq; | ||
663 | if (mrq) { | 1056 | if (mrq) { |
664 | /* | 1057 | if (mrq == host->mrq) { |
665 | * Reset controller to terminate any ongoing | 1058 | /* |
666 | * commands or data transfers. | 1059 | * Reset controller to terminate any ongoing |
667 | */ | 1060 | * commands or data transfers. |
668 | mci_writel(host, CR, MCI_CR_SWRST); | 1061 | */ |
1062 | mci_writel(host, CR, MCI_CR_SWRST); | ||
1063 | mci_writel(host, CR, MCI_CR_MCIEN); | ||
1064 | mci_writel(host, MR, host->mode_reg); | ||
669 | 1065 | ||
670 | if (!atmci_is_completed(host, EVENT_CMD_COMPLETE)) | ||
671 | mrq->cmd->error = -ENOMEDIUM; | ||
672 | |||
673 | if (mrq->data && !atmci_is_completed(host, | ||
674 | EVENT_DATA_COMPLETE)) { | ||
675 | host->data = NULL; | 1066 | host->data = NULL; |
676 | mrq->data->error = -ENOMEDIUM; | 1067 | host->cmd = NULL; |
1068 | |||
1069 | switch (host->state) { | ||
1070 | case STATE_IDLE: | ||
1071 | break; | ||
1072 | case STATE_SENDING_CMD: | ||
1073 | mrq->cmd->error = -ENOMEDIUM; | ||
1074 | if (!mrq->data) | ||
1075 | break; | ||
1076 | /* fall through */ | ||
1077 | case STATE_SENDING_DATA: | ||
1078 | mrq->data->error = -ENOMEDIUM; | ||
1079 | atmci_stop_dma(host); | ||
1080 | break; | ||
1081 | case STATE_DATA_BUSY: | ||
1082 | case STATE_DATA_ERROR: | ||
1083 | if (mrq->data->error == -EINPROGRESS) | ||
1084 | mrq->data->error = -ENOMEDIUM; | ||
1085 | if (!mrq->stop) | ||
1086 | break; | ||
1087 | /* fall through */ | ||
1088 | case STATE_SENDING_STOP: | ||
1089 | mrq->stop->error = -ENOMEDIUM; | ||
1090 | break; | ||
1091 | } | ||
1092 | |||
1093 | atmci_request_end(host, mrq); | ||
1094 | } else { | ||
1095 | list_del(&slot->queue_node); | ||
1096 | mrq->cmd->error = -ENOMEDIUM; | ||
1097 | if (mrq->data) | ||
1098 | mrq->data->error = -ENOMEDIUM; | ||
1099 | if (mrq->stop) | ||
1100 | mrq->stop->error = -ENOMEDIUM; | ||
1101 | |||
1102 | spin_unlock(&host->lock); | ||
1103 | mmc_request_done(slot->mmc, mrq); | ||
1104 | spin_lock(&host->lock); | ||
677 | } | 1105 | } |
678 | if (mrq->stop && !atmci_is_completed(host, | ||
679 | EVENT_STOP_COMPLETE)) | ||
680 | mrq->stop->error = -ENOMEDIUM; | ||
681 | |||
682 | host->cmd = NULL; | ||
683 | atmci_request_end(host->mmc, mrq); | ||
684 | } | 1106 | } |
1107 | spin_unlock(&host->lock); | ||
685 | 1108 | ||
686 | mmc_detect_change(host->mmc, 0); | 1109 | mmc_detect_change(slot->mmc, 0); |
687 | } | 1110 | } |
688 | } | 1111 | } |
689 | 1112 | ||
690 | static void atmci_tasklet_func(unsigned long priv) | 1113 | static void atmci_tasklet_func(unsigned long priv) |
691 | { | 1114 | { |
692 | struct mmc_host *mmc = (struct mmc_host *)priv; | 1115 | struct atmel_mci *host = (struct atmel_mci *)priv; |
693 | struct atmel_mci *host = mmc_priv(mmc); | ||
694 | struct mmc_request *mrq = host->mrq; | 1116 | struct mmc_request *mrq = host->mrq; |
695 | struct mmc_data *data = host->data; | 1117 | struct mmc_data *data = host->data; |
1118 | struct mmc_command *cmd = host->cmd; | ||
1119 | enum atmel_mci_state state = host->state; | ||
1120 | enum atmel_mci_state prev_state; | ||
1121 | u32 status; | ||
1122 | |||
1123 | spin_lock(&host->lock); | ||
696 | 1124 | ||
697 | dev_vdbg(&mmc->class_dev, | 1125 | state = host->state; |
698 | "tasklet: pending/completed/mask %lx/%lx/%x\n", | 1126 | |
699 | host->pending_events, host->completed_events, | 1127 | dev_vdbg(&host->pdev->dev, |
1128 | "tasklet: state %u pending/completed/mask %lx/%lx/%x\n", | ||
1129 | state, host->pending_events, host->completed_events, | ||
700 | mci_readl(host, IMR)); | 1130 | mci_readl(host, IMR)); |
701 | 1131 | ||
702 | if (atmci_test_and_clear_pending(host, EVENT_CMD_COMPLETE)) { | 1132 | do { |
703 | /* | 1133 | prev_state = state; |
704 | * host->cmd must be set to NULL before the interrupt | ||
705 | * handler sees EVENT_CMD_COMPLETE | ||
706 | */ | ||
707 | host->cmd = NULL; | ||
708 | smp_wmb(); | ||
709 | atmci_set_completed(host, EVENT_CMD_COMPLETE); | ||
710 | atmci_command_complete(host, mrq->cmd, host->cmd_status); | ||
711 | |||
712 | if (!mrq->cmd->error && mrq->stop | ||
713 | && atmci_is_completed(host, EVENT_XFER_COMPLETE) | ||
714 | && !atmci_test_and_set_completed(host, | ||
715 | EVENT_STOP_SENT)) | ||
716 | send_stop_cmd(host->mmc, mrq->data); | ||
717 | } | ||
718 | if (atmci_test_and_clear_pending(host, EVENT_STOP_COMPLETE)) { | ||
719 | /* | ||
720 | * host->cmd must be set to NULL before the interrupt | ||
721 | * handler sees EVENT_STOP_COMPLETE | ||
722 | */ | ||
723 | host->cmd = NULL; | ||
724 | smp_wmb(); | ||
725 | atmci_set_completed(host, EVENT_STOP_COMPLETE); | ||
726 | atmci_command_complete(host, mrq->stop, host->stop_status); | ||
727 | } | ||
728 | if (atmci_test_and_clear_pending(host, EVENT_DATA_ERROR)) { | ||
729 | u32 status = host->data_status; | ||
730 | 1134 | ||
731 | dev_vdbg(&mmc->class_dev, "data error: status=%08x\n", status); | 1135 | switch (state) { |
1136 | case STATE_IDLE: | ||
1137 | break; | ||
732 | 1138 | ||
733 | atmci_set_completed(host, EVENT_DATA_ERROR); | 1139 | case STATE_SENDING_CMD: |
734 | atmci_set_completed(host, EVENT_DATA_COMPLETE); | 1140 | if (!atmci_test_and_clear_pending(host, |
1141 | EVENT_CMD_COMPLETE)) | ||
1142 | break; | ||
735 | 1143 | ||
736 | if (status & MCI_DTOE) { | 1144 | host->cmd = NULL; |
737 | dev_dbg(&mmc->class_dev, | 1145 | atmci_set_completed(host, EVENT_CMD_COMPLETE); |
738 | "data timeout error\n"); | 1146 | atmci_command_complete(host, mrq->cmd); |
739 | data->error = -ETIMEDOUT; | 1147 | if (!mrq->data || cmd->error) { |
740 | } else if (status & MCI_DCRCE) { | 1148 | atmci_request_end(host, host->mrq); |
741 | dev_dbg(&mmc->class_dev, "data CRC error\n"); | 1149 | goto unlock; |
742 | data->error = -EILSEQ; | 1150 | } |
743 | } else { | 1151 | |
744 | dev_dbg(&mmc->class_dev, | 1152 | prev_state = state = STATE_SENDING_DATA; |
745 | "data FIFO error (status=%08x)\n", | 1153 | /* fall through */ |
746 | status); | 1154 | |
747 | data->error = -EIO; | 1155 | case STATE_SENDING_DATA: |
748 | } | 1156 | if (atmci_test_and_clear_pending(host, |
1157 | EVENT_DATA_ERROR)) { | ||
1158 | atmci_stop_dma(host); | ||
1159 | if (data->stop) | ||
1160 | send_stop_cmd(host, data); | ||
1161 | state = STATE_DATA_ERROR; | ||
1162 | break; | ||
1163 | } | ||
749 | 1164 | ||
750 | if (host->present && data->stop | 1165 | if (!atmci_test_and_clear_pending(host, |
751 | && atmci_is_completed(host, EVENT_CMD_COMPLETE) | 1166 | EVENT_XFER_COMPLETE)) |
752 | && !atmci_test_and_set_completed( | 1167 | break; |
753 | host, EVENT_STOP_SENT)) | ||
754 | send_stop_cmd(host->mmc, data); | ||
755 | 1168 | ||
756 | host->data = NULL; | 1169 | atmci_set_completed(host, EVENT_XFER_COMPLETE); |
757 | } | 1170 | prev_state = state = STATE_DATA_BUSY; |
758 | if (atmci_test_and_clear_pending(host, EVENT_DATA_COMPLETE)) { | 1171 | /* fall through */ |
759 | atmci_set_completed(host, EVENT_DATA_COMPLETE); | 1172 | |
1173 | case STATE_DATA_BUSY: | ||
1174 | if (!atmci_test_and_clear_pending(host, | ||
1175 | EVENT_DATA_COMPLETE)) | ||
1176 | break; | ||
760 | 1177 | ||
761 | if (!atmci_is_completed(host, EVENT_DATA_ERROR)) { | 1178 | host->data = NULL; |
762 | data->bytes_xfered = data->blocks * data->blksz; | 1179 | atmci_set_completed(host, EVENT_DATA_COMPLETE); |
763 | data->error = 0; | 1180 | status = host->data_status; |
1181 | if (unlikely(status & ATMCI_DATA_ERROR_FLAGS)) { | ||
1182 | if (status & MCI_DTOE) { | ||
1183 | dev_dbg(&host->pdev->dev, | ||
1184 | "data timeout error\n"); | ||
1185 | data->error = -ETIMEDOUT; | ||
1186 | } else if (status & MCI_DCRCE) { | ||
1187 | dev_dbg(&host->pdev->dev, | ||
1188 | "data CRC error\n"); | ||
1189 | data->error = -EILSEQ; | ||
1190 | } else { | ||
1191 | dev_dbg(&host->pdev->dev, | ||
1192 | "data FIFO error (status=%08x)\n", | ||
1193 | status); | ||
1194 | data->error = -EIO; | ||
1195 | } | ||
1196 | } else { | ||
1197 | data->bytes_xfered = data->blocks * data->blksz; | ||
1198 | data->error = 0; | ||
1199 | } | ||
1200 | |||
1201 | if (!data->stop) { | ||
1202 | atmci_request_end(host, host->mrq); | ||
1203 | goto unlock; | ||
1204 | } | ||
1205 | |||
1206 | prev_state = state = STATE_SENDING_STOP; | ||
1207 | if (!data->error) | ||
1208 | send_stop_cmd(host, data); | ||
1209 | /* fall through */ | ||
1210 | |||
1211 | case STATE_SENDING_STOP: | ||
1212 | if (!atmci_test_and_clear_pending(host, | ||
1213 | EVENT_CMD_COMPLETE)) | ||
1214 | break; | ||
1215 | |||
1216 | host->cmd = NULL; | ||
1217 | atmci_command_complete(host, mrq->stop); | ||
1218 | atmci_request_end(host, host->mrq); | ||
1219 | goto unlock; | ||
1220 | |||
1221 | case STATE_DATA_ERROR: | ||
1222 | if (!atmci_test_and_clear_pending(host, | ||
1223 | EVENT_XFER_COMPLETE)) | ||
1224 | break; | ||
1225 | |||
1226 | state = STATE_DATA_BUSY; | ||
1227 | break; | ||
764 | } | 1228 | } |
1229 | } while (state != prev_state); | ||
765 | 1230 | ||
766 | host->data = NULL; | 1231 | host->state = state; |
767 | } | ||
768 | 1232 | ||
769 | if (host->mrq && !host->cmd && !host->data) | 1233 | unlock: |
770 | atmci_request_end(mmc, host->mrq); | 1234 | spin_unlock(&host->lock); |
771 | } | 1235 | } |
772 | 1236 | ||
773 | static void atmci_read_data_pio(struct atmel_mci *host) | 1237 | static void atmci_read_data_pio(struct atmel_mci *host) |
@@ -789,6 +1253,7 @@ static void atmci_read_data_pio(struct atmel_mci *host) | |||
789 | nbytes += 4; | 1253 | nbytes += 4; |
790 | 1254 | ||
791 | if (offset == sg->length) { | 1255 | if (offset == sg->length) { |
1256 | flush_dcache_page(sg_page(sg)); | ||
792 | host->sg = sg = sg_next(sg); | 1257 | host->sg = sg = sg_next(sg); |
793 | if (!sg) | 1258 | if (!sg) |
794 | goto done; | 1259 | goto done; |
@@ -817,9 +1282,11 @@ static void atmci_read_data_pio(struct atmel_mci *host) | |||
817 | mci_writel(host, IDR, (MCI_NOTBUSY | MCI_RXRDY | 1282 | mci_writel(host, IDR, (MCI_NOTBUSY | MCI_RXRDY |
818 | | ATMCI_DATA_ERROR_FLAGS)); | 1283 | | ATMCI_DATA_ERROR_FLAGS)); |
819 | host->data_status = status; | 1284 | host->data_status = status; |
1285 | data->bytes_xfered += nbytes; | ||
1286 | smp_wmb(); | ||
820 | atmci_set_pending(host, EVENT_DATA_ERROR); | 1287 | atmci_set_pending(host, EVENT_DATA_ERROR); |
821 | tasklet_schedule(&host->tasklet); | 1288 | tasklet_schedule(&host->tasklet); |
822 | break; | 1289 | return; |
823 | } | 1290 | } |
824 | } while (status & MCI_RXRDY); | 1291 | } while (status & MCI_RXRDY); |
825 | 1292 | ||
@@ -832,10 +1299,8 @@ done: | |||
832 | mci_writel(host, IDR, MCI_RXRDY); | 1299 | mci_writel(host, IDR, MCI_RXRDY); |
833 | mci_writel(host, IER, MCI_NOTBUSY); | 1300 | mci_writel(host, IER, MCI_NOTBUSY); |
834 | data->bytes_xfered += nbytes; | 1301 | data->bytes_xfered += nbytes; |
835 | atmci_set_completed(host, EVENT_XFER_COMPLETE); | 1302 | smp_wmb(); |
836 | if (data->stop && atmci_is_completed(host, EVENT_CMD_COMPLETE) | 1303 | atmci_set_pending(host, EVENT_XFER_COMPLETE); |
837 | && !atmci_test_and_set_completed(host, EVENT_STOP_SENT)) | ||
838 | send_stop_cmd(host->mmc, data); | ||
839 | } | 1304 | } |
840 | 1305 | ||
841 | static void atmci_write_data_pio(struct atmel_mci *host) | 1306 | static void atmci_write_data_pio(struct atmel_mci *host) |
@@ -888,9 +1353,11 @@ static void atmci_write_data_pio(struct atmel_mci *host) | |||
888 | mci_writel(host, IDR, (MCI_NOTBUSY | MCI_TXRDY | 1353 | mci_writel(host, IDR, (MCI_NOTBUSY | MCI_TXRDY |
889 | | ATMCI_DATA_ERROR_FLAGS)); | 1354 | | ATMCI_DATA_ERROR_FLAGS)); |
890 | host->data_status = status; | 1355 | host->data_status = status; |
1356 | data->bytes_xfered += nbytes; | ||
1357 | smp_wmb(); | ||
891 | atmci_set_pending(host, EVENT_DATA_ERROR); | 1358 | atmci_set_pending(host, EVENT_DATA_ERROR); |
892 | tasklet_schedule(&host->tasklet); | 1359 | tasklet_schedule(&host->tasklet); |
893 | break; | 1360 | return; |
894 | } | 1361 | } |
895 | } while (status & MCI_TXRDY); | 1362 | } while (status & MCI_TXRDY); |
896 | 1363 | ||
@@ -903,38 +1370,26 @@ done: | |||
903 | mci_writel(host, IDR, MCI_TXRDY); | 1370 | mci_writel(host, IDR, MCI_TXRDY); |
904 | mci_writel(host, IER, MCI_NOTBUSY); | 1371 | mci_writel(host, IER, MCI_NOTBUSY); |
905 | data->bytes_xfered += nbytes; | 1372 | data->bytes_xfered += nbytes; |
906 | atmci_set_completed(host, EVENT_XFER_COMPLETE); | 1373 | smp_wmb(); |
907 | if (data->stop && atmci_is_completed(host, EVENT_CMD_COMPLETE) | 1374 | atmci_set_pending(host, EVENT_XFER_COMPLETE); |
908 | && !atmci_test_and_set_completed(host, EVENT_STOP_SENT)) | ||
909 | send_stop_cmd(host->mmc, data); | ||
910 | } | 1375 | } |
911 | 1376 | ||
912 | static void atmci_cmd_interrupt(struct mmc_host *mmc, u32 status) | 1377 | static void atmci_cmd_interrupt(struct atmel_mci *host, u32 status) |
913 | { | 1378 | { |
914 | struct atmel_mci *host = mmc_priv(mmc); | ||
915 | |||
916 | mci_writel(host, IDR, MCI_CMDRDY); | 1379 | mci_writel(host, IDR, MCI_CMDRDY); |
917 | 1380 | ||
918 | if (atmci_is_completed(host, EVENT_STOP_SENT)) { | 1381 | host->cmd_status = status; |
919 | host->stop_status = status; | 1382 | smp_wmb(); |
920 | atmci_set_pending(host, EVENT_STOP_COMPLETE); | 1383 | atmci_set_pending(host, EVENT_CMD_COMPLETE); |
921 | } else { | ||
922 | host->cmd_status = status; | ||
923 | atmci_set_pending(host, EVENT_CMD_COMPLETE); | ||
924 | } | ||
925 | |||
926 | tasklet_schedule(&host->tasklet); | 1384 | tasklet_schedule(&host->tasklet); |
927 | } | 1385 | } |
928 | 1386 | ||
929 | static irqreturn_t atmci_interrupt(int irq, void *dev_id) | 1387 | static irqreturn_t atmci_interrupt(int irq, void *dev_id) |
930 | { | 1388 | { |
931 | struct mmc_host *mmc = dev_id; | 1389 | struct atmel_mci *host = dev_id; |
932 | struct atmel_mci *host = mmc_priv(mmc); | ||
933 | u32 status, mask, pending; | 1390 | u32 status, mask, pending; |
934 | unsigned int pass_count = 0; | 1391 | unsigned int pass_count = 0; |
935 | 1392 | ||
936 | spin_lock(&mmc->lock); | ||
937 | |||
938 | do { | 1393 | do { |
939 | status = mci_readl(host, SR); | 1394 | status = mci_readl(host, SR); |
940 | mask = mci_readl(host, IMR); | 1395 | mask = mci_readl(host, IMR); |
@@ -946,13 +1401,18 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) | |||
946 | mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS | 1401 | mci_writel(host, IDR, ATMCI_DATA_ERROR_FLAGS |
947 | | MCI_RXRDY | MCI_TXRDY); | 1402 | | MCI_RXRDY | MCI_TXRDY); |
948 | pending &= mci_readl(host, IMR); | 1403 | pending &= mci_readl(host, IMR); |
1404 | |||
949 | host->data_status = status; | 1405 | host->data_status = status; |
1406 | smp_wmb(); | ||
950 | atmci_set_pending(host, EVENT_DATA_ERROR); | 1407 | atmci_set_pending(host, EVENT_DATA_ERROR); |
951 | tasklet_schedule(&host->tasklet); | 1408 | tasklet_schedule(&host->tasklet); |
952 | } | 1409 | } |
953 | if (pending & MCI_NOTBUSY) { | 1410 | if (pending & MCI_NOTBUSY) { |
954 | mci_writel(host, IDR, (MCI_NOTBUSY | 1411 | mci_writel(host, IDR, |
955 | | ATMCI_DATA_ERROR_FLAGS)); | 1412 | ATMCI_DATA_ERROR_FLAGS | MCI_NOTBUSY); |
1413 | if (!host->data_status) | ||
1414 | host->data_status = status; | ||
1415 | smp_wmb(); | ||
956 | atmci_set_pending(host, EVENT_DATA_COMPLETE); | 1416 | atmci_set_pending(host, EVENT_DATA_COMPLETE); |
957 | tasklet_schedule(&host->tasklet); | 1417 | tasklet_schedule(&host->tasklet); |
958 | } | 1418 | } |
@@ -962,18 +1422,15 @@ static irqreturn_t atmci_interrupt(int irq, void *dev_id) | |||
962 | atmci_write_data_pio(host); | 1422 | atmci_write_data_pio(host); |
963 | 1423 | ||
964 | if (pending & MCI_CMDRDY) | 1424 | if (pending & MCI_CMDRDY) |
965 | atmci_cmd_interrupt(mmc, status); | 1425 | atmci_cmd_interrupt(host, status); |
966 | } while (pass_count++ < 5); | 1426 | } while (pass_count++ < 5); |
967 | 1427 | ||
968 | spin_unlock(&mmc->lock); | ||
969 | |||
970 | return pass_count ? IRQ_HANDLED : IRQ_NONE; | 1428 | return pass_count ? IRQ_HANDLED : IRQ_NONE; |
971 | } | 1429 | } |
972 | 1430 | ||
973 | static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id) | 1431 | static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id) |
974 | { | 1432 | { |
975 | struct mmc_host *mmc = dev_id; | 1433 | struct atmel_mci_slot *slot = dev_id; |
976 | struct atmel_mci *host = mmc_priv(mmc); | ||
977 | 1434 | ||
978 | /* | 1435 | /* |
979 | * Disable interrupts until the pin has stabilized and check | 1436 | * Disable interrupts until the pin has stabilized and check |
@@ -981,19 +1438,176 @@ static irqreturn_t atmci_detect_interrupt(int irq, void *dev_id) | |||
981 | * middle of the timer routine when this interrupt triggers. | 1438 | * middle of the timer routine when this interrupt triggers. |
982 | */ | 1439 | */ |
983 | disable_irq_nosync(irq); | 1440 | disable_irq_nosync(irq); |
984 | mod_timer(&host->detect_timer, jiffies + msecs_to_jiffies(20)); | 1441 | mod_timer(&slot->detect_timer, jiffies + msecs_to_jiffies(20)); |
985 | 1442 | ||
986 | return IRQ_HANDLED; | 1443 | return IRQ_HANDLED; |
987 | } | 1444 | } |
988 | 1445 | ||
1446 | #ifdef CONFIG_MMC_ATMELMCI_DMA | ||
1447 | |||
1448 | static inline struct atmel_mci * | ||
1449 | dma_client_to_atmel_mci(struct dma_client *client) | ||
1450 | { | ||
1451 | return container_of(client, struct atmel_mci, dma.client); | ||
1452 | } | ||
1453 | |||
1454 | static enum dma_state_client atmci_dma_event(struct dma_client *client, | ||
1455 | struct dma_chan *chan, enum dma_state state) | ||
1456 | { | ||
1457 | struct atmel_mci *host; | ||
1458 | enum dma_state_client ret = DMA_NAK; | ||
1459 | |||
1460 | host = dma_client_to_atmel_mci(client); | ||
1461 | |||
1462 | switch (state) { | ||
1463 | case DMA_RESOURCE_AVAILABLE: | ||
1464 | spin_lock_bh(&host->lock); | ||
1465 | if (!host->dma.chan) { | ||
1466 | host->dma.chan = chan; | ||
1467 | ret = DMA_ACK; | ||
1468 | } | ||
1469 | spin_unlock_bh(&host->lock); | ||
1470 | |||
1471 | if (ret == DMA_ACK) | ||
1472 | dev_info(&host->pdev->dev, | ||
1473 | "Using %s for DMA transfers\n", | ||
1474 | chan->dev.bus_id); | ||
1475 | break; | ||
1476 | |||
1477 | case DMA_RESOURCE_REMOVED: | ||
1478 | spin_lock_bh(&host->lock); | ||
1479 | if (host->dma.chan == chan) { | ||
1480 | host->dma.chan = NULL; | ||
1481 | ret = DMA_ACK; | ||
1482 | } | ||
1483 | spin_unlock_bh(&host->lock); | ||
1484 | |||
1485 | if (ret == DMA_ACK) | ||
1486 | dev_info(&host->pdev->dev, | ||
1487 | "Lost %s, falling back to PIO\n", | ||
1488 | chan->dev.bus_id); | ||
1489 | break; | ||
1490 | |||
1491 | default: | ||
1492 | break; | ||
1493 | } | ||
1494 | |||
1495 | |||
1496 | return ret; | ||
1497 | } | ||
1498 | #endif /* CONFIG_MMC_ATMELMCI_DMA */ | ||
1499 | |||
1500 | static int __init atmci_init_slot(struct atmel_mci *host, | ||
1501 | struct mci_slot_pdata *slot_data, unsigned int id, | ||
1502 | u32 sdc_reg) | ||
1503 | { | ||
1504 | struct mmc_host *mmc; | ||
1505 | struct atmel_mci_slot *slot; | ||
1506 | |||
1507 | mmc = mmc_alloc_host(sizeof(struct atmel_mci_slot), &host->pdev->dev); | ||
1508 | if (!mmc) | ||
1509 | return -ENOMEM; | ||
1510 | |||
1511 | slot = mmc_priv(mmc); | ||
1512 | slot->mmc = mmc; | ||
1513 | slot->host = host; | ||
1514 | slot->detect_pin = slot_data->detect_pin; | ||
1515 | slot->wp_pin = slot_data->wp_pin; | ||
1516 | slot->sdc_reg = sdc_reg; | ||
1517 | |||
1518 | mmc->ops = &atmci_ops; | ||
1519 | mmc->f_min = DIV_ROUND_UP(host->bus_hz, 512); | ||
1520 | mmc->f_max = host->bus_hz / 2; | ||
1521 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
1522 | if (slot_data->bus_width >= 4) | ||
1523 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
1524 | |||
1525 | mmc->max_hw_segs = 64; | ||
1526 | mmc->max_phys_segs = 64; | ||
1527 | mmc->max_req_size = 32768 * 512; | ||
1528 | mmc->max_blk_size = 32768; | ||
1529 | mmc->max_blk_count = 512; | ||
1530 | |||
1531 | /* Assume card is present initially */ | ||
1532 | set_bit(ATMCI_CARD_PRESENT, &slot->flags); | ||
1533 | if (gpio_is_valid(slot->detect_pin)) { | ||
1534 | if (gpio_request(slot->detect_pin, "mmc_detect")) { | ||
1535 | dev_dbg(&mmc->class_dev, "no detect pin available\n"); | ||
1536 | slot->detect_pin = -EBUSY; | ||
1537 | } else if (gpio_get_value(slot->detect_pin)) { | ||
1538 | clear_bit(ATMCI_CARD_PRESENT, &slot->flags); | ||
1539 | } | ||
1540 | } | ||
1541 | |||
1542 | if (!gpio_is_valid(slot->detect_pin)) | ||
1543 | mmc->caps |= MMC_CAP_NEEDS_POLL; | ||
1544 | |||
1545 | if (gpio_is_valid(slot->wp_pin)) { | ||
1546 | if (gpio_request(slot->wp_pin, "mmc_wp")) { | ||
1547 | dev_dbg(&mmc->class_dev, "no WP pin available\n"); | ||
1548 | slot->wp_pin = -EBUSY; | ||
1549 | } | ||
1550 | } | ||
1551 | |||
1552 | host->slot[id] = slot; | ||
1553 | mmc_add_host(mmc); | ||
1554 | |||
1555 | if (gpio_is_valid(slot->detect_pin)) { | ||
1556 | int ret; | ||
1557 | |||
1558 | setup_timer(&slot->detect_timer, atmci_detect_change, | ||
1559 | (unsigned long)slot); | ||
1560 | |||
1561 | ret = request_irq(gpio_to_irq(slot->detect_pin), | ||
1562 | atmci_detect_interrupt, | ||
1563 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | ||
1564 | "mmc-detect", slot); | ||
1565 | if (ret) { | ||
1566 | dev_dbg(&mmc->class_dev, | ||
1567 | "could not request IRQ %d for detect pin\n", | ||
1568 | gpio_to_irq(slot->detect_pin)); | ||
1569 | gpio_free(slot->detect_pin); | ||
1570 | slot->detect_pin = -EBUSY; | ||
1571 | } | ||
1572 | } | ||
1573 | |||
1574 | atmci_init_debugfs(slot); | ||
1575 | |||
1576 | return 0; | ||
1577 | } | ||
1578 | |||
1579 | static void __exit atmci_cleanup_slot(struct atmel_mci_slot *slot, | ||
1580 | unsigned int id) | ||
1581 | { | ||
1582 | /* Debugfs stuff is cleaned up by mmc core */ | ||
1583 | |||
1584 | set_bit(ATMCI_SHUTDOWN, &slot->flags); | ||
1585 | smp_wmb(); | ||
1586 | |||
1587 | mmc_remove_host(slot->mmc); | ||
1588 | |||
1589 | if (gpio_is_valid(slot->detect_pin)) { | ||
1590 | int pin = slot->detect_pin; | ||
1591 | |||
1592 | free_irq(gpio_to_irq(pin), slot); | ||
1593 | del_timer_sync(&slot->detect_timer); | ||
1594 | gpio_free(pin); | ||
1595 | } | ||
1596 | if (gpio_is_valid(slot->wp_pin)) | ||
1597 | gpio_free(slot->wp_pin); | ||
1598 | |||
1599 | slot->host->slot[id] = NULL; | ||
1600 | mmc_free_host(slot->mmc); | ||
1601 | } | ||
1602 | |||
989 | static int __init atmci_probe(struct platform_device *pdev) | 1603 | static int __init atmci_probe(struct platform_device *pdev) |
990 | { | 1604 | { |
991 | struct mci_platform_data *pdata; | 1605 | struct mci_platform_data *pdata; |
992 | struct atmel_mci *host; | 1606 | struct atmel_mci *host; |
993 | struct mmc_host *mmc; | 1607 | struct resource *regs; |
994 | struct resource *regs; | 1608 | unsigned int nr_slots; |
995 | int irq; | 1609 | int irq; |
996 | int ret; | 1610 | int ret; |
997 | 1611 | ||
998 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1612 | regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
999 | if (!regs) | 1613 | if (!regs) |
@@ -1005,15 +1619,13 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
1005 | if (irq < 0) | 1619 | if (irq < 0) |
1006 | return irq; | 1620 | return irq; |
1007 | 1621 | ||
1008 | mmc = mmc_alloc_host(sizeof(struct atmel_mci), &pdev->dev); | 1622 | host = kzalloc(sizeof(struct atmel_mci), GFP_KERNEL); |
1009 | if (!mmc) | 1623 | if (!host) |
1010 | return -ENOMEM; | 1624 | return -ENOMEM; |
1011 | 1625 | ||
1012 | host = mmc_priv(mmc); | ||
1013 | host->pdev = pdev; | 1626 | host->pdev = pdev; |
1014 | host->mmc = mmc; | 1627 | spin_lock_init(&host->lock); |
1015 | host->detect_pin = pdata->detect_pin; | 1628 | INIT_LIST_HEAD(&host->queue); |
1016 | host->wp_pin = pdata->wp_pin; | ||
1017 | 1629 | ||
1018 | host->mck = clk_get(&pdev->dev, "mci_clk"); | 1630 | host->mck = clk_get(&pdev->dev, "mci_clk"); |
1019 | if (IS_ERR(host->mck)) { | 1631 | if (IS_ERR(host->mck)) { |
@@ -1033,122 +1645,102 @@ static int __init atmci_probe(struct platform_device *pdev) | |||
1033 | 1645 | ||
1034 | host->mapbase = regs->start; | 1646 | host->mapbase = regs->start; |
1035 | 1647 | ||
1036 | mmc->ops = &atmci_ops; | 1648 | tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)host); |
1037 | mmc->f_min = (host->bus_hz + 511) / 512; | ||
1038 | mmc->f_max = host->bus_hz / 2; | ||
1039 | mmc->ocr_avail = MMC_VDD_32_33 | MMC_VDD_33_34; | ||
1040 | mmc->caps |= MMC_CAP_4_BIT_DATA; | ||
1041 | |||
1042 | mmc->max_hw_segs = 64; | ||
1043 | mmc->max_phys_segs = 64; | ||
1044 | mmc->max_req_size = 32768 * 512; | ||
1045 | mmc->max_blk_size = 32768; | ||
1046 | mmc->max_blk_count = 512; | ||
1047 | |||
1048 | tasklet_init(&host->tasklet, atmci_tasklet_func, (unsigned long)mmc); | ||
1049 | 1649 | ||
1050 | ret = request_irq(irq, atmci_interrupt, 0, pdev->dev.bus_id, mmc); | 1650 | ret = request_irq(irq, atmci_interrupt, 0, pdev->dev.bus_id, host); |
1051 | if (ret) | 1651 | if (ret) |
1052 | goto err_request_irq; | 1652 | goto err_request_irq; |
1053 | 1653 | ||
1054 | /* Assume card is present if we don't have a detect pin */ | 1654 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
1055 | host->present = 1; | 1655 | if (pdata->dma_slave) { |
1056 | if (gpio_is_valid(host->detect_pin)) { | 1656 | struct dma_slave *slave = pdata->dma_slave; |
1057 | if (gpio_request(host->detect_pin, "mmc_detect")) { | ||
1058 | dev_dbg(&mmc->class_dev, "no detect pin available\n"); | ||
1059 | host->detect_pin = -1; | ||
1060 | } else { | ||
1061 | host->present = !gpio_get_value(host->detect_pin); | ||
1062 | } | ||
1063 | } | ||
1064 | 1657 | ||
1065 | if (!gpio_is_valid(host->detect_pin)) | 1658 | slave->tx_reg = regs->start + MCI_TDR; |
1066 | mmc->caps |= MMC_CAP_NEEDS_POLL; | 1659 | slave->rx_reg = regs->start + MCI_RDR; |
1067 | 1660 | ||
1068 | if (gpio_is_valid(host->wp_pin)) { | 1661 | /* Try to grab a DMA channel */ |
1069 | if (gpio_request(host->wp_pin, "mmc_wp")) { | 1662 | host->dma.client.event_callback = atmci_dma_event; |
1070 | dev_dbg(&mmc->class_dev, "no WP pin available\n"); | 1663 | dma_cap_set(DMA_SLAVE, host->dma.client.cap_mask); |
1071 | host->wp_pin = -1; | 1664 | host->dma.client.slave = slave; |
1072 | } | 1665 | |
1666 | dma_async_client_register(&host->dma.client); | ||
1667 | dma_async_client_chan_request(&host->dma.client); | ||
1668 | } else { | ||
1669 | dev_notice(&pdev->dev, "DMA not available, using PIO\n"); | ||
1073 | } | 1670 | } |
1671 | #endif /* CONFIG_MMC_ATMELMCI_DMA */ | ||
1074 | 1672 | ||
1075 | platform_set_drvdata(pdev, host); | 1673 | platform_set_drvdata(pdev, host); |
1076 | 1674 | ||
1077 | mmc_add_host(mmc); | 1675 | /* We need at least one slot to succeed */ |
1078 | 1676 | nr_slots = 0; | |
1079 | if (gpio_is_valid(host->detect_pin)) { | 1677 | ret = -ENODEV; |
1080 | setup_timer(&host->detect_timer, atmci_detect_change, | 1678 | if (pdata->slot[0].bus_width) { |
1081 | (unsigned long)host); | 1679 | ret = atmci_init_slot(host, &pdata->slot[0], |
1082 | 1680 | MCI_SDCSEL_SLOT_A, 0); | |
1083 | ret = request_irq(gpio_to_irq(host->detect_pin), | 1681 | if (!ret) |
1084 | atmci_detect_interrupt, | 1682 | nr_slots++; |
1085 | IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, | 1683 | } |
1086 | "mmc-detect", mmc); | 1684 | if (pdata->slot[1].bus_width) { |
1087 | if (ret) { | 1685 | ret = atmci_init_slot(host, &pdata->slot[1], |
1088 | dev_dbg(&mmc->class_dev, | 1686 | MCI_SDCSEL_SLOT_B, 1); |
1089 | "could not request IRQ %d for detect pin\n", | 1687 | if (!ret) |
1090 | gpio_to_irq(host->detect_pin)); | 1688 | nr_slots++; |
1091 | gpio_free(host->detect_pin); | ||
1092 | host->detect_pin = -1; | ||
1093 | } | ||
1094 | } | 1689 | } |
1095 | 1690 | ||
1096 | dev_info(&mmc->class_dev, | 1691 | if (!nr_slots) |
1097 | "Atmel MCI controller at 0x%08lx irq %d\n", | 1692 | goto err_init_slot; |
1098 | host->mapbase, irq); | ||
1099 | 1693 | ||
1100 | atmci_init_debugfs(host); | 1694 | dev_info(&pdev->dev, |
1695 | "Atmel MCI controller at 0x%08lx irq %d, %u slots\n", | ||
1696 | host->mapbase, irq, nr_slots); | ||
1101 | 1697 | ||
1102 | return 0; | 1698 | return 0; |
1103 | 1699 | ||
1700 | err_init_slot: | ||
1701 | #ifdef CONFIG_MMC_ATMELMCI_DMA | ||
1702 | if (pdata->dma_slave) | ||
1703 | dma_async_client_unregister(&host->dma.client); | ||
1704 | #endif | ||
1705 | free_irq(irq, host); | ||
1104 | err_request_irq: | 1706 | err_request_irq: |
1105 | iounmap(host->regs); | 1707 | iounmap(host->regs); |
1106 | err_ioremap: | 1708 | err_ioremap: |
1107 | clk_put(host->mck); | 1709 | clk_put(host->mck); |
1108 | err_clk_get: | 1710 | err_clk_get: |
1109 | mmc_free_host(mmc); | 1711 | kfree(host); |
1110 | return ret; | 1712 | return ret; |
1111 | } | 1713 | } |
1112 | 1714 | ||
1113 | static int __exit atmci_remove(struct platform_device *pdev) | 1715 | static int __exit atmci_remove(struct platform_device *pdev) |
1114 | { | 1716 | { |
1115 | struct atmel_mci *host = platform_get_drvdata(pdev); | 1717 | struct atmel_mci *host = platform_get_drvdata(pdev); |
1718 | unsigned int i; | ||
1116 | 1719 | ||
1117 | platform_set_drvdata(pdev, NULL); | 1720 | platform_set_drvdata(pdev, NULL); |
1118 | 1721 | ||
1119 | if (host) { | 1722 | for (i = 0; i < ATMEL_MCI_MAX_NR_SLOTS; i++) { |
1120 | /* Debugfs stuff is cleaned up by mmc core */ | 1723 | if (host->slot[i]) |
1121 | 1724 | atmci_cleanup_slot(host->slot[i], i); | |
1122 | if (gpio_is_valid(host->detect_pin)) { | 1725 | } |
1123 | int pin = host->detect_pin; | ||
1124 | |||
1125 | /* Make sure the timer doesn't enable the interrupt */ | ||
1126 | host->detect_pin = -1; | ||
1127 | smp_wmb(); | ||
1128 | |||
1129 | free_irq(gpio_to_irq(pin), host->mmc); | ||
1130 | del_timer_sync(&host->detect_timer); | ||
1131 | gpio_free(pin); | ||
1132 | } | ||
1133 | |||
1134 | mmc_remove_host(host->mmc); | ||
1135 | 1726 | ||
1136 | clk_enable(host->mck); | 1727 | clk_enable(host->mck); |
1137 | mci_writel(host, IDR, ~0UL); | 1728 | mci_writel(host, IDR, ~0UL); |
1138 | mci_writel(host, CR, MCI_CR_MCIDIS); | 1729 | mci_writel(host, CR, MCI_CR_MCIDIS); |
1139 | mci_readl(host, SR); | 1730 | mci_readl(host, SR); |
1140 | clk_disable(host->mck); | 1731 | clk_disable(host->mck); |
1141 | 1732 | ||
1142 | if (gpio_is_valid(host->wp_pin)) | 1733 | #ifdef CONFIG_MMC_ATMELMCI_DMA |
1143 | gpio_free(host->wp_pin); | 1734 | if (host->dma.client.slave) |
1735 | dma_async_client_unregister(&host->dma.client); | ||
1736 | #endif | ||
1144 | 1737 | ||
1145 | free_irq(platform_get_irq(pdev, 0), host->mmc); | 1738 | free_irq(platform_get_irq(pdev, 0), host); |
1146 | iounmap(host->regs); | 1739 | iounmap(host->regs); |
1147 | 1740 | ||
1148 | clk_put(host->mck); | 1741 | clk_put(host->mck); |
1742 | kfree(host); | ||
1149 | 1743 | ||
1150 | mmc_free_host(host->mmc); | ||
1151 | } | ||
1152 | return 0; | 1744 | return 0; |
1153 | } | 1745 | } |
1154 | 1746 | ||
diff --git a/drivers/mmc/host/mmc_spi.c b/drivers/mmc/host/mmc_spi.c index 7503b81374e0..07faf5412a1f 100644 --- a/drivers/mmc/host/mmc_spi.c +++ b/drivers/mmc/host/mmc_spi.c | |||
@@ -95,8 +95,6 @@ | |||
95 | * reads which takes nowhere near that long. Older cards may be able to use | 95 | * reads which takes nowhere near that long. Older cards may be able to use |
96 | * shorter timeouts ... but why bother? | 96 | * shorter timeouts ... but why bother? |
97 | */ | 97 | */ |
98 | #define readblock_timeout ktime_set(0, 100 * 1000 * 1000) | ||
99 | #define writeblock_timeout ktime_set(0, 250 * 1000 * 1000) | ||
100 | #define r1b_timeout ktime_set(3, 0) | 98 | #define r1b_timeout ktime_set(3, 0) |
101 | 99 | ||
102 | 100 | ||
@@ -220,9 +218,9 @@ mmc_spi_wait_unbusy(struct mmc_spi_host *host, ktime_t timeout) | |||
220 | return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0); | 218 | return mmc_spi_skip(host, timeout, sizeof(host->data->status), 0); |
221 | } | 219 | } |
222 | 220 | ||
223 | static int mmc_spi_readtoken(struct mmc_spi_host *host) | 221 | static int mmc_spi_readtoken(struct mmc_spi_host *host, ktime_t timeout) |
224 | { | 222 | { |
225 | return mmc_spi_skip(host, readblock_timeout, 1, 0xff); | 223 | return mmc_spi_skip(host, timeout, 1, 0xff); |
226 | } | 224 | } |
227 | 225 | ||
228 | 226 | ||
@@ -605,7 +603,8 @@ mmc_spi_setup_data_message( | |||
605 | * Return negative errno, else success. | 603 | * Return negative errno, else success. |
606 | */ | 604 | */ |
607 | static int | 605 | static int |
608 | mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t) | 606 | mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t, |
607 | ktime_t timeout) | ||
609 | { | 608 | { |
610 | struct spi_device *spi = host->spi; | 609 | struct spi_device *spi = host->spi; |
611 | int status, i; | 610 | int status, i; |
@@ -673,7 +672,7 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t) | |||
673 | if (scratch->status[i] != 0) | 672 | if (scratch->status[i] != 0) |
674 | return 0; | 673 | return 0; |
675 | } | 674 | } |
676 | return mmc_spi_wait_unbusy(host, writeblock_timeout); | 675 | return mmc_spi_wait_unbusy(host, timeout); |
677 | } | 676 | } |
678 | 677 | ||
679 | /* | 678 | /* |
@@ -693,7 +692,8 @@ mmc_spi_writeblock(struct mmc_spi_host *host, struct spi_transfer *t) | |||
693 | * STOP_TRANSMISSION command. | 692 | * STOP_TRANSMISSION command. |
694 | */ | 693 | */ |
695 | static int | 694 | static int |
696 | mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t) | 695 | mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t, |
696 | ktime_t timeout) | ||
697 | { | 697 | { |
698 | struct spi_device *spi = host->spi; | 698 | struct spi_device *spi = host->spi; |
699 | int status; | 699 | int status; |
@@ -707,7 +707,7 @@ mmc_spi_readblock(struct mmc_spi_host *host, struct spi_transfer *t) | |||
707 | return status; | 707 | return status; |
708 | status = scratch->status[0]; | 708 | status = scratch->status[0]; |
709 | if (status == 0xff || status == 0) | 709 | if (status == 0xff || status == 0) |
710 | status = mmc_spi_readtoken(host); | 710 | status = mmc_spi_readtoken(host, timeout); |
711 | 711 | ||
712 | if (status == SPI_TOKEN_SINGLE) { | 712 | if (status == SPI_TOKEN_SINGLE) { |
713 | if (host->dma_dev) { | 713 | if (host->dma_dev) { |
@@ -778,6 +778,8 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, | |||
778 | struct scatterlist *sg; | 778 | struct scatterlist *sg; |
779 | unsigned n_sg; | 779 | unsigned n_sg; |
780 | int multiple = (data->blocks > 1); | 780 | int multiple = (data->blocks > 1); |
781 | u32 clock_rate; | ||
782 | ktime_t timeout; | ||
781 | 783 | ||
782 | if (data->flags & MMC_DATA_READ) | 784 | if (data->flags & MMC_DATA_READ) |
783 | direction = DMA_FROM_DEVICE; | 785 | direction = DMA_FROM_DEVICE; |
@@ -786,6 +788,14 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, | |||
786 | mmc_spi_setup_data_message(host, multiple, direction); | 788 | mmc_spi_setup_data_message(host, multiple, direction); |
787 | t = &host->t; | 789 | t = &host->t; |
788 | 790 | ||
791 | if (t->speed_hz) | ||
792 | clock_rate = t->speed_hz; | ||
793 | else | ||
794 | clock_rate = spi->max_speed_hz; | ||
795 | |||
796 | timeout = ktime_add_ns(ktime_set(0, 0), data->timeout_ns + | ||
797 | data->timeout_clks * 1000000 / clock_rate); | ||
798 | |||
789 | /* Handle scatterlist segments one at a time, with synch for | 799 | /* Handle scatterlist segments one at a time, with synch for |
790 | * each 512-byte block | 800 | * each 512-byte block |
791 | */ | 801 | */ |
@@ -832,9 +842,9 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, | |||
832 | t->len); | 842 | t->len); |
833 | 843 | ||
834 | if (direction == DMA_TO_DEVICE) | 844 | if (direction == DMA_TO_DEVICE) |
835 | status = mmc_spi_writeblock(host, t); | 845 | status = mmc_spi_writeblock(host, t, timeout); |
836 | else | 846 | else |
837 | status = mmc_spi_readblock(host, t); | 847 | status = mmc_spi_readblock(host, t, timeout); |
838 | if (status < 0) | 848 | if (status < 0) |
839 | break; | 849 | break; |
840 | 850 | ||
@@ -917,7 +927,7 @@ mmc_spi_data_do(struct mmc_spi_host *host, struct mmc_command *cmd, | |||
917 | if (scratch->status[tmp] != 0) | 927 | if (scratch->status[tmp] != 0) |
918 | return; | 928 | return; |
919 | } | 929 | } |
920 | tmp = mmc_spi_wait_unbusy(host, writeblock_timeout); | 930 | tmp = mmc_spi_wait_unbusy(host, timeout); |
921 | if (tmp < 0 && !data->error) | 931 | if (tmp < 0 && !data->error) |
922 | data->error = tmp; | 932 | data->error = tmp; |
923 | } | 933 | } |
diff --git a/drivers/mmc/host/sdhci-pci.c b/drivers/mmc/host/sdhci-pci.c index fcb14c2346cc..0a84f10d719c 100644 --- a/drivers/mmc/host/sdhci-pci.c +++ b/drivers/mmc/host/sdhci-pci.c | |||
@@ -144,7 +144,8 @@ static int jmicron_probe(struct sdhci_pci_chip *chip) | |||
144 | SDHCI_QUIRK_32BIT_DMA_SIZE | | 144 | SDHCI_QUIRK_32BIT_DMA_SIZE | |
145 | SDHCI_QUIRK_32BIT_ADMA_SIZE | | 145 | SDHCI_QUIRK_32BIT_ADMA_SIZE | |
146 | SDHCI_QUIRK_RESET_AFTER_REQUEST | | 146 | SDHCI_QUIRK_RESET_AFTER_REQUEST | |
147 | SDHCI_QUIRK_BROKEN_SMALL_PIO; | 147 | SDHCI_QUIRK_BROKEN_SMALL_PIO | |
148 | SDHCI_QUIRK_FORCE_HIGHSPEED; | ||
148 | } | 149 | } |
149 | 150 | ||
150 | /* | 151 | /* |
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c index e3a8133560a2..30f64b1f2354 100644 --- a/drivers/mmc/host/sdhci.c +++ b/drivers/mmc/host/sdhci.c | |||
@@ -177,7 +177,7 @@ static void sdhci_read_block_pio(struct sdhci_host *host) | |||
177 | { | 177 | { |
178 | unsigned long flags; | 178 | unsigned long flags; |
179 | size_t blksize, len, chunk; | 179 | size_t blksize, len, chunk; |
180 | u32 scratch; | 180 | u32 uninitialized_var(scratch); |
181 | u8 *buf; | 181 | u8 *buf; |
182 | 182 | ||
183 | DBG("PIO reading\n"); | 183 | DBG("PIO reading\n"); |
@@ -1154,7 +1154,7 @@ static void sdhci_tasklet_card(unsigned long param) | |||
1154 | 1154 | ||
1155 | spin_unlock_irqrestore(&host->lock, flags); | 1155 | spin_unlock_irqrestore(&host->lock, flags); |
1156 | 1156 | ||
1157 | mmc_detect_change(host->mmc, msecs_to_jiffies(500)); | 1157 | mmc_detect_change(host->mmc, msecs_to_jiffies(200)); |
1158 | } | 1158 | } |
1159 | 1159 | ||
1160 | static void sdhci_tasklet_finish(unsigned long param) | 1160 | static void sdhci_tasklet_finish(unsigned long param) |
@@ -1266,9 +1266,31 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask) | |||
1266 | SDHCI_INT_INDEX)) | 1266 | SDHCI_INT_INDEX)) |
1267 | host->cmd->error = -EILSEQ; | 1267 | host->cmd->error = -EILSEQ; |
1268 | 1268 | ||
1269 | if (host->cmd->error) | 1269 | if (host->cmd->error) { |
1270 | tasklet_schedule(&host->finish_tasklet); | 1270 | tasklet_schedule(&host->finish_tasklet); |
1271 | else if (intmask & SDHCI_INT_RESPONSE) | 1271 | return; |
1272 | } | ||
1273 | |||
1274 | /* | ||
1275 | * The host can send and interrupt when the busy state has | ||
1276 | * ended, allowing us to wait without wasting CPU cycles. | ||
1277 | * Unfortunately this is overloaded on the "data complete" | ||
1278 | * interrupt, so we need to take some care when handling | ||
1279 | * it. | ||
1280 | * | ||
1281 | * Note: The 1.0 specification is a bit ambiguous about this | ||
1282 | * feature so there might be some problems with older | ||
1283 | * controllers. | ||
1284 | */ | ||
1285 | if (host->cmd->flags & MMC_RSP_BUSY) { | ||
1286 | if (host->cmd->data) | ||
1287 | DBG("Cannot wait for busy signal when also " | ||
1288 | "doing a data transfer"); | ||
1289 | else | ||
1290 | return; | ||
1291 | } | ||
1292 | |||
1293 | if (intmask & SDHCI_INT_RESPONSE) | ||
1272 | sdhci_finish_command(host); | 1294 | sdhci_finish_command(host); |
1273 | } | 1295 | } |
1274 | 1296 | ||
@@ -1278,11 +1300,16 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask) | |||
1278 | 1300 | ||
1279 | if (!host->data) { | 1301 | if (!host->data) { |
1280 | /* | 1302 | /* |
1281 | * A data end interrupt is sent together with the response | 1303 | * The "data complete" interrupt is also used to |
1282 | * for the stop command. | 1304 | * indicate that a busy state has ended. See comment |
1305 | * above in sdhci_cmd_irq(). | ||
1283 | */ | 1306 | */ |
1284 | if (intmask & SDHCI_INT_DATA_END) | 1307 | if (host->cmd && (host->cmd->flags & MMC_RSP_BUSY)) { |
1285 | return; | 1308 | if (intmask & SDHCI_INT_DATA_END) { |
1309 | sdhci_finish_command(host); | ||
1310 | return; | ||
1311 | } | ||
1312 | } | ||
1286 | 1313 | ||
1287 | printk(KERN_ERR "%s: Got data interrupt 0x%08x even " | 1314 | printk(KERN_ERR "%s: Got data interrupt 0x%08x even " |
1288 | "though no data operation was in progress.\n", | 1315 | "though no data operation was in progress.\n", |
@@ -1604,7 +1631,8 @@ int sdhci_add_host(struct sdhci_host *host) | |||
1604 | mmc->f_max = host->max_clk; | 1631 | mmc->f_max = host->max_clk; |
1605 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; | 1632 | mmc->caps = MMC_CAP_4_BIT_DATA | MMC_CAP_SDIO_IRQ; |
1606 | 1633 | ||
1607 | if (caps & SDHCI_CAN_DO_HISPD) | 1634 | if ((caps & SDHCI_CAN_DO_HISPD) || |
1635 | (host->quirks & SDHCI_QUIRK_FORCE_HIGHSPEED)) | ||
1608 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; | 1636 | mmc->caps |= MMC_CAP_SD_HIGHSPEED; |
1609 | 1637 | ||
1610 | mmc->ocr_avail = 0; | 1638 | mmc->ocr_avail = 0; |
diff --git a/drivers/mmc/host/sdhci.h b/drivers/mmc/host/sdhci.h index 197d4a05f4ae..31f4b1528e76 100644 --- a/drivers/mmc/host/sdhci.h +++ b/drivers/mmc/host/sdhci.h | |||
@@ -208,6 +208,8 @@ struct sdhci_host { | |||
208 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) | 208 | #define SDHCI_QUIRK_BROKEN_TIMEOUT_VAL (1<<12) |
209 | /* Controller has an issue with buffer bits for small transfers */ | 209 | /* Controller has an issue with buffer bits for small transfers */ |
210 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) | 210 | #define SDHCI_QUIRK_BROKEN_SMALL_PIO (1<<13) |
211 | /* Controller supports high speed but doesn't have the caps bit set */ | ||
212 | #define SDHCI_QUIRK_FORCE_HIGHSPEED (1<<14) | ||
211 | 213 | ||
212 | int irq; /* Device IRQ */ | 214 | int irq; /* Device IRQ */ |
213 | void __iomem * ioaddr; /* Mapped address */ | 215 | void __iomem * ioaddr; /* Mapped address */ |
diff --git a/drivers/mtd/maps/sun_uflash.c b/drivers/mtd/maps/sun_uflash.c index 0d7c88396c88..fd7a1017399a 100644 --- a/drivers/mtd/maps/sun_uflash.c +++ b/drivers/mtd/maps/sun_uflash.c | |||
@@ -1,13 +1,10 @@ | |||
1 | /* | 1 | /* sun_uflash.c - Driver for user-programmable flash on |
2 | * | 2 | * Sun Microsystems SME boardsets. |
3 | * sun_uflash - Driver implementation for user-programmable flash | ||
4 | * present on many Sun Microsystems SME boardsets. | ||
5 | * | 3 | * |
6 | * This driver does NOT provide access to the OBP-flash for | 4 | * This driver does NOT provide access to the OBP-flash for |
7 | * safety reasons-- use <linux>/drivers/sbus/char/flash.c instead. | 5 | * safety reasons-- use <linux>/drivers/sbus/char/flash.c instead. |
8 | * | 6 | * |
9 | * Copyright (c) 2001 Eric Brower (ebrower@usa.net) | 7 | * Copyright (c) 2001 Eric Brower (ebrower@usa.net) |
10 | * | ||
11 | */ | 8 | */ |
12 | 9 | ||
13 | #include <linux/kernel.h> | 10 | #include <linux/kernel.h> |
@@ -16,8 +13,8 @@ | |||
16 | #include <linux/errno.h> | 13 | #include <linux/errno.h> |
17 | #include <linux/init.h> | 14 | #include <linux/init.h> |
18 | #include <linux/ioport.h> | 15 | #include <linux/ioport.h> |
19 | #include <asm/ebus.h> | 16 | #include <linux/of.h> |
20 | #include <asm/oplib.h> | 17 | #include <linux/of_device.h> |
21 | #include <asm/prom.h> | 18 | #include <asm/prom.h> |
22 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
23 | #include <asm/io.h> | 20 | #include <asm/io.h> |
@@ -26,67 +23,65 @@ | |||
26 | #include <linux/mtd/map.h> | 23 | #include <linux/mtd/map.h> |
27 | 24 | ||
28 | #define UFLASH_OBPNAME "flashprom" | 25 | #define UFLASH_OBPNAME "flashprom" |
29 | #define UFLASH_DEVNAME "userflash" | 26 | #define DRIVER_NAME "sun_uflash" |
27 | #define PFX DRIVER_NAME ": " | ||
30 | 28 | ||
31 | #define UFLASH_WINDOW_SIZE 0x200000 | 29 | #define UFLASH_WINDOW_SIZE 0x200000 |
32 | #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */ | 30 | #define UFLASH_BUSWIDTH 1 /* EBus is 8-bit */ |
33 | 31 | ||
34 | MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); | 32 | MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); |
35 | MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets"); | 33 | MODULE_DESCRIPTION("User-programmable flash device on Sun Microsystems boardsets"); |
36 | MODULE_SUPPORTED_DEVICE("userflash"); | 34 | MODULE_SUPPORTED_DEVICE(DRIVER_NAME); |
37 | MODULE_LICENSE("GPL"); | 35 | MODULE_LICENSE("GPL"); |
38 | MODULE_VERSION("2.0"); | 36 | MODULE_VERSION("2.1"); |
39 | 37 | ||
40 | static LIST_HEAD(device_list); | ||
41 | struct uflash_dev { | 38 | struct uflash_dev { |
42 | const char *name; /* device name */ | 39 | const char *name; /* device name */ |
43 | struct map_info map; /* mtd map info */ | 40 | struct map_info map; /* mtd map info */ |
44 | struct mtd_info *mtd; /* mtd info */ | 41 | struct mtd_info *mtd; /* mtd info */ |
45 | }; | 42 | }; |
46 | 43 | ||
47 | |||
48 | struct map_info uflash_map_templ = { | 44 | struct map_info uflash_map_templ = { |
49 | .name = "SUNW,???-????", | 45 | .name = "SUNW,???-????", |
50 | .size = UFLASH_WINDOW_SIZE, | 46 | .size = UFLASH_WINDOW_SIZE, |
51 | .bankwidth = UFLASH_BUSWIDTH, | 47 | .bankwidth = UFLASH_BUSWIDTH, |
52 | }; | 48 | }; |
53 | 49 | ||
54 | int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp) | 50 | int uflash_devinit(struct of_device *op, struct device_node *dp) |
55 | { | 51 | { |
56 | struct uflash_dev *up; | 52 | struct uflash_dev *up; |
57 | struct resource *res; | ||
58 | 53 | ||
59 | res = &edev->resource[0]; | 54 | if (op->resource[1].flags) { |
60 | |||
61 | if (edev->num_addrs != 1) { | ||
62 | /* Non-CFI userflash device-- once I find one we | 55 | /* Non-CFI userflash device-- once I find one we |
63 | * can work on supporting it. | 56 | * can work on supporting it. |
64 | */ | 57 | */ |
65 | printk("%s: unsupported device at 0x%llx (%d regs): " \ | 58 | printk(KERN_ERR PFX "Unsupported device at %s, 0x%llx\n", |
66 | "email ebrower@usa.net\n", | 59 | dp->full_name, (unsigned long long)op->resource[0].start); |
67 | dp->full_name, (unsigned long long)res->start, | ||
68 | edev->num_addrs); | ||
69 | 60 | ||
70 | return -ENODEV; | 61 | return -ENODEV; |
71 | } | 62 | } |
72 | 63 | ||
73 | up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL); | 64 | up = kzalloc(sizeof(struct uflash_dev), GFP_KERNEL); |
74 | if (!up) | 65 | if (!up) { |
66 | printk(KERN_ERR PFX "Cannot allocate struct uflash_dev\n"); | ||
75 | return -ENOMEM; | 67 | return -ENOMEM; |
68 | } | ||
76 | 69 | ||
77 | /* copy defaults and tweak parameters */ | 70 | /* copy defaults and tweak parameters */ |
78 | memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ)); | 71 | memcpy(&up->map, &uflash_map_templ, sizeof(uflash_map_templ)); |
79 | up->map.size = (res->end - res->start) + 1UL; | 72 | |
73 | up->map.size = resource_size(&op->resource[0]); | ||
80 | 74 | ||
81 | up->name = of_get_property(dp, "model", NULL); | 75 | up->name = of_get_property(dp, "model", NULL); |
82 | if (up->name && 0 < strlen(up->name)) | 76 | if (up->name && 0 < strlen(up->name)) |
83 | up->map.name = (char *)up->name; | 77 | up->map.name = (char *)up->name; |
84 | 78 | ||
85 | up->map.phys = res->start; | 79 | up->map.phys = op->resource[0].start; |
86 | 80 | ||
87 | up->map.virt = ioremap_nocache(res->start, up->map.size); | 81 | up->map.virt = of_ioremap(&op->resource[0], 0, up->map.size, |
82 | DRIVER_NAME); | ||
88 | if (!up->map.virt) { | 83 | if (!up->map.virt) { |
89 | printk("%s: Failed to map device.\n", dp->full_name); | 84 | printk(KERN_ERR PFX "Failed to map device.\n"); |
90 | kfree(up); | 85 | kfree(up); |
91 | 86 | ||
92 | return -EINVAL; | 87 | return -EINVAL; |
@@ -97,7 +92,7 @@ int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp) | |||
97 | /* MTD registration */ | 92 | /* MTD registration */ |
98 | up->mtd = do_map_probe("cfi_probe", &up->map); | 93 | up->mtd = do_map_probe("cfi_probe", &up->map); |
99 | if (!up->mtd) { | 94 | if (!up->mtd) { |
100 | iounmap(up->map.virt); | 95 | of_iounmap(&op->resource[0], up->map.virt, up->map.size); |
101 | kfree(up); | 96 | kfree(up); |
102 | 97 | ||
103 | return -ENXIO; | 98 | return -ENXIO; |
@@ -107,32 +102,34 @@ int uflash_devinit(struct linux_ebus_device *edev, struct device_node *dp) | |||
107 | 102 | ||
108 | add_mtd_device(up->mtd); | 103 | add_mtd_device(up->mtd); |
109 | 104 | ||
110 | dev_set_drvdata(&edev->ofdev.dev, up); | 105 | dev_set_drvdata(&op->dev, up); |
111 | 106 | ||
112 | return 0; | 107 | return 0; |
113 | } | 108 | } |
114 | 109 | ||
115 | static int __devinit uflash_probe(struct of_device *dev, const struct of_device_id *match) | 110 | static int __devinit uflash_probe(struct of_device *op, const struct of_device_id *match) |
116 | { | 111 | { |
117 | struct linux_ebus_device *edev = to_ebus_device(&dev->dev); | 112 | struct device_node *dp = op->node; |
118 | struct device_node *dp = dev->node; | ||
119 | 113 | ||
120 | if (of_find_property(dp, "user", NULL)) | 114 | /* Flashprom must have the "user" property in order to |
115 | * be used by this driver. | ||
116 | */ | ||
117 | if (!of_find_property(dp, "user", NULL)) | ||
121 | return -ENODEV; | 118 | return -ENODEV; |
122 | 119 | ||
123 | return uflash_devinit(edev, dp); | 120 | return uflash_devinit(op, dp); |
124 | } | 121 | } |
125 | 122 | ||
126 | static int __devexit uflash_remove(struct of_device *dev) | 123 | static int __devexit uflash_remove(struct of_device *op) |
127 | { | 124 | { |
128 | struct uflash_dev *up = dev_get_drvdata(&dev->dev); | 125 | struct uflash_dev *up = dev_get_drvdata(&op->dev); |
129 | 126 | ||
130 | if (up->mtd) { | 127 | if (up->mtd) { |
131 | del_mtd_device(up->mtd); | 128 | del_mtd_device(up->mtd); |
132 | map_destroy(up->mtd); | 129 | map_destroy(up->mtd); |
133 | } | 130 | } |
134 | if (up->map.virt) { | 131 | if (up->map.virt) { |
135 | iounmap(up->map.virt); | 132 | of_iounmap(&op->resource[0], up->map.virt, up->map.size); |
136 | up->map.virt = NULL; | 133 | up->map.virt = NULL; |
137 | } | 134 | } |
138 | 135 | ||
@@ -141,7 +138,7 @@ static int __devexit uflash_remove(struct of_device *dev) | |||
141 | return 0; | 138 | return 0; |
142 | } | 139 | } |
143 | 140 | ||
144 | static struct of_device_id uflash_match[] = { | 141 | static const struct of_device_id uflash_match[] = { |
145 | { | 142 | { |
146 | .name = UFLASH_OBPNAME, | 143 | .name = UFLASH_OBPNAME, |
147 | }, | 144 | }, |
@@ -151,7 +148,7 @@ static struct of_device_id uflash_match[] = { | |||
151 | MODULE_DEVICE_TABLE(of, uflash_match); | 148 | MODULE_DEVICE_TABLE(of, uflash_match); |
152 | 149 | ||
153 | static struct of_platform_driver uflash_driver = { | 150 | static struct of_platform_driver uflash_driver = { |
154 | .name = UFLASH_DEVNAME, | 151 | .name = DRIVER_NAME, |
155 | .match_table = uflash_match, | 152 | .match_table = uflash_match, |
156 | .probe = uflash_probe, | 153 | .probe = uflash_probe, |
157 | .remove = __devexit_p(uflash_remove), | 154 | .remove = __devexit_p(uflash_remove), |
@@ -159,7 +156,7 @@ static struct of_platform_driver uflash_driver = { | |||
159 | 156 | ||
160 | static int __init uflash_init(void) | 157 | static int __init uflash_init(void) |
161 | { | 158 | { |
162 | return of_register_driver(&uflash_driver, &ebus_bus_type); | 159 | return of_register_driver(&uflash_driver, &of_bus_type); |
163 | } | 160 | } |
164 | 161 | ||
165 | static void __exit uflash_exit(void) | 162 | static void __exit uflash_exit(void) |
diff --git a/drivers/net/e1000/e1000_main.c b/drivers/net/e1000/e1000_main.c index 3bafaede7916..fac82152e4c8 100644 --- a/drivers/net/e1000/e1000_main.c +++ b/drivers/net/e1000/e1000_main.c | |||
@@ -1047,6 +1047,11 @@ static int __devinit e1000_probe(struct pci_dev *pdev, | |||
1047 | 1047 | ||
1048 | netdev->features |= NETIF_F_LLTX; | 1048 | netdev->features |= NETIF_F_LLTX; |
1049 | 1049 | ||
1050 | netdev->vlan_features |= NETIF_F_TSO; | ||
1051 | netdev->vlan_features |= NETIF_F_TSO6; | ||
1052 | netdev->vlan_features |= NETIF_F_HW_CSUM; | ||
1053 | netdev->vlan_features |= NETIF_F_SG; | ||
1054 | |||
1050 | adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); | 1055 | adapter->en_mng_pt = e1000_enable_mng_pass_thru(hw); |
1051 | 1056 | ||
1052 | /* initialize eeprom parameters */ | 1057 | /* initialize eeprom parameters */ |
diff --git a/drivers/net/myri_sbus.c b/drivers/net/myri_sbus.c index 06e682334c7e..3ad7589d6a1c 100644 --- a/drivers/net/myri_sbus.c +++ b/drivers/net/myri_sbus.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* myri_sbus.c: MyriCOM MyriNET SBUS card driver. | 1 | /* myri_sbus.c: MyriCOM MyriNET SBUS card driver. |
2 | * | 2 | * |
3 | * Copyright (C) 1996, 1999, 2006 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 1996, 1999, 2006, 2008 David S. Miller (davem@davemloft.net) |
4 | */ | 4 | */ |
5 | 5 | ||
6 | static char version[] = | 6 | static char version[] = |
@@ -22,6 +22,9 @@ static char version[] = | |||
22 | #include <linux/etherdevice.h> | 22 | #include <linux/etherdevice.h> |
23 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
24 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
25 | #include <linux/dma-mapping.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/of_device.h> | ||
25 | 28 | ||
26 | #include <net/dst.h> | 29 | #include <net/dst.h> |
27 | #include <net/arp.h> | 30 | #include <net/arp.h> |
@@ -33,7 +36,6 @@ static char version[] = | |||
33 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
34 | #include <asm/byteorder.h> | 37 | #include <asm/byteorder.h> |
35 | #include <asm/idprom.h> | 38 | #include <asm/idprom.h> |
36 | #include <asm/sbus.h> | ||
37 | #include <asm/openprom.h> | 39 | #include <asm/openprom.h> |
38 | #include <asm/oplib.h> | 40 | #include <asm/oplib.h> |
39 | #include <asm/auxio.h> | 41 | #include <asm/auxio.h> |
@@ -243,7 +245,8 @@ static void myri_clean_rings(struct myri_eth *mp) | |||
243 | u32 dma_addr; | 245 | u32 dma_addr; |
244 | 246 | ||
245 | dma_addr = sbus_readl(&rxd->myri_scatters[0].addr); | 247 | dma_addr = sbus_readl(&rxd->myri_scatters[0].addr); |
246 | sbus_unmap_single(mp->myri_sdev, dma_addr, RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE); | 248 | dma_unmap_single(&mp->myri_op->dev, dma_addr, |
249 | RX_ALLOC_SIZE, DMA_FROM_DEVICE); | ||
247 | dev_kfree_skb(mp->rx_skbs[i]); | 250 | dev_kfree_skb(mp->rx_skbs[i]); |
248 | mp->rx_skbs[i] = NULL; | 251 | mp->rx_skbs[i] = NULL; |
249 | } | 252 | } |
@@ -259,7 +262,9 @@ static void myri_clean_rings(struct myri_eth *mp) | |||
259 | u32 dma_addr; | 262 | u32 dma_addr; |
260 | 263 | ||
261 | dma_addr = sbus_readl(&txd->myri_gathers[0].addr); | 264 | dma_addr = sbus_readl(&txd->myri_gathers[0].addr); |
262 | sbus_unmap_single(mp->myri_sdev, dma_addr, (skb->len + 3) & ~3, SBUS_DMA_TODEVICE); | 265 | dma_unmap_single(&mp->myri_op->dev, dma_addr, |
266 | (skb->len + 3) & ~3, | ||
267 | DMA_TO_DEVICE); | ||
263 | dev_kfree_skb(mp->tx_skbs[i]); | 268 | dev_kfree_skb(mp->tx_skbs[i]); |
264 | mp->tx_skbs[i] = NULL; | 269 | mp->tx_skbs[i] = NULL; |
265 | } | 270 | } |
@@ -288,7 +293,9 @@ static void myri_init_rings(struct myri_eth *mp, int from_irq) | |||
288 | skb->dev = dev; | 293 | skb->dev = dev; |
289 | skb_put(skb, RX_ALLOC_SIZE); | 294 | skb_put(skb, RX_ALLOC_SIZE); |
290 | 295 | ||
291 | dma_addr = sbus_map_single(mp->myri_sdev, skb->data, RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE); | 296 | dma_addr = dma_map_single(&mp->myri_op->dev, |
297 | skb->data, RX_ALLOC_SIZE, | ||
298 | DMA_FROM_DEVICE); | ||
292 | sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr); | 299 | sbus_writel(dma_addr, &rxd[i].myri_scatters[0].addr); |
293 | sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len); | 300 | sbus_writel(RX_ALLOC_SIZE, &rxd[i].myri_scatters[0].len); |
294 | sbus_writel(i, &rxd[i].ctx); | 301 | sbus_writel(i, &rxd[i].ctx); |
@@ -344,7 +351,8 @@ static void myri_tx(struct myri_eth *mp, struct net_device *dev) | |||
344 | 351 | ||
345 | DTX(("SKB[%d] ", entry)); | 352 | DTX(("SKB[%d] ", entry)); |
346 | dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr); | 353 | dma_addr = sbus_readl(&sq->myri_txd[entry].myri_gathers[0].addr); |
347 | sbus_unmap_single(mp->myri_sdev, dma_addr, skb->len, SBUS_DMA_TODEVICE); | 354 | dma_unmap_single(&mp->myri_op->dev, dma_addr, |
355 | skb->len, DMA_TO_DEVICE); | ||
348 | dev_kfree_skb(skb); | 356 | dev_kfree_skb(skb); |
349 | mp->tx_skbs[entry] = NULL; | 357 | mp->tx_skbs[entry] = NULL; |
350 | dev->stats.tx_packets++; | 358 | dev->stats.tx_packets++; |
@@ -423,9 +431,9 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev) | |||
423 | 431 | ||
424 | /* Check for errors. */ | 432 | /* Check for errors. */ |
425 | DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum)); | 433 | DRX(("rxd[%d]: %p len[%d] csum[%08x] ", entry, rxd, len, csum)); |
426 | sbus_dma_sync_single_for_cpu(mp->myri_sdev, | 434 | dma_sync_single_for_cpu(&mp->myri_op->dev, |
427 | sbus_readl(&rxd->myri_scatters[0].addr), | 435 | sbus_readl(&rxd->myri_scatters[0].addr), |
428 | RX_ALLOC_SIZE, SBUS_DMA_FROMDEVICE); | 436 | RX_ALLOC_SIZE, DMA_FROM_DEVICE); |
429 | if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) { | 437 | if (len < (ETH_HLEN + MYRI_PAD_LEN) || (skb->data[0] != MYRI_PAD_LEN)) { |
430 | DRX(("ERROR[")); | 438 | DRX(("ERROR[")); |
431 | dev->stats.rx_errors++; | 439 | dev->stats.rx_errors++; |
@@ -442,10 +450,10 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev) | |||
442 | drops++; | 450 | drops++; |
443 | DRX(("DROP ")); | 451 | DRX(("DROP ")); |
444 | dev->stats.rx_dropped++; | 452 | dev->stats.rx_dropped++; |
445 | sbus_dma_sync_single_for_device(mp->myri_sdev, | 453 | dma_sync_single_for_device(&mp->myri_op->dev, |
446 | sbus_readl(&rxd->myri_scatters[0].addr), | 454 | sbus_readl(&rxd->myri_scatters[0].addr), |
447 | RX_ALLOC_SIZE, | 455 | RX_ALLOC_SIZE, |
448 | SBUS_DMA_FROMDEVICE); | 456 | DMA_FROM_DEVICE); |
449 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); | 457 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); |
450 | sbus_writel(index, &rxd->ctx); | 458 | sbus_writel(index, &rxd->ctx); |
451 | sbus_writel(1, &rxd->num_sg); | 459 | sbus_writel(1, &rxd->num_sg); |
@@ -464,17 +472,17 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev) | |||
464 | DRX(("skb_alloc(FAILED) ")); | 472 | DRX(("skb_alloc(FAILED) ")); |
465 | goto drop_it; | 473 | goto drop_it; |
466 | } | 474 | } |
467 | sbus_unmap_single(mp->myri_sdev, | 475 | dma_unmap_single(&mp->myri_op->dev, |
468 | sbus_readl(&rxd->myri_scatters[0].addr), | 476 | sbus_readl(&rxd->myri_scatters[0].addr), |
469 | RX_ALLOC_SIZE, | 477 | RX_ALLOC_SIZE, |
470 | SBUS_DMA_FROMDEVICE); | 478 | DMA_FROM_DEVICE); |
471 | mp->rx_skbs[index] = new_skb; | 479 | mp->rx_skbs[index] = new_skb; |
472 | new_skb->dev = dev; | 480 | new_skb->dev = dev; |
473 | skb_put(new_skb, RX_ALLOC_SIZE); | 481 | skb_put(new_skb, RX_ALLOC_SIZE); |
474 | dma_addr = sbus_map_single(mp->myri_sdev, | 482 | dma_addr = dma_map_single(&mp->myri_op->dev, |
475 | new_skb->data, | 483 | new_skb->data, |
476 | RX_ALLOC_SIZE, | 484 | RX_ALLOC_SIZE, |
477 | SBUS_DMA_FROMDEVICE); | 485 | DMA_FROM_DEVICE); |
478 | sbus_writel(dma_addr, &rxd->myri_scatters[0].addr); | 486 | sbus_writel(dma_addr, &rxd->myri_scatters[0].addr); |
479 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); | 487 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); |
480 | sbus_writel(index, &rxd->ctx); | 488 | sbus_writel(index, &rxd->ctx); |
@@ -500,10 +508,10 @@ static void myri_rx(struct myri_eth *mp, struct net_device *dev) | |||
500 | 508 | ||
501 | /* Reuse original ring buffer. */ | 509 | /* Reuse original ring buffer. */ |
502 | DRX(("reuse ")); | 510 | DRX(("reuse ")); |
503 | sbus_dma_sync_single_for_device(mp->myri_sdev, | 511 | dma_sync_single_for_device(&mp->myri_op->dev, |
504 | sbus_readl(&rxd->myri_scatters[0].addr), | 512 | sbus_readl(&rxd->myri_scatters[0].addr), |
505 | RX_ALLOC_SIZE, | 513 | RX_ALLOC_SIZE, |
506 | SBUS_DMA_FROMDEVICE); | 514 | DMA_FROM_DEVICE); |
507 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); | 515 | sbus_writel(RX_ALLOC_SIZE, &rxd->myri_scatters[0].len); |
508 | sbus_writel(index, &rxd->ctx); | 516 | sbus_writel(index, &rxd->ctx); |
509 | sbus_writel(1, &rxd->num_sg); | 517 | sbus_writel(1, &rxd->num_sg); |
@@ -652,7 +660,8 @@ static int myri_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
652 | sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]); | 660 | sbus_writew((skb->data[4] << 8) | skb->data[5], &txd->addr[3]); |
653 | } | 661 | } |
654 | 662 | ||
655 | dma_addr = sbus_map_single(mp->myri_sdev, skb->data, len, SBUS_DMA_TODEVICE); | 663 | dma_addr = dma_map_single(&mp->myri_op->dev, skb->data, |
664 | len, DMA_TO_DEVICE); | ||
656 | sbus_writel(dma_addr, &txd->myri_gathers[0].addr); | 665 | sbus_writel(dma_addr, &txd->myri_gathers[0].addr); |
657 | sbus_writel(len, &txd->myri_gathers[0].len); | 666 | sbus_writel(len, &txd->myri_gathers[0].len); |
658 | sbus_writel(1, &txd->num_sg); | 667 | sbus_writel(1, &txd->num_sg); |
@@ -891,30 +900,30 @@ static const struct header_ops myri_header_ops = { | |||
891 | .cache_update = myri_header_cache_update, | 900 | .cache_update = myri_header_cache_update, |
892 | }; | 901 | }; |
893 | 902 | ||
894 | static int __devinit myri_ether_init(struct sbus_dev *sdev) | 903 | static int __devinit myri_sbus_probe(struct of_device *op, const struct of_device_id *match) |
895 | { | 904 | { |
896 | static int num; | 905 | struct device_node *dp = op->node; |
897 | static unsigned version_printed; | 906 | static unsigned version_printed; |
898 | struct net_device *dev; | 907 | struct net_device *dev; |
899 | struct myri_eth *mp; | ||
900 | unsigned char prop_buf[32]; | ||
901 | int i; | ||
902 | DECLARE_MAC_BUF(mac); | 908 | DECLARE_MAC_BUF(mac); |
909 | struct myri_eth *mp; | ||
910 | const void *prop; | ||
911 | static int num; | ||
912 | int i, len; | ||
903 | 913 | ||
904 | DET(("myri_ether_init(%p,%d):\n", sdev, num)); | 914 | DET(("myri_ether_init(%p,%d):\n", op, num)); |
905 | dev = alloc_etherdev(sizeof(struct myri_eth)); | 915 | dev = alloc_etherdev(sizeof(struct myri_eth)); |
906 | |||
907 | if (!dev) | 916 | if (!dev) |
908 | return -ENOMEM; | 917 | return -ENOMEM; |
909 | 918 | ||
910 | if (version_printed++ == 0) | 919 | if (version_printed++ == 0) |
911 | printk(version); | 920 | printk(version); |
912 | 921 | ||
913 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | 922 | SET_NETDEV_DEV(dev, &op->dev); |
914 | 923 | ||
915 | mp = (struct myri_eth *) dev->priv; | 924 | mp = netdev_priv(dev); |
916 | spin_lock_init(&mp->irq_lock); | 925 | spin_lock_init(&mp->irq_lock); |
917 | mp->myri_sdev = sdev; | 926 | mp->myri_op = op; |
918 | 927 | ||
919 | /* Clean out skb arrays. */ | 928 | /* Clean out skb arrays. */ |
920 | for (i = 0; i < (RX_RING_SIZE + 1); i++) | 929 | for (i = 0; i < (RX_RING_SIZE + 1); i++) |
@@ -924,55 +933,44 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
924 | mp->tx_skbs[i] = NULL; | 933 | mp->tx_skbs[i] = NULL; |
925 | 934 | ||
926 | /* First check for EEPROM information. */ | 935 | /* First check for EEPROM information. */ |
927 | i = prom_getproperty(sdev->prom_node, "myrinet-eeprom-info", | 936 | prop = of_get_property(dp, "myrinet-eeprom-info", &len); |
928 | (char *)&mp->eeprom, sizeof(struct myri_eeprom)); | 937 | |
929 | DET(("prom_getprop(myrinet-eeprom-info) returns %d\n", i)); | 938 | if (prop) |
930 | if (i == 0 || i == -1) { | 939 | memcpy(&mp->eeprom, prop, sizeof(struct myri_eeprom)); |
940 | if (!prop) { | ||
931 | /* No eeprom property, must cook up the values ourselves. */ | 941 | /* No eeprom property, must cook up the values ourselves. */ |
932 | DET(("No EEPROM: ")); | 942 | DET(("No EEPROM: ")); |
933 | mp->eeprom.bus_type = BUS_TYPE_SBUS; | 943 | mp->eeprom.bus_type = BUS_TYPE_SBUS; |
934 | mp->eeprom.cpuvers = prom_getintdefault(sdev->prom_node,"cpu_version",0); | 944 | mp->eeprom.cpuvers = |
935 | mp->eeprom.cval = prom_getintdefault(sdev->prom_node,"clock_value",0); | 945 | of_getintprop_default(dp, "cpu_version", 0); |
936 | mp->eeprom.ramsz = prom_getintdefault(sdev->prom_node,"sram_size",0); | 946 | mp->eeprom.cval = |
937 | DET(("cpuvers[%d] cval[%d] ramsz[%d]\n", mp->eeprom.cpuvers, | 947 | of_getintprop_default(dp, "clock_value", 0); |
938 | mp->eeprom.cval, mp->eeprom.ramsz)); | 948 | mp->eeprom.ramsz = of_getintprop_default(dp, "sram_size", 0); |
939 | if (mp->eeprom.cpuvers == 0) { | 949 | if (!mp->eeprom.cpuvers) |
940 | DET(("EEPROM: cpuvers was zero, setting to %04x\n",CPUVERS_2_3)); | ||
941 | mp->eeprom.cpuvers = CPUVERS_2_3; | 950 | mp->eeprom.cpuvers = CPUVERS_2_3; |
942 | } | 951 | if (mp->eeprom.cpuvers < CPUVERS_3_0) |
943 | if (mp->eeprom.cpuvers < CPUVERS_3_0) { | ||
944 | DET(("EEPROM: cpuvers < CPUVERS_3_0, clockval set to zero.\n")); | ||
945 | mp->eeprom.cval = 0; | 952 | mp->eeprom.cval = 0; |
946 | } | 953 | if (!mp->eeprom.ramsz) |
947 | if (mp->eeprom.ramsz == 0) { | ||
948 | DET(("EEPROM: ramsz == 0, setting to 128k\n")); | ||
949 | mp->eeprom.ramsz = (128 * 1024); | 954 | mp->eeprom.ramsz = (128 * 1024); |
950 | } | 955 | |
951 | i = prom_getproperty(sdev->prom_node, "myrinet-board-id", | 956 | prop = of_get_property(dp, "myrinet-board-id", &len); |
952 | &prop_buf[0], 10); | 957 | if (prop) |
953 | DET(("EEPROM: prom_getprop(myrinet-board-id) returns %d\n", i)); | 958 | memcpy(&mp->eeprom.id[0], prop, 6); |
954 | if ((i != 0) && (i != -1)) | ||
955 | memcpy(&mp->eeprom.id[0], &prop_buf[0], 6); | ||
956 | else | 959 | else |
957 | set_boardid_from_idprom(mp, num); | 960 | set_boardid_from_idprom(mp, num); |
958 | i = prom_getproperty(sdev->prom_node, "fpga_version", | 961 | |
959 | &mp->eeprom.fvers[0], 32); | 962 | prop = of_get_property(dp, "fpga_version", &len); |
960 | DET(("EEPROM: prom_getprop(fpga_version) returns %d\n", i)); | 963 | if (prop) |
961 | if (i == 0 || i == -1) | 964 | memcpy(&mp->eeprom.fvers[0], prop, 32); |
965 | else | ||
962 | memset(&mp->eeprom.fvers[0], 0, 32); | 966 | memset(&mp->eeprom.fvers[0], 0, 32); |
963 | 967 | ||
964 | if (mp->eeprom.cpuvers == CPUVERS_4_1) { | 968 | if (mp->eeprom.cpuvers == CPUVERS_4_1) { |
965 | DET(("EEPROM: cpuvers CPUVERS_4_1, ")); | 969 | if (mp->eeprom.ramsz == (128 * 1024)) |
966 | if (mp->eeprom.ramsz == (128 * 1024)) { | ||
967 | DET(("ramsize 128k, setting to 256k, ")); | ||
968 | mp->eeprom.ramsz = (256 * 1024); | 970 | mp->eeprom.ramsz = (256 * 1024); |
969 | } | 971 | if ((mp->eeprom.cval == 0x40414041) || |
970 | if ((mp->eeprom.cval==0x40414041)||(mp->eeprom.cval==0x90449044)){ | 972 | (mp->eeprom.cval == 0x90449044)) |
971 | DET(("changing cval from %08x to %08x ", | ||
972 | mp->eeprom.cval, 0x50e450e4)); | ||
973 | mp->eeprom.cval = 0x50e450e4; | 973 | mp->eeprom.cval = 0x50e450e4; |
974 | } | ||
975 | DET(("\n")); | ||
976 | } | 974 | } |
977 | } | 975 | } |
978 | #ifdef DEBUG_DETECT | 976 | #ifdef DEBUG_DETECT |
@@ -991,8 +989,8 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
991 | * XXX only a valid version for PCI cards? Ask feldy... | 989 | * XXX only a valid version for PCI cards? Ask feldy... |
992 | */ | 990 | */ |
993 | DET(("Mapping regs for cpuvers < CPUVERS_4_0\n")); | 991 | DET(("Mapping regs for cpuvers < CPUVERS_4_0\n")); |
994 | mp->regs = sbus_ioremap(&sdev->resource[0], 0, | 992 | mp->regs = of_ioremap(&op->resource[0], 0, |
995 | mp->reg_size, "MyriCOM Regs"); | 993 | mp->reg_size, "MyriCOM Regs"); |
996 | if (!mp->regs) { | 994 | if (!mp->regs) { |
997 | printk("MyriCOM: Cannot map MyriCOM registers.\n"); | 995 | printk("MyriCOM: Cannot map MyriCOM registers.\n"); |
998 | goto err; | 996 | goto err; |
@@ -1001,13 +999,12 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
1001 | mp->lregs = mp->lanai + (0x10000 * 2); | 999 | mp->lregs = mp->lanai + (0x10000 * 2); |
1002 | } else { | 1000 | } else { |
1003 | DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n")); | 1001 | DET(("Mapping regs for cpuvers >= CPUVERS_4_0\n")); |
1004 | mp->cregs = sbus_ioremap(&sdev->resource[0], 0, | 1002 | mp->cregs = of_ioremap(&op->resource[0], 0, |
1005 | PAGE_SIZE, "MyriCOM Control Regs"); | 1003 | PAGE_SIZE, "MyriCOM Control Regs"); |
1006 | mp->lregs = sbus_ioremap(&sdev->resource[0], (256 * 1024), | 1004 | mp->lregs = of_ioremap(&op->resource[0], (256 * 1024), |
1007 | PAGE_SIZE, "MyriCOM LANAI Regs"); | 1005 | PAGE_SIZE, "MyriCOM LANAI Regs"); |
1008 | mp->lanai = | 1006 | mp->lanai = of_ioremap(&op->resource[0], (512 * 1024), |
1009 | sbus_ioremap(&sdev->resource[0], (512 * 1024), | 1007 | mp->eeprom.ramsz, "MyriCOM SRAM"); |
1010 | mp->eeprom.ramsz, "MyriCOM SRAM"); | ||
1011 | } | 1008 | } |
1012 | DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n", | 1009 | DET(("Registers mapped: cregs[%p] lregs[%p] lanai[%p]\n", |
1013 | mp->cregs, mp->lregs, mp->lanai)); | 1010 | mp->cregs, mp->lregs, mp->lanai)); |
@@ -1039,16 +1036,15 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
1039 | myri_reset_on(mp->cregs); | 1036 | myri_reset_on(mp->cregs); |
1040 | 1037 | ||
1041 | /* Get the supported DVMA burst sizes from our SBUS. */ | 1038 | /* Get the supported DVMA burst sizes from our SBUS. */ |
1042 | mp->myri_bursts = prom_getintdefault(mp->myri_sdev->bus->prom_node, | 1039 | mp->myri_bursts = of_getintprop_default(dp->parent, |
1043 | "burst-sizes", 0x00); | 1040 | "burst-sizes", 0x00); |
1044 | 1041 | if (!sbus_can_burst64()) | |
1045 | if (!sbus_can_burst64(sdev)) | ||
1046 | mp->myri_bursts &= ~(DMA_BURST64); | 1042 | mp->myri_bursts &= ~(DMA_BURST64); |
1047 | 1043 | ||
1048 | DET(("MYRI bursts %02x\n", mp->myri_bursts)); | 1044 | DET(("MYRI bursts %02x\n", mp->myri_bursts)); |
1049 | 1045 | ||
1050 | /* Encode SBUS interrupt level in second control register. */ | 1046 | /* Encode SBUS interrupt level in second control register. */ |
1051 | i = prom_getint(sdev->prom_node, "interrupts"); | 1047 | i = of_getintprop_default(dp, "interrupts", 0); |
1052 | if (i == 0) | 1048 | if (i == 0) |
1053 | i = 4; | 1049 | i = 4; |
1054 | DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n", | 1050 | DET(("prom_getint(interrupts)==%d, irqlvl set to %04x\n", |
@@ -1063,7 +1059,7 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
1063 | dev->tx_timeout = &myri_tx_timeout; | 1059 | dev->tx_timeout = &myri_tx_timeout; |
1064 | dev->watchdog_timeo = 5*HZ; | 1060 | dev->watchdog_timeo = 5*HZ; |
1065 | dev->set_multicast_list = &myri_set_multicast; | 1061 | dev->set_multicast_list = &myri_set_multicast; |
1066 | dev->irq = sdev->irqs[0]; | 1062 | dev->irq = op->irqs[0]; |
1067 | 1063 | ||
1068 | /* Register interrupt handler now. */ | 1064 | /* Register interrupt handler now. */ |
1069 | DET(("Requesting MYRIcom IRQ line.\n")); | 1065 | DET(("Requesting MYRIcom IRQ line.\n")); |
@@ -1088,7 +1084,7 @@ static int __devinit myri_ether_init(struct sbus_dev *sdev) | |||
1088 | goto err_free_irq; | 1084 | goto err_free_irq; |
1089 | } | 1085 | } |
1090 | 1086 | ||
1091 | dev_set_drvdata(&sdev->ofdev.dev, mp); | 1087 | dev_set_drvdata(&op->dev, mp); |
1092 | 1088 | ||
1093 | num++; | 1089 | num++; |
1094 | 1090 | ||
@@ -1105,17 +1101,9 @@ err: | |||
1105 | return -ENODEV; | 1101 | return -ENODEV; |
1106 | } | 1102 | } |
1107 | 1103 | ||
1108 | 1104 | static int __devexit myri_sbus_remove(struct of_device *op) | |
1109 | static int __devinit myri_sbus_probe(struct of_device *dev, const struct of_device_id *match) | ||
1110 | { | ||
1111 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
1112 | |||
1113 | return myri_ether_init(sdev); | ||
1114 | } | ||
1115 | |||
1116 | static int __devexit myri_sbus_remove(struct of_device *dev) | ||
1117 | { | 1105 | { |
1118 | struct myri_eth *mp = dev_get_drvdata(&dev->dev); | 1106 | struct myri_eth *mp = dev_get_drvdata(&op->dev); |
1119 | struct net_device *net_dev = mp->dev; | 1107 | struct net_device *net_dev = mp->dev; |
1120 | 1108 | ||
1121 | unregister_netdev(net_dev); | 1109 | unregister_netdev(net_dev); |
@@ -1123,21 +1111,21 @@ static int __devexit myri_sbus_remove(struct of_device *dev) | |||
1123 | free_irq(net_dev->irq, net_dev); | 1111 | free_irq(net_dev->irq, net_dev); |
1124 | 1112 | ||
1125 | if (mp->eeprom.cpuvers < CPUVERS_4_0) { | 1113 | if (mp->eeprom.cpuvers < CPUVERS_4_0) { |
1126 | sbus_iounmap(mp->regs, mp->reg_size); | 1114 | of_iounmap(&op->resource[0], mp->regs, mp->reg_size); |
1127 | } else { | 1115 | } else { |
1128 | sbus_iounmap(mp->cregs, PAGE_SIZE); | 1116 | of_iounmap(&op->resource[0], mp->cregs, PAGE_SIZE); |
1129 | sbus_iounmap(mp->lregs, (256 * 1024)); | 1117 | of_iounmap(&op->resource[0], mp->lregs, (256 * 1024)); |
1130 | sbus_iounmap(mp->lanai, (512 * 1024)); | 1118 | of_iounmap(&op->resource[0], mp->lanai, (512 * 1024)); |
1131 | } | 1119 | } |
1132 | 1120 | ||
1133 | free_netdev(net_dev); | 1121 | free_netdev(net_dev); |
1134 | 1122 | ||
1135 | dev_set_drvdata(&dev->dev, NULL); | 1123 | dev_set_drvdata(&op->dev, NULL); |
1136 | 1124 | ||
1137 | return 0; | 1125 | return 0; |
1138 | } | 1126 | } |
1139 | 1127 | ||
1140 | static struct of_device_id myri_sbus_match[] = { | 1128 | static const struct of_device_id myri_sbus_match[] = { |
1141 | { | 1129 | { |
1142 | .name = "MYRICOM,mlanai", | 1130 | .name = "MYRICOM,mlanai", |
1143 | }, | 1131 | }, |
@@ -1158,7 +1146,7 @@ static struct of_platform_driver myri_sbus_driver = { | |||
1158 | 1146 | ||
1159 | static int __init myri_sbus_init(void) | 1147 | static int __init myri_sbus_init(void) |
1160 | { | 1148 | { |
1161 | return of_register_driver(&myri_sbus_driver, &sbus_bus_type); | 1149 | return of_register_driver(&myri_sbus_driver, &of_bus_type); |
1162 | } | 1150 | } |
1163 | 1151 | ||
1164 | static void __exit myri_sbus_exit(void) | 1152 | static void __exit myri_sbus_exit(void) |
diff --git a/drivers/net/myri_sbus.h b/drivers/net/myri_sbus.h index 5d93fcc95d55..ff363e95d9cf 100644 --- a/drivers/net/myri_sbus.h +++ b/drivers/net/myri_sbus.h | |||
@@ -288,7 +288,7 @@ struct myri_eth { | |||
288 | struct myri_eeprom eeprom; /* Local copy of EEPROM. */ | 288 | struct myri_eeprom eeprom; /* Local copy of EEPROM. */ |
289 | unsigned int reg_size; /* Size of register space. */ | 289 | unsigned int reg_size; /* Size of register space. */ |
290 | unsigned int shmem_base; /* Offset to shared ram. */ | 290 | unsigned int shmem_base; /* Offset to shared ram. */ |
291 | struct sbus_dev *myri_sdev; /* Our SBUS device struct. */ | 291 | struct of_device *myri_op; /* Our OF device struct. */ |
292 | }; | 292 | }; |
293 | 293 | ||
294 | /* We use this to acquire receive skb's that we can DMA directly into. */ | 294 | /* We use this to acquire receive skb's that we can DMA directly into. */ |
diff --git a/drivers/net/niu.c b/drivers/net/niu.c index e3be81eba8a4..ebc812702903 100644 --- a/drivers/net/niu.c +++ b/drivers/net/niu.c | |||
@@ -9130,7 +9130,7 @@ static int __devexit niu_of_remove(struct of_device *op) | |||
9130 | return 0; | 9130 | return 0; |
9131 | } | 9131 | } |
9132 | 9132 | ||
9133 | static struct of_device_id niu_match[] = { | 9133 | static const struct of_device_id niu_match[] = { |
9134 | { | 9134 | { |
9135 | .name = "network", | 9135 | .name = "network", |
9136 | .compatible = "SUNW,niusl", | 9136 | .compatible = "SUNW,niusl", |
diff --git a/drivers/net/smc911x.c b/drivers/net/smc911x.c index 02cc064c2c8b..3d19d00e8eec 100644 --- a/drivers/net/smc911x.c +++ b/drivers/net/smc911x.c | |||
@@ -722,6 +722,9 @@ static void smc911x_phy_detect(struct net_device *dev) | |||
722 | break; | 722 | break; |
723 | } | 723 | } |
724 | } | 724 | } |
725 | if (phyaddr < 32) | ||
726 | /* Found an external PHY */ | ||
727 | break; | ||
725 | } | 728 | } |
726 | default: | 729 | default: |
727 | /* Internal media only */ | 730 | /* Internal media only */ |
diff --git a/drivers/net/sunbmac.c b/drivers/net/sunbmac.c index 31e7384e312a..018d0fca9422 100644 --- a/drivers/net/sunbmac.c +++ b/drivers/net/sunbmac.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* $Id: sunbmac.c,v 1.30 2002/01/15 06:48:55 davem Exp $ | 1 | /* sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters. |
2 | * sunbmac.c: Driver for Sparc BigMAC 100baseT ethernet adapters. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1997, 1998, 1999, 2003 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 1997, 1998, 1999, 2003, 2008 David S. Miller (davem@davemloft.net) |
5 | */ | 4 | */ |
6 | 5 | ||
7 | #include <linux/module.h> | 6 | #include <linux/module.h> |
@@ -23,6 +22,9 @@ | |||
23 | #include <linux/etherdevice.h> | 22 | #include <linux/etherdevice.h> |
24 | #include <linux/skbuff.h> | 23 | #include <linux/skbuff.h> |
25 | #include <linux/bitops.h> | 24 | #include <linux/bitops.h> |
25 | #include <linux/dma-mapping.h> | ||
26 | #include <linux/of.h> | ||
27 | #include <linux/of_device.h> | ||
26 | 28 | ||
27 | #include <asm/auxio.h> | 29 | #include <asm/auxio.h> |
28 | #include <asm/byteorder.h> | 30 | #include <asm/byteorder.h> |
@@ -32,15 +34,14 @@ | |||
32 | #include <asm/openprom.h> | 34 | #include <asm/openprom.h> |
33 | #include <asm/oplib.h> | 35 | #include <asm/oplib.h> |
34 | #include <asm/pgtable.h> | 36 | #include <asm/pgtable.h> |
35 | #include <asm/sbus.h> | ||
36 | #include <asm/system.h> | 37 | #include <asm/system.h> |
37 | 38 | ||
38 | #include "sunbmac.h" | 39 | #include "sunbmac.h" |
39 | 40 | ||
40 | #define DRV_NAME "sunbmac" | 41 | #define DRV_NAME "sunbmac" |
41 | #define DRV_VERSION "2.0" | 42 | #define DRV_VERSION "2.1" |
42 | #define DRV_RELDATE "11/24/03" | 43 | #define DRV_RELDATE "August 26, 2008" |
43 | #define DRV_AUTHOR "David S. Miller (davem@redhat.com)" | 44 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" |
44 | 45 | ||
45 | static char version[] = | 46 | static char version[] = |
46 | DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; | 47 | DRV_NAME ".c:v" DRV_VERSION " " DRV_RELDATE " " DRV_AUTHOR "\n"; |
@@ -96,8 +97,8 @@ static int qec_global_reset(void __iomem *gregs) | |||
96 | 97 | ||
97 | static void qec_init(struct bigmac *bp) | 98 | static void qec_init(struct bigmac *bp) |
98 | { | 99 | { |
100 | struct of_device *qec_op = bp->qec_op; | ||
99 | void __iomem *gregs = bp->gregs; | 101 | void __iomem *gregs = bp->gregs; |
100 | struct sbus_dev *qec_sdev = bp->qec_sdev; | ||
101 | u8 bsizes = bp->bigmac_bursts; | 102 | u8 bsizes = bp->bigmac_bursts; |
102 | u32 regval; | 103 | u32 regval; |
103 | 104 | ||
@@ -112,13 +113,13 @@ static void qec_init(struct bigmac *bp) | |||
112 | sbus_writel(GLOB_PSIZE_2048, gregs + GLOB_PSIZE); | 113 | sbus_writel(GLOB_PSIZE_2048, gregs + GLOB_PSIZE); |
113 | 114 | ||
114 | /* All of memsize is given to bigmac. */ | 115 | /* All of memsize is given to bigmac. */ |
115 | sbus_writel(qec_sdev->reg_addrs[1].reg_size, | 116 | sbus_writel(resource_size(&qec_op->resource[1]), |
116 | gregs + GLOB_MSIZE); | 117 | gregs + GLOB_MSIZE); |
117 | 118 | ||
118 | /* Half to the transmitter, half to the receiver. */ | 119 | /* Half to the transmitter, half to the receiver. */ |
119 | sbus_writel(qec_sdev->reg_addrs[1].reg_size >> 1, | 120 | sbus_writel(resource_size(&qec_op->resource[1]) >> 1, |
120 | gregs + GLOB_TSIZE); | 121 | gregs + GLOB_TSIZE); |
121 | sbus_writel(qec_sdev->reg_addrs[1].reg_size >> 1, | 122 | sbus_writel(resource_size(&qec_op->resource[1]) >> 1, |
122 | gregs + GLOB_RSIZE); | 123 | gregs + GLOB_RSIZE); |
123 | } | 124 | } |
124 | 125 | ||
@@ -239,9 +240,10 @@ static void bigmac_init_rings(struct bigmac *bp, int from_irq) | |||
239 | skb_reserve(skb, 34); | 240 | skb_reserve(skb, 34); |
240 | 241 | ||
241 | bb->be_rxd[i].rx_addr = | 242 | bb->be_rxd[i].rx_addr = |
242 | sbus_map_single(bp->bigmac_sdev, skb->data, | 243 | dma_map_single(&bp->bigmac_op->dev, |
243 | RX_BUF_ALLOC_SIZE - 34, | 244 | skb->data, |
244 | SBUS_DMA_FROMDEVICE); | 245 | RX_BUF_ALLOC_SIZE - 34, |
246 | DMA_FROM_DEVICE); | ||
245 | bb->be_rxd[i].rx_flags = | 247 | bb->be_rxd[i].rx_flags = |
246 | (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); | 248 | (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); |
247 | } | 249 | } |
@@ -776,9 +778,9 @@ static void bigmac_tx(struct bigmac *bp) | |||
776 | skb = bp->tx_skbs[elem]; | 778 | skb = bp->tx_skbs[elem]; |
777 | bp->enet_stats.tx_packets++; | 779 | bp->enet_stats.tx_packets++; |
778 | bp->enet_stats.tx_bytes += skb->len; | 780 | bp->enet_stats.tx_bytes += skb->len; |
779 | sbus_unmap_single(bp->bigmac_sdev, | 781 | dma_unmap_single(&bp->bigmac_op->dev, |
780 | this->tx_addr, skb->len, | 782 | this->tx_addr, skb->len, |
781 | SBUS_DMA_TODEVICE); | 783 | DMA_TO_DEVICE); |
782 | 784 | ||
783 | DTX(("skb(%p) ", skb)); | 785 | DTX(("skb(%p) ", skb)); |
784 | bp->tx_skbs[elem] = NULL; | 786 | bp->tx_skbs[elem] = NULL; |
@@ -831,18 +833,19 @@ static void bigmac_rx(struct bigmac *bp) | |||
831 | drops++; | 833 | drops++; |
832 | goto drop_it; | 834 | goto drop_it; |
833 | } | 835 | } |
834 | sbus_unmap_single(bp->bigmac_sdev, | 836 | dma_unmap_single(&bp->bigmac_op->dev, |
835 | this->rx_addr, | 837 | this->rx_addr, |
836 | RX_BUF_ALLOC_SIZE - 34, | 838 | RX_BUF_ALLOC_SIZE - 34, |
837 | SBUS_DMA_FROMDEVICE); | 839 | DMA_FROM_DEVICE); |
838 | bp->rx_skbs[elem] = new_skb; | 840 | bp->rx_skbs[elem] = new_skb; |
839 | new_skb->dev = bp->dev; | 841 | new_skb->dev = bp->dev; |
840 | skb_put(new_skb, ETH_FRAME_LEN); | 842 | skb_put(new_skb, ETH_FRAME_LEN); |
841 | skb_reserve(new_skb, 34); | 843 | skb_reserve(new_skb, 34); |
842 | this->rx_addr = sbus_map_single(bp->bigmac_sdev, | 844 | this->rx_addr = |
843 | new_skb->data, | 845 | dma_map_single(&bp->bigmac_op->dev, |
844 | RX_BUF_ALLOC_SIZE - 34, | 846 | new_skb->data, |
845 | SBUS_DMA_FROMDEVICE); | 847 | RX_BUF_ALLOC_SIZE - 34, |
848 | DMA_FROM_DEVICE); | ||
846 | this->rx_flags = | 849 | this->rx_flags = |
847 | (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); | 850 | (RXD_OWN | ((RX_BUF_ALLOC_SIZE - 34) & RXD_LENGTH)); |
848 | 851 | ||
@@ -857,13 +860,13 @@ static void bigmac_rx(struct bigmac *bp) | |||
857 | } | 860 | } |
858 | skb_reserve(copy_skb, 2); | 861 | skb_reserve(copy_skb, 2); |
859 | skb_put(copy_skb, len); | 862 | skb_put(copy_skb, len); |
860 | sbus_dma_sync_single_for_cpu(bp->bigmac_sdev, | 863 | dma_sync_single_for_cpu(&bp->bigmac_op->dev, |
861 | this->rx_addr, len, | 864 | this->rx_addr, len, |
862 | SBUS_DMA_FROMDEVICE); | 865 | DMA_FROM_DEVICE); |
863 | skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len); | 866 | skb_copy_to_linear_data(copy_skb, (unsigned char *)skb->data, len); |
864 | sbus_dma_sync_single_for_device(bp->bigmac_sdev, | 867 | dma_sync_single_for_device(&bp->bigmac_op->dev, |
865 | this->rx_addr, len, | 868 | this->rx_addr, len, |
866 | SBUS_DMA_FROMDEVICE); | 869 | DMA_FROM_DEVICE); |
867 | 870 | ||
868 | /* Reuse original ring buffer. */ | 871 | /* Reuse original ring buffer. */ |
869 | this->rx_flags = | 872 | this->rx_flags = |
@@ -959,7 +962,8 @@ static int bigmac_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
959 | u32 mapping; | 962 | u32 mapping; |
960 | 963 | ||
961 | len = skb->len; | 964 | len = skb->len; |
962 | mapping = sbus_map_single(bp->bigmac_sdev, skb->data, len, SBUS_DMA_TODEVICE); | 965 | mapping = dma_map_single(&bp->bigmac_op->dev, skb->data, |
966 | len, DMA_TO_DEVICE); | ||
963 | 967 | ||
964 | /* Avoid a race... */ | 968 | /* Avoid a race... */ |
965 | spin_lock_irq(&bp->lock); | 969 | spin_lock_irq(&bp->lock); |
@@ -1051,12 +1055,8 @@ static void bigmac_set_multicast(struct net_device *dev) | |||
1051 | /* Ethtool support... */ | 1055 | /* Ethtool support... */ |
1052 | static void bigmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | 1056 | static void bigmac_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) |
1053 | { | 1057 | { |
1054 | struct bigmac *bp = dev->priv; | ||
1055 | |||
1056 | strcpy(info->driver, "sunbmac"); | 1058 | strcpy(info->driver, "sunbmac"); |
1057 | strcpy(info->version, "2.0"); | 1059 | strcpy(info->version, "2.0"); |
1058 | sprintf(info->bus_info, "SBUS:%d", | ||
1059 | bp->qec_sdev->slot); | ||
1060 | } | 1060 | } |
1061 | 1061 | ||
1062 | static u32 bigmac_get_link(struct net_device *dev) | 1062 | static u32 bigmac_get_link(struct net_device *dev) |
@@ -1075,14 +1075,15 @@ static const struct ethtool_ops bigmac_ethtool_ops = { | |||
1075 | .get_link = bigmac_get_link, | 1075 | .get_link = bigmac_get_link, |
1076 | }; | 1076 | }; |
1077 | 1077 | ||
1078 | static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | 1078 | static int __devinit bigmac_ether_init(struct of_device *op, |
1079 | struct of_device *qec_op) | ||
1079 | { | 1080 | { |
1080 | struct net_device *dev; | ||
1081 | static int version_printed; | 1081 | static int version_printed; |
1082 | struct bigmac *bp; | 1082 | struct net_device *dev; |
1083 | u8 bsizes, bsizes_more; | 1083 | u8 bsizes, bsizes_more; |
1084 | int i; | ||
1085 | DECLARE_MAC_BUF(mac); | 1084 | DECLARE_MAC_BUF(mac); |
1085 | struct bigmac *bp; | ||
1086 | int i; | ||
1086 | 1087 | ||
1087 | /* Get a new device struct for this interface. */ | 1088 | /* Get a new device struct for this interface. */ |
1088 | dev = alloc_etherdev(sizeof(struct bigmac)); | 1089 | dev = alloc_etherdev(sizeof(struct bigmac)); |
@@ -1092,32 +1093,21 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
1092 | if (version_printed++ == 0) | 1093 | if (version_printed++ == 0) |
1093 | printk(KERN_INFO "%s", version); | 1094 | printk(KERN_INFO "%s", version); |
1094 | 1095 | ||
1095 | dev->base_addr = (long) qec_sdev; | ||
1096 | for (i = 0; i < 6; i++) | 1096 | for (i = 0; i < 6; i++) |
1097 | dev->dev_addr[i] = idprom->id_ethaddr[i]; | 1097 | dev->dev_addr[i] = idprom->id_ethaddr[i]; |
1098 | 1098 | ||
1099 | /* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */ | 1099 | /* Setup softc, with backpointers to QEC and BigMAC SBUS device structs. */ |
1100 | bp = dev->priv; | 1100 | bp = netdev_priv(dev); |
1101 | bp->qec_sdev = qec_sdev; | 1101 | bp->qec_op = qec_op; |
1102 | bp->bigmac_sdev = qec_sdev->child; | 1102 | bp->bigmac_op = op; |
1103 | 1103 | ||
1104 | SET_NETDEV_DEV(dev, &bp->bigmac_sdev->ofdev.dev); | 1104 | SET_NETDEV_DEV(dev, &op->dev); |
1105 | 1105 | ||
1106 | spin_lock_init(&bp->lock); | 1106 | spin_lock_init(&bp->lock); |
1107 | 1107 | ||
1108 | /* Verify the registers we expect, are actually there. */ | ||
1109 | if ((bp->bigmac_sdev->num_registers != 3) || | ||
1110 | (bp->qec_sdev->num_registers != 2)) { | ||
1111 | printk(KERN_ERR "BIGMAC: Device does not have 2 and 3 regs, it has %d and %d.\n", | ||
1112 | bp->qec_sdev->num_registers, | ||
1113 | bp->bigmac_sdev->num_registers); | ||
1114 | printk(KERN_ERR "BIGMAC: Would you like that for here or to go?\n"); | ||
1115 | goto fail_and_cleanup; | ||
1116 | } | ||
1117 | |||
1118 | /* Map in QEC global control registers. */ | 1108 | /* Map in QEC global control registers. */ |
1119 | bp->gregs = sbus_ioremap(&bp->qec_sdev->resource[0], 0, | 1109 | bp->gregs = of_ioremap(&qec_op->resource[0], 0, |
1120 | GLOB_REG_SIZE, "BigMAC QEC GLobal Regs"); | 1110 | GLOB_REG_SIZE, "BigMAC QEC GLobal Regs"); |
1121 | if (!bp->gregs) { | 1111 | if (!bp->gregs) { |
1122 | printk(KERN_ERR "BIGMAC: Cannot map QEC global registers.\n"); | 1112 | printk(KERN_ERR "BIGMAC: Cannot map QEC global registers.\n"); |
1123 | goto fail_and_cleanup; | 1113 | goto fail_and_cleanup; |
@@ -1134,13 +1124,8 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
1134 | goto fail_and_cleanup; | 1124 | goto fail_and_cleanup; |
1135 | 1125 | ||
1136 | /* Get supported SBUS burst sizes. */ | 1126 | /* Get supported SBUS burst sizes. */ |
1137 | bsizes = prom_getintdefault(bp->qec_sdev->prom_node, | 1127 | bsizes = of_getintprop_default(qec_op->node, "burst-sizes", 0xff); |
1138 | "burst-sizes", | 1128 | bsizes_more = of_getintprop_default(qec_op->node, "burst-sizes", 0xff); |
1139 | 0xff); | ||
1140 | |||
1141 | bsizes_more = prom_getintdefault(bp->qec_sdev->bus->prom_node, | ||
1142 | "burst-sizes", | ||
1143 | 0xff); | ||
1144 | 1129 | ||
1145 | bsizes &= 0xff; | 1130 | bsizes &= 0xff; |
1146 | if (bsizes_more != 0xff) | 1131 | if (bsizes_more != 0xff) |
@@ -1154,16 +1139,16 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
1154 | qec_init(bp); | 1139 | qec_init(bp); |
1155 | 1140 | ||
1156 | /* Map in the BigMAC channel registers. */ | 1141 | /* Map in the BigMAC channel registers. */ |
1157 | bp->creg = sbus_ioremap(&bp->bigmac_sdev->resource[0], 0, | 1142 | bp->creg = of_ioremap(&op->resource[0], 0, |
1158 | CREG_REG_SIZE, "BigMAC QEC Channel Regs"); | 1143 | CREG_REG_SIZE, "BigMAC QEC Channel Regs"); |
1159 | if (!bp->creg) { | 1144 | if (!bp->creg) { |
1160 | printk(KERN_ERR "BIGMAC: Cannot map QEC channel registers.\n"); | 1145 | printk(KERN_ERR "BIGMAC: Cannot map QEC channel registers.\n"); |
1161 | goto fail_and_cleanup; | 1146 | goto fail_and_cleanup; |
1162 | } | 1147 | } |
1163 | 1148 | ||
1164 | /* Map in the BigMAC control registers. */ | 1149 | /* Map in the BigMAC control registers. */ |
1165 | bp->bregs = sbus_ioremap(&bp->bigmac_sdev->resource[1], 0, | 1150 | bp->bregs = of_ioremap(&op->resource[1], 0, |
1166 | BMAC_REG_SIZE, "BigMAC Primary Regs"); | 1151 | BMAC_REG_SIZE, "BigMAC Primary Regs"); |
1167 | if (!bp->bregs) { | 1152 | if (!bp->bregs) { |
1168 | printk(KERN_ERR "BIGMAC: Cannot map BigMAC primary registers.\n"); | 1153 | printk(KERN_ERR "BIGMAC: Cannot map BigMAC primary registers.\n"); |
1169 | goto fail_and_cleanup; | 1154 | goto fail_and_cleanup; |
@@ -1172,8 +1157,8 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
1172 | /* Map in the BigMAC transceiver registers, this is how you poke at | 1157 | /* Map in the BigMAC transceiver registers, this is how you poke at |
1173 | * the BigMAC's PHY. | 1158 | * the BigMAC's PHY. |
1174 | */ | 1159 | */ |
1175 | bp->tregs = sbus_ioremap(&bp->bigmac_sdev->resource[2], 0, | 1160 | bp->tregs = of_ioremap(&op->resource[2], 0, |
1176 | TCVR_REG_SIZE, "BigMAC Transceiver Regs"); | 1161 | TCVR_REG_SIZE, "BigMAC Transceiver Regs"); |
1177 | if (!bp->tregs) { | 1162 | if (!bp->tregs) { |
1178 | printk(KERN_ERR "BIGMAC: Cannot map BigMAC transceiver registers.\n"); | 1163 | printk(KERN_ERR "BIGMAC: Cannot map BigMAC transceiver registers.\n"); |
1179 | goto fail_and_cleanup; | 1164 | goto fail_and_cleanup; |
@@ -1183,17 +1168,17 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
1183 | bigmac_stop(bp); | 1168 | bigmac_stop(bp); |
1184 | 1169 | ||
1185 | /* Allocate transmit/receive descriptor DVMA block. */ | 1170 | /* Allocate transmit/receive descriptor DVMA block. */ |
1186 | bp->bmac_block = sbus_alloc_consistent(bp->bigmac_sdev, | 1171 | bp->bmac_block = dma_alloc_coherent(&bp->bigmac_op->dev, |
1187 | PAGE_SIZE, | 1172 | PAGE_SIZE, |
1188 | &bp->bblock_dvma); | 1173 | &bp->bblock_dvma, GFP_ATOMIC); |
1189 | if (bp->bmac_block == NULL || bp->bblock_dvma == 0) { | 1174 | if (bp->bmac_block == NULL || bp->bblock_dvma == 0) { |
1190 | printk(KERN_ERR "BIGMAC: Cannot allocate consistent DMA.\n"); | 1175 | printk(KERN_ERR "BIGMAC: Cannot allocate consistent DMA.\n"); |
1191 | goto fail_and_cleanup; | 1176 | goto fail_and_cleanup; |
1192 | } | 1177 | } |
1193 | 1178 | ||
1194 | /* Get the board revision of this BigMAC. */ | 1179 | /* Get the board revision of this BigMAC. */ |
1195 | bp->board_rev = prom_getintdefault(bp->bigmac_sdev->prom_node, | 1180 | bp->board_rev = of_getintprop_default(bp->bigmac_op->node, |
1196 | "board-version", 1); | 1181 | "board-version", 1); |
1197 | 1182 | ||
1198 | /* Init auto-negotiation timer state. */ | 1183 | /* Init auto-negotiation timer state. */ |
1199 | init_timer(&bp->bigmac_timer); | 1184 | init_timer(&bp->bigmac_timer); |
@@ -1217,7 +1202,7 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
1217 | dev->watchdog_timeo = 5*HZ; | 1202 | dev->watchdog_timeo = 5*HZ; |
1218 | 1203 | ||
1219 | /* Finish net device registration. */ | 1204 | /* Finish net device registration. */ |
1220 | dev->irq = bp->bigmac_sdev->irqs[0]; | 1205 | dev->irq = bp->bigmac_op->irqs[0]; |
1221 | dev->dma = 0; | 1206 | dev->dma = 0; |
1222 | 1207 | ||
1223 | if (register_netdev(dev)) { | 1208 | if (register_netdev(dev)) { |
@@ -1225,7 +1210,7 @@ static int __devinit bigmac_ether_init(struct sbus_dev *qec_sdev) | |||
1225 | goto fail_and_cleanup; | 1210 | goto fail_and_cleanup; |
1226 | } | 1211 | } |
1227 | 1212 | ||
1228 | dev_set_drvdata(&bp->bigmac_sdev->ofdev.dev, bp); | 1213 | dev_set_drvdata(&bp->bigmac_op->dev, bp); |
1229 | 1214 | ||
1230 | printk(KERN_INFO "%s: BigMAC 100baseT Ethernet %s\n", | 1215 | printk(KERN_INFO "%s: BigMAC 100baseT Ethernet %s\n", |
1231 | dev->name, print_mac(mac, dev->dev_addr)); | 1216 | dev->name, print_mac(mac, dev->dev_addr)); |
@@ -1236,66 +1221,67 @@ fail_and_cleanup: | |||
1236 | /* Something went wrong, undo whatever we did so far. */ | 1221 | /* Something went wrong, undo whatever we did so far. */ |
1237 | /* Free register mappings if any. */ | 1222 | /* Free register mappings if any. */ |
1238 | if (bp->gregs) | 1223 | if (bp->gregs) |
1239 | sbus_iounmap(bp->gregs, GLOB_REG_SIZE); | 1224 | of_iounmap(&qec_op->resource[0], bp->gregs, GLOB_REG_SIZE); |
1240 | if (bp->creg) | 1225 | if (bp->creg) |
1241 | sbus_iounmap(bp->creg, CREG_REG_SIZE); | 1226 | of_iounmap(&op->resource[0], bp->creg, CREG_REG_SIZE); |
1242 | if (bp->bregs) | 1227 | if (bp->bregs) |
1243 | sbus_iounmap(bp->bregs, BMAC_REG_SIZE); | 1228 | of_iounmap(&op->resource[1], bp->bregs, BMAC_REG_SIZE); |
1244 | if (bp->tregs) | 1229 | if (bp->tregs) |
1245 | sbus_iounmap(bp->tregs, TCVR_REG_SIZE); | 1230 | of_iounmap(&op->resource[2], bp->tregs, TCVR_REG_SIZE); |
1246 | 1231 | ||
1247 | if (bp->bmac_block) | 1232 | if (bp->bmac_block) |
1248 | sbus_free_consistent(bp->bigmac_sdev, | 1233 | dma_free_coherent(&bp->bigmac_op->dev, |
1249 | PAGE_SIZE, | 1234 | PAGE_SIZE, |
1250 | bp->bmac_block, | 1235 | bp->bmac_block, |
1251 | bp->bblock_dvma); | 1236 | bp->bblock_dvma); |
1252 | 1237 | ||
1253 | /* This also frees the co-located 'dev->priv' */ | 1238 | /* This also frees the co-located 'dev->priv' */ |
1254 | free_netdev(dev); | 1239 | free_netdev(dev); |
1255 | return -ENODEV; | 1240 | return -ENODEV; |
1256 | } | 1241 | } |
1257 | 1242 | ||
1258 | /* QEC can be the parent of either QuadEthernet or | 1243 | /* QEC can be the parent of either QuadEthernet or a BigMAC. We want |
1259 | * a BigMAC. We want the latter. | 1244 | * the latter. |
1260 | */ | 1245 | */ |
1261 | static int __devinit bigmac_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 1246 | static int __devinit bigmac_sbus_probe(struct of_device *op, |
1247 | const struct of_device_id *match) | ||
1262 | { | 1248 | { |
1263 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | 1249 | struct device *parent = op->dev.parent; |
1264 | struct device_node *dp = dev->node; | 1250 | struct of_device *qec_op; |
1265 | 1251 | ||
1266 | if (!strcmp(dp->name, "be")) | 1252 | qec_op = to_of_device(parent); |
1267 | sdev = sdev->parent; | ||
1268 | 1253 | ||
1269 | return bigmac_ether_init(sdev); | 1254 | return bigmac_ether_init(op, qec_op); |
1270 | } | 1255 | } |
1271 | 1256 | ||
1272 | static int __devexit bigmac_sbus_remove(struct of_device *dev) | 1257 | static int __devexit bigmac_sbus_remove(struct of_device *op) |
1273 | { | 1258 | { |
1274 | struct bigmac *bp = dev_get_drvdata(&dev->dev); | 1259 | struct bigmac *bp = dev_get_drvdata(&op->dev); |
1260 | struct device *parent = op->dev.parent; | ||
1275 | struct net_device *net_dev = bp->dev; | 1261 | struct net_device *net_dev = bp->dev; |
1262 | struct of_device *qec_op; | ||
1263 | |||
1264 | qec_op = to_of_device(parent); | ||
1276 | 1265 | ||
1277 | unregister_netdev(net_dev); | 1266 | unregister_netdev(net_dev); |
1278 | 1267 | ||
1279 | sbus_iounmap(bp->gregs, GLOB_REG_SIZE); | 1268 | of_iounmap(&qec_op->resource[0], bp->gregs, GLOB_REG_SIZE); |
1280 | sbus_iounmap(bp->creg, CREG_REG_SIZE); | 1269 | of_iounmap(&op->resource[0], bp->creg, CREG_REG_SIZE); |
1281 | sbus_iounmap(bp->bregs, BMAC_REG_SIZE); | 1270 | of_iounmap(&op->resource[1], bp->bregs, BMAC_REG_SIZE); |
1282 | sbus_iounmap(bp->tregs, TCVR_REG_SIZE); | 1271 | of_iounmap(&op->resource[2], bp->tregs, TCVR_REG_SIZE); |
1283 | sbus_free_consistent(bp->bigmac_sdev, | 1272 | dma_free_coherent(&op->dev, |
1284 | PAGE_SIZE, | 1273 | PAGE_SIZE, |
1285 | bp->bmac_block, | 1274 | bp->bmac_block, |
1286 | bp->bblock_dvma); | 1275 | bp->bblock_dvma); |
1287 | 1276 | ||
1288 | free_netdev(net_dev); | 1277 | free_netdev(net_dev); |
1289 | 1278 | ||
1290 | dev_set_drvdata(&dev->dev, NULL); | 1279 | dev_set_drvdata(&op->dev, NULL); |
1291 | 1280 | ||
1292 | return 0; | 1281 | return 0; |
1293 | } | 1282 | } |
1294 | 1283 | ||
1295 | static struct of_device_id bigmac_sbus_match[] = { | 1284 | static const struct of_device_id bigmac_sbus_match[] = { |
1296 | { | ||
1297 | .name = "qec", | ||
1298 | }, | ||
1299 | { | 1285 | { |
1300 | .name = "be", | 1286 | .name = "be", |
1301 | }, | 1287 | }, |
@@ -1313,7 +1299,7 @@ static struct of_platform_driver bigmac_sbus_driver = { | |||
1313 | 1299 | ||
1314 | static int __init bigmac_init(void) | 1300 | static int __init bigmac_init(void) |
1315 | { | 1301 | { |
1316 | return of_register_driver(&bigmac_sbus_driver, &sbus_bus_type); | 1302 | return of_register_driver(&bigmac_sbus_driver, &of_bus_type); |
1317 | } | 1303 | } |
1318 | 1304 | ||
1319 | static void __exit bigmac_exit(void) | 1305 | static void __exit bigmac_exit(void) |
diff --git a/drivers/net/sunbmac.h b/drivers/net/sunbmac.h index b563d3c2993e..8840bc0b840b 100644 --- a/drivers/net/sunbmac.h +++ b/drivers/net/sunbmac.h | |||
@@ -329,8 +329,8 @@ struct bigmac { | |||
329 | unsigned int timer_ticks; | 329 | unsigned int timer_ticks; |
330 | 330 | ||
331 | struct net_device_stats enet_stats; | 331 | struct net_device_stats enet_stats; |
332 | struct sbus_dev *qec_sdev; | 332 | struct of_device *qec_op; |
333 | struct sbus_dev *bigmac_sdev; | 333 | struct of_device *bigmac_op; |
334 | struct net_device *dev; | 334 | struct net_device *dev; |
335 | }; | 335 | }; |
336 | 336 | ||
diff --git a/drivers/net/sunhme.c b/drivers/net/sunhme.c index b79d5f018f79..f1ebeb5f65b2 100644 --- a/drivers/net/sunhme.c +++ b/drivers/net/sunhme.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * "Happy Meal Ethernet" found on SunSwift SBUS cards. | 3 | * "Happy Meal Ethernet" found on SunSwift SBUS cards. |
4 | * | 4 | * |
5 | * Copyright (C) 1996, 1998, 1999, 2002, 2003, | 5 | * Copyright (C) 1996, 1998, 1999, 2002, 2003, |
6 | 2006 David S. Miller (davem@davemloft.net) | 6 | * 2006, 2008 David S. Miller (davem@davemloft.net) |
7 | * | 7 | * |
8 | * Changes : | 8 | * Changes : |
9 | * 2000/11/11 Willy Tarreau <willy AT meta-x.org> | 9 | * 2000/11/11 Willy Tarreau <willy AT meta-x.org> |
@@ -34,6 +34,7 @@ | |||
34 | #include <linux/skbuff.h> | 34 | #include <linux/skbuff.h> |
35 | #include <linux/mm.h> | 35 | #include <linux/mm.h> |
36 | #include <linux/bitops.h> | 36 | #include <linux/bitops.h> |
37 | #include <linux/dma-mapping.h> | ||
37 | 38 | ||
38 | #include <asm/system.h> | 39 | #include <asm/system.h> |
39 | #include <asm/io.h> | 40 | #include <asm/io.h> |
@@ -41,8 +42,9 @@ | |||
41 | #include <asm/byteorder.h> | 42 | #include <asm/byteorder.h> |
42 | 43 | ||
43 | #ifdef CONFIG_SPARC | 44 | #ifdef CONFIG_SPARC |
45 | #include <linux/of.h> | ||
46 | #include <linux/of_device.h> | ||
44 | #include <asm/idprom.h> | 47 | #include <asm/idprom.h> |
45 | #include <asm/sbus.h> | ||
46 | #include <asm/openprom.h> | 48 | #include <asm/openprom.h> |
47 | #include <asm/oplib.h> | 49 | #include <asm/oplib.h> |
48 | #include <asm/prom.h> | 50 | #include <asm/prom.h> |
@@ -60,8 +62,8 @@ | |||
60 | #include "sunhme.h" | 62 | #include "sunhme.h" |
61 | 63 | ||
62 | #define DRV_NAME "sunhme" | 64 | #define DRV_NAME "sunhme" |
63 | #define DRV_VERSION "3.00" | 65 | #define DRV_VERSION "3.10" |
64 | #define DRV_RELDATE "June 23, 2006" | 66 | #define DRV_RELDATE "August 26, 2008" |
65 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" | 67 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" |
66 | 68 | ||
67 | static char version[] = | 69 | static char version[] = |
@@ -251,13 +253,13 @@ static u32 pci_hme_read_desc32(hme32 *p) | |||
251 | #define hme_read_desc32(__hp, __p) \ | 253 | #define hme_read_desc32(__hp, __p) \ |
252 | ((__hp)->read_desc32(__p)) | 254 | ((__hp)->read_desc32(__p)) |
253 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ | 255 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ |
254 | ((__hp)->dma_map((__hp)->happy_dev, (__ptr), (__size), (__dir))) | 256 | ((__hp)->dma_map((__hp)->dma_dev, (__ptr), (__size), (__dir))) |
255 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ | 257 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ |
256 | ((__hp)->dma_unmap((__hp)->happy_dev, (__addr), (__size), (__dir))) | 258 | ((__hp)->dma_unmap((__hp)->dma_dev, (__addr), (__size), (__dir))) |
257 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ | 259 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ |
258 | ((__hp)->dma_sync_for_cpu((__hp)->happy_dev, (__addr), (__size), (__dir))) | 260 | ((__hp)->dma_sync_for_cpu((__hp)->dma_dev, (__addr), (__size), (__dir))) |
259 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ | 261 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ |
260 | ((__hp)->dma_sync_for_device((__hp)->happy_dev, (__addr), (__size), (__dir))) | 262 | ((__hp)->dma_sync_for_device((__hp)->dma_dev, (__addr), (__size), (__dir))) |
261 | #else | 263 | #else |
262 | #ifdef CONFIG_SBUS | 264 | #ifdef CONFIG_SBUS |
263 | /* SBUS only compilation */ | 265 | /* SBUS only compilation */ |
@@ -277,13 +279,13 @@ do { (__txd)->tx_addr = (__force hme32)(u32)(__addr); \ | |||
277 | } while(0) | 279 | } while(0) |
278 | #define hme_read_desc32(__hp, __p) ((__force u32)(hme32)*(__p)) | 280 | #define hme_read_desc32(__hp, __p) ((__force u32)(hme32)*(__p)) |
279 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ | 281 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ |
280 | sbus_map_single((__hp)->happy_dev, (__ptr), (__size), (__dir)) | 282 | dma_map_single((__hp)->dma_dev, (__ptr), (__size), (__dir)) |
281 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ | 283 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ |
282 | sbus_unmap_single((__hp)->happy_dev, (__addr), (__size), (__dir)) | 284 | dma_unmap_single((__hp)->dma_dev, (__addr), (__size), (__dir)) |
283 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ | 285 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ |
284 | sbus_dma_sync_single_for_cpu((__hp)->happy_dev, (__addr), (__size), (__dir)) | 286 | dma_dma_sync_single_for_cpu((__hp)->dma_dev, (__addr), (__size), (__dir)) |
285 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ | 287 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ |
286 | sbus_dma_sync_single_for_device((__hp)->happy_dev, (__addr), (__size), (__dir)) | 288 | dma_dma_sync_single_for_device((__hp)->dma_dev, (__addr), (__size), (__dir)) |
287 | #else | 289 | #else |
288 | /* PCI only compilation */ | 290 | /* PCI only compilation */ |
289 | #define hme_write32(__hp, __reg, __val) \ | 291 | #define hme_write32(__hp, __reg, __val) \ |
@@ -305,36 +307,17 @@ static inline u32 hme_read_desc32(struct happy_meal *hp, hme32 *p) | |||
305 | return le32_to_cpup((__le32 *)p); | 307 | return le32_to_cpup((__le32 *)p); |
306 | } | 308 | } |
307 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ | 309 | #define hme_dma_map(__hp, __ptr, __size, __dir) \ |
308 | pci_map_single((__hp)->happy_dev, (__ptr), (__size), (__dir)) | 310 | pci_map_single((__hp)->dma_dev, (__ptr), (__size), (__dir)) |
309 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ | 311 | #define hme_dma_unmap(__hp, __addr, __size, __dir) \ |
310 | pci_unmap_single((__hp)->happy_dev, (__addr), (__size), (__dir)) | 312 | pci_unmap_single((__hp)->dma_dev, (__addr), (__size), (__dir)) |
311 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ | 313 | #define hme_dma_sync_for_cpu(__hp, __addr, __size, __dir) \ |
312 | pci_dma_sync_single_for_cpu((__hp)->happy_dev, (__addr), (__size), (__dir)) | 314 | pci_dma_sync_single_for_cpu((__hp)->dma_dev, (__addr), (__size), (__dir)) |
313 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ | 315 | #define hme_dma_sync_for_device(__hp, __addr, __size, __dir) \ |
314 | pci_dma_sync_single_for_device((__hp)->happy_dev, (__addr), (__size), (__dir)) | 316 | pci_dma_sync_single_for_device((__hp)->dma_dev, (__addr), (__size), (__dir)) |
315 | #endif | 317 | #endif |
316 | #endif | 318 | #endif |
317 | 319 | ||
318 | 320 | ||
319 | #ifdef SBUS_DMA_BIDIRECTIONAL | ||
320 | # define DMA_BIDIRECTIONAL SBUS_DMA_BIDIRECTIONAL | ||
321 | #else | ||
322 | # define DMA_BIDIRECTIONAL 0 | ||
323 | #endif | ||
324 | |||
325 | #ifdef SBUS_DMA_FROMDEVICE | ||
326 | # define DMA_FROMDEVICE SBUS_DMA_FROMDEVICE | ||
327 | #else | ||
328 | # define DMA_TODEVICE 1 | ||
329 | #endif | ||
330 | |||
331 | #ifdef SBUS_DMA_TODEVICE | ||
332 | # define DMA_TODEVICE SBUS_DMA_TODEVICE | ||
333 | #else | ||
334 | # define DMA_FROMDEVICE 2 | ||
335 | #endif | ||
336 | |||
337 | |||
338 | /* Oh yes, the MIF BitBang is mighty fun to program. BitBucket is more like it. */ | 321 | /* Oh yes, the MIF BitBang is mighty fun to program. BitBucket is more like it. */ |
339 | static void BB_PUT_BIT(struct happy_meal *hp, void __iomem *tregs, int bit) | 322 | static void BB_PUT_BIT(struct happy_meal *hp, void __iomem *tregs, int bit) |
340 | { | 323 | { |
@@ -1224,7 +1207,8 @@ static void happy_meal_clean_rings(struct happy_meal *hp) | |||
1224 | 1207 | ||
1225 | rxd = &hp->happy_block->happy_meal_rxd[i]; | 1208 | rxd = &hp->happy_block->happy_meal_rxd[i]; |
1226 | dma_addr = hme_read_desc32(hp, &rxd->rx_addr); | 1209 | dma_addr = hme_read_desc32(hp, &rxd->rx_addr); |
1227 | hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE); | 1210 | dma_unmap_single(hp->dma_dev, dma_addr, |
1211 | RX_BUF_ALLOC_SIZE, DMA_FROM_DEVICE); | ||
1228 | dev_kfree_skb_any(skb); | 1212 | dev_kfree_skb_any(skb); |
1229 | hp->rx_skbs[i] = NULL; | 1213 | hp->rx_skbs[i] = NULL; |
1230 | } | 1214 | } |
@@ -1242,10 +1226,10 @@ static void happy_meal_clean_rings(struct happy_meal *hp) | |||
1242 | for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) { | 1226 | for (frag = 0; frag <= skb_shinfo(skb)->nr_frags; frag++) { |
1243 | txd = &hp->happy_block->happy_meal_txd[i]; | 1227 | txd = &hp->happy_block->happy_meal_txd[i]; |
1244 | dma_addr = hme_read_desc32(hp, &txd->tx_addr); | 1228 | dma_addr = hme_read_desc32(hp, &txd->tx_addr); |
1245 | hme_dma_unmap(hp, dma_addr, | 1229 | dma_unmap_single(hp->dma_dev, dma_addr, |
1246 | (hme_read_desc32(hp, &txd->tx_flags) | 1230 | (hme_read_desc32(hp, &txd->tx_flags) |
1247 | & TXFLAG_SIZE), | 1231 | & TXFLAG_SIZE), |
1248 | DMA_TODEVICE); | 1232 | DMA_TO_DEVICE); |
1249 | 1233 | ||
1250 | if (frag != skb_shinfo(skb)->nr_frags) | 1234 | if (frag != skb_shinfo(skb)->nr_frags) |
1251 | i++; | 1235 | i++; |
@@ -1287,7 +1271,8 @@ static void happy_meal_init_rings(struct happy_meal *hp) | |||
1287 | skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); | 1271 | skb_put(skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); |
1288 | hme_write_rxd(hp, &hb->happy_meal_rxd[i], | 1272 | hme_write_rxd(hp, &hb->happy_meal_rxd[i], |
1289 | (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)), | 1273 | (RXFLAG_OWN | ((RX_BUF_ALLOC_SIZE - RX_OFFSET) << 16)), |
1290 | hme_dma_map(hp, skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE)); | 1274 | dma_map_single(hp->dma_dev, skb->data, RX_BUF_ALLOC_SIZE, |
1275 | DMA_FROM_DEVICE)); | ||
1291 | skb_reserve(skb, RX_OFFSET); | 1276 | skb_reserve(skb, RX_OFFSET); |
1292 | } | 1277 | } |
1293 | 1278 | ||
@@ -1593,7 +1578,7 @@ static int happy_meal_init(struct happy_meal *hp) | |||
1593 | if ((hp->happy_bursts & DMA_BURST64) && | 1578 | if ((hp->happy_bursts & DMA_BURST64) && |
1594 | ((hp->happy_flags & HFLAG_PCI) != 0 | 1579 | ((hp->happy_flags & HFLAG_PCI) != 0 |
1595 | #ifdef CONFIG_SBUS | 1580 | #ifdef CONFIG_SBUS |
1596 | || sbus_can_burst64(hp->happy_dev) | 1581 | || sbus_can_burst64() |
1597 | #endif | 1582 | #endif |
1598 | || 0)) { | 1583 | || 0)) { |
1599 | u32 gcfg = GREG_CFG_BURST64; | 1584 | u32 gcfg = GREG_CFG_BURST64; |
@@ -1603,11 +1588,13 @@ static int happy_meal_init(struct happy_meal *hp) | |||
1603 | * do not. -DaveM | 1588 | * do not. -DaveM |
1604 | */ | 1589 | */ |
1605 | #ifdef CONFIG_SBUS | 1590 | #ifdef CONFIG_SBUS |
1606 | if ((hp->happy_flags & HFLAG_PCI) == 0 && | 1591 | if ((hp->happy_flags & HFLAG_PCI) == 0) { |
1607 | sbus_can_dma_64bit(hp->happy_dev)) { | 1592 | struct of_device *op = hp->happy_dev; |
1608 | sbus_set_sbus64(hp->happy_dev, | 1593 | if (sbus_can_dma_64bit()) { |
1609 | hp->happy_bursts); | 1594 | sbus_set_sbus64(&op->dev, |
1610 | gcfg |= GREG_CFG_64BIT; | 1595 | hp->happy_bursts); |
1596 | gcfg |= GREG_CFG_64BIT; | ||
1597 | } | ||
1611 | } | 1598 | } |
1612 | #endif | 1599 | #endif |
1613 | 1600 | ||
@@ -1966,7 +1953,7 @@ static void happy_meal_tx(struct happy_meal *hp) | |||
1966 | dma_len = hme_read_desc32(hp, &this->tx_flags); | 1953 | dma_len = hme_read_desc32(hp, &this->tx_flags); |
1967 | 1954 | ||
1968 | dma_len &= TXFLAG_SIZE; | 1955 | dma_len &= TXFLAG_SIZE; |
1969 | hme_dma_unmap(hp, dma_addr, dma_len, DMA_TODEVICE); | 1956 | dma_unmap_single(hp->dma_dev, dma_addr, dma_len, DMA_TO_DEVICE); |
1970 | 1957 | ||
1971 | elem = NEXT_TX(elem); | 1958 | elem = NEXT_TX(elem); |
1972 | this = &txbase[elem]; | 1959 | this = &txbase[elem]; |
@@ -2044,13 +2031,14 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) | |||
2044 | drops++; | 2031 | drops++; |
2045 | goto drop_it; | 2032 | goto drop_it; |
2046 | } | 2033 | } |
2047 | hme_dma_unmap(hp, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE); | 2034 | dma_unmap_single(hp->dma_dev, dma_addr, RX_BUF_ALLOC_SIZE, DMA_FROM_DEVICE); |
2048 | hp->rx_skbs[elem] = new_skb; | 2035 | hp->rx_skbs[elem] = new_skb; |
2049 | new_skb->dev = dev; | 2036 | new_skb->dev = dev; |
2050 | skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); | 2037 | skb_put(new_skb, (ETH_FRAME_LEN + RX_OFFSET + 4)); |
2051 | hme_write_rxd(hp, this, | 2038 | hme_write_rxd(hp, this, |
2052 | (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), | 2039 | (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), |
2053 | hme_dma_map(hp, new_skb->data, RX_BUF_ALLOC_SIZE, DMA_FROMDEVICE)); | 2040 | dma_map_single(hp->dma_dev, new_skb->data, RX_BUF_ALLOC_SIZE, |
2041 | DMA_FROM_DEVICE)); | ||
2054 | skb_reserve(new_skb, RX_OFFSET); | 2042 | skb_reserve(new_skb, RX_OFFSET); |
2055 | 2043 | ||
2056 | /* Trim the original skb for the netif. */ | 2044 | /* Trim the original skb for the netif. */ |
@@ -2065,10 +2053,9 @@ static void happy_meal_rx(struct happy_meal *hp, struct net_device *dev) | |||
2065 | 2053 | ||
2066 | skb_reserve(copy_skb, 2); | 2054 | skb_reserve(copy_skb, 2); |
2067 | skb_put(copy_skb, len); | 2055 | skb_put(copy_skb, len); |
2068 | hme_dma_sync_for_cpu(hp, dma_addr, len, DMA_FROMDEVICE); | 2056 | dma_sync_single_for_cpu(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE); |
2069 | skb_copy_from_linear_data(skb, copy_skb->data, len); | 2057 | skb_copy_from_linear_data(skb, copy_skb->data, len); |
2070 | hme_dma_sync_for_device(hp, dma_addr, len, DMA_FROMDEVICE); | 2058 | dma_sync_single_for_device(hp->dma_dev, dma_addr, len, DMA_FROM_DEVICE); |
2071 | |||
2072 | /* Reuse original ring buffer. */ | 2059 | /* Reuse original ring buffer. */ |
2073 | hme_write_rxd(hp, this, | 2060 | hme_write_rxd(hp, this, |
2074 | (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), | 2061 | (RXFLAG_OWN|((RX_BUF_ALLOC_SIZE-RX_OFFSET)<<16)), |
@@ -2300,7 +2287,7 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2300 | u32 mapping, len; | 2287 | u32 mapping, len; |
2301 | 2288 | ||
2302 | len = skb->len; | 2289 | len = skb->len; |
2303 | mapping = hme_dma_map(hp, skb->data, len, DMA_TODEVICE); | 2290 | mapping = dma_map_single(hp->dma_dev, skb->data, len, DMA_TO_DEVICE); |
2304 | tx_flags |= (TXFLAG_SOP | TXFLAG_EOP); | 2291 | tx_flags |= (TXFLAG_SOP | TXFLAG_EOP); |
2305 | hme_write_txd(hp, &hp->happy_block->happy_meal_txd[entry], | 2292 | hme_write_txd(hp, &hp->happy_block->happy_meal_txd[entry], |
2306 | (tx_flags | (len & TXFLAG_SIZE)), | 2293 | (tx_flags | (len & TXFLAG_SIZE)), |
@@ -2314,7 +2301,8 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2314 | * Otherwise we could race with the device. | 2301 | * Otherwise we could race with the device. |
2315 | */ | 2302 | */ |
2316 | first_len = skb_headlen(skb); | 2303 | first_len = skb_headlen(skb); |
2317 | first_mapping = hme_dma_map(hp, skb->data, first_len, DMA_TODEVICE); | 2304 | first_mapping = dma_map_single(hp->dma_dev, skb->data, first_len, |
2305 | DMA_TO_DEVICE); | ||
2318 | entry = NEXT_TX(entry); | 2306 | entry = NEXT_TX(entry); |
2319 | 2307 | ||
2320 | for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { | 2308 | for (frag = 0; frag < skb_shinfo(skb)->nr_frags; frag++) { |
@@ -2322,10 +2310,9 @@ static int happy_meal_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
2322 | u32 len, mapping, this_txflags; | 2310 | u32 len, mapping, this_txflags; |
2323 | 2311 | ||
2324 | len = this_frag->size; | 2312 | len = this_frag->size; |
2325 | mapping = hme_dma_map(hp, | 2313 | mapping = dma_map_page(hp->dma_dev, this_frag->page, |
2326 | ((void *) page_address(this_frag->page) + | 2314 | this_frag->page_offset, len, |
2327 | this_frag->page_offset), | 2315 | DMA_TO_DEVICE); |
2328 | len, DMA_TODEVICE); | ||
2329 | this_txflags = tx_flags; | 2316 | this_txflags = tx_flags; |
2330 | if (frag == skb_shinfo(skb)->nr_frags - 1) | 2317 | if (frag == skb_shinfo(skb)->nr_frags - 1) |
2331 | this_txflags |= TXFLAG_EOP; | 2318 | this_txflags |= TXFLAG_EOP; |
@@ -2493,9 +2480,12 @@ static void hme_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info | |||
2493 | } | 2480 | } |
2494 | #ifdef CONFIG_SBUS | 2481 | #ifdef CONFIG_SBUS |
2495 | else { | 2482 | else { |
2496 | struct sbus_dev *sdev = hp->happy_dev; | 2483 | const struct linux_prom_registers *regs; |
2497 | sprintf(info->bus_info, "SBUS:%d", | 2484 | struct of_device *op = hp->happy_dev; |
2498 | sdev->slot); | 2485 | regs = of_get_property(op->node, "regs", NULL); |
2486 | if (regs) | ||
2487 | sprintf(info->bus_info, "SBUS:%d", | ||
2488 | regs->which_io); | ||
2499 | } | 2489 | } |
2500 | #endif | 2490 | #endif |
2501 | } | 2491 | } |
@@ -2521,63 +2511,21 @@ static const struct ethtool_ops hme_ethtool_ops = { | |||
2521 | static int hme_version_printed; | 2511 | static int hme_version_printed; |
2522 | 2512 | ||
2523 | #ifdef CONFIG_SBUS | 2513 | #ifdef CONFIG_SBUS |
2524 | void __devinit quattro_get_ranges(struct quattro *qp) | ||
2525 | { | ||
2526 | struct sbus_dev *sdev = qp->quattro_dev; | ||
2527 | int err; | ||
2528 | |||
2529 | err = prom_getproperty(sdev->prom_node, | ||
2530 | "ranges", | ||
2531 | (char *)&qp->ranges[0], | ||
2532 | sizeof(qp->ranges)); | ||
2533 | if (err == 0 || err == -1) { | ||
2534 | qp->nranges = 0; | ||
2535 | return; | ||
2536 | } | ||
2537 | qp->nranges = (err / sizeof(struct linux_prom_ranges)); | ||
2538 | } | ||
2539 | |||
2540 | static void __devinit quattro_apply_ranges(struct quattro *qp, struct happy_meal *hp) | ||
2541 | { | ||
2542 | struct sbus_dev *sdev = hp->happy_dev; | ||
2543 | int rng; | ||
2544 | |||
2545 | for (rng = 0; rng < qp->nranges; rng++) { | ||
2546 | struct linux_prom_ranges *rngp = &qp->ranges[rng]; | ||
2547 | int reg; | ||
2548 | |||
2549 | for (reg = 0; reg < 5; reg++) { | ||
2550 | if (sdev->reg_addrs[reg].which_io == | ||
2551 | rngp->ot_child_space) | ||
2552 | break; | ||
2553 | } | ||
2554 | if (reg == 5) | ||
2555 | continue; | ||
2556 | |||
2557 | sdev->reg_addrs[reg].which_io = rngp->ot_parent_space; | ||
2558 | sdev->reg_addrs[reg].phys_addr += rngp->ot_parent_base; | ||
2559 | } | ||
2560 | } | ||
2561 | |||
2562 | /* Given a happy meal sbus device, find it's quattro parent. | 2514 | /* Given a happy meal sbus device, find it's quattro parent. |
2563 | * If none exist, allocate and return a new one. | 2515 | * If none exist, allocate and return a new one. |
2564 | * | 2516 | * |
2565 | * Return NULL on failure. | 2517 | * Return NULL on failure. |
2566 | */ | 2518 | */ |
2567 | static struct quattro * __devinit quattro_sbus_find(struct sbus_dev *goal_sdev) | 2519 | static struct quattro * __devinit quattro_sbus_find(struct of_device *child) |
2568 | { | 2520 | { |
2569 | struct sbus_dev *sdev; | 2521 | struct device *parent = child->dev.parent; |
2522 | struct of_device *op; | ||
2570 | struct quattro *qp; | 2523 | struct quattro *qp; |
2571 | int i; | ||
2572 | 2524 | ||
2573 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2525 | op = to_of_device(parent); |
2574 | for (i = 0, sdev = qp->quattro_dev; | 2526 | qp = dev_get_drvdata(&op->dev); |
2575 | (sdev != NULL) && (i < 4); | 2527 | if (qp) |
2576 | sdev = sdev->next, i++) { | 2528 | return qp; |
2577 | if (sdev == goal_sdev) | ||
2578 | return qp; | ||
2579 | } | ||
2580 | } | ||
2581 | 2529 | ||
2582 | qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); | 2530 | qp = kmalloc(sizeof(struct quattro), GFP_KERNEL); |
2583 | if (qp != NULL) { | 2531 | if (qp != NULL) { |
@@ -2586,10 +2534,11 @@ static struct quattro * __devinit quattro_sbus_find(struct sbus_dev *goal_sdev) | |||
2586 | for (i = 0; i < 4; i++) | 2534 | for (i = 0; i < 4; i++) |
2587 | qp->happy_meals[i] = NULL; | 2535 | qp->happy_meals[i] = NULL; |
2588 | 2536 | ||
2589 | qp->quattro_dev = goal_sdev; | 2537 | qp->quattro_dev = child; |
2590 | qp->next = qfe_sbus_list; | 2538 | qp->next = qfe_sbus_list; |
2591 | qfe_sbus_list = qp; | 2539 | qfe_sbus_list = qp; |
2592 | quattro_get_ranges(qp); | 2540 | |
2541 | dev_set_drvdata(&op->dev, qp); | ||
2593 | } | 2542 | } |
2594 | return qp; | 2543 | return qp; |
2595 | } | 2544 | } |
@@ -2602,10 +2551,10 @@ static void __init quattro_sbus_register_irqs(void) | |||
2602 | struct quattro *qp; | 2551 | struct quattro *qp; |
2603 | 2552 | ||
2604 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2553 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { |
2605 | struct sbus_dev *sdev = qp->quattro_dev; | 2554 | struct of_device *op = qp->quattro_dev; |
2606 | int err; | 2555 | int err; |
2607 | 2556 | ||
2608 | err = request_irq(sdev->irqs[0], | 2557 | err = request_irq(op->irqs[0], |
2609 | quattro_sbus_interrupt, | 2558 | quattro_sbus_interrupt, |
2610 | IRQF_SHARED, "Quattro", | 2559 | IRQF_SHARED, "Quattro", |
2611 | qp); | 2560 | qp); |
@@ -2621,9 +2570,9 @@ static void quattro_sbus_free_irqs(void) | |||
2621 | struct quattro *qp; | 2570 | struct quattro *qp; |
2622 | 2571 | ||
2623 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { | 2572 | for (qp = qfe_sbus_list; qp != NULL; qp = qp->next) { |
2624 | struct sbus_dev *sdev = qp->quattro_dev; | 2573 | struct of_device *op = qp->quattro_dev; |
2625 | 2574 | ||
2626 | free_irq(sdev->irqs[0], qp); | 2575 | free_irq(op->irqs[0], qp); |
2627 | } | 2576 | } |
2628 | } | 2577 | } |
2629 | #endif /* CONFIG_SBUS */ | 2578 | #endif /* CONFIG_SBUS */ |
@@ -2660,9 +2609,9 @@ static struct quattro * __devinit quattro_pci_find(struct pci_dev *pdev) | |||
2660 | #endif /* CONFIG_PCI */ | 2609 | #endif /* CONFIG_PCI */ |
2661 | 2610 | ||
2662 | #ifdef CONFIG_SBUS | 2611 | #ifdef CONFIG_SBUS |
2663 | static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe) | 2612 | static int __devinit happy_meal_sbus_probe_one(struct of_device *op, int is_qfe) |
2664 | { | 2613 | { |
2665 | struct device_node *dp = sdev->ofdev.node; | 2614 | struct device_node *dp = op->node, *sbus_dp; |
2666 | struct quattro *qp = NULL; | 2615 | struct quattro *qp = NULL; |
2667 | struct happy_meal *hp; | 2616 | struct happy_meal *hp; |
2668 | struct net_device *dev; | 2617 | struct net_device *dev; |
@@ -2671,7 +2620,7 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
2671 | DECLARE_MAC_BUF(mac); | 2620 | DECLARE_MAC_BUF(mac); |
2672 | 2621 | ||
2673 | if (is_qfe) { | 2622 | if (is_qfe) { |
2674 | qp = quattro_sbus_find(sdev); | 2623 | qp = quattro_sbus_find(op); |
2675 | if (qp == NULL) | 2624 | if (qp == NULL) |
2676 | goto err_out; | 2625 | goto err_out; |
2677 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) | 2626 | for (qfe_slot = 0; qfe_slot < 4; qfe_slot++) |
@@ -2685,7 +2634,7 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
2685 | dev = alloc_etherdev(sizeof(struct happy_meal)); | 2634 | dev = alloc_etherdev(sizeof(struct happy_meal)); |
2686 | if (!dev) | 2635 | if (!dev) |
2687 | goto err_out; | 2636 | goto err_out; |
2688 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | 2637 | SET_NETDEV_DEV(dev, &op->dev); |
2689 | 2638 | ||
2690 | if (hme_version_printed++ == 0) | 2639 | if (hme_version_printed++ == 0) |
2691 | printk(KERN_INFO "%s", version); | 2640 | printk(KERN_INFO "%s", version); |
@@ -2713,56 +2662,50 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
2713 | memcpy(dev->dev_addr, idprom->id_ethaddr, 6); | 2662 | memcpy(dev->dev_addr, idprom->id_ethaddr, 6); |
2714 | } | 2663 | } |
2715 | 2664 | ||
2716 | hp = dev->priv; | 2665 | hp = netdev_priv(dev); |
2717 | 2666 | ||
2718 | hp->happy_dev = sdev; | 2667 | hp->happy_dev = op; |
2668 | hp->dma_dev = &op->dev; | ||
2719 | 2669 | ||
2720 | spin_lock_init(&hp->happy_lock); | 2670 | spin_lock_init(&hp->happy_lock); |
2721 | 2671 | ||
2722 | err = -ENODEV; | 2672 | err = -ENODEV; |
2723 | if (sdev->num_registers != 5) { | ||
2724 | printk(KERN_ERR "happymeal: Device needs 5 regs, has %d.\n", | ||
2725 | sdev->num_registers); | ||
2726 | goto err_out_free_netdev; | ||
2727 | } | ||
2728 | |||
2729 | if (qp != NULL) { | 2673 | if (qp != NULL) { |
2730 | hp->qfe_parent = qp; | 2674 | hp->qfe_parent = qp; |
2731 | hp->qfe_ent = qfe_slot; | 2675 | hp->qfe_ent = qfe_slot; |
2732 | qp->happy_meals[qfe_slot] = dev; | 2676 | qp->happy_meals[qfe_slot] = dev; |
2733 | quattro_apply_ranges(qp, hp); | ||
2734 | } | 2677 | } |
2735 | 2678 | ||
2736 | hp->gregs = sbus_ioremap(&sdev->resource[0], 0, | 2679 | hp->gregs = of_ioremap(&op->resource[0], 0, |
2737 | GREG_REG_SIZE, "HME Global Regs"); | 2680 | GREG_REG_SIZE, "HME Global Regs"); |
2738 | if (!hp->gregs) { | 2681 | if (!hp->gregs) { |
2739 | printk(KERN_ERR "happymeal: Cannot map global registers.\n"); | 2682 | printk(KERN_ERR "happymeal: Cannot map global registers.\n"); |
2740 | goto err_out_free_netdev; | 2683 | goto err_out_free_netdev; |
2741 | } | 2684 | } |
2742 | 2685 | ||
2743 | hp->etxregs = sbus_ioremap(&sdev->resource[1], 0, | 2686 | hp->etxregs = of_ioremap(&op->resource[1], 0, |
2744 | ETX_REG_SIZE, "HME TX Regs"); | 2687 | ETX_REG_SIZE, "HME TX Regs"); |
2745 | if (!hp->etxregs) { | 2688 | if (!hp->etxregs) { |
2746 | printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n"); | 2689 | printk(KERN_ERR "happymeal: Cannot map MAC TX registers.\n"); |
2747 | goto err_out_iounmap; | 2690 | goto err_out_iounmap; |
2748 | } | 2691 | } |
2749 | 2692 | ||
2750 | hp->erxregs = sbus_ioremap(&sdev->resource[2], 0, | 2693 | hp->erxregs = of_ioremap(&op->resource[2], 0, |
2751 | ERX_REG_SIZE, "HME RX Regs"); | 2694 | ERX_REG_SIZE, "HME RX Regs"); |
2752 | if (!hp->erxregs) { | 2695 | if (!hp->erxregs) { |
2753 | printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n"); | 2696 | printk(KERN_ERR "happymeal: Cannot map MAC RX registers.\n"); |
2754 | goto err_out_iounmap; | 2697 | goto err_out_iounmap; |
2755 | } | 2698 | } |
2756 | 2699 | ||
2757 | hp->bigmacregs = sbus_ioremap(&sdev->resource[3], 0, | 2700 | hp->bigmacregs = of_ioremap(&op->resource[3], 0, |
2758 | BMAC_REG_SIZE, "HME BIGMAC Regs"); | 2701 | BMAC_REG_SIZE, "HME BIGMAC Regs"); |
2759 | if (!hp->bigmacregs) { | 2702 | if (!hp->bigmacregs) { |
2760 | printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n"); | 2703 | printk(KERN_ERR "happymeal: Cannot map BIGMAC registers.\n"); |
2761 | goto err_out_iounmap; | 2704 | goto err_out_iounmap; |
2762 | } | 2705 | } |
2763 | 2706 | ||
2764 | hp->tcvregs = sbus_ioremap(&sdev->resource[4], 0, | 2707 | hp->tcvregs = of_ioremap(&op->resource[4], 0, |
2765 | TCVR_REG_SIZE, "HME Tranceiver Regs"); | 2708 | TCVR_REG_SIZE, "HME Tranceiver Regs"); |
2766 | if (!hp->tcvregs) { | 2709 | if (!hp->tcvregs) { |
2767 | printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n"); | 2710 | printk(KERN_ERR "happymeal: Cannot map TCVR registers.\n"); |
2768 | goto err_out_iounmap; | 2711 | goto err_out_iounmap; |
@@ -2781,13 +2724,18 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
2781 | if (qp != NULL) | 2724 | if (qp != NULL) |
2782 | hp->happy_flags |= HFLAG_QUATTRO; | 2725 | hp->happy_flags |= HFLAG_QUATTRO; |
2783 | 2726 | ||
2727 | sbus_dp = to_of_device(op->dev.parent)->node; | ||
2728 | if (is_qfe) | ||
2729 | sbus_dp = to_of_device(op->dev.parent->parent)->node; | ||
2730 | |||
2784 | /* Get the supported DVMA burst sizes from our Happy SBUS. */ | 2731 | /* Get the supported DVMA burst sizes from our Happy SBUS. */ |
2785 | hp->happy_bursts = of_getintprop_default(sdev->bus->ofdev.node, | 2732 | hp->happy_bursts = of_getintprop_default(sbus_dp, |
2786 | "burst-sizes", 0x00); | 2733 | "burst-sizes", 0x00); |
2787 | 2734 | ||
2788 | hp->happy_block = sbus_alloc_consistent(hp->happy_dev, | 2735 | hp->happy_block = dma_alloc_coherent(hp->dma_dev, |
2789 | PAGE_SIZE, | 2736 | PAGE_SIZE, |
2790 | &hp->hblock_dvma); | 2737 | &hp->hblock_dvma, |
2738 | GFP_ATOMIC); | ||
2791 | err = -ENOMEM; | 2739 | err = -ENOMEM; |
2792 | if (!hp->happy_block) { | 2740 | if (!hp->happy_block) { |
2793 | printk(KERN_ERR "happymeal: Cannot allocate descriptors.\n"); | 2741 | printk(KERN_ERR "happymeal: Cannot allocate descriptors.\n"); |
@@ -2816,19 +2764,13 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
2816 | /* Happy Meal can do it all... */ | 2764 | /* Happy Meal can do it all... */ |
2817 | dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; | 2765 | dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; |
2818 | 2766 | ||
2819 | dev->irq = sdev->irqs[0]; | 2767 | dev->irq = op->irqs[0]; |
2820 | 2768 | ||
2821 | #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) | 2769 | #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) |
2822 | /* Hook up PCI register/dma accessors. */ | 2770 | /* Hook up SBUS register/descriptor accessors. */ |
2823 | hp->read_desc32 = sbus_hme_read_desc32; | 2771 | hp->read_desc32 = sbus_hme_read_desc32; |
2824 | hp->write_txd = sbus_hme_write_txd; | 2772 | hp->write_txd = sbus_hme_write_txd; |
2825 | hp->write_rxd = sbus_hme_write_rxd; | 2773 | hp->write_rxd = sbus_hme_write_rxd; |
2826 | hp->dma_map = (u32 (*)(void *, void *, long, int))sbus_map_single; | ||
2827 | hp->dma_unmap = (void (*)(void *, u32, long, int))sbus_unmap_single; | ||
2828 | hp->dma_sync_for_cpu = (void (*)(void *, u32, long, int)) | ||
2829 | sbus_dma_sync_single_for_cpu; | ||
2830 | hp->dma_sync_for_device = (void (*)(void *, u32, long, int)) | ||
2831 | sbus_dma_sync_single_for_device; | ||
2832 | hp->read32 = sbus_hme_read32; | 2774 | hp->read32 = sbus_hme_read32; |
2833 | hp->write32 = sbus_hme_write32; | 2775 | hp->write32 = sbus_hme_write32; |
2834 | #endif | 2776 | #endif |
@@ -2843,10 +2785,10 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
2843 | if (register_netdev(hp->dev)) { | 2785 | if (register_netdev(hp->dev)) { |
2844 | printk(KERN_ERR "happymeal: Cannot register net device, " | 2786 | printk(KERN_ERR "happymeal: Cannot register net device, " |
2845 | "aborting.\n"); | 2787 | "aborting.\n"); |
2846 | goto err_out_free_consistent; | 2788 | goto err_out_free_coherent; |
2847 | } | 2789 | } |
2848 | 2790 | ||
2849 | dev_set_drvdata(&sdev->ofdev.dev, hp); | 2791 | dev_set_drvdata(&op->dev, hp); |
2850 | 2792 | ||
2851 | if (qfe_slot != -1) | 2793 | if (qfe_slot != -1) |
2852 | printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", | 2794 | printk(KERN_INFO "%s: Quattro HME slot %d (SBUS) 10/100baseT Ethernet ", |
@@ -2859,23 +2801,23 @@ static int __devinit happy_meal_sbus_probe_one(struct sbus_dev *sdev, int is_qfe | |||
2859 | 2801 | ||
2860 | return 0; | 2802 | return 0; |
2861 | 2803 | ||
2862 | err_out_free_consistent: | 2804 | err_out_free_coherent: |
2863 | sbus_free_consistent(hp->happy_dev, | 2805 | dma_free_coherent(hp->dma_dev, |
2864 | PAGE_SIZE, | 2806 | PAGE_SIZE, |
2865 | hp->happy_block, | 2807 | hp->happy_block, |
2866 | hp->hblock_dvma); | 2808 | hp->hblock_dvma); |
2867 | 2809 | ||
2868 | err_out_iounmap: | 2810 | err_out_iounmap: |
2869 | if (hp->gregs) | 2811 | if (hp->gregs) |
2870 | sbus_iounmap(hp->gregs, GREG_REG_SIZE); | 2812 | of_iounmap(&op->resource[0], hp->gregs, GREG_REG_SIZE); |
2871 | if (hp->etxregs) | 2813 | if (hp->etxregs) |
2872 | sbus_iounmap(hp->etxregs, ETX_REG_SIZE); | 2814 | of_iounmap(&op->resource[1], hp->etxregs, ETX_REG_SIZE); |
2873 | if (hp->erxregs) | 2815 | if (hp->erxregs) |
2874 | sbus_iounmap(hp->erxregs, ERX_REG_SIZE); | 2816 | of_iounmap(&op->resource[2], hp->erxregs, ERX_REG_SIZE); |
2875 | if (hp->bigmacregs) | 2817 | if (hp->bigmacregs) |
2876 | sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); | 2818 | of_iounmap(&op->resource[3], hp->bigmacregs, BMAC_REG_SIZE); |
2877 | if (hp->tcvregs) | 2819 | if (hp->tcvregs) |
2878 | sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); | 2820 | of_iounmap(&op->resource[4], hp->tcvregs, TCVR_REG_SIZE); |
2879 | 2821 | ||
2880 | err_out_free_netdev: | 2822 | err_out_free_netdev: |
2881 | free_netdev(dev); | 2823 | free_netdev(dev); |
@@ -3035,6 +2977,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, | |||
3035 | memset(hp, 0, sizeof(*hp)); | 2977 | memset(hp, 0, sizeof(*hp)); |
3036 | 2978 | ||
3037 | hp->happy_dev = pdev; | 2979 | hp->happy_dev = pdev; |
2980 | hp->dma_dev = &pdev->dev; | ||
3038 | 2981 | ||
3039 | spin_lock_init(&hp->happy_lock); | 2982 | spin_lock_init(&hp->happy_lock); |
3040 | 2983 | ||
@@ -3121,7 +3064,7 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, | |||
3121 | #endif | 3064 | #endif |
3122 | 3065 | ||
3123 | hp->happy_block = (struct hmeal_init_block *) | 3066 | hp->happy_block = (struct hmeal_init_block *) |
3124 | pci_alloc_consistent(pdev, PAGE_SIZE, &hp->hblock_dvma); | 3067 | dma_alloc_coherent(&pdev->dev, PAGE_SIZE, &hp->hblock_dvma, GFP_KERNEL); |
3125 | 3068 | ||
3126 | err = -ENODEV; | 3069 | err = -ENODEV; |
3127 | if (!hp->happy_block) { | 3070 | if (!hp->happy_block) { |
@@ -3151,16 +3094,10 @@ static int __devinit happy_meal_pci_probe(struct pci_dev *pdev, | |||
3151 | dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; | 3094 | dev->features |= NETIF_F_SG | NETIF_F_HW_CSUM; |
3152 | 3095 | ||
3153 | #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) | 3096 | #if defined(CONFIG_SBUS) && defined(CONFIG_PCI) |
3154 | /* Hook up PCI register/dma accessors. */ | 3097 | /* Hook up PCI register/descriptor accessors. */ |
3155 | hp->read_desc32 = pci_hme_read_desc32; | 3098 | hp->read_desc32 = pci_hme_read_desc32; |
3156 | hp->write_txd = pci_hme_write_txd; | 3099 | hp->write_txd = pci_hme_write_txd; |
3157 | hp->write_rxd = pci_hme_write_rxd; | 3100 | hp->write_rxd = pci_hme_write_rxd; |
3158 | hp->dma_map = (u32 (*)(void *, void *, long, int))pci_map_single; | ||
3159 | hp->dma_unmap = (void (*)(void *, u32, long, int))pci_unmap_single; | ||
3160 | hp->dma_sync_for_cpu = (void (*)(void *, u32, long, int)) | ||
3161 | pci_dma_sync_single_for_cpu; | ||
3162 | hp->dma_sync_for_device = (void (*)(void *, u32, long, int)) | ||
3163 | pci_dma_sync_single_for_device; | ||
3164 | hp->read32 = pci_hme_read32; | 3101 | hp->read32 = pci_hme_read32; |
3165 | hp->write32 = pci_hme_write32; | 3102 | hp->write32 = pci_hme_write32; |
3166 | #endif | 3103 | #endif |
@@ -3231,10 +3168,8 @@ static void __devexit happy_meal_pci_remove(struct pci_dev *pdev) | |||
3231 | 3168 | ||
3232 | unregister_netdev(net_dev); | 3169 | unregister_netdev(net_dev); |
3233 | 3170 | ||
3234 | pci_free_consistent(hp->happy_dev, | 3171 | dma_free_coherent(hp->dma_dev, PAGE_SIZE, |
3235 | PAGE_SIZE, | 3172 | hp->happy_block, hp->hblock_dvma); |
3236 | hp->happy_block, | ||
3237 | hp->hblock_dvma); | ||
3238 | iounmap(hp->gregs); | 3173 | iounmap(hp->gregs); |
3239 | pci_release_regions(hp->happy_dev); | 3174 | pci_release_regions(hp->happy_dev); |
3240 | 3175 | ||
@@ -3279,46 +3214,45 @@ static void happy_meal_pci_exit(void) | |||
3279 | #endif | 3214 | #endif |
3280 | 3215 | ||
3281 | #ifdef CONFIG_SBUS | 3216 | #ifdef CONFIG_SBUS |
3282 | static int __devinit hme_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 3217 | static int __devinit hme_sbus_probe(struct of_device *op, const struct of_device_id *match) |
3283 | { | 3218 | { |
3284 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | 3219 | struct device_node *dp = op->node; |
3285 | struct device_node *dp = dev->node; | ||
3286 | const char *model = of_get_property(dp, "model", NULL); | 3220 | const char *model = of_get_property(dp, "model", NULL); |
3287 | int is_qfe = (match->data != NULL); | 3221 | int is_qfe = (match->data != NULL); |
3288 | 3222 | ||
3289 | if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe")) | 3223 | if (!is_qfe && model && !strcmp(model, "SUNW,sbus-qfe")) |
3290 | is_qfe = 1; | 3224 | is_qfe = 1; |
3291 | 3225 | ||
3292 | return happy_meal_sbus_probe_one(sdev, is_qfe); | 3226 | return happy_meal_sbus_probe_one(op, is_qfe); |
3293 | } | 3227 | } |
3294 | 3228 | ||
3295 | static int __devexit hme_sbus_remove(struct of_device *dev) | 3229 | static int __devexit hme_sbus_remove(struct of_device *op) |
3296 | { | 3230 | { |
3297 | struct happy_meal *hp = dev_get_drvdata(&dev->dev); | 3231 | struct happy_meal *hp = dev_get_drvdata(&op->dev); |
3298 | struct net_device *net_dev = hp->dev; | 3232 | struct net_device *net_dev = hp->dev; |
3299 | 3233 | ||
3300 | unregister_netdev(net_dev); | 3234 | unregister_netdev(net_dev); |
3301 | 3235 | ||
3302 | /* XXX qfe parent interrupt... */ | 3236 | /* XXX qfe parent interrupt... */ |
3303 | 3237 | ||
3304 | sbus_iounmap(hp->gregs, GREG_REG_SIZE); | 3238 | of_iounmap(&op->resource[0], hp->gregs, GREG_REG_SIZE); |
3305 | sbus_iounmap(hp->etxregs, ETX_REG_SIZE); | 3239 | of_iounmap(&op->resource[1], hp->etxregs, ETX_REG_SIZE); |
3306 | sbus_iounmap(hp->erxregs, ERX_REG_SIZE); | 3240 | of_iounmap(&op->resource[2], hp->erxregs, ERX_REG_SIZE); |
3307 | sbus_iounmap(hp->bigmacregs, BMAC_REG_SIZE); | 3241 | of_iounmap(&op->resource[3], hp->bigmacregs, BMAC_REG_SIZE); |
3308 | sbus_iounmap(hp->tcvregs, TCVR_REG_SIZE); | 3242 | of_iounmap(&op->resource[4], hp->tcvregs, TCVR_REG_SIZE); |
3309 | sbus_free_consistent(hp->happy_dev, | 3243 | dma_free_coherent(hp->dma_dev, |
3310 | PAGE_SIZE, | 3244 | PAGE_SIZE, |
3311 | hp->happy_block, | 3245 | hp->happy_block, |
3312 | hp->hblock_dvma); | 3246 | hp->hblock_dvma); |
3313 | 3247 | ||
3314 | free_netdev(net_dev); | 3248 | free_netdev(net_dev); |
3315 | 3249 | ||
3316 | dev_set_drvdata(&dev->dev, NULL); | 3250 | dev_set_drvdata(&op->dev, NULL); |
3317 | 3251 | ||
3318 | return 0; | 3252 | return 0; |
3319 | } | 3253 | } |
3320 | 3254 | ||
3321 | static struct of_device_id hme_sbus_match[] = { | 3255 | static const struct of_device_id hme_sbus_match[] = { |
3322 | { | 3256 | { |
3323 | .name = "SUNW,hme", | 3257 | .name = "SUNW,hme", |
3324 | }, | 3258 | }, |
@@ -3346,7 +3280,7 @@ static int __init happy_meal_sbus_init(void) | |||
3346 | { | 3280 | { |
3347 | int err; | 3281 | int err; |
3348 | 3282 | ||
3349 | err = of_register_driver(&hme_sbus_driver, &sbus_bus_type); | 3283 | err = of_register_driver(&hme_sbus_driver, &of_bus_type); |
3350 | if (!err) | 3284 | if (!err) |
3351 | quattro_sbus_register_irqs(); | 3285 | quattro_sbus_register_irqs(); |
3352 | 3286 | ||
diff --git a/drivers/net/sunhme.h b/drivers/net/sunhme.h index 4da5539fac7b..efd2ca0fcad3 100644 --- a/drivers/net/sunhme.h +++ b/drivers/net/sunhme.h | |||
@@ -405,14 +405,11 @@ struct happy_meal { | |||
405 | u32 (*read_desc32)(hme32 *); | 405 | u32 (*read_desc32)(hme32 *); |
406 | void (*write_txd)(struct happy_meal_txd *, u32, u32); | 406 | void (*write_txd)(struct happy_meal_txd *, u32, u32); |
407 | void (*write_rxd)(struct happy_meal_rxd *, u32, u32); | 407 | void (*write_rxd)(struct happy_meal_rxd *, u32, u32); |
408 | u32 (*dma_map)(void *, void *, long, int); | ||
409 | void (*dma_unmap)(void *, u32, long, int); | ||
410 | void (*dma_sync_for_cpu)(void *, u32, long, int); | ||
411 | void (*dma_sync_for_device)(void *, u32, long, int); | ||
412 | #endif | 408 | #endif |
413 | 409 | ||
414 | /* This is either a sbus_dev or a pci_dev. */ | 410 | /* This is either an of_device or a pci_dev. */ |
415 | void *happy_dev; | 411 | void *happy_dev; |
412 | struct device *dma_dev; | ||
416 | 413 | ||
417 | spinlock_t happy_lock; | 414 | spinlock_t happy_lock; |
418 | 415 | ||
diff --git a/drivers/net/sunlance.c b/drivers/net/sunlance.c index 4e994f87469e..704301a5a7ff 100644 --- a/drivers/net/sunlance.c +++ b/drivers/net/sunlance.c | |||
@@ -91,6 +91,9 @@ static char lancestr[] = "LANCE"; | |||
91 | #include <linux/skbuff.h> | 91 | #include <linux/skbuff.h> |
92 | #include <linux/ethtool.h> | 92 | #include <linux/ethtool.h> |
93 | #include <linux/bitops.h> | 93 | #include <linux/bitops.h> |
94 | #include <linux/dma-mapping.h> | ||
95 | #include <linux/of.h> | ||
96 | #include <linux/of_device.h> | ||
94 | 97 | ||
95 | #include <asm/system.h> | 98 | #include <asm/system.h> |
96 | #include <asm/io.h> | 99 | #include <asm/io.h> |
@@ -98,7 +101,6 @@ static char lancestr[] = "LANCE"; | |||
98 | #include <asm/pgtable.h> | 101 | #include <asm/pgtable.h> |
99 | #include <asm/byteorder.h> /* Used by the checksum routines */ | 102 | #include <asm/byteorder.h> /* Used by the checksum routines */ |
100 | #include <asm/idprom.h> | 103 | #include <asm/idprom.h> |
101 | #include <asm/sbus.h> | ||
102 | #include <asm/prom.h> | 104 | #include <asm/prom.h> |
103 | #include <asm/auxio.h> /* For tpe-link-test? setting */ | 105 | #include <asm/auxio.h> /* For tpe-link-test? setting */ |
104 | #include <asm/irq.h> | 106 | #include <asm/irq.h> |
@@ -248,7 +250,7 @@ struct lance_private { | |||
248 | int rx_new, tx_new; | 250 | int rx_new, tx_new; |
249 | int rx_old, tx_old; | 251 | int rx_old, tx_old; |
250 | 252 | ||
251 | struct sbus_dma *ledma; /* If set this points to ledma */ | 253 | struct of_device *ledma; /* If set this points to ledma */ |
252 | char tpe; /* cable-selection is TPE */ | 254 | char tpe; /* cable-selection is TPE */ |
253 | char auto_select; /* cable-selection by carrier */ | 255 | char auto_select; /* cable-selection by carrier */ |
254 | char burst_sizes; /* ledma SBus burst sizes */ | 256 | char burst_sizes; /* ledma SBus burst sizes */ |
@@ -263,7 +265,8 @@ struct lance_private { | |||
263 | char *name; | 265 | char *name; |
264 | dma_addr_t init_block_dvma; | 266 | dma_addr_t init_block_dvma; |
265 | struct net_device *dev; /* Backpointer */ | 267 | struct net_device *dev; /* Backpointer */ |
266 | struct sbus_dev *sdev; | 268 | struct of_device *op; |
269 | struct of_device *lebuffer; | ||
267 | struct timer_list multicast_timer; | 270 | struct timer_list multicast_timer; |
268 | }; | 271 | }; |
269 | 272 | ||
@@ -1272,27 +1275,29 @@ static void lance_set_multicast_retry(unsigned long _opaque) | |||
1272 | static void lance_free_hwresources(struct lance_private *lp) | 1275 | static void lance_free_hwresources(struct lance_private *lp) |
1273 | { | 1276 | { |
1274 | if (lp->lregs) | 1277 | if (lp->lregs) |
1275 | sbus_iounmap(lp->lregs, LANCE_REG_SIZE); | 1278 | of_iounmap(&lp->op->resource[0], lp->lregs, LANCE_REG_SIZE); |
1279 | if (lp->dregs) { | ||
1280 | struct of_device *ledma = lp->ledma; | ||
1281 | |||
1282 | of_iounmap(&ledma->resource[0], lp->dregs, | ||
1283 | resource_size(&ledma->resource[0])); | ||
1284 | } | ||
1276 | if (lp->init_block_iomem) { | 1285 | if (lp->init_block_iomem) { |
1277 | sbus_iounmap(lp->init_block_iomem, | 1286 | of_iounmap(&lp->lebuffer->resource[0], lp->init_block_iomem, |
1278 | sizeof(struct lance_init_block)); | 1287 | sizeof(struct lance_init_block)); |
1279 | } else if (lp->init_block_mem) { | 1288 | } else if (lp->init_block_mem) { |
1280 | sbus_free_consistent(lp->sdev, | 1289 | dma_free_coherent(&lp->op->dev, |
1281 | sizeof(struct lance_init_block), | 1290 | sizeof(struct lance_init_block), |
1282 | lp->init_block_mem, | 1291 | lp->init_block_mem, |
1283 | lp->init_block_dvma); | 1292 | lp->init_block_dvma); |
1284 | } | 1293 | } |
1285 | } | 1294 | } |
1286 | 1295 | ||
1287 | /* Ethtool support... */ | 1296 | /* Ethtool support... */ |
1288 | static void sparc_lance_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | 1297 | static void sparc_lance_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) |
1289 | { | 1298 | { |
1290 | struct lance_private *lp = netdev_priv(dev); | ||
1291 | |||
1292 | strcpy(info->driver, "sunlance"); | 1299 | strcpy(info->driver, "sunlance"); |
1293 | strcpy(info->version, "2.02"); | 1300 | strcpy(info->version, "2.02"); |
1294 | sprintf(info->bus_info, "SBUS:%d", | ||
1295 | lp->sdev->slot); | ||
1296 | } | 1301 | } |
1297 | 1302 | ||
1298 | static u32 sparc_lance_get_link(struct net_device *dev) | 1303 | static u32 sparc_lance_get_link(struct net_device *dev) |
@@ -1308,16 +1313,16 @@ static const struct ethtool_ops sparc_lance_ethtool_ops = { | |||
1308 | .get_link = sparc_lance_get_link, | 1313 | .get_link = sparc_lance_get_link, |
1309 | }; | 1314 | }; |
1310 | 1315 | ||
1311 | static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | 1316 | static int __devinit sparc_lance_probe_one(struct of_device *op, |
1312 | struct sbus_dma *ledma, | 1317 | struct of_device *ledma, |
1313 | struct sbus_dev *lebuffer) | 1318 | struct of_device *lebuffer) |
1314 | { | 1319 | { |
1320 | struct device_node *dp = op->node; | ||
1315 | static unsigned version_printed; | 1321 | static unsigned version_printed; |
1316 | struct device_node *dp = sdev->ofdev.node; | ||
1317 | struct net_device *dev; | ||
1318 | struct lance_private *lp; | 1322 | struct lance_private *lp; |
1319 | int i; | 1323 | struct net_device *dev; |
1320 | DECLARE_MAC_BUF(mac); | 1324 | DECLARE_MAC_BUF(mac); |
1325 | int i; | ||
1321 | 1326 | ||
1322 | dev = alloc_etherdev(sizeof(struct lance_private) + 8); | 1327 | dev = alloc_etherdev(sizeof(struct lance_private) + 8); |
1323 | if (!dev) | 1328 | if (!dev) |
@@ -1338,14 +1343,27 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | |||
1338 | dev->dev_addr[i] = idprom->id_ethaddr[i]; | 1343 | dev->dev_addr[i] = idprom->id_ethaddr[i]; |
1339 | 1344 | ||
1340 | /* Get the IO region */ | 1345 | /* Get the IO region */ |
1341 | lp->lregs = sbus_ioremap(&sdev->resource[0], 0, | 1346 | lp->lregs = of_ioremap(&op->resource[0], 0, |
1342 | LANCE_REG_SIZE, lancestr); | 1347 | LANCE_REG_SIZE, lancestr); |
1343 | if (!lp->lregs) { | 1348 | if (!lp->lregs) { |
1344 | printk(KERN_ERR "SunLance: Cannot map registers.\n"); | 1349 | printk(KERN_ERR "SunLance: Cannot map registers.\n"); |
1345 | goto fail; | 1350 | goto fail; |
1346 | } | 1351 | } |
1347 | 1352 | ||
1348 | lp->sdev = sdev; | 1353 | lp->ledma = ledma; |
1354 | if (lp->ledma) { | ||
1355 | lp->dregs = of_ioremap(&ledma->resource[0], 0, | ||
1356 | resource_size(&ledma->resource[0]), | ||
1357 | "ledma"); | ||
1358 | if (!lp->dregs) { | ||
1359 | printk(KERN_ERR "SunLance: Cannot map " | ||
1360 | "ledma registers.\n"); | ||
1361 | goto fail; | ||
1362 | } | ||
1363 | } | ||
1364 | |||
1365 | lp->op = op; | ||
1366 | lp->lebuffer = lebuffer; | ||
1349 | if (lebuffer) { | 1367 | if (lebuffer) { |
1350 | /* sanity check */ | 1368 | /* sanity check */ |
1351 | if (lebuffer->resource[0].start & 7) { | 1369 | if (lebuffer->resource[0].start & 7) { |
@@ -1353,8 +1371,8 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | |||
1353 | goto fail; | 1371 | goto fail; |
1354 | } | 1372 | } |
1355 | lp->init_block_iomem = | 1373 | lp->init_block_iomem = |
1356 | sbus_ioremap(&lebuffer->resource[0], 0, | 1374 | of_ioremap(&lebuffer->resource[0], 0, |
1357 | sizeof(struct lance_init_block), "lebuffer"); | 1375 | sizeof(struct lance_init_block), "lebuffer"); |
1358 | if (!lp->init_block_iomem) { | 1376 | if (!lp->init_block_iomem) { |
1359 | printk(KERN_ERR "SunLance: Cannot map PIO buffer.\n"); | 1377 | printk(KERN_ERR "SunLance: Cannot map PIO buffer.\n"); |
1360 | goto fail; | 1378 | goto fail; |
@@ -1366,9 +1384,10 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | |||
1366 | lp->tx = lance_tx_pio; | 1384 | lp->tx = lance_tx_pio; |
1367 | } else { | 1385 | } else { |
1368 | lp->init_block_mem = | 1386 | lp->init_block_mem = |
1369 | sbus_alloc_consistent(sdev, sizeof(struct lance_init_block), | 1387 | dma_alloc_coherent(&op->dev, |
1370 | &lp->init_block_dvma); | 1388 | sizeof(struct lance_init_block), |
1371 | if (!lp->init_block_mem || lp->init_block_dvma == 0) { | 1389 | &lp->init_block_dvma, GFP_ATOMIC); |
1390 | if (!lp->init_block_mem) { | ||
1372 | printk(KERN_ERR "SunLance: Cannot allocate consistent DMA memory.\n"); | 1391 | printk(KERN_ERR "SunLance: Cannot allocate consistent DMA memory.\n"); |
1373 | goto fail; | 1392 | goto fail; |
1374 | } | 1393 | } |
@@ -1383,13 +1402,13 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | |||
1383 | LE_C3_BCON)); | 1402 | LE_C3_BCON)); |
1384 | 1403 | ||
1385 | lp->name = lancestr; | 1404 | lp->name = lancestr; |
1386 | lp->ledma = ledma; | ||
1387 | 1405 | ||
1388 | lp->burst_sizes = 0; | 1406 | lp->burst_sizes = 0; |
1389 | if (lp->ledma) { | 1407 | if (lp->ledma) { |
1390 | struct device_node *ledma_dp = ledma->sdev->ofdev.node; | 1408 | struct device_node *ledma_dp = ledma->node; |
1391 | const char *prop; | 1409 | struct device_node *sbus_dp; |
1392 | unsigned int sbmask; | 1410 | unsigned int sbmask; |
1411 | const char *prop; | ||
1393 | u32 csr; | 1412 | u32 csr; |
1394 | 1413 | ||
1395 | /* Find burst-size property for ledma */ | 1414 | /* Find burst-size property for ledma */ |
@@ -1397,7 +1416,8 @@ static int __devinit sparc_lance_probe_one(struct sbus_dev *sdev, | |||
1397 | "burst-sizes", 0); | 1416 | "burst-sizes", 0); |
1398 | 1417 | ||
1399 | /* ledma may be capable of fast bursts, but sbus may not. */ | 1418 | /* ledma may be capable of fast bursts, but sbus may not. */ |
1400 | sbmask = of_getintprop_default(ledma_dp, "burst-sizes", | 1419 | sbus_dp = ledma_dp->parent; |
1420 | sbmask = of_getintprop_default(sbus_dp, "burst-sizes", | ||
1401 | DMA_BURSTBITS); | 1421 | DMA_BURSTBITS); |
1402 | lp->burst_sizes &= sbmask; | 1422 | lp->burst_sizes &= sbmask; |
1403 | 1423 | ||
@@ -1435,8 +1455,6 @@ no_link_test: | |||
1435 | lp->tpe = 1; | 1455 | lp->tpe = 1; |
1436 | } | 1456 | } |
1437 | 1457 | ||
1438 | lp->dregs = ledma->regs; | ||
1439 | |||
1440 | /* Reset ledma */ | 1458 | /* Reset ledma */ |
1441 | csr = sbus_readl(lp->dregs + DMA_CSR); | 1459 | csr = sbus_readl(lp->dregs + DMA_CSR); |
1442 | sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR); | 1460 | sbus_writel(csr | DMA_RST_ENET, lp->dregs + DMA_CSR); |
@@ -1446,7 +1464,7 @@ no_link_test: | |||
1446 | lp->dregs = NULL; | 1464 | lp->dregs = NULL; |
1447 | 1465 | ||
1448 | lp->dev = dev; | 1466 | lp->dev = dev; |
1449 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | 1467 | SET_NETDEV_DEV(dev, &op->dev); |
1450 | dev->open = &lance_open; | 1468 | dev->open = &lance_open; |
1451 | dev->stop = &lance_close; | 1469 | dev->stop = &lance_close; |
1452 | dev->hard_start_xmit = &lance_start_xmit; | 1470 | dev->hard_start_xmit = &lance_start_xmit; |
@@ -1455,9 +1473,7 @@ no_link_test: | |||
1455 | dev->set_multicast_list = &lance_set_multicast; | 1473 | dev->set_multicast_list = &lance_set_multicast; |
1456 | dev->ethtool_ops = &sparc_lance_ethtool_ops; | 1474 | dev->ethtool_ops = &sparc_lance_ethtool_ops; |
1457 | 1475 | ||
1458 | dev->irq = sdev->irqs[0]; | 1476 | dev->irq = op->irqs[0]; |
1459 | |||
1460 | dev->dma = 0; | ||
1461 | 1477 | ||
1462 | /* We cannot sleep if the chip is busy during a | 1478 | /* We cannot sleep if the chip is busy during a |
1463 | * multicast list update event, because such events | 1479 | * multicast list update event, because such events |
@@ -1473,7 +1489,7 @@ no_link_test: | |||
1473 | goto fail; | 1489 | goto fail; |
1474 | } | 1490 | } |
1475 | 1491 | ||
1476 | dev_set_drvdata(&sdev->ofdev.dev, lp); | 1492 | dev_set_drvdata(&op->dev, lp); |
1477 | 1493 | ||
1478 | printk(KERN_INFO "%s: LANCE %s\n", | 1494 | printk(KERN_INFO "%s: LANCE %s\n", |
1479 | dev->name, print_mac(mac, dev->dev_addr)); | 1495 | dev->name, print_mac(mac, dev->dev_addr)); |
@@ -1486,80 +1502,25 @@ fail: | |||
1486 | return -ENODEV; | 1502 | return -ENODEV; |
1487 | } | 1503 | } |
1488 | 1504 | ||
1489 | /* On 4m, find the associated dma for the lance chip */ | 1505 | static int __devinit sunlance_sbus_probe(struct of_device *op, const struct of_device_id *match) |
1490 | static struct sbus_dma * __devinit find_ledma(struct sbus_dev *sdev) | ||
1491 | { | ||
1492 | struct sbus_dma *p; | ||
1493 | |||
1494 | for_each_dvma(p) { | ||
1495 | if (p->sdev == sdev) | ||
1496 | return p; | ||
1497 | } | ||
1498 | return NULL; | ||
1499 | } | ||
1500 | |||
1501 | #ifdef CONFIG_SUN4 | ||
1502 | |||
1503 | #include <asm/sun4paddr.h> | ||
1504 | #include <asm/machines.h> | ||
1505 | |||
1506 | /* Find all the lance cards on the system and initialize them */ | ||
1507 | static struct sbus_dev sun4_sdev; | ||
1508 | static int __devinit sparc_lance_init(void) | ||
1509 | { | ||
1510 | if ((idprom->id_machtype == (SM_SUN4|SM_4_330)) || | ||
1511 | (idprom->id_machtype == (SM_SUN4|SM_4_470))) { | ||
1512 | memset(&sun4_sdev, 0, sizeof(struct sbus_dev)); | ||
1513 | sun4_sdev.reg_addrs[0].phys_addr = sun4_eth_physaddr; | ||
1514 | sun4_sdev.irqs[0] = 6; | ||
1515 | return sparc_lance_probe_one(&sun4_sdev, NULL, NULL); | ||
1516 | } | ||
1517 | return -ENODEV; | ||
1518 | } | ||
1519 | |||
1520 | static int __exit sunlance_sun4_remove(void) | ||
1521 | { | 1506 | { |
1522 | struct lance_private *lp = dev_get_drvdata(&sun4_sdev.ofdev.dev); | 1507 | struct of_device *parent = to_of_device(op->dev.parent); |
1523 | struct net_device *net_dev = lp->dev; | 1508 | struct device_node *parent_dp = parent->node; |
1524 | |||
1525 | unregister_netdev(net_dev); | ||
1526 | |||
1527 | lance_free_hwresources(lp); | ||
1528 | |||
1529 | free_netdev(net_dev); | ||
1530 | |||
1531 | dev_set_drvdata(&sun4_sdev.ofdev.dev, NULL); | ||
1532 | |||
1533 | return 0; | ||
1534 | } | ||
1535 | |||
1536 | #else /* !CONFIG_SUN4 */ | ||
1537 | |||
1538 | static int __devinit sunlance_sbus_probe(struct of_device *dev, const struct of_device_id *match) | ||
1539 | { | ||
1540 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
1541 | int err; | 1509 | int err; |
1542 | 1510 | ||
1543 | if (sdev->parent) { | 1511 | if (!strcmp(parent_dp->name, "ledma")) { |
1544 | struct of_device *parent = &sdev->parent->ofdev; | 1512 | err = sparc_lance_probe_one(op, parent, NULL); |
1545 | 1513 | } else if (!strcmp(parent_dp->name, "lebuffer")) { | |
1546 | if (!strcmp(parent->node->name, "ledma")) { | 1514 | err = sparc_lance_probe_one(op, NULL, parent); |
1547 | struct sbus_dma *ledma = find_ledma(to_sbus_device(&parent->dev)); | ||
1548 | |||
1549 | err = sparc_lance_probe_one(sdev, ledma, NULL); | ||
1550 | } else if (!strcmp(parent->node->name, "lebuffer")) { | ||
1551 | err = sparc_lance_probe_one(sdev, NULL, to_sbus_device(&parent->dev)); | ||
1552 | } else | ||
1553 | err = sparc_lance_probe_one(sdev, NULL, NULL); | ||
1554 | } else | 1515 | } else |
1555 | err = sparc_lance_probe_one(sdev, NULL, NULL); | 1516 | err = sparc_lance_probe_one(op, NULL, NULL); |
1556 | 1517 | ||
1557 | return err; | 1518 | return err; |
1558 | } | 1519 | } |
1559 | 1520 | ||
1560 | static int __devexit sunlance_sbus_remove(struct of_device *dev) | 1521 | static int __devexit sunlance_sbus_remove(struct of_device *op) |
1561 | { | 1522 | { |
1562 | struct lance_private *lp = dev_get_drvdata(&dev->dev); | 1523 | struct lance_private *lp = dev_get_drvdata(&op->dev); |
1563 | struct net_device *net_dev = lp->dev; | 1524 | struct net_device *net_dev = lp->dev; |
1564 | 1525 | ||
1565 | unregister_netdev(net_dev); | 1526 | unregister_netdev(net_dev); |
@@ -1568,12 +1529,12 @@ static int __devexit sunlance_sbus_remove(struct of_device *dev) | |||
1568 | 1529 | ||
1569 | free_netdev(net_dev); | 1530 | free_netdev(net_dev); |
1570 | 1531 | ||
1571 | dev_set_drvdata(&dev->dev, NULL); | 1532 | dev_set_drvdata(&op->dev, NULL); |
1572 | 1533 | ||
1573 | return 0; | 1534 | return 0; |
1574 | } | 1535 | } |
1575 | 1536 | ||
1576 | static struct of_device_id sunlance_sbus_match[] = { | 1537 | static const struct of_device_id sunlance_sbus_match[] = { |
1577 | { | 1538 | { |
1578 | .name = "le", | 1539 | .name = "le", |
1579 | }, | 1540 | }, |
@@ -1593,17 +1554,12 @@ static struct of_platform_driver sunlance_sbus_driver = { | |||
1593 | /* Find all the lance cards on the system and initialize them */ | 1554 | /* Find all the lance cards on the system and initialize them */ |
1594 | static int __init sparc_lance_init(void) | 1555 | static int __init sparc_lance_init(void) |
1595 | { | 1556 | { |
1596 | return of_register_driver(&sunlance_sbus_driver, &sbus_bus_type); | 1557 | return of_register_driver(&sunlance_sbus_driver, &of_bus_type); |
1597 | } | 1558 | } |
1598 | #endif /* !CONFIG_SUN4 */ | ||
1599 | 1559 | ||
1600 | static void __exit sparc_lance_exit(void) | 1560 | static void __exit sparc_lance_exit(void) |
1601 | { | 1561 | { |
1602 | #ifdef CONFIG_SUN4 | ||
1603 | sunlance_sun4_remove(); | ||
1604 | #else | ||
1605 | of_unregister_driver(&sunlance_sbus_driver); | 1562 | of_unregister_driver(&sunlance_sbus_driver); |
1606 | #endif | ||
1607 | } | 1563 | } |
1608 | 1564 | ||
1609 | module_init(sparc_lance_init); | 1565 | module_init(sparc_lance_init); |
diff --git a/drivers/net/sunqe.c b/drivers/net/sunqe.c index e811331d4608..f63644744ff9 100644 --- a/drivers/net/sunqe.c +++ b/drivers/net/sunqe.c | |||
@@ -3,7 +3,7 @@ | |||
3 | * controller out there can be most efficiently programmed | 3 | * controller out there can be most efficiently programmed |
4 | * if you make it look like a LANCE. | 4 | * if you make it look like a LANCE. |
5 | * | 5 | * |
6 | * Copyright (C) 1996, 1999, 2003, 2006 David S. Miller (davem@davemloft.net) | 6 | * Copyright (C) 1996, 1999, 2003, 2006, 2008 David S. Miller (davem@davemloft.net) |
7 | */ | 7 | */ |
8 | 8 | ||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
@@ -24,13 +24,15 @@ | |||
24 | #include <linux/skbuff.h> | 24 | #include <linux/skbuff.h> |
25 | #include <linux/ethtool.h> | 25 | #include <linux/ethtool.h> |
26 | #include <linux/bitops.h> | 26 | #include <linux/bitops.h> |
27 | #include <linux/dma-mapping.h> | ||
28 | #include <linux/of.h> | ||
29 | #include <linux/of_device.h> | ||
27 | 30 | ||
28 | #include <asm/system.h> | 31 | #include <asm/system.h> |
29 | #include <asm/io.h> | 32 | #include <asm/io.h> |
30 | #include <asm/dma.h> | 33 | #include <asm/dma.h> |
31 | #include <asm/byteorder.h> | 34 | #include <asm/byteorder.h> |
32 | #include <asm/idprom.h> | 35 | #include <asm/idprom.h> |
33 | #include <asm/sbus.h> | ||
34 | #include <asm/openprom.h> | 36 | #include <asm/openprom.h> |
35 | #include <asm/oplib.h> | 37 | #include <asm/oplib.h> |
36 | #include <asm/auxio.h> | 38 | #include <asm/auxio.h> |
@@ -40,8 +42,8 @@ | |||
40 | #include "sunqe.h" | 42 | #include "sunqe.h" |
41 | 43 | ||
42 | #define DRV_NAME "sunqe" | 44 | #define DRV_NAME "sunqe" |
43 | #define DRV_VERSION "4.0" | 45 | #define DRV_VERSION "4.1" |
44 | #define DRV_RELDATE "June 23, 2006" | 46 | #define DRV_RELDATE "August 27, 2008" |
45 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" | 47 | #define DRV_AUTHOR "David S. Miller (davem@davemloft.net)" |
46 | 48 | ||
47 | static char version[] = | 49 | static char version[] = |
@@ -690,12 +692,18 @@ static void qe_set_multicast(struct net_device *dev) | |||
690 | /* Ethtool support... */ | 692 | /* Ethtool support... */ |
691 | static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) | 693 | static void qe_get_drvinfo(struct net_device *dev, struct ethtool_drvinfo *info) |
692 | { | 694 | { |
695 | const struct linux_prom_registers *regs; | ||
693 | struct sunqe *qep = dev->priv; | 696 | struct sunqe *qep = dev->priv; |
697 | struct of_device *op; | ||
694 | 698 | ||
695 | strcpy(info->driver, "sunqe"); | 699 | strcpy(info->driver, "sunqe"); |
696 | strcpy(info->version, "3.0"); | 700 | strcpy(info->version, "3.0"); |
697 | sprintf(info->bus_info, "SBUS:%d", | 701 | |
698 | qep->qe_sdev->slot); | 702 | op = qep->op; |
703 | regs = of_get_property(op->node, "reg", NULL); | ||
704 | if (regs) | ||
705 | sprintf(info->bus_info, "SBUS:%d", regs->which_io); | ||
706 | |||
699 | } | 707 | } |
700 | 708 | ||
701 | static u32 qe_get_link(struct net_device *dev) | 709 | static u32 qe_get_link(struct net_device *dev) |
@@ -717,11 +725,11 @@ static const struct ethtool_ops qe_ethtool_ops = { | |||
717 | }; | 725 | }; |
718 | 726 | ||
719 | /* This is only called once at boot time for each card probed. */ | 727 | /* This is only called once at boot time for each card probed. */ |
720 | static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev) | 728 | static void qec_init_once(struct sunqec *qecp, struct of_device *op) |
721 | { | 729 | { |
722 | u8 bsizes = qecp->qec_bursts; | 730 | u8 bsizes = qecp->qec_bursts; |
723 | 731 | ||
724 | if (sbus_can_burst64(qsdev) && (bsizes & DMA_BURST64)) { | 732 | if (sbus_can_burst64() && (bsizes & DMA_BURST64)) { |
725 | sbus_writel(GLOB_CTRL_B64, qecp->gregs + GLOB_CTRL); | 733 | sbus_writel(GLOB_CTRL_B64, qecp->gregs + GLOB_CTRL); |
726 | } else if (bsizes & DMA_BURST32) { | 734 | } else if (bsizes & DMA_BURST32) { |
727 | sbus_writel(GLOB_CTRL_B32, qecp->gregs + GLOB_CTRL); | 735 | sbus_writel(GLOB_CTRL_B32, qecp->gregs + GLOB_CTRL); |
@@ -735,15 +743,15 @@ static inline void qec_init_once(struct sunqec *qecp, struct sbus_dev *qsdev) | |||
735 | sbus_writel(GLOB_PSIZE_2048, qecp->gregs + GLOB_PSIZE); | 743 | sbus_writel(GLOB_PSIZE_2048, qecp->gregs + GLOB_PSIZE); |
736 | 744 | ||
737 | /* Set the local memsize register, divided up to one piece per QE channel. */ | 745 | /* Set the local memsize register, divided up to one piece per QE channel. */ |
738 | sbus_writel((qsdev->reg_addrs[1].reg_size >> 2), | 746 | sbus_writel((resource_size(&op->resource[1]) >> 2), |
739 | qecp->gregs + GLOB_MSIZE); | 747 | qecp->gregs + GLOB_MSIZE); |
740 | 748 | ||
741 | /* Divide up the local QEC memory amongst the 4 QE receiver and | 749 | /* Divide up the local QEC memory amongst the 4 QE receiver and |
742 | * transmitter FIFOs. Basically it is (total / 2 / num_channels). | 750 | * transmitter FIFOs. Basically it is (total / 2 / num_channels). |
743 | */ | 751 | */ |
744 | sbus_writel((qsdev->reg_addrs[1].reg_size >> 2) >> 1, | 752 | sbus_writel((resource_size(&op->resource[1]) >> 2) >> 1, |
745 | qecp->gregs + GLOB_TSIZE); | 753 | qecp->gregs + GLOB_TSIZE); |
746 | sbus_writel((qsdev->reg_addrs[1].reg_size >> 2) >> 1, | 754 | sbus_writel((resource_size(&op->resource[1]) >> 2) >> 1, |
747 | qecp->gregs + GLOB_RSIZE); | 755 | qecp->gregs + GLOB_RSIZE); |
748 | } | 756 | } |
749 | 757 | ||
@@ -767,24 +775,21 @@ static u8 __devinit qec_get_burst(struct device_node *dp) | |||
767 | return bsizes; | 775 | return bsizes; |
768 | } | 776 | } |
769 | 777 | ||
770 | static struct sunqec * __devinit get_qec(struct sbus_dev *child_sdev) | 778 | static struct sunqec * __devinit get_qec(struct of_device *child) |
771 | { | 779 | { |
772 | struct sbus_dev *qec_sdev = child_sdev->parent; | 780 | struct of_device *op = to_of_device(child->dev.parent); |
773 | struct sunqec *qecp; | 781 | struct sunqec *qecp; |
774 | 782 | ||
775 | for (qecp = root_qec_dev; qecp; qecp = qecp->next_module) { | 783 | qecp = dev_get_drvdata(&op->dev); |
776 | if (qecp->qec_sdev == qec_sdev) | ||
777 | break; | ||
778 | } | ||
779 | if (!qecp) { | 784 | if (!qecp) { |
780 | qecp = kzalloc(sizeof(struct sunqec), GFP_KERNEL); | 785 | qecp = kzalloc(sizeof(struct sunqec), GFP_KERNEL); |
781 | if (qecp) { | 786 | if (qecp) { |
782 | u32 ctrl; | 787 | u32 ctrl; |
783 | 788 | ||
784 | qecp->qec_sdev = qec_sdev; | 789 | qecp->op = op; |
785 | qecp->gregs = sbus_ioremap(&qec_sdev->resource[0], 0, | 790 | qecp->gregs = of_ioremap(&op->resource[0], 0, |
786 | GLOB_REG_SIZE, | 791 | GLOB_REG_SIZE, |
787 | "QEC Global Registers"); | 792 | "QEC Global Registers"); |
788 | if (!qecp->gregs) | 793 | if (!qecp->gregs) |
789 | goto fail; | 794 | goto fail; |
790 | 795 | ||
@@ -799,16 +804,18 @@ static struct sunqec * __devinit get_qec(struct sbus_dev *child_sdev) | |||
799 | if (qec_global_reset(qecp->gregs)) | 804 | if (qec_global_reset(qecp->gregs)) |
800 | goto fail; | 805 | goto fail; |
801 | 806 | ||
802 | qecp->qec_bursts = qec_get_burst(qec_sdev->ofdev.node); | 807 | qecp->qec_bursts = qec_get_burst(op->node); |
803 | 808 | ||
804 | qec_init_once(qecp, qec_sdev); | 809 | qec_init_once(qecp, op); |
805 | 810 | ||
806 | if (request_irq(qec_sdev->irqs[0], &qec_interrupt, | 811 | if (request_irq(op->irqs[0], &qec_interrupt, |
807 | IRQF_SHARED, "qec", (void *) qecp)) { | 812 | IRQF_SHARED, "qec", (void *) qecp)) { |
808 | printk(KERN_ERR "qec: Can't register irq.\n"); | 813 | printk(KERN_ERR "qec: Can't register irq.\n"); |
809 | goto fail; | 814 | goto fail; |
810 | } | 815 | } |
811 | 816 | ||
817 | dev_set_drvdata(&op->dev, qecp); | ||
818 | |||
812 | qecp->next_module = root_qec_dev; | 819 | qecp->next_module = root_qec_dev; |
813 | root_qec_dev = qecp; | 820 | root_qec_dev = qecp; |
814 | } | 821 | } |
@@ -818,17 +825,17 @@ static struct sunqec * __devinit get_qec(struct sbus_dev *child_sdev) | |||
818 | 825 | ||
819 | fail: | 826 | fail: |
820 | if (qecp->gregs) | 827 | if (qecp->gregs) |
821 | sbus_iounmap(qecp->gregs, GLOB_REG_SIZE); | 828 | of_iounmap(&op->resource[0], qecp->gregs, GLOB_REG_SIZE); |
822 | kfree(qecp); | 829 | kfree(qecp); |
823 | return NULL; | 830 | return NULL; |
824 | } | 831 | } |
825 | 832 | ||
826 | static int __devinit qec_ether_init(struct sbus_dev *sdev) | 833 | static int __devinit qec_ether_init(struct of_device *op) |
827 | { | 834 | { |
828 | static unsigned version_printed; | 835 | static unsigned version_printed; |
829 | struct net_device *dev; | 836 | struct net_device *dev; |
830 | struct sunqe *qe; | ||
831 | struct sunqec *qecp; | 837 | struct sunqec *qecp; |
838 | struct sunqe *qe; | ||
832 | int i, res; | 839 | int i, res; |
833 | 840 | ||
834 | if (version_printed++ == 0) | 841 | if (version_printed++ == 0) |
@@ -842,49 +849,42 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev) | |||
842 | 849 | ||
843 | qe = netdev_priv(dev); | 850 | qe = netdev_priv(dev); |
844 | 851 | ||
845 | i = of_getintprop_default(sdev->ofdev.node, "channel#", -1); | 852 | res = -ENODEV; |
846 | if (i == -1) { | 853 | |
847 | struct sbus_dev *td = sdev->parent->child; | 854 | i = of_getintprop_default(op->node, "channel#", -1); |
848 | i = 0; | 855 | if (i == -1) |
849 | while (td != sdev) { | 856 | goto fail; |
850 | td = td->next; | ||
851 | i++; | ||
852 | } | ||
853 | } | ||
854 | qe->channel = i; | 857 | qe->channel = i; |
855 | spin_lock_init(&qe->lock); | 858 | spin_lock_init(&qe->lock); |
856 | 859 | ||
857 | res = -ENODEV; | 860 | qecp = get_qec(op); |
858 | qecp = get_qec(sdev); | ||
859 | if (!qecp) | 861 | if (!qecp) |
860 | goto fail; | 862 | goto fail; |
861 | 863 | ||
862 | qecp->qes[qe->channel] = qe; | 864 | qecp->qes[qe->channel] = qe; |
863 | qe->dev = dev; | 865 | qe->dev = dev; |
864 | qe->parent = qecp; | 866 | qe->parent = qecp; |
865 | qe->qe_sdev = sdev; | 867 | qe->op = op; |
866 | 868 | ||
867 | res = -ENOMEM; | 869 | res = -ENOMEM; |
868 | qe->qcregs = sbus_ioremap(&qe->qe_sdev->resource[0], 0, | 870 | qe->qcregs = of_ioremap(&op->resource[0], 0, |
869 | CREG_REG_SIZE, "QEC Channel Registers"); | 871 | CREG_REG_SIZE, "QEC Channel Registers"); |
870 | if (!qe->qcregs) { | 872 | if (!qe->qcregs) { |
871 | printk(KERN_ERR "qe: Cannot map channel registers.\n"); | 873 | printk(KERN_ERR "qe: Cannot map channel registers.\n"); |
872 | goto fail; | 874 | goto fail; |
873 | } | 875 | } |
874 | 876 | ||
875 | qe->mregs = sbus_ioremap(&qe->qe_sdev->resource[1], 0, | 877 | qe->mregs = of_ioremap(&op->resource[1], 0, |
876 | MREGS_REG_SIZE, "QE MACE Registers"); | 878 | MREGS_REG_SIZE, "QE MACE Registers"); |
877 | if (!qe->mregs) { | 879 | if (!qe->mregs) { |
878 | printk(KERN_ERR "qe: Cannot map MACE registers.\n"); | 880 | printk(KERN_ERR "qe: Cannot map MACE registers.\n"); |
879 | goto fail; | 881 | goto fail; |
880 | } | 882 | } |
881 | 883 | ||
882 | qe->qe_block = sbus_alloc_consistent(qe->qe_sdev, | 884 | qe->qe_block = dma_alloc_coherent(&op->dev, PAGE_SIZE, |
883 | PAGE_SIZE, | 885 | &qe->qblock_dvma, GFP_ATOMIC); |
884 | &qe->qblock_dvma); | 886 | qe->buffers = dma_alloc_coherent(&op->dev, sizeof(struct sunqe_buffers), |
885 | qe->buffers = sbus_alloc_consistent(qe->qe_sdev, | 887 | &qe->buffers_dvma, GFP_ATOMIC); |
886 | sizeof(struct sunqe_buffers), | ||
887 | &qe->buffers_dvma); | ||
888 | if (qe->qe_block == NULL || qe->qblock_dvma == 0 || | 888 | if (qe->qe_block == NULL || qe->qblock_dvma == 0 || |
889 | qe->buffers == NULL || qe->buffers_dvma == 0) | 889 | qe->buffers == NULL || qe->buffers_dvma == 0) |
890 | goto fail; | 890 | goto fail; |
@@ -892,7 +892,7 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev) | |||
892 | /* Stop this QE. */ | 892 | /* Stop this QE. */ |
893 | qe_stop(qe); | 893 | qe_stop(qe); |
894 | 894 | ||
895 | SET_NETDEV_DEV(dev, &sdev->ofdev.dev); | 895 | SET_NETDEV_DEV(dev, &op->dev); |
896 | 896 | ||
897 | dev->open = qe_open; | 897 | dev->open = qe_open; |
898 | dev->stop = qe_close; | 898 | dev->stop = qe_close; |
@@ -900,7 +900,7 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev) | |||
900 | dev->set_multicast_list = qe_set_multicast; | 900 | dev->set_multicast_list = qe_set_multicast; |
901 | dev->tx_timeout = qe_tx_timeout; | 901 | dev->tx_timeout = qe_tx_timeout; |
902 | dev->watchdog_timeo = 5*HZ; | 902 | dev->watchdog_timeo = 5*HZ; |
903 | dev->irq = sdev->irqs[0]; | 903 | dev->irq = op->irqs[0]; |
904 | dev->dma = 0; | 904 | dev->dma = 0; |
905 | dev->ethtool_ops = &qe_ethtool_ops; | 905 | dev->ethtool_ops = &qe_ethtool_ops; |
906 | 906 | ||
@@ -908,7 +908,7 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev) | |||
908 | if (res) | 908 | if (res) |
909 | goto fail; | 909 | goto fail; |
910 | 910 | ||
911 | dev_set_drvdata(&sdev->ofdev.dev, qe); | 911 | dev_set_drvdata(&op->dev, qe); |
912 | 912 | ||
913 | printk(KERN_INFO "%s: qe channel[%d] ", dev->name, qe->channel); | 913 | printk(KERN_INFO "%s: qe channel[%d] ", dev->name, qe->channel); |
914 | for (i = 0; i < 6; i++) | 914 | for (i = 0; i < 6; i++) |
@@ -922,58 +922,50 @@ static int __devinit qec_ether_init(struct sbus_dev *sdev) | |||
922 | 922 | ||
923 | fail: | 923 | fail: |
924 | if (qe->qcregs) | 924 | if (qe->qcregs) |
925 | sbus_iounmap(qe->qcregs, CREG_REG_SIZE); | 925 | of_iounmap(&op->resource[0], qe->qcregs, CREG_REG_SIZE); |
926 | if (qe->mregs) | 926 | if (qe->mregs) |
927 | sbus_iounmap(qe->mregs, MREGS_REG_SIZE); | 927 | of_iounmap(&op->resource[1], qe->mregs, MREGS_REG_SIZE); |
928 | if (qe->qe_block) | 928 | if (qe->qe_block) |
929 | sbus_free_consistent(qe->qe_sdev, | 929 | dma_free_coherent(&op->dev, PAGE_SIZE, |
930 | PAGE_SIZE, | 930 | qe->qe_block, qe->qblock_dvma); |
931 | qe->qe_block, | ||
932 | qe->qblock_dvma); | ||
933 | if (qe->buffers) | 931 | if (qe->buffers) |
934 | sbus_free_consistent(qe->qe_sdev, | 932 | dma_free_coherent(&op->dev, |
935 | sizeof(struct sunqe_buffers), | 933 | sizeof(struct sunqe_buffers), |
936 | qe->buffers, | 934 | qe->buffers, |
937 | qe->buffers_dvma); | 935 | qe->buffers_dvma); |
938 | 936 | ||
939 | free_netdev(dev); | 937 | free_netdev(dev); |
940 | 938 | ||
941 | return res; | 939 | return res; |
942 | } | 940 | } |
943 | 941 | ||
944 | static int __devinit qec_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 942 | static int __devinit qec_sbus_probe(struct of_device *op, const struct of_device_id *match) |
945 | { | 943 | { |
946 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | 944 | return qec_ether_init(op); |
947 | |||
948 | return qec_ether_init(sdev); | ||
949 | } | 945 | } |
950 | 946 | ||
951 | static int __devexit qec_sbus_remove(struct of_device *dev) | 947 | static int __devexit qec_sbus_remove(struct of_device *op) |
952 | { | 948 | { |
953 | struct sunqe *qp = dev_get_drvdata(&dev->dev); | 949 | struct sunqe *qp = dev_get_drvdata(&op->dev); |
954 | struct net_device *net_dev = qp->dev; | 950 | struct net_device *net_dev = qp->dev; |
955 | 951 | ||
956 | unregister_netdev(net_dev); | 952 | unregister_netdev(net_dev); |
957 | 953 | ||
958 | sbus_iounmap(qp->qcregs, CREG_REG_SIZE); | 954 | of_iounmap(&op->resource[0], qp->qcregs, CREG_REG_SIZE); |
959 | sbus_iounmap(qp->mregs, MREGS_REG_SIZE); | 955 | of_iounmap(&op->resource[1], qp->mregs, MREGS_REG_SIZE); |
960 | sbus_free_consistent(qp->qe_sdev, | 956 | dma_free_coherent(&op->dev, PAGE_SIZE, |
961 | PAGE_SIZE, | 957 | qp->qe_block, qp->qblock_dvma); |
962 | qp->qe_block, | 958 | dma_free_coherent(&op->dev, sizeof(struct sunqe_buffers), |
963 | qp->qblock_dvma); | 959 | qp->buffers, qp->buffers_dvma); |
964 | sbus_free_consistent(qp->qe_sdev, | ||
965 | sizeof(struct sunqe_buffers), | ||
966 | qp->buffers, | ||
967 | qp->buffers_dvma); | ||
968 | 960 | ||
969 | free_netdev(net_dev); | 961 | free_netdev(net_dev); |
970 | 962 | ||
971 | dev_set_drvdata(&dev->dev, NULL); | 963 | dev_set_drvdata(&op->dev, NULL); |
972 | 964 | ||
973 | return 0; | 965 | return 0; |
974 | } | 966 | } |
975 | 967 | ||
976 | static struct of_device_id qec_sbus_match[] = { | 968 | static const struct of_device_id qec_sbus_match[] = { |
977 | { | 969 | { |
978 | .name = "qe", | 970 | .name = "qe", |
979 | }, | 971 | }, |
@@ -991,7 +983,7 @@ static struct of_platform_driver qec_sbus_driver = { | |||
991 | 983 | ||
992 | static int __init qec_init(void) | 984 | static int __init qec_init(void) |
993 | { | 985 | { |
994 | return of_register_driver(&qec_sbus_driver, &sbus_bus_type); | 986 | return of_register_driver(&qec_sbus_driver, &of_bus_type); |
995 | } | 987 | } |
996 | 988 | ||
997 | static void __exit qec_exit(void) | 989 | static void __exit qec_exit(void) |
@@ -1000,11 +992,11 @@ static void __exit qec_exit(void) | |||
1000 | 992 | ||
1001 | while (root_qec_dev) { | 993 | while (root_qec_dev) { |
1002 | struct sunqec *next = root_qec_dev->next_module; | 994 | struct sunqec *next = root_qec_dev->next_module; |
995 | struct of_device *op = root_qec_dev->op; | ||
1003 | 996 | ||
1004 | free_irq(root_qec_dev->qec_sdev->irqs[0], | 997 | free_irq(op->irqs[0], (void *) root_qec_dev); |
1005 | (void *) root_qec_dev); | 998 | of_iounmap(&op->resource[0], root_qec_dev->gregs, |
1006 | sbus_iounmap(root_qec_dev->gregs, GLOB_REG_SIZE); | 999 | GLOB_REG_SIZE); |
1007 | |||
1008 | kfree(root_qec_dev); | 1000 | kfree(root_qec_dev); |
1009 | 1001 | ||
1010 | root_qec_dev = next; | 1002 | root_qec_dev = next; |
diff --git a/drivers/net/sunqe.h b/drivers/net/sunqe.h index 347c8ddc1592..5813a7b2faa5 100644 --- a/drivers/net/sunqe.h +++ b/drivers/net/sunqe.h | |||
@@ -314,7 +314,7 @@ struct sunqec { | |||
314 | void __iomem *gregs; /* QEC Global Registers */ | 314 | void __iomem *gregs; /* QEC Global Registers */ |
315 | struct sunqe *qes[4]; /* Each child MACE */ | 315 | struct sunqe *qes[4]; /* Each child MACE */ |
316 | unsigned int qec_bursts; /* Support burst sizes */ | 316 | unsigned int qec_bursts; /* Support burst sizes */ |
317 | struct sbus_dev *qec_sdev; /* QEC's SBUS device */ | 317 | struct of_device *op; /* QEC's OF device */ |
318 | struct sunqec *next_module; /* List of all QECs in system */ | 318 | struct sunqec *next_module; /* List of all QECs in system */ |
319 | }; | 319 | }; |
320 | 320 | ||
@@ -342,7 +342,7 @@ struct sunqe { | |||
342 | __u32 buffers_dvma; /* DVMA visible address. */ | 342 | __u32 buffers_dvma; /* DVMA visible address. */ |
343 | struct sunqec *parent; | 343 | struct sunqec *parent; |
344 | u8 mconfig; /* Base MACE mconfig value */ | 344 | u8 mconfig; /* Base MACE mconfig value */ |
345 | struct sbus_dev *qe_sdev; /* QE's SBUS device struct */ | 345 | struct of_device *op; /* QE's OF device struct */ |
346 | struct net_device *dev; /* QE's netdevice struct */ | 346 | struct net_device *dev; /* QE's netdevice struct */ |
347 | int channel; /* Who am I? */ | 347 | int channel; /* Who am I? */ |
348 | }; | 348 | }; |
diff --git a/drivers/net/sunvnet.c b/drivers/net/sunvnet.c index 6415ce15c2ef..a720065553df 100644 --- a/drivers/net/sunvnet.c +++ b/drivers/net/sunvnet.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* sunvnet.c: Sun LDOM Virtual Network Driver. | 1 | /* sunvnet.c: Sun LDOM Virtual Network Driver. |
2 | * | 2 | * |
3 | * Copyright (C) 2007 David S. Miller <davem@davemloft.net> | 3 | * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net> |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/module.h> | 6 | #include <linux/module.h> |
@@ -1260,7 +1260,7 @@ static int vnet_port_remove(struct vio_dev *vdev) | |||
1260 | return 0; | 1260 | return 0; |
1261 | } | 1261 | } |
1262 | 1262 | ||
1263 | static struct vio_device_id vnet_port_match[] = { | 1263 | static const struct vio_device_id vnet_port_match[] = { |
1264 | { | 1264 | { |
1265 | .type = "vnet-port", | 1265 | .type = "vnet-port", |
1266 | }, | 1266 | }, |
diff --git a/drivers/parport/parport_sunbpp.c b/drivers/parport/parport_sunbpp.c index 9d595aa91e46..065f229580d5 100644 --- a/drivers/parport/parport_sunbpp.c +++ b/drivers/parport/parport_sunbpp.c | |||
@@ -26,6 +26,8 @@ | |||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/slab.h> | 27 | #include <linux/slab.h> |
28 | #include <linux/init.h> | 28 | #include <linux/init.h> |
29 | #include <linux/of.h> | ||
30 | #include <linux/of_device.h> | ||
29 | 31 | ||
30 | #include <linux/parport.h> | 32 | #include <linux/parport.h> |
31 | 33 | ||
@@ -34,7 +36,6 @@ | |||
34 | 36 | ||
35 | #include <asm/io.h> | 37 | #include <asm/io.h> |
36 | #include <asm/oplib.h> /* OpenProm Library */ | 38 | #include <asm/oplib.h> /* OpenProm Library */ |
37 | #include <asm/sbus.h> | ||
38 | #include <asm/dma.h> /* BPP uses LSI 64854 for DMA */ | 39 | #include <asm/dma.h> /* BPP uses LSI 64854 for DMA */ |
39 | #include <asm/irq.h> | 40 | #include <asm/irq.h> |
40 | #include <asm/sunbpp.h> | 41 | #include <asm/sunbpp.h> |
@@ -285,38 +286,37 @@ static struct parport_operations parport_sunbpp_ops = | |||
285 | .owner = THIS_MODULE, | 286 | .owner = THIS_MODULE, |
286 | }; | 287 | }; |
287 | 288 | ||
288 | static int __devinit init_one_port(struct sbus_dev *sdev) | 289 | static int __devinit bpp_probe(struct of_device *op, const struct of_device_id *match) |
289 | { | 290 | { |
290 | struct parport *p; | ||
291 | /* at least in theory there may be a "we don't dma" case */ | ||
292 | struct parport_operations *ops; | 291 | struct parport_operations *ops; |
293 | void __iomem *base; | ||
294 | int irq, dma, err = 0, size; | ||
295 | struct bpp_regs __iomem *regs; | 292 | struct bpp_regs __iomem *regs; |
293 | int irq, dma, err = 0, size; | ||
296 | unsigned char value_tcr; | 294 | unsigned char value_tcr; |
295 | void __iomem *base; | ||
296 | struct parport *p; | ||
297 | 297 | ||
298 | irq = sdev->irqs[0]; | 298 | irq = op->irqs[0]; |
299 | base = sbus_ioremap(&sdev->resource[0], 0, | 299 | base = of_ioremap(&op->resource[0], 0, |
300 | sdev->reg_addrs[0].reg_size, | 300 | resource_size(&op->resource[0]), |
301 | "sunbpp"); | 301 | "sunbpp"); |
302 | if (!base) | 302 | if (!base) |
303 | return -ENODEV; | 303 | return -ENODEV; |
304 | 304 | ||
305 | size = sdev->reg_addrs[0].reg_size; | 305 | size = resource_size(&op->resource[0]); |
306 | dma = PARPORT_DMA_NONE; | 306 | dma = PARPORT_DMA_NONE; |
307 | 307 | ||
308 | ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); | 308 | ops = kmalloc(sizeof(struct parport_operations), GFP_KERNEL); |
309 | if (!ops) | 309 | if (!ops) |
310 | goto out_unmap; | 310 | goto out_unmap; |
311 | 311 | ||
312 | memcpy (ops, &parport_sunbpp_ops, sizeof (struct parport_operations)); | 312 | memcpy (ops, &parport_sunbpp_ops, sizeof(struct parport_operations)); |
313 | 313 | ||
314 | dprintk(("register_port\n")); | 314 | dprintk(("register_port\n")); |
315 | if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) | 315 | if (!(p = parport_register_port((unsigned long)base, irq, dma, ops))) |
316 | goto out_free_ops; | 316 | goto out_free_ops; |
317 | 317 | ||
318 | p->size = size; | 318 | p->size = size; |
319 | p->dev = &sdev->ofdev.dev; | 319 | p->dev = &op->dev; |
320 | 320 | ||
321 | if ((err = request_irq(p->irq, parport_irq_handler, | 321 | if ((err = request_irq(p->irq, parport_irq_handler, |
322 | IRQF_SHARED, p->name, p)) != 0) { | 322 | IRQF_SHARED, p->name, p)) != 0) { |
@@ -333,7 +333,7 @@ static int __devinit init_one_port(struct sbus_dev *sdev) | |||
333 | 333 | ||
334 | printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); | 334 | printk(KERN_INFO "%s: sunbpp at 0x%lx\n", p->name, p->base); |
335 | 335 | ||
336 | dev_set_drvdata(&sdev->ofdev.dev, p); | 336 | dev_set_drvdata(&op->dev, p); |
337 | 337 | ||
338 | parport_announce_port(p); | 338 | parport_announce_port(p); |
339 | 339 | ||
@@ -346,21 +346,14 @@ out_free_ops: | |||
346 | kfree(ops); | 346 | kfree(ops); |
347 | 347 | ||
348 | out_unmap: | 348 | out_unmap: |
349 | sbus_iounmap(base, size); | 349 | of_iounmap(&op->resource[0], base, size); |
350 | 350 | ||
351 | return err; | 351 | return err; |
352 | } | 352 | } |
353 | 353 | ||
354 | static int __devinit bpp_probe(struct of_device *dev, const struct of_device_id *match) | 354 | static int __devexit bpp_remove(struct of_device *op) |
355 | { | ||
356 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
357 | |||
358 | return init_one_port(sdev); | ||
359 | } | ||
360 | |||
361 | static int __devexit bpp_remove(struct of_device *dev) | ||
362 | { | 355 | { |
363 | struct parport *p = dev_get_drvdata(&dev->dev); | 356 | struct parport *p = dev_get_drvdata(&op->dev); |
364 | struct parport_operations *ops = p->ops; | 357 | struct parport_operations *ops = p->ops; |
365 | 358 | ||
366 | parport_remove_port(p); | 359 | parport_remove_port(p); |
@@ -370,16 +363,16 @@ static int __devexit bpp_remove(struct of_device *dev) | |||
370 | free_irq(p->irq, p); | 363 | free_irq(p->irq, p); |
371 | } | 364 | } |
372 | 365 | ||
373 | sbus_iounmap((void __iomem *) p->base, p->size); | 366 | of_iounmap(&op->resource[0], (void __iomem *) p->base, p->size); |
374 | parport_put_port(p); | 367 | parport_put_port(p); |
375 | kfree(ops); | 368 | kfree(ops); |
376 | 369 | ||
377 | dev_set_drvdata(&dev->dev, NULL); | 370 | dev_set_drvdata(&op->dev, NULL); |
378 | 371 | ||
379 | return 0; | 372 | return 0; |
380 | } | 373 | } |
381 | 374 | ||
382 | static struct of_device_id bpp_match[] = { | 375 | static const struct of_device_id bpp_match[] = { |
383 | { | 376 | { |
384 | .name = "SUNW,bpp", | 377 | .name = "SUNW,bpp", |
385 | }, | 378 | }, |
@@ -397,7 +390,7 @@ static struct of_platform_driver bpp_sbus_driver = { | |||
397 | 390 | ||
398 | static int __init parport_sunbpp_init(void) | 391 | static int __init parport_sunbpp_init(void) |
399 | { | 392 | { |
400 | return of_register_driver(&bpp_sbus_driver, &sbus_bus_type); | 393 | return of_register_driver(&bpp_sbus_driver, &of_bus_type); |
401 | } | 394 | } |
402 | 395 | ||
403 | static void __exit parport_sunbpp_exit(void) | 396 | static void __exit parport_sunbpp_exit(void) |
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig index 9a9755c92fad..b57fba5c6d02 100644 --- a/drivers/rtc/Kconfig +++ b/drivers/rtc/Kconfig | |||
@@ -329,7 +329,7 @@ comment "Platform RTC drivers" | |||
329 | 329 | ||
330 | config RTC_DRV_CMOS | 330 | config RTC_DRV_CMOS |
331 | tristate "PC-style 'CMOS'" | 331 | tristate "PC-style 'CMOS'" |
332 | depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS | 332 | depends on X86 || ALPHA || ARM || M32R || ATARI || PPC || MIPS || SPARC64 |
333 | default y if X86 | 333 | default y if X86 |
334 | help | 334 | help |
335 | Say "yes" here to get direct support for the real time clock | 335 | Say "yes" here to get direct support for the real time clock |
@@ -406,14 +406,26 @@ config RTC_DRV_M48T86 | |||
406 | will be called rtc-m48t86. | 406 | will be called rtc-m48t86. |
407 | 407 | ||
408 | config RTC_DRV_M48T59 | 408 | config RTC_DRV_M48T59 |
409 | tristate "ST M48T59" | 409 | tristate "ST M48T59/M48T08/M48T02" |
410 | help | 410 | help |
411 | If you say Y here you will get support for the | 411 | If you say Y here you will get support for the |
412 | ST M48T59 RTC chip. | 412 | ST M48T59 RTC chip and compatible ST M48T08 and M48T02. |
413 | |||
414 | These chips are usually found in Sun SPARC and UltraSPARC | ||
415 | workstations. | ||
413 | 416 | ||
414 | This driver can also be built as a module, if so, the module | 417 | This driver can also be built as a module, if so, the module |
415 | will be called "rtc-m48t59". | 418 | will be called "rtc-m48t59". |
416 | 419 | ||
420 | config RTC_DRV_BQ4802 | ||
421 | tristate "TI BQ4802" | ||
422 | help | ||
423 | If you say Y here you will get support for the TI | ||
424 | BQ4802 RTC chip. | ||
425 | |||
426 | This driver can also be built as a module. If so, the module | ||
427 | will be called rtc-bq4802. | ||
428 | |||
417 | config RTC_DRV_V3020 | 429 | config RTC_DRV_V3020 |
418 | tristate "EM Microelectronic V3020" | 430 | tristate "EM Microelectronic V3020" |
419 | help | 431 | help |
@@ -583,4 +595,18 @@ config RTC_DRV_PPC | |||
583 | the RTC. This exposes that functionality through the generic RTC | 595 | the RTC. This exposes that functionality through the generic RTC |
584 | class. | 596 | class. |
585 | 597 | ||
598 | config RTC_DRV_SUN4V | ||
599 | bool "SUN4V Hypervisor RTC" | ||
600 | depends on SPARC64 | ||
601 | help | ||
602 | If you say Y here you will get support for the Hypervisor | ||
603 | based RTC on SUN4V systems. | ||
604 | |||
605 | config RTC_DRV_STARFIRE | ||
606 | bool "Starfire RTC" | ||
607 | depends on SPARC64 | ||
608 | help | ||
609 | If you say Y here you will get support for the RTC found on | ||
610 | Starfire systems. | ||
611 | |||
586 | endif # RTC_CLASS | 612 | endif # RTC_CLASS |
diff --git a/drivers/rtc/Makefile b/drivers/rtc/Makefile index 18622ef84cab..10f41f85c38a 100644 --- a/drivers/rtc/Makefile +++ b/drivers/rtc/Makefile | |||
@@ -38,6 +38,9 @@ obj-$(CONFIG_RTC_DRV_M41T80) += rtc-m41t80.o | |||
38 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o | 38 | obj-$(CONFIG_RTC_DRV_M41T94) += rtc-m41t94.o |
39 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o | 39 | obj-$(CONFIG_RTC_DRV_M48T59) += rtc-m48t59.o |
40 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o | 40 | obj-$(CONFIG_RTC_DRV_M48T86) += rtc-m48t86.o |
41 | obj-$(CONFIG_RTC_DRV_BQ4802) += rtc-bq4802.o | ||
42 | obj-$(CONFIG_RTC_DRV_SUN4V) += rtc-sun4v.o | ||
43 | obj-$(CONFIG_RTC_DRV_STARFIRE) += rtc-starfire.o | ||
41 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o | 44 | obj-$(CONFIG_RTC_DRV_MAX6900) += rtc-max6900.o |
42 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o | 45 | obj-$(CONFIG_RTC_DRV_MAX6902) += rtc-max6902.o |
43 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o | 46 | obj-$(CONFIG_RTC_DRV_OMAP) += rtc-omap.o |
diff --git a/drivers/rtc/rtc-bq4802.c b/drivers/rtc/rtc-bq4802.c new file mode 100644 index 000000000000..189a018bdf34 --- /dev/null +++ b/drivers/rtc/rtc-bq4802.c | |||
@@ -0,0 +1,230 @@ | |||
1 | /* rtc-bq4802.c: TI BQ4802 RTC driver. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/io.h> | ||
10 | #include <linux/platform_device.h> | ||
11 | #include <linux/rtc.h> | ||
12 | #include <linux/bcd.h> | ||
13 | |||
14 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
15 | MODULE_DESCRIPTION("TI BQ4802 RTC driver"); | ||
16 | MODULE_LICENSE("GPL"); | ||
17 | |||
18 | struct bq4802 { | ||
19 | void __iomem *regs; | ||
20 | unsigned long ioport; | ||
21 | struct rtc_device *rtc; | ||
22 | spinlock_t lock; | ||
23 | struct resource *r; | ||
24 | u8 (*read)(struct bq4802 *, int); | ||
25 | void (*write)(struct bq4802 *, int, u8); | ||
26 | }; | ||
27 | |||
28 | static u8 bq4802_read_io(struct bq4802 *p, int off) | ||
29 | { | ||
30 | return inb(p->ioport + off); | ||
31 | } | ||
32 | |||
33 | static void bq4802_write_io(struct bq4802 *p, int off, u8 val) | ||
34 | { | ||
35 | outb(val, p->ioport + off); | ||
36 | } | ||
37 | |||
38 | static u8 bq4802_read_mem(struct bq4802 *p, int off) | ||
39 | { | ||
40 | return readb(p->regs + off); | ||
41 | } | ||
42 | |||
43 | static void bq4802_write_mem(struct bq4802 *p, int off, u8 val) | ||
44 | { | ||
45 | writeb(val, p->regs + off); | ||
46 | } | ||
47 | |||
48 | static int bq4802_read_time(struct device *dev, struct rtc_time *tm) | ||
49 | { | ||
50 | struct platform_device *pdev = to_platform_device(dev); | ||
51 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
52 | unsigned long flags; | ||
53 | unsigned int century; | ||
54 | u8 val; | ||
55 | |||
56 | spin_lock_irqsave(&p->lock, flags); | ||
57 | |||
58 | val = p->read(p, 0x0e); | ||
59 | p->write(p, 0xe, val | 0x08); | ||
60 | |||
61 | tm->tm_sec = p->read(p, 0x00); | ||
62 | tm->tm_min = p->read(p, 0x02); | ||
63 | tm->tm_hour = p->read(p, 0x04); | ||
64 | tm->tm_mday = p->read(p, 0x06); | ||
65 | tm->tm_mon = p->read(p, 0x09); | ||
66 | tm->tm_year = p->read(p, 0x0a); | ||
67 | tm->tm_wday = p->read(p, 0x08); | ||
68 | century = p->read(p, 0x0f); | ||
69 | |||
70 | p->write(p, 0x0e, val); | ||
71 | |||
72 | spin_unlock_irqrestore(&p->lock, flags); | ||
73 | |||
74 | BCD_TO_BIN(tm->tm_sec); | ||
75 | BCD_TO_BIN(tm->tm_min); | ||
76 | BCD_TO_BIN(tm->tm_hour); | ||
77 | BCD_TO_BIN(tm->tm_mday); | ||
78 | BCD_TO_BIN(tm->tm_mon); | ||
79 | BCD_TO_BIN(tm->tm_year); | ||
80 | BCD_TO_BIN(tm->tm_wday); | ||
81 | BCD_TO_BIN(century); | ||
82 | |||
83 | tm->tm_year += (century * 100); | ||
84 | tm->tm_year -= 1900; | ||
85 | |||
86 | tm->tm_mon--; | ||
87 | |||
88 | return 0; | ||
89 | } | ||
90 | |||
91 | static int bq4802_set_time(struct device *dev, struct rtc_time *tm) | ||
92 | { | ||
93 | struct platform_device *pdev = to_platform_device(dev); | ||
94 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
95 | u8 sec, min, hrs, day, mon, yrs, century, val; | ||
96 | unsigned long flags; | ||
97 | unsigned int year; | ||
98 | |||
99 | year = tm->tm_year + 1900; | ||
100 | century = year / 100; | ||
101 | yrs = year % 100; | ||
102 | |||
103 | mon = tm->tm_mon + 1; /* tm_mon starts at zero */ | ||
104 | day = tm->tm_mday; | ||
105 | hrs = tm->tm_hour; | ||
106 | min = tm->tm_min; | ||
107 | sec = tm->tm_sec; | ||
108 | |||
109 | BIN_TO_BCD(sec); | ||
110 | BIN_TO_BCD(min); | ||
111 | BIN_TO_BCD(hrs); | ||
112 | BIN_TO_BCD(day); | ||
113 | BIN_TO_BCD(mon); | ||
114 | BIN_TO_BCD(yrs); | ||
115 | BIN_TO_BCD(century); | ||
116 | |||
117 | spin_lock_irqsave(&p->lock, flags); | ||
118 | |||
119 | val = p->read(p, 0x0e); | ||
120 | p->write(p, 0x0e, val | 0x08); | ||
121 | |||
122 | p->write(p, 0x00, sec); | ||
123 | p->write(p, 0x02, min); | ||
124 | p->write(p, 0x04, hrs); | ||
125 | p->write(p, 0x06, day); | ||
126 | p->write(p, 0x09, mon); | ||
127 | p->write(p, 0x0a, yrs); | ||
128 | p->write(p, 0x0f, century); | ||
129 | |||
130 | p->write(p, 0x0e, val); | ||
131 | |||
132 | spin_unlock_irqrestore(&p->lock, flags); | ||
133 | |||
134 | return 0; | ||
135 | } | ||
136 | |||
137 | static const struct rtc_class_ops bq4802_ops = { | ||
138 | .read_time = bq4802_read_time, | ||
139 | .set_time = bq4802_set_time, | ||
140 | }; | ||
141 | |||
142 | static int __devinit bq4802_probe(struct platform_device *pdev) | ||
143 | { | ||
144 | struct bq4802 *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
145 | int err = -ENOMEM; | ||
146 | |||
147 | if (!p) | ||
148 | goto out; | ||
149 | |||
150 | spin_lock_init(&p->lock); | ||
151 | |||
152 | p->r = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
153 | if (!p->r) { | ||
154 | p->r = platform_get_resource(pdev, IORESOURCE_IO, 0); | ||
155 | err = -EINVAL; | ||
156 | if (!p->r) | ||
157 | goto out_free; | ||
158 | } | ||
159 | if (p->r->flags & IORESOURCE_IO) { | ||
160 | p->ioport = p->r->start; | ||
161 | p->read = bq4802_read_io; | ||
162 | p->write = bq4802_write_io; | ||
163 | } else if (p->r->flags & IORESOURCE_MEM) { | ||
164 | p->regs = ioremap(p->r->start, resource_size(p->r)); | ||
165 | p->read = bq4802_read_mem; | ||
166 | p->write = bq4802_write_mem; | ||
167 | } else { | ||
168 | err = -EINVAL; | ||
169 | goto out_free; | ||
170 | } | ||
171 | |||
172 | p->rtc = rtc_device_register("bq4802", &pdev->dev, | ||
173 | &bq4802_ops, THIS_MODULE); | ||
174 | if (IS_ERR(p->rtc)) { | ||
175 | err = PTR_ERR(p->rtc); | ||
176 | goto out_iounmap; | ||
177 | } | ||
178 | |||
179 | platform_set_drvdata(pdev, p); | ||
180 | err = 0; | ||
181 | out: | ||
182 | return err; | ||
183 | |||
184 | out_iounmap: | ||
185 | if (p->r->flags & IORESOURCE_MEM) | ||
186 | iounmap(p->regs); | ||
187 | out_free: | ||
188 | kfree(p); | ||
189 | goto out; | ||
190 | } | ||
191 | |||
192 | static int __devexit bq4802_remove(struct platform_device *pdev) | ||
193 | { | ||
194 | struct bq4802 *p = platform_get_drvdata(pdev); | ||
195 | |||
196 | rtc_device_unregister(p->rtc); | ||
197 | if (p->r->flags & IORESOURCE_MEM) | ||
198 | iounmap(p->regs); | ||
199 | |||
200 | platform_set_drvdata(pdev, NULL); | ||
201 | |||
202 | kfree(p); | ||
203 | |||
204 | return 0; | ||
205 | } | ||
206 | |||
207 | /* work with hotplug and coldplug */ | ||
208 | MODULE_ALIAS("platform:rtc-bq4802"); | ||
209 | |||
210 | static struct platform_driver bq4802_driver = { | ||
211 | .driver = { | ||
212 | .name = "rtc-bq4802", | ||
213 | .owner = THIS_MODULE, | ||
214 | }, | ||
215 | .probe = bq4802_probe, | ||
216 | .remove = __devexit_p(bq4802_remove), | ||
217 | }; | ||
218 | |||
219 | static int __init bq4802_init(void) | ||
220 | { | ||
221 | return platform_driver_register(&bq4802_driver); | ||
222 | } | ||
223 | |||
224 | static void __exit bq4802_exit(void) | ||
225 | { | ||
226 | platform_driver_unregister(&bq4802_driver); | ||
227 | } | ||
228 | |||
229 | module_init(bq4802_init); | ||
230 | module_exit(bq4802_exit); | ||
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c index b184367637d0..b23af0c2a869 100644 --- a/drivers/rtc/rtc-cmos.c +++ b/drivers/rtc/rtc-cmos.c | |||
@@ -636,7 +636,7 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
636 | */ | 636 | */ |
637 | #if defined(CONFIG_ATARI) | 637 | #if defined(CONFIG_ATARI) |
638 | address_space = 64; | 638 | address_space = 64; |
639 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) | 639 | #elif defined(__i386__) || defined(__x86_64__) || defined(__arm__) || defined(__sparc__) |
640 | address_space = 128; | 640 | address_space = 128; |
641 | #else | 641 | #else |
642 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. | 642 | #warning Assuming 128 bytes of RTC+NVRAM address space, not 64 bytes. |
@@ -699,7 +699,8 @@ cmos_do_probe(struct device *dev, struct resource *ports, int rtc_irq) | |||
699 | /* FIXME teach the alarm code how to handle binary mode; | 699 | /* FIXME teach the alarm code how to handle binary mode; |
700 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. | 700 | * <asm-generic/rtc.h> doesn't know 12-hour mode either. |
701 | */ | 701 | */ |
702 | if (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY))) { | 702 | if (is_valid_irq(rtc_irq) && |
703 | (!(rtc_control & RTC_24H) || (rtc_control & (RTC_DM_BINARY)))) { | ||
703 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); | 704 | dev_dbg(dev, "only 24-hr BCD mode supported\n"); |
704 | retval = -ENXIO; | 705 | retval = -ENXIO; |
705 | goto cleanup1; | 706 | goto cleanup1; |
diff --git a/drivers/rtc/rtc-m48t59.c b/drivers/rtc/rtc-m48t59.c index 013e6c103b9c..ce4eff6a8d51 100644 --- a/drivers/rtc/rtc-m48t59.c +++ b/drivers/rtc/rtc-m48t59.c | |||
@@ -24,8 +24,9 @@ | |||
24 | #define NO_IRQ (-1) | 24 | #define NO_IRQ (-1) |
25 | #endif | 25 | #endif |
26 | 26 | ||
27 | #define M48T59_READ(reg) pdata->read_byte(dev, reg) | 27 | #define M48T59_READ(reg) (pdata->read_byte(dev, pdata->offset + reg)) |
28 | #define M48T59_WRITE(val, reg) pdata->write_byte(dev, reg, val) | 28 | #define M48T59_WRITE(val, reg) \ |
29 | (pdata->write_byte(dev, pdata->offset + reg, val)) | ||
29 | 30 | ||
30 | #define M48T59_SET_BITS(mask, reg) \ | 31 | #define M48T59_SET_BITS(mask, reg) \ |
31 | M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) | 32 | M48T59_WRITE((M48T59_READ(reg) | (mask)), (reg)) |
@@ -34,7 +35,6 @@ | |||
34 | 35 | ||
35 | struct m48t59_private { | 36 | struct m48t59_private { |
36 | void __iomem *ioaddr; | 37 | void __iomem *ioaddr; |
37 | unsigned int size; /* iomem size */ | ||
38 | int irq; | 38 | int irq; |
39 | struct rtc_device *rtc; | 39 | struct rtc_device *rtc; |
40 | spinlock_t lock; /* serialize the NVRAM and RTC access */ | 40 | spinlock_t lock; /* serialize the NVRAM and RTC access */ |
@@ -82,7 +82,8 @@ static int m48t59_rtc_read_time(struct device *dev, struct rtc_time *tm) | |||
82 | tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); | 82 | tm->tm_mday = BCD2BIN(M48T59_READ(M48T59_MDAY)); |
83 | 83 | ||
84 | val = M48T59_READ(M48T59_WDAY); | 84 | val = M48T59_READ(M48T59_WDAY); |
85 | if ((val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { | 85 | if ((pdata->type == M48T59RTC_TYPE_M48T59) && |
86 | (val & M48T59_WDAY_CEB) && (val & M48T59_WDAY_CB)) { | ||
86 | dev_dbg(dev, "Century bit is enabled\n"); | 87 | dev_dbg(dev, "Century bit is enabled\n"); |
87 | tm->tm_year += 100; /* one century */ | 88 | tm->tm_year += 100; /* one century */ |
88 | } | 89 | } |
@@ -126,7 +127,7 @@ static int m48t59_rtc_set_time(struct device *dev, struct rtc_time *tm) | |||
126 | M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); | 127 | M48T59_WRITE((BIN2BCD(tm->tm_mon + 1) & 0x1F), M48T59_MONTH); |
127 | M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); | 128 | M48T59_WRITE(BIN2BCD(tm->tm_year % 100), M48T59_YEAR); |
128 | 129 | ||
129 | if (tm->tm_year/100) | 130 | if (pdata->type == M48T59RTC_TYPE_M48T59 && (tm->tm_year / 100)) |
130 | val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); | 131 | val = (M48T59_WDAY_CEB | M48T59_WDAY_CB); |
131 | val |= (BIN2BCD(tm->tm_wday) & 0x07); | 132 | val |= (BIN2BCD(tm->tm_wday) & 0x07); |
132 | M48T59_WRITE(val, M48T59_WDAY); | 133 | M48T59_WRITE(val, M48T59_WDAY); |
@@ -310,6 +311,11 @@ static const struct rtc_class_ops m48t59_rtc_ops = { | |||
310 | .proc = m48t59_rtc_proc, | 311 | .proc = m48t59_rtc_proc, |
311 | }; | 312 | }; |
312 | 313 | ||
314 | static const struct rtc_class_ops m48t02_rtc_ops = { | ||
315 | .read_time = m48t59_rtc_read_time, | ||
316 | .set_time = m48t59_rtc_set_time, | ||
317 | }; | ||
318 | |||
313 | static ssize_t m48t59_nvram_read(struct kobject *kobj, | 319 | static ssize_t m48t59_nvram_read(struct kobject *kobj, |
314 | struct bin_attribute *bin_attr, | 320 | struct bin_attribute *bin_attr, |
315 | char *buf, loff_t pos, size_t size) | 321 | char *buf, loff_t pos, size_t size) |
@@ -321,7 +327,7 @@ static ssize_t m48t59_nvram_read(struct kobject *kobj, | |||
321 | ssize_t cnt = 0; | 327 | ssize_t cnt = 0; |
322 | unsigned long flags; | 328 | unsigned long flags; |
323 | 329 | ||
324 | for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { | 330 | for (; size > 0 && pos < pdata->offset; cnt++, size--) { |
325 | spin_lock_irqsave(&m48t59->lock, flags); | 331 | spin_lock_irqsave(&m48t59->lock, flags); |
326 | *buf++ = M48T59_READ(cnt); | 332 | *buf++ = M48T59_READ(cnt); |
327 | spin_unlock_irqrestore(&m48t59->lock, flags); | 333 | spin_unlock_irqrestore(&m48t59->lock, flags); |
@@ -341,7 +347,7 @@ static ssize_t m48t59_nvram_write(struct kobject *kobj, | |||
341 | ssize_t cnt = 0; | 347 | ssize_t cnt = 0; |
342 | unsigned long flags; | 348 | unsigned long flags; |
343 | 349 | ||
344 | for (; size > 0 && pos < M48T59_NVRAM_SIZE; cnt++, size--) { | 350 | for (; size > 0 && pos < pdata->offset; cnt++, size--) { |
345 | spin_lock_irqsave(&m48t59->lock, flags); | 351 | spin_lock_irqsave(&m48t59->lock, flags); |
346 | M48T59_WRITE(*buf++, cnt); | 352 | M48T59_WRITE(*buf++, cnt); |
347 | spin_unlock_irqrestore(&m48t59->lock, flags); | 353 | spin_unlock_irqrestore(&m48t59->lock, flags); |
@@ -358,7 +364,6 @@ static struct bin_attribute m48t59_nvram_attr = { | |||
358 | }, | 364 | }, |
359 | .read = m48t59_nvram_read, | 365 | .read = m48t59_nvram_read, |
360 | .write = m48t59_nvram_write, | 366 | .write = m48t59_nvram_write, |
361 | .size = M48T59_NVRAM_SIZE, | ||
362 | }; | 367 | }; |
363 | 368 | ||
364 | static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | 369 | static int __devinit m48t59_rtc_probe(struct platform_device *pdev) |
@@ -367,6 +372,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
367 | struct m48t59_private *m48t59 = NULL; | 372 | struct m48t59_private *m48t59 = NULL; |
368 | struct resource *res; | 373 | struct resource *res; |
369 | int ret = -ENOMEM; | 374 | int ret = -ENOMEM; |
375 | char *name; | ||
376 | const struct rtc_class_ops *ops; | ||
370 | 377 | ||
371 | /* This chip could be memory-mapped or I/O-mapped */ | 378 | /* This chip could be memory-mapped or I/O-mapped */ |
372 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 379 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
@@ -391,6 +398,8 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
391 | /* Ensure we only kmalloc platform data once */ | 398 | /* Ensure we only kmalloc platform data once */ |
392 | pdev->dev.platform_data = pdata; | 399 | pdev->dev.platform_data = pdata; |
393 | } | 400 | } |
401 | if (!pdata->type) | ||
402 | pdata->type = M48T59RTC_TYPE_M48T59; | ||
394 | 403 | ||
395 | /* Try to use the generic memory read/write ops */ | 404 | /* Try to use the generic memory read/write ops */ |
396 | if (!pdata->write_byte) | 405 | if (!pdata->write_byte) |
@@ -403,10 +412,14 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
403 | if (!m48t59) | 412 | if (!m48t59) |
404 | return -ENOMEM; | 413 | return -ENOMEM; |
405 | 414 | ||
406 | m48t59->size = res->end - res->start + 1; | 415 | m48t59->ioaddr = pdata->ioaddr; |
407 | m48t59->ioaddr = ioremap(res->start, m48t59->size); | 416 | |
408 | if (!m48t59->ioaddr) | 417 | if (!m48t59->ioaddr) { |
409 | goto out; | 418 | /* ioaddr not mapped externally */ |
419 | m48t59->ioaddr = ioremap(res->start, res->end - res->start + 1); | ||
420 | if (!m48t59->ioaddr) | ||
421 | goto out; | ||
422 | } | ||
410 | 423 | ||
411 | /* Try to get irq number. We also can work in | 424 | /* Try to get irq number. We also can work in |
412 | * the mode without IRQ. | 425 | * the mode without IRQ. |
@@ -421,14 +434,36 @@ static int __devinit m48t59_rtc_probe(struct platform_device *pdev) | |||
421 | if (ret) | 434 | if (ret) |
422 | goto out; | 435 | goto out; |
423 | } | 436 | } |
437 | switch (pdata->type) { | ||
438 | case M48T59RTC_TYPE_M48T59: | ||
439 | name = "m48t59"; | ||
440 | ops = &m48t59_rtc_ops; | ||
441 | pdata->offset = 0x1ff0; | ||
442 | break; | ||
443 | case M48T59RTC_TYPE_M48T02: | ||
444 | name = "m48t02"; | ||
445 | ops = &m48t02_rtc_ops; | ||
446 | pdata->offset = 0x7f0; | ||
447 | break; | ||
448 | case M48T59RTC_TYPE_M48T08: | ||
449 | name = "m48t08"; | ||
450 | ops = &m48t02_rtc_ops; | ||
451 | pdata->offset = 0x1ff0; | ||
452 | break; | ||
453 | default: | ||
454 | dev_err(&pdev->dev, "Unknown RTC type\n"); | ||
455 | ret = -ENODEV; | ||
456 | goto out; | ||
457 | } | ||
424 | 458 | ||
425 | m48t59->rtc = rtc_device_register("m48t59", &pdev->dev, | 459 | m48t59->rtc = rtc_device_register(name, &pdev->dev, ops, THIS_MODULE); |
426 | &m48t59_rtc_ops, THIS_MODULE); | ||
427 | if (IS_ERR(m48t59->rtc)) { | 460 | if (IS_ERR(m48t59->rtc)) { |
428 | ret = PTR_ERR(m48t59->rtc); | 461 | ret = PTR_ERR(m48t59->rtc); |
429 | goto out; | 462 | goto out; |
430 | } | 463 | } |
431 | 464 | ||
465 | m48t59_nvram_attr.size = pdata->offset; | ||
466 | |||
432 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 467 | ret = sysfs_create_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
433 | if (ret) | 468 | if (ret) |
434 | goto out; | 469 | goto out; |
@@ -452,11 +487,12 @@ out: | |||
452 | static int __devexit m48t59_rtc_remove(struct platform_device *pdev) | 487 | static int __devexit m48t59_rtc_remove(struct platform_device *pdev) |
453 | { | 488 | { |
454 | struct m48t59_private *m48t59 = platform_get_drvdata(pdev); | 489 | struct m48t59_private *m48t59 = platform_get_drvdata(pdev); |
490 | struct m48t59_plat_data *pdata = pdev->dev.platform_data; | ||
455 | 491 | ||
456 | sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); | 492 | sysfs_remove_bin_file(&pdev->dev.kobj, &m48t59_nvram_attr); |
457 | if (!IS_ERR(m48t59->rtc)) | 493 | if (!IS_ERR(m48t59->rtc)) |
458 | rtc_device_unregister(m48t59->rtc); | 494 | rtc_device_unregister(m48t59->rtc); |
459 | if (m48t59->ioaddr) | 495 | if (m48t59->ioaddr && !pdata->ioaddr) |
460 | iounmap(m48t59->ioaddr); | 496 | iounmap(m48t59->ioaddr); |
461 | if (m48t59->irq != NO_IRQ) | 497 | if (m48t59->irq != NO_IRQ) |
462 | free_irq(m48t59->irq, &pdev->dev); | 498 | free_irq(m48t59->irq, &pdev->dev); |
@@ -491,5 +527,5 @@ module_init(m48t59_rtc_init); | |||
491 | module_exit(m48t59_rtc_exit); | 527 | module_exit(m48t59_rtc_exit); |
492 | 528 | ||
493 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); | 529 | MODULE_AUTHOR("Mark Zhan <rongkai.zhan@windriver.com>"); |
494 | MODULE_DESCRIPTION("M48T59 RTC driver"); | 530 | MODULE_DESCRIPTION("M48T59/M48T02/M48T08 RTC driver"); |
495 | MODULE_LICENSE("GPL"); | 531 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/rtc/rtc-starfire.c b/drivers/rtc/rtc-starfire.c new file mode 100644 index 000000000000..7ccb0dd700af --- /dev/null +++ b/drivers/rtc/rtc-starfire.c | |||
@@ -0,0 +1,120 @@ | |||
1 | /* rtc-starfire.c: Starfire platform RTC driver. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/time.h> | ||
10 | #include <linux/rtc.h> | ||
11 | #include <linux/platform_device.h> | ||
12 | |||
13 | #include <asm/oplib.h> | ||
14 | |||
15 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
16 | MODULE_DESCRIPTION("Starfire RTC driver"); | ||
17 | MODULE_LICENSE("GPL"); | ||
18 | |||
19 | struct starfire_rtc { | ||
20 | struct rtc_device *rtc; | ||
21 | spinlock_t lock; | ||
22 | }; | ||
23 | |||
24 | static u32 starfire_get_time(void) | ||
25 | { | ||
26 | static char obp_gettod[32]; | ||
27 | static u32 unix_tod; | ||
28 | |||
29 | sprintf(obp_gettod, "h# %08x unix-gettod", | ||
30 | (unsigned int) (long) &unix_tod); | ||
31 | prom_feval(obp_gettod); | ||
32 | |||
33 | return unix_tod; | ||
34 | } | ||
35 | |||
36 | static int starfire_read_time(struct device *dev, struct rtc_time *tm) | ||
37 | { | ||
38 | struct starfire_rtc *p = dev_get_drvdata(dev); | ||
39 | unsigned long flags, secs; | ||
40 | |||
41 | spin_lock_irqsave(&p->lock, flags); | ||
42 | secs = starfire_get_time(); | ||
43 | spin_unlock_irqrestore(&p->lock, flags); | ||
44 | |||
45 | rtc_time_to_tm(secs, tm); | ||
46 | |||
47 | return 0; | ||
48 | } | ||
49 | |||
50 | static int starfire_set_time(struct device *dev, struct rtc_time *tm) | ||
51 | { | ||
52 | unsigned long secs; | ||
53 | int err; | ||
54 | |||
55 | err = rtc_tm_to_time(tm, &secs); | ||
56 | if (err) | ||
57 | return err; | ||
58 | |||
59 | /* Do nothing, time is set using the service processor | ||
60 | * console on this platform. | ||
61 | */ | ||
62 | return 0; | ||
63 | } | ||
64 | |||
65 | static const struct rtc_class_ops starfire_rtc_ops = { | ||
66 | .read_time = starfire_read_time, | ||
67 | .set_time = starfire_set_time, | ||
68 | }; | ||
69 | |||
70 | static int __devinit starfire_rtc_probe(struct platform_device *pdev) | ||
71 | { | ||
72 | struct starfire_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
73 | |||
74 | if (!p) | ||
75 | return -ENOMEM; | ||
76 | |||
77 | spin_lock_init(&p->lock); | ||
78 | |||
79 | p->rtc = rtc_device_register("starfire", &pdev->dev, | ||
80 | &starfire_rtc_ops, THIS_MODULE); | ||
81 | if (IS_ERR(p->rtc)) { | ||
82 | int err = PTR_ERR(p->rtc); | ||
83 | kfree(p); | ||
84 | return err; | ||
85 | } | ||
86 | platform_set_drvdata(pdev, p); | ||
87 | return 0; | ||
88 | } | ||
89 | |||
90 | static int __devexit starfire_rtc_remove(struct platform_device *pdev) | ||
91 | { | ||
92 | struct starfire_rtc *p = platform_get_drvdata(pdev); | ||
93 | |||
94 | rtc_device_unregister(p->rtc); | ||
95 | kfree(p); | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
100 | static struct platform_driver starfire_rtc_driver = { | ||
101 | .driver = { | ||
102 | .name = "rtc-starfire", | ||
103 | .owner = THIS_MODULE, | ||
104 | }, | ||
105 | .probe = starfire_rtc_probe, | ||
106 | .remove = __devexit_p(starfire_rtc_remove), | ||
107 | }; | ||
108 | |||
109 | static int __init starfire_rtc_init(void) | ||
110 | { | ||
111 | return platform_driver_register(&starfire_rtc_driver); | ||
112 | } | ||
113 | |||
114 | static void __exit starfire_rtc_exit(void) | ||
115 | { | ||
116 | platform_driver_unregister(&starfire_rtc_driver); | ||
117 | } | ||
118 | |||
119 | module_init(starfire_rtc_init); | ||
120 | module_exit(starfire_rtc_exit); | ||
diff --git a/drivers/rtc/rtc-sun4v.c b/drivers/rtc/rtc-sun4v.c new file mode 100644 index 000000000000..2012ccbb4a53 --- /dev/null +++ b/drivers/rtc/rtc-sun4v.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* rtc-sun4c.c: Hypervisor based RTC for SUN4V systems. | ||
2 | * | ||
3 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/module.h> | ||
8 | #include <linux/delay.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/time.h> | ||
11 | #include <linux/rtc.h> | ||
12 | #include <linux/platform_device.h> | ||
13 | |||
14 | #include <asm/hypervisor.h> | ||
15 | |||
16 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); | ||
17 | MODULE_DESCRIPTION("SUN4V RTC driver"); | ||
18 | MODULE_LICENSE("GPL"); | ||
19 | |||
20 | struct sun4v_rtc { | ||
21 | struct rtc_device *rtc; | ||
22 | spinlock_t lock; | ||
23 | }; | ||
24 | |||
25 | static unsigned long hypervisor_get_time(void) | ||
26 | { | ||
27 | unsigned long ret, time; | ||
28 | int retries = 10000; | ||
29 | |||
30 | retry: | ||
31 | ret = sun4v_tod_get(&time); | ||
32 | if (ret == HV_EOK) | ||
33 | return time; | ||
34 | if (ret == HV_EWOULDBLOCK) { | ||
35 | if (--retries > 0) { | ||
36 | udelay(100); | ||
37 | goto retry; | ||
38 | } | ||
39 | printk(KERN_WARNING "SUN4V: tod_get() timed out.\n"); | ||
40 | return 0; | ||
41 | } | ||
42 | printk(KERN_WARNING "SUN4V: tod_get() not supported.\n"); | ||
43 | return 0; | ||
44 | } | ||
45 | |||
46 | static int sun4v_read_time(struct device *dev, struct rtc_time *tm) | ||
47 | { | ||
48 | struct sun4v_rtc *p = dev_get_drvdata(dev); | ||
49 | unsigned long flags, secs; | ||
50 | |||
51 | spin_lock_irqsave(&p->lock, flags); | ||
52 | secs = hypervisor_get_time(); | ||
53 | spin_unlock_irqrestore(&p->lock, flags); | ||
54 | |||
55 | rtc_time_to_tm(secs, tm); | ||
56 | |||
57 | return 0; | ||
58 | } | ||
59 | |||
60 | static int hypervisor_set_time(unsigned long secs) | ||
61 | { | ||
62 | unsigned long ret; | ||
63 | int retries = 10000; | ||
64 | |||
65 | retry: | ||
66 | ret = sun4v_tod_set(secs); | ||
67 | if (ret == HV_EOK) | ||
68 | return 0; | ||
69 | if (ret == HV_EWOULDBLOCK) { | ||
70 | if (--retries > 0) { | ||
71 | udelay(100); | ||
72 | goto retry; | ||
73 | } | ||
74 | printk(KERN_WARNING "SUN4V: tod_set() timed out.\n"); | ||
75 | return -EAGAIN; | ||
76 | } | ||
77 | printk(KERN_WARNING "SUN4V: tod_set() not supported.\n"); | ||
78 | return -EOPNOTSUPP; | ||
79 | } | ||
80 | |||
81 | static int sun4v_set_time(struct device *dev, struct rtc_time *tm) | ||
82 | { | ||
83 | struct sun4v_rtc *p = dev_get_drvdata(dev); | ||
84 | unsigned long flags, secs; | ||
85 | int err; | ||
86 | |||
87 | err = rtc_tm_to_time(tm, &secs); | ||
88 | if (err) | ||
89 | return err; | ||
90 | |||
91 | spin_lock_irqsave(&p->lock, flags); | ||
92 | err = hypervisor_set_time(secs); | ||
93 | spin_unlock_irqrestore(&p->lock, flags); | ||
94 | |||
95 | return err; | ||
96 | } | ||
97 | |||
98 | static const struct rtc_class_ops sun4v_rtc_ops = { | ||
99 | .read_time = sun4v_read_time, | ||
100 | .set_time = sun4v_set_time, | ||
101 | }; | ||
102 | |||
103 | static int __devinit sun4v_rtc_probe(struct platform_device *pdev) | ||
104 | { | ||
105 | struct sun4v_rtc *p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
106 | |||
107 | if (!p) | ||
108 | return -ENOMEM; | ||
109 | |||
110 | spin_lock_init(&p->lock); | ||
111 | |||
112 | p->rtc = rtc_device_register("sun4v", &pdev->dev, | ||
113 | &sun4v_rtc_ops, THIS_MODULE); | ||
114 | if (IS_ERR(p->rtc)) { | ||
115 | int err = PTR_ERR(p->rtc); | ||
116 | kfree(p); | ||
117 | return err; | ||
118 | } | ||
119 | platform_set_drvdata(pdev, p); | ||
120 | return 0; | ||
121 | } | ||
122 | |||
123 | static int __devexit sun4v_rtc_remove(struct platform_device *pdev) | ||
124 | { | ||
125 | struct sun4v_rtc *p = platform_get_drvdata(pdev); | ||
126 | |||
127 | rtc_device_unregister(p->rtc); | ||
128 | kfree(p); | ||
129 | |||
130 | return 0; | ||
131 | } | ||
132 | |||
133 | static struct platform_driver sun4v_rtc_driver = { | ||
134 | .driver = { | ||
135 | .name = "rtc-sun4v", | ||
136 | .owner = THIS_MODULE, | ||
137 | }, | ||
138 | .probe = sun4v_rtc_probe, | ||
139 | .remove = __devexit_p(sun4v_rtc_remove), | ||
140 | }; | ||
141 | |||
142 | static int __init sun4v_rtc_init(void) | ||
143 | { | ||
144 | return platform_driver_register(&sun4v_rtc_driver); | ||
145 | } | ||
146 | |||
147 | static void __exit sun4v_rtc_exit(void) | ||
148 | { | ||
149 | platform_driver_unregister(&sun4v_rtc_driver); | ||
150 | } | ||
151 | |||
152 | module_init(sun4v_rtc_init); | ||
153 | module_exit(sun4v_rtc_exit); | ||
diff --git a/drivers/sbus/Makefile b/drivers/sbus/Makefile index 7b1d24d95308..e94dc25805f9 100644 --- a/drivers/sbus/Makefile +++ b/drivers/sbus/Makefile | |||
@@ -2,8 +2,4 @@ | |||
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | ifneq ($(ARCH),m68k) | ||
6 | obj-y := sbus.o dvma.o | ||
7 | endif | ||
8 | |||
9 | obj-$(CONFIG_SBUSCHAR) += char/ | 5 | obj-$(CONFIG_SBUSCHAR) += char/ |
diff --git a/drivers/sbus/char/Kconfig b/drivers/sbus/char/Kconfig index 400c65bfb8c7..73cde85d04d8 100644 --- a/drivers/sbus/char/Kconfig +++ b/drivers/sbus/char/Kconfig | |||
@@ -13,16 +13,6 @@ config SUN_OPENPROMIO | |||
13 | 13 | ||
14 | If unsure, say Y. | 14 | If unsure, say Y. |
15 | 15 | ||
16 | config SUN_MOSTEK_RTC | ||
17 | tristate "Mostek real time clock support" | ||
18 | depends on SPARC32 | ||
19 | help | ||
20 | The Mostek RTC chip is used on all known Sun computers except | ||
21 | some JavaStations. For a JavaStation you need to say Y both here | ||
22 | and to "Enhanced Real Time Clock Support". | ||
23 | |||
24 | Say Y here unless you are building a special purpose kernel. | ||
25 | |||
26 | config OBP_FLASH | 16 | config OBP_FLASH |
27 | tristate "OBP Flash Device support" | 17 | tristate "OBP Flash Device support" |
28 | depends on SPARC64 | 18 | depends on SPARC64 |
@@ -30,26 +20,9 @@ config OBP_FLASH | |||
30 | The OpenBoot PROM on Ultra systems is flashable. If you want to be | 20 | The OpenBoot PROM on Ultra systems is flashable. If you want to be |
31 | able to upgrade the OBP firmware, say Y here. | 21 | able to upgrade the OBP firmware, say Y here. |
32 | 22 | ||
33 | config SUN_BPP | ||
34 | tristate "Bidirectional parallel port support (OBSOLETE)" | ||
35 | depends on EXPERIMENTAL | ||
36 | help | ||
37 | Say Y here to support Sun's obsolete variant of IEEE1284 | ||
38 | bidirectional parallel port protocol as /dev/bppX. Can be built on | ||
39 | x86 machines. | ||
40 | |||
41 | config SUN_VIDEOPIX | ||
42 | tristate "Videopix Frame Grabber (EXPERIMENTAL)" | ||
43 | depends on EXPERIMENTAL && (BROKEN || !64BIT) | ||
44 | help | ||
45 | Say Y here to support the Videopix Frame Grabber from Sun | ||
46 | Microsystems, commonly found on SPARCstations. This card, which is | ||
47 | based on the Phillips SAA9051, can handle NTSC and PAL/SECAM and | ||
48 | SVIDEO signals. | ||
49 | |||
50 | config TADPOLE_TS102_UCTRL | 23 | config TADPOLE_TS102_UCTRL |
51 | tristate "Tadpole TS102 Microcontroller support (EXPERIMENTAL)" | 24 | tristate "Tadpole TS102 Microcontroller support (EXPERIMENTAL)" |
52 | depends on EXPERIMENTAL && SPARC32 | 25 | depends on EXPERIMENTAL |
53 | help | 26 | help |
54 | Say Y here to directly support the TS102 Microcontroller interface | 27 | Say Y here to directly support the TS102 Microcontroller interface |
55 | on the Tadpole Sparcbook 3. This device handles power-management | 28 | on the Tadpole Sparcbook 3. This device handles power-management |
diff --git a/drivers/sbus/char/Makefile b/drivers/sbus/char/Makefile index 7ab060e9a5fe..78b6183c9866 100644 --- a/drivers/sbus/char/Makefile +++ b/drivers/sbus/char/Makefile | |||
@@ -7,18 +7,12 @@ | |||
7 | # Rewritten to use lists instead of if-statements. | 7 | # Rewritten to use lists instead of if-statements. |
8 | # | 8 | # |
9 | 9 | ||
10 | vfc-objs := vfc_dev.o vfc_i2c.o | ||
11 | bbc-objs := bbc_i2c.o bbc_envctrl.o | 10 | bbc-objs := bbc_i2c.o bbc_envctrl.o |
12 | 11 | ||
13 | obj-$(CONFIG_ENVCTRL) += envctrl.o | 12 | obj-$(CONFIG_ENVCTRL) += envctrl.o |
14 | obj-$(CONFIG_DISPLAY7SEG) += display7seg.o | 13 | obj-$(CONFIG_DISPLAY7SEG) += display7seg.o |
15 | obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwatchdog.o | ||
16 | obj-$(CONFIG_WATCHDOG_RIO) += riowatchdog.o | ||
17 | obj-$(CONFIG_OBP_FLASH) += flash.o | 14 | obj-$(CONFIG_OBP_FLASH) += flash.o |
18 | obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o | 15 | obj-$(CONFIG_SUN_OPENPROMIO) += openprom.o |
19 | obj-$(CONFIG_SUN_MOSTEK_RTC) += rtc.o | ||
20 | obj-$(CONFIG_SUN_BPP) += bpp.o | ||
21 | obj-$(CONFIG_SUN_VIDEOPIX) += vfc.o | ||
22 | obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o | 16 | obj-$(CONFIG_TADPOLE_TS102_UCTRL) += uctrl.o |
23 | obj-$(CONFIG_SUN_JSFLASH) += jsflash.o | 17 | obj-$(CONFIG_SUN_JSFLASH) += jsflash.o |
24 | obj-$(CONFIG_BBC_I2C) += bbc.o | 18 | obj-$(CONFIG_BBC_I2C) += bbc.o |
diff --git a/drivers/sbus/char/bbc_envctrl.c b/drivers/sbus/char/bbc_envctrl.c index 0bde26989a23..15dab96d05e3 100644 --- a/drivers/sbus/char/bbc_envctrl.c +++ b/drivers/sbus/char/bbc_envctrl.c | |||
@@ -1,15 +1,15 @@ | |||
1 | /* $Id: bbc_envctrl.c,v 1.4 2001/04/06 16:48:08 davem Exp $ | 1 | /* bbc_envctrl.c: UltraSPARC-III environment control driver. |
2 | * bbc_envctrl.c: UltraSPARC-III environment control driver. | ||
3 | * | 2 | * |
4 | * Copyright (C) 2001 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net) |
5 | */ | 4 | */ |
6 | 5 | ||
7 | #include <linux/kthread.h> | 6 | #include <linux/kthread.h> |
8 | #include <linux/delay.h> | 7 | #include <linux/delay.h> |
9 | #include <linux/kmod.h> | 8 | #include <linux/kmod.h> |
10 | #include <linux/reboot.h> | 9 | #include <linux/reboot.h> |
10 | #include <linux/of.h> | ||
11 | #include <linux/of_device.h> | ||
11 | #include <asm/oplib.h> | 12 | #include <asm/oplib.h> |
12 | #include <asm/ebus.h> | ||
13 | 13 | ||
14 | #include "bbc_i2c.h" | 14 | #include "bbc_i2c.h" |
15 | #include "max1617.h" | 15 | #include "max1617.h" |
@@ -75,43 +75,8 @@ static struct temp_limits amb_temp_limits[2] = { | |||
75 | { 65, 55, 40, 5, -5, -10 }, | 75 | { 65, 55, 40, 5, -5, -10 }, |
76 | }; | 76 | }; |
77 | 77 | ||
78 | enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX }; | 78 | static LIST_HEAD(all_temps); |
79 | 79 | static LIST_HEAD(all_fans); | |
80 | struct bbc_cpu_temperature { | ||
81 | struct bbc_cpu_temperature *next; | ||
82 | |||
83 | struct bbc_i2c_client *client; | ||
84 | int index; | ||
85 | |||
86 | /* Current readings, and history. */ | ||
87 | s8 curr_cpu_temp; | ||
88 | s8 curr_amb_temp; | ||
89 | s8 prev_cpu_temp; | ||
90 | s8 prev_amb_temp; | ||
91 | s8 avg_cpu_temp; | ||
92 | s8 avg_amb_temp; | ||
93 | |||
94 | int sample_tick; | ||
95 | |||
96 | enum fan_action fan_todo[2]; | ||
97 | #define FAN_AMBIENT 0 | ||
98 | #define FAN_CPU 1 | ||
99 | }; | ||
100 | |||
101 | struct bbc_cpu_temperature *all_bbc_temps; | ||
102 | |||
103 | struct bbc_fan_control { | ||
104 | struct bbc_fan_control *next; | ||
105 | |||
106 | struct bbc_i2c_client *client; | ||
107 | int index; | ||
108 | |||
109 | int psupply_fan_on; | ||
110 | int cpu_fan_speed; | ||
111 | int system_fan_speed; | ||
112 | }; | ||
113 | |||
114 | struct bbc_fan_control *all_bbc_fans; | ||
115 | 80 | ||
116 | #define CPU_FAN_REG 0xf0 | 81 | #define CPU_FAN_REG 0xf0 |
117 | #define SYS_FAN_REG 0xf2 | 82 | #define SYS_FAN_REG 0xf2 |
@@ -330,7 +295,7 @@ static enum fan_action prioritize_fan_action(int which_fan) | |||
330 | * recommend we do, and perform that action on all the | 295 | * recommend we do, and perform that action on all the |
331 | * fans. | 296 | * fans. |
332 | */ | 297 | */ |
333 | for (tp = all_bbc_temps; tp; tp = tp->next) { | 298 | list_for_each_entry(tp, &all_temps, glob_list) { |
334 | if (tp->fan_todo[which_fan] == FAN_FULLBLAST) { | 299 | if (tp->fan_todo[which_fan] == FAN_FULLBLAST) { |
335 | decision = FAN_FULLBLAST; | 300 | decision = FAN_FULLBLAST; |
336 | break; | 301 | break; |
@@ -439,7 +404,7 @@ static void fans_full_blast(void) | |||
439 | /* Since we will not be monitoring things anymore, put | 404 | /* Since we will not be monitoring things anymore, put |
440 | * the fans on full blast. | 405 | * the fans on full blast. |
441 | */ | 406 | */ |
442 | for (fp = all_bbc_fans; fp; fp = fp->next) { | 407 | list_for_each_entry(fp, &all_fans, glob_list) { |
443 | fp->cpu_fan_speed = FAN_SPEED_MAX; | 408 | fp->cpu_fan_speed = FAN_SPEED_MAX; |
444 | fp->system_fan_speed = FAN_SPEED_MAX; | 409 | fp->system_fan_speed = FAN_SPEED_MAX; |
445 | fp->psupply_fan_on = 1; | 410 | fp->psupply_fan_on = 1; |
@@ -463,11 +428,11 @@ static int kenvctrld(void *__unused) | |||
463 | if (kthread_should_stop()) | 428 | if (kthread_should_stop()) |
464 | break; | 429 | break; |
465 | 430 | ||
466 | for (tp = all_bbc_temps; tp; tp = tp->next) { | 431 | list_for_each_entry(tp, &all_temps, glob_list) { |
467 | get_current_temps(tp); | 432 | get_current_temps(tp); |
468 | analyze_temps(tp, &last_warning_jiffies); | 433 | analyze_temps(tp, &last_warning_jiffies); |
469 | } | 434 | } |
470 | for (fp = all_bbc_fans; fp; fp = fp->next) | 435 | list_for_each_entry(fp, &all_fans, glob_list) |
471 | maybe_new_fan_speeds(fp); | 436 | maybe_new_fan_speeds(fp); |
472 | } | 437 | } |
473 | printk(KERN_INFO "bbc_envctrl: kenvctrld exiting...\n"); | 438 | printk(KERN_INFO "bbc_envctrl: kenvctrld exiting...\n"); |
@@ -477,7 +442,8 @@ static int kenvctrld(void *__unused) | |||
477 | return 0; | 442 | return 0; |
478 | } | 443 | } |
479 | 444 | ||
480 | static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) | 445 | static void attach_one_temp(struct bbc_i2c_bus *bp, struct of_device *op, |
446 | int temp_idx) | ||
481 | { | 447 | { |
482 | struct bbc_cpu_temperature *tp; | 448 | struct bbc_cpu_temperature *tp; |
483 | 449 | ||
@@ -485,20 +451,17 @@ static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) | |||
485 | if (!tp) | 451 | if (!tp) |
486 | return; | 452 | return; |
487 | 453 | ||
488 | tp->client = bbc_i2c_attach(echild); | 454 | tp->client = bbc_i2c_attach(bp, op); |
489 | if (!tp->client) { | 455 | if (!tp->client) { |
490 | kfree(tp); | 456 | kfree(tp); |
491 | return; | 457 | return; |
492 | } | 458 | } |
493 | 459 | ||
460 | |||
494 | tp->index = temp_idx; | 461 | tp->index = temp_idx; |
495 | { | 462 | |
496 | struct bbc_cpu_temperature **tpp = &all_bbc_temps; | 463 | list_add(&tp->glob_list, &all_temps); |
497 | while (*tpp) | 464 | list_add(&tp->bp_list, &bp->temps); |
498 | tpp = &((*tpp)->next); | ||
499 | tp->next = NULL; | ||
500 | *tpp = tp; | ||
501 | } | ||
502 | 465 | ||
503 | /* Tell it to convert once every 5 seconds, clear all cfg | 466 | /* Tell it to convert once every 5 seconds, clear all cfg |
504 | * bits. | 467 | * bits. |
@@ -524,7 +487,8 @@ static void attach_one_temp(struct linux_ebus_child *echild, int temp_idx) | |||
524 | tp->fan_todo[FAN_CPU] = FAN_SAME; | 487 | tp->fan_todo[FAN_CPU] = FAN_SAME; |
525 | } | 488 | } |
526 | 489 | ||
527 | static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) | 490 | static void attach_one_fan(struct bbc_i2c_bus *bp, struct of_device *op, |
491 | int fan_idx) | ||
528 | { | 492 | { |
529 | struct bbc_fan_control *fp; | 493 | struct bbc_fan_control *fp; |
530 | 494 | ||
@@ -532,7 +496,7 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) | |||
532 | if (!fp) | 496 | if (!fp) |
533 | return; | 497 | return; |
534 | 498 | ||
535 | fp->client = bbc_i2c_attach(echild); | 499 | fp->client = bbc_i2c_attach(bp, op); |
536 | if (!fp->client) { | 500 | if (!fp->client) { |
537 | kfree(fp); | 501 | kfree(fp); |
538 | return; | 502 | return; |
@@ -540,13 +504,8 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) | |||
540 | 504 | ||
541 | fp->index = fan_idx; | 505 | fp->index = fan_idx; |
542 | 506 | ||
543 | { | 507 | list_add(&fp->glob_list, &all_fans); |
544 | struct bbc_fan_control **fpp = &all_bbc_fans; | 508 | list_add(&fp->bp_list, &bp->fans); |
545 | while (*fpp) | ||
546 | fpp = &((*fpp)->next); | ||
547 | fp->next = NULL; | ||
548 | *fpp = fp; | ||
549 | } | ||
550 | 509 | ||
551 | /* The i2c device controlling the fans is write-only. | 510 | /* The i2c device controlling the fans is write-only. |
552 | * So the only way to keep track of the current power | 511 | * So the only way to keep track of the current power |
@@ -563,18 +522,18 @@ static void attach_one_fan(struct linux_ebus_child *echild, int fan_idx) | |||
563 | set_fan_speeds(fp); | 522 | set_fan_speeds(fp); |
564 | } | 523 | } |
565 | 524 | ||
566 | int bbc_envctrl_init(void) | 525 | int bbc_envctrl_init(struct bbc_i2c_bus *bp) |
567 | { | 526 | { |
568 | struct linux_ebus_child *echild; | 527 | struct of_device *op; |
569 | int temp_index = 0; | 528 | int temp_index = 0; |
570 | int fan_index = 0; | 529 | int fan_index = 0; |
571 | int devidx = 0; | 530 | int devidx = 0; |
572 | 531 | ||
573 | while ((echild = bbc_i2c_getdev(devidx++)) != NULL) { | 532 | while ((op = bbc_i2c_getdev(bp, devidx++)) != NULL) { |
574 | if (!strcmp(echild->prom_node->name, "temperature")) | 533 | if (!strcmp(op->node->name, "temperature")) |
575 | attach_one_temp(echild, temp_index++); | 534 | attach_one_temp(bp, op, temp_index++); |
576 | if (!strcmp(echild->prom_node->name, "fan-control")) | 535 | if (!strcmp(op->node->name, "fan-control")) |
577 | attach_one_fan(echild, fan_index++); | 536 | attach_one_fan(bp, op, fan_index++); |
578 | } | 537 | } |
579 | if (temp_index != 0 && fan_index != 0) { | 538 | if (temp_index != 0 && fan_index != 0) { |
580 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); | 539 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); |
@@ -597,26 +556,22 @@ static void destroy_one_fan(struct bbc_fan_control *fp) | |||
597 | kfree(fp); | 556 | kfree(fp); |
598 | } | 557 | } |
599 | 558 | ||
600 | void bbc_envctrl_cleanup(void) | 559 | void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp) |
601 | { | 560 | { |
602 | struct bbc_cpu_temperature *tp; | 561 | struct bbc_cpu_temperature *tp, *tpos; |
603 | struct bbc_fan_control *fp; | 562 | struct bbc_fan_control *fp, *fpos; |
604 | 563 | ||
605 | kthread_stop(kenvctrld_task); | 564 | kthread_stop(kenvctrld_task); |
606 | 565 | ||
607 | tp = all_bbc_temps; | 566 | list_for_each_entry_safe(tp, tpos, &bp->temps, bp_list) { |
608 | while (tp != NULL) { | 567 | list_del(&tp->bp_list); |
609 | struct bbc_cpu_temperature *next = tp->next; | 568 | list_del(&tp->glob_list); |
610 | destroy_one_temp(tp); | 569 | destroy_one_temp(tp); |
611 | tp = next; | ||
612 | } | 570 | } |
613 | all_bbc_temps = NULL; | ||
614 | 571 | ||
615 | fp = all_bbc_fans; | 572 | list_for_each_entry_safe(fp, fpos, &bp->fans, bp_list) { |
616 | while (fp != NULL) { | 573 | list_del(&fp->bp_list); |
617 | struct bbc_fan_control *next = fp->next; | 574 | list_del(&fp->glob_list); |
618 | destroy_one_fan(fp); | 575 | destroy_one_fan(fp); |
619 | fp = next; | ||
620 | } | 576 | } |
621 | all_bbc_fans = NULL; | ||
622 | } | 577 | } |
diff --git a/drivers/sbus/char/bbc_i2c.c b/drivers/sbus/char/bbc_i2c.c index ac8ef2ce07fb..f08e169ba1b5 100644 --- a/drivers/sbus/char/bbc_i2c.c +++ b/drivers/sbus/char/bbc_i2c.c | |||
@@ -1,8 +1,7 @@ | |||
1 | /* $Id: bbc_i2c.c,v 1.2 2001/04/02 09:59:08 davem Exp $ | 1 | /* bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III |
2 | * bbc_i2c.c: I2C low-level driver for BBC device on UltraSPARC-III | ||
3 | * platforms. | 2 | * platforms. |
4 | * | 3 | * |
5 | * Copyright (C) 2001 David S. Miller (davem@redhat.com) | 4 | * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net) |
6 | */ | 5 | */ |
7 | 6 | ||
8 | #include <linux/module.h> | 7 | #include <linux/module.h> |
@@ -14,9 +13,8 @@ | |||
14 | #include <linux/delay.h> | 13 | #include <linux/delay.h> |
15 | #include <linux/init.h> | 14 | #include <linux/init.h> |
16 | #include <linux/interrupt.h> | 15 | #include <linux/interrupt.h> |
17 | #include <asm/oplib.h> | 16 | #include <linux/of.h> |
18 | #include <asm/ebus.h> | 17 | #include <linux/of_device.h> |
19 | #include <asm/spitfire.h> | ||
20 | #include <asm/bbc.h> | 18 | #include <asm/bbc.h> |
21 | #include <asm/io.h> | 19 | #include <asm/io.h> |
22 | 20 | ||
@@ -53,54 +51,12 @@ | |||
53 | * The second controller also connects to the smartcard reader, if present. | 51 | * The second controller also connects to the smartcard reader, if present. |
54 | */ | 52 | */ |
55 | 53 | ||
56 | #define NUM_CHILDREN 8 | 54 | static void set_device_claimage(struct bbc_i2c_bus *bp, struct of_device *op, int val) |
57 | struct bbc_i2c_bus { | ||
58 | struct bbc_i2c_bus *next; | ||
59 | int index; | ||
60 | spinlock_t lock; | ||
61 | void __iomem *i2c_bussel_reg; | ||
62 | void __iomem *i2c_control_regs; | ||
63 | unsigned char own, clock; | ||
64 | |||
65 | wait_queue_head_t wq; | ||
66 | volatile int waiting; | ||
67 | |||
68 | struct linux_ebus_device *bus_edev; | ||
69 | struct { | ||
70 | struct linux_ebus_child *device; | ||
71 | int client_claimed; | ||
72 | } devs[NUM_CHILDREN]; | ||
73 | }; | ||
74 | |||
75 | static struct bbc_i2c_bus *all_bbc_i2c; | ||
76 | |||
77 | struct bbc_i2c_client { | ||
78 | struct bbc_i2c_bus *bp; | ||
79 | struct linux_ebus_child *echild; | ||
80 | int bus; | ||
81 | int address; | ||
82 | }; | ||
83 | |||
84 | static int find_device(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild) | ||
85 | { | 55 | { |
86 | int i; | 56 | int i; |
87 | 57 | ||
88 | for (i = 0; i < NUM_CHILDREN; i++) { | 58 | for (i = 0; i < NUM_CHILDREN; i++) { |
89 | if (bp->devs[i].device == echild) { | 59 | if (bp->devs[i].device == op) { |
90 | if (bp->devs[i].client_claimed) | ||
91 | return 0; | ||
92 | return 1; | ||
93 | } | ||
94 | } | ||
95 | return 0; | ||
96 | } | ||
97 | |||
98 | static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child *echild, int val) | ||
99 | { | ||
100 | int i; | ||
101 | |||
102 | for (i = 0; i < NUM_CHILDREN; i++) { | ||
103 | if (bp->devs[i].device == echild) { | ||
104 | bp->devs[i].client_claimed = val; | 60 | bp->devs[i].client_claimed = val; |
105 | return; | 61 | return; |
106 | } | 62 | } |
@@ -110,61 +66,47 @@ static void set_device_claimage(struct bbc_i2c_bus *bp, struct linux_ebus_child | |||
110 | #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) | 66 | #define claim_device(BP,ECHILD) set_device_claimage(BP,ECHILD,1) |
111 | #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) | 67 | #define release_device(BP,ECHILD) set_device_claimage(BP,ECHILD,0) |
112 | 68 | ||
113 | static struct bbc_i2c_bus *find_bus_for_device(struct linux_ebus_child *echild) | 69 | struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *bp, int index) |
114 | { | 70 | { |
115 | struct bbc_i2c_bus *bp = all_bbc_i2c; | 71 | struct of_device *op = NULL; |
72 | int curidx = 0, i; | ||
116 | 73 | ||
117 | while (bp != NULL) { | 74 | for (i = 0; i < NUM_CHILDREN; i++) { |
118 | if (find_device(bp, echild) != 0) | 75 | if (!(op = bp->devs[i].device)) |
119 | break; | 76 | break; |
120 | bp = bp->next; | 77 | if (curidx == index) |
78 | goto out; | ||
79 | op = NULL; | ||
80 | curidx++; | ||
121 | } | 81 | } |
122 | 82 | ||
123 | return bp; | ||
124 | } | ||
125 | |||
126 | struct linux_ebus_child *bbc_i2c_getdev(int index) | ||
127 | { | ||
128 | struct bbc_i2c_bus *bp = all_bbc_i2c; | ||
129 | struct linux_ebus_child *echild = NULL; | ||
130 | int curidx = 0; | ||
131 | |||
132 | while (bp != NULL) { | ||
133 | struct bbc_i2c_bus *next = bp->next; | ||
134 | int i; | ||
135 | |||
136 | for (i = 0; i < NUM_CHILDREN; i++) { | ||
137 | if (!(echild = bp->devs[i].device)) | ||
138 | break; | ||
139 | if (curidx == index) | ||
140 | goto out; | ||
141 | echild = NULL; | ||
142 | curidx++; | ||
143 | } | ||
144 | bp = next; | ||
145 | } | ||
146 | out: | 83 | out: |
147 | if (curidx == index) | 84 | if (curidx == index) |
148 | return echild; | 85 | return op; |
149 | return NULL; | 86 | return NULL; |
150 | } | 87 | } |
151 | 88 | ||
152 | struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild) | 89 | struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *op) |
153 | { | 90 | { |
154 | struct bbc_i2c_bus *bp = find_bus_for_device(echild); | ||
155 | struct bbc_i2c_client *client; | 91 | struct bbc_i2c_client *client; |
92 | const u32 *reg; | ||
156 | 93 | ||
157 | if (!bp) | ||
158 | return NULL; | ||
159 | client = kzalloc(sizeof(*client), GFP_KERNEL); | 94 | client = kzalloc(sizeof(*client), GFP_KERNEL); |
160 | if (!client) | 95 | if (!client) |
161 | return NULL; | 96 | return NULL; |
162 | client->bp = bp; | 97 | client->bp = bp; |
163 | client->echild = echild; | 98 | client->op = op; |
164 | client->bus = echild->resource[0].start; | 99 | |
165 | client->address = echild->resource[1].start; | 100 | reg = of_get_property(op->node, "reg", NULL); |
101 | if (!reg) { | ||
102 | kfree(client); | ||
103 | return NULL; | ||
104 | } | ||
166 | 105 | ||
167 | claim_device(bp, echild); | 106 | client->bus = reg[0]; |
107 | client->address = reg[1]; | ||
108 | |||
109 | claim_device(bp, op); | ||
168 | 110 | ||
169 | return client; | 111 | return client; |
170 | } | 112 | } |
@@ -172,9 +114,9 @@ struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *echild) | |||
172 | void bbc_i2c_detach(struct bbc_i2c_client *client) | 114 | void bbc_i2c_detach(struct bbc_i2c_client *client) |
173 | { | 115 | { |
174 | struct bbc_i2c_bus *bp = client->bp; | 116 | struct bbc_i2c_bus *bp = client->bp; |
175 | struct linux_ebus_child *echild = client->echild; | 117 | struct of_device *op = client->op; |
176 | 118 | ||
177 | release_device(bp, echild); | 119 | release_device(bp, op); |
178 | kfree(client); | 120 | kfree(client); |
179 | } | 121 | } |
180 | 122 | ||
@@ -355,44 +297,43 @@ static void __init reset_one_i2c(struct bbc_i2c_bus *bp) | |||
355 | writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); | 297 | writeb(I2C_PCF_IDLE, bp->i2c_control_regs + 0x0); |
356 | } | 298 | } |
357 | 299 | ||
358 | static int __init attach_one_i2c(struct linux_ebus_device *edev, int index) | 300 | static struct bbc_i2c_bus * __init attach_one_i2c(struct of_device *op, int index) |
359 | { | 301 | { |
360 | struct bbc_i2c_bus *bp; | 302 | struct bbc_i2c_bus *bp; |
361 | struct linux_ebus_child *echild; | 303 | struct device_node *dp; |
362 | int entry; | 304 | int entry; |
363 | 305 | ||
364 | bp = kzalloc(sizeof(*bp), GFP_KERNEL); | 306 | bp = kzalloc(sizeof(*bp), GFP_KERNEL); |
365 | if (!bp) | 307 | if (!bp) |
366 | return -ENOMEM; | 308 | return NULL; |
367 | 309 | ||
368 | bp->i2c_control_regs = ioremap(edev->resource[0].start, 0x2); | 310 | bp->i2c_control_regs = of_ioremap(&op->resource[0], 0, 0x2, "bbc_i2c_regs"); |
369 | if (!bp->i2c_control_regs) | 311 | if (!bp->i2c_control_regs) |
370 | goto fail; | 312 | goto fail; |
371 | 313 | ||
372 | if (edev->num_addrs == 2) { | 314 | bp->i2c_bussel_reg = of_ioremap(&op->resource[1], 0, 0x1, "bbc_i2c_bussel"); |
373 | bp->i2c_bussel_reg = ioremap(edev->resource[1].start, 0x1); | 315 | if (!bp->i2c_bussel_reg) |
374 | if (!bp->i2c_bussel_reg) | 316 | goto fail; |
375 | goto fail; | ||
376 | } | ||
377 | 317 | ||
378 | bp->waiting = 0; | 318 | bp->waiting = 0; |
379 | init_waitqueue_head(&bp->wq); | 319 | init_waitqueue_head(&bp->wq); |
380 | if (request_irq(edev->irqs[0], bbc_i2c_interrupt, | 320 | if (request_irq(op->irqs[0], bbc_i2c_interrupt, |
381 | IRQF_SHARED, "bbc_i2c", bp)) | 321 | IRQF_SHARED, "bbc_i2c", bp)) |
382 | goto fail; | 322 | goto fail; |
383 | 323 | ||
384 | bp->index = index; | 324 | bp->index = index; |
385 | bp->bus_edev = edev; | 325 | bp->op = op; |
386 | 326 | ||
387 | spin_lock_init(&bp->lock); | 327 | spin_lock_init(&bp->lock); |
388 | bp->next = all_bbc_i2c; | ||
389 | all_bbc_i2c = bp; | ||
390 | 328 | ||
391 | entry = 0; | 329 | entry = 0; |
392 | for (echild = edev->children; | 330 | for (dp = op->node->child; |
393 | echild && entry < 8; | 331 | dp && entry < 8; |
394 | echild = echild->next, entry++) { | 332 | dp = dp->sibling, entry++) { |
395 | bp->devs[entry].device = echild; | 333 | struct of_device *child_op; |
334 | |||
335 | child_op = of_find_device_by_node(dp); | ||
336 | bp->devs[entry].device = child_op; | ||
396 | bp->devs[entry].client_claimed = 0; | 337 | bp->devs[entry].client_claimed = 0; |
397 | } | 338 | } |
398 | 339 | ||
@@ -406,86 +347,90 @@ static int __init attach_one_i2c(struct linux_ebus_device *edev, int index) | |||
406 | 347 | ||
407 | reset_one_i2c(bp); | 348 | reset_one_i2c(bp); |
408 | 349 | ||
409 | return 0; | 350 | return bp; |
410 | 351 | ||
411 | fail: | 352 | fail: |
412 | if (bp->i2c_bussel_reg) | 353 | if (bp->i2c_bussel_reg) |
413 | iounmap(bp->i2c_bussel_reg); | 354 | of_iounmap(&op->resource[1], bp->i2c_bussel_reg, 1); |
414 | if (bp->i2c_control_regs) | 355 | if (bp->i2c_control_regs) |
415 | iounmap(bp->i2c_control_regs); | 356 | of_iounmap(&op->resource[0], bp->i2c_control_regs, 2); |
416 | kfree(bp); | 357 | kfree(bp); |
417 | return -EINVAL; | 358 | return NULL; |
418 | } | ||
419 | |||
420 | static int __init bbc_present(void) | ||
421 | { | ||
422 | struct linux_ebus *ebus = NULL; | ||
423 | struct linux_ebus_device *edev = NULL; | ||
424 | |||
425 | for_each_ebus(ebus) { | ||
426 | for_each_ebusdev(edev, ebus) { | ||
427 | if (!strcmp(edev->prom_node->name, "bbc")) | ||
428 | return 1; | ||
429 | } | ||
430 | } | ||
431 | return 0; | ||
432 | } | 359 | } |
433 | 360 | ||
434 | extern int bbc_envctrl_init(void); | 361 | extern int bbc_envctrl_init(struct bbc_i2c_bus *bp); |
435 | extern void bbc_envctrl_cleanup(void); | 362 | extern void bbc_envctrl_cleanup(struct bbc_i2c_bus *bp); |
436 | static void bbc_i2c_cleanup(void); | ||
437 | 363 | ||
438 | static int __init bbc_i2c_init(void) | 364 | static int __devinit bbc_i2c_probe(struct of_device *op, |
365 | const struct of_device_id *match) | ||
439 | { | 366 | { |
440 | struct linux_ebus *ebus = NULL; | 367 | struct bbc_i2c_bus *bp; |
441 | struct linux_ebus_device *edev = NULL; | ||
442 | int err, index = 0; | 368 | int err, index = 0; |
443 | 369 | ||
444 | if ((tlb_type != cheetah && tlb_type != cheetah_plus) || | 370 | bp = attach_one_i2c(op, index); |
445 | !bbc_present()) | 371 | if (!bp) |
446 | return -ENODEV; | 372 | return -EINVAL; |
447 | 373 | ||
448 | for_each_ebus(ebus) { | 374 | err = bbc_envctrl_init(bp); |
449 | for_each_ebusdev(edev, ebus) { | 375 | if (err) { |
450 | if (!strcmp(edev->prom_node->name, "i2c")) { | 376 | free_irq(op->irqs[0], bp); |
451 | if (!attach_one_i2c(edev, index)) | 377 | if (bp->i2c_bussel_reg) |
452 | index++; | 378 | of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1); |
453 | } | 379 | if (bp->i2c_control_regs) |
454 | } | 380 | of_iounmap(&op->resource[1], bp->i2c_control_regs, 2); |
381 | kfree(bp); | ||
382 | } else { | ||
383 | dev_set_drvdata(&op->dev, bp); | ||
455 | } | 384 | } |
456 | 385 | ||
457 | if (!index) | ||
458 | return -ENODEV; | ||
459 | |||
460 | err = bbc_envctrl_init(); | ||
461 | if (err) | ||
462 | bbc_i2c_cleanup(); | ||
463 | return err; | 386 | return err; |
464 | } | 387 | } |
465 | 388 | ||
466 | static void bbc_i2c_cleanup(void) | 389 | static int __devexit bbc_i2c_remove(struct of_device *op) |
467 | { | 390 | { |
468 | struct bbc_i2c_bus *bp = all_bbc_i2c; | 391 | struct bbc_i2c_bus *bp = dev_get_drvdata(&op->dev); |
392 | |||
393 | bbc_envctrl_cleanup(bp); | ||
394 | |||
395 | free_irq(op->irqs[0], bp); | ||
469 | 396 | ||
470 | bbc_envctrl_cleanup(); | 397 | if (bp->i2c_bussel_reg) |
398 | of_iounmap(&op->resource[0], bp->i2c_bussel_reg, 1); | ||
399 | if (bp->i2c_control_regs) | ||
400 | of_iounmap(&op->resource[1], bp->i2c_control_regs, 2); | ||
471 | 401 | ||
472 | while (bp != NULL) { | 402 | kfree(bp); |
473 | struct bbc_i2c_bus *next = bp->next; | ||
474 | 403 | ||
475 | free_irq(bp->bus_edev->irqs[0], bp); | 404 | return 0; |
405 | } | ||
476 | 406 | ||
477 | if (bp->i2c_bussel_reg) | 407 | static const struct of_device_id bbc_i2c_match[] = { |
478 | iounmap(bp->i2c_bussel_reg); | 408 | { |
479 | if (bp->i2c_control_regs) | 409 | .name = "i2c", |
480 | iounmap(bp->i2c_control_regs); | 410 | .compatible = "SUNW,bbc-i2c", |
411 | }, | ||
412 | {}, | ||
413 | }; | ||
414 | MODULE_DEVICE_TABLE(of, bbc_i2c_match); | ||
481 | 415 | ||
482 | kfree(bp); | 416 | static struct of_platform_driver bbc_i2c_driver = { |
417 | .name = "bbc_i2c", | ||
418 | .match_table = bbc_i2c_match, | ||
419 | .probe = bbc_i2c_probe, | ||
420 | .remove = __devexit_p(bbc_i2c_remove), | ||
421 | }; | ||
483 | 422 | ||
484 | bp = next; | 423 | static int __init bbc_i2c_init(void) |
485 | } | 424 | { |
486 | all_bbc_i2c = NULL; | 425 | return of_register_driver(&bbc_i2c_driver, &of_bus_type); |
426 | } | ||
427 | |||
428 | static void __exit bbc_i2c_exit(void) | ||
429 | { | ||
430 | of_unregister_driver(&bbc_i2c_driver); | ||
487 | } | 431 | } |
488 | 432 | ||
489 | module_init(bbc_i2c_init); | 433 | module_init(bbc_i2c_init); |
490 | module_exit(bbc_i2c_cleanup); | 434 | module_exit(bbc_i2c_exit); |
435 | |||
491 | MODULE_LICENSE("GPL"); | 436 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/sbus/char/bbc_i2c.h b/drivers/sbus/char/bbc_i2c.h index fb01bd17704b..83c4811b7b5e 100644 --- a/drivers/sbus/char/bbc_i2c.h +++ b/drivers/sbus/char/bbc_i2c.h | |||
@@ -1,14 +1,79 @@ | |||
1 | /* $Id: bbc_i2c.h,v 1.2 2001/04/02 09:59:25 davem Exp $ */ | ||
2 | #ifndef _BBC_I2C_H | 1 | #ifndef _BBC_I2C_H |
3 | #define _BBC_I2C_H | 2 | #define _BBC_I2C_H |
4 | 3 | ||
5 | #include <asm/ebus.h> | 4 | #include <linux/of.h> |
5 | #include <linux/of_device.h> | ||
6 | #include <linux/list.h> | ||
6 | 7 | ||
7 | struct bbc_i2c_client; | 8 | struct bbc_i2c_client { |
9 | struct bbc_i2c_bus *bp; | ||
10 | struct of_device *op; | ||
11 | int bus; | ||
12 | int address; | ||
13 | }; | ||
14 | |||
15 | enum fan_action { FAN_SLOWER, FAN_SAME, FAN_FASTER, FAN_FULLBLAST, FAN_STATE_MAX }; | ||
16 | |||
17 | struct bbc_cpu_temperature { | ||
18 | struct list_head bp_list; | ||
19 | struct list_head glob_list; | ||
20 | |||
21 | struct bbc_i2c_client *client; | ||
22 | int index; | ||
23 | |||
24 | /* Current readings, and history. */ | ||
25 | s8 curr_cpu_temp; | ||
26 | s8 curr_amb_temp; | ||
27 | s8 prev_cpu_temp; | ||
28 | s8 prev_amb_temp; | ||
29 | s8 avg_cpu_temp; | ||
30 | s8 avg_amb_temp; | ||
31 | |||
32 | int sample_tick; | ||
33 | |||
34 | enum fan_action fan_todo[2]; | ||
35 | #define FAN_AMBIENT 0 | ||
36 | #define FAN_CPU 1 | ||
37 | }; | ||
38 | |||
39 | struct bbc_fan_control { | ||
40 | struct list_head bp_list; | ||
41 | struct list_head glob_list; | ||
42 | |||
43 | struct bbc_i2c_client *client; | ||
44 | int index; | ||
45 | |||
46 | int psupply_fan_on; | ||
47 | int cpu_fan_speed; | ||
48 | int system_fan_speed; | ||
49 | }; | ||
50 | |||
51 | #define NUM_CHILDREN 8 | ||
52 | |||
53 | struct bbc_i2c_bus { | ||
54 | struct bbc_i2c_bus *next; | ||
55 | int index; | ||
56 | spinlock_t lock; | ||
57 | void __iomem *i2c_bussel_reg; | ||
58 | void __iomem *i2c_control_regs; | ||
59 | unsigned char own, clock; | ||
60 | |||
61 | wait_queue_head_t wq; | ||
62 | volatile int waiting; | ||
63 | |||
64 | struct list_head temps; | ||
65 | struct list_head fans; | ||
66 | |||
67 | struct of_device *op; | ||
68 | struct { | ||
69 | struct of_device *device; | ||
70 | int client_claimed; | ||
71 | } devs[NUM_CHILDREN]; | ||
72 | }; | ||
8 | 73 | ||
9 | /* Probing and attachment. */ | 74 | /* Probing and attachment. */ |
10 | extern struct linux_ebus_child *bbc_i2c_getdev(int); | 75 | extern struct of_device *bbc_i2c_getdev(struct bbc_i2c_bus *, int); |
11 | extern struct bbc_i2c_client *bbc_i2c_attach(struct linux_ebus_child *); | 76 | extern struct bbc_i2c_client *bbc_i2c_attach(struct bbc_i2c_bus *bp, struct of_device *); |
12 | extern void bbc_i2c_detach(struct bbc_i2c_client *); | 77 | extern void bbc_i2c_detach(struct bbc_i2c_client *); |
13 | 78 | ||
14 | /* Register read/write. NOTE: Blocking! */ | 79 | /* Register read/write. NOTE: Blocking! */ |
diff --git a/drivers/sbus/char/bpp.c b/drivers/sbus/char/bpp.c deleted file mode 100644 index bba21e053a1b..000000000000 --- a/drivers/sbus/char/bpp.c +++ /dev/null | |||
@@ -1,1055 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/sbus/char/bpp.c | ||
3 | * | ||
4 | * Copyright (c) 1995 Picture Elements | ||
5 | * Stephen Williams (steve@icarus.com) | ||
6 | * Gus Baldauf (gbaldauf@ix.netcom.com) | ||
7 | * | ||
8 | * Linux/SPARC port by Peter Zaitcev. | ||
9 | * Integration into SPARC tree by Tom Dyas. | ||
10 | */ | ||
11 | |||
12 | |||
13 | #include <linux/kernel.h> | ||
14 | #include <linux/module.h> | ||
15 | #include <linux/fs.h> | ||
16 | #include <linux/errno.h> | ||
17 | #include <linux/sched.h> | ||
18 | #include <linux/spinlock.h> | ||
19 | #include <linux/timer.h> | ||
20 | #include <linux/ioport.h> | ||
21 | #include <linux/major.h> | ||
22 | #include <linux/smp_lock.h> | ||
23 | |||
24 | #include <asm/uaccess.h> | ||
25 | #include <asm/io.h> | ||
26 | |||
27 | #if defined(__i386__) | ||
28 | # include <asm/system.h> | ||
29 | #endif | ||
30 | |||
31 | #if defined(__sparc__) | ||
32 | # include <linux/init.h> | ||
33 | # include <linux/delay.h> /* udelay() */ | ||
34 | |||
35 | # include <asm/oplib.h> /* OpenProm Library */ | ||
36 | # include <asm/sbus.h> | ||
37 | #endif | ||
38 | |||
39 | #include <asm/bpp.h> | ||
40 | |||
41 | #define BPP_PROBE_CODE 0x55 | ||
42 | #define BPP_DELAY 100 | ||
43 | |||
44 | static const unsigned BPP_MAJOR = LP_MAJOR; | ||
45 | static const char *bpp_dev_name = "bpp"; | ||
46 | |||
47 | /* When switching from compatibility to a mode where I can read, try | ||
48 | the following mode first. */ | ||
49 | |||
50 | /* const unsigned char DEFAULT_ECP = 0x10; */ | ||
51 | static const unsigned char DEFAULT_ECP = 0x30; | ||
52 | static const unsigned char DEFAULT_NIBBLE = 0x00; | ||
53 | |||
54 | /* | ||
55 | * These are 1284 time constraints, in units of jiffies. | ||
56 | */ | ||
57 | |||
58 | static const unsigned long TIME_PSetup = 1; | ||
59 | static const unsigned long TIME_PResponse = 6; | ||
60 | static const unsigned long TIME_IDLE_LIMIT = 2000; | ||
61 | |||
62 | /* | ||
63 | * One instance per supported subdevice... | ||
64 | */ | ||
65 | # define BPP_NO 3 | ||
66 | |||
67 | enum IEEE_Mode { COMPATIBILITY, NIBBLE, ECP, ECP_RLE, EPP }; | ||
68 | |||
69 | struct inst { | ||
70 | unsigned present : 1; /* True if the hardware exists */ | ||
71 | unsigned enhanced : 1; /* True if the hardware in "enhanced" */ | ||
72 | unsigned opened : 1; /* True if the device is opened already */ | ||
73 | unsigned run_flag : 1; /* True if waiting for a repeate byte */ | ||
74 | |||
75 | unsigned char direction; /* 0 --> out, 0x20 --> IN */ | ||
76 | unsigned char pp_state; /* State of host controlled pins. */ | ||
77 | enum IEEE_Mode mode; | ||
78 | |||
79 | unsigned char run_length; | ||
80 | unsigned char repeat_byte; | ||
81 | }; | ||
82 | |||
83 | static struct inst instances[BPP_NO]; | ||
84 | |||
85 | #if defined(__i386__) | ||
86 | |||
87 | static const unsigned short base_addrs[BPP_NO] = { 0x278, 0x378, 0x3bc }; | ||
88 | |||
89 | /* | ||
90 | * These are for data access. | ||
91 | * Control lines accesses are hidden in set_bits() and get_bits(). | ||
92 | * The exception is the probe procedure, which is system-dependent. | ||
93 | */ | ||
94 | #define bpp_outb_p(data, base) outb_p((data), (base)) | ||
95 | #define bpp_inb(base) inb(base) | ||
96 | #define bpp_inb_p(base) inb_p(base) | ||
97 | |||
98 | /* | ||
99 | * This method takes the pin values mask and sets the hardware pins to | ||
100 | * the requested value: 1 == high voltage, 0 == low voltage. This | ||
101 | * burries the annoying PC bit inversion and preserves the direction | ||
102 | * flag. | ||
103 | */ | ||
104 | static void set_pins(unsigned short pins, unsigned minor) | ||
105 | { | ||
106 | unsigned char bits = instances[minor].direction; /* == 0x20 */ | ||
107 | |||
108 | if (! (pins & BPP_PP_nStrobe)) bits |= 1; | ||
109 | if (! (pins & BPP_PP_nAutoFd)) bits |= 2; | ||
110 | if ( pins & BPP_PP_nInit) bits |= 4; | ||
111 | if (! (pins & BPP_PP_nSelectIn)) bits |= 8; | ||
112 | |||
113 | instances[minor].pp_state = bits; | ||
114 | |||
115 | outb_p(bits, base_addrs[minor]+2); | ||
116 | } | ||
117 | |||
118 | static unsigned short get_pins(unsigned minor) | ||
119 | { | ||
120 | unsigned short bits = 0; | ||
121 | |||
122 | unsigned value = instances[minor].pp_state; | ||
123 | if (! (value & 0x01)) bits |= BPP_PP_nStrobe; | ||
124 | if (! (value & 0x02)) bits |= BPP_PP_nAutoFd; | ||
125 | if (value & 0x04) bits |= BPP_PP_nInit; | ||
126 | if (! (value & 0x08)) bits |= BPP_PP_nSelectIn; | ||
127 | |||
128 | value = inb_p(base_addrs[minor]+1); | ||
129 | if (value & 0x08) bits |= BPP_GP_nFault; | ||
130 | if (value & 0x10) bits |= BPP_GP_Select; | ||
131 | if (value & 0x20) bits |= BPP_GP_PError; | ||
132 | if (value & 0x40) bits |= BPP_GP_nAck; | ||
133 | if (! (value & 0x80)) bits |= BPP_GP_Busy; | ||
134 | |||
135 | return bits; | ||
136 | } | ||
137 | |||
138 | #endif /* __i386__ */ | ||
139 | |||
140 | #if defined(__sparc__) | ||
141 | |||
142 | /* | ||
143 | * Register block | ||
144 | */ | ||
145 | /* DMA registers */ | ||
146 | #define BPP_CSR 0x00 | ||
147 | #define BPP_ADDR 0x04 | ||
148 | #define BPP_BCNT 0x08 | ||
149 | #define BPP_TST_CSR 0x0C | ||
150 | /* Parallel Port registers */ | ||
151 | #define BPP_HCR 0x10 | ||
152 | #define BPP_OCR 0x12 | ||
153 | #define BPP_DR 0x14 | ||
154 | #define BPP_TCR 0x15 | ||
155 | #define BPP_OR 0x16 | ||
156 | #define BPP_IR 0x17 | ||
157 | #define BPP_ICR 0x18 | ||
158 | #define BPP_SIZE 0x1A | ||
159 | |||
160 | /* BPP_CSR. Bits of type RW1 are cleared with writing '1'. */ | ||
161 | #define P_DEV_ID_MASK 0xf0000000 /* R */ | ||
162 | #define P_DEV_ID_ZEBRA 0x40000000 | ||
163 | #define P_DEV_ID_L64854 0xa0000000 /* == NCR 89C100+89C105. Pity. */ | ||
164 | #define P_NA_LOADED 0x08000000 /* R NA wirtten but was not used */ | ||
165 | #define P_A_LOADED 0x04000000 /* R */ | ||
166 | #define P_DMA_ON 0x02000000 /* R DMA is not disabled */ | ||
167 | #define P_EN_NEXT 0x01000000 /* RW */ | ||
168 | #define P_TCI_DIS 0x00800000 /* RW TCI forbidden from interrupts */ | ||
169 | #define P_DIAG 0x00100000 /* RW Disables draining and resetting | ||
170 | of P-FIFO on loading of P_ADDR*/ | ||
171 | #define P_BURST_SIZE 0x000c0000 /* RW SBus burst size */ | ||
172 | #define P_BURST_8 0x00000000 | ||
173 | #define P_BURST_4 0x00040000 | ||
174 | #define P_BURST_1 0x00080000 /* "No burst" write */ | ||
175 | #define P_TC 0x00004000 /* RW1 Term Count, can be cleared when | ||
176 | P_EN_NEXT=1 */ | ||
177 | #define P_EN_CNT 0x00002000 /* RW */ | ||
178 | #define P_EN_DMA 0x00000200 /* RW */ | ||
179 | #define P_WRITE 0x00000100 /* R DMA dir, 1=to ram, 0=to port */ | ||
180 | #define P_RESET 0x00000080 /* RW */ | ||
181 | #define P_SLAVE_ERR 0x00000040 /* RW1 Access size error */ | ||
182 | #define P_INVALIDATE 0x00000020 /* W Drop P-FIFO */ | ||
183 | #define P_INT_EN 0x00000010 /* RW OK to P_INT_PEND||P_ERR_PEND */ | ||
184 | #define P_DRAINING 0x0000000c /* R P-FIFO is draining to memory */ | ||
185 | #define P_ERR_PEND 0x00000002 /* R */ | ||
186 | #define P_INT_PEND 0x00000001 /* R */ | ||
187 | |||
188 | /* BPP_HCR. Time is in increments of SBus clock. */ | ||
189 | #define P_HCR_TEST 0x8000 /* Allows buried counters to be read */ | ||
190 | #define P_HCR_DSW 0x7f00 /* Data strobe width (in ticks) */ | ||
191 | #define P_HCR_DDS 0x007f /* Data setup before strobe (in ticks) */ | ||
192 | |||
193 | /* BPP_OCR. */ | ||
194 | #define P_OCR_MEM_CLR 0x8000 | ||
195 | #define P_OCR_DATA_SRC 0x4000 /* ) */ | ||
196 | #define P_OCR_DS_DSEL 0x2000 /* ) Bidirectional */ | ||
197 | #define P_OCR_BUSY_DSEL 0x1000 /* ) selects */ | ||
198 | #define P_OCR_ACK_DSEL 0x0800 /* ) */ | ||
199 | #define P_OCR_EN_DIAG 0x0400 | ||
200 | #define P_OCR_BUSY_OP 0x0200 /* Busy operation */ | ||
201 | #define P_OCR_ACK_OP 0x0100 /* Ack operation */ | ||
202 | #define P_OCR_SRST 0x0080 /* Reset state machines. Not selfcleaning. */ | ||
203 | #define P_OCR_IDLE 0x0008 /* PP data transfer state machine is idle */ | ||
204 | #define P_OCR_V_ILCK 0x0002 /* Versatec faded. Zebra only. */ | ||
205 | #define P_OCR_EN_VER 0x0001 /* Enable Versatec (0 - enable). Zebra only. */ | ||
206 | |||
207 | /* BPP_TCR */ | ||
208 | #define P_TCR_DIR 0x08 | ||
209 | #define P_TCR_BUSY 0x04 | ||
210 | #define P_TCR_ACK 0x02 | ||
211 | #define P_TCR_DS 0x01 /* Strobe */ | ||
212 | |||
213 | /* BPP_OR */ | ||
214 | #define P_OR_V3 0x20 /* ) */ | ||
215 | #define P_OR_V2 0x10 /* ) on Zebra only */ | ||
216 | #define P_OR_V1 0x08 /* ) */ | ||
217 | #define P_OR_INIT 0x04 | ||
218 | #define P_OR_AFXN 0x02 /* Auto Feed */ | ||
219 | #define P_OR_SLCT_IN 0x01 | ||
220 | |||
221 | /* BPP_IR */ | ||
222 | #define P_IR_PE 0x04 | ||
223 | #define P_IR_SLCT 0x02 | ||
224 | #define P_IR_ERR 0x01 | ||
225 | |||
226 | /* BPP_ICR */ | ||
227 | #define P_DS_IRQ 0x8000 /* RW1 */ | ||
228 | #define P_ACK_IRQ 0x4000 /* RW1 */ | ||
229 | #define P_BUSY_IRQ 0x2000 /* RW1 */ | ||
230 | #define P_PE_IRQ 0x1000 /* RW1 */ | ||
231 | #define P_SLCT_IRQ 0x0800 /* RW1 */ | ||
232 | #define P_ERR_IRQ 0x0400 /* RW1 */ | ||
233 | #define P_DS_IRQ_EN 0x0200 /* RW Always on rising edge */ | ||
234 | #define P_ACK_IRQ_EN 0x0100 /* RW Always on rising edge */ | ||
235 | #define P_BUSY_IRP 0x0080 /* RW 1= rising edge */ | ||
236 | #define P_BUSY_IRQ_EN 0x0040 /* RW */ | ||
237 | #define P_PE_IRP 0x0020 /* RW 1= rising edge */ | ||
238 | #define P_PE_IRQ_EN 0x0010 /* RW */ | ||
239 | #define P_SLCT_IRP 0x0008 /* RW 1= rising edge */ | ||
240 | #define P_SLCT_IRQ_EN 0x0004 /* RW */ | ||
241 | #define P_ERR_IRP 0x0002 /* RW1 1= rising edge */ | ||
242 | #define P_ERR_IRQ_EN 0x0001 /* RW */ | ||
243 | |||
244 | static void __iomem *base_addrs[BPP_NO]; | ||
245 | |||
246 | #define bpp_outb_p(data, base) sbus_writeb(data, (base) + BPP_DR) | ||
247 | #define bpp_inb_p(base) sbus_readb((base) + BPP_DR) | ||
248 | #define bpp_inb(base) sbus_readb((base) + BPP_DR) | ||
249 | |||
250 | static void set_pins(unsigned short pins, unsigned minor) | ||
251 | { | ||
252 | void __iomem *base = base_addrs[minor]; | ||
253 | unsigned char bits_tcr = 0, bits_or = 0; | ||
254 | |||
255 | if (instances[minor].direction & 0x20) bits_tcr |= P_TCR_DIR; | ||
256 | if ( pins & BPP_PP_nStrobe) bits_tcr |= P_TCR_DS; | ||
257 | |||
258 | if ( pins & BPP_PP_nAutoFd) bits_or |= P_OR_AFXN; | ||
259 | if (! (pins & BPP_PP_nInit)) bits_or |= P_OR_INIT; | ||
260 | if (! (pins & BPP_PP_nSelectIn)) bits_or |= P_OR_SLCT_IN; | ||
261 | |||
262 | sbus_writeb(bits_or, base + BPP_OR); | ||
263 | sbus_writeb(bits_tcr, base + BPP_TCR); | ||
264 | } | ||
265 | |||
266 | /* | ||
267 | * i386 people read output pins from a software image. | ||
268 | * We may get them back from hardware. | ||
269 | * Again, inversion of pins must he buried here. | ||
270 | */ | ||
271 | static unsigned short get_pins(unsigned minor) | ||
272 | { | ||
273 | void __iomem *base = base_addrs[minor]; | ||
274 | unsigned short bits = 0; | ||
275 | unsigned value_tcr = sbus_readb(base + BPP_TCR); | ||
276 | unsigned value_ir = sbus_readb(base + BPP_IR); | ||
277 | unsigned value_or = sbus_readb(base + BPP_OR); | ||
278 | |||
279 | if (value_tcr & P_TCR_DS) bits |= BPP_PP_nStrobe; | ||
280 | if (value_or & P_OR_AFXN) bits |= BPP_PP_nAutoFd; | ||
281 | if (! (value_or & P_OR_INIT)) bits |= BPP_PP_nInit; | ||
282 | if (! (value_or & P_OR_SLCT_IN)) bits |= BPP_PP_nSelectIn; | ||
283 | |||
284 | if (value_ir & P_IR_ERR) bits |= BPP_GP_nFault; | ||
285 | if (! (value_ir & P_IR_SLCT)) bits |= BPP_GP_Select; | ||
286 | if (! (value_ir & P_IR_PE)) bits |= BPP_GP_PError; | ||
287 | if (! (value_tcr & P_TCR_ACK)) bits |= BPP_GP_nAck; | ||
288 | if (value_tcr & P_TCR_BUSY) bits |= BPP_GP_Busy; | ||
289 | |||
290 | return bits; | ||
291 | } | ||
292 | |||
293 | #endif /* __sparc__ */ | ||
294 | |||
295 | static void snooze(unsigned long snooze_time, unsigned minor) | ||
296 | { | ||
297 | schedule_timeout_uninterruptible(snooze_time + 1); | ||
298 | } | ||
299 | |||
300 | static int wait_for(unsigned short set, unsigned short clr, | ||
301 | unsigned long delay, unsigned minor) | ||
302 | { | ||
303 | unsigned short pins = get_pins(minor); | ||
304 | |||
305 | unsigned long extime = 0; | ||
306 | |||
307 | /* | ||
308 | * Try a real fast scan for the first jiffy, in case the device | ||
309 | * responds real good. The first while loop guesses an expire | ||
310 | * time accounting for possible wraparound of jiffies. | ||
311 | */ | ||
312 | while (time_after_eq(jiffies, extime)) extime = jiffies + 1; | ||
313 | while ( (time_before(jiffies, extime)) | ||
314 | && (((pins & set) != set) || ((pins & clr) != 0)) ) { | ||
315 | pins = get_pins(minor); | ||
316 | } | ||
317 | |||
318 | delay -= 1; | ||
319 | |||
320 | /* | ||
321 | * If my delay expired or the pins are still not where I want | ||
322 | * them, then resort to using the timer and greatly reduce my | ||
323 | * sample rate. If the peripheral is going to be slow, this will | ||
324 | * give the CPU up to some more worthy process. | ||
325 | */ | ||
326 | while ( delay && (((pins & set) != set) || ((pins & clr) != 0)) ) { | ||
327 | |||
328 | snooze(1, minor); | ||
329 | pins = get_pins(minor); | ||
330 | delay -= 1; | ||
331 | } | ||
332 | |||
333 | if (delay == 0) return -1; | ||
334 | else return pins; | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * Return ZERO(0) If the negotiation succeeds, an errno otherwise. An | ||
339 | * errno means something broke, and I do not yet know how to fix it. | ||
340 | */ | ||
341 | static int negotiate(unsigned char mode, unsigned minor) | ||
342 | { | ||
343 | int rc; | ||
344 | unsigned short pins = get_pins(minor); | ||
345 | if (pins & BPP_PP_nSelectIn) return -EIO; | ||
346 | |||
347 | |||
348 | /* Event 0: Write the mode to the data lines */ | ||
349 | bpp_outb_p(mode, base_addrs[minor]); | ||
350 | |||
351 | snooze(TIME_PSetup, minor); | ||
352 | |||
353 | /* Event 1: Strobe the mode code into the peripheral */ | ||
354 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
355 | |||
356 | /* Wait for Event 2: Peripheral responds as a 1284 device. */ | ||
357 | rc = wait_for(BPP_GP_PError|BPP_GP_Select|BPP_GP_nFault, | ||
358 | BPP_GP_nAck, | ||
359 | TIME_PResponse, | ||
360 | minor); | ||
361 | |||
362 | if (rc == -1) return -ETIMEDOUT; | ||
363 | |||
364 | /* Event 3: latch extensibility request */ | ||
365 | set_pins(BPP_PP_nSelectIn|BPP_PP_nInit, minor); | ||
366 | |||
367 | /* ... quick nap while peripheral ponders the byte i'm sending...*/ | ||
368 | snooze(1, minor); | ||
369 | |||
370 | /* Event 4: restore strobe, to ACK peripheral's response. */ | ||
371 | set_pins(BPP_PP_nSelectIn|BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
372 | |||
373 | /* Wait for Event 6: Peripheral latches response bits */ | ||
374 | rc = wait_for(BPP_GP_nAck, 0, TIME_PSetup+TIME_PResponse, minor); | ||
375 | if (rc == -1) return -EIO; | ||
376 | |||
377 | /* A 1284 device cannot refuse nibble mode */ | ||
378 | if (mode == DEFAULT_NIBBLE) return 0; | ||
379 | |||
380 | if (pins & BPP_GP_Select) return 0; | ||
381 | |||
382 | return -EPROTONOSUPPORT; | ||
383 | } | ||
384 | |||
385 | static int terminate(unsigned minor) | ||
386 | { | ||
387 | int rc; | ||
388 | |||
389 | /* Event 22: Request termination of 1284 mode */ | ||
390 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
391 | |||
392 | /* Wait for Events 23 and 24: ACK termination request. */ | ||
393 | rc = wait_for(BPP_GP_Busy|BPP_GP_nFault, | ||
394 | BPP_GP_nAck, | ||
395 | TIME_PSetup+TIME_PResponse, | ||
396 | minor); | ||
397 | |||
398 | instances[minor].direction = 0; | ||
399 | instances[minor].mode = COMPATIBILITY; | ||
400 | |||
401 | if (rc == -1) { | ||
402 | return -EIO; | ||
403 | } | ||
404 | |||
405 | /* Event 25: Handshake by lowering nAutoFd */ | ||
406 | set_pins(BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
407 | |||
408 | /* Event 26: Peripheral wiggles lines... */ | ||
409 | |||
410 | /* Event 27: Peripheral sets nAck HIGH to ack handshake */ | ||
411 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | ||
412 | if (rc == -1) { | ||
413 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
414 | return -EIO; | ||
415 | } | ||
416 | |||
417 | /* Event 28: Finish phase by raising nAutoFd */ | ||
418 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, minor); | ||
419 | |||
420 | return 0; | ||
421 | } | ||
422 | |||
423 | static DEFINE_SPINLOCK(bpp_open_lock); | ||
424 | |||
425 | /* | ||
426 | * Allow only one process to open the device at a time. | ||
427 | */ | ||
428 | static int bpp_open(struct inode *inode, struct file *f) | ||
429 | { | ||
430 | unsigned minor = iminor(inode); | ||
431 | int ret; | ||
432 | |||
433 | lock_kernel(); | ||
434 | spin_lock(&bpp_open_lock); | ||
435 | ret = 0; | ||
436 | if (minor >= BPP_NO) { | ||
437 | ret = -ENODEV; | ||
438 | } else { | ||
439 | if (! instances[minor].present) { | ||
440 | ret = -ENODEV; | ||
441 | } else { | ||
442 | if (instances[minor].opened) | ||
443 | ret = -EBUSY; | ||
444 | else | ||
445 | instances[minor].opened = 1; | ||
446 | } | ||
447 | } | ||
448 | spin_unlock(&bpp_open_lock); | ||
449 | unlock_kernel(); | ||
450 | |||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | /* | ||
455 | * When the process closes the device, this method is called to clean | ||
456 | * up and reset the hardware. Always leave the device in compatibility | ||
457 | * mode as this is a reasonable place to clean up from messes made by | ||
458 | * ioctls, or other mayhem. | ||
459 | */ | ||
460 | static int bpp_release(struct inode *inode, struct file *f) | ||
461 | { | ||
462 | unsigned minor = iminor(inode); | ||
463 | |||
464 | spin_lock(&bpp_open_lock); | ||
465 | instances[minor].opened = 0; | ||
466 | |||
467 | if (instances[minor].mode != COMPATIBILITY) | ||
468 | terminate(minor); | ||
469 | |||
470 | spin_unlock(&bpp_open_lock); | ||
471 | |||
472 | return 0; | ||
473 | } | ||
474 | |||
475 | static long read_nibble(unsigned minor, char __user *c, unsigned long cnt) | ||
476 | { | ||
477 | unsigned long remaining = cnt; | ||
478 | long rc; | ||
479 | |||
480 | while (remaining > 0) { | ||
481 | unsigned char byte = 0; | ||
482 | int pins; | ||
483 | |||
484 | /* Event 7: request nibble */ | ||
485 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor); | ||
486 | |||
487 | /* Wait for event 9: Peripher strobes first nibble */ | ||
488 | pins = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); | ||
489 | if (pins == -1) return -ETIMEDOUT; | ||
490 | |||
491 | /* Event 10: I handshake nibble */ | ||
492 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor); | ||
493 | if (pins & BPP_GP_nFault) byte |= 0x01; | ||
494 | if (pins & BPP_GP_Select) byte |= 0x02; | ||
495 | if (pins & BPP_GP_PError) byte |= 0x04; | ||
496 | if (pins & BPP_GP_Busy) byte |= 0x08; | ||
497 | |||
498 | /* Wait for event 11: Peripheral handshakes nibble */ | ||
499 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | ||
500 | |||
501 | /* Event 7: request nibble */ | ||
502 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe, minor); | ||
503 | |||
504 | /* Wait for event 9: Peripher strobes first nibble */ | ||
505 | pins = wait_for(0, BPP_GP_nAck, TIME_PResponse, minor); | ||
506 | if (rc == -1) return -ETIMEDOUT; | ||
507 | |||
508 | /* Event 10: I handshake nibble */ | ||
509 | set_pins(BPP_PP_nSelectIn|BPP_PP_nStrobe|BPP_PP_nAutoFd, minor); | ||
510 | if (pins & BPP_GP_nFault) byte |= 0x10; | ||
511 | if (pins & BPP_GP_Select) byte |= 0x20; | ||
512 | if (pins & BPP_GP_PError) byte |= 0x40; | ||
513 | if (pins & BPP_GP_Busy) byte |= 0x80; | ||
514 | |||
515 | if (put_user(byte, c)) | ||
516 | return -EFAULT; | ||
517 | c += 1; | ||
518 | remaining -= 1; | ||
519 | |||
520 | /* Wait for event 11: Peripheral handshakes nibble */ | ||
521 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | ||
522 | if (rc == -1) return -EIO; | ||
523 | } | ||
524 | |||
525 | return cnt - remaining; | ||
526 | } | ||
527 | |||
528 | static long read_ecp(unsigned minor, char __user *c, unsigned long cnt) | ||
529 | { | ||
530 | unsigned long remaining; | ||
531 | long rc; | ||
532 | |||
533 | /* Turn ECP mode from forward to reverse if needed. */ | ||
534 | if (! instances[minor].direction) { | ||
535 | unsigned short pins = get_pins(minor); | ||
536 | |||
537 | /* Event 38: Turn the bus around */ | ||
538 | instances[minor].direction = 0x20; | ||
539 | pins &= ~BPP_PP_nAutoFd; | ||
540 | set_pins(pins, minor); | ||
541 | |||
542 | /* Event 39: Set pins for reverse mode. */ | ||
543 | snooze(TIME_PSetup, minor); | ||
544 | set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); | ||
545 | |||
546 | /* Wait for event 40: Peripheral ready to be strobed */ | ||
547 | rc = wait_for(0, BPP_GP_PError, TIME_PResponse, minor); | ||
548 | if (rc == -1) return -ETIMEDOUT; | ||
549 | } | ||
550 | |||
551 | remaining = cnt; | ||
552 | |||
553 | while (remaining > 0) { | ||
554 | |||
555 | /* If there is a run length for a repeated byte, repeat */ | ||
556 | /* that byte a few times. */ | ||
557 | if (instances[minor].run_length && !instances[minor].run_flag) { | ||
558 | |||
559 | char buffer[128]; | ||
560 | unsigned idx; | ||
561 | unsigned repeat = remaining < instances[minor].run_length | ||
562 | ? remaining | ||
563 | : instances[minor].run_length; | ||
564 | |||
565 | for (idx = 0 ; idx < repeat ; idx += 1) | ||
566 | buffer[idx] = instances[minor].repeat_byte; | ||
567 | |||
568 | if (copy_to_user(c, buffer, repeat)) | ||
569 | return -EFAULT; | ||
570 | remaining -= repeat; | ||
571 | c += repeat; | ||
572 | instances[minor].run_length -= repeat; | ||
573 | } | ||
574 | |||
575 | if (remaining == 0) break; | ||
576 | |||
577 | |||
578 | /* Wait for Event 43: Data active on the bus. */ | ||
579 | rc = wait_for(0, BPP_GP_nAck, TIME_IDLE_LIMIT, minor); | ||
580 | if (rc == -1) break; | ||
581 | |||
582 | if (rc & BPP_GP_Busy) { | ||
583 | /* OK, this is data. read it in. */ | ||
584 | unsigned char byte = bpp_inb(base_addrs[minor]); | ||
585 | if (put_user(byte, c)) | ||
586 | return -EFAULT; | ||
587 | c += 1; | ||
588 | remaining -= 1; | ||
589 | |||
590 | if (instances[minor].run_flag) { | ||
591 | instances[minor].repeat_byte = byte; | ||
592 | instances[minor].run_flag = 0; | ||
593 | } | ||
594 | |||
595 | } else { | ||
596 | unsigned char byte = bpp_inb(base_addrs[minor]); | ||
597 | if (byte & 0x80) { | ||
598 | printk("bpp%d: " | ||
599 | "Ignoring ECP channel %u from device.\n", | ||
600 | minor, byte & 0x7f); | ||
601 | } else { | ||
602 | instances[minor].run_length = byte; | ||
603 | instances[minor].run_flag = 1; | ||
604 | } | ||
605 | } | ||
606 | |||
607 | /* Event 44: I got it. */ | ||
608 | set_pins(BPP_PP_nStrobe|BPP_PP_nAutoFd|BPP_PP_nSelectIn, minor); | ||
609 | |||
610 | /* Wait for event 45: peripheral handshake */ | ||
611 | rc = wait_for(BPP_GP_nAck, 0, TIME_PResponse, minor); | ||
612 | if (rc == -1) return -ETIMEDOUT; | ||
613 | |||
614 | /* Event 46: Finish handshake */ | ||
615 | set_pins(BPP_PP_nStrobe|BPP_PP_nSelectIn, minor); | ||
616 | |||
617 | } | ||
618 | |||
619 | |||
620 | return cnt - remaining; | ||
621 | } | ||
622 | |||
623 | static ssize_t bpp_read(struct file *f, char __user *c, size_t cnt, loff_t * ppos) | ||
624 | { | ||
625 | long rc; | ||
626 | unsigned minor = iminor(f->f_path.dentry->d_inode); | ||
627 | if (minor >= BPP_NO) return -ENODEV; | ||
628 | if (!instances[minor].present) return -ENODEV; | ||
629 | |||
630 | switch (instances[minor].mode) { | ||
631 | |||
632 | default: | ||
633 | if (instances[minor].mode != COMPATIBILITY) | ||
634 | terminate(minor); | ||
635 | |||
636 | if (instances[minor].enhanced) { | ||
637 | /* For now, do all reads with ECP-RLE mode */ | ||
638 | unsigned short pins; | ||
639 | |||
640 | rc = negotiate(DEFAULT_ECP, minor); | ||
641 | if (rc < 0) break; | ||
642 | |||
643 | instances[minor].mode = ECP_RLE; | ||
644 | |||
645 | /* Event 30: set nAutoFd low to setup for ECP mode */ | ||
646 | pins = get_pins(minor); | ||
647 | pins &= ~BPP_PP_nAutoFd; | ||
648 | set_pins(pins, minor); | ||
649 | |||
650 | /* Wait for Event 31: peripheral ready */ | ||
651 | rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); | ||
652 | if (rc == -1) return -ETIMEDOUT; | ||
653 | |||
654 | rc = read_ecp(minor, c, cnt); | ||
655 | |||
656 | } else { | ||
657 | rc = negotiate(DEFAULT_NIBBLE, minor); | ||
658 | if (rc < 0) break; | ||
659 | |||
660 | instances[minor].mode = NIBBLE; | ||
661 | |||
662 | rc = read_nibble(minor, c, cnt); | ||
663 | } | ||
664 | break; | ||
665 | |||
666 | case NIBBLE: | ||
667 | rc = read_nibble(minor, c, cnt); | ||
668 | break; | ||
669 | |||
670 | case ECP: | ||
671 | case ECP_RLE: | ||
672 | rc = read_ecp(minor, c, cnt); | ||
673 | break; | ||
674 | |||
675 | } | ||
676 | |||
677 | |||
678 | return rc; | ||
679 | } | ||
680 | |||
681 | /* | ||
682 | * Compatibility mode handshaking is a matter of writing data, | ||
683 | * strobing it, and waiting for the printer to stop being busy. | ||
684 | */ | ||
685 | static long write_compat(unsigned minor, const char __user *c, unsigned long cnt) | ||
686 | { | ||
687 | long rc; | ||
688 | unsigned short pins = get_pins(minor); | ||
689 | |||
690 | unsigned long remaining = cnt; | ||
691 | |||
692 | |||
693 | while (remaining > 0) { | ||
694 | unsigned char byte; | ||
695 | |||
696 | if (get_user(byte, c)) | ||
697 | return -EFAULT; | ||
698 | c += 1; | ||
699 | |||
700 | rc = wait_for(BPP_GP_nAck, BPP_GP_Busy, TIME_IDLE_LIMIT, minor); | ||
701 | if (rc == -1) return -ETIMEDOUT; | ||
702 | |||
703 | bpp_outb_p(byte, base_addrs[minor]); | ||
704 | remaining -= 1; | ||
705 | /* snooze(1, minor); */ | ||
706 | |||
707 | pins &= ~BPP_PP_nStrobe; | ||
708 | set_pins(pins, minor); | ||
709 | |||
710 | rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); | ||
711 | |||
712 | pins |= BPP_PP_nStrobe; | ||
713 | set_pins(pins, minor); | ||
714 | } | ||
715 | |||
716 | return cnt - remaining; | ||
717 | } | ||
718 | |||
719 | /* | ||
720 | * Write data using ECP mode. Watch out that the port may be set up | ||
721 | * for reading. If so, turn the port around. | ||
722 | */ | ||
723 | static long write_ecp(unsigned minor, const char __user *c, unsigned long cnt) | ||
724 | { | ||
725 | unsigned short pins = get_pins(minor); | ||
726 | unsigned long remaining = cnt; | ||
727 | |||
728 | if (instances[minor].direction) { | ||
729 | int rc; | ||
730 | |||
731 | /* Event 47 Request bus be turned around */ | ||
732 | pins |= BPP_PP_nInit; | ||
733 | set_pins(pins, minor); | ||
734 | |||
735 | /* Wait for Event 49: Peripheral relinquished bus */ | ||
736 | rc = wait_for(BPP_GP_PError, 0, TIME_PResponse, minor); | ||
737 | |||
738 | pins |= BPP_PP_nAutoFd; | ||
739 | instances[minor].direction = 0; | ||
740 | set_pins(pins, minor); | ||
741 | } | ||
742 | |||
743 | while (remaining > 0) { | ||
744 | unsigned char byte; | ||
745 | int rc; | ||
746 | |||
747 | if (get_user(byte, c)) | ||
748 | return -EFAULT; | ||
749 | |||
750 | rc = wait_for(0, BPP_GP_Busy, TIME_PResponse, minor); | ||
751 | if (rc == -1) return -ETIMEDOUT; | ||
752 | |||
753 | c += 1; | ||
754 | |||
755 | bpp_outb_p(byte, base_addrs[minor]); | ||
756 | |||
757 | pins &= ~BPP_PP_nStrobe; | ||
758 | set_pins(pins, minor); | ||
759 | |||
760 | pins |= BPP_PP_nStrobe; | ||
761 | rc = wait_for(BPP_GP_Busy, 0, TIME_PResponse, minor); | ||
762 | if (rc == -1) return -EIO; | ||
763 | |||
764 | set_pins(pins, minor); | ||
765 | } | ||
766 | |||
767 | return cnt - remaining; | ||
768 | } | ||
769 | |||
770 | /* | ||
771 | * Write to the peripheral. Be sensitive of the current mode. If I'm | ||
772 | * in a mode that can be turned around (ECP) then just do | ||
773 | * that. Otherwise, terminate and do my writing in compat mode. This | ||
774 | * is the safest course as any device can handle it. | ||
775 | */ | ||
776 | static ssize_t bpp_write(struct file *f, const char __user *c, size_t cnt, loff_t * ppos) | ||
777 | { | ||
778 | long errno = 0; | ||
779 | unsigned minor = iminor(f->f_path.dentry->d_inode); | ||
780 | if (minor >= BPP_NO) return -ENODEV; | ||
781 | if (!instances[minor].present) return -ENODEV; | ||
782 | |||
783 | switch (instances[minor].mode) { | ||
784 | |||
785 | case ECP: | ||
786 | case ECP_RLE: | ||
787 | errno = write_ecp(minor, c, cnt); | ||
788 | break; | ||
789 | case COMPATIBILITY: | ||
790 | errno = write_compat(minor, c, cnt); | ||
791 | break; | ||
792 | default: | ||
793 | terminate(minor); | ||
794 | errno = write_compat(minor, c, cnt); | ||
795 | } | ||
796 | |||
797 | return errno; | ||
798 | } | ||
799 | |||
800 | static int bpp_ioctl(struct inode *inode, struct file *f, unsigned int cmd, | ||
801 | unsigned long arg) | ||
802 | { | ||
803 | int errno = 0; | ||
804 | |||
805 | unsigned minor = iminor(inode); | ||
806 | if (minor >= BPP_NO) return -ENODEV; | ||
807 | if (!instances[minor].present) return -ENODEV; | ||
808 | |||
809 | |||
810 | switch (cmd) { | ||
811 | |||
812 | case BPP_PUT_PINS: | ||
813 | set_pins(arg, minor); | ||
814 | break; | ||
815 | |||
816 | case BPP_GET_PINS: | ||
817 | errno = get_pins(minor); | ||
818 | break; | ||
819 | |||
820 | case BPP_PUT_DATA: | ||
821 | bpp_outb_p(arg, base_addrs[minor]); | ||
822 | break; | ||
823 | |||
824 | case BPP_GET_DATA: | ||
825 | errno = bpp_inb_p(base_addrs[minor]); | ||
826 | break; | ||
827 | |||
828 | case BPP_SET_INPUT: | ||
829 | if (arg) | ||
830 | if (instances[minor].enhanced) { | ||
831 | unsigned short bits = get_pins(minor); | ||
832 | instances[minor].direction = 0x20; | ||
833 | set_pins(bits, minor); | ||
834 | } else { | ||
835 | errno = -ENOTTY; | ||
836 | } | ||
837 | else { | ||
838 | unsigned short bits = get_pins(minor); | ||
839 | instances[minor].direction = 0x00; | ||
840 | set_pins(bits, minor); | ||
841 | } | ||
842 | break; | ||
843 | |||
844 | default: | ||
845 | errno = -EINVAL; | ||
846 | } | ||
847 | |||
848 | return errno; | ||
849 | } | ||
850 | |||
851 | static const struct file_operations bpp_fops = { | ||
852 | .owner = THIS_MODULE, | ||
853 | .read = bpp_read, | ||
854 | .write = bpp_write, | ||
855 | .ioctl = bpp_ioctl, | ||
856 | .open = bpp_open, | ||
857 | .release = bpp_release, | ||
858 | }; | ||
859 | |||
860 | #if defined(__i386__) | ||
861 | |||
862 | #define collectLptPorts() {} | ||
863 | |||
864 | static void probeLptPort(unsigned idx) | ||
865 | { | ||
866 | unsigned int testvalue; | ||
867 | const unsigned short lpAddr = base_addrs[idx]; | ||
868 | |||
869 | instances[idx].present = 0; | ||
870 | instances[idx].enhanced = 0; | ||
871 | instances[idx].direction = 0; | ||
872 | instances[idx].mode = COMPATIBILITY; | ||
873 | instances[idx].run_length = 0; | ||
874 | instances[idx].run_flag = 0; | ||
875 | if (!request_region(lpAddr,3, bpp_dev_name)) return; | ||
876 | |||
877 | /* | ||
878 | * First, make sure the instance exists. Do this by writing to | ||
879 | * the data latch and reading the value back. If the port *is* | ||
880 | * present, test to see if it supports extended-mode | ||
881 | * operation. This will be required for IEEE1284 reverse | ||
882 | * transfers. | ||
883 | */ | ||
884 | |||
885 | outb_p(BPP_PROBE_CODE, lpAddr); | ||
886 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | ||
887 | ; | ||
888 | testvalue = inb_p(lpAddr); | ||
889 | if (testvalue == BPP_PROBE_CODE) { | ||
890 | unsigned save; | ||
891 | instances[idx].present = 1; | ||
892 | |||
893 | save = inb_p(lpAddr+2); | ||
894 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | ||
895 | ; | ||
896 | outb_p(save|0x20, lpAddr+2); | ||
897 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | ||
898 | ; | ||
899 | outb_p(~BPP_PROBE_CODE, lpAddr); | ||
900 | for (testvalue=0; testvalue<BPP_DELAY; testvalue++) | ||
901 | ; | ||
902 | testvalue = inb_p(lpAddr); | ||
903 | if ((testvalue&0xff) == (0xff&~BPP_PROBE_CODE)) | ||
904 | instances[idx].enhanced = 0; | ||
905 | else | ||
906 | instances[idx].enhanced = 1; | ||
907 | outb_p(save, lpAddr+2); | ||
908 | } | ||
909 | else { | ||
910 | release_region(lpAddr,3); | ||
911 | } | ||
912 | /* | ||
913 | * Leave the port in compat idle mode. | ||
914 | */ | ||
915 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); | ||
916 | |||
917 | printk("bpp%d: Port at 0x%03x: Enhanced mode %s\n", idx, base_addrs[idx], | ||
918 | instances[idx].enhanced? "SUPPORTED" : "UNAVAILABLE"); | ||
919 | } | ||
920 | |||
921 | static inline void freeLptPort(int idx) | ||
922 | { | ||
923 | release_region(base_addrs[idx], 3); | ||
924 | } | ||
925 | |||
926 | #endif | ||
927 | |||
928 | #if defined(__sparc__) | ||
929 | |||
930 | static void __iomem *map_bpp(struct sbus_dev *dev, int idx) | ||
931 | { | ||
932 | return sbus_ioremap(&dev->resource[0], 0, BPP_SIZE, "bpp"); | ||
933 | } | ||
934 | |||
935 | static int collectLptPorts(void) | ||
936 | { | ||
937 | struct sbus_bus *bus; | ||
938 | struct sbus_dev *dev; | ||
939 | int count; | ||
940 | |||
941 | count = 0; | ||
942 | for_all_sbusdev(dev, bus) { | ||
943 | if (strcmp(dev->prom_name, "SUNW,bpp") == 0) { | ||
944 | if (count >= BPP_NO) { | ||
945 | printk(KERN_NOTICE | ||
946 | "bpp: More than %d bpp ports," | ||
947 | " rest is ignored\n", BPP_NO); | ||
948 | return count; | ||
949 | } | ||
950 | base_addrs[count] = map_bpp(dev, count); | ||
951 | count++; | ||
952 | } | ||
953 | } | ||
954 | return count; | ||
955 | } | ||
956 | |||
957 | static void probeLptPort(unsigned idx) | ||
958 | { | ||
959 | void __iomem *rp = base_addrs[idx]; | ||
960 | __u32 csr; | ||
961 | char *brand; | ||
962 | |||
963 | instances[idx].present = 0; | ||
964 | instances[idx].enhanced = 0; | ||
965 | instances[idx].direction = 0; | ||
966 | instances[idx].mode = COMPATIBILITY; | ||
967 | instances[idx].run_length = 0; | ||
968 | instances[idx].run_flag = 0; | ||
969 | |||
970 | if (!rp) return; | ||
971 | |||
972 | instances[idx].present = 1; | ||
973 | instances[idx].enhanced = 1; /* Sure */ | ||
974 | |||
975 | csr = sbus_readl(rp + BPP_CSR); | ||
976 | if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { | ||
977 | udelay(20); | ||
978 | csr = sbus_readl(rp + BPP_CSR); | ||
979 | if ((csr & P_DRAINING) != 0 && (csr & P_ERR_PEND) == 0) { | ||
980 | printk("bpp%d: DRAINING still active (0x%08x)\n", idx, csr); | ||
981 | } | ||
982 | } | ||
983 | printk("bpp%d: reset with 0x%08x ..", idx, csr); | ||
984 | sbus_writel((csr | P_RESET) & ~P_INT_EN, rp + BPP_CSR); | ||
985 | udelay(500); | ||
986 | sbus_writel(sbus_readl(rp + BPP_CSR) & ~P_RESET, rp + BPP_CSR); | ||
987 | csr = sbus_readl(rp + BPP_CSR); | ||
988 | printk(" done with csr=0x%08x ocr=0x%04x\n", | ||
989 | csr, sbus_readw(rp + BPP_OCR)); | ||
990 | |||
991 | switch (csr & P_DEV_ID_MASK) { | ||
992 | case P_DEV_ID_ZEBRA: | ||
993 | brand = "Zebra"; | ||
994 | break; | ||
995 | case P_DEV_ID_L64854: | ||
996 | brand = "DMA2"; | ||
997 | break; | ||
998 | default: | ||
999 | brand = "Unknown"; | ||
1000 | } | ||
1001 | printk("bpp%d: %s at %p\n", idx, brand, rp); | ||
1002 | |||
1003 | /* | ||
1004 | * Leave the port in compat idle mode. | ||
1005 | */ | ||
1006 | set_pins(BPP_PP_nAutoFd|BPP_PP_nStrobe|BPP_PP_nInit, idx); | ||
1007 | |||
1008 | return; | ||
1009 | } | ||
1010 | |||
1011 | static inline void freeLptPort(int idx) | ||
1012 | { | ||
1013 | sbus_iounmap(base_addrs[idx], BPP_SIZE); | ||
1014 | } | ||
1015 | |||
1016 | #endif | ||
1017 | |||
1018 | static int __init bpp_init(void) | ||
1019 | { | ||
1020 | int rc; | ||
1021 | unsigned idx; | ||
1022 | |||
1023 | rc = collectLptPorts(); | ||
1024 | if (rc == 0) | ||
1025 | return -ENODEV; | ||
1026 | |||
1027 | rc = register_chrdev(BPP_MAJOR, bpp_dev_name, &bpp_fops); | ||
1028 | if (rc < 0) | ||
1029 | return rc; | ||
1030 | |||
1031 | for (idx = 0; idx < BPP_NO; idx++) { | ||
1032 | instances[idx].opened = 0; | ||
1033 | probeLptPort(idx); | ||
1034 | } | ||
1035 | |||
1036 | return 0; | ||
1037 | } | ||
1038 | |||
1039 | static void __exit bpp_cleanup(void) | ||
1040 | { | ||
1041 | unsigned idx; | ||
1042 | |||
1043 | unregister_chrdev(BPP_MAJOR, bpp_dev_name); | ||
1044 | |||
1045 | for (idx = 0; idx < BPP_NO; idx++) { | ||
1046 | if (instances[idx].present) | ||
1047 | freeLptPort(idx); | ||
1048 | } | ||
1049 | } | ||
1050 | |||
1051 | module_init(bpp_init); | ||
1052 | module_exit(bpp_cleanup); | ||
1053 | |||
1054 | MODULE_LICENSE("GPL"); | ||
1055 | |||
diff --git a/drivers/sbus/char/cpwatchdog.c b/drivers/sbus/char/cpwatchdog.c deleted file mode 100644 index 23abfdfb44f1..000000000000 --- a/drivers/sbus/char/cpwatchdog.c +++ /dev/null | |||
@@ -1,858 +0,0 @@ | |||
1 | /* cpwatchdog.c - driver implementation for hardware watchdog | ||
2 | * timers found on Sun Microsystems CP1400 and CP1500 boards. | ||
3 | * | ||
4 | * This device supports both the generic Linux watchdog | ||
5 | * interface and Solaris-compatible ioctls as best it is | ||
6 | * able. | ||
7 | * | ||
8 | * NOTE: CP1400 systems appear to have a defective intr_mask | ||
9 | * register on the PLD, preventing the disabling of | ||
10 | * timer interrupts. We use a timer to periodically | ||
11 | * reset 'stopped' watchdogs on affected platforms. | ||
12 | * | ||
13 | * Copyright (c) 2000 Eric Brower (ebrower@usa.net) | ||
14 | */ | ||
15 | |||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/module.h> | ||
18 | #include <linux/fs.h> | ||
19 | #include <linux/errno.h> | ||
20 | #include <linux/major.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/miscdevice.h> | ||
23 | #include <linux/interrupt.h> | ||
24 | #include <linux/ioport.h> | ||
25 | #include <linux/timer.h> | ||
26 | #include <linux/smp_lock.h> | ||
27 | #include <linux/io.h> | ||
28 | #include <asm/irq.h> | ||
29 | #include <asm/ebus.h> | ||
30 | #include <asm/oplib.h> | ||
31 | #include <asm/uaccess.h> | ||
32 | |||
33 | #include <asm/watchdog.h> | ||
34 | |||
35 | #define WD_OBPNAME "watchdog" | ||
36 | #define WD_BADMODEL "SUNW,501-5336" | ||
37 | #define WD_BTIMEOUT (jiffies + (HZ * 1000)) | ||
38 | #define WD_BLIMIT 0xFFFF | ||
39 | |||
40 | #define WD0_DEVNAME "watchdog0" | ||
41 | #define WD1_DEVNAME "watchdog1" | ||
42 | #define WD2_DEVNAME "watchdog2" | ||
43 | |||
44 | #define WD0_MINOR 212 | ||
45 | #define WD1_MINOR 213 | ||
46 | #define WD2_MINOR 214 | ||
47 | |||
48 | |||
49 | /* Internal driver definitions | ||
50 | */ | ||
51 | #define WD0_ID 0 /* Watchdog0 */ | ||
52 | #define WD1_ID 1 /* Watchdog1 */ | ||
53 | #define WD2_ID 2 /* Watchdog2 */ | ||
54 | #define WD_NUMDEVS 3 /* Device contains 3 timers */ | ||
55 | |||
56 | #define WD_INTR_OFF 0 /* Interrupt disable value */ | ||
57 | #define WD_INTR_ON 1 /* Interrupt enable value */ | ||
58 | |||
59 | #define WD_STAT_INIT 0x01 /* Watchdog timer is initialized */ | ||
60 | #define WD_STAT_BSTOP 0x02 /* Watchdog timer is brokenstopped */ | ||
61 | #define WD_STAT_SVCD 0x04 /* Watchdog interrupt occurred */ | ||
62 | |||
63 | /* Register value definitions | ||
64 | */ | ||
65 | #define WD0_INTR_MASK 0x01 /* Watchdog device interrupt masks */ | ||
66 | #define WD1_INTR_MASK 0x02 | ||
67 | #define WD2_INTR_MASK 0x04 | ||
68 | |||
69 | #define WD_S_RUNNING 0x01 /* Watchdog device status running */ | ||
70 | #define WD_S_EXPIRED 0x02 /* Watchdog device status expired */ | ||
71 | |||
72 | /* Sun uses Altera PLD EPF8820ATC144-4 | ||
73 | * providing three hardware watchdogs: | ||
74 | * | ||
75 | * 1) RIC - sends an interrupt when triggered | ||
76 | * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU | ||
77 | * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board | ||
78 | * | ||
79 | *** Timer register block definition (struct wd_timer_regblk) | ||
80 | * | ||
81 | * dcntr and limit registers (halfword access): | ||
82 | * ------------------- | ||
83 | * | 15 | ...| 1 | 0 | | ||
84 | * ------------------- | ||
85 | * |- counter val -| | ||
86 | * ------------------- | ||
87 | * dcntr - Current 16-bit downcounter value. | ||
88 | * When downcounter reaches '0' watchdog expires. | ||
89 | * Reading this register resets downcounter with 'limit' value. | ||
90 | * limit - 16-bit countdown value in 1/10th second increments. | ||
91 | * Writing this register begins countdown with input value. | ||
92 | * Reading from this register does not affect counter. | ||
93 | * NOTES: After watchdog reset, dcntr and limit contain '1' | ||
94 | * | ||
95 | * status register (byte access): | ||
96 | * --------------------------- | ||
97 | * | 7 | ... | 2 | 1 | 0 | | ||
98 | * --------------+------------ | ||
99 | * |- UNUSED -| EXP | RUN | | ||
100 | * --------------------------- | ||
101 | * status- Bit 0 - Watchdog is running | ||
102 | * Bit 1 - Watchdog has expired | ||
103 | * | ||
104 | *** PLD register block definition (struct wd_pld_regblk) | ||
105 | * | ||
106 | * intr_mask register (byte access): | ||
107 | * --------------------------------- | ||
108 | * | 7 | ... | 3 | 2 | 1 | 0 | | ||
109 | * +-------------+------------------ | ||
110 | * |- UNUSED -| WD3 | WD2 | WD1 | | ||
111 | * --------------------------------- | ||
112 | * WD3 - 1 == Interrupt disabled for watchdog 3 | ||
113 | * WD2 - 1 == Interrupt disabled for watchdog 2 | ||
114 | * WD1 - 1 == Interrupt disabled for watchdog 1 | ||
115 | * | ||
116 | * pld_status register (byte access): | ||
117 | * UNKNOWN, MAGICAL MYSTERY REGISTER | ||
118 | * | ||
119 | */ | ||
120 | #define WD_TIMER_REGSZ 16 | ||
121 | #define WD0_OFF 0 | ||
122 | #define WD1_OFF (WD_TIMER_REGSZ * 1) | ||
123 | #define WD2_OFF (WD_TIMER_REGSZ * 2) | ||
124 | #define PLD_OFF (WD_TIMER_REGSZ * 3) | ||
125 | |||
126 | #define WD_DCNTR 0x00 | ||
127 | #define WD_LIMIT 0x04 | ||
128 | #define WD_STATUS 0x08 | ||
129 | |||
130 | #define PLD_IMASK (PLD_OFF + 0x00) | ||
131 | #define PLD_STATUS (PLD_OFF + 0x04) | ||
132 | |||
133 | /* Individual timer structure | ||
134 | */ | ||
135 | struct wd_timer { | ||
136 | __u16 timeout; | ||
137 | __u8 intr_mask; | ||
138 | unsigned char runstatus; | ||
139 | void __iomem *regs; | ||
140 | }; | ||
141 | |||
142 | /* Device structure | ||
143 | */ | ||
144 | struct wd_device { | ||
145 | int irq; | ||
146 | spinlock_t lock; | ||
147 | unsigned char isbaddoggie; /* defective PLD */ | ||
148 | unsigned char opt_enable; | ||
149 | unsigned char opt_reboot; | ||
150 | unsigned short opt_timeout; | ||
151 | unsigned char initialized; | ||
152 | struct wd_timer watchdog[WD_NUMDEVS]; | ||
153 | void __iomem *regs; | ||
154 | }; | ||
155 | |||
156 | static struct wd_device wd_dev = { | ||
157 | 0, __SPIN_LOCK_UNLOCKED(wd_dev.lock), 0, 0, 0, 0, | ||
158 | }; | ||
159 | |||
160 | static struct timer_list wd_timer; | ||
161 | |||
162 | static int wd0_timeout = 0; | ||
163 | static int wd1_timeout = 0; | ||
164 | static int wd2_timeout = 0; | ||
165 | |||
166 | #ifdef MODULE | ||
167 | module_param (wd0_timeout, int, 0); | ||
168 | MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs"); | ||
169 | module_param (wd1_timeout, int, 0); | ||
170 | MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs"); | ||
171 | module_param (wd2_timeout, int, 0); | ||
172 | MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs"); | ||
173 | |||
174 | MODULE_AUTHOR | ||
175 | ("Eric Brower <ebrower@usa.net>"); | ||
176 | MODULE_DESCRIPTION | ||
177 | ("Hardware watchdog driver for Sun Microsystems CP1400/1500"); | ||
178 | MODULE_LICENSE("GPL"); | ||
179 | MODULE_SUPPORTED_DEVICE | ||
180 | ("watchdog"); | ||
181 | #endif /* ifdef MODULE */ | ||
182 | |||
183 | /* Forward declarations of internal methods | ||
184 | */ | ||
185 | #ifdef WD_DEBUG | ||
186 | static void wd_dumpregs(void); | ||
187 | #endif | ||
188 | static irqreturn_t wd_interrupt(int irq, void *dev_id); | ||
189 | static void wd_toggleintr(struct wd_timer* pTimer, int enable); | ||
190 | static void wd_pingtimer(struct wd_timer* pTimer); | ||
191 | static void wd_starttimer(struct wd_timer* pTimer); | ||
192 | static void wd_resetbrokentimer(struct wd_timer* pTimer); | ||
193 | static void wd_stoptimer(struct wd_timer* pTimer); | ||
194 | static void wd_brokentimer(unsigned long data); | ||
195 | static int wd_getstatus(struct wd_timer* pTimer); | ||
196 | |||
197 | /* PLD expects words to be written in LSB format, | ||
198 | * so we must flip all words prior to writing them to regs | ||
199 | */ | ||
200 | static inline unsigned short flip_word(unsigned short word) | ||
201 | { | ||
202 | return ((word & 0xff) << 8) | ((word >> 8) & 0xff); | ||
203 | } | ||
204 | |||
205 | #define wd_writew(val, addr) (writew(flip_word(val), addr)) | ||
206 | #define wd_readw(addr) (flip_word(readw(addr))) | ||
207 | #define wd_writeb(val, addr) (writeb(val, addr)) | ||
208 | #define wd_readb(addr) (readb(addr)) | ||
209 | |||
210 | |||
211 | /* CP1400s seem to have broken PLD implementations-- | ||
212 | * the interrupt_mask register cannot be written, so | ||
213 | * no timer interrupts can be masked within the PLD. | ||
214 | */ | ||
215 | static inline int wd_isbroken(void) | ||
216 | { | ||
217 | /* we could test this by read/write/read/restore | ||
218 | * on the interrupt mask register only if OBP | ||
219 | * 'watchdog-enable?' == FALSE, but it seems | ||
220 | * ubiquitous on CP1400s | ||
221 | */ | ||
222 | char val[32]; | ||
223 | prom_getproperty(prom_root_node, "model", val, sizeof(val)); | ||
224 | return((!strcmp(val, WD_BADMODEL)) ? 1 : 0); | ||
225 | } | ||
226 | |||
227 | /* Retrieve watchdog-enable? option from OBP | ||
228 | * Returns 0 if false, 1 if true | ||
229 | */ | ||
230 | static inline int wd_opt_enable(void) | ||
231 | { | ||
232 | int opt_node; | ||
233 | |||
234 | opt_node = prom_getchild(prom_root_node); | ||
235 | opt_node = prom_searchsiblings(opt_node, "options"); | ||
236 | return((-1 == prom_getint(opt_node, "watchdog-enable?")) ? 0 : 1); | ||
237 | } | ||
238 | |||
239 | /* Retrieve watchdog-reboot? option from OBP | ||
240 | * Returns 0 if false, 1 if true | ||
241 | */ | ||
242 | static inline int wd_opt_reboot(void) | ||
243 | { | ||
244 | int opt_node; | ||
245 | |||
246 | opt_node = prom_getchild(prom_root_node); | ||
247 | opt_node = prom_searchsiblings(opt_node, "options"); | ||
248 | return((-1 == prom_getint(opt_node, "watchdog-reboot?")) ? 0 : 1); | ||
249 | } | ||
250 | |||
251 | /* Retrieve watchdog-timeout option from OBP | ||
252 | * Returns OBP value, or 0 if not located | ||
253 | */ | ||
254 | static inline int wd_opt_timeout(void) | ||
255 | { | ||
256 | int opt_node; | ||
257 | char value[32]; | ||
258 | char *p = value; | ||
259 | |||
260 | opt_node = prom_getchild(prom_root_node); | ||
261 | opt_node = prom_searchsiblings(opt_node, "options"); | ||
262 | opt_node = prom_getproperty(opt_node, | ||
263 | "watchdog-timeout", | ||
264 | value, | ||
265 | sizeof(value)); | ||
266 | if(-1 != opt_node) { | ||
267 | /* atoi implementation */ | ||
268 | for(opt_node = 0; /* nop */; p++) { | ||
269 | if(*p >= '0' && *p <= '9') { | ||
270 | opt_node = (10*opt_node)+(*p-'0'); | ||
271 | } | ||
272 | else { | ||
273 | break; | ||
274 | } | ||
275 | } | ||
276 | } | ||
277 | return((-1 == opt_node) ? (0) : (opt_node)); | ||
278 | } | ||
279 | |||
280 | static int wd_open(struct inode *inode, struct file *f) | ||
281 | { | ||
282 | lock_kernel(); | ||
283 | switch(iminor(inode)) | ||
284 | { | ||
285 | case WD0_MINOR: | ||
286 | f->private_data = &wd_dev.watchdog[WD0_ID]; | ||
287 | break; | ||
288 | case WD1_MINOR: | ||
289 | f->private_data = &wd_dev.watchdog[WD1_ID]; | ||
290 | break; | ||
291 | case WD2_MINOR: | ||
292 | f->private_data = &wd_dev.watchdog[WD2_ID]; | ||
293 | break; | ||
294 | default: | ||
295 | unlock_kernel(); | ||
296 | return(-ENODEV); | ||
297 | } | ||
298 | |||
299 | /* Register IRQ on first open of device */ | ||
300 | if(0 == wd_dev.initialized) | ||
301 | { | ||
302 | if (request_irq(wd_dev.irq, | ||
303 | &wd_interrupt, | ||
304 | IRQF_SHARED, | ||
305 | WD_OBPNAME, | ||
306 | (void *)wd_dev.regs)) { | ||
307 | printk("%s: Cannot register IRQ %d\n", | ||
308 | WD_OBPNAME, wd_dev.irq); | ||
309 | unlock_kernel(); | ||
310 | return(-EBUSY); | ||
311 | } | ||
312 | wd_dev.initialized = 1; | ||
313 | } | ||
314 | |||
315 | unlock_kernel(); | ||
316 | return(nonseekable_open(inode, f)); | ||
317 | } | ||
318 | |||
319 | static int wd_release(struct inode *inode, struct file *file) | ||
320 | { | ||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int wd_ioctl(struct inode *inode, struct file *file, | ||
325 | unsigned int cmd, unsigned long arg) | ||
326 | { | ||
327 | int setopt = 0; | ||
328 | struct wd_timer* pTimer = (struct wd_timer*)file->private_data; | ||
329 | void __user *argp = (void __user *)arg; | ||
330 | struct watchdog_info info = { | ||
331 | 0, | ||
332 | 0, | ||
333 | "Altera EPF8820ATC144-4" | ||
334 | }; | ||
335 | |||
336 | if(NULL == pTimer) { | ||
337 | return(-EINVAL); | ||
338 | } | ||
339 | |||
340 | switch(cmd) | ||
341 | { | ||
342 | /* Generic Linux IOCTLs */ | ||
343 | case WDIOC_GETSUPPORT: | ||
344 | if(copy_to_user(argp, &info, sizeof(struct watchdog_info))) { | ||
345 | return(-EFAULT); | ||
346 | } | ||
347 | break; | ||
348 | case WDIOC_GETSTATUS: | ||
349 | case WDIOC_GETBOOTSTATUS: | ||
350 | if (put_user(0, (int __user *)argp)) | ||
351 | return -EFAULT; | ||
352 | break; | ||
353 | case WDIOC_KEEPALIVE: | ||
354 | wd_pingtimer(pTimer); | ||
355 | break; | ||
356 | case WDIOC_SETOPTIONS: | ||
357 | if(copy_from_user(&setopt, argp, sizeof(unsigned int))) { | ||
358 | return -EFAULT; | ||
359 | } | ||
360 | if(setopt & WDIOS_DISABLECARD) { | ||
361 | if(wd_dev.opt_enable) { | ||
362 | printk( | ||
363 | "%s: cannot disable watchdog in ENABLED mode\n", | ||
364 | WD_OBPNAME); | ||
365 | return(-EINVAL); | ||
366 | } | ||
367 | wd_stoptimer(pTimer); | ||
368 | } | ||
369 | else if(setopt & WDIOS_ENABLECARD) { | ||
370 | wd_starttimer(pTimer); | ||
371 | } | ||
372 | else { | ||
373 | return(-EINVAL); | ||
374 | } | ||
375 | break; | ||
376 | /* Solaris-compatible IOCTLs */ | ||
377 | case WIOCGSTAT: | ||
378 | setopt = wd_getstatus(pTimer); | ||
379 | if(copy_to_user(argp, &setopt, sizeof(unsigned int))) { | ||
380 | return(-EFAULT); | ||
381 | } | ||
382 | break; | ||
383 | case WIOCSTART: | ||
384 | wd_starttimer(pTimer); | ||
385 | break; | ||
386 | case WIOCSTOP: | ||
387 | if(wd_dev.opt_enable) { | ||
388 | printk("%s: cannot disable watchdog in ENABLED mode\n", | ||
389 | WD_OBPNAME); | ||
390 | return(-EINVAL); | ||
391 | } | ||
392 | wd_stoptimer(pTimer); | ||
393 | break; | ||
394 | default: | ||
395 | return(-EINVAL); | ||
396 | } | ||
397 | return(0); | ||
398 | } | ||
399 | |||
400 | static long wd_compat_ioctl(struct file *file, unsigned int cmd, | ||
401 | unsigned long arg) | ||
402 | { | ||
403 | int rval = -ENOIOCTLCMD; | ||
404 | |||
405 | switch (cmd) { | ||
406 | /* solaris ioctls are specific to this driver */ | ||
407 | case WIOCSTART: | ||
408 | case WIOCSTOP: | ||
409 | case WIOCGSTAT: | ||
410 | lock_kernel(); | ||
411 | rval = wd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); | ||
412 | unlock_kernel(); | ||
413 | break; | ||
414 | /* everything else is handled by the generic compat layer */ | ||
415 | default: | ||
416 | break; | ||
417 | } | ||
418 | |||
419 | return rval; | ||
420 | } | ||
421 | |||
422 | static ssize_t wd_write(struct file *file, | ||
423 | const char __user *buf, | ||
424 | size_t count, | ||
425 | loff_t *ppos) | ||
426 | { | ||
427 | struct wd_timer* pTimer = (struct wd_timer*)file->private_data; | ||
428 | |||
429 | if(NULL == pTimer) { | ||
430 | return(-EINVAL); | ||
431 | } | ||
432 | |||
433 | if (count) { | ||
434 | wd_pingtimer(pTimer); | ||
435 | return 1; | ||
436 | } | ||
437 | return 0; | ||
438 | } | ||
439 | |||
440 | static ssize_t wd_read(struct file * file, char __user *buffer, | ||
441 | size_t count, loff_t *ppos) | ||
442 | { | ||
443 | #ifdef WD_DEBUG | ||
444 | wd_dumpregs(); | ||
445 | return(0); | ||
446 | #else | ||
447 | return(-EINVAL); | ||
448 | #endif /* ifdef WD_DEBUG */ | ||
449 | } | ||
450 | |||
451 | static irqreturn_t wd_interrupt(int irq, void *dev_id) | ||
452 | { | ||
453 | /* Only WD0 will interrupt-- others are NMI and we won't | ||
454 | * see them here.... | ||
455 | */ | ||
456 | spin_lock_irq(&wd_dev.lock); | ||
457 | if((unsigned long)wd_dev.regs == (unsigned long)dev_id) | ||
458 | { | ||
459 | wd_stoptimer(&wd_dev.watchdog[WD0_ID]); | ||
460 | wd_dev.watchdog[WD0_ID].runstatus |= WD_STAT_SVCD; | ||
461 | } | ||
462 | spin_unlock_irq(&wd_dev.lock); | ||
463 | return IRQ_HANDLED; | ||
464 | } | ||
465 | |||
466 | static const struct file_operations wd_fops = { | ||
467 | .owner = THIS_MODULE, | ||
468 | .ioctl = wd_ioctl, | ||
469 | .compat_ioctl = wd_compat_ioctl, | ||
470 | .open = wd_open, | ||
471 | .write = wd_write, | ||
472 | .read = wd_read, | ||
473 | .release = wd_release, | ||
474 | }; | ||
475 | |||
476 | static struct miscdevice wd0_miscdev = { WD0_MINOR, WD0_DEVNAME, &wd_fops }; | ||
477 | static struct miscdevice wd1_miscdev = { WD1_MINOR, WD1_DEVNAME, &wd_fops }; | ||
478 | static struct miscdevice wd2_miscdev = { WD2_MINOR, WD2_DEVNAME, &wd_fops }; | ||
479 | |||
480 | #ifdef WD_DEBUG | ||
481 | static void wd_dumpregs(void) | ||
482 | { | ||
483 | /* Reading from downcounters initiates watchdog countdown-- | ||
484 | * Example is included below for illustration purposes. | ||
485 | */ | ||
486 | int i; | ||
487 | printk("%s: dumping register values\n", WD_OBPNAME); | ||
488 | for(i = WD0_ID; i < WD_NUMDEVS; ++i) { | ||
489 | /* printk("\t%s%i: dcntr at 0x%lx: 0x%x\n", | ||
490 | * WD_OBPNAME, | ||
491 | * i, | ||
492 | * (unsigned long)(&wd_dev.watchdog[i].regs->dcntr), | ||
493 | * readw(&wd_dev.watchdog[i].regs->dcntr)); | ||
494 | */ | ||
495 | printk("\t%s%i: limit at 0x%lx: 0x%x\n", | ||
496 | WD_OBPNAME, | ||
497 | i, | ||
498 | (unsigned long)(&wd_dev.watchdog[i].regs->limit), | ||
499 | readw(&wd_dev.watchdog[i].regs->limit)); | ||
500 | printk("\t%s%i: status at 0x%lx: 0x%x\n", | ||
501 | WD_OBPNAME, | ||
502 | i, | ||
503 | (unsigned long)(&wd_dev.watchdog[i].regs->status), | ||
504 | readb(&wd_dev.watchdog[i].regs->status)); | ||
505 | printk("\t%s%i: driver status: 0x%x\n", | ||
506 | WD_OBPNAME, | ||
507 | i, | ||
508 | wd_getstatus(&wd_dev.watchdog[i])); | ||
509 | } | ||
510 | printk("\tintr_mask at %p: 0x%x\n", | ||
511 | wd_dev.regs + PLD_IMASK, | ||
512 | readb(wd_dev.regs + PLD_IMASK)); | ||
513 | printk("\tpld_status at %p: 0x%x\n", | ||
514 | wd_dev.regs + PLD_STATUS, | ||
515 | readb(wd_dev.regs + PLD_STATUS)); | ||
516 | } | ||
517 | #endif | ||
518 | |||
519 | /* Enable or disable watchdog interrupts | ||
520 | * Because of the CP1400 defect this should only be | ||
521 | * called during initialzation or by wd_[start|stop]timer() | ||
522 | * | ||
523 | * pTimer - pointer to timer device, or NULL to indicate all timers | ||
524 | * enable - non-zero to enable interrupts, zero to disable | ||
525 | */ | ||
526 | static void wd_toggleintr(struct wd_timer* pTimer, int enable) | ||
527 | { | ||
528 | unsigned char curregs = wd_readb(wd_dev.regs + PLD_IMASK); | ||
529 | unsigned char setregs = | ||
530 | (NULL == pTimer) ? | ||
531 | (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : | ||
532 | (pTimer->intr_mask); | ||
533 | |||
534 | (WD_INTR_ON == enable) ? | ||
535 | (curregs &= ~setregs): | ||
536 | (curregs |= setregs); | ||
537 | |||
538 | wd_writeb(curregs, wd_dev.regs + PLD_IMASK); | ||
539 | return; | ||
540 | } | ||
541 | |||
542 | /* Reset countdown timer with 'limit' value and continue countdown. | ||
543 | * This will not start a stopped timer. | ||
544 | * | ||
545 | * pTimer - pointer to timer device | ||
546 | */ | ||
547 | static void wd_pingtimer(struct wd_timer* pTimer) | ||
548 | { | ||
549 | if (wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) { | ||
550 | wd_readw(pTimer->regs + WD_DCNTR); | ||
551 | } | ||
552 | } | ||
553 | |||
554 | /* Stop a running watchdog timer-- the timer actually keeps | ||
555 | * running, but the interrupt is masked so that no action is | ||
556 | * taken upon expiration. | ||
557 | * | ||
558 | * pTimer - pointer to timer device | ||
559 | */ | ||
560 | static void wd_stoptimer(struct wd_timer* pTimer) | ||
561 | { | ||
562 | if(wd_readb(pTimer->regs + WD_STATUS) & WD_S_RUNNING) { | ||
563 | wd_toggleintr(pTimer, WD_INTR_OFF); | ||
564 | |||
565 | if(wd_dev.isbaddoggie) { | ||
566 | pTimer->runstatus |= WD_STAT_BSTOP; | ||
567 | wd_brokentimer((unsigned long)&wd_dev); | ||
568 | } | ||
569 | } | ||
570 | } | ||
571 | |||
572 | /* Start a watchdog timer with the specified limit value | ||
573 | * If the watchdog is running, it will be restarted with | ||
574 | * the provided limit value. | ||
575 | * | ||
576 | * This function will enable interrupts on the specified | ||
577 | * watchdog. | ||
578 | * | ||
579 | * pTimer - pointer to timer device | ||
580 | * limit - limit (countdown) value in 1/10th seconds | ||
581 | */ | ||
582 | static void wd_starttimer(struct wd_timer* pTimer) | ||
583 | { | ||
584 | if(wd_dev.isbaddoggie) { | ||
585 | pTimer->runstatus &= ~WD_STAT_BSTOP; | ||
586 | } | ||
587 | pTimer->runstatus &= ~WD_STAT_SVCD; | ||
588 | |||
589 | wd_writew(pTimer->timeout, pTimer->regs + WD_LIMIT); | ||
590 | wd_toggleintr(pTimer, WD_INTR_ON); | ||
591 | } | ||
592 | |||
593 | /* Restarts timer with maximum limit value and | ||
594 | * does not unset 'brokenstop' value. | ||
595 | */ | ||
596 | static void wd_resetbrokentimer(struct wd_timer* pTimer) | ||
597 | { | ||
598 | wd_toggleintr(pTimer, WD_INTR_ON); | ||
599 | wd_writew(WD_BLIMIT, pTimer->regs + WD_LIMIT); | ||
600 | } | ||
601 | |||
602 | /* Timer device initialization helper. | ||
603 | * Returns 0 on success, other on failure | ||
604 | */ | ||
605 | static int wd_inittimer(int whichdog) | ||
606 | { | ||
607 | struct miscdevice *whichmisc; | ||
608 | void __iomem *whichregs; | ||
609 | char whichident[8]; | ||
610 | int whichmask; | ||
611 | __u16 whichlimit; | ||
612 | |||
613 | switch(whichdog) | ||
614 | { | ||
615 | case WD0_ID: | ||
616 | whichmisc = &wd0_miscdev; | ||
617 | strcpy(whichident, "RIC"); | ||
618 | whichregs = wd_dev.regs + WD0_OFF; | ||
619 | whichmask = WD0_INTR_MASK; | ||
620 | whichlimit= (0 == wd0_timeout) ? | ||
621 | (wd_dev.opt_timeout): | ||
622 | (wd0_timeout); | ||
623 | break; | ||
624 | case WD1_ID: | ||
625 | whichmisc = &wd1_miscdev; | ||
626 | strcpy(whichident, "XIR"); | ||
627 | whichregs = wd_dev.regs + WD1_OFF; | ||
628 | whichmask = WD1_INTR_MASK; | ||
629 | whichlimit= (0 == wd1_timeout) ? | ||
630 | (wd_dev.opt_timeout): | ||
631 | (wd1_timeout); | ||
632 | break; | ||
633 | case WD2_ID: | ||
634 | whichmisc = &wd2_miscdev; | ||
635 | strcpy(whichident, "POR"); | ||
636 | whichregs = wd_dev.regs + WD2_OFF; | ||
637 | whichmask = WD2_INTR_MASK; | ||
638 | whichlimit= (0 == wd2_timeout) ? | ||
639 | (wd_dev.opt_timeout): | ||
640 | (wd2_timeout); | ||
641 | break; | ||
642 | default: | ||
643 | printk("%s: %s: invalid watchdog id: %i\n", | ||
644 | WD_OBPNAME, __func__, whichdog); | ||
645 | return(1); | ||
646 | } | ||
647 | if(0 != misc_register(whichmisc)) | ||
648 | { | ||
649 | return(1); | ||
650 | } | ||
651 | wd_dev.watchdog[whichdog].regs = whichregs; | ||
652 | wd_dev.watchdog[whichdog].timeout = whichlimit; | ||
653 | wd_dev.watchdog[whichdog].intr_mask = whichmask; | ||
654 | wd_dev.watchdog[whichdog].runstatus &= ~WD_STAT_BSTOP; | ||
655 | wd_dev.watchdog[whichdog].runstatus |= WD_STAT_INIT; | ||
656 | |||
657 | printk("%s%i: %s hardware watchdog [%01i.%i sec] %s\n", | ||
658 | WD_OBPNAME, | ||
659 | whichdog, | ||
660 | whichident, | ||
661 | wd_dev.watchdog[whichdog].timeout / 10, | ||
662 | wd_dev.watchdog[whichdog].timeout % 10, | ||
663 | (0 != wd_dev.opt_enable) ? "in ENABLED mode" : ""); | ||
664 | return(0); | ||
665 | } | ||
666 | |||
667 | /* Timer method called to reset stopped watchdogs-- | ||
668 | * because of the PLD bug on CP1400, we cannot mask | ||
669 | * interrupts within the PLD so me must continually | ||
670 | * reset the timers ad infinitum. | ||
671 | */ | ||
672 | static void wd_brokentimer(unsigned long data) | ||
673 | { | ||
674 | struct wd_device* pDev = (struct wd_device*)data; | ||
675 | int id, tripped = 0; | ||
676 | |||
677 | /* kill a running timer instance, in case we | ||
678 | * were called directly instead of by kernel timer | ||
679 | */ | ||
680 | if(timer_pending(&wd_timer)) { | ||
681 | del_timer(&wd_timer); | ||
682 | } | ||
683 | |||
684 | for(id = WD0_ID; id < WD_NUMDEVS; ++id) { | ||
685 | if(pDev->watchdog[id].runstatus & WD_STAT_BSTOP) { | ||
686 | ++tripped; | ||
687 | wd_resetbrokentimer(&pDev->watchdog[id]); | ||
688 | } | ||
689 | } | ||
690 | |||
691 | if(tripped) { | ||
692 | /* there is at least one timer brokenstopped-- reschedule */ | ||
693 | init_timer(&wd_timer); | ||
694 | wd_timer.expires = WD_BTIMEOUT; | ||
695 | add_timer(&wd_timer); | ||
696 | } | ||
697 | } | ||
698 | |||
699 | static int wd_getstatus(struct wd_timer* pTimer) | ||
700 | { | ||
701 | unsigned char stat = wd_readb(pTimer->regs + WD_STATUS); | ||
702 | unsigned char intr = wd_readb(wd_dev.regs + PLD_IMASK); | ||
703 | unsigned char ret = WD_STOPPED; | ||
704 | |||
705 | /* determine STOPPED */ | ||
706 | if(0 == stat ) { | ||
707 | return(ret); | ||
708 | } | ||
709 | /* determine EXPIRED vs FREERUN vs RUNNING */ | ||
710 | else if(WD_S_EXPIRED & stat) { | ||
711 | ret = WD_EXPIRED; | ||
712 | } | ||
713 | else if(WD_S_RUNNING & stat) { | ||
714 | if(intr & pTimer->intr_mask) { | ||
715 | ret = WD_FREERUN; | ||
716 | } | ||
717 | else { | ||
718 | /* Fudge WD_EXPIRED status for defective CP1400-- | ||
719 | * IF timer is running | ||
720 | * AND brokenstop is set | ||
721 | * AND an interrupt has been serviced | ||
722 | * we are WD_EXPIRED. | ||
723 | * | ||
724 | * IF timer is running | ||
725 | * AND brokenstop is set | ||
726 | * AND no interrupt has been serviced | ||
727 | * we are WD_FREERUN. | ||
728 | */ | ||
729 | if(wd_dev.isbaddoggie && (pTimer->runstatus & WD_STAT_BSTOP)) { | ||
730 | if(pTimer->runstatus & WD_STAT_SVCD) { | ||
731 | ret = WD_EXPIRED; | ||
732 | } | ||
733 | else { | ||
734 | /* we could as well pretend we are expired */ | ||
735 | ret = WD_FREERUN; | ||
736 | } | ||
737 | } | ||
738 | else { | ||
739 | ret = WD_RUNNING; | ||
740 | } | ||
741 | } | ||
742 | } | ||
743 | |||
744 | /* determine SERVICED */ | ||
745 | if(pTimer->runstatus & WD_STAT_SVCD) { | ||
746 | ret |= WD_SERVICED; | ||
747 | } | ||
748 | |||
749 | return(ret); | ||
750 | } | ||
751 | |||
752 | static int __init wd_init(void) | ||
753 | { | ||
754 | int id; | ||
755 | struct linux_ebus *ebus = NULL; | ||
756 | struct linux_ebus_device *edev = NULL; | ||
757 | |||
758 | for_each_ebus(ebus) { | ||
759 | for_each_ebusdev(edev, ebus) { | ||
760 | if (!strcmp(edev->ofdev.node->name, WD_OBPNAME)) | ||
761 | goto ebus_done; | ||
762 | } | ||
763 | } | ||
764 | |||
765 | ebus_done: | ||
766 | if(!edev) { | ||
767 | printk("%s: unable to locate device\n", WD_OBPNAME); | ||
768 | return -ENODEV; | ||
769 | } | ||
770 | |||
771 | wd_dev.regs = | ||
772 | ioremap(edev->resource[0].start, 4 * WD_TIMER_REGSZ); /* ? */ | ||
773 | |||
774 | if(NULL == wd_dev.regs) { | ||
775 | printk("%s: unable to map registers\n", WD_OBPNAME); | ||
776 | return(-ENODEV); | ||
777 | } | ||
778 | |||
779 | /* initialize device structure from OBP parameters */ | ||
780 | wd_dev.irq = edev->irqs[0]; | ||
781 | wd_dev.opt_enable = wd_opt_enable(); | ||
782 | wd_dev.opt_reboot = wd_opt_reboot(); | ||
783 | wd_dev.opt_timeout = wd_opt_timeout(); | ||
784 | wd_dev.isbaddoggie = wd_isbroken(); | ||
785 | |||
786 | /* disable all interrupts unless watchdog-enabled? == true */ | ||
787 | if(! wd_dev.opt_enable) { | ||
788 | wd_toggleintr(NULL, WD_INTR_OFF); | ||
789 | } | ||
790 | |||
791 | /* register miscellaneous devices */ | ||
792 | for(id = WD0_ID; id < WD_NUMDEVS; ++id) { | ||
793 | if(0 != wd_inittimer(id)) { | ||
794 | printk("%s%i: unable to initialize\n", WD_OBPNAME, id); | ||
795 | } | ||
796 | } | ||
797 | |||
798 | /* warn about possible defective PLD */ | ||
799 | if(wd_dev.isbaddoggie) { | ||
800 | init_timer(&wd_timer); | ||
801 | wd_timer.function = wd_brokentimer; | ||
802 | wd_timer.data = (unsigned long)&wd_dev; | ||
803 | wd_timer.expires = WD_BTIMEOUT; | ||
804 | |||
805 | printk("%s: PLD defect workaround enabled for model %s\n", | ||
806 | WD_OBPNAME, WD_BADMODEL); | ||
807 | } | ||
808 | return(0); | ||
809 | } | ||
810 | |||
811 | static void __exit wd_cleanup(void) | ||
812 | { | ||
813 | int id; | ||
814 | |||
815 | /* if 'watchdog-enable?' == TRUE, timers are not stopped | ||
816 | * when module is unloaded. All brokenstopped timers will | ||
817 | * also now eventually trip. | ||
818 | */ | ||
819 | for(id = WD0_ID; id < WD_NUMDEVS; ++id) { | ||
820 | if(WD_S_RUNNING == wd_readb(wd_dev.watchdog[id].regs + WD_STATUS)) { | ||
821 | if(wd_dev.opt_enable) { | ||
822 | printk(KERN_WARNING "%s%i: timer not stopped at release\n", | ||
823 | WD_OBPNAME, id); | ||
824 | } | ||
825 | else { | ||
826 | wd_stoptimer(&wd_dev.watchdog[id]); | ||
827 | if(wd_dev.watchdog[id].runstatus & WD_STAT_BSTOP) { | ||
828 | wd_resetbrokentimer(&wd_dev.watchdog[id]); | ||
829 | printk(KERN_WARNING | ||
830 | "%s%i: defect workaround disabled at release, "\ | ||
831 | "timer expires in ~%01i sec\n", | ||
832 | WD_OBPNAME, id, | ||
833 | wd_readw(wd_dev.watchdog[id].regs + WD_LIMIT) / 10); | ||
834 | } | ||
835 | } | ||
836 | } | ||
837 | } | ||
838 | |||
839 | if(wd_dev.isbaddoggie && timer_pending(&wd_timer)) { | ||
840 | del_timer(&wd_timer); | ||
841 | } | ||
842 | if(0 != (wd_dev.watchdog[WD0_ID].runstatus & WD_STAT_INIT)) { | ||
843 | misc_deregister(&wd0_miscdev); | ||
844 | } | ||
845 | if(0 != (wd_dev.watchdog[WD1_ID].runstatus & WD_STAT_INIT)) { | ||
846 | misc_deregister(&wd1_miscdev); | ||
847 | } | ||
848 | if(0 != (wd_dev.watchdog[WD2_ID].runstatus & WD_STAT_INIT)) { | ||
849 | misc_deregister(&wd2_miscdev); | ||
850 | } | ||
851 | if(0 != wd_dev.initialized) { | ||
852 | free_irq(wd_dev.irq, (void *)wd_dev.regs); | ||
853 | } | ||
854 | iounmap(wd_dev.regs); | ||
855 | } | ||
856 | |||
857 | module_init(wd_init); | ||
858 | module_exit(wd_cleanup); | ||
diff --git a/drivers/sbus/char/display7seg.c b/drivers/sbus/char/display7seg.c index d8f5c0ca236d..2550af4ae432 100644 --- a/drivers/sbus/char/display7seg.c +++ b/drivers/sbus/char/display7seg.c | |||
@@ -1,10 +1,7 @@ | |||
1 | /* $Id: display7seg.c,v 1.6 2002/01/08 16:00:16 davem Exp $ | 1 | /* display7seg.c - Driver implementation for the 7-segment display |
2 | * | 2 | * present on Sun Microsystems CP1400 and CP1500 |
3 | * display7seg - Driver implementation for the 7-segment display | ||
4 | * present on Sun Microsystems CP1400 and CP1500 | ||
5 | * | 3 | * |
6 | * Copyright (c) 2000 Eric Brower (ebrower@usa.net) | 4 | * Copyright (c) 2000 Eric Brower (ebrower@usa.net) |
7 | * | ||
8 | */ | 5 | */ |
9 | 6 | ||
10 | #include <linux/kernel.h> | 7 | #include <linux/kernel.h> |
@@ -16,22 +13,20 @@ | |||
16 | #include <linux/miscdevice.h> | 13 | #include <linux/miscdevice.h> |
17 | #include <linux/ioport.h> /* request_region */ | 14 | #include <linux/ioport.h> /* request_region */ |
18 | #include <linux/smp_lock.h> | 15 | #include <linux/smp_lock.h> |
16 | #include <linux/of.h> | ||
17 | #include <linux/of_device.h> | ||
19 | #include <asm/atomic.h> | 18 | #include <asm/atomic.h> |
20 | #include <asm/ebus.h> /* EBus device */ | ||
21 | #include <asm/oplib.h> /* OpenProm Library */ | ||
22 | #include <asm/uaccess.h> /* put_/get_user */ | 19 | #include <asm/uaccess.h> /* put_/get_user */ |
23 | #include <asm/io.h> | 20 | #include <asm/io.h> |
24 | 21 | ||
25 | #include <asm/display7seg.h> | 22 | #include <asm/display7seg.h> |
26 | 23 | ||
27 | #define D7S_MINOR 193 | 24 | #define D7S_MINOR 193 |
28 | #define D7S_OBPNAME "display7seg" | 25 | #define DRIVER_NAME "d7s" |
29 | #define D7S_DEVNAME "d7s" | 26 | #define PFX DRIVER_NAME ": " |
30 | 27 | ||
31 | static int sol_compat = 0; /* Solaris compatibility mode */ | 28 | static int sol_compat = 0; /* Solaris compatibility mode */ |
32 | 29 | ||
33 | #ifdef MODULE | ||
34 | |||
35 | /* Solaris compatibility flag - | 30 | /* Solaris compatibility flag - |
36 | * The Solaris implementation omits support for several | 31 | * The Solaris implementation omits support for several |
37 | * documented driver features (ref Sun doc 806-0180-03). | 32 | * documented driver features (ref Sun doc 806-0180-03). |
@@ -46,20 +41,20 @@ static int sol_compat = 0; /* Solaris compatibility mode */ | |||
46 | * If you wish the device to operate as under Solaris, | 41 | * If you wish the device to operate as under Solaris, |
47 | * omitting above features, set this parameter to non-zero. | 42 | * omitting above features, set this parameter to non-zero. |
48 | */ | 43 | */ |
49 | module_param | 44 | module_param(sol_compat, int, 0); |
50 | (sol_compat, int, 0); | 45 | MODULE_PARM_DESC(sol_compat, |
51 | MODULE_PARM_DESC | 46 | "Disables documented functionality omitted from Solaris driver"); |
52 | (sol_compat, | 47 | |
53 | "Disables documented functionality omitted from Solaris driver"); | 48 | MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); |
54 | 49 | MODULE_DESCRIPTION("7-Segment Display driver for Sun Microsystems CP1400/1500"); | |
55 | MODULE_AUTHOR | ||
56 | ("Eric Brower <ebrower@usa.net>"); | ||
57 | MODULE_DESCRIPTION | ||
58 | ("7-Segment Display driver for Sun Microsystems CP1400/1500"); | ||
59 | MODULE_LICENSE("GPL"); | 50 | MODULE_LICENSE("GPL"); |
60 | MODULE_SUPPORTED_DEVICE | 51 | MODULE_SUPPORTED_DEVICE("d7s"); |
61 | ("d7s"); | 52 | |
62 | #endif /* ifdef MODULE */ | 53 | struct d7s { |
54 | void __iomem *regs; | ||
55 | bool flipped; | ||
56 | }; | ||
57 | struct d7s *d7s_device; | ||
63 | 58 | ||
64 | /* | 59 | /* |
65 | * Register block address- see header for details | 60 | * Register block address- see header for details |
@@ -72,22 +67,6 @@ MODULE_SUPPORTED_DEVICE | |||
72 | * FLIP - Inverts display for upside-down mounted board | 67 | * FLIP - Inverts display for upside-down mounted board |
73 | * bits 0-4 - 7-segment display contents | 68 | * bits 0-4 - 7-segment display contents |
74 | */ | 69 | */ |
75 | static void __iomem* d7s_regs; | ||
76 | |||
77 | static inline void d7s_free(void) | ||
78 | { | ||
79 | iounmap(d7s_regs); | ||
80 | } | ||
81 | |||
82 | static inline int d7s_obpflipped(void) | ||
83 | { | ||
84 | int opt_node; | ||
85 | |||
86 | opt_node = prom_getchild(prom_root_node); | ||
87 | opt_node = prom_searchsiblings(opt_node, "options"); | ||
88 | return ((-1 != prom_getintdefault(opt_node, "d7s-flipped?", -1)) ? 0 : 1); | ||
89 | } | ||
90 | |||
91 | static atomic_t d7s_users = ATOMIC_INIT(0); | 70 | static atomic_t d7s_users = ATOMIC_INIT(0); |
92 | 71 | ||
93 | static int d7s_open(struct inode *inode, struct file *f) | 72 | static int d7s_open(struct inode *inode, struct file *f) |
@@ -106,12 +85,15 @@ static int d7s_release(struct inode *inode, struct file *f) | |||
106 | * are not operating in solaris-compat mode | 85 | * are not operating in solaris-compat mode |
107 | */ | 86 | */ |
108 | if (atomic_dec_and_test(&d7s_users) && !sol_compat) { | 87 | if (atomic_dec_and_test(&d7s_users) && !sol_compat) { |
109 | int regval = 0; | 88 | struct d7s *p = d7s_device; |
110 | 89 | u8 regval = 0; | |
111 | regval = readb(d7s_regs); | 90 | |
112 | (0 == d7s_obpflipped()) ? | 91 | regval = readb(p->regs); |
113 | writeb(regval |= D7S_FLIP, d7s_regs): | 92 | if (p->flipped) |
114 | writeb(regval &= ~D7S_FLIP, d7s_regs); | 93 | regval |= D7S_FLIP; |
94 | else | ||
95 | regval &= ~D7S_FLIP; | ||
96 | writeb(regval, p->regs); | ||
115 | } | 97 | } |
116 | 98 | ||
117 | return 0; | 99 | return 0; |
@@ -119,9 +101,10 @@ static int d7s_release(struct inode *inode, struct file *f) | |||
119 | 101 | ||
120 | static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | 102 | static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
121 | { | 103 | { |
122 | __u8 regs = readb(d7s_regs); | 104 | struct d7s *p = d7s_device; |
123 | __u8 ireg = 0; | 105 | u8 regs = readb(p->regs); |
124 | int error = 0; | 106 | int error = 0; |
107 | u8 ireg = 0; | ||
125 | 108 | ||
126 | if (D7S_MINOR != iminor(file->f_path.dentry->d_inode)) | 109 | if (D7S_MINOR != iminor(file->f_path.dentry->d_inode)) |
127 | return -ENODEV; | 110 | return -ENODEV; |
@@ -129,18 +112,20 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
129 | lock_kernel(); | 112 | lock_kernel(); |
130 | switch (cmd) { | 113 | switch (cmd) { |
131 | case D7SIOCWR: | 114 | case D7SIOCWR: |
132 | /* assign device register values | 115 | /* assign device register values we mask-out D7S_FLIP |
133 | * we mask-out D7S_FLIP if in sol_compat mode | 116 | * if in sol_compat mode |
134 | */ | 117 | */ |
135 | if (get_user(ireg, (int __user *) arg)) { | 118 | if (get_user(ireg, (int __user *) arg)) { |
136 | error = -EFAULT; | 119 | error = -EFAULT; |
137 | break; | 120 | break; |
138 | } | 121 | } |
139 | if (0 != sol_compat) { | 122 | if (sol_compat) { |
140 | (regs & D7S_FLIP) ? | 123 | if (regs & D7S_FLIP) |
141 | (ireg |= D7S_FLIP) : (ireg &= ~D7S_FLIP); | 124 | ireg |= D7S_FLIP; |
125 | else | ||
126 | ireg &= ~D7S_FLIP; | ||
142 | } | 127 | } |
143 | writeb(ireg, d7s_regs); | 128 | writeb(ireg, p->regs); |
144 | break; | 129 | break; |
145 | 130 | ||
146 | case D7SIOCRD: | 131 | case D7SIOCRD: |
@@ -158,9 +143,11 @@ static long d7s_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | |||
158 | 143 | ||
159 | case D7SIOCTM: | 144 | case D7SIOCTM: |
160 | /* toggle device mode-- flip display orientation */ | 145 | /* toggle device mode-- flip display orientation */ |
161 | (regs & D7S_FLIP) ? | 146 | if (regs & D7S_FLIP) |
162 | (regs &= ~D7S_FLIP) : (regs |= D7S_FLIP); | 147 | regs &= ~D7S_FLIP; |
163 | writeb(regs, d7s_regs); | 148 | else |
149 | regs |= D7S_FLIP; | ||
150 | writeb(regs, p->regs); | ||
164 | break; | 151 | break; |
165 | }; | 152 | }; |
166 | unlock_kernel(); | 153 | unlock_kernel(); |
@@ -176,69 +163,123 @@ static const struct file_operations d7s_fops = { | |||
176 | .release = d7s_release, | 163 | .release = d7s_release, |
177 | }; | 164 | }; |
178 | 165 | ||
179 | static struct miscdevice d7s_miscdev = { D7S_MINOR, D7S_DEVNAME, &d7s_fops }; | 166 | static struct miscdevice d7s_miscdev = { |
167 | .minor = D7S_MINOR, | ||
168 | .name = DRIVER_NAME, | ||
169 | .fops = &d7s_fops | ||
170 | }; | ||
180 | 171 | ||
181 | static int __init d7s_init(void) | 172 | static int __devinit d7s_probe(struct of_device *op, |
173 | const struct of_device_id *match) | ||
182 | { | 174 | { |
183 | struct linux_ebus *ebus = NULL; | 175 | struct device_node *opts; |
184 | struct linux_ebus_device *edev = NULL; | 176 | int err = -EINVAL; |
185 | int iTmp = 0, regs = 0; | 177 | struct d7s *p; |
186 | 178 | u8 regs; | |
187 | for_each_ebus(ebus) { | 179 | |
188 | for_each_ebusdev(edev, ebus) { | 180 | if (d7s_device) |
189 | if (!strcmp(edev->prom_node->name, D7S_OBPNAME)) | 181 | goto out; |
190 | goto ebus_done; | 182 | |
191 | } | 183 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
184 | err = -ENOMEM; | ||
185 | if (!p) | ||
186 | goto out; | ||
187 | |||
188 | p->regs = of_ioremap(&op->resource[0], 0, sizeof(u8), "d7s"); | ||
189 | if (!p->regs) { | ||
190 | printk(KERN_ERR PFX "Cannot map chip registers\n"); | ||
191 | goto out_free; | ||
192 | } | 192 | } |
193 | 193 | ||
194 | ebus_done: | 194 | err = misc_register(&d7s_miscdev); |
195 | if(!edev) { | 195 | if (err) { |
196 | printk("%s: unable to locate device\n", D7S_DEVNAME); | 196 | printk(KERN_ERR PFX "Unable to acquire miscdevice minor %i\n", |
197 | return -ENODEV; | 197 | D7S_MINOR); |
198 | goto out_iounmap; | ||
198 | } | 199 | } |
199 | 200 | ||
200 | d7s_regs = ioremap(edev->resource[0].start, sizeof(__u8)); | 201 | /* OBP option "d7s-flipped?" is honored as default for the |
201 | 202 | * device, and reset default when detached | |
202 | iTmp = misc_register(&d7s_miscdev); | ||
203 | if (0 != iTmp) { | ||
204 | printk("%s: unable to acquire miscdevice minor %i\n", | ||
205 | D7S_DEVNAME, D7S_MINOR); | ||
206 | iounmap(d7s_regs); | ||
207 | return iTmp; | ||
208 | } | ||
209 | |||
210 | /* OBP option "d7s-flipped?" is honored as default | ||
211 | * for the device, and reset default when detached | ||
212 | */ | 203 | */ |
213 | regs = readb(d7s_regs); | 204 | regs = readb(p->regs); |
214 | iTmp = d7s_obpflipped(); | 205 | opts = of_find_node_by_path("/options"); |
215 | (0 == iTmp) ? | 206 | if (opts && |
216 | writeb(regs |= D7S_FLIP, d7s_regs): | 207 | of_get_property(opts, "d7s-flipped?", NULL)) |
217 | writeb(regs &= ~D7S_FLIP, d7s_regs); | 208 | p->flipped = true; |
218 | 209 | ||
219 | printk("%s: 7-Segment Display%s at 0x%lx %s\n", | 210 | if (p->flipped) |
220 | D7S_DEVNAME, | 211 | regs |= D7S_FLIP; |
221 | (0 == iTmp) ? (" (FLIPPED)") : (""), | 212 | else |
222 | edev->resource[0].start, | 213 | regs &= ~D7S_FLIP; |
223 | (0 != sol_compat) ? ("in sol_compat mode") : ("")); | 214 | |
224 | 215 | writeb(regs, p->regs); | |
225 | return 0; | 216 | |
217 | printk(KERN_INFO PFX "7-Segment Display%s at [%s:0x%lx] %s\n", | ||
218 | op->node->full_name, | ||
219 | (regs & D7S_FLIP) ? " (FLIPPED)" : "", | ||
220 | op->resource[0].start, | ||
221 | sol_compat ? "in sol_compat mode" : ""); | ||
222 | |||
223 | dev_set_drvdata(&op->dev, p); | ||
224 | d7s_device = p; | ||
225 | err = 0; | ||
226 | |||
227 | out: | ||
228 | return err; | ||
229 | |||
230 | out_iounmap: | ||
231 | of_iounmap(&op->resource[0], p->regs, sizeof(u8)); | ||
232 | |||
233 | out_free: | ||
234 | kfree(p); | ||
235 | goto out; | ||
226 | } | 236 | } |
227 | 237 | ||
228 | static void __exit d7s_cleanup(void) | 238 | static int __devexit d7s_remove(struct of_device *op) |
229 | { | 239 | { |
230 | int regs = readb(d7s_regs); | 240 | struct d7s *p = dev_get_drvdata(&op->dev); |
241 | u8 regs = readb(p->regs); | ||
231 | 242 | ||
232 | /* Honor OBP d7s-flipped? unless operating in solaris-compat mode */ | 243 | /* Honor OBP d7s-flipped? unless operating in solaris-compat mode */ |
233 | if (0 == sol_compat) { | 244 | if (sol_compat) { |
234 | (0 == d7s_obpflipped()) ? | 245 | if (p->flipped) |
235 | writeb(regs |= D7S_FLIP, d7s_regs): | 246 | regs |= D7S_FLIP; |
236 | writeb(regs &= ~D7S_FLIP, d7s_regs); | 247 | else |
248 | regs &= ~D7S_FLIP; | ||
249 | writeb(regs, p->regs); | ||
237 | } | 250 | } |
238 | 251 | ||
239 | misc_deregister(&d7s_miscdev); | 252 | misc_deregister(&d7s_miscdev); |
240 | d7s_free(); | 253 | of_iounmap(&op->resource[0], p->regs, sizeof(u8)); |
254 | kfree(p); | ||
255 | |||
256 | return 0; | ||
257 | } | ||
258 | |||
259 | static const struct of_device_id d7s_match[] = { | ||
260 | { | ||
261 | .name = "display7seg", | ||
262 | }, | ||
263 | {}, | ||
264 | }; | ||
265 | MODULE_DEVICE_TABLE(of, d7s_match); | ||
266 | |||
267 | static struct of_platform_driver d7s_driver = { | ||
268 | .name = DRIVER_NAME, | ||
269 | .match_table = d7s_match, | ||
270 | .probe = d7s_probe, | ||
271 | .remove = __devexit_p(d7s_remove), | ||
272 | }; | ||
273 | |||
274 | static int __init d7s_init(void) | ||
275 | { | ||
276 | return of_register_driver(&d7s_driver, &of_bus_type); | ||
277 | } | ||
278 | |||
279 | static void __exit d7s_exit(void) | ||
280 | { | ||
281 | of_unregister_driver(&d7s_driver); | ||
241 | } | 282 | } |
242 | 283 | ||
243 | module_init(d7s_init); | 284 | module_init(d7s_init); |
244 | module_exit(d7s_cleanup); | 285 | module_exit(d7s_exit); |
diff --git a/drivers/sbus/char/envctrl.c b/drivers/sbus/char/envctrl.c index a408402426f8..58e583b61e60 100644 --- a/drivers/sbus/char/envctrl.c +++ b/drivers/sbus/char/envctrl.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* $Id: envctrl.c,v 1.25 2002/01/15 09:01:26 davem Exp $ | 1 | /* envctrl.c: Temperature and Fan monitoring on Machines providing it. |
2 | * envctrl.c: Temperature and Fan monitoring on Machines providing it. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) | 3 | * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be) |
5 | * Copyright (C) 2000 Vinh Truong (vinh.truong@eng.sun.com) | 4 | * Copyright (C) 2000 Vinh Truong (vinh.truong@eng.sun.com) |
@@ -28,12 +27,16 @@ | |||
28 | #include <linux/kmod.h> | 27 | #include <linux/kmod.h> |
29 | #include <linux/reboot.h> | 28 | #include <linux/reboot.h> |
30 | #include <linux/smp_lock.h> | 29 | #include <linux/smp_lock.h> |
30 | #include <linux/of.h> | ||
31 | #include <linux/of_device.h> | ||
31 | 32 | ||
32 | #include <asm/ebus.h> | ||
33 | #include <asm/uaccess.h> | 33 | #include <asm/uaccess.h> |
34 | #include <asm/envctrl.h> | 34 | #include <asm/envctrl.h> |
35 | #include <asm/io.h> | 35 | #include <asm/io.h> |
36 | 36 | ||
37 | #define DRIVER_NAME "envctrl" | ||
38 | #define PFX DRIVER_NAME ": " | ||
39 | |||
37 | #define ENVCTRL_MINOR 162 | 40 | #define ENVCTRL_MINOR 162 |
38 | 41 | ||
39 | #define PCF8584_ADDRESS 0x55 | 42 | #define PCF8584_ADDRESS 0x55 |
@@ -193,7 +196,7 @@ static void envtrl_i2c_test_pin(void) | |||
193 | } | 196 | } |
194 | 197 | ||
195 | if (limit <= 0) | 198 | if (limit <= 0) |
196 | printk(KERN_INFO "envctrl: Pin status will not clear.\n"); | 199 | printk(KERN_INFO PFX "Pin status will not clear.\n"); |
197 | } | 200 | } |
198 | 201 | ||
199 | /* Function Description: Test busy bit. | 202 | /* Function Description: Test busy bit. |
@@ -211,7 +214,7 @@ static void envctrl_i2c_test_bb(void) | |||
211 | } | 214 | } |
212 | 215 | ||
213 | if (limit <= 0) | 216 | if (limit <= 0) |
214 | printk(KERN_INFO "envctrl: Busy bit will not clear.\n"); | 217 | printk(KERN_INFO PFX "Busy bit will not clear.\n"); |
215 | } | 218 | } |
216 | 219 | ||
217 | /* Function Description: Send the address for a read access. | 220 | /* Function Description: Send the address for a read access. |
@@ -858,11 +861,10 @@ static void envctrl_init_voltage_status(struct i2c_child_t *pchild) | |||
858 | /* Function Description: Initialize i2c child device. | 861 | /* Function Description: Initialize i2c child device. |
859 | * Return: None. | 862 | * Return: None. |
860 | */ | 863 | */ |
861 | static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, | 864 | static void envctrl_init_i2c_child(struct device_node *dp, |
862 | struct i2c_child_t *pchild) | 865 | struct i2c_child_t *pchild) |
863 | { | 866 | { |
864 | int len, i, tbls_size = 0; | 867 | int len, i, tbls_size = 0; |
865 | struct device_node *dp = edev_child->prom_node; | ||
866 | const void *pval; | 868 | const void *pval; |
867 | 869 | ||
868 | /* Get device address. */ | 870 | /* Get device address. */ |
@@ -882,12 +884,12 @@ static void envctrl_init_i2c_child(struct linux_ebus_child *edev_child, | |||
882 | 884 | ||
883 | pchild->tables = kmalloc(tbls_size, GFP_KERNEL); | 885 | pchild->tables = kmalloc(tbls_size, GFP_KERNEL); |
884 | if (pchild->tables == NULL){ | 886 | if (pchild->tables == NULL){ |
885 | printk("envctrl: Failed to allocate table.\n"); | 887 | printk(KERN_ERR PFX "Failed to allocate table.\n"); |
886 | return; | 888 | return; |
887 | } | 889 | } |
888 | pval = of_get_property(dp, "tables", &len); | 890 | pval = of_get_property(dp, "tables", &len); |
889 | if (!pval || len <= 0) { | 891 | if (!pval || len <= 0) { |
890 | printk("envctrl: Failed to get table.\n"); | 892 | printk(KERN_ERR PFX "Failed to get table.\n"); |
891 | return; | 893 | return; |
892 | } | 894 | } |
893 | memcpy(pchild->tables, pval, len); | 895 | memcpy(pchild->tables, pval, len); |
@@ -993,14 +995,14 @@ static int kenvctrld(void *__unused) | |||
993 | struct i2c_child_t *cputemp; | 995 | struct i2c_child_t *cputemp; |
994 | 996 | ||
995 | if (NULL == (cputemp = envctrl_get_i2c_child(ENVCTRL_CPUTEMP_MON))) { | 997 | if (NULL == (cputemp = envctrl_get_i2c_child(ENVCTRL_CPUTEMP_MON))) { |
996 | printk(KERN_ERR | 998 | printk(KERN_ERR PFX |
997 | "envctrl: kenvctrld unable to monitor CPU temp-- exiting\n"); | 999 | "kenvctrld unable to monitor CPU temp-- exiting\n"); |
998 | return -ENODEV; | 1000 | return -ENODEV; |
999 | } | 1001 | } |
1000 | 1002 | ||
1001 | poll_interval = 5000; /* TODO env_mon_interval */ | 1003 | poll_interval = 5000; /* TODO env_mon_interval */ |
1002 | 1004 | ||
1003 | printk(KERN_INFO "envctrl: %s starting...\n", current->comm); | 1005 | printk(KERN_INFO PFX "%s starting...\n", current->comm); |
1004 | for (;;) { | 1006 | for (;;) { |
1005 | msleep_interruptible(poll_interval); | 1007 | msleep_interruptible(poll_interval); |
1006 | 1008 | ||
@@ -1022,54 +1024,35 @@ static int kenvctrld(void *__unused) | |||
1022 | } | 1024 | } |
1023 | } | 1025 | } |
1024 | } | 1026 | } |
1025 | printk(KERN_INFO "envctrl: %s exiting...\n", current->comm); | 1027 | printk(KERN_INFO PFX "%s exiting...\n", current->comm); |
1026 | return 0; | 1028 | return 0; |
1027 | } | 1029 | } |
1028 | 1030 | ||
1029 | static int __init envctrl_init(void) | 1031 | static int __devinit envctrl_probe(struct of_device *op, |
1032 | const struct of_device_id *match) | ||
1030 | { | 1033 | { |
1031 | struct linux_ebus *ebus = NULL; | 1034 | struct device_node *dp; |
1032 | struct linux_ebus_device *edev = NULL; | 1035 | int index, err; |
1033 | struct linux_ebus_child *edev_child = NULL; | ||
1034 | int err, i = 0; | ||
1035 | |||
1036 | for_each_ebus(ebus) { | ||
1037 | for_each_ebusdev(edev, ebus) { | ||
1038 | if (!strcmp(edev->prom_node->name, "bbc")) { | ||
1039 | /* If we find a boot-bus controller node, | ||
1040 | * then this envctrl driver is not for us. | ||
1041 | */ | ||
1042 | return -ENODEV; | ||
1043 | } | ||
1044 | } | ||
1045 | } | ||
1046 | 1036 | ||
1047 | /* Traverse through ebus and ebus device list for i2c device and | 1037 | if (i2c) |
1048 | * adc and gpio nodes. | 1038 | return -EINVAL; |
1049 | */ | 1039 | |
1050 | for_each_ebus(ebus) { | 1040 | i2c = of_ioremap(&op->resource[0], 0, 0x2, DRIVER_NAME); |
1051 | for_each_ebusdev(edev, ebus) { | 1041 | if (!i2c) |
1052 | if (!strcmp(edev->prom_node->name, "i2c")) { | 1042 | return -ENOMEM; |
1053 | i2c = ioremap(edev->resource[0].start, 0x2); | 1043 | |
1054 | for_each_edevchild(edev, edev_child) { | 1044 | index = 0; |
1055 | if (!strcmp("gpio", edev_child->prom_node->name)) { | 1045 | dp = op->node->child; |
1056 | i2c_childlist[i].i2ctype = I2C_GPIO; | 1046 | while (dp) { |
1057 | envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); | 1047 | if (!strcmp(dp->name, "gpio")) { |
1058 | } | 1048 | i2c_childlist[index].i2ctype = I2C_GPIO; |
1059 | if (!strcmp("adc", edev_child->prom_node->name)) { | 1049 | envctrl_init_i2c_child(dp, &(i2c_childlist[index++])); |
1060 | i2c_childlist[i].i2ctype = I2C_ADC; | 1050 | } else if (!strcmp(dp->name, "adc")) { |
1061 | envctrl_init_i2c_child(edev_child, &(i2c_childlist[i++])); | 1051 | i2c_childlist[index].i2ctype = I2C_ADC; |
1062 | } | 1052 | envctrl_init_i2c_child(dp, &(i2c_childlist[index++])); |
1063 | } | ||
1064 | goto done; | ||
1065 | } | ||
1066 | } | 1053 | } |
1067 | } | ||
1068 | 1054 | ||
1069 | done: | 1055 | dp = dp->sibling; |
1070 | if (!edev) { | ||
1071 | printk("envctrl: I2C device not found.\n"); | ||
1072 | return -ENODEV; | ||
1073 | } | 1056 | } |
1074 | 1057 | ||
1075 | /* Set device address. */ | 1058 | /* Set device address. */ |
@@ -1087,7 +1070,7 @@ done: | |||
1087 | /* Register the device as a minor miscellaneous device. */ | 1070 | /* Register the device as a minor miscellaneous device. */ |
1088 | err = misc_register(&envctrl_dev); | 1071 | err = misc_register(&envctrl_dev); |
1089 | if (err) { | 1072 | if (err) { |
1090 | printk("envctrl: Unable to get misc minor %d\n", | 1073 | printk(KERN_ERR PFX "Unable to get misc minor %d\n", |
1091 | envctrl_dev.minor); | 1074 | envctrl_dev.minor); |
1092 | goto out_iounmap; | 1075 | goto out_iounmap; |
1093 | } | 1076 | } |
@@ -1096,12 +1079,12 @@ done: | |||
1096 | * a next child device, so we decrement before reverse-traversal of | 1079 | * a next child device, so we decrement before reverse-traversal of |
1097 | * child devices. | 1080 | * child devices. |
1098 | */ | 1081 | */ |
1099 | printk("envctrl: initialized "); | 1082 | printk(KERN_INFO PFX "Initialized "); |
1100 | for (--i; i >= 0; --i) { | 1083 | for (--index; index >= 0; --index) { |
1101 | printk("[%s 0x%lx]%s", | 1084 | printk("[%s 0x%lx]%s", |
1102 | (I2C_ADC == i2c_childlist[i].i2ctype) ? ("adc") : | 1085 | (I2C_ADC == i2c_childlist[index].i2ctype) ? "adc" : |
1103 | ((I2C_GPIO == i2c_childlist[i].i2ctype) ? ("gpio") : ("unknown")), | 1086 | ((I2C_GPIO == i2c_childlist[index].i2ctype) ? "gpio" : "unknown"), |
1104 | i2c_childlist[i].addr, (0 == i) ? ("\n") : (" ")); | 1087 | i2c_childlist[index].addr, (0 == index) ? "\n" : " "); |
1105 | } | 1088 | } |
1106 | 1089 | ||
1107 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); | 1090 | kenvctrld_task = kthread_run(kenvctrld, NULL, "kenvctrld"); |
@@ -1115,26 +1098,54 @@ done: | |||
1115 | out_deregister: | 1098 | out_deregister: |
1116 | misc_deregister(&envctrl_dev); | 1099 | misc_deregister(&envctrl_dev); |
1117 | out_iounmap: | 1100 | out_iounmap: |
1118 | iounmap(i2c); | 1101 | of_iounmap(&op->resource[0], i2c, 0x2); |
1119 | for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) | 1102 | for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++) |
1120 | kfree(i2c_childlist[i].tables); | 1103 | kfree(i2c_childlist[index].tables); |
1121 | 1104 | ||
1122 | return err; | 1105 | return err; |
1123 | } | 1106 | } |
1124 | 1107 | ||
1125 | static void __exit envctrl_cleanup(void) | 1108 | static int __devexit envctrl_remove(struct of_device *op) |
1126 | { | 1109 | { |
1127 | int i; | 1110 | int index; |
1128 | 1111 | ||
1129 | kthread_stop(kenvctrld_task); | 1112 | kthread_stop(kenvctrld_task); |
1130 | 1113 | ||
1131 | iounmap(i2c); | 1114 | of_iounmap(&op->resource[0], i2c, 0x2); |
1132 | misc_deregister(&envctrl_dev); | 1115 | misc_deregister(&envctrl_dev); |
1133 | 1116 | ||
1134 | for (i = 0; i < ENVCTRL_MAX_CPU * 2; i++) | 1117 | for (index = 0; index < ENVCTRL_MAX_CPU * 2; index++) |
1135 | kfree(i2c_childlist[i].tables); | 1118 | kfree(i2c_childlist[index].tables); |
1119 | |||
1120 | return 0; | ||
1121 | } | ||
1122 | |||
1123 | static const struct of_device_id envctrl_match[] = { | ||
1124 | { | ||
1125 | .name = "i2c", | ||
1126 | .compatible = "i2cpcf,8584", | ||
1127 | }, | ||
1128 | {}, | ||
1129 | }; | ||
1130 | MODULE_DEVICE_TABLE(of, envctrl_match); | ||
1131 | |||
1132 | static struct of_platform_driver envctrl_driver = { | ||
1133 | .name = DRIVER_NAME, | ||
1134 | .match_table = envctrl_match, | ||
1135 | .probe = envctrl_probe, | ||
1136 | .remove = __devexit_p(envctrl_remove), | ||
1137 | }; | ||
1138 | |||
1139 | static int __init envctrl_init(void) | ||
1140 | { | ||
1141 | return of_register_driver(&envctrl_driver, &of_bus_type); | ||
1142 | } | ||
1143 | |||
1144 | static void __exit envctrl_exit(void) | ||
1145 | { | ||
1146 | of_unregister_driver(&envctrl_driver); | ||
1136 | } | 1147 | } |
1137 | 1148 | ||
1138 | module_init(envctrl_init); | 1149 | module_init(envctrl_init); |
1139 | module_exit(envctrl_cleanup); | 1150 | module_exit(envctrl_exit); |
1140 | MODULE_LICENSE("GPL"); | 1151 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/sbus/char/flash.c b/drivers/sbus/char/flash.c index 7d95e151513a..41083472ff4f 100644 --- a/drivers/sbus/char/flash.c +++ b/drivers/sbus/char/flash.c | |||
@@ -1,5 +1,4 @@ | |||
1 | /* $Id: flash.c,v 1.25 2001/12/21 04:56:16 davem Exp $ | 1 | /* flash.c: Allow mmap access to the OBP Flash, for OBP updates. |
2 | * flash.c: Allow mmap access to the OBP Flash, for OBP updates. | ||
3 | * | 2 | * |
4 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) | 3 | * Copyright (C) 1997 Eddie C. Dost (ecd@skynet.be) |
5 | */ | 4 | */ |
@@ -15,13 +14,13 @@ | |||
15 | #include <linux/smp_lock.h> | 14 | #include <linux/smp_lock.h> |
16 | #include <linux/spinlock.h> | 15 | #include <linux/spinlock.h> |
17 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/of.h> | ||
18 | #include <linux/of_device.h> | ||
18 | 19 | ||
19 | #include <asm/system.h> | 20 | #include <asm/system.h> |
20 | #include <asm/uaccess.h> | 21 | #include <asm/uaccess.h> |
21 | #include <asm/pgtable.h> | 22 | #include <asm/pgtable.h> |
22 | #include <asm/io.h> | 23 | #include <asm/io.h> |
23 | #include <asm/sbus.h> | ||
24 | #include <asm/ebus.h> | ||
25 | #include <asm/upa.h> | 24 | #include <asm/upa.h> |
26 | 25 | ||
27 | static DEFINE_SPINLOCK(flash_lock); | 26 | static DEFINE_SPINLOCK(flash_lock); |
@@ -161,97 +160,68 @@ static const struct file_operations flash_fops = { | |||
161 | 160 | ||
162 | static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; | 161 | static struct miscdevice flash_dev = { FLASH_MINOR, "flash", &flash_fops }; |
163 | 162 | ||
164 | static int __init flash_init(void) | 163 | static int __devinit flash_probe(struct of_device *op, |
164 | const struct of_device_id *match) | ||
165 | { | 165 | { |
166 | struct sbus_bus *sbus; | 166 | struct device_node *dp = op->node; |
167 | struct sbus_dev *sdev = NULL; | 167 | struct device_node *parent; |
168 | #ifdef CONFIG_PCI | ||
169 | struct linux_ebus *ebus; | ||
170 | struct linux_ebus_device *edev = NULL; | ||
171 | struct linux_prom_registers regs[2]; | ||
172 | int len, nregs; | ||
173 | #endif | ||
174 | int err; | ||
175 | |||
176 | for_all_sbusdev(sdev, sbus) { | ||
177 | if (!strcmp(sdev->prom_name, "flashprom")) { | ||
178 | if (sdev->reg_addrs[0].phys_addr == sdev->reg_addrs[1].phys_addr) { | ||
179 | flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | | ||
180 | (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); | ||
181 | flash.read_size = sdev->reg_addrs[0].reg_size; | ||
182 | flash.write_base = flash.read_base; | ||
183 | flash.write_size = flash.read_size; | ||
184 | } else { | ||
185 | flash.read_base = ((unsigned long)sdev->reg_addrs[0].phys_addr) | | ||
186 | (((unsigned long)sdev->reg_addrs[0].which_io)<<32UL); | ||
187 | flash.read_size = sdev->reg_addrs[0].reg_size; | ||
188 | flash.write_base = ((unsigned long)sdev->reg_addrs[1].phys_addr) | | ||
189 | (((unsigned long)sdev->reg_addrs[1].which_io)<<32UL); | ||
190 | flash.write_size = sdev->reg_addrs[1].reg_size; | ||
191 | } | ||
192 | flash.busy = 0; | ||
193 | break; | ||
194 | } | ||
195 | } | ||
196 | if (!sdev) { | ||
197 | #ifdef CONFIG_PCI | ||
198 | const struct linux_prom_registers *ebus_regs; | ||
199 | |||
200 | for_each_ebus(ebus) { | ||
201 | for_each_ebusdev(edev, ebus) { | ||
202 | if (!strcmp(edev->prom_node->name, "flashprom")) | ||
203 | goto ebus_done; | ||
204 | } | ||
205 | } | ||
206 | ebus_done: | ||
207 | if (!edev) | ||
208 | return -ENODEV; | ||
209 | |||
210 | ebus_regs = of_get_property(edev->prom_node, "reg", &len); | ||
211 | if (!ebus_regs || (len % sizeof(regs[0])) != 0) { | ||
212 | printk("flash: Strange reg property size %d\n", len); | ||
213 | return -ENODEV; | ||
214 | } | ||
215 | |||
216 | nregs = len / sizeof(ebus_regs[0]); | ||
217 | 168 | ||
218 | flash.read_base = edev->resource[0].start; | 169 | parent = dp->parent; |
219 | flash.read_size = ebus_regs[0].reg_size; | ||
220 | 170 | ||
221 | if (nregs == 1) { | 171 | if (strcmp(parent->name, "sbus") && |
222 | flash.write_base = edev->resource[0].start; | 172 | strcmp(parent->name, "sbi") && |
223 | flash.write_size = ebus_regs[0].reg_size; | 173 | strcmp(parent->name, "ebus")) |
224 | } else if (nregs == 2) { | ||
225 | flash.write_base = edev->resource[1].start; | ||
226 | flash.write_size = ebus_regs[1].reg_size; | ||
227 | } else { | ||
228 | printk("flash: Strange number of regs %d\n", nregs); | ||
229 | return -ENODEV; | ||
230 | } | ||
231 | |||
232 | flash.busy = 0; | ||
233 | |||
234 | #else | ||
235 | return -ENODEV; | 174 | return -ENODEV; |
236 | #endif | 175 | |
176 | flash.read_base = op->resource[0].start; | ||
177 | flash.read_size = resource_size(&op->resource[0]); | ||
178 | if (op->resource[1].flags) { | ||
179 | flash.write_base = op->resource[1].start; | ||
180 | flash.write_size = resource_size(&op->resource[1]); | ||
181 | } else { | ||
182 | flash.write_base = op->resource[0].start; | ||
183 | flash.write_size = resource_size(&op->resource[0]); | ||
237 | } | 184 | } |
185 | flash.busy = 0; | ||
238 | 186 | ||
239 | printk("OBP Flash: RD %lx[%lx] WR %lx[%lx]\n", | 187 | printk(KERN_INFO "%s: OBP Flash, RD %lx[%lx] WR %lx[%lx]\n", |
188 | op->node->full_name, | ||
240 | flash.read_base, flash.read_size, | 189 | flash.read_base, flash.read_size, |
241 | flash.write_base, flash.write_size); | 190 | flash.write_base, flash.write_size); |
242 | 191 | ||
243 | err = misc_register(&flash_dev); | 192 | return misc_register(&flash_dev); |
244 | if (err) { | 193 | } |
245 | printk(KERN_ERR "flash: unable to get misc minor\n"); | 194 | |
246 | return err; | 195 | static int __devexit flash_remove(struct of_device *op) |
247 | } | 196 | { |
197 | misc_deregister(&flash_dev); | ||
248 | 198 | ||
249 | return 0; | 199 | return 0; |
250 | } | 200 | } |
251 | 201 | ||
202 | static const struct of_device_id flash_match[] = { | ||
203 | { | ||
204 | .name = "flashprom", | ||
205 | }, | ||
206 | {}, | ||
207 | }; | ||
208 | MODULE_DEVICE_TABLE(of, flash_match); | ||
209 | |||
210 | static struct of_platform_driver flash_driver = { | ||
211 | .name = "flash", | ||
212 | .match_table = flash_match, | ||
213 | .probe = flash_probe, | ||
214 | .remove = __devexit_p(flash_remove), | ||
215 | }; | ||
216 | |||
217 | static int __init flash_init(void) | ||
218 | { | ||
219 | return of_register_driver(&flash_driver, &of_bus_type); | ||
220 | } | ||
221 | |||
252 | static void __exit flash_cleanup(void) | 222 | static void __exit flash_cleanup(void) |
253 | { | 223 | { |
254 | misc_deregister(&flash_dev); | 224 | of_unregister_driver(&flash_driver); |
255 | } | 225 | } |
256 | 226 | ||
257 | module_init(flash_init); | 227 | module_init(flash_init); |
diff --git a/drivers/sbus/char/rtc.c b/drivers/sbus/char/rtc.c deleted file mode 100644 index b0429917154d..000000000000 --- a/drivers/sbus/char/rtc.c +++ /dev/null | |||
@@ -1,275 +0,0 @@ | |||
1 | /* $Id: rtc.c,v 1.28 2001/10/08 22:19:51 davem Exp $ | ||
2 | * | ||
3 | * Linux/SPARC Real Time Clock Driver | ||
4 | * Copyright (C) 1996 Thomas K. Dyas (tdyas@eden.rutgers.edu) | ||
5 | * | ||
6 | * This is a little driver that lets a user-level program access | ||
7 | * the SPARC Mostek real time clock chip. It is no use unless you | ||
8 | * use the modified clock utility. | ||
9 | * | ||
10 | * Get the modified clock utility from: | ||
11 | * ftp://vger.kernel.org/pub/linux/Sparc/userland/clock.c | ||
12 | */ | ||
13 | |||
14 | #include <linux/module.h> | ||
15 | #include <linux/smp_lock.h> | ||
16 | #include <linux/types.h> | ||
17 | #include <linux/errno.h> | ||
18 | #include <linux/miscdevice.h> | ||
19 | #include <linux/slab.h> | ||
20 | #include <linux/fcntl.h> | ||
21 | #include <linux/poll.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <asm/io.h> | ||
24 | #include <asm/mostek.h> | ||
25 | #include <asm/system.h> | ||
26 | #include <asm/uaccess.h> | ||
27 | #include <asm/rtc.h> | ||
28 | |||
29 | static int rtc_busy = 0; | ||
30 | |||
31 | /* This is the structure layout used by drivers/char/rtc.c, we | ||
32 | * support that driver's ioctls so that things are less messy in | ||
33 | * userspace. | ||
34 | */ | ||
35 | struct rtc_time_generic { | ||
36 | int tm_sec; | ||
37 | int tm_min; | ||
38 | int tm_hour; | ||
39 | int tm_mday; | ||
40 | int tm_mon; | ||
41 | int tm_year; | ||
42 | int tm_wday; | ||
43 | int tm_yday; | ||
44 | int tm_isdst; | ||
45 | }; | ||
46 | #define RTC_AIE_ON _IO('p', 0x01) /* Alarm int. enable on */ | ||
47 | #define RTC_AIE_OFF _IO('p', 0x02) /* ... off */ | ||
48 | #define RTC_UIE_ON _IO('p', 0x03) /* Update int. enable on */ | ||
49 | #define RTC_UIE_OFF _IO('p', 0x04) /* ... off */ | ||
50 | #define RTC_PIE_ON _IO('p', 0x05) /* Periodic int. enable on */ | ||
51 | #define RTC_PIE_OFF _IO('p', 0x06) /* ... off */ | ||
52 | #define RTC_WIE_ON _IO('p', 0x0f) /* Watchdog int. enable on */ | ||
53 | #define RTC_WIE_OFF _IO('p', 0x10) /* ... off */ | ||
54 | #define RTC_RD_TIME _IOR('p', 0x09, struct rtc_time_generic) /* Read RTC time */ | ||
55 | #define RTC_SET_TIME _IOW('p', 0x0a, struct rtc_time_generic) /* Set RTC time */ | ||
56 | #define RTC_ALM_SET _IOW('p', 0x07, struct rtc_time) /* Set alarm time */ | ||
57 | #define RTC_ALM_READ _IOR('p', 0x08, struct rtc_time) /* Read alarm time */ | ||
58 | #define RTC_IRQP_READ _IOR('p', 0x0b, unsigned long) /* Read IRQ rate */ | ||
59 | #define RTC_IRQP_SET _IOW('p', 0x0c, unsigned long) /* Set IRQ rate */ | ||
60 | #define RTC_EPOCH_READ _IOR('p', 0x0d, unsigned long) /* Read epoch */ | ||
61 | #define RTC_EPOCH_SET _IOW('p', 0x0e, unsigned long) /* Set epoch */ | ||
62 | #define RTC_WKALM_SET _IOW('p', 0x0f, struct rtc_wkalrm)/* Set wakeup alarm*/ | ||
63 | #define RTC_WKALM_RD _IOR('p', 0x10, struct rtc_wkalrm)/* Get wakeup alarm*/ | ||
64 | #define RTC_PLL_GET _IOR('p', 0x11, struct rtc_pll_info) /* Get PLL correction */ | ||
65 | #define RTC_PLL_SET _IOW('p', 0x12, struct rtc_pll_info) /* Set PLL correction */ | ||
66 | |||
67 | /* Retrieve the current date and time from the real time clock. */ | ||
68 | static void get_rtc_time(struct rtc_time *t) | ||
69 | { | ||
70 | void __iomem *regs = mstk48t02_regs; | ||
71 | u8 tmp; | ||
72 | |||
73 | spin_lock_irq(&mostek_lock); | ||
74 | |||
75 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
76 | tmp |= MSTK_CREG_READ; | ||
77 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
78 | |||
79 | t->sec = MSTK_REG_SEC(regs); | ||
80 | t->min = MSTK_REG_MIN(regs); | ||
81 | t->hour = MSTK_REG_HOUR(regs); | ||
82 | t->dow = MSTK_REG_DOW(regs); | ||
83 | t->dom = MSTK_REG_DOM(regs); | ||
84 | t->month = MSTK_REG_MONTH(regs); | ||
85 | t->year = MSTK_CVT_YEAR( MSTK_REG_YEAR(regs) ); | ||
86 | |||
87 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
88 | tmp &= ~MSTK_CREG_READ; | ||
89 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
90 | |||
91 | spin_unlock_irq(&mostek_lock); | ||
92 | } | ||
93 | |||
94 | /* Set the current date and time inthe real time clock. */ | ||
95 | void set_rtc_time(struct rtc_time *t) | ||
96 | { | ||
97 | void __iomem *regs = mstk48t02_regs; | ||
98 | u8 tmp; | ||
99 | |||
100 | spin_lock_irq(&mostek_lock); | ||
101 | |||
102 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
103 | tmp |= MSTK_CREG_WRITE; | ||
104 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
105 | |||
106 | MSTK_SET_REG_SEC(regs,t->sec); | ||
107 | MSTK_SET_REG_MIN(regs,t->min); | ||
108 | MSTK_SET_REG_HOUR(regs,t->hour); | ||
109 | MSTK_SET_REG_DOW(regs,t->dow); | ||
110 | MSTK_SET_REG_DOM(regs,t->dom); | ||
111 | MSTK_SET_REG_MONTH(regs,t->month); | ||
112 | MSTK_SET_REG_YEAR(regs,t->year - MSTK_YEAR_ZERO); | ||
113 | |||
114 | tmp = mostek_read(regs + MOSTEK_CREG); | ||
115 | tmp &= ~MSTK_CREG_WRITE; | ||
116 | mostek_write(regs + MOSTEK_CREG, tmp); | ||
117 | |||
118 | spin_unlock_irq(&mostek_lock); | ||
119 | } | ||
120 | |||
121 | static int put_rtc_time_generic(void __user *argp, struct rtc_time *tm) | ||
122 | { | ||
123 | struct rtc_time_generic __user *utm = argp; | ||
124 | |||
125 | if (__put_user(tm->sec, &utm->tm_sec) || | ||
126 | __put_user(tm->min, &utm->tm_min) || | ||
127 | __put_user(tm->hour, &utm->tm_hour) || | ||
128 | __put_user(tm->dom, &utm->tm_mday) || | ||
129 | __put_user(tm->month, &utm->tm_mon) || | ||
130 | __put_user(tm->year, &utm->tm_year) || | ||
131 | __put_user(tm->dow, &utm->tm_wday) || | ||
132 | __put_user(0, &utm->tm_yday) || | ||
133 | __put_user(0, &utm->tm_isdst)) | ||
134 | return -EFAULT; | ||
135 | |||
136 | return 0; | ||
137 | } | ||
138 | |||
139 | static int get_rtc_time_generic(struct rtc_time *tm, void __user *argp) | ||
140 | { | ||
141 | struct rtc_time_generic __user *utm = argp; | ||
142 | |||
143 | if (__get_user(tm->sec, &utm->tm_sec) || | ||
144 | __get_user(tm->min, &utm->tm_min) || | ||
145 | __get_user(tm->hour, &utm->tm_hour) || | ||
146 | __get_user(tm->dom, &utm->tm_mday) || | ||
147 | __get_user(tm->month, &utm->tm_mon) || | ||
148 | __get_user(tm->year, &utm->tm_year) || | ||
149 | __get_user(tm->dow, &utm->tm_wday)) | ||
150 | return -EFAULT; | ||
151 | |||
152 | return 0; | ||
153 | } | ||
154 | |||
155 | static int rtc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
156 | unsigned long arg) | ||
157 | { | ||
158 | struct rtc_time rtc_tm; | ||
159 | void __user *argp = (void __user *)arg; | ||
160 | |||
161 | switch (cmd) { | ||
162 | /* No interrupt support, return an error | ||
163 | * compatible with drivers/char/rtc.c | ||
164 | */ | ||
165 | case RTC_AIE_OFF: | ||
166 | case RTC_AIE_ON: | ||
167 | case RTC_PIE_OFF: | ||
168 | case RTC_PIE_ON: | ||
169 | case RTC_UIE_OFF: | ||
170 | case RTC_UIE_ON: | ||
171 | case RTC_IRQP_READ: | ||
172 | case RTC_IRQP_SET: | ||
173 | case RTC_EPOCH_SET: | ||
174 | case RTC_EPOCH_READ: | ||
175 | return -EINVAL; | ||
176 | |||
177 | case RTCGET: | ||
178 | case RTC_RD_TIME: | ||
179 | memset(&rtc_tm, 0, sizeof(struct rtc_time)); | ||
180 | get_rtc_time(&rtc_tm); | ||
181 | |||
182 | if (cmd == RTCGET) { | ||
183 | if (copy_to_user(argp, &rtc_tm, | ||
184 | sizeof(struct rtc_time))) | ||
185 | return -EFAULT; | ||
186 | } else if (put_rtc_time_generic(argp, &rtc_tm)) | ||
187 | return -EFAULT; | ||
188 | |||
189 | return 0; | ||
190 | |||
191 | |||
192 | case RTCSET: | ||
193 | case RTC_SET_TIME: | ||
194 | if (!capable(CAP_SYS_TIME)) | ||
195 | return -EPERM; | ||
196 | |||
197 | if (cmd == RTCSET) { | ||
198 | if (copy_from_user(&rtc_tm, argp, | ||
199 | sizeof(struct rtc_time))) | ||
200 | return -EFAULT; | ||
201 | } else if (get_rtc_time_generic(&rtc_tm, argp)) | ||
202 | return -EFAULT; | ||
203 | |||
204 | set_rtc_time(&rtc_tm); | ||
205 | |||
206 | return 0; | ||
207 | |||
208 | default: | ||
209 | return -EINVAL; | ||
210 | } | ||
211 | } | ||
212 | |||
213 | static int rtc_open(struct inode *inode, struct file *file) | ||
214 | { | ||
215 | int ret; | ||
216 | |||
217 | lock_kernel(); | ||
218 | spin_lock_irq(&mostek_lock); | ||
219 | if (rtc_busy) { | ||
220 | ret = -EBUSY; | ||
221 | } else { | ||
222 | rtc_busy = 1; | ||
223 | ret = 0; | ||
224 | } | ||
225 | spin_unlock_irq(&mostek_lock); | ||
226 | unlock_kernel(); | ||
227 | |||
228 | return ret; | ||
229 | } | ||
230 | |||
231 | static int rtc_release(struct inode *inode, struct file *file) | ||
232 | { | ||
233 | rtc_busy = 0; | ||
234 | |||
235 | return 0; | ||
236 | } | ||
237 | |||
238 | static const struct file_operations rtc_fops = { | ||
239 | .owner = THIS_MODULE, | ||
240 | .llseek = no_llseek, | ||
241 | .ioctl = rtc_ioctl, | ||
242 | .open = rtc_open, | ||
243 | .release = rtc_release, | ||
244 | }; | ||
245 | |||
246 | static struct miscdevice rtc_dev = { RTC_MINOR, "rtc", &rtc_fops }; | ||
247 | |||
248 | static int __init rtc_sun_init(void) | ||
249 | { | ||
250 | int error; | ||
251 | |||
252 | /* It is possible we are being driven by some other RTC chip | ||
253 | * and thus another RTC driver is handling things. | ||
254 | */ | ||
255 | if (!mstk48t02_regs) | ||
256 | return -ENODEV; | ||
257 | |||
258 | error = misc_register(&rtc_dev); | ||
259 | if (error) { | ||
260 | printk(KERN_ERR "rtc: unable to get misc minor for Mostek\n"); | ||
261 | return error; | ||
262 | } | ||
263 | printk("rtc_sun_init: Registered Mostek RTC driver.\n"); | ||
264 | |||
265 | return 0; | ||
266 | } | ||
267 | |||
268 | static void __exit rtc_sun_cleanup(void) | ||
269 | { | ||
270 | misc_deregister(&rtc_dev); | ||
271 | } | ||
272 | |||
273 | module_init(rtc_sun_init); | ||
274 | module_exit(rtc_sun_cleanup); | ||
275 | MODULE_LICENSE("GPL"); | ||
diff --git a/drivers/sbus/char/uctrl.c b/drivers/sbus/char/uctrl.c index 777637594acd..27993c37775d 100644 --- a/drivers/sbus/char/uctrl.c +++ b/drivers/sbus/char/uctrl.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* $Id: uctrl.c,v 1.12 2001/10/08 22:19:51 davem Exp $ | 1 | /* uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3 |
2 | * uctrl.c: TS102 Microcontroller interface on Tadpole Sparcbook 3 | ||
3 | * | 2 | * |
4 | * Copyright 1999 Derrick J Brashear (shadow@dementia.org) | 3 | * Copyright 1999 Derrick J Brashear (shadow@dementia.org) |
4 | * Copyright 2008 David S. Miller (davem@davemloft.net) | ||
5 | */ | 5 | */ |
6 | 6 | ||
7 | #include <linux/module.h> | 7 | #include <linux/module.h> |
@@ -14,6 +14,8 @@ | |||
14 | #include <linux/init.h> | 14 | #include <linux/init.h> |
15 | #include <linux/miscdevice.h> | 15 | #include <linux/miscdevice.h> |
16 | #include <linux/mm.h> | 16 | #include <linux/mm.h> |
17 | #include <linux/of.h> | ||
18 | #include <linux/of_device.h> | ||
17 | 19 | ||
18 | #include <asm/openprom.h> | 20 | #include <asm/openprom.h> |
19 | #include <asm/oplib.h> | 21 | #include <asm/oplib.h> |
@@ -21,7 +23,6 @@ | |||
21 | #include <asm/irq.h> | 23 | #include <asm/irq.h> |
22 | #include <asm/io.h> | 24 | #include <asm/io.h> |
23 | #include <asm/pgtable.h> | 25 | #include <asm/pgtable.h> |
24 | #include <asm/sbus.h> | ||
25 | 26 | ||
26 | #define UCTRL_MINOR 174 | 27 | #define UCTRL_MINOR 174 |
27 | 28 | ||
@@ -33,26 +34,26 @@ | |||
33 | #endif | 34 | #endif |
34 | 35 | ||
35 | struct uctrl_regs { | 36 | struct uctrl_regs { |
36 | volatile u32 uctrl_intr; | 37 | u32 uctrl_intr; |
37 | volatile u32 uctrl_data; | 38 | u32 uctrl_data; |
38 | volatile u32 uctrl_stat; | 39 | u32 uctrl_stat; |
39 | volatile u32 uctrl_xxx[5]; | 40 | u32 uctrl_xxx[5]; |
40 | }; | 41 | }; |
41 | 42 | ||
42 | struct ts102_regs { | 43 | struct ts102_regs { |
43 | volatile u32 card_a_intr; | 44 | u32 card_a_intr; |
44 | volatile u32 card_a_stat; | 45 | u32 card_a_stat; |
45 | volatile u32 card_a_ctrl; | 46 | u32 card_a_ctrl; |
46 | volatile u32 card_a_xxx; | 47 | u32 card_a_xxx; |
47 | volatile u32 card_b_intr; | 48 | u32 card_b_intr; |
48 | volatile u32 card_b_stat; | 49 | u32 card_b_stat; |
49 | volatile u32 card_b_ctrl; | 50 | u32 card_b_ctrl; |
50 | volatile u32 card_b_xxx; | 51 | u32 card_b_xxx; |
51 | volatile u32 uctrl_intr; | 52 | u32 uctrl_intr; |
52 | volatile u32 uctrl_data; | 53 | u32 uctrl_data; |
53 | volatile u32 uctrl_stat; | 54 | u32 uctrl_stat; |
54 | volatile u32 uctrl_xxx; | 55 | u32 uctrl_xxx; |
55 | volatile u32 ts102_xxx[4]; | 56 | u32 ts102_xxx[4]; |
56 | }; | 57 | }; |
57 | 58 | ||
58 | /* Bits for uctrl_intr register */ | 59 | /* Bits for uctrl_intr register */ |
@@ -186,17 +187,15 @@ enum uctrl_opcode { | |||
186 | POWER_RESTART=0x83, | 187 | POWER_RESTART=0x83, |
187 | }; | 188 | }; |
188 | 189 | ||
189 | struct uctrl_driver { | 190 | static struct uctrl_driver { |
190 | struct uctrl_regs *regs; | 191 | struct uctrl_regs __iomem *regs; |
191 | int irq; | 192 | int irq; |
192 | int pending; | 193 | int pending; |
193 | struct uctrl_status status; | 194 | struct uctrl_status status; |
194 | }; | 195 | } *global_driver; |
195 | |||
196 | static struct uctrl_driver drv; | ||
197 | 196 | ||
198 | static void uctrl_get_event_status(void); | 197 | static void uctrl_get_event_status(struct uctrl_driver *); |
199 | static void uctrl_get_external_status(void); | 198 | static void uctrl_get_external_status(struct uctrl_driver *); |
200 | 199 | ||
201 | static int | 200 | static int |
202 | uctrl_ioctl(struct inode *inode, struct file *file, | 201 | uctrl_ioctl(struct inode *inode, struct file *file, |
@@ -213,16 +212,14 @@ static int | |||
213 | uctrl_open(struct inode *inode, struct file *file) | 212 | uctrl_open(struct inode *inode, struct file *file) |
214 | { | 213 | { |
215 | lock_kernel(); | 214 | lock_kernel(); |
216 | uctrl_get_event_status(); | 215 | uctrl_get_event_status(global_driver); |
217 | uctrl_get_external_status(); | 216 | uctrl_get_external_status(global_driver); |
218 | unlock_kernel(); | 217 | unlock_kernel(); |
219 | return 0; | 218 | return 0; |
220 | } | 219 | } |
221 | 220 | ||
222 | static irqreturn_t uctrl_interrupt(int irq, void *dev_id) | 221 | static irqreturn_t uctrl_interrupt(int irq, void *dev_id) |
223 | { | 222 | { |
224 | struct uctrl_driver *driver = (struct uctrl_driver *)dev_id; | ||
225 | printk("in uctrl_interrupt\n"); | ||
226 | return IRQ_HANDLED; | 223 | return IRQ_HANDLED; |
227 | } | 224 | } |
228 | 225 | ||
@@ -244,11 +241,11 @@ static struct miscdevice uctrl_dev = { | |||
244 | { \ | 241 | { \ |
245 | unsigned int i; \ | 242 | unsigned int i; \ |
246 | for (i = 0; i < 10000; i++) { \ | 243 | for (i = 0; i < 10000; i++) { \ |
247 | if (UCTRL_STAT_TXNF_STA & driver->regs->uctrl_stat) \ | 244 | if (UCTRL_STAT_TXNF_STA & sbus_readl(&driver->regs->uctrl_stat)) \ |
248 | break; \ | 245 | break; \ |
249 | } \ | 246 | } \ |
250 | dprintk(("write data 0x%02x\n", value)); \ | 247 | dprintk(("write data 0x%02x\n", value)); \ |
251 | driver->regs->uctrl_data = value; \ | 248 | sbus_writel(value, &driver->regs->uctrl_data); \ |
252 | } | 249 | } |
253 | 250 | ||
254 | /* Wait for something to read, read it, then clear the bit */ | 251 | /* Wait for something to read, read it, then clear the bit */ |
@@ -257,24 +254,23 @@ static struct miscdevice uctrl_dev = { | |||
257 | unsigned int i; \ | 254 | unsigned int i; \ |
258 | value = 0; \ | 255 | value = 0; \ |
259 | for (i = 0; i < 10000; i++) { \ | 256 | for (i = 0; i < 10000; i++) { \ |
260 | if ((UCTRL_STAT_RXNE_STA & driver->regs->uctrl_stat) == 0) \ | 257 | if ((UCTRL_STAT_RXNE_STA & sbus_readl(&driver->regs->uctrl_stat)) == 0) \ |
261 | break; \ | 258 | break; \ |
262 | udelay(1); \ | 259 | udelay(1); \ |
263 | } \ | 260 | } \ |
264 | value = driver->regs->uctrl_data; \ | 261 | value = sbus_readl(&driver->regs->uctrl_data); \ |
265 | dprintk(("read data 0x%02x\n", value)); \ | 262 | dprintk(("read data 0x%02x\n", value)); \ |
266 | driver->regs->uctrl_stat = UCTRL_STAT_RXNE_STA; \ | 263 | sbus_writel(UCTRL_STAT_RXNE_STA, &driver->regs->uctrl_stat); \ |
267 | } | 264 | } |
268 | 265 | ||
269 | static void uctrl_do_txn(struct uctrl_txn *txn) | 266 | static void uctrl_do_txn(struct uctrl_driver *driver, struct uctrl_txn *txn) |
270 | { | 267 | { |
271 | struct uctrl_driver *driver = &drv; | ||
272 | int stat, incnt, outcnt, bytecnt, intr; | 268 | int stat, incnt, outcnt, bytecnt, intr; |
273 | u32 byte; | 269 | u32 byte; |
274 | 270 | ||
275 | stat = driver->regs->uctrl_stat; | 271 | stat = sbus_readl(&driver->regs->uctrl_stat); |
276 | intr = driver->regs->uctrl_intr; | 272 | intr = sbus_readl(&driver->regs->uctrl_intr); |
277 | driver->regs->uctrl_stat = stat; | 273 | sbus_writel(stat, &driver->regs->uctrl_stat); |
278 | 274 | ||
279 | dprintk(("interrupt stat 0x%x int 0x%x\n", stat, intr)); | 275 | dprintk(("interrupt stat 0x%x int 0x%x\n", stat, intr)); |
280 | 276 | ||
@@ -305,9 +301,8 @@ static void uctrl_do_txn(struct uctrl_txn *txn) | |||
305 | } | 301 | } |
306 | } | 302 | } |
307 | 303 | ||
308 | static void uctrl_get_event_status(void) | 304 | static void uctrl_get_event_status(struct uctrl_driver *driver) |
309 | { | 305 | { |
310 | struct uctrl_driver *driver = &drv; | ||
311 | struct uctrl_txn txn; | 306 | struct uctrl_txn txn; |
312 | u8 outbits[2]; | 307 | u8 outbits[2]; |
313 | 308 | ||
@@ -317,7 +312,7 @@ static void uctrl_get_event_status(void) | |||
317 | txn.inbuf = NULL; | 312 | txn.inbuf = NULL; |
318 | txn.outbuf = outbits; | 313 | txn.outbuf = outbits; |
319 | 314 | ||
320 | uctrl_do_txn(&txn); | 315 | uctrl_do_txn(driver, &txn); |
321 | 316 | ||
322 | dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); | 317 | dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); |
323 | driver->status.event_status = | 318 | driver->status.event_status = |
@@ -325,9 +320,8 @@ static void uctrl_get_event_status(void) | |||
325 | dprintk(("ev is %x\n", driver->status.event_status)); | 320 | dprintk(("ev is %x\n", driver->status.event_status)); |
326 | } | 321 | } |
327 | 322 | ||
328 | static void uctrl_get_external_status(void) | 323 | static void uctrl_get_external_status(struct uctrl_driver *driver) |
329 | { | 324 | { |
330 | struct uctrl_driver *driver = &drv; | ||
331 | struct uctrl_txn txn; | 325 | struct uctrl_txn txn; |
332 | u8 outbits[2]; | 326 | u8 outbits[2]; |
333 | int i, v; | 327 | int i, v; |
@@ -338,7 +332,7 @@ static void uctrl_get_external_status(void) | |||
338 | txn.inbuf = NULL; | 332 | txn.inbuf = NULL; |
339 | txn.outbuf = outbits; | 333 | txn.outbuf = outbits; |
340 | 334 | ||
341 | uctrl_do_txn(&txn); | 335 | uctrl_do_txn(driver, &txn); |
342 | 336 | ||
343 | dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); | 337 | dprintk(("bytes %x %x\n", (outbits[0] & 0xff), (outbits[1] & 0xff))); |
344 | driver->status.external_status = | 338 | driver->status.external_status = |
@@ -354,71 +348,101 @@ static void uctrl_get_external_status(void) | |||
354 | 348 | ||
355 | } | 349 | } |
356 | 350 | ||
357 | static int __init ts102_uctrl_init(void) | 351 | static int __devinit uctrl_probe(struct of_device *op, |
352 | const struct of_device_id *match) | ||
358 | { | 353 | { |
359 | struct uctrl_driver *driver = &drv; | 354 | struct uctrl_driver *p; |
360 | int len; | 355 | int err = -ENOMEM; |
361 | struct linux_prom_irqs tmp_irq[2]; | ||
362 | unsigned int vaddr[2] = { 0, 0 }; | ||
363 | int tmpnode, uctrlnode = prom_getchild(prom_root_node); | ||
364 | int err; | ||
365 | 356 | ||
366 | tmpnode = prom_searchsiblings(uctrlnode, "obio"); | 357 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
358 | if (!p) { | ||
359 | printk(KERN_ERR "uctrl: Unable to allocate device struct.\n"); | ||
360 | goto out; | ||
361 | } | ||
367 | 362 | ||
368 | if (tmpnode) | 363 | p->regs = of_ioremap(&op->resource[0], 0, |
369 | uctrlnode = prom_getchild(tmpnode); | 364 | resource_size(&op->resource[0]), |
365 | "uctrl"); | ||
366 | if (!p->regs) { | ||
367 | printk(KERN_ERR "uctrl: Unable to map registers.\n"); | ||
368 | goto out_free; | ||
369 | } | ||
370 | 370 | ||
371 | uctrlnode = prom_searchsiblings(uctrlnode, "uctrl"); | 371 | p->irq = op->irqs[0]; |
372 | err = request_irq(p->irq, uctrl_interrupt, 0, "uctrl", p); | ||
373 | if (err) { | ||
374 | printk(KERN_ERR "uctrl: Unable to register irq.\n"); | ||
375 | goto out_iounmap; | ||
376 | } | ||
372 | 377 | ||
373 | if (!uctrlnode) | 378 | err = misc_register(&uctrl_dev); |
374 | return -ENODEV; | 379 | if (err) { |
380 | printk(KERN_ERR "uctrl: Unable to register misc device.\n"); | ||
381 | goto out_free_irq; | ||
382 | } | ||
375 | 383 | ||
376 | /* the prom mapped it for us */ | 384 | sbus_writel(UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK, &p->regs->uctrl_intr); |
377 | len = prom_getproperty(uctrlnode, "address", (void *) vaddr, | 385 | printk(KERN_INFO "%s: uctrl regs[0x%p] (irq %d)\n", |
378 | sizeof(vaddr)); | 386 | op->node->full_name, p->regs, p->irq); |
379 | driver->regs = (struct uctrl_regs *)vaddr[0]; | 387 | uctrl_get_event_status(p); |
388 | uctrl_get_external_status(p); | ||
380 | 389 | ||
381 | len = prom_getproperty(uctrlnode, "intr", (char *) tmp_irq, | 390 | dev_set_drvdata(&op->dev, p); |
382 | sizeof(tmp_irq)); | 391 | global_driver = p; |
383 | 392 | ||
384 | /* Flush device */ | 393 | out: |
385 | READUCTLDATA(len); | 394 | return err; |
386 | 395 | ||
387 | if(!driver->irq) | 396 | out_free_irq: |
388 | driver->irq = tmp_irq[0].pri; | 397 | free_irq(p->irq, p); |
389 | 398 | ||
390 | err = request_irq(driver->irq, uctrl_interrupt, 0, "uctrl", driver); | 399 | out_iounmap: |
391 | if (err) { | 400 | of_iounmap(&op->resource[0], p->regs, resource_size(&op->resource[0])); |
392 | printk("%s: unable to register irq %d\n", | ||
393 | __func__, driver->irq); | ||
394 | return err; | ||
395 | } | ||
396 | 401 | ||
397 | if (misc_register(&uctrl_dev)) { | 402 | out_free: |
398 | printk("%s: unable to get misc minor %d\n", | 403 | kfree(p); |
399 | __func__, uctrl_dev.minor); | 404 | goto out; |
400 | free_irq(driver->irq, driver); | 405 | } |
401 | return -ENODEV; | ||
402 | } | ||
403 | 406 | ||
404 | driver->regs->uctrl_intr = UCTRL_INTR_RXNE_REQ|UCTRL_INTR_RXNE_MSK; | 407 | static int __devexit uctrl_remove(struct of_device *op) |
405 | printk("uctrl: 0x%p (irq %d)\n", driver->regs, driver->irq); | 408 | { |
406 | uctrl_get_event_status(); | 409 | struct uctrl_driver *p = dev_get_drvdata(&op->dev); |
407 | uctrl_get_external_status(); | 410 | |
408 | return 0; | 411 | if (p) { |
412 | misc_deregister(&uctrl_dev); | ||
413 | free_irq(p->irq, p); | ||
414 | of_iounmap(&op->resource[0], p->regs, resource_size(&op->resource[0])); | ||
415 | kfree(p); | ||
416 | } | ||
417 | return 0; | ||
409 | } | 418 | } |
410 | 419 | ||
411 | static void __exit ts102_uctrl_cleanup(void) | 420 | static const struct of_device_id uctrl_match[] = { |
421 | { | ||
422 | .name = "uctrl", | ||
423 | }, | ||
424 | {}, | ||
425 | }; | ||
426 | MODULE_DEVICE_TABLE(of, uctrl_match); | ||
427 | |||
428 | static struct of_platform_driver uctrl_driver = { | ||
429 | .name = "uctrl", | ||
430 | .match_table = uctrl_match, | ||
431 | .probe = uctrl_probe, | ||
432 | .remove = __devexit_p(uctrl_remove), | ||
433 | }; | ||
434 | |||
435 | |||
436 | static int __init uctrl_init(void) | ||
412 | { | 437 | { |
413 | struct uctrl_driver *driver = &drv; | 438 | return of_register_driver(&uctrl_driver, &of_bus_type); |
439 | } | ||
414 | 440 | ||
415 | misc_deregister(&uctrl_dev); | 441 | static void __exit uctrl_exit(void) |
416 | if (driver->irq) | 442 | { |
417 | free_irq(driver->irq, driver); | 443 | of_unregister_driver(&uctrl_driver); |
418 | if (driver->regs) | ||
419 | driver->regs = NULL; | ||
420 | } | 444 | } |
421 | 445 | ||
422 | module_init(ts102_uctrl_init); | 446 | module_init(uctrl_init); |
423 | module_exit(ts102_uctrl_cleanup); | 447 | module_exit(uctrl_exit); |
424 | MODULE_LICENSE("GPL"); | 448 | MODULE_LICENSE("GPL"); |
diff --git a/drivers/sbus/char/vfc.h b/drivers/sbus/char/vfc.h deleted file mode 100644 index a5240c52aa0b..000000000000 --- a/drivers/sbus/char/vfc.h +++ /dev/null | |||
@@ -1,171 +0,0 @@ | |||
1 | #ifndef _LINUX_VFC_H_ | ||
2 | #define _LINUX_VFC_H_ | ||
3 | |||
4 | /* | ||
5 | * The control register for the vfc is at offset 0x4000 | ||
6 | * The first field ram bank is located at offset 0x5000 | ||
7 | * The second field ram bank is at offset 0x7000 | ||
8 | * i2c_reg address the Phillips PCF8584(see notes in vfc_i2c.c) | ||
9 | * data and transmit register. | ||
10 | * i2c_s1 controls register s1 of the PCF8584 | ||
11 | * i2c_write seems to be similar to i2c_write but I am not | ||
12 | * quite sure why sun uses it | ||
13 | * | ||
14 | * I am also not sure whether or not you can read the fram bank as a | ||
15 | * whole or whether you must read each word individually from offset | ||
16 | * 0x5000 as soon as I figure it out I will update this file */ | ||
17 | |||
18 | struct vfc_regs { | ||
19 | char pad1[0x4000]; | ||
20 | unsigned int control; /* Offset 0x4000 */ | ||
21 | char pad2[0xffb]; /* from offset 0x4004 to 0x5000 */ | ||
22 | unsigned int fram_bank1; /* Offset 0x5000 */ | ||
23 | char pad3[0xffb]; /* from offset 0x5004 to 0x6000 */ | ||
24 | unsigned int i2c_reg; /* Offset 0x6000 */ | ||
25 | unsigned int i2c_magic2; /* Offset 0x6004 */ | ||
26 | unsigned int i2c_s1; /* Offset 0x6008 */ | ||
27 | unsigned int i2c_write; /* Offset 0x600c */ | ||
28 | char pad4[0xff0]; /* from offset 0x6010 to 0x7000 */ | ||
29 | unsigned int fram_bank2; /* Offset 0x7000 */ | ||
30 | char pad5[0x1000]; | ||
31 | }; | ||
32 | |||
33 | #define VFC_SAA9051_NR (13) | ||
34 | #define VFC_SAA9051_ADDR (0x8a) | ||
35 | /* The saa9051 returns the following for its status | ||
36 | * bit 0 - 0 | ||
37 | * bit 1 - SECAM color detected (1=found,0=not found) | ||
38 | * bit 2 - COLOR detected (1=found,0=not found) | ||
39 | * bit 3 - 0 | ||
40 | * bit 4 - Field frequency bit (1=60Hz (NTSC), 0=50Hz (PAL)) | ||
41 | * bit 5 - 1 | ||
42 | * bit 6 - horizontal frequency lock (1=transmitter found, | ||
43 | * 0=no transmitter) | ||
44 | * bit 7 - Power on reset bit (1=reset,0=at least one successful | ||
45 | * read of the status byte) | ||
46 | */ | ||
47 | |||
48 | #define VFC_SAA9051_PONRES (0x80) | ||
49 | #define VFC_SAA9051_HLOCK (0x40) | ||
50 | #define VFC_SAA9051_FD (0x10) | ||
51 | #define VFC_SAA9051_CD (0x04) | ||
52 | #define VFC_SAA9051_CS (0x02) | ||
53 | |||
54 | |||
55 | /* The various saa9051 sub addresses */ | ||
56 | |||
57 | #define VFC_SAA9051_IDEL (0) | ||
58 | #define VFC_SAA9051_HSY_START (1) | ||
59 | #define VFC_SAA9051_HSY_STOP (2) | ||
60 | #define VFC_SAA9051_HC_START (3) | ||
61 | #define VFC_SAA9051_HC_STOP (4) | ||
62 | #define VFC_SAA9051_HS_START (5) | ||
63 | #define VFC_SAA9051_HORIZ_PEAK (6) | ||
64 | #define VFC_SAA9051_HUE (7) | ||
65 | #define VFC_SAA9051_C1 (8) | ||
66 | #define VFC_SAA9051_C2 (9) | ||
67 | #define VFC_SAA9051_C3 (0xa) | ||
68 | #define VFC_SAA9051_SECAM_DELAY (0xb) | ||
69 | |||
70 | |||
71 | /* Bit settings for saa9051 sub address 0x06 */ | ||
72 | |||
73 | #define VFC_SAA9051_AP1 (0x01) | ||
74 | #define VFC_SAA9051_AP2 (0x02) | ||
75 | #define VFC_SAA9051_COR1 (0x04) | ||
76 | #define VFC_SAA9051_COR2 (0x08) | ||
77 | #define VFC_SAA9051_BP1 (0x10) | ||
78 | #define VFC_SAA9051_BP2 (0x20) | ||
79 | #define VFC_SAA9051_PF (0x40) | ||
80 | #define VFC_SAA9051_BY (0x80) | ||
81 | |||
82 | |||
83 | /* Bit settings for saa9051 sub address 0x08 */ | ||
84 | |||
85 | #define VFC_SAA9051_CCFR0 (0x01) | ||
86 | #define VFC_SAA9051_CCFR1 (0x02) | ||
87 | #define VFC_SAA9051_YPN (0x04) | ||
88 | #define VFC_SAA9051_ALT (0x08) | ||
89 | #define VFC_SAA9051_CO (0x10) | ||
90 | #define VFC_SAA9051_VTR (0x20) | ||
91 | #define VFC_SAA9051_FS (0x40) | ||
92 | #define VFC_SAA9051_HPLL (0x80) | ||
93 | |||
94 | |||
95 | /* Bit settings for saa9051 sub address 9 */ | ||
96 | |||
97 | #define VFC_SAA9051_SS0 (0x01) | ||
98 | #define VFC_SAA9051_SS1 (0x02) | ||
99 | #define VFC_SAA9051_AFCC (0x04) | ||
100 | #define VFC_SAA9051_CI (0x08) | ||
101 | #define VFC_SAA9051_SA9D4 (0x10) /* Don't care bit */ | ||
102 | #define VFC_SAA9051_OEC (0x20) | ||
103 | #define VFC_SAA9051_OEY (0x40) | ||
104 | #define VFC_SAA9051_VNL (0x80) | ||
105 | |||
106 | |||
107 | /* Bit settings for saa9051 sub address 0x0A */ | ||
108 | |||
109 | #define VFC_SAA9051_YDL0 (0x01) | ||
110 | #define VFC_SAA9051_YDL1 (0x02) | ||
111 | #define VFC_SAA9051_YDL2 (0x04) | ||
112 | #define VFC_SAA9051_SS2 (0x08) | ||
113 | #define VFC_SAA9051_SS3 (0x10) | ||
114 | #define VFC_SAA9051_YC (0x20) | ||
115 | #define VFC_SAA9051_CT (0x40) | ||
116 | #define VFC_SAA9051_SYC (0x80) | ||
117 | |||
118 | |||
119 | #define VFC_SAA9051_SA(a,b) ((a)->saa9051_state_array[(b)+1]) | ||
120 | #define vfc_update_saa9051(a) (vfc_i2c_sendbuf((a),VFC_SAA9051_ADDR,\ | ||
121 | (a)->saa9051_state_array,\ | ||
122 | VFC_SAA9051_NR)) | ||
123 | |||
124 | |||
125 | struct vfc_dev { | ||
126 | volatile struct vfc_regs __iomem *regs; | ||
127 | struct vfc_regs *phys_regs; | ||
128 | unsigned int control_reg; | ||
129 | struct mutex device_lock_mtx; | ||
130 | int instance; | ||
131 | int busy; | ||
132 | unsigned long which_io; | ||
133 | unsigned char saa9051_state_array[VFC_SAA9051_NR]; | ||
134 | }; | ||
135 | |||
136 | void captstat_reset(struct vfc_dev *); | ||
137 | void memptr_reset(struct vfc_dev *); | ||
138 | |||
139 | int vfc_pcf8584_init(struct vfc_dev *); | ||
140 | void vfc_i2c_delay_no_busy(struct vfc_dev *, unsigned long); | ||
141 | void vfc_i2c_delay(struct vfc_dev *); | ||
142 | int vfc_i2c_sendbuf(struct vfc_dev *, unsigned char, char *, int) ; | ||
143 | int vfc_i2c_recvbuf(struct vfc_dev *, unsigned char, char *, int) ; | ||
144 | int vfc_i2c_reset_bus(struct vfc_dev *); | ||
145 | int vfc_init_i2c_bus(struct vfc_dev *); | ||
146 | |||
147 | #define VFC_CONTROL_DIAGMODE 0x10000000 | ||
148 | #define VFC_CONTROL_MEMPTR 0x20000000 | ||
149 | #define VFC_CONTROL_CAPTURE 0x02000000 | ||
150 | #define VFC_CONTROL_CAPTRESET 0x04000000 | ||
151 | |||
152 | #define VFC_STATUS_CAPTURE 0x08000000 | ||
153 | |||
154 | #ifdef VFC_IOCTL_DEBUG | ||
155 | #define VFC_IOCTL_DEBUG_PRINTK(a) printk a | ||
156 | #else | ||
157 | #define VFC_IOCTL_DEBUG_PRINTK(a) | ||
158 | #endif | ||
159 | |||
160 | #ifdef VFC_I2C_DEBUG | ||
161 | #define VFC_I2C_DEBUG_PRINTK(a) printk a | ||
162 | #else | ||
163 | #define VFC_I2C_DEBUG_PRINTK(a) | ||
164 | #endif | ||
165 | |||
166 | #endif /* _LINUX_VFC_H_ */ | ||
167 | |||
168 | |||
169 | |||
170 | |||
171 | |||
diff --git a/drivers/sbus/char/vfc_dev.c b/drivers/sbus/char/vfc_dev.c deleted file mode 100644 index 25181bb7d627..000000000000 --- a/drivers/sbus/char/vfc_dev.c +++ /dev/null | |||
@@ -1,736 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/sbus/char/vfc_dev.c | ||
3 | * | ||
4 | * Driver for the Videopix Frame Grabber. | ||
5 | * | ||
6 | * In order to use the VFC you need to program the video controller | ||
7 | * chip. This chip is the Phillips SAA9051. You need to call their | ||
8 | * documentation ordering line to get the docs. | ||
9 | * | ||
10 | * There is very little documentation on the VFC itself. There is | ||
11 | * some useful info that can be found in the manuals that come with | ||
12 | * the card. I will hopefully write some better docs at a later date. | ||
13 | * | ||
14 | * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu) | ||
15 | * */ | ||
16 | |||
17 | #include <linux/module.h> | ||
18 | #include <linux/kernel.h> | ||
19 | #include <linux/string.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/errno.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/delay.h> | ||
24 | #include <linux/spinlock.h> | ||
25 | #include <linux/mutex.h> | ||
26 | #include <linux/mm.h> | ||
27 | #include <linux/smp_lock.h> | ||
28 | |||
29 | #include <asm/openprom.h> | ||
30 | #include <asm/oplib.h> | ||
31 | #include <asm/io.h> | ||
32 | #include <asm/system.h> | ||
33 | #include <asm/sbus.h> | ||
34 | #include <asm/page.h> | ||
35 | #include <asm/pgtable.h> | ||
36 | #include <asm/uaccess.h> | ||
37 | |||
38 | #define VFC_MAJOR (60) | ||
39 | |||
40 | #if 0 | ||
41 | #define VFC_IOCTL_DEBUG | ||
42 | #endif | ||
43 | |||
44 | #include "vfc.h" | ||
45 | #include <asm/vfc_ioctls.h> | ||
46 | |||
47 | static const struct file_operations vfc_fops; | ||
48 | static struct vfc_dev **vfc_dev_lst; | ||
49 | static char vfcstr[]="vfc"; | ||
50 | static unsigned char saa9051_init_array[VFC_SAA9051_NR] = { | ||
51 | 0x00, 0x64, 0x72, 0x52, | ||
52 | 0x36, 0x18, 0xff, 0x20, | ||
53 | 0xfc, 0x77, 0xe3, 0x50, | ||
54 | 0x3e | ||
55 | }; | ||
56 | |||
57 | static void vfc_lock_device(struct vfc_dev *dev) | ||
58 | { | ||
59 | mutex_lock(&dev->device_lock_mtx); | ||
60 | } | ||
61 | |||
62 | static void vfc_unlock_device(struct vfc_dev *dev) | ||
63 | { | ||
64 | mutex_unlock(&dev->device_lock_mtx); | ||
65 | } | ||
66 | |||
67 | |||
68 | static void vfc_captstat_reset(struct vfc_dev *dev) | ||
69 | { | ||
70 | dev->control_reg |= VFC_CONTROL_CAPTRESET; | ||
71 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
72 | dev->control_reg &= ~VFC_CONTROL_CAPTRESET; | ||
73 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
74 | dev->control_reg |= VFC_CONTROL_CAPTRESET; | ||
75 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
76 | } | ||
77 | |||
78 | static void vfc_memptr_reset(struct vfc_dev *dev) | ||
79 | { | ||
80 | dev->control_reg |= VFC_CONTROL_MEMPTR; | ||
81 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
82 | dev->control_reg &= ~VFC_CONTROL_MEMPTR; | ||
83 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
84 | dev->control_reg |= VFC_CONTROL_MEMPTR; | ||
85 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
86 | } | ||
87 | |||
88 | static int vfc_csr_init(struct vfc_dev *dev) | ||
89 | { | ||
90 | dev->control_reg = 0x80000000; | ||
91 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
92 | udelay(200); | ||
93 | dev->control_reg &= ~0x80000000; | ||
94 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
95 | udelay(100); | ||
96 | sbus_writel(0x0f000000, &dev->regs->i2c_magic2); | ||
97 | |||
98 | vfc_memptr_reset(dev); | ||
99 | |||
100 | dev->control_reg &= ~VFC_CONTROL_DIAGMODE; | ||
101 | dev->control_reg &= ~VFC_CONTROL_CAPTURE; | ||
102 | dev->control_reg |= 0x40000000; | ||
103 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
104 | |||
105 | vfc_captstat_reset(dev); | ||
106 | |||
107 | return 0; | ||
108 | } | ||
109 | |||
110 | static int vfc_saa9051_init(struct vfc_dev *dev) | ||
111 | { | ||
112 | int i; | ||
113 | |||
114 | for (i = 0; i < VFC_SAA9051_NR; i++) | ||
115 | dev->saa9051_state_array[i] = saa9051_init_array[i]; | ||
116 | |||
117 | vfc_i2c_sendbuf(dev,VFC_SAA9051_ADDR, | ||
118 | dev->saa9051_state_array, VFC_SAA9051_NR); | ||
119 | return 0; | ||
120 | } | ||
121 | |||
122 | static int init_vfc_hw(struct vfc_dev *dev) | ||
123 | { | ||
124 | vfc_lock_device(dev); | ||
125 | vfc_csr_init(dev); | ||
126 | |||
127 | vfc_pcf8584_init(dev); | ||
128 | vfc_init_i2c_bus(dev); /* hopefully this doesn't undo the magic | ||
129 | sun code above*/ | ||
130 | vfc_saa9051_init(dev); | ||
131 | vfc_unlock_device(dev); | ||
132 | return 0; | ||
133 | } | ||
134 | |||
135 | static int init_vfc_devstruct(struct vfc_dev *dev, int instance) | ||
136 | { | ||
137 | dev->instance=instance; | ||
138 | mutex_init(&dev->device_lock_mtx); | ||
139 | dev->control_reg=0; | ||
140 | dev->busy=0; | ||
141 | return 0; | ||
142 | } | ||
143 | |||
144 | static int init_vfc_device(struct sbus_dev *sdev,struct vfc_dev *dev, | ||
145 | int instance) | ||
146 | { | ||
147 | if(dev == NULL) { | ||
148 | printk(KERN_ERR "VFC: Bogus pointer passed\n"); | ||
149 | return -ENOMEM; | ||
150 | } | ||
151 | printk("Initializing vfc%d\n",instance); | ||
152 | dev->regs = NULL; | ||
153 | dev->regs = (volatile struct vfc_regs __iomem *) | ||
154 | sbus_ioremap(&sdev->resource[0], 0, | ||
155 | sizeof(struct vfc_regs), vfcstr); | ||
156 | dev->which_io = sdev->reg_addrs[0].which_io; | ||
157 | dev->phys_regs = (struct vfc_regs *) sdev->reg_addrs[0].phys_addr; | ||
158 | if (dev->regs == NULL) | ||
159 | return -EIO; | ||
160 | |||
161 | printk("vfc%d: registers mapped at phys_addr: 0x%lx\n virt_addr: 0x%lx\n", | ||
162 | instance,(unsigned long)sdev->reg_addrs[0].phys_addr,(unsigned long)dev->regs); | ||
163 | |||
164 | if (init_vfc_devstruct(dev, instance)) | ||
165 | return -EINVAL; | ||
166 | if (init_vfc_hw(dev)) | ||
167 | return -EIO; | ||
168 | return 0; | ||
169 | } | ||
170 | |||
171 | |||
172 | static struct vfc_dev *vfc_get_dev_ptr(int instance) | ||
173 | { | ||
174 | return vfc_dev_lst[instance]; | ||
175 | } | ||
176 | |||
177 | static DEFINE_SPINLOCK(vfc_dev_lock); | ||
178 | |||
179 | static int vfc_open(struct inode *inode, struct file *file) | ||
180 | { | ||
181 | struct vfc_dev *dev; | ||
182 | |||
183 | lock_kernel(); | ||
184 | spin_lock(&vfc_dev_lock); | ||
185 | dev = vfc_get_dev_ptr(iminor(inode)); | ||
186 | if (dev == NULL) { | ||
187 | spin_unlock(&vfc_dev_lock); | ||
188 | unlock_kernel(); | ||
189 | return -ENODEV; | ||
190 | } | ||
191 | if (dev->busy) { | ||
192 | spin_unlock(&vfc_dev_lock); | ||
193 | unlock_kernel(); | ||
194 | return -EBUSY; | ||
195 | } | ||
196 | |||
197 | dev->busy = 1; | ||
198 | spin_unlock(&vfc_dev_lock); | ||
199 | |||
200 | vfc_lock_device(dev); | ||
201 | |||
202 | vfc_csr_init(dev); | ||
203 | vfc_pcf8584_init(dev); | ||
204 | vfc_init_i2c_bus(dev); | ||
205 | vfc_saa9051_init(dev); | ||
206 | vfc_memptr_reset(dev); | ||
207 | vfc_captstat_reset(dev); | ||
208 | |||
209 | vfc_unlock_device(dev); | ||
210 | unlock_kernel(); | ||
211 | return 0; | ||
212 | } | ||
213 | |||
214 | static int vfc_release(struct inode *inode,struct file *file) | ||
215 | { | ||
216 | struct vfc_dev *dev; | ||
217 | |||
218 | spin_lock(&vfc_dev_lock); | ||
219 | dev = vfc_get_dev_ptr(iminor(inode)); | ||
220 | if (!dev || !dev->busy) { | ||
221 | spin_unlock(&vfc_dev_lock); | ||
222 | return -EINVAL; | ||
223 | } | ||
224 | dev->busy = 0; | ||
225 | spin_unlock(&vfc_dev_lock); | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | static int vfc_debug(struct vfc_dev *dev, int cmd, void __user *argp) | ||
230 | { | ||
231 | struct vfc_debug_inout inout; | ||
232 | unsigned char *buffer; | ||
233 | |||
234 | if (!capable(CAP_SYS_ADMIN)) | ||
235 | return -EPERM; | ||
236 | |||
237 | switch(cmd) { | ||
238 | case VFC_I2C_SEND: | ||
239 | if(copy_from_user(&inout, argp, sizeof(inout))) | ||
240 | return -EFAULT; | ||
241 | |||
242 | buffer = kmalloc(inout.len, GFP_KERNEL); | ||
243 | if (buffer == NULL) | ||
244 | return -ENOMEM; | ||
245 | |||
246 | if(copy_from_user(buffer, inout.buffer, inout.len)) { | ||
247 | kfree(buffer); | ||
248 | return -EFAULT; | ||
249 | } | ||
250 | |||
251 | |||
252 | vfc_lock_device(dev); | ||
253 | inout.ret= | ||
254 | vfc_i2c_sendbuf(dev,inout.addr & 0xff, | ||
255 | buffer,inout.len); | ||
256 | |||
257 | if (copy_to_user(argp,&inout,sizeof(inout))) { | ||
258 | vfc_unlock_device(dev); | ||
259 | kfree(buffer); | ||
260 | return -EFAULT; | ||
261 | } | ||
262 | vfc_unlock_device(dev); | ||
263 | |||
264 | break; | ||
265 | case VFC_I2C_RECV: | ||
266 | if (copy_from_user(&inout, argp, sizeof(inout))) | ||
267 | return -EFAULT; | ||
268 | |||
269 | buffer = kzalloc(inout.len, GFP_KERNEL); | ||
270 | if (buffer == NULL) | ||
271 | return -ENOMEM; | ||
272 | |||
273 | vfc_lock_device(dev); | ||
274 | inout.ret= | ||
275 | vfc_i2c_recvbuf(dev,inout.addr & 0xff | ||
276 | ,buffer,inout.len); | ||
277 | vfc_unlock_device(dev); | ||
278 | |||
279 | if (copy_to_user(inout.buffer, buffer, inout.len)) { | ||
280 | kfree(buffer); | ||
281 | return -EFAULT; | ||
282 | } | ||
283 | if (copy_to_user(argp,&inout,sizeof(inout))) { | ||
284 | kfree(buffer); | ||
285 | return -EFAULT; | ||
286 | } | ||
287 | kfree(buffer); | ||
288 | break; | ||
289 | default: | ||
290 | return -EINVAL; | ||
291 | }; | ||
292 | |||
293 | return 0; | ||
294 | } | ||
295 | |||
296 | static int vfc_capture_start(struct vfc_dev *dev) | ||
297 | { | ||
298 | vfc_captstat_reset(dev); | ||
299 | dev->control_reg = sbus_readl(&dev->regs->control); | ||
300 | if((dev->control_reg & VFC_STATUS_CAPTURE)) { | ||
301 | printk(KERN_ERR "vfc%d: vfc capture status not reset\n", | ||
302 | dev->instance); | ||
303 | return -EIO; | ||
304 | } | ||
305 | |||
306 | vfc_lock_device(dev); | ||
307 | dev->control_reg &= ~VFC_CONTROL_CAPTURE; | ||
308 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
309 | dev->control_reg |= VFC_CONTROL_CAPTURE; | ||
310 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
311 | dev->control_reg &= ~VFC_CONTROL_CAPTURE; | ||
312 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
313 | vfc_unlock_device(dev); | ||
314 | |||
315 | return 0; | ||
316 | } | ||
317 | |||
318 | static int vfc_capture_poll(struct vfc_dev *dev) | ||
319 | { | ||
320 | int timeout = 1000; | ||
321 | |||
322 | while (!timeout--) { | ||
323 | if (sbus_readl(&dev->regs->control) & VFC_STATUS_CAPTURE) | ||
324 | break; | ||
325 | vfc_i2c_delay_no_busy(dev, 100); | ||
326 | } | ||
327 | if(!timeout) { | ||
328 | printk(KERN_WARNING "vfc%d: capture timed out\n", | ||
329 | dev->instance); | ||
330 | return -ETIMEDOUT; | ||
331 | } | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | |||
336 | |||
337 | static int vfc_set_control_ioctl(struct inode *inode, struct file *file, | ||
338 | struct vfc_dev *dev, unsigned long arg) | ||
339 | { | ||
340 | int setcmd, ret = 0; | ||
341 | |||
342 | if (copy_from_user(&setcmd,(void __user *)arg,sizeof(unsigned int))) | ||
343 | return -EFAULT; | ||
344 | |||
345 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSCTRL) arg=0x%x\n", | ||
346 | dev->instance,setcmd)); | ||
347 | |||
348 | switch(setcmd) { | ||
349 | case MEMPRST: | ||
350 | vfc_lock_device(dev); | ||
351 | vfc_memptr_reset(dev); | ||
352 | vfc_unlock_device(dev); | ||
353 | ret=0; | ||
354 | break; | ||
355 | case CAPTRCMD: | ||
356 | vfc_capture_start(dev); | ||
357 | vfc_capture_poll(dev); | ||
358 | break; | ||
359 | case DIAGMODE: | ||
360 | if(capable(CAP_SYS_ADMIN)) { | ||
361 | vfc_lock_device(dev); | ||
362 | dev->control_reg |= VFC_CONTROL_DIAGMODE; | ||
363 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
364 | vfc_unlock_device(dev); | ||
365 | ret = 0; | ||
366 | } else { | ||
367 | ret = -EPERM; | ||
368 | } | ||
369 | break; | ||
370 | case NORMMODE: | ||
371 | vfc_lock_device(dev); | ||
372 | dev->control_reg &= ~VFC_CONTROL_DIAGMODE; | ||
373 | sbus_writel(dev->control_reg, &dev->regs->control); | ||
374 | vfc_unlock_device(dev); | ||
375 | ret = 0; | ||
376 | break; | ||
377 | case CAPTRSTR: | ||
378 | vfc_capture_start(dev); | ||
379 | ret = 0; | ||
380 | break; | ||
381 | case CAPTRWAIT: | ||
382 | vfc_capture_poll(dev); | ||
383 | ret = 0; | ||
384 | break; | ||
385 | default: | ||
386 | ret = -EINVAL; | ||
387 | break; | ||
388 | }; | ||
389 | |||
390 | return ret; | ||
391 | } | ||
392 | |||
393 | |||
394 | static int vfc_port_change_ioctl(struct inode *inode, struct file *file, | ||
395 | struct vfc_dev *dev, unsigned long arg) | ||
396 | { | ||
397 | int ret = 0; | ||
398 | int cmd; | ||
399 | |||
400 | if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) { | ||
401 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " | ||
402 | "vfc_port_change_ioctl\n", | ||
403 | dev->instance)); | ||
404 | return -EFAULT; | ||
405 | } | ||
406 | |||
407 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCPORTCHG) arg=0x%x\n", | ||
408 | dev->instance, cmd)); | ||
409 | |||
410 | switch(cmd) { | ||
411 | case 1: | ||
412 | case 2: | ||
413 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x72; | ||
414 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x52; | ||
415 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0x36; | ||
416 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0x18; | ||
417 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = VFC_SAA9051_BP2; | ||
418 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_CT | VFC_SAA9051_SS3; | ||
419 | VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0x3e; | ||
420 | break; | ||
421 | case 3: | ||
422 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_START) = 0x3a; | ||
423 | VFC_SAA9051_SA(dev,VFC_SAA9051_HSY_STOP) = 0x17; | ||
424 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_START) = 0xfa; | ||
425 | VFC_SAA9051_SA(dev,VFC_SAA9051_HC_STOP) = 0xde; | ||
426 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) = | ||
427 | VFC_SAA9051_BY | VFC_SAA9051_PF | VFC_SAA9051_BP2; | ||
428 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) = VFC_SAA9051_YC; | ||
429 | VFC_SAA9051_SA(dev,VFC_SAA9051_SECAM_DELAY) = 0; | ||
430 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= | ||
431 | ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); | ||
432 | break; | ||
433 | default: | ||
434 | ret = -EINVAL; | ||
435 | return ret; | ||
436 | break; | ||
437 | } | ||
438 | |||
439 | switch(cmd) { | ||
440 | case 1: | ||
441 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= | ||
442 | (VFC_SAA9051_SS0 | VFC_SAA9051_SS1); | ||
443 | break; | ||
444 | case 2: | ||
445 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) &= | ||
446 | ~(VFC_SAA9051_SS0 | VFC_SAA9051_SS1); | ||
447 | VFC_SAA9051_SA(dev,VFC_SAA9051_C2) |= VFC_SAA9051_SS0; | ||
448 | break; | ||
449 | case 3: | ||
450 | break; | ||
451 | default: | ||
452 | ret = -EINVAL; | ||
453 | return ret; | ||
454 | break; | ||
455 | } | ||
456 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) &= ~(VFC_SAA9051_SS2); | ||
457 | ret=vfc_update_saa9051(dev); | ||
458 | udelay(500); | ||
459 | VFC_SAA9051_SA(dev,VFC_SAA9051_C3) |= (VFC_SAA9051_SS2); | ||
460 | ret=vfc_update_saa9051(dev); | ||
461 | return ret; | ||
462 | } | ||
463 | |||
464 | static int vfc_set_video_ioctl(struct inode *inode, struct file *file, | ||
465 | struct vfc_dev *dev, unsigned long arg) | ||
466 | { | ||
467 | int ret = 0; | ||
468 | int cmd; | ||
469 | |||
470 | if(copy_from_user(&cmd, (void __user *)arg, sizeof(unsigned int))) { | ||
471 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " | ||
472 | "vfc_set_video_ioctl\n", | ||
473 | dev->instance)); | ||
474 | return ret; | ||
475 | } | ||
476 | |||
477 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCSVID) arg=0x%x\n", | ||
478 | dev->instance, cmd)); | ||
479 | switch(cmd) { | ||
480 | case STD_NTSC: | ||
481 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~VFC_SAA9051_ALT; | ||
482 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_YPN | | ||
483 | VFC_SAA9051_CCFR0 | VFC_SAA9051_CCFR1 | VFC_SAA9051_FS; | ||
484 | ret = vfc_update_saa9051(dev); | ||
485 | break; | ||
486 | case STD_PAL: | ||
487 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_YPN | | ||
488 | VFC_SAA9051_CCFR1 | | ||
489 | VFC_SAA9051_CCFR0 | | ||
490 | VFC_SAA9051_FS); | ||
491 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_ALT; | ||
492 | ret = vfc_update_saa9051(dev); | ||
493 | break; | ||
494 | |||
495 | case COLOR_ON: | ||
496 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) |= VFC_SAA9051_CO; | ||
497 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) &= | ||
498 | ~(VFC_SAA9051_BY | VFC_SAA9051_PF); | ||
499 | ret = vfc_update_saa9051(dev); | ||
500 | break; | ||
501 | case MONO: | ||
502 | VFC_SAA9051_SA(dev,VFC_SAA9051_C1) &= ~(VFC_SAA9051_CO); | ||
503 | VFC_SAA9051_SA(dev,VFC_SAA9051_HORIZ_PEAK) |= | ||
504 | (VFC_SAA9051_BY | VFC_SAA9051_PF); | ||
505 | ret = vfc_update_saa9051(dev); | ||
506 | break; | ||
507 | default: | ||
508 | ret = -EINVAL; | ||
509 | break; | ||
510 | }; | ||
511 | |||
512 | return ret; | ||
513 | } | ||
514 | |||
515 | static int vfc_get_video_ioctl(struct inode *inode, struct file *file, | ||
516 | struct vfc_dev *dev, unsigned long arg) | ||
517 | { | ||
518 | int ret = 0; | ||
519 | unsigned int status = NO_LOCK; | ||
520 | unsigned char buf[1]; | ||
521 | |||
522 | if(vfc_i2c_recvbuf(dev, VFC_SAA9051_ADDR, buf, 1)) { | ||
523 | printk(KERN_ERR "vfc%d: Unable to get status\n", | ||
524 | dev->instance); | ||
525 | return -EIO; | ||
526 | } | ||
527 | |||
528 | if(buf[0] & VFC_SAA9051_HLOCK) { | ||
529 | status = NO_LOCK; | ||
530 | } else if(buf[0] & VFC_SAA9051_FD) { | ||
531 | if(buf[0] & VFC_SAA9051_CD) | ||
532 | status = NTSC_COLOR; | ||
533 | else | ||
534 | status = NTSC_NOCOLOR; | ||
535 | } else { | ||
536 | if(buf[0] & VFC_SAA9051_CD) | ||
537 | status = PAL_COLOR; | ||
538 | else | ||
539 | status = PAL_NOCOLOR; | ||
540 | } | ||
541 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGVID) returning status 0x%x; " | ||
542 | "buf[0]=%x\n", dev->instance, status, buf[0])); | ||
543 | |||
544 | if (copy_to_user((void __user *)arg,&status,sizeof(unsigned int))) { | ||
545 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer to " | ||
546 | "vfc_get_video_ioctl\n", | ||
547 | dev->instance)); | ||
548 | return ret; | ||
549 | } | ||
550 | return ret; | ||
551 | } | ||
552 | |||
553 | static int vfc_ioctl(struct inode *inode, struct file *file, unsigned int cmd, | ||
554 | unsigned long arg) | ||
555 | { | ||
556 | int ret = 0; | ||
557 | unsigned int tmp; | ||
558 | struct vfc_dev *dev; | ||
559 | void __user *argp = (void __user *)arg; | ||
560 | |||
561 | dev = vfc_get_dev_ptr(iminor(inode)); | ||
562 | if(dev == NULL) | ||
563 | return -ENODEV; | ||
564 | |||
565 | switch(cmd & 0x0000ffff) { | ||
566 | case VFCGCTRL: | ||
567 | #if 0 | ||
568 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCGCTRL)\n", dev->instance)); | ||
569 | #endif | ||
570 | tmp = sbus_readl(&dev->regs->control); | ||
571 | if(copy_to_user(argp, &tmp, sizeof(unsigned int))) { | ||
572 | ret = -EFAULT; | ||
573 | break; | ||
574 | } | ||
575 | ret = 0; | ||
576 | break; | ||
577 | case VFCSCTRL: | ||
578 | ret = vfc_set_control_ioctl(inode, file, dev, arg); | ||
579 | break; | ||
580 | case VFCGVID: | ||
581 | ret = vfc_get_video_ioctl(inode, file, dev, arg); | ||
582 | break; | ||
583 | case VFCSVID: | ||
584 | ret = vfc_set_video_ioctl(inode, file, dev, arg); | ||
585 | break; | ||
586 | case VFCHUE: | ||
587 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCHUE)\n", dev->instance)); | ||
588 | if(copy_from_user(&tmp,argp,sizeof(unsigned int))) { | ||
589 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: User passed bogus pointer " | ||
590 | "to IOCTL(VFCHUE)", dev->instance)); | ||
591 | ret = -EFAULT; | ||
592 | } else { | ||
593 | VFC_SAA9051_SA(dev,VFC_SAA9051_HUE) = tmp; | ||
594 | vfc_update_saa9051(dev); | ||
595 | ret = 0; | ||
596 | } | ||
597 | break; | ||
598 | case VFCPORTCHG: | ||
599 | ret = vfc_port_change_ioctl(inode, file, dev, arg); | ||
600 | break; | ||
601 | case VFCRDINFO: | ||
602 | ret = -EINVAL; | ||
603 | VFC_IOCTL_DEBUG_PRINTK(("vfc%d: IOCTL(VFCRDINFO)\n", dev->instance)); | ||
604 | break; | ||
605 | default: | ||
606 | ret = vfc_debug(vfc_get_dev_ptr(iminor(inode)), cmd, argp); | ||
607 | break; | ||
608 | }; | ||
609 | |||
610 | return ret; | ||
611 | } | ||
612 | |||
613 | static int vfc_mmap(struct file *file, struct vm_area_struct *vma) | ||
614 | { | ||
615 | unsigned int map_size, ret, map_offset; | ||
616 | struct vfc_dev *dev; | ||
617 | |||
618 | dev = vfc_get_dev_ptr(iminor(file->f_path.dentry->d_inode)); | ||
619 | if(dev == NULL) | ||
620 | return -ENODEV; | ||
621 | |||
622 | map_size = vma->vm_end - vma->vm_start; | ||
623 | if(map_size > sizeof(struct vfc_regs)) | ||
624 | map_size = sizeof(struct vfc_regs); | ||
625 | |||
626 | vma->vm_flags |= | ||
627 | (VM_MAYREAD | VM_MAYWRITE | VM_MAYSHARE); | ||
628 | map_offset = (unsigned int) (long)dev->phys_regs; | ||
629 | ret = io_remap_pfn_range(vma, vma->vm_start, | ||
630 | MK_IOSPACE_PFN(dev->which_io, | ||
631 | map_offset >> PAGE_SHIFT), | ||
632 | map_size, vma->vm_page_prot); | ||
633 | |||
634 | if(ret) | ||
635 | return -EAGAIN; | ||
636 | |||
637 | return 0; | ||
638 | } | ||
639 | |||
640 | |||
641 | static const struct file_operations vfc_fops = { | ||
642 | .owner = THIS_MODULE, | ||
643 | .llseek = no_llseek, | ||
644 | .ioctl = vfc_ioctl, | ||
645 | .mmap = vfc_mmap, | ||
646 | .open = vfc_open, | ||
647 | .release = vfc_release, | ||
648 | }; | ||
649 | |||
650 | static int vfc_probe(void) | ||
651 | { | ||
652 | struct sbus_bus *sbus; | ||
653 | struct sbus_dev *sdev = NULL; | ||
654 | int ret; | ||
655 | int instance = 0, cards = 0; | ||
656 | |||
657 | for_all_sbusdev(sdev, sbus) { | ||
658 | if (strcmp(sdev->prom_name, "vfc") == 0) { | ||
659 | cards++; | ||
660 | continue; | ||
661 | } | ||
662 | } | ||
663 | |||
664 | if (!cards) | ||
665 | return -ENODEV; | ||
666 | |||
667 | vfc_dev_lst = kcalloc(cards + 1, sizeof(struct vfc_dev*), GFP_KERNEL); | ||
668 | if (vfc_dev_lst == NULL) | ||
669 | return -ENOMEM; | ||
670 | vfc_dev_lst[cards] = NULL; | ||
671 | |||
672 | ret = register_chrdev(VFC_MAJOR, vfcstr, &vfc_fops); | ||
673 | if(ret) { | ||
674 | printk(KERN_ERR "Unable to get major number %d\n", VFC_MAJOR); | ||
675 | kfree(vfc_dev_lst); | ||
676 | return -EIO; | ||
677 | } | ||
678 | instance = 0; | ||
679 | for_all_sbusdev(sdev, sbus) { | ||
680 | if (strcmp(sdev->prom_name, "vfc") == 0) { | ||
681 | vfc_dev_lst[instance]=(struct vfc_dev *) | ||
682 | kmalloc(sizeof(struct vfc_dev), GFP_KERNEL); | ||
683 | if (vfc_dev_lst[instance] == NULL) | ||
684 | return -ENOMEM; | ||
685 | ret = init_vfc_device(sdev, | ||
686 | vfc_dev_lst[instance], | ||
687 | instance); | ||
688 | if(ret) { | ||
689 | printk(KERN_ERR "Unable to initialize" | ||
690 | " vfc%d device\n", | ||
691 | instance); | ||
692 | } else { | ||
693 | } | ||
694 | |||
695 | instance++; | ||
696 | continue; | ||
697 | } | ||
698 | } | ||
699 | |||
700 | return 0; | ||
701 | } | ||
702 | |||
703 | #ifdef MODULE | ||
704 | int init_module(void) | ||
705 | #else | ||
706 | int vfc_init(void) | ||
707 | #endif | ||
708 | { | ||
709 | return vfc_probe(); | ||
710 | } | ||
711 | |||
712 | #ifdef MODULE | ||
713 | static void deinit_vfc_device(struct vfc_dev *dev) | ||
714 | { | ||
715 | if(dev == NULL) | ||
716 | return; | ||
717 | sbus_iounmap(dev->regs, sizeof(struct vfc_regs)); | ||
718 | kfree(dev); | ||
719 | } | ||
720 | |||
721 | void cleanup_module(void) | ||
722 | { | ||
723 | struct vfc_dev **devp; | ||
724 | |||
725 | unregister_chrdev(VFC_MAJOR,vfcstr); | ||
726 | |||
727 | for (devp = vfc_dev_lst; *devp; devp++) | ||
728 | deinit_vfc_device(*devp); | ||
729 | |||
730 | kfree(vfc_dev_lst); | ||
731 | return; | ||
732 | } | ||
733 | #endif | ||
734 | |||
735 | MODULE_LICENSE("GPL"); | ||
736 | |||
diff --git a/drivers/sbus/char/vfc_i2c.c b/drivers/sbus/char/vfc_i2c.c deleted file mode 100644 index 32b986e0ed78..000000000000 --- a/drivers/sbus/char/vfc_i2c.c +++ /dev/null | |||
@@ -1,335 +0,0 @@ | |||
1 | /* | ||
2 | * drivers/sbus/char/vfc_i2c.c | ||
3 | * | ||
4 | * Driver for the Videopix Frame Grabber. | ||
5 | * | ||
6 | * Functions that support the Phillips i2c(I squared C) bus on the vfc | ||
7 | * Documentation for the Phillips I2C bus can be found on the | ||
8 | * phillips home page | ||
9 | * | ||
10 | * Copyright (C) 1996 Manish Vachharajani (mvachhar@noc.rutgers.edu) | ||
11 | * | ||
12 | */ | ||
13 | |||
14 | /* NOTE: It seems to me that the documentation regarding the | ||
15 | pcd8584t/pcf8584 does not show the correct way to address the i2c bus. | ||
16 | Based on the information on the I2C bus itself and the remainder of | ||
17 | the Phillips docs the following algorithms appear to be correct. I am | ||
18 | fairly certain that the flowcharts in the phillips docs are wrong. */ | ||
19 | |||
20 | |||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/string.h> | ||
23 | #include <linux/slab.h> | ||
24 | #include <linux/errno.h> | ||
25 | #include <linux/sched.h> | ||
26 | #include <linux/wait.h> | ||
27 | #include <linux/delay.h> | ||
28 | #include <asm/openprom.h> | ||
29 | #include <asm/oplib.h> | ||
30 | #include <asm/io.h> | ||
31 | #include <asm/system.h> | ||
32 | #include <asm/sbus.h> | ||
33 | |||
34 | #if 0 | ||
35 | #define VFC_I2C_DEBUG | ||
36 | #endif | ||
37 | |||
38 | #include "vfc.h" | ||
39 | #include "vfc_i2c.h" | ||
40 | |||
41 | #define WRITE_S1(__val) \ | ||
42 | sbus_writel(__val, &dev->regs->i2c_s1) | ||
43 | #define WRITE_REG(__val) \ | ||
44 | sbus_writel(__val, &dev->regs->i2c_reg) | ||
45 | |||
46 | #define VFC_I2C_READ (0x1) | ||
47 | #define VFC_I2C_WRITE (0x0) | ||
48 | |||
49 | /****** | ||
50 | The i2c bus controller chip on the VFC is a pcd8584t, but | ||
51 | phillips claims it doesn't exist. As far as I can tell it is | ||
52 | identical to the PCF8584 so I treat it like it is the pcf8584. | ||
53 | |||
54 | NOTE: The pcf8584 only cares | ||
55 | about the msb of the word you feed it | ||
56 | *****/ | ||
57 | |||
58 | int vfc_pcf8584_init(struct vfc_dev *dev) | ||
59 | { | ||
60 | /* This will also choose register S0_OWN so we can set it. */ | ||
61 | WRITE_S1(RESET); | ||
62 | |||
63 | /* The pcf8584 shifts this value left one bit and uses | ||
64 | * it as its i2c bus address. | ||
65 | */ | ||
66 | WRITE_REG(0x55000000); | ||
67 | |||
68 | /* This will set the i2c bus at the same speed sun uses, | ||
69 | * and set another magic bit. | ||
70 | */ | ||
71 | WRITE_S1(SELECT(S2)); | ||
72 | WRITE_REG(0x14000000); | ||
73 | |||
74 | /* Enable the serial port, idle the i2c bus and set | ||
75 | * the data reg to s0. | ||
76 | */ | ||
77 | WRITE_S1(CLEAR_I2C_BUS); | ||
78 | udelay(100); | ||
79 | return 0; | ||
80 | } | ||
81 | |||
82 | void vfc_i2c_delay_no_busy(struct vfc_dev *dev, unsigned long usecs) | ||
83 | { | ||
84 | schedule_timeout_uninterruptible(usecs_to_jiffies(usecs)); | ||
85 | } | ||
86 | |||
87 | void inline vfc_i2c_delay(struct vfc_dev *dev) | ||
88 | { | ||
89 | vfc_i2c_delay_no_busy(dev, 100); | ||
90 | } | ||
91 | |||
92 | int vfc_init_i2c_bus(struct vfc_dev *dev) | ||
93 | { | ||
94 | WRITE_S1(ENABLE_SERIAL | SELECT(S0) | ACK); | ||
95 | vfc_i2c_reset_bus(dev); | ||
96 | return 0; | ||
97 | } | ||
98 | |||
99 | int vfc_i2c_reset_bus(struct vfc_dev *dev) | ||
100 | { | ||
101 | VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: Resetting the i2c bus\n", | ||
102 | dev->instance)); | ||
103 | if(dev == NULL) | ||
104 | return -EINVAL; | ||
105 | if(dev->regs == NULL) | ||
106 | return -EINVAL; | ||
107 | WRITE_S1(SEND_I2C_STOP); | ||
108 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
109 | vfc_i2c_delay(dev); | ||
110 | WRITE_S1(CLEAR_I2C_BUS); | ||
111 | VFC_I2C_DEBUG_PRINTK((KERN_DEBUG "vfc%d: I2C status %x\n", | ||
112 | dev->instance, | ||
113 | sbus_readl(&dev->regs->i2c_s1))); | ||
114 | return 0; | ||
115 | } | ||
116 | |||
117 | static int vfc_i2c_wait_for_bus(struct vfc_dev *dev) | ||
118 | { | ||
119 | int timeout = 1000; | ||
120 | |||
121 | while(!(sbus_readl(&dev->regs->i2c_s1) & BB)) { | ||
122 | if(!(timeout--)) | ||
123 | return -ETIMEDOUT; | ||
124 | vfc_i2c_delay(dev); | ||
125 | } | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int vfc_i2c_wait_for_pin(struct vfc_dev *dev, int ack) | ||
130 | { | ||
131 | int timeout = 1000; | ||
132 | int s1; | ||
133 | |||
134 | while ((s1 = sbus_readl(&dev->regs->i2c_s1)) & PIN) { | ||
135 | if (!(timeout--)) | ||
136 | return -ETIMEDOUT; | ||
137 | vfc_i2c_delay(dev); | ||
138 | } | ||
139 | if (ack == VFC_I2C_ACK_CHECK) { | ||
140 | if(s1 & LRB) | ||
141 | return -EIO; | ||
142 | } | ||
143 | return 0; | ||
144 | } | ||
145 | |||
146 | #define SHIFT(a) ((a) << 24) | ||
147 | static int vfc_i2c_xmit_addr(struct vfc_dev *dev, unsigned char addr, | ||
148 | char mode) | ||
149 | { | ||
150 | int ret, raddr; | ||
151 | #if 1 | ||
152 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
153 | WRITE_S1(SELECT(S0) | ENABLE_SERIAL); | ||
154 | vfc_i2c_delay(dev); | ||
155 | #endif | ||
156 | |||
157 | switch(mode) { | ||
158 | case VFC_I2C_READ: | ||
159 | raddr = SHIFT(((unsigned int)addr | 0x1)); | ||
160 | WRITE_REG(raddr); | ||
161 | VFC_I2C_DEBUG_PRINTK(("vfc%d: receiving from i2c addr 0x%x\n", | ||
162 | dev->instance, addr | 0x1)); | ||
163 | break; | ||
164 | case VFC_I2C_WRITE: | ||
165 | raddr = SHIFT((unsigned int)addr & ~0x1); | ||
166 | WRITE_REG(raddr); | ||
167 | VFC_I2C_DEBUG_PRINTK(("vfc%d: sending to i2c addr 0x%x\n", | ||
168 | dev->instance, addr & ~0x1)); | ||
169 | break; | ||
170 | default: | ||
171 | return -EINVAL; | ||
172 | }; | ||
173 | |||
174 | WRITE_S1(SEND_I2C_START); | ||
175 | vfc_i2c_delay(dev); | ||
176 | ret = vfc_i2c_wait_for_pin(dev,VFC_I2C_ACK_CHECK); /* We wait | ||
177 | for the | ||
178 | i2c send | ||
179 | to finish | ||
180 | here but | ||
181 | Sun | ||
182 | doesn't, | ||
183 | hmm */ | ||
184 | if (ret) { | ||
185 | printk(KERN_ERR "vfc%d: VFC xmit addr timed out or no ack\n", | ||
186 | dev->instance); | ||
187 | return ret; | ||
188 | } else if (mode == VFC_I2C_READ) { | ||
189 | if ((ret = sbus_readl(&dev->regs->i2c_reg) & 0xff000000) != raddr) { | ||
190 | printk(KERN_WARNING | ||
191 | "vfc%d: returned slave address " | ||
192 | "mismatch(%x,%x)\n", | ||
193 | dev->instance, raddr, ret); | ||
194 | } | ||
195 | } | ||
196 | return 0; | ||
197 | } | ||
198 | |||
199 | static int vfc_i2c_xmit_byte(struct vfc_dev *dev,unsigned char *byte) | ||
200 | { | ||
201 | int ret; | ||
202 | u32 val = SHIFT((unsigned int)*byte); | ||
203 | |||
204 | WRITE_REG(val); | ||
205 | |||
206 | ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_ACK_CHECK); | ||
207 | switch(ret) { | ||
208 | case -ETIMEDOUT: | ||
209 | printk(KERN_ERR "vfc%d: VFC xmit byte timed out or no ack\n", | ||
210 | dev->instance); | ||
211 | break; | ||
212 | case -EIO: | ||
213 | ret = XMIT_LAST_BYTE; | ||
214 | break; | ||
215 | default: | ||
216 | break; | ||
217 | }; | ||
218 | |||
219 | return ret; | ||
220 | } | ||
221 | |||
222 | static int vfc_i2c_recv_byte(struct vfc_dev *dev, unsigned char *byte, | ||
223 | int last) | ||
224 | { | ||
225 | int ret; | ||
226 | |||
227 | if (last) { | ||
228 | WRITE_REG(NEGATIVE_ACK); | ||
229 | VFC_I2C_DEBUG_PRINTK(("vfc%d: sending negative ack\n", | ||
230 | dev->instance)); | ||
231 | } else { | ||
232 | WRITE_S1(ACK); | ||
233 | } | ||
234 | |||
235 | ret = vfc_i2c_wait_for_pin(dev, VFC_I2C_NO_ACK_CHECK); | ||
236 | if(ret) { | ||
237 | printk(KERN_ERR "vfc%d: " | ||
238 | "VFC recv byte timed out\n", | ||
239 | dev->instance); | ||
240 | } | ||
241 | *byte = (sbus_readl(&dev->regs->i2c_reg)) >> 24; | ||
242 | return ret; | ||
243 | } | ||
244 | |||
245 | int vfc_i2c_recvbuf(struct vfc_dev *dev, unsigned char addr, | ||
246 | char *buf, int count) | ||
247 | { | ||
248 | int ret, last; | ||
249 | |||
250 | if(!(count && buf && dev && dev->regs) ) | ||
251 | return -EINVAL; | ||
252 | |||
253 | if ((ret = vfc_i2c_wait_for_bus(dev))) { | ||
254 | printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); | ||
255 | return ret; | ||
256 | } | ||
257 | |||
258 | if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_READ))) { | ||
259 | WRITE_S1(SEND_I2C_STOP); | ||
260 | vfc_i2c_delay(dev); | ||
261 | return ret; | ||
262 | } | ||
263 | |||
264 | last = 0; | ||
265 | while (count--) { | ||
266 | if (!count) | ||
267 | last = 1; | ||
268 | if ((ret = vfc_i2c_recv_byte(dev, buf, last))) { | ||
269 | printk(KERN_ERR "vfc%d: " | ||
270 | "VFC error while receiving byte\n", | ||
271 | dev->instance); | ||
272 | WRITE_S1(SEND_I2C_STOP); | ||
273 | ret = -EINVAL; | ||
274 | } | ||
275 | buf++; | ||
276 | } | ||
277 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
278 | vfc_i2c_delay(dev); | ||
279 | return ret; | ||
280 | } | ||
281 | |||
282 | int vfc_i2c_sendbuf(struct vfc_dev *dev, unsigned char addr, | ||
283 | char *buf, int count) | ||
284 | { | ||
285 | int ret; | ||
286 | |||
287 | if (!(buf && dev && dev->regs)) | ||
288 | return -EINVAL; | ||
289 | |||
290 | if ((ret = vfc_i2c_wait_for_bus(dev))) { | ||
291 | printk(KERN_ERR "vfc%d: VFC I2C bus busy\n", dev->instance); | ||
292 | return ret; | ||
293 | } | ||
294 | |||
295 | if ((ret = vfc_i2c_xmit_addr(dev, addr, VFC_I2C_WRITE))) { | ||
296 | WRITE_S1(SEND_I2C_STOP); | ||
297 | vfc_i2c_delay(dev); | ||
298 | return ret; | ||
299 | } | ||
300 | |||
301 | while(count--) { | ||
302 | ret = vfc_i2c_xmit_byte(dev, buf); | ||
303 | switch(ret) { | ||
304 | case XMIT_LAST_BYTE: | ||
305 | VFC_I2C_DEBUG_PRINTK(("vfc%d: " | ||
306 | "Receiver ended transmission with " | ||
307 | " %d bytes remaining\n", | ||
308 | dev->instance, count)); | ||
309 | ret = 0; | ||
310 | goto done; | ||
311 | break; | ||
312 | case 0: | ||
313 | break; | ||
314 | default: | ||
315 | printk(KERN_ERR "vfc%d: " | ||
316 | "VFC error while sending byte\n", dev->instance); | ||
317 | break; | ||
318 | }; | ||
319 | |||
320 | buf++; | ||
321 | } | ||
322 | done: | ||
323 | WRITE_S1(SEND_I2C_STOP | ACK); | ||
324 | vfc_i2c_delay(dev); | ||
325 | return ret; | ||
326 | } | ||
327 | |||
328 | |||
329 | |||
330 | |||
331 | |||
332 | |||
333 | |||
334 | |||
335 | |||
diff --git a/drivers/sbus/char/vfc_i2c.h b/drivers/sbus/char/vfc_i2c.h deleted file mode 100644 index a2e6973209d5..000000000000 --- a/drivers/sbus/char/vfc_i2c.h +++ /dev/null | |||
@@ -1,44 +0,0 @@ | |||
1 | #ifndef _LINUX_VFC_I2C_H_ | ||
2 | #define _LINUX_VFC_I2C_H_ | ||
3 | |||
4 | /* control bits */ | ||
5 | #define PIN (0x80000000) | ||
6 | #define ESO (0x40000000) | ||
7 | #define ES1 (0x20000000) | ||
8 | #define ES2 (0x10000000) | ||
9 | #define ENI (0x08000000) | ||
10 | #define STA (0x04000000) | ||
11 | #define STO (0x02000000) | ||
12 | #define ACK (0x01000000) | ||
13 | |||
14 | /* status bits */ | ||
15 | #define STS (0x20000000) | ||
16 | #define BER (0x10000000) | ||
17 | #define LRB (0x08000000) | ||
18 | #define AAS (0x04000000) | ||
19 | #define LAB (0x02000000) | ||
20 | #define BB (0x01000000) | ||
21 | |||
22 | #define SEND_I2C_START (PIN | ESO | STA) | ||
23 | #define SEND_I2C_STOP (PIN | ESO | STO) | ||
24 | #define CLEAR_I2C_BUS (PIN | ESO | ACK) | ||
25 | #define NEGATIVE_ACK ((ESO) & ~ACK) | ||
26 | |||
27 | #define SELECT(a) (a) | ||
28 | #define S0 (PIN | ESO | ES1) | ||
29 | #define S0_OWN (PIN) | ||
30 | #define S2 (PIN | ES1) | ||
31 | #define S3 (PIN | ES2) | ||
32 | |||
33 | #define ENABLE_SERIAL (PIN | ESO) | ||
34 | #define DISABLE_SERIAL (PIN) | ||
35 | #define RESET (PIN) | ||
36 | |||
37 | #define XMIT_LAST_BYTE (1) | ||
38 | #define VFC_I2C_ACK_CHECK (1) | ||
39 | #define VFC_I2C_NO_ACK_CHECK (0) | ||
40 | |||
41 | #endif /* _LINUX_VFC_I2C_H_ */ | ||
42 | |||
43 | |||
44 | |||
diff --git a/drivers/sbus/dvma.c b/drivers/sbus/dvma.c deleted file mode 100644 index ab0d2de3324c..000000000000 --- a/drivers/sbus/dvma.c +++ /dev/null | |||
@@ -1,136 +0,0 @@ | |||
1 | /* dvma.c: Routines that are used to access DMA on the Sparc SBus. | ||
2 | * | ||
3 | * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) | ||
4 | */ | ||
5 | |||
6 | #include <linux/string.h> | ||
7 | #include <linux/kernel.h> | ||
8 | #include <linux/slab.h> | ||
9 | #include <linux/init.h> | ||
10 | #include <linux/delay.h> | ||
11 | |||
12 | #include <asm/oplib.h> | ||
13 | #include <asm/io.h> | ||
14 | #include <asm/dma.h> | ||
15 | #include <asm/sbus.h> | ||
16 | |||
17 | struct sbus_dma *dma_chain; | ||
18 | |||
19 | static void __init init_one_dvma(struct sbus_dma *dma, int num_dma) | ||
20 | { | ||
21 | printk("dma%d: ", num_dma); | ||
22 | |||
23 | dma->next = NULL; | ||
24 | dma->running = 0; /* No transfers going on as of yet */ | ||
25 | dma->allocated = 0; /* No one has allocated us yet */ | ||
26 | switch(sbus_readl(dma->regs + DMA_CSR)&DMA_DEVICE_ID) { | ||
27 | case DMA_VERS0: | ||
28 | dma->revision = dvmarev0; | ||
29 | printk("Revision 0 "); | ||
30 | break; | ||
31 | case DMA_ESCV1: | ||
32 | dma->revision = dvmaesc1; | ||
33 | printk("ESC Revision 1 "); | ||
34 | break; | ||
35 | case DMA_VERS1: | ||
36 | dma->revision = dvmarev1; | ||
37 | printk("Revision 1 "); | ||
38 | break; | ||
39 | case DMA_VERS2: | ||
40 | dma->revision = dvmarev2; | ||
41 | printk("Revision 2 "); | ||
42 | break; | ||
43 | case DMA_VERHME: | ||
44 | dma->revision = dvmahme; | ||
45 | printk("HME DVMA gate array "); | ||
46 | break; | ||
47 | case DMA_VERSPLUS: | ||
48 | dma->revision = dvmarevplus; | ||
49 | printk("Revision 1 PLUS "); | ||
50 | break; | ||
51 | default: | ||
52 | printk("unknown dma version %08x", | ||
53 | sbus_readl(dma->regs + DMA_CSR) & DMA_DEVICE_ID); | ||
54 | dma->allocated = 1; | ||
55 | break; | ||
56 | } | ||
57 | printk("\n"); | ||
58 | } | ||
59 | |||
60 | /* Probe this SBus DMA module(s) */ | ||
61 | void __init dvma_init(struct sbus_bus *sbus) | ||
62 | { | ||
63 | struct sbus_dev *this_dev; | ||
64 | struct sbus_dma *dma; | ||
65 | struct sbus_dma *dchain; | ||
66 | static int num_dma = 0; | ||
67 | |||
68 | for_each_sbusdev(this_dev, sbus) { | ||
69 | char *name = this_dev->prom_name; | ||
70 | int hme = 0; | ||
71 | |||
72 | if(!strcmp(name, "SUNW,fas")) | ||
73 | hme = 1; | ||
74 | else if(strcmp(name, "dma") && | ||
75 | strcmp(name, "ledma") && | ||
76 | strcmp(name, "espdma")) | ||
77 | continue; | ||
78 | |||
79 | /* Found one... */ | ||
80 | dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC); | ||
81 | |||
82 | dma->sdev = this_dev; | ||
83 | |||
84 | /* Put at end of dma chain */ | ||
85 | dchain = dma_chain; | ||
86 | if(dchain) { | ||
87 | while(dchain->next) | ||
88 | dchain = dchain->next; | ||
89 | dchain->next = dma; | ||
90 | } else { | ||
91 | /* We're the first in line */ | ||
92 | dma_chain = dma; | ||
93 | } | ||
94 | |||
95 | dma->regs = sbus_ioremap(&dma->sdev->resource[0], 0, | ||
96 | dma->sdev->resource[0].end - dma->sdev->resource[0].start + 1, | ||
97 | "dma"); | ||
98 | |||
99 | dma->node = dma->sdev->prom_node; | ||
100 | |||
101 | init_one_dvma(dma, num_dma++); | ||
102 | } | ||
103 | } | ||
104 | |||
105 | #ifdef CONFIG_SUN4 | ||
106 | |||
107 | #include <asm/sun4paddr.h> | ||
108 | |||
109 | void __init sun4_dvma_init(void) | ||
110 | { | ||
111 | struct sbus_dma *dma; | ||
112 | struct resource r; | ||
113 | |||
114 | if(sun4_dma_physaddr) { | ||
115 | dma = kmalloc(sizeof(struct sbus_dma), GFP_ATOMIC); | ||
116 | |||
117 | /* No SBUS */ | ||
118 | dma->sdev = NULL; | ||
119 | |||
120 | /* Only one DMA device */ | ||
121 | dma_chain = dma; | ||
122 | |||
123 | memset(&r, 0, sizeof(r)); | ||
124 | r.start = sun4_dma_physaddr; | ||
125 | dma->regs = sbus_ioremap(&r, 0, PAGE_SIZE, "dma"); | ||
126 | |||
127 | /* No prom node */ | ||
128 | dma->node = 0x0; | ||
129 | |||
130 | init_one_dvma(dma, 0); | ||
131 | } else { | ||
132 | dma_chain = NULL; | ||
133 | } | ||
134 | } | ||
135 | |||
136 | #endif | ||
diff --git a/drivers/sbus/sbus.c b/drivers/sbus/sbus.c deleted file mode 100644 index 9c129248466c..000000000000 --- a/drivers/sbus/sbus.c +++ /dev/null | |||
@@ -1,316 +0,0 @@ | |||
1 | /* sbus.c: SBus support routines. | ||
2 | * | ||
3 | * Copyright (C) 1995, 2006 David S. Miller (davem@davemloft.net) | ||
4 | */ | ||
5 | |||
6 | #include <linux/kernel.h> | ||
7 | #include <linux/slab.h> | ||
8 | #include <linux/init.h> | ||
9 | #include <linux/device.h> | ||
10 | #include <linux/of_device.h> | ||
11 | |||
12 | #include <asm/system.h> | ||
13 | #include <asm/sbus.h> | ||
14 | #include <asm/dma.h> | ||
15 | #include <asm/oplib.h> | ||
16 | #include <asm/prom.h> | ||
17 | #include <asm/bpp.h> | ||
18 | #include <asm/irq.h> | ||
19 | |||
20 | static ssize_t | ||
21 | show_sbusobppath_attr(struct device * dev, struct device_attribute * attr, char * buf) | ||
22 | { | ||
23 | struct sbus_dev *sbus; | ||
24 | |||
25 | sbus = to_sbus_device(dev); | ||
26 | |||
27 | return snprintf (buf, PAGE_SIZE, "%s\n", sbus->ofdev.node->full_name); | ||
28 | } | ||
29 | |||
30 | static DEVICE_ATTR(obppath, S_IRUSR | S_IRGRP | S_IROTH, show_sbusobppath_attr, NULL); | ||
31 | |||
32 | struct sbus_bus *sbus_root; | ||
33 | |||
34 | static void __init fill_sbus_device(struct device_node *dp, struct sbus_dev *sdev) | ||
35 | { | ||
36 | struct dev_archdata *sd; | ||
37 | unsigned long base; | ||
38 | const void *pval; | ||
39 | int len, err; | ||
40 | |||
41 | sdev->prom_node = dp->node; | ||
42 | strcpy(sdev->prom_name, dp->name); | ||
43 | |||
44 | pval = of_get_property(dp, "reg", &len); | ||
45 | sdev->num_registers = 0; | ||
46 | if (pval) { | ||
47 | memcpy(sdev->reg_addrs, pval, len); | ||
48 | |||
49 | sdev->num_registers = | ||
50 | len / sizeof(struct linux_prom_registers); | ||
51 | |||
52 | base = (unsigned long) sdev->reg_addrs[0].phys_addr; | ||
53 | |||
54 | /* Compute the slot number. */ | ||
55 | if (base >= SUN_SBUS_BVADDR && sparc_cpu_model == sun4m) | ||
56 | sdev->slot = sbus_dev_slot(base); | ||
57 | else | ||
58 | sdev->slot = sdev->reg_addrs[0].which_io; | ||
59 | } | ||
60 | |||
61 | pval = of_get_property(dp, "ranges", &len); | ||
62 | sdev->num_device_ranges = 0; | ||
63 | if (pval) { | ||
64 | memcpy(sdev->device_ranges, pval, len); | ||
65 | sdev->num_device_ranges = | ||
66 | len / sizeof(struct linux_prom_ranges); | ||
67 | } | ||
68 | |||
69 | sbus_fill_device_irq(sdev); | ||
70 | |||
71 | sd = &sdev->ofdev.dev.archdata; | ||
72 | sd->prom_node = dp; | ||
73 | sd->op = &sdev->ofdev; | ||
74 | |||
75 | sdev->ofdev.node = dp; | ||
76 | if (sdev->parent) | ||
77 | sdev->ofdev.dev.parent = &sdev->parent->ofdev.dev; | ||
78 | else | ||
79 | sdev->ofdev.dev.parent = &sdev->bus->ofdev.dev; | ||
80 | sdev->ofdev.dev.bus = &sbus_bus_type; | ||
81 | dev_set_name(&sdev->ofdev.dev, "sbus[%08x]", dp->node); | ||
82 | |||
83 | if (of_device_register(&sdev->ofdev) != 0) | ||
84 | printk(KERN_DEBUG "sbus: device registration error for %s!\n", | ||
85 | dp->path_component_name); | ||
86 | |||
87 | /* WE HAVE BEEN INVADED BY ALIENS! */ | ||
88 | err = sysfs_create_file(&sdev->ofdev.dev.kobj, &dev_attr_obppath.attr); | ||
89 | } | ||
90 | |||
91 | static void __init sbus_bus_ranges_init(struct device_node *dp, struct sbus_bus *sbus) | ||
92 | { | ||
93 | const void *pval; | ||
94 | int len; | ||
95 | |||
96 | pval = of_get_property(dp, "ranges", &len); | ||
97 | sbus->num_sbus_ranges = 0; | ||
98 | if (pval) { | ||
99 | memcpy(sbus->sbus_ranges, pval, len); | ||
100 | sbus->num_sbus_ranges = | ||
101 | len / sizeof(struct linux_prom_ranges); | ||
102 | |||
103 | sbus_arch_bus_ranges_init(dp->parent, sbus); | ||
104 | } | ||
105 | } | ||
106 | |||
107 | static void __init __apply_ranges_to_regs(struct linux_prom_ranges *ranges, | ||
108 | int num_ranges, | ||
109 | struct linux_prom_registers *regs, | ||
110 | int num_regs) | ||
111 | { | ||
112 | if (num_ranges) { | ||
113 | int regnum; | ||
114 | |||
115 | for (regnum = 0; regnum < num_regs; regnum++) { | ||
116 | int rngnum; | ||
117 | |||
118 | for (rngnum = 0; rngnum < num_ranges; rngnum++) { | ||
119 | if (regs[regnum].which_io == ranges[rngnum].ot_child_space) | ||
120 | break; | ||
121 | } | ||
122 | if (rngnum == num_ranges) { | ||
123 | /* We used to flag this as an error. Actually | ||
124 | * some devices do not report the regs as we expect. | ||
125 | * For example, see SUNW,pln device. In that case | ||
126 | * the reg property is in a format internal to that | ||
127 | * node, ie. it is not in the SBUS register space | ||
128 | * per se. -DaveM | ||
129 | */ | ||
130 | return; | ||
131 | } | ||
132 | regs[regnum].which_io = ranges[rngnum].ot_parent_space; | ||
133 | regs[regnum].phys_addr -= ranges[rngnum].ot_child_base; | ||
134 | regs[regnum].phys_addr += ranges[rngnum].ot_parent_base; | ||
135 | } | ||
136 | } | ||
137 | } | ||
138 | |||
139 | static void __init __fixup_regs_sdev(struct sbus_dev *sdev) | ||
140 | { | ||
141 | if (sdev->num_registers != 0) { | ||
142 | struct sbus_dev *parent = sdev->parent; | ||
143 | int i; | ||
144 | |||
145 | while (parent != NULL) { | ||
146 | __apply_ranges_to_regs(parent->device_ranges, | ||
147 | parent->num_device_ranges, | ||
148 | sdev->reg_addrs, | ||
149 | sdev->num_registers); | ||
150 | |||
151 | parent = parent->parent; | ||
152 | } | ||
153 | |||
154 | __apply_ranges_to_regs(sdev->bus->sbus_ranges, | ||
155 | sdev->bus->num_sbus_ranges, | ||
156 | sdev->reg_addrs, | ||
157 | sdev->num_registers); | ||
158 | |||
159 | for (i = 0; i < sdev->num_registers; i++) { | ||
160 | struct resource *res = &sdev->resource[i]; | ||
161 | |||
162 | res->start = sdev->reg_addrs[i].phys_addr; | ||
163 | res->end = (res->start + | ||
164 | (unsigned long)sdev->reg_addrs[i].reg_size - 1UL); | ||
165 | res->flags = IORESOURCE_IO | | ||
166 | (sdev->reg_addrs[i].which_io & 0xff); | ||
167 | } | ||
168 | } | ||
169 | } | ||
170 | |||
171 | static void __init sbus_fixup_all_regs(struct sbus_dev *first_sdev) | ||
172 | { | ||
173 | struct sbus_dev *sdev; | ||
174 | |||
175 | for (sdev = first_sdev; sdev; sdev = sdev->next) { | ||
176 | if (sdev->child) | ||
177 | sbus_fixup_all_regs(sdev->child); | ||
178 | __fixup_regs_sdev(sdev); | ||
179 | } | ||
180 | } | ||
181 | |||
182 | /* We preserve the "probe order" of these bus and device lists to give | ||
183 | * the same ordering as the old code. | ||
184 | */ | ||
185 | static void __init sbus_insert(struct sbus_bus *sbus, struct sbus_bus **root) | ||
186 | { | ||
187 | while (*root) | ||
188 | root = &(*root)->next; | ||
189 | *root = sbus; | ||
190 | sbus->next = NULL; | ||
191 | } | ||
192 | |||
193 | static void __init sdev_insert(struct sbus_dev *sdev, struct sbus_dev **root) | ||
194 | { | ||
195 | while (*root) | ||
196 | root = &(*root)->next; | ||
197 | *root = sdev; | ||
198 | sdev->next = NULL; | ||
199 | } | ||
200 | |||
201 | static void __init walk_children(struct device_node *dp, struct sbus_dev *parent, struct sbus_bus *sbus) | ||
202 | { | ||
203 | dp = dp->child; | ||
204 | while (dp) { | ||
205 | struct sbus_dev *sdev; | ||
206 | |||
207 | sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); | ||
208 | if (sdev) { | ||
209 | sdev_insert(sdev, &parent->child); | ||
210 | |||
211 | sdev->bus = sbus; | ||
212 | sdev->parent = parent; | ||
213 | sdev->ofdev.dev.archdata.iommu = | ||
214 | sbus->ofdev.dev.archdata.iommu; | ||
215 | sdev->ofdev.dev.archdata.stc = | ||
216 | sbus->ofdev.dev.archdata.stc; | ||
217 | |||
218 | fill_sbus_device(dp, sdev); | ||
219 | |||
220 | walk_children(dp, sdev, sbus); | ||
221 | } | ||
222 | dp = dp->sibling; | ||
223 | } | ||
224 | } | ||
225 | |||
226 | static void __init build_one_sbus(struct device_node *dp, int num_sbus) | ||
227 | { | ||
228 | struct sbus_bus *sbus; | ||
229 | unsigned int sbus_clock; | ||
230 | struct device_node *dev_dp; | ||
231 | |||
232 | sbus = kzalloc(sizeof(struct sbus_bus), GFP_ATOMIC); | ||
233 | if (!sbus) | ||
234 | return; | ||
235 | |||
236 | sbus_insert(sbus, &sbus_root); | ||
237 | sbus->prom_node = dp->node; | ||
238 | |||
239 | sbus_setup_iommu(sbus, dp); | ||
240 | |||
241 | printk("sbus%d: ", num_sbus); | ||
242 | |||
243 | sbus_clock = of_getintprop_default(dp, "clock-frequency", | ||
244 | (25*1000*1000)); | ||
245 | sbus->clock_freq = sbus_clock; | ||
246 | |||
247 | printk("Clock %d.%d MHz\n", (int) ((sbus_clock/1000)/1000), | ||
248 | (int) (((sbus_clock/1000)%1000 != 0) ? | ||
249 | (((sbus_clock/1000)%1000) + 1000) : 0)); | ||
250 | |||
251 | strcpy(sbus->prom_name, dp->name); | ||
252 | |||
253 | sbus_setup_arch_props(sbus, dp); | ||
254 | |||
255 | sbus_bus_ranges_init(dp, sbus); | ||
256 | |||
257 | sbus->ofdev.node = dp; | ||
258 | sbus->ofdev.dev.parent = NULL; | ||
259 | sbus->ofdev.dev.bus = &sbus_bus_type; | ||
260 | dev_set_name(&sbus->ofdev.dev, "sbus%d", num_sbus); | ||
261 | |||
262 | if (of_device_register(&sbus->ofdev) != 0) | ||
263 | printk(KERN_DEBUG "sbus: device registration error for %s!\n", | ||
264 | dev_name(&sbus->ofdev.dev)); | ||
265 | |||
266 | dev_dp = dp->child; | ||
267 | while (dev_dp) { | ||
268 | struct sbus_dev *sdev; | ||
269 | |||
270 | sdev = kzalloc(sizeof(struct sbus_dev), GFP_ATOMIC); | ||
271 | if (sdev) { | ||
272 | sdev_insert(sdev, &sbus->devices); | ||
273 | |||
274 | sdev->bus = sbus; | ||
275 | sdev->parent = NULL; | ||
276 | sdev->ofdev.dev.archdata.iommu = | ||
277 | sbus->ofdev.dev.archdata.iommu; | ||
278 | sdev->ofdev.dev.archdata.stc = | ||
279 | sbus->ofdev.dev.archdata.stc; | ||
280 | |||
281 | fill_sbus_device(dev_dp, sdev); | ||
282 | |||
283 | walk_children(dev_dp, sdev, sbus); | ||
284 | } | ||
285 | dev_dp = dev_dp->sibling; | ||
286 | } | ||
287 | |||
288 | sbus_fixup_all_regs(sbus->devices); | ||
289 | |||
290 | dvma_init(sbus); | ||
291 | } | ||
292 | |||
293 | static int __init sbus_init(void) | ||
294 | { | ||
295 | struct device_node *dp; | ||
296 | const char *sbus_name = "sbus"; | ||
297 | int num_sbus = 0; | ||
298 | |||
299 | if (sbus_arch_preinit()) | ||
300 | return 0; | ||
301 | |||
302 | if (sparc_cpu_model == sun4d) | ||
303 | sbus_name = "sbi"; | ||
304 | |||
305 | for_each_node_by_name(dp, sbus_name) { | ||
306 | build_one_sbus(dp, num_sbus); | ||
307 | num_sbus++; | ||
308 | |||
309 | } | ||
310 | |||
311 | sbus_arch_postinit(); | ||
312 | |||
313 | return 0; | ||
314 | } | ||
315 | |||
316 | subsys_initcall(sbus_init); | ||
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h index bb43a1388188..28e22acf87ea 100644 --- a/drivers/scsi/esp_scsi.h +++ b/drivers/scsi/esp_scsi.h | |||
@@ -521,7 +521,8 @@ struct esp { | |||
521 | 521 | ||
522 | struct completion *eh_reset; | 522 | struct completion *eh_reset; |
523 | 523 | ||
524 | struct sbus_dma *dma; | 524 | void *dma; |
525 | int dmarev; | ||
525 | }; | 526 | }; |
526 | 527 | ||
527 | /* A front-end driver for the ESP chip should do the following in | 528 | /* A front-end driver for the ESP chip should do the following in |
diff --git a/drivers/scsi/qlogicpti.c b/drivers/scsi/qlogicpti.c index 905350896725..69d6ad862b60 100644 --- a/drivers/scsi/qlogicpti.c +++ b/drivers/scsi/qlogicpti.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* qlogicpti.c: Performance Technologies QlogicISP sbus card driver. | 1 | /* qlogicpti.c: Performance Technologies QlogicISP sbus card driver. |
2 | * | 2 | * |
3 | * Copyright (C) 1996, 2006 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 1996, 2006, 2008 David S. Miller (davem@davemloft.net) |
4 | * | 4 | * |
5 | * A lot of this driver was directly stolen from Erik H. Moe's PCI | 5 | * A lot of this driver was directly stolen from Erik H. Moe's PCI |
6 | * Qlogic ISP driver. Mucho kudos to him for this code. | 6 | * Qlogic ISP driver. Mucho kudos to him for this code. |
@@ -25,12 +25,14 @@ | |||
25 | #include <linux/interrupt.h> | 25 | #include <linux/interrupt.h> |
26 | #include <linux/module.h> | 26 | #include <linux/module.h> |
27 | #include <linux/jiffies.h> | 27 | #include <linux/jiffies.h> |
28 | #include <linux/dma-mapping.h> | ||
29 | #include <linux/of.h> | ||
30 | #include <linux/of_device.h> | ||
28 | 31 | ||
29 | #include <asm/byteorder.h> | 32 | #include <asm/byteorder.h> |
30 | 33 | ||
31 | #include "qlogicpti.h" | 34 | #include "qlogicpti.h" |
32 | 35 | ||
33 | #include <asm/sbus.h> | ||
34 | #include <asm/dma.h> | 36 | #include <asm/dma.h> |
35 | #include <asm/system.h> | 37 | #include <asm/system.h> |
36 | #include <asm/ptrace.h> | 38 | #include <asm/ptrace.h> |
@@ -157,7 +159,7 @@ static inline void set_sbus_cfg1(struct qlogicpti *qpti) | |||
157 | * is a nop and the chip ends up using the smallest burst | 159 | * is a nop and the chip ends up using the smallest burst |
158 | * size. -DaveM | 160 | * size. -DaveM |
159 | */ | 161 | */ |
160 | if (sbus_can_burst64(qpti->sdev) && (bursts & DMA_BURST64)) { | 162 | if (sbus_can_burst64() && (bursts & DMA_BURST64)) { |
161 | val = (SBUS_CFG1_BENAB | SBUS_CFG1_B64); | 163 | val = (SBUS_CFG1_BENAB | SBUS_CFG1_B64); |
162 | } else | 164 | } else |
163 | #endif | 165 | #endif |
@@ -684,19 +686,19 @@ static void __devexit qpti_chain_del(struct qlogicpti *qpti) | |||
684 | 686 | ||
685 | static int __devinit qpti_map_regs(struct qlogicpti *qpti) | 687 | static int __devinit qpti_map_regs(struct qlogicpti *qpti) |
686 | { | 688 | { |
687 | struct sbus_dev *sdev = qpti->sdev; | 689 | struct of_device *op = qpti->op; |
688 | 690 | ||
689 | qpti->qregs = sbus_ioremap(&sdev->resource[0], 0, | 691 | qpti->qregs = of_ioremap(&op->resource[0], 0, |
690 | sdev->reg_addrs[0].reg_size, | 692 | resource_size(&op->resource[0]), |
691 | "PTI Qlogic/ISP"); | 693 | "PTI Qlogic/ISP"); |
692 | if (!qpti->qregs) { | 694 | if (!qpti->qregs) { |
693 | printk("PTI: Qlogic/ISP registers are unmappable\n"); | 695 | printk("PTI: Qlogic/ISP registers are unmappable\n"); |
694 | return -1; | 696 | return -1; |
695 | } | 697 | } |
696 | if (qpti->is_pti) { | 698 | if (qpti->is_pti) { |
697 | qpti->sreg = sbus_ioremap(&sdev->resource[0], (16 * 4096), | 699 | qpti->sreg = of_ioremap(&op->resource[0], (16 * 4096), |
698 | sizeof(unsigned char), | 700 | sizeof(unsigned char), |
699 | "PTI Qlogic/ISP statreg"); | 701 | "PTI Qlogic/ISP statreg"); |
700 | if (!qpti->sreg) { | 702 | if (!qpti->sreg) { |
701 | printk("PTI: Qlogic/ISP status register is unmappable\n"); | 703 | printk("PTI: Qlogic/ISP status register is unmappable\n"); |
702 | return -1; | 704 | return -1; |
@@ -707,9 +709,9 @@ static int __devinit qpti_map_regs(struct qlogicpti *qpti) | |||
707 | 709 | ||
708 | static int __devinit qpti_register_irq(struct qlogicpti *qpti) | 710 | static int __devinit qpti_register_irq(struct qlogicpti *qpti) |
709 | { | 711 | { |
710 | struct sbus_dev *sdev = qpti->sdev; | 712 | struct of_device *op = qpti->op; |
711 | 713 | ||
712 | qpti->qhost->irq = qpti->irq = sdev->irqs[0]; | 714 | qpti->qhost->irq = qpti->irq = op->irqs[0]; |
713 | 715 | ||
714 | /* We used to try various overly-clever things to | 716 | /* We used to try various overly-clever things to |
715 | * reduce the interrupt processing overhead on | 717 | * reduce the interrupt processing overhead on |
@@ -732,17 +734,19 @@ fail: | |||
732 | 734 | ||
733 | static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) | 735 | static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) |
734 | { | 736 | { |
735 | qpti->scsi_id = prom_getintdefault(qpti->prom_node, | 737 | struct of_device *op = qpti->op; |
736 | "initiator-id", | 738 | struct device_node *dp; |
737 | -1); | 739 | |
740 | dp = op->node; | ||
741 | |||
742 | qpti->scsi_id = of_getintprop_default(dp, "initiator-id", -1); | ||
738 | if (qpti->scsi_id == -1) | 743 | if (qpti->scsi_id == -1) |
739 | qpti->scsi_id = prom_getintdefault(qpti->prom_node, | 744 | qpti->scsi_id = of_getintprop_default(dp, "scsi-initiator-id", |
740 | "scsi-initiator-id", | 745 | -1); |
741 | -1); | ||
742 | if (qpti->scsi_id == -1) | 746 | if (qpti->scsi_id == -1) |
743 | qpti->scsi_id = | 747 | qpti->scsi_id = |
744 | prom_getintdefault(qpti->sdev->bus->prom_node, | 748 | of_getintprop_default(dp->parent, |
745 | "scsi-initiator-id", 7); | 749 | "scsi-initiator-id", 7); |
746 | qpti->qhost->this_id = qpti->scsi_id; | 750 | qpti->qhost->this_id = qpti->scsi_id; |
747 | qpti->qhost->max_sectors = 64; | 751 | qpti->qhost->max_sectors = 64; |
748 | 752 | ||
@@ -751,12 +755,11 @@ static void __devinit qpti_get_scsi_id(struct qlogicpti *qpti) | |||
751 | 755 | ||
752 | static void qpti_get_bursts(struct qlogicpti *qpti) | 756 | static void qpti_get_bursts(struct qlogicpti *qpti) |
753 | { | 757 | { |
754 | struct sbus_dev *sdev = qpti->sdev; | 758 | struct of_device *op = qpti->op; |
755 | u8 bursts, bmask; | 759 | u8 bursts, bmask; |
756 | 760 | ||
757 | bursts = prom_getintdefault(qpti->prom_node, "burst-sizes", 0xff); | 761 | bursts = of_getintprop_default(op->node, "burst-sizes", 0xff); |
758 | bmask = prom_getintdefault(sdev->bus->prom_node, | 762 | bmask = of_getintprop_default(op->node->parent, "burst-sizes", 0xff); |
759 | "burst-sizes", 0xff); | ||
760 | if (bmask != 0xff) | 763 | if (bmask != 0xff) |
761 | bursts &= bmask; | 764 | bursts &= bmask; |
762 | if (bursts == 0xff || | 765 | if (bursts == 0xff || |
@@ -785,25 +788,25 @@ static void qpti_get_clock(struct qlogicpti *qpti) | |||
785 | */ | 788 | */ |
786 | static int __devinit qpti_map_queues(struct qlogicpti *qpti) | 789 | static int __devinit qpti_map_queues(struct qlogicpti *qpti) |
787 | { | 790 | { |
788 | struct sbus_dev *sdev = qpti->sdev; | 791 | struct of_device *op = qpti->op; |
789 | 792 | ||
790 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) | 793 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) |
791 | qpti->res_cpu = sbus_alloc_consistent(sdev, | 794 | qpti->res_cpu = dma_alloc_coherent(&op->dev, |
792 | QSIZE(RES_QUEUE_LEN), | 795 | QSIZE(RES_QUEUE_LEN), |
793 | &qpti->res_dvma); | 796 | &qpti->res_dvma, GFP_ATOMIC); |
794 | if (qpti->res_cpu == NULL || | 797 | if (qpti->res_cpu == NULL || |
795 | qpti->res_dvma == 0) { | 798 | qpti->res_dvma == 0) { |
796 | printk("QPTI: Cannot map response queue.\n"); | 799 | printk("QPTI: Cannot map response queue.\n"); |
797 | return -1; | 800 | return -1; |
798 | } | 801 | } |
799 | 802 | ||
800 | qpti->req_cpu = sbus_alloc_consistent(sdev, | 803 | qpti->req_cpu = dma_alloc_coherent(&op->dev, |
801 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), | 804 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), |
802 | &qpti->req_dvma); | 805 | &qpti->req_dvma, GFP_ATOMIC); |
803 | if (qpti->req_cpu == NULL || | 806 | if (qpti->req_cpu == NULL || |
804 | qpti->req_dvma == 0) { | 807 | qpti->req_dvma == 0) { |
805 | sbus_free_consistent(sdev, QSIZE(RES_QUEUE_LEN), | 808 | dma_free_coherent(&op->dev, QSIZE(RES_QUEUE_LEN), |
806 | qpti->res_cpu, qpti->res_dvma); | 809 | qpti->res_cpu, qpti->res_dvma); |
807 | printk("QPTI: Cannot map request queue.\n"); | 810 | printk("QPTI: Cannot map request queue.\n"); |
808 | return -1; | 811 | return -1; |
809 | } | 812 | } |
@@ -875,8 +878,9 @@ static inline int load_cmd(struct scsi_cmnd *Cmnd, struct Command_Entry *cmd, | |||
875 | int sg_count; | 878 | int sg_count; |
876 | 879 | ||
877 | sg = scsi_sglist(Cmnd); | 880 | sg = scsi_sglist(Cmnd); |
878 | sg_count = sbus_map_sg(qpti->sdev, sg, scsi_sg_count(Cmnd), | 881 | sg_count = dma_map_sg(&qpti->op->dev, sg, |
879 | Cmnd->sc_data_direction); | 882 | scsi_sg_count(Cmnd), |
883 | Cmnd->sc_data_direction); | ||
880 | 884 | ||
881 | ds = cmd->dataseg; | 885 | ds = cmd->dataseg; |
882 | cmd->segment_cnt = sg_count; | 886 | cmd->segment_cnt = sg_count; |
@@ -1152,9 +1156,9 @@ static struct scsi_cmnd *qlogicpti_intr_handler(struct qlogicpti *qpti) | |||
1152 | Cmnd->result = DID_ERROR << 16; | 1156 | Cmnd->result = DID_ERROR << 16; |
1153 | 1157 | ||
1154 | if (scsi_bufflen(Cmnd)) | 1158 | if (scsi_bufflen(Cmnd)) |
1155 | sbus_unmap_sg(qpti->sdev, | 1159 | dma_unmap_sg(&qpti->op->dev, |
1156 | scsi_sglist(Cmnd), scsi_sg_count(Cmnd), | 1160 | scsi_sglist(Cmnd), scsi_sg_count(Cmnd), |
1157 | Cmnd->sc_data_direction); | 1161 | Cmnd->sc_data_direction); |
1158 | 1162 | ||
1159 | qpti->cmd_count[Cmnd->device->id]--; | 1163 | qpti->cmd_count[Cmnd->device->id]--; |
1160 | sbus_writew(out_ptr, qpti->qregs + MBOX5); | 1164 | sbus_writew(out_ptr, qpti->qregs + MBOX5); |
@@ -1268,34 +1272,32 @@ static struct scsi_host_template qpti_template = { | |||
1268 | .use_clustering = ENABLE_CLUSTERING, | 1272 | .use_clustering = ENABLE_CLUSTERING, |
1269 | }; | 1273 | }; |
1270 | 1274 | ||
1271 | static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 1275 | static int __devinit qpti_sbus_probe(struct of_device *op, const struct of_device_id *match) |
1272 | { | 1276 | { |
1273 | static int nqptis; | ||
1274 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
1275 | struct device_node *dp = dev->node; | ||
1276 | struct scsi_host_template *tpnt = match->data; | 1277 | struct scsi_host_template *tpnt = match->data; |
1278 | struct device_node *dp = op->node; | ||
1277 | struct Scsi_Host *host; | 1279 | struct Scsi_Host *host; |
1278 | struct qlogicpti *qpti; | 1280 | struct qlogicpti *qpti; |
1281 | static int nqptis; | ||
1279 | const char *fcode; | 1282 | const char *fcode; |
1280 | 1283 | ||
1281 | /* Sometimes Antares cards come up not completely | 1284 | /* Sometimes Antares cards come up not completely |
1282 | * setup, and we get a report of a zero IRQ. | 1285 | * setup, and we get a report of a zero IRQ. |
1283 | */ | 1286 | */ |
1284 | if (sdev->irqs[0] == 0) | 1287 | if (op->irqs[0] == 0) |
1285 | return -ENODEV; | 1288 | return -ENODEV; |
1286 | 1289 | ||
1287 | host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); | 1290 | host = scsi_host_alloc(tpnt, sizeof(struct qlogicpti)); |
1288 | if (!host) | 1291 | if (!host) |
1289 | return -ENOMEM; | 1292 | return -ENOMEM; |
1290 | 1293 | ||
1291 | qpti = (struct qlogicpti *) host->hostdata; | 1294 | qpti = shost_priv(host); |
1292 | 1295 | ||
1293 | host->max_id = MAX_TARGETS; | 1296 | host->max_id = MAX_TARGETS; |
1294 | qpti->qhost = host; | 1297 | qpti->qhost = host; |
1295 | qpti->sdev = sdev; | 1298 | qpti->op = op; |
1296 | qpti->qpti_id = nqptis; | 1299 | qpti->qpti_id = nqptis; |
1297 | qpti->prom_node = sdev->prom_node; | 1300 | strcpy(qpti->prom_name, op->node->name); |
1298 | strcpy(qpti->prom_name, sdev->ofdev.node->name); | ||
1299 | qpti->is_pti = strcmp(qpti->prom_name, "QLGC,isp"); | 1301 | qpti->is_pti = strcmp(qpti->prom_name, "QLGC,isp"); |
1300 | 1302 | ||
1301 | if (qpti_map_regs(qpti) < 0) | 1303 | if (qpti_map_regs(qpti) < 0) |
@@ -1341,12 +1343,12 @@ static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_devi | |||
1341 | (qpti->ultra ? "Ultra" : "Fast"), | 1343 | (qpti->ultra ? "Ultra" : "Fast"), |
1342 | (qpti->differential ? "differential" : "single ended")); | 1344 | (qpti->differential ? "differential" : "single ended")); |
1343 | 1345 | ||
1344 | if (scsi_add_host(host, &dev->dev)) { | 1346 | if (scsi_add_host(host, &op->dev)) { |
1345 | printk("qlogicpti%d: Failed scsi_add_host\n", qpti->qpti_id); | 1347 | printk("qlogicpti%d: Failed scsi_add_host\n", qpti->qpti_id); |
1346 | goto fail_unmap_queues; | 1348 | goto fail_unmap_queues; |
1347 | } | 1349 | } |
1348 | 1350 | ||
1349 | dev_set_drvdata(&sdev->ofdev.dev, qpti); | 1351 | dev_set_drvdata(&op->dev, qpti); |
1350 | 1352 | ||
1351 | qpti_chain_add(qpti); | 1353 | qpti_chain_add(qpti); |
1352 | 1354 | ||
@@ -1357,19 +1359,20 @@ static int __devinit qpti_sbus_probe(struct of_device *dev, const struct of_devi | |||
1357 | 1359 | ||
1358 | fail_unmap_queues: | 1360 | fail_unmap_queues: |
1359 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) | 1361 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) |
1360 | sbus_free_consistent(qpti->sdev, | 1362 | dma_free_coherent(&op->dev, |
1361 | QSIZE(RES_QUEUE_LEN), | 1363 | QSIZE(RES_QUEUE_LEN), |
1362 | qpti->res_cpu, qpti->res_dvma); | 1364 | qpti->res_cpu, qpti->res_dvma); |
1363 | sbus_free_consistent(qpti->sdev, | 1365 | dma_free_coherent(&op->dev, |
1364 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), | 1366 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), |
1365 | qpti->req_cpu, qpti->req_dvma); | 1367 | qpti->req_cpu, qpti->req_dvma); |
1366 | #undef QSIZE | 1368 | #undef QSIZE |
1367 | 1369 | ||
1368 | fail_unmap_regs: | 1370 | fail_unmap_regs: |
1369 | sbus_iounmap(qpti->qregs, | 1371 | of_iounmap(&op->resource[0], qpti->qregs, |
1370 | qpti->sdev->reg_addrs[0].reg_size); | 1372 | resource_size(&op->resource[0])); |
1371 | if (qpti->is_pti) | 1373 | if (qpti->is_pti) |
1372 | sbus_iounmap(qpti->sreg, sizeof(unsigned char)); | 1374 | of_iounmap(&op->resource[0], qpti->sreg, |
1375 | sizeof(unsigned char)); | ||
1373 | 1376 | ||
1374 | fail_free_irq: | 1377 | fail_free_irq: |
1375 | free_irq(qpti->irq, qpti); | 1378 | free_irq(qpti->irq, qpti); |
@@ -1380,9 +1383,9 @@ fail_unlink: | |||
1380 | return -ENODEV; | 1383 | return -ENODEV; |
1381 | } | 1384 | } |
1382 | 1385 | ||
1383 | static int __devexit qpti_sbus_remove(struct of_device *dev) | 1386 | static int __devexit qpti_sbus_remove(struct of_device *op) |
1384 | { | 1387 | { |
1385 | struct qlogicpti *qpti = dev_get_drvdata(&dev->dev); | 1388 | struct qlogicpti *qpti = dev_get_drvdata(&op->dev); |
1386 | 1389 | ||
1387 | qpti_chain_del(qpti); | 1390 | qpti_chain_del(qpti); |
1388 | 1391 | ||
@@ -1395,24 +1398,25 @@ static int __devexit qpti_sbus_remove(struct of_device *dev) | |||
1395 | free_irq(qpti->irq, qpti); | 1398 | free_irq(qpti->irq, qpti); |
1396 | 1399 | ||
1397 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) | 1400 | #define QSIZE(entries) (((entries) + 1) * QUEUE_ENTRY_LEN) |
1398 | sbus_free_consistent(qpti->sdev, | 1401 | dma_free_coherent(&op->dev, |
1399 | QSIZE(RES_QUEUE_LEN), | 1402 | QSIZE(RES_QUEUE_LEN), |
1400 | qpti->res_cpu, qpti->res_dvma); | 1403 | qpti->res_cpu, qpti->res_dvma); |
1401 | sbus_free_consistent(qpti->sdev, | 1404 | dma_free_coherent(&op->dev, |
1402 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), | 1405 | QSIZE(QLOGICPTI_REQ_QUEUE_LEN), |
1403 | qpti->req_cpu, qpti->req_dvma); | 1406 | qpti->req_cpu, qpti->req_dvma); |
1404 | #undef QSIZE | 1407 | #undef QSIZE |
1405 | 1408 | ||
1406 | sbus_iounmap(qpti->qregs, qpti->sdev->reg_addrs[0].reg_size); | 1409 | of_iounmap(&op->resource[0], qpti->qregs, |
1410 | resource_size(&op->resource[0])); | ||
1407 | if (qpti->is_pti) | 1411 | if (qpti->is_pti) |
1408 | sbus_iounmap(qpti->sreg, sizeof(unsigned char)); | 1412 | of_iounmap(&op->resource[0], qpti->sreg, sizeof(unsigned char)); |
1409 | 1413 | ||
1410 | scsi_host_put(qpti->qhost); | 1414 | scsi_host_put(qpti->qhost); |
1411 | 1415 | ||
1412 | return 0; | 1416 | return 0; |
1413 | } | 1417 | } |
1414 | 1418 | ||
1415 | static struct of_device_id qpti_match[] = { | 1419 | static const struct of_device_id qpti_match[] = { |
1416 | { | 1420 | { |
1417 | .name = "ptisp", | 1421 | .name = "ptisp", |
1418 | .data = &qpti_template, | 1422 | .data = &qpti_template, |
@@ -1442,7 +1446,7 @@ static struct of_platform_driver qpti_sbus_driver = { | |||
1442 | 1446 | ||
1443 | static int __init qpti_init(void) | 1447 | static int __init qpti_init(void) |
1444 | { | 1448 | { |
1445 | return of_register_driver(&qpti_sbus_driver, &sbus_bus_type); | 1449 | return of_register_driver(&qpti_sbus_driver, &of_bus_type); |
1446 | } | 1450 | } |
1447 | 1451 | ||
1448 | static void __exit qpti_exit(void) | 1452 | static void __exit qpti_exit(void) |
@@ -1453,7 +1457,7 @@ static void __exit qpti_exit(void) | |||
1453 | MODULE_DESCRIPTION("QlogicISP SBUS driver"); | 1457 | MODULE_DESCRIPTION("QlogicISP SBUS driver"); |
1454 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); | 1458 | MODULE_AUTHOR("David S. Miller (davem@davemloft.net)"); |
1455 | MODULE_LICENSE("GPL"); | 1459 | MODULE_LICENSE("GPL"); |
1456 | MODULE_VERSION("2.0"); | 1460 | MODULE_VERSION("2.1"); |
1457 | 1461 | ||
1458 | module_init(qpti_init); | 1462 | module_init(qpti_init); |
1459 | module_exit(qpti_exit); | 1463 | module_exit(qpti_exit); |
diff --git a/drivers/scsi/qlogicpti.h b/drivers/scsi/qlogicpti.h index ef6da2df584b..9c053bbaa877 100644 --- a/drivers/scsi/qlogicpti.h +++ b/drivers/scsi/qlogicpti.h | |||
@@ -342,7 +342,7 @@ struct qlogicpti { | |||
342 | u_int req_in_ptr; /* index of next request slot */ | 342 | u_int req_in_ptr; /* index of next request slot */ |
343 | u_int res_out_ptr; /* index of next result slot */ | 343 | u_int res_out_ptr; /* index of next result slot */ |
344 | long send_marker; /* must we send a marker? */ | 344 | long send_marker; /* must we send a marker? */ |
345 | struct sbus_dev *sdev; | 345 | struct of_device *op; |
346 | unsigned long __pad; | 346 | unsigned long __pad; |
347 | 347 | ||
348 | int cmd_count[MAX_TARGETS]; | 348 | int cmd_count[MAX_TARGETS]; |
diff --git a/drivers/scsi/sun_esp.c b/drivers/scsi/sun_esp.c index f9cf70151366..3d73aad4bc82 100644 --- a/drivers/scsi/sun_esp.c +++ b/drivers/scsi/sun_esp.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* sun_esp.c: ESP front-end for Sparc SBUS systems. | 1 | /* sun_esp.c: ESP front-end for Sparc SBUS systems. |
2 | * | 2 | * |
3 | * Copyright (C) 2007 David S. Miller (davem@davemloft.net) | 3 | * Copyright (C) 2007, 2008 David S. Miller (davem@davemloft.net) |
4 | */ | 4 | */ |
5 | 5 | ||
6 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
@@ -9,60 +9,70 @@ | |||
9 | #include <linux/module.h> | 9 | #include <linux/module.h> |
10 | #include <linux/mm.h> | 10 | #include <linux/mm.h> |
11 | #include <linux/init.h> | 11 | #include <linux/init.h> |
12 | #include <linux/dma-mapping.h> | ||
13 | #include <linux/of.h> | ||
14 | #include <linux/of_device.h> | ||
12 | 15 | ||
13 | #include <asm/irq.h> | 16 | #include <asm/irq.h> |
14 | #include <asm/io.h> | 17 | #include <asm/io.h> |
15 | #include <asm/dma.h> | 18 | #include <asm/dma.h> |
16 | 19 | ||
17 | #include <asm/sbus.h> | ||
18 | |||
19 | #include <scsi/scsi_host.h> | 20 | #include <scsi/scsi_host.h> |
20 | 21 | ||
21 | #include "esp_scsi.h" | 22 | #include "esp_scsi.h" |
22 | 23 | ||
23 | #define DRV_MODULE_NAME "sun_esp" | 24 | #define DRV_MODULE_NAME "sun_esp" |
24 | #define PFX DRV_MODULE_NAME ": " | 25 | #define PFX DRV_MODULE_NAME ": " |
25 | #define DRV_VERSION "1.000" | 26 | #define DRV_VERSION "1.100" |
26 | #define DRV_MODULE_RELDATE "April 19, 2007" | 27 | #define DRV_MODULE_RELDATE "August 27, 2008" |
27 | 28 | ||
28 | #define dma_read32(REG) \ | 29 | #define dma_read32(REG) \ |
29 | sbus_readl(esp->dma_regs + (REG)) | 30 | sbus_readl(esp->dma_regs + (REG)) |
30 | #define dma_write32(VAL, REG) \ | 31 | #define dma_write32(VAL, REG) \ |
31 | sbus_writel((VAL), esp->dma_regs + (REG)) | 32 | sbus_writel((VAL), esp->dma_regs + (REG)) |
32 | 33 | ||
33 | static int __devinit esp_sbus_find_dma(struct esp *esp, struct sbus_dev *dma_sdev) | 34 | /* DVMA chip revisions */ |
34 | { | 35 | enum dvma_rev { |
35 | struct sbus_dev *sdev = esp->dev; | 36 | dvmarev0, |
36 | struct sbus_dma *dma; | 37 | dvmaesc1, |
38 | dvmarev1, | ||
39 | dvmarev2, | ||
40 | dvmarev3, | ||
41 | dvmarevplus, | ||
42 | dvmahme | ||
43 | }; | ||
37 | 44 | ||
38 | if (dma_sdev != NULL) { | 45 | static int __devinit esp_sbus_setup_dma(struct esp *esp, |
39 | for_each_dvma(dma) { | 46 | struct of_device *dma_of) |
40 | if (dma->sdev == dma_sdev) | 47 | { |
41 | break; | 48 | esp->dma = dma_of; |
42 | } | ||
43 | } else { | ||
44 | for_each_dvma(dma) { | ||
45 | if (dma->sdev == NULL) | ||
46 | break; | ||
47 | 49 | ||
48 | /* If bus + slot are the same and it has the | 50 | esp->dma_regs = of_ioremap(&dma_of->resource[0], 0, |
49 | * correct OBP name, it's ours. | 51 | resource_size(&dma_of->resource[0]), |
50 | */ | 52 | "espdma"); |
51 | if (sdev->bus == dma->sdev->bus && | 53 | if (!esp->dma_regs) |
52 | sdev->slot == dma->sdev->slot && | 54 | return -ENOMEM; |
53 | (!strcmp(dma->sdev->prom_name, "dma") || | ||
54 | !strcmp(dma->sdev->prom_name, "espdma"))) | ||
55 | break; | ||
56 | } | ||
57 | } | ||
58 | 55 | ||
59 | if (dma == NULL) { | 56 | switch (dma_read32(DMA_CSR) & DMA_DEVICE_ID) { |
60 | printk(KERN_ERR PFX "[%s] Cannot find dma.\n", | 57 | case DMA_VERS0: |
61 | sdev->ofdev.node->full_name); | 58 | esp->dmarev = dvmarev0; |
62 | return -ENODEV; | 59 | break; |
60 | case DMA_ESCV1: | ||
61 | esp->dmarev = dvmaesc1; | ||
62 | break; | ||
63 | case DMA_VERS1: | ||
64 | esp->dmarev = dvmarev1; | ||
65 | break; | ||
66 | case DMA_VERS2: | ||
67 | esp->dmarev = dvmarev2; | ||
68 | break; | ||
69 | case DMA_VERHME: | ||
70 | esp->dmarev = dvmahme; | ||
71 | break; | ||
72 | case DMA_VERSPLUS: | ||
73 | esp->dmarev = dvmarevplus; | ||
74 | break; | ||
63 | } | 75 | } |
64 | esp->dma = dma; | ||
65 | esp->dma_regs = dma->regs; | ||
66 | 76 | ||
67 | return 0; | 77 | return 0; |
68 | 78 | ||
@@ -70,18 +80,18 @@ static int __devinit esp_sbus_find_dma(struct esp *esp, struct sbus_dev *dma_sde | |||
70 | 80 | ||
71 | static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) | 81 | static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) |
72 | { | 82 | { |
73 | struct sbus_dev *sdev = esp->dev; | 83 | struct of_device *op = esp->dev; |
74 | struct resource *res; | 84 | struct resource *res; |
75 | 85 | ||
76 | /* On HME, two reg sets exist, first is DVMA, | 86 | /* On HME, two reg sets exist, first is DVMA, |
77 | * second is ESP registers. | 87 | * second is ESP registers. |
78 | */ | 88 | */ |
79 | if (hme) | 89 | if (hme) |
80 | res = &sdev->resource[1]; | 90 | res = &op->resource[1]; |
81 | else | 91 | else |
82 | res = &sdev->resource[0]; | 92 | res = &op->resource[0]; |
83 | 93 | ||
84 | esp->regs = sbus_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP"); | 94 | esp->regs = of_ioremap(res, 0, SBUS_ESP_REG_SIZE, "ESP"); |
85 | if (!esp->regs) | 95 | if (!esp->regs) |
86 | return -ENOMEM; | 96 | return -ENOMEM; |
87 | 97 | ||
@@ -90,10 +100,11 @@ static int __devinit esp_sbus_map_regs(struct esp *esp, int hme) | |||
90 | 100 | ||
91 | static int __devinit esp_sbus_map_command_block(struct esp *esp) | 101 | static int __devinit esp_sbus_map_command_block(struct esp *esp) |
92 | { | 102 | { |
93 | struct sbus_dev *sdev = esp->dev; | 103 | struct of_device *op = esp->dev; |
94 | 104 | ||
95 | esp->command_block = sbus_alloc_consistent(sdev, 16, | 105 | esp->command_block = dma_alloc_coherent(&op->dev, 16, |
96 | &esp->command_block_dma); | 106 | &esp->command_block_dma, |
107 | GFP_ATOMIC); | ||
97 | if (!esp->command_block) | 108 | if (!esp->command_block) |
98 | return -ENOMEM; | 109 | return -ENOMEM; |
99 | return 0; | 110 | return 0; |
@@ -102,17 +113,18 @@ static int __devinit esp_sbus_map_command_block(struct esp *esp) | |||
102 | static int __devinit esp_sbus_register_irq(struct esp *esp) | 113 | static int __devinit esp_sbus_register_irq(struct esp *esp) |
103 | { | 114 | { |
104 | struct Scsi_Host *host = esp->host; | 115 | struct Scsi_Host *host = esp->host; |
105 | struct sbus_dev *sdev = esp->dev; | 116 | struct of_device *op = esp->dev; |
106 | 117 | ||
107 | host->irq = sdev->irqs[0]; | 118 | host->irq = op->irqs[0]; |
108 | return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); | 119 | return request_irq(host->irq, scsi_esp_intr, IRQF_SHARED, "ESP", esp); |
109 | } | 120 | } |
110 | 121 | ||
111 | static void __devinit esp_get_scsi_id(struct esp *esp) | 122 | static void __devinit esp_get_scsi_id(struct esp *esp, struct of_device *espdma) |
112 | { | 123 | { |
113 | struct sbus_dev *sdev = esp->dev; | 124 | struct of_device *op = esp->dev; |
114 | struct device_node *dp = sdev->ofdev.node; | 125 | struct device_node *dp; |
115 | 126 | ||
127 | dp = op->node; | ||
116 | esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff); | 128 | esp->scsi_id = of_getintprop_default(dp, "initiator-id", 0xff); |
117 | if (esp->scsi_id != 0xff) | 129 | if (esp->scsi_id != 0xff) |
118 | goto done; | 130 | goto done; |
@@ -121,13 +133,7 @@ static void __devinit esp_get_scsi_id(struct esp *esp) | |||
121 | if (esp->scsi_id != 0xff) | 133 | if (esp->scsi_id != 0xff) |
122 | goto done; | 134 | goto done; |
123 | 135 | ||
124 | if (!sdev->bus) { | 136 | esp->scsi_id = of_getintprop_default(espdma->node, |
125 | /* SUN4 */ | ||
126 | esp->scsi_id = 7; | ||
127 | goto done; | ||
128 | } | ||
129 | |||
130 | esp->scsi_id = of_getintprop_default(sdev->bus->ofdev.node, | ||
131 | "scsi-initiator-id", 7); | 137 | "scsi-initiator-id", 7); |
132 | 138 | ||
133 | done: | 139 | done: |
@@ -137,9 +143,10 @@ done: | |||
137 | 143 | ||
138 | static void __devinit esp_get_differential(struct esp *esp) | 144 | static void __devinit esp_get_differential(struct esp *esp) |
139 | { | 145 | { |
140 | struct sbus_dev *sdev = esp->dev; | 146 | struct of_device *op = esp->dev; |
141 | struct device_node *dp = sdev->ofdev.node; | 147 | struct device_node *dp; |
142 | 148 | ||
149 | dp = op->node; | ||
143 | if (of_find_property(dp, "differential", NULL)) | 150 | if (of_find_property(dp, "differential", NULL)) |
144 | esp->flags |= ESP_FLAG_DIFFERENTIAL; | 151 | esp->flags |= ESP_FLAG_DIFFERENTIAL; |
145 | else | 152 | else |
@@ -148,43 +155,36 @@ static void __devinit esp_get_differential(struct esp *esp) | |||
148 | 155 | ||
149 | static void __devinit esp_get_clock_params(struct esp *esp) | 156 | static void __devinit esp_get_clock_params(struct esp *esp) |
150 | { | 157 | { |
151 | struct sbus_dev *sdev = esp->dev; | 158 | struct of_device *op = esp->dev; |
152 | struct device_node *dp = sdev->ofdev.node; | 159 | struct device_node *bus_dp, *dp; |
153 | struct device_node *bus_dp; | ||
154 | int fmhz; | 160 | int fmhz; |
155 | 161 | ||
156 | bus_dp = NULL; | 162 | dp = op->node; |
157 | if (sdev != NULL && sdev->bus != NULL) | 163 | bus_dp = dp->parent; |
158 | bus_dp = sdev->bus->ofdev.node; | ||
159 | 164 | ||
160 | fmhz = of_getintprop_default(dp, "clock-frequency", 0); | 165 | fmhz = of_getintprop_default(dp, "clock-frequency", 0); |
161 | if (fmhz == 0) | 166 | if (fmhz == 0) |
162 | fmhz = (!bus_dp) ? 0 : | 167 | fmhz = of_getintprop_default(bus_dp, "clock-frequency", 0); |
163 | of_getintprop_default(bus_dp, "clock-frequency", 0); | ||
164 | 168 | ||
165 | esp->cfreq = fmhz; | 169 | esp->cfreq = fmhz; |
166 | } | 170 | } |
167 | 171 | ||
168 | static void __devinit esp_get_bursts(struct esp *esp, struct sbus_dev *dma) | 172 | static void __devinit esp_get_bursts(struct esp *esp, struct of_device *dma_of) |
169 | { | 173 | { |
170 | struct sbus_dev *sdev = esp->dev; | 174 | struct device_node *dma_dp = dma_of->node; |
171 | struct device_node *dp = sdev->ofdev.node; | 175 | struct of_device *op = esp->dev; |
172 | u8 bursts; | 176 | struct device_node *dp; |
177 | u8 bursts, val; | ||
173 | 178 | ||
179 | dp = op->node; | ||
174 | bursts = of_getintprop_default(dp, "burst-sizes", 0xff); | 180 | bursts = of_getintprop_default(dp, "burst-sizes", 0xff); |
175 | if (dma) { | 181 | val = of_getintprop_default(dma_dp, "burst-sizes", 0xff); |
176 | struct device_node *dma_dp = dma->ofdev.node; | 182 | if (val != 0xff) |
177 | u8 val = of_getintprop_default(dma_dp, "burst-sizes", 0xff); | 183 | bursts &= val; |
178 | if (val != 0xff) | ||
179 | bursts &= val; | ||
180 | } | ||
181 | 184 | ||
182 | if (sdev->bus) { | 185 | val = of_getintprop_default(dma_dp->parent, "burst-sizes", 0xff); |
183 | u8 val = of_getintprop_default(sdev->bus->ofdev.node, | 186 | if (val != 0xff) |
184 | "burst-sizes", 0xff); | 187 | bursts &= val; |
185 | if (val != 0xff) | ||
186 | bursts &= val; | ||
187 | } | ||
188 | 188 | ||
189 | if (bursts == 0xff || | 189 | if (bursts == 0xff || |
190 | (bursts & DMA_BURST16) == 0 || | 190 | (bursts & DMA_BURST16) == 0 || |
@@ -194,9 +194,9 @@ static void __devinit esp_get_bursts(struct esp *esp, struct sbus_dev *dma) | |||
194 | esp->bursts = bursts; | 194 | esp->bursts = bursts; |
195 | } | 195 | } |
196 | 196 | ||
197 | static void __devinit esp_sbus_get_props(struct esp *esp, struct sbus_dev *espdma) | 197 | static void __devinit esp_sbus_get_props(struct esp *esp, struct of_device *espdma) |
198 | { | 198 | { |
199 | esp_get_scsi_id(esp); | 199 | esp_get_scsi_id(esp, espdma); |
200 | esp_get_differential(esp); | 200 | esp_get_differential(esp); |
201 | esp_get_clock_params(esp); | 201 | esp_get_clock_params(esp); |
202 | esp_get_bursts(esp, espdma); | 202 | esp_get_bursts(esp, espdma); |
@@ -215,25 +215,33 @@ static u8 sbus_esp_read8(struct esp *esp, unsigned long reg) | |||
215 | static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, | 215 | static dma_addr_t sbus_esp_map_single(struct esp *esp, void *buf, |
216 | size_t sz, int dir) | 216 | size_t sz, int dir) |
217 | { | 217 | { |
218 | return sbus_map_single(esp->dev, buf, sz, dir); | 218 | struct of_device *op = esp->dev; |
219 | |||
220 | return dma_map_single(&op->dev, buf, sz, dir); | ||
219 | } | 221 | } |
220 | 222 | ||
221 | static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, | 223 | static int sbus_esp_map_sg(struct esp *esp, struct scatterlist *sg, |
222 | int num_sg, int dir) | 224 | int num_sg, int dir) |
223 | { | 225 | { |
224 | return sbus_map_sg(esp->dev, sg, num_sg, dir); | 226 | struct of_device *op = esp->dev; |
227 | |||
228 | return dma_map_sg(&op->dev, sg, num_sg, dir); | ||
225 | } | 229 | } |
226 | 230 | ||
227 | static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, | 231 | static void sbus_esp_unmap_single(struct esp *esp, dma_addr_t addr, |
228 | size_t sz, int dir) | 232 | size_t sz, int dir) |
229 | { | 233 | { |
230 | sbus_unmap_single(esp->dev, addr, sz, dir); | 234 | struct of_device *op = esp->dev; |
235 | |||
236 | dma_unmap_single(&op->dev, addr, sz, dir); | ||
231 | } | 237 | } |
232 | 238 | ||
233 | static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, | 239 | static void sbus_esp_unmap_sg(struct esp *esp, struct scatterlist *sg, |
234 | int num_sg, int dir) | 240 | int num_sg, int dir) |
235 | { | 241 | { |
236 | sbus_unmap_sg(esp->dev, sg, num_sg, dir); | 242 | struct of_device *op = esp->dev; |
243 | |||
244 | dma_unmap_sg(&op->dev, sg, num_sg, dir); | ||
237 | } | 245 | } |
238 | 246 | ||
239 | static int sbus_esp_irq_pending(struct esp *esp) | 247 | static int sbus_esp_irq_pending(struct esp *esp) |
@@ -247,24 +255,26 @@ static void sbus_esp_reset_dma(struct esp *esp) | |||
247 | { | 255 | { |
248 | int can_do_burst16, can_do_burst32, can_do_burst64; | 256 | int can_do_burst16, can_do_burst32, can_do_burst64; |
249 | int can_do_sbus64, lim; | 257 | int can_do_sbus64, lim; |
258 | struct of_device *op; | ||
250 | u32 val; | 259 | u32 val; |
251 | 260 | ||
252 | can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; | 261 | can_do_burst16 = (esp->bursts & DMA_BURST16) != 0; |
253 | can_do_burst32 = (esp->bursts & DMA_BURST32) != 0; | 262 | can_do_burst32 = (esp->bursts & DMA_BURST32) != 0; |
254 | can_do_burst64 = 0; | 263 | can_do_burst64 = 0; |
255 | can_do_sbus64 = 0; | 264 | can_do_sbus64 = 0; |
256 | if (sbus_can_dma_64bit(esp->dev)) | 265 | op = esp->dev; |
266 | if (sbus_can_dma_64bit()) | ||
257 | can_do_sbus64 = 1; | 267 | can_do_sbus64 = 1; |
258 | if (sbus_can_burst64(esp->sdev)) | 268 | if (sbus_can_burst64()) |
259 | can_do_burst64 = (esp->bursts & DMA_BURST64) != 0; | 269 | can_do_burst64 = (esp->bursts & DMA_BURST64) != 0; |
260 | 270 | ||
261 | /* Put the DVMA into a known state. */ | 271 | /* Put the DVMA into a known state. */ |
262 | if (esp->dma->revision != dvmahme) { | 272 | if (esp->dmarev != dvmahme) { |
263 | val = dma_read32(DMA_CSR); | 273 | val = dma_read32(DMA_CSR); |
264 | dma_write32(val | DMA_RST_SCSI, DMA_CSR); | 274 | dma_write32(val | DMA_RST_SCSI, DMA_CSR); |
265 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); | 275 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); |
266 | } | 276 | } |
267 | switch (esp->dma->revision) { | 277 | switch (esp->dmarev) { |
268 | case dvmahme: | 278 | case dvmahme: |
269 | dma_write32(DMA_RESET_FAS366, DMA_CSR); | 279 | dma_write32(DMA_RESET_FAS366, DMA_CSR); |
270 | dma_write32(DMA_RST_SCSI, DMA_CSR); | 280 | dma_write32(DMA_RST_SCSI, DMA_CSR); |
@@ -282,7 +292,7 @@ static void sbus_esp_reset_dma(struct esp *esp) | |||
282 | 292 | ||
283 | if (can_do_sbus64) { | 293 | if (can_do_sbus64) { |
284 | esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64; | 294 | esp->prev_hme_dmacsr |= DMA_SCSI_SBUS64; |
285 | sbus_set_sbus64(esp->dev, esp->bursts); | 295 | sbus_set_sbus64(&op->dev, esp->bursts); |
286 | } | 296 | } |
287 | 297 | ||
288 | lim = 1000; | 298 | lim = 1000; |
@@ -346,14 +356,14 @@ static void sbus_esp_dma_drain(struct esp *esp) | |||
346 | u32 csr; | 356 | u32 csr; |
347 | int lim; | 357 | int lim; |
348 | 358 | ||
349 | if (esp->dma->revision == dvmahme) | 359 | if (esp->dmarev == dvmahme) |
350 | return; | 360 | return; |
351 | 361 | ||
352 | csr = dma_read32(DMA_CSR); | 362 | csr = dma_read32(DMA_CSR); |
353 | if (!(csr & DMA_FIFO_ISDRAIN)) | 363 | if (!(csr & DMA_FIFO_ISDRAIN)) |
354 | return; | 364 | return; |
355 | 365 | ||
356 | if (esp->dma->revision != dvmarev3 && esp->dma->revision != dvmaesc1) | 366 | if (esp->dmarev != dvmarev3 && esp->dmarev != dvmaesc1) |
357 | dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR); | 367 | dma_write32(csr | DMA_FIFO_STDRAIN, DMA_CSR); |
358 | 368 | ||
359 | lim = 1000; | 369 | lim = 1000; |
@@ -369,7 +379,7 @@ static void sbus_esp_dma_drain(struct esp *esp) | |||
369 | 379 | ||
370 | static void sbus_esp_dma_invalidate(struct esp *esp) | 380 | static void sbus_esp_dma_invalidate(struct esp *esp) |
371 | { | 381 | { |
372 | if (esp->dma->revision == dvmahme) { | 382 | if (esp->dmarev == dvmahme) { |
373 | dma_write32(DMA_RST_SCSI, DMA_CSR); | 383 | dma_write32(DMA_RST_SCSI, DMA_CSR); |
374 | 384 | ||
375 | esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr | | 385 | esp->prev_hme_dmacsr = ((esp->prev_hme_dmacsr | |
@@ -440,7 +450,7 @@ static void sbus_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count, | |||
440 | else | 450 | else |
441 | csr &= ~DMA_ST_WRITE; | 451 | csr &= ~DMA_ST_WRITE; |
442 | dma_write32(csr, DMA_CSR); | 452 | dma_write32(csr, DMA_CSR); |
443 | if (esp->dma->revision == dvmaesc1) { | 453 | if (esp->dmarev == dvmaesc1) { |
444 | u32 end = PAGE_ALIGN(addr + dma_count + 16U); | 454 | u32 end = PAGE_ALIGN(addr + dma_count + 16U); |
445 | dma_write32(end - addr, DMA_COUNT); | 455 | dma_write32(end - addr, DMA_COUNT); |
446 | } | 456 | } |
@@ -476,10 +486,8 @@ static const struct esp_driver_ops sbus_esp_ops = { | |||
476 | .dma_error = sbus_esp_dma_error, | 486 | .dma_error = sbus_esp_dma_error, |
477 | }; | 487 | }; |
478 | 488 | ||
479 | static int __devinit esp_sbus_probe_one(struct device *dev, | 489 | static int __devinit esp_sbus_probe_one(struct of_device *op, |
480 | struct sbus_dev *esp_dev, | 490 | struct of_device *espdma, |
481 | struct sbus_dev *espdma, | ||
482 | struct sbus_bus *sbus, | ||
483 | int hme) | 491 | int hme) |
484 | { | 492 | { |
485 | struct scsi_host_template *tpnt = &scsi_esp_template; | 493 | struct scsi_host_template *tpnt = &scsi_esp_template; |
@@ -497,13 +505,13 @@ static int __devinit esp_sbus_probe_one(struct device *dev, | |||
497 | esp = shost_priv(host); | 505 | esp = shost_priv(host); |
498 | 506 | ||
499 | esp->host = host; | 507 | esp->host = host; |
500 | esp->dev = esp_dev; | 508 | esp->dev = op; |
501 | esp->ops = &sbus_esp_ops; | 509 | esp->ops = &sbus_esp_ops; |
502 | 510 | ||
503 | if (hme) | 511 | if (hme) |
504 | esp->flags |= ESP_FLAG_WIDE_CAPABLE; | 512 | esp->flags |= ESP_FLAG_WIDE_CAPABLE; |
505 | 513 | ||
506 | err = esp_sbus_find_dma(esp, espdma); | 514 | err = esp_sbus_setup_dma(esp, espdma); |
507 | if (err < 0) | 515 | if (err < 0) |
508 | goto fail_unlink; | 516 | goto fail_unlink; |
509 | 517 | ||
@@ -525,15 +533,15 @@ static int __devinit esp_sbus_probe_one(struct device *dev, | |||
525 | * come up with the reset bit set, so make sure that | 533 | * come up with the reset bit set, so make sure that |
526 | * is clear first. | 534 | * is clear first. |
527 | */ | 535 | */ |
528 | if (esp->dma->revision == dvmaesc1) { | 536 | if (esp->dmarev == dvmaesc1) { |
529 | u32 val = dma_read32(DMA_CSR); | 537 | u32 val = dma_read32(DMA_CSR); |
530 | 538 | ||
531 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); | 539 | dma_write32(val & ~DMA_RST_SCSI, DMA_CSR); |
532 | } | 540 | } |
533 | 541 | ||
534 | dev_set_drvdata(&esp_dev->ofdev.dev, esp); | 542 | dev_set_drvdata(&op->dev, esp); |
535 | 543 | ||
536 | err = scsi_esp_register(esp, dev); | 544 | err = scsi_esp_register(esp, &op->dev); |
537 | if (err) | 545 | if (err) |
538 | goto fail_free_irq; | 546 | goto fail_free_irq; |
539 | 547 | ||
@@ -542,41 +550,46 @@ static int __devinit esp_sbus_probe_one(struct device *dev, | |||
542 | fail_free_irq: | 550 | fail_free_irq: |
543 | free_irq(host->irq, esp); | 551 | free_irq(host->irq, esp); |
544 | fail_unmap_command_block: | 552 | fail_unmap_command_block: |
545 | sbus_free_consistent(esp->dev, 16, | 553 | dma_free_coherent(&op->dev, 16, |
546 | esp->command_block, | 554 | esp->command_block, |
547 | esp->command_block_dma); | 555 | esp->command_block_dma); |
548 | fail_unmap_regs: | 556 | fail_unmap_regs: |
549 | sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE); | 557 | of_iounmap(&op->resource[(hme ? 1 : 0)], esp->regs, SBUS_ESP_REG_SIZE); |
550 | fail_unlink: | 558 | fail_unlink: |
551 | scsi_host_put(host); | 559 | scsi_host_put(host); |
552 | fail: | 560 | fail: |
553 | return err; | 561 | return err; |
554 | } | 562 | } |
555 | 563 | ||
556 | static int __devinit esp_sbus_probe(struct of_device *dev, const struct of_device_id *match) | 564 | static int __devinit esp_sbus_probe(struct of_device *op, const struct of_device_id *match) |
557 | { | 565 | { |
558 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | 566 | struct device_node *dma_node = NULL; |
559 | struct device_node *dp = dev->node; | 567 | struct device_node *dp = op->node; |
560 | struct sbus_dev *dma_sdev = NULL; | 568 | struct of_device *dma_of = NULL; |
561 | int hme = 0; | 569 | int hme = 0; |
562 | 570 | ||
563 | if (dp->parent && | 571 | if (dp->parent && |
564 | (!strcmp(dp->parent->name, "espdma") || | 572 | (!strcmp(dp->parent->name, "espdma") || |
565 | !strcmp(dp->parent->name, "dma"))) | 573 | !strcmp(dp->parent->name, "dma"))) |
566 | dma_sdev = sdev->parent; | 574 | dma_node = dp->parent; |
567 | else if (!strcmp(dp->name, "SUNW,fas")) { | 575 | else if (!strcmp(dp->name, "SUNW,fas")) { |
568 | dma_sdev = sdev; | 576 | dma_node = op->node; |
569 | hme = 1; | 577 | hme = 1; |
570 | } | 578 | } |
579 | if (dma_node) | ||
580 | dma_of = of_find_device_by_node(dma_node); | ||
581 | if (!dma_of) | ||
582 | return -ENODEV; | ||
571 | 583 | ||
572 | return esp_sbus_probe_one(&dev->dev, sdev, dma_sdev, | 584 | return esp_sbus_probe_one(op, dma_of, hme); |
573 | sdev->bus, hme); | ||
574 | } | 585 | } |
575 | 586 | ||
576 | static int __devexit esp_sbus_remove(struct of_device *dev) | 587 | static int __devexit esp_sbus_remove(struct of_device *op) |
577 | { | 588 | { |
578 | struct esp *esp = dev_get_drvdata(&dev->dev); | 589 | struct esp *esp = dev_get_drvdata(&op->dev); |
590 | struct of_device *dma_of = esp->dma; | ||
579 | unsigned int irq = esp->host->irq; | 591 | unsigned int irq = esp->host->irq; |
592 | bool is_hme; | ||
580 | u32 val; | 593 | u32 val; |
581 | 594 | ||
582 | scsi_esp_unregister(esp); | 595 | scsi_esp_unregister(esp); |
@@ -586,17 +599,25 @@ static int __devexit esp_sbus_remove(struct of_device *dev) | |||
586 | dma_write32(val & ~DMA_INT_ENAB, DMA_CSR); | 599 | dma_write32(val & ~DMA_INT_ENAB, DMA_CSR); |
587 | 600 | ||
588 | free_irq(irq, esp); | 601 | free_irq(irq, esp); |
589 | sbus_free_consistent(esp->dev, 16, | 602 | |
590 | esp->command_block, | 603 | is_hme = (esp->dmarev == dvmahme); |
591 | esp->command_block_dma); | 604 | |
592 | sbus_iounmap(esp->regs, SBUS_ESP_REG_SIZE); | 605 | dma_free_coherent(&op->dev, 16, |
606 | esp->command_block, | ||
607 | esp->command_block_dma); | ||
608 | of_iounmap(&op->resource[(is_hme ? 1 : 0)], esp->regs, | ||
609 | SBUS_ESP_REG_SIZE); | ||
610 | of_iounmap(&dma_of->resource[0], esp->dma_regs, | ||
611 | resource_size(&dma_of->resource[0])); | ||
593 | 612 | ||
594 | scsi_host_put(esp->host); | 613 | scsi_host_put(esp->host); |
595 | 614 | ||
615 | dev_set_drvdata(&op->dev, NULL); | ||
616 | |||
596 | return 0; | 617 | return 0; |
597 | } | 618 | } |
598 | 619 | ||
599 | static struct of_device_id esp_match[] = { | 620 | static const struct of_device_id esp_match[] = { |
600 | { | 621 | { |
601 | .name = "SUNW,esp", | 622 | .name = "SUNW,esp", |
602 | }, | 623 | }, |
@@ -619,7 +640,7 @@ static struct of_platform_driver esp_sbus_driver = { | |||
619 | 640 | ||
620 | static int __init sunesp_init(void) | 641 | static int __init sunesp_init(void) |
621 | { | 642 | { |
622 | return of_register_driver(&esp_sbus_driver, &sbus_bus_type); | 643 | return of_register_driver(&esp_sbus_driver, &of_bus_type); |
623 | } | 644 | } |
624 | 645 | ||
625 | static void __exit sunesp_exit(void) | 646 | static void __exit sunesp_exit(void) |
diff --git a/drivers/serial/sunhv.c b/drivers/serial/sunhv.c index e41766d08035..a94a2ab4b571 100644 --- a/drivers/serial/sunhv.c +++ b/drivers/serial/sunhv.c | |||
@@ -616,7 +616,7 @@ static int __devexit hv_remove(struct of_device *dev) | |||
616 | return 0; | 616 | return 0; |
617 | } | 617 | } |
618 | 618 | ||
619 | static struct of_device_id hv_match[] = { | 619 | static const struct of_device_id hv_match[] = { |
620 | { | 620 | { |
621 | .name = "console", | 621 | .name = "console", |
622 | .compatible = "qcn", | 622 | .compatible = "qcn", |
diff --git a/drivers/serial/sunsab.c b/drivers/serial/sunsab.c index 29b4458abf74..0355efe115d9 100644 --- a/drivers/serial/sunsab.c +++ b/drivers/serial/sunsab.c | |||
@@ -1078,7 +1078,7 @@ static int __devexit sab_remove(struct of_device *op) | |||
1078 | return 0; | 1078 | return 0; |
1079 | } | 1079 | } |
1080 | 1080 | ||
1081 | static struct of_device_id sab_match[] = { | 1081 | static const struct of_device_id sab_match[] = { |
1082 | { | 1082 | { |
1083 | .name = "se", | 1083 | .name = "se", |
1084 | }, | 1084 | }, |
diff --git a/drivers/serial/sunsu.c b/drivers/serial/sunsu.c index a378464f9292..a4dc79b1d7ab 100644 --- a/drivers/serial/sunsu.c +++ b/drivers/serial/sunsu.c | |||
@@ -1506,7 +1506,7 @@ static int __devexit su_remove(struct of_device *op) | |||
1506 | return 0; | 1506 | return 0; |
1507 | } | 1507 | } |
1508 | 1508 | ||
1509 | static struct of_device_id su_match[] = { | 1509 | static const struct of_device_id su_match[] = { |
1510 | { | 1510 | { |
1511 | .name = "su", | 1511 | .name = "su", |
1512 | }, | 1512 | }, |
diff --git a/drivers/serial/sunzilog.c b/drivers/serial/sunzilog.c index 3cb4c8aee13f..45a299f35617 100644 --- a/drivers/serial/sunzilog.c +++ b/drivers/serial/sunzilog.c | |||
@@ -1480,7 +1480,7 @@ static int __devexit zs_remove(struct of_device *op) | |||
1480 | return 0; | 1480 | return 0; |
1481 | } | 1481 | } |
1482 | 1482 | ||
1483 | static struct of_device_id zs_match[] = { | 1483 | static const struct of_device_id zs_match[] = { |
1484 | { | 1484 | { |
1485 | .name = "zs", | 1485 | .name = "zs", |
1486 | }, | 1486 | }, |
diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index e721644bad74..1e35ba6f18e0 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c | |||
@@ -372,7 +372,7 @@ static int __devexit bw2_remove(struct of_device *op) | |||
372 | return 0; | 372 | return 0; |
373 | } | 373 | } |
374 | 374 | ||
375 | static struct of_device_id bw2_match[] = { | 375 | static const struct of_device_id bw2_match[] = { |
376 | { | 376 | { |
377 | .name = "bwtwo", | 377 | .name = "bwtwo", |
378 | }, | 378 | }, |
diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index b17e74671779..a2d1882791a5 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c | |||
@@ -589,7 +589,7 @@ static int __devexit cg14_remove(struct of_device *op) | |||
589 | return 0; | 589 | return 0; |
590 | } | 590 | } |
591 | 591 | ||
592 | static struct of_device_id cg14_match[] = { | 592 | static const struct of_device_id cg14_match[] = { |
593 | { | 593 | { |
594 | .name = "cgfourteen", | 594 | .name = "cgfourteen", |
595 | }, | 595 | }, |
diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index 3aa7b6cb0268..99f87fb61d05 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c | |||
@@ -456,7 +456,7 @@ static int __devexit cg3_remove(struct of_device *op) | |||
456 | return 0; | 456 | return 0; |
457 | } | 457 | } |
458 | 458 | ||
459 | static struct of_device_id cg3_match[] = { | 459 | static const struct of_device_id cg3_match[] = { |
460 | { | 460 | { |
461 | .name = "cgthree", | 461 | .name = "cgthree", |
462 | }, | 462 | }, |
diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 2f64bb3bd254..940ec04f0f1b 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c | |||
@@ -34,10 +34,11 @@ static int cg6_blank(int, struct fb_info *); | |||
34 | 34 | ||
35 | static void cg6_imageblit(struct fb_info *, const struct fb_image *); | 35 | static void cg6_imageblit(struct fb_info *, const struct fb_image *); |
36 | static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); | 36 | static void cg6_fillrect(struct fb_info *, const struct fb_fillrect *); |
37 | static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area); | ||
37 | static int cg6_sync(struct fb_info *); | 38 | static int cg6_sync(struct fb_info *); |
38 | static int cg6_mmap(struct fb_info *, struct vm_area_struct *); | 39 | static int cg6_mmap(struct fb_info *, struct vm_area_struct *); |
39 | static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); | 40 | static int cg6_ioctl(struct fb_info *, unsigned int, unsigned long); |
40 | static void cg6_copyarea(struct fb_info *info, const struct fb_copyarea *area); | 41 | static int cg6_pan_display(struct fb_var_screeninfo *, struct fb_info *); |
41 | 42 | ||
42 | /* | 43 | /* |
43 | * Frame buffer operations | 44 | * Frame buffer operations |
@@ -47,6 +48,7 @@ static struct fb_ops cg6_ops = { | |||
47 | .owner = THIS_MODULE, | 48 | .owner = THIS_MODULE, |
48 | .fb_setcolreg = cg6_setcolreg, | 49 | .fb_setcolreg = cg6_setcolreg, |
49 | .fb_blank = cg6_blank, | 50 | .fb_blank = cg6_blank, |
51 | .fb_pan_display = cg6_pan_display, | ||
50 | .fb_fillrect = cg6_fillrect, | 52 | .fb_fillrect = cg6_fillrect, |
51 | .fb_copyarea = cg6_copyarea, | 53 | .fb_copyarea = cg6_copyarea, |
52 | .fb_imageblit = cg6_imageblit, | 54 | .fb_imageblit = cg6_imageblit, |
@@ -161,6 +163,7 @@ static struct fb_ops cg6_ops = { | |||
161 | #define CG6_THC_MISC_INT_ENAB (1 << 5) | 163 | #define CG6_THC_MISC_INT_ENAB (1 << 5) |
162 | #define CG6_THC_MISC_INT (1 << 4) | 164 | #define CG6_THC_MISC_INT (1 << 4) |
163 | #define CG6_THC_MISC_INIT 0x9f | 165 | #define CG6_THC_MISC_INIT 0x9f |
166 | #define CG6_THC_CURSOFF ((65536-32) | ((65536-32) << 16)) | ||
164 | 167 | ||
165 | /* The contents are unknown */ | 168 | /* The contents are unknown */ |
166 | struct cg6_tec { | 169 | struct cg6_tec { |
@@ -280,6 +283,33 @@ static int cg6_sync(struct fb_info *info) | |||
280 | return 0; | 283 | return 0; |
281 | } | 284 | } |
282 | 285 | ||
286 | static void cg6_switch_from_graph(struct cg6_par *par) | ||
287 | { | ||
288 | struct cg6_thc __iomem *thc = par->thc; | ||
289 | unsigned long flags; | ||
290 | |||
291 | spin_lock_irqsave(&par->lock, flags); | ||
292 | |||
293 | /* Hide the cursor. */ | ||
294 | sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy); | ||
295 | |||
296 | spin_unlock_irqrestore(&par->lock, flags); | ||
297 | } | ||
298 | |||
299 | static int cg6_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | ||
300 | { | ||
301 | struct cg6_par *par = (struct cg6_par *)info->par; | ||
302 | |||
303 | /* We just use this to catch switches out of | ||
304 | * graphics mode. | ||
305 | */ | ||
306 | cg6_switch_from_graph(par); | ||
307 | |||
308 | if (var->xoffset || var->yoffset || var->vmode) | ||
309 | return -EINVAL; | ||
310 | return 0; | ||
311 | } | ||
312 | |||
283 | /** | 313 | /** |
284 | * cg6_fillrect - Draws a rectangle on the screen. | 314 | * cg6_fillrect - Draws a rectangle on the screen. |
285 | * | 315 | * |
@@ -643,9 +673,13 @@ static void __devinit cg6_chip_init(struct fb_info *info) | |||
643 | struct cg6_par *par = (struct cg6_par *)info->par; | 673 | struct cg6_par *par = (struct cg6_par *)info->par; |
644 | struct cg6_tec __iomem *tec = par->tec; | 674 | struct cg6_tec __iomem *tec = par->tec; |
645 | struct cg6_fbc __iomem *fbc = par->fbc; | 675 | struct cg6_fbc __iomem *fbc = par->fbc; |
676 | struct cg6_thc __iomem *thc = par->thc; | ||
646 | u32 rev, conf, mode; | 677 | u32 rev, conf, mode; |
647 | int i; | 678 | int i; |
648 | 679 | ||
680 | /* Hide the cursor. */ | ||
681 | sbus_writel(CG6_THC_CURSOFF, &thc->thc_cursxy); | ||
682 | |||
649 | /* Turn off stuff in the Transform Engine. */ | 683 | /* Turn off stuff in the Transform Engine. */ |
650 | sbus_writel(0, &tec->tec_matrix); | 684 | sbus_writel(0, &tec->tec_matrix); |
651 | sbus_writel(0, &tec->tec_clip); | 685 | sbus_writel(0, &tec->tec_clip); |
@@ -814,7 +848,7 @@ static int __devexit cg6_remove(struct of_device *op) | |||
814 | return 0; | 848 | return 0; |
815 | } | 849 | } |
816 | 850 | ||
817 | static struct of_device_id cg6_match[] = { | 851 | static const struct of_device_id cg6_match[] = { |
818 | { | 852 | { |
819 | .name = "cgsix", | 853 | .name = "cgsix", |
820 | }, | 854 | }, |
diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 7992b13ee68f..9dbb9646081f 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c | |||
@@ -1042,7 +1042,7 @@ static int __devexit ffb_remove(struct of_device *op) | |||
1042 | return 0; | 1042 | return 0; |
1043 | } | 1043 | } |
1044 | 1044 | ||
1045 | static struct of_device_id ffb_match[] = { | 1045 | static const struct of_device_id ffb_match[] = { |
1046 | { | 1046 | { |
1047 | .name = "SUNW,ffb", | 1047 | .name = "SUNW,ffb", |
1048 | }, | 1048 | }, |
diff --git a/drivers/video/leo.c b/drivers/video/leo.c index 13fea61d6ae4..7c7e8c2da9d9 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c | |||
@@ -33,6 +33,7 @@ static int leo_blank(int, struct fb_info *); | |||
33 | 33 | ||
34 | static int leo_mmap(struct fb_info *, struct vm_area_struct *); | 34 | static int leo_mmap(struct fb_info *, struct vm_area_struct *); |
35 | static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); | 35 | static int leo_ioctl(struct fb_info *, unsigned int, unsigned long); |
36 | static int leo_pan_display(struct fb_var_screeninfo *, struct fb_info *); | ||
36 | 37 | ||
37 | /* | 38 | /* |
38 | * Frame buffer operations | 39 | * Frame buffer operations |
@@ -42,6 +43,7 @@ static struct fb_ops leo_ops = { | |||
42 | .owner = THIS_MODULE, | 43 | .owner = THIS_MODULE, |
43 | .fb_setcolreg = leo_setcolreg, | 44 | .fb_setcolreg = leo_setcolreg, |
44 | .fb_blank = leo_blank, | 45 | .fb_blank = leo_blank, |
46 | .fb_pan_display = leo_pan_display, | ||
45 | .fb_fillrect = cfb_fillrect, | 47 | .fb_fillrect = cfb_fillrect, |
46 | .fb_copyarea = cfb_copyarea, | 48 | .fb_copyarea = cfb_copyarea, |
47 | .fb_imageblit = cfb_imageblit, | 49 | .fb_imageblit = cfb_imageblit, |
@@ -206,6 +208,60 @@ static void leo_wait(struct leo_lx_krn __iomem *lx_krn) | |||
206 | return; | 208 | return; |
207 | } | 209 | } |
208 | 210 | ||
211 | static void leo_switch_from_graph(struct fb_info *info) | ||
212 | { | ||
213 | struct leo_par *par = (struct leo_par *) info->par; | ||
214 | struct leo_ld_ss0 __iomem *ss = par->ld_ss0; | ||
215 | struct leo_cursor __iomem *cursor = par->cursor; | ||
216 | unsigned long flags; | ||
217 | u32 val; | ||
218 | |||
219 | spin_lock_irqsave(&par->lock, flags); | ||
220 | |||
221 | par->extent = ((info->var.xres - 1) | | ||
222 | ((info->var.yres - 1) << 16)); | ||
223 | |||
224 | sbus_writel(0xffffffff, &ss->wid); | ||
225 | sbus_writel(0xffff, &ss->wmask); | ||
226 | sbus_writel(0, &ss->vclipmin); | ||
227 | sbus_writel(par->extent, &ss->vclipmax); | ||
228 | sbus_writel(0, &ss->fg); | ||
229 | sbus_writel(0xff000000, &ss->planemask); | ||
230 | sbus_writel(0x310850, &ss->rop); | ||
231 | sbus_writel(0, &ss->widclip); | ||
232 | sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11), | ||
233 | &par->lc_ss0_usr->extent); | ||
234 | sbus_writel(4, &par->lc_ss0_usr->addrspace); | ||
235 | sbus_writel(0x80000000, &par->lc_ss0_usr->fill); | ||
236 | sbus_writel(0, &par->lc_ss0_usr->fontt); | ||
237 | do { | ||
238 | val = sbus_readl(&par->lc_ss0_usr->csr); | ||
239 | } while (val & 0x20000000); | ||
240 | |||
241 | /* setup screen buffer for cfb_* functions */ | ||
242 | sbus_writel(1, &ss->wid); | ||
243 | sbus_writel(0x00ffffff, &ss->planemask); | ||
244 | sbus_writel(0x310b90, &ss->rop); | ||
245 | sbus_writel(0, &par->lc_ss0_usr->addrspace); | ||
246 | |||
247 | /* hide cursor */ | ||
248 | sbus_writel(sbus_readl(&cursor->cur_misc) & ~LEO_CUR_ENABLE, &cursor->cur_misc); | ||
249 | |||
250 | spin_unlock_irqrestore(&par->lock, flags); | ||
251 | } | ||
252 | |||
253 | static int leo_pan_display(struct fb_var_screeninfo *var, struct fb_info *info) | ||
254 | { | ||
255 | /* We just use this to catch switches out of | ||
256 | * graphics mode. | ||
257 | */ | ||
258 | leo_switch_from_graph(info); | ||
259 | |||
260 | if (var->xoffset || var->yoffset || var->vmode) | ||
261 | return -EINVAL; | ||
262 | return 0; | ||
263 | } | ||
264 | |||
209 | /** | 265 | /** |
210 | * leo_setcolreg - Optional function. Sets a color register. | 266 | * leo_setcolreg - Optional function. Sets a color register. |
211 | * @regno: boolean, 0 copy local, 1 get_user() function | 267 | * @regno: boolean, 0 copy local, 1 get_user() function |
@@ -454,44 +510,6 @@ static void leo_init_wids(struct fb_info *info) | |||
454 | leo_wid_put(info, &wl); | 510 | leo_wid_put(info, &wl); |
455 | } | 511 | } |
456 | 512 | ||
457 | static void leo_switch_from_graph(struct fb_info *info) | ||
458 | { | ||
459 | struct leo_par *par = (struct leo_par *) info->par; | ||
460 | struct leo_ld_ss0 __iomem *ss = par->ld_ss0; | ||
461 | unsigned long flags; | ||
462 | u32 val; | ||
463 | |||
464 | spin_lock_irqsave(&par->lock, flags); | ||
465 | |||
466 | par->extent = ((info->var.xres - 1) | | ||
467 | ((info->var.yres - 1) << 16)); | ||
468 | |||
469 | sbus_writel(0xffffffff, &ss->wid); | ||
470 | sbus_writel(0xffff, &ss->wmask); | ||
471 | sbus_writel(0, &ss->vclipmin); | ||
472 | sbus_writel(par->extent, &ss->vclipmax); | ||
473 | sbus_writel(0, &ss->fg); | ||
474 | sbus_writel(0xff000000, &ss->planemask); | ||
475 | sbus_writel(0x310850, &ss->rop); | ||
476 | sbus_writel(0, &ss->widclip); | ||
477 | sbus_writel((info->var.xres-1) | ((info->var.yres-1) << 11), | ||
478 | &par->lc_ss0_usr->extent); | ||
479 | sbus_writel(4, &par->lc_ss0_usr->addrspace); | ||
480 | sbus_writel(0x80000000, &par->lc_ss0_usr->fill); | ||
481 | sbus_writel(0, &par->lc_ss0_usr->fontt); | ||
482 | do { | ||
483 | val = sbus_readl(&par->lc_ss0_usr->csr); | ||
484 | } while (val & 0x20000000); | ||
485 | |||
486 | /* setup screen buffer for cfb_* functions */ | ||
487 | sbus_writel(1, &ss->wid); | ||
488 | sbus_writel(0x00ffffff, &ss->planemask); | ||
489 | sbus_writel(0x310b90, &ss->rop); | ||
490 | sbus_writel(0, &par->lc_ss0_usr->addrspace); | ||
491 | |||
492 | spin_unlock_irqrestore(&par->lock, flags); | ||
493 | } | ||
494 | |||
495 | static void leo_init_hw(struct fb_info *info) | 513 | static void leo_init_hw(struct fb_info *info) |
496 | { | 514 | { |
497 | struct leo_par *par = (struct leo_par *) info->par; | 515 | struct leo_par *par = (struct leo_par *) info->par; |
@@ -641,7 +659,7 @@ static int __devexit leo_remove(struct of_device *op) | |||
641 | return 0; | 659 | return 0; |
642 | } | 660 | } |
643 | 661 | ||
644 | static struct of_device_id leo_match[] = { | 662 | static const struct of_device_id leo_match[] = { |
645 | { | 663 | { |
646 | .name = "SUNW,leo", | 664 | .name = "SUNW,leo", |
647 | }, | 665 | }, |
diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 9e903454ffc1..7000f2cd5854 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c | |||
@@ -349,7 +349,7 @@ static int __devexit p9100_remove(struct of_device *op) | |||
349 | return 0; | 349 | return 0; |
350 | } | 350 | } |
351 | 351 | ||
352 | static struct of_device_id p9100_match[] = { | 352 | static const struct of_device_id p9100_match[] = { |
353 | { | 353 | { |
354 | .name = "p9100", | 354 | .name = "p9100", |
355 | }, | 355 | }, |
diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 2a03f78bbb0d..643afbfe8277 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c | |||
@@ -505,7 +505,7 @@ static int __devexit tcx_remove(struct of_device *op) | |||
505 | return 0; | 505 | return 0; |
506 | } | 506 | } |
507 | 507 | ||
508 | static struct of_device_id tcx_match[] = { | 508 | static const struct of_device_id tcx_match[] = { |
509 | { | 509 | { |
510 | .name = "SUNW,tcx", | 510 | .name = "SUNW,tcx", |
511 | }, | 511 | }, |
diff --git a/drivers/watchdog/Kconfig b/drivers/watchdog/Kconfig index c51036716700..1a22fe782a27 100644 --- a/drivers/watchdog/Kconfig +++ b/drivers/watchdog/Kconfig | |||
@@ -66,6 +66,13 @@ config AT91RM9200_WATCHDOG | |||
66 | Watchdog timer embedded into AT91RM9200 chips. This will reboot your | 66 | Watchdog timer embedded into AT91RM9200 chips. This will reboot your |
67 | system when the timeout is reached. | 67 | system when the timeout is reached. |
68 | 68 | ||
69 | config AT91SAM9X_WATCHDOG | ||
70 | tristate "AT91SAM9X watchdog" | ||
71 | depends on WATCHDOG && (ARCH_AT91SAM9260 || ARCH_AT91SAM9261) | ||
72 | help | ||
73 | Watchdog timer embedded into AT91SAM9X chips. This will reboot your | ||
74 | system when the timeout is reached. | ||
75 | |||
69 | config 21285_WATCHDOG | 76 | config 21285_WATCHDOG |
70 | tristate "DC21285 watchdog" | 77 | tristate "DC21285 watchdog" |
71 | depends on FOOTBRIDGE | 78 | depends on FOOTBRIDGE |
@@ -217,6 +224,15 @@ config DAVINCI_WATCHDOG | |||
217 | NOTE: once enabled, this timer cannot be disabled. | 224 | NOTE: once enabled, this timer cannot be disabled. |
218 | Say N if you are unsure. | 225 | Say N if you are unsure. |
219 | 226 | ||
227 | config ORION5X_WATCHDOG | ||
228 | tristate "Orion5x watchdog" | ||
229 | depends on ARCH_ORION5X | ||
230 | help | ||
231 | Say Y here if to include support for the watchdog timer | ||
232 | in the Orion5x ARM SoCs. | ||
233 | To compile this driver as a module, choose M here: the | ||
234 | module will be called orion5x_wdt. | ||
235 | |||
220 | # ARM26 Architecture | 236 | # ARM26 Architecture |
221 | 237 | ||
222 | # AVR32 Architecture | 238 | # AVR32 Architecture |
@@ -416,6 +432,18 @@ config IT8712F_WDT | |||
416 | To compile this driver as a module, choose M here: the | 432 | To compile this driver as a module, choose M here: the |
417 | module will be called it8712f_wdt. | 433 | module will be called it8712f_wdt. |
418 | 434 | ||
435 | config IT87_WDT | ||
436 | tristate "IT87 Watchdog Timer" | ||
437 | depends on X86 && EXPERIMENTAL | ||
438 | ---help--- | ||
439 | This is the driver for the hardware watchdog on the ITE IT8716, | ||
440 | IT8718, IT8726, IT8712(Version J,K) Super I/O chips. This watchdog | ||
441 | simply watches your kernel to make sure it doesn't freeze, and if | ||
442 | it does, it reboots your computer after a certain amount of time. | ||
443 | |||
444 | To compile this driver as a module, choose M here: the module will | ||
445 | be called it87_wdt. | ||
446 | |||
419 | config HP_WATCHDOG | 447 | config HP_WATCHDOG |
420 | tristate "HP Proliant iLO 2 Hardware Watchdog Timer" | 448 | tristate "HP Proliant iLO 2 Hardware Watchdog Timer" |
421 | depends on X86 | 449 | depends on X86 |
@@ -573,6 +601,21 @@ config W83697HF_WDT | |||
573 | 601 | ||
574 | Most people will say N. | 602 | Most people will say N. |
575 | 603 | ||
604 | config W83697UG_WDT | ||
605 | tristate "W83697UG/W83697UF Watchdog Timer" | ||
606 | depends on X86 | ||
607 | ---help--- | ||
608 | This is the driver for the hardware watchdog on the W83697UG/UF | ||
609 | chipset as used in MSI Fuzzy CX700 VIA motherboards (and likely others). | ||
610 | This watchdog simply watches your kernel to make sure it doesn't | ||
611 | freeze, and if it does, it reboots your computer after a certain | ||
612 | amount of time. | ||
613 | |||
614 | To compile this driver as a module, choose M here: the | ||
615 | module will be called w83697ug_wdt. | ||
616 | |||
617 | Most people will say N. | ||
618 | |||
576 | config W83877F_WDT | 619 | config W83877F_WDT |
577 | tristate "W83877F (EMACS) Watchdog Timer" | 620 | tristate "W83877F (EMACS) Watchdog Timer" |
578 | depends on X86 | 621 | depends on X86 |
diff --git a/drivers/watchdog/Makefile b/drivers/watchdog/Makefile index e0ef123fbdea..e352bbb7630b 100644 --- a/drivers/watchdog/Makefile +++ b/drivers/watchdog/Makefile | |||
@@ -26,6 +26,7 @@ obj-$(CONFIG_USBPCWATCHDOG) += pcwd_usb.o | |||
26 | 26 | ||
27 | # ARM Architecture | 27 | # ARM Architecture |
28 | obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o | 28 | obj-$(CONFIG_AT91RM9200_WATCHDOG) += at91rm9200_wdt.o |
29 | obj-$(CONFIG_AT91SAM9X_WATCHDOG) += at91sam9_wdt.o | ||
29 | obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o | 30 | obj-$(CONFIG_OMAP_WATCHDOG) += omap_wdt.o |
30 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o | 31 | obj-$(CONFIG_21285_WATCHDOG) += wdt285.o |
31 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o | 32 | obj-$(CONFIG_977_WATCHDOG) += wdt977.o |
@@ -39,6 +40,7 @@ obj-$(CONFIG_EP93XX_WATCHDOG) += ep93xx_wdt.o | |||
39 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o | 40 | obj-$(CONFIG_PNX4008_WATCHDOG) += pnx4008_wdt.o |
40 | obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o | 41 | obj-$(CONFIG_IOP_WATCHDOG) += iop_wdt.o |
41 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o | 42 | obj-$(CONFIG_DAVINCI_WATCHDOG) += davinci_wdt.o |
43 | obj-$(CONFIG_ORION5X_WATCHDOG) += orion5x_wdt.o | ||
42 | 44 | ||
43 | # ARM26 Architecture | 45 | # ARM26 Architecture |
44 | 46 | ||
@@ -71,6 +73,7 @@ ifeq ($(CONFIG_ITCO_VENDOR_SUPPORT),y) | |||
71 | obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o | 73 | obj-$(CONFIG_ITCO_WDT) += iTCO_vendor_support.o |
72 | endif | 74 | endif |
73 | obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o | 75 | obj-$(CONFIG_IT8712F_WDT) += it8712f_wdt.o |
76 | obj-$(CONFIG_IT87_WDT) += it87_wdt.o | ||
74 | obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o | 77 | obj-$(CONFIG_HP_WATCHDOG) += hpwdt.o |
75 | obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o | 78 | obj-$(CONFIG_SC1200_WDT) += sc1200wdt.o |
76 | obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o | 79 | obj-$(CONFIG_SCx200_WDT) += scx200_wdt.o |
@@ -83,6 +86,7 @@ obj-$(CONFIG_CPU5_WDT) += cpu5wdt.o | |||
83 | obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o | 86 | obj-$(CONFIG_SMSC37B787_WDT) += smsc37b787_wdt.o |
84 | obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o | 87 | obj-$(CONFIG_W83627HF_WDT) += w83627hf_wdt.o |
85 | obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o | 88 | obj-$(CONFIG_W83697HF_WDT) += w83697hf_wdt.o |
89 | obj-$(CONFIG_W83697UG_WDT) += w83697ug_wdt.o | ||
86 | obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o | 90 | obj-$(CONFIG_W83877F_WDT) += w83877f_wdt.o |
87 | obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o | 91 | obj-$(CONFIG_W83977F_WDT) += w83977f_wdt.o |
88 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o | 92 | obj-$(CONFIG_MACHZ_WDT) += machzwd.o |
@@ -123,6 +127,9 @@ obj-$(CONFIG_SH_WDT) += shwdt.o | |||
123 | 127 | ||
124 | # SPARC64 Architecture | 128 | # SPARC64 Architecture |
125 | 129 | ||
130 | obj-$(CONFIG_WATCHDOG_RIO) += riowd.o | ||
131 | obj-$(CONFIG_WATCHDOG_CP1XXX) += cpwd.o | ||
132 | |||
126 | # XTENSA Architecture | 133 | # XTENSA Architecture |
127 | 134 | ||
128 | # Architecture Independant | 135 | # Architecture Independant |
diff --git a/drivers/watchdog/at91sam9_wdt.c b/drivers/watchdog/at91sam9_wdt.c new file mode 100644 index 000000000000..b4babfc31586 --- /dev/null +++ b/drivers/watchdog/at91sam9_wdt.c | |||
@@ -0,0 +1,328 @@ | |||
1 | /* | ||
2 | * Watchdog driver for Atmel AT91SAM9x processors. | ||
3 | * | ||
4 | * Copyright (C) 2008 Renaud CERRATO r.cerrato@til-technologies.fr | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or | ||
7 | * modify it under the terms of the GNU General Public License | ||
8 | * as published by the Free Software Foundation; either version | ||
9 | * 2 of the License, or (at your option) any later version. | ||
10 | */ | ||
11 | |||
12 | /* | ||
13 | * The Watchdog Timer Mode Register can be only written to once. If the | ||
14 | * timeout need to be set from Linux, be sure that the bootstrap or the | ||
15 | * bootloader doesn't write to this register. | ||
16 | */ | ||
17 | |||
18 | #include <linux/errno.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/kernel.h> | ||
22 | #include <linux/miscdevice.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/moduleparam.h> | ||
25 | #include <linux/platform_device.h> | ||
26 | #include <linux/types.h> | ||
27 | #include <linux/watchdog.h> | ||
28 | #include <linux/jiffies.h> | ||
29 | #include <linux/timer.h> | ||
30 | #include <linux/bitops.h> | ||
31 | #include <linux/uaccess.h> | ||
32 | |||
33 | #include <asm/arch/at91_wdt.h> | ||
34 | |||
35 | #define DRV_NAME "AT91SAM9 Watchdog" | ||
36 | |||
37 | /* AT91SAM9 watchdog runs a 12bit counter @ 256Hz, | ||
38 | * use this to convert a watchdog | ||
39 | * value from/to milliseconds. | ||
40 | */ | ||
41 | #define ms_to_ticks(t) (((t << 8) / 1000) - 1) | ||
42 | #define ticks_to_ms(t) (((t + 1) * 1000) >> 8) | ||
43 | |||
44 | /* Hardware timeout in seconds */ | ||
45 | #define WDT_HW_TIMEOUT 2 | ||
46 | |||
47 | /* Timer heartbeat (500ms) */ | ||
48 | #define WDT_TIMEOUT (HZ/2) | ||
49 | |||
50 | /* User land timeout */ | ||
51 | #define WDT_HEARTBEAT 15 | ||
52 | static int heartbeat = WDT_HEARTBEAT; | ||
53 | module_param(heartbeat, int, 0); | ||
54 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeats in seconds. " | ||
55 | "(default = " __MODULE_STRING(WDT_HEARTBEAT) ")"); | ||
56 | |||
57 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
58 | module_param(nowayout, int, 0); | ||
59 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started " | ||
60 | "(default=" __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
61 | |||
62 | static void at91_ping(unsigned long data); | ||
63 | |||
64 | static struct { | ||
65 | unsigned long next_heartbeat; /* the next_heartbeat for the timer */ | ||
66 | unsigned long open; | ||
67 | char expect_close; | ||
68 | struct timer_list timer; /* The timer that pings the watchdog */ | ||
69 | } at91wdt_private; | ||
70 | |||
71 | /* ......................................................................... */ | ||
72 | |||
73 | |||
74 | /* | ||
75 | * Reload the watchdog timer. (ie, pat the watchdog) | ||
76 | */ | ||
77 | static inline void at91_wdt_reset(void) | ||
78 | { | ||
79 | at91_sys_write(AT91_WDT_CR, AT91_WDT_KEY | AT91_WDT_WDRSTT); | ||
80 | } | ||
81 | |||
82 | /* | ||
83 | * Timer tick | ||
84 | */ | ||
85 | static void at91_ping(unsigned long data) | ||
86 | { | ||
87 | if (time_before(jiffies, at91wdt_private.next_heartbeat) || | ||
88 | (!nowayout && !at91wdt_private.open)) { | ||
89 | at91_wdt_reset(); | ||
90 | mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); | ||
91 | } else | ||
92 | printk(KERN_CRIT DRV_NAME": I will reset your machine !\n"); | ||
93 | } | ||
94 | |||
95 | /* | ||
96 | * Watchdog device is opened, and watchdog starts running. | ||
97 | */ | ||
98 | static int at91_wdt_open(struct inode *inode, struct file *file) | ||
99 | { | ||
100 | if (test_and_set_bit(0, &at91wdt_private.open)) | ||
101 | return -EBUSY; | ||
102 | |||
103 | at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; | ||
104 | mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); | ||
105 | |||
106 | return nonseekable_open(inode, file); | ||
107 | } | ||
108 | |||
109 | /* | ||
110 | * Close the watchdog device. | ||
111 | */ | ||
112 | static int at91_wdt_close(struct inode *inode, struct file *file) | ||
113 | { | ||
114 | clear_bit(0, &at91wdt_private.open); | ||
115 | |||
116 | /* stop internal ping */ | ||
117 | if (!at91wdt_private.expect_close) | ||
118 | del_timer(&at91wdt_private.timer); | ||
119 | |||
120 | at91wdt_private.expect_close = 0; | ||
121 | return 0; | ||
122 | } | ||
123 | |||
124 | /* | ||
125 | * Set the watchdog time interval in 1/256Hz (write-once) | ||
126 | * Counter is 12 bit. | ||
127 | */ | ||
128 | static int at91_wdt_settimeout(unsigned int timeout) | ||
129 | { | ||
130 | unsigned int reg; | ||
131 | unsigned int mr; | ||
132 | |||
133 | /* Check if disabled */ | ||
134 | mr = at91_sys_read(AT91_WDT_MR); | ||
135 | if (mr & AT91_WDT_WDDIS) { | ||
136 | printk(KERN_ERR DRV_NAME": sorry, watchdog is disabled\n"); | ||
137 | return -EIO; | ||
138 | } | ||
139 | |||
140 | /* | ||
141 | * All counting occurs at SLOW_CLOCK / 128 = 256 Hz | ||
142 | * | ||
143 | * Since WDV is a 12-bit counter, the maximum period is | ||
144 | * 4096 / 256 = 16 seconds. | ||
145 | */ | ||
146 | reg = AT91_WDT_WDRSTEN /* causes watchdog reset */ | ||
147 | /* | AT91_WDT_WDRPROC causes processor reset only */ | ||
148 | | AT91_WDT_WDDBGHLT /* disabled in debug mode */ | ||
149 | | AT91_WDT_WDD /* restart at any time */ | ||
150 | | (timeout & AT91_WDT_WDV); /* timer value */ | ||
151 | at91_sys_write(AT91_WDT_MR, reg); | ||
152 | |||
153 | return 0; | ||
154 | } | ||
155 | |||
156 | static const struct watchdog_info at91_wdt_info = { | ||
157 | .identity = DRV_NAME, | ||
158 | .options = WDIOF_SETTIMEOUT | WDIOF_KEEPALIVEPING, | ||
159 | }; | ||
160 | |||
161 | /* | ||
162 | * Handle commands from user-space. | ||
163 | */ | ||
164 | static long at91_wdt_ioctl(struct file *file, | ||
165 | unsigned int cmd, unsigned long arg) | ||
166 | { | ||
167 | void __user *argp = (void __user *)arg; | ||
168 | int __user *p = argp; | ||
169 | int new_value; | ||
170 | |||
171 | switch (cmd) { | ||
172 | case WDIOC_GETSUPPORT: | ||
173 | return copy_to_user(argp, &at91_wdt_info, | ||
174 | sizeof(at91_wdt_info)) ? -EFAULT : 0; | ||
175 | |||
176 | case WDIOC_GETSTATUS: | ||
177 | case WDIOC_GETBOOTSTATUS: | ||
178 | return put_user(0, p); | ||
179 | |||
180 | case WDIOC_KEEPALIVE: | ||
181 | at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; | ||
182 | return 0; | ||
183 | |||
184 | case WDIOC_SETTIMEOUT: | ||
185 | if (get_user(new_value, p)) | ||
186 | return -EFAULT; | ||
187 | |||
188 | heartbeat = new_value; | ||
189 | at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; | ||
190 | |||
191 | return put_user(new_value, p); /* return current value */ | ||
192 | |||
193 | case WDIOC_GETTIMEOUT: | ||
194 | return put_user(heartbeat, p); | ||
195 | } | ||
196 | return -ENOTTY; | ||
197 | } | ||
198 | |||
199 | /* | ||
200 | * Pat the watchdog whenever device is written to. | ||
201 | */ | ||
202 | static ssize_t at91_wdt_write(struct file *file, const char *data, size_t len, | ||
203 | loff_t *ppos) | ||
204 | { | ||
205 | if (!len) | ||
206 | return 0; | ||
207 | |||
208 | /* Scan for magic character */ | ||
209 | if (!nowayout) { | ||
210 | size_t i; | ||
211 | |||
212 | at91wdt_private.expect_close = 0; | ||
213 | |||
214 | for (i = 0; i < len; i++) { | ||
215 | char c; | ||
216 | if (get_user(c, data + i)) | ||
217 | return -EFAULT; | ||
218 | if (c == 'V') { | ||
219 | at91wdt_private.expect_close = 42; | ||
220 | break; | ||
221 | } | ||
222 | } | ||
223 | } | ||
224 | |||
225 | at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; | ||
226 | |||
227 | return len; | ||
228 | } | ||
229 | |||
230 | /* ......................................................................... */ | ||
231 | |||
232 | static const struct file_operations at91wdt_fops = { | ||
233 | .owner = THIS_MODULE, | ||
234 | .llseek = no_llseek, | ||
235 | .unlocked_ioctl = at91_wdt_ioctl, | ||
236 | .open = at91_wdt_open, | ||
237 | .release = at91_wdt_close, | ||
238 | .write = at91_wdt_write, | ||
239 | }; | ||
240 | |||
241 | static struct miscdevice at91wdt_miscdev = { | ||
242 | .minor = WATCHDOG_MINOR, | ||
243 | .name = "watchdog", | ||
244 | .fops = &at91wdt_fops, | ||
245 | }; | ||
246 | |||
247 | static int __init at91wdt_probe(struct platform_device *pdev) | ||
248 | { | ||
249 | int res; | ||
250 | |||
251 | if (at91wdt_miscdev.parent) | ||
252 | return -EBUSY; | ||
253 | at91wdt_miscdev.parent = &pdev->dev; | ||
254 | |||
255 | /* Set watchdog */ | ||
256 | res = at91_wdt_settimeout(ms_to_ticks(WDT_HW_TIMEOUT * 1000)); | ||
257 | if (res) | ||
258 | return res; | ||
259 | |||
260 | res = misc_register(&at91wdt_miscdev); | ||
261 | if (res) | ||
262 | return res; | ||
263 | |||
264 | at91wdt_private.next_heartbeat = jiffies + heartbeat * HZ; | ||
265 | setup_timer(&at91wdt_private.timer, at91_ping, 0); | ||
266 | mod_timer(&at91wdt_private.timer, jiffies + WDT_TIMEOUT); | ||
267 | |||
268 | printk(KERN_INFO DRV_NAME " enabled (heartbeat=%d sec, nowayout=%d)\n", | ||
269 | heartbeat, nowayout); | ||
270 | |||
271 | return 0; | ||
272 | } | ||
273 | |||
274 | static int __exit at91wdt_remove(struct platform_device *pdev) | ||
275 | { | ||
276 | int res; | ||
277 | |||
278 | res = misc_deregister(&at91wdt_miscdev); | ||
279 | if (!res) | ||
280 | at91wdt_miscdev.parent = NULL; | ||
281 | |||
282 | return res; | ||
283 | } | ||
284 | |||
285 | #ifdef CONFIG_PM | ||
286 | |||
287 | static int at91wdt_suspend(struct platform_device *pdev, pm_message_t message) | ||
288 | { | ||
289 | return 0; | ||
290 | } | ||
291 | |||
292 | static int at91wdt_resume(struct platform_device *pdev) | ||
293 | { | ||
294 | return 0; | ||
295 | } | ||
296 | |||
297 | #else | ||
298 | #define at91wdt_suspend NULL | ||
299 | #define at91wdt_resume NULL | ||
300 | #endif | ||
301 | |||
302 | static struct platform_driver at91wdt_driver = { | ||
303 | .remove = __exit_p(at91wdt_remove), | ||
304 | .suspend = at91wdt_suspend, | ||
305 | .resume = at91wdt_resume, | ||
306 | .driver = { | ||
307 | .name = "at91_wdt", | ||
308 | .owner = THIS_MODULE, | ||
309 | }, | ||
310 | }; | ||
311 | |||
312 | static int __init at91sam_wdt_init(void) | ||
313 | { | ||
314 | return platform_driver_probe(&at91wdt_driver, at91wdt_probe); | ||
315 | } | ||
316 | |||
317 | static void __exit at91sam_wdt_exit(void) | ||
318 | { | ||
319 | platform_driver_unregister(&at91wdt_driver); | ||
320 | } | ||
321 | |||
322 | module_init(at91sam_wdt_init); | ||
323 | module_exit(at91sam_wdt_exit); | ||
324 | |||
325 | MODULE_AUTHOR("Renaud CERRATO <r.cerrato@til-technologies.fr>"); | ||
326 | MODULE_DESCRIPTION("Watchdog driver for Atmel AT91SAM9x processors"); | ||
327 | MODULE_LICENSE("GPL"); | ||
328 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/watchdog/cpwd.c b/drivers/watchdog/cpwd.c new file mode 100644 index 000000000000..084dfe9cecfb --- /dev/null +++ b/drivers/watchdog/cpwd.c | |||
@@ -0,0 +1,695 @@ | |||
1 | /* cpwd.c - driver implementation for hardware watchdog | ||
2 | * timers found on Sun Microsystems CP1400 and CP1500 boards. | ||
3 | * | ||
4 | * This device supports both the generic Linux watchdog | ||
5 | * interface and Solaris-compatible ioctls as best it is | ||
6 | * able. | ||
7 | * | ||
8 | * NOTE: CP1400 systems appear to have a defective intr_mask | ||
9 | * register on the PLD, preventing the disabling of | ||
10 | * timer interrupts. We use a timer to periodically | ||
11 | * reset 'stopped' watchdogs on affected platforms. | ||
12 | * | ||
13 | * Copyright (c) 2000 Eric Brower (ebrower@usa.net) | ||
14 | * Copyright (C) 2008 David S. Miller <davem@davemloft.net> | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/module.h> | ||
19 | #include <linux/fs.h> | ||
20 | #include <linux/errno.h> | ||
21 | #include <linux/major.h> | ||
22 | #include <linux/init.h> | ||
23 | #include <linux/miscdevice.h> | ||
24 | #include <linux/interrupt.h> | ||
25 | #include <linux/ioport.h> | ||
26 | #include <linux/timer.h> | ||
27 | #include <linux/smp_lock.h> | ||
28 | #include <linux/io.h> | ||
29 | #include <linux/of.h> | ||
30 | #include <linux/of_device.h> | ||
31 | |||
32 | #include <asm/irq.h> | ||
33 | #include <asm/uaccess.h> | ||
34 | |||
35 | #include <asm/watchdog.h> | ||
36 | |||
37 | #define DRIVER_NAME "cpwd" | ||
38 | #define PFX DRIVER_NAME ": " | ||
39 | |||
40 | #define WD_OBPNAME "watchdog" | ||
41 | #define WD_BADMODEL "SUNW,501-5336" | ||
42 | #define WD_BTIMEOUT (jiffies + (HZ * 1000)) | ||
43 | #define WD_BLIMIT 0xFFFF | ||
44 | |||
45 | #define WD0_MINOR 212 | ||
46 | #define WD1_MINOR 213 | ||
47 | #define WD2_MINOR 214 | ||
48 | |||
49 | /* Internal driver definitions. */ | ||
50 | #define WD0_ID 0 | ||
51 | #define WD1_ID 1 | ||
52 | #define WD2_ID 2 | ||
53 | #define WD_NUMDEVS 3 | ||
54 | |||
55 | #define WD_INTR_OFF 0 | ||
56 | #define WD_INTR_ON 1 | ||
57 | |||
58 | #define WD_STAT_INIT 0x01 /* Watchdog timer is initialized */ | ||
59 | #define WD_STAT_BSTOP 0x02 /* Watchdog timer is brokenstopped */ | ||
60 | #define WD_STAT_SVCD 0x04 /* Watchdog interrupt occurred */ | ||
61 | |||
62 | /* Register value definitions | ||
63 | */ | ||
64 | #define WD0_INTR_MASK 0x01 /* Watchdog device interrupt masks */ | ||
65 | #define WD1_INTR_MASK 0x02 | ||
66 | #define WD2_INTR_MASK 0x04 | ||
67 | |||
68 | #define WD_S_RUNNING 0x01 /* Watchdog device status running */ | ||
69 | #define WD_S_EXPIRED 0x02 /* Watchdog device status expired */ | ||
70 | |||
71 | struct cpwd { | ||
72 | void __iomem *regs; | ||
73 | spinlock_t lock; | ||
74 | |||
75 | unsigned int irq; | ||
76 | |||
77 | unsigned long timeout; | ||
78 | bool enabled; | ||
79 | bool reboot; | ||
80 | bool broken; | ||
81 | bool initialized; | ||
82 | |||
83 | struct { | ||
84 | struct miscdevice misc; | ||
85 | void __iomem *regs; | ||
86 | u8 intr_mask; | ||
87 | u8 runstatus; | ||
88 | u16 timeout; | ||
89 | } devs[WD_NUMDEVS]; | ||
90 | }; | ||
91 | |||
92 | static struct cpwd *cpwd_device; | ||
93 | |||
94 | /* Sun uses Altera PLD EPF8820ATC144-4 | ||
95 | * providing three hardware watchdogs: | ||
96 | * | ||
97 | * 1) RIC - sends an interrupt when triggered | ||
98 | * 2) XIR - asserts XIR_B_RESET when triggered, resets CPU | ||
99 | * 3) POR - asserts POR_B_RESET when triggered, resets CPU, backplane, board | ||
100 | * | ||
101 | *** Timer register block definition (struct wd_timer_regblk) | ||
102 | * | ||
103 | * dcntr and limit registers (halfword access): | ||
104 | * ------------------- | ||
105 | * | 15 | ...| 1 | 0 | | ||
106 | * ------------------- | ||
107 | * |- counter val -| | ||
108 | * ------------------- | ||
109 | * dcntr - Current 16-bit downcounter value. | ||
110 | * When downcounter reaches '0' watchdog expires. | ||
111 | * Reading this register resets downcounter with 'limit' value. | ||
112 | * limit - 16-bit countdown value in 1/10th second increments. | ||
113 | * Writing this register begins countdown with input value. | ||
114 | * Reading from this register does not affect counter. | ||
115 | * NOTES: After watchdog reset, dcntr and limit contain '1' | ||
116 | * | ||
117 | * status register (byte access): | ||
118 | * --------------------------- | ||
119 | * | 7 | ... | 2 | 1 | 0 | | ||
120 | * --------------+------------ | ||
121 | * |- UNUSED -| EXP | RUN | | ||
122 | * --------------------------- | ||
123 | * status- Bit 0 - Watchdog is running | ||
124 | * Bit 1 - Watchdog has expired | ||
125 | * | ||
126 | *** PLD register block definition (struct wd_pld_regblk) | ||
127 | * | ||
128 | * intr_mask register (byte access): | ||
129 | * --------------------------------- | ||
130 | * | 7 | ... | 3 | 2 | 1 | 0 | | ||
131 | * +-------------+------------------ | ||
132 | * |- UNUSED -| WD3 | WD2 | WD1 | | ||
133 | * --------------------------------- | ||
134 | * WD3 - 1 == Interrupt disabled for watchdog 3 | ||
135 | * WD2 - 1 == Interrupt disabled for watchdog 2 | ||
136 | * WD1 - 1 == Interrupt disabled for watchdog 1 | ||
137 | * | ||
138 | * pld_status register (byte access): | ||
139 | * UNKNOWN, MAGICAL MYSTERY REGISTER | ||
140 | * | ||
141 | */ | ||
142 | #define WD_TIMER_REGSZ 16 | ||
143 | #define WD0_OFF 0 | ||
144 | #define WD1_OFF (WD_TIMER_REGSZ * 1) | ||
145 | #define WD2_OFF (WD_TIMER_REGSZ * 2) | ||
146 | #define PLD_OFF (WD_TIMER_REGSZ * 3) | ||
147 | |||
148 | #define WD_DCNTR 0x00 | ||
149 | #define WD_LIMIT 0x04 | ||
150 | #define WD_STATUS 0x08 | ||
151 | |||
152 | #define PLD_IMASK (PLD_OFF + 0x00) | ||
153 | #define PLD_STATUS (PLD_OFF + 0x04) | ||
154 | |||
155 | static struct timer_list cpwd_timer; | ||
156 | |||
157 | static int wd0_timeout = 0; | ||
158 | static int wd1_timeout = 0; | ||
159 | static int wd2_timeout = 0; | ||
160 | |||
161 | module_param (wd0_timeout, int, 0); | ||
162 | MODULE_PARM_DESC(wd0_timeout, "Default watchdog0 timeout in 1/10secs"); | ||
163 | module_param (wd1_timeout, int, 0); | ||
164 | MODULE_PARM_DESC(wd1_timeout, "Default watchdog1 timeout in 1/10secs"); | ||
165 | module_param (wd2_timeout, int, 0); | ||
166 | MODULE_PARM_DESC(wd2_timeout, "Default watchdog2 timeout in 1/10secs"); | ||
167 | |||
168 | MODULE_AUTHOR("Eric Brower <ebrower@usa.net>"); | ||
169 | MODULE_DESCRIPTION("Hardware watchdog driver for Sun Microsystems CP1400/1500"); | ||
170 | MODULE_LICENSE("GPL"); | ||
171 | MODULE_SUPPORTED_DEVICE("watchdog"); | ||
172 | |||
173 | static void cpwd_writew(u16 val, void __iomem *addr) | ||
174 | { | ||
175 | writew(cpu_to_le16(val), addr); | ||
176 | } | ||
177 | static u16 cpwd_readw(void __iomem *addr) | ||
178 | { | ||
179 | u16 val = readw(addr); | ||
180 | |||
181 | return le16_to_cpu(val); | ||
182 | } | ||
183 | |||
184 | static void cpwd_writeb(u8 val, void __iomem *addr) | ||
185 | { | ||
186 | writeb(val, addr); | ||
187 | } | ||
188 | |||
189 | static u8 cpwd_readb(void __iomem *addr) | ||
190 | { | ||
191 | return readb(addr); | ||
192 | } | ||
193 | |||
194 | /* Enable or disable watchdog interrupts | ||
195 | * Because of the CP1400 defect this should only be | ||
196 | * called during initialzation or by wd_[start|stop]timer() | ||
197 | * | ||
198 | * index - sub-device index, or -1 for 'all' | ||
199 | * enable - non-zero to enable interrupts, zero to disable | ||
200 | */ | ||
201 | static void cpwd_toggleintr(struct cpwd *p, int index, int enable) | ||
202 | { | ||
203 | unsigned char curregs = cpwd_readb(p->regs + PLD_IMASK); | ||
204 | unsigned char setregs = | ||
205 | (index == -1) ? | ||
206 | (WD0_INTR_MASK | WD1_INTR_MASK | WD2_INTR_MASK) : | ||
207 | (p->devs[index].intr_mask); | ||
208 | |||
209 | if (enable == WD_INTR_ON) | ||
210 | curregs &= ~setregs; | ||
211 | else | ||
212 | curregs |= setregs; | ||
213 | |||
214 | cpwd_writeb(curregs, p->regs + PLD_IMASK); | ||
215 | } | ||
216 | |||
217 | /* Restarts timer with maximum limit value and | ||
218 | * does not unset 'brokenstop' value. | ||
219 | */ | ||
220 | static void cpwd_resetbrokentimer(struct cpwd *p, int index) | ||
221 | { | ||
222 | cpwd_toggleintr(p, index, WD_INTR_ON); | ||
223 | cpwd_writew(WD_BLIMIT, p->devs[index].regs + WD_LIMIT); | ||
224 | } | ||
225 | |||
226 | /* Timer method called to reset stopped watchdogs-- | ||
227 | * because of the PLD bug on CP1400, we cannot mask | ||
228 | * interrupts within the PLD so me must continually | ||
229 | * reset the timers ad infinitum. | ||
230 | */ | ||
231 | static void cpwd_brokentimer(unsigned long data) | ||
232 | { | ||
233 | struct cpwd *p = (struct cpwd *) data; | ||
234 | int id, tripped = 0; | ||
235 | |||
236 | /* kill a running timer instance, in case we | ||
237 | * were called directly instead of by kernel timer | ||
238 | */ | ||
239 | if (timer_pending(&cpwd_timer)) | ||
240 | del_timer(&cpwd_timer); | ||
241 | |||
242 | for (id = 0; id < WD_NUMDEVS; id++) { | ||
243 | if (p->devs[id].runstatus & WD_STAT_BSTOP) { | ||
244 | ++tripped; | ||
245 | cpwd_resetbrokentimer(p, id); | ||
246 | } | ||
247 | } | ||
248 | |||
249 | if (tripped) { | ||
250 | /* there is at least one timer brokenstopped-- reschedule */ | ||
251 | cpwd_timer.expires = WD_BTIMEOUT; | ||
252 | add_timer(&cpwd_timer); | ||
253 | } | ||
254 | } | ||
255 | |||
256 | /* Reset countdown timer with 'limit' value and continue countdown. | ||
257 | * This will not start a stopped timer. | ||
258 | */ | ||
259 | static void cpwd_pingtimer(struct cpwd *p, int index) | ||
260 | { | ||
261 | if (cpwd_readb(p->devs[index].regs + WD_STATUS) & WD_S_RUNNING) | ||
262 | cpwd_readw(p->devs[index].regs + WD_DCNTR); | ||
263 | } | ||
264 | |||
265 | /* Stop a running watchdog timer-- the timer actually keeps | ||
266 | * running, but the interrupt is masked so that no action is | ||
267 | * taken upon expiration. | ||
268 | */ | ||
269 | static void cpwd_stoptimer(struct cpwd *p, int index) | ||
270 | { | ||
271 | if (cpwd_readb(p->devs[index].regs + WD_STATUS) & WD_S_RUNNING) { | ||
272 | cpwd_toggleintr(p, index, WD_INTR_OFF); | ||
273 | |||
274 | if (p->broken) { | ||
275 | p->devs[index].runstatus |= WD_STAT_BSTOP; | ||
276 | cpwd_brokentimer((unsigned long) p); | ||
277 | } | ||
278 | } | ||
279 | } | ||
280 | |||
281 | /* Start a watchdog timer with the specified limit value | ||
282 | * If the watchdog is running, it will be restarted with | ||
283 | * the provided limit value. | ||
284 | * | ||
285 | * This function will enable interrupts on the specified | ||
286 | * watchdog. | ||
287 | */ | ||
288 | static void cpwd_starttimer(struct cpwd *p, int index) | ||
289 | { | ||
290 | if (p->broken) | ||
291 | p->devs[index].runstatus &= ~WD_STAT_BSTOP; | ||
292 | |||
293 | p->devs[index].runstatus &= ~WD_STAT_SVCD; | ||
294 | |||
295 | cpwd_writew(p->devs[index].timeout, p->devs[index].regs + WD_LIMIT); | ||
296 | cpwd_toggleintr(p, index, WD_INTR_ON); | ||
297 | } | ||
298 | |||
299 | static int cpwd_getstatus(struct cpwd *p, int index) | ||
300 | { | ||
301 | unsigned char stat = cpwd_readb(p->devs[index].regs + WD_STATUS); | ||
302 | unsigned char intr = cpwd_readb(p->devs[index].regs + PLD_IMASK); | ||
303 | unsigned char ret = WD_STOPPED; | ||
304 | |||
305 | /* determine STOPPED */ | ||
306 | if (!stat) | ||
307 | return ret; | ||
308 | |||
309 | /* determine EXPIRED vs FREERUN vs RUNNING */ | ||
310 | else if (WD_S_EXPIRED & stat) { | ||
311 | ret = WD_EXPIRED; | ||
312 | } else if(WD_S_RUNNING & stat) { | ||
313 | if (intr & p->devs[index].intr_mask) { | ||
314 | ret = WD_FREERUN; | ||
315 | } else { | ||
316 | /* Fudge WD_EXPIRED status for defective CP1400-- | ||
317 | * IF timer is running | ||
318 | * AND brokenstop is set | ||
319 | * AND an interrupt has been serviced | ||
320 | * we are WD_EXPIRED. | ||
321 | * | ||
322 | * IF timer is running | ||
323 | * AND brokenstop is set | ||
324 | * AND no interrupt has been serviced | ||
325 | * we are WD_FREERUN. | ||
326 | */ | ||
327 | if (p->broken && | ||
328 | (p->devs[index].runstatus & WD_STAT_BSTOP)) { | ||
329 | if (p->devs[index].runstatus & WD_STAT_SVCD) { | ||
330 | ret = WD_EXPIRED; | ||
331 | } else { | ||
332 | /* we could as well pretend we are expired */ | ||
333 | ret = WD_FREERUN; | ||
334 | } | ||
335 | } else { | ||
336 | ret = WD_RUNNING; | ||
337 | } | ||
338 | } | ||
339 | } | ||
340 | |||
341 | /* determine SERVICED */ | ||
342 | if (p->devs[index].runstatus & WD_STAT_SVCD) | ||
343 | ret |= WD_SERVICED; | ||
344 | |||
345 | return(ret); | ||
346 | } | ||
347 | |||
348 | static irqreturn_t cpwd_interrupt(int irq, void *dev_id) | ||
349 | { | ||
350 | struct cpwd *p = dev_id; | ||
351 | |||
352 | /* Only WD0 will interrupt-- others are NMI and we won't | ||
353 | * see them here.... | ||
354 | */ | ||
355 | spin_lock_irq(&p->lock); | ||
356 | |||
357 | cpwd_stoptimer(p, WD0_ID); | ||
358 | p->devs[WD0_ID].runstatus |= WD_STAT_SVCD; | ||
359 | |||
360 | spin_unlock_irq(&p->lock); | ||
361 | |||
362 | return IRQ_HANDLED; | ||
363 | } | ||
364 | |||
365 | static int cpwd_open(struct inode *inode, struct file *f) | ||
366 | { | ||
367 | struct cpwd *p = cpwd_device; | ||
368 | |||
369 | lock_kernel(); | ||
370 | switch(iminor(inode)) { | ||
371 | case WD0_MINOR: | ||
372 | case WD1_MINOR: | ||
373 | case WD2_MINOR: | ||
374 | break; | ||
375 | |||
376 | default: | ||
377 | unlock_kernel(); | ||
378 | return -ENODEV; | ||
379 | } | ||
380 | |||
381 | /* Register IRQ on first open of device */ | ||
382 | if (!p->initialized) { | ||
383 | if (request_irq(p->irq, &cpwd_interrupt, | ||
384 | IRQF_SHARED, DRIVER_NAME, p)) { | ||
385 | printk(KERN_ERR PFX "Cannot register IRQ %d\n", | ||
386 | p->irq); | ||
387 | unlock_kernel(); | ||
388 | return -EBUSY; | ||
389 | } | ||
390 | p->initialized = true; | ||
391 | } | ||
392 | |||
393 | unlock_kernel(); | ||
394 | |||
395 | return nonseekable_open(inode, f); | ||
396 | } | ||
397 | |||
398 | static int cpwd_release(struct inode *inode, struct file *file) | ||
399 | { | ||
400 | return 0; | ||
401 | } | ||
402 | |||
403 | static int cpwd_ioctl(struct inode *inode, struct file *file, | ||
404 | unsigned int cmd, unsigned long arg) | ||
405 | { | ||
406 | static struct watchdog_info info = { | ||
407 | .options = WDIOF_SETTIMEOUT, | ||
408 | .firmware_version = 1, | ||
409 | .identity = DRIVER_NAME, | ||
410 | }; | ||
411 | void __user *argp = (void __user *)arg; | ||
412 | int index = iminor(inode) - WD0_MINOR; | ||
413 | struct cpwd *p = cpwd_device; | ||
414 | int setopt = 0; | ||
415 | |||
416 | switch (cmd) { | ||
417 | /* Generic Linux IOCTLs */ | ||
418 | case WDIOC_GETSUPPORT: | ||
419 | if (copy_to_user(argp, &info, sizeof(struct watchdog_info))) | ||
420 | return -EFAULT; | ||
421 | break; | ||
422 | |||
423 | case WDIOC_GETSTATUS: | ||
424 | case WDIOC_GETBOOTSTATUS: | ||
425 | if (put_user(0, (int __user *)argp)) | ||
426 | return -EFAULT; | ||
427 | break; | ||
428 | |||
429 | case WDIOC_KEEPALIVE: | ||
430 | cpwd_pingtimer(p, index); | ||
431 | break; | ||
432 | |||
433 | case WDIOC_SETOPTIONS: | ||
434 | if (copy_from_user(&setopt, argp, sizeof(unsigned int))) | ||
435 | return -EFAULT; | ||
436 | |||
437 | if (setopt & WDIOS_DISABLECARD) { | ||
438 | if (p->enabled) | ||
439 | return -EINVAL; | ||
440 | cpwd_stoptimer(p, index); | ||
441 | } else if (setopt & WDIOS_ENABLECARD) { | ||
442 | cpwd_starttimer(p, index); | ||
443 | } else { | ||
444 | return -EINVAL; | ||
445 | } | ||
446 | break; | ||
447 | |||
448 | /* Solaris-compatible IOCTLs */ | ||
449 | case WIOCGSTAT: | ||
450 | setopt = cpwd_getstatus(p, index); | ||
451 | if (copy_to_user(argp, &setopt, sizeof(unsigned int))) | ||
452 | return -EFAULT; | ||
453 | break; | ||
454 | |||
455 | case WIOCSTART: | ||
456 | cpwd_starttimer(p, index); | ||
457 | break; | ||
458 | |||
459 | case WIOCSTOP: | ||
460 | if (p->enabled) | ||
461 | return(-EINVAL); | ||
462 | |||
463 | cpwd_stoptimer(p, index); | ||
464 | break; | ||
465 | |||
466 | default: | ||
467 | return -EINVAL; | ||
468 | } | ||
469 | |||
470 | return 0; | ||
471 | } | ||
472 | |||
473 | static long cpwd_compat_ioctl(struct file *file, unsigned int cmd, | ||
474 | unsigned long arg) | ||
475 | { | ||
476 | int rval = -ENOIOCTLCMD; | ||
477 | |||
478 | switch (cmd) { | ||
479 | /* solaris ioctls are specific to this driver */ | ||
480 | case WIOCSTART: | ||
481 | case WIOCSTOP: | ||
482 | case WIOCGSTAT: | ||
483 | lock_kernel(); | ||
484 | rval = cpwd_ioctl(file->f_path.dentry->d_inode, file, cmd, arg); | ||
485 | unlock_kernel(); | ||
486 | break; | ||
487 | |||
488 | /* everything else is handled by the generic compat layer */ | ||
489 | default: | ||
490 | break; | ||
491 | } | ||
492 | |||
493 | return rval; | ||
494 | } | ||
495 | |||
496 | static ssize_t cpwd_write(struct file *file, const char __user *buf, | ||
497 | size_t count, loff_t *ppos) | ||
498 | { | ||
499 | struct inode *inode = file->f_path.dentry->d_inode; | ||
500 | struct cpwd *p = cpwd_device; | ||
501 | int index = iminor(inode); | ||
502 | |||
503 | if (count) { | ||
504 | cpwd_pingtimer(p, index); | ||
505 | return 1; | ||
506 | } | ||
507 | |||
508 | return 0; | ||
509 | } | ||
510 | |||
511 | static ssize_t cpwd_read(struct file * file, char __user *buffer, | ||
512 | size_t count, loff_t *ppos) | ||
513 | { | ||
514 | return -EINVAL; | ||
515 | } | ||
516 | |||
517 | static const struct file_operations cpwd_fops = { | ||
518 | .owner = THIS_MODULE, | ||
519 | .ioctl = cpwd_ioctl, | ||
520 | .compat_ioctl = cpwd_compat_ioctl, | ||
521 | .open = cpwd_open, | ||
522 | .write = cpwd_write, | ||
523 | .read = cpwd_read, | ||
524 | .release = cpwd_release, | ||
525 | }; | ||
526 | |||
527 | static int __devinit cpwd_probe(struct of_device *op, | ||
528 | const struct of_device_id *match) | ||
529 | { | ||
530 | struct device_node *options; | ||
531 | const char *str_prop; | ||
532 | const void *prop_val; | ||
533 | int i, err = -EINVAL; | ||
534 | struct cpwd *p; | ||
535 | |||
536 | if (cpwd_device) | ||
537 | return -EINVAL; | ||
538 | |||
539 | p = kzalloc(sizeof(*p), GFP_KERNEL); | ||
540 | err = -ENOMEM; | ||
541 | if (!p) { | ||
542 | printk(KERN_ERR PFX "Unable to allocate struct cpwd.\n"); | ||
543 | goto out; | ||
544 | } | ||
545 | |||
546 | p->irq = op->irqs[0]; | ||
547 | |||
548 | spin_lock_init(&p->lock); | ||
549 | |||
550 | p->regs = of_ioremap(&op->resource[0], 0, | ||
551 | 4 * WD_TIMER_REGSZ, DRIVER_NAME); | ||
552 | if (!p->regs) { | ||
553 | printk(KERN_ERR PFX "Unable to map registers.\n"); | ||
554 | goto out_free; | ||
555 | } | ||
556 | |||
557 | options = of_find_node_by_path("/options"); | ||
558 | err = -ENODEV; | ||
559 | if (!options) { | ||
560 | printk(KERN_ERR PFX "Unable to find /options node.\n"); | ||
561 | goto out_iounmap; | ||
562 | } | ||
563 | |||
564 | prop_val = of_get_property(options, "watchdog-enable?", NULL); | ||
565 | p->enabled = (prop_val ? true : false); | ||
566 | |||
567 | prop_val = of_get_property(options, "watchdog-reboot?", NULL); | ||
568 | p->reboot = (prop_val ? true : false); | ||
569 | |||
570 | str_prop = of_get_property(options, "watchdog-timeout", NULL); | ||
571 | if (str_prop) | ||
572 | p->timeout = simple_strtoul(str_prop, NULL, 10); | ||
573 | |||
574 | /* CP1400s seem to have broken PLD implementations-- the | ||
575 | * interrupt_mask register cannot be written, so no timer | ||
576 | * interrupts can be masked within the PLD. | ||
577 | */ | ||
578 | str_prop = of_get_property(op->node, "model", NULL); | ||
579 | p->broken = (str_prop && !strcmp(str_prop, WD_BADMODEL)); | ||
580 | |||
581 | if (!p->enabled) | ||
582 | cpwd_toggleintr(p, -1, WD_INTR_OFF); | ||
583 | |||
584 | for (i = 0; i < WD_NUMDEVS; i++) { | ||
585 | static const char *cpwd_names[] = { "RIC", "XIR", "POR" }; | ||
586 | static int *parms[] = { &wd0_timeout, | ||
587 | &wd1_timeout, | ||
588 | &wd2_timeout }; | ||
589 | struct miscdevice *mp = &p->devs[i].misc; | ||
590 | |||
591 | mp->minor = WD0_MINOR + i; | ||
592 | mp->name = cpwd_names[i]; | ||
593 | mp->fops = &cpwd_fops; | ||
594 | |||
595 | p->devs[i].regs = p->regs + (i * WD_TIMER_REGSZ); | ||
596 | p->devs[i].intr_mask = (WD0_INTR_MASK << i); | ||
597 | p->devs[i].runstatus &= ~WD_STAT_BSTOP; | ||
598 | p->devs[i].runstatus |= WD_STAT_INIT; | ||
599 | p->devs[i].timeout = p->timeout; | ||
600 | if (*parms[i]) | ||
601 | p->devs[i].timeout = *parms[i]; | ||
602 | |||
603 | err = misc_register(&p->devs[i].misc); | ||
604 | if (err) { | ||
605 | printk(KERN_ERR "Could not register misc device for " | ||
606 | "dev %d\n", i); | ||
607 | goto out_unregister; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | if (p->broken) { | ||
612 | init_timer(&cpwd_timer); | ||
613 | cpwd_timer.function = cpwd_brokentimer; | ||
614 | cpwd_timer.data = (unsigned long) p; | ||
615 | cpwd_timer.expires = WD_BTIMEOUT; | ||
616 | |||
617 | printk(KERN_INFO PFX "PLD defect workaround enabled for " | ||
618 | "model " WD_BADMODEL ".\n"); | ||
619 | } | ||
620 | |||
621 | dev_set_drvdata(&op->dev, p); | ||
622 | cpwd_device = p; | ||
623 | err = 0; | ||
624 | |||
625 | out: | ||
626 | return err; | ||
627 | |||
628 | out_unregister: | ||
629 | for (i--; i >= 0; i--) | ||
630 | misc_deregister(&p->devs[i].misc); | ||
631 | |||
632 | out_iounmap: | ||
633 | of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ); | ||
634 | |||
635 | out_free: | ||
636 | kfree(p); | ||
637 | goto out; | ||
638 | } | ||
639 | |||
640 | static int __devexit cpwd_remove(struct of_device *op) | ||
641 | { | ||
642 | struct cpwd *p = dev_get_drvdata(&op->dev); | ||
643 | int i; | ||
644 | |||
645 | for (i = 0; i < 4; i++) { | ||
646 | misc_deregister(&p->devs[i].misc); | ||
647 | |||
648 | if (!p->enabled) { | ||
649 | cpwd_stoptimer(p, i); | ||
650 | if (p->devs[i].runstatus & WD_STAT_BSTOP) | ||
651 | cpwd_resetbrokentimer(p, i); | ||
652 | } | ||
653 | } | ||
654 | |||
655 | if (p->broken) | ||
656 | del_timer_sync(&cpwd_timer); | ||
657 | |||
658 | if (p->initialized) | ||
659 | free_irq(p->irq, p); | ||
660 | |||
661 | of_iounmap(&op->resource[0], p->regs, 4 * WD_TIMER_REGSZ); | ||
662 | kfree(p); | ||
663 | |||
664 | cpwd_device = NULL; | ||
665 | |||
666 | return 0; | ||
667 | } | ||
668 | |||
669 | static const struct of_device_id cpwd_match[] = { | ||
670 | { | ||
671 | .name = "watchdog", | ||
672 | }, | ||
673 | {}, | ||
674 | }; | ||
675 | MODULE_DEVICE_TABLE(of, cpwd_match); | ||
676 | |||
677 | static struct of_platform_driver cpwd_driver = { | ||
678 | .name = DRIVER_NAME, | ||
679 | .match_table = cpwd_match, | ||
680 | .probe = cpwd_probe, | ||
681 | .remove = __devexit_p(cpwd_remove), | ||
682 | }; | ||
683 | |||
684 | static int __init cpwd_init(void) | ||
685 | { | ||
686 | return of_register_driver(&cpwd_driver, &of_bus_type); | ||
687 | } | ||
688 | |||
689 | static void __exit cpwd_exit(void) | ||
690 | { | ||
691 | of_unregister_driver(&cpwd_driver); | ||
692 | } | ||
693 | |||
694 | module_init(cpwd_init); | ||
695 | module_exit(cpwd_exit); | ||
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c new file mode 100644 index 000000000000..afb8af397a9f --- /dev/null +++ b/drivers/watchdog/it87_wdt.c | |||
@@ -0,0 +1,725 @@ | |||
1 | /* | ||
2 | * Watchdog Timer Driver | ||
3 | * for ITE IT87xx Environment Control - Low Pin Count Input / Output | ||
4 | * | ||
5 | * (c) Copyright 2007 Oliver Schuster <olivers137@aol.com> | ||
6 | * | ||
7 | * Based on softdog.c by Alan Cox, | ||
8 | * 83977f_wdt.c by Jose Goncalves, | ||
9 | * it87.c by Chris Gauthron, Jean Delvare | ||
10 | * | ||
11 | * Data-sheets: Publicly available at the ITE website | ||
12 | * http://www.ite.com.tw/ | ||
13 | * | ||
14 | * Support of the watchdog timers, which are available on | ||
15 | * IT8716, IT8718, IT8726 and IT8712 (J,K version). | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or | ||
18 | * modify it under the terms of the GNU General Public License | ||
19 | * as published by the Free Software Foundation; either version | ||
20 | * 2 of the License, or (at your option) any later version. | ||
21 | * | ||
22 | * This program is distributed in the hope that it will be useful, | ||
23 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
24 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
25 | * GNU General Public License for more details. | ||
26 | * | ||
27 | * You should have received a copy of the GNU General Public License | ||
28 | * along with this program; if not, write to the Free Software | ||
29 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | ||
30 | */ | ||
31 | |||
32 | #include <linux/module.h> | ||
33 | #include <linux/moduleparam.h> | ||
34 | #include <linux/types.h> | ||
35 | #include <linux/kernel.h> | ||
36 | #include <linux/fs.h> | ||
37 | #include <linux/miscdevice.h> | ||
38 | #include <linux/init.h> | ||
39 | #include <linux/ioport.h> | ||
40 | #include <linux/watchdog.h> | ||
41 | #include <linux/notifier.h> | ||
42 | #include <linux/reboot.h> | ||
43 | #include <linux/uaccess.h> | ||
44 | #include <linux/io.h> | ||
45 | |||
46 | #include <asm/system.h> | ||
47 | |||
48 | #define WATCHDOG_VERSION "1.12" | ||
49 | #define WATCHDOG_NAME "IT87 WDT" | ||
50 | #define PFX WATCHDOG_NAME ": " | ||
51 | #define DRIVER_VERSION WATCHDOG_NAME " driver, v" WATCHDOG_VERSION "\n" | ||
52 | #define WD_MAGIC 'V' | ||
53 | |||
54 | /* Defaults for Module Parameter */ | ||
55 | #define DEFAULT_NOGAMEPORT 0 | ||
56 | #define DEFAULT_EXCLUSIVE 1 | ||
57 | #define DEFAULT_TIMEOUT 60 | ||
58 | #define DEFAULT_TESTMODE 0 | ||
59 | #define DEFAULT_NOWAYOUT WATCHDOG_NOWAYOUT | ||
60 | |||
61 | /* IO Ports */ | ||
62 | #define REG 0x2e | ||
63 | #define VAL 0x2f | ||
64 | |||
65 | /* Logical device Numbers LDN */ | ||
66 | #define GPIO 0x07 | ||
67 | #define GAMEPORT 0x09 | ||
68 | #define CIR 0x0a | ||
69 | |||
70 | /* Configuration Registers and Functions */ | ||
71 | #define LDNREG 0x07 | ||
72 | #define CHIPID 0x20 | ||
73 | #define CHIPREV 0x22 | ||
74 | #define ACTREG 0x30 | ||
75 | #define BASEREG 0x60 | ||
76 | |||
77 | /* Chip Id numbers */ | ||
78 | #define NO_DEV_ID 0xffff | ||
79 | #define IT8705_ID 0x8705 | ||
80 | #define IT8712_ID 0x8712 | ||
81 | #define IT8716_ID 0x8716 | ||
82 | #define IT8718_ID 0x8718 | ||
83 | #define IT8726_ID 0x8726 /* the data sheet suggest wrongly 0x8716 */ | ||
84 | |||
85 | /* GPIO Configuration Registers LDN=0x07 */ | ||
86 | #define WDTCTRL 0x71 | ||
87 | #define WDTCFG 0x72 | ||
88 | #define WDTVALLSB 0x73 | ||
89 | #define WDTVALMSB 0x74 | ||
90 | |||
91 | /* GPIO Bits WDTCTRL */ | ||
92 | #define WDT_CIRINT 0x80 | ||
93 | #define WDT_MOUSEINT 0x40 | ||
94 | #define WDT_KYBINT 0x20 | ||
95 | #define WDT_GAMEPORT 0x10 /* not it8718 */ | ||
96 | #define WDT_FORCE 0x02 | ||
97 | #define WDT_ZERO 0x01 | ||
98 | |||
99 | /* GPIO Bits WDTCFG */ | ||
100 | #define WDT_TOV1 0x80 | ||
101 | #define WDT_KRST 0x40 | ||
102 | #define WDT_TOVE 0x20 | ||
103 | #define WDT_PWROK 0x10 | ||
104 | #define WDT_INT_MASK 0x0f | ||
105 | |||
106 | /* CIR Configuration Register LDN=0x0a */ | ||
107 | #define CIR_ILS 0x70 | ||
108 | |||
109 | /* The default Base address is not always available, we use this */ | ||
110 | #define CIR_BASE 0x0208 | ||
111 | |||
112 | /* CIR Controller */ | ||
113 | #define CIR_DR(b) (b) | ||
114 | #define CIR_IER(b) (b + 1) | ||
115 | #define CIR_RCR(b) (b + 2) | ||
116 | #define CIR_TCR1(b) (b + 3) | ||
117 | #define CIR_TCR2(b) (b + 4) | ||
118 | #define CIR_TSR(b) (b + 5) | ||
119 | #define CIR_RSR(b) (b + 6) | ||
120 | #define CIR_BDLR(b) (b + 5) | ||
121 | #define CIR_BDHR(b) (b + 6) | ||
122 | #define CIR_IIR(b) (b + 7) | ||
123 | |||
124 | /* Default Base address of Game port */ | ||
125 | #define GP_BASE_DEFAULT 0x0201 | ||
126 | |||
127 | /* wdt_status */ | ||
128 | #define WDTS_TIMER_RUN 0 | ||
129 | #define WDTS_DEV_OPEN 1 | ||
130 | #define WDTS_KEEPALIVE 2 | ||
131 | #define WDTS_LOCKED 3 | ||
132 | #define WDTS_USE_GP 4 | ||
133 | #define WDTS_EXPECTED 5 | ||
134 | |||
135 | static unsigned int base, gpact, ciract; | ||
136 | static unsigned long wdt_status; | ||
137 | static DEFINE_SPINLOCK(spinlock); | ||
138 | |||
139 | static int nogameport = DEFAULT_NOGAMEPORT; | ||
140 | static int exclusive = DEFAULT_EXCLUSIVE; | ||
141 | static int timeout = DEFAULT_TIMEOUT; | ||
142 | static int testmode = DEFAULT_TESTMODE; | ||
143 | static int nowayout = DEFAULT_NOWAYOUT; | ||
144 | |||
145 | module_param(nogameport, int, 0); | ||
146 | MODULE_PARM_DESC(nogameport, "Forbid the activation of game port, default=" | ||
147 | __MODULE_STRING(DEFAULT_NOGAMEPORT)); | ||
148 | module_param(exclusive, int, 0); | ||
149 | MODULE_PARM_DESC(exclusive, "Watchdog exclusive device open, default=" | ||
150 | __MODULE_STRING(DEFAULT_EXCLUSIVE)); | ||
151 | module_param(timeout, int, 0); | ||
152 | MODULE_PARM_DESC(timeout, "Watchdog timeout in seconds, default=" | ||
153 | __MODULE_STRING(DEFAULT_TIMEOUT)); | ||
154 | module_param(testmode, int, 0); | ||
155 | MODULE_PARM_DESC(testmode, "Watchdog test mode (1 = no reboot), default=" | ||
156 | __MODULE_STRING(DEFAULT_TESTMODE)); | ||
157 | module_param(nowayout, int, 0); | ||
158 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started, default=" | ||
159 | __MODULE_STRING(WATCHDOG_NOWAYOUT)); | ||
160 | |||
161 | /* Superio Chip */ | ||
162 | |||
163 | static inline void superio_enter(void) | ||
164 | { | ||
165 | outb(0x87, REG); | ||
166 | outb(0x01, REG); | ||
167 | outb(0x55, REG); | ||
168 | outb(0x55, REG); | ||
169 | } | ||
170 | |||
171 | static inline void superio_exit(void) | ||
172 | { | ||
173 | outb(0x02, REG); | ||
174 | outb(0x02, VAL); | ||
175 | } | ||
176 | |||
177 | static inline void superio_select(int ldn) | ||
178 | { | ||
179 | outb(LDNREG, REG); | ||
180 | outb(ldn, VAL); | ||
181 | } | ||
182 | |||
183 | static inline int superio_inb(int reg) | ||
184 | { | ||
185 | outb(reg, REG); | ||
186 | return inb(VAL); | ||
187 | } | ||
188 | |||
189 | static inline void superio_outb(int val, int reg) | ||
190 | { | ||
191 | outb(reg, REG); | ||
192 | outb(val, VAL); | ||
193 | } | ||
194 | |||
195 | static inline int superio_inw(int reg) | ||
196 | { | ||
197 | int val; | ||
198 | outb(reg++, REG); | ||
199 | val = inb(VAL) << 8; | ||
200 | outb(reg, REG); | ||
201 | val |= inb(VAL); | ||
202 | return val; | ||
203 | } | ||
204 | |||
205 | static inline void superio_outw(int val, int reg) | ||
206 | { | ||
207 | outb(reg++, REG); | ||
208 | outb(val >> 8, VAL); | ||
209 | outb(reg, REG); | ||
210 | outb(val, VAL); | ||
211 | } | ||
212 | |||
213 | /* watchdog timer handling */ | ||
214 | |||
215 | static void wdt_keepalive(void) | ||
216 | { | ||
217 | if (test_bit(WDTS_USE_GP, &wdt_status)) | ||
218 | inb(base); | ||
219 | else | ||
220 | /* The timer reloads with around 5 msec delay */ | ||
221 | outb(0x55, CIR_DR(base)); | ||
222 | set_bit(WDTS_KEEPALIVE, &wdt_status); | ||
223 | } | ||
224 | |||
225 | static void wdt_start(void) | ||
226 | { | ||
227 | unsigned long flags; | ||
228 | |||
229 | spin_lock_irqsave(&spinlock, flags); | ||
230 | superio_enter(); | ||
231 | |||
232 | superio_select(GPIO); | ||
233 | if (test_bit(WDTS_USE_GP, &wdt_status)) | ||
234 | superio_outb(WDT_GAMEPORT, WDTCTRL); | ||
235 | else | ||
236 | superio_outb(WDT_CIRINT, WDTCTRL); | ||
237 | if (!testmode) | ||
238 | superio_outb(WDT_TOV1 | WDT_KRST | WDT_PWROK, WDTCFG); | ||
239 | else | ||
240 | superio_outb(WDT_TOV1, WDTCFG); | ||
241 | superio_outb(timeout>>8, WDTVALMSB); | ||
242 | superio_outb(timeout, WDTVALLSB); | ||
243 | |||
244 | superio_exit(); | ||
245 | spin_unlock_irqrestore(&spinlock, flags); | ||
246 | } | ||
247 | |||
248 | static void wdt_stop(void) | ||
249 | { | ||
250 | unsigned long flags; | ||
251 | |||
252 | spin_lock_irqsave(&spinlock, flags); | ||
253 | superio_enter(); | ||
254 | |||
255 | superio_select(GPIO); | ||
256 | superio_outb(0x00, WDTCTRL); | ||
257 | superio_outb(WDT_TOV1, WDTCFG); | ||
258 | superio_outb(0x00, WDTVALMSB); | ||
259 | superio_outb(0x00, WDTVALLSB); | ||
260 | |||
261 | superio_exit(); | ||
262 | spin_unlock_irqrestore(&spinlock, flags); | ||
263 | } | ||
264 | |||
265 | /** | ||
266 | * wdt_set_timeout - set a new timeout value with watchdog ioctl | ||
267 | * @t: timeout value in seconds | ||
268 | * | ||
269 | * The hardware device has a 16 bit watchdog timer, thus the | ||
270 | * timeout time ranges between 1 and 65535 seconds. | ||
271 | * | ||
272 | * Used within WDIOC_SETTIMEOUT watchdog device ioctl. | ||
273 | */ | ||
274 | |||
275 | static int wdt_set_timeout(int t) | ||
276 | { | ||
277 | unsigned long flags; | ||
278 | |||
279 | if (t < 1 || t > 65535) | ||
280 | return -EINVAL; | ||
281 | |||
282 | timeout = t; | ||
283 | |||
284 | spin_lock_irqsave(&spinlock, flags); | ||
285 | if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { | ||
286 | superio_enter(); | ||
287 | |||
288 | superio_select(GPIO); | ||
289 | superio_outb(t>>8, WDTVALMSB); | ||
290 | superio_outb(t, WDTVALLSB); | ||
291 | |||
292 | superio_exit(); | ||
293 | } | ||
294 | spin_unlock_irqrestore(&spinlock, flags); | ||
295 | return 0; | ||
296 | } | ||
297 | |||
298 | /** | ||
299 | * wdt_get_status - determines the status supported by watchdog ioctl | ||
300 | * @status: status returned to user space | ||
301 | * | ||
302 | * The status bit of the device does not allow to distinguish | ||
303 | * between a regular system reset and a watchdog forced reset. | ||
304 | * But, in test mode it is useful, so it is supported through | ||
305 | * WDIOC_GETSTATUS watchdog ioctl. Additionally the driver | ||
306 | * reports the keepalive signal and the acception of the magic. | ||
307 | * | ||
308 | * Used within WDIOC_GETSTATUS watchdog device ioctl. | ||
309 | */ | ||
310 | |||
311 | static int wdt_get_status(int *status) | ||
312 | { | ||
313 | unsigned long flags; | ||
314 | |||
315 | *status = 0; | ||
316 | if (testmode) { | ||
317 | spin_lock_irqsave(&spinlock, flags); | ||
318 | superio_enter(); | ||
319 | superio_select(GPIO); | ||
320 | if (superio_inb(WDTCTRL) & WDT_ZERO) { | ||
321 | superio_outb(0x00, WDTCTRL); | ||
322 | clear_bit(WDTS_TIMER_RUN, &wdt_status); | ||
323 | *status |= WDIOF_CARDRESET; | ||
324 | } | ||
325 | |||
326 | superio_exit(); | ||
327 | spin_unlock_irqrestore(&spinlock, flags); | ||
328 | } | ||
329 | if (test_and_clear_bit(WDTS_KEEPALIVE, &wdt_status)) | ||
330 | *status |= WDIOF_KEEPALIVEPING; | ||
331 | if (test_bit(WDTS_EXPECTED, &wdt_status)) | ||
332 | *status |= WDIOF_MAGICCLOSE; | ||
333 | return 0; | ||
334 | } | ||
335 | |||
336 | /* /dev/watchdog handling */ | ||
337 | |||
338 | /** | ||
339 | * wdt_open - watchdog file_operations .open | ||
340 | * @inode: inode of the device | ||
341 | * @file: file handle to the device | ||
342 | * | ||
343 | * The watchdog timer starts by opening the device. | ||
344 | * | ||
345 | * Used within the file operation of the watchdog device. | ||
346 | */ | ||
347 | |||
348 | static int wdt_open(struct inode *inode, struct file *file) | ||
349 | { | ||
350 | if (exclusive && test_and_set_bit(WDTS_DEV_OPEN, &wdt_status)) | ||
351 | return -EBUSY; | ||
352 | if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) { | ||
353 | if (nowayout && !test_and_set_bit(WDTS_LOCKED, &wdt_status)) | ||
354 | __module_get(THIS_MODULE); | ||
355 | wdt_start(); | ||
356 | } | ||
357 | return nonseekable_open(inode, file); | ||
358 | } | ||
359 | |||
360 | /** | ||
361 | * wdt_release - watchdog file_operations .release | ||
362 | * @inode: inode of the device | ||
363 | * @file: file handle to the device | ||
364 | * | ||
365 | * Closing the watchdog device either stops the watchdog timer | ||
366 | * or in the case, that nowayout is set or the magic character | ||
367 | * wasn't written, a critical warning about an running watchdog | ||
368 | * timer is given. | ||
369 | * | ||
370 | * Used within the file operation of the watchdog device. | ||
371 | */ | ||
372 | |||
373 | static int wdt_release(struct inode *inode, struct file *file) | ||
374 | { | ||
375 | if (test_bit(WDTS_TIMER_RUN, &wdt_status)) { | ||
376 | if (test_and_clear_bit(WDTS_EXPECTED, &wdt_status)) { | ||
377 | wdt_stop(); | ||
378 | clear_bit(WDTS_TIMER_RUN, &wdt_status); | ||
379 | } else { | ||
380 | wdt_keepalive(); | ||
381 | printk(KERN_CRIT PFX | ||
382 | "unexpected close, not stopping watchdog!\n"); | ||
383 | } | ||
384 | } | ||
385 | clear_bit(WDTS_DEV_OPEN, &wdt_status); | ||
386 | return 0; | ||
387 | } | ||
388 | |||
389 | /** | ||
390 | * wdt_write - watchdog file_operations .write | ||
391 | * @file: file handle to the watchdog | ||
392 | * @buf: buffer to write | ||
393 | * @count: count of bytes | ||
394 | * @ppos: pointer to the position to write. No seeks allowed | ||
395 | * | ||
396 | * A write to a watchdog device is defined as a keepalive signal. Any | ||
397 | * write of data will do, as we don't define content meaning. | ||
398 | * | ||
399 | * Used within the file operation of the watchdog device. | ||
400 | */ | ||
401 | |||
402 | static ssize_t wdt_write(struct file *file, const char __user *buf, | ||
403 | size_t count, loff_t *ppos) | ||
404 | { | ||
405 | if (count) { | ||
406 | clear_bit(WDTS_EXPECTED, &wdt_status); | ||
407 | wdt_keepalive(); | ||
408 | } | ||
409 | if (!nowayout) { | ||
410 | size_t ofs; | ||
411 | |||
412 | /* note: just in case someone wrote the magic character long ago */ | ||
413 | for (ofs = 0; ofs != count; ofs++) { | ||
414 | char c; | ||
415 | if (get_user(c, buf + ofs)) | ||
416 | return -EFAULT; | ||
417 | if (c == WD_MAGIC) | ||
418 | set_bit(WDTS_EXPECTED, &wdt_status); | ||
419 | } | ||
420 | } | ||
421 | return count; | ||
422 | } | ||
423 | |||
424 | static struct watchdog_info ident = { | ||
425 | .options = WDIOF_SETTIMEOUT | WDIOF_MAGICCLOSE | WDIOF_KEEPALIVEPING, | ||
426 | .firmware_version = 1, | ||
427 | .identity = WATCHDOG_NAME, | ||
428 | }; | ||
429 | |||
430 | /** | ||
431 | * wdt_ioctl - watchdog file_operations .unlocked_ioctl | ||
432 | * @file: file handle to the device | ||
433 | * @cmd: watchdog command | ||
434 | * @arg: argument pointer | ||
435 | * | ||
436 | * The watchdog API defines a common set of functions for all watchdogs | ||
437 | * according to their available features. | ||
438 | * | ||
439 | * Used within the file operation of the watchdog device. | ||
440 | */ | ||
441 | |||
442 | static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
443 | { | ||
444 | int rc = 0, status, new_options, new_timeout; | ||
445 | union { | ||
446 | struct watchdog_info __user *ident; | ||
447 | int __user *i; | ||
448 | } uarg; | ||
449 | |||
450 | uarg.i = (int __user *)arg; | ||
451 | |||
452 | switch (cmd) { | ||
453 | case WDIOC_GETSUPPORT: | ||
454 | return copy_to_user(uarg.ident, | ||
455 | &ident, sizeof(ident)) ? -EFAULT : 0; | ||
456 | |||
457 | case WDIOC_GETSTATUS: | ||
458 | wdt_get_status(&status); | ||
459 | return put_user(status, uarg.i); | ||
460 | |||
461 | case WDIOC_GETBOOTSTATUS: | ||
462 | return put_user(0, uarg.i); | ||
463 | |||
464 | case WDIOC_KEEPALIVE: | ||
465 | wdt_keepalive(); | ||
466 | return 0; | ||
467 | |||
468 | case WDIOC_SETOPTIONS: | ||
469 | if (get_user(new_options, uarg.i)) | ||
470 | return -EFAULT; | ||
471 | |||
472 | switch (new_options) { | ||
473 | case WDIOS_DISABLECARD: | ||
474 | if (test_bit(WDTS_TIMER_RUN, &wdt_status)) | ||
475 | wdt_stop(); | ||
476 | clear_bit(WDTS_TIMER_RUN, &wdt_status); | ||
477 | return 0; | ||
478 | |||
479 | case WDIOS_ENABLECARD: | ||
480 | if (!test_and_set_bit(WDTS_TIMER_RUN, &wdt_status)) | ||
481 | wdt_start(); | ||
482 | return 0; | ||
483 | |||
484 | default: | ||
485 | return -EFAULT; | ||
486 | } | ||
487 | |||
488 | case WDIOC_SETTIMEOUT: | ||
489 | if (get_user(new_timeout, uarg.i)) | ||
490 | return -EFAULT; | ||
491 | rc = wdt_set_timeout(new_timeout); | ||
492 | case WDIOC_GETTIMEOUT: | ||
493 | if (put_user(timeout, uarg.i)) | ||
494 | return -EFAULT; | ||
495 | return rc; | ||
496 | |||
497 | default: | ||
498 | return -ENOTTY; | ||
499 | } | ||
500 | } | ||
501 | |||
502 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | ||
503 | void *unused) | ||
504 | { | ||
505 | if (code == SYS_DOWN || code == SYS_HALT) | ||
506 | wdt_stop(); | ||
507 | return NOTIFY_DONE; | ||
508 | } | ||
509 | |||
510 | static const struct file_operations wdt_fops = { | ||
511 | .owner = THIS_MODULE, | ||
512 | .llseek = no_llseek, | ||
513 | .write = wdt_write, | ||
514 | .unlocked_ioctl = wdt_ioctl, | ||
515 | .open = wdt_open, | ||
516 | .release = wdt_release, | ||
517 | }; | ||
518 | |||
519 | static struct miscdevice wdt_miscdev = { | ||
520 | .minor = WATCHDOG_MINOR, | ||
521 | .name = "watchdog", | ||
522 | .fops = &wdt_fops, | ||
523 | }; | ||
524 | |||
525 | static struct notifier_block wdt_notifier = { | ||
526 | .notifier_call = wdt_notify_sys, | ||
527 | }; | ||
528 | |||
529 | static int __init it87_wdt_init(void) | ||
530 | { | ||
531 | int rc = 0; | ||
532 | u16 chip_type; | ||
533 | u8 chip_rev; | ||
534 | unsigned long flags; | ||
535 | |||
536 | spin_lock_irqsave(&spinlock, flags); | ||
537 | superio_enter(); | ||
538 | chip_type = superio_inw(CHIPID); | ||
539 | chip_rev = superio_inb(CHIPREV) & 0x0f; | ||
540 | superio_exit(); | ||
541 | spin_unlock_irqrestore(&spinlock, flags); | ||
542 | |||
543 | switch (chip_type) { | ||
544 | case IT8716_ID: | ||
545 | case IT8718_ID: | ||
546 | case IT8726_ID: | ||
547 | break; | ||
548 | case IT8712_ID: | ||
549 | if (chip_rev > 7) | ||
550 | break; | ||
551 | case IT8705_ID: | ||
552 | printk(KERN_ERR PFX | ||
553 | "Unsupported Chip found, Chip %04x Revision %02x\n", | ||
554 | chip_type, chip_rev); | ||
555 | return -ENODEV; | ||
556 | case NO_DEV_ID: | ||
557 | printk(KERN_ERR PFX "no device\n"); | ||
558 | return -ENODEV; | ||
559 | default: | ||
560 | printk(KERN_ERR PFX | ||
561 | "Unknown Chip found, Chip %04x Revision %04x\n", | ||
562 | chip_type, chip_rev); | ||
563 | return -ENODEV; | ||
564 | } | ||
565 | |||
566 | spin_lock_irqsave(&spinlock, flags); | ||
567 | superio_enter(); | ||
568 | |||
569 | superio_select(GPIO); | ||
570 | superio_outb(WDT_TOV1, WDTCFG); | ||
571 | superio_outb(0x00, WDTCTRL); | ||
572 | |||
573 | /* First try to get Gameport support */ | ||
574 | if (chip_type != IT8718_ID && !nogameport) { | ||
575 | superio_select(GAMEPORT); | ||
576 | base = superio_inw(BASEREG); | ||
577 | if (!base) { | ||
578 | base = GP_BASE_DEFAULT; | ||
579 | superio_outw(base, BASEREG); | ||
580 | } | ||
581 | gpact = superio_inb(ACTREG); | ||
582 | superio_outb(0x01, ACTREG); | ||
583 | superio_exit(); | ||
584 | spin_unlock_irqrestore(&spinlock, flags); | ||
585 | if (request_region(base, 1, WATCHDOG_NAME)) | ||
586 | set_bit(WDTS_USE_GP, &wdt_status); | ||
587 | else | ||
588 | rc = -EIO; | ||
589 | } else { | ||
590 | superio_exit(); | ||
591 | spin_unlock_irqrestore(&spinlock, flags); | ||
592 | } | ||
593 | |||
594 | /* If we haven't Gameport support, try to get CIR support */ | ||
595 | if (!test_bit(WDTS_USE_GP, &wdt_status)) { | ||
596 | if (!request_region(CIR_BASE, 8, WATCHDOG_NAME)) { | ||
597 | if (rc == -EIO) | ||
598 | printk(KERN_ERR PFX | ||
599 | "I/O Address 0x%04x and 0x%04x" | ||
600 | " already in use\n", base, CIR_BASE); | ||
601 | else | ||
602 | printk(KERN_ERR PFX | ||
603 | "I/O Address 0x%04x already in use\n", | ||
604 | CIR_BASE); | ||
605 | rc = -EIO; | ||
606 | goto err_out; | ||
607 | } | ||
608 | base = CIR_BASE; | ||
609 | spin_lock_irqsave(&spinlock, flags); | ||
610 | superio_enter(); | ||
611 | |||
612 | superio_select(CIR); | ||
613 | superio_outw(base, BASEREG); | ||
614 | superio_outb(0x00, CIR_ILS); | ||
615 | ciract = superio_inb(ACTREG); | ||
616 | superio_outb(0x01, ACTREG); | ||
617 | if (rc == -EIO) { | ||
618 | superio_select(GAMEPORT); | ||
619 | superio_outb(gpact, ACTREG); | ||
620 | } | ||
621 | |||
622 | superio_exit(); | ||
623 | spin_unlock_irqrestore(&spinlock, flags); | ||
624 | } | ||
625 | |||
626 | if (timeout < 1 || timeout > 65535) { | ||
627 | timeout = DEFAULT_TIMEOUT; | ||
628 | printk(KERN_WARNING PFX | ||
629 | "Timeout value out of range, use default %d sec\n", | ||
630 | DEFAULT_TIMEOUT); | ||
631 | } | ||
632 | |||
633 | rc = register_reboot_notifier(&wdt_notifier); | ||
634 | if (rc) { | ||
635 | printk(KERN_ERR PFX | ||
636 | "Cannot register reboot notifier (err=%d)\n", rc); | ||
637 | goto err_out_region; | ||
638 | } | ||
639 | |||
640 | rc = misc_register(&wdt_miscdev); | ||
641 | if (rc) { | ||
642 | printk(KERN_ERR PFX | ||
643 | "Cannot register miscdev on minor=%d (err=%d)\n", | ||
644 | wdt_miscdev.minor, rc); | ||
645 | goto err_out_reboot; | ||
646 | } | ||
647 | |||
648 | /* Initialize CIR to use it as keepalive source */ | ||
649 | if (!test_bit(WDTS_USE_GP, &wdt_status)) { | ||
650 | outb(0x00, CIR_RCR(base)); | ||
651 | outb(0xc0, CIR_TCR1(base)); | ||
652 | outb(0x5c, CIR_TCR2(base)); | ||
653 | outb(0x10, CIR_IER(base)); | ||
654 | outb(0x00, CIR_BDHR(base)); | ||
655 | outb(0x01, CIR_BDLR(base)); | ||
656 | outb(0x09, CIR_IER(base)); | ||
657 | } | ||
658 | |||
659 | printk(KERN_INFO PFX "Chip it%04x revision %d initialized. " | ||
660 | "timeout=%d sec (nowayout=%d testmode=%d exclusive=%d " | ||
661 | "nogameport=%d)\n", chip_type, chip_rev, timeout, | ||
662 | nowayout, testmode, exclusive, nogameport); | ||
663 | |||
664 | return 0; | ||
665 | |||
666 | err_out_reboot: | ||
667 | unregister_reboot_notifier(&wdt_notifier); | ||
668 | err_out_region: | ||
669 | release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8); | ||
670 | if (!test_bit(WDTS_USE_GP, &wdt_status)) { | ||
671 | spin_lock_irqsave(&spinlock, flags); | ||
672 | superio_enter(); | ||
673 | superio_select(CIR); | ||
674 | superio_outb(ciract, ACTREG); | ||
675 | superio_exit(); | ||
676 | spin_unlock_irqrestore(&spinlock, flags); | ||
677 | } | ||
678 | err_out: | ||
679 | if (chip_type != IT8718_ID && !nogameport) { | ||
680 | spin_lock_irqsave(&spinlock, flags); | ||
681 | superio_enter(); | ||
682 | superio_select(GAMEPORT); | ||
683 | superio_outb(gpact, ACTREG); | ||
684 | superio_exit(); | ||
685 | spin_unlock_irqrestore(&spinlock, flags); | ||
686 | } | ||
687 | |||
688 | return rc; | ||
689 | } | ||
690 | |||
691 | static void __exit it87_wdt_exit(void) | ||
692 | { | ||
693 | unsigned long flags; | ||
694 | int nolock; | ||
695 | |||
696 | nolock = !spin_trylock_irqsave(&spinlock, flags); | ||
697 | superio_enter(); | ||
698 | superio_select(GPIO); | ||
699 | superio_outb(0x00, WDTCTRL); | ||
700 | superio_outb(0x00, WDTCFG); | ||
701 | superio_outb(0x00, WDTVALMSB); | ||
702 | superio_outb(0x00, WDTVALLSB); | ||
703 | if (test_bit(WDTS_USE_GP, &wdt_status)) { | ||
704 | superio_select(GAMEPORT); | ||
705 | superio_outb(gpact, ACTREG); | ||
706 | } else { | ||
707 | superio_select(CIR); | ||
708 | superio_outb(ciract, ACTREG); | ||
709 | } | ||
710 | superio_exit(); | ||
711 | if (!nolock) | ||
712 | spin_unlock_irqrestore(&spinlock, flags); | ||
713 | |||
714 | misc_deregister(&wdt_miscdev); | ||
715 | unregister_reboot_notifier(&wdt_notifier); | ||
716 | release_region(base, test_bit(WDTS_USE_GP, &wdt_status) ? 1 : 8); | ||
717 | } | ||
718 | |||
719 | module_init(it87_wdt_init); | ||
720 | module_exit(it87_wdt_exit); | ||
721 | |||
722 | MODULE_AUTHOR("Oliver Schuster"); | ||
723 | MODULE_DESCRIPTION("Hardware Watchdog Device Driver for IT87xx EC-LPC I/O"); | ||
724 | MODULE_LICENSE("GPL"); | ||
725 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c index 3a11dadfd8e7..7bcbb7f4745f 100644 --- a/drivers/watchdog/omap_wdt.c +++ b/drivers/watchdog/omap_wdt.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * linux/drivers/char/watchdog/omap_wdt.c | 2 | * omap_wdt.c |
3 | * | 3 | * |
4 | * Watchdog driver for the TI OMAP 16xx & 24xx 32KHz (non-secure) watchdog | 4 | * Watchdog driver for the TI OMAP 16xx & 24xx/34xx 32KHz (non-secure) watchdog |
5 | * | 5 | * |
6 | * Author: MontaVista Software, Inc. | 6 | * Author: MontaVista Software, Inc. |
7 | * <gdavis@mvista.com> or <source@mvista.com> | 7 | * <gdavis@mvista.com> or <source@mvista.com> |
@@ -47,50 +47,68 @@ | |||
47 | 47 | ||
48 | #include "omap_wdt.h" | 48 | #include "omap_wdt.h" |
49 | 49 | ||
50 | static struct platform_device *omap_wdt_dev; | ||
51 | |||
50 | static unsigned timer_margin; | 52 | static unsigned timer_margin; |
51 | module_param(timer_margin, uint, 0); | 53 | module_param(timer_margin, uint, 0); |
52 | MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); | 54 | MODULE_PARM_DESC(timer_margin, "initial watchdog timeout (in seconds)"); |
53 | 55 | ||
54 | static int omap_wdt_users; | ||
55 | static struct clk *armwdt_ck; | ||
56 | static struct clk *mpu_wdt_ick; | ||
57 | static struct clk *mpu_wdt_fck; | ||
58 | |||
59 | static unsigned int wdt_trgr_pattern = 0x1234; | 56 | static unsigned int wdt_trgr_pattern = 0x1234; |
60 | static spinlock_t wdt_lock; | 57 | static spinlock_t wdt_lock; |
61 | 58 | ||
62 | static void omap_wdt_ping(void) | 59 | struct omap_wdt_dev { |
60 | void __iomem *base; /* physical */ | ||
61 | struct device *dev; | ||
62 | int omap_wdt_users; | ||
63 | struct clk *armwdt_ck; | ||
64 | struct clk *mpu_wdt_ick; | ||
65 | struct clk *mpu_wdt_fck; | ||
66 | struct resource *mem; | ||
67 | struct miscdevice omap_wdt_miscdev; | ||
68 | }; | ||
69 | |||
70 | static void omap_wdt_ping(struct omap_wdt_dev *wdev) | ||
63 | { | 71 | { |
72 | void __iomem *base = wdev->base; | ||
73 | |||
64 | /* wait for posted write to complete */ | 74 | /* wait for posted write to complete */ |
65 | while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08) | 75 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) |
66 | cpu_relax(); | 76 | cpu_relax(); |
77 | |||
67 | wdt_trgr_pattern = ~wdt_trgr_pattern; | 78 | wdt_trgr_pattern = ~wdt_trgr_pattern; |
68 | omap_writel(wdt_trgr_pattern, (OMAP_WATCHDOG_TGR)); | 79 | __raw_writel(wdt_trgr_pattern, (base + OMAP_WATCHDOG_TGR)); |
80 | |||
69 | /* wait for posted write to complete */ | 81 | /* wait for posted write to complete */ |
70 | while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x08) | 82 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x08) |
71 | cpu_relax(); | 83 | cpu_relax(); |
72 | /* reloaded WCRR from WLDR */ | 84 | /* reloaded WCRR from WLDR */ |
73 | } | 85 | } |
74 | 86 | ||
75 | static void omap_wdt_enable(void) | 87 | static void omap_wdt_enable(struct omap_wdt_dev *wdev) |
76 | { | 88 | { |
89 | void __iomem *base = wdev->base; | ||
90 | |||
77 | /* Sequence to enable the watchdog */ | 91 | /* Sequence to enable the watchdog */ |
78 | omap_writel(0xBBBB, OMAP_WATCHDOG_SPR); | 92 | __raw_writel(0xBBBB, base + OMAP_WATCHDOG_SPR); |
79 | while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10) | 93 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) |
80 | cpu_relax(); | 94 | cpu_relax(); |
81 | omap_writel(0x4444, OMAP_WATCHDOG_SPR); | 95 | |
82 | while ((omap_readl(OMAP_WATCHDOG_WPS)) & 0x10) | 96 | __raw_writel(0x4444, base + OMAP_WATCHDOG_SPR); |
97 | while ((__raw_readl(base + OMAP_WATCHDOG_WPS)) & 0x10) | ||
83 | cpu_relax(); | 98 | cpu_relax(); |
84 | } | 99 | } |
85 | 100 | ||
86 | static void omap_wdt_disable(void) | 101 | static void omap_wdt_disable(struct omap_wdt_dev *wdev) |
87 | { | 102 | { |
103 | void __iomem *base = wdev->base; | ||
104 | |||
88 | /* sequence required to disable watchdog */ | 105 | /* sequence required to disable watchdog */ |
89 | omap_writel(0xAAAA, OMAP_WATCHDOG_SPR); /* TIMER_MODE */ | 106 | __raw_writel(0xAAAA, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ |
90 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10) | 107 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) |
91 | cpu_relax(); | 108 | cpu_relax(); |
92 | omap_writel(0x5555, OMAP_WATCHDOG_SPR); /* TIMER_MODE */ | 109 | |
93 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x10) | 110 | __raw_writel(0x5555, base + OMAP_WATCHDOG_SPR); /* TIMER_MODE */ |
111 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x10) | ||
94 | cpu_relax(); | 112 | cpu_relax(); |
95 | } | 113 | } |
96 | 114 | ||
@@ -103,83 +121,90 @@ static void omap_wdt_adjust_timeout(unsigned new_timeout) | |||
103 | timer_margin = new_timeout; | 121 | timer_margin = new_timeout; |
104 | } | 122 | } |
105 | 123 | ||
106 | static void omap_wdt_set_timeout(void) | 124 | static void omap_wdt_set_timeout(struct omap_wdt_dev *wdev) |
107 | { | 125 | { |
108 | u32 pre_margin = GET_WLDR_VAL(timer_margin); | 126 | u32 pre_margin = GET_WLDR_VAL(timer_margin); |
127 | void __iomem *base = wdev->base; | ||
109 | 128 | ||
110 | /* just count up at 32 KHz */ | 129 | /* just count up at 32 KHz */ |
111 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04) | 130 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) |
112 | cpu_relax(); | 131 | cpu_relax(); |
113 | omap_writel(pre_margin, OMAP_WATCHDOG_LDR); | 132 | |
114 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x04) | 133 | __raw_writel(pre_margin, base + OMAP_WATCHDOG_LDR); |
134 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x04) | ||
115 | cpu_relax(); | 135 | cpu_relax(); |
116 | } | 136 | } |
117 | 137 | ||
118 | /* | 138 | /* |
119 | * Allow only one task to hold it open | 139 | * Allow only one task to hold it open |
120 | */ | 140 | */ |
121 | |||
122 | static int omap_wdt_open(struct inode *inode, struct file *file) | 141 | static int omap_wdt_open(struct inode *inode, struct file *file) |
123 | { | 142 | { |
124 | if (test_and_set_bit(1, (unsigned long *)&omap_wdt_users)) | 143 | struct omap_wdt_dev *wdev = platform_get_drvdata(omap_wdt_dev); |
144 | void __iomem *base = wdev->base; | ||
145 | |||
146 | if (test_and_set_bit(1, (unsigned long *)&(wdev->omap_wdt_users))) | ||
125 | return -EBUSY; | 147 | return -EBUSY; |
126 | 148 | ||
127 | if (cpu_is_omap16xx()) | 149 | if (cpu_is_omap16xx()) |
128 | clk_enable(armwdt_ck); /* Enable the clock */ | 150 | clk_enable(wdev->armwdt_ck); /* Enable the clock */ |
129 | 151 | ||
130 | if (cpu_is_omap24xx()) { | 152 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { |
131 | clk_enable(mpu_wdt_ick); /* Enable the interface clock */ | 153 | clk_enable(wdev->mpu_wdt_ick); /* Enable the interface clock */ |
132 | clk_enable(mpu_wdt_fck); /* Enable the functional clock */ | 154 | clk_enable(wdev->mpu_wdt_fck); /* Enable the functional clock */ |
133 | } | 155 | } |
134 | 156 | ||
135 | /* initialize prescaler */ | 157 | /* initialize prescaler */ |
136 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01) | 158 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) |
137 | cpu_relax(); | 159 | cpu_relax(); |
138 | omap_writel((1 << 5) | (PTV << 2), OMAP_WATCHDOG_CNTRL); | 160 | |
139 | while (omap_readl(OMAP_WATCHDOG_WPS) & 0x01) | 161 | __raw_writel((1 << 5) | (PTV << 2), base + OMAP_WATCHDOG_CNTRL); |
162 | while (__raw_readl(base + OMAP_WATCHDOG_WPS) & 0x01) | ||
140 | cpu_relax(); | 163 | cpu_relax(); |
141 | 164 | ||
142 | omap_wdt_set_timeout(); | 165 | file->private_data = (void *) wdev; |
143 | omap_wdt_enable(); | 166 | |
167 | omap_wdt_set_timeout(wdev); | ||
168 | omap_wdt_enable(wdev); | ||
169 | |||
144 | return nonseekable_open(inode, file); | 170 | return nonseekable_open(inode, file); |
145 | } | 171 | } |
146 | 172 | ||
147 | static int omap_wdt_release(struct inode *inode, struct file *file) | 173 | static int omap_wdt_release(struct inode *inode, struct file *file) |
148 | { | 174 | { |
175 | struct omap_wdt_dev *wdev = file->private_data; | ||
176 | |||
149 | /* | 177 | /* |
150 | * Shut off the timer unless NOWAYOUT is defined. | 178 | * Shut off the timer unless NOWAYOUT is defined. |
151 | */ | 179 | */ |
152 | #ifndef CONFIG_WATCHDOG_NOWAYOUT | 180 | #ifndef CONFIG_WATCHDOG_NOWAYOUT |
153 | omap_wdt_disable(); | ||
154 | 181 | ||
155 | if (cpu_is_omap16xx()) { | 182 | omap_wdt_disable(wdev); |
156 | clk_disable(armwdt_ck); /* Disable the clock */ | ||
157 | clk_put(armwdt_ck); | ||
158 | armwdt_ck = NULL; | ||
159 | } | ||
160 | 183 | ||
161 | if (cpu_is_omap24xx()) { | 184 | if (cpu_is_omap16xx()) |
162 | clk_disable(mpu_wdt_ick); /* Disable the clock */ | 185 | clk_disable(wdev->armwdt_ck); /* Disable the clock */ |
163 | clk_disable(mpu_wdt_fck); /* Disable the clock */ | 186 | |
164 | clk_put(mpu_wdt_ick); | 187 | if (cpu_is_omap24xx() || cpu_is_omap34xx()) { |
165 | clk_put(mpu_wdt_fck); | 188 | clk_disable(wdev->mpu_wdt_ick); /* Disable the clock */ |
166 | mpu_wdt_ick = NULL; | 189 | clk_disable(wdev->mpu_wdt_fck); /* Disable the clock */ |
167 | mpu_wdt_fck = NULL; | ||
168 | } | 190 | } |
169 | #else | 191 | #else |
170 | printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); | 192 | printk(KERN_CRIT "omap_wdt: Unexpected close, not stopping!\n"); |
171 | #endif | 193 | #endif |
172 | omap_wdt_users = 0; | 194 | wdev->omap_wdt_users = 0; |
195 | |||
173 | return 0; | 196 | return 0; |
174 | } | 197 | } |
175 | 198 | ||
176 | static ssize_t omap_wdt_write(struct file *file, const char __user *data, | 199 | static ssize_t omap_wdt_write(struct file *file, const char __user *data, |
177 | size_t len, loff_t *ppos) | 200 | size_t len, loff_t *ppos) |
178 | { | 201 | { |
202 | struct omap_wdt_dev *wdev = file->private_data; | ||
203 | |||
179 | /* Refresh LOAD_TIME. */ | 204 | /* Refresh LOAD_TIME. */ |
180 | if (len) { | 205 | if (len) { |
181 | spin_lock(&wdt_lock); | 206 | spin_lock(&wdt_lock); |
182 | omap_wdt_ping(); | 207 | omap_wdt_ping(wdev); |
183 | spin_unlock(&wdt_lock); | 208 | spin_unlock(&wdt_lock); |
184 | } | 209 | } |
185 | return len; | 210 | return len; |
@@ -188,6 +213,7 @@ static ssize_t omap_wdt_write(struct file *file, const char __user *data, | |||
188 | static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | 213 | static long omap_wdt_ioctl(struct file *file, unsigned int cmd, |
189 | unsigned long arg) | 214 | unsigned long arg) |
190 | { | 215 | { |
216 | struct omap_wdt_dev *wdev; | ||
191 | int new_margin; | 217 | int new_margin; |
192 | static const struct watchdog_info ident = { | 218 | static const struct watchdog_info ident = { |
193 | .identity = "OMAP Watchdog", | 219 | .identity = "OMAP Watchdog", |
@@ -195,6 +221,8 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | |||
195 | .firmware_version = 0, | 221 | .firmware_version = 0, |
196 | }; | 222 | }; |
197 | 223 | ||
224 | wdev = file->private_data; | ||
225 | |||
198 | switch (cmd) { | 226 | switch (cmd) { |
199 | case WDIOC_GETSUPPORT: | 227 | case WDIOC_GETSUPPORT: |
200 | return copy_to_user((struct watchdog_info __user *)arg, &ident, | 228 | return copy_to_user((struct watchdog_info __user *)arg, &ident, |
@@ -203,14 +231,14 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | |||
203 | return put_user(0, (int __user *)arg); | 231 | return put_user(0, (int __user *)arg); |
204 | case WDIOC_GETBOOTSTATUS: | 232 | case WDIOC_GETBOOTSTATUS: |
205 | if (cpu_is_omap16xx()) | 233 | if (cpu_is_omap16xx()) |
206 | return put_user(omap_readw(ARM_SYSST), | 234 | return put_user(__raw_readw(ARM_SYSST), |
207 | (int __user *)arg); | 235 | (int __user *)arg); |
208 | if (cpu_is_omap24xx()) | 236 | if (cpu_is_omap24xx()) |
209 | return put_user(omap_prcm_get_reset_sources(), | 237 | return put_user(omap_prcm_get_reset_sources(), |
210 | (int __user *)arg); | 238 | (int __user *)arg); |
211 | case WDIOC_KEEPALIVE: | 239 | case WDIOC_KEEPALIVE: |
212 | spin_lock(&wdt_lock); | 240 | spin_lock(&wdt_lock); |
213 | omap_wdt_ping(); | 241 | omap_wdt_ping(wdev); |
214 | spin_unlock(&wdt_lock); | 242 | spin_unlock(&wdt_lock); |
215 | return 0; | 243 | return 0; |
216 | case WDIOC_SETTIMEOUT: | 244 | case WDIOC_SETTIMEOUT: |
@@ -219,11 +247,11 @@ static long omap_wdt_ioctl(struct file *file, unsigned int cmd, | |||
219 | omap_wdt_adjust_timeout(new_margin); | 247 | omap_wdt_adjust_timeout(new_margin); |
220 | 248 | ||
221 | spin_lock(&wdt_lock); | 249 | spin_lock(&wdt_lock); |
222 | omap_wdt_disable(); | 250 | omap_wdt_disable(wdev); |
223 | omap_wdt_set_timeout(); | 251 | omap_wdt_set_timeout(wdev); |
224 | omap_wdt_enable(); | 252 | omap_wdt_enable(wdev); |
225 | 253 | ||
226 | omap_wdt_ping(); | 254 | omap_wdt_ping(wdev); |
227 | spin_unlock(&wdt_lock); | 255 | spin_unlock(&wdt_lock); |
228 | /* Fall */ | 256 | /* Fall */ |
229 | case WDIOC_GETTIMEOUT: | 257 | case WDIOC_GETTIMEOUT: |
@@ -241,96 +269,173 @@ static const struct file_operations omap_wdt_fops = { | |||
241 | .release = omap_wdt_release, | 269 | .release = omap_wdt_release, |
242 | }; | 270 | }; |
243 | 271 | ||
244 | static struct miscdevice omap_wdt_miscdev = { | ||
245 | .minor = WATCHDOG_MINOR, | ||
246 | .name = "watchdog", | ||
247 | .fops = &omap_wdt_fops, | ||
248 | }; | ||
249 | |||
250 | static int __init omap_wdt_probe(struct platform_device *pdev) | 272 | static int __init omap_wdt_probe(struct platform_device *pdev) |
251 | { | 273 | { |
252 | struct resource *res, *mem; | 274 | struct resource *res, *mem; |
275 | struct omap_wdt_dev *wdev; | ||
253 | int ret; | 276 | int ret; |
254 | 277 | ||
255 | /* reserve static register mappings */ | 278 | /* reserve static register mappings */ |
256 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 279 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
257 | if (!res) | 280 | if (!res) { |
258 | return -ENOENT; | 281 | ret = -ENOENT; |
282 | goto err_get_resource; | ||
283 | } | ||
284 | |||
285 | if (omap_wdt_dev) { | ||
286 | ret = -EBUSY; | ||
287 | goto err_busy; | ||
288 | } | ||
259 | 289 | ||
260 | mem = request_mem_region(res->start, res->end - res->start + 1, | 290 | mem = request_mem_region(res->start, res->end - res->start + 1, |
261 | pdev->name); | 291 | pdev->name); |
262 | if (mem == NULL) | 292 | if (!mem) { |
263 | return -EBUSY; | 293 | ret = -EBUSY; |
294 | goto err_busy; | ||
295 | } | ||
264 | 296 | ||
265 | platform_set_drvdata(pdev, mem); | 297 | wdev = kzalloc(sizeof(struct omap_wdt_dev), GFP_KERNEL); |
298 | if (!wdev) { | ||
299 | ret = -ENOMEM; | ||
300 | goto err_kzalloc; | ||
301 | } | ||
266 | 302 | ||
267 | omap_wdt_users = 0; | 303 | wdev->omap_wdt_users = 0; |
304 | wdev->mem = mem; | ||
268 | 305 | ||
269 | if (cpu_is_omap16xx()) { | 306 | if (cpu_is_omap16xx()) { |
270 | armwdt_ck = clk_get(&pdev->dev, "armwdt_ck"); | 307 | wdev->armwdt_ck = clk_get(&pdev->dev, "armwdt_ck"); |
271 | if (IS_ERR(armwdt_ck)) { | 308 | if (IS_ERR(wdev->armwdt_ck)) { |
272 | ret = PTR_ERR(armwdt_ck); | 309 | ret = PTR_ERR(wdev->armwdt_ck); |
273 | armwdt_ck = NULL; | 310 | wdev->armwdt_ck = NULL; |
274 | goto fail; | 311 | goto err_clk; |
275 | } | 312 | } |
276 | } | 313 | } |
277 | 314 | ||
278 | if (cpu_is_omap24xx()) { | 315 | if (cpu_is_omap24xx()) { |
279 | mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick"); | 316 | wdev->mpu_wdt_ick = clk_get(&pdev->dev, "mpu_wdt_ick"); |
280 | if (IS_ERR(mpu_wdt_ick)) { | 317 | if (IS_ERR(wdev->mpu_wdt_ick)) { |
281 | ret = PTR_ERR(mpu_wdt_ick); | 318 | ret = PTR_ERR(wdev->mpu_wdt_ick); |
282 | mpu_wdt_ick = NULL; | 319 | wdev->mpu_wdt_ick = NULL; |
283 | goto fail; | 320 | goto err_clk; |
284 | } | 321 | } |
285 | mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); | 322 | wdev->mpu_wdt_fck = clk_get(&pdev->dev, "mpu_wdt_fck"); |
286 | if (IS_ERR(mpu_wdt_fck)) { | 323 | if (IS_ERR(wdev->mpu_wdt_fck)) { |
287 | ret = PTR_ERR(mpu_wdt_fck); | 324 | ret = PTR_ERR(wdev->mpu_wdt_fck); |
288 | mpu_wdt_fck = NULL; | 325 | wdev->mpu_wdt_fck = NULL; |
289 | goto fail; | 326 | goto err_clk; |
290 | } | 327 | } |
291 | } | 328 | } |
292 | 329 | ||
293 | omap_wdt_disable(); | 330 | if (cpu_is_omap34xx()) { |
331 | wdev->mpu_wdt_ick = clk_get(&pdev->dev, "wdt2_ick"); | ||
332 | if (IS_ERR(wdev->mpu_wdt_ick)) { | ||
333 | ret = PTR_ERR(wdev->mpu_wdt_ick); | ||
334 | wdev->mpu_wdt_ick = NULL; | ||
335 | goto err_clk; | ||
336 | } | ||
337 | wdev->mpu_wdt_fck = clk_get(&pdev->dev, "wdt2_fck"); | ||
338 | if (IS_ERR(wdev->mpu_wdt_fck)) { | ||
339 | ret = PTR_ERR(wdev->mpu_wdt_fck); | ||
340 | wdev->mpu_wdt_fck = NULL; | ||
341 | goto err_clk; | ||
342 | } | ||
343 | } | ||
344 | wdev->base = ioremap(res->start, res->end - res->start + 1); | ||
345 | if (!wdev->base) { | ||
346 | ret = -ENOMEM; | ||
347 | goto err_ioremap; | ||
348 | } | ||
349 | |||
350 | platform_set_drvdata(pdev, wdev); | ||
351 | |||
352 | omap_wdt_disable(wdev); | ||
294 | omap_wdt_adjust_timeout(timer_margin); | 353 | omap_wdt_adjust_timeout(timer_margin); |
295 | 354 | ||
296 | omap_wdt_miscdev.parent = &pdev->dev; | 355 | wdev->omap_wdt_miscdev.parent = &pdev->dev; |
297 | ret = misc_register(&omap_wdt_miscdev); | 356 | wdev->omap_wdt_miscdev.minor = WATCHDOG_MINOR; |
357 | wdev->omap_wdt_miscdev.name = "watchdog"; | ||
358 | wdev->omap_wdt_miscdev.fops = &omap_wdt_fops; | ||
359 | |||
360 | ret = misc_register(&(wdev->omap_wdt_miscdev)); | ||
298 | if (ret) | 361 | if (ret) |
299 | goto fail; | 362 | goto err_misc; |
300 | 363 | ||
301 | pr_info("OMAP Watchdog Timer: initial timeout %d sec\n", timer_margin); | 364 | pr_info("OMAP Watchdog Timer Rev 0x%02x: initial timeout %d sec\n", |
365 | __raw_readl(wdev->base + OMAP_WATCHDOG_REV) & 0xFF, | ||
366 | timer_margin); | ||
302 | 367 | ||
303 | /* autogate OCP interface clock */ | 368 | /* autogate OCP interface clock */ |
304 | omap_writel(0x01, OMAP_WATCHDOG_SYS_CONFIG); | 369 | __raw_writel(0x01, wdev->base + OMAP_WATCHDOG_SYS_CONFIG); |
370 | |||
371 | omap_wdt_dev = pdev; | ||
372 | |||
305 | return 0; | 373 | return 0; |
306 | 374 | ||
307 | fail: | 375 | err_misc: |
308 | if (armwdt_ck) | 376 | platform_set_drvdata(pdev, NULL); |
309 | clk_put(armwdt_ck); | 377 | iounmap(wdev->base); |
310 | if (mpu_wdt_ick) | 378 | |
311 | clk_put(mpu_wdt_ick); | 379 | err_ioremap: |
312 | if (mpu_wdt_fck) | 380 | wdev->base = NULL; |
313 | clk_put(mpu_wdt_fck); | 381 | |
314 | release_resource(mem); | 382 | err_clk: |
383 | if (wdev->armwdt_ck) | ||
384 | clk_put(wdev->armwdt_ck); | ||
385 | if (wdev->mpu_wdt_ick) | ||
386 | clk_put(wdev->mpu_wdt_ick); | ||
387 | if (wdev->mpu_wdt_fck) | ||
388 | clk_put(wdev->mpu_wdt_fck); | ||
389 | kfree(wdev); | ||
390 | |||
391 | err_kzalloc: | ||
392 | release_mem_region(res->start, res->end - res->start + 1); | ||
393 | |||
394 | err_busy: | ||
395 | err_get_resource: | ||
396 | |||
315 | return ret; | 397 | return ret; |
316 | } | 398 | } |
317 | 399 | ||
318 | static void omap_wdt_shutdown(struct platform_device *pdev) | 400 | static void omap_wdt_shutdown(struct platform_device *pdev) |
319 | { | 401 | { |
320 | omap_wdt_disable(); | 402 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
403 | |||
404 | if (wdev->omap_wdt_users) | ||
405 | omap_wdt_disable(wdev); | ||
321 | } | 406 | } |
322 | 407 | ||
323 | static int omap_wdt_remove(struct platform_device *pdev) | 408 | static int omap_wdt_remove(struct platform_device *pdev) |
324 | { | 409 | { |
325 | struct resource *mem = platform_get_drvdata(pdev); | 410 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
326 | misc_deregister(&omap_wdt_miscdev); | 411 | struct resource *res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
327 | release_resource(mem); | 412 | |
328 | if (armwdt_ck) | 413 | if (!res) |
329 | clk_put(armwdt_ck); | 414 | return -ENOENT; |
330 | if (mpu_wdt_ick) | 415 | |
331 | clk_put(mpu_wdt_ick); | 416 | misc_deregister(&(wdev->omap_wdt_miscdev)); |
332 | if (mpu_wdt_fck) | 417 | release_mem_region(res->start, res->end - res->start + 1); |
333 | clk_put(mpu_wdt_fck); | 418 | platform_set_drvdata(pdev, NULL); |
419 | |||
420 | if (wdev->armwdt_ck) { | ||
421 | clk_put(wdev->armwdt_ck); | ||
422 | wdev->armwdt_ck = NULL; | ||
423 | } | ||
424 | |||
425 | if (wdev->mpu_wdt_ick) { | ||
426 | clk_put(wdev->mpu_wdt_ick); | ||
427 | wdev->mpu_wdt_ick = NULL; | ||
428 | } | ||
429 | |||
430 | if (wdev->mpu_wdt_fck) { | ||
431 | clk_put(wdev->mpu_wdt_fck); | ||
432 | wdev->mpu_wdt_fck = NULL; | ||
433 | } | ||
434 | iounmap(wdev->base); | ||
435 | |||
436 | kfree(wdev); | ||
437 | omap_wdt_dev = NULL; | ||
438 | |||
334 | return 0; | 439 | return 0; |
335 | } | 440 | } |
336 | 441 | ||
@@ -344,17 +449,23 @@ static int omap_wdt_remove(struct platform_device *pdev) | |||
344 | 449 | ||
345 | static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) | 450 | static int omap_wdt_suspend(struct platform_device *pdev, pm_message_t state) |
346 | { | 451 | { |
347 | if (omap_wdt_users) | 452 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
348 | omap_wdt_disable(); | 453 | |
454 | if (wdev->omap_wdt_users) | ||
455 | omap_wdt_disable(wdev); | ||
456 | |||
349 | return 0; | 457 | return 0; |
350 | } | 458 | } |
351 | 459 | ||
352 | static int omap_wdt_resume(struct platform_device *pdev) | 460 | static int omap_wdt_resume(struct platform_device *pdev) |
353 | { | 461 | { |
354 | if (omap_wdt_users) { | 462 | struct omap_wdt_dev *wdev = platform_get_drvdata(pdev); |
355 | omap_wdt_enable(); | 463 | |
356 | omap_wdt_ping(); | 464 | if (wdev->omap_wdt_users) { |
465 | omap_wdt_enable(wdev); | ||
466 | omap_wdt_ping(wdev); | ||
357 | } | 467 | } |
468 | |||
358 | return 0; | 469 | return 0; |
359 | } | 470 | } |
360 | 471 | ||
diff --git a/drivers/watchdog/omap_wdt.h b/drivers/watchdog/omap_wdt.h index 52a532a5114a..fc02ec6a0386 100644 --- a/drivers/watchdog/omap_wdt.h +++ b/drivers/watchdog/omap_wdt.h | |||
@@ -30,25 +30,15 @@ | |||
30 | #ifndef _OMAP_WATCHDOG_H | 30 | #ifndef _OMAP_WATCHDOG_H |
31 | #define _OMAP_WATCHDOG_H | 31 | #define _OMAP_WATCHDOG_H |
32 | 32 | ||
33 | #define OMAP1610_WATCHDOG_BASE 0xfffeb000 | 33 | #define OMAP_WATCHDOG_REV (0x00) |
34 | #define OMAP2420_WATCHDOG_BASE 0x48022000 /*WDT Timer 2 */ | 34 | #define OMAP_WATCHDOG_SYS_CONFIG (0x10) |
35 | 35 | #define OMAP_WATCHDOG_STATUS (0x14) | |
36 | #ifdef CONFIG_ARCH_OMAP24XX | 36 | #define OMAP_WATCHDOG_CNTRL (0x24) |
37 | #define OMAP_WATCHDOG_BASE OMAP2420_WATCHDOG_BASE | 37 | #define OMAP_WATCHDOG_CRR (0x28) |
38 | #else | 38 | #define OMAP_WATCHDOG_LDR (0x2c) |
39 | #define OMAP_WATCHDOG_BASE OMAP1610_WATCHDOG_BASE | 39 | #define OMAP_WATCHDOG_TGR (0x30) |
40 | #define RM_RSTST_WKUP 0 | 40 | #define OMAP_WATCHDOG_WPS (0x34) |
41 | #endif | 41 | #define OMAP_WATCHDOG_SPR (0x48) |
42 | |||
43 | #define OMAP_WATCHDOG_REV (OMAP_WATCHDOG_BASE + 0x00) | ||
44 | #define OMAP_WATCHDOG_SYS_CONFIG (OMAP_WATCHDOG_BASE + 0x10) | ||
45 | #define OMAP_WATCHDOG_STATUS (OMAP_WATCHDOG_BASE + 0x14) | ||
46 | #define OMAP_WATCHDOG_CNTRL (OMAP_WATCHDOG_BASE + 0x24) | ||
47 | #define OMAP_WATCHDOG_CRR (OMAP_WATCHDOG_BASE + 0x28) | ||
48 | #define OMAP_WATCHDOG_LDR (OMAP_WATCHDOG_BASE + 0x2c) | ||
49 | #define OMAP_WATCHDOG_TGR (OMAP_WATCHDOG_BASE + 0x30) | ||
50 | #define OMAP_WATCHDOG_WPS (OMAP_WATCHDOG_BASE + 0x34) | ||
51 | #define OMAP_WATCHDOG_SPR (OMAP_WATCHDOG_BASE + 0x48) | ||
52 | 42 | ||
53 | /* Using the prescaler, the OMAP watchdog could go for many | 43 | /* Using the prescaler, the OMAP watchdog could go for many |
54 | * months before firing. These limits work without scaling, | 44 | * months before firing. These limits work without scaling, |
diff --git a/drivers/watchdog/orion5x_wdt.c b/drivers/watchdog/orion5x_wdt.c new file mode 100644 index 000000000000..14a339f58b6a --- /dev/null +++ b/drivers/watchdog/orion5x_wdt.c | |||
@@ -0,0 +1,245 @@ | |||
1 | /* | ||
2 | * drivers/watchdog/orion5x_wdt.c | ||
3 | * | ||
4 | * Watchdog driver for Orion5x processors | ||
5 | * | ||
6 | * Author: Sylver Bruneau <sylver.bruneau@googlemail.com> | ||
7 | * | ||
8 | * This file is licensed under the terms of the GNU General Public | ||
9 | * License version 2. This program is licensed "as is" without any | ||
10 | * warranty of any kind, whether express or implied. | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/moduleparam.h> | ||
15 | #include <linux/types.h> | ||
16 | #include <linux/kernel.h> | ||
17 | #include <linux/fs.h> | ||
18 | #include <linux/miscdevice.h> | ||
19 | #include <linux/watchdog.h> | ||
20 | #include <linux/init.h> | ||
21 | #include <linux/uaccess.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/spinlock.h> | ||
24 | |||
25 | /* | ||
26 | * Watchdog timer block registers. | ||
27 | */ | ||
28 | #define TIMER_CTRL (TIMER_VIRT_BASE + 0x0000) | ||
29 | #define WDT_EN 0x0010 | ||
30 | #define WDT_VAL (TIMER_VIRT_BASE + 0x0024) | ||
31 | |||
32 | #define WDT_MAX_DURATION (0xffffffff / ORION5X_TCLK) | ||
33 | #define WDT_IN_USE 0 | ||
34 | #define WDT_OK_TO_CLOSE 1 | ||
35 | |||
36 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
37 | static int heartbeat = WDT_MAX_DURATION; /* (seconds) */ | ||
38 | static unsigned long wdt_status; | ||
39 | static spinlock_t wdt_lock; | ||
40 | |||
41 | static void wdt_enable(void) | ||
42 | { | ||
43 | u32 reg; | ||
44 | |||
45 | spin_lock(&wdt_lock); | ||
46 | |||
47 | /* Set watchdog duration */ | ||
48 | writel(ORION5X_TCLK * heartbeat, WDT_VAL); | ||
49 | |||
50 | /* Clear watchdog timer interrupt */ | ||
51 | reg = readl(BRIDGE_CAUSE); | ||
52 | reg &= ~WDT_INT_REQ; | ||
53 | writel(reg, BRIDGE_CAUSE); | ||
54 | |||
55 | /* Enable watchdog timer */ | ||
56 | reg = readl(TIMER_CTRL); | ||
57 | reg |= WDT_EN; | ||
58 | writel(reg, TIMER_CTRL); | ||
59 | |||
60 | /* Enable reset on watchdog */ | ||
61 | reg = readl(CPU_RESET_MASK); | ||
62 | reg |= WDT_RESET; | ||
63 | writel(reg, CPU_RESET_MASK); | ||
64 | |||
65 | spin_unlock(&wdt_lock); | ||
66 | } | ||
67 | |||
68 | static void wdt_disable(void) | ||
69 | { | ||
70 | u32 reg; | ||
71 | |||
72 | spin_lock(&wdt_lock); | ||
73 | |||
74 | /* Disable reset on watchdog */ | ||
75 | reg = readl(CPU_RESET_MASK); | ||
76 | reg &= ~WDT_RESET; | ||
77 | writel(reg, CPU_RESET_MASK); | ||
78 | |||
79 | /* Disable watchdog timer */ | ||
80 | reg = readl(TIMER_CTRL); | ||
81 | reg &= ~WDT_EN; | ||
82 | writel(reg, TIMER_CTRL); | ||
83 | |||
84 | spin_unlock(&wdt_lock); | ||
85 | } | ||
86 | |||
87 | static int orion5x_wdt_get_timeleft(int *time_left) | ||
88 | { | ||
89 | spin_lock(&wdt_lock); | ||
90 | *time_left = readl(WDT_VAL) / ORION5X_TCLK; | ||
91 | spin_unlock(&wdt_lock); | ||
92 | return 0; | ||
93 | } | ||
94 | |||
95 | static int orion5x_wdt_open(struct inode *inode, struct file *file) | ||
96 | { | ||
97 | if (test_and_set_bit(WDT_IN_USE, &wdt_status)) | ||
98 | return -EBUSY; | ||
99 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
100 | wdt_enable(); | ||
101 | return nonseekable_open(inode, file); | ||
102 | } | ||
103 | |||
104 | static ssize_t orion5x_wdt_write(struct file *file, const char *data, | ||
105 | size_t len, loff_t *ppos) | ||
106 | { | ||
107 | if (len) { | ||
108 | if (!nowayout) { | ||
109 | size_t i; | ||
110 | |||
111 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
112 | for (i = 0; i != len; i++) { | ||
113 | char c; | ||
114 | |||
115 | if (get_user(c, data + i)) | ||
116 | return -EFAULT; | ||
117 | if (c == 'V') | ||
118 | set_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
119 | } | ||
120 | } | ||
121 | wdt_enable(); | ||
122 | } | ||
123 | return len; | ||
124 | } | ||
125 | |||
126 | static struct watchdog_info ident = { | ||
127 | .options = WDIOF_MAGICCLOSE | WDIOF_SETTIMEOUT | | ||
128 | WDIOF_KEEPALIVEPING, | ||
129 | .identity = "Orion5x Watchdog", | ||
130 | }; | ||
131 | |||
132 | |||
133 | static long orion5x_wdt_ioctl(struct file *file, unsigned int cmd, | ||
134 | unsigned long arg) | ||
135 | { | ||
136 | int ret = -ENOTTY; | ||
137 | int time; | ||
138 | |||
139 | switch (cmd) { | ||
140 | case WDIOC_GETSUPPORT: | ||
141 | ret = copy_to_user((struct watchdog_info *)arg, &ident, | ||
142 | sizeof(ident)) ? -EFAULT : 0; | ||
143 | break; | ||
144 | |||
145 | case WDIOC_GETSTATUS: | ||
146 | case WDIOC_GETBOOTSTATUS: | ||
147 | ret = put_user(0, (int *)arg); | ||
148 | break; | ||
149 | |||
150 | case WDIOC_KEEPALIVE: | ||
151 | wdt_enable(); | ||
152 | ret = 0; | ||
153 | break; | ||
154 | |||
155 | case WDIOC_SETTIMEOUT: | ||
156 | ret = get_user(time, (int *)arg); | ||
157 | if (ret) | ||
158 | break; | ||
159 | |||
160 | if (time <= 0 || time > WDT_MAX_DURATION) { | ||
161 | ret = -EINVAL; | ||
162 | break; | ||
163 | } | ||
164 | heartbeat = time; | ||
165 | wdt_enable(); | ||
166 | /* Fall through */ | ||
167 | |||
168 | case WDIOC_GETTIMEOUT: | ||
169 | ret = put_user(heartbeat, (int *)arg); | ||
170 | break; | ||
171 | |||
172 | case WDIOC_GETTIMELEFT: | ||
173 | if (orion5x_wdt_get_timeleft(&time)) { | ||
174 | ret = -EINVAL; | ||
175 | break; | ||
176 | } | ||
177 | ret = put_user(time, (int *)arg); | ||
178 | break; | ||
179 | } | ||
180 | return ret; | ||
181 | } | ||
182 | |||
183 | static int orion5x_wdt_release(struct inode *inode, struct file *file) | ||
184 | { | ||
185 | if (test_bit(WDT_OK_TO_CLOSE, &wdt_status)) | ||
186 | wdt_disable(); | ||
187 | else | ||
188 | printk(KERN_CRIT "WATCHDOG: Device closed unexpectedly - " | ||
189 | "timer will not stop\n"); | ||
190 | clear_bit(WDT_IN_USE, &wdt_status); | ||
191 | clear_bit(WDT_OK_TO_CLOSE, &wdt_status); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | |||
197 | static const struct file_operations orion5x_wdt_fops = { | ||
198 | .owner = THIS_MODULE, | ||
199 | .llseek = no_llseek, | ||
200 | .write = orion5x_wdt_write, | ||
201 | .unlocked_ioctl = orion5x_wdt_ioctl, | ||
202 | .open = orion5x_wdt_open, | ||
203 | .release = orion5x_wdt_release, | ||
204 | }; | ||
205 | |||
206 | static struct miscdevice orion5x_wdt_miscdev = { | ||
207 | .minor = WATCHDOG_MINOR, | ||
208 | .name = "watchdog", | ||
209 | .fops = &orion5x_wdt_fops, | ||
210 | }; | ||
211 | |||
212 | static int __init orion5x_wdt_init(void) | ||
213 | { | ||
214 | int ret; | ||
215 | |||
216 | spin_lock_init(&wdt_lock); | ||
217 | |||
218 | ret = misc_register(&orion5x_wdt_miscdev); | ||
219 | if (ret == 0) | ||
220 | printk("Orion5x Watchdog Timer: heartbeat %d sec\n", | ||
221 | heartbeat); | ||
222 | |||
223 | return ret; | ||
224 | } | ||
225 | |||
226 | static void __exit orion5x_wdt_exit(void) | ||
227 | { | ||
228 | misc_deregister(&orion5x_wdt_miscdev); | ||
229 | } | ||
230 | |||
231 | module_init(orion5x_wdt_init); | ||
232 | module_exit(orion5x_wdt_exit); | ||
233 | |||
234 | MODULE_AUTHOR("Sylver Bruneau <sylver.bruneau@googlemail.com>"); | ||
235 | MODULE_DESCRIPTION("Orion5x Processor Watchdog"); | ||
236 | |||
237 | module_param(heartbeat, int, 0); | ||
238 | MODULE_PARM_DESC(heartbeat, "Watchdog heartbeat in seconds (default is " | ||
239 | __MODULE_STRING(WDT_MAX_DURATION) ")"); | ||
240 | |||
241 | module_param(nowayout, int, 0); | ||
242 | MODULE_PARM_DESC(nowayout, "Watchdog cannot be stopped once started"); | ||
243 | |||
244 | MODULE_LICENSE("GPL"); | ||
245 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/drivers/sbus/char/riowatchdog.c b/drivers/watchdog/riowd.c index 88c0fc6395e1..09cb1833ea27 100644 --- a/drivers/sbus/char/riowatchdog.c +++ b/drivers/watchdog/riowd.c | |||
@@ -1,7 +1,6 @@ | |||
1 | /* $Id: riowatchdog.c,v 1.3.2.2 2002/01/23 18:48:02 davem Exp $ | 1 | /* riowd.c - driver for hw watchdog inside Super I/O of RIO |
2 | * riowatchdog.c - driver for hw watchdog inside Super I/O of RIO | ||
3 | * | 2 | * |
4 | * Copyright (C) 2001 David S. Miller (davem@redhat.com) | 3 | * Copyright (C) 2001, 2008 David S. Miller (davem@davemloft.net) |
5 | */ | 4 | */ |
6 | 5 | ||
7 | #include <linux/kernel.h> | 6 | #include <linux/kernel.h> |
@@ -12,14 +11,13 @@ | |||
12 | #include <linux/init.h> | 11 | #include <linux/init.h> |
13 | #include <linux/miscdevice.h> | 12 | #include <linux/miscdevice.h> |
14 | #include <linux/smp_lock.h> | 13 | #include <linux/smp_lock.h> |
14 | #include <linux/watchdog.h> | ||
15 | #include <linux/of.h> | ||
16 | #include <linux/of_device.h> | ||
15 | 17 | ||
16 | #include <asm/io.h> | 18 | #include <asm/io.h> |
17 | #include <asm/ebus.h> | ||
18 | #include <asm/bbc.h> | ||
19 | #include <asm/oplib.h> | ||
20 | #include <asm/uaccess.h> | 19 | #include <asm/uaccess.h> |
21 | 20 | ||
22 | #include <asm/watchdog.h> | ||
23 | 21 | ||
24 | /* RIO uses the NatSemi Super I/O power management logical device | 22 | /* RIO uses the NatSemi Super I/O power management logical device |
25 | * as its' watchdog. | 23 | * as its' watchdog. |
@@ -45,74 +43,35 @@ | |||
45 | * The watchdog device generates no interrupts. | 43 | * The watchdog device generates no interrupts. |
46 | */ | 44 | */ |
47 | 45 | ||
48 | MODULE_AUTHOR("David S. Miller <davem@redhat.com>"); | 46 | MODULE_AUTHOR("David S. Miller <davem@davemloft.net>"); |
49 | MODULE_DESCRIPTION("Hardware watchdog driver for Sun RIO"); | 47 | MODULE_DESCRIPTION("Hardware watchdog driver for Sun RIO"); |
50 | MODULE_SUPPORTED_DEVICE("watchdog"); | 48 | MODULE_SUPPORTED_DEVICE("watchdog"); |
51 | MODULE_LICENSE("GPL"); | 49 | MODULE_LICENSE("GPL"); |
52 | 50 | ||
53 | #define RIOWD_NAME "pmc" | 51 | #define DRIVER_NAME "riowd" |
54 | #define RIOWD_MINOR 215 | 52 | #define PFX DRIVER_NAME ": " |
55 | 53 | ||
56 | static DEFINE_SPINLOCK(riowd_lock); | 54 | struct riowd { |
55 | void __iomem *regs; | ||
56 | spinlock_t lock; | ||
57 | }; | ||
58 | |||
59 | static struct riowd *riowd_device; | ||
57 | 60 | ||
58 | static void __iomem *bbc_regs; | ||
59 | static void __iomem *riowd_regs; | ||
60 | #define WDTO_INDEX 0x05 | 61 | #define WDTO_INDEX 0x05 |
61 | 62 | ||
62 | static int riowd_timeout = 1; /* in minutes */ | 63 | static int riowd_timeout = 1; /* in minutes */ |
63 | module_param(riowd_timeout, int, 0); | 64 | module_param(riowd_timeout, int, 0); |
64 | MODULE_PARM_DESC(riowd_timeout, "Watchdog timeout in minutes"); | 65 | MODULE_PARM_DESC(riowd_timeout, "Watchdog timeout in minutes"); |
65 | 66 | ||
66 | #if 0 /* Currently unused. */ | 67 | static void riowd_writereg(struct riowd *p, u8 val, int index) |
67 | static u8 riowd_readreg(int index) | ||
68 | { | 68 | { |
69 | unsigned long flags; | 69 | unsigned long flags; |
70 | u8 ret; | ||
71 | 70 | ||
72 | spin_lock_irqsave(&riowd_lock, flags); | 71 | spin_lock_irqsave(&p->lock, flags); |
73 | writeb(index, riowd_regs + 0); | 72 | writeb(index, p->regs + 0); |
74 | ret = readb(riowd_regs + 1); | 73 | writeb(val, p->regs + 1); |
75 | spin_unlock_irqrestore(&riowd_lock, flags); | 74 | spin_unlock_irqrestore(&p->lock, flags); |
76 | |||
77 | return ret; | ||
78 | } | ||
79 | #endif | ||
80 | |||
81 | static void riowd_writereg(u8 val, int index) | ||
82 | { | ||
83 | unsigned long flags; | ||
84 | |||
85 | spin_lock_irqsave(&riowd_lock, flags); | ||
86 | writeb(index, riowd_regs + 0); | ||
87 | writeb(val, riowd_regs + 1); | ||
88 | spin_unlock_irqrestore(&riowd_lock, flags); | ||
89 | } | ||
90 | |||
91 | static void riowd_pingtimer(void) | ||
92 | { | ||
93 | riowd_writereg(riowd_timeout, WDTO_INDEX); | ||
94 | } | ||
95 | |||
96 | static void riowd_stoptimer(void) | ||
97 | { | ||
98 | u8 val; | ||
99 | |||
100 | riowd_writereg(0, WDTO_INDEX); | ||
101 | |||
102 | val = readb(bbc_regs + BBC_WDACTION); | ||
103 | val &= ~BBC_WDACTION_RST; | ||
104 | writeb(val, bbc_regs + BBC_WDACTION); | ||
105 | } | ||
106 | |||
107 | static void riowd_starttimer(void) | ||
108 | { | ||
109 | u8 val; | ||
110 | |||
111 | riowd_writereg(riowd_timeout, WDTO_INDEX); | ||
112 | |||
113 | val = readb(bbc_regs + BBC_WDACTION); | ||
114 | val |= BBC_WDACTION_RST; | ||
115 | writeb(val, bbc_regs + BBC_WDACTION); | ||
116 | } | 75 | } |
117 | 76 | ||
118 | static int riowd_open(struct inode *inode, struct file *filp) | 77 | static int riowd_open(struct inode *inode, struct file *filp) |
@@ -131,9 +90,12 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, | |||
131 | unsigned int cmd, unsigned long arg) | 90 | unsigned int cmd, unsigned long arg) |
132 | { | 91 | { |
133 | static struct watchdog_info info = { | 92 | static struct watchdog_info info = { |
134 | WDIOF_SETTIMEOUT, 0, "Natl. Semiconductor PC97317" | 93 | .options = WDIOF_SETTIMEOUT, |
94 | .firmware_version = 1, | ||
95 | .identity = DRIVER_NAME, | ||
135 | }; | 96 | }; |
136 | void __user *argp = (void __user *)arg; | 97 | void __user *argp = (void __user *)arg; |
98 | struct riowd *p = riowd_device; | ||
137 | unsigned int options; | 99 | unsigned int options; |
138 | int new_margin; | 100 | int new_margin; |
139 | 101 | ||
@@ -150,7 +112,7 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, | |||
150 | break; | 112 | break; |
151 | 113 | ||
152 | case WDIOC_KEEPALIVE: | 114 | case WDIOC_KEEPALIVE: |
153 | riowd_pingtimer(); | 115 | riowd_writereg(p, riowd_timeout, WDTO_INDEX); |
154 | break; | 116 | break; |
155 | 117 | ||
156 | case WDIOC_SETOPTIONS: | 118 | case WDIOC_SETOPTIONS: |
@@ -158,9 +120,9 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, | |||
158 | return -EFAULT; | 120 | return -EFAULT; |
159 | 121 | ||
160 | if (options & WDIOS_DISABLECARD) | 122 | if (options & WDIOS_DISABLECARD) |
161 | riowd_stoptimer(); | 123 | riowd_writereg(p, 0, WDTO_INDEX); |
162 | else if (options & WDIOS_ENABLECARD) | 124 | else if (options & WDIOS_ENABLECARD) |
163 | riowd_starttimer(); | 125 | riowd_writereg(p, riowd_timeout, WDTO_INDEX); |
164 | else | 126 | else |
165 | return -EINVAL; | 127 | return -EINVAL; |
166 | 128 | ||
@@ -170,9 +132,9 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, | |||
170 | if (get_user(new_margin, (int __user *)argp)) | 132 | if (get_user(new_margin, (int __user *)argp)) |
171 | return -EFAULT; | 133 | return -EFAULT; |
172 | if ((new_margin < 60) || (new_margin > (255 * 60))) | 134 | if ((new_margin < 60) || (new_margin > (255 * 60))) |
173 | return -EINVAL; | 135 | return -EINVAL; |
174 | riowd_timeout = (new_margin + 59) / 60; | 136 | riowd_timeout = (new_margin + 59) / 60; |
175 | riowd_pingtimer(); | 137 | riowd_writereg(p, riowd_timeout, WDTO_INDEX); |
176 | /* Fall */ | 138 | /* Fall */ |
177 | 139 | ||
178 | case WDIOC_GETTIMEOUT: | 140 | case WDIOC_GETTIMEOUT: |
@@ -187,8 +149,10 @@ static int riowd_ioctl(struct inode *inode, struct file *filp, | |||
187 | 149 | ||
188 | static ssize_t riowd_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) | 150 | static ssize_t riowd_write(struct file *file, const char __user *buf, size_t count, loff_t *ppos) |
189 | { | 151 | { |
152 | struct riowd *p = riowd_device; | ||
153 | |||
190 | if (count) { | 154 | if (count) { |
191 | riowd_pingtimer(); | 155 | riowd_writereg(p, riowd_timeout, WDTO_INDEX); |
192 | return 1; | 156 | return 1; |
193 | } | 157 | } |
194 | 158 | ||
@@ -197,99 +161,99 @@ static ssize_t riowd_write(struct file *file, const char __user *buf, size_t cou | |||
197 | 161 | ||
198 | static const struct file_operations riowd_fops = { | 162 | static const struct file_operations riowd_fops = { |
199 | .owner = THIS_MODULE, | 163 | .owner = THIS_MODULE, |
164 | .llseek = no_llseek, | ||
200 | .ioctl = riowd_ioctl, | 165 | .ioctl = riowd_ioctl, |
201 | .open = riowd_open, | 166 | .open = riowd_open, |
202 | .write = riowd_write, | 167 | .write = riowd_write, |
203 | .release = riowd_release, | 168 | .release = riowd_release, |
204 | }; | 169 | }; |
205 | 170 | ||
206 | static struct miscdevice riowd_miscdev = { RIOWD_MINOR, RIOWD_NAME, &riowd_fops }; | 171 | static struct miscdevice riowd_miscdev = { |
172 | .minor = WATCHDOG_MINOR, | ||
173 | .name = "watchdog", | ||
174 | .fops = &riowd_fops | ||
175 | }; | ||
207 | 176 | ||
208 | static int __init riowd_bbc_init(void) | 177 | static int __devinit riowd_probe(struct of_device *op, |
178 | const struct of_device_id *match) | ||
209 | { | 179 | { |
210 | struct linux_ebus *ebus = NULL; | 180 | struct riowd *p; |
211 | struct linux_ebus_device *edev = NULL; | 181 | int err = -EINVAL; |
212 | u8 val; | ||
213 | |||
214 | for_each_ebus(ebus) { | ||
215 | for_each_ebusdev(edev, ebus) { | ||
216 | if (!strcmp(edev->ofdev.node->name, "bbc")) | ||
217 | goto found_bbc; | ||
218 | } | ||
219 | } | ||
220 | 182 | ||
221 | found_bbc: | 183 | if (riowd_device) |
222 | if (!edev) | 184 | goto out; |
223 | return -ENODEV; | ||
224 | bbc_regs = ioremap(edev->resource[0].start, BBC_REGS_SIZE); | ||
225 | if (!bbc_regs) | ||
226 | return -ENODEV; | ||
227 | 185 | ||
228 | /* Turn it off. */ | 186 | err = -ENOMEM; |
229 | val = readb(bbc_regs + BBC_WDACTION); | 187 | p = kzalloc(sizeof(*p), GFP_KERNEL); |
230 | val &= ~BBC_WDACTION_RST; | 188 | if (!p) |
231 | writeb(val, bbc_regs + BBC_WDACTION); | 189 | goto out; |
232 | 190 | ||
233 | return 0; | 191 | spin_lock_init(&p->lock); |
234 | } | ||
235 | 192 | ||
236 | static int __init riowd_init(void) | 193 | p->regs = of_ioremap(&op->resource[0], 0, 2, DRIVER_NAME); |
237 | { | 194 | if (!p->regs) { |
238 | struct linux_ebus *ebus = NULL; | 195 | printk(KERN_ERR PFX "Cannot map registers.\n"); |
239 | struct linux_ebus_device *edev = NULL; | 196 | goto out_free; |
240 | |||
241 | for_each_ebus(ebus) { | ||
242 | for_each_ebusdev(edev, ebus) { | ||
243 | if (!strcmp(edev->ofdev.node->name, RIOWD_NAME)) | ||
244 | goto ebus_done; | ||
245 | } | ||
246 | } | 197 | } |
247 | 198 | ||
248 | ebus_done: | 199 | err = misc_register(&riowd_miscdev); |
249 | if (!edev) | 200 | if (err) { |
250 | goto fail; | 201 | printk(KERN_ERR PFX "Cannot register watchdog misc device.\n"); |
251 | 202 | goto out_iounmap; | |
252 | riowd_regs = ioremap(edev->resource[0].start, 2); | ||
253 | if (riowd_regs == NULL) { | ||
254 | printk(KERN_ERR "pmc: Cannot map registers.\n"); | ||
255 | return -ENODEV; | ||
256 | } | 203 | } |
257 | 204 | ||
258 | if (riowd_bbc_init()) { | 205 | printk(KERN_INFO PFX "Hardware watchdog [%i minutes], " |
259 | printk(KERN_ERR "pmc: Failure initializing BBC config.\n"); | 206 | "regs at %p\n", riowd_timeout, p->regs); |
260 | goto fail; | ||
261 | } | ||
262 | 207 | ||
263 | if (misc_register(&riowd_miscdev)) { | 208 | dev_set_drvdata(&op->dev, p); |
264 | printk(KERN_ERR "pmc: Cannot register watchdog misc device.\n"); | 209 | riowd_device = p; |
265 | goto fail; | 210 | err = 0; |
266 | } | ||
267 | 211 | ||
268 | printk(KERN_INFO "pmc: Hardware watchdog [%i minutes], " | 212 | out_iounmap: |
269 | "regs at %p\n", riowd_timeout, riowd_regs); | 213 | of_iounmap(&op->resource[0], p->regs, 2); |
270 | 214 | ||
271 | return 0; | 215 | out_free: |
216 | kfree(p); | ||
272 | 217 | ||
273 | fail: | 218 | out: |
274 | if (riowd_regs) { | 219 | return err; |
275 | iounmap(riowd_regs); | ||
276 | riowd_regs = NULL; | ||
277 | } | ||
278 | if (bbc_regs) { | ||
279 | iounmap(bbc_regs); | ||
280 | bbc_regs = NULL; | ||
281 | } | ||
282 | return -ENODEV; | ||
283 | } | 220 | } |
284 | 221 | ||
285 | static void __exit riowd_cleanup(void) | 222 | static int __devexit riowd_remove(struct of_device *op) |
286 | { | 223 | { |
224 | struct riowd *p = dev_get_drvdata(&op->dev); | ||
225 | |||
287 | misc_deregister(&riowd_miscdev); | 226 | misc_deregister(&riowd_miscdev); |
288 | iounmap(riowd_regs); | 227 | of_iounmap(&op->resource[0], p->regs, 2); |
289 | riowd_regs = NULL; | 228 | kfree(p); |
290 | iounmap(bbc_regs); | 229 | |
291 | bbc_regs = NULL; | 230 | return 0; |
231 | } | ||
232 | |||
233 | static const struct of_device_id riowd_match[] = { | ||
234 | { | ||
235 | .name = "pmc", | ||
236 | }, | ||
237 | {}, | ||
238 | }; | ||
239 | MODULE_DEVICE_TABLE(of, riowd_match); | ||
240 | |||
241 | static struct of_platform_driver riowd_driver = { | ||
242 | .name = DRIVER_NAME, | ||
243 | .match_table = riowd_match, | ||
244 | .probe = riowd_probe, | ||
245 | .remove = __devexit_p(riowd_remove), | ||
246 | }; | ||
247 | |||
248 | static int __init riowd_init(void) | ||
249 | { | ||
250 | return of_register_driver(&riowd_driver, &of_bus_type); | ||
251 | } | ||
252 | |||
253 | static void __exit riowd_exit(void) | ||
254 | { | ||
255 | of_unregister_driver(&riowd_driver); | ||
292 | } | 256 | } |
293 | 257 | ||
294 | module_init(riowd_init); | 258 | module_init(riowd_init); |
295 | module_exit(riowd_cleanup); | 259 | module_exit(riowd_exit); |
diff --git a/drivers/watchdog/w83697ug_wdt.c b/drivers/watchdog/w83697ug_wdt.c new file mode 100644 index 000000000000..c73b5e2919c6 --- /dev/null +++ b/drivers/watchdog/w83697ug_wdt.c | |||
@@ -0,0 +1,392 @@ | |||
1 | /* | ||
2 | * w83697ug/uf WDT driver | ||
3 | * | ||
4 | * (c) Copyright 2008 Flemming Fransen <ff@nrvissing.net> | ||
5 | * reused original code to supoprt w83697ug/uf. | ||
6 | * | ||
7 | * Based on w83627hf_wdt.c which is based on advantechwdt.c | ||
8 | * which is based on wdt.c. | ||
9 | * Original copyright messages: | ||
10 | * | ||
11 | * (c) Copyright 2007 Vlad Drukker <vlad@storewiz.com> | ||
12 | * added support for W83627THF. | ||
13 | * | ||
14 | * (c) Copyright 2003 Pádraig Brady <P@draigBrady.com> | ||
15 | * | ||
16 | * (c) Copyright 2000-2001 Marek Michalkiewicz <marekm@linux.org.pl> | ||
17 | * | ||
18 | * (c) Copyright 1996 Alan Cox <alan@redhat.com>, All Rights Reserved. | ||
19 | * http://www.redhat.com | ||
20 | * | ||
21 | * This program is free software; you can redistribute it and/or | ||
22 | * modify it under the terms of the GNU General Public License | ||
23 | * as published by the Free Software Foundation; either version | ||
24 | * 2 of the License, or (at your option) any later version. | ||
25 | * | ||
26 | * Neither Alan Cox nor CymruNet Ltd. admit liability nor provide | ||
27 | * warranty for any of this software. This material is provided | ||
28 | * "AS-IS" and at no charge. | ||
29 | * | ||
30 | * (c) Copyright 1995 Alan Cox <alan@redhat.com> | ||
31 | */ | ||
32 | |||
33 | #include <linux/module.h> | ||
34 | #include <linux/moduleparam.h> | ||
35 | #include <linux/types.h> | ||
36 | #include <linux/miscdevice.h> | ||
37 | #include <linux/watchdog.h> | ||
38 | #include <linux/fs.h> | ||
39 | #include <linux/ioport.h> | ||
40 | #include <linux/notifier.h> | ||
41 | #include <linux/reboot.h> | ||
42 | #include <linux/init.h> | ||
43 | #include <linux/spinlock.h> | ||
44 | #include <linux/io.h> | ||
45 | #include <linux/uaccess.h> | ||
46 | |||
47 | #include <asm/system.h> | ||
48 | |||
49 | #define WATCHDOG_NAME "w83697ug/uf WDT" | ||
50 | #define PFX WATCHDOG_NAME ": " | ||
51 | #define WATCHDOG_TIMEOUT 60 /* 60 sec default timeout */ | ||
52 | |||
53 | static unsigned long wdt_is_open; | ||
54 | static char expect_close; | ||
55 | static DEFINE_SPINLOCK(io_lock); | ||
56 | |||
57 | static int wdt_io = 0x2e; | ||
58 | module_param(wdt_io, int, 0); | ||
59 | MODULE_PARM_DESC(wdt_io, "w83697ug/uf WDT io port (default 0x2e)"); | ||
60 | |||
61 | static int timeout = WATCHDOG_TIMEOUT; /* in seconds */ | ||
62 | module_param(timeout, int, 0); | ||
63 | MODULE_PARM_DESC(timeout, | ||
64 | "Watchdog timeout in seconds. 1<= timeout <=255 (default=" | ||
65 | __MODULE_STRING(WATCHDOG_TIMEOUT) ")"); | ||
66 | |||
67 | static int nowayout = WATCHDOG_NOWAYOUT; | ||
68 | module_param(nowayout, int, 0); | ||
69 | MODULE_PARM_DESC(nowayout, | ||
70 | "Watchdog cannot be stopped once started (default=" | ||
71 | __MODULE_STRING(WATCHDOG_NOWAYOUT) ")"); | ||
72 | |||
73 | /* | ||
74 | * Kernel methods. | ||
75 | */ | ||
76 | |||
77 | #define WDT_EFER (wdt_io+0) /* Extended Function Enable Registers */ | ||
78 | #define WDT_EFIR (wdt_io+0) /* Extended Function Index Register | ||
79 | (same as EFER) */ | ||
80 | #define WDT_EFDR (WDT_EFIR+1) /* Extended Function Data Register */ | ||
81 | |||
82 | static void w83697ug_select_wd_register(void) | ||
83 | { | ||
84 | unsigned char c; | ||
85 | unsigned char version; | ||
86 | |||
87 | outb_p(0x87, WDT_EFER); /* Enter extended function mode */ | ||
88 | outb_p(0x87, WDT_EFER); /* Again according to manual */ | ||
89 | |||
90 | outb(0x20, WDT_EFER); /* check chip version */ | ||
91 | version = inb(WDT_EFDR); | ||
92 | |||
93 | if (version == 0x68) { /* W83697UG */ | ||
94 | printk(KERN_INFO PFX "Watchdog chip version 0x%02x = " | ||
95 | "W83697UG/UF found at 0x%04x\n", version, wdt_io); | ||
96 | |||
97 | outb_p(0x2b, WDT_EFER); | ||
98 | c = inb_p(WDT_EFDR); /* select WDT0 */ | ||
99 | c &= ~0x04; | ||
100 | outb_p(0x2b, WDT_EFER); | ||
101 | outb_p(c, WDT_EFDR); /* set pin118 to WDT0 */ | ||
102 | |||
103 | } else { | ||
104 | printk(KERN_ERR PFX "No W83697UG/UF could be found\n"); | ||
105 | return -EIO; | ||
106 | } | ||
107 | |||
108 | outb_p(0x07, WDT_EFER); /* point to logical device number reg */ | ||
109 | outb_p(0x08, WDT_EFDR); /* select logical device 8 (GPIO2) */ | ||
110 | outb_p(0x30, WDT_EFER); /* select CR30 */ | ||
111 | c = inb_p(WDT_EFDR); | ||
112 | outb_p(c || 0x01, WDT_EFDR); /* set bit 0 to activate GPIO2 */ | ||
113 | } | ||
114 | |||
115 | static void w83697ug_unselect_wd_register(void) | ||
116 | { | ||
117 | outb_p(0xAA, WDT_EFER); /* Leave extended function mode */ | ||
118 | } | ||
119 | |||
120 | static void w83697ug_init(void) | ||
121 | { | ||
122 | unsigned char t; | ||
123 | |||
124 | w83697ug_select_wd_register(); | ||
125 | |||
126 | outb_p(0xF6, WDT_EFER); /* Select CRF6 */ | ||
127 | t = inb_p(WDT_EFDR); /* read CRF6 */ | ||
128 | if (t != 0) { | ||
129 | printk(KERN_INFO PFX "Watchdog already running." | ||
130 | " Resetting timeout to %d sec\n", timeout); | ||
131 | outb_p(timeout, WDT_EFDR); /* Write back to CRF6 */ | ||
132 | } | ||
133 | outb_p(0xF5, WDT_EFER); /* Select CRF5 */ | ||
134 | t = inb_p(WDT_EFDR); /* read CRF5 */ | ||
135 | t &= ~0x0C; /* set second mode & | ||
136 | disable keyboard turning off watchdog */ | ||
137 | outb_p(t, WDT_EFDR); /* Write back to CRF5 */ | ||
138 | |||
139 | w83697ug_unselect_wd_register(); | ||
140 | } | ||
141 | |||
142 | static void wdt_ctrl(int timeout) | ||
143 | { | ||
144 | spin_lock(&io_lock); | ||
145 | |||
146 | w83697ug_select_wd_register(); | ||
147 | |||
148 | outb_p(0xF4, WDT_EFER); /* Select CRF4 */ | ||
149 | outb_p(timeout, WDT_EFDR); /* Write Timeout counter to CRF4 */ | ||
150 | |||
151 | w83697ug_unselect_wd_register(); | ||
152 | |||
153 | spin_unlock(&io_lock); | ||
154 | } | ||
155 | |||
156 | static int wdt_ping(void) | ||
157 | { | ||
158 | wdt_ctrl(timeout); | ||
159 | return 0; | ||
160 | } | ||
161 | |||
162 | static int wdt_disable(void) | ||
163 | { | ||
164 | wdt_ctrl(0); | ||
165 | return 0; | ||
166 | } | ||
167 | |||
168 | static int wdt_set_heartbeat(int t) | ||
169 | { | ||
170 | if (t < 1 || t > 255) | ||
171 | return -EINVAL; | ||
172 | |||
173 | timeout = t; | ||
174 | return 0; | ||
175 | } | ||
176 | |||
177 | static ssize_t wdt_write(struct file *file, const char __user *buf, | ||
178 | size_t count, loff_t *ppos) | ||
179 | { | ||
180 | if (count) { | ||
181 | if (!nowayout) { | ||
182 | size_t i; | ||
183 | |||
184 | expect_close = 0; | ||
185 | |||
186 | for (i = 0; i != count; i++) { | ||
187 | char c; | ||
188 | if (get_user(c, buf + i)) | ||
189 | return -EFAULT; | ||
190 | if (c == 'V') | ||
191 | expect_close = 42; | ||
192 | } | ||
193 | } | ||
194 | wdt_ping(); | ||
195 | } | ||
196 | return count; | ||
197 | } | ||
198 | |||
199 | static long wdt_ioctl(struct file *file, unsigned int cmd, unsigned long arg) | ||
200 | { | ||
201 | void __user *argp = (void __user *)arg; | ||
202 | int __user *p = argp; | ||
203 | int new_timeout; | ||
204 | static const struct watchdog_info ident = { | ||
205 | .options = WDIOF_KEEPALIVEPING | | ||
206 | WDIOF_SETTIMEOUT | | ||
207 | WDIOF_MAGICCLOSE, | ||
208 | .firmware_version = 1, | ||
209 | .identity = "W83697UG WDT", | ||
210 | }; | ||
211 | |||
212 | switch (cmd) { | ||
213 | case WDIOC_GETSUPPORT: | ||
214 | if (copy_to_user(argp, &ident, sizeof(ident))) | ||
215 | return -EFAULT; | ||
216 | break; | ||
217 | |||
218 | case WDIOC_GETSTATUS: | ||
219 | case WDIOC_GETBOOTSTATUS: | ||
220 | return put_user(0, p); | ||
221 | |||
222 | case WDIOC_SETOPTIONS: | ||
223 | { | ||
224 | int options, retval = -EINVAL; | ||
225 | |||
226 | if (get_user(options, p)) | ||
227 | return -EFAULT; | ||
228 | |||
229 | if (options & WDIOS_DISABLECARD) { | ||
230 | wdt_disable(); | ||
231 | retval = 0; | ||
232 | } | ||
233 | |||
234 | if (options & WDIOS_ENABLECARD) { | ||
235 | wdt_ping(); | ||
236 | retval = 0; | ||
237 | } | ||
238 | |||
239 | return retval; | ||
240 | } | ||
241 | |||
242 | case WDIOC_KEEPALIVE: | ||
243 | wdt_ping(); | ||
244 | break; | ||
245 | |||
246 | case WDIOC_SETTIMEOUT: | ||
247 | if (get_user(new_timeout, p)) | ||
248 | return -EFAULT; | ||
249 | if (wdt_set_heartbeat(new_timeout)) | ||
250 | return -EINVAL; | ||
251 | wdt_ping(); | ||
252 | /* Fall */ | ||
253 | |||
254 | case WDIOC_GETTIMEOUT: | ||
255 | return put_user(timeout, p); | ||
256 | |||
257 | default: | ||
258 | return -ENOTTY; | ||
259 | } | ||
260 | return 0; | ||
261 | } | ||
262 | |||
263 | static int wdt_open(struct inode *inode, struct file *file) | ||
264 | { | ||
265 | if (test_and_set_bit(0, &wdt_is_open)) | ||
266 | return -EBUSY; | ||
267 | /* | ||
268 | * Activate | ||
269 | */ | ||
270 | |||
271 | wdt_ping(); | ||
272 | return nonseekable_open(inode, file); | ||
273 | } | ||
274 | |||
275 | static int wdt_close(struct inode *inode, struct file *file) | ||
276 | { | ||
277 | if (expect_close == 42) | ||
278 | wdt_disable(); | ||
279 | else { | ||
280 | printk(KERN_CRIT PFX | ||
281 | "Unexpected close, not stopping watchdog!\n"); | ||
282 | wdt_ping(); | ||
283 | } | ||
284 | expect_close = 0; | ||
285 | clear_bit(0, &wdt_is_open); | ||
286 | return 0; | ||
287 | } | ||
288 | |||
289 | /* | ||
290 | * Notifier for system down | ||
291 | */ | ||
292 | |||
293 | static int wdt_notify_sys(struct notifier_block *this, unsigned long code, | ||
294 | void *unused) | ||
295 | { | ||
296 | if (code == SYS_DOWN || code == SYS_HALT) | ||
297 | wdt_disable(); /* Turn the WDT off */ | ||
298 | |||
299 | return NOTIFY_DONE; | ||
300 | } | ||
301 | |||
302 | /* | ||
303 | * Kernel Interfaces | ||
304 | */ | ||
305 | |||
306 | static const struct file_operations wdt_fops = { | ||
307 | .owner = THIS_MODULE, | ||
308 | .llseek = no_llseek, | ||
309 | .write = wdt_write, | ||
310 | .unlocked_ioctl = wdt_ioctl, | ||
311 | .open = wdt_open, | ||
312 | .release = wdt_close, | ||
313 | }; | ||
314 | |||
315 | static struct miscdevice wdt_miscdev = { | ||
316 | .minor = WATCHDOG_MINOR, | ||
317 | .name = "watchdog", | ||
318 | .fops = &wdt_fops, | ||
319 | }; | ||
320 | |||
321 | /* | ||
322 | * The WDT needs to learn about soft shutdowns in order to | ||
323 | * turn the timebomb registers off. | ||
324 | */ | ||
325 | |||
326 | static struct notifier_block wdt_notifier = { | ||
327 | .notifier_call = wdt_notify_sys, | ||
328 | }; | ||
329 | |||
330 | static int __init wdt_init(void) | ||
331 | { | ||
332 | int ret; | ||
333 | |||
334 | printk(KERN_INFO "WDT driver for the Winbond(TM) W83697UG/UF Super I/O chip initialising.\n"); | ||
335 | |||
336 | if (wdt_set_heartbeat(timeout)) { | ||
337 | wdt_set_heartbeat(WATCHDOG_TIMEOUT); | ||
338 | printk(KERN_INFO PFX | ||
339 | "timeout value must be 1<=timeout<=255, using %d\n", | ||
340 | WATCHDOG_TIMEOUT); | ||
341 | } | ||
342 | |||
343 | if (!request_region(wdt_io, 1, WATCHDOG_NAME)) { | ||
344 | printk(KERN_ERR PFX "I/O address 0x%04x already in use\n", | ||
345 | wdt_io); | ||
346 | ret = -EIO; | ||
347 | goto out; | ||
348 | } | ||
349 | |||
350 | w83697ug_init(); | ||
351 | |||
352 | ret = register_reboot_notifier(&wdt_notifier); | ||
353 | if (ret != 0) { | ||
354 | printk(KERN_ERR PFX | ||
355 | "cannot register reboot notifier (err=%d)\n", ret); | ||
356 | goto unreg_regions; | ||
357 | } | ||
358 | |||
359 | ret = misc_register(&wdt_miscdev); | ||
360 | if (ret != 0) { | ||
361 | printk(KERN_ERR PFX | ||
362 | "cannot register miscdev on minor=%d (err=%d)\n", | ||
363 | WATCHDOG_MINOR, ret); | ||
364 | goto unreg_reboot; | ||
365 | } | ||
366 | |||
367 | printk(KERN_INFO PFX "initialized. timeout=%d sec (nowayout=%d)\n", | ||
368 | timeout, nowayout); | ||
369 | |||
370 | out: | ||
371 | return ret; | ||
372 | unreg_reboot: | ||
373 | unregister_reboot_notifier(&wdt_notifier); | ||
374 | unreg_regions: | ||
375 | release_region(wdt_io, 1); | ||
376 | goto out; | ||
377 | } | ||
378 | |||
379 | static void __exit wdt_exit(void) | ||
380 | { | ||
381 | misc_deregister(&wdt_miscdev); | ||
382 | unregister_reboot_notifier(&wdt_notifier); | ||
383 | release_region(wdt_io, 1); | ||
384 | } | ||
385 | |||
386 | module_init(wdt_init); | ||
387 | module_exit(wdt_exit); | ||
388 | |||
389 | MODULE_LICENSE("GPL"); | ||
390 | MODULE_AUTHOR("Flemming Frandsen <ff@nrvissing.net>"); | ||
391 | MODULE_DESCRIPTION("w83697ug/uf WDT driver"); | ||
392 | MODULE_ALIAS_MISCDEV(WATCHDOG_MINOR); | ||
diff --git a/fs/ioctl.c b/fs/ioctl.c index 33a6b7ecb8b8..d152856c371b 100644 --- a/fs/ioctl.c +++ b/fs/ioctl.c | |||
@@ -226,6 +226,8 @@ static int ioctl_fiemap(struct file *filp, unsigned long arg) | |||
226 | return error; | 226 | return error; |
227 | } | 227 | } |
228 | 228 | ||
229 | #ifdef CONFIG_BLOCK | ||
230 | |||
229 | #define blk_to_logical(inode, blk) (blk << (inode)->i_blkbits) | 231 | #define blk_to_logical(inode, blk) (blk << (inode)->i_blkbits) |
230 | #define logical_to_blk(inode, offset) (offset >> (inode)->i_blkbits); | 232 | #define logical_to_blk(inode, offset) (offset >> (inode)->i_blkbits); |
231 | 233 | ||
@@ -342,6 +344,8 @@ int generic_block_fiemap(struct inode *inode, | |||
342 | } | 344 | } |
343 | EXPORT_SYMBOL(generic_block_fiemap); | 345 | EXPORT_SYMBOL(generic_block_fiemap); |
344 | 346 | ||
347 | #endif /* CONFIG_BLOCK */ | ||
348 | |||
345 | static int file_ioctl(struct file *filp, unsigned int cmd, | 349 | static int file_ioctl(struct file *filp, unsigned int cmd, |
346 | unsigned long arg) | 350 | unsigned long arg) |
347 | { | 351 | { |
diff --git a/include/linux/key.h b/include/linux/key.h index c45c962d1cc5..1b70e35a71e3 100644 --- a/include/linux/key.h +++ b/include/linux/key.h | |||
@@ -299,6 +299,7 @@ extern void key_init(void); | |||
299 | #define key_validate(k) 0 | 299 | #define key_validate(k) 0 |
300 | #define key_serial(k) 0 | 300 | #define key_serial(k) 0 |
301 | #define key_get(k) ({ NULL; }) | 301 | #define key_get(k) ({ NULL; }) |
302 | #define key_revoke(k) do { } while(0) | ||
302 | #define key_put(k) do { } while(0) | 303 | #define key_put(k) do { } while(0) |
303 | #define key_ref_put(k) do { } while(0) | 304 | #define key_ref_put(k) do { } while(0) |
304 | #define make_key_ref(k, p) ({ NULL; }) | 305 | #define make_key_ref(k, p) ({ NULL; }) |
diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 9c288c909878..bde891f64591 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h | |||
@@ -65,7 +65,7 @@ struct mmc_host_ops { | |||
65 | * -ENOSYS when not supported (equal to NULL callback) | 65 | * -ENOSYS when not supported (equal to NULL callback) |
66 | * or a negative errno value when something bad happened | 66 | * or a negative errno value when something bad happened |
67 | * | 67 | * |
68 | * Return values for the get_ro callback should be: | 68 | * Return values for the get_cd callback should be: |
69 | * 0 for a absent card | 69 | * 0 for a absent card |
70 | * 1 for a present card | 70 | * 1 for a present card |
71 | * -ENOSYS when not supported (equal to NULL callback) | 71 | * -ENOSYS when not supported (equal to NULL callback) |
diff --git a/include/linux/rtc/m48t59.h b/include/linux/rtc/m48t59.h index e8c7c21ceb1f..6fc961459b4a 100644 --- a/include/linux/rtc/m48t59.h +++ b/include/linux/rtc/m48t59.h | |||
@@ -18,40 +18,47 @@ | |||
18 | /* | 18 | /* |
19 | * M48T59 Register Offset | 19 | * M48T59 Register Offset |
20 | */ | 20 | */ |
21 | #define M48T59_YEAR 0x1fff | 21 | #define M48T59_YEAR 0xf |
22 | #define M48T59_MONTH 0x1ffe | 22 | #define M48T59_MONTH 0xe |
23 | #define M48T59_MDAY 0x1ffd /* Day of Month */ | 23 | #define M48T59_MDAY 0xd /* Day of Month */ |
24 | #define M48T59_WDAY 0x1ffc /* Day of Week */ | 24 | #define M48T59_WDAY 0xc /* Day of Week */ |
25 | #define M48T59_WDAY_CB 0x20 /* Century Bit */ | 25 | #define M48T59_WDAY_CB 0x20 /* Century Bit */ |
26 | #define M48T59_WDAY_CEB 0x10 /* Century Enable Bit */ | 26 | #define M48T59_WDAY_CEB 0x10 /* Century Enable Bit */ |
27 | #define M48T59_HOUR 0x1ffb | 27 | #define M48T59_HOUR 0xb |
28 | #define M48T59_MIN 0x1ffa | 28 | #define M48T59_MIN 0xa |
29 | #define M48T59_SEC 0x1ff9 | 29 | #define M48T59_SEC 0x9 |
30 | #define M48T59_CNTL 0x1ff8 | 30 | #define M48T59_CNTL 0x8 |
31 | #define M48T59_CNTL_READ 0x40 | 31 | #define M48T59_CNTL_READ 0x40 |
32 | #define M48T59_CNTL_WRITE 0x80 | 32 | #define M48T59_CNTL_WRITE 0x80 |
33 | #define M48T59_WATCHDOG 0x1ff7 | 33 | #define M48T59_WATCHDOG 0x7 |
34 | #define M48T59_INTR 0x1ff6 | 34 | #define M48T59_INTR 0x6 |
35 | #define M48T59_INTR_AFE 0x80 /* Alarm Interrupt Enable */ | 35 | #define M48T59_INTR_AFE 0x80 /* Alarm Interrupt Enable */ |
36 | #define M48T59_INTR_ABE 0x20 | 36 | #define M48T59_INTR_ABE 0x20 |
37 | #define M48T59_ALARM_DATE 0x1ff5 | 37 | #define M48T59_ALARM_DATE 0x5 |
38 | #define M48T59_ALARM_HOUR 0x1ff4 | 38 | #define M48T59_ALARM_HOUR 0x4 |
39 | #define M48T59_ALARM_MIN 0x1ff3 | 39 | #define M48T59_ALARM_MIN 0x3 |
40 | #define M48T59_ALARM_SEC 0x1ff2 | 40 | #define M48T59_ALARM_SEC 0x2 |
41 | #define M48T59_UNUSED 0x1ff1 | 41 | #define M48T59_UNUSED 0x1 |
42 | #define M48T59_FLAGS 0x1ff0 | 42 | #define M48T59_FLAGS 0x0 |
43 | #define M48T59_FLAGS_WDT 0x80 /* watchdog timer expired */ | 43 | #define M48T59_FLAGS_WDT 0x80 /* watchdog timer expired */ |
44 | #define M48T59_FLAGS_AF 0x40 /* alarm */ | 44 | #define M48T59_FLAGS_AF 0x40 /* alarm */ |
45 | #define M48T59_FLAGS_BF 0x10 /* low battery */ | 45 | #define M48T59_FLAGS_BF 0x10 /* low battery */ |
46 | 46 | ||
47 | #define M48T59_NVRAM_SIZE 0x1ff0 | 47 | #define M48T59RTC_TYPE_M48T59 0 /* to keep compatibility */ |
48 | #define M48T59RTC_TYPE_M48T02 1 | ||
49 | #define M48T59RTC_TYPE_M48T08 2 | ||
48 | 50 | ||
49 | struct m48t59_plat_data { | 51 | struct m48t59_plat_data { |
50 | /* The method to access M48T59 registers, | 52 | /* The method to access M48T59 registers */ |
51 | * NOTE: The 'ofs' should be 0x00~0x1fff | ||
52 | */ | ||
53 | void (*write_byte)(struct device *dev, u32 ofs, u8 val); | 53 | void (*write_byte)(struct device *dev, u32 ofs, u8 val); |
54 | unsigned char (*read_byte)(struct device *dev, u32 ofs); | 54 | unsigned char (*read_byte)(struct device *dev, u32 ofs); |
55 | |||
56 | int type; /* RTC model */ | ||
57 | |||
58 | /* ioaddr mapped externally */ | ||
59 | void __iomem *ioaddr; | ||
60 | /* offset to RTC registers, automatically set according to the type */ | ||
61 | unsigned int offset; | ||
55 | }; | 62 | }; |
56 | 63 | ||
57 | #endif /* _LINUX_RTC_M48T59_H_ */ | 64 | #endif /* _LINUX_RTC_M48T59_H_ */ |
diff --git a/include/sound/core.h b/include/sound/core.h index e5eec5f73502..35424a971b7a 100644 --- a/include/sound/core.h +++ b/include/sound/core.h | |||
@@ -43,9 +43,6 @@ | |||
43 | #ifdef CONFIG_PCI | 43 | #ifdef CONFIG_PCI |
44 | struct pci_dev; | 44 | struct pci_dev; |
45 | #endif | 45 | #endif |
46 | #ifdef CONFIG_SBUS | ||
47 | struct sbus_dev; | ||
48 | #endif | ||
49 | 46 | ||
50 | /* device allocation stuff */ | 47 | /* device allocation stuff */ |
51 | 48 | ||
diff --git a/include/sound/memalloc.h b/include/sound/memalloc.h index d787a6b4a101..7ccce94a5255 100644 --- a/include/sound/memalloc.h +++ b/include/sound/memalloc.h | |||
@@ -37,7 +37,6 @@ struct snd_dma_device { | |||
37 | #ifndef snd_dma_pci_data | 37 | #ifndef snd_dma_pci_data |
38 | #define snd_dma_pci_data(pci) (&(pci)->dev) | 38 | #define snd_dma_pci_data(pci) (&(pci)->dev) |
39 | #define snd_dma_isa_data() NULL | 39 | #define snd_dma_isa_data() NULL |
40 | #define snd_dma_sbus_data(sbus) ((struct device *)(sbus)) | ||
41 | #define snd_dma_continuous_data(x) ((struct device *)(unsigned long)(x)) | 40 | #define snd_dma_continuous_data(x) ((struct device *)(unsigned long)(x)) |
42 | #endif | 41 | #endif |
43 | 42 | ||
@@ -49,7 +48,6 @@ struct snd_dma_device { | |||
49 | #define SNDRV_DMA_TYPE_CONTINUOUS 1 /* continuous no-DMA memory */ | 48 | #define SNDRV_DMA_TYPE_CONTINUOUS 1 /* continuous no-DMA memory */ |
50 | #define SNDRV_DMA_TYPE_DEV 2 /* generic device continuous */ | 49 | #define SNDRV_DMA_TYPE_DEV 2 /* generic device continuous */ |
51 | #define SNDRV_DMA_TYPE_DEV_SG 3 /* generic device SG-buffer */ | 50 | #define SNDRV_DMA_TYPE_DEV_SG 3 /* generic device SG-buffer */ |
52 | #define SNDRV_DMA_TYPE_SBUS 4 /* SBUS continuous */ | ||
53 | 51 | ||
54 | /* | 52 | /* |
55 | * info for buffer allocation | 53 | * info for buffer allocation |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 50ec0886fa3d..1bf369bd4423 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -118,10 +118,8 @@ extern char modprobe_path[]; | |||
118 | extern int sg_big_buff; | 118 | extern int sg_big_buff; |
119 | #endif | 119 | #endif |
120 | 120 | ||
121 | #ifdef __sparc__ | 121 | #ifdef CONFIG_SPARC |
122 | extern char reboot_command []; | 122 | #include <asm/system.h> |
123 | extern int stop_a_enabled; | ||
124 | extern int scons_pwroff; | ||
125 | #endif | 123 | #endif |
126 | 124 | ||
127 | #ifdef __hppa__ | 125 | #ifdef __hppa__ |
@@ -415,7 +413,7 @@ static struct ctl_table kern_table[] = { | |||
415 | .mode = 0644, | 413 | .mode = 0644, |
416 | .proc_handler = &proc_dointvec, | 414 | .proc_handler = &proc_dointvec, |
417 | }, | 415 | }, |
418 | #ifdef __sparc__ | 416 | #ifdef CONFIG_SPARC |
419 | { | 417 | { |
420 | .ctl_name = KERN_SPARC_REBOOT, | 418 | .ctl_name = KERN_SPARC_REBOOT, |
421 | .procname = "reboot-cmd", | 419 | .procname = "reboot-cmd", |
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c index 05ebce2881ef..85c487b8572b 100644 --- a/net/ipv4/ip_gre.c +++ b/net/ipv4/ip_gre.c | |||
@@ -1345,7 +1345,7 @@ out: | |||
1345 | static void ipgre_netlink_parms(struct nlattr *data[], | 1345 | static void ipgre_netlink_parms(struct nlattr *data[], |
1346 | struct ip_tunnel_parm *parms) | 1346 | struct ip_tunnel_parm *parms) |
1347 | { | 1347 | { |
1348 | memset(parms, 0, sizeof(parms)); | 1348 | memset(parms, 0, sizeof(*parms)); |
1349 | 1349 | ||
1350 | parms->iph.protocol = IPPROTO_GRE; | 1350 | parms->iph.protocol = IPPROTO_GRE; |
1351 | 1351 | ||
diff --git a/net/netfilter/ipvs/Kconfig b/net/netfilter/ipvs/Kconfig index de6004de80bc..05048e403266 100644 --- a/net/netfilter/ipvs/Kconfig +++ b/net/netfilter/ipvs/Kconfig | |||
@@ -2,8 +2,8 @@ | |||
2 | # IP Virtual Server configuration | 2 | # IP Virtual Server configuration |
3 | # | 3 | # |
4 | menuconfig IP_VS | 4 | menuconfig IP_VS |
5 | tristate "IP virtual server support (EXPERIMENTAL)" | 5 | tristate "IP virtual server support" |
6 | depends on NETFILTER | 6 | depends on NET && INET && NETFILTER |
7 | ---help--- | 7 | ---help--- |
8 | IP Virtual Server support will let you build a high-performance | 8 | IP Virtual Server support will let you build a high-performance |
9 | virtual server based on cluster of two or more real servers. This | 9 | virtual server based on cluster of two or more real servers. This |
diff --git a/sound/core/memalloc.c b/sound/core/memalloc.c index a7b46ec72f32..1b3534d67686 100644 --- a/sound/core/memalloc.c +++ b/sound/core/memalloc.c | |||
@@ -33,9 +33,6 @@ | |||
33 | #include <linux/moduleparam.h> | 33 | #include <linux/moduleparam.h> |
34 | #include <linux/mutex.h> | 34 | #include <linux/mutex.h> |
35 | #include <sound/memalloc.h> | 35 | #include <sound/memalloc.h> |
36 | #ifdef CONFIG_SBUS | ||
37 | #include <asm/sbus.h> | ||
38 | #endif | ||
39 | 36 | ||
40 | 37 | ||
41 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>"); | 38 | MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>, Jaroslav Kysela <perex@perex.cz>"); |
@@ -162,39 +159,6 @@ static void snd_free_dev_pages(struct device *dev, size_t size, void *ptr, | |||
162 | } | 159 | } |
163 | #endif /* CONFIG_HAS_DMA */ | 160 | #endif /* CONFIG_HAS_DMA */ |
164 | 161 | ||
165 | #ifdef CONFIG_SBUS | ||
166 | |||
167 | static void *snd_malloc_sbus_pages(struct device *dev, size_t size, | ||
168 | dma_addr_t *dma_addr) | ||
169 | { | ||
170 | struct sbus_dev *sdev = (struct sbus_dev *)dev; | ||
171 | int pg; | ||
172 | void *res; | ||
173 | |||
174 | if (WARN_ON(!dma_addr)) | ||
175 | return NULL; | ||
176 | pg = get_order(size); | ||
177 | res = sbus_alloc_consistent(sdev, PAGE_SIZE * (1 << pg), dma_addr); | ||
178 | if (res != NULL) | ||
179 | inc_snd_pages(pg); | ||
180 | return res; | ||
181 | } | ||
182 | |||
183 | static void snd_free_sbus_pages(struct device *dev, size_t size, | ||
184 | void *ptr, dma_addr_t dma_addr) | ||
185 | { | ||
186 | struct sbus_dev *sdev = (struct sbus_dev *)dev; | ||
187 | int pg; | ||
188 | |||
189 | if (ptr == NULL) | ||
190 | return; | ||
191 | pg = get_order(size); | ||
192 | dec_snd_pages(pg); | ||
193 | sbus_free_consistent(sdev, PAGE_SIZE * (1 << pg), ptr, dma_addr); | ||
194 | } | ||
195 | |||
196 | #endif /* CONFIG_SBUS */ | ||
197 | |||
198 | /* | 162 | /* |
199 | * | 163 | * |
200 | * ALSA generic memory management | 164 | * ALSA generic memory management |
@@ -231,11 +195,6 @@ int snd_dma_alloc_pages(int type, struct device *device, size_t size, | |||
231 | dmab->area = snd_malloc_pages(size, (unsigned long)device); | 195 | dmab->area = snd_malloc_pages(size, (unsigned long)device); |
232 | dmab->addr = 0; | 196 | dmab->addr = 0; |
233 | break; | 197 | break; |
234 | #ifdef CONFIG_SBUS | ||
235 | case SNDRV_DMA_TYPE_SBUS: | ||
236 | dmab->area = snd_malloc_sbus_pages(device, size, &dmab->addr); | ||
237 | break; | ||
238 | #endif | ||
239 | #ifdef CONFIG_HAS_DMA | 198 | #ifdef CONFIG_HAS_DMA |
240 | case SNDRV_DMA_TYPE_DEV: | 199 | case SNDRV_DMA_TYPE_DEV: |
241 | dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); | 200 | dmab->area = snd_malloc_dev_pages(device, size, &dmab->addr); |
@@ -306,11 +265,6 @@ void snd_dma_free_pages(struct snd_dma_buffer *dmab) | |||
306 | case SNDRV_DMA_TYPE_CONTINUOUS: | 265 | case SNDRV_DMA_TYPE_CONTINUOUS: |
307 | snd_free_pages(dmab->area, dmab->bytes); | 266 | snd_free_pages(dmab->area, dmab->bytes); |
308 | break; | 267 | break; |
309 | #ifdef CONFIG_SBUS | ||
310 | case SNDRV_DMA_TYPE_SBUS: | ||
311 | snd_free_sbus_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); | ||
312 | break; | ||
313 | #endif | ||
314 | #ifdef CONFIG_HAS_DMA | 268 | #ifdef CONFIG_HAS_DMA |
315 | case SNDRV_DMA_TYPE_DEV: | 269 | case SNDRV_DMA_TYPE_DEV: |
316 | snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); | 270 | snd_free_dev_pages(dmab->dev.dev, dmab->bytes, dmab->area, dmab->addr); |
@@ -419,7 +373,7 @@ static int snd_mem_proc_read(struct seq_file *seq, void *offset) | |||
419 | long pages = snd_allocated_pages >> (PAGE_SHIFT-12); | 373 | long pages = snd_allocated_pages >> (PAGE_SHIFT-12); |
420 | struct snd_mem_list *mem; | 374 | struct snd_mem_list *mem; |
421 | int devno; | 375 | int devno; |
422 | static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG", "SBUS" }; | 376 | static char *types[] = { "UNKNOWN", "CONT", "DEV", "DEV-SG" }; |
423 | 377 | ||
424 | mutex_lock(&list_mutex); | 378 | mutex_lock(&list_mutex); |
425 | seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n", | 379 | seq_printf(seq, "pages : %li bytes (%li pages per %likB)\n", |
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c index 49acee0c4840..f87933e48812 100644 --- a/sound/sparc/amd7930.c +++ b/sound/sparc/amd7930.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for AMD7930 sound chips found on Sparcs. | 2 | * Driver for AMD7930 sound chips found on Sparcs. |
3 | * Copyright (C) 2002 David S. Miller <davem@redhat.com> | 3 | * Copyright (C) 2002, 2008 David S. Miller <davem@davemloft.net> |
4 | * | 4 | * |
5 | * Based entirely upon drivers/sbus/audio/amd7930.c which is: | 5 | * Based entirely upon drivers/sbus/audio/amd7930.c which is: |
6 | * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu) | 6 | * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu) |
@@ -35,6 +35,8 @@ | |||
35 | #include <linux/init.h> | 35 | #include <linux/init.h> |
36 | #include <linux/interrupt.h> | 36 | #include <linux/interrupt.h> |
37 | #include <linux/moduleparam.h> | 37 | #include <linux/moduleparam.h> |
38 | #include <linux/of.h> | ||
39 | #include <linux/of_device.h> | ||
38 | 40 | ||
39 | #include <sound/core.h> | 41 | #include <sound/core.h> |
40 | #include <sound/pcm.h> | 42 | #include <sound/pcm.h> |
@@ -44,7 +46,6 @@ | |||
44 | 46 | ||
45 | #include <asm/io.h> | 47 | #include <asm/io.h> |
46 | #include <asm/irq.h> | 48 | #include <asm/irq.h> |
47 | #include <asm/sbus.h> | ||
48 | #include <asm/prom.h> | 49 | #include <asm/prom.h> |
49 | 50 | ||
50 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 51 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
@@ -335,8 +336,8 @@ struct snd_amd7930 { | |||
335 | int pgain; | 336 | int pgain; |
336 | int mgain; | 337 | int mgain; |
337 | 338 | ||
339 | struct of_device *op; | ||
338 | unsigned int irq; | 340 | unsigned int irq; |
339 | unsigned int regs_size; | ||
340 | struct snd_amd7930 *next; | 341 | struct snd_amd7930 *next; |
341 | }; | 342 | }; |
342 | 343 | ||
@@ -905,13 +906,16 @@ static int __devinit snd_amd7930_mixer(struct snd_amd7930 *amd) | |||
905 | 906 | ||
906 | static int snd_amd7930_free(struct snd_amd7930 *amd) | 907 | static int snd_amd7930_free(struct snd_amd7930 *amd) |
907 | { | 908 | { |
909 | struct of_device *op = amd->op; | ||
910 | |||
908 | amd7930_idle(amd); | 911 | amd7930_idle(amd); |
909 | 912 | ||
910 | if (amd->irq) | 913 | if (amd->irq) |
911 | free_irq(amd->irq, amd); | 914 | free_irq(amd->irq, amd); |
912 | 915 | ||
913 | if (amd->regs) | 916 | if (amd->regs) |
914 | sbus_iounmap(amd->regs, amd->regs_size); | 917 | of_iounmap(&op->resource[0], amd->regs, |
918 | resource_size(&op->resource[0])); | ||
915 | 919 | ||
916 | kfree(amd); | 920 | kfree(amd); |
917 | 921 | ||
@@ -930,13 +934,12 @@ static struct snd_device_ops snd_amd7930_dev_ops = { | |||
930 | }; | 934 | }; |
931 | 935 | ||
932 | static int __devinit snd_amd7930_create(struct snd_card *card, | 936 | static int __devinit snd_amd7930_create(struct snd_card *card, |
933 | struct resource *rp, | 937 | struct of_device *op, |
934 | unsigned int reg_size, | ||
935 | int irq, int dev, | 938 | int irq, int dev, |
936 | struct snd_amd7930 **ramd) | 939 | struct snd_amd7930 **ramd) |
937 | { | 940 | { |
938 | unsigned long flags; | ||
939 | struct snd_amd7930 *amd; | 941 | struct snd_amd7930 *amd; |
942 | unsigned long flags; | ||
940 | int err; | 943 | int err; |
941 | 944 | ||
942 | *ramd = NULL; | 945 | *ramd = NULL; |
@@ -946,9 +949,10 @@ static int __devinit snd_amd7930_create(struct snd_card *card, | |||
946 | 949 | ||
947 | spin_lock_init(&amd->lock); | 950 | spin_lock_init(&amd->lock); |
948 | amd->card = card; | 951 | amd->card = card; |
949 | amd->regs_size = reg_size; | 952 | amd->op = op; |
950 | 953 | ||
951 | amd->regs = sbus_ioremap(rp, 0, amd->regs_size, "amd7930"); | 954 | amd->regs = of_ioremap(&op->resource[0], 0, |
955 | resource_size(&op->resource[0]), "amd7930"); | ||
952 | if (!amd->regs) { | 956 | if (!amd->regs) { |
953 | snd_printk("amd7930-%d: Unable to map chip registers.\n", dev); | 957 | snd_printk("amd7930-%d: Unable to map chip registers.\n", dev); |
954 | return -EIO; | 958 | return -EIO; |
@@ -997,12 +1001,15 @@ static int __devinit snd_amd7930_create(struct snd_card *card, | |||
997 | return 0; | 1001 | return 0; |
998 | } | 1002 | } |
999 | 1003 | ||
1000 | static int __devinit amd7930_attach_common(struct resource *rp, int irq) | 1004 | static int __devinit amd7930_sbus_probe(struct of_device *op, const struct of_device_id *match) |
1001 | { | 1005 | { |
1006 | struct resource *rp = &op->resource[0]; | ||
1002 | static int dev_num; | 1007 | static int dev_num; |
1003 | struct snd_card *card; | 1008 | struct snd_card *card; |
1004 | struct snd_amd7930 *amd; | 1009 | struct snd_amd7930 *amd; |
1005 | int err; | 1010 | int err, irq; |
1011 | |||
1012 | irq = op->irqs[0]; | ||
1006 | 1013 | ||
1007 | if (dev_num >= SNDRV_CARDS) | 1014 | if (dev_num >= SNDRV_CARDS) |
1008 | return -ENODEV; | 1015 | return -ENODEV; |
@@ -1023,8 +1030,7 @@ static int __devinit amd7930_attach_common(struct resource *rp, int irq) | |||
1023 | (unsigned long long)rp->start, | 1030 | (unsigned long long)rp->start, |
1024 | irq); | 1031 | irq); |
1025 | 1032 | ||
1026 | if ((err = snd_amd7930_create(card, rp, | 1033 | if ((err = snd_amd7930_create(card, op, |
1027 | (rp->end - rp->start) + 1, | ||
1028 | irq, dev_num, &amd)) < 0) | 1034 | irq, dev_num, &amd)) < 0) |
1029 | goto out_err; | 1035 | goto out_err; |
1030 | 1036 | ||
@@ -1049,43 +1055,7 @@ out_err: | |||
1049 | return err; | 1055 | return err; |
1050 | } | 1056 | } |
1051 | 1057 | ||
1052 | static int __devinit amd7930_obio_attach(struct device_node *dp) | 1058 | static const struct of_device_id amd7930_match[] = { |
1053 | { | ||
1054 | const struct linux_prom_registers *regs; | ||
1055 | const struct linux_prom_irqs *irqp; | ||
1056 | struct resource res, *rp; | ||
1057 | int len; | ||
1058 | |||
1059 | irqp = of_get_property(dp, "intr", &len); | ||
1060 | if (!irqp) { | ||
1061 | snd_printk("%s: Firmware node lacks IRQ property.\n", | ||
1062 | dp->full_name); | ||
1063 | return -ENODEV; | ||
1064 | } | ||
1065 | |||
1066 | regs = of_get_property(dp, "reg", &len); | ||
1067 | if (!regs) { | ||
1068 | snd_printk("%s: Firmware node lacks register property.\n", | ||
1069 | dp->full_name); | ||
1070 | return -ENODEV; | ||
1071 | } | ||
1072 | |||
1073 | rp = &res; | ||
1074 | rp->start = regs->phys_addr; | ||
1075 | rp->end = rp->start + regs->reg_size - 1; | ||
1076 | rp->flags = IORESOURCE_IO | (regs->which_io & 0xff); | ||
1077 | |||
1078 | return amd7930_attach_common(rp, irqp->pri); | ||
1079 | } | ||
1080 | |||
1081 | static int __devinit amd7930_sbus_probe(struct of_device *dev, const struct of_device_id *match) | ||
1082 | { | ||
1083 | struct sbus_dev *sdev = to_sbus_device(&dev->dev); | ||
1084 | |||
1085 | return amd7930_attach_common(&sdev->resource[0], sdev->irqs[0]); | ||
1086 | } | ||
1087 | |||
1088 | static struct of_device_id amd7930_match[] = { | ||
1089 | { | 1059 | { |
1090 | .name = "audio", | 1060 | .name = "audio", |
1091 | }, | 1061 | }, |
@@ -1100,20 +1070,7 @@ static struct of_platform_driver amd7930_sbus_driver = { | |||
1100 | 1070 | ||
1101 | static int __init amd7930_init(void) | 1071 | static int __init amd7930_init(void) |
1102 | { | 1072 | { |
1103 | struct device_node *dp; | 1073 | return of_register_driver(&amd7930_sbus_driver, &of_bus_type); |
1104 | |||
1105 | /* Try to find the sun4c "audio" node first. */ | ||
1106 | dp = of_find_node_by_path("/"); | ||
1107 | dp = dp->child; | ||
1108 | while (dp) { | ||
1109 | if (!strcmp(dp->name, "audio")) | ||
1110 | amd7930_obio_attach(dp); | ||
1111 | |||
1112 | dp = dp->sibling; | ||
1113 | } | ||
1114 | |||
1115 | /* Probe each SBUS for amd7930 chips. */ | ||
1116 | return of_register_driver(&amd7930_sbus_driver, &sbus_bus_type); | ||
1117 | } | 1074 | } |
1118 | 1075 | ||
1119 | static void __exit amd7930_exit(void) | 1076 | static void __exit amd7930_exit(void) |
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index 791d2fb821d1..d44bf98e965e 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c | |||
@@ -1,6 +1,6 @@ | |||
1 | /* | 1 | /* |
2 | * Driver for CS4231 sound chips found on Sparcs. | 2 | * Driver for CS4231 sound chips found on Sparcs. |
3 | * Copyright (C) 2002 David S. Miller <davem@redhat.com> | 3 | * Copyright (C) 2002, 2008 David S. Miller <davem@davemloft.net> |
4 | * | 4 | * |
5 | * Based entirely upon drivers/sbus/audio/cs4231.c which is: | 5 | * Based entirely upon drivers/sbus/audio/cs4231.c which is: |
6 | * Copyright (C) 1996, 1997, 1998 Derrick J Brashear (shadow@andrew.cmu.edu) | 6 | * Copyright (C) 1996, 1997, 1998 Derrick J Brashear (shadow@andrew.cmu.edu) |
@@ -17,7 +17,8 @@ | |||
17 | #include <linux/moduleparam.h> | 17 | #include <linux/moduleparam.h> |
18 | #include <linux/irq.h> | 18 | #include <linux/irq.h> |
19 | #include <linux/io.h> | 19 | #include <linux/io.h> |
20 | 20 | #include <linux/of.h> | |
21 | #include <linux/of_device.h> | ||
21 | 22 | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
@@ -29,13 +30,12 @@ | |||
29 | 30 | ||
30 | #ifdef CONFIG_SBUS | 31 | #ifdef CONFIG_SBUS |
31 | #define SBUS_SUPPORT | 32 | #define SBUS_SUPPORT |
32 | #include <asm/sbus.h> | ||
33 | #endif | 33 | #endif |
34 | 34 | ||
35 | #if defined(CONFIG_PCI) && defined(CONFIG_SPARC64) | 35 | #if defined(CONFIG_PCI) && defined(CONFIG_SPARC64) |
36 | #define EBUS_SUPPORT | 36 | #define EBUS_SUPPORT |
37 | #include <linux/pci.h> | 37 | #include <linux/pci.h> |
38 | #include <asm/ebus.h> | 38 | #include <asm/ebus_dma.h> |
39 | #endif | 39 | #endif |
40 | 40 | ||
41 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ | 41 | static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ |
@@ -70,8 +70,6 @@ struct cs4231_dma_control { | |||
70 | int (*request)(struct cs4231_dma_control *dma_cont, | 70 | int (*request)(struct cs4231_dma_control *dma_cont, |
71 | dma_addr_t bus_addr, size_t len); | 71 | dma_addr_t bus_addr, size_t len); |
72 | unsigned int (*address)(struct cs4231_dma_control *dma_cont); | 72 | unsigned int (*address)(struct cs4231_dma_control *dma_cont); |
73 | void (*preallocate)(struct snd_cs4231 *chip, | ||
74 | struct snd_pcm *pcm); | ||
75 | #ifdef EBUS_SUPPORT | 73 | #ifdef EBUS_SUPPORT |
76 | struct ebus_dma_info ebus_info; | 74 | struct ebus_dma_info ebus_info; |
77 | #endif | 75 | #endif |
@@ -114,21 +112,12 @@ struct snd_cs4231 { | |||
114 | struct mutex mce_mutex; /* mutex for mce register */ | 112 | struct mutex mce_mutex; /* mutex for mce register */ |
115 | struct mutex open_mutex; /* mutex for ALSA open/close */ | 113 | struct mutex open_mutex; /* mutex for ALSA open/close */ |
116 | 114 | ||
117 | union { | 115 | struct of_device *op; |
118 | #ifdef SBUS_SUPPORT | ||
119 | struct sbus_dev *sdev; | ||
120 | #endif | ||
121 | #ifdef EBUS_SUPPORT | ||
122 | struct pci_dev *pdev; | ||
123 | #endif | ||
124 | } dev_u; | ||
125 | unsigned int irq[2]; | 116 | unsigned int irq[2]; |
126 | unsigned int regs_size; | 117 | unsigned int regs_size; |
127 | struct snd_cs4231 *next; | 118 | struct snd_cs4231 *next; |
128 | }; | 119 | }; |
129 | 120 | ||
130 | static struct snd_cs4231 *cs4231_list; | ||
131 | |||
132 | /* Eventually we can use sound/isa/cs423x/cs4231_lib.c directly, but for | 121 | /* Eventually we can use sound/isa/cs423x/cs4231_lib.c directly, but for |
133 | * now.... -DaveM | 122 | * now.... -DaveM |
134 | */ | 123 | */ |
@@ -267,27 +256,19 @@ static unsigned char snd_cs4231_original_image[32] = | |||
267 | 256 | ||
268 | static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr) | 257 | static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr) |
269 | { | 258 | { |
270 | #ifdef EBUS_SUPPORT | ||
271 | if (cp->flags & CS4231_FLAG_EBUS) | 259 | if (cp->flags & CS4231_FLAG_EBUS) |
272 | return readb(reg_addr); | 260 | return readb(reg_addr); |
273 | else | 261 | else |
274 | #endif | ||
275 | #ifdef SBUS_SUPPORT | ||
276 | return sbus_readb(reg_addr); | 262 | return sbus_readb(reg_addr); |
277 | #endif | ||
278 | } | 263 | } |
279 | 264 | ||
280 | static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, | 265 | static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, |
281 | void __iomem *reg_addr) | 266 | void __iomem *reg_addr) |
282 | { | 267 | { |
283 | #ifdef EBUS_SUPPORT | ||
284 | if (cp->flags & CS4231_FLAG_EBUS) | 268 | if (cp->flags & CS4231_FLAG_EBUS) |
285 | return writeb(val, reg_addr); | 269 | return writeb(val, reg_addr); |
286 | else | 270 | else |
287 | #endif | ||
288 | #ifdef SBUS_SUPPORT | ||
289 | return sbus_writeb(val, reg_addr); | 271 | return sbus_writeb(val, reg_addr); |
290 | #endif | ||
291 | } | 272 | } |
292 | 273 | ||
293 | /* | 274 | /* |
@@ -1258,7 +1239,9 @@ static int __init snd_cs4231_pcm(struct snd_card *card) | |||
1258 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; | 1239 | pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; |
1259 | strcpy(pcm->name, "CS4231"); | 1240 | strcpy(pcm->name, "CS4231"); |
1260 | 1241 | ||
1261 | chip->p_dma.preallocate(chip, pcm); | 1242 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, |
1243 | &chip->op->dev, | ||
1244 | 64 * 1024, 128 * 1024); | ||
1262 | 1245 | ||
1263 | chip->pcm = pcm; | 1246 | chip->pcm = pcm; |
1264 | 1247 | ||
@@ -1627,8 +1610,7 @@ static int __init cs4231_attach_finish(struct snd_card *card) | |||
1627 | if (err < 0) | 1610 | if (err < 0) |
1628 | goto out_err; | 1611 | goto out_err; |
1629 | 1612 | ||
1630 | chip->next = cs4231_list; | 1613 | dev_set_drvdata(&chip->op->dev, chip); |
1631 | cs4231_list = chip; | ||
1632 | 1614 | ||
1633 | dev++; | 1615 | dev++; |
1634 | return 0; | 1616 | return 0; |
@@ -1783,24 +1765,19 @@ static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) | |||
1783 | return sbus_readl(base->regs + base->dir + APCVA); | 1765 | return sbus_readl(base->regs + base->dir + APCVA); |
1784 | } | 1766 | } |
1785 | 1767 | ||
1786 | static void sbus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm) | ||
1787 | { | ||
1788 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, | ||
1789 | snd_dma_sbus_data(chip->dev_u.sdev), | ||
1790 | 64 * 1024, 128 * 1024); | ||
1791 | } | ||
1792 | |||
1793 | /* | 1768 | /* |
1794 | * Init and exit routines | 1769 | * Init and exit routines |
1795 | */ | 1770 | */ |
1796 | 1771 | ||
1797 | static int snd_cs4231_sbus_free(struct snd_cs4231 *chip) | 1772 | static int snd_cs4231_sbus_free(struct snd_cs4231 *chip) |
1798 | { | 1773 | { |
1774 | struct of_device *op = chip->op; | ||
1775 | |||
1799 | if (chip->irq[0]) | 1776 | if (chip->irq[0]) |
1800 | free_irq(chip->irq[0], chip); | 1777 | free_irq(chip->irq[0], chip); |
1801 | 1778 | ||
1802 | if (chip->port) | 1779 | if (chip->port) |
1803 | sbus_iounmap(chip->port, chip->regs_size); | 1780 | of_iounmap(&op->resource[0], chip->port, chip->regs_size); |
1804 | 1781 | ||
1805 | return 0; | 1782 | return 0; |
1806 | } | 1783 | } |
@@ -1817,7 +1794,7 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = { | |||
1817 | }; | 1794 | }; |
1818 | 1795 | ||
1819 | static int __init snd_cs4231_sbus_create(struct snd_card *card, | 1796 | static int __init snd_cs4231_sbus_create(struct snd_card *card, |
1820 | struct sbus_dev *sdev, | 1797 | struct of_device *op, |
1821 | int dev) | 1798 | int dev) |
1822 | { | 1799 | { |
1823 | struct snd_cs4231 *chip = card->private_data; | 1800 | struct snd_cs4231 *chip = card->private_data; |
@@ -1828,13 +1805,13 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, | |||
1828 | spin_lock_init(&chip->p_dma.sbus_info.lock); | 1805 | spin_lock_init(&chip->p_dma.sbus_info.lock); |
1829 | mutex_init(&chip->mce_mutex); | 1806 | mutex_init(&chip->mce_mutex); |
1830 | mutex_init(&chip->open_mutex); | 1807 | mutex_init(&chip->open_mutex); |
1831 | chip->dev_u.sdev = sdev; | 1808 | chip->op = op; |
1832 | chip->regs_size = sdev->reg_addrs[0].reg_size; | 1809 | chip->regs_size = resource_size(&op->resource[0]); |
1833 | memcpy(&chip->image, &snd_cs4231_original_image, | 1810 | memcpy(&chip->image, &snd_cs4231_original_image, |
1834 | sizeof(snd_cs4231_original_image)); | 1811 | sizeof(snd_cs4231_original_image)); |
1835 | 1812 | ||
1836 | chip->port = sbus_ioremap(&sdev->resource[0], 0, | 1813 | chip->port = of_ioremap(&op->resource[0], 0, |
1837 | chip->regs_size, "cs4231"); | 1814 | chip->regs_size, "cs4231"); |
1838 | if (!chip->port) { | 1815 | if (!chip->port) { |
1839 | snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); | 1816 | snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); |
1840 | return -EIO; | 1817 | return -EIO; |
@@ -1849,22 +1826,20 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, | |||
1849 | chip->p_dma.enable = sbus_dma_enable; | 1826 | chip->p_dma.enable = sbus_dma_enable; |
1850 | chip->p_dma.request = sbus_dma_request; | 1827 | chip->p_dma.request = sbus_dma_request; |
1851 | chip->p_dma.address = sbus_dma_addr; | 1828 | chip->p_dma.address = sbus_dma_addr; |
1852 | chip->p_dma.preallocate = sbus_dma_preallocate; | ||
1853 | 1829 | ||
1854 | chip->c_dma.prepare = sbus_dma_prepare; | 1830 | chip->c_dma.prepare = sbus_dma_prepare; |
1855 | chip->c_dma.enable = sbus_dma_enable; | 1831 | chip->c_dma.enable = sbus_dma_enable; |
1856 | chip->c_dma.request = sbus_dma_request; | 1832 | chip->c_dma.request = sbus_dma_request; |
1857 | chip->c_dma.address = sbus_dma_addr; | 1833 | chip->c_dma.address = sbus_dma_addr; |
1858 | chip->c_dma.preallocate = sbus_dma_preallocate; | ||
1859 | 1834 | ||
1860 | if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt, | 1835 | if (request_irq(op->irqs[0], snd_cs4231_sbus_interrupt, |
1861 | IRQF_SHARED, "cs4231", chip)) { | 1836 | IRQF_SHARED, "cs4231", chip)) { |
1862 | snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %d\n", | 1837 | snd_printdd("cs4231-%d: Unable to grab SBUS IRQ %d\n", |
1863 | dev, sdev->irqs[0]); | 1838 | dev, op->irqs[0]); |
1864 | snd_cs4231_sbus_free(chip); | 1839 | snd_cs4231_sbus_free(chip); |
1865 | return -EBUSY; | 1840 | return -EBUSY; |
1866 | } | 1841 | } |
1867 | chip->irq[0] = sdev->irqs[0]; | 1842 | chip->irq[0] = op->irqs[0]; |
1868 | 1843 | ||
1869 | if (snd_cs4231_probe(chip) < 0) { | 1844 | if (snd_cs4231_probe(chip) < 0) { |
1870 | snd_cs4231_sbus_free(chip); | 1845 | snd_cs4231_sbus_free(chip); |
@@ -1881,9 +1856,9 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, | |||
1881 | return 0; | 1856 | return 0; |
1882 | } | 1857 | } |
1883 | 1858 | ||
1884 | static int __init cs4231_sbus_attach(struct sbus_dev *sdev) | 1859 | static int __devinit cs4231_sbus_probe(struct of_device *op, const struct of_device_id *match) |
1885 | { | 1860 | { |
1886 | struct resource *rp = &sdev->resource[0]; | 1861 | struct resource *rp = &op->resource[0]; |
1887 | struct snd_card *card; | 1862 | struct snd_card *card; |
1888 | int err; | 1863 | int err; |
1889 | 1864 | ||
@@ -1895,9 +1870,9 @@ static int __init cs4231_sbus_attach(struct sbus_dev *sdev) | |||
1895 | card->shortname, | 1870 | card->shortname, |
1896 | rp->flags & 0xffL, | 1871 | rp->flags & 0xffL, |
1897 | (unsigned long long)rp->start, | 1872 | (unsigned long long)rp->start, |
1898 | sdev->irqs[0]); | 1873 | op->irqs[0]); |
1899 | 1874 | ||
1900 | err = snd_cs4231_sbus_create(card, sdev, dev); | 1875 | err = snd_cs4231_sbus_create(card, op, dev); |
1901 | if (err < 0) { | 1876 | if (err < 0) { |
1902 | snd_card_free(card); | 1877 | snd_card_free(card); |
1903 | return err; | 1878 | return err; |
@@ -1950,30 +1925,25 @@ static unsigned int _ebus_dma_addr(struct cs4231_dma_control *dma_cont) | |||
1950 | return ebus_dma_addr(&dma_cont->ebus_info); | 1925 | return ebus_dma_addr(&dma_cont->ebus_info); |
1951 | } | 1926 | } |
1952 | 1927 | ||
1953 | static void _ebus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm) | ||
1954 | { | ||
1955 | snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV, | ||
1956 | snd_dma_pci_data(chip->dev_u.pdev), | ||
1957 | 64*1024, 128*1024); | ||
1958 | } | ||
1959 | |||
1960 | /* | 1928 | /* |
1961 | * Init and exit routines | 1929 | * Init and exit routines |
1962 | */ | 1930 | */ |
1963 | 1931 | ||
1964 | static int snd_cs4231_ebus_free(struct snd_cs4231 *chip) | 1932 | static int snd_cs4231_ebus_free(struct snd_cs4231 *chip) |
1965 | { | 1933 | { |
1934 | struct of_device *op = chip->op; | ||
1935 | |||
1966 | if (chip->c_dma.ebus_info.regs) { | 1936 | if (chip->c_dma.ebus_info.regs) { |
1967 | ebus_dma_unregister(&chip->c_dma.ebus_info); | 1937 | ebus_dma_unregister(&chip->c_dma.ebus_info); |
1968 | iounmap(chip->c_dma.ebus_info.regs); | 1938 | of_iounmap(&op->resource[2], chip->c_dma.ebus_info.regs, 0x10); |
1969 | } | 1939 | } |
1970 | if (chip->p_dma.ebus_info.regs) { | 1940 | if (chip->p_dma.ebus_info.regs) { |
1971 | ebus_dma_unregister(&chip->p_dma.ebus_info); | 1941 | ebus_dma_unregister(&chip->p_dma.ebus_info); |
1972 | iounmap(chip->p_dma.ebus_info.regs); | 1942 | of_iounmap(&op->resource[1], chip->p_dma.ebus_info.regs, 0x10); |
1973 | } | 1943 | } |
1974 | 1944 | ||
1975 | if (chip->port) | 1945 | if (chip->port) |
1976 | iounmap(chip->port); | 1946 | of_iounmap(&op->resource[0], chip->port, 0x10); |
1977 | 1947 | ||
1978 | return 0; | 1948 | return 0; |
1979 | } | 1949 | } |
@@ -1990,7 +1960,7 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = { | |||
1990 | }; | 1960 | }; |
1991 | 1961 | ||
1992 | static int __init snd_cs4231_ebus_create(struct snd_card *card, | 1962 | static int __init snd_cs4231_ebus_create(struct snd_card *card, |
1993 | struct linux_ebus_device *edev, | 1963 | struct of_device *op, |
1994 | int dev) | 1964 | int dev) |
1995 | { | 1965 | { |
1996 | struct snd_cs4231 *chip = card->private_data; | 1966 | struct snd_cs4231 *chip = card->private_data; |
@@ -2002,35 +1972,35 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, | |||
2002 | mutex_init(&chip->mce_mutex); | 1972 | mutex_init(&chip->mce_mutex); |
2003 | mutex_init(&chip->open_mutex); | 1973 | mutex_init(&chip->open_mutex); |
2004 | chip->flags |= CS4231_FLAG_EBUS; | 1974 | chip->flags |= CS4231_FLAG_EBUS; |
2005 | chip->dev_u.pdev = edev->bus->self; | 1975 | chip->op = op; |
2006 | memcpy(&chip->image, &snd_cs4231_original_image, | 1976 | memcpy(&chip->image, &snd_cs4231_original_image, |
2007 | sizeof(snd_cs4231_original_image)); | 1977 | sizeof(snd_cs4231_original_image)); |
2008 | strcpy(chip->c_dma.ebus_info.name, "cs4231(capture)"); | 1978 | strcpy(chip->c_dma.ebus_info.name, "cs4231(capture)"); |
2009 | chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; | 1979 | chip->c_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; |
2010 | chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback; | 1980 | chip->c_dma.ebus_info.callback = snd_cs4231_ebus_capture_callback; |
2011 | chip->c_dma.ebus_info.client_cookie = chip; | 1981 | chip->c_dma.ebus_info.client_cookie = chip; |
2012 | chip->c_dma.ebus_info.irq = edev->irqs[0]; | 1982 | chip->c_dma.ebus_info.irq = op->irqs[0]; |
2013 | strcpy(chip->p_dma.ebus_info.name, "cs4231(play)"); | 1983 | strcpy(chip->p_dma.ebus_info.name, "cs4231(play)"); |
2014 | chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; | 1984 | chip->p_dma.ebus_info.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER; |
2015 | chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback; | 1985 | chip->p_dma.ebus_info.callback = snd_cs4231_ebus_play_callback; |
2016 | chip->p_dma.ebus_info.client_cookie = chip; | 1986 | chip->p_dma.ebus_info.client_cookie = chip; |
2017 | chip->p_dma.ebus_info.irq = edev->irqs[1]; | 1987 | chip->p_dma.ebus_info.irq = op->irqs[1]; |
2018 | 1988 | ||
2019 | chip->p_dma.prepare = _ebus_dma_prepare; | 1989 | chip->p_dma.prepare = _ebus_dma_prepare; |
2020 | chip->p_dma.enable = _ebus_dma_enable; | 1990 | chip->p_dma.enable = _ebus_dma_enable; |
2021 | chip->p_dma.request = _ebus_dma_request; | 1991 | chip->p_dma.request = _ebus_dma_request; |
2022 | chip->p_dma.address = _ebus_dma_addr; | 1992 | chip->p_dma.address = _ebus_dma_addr; |
2023 | chip->p_dma.preallocate = _ebus_dma_preallocate; | ||
2024 | 1993 | ||
2025 | chip->c_dma.prepare = _ebus_dma_prepare; | 1994 | chip->c_dma.prepare = _ebus_dma_prepare; |
2026 | chip->c_dma.enable = _ebus_dma_enable; | 1995 | chip->c_dma.enable = _ebus_dma_enable; |
2027 | chip->c_dma.request = _ebus_dma_request; | 1996 | chip->c_dma.request = _ebus_dma_request; |
2028 | chip->c_dma.address = _ebus_dma_addr; | 1997 | chip->c_dma.address = _ebus_dma_addr; |
2029 | chip->c_dma.preallocate = _ebus_dma_preallocate; | ||
2030 | 1998 | ||
2031 | chip->port = ioremap(edev->resource[0].start, 0x10); | 1999 | chip->port = of_ioremap(&op->resource[0], 0, 0x10, "cs4231"); |
2032 | chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10); | 2000 | chip->p_dma.ebus_info.regs = |
2033 | chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10); | 2001 | of_ioremap(&op->resource[1], 0, 0x10, "cs4231_pdma"); |
2002 | chip->c_dma.ebus_info.regs = | ||
2003 | of_ioremap(&op->resource[2], 0, 0x10, "cs4231_cdma"); | ||
2034 | if (!chip->port || !chip->p_dma.ebus_info.regs || | 2004 | if (!chip->port || !chip->p_dma.ebus_info.regs || |
2035 | !chip->c_dma.ebus_info.regs) { | 2005 | !chip->c_dma.ebus_info.regs) { |
2036 | snd_cs4231_ebus_free(chip); | 2006 | snd_cs4231_ebus_free(chip); |
@@ -2078,7 +2048,7 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, | |||
2078 | return 0; | 2048 | return 0; |
2079 | } | 2049 | } |
2080 | 2050 | ||
2081 | static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) | 2051 | static int __devinit cs4231_ebus_probe(struct of_device *op, const struct of_device_id *match) |
2082 | { | 2052 | { |
2083 | struct snd_card *card; | 2053 | struct snd_card *card; |
2084 | int err; | 2054 | int err; |
@@ -2089,10 +2059,10 @@ static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) | |||
2089 | 2059 | ||
2090 | sprintf(card->longname, "%s at 0x%lx, irq %d", | 2060 | sprintf(card->longname, "%s at 0x%lx, irq %d", |
2091 | card->shortname, | 2061 | card->shortname, |
2092 | edev->resource[0].start, | 2062 | op->resource[0].start, |
2093 | edev->irqs[0]); | 2063 | op->irqs[0]); |
2094 | 2064 | ||
2095 | err = snd_cs4231_ebus_create(card, edev, dev); | 2065 | err = snd_cs4231_ebus_create(card, op, dev); |
2096 | if (err < 0) { | 2066 | if (err < 0) { |
2097 | snd_card_free(card); | 2067 | snd_card_free(card); |
2098 | return err; | 2068 | return err; |
@@ -2102,68 +2072,57 @@ static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) | |||
2102 | } | 2072 | } |
2103 | #endif | 2073 | #endif |
2104 | 2074 | ||
2105 | static int __init cs4231_init(void) | 2075 | static int __devinit cs4231_probe(struct of_device *op, const struct of_device_id *match) |
2106 | { | 2076 | { |
2107 | #ifdef SBUS_SUPPORT | ||
2108 | struct sbus_bus *sbus; | ||
2109 | struct sbus_dev *sdev; | ||
2110 | #endif | ||
2111 | #ifdef EBUS_SUPPORT | 2077 | #ifdef EBUS_SUPPORT |
2112 | struct linux_ebus *ebus; | 2078 | if (!strcmp(op->node->parent->name, "ebus")) |
2113 | struct linux_ebus_device *edev; | 2079 | return cs4231_ebus_probe(op, match); |
2114 | #endif | 2080 | #endif |
2115 | int found; | ||
2116 | |||
2117 | found = 0; | ||
2118 | |||
2119 | #ifdef SBUS_SUPPORT | 2081 | #ifdef SBUS_SUPPORT |
2120 | for_all_sbusdev(sdev, sbus) { | 2082 | if (!strcmp(op->node->parent->name, "sbus") || |
2121 | if (!strcmp(sdev->prom_name, "SUNW,CS4231")) { | 2083 | !strcmp(op->node->parent->name, "sbi")) |
2122 | if (cs4231_sbus_attach(sdev) == 0) | 2084 | return cs4231_sbus_probe(op, match); |
2123 | found++; | ||
2124 | } | ||
2125 | } | ||
2126 | #endif | 2085 | #endif |
2127 | #ifdef EBUS_SUPPORT | 2086 | return -ENODEV; |
2128 | for_each_ebus(ebus) { | 2087 | } |
2129 | for_each_ebusdev(edev, ebus) { | ||
2130 | int match = 0; | ||
2131 | |||
2132 | if (!strcmp(edev->prom_node->name, "SUNW,CS4231")) { | ||
2133 | match = 1; | ||
2134 | } else if (!strcmp(edev->prom_node->name, "audio")) { | ||
2135 | const char *compat; | ||
2136 | |||
2137 | compat = of_get_property(edev->prom_node, | ||
2138 | "compatible", NULL); | ||
2139 | if (compat && !strcmp(compat, "SUNW,CS4231")) | ||
2140 | match = 1; | ||
2141 | } | ||
2142 | 2088 | ||
2143 | if (match && | 2089 | static int __devexit cs4231_remove(struct of_device *op) |
2144 | cs4231_ebus_attach(edev) == 0) | 2090 | { |
2145 | found++; | 2091 | struct snd_cs4231 *chip = dev_get_drvdata(&op->dev); |
2146 | } | ||
2147 | } | ||
2148 | #endif | ||
2149 | 2092 | ||
2093 | snd_card_free(chip->card); | ||
2150 | 2094 | ||
2151 | return (found > 0) ? 0 : -EIO; | 2095 | return 0; |
2152 | } | 2096 | } |
2153 | 2097 | ||
2154 | static void __exit cs4231_exit(void) | 2098 | static const struct of_device_id cs4231_match[] = { |
2155 | { | 2099 | { |
2156 | struct snd_cs4231 *p = cs4231_list; | 2100 | .name = "SUNW,CS4231", |
2101 | }, | ||
2102 | { | ||
2103 | .name = "audio", | ||
2104 | .compatible = "SUNW,CS4231", | ||
2105 | }, | ||
2106 | {}, | ||
2107 | }; | ||
2157 | 2108 | ||
2158 | while (p != NULL) { | 2109 | MODULE_DEVICE_TABLE(of, cs4231_match); |
2159 | struct snd_cs4231 *next = p->next; | ||
2160 | 2110 | ||
2161 | snd_card_free(p->card); | 2111 | static struct of_platform_driver cs4231_driver = { |
2112 | .name = "audio", | ||
2113 | .match_table = cs4231_match, | ||
2114 | .probe = cs4231_probe, | ||
2115 | .remove = __devexit_p(cs4231_remove), | ||
2116 | }; | ||
2162 | 2117 | ||
2163 | p = next; | 2118 | static int __init cs4231_init(void) |
2164 | } | 2119 | { |
2120 | return of_register_driver(&cs4231_driver, &of_bus_type); | ||
2121 | } | ||
2165 | 2122 | ||
2166 | cs4231_list = NULL; | 2123 | static void __exit cs4231_exit(void) |
2124 | { | ||
2125 | of_unregister_driver(&cs4231_driver); | ||
2167 | } | 2126 | } |
2168 | 2127 | ||
2169 | module_init(cs4231_init); | 2128 | module_init(cs4231_init); |
diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index c534a2a849fa..c257ad8bdfbc 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c | |||
@@ -57,6 +57,7 @@ | |||
57 | #include <linux/delay.h> | 57 | #include <linux/delay.h> |
58 | #include <linux/irq.h> | 58 | #include <linux/irq.h> |
59 | #include <linux/io.h> | 59 | #include <linux/io.h> |
60 | #include <linux/dma-mapping.h> | ||
60 | 61 | ||
61 | #include <sound/core.h> | 62 | #include <sound/core.h> |
62 | #include <sound/pcm.h> | 63 | #include <sound/pcm.h> |
@@ -66,7 +67,7 @@ | |||
66 | #include <sound/initval.h> | 67 | #include <sound/initval.h> |
67 | 68 | ||
68 | #include <linux/of.h> | 69 | #include <linux/of.h> |
69 | #include <asm/sbus.h> | 70 | #include <linux/of_device.h> |
70 | #include <asm/atomic.h> | 71 | #include <asm/atomic.h> |
71 | 72 | ||
72 | MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets"); | 73 | MODULE_AUTHOR("Rudolf Koenig, Brent Baccala and Martin Habets"); |
@@ -297,7 +298,7 @@ struct dbri_streaminfo { | |||
297 | /* This structure holds the information for both chips (DBRI & CS4215) */ | 298 | /* This structure holds the information for both chips (DBRI & CS4215) */ |
298 | struct snd_dbri { | 299 | struct snd_dbri { |
299 | int regs_size, irq; /* Needed for unload */ | 300 | int regs_size, irq; /* Needed for unload */ |
300 | struct sbus_dev *sdev; /* SBUS device info */ | 301 | struct of_device *op; /* OF device info */ |
301 | spinlock_t lock; | 302 | spinlock_t lock; |
302 | 303 | ||
303 | struct dbri_dma *dma; /* Pointer to our DMA block */ | 304 | struct dbri_dma *dma; /* Pointer to our DMA block */ |
@@ -2093,14 +2094,15 @@ static int snd_dbri_hw_params(struct snd_pcm_substream *substream, | |||
2093 | */ | 2094 | */ |
2094 | if (info->dvma_buffer == 0) { | 2095 | if (info->dvma_buffer == 0) { |
2095 | if (DBRI_STREAMNO(substream) == DBRI_PLAY) | 2096 | if (DBRI_STREAMNO(substream) == DBRI_PLAY) |
2096 | direction = SBUS_DMA_TODEVICE; | 2097 | direction = DMA_TO_DEVICE; |
2097 | else | 2098 | else |
2098 | direction = SBUS_DMA_FROMDEVICE; | 2099 | direction = DMA_FROM_DEVICE; |
2099 | 2100 | ||
2100 | info->dvma_buffer = sbus_map_single(dbri->sdev, | 2101 | info->dvma_buffer = |
2101 | runtime->dma_area, | 2102 | dma_map_single(&dbri->op->dev, |
2102 | params_buffer_bytes(hw_params), | 2103 | runtime->dma_area, |
2103 | direction); | 2104 | params_buffer_bytes(hw_params), |
2105 | direction); | ||
2104 | } | 2106 | } |
2105 | 2107 | ||
2106 | direction = params_buffer_bytes(hw_params); | 2108 | direction = params_buffer_bytes(hw_params); |
@@ -2121,12 +2123,12 @@ static int snd_dbri_hw_free(struct snd_pcm_substream *substream) | |||
2121 | */ | 2123 | */ |
2122 | if (info->dvma_buffer) { | 2124 | if (info->dvma_buffer) { |
2123 | if (DBRI_STREAMNO(substream) == DBRI_PLAY) | 2125 | if (DBRI_STREAMNO(substream) == DBRI_PLAY) |
2124 | direction = SBUS_DMA_TODEVICE; | 2126 | direction = DMA_TO_DEVICE; |
2125 | else | 2127 | else |
2126 | direction = SBUS_DMA_FROMDEVICE; | 2128 | direction = DMA_FROM_DEVICE; |
2127 | 2129 | ||
2128 | sbus_unmap_single(dbri->sdev, info->dvma_buffer, | 2130 | dma_unmap_single(&dbri->op->dev, info->dvma_buffer, |
2129 | substream->runtime->buffer_size, direction); | 2131 | substream->runtime->buffer_size, direction); |
2130 | info->dvma_buffer = 0; | 2132 | info->dvma_buffer = 0; |
2131 | } | 2133 | } |
2132 | if (info->pipe != -1) { | 2134 | if (info->pipe != -1) { |
@@ -2519,31 +2521,32 @@ static void __devinit snd_dbri_proc(struct snd_card *card) | |||
2519 | static void snd_dbri_free(struct snd_dbri *dbri); | 2521 | static void snd_dbri_free(struct snd_dbri *dbri); |
2520 | 2522 | ||
2521 | static int __devinit snd_dbri_create(struct snd_card *card, | 2523 | static int __devinit snd_dbri_create(struct snd_card *card, |
2522 | struct sbus_dev *sdev, | 2524 | struct of_device *op, |
2523 | int irq, int dev) | 2525 | int irq, int dev) |
2524 | { | 2526 | { |
2525 | struct snd_dbri *dbri = card->private_data; | 2527 | struct snd_dbri *dbri = card->private_data; |
2526 | int err; | 2528 | int err; |
2527 | 2529 | ||
2528 | spin_lock_init(&dbri->lock); | 2530 | spin_lock_init(&dbri->lock); |
2529 | dbri->sdev = sdev; | 2531 | dbri->op = op; |
2530 | dbri->irq = irq; | 2532 | dbri->irq = irq; |
2531 | 2533 | ||
2532 | dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), | 2534 | dbri->dma = dma_alloc_coherent(&op->dev, |
2533 | &dbri->dma_dvma); | 2535 | sizeof(struct dbri_dma), |
2536 | &dbri->dma_dvma, GFP_ATOMIC); | ||
2534 | memset((void *)dbri->dma, 0, sizeof(struct dbri_dma)); | 2537 | memset((void *)dbri->dma, 0, sizeof(struct dbri_dma)); |
2535 | 2538 | ||
2536 | dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n", | 2539 | dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n", |
2537 | dbri->dma, dbri->dma_dvma); | 2540 | dbri->dma, dbri->dma_dvma); |
2538 | 2541 | ||
2539 | /* Map the registers into memory. */ | 2542 | /* Map the registers into memory. */ |
2540 | dbri->regs_size = sdev->reg_addrs[0].reg_size; | 2543 | dbri->regs_size = resource_size(&op->resource[0]); |
2541 | dbri->regs = sbus_ioremap(&sdev->resource[0], 0, | 2544 | dbri->regs = of_ioremap(&op->resource[0], 0, |
2542 | dbri->regs_size, "DBRI Registers"); | 2545 | dbri->regs_size, "DBRI Registers"); |
2543 | if (!dbri->regs) { | 2546 | if (!dbri->regs) { |
2544 | printk(KERN_ERR "DBRI: could not allocate registers\n"); | 2547 | printk(KERN_ERR "DBRI: could not allocate registers\n"); |
2545 | sbus_free_consistent(sdev, sizeof(struct dbri_dma), | 2548 | dma_free_coherent(&op->dev, sizeof(struct dbri_dma), |
2546 | (void *)dbri->dma, dbri->dma_dvma); | 2549 | (void *)dbri->dma, dbri->dma_dvma); |
2547 | return -EIO; | 2550 | return -EIO; |
2548 | } | 2551 | } |
2549 | 2552 | ||
@@ -2551,9 +2554,9 @@ static int __devinit snd_dbri_create(struct snd_card *card, | |||
2551 | "DBRI audio", dbri); | 2554 | "DBRI audio", dbri); |
2552 | if (err) { | 2555 | if (err) { |
2553 | printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq); | 2556 | printk(KERN_ERR "DBRI: Can't get irq %d\n", dbri->irq); |
2554 | sbus_iounmap(dbri->regs, dbri->regs_size); | 2557 | of_iounmap(&op->resource[0], dbri->regs, dbri->regs_size); |
2555 | sbus_free_consistent(sdev, sizeof(struct dbri_dma), | 2558 | dma_free_coherent(&op->dev, sizeof(struct dbri_dma), |
2556 | (void *)dbri->dma, dbri->dma_dvma); | 2559 | (void *)dbri->dma, dbri->dma_dvma); |
2557 | return err; | 2560 | return err; |
2558 | } | 2561 | } |
2559 | 2562 | ||
@@ -2577,27 +2580,23 @@ static void snd_dbri_free(struct snd_dbri *dbri) | |||
2577 | free_irq(dbri->irq, dbri); | 2580 | free_irq(dbri->irq, dbri); |
2578 | 2581 | ||
2579 | if (dbri->regs) | 2582 | if (dbri->regs) |
2580 | sbus_iounmap(dbri->regs, dbri->regs_size); | 2583 | of_iounmap(&dbri->op->resource[0], dbri->regs, dbri->regs_size); |
2581 | 2584 | ||
2582 | if (dbri->dma) | 2585 | if (dbri->dma) |
2583 | sbus_free_consistent(dbri->sdev, sizeof(struct dbri_dma), | 2586 | dma_free_coherent(&dbri->op->dev, |
2584 | (void *)dbri->dma, dbri->dma_dvma); | 2587 | sizeof(struct dbri_dma), |
2588 | (void *)dbri->dma, dbri->dma_dvma); | ||
2585 | } | 2589 | } |
2586 | 2590 | ||
2587 | static int __devinit dbri_probe(struct of_device *of_dev, | 2591 | static int __devinit dbri_probe(struct of_device *op, const struct of_device_id *match) |
2588 | const struct of_device_id *match) | ||
2589 | { | 2592 | { |
2590 | struct sbus_dev *sdev = to_sbus_device(&of_dev->dev); | ||
2591 | struct snd_dbri *dbri; | 2593 | struct snd_dbri *dbri; |
2592 | int irq; | ||
2593 | struct resource *rp; | 2594 | struct resource *rp; |
2594 | struct snd_card *card; | 2595 | struct snd_card *card; |
2595 | static int dev = 0; | 2596 | static int dev = 0; |
2597 | int irq; | ||
2596 | int err; | 2598 | int err; |
2597 | 2599 | ||
2598 | dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", | ||
2599 | sdev->prom_name, sdev->slot); | ||
2600 | |||
2601 | if (dev >= SNDRV_CARDS) | 2600 | if (dev >= SNDRV_CARDS) |
2602 | return -ENODEV; | 2601 | return -ENODEV; |
2603 | if (!enable[dev]) { | 2602 | if (!enable[dev]) { |
@@ -2605,7 +2604,7 @@ static int __devinit dbri_probe(struct of_device *of_dev, | |||
2605 | return -ENOENT; | 2604 | return -ENOENT; |
2606 | } | 2605 | } |
2607 | 2606 | ||
2608 | irq = sdev->irqs[0]; | 2607 | irq = op->irqs[0]; |
2609 | if (irq <= 0) { | 2608 | if (irq <= 0) { |
2610 | printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev); | 2609 | printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev); |
2611 | return -ENODEV; | 2610 | return -ENODEV; |
@@ -2618,12 +2617,12 @@ static int __devinit dbri_probe(struct of_device *of_dev, | |||
2618 | 2617 | ||
2619 | strcpy(card->driver, "DBRI"); | 2618 | strcpy(card->driver, "DBRI"); |
2620 | strcpy(card->shortname, "Sun DBRI"); | 2619 | strcpy(card->shortname, "Sun DBRI"); |
2621 | rp = &sdev->resource[0]; | 2620 | rp = &op->resource[0]; |
2622 | sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d", | 2621 | sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d", |
2623 | card->shortname, | 2622 | card->shortname, |
2624 | rp->flags & 0xffL, (unsigned long long)rp->start, irq); | 2623 | rp->flags & 0xffL, (unsigned long long)rp->start, irq); |
2625 | 2624 | ||
2626 | err = snd_dbri_create(card, sdev, irq, dev); | 2625 | err = snd_dbri_create(card, op, irq, dev); |
2627 | if (err < 0) { | 2626 | if (err < 0) { |
2628 | snd_card_free(card); | 2627 | snd_card_free(card); |
2629 | return err; | 2628 | return err; |
@@ -2640,7 +2639,7 @@ static int __devinit dbri_probe(struct of_device *of_dev, | |||
2640 | 2639 | ||
2641 | /* /proc file handling */ | 2640 | /* /proc file handling */ |
2642 | snd_dbri_proc(card); | 2641 | snd_dbri_proc(card); |
2643 | dev_set_drvdata(&of_dev->dev, card); | 2642 | dev_set_drvdata(&op->dev, card); |
2644 | 2643 | ||
2645 | err = snd_card_register(card); | 2644 | err = snd_card_register(card); |
2646 | if (err < 0) | 2645 | if (err < 0) |
@@ -2648,7 +2647,7 @@ static int __devinit dbri_probe(struct of_device *of_dev, | |||
2648 | 2647 | ||
2649 | printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n", | 2648 | printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n", |
2650 | dev, dbri->regs, | 2649 | dev, dbri->regs, |
2651 | dbri->irq, sdev->prom_name[9], dbri->mm.version); | 2650 | dbri->irq, op->node->name[9], dbri->mm.version); |
2652 | dev++; | 2651 | dev++; |
2653 | 2652 | ||
2654 | return 0; | 2653 | return 0; |
@@ -2659,19 +2658,19 @@ _err: | |||
2659 | return err; | 2658 | return err; |
2660 | } | 2659 | } |
2661 | 2660 | ||
2662 | static int __devexit dbri_remove(struct of_device *dev) | 2661 | static int __devexit dbri_remove(struct of_device *op) |
2663 | { | 2662 | { |
2664 | struct snd_card *card = dev_get_drvdata(&dev->dev); | 2663 | struct snd_card *card = dev_get_drvdata(&op->dev); |
2665 | 2664 | ||
2666 | snd_dbri_free(card->private_data); | 2665 | snd_dbri_free(card->private_data); |
2667 | snd_card_free(card); | 2666 | snd_card_free(card); |
2668 | 2667 | ||
2669 | dev_set_drvdata(&dev->dev, NULL); | 2668 | dev_set_drvdata(&op->dev, NULL); |
2670 | 2669 | ||
2671 | return 0; | 2670 | return 0; |
2672 | } | 2671 | } |
2673 | 2672 | ||
2674 | static struct of_device_id dbri_match[] = { | 2673 | static const struct of_device_id dbri_match[] = { |
2675 | { | 2674 | { |
2676 | .name = "SUNW,DBRIe", | 2675 | .name = "SUNW,DBRIe", |
2677 | }, | 2676 | }, |
@@ -2693,7 +2692,7 @@ static struct of_platform_driver dbri_sbus_driver = { | |||
2693 | /* Probe for the dbri chip and then attach the driver. */ | 2692 | /* Probe for the dbri chip and then attach the driver. */ |
2694 | static int __init dbri_init(void) | 2693 | static int __init dbri_init(void) |
2695 | { | 2694 | { |
2696 | return of_register_driver(&dbri_sbus_driver, &sbus_bus_type); | 2695 | return of_register_driver(&dbri_sbus_driver, &of_bus_type); |
2697 | } | 2696 | } |
2698 | 2697 | ||
2699 | static void __exit dbri_exit(void) | 2698 | static void __exit dbri_exit(void) |