diff options
Diffstat (limited to 'arch/arm/mach-omap2/mux.c')
-rw-r--r-- | arch/arm/mach-omap2/mux.c | 89 |
1 files changed, 87 insertions, 2 deletions
diff --git a/arch/arm/mach-omap2/mux.c b/arch/arm/mach-omap2/mux.c index 655e9480eb98..e1cc75d1a57a 100644 --- a/arch/arm/mach-omap2/mux.c +++ b/arch/arm/mach-omap2/mux.c | |||
@@ -32,6 +32,8 @@ | |||
32 | #include <linux/debugfs.h> | 32 | #include <linux/debugfs.h> |
33 | #include <linux/seq_file.h> | 33 | #include <linux/seq_file.h> |
34 | #include <linux/uaccess.h> | 34 | #include <linux/uaccess.h> |
35 | #include <linux/irq.h> | ||
36 | #include <linux/interrupt.h> | ||
35 | 37 | ||
36 | #include <asm/system.h> | 38 | #include <asm/system.h> |
37 | 39 | ||
@@ -39,6 +41,7 @@ | |||
39 | 41 | ||
40 | #include "control.h" | 42 | #include "control.h" |
41 | #include "mux.h" | 43 | #include "mux.h" |
44 | #include "prm.h" | ||
42 | 45 | ||
43 | #define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */ | 46 | #define OMAP_MUX_BASE_OFFSET 0x30 /* Offset from CTRL_BASE */ |
44 | #define OMAP_MUX_BASE_SZ 0x5ca | 47 | #define OMAP_MUX_BASE_SZ 0x5ca |
@@ -306,7 +309,8 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads) | |||
306 | pad->idle = bpad->idle; | 309 | pad->idle = bpad->idle; |
307 | pad->off = bpad->off; | 310 | pad->off = bpad->off; |
308 | 311 | ||
309 | if (pad->flags & OMAP_DEVICE_PAD_REMUX) | 312 | if (pad->flags & |
313 | (OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP)) | ||
310 | nr_pads_dynamic++; | 314 | nr_pads_dynamic++; |
311 | 315 | ||
312 | pr_debug("%s: Initialized %s\n", __func__, pad->name); | 316 | pr_debug("%s: Initialized %s\n", __func__, pad->name); |
@@ -331,7 +335,8 @@ omap_hwmod_mux_init(struct omap_device_pad *bpads, int nr_pads) | |||
331 | for (i = 0; i < hmux->nr_pads; i++) { | 335 | for (i = 0; i < hmux->nr_pads; i++) { |
332 | struct omap_device_pad *pad = &hmux->pads[i]; | 336 | struct omap_device_pad *pad = &hmux->pads[i]; |
333 | 337 | ||
334 | if (pad->flags & OMAP_DEVICE_PAD_REMUX) { | 338 | if (pad->flags & |
339 | (OMAP_DEVICE_PAD_REMUX | OMAP_DEVICE_PAD_WAKEUP)) { | ||
335 | pr_debug("%s: pad %s tagged dynamic\n", | 340 | pr_debug("%s: pad %s tagged dynamic\n", |
336 | __func__, pad->name); | 341 | __func__, pad->name); |
337 | hmux->pads_dynamic[nr_pads_dynamic] = pad; | 342 | hmux->pads_dynamic[nr_pads_dynamic] = pad; |
@@ -351,6 +356,78 @@ err1: | |||
351 | return NULL; | 356 | return NULL; |
352 | } | 357 | } |
353 | 358 | ||
359 | /** | ||
360 | * omap_hwmod_mux_scan_wakeups - omap hwmod scan wakeup pads | ||
361 | * @hmux: Pads for a hwmod | ||
362 | * @mpu_irqs: MPU irq array for a hwmod | ||
363 | * | ||
364 | * Scans the wakeup status of pads for a single hwmod. If an irq | ||
365 | * array is defined for this mux, the parser will call the registered | ||
366 | * ISRs for corresponding pads, otherwise the parser will stop at the | ||
367 | * first wakeup active pad and return. Returns true if there is a | ||
368 | * pending and non-served wakeup event for the mux, otherwise false. | ||
369 | */ | ||
370 | static bool omap_hwmod_mux_scan_wakeups(struct omap_hwmod_mux_info *hmux, | ||
371 | struct omap_hwmod_irq_info *mpu_irqs) | ||
372 | { | ||
373 | int i, irq; | ||
374 | unsigned int val; | ||
375 | u32 handled_irqs = 0; | ||
376 | |||
377 | for (i = 0; i < hmux->nr_pads_dynamic; i++) { | ||
378 | struct omap_device_pad *pad = hmux->pads_dynamic[i]; | ||
379 | |||
380 | if (!(pad->flags & OMAP_DEVICE_PAD_WAKEUP) || | ||
381 | !(pad->idle & OMAP_WAKEUP_EN)) | ||
382 | continue; | ||
383 | |||
384 | val = omap_mux_read(pad->partition, pad->mux->reg_offset); | ||
385 | if (!(val & OMAP_WAKEUP_EVENT)) | ||
386 | continue; | ||
387 | |||
388 | if (!hmux->irqs) | ||
389 | return true; | ||
390 | |||
391 | irq = hmux->irqs[i]; | ||
392 | /* make sure we only handle each irq once */ | ||
393 | if (handled_irqs & 1 << irq) | ||
394 | continue; | ||
395 | |||
396 | handled_irqs |= 1 << irq; | ||
397 | |||
398 | generic_handle_irq(mpu_irqs[irq].irq); | ||
399 | } | ||
400 | |||
401 | return false; | ||
402 | } | ||
403 | |||
404 | /** | ||
405 | * _omap_hwmod_mux_handle_irq - Process wakeup events for a single hwmod | ||
406 | * | ||
407 | * Checks a single hwmod for every wakeup capable pad to see if there is an | ||
408 | * active wakeup event. If this is the case, call the corresponding ISR. | ||
409 | */ | ||
410 | static int _omap_hwmod_mux_handle_irq(struct omap_hwmod *oh, void *data) | ||
411 | { | ||
412 | if (!oh->mux || !oh->mux->enabled) | ||
413 | return 0; | ||
414 | if (omap_hwmod_mux_scan_wakeups(oh->mux, oh->mpu_irqs)) | ||
415 | generic_handle_irq(oh->mpu_irqs[0].irq); | ||
416 | return 0; | ||
417 | } | ||
418 | |||
419 | /** | ||
420 | * omap_hwmod_mux_handle_irq - Process pad wakeup irqs. | ||
421 | * | ||
422 | * Calls a function for each registered omap_hwmod to check | ||
423 | * pad wakeup statuses. | ||
424 | */ | ||
425 | static irqreturn_t omap_hwmod_mux_handle_irq(int irq, void *unused) | ||
426 | { | ||
427 | omap_hwmod_for_each(_omap_hwmod_mux_handle_irq, NULL); | ||
428 | return IRQ_HANDLED; | ||
429 | } | ||
430 | |||
354 | /* Assumes the calling function takes care of locking */ | 431 | /* Assumes the calling function takes care of locking */ |
355 | void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state) | 432 | void omap_hwmod_mux(struct omap_hwmod_mux_info *hmux, u8 state) |
356 | { | 433 | { |
@@ -715,6 +792,7 @@ static void __init omap_mux_free_names(struct omap_mux *m) | |||
715 | static int __init omap_mux_late_init(void) | 792 | static int __init omap_mux_late_init(void) |
716 | { | 793 | { |
717 | struct omap_mux_partition *partition; | 794 | struct omap_mux_partition *partition; |
795 | int ret; | ||
718 | 796 | ||
719 | list_for_each_entry(partition, &mux_partitions, node) { | 797 | list_for_each_entry(partition, &mux_partitions, node) { |
720 | struct omap_mux_entry *e, *tmp; | 798 | struct omap_mux_entry *e, *tmp; |
@@ -735,6 +813,13 @@ static int __init omap_mux_late_init(void) | |||
735 | } | 813 | } |
736 | } | 814 | } |
737 | 815 | ||
816 | ret = request_irq(omap_prcm_event_to_irq("io"), | ||
817 | omap_hwmod_mux_handle_irq, IRQF_SHARED | IRQF_NO_SUSPEND, | ||
818 | "hwmod_io", omap_mux_late_init); | ||
819 | |||
820 | if (ret) | ||
821 | pr_warning("mux: Failed to setup hwmod io irq %d\n", ret); | ||
822 | |||
738 | omap_mux_dbg_init(); | 823 | omap_mux_dbg_init(); |
739 | 824 | ||
740 | return 0; | 825 | return 0; |