XMC4xxx: Add commin USIC support logic for use in all USIC configurations.

This commit is contained in:
Gregory Nutt 2017-03-19 12:48:37 -06:00
parent 59b9ef8fdc
commit 5c0be816a5
7 changed files with 465 additions and 48 deletions

View File

@ -33,8 +33,8 @@
*
************************************************************************************/
#ifndef __ARCH_ARM_INCLUDE_XM4_CHIP_H
#define __ARCH_ARM_INCLUDE_XM4_CHIP_H
#ifndef __ARCH_ARM_INCLUDE_XMC4_CHIP_H
#define __ARCH_ARM_INCLUDE_XMC4_CHIP_H
/************************************************************************************
* Included Files
@ -49,7 +49,7 @@
/* Get customizations for each supported chip */
#if defined(CONFIG_ARCH_CHIP_XMC4500)
# define XM4_NUSIC 3 /* Three USIC modules: USCI0-2 */
# define XMC4_NUSIC 3 /* Three USIC modules: USCI0-2 */
#else
# error "Unsupported XMC4xxx chip"
@ -127,4 +127,4 @@
* Public Functions
************************************************************************************/
#endif /* __ARCH_ARM_INCLUDE_XM4_CHIP_H */
#endif /* __ARCH_ARM_INCLUDE_XMC4_CHIP_H */

View File

@ -112,7 +112,7 @@ CHIP_ASRCS =
CHIP_CSRCS = xmc4_allocateheap.c xmc4_clockconfig.c xmc4_clockutils.c
CHIP_CSRCS += xmc4_clrpend.c xmc4_idle.c xmc4_irq.c xmc4_lowputc.c
CHIP_CSRCS += xmc4_gpio.c xmc4_serial.c xmc4_start.c
CHIP_CSRCS += xmc4_gpio.c xmc4_serial.c xmc4_start.c xmc4_usic.c
# Configuration-dependent Kinetis files

View File

@ -969,32 +969,32 @@
#define SCU_CGAT0_POSIF0 (1 << 9) /* Bit 9: POSIF0 Gating Status */
#define SCU_CGAT0_POSIF1 (1 << 10) /* Bit 10: POSIF1 Gating Status */
#define SCU_CGAT0_USIC0 (1 << 11) /* Bit 11: USIC0 Gating Status */
#define SCU_CGAT0_ERU1_ (1 << 16) /* Bit 16: ERU1 Gating Status */
#define SCU_CGAT0_ERU1 (1 << 16) /* Bit 16: ERU1 Gating Status */
/* Peripheral 1 Clock Gating Status, Peripheral 1 Clock Gating Set, Peripheral 1 Clock Gating Clear */
#define SCU_CGATSTAT1_CCU43 (1 << 0) /* Bit 0: CCU43 Gating Status */
#define SCU_CGATSTAT1_LEDTSCU0 (1 << 3) /* Bit 3: LEDTS Gating Status */
#define SCU_CGATSTAT1_MCAN0 (1 << 4) /* Bit 4: MultiCAN Gating Status */
#define SCU_CGATSTAT1_DAC (1 << 5) /* Bit 5: DAC Gating Status */
#define SCU_CGATSTAT1_MMCI (1 << 6) /* Bit 6: MMC Interface Gating Status */
#define SCU_CGATSTAT1_USIC1 (1 << 7) /* Bit 7: USIC1 Gating Status */
#define SCU_CGATSTAT1_USIC2 (1 << 8) /* Bit 8: USIC1 Gating Status */
#define SCU_CGATSTAT1_PPORTS (1 << 9) /* Bit 9: PORTS Gating Status */
#define SCU_CGAT1_CCU43 (1 << 0) /* Bit 0: CCU43 Gating Status */
#define SCU_CGAT1_LEDTSCU0 (1 << 3) /* Bit 3: LEDTS Gating Status */
#define SCU_CGAT1_MCAN0 (1 << 4) /* Bit 4: MultiCAN Gating Status */
#define SCU_CGAT1_DAC (1 << 5) /* Bit 5: DAC Gating Status */
#define SCU_CGAT1_MMCI (1 << 6) /* Bit 6: MMC Interface Gating Status */
#define SCU_CGAT1_USIC1 (1 << 7) /* Bit 7: USIC1 Gating Status */
#define SCU_CGAT1_USIC2 (1 << 8) /* Bit 8: USIC1 Gating Status */
#define SCU_CGAT1_PPORTS (1 << 9) /* Bit 9: PORTS Gating Status */
/* Peripheral 2 Clock Gating Status, Peripheral 2 Clock Gating Set, Peripheral 2 Clock Gating Clear */
#define SCU_CGATSTAT2_WDT (1 << 1) /* Bit 1: WDT Gating Status */
#define SCU_CGATSTAT2_ETH0 (1 << 2) /* Bit 2: ETH0 Gating Status */
#define SCU_CGATSTAT2_DMA0 (1 << 4) /* Bit 4: DMA0 Gating Status */
#define SCU_CGATSTAT2_DMA1 (1 << 5) /* Bit 5: DMA1 Gating Status */
#define SCU_CGATSTAT2_FCE (1 << 6) /* Bit 6: FCE Gating Status */
#define SCU_CGATSTAT2_USB (1 << 7) /* Bit 7: USB Gating Status */
#define SCU_CGATSTAT2_ECAT (1 << 10) /* Bit 10: ECAT Gating Status */
#define SCU_CGAT2_WDT (1 << 1) /* Bit 1: WDT Gating Status */
#define SCU_CGAT2_ETH0 (1 << 2) /* Bit 2: ETH0 Gating Status */
#define SCU_CGAT2_DMA0 (1 << 4) /* Bit 4: DMA0 Gating Status */
#define SCU_CGAT2_DMA1 (1 << 5) /* Bit 5: DMA1 Gating Status */
#define SCU_CGAT2_FCE (1 << 6) /* Bit 6: FCE Gating Status */
#define SCU_CGAT2_USB (1 << 7) /* Bit 7: USB Gating Status */
#define SCU_CGAT2_ECAT (1 << 10) /* Bit 10: ECAT Gating Status */
/* Peripheral 3 Clock Gating Status, Peripheral 3 Clock Gating Set, Peripheral 3 Clock Gating Clear */
#define SCU_CGATSTAT3_EBU (1 << 2) /* Bit 2: EBU Gating Status */
#define SCU_CGAT3_EBU (1 << 2) /* Bit 2: EBU Gating Status */
/* Oscillator Control SCU Registers */

View File

@ -44,22 +44,6 @@
#include "nvic.h"
#include "up_arch.h"
/****************************************************************************
* Pre-processor Definitions
****************************************************************************/
/****************************************************************************
* Public Data
****************************************************************************/
/****************************************************************************
* Private Data
****************************************************************************/
/****************************************************************************
* Private Functions
****************************************************************************/
/****************************************************************************
* Public Functions
****************************************************************************/

View File

@ -232,6 +232,7 @@ struct xmc4_dev_s
uintptr_t uartbase; /* Base address of UART registers */
uint32_t baud; /* Configured baud */
uint32_t clock; /* Clocking frequency of the UART module */
uint8_t channel; /* USIC channel identification */
uint8_t irqs; /* Status IRQ associated with this UART (for enable) */
uint8_t ie; /* Interrupts enabled */
uint8_t parity; /* 0=none, 1=odd, 2=even */
@ -312,8 +313,9 @@ static char g_uart5txbuffer[CONFIG_UART5_TXBUFSIZE];
#ifdef HAVE_UART0
static struct xmc4_dev_s g_uart0priv =
{
.uartbase = XMC4_UART0_BASE,
.uartbase = XMC4_USIC0_CH0_BASE,
.clock = BOARD_CORECLK_FREQ,
.channel = (uint8_t)USIC0_CHAN0,
.baud = CONFIG_UART0_BAUD,
.irqs = XMC4_IRQ_USIC0,
.parity = CONFIG_UART0_PARITY,
@ -343,8 +345,9 @@ static uart_dev_t g_uart0port =
#ifdef HAVE_UART1
static struct xmc4_dev_s g_uart1priv =
{
.uartbase = XMC4_UART1_BASE,
.uartbase = XMC4_USIC0_CH1_BASE,
.clock = BOARD_CORECLK_FREQ,
.channel = (uint8_t)USIC0_CHAN1,
.baud = CONFIG_UART1_BAUD,
.irqs = XMC4_IRQ_USIC1,
.parity = CONFIG_UART1_PARITY,
@ -374,8 +377,9 @@ static uart_dev_t g_uart1port =
#ifdef HAVE_UART2
static struct xmc4_dev_s g_uart2priv =
{
.uartbase = XMC4_UART2_BASE,
.uartbase = XMC4_USIC1_CH0_BASE,
.clock = BOARD_BUS_FREQ,
.channel = (uint8_t)USIC1_CHAN0,
.baud = CONFIG_UART2_BAUD,
.irqs = XMC4_IRQ_USIC2,
.parity = CONFIG_UART2_PARITY,
@ -405,8 +409,9 @@ static uart_dev_t g_uart2port =
#ifdef HAVE_UART3
static struct xmc4_dev_s g_uart3priv =
{
.uartbase = XMC4_UART3_BASE,
.uartbase = XMC4_USIC1_CH1_BASE,
.clock = BOARD_BUS_FREQ,
.channel = (uint8_t)USIC1_CHAN1,
.baud = CONFIG_UART3_BAUD,
.irqs = XMC4_IRQ_USIC3,
.parity = CONFIG_UART3_PARITY,
@ -436,8 +441,9 @@ static uart_dev_t g_uart3port =
#ifdef HAVE_UART4
static struct xmc4_dev_s g_uart4priv =
{
.uartbase = XMC4_UART4_BASE,
.uartbase = XMC4_USIC2_CH0_BASE,
.clock = BOARD_BUS_FREQ,
.channel = (uint8_t)USIC2_CHAN0,
.baud = CONFIG_UART4_BAUD,
.irqs = XMC4_IRQ_USIC4,
.parity = CONFIG_UART4_PARITY,
@ -467,8 +473,9 @@ static uart_dev_t g_uart4port =
#ifdef HAVE_UART5
static struct xmc4_dev_s g_uart5priv =
{
.uartbase = XMC4_UART5_BASE,
.uartbase = XMC4_USIC2_CH1_BASE,
.clock = BOARD_BUS_FREQ,
.channel = (uint8_t)USIC2_CHAN1,
.baud = CONFIG_UART5_BAUD,
.irqs = XMC4_IRQ_USIC5,
.parity = CONFIG_UART5_PARITY,

View File

@ -0,0 +1,397 @@
/****************************************************************************
* arch/arm/src/xmc4/xmc4_usic.c
*
* Copyright (C) 2017 Gregory Nutt. All rights reserved.
* Author: Gregory Nutt <gnutt@nuttx.org>
*
* 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.
* 3. Neither the name NuttX 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.
*
****************************************************************************/
/****************************************************************************
* Included Files
****************************************************************************/
#include <nuttx/config.h>
#include <sys/types.h>
#include <stdint.h>
#include <errno.h>
#include <arch/xmc4/chip.h>
#include "up_arch.h"
#include "chip/xmc4_usic.h"
#include "chip/xmc4_scu.h"
#include "xmc4_usic.h"
/****************************************************************************
* Public Functions
****************************************************************************/
/****************************************************************************
* Name: xmc4_enable_usic
*
* Description:
* Enable the USIC module indicated by the 'usic' enumeration value
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned to
* indicate the nature of any failure.
*
****************************************************************************/
int xmc4_enable_usic(enum usic_e usic)
{
switch (usic)
{
case USIC0:
/* Check if USIC0 is already ungated */
if ((getreg32(XMC4_SCU_CGATSTAT0) & SCU_CGAT0_USIC0) == 0)
{
/* Ungate USIC0 clocking */
putreg32(SCU_CGAT0_USIC0, XMC4_SCU_CGATCLR0);
/* De-assert peripheral reset USIC0 */
putreg32(SCU_PR0_USIC0RS, XMC4_SCU_PRCLR0);
}
break;
#if XMC4_NUSIC > 1
case USIC1:
/* Check if USIC1 is already ungated */
if ((getreg32(XMC4_SCU_CGATSTAT1) & SCU_CGAT1_USIC1) == 0)
{
/* Ungate USIC1 clocking */
putreg32(SCU_CGAT1_USIC1, XMC4_SCU_CGATCLR1);
/* De-assert peripheral reset USIC1 */
putreg32(SCU_PR1_USIC1RS, XMC4_SCU_PRCLR1);
}
break;
#if XMC4_NUSIC > 2
case USIC2:
/* Check if USIC2 is already ungated */
if ((getreg32(XMC4_SCU_CGATSTAT1) & SCU_CGAT1_USIC2) == 0)
{
/* Ungate USIC2 clocking */
putreg32(SCU_CGAT1_USIC2, XMC4_SCU_CGATCLR1);
/* De-assert peripheral reset USIC2 */
putreg32(SCU_PR1_USIC2RS, XMC4_SCU_PRCLR1);
}
break;
#endif
#endif
default:
return -EINVAL;
}
return OK;
}
/****************************************************************************
* Name: xmc4_disable_usic
*
* Description:
* Disable the USIC module indicated by the 'usic' enumeration value
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned to
* indicate the nature of any failure.
*
****************************************************************************/
int xmc4_disable_usic(enum usic_e usic)
{
switch (usic)
{
case USIC0:
/* Assert peripheral reset USIC0 */
putreg32(SCU_PR0_USIC0RS, XMC4_SCU_PRSET0);
/* Gate USIC0 clocking */
putreg32(SCU_CGAT0_USIC0, XMC4_SCU_CGATSET0);
break;
#if XMC4_NUSIC > 1
case USIC1:
/* Assert peripheral reset USIC0 */
putreg32(SCU_PR1_USIC1RS, XMC4_SCU_PRSET1);
/* Gate USIC0 clocking */
putreg32(SCU_CGAT1_USIC1, XMC4_SCU_CGATSET1);
break;
#if XMC4_NUSIC > 2
case USIC2:
/* Assert peripheral reset USIC0 */
putreg32(SCU_PR1_USIC2RS, XMC4_SCU_PRSET1);
/* Gate USIC0 clocking */
putreg32(SCU_CGAT1_USIC2, XMC4_SCU_CGATSET1);
break;
#endif
#endif
default:
return -EINVAL;
}
return OK;
}
/****************************************************************************
* Name: xmc4_enable_usic_channel
*
* Description:
* Enable the USIC channel indicated by 'channel'. Also enable and reset
* the USIC module if it is not already enabled.
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned to
* indicate the nature of any failure.
*
****************************************************************************/
int xmc4_enable_usic_channel(enum usic_channel_e channel)
{
uintptr_t base;
uintptr_t regaddr;
uint32_t regval;
switch (channel)
{
case USIC0_CHAN0:
/* USIC0 Channel 0 base address */
base = XMC4_USIC0_CH0_BASE;
/* Enable USIC0 */
xmc4_enable_usic(USIC0);
break;
case USIC0_CHAN1:
/* USIC0 Channel 1 base address */
base = XMC4_USIC0_CH1_BASE;
/* Enable USIC0 */
xmc4_enable_usic(USIC0);
break;
#if XMC4_NUSIC > 1
case USIC1_CHAN0:
/* USIC1 Channel 0 base address */
base = XMC4_USIC1_CH0_BASE;
/* Enable USIC1 */
xmc4_enable_usic(USIC1);
break;
case USIC1_CHAN1:
/* USIC1 Channel 1 base address */
base = XMC4_USIC1_CH1_BASE;
/* Enable USIC1 */
xmc4_enable_usic(USIC1);
break;
#if XMC4_NUSIC > 2
case USIC2_CHAN0:
/* USIC2 Channel 0 base address */
base = XMC4_USIC2_CH0_BASE;
/* Enable USIC2 */
xmc4_enable_usic(USIC2);
break;
case USIC2_CHAN1:
/* USIC2 Channel 1 base address */
base = XMC4_USIC2_CH1_BASE;
/* Enable USIC2 */
xmc4_enable_usic(USIC2);
break;
#endif
#endif
default:
return -EINVAL;
}
/* Enable USIC channel */
regaddr = base + XMC4_USIC_KSCFG_OFFSET;
putreg32(USIC_KSCFG_MODEN | USIC_KSCFG_BPMODEN, regaddr);
/* Wait for the channel to become fully enabled */
while ((getreg32(regaddr) & USIC_KSCFG_MODEN) == 0)
{
}
/* Set USIC channel in IDLE mode */
regaddr = base + XMC4_USIC_CCR_OFFSET;
regval = getreg32(regaddr);
regval &= ~USIC_CCR_MODE_MASK;
putreg32(regval, regaddr);
return OK;
}
/****************************************************************************
* Name: xmc4_disable_usic_channel
*
* Description:
* Disable the USIC channel indicated by 'channel'. Also disable and reset
* the USIC module if both channels have been disabled.
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned to
* indicate the nature of any failure.
*
****************************************************************************/
int xmc4_disable_usic_channel(enum usic_channel_e channel)
{
uintptr_t base;
uintptr_t other;
uintptr_t regaddr;
uint32_t regval;
enum usic_e usic;
switch (channel)
{
case USIC0_CHAN0:
/* Enable USIC0 Channel 0 base address */
base = XMC4_USIC0_CH0_BASE;
other = XMC4_USIC0_CH1_BASE;
usic = USIC0;
break;
case USIC0_CHAN1:
/* Enable USIC0 Channel 1 base address */
base = XMC4_USIC0_CH1_BASE;
other = XMC4_USIC0_CH0_BASE;
usic = USIC0;
break;
#if XMC4_NUSIC > 1
case USIC1_CHAN0:
/* Enable USIC1 Channel 0 base address */
base = XMC4_USIC1_CH0_BASE;
other = XMC4_USIC1_CH1_BASE;
usic = USIC1;
break;
case USIC1_CHAN1:
/* Enable USIC1 Channel 1 base address */
base = XMC4_USIC1_CH1_BASE;
other = XMC4_USIC1_CH0_BASE;
usic = USIC1;
break;
#if XMC4_NUSIC > 2
case USIC2_CHAN0:
/* Enable USIC2 Channel 0 base address */
base = XMC4_USIC2_CH0_BASE;
other = XMC4_USIC2_CH1_BASE;
usic = USIC2;
break;
case USIC2_CHAN1:
/* Enable USIC2 Channel 1 base address */
base = XMC4_USIC2_CH1_BASE;
other = XMC4_USIC2_CH0_BASE;
usic = USIC2;
break;
#endif
#endif
default:
return -EINVAL;
}
/* Disable this channel */
regaddr = base + XMC4_USIC_KSCFG_OFFSET;
regval = getreg32(regaddr);
regval &= ~USIC_KSCFG_MODEN;
regval |= USIC_KSCFG_BPMODEN;
putreg32(regval, regaddr);
/* Check if the other channel has also been disabled */
regaddr = other + XMC4_USIC_KSCFG_OFFSET;
if ((getreg32(regaddr) & USIC_KSCFG_MODEN) == 0)
{
/* Yes... Disable the USIC module */
xmc4_disable_usic(usic);
}
return OK;
}

View File

@ -67,10 +67,10 @@ enum usic_channel_e
{
USIC0_CHAN0 = 0, /* USIC0, Channel 0 */
USIC0_CHAN1 = 1, /* USIC0, Channel 1 */
USIC1_CHAN0 = 0, /* USIC1, Channel 0 */
USIC1_CHAN1 = 1, /* USIC1, Channel 1 */
USIC2_CHAN0 = 0, /* USIC2, Channel 0 */
USIC2_CHAN1 = 1 /* USIC2, Channel 1 */
USIC1_CHAN0 = 2, /* USIC1, Channel 0 */
USIC1_CHAN1 = 3, /* USIC1, Channel 1 */
USIC2_CHAN0 = 4, /* USIC2, Channel 0 */
USIC2_CHAN1 = 5 /* USIC2, Channel 1 */
};
/****************************************************************************
@ -91,6 +91,20 @@ enum usic_channel_e
int xmc4_enable_usic(enum usic_e usic);
/****************************************************************************
* Name: xmc4_disable_usic
*
* Description:
* Disable the USIC module indicated by the 'usic' enumeration value
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned to
* indicate the nature of any failure.
*
****************************************************************************/
int xmc4_disable_usic(enum usic_e usic);
/****************************************************************************
* Name: xmc4_enable_usic_channel
*
@ -106,4 +120,19 @@ int xmc4_enable_usic(enum usic_e usic);
int xmc4_enable_usic_channel(enum usic_channel_e channel);
/****************************************************************************
* Name: xmc4_disable_usic_channel
*
* Description:
* Disable the USIC channel indicated by 'channel'. Also disable and reset
* the USIC module if both channels have been disabled.
*
* Returned Value:
* Zero (OK) is returned on success; A negated errno value is returned to
* indicate the nature of any failure.
*
****************************************************************************/
int xmc4_disable_usic_channel(enum usic_channel_e channel);
#endif /* __ARCH_ARM_SRC_XMC4_XMC4_USIC_H */