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

clk: stm32f469: Add QSPI clock

This patch adds the QSPI clock for stm32f469 discovery board.
The gate mapping is a little bit different from stm32f429 soc.
Signed-off-by: default avatarGabriel Fernandez <gabriel.fernandez@st.com>
Acked-by: default avatarRob Herring <robh@kernel.org>
Signed-off-by: default avatarStephen Boyd <sboyd@codeaurora.org>
parent 4261a881
...@@ -7,7 +7,9 @@ Please refer to clock-bindings.txt for common clock controller binding usage. ...@@ -7,7 +7,9 @@ Please refer to clock-bindings.txt for common clock controller binding usage.
Please also refer to reset.txt for common reset controller binding usage. Please also refer to reset.txt for common reset controller binding usage.
Required properties: Required properties:
- compatible: Should be "st,stm32f42xx-rcc" - compatible: Should be:
"st,stm32f42xx-rcc"
"st,stm32f469-rcc"
- reg: should be register base and length as documented in the - reg: should be register base and length as documented in the
datasheet datasheet
- #reset-cells: 1, see below - #reset-cells: 1, see below
......
...@@ -46,7 +46,7 @@ struct stm32f4_gate_data { ...@@ -46,7 +46,7 @@ struct stm32f4_gate_data {
unsigned long flags; unsigned long flags;
}; };
static const struct stm32f4_gate_data stm32f4_gates[] __initconst = { static const struct stm32f4_gate_data stm32f429_gates[] __initconst = {
{ STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" }, { STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" }, { STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" }, { STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
...@@ -126,22 +126,108 @@ static const struct stm32f4_gate_data stm32f4_gates[] __initconst = { ...@@ -126,22 +126,108 @@ static const struct stm32f4_gate_data stm32f4_gates[] __initconst = {
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" }, { STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
}; };
static const struct stm32f4_gate_data stm32f469_gates[] __initconst = {
{ STM32F4_RCC_AHB1ENR, 0, "gpioa", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 1, "gpiob", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 2, "gpioc", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 3, "gpiod", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 4, "gpioe", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 5, "gpiof", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 6, "gpiog", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 7, "gpioh", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 8, "gpioi", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 9, "gpioj", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 10, "gpiok", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 12, "crc", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 18, "bkpsra", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 20, "ccmdatam", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 21, "dma1", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 22, "dma2", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 23, "dma2d", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 25, "ethmac", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 26, "ethmactx", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 27, "ethmacrx", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 28, "ethmacptp", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 29, "otghs", "ahb_div" },
{ STM32F4_RCC_AHB1ENR, 30, "otghsulpi", "ahb_div" },
{ STM32F4_RCC_AHB2ENR, 0, "dcmi", "ahb_div" },
{ STM32F4_RCC_AHB2ENR, 4, "cryp", "ahb_div" },
{ STM32F4_RCC_AHB2ENR, 5, "hash", "ahb_div" },
{ STM32F4_RCC_AHB2ENR, 6, "rng", "pll48" },
{ STM32F4_RCC_AHB2ENR, 7, "otgfs", "pll48" },
{ STM32F4_RCC_AHB3ENR, 0, "fmc", "ahb_div",
CLK_IGNORE_UNUSED },
{ STM32F4_RCC_AHB3ENR, 1, "qspi", "ahb_div",
CLK_IGNORE_UNUSED },
{ STM32F4_RCC_APB1ENR, 0, "tim2", "apb1_mul" },
{ STM32F4_RCC_APB1ENR, 1, "tim3", "apb1_mul" },
{ STM32F4_RCC_APB1ENR, 2, "tim4", "apb1_mul" },
{ STM32F4_RCC_APB1ENR, 3, "tim5", "apb1_mul" },
{ STM32F4_RCC_APB1ENR, 4, "tim6", "apb1_mul" },
{ STM32F4_RCC_APB1ENR, 5, "tim7", "apb1_mul" },
{ STM32F4_RCC_APB1ENR, 6, "tim12", "apb1_mul" },
{ STM32F4_RCC_APB1ENR, 7, "tim13", "apb1_mul" },
{ STM32F4_RCC_APB1ENR, 8, "tim14", "apb1_mul" },
{ STM32F4_RCC_APB1ENR, 11, "wwdg", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 14, "spi2", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 15, "spi3", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 17, "uart2", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 18, "uart3", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 19, "uart4", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 20, "uart5", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 21, "i2c1", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 22, "i2c2", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 23, "i2c3", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 25, "can1", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 26, "can2", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 28, "pwr", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 29, "dac", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 30, "uart7", "apb1_div" },
{ STM32F4_RCC_APB1ENR, 31, "uart8", "apb1_div" },
{ STM32F4_RCC_APB2ENR, 0, "tim1", "apb2_mul" },
{ STM32F4_RCC_APB2ENR, 1, "tim8", "apb2_mul" },
{ STM32F4_RCC_APB2ENR, 4, "usart1", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 5, "usart6", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 8, "adc1", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 9, "adc2", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 10, "adc3", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 11, "sdio", "pll48" },
{ STM32F4_RCC_APB2ENR, 12, "spi1", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 13, "spi4", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 14, "syscfg", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 16, "tim9", "apb2_mul" },
{ STM32F4_RCC_APB2ENR, 17, "tim10", "apb2_mul" },
{ STM32F4_RCC_APB2ENR, 18, "tim11", "apb2_mul" },
{ STM32F4_RCC_APB2ENR, 20, "spi5", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 21, "spi6", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 22, "sai1", "apb2_div" },
{ STM32F4_RCC_APB2ENR, 26, "ltdc", "apb2_div" },
};
enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK }; enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK };
/*
* MAX_CLKS is the maximum value in the enumeration below plus the combined
* hweight of stm32f42xx_gate_map (plus one).
*/
#define MAX_CLKS (71 + END_PRIMARY_CLK + 1)
/* /*
* This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
* have gate bits associated with them. Its combined hweight is 71. * have gate bits associated with them. Its combined hweight is 71.
*/ */
static const u64 stm32f42xx_gate_map[] = { 0x000000f17ef417ffull, #define MAX_GATE_MAP 3
0x0000000000000001ull,
0x04777f33f6fec9ffull }; static const u64 stm32f42xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
0x0000000000000001ull,
0x04777f33f6fec9ffull };
static const u64 stm32f46xx_gate_map[MAX_GATE_MAP] = { 0x000000f17ef417ffull,
0x0000000000000003ull,
0x0c777f33f6fec9ffull };
static const u64 *stm32f4_gate_map;
static struct clk_hw **clks;
static struct clk_hw *clks[MAX_CLKS];
static DEFINE_SPINLOCK(stm32f4_clk_lock); static DEFINE_SPINLOCK(stm32f4_clk_lock);
static void __iomem *base; static void __iomem *base;
...@@ -263,7 +349,7 @@ static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk) ...@@ -263,7 +349,7 @@ static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk)
*/ */
static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
{ {
u64 table[ARRAY_SIZE(stm32f42xx_gate_map)]; u64 table[MAX_GATE_MAP];
if (primary == 1) { if (primary == 1) {
if (WARN_ON(secondary >= END_PRIMARY_CLK)) if (WARN_ON(secondary >= END_PRIMARY_CLK))
...@@ -271,7 +357,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary) ...@@ -271,7 +357,7 @@ static int stm32f4_rcc_lookup_clk_idx(u8 primary, u8 secondary)
return secondary; return secondary;
} }
memcpy(table, stm32f42xx_gate_map, sizeof(table)); memcpy(table, stm32f4_gate_map, sizeof(table));
/* only bits set in table can be used as indices */ /* only bits set in table can be used as indices */
if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) || if (WARN_ON(secondary >= BITS_PER_BYTE * sizeof(table) ||
...@@ -525,10 +611,42 @@ static const char *rtc_parents[4] = { ...@@ -525,10 +611,42 @@ static const char *rtc_parents[4] = {
"no-clock", "lse", "lsi", "hse-rtc" "no-clock", "lse", "lsi", "hse-rtc"
}; };
struct stm32f4_clk_data {
const struct stm32f4_gate_data *gates_data;
const u64 *gates_map;
int gates_num;
};
static const struct stm32f4_clk_data stm32f429_clk_data = {
.gates_data = stm32f429_gates,
.gates_map = stm32f42xx_gate_map,
.gates_num = ARRAY_SIZE(stm32f429_gates),
};
static const struct stm32f4_clk_data stm32f469_clk_data = {
.gates_data = stm32f469_gates,
.gates_map = stm32f46xx_gate_map,
.gates_num = ARRAY_SIZE(stm32f469_gates),
};
static const struct of_device_id stm32f4_of_match[] = {
{
.compatible = "st,stm32f42xx-rcc",
.data = &stm32f429_clk_data
},
{
.compatible = "st,stm32f469-rcc",
.data = &stm32f469_clk_data
},
{}
};
static void __init stm32f4_rcc_init(struct device_node *np) static void __init stm32f4_rcc_init(struct device_node *np)
{ {
const char *hse_clk; const char *hse_clk;
int n; int n;
const struct of_device_id *match;
const struct stm32f4_clk_data *data;
base = of_iomap(np, 0); base = of_iomap(np, 0);
if (!base) { if (!base) {
...@@ -542,6 +660,19 @@ static void __init stm32f4_rcc_init(struct device_node *np) ...@@ -542,6 +660,19 @@ static void __init stm32f4_rcc_init(struct device_node *np)
pr_warn("%s: Unable to get syscfg\n", __func__); pr_warn("%s: Unable to get syscfg\n", __func__);
} }
match = of_match_node(stm32f4_of_match, np);
if (WARN_ON(!match))
return;
data = match->data;
clks = kmalloc_array(data->gates_num + END_PRIMARY_CLK,
sizeof(*clks), GFP_KERNEL);
if (!clks)
goto fail;
stm32f4_gate_map = data->gates_map;
hse_clk = of_clk_get_parent_name(np, 0); hse_clk = of_clk_get_parent_name(np, 0);
clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0, clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
...@@ -574,11 +705,15 @@ static void __init stm32f4_rcc_init(struct device_node *np) ...@@ -574,11 +705,15 @@ static void __init stm32f4_rcc_init(struct device_node *np)
clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div", clks[FCLK] = clk_hw_register_fixed_factor(NULL, "fclk", "ahb_div",
0, 1, 1); 0, 1, 1);
for (n = 0; n < ARRAY_SIZE(stm32f4_gates); n++) { for (n = 0; n < data->gates_num; n++) {
const struct stm32f4_gate_data *gd = &stm32f4_gates[n]; const struct stm32f4_gate_data *gd;
unsigned int secondary = unsigned int secondary;
8 * (gd->offset - STM32F4_RCC_AHB1ENR) + gd->bit_idx; int idx;
int idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
gd = &data->gates_data[n];
secondary = 8 * (gd->offset - STM32F4_RCC_AHB1ENR) +
gd->bit_idx;
idx = stm32f4_rcc_lookup_clk_idx(0, secondary);
if (idx < 0) if (idx < 0)
goto fail; goto fail;
...@@ -630,6 +765,8 @@ static void __init stm32f4_rcc_init(struct device_node *np) ...@@ -630,6 +765,8 @@ static void __init stm32f4_rcc_init(struct device_node *np)
of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL); of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
return; return;
fail: fail:
kfree(clks);
iounmap(base); iounmap(base);
} }
CLK_OF_DECLARE(stm32f4_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init); CLK_OF_DECLARE(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
CLK_OF_DECLARE(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
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