Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1759475AbYCDIeq (ORCPT ); Tue, 4 Mar 2008 03:34:46 -0500 Received: (majordomo@vger.kernel.org) by vger.kernel.org id S1755325AbYCDIa6 (ORCPT ); Tue, 4 Mar 2008 03:30:58 -0500 Received: from de01egw01.freescale.net ([192.88.165.102]:46129 "EHLO de01egw01.freescale.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754652AbYCDIaz (ORCPT ); Tue, 4 Mar 2008 03:30:55 -0500 From: Zhang Wei To: mporter@kernel.crashing.org, galak@kernel.crashing.org Cc: linux-kernel@vger.kernel.org, linuxppc-dev@ozlabs.org, Zhang Wei Subject: [PATCH 13/17] Add FSL RapidIO controller memory ops functions. Date: Wed, 5 Mar 2008 00:29:58 +0800 Message-Id: <1204648202-5495-13-git-send-email-wei.zhang@freescale.com> X-Mailer: git-send-email 1.5.4 In-Reply-To: <1204648202-5495-12-git-send-email-wei.zhang@freescale.com> References: <1204648202-5495-1-git-send-email-wei.zhang@freescale.com> <1204648202-5495-2-git-send-email-wei.zhang@freescale.com> <1204648202-5495-3-git-send-email-wei.zhang@freescale.com> <1204648202-5495-4-git-send-email-wei.zhang@freescale.com> <1204648202-5495-5-git-send-email-wei.zhang@freescale.com> <1204648202-5495-6-git-send-email-wei.zhang@freescale.com> <1204648202-5495-7-git-send-email-wei.zhang@freescale.com> <1204648202-5495-8-git-send-email-wei.zhang@freescale.com> <1204648202-5495-9-git-send-email-wei.zhang@freescale.com> <1204648202-5495-10-git-send-email-wei.zhang@freescale.com> <1204648202-5495-11-git-send-email-wei.zhang@freescale.com> <1204648202-5495-12-git-send-email-wei.zhang@freescale.com> X-OriginalArrivalTime: 04 Mar 2008 08:30:36.0766 (UTC) FILETIME=[056C7FE0:01C87DD2] Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 8204 Lines: 265 Add FSL RapidIO controller (MPC85xx, MPC86xx) memory operation functions, which include map inbound/outbound window and unmap incound/outbound window. Signed-off-by: Zhang Wei --- arch/powerpc/sysdev/fsl_rio.c | 202 +++++++++++++++++++++++++++++++++++++++++ 1 files changed, 202 insertions(+), 0 deletions(-) diff --git a/arch/powerpc/sysdev/fsl_rio.c b/arch/powerpc/sysdev/fsl_rio.c index d793084..c260ae5 100644 --- a/arch/powerpc/sysdev/fsl_rio.c +++ b/arch/powerpc/sysdev/fsl_rio.c @@ -30,6 +30,8 @@ #define IRQ_RIO_TX(m) (((struct rio_priv *)(m->priv))->txirq) #define IRQ_RIO_RX(m) (((struct rio_priv *)(m->priv))->rxirq) +#define IS_64BIT_RES ((sizeof(resource_size_t) == 8) ? 1 : 0) + #define RIO_ATMU_REGS_OFFSET 0x10c00 #define RIO_P_MSG_REGS_OFFSET 0x11000 #define RIO_S_MSG_REGS_OFFSET 0x13000 @@ -39,6 +41,15 @@ #define RIO_ISR_AACR_AA 0x1 /* Accept All ID */ #define RIO_MAINT_WIN_SIZE 0x400000 #define RIO_DBELL_WIN_SIZE 0x1000 +#define RIO_MAX_INB_ATMU 4 +#define RIO_MAX_OUTB_ATMU 8 +#define RIO_INB_ATMU_REGS_OFFSET 0x10de0 +#define RIO_ATMU_EN_MASK 0x80000000 + +#define RIO_NREAD 0x4 +#define RIO_NWRITE 0x4 +#define RIO_NWRITE_R 0x5 +#define RIO_NREAD_R 0x5 #define RIO_MSG_OMR_MUI 0x00000002 #define RIO_MSG_OSR_TE 0x00000080 @@ -82,6 +93,15 @@ struct rio_atmu_regs { u32 pad3[3]; }; +struct rio_inb_atmu_regs { + u32 riwtar; + u32 pad1; + u32 riwbar; + u32 pad2; + u32 riwar; + u32 pad3[3]; +}; + struct rio_msg_regs { u32 omr; u32 osr; @@ -334,6 +354,180 @@ fsl_rio_config_write(struct rio_mport *mport, int index, u16 destid, } /** + * fsl_rio_map_inb_mem -- Mapping inbound memory region. + * @lstart: Local memory space start address. + * @rstart: RapidIO space start address. + * @size: The mapping region size. + * @flags: Flags for mapping. 0 for using default flags. + * + * Return: 0 -- Success. + * + * This function will create the inbound mapping + * from rstart to lstart. + */ +static int fsl_rio_map_inb_mem(struct rio_mport *mport, resource_size_t lstart, + resource_size_t rstart, resource_size_t size, u32 flags) +{ + int i; + struct rio_priv *priv = mport->priv; + struct rio_inb_atmu_regs __iomem *inbatmu = (struct rio_inb_atmu_regs *) + (priv->regs_win + RIO_INB_ATMU_REGS_OFFSET) - 1; + int size_ffs; + resource_size_t align; + + if (flags == 0) + flags = (RIO_NREAD_R << 4) | RIO_NWRITE_R; + + align = (size < 0x1000) ? 0x1000 : 1 << (__ilog2(size - 1) + 1); + + /* Align the size */ + if ((lstart + size) > (_ALIGN_DOWN(lstart, align) + align)) { + size_ffs = __ffs(_ALIGN_DOWN(lstart + size - 1, align)); + size = 1 << (size_ffs + (((_ALIGN_DOWN(lstart, 1 << size_ffs) + + (1 << size_ffs)) < (lstart + size)) ? 1 : 0)); + } else + size = align; + + if ((lstart & (size - 1)) != (rstart & (size - 1))) { + dev_err(mport->dev, "The local address 0x%x can not be aligned " + "to the same size 0x%x with the RapidIO space " + "address 0x%x!\n", lstart, size, rstart); + return -EINVAL; + } + + /* Search for free inbound ATMU */ + for (i = 1; + (i <= RIO_MAX_INB_ATMU) && (inbatmu->riwar & RIO_ATMU_EN_MASK); + i++, inbatmu--) + ; + + if (i > RIO_MAX_INB_ATMU) { + dev_err(mport->dev, "No free inbound ATMU!\n"); + return -EBUSY; + } + out_be32(&inbatmu->riwtar, ((IS_64BIT_RES ? (lstart >> 32) + & 0xf : 0) << 20) | ((lstart >> 12) & 0xfffff)); + out_be32(&inbatmu->riwbar, ((IS_64BIT_RES ? (rstart >> 32) + & 0x3 : 0) << 20) | ((rstart >> 12) & 0xfffff)); + out_be32(&inbatmu->riwar, 0x80000000 | (0xf << 20) + | ((flags & 0xff) << 12) + | (__ilog2(size) - 1)); + return 0; +} + +/** + * fsl_rio_map_outb_mem -- Mapping outbound memory region. + * @lstart: Local memory space start address. + * @rstart: RapidIO space start address. + * @size: The mapping region size. + * @tid: The target RapidIO device id. + * @flags: Flags for mapping. 0 for using default flags. + * + * Return: 0 -- Success. + * + * This function will create the outbound mapping + * from lstart to rstart. + */ +static int fsl_rio_map_outb_mem(struct rio_mport *mport, resource_size_t lstart, + resource_size_t rstart, resource_size_t size, + u16 tid, u32 flags) +{ + int i; + struct rio_priv *priv = mport->priv; + struct rio_atmu_regs __iomem *outbatmu = (struct rio_atmu_regs *) + (priv->regs_win + RIO_ATMU_REGS_OFFSET) + 1; + int size_ffs; + resource_size_t align; + + if (flags == 0) + flags = (RIO_NREAD << 4) | RIO_NWRITE_R; + + align = (size < 0x1000) ? 0x1000 : 1 << (__ilog2(size - 1) + 1); + + /* Align the size */ + if ((lstart + size) > (_ALIGN_DOWN(lstart, align) + align)) { + size_ffs = __ffs(_ALIGN_DOWN(lstart + size - 1, align)); + size = 1 << (size_ffs + (((_ALIGN_DOWN(lstart, 1 << size_ffs) + + (1 << size_ffs)) < (lstart + size)) ? 1 : 0)); + } else + size = align; + + if ((lstart & (size - 1)) != (rstart & (size - 1))) { + dev_err(mport->dev, "The local address 0x%x can not be aligned " + "to the same size 0x%x with the RapidIO space address " + "0x%x!\n", lstart, size, rstart); + return -EINVAL; + } + + /* Search for free outbound ATMU */ + for (i = 1; + (i <= RIO_MAX_OUTB_ATMU) && (outbatmu->rowar & RIO_ATMU_EN_MASK); + i++, outbatmu++) + ; + + if (i > RIO_MAX_OUTB_ATMU) { + dev_err(mport->dev, "No free outbound ATMU!\n"); + return -EBUSY; + } + out_be32(&outbatmu->rowtar, ((tid & 0x3ff) << 22) + | ((IS_64BIT_RES ? (rstart >> 32) & 0x3 : 0) << 20) + | ((rstart >> 12) & 0xfffff)); + if (mport->phy_type == RIO_PHY_SERIAL) + out_be32(&outbatmu->rowtear, tid >> 10); + out_be32(&outbatmu->rowbar, ((IS_64BIT_RES ? + (lstart >> 32) & 0xf : 0) << 20) + | ((lstart >> 12) & 0xfffff)); + out_be32(&outbatmu->rowar, 0x80000000 + | ((flags & 0xff) << 12) + | (__ilog2(size) - 1)); + return 0; +} + +/** + * fsl_rio_unmap_inb_mem -- Unmapping inbound memory region. + * @lstart: Local memory space start address. + */ +static void fsl_rio_unmap_inb_mem(struct rio_mport *mport, resource_size_t lstart) +{ + int i; + struct rio_priv *priv = mport->priv; + struct rio_inb_atmu_regs __iomem *inbatmu = (struct rio_inb_atmu_regs *) + (priv->regs_win + RIO_INB_ATMU_REGS_OFFSET) - 1; + + /* Search for inbound ATMU */ + for (i = 1; i <= RIO_MAX_INB_ATMU ; i++, inbatmu--) { + u32 tar = ((IS_64BIT_RES ? (lstart >> 32) & 0xf : 0) << 20) + | ((lstart >> 12) & 0xfffff); + if (inbatmu->riwtar == tar) { + out_be32(&inbatmu->riwar, ~(RIO_ATMU_EN_MASK)); + return; + } + } +} + +/** + * fsl_rio_unmap_inb_mem -- Unmapping outbound memory region. + * @lstart: Local memory space start address. + */ +static void fsl_rio_unmap_outb_mem(struct rio_mport *mport, resource_size_t lstart) +{ + int i; + struct rio_priv *priv = mport->priv; + struct rio_atmu_regs __iomem *outbatmu = (struct rio_atmu_regs *) + (priv->regs_win + RIO_ATMU_REGS_OFFSET) + 1; + + /* Search for outbound ATMU */ + for (i = 1; i <= RIO_MAX_OUTB_ATMU ; i++, outbatmu++) { + u32 bar = ((IS_64BIT_RES ? (lstart >> 32) & 0xf : 0) << 20) + | ((lstart >> 12) & 0xfffff); + if (outbatmu->rowbar == bar) { + out_be32(&outbatmu->rowar, ~(RIO_ATMU_EN_MASK)); + return; + } + } +} + +/** * rio_hw_add_outb_message - Add message to the MPC85xx outbound message queue * @mport: Master port with outbound message queue * @rdev: Target of outbound message @@ -956,6 +1150,13 @@ static int fsl_rio_get_cmdline(char *s) __setup("riohdid=", fsl_rio_get_cmdline); +static struct rio_mem_ops fsl_mem_ops = { + .map_inb = fsl_rio_map_inb_mem, + .map_outb = fsl_rio_map_outb_mem, + .unmap_inb = fsl_rio_unmap_inb_mem, + .unmap_outb = fsl_rio_unmap_outb_mem, +}; + static inline void fsl_rio_info(struct device *dev, u32 ccsr) { const char *str; @@ -1099,6 +1300,7 @@ int fsl_rio_setup(struct of_device *dev) strcpy(port->name, "RIO0 mport"); port->ops = ops; + port->mops = &fsl_mem_ops; port->host_deviceid = fsl_rio_get_hdid(port->id); port->priv = priv; -- 1.5.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/