staging: fsl-mc: split mc-io definitions into a separate file
An mc-io is a software abstraction of a dpmcp object (an MC portal). Routines to create/initialize/reset this portal abstraction were split between the allocator and mc-sys.c (MC command interface). Move mc-io/portal related definitions into one source file. Signed-off-by: Stuart Yoder <stuart.yoder@nxp.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
Родитель
693c5a9d43
Коммит
7f59f4c71d
|
@ -9,6 +9,7 @@ obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
|
|||
|
||||
mc-bus-driver-objs := fsl-mc-bus.o \
|
||||
mc-sys.o \
|
||||
mc-io.o \
|
||||
dprc.o \
|
||||
dpmng.o \
|
||||
dprc-driver.o \
|
||||
|
|
|
@ -13,8 +13,6 @@
|
|||
#include <linux/module.h>
|
||||
#include "../include/dpbp-cmd.h"
|
||||
#include "../include/dpcon-cmd.h"
|
||||
#include "dpmcp-cmd.h"
|
||||
#include "dpmcp.h"
|
||||
#include "fsl-mc-private.h"
|
||||
#include <linux/msi.h>
|
||||
|
||||
|
@ -257,144 +255,6 @@ out_unlock:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_mc_resource_free);
|
||||
|
||||
/**
|
||||
* fsl_mc_portal_allocate - Allocates an MC portal
|
||||
*
|
||||
* @mc_dev: MC device for which the MC portal is to be allocated
|
||||
* @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated
|
||||
* MC portal.
|
||||
* @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object
|
||||
* that wraps the allocated MC portal is to be returned
|
||||
*
|
||||
* This function allocates an MC portal from the device's parent DPRC,
|
||||
* from the corresponding MC bus' pool of MC portals and wraps
|
||||
* it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the
|
||||
* portal is allocated from its own MC bus.
|
||||
*/
|
||||
int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
|
||||
u16 mc_io_flags,
|
||||
struct fsl_mc_io **new_mc_io)
|
||||
{
|
||||
struct fsl_mc_device *mc_bus_dev;
|
||||
struct fsl_mc_bus *mc_bus;
|
||||
phys_addr_t mc_portal_phys_addr;
|
||||
size_t mc_portal_size;
|
||||
struct fsl_mc_device *dpmcp_dev;
|
||||
int error = -EINVAL;
|
||||
struct fsl_mc_resource *resource = NULL;
|
||||
struct fsl_mc_io *mc_io = NULL;
|
||||
|
||||
if (mc_dev->flags & FSL_MC_IS_DPRC) {
|
||||
mc_bus_dev = mc_dev;
|
||||
} else {
|
||||
if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
|
||||
return error;
|
||||
|
||||
mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
|
||||
}
|
||||
|
||||
mc_bus = to_fsl_mc_bus(mc_bus_dev);
|
||||
*new_mc_io = NULL;
|
||||
error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
error = -EINVAL;
|
||||
dpmcp_dev = resource->data;
|
||||
if (WARN_ON(!dpmcp_dev))
|
||||
goto error_cleanup_resource;
|
||||
|
||||
if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
|
||||
(dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
|
||||
dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) {
|
||||
dev_err(&dpmcp_dev->dev,
|
||||
"ERROR: Version %d.%d of DPMCP not supported.\n",
|
||||
dpmcp_dev->obj_desc.ver_major,
|
||||
dpmcp_dev->obj_desc.ver_minor);
|
||||
error = -ENOTSUPP;
|
||||
goto error_cleanup_resource;
|
||||
}
|
||||
|
||||
if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0))
|
||||
goto error_cleanup_resource;
|
||||
|
||||
mc_portal_phys_addr = dpmcp_dev->regions[0].start;
|
||||
mc_portal_size = dpmcp_dev->regions[0].end -
|
||||
dpmcp_dev->regions[0].start + 1;
|
||||
|
||||
if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size))
|
||||
goto error_cleanup_resource;
|
||||
|
||||
error = fsl_create_mc_io(&mc_bus_dev->dev,
|
||||
mc_portal_phys_addr,
|
||||
mc_portal_size, dpmcp_dev,
|
||||
mc_io_flags, &mc_io);
|
||||
if (error < 0)
|
||||
goto error_cleanup_resource;
|
||||
|
||||
*new_mc_io = mc_io;
|
||||
return 0;
|
||||
|
||||
error_cleanup_resource:
|
||||
fsl_mc_resource_free(resource);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
|
||||
|
||||
/**
|
||||
* fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
|
||||
* of a given MC bus
|
||||
*
|
||||
* @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
|
||||
*/
|
||||
void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
|
||||
{
|
||||
struct fsl_mc_device *dpmcp_dev;
|
||||
struct fsl_mc_resource *resource;
|
||||
|
||||
/*
|
||||
* Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed
|
||||
* to have a DPMCP object associated with.
|
||||
*/
|
||||
dpmcp_dev = mc_io->dpmcp_dev;
|
||||
if (WARN_ON(!dpmcp_dev))
|
||||
return;
|
||||
|
||||
resource = dpmcp_dev->resource;
|
||||
if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP))
|
||||
return;
|
||||
|
||||
if (WARN_ON(resource->data != dpmcp_dev))
|
||||
return;
|
||||
|
||||
fsl_destroy_mc_io(mc_io);
|
||||
fsl_mc_resource_free(resource);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
|
||||
|
||||
/**
|
||||
* fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
|
||||
*
|
||||
* @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
|
||||
*/
|
||||
int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
|
||||
{
|
||||
int error;
|
||||
struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
|
||||
|
||||
if (WARN_ON(!dpmcp_dev))
|
||||
return -EINVAL;
|
||||
|
||||
error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
|
||||
if (error < 0) {
|
||||
dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
|
||||
|
||||
/**
|
||||
* fsl_mc_object_allocate - Allocates a MC object device of the given
|
||||
* pool type from a given MC bus
|
||||
|
|
|
@ -41,4 +41,12 @@ int __init its_fsl_mc_msi_init(void);
|
|||
|
||||
void its_fsl_mc_msi_cleanup(void);
|
||||
|
||||
int __must_check fsl_create_mc_io(struct device *dev,
|
||||
phys_addr_t mc_portal_phys_addr,
|
||||
u32 mc_portal_size,
|
||||
struct fsl_mc_device *dpmcp_dev,
|
||||
u32 flags, struct fsl_mc_io **new_mc_io);
|
||||
|
||||
void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
|
||||
|
||||
#endif /* _FSL_MC_PRIVATE_H_ */
|
||||
|
|
|
@ -0,0 +1,318 @@
|
|||
/* Copyright 2013-2016 Freescale Semiconductor Inc.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* * Neither the name of the above-listed copyright holders nor the
|
||||
* names of any contributors may be used to endorse or promote products
|
||||
* derived from this software without specific prior written permission.
|
||||
*
|
||||
*
|
||||
* ALTERNATIVELY, this software may be distributed under the terms of the
|
||||
* GNU General Public License ("GPL") as published by the Free Software
|
||||
* Foundation, either version 2 of that License or (at your option) any
|
||||
* later version.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/mc-bus.h"
|
||||
#include "../include/mc-sys.h"
|
||||
#include "fsl-mc-private.h"
|
||||
#include "dpmcp.h"
|
||||
#include "dpmcp-cmd.h"
|
||||
|
||||
static int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
|
||||
struct fsl_mc_device *dpmcp_dev)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (WARN_ON(!dpmcp_dev))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(mc_io->dpmcp_dev))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(dpmcp_dev->mc_io))
|
||||
return -EINVAL;
|
||||
|
||||
error = dpmcp_open(mc_io,
|
||||
0,
|
||||
dpmcp_dev->obj_desc.id,
|
||||
&dpmcp_dev->mc_handle);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
mc_io->dpmcp_dev = dpmcp_dev;
|
||||
dpmcp_dev->mc_io = mc_io;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
|
||||
{
|
||||
int error;
|
||||
struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
|
||||
|
||||
if (WARN_ON(!dpmcp_dev))
|
||||
return;
|
||||
|
||||
if (WARN_ON(dpmcp_dev->mc_io != mc_io))
|
||||
return;
|
||||
|
||||
error = dpmcp_close(mc_io,
|
||||
0,
|
||||
dpmcp_dev->mc_handle);
|
||||
if (error < 0) {
|
||||
dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n",
|
||||
error);
|
||||
}
|
||||
|
||||
mc_io->dpmcp_dev = NULL;
|
||||
dpmcp_dev->mc_io = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an MC I/O object
|
||||
*
|
||||
* @dev: device to be associated with the MC I/O object
|
||||
* @mc_portal_phys_addr: physical address of the MC portal to use
|
||||
* @mc_portal_size: size in bytes of the MC portal
|
||||
* @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O
|
||||
* object or NULL if none.
|
||||
* @flags: flags for the new MC I/O object
|
||||
* @new_mc_io: Area to return pointer to newly created MC I/O object
|
||||
*
|
||||
* Returns '0' on Success; Error code otherwise.
|
||||
*/
|
||||
int __must_check fsl_create_mc_io(struct device *dev,
|
||||
phys_addr_t mc_portal_phys_addr,
|
||||
u32 mc_portal_size,
|
||||
struct fsl_mc_device *dpmcp_dev,
|
||||
u32 flags, struct fsl_mc_io **new_mc_io)
|
||||
{
|
||||
int error;
|
||||
struct fsl_mc_io *mc_io;
|
||||
void __iomem *mc_portal_virt_addr;
|
||||
struct resource *res;
|
||||
|
||||
mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
|
||||
if (!mc_io)
|
||||
return -ENOMEM;
|
||||
|
||||
mc_io->dev = dev;
|
||||
mc_io->flags = flags;
|
||||
mc_io->portal_phys_addr = mc_portal_phys_addr;
|
||||
mc_io->portal_size = mc_portal_size;
|
||||
if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
|
||||
spin_lock_init(&mc_io->spinlock);
|
||||
else
|
||||
mutex_init(&mc_io->mutex);
|
||||
|
||||
res = devm_request_mem_region(dev,
|
||||
mc_portal_phys_addr,
|
||||
mc_portal_size,
|
||||
"mc_portal");
|
||||
if (!res) {
|
||||
dev_err(dev,
|
||||
"devm_request_mem_region failed for MC portal %#llx\n",
|
||||
mc_portal_phys_addr);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
mc_portal_virt_addr = devm_ioremap_nocache(dev,
|
||||
mc_portal_phys_addr,
|
||||
mc_portal_size);
|
||||
if (!mc_portal_virt_addr) {
|
||||
dev_err(dev,
|
||||
"devm_ioremap_nocache failed for MC portal %#llx\n",
|
||||
mc_portal_phys_addr);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
mc_io->portal_virt_addr = mc_portal_virt_addr;
|
||||
if (dpmcp_dev) {
|
||||
error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev);
|
||||
if (error < 0)
|
||||
goto error_destroy_mc_io;
|
||||
}
|
||||
|
||||
*new_mc_io = mc_io;
|
||||
return 0;
|
||||
|
||||
error_destroy_mc_io:
|
||||
fsl_destroy_mc_io(mc_io);
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroys an MC I/O object
|
||||
*
|
||||
* @mc_io: MC I/O object to destroy
|
||||
*/
|
||||
void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
|
||||
{
|
||||
struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
|
||||
|
||||
if (dpmcp_dev)
|
||||
fsl_mc_io_unset_dpmcp(mc_io);
|
||||
|
||||
devm_iounmap(mc_io->dev, mc_io->portal_virt_addr);
|
||||
devm_release_mem_region(mc_io->dev,
|
||||
mc_io->portal_phys_addr,
|
||||
mc_io->portal_size);
|
||||
|
||||
mc_io->portal_virt_addr = NULL;
|
||||
devm_kfree(mc_io->dev, mc_io);
|
||||
}
|
||||
|
||||
/**
|
||||
* fsl_mc_portal_allocate - Allocates an MC portal
|
||||
*
|
||||
* @mc_dev: MC device for which the MC portal is to be allocated
|
||||
* @mc_io_flags: Flags for the fsl_mc_io object that wraps the allocated
|
||||
* MC portal.
|
||||
* @new_mc_io: Pointer to area where the pointer to the fsl_mc_io object
|
||||
* that wraps the allocated MC portal is to be returned
|
||||
*
|
||||
* This function allocates an MC portal from the device's parent DPRC,
|
||||
* from the corresponding MC bus' pool of MC portals and wraps
|
||||
* it in a new fsl_mc_io object. If 'mc_dev' is a DPRC itself, the
|
||||
* portal is allocated from its own MC bus.
|
||||
*/
|
||||
int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
|
||||
u16 mc_io_flags,
|
||||
struct fsl_mc_io **new_mc_io)
|
||||
{
|
||||
struct fsl_mc_device *mc_bus_dev;
|
||||
struct fsl_mc_bus *mc_bus;
|
||||
phys_addr_t mc_portal_phys_addr;
|
||||
size_t mc_portal_size;
|
||||
struct fsl_mc_device *dpmcp_dev;
|
||||
int error = -EINVAL;
|
||||
struct fsl_mc_resource *resource = NULL;
|
||||
struct fsl_mc_io *mc_io = NULL;
|
||||
|
||||
if (mc_dev->flags & FSL_MC_IS_DPRC) {
|
||||
mc_bus_dev = mc_dev;
|
||||
} else {
|
||||
if (WARN_ON(!dev_is_fsl_mc(mc_dev->dev.parent)))
|
||||
return error;
|
||||
|
||||
mc_bus_dev = to_fsl_mc_device(mc_dev->dev.parent);
|
||||
}
|
||||
|
||||
mc_bus = to_fsl_mc_bus(mc_bus_dev);
|
||||
*new_mc_io = NULL;
|
||||
error = fsl_mc_resource_allocate(mc_bus, FSL_MC_POOL_DPMCP, &resource);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
error = -EINVAL;
|
||||
dpmcp_dev = resource->data;
|
||||
if (WARN_ON(!dpmcp_dev))
|
||||
goto error_cleanup_resource;
|
||||
|
||||
if (dpmcp_dev->obj_desc.ver_major < DPMCP_MIN_VER_MAJOR ||
|
||||
(dpmcp_dev->obj_desc.ver_major == DPMCP_MIN_VER_MAJOR &&
|
||||
dpmcp_dev->obj_desc.ver_minor < DPMCP_MIN_VER_MINOR)) {
|
||||
dev_err(&dpmcp_dev->dev,
|
||||
"ERROR: Version %d.%d of DPMCP not supported.\n",
|
||||
dpmcp_dev->obj_desc.ver_major,
|
||||
dpmcp_dev->obj_desc.ver_minor);
|
||||
error = -ENOTSUPP;
|
||||
goto error_cleanup_resource;
|
||||
}
|
||||
|
||||
if (WARN_ON(dpmcp_dev->obj_desc.region_count == 0))
|
||||
goto error_cleanup_resource;
|
||||
|
||||
mc_portal_phys_addr = dpmcp_dev->regions[0].start;
|
||||
mc_portal_size = dpmcp_dev->regions[0].end -
|
||||
dpmcp_dev->regions[0].start + 1;
|
||||
|
||||
if (WARN_ON(mc_portal_size != mc_bus_dev->mc_io->portal_size))
|
||||
goto error_cleanup_resource;
|
||||
|
||||
error = fsl_create_mc_io(&mc_bus_dev->dev,
|
||||
mc_portal_phys_addr,
|
||||
mc_portal_size, dpmcp_dev,
|
||||
mc_io_flags, &mc_io);
|
||||
if (error < 0)
|
||||
goto error_cleanup_resource;
|
||||
|
||||
*new_mc_io = mc_io;
|
||||
return 0;
|
||||
|
||||
error_cleanup_resource:
|
||||
fsl_mc_resource_free(resource);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_mc_portal_allocate);
|
||||
|
||||
/**
|
||||
* fsl_mc_portal_free - Returns an MC portal to the pool of free MC portals
|
||||
* of a given MC bus
|
||||
*
|
||||
* @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
|
||||
*/
|
||||
void fsl_mc_portal_free(struct fsl_mc_io *mc_io)
|
||||
{
|
||||
struct fsl_mc_device *dpmcp_dev;
|
||||
struct fsl_mc_resource *resource;
|
||||
|
||||
/*
|
||||
* Every mc_io obtained by calling fsl_mc_portal_allocate() is supposed
|
||||
* to have a DPMCP object associated with.
|
||||
*/
|
||||
dpmcp_dev = mc_io->dpmcp_dev;
|
||||
if (WARN_ON(!dpmcp_dev))
|
||||
return;
|
||||
|
||||
resource = dpmcp_dev->resource;
|
||||
if (WARN_ON(!resource || resource->type != FSL_MC_POOL_DPMCP))
|
||||
return;
|
||||
|
||||
if (WARN_ON(resource->data != dpmcp_dev))
|
||||
return;
|
||||
|
||||
fsl_destroy_mc_io(mc_io);
|
||||
fsl_mc_resource_free(resource);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_mc_portal_free);
|
||||
|
||||
/**
|
||||
* fsl_mc_portal_reset - Resets the dpmcp object for a given fsl_mc_io object
|
||||
*
|
||||
* @mc_io: Pointer to the fsl_mc_io object that wraps the MC portal to free
|
||||
*/
|
||||
int fsl_mc_portal_reset(struct fsl_mc_io *mc_io)
|
||||
{
|
||||
int error;
|
||||
struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
|
||||
|
||||
if (WARN_ON(!dpmcp_dev))
|
||||
return -EINVAL;
|
||||
|
||||
error = dpmcp_reset(mc_io, 0, dpmcp_dev->mc_handle);
|
||||
if (error < 0) {
|
||||
dev_err(&dpmcp_dev->dev, "dpmcp_reset() failed: %d\n", error);
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_mc_portal_reset);
|
|
@ -68,153 +68,6 @@ static u16 mc_cmd_hdr_read_cmdid(struct mc_command *cmd)
|
|||
return (cmd_id & MC_CMD_HDR_CMDID_MASK) >> MC_CMD_HDR_CMDID_SHIFT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an MC I/O object
|
||||
*
|
||||
* @dev: device to be associated with the MC I/O object
|
||||
* @mc_portal_phys_addr: physical address of the MC portal to use
|
||||
* @mc_portal_size: size in bytes of the MC portal
|
||||
* @dpmcp-dev: Pointer to the DPMCP object associated with this MC I/O
|
||||
* object or NULL if none.
|
||||
* @flags: flags for the new MC I/O object
|
||||
* @new_mc_io: Area to return pointer to newly created MC I/O object
|
||||
*
|
||||
* Returns '0' on Success; Error code otherwise.
|
||||
*/
|
||||
int __must_check fsl_create_mc_io(struct device *dev,
|
||||
phys_addr_t mc_portal_phys_addr,
|
||||
u32 mc_portal_size,
|
||||
struct fsl_mc_device *dpmcp_dev,
|
||||
u32 flags, struct fsl_mc_io **new_mc_io)
|
||||
{
|
||||
int error;
|
||||
struct fsl_mc_io *mc_io;
|
||||
void __iomem *mc_portal_virt_addr;
|
||||
struct resource *res;
|
||||
|
||||
mc_io = devm_kzalloc(dev, sizeof(*mc_io), GFP_KERNEL);
|
||||
if (!mc_io)
|
||||
return -ENOMEM;
|
||||
|
||||
mc_io->dev = dev;
|
||||
mc_io->flags = flags;
|
||||
mc_io->portal_phys_addr = mc_portal_phys_addr;
|
||||
mc_io->portal_size = mc_portal_size;
|
||||
if (flags & FSL_MC_IO_ATOMIC_CONTEXT_PORTAL)
|
||||
spin_lock_init(&mc_io->spinlock);
|
||||
else
|
||||
mutex_init(&mc_io->mutex);
|
||||
|
||||
res = devm_request_mem_region(dev,
|
||||
mc_portal_phys_addr,
|
||||
mc_portal_size,
|
||||
"mc_portal");
|
||||
if (!res) {
|
||||
dev_err(dev,
|
||||
"devm_request_mem_region failed for MC portal %#llx\n",
|
||||
mc_portal_phys_addr);
|
||||
return -EBUSY;
|
||||
}
|
||||
|
||||
mc_portal_virt_addr = devm_ioremap_nocache(dev,
|
||||
mc_portal_phys_addr,
|
||||
mc_portal_size);
|
||||
if (!mc_portal_virt_addr) {
|
||||
dev_err(dev,
|
||||
"devm_ioremap_nocache failed for MC portal %#llx\n",
|
||||
mc_portal_phys_addr);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
mc_io->portal_virt_addr = mc_portal_virt_addr;
|
||||
if (dpmcp_dev) {
|
||||
error = fsl_mc_io_set_dpmcp(mc_io, dpmcp_dev);
|
||||
if (error < 0)
|
||||
goto error_destroy_mc_io;
|
||||
}
|
||||
|
||||
*new_mc_io = mc_io;
|
||||
return 0;
|
||||
|
||||
error_destroy_mc_io:
|
||||
fsl_destroy_mc_io(mc_io);
|
||||
return error;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_create_mc_io);
|
||||
|
||||
/**
|
||||
* Destroys an MC I/O object
|
||||
*
|
||||
* @mc_io: MC I/O object to destroy
|
||||
*/
|
||||
void fsl_destroy_mc_io(struct fsl_mc_io *mc_io)
|
||||
{
|
||||
struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
|
||||
|
||||
if (dpmcp_dev)
|
||||
fsl_mc_io_unset_dpmcp(mc_io);
|
||||
|
||||
devm_iounmap(mc_io->dev, mc_io->portal_virt_addr);
|
||||
devm_release_mem_region(mc_io->dev,
|
||||
mc_io->portal_phys_addr,
|
||||
mc_io->portal_size);
|
||||
|
||||
mc_io->portal_virt_addr = NULL;
|
||||
devm_kfree(mc_io->dev, mc_io);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_destroy_mc_io);
|
||||
|
||||
int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
|
||||
struct fsl_mc_device *dpmcp_dev)
|
||||
{
|
||||
int error;
|
||||
|
||||
if (WARN_ON(!dpmcp_dev))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(mc_io->dpmcp_dev))
|
||||
return -EINVAL;
|
||||
|
||||
if (WARN_ON(dpmcp_dev->mc_io))
|
||||
return -EINVAL;
|
||||
|
||||
error = dpmcp_open(mc_io,
|
||||
0,
|
||||
dpmcp_dev->obj_desc.id,
|
||||
&dpmcp_dev->mc_handle);
|
||||
if (error < 0)
|
||||
return error;
|
||||
|
||||
mc_io->dpmcp_dev = dpmcp_dev;
|
||||
dpmcp_dev->mc_io = mc_io;
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_mc_io_set_dpmcp);
|
||||
|
||||
void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io)
|
||||
{
|
||||
int error;
|
||||
struct fsl_mc_device *dpmcp_dev = mc_io->dpmcp_dev;
|
||||
|
||||
if (WARN_ON(!dpmcp_dev))
|
||||
return;
|
||||
|
||||
if (WARN_ON(dpmcp_dev->mc_io != mc_io))
|
||||
return;
|
||||
|
||||
error = dpmcp_close(mc_io,
|
||||
0,
|
||||
dpmcp_dev->mc_handle);
|
||||
if (error < 0) {
|
||||
dev_err(&dpmcp_dev->dev, "dpmcp_close() failed: %d\n",
|
||||
error);
|
||||
}
|
||||
|
||||
mc_io->dpmcp_dev = NULL;
|
||||
dpmcp_dev->mc_io = NULL;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(fsl_mc_io_unset_dpmcp);
|
||||
|
||||
static int mc_status_to_error(enum mc_cmd_status status)
|
||||
{
|
||||
static const int mc_status_to_error_map[] = {
|
||||
|
|
|
@ -95,19 +95,6 @@ struct fsl_mc_io {
|
|||
};
|
||||
};
|
||||
|
||||
int __must_check fsl_create_mc_io(struct device *dev,
|
||||
phys_addr_t mc_portal_phys_addr,
|
||||
u32 mc_portal_size,
|
||||
struct fsl_mc_device *dpmcp_dev,
|
||||
u32 flags, struct fsl_mc_io **new_mc_io);
|
||||
|
||||
void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
|
||||
|
||||
int fsl_mc_io_set_dpmcp(struct fsl_mc_io *mc_io,
|
||||
struct fsl_mc_device *dpmcp_dev);
|
||||
|
||||
void fsl_mc_io_unset_dpmcp(struct fsl_mc_io *mc_io);
|
||||
|
||||
int mc_send_command(struct fsl_mc_io *mc_io, struct mc_command *cmd);
|
||||
|
||||
#endif /* _FSL_MC_SYS_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче