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
This commit is contained in:
commit
477d7caeed
|
@ -0,0 +1,59 @@
|
|||
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>;
|
||||
};
|
|
@ -1,9 +1,11 @@
|
|||
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
|
||||
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:
|
||||
- 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.
|
||||
- interrupts: Should contain the IRQ line for the PDC.
|
||||
- #mbox-cells: 1
|
||||
|
|
|
@ -144,12 +144,22 @@ config XGENE_SLIMPRO_MBOX
|
|||
want to use the APM X-Gene SLIMpro IPCM support.
|
||||
|
||||
config BCM_PDC_MBOX
|
||||
tristate "Broadcom PDC Mailbox"
|
||||
depends on ARM64 || COMPILE_TEST
|
||||
tristate "Broadcom FlexSparx DMA Mailbox"
|
||||
depends on ARCH_BCM_IPROC || COMPILE_TEST
|
||||
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
|
||||
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
|
||||
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
|
||||
|
|
|
@ -30,4 +30,6 @@ obj-$(CONFIG_HI6220_MBOX) += hi6220-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
|
||||
|
|
1595
drivers/mailbox/bcm-flexrm-mailbox.c
Normal file
1595
drivers/mailbox/bcm-flexrm-mailbox.c
Normal file
File diff suppressed because it is too large
Load diff
|
@ -18,7 +18,8 @@
|
|||
* Broadcom PDC Mailbox Driver
|
||||
* 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
|
||||
* 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
|
||||
* controller, once for each PDC instance. Ring 0 for each PDC is registered as
|
||||
|
@ -108,6 +109,7 @@
|
|||
#define PDC_INTMASK_OFFSET 0x24
|
||||
#define PDC_INTSTATUS_OFFSET 0x20
|
||||
#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
|
||||
|
@ -162,6 +164,11 @@
|
|||
/* Maximum size buffer the DMA engine can handle */
|
||||
#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 {
|
||||
void *ctx; /* opaque context associated with frame */
|
||||
};
|
||||
|
@ -211,13 +218,13 @@ struct pdc_regs {
|
|||
u32 gptimer; /* 0x028 */
|
||||
|
||||
u32 PAD;
|
||||
u32 intrcvlazy_0; /* 0x030 */
|
||||
u32 intrcvlazy_1; /* 0x034 */
|
||||
u32 intrcvlazy_2; /* 0x038 */
|
||||
u32 intrcvlazy_3; /* 0x03c */
|
||||
u32 intrcvlazy_0; /* 0x030 (Only in PDC, not FA2) */
|
||||
u32 intrcvlazy_1; /* 0x034 (Only in PDC, not FA2) */
|
||||
u32 intrcvlazy_2; /* 0x038 (Only in PDC, not FA2) */
|
||||
u32 intrcvlazy_3; /* 0x03c (Only in PDC, not FA2) */
|
||||
|
||||
u32 PAD[48];
|
||||
u32 removed_intrecvlazy; /* 0x100 */
|
||||
u32 fa_intrecvlazy; /* 0x100 (Only in FA2, not PDC) */
|
||||
u32 flowctlthresh; /* 0x104 */
|
||||
u32 wrrthresh; /* 0x108 */
|
||||
u32 gmac_idle_cnt_thresh; /* 0x10c */
|
||||
|
@ -243,7 +250,7 @@ struct pdc_regs {
|
|||
u32 serdes_status1; /* 0x1b0 */
|
||||
u32 PAD[11]; /* 0x1b4-1dc */
|
||||
u32 clk_ctl_st; /* 0x1e0 */
|
||||
u32 hw_war; /* 0x1e4 */
|
||||
u32 hw_war; /* 0x1e4 (Only in PDC, not FA2) */
|
||||
u32 pwrctl; /* 0x1e8 */
|
||||
u32 PAD[5];
|
||||
|
||||
|
@ -410,6 +417,9 @@ struct pdc_state {
|
|||
u32 txnobuf; /* unable to create tx descriptor */
|
||||
u32 rxnobuf; /* unable to create rx descriptor */
|
||||
u32 rx_oflow; /* count of rx overflows */
|
||||
|
||||
/* hardware type - FA2 or PDC/MDE */
|
||||
enum pdc_hw hw_type;
|
||||
};
|
||||
|
||||
/* Global variables */
|
||||
|
@ -1396,7 +1406,13 @@ static int pdc_interrupts_init(struct pdc_state *pdcs)
|
|||
|
||||
/* interrupt configuration */
|
||||
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 */
|
||||
pdcs->pdc_irq = irq_of_parse_and_map(dn, 0);
|
||||
|
@ -1465,6 +1481,17 @@ static int pdc_mb_init(struct pdc_state *pdcs)
|
|||
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.
|
||||
* @pdev: Platform device
|
||||
|
@ -1481,6 +1508,8 @@ static int pdc_dt_read(struct platform_device *pdev, struct pdc_state *pdcs)
|
|||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *dn = pdev->dev.of_node;
|
||||
const struct of_device_id *match;
|
||||
const int *hw_type;
|
||||
int err;
|
||||
|
||||
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)
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -1525,7 +1562,7 @@ static int pdc_probe(struct platform_device *pdev)
|
|||
pdcs->pdc_idx = 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) {
|
||||
dev_warn(dev, "PDC device cannot perform DMA. Error %d.", err);
|
||||
goto cleanup;
|
||||
|
@ -1611,12 +1648,6 @@ static int pdc_remove(struct platform_device *pdev)
|
|||
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 = {
|
||||
.probe = pdc_probe,
|
||||
.remove = pdc_remove,
|
||||
|
|
|
@ -221,7 +221,7 @@ static void hi6220_mbox_shutdown(struct mbox_chan *chan)
|
|||
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,
|
||||
.startup = hi6220_mbox_startup,
|
||||
.shutdown = hi6220_mbox_shutdown,
|
||||
|
|
|
@ -174,7 +174,7 @@ static void slimpro_mbox_shutdown(struct mbox_chan *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,
|
||||
.startup = slimpro_mbox_startup,
|
||||
.shutdown = slimpro_mbox_shutdown,
|
||||
|
|
|
@ -103,11 +103,14 @@ static void tx_tick(struct mbox_chan *chan, int r)
|
|||
/* Submit next message */
|
||||
msg_submit(chan);
|
||||
|
||||
if (!mssg)
|
||||
return;
|
||||
|
||||
/* Notify the client */
|
||||
if (mssg && chan->cl->tx_done)
|
||||
if (chan->cl->tx_done)
|
||||
chan->cl->tx_done(chan->cl, mssg, r);
|
||||
|
||||
if (chan->cl->tx_block)
|
||||
if (r != -ETIME && chan->cl->tx_block)
|
||||
complete(&chan->tx_complete);
|
||||
}
|
||||
|
||||
|
@ -260,7 +263,7 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
|
|||
|
||||
msg_submit(chan);
|
||||
|
||||
if (chan->cl->tx_block && chan->active_req) {
|
||||
if (chan->cl->tx_block) {
|
||||
unsigned long wait;
|
||||
int ret;
|
||||
|
||||
|
@ -271,8 +274,8 @@ int mbox_send_message(struct mbox_chan *chan, void *mssg)
|
|||
|
||||
ret = wait_for_completion_timeout(&chan->tx_complete, wait);
|
||||
if (ret == 0) {
|
||||
t = -EIO;
|
||||
tx_tick(chan, -EIO);
|
||||
t = -ETIME;
|
||||
tx_tick(chan, t);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -453,6 +456,12 @@ int mbox_controller_register(struct mbox_controller *mbox)
|
|||
txdone = TXDONE_BY_ACK;
|
||||
|
||||
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_MODE_REL);
|
||||
mbox->poll_hrt.function = txdone_hrtimer;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
enum brcm_message_type {
|
||||
BRCM_MESSAGE_UNKNOWN = 0,
|
||||
BRCM_MESSAGE_BATCH,
|
||||
BRCM_MESSAGE_SPU,
|
||||
BRCM_MESSAGE_SBA,
|
||||
BRCM_MESSAGE_MAX,
|
||||
|
@ -23,23 +24,28 @@ enum brcm_message_type {
|
|||
|
||||
struct brcm_sba_command {
|
||||
u64 cmd;
|
||||
u64 *cmd_dma;
|
||||
dma_addr_t cmd_dma_addr;
|
||||
#define BRCM_SBA_CMD_TYPE_A BIT(0)
|
||||
#define BRCM_SBA_CMD_TYPE_B BIT(1)
|
||||
#define BRCM_SBA_CMD_TYPE_C BIT(2)
|
||||
#define BRCM_SBA_CMD_HAS_RESP BIT(3)
|
||||
#define BRCM_SBA_CMD_HAS_OUTPUT BIT(4)
|
||||
u64 flags;
|
||||
dma_addr_t input;
|
||||
size_t input_len;
|
||||
dma_addr_t resp;
|
||||
size_t resp_len;
|
||||
dma_addr_t output;
|
||||
size_t output_len;
|
||||
dma_addr_t data;
|
||||
size_t data_len;
|
||||
};
|
||||
|
||||
struct brcm_message {
|
||||
enum brcm_message_type type;
|
||||
union {
|
||||
struct {
|
||||
struct brcm_message *msgs;
|
||||
unsigned int msgs_queued;
|
||||
unsigned int msgs_count;
|
||||
} batch;
|
||||
struct {
|
||||
struct scatterlist *src;
|
||||
struct scatterlist *dst;
|
||||
|
|
Loading…
Reference in a new issue