OSDN Git Service

clk: at91: allow configuring generated PCR layout
authorAlexandre Belloni <alexandre.belloni@bootlin.com>
Tue, 2 Apr 2019 12:50:51 +0000 (14:50 +0200)
committerStephen Boyd <sboyd@kernel.org>
Thu, 25 Apr 2019 19:34:03 +0000 (12:34 -0700)
The PCR register layout for GCLKCSS is changing for the future SoCs, allow
configuring it.

Signed-off-by: Alexandre Belloni <alexandre.belloni@bootlin.com>
Signed-off-by: Stephen Boyd <sboyd@kernel.org>
drivers/clk/at91/clk-generated.c
drivers/clk/at91/dt-compat.c
drivers/clk/at91/pmc.h
drivers/clk/at91/sama5d2.c
include/linux/clk/at91_pmc.h

index 66e7f7b..5f18847 100644 (file)
@@ -11,6 +11,7 @@
  *
  */
 
+#include <linux/bitfield.h>
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/at91_pmc.h>
@@ -31,6 +32,7 @@ struct clk_generated {
        spinlock_t *lock;
        u32 id;
        u32 gckdiv;
+       const struct clk_pcr_layout *layout;
        u8 parent_id;
        bool audio_pll_allowed;
 };
@@ -47,14 +49,14 @@ static int clk_generated_enable(struct clk_hw *hw)
                 __func__, gck->gckdiv, gck->parent_id);
 
        spin_lock_irqsave(gck->lock, flags);
-       regmap_write(gck->regmap, AT91_PMC_PCR,
-                    (gck->id & AT91_PMC_PCR_PID_MASK));
-       regmap_update_bits(gck->regmap, AT91_PMC_PCR,
-                          AT91_PMC_PCR_GCKDIV_MASK | AT91_PMC_PCR_GCKCSS_MASK |
-                          AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
-                          AT91_PMC_PCR_GCKCSS(gck->parent_id) |
-                          AT91_PMC_PCR_CMD |
-                          AT91_PMC_PCR_GCKDIV(gck->gckdiv) |
+       regmap_write(gck->regmap, gck->layout->offset,
+                    (gck->id & gck->layout->pid_mask));
+       regmap_update_bits(gck->regmap, gck->layout->offset,
+                          AT91_PMC_PCR_GCKDIV_MASK | gck->layout->gckcss_mask |
+                          gck->layout->cmd | AT91_PMC_PCR_GCKEN,
+                          field_prep(gck->layout->gckcss_mask, gck->parent_id) |
+                          gck->layout->cmd |
+                          FIELD_PREP(AT91_PMC_PCR_GCKDIV_MASK, gck->gckdiv) |
                           AT91_PMC_PCR_GCKEN);
        spin_unlock_irqrestore(gck->lock, flags);
        return 0;
@@ -66,11 +68,11 @@ static void clk_generated_disable(struct clk_hw *hw)
        unsigned long flags;
 
        spin_lock_irqsave(gck->lock, flags);
-       regmap_write(gck->regmap, AT91_PMC_PCR,
-                    (gck->id & AT91_PMC_PCR_PID_MASK));
-       regmap_update_bits(gck->regmap, AT91_PMC_PCR,
-                          AT91_PMC_PCR_CMD | AT91_PMC_PCR_GCKEN,
-                          AT91_PMC_PCR_CMD);
+       regmap_write(gck->regmap, gck->layout->offset,
+                    (gck->id & gck->layout->pid_mask));
+       regmap_update_bits(gck->regmap, gck->layout->offset,
+                          gck->layout->cmd | AT91_PMC_PCR_GCKEN,
+                          gck->layout->cmd);
        spin_unlock_irqrestore(gck->lock, flags);
 }
 
@@ -81,9 +83,9 @@ static int clk_generated_is_enabled(struct clk_hw *hw)
        unsigned int status;
 
        spin_lock_irqsave(gck->lock, flags);
-       regmap_write(gck->regmap, AT91_PMC_PCR,
-                    (gck->id & AT91_PMC_PCR_PID_MASK));
-       regmap_read(gck->regmap, AT91_PMC_PCR, &status);
+       regmap_write(gck->regmap, gck->layout->offset,
+                    (gck->id & gck->layout->pid_mask));
+       regmap_read(gck->regmap, gck->layout->offset, &status);
        spin_unlock_irqrestore(gck->lock, flags);
 
        return status & AT91_PMC_PCR_GCKEN ? 1 : 0;
@@ -259,19 +261,18 @@ static void clk_generated_startup(struct clk_generated *gck)
        unsigned long flags;
 
        spin_lock_irqsave(gck->lock, flags);
-       regmap_write(gck->regmap, AT91_PMC_PCR,
-                    (gck->id & AT91_PMC_PCR_PID_MASK));
-       regmap_read(gck->regmap, AT91_PMC_PCR, &tmp);
+       regmap_write(gck->regmap, gck->layout->offset,
+                    (gck->id & gck->layout->pid_mask));
+       regmap_read(gck->regmap, gck->layout->offset, &tmp);
        spin_unlock_irqrestore(gck->lock, flags);
 
-       gck->parent_id = (tmp & AT91_PMC_PCR_GCKCSS_MASK)
-                                       >> AT91_PMC_PCR_GCKCSS_OFFSET;
-       gck->gckdiv = (tmp & AT91_PMC_PCR_GCKDIV_MASK)
-                                       >> AT91_PMC_PCR_GCKDIV_OFFSET;
+       gck->parent_id = field_get(gck->layout->gckcss_mask, tmp);
+       gck->gckdiv = FIELD_GET(AT91_PMC_PCR_GCKDIV_MASK, tmp);
 }
 
 struct clk_hw * __init
 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
+                           const struct clk_pcr_layout *layout,
                            const char *name, const char **parent_names,
                            u8 num_parents, u8 id, bool pll_audio,
                            const struct clk_range *range)
@@ -298,6 +299,7 @@ at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
        gck->lock = lock;
        gck->range = *range;
        gck->audio_pll_allowed = pll_audio;
+       gck->layout = layout;
 
        clk_generated_startup(gck);
        hw = &gck->hw;
index aa09072..aa1754e 100644 (file)
@@ -154,7 +154,8 @@ static void __init of_sama5d2_clk_generated_setup(struct device_node *np)
                     id == GCK_ID_CLASSD))
                        pll_audio = true;
 
-               hw = at91_clk_register_generated(regmap, &pmc_pcr_lock, name,
+               hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
+                                                &dt_pcr_layout, name,
                                                 parent_names, num_parents,
                                                 id, pll_audio, &range);
                if (IS_ERR(hw))
index 616c045..4027306 100644 (file)
@@ -116,6 +116,7 @@ at91_clk_register_audio_pll_pmc(struct regmap *regmap, const char *name,
 
 struct clk_hw * __init
 at91_clk_register_generated(struct regmap *regmap, spinlock_t *lock,
+                           const struct clk_pcr_layout *layout,
                            const char *name, const char **parent_names,
                            u8 num_parents, u8 id, bool pll_audio,
                            const struct clk_range *range);
index 9d128bd..0961568 100644 (file)
@@ -305,6 +305,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
        parent_names[5] = "audiopll_pmcck";
        for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
                hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
+                                                &sama5d2_pcr_layout,
                                                 sama5d2_gck[i].n,
                                                 parent_names, 6,
                                                 sama5d2_gck[i].id,
index b97b8dc..31f00eb 100644 (file)
 
 #define AT91_PMC_PCR           0x10c                   /* Peripheral Control Register [some SAM9 and SAMA5] */
 #define                AT91_PMC_PCR_PID_MASK           0x3f
-#define                AT91_PMC_PCR_GCKCSS_OFFSET      8
-#define                AT91_PMC_PCR_GCKCSS_MASK        (0x7  << AT91_PMC_PCR_GCKCSS_OFFSET)
-#define                AT91_PMC_PCR_GCKCSS(n)          ((n)  << AT91_PMC_PCR_GCKCSS_OFFSET)    /* GCK Clock Source Selection */
 #define                AT91_PMC_PCR_CMD                (0x1  <<  12)                           /* Command (read=0, write=1) */
-#define                AT91_PMC_PCR_GCKDIV_OFFSET      20
-#define                AT91_PMC_PCR_GCKDIV_MASK        (0xff  << AT91_PMC_PCR_GCKDIV_OFFSET)
-#define                AT91_PMC_PCR_GCKDIV(n)          ((n)  << AT91_PMC_PCR_GCKDIV_OFFSET)    /* Generated Clock Divisor Value */
+#define                AT91_PMC_PCR_GCKDIV_MASK        GENMASK(27, 20)
 #define                AT91_PMC_PCR_EN                 (0x1  <<  28)                           /* Enable */
 #define                AT91_PMC_PCR_GCKEN              (0x1  <<  29)                           /* GCK Enable */