aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/platforms/powernv/opal.c
diff options
context:
space:
mode:
authorOlof Johansson <olof@lixom.net>2013-11-15 18:17:59 -0500
committerOlof Johansson <olof@lixom.net>2013-11-15 18:17:59 -0500
commit6886059f2ef5d62c73e87a905e84fa4f87d56074 (patch)
treedfe6e1611d7c50057df52db7b55eafbfb8e33a93 /arch/powerpc/platforms/powernv/opal.c
parentca439c9b983ffa14e9eae6030e3ee80ad039388f (diff)
parent26273e02a0cf18eb72416559310d3294390a9024 (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.c58
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 */
28struct kobject *opal_kobj;
29
25struct opal { 30struct 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
78static int __init opal_register_exception_handlers(void) 83static 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
165int opal_get_chars(uint32_t vtermno, char *buf, int count) 172int 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
182int opal_put_chars(uint32_t vtermno, const char *data, int total_len) 189int 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
361static irqreturn_t opal_interrupt(int irq, void *data) 372static 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
383static 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
372static int __init opal_init(void) 394static 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}
419subsys_initcall(opal_init); 449subsys_initcall(opal_init);