/* Copyright 2008 - 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 Freescale Semiconductor nor the
* names of its 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 Freescale Semiconductor ``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 Freescale Semiconductor 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_QMAN_H
#define __FSL_QMAN_H
#include <linux/bitops.h>
/* Hardware constants */
#define QM_CHANNEL_SWPORTAL0 0
#define QMAN_CHANNEL_POOL1 0x21
#define QMAN_CHANNEL_CAAM 0x80
#define QMAN_CHANNEL_POOL1_REV3 0x401
#define QMAN_CHANNEL_CAAM_REV3 0x840
extern u16 qm_channel_pool1;
extern u16 qm_channel_caam;
/* Portal processing (interrupt) sources */
#define QM_PIRQ_CSCI 0x00100000 /* Congestion State Change */
#define QM_PIRQ_EQCI 0x00080000 /* Enqueue Command Committed */
#define QM_PIRQ_EQRI 0x00040000 /* EQCR Ring (below threshold) */
#define QM_PIRQ_DQRI 0x00020000 /* DQRR Ring (non-empty) */
#define QM_PIRQ_MRI 0x00010000 /* MR Ring (non-empty) */
/*
* This mask contains all the interrupt sources that need handling except DQRI,
* ie. that if present should trigger slow-path processing.
*/
#define QM_PIRQ_SLOW (QM_PIRQ_CSCI | QM_PIRQ_EQCI | QM_PIRQ_EQRI | \
QM_PIRQ_MRI)
/* For qman_static_dequeue_*** APIs */
#define QM_SDQCR_CHANNELS_POOL_MASK 0x00007fff
/* for n in [1,15] */
#define QM_SDQCR_CHANNELS_POOL(n) (0x00008000 >> (n))
/* for conversion from n of qm_channel */
static inline u32 QM_SDQCR_CHANNELS_POOL_CONV(u16 channel)
{
return QM_SDQCR_CHANNELS_POOL(channel + 1 - qm_channel_pool1);
}
/* --- QMan data structures (and associated constants) --- */
/* "Frame Descriptor (FD)" */
struct qm_fd {
union {
struct {
u8 cfg8b_w1;
u8 bpid; /* Buffer Pool ID */
u8 cfg8b_w3;
u8 addr_hi; /* high 8-bits of 40-bit address */
__be32 addr_lo; /* low 32-bits of 40-bit address */
} __packed;
__be64 data;
};
__be32 cfg; /* format, offset, length / congestion */
union {
__be32 cmd;
__be32 status;
};
} __aligned(8);
#define QM_FD_FORMAT_SG BIT(31)
#define QM_FD_FORMAT_LONG BIT(30)
#define QM_FD_FORMAT_COMPOUND BIT(29)
#define QM_FD_FORMAT_MASK GENMASK(31, 29)
#define QM_FD_OFF_SHIFT 20
#define QM_FD_OFF_MASK GENMASK(28, 20)
#define QM_FD_LEN_MASK GENMASK(19, 0)
#define QM_FD_LEN_BIG_MASK GENMASK(28, 0)
enum qm_fd_format {
/*
* 'contig' implies a contiguous buffer, whereas 'sg' implies a
* scatter-gather table. 'big' implies a 29-bit length with no offset
* field, otherwise length is 20-bit and offset is 9-bit. 'compound'
* implies a s/g-like table, where each entry itself represents a frame
* (contiguous or scatter-gather) and the 29-bit "length" is
* interpreted purely for congestion calculations, ie. a "congestion
* weight".
*/
qm_fd_contig = 0,
qm_fd_contig_big = QM_FD_FORMAT_LONG,
qm_fd_sg = QM_FD_FORMAT_SG,
qm_fd_sg_big = QM_FD_FORMAT_SG | QM_FD_FORMAT_LONG,
qm_fd_compound = QM_FD_FORMAT_COMPOUND
};
static inline dma_addr_t qm_fd_addr(const struct qm_fd *fd)
{
return be64_to_cpu(fd->data) & 0xffffffffffLLU;
}
static inline u64 qm_fd_addr_get64(const struct qm_fd *fd)
{
return be64_to_cpu(fd->data) & 0xffffffffffLLU;
}
static inline void qm_fd_addr_set64(struct qm_fd *fd, u64 addr)
{
fd->addr_hi = upper_32_bits(addr);
fd->addr_lo = cpu_to_be32(lower_32_bits(addr));
}
/*
* The 'format' field indicates the interpretation of the remaining
* 29 bits of the 32-bit word.
* If 'format' is _contig or _sg, 20b length and 9b offset.
* If 'format' is _contig_big or _sg_big, 29b length.
* If 'format' is _compound, 29b "congestion weight".
*/
static inline enum qm_fd_format qm_fd_get_format(const struct qm_fd *fd)
{
return be32_to_cpu(fd->cfg) & QM_FD_FORMAT_MASK;
}
static inline int qm_fd_get_offset(const struct qm_fd *fd)
{
return (be32_to_cpu(fd->cfg) & QM_FD_OFF_MASK) >> QM_FD_OFF_SHIFT;
}
static inline int qm_fd_get_length(const struct qm_fd *fd)
{
return be32_to_cpu(fd->cfg) & QM_FD_LEN_MASK;
}
static inline int qm_fd_get_len_big(const struct qm_fd *fd)
{
return be32_to_cpu(fd->cfg)