drivers: reset: added Reset Controller for Raspberry Pi Pico
added Reset Controller driver for Raspberry Pi Pico board Signed-off-by: Andrei-Edward Popa <andrei.popa105@yahoo.com>
This commit is contained in:
parent
a4e762b1fd
commit
3d24f62c05
4 changed files with 171 additions and 0 deletions
|
@ -1,3 +1,4 @@
|
||||||
# SPDX-License-Identifier: Apache-2.0
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
zephyr_library()
|
zephyr_library()
|
||||||
|
zephyr_library_sources_ifdef(CONFIG_RESET_RPI_PICO reset_rpi_pico.c)
|
||||||
|
|
|
@ -27,4 +27,6 @@ config RESET_INIT_PRIORITY
|
||||||
|
|
||||||
comment "Reset Controller Drivers"
|
comment "Reset Controller Drivers"
|
||||||
|
|
||||||
|
rsource "Kconfig.rpi_pico"
|
||||||
|
|
||||||
endif # RESET
|
endif # RESET
|
||||||
|
|
9
drivers/reset/Kconfig.rpi_pico
Normal file
9
drivers/reset/Kconfig.rpi_pico
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
# Copyright (c) 2022 Andrei-Edward Popa
|
||||||
|
# SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
# Workaround for not being able to have commas in macro arguments
|
||||||
|
DT_COMPAT_RPI_PICO_RESET := raspberrypi,pico-reset
|
||||||
|
|
||||||
|
config RESET_RPI_PICO
|
||||||
|
bool "Raspberry Pi Reset Controller driver"
|
||||||
|
default $(dt_compat_enabled,$(DT_COMPAT_RPI_PICO_RESET))
|
159
drivers/reset/reset_rpi_pico.c
Normal file
159
drivers/reset/reset_rpi_pico.c
Normal file
|
@ -0,0 +1,159 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2022 Andrei-Edward Popa
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DT_DRV_COMPAT raspberrypi_pico_reset
|
||||||
|
|
||||||
|
#include <device.h>
|
||||||
|
#include <drivers/reset.h>
|
||||||
|
|
||||||
|
struct reset_rpi_config {
|
||||||
|
DEVICE_MMIO_ROM;
|
||||||
|
uint8_t reg_width;
|
||||||
|
uint8_t active_low;
|
||||||
|
uintptr_t base_address;
|
||||||
|
};
|
||||||
|
|
||||||
|
static int reset_rpi_read_register(const struct device *dev, uint16_t offset, uint32_t *value)
|
||||||
|
{
|
||||||
|
const struct reset_rpi_config *config = dev->config;
|
||||||
|
uint32_t base_address = config->base_address;
|
||||||
|
|
||||||
|
switch (config->reg_width) {
|
||||||
|
case 1:
|
||||||
|
*value = sys_read8(base_address + offset);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
*value = sys_read16(base_address + offset);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
*value = sys_read32(base_address + offset);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_rpi_write_register(const struct device *dev, uint16_t offset, uint32_t value)
|
||||||
|
{
|
||||||
|
const struct reset_rpi_config *config = dev->config;
|
||||||
|
uint32_t base_address = config->base_address;
|
||||||
|
|
||||||
|
switch (config->reg_width) {
|
||||||
|
case 1:
|
||||||
|
sys_write8(value, base_address + offset);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
sys_write16(value, base_address + offset);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
sys_write32(value, base_address + offset);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_rpi_status(const struct device *dev, uint32_t id, uint8_t *status)
|
||||||
|
{
|
||||||
|
const struct reset_rpi_config *config = dev->config;
|
||||||
|
uint16_t offset;
|
||||||
|
uint32_t value;
|
||||||
|
uint8_t regbit;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = id / (config->reg_width * CHAR_BIT);
|
||||||
|
regbit = id % (config->reg_width * CHAR_BIT);
|
||||||
|
|
||||||
|
ret = reset_rpi_read_register(dev, offset, &value);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
*status = !(value & BIT(regbit)) ^ !config->active_low;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_rpi_update(const struct device *dev, uint32_t id, uint8_t assert)
|
||||||
|
{
|
||||||
|
const struct reset_rpi_config *config = dev->config;
|
||||||
|
uint16_t offset;
|
||||||
|
uint32_t value;
|
||||||
|
uint8_t regbit;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
offset = id / (config->reg_width * CHAR_BIT);
|
||||||
|
regbit = id % (config->reg_width * CHAR_BIT);
|
||||||
|
|
||||||
|
ret = reset_rpi_read_register(dev, offset, &value);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (assert ^ config->active_low) {
|
||||||
|
value |= BIT(regbit);
|
||||||
|
} else {
|
||||||
|
value &= ~BIT(regbit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return reset_rpi_write_register(dev, offset, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_rpi_assert(const struct device *dev, uint32_t id)
|
||||||
|
{
|
||||||
|
return reset_rpi_update(dev, id, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_rpi_deassert(const struct device *dev, uint32_t id)
|
||||||
|
{
|
||||||
|
return reset_rpi_update(dev, id, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_rpi_toggle(const struct device *dev, uint32_t id)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = reset_rpi_assert(dev, id);
|
||||||
|
if (ret) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return reset_rpi_deassert(dev, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int reset_rpi_init(const struct device *dev)
|
||||||
|
{
|
||||||
|
DEVICE_MMIO_MAP(dev, K_MEM_CACHE_NONE);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct reset_driver_api reset_rpi_driver_api = {
|
||||||
|
.status = reset_rpi_status,
|
||||||
|
.assert = reset_rpi_assert,
|
||||||
|
.deassert = reset_rpi_deassert,
|
||||||
|
.toggle = reset_rpi_toggle,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define RPI_RESET_INIT(idx) \
|
||||||
|
static const struct reset_rpi_config reset_rpi_config_##idx = { \
|
||||||
|
DEVICE_MMIO_ROM_INIT(DT_DRV_INST(idx)), \
|
||||||
|
.reg_width = DT_INST_PROP_OR(idx, reg_width, 4), \
|
||||||
|
.active_low = DT_INST_PROP_OR(idx, active_low, 0), \
|
||||||
|
.base_address = DT_INST_REG_ADDR(idx), \
|
||||||
|
}; \
|
||||||
|
\
|
||||||
|
DEVICE_DT_INST_DEFINE(idx, reset_rpi_init, \
|
||||||
|
NULL, NULL, \
|
||||||
|
&reset_rpi_config_##idx, PRE_KERNEL_1, \
|
||||||
|
CONFIG_RESET_INIT_PRIORITY, \
|
||||||
|
&reset_rpi_driver_api);
|
||||||
|
|
||||||
|
DT_INST_FOREACH_STATUS_OKAY(RPI_RESET_INIT);
|
Loading…
Add table
Add a link
Reference in a new issue