clk: stm32f7: add clock driver for stm32f7 family

add basic clock driver support for stm32f7 to enable clocks required by
the peripherals.

Signed-off-by: Vikas Manocha <vikas.manocha@st.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
This commit is contained in:
Vikas Manocha 2017-02-12 10:25:45 -08:00 committed by Tom Rini
parent 42bf5e7c27
commit 712f99a5dd
6 changed files with 157 additions and 6 deletions

View File

@ -5,4 +5,4 @@
# SPDX-License-Identifier: GPL-2.0+
#
obj-y += timer.o clock.o soc.o
obj-y += timer.o soc.o

View File

@ -17,8 +17,6 @@ u32 get_cpu_rev(void)
int arch_cpu_init(void)
{
configure_clocks();
/*
* Configure the memory protection unit (MPU)
* 0x00000000 - 0xffffffff: Strong-order, Shareable

View File

@ -39,3 +39,4 @@ CONFIG_DM_SPI=y
CONFIG_STM32_QSPI=y
CONFIG_OF_LIBFDT_OVERLAY=y
# CONFIG_EFI_LOADER is not set
CONFIG_CLK=y

View File

@ -0,0 +1,95 @@
STMicroelectronics STM32 Reset and Clock Controller
===================================================
The RCC IP is both a reset and a clock controller.
Please refer to clock-bindings.txt for common clock controller binding usage.
Please also refer to reset.txt for common reset controller binding usage.
Required properties:
- compatible: Should be:
"st,stm32f42xx-rcc"
"st,stm32f469-rcc"
- reg: should be register base and length as documented in the
datasheet
- #reset-cells: 1, see below
- #clock-cells: 2, device nodes should specify the clock in their "clocks"
property, containing a phandle to the clock device node, an index selecting
between gated clocks and other clocks and an index specifying the clock to
use.
Example:
rcc: rcc@40023800 {
#reset-cells = <1>;
#clock-cells = <2>
compatible = "st,stm32f42xx-rcc", "st,stm32-rcc";
reg = <0x40023800 0x400>;
};
Specifying gated clocks
=======================
The primary index must be set to 0.
The secondary index is the bit number within the RCC register bank, starting
from the first RCC clock enable register (RCC_AHB1ENR, address offset 0x30).
It is calculated as: index = register_offset / 4 * 32 + bit_offset.
Where bit_offset is the bit offset within the register (LSB is 0, MSB is 31).
To simplify the usage and to share bit definition with the reset and clock
drivers of the RCC IP, macros are available to generate the index in
human-readble format.
For STM32F4 series, the macro are available here:
- include/dt-bindings/mfd/stm32f4-rcc.h
Example:
/* Gated clock, AHB1 bit 0 (GPIOA) */
... {
clocks = <&rcc 0 STM32F4_AHB1_CLOCK(GPIOA)>
};
/* Gated clock, AHB2 bit 4 (CRYP) */
... {
clocks = <&rcc 0 STM32F4_AHB2_CLOCK(CRYP)>
};
Specifying other clocks
=======================
The primary index must be set to 1.
The secondary index is bound with the following magic numbers:
0 SYSTICK
1 FCLK
Example:
/* Misc clock, FCLK */
... {
clocks = <&rcc 1 STM32F4_APB1_CLOCK(TIM2)>
};
Specifying softreset control of devices
=======================================
Device nodes should specify the reset channel required in their "resets"
property, containing a phandle to the reset device node and an index specifying
which channel to use.
The index is the bit number within the RCC registers bank, starting from RCC
base address.
It is calculated as: index = register_offset / 4 * 32 + bit_offset.
Where bit_offset is the bit offset within the register.
For example, for CRC reset:
crc = AHB1RSTR_offset / 4 * 32 + CRCRST_bit_offset = 0x10 / 4 * 32 + 12 = 140
example:
timer2 {
resets = <&rcc STM32F4_APB1_RESET(TIM2)>;
};

View File

@ -18,5 +18,5 @@ obj-$(CONFIG_CLK_UNIPHIER) += uniphier/
obj-$(CONFIG_CLK_EXYNOS) += exynos/
obj-$(CONFIG_CLK_AT91) += at91/
obj-$(CONFIG_CLK_BOSTON) += clk_boston.o
obj-$(CONFIG_ARCH_ASPEED) += aspeed/
obj-$(CONFIG_STM32F7) += clk_stm32f7.o

View File

@ -1,11 +1,12 @@
/*
* (C) Copyright 2016
* (C) Copyright 2017
* Vikas Manocha, <vikas.manocha@st.com>
*
* SPDX-License-Identifier: GPL-2.0+
*/
#include <common.h>
#include <clk-uclass.h>
#include <dm.h>
#include <asm/io.h>
#include <asm/arch/rcc.h>
#include <asm/arch/stm32.h>
@ -212,6 +213,17 @@ unsigned long clock_get(enum clock clck)
}
}
static int stm32_clk_enable(struct clk *clk)
{
u32 offset = clk->id / 32;
u32 bit_index = clk->id % 32;
debug("%s: clkid = %ld, offset from AHB1ENR is %d, bit_index = %d\n",
__func__, clk->id, offset, bit_index);
setbits_le32(&STM32_RCC->ahb1enr + offset, BIT(bit_index));
return 0;
}
void clock_setup(int peripheral)
{
@ -273,3 +285,48 @@ void clock_setup(int peripheral)
break;
}
}
static int stm32_clk_probe(struct udevice *dev)
{
debug("%s: stm32_clk_probe\n", __func__);
configure_clocks();
return 0;
}
static int stm32_clk_of_xlate(struct clk *clk,
struct fdtdec_phandle_args *args)
{
debug("%s(clk=%p)\n", __func__, clk);
if (args->args_count != 2) {
debug("Invaild args_count: %d\n", args->args_count);
return -EINVAL;
}
if (args->args_count)
clk->id = args->args[1];
else
clk->id = 0;
return 0;
}
static struct clk_ops stm32_clk_ops = {
.of_xlate = stm32_clk_of_xlate,
.enable = stm32_clk_enable,
};
static const struct udevice_id stm32_clk_ids[] = {
{ .compatible = "st,stm32f42xx-rcc"},
{}
};
U_BOOT_DRIVER(stm32f7_clk) = {
.name = "stm32f7_clk",
.id = UCLASS_CLK,
.of_match = stm32_clk_ids,
.ops = &stm32_clk_ops,
.probe = stm32_clk_probe,
.flags = DM_FLAG_PRE_RELOC,
};