mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2025-12-05 15:15:44 +00:00
bsps/arm/beagle/dcan: Added DCAN support
This commit is contained in:
committed by
Christian Mauderer
parent
cd91b37dce
commit
26d50bdfb6
104
bsps/arm/beagle/dcan/am335x-dcan.c
Normal file
104
bsps/arm/beagle/dcan/am335x-dcan.c
Normal file
@@ -0,0 +1,104 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup CANBus
|
||||||
|
*
|
||||||
|
* @brief Controller Area Network (CAN) Bus Implementation
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Prashanth S (fishesprashanth@gmail.com)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <dev/can/can.h>
|
||||||
|
|
||||||
|
#include <bsp/am335x_dcan.h>
|
||||||
|
#include <bsp/soc_AM335x.h>
|
||||||
|
|
||||||
|
#define IF_NAME_SIZE_MAX (12)
|
||||||
|
|
||||||
|
void beagle_can_init(void *node)
|
||||||
|
{
|
||||||
|
/* FIXME: Remove this method, Check if the device node belongs to CAN
|
||||||
|
* Will be removed once device tree support is added
|
||||||
|
*/
|
||||||
|
static int init = 0;
|
||||||
|
|
||||||
|
if (init != 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
init = 1;
|
||||||
|
|
||||||
|
CAN_DEBUG("beagle_can_init\n");
|
||||||
|
|
||||||
|
char if_name[IF_NAME_SIZE_MAX];
|
||||||
|
|
||||||
|
struct am335x_dcan_priv *priv = NULL;
|
||||||
|
|
||||||
|
/* FIXME: Get hardware specific information from device tree */
|
||||||
|
struct am335x_dcan_irq dcan_irq_nums[2] = {{52, 53, 54}, {55, 56, 57}};
|
||||||
|
uint32_t dcan_base_reg_addr[] = {SOC_DCAN_0_REGS, SOC_DCAN_1_REGS};
|
||||||
|
|
||||||
|
for (int i = 0; i < CAN_NODES; i++) {
|
||||||
|
priv = (struct am335x_dcan_priv *)calloc(1, sizeof(struct am335x_dcan_priv));
|
||||||
|
|
||||||
|
if (priv == NULL) {
|
||||||
|
CAN_ERR("beagle_can_init: calloc failed: cannot allocate memory\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Get hardware specific information from device tree */
|
||||||
|
priv->node = i;
|
||||||
|
priv->base_reg = dcan_base_reg_addr[i];
|
||||||
|
priv->irq = dcan_irq_nums[i];
|
||||||
|
priv->baudrate = 1000000;
|
||||||
|
|
||||||
|
if (dcan_init(priv) < 0) {
|
||||||
|
CAN_ERR("beagle_can_init: CAN controller %d initialization failed\n", priv->node);
|
||||||
|
free(priv);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct can_bus *bus = can_bus_alloc_and_init(sizeof(struct can_bus));
|
||||||
|
|
||||||
|
priv->bus = bus;
|
||||||
|
|
||||||
|
snprintf(if_name, IF_NAME_SIZE_MAX, "/dev/can%d", i);
|
||||||
|
|
||||||
|
bus->priv = priv;
|
||||||
|
dcan_init_ops(priv);
|
||||||
|
|
||||||
|
if (can_bus_register(bus, if_name) != 0) {
|
||||||
|
CAN_ERR("beagle_can_init: bus register failed\n");
|
||||||
|
free(priv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAN_DEBUG("beagle_can_init: can_bus_registered %s\n", if_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
646
bsps/arm/beagle/dcan/dcan.c
Normal file
646
bsps/arm/beagle/dcan/dcan.c
Normal file
@@ -0,0 +1,646 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup CANBus
|
||||||
|
*
|
||||||
|
* @brief Controller Area Network (DCAN) Controller Implementation
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Prashanth S (fishesprashanth@gmail.com)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <bsp.h>
|
||||||
|
#include <bsp/am335x_dcan.h>
|
||||||
|
#include <bsp/soc_AM335x.h>
|
||||||
|
#include <bsp/hw_control_AM335x.h>
|
||||||
|
|
||||||
|
#include <bsp/irq.h>
|
||||||
|
#include <bsp/irq-generic.h>
|
||||||
|
|
||||||
|
#include <dev/can/can.h>
|
||||||
|
|
||||||
|
#include "hw_dcan.h"
|
||||||
|
#include "hw_cm_per.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Pin configurations.
|
||||||
|
*/
|
||||||
|
#define AM335x_PIN_IN_OFFSET (0x138)
|
||||||
|
#define AM335x_PIN_SLEW_FAST (0 << 6)
|
||||||
|
#define AM335x_PIN_SLEW_SLOW (1 << 6)
|
||||||
|
#define AM335x_PIN_RX_DISABLE (0 << 5)
|
||||||
|
#define AM335x_PIN_RX_ENABLE (1 << 5)
|
||||||
|
#define AM335x_PIN_PULL_DIS (1 << 3)
|
||||||
|
#define AM335x_PIN_PULL_EN (0 << 3)
|
||||||
|
#define AM335x_PIN_PULL_UP ((1 << 4) | AM335x_PIN_PULL_EN)
|
||||||
|
#define AM335x_PIN_PULL_DOWN ((0 << 4) | AM335x_PIN_PULL_EN)
|
||||||
|
|
||||||
|
#define AM335x_PIN_MODE_0 (0)
|
||||||
|
#define AM335x_PIN_MODE_1 (1)
|
||||||
|
#define AM335x_PIN_MODE_2 (2)
|
||||||
|
|
||||||
|
static int dcan_tx(void *, struct can_msg *);
|
||||||
|
static bool dcan_tx_ready(void *);
|
||||||
|
static void dcan_int_enable(struct am335x_dcan_priv *);
|
||||||
|
static void dcan_int_disable(struct am335x_dcan_priv *);
|
||||||
|
static void dcan_reset(struct am335x_dcan_priv *priv);
|
||||||
|
static void dcan_clk_config(uint32_t node);
|
||||||
|
static void dcan_isr(void *data);
|
||||||
|
static void dcan_int(void *, bool);
|
||||||
|
static int dcan_intr_init(struct am335x_dcan_priv *priv);
|
||||||
|
static void dcan_inval_obj(struct am335x_dcan_priv *priv, uint32_t index);
|
||||||
|
static void dcan_init_rxobj(struct am335x_dcan_priv *priv);
|
||||||
|
static void dcan_save_msg(struct am335x_dcan_priv *priv, struct can_msg *msg);
|
||||||
|
static void dcan_read_obj(struct am335x_dcan_priv *priv, uint32_t index);
|
||||||
|
static void dcan_bittiming(struct am335x_dcan_priv *priv);
|
||||||
|
static void am335x_dcan_pinmux(uint32_t index);
|
||||||
|
|
||||||
|
/* FIXME: Should be moved to shared beagle */
|
||||||
|
uint32_t am335x_get_sysclk(void);
|
||||||
|
|
||||||
|
static struct can_dev_ops dev_ops = {
|
||||||
|
.dev_tx = dcan_tx,
|
||||||
|
.dev_tx_ready = dcan_tx_ready,
|
||||||
|
.dev_int = dcan_int,
|
||||||
|
};
|
||||||
|
|
||||||
|
void dcan_init_ops(struct am335x_dcan_priv *priv)
|
||||||
|
{
|
||||||
|
CAN_DEBUG("dcan_init_ops\n");
|
||||||
|
priv->bus->can_dev_ops = &dev_ops;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert Data Length Code (CAN specific) to length
|
||||||
|
* of the CAN message.
|
||||||
|
*
|
||||||
|
* @param[in] Data Length Code for the CAN message.
|
||||||
|
*
|
||||||
|
* @retval Corresponding length for the DLC.
|
||||||
|
*/
|
||||||
|
static uint16_t can_dlc_to_len(uint16_t dlc)
|
||||||
|
{
|
||||||
|
if (dlc > 8) {
|
||||||
|
switch(dlc) {
|
||||||
|
case 9:
|
||||||
|
dlc = 12;
|
||||||
|
case 10:
|
||||||
|
dlc = 16;
|
||||||
|
case 11:
|
||||||
|
dlc = 20;
|
||||||
|
case 12:
|
||||||
|
dlc = 24;
|
||||||
|
case 13:
|
||||||
|
dlc = 32;
|
||||||
|
case 14:
|
||||||
|
dlc = 48;
|
||||||
|
default:
|
||||||
|
dlc = 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return dlc;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Convert Length to Data Length Code (CAN specific).
|
||||||
|
*
|
||||||
|
* @param[in] Length of the CAN message.
|
||||||
|
*
|
||||||
|
* @retval Corresponding DLC for the length.
|
||||||
|
*/
|
||||||
|
static uint16_t can_len_to_dlc(uint16_t len)
|
||||||
|
{
|
||||||
|
if (len > 8) {
|
||||||
|
switch(len) {
|
||||||
|
case 12:
|
||||||
|
len = 9;
|
||||||
|
case 16:
|
||||||
|
len = 10;
|
||||||
|
case 20:
|
||||||
|
len = 11;
|
||||||
|
case 24:
|
||||||
|
len = 12;
|
||||||
|
case 32:
|
||||||
|
len = 13;
|
||||||
|
case 48:
|
||||||
|
len = 14;
|
||||||
|
default:
|
||||||
|
len = 64;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* FIXME: Make DCAN_TXRQ dynamic */
|
||||||
|
static bool dcan_tx_ready(void *data)
|
||||||
|
{
|
||||||
|
struct am335x_dcan_priv *priv = (struct am335x_dcan_priv *)data;
|
||||||
|
|
||||||
|
CAN_DEBUG("dcan_tx_ready %08x = %08x\n", priv->base_reg + DCAN_TXRQ(1),
|
||||||
|
can_getreg(priv, DCAN_TXRQ(1)));
|
||||||
|
|
||||||
|
if (can_getreg(priv, DCAN_TXRQ(1)) == 0xffffffff)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_inval_obj(struct am335x_dcan_priv *priv, uint32_t index)
|
||||||
|
{
|
||||||
|
while (can_getreg(priv, DCAN_IFCMD(2)) & DCAN_IFCMD_BUSY) {
|
||||||
|
/* busy wait */
|
||||||
|
}
|
||||||
|
|
||||||
|
can_putreg(priv, DCAN_IFARB(2), 0);
|
||||||
|
|
||||||
|
/* Disable rx and tx interrupts, clear transmit request */
|
||||||
|
|
||||||
|
can_putreg(priv, DCAN_IFMCTL(2), DCAN_IFMCTL_EOB & (~DCAN_IFMCTL_INTPND));
|
||||||
|
can_putreg(priv, DCAN_IFCMD(2), DCAN_IFCMD_WR_RD |
|
||||||
|
DCAN_IFCMD_CLRINTPND | DCAN_IFCMD_CONTROL | DCAN_IFCMD_ARB |
|
||||||
|
DCAN_IFCMD_MSG_NUM(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_init_rxobj(struct am335x_dcan_priv *priv)
|
||||||
|
{
|
||||||
|
while (can_getreg(priv, DCAN_IFCMD(2)) & DCAN_IFCMD_BUSY) {
|
||||||
|
/* busy wait */
|
||||||
|
}
|
||||||
|
|
||||||
|
can_putreg(priv, DCAN_IFMSK(2), DCAN_IFMSK_MXTD | DCAN_IFMSK_MDIR);
|
||||||
|
can_putreg(priv, DCAN_IFMCTL(2), DCAN_IFMCTL_DATALENGTHCODE |
|
||||||
|
DCAN_IFMCTL_EOB | DCAN_IFMCTL_RXIE | DCAN_IFMCTL_UMASK);
|
||||||
|
|
||||||
|
#ifdef CONFIG_CAN_EXTID
|
||||||
|
can_putreg(priv, DCAN_IFARB(2),
|
||||||
|
DCAN_IFARB_MSGVAL | DCAN_IFARB_XTD);
|
||||||
|
#else
|
||||||
|
can_putreg(priv, DCAN_IFARB(2), DCAN_IFARB_MSGVAL);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (int i = CAN_RX_MSG_OBJ_START_NUM; i <= CAN_RX_MSG_OBJ_END_NUM; i++)
|
||||||
|
{
|
||||||
|
while (can_getreg(priv, DCAN_IFCMD(2)) & DCAN_IFCMD_BUSY) {
|
||||||
|
/* busy wait */
|
||||||
|
}
|
||||||
|
can_putreg(priv, DCAN_IFCMD(2),
|
||||||
|
DCAN_IFCMD_WR_RD | DCAN_IFCMD_MASK |
|
||||||
|
DCAN_IFCMD_ARB | DCAN_IFCMD_CONTROL |
|
||||||
|
DCAN_IFCMD_CLRINTPND |
|
||||||
|
DCAN_IFCMD_DATAA | DCAN_IFCMD_DATAB |
|
||||||
|
DCAN_IFCMD_MSG_NUM(i));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_save_msg(struct am335x_dcan_priv *priv, struct can_msg *msg)
|
||||||
|
{
|
||||||
|
uint32_t regval;
|
||||||
|
|
||||||
|
regval = can_getreg(priv, DCAN_IFARB(2));
|
||||||
|
CAN_DEBUG("IFARB = %08X\n", regval);
|
||||||
|
|
||||||
|
/* FIXME: Add extid support in ifdefs */
|
||||||
|
msg->id = (regval >> 18) & DCAN_IFARB_MSK;
|
||||||
|
|
||||||
|
/* FIXME: This is to handle RTR feature not implemented yet */
|
||||||
|
/* msg->rtr = ((regval & DCAN_IFARB_DIR) != 0); */
|
||||||
|
|
||||||
|
#ifdef CONFIG_CAN_EXTID
|
||||||
|
msg->flags |= ((regval & DCAN_IFARB_XTD) != 0) ? DCAN_XTD : 0;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
regval = can_getreg(priv, DCAN_IFMCTL(2));
|
||||||
|
msg->len = can_dlc_to_len((regval >> DCAN_IFMCTL_DATALENGTHCODE_SHIFT) & DCAN_IFMCTL_DATALENGTHCODE);
|
||||||
|
|
||||||
|
((uint32_t *)msg->data)[0] = can_getreg(priv, DCAN_IFDATA(2));
|
||||||
|
((uint32_t *)msg->data)[1] = can_getreg(priv, DCAN_IFDATB(2));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_read_obj(struct am335x_dcan_priv *priv, uint32_t index)
|
||||||
|
{
|
||||||
|
while (can_getreg(priv, DCAN_IFCMD(2)) & DCAN_IFCMD_BUSY) {
|
||||||
|
/* busy wait */
|
||||||
|
}
|
||||||
|
|
||||||
|
can_putreg(priv, DCAN_IFCMD(2),
|
||||||
|
DCAN_IFCMD_MASK | DCAN_IFCMD_ARB |
|
||||||
|
DCAN_IFCMD_CONTROL | DCAN_IFCMD_CLRINTPND | DCAN_IFCMD_DATAA |
|
||||||
|
DCAN_IFCMD_DATAB | DCAN_IFCMD_MSG_NUM(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_isr(void *data)
|
||||||
|
{
|
||||||
|
struct am335x_dcan_priv *priv = data;
|
||||||
|
CAN_DEBUG(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dcan_isr entry node = %d\n", priv->node);
|
||||||
|
|
||||||
|
uint32_t interrupt = can_getreg(priv, DCAN_INT) & DCAN_INT_INT0ID;
|
||||||
|
uint32_t stat = can_getreg(priv, DCAN_ES);
|
||||||
|
uint32_t regval;
|
||||||
|
|
||||||
|
CAN_DEBUG("DCAN_INT = %08x DCAN_ES = %08x\n", interrupt, stat);
|
||||||
|
|
||||||
|
if (interrupt & 0x8000) {
|
||||||
|
/* Clear all warning/error states except RXOK/TXOK */
|
||||||
|
|
||||||
|
regval = can_getreg(priv, DCAN_ES);
|
||||||
|
regval &= DCAN_ES_RXOK | DCAN_ES_TXOK;
|
||||||
|
can_putreg(priv, DCAN_ES, regval);
|
||||||
|
|
||||||
|
if (stat & (DCAN_ES_BOFF | DCAN_ES_EPASS | DCAN_ES_EWARN)) {
|
||||||
|
CAN_ERR("CAN: dcan_isr: Error state\n");
|
||||||
|
REG(priv->base_reg + DCAN_CTL) |= (DCAN_CTL_ABO);
|
||||||
|
dcan_reset(priv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (interrupt != 0 && (interrupt & 0x8000) == 0) {
|
||||||
|
uint32_t msgindex = interrupt & 0x7fff;
|
||||||
|
CAN_DEBUG("msgindex %d\n", msgindex);
|
||||||
|
|
||||||
|
/* if no error detected */
|
||||||
|
|
||||||
|
if (((stat & DCAN_ES_LEC) == 0) ||
|
||||||
|
((stat & DCAN_ES_LEC) == DCAN_ES_LEC)) {
|
||||||
|
if (msgindex <= CAN_RX_MSG_OBJ_END_NUM) {
|
||||||
|
CAN_DEBUG("rx interrupt msgobj = %u\n", msgindex);
|
||||||
|
struct can_msg msg;
|
||||||
|
|
||||||
|
regval = can_getreg(priv, DCAN_ES);
|
||||||
|
regval &= ~DCAN_ES_RXOK;
|
||||||
|
can_putreg(priv, DCAN_ES, regval);
|
||||||
|
|
||||||
|
dcan_read_obj(priv, msgindex);
|
||||||
|
dcan_save_msg(priv, &msg);
|
||||||
|
#ifdef CAN_DEBUG_ISR
|
||||||
|
can_print_msg(&msg);
|
||||||
|
#endif /* CAN_DEBUG_ISR */
|
||||||
|
dcan_inval_obj(priv, msgindex);
|
||||||
|
|
||||||
|
can_receive(priv->bus, &msg);
|
||||||
|
} else {
|
||||||
|
CAN_DEBUG("tx interrupt msgobj = %u\n", msgindex);
|
||||||
|
|
||||||
|
regval = can_getreg(priv, DCAN_ES);
|
||||||
|
regval &= ~DCAN_ES_TXOK;
|
||||||
|
can_putreg(priv, DCAN_ES, regval);
|
||||||
|
|
||||||
|
dcan_inval_obj(priv, msgindex);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
dcan_inval_obj(priv, msgindex);
|
||||||
|
}
|
||||||
|
|
||||||
|
can_putreg(priv, DCAN_ES, 0);
|
||||||
|
|
||||||
|
if (msgindex == CAN_RX_MSG_OBJ_END_NUM) {
|
||||||
|
dcan_init_rxobj(priv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
interrupt = can_getreg(priv, DCAN_INT);
|
||||||
|
CAN_DEBUG("DCAN_INT = %08x\n", interrupt);
|
||||||
|
} while (interrupt != 0);
|
||||||
|
|
||||||
|
can_tx_done(priv->bus);
|
||||||
|
|
||||||
|
CAN_DEBUG(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>> dcan_isr exit\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_int_enable(struct am335x_dcan_priv *priv)
|
||||||
|
{
|
||||||
|
CAN_DEBUG("dcan_int_enable\n");
|
||||||
|
bsp_interrupt_vector_enable(priv->irq.dcan_intr0);
|
||||||
|
bsp_interrupt_vector_enable(priv->irq.dcan_intr1);
|
||||||
|
bsp_interrupt_vector_enable(priv->irq.dcan_parity);
|
||||||
|
|
||||||
|
REG(priv->base_reg + DCAN_CTL) |= DCAN_CTL_EIE | DCAN_CTL_SIE;
|
||||||
|
REG(priv->base_reg + DCAN_CTL) |= DCAN_CTL_IE1 | DCAN_CTL_IE0;
|
||||||
|
|
||||||
|
CAN_DEBUG("DCAN_CTL = 0x%08X\n", can_getreg(priv, DCAN_CTL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_int_disable(struct am335x_dcan_priv *priv)
|
||||||
|
{
|
||||||
|
CAN_DEBUG("dcan_int_disable\n");
|
||||||
|
bsp_interrupt_vector_disable(priv->irq.dcan_intr0);
|
||||||
|
bsp_interrupt_vector_disable(priv->irq.dcan_intr1);
|
||||||
|
bsp_interrupt_vector_disable(priv->irq.dcan_parity);
|
||||||
|
|
||||||
|
REG(priv->base_reg + DCAN_CTL) &= (~(DCAN_CTL_EIE | DCAN_CTL_SIE));
|
||||||
|
REG(priv->base_reg + DCAN_CTL) &= (~(DCAN_CTL_IE1 | DCAN_CTL_IE0));
|
||||||
|
|
||||||
|
CAN_DEBUG("DCAN_CTL = 0x%08X\n", can_getreg(priv, DCAN_CTL));
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_int(void *data, bool flag)
|
||||||
|
{
|
||||||
|
if (flag == true) {
|
||||||
|
dcan_int_enable(data);
|
||||||
|
} else {
|
||||||
|
dcan_int_disable(data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dcan_tx(void *data, struct can_msg *msg)
|
||||||
|
{
|
||||||
|
uint32_t regval;
|
||||||
|
uint32_t num;
|
||||||
|
uint32_t id;
|
||||||
|
uint32_t dlc;
|
||||||
|
uint8_t txobj;
|
||||||
|
|
||||||
|
struct am335x_dcan_priv *priv = (struct am335x_dcan_priv *)data;
|
||||||
|
|
||||||
|
CAN_DEBUG("dcan_tx Entry\n");
|
||||||
|
|
||||||
|
regval = can_getreg(priv, DCAN_TXRQ(1));
|
||||||
|
CAN_DEBUG("DCAN_TXRQ = 0x%08X\n", regval);
|
||||||
|
|
||||||
|
for (num = 0; num < 32; num++) {
|
||||||
|
if ((regval & (1 << num)) == 0) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (num == 32) {
|
||||||
|
return RTEMS_NO_MEMORY;
|
||||||
|
}
|
||||||
|
|
||||||
|
txobj = CAN_TX_MSG_OBJ_START_NUM + num;
|
||||||
|
if (txobj > CAN_TX_MSG_OBJ_END_NUM) {
|
||||||
|
CAN_DEBUG("dcan_tx Calculated txobj num exceeds the CAN_TX_MSG_OBJ_END_NUM\n")
|
||||||
|
return RTEMS_INTERNAL_ERROR;
|
||||||
|
}
|
||||||
|
CAN_DEBUG("msgobj num = %u\n", txobj);
|
||||||
|
|
||||||
|
id = msg->id;
|
||||||
|
dlc = can_len_to_dlc(msg->len);
|
||||||
|
|
||||||
|
CAN_DEBUG("CAN-%d ID: %d LEN: %d\n",
|
||||||
|
priv->node, msg->id, msg->len);
|
||||||
|
|
||||||
|
/* FIXME: Add support for EXT ID */
|
||||||
|
can_putreg(priv, DCAN_IFMSK(1), 0xffff);
|
||||||
|
|
||||||
|
regval = ((dlc & DCAN_IFMCTL_DATALENGTHCODE) |
|
||||||
|
DCAN_IFMCTL_EOB | DCAN_IFMCTL_TXRQST |
|
||||||
|
DCAN_IFMCTL_TXIE);
|
||||||
|
can_putreg(priv, DCAN_IFMCTL(1), regval);
|
||||||
|
|
||||||
|
/* Write data to IF1 data registers */
|
||||||
|
regval = msg->data[0] + (msg->data[1] << 8) +
|
||||||
|
(msg->data[2] << 16) + (msg->data[3] << 24);
|
||||||
|
can_putreg(priv, DCAN_IFDATA(1), regval);
|
||||||
|
|
||||||
|
regval = msg->data[4] + (msg->data[5] << 8) +
|
||||||
|
(msg->data[6] << 16) + (msg->data[7] << 24);
|
||||||
|
can_putreg(priv, DCAN_IFDATB(1), regval);
|
||||||
|
|
||||||
|
#ifdef CONFIG_CAN_EXTID
|
||||||
|
can_putreg(priv,
|
||||||
|
DCAN_IFARB(1),
|
||||||
|
DCAN_IFARB_DIR | DCAN_IFARB_MSGVAL |
|
||||||
|
DCAN_IFARB_XTD | (id << DCAN_IFARB_MSK_SHIFT));
|
||||||
|
#else
|
||||||
|
can_putreg(priv,
|
||||||
|
DCAN_IFARB(1),
|
||||||
|
DCAN_IFARB_DIR | DCAN_IFARB_MSGVAL |
|
||||||
|
(id << 18));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Write to Message RAM */
|
||||||
|
regval = (DCAN_IFCMD_WR_RD | DCAN_IFCMD_MASK |
|
||||||
|
DCAN_IFCMD_ARB | DCAN_IFCMD_CONTROL |
|
||||||
|
DCAN_IFCMD_CLRINTPND | DCAN_IFCMD_TXRQST_NEWDAT |
|
||||||
|
DCAN_IFCMD_DATAA | DCAN_IFCMD_DATAB |
|
||||||
|
DCAN_IFCMD_MSG_NUM(txobj));
|
||||||
|
can_putreg(priv, DCAN_IFCMD(1), regval);
|
||||||
|
|
||||||
|
regval = can_getreg(priv, DCAN_TXRQ(1));
|
||||||
|
|
||||||
|
CAN_DEBUG("msgobj = %u DCAN_TXRQ(1) = 0x%08X\n", txobj, regval);
|
||||||
|
|
||||||
|
CAN_DEBUG("dcan_tx Exit\n");
|
||||||
|
|
||||||
|
return RTEMS_SUCCESSFUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void am335x_dcan_pinmux(uint32_t index)
|
||||||
|
{
|
||||||
|
CAN_DEBUG("am335x_dcan_pinmux for node = 0x%08X\n", index);
|
||||||
|
|
||||||
|
/* FIXME: Add a common way of configuring control module */
|
||||||
|
if (index == 1) {
|
||||||
|
REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_RXD) = AM335x_PIN_PULL_UP
|
||||||
|
| AM335x_PIN_RX_DISABLE | AM335x_PIN_MODE_2;
|
||||||
|
REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_TXD) = AM335x_PIN_PULL_UP
|
||||||
|
| AM335x_PIN_RX_ENABLE | AM335x_PIN_MODE_2;
|
||||||
|
} else if (index == 0) {
|
||||||
|
REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_CTSN) = AM335x_PIN_PULL_UP
|
||||||
|
| AM335x_PIN_RX_DISABLE | AM335x_PIN_MODE_2;
|
||||||
|
REG(AM335X_PADCONF_BASE + AM335X_CONF_UART1_RTSN) = AM335x_PIN_PULL_UP
|
||||||
|
| AM335x_PIN_RX_ENABLE | AM335x_PIN_MODE_2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t am335x_get_sysclk(void)
|
||||||
|
{
|
||||||
|
uint32_t reg_val = REG(SOC_CONTROL_REGS + CONTROL_STATUS);
|
||||||
|
|
||||||
|
switch(reg_val & CONTROL_STATUS_SYSBOOT1_MASK) {
|
||||||
|
case CONTROL_STATUS_SYSBOOT1_19p2MHZ:
|
||||||
|
return 19200000;
|
||||||
|
case CONTROL_STATUS_SYSBOOT1_24MHZ:
|
||||||
|
return 24000000;
|
||||||
|
case CONTROL_STATUS_SYSBOOT1_25MHZ:
|
||||||
|
return 25000000;
|
||||||
|
case CONTROL_STATUS_SYSBOOT1_26MHZ:
|
||||||
|
return 26000000;
|
||||||
|
default:
|
||||||
|
CAN_ERR("DCANGetSysCLK: failed\n");
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_bittiming(struct am335x_dcan_priv *priv)
|
||||||
|
{
|
||||||
|
uint32_t ts1 = CONFIG_AM335X_CAN_TSEG1;
|
||||||
|
uint32_t ts2 = CONFIG_AM335X_CAN_TSEG2;
|
||||||
|
uint32_t sjw = 1;
|
||||||
|
uint32_t brp = CAN_CLOCK_FREQUENCY / (priv->baudrate * CAN_BIT_QUANTA);
|
||||||
|
|
||||||
|
uint32_t regval;
|
||||||
|
|
||||||
|
CAN_DEBUG("CAN%d PCLK: %d baud: %d\n",
|
||||||
|
priv->node, CAN_CLOCK_FREQUENCY, priv->baudrate);
|
||||||
|
CAN_DEBUG("TS1: %d TS2: %d BRP: %d SJW= %d\n", ts1, ts2, brp, sjw);
|
||||||
|
/* Start configuring bit timing */
|
||||||
|
|
||||||
|
regval = REG(priv->base_reg + DCAN_CTL);
|
||||||
|
regval |= DCAN_CTL_CCE;
|
||||||
|
can_putreg(priv, DCAN_CTL, regval);
|
||||||
|
|
||||||
|
regval = (((brp - 1) << DCAN_BTR_BRP_SHIFT)
|
||||||
|
| ((ts1 - 1) << DCAN_BTR_TSEG1_SHIFT)
|
||||||
|
| ((ts2 - 1) << DCAN_BTR_TSEG2_SHIFT)
|
||||||
|
| ((sjw - 1) << DCAN_BTR_SJW_SHIFT));
|
||||||
|
|
||||||
|
CAN_DEBUG("Setting CANxBTR= 0x%08x\n", regval);
|
||||||
|
|
||||||
|
/* Set bit timing */
|
||||||
|
can_putreg(priv, DCAN_BTR, regval);
|
||||||
|
|
||||||
|
/* Stop configuring bit timing */
|
||||||
|
regval = can_getreg(priv, DCAN_CTL);
|
||||||
|
regval &= ~DCAN_CTL_CCE;
|
||||||
|
can_putreg(priv, DCAN_CTL, regval);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int dcan_intr_init(struct am335x_dcan_priv *priv)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if ((ret = rtems_interrupt_handler_install(priv->irq.dcan_intr0, "can-intr-0",
|
||||||
|
RTEMS_INTERRUPT_UNIQUE, dcan_isr, (void *)priv)) != RTEMS_SUCCESSFUL) {
|
||||||
|
CAN_ERR("interrupt registration failed irq = %u\n", priv->irq.dcan_intr0);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAN_DEBUG("Interrupt registration successful intr 0 = %u\n", priv->irq.dcan_intr0);
|
||||||
|
|
||||||
|
if ((ret = rtems_interrupt_handler_install(priv->irq.dcan_intr1, "can-intr-1",
|
||||||
|
RTEMS_INTERRUPT_UNIQUE, dcan_isr, (void *)priv)) != RTEMS_SUCCESSFUL) {
|
||||||
|
CAN_ERR("interrupt registration failed irq = %u\n", priv->irq.dcan_intr1);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAN_DEBUG("Interrupt registration successful intr 1 = %u\n", priv->irq.dcan_intr1);
|
||||||
|
|
||||||
|
if ((ret = rtems_interrupt_handler_install(priv->irq.dcan_parity, "can-intr-parity",
|
||||||
|
RTEMS_INTERRUPT_UNIQUE, dcan_isr, (void *)priv)) != RTEMS_SUCCESSFUL) {
|
||||||
|
CAN_ERR("interrupt registration failed irq = %u\n", priv->irq.dcan_parity);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
CAN_DEBUG("Interrupt registration successful intr parity = %u\n", priv->irq.dcan_parity);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_clk_config(uint32_t node)
|
||||||
|
{
|
||||||
|
if (node == 1) {
|
||||||
|
CAN_DEBUG("CLK for DCAN1\n");
|
||||||
|
REG(SOC_CM_PER_REGS + CM_PER_DCAN1_CLKCTRL) =
|
||||||
|
CM_PER_DCAN1_CLKCTRL_MODULEMODE_ENABLE;
|
||||||
|
|
||||||
|
while((REG(SOC_CM_PER_REGS + CM_PER_DCAN1_CLKCTRL) &
|
||||||
|
CM_PER_DCAN1_CLKCTRL_MODULEMODE) !=
|
||||||
|
CM_PER_DCAN1_CLKCTRL_MODULEMODE_ENABLE);
|
||||||
|
} else if (node == 0) {
|
||||||
|
CAN_DEBUG("CLK for DCAN0\n");
|
||||||
|
REG(SOC_CM_PER_REGS + CM_PER_DCAN0_CLKCTRL) =
|
||||||
|
CM_PER_DCAN0_CLKCTRL_MODULEMODE_ENABLE;
|
||||||
|
|
||||||
|
while((REG(SOC_CM_PER_REGS + CM_PER_DCAN0_CLKCTRL) &
|
||||||
|
CM_PER_DCAN0_CLKCTRL_MODULEMODE) !=
|
||||||
|
CM_PER_DCAN0_CLKCTRL_MODULEMODE_ENABLE);
|
||||||
|
} else {
|
||||||
|
CAN_ERR("dcan_clk_config: unsupported node\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int dcan_init(struct am335x_dcan_priv *priv)
|
||||||
|
{
|
||||||
|
uint32_t regval;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
CAN_DEBUG("DCAN Node %d\n", priv->node);
|
||||||
|
|
||||||
|
dcan_clk_config(priv->node);
|
||||||
|
|
||||||
|
am335x_dcan_pinmux(priv->node);
|
||||||
|
|
||||||
|
REG(SOC_CONTROL_REGS + CONTROL_DCAN_RAMINIT) |=
|
||||||
|
CONTROL_DCAN_RAMINIT_DCAN1_RAMINIT_START;
|
||||||
|
while ((REG(SOC_CONTROL_REGS + CONTROL_DCAN_RAMINIT) &
|
||||||
|
CONTROL_DCAN_RAMINIT_DCAN1_RAMINIT_START) == 0);
|
||||||
|
|
||||||
|
dcan_reset(priv);
|
||||||
|
|
||||||
|
dcan_bittiming(priv);
|
||||||
|
|
||||||
|
#ifdef CAN_DEBUG
|
||||||
|
dcan_tx_ready(priv);
|
||||||
|
#endif /* CAN_DEBUG */
|
||||||
|
|
||||||
|
for (int i = 0; i < CAN_NUM_OF_MSG_OBJS; i++) {
|
||||||
|
dcan_inval_obj(priv, i);
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CAN_DEBUG
|
||||||
|
dcan_tx_ready(priv);
|
||||||
|
|
||||||
|
/* FIXME: This is for Enabling loopback and ABO, configure it from ioctl. */
|
||||||
|
REG(priv->base_reg + DCAN_CTL) |= DCAN_CTL_ABO | DCAN_CTL_TEST;
|
||||||
|
#endif /* CAN_DEBUG */
|
||||||
|
|
||||||
|
regval = can_getreg(priv, DCAN_CTL);
|
||||||
|
regval &= ~DCAN_CTL_INIT;
|
||||||
|
can_putreg(priv, DCAN_CTL, regval);
|
||||||
|
|
||||||
|
while (can_getreg(priv, DCAN_CTL) & DCAN_CTL_INIT);
|
||||||
|
|
||||||
|
/* FIXME: This is for enabling Loopback, should be configured from ioctl */
|
||||||
|
/*
|
||||||
|
CAN_DEBUG("Enabling Loopback\n");
|
||||||
|
REG(priv->base_reg + DCAN_CTL) |= DCAN_CTL_TEST;
|
||||||
|
REG(priv->base_reg + DCAN_TEST) |= DCAN_TEST_LBACK;
|
||||||
|
*/
|
||||||
|
|
||||||
|
dcan_init_rxobj(priv);
|
||||||
|
|
||||||
|
if ((ret = dcan_intr_init(priv)) != RTEMS_SUCCESSFUL) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
regval = can_getreg(priv, DCAN_CTL);
|
||||||
|
regval |= (DCAN_CTL_IE0 | DCAN_CTL_SIE | DCAN_CTL_EIE);
|
||||||
|
can_putreg(priv, DCAN_CTL, regval);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dcan_reset(struct am335x_dcan_priv *priv)
|
||||||
|
{
|
||||||
|
can_putreg(priv, DCAN_CTL, DCAN_CTL_INIT | DCAN_CTL_SWR);
|
||||||
|
while (can_getreg(priv, DCAN_CTL) & DCAN_CTL_SWR);
|
||||||
|
}
|
||||||
1407
bsps/arm/beagle/dcan/hw_cm_per.h
Executable file
1407
bsps/arm/beagle/dcan/hw_cm_per.h
Executable file
File diff suppressed because it is too large
Load Diff
1289
bsps/arm/beagle/dcan/hw_dcan.h
Executable file
1289
bsps/arm/beagle/dcan/hw_dcan.h
Executable file
File diff suppressed because it is too large
Load Diff
106
bsps/arm/beagle/include/bsp/am335x_dcan.h
Normal file
106
bsps/arm/beagle/include/bsp/am335x_dcan.h
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
/* SPDX-License-Identifier: BSD-2-Clause */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
*
|
||||||
|
* @ingroup CANBus
|
||||||
|
*
|
||||||
|
* @brief Controller Area Network (DCAN) Controller Implementation
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2022 Prashanth S (fishesprashanth@gmail.com)
|
||||||
|
*
|
||||||
|
* Redistribution and use in source and binary forms, with or without
|
||||||
|
* modification, are permitted provided that the following conditions
|
||||||
|
* are met:
|
||||||
|
* 1. Redistributions of source code must retain the above copyright
|
||||||
|
* notice, this list of conditions and the following disclaimer.
|
||||||
|
* 2. 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.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER OR CONTRIBUTORS 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 _BSP_AM335X_CAN_H
|
||||||
|
#define _BSP_AM335X_CAN_H
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <dev/can/can.h>
|
||||||
|
#include <bsp.h>
|
||||||
|
|
||||||
|
#define CAN_NODES 2
|
||||||
|
|
||||||
|
#define CAN_NUM_OF_MSG_OBJS (0x40)
|
||||||
|
#define CAN_RX_MSG_OBJ_NUM (0x20)
|
||||||
|
#define CAN_TX_MSG_OBJ_NUM (0x20)
|
||||||
|
|
||||||
|
#define CAN_EXT_MSG (0x00000001)
|
||||||
|
|
||||||
|
#define CAN_TX_MSG_OBJ_START_NUM ((CAN_NUM_OF_MSG_OBJS / 2) + 1)
|
||||||
|
#define CAN_TX_MSG_OBJ_END_NUM (CAN_NUM_OF_MSG_OBJS)
|
||||||
|
|
||||||
|
#define CAN_RX_MSG_OBJ_START_NUM (1)
|
||||||
|
#define CAN_RX_MSG_OBJ_END_NUM (CAN_NUM_OF_MSG_OBJS / 2)
|
||||||
|
|
||||||
|
#define DCAN_IFCMD_MSG_NUM_SHIFT (0) /* Bits 0-7: Number of message object in message RAM which is used for data transfer */
|
||||||
|
#define DCAN_IFCMD_MSG_NUM_MASK (0xff << DCAN_IFCMD_MSG_NUM_SHIFT)
|
||||||
|
#define DCAN_IFCMD_MSG_NUM(n) (((unsigned int)(n) & DCAN_IFCMD_MSG_NUM_MASK) << DCAN_IFCMD_MSG_NUM_SHIFT)
|
||||||
|
|
||||||
|
#define CONTROL_STATUS_SYSBOOT1_MASK (3 << CONTROL_STATUS_SYSBOOT1_SHIFT)
|
||||||
|
#define CONTROL_STATUS_SYSBOOT1_19p2MHZ (0 << CONTROL_STATUS_SYSBOOT1_SHIFT)
|
||||||
|
#define CONTROL_STATUS_SYSBOOT1_24MHZ (1 << CONTROL_STATUS_SYSBOOT1_SHIFT)
|
||||||
|
#define CONTROL_STATUS_SYSBOOT1_25MHZ (2 << CONTROL_STATUS_SYSBOOT1_SHIFT)
|
||||||
|
#define CONTROL_STATUS_SYSBOOT1_26MHZ (3 << CONTROL_STATUS_SYSBOOT1_SHIFT)
|
||||||
|
|
||||||
|
#define CONFIG_AM335X_CAN_TSEG1 6
|
||||||
|
#define CONFIG_AM335X_CAN_TSEG2 1
|
||||||
|
#define CAN_BIT_QUANTA (CONFIG_AM335X_CAN_TSEG1 + CONFIG_AM335X_CAN_TSEG2 + 1)
|
||||||
|
#define CAN_CLOCK_FREQUENCY (am335x_get_sysclk())
|
||||||
|
|
||||||
|
struct am335x_dcan_irq {
|
||||||
|
uint32_t dcan_intr0;
|
||||||
|
uint32_t dcan_intr1;
|
||||||
|
uint32_t dcan_parity;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct am335x_dcan_priv {
|
||||||
|
uint32_t node;
|
||||||
|
uint32_t base_reg;
|
||||||
|
uint32_t baudrate;
|
||||||
|
struct can_bus *bus;
|
||||||
|
struct am335x_dcan_irq irq;
|
||||||
|
};
|
||||||
|
|
||||||
|
int dcan_init(struct am335x_dcan_priv *dcan_priv);
|
||||||
|
void beagle_can_init(void *node);
|
||||||
|
|
||||||
|
void dcan_init_ops(struct am335x_dcan_priv *priv);
|
||||||
|
|
||||||
|
#define can_putreg(priv, off, val) \
|
||||||
|
do { \
|
||||||
|
REG(priv->base_reg + off) = val; \
|
||||||
|
CAN_DEBUG_REG("%s:%d %08x<-%08x\n", __FILE__, __LINE__, priv->base_reg + off, val); \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
static inline uint32_t can_getreg(struct am335x_dcan_priv *priv, uint32_t off)
|
||||||
|
{
|
||||||
|
CAN_DEBUG_REG("can_getreg 0x%08x = 0x%08x\n", priv->base_reg + off,
|
||||||
|
REG(priv->base_reg + off));
|
||||||
|
return REG(priv->base_reg + off);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* _BSP_AM335X_CAN_H */
|
||||||
7794
bsps/arm/beagle/include/bsp/hw_control_AM335x.h
Executable file
7794
bsps/arm/beagle/include/bsp/hw_control_AM335x.h
Executable file
File diff suppressed because it is too large
Load Diff
206
bsps/arm/beagle/include/bsp/soc_AM335x.h
Executable file
206
bsps/arm/beagle/include/bsp/soc_AM335x.h
Executable file
@@ -0,0 +1,206 @@
|
|||||||
|
/** ============================================================================
|
||||||
|
* \file soc_AM33XX.h
|
||||||
|
*
|
||||||
|
* \brief This file contains the peripheral information for AM33XX SoC
|
||||||
|
*
|
||||||
|
* ============================================================================
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* 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 Texas Instruments Incorporated nor the names of
|
||||||
|
* its contributors may be used to endorse or promote products derived
|
||||||
|
* from this software without specific prior written permission.
|
||||||
|
*
|
||||||
|
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||||
|
* "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 THE COPYRIGHT
|
||||||
|
* OWNER OR CONTRIBUTORS 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 _SOC_AM33XX_H_
|
||||||
|
#define _SOC_AM33XX_H_
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/** Cache Line size in ARM Cortex-A8. */
|
||||||
|
#define SOC_CACHELINE_SIZE_MAX (64)
|
||||||
|
|
||||||
|
/** @brief Base address of AINTC memory mapped registers */
|
||||||
|
#define SOC_AINTC_REGS (0x48200000)
|
||||||
|
|
||||||
|
/** @brief Base addresses of UART memory mapped registers */
|
||||||
|
#define SOC_UART_0_REGS (0x44E09000)
|
||||||
|
#define SOC_UART_1_REGS (0x48022000)
|
||||||
|
#define SOC_UART_2_REGS (0x48024000)
|
||||||
|
#define SOC_UART_3_REGS (0x481A6000)
|
||||||
|
#define SOC_UART_4_REGS (0x481A8000)
|
||||||
|
#define SOC_UART_5_REGS (0x481AA000)
|
||||||
|
|
||||||
|
/** @brief Base addresses of USB memory mapped registers */
|
||||||
|
#define SOC_USB_0_BASE (0x47401400)
|
||||||
|
#define SOC_USB_1_BASE (0x47401C00)
|
||||||
|
/** @brief Base addresses of SPI memory mapped registers */
|
||||||
|
#define SOC_SPI_0_REGS (0x48030000)
|
||||||
|
#define SOC_SPI_1_REGS (0x481A0000)
|
||||||
|
|
||||||
|
/** @brief Base addresses of GPIO memory mapped registers */
|
||||||
|
#define SOC_GPIO_0_REGS (0x44E07000)
|
||||||
|
#define SOC_GPIO_1_REGS (0x4804C000)
|
||||||
|
#define SOC_GPIO_2_REGS (0x481AC000)
|
||||||
|
#define SOC_GPIO_3_REGS (0x481AE000)
|
||||||
|
|
||||||
|
/** @brief Base addresses of DMTIMER memory mapped registers */
|
||||||
|
#define SOC_DMTIMER_0_REGS (0x44E05000)
|
||||||
|
#define SOC_DMTIMER_1_REGS (0x44E31000)
|
||||||
|
#define SOC_DMTIMER_2_REGS (0x48040000)
|
||||||
|
#define SOC_DMTIMER_3_REGS (0x48042000)
|
||||||
|
#define SOC_DMTIMER_4_REGS (0x48044000)
|
||||||
|
#define SOC_DMTIMER_5_REGS (0x48046000)
|
||||||
|
#define SOC_DMTIMER_6_REGS (0x48048000)
|
||||||
|
#define SOC_DMTIMER_7_REGS (0x4804A000)
|
||||||
|
|
||||||
|
/** @brief Base address of MMC memory mapped registers */
|
||||||
|
#define SOC_MMCHS_0_REGS (0x48060000)
|
||||||
|
#define SOC_MMCHS_1_REGS (0x481D8000)
|
||||||
|
#define SOC_MMCHS_2_REGS (0x47810000)
|
||||||
|
|
||||||
|
/** @brief Base address of GPMC memory mapped registers */
|
||||||
|
#define SOC_GPMC_0_REGS (0x50000000)
|
||||||
|
|
||||||
|
/** @brief Base address of GPMC memory mapped registers */
|
||||||
|
#define SOC_ELM_0_REGS (0x48080000)
|
||||||
|
|
||||||
|
/** @brief Base address of I2C memory mapped registers */
|
||||||
|
#define SOC_I2C_0_REGS (0x44E0B000)
|
||||||
|
#define SOC_I2C_1_REGS (0x4802A000)
|
||||||
|
#define SOC_I2C_2_REGS (0x4819C000)
|
||||||
|
|
||||||
|
/** @brief Base address of WDT memory mapped registers */
|
||||||
|
#define SOC_WDT_0_REGS (0x44E33000)
|
||||||
|
#define SOC_WDT_1_REGS (0x44E35000)
|
||||||
|
|
||||||
|
/** @brief Base address of WDT memory mapped registers */
|
||||||
|
#define SOC_CPSW_SS_REGS (0x4A100000)
|
||||||
|
#define SOC_CPSW_MDIO_REGS (0x4A101000)
|
||||||
|
#define SOC_CPSW_WR_REGS (0x4A101200)
|
||||||
|
#define SOC_CPSW_CPDMA_REGS (0x4A100800)
|
||||||
|
#define SOC_CPSW_ALE_REGS (0x4A100D00)
|
||||||
|
#define SOC_CPSW_STAT_REGS (0x4A100900)
|
||||||
|
#define SOC_CPSW_PORT_0_REGS (0x4A100100)
|
||||||
|
#define SOC_CPSW_PORT_1_REGS (0x4A100200)
|
||||||
|
#define SOC_CPSW_SLIVER_1_REGS (0x4A100D80)
|
||||||
|
#define SOC_CPSW_PORT_2_REGS (0x4A100300)
|
||||||
|
#define SOC_CPSW_SLIVER_2_REGS (0x4A100DC0)
|
||||||
|
#define SOC_CPSW_CPPI_RAM_REGS (0x4A102000)
|
||||||
|
|
||||||
|
/** @brief Base address of McASP memory mapped registers */
|
||||||
|
#define SOC_MCASP_0_CTRL_REGS (0x48038000)
|
||||||
|
#define SOC_MCASP_0_FIFO_REGS (SOC_MCASP_0_CTRL_REGS + 0x1000)
|
||||||
|
#define SOC_MCASP_0_DATA_REGS (0x46000000)
|
||||||
|
#define SOC_MCASP_1_CTRL_REGS (0x4803C000)
|
||||||
|
#define SOC_MCASP_1_FIFO_REGS (SOC_MCASP_1_CTRL_REGS + 0x1000)
|
||||||
|
#define SOC_MCASP_1_DATA_REGS (0x46400000)
|
||||||
|
|
||||||
|
/** @brief Base address of EMIF memory mapped registers */
|
||||||
|
#define SOC_EMIF_0_REGS (0x4C000000)
|
||||||
|
|
||||||
|
/** @brief Base addresses of RTC memory mapped registers */
|
||||||
|
#define SOC_RTC_0_REGS (0x44E3E000)
|
||||||
|
|
||||||
|
/** @brief Base addresses of PRCM memory mapped registers */
|
||||||
|
#define SOC_PRCM_REGS (0x44E00000)
|
||||||
|
#define SOC_CM_PER_REGS (SOC_PRCM_REGS + 0)
|
||||||
|
#define SOC_CM_WKUP_REGS (SOC_PRCM_REGS + 0x400)
|
||||||
|
#define SOC_CM_DPLL_REGS (SOC_PRCM_REGS + 0x500)
|
||||||
|
#define SOC_CM_MPU_REGS (SOC_PRCM_REGS + 0x600)
|
||||||
|
#define SOC_CM_DEVICE_REGS (SOC_PRCM_REGS + 0x700)
|
||||||
|
#define SOC_CM_RTC_REGS (SOC_PRCM_REGS + 0x800)
|
||||||
|
#define SOC_CM_GFX_REGS (SOC_PRCM_REGS + 0x900)
|
||||||
|
#define SOC_CM_CEFUSE_REGS (SOC_PRCM_REGS + 0xA00)
|
||||||
|
#define SOC_OCP_SOCKET_RAM_REGS (SOC_PRCM_REGS + 0xB00)
|
||||||
|
#define SOC_PRM_PER_REGS (SOC_PRCM_REGS + 0xC00)
|
||||||
|
#define SOC_PRM_WKUP_REGS (SOC_PRCM_REGS + 0xD00)
|
||||||
|
#define SOC_PRM_MPU_REGS (SOC_PRCM_REGS + 0xE00)
|
||||||
|
#define SOC_PRM_DEVICE_REGS (SOC_PRCM_REGS + 0xF00)
|
||||||
|
#define SOC_PRM_RTC_REGS (SOC_PRCM_REGS + 0x1000)
|
||||||
|
#define SOC_PRM_GFX_REGS (SOC_PRCM_REGS + 0x1100)
|
||||||
|
#define SOC_PRM_CEFUSE_REGS (SOC_PRCM_REGS + 0x1200)
|
||||||
|
|
||||||
|
/** @brief Base address of control module memory mapped registers */
|
||||||
|
#define SOC_CONTROL_REGS (0x44E10000)
|
||||||
|
|
||||||
|
|
||||||
|
/** @brief Base address of Channel controller memory mapped registers */
|
||||||
|
#define SOC_EDMA30CC_0_REGS (0x49000000)
|
||||||
|
|
||||||
|
/** @brief Base address of DCAN module memory mapped registers */
|
||||||
|
#define SOC_DCAN_0_REGS (0x481CC000)
|
||||||
|
#define SOC_DCAN_1_REGS (0x481D0000)
|
||||||
|
|
||||||
|
/******************************************************************************\
|
||||||
|
* Parameterizable Configuration:- These are fed directly from the RTL
|
||||||
|
* parameters for the given SOC
|
||||||
|
\******************************************************************************/
|
||||||
|
#define TPCC_MUX(n) 0xF90 + ((n) * 4)
|
||||||
|
|
||||||
|
|
||||||
|
#define SOC_LCDC_0_REGS 0x4830E000
|
||||||
|
|
||||||
|
#define SOC_ADC_TSC_0_REGS 0x44E0D000
|
||||||
|
|
||||||
|
/** @brief Base addresses of PWMSS memory mapped registers. */
|
||||||
|
|
||||||
|
#define SOC_PWMSS0_REGS (0x48300000)
|
||||||
|
#define SOC_PWMSS1_REGS (0x48302000)
|
||||||
|
#define SOC_PWMSS2_REGS (0x48304000)
|
||||||
|
|
||||||
|
#define SOC_ECAP_REGS (0x00000100)
|
||||||
|
#define SOC_EQEP_REGS (0x00000180)
|
||||||
|
#define SOC_EPWM_REGS (0x00000200)
|
||||||
|
|
||||||
|
#define SOC_ECAP_0_REGS (SOC_PWMSS0_REGS + SOC_ECAP_REGS)
|
||||||
|
#define SOC_ECAP_1_REGS (SOC_PWMSS1_REGS + SOC_ECAP_REGS)
|
||||||
|
#define SOC_ECAP_2_REGS (SOC_PWMSS2_REGS + SOC_ECAP_REGS)
|
||||||
|
|
||||||
|
#define SOC_EQEP_0_REGS (SOC_PWMSS0_REGS + SOC_EQEP_REGS)
|
||||||
|
#define SOC_EQEP_1_REGS (SOC_PWMSS1_REGS + SOC_EQEP_REGS)
|
||||||
|
#define SOC_EQEP_2_REGS (SOC_PWMSS2_REGS + SOC_EQEP_REGS)
|
||||||
|
|
||||||
|
#define SOC_EPWM_0_REGS (SOC_PWMSS0_REGS + SOC_EPWM_REGS)
|
||||||
|
#define SOC_EPWM_1_REGS (SOC_PWMSS1_REGS + SOC_EPWM_REGS)
|
||||||
|
#define SOC_EPWM_2_REGS (SOC_PWMSS2_REGS + SOC_EPWM_REGS)
|
||||||
|
|
||||||
|
|
||||||
|
#define SOC_EPWM_MODULE_FREQ 100
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _SOC_AM33XX_H_ */
|
||||||
@@ -35,6 +35,8 @@ source:
|
|||||||
- bsps/arm/beagle/qep/qep.c
|
- bsps/arm/beagle/qep/qep.c
|
||||||
- bsps/arm/beagle/rtc/rtc.c
|
- bsps/arm/beagle/rtc/rtc.c
|
||||||
- bsps/arm/beagle/spi/spi.c
|
- bsps/arm/beagle/spi/spi.c
|
||||||
|
- bsps/arm/beagle/dcan/dcan.c
|
||||||
|
- bsps/arm/beagle/dcan/am335x-dcan.c
|
||||||
- bsps/arm/beagle/start/bspdebug.c
|
- bsps/arm/beagle/start/bspdebug.c
|
||||||
- bsps/arm/beagle/start/bspreset.c
|
- bsps/arm/beagle/start/bspreset.c
|
||||||
- bsps/arm/beagle/start/bspstart.c
|
- bsps/arm/beagle/start/bspstart.c
|
||||||
|
|||||||
Reference in New Issue
Block a user