Commit fd7a1c90 authored by Gabriel Fernandez's avatar Gabriel Fernandez Committed by Stephen Boyd

clk: stm32: introduce clocks for STM32MP257 platform

This driver is intended for the STM32MP25 clock family and utilizes
the stm32-core API, similar to the stm32mp13 clock driver.
Signed-off-by: default avatarGabriel Fernandez <gabriel.fernandez@foss.st.com>
Link: https://lore.kernel.org/r/20240411092453.243633-4-gabriel.fernandez@foss.st.comSigned-off-by: default avatarStephen Boyd <sboyd@kernel.org>
parent df5df125
......@@ -25,5 +25,12 @@ config COMMON_CLK_STM32MP157
help
Support for stm32mp15x SoC family clocks.
config COMMON_CLK_STM32MP257
bool "Clock driver for stm32mp25x clocks"
depends on ARM64 || COMPILE_TEST
default y
help
Support for stm32mp25x SoC family clocks.
endif
obj-$(CONFIG_COMMON_CLK_STM32MP135) += clk-stm32mp13.o clk-stm32-core.o reset-stm32.o
obj-$(CONFIG_COMMON_CLK_STM32MP157) += clk-stm32mp1.o reset-stm32.o
obj-$(CONFIG_COMMON_CLK_STM32MP257) += clk-stm32mp25.o clk-stm32-core.o reset-stm32.o
This diff is collapsed.
......@@ -19,6 +19,7 @@ struct stm32_reset_data {
struct reset_controller_dev rcdev;
void __iomem *membase;
u32 clear_offset;
const struct stm32_reset_cfg **reset_lines;
};
static inline struct stm32_reset_data *
......@@ -27,22 +28,46 @@ to_stm32_reset_data(struct reset_controller_dev *rcdev)
return container_of(rcdev, struct stm32_reset_data, rcdev);
}
static const struct stm32_reset_cfg *stm32_get_reset_line(struct reset_controller_dev *rcdev,
unsigned long id,
struct stm32_reset_cfg *line)
{
struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
if (!data->reset_lines) {
int reg_width = sizeof(u32);
int bank = id / (reg_width * BITS_PER_BYTE);
int offset = id % (reg_width * BITS_PER_BYTE);
line->offset = bank * reg_width;
line->bit_idx = offset;
line->set_clr = (data->clear_offset ? true : false);
return line;
}
return data->reset_lines[id];
}
static int stm32_reset_update(struct reset_controller_dev *rcdev,
unsigned long id, bool assert)
{
struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
int reg_width = sizeof(u32);
int bank = id / (reg_width * BITS_PER_BYTE);
int offset = id % (reg_width * BITS_PER_BYTE);
struct stm32_reset_cfg line_reset;
const struct stm32_reset_cfg *ptr_line;
if (data->clear_offset) {
ptr_line = stm32_get_reset_line(rcdev, id, &line_reset);
if (!ptr_line)
return -EPERM;
if (ptr_line->set_clr) {
void __iomem *addr;
addr = data->membase + (bank * reg_width);
addr = data->membase + ptr_line->offset;
if (!assert)
addr += data->clear_offset;
writel(BIT(offset), addr);
writel(BIT(ptr_line->bit_idx), addr);
} else {
unsigned long flags;
......@@ -50,14 +75,14 @@ static int stm32_reset_update(struct reset_controller_dev *rcdev,
spin_lock_irqsave(&data->lock, flags);
reg = readl(data->membase + (bank * reg_width));
reg = readl(data->membase + ptr_line->offset);
if (assert)
reg |= BIT(offset);
reg |= BIT(ptr_line->bit_idx);
else
reg &= ~BIT(offset);
reg &= ~BIT(ptr_line->bit_idx);
writel(reg, data->membase + (bank * reg_width));
writel(reg, data->membase + ptr_line->offset);
spin_unlock_irqrestore(&data->lock, flags);
}
......@@ -81,14 +106,17 @@ static int stm32_reset_status(struct reset_controller_dev *rcdev,
unsigned long id)
{
struct stm32_reset_data *data = to_stm32_reset_data(rcdev);
int reg_width = sizeof(u32);
int bank = id / (reg_width * BITS_PER_BYTE);
int offset = id % (reg_width * BITS_PER_BYTE);
struct stm32_reset_cfg line_reset;
const struct stm32_reset_cfg *ptr_line;
u32 reg;
reg = readl(data->membase + (bank * reg_width));
ptr_line = stm32_get_reset_line(rcdev, id, &line_reset);
if (!ptr_line)
return -EPERM;
reg = readl(data->membase + ptr_line->offset);
return !!(reg & BIT(offset));
return !!(reg & BIT(ptr_line->bit_idx));
}
static const struct reset_control_ops stm32_reset_ops = {
......@@ -113,6 +141,7 @@ int stm32_rcc_reset_init(struct device *dev, struct clk_stm32_reset_data *data,
reset_data->rcdev.ops = &stm32_reset_ops;
reset_data->rcdev.of_node = dev_of_node(dev);
reset_data->rcdev.nr_resets = data->nr_lines;
reset_data->reset_lines = data->reset_lines;
reset_data->clear_offset = data->clear_offset;
return reset_controller_register(&reset_data->rcdev);
......
......@@ -4,8 +4,15 @@
* Author: Gabriel Fernandez <gabriel.fernandez@foss.st.com> for STMicroelectronics.
*/
struct stm32_reset_cfg {
u16 offset;
u8 bit_idx;
bool set_clr;
};
struct clk_stm32_reset_data {
const struct reset_control_ops *ops;
const struct stm32_reset_cfg **reset_lines;
unsigned int nr_lines;
u32 clear_offset;
};
......
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment