zephyr/drivers/flash/flash_stm32f3x.c
Erwan Gouriou 726d4dc437 drivers: stm32: clean up after stm23cube based clock control
After activation of cube based driver support on L4 and F3 series,
this commits performs the clean up of F3 and L4 relative code to
native clock control drivers.
Indirectly, it makes pwm driver supported de facto on F3 series

Change-Id: Idac17103a9b5ef6eab540719343cc8f5865f15fa
Signed-off-by: Erwan Gouriou <erwan.gouriou@linaro.org>
2017-02-10 14:47:41 -06:00

150 lines
3.3 KiB
C

/*
* Copyright (c) 2016 RnDity Sp. z o.o.
*
* SPDX-License-Identifier: Apache-2.0
*/
#include <errno.h>
#include <misc/__assert.h>
#include <clock_control/stm32_clock_control.h>
#include "flash_stm32f3x.h"
static int flash_stm32_erase(struct device *dev, off_t offset, size_t size)
{
uint32_t first_page_addr = 0;
uint32_t last_page_addr = 0;
uint16_t no_of_pages = size / CONFIG_FLASH_PAGE_SIZE;
uint16_t page_index = 0;
/* Check offset and size alignment. */
if (((offset % CONFIG_FLASH_PAGE_SIZE) != 0) ||
((size % CONFIG_FLASH_PAGE_SIZE) != 0) ||
(no_of_pages == 0)) {
return -EINVAL;
}
/* Find address of the first page to be erased. */
page_index = offset / CONFIG_FLASH_PAGE_SIZE;
first_page_addr = CONFIG_FLASH_BASE_ADDRESS +
page_index * CONFIG_FLASH_PAGE_SIZE;
__ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(first_page_addr));
/* Find address of the last page to be erased. */
page_index = ((offset + size) / CONFIG_FLASH_PAGE_SIZE) - 1;
last_page_addr = CONFIG_FLASH_BASE_ADDRESS +
page_index * CONFIG_FLASH_PAGE_SIZE;
__ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(last_page_addr));
while (no_of_pages) {
if (flash_stm32_erase_page(dev, first_page_addr)
!= FLASH_COMPLETE) {
return -EINVAL;
}
no_of_pages--;
first_page_addr += CONFIG_FLASH_PAGE_SIZE;
}
return 0;
}
static int flash_stm32_read(struct device *dev, off_t offset,
void *data, size_t len)
{
uint32_t address = CONFIG_FLASH_BASE_ADDRESS + offset;
__ASSERT_NO_MSG(IS_FLASH_PROGRAM_ADDRESS(address));
flash_stm32_read_data(data, address, len);
return 0;
}
static int flash_stm32_write(struct device *dev, off_t offset,
const void *data, size_t len)
{
uint16_t halfword = 0;
uint32_t address =
CONFIG_FLASH_BASE_ADDRESS + offset;
uint8_t remainder = 0;
if ((len % 2) != 0) {
remainder = 1;
}
len = len / 2;
while (len--) {
halfword = *((uint8_t *)data++);
halfword |= *((uint8_t *)data++) << 8;
if (flash_stm32_program_halfword(dev, address, halfword)
!= FLASH_COMPLETE) {
return -EINVAL;
}
address += 2;
}
if (remainder) {
halfword = (*((uint16_t *)data)) & 0x00FF;
if (flash_stm32_program_halfword(dev, address, halfword)
!= FLASH_COMPLETE) {
return -EINVAL;
}
}
return 0;
}
static int flash_stm32_protection_set(struct device *dev, bool enable)
{
if (enable) {
flash_stm32_lock(dev);
} else {
flash_stm32_unlock(dev);
}
return 0;
}
static int flash_stm32_init(struct device *dev)
{
const struct flash_stm32_dev_config *cfg = FLASH_CFG(dev);
struct device *clk = device_get_binding(STM32_CLOCK_CONTROL_NAME);
if (clock_control_on(clk, (clock_control_subsys_t *) &cfg->pclken) != 0)
return -ENODEV;
return 0;
}
static const struct flash_driver_api flash_stm32_api = {
.read = flash_stm32_read,
.write = flash_stm32_write,
.erase = flash_stm32_erase,
.write_protection = flash_stm32_protection_set,
};
static const struct flash_stm32_dev_config flash_device_config = {
.base = (uint32_t *)FLASH_R_BASE,
.pclken = { .bus = STM32_CLOCK_BUS_APB1,
.enr = LL_AHB1_GRP1_PERIPH_FLASH},
};
static struct flash_stm32_dev_data flash_device_data = {
};
DEVICE_AND_API_INIT(flash_stm32, CONFIG_SOC_FLASH_STM32_DEV_NAME,
flash_stm32_init,
&flash_device_data,
&flash_device_config,
POST_KERNEL,
CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
&flash_stm32_api);