Commit c3954f5d authored by Martin Jeřábek's avatar Martin Jeřábek Committed by Martin Jeřábek

driver: linux module, ...

- linux module
- use priv->{read,write}_reg instead of direct calls
- add ctu_can_fd_reset
- number buffers from 0, not from 1
- fix: ctu_can_fd_set_mode: oneshot, berr_reporting
- ctu_can_fd_read_err_ctrs: requires non-null params
- ctu_can_fd_read_rx_frame: option to fetch the first ID word sooner
  to determine FD/non-FD frame for skb allocation
- ctu_can_fd_insert_frame: add param isfd, fix for RTR
- minor optimizations

TODO: split this large commit
parent cd093723
......@@ -2,18 +2,22 @@ SRCS := ctu_can_fd_hw.c ctu_can_fd_linux_defs.c ctu_can_fd_userspace.cpp
OBJS := $(addsuffix .o,$(SRCS))
DEPS := $(addsuffix .d,$(SRCS))
P := /home/mjerabek/Xilinx/vivado-2017.3/SDK/2017.3/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-
#P := /home/martin/programs/Xilinx/SDK/2017.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-
ifeq ($(shell hostname),majernb)
P := /home/martin/programs/Xilinx/SDK/2017.4/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-
else
P := /home/mjerabek/Xilinx/vivado-2017.3/SDK/2017.3/gnu/aarch32/lin/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf-
endif
#P := arm-linux-gnueabihf-
CC := $(P)gcc
CXX := $(P)g++
#CC := clang -target armv7a-pc-linux-gnueabi -march=armv7 -mthumb
XFLAGS := -Wall -Wextra -O2 -D__BIG_ENDIAN_BITFIELD
XFLAGS := -Wall -Wextra -O2 -D__LITTLE_ENDIAN_BITFIELD -mthumb
CFLAGS := $(XFLAGS) -Werror=implicit-function-declaration
CXXFLAGS := $(XFLAGS)
#LDFLAGS := -fuse-ld=gold
all: test
cp ./test /srv/nfs4/debian-armhf-devel/
test: $(OBJS)
$(CXX) $(XFLAGS) -o $@ $(OBJS) $(LDFLAGS)
......
This diff is collapsed.
This diff is collapsed.
......@@ -31,7 +31,14 @@
#ifndef __CTU_CAN_FD_HW__
#define __CTU_CAN_FD_HW__
#include <asm/byteorder.h>
#if defined(__LITTLE_ENDIAN_BITFIELD) == defined(__BIG_ENDIAN_BITFIELD)
# error Either __BIG_ENDIAN_BITFIELD or __LITTLE_ENDIAN_BITFIELD must be defined.
#endif
#include "ctu_can_fd_regs.h"
#include "ctu_can_fd_frame.h"
/*
MJ TODO:
......@@ -45,16 +52,16 @@
#define CTU_CAN_FD_RETR_MAX 15
#define CTU_CAN_FD_FILTER_A 0x01
#define CTU_CAN_FD_FILTER_B 0x02
#define CTU_CAN_FD_FILTER_C 0x03
#define CTU_CAN_FD_FILTER_A 0
#define CTU_CAN_FD_FILTER_B 1
#define CTU_CAN_FD_FILTER_C 2
#define CTU_CAN_FD_TXT_BUFFER_COUNT 4
#define CTU_CAN_FD_TXT_BUFFER_1 0x1
#define CTU_CAN_FD_TXT_BUFFER_2 0x2
#define CTU_CAN_FD_TXT_BUFFER_3 0x3
#define CTU_CAN_FD_TXT_BUFFER_4 0x4
#define CTU_CAN_FD_TXT_BUFFER_1 0
#define CTU_CAN_FD_TXT_BUFFER_2 1
#define CTU_CAN_FD_TXT_BUFFER_3 2
#define CTU_CAN_FD_TXT_BUFFER_4 3
/*
* Status macros -> pass "ctu_can_get_status" result
......@@ -76,7 +83,7 @@
#define CTU_CAN_FD_EWL(stat) (!!(stat).s.ewl)
// True if at least one TXT Buffer is empty
#define CTU_CAN_FD_TXTNE(stat) (!!(stat).s.tbs)
#define CTU_CAN_FD_TXTNF(stat) (!!(stat).s.tbs)
// True if data overrun flag of RX Buffer occurred
#define CTU_CAN_FD_DATA_OVERRUN(stat) (!!(stat).s.dos)
......@@ -122,51 +129,25 @@
// TX Buffer received HW command interrupt
#define CTU_CAN_FD_TXT_BUF_HWCMD_INT(int_stat) (!!(int_stat).s.txbhci)
static inline bool CTU_CAN_FD_INT_ERROR(union ctu_can_fd_int_stat i) {
return i.s.ei || i.s.doi || i.s.epi || i.s.ali;
}
struct ctucanfd_priv;
#ifndef ctucanfd_priv
struct ctucanfd_priv {
void __iomem *mem_base;
u32 (*read_reg)(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg);
void (*write_reg)(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg, u32 val);
};
#endif
static inline void ctu_can_fd_write32(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg,
u32 val)
{
iowrite32(val, (char *)priv->mem_base + reg);
}
static inline void ctu_can_fd_write16(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg,
u16 val)
{
iowrite16(val, (char *)priv->mem_base + reg);
}
static inline void ctu_can_fd_write8(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg,
u8 val)
{
iowrite8(val, (char *)priv->mem_base + reg);
}
static inline void ctu_can_fd_write_txt_buf(struct ctucanfd_priv *priv,
enum ctu_can_fd_regs buf_base,
u32 offset, u32 val)
{
iowrite32(val, (char *)priv->mem_base + buf_base + offset);
}
static inline u32 ctu_can_fd_read32(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg)
{
return ioread32((const char *)priv->mem_base + reg);
}
static inline u16 ctu_can_fd_read16(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg)
{
return ioread16((const char *)priv->mem_base + reg);
}
static inline u8 ctu_can_fd_read8(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg)
{
return ioread8((const char *)priv->mem_base + reg);
}
void ctu_can_fd_write32(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg,
u32 val);
void ctu_can_fd_write32_be(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg,
u32 val);
u32 ctu_can_fd_read32(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg);
u32 ctu_can_fd_read32_be(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg);
/*
......@@ -200,11 +181,21 @@ u32 ctu_can_fd_get_version(struct ctucanfd_priv *priv);
* Arguments:
* priv Private info
* enable Enable/disable the core.
*
*/
void ctu_can_fd_enable(struct ctucanfd_priv *priv, bool enable);
/*
* Resets the CTU CAN FD Core.
* NOTE: After resetting, you must wait until ctu_can_fd_check_access()
* succeeds!
*
* Arguments:
* priv Private info
*/
void ctu_can_fd_reset(struct ctucanfd_priv *priv);
/*
* Configures CTU CAN FD Core to limit the amount of retransmit attempts after
* occurence of error (Error frame, Arbitration lost). If retransmit limit is
......@@ -415,10 +406,8 @@ static inline void ctu_can_fd_set_def_err_limits(struct ctucanfd_priv *priv)
* Arguments:
* priv Private info
* ctr Pointer to error counter structure to fill
* Returns:
* True if read succesfully, false otherwise.
*/
bool ctu_can_fd_read_err_ctrs(struct ctucanfd_priv *priv, struct can_berr_counter *ctr);
void ctu_can_fd_read_err_ctrs(struct ctucanfd_priv *priv, struct can_berr_counter *ctr);
/*
......@@ -661,6 +650,9 @@ void ctu_can_fd_set_rx_tsop(struct ctucanfd_priv *priv, enum ctu_can_fd_rx_setti
void ctu_can_fd_read_rx_frame(struct ctucanfd_priv *priv, struct canfd_frame *data, u64 *ts);
void ctu_can_fd_read_rx_frame_ffw(struct ctucanfd_priv *priv, struct canfd_frame *cf, u64 *ts, union ctu_can_fd_frame_form_w ffw);
/*
* Returns status of TXT Buffer.
*
......@@ -762,11 +754,12 @@ void ctu_can_fd_set_txt_priority(struct ctucanfd_priv *priv, const u8 *prio);
* data Pointer to CAN Frame buffer.
* u64 Timestamp when the buffer should be sent.
* buf Index of TXT Buffer where to insert the CAN Frame.
* isfdf True if the frame is a FD frame.
* Returns:
* True if the frame was inserted succesfully, False otherwise.
*/
bool ctu_can_fd_insert_frame(struct ctucanfd_priv *priv, const struct canfd_frame *data, u64 ts,
u8 buf);
u8 buf, bool isfdf);
/*
* Read transceiver delay as measured by CTU CAN FD Core. Note that
......
......@@ -112,6 +112,13 @@ static inline u16 ioread16(const void *addr) {return *(const volatile u16*)addr;
__attribute__((noinline))
static inline u8 ioread8(const void *addr) {return *(const volatile u8*)addr;}
// TODO: perform actual conversions
__attribute__((noinline))
static inline void iowrite32be(u32 value, void *addr) {*(volatile u32*)addr = value;}
__attribute__((noinline))
static inline u32 ioread32be(const void *addr) {return *(const volatile u32*)addr;}
/* CAN DLC to real data length conversion helpers */
u8 can_dlc2len(u8 can_dlc);
u8 can_len2dlc(u8 len);
......
......@@ -53,6 +53,14 @@ void *mem_map(unsigned long mem_start, unsigned long mem_length)
return mem;
}
unsigned ctu_can_fd_read8(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg) {
return priv->read_reg(priv, (enum ctu_can_fd_regs)(reg & ~3)) >> (8 * (reg & 3));
}
unsigned ctu_can_fd_read16(struct ctucanfd_priv *priv, enum ctu_can_fd_regs reg) {
return priv->read_reg(priv, (enum ctu_can_fd_regs)(reg & ~1)) >> (8 * (reg & 1));
}
int main(int argc, char *argv[])
{
uint32_t addr_base;
......@@ -118,6 +126,7 @@ int main(int argc, char *argv[])
priv->mem_base = base;
priv->read_reg = ctu_can_fd_read32;
priv->write_reg = ctu_can_fd_write32;
union ctu_can_fd_device_id_version reg;
reg.u32 = ctu_can_fd_read32(priv, CTU_CAN_FD_DEVICE_ID);
......@@ -130,15 +139,19 @@ int main(int argc, char *argv[])
u32 version = ctu_can_fd_get_version(priv);
printf("Core version: %u\n", version);
//struct can_ctrlmode ctrlmode = {CAN_CTRLMODE_FD, CAN_CTRLMODE_FD};
//ctu_can_fd_set_mode(priv, &ctrlmode);
// reset
union ctu_can_fd_mode_command_status_settings mode;
mode.s.rst = 1;
ctu_can_fd_write8(priv, CTU_CAN_FD_MODE, mode.u32);
ctu_can_fd_reset(priv);
{
union ctu_can_fd_mode_command_status_settings mode;
mode.u32 = priv->read_reg(priv, CTU_CAN_FD_MODE);
if (mode.s.ena) {
printf("Core is enabled but should be disabled!\n");
}
}
struct net_device nd;
nd.can.clock.freq = 100000000;
......@@ -165,7 +178,8 @@ int main(int argc, char *argv[])
ctu_can_fd_set_nom_bittiming(priv, &nom_timing);
ctu_can_fd_rel_rx_buf(priv);
ctu_can_fd_set_ret_limit(priv, true, 1);
//ctu_can_fd_set_ret_limit(priv, true, 1);
ctu_can_fd_set_ret_limit(priv, false, 0);
ctu_can_fd_abort_tx(priv);
ctu_can_fd_txt_set_abort(priv, CTU_CAN_FD_TXT_BUFFER_1);
ctu_can_fd_txt_set_empty(priv, CTU_CAN_FD_TXT_BUFFER_1);
......@@ -181,7 +195,7 @@ int main(int argc, char *argv[])
memcpy(txf.data, d, sizeof(d));
txf.len = sizeof(d);
res = ctu_can_fd_insert_frame(priv, &txf, 0, CTU_CAN_FD_TXT_BUFFER_1);
res = ctu_can_fd_insert_frame(priv, &txf, 0, CTU_CAN_FD_TXT_BUFFER_1, false);
if (!res)
printf("TX failed\n");
ctu_can_fd_txt_set_rdy(priv, CTU_CAN_FD_TXT_BUFFER_1);
......
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