/* SPDX-License-Identifier: BSD-2-Clause */
/*
* Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
*
* 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.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stm32h7/hal.h>
#include <rtems.h>
stm32h7_module_index stm32h7_get_module_index(const void *regs)
{
switch ((uintptr_t) regs) {
case GPIOA_BASE:
return STM32H7_MODULE_GPIOA;
case GPIOB_BASE:
return STM32H7_MODULE_GPIOB;
case GPIOC_BASE:
return STM32H7_MODULE_GPIOC;
case GPIOD_BASE:
return STM32H7_MODULE_GPIOD;
case GPIOE_BASE:
return STM32H7_MODULE_GPIOE;
case GPIOF_BASE:
return STM32H7_MODULE_GPIOF;
case GPIOG_BASE:
return STM32H7_MODULE_GPIOG;
case GPIOH_BASE:
return STM32H7_MODULE_GPIOH;
case GPIOI_BASE:
return STM32H7_MODULE_GPIOI;
case GPIOJ_BASE:
return STM32H7_MODULE_GPIOJ;
case GPIOK_BASE:
return STM32H7_MODULE_GPIOK;
case USART1_BASE:
return STM32H7_MODULE_USART1;
case USART2_BASE:
return STM32H7_MODULE_USART2;
case USART3_BASE:
return STM32H7_MODULE_USART3;
case UART4_BASE:
return STM32H7_MODULE_UART4;
case UART5_BASE:
return STM32H7_MODULE_UART5;
case USART6_BASE:
return STM32H7_MODULE_USART6;
case UART7_BASE:
return STM32H7_MODULE_UART7;
case UART8_BASE:
return STM32H7_MODULE_UART8;
#ifdef UART9_BASE
case UART9_BASE:
return STM32H7_MODULE_UART9;
#endif
#ifdef USART10_BASE
case USART10_BASE:
return STM32H7_MODULE_USART10;
#endif
case RNG_BASE:
return STM32H7_MODULE_RNG;
}
return STM32H7_MODULE_INVALID;
}
typedef struct {
__IO uint32_t *enr;
uint32_t enable_bit;
} stm32h7_clk_info;
static const stm32h7_clk_info stm32h7_clk[] = {
[STM32H7_MODULE_INVALID] = { NULL, 0 },
[STM32H7_MODULE_GPIOA] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOAEN },
[STM32H7_MODULE_GPIOB] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOBEN },
[STM32H7_MODULE_GPIOC] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOCEN },
[STM32H7_MODULE_GPIOD] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIODEN },
[STM32H7_MODULE_GPIOE] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOEEN },
[STM32H7_MODULE_GPIOF] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOFEN },
[STM32H7_MODULE_GPIOG] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOGEN },
[STM32H7_MODULE_GPIOH] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOHEN },
[STM32H7_MODULE_GPIOI] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOIEN },
[STM32H7_MODULE_GPIOJ] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOJEN },
[STM32H7_MODULE_GPIOK] = { &RCC->AHB4ENR, RCC_AHB4ENR_GPIOKEN },
[STM32H7_MODULE_USART1] = { &RCC->APB2ENR, RCC_APB2ENR_USART1EN },
[STM32H7_MODULE_USART2] = { &RCC->APB1LENR, RCC_APB1LENR_USART2EN },
[STM32H7_MODULE_USART3] = { &RCC->APB1LENR, RCC_APB1LENR_USART3EN },
[STM32H7_MODULE_UART4] = { &RCC->APB1LENR, RCC_APB1LENR_UART4EN },
[STM32H7_MODULE_UART5] = { &RCC->APB1LENR, RCC_APB1LENR_UART5EN },
[STM32H7_MODULE_USART6] = { &RCC->APB2ENR, RCC_APB2ENR_USART6EN },
[STM32H7_MODULE_UART7] = { &RCC->APB1LENR, RCC_APB1LENR_UART7EN },
[STM32H7_MODULE_UART8] = { &RCC->APB1LENR, RCC_APB1LENR_UART8EN },
#ifdef UART9_BASE
[STM32H7_MODULE_UART9] = { &RCC->APB2ENR, RCC_APB2ENR_UART9EN },
#else
[STM32H7_MODULE_UART9] = { NULL, 0 },
#endif
#ifdef USART10_BASE
[STM32H7_MODULE_USART10] = { &RCC->APB2ENR, RCC_APB2ENR_USART10EN },
#else
[STM32H7_MODULE_USART10] = { NULL, 0 },
#endif
[STM32H7_MODULE_RNG] = { &RCC->AHB2ENR, RCC_AHB2ENR_RNGEN },
[STM32H7_MODULE_ETH1MAC] = { &RCC->AHB1ENR, RCC_AHB1ENR_ETH1MACEN },
[STM32H7_MODULE_ETH1TX] = { &RCC->AHB1ENR, RCC_AHB1ENR_ETH1TXEN },
[STM32H7_MODULE_ETH1RX] = { &RCC->AHB1ENR, RCC_AHB1ENR_ETH1RXEN },
[STM32H7_MODULE_USB1_OTG] = { &RCC->AHB1ENR, RCC_AHB1ENR_USB1OTGHSEN },
[STM32H7_MODULE_USB1_OTG_ULPI] = { &RCC->AHB1ENR, RCC_AHB1ENR_USB1OTGHSULPIEN },
[STM32H7_MODULE_USB2_OTG] = { &RCC->AHB1ENR, RCC_AHB1ENR_USB2OTGHSEN },
[STM32H7_MODULE_USB2_OTG_ULPI] = { &RCC->AHB1ENR, RCC_AHB1ENR_USB2OTGHSULPIEN }
};
void stm32h7_clk_enable(stm32h7_module_index index)
{
__IO uint32_t *enr;
uint32_t enable_bit;
rtems_interrupt_level level;
enr = stm32h7_clk[index].enr;
enable_bit = stm32h7_clk[index].enable_bit;
rtems_interrupt_disable(level);
SET_BIT(*enr, enable_bit);
/* Delay after an RCC peripheral clock enabling */
*enr;
rtems_interrupt_enable(level);
}
void stm32h7_clk_disable(stm32h7_module_index index)
{
__IO uint32_t *enr;
uint32_t enable_bit;
rtems_interrupt_level level;
enr = stm32h7_clk[index].enr;
enable_bit = stm32h7_clk[index].enable_bit;
rtems_interrupt_disable(level);
CLEAR_BIT(*enr, enable_bit);
rtems_interrupt_enable(level);
}
static const stm32h7_clk_info stm32h7_clk_low_power[] = {
[STM32H7_MODULE_INVALID] = { NULL, 0 },
[STM32H7_MODULE_GPIOA] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOALPEN },
[STM32H7_MODULE_GPIOB] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOBLPEN },
[STM32H7_MODULE_GPIOC] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOCLPEN },
[STM32H7_MODULE_GPIOD] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIODLPEN },
[STM32H7_MODULE_GPIOE] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOELPEN },
[STM32H7_MODULE_GPIOF] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOFLPEN },
[STM32H7_MODULE_GPIOG] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOGLPEN },
[STM32H7_MODULE_GPIOH] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOHLPEN },
[STM32H7_MODULE_GPIOI] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOILPEN },
[STM32H7_MODULE_GPIOJ] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOJLPEN },
[STM32H7_MODULE_GPIOK] = { &RCC->AHB4LPENR, RCC_AHB4LPENR_GPIOKLPEN },
[STM32H7_MODULE_USART1] = { &RCC->APB2LPENR, RCC_APB2LPENR_USART1LPEN },
[STM32H7_MODULE_USART2] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_USART2LPEN },
[STM32H7_MODULE_USART3] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_USART3LPEN },
[STM32H7_MODULE_UART4] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_UART4LPEN },
[STM32H7_MODULE_UART5] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_UART5LPEN },
[STM32H7_MODULE_USART6] = { &RCC->APB2LPENR, RCC_APB2LPENR_USART6LPEN },
[STM32H7_MODULE_UART7] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_UART7LPEN },
[STM32H7_MODULE_UART8] = { &RCC->APB1LLPENR, RCC_APB1LLPENR_UART8LPEN },
#ifdef UART9_BASE
[STM32H7_MODULE_UART9] = { &RCC->APB2LPENR, RCC_APB2LPENR_UART9LPEN },
#else
[STM32H7_MODULE_UART9] = { NULL, 0 },
#endif
#ifdef USART10_BASE
[STM32H7_MODULE_USART10] = { &RCC->APB2LPENR, RCC_APB2LPENR_USART10LPEN },
#else
[STM32H7_MODULE_USART10] = { NULL, 0 },
#endif
[STM32H7_MODULE_RNG] = { &RCC->AHB2LPENR, RCC_AHB2LPENR_RNGLPEN },
[STM32H7_MODULE_ETH1MAC] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_ETH1MACLPEN },
[STM32H7_MODULE_ETH1TX] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_ETH1TXLPEN },
[STM32H7_MODULE_ETH1RX] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_ETH1RXLPEN },
[STM32H7_MODULE_USB1_OTG] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_USB1OTGHSLPEN },
[STM32H7_MODULE_USB1_OTG_ULPI] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_USB1OTGHSULPILPEN },
[STM32H7_MODULE_USB2_OTG] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_USB2OTGHSLPEN },
[STM32H7_MODULE_USB2_OTG_ULPI] = { &RCC->AHB1LPENR, RCC_AHB1LPENR_USB2OTGHSULPILPEN }
};
void stm32h7_clk_low_power_enable(stm32h7_module_index index)
{
__IO uint32_t *enr;
uint32_t enable_bit;
rtems_interrupt_level level;
enr = stm32h7_clk_low_power[index].enr;
enable_bit = stm32h7_clk_low_power[index].enable_bit;
rtems_interrupt_disable(level);
SET_BIT(*enr, enable_bit);
/* Delay after an RCC peripheral clock enabling */
*enr;
rtems_interrupt_enable(level);
}
void stm32h7_clk_low_power_disable(stm32h7_module_index index)
{
__IO uint32_t *enr;
uint32_t enable_bit;
rtems_interrupt_level level;
enr = stm32h7_clk_low_power[index].enr;
enable_bit = stm32h7_clk_low_power[index].enable_bit;
rtems_interrupt_disable(level);
CLEAR_BIT(*enr, enable_bit);
rtems_interrupt_enable(level);
}
void stm32h7_gpio_init(const stm32h7_gpio_config *config)
{
stm32h7_module_index index;
index = stm32h7_get_module_index(config->regs);
stm32h7_clk_enable(index);
HAL_GPIO_Init(config->regs, &config->config);
}
void stm32h7_uart_polled_write(rtems_termios_device_context *base, char c)
{
stm32h7_uart_context *ctx;
USART_TypeDef *regs;
ctx = stm32h7_uart_get_context(base);
regs = ctx->uart.Instance;
while ((regs->ISR & USART_ISR_TXE_TXFNF) == 0) {
/* Wait */
}
regs->TDR = (uint8_t) c;
}
int stm32h7_uart_polled_read(rtems_termios_device_context *base)
{
stm32h7_uart_context *ctx;
USART_TypeDef *regs;
ctx = stm32h7_uart_get_context(base);
regs = ctx->uart.Instance;
if ((regs->ISR & USART_ISR_RXNE_RXFNE) == 0) {
return -1;
}
return (uint8_t) regs->RDR;
}