powerpc/fsl-rio: add support for mapping inbound windows
Add support for mapping and unmapping of inbound rapidio windows. This allows for drivers to open up a part of local memory on the rapidio network. Also applications can use this and tranfer blocks of data over the network. Signed-off-by: Martijn de Gouw <martijn.de.gouw@prodrive-technologies.com> [scottwood@freescale.com: updated commit message based on review] Signed-off-by: Scott Wood <scottwood@freescale.com>
This commit is contained in:
parent
e327fff47b
commit
e6a546fd03
@ -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;
|
||||
|
||||
|
@ -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 */
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user