]> Git Repo - linux.git/commitdiff
Merge branches 'clk-qcom-rpm8974', 'clk-stm32f4', 'clk-ipq4019' and 'clk-fixes' into...
authorStephen Boyd <[email protected]>
Tue, 10 Jan 2017 00:06:11 +0000 (16:06 -0800)
committerStephen Boyd <[email protected]>
Tue, 10 Jan 2017 00:06:11 +0000 (16:06 -0800)
* clk-qcom-rpm8974:
  clk: qcom: smd-rpmcc: Add msm8974 clocks

* clk-stm32f4:
  clk: stm32f4: SDIO & 48Mhz clock management for STM32F469 board
  clk: stm32f4: Add SAI clocks
  clk: stm32f4: Add I2S clock
  clk: stm32f4: Add lcd-tft clock
  clk: stm32f4: Add post divisor for I2S & SAI PLLs
  clk: stm32f4: Add PLL_I2S & PLL_SAI for STM32F429/469 boards
  clk: stm32f4: Update DT bindings documentation

* clk-ipq4019:
  clk: qcom: ipq4019: Add the cpu clock frequency change notifier
  clk: qcom: ipq4019: Add all the frequencies for apss cpu
  clk: qcom: ipq4019: correct sdcc frequency and parent name
  clk: qcom: ipq4019: Add the nodes for pcnoc
  clk: qcom: ipq4019: Add the apss cpu pll divider clock node
  clk: qcom: ipq4019: remove fixed clocks and add pll clocks

* clk-fixes:
  clk: stm32f4: Use CLK_OF_DECLARE_DRIVER initialization method
  clk: renesas: mstp: Support 8-bit registers for r7s72100

1  2  3  4  5 
drivers/clk/clk-stm32f4.c

index 5eb05dbf59b84d27d79106adeb7405d15de1433a,5eb05dbf59b84d27d79106adeb7405d15de1433a,da109f63e85e4a3e59323f429ad13747877db26a,5eb05dbf59b84d27d79106adeb7405d15de1433a,fc585f370549a336ea12cc5c323dbc77aec69825..42f8534996def2aa66131adc5091400a3c27a4b5
     #include <linux/regmap.h>
     #include <linux/mfd/syscon.h>
     
++ ++/*
++ ++ * Include list of clocks wich are not derived from system clock (SYSCLOCK)
++ ++ * The index of these clocks is the secondary index of DT bindings
++ ++ *
++ ++ */
++ ++#include <dt-bindings/clock/stm32fx-clock.h>
++ ++
++ ++#define STM32F4_RCC_CR                     0x00
     #define STM32F4_RCC_PLLCFGR                0x04
     #define STM32F4_RCC_CFGR           0x08
     #define STM32F4_RCC_AHB1ENR                0x30
     #define STM32F4_RCC_APB2ENR                0x44
     #define STM32F4_RCC_BDCR           0x70
     #define STM32F4_RCC_CSR                    0x74
++ ++#define STM32F4_RCC_PLLI2SCFGR             0x84
++ ++#define STM32F4_RCC_PLLSAICFGR             0x88
++ ++#define STM32F4_RCC_DCKCFGR                0x8c
++ ++
++ ++#define NONE -1
++ ++#define NO_IDX  NONE
++ ++#define NO_MUX  NONE
++ ++#define NO_GATE NONE
     
     struct stm32f4_gate_data {
        u8      offset;
@@@@@@ -195,7 -195,7 -211,7 -195,7 -195,7 +211,7 @@@@@@ static const struct stm32f4_gate_data s
        { 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, 11,      "sdio",         "sdmux" },
        { STM32F4_RCC_APB2ENR, 12,      "spi1",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 13,      "spi4",         "apb2_div" },
        { STM32F4_RCC_APB2ENR, 14,      "syscfg",       "apb2_div" },
        { STM32F4_RCC_APB2ENR, 26,      "ltdc",         "apb2_div" },
     };
     
-- --enum { SYSTICK, FCLK, CLK_LSI, CLK_LSE, CLK_HSE_RTC, CLK_RTC, END_PRIMARY_CLK };
-- --
     /*
      * This bitmask tells us which bit offsets (0..192) on STM32F4[23]xxx
      * have gate bits associated with them. Its combined hweight is 71.
@@@@@@ -324,23 -324,23 -338,342 -324,23 -324,23 +338,342 @@@@@@ static struct clk *clk_register_apb_mul
        return clk;
     }
     
-- --/*
-- -- * Decode current PLL state and (statically) model the state we inherit from
-- -- * the bootloader.
-- -- */
-- --static void stm32f4_rcc_register_pll(const char *hse_clk, const char *hsi_clk)
++ ++enum {
++ ++   PLL,
++ ++   PLL_I2S,
++ ++   PLL_SAI,
++ ++};
++ ++
++ ++static const struct clk_div_table pll_divp_table[] = {
++ ++   { 0, 2 }, { 1, 4 }, { 2, 6 }, { 3, 8 }, { 0 }
++ ++};
++ ++
++ ++static const struct clk_div_table pll_divr_table[] = {
++ ++   { 2, 2 }, { 3, 3 }, { 4, 4 }, { 5, 5 }, { 6, 6 }, { 7, 7 }, { 0 }
++ ++};
++ ++
++ ++struct stm32f4_pll {
++ ++   spinlock_t *lock;
++ ++   struct  clk_gate gate;
++ ++   u8 offset;
++ ++   u8 bit_rdy_idx;
++ ++   u8 status;
++ ++   u8 n_start;
++ ++};
++ ++
++ ++#define to_stm32f4_pll(_gate) container_of(_gate, struct stm32f4_pll, gate)
++ ++
++ ++struct stm32f4_pll_post_div_data {
++ ++   int idx;
++ ++   u8 pll_num;
++ ++   const char *name;
++ ++   const char *parent;
++ ++   u8 flag;
++ ++   u8 offset;
++ ++   u8 shift;
++ ++   u8 width;
++ ++   u8 flag_div;
++ ++   const struct clk_div_table *div_table;
++ ++};
++ ++
++ ++struct stm32f4_vco_data {
++ ++   const char *vco_name;
++ ++   u8 offset;
++ ++   u8 bit_idx;
++ ++   u8 bit_rdy_idx;
++ ++};
++ ++
++ ++static const struct stm32f4_vco_data  vco_data[] = {
++ ++   { "vco",     STM32F4_RCC_PLLCFGR,    24, 25 },
++ ++   { "vco-i2s", STM32F4_RCC_PLLI2SCFGR, 26, 27 },
++ ++   { "vco-sai", STM32F4_RCC_PLLSAICFGR, 28, 29 },
++ ++};
++ ++
++ ++
++ ++static const struct clk_div_table post_divr_table[] = {
++ ++   { 0, 2 }, { 1, 4 }, { 2, 8 }, { 3, 16 }, { 0 }
++ ++};
++ ++
++ ++#define MAX_POST_DIV 3
++ ++static const struct stm32f4_pll_post_div_data  post_div_data[MAX_POST_DIV] = {
++ ++   { CLK_I2SQ_PDIV, PLL_I2S, "plli2s-q-div", "plli2s-q",
++ ++           CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 0, 5, 0, NULL},
++ ++
++ ++   { CLK_SAIQ_PDIV, PLL_SAI, "pllsai-q-div", "pllsai-q",
++ ++           CLK_SET_RATE_PARENT, STM32F4_RCC_DCKCFGR, 8, 5, 0, NULL },
++ ++
++ ++   { NO_IDX, PLL_SAI, "pllsai-r-div", "pllsai-r", CLK_SET_RATE_PARENT,
++ ++           STM32F4_RCC_DCKCFGR, 16, 2, 0, post_divr_table },
++ ++};
++ ++
++ ++struct stm32f4_div_data {
++ ++   u8 shift;
++ ++   u8 width;
++ ++   u8 flag_div;
++ ++   const struct clk_div_table *div_table;
++ ++};
++ ++
++ ++#define MAX_PLL_DIV 3
++ ++static const struct stm32f4_div_data  div_data[MAX_PLL_DIV] = {
++ ++   { 16, 2, 0,                     pll_divp_table  },
++ ++   { 24, 4, CLK_DIVIDER_ONE_BASED, NULL            },
++ ++   { 28, 3, 0,                     pll_divr_table  },
++ ++};
++ ++
++ ++struct stm32f4_pll_data {
++ ++   u8 pll_num;
++ ++   u8 n_start;
++ ++   const char *div_name[MAX_PLL_DIV];
++ ++};
++ ++
++ ++static const struct stm32f4_pll_data stm32f429_pll[MAX_PLL_DIV] = {
++ ++   { PLL,     192, { "pll", "pll48",    NULL       } },
++ ++   { PLL_I2S, 192, { NULL,  "plli2s-q", "plli2s-r" } },
++ ++   { PLL_SAI,  49, { NULL,  "pllsai-q", "pllsai-r" } },
++ ++};
++ ++
++ ++static const struct stm32f4_pll_data stm32f469_pll[MAX_PLL_DIV] = {
++ ++   { PLL,     50, { "pll",      "pll-q",    NULL       } },
++ ++   { PLL_I2S, 50, { "plli2s-p", "plli2s-q", "plli2s-r" } },
++ ++   { PLL_SAI, 50, { "pllsai-p", "pllsai-q", "pllsai-r" } },
++ ++};
++ ++
++ ++static int stm32f4_pll_is_enabled(struct clk_hw *hw)
++ ++{
++ ++   return clk_gate_ops.is_enabled(hw);
++ ++}
++ ++
++ ++static int stm32f4_pll_enable(struct clk_hw *hw)
++ ++{
++ ++   struct clk_gate *gate = to_clk_gate(hw);
++ ++   struct stm32f4_pll *pll = to_stm32f4_pll(gate);
++ ++   int ret = 0;
++ ++   unsigned long reg;
++ ++
++ ++   ret = clk_gate_ops.enable(hw);
++ ++
++ ++   ret = readl_relaxed_poll_timeout_atomic(base + STM32F4_RCC_CR, reg,
++ ++                   reg & (1 << pll->bit_rdy_idx), 0, 10000);
++ ++
++ ++   return ret;
++ ++}
++ ++
++ ++static void stm32f4_pll_disable(struct clk_hw *hw)
++ ++{
++ ++   clk_gate_ops.disable(hw);
++ ++}
++ ++
++ ++static unsigned long stm32f4_pll_recalc(struct clk_hw *hw,
++ ++           unsigned long parent_rate)
++ ++{
++ ++   struct clk_gate *gate = to_clk_gate(hw);
++ ++   struct stm32f4_pll *pll = to_stm32f4_pll(gate);
++ ++   unsigned long n;
++ ++
++ ++   n = (readl(base + pll->offset) >> 6) & 0x1ff;
++ ++
++ ++   return parent_rate * n;
++ ++}
++ ++
++ ++static long stm32f4_pll_round_rate(struct clk_hw *hw, unsigned long rate,
++ ++           unsigned long *prate)
++ ++{
++ ++   struct clk_gate *gate = to_clk_gate(hw);
++ ++   struct stm32f4_pll *pll = to_stm32f4_pll(gate);
++ ++   unsigned long n;
++ ++
++ ++   n = rate / *prate;
++ ++
++ ++   if (n < pll->n_start)
++ ++           n = pll->n_start;
++ ++   else if (n > 432)
++ ++           n = 432;
++ ++
++ ++   return *prate * n;
++ ++}
++ ++
++ ++static int stm32f4_pll_set_rate(struct clk_hw *hw, unsigned long rate,
++ ++                           unsigned long parent_rate)
++ ++{
++ ++   struct clk_gate *gate = to_clk_gate(hw);
++ ++   struct stm32f4_pll *pll = to_stm32f4_pll(gate);
++ ++
++ ++   unsigned long n;
++ ++   unsigned long val;
++ ++   int pll_state;
++ ++
++ ++   pll_state = stm32f4_pll_is_enabled(hw);
++ ++
++ ++   if (pll_state)
++ ++           stm32f4_pll_disable(hw);
++ ++
++ ++   n = rate  / parent_rate;
++ ++
++ ++   val = readl(base + pll->offset) & ~(0x1ff << 6);
++ ++
++ ++   writel(val | ((n & 0x1ff) <<  6), base + pll->offset);
++ ++
++ ++   if (pll_state)
++ ++           stm32f4_pll_enable(hw);
++ ++
++ ++   return 0;
++ ++}
++ ++
++ ++static const struct clk_ops stm32f4_pll_gate_ops = {
++ ++   .enable         = stm32f4_pll_enable,
++ ++   .disable        = stm32f4_pll_disable,
++ ++   .is_enabled     = stm32f4_pll_is_enabled,
++ ++   .recalc_rate    = stm32f4_pll_recalc,
++ ++   .round_rate     = stm32f4_pll_round_rate,
++ ++   .set_rate       = stm32f4_pll_set_rate,
++ ++};
++ ++
++ ++struct stm32f4_pll_div {
++ ++   struct clk_divider div;
++ ++   struct clk_hw *hw_pll;
++ ++};
++ ++
++ ++#define to_pll_div_clk(_div) container_of(_div, struct stm32f4_pll_div, div)
++ ++
++ ++static unsigned long stm32f4_pll_div_recalc_rate(struct clk_hw *hw,
++ ++           unsigned long parent_rate)
++ ++{
++ ++   return clk_divider_ops.recalc_rate(hw, parent_rate);
++ ++}
++ ++
++ ++static long stm32f4_pll_div_round_rate(struct clk_hw *hw, unsigned long rate,
++ ++                           unsigned long *prate)
++ ++{
++ ++   return clk_divider_ops.round_rate(hw, rate, prate);
++ ++}
++ ++
++ ++static int stm32f4_pll_div_set_rate(struct clk_hw *hw, unsigned long rate,
++ ++                           unsigned long parent_rate)
     {
-- --   unsigned long pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
++ ++   int pll_state, ret;
++ ++
++ ++   struct clk_divider *div = to_clk_divider(hw);
++ ++   struct stm32f4_pll_div *pll_div = to_pll_div_clk(div);
++ ++
++ ++   pll_state = stm32f4_pll_is_enabled(pll_div->hw_pll);
++ ++
++ ++   if (pll_state)
++ ++           stm32f4_pll_disable(pll_div->hw_pll);
++ ++
++ ++   ret = clk_divider_ops.set_rate(hw, rate, parent_rate);
     
-- --   unsigned long pllm   = pllcfgr & 0x3f;
-- --   unsigned long plln   = (pllcfgr >> 6) & 0x1ff;
-- --   unsigned long pllp   = BIT(((pllcfgr >> 16) & 3) + 1);
-- --   const char   *pllsrc = pllcfgr & BIT(22) ? hse_clk : hsi_clk;
-- --   unsigned long pllq   = (pllcfgr >> 24) & 0xf;
++ ++   if (pll_state)
++ ++           stm32f4_pll_enable(pll_div->hw_pll);
     
-- --   clk_register_fixed_factor(NULL, "vco", pllsrc, 0, plln, pllm);
-- --   clk_register_fixed_factor(NULL, "pll", "vco", 0, 1, pllp);
-- --   clk_register_fixed_factor(NULL, "pll48", "vco", 0, 1, pllq);
++ ++   return ret;
++ ++}
++ ++
++ ++static const struct clk_ops stm32f4_pll_div_ops = {
++ ++   .recalc_rate = stm32f4_pll_div_recalc_rate,
++ ++   .round_rate = stm32f4_pll_div_round_rate,
++ ++   .set_rate = stm32f4_pll_div_set_rate,
++ ++};
++ ++
++ ++static struct clk_hw *clk_register_pll_div(const char *name,
++ ++           const char *parent_name, unsigned long flags,
++ ++           void __iomem *reg, u8 shift, u8 width,
++ ++           u8 clk_divider_flags, const struct clk_div_table *table,
++ ++           struct clk_hw *pll_hw, spinlock_t *lock)
++ ++{
++ ++   struct stm32f4_pll_div *pll_div;
++ ++   struct clk_hw *hw;
++ ++   struct clk_init_data init;
++ ++   int ret;
++ ++
++ ++   /* allocate the divider */
++ ++   pll_div = kzalloc(sizeof(*pll_div), GFP_KERNEL);
++ ++   if (!pll_div)
++ ++           return ERR_PTR(-ENOMEM);
++ ++
++ ++   init.name = name;
++ ++   init.ops = &stm32f4_pll_div_ops;
++ ++   init.flags = flags;
++ ++   init.parent_names = (parent_name ? &parent_name : NULL);
++ ++   init.num_parents = (parent_name ? 1 : 0);
++ ++
++ ++   /* struct clk_divider assignments */
++ ++   pll_div->div.reg = reg;
++ ++   pll_div->div.shift = shift;
++ ++   pll_div->div.width = width;
++ ++   pll_div->div.flags = clk_divider_flags;
++ ++   pll_div->div.lock = lock;
++ ++   pll_div->div.table = table;
++ ++   pll_div->div.hw.init = &init;
++ ++
++ ++   pll_div->hw_pll = pll_hw;
++ ++
++ ++   /* register the clock */
++ ++   hw = &pll_div->div.hw;
++ ++   ret = clk_hw_register(NULL, hw);
++ ++   if (ret) {
++ ++           kfree(pll_div);
++ ++           hw = ERR_PTR(ret);
++ ++   }
++ ++
++ ++   return hw;
++ ++}
++ ++
++ ++static struct clk_hw *stm32f4_rcc_register_pll(const char *pllsrc,
++ ++           const struct stm32f4_pll_data *data,  spinlock_t *lock)
++ ++{
++ ++   struct stm32f4_pll *pll;
++ ++   struct clk_init_data init = { NULL };
++ ++   void __iomem *reg;
++ ++   struct clk_hw *pll_hw;
++ ++   int ret;
++ ++   int i;
++ ++   const struct stm32f4_vco_data *vco;
++ ++
++ ++
++ ++   pll = kzalloc(sizeof(*pll), GFP_KERNEL);
++ ++   if (!pll)
++ ++           return ERR_PTR(-ENOMEM);
++ ++
++ ++   vco = &vco_data[data->pll_num];
++ ++
++ ++   init.name = vco->vco_name;
++ ++   init.ops = &stm32f4_pll_gate_ops;
++ ++   init.flags = CLK_SET_RATE_GATE;
++ ++   init.parent_names = &pllsrc;
++ ++   init.num_parents = 1;
++ ++
++ ++   pll->gate.lock = lock;
++ ++   pll->gate.reg = base + STM32F4_RCC_CR;
++ ++   pll->gate.bit_idx = vco->bit_idx;
++ ++   pll->gate.hw.init = &init;
++ ++
++ ++   pll->offset = vco->offset;
++ ++   pll->n_start = data->n_start;
++ ++   pll->bit_rdy_idx = vco->bit_rdy_idx;
++ ++   pll->status = (readl(base + STM32F4_RCC_CR) >> vco->bit_idx) & 0x1;
++ ++
++ ++   reg = base + pll->offset;
++ ++
++ ++   pll_hw = &pll->gate.hw;
++ ++   ret = clk_hw_register(NULL, pll_hw);
++ ++   if (ret) {
++ ++           kfree(pll);
++ ++           return ERR_PTR(ret);
++ ++   }
++ ++
++ ++   for (i = 0; i < MAX_PLL_DIV; i++)
++ ++           if (data->div_name[i])
++ ++                   clk_register_pll_div(data->div_name[i],
++ ++                                   vco->vco_name,
++ ++                                   0,
++ ++                                   reg,
++ ++                                   div_data[i].shift,
++ ++                                   div_data[i].width,
++ ++                                   div_data[i].flag_div,
++ ++                                   div_data[i].div_table,
++ ++                                   pll_hw,
++ ++                                   lock);
++ ++   return pll_hw;
     }
     
     /*
@@@@@@ -611,22 -611,22 -944,121 -611,22 -611,22 +944,121 @@@@@@ static const char *rtc_parents[4] = 
        "no-clock", "lse", "lsi", "hse-rtc"
     };
     
++ ++static const char *lcd_parent[1] = { "pllsai-r-div" };
++ ++
++ ++static const char *i2s_parents[2] = { "plli2s-r", NULL };
++ ++
++ ++static const char *sai_parents[4] = { "pllsai-q-div", "plli2s-q-div", NULL,
++ ++   "no-clock" };
++ ++
++ ++static const char *pll48_parents[2] = { "pll-q", "pllsai-p" };
++ ++
++ ++static const char *sdmux_parents[2] = { "pll48", "sys" };
++ ++
++ ++struct stm32_aux_clk {
++ ++   int idx;
++ ++   const char *name;
++ ++   const char * const *parent_names;
++ ++   int num_parents;
++ ++   int offset_mux;
++ ++   u8 shift;
++ ++   u8 mask;
++ ++   int offset_gate;
++ ++   u8 bit_idx;
++ ++   unsigned long flags;
++ ++};
++ ++
     struct stm32f4_clk_data {
        const struct stm32f4_gate_data *gates_data;
        const u64 *gates_map;
        int gates_num;
++ ++   const struct stm32f4_pll_data *pll_data;
++ ++   const struct stm32_aux_clk *aux_clk;
++ ++   int aux_clk_num;
++ ++};
++ ++
++ ++static const struct stm32_aux_clk stm32f429_aux_clk[] = {
++ ++   {
++ ++           CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
++ ++           NO_MUX, 0, 0,
++ ++           STM32F4_RCC_APB2ENR, 26,
++ ++           CLK_SET_RATE_PARENT
++ ++   },
++ ++   {
++ ++           CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
++ ++           STM32F4_RCC_CFGR, 23, 1,
++ ++           NO_GATE, 0,
++ ++           CLK_SET_RATE_PARENT
++ ++   },
++ ++   {
++ ++           CLK_SAI1, "sai1-a", sai_parents, ARRAY_SIZE(sai_parents),
++ ++           STM32F4_RCC_DCKCFGR, 20, 3,
++ ++           STM32F4_RCC_APB2ENR, 22,
++ ++           CLK_SET_RATE_PARENT
++ ++   },
++ ++   {
++ ++           CLK_SAI2, "sai1-b", sai_parents, ARRAY_SIZE(sai_parents),
++ ++           STM32F4_RCC_DCKCFGR, 22, 3,
++ ++           STM32F4_RCC_APB2ENR, 22,
++ ++           CLK_SET_RATE_PARENT
++ ++   },
++ ++};
++ ++
++ ++static const struct stm32_aux_clk stm32f469_aux_clk[] = {
++ ++   {
++ ++           CLK_LCD, "lcd-tft", lcd_parent, ARRAY_SIZE(lcd_parent),
++ ++           NO_MUX, 0, 0,
++ ++           STM32F4_RCC_APB2ENR, 26,
++ ++           CLK_SET_RATE_PARENT
++ ++   },
++ ++   {
++ ++           CLK_I2S, "i2s", i2s_parents, ARRAY_SIZE(i2s_parents),
++ ++           STM32F4_RCC_CFGR, 23, 1,
++ ++           NO_GATE, 0,
++ ++           CLK_SET_RATE_PARENT
++ ++   },
++ ++   {
++ ++           CLK_SAI1, "sai1-a", sai_parents, ARRAY_SIZE(sai_parents),
++ ++           STM32F4_RCC_DCKCFGR, 20, 3,
++ ++           STM32F4_RCC_APB2ENR, 22,
++ ++           CLK_SET_RATE_PARENT
++ ++   },
++ ++   {
++ ++           CLK_SAI2, "sai1-b", sai_parents, ARRAY_SIZE(sai_parents),
++ ++           STM32F4_RCC_DCKCFGR, 22, 3,
++ ++           STM32F4_RCC_APB2ENR, 22,
++ ++           CLK_SET_RATE_PARENT
++ ++   },
++ ++   {
++ ++           NO_IDX, "pll48", pll48_parents, ARRAY_SIZE(pll48_parents),
++ ++           STM32F4_RCC_DCKCFGR, 27, 1,
++ ++           NO_GATE, 0,
++ ++           0
++ ++   },
++ ++   {
++ ++           NO_IDX, "sdmux", sdmux_parents, ARRAY_SIZE(sdmux_parents),
++ ++           STM32F4_RCC_DCKCFGR, 28, 1,
++ ++           NO_GATE, 0,
++ ++           0
++ ++   },
     };
     
     static const struct stm32f4_clk_data stm32f429_clk_data = {
        .gates_data     = stm32f429_gates,
        .gates_map      = stm32f42xx_gate_map,
        .gates_num      = ARRAY_SIZE(stm32f429_gates),
++ ++   .pll_data       = stm32f429_pll,
++ ++   .aux_clk        = stm32f429_aux_clk,
++ ++   .aux_clk_num    = ARRAY_SIZE(stm32f429_aux_clk),
     };
     
     static const struct stm32f4_clk_data stm32f469_clk_data = {
        .gates_data     = stm32f469_gates,
        .gates_map      = stm32f46xx_gate_map,
        .gates_num      = ARRAY_SIZE(stm32f469_gates),
++ ++   .pll_data       = stm32f469_pll,
++ ++   .aux_clk        = stm32f469_aux_clk,
++ ++   .aux_clk_num    = ARRAY_SIZE(stm32f469_aux_clk),
     };
     
     static const struct of_device_id stm32f4_of_match[] = {
        {}
     };
     
++ ++static struct clk_hw *stm32_register_aux_clk(const char *name,
++ ++           const char * const *parent_names, int num_parents,
++ ++           int offset_mux, u8 shift, u8 mask,
++ ++           int offset_gate, u8 bit_idx,
++ ++           unsigned long flags, spinlock_t *lock)
++ ++{
++ ++   struct clk_hw *hw;
++ ++   struct clk_gate *gate;
++ ++   struct clk_mux *mux = NULL;
++ ++   struct clk_hw *mux_hw = NULL, *gate_hw = NULL;
++ ++   const struct clk_ops *mux_ops = NULL, *gate_ops = NULL;
++ ++
++ ++   if (offset_gate != NO_GATE) {
++ ++           gate = kzalloc(sizeof(*gate), GFP_KERNEL);
++ ++           if (!gate) {
++ ++                   hw = ERR_PTR(-EINVAL);
++ ++                   goto fail;
++ ++           }
++ ++
++ ++           gate->reg = base + offset_gate;
++ ++           gate->bit_idx = bit_idx;
++ ++           gate->flags = 0;
++ ++           gate->lock = lock;
++ ++           gate_hw = &gate->hw;
++ ++           gate_ops = &clk_gate_ops;
++ ++   }
++ ++
++ ++   if (offset_mux != NO_MUX) {
++ ++           mux = kzalloc(sizeof(*mux), GFP_KERNEL);
++ ++           if (!mux) {
++ ++                   kfree(gate);
++ ++                   hw = ERR_PTR(-EINVAL);
++ ++                   goto fail;
++ ++           }
++ ++
++ ++           mux->reg = base + offset_mux;
++ ++           mux->shift = shift;
++ ++           mux->mask = mask;
++ ++           mux->flags = 0;
++ ++           mux_hw = &mux->hw;
++ ++           mux_ops = &clk_mux_ops;
++ ++   }
++ ++
++ ++   if (mux_hw == NULL && gate_hw == NULL)
++ ++           return ERR_PTR(-EINVAL);
++ ++
++ ++   hw = clk_hw_register_composite(NULL, name, parent_names, num_parents,
++ ++                   mux_hw, mux_ops,
++ ++                   NULL, NULL,
++ ++                   gate_hw, gate_ops,
++ ++                   flags);
++ ++
++ ++   if (IS_ERR(hw)) {
++ ++           kfree(gate);
++ ++           kfree(mux);
++ ++   }
++ ++fail:
++ ++   return hw;
++ ++}
++ ++
     static void __init stm32f4_rcc_init(struct device_node *np)
     {
-- --   const char *hse_clk;
++ ++   const char *hse_clk, *i2s_in_clk;
        int n;
        const struct of_device_id *match;
        const struct stm32f4_clk_data *data;
++ ++   unsigned long pllcfgr;
++ ++   const char *pllsrc;
++ ++   unsigned long pllm;
     
        base = of_iomap(np, 0);
        if (!base) {
     
        hse_clk = of_clk_get_parent_name(np, 0);
     
++ ++   i2s_in_clk = of_clk_get_parent_name(np, 1);
++ ++
++ ++   i2s_parents[1] = i2s_in_clk;
++ ++   sai_parents[2] = i2s_in_clk;
++ ++
        clk_register_fixed_rate_with_accuracy(NULL, "hsi", NULL, 0,
                        16000000, 160000);
-- --   stm32f4_rcc_register_pll(hse_clk, "hsi");
++ ++   pllcfgr = readl(base + STM32F4_RCC_PLLCFGR);
++ ++   pllsrc = pllcfgr & BIT(22) ? hse_clk : "hsi";
++ ++   pllm = pllcfgr & 0x3f;
++ ++
++ ++   clk_hw_register_fixed_factor(NULL, "vco_in", pllsrc,
++ ++                                          0, 1, pllm);
++ ++
++ ++   stm32f4_rcc_register_pll("vco_in", &data->pll_data[0],
++ ++                   &stm32f4_clk_lock);
++ ++
++ ++   clks[PLL_VCO_I2S] = stm32f4_rcc_register_pll("vco_in",
++ ++                   &data->pll_data[1], &stm32f4_clk_lock);
++ ++
++ ++   clks[PLL_VCO_SAI] = stm32f4_rcc_register_pll("vco_in",
++ ++                   &data->pll_data[2], &stm32f4_clk_lock);
++ ++
++ ++   for (n = 0; n < MAX_POST_DIV; n++) {
++ ++           const struct stm32f4_pll_post_div_data *post_div;
++ ++           struct clk_hw *hw;
++ ++
++ ++           post_div = &post_div_data[n];
++ ++
++ ++           hw = clk_register_pll_div(post_div->name,
++ ++                           post_div->parent,
++ ++                           post_div->flag,
++ ++                           base + post_div->offset,
++ ++                           post_div->shift,
++ ++                           post_div->width,
++ ++                           post_div->flag_div,
++ ++                           post_div->div_table,
++ ++                           clks[post_div->pll_num],
++ ++                           &stm32f4_clk_lock);
++ ++
++ ++           if (post_div->idx != NO_IDX)
++ ++                   clks[post_div->idx] = hw;
++ ++   }
     
        sys_parents[1] = hse_clk;
        clk_register_mux_table(
                goto fail;
        }
     
++ ++   for (n = 0; n < data->aux_clk_num; n++) {
++ ++           const struct stm32_aux_clk *aux_clk;
++ ++           struct clk_hw *hw;
++ ++
++ ++           aux_clk = &data->aux_clk[n];
++ ++
++ ++           hw = stm32_register_aux_clk(aux_clk->name,
++ ++                           aux_clk->parent_names, aux_clk->num_parents,
++ ++                           aux_clk->offset_mux, aux_clk->shift,
++ ++                           aux_clk->mask, aux_clk->offset_gate,
++ ++                           aux_clk->bit_idx, aux_clk->flags,
++ ++                           &stm32f4_clk_lock);
++ ++
++ ++           if (IS_ERR(hw)) {
++ ++                   pr_warn("Unable to register %s clk\n", aux_clk->name);
++ ++                   continue;
++ ++           }
++ ++
++ ++           if (aux_clk->idx != NO_IDX)
++ ++                   clks[aux_clk->idx] = hw;
++ ++   }
++ ++
        of_clk_add_hw_provider(np, stm32f4_rcc_lookup_clk, NULL);
        return;
     fail:
        kfree(clks);
        iounmap(base);
     }
---- CLK_OF_DECLARE(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
---- CLK_OF_DECLARE(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
++++ CLK_OF_DECLARE_DRIVER(stm32f42xx_rcc, "st,stm32f42xx-rcc", stm32f4_rcc_init);
++++ CLK_OF_DECLARE_DRIVER(stm32f46xx_rcc, "st,stm32f469-rcc", stm32f4_rcc_init);
This page took 0.098768 seconds and 4 git commands to generate.