root/drivers/clk/rockchip/clk-inverter.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rockchip_inv_get_phase
  2. rockchip_inv_set_phase
  3. rockchip_clk_register_inverter

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * Copyright 2015 Heiko Stuebner <heiko@sntech.de>
   4  */
   5 
   6 #include <linux/slab.h>
   7 #include <linux/clk-provider.h>
   8 #include <linux/io.h>
   9 #include <linux/spinlock.h>
  10 #include <linux/kernel.h>
  11 #include "clk.h"
  12 
  13 struct rockchip_inv_clock {
  14         struct clk_hw   hw;
  15         void __iomem    *reg;
  16         int             shift;
  17         int             flags;
  18         spinlock_t      *lock;
  19 };
  20 
  21 #define to_inv_clock(_hw) container_of(_hw, struct rockchip_inv_clock, hw)
  22 
  23 #define INVERTER_MASK 0x1
  24 
  25 static int rockchip_inv_get_phase(struct clk_hw *hw)
  26 {
  27         struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
  28         u32 val;
  29 
  30         val = readl(inv_clock->reg) >> inv_clock->shift;
  31         val &= INVERTER_MASK;
  32         return val ? 180 : 0;
  33 }
  34 
  35 static int rockchip_inv_set_phase(struct clk_hw *hw, int degrees)
  36 {
  37         struct rockchip_inv_clock *inv_clock = to_inv_clock(hw);
  38         u32 val;
  39 
  40         if (degrees % 180 == 0) {
  41                 val = !!degrees;
  42         } else {
  43                 pr_err("%s: unsupported phase %d for %s\n",
  44                        __func__, degrees, clk_hw_get_name(hw));
  45                 return -EINVAL;
  46         }
  47 
  48         if (inv_clock->flags & ROCKCHIP_INVERTER_HIWORD_MASK) {
  49                 writel(HIWORD_UPDATE(val, INVERTER_MASK, inv_clock->shift),
  50                        inv_clock->reg);
  51         } else {
  52                 unsigned long flags;
  53                 u32 reg;
  54 
  55                 spin_lock_irqsave(inv_clock->lock, flags);
  56 
  57                 reg = readl(inv_clock->reg);
  58                 reg &= ~BIT(inv_clock->shift);
  59                 reg |= val;
  60                 writel(reg, inv_clock->reg);
  61 
  62                 spin_unlock_irqrestore(inv_clock->lock, flags);
  63         }
  64 
  65         return 0;
  66 }
  67 
  68 static const struct clk_ops rockchip_inv_clk_ops = {
  69         .get_phase      = rockchip_inv_get_phase,
  70         .set_phase      = rockchip_inv_set_phase,
  71 };
  72 
  73 struct clk *rockchip_clk_register_inverter(const char *name,
  74                                 const char *const *parent_names, u8 num_parents,
  75                                 void __iomem *reg, int shift, int flags,
  76                                 spinlock_t *lock)
  77 {
  78         struct clk_init_data init;
  79         struct rockchip_inv_clock *inv_clock;
  80         struct clk *clk;
  81 
  82         inv_clock = kmalloc(sizeof(*inv_clock), GFP_KERNEL);
  83         if (!inv_clock)
  84                 return ERR_PTR(-ENOMEM);
  85 
  86         init.name = name;
  87         init.num_parents = num_parents;
  88         init.flags = CLK_SET_RATE_PARENT;
  89         init.parent_names = parent_names;
  90         init.ops = &rockchip_inv_clk_ops;
  91 
  92         inv_clock->hw.init = &init;
  93         inv_clock->reg = reg;
  94         inv_clock->shift = shift;
  95         inv_clock->flags = flags;
  96         inv_clock->lock = lock;
  97 
  98         clk = clk_register(NULL, &inv_clock->hw);
  99         if (IS_ERR(clk))
 100                 kfree(inv_clock);
 101 
 102         return clk;
 103 }

/* [<][>][^][v][top][bottom][index][help] */