Commit 477d7cae authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'mailbox-for-next' of git://git.linaro.org/landing-teams/working/fujitsu/integration

Pull mailbox updates from Jassi Brar:

 - new driver for Broadcom FlexRM controller

 - constify data structures of callback functions in some drivers

 - a few bug fixes uncovered by multi-threaded use of mailbox channels
   in blocking mode

* 'mailbox-for-next' of git://git.linaro.org/landing-teams/working/fujitsu/integration:
  mailbox: handle empty message in tx_tick
  mailbox: skip complete wait event if timer expired
  mailbox: always wait in mbox_send_message for blocking Tx mode
  mailbox: Remove depends on COMPILE_TEST for BCM_FLEXRM_MBOX
  mailbox: check ->last_tx_done for NULL in case of timer-based polling
  dt-bindings: Add DT bindings info for FlexRM ring manager
  mailbox: Add driver for Broadcom FlexRM ring manager
  dt-bindings: mailbox: Update doc with NSP PDC/mailbox support
  mailbox: bcm-pdc: Add Northstar Plus support to PDC driver
  mailbox: constify mbox_chan_ops structures
parents 6fb41cbd cb710ab1
Broadcom FlexRM Ring Manager
============================
The Broadcom FlexRM ring manager provides a set of rings which can be
used to submit work to offload engines. An SoC may have multiple FlexRM
hardware blocks. There is one device tree entry per FlexRM block. The
FlexRM driver will create a mailbox-controller instance for given FlexRM
hardware block where each mailbox channel is a separate FlexRM ring.
Required properties:
--------------------
- compatible: Should be "brcm,iproc-flexrm-mbox"
- reg: Specifies base physical address and size of the FlexRM
ring registers
- msi-parent: Phandles (and potential Device IDs) to MSI controllers
The FlexRM engine will send MSIs (instead of wired
interrupts) to CPU. There is one MSI for each FlexRM ring.
Refer devicetree/bindings/interrupt-controller/msi.txt
- #mbox-cells: Specifies the number of cells needed to encode a mailbox
channel. This should be 3.
The 1st cell is the mailbox channel number.
The 2nd cell contains MSI completion threshold. This is the
number of completion messages for which FlexRM will inject
one MSI interrupt to CPU.
The 3nd cell contains MSI timer value representing time for
which FlexRM will wait to accumulate N completion messages
where N is the value specified by 2nd cell above. If FlexRM
does not get required number of completion messages in time
specified by this cell then it will inject one MSI interrupt
to CPU provided atleast one completion message is available.
Optional properties:
--------------------
- dma-coherent: Present if DMA operations made by the FlexRM engine (such
as DMA descriptor access, access to buffers pointed by DMA
descriptors and read/write pointer updates to DDR) are
cache coherent with the CPU.
Example:
--------
crypto_mbox: mbox@67000000 {
compatible = "brcm,iproc-flexrm-mbox";
reg = <0x67000000 0x200000>;
msi-parent = <&gic_its 0x7f00>;
#mbox-cells = <3>;
};
crypto@672c0000 {
compatible = "brcm,spu2-v2-crypto";
reg = <0x672c0000 0x1000>;
mboxes = <&crypto_mbox 0 0x1 0xffff>,
<&crypto_mbox 1 0x1 0xffff>,
<&crypto_mbox 16 0x1 0xffff>,
<&crypto_mbox 17 0x1 0xffff>,
<&crypto_mbox 30 0x1 0xffff>,
<&crypto_mbox 31 0x1 0xffff>;
};
The PDC driver manages data transfer to and from various offload engines The PDC driver manages data transfer to and from various offload engines
on some Broadcom SoCs. An SoC may have multiple PDC hardware blocks. There is on some Broadcom SoCs. An SoC may have multiple PDC hardware blocks. There is
one device tree entry per block. one device tree entry per block. On some chips, the PDC functionality is
handled by the FA2 (Northstar Plus).
Required properties: Required properties:
- compatible : Should be "brcm,iproc-pdc-mbox". - compatible : Should be "brcm,iproc-pdc-mbox" or "brcm,iproc-fa2-mbox" for
FA2/Northstar Plus.
- reg: Should contain PDC registers location and length. - reg: Should contain PDC registers location and length.
- interrupts: Should contain the IRQ line for the PDC. - interrupts: Should contain the IRQ line for the PDC.
- #mbox-cells: 1 - #mbox-cells: 1
......
...@@ -144,12 +144,22 @@ config XGENE_SLIMPRO_MBOX ...@@ -144,12 +144,22 @@ config XGENE_SLIMPRO_MBOX
want to use the APM X-Gene SLIMpro IPCM support. want to use the APM X-Gene SLIMpro IPCM support.
config BCM_PDC_MBOX config BCM_PDC_MBOX
tristate "Broadcom PDC Mailbox" tristate "Broadcom FlexSparx DMA Mailbox"
depends on ARM64 || COMPILE_TEST depends on ARCH_BCM_IPROC || COMPILE_TEST
depends on HAS_DMA depends on HAS_DMA
help
Mailbox implementation for the Broadcom FlexSparx DMA ring manager,
which provides access to various offload engines on Broadcom
SoCs, including FA2/FA+ on Northstar Plus and PDC on Northstar 2.
config BCM_FLEXRM_MBOX
tristate "Broadcom FlexRM Mailbox"
depends on ARM64
depends on HAS_DMA
select GENERIC_MSI_IRQ_DOMAIN
default ARCH_BCM_IPROC default ARCH_BCM_IPROC
help help
Mailbox implementation for the Broadcom PDC ring manager, Mailbox implementation of the Broadcom FlexRM ring manager,
which provides access to various offload engines on Broadcom which provides access to various offload engines on Broadcom
SoCs. Say Y here if you want to use the Broadcom PDC. SoCs. Say Y here if you want to use the Broadcom FlexRM.
endif endif
...@@ -30,4 +30,6 @@ obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o ...@@ -30,4 +30,6 @@ obj-$(CONFIG_HI6220_MBOX) += hi6220-mailbox.o
obj-$(CONFIG_BCM_PDC_MBOX) += bcm-pdc-mailbox.o obj-$(CONFIG_BCM_PDC_MBOX) += bcm-pdc-mailbox.o
obj-$(CONFIG_BCM_FLEXRM_MBOX) += bcm-flexrm-mailbox.o
obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o obj-$(CONFIG_TEGRA_HSP_MBOX) += tegra-hsp.o
This diff is collapsed.
...@@ -18,7 +18,8 @@ ...@@ -18,7 +18,8 @@
* Broadcom PDC Mailbox Driver * Broadcom PDC Mailbox Driver
* The PDC provides a ring based programming interface to one or more hardware * The PDC provides a ring based programming interface to one or more hardware
* offload engines. For example, the PDC driver works with both SPU-M and SPU2 * offload engines. For example, the PDC driver works with both SPU-M and SPU2
* cryptographic offload hardware. In some chips the PDC is referred to as MDE. * cryptographic offload hardware. In some chips the PDC is referred to as MDE,
* and in others the FA2/FA+ hardware is used with this PDC driver.
* *
* The PDC driver registers with the Linux mailbox framework as a mailbox * The PDC driver registers with the Linux mailbox framework as a mailbox
* controller, once for each PDC instance. Ring 0 for each PDC is registered as * controller, once for each PDC instance. Ring 0 for each PDC is registered as
...@@ -108,6 +109,7 @@ ...@@ -108,6 +109,7 @@
#define PDC_INTMASK_OFFSET 0x24 #define PDC_INTMASK_OFFSET 0x24
#define PDC_INTSTATUS_OFFSET 0x20 #define PDC_INTSTATUS_OFFSET 0x20
#define PDC_RCVLAZY0_OFFSET (0x30 + 4 * PDC_RINGSET) #define PDC_RCVLAZY0_OFFSET (0x30 + 4 * PDC_RINGSET)
#define FA_RCVLAZY0_OFFSET 0x100
/* /*
* For SPU2, configure MDE_CKSUM_CONTROL to write 17 bytes of metadata * For SPU2, configure MDE_CKSUM_CONTROL to write 17 bytes of metadata
...@@ -162,6 +164,11 @@ ...@@ -162,6 +164,11 @@
/* Maximum size buffer the DMA engine can handle */ /* Maximum size buffer the DMA engine can handle */
#define PDC_DMA_BUF_MAX 16384 #define PDC_DMA_BUF_MAX 16384
enum pdc_hw {
FA_HW, /* FA2/FA+ hardware (i.e. Northstar Plus) */
PDC_HW /* PDC/MDE hardware (i.e. Northstar 2, Pegasus) */
};
struct pdc_dma_map { struct pdc_dma_map {
void *ctx; /* opaque context associated with frame */ void *ctx; /* opaque context associated with frame */
}; };
...@@ -211,13 +218,13 @@ struct pdc_regs { ...@@ -211,13 +218,13 @@ struct pdc_regs {
u32 gptimer; /* 0x028 */ u32 gptimer; /* 0x028 */
u32 PAD; u32 PAD;
u32 intrcvlazy_0; /* 0x030 */ u32 intrcvlazy_0; /* 0x030 (Only in PDC, not FA2) */
u32 intrcvlazy_1; /* 0x034 */ u32 intrcvlazy_1; /* 0x034 (Only in PDC, not FA2) */
u32 intrcvlazy_2; /* 0x038 */ u32 intrcvlazy_2; /* 0x038 (Only in PDC, not FA2) */
u32 intrcvlazy_3; /* 0x03c */ u32 intrcvlazy_3; /* 0x03c (Only in PDC, not FA2) */
u32 PAD[48]; u32 PAD[48];
u32 removed_intrecvlazy; /* 0x100 */ u32 fa_intrecvlazy; /* 0x100 (Only in FA2, not PDC) */
u32 flowctlthresh; /* 0x104 */ u32 flowctlthresh; /* 0x104 */
u32 wrrthresh; /* 0x108 */ u32 wrrthresh; /* 0x108 */
u32 gmac_idle_cnt_thresh; /* 0x10c */ u32 gmac_idle_cnt_thresh; /* 0x10c */
...@@ -243,7 +250,7 @@ struct pdc_regs { ...@@ -243,7 +250,7 @@ struct pdc_regs {
u32 serdes_status1; /* 0x1b0 */ u32 serdes_status1; /* 0x1b0 */
u32 PAD[11]; /* 0x1b4-1dc */ u32 PAD[11]; /* 0x1b4-1dc */
u32 clk_ctl_st; /* 0x1e0 */ u32 clk_ctl_st; /* 0x1e0 */
u32 hw_war; /* 0x1e4 */ u32 hw_war; /* 0x1e4 (Only in PDC, not FA2) */
u32 pwrctl; /* 0x1e8 */ u32 pwrctl; /* 0x1e8 */
u32 PAD[5]; u32 PAD[5];
...@@ -410,6 +417,9 @@ struct pdc_state { ...@@ -410,6 +417,9 @@ struct pdc_state {
u32 txnobuf; /* unable to create tx descriptor */ u32 txnobuf; /* unable to create tx descriptor */
u32 rxnobuf; /* unable to create rx descriptor */ u32 rxnobuf; /* unable to create rx descriptor */
u32 rx_oflow; /* count of rx overflows */ u32 rx_oflow; /* count of rx overflows */
/* hardware type - FA2 or PDC/MDE */
enum pdc_hw hw_type;
}; };
/* Global variables */ /* Global variables */
...@@ -1396,7 +1406,13 @@ static int pdc_interrupts_init(struct pdc_state *pdcs) ...@@ -1396,7 +1406,13 @@ static int pdc_interrupts_init(struct pdc_state *pdcs)
/* interrupt configuration */ /* interrupt configuration */
iowrite32(PDC_INTMASK, pdcs->pdc_reg_vbase + PDC_INTMASK_OFFSET); iowrite32(PDC_INTMASK, pdcs->pdc_reg_vbase + PDC_INTMASK_OFFSET);
iowrite32(PDC_LAZY_INT, pdcs->pdc_reg_vbase + PDC_RCVLAZY0_OFFSET);
if (pdcs->hw_type == FA_HW)
iowrite32(PDC_LAZY_INT, pdcs->pdc_reg_vbase +
FA_RCVLAZY0_OFFSET);
else
iowrite32(PDC_LAZY_INT, pdcs->pdc_reg_vbase +
PDC_RCVLAZY0_OFFSET);
/* read irq from device tree */ /* read irq from device tree */
pdcs->pdc_irq = irq_of_parse_and_map(dn, 0); pdcs->pdc_irq = irq_of_parse_and_map(dn, 0);
...@@ -1465,6 +1481,17 @@ static int pdc_mb_init(struct pdc_state *pdcs) ...@@ -1465,6 +1481,17 @@ static int pdc_mb_init(struct pdc_state *pdcs)
return 0; return 0;
} }
/* Device tree API */
static const int pdc_hw = PDC_HW;
static const int fa_hw = FA_HW;
static const struct of_device_id pdc_mbox_of_match[] = {
{.compatible = "brcm,iproc-pdc-mbox", .data = &pdc_hw},
{.compatible = "brcm,iproc-fa2-mbox", .data = &fa_hw},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, pdc_mbox_of_match);
/** /**
* pdc_dt_read() - Read application-specific data from device tree. * pdc_dt_read() - Read application-specific data from device tree.
* @pdev: Platform device * @pdev: Platform device
...@@ -1481,6 +1508,8 @@ static int pdc_dt_read(struct platform_device *pdev, struct pdc_state *pdcs) ...@@ -1481,6 +1508,8 @@ static int pdc_dt_read(struct platform_device *pdev, struct pdc_state *pdcs)
{ {
struct device *dev = &pdev->dev; struct device *dev = &pdev->dev;
struct device_node *dn = pdev->dev.of_node; struct device_node *dn = pdev->dev.of_node;
const struct of_device_id *match;
const int *hw_type;
int err; int err;
err = of_property_read_u32(dn, "brcm,rx-status-len", err = of_property_read_u32(dn, "brcm,rx-status-len",
...@@ -1492,6 +1521,14 @@ static int pdc_dt_read(struct platform_device *pdev, struct pdc_state *pdcs) ...@@ -1492,6 +1521,14 @@ static int pdc_dt_read(struct platform_device *pdev, struct pdc_state *pdcs)
pdcs->use_bcm_hdr = of_property_read_bool(dn, "brcm,use-bcm-hdr"); pdcs->use_bcm_hdr = of_property_read_bool(dn, "brcm,use-bcm-hdr");
pdcs->hw_type = PDC_HW;
match = of_match_device(of_match_ptr(pdc_mbox_of_match), dev);
if (match != NULL) {
hw_type = match->data;
pdcs->hw_type = *hw_type;
}
return 0; return 0;
} }
...@@ -1525,7 +1562,7 @@ static int pdc_probe(struct platform_device *pdev) ...@@ -1525,7 +1562,7 @@ static int pdc_probe(struct platform_device *pdev)
pdcs->pdc_idx = pdcg.num_spu; pdcs->pdc_idx = pdcg.num_spu;
pdcg.num_spu++; pdcg.num_spu++;
err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(32)); err = dma_set_mask_and_coherent(dev, DMA_BIT_MASK(39));
if (err) { if (err) {
dev_warn(dev, "PDC device cannot perform DMA. Error %d.", err); dev_warn(dev, "PDC device cannot perform DMA. Error %d.", err);
goto cleanup; goto cleanup;
...@@ -1611,12 +1648,6 @@ static int pdc_remove(struct platform_device *pdev) ...@@ -1611,12 +1648,6 @@ static int pdc_remove(struct platform_device *pdev)
return 0; return 0;
} }
static const struct of_device_id pdc_mbox_of_match[] = {
{.compatible = "brcm,iproc-pdc-mbox"},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, pdc_mbox_of_match);
static struct platform_driver pdc_mbox_driver = { static struct platform_driver pdc_mbox_driver = {
.probe = pdc_probe, .probe = pdc_probe,
.remove = pdc_remove, .remove = pdc_remove,
......
...@@ -221,7 +221,7 @@ static void hi6220_mbox_shutdown(struct mbox_chan *chan) ...@@ -221,7 +221,7 @@ static void hi6220_mbox_shutdown(struct mbox_chan *chan)
mbox->irq_map_chan[mchan->ack_irq] = NULL; mbox->irq_map_chan[mchan->ack_irq] = NULL;
} }
static struct mbox_chan_ops hi6220_mbox_ops = { static const struct mbox_chan_ops hi6220_mbox_ops = {
.send_data = hi6220_mbox_send_data, .send_data = hi6220_mbox_send_data,
.startup = hi6220_mbox_startup, .startup = hi6220_mbox_startup,
.shutdown = hi6220_mbox_shutdown, .shutdown = hi6220_mbox_shutdown,
......
...@@ -174,7 +174,7 @@ static void slimpro_mbox_shutdown(struct mbox_chan *chan) ...@@ -174,7 +174,7 @@ static void slimpro_mbox_shutdown(struct mbox_chan *chan)
devm_free_irq(mb_chan->dev, mb_chan->irq, mb_chan); devm_free_irq(mb_chan->dev, mb_chan->irq, mb_chan);
} }
static struct mbox_chan_ops slimpro_mbox_ops = { static const struct mbox_chan_ops slimpro_mbox_ops = {
.send_data = slimpro_mbox_send_data, .send_data = slimpro_mbox_send_data,
.startup = slimpro_mbox_startup, .startup = slimpro_mbox_startup,
.shutdown = slimpro_mbox_shutdown, .shutdown = slimpro_mbox_shutdown,
......
...@@ -103,11 +103,14 @@ static void tx_tick(struct mbox_chan *chan, int r) ...@@ -103,11 +103,14 @@ static void tx_tick(struct mbox_chan *chan, int r)
/* Submit next message */ /* Submit next message */
msg_submit(chan); msg_submit(chan);
if (!mssg)
return;
/* Notify the client */ /* Notify the client */
if (mssg && chan->cl->tx_done) if (chan->cl->tx_done)
chan->cl->tx_done(chan->cl, mssg, r); chan->cl->tx_done(chan->cl, mssg, r);
if (chan->cl->tx_block) if (r != -ETIME && chan->cl->tx_block)
complete(&chan->tx_complete); complete(&chan->tx_complete);
} }
...@@ -260,7 +263,7 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg) ...@@ -260,7 +263,7 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
msg_submit(chan); msg_submit(chan);
if (chan->cl->tx_block && chan->active_req) { if (chan->cl->tx_block) {
unsigned long wait; unsigned long wait;
int ret; int ret;
...@@ -271,8 +274,8 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg) ...@@ -271,8 +274,8 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
ret = wait_for_completion_timeout(&chan->tx_complete, wait); ret = wait_for_completion_timeout(&chan->tx_complete, wait);
if (ret == 0) { if (ret == 0) {
t = -EIO; t = -ETIME;
tx_tick(chan, -EIO); tx_tick(chan, t);
} }
} }
...@@ -453,6 +456,12 @@ int mbox_controller_register(struct mbox_controller *mbox) ...@@ -453,6 +456,12 @@ int mbox_controller_register(struct mbox_controller *mbox)
txdone = TXDONE_BY_ACK; txdone = TXDONE_BY_ACK;
if (txdone == TXDONE_BY_POLL) { if (txdone == TXDONE_BY_POLL) {
if (!mbox->ops->last_tx_done) {
dev_err(mbox->dev, "last_tx_done method is absent\n");
return -EINVAL;
}
hrtimer_init(&mbox->poll_hrt, CLOCK_MONOTONIC, hrtimer_init(&mbox->poll_hrt, CLOCK_MONOTONIC,
HRTIMER_MODE_REL); HRTIMER_MODE_REL);
mbox->poll_hrt.function = txdone_hrtimer; mbox->poll_hrt.function = txdone_hrtimer;
......
...@@ -16,6 +16,7 @@ ...@@ -16,6 +16,7 @@
enum brcm_message_type { enum brcm_message_type {
BRCM_MESSAGE_UNKNOWN = 0, BRCM_MESSAGE_UNKNOWN = 0,
BRCM_MESSAGE_BATCH,
BRCM_MESSAGE_SPU, BRCM_MESSAGE_SPU,
BRCM_MESSAGE_SBA, BRCM_MESSAGE_SBA,
BRCM_MESSAGE_MAX, BRCM_MESSAGE_MAX,
...@@ -23,23 +24,28 @@ enum brcm_message_type { ...@@ -23,23 +24,28 @@ enum brcm_message_type {
struct brcm_sba_command { struct brcm_sba_command {
u64 cmd; u64 cmd;
u64 *cmd_dma;
dma_addr_t cmd_dma_addr;
#define BRCM_SBA_CMD_TYPE_A BIT(0) #define BRCM_SBA_CMD_TYPE_A BIT(0)
#define BRCM_SBA_CMD_TYPE_B BIT(1) #define BRCM_SBA_CMD_TYPE_B BIT(1)
#define BRCM_SBA_CMD_TYPE_C BIT(2) #define BRCM_SBA_CMD_TYPE_C BIT(2)
#define BRCM_SBA_CMD_HAS_RESP BIT(3) #define BRCM_SBA_CMD_HAS_RESP BIT(3)
#define BRCM_SBA_CMD_HAS_OUTPUT BIT(4) #define BRCM_SBA_CMD_HAS_OUTPUT BIT(4)
u64 flags; u64 flags;
dma_addr_t input;
size_t input_len;
dma_addr_t resp; dma_addr_t resp;
size_t resp_len; size_t resp_len;
dma_addr_t output; dma_addr_t data;
size_t output_len; size_t data_len;
}; };
struct brcm_message { struct brcm_message {
enum brcm_message_type type; enum brcm_message_type type;
union { union {
struct {
struct brcm_message *msgs;
unsigned int msgs_queued;
unsigned int msgs_count;
} batch;
struct { struct {
struct scatterlist *src; struct scatterlist *src;
struct scatterlist *dst; struct scatterlist *dst;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment