Commit 197f4d6a authored by J. German Rivera's avatar J. German Rivera Committed by Greg Kroah-Hartman

staging: fsl-mc: fsl-mc object allocator driver

The fsl-mc object allocator driver manages "allocatable" fsl-mc
objects such as DPBPs, DPMCPs and DPCONs. It provides services to
other fsl-mc drivers to allocate/deallocate these types of objects.
Signed-off-by: default avatarJ. German Rivera <German.Rivera@freescale.com>
Signed-off-by: default avatarStuart Yoder <stuart.yoder@freescale.com>
Acked-by: default avatarAlexander Graf <agraf@suse.de>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent f2f2726b
......@@ -5,7 +5,8 @@
#
# This file is released under the GPLv2
#
obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o
obj-$(CONFIG_FSL_MC_BUS) += mc-bus-driver.o \
mc-allocator-driver.o
mc-bus-driver-objs := mc-bus.o \
mc-sys.o \
......@@ -13,3 +14,6 @@ mc-bus-driver-objs := mc-bus.o \
dpmng.o \
dprc-driver.o
mc-allocator-driver-objs := mc-allocator.o \
dpmcp.o \
dpbp.o
/* Copyright 2013-2014 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-sys.h"
#include "../include/mc-cmd.h"
#include "../include/dpbp.h"
#include "../include/dpbp-cmd.h"
int dpbp_open(struct fsl_mc_io *mc_io, int dpbp_id, uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
MC_CMD_PRI_LOW, 0);
cmd.params[0] |= mc_enc(0, 32, dpbp_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
return err;
}
EXPORT_SYMBOL(dpbp_open);
int dpbp_close(struct fsl_mc_io *mc_io, uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, MC_CMD_PRI_HIGH,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
EXPORT_SYMBOL(dpbp_close);
int dpbp_create(struct fsl_mc_io *mc_io,
const struct dpbp_cfg *cfg,
uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
(void)(cfg); /* unused */
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_CREATE,
MC_CMD_PRI_LOW, 0);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
return 0;
}
int dpbp_destroy(struct fsl_mc_io *mc_io, uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY,
MC_CMD_PRI_LOW, token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_enable(struct fsl_mc_io *mc_io, uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, MC_CMD_PRI_LOW,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
EXPORT_SYMBOL(dpbp_enable);
int dpbp_disable(struct fsl_mc_io *mc_io, uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
MC_CMD_PRI_LOW, token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
EXPORT_SYMBOL(dpbp_disable);
int dpbp_is_enabled(struct fsl_mc_io *mc_io, uint16_t token, int *en)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_IS_ENABLED, MC_CMD_PRI_LOW,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*en = (int)mc_dec(cmd.params[0], 0, 1);
return 0;
}
int dpbp_reset(struct fsl_mc_io *mc_io, uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
MC_CMD_PRI_LOW, token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_set_irq(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint64_t irq_paddr,
uint32_t irq_val,
int user_irq_id)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(0, 8, irq_index);
cmd.params[0] |= mc_enc(32, 32, irq_val);
cmd.params[1] |= mc_enc(0, 64, irq_paddr);
cmd.params[2] |= mc_enc(0, 32, user_irq_id);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_get_irq(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
int *type,
uint64_t *irq_paddr,
uint32_t *irq_val,
int *user_irq_id)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*irq_val = (uint32_t)mc_dec(cmd.params[0], 0, 32);
*irq_paddr = (uint64_t)mc_dec(cmd.params[1], 0, 64);
*user_irq_id = (int)mc_dec(cmd.params[2], 0, 32);
*type = (int)mc_dec(cmd.params[2], 32, 32);
return 0;
}
int dpbp_set_irq_enable(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint8_t en)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_ENABLE,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(0, 8, en);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_get_irq_enable(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint8_t *en)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_ENABLE,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*en = (uint8_t)mc_dec(cmd.params[0], 0, 8);
return 0;
}
int dpbp_set_irq_mask(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint32_t mask)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_SET_IRQ_MASK,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(0, 32, mask);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_get_irq_mask(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint32_t *mask)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_MASK,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*mask = (uint32_t)mc_dec(cmd.params[0], 0, 32);
return 0;
}
int dpbp_get_irq_status(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint32_t *status)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_IRQ_STATUS,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*status = (uint32_t)mc_dec(cmd.params[0], 0, 32);
return 0;
}
int dpbp_clear_irq_status(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint32_t status)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLEAR_IRQ_STATUS,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(0, 32, status);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_get_attributes(struct fsl_mc_io *mc_io,
uint16_t token,
struct dpbp_attr *attr)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_GET_ATTR,
MC_CMD_PRI_LOW, token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
attr->bpid = (uint16_t)mc_dec(cmd.params[0], 16, 16);
attr->id = (int)mc_dec(cmd.params[0], 32, 32);
attr->version.major = (uint16_t)mc_dec(cmd.params[1], 0, 16);
attr->version.minor = (uint16_t)mc_dec(cmd.params[1], 16, 16);
return 0;
}
EXPORT_SYMBOL(dpbp_get_attributes);
/* Copyright 2013-2015 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.
*/
#ifndef _FSL_DPMCP_CMD_H
#define _FSL_DPMCP_CMD_H
/* DPMCP Version */
#define DPMCP_VER_MAJOR 2
#define DPMCP_VER_MINOR 0
/* Command IDs */
#define DPMCP_CMDID_CLOSE 0x800
#define DPMCP_CMDID_OPEN 0x80b
#define DPMCP_CMDID_CREATE 0x90b
#define DPMCP_CMDID_DESTROY 0x900
#define DPMCP_CMDID_GET_ATTR 0x004
#define DPMCP_CMDID_RESET 0x005
#define DPMCP_CMDID_SET_IRQ 0x010
#define DPMCP_CMDID_GET_IRQ 0x011
#define DPMCP_CMDID_SET_IRQ_ENABLE 0x012
#define DPMCP_CMDID_GET_IRQ_ENABLE 0x013
#define DPMCP_CMDID_SET_IRQ_MASK 0x014
#define DPMCP_CMDID_GET_IRQ_MASK 0x015
#define DPMCP_CMDID_GET_IRQ_STATUS 0x016
#define DPMCP_CMDID_CLEAR_IRQ_STATUS 0x017
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_CMD_CREATE(cmd, cfg) \
MC_CMD_OP(cmd, 0, 0, 32, int, cfg->portal_id)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_CMD_SET_IRQ(cmd, irq_index, irq_addr, irq_val, user_irq_id) \
do { \
MC_CMD_OP(cmd, 0, 0, 8, uint8_t, irq_index);\
MC_CMD_OP(cmd, 0, 32, 32, uint32_t, irq_val);\
MC_CMD_OP(cmd, 1, 0, 64, uint64_t, irq_addr); \
MC_CMD_OP(cmd, 2, 0, 32, int, user_irq_id); \
} while (0)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_CMD_GET_IRQ(cmd, irq_index) \
MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_RSP_GET_IRQ(cmd, type, irq_addr, irq_val, user_irq_id) \
do { \
MC_RSP_OP(cmd, 0, 0, 32, uint32_t, irq_val); \
MC_RSP_OP(cmd, 1, 0, 64, uint64_t, irq_addr); \
MC_RSP_OP(cmd, 2, 0, 32, int, user_irq_id); \
MC_RSP_OP(cmd, 2, 32, 32, int, type); \
} while (0)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_CMD_SET_IRQ_ENABLE(cmd, irq_index, en) \
do { \
MC_CMD_OP(cmd, 0, 0, 8, uint8_t, en); \
MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
} while (0)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_CMD_GET_IRQ_ENABLE(cmd, irq_index) \
MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_RSP_GET_IRQ_ENABLE(cmd, en) \
MC_RSP_OP(cmd, 0, 0, 8, uint8_t, en)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_CMD_SET_IRQ_MASK(cmd, irq_index, mask) \
do { \
MC_CMD_OP(cmd, 0, 0, 32, uint32_t, mask);\
MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
} while (0)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_CMD_GET_IRQ_MASK(cmd, irq_index) \
MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_RSP_GET_IRQ_MASK(cmd, mask) \
MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mask)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_CMD_GET_IRQ_STATUS(cmd, irq_index) \
MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_RSP_GET_IRQ_STATUS(cmd, status) \
MC_RSP_OP(cmd, 0, 0, 32, uint32_t, status)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_CMD_CLEAR_IRQ_STATUS(cmd, irq_index, status) \
do { \
MC_CMD_OP(cmd, 0, 0, 32, uint32_t, status); \
MC_CMD_OP(cmd, 0, 32, 8, uint8_t, irq_index);\
} while (0)
/* cmd, param, offset, width, type, arg_name */
#define DPMCP_RSP_GET_ATTRIBUTES(cmd, attr) \
do { \
MC_RSP_OP(cmd, 0, 32, 32, int, attr->id);\
MC_RSP_OP(cmd, 1, 0, 16, uint16_t, attr->version.major);\
MC_RSP_OP(cmd, 1, 16, 16, uint16_t, attr->version.minor);\
} while (0)
#endif /* _FSL_DPMCP_CMD_H */
/* Copyright 2013-2015 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-sys.h"
#include "../include/mc-cmd.h"
#include "dpmcp.h"
#include "dpmcp-cmd.h"
int dpmcp_open(struct fsl_mc_io *mc_io, int dpmcp_id, uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_OPEN,
MC_CMD_PRI_LOW, 0);
cmd.params[0] |= mc_enc(0, 32, dpmcp_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
return err;
}
int dpmcp_close(struct fsl_mc_io *mc_io, uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLOSE, MC_CMD_PRI_HIGH,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmcp_create(struct fsl_mc_io *mc_io,
const struct dpmcp_cfg *cfg,
uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CREATE,
MC_CMD_PRI_LOW, 0);
cmd.params[0] |= mc_enc(0, 32, cfg->portal_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*token = MC_CMD_HDR_READ_TOKEN(cmd.header);
return 0;
}
int dpmcp_destroy(struct fsl_mc_io *mc_io, uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_DESTROY,
MC_CMD_PRI_LOW, token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmcp_reset(struct fsl_mc_io *mc_io, uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_RESET,
MC_CMD_PRI_LOW, token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmcp_set_irq(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint64_t irq_addr,
uint32_t irq_val,
int user_irq_id)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(0, 8, irq_index);
cmd.params[0] |= mc_enc(32, 32, irq_val);
cmd.params[1] |= mc_enc(0, 64, irq_addr);
cmd.params[2] |= mc_enc(0, 32, user_irq_id);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmcp_get_irq(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
int *type,
uint64_t *irq_addr,
uint32_t *irq_val,
int *user_irq_id)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*irq_val = (uint32_t)mc_dec(cmd.params[0], 0, 32);
*irq_addr = (uint64_t)mc_dec(cmd.params[1], 0, 64);
*user_irq_id = (int)mc_dec(cmd.params[2], 0, 32);
*type = (int)mc_dec(cmd.params[2], 32, 32);
return 0;
}
int dpmcp_set_irq_enable(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint8_t en)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_ENABLE,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(0, 8, en);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmcp_get_irq_enable(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint8_t *en)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_ENABLE,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*en = (uint8_t)mc_dec(cmd.params[0], 0, 8);
return 0;
}
int dpmcp_set_irq_mask(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint32_t mask)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_SET_IRQ_MASK,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(0, 32, mask);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmcp_get_irq_mask(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint32_t *mask)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_MASK,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*mask = (uint32_t)mc_dec(cmd.params[0], 0, 32);
return 0;
}
int dpmcp_get_irq_status(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint32_t *status)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_IRQ_STATUS,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
*status = (uint32_t)mc_dec(cmd.params[0], 0, 32);
return 0;
}
int dpmcp_clear_irq_status(struct fsl_mc_io *mc_io,
uint16_t token,
uint8_t irq_index,
uint32_t status)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_CLEAR_IRQ_STATUS,
MC_CMD_PRI_LOW, token);
cmd.params[0] |= mc_enc(0, 32, status);
cmd.params[0] |= mc_enc(32, 8, irq_index);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmcp_get_attributes(struct fsl_mc_io *mc_io,
uint16_t token,
struct dpmcp_attr *attr)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMCP_CMDID_GET_ATTR,
MC_CMD_PRI_LOW, token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
attr->id = (int)mc_dec(cmd.params[0], 32, 32);
attr->version.major = (uint16_t)mc_dec(cmd.params[1], 0, 16);
attr->version.minor = (uint16_t)mc_dec(cmd.params[1], 16, 16);
return 0;
}
This diff is collapsed.
......@@ -156,6 +156,85 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
}
}
static void dprc_init_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
{
int pool_type;
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++) {
struct fsl_mc_resource_pool *res_pool =
&mc_bus->resource_pools[pool_type];
res_pool->type = pool_type;
res_pool->max_count = 0;
res_pool->free_count = 0;
res_pool->mc_bus = mc_bus;
INIT_LIST_HEAD(&res_pool->free_list);
mutex_init(&res_pool->mutex);
}
}
static void dprc_cleanup_resource_pool(struct fsl_mc_device *mc_bus_dev,
enum fsl_mc_pool_type pool_type)
{
struct fsl_mc_resource *resource;
struct fsl_mc_resource *next;
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
struct fsl_mc_resource_pool *res_pool =
&mc_bus->resource_pools[pool_type];
int free_count = 0;
WARN_ON(res_pool->type != pool_type);
WARN_ON(res_pool->free_count != res_pool->max_count);
list_for_each_entry_safe(resource, next, &res_pool->free_list, node) {
free_count++;
WARN_ON(resource->type != res_pool->type);
WARN_ON(resource->parent_pool != res_pool);
devm_kfree(&mc_bus_dev->dev, resource);
}
WARN_ON(free_count != res_pool->free_count);
}
static void dprc_cleanup_all_resource_pools(struct fsl_mc_device *mc_bus_dev)
{
int pool_type;
for (pool_type = 0; pool_type < FSL_MC_NUM_POOL_TYPES; pool_type++)
dprc_cleanup_resource_pool(mc_bus_dev, pool_type);
}
static void reorder_obj_desc_array(struct dprc_obj_desc *obj_desc_array,
int num_devs)
{
struct dprc_obj_desc tmp;
struct dprc_obj_desc *top_cursor = &obj_desc_array[0];
struct dprc_obj_desc *bottom_cursor = &obj_desc_array[num_devs - 1];
/*
* Reorder entries in obj_desc_array so that all allocatable devices
* are placed before all non-allocatable devices:
*
* Loop Invariant: everything before top_cursor is allocatable and
* everything after bottom_cursor is non-allocatable.
*/
while (top_cursor < bottom_cursor) {
if (FSL_MC_IS_ALLOCATABLE(top_cursor->type)) {
top_cursor++;
} else {
if (FSL_MC_IS_ALLOCATABLE(bottom_cursor->type)) {
tmp = *bottom_cursor;
*bottom_cursor = *top_cursor;
*top_cursor = tmp;
top_cursor++;
}
bottom_cursor--;
}
}
}
/**
* dprc_scan_objects - Discover objects in a DPRC
*
......@@ -164,6 +243,14 @@ static void dprc_add_new_devices(struct fsl_mc_device *mc_bus_dev,
* Detects objects added and removed from a DPRC and synchronizes the
* state of the Linux bus driver, MC by adding and removing
* devices accordingly.
* Two types of devices can be found in a DPRC: allocatable objects (e.g.,
* dpbp, dpmcp) and non-allocatable devices (e.g., dprc, dpni).
* All allocatable devices needed to be probed before all non-allocatable
* devices, to ensure that device drivers for non-allocatable
* devices can allocate any type of allocatable devices.
* That is, we need to ensure that the corresponding resource pools are
* populated before they can get allocation requests from probe callbacks
* of the device drivers for the non-allocatable devices.
*/
int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
{
......@@ -226,6 +313,8 @@ int dprc_scan_objects(struct fsl_mc_device *mc_bus_dev)
"%d out of %d devices could not be retrieved\n",
dprc_get_obj_failures, num_child_objects);
}
reorder_obj_desc_array(child_obj_desc_array, num_child_objects);
}
dprc_remove_devices(mc_bus_dev, child_obj_desc_array,
......@@ -255,12 +344,20 @@ int dprc_scan_container(struct fsl_mc_device *mc_bus_dev)
int error;
struct fsl_mc_bus *mc_bus = to_fsl_mc_bus(mc_bus_dev);
dprc_init_all_resource_pools(mc_bus_dev);
/*
* Discover objects in the DPRC:
*/
mutex_lock(&mc_bus->scan_mutex);
error = dprc_scan_objects(mc_bus_dev);
mutex_unlock(&mc_bus->scan_mutex);
if (error < 0)
goto error;
return 0;
error:
dprc_cleanup_all_resource_pools(mc_bus_dev);
return error;
}
EXPORT_SYMBOL_GPL(dprc_scan_container);
......@@ -272,6 +369,8 @@ EXPORT_SYMBOL_GPL(dprc_scan_container);
*
* It opens the physical DPRC in the MC.
* It scans the DPRC to discover the MC objects contained in it.
* It creates the interrupt pool for the MC bus associated with the DPRC.
* It configures the interrupts for the DPRC device itself.
*/
static int dprc_probe(struct fsl_mc_device *mc_dev)
{
......@@ -295,7 +394,7 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
error = fsl_create_mc_io(&mc_dev->dev,
mc_dev->regions[0].start,
region_size,
0, &mc_dev->mc_io);
NULL, 0, &mc_dev->mc_io);
if (error < 0)
return error;
}
......@@ -334,6 +433,8 @@ static int dprc_probe(struct fsl_mc_device *mc_dev)
*
* It removes the DPRC's child objects from Linux (not from the MC) and
* closes the DPRC device in the MC.
* It tears down the interrupts that were configured for the DPRC device.
* It destroys the interrupt pool associated with this MC bus.
*/
static int dprc_remove(struct fsl_mc_device *mc_dev)
{
......@@ -345,6 +446,7 @@ static int dprc_remove(struct fsl_mc_device *mc_dev)
return -EINVAL;
device_for_each_child(&mc_dev->dev, NULL, __fsl_mc_device_remove);
dprc_cleanup_all_resource_pools(mc_dev);
error = dprc_close(mc_dev->mc_io, mc_dev->mc_handle);
if (error < 0)
dev_err(&mc_dev->dev, "dprc_close() failed: %d\n", error);
......
This diff is collapsed.
......@@ -604,7 +604,7 @@ static int fsl_mc_bus_probe(struct platform_device *pdev)
mc_portal_phys_addr = res.start;
mc_portal_size = resource_size(&res);
error = fsl_create_mc_io(&pdev->dev, mc_portal_phys_addr,
mc_portal_size, 0, &mc_io);
mc_portal_size, NULL, 0, &mc_io);
if (error < 0)
return error;
......
......@@ -60,6 +60,8 @@
* @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
* @resource: Pointer to MC bus object allocator resource 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
*
......@@ -68,6 +70,7 @@
int __must_check fsl_create_mc_io(struct device *dev,
phys_addr_t mc_portal_phys_addr,
uint32_t mc_portal_size,
struct fsl_mc_resource *resource,
uint32_t flags, struct fsl_mc_io **new_mc_io)
{
struct fsl_mc_io *mc_io;
......@@ -82,6 +85,7 @@ int __must_check fsl_create_mc_io(struct device *dev,
mc_io->flags = flags;
mc_io->portal_phys_addr = mc_portal_phys_addr;
mc_io->portal_size = mc_portal_size;
mc_io->resource = resource;
res = devm_request_mem_region(dev,
mc_portal_phys_addr,
mc_portal_size,
......
/* Copyright 2013-2014 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.
*/
#ifndef _FSL_DPBP_CMD_H
#define _FSL_DPBP_CMD_H
/* DPBP Version */
#define DPBP_VER_MAJOR 2
#define DPBP_VER_MINOR 0
/* Command IDs */
#define DPBP_CMDID_CLOSE 0x800
#define DPBP_CMDID_OPEN 0x804
#define DPBP_CMDID_CREATE 0x904
#define DPBP_CMDID_DESTROY 0x900
#define DPBP_CMDID_ENABLE 0x002
#define DPBP_CMDID_DISABLE 0x003
#define DPBP_CMDID_GET_ATTR 0x004
#define DPBP_CMDID_RESET 0x005
#define DPBP_CMDID_IS_ENABLED 0x006
#define DPBP_CMDID_SET_IRQ 0x010
#define DPBP_CMDID_GET_IRQ 0x011
#define DPBP_CMDID_SET_IRQ_ENABLE 0x012
#define DPBP_CMDID_GET_IRQ_ENABLE 0x013
#define DPBP_CMDID_SET_IRQ_MASK 0x014
#define DPBP_CMDID_GET_IRQ_MASK 0x015
#define DPBP_CMDID_GET_IRQ_STATUS 0x016
#define DPBP_CMDID_CLEAR_IRQ_STATUS 0x017
#endif /* _FSL_DPBP_CMD_H */
This diff is collapsed.
/* Copyright 2013-2015 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.
*/
#ifndef _FSL_DPCON_CMD_H
#define _FSL_DPCON_CMD_H
/* DPCON Version */
#define DPCON_VER_MAJOR 2
#define DPCON_VER_MINOR 0
/* Command IDs */
#define DPCON_CMDID_CLOSE 0x800
#define DPCON_CMDID_OPEN 0x808
#define DPCON_CMDID_CREATE 0x908
#define DPCON_CMDID_DESTROY 0x900
#define DPCON_CMDID_ENABLE 0x002
#define DPCON_CMDID_DISABLE 0x003
#define DPCON_CMDID_GET_ATTR 0x004
#define DPCON_CMDID_RESET 0x005
#define DPCON_CMDID_IS_ENABLED 0x006
#define DPCON_CMDID_SET_IRQ 0x010
#define DPCON_CMDID_GET_IRQ 0x011
#define DPCON_CMDID_SET_IRQ_ENABLE 0x012
#define DPCON_CMDID_GET_IRQ_ENABLE 0x013
#define DPCON_CMDID_SET_IRQ_MASK 0x014
#define DPCON_CMDID_GET_IRQ_MASK 0x015
#define DPCON_CMDID_GET_IRQ_STATUS 0x016
#define DPCON_CMDID_CLEAR_IRQ_STATUS 0x017
#define DPCON_CMDID_SET_NOTIFICATION 0x100
#endif /* _FSL_DPCON_CMD_H */
......@@ -21,6 +21,11 @@
(strcmp((_mc_dev)->obj_desc.type, (_obj_desc)->type) == 0 && \
(_mc_dev)->obj_desc.id == (_obj_desc)->id)
#define FSL_MC_IS_ALLOCATABLE(_obj_type) \
(strcmp(_obj_type, "dpbp") == 0 || \
strcmp(_obj_type, "dpmcp") == 0 || \
strcmp(_obj_type, "dpcon") == 0)
/**
* struct fsl_mc - Private data of a "fsl,qoriq-mc" platform device
* @root_mc_bus_dev: MC object device representing the root DPRC
......@@ -32,19 +37,6 @@ struct fsl_mc {
struct fsl_mc_addr_translation_range *translation_ranges;
};
/**
* struct fsl_mc_bus - logical bus that corresponds to a physical DPRC
* @mc_dev: fsl-mc device for the bus device itself.
* @scan_mutex: Serializes bus scanning
*/
struct fsl_mc_bus {
struct fsl_mc_device mc_dev;
struct mutex scan_mutex; /* serializes bus scanning */
};
#define to_fsl_mc_bus(_mc_dev) \
container_of(_mc_dev, struct fsl_mc_bus, mc_dev)
/**
* struct fsl_mc_addr_translation_range - bus to system address translation
* range
......@@ -59,6 +51,42 @@ struct fsl_mc_addr_translation_range {
phys_addr_t start_phys_addr;
};
/**
* struct fsl_mc_resource_pool - Pool of MC resources of a given
* type
* @type: type of resources in the pool
* @max_count: maximum number of resources in the pool
* @free_count: number of free resources in the pool
* @mutex: mutex to serialize access to the pool's free list
* @free_list: anchor node of list of free resources in the pool
* @mc_bus: pointer to the MC bus that owns this resource pool
*/
struct fsl_mc_resource_pool {
enum fsl_mc_pool_type type;
int16_t max_count;
int16_t free_count;
struct mutex mutex; /* serializes access to free_list */
struct list_head free_list;
struct fsl_mc_bus *mc_bus;
};
/**
* struct fsl_mc_bus - logical bus that corresponds to a physical DPRC
* @mc_dev: fsl-mc device for the bus device itself.
* @resource_pools: array of resource pools (one pool per resource type)
* for this MC bus. These resources represent allocatable entities
* from the physical DPRC.
* @scan_mutex: Serializes bus scanning
*/
struct fsl_mc_bus {
struct fsl_mc_device mc_dev;
struct fsl_mc_resource_pool resource_pools[FSL_MC_NUM_POOL_TYPES];
struct mutex scan_mutex; /* serializes bus scanning */
};
#define to_fsl_mc_bus(_mc_dev) \
container_of(_mc_dev, struct fsl_mc_bus, mc_dev)
int __must_check fsl_mc_device_add(struct dprc_obj_desc *obj_desc,
struct fsl_mc_io *mc_io,
struct device *parent_dev,
......@@ -74,4 +102,11 @@ int __init dprc_driver_init(void);
void __exit dprc_driver_exit(void);
int __must_check fsl_mc_resource_allocate(struct fsl_mc_bus *mc_bus,
enum fsl_mc_pool_type pool_type,
struct fsl_mc_resource
**new_resource);
void fsl_mc_resource_free(struct fsl_mc_resource *resource);
#endif /* _FSL_MC_PRIVATE_H_ */
......@@ -40,6 +40,7 @@
#include <linux/io.h>
#include <linux/dma-mapping.h>
struct fsl_mc_resource;
struct mc_command;
/**
......@@ -49,6 +50,9 @@ struct mc_command;
* @portal_size: MC command portal size in bytes
* @portal_phys_addr: MC command portal physical address
* @portal_virt_addr: MC command portal virtual address
* @resource: generic resource associated with the MC portal if
* the MC portal came from a resource pool, or NULL if the MC portal
* is permanently bound to a device (e.g., a DPRC)
*/
struct fsl_mc_io {
struct device *dev;
......@@ -56,11 +60,13 @@ struct fsl_mc_io {
uint32_t portal_size;
phys_addr_t portal_phys_addr;
void __iomem *portal_virt_addr;
struct fsl_mc_resource *resource;
};
int __must_check fsl_create_mc_io(struct device *dev,
phys_addr_t mc_portal_phys_addr,
uint32_t mc_portal_size,
struct fsl_mc_resource *resource,
uint32_t flags, struct fsl_mc_io **new_mc_io);
void fsl_destroy_mc_io(struct fsl_mc_io *mc_io);
......
......@@ -65,6 +65,44 @@ struct fsl_mc_device_match_id {
uint32_t ver_minor;
};
/**
* enum fsl_mc_pool_type - Types of allocatable MC bus resources
*
* Entries in these enum are used as indices in the array of resource
* pools of an fsl_mc_bus object.
*/
enum fsl_mc_pool_type {
FSL_MC_POOL_DPMCP = 0x0, /* corresponds to "dpmcp" in the MC */
FSL_MC_POOL_DPBP, /* corresponds to "dpbp" in the MC */
FSL_MC_POOL_DPCON, /* corresponds to "dpcon" in the MC */
/*
* NOTE: New resource pool types must be added before this entry
*/
FSL_MC_NUM_POOL_TYPES
};
/**
* struct fsl_mc_resource - MC generic resource
* @type: type of resource
* @id: unique MC resource Id within the resources of the same type
* @data: pointer to resource-specific data if the resource is currently
* allocated, or NULL if the resource is not currently allocated.
* @parent_pool: pointer to the parent resource pool from which this
* resource is allocated from.
* @node: Node in the free list of the corresponding resource pool
*
* NOTE: This structure is to be embedded as a field of specific
* MC resource structures.
*/
struct fsl_mc_resource {
enum fsl_mc_pool_type type;
int32_t id;
void *data;
struct fsl_mc_resource_pool *parent_pool;
struct list_head node;
};
/**
* Bit masks for a MC object device (struct fsl_mc_device) flags
*/
......@@ -86,6 +124,7 @@ struct fsl_mc_device_match_id {
* NULL if none.
* @obj_desc: MC description of the DPAA device
* @regions: pointer to array of MMIO region entries
* @resource: generic resource associated with this MC object device, if any.
*
* Generic device object for MC object devices that are "attached" to a
* MC bus.
......@@ -95,6 +134,17 @@ struct fsl_mc_device_match_id {
* - The SMMU notifier callback gets invoked after device_add() has been
* called for an MC object device, but before the device-specific probe
* callback gets called.
* - DP_OBJ_DPRC objects are the only MC objects that have built-in MC
* portals. For all other MC objects, their device drivers are responsible for
* allocating MC portals for them by calling fsl_mc_portal_allocate().
* - Some types of MC objects (e.g., DP_OBJ_DPBP, DP_OBJ_DPCON) are
* treated as resources that can be allocated/deallocated from the
* corresponding resource pool in the object's parent DPRC, using the
* fsl_mc_object_allocate()/fsl_mc_object_free() functions. These MC objects
* are known as "allocatable" objects. For them, the corresponding
* fsl_mc_device's 'resource' points to the associated resource object.
* For MC objects that are not allocatable (e.g., DP_OBJ_DPRC, DP_OBJ_DPNI),
* 'resource' is NULL.
*/
struct fsl_mc_device {
struct device dev;
......@@ -105,6 +155,7 @@ struct fsl_mc_device {
struct fsl_mc_io *mc_io;
struct dprc_obj_desc obj_desc;
struct resource *regions;
struct fsl_mc_resource *resource;
};
#define to_fsl_mc_device(_dev) \
......@@ -131,6 +182,20 @@ int __must_check __fsl_mc_driver_register(struct fsl_mc_driver *fsl_mc_driver,
void fsl_mc_driver_unregister(struct fsl_mc_driver *driver);
int __must_check fsl_mc_portal_allocate(struct fsl_mc_device *mc_dev,
uint16_t mc_io_flags,
struct fsl_mc_io **new_mc_io);
void fsl_mc_portal_free(struct fsl_mc_io *mc_io);
int fsl_mc_portal_reset(struct fsl_mc_io *mc_io);
int __must_check fsl_mc_object_allocate(struct fsl_mc_device *mc_dev,
enum fsl_mc_pool_type pool_type,
struct fsl_mc_device **new_mc_adev);
void fsl_mc_object_free(struct fsl_mc_device *mc_adev);
extern struct bus_type fsl_mc_bus_type;
#endif /* _FSL_MC_H_ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment