[PATCH] fsl-rio: add support for mapping inbound windows
Scott Wood
scottwood at freescale.com
Wed Aug 6 07:37:43 EST 2014
On Tue, 2014-08-05 at 15:52 +0200, Martijn de Gouw wrote:
> Add support for mapping and unmapping of inbound rapidio windows.
>
> Signed-off-by: Martijn de Gouw <martijn.de.gouw at prodrive-technologies.com>
Could you elaborate in the changelog on what this fixes or makes
possible? E.g. did the driver previously not support inbound
transactions at all, or did it assume the window was set up by a
bootloader?
Liu Gang, could you review this?
-Scott
> ---
> arch/powerpc/sysdev/fsl_rio.c | 104 +++++++++++++++++++++++++++++++++++++++++
> arch/powerpc/sysdev/fsl_rio.h | 13 ++++++
> 2 files changed, 117 insertions(+)
>
> diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c
> index c04b718..08d60f1 100644
> --- a/arch/powerpc/sysdev/fsl_rio.c
> +++ b/arch/powerpc/sysdev/fsl_rio.c
> @@ -58,6 +58,19 @@
> #define RIO_ISR_AACR 0x10120
> #define RIO_ISR_AACR_AA 0x1 /* Accept All ID */
>
> +#define RIWTAR_TRAD_VAL_SHIFT 12
> +#define RIWTAR_TRAD_MASK 0x00FFFFFF
> +#define RIWBAR_BADD_VAL_SHIFT 12
> +#define RIWBAR_BADD_MASK 0x003FFFFF
> +#define RIWAR_ENABLE 0x80000000
> +#define RIWAR_TGINT_LOCAL 0x00F00000
> +#define RIWAR_RDTYP_NO_SNOOP 0x00040000
> +#define RIWAR_RDTYP_SNOOP 0x00050000
> +#define RIWAR_WRTYP_NO_SNOOP 0x00004000
> +#define RIWAR_WRTYP_SNOOP 0x00005000
> +#define RIWAR_WRTYP_ALLOC 0x00006000
> +#define RIWAR_SIZE_MASK 0x0000003F
> +
> #define __fsl_read_rio_config(x, addr, err, op) \
> __asm__ __volatile__( \
> "1: "op" %1,0(%2)\n" \
> @@ -266,6 +279,89 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid,
> return 0;
> }
>
> +static void fsl_rio_inbound_mem_init(struct rio_priv *priv)
> +{
> + int i;
> +
> + /* close inbound windows */
> + for (i = 0; i < RIO_INB_ATMU_COUNT; i++)
> + out_be32(&priv->inb_atmu_regs[i].riwar, 0);
> +}
> +
> +int fsl_map_inb_mem(struct rio_mport *mport, dma_addr_t lstart,
> + u64 rstart, u32 size, u32 flags)
> +{
> + struct rio_priv *priv = mport->priv;
> + u32 base_size;
> + unsigned int base_size_log;
> + u64 win_start, win_end;
> + u32 riwar;
> + int i;
> +
> + if ((size & (size - 1)) != 0)
> + return -EINVAL;
> +
> + base_size_log = ilog2(size);
> + base_size = 1 << base_size_log;
> +
> + /* check if addresses are aligned with the window size */
> + if (lstart & (base_size - 1))
> + return -EINVAL;
> + if (rstart & (base_size - 1))
> + return -EINVAL;
> +
> + /* check for conflicting ranges */
> + for (i = 0; i < RIO_INB_ATMU_COUNT; i++) {
> + riwar = in_be32(&priv->inb_atmu_regs[i].riwar);
> + if ((riwar & RIWAR_ENABLE) == 0)
> + continue;
> + win_start = ((u64)(in_be32(&priv->inb_atmu_regs[i].riwbar) & RIWBAR_BADD_MASK))
> + << RIWBAR_BADD_VAL_SHIFT;
> + win_end = win_start + ((1 << ((riwar & RIWAR_SIZE_MASK) + 1)) - 1);
> + if (rstart < win_end && (rstart + size) > win_start)
> + return -EINVAL;
> + }
> +
> + /* find unused atmu */
> + for (i = 0; i < RIO_INB_ATMU_COUNT; i++) {
> + riwar = in_be32(&priv->inb_atmu_regs[i].riwar);
> + if ((riwar & RIWAR_ENABLE) == 0)
> + break;
> + }
> + if (i >= RIO_INB_ATMU_COUNT)
> + return -ENOMEM;
> +
> + out_be32(&priv->inb_atmu_regs[i].riwtar, lstart >> RIWTAR_TRAD_VAL_SHIFT);
> + out_be32(&priv->inb_atmu_regs[i].riwbar, rstart >> RIWBAR_BADD_VAL_SHIFT);
> + out_be32(&priv->inb_atmu_regs[i].riwar, RIWAR_ENABLE | RIWAR_TGINT_LOCAL |
> + RIWAR_RDTYP_SNOOP | RIWAR_WRTYP_SNOOP | (base_size_log - 1));
> +
> + return 0;
> +}
> +
> +void fsl_unmap_inb_mem(struct rio_mport *mport, dma_addr_t lstart)
> +{
> + u32 win_start_shift, base_start_shift;
> + struct rio_priv *priv = mport->priv;
> + u32 riwar, riwtar;
> + int i;
> +
> + /* skip default window */
> + base_start_shift = lstart >> RIWTAR_TRAD_VAL_SHIFT;
> + for (i = 0; i < RIO_INB_ATMU_COUNT; i++) {
> + riwar = in_be32(&priv->inb_atmu_regs[i].riwar);
> + if ((riwar & RIWAR_ENABLE) == 0)
> + continue;
> +
> + riwtar = in_be32(&priv->inb_atmu_regs[i].riwtar);
> + win_start_shift = riwtar & RIWTAR_TRAD_MASK;
> + if (win_start_shift == base_start_shift) {
> + out_be32(&priv->inb_atmu_regs[i].riwar, riwar & ~RIWAR_ENABLE);
> + return;
> + }
> + }
> +}
> +
> void fsl_rio_port_error_handler(int offset)
> {
> /*XXX: Error recovery is not implemented, we just clear errors */
> @@ -389,6 +485,8 @@ int fsl_rio_setup(struct platform_device *dev)
> ops->add_outb_message = fsl_add_outb_message;
> ops->add_inb_buffer = fsl_add_inb_buffer;
> ops->get_inb_message = fsl_get_inb_message;
> + ops->map_inb = fsl_map_inb_mem;
> + ops->unmap_inb = fsl_unmap_inb_mem;
>
> rmu_node = of_parse_phandle(dev->dev.of_node, "fsl,srio-rmu-handle", 0);
> if (!rmu_node) {
> @@ -602,6 +700,11 @@ int fsl_rio_setup(struct platform_device *dev)
> RIO_ATMU_REGS_PORT2_OFFSET));
>
> priv->maint_atmu_regs = priv->atmu_regs + 1;
> + priv->inb_atmu_regs = (struct rio_inb_atmu_regs __iomem *)
> + (priv->regs_win +
> + ((i == 0) ? RIO_INB_ATMU_REGS_PORT1_OFFSET :
> + RIO_INB_ATMU_REGS_PORT2_OFFSET));
> +
>
> /* Set to receive any dist ID for serial RapidIO controller. */
> if (port->phy_type == RIO_PHY_SERIAL)
> @@ -620,6 +723,7 @@ int fsl_rio_setup(struct platform_device *dev)
> rio_law_start = range_start;
>
> fsl_rio_setup_rmu(port, rmu_np[i]);
> + fsl_rio_inbound_mem_init(priv);
>
> dbell->mport[i] = port;
>
> diff --git a/arch/powerpc/sysdev/fsl_rio.h b/arch/powerpc/sysdev/fsl_rio.h
> index ae8e274..d53407a 100644
> --- a/arch/powerpc/sysdev/fsl_rio.h
> +++ b/arch/powerpc/sysdev/fsl_rio.h
> @@ -50,9 +50,12 @@
> #define RIO_S_DBELL_REGS_OFFSET 0x13400
> #define RIO_S_PW_REGS_OFFSET 0x134e0
> #define RIO_ATMU_REGS_DBELL_OFFSET 0x10C40
> +#define RIO_INB_ATMU_REGS_PORT1_OFFSET 0x10d60
> +#define RIO_INB_ATMU_REGS_PORT2_OFFSET 0x10f60
>
> #define MAX_MSG_UNIT_NUM 2
> #define MAX_PORT_NUM 4
> +#define RIO_INB_ATMU_COUNT 4
>
> struct rio_atmu_regs {
> u32 rowtar;
> @@ -63,6 +66,15 @@ struct rio_atmu_regs {
> u32 pad2[3];
> };
>
> +struct rio_inb_atmu_regs {
> + u32 riwtar;
> + u32 pad1;
> + u32 riwbar;
> + u32 pad2;
> + u32 riwar;
> + u32 pad3[3];
> +};
> +
> struct rio_dbell_ring {
> void *virt;
> dma_addr_t phys;
> @@ -99,6 +111,7 @@ struct rio_priv {
> void __iomem *regs_win;
> struct rio_atmu_regs __iomem *atmu_regs;
> struct rio_atmu_regs __iomem *maint_atmu_regs;
> + struct rio_inb_atmu_regs __iomem *inb_atmu_regs;
> void __iomem *maint_win;
> void *rmm_handle; /* RapidIO message manager(unit) Handle */
> };
More information about the Linuxppc-dev
mailing list