Commit 14ed5c86d20d0e7660b3ee6c575513128aebda8a
Exists in
ti-linux-3.14.y
and in
2 other branches
Merge branch 'pm-ti-linux-3.14.y' of git://git.ti.com/~kristo/ti-linux-kernel/pm…
…-linux-feature-tree into ti-linux-3.14.y TI-Feature: power_management_base TI-Tree: git://git.ti.com/~kristo/ti-linux-kernel/pm-linux-feature-tree.git TI-Branch: pm-ti-linux-3.14.y * 'pm-ti-linux-3.14.y' of git://git.ti.com/~kristo/ti-linux-kernel/pm-linux-feature-tree: ARM: OMAP2: pm33xx: Bump firmware version requirement to 0x190 remoteproc: wkup_m3_rproc: Modify wkup_m3_ping to not use interrupts remoteproc: wkup_m3: Defer probe until wkup_m3_pm_ops are populated ARM: OMAP2+: pm33xx: Only pass i2c volt scale offsets for DeepSleep ARM: dts: AM4372: Add ti,mbox-send-noirq to wkup_m3 mailbox ARM: dts: AM33XX: Add ti,mbox-send-noirq to wkup_m3 mailbox mailbox/omap: Add ti,mbox-send-noirq quirk to fix AM33xx CPU Idle Signed-off-by: Dan Murphy <DMurphy@ti.com>
Showing 7 changed files Side-by-side Diff
Documentation/devicetree/bindings/mailbox/omap-mailbox.txt
... | ... | @@ -75,6 +75,14 @@ |
75 | 75 | Cell #3 (usr_id) - mailbox user id for identifying the interrupt line |
76 | 76 | associated with generating a tx/rx fifo interrupt. |
77 | 77 | |
78 | +Optional Properties: | |
79 | +-------------------- | |
80 | +- ti,mbox-send-noirq: Quirk flag to allow the client user of this sub-mailbox | |
81 | + to send messages without triggering a Tx ready interrupt, | |
82 | + and to control the Tx ticker. Should be used only on | |
83 | + sub-mailboxes used to communicate with WkupM3 remote | |
84 | + processor on AM33xx/AM43xx SoCs. | |
85 | + | |
78 | 86 | Mailbox Users: |
79 | 87 | ============== |
80 | 88 | A device needing to communicate with a target processor device should specify |
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/am4372.dtsi
arch/arm/mach-omap2/pm33xx.c
... | ... | @@ -115,6 +115,7 @@ |
115 | 115 | am33xx_pm->ipc.reg1 = IPC_CMD_IDLE; |
116 | 116 | am33xx_pm->ipc.reg2 = DS_IPC_DEFAULT; |
117 | 117 | am33xx_pm->ipc.reg3 = m3_flags; |
118 | + am33xx_pm->ipc.reg5 = DS_IPC_DEFAULT; | |
118 | 119 | wkup_m3_set_cmd(&am33xx_pm->ipc); |
119 | 120 | ret = wkup_m3_ping(); |
120 | 121 | if (ret < 0) |
121 | 122 | |
... | ... | @@ -341,9 +342,11 @@ |
341 | 342 | switch (state) { |
342 | 343 | case PM_SUSPEND_MEM: |
343 | 344 | am33xx_pm->ipc.reg1 = IPC_CMD_DS0; |
345 | + am33xx_pm->ipc.reg5 = am33xx_pm->m3_i2c_sequence_offsets; | |
344 | 346 | break; |
345 | 347 | case PM_SUSPEND_STANDBY: |
346 | 348 | am33xx_pm->ipc.reg1 = IPC_CMD_STANDBY; |
349 | + am33xx_pm->ipc.reg5 = DS_IPC_DEFAULT; | |
347 | 350 | break; |
348 | 351 | } |
349 | 352 | |
... | ... | @@ -422,7 +425,7 @@ |
422 | 425 | val = (aux_base + hdr.sleep_offset); |
423 | 426 | val |= ((aux_base + hdr.wake_offset) << 16); |
424 | 427 | |
425 | - am33xx_pm->ipc.reg5 = val; | |
428 | + am33xx_pm->m3_i2c_sequence_offsets = val; | |
426 | 429 | |
427 | 430 | release_sd_fw: |
428 | 431 | release_firmware(fw); |
arch/arm/mach-omap2/pm33xx.h
... | ... | @@ -35,6 +35,7 @@ |
35 | 35 | struct am33xx_pm_ops *ops; |
36 | 36 | u8 state; |
37 | 37 | u32 ver; |
38 | + u32 m3_i2c_sequence_offsets; | |
38 | 39 | const char *sd_fw_name; |
39 | 40 | }; |
40 | 41 | |
... | ... | @@ -69,7 +70,7 @@ |
69 | 70 | #define IPC_CMD_RESET 0xe |
70 | 71 | #define DS_IPC_DEFAULT 0xffffffff |
71 | 72 | #define M3_VERSION_UNKNOWN 0x0000ffff |
72 | -#define M3_BASELINE_VERSION 0x189 | |
73 | +#define M3_BASELINE_VERSION 0x190 | |
73 | 74 | |
74 | 75 | #define M3_STATE_UNKNOWN 0 |
75 | 76 | #define M3_STATE_RESET 1 |
drivers/mailbox/omap-mailbox.c
... | ... | @@ -67,6 +67,13 @@ |
67 | 67 | #define MBOX_NR_REGS (MBOX_REG_SIZE / sizeof(u32)) |
68 | 68 | #define OMAP4_MBOX_NR_REGS (OMAP4_MBOX_REG_SIZE / sizeof(u32)) |
69 | 69 | |
70 | +/* | |
71 | + * We need this for special case handling where controller indicates done | |
72 | + * state with IRQ but a specific channel needs to use manually ACK (used | |
73 | + * by wkup_m3 on AM33xx/AM43xx). | |
74 | + */ | |
75 | +#define MBOX_TXDONE_BY_ACK (1 << 2) | |
76 | + | |
70 | 77 | struct omap_mbox_fifo { |
71 | 78 | unsigned long msg; |
72 | 79 | unsigned long fifo_stat; |
... | ... | @@ -106,6 +113,7 @@ |
106 | 113 | int rx_irq; |
107 | 114 | |
108 | 115 | const char *name; |
116 | + bool send_no_irq; | |
109 | 117 | }; |
110 | 118 | |
111 | 119 | struct omap_mbox { |
... | ... | @@ -119,6 +127,7 @@ |
119 | 127 | u32 ctx[OMAP4_MBOX_NR_REGS]; |
120 | 128 | u32 intr_type; |
121 | 129 | struct mbox_chan *chan; |
130 | + bool send_no_irq; | |
122 | 131 | }; |
123 | 132 | |
124 | 133 | /* global variables for the mailbox devices */ |
... | ... | @@ -418,6 +427,9 @@ |
418 | 427 | goto fail_request_irq; |
419 | 428 | } |
420 | 429 | |
430 | + if (mbox->send_no_irq) | |
431 | + mbox->chan->txdone_method = MBOX_TXDONE_BY_ACK; | |
432 | + | |
421 | 433 | _omap_mbox_enable_irq(mbox, IRQ_RX); |
422 | 434 | |
423 | 435 | return 0; |
424 | 436 | |
425 | 437 | |
426 | 438 | |
... | ... | @@ -586,14 +598,28 @@ |
586 | 598 | mutex_unlock(&mdev->cfg_lock); |
587 | 599 | } |
588 | 600 | |
589 | -static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data) | |
601 | +static int omap_mbox_chan_send_noirq(struct omap_mbox *mbox, void *data) | |
590 | 602 | { |
591 | - struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan); | |
592 | 603 | int ret = -EBUSY; |
593 | 604 | |
594 | - if (!mbox) | |
595 | - return -EINVAL; | |
605 | + if (!mbox_fifo_full(mbox)) { | |
606 | + _omap_mbox_enable_irq(mbox, IRQ_RX); | |
607 | + mbox_fifo_write(mbox, (mbox_msg_t)data); | |
608 | + ret = 0; | |
609 | + _omap_mbox_disable_irq(mbox, IRQ_RX); | |
596 | 610 | |
611 | + /* we must read and ack the interrupt directly from here */ | |
612 | + mbox_fifo_read(mbox); | |
613 | + ack_mbox_irq(mbox, IRQ_RX); | |
614 | + } | |
615 | + | |
616 | + return ret; | |
617 | +} | |
618 | + | |
619 | +static int omap_mbox_chan_send(struct omap_mbox *mbox, void *data) | |
620 | +{ | |
621 | + int ret = -EBUSY; | |
622 | + | |
597 | 623 | if (!mbox_fifo_full(mbox)) { |
598 | 624 | mbox_fifo_write(mbox, (mbox_msg_t)data); |
599 | 625 | ret = 0; |
... | ... | @@ -604,6 +630,22 @@ |
604 | 630 | return ret; |
605 | 631 | } |
606 | 632 | |
633 | +static int omap_mbox_chan_send_data(struct mbox_chan *chan, void *data) | |
634 | +{ | |
635 | + struct omap_mbox *mbox = mbox_chan_to_omap_mbox(chan); | |
636 | + int ret; | |
637 | + | |
638 | + if (!mbox) | |
639 | + return -EINVAL; | |
640 | + | |
641 | + if (mbox->send_no_irq) | |
642 | + ret = omap_mbox_chan_send_noirq(mbox, data); | |
643 | + else | |
644 | + ret = omap_mbox_chan_send(mbox, data); | |
645 | + | |
646 | + return ret; | |
647 | +} | |
648 | + | |
607 | 649 | static struct mbox_chan_ops omap_mbox_chan_ops = { |
608 | 650 | .startup = omap_mbox_chan_startup, |
609 | 651 | .send_data = omap_mbox_chan_send_data, |
... | ... | @@ -732,6 +774,9 @@ |
732 | 774 | finfo->rx_usr = tmp[2]; |
733 | 775 | |
734 | 776 | finfo->name = child->name; |
777 | + | |
778 | + if (of_find_property(child, "ti,mbox-send-noirq", NULL)) | |
779 | + finfo->send_no_irq = true; | |
735 | 780 | } else { |
736 | 781 | finfo->tx_id = info->tx_id; |
737 | 782 | finfo->rx_id = info->rx_id; |
... | ... | @@ -791,6 +836,7 @@ |
791 | 836 | fifo->irqstatus = MAILBOX_IRQSTATUS(intr_type, finfo->rx_usr); |
792 | 837 | fifo->irqdisable = MAILBOX_IRQDISABLE(intr_type, finfo->rx_usr); |
793 | 838 | |
839 | + mbox->send_no_irq = finfo->send_no_irq; | |
794 | 840 | mbox->intr_type = intr_type; |
795 | 841 | |
796 | 842 | mbox->parent = mdev; |
drivers/remoteproc/wkup_m3_rproc.c
... | ... | @@ -150,11 +150,6 @@ |
150 | 150 | wkup_m3_ctrl_ipc_write(m3_rproc_static, val, 2); |
151 | 151 | } |
152 | 152 | |
153 | -static void wkup_m3_mbox_callback(struct mbox_client *client, void *data) | |
154 | -{ | |
155 | - omap_mbox_disable_irq(m3_rproc_static->mbox, IRQ_RX); | |
156 | -} | |
157 | - | |
158 | 153 | void wkup_m3_set_rtc_only_mode(void) |
159 | 154 | { |
160 | 155 | m3_rproc_static->is_rtc_only = true; |
... | ... | @@ -179,7 +174,7 @@ |
179 | 174 | |
180 | 175 | m3_rproc->mbox_client.dev = dev; |
181 | 176 | m3_rproc->mbox_client.tx_done = NULL; |
182 | - m3_rproc->mbox_client.rx_callback = wkup_m3_mbox_callback; | |
177 | + m3_rproc->mbox_client.rx_callback = NULL; | |
183 | 178 | m3_rproc->mbox_client.tx_block = false; |
184 | 179 | m3_rproc->mbox_client.knows_txdone = false; |
185 | 180 | |
186 | 181 | |
... | ... | @@ -283,13 +278,13 @@ |
283 | 278 | * the RX callback to avoid multiple interrupts being received |
284 | 279 | * by the CM3. |
285 | 280 | */ |
286 | - omap_mbox_enable_irq(m3_rproc_static->mbox, IRQ_RX); | |
287 | 281 | ret = mbox_send_message(m3_rproc_static->mbox, (void *)dummy_msg); |
288 | 282 | if (ret < 0) { |
289 | 283 | pr_err("%s: mbox_send_message() failed: %d\n", __func__, ret); |
290 | 284 | return ret; |
291 | 285 | } |
292 | 286 | |
287 | + mbox_client_txdone(m3_rproc_static->mbox, 0); | |
293 | 288 | return 0; |
294 | 289 | } |
295 | 290 | |
... | ... | @@ -388,6 +383,9 @@ |
388 | 383 | int irq, ret; |
389 | 384 | struct resource *res; |
390 | 385 | struct task_struct *task; |
386 | + | |
387 | + if (!wkup_m3_pm_ops) | |
388 | + return -EPROBE_DEFER; | |
391 | 389 | |
392 | 390 | pm_runtime_enable(&pdev->dev); |
393 | 391 |