Commit fe83df23 authored by Federico Vaga's avatar Federico Vaga

sw:drv: data from FPGA is always little-endian

The data coming out from the FMC-ADC-110M FPGA is always using the
little-endian byte order. This means that we need to fix the byte
order only on big-endian CPUs.

This allows to improve performances on SVEC-based designs since there
is no need anymore to fix the endianness in software becuase it is
already done in hardware.
Signed-off-by: Federico Vaga's avatarFederico Vaga <federico.vaga@cern.ch>
parent a7b1c459
......@@ -4,53 +4,40 @@
* Author: Federico Vaga <federico.vaga@cern.ch>
*/
#include <linux/kernel.h>
#include <linux/errno.h>
#include <linux/types.h>
#ifdef CONFIG_FMC_ADC_SVEC
#include "vmebus.h"
#endif
#include "fmc-adc-100m14b4cha-private.h"
/* Endianess */
#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 0
#endif
#ifndef BIG_ENDIAN
#define BIG_ENDIAN 1
#endif
static void zfad_dma_done(struct zio_cset *cset);
static int __get_endian(void)
{
int i = 1;
char *p = (char *)&i;
if (p[0] == 1)
return LITTLE_ENDIAN;
else
return BIG_ENDIAN;
}
/**
* Fix endianess from big to host endianess (32bit)
* Fix endianness from little to host endianess (32bit)
* @byte_lenght: number of bytes to fix (32bit aligned)
* @buffer: buffer to fix
*
* Data coming from the ADC IP-CORE are little-endian, so on big endian CPUs
* we have to swap the byte order.
*/
static void __endianness(unsigned int byte_length, void *buffer)
#ifdef __BIG_ENDIAN
static void fix_endianness(unsigned int byte_length, void *buffer)
{
/* CPU may be little endian, VME is big endian */
if (__get_endian() == LITTLE_ENDIAN) {
/* swap samples and trig timetag all seen as 32bits words */
int i;
int size = byte_length / 4;
uint32_t *ptr = buffer;
/* swap samples and trig timetag all seen as 32bits words */
int i;
int size = byte_length / 4;
uint32_t *ptr = buffer;
for (i = 0; i < size; ++i, ++ptr)
*ptr = __be32_to_cpu(*ptr);
}
for (i = 0; i < size; ++i, ++ptr)
le32_to_cpus(ptr);
}
#else
static void fix_endianness(unsigned int byte_length, void *buffer){ return; }
#endif
struct zfad_timetag {
uint32_t sec_low;
......@@ -320,12 +307,7 @@ static int zfad_dma_block_to_pages(struct page **pages, unsigned int nr_pages,
static void zfad_dma_context_exit_svec(struct zio_cset *cset,
struct zfad_block *zfad_block)
{
struct fa_dev *fa = cset->zdev->priv_d;
kfree(zfad_block->dma_ctx);
if (fa_is_flag_set(fa, FMC_ADC_DATA_NO_SWAP))
return;
__endianness(zfad_block->block->datalen, zfad_block->block->data);
}
static void zfad_dma_context_exit(struct zio_cset *cset,
......@@ -333,6 +315,7 @@ static void zfad_dma_context_exit(struct zio_cset *cset,
{
struct fa_dev *fa = cset->zdev->priv_d;
fix_endianness(zfad_block->block->datalen, zfad_block->block->data);
if (fa_is_flag_set(fa, FMC_ADC_SVEC))
zfad_dma_context_exit_svec(cset, zfad_block);
}
......
......@@ -7,9 +7,8 @@
#ifndef __FMC_ADC_PDATA_H__
#define __FMC_ADC_PDATA_H__
#define FMC_ADC_BIG_ENDIAN BIT(0)
#define FMC_ADC_BIG_ENDIAN BIT(0) /* Registers are in BIG ENDIAN */
#define FMC_ADC_NOSQUASH_SCATTERLIST BIT(1)
#define FMC_ADC_DATA_NO_SWAP BIT(2)
/*
* In principle this should not be necessary. The two variants should
......
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