avionic design with actual uboot and tooling

submodule of avionic design uboot bootloader and with included tools to
get you started , read readme.md and readme-tk1-loader.md
This commit is contained in:
2026-03-03 21:46:32 +02:00
parent fe3ba02c96
commit 68d74d3181
11967 changed files with 2221897 additions and 0 deletions

View File

@@ -0,0 +1,15 @@
#
# Copyright 2014 Freescale Semiconductor, Inc.
#
# SPDX-License-Identifier: GPL-2.0+
#
# Layerscape MC driver
obj-y += mc.o \
mc_sys.o \
dpmng.o \
dprc.o \
dpbp.o \
dpni.o \
dpmac.o
obj-y += dpio/

View File

@@ -0,0 +1,159 @@
/*
* Freescale Layerscape MC I/O wrapper
*
* Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
* Author: German Rivera <German.Rivera@freescale.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpbp.h>
int dpbp_open(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
int dpbp_id,
uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_OPEN,
cmd_flags,
0);
DPBP_CMD_OPEN(cmd, 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;
}
int dpbp_close(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_CLOSE, cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_create(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
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,
cmd_flags,
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,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_DESTROY,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_enable(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_ENABLE, cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_disable(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_DISABLE,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_reset(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPBP_CMDID_RESET,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpbp_get_attributes(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
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,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPBP_RSP_GET_ATTRIBUTES(cmd, attr);
return 0;
}

View File

@@ -0,0 +1,9 @@
#
# Copyright 2014 Freescale Semiconductor, Inc.
#
# SPDX-License-Identifier: GPL-2.0+
#
# Layerscape MC DPIO driver
obj-y += dpio.o \
qbman_portal.o

View File

@@ -0,0 +1,158 @@
/*
* Copyright (C) 2013-2015 Freescale Semiconductor
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpio.h>
int dpio_open(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
int dpio_id,
uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPIO_CMDID_OPEN,
cmd_flags,
0);
DPIO_CMD_OPEN(cmd, dpio_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 dpio_close(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPIO_CMDID_CLOSE,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpio_create(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
const struct dpio_cfg *cfg,
uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPIO_CMDID_CREATE,
cmd_flags,
0);
DPIO_CMD_CREATE(cmd, cfg);
/* 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 dpio_destroy(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPIO_CMDID_DESTROY,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpio_enable(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPIO_CMDID_ENABLE,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpio_disable(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPIO_CMDID_DISABLE,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpio_reset(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPIO_CMDID_RESET,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpio_get_attributes(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpio_attr *attr)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPIO_CMDID_GET_ATTR,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPIO_RSP_GET_ATTR(cmd, attr);
return 0;
}

View File

@@ -0,0 +1,601 @@
/*
* Copyright (C) 2014 Freescale Semiconductor
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include "qbman_portal.h"
/* QBMan portal management command codes */
#define QBMAN_MC_ACQUIRE 0x30
#define QBMAN_WQCHAN_CONFIGURE 0x46
/* CINH register offsets */
#define QBMAN_CINH_SWP_EQAR 0x8c0
#define QBMAN_CINH_SWP_DCAP 0xac0
#define QBMAN_CINH_SWP_SDQCR 0xb00
#define QBMAN_CINH_SWP_RAR 0xcc0
/* CENA register offsets */
#define QBMAN_CENA_SWP_EQCR(n) (0x000 + ((uint32_t)(n) << 6))
#define QBMAN_CENA_SWP_DQRR(n) (0x200 + ((uint32_t)(n) << 6))
#define QBMAN_CENA_SWP_RCR(n) (0x400 + ((uint32_t)(n) << 6))
#define QBMAN_CENA_SWP_CR 0x600
#define QBMAN_CENA_SWP_RR(vb) (0x700 + ((uint32_t)(vb) >> 1))
#define QBMAN_CENA_SWP_VDQCR 0x780
/* Reverse mapping of QBMAN_CENA_SWP_DQRR() */
#define QBMAN_IDX_FROM_DQRR(p) (((unsigned long)p & 0xff) >> 6)
/*******************************/
/* Pre-defined attribute codes */
/*******************************/
struct qb_attr_code code_generic_verb = QB_CODE(0, 0, 7);
struct qb_attr_code code_generic_rslt = QB_CODE(0, 8, 8);
/*************************/
/* SDQCR attribute codes */
/*************************/
/* we put these here because at least some of them are required by
* qbman_swp_init() */
struct qb_attr_code code_sdqcr_dct = QB_CODE(0, 24, 2);
struct qb_attr_code code_sdqcr_fc = QB_CODE(0, 29, 1);
struct qb_attr_code code_sdqcr_tok = QB_CODE(0, 16, 8);
#define CODE_SDQCR_DQSRC(n) QB_CODE(0, n, 1)
enum qbman_sdqcr_dct {
qbman_sdqcr_dct_null = 0,
qbman_sdqcr_dct_prio_ics,
qbman_sdqcr_dct_active_ics,
qbman_sdqcr_dct_active
};
enum qbman_sdqcr_fc {
qbman_sdqcr_fc_one = 0,
qbman_sdqcr_fc_up_to_3 = 1
};
/*********************************/
/* Portal constructor/destructor */
/*********************************/
/* Software portals should always be in the power-on state when we initialise,
* due to the CCSR-based portal reset functionality that MC has. */
struct qbman_swp *qbman_swp_init(const struct qbman_swp_desc *d)
{
int ret;
struct qbman_swp *p = malloc(sizeof(struct qbman_swp));
if (!p)
return NULL;
p->desc = d;
#ifdef QBMAN_CHECKING
p->mc.check = swp_mc_can_start;
#endif
p->mc.valid_bit = QB_VALID_BIT;
p->sdq = 0;
qb_attr_code_encode(&code_sdqcr_dct, &p->sdq, qbman_sdqcr_dct_prio_ics);
qb_attr_code_encode(&code_sdqcr_fc, &p->sdq, qbman_sdqcr_fc_up_to_3);
qb_attr_code_encode(&code_sdqcr_tok, &p->sdq, 0xbb);
atomic_set(&p->vdq.busy, 1);
p->vdq.valid_bit = QB_VALID_BIT;
p->dqrr.next_idx = 0;
p->dqrr.valid_bit = QB_VALID_BIT;
ret = qbman_swp_sys_init(&p->sys, d);
if (ret) {
free(p);
printf("qbman_swp_sys_init() failed %d\n", ret);
return NULL;
}
qbman_cinh_write(&p->sys, QBMAN_CINH_SWP_SDQCR, p->sdq);
return p;
}
/***********************/
/* Management commands */
/***********************/
/*
* Internal code common to all types of management commands.
*/
void *qbman_swp_mc_start(struct qbman_swp *p)
{
void *ret;
int *return_val;
#ifdef QBMAN_CHECKING
BUG_ON(p->mc.check != swp_mc_can_start);
#endif
ret = qbman_cena_write_start(&p->sys, QBMAN_CENA_SWP_CR);
#ifdef QBMAN_CHECKING
return_val = (int *)ret;
if (!(*return_val))
p->mc.check = swp_mc_can_submit;
#endif
return ret;
}
void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb)
{
uint32_t *v = cmd;
#ifdef QBMAN_CHECKING
BUG_ON(p->mc.check != swp_mc_can_submit);
#endif
lwsync();
/* TBD: "|=" is going to hurt performance. Need to move as many fields
* out of word zero, and for those that remain, the "OR" needs to occur
* at the caller side. This debug check helps to catch cases where the
* caller wants to OR but has forgotten to do so. */
BUG_ON((*v & cmd_verb) != *v);
*v = cmd_verb | p->mc.valid_bit;
qbman_cena_write_complete(&p->sys, QBMAN_CENA_SWP_CR, cmd);
/* TODO: add prefetch support for GPP */
#ifdef QBMAN_CHECKING
p->mc.check = swp_mc_can_poll;
#endif
}
void *qbman_swp_mc_result(struct qbman_swp *p)
{
uint32_t *ret, verb;
#ifdef QBMAN_CHECKING
BUG_ON(p->mc.check != swp_mc_can_poll);
#endif
ret = qbman_cena_read(&p->sys, QBMAN_CENA_SWP_RR(p->mc.valid_bit));
/* Remove the valid-bit - command completed iff the rest is non-zero */
verb = ret[0] & ~QB_VALID_BIT;
if (!verb)
return NULL;
#ifdef QBMAN_CHECKING
p->mc.check = swp_mc_can_start;
#endif
p->mc.valid_bit ^= QB_VALID_BIT;
return ret;
}
/***********/
/* Enqueue */
/***********/
/* These should be const, eventually */
static struct qb_attr_code code_eq_cmd = QB_CODE(0, 0, 2);
static struct qb_attr_code code_eq_orp_en = QB_CODE(0, 2, 1);
static struct qb_attr_code code_eq_tgt_id = QB_CODE(2, 0, 24);
/* static struct qb_attr_code code_eq_tag = QB_CODE(3, 0, 32); */
static struct qb_attr_code code_eq_qd_en = QB_CODE(0, 4, 1);
static struct qb_attr_code code_eq_qd_bin = QB_CODE(4, 0, 16);
static struct qb_attr_code code_eq_qd_pri = QB_CODE(4, 16, 4);
static struct qb_attr_code code_eq_rsp_stash = QB_CODE(5, 16, 1);
static struct qb_attr_code code_eq_rsp_lo = QB_CODE(6, 0, 32);
enum qbman_eq_cmd_e {
/* No enqueue, primarily for plugging ORP gaps for dropped frames */
qbman_eq_cmd_empty,
/* DMA an enqueue response once complete */
qbman_eq_cmd_respond,
/* DMA an enqueue response only if the enqueue fails */
qbman_eq_cmd_respond_reject
};
void qbman_eq_desc_clear(struct qbman_eq_desc *d)
{
memset(d, 0, sizeof(*d));
}
void qbman_eq_desc_set_no_orp(struct qbman_eq_desc *d, int respond_success)
{
uint32_t *cl = qb_cl(d);
qb_attr_code_encode(&code_eq_orp_en, cl, 0);
qb_attr_code_encode(&code_eq_cmd, cl,
respond_success ? qbman_eq_cmd_respond :
qbman_eq_cmd_respond_reject);
}
void qbman_eq_desc_set_response(struct qbman_eq_desc *d,
dma_addr_t storage_phys,
int stash)
{
uint32_t *cl = qb_cl(d);
qb_attr_code_encode_64(&code_eq_rsp_lo, (uint64_t *)cl, storage_phys);
qb_attr_code_encode(&code_eq_rsp_stash, cl, !!stash);
}
void qbman_eq_desc_set_qd(struct qbman_eq_desc *d, uint32_t qdid,
uint32_t qd_bin, uint32_t qd_prio)
{
uint32_t *cl = qb_cl(d);
qb_attr_code_encode(&code_eq_qd_en, cl, 1);
qb_attr_code_encode(&code_eq_tgt_id, cl, qdid);
qb_attr_code_encode(&code_eq_qd_bin, cl, qd_bin);
qb_attr_code_encode(&code_eq_qd_pri, cl, qd_prio);
}
#define EQAR_IDX(eqar) ((eqar) & 0x7)
#define EQAR_VB(eqar) ((eqar) & 0x80)
#define EQAR_SUCCESS(eqar) ((eqar) & 0x100)
int qbman_swp_enqueue(struct qbman_swp *s, const struct qbman_eq_desc *d,
const struct qbman_fd *fd)
{
uint32_t *p;
const uint32_t *cl = qb_cl(d);
uint32_t eqar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_EQAR);
debug("EQAR=%08x\n", eqar);
if (!EQAR_SUCCESS(eqar))
return -EBUSY;
p = qbman_cena_write_start(&s->sys,
QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)));
word_copy(&p[1], &cl[1], 7);
word_copy(&p[8], fd, sizeof(*fd) >> 2);
lwsync();
/* Set the verb byte, have to substitute in the valid-bit */
p[0] = cl[0] | EQAR_VB(eqar);
qbman_cena_write_complete(&s->sys,
QBMAN_CENA_SWP_EQCR(EQAR_IDX(eqar)),
p);
return 0;
}
/***************************/
/* Volatile (pull) dequeue */
/***************************/
/* These should be const, eventually */
static struct qb_attr_code code_pull_dct = QB_CODE(0, 0, 2);
static struct qb_attr_code code_pull_dt = QB_CODE(0, 2, 2);
static struct qb_attr_code code_pull_rls = QB_CODE(0, 4, 1);
static struct qb_attr_code code_pull_stash = QB_CODE(0, 5, 1);
static struct qb_attr_code code_pull_numframes = QB_CODE(0, 8, 4);
static struct qb_attr_code code_pull_token = QB_CODE(0, 16, 8);
static struct qb_attr_code code_pull_dqsource = QB_CODE(1, 0, 24);
static struct qb_attr_code code_pull_rsp_lo = QB_CODE(2, 0, 32);
enum qb_pull_dt_e {
qb_pull_dt_channel,
qb_pull_dt_workqueue,
qb_pull_dt_framequeue
};
void qbman_pull_desc_clear(struct qbman_pull_desc *d)
{
memset(d, 0, sizeof(*d));
}
void qbman_pull_desc_set_storage(struct qbman_pull_desc *d,
struct ldpaa_dq *storage,
dma_addr_t storage_phys,
int stash)
{
uint32_t *cl = qb_cl(d);
/* Squiggle the pointer 'storage' into the extra 2 words of the
* descriptor (which aren't copied to the hw command) */
*(void **)&cl[4] = storage;
if (!storage) {
qb_attr_code_encode(&code_pull_rls, cl, 0);
return;
}
qb_attr_code_encode(&code_pull_rls, cl, 1);
qb_attr_code_encode(&code_pull_stash, cl, !!stash);
qb_attr_code_encode_64(&code_pull_rsp_lo, (uint64_t *)cl, storage_phys);
}
void qbman_pull_desc_set_numframes(struct qbman_pull_desc *d, uint8_t numframes)
{
uint32_t *cl = qb_cl(d);
BUG_ON(!numframes || (numframes > 16));
qb_attr_code_encode(&code_pull_numframes, cl,
(uint32_t)(numframes - 1));
}
void qbman_pull_desc_set_token(struct qbman_pull_desc *d, uint8_t token)
{
uint32_t *cl = qb_cl(d);
qb_attr_code_encode(&code_pull_token, cl, token);
}
void qbman_pull_desc_set_fq(struct qbman_pull_desc *d, uint32_t fqid)
{
uint32_t *cl = qb_cl(d);
qb_attr_code_encode(&code_pull_dct, cl, 1);
qb_attr_code_encode(&code_pull_dt, cl, qb_pull_dt_framequeue);
qb_attr_code_encode(&code_pull_dqsource, cl, fqid);
}
int qbman_swp_pull(struct qbman_swp *s, struct qbman_pull_desc *d)
{
uint32_t *p;
uint32_t *cl = qb_cl(d);
if (!atomic_dec_and_test(&s->vdq.busy)) {
atomic_inc(&s->vdq.busy);
return -EBUSY;
}
s->vdq.storage = *(void **)&cl[4];
s->vdq.token = qb_attr_code_decode(&code_pull_token, cl);
p = qbman_cena_write_start(&s->sys, QBMAN_CENA_SWP_VDQCR);
word_copy(&p[1], &cl[1], 3);
lwsync();
/* Set the verb byte, have to substitute in the valid-bit */
p[0] = cl[0] | s->vdq.valid_bit;
s->vdq.valid_bit ^= QB_VALID_BIT;
qbman_cena_write_complete(&s->sys, QBMAN_CENA_SWP_VDQCR, p);
return 0;
}
/****************/
/* Polling DQRR */
/****************/
static struct qb_attr_code code_dqrr_verb = QB_CODE(0, 0, 8);
static struct qb_attr_code code_dqrr_response = QB_CODE(0, 0, 7);
static struct qb_attr_code code_dqrr_stat = QB_CODE(0, 8, 8);
#define QBMAN_DQRR_RESPONSE_DQ 0x60
#define QBMAN_DQRR_RESPONSE_FQRN 0x21
#define QBMAN_DQRR_RESPONSE_FQRNI 0x22
#define QBMAN_DQRR_RESPONSE_FQPN 0x24
#define QBMAN_DQRR_RESPONSE_FQDAN 0x25
#define QBMAN_DQRR_RESPONSE_CDAN 0x26
#define QBMAN_DQRR_RESPONSE_CSCN_MEM 0x27
#define QBMAN_DQRR_RESPONSE_CGCU 0x28
#define QBMAN_DQRR_RESPONSE_BPSCN 0x29
#define QBMAN_DQRR_RESPONSE_CSCN_WQ 0x2a
/* NULL return if there are no unconsumed DQRR entries. Returns a DQRR entry
* only once, so repeated calls can return a sequence of DQRR entries, without
* requiring they be consumed immediately or in any particular order. */
const struct ldpaa_dq *qbman_swp_dqrr_next(struct qbman_swp *s)
{
uint32_t verb;
uint32_t response_verb;
uint32_t flags;
const struct ldpaa_dq *dq;
const uint32_t *p;
dq = qbman_cena_read(&s->sys, QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
p = qb_cl(dq);
verb = qb_attr_code_decode(&code_dqrr_verb, p);
/* If the valid-bit isn't of the expected polarity, nothing there. Note,
* in the DQRR reset bug workaround, we shouldn't need to skip these
* check, because we've already determined that a new entry is available
* and we've invalidated the cacheline before reading it, so the
* valid-bit behaviour is repaired and should tell us what we already
* knew from reading PI.
*/
if ((verb & QB_VALID_BIT) != s->dqrr.valid_bit) {
qbman_cena_invalidate_prefetch(&s->sys,
QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
return NULL;
}
/* There's something there. Move "next_idx" attention to the next ring
* entry (and prefetch it) before returning what we found. */
s->dqrr.next_idx++;
s->dqrr.next_idx &= QBMAN_DQRR_SIZE - 1; /* Wrap around at 4 */
/* TODO: it's possible to do all this without conditionals, optimise it
* later. */
if (!s->dqrr.next_idx)
s->dqrr.valid_bit ^= QB_VALID_BIT;
/* If this is the final response to a volatile dequeue command
indicate that the vdq is no longer busy */
flags = ldpaa_dq_flags(dq);
response_verb = qb_attr_code_decode(&code_dqrr_response, &verb);
if ((response_verb == QBMAN_DQRR_RESPONSE_DQ) &&
(flags & LDPAA_DQ_STAT_VOLATILE) &&
(flags & LDPAA_DQ_STAT_EXPIRED))
atomic_inc(&s->vdq.busy);
qbman_cena_invalidate_prefetch(&s->sys,
QBMAN_CENA_SWP_DQRR(s->dqrr.next_idx));
return dq;
}
/* Consume DQRR entries previously returned from qbman_swp_dqrr_next(). */
void qbman_swp_dqrr_consume(struct qbman_swp *s, const struct ldpaa_dq *dq)
{
qbman_cinh_write(&s->sys, QBMAN_CINH_SWP_DCAP, QBMAN_IDX_FROM_DQRR(dq));
}
/*********************************/
/* Polling user-provided storage */
/*********************************/
void qbman_dq_entry_set_oldtoken(struct ldpaa_dq *dq,
unsigned int num_entries,
uint8_t oldtoken)
{
memset(dq, oldtoken, num_entries * sizeof(*dq));
}
int qbman_dq_entry_has_newtoken(struct qbman_swp *s,
const struct ldpaa_dq *dq,
uint8_t newtoken)
{
/* To avoid converting the little-endian DQ entry to host-endian prior
* to us knowing whether there is a valid entry or not (and run the
* risk of corrupting the incoming hardware LE write), we detect in
* hardware endianness rather than host. This means we need a different
* "code" depending on whether we are BE or LE in software, which is
* where DQRR_TOK_OFFSET comes in... */
static struct qb_attr_code code_dqrr_tok_detect =
QB_CODE(0, DQRR_TOK_OFFSET, 8);
/* The user trying to poll for a result treats "dq" as const. It is
* however the same address that was provided to us non-const in the
* first place, for directing hardware DMA to. So we can cast away the
* const because it is mutable from our perspective. */
uint32_t *p = qb_cl((struct ldpaa_dq *)dq);
uint32_t token;
token = qb_attr_code_decode(&code_dqrr_tok_detect, &p[1]);
if (token != newtoken)
return 0;
/* Only now do we convert from hardware to host endianness. Also, as we
* are returning success, the user has promised not to call us again, so
* there's no risk of us converting the endianness twice... */
make_le32_n(p, 16);
/* VDQCR "no longer busy" hook - not quite the same as DQRR, because the
* fact "VDQCR" shows busy doesn't mean that the result we're looking at
* is from the same command. Eg. we may be looking at our 10th dequeue
* result from our first VDQCR command, yet the second dequeue command
* could have been kicked off already, after seeing the 1st result. Ie.
* the result we're looking at is not necessarily proof that we can
* reset "busy". We instead base the decision on whether the current
* result is sitting at the first 'storage' location of the busy
* command. */
if (s->vdq.storage == dq) {
s->vdq.storage = NULL;
atomic_inc(&s->vdq.busy);
}
return 1;
}
/********************************/
/* Categorising dequeue entries */
/********************************/
static inline int __qbman_dq_entry_is_x(const struct ldpaa_dq *dq, uint32_t x)
{
const uint32_t *p = qb_cl(dq);
uint32_t response_verb = qb_attr_code_decode(&code_dqrr_response, p);
return response_verb == x;
}
int qbman_dq_entry_is_DQ(const struct ldpaa_dq *dq)
{
return __qbman_dq_entry_is_x(dq, QBMAN_DQRR_RESPONSE_DQ);
}
/*********************************/
/* Parsing frame dequeue results */
/*********************************/
/* These APIs assume qbman_dq_entry_is_DQ() is TRUE */
uint32_t ldpaa_dq_flags(const struct ldpaa_dq *dq)
{
const uint32_t *p = qb_cl(dq);
return qb_attr_code_decode(&code_dqrr_stat, p);
}
const struct dpaa_fd *ldpaa_dq_fd(const struct ldpaa_dq *dq)
{
const uint32_t *p = qb_cl(dq);
return (const struct dpaa_fd *)&p[8];
}
/******************/
/* Buffer release */
/******************/
/* These should be const, eventually */
/* static struct qb_attr_code code_release_num = QB_CODE(0, 0, 3); */
static struct qb_attr_code code_release_set_me = QB_CODE(0, 5, 1);
static struct qb_attr_code code_release_bpid = QB_CODE(0, 16, 16);
void qbman_release_desc_clear(struct qbman_release_desc *d)
{
uint32_t *cl;
memset(d, 0, sizeof(*d));
cl = qb_cl(d);
qb_attr_code_encode(&code_release_set_me, cl, 1);
}
void qbman_release_desc_set_bpid(struct qbman_release_desc *d, uint32_t bpid)
{
uint32_t *cl = qb_cl(d);
qb_attr_code_encode(&code_release_bpid, cl, bpid);
}
#define RAR_IDX(rar) ((rar) & 0x7)
#define RAR_VB(rar) ((rar) & 0x80)
#define RAR_SUCCESS(rar) ((rar) & 0x100)
int qbman_swp_release(struct qbman_swp *s, const struct qbman_release_desc *d,
const uint64_t *buffers, unsigned int num_buffers)
{
uint32_t *p;
const uint32_t *cl = qb_cl(d);
uint32_t rar = qbman_cinh_read(&s->sys, QBMAN_CINH_SWP_RAR);
debug("RAR=%08x\n", rar);
if (!RAR_SUCCESS(rar))
return -EBUSY;
BUG_ON(!num_buffers || (num_buffers > 7));
/* Start the release command */
p = qbman_cena_write_start(&s->sys,
QBMAN_CENA_SWP_RCR(RAR_IDX(rar)));
/* Copy the caller's buffer pointers to the command */
u64_to_le32_copy(&p[2], buffers, num_buffers);
lwsync();
/* Set the verb byte, have to substitute in the valid-bit and the number
* of buffers. */
p[0] = cl[0] | RAR_VB(rar) | num_buffers;
qbman_cena_write_complete(&s->sys,
QBMAN_CENA_SWP_RCR(RAR_IDX(rar)),
p);
return 0;
}
/*******************/
/* Buffer acquires */
/*******************/
/* These should be const, eventually */
static struct qb_attr_code code_acquire_bpid = QB_CODE(0, 16, 16);
static struct qb_attr_code code_acquire_num = QB_CODE(1, 0, 3);
static struct qb_attr_code code_acquire_r_num = QB_CODE(1, 0, 3);
int qbman_swp_acquire(struct qbman_swp *s, uint32_t bpid, uint64_t *buffers,
unsigned int num_buffers)
{
uint32_t *p;
uint32_t verb, rslt, num;
BUG_ON(!num_buffers || (num_buffers > 7));
/* Start the management command */
p = qbman_swp_mc_start(s);
if (!p)
return -EBUSY;
/* Encode the caller-provided attributes */
qb_attr_code_encode(&code_acquire_bpid, p, bpid);
qb_attr_code_encode(&code_acquire_num, p, num_buffers);
/* Complete the management command */
p = qbman_swp_mc_complete(s, p, p[0] | QBMAN_MC_ACQUIRE);
/* Decode the outcome */
verb = qb_attr_code_decode(&code_generic_verb, p);
rslt = qb_attr_code_decode(&code_generic_rslt, p);
num = qb_attr_code_decode(&code_acquire_r_num, p);
BUG_ON(verb != QBMAN_MC_ACQUIRE);
/* Determine success or failure */
if (unlikely(rslt != QBMAN_MC_RSLT_OK)) {
printf("Acquire buffers from BPID 0x%x failed, code=0x%02x\n",
bpid, rslt);
return -EIO;
}
BUG_ON(num > num_buffers);
/* Copy the acquired buffers to the caller's array */
u64_from_le32_copy(buffers, &p[2], num);
return (int)num;
}

View File

@@ -0,0 +1,167 @@
/*
* Copyright (C) 2014 Freescale Semiconductor
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include "qbman_private.h"
#include <fsl-mc/fsl_qbman_portal.h>
#include <fsl-mc/fsl_dpaa_fd.h>
/* All QBMan command and result structures use this "valid bit" encoding */
#define QB_VALID_BIT ((uint32_t)0x80)
/* Management command result codes */
#define QBMAN_MC_RSLT_OK 0xf0
/* TBD: as of QBMan 4.1, DQRR will be 8 rather than 4! */
#define QBMAN_DQRR_SIZE 4
/* --------------------- */
/* portal data structure */
/* --------------------- */
struct qbman_swp {
const struct qbman_swp_desc *desc;
/* The qbman_sys (ie. arch/OS-specific) support code can put anything it
* needs in here. */
struct qbman_swp_sys sys;
/* Management commands */
struct {
#ifdef QBMAN_CHECKING
enum swp_mc_check {
swp_mc_can_start, /* call __qbman_swp_mc_start() */
swp_mc_can_submit, /* call __qbman_swp_mc_submit() */
swp_mc_can_poll, /* call __qbman_swp_mc_result() */
} check;
#endif
uint32_t valid_bit; /* 0x00 or 0x80 */
} mc;
/* Push dequeues */
uint32_t sdq;
/* Volatile dequeues */
struct {
/* VDQCR supports a "1 deep pipeline", meaning that if you know
* the last-submitted command is already executing in the
* hardware (as evidenced by at least 1 valid dequeue result),
* you can write another dequeue command to the register, the
* hardware will start executing it as soon as the
* already-executing command terminates. (This minimises latency
* and stalls.) With that in mind, this "busy" variable refers
* to whether or not a command can be submitted, not whether or
* not a previously-submitted command is still executing. In
* other words, once proof is seen that the previously-submitted
* command is executing, "vdq" is no longer "busy".
*/
atomic_t busy;
uint32_t valid_bit; /* 0x00 or 0x80 */
/* We need to determine when vdq is no longer busy. This depends
* on whether the "busy" (last-submitted) dequeue command is
* targeting DQRR or main-memory, and detected is based on the
* presence of the dequeue command's "token" showing up in
* dequeue entries in DQRR or main-memory (respectively). Debug
* builds will, when submitting vdq commands, verify that the
* dequeue result location is not already equal to the command's
* token value. */
struct ldpaa_dq *storage; /* NULL if DQRR */
uint32_t token;
} vdq;
/* DQRR */
struct {
uint32_t next_idx;
uint32_t valid_bit;
} dqrr;
};
/* -------------------------- */
/* portal management commands */
/* -------------------------- */
/* Different management commands all use this common base layer of code to issue
* commands and poll for results. The first function returns a pointer to where
* the caller should fill in their MC command (though they should ignore the
* verb byte), the second function commits merges in the caller-supplied command
* verb (which should not include the valid-bit) and submits the command to
* hardware, and the third function checks for a completed response (returns
* non-NULL if only if the response is complete). */
void *qbman_swp_mc_start(struct qbman_swp *p);
void qbman_swp_mc_submit(struct qbman_swp *p, void *cmd, uint32_t cmd_verb);
void *qbman_swp_mc_result(struct qbman_swp *p);
/* Wraps up submit + poll-for-result */
static inline void *qbman_swp_mc_complete(struct qbman_swp *swp, void *cmd,
uint32_t cmd_verb)
{
int loopvar;
qbman_swp_mc_submit(swp, cmd, cmd_verb);
DBG_POLL_START(loopvar);
do {
DBG_POLL_CHECK(loopvar);
cmd = qbman_swp_mc_result(swp);
} while (!cmd);
return cmd;
}
/* ------------ */
/* qb_attr_code */
/* ------------ */
/* This struct locates a sub-field within a QBMan portal (CENA) cacheline which
* is either serving as a configuration command or a query result. The
* representation is inherently little-endian, as the indexing of the words is
* itself little-endian in nature and layerscape is little endian for anything
* that crosses a word boundary too (64-bit fields are the obvious examples).
*/
struct qb_attr_code {
unsigned int word; /* which uint32_t[] array member encodes the field */
unsigned int lsoffset; /* encoding offset from ls-bit */
unsigned int width; /* encoding width. (bool must be 1.) */
};
/* Macros to define codes */
#define QB_CODE(a, b, c) { a, b, c}
/* decode a field from a cacheline */
static inline uint32_t qb_attr_code_decode(const struct qb_attr_code *code,
const uint32_t *cacheline)
{
return d32_uint32_t(code->lsoffset, code->width, cacheline[code->word]);
}
/* encode a field to a cacheline */
static inline void qb_attr_code_encode(const struct qb_attr_code *code,
uint32_t *cacheline, uint32_t val)
{
cacheline[code->word] =
r32_uint32_t(code->lsoffset, code->width, cacheline[code->word])
| e32_uint32_t(code->lsoffset, code->width, val);
}
static inline void qb_attr_code_encode_64(const struct qb_attr_code *code,
uint64_t *cacheline, uint64_t val)
{
cacheline[code->word / 2] = val;
}
/* ---------------------- */
/* Descriptors/cachelines */
/* ---------------------- */
/* To avoid needless dynamic allocation, the driver API often gives the caller
* a "descriptor" type that the caller can instantiate however they like.
* Ultimately though, it is just a cacheline of binary storage (or something
* smaller when it is known that the descriptor doesn't need all 64 bytes) for
* holding pre-formatted pieces of hardware commands. The performance-critical
* code can then copy these descriptors directly into hardware command
* registers more efficiently than trying to construct/format commands
* on-the-fly. The API user sees the descriptor as an array of 32-bit words in
* order for the compiler to know its size, but the internal details are not
* exposed. The following macro is used within the driver for converting *any*
* descriptor pointer to a usable array pointer. The use of a macro (instead of
* an inline) is necessary to work with different descriptor types and to work
* correctly with const and non-const inputs (and similarly-qualified outputs).
*/
#define qb_cl(d) (&(d)->dont_manipulate_directly[0])

View File

@@ -0,0 +1,169 @@
/*
* Copyright (C) 2014 Freescale Semiconductor
*
* SPDX-License-Identifier: GPL-2.0+
*/
/* Perform extra checking */
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#include <linux/types.h>
#include <asm/atomic.h>
#include <malloc.h>
#include <fsl-mc/fsl_qbman_base.h>
#define QBMAN_CHECKING
/* Any time there is a register interface which we poll on, this provides a
* "break after x iterations" scheme for it. It's handy for debugging, eg.
* where you don't want millions of lines of log output from a polling loop
* that won't, because such things tend to drown out the earlier log output
* that might explain what caused the problem. (NB: put ";" after each macro!)
* TODO: we should probably remove this once we're done sanitising the
* simulator...
*/
#define DBG_POLL_START(loopvar) (loopvar = 10)
#define DBG_POLL_CHECK(loopvar) \
do {if (!(loopvar--)) BUG_ON(NULL == "DBG_POLL_CHECK"); } while (0)
/* For CCSR or portal-CINH registers that contain fields at arbitrary offsets
* and widths, these macro-generated encode/decode/isolate/remove inlines can
* be used.
*
* Eg. to "d"ecode a 14-bit field out of a register (into a "uint16_t" type),
* where the field is located 3 bits "up" from the least-significant bit of the
* register (ie. the field location within the 32-bit register corresponds to a
* mask of 0x0001fff8), you would do;
* uint16_t field = d32_uint16_t(3, 14, reg_value);
*
* Or to "e"ncode a 1-bit boolean value (input type is "int", zero is FALSE,
* non-zero is TRUE, so must convert all non-zero inputs to 1, hence the "!!"
* operator) into a register at bit location 0x00080000 (19 bits "in" from the
* LS bit), do;
* reg_value |= e32_int(19, 1, !!field);
*
* If you wish to read-modify-write a register, such that you leave the 14-bit
* field as-is but have all other fields set to zero, then "i"solate the 14-bit
* value using;
* reg_value = i32_uint16_t(3, 14, reg_value);
*
* Alternatively, you could "r"emove the 1-bit boolean field (setting it to
* zero) but leaving all other fields as-is;
* reg_val = r32_int(19, 1, reg_value);
*
*/
#define MAKE_MASK32(width) (width == 32 ? 0xffffffff : \
(uint32_t)((1 << width) - 1))
#define DECLARE_CODEC32(t) \
static inline uint32_t e32_##t(uint32_t lsoffset, uint32_t width, t val) \
{ \
BUG_ON(width > (sizeof(t) * 8)); \
return ((uint32_t)val & MAKE_MASK32(width)) << lsoffset; \
} \
static inline t d32_##t(uint32_t lsoffset, uint32_t width, uint32_t val) \
{ \
BUG_ON(width > (sizeof(t) * 8)); \
return (t)((val >> lsoffset) & MAKE_MASK32(width)); \
} \
static inline uint32_t i32_##t(uint32_t lsoffset, uint32_t width, \
uint32_t val) \
{ \
BUG_ON(width > (sizeof(t) * 8)); \
return e32_##t(lsoffset, width, d32_##t(lsoffset, width, val)); \
} \
static inline uint32_t r32_##t(uint32_t lsoffset, uint32_t width, \
uint32_t val) \
{ \
BUG_ON(width > (sizeof(t) * 8)); \
return ~(MAKE_MASK32(width) << lsoffset) & val; \
}
DECLARE_CODEC32(uint32_t)
DECLARE_CODEC32(uint16_t)
DECLARE_CODEC32(uint8_t)
DECLARE_CODEC32(int)
/*********************/
/* Debugging assists */
/*********************/
static inline void __hexdump(unsigned long start, unsigned long end,
unsigned long p, size_t sz, const unsigned char *c)
{
while (start < end) {
unsigned int pos = 0;
char buf[64];
int nl = 0;
pos += sprintf(buf + pos, "%08lx: ", start);
do {
if ((start < p) || (start >= (p + sz)))
pos += sprintf(buf + pos, "..");
else
pos += sprintf(buf + pos, "%02x", *(c++));
if (!(++start & 15)) {
buf[pos++] = '\n';
nl = 1;
} else {
nl = 0;
if (!(start & 1))
buf[pos++] = ' ';
if (!(start & 3))
buf[pos++] = ' ';
}
} while (start & 15);
if (!nl)
buf[pos++] = '\n';
buf[pos] = '\0';
debug("%s", buf);
}
}
static inline void hexdump(const void *ptr, size_t sz)
{
unsigned long p = (unsigned long)ptr;
unsigned long start = p & ~(unsigned long)15;
unsigned long end = (p + sz + 15) & ~(unsigned long)15;
const unsigned char *c = ptr;
__hexdump(start, end, p, sz, c);
}
#if defined(__BIG_ENDIAN)
#define DQRR_TOK_OFFSET 0
#else
#define DQRR_TOK_OFFSET 24
#endif
/* Similarly-named functions */
#define upper32(a) upper_32_bits(a)
#define lower32(a) lower_32_bits(a)
/****************/
/* arch assists */
/****************/
static inline void dcbz(void *ptr)
{
uint32_t *p = ptr;
BUG_ON((unsigned long)ptr & 63);
p[0] = 0;
p[1] = 0;
p[2] = 0;
p[3] = 0;
p[4] = 0;
p[5] = 0;
p[6] = 0;
p[7] = 0;
p[8] = 0;
p[9] = 0;
p[10] = 0;
p[11] = 0;
p[12] = 0;
p[13] = 0;
p[14] = 0;
p[15] = 0;
}
#define lwsync()
#include "qbman_sys.h"

View File

@@ -0,0 +1,290 @@
/*
* Copyright (C) 2014 Freescale Semiconductor
*
* SPDX-License-Identifier: GPL-2.0+
*/
/* qbman_sys_decl.h and qbman_sys.h are the two platform-specific files in the
* driver. They are only included via qbman_private.h, which is itself a
* platform-independent file and is included by all the other driver source.
*
* qbman_sys_decl.h is included prior to all other declarations and logic, and
* it exists to provide compatibility with any linux interfaces our
* single-source driver code is dependent on (eg. kmalloc). Ie. this file
* provides linux compatibility.
*
* This qbman_sys.h header, on the other hand, is included *after* any common
* and platform-neutral declarations and logic in qbman_private.h, and exists to
* implement any platform-specific logic of the qbman driver itself. Ie. it is
* *not* to provide linux compatibility.
*/
/* Trace the 3 different classes of read/write access to QBMan. #undef as
* required. */
#undef QBMAN_CCSR_TRACE
#undef QBMAN_CINH_TRACE
#undef QBMAN_CENA_TRACE
/* Temporarily define this to get around the fact that cache enabled mapping is
* not working right now. Will remove this after uboot could map the cache
* enabled portal memory.
*/
#define QBMAN_CINH_ONLY
static inline void word_copy(void *d, const void *s, unsigned int cnt)
{
uint32_t *dd = d;
const uint32_t *ss = s;
while (cnt--)
*(dd++) = *(ss++);
}
/* Currently, the CENA support code expects each 32-bit word to be written in
* host order, and these are converted to hardware (little-endian) order on
* command submission. However, 64-bit quantities are must be written (and read)
* as two 32-bit words with the least-significant word first, irrespective of
* host endianness. */
static inline void u64_to_le32_copy(void *d, const uint64_t *s,
unsigned int cnt)
{
uint32_t *dd = d;
const uint32_t *ss = (const uint32_t *)s;
while (cnt--) {
/* TBD: the toolchain was choking on the use of 64-bit types up
* until recently so this works entirely with 32-bit variables.
* When 64-bit types become usable again, investigate better
* ways of doing this. */
#if defined(__BIG_ENDIAN)
*(dd++) = ss[1];
*(dd++) = ss[0];
ss += 2;
#else
*(dd++) = *(ss++);
*(dd++) = *(ss++);
#endif
}
}
static inline void u64_from_le32_copy(uint64_t *d, const void *s,
unsigned int cnt)
{
const uint32_t *ss = s;
uint32_t *dd = (uint32_t *)d;
while (cnt--) {
#if defined(__BIG_ENDIAN)
dd[1] = *(ss++);
dd[0] = *(ss++);
dd += 2;
#else
*(dd++) = *(ss++);
*(dd++) = *(ss++);
#endif
}
}
/* Convert a host-native 32bit value into little endian */
#if defined(__BIG_ENDIAN)
static inline uint32_t make_le32(uint32_t val)
{
return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
}
#else
#define make_le32(val) (val)
#endif
static inline void make_le32_n(uint32_t *val, unsigned int num)
{
while (num--) {
*val = make_le32(*val);
val++;
}
}
/******************/
/* Portal access */
/******************/
struct qbman_swp_sys {
/* On GPP, the sys support for qbman_swp is here. The CENA region isi
* not an mmap() of the real portal registers, but an allocated
* place-holder, because the actual writes/reads to/from the portal are
* marshalled from these allocated areas using QBMan's "MC access
* registers". CINH accesses are atomic so there's no need for a
* place-holder. */
void *cena;
void __iomem *addr_cena;
void __iomem *addr_cinh;
};
/* P_OFFSET is (ACCESS_CMD,0,12) - offset within the portal
* C is (ACCESS_CMD,12,1) - is inhibited? (0==CENA, 1==CINH)
* SWP_IDX is (ACCESS_CMD,16,10) - Software portal index
* P is (ACCESS_CMD,28,1) - (0==special portal, 1==any portal)
* T is (ACCESS_CMD,29,1) - Command type (0==READ, 1==WRITE)
* E is (ACCESS_CMD,31,1) - Command execute (1 to issue, poll for 0==complete)
*/
static inline void qbman_cinh_write(struct qbman_swp_sys *s, uint32_t offset,
uint32_t val)
{
__raw_writel(val, s->addr_cinh + offset);
#ifdef QBMAN_CINH_TRACE
pr_info("qbman_cinh_write(%p:0x%03x) 0x%08x\n",
s->addr_cinh, offset, val);
#endif
}
static inline uint32_t qbman_cinh_read(struct qbman_swp_sys *s, uint32_t offset)
{
uint32_t reg = __raw_readl(s->addr_cinh + offset);
#ifdef QBMAN_CINH_TRACE
pr_info("qbman_cinh_read(%p:0x%03x) 0x%08x\n",
s->addr_cinh, offset, reg);
#endif
return reg;
}
static inline void *qbman_cena_write_start(struct qbman_swp_sys *s,
uint32_t offset)
{
void *shadow = s->cena + offset;
#ifdef QBMAN_CENA_TRACE
pr_info("qbman_cena_write_start(%p:0x%03x) %p\n",
s->addr_cena, offset, shadow);
#endif
BUG_ON(offset & 63);
dcbz(shadow);
return shadow;
}
static inline void qbman_cena_write_complete(struct qbman_swp_sys *s,
uint32_t offset, void *cmd)
{
const uint32_t *shadow = cmd;
int loop;
#ifdef QBMAN_CENA_TRACE
pr_info("qbman_cena_write_complete(%p:0x%03x) %p\n",
s->addr_cena, offset, shadow);
hexdump(cmd, 64);
#endif
for (loop = 15; loop >= 0; loop--)
#ifdef QBMAN_CINH_ONLY
__raw_writel(shadow[loop], s->addr_cinh +
offset + loop * 4);
#else
__raw_writel(shadow[loop], s->addr_cena +
offset + loop * 4);
#endif
}
static inline void *qbman_cena_read(struct qbman_swp_sys *s, uint32_t offset)
{
uint32_t *shadow = s->cena + offset;
unsigned int loop;
#ifdef QBMAN_CENA_TRACE
pr_info("qbman_cena_read(%p:0x%03x) %p\n",
s->addr_cena, offset, shadow);
#endif
for (loop = 0; loop < 16; loop++)
#ifdef QBMAN_CINH_ONLY
shadow[loop] = __raw_readl(s->addr_cinh + offset
+ loop * 4);
#else
shadow[loop] = __raw_readl(s->addr_cena + offset
+ loop * 4);
#endif
#ifdef QBMAN_CENA_TRACE
hexdump(shadow, 64);
#endif
return shadow;
}
static inline void qbman_cena_invalidate_prefetch(struct qbman_swp_sys *s,
uint32_t offset)
{
}
/******************/
/* Portal support */
/******************/
/* The SWP_CFG portal register is special, in that it is used by the
* platform-specific code rather than the platform-independent code in
* qbman_portal.c. So use of it is declared locally here. */
#define QBMAN_CINH_SWP_CFG 0xd00
/* For MC portal use, we always configure with
* DQRR_MF is (SWP_CFG,20,3) - DQRR max fill (<- 0x4)
* EST is (SWP_CFG,16,3) - EQCR_CI stashing threshold (<- 0x0)
* RPM is (SWP_CFG,12,2) - RCR production notification mode (<- 0x3)
* DCM is (SWP_CFG,10,2) - DQRR consumption notification mode (<- 0x2)
* EPM is (SWP_CFG,8,2) - EQCR production notification mode (<- 0x3)
* SD is (SWP_CFG,5,1) - memory stashing drop enable (<- FALSE)
* SP is (SWP_CFG,4,1) - memory stashing priority (<- TRUE)
* SE is (SWP_CFG,3,1) - memory stashing enable (<- 0x0)
* DP is (SWP_CFG,2,1) - dequeue stashing priority (<- TRUE)
* DE is (SWP_CFG,1,1) - dequeue stashing enable (<- 0x0)
* EP is (SWP_CFG,0,1) - EQCR_CI stashing priority (<- FALSE)
*/
static inline uint32_t qbman_set_swp_cfg(uint8_t max_fill, uint8_t wn,
uint8_t est, uint8_t rpm, uint8_t dcm,
uint8_t epm, int sd, int sp, int se,
int dp, int de, int ep)
{
uint32_t reg;
reg = e32_uint8_t(20, 3, max_fill) | e32_uint8_t(16, 3, est) |
e32_uint8_t(12, 2, rpm) | e32_uint8_t(10, 2, dcm) |
e32_uint8_t(8, 2, epm) | e32_int(5, 1, sd) |
e32_int(4, 1, sp) | e32_int(3, 1, se) | e32_int(2, 1, dp) |
e32_int(1, 1, de) | e32_int(0, 1, ep) | e32_uint8_t(14, 1, wn);
return reg;
}
static inline int qbman_swp_sys_init(struct qbman_swp_sys *s,
const struct qbman_swp_desc *d)
{
uint32_t reg;
s->addr_cena = d->cena_bar;
s->addr_cinh = d->cinh_bar;
s->cena = (void *)valloc(CONFIG_SYS_PAGE_SIZE);
if (!s->cena) {
printf("Could not allocate page for cena shadow\n");
return -1;
}
memset((void *)s->cena, 0x00, CONFIG_SYS_PAGE_SIZE);
#ifdef QBMAN_CHECKING
/* We should never be asked to initialise for a portal that isn't in
* the power-on state. (Ie. don't forget to reset portals when they are
* decommissioned!)
*/
reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG);
BUG_ON(reg);
#endif
#ifdef QBMAN_CINH_ONLY
reg = qbman_set_swp_cfg(4, 1, 0, 3, 2, 3, 0, 1, 0, 1, 0, 0);
#else
reg = qbman_set_swp_cfg(4, 0, 0, 3, 2, 3, 0, 1, 0, 1, 0, 0);
#endif
qbman_cinh_write(s, QBMAN_CINH_SWP_CFG, reg);
reg = qbman_cinh_read(s, QBMAN_CINH_SWP_CFG);
if (!reg) {
printf("The portal is not enabled!\n");
free(s->cena);
return -1;
}
return 0;
}
static inline void qbman_swp_sys_finish(struct qbman_swp_sys *s)
{
free((void *)s->cena);
}

View File

@@ -0,0 +1,222 @@
/*
* Freescale Layerscape MC I/O wrapper
*
* Copyright (C) 2015 Freescale Semiconductor, Inc.
* Author: Prabhakar Kushwaha <prabhakar@freescale.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpmac.h>
int dpmac_open(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
int dpmac_id,
uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_OPEN,
cmd_flags,
0);
DPMAC_CMD_OPEN(cmd, dpmac_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 dpmac_close(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CLOSE, cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmac_create(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
const struct dpmac_cfg *cfg,
uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_CREATE,
cmd_flags,
0);
DPMAC_CMD_CREATE(cmd, cfg);
/* 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 dpmac_destroy(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_DESTROY,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmac_get_attributes(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpmac_attr *attr)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_ATTR,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPMAC_RSP_GET_ATTRIBUTES(cmd, attr);
return 0;
}
int dpmac_mdio_read(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpmac_mdio_cfg *cfg)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_READ,
cmd_flags,
token);
DPMAC_CMD_MDIO_READ(cmd, cfg);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPMAC_RSP_MDIO_READ(cmd, cfg->data);
return 0;
}
int dpmac_mdio_write(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpmac_mdio_cfg *cfg)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_MDIO_WRITE,
cmd_flags,
token);
DPMAC_CMD_MDIO_WRITE(cmd, cfg);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmac_get_link_cfg(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpmac_link_cfg *cfg)
{
struct mc_command cmd = { 0 };
int err = 0;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_LINK_CFG,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
DPMAC_RSP_GET_LINK_CFG(cmd, cfg);
return 0;
}
int dpmac_set_link_state(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpmac_link_state *link_state)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_SET_LINK_STATE,
cmd_flags,
token);
DPMAC_CMD_SET_LINK_STATE(cmd, link_state);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpmac_get_counter(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
enum dpmac_counter type,
uint64_t *counter)
{
struct mc_command cmd = { 0 };
int err = 0;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMAC_CMDID_GET_COUNTER,
cmd_flags,
token);
DPMAC_CMD_GET_COUNTER(cmd, type);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
DPMAC_RSP_GET_COUNTER(cmd, *counter);
return 0;
}

View File

@@ -0,0 +1,31 @@
/* Copyright 2013-2015 Freescale Semiconductor Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpmng.h>
#include "fsl_dpmng_cmd.h"
int mc_get_version(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
struct mc_version *mc_ver_info)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPMNG_CMDID_GET_VERSION,
cmd_flags,
0);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPMNG_RSP_GET_VERSION(cmd, mc_ver_info);
return 0;
}

View File

@@ -0,0 +1,685 @@
/*
* Copyright (C) 2013-2015 Freescale Semiconductor
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dpni.h>
int dpni_prepare_extended_cfg(const struct dpni_extended_cfg *cfg,
uint8_t *ext_cfg_buf)
{
uint64_t *ext_params = (uint64_t *)ext_cfg_buf;
DPNI_PREP_EXTENDED_CFG(ext_params, cfg);
return 0;
}
int dpni_extract_extended_cfg(struct dpni_extended_cfg *cfg,
const uint8_t *ext_cfg_buf)
{
uint64_t *ext_params = (uint64_t *)ext_cfg_buf;
DPNI_EXT_EXTENDED_CFG(ext_params, cfg);
return 0;
}
int dpni_open(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
int dpni_id,
uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_OPEN,
cmd_flags,
0);
DPNI_CMD_OPEN(cmd, dpni_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 dpni_close(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_CLOSE,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_create(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
const struct dpni_cfg *cfg,
uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_CREATE,
cmd_flags,
0);
DPNI_CMD_CREATE(cmd, cfg);
/* 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 dpni_destroy(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_DESTROY,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_set_pools(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const struct dpni_pools_cfg *cfg)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_POOLS,
cmd_flags,
token);
DPNI_CMD_SET_POOLS(cmd, cfg);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_enable(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_ENABLE,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_disable(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_DISABLE,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_reset(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_RESET,
cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_get_attributes(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpni_attr *attr)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_ATTR,
cmd_flags,
token);
DPNI_CMD_GET_ATTR(cmd, attr);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_ATTR(cmd, attr);
return 0;
}
int dpni_set_errors_behavior(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpni_error_cfg *cfg)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_ERRORS_BEHAVIOR,
cmd_flags,
token);
DPNI_CMD_SET_ERRORS_BEHAVIOR(cmd, cfg);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_get_rx_buffer_layout(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpni_buffer_layout *layout)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_BUFFER_LAYOUT,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_RX_BUFFER_LAYOUT(cmd, layout);
return 0;
}
int dpni_set_rx_buffer_layout(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const struct dpni_buffer_layout *layout)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_BUFFER_LAYOUT,
cmd_flags,
token);
DPNI_CMD_SET_RX_BUFFER_LAYOUT(cmd, layout);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_get_tx_buffer_layout(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpni_buffer_layout *layout)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_BUFFER_LAYOUT,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_TX_BUFFER_LAYOUT(cmd, layout);
return 0;
}
int dpni_set_tx_buffer_layout(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const struct dpni_buffer_layout *layout)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_BUFFER_LAYOUT,
cmd_flags,
token);
DPNI_CMD_SET_TX_BUFFER_LAYOUT(cmd, layout);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_get_tx_conf_buffer_layout(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpni_buffer_layout *layout)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF_BUFFER_LAYOUT,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_TX_CONF_BUFFER_LAYOUT(cmd, layout);
return 0;
}
int dpni_set_tx_conf_buffer_layout(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const struct dpni_buffer_layout *layout)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF_BUFFER_LAYOUT,
cmd_flags,
token);
DPNI_CMD_SET_TX_CONF_BUFFER_LAYOUT(cmd, layout);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_get_qdid(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint16_t *qdid)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_QDID,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_QDID(cmd, *qdid);
return 0;
}
int dpni_get_tx_data_offset(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint16_t *data_offset)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_DATA_OFFSET,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_TX_DATA_OFFSET(cmd, *data_offset);
return 0;
}
int dpni_get_counter(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
enum dpni_counter counter,
uint64_t *value)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_COUNTER,
cmd_flags,
token);
DPNI_CMD_GET_COUNTER(cmd, counter);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_COUNTER(cmd, *value);
return 0;
}
int dpni_set_counter(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
enum dpni_counter counter,
uint64_t value)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_COUNTER,
cmd_flags,
token);
DPNI_CMD_SET_COUNTER(cmd, counter, value);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_set_link_cfg(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const struct dpni_link_cfg *cfg)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_LINK_CFG,
cmd_flags,
token);
DPNI_CMD_SET_LINK_CFG(cmd, cfg);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_get_link_state(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dpni_link_state *state)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_LINK_STATE,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_LINK_STATE(cmd, state);
return 0;
}
int dpni_set_primary_mac_addr(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const uint8_t mac_addr[6])
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_PRIM_MAC,
cmd_flags,
token);
DPNI_CMD_SET_PRIMARY_MAC_ADDR(cmd, mac_addr);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_get_primary_mac_addr(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t mac_addr[6])
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_PRIM_MAC,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_PRIMARY_MAC_ADDR(cmd, mac_addr);
return 0;
}
int dpni_add_mac_addr(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const uint8_t mac_addr[6])
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_ADD_MAC_ADDR,
cmd_flags,
token);
DPNI_CMD_ADD_MAC_ADDR(cmd, mac_addr);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_remove_mac_addr(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const uint8_t mac_addr[6])
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_REMOVE_MAC_ADDR,
cmd_flags,
token);
DPNI_CMD_REMOVE_MAC_ADDR(cmd, mac_addr);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_set_tx_flow(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint16_t *flow_id,
const struct dpni_tx_flow_cfg *cfg)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_FLOW,
cmd_flags,
token);
DPNI_CMD_SET_TX_FLOW(cmd, *flow_id, cfg);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_SET_TX_FLOW(cmd, *flow_id);
return 0;
}
int dpni_get_tx_flow(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint16_t flow_id,
struct dpni_tx_flow_attr *attr)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_FLOW,
cmd_flags,
token);
DPNI_CMD_GET_TX_FLOW(cmd, flow_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_TX_FLOW(cmd, attr);
return 0;
}
int dpni_set_rx_flow(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t tc_id,
uint16_t flow_id,
const struct dpni_queue_cfg *cfg)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_RX_FLOW,
cmd_flags,
token);
DPNI_CMD_SET_RX_FLOW(cmd, tc_id, flow_id, cfg);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_get_rx_flow(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint8_t tc_id,
uint16_t flow_id,
struct dpni_queue_attr *attr)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_RX_FLOW,
cmd_flags,
token);
DPNI_CMD_GET_RX_FLOW(cmd, tc_id, flow_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPNI_RSP_GET_RX_FLOW(cmd, attr);
return 0;
}
int dpni_set_tx_conf(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint16_t flow_id,
const struct dpni_tx_conf_cfg *cfg)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_SET_TX_CONF,
cmd_flags,
token);
DPNI_CMD_SET_TX_CONF(cmd, flow_id, cfg);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dpni_get_tx_conf(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
uint16_t flow_id,
struct dpni_tx_conf_attr *attr)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPNI_CMDID_GET_TX_CONF,
cmd_flags,
token);
DPNI_CMD_GET_TX_CONF(cmd, flow_id);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
DPNI_RSP_GET_TX_CONF(cmd, attr);
return 0;
}

View File

@@ -0,0 +1,355 @@
/*
* Freescale Layerscape MC I/O wrapper
*
* Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
* Author: German Rivera <German.Rivera@freescale.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <fsl-mc/fsl_dprc.h>
int dprc_get_container_id(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
int *container_id)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONT_ID,
cmd_flags,
0);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPRC_RSP_GET_CONTAINER_ID(cmd, *container_id);
return 0;
}
int dprc_open(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
int container_id,
uint16_t *token)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_OPEN, cmd_flags,
0);
DPRC_CMD_OPEN(cmd, container_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 dprc_close(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_CLOSE, cmd_flags,
token);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dprc_create_container(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dprc_cfg *cfg,
int *child_container_id,
uint64_t *child_portal_paddr)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
DPRC_CMD_CREATE_CONTAINER(cmd, cfg);
cmd.header = mc_encode_cmd_header(DPRC_CMDID_CREATE_CONT,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPRC_RSP_CREATE_CONTAINER(cmd, *child_container_id,
*child_portal_paddr);
return 0;
}
int dprc_destroy_container(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
int child_container_id)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_DESTROY_CONT,
cmd_flags,
token);
DPRC_CMD_DESTROY_CONTAINER(cmd, child_container_id);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dprc_reset_container(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
int child_container_id)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_RESET_CONT,
cmd_flags,
token);
DPRC_CMD_RESET_CONTAINER(cmd, child_container_id);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dprc_get_attributes(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
struct dprc_attributes *attr)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_ATTR,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPRC_RSP_GET_ATTRIBUTES(cmd, attr);
return 0;
}
int dprc_get_obj_count(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
int *obj_count)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_COUNT,
cmd_flags,
token);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPRC_RSP_GET_OBJ_COUNT(cmd, *obj_count);
return 0;
}
int dprc_get_obj(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
int obj_index,
struct dprc_obj_desc *obj_desc)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ,
cmd_flags,
token);
DPRC_CMD_GET_OBJ(cmd, obj_index);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPRC_RSP_GET_OBJ(cmd, obj_desc);
return 0;
}
int dprc_get_res_count(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
char *type,
int *res_count)
{
struct mc_command cmd = { 0 };
int err;
*res_count = 0;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_COUNT,
cmd_flags,
token);
DPRC_CMD_GET_RES_COUNT(cmd, type);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPRC_RSP_GET_RES_COUNT(cmd, *res_count);
return 0;
}
int dprc_get_res_ids(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
char *type,
struct dprc_res_ids_range_desc *range_desc)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_RES_IDS,
cmd_flags,
token);
DPRC_CMD_GET_RES_IDS(cmd, range_desc, type);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPRC_RSP_GET_RES_IDS(cmd, range_desc);
return 0;
}
int dprc_get_obj_region(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
char *obj_type,
int obj_id,
uint8_t region_index,
struct dprc_region_desc *region_desc)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_OBJ_REG,
cmd_flags,
token);
DPRC_CMD_GET_OBJ_REGION(cmd, obj_type, obj_id, region_index);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPRC_RSP_GET_OBJ_REGION(cmd, region_desc);
return 0;
}
int dprc_connect(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const struct dprc_endpoint *endpoint1,
const struct dprc_endpoint *endpoint2,
const struct dprc_connection_cfg *cfg)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_CONNECT,
cmd_flags,
token);
DPRC_CMD_CONNECT(cmd, endpoint1, endpoint2, cfg);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dprc_disconnect(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const struct dprc_endpoint *endpoint)
{
struct mc_command cmd = { 0 };
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_DISCONNECT,
cmd_flags,
token);
DPRC_CMD_DISCONNECT(cmd, endpoint);
/* send command to mc*/
return mc_send_command(mc_io, &cmd);
}
int dprc_get_connection(struct fsl_mc_io *mc_io,
uint32_t cmd_flags,
uint16_t token,
const struct dprc_endpoint *endpoint1,
struct dprc_endpoint *endpoint2,
int *state)
{
struct mc_command cmd = { 0 };
int err;
/* prepare command */
cmd.header = mc_encode_cmd_header(DPRC_CMDID_GET_CONNECTION,
cmd_flags,
token);
DPRC_CMD_GET_CONNECTION(cmd, endpoint1);
/* send command to mc*/
err = mc_send_command(mc_io, &cmd);
if (err)
return err;
/* retrieve response parameters */
DPRC_RSP_GET_CONNECTION(cmd, endpoint2, *state);
return 0;
}

View File

@@ -0,0 +1,19 @@
/* Copyright 2013-2015 Freescale Semiconductor Inc.
*
* SPDX-License-Identifier: GPL-2.0+
*/
#ifndef __FSL_DPMNG_CMD_H
#define __FSL_DPMNG_CMD_H
/* Command IDs */
#define DPMNG_CMDID_GET_VERSION 0x831
/* cmd, param, offset, width, type, arg_name */
#define DPMNG_RSP_GET_VERSION(cmd, mc_ver_info) \
do { \
MC_RSP_OP(cmd, 0, 0, 32, uint32_t, mc_ver_info->revision); \
MC_RSP_OP(cmd, 0, 32, 32, uint32_t, mc_ver_info->major); \
MC_RSP_OP(cmd, 1, 0, 32, uint32_t, mc_ver_info->minor); \
} while (0)
#endif /* __FSL_DPMNG_CMD_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,63 @@
/*
* Freescale Layerscape MC I/O wrapper
*
* Copyright (C) 2013-2015 Freescale Semiconductor, Inc.
* Author: German Rivera <German.Rivera@freescale.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <fsl-mc/fsl_mc_sys.h>
#include <fsl-mc/fsl_mc_cmd.h>
#include <common.h>
#include <errno.h>
#include <asm/io.h>
#define MC_CMD_HDR_READ_CMDID(_hdr) \
((uint16_t)mc_dec((_hdr), MC_CMD_HDR_CMDID_O, MC_CMD_HDR_CMDID_S))
/**
* mc_send_command - Send MC command and wait for response
*
* @mc_io: Pointer to MC I/O object to be used
* @cmd: MC command buffer. On input, it contains the command to send to the MC.
* On output, it contains the response from the MC if any.
*
* Depending on the sharing option specified when creating the MC portal
* wrapper, this function will use a spinlock or mutex to ensure exclusive
* access to the MC portal from the point when the command is sent until a
* response is received from the MC.
*/
int mc_send_command(struct fsl_mc_io *mc_io,
struct mc_command *cmd)
{
enum mc_cmd_status status;
int timeout = 12000;
mc_write_command(mc_io->mmio_regs, cmd);
for ( ; ; ) {
status = mc_read_response(mc_io->mmio_regs, cmd);
if (status != MC_CMD_STATUS_READY)
break;
if (--timeout == 0) {
printf("Error: Timeout waiting for MC response\n");
return -ETIMEDOUT;
}
udelay(500);
}
if (status != MC_CMD_STATUS_OK) {
printf("Error: MC command failed (portal: %p, obj handle: %#x, command: %#x, status: %#x)\n",
mc_io->mmio_regs,
(unsigned int)MC_CMD_HDR_READ_TOKEN(cmd->header),
(unsigned int)MC_CMD_HDR_READ_CMDID(cmd->header),
(unsigned int)status);
return -EIO;
}
return 0;
}