diff options
author | Olof Johansson <olof@lixom.net> | 2013-11-15 18:17:59 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-11-15 18:17:59 -0500 |
commit | 6886059f2ef5d62c73e87a905e84fa4f87d56074 (patch) | |
tree | dfe6e1611d7c50057df52db7b55eafbfb8e33a93 /arch/powerpc/platforms/powernv/opal.c | |
parent | ca439c9b983ffa14e9eae6030e3ee80ad039388f (diff) | |
parent | 26273e02a0cf18eb72416559310d3294390a9024 (diff) |
Merge tag 'omap-for-v3.13/fixes-for-merge-window-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap into fixes
Few clock fixes, a runtime PM fix, and pinctrl-single fix along
with few other fixes that popped up during the merge window.
* tag 'omap-for-v3.13/fixes-for-merge-window-take2' of git://git.kernel.org/pub/scm/linux/kernel/git/tmlind/linux-omap:
ARM: OMAP2+: Fix build for dra7xx without omap4 and 5
ARM: OMAP2+: omap_device: maintain sane runtime pm status around suspend/resume
doc: devicetree: Add bindings documentation for omap-des driver
ARM: dts: doc: Document missing compatible property for omap-sham driver
ARM: OMAP3: Beagle: fix return value check in beagle_opp_init()
ARM: OMAP: devicetree: fix SPI node compatible property syntax items
pinctrl: single: call pcs_soc->rearm() whenever IRQ mask is changed
ARM: OMAP2+: smsc911x: fix return value check in gpmc_smsc911x_init()
+ sync with newer trunk
Diffstat (limited to 'arch/powerpc/platforms/powernv/opal.c')
-rw-r--r-- | arch/powerpc/platforms/powernv/opal.c | 58 |
1 files changed, 44 insertions, 14 deletions
diff --git a/arch/powerpc/platforms/powernv/opal.c b/arch/powerpc/platforms/powernv/opal.c index 2911abe550f1..1c798cd55372 100644 --- a/arch/powerpc/platforms/powernv/opal.c +++ b/arch/powerpc/platforms/powernv/opal.c | |||
@@ -13,15 +13,20 @@ | |||
13 | 13 | ||
14 | #include <linux/types.h> | 14 | #include <linux/types.h> |
15 | #include <linux/of.h> | 15 | #include <linux/of.h> |
16 | #include <linux/of_fdt.h> | ||
16 | #include <linux/of_platform.h> | 17 | #include <linux/of_platform.h> |
17 | #include <linux/interrupt.h> | 18 | #include <linux/interrupt.h> |
18 | #include <linux/notifier.h> | 19 | #include <linux/notifier.h> |
19 | #include <linux/slab.h> | 20 | #include <linux/slab.h> |
21 | #include <linux/kobject.h> | ||
20 | #include <asm/opal.h> | 22 | #include <asm/opal.h> |
21 | #include <asm/firmware.h> | 23 | #include <asm/firmware.h> |
22 | 24 | ||
23 | #include "powernv.h" | 25 | #include "powernv.h" |
24 | 26 | ||
27 | /* /sys/firmware/opal */ | ||
28 | struct kobject *opal_kobj; | ||
29 | |||
25 | struct opal { | 30 | struct opal { |
26 | u64 base; | 31 | u64 base; |
27 | u64 entry; | 32 | u64 entry; |
@@ -77,6 +82,7 @@ int __init early_init_dt_scan_opal(unsigned long node, | |||
77 | 82 | ||
78 | static int __init opal_register_exception_handlers(void) | 83 | static int __init opal_register_exception_handlers(void) |
79 | { | 84 | { |
85 | #ifdef __BIG_ENDIAN__ | ||
80 | u64 glue; | 86 | u64 glue; |
81 | 87 | ||
82 | if (!(powerpc_firmware_features & FW_FEATURE_OPAL)) | 88 | if (!(powerpc_firmware_features & FW_FEATURE_OPAL)) |
@@ -94,6 +100,7 @@ static int __init opal_register_exception_handlers(void) | |||
94 | 0, glue); | 100 | 0, glue); |
95 | glue += 128; | 101 | glue += 128; |
96 | opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); | 102 | opal_register_exception_handler(OPAL_SOFTPATCH_HANDLER, 0, glue); |
103 | #endif | ||
97 | 104 | ||
98 | return 0; | 105 | return 0; |
99 | } | 106 | } |
@@ -164,27 +171,28 @@ void opal_notifier_disable(void) | |||
164 | 171 | ||
165 | int opal_get_chars(uint32_t vtermno, char *buf, int count) | 172 | int opal_get_chars(uint32_t vtermno, char *buf, int count) |
166 | { | 173 | { |
167 | s64 len, rc; | 174 | s64 rc; |
168 | u64 evt; | 175 | __be64 evt, len; |
169 | 176 | ||
170 | if (!opal.entry) | 177 | if (!opal.entry) |
171 | return -ENODEV; | 178 | return -ENODEV; |
172 | opal_poll_events(&evt); | 179 | opal_poll_events(&evt); |
173 | if ((evt & OPAL_EVENT_CONSOLE_INPUT) == 0) | 180 | if ((be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_INPUT) == 0) |
174 | return 0; | 181 | return 0; |
175 | len = count; | 182 | len = cpu_to_be64(count); |
176 | rc = opal_console_read(vtermno, &len, buf); | 183 | rc = opal_console_read(vtermno, &len, buf); |
177 | if (rc == OPAL_SUCCESS) | 184 | if (rc == OPAL_SUCCESS) |
178 | return len; | 185 | return be64_to_cpu(len); |
179 | return 0; | 186 | return 0; |
180 | } | 187 | } |
181 | 188 | ||
182 | int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | 189 | int opal_put_chars(uint32_t vtermno, const char *data, int total_len) |
183 | { | 190 | { |
184 | int written = 0; | 191 | int written = 0; |
192 | __be64 olen; | ||
185 | s64 len, rc; | 193 | s64 len, rc; |
186 | unsigned long flags; | 194 | unsigned long flags; |
187 | u64 evt; | 195 | __be64 evt; |
188 | 196 | ||
189 | if (!opal.entry) | 197 | if (!opal.entry) |
190 | return -ENODEV; | 198 | return -ENODEV; |
@@ -199,13 +207,14 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | |||
199 | */ | 207 | */ |
200 | spin_lock_irqsave(&opal_write_lock, flags); | 208 | spin_lock_irqsave(&opal_write_lock, flags); |
201 | if (firmware_has_feature(FW_FEATURE_OPALv2)) { | 209 | if (firmware_has_feature(FW_FEATURE_OPALv2)) { |
202 | rc = opal_console_write_buffer_space(vtermno, &len); | 210 | rc = opal_console_write_buffer_space(vtermno, &olen); |
211 | len = be64_to_cpu(olen); | ||
203 | if (rc || len < total_len) { | 212 | if (rc || len < total_len) { |
204 | spin_unlock_irqrestore(&opal_write_lock, flags); | 213 | spin_unlock_irqrestore(&opal_write_lock, flags); |
205 | /* Closed -> drop characters */ | 214 | /* Closed -> drop characters */ |
206 | if (rc) | 215 | if (rc) |
207 | return total_len; | 216 | return total_len; |
208 | opal_poll_events(&evt); | 217 | opal_poll_events(NULL); |
209 | return -EAGAIN; | 218 | return -EAGAIN; |
210 | } | 219 | } |
211 | } | 220 | } |
@@ -216,8 +225,9 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | |||
216 | rc = OPAL_BUSY; | 225 | rc = OPAL_BUSY; |
217 | while(total_len > 0 && (rc == OPAL_BUSY || | 226 | while(total_len > 0 && (rc == OPAL_BUSY || |
218 | rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { | 227 | rc == OPAL_BUSY_EVENT || rc == OPAL_SUCCESS)) { |
219 | len = total_len; | 228 | olen = cpu_to_be64(total_len); |
220 | rc = opal_console_write(vtermno, &len, data); | 229 | rc = opal_console_write(vtermno, &olen, data); |
230 | len = be64_to_cpu(olen); | ||
221 | 231 | ||
222 | /* Closed or other error drop */ | 232 | /* Closed or other error drop */ |
223 | if (rc != OPAL_SUCCESS && rc != OPAL_BUSY && | 233 | if (rc != OPAL_SUCCESS && rc != OPAL_BUSY && |
@@ -237,7 +247,8 @@ int opal_put_chars(uint32_t vtermno, const char *data, int total_len) | |||
237 | */ | 247 | */ |
238 | do | 248 | do |
239 | opal_poll_events(&evt); | 249 | opal_poll_events(&evt); |
240 | while(rc == OPAL_SUCCESS && (evt & OPAL_EVENT_CONSOLE_OUTPUT)); | 250 | while(rc == OPAL_SUCCESS && |
251 | (be64_to_cpu(evt) & OPAL_EVENT_CONSOLE_OUTPUT)); | ||
241 | } | 252 | } |
242 | spin_unlock_irqrestore(&opal_write_lock, flags); | 253 | spin_unlock_irqrestore(&opal_write_lock, flags); |
243 | return written; | 254 | return written; |
@@ -360,7 +371,7 @@ int opal_machine_check(struct pt_regs *regs) | |||
360 | 371 | ||
361 | static irqreturn_t opal_interrupt(int irq, void *data) | 372 | static irqreturn_t opal_interrupt(int irq, void *data) |
362 | { | 373 | { |
363 | uint64_t events; | 374 | __be64 events; |
364 | 375 | ||
365 | opal_handle_interrupt(virq_to_hw(irq), &events); | 376 | opal_handle_interrupt(virq_to_hw(irq), &events); |
366 | 377 | ||
@@ -369,10 +380,21 @@ static irqreturn_t opal_interrupt(int irq, void *data) | |||
369 | return IRQ_HANDLED; | 380 | return IRQ_HANDLED; |
370 | } | 381 | } |
371 | 382 | ||
383 | static int opal_sysfs_init(void) | ||
384 | { | ||
385 | opal_kobj = kobject_create_and_add("opal", firmware_kobj); | ||
386 | if (!opal_kobj) { | ||
387 | pr_warn("kobject_create_and_add opal failed\n"); | ||
388 | return -ENOMEM; | ||
389 | } | ||
390 | |||
391 | return 0; | ||
392 | } | ||
393 | |||
372 | static int __init opal_init(void) | 394 | static int __init opal_init(void) |
373 | { | 395 | { |
374 | struct device_node *np, *consoles; | 396 | struct device_node *np, *consoles; |
375 | const u32 *irqs; | 397 | const __be32 *irqs; |
376 | int rc, i, irqlen; | 398 | int rc, i, irqlen; |
377 | 399 | ||
378 | opal_node = of_find_node_by_path("/ibm,opal"); | 400 | opal_node = of_find_node_by_path("/ibm,opal"); |
@@ -414,6 +436,14 @@ static int __init opal_init(void) | |||
414 | " (0x%x)\n", rc, irq, hwirq); | 436 | " (0x%x)\n", rc, irq, hwirq); |
415 | opal_irqs[i] = irq; | 437 | opal_irqs[i] = irq; |
416 | } | 438 | } |
439 | |||
440 | /* Create "opal" kobject under /sys/firmware */ | ||
441 | rc = opal_sysfs_init(); | ||
442 | if (rc == 0) { | ||
443 | /* Setup code update interface */ | ||
444 | opal_flash_init(); | ||
445 | } | ||
446 | |||
417 | return 0; | 447 | return 0; |
418 | } | 448 | } |
419 | subsys_initcall(opal_init); | 449 | subsys_initcall(opal_init); |