162306a36Sopenharmony_ci/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright 2013-2016 Freescale Semiconductor, Inc.
462306a36Sopenharmony_ci * Copyright 2016-2017 NXP
562306a36Sopenharmony_ci */
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#ifndef __SG_SW_QM_H
862306a36Sopenharmony_ci#define __SG_SW_QM_H
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <soc/fsl/qman.h>
1162306a36Sopenharmony_ci#include "regs.h"
1262306a36Sopenharmony_ci
1362306a36Sopenharmony_cistatic inline void __dma_to_qm_sg(struct qm_sg_entry *qm_sg_ptr, dma_addr_t dma,
1462306a36Sopenharmony_ci				  u16 offset)
1562306a36Sopenharmony_ci{
1662306a36Sopenharmony_ci	qm_sg_entry_set64(qm_sg_ptr, dma);
1762306a36Sopenharmony_ci	qm_sg_ptr->__reserved2 = 0;
1862306a36Sopenharmony_ci	qm_sg_ptr->bpid = 0;
1962306a36Sopenharmony_ci	qm_sg_ptr->offset = cpu_to_be16(offset & QM_SG_OFF_MASK);
2062306a36Sopenharmony_ci}
2162306a36Sopenharmony_ci
2262306a36Sopenharmony_cistatic inline void dma_to_qm_sg_one(struct qm_sg_entry *qm_sg_ptr,
2362306a36Sopenharmony_ci				    dma_addr_t dma, u32 len, u16 offset)
2462306a36Sopenharmony_ci{
2562306a36Sopenharmony_ci	__dma_to_qm_sg(qm_sg_ptr, dma, offset);
2662306a36Sopenharmony_ci	qm_sg_entry_set_len(qm_sg_ptr, len);
2762306a36Sopenharmony_ci}
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_cistatic inline void dma_to_qm_sg_one_last(struct qm_sg_entry *qm_sg_ptr,
3062306a36Sopenharmony_ci					 dma_addr_t dma, u32 len, u16 offset)
3162306a36Sopenharmony_ci{
3262306a36Sopenharmony_ci	__dma_to_qm_sg(qm_sg_ptr, dma, offset);
3362306a36Sopenharmony_ci	qm_sg_entry_set_f(qm_sg_ptr, len);
3462306a36Sopenharmony_ci}
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_cistatic inline void dma_to_qm_sg_one_ext(struct qm_sg_entry *qm_sg_ptr,
3762306a36Sopenharmony_ci					dma_addr_t dma, u32 len, u16 offset)
3862306a36Sopenharmony_ci{
3962306a36Sopenharmony_ci	__dma_to_qm_sg(qm_sg_ptr, dma, offset);
4062306a36Sopenharmony_ci	qm_sg_ptr->cfg = cpu_to_be32(QM_SG_EXT | (len & QM_SG_LEN_MASK));
4162306a36Sopenharmony_ci}
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_cistatic inline void dma_to_qm_sg_one_last_ext(struct qm_sg_entry *qm_sg_ptr,
4462306a36Sopenharmony_ci					     dma_addr_t dma, u32 len,
4562306a36Sopenharmony_ci					     u16 offset)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci	__dma_to_qm_sg(qm_sg_ptr, dma, offset);
4862306a36Sopenharmony_ci	qm_sg_ptr->cfg = cpu_to_be32(QM_SG_EXT | QM_SG_FIN |
4962306a36Sopenharmony_ci				     (len & QM_SG_LEN_MASK));
5062306a36Sopenharmony_ci}
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci/*
5362306a36Sopenharmony_ci * convert scatterlist to h/w link table format
5462306a36Sopenharmony_ci * but does not have final bit; instead, returns last entry
5562306a36Sopenharmony_ci */
5662306a36Sopenharmony_cistatic inline struct qm_sg_entry *
5762306a36Sopenharmony_cisg_to_qm_sg(struct scatterlist *sg, int len,
5862306a36Sopenharmony_ci	    struct qm_sg_entry *qm_sg_ptr, u16 offset)
5962306a36Sopenharmony_ci{
6062306a36Sopenharmony_ci	int ent_len;
6162306a36Sopenharmony_ci
6262306a36Sopenharmony_ci	while (len) {
6362306a36Sopenharmony_ci		ent_len = min_t(int, sg_dma_len(sg), len);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci		dma_to_qm_sg_one(qm_sg_ptr, sg_dma_address(sg), ent_len,
6662306a36Sopenharmony_ci				 offset);
6762306a36Sopenharmony_ci		qm_sg_ptr++;
6862306a36Sopenharmony_ci		sg = sg_next(sg);
6962306a36Sopenharmony_ci		len -= ent_len;
7062306a36Sopenharmony_ci	}
7162306a36Sopenharmony_ci	return qm_sg_ptr - 1;
7262306a36Sopenharmony_ci}
7362306a36Sopenharmony_ci
7462306a36Sopenharmony_ci/*
7562306a36Sopenharmony_ci * convert scatterlist to h/w link table format
7662306a36Sopenharmony_ci * scatterlist must have been previously dma mapped
7762306a36Sopenharmony_ci */
7862306a36Sopenharmony_cistatic inline void sg_to_qm_sg_last(struct scatterlist *sg, int len,
7962306a36Sopenharmony_ci				    struct qm_sg_entry *qm_sg_ptr, u16 offset)
8062306a36Sopenharmony_ci{
8162306a36Sopenharmony_ci	qm_sg_ptr = sg_to_qm_sg(sg, len, qm_sg_ptr, offset);
8262306a36Sopenharmony_ci	qm_sg_entry_set_f(qm_sg_ptr, qm_sg_entry_get_len(qm_sg_ptr));
8362306a36Sopenharmony_ci}
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci#endif /* __SG_SW_QM_H */
86