blob: 16f399f91b28aecb04bc20ad558f6e13d3324e29 [file] [log] [blame]
/*
* SPDX-License-Identifier: Apache-2.0
* Copyright (c) 2024 sensry.io
*/
#include "soc.h"
#include "udma.h"
#define SY1XX_UDMA_CTRL_PER_CG (SY1XX_ARCHI_UDMA_ADDR + SY1XX_UDMA_CONF_OFFSET)
#define SY1XX_MAX_UART_COUNT 3
#define SY1XX_MAX_I2C_COUNT 4
#define SY1XX_MAX_SPI_COUNT 7
#define SY1XX_MAX_ETH_COUNT 1
void sy1xx_udma_enable_clock(sy1xx_udma_module_t module, uint32_t instance)
{
uint32_t udma_ctrl_per_cg = sys_read32(SY1XX_UDMA_CTRL_PER_CG);
switch (module) {
case SY1XX_UDMA_MODULE_UART:
if (instance >= SY1XX_MAX_UART_COUNT) {
return;
}
udma_ctrl_per_cg |= 1 << (instance + 0);
break;
case SY1XX_UDMA_MODULE_I2C:
if (instance >= SY1XX_MAX_I2C_COUNT) {
return;
}
udma_ctrl_per_cg |= 1 << (instance + 10);
break;
case SY1XX_UDMA_MODULE_SPI:
if (instance >= SY1XX_MAX_SPI_COUNT) {
return;
}
udma_ctrl_per_cg |= 1 << (instance + 3);
break;
case SY1XX_UDMA_MODULE_MAC:
if (instance >= SY1XX_MAX_ETH_COUNT) {
return;
}
udma_ctrl_per_cg |= 1 << (instance + 20);
break;
case SY1XX_UDMA_MAX_MODULE_COUNT:
break;
}
sys_write32(udma_ctrl_per_cg, SY1XX_UDMA_CTRL_PER_CG);
}
void sy1xx_udma_disable_clock(sy1xx_udma_module_t module, uint32_t instance)
{
uint32_t udma_ctrl_per_cg = sys_read32(SY1XX_UDMA_CTRL_PER_CG);
switch (module) {
case SY1XX_UDMA_MODULE_UART:
if (instance >= SY1XX_MAX_UART_COUNT) {
return;
}
udma_ctrl_per_cg &= ~(1 << (instance + 0));
break;
case SY1XX_UDMA_MODULE_I2C:
if (instance >= SY1XX_MAX_I2C_COUNT) {
return;
}
udma_ctrl_per_cg &= ~(1 << (instance + 10));
break;
case SY1XX_UDMA_MODULE_SPI:
if (instance >= SY1XX_MAX_SPI_COUNT) {
return;
}
udma_ctrl_per_cg &= ~(1 << (instance + 3));
break;
case SY1XX_UDMA_MODULE_MAC:
if (instance >= SY1XX_MAX_ETH_COUNT) {
return;
}
udma_ctrl_per_cg &= ~(1 << (instance + 20));
break;
case SY1XX_UDMA_MAX_MODULE_COUNT:
break;
}
sys_write32(udma_ctrl_per_cg, SY1XX_UDMA_CTRL_PER_CG);
}
void sy1xx_udma_busy_delay(uint32_t msec)
{
uint32_t sec = 250000000;
uint32_t millis = (sec / 1000) * msec;
for (uint32_t i = 0; i < millis; i++) {
__asm__("nop");
}
}
int32_t sy1xx_udma_cancel(uint32_t base, uint32_t channel)
{
uint32_t channel_offset = channel == 0 ? 0x00 : 0x10;
/* clear existing */
SY1XX_UDMA_WRITE_REG(base, SY1XX_UDMA_CFG_REG + channel_offset,
SY1XX_UDMA_CHANNEL_CFG_CLEAR);
return 0;
}
int32_t sy1xx_udma_is_ready(uint32_t base, uint32_t channel)
{
uint32_t channel_offset = channel == 0 ? 0x00 : 0x10;
int32_t isBusy = SY1XX_UDMA_READ_REG(base, SY1XX_UDMA_CFG_REG + channel_offset) &
(SY1XX_UDMA_CHANNEL_CFG_EN);
return isBusy ? 0 : 1;
}
int32_t sy1xx_udma_wait_for_finished(uint32_t base, uint32_t channel)
{
uint32_t channel_offset = channel == 0 ? 0x00 : 0x10;
volatile uint32_t timeout = 200;
while (SY1XX_UDMA_READ_REG(base, SY1XX_UDMA_CFG_REG + channel_offset) &
(SY1XX_UDMA_CHANNEL_CFG_EN)) {
sy1xx_udma_busy_delay(1);
timeout--;
if (timeout == 0) {
return -1;
}
}
return 0;
}
int32_t sy1xx_udma_wait_for_status(uint32_t base)
{
volatile uint32_t timeout = 200;
while (SY1XX_UDMA_READ_REG(base, SY1XX_UDMA_STATUS) & (0x3)) {
sy1xx_udma_busy_delay(1);
timeout--;
if (timeout == 0) {
return -1;
}
}
return 0;
}
int32_t sy1xx_udma_start(uint32_t base, uint32_t channel, uint32_t saddr, uint32_t size,
uint32_t optional_cfg)
{
uint32_t channel_offset = channel == 0 ? 0x00 : 0x10;
SY1XX_UDMA_WRITE_REG(base, SY1XX_UDMA_SADDR_REG + channel_offset, saddr);
SY1XX_UDMA_WRITE_REG(base, SY1XX_UDMA_SIZE_REG + channel_offset, size);
SY1XX_UDMA_WRITE_REG(base, SY1XX_UDMA_CFG_REG + channel_offset,
SY1XX_UDMA_CHANNEL_CFG_EN | optional_cfg);
return 0;
}
int32_t sy1xx_udma_get_remaining(uint32_t base, uint32_t channel)
{
uint32_t channel_offset = channel == 0 ? 0x00 : 0x10;
int32_t size = SY1XX_UDMA_READ_REG(base, SY1XX_UDMA_SIZE_REG + channel_offset);
return size;
}