root/drivers/clk/clk-xgene.c

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

DEFINITIONS

This source file includes following definitions.
  1. xgene_clk_read
  2. xgene_clk_write
  3. xgene_clk_pll_is_enabled
  4. xgene_clk_pll_recalc_rate
  5. xgene_register_clk_pll
  6. xgene_pllclk_version
  7. xgene_pllclk_init
  8. xgene_socpllclk_init
  9. xgene_pcppllclk_init
  10. xgene_clk_pmd_recalc_rate
  11. xgene_clk_pmd_round_rate
  12. xgene_clk_pmd_set_rate
  13. xgene_register_clk_pmd
  14. xgene_pmdclk_init
  15. xgene_clk_enable
  16. xgene_clk_disable
  17. xgene_clk_is_enabled
  18. xgene_clk_recalc_rate
  19. xgene_clk_set_rate
  20. xgene_clk_round_rate
  21. xgene_register_clk
  22. xgene_devclk_init

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3  * clk-xgene.c - AppliedMicro X-Gene Clock Interface
   4  *
   5  * Copyright (c) 2013, Applied Micro Circuits Corporation
   6  * Author: Loc Ho <lho@apm.com>
   7  */
   8 #include <linux/module.h>
   9 #include <linux/spinlock.h>
  10 #include <linux/io.h>
  11 #include <linux/of.h>
  12 #include <linux/clkdev.h>
  13 #include <linux/clk-provider.h>
  14 #include <linux/of_address.h>
  15 
  16 /* Register SCU_PCPPLL bit fields */
  17 #define N_DIV_RD(src)                   ((src) & 0x000001ff)
  18 #define SC_N_DIV_RD(src)                ((src) & 0x0000007f)
  19 #define SC_OUTDIV2(src)                 (((src) & 0x00000100) >> 8)
  20 
  21 /* Register SCU_SOCPLL bit fields */
  22 #define CLKR_RD(src)                    (((src) & 0x07000000)>>24)
  23 #define CLKOD_RD(src)                   (((src) & 0x00300000)>>20)
  24 #define REGSPEC_RESET_F1_MASK           0x00010000
  25 #define CLKF_RD(src)                    (((src) & 0x000001ff))
  26 
  27 #define XGENE_CLK_DRIVER_VER            "0.1"
  28 
  29 static DEFINE_SPINLOCK(clk_lock);
  30 
  31 static inline u32 xgene_clk_read(void __iomem *csr)
  32 {
  33         return readl_relaxed(csr);
  34 }
  35 
  36 static inline void xgene_clk_write(u32 data, void __iomem *csr)
  37 {
  38         writel_relaxed(data, csr);
  39 }
  40 
  41 /* PLL Clock */
  42 enum xgene_pll_type {
  43         PLL_TYPE_PCP = 0,
  44         PLL_TYPE_SOC = 1,
  45 };
  46 
  47 struct xgene_clk_pll {
  48         struct clk_hw   hw;
  49         void __iomem    *reg;
  50         spinlock_t      *lock;
  51         u32             pll_offset;
  52         enum xgene_pll_type     type;
  53         int             version;
  54 };
  55 
  56 #define to_xgene_clk_pll(_hw) container_of(_hw, struct xgene_clk_pll, hw)
  57 
  58 static int xgene_clk_pll_is_enabled(struct clk_hw *hw)
  59 {
  60         struct xgene_clk_pll *pllclk = to_xgene_clk_pll(hw);
  61         u32 data;
  62 
  63         data = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
  64         pr_debug("%s pll %s\n", clk_hw_get_name(hw),
  65                 data & REGSPEC_RESET_F1_MASK ? "disabled" : "enabled");
  66 
  67         return data & REGSPEC_RESET_F1_MASK ? 0 : 1;
  68 }
  69 
  70 static unsigned long xgene_clk_pll_recalc_rate(struct clk_hw *hw,
  71                                 unsigned long parent_rate)
  72 {
  73         struct xgene_clk_pll *pllclk = to_xgene_clk_pll(hw);
  74         unsigned long fref;
  75         unsigned long fvco;
  76         u32 pll;
  77         u32 nref;
  78         u32 nout;
  79         u32 nfb;
  80 
  81         pll = xgene_clk_read(pllclk->reg + pllclk->pll_offset);
  82 
  83         if (pllclk->version <= 1) {
  84                 if (pllclk->type == PLL_TYPE_PCP) {
  85                         /*
  86                         * PLL VCO = Reference clock * NF
  87                         * PCP PLL = PLL_VCO / 2
  88                         */
  89                         nout = 2;
  90                         fvco = parent_rate * (N_DIV_RD(pll) + 4);
  91                 } else {
  92                         /*
  93                         * Fref = Reference Clock / NREF;
  94                         * Fvco = Fref * NFB;
  95                         * Fout = Fvco / NOUT;
  96                         */
  97                         nref = CLKR_RD(pll) + 1;
  98                         nout = CLKOD_RD(pll) + 1;
  99                         nfb = CLKF_RD(pll);
 100                         fref = parent_rate / nref;
 101                         fvco = fref * nfb;
 102                 }
 103         } else {
 104                 /*
 105                  * fvco = Reference clock * FBDIVC
 106                  * PLL freq = fvco / NOUT
 107                  */
 108                 nout = SC_OUTDIV2(pll) ? 2 : 3;
 109                 fvco = parent_rate * SC_N_DIV_RD(pll);
 110         }
 111         pr_debug("%s pll recalc rate %ld parent %ld version %d\n",
 112                  clk_hw_get_name(hw), fvco / nout, parent_rate,
 113                  pllclk->version);
 114 
 115         return fvco / nout;
 116 }
 117 
 118 static const struct clk_ops xgene_clk_pll_ops = {
 119         .is_enabled = xgene_clk_pll_is_enabled,
 120         .recalc_rate = xgene_clk_pll_recalc_rate,
 121 };
 122 
 123 static struct clk *xgene_register_clk_pll(struct device *dev,
 124         const char *name, const char *parent_name,
 125         unsigned long flags, void __iomem *reg, u32 pll_offset,
 126         u32 type, spinlock_t *lock, int version)
 127 {
 128         struct xgene_clk_pll *apmclk;
 129         struct clk *clk;
 130         struct clk_init_data init;
 131 
 132         /* allocate the APM clock structure */
 133         apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL);
 134         if (!apmclk)
 135                 return ERR_PTR(-ENOMEM);
 136 
 137         init.name = name;
 138         init.ops = &xgene_clk_pll_ops;
 139         init.flags = flags;
 140         init.parent_names = parent_name ? &parent_name : NULL;
 141         init.num_parents = parent_name ? 1 : 0;
 142 
 143         apmclk->version = version;
 144         apmclk->reg = reg;
 145         apmclk->lock = lock;
 146         apmclk->pll_offset = pll_offset;
 147         apmclk->type = type;
 148         apmclk->hw.init = &init;
 149 
 150         /* Register the clock */
 151         clk = clk_register(dev, &apmclk->hw);
 152         if (IS_ERR(clk)) {
 153                 pr_err("%s: could not register clk %s\n", __func__, name);
 154                 kfree(apmclk);
 155                 return NULL;
 156         }
 157         return clk;
 158 }
 159 
 160 static int xgene_pllclk_version(struct device_node *np)
 161 {
 162         if (of_device_is_compatible(np, "apm,xgene-socpll-clock"))
 163                 return 1;
 164         if (of_device_is_compatible(np, "apm,xgene-pcppll-clock"))
 165                 return 1;
 166         return 2;
 167 }
 168 
 169 static void xgene_pllclk_init(struct device_node *np, enum xgene_pll_type pll_type)
 170 {
 171         const char *clk_name = np->full_name;
 172         struct clk *clk;
 173         void __iomem *reg;
 174         int version = xgene_pllclk_version(np);
 175 
 176         reg = of_iomap(np, 0);
 177         if (!reg) {
 178                 pr_err("Unable to map CSR register for %pOF\n", np);
 179                 return;
 180         }
 181         of_property_read_string(np, "clock-output-names", &clk_name);
 182         clk = xgene_register_clk_pll(NULL,
 183                         clk_name, of_clk_get_parent_name(np, 0),
 184                         0, reg, 0, pll_type, &clk_lock,
 185                         version);
 186         if (!IS_ERR(clk)) {
 187                 of_clk_add_provider(np, of_clk_src_simple_get, clk);
 188                 clk_register_clkdev(clk, clk_name, NULL);
 189                 pr_debug("Add %s clock PLL\n", clk_name);
 190         }
 191 }
 192 
 193 static void xgene_socpllclk_init(struct device_node *np)
 194 {
 195         xgene_pllclk_init(np, PLL_TYPE_SOC);
 196 }
 197 
 198 static void xgene_pcppllclk_init(struct device_node *np)
 199 {
 200         xgene_pllclk_init(np, PLL_TYPE_PCP);
 201 }
 202 
 203 /**
 204  * struct xgene_clk_pmd - PMD clock
 205  *
 206  * @hw:         handle between common and hardware-specific interfaces
 207  * @reg:        register containing the fractional scale multiplier (scaler)
 208  * @shift:      shift to the unit bit field
 209  * @denom:      1/denominator unit
 210  * @lock:       register lock
 211  * Flags:
 212  * XGENE_CLK_PMD_SCALE_INVERTED - By default the scaler is the value read
 213  *      from the register plus one. For example,
 214  *              0 for (0 + 1) / denom,
 215  *              1 for (1 + 1) / denom and etc.
 216  *      If this flag is set, it is
 217  *              0 for (denom - 0) / denom,
 218  *              1 for (denom - 1) / denom and etc.
 219  *
 220  */
 221 struct xgene_clk_pmd {
 222         struct clk_hw   hw;
 223         void __iomem    *reg;
 224         u8              shift;
 225         u32             mask;
 226         u64             denom;
 227         u32             flags;
 228         spinlock_t      *lock;
 229 };
 230 
 231 #define to_xgene_clk_pmd(_hw) container_of(_hw, struct xgene_clk_pmd, hw)
 232 
 233 #define XGENE_CLK_PMD_SCALE_INVERTED    BIT(0)
 234 #define XGENE_CLK_PMD_SHIFT             8
 235 #define XGENE_CLK_PMD_WIDTH             3
 236 
 237 static unsigned long xgene_clk_pmd_recalc_rate(struct clk_hw *hw,
 238                                                unsigned long parent_rate)
 239 {
 240         struct xgene_clk_pmd *fd = to_xgene_clk_pmd(hw);
 241         unsigned long flags = 0;
 242         u64 ret, scale;
 243         u32 val;
 244 
 245         if (fd->lock)
 246                 spin_lock_irqsave(fd->lock, flags);
 247         else
 248                 __acquire(fd->lock);
 249 
 250         val = readl(fd->reg);
 251 
 252         if (fd->lock)
 253                 spin_unlock_irqrestore(fd->lock, flags);
 254         else
 255                 __release(fd->lock);
 256 
 257         ret = (u64)parent_rate;
 258 
 259         scale = (val & fd->mask) >> fd->shift;
 260         if (fd->flags & XGENE_CLK_PMD_SCALE_INVERTED)
 261                 scale = fd->denom - scale;
 262         else
 263                 scale++;
 264 
 265         /* freq = parent_rate * scaler / denom */
 266         do_div(ret, fd->denom);
 267         ret *= scale;
 268         if (ret == 0)
 269                 ret = (u64)parent_rate;
 270 
 271         return ret;
 272 }
 273 
 274 static long xgene_clk_pmd_round_rate(struct clk_hw *hw, unsigned long rate,
 275                                      unsigned long *parent_rate)
 276 {
 277         struct xgene_clk_pmd *fd = to_xgene_clk_pmd(hw);
 278         u64 ret, scale;
 279 
 280         if (!rate || rate >= *parent_rate)
 281                 return *parent_rate;
 282 
 283         /* freq = parent_rate * scaler / denom */
 284         ret = rate * fd->denom;
 285         scale = DIV_ROUND_UP_ULL(ret, *parent_rate);
 286 
 287         ret = (u64)*parent_rate * scale;
 288         do_div(ret, fd->denom);
 289 
 290         return ret;
 291 }
 292 
 293 static int xgene_clk_pmd_set_rate(struct clk_hw *hw, unsigned long rate,
 294                                   unsigned long parent_rate)
 295 {
 296         struct xgene_clk_pmd *fd = to_xgene_clk_pmd(hw);
 297         unsigned long flags = 0;
 298         u64 scale, ret;
 299         u32 val;
 300 
 301         /*
 302          * Compute the scaler:
 303          *
 304          * freq = parent_rate * scaler / denom, or
 305          * scaler = freq * denom / parent_rate
 306          */
 307         ret = rate * fd->denom;
 308         scale = DIV_ROUND_UP_ULL(ret, (u64)parent_rate);
 309 
 310         /* Check if inverted */
 311         if (fd->flags & XGENE_CLK_PMD_SCALE_INVERTED)
 312                 scale = fd->denom - scale;
 313         else
 314                 scale--;
 315 
 316         if (fd->lock)
 317                 spin_lock_irqsave(fd->lock, flags);
 318         else
 319                 __acquire(fd->lock);
 320 
 321         val = readl(fd->reg);
 322         val &= ~fd->mask;
 323         val |= (scale << fd->shift);
 324         writel(val, fd->reg);
 325 
 326         if (fd->lock)
 327                 spin_unlock_irqrestore(fd->lock, flags);
 328         else
 329                 __release(fd->lock);
 330 
 331         return 0;
 332 }
 333 
 334 static const struct clk_ops xgene_clk_pmd_ops = {
 335         .recalc_rate = xgene_clk_pmd_recalc_rate,
 336         .round_rate = xgene_clk_pmd_round_rate,
 337         .set_rate = xgene_clk_pmd_set_rate,
 338 };
 339 
 340 static struct clk *
 341 xgene_register_clk_pmd(struct device *dev,
 342                        const char *name, const char *parent_name,
 343                        unsigned long flags, void __iomem *reg, u8 shift,
 344                        u8 width, u64 denom, u32 clk_flags, spinlock_t *lock)
 345 {
 346         struct xgene_clk_pmd *fd;
 347         struct clk_init_data init;
 348         struct clk *clk;
 349 
 350         fd = kzalloc(sizeof(*fd), GFP_KERNEL);
 351         if (!fd)
 352                 return ERR_PTR(-ENOMEM);
 353 
 354         init.name = name;
 355         init.ops = &xgene_clk_pmd_ops;
 356         init.flags = flags;
 357         init.parent_names = parent_name ? &parent_name : NULL;
 358         init.num_parents = parent_name ? 1 : 0;
 359 
 360         fd->reg = reg;
 361         fd->shift = shift;
 362         fd->mask = (BIT(width) - 1) << shift;
 363         fd->denom = denom;
 364         fd->flags = clk_flags;
 365         fd->lock = lock;
 366         fd->hw.init = &init;
 367 
 368         clk = clk_register(dev, &fd->hw);
 369         if (IS_ERR(clk)) {
 370                 pr_err("%s: could not register clk %s\n", __func__, name);
 371                 kfree(fd);
 372                 return NULL;
 373         }
 374 
 375         return clk;
 376 }
 377 
 378 static void xgene_pmdclk_init(struct device_node *np)
 379 {
 380         const char *clk_name = np->full_name;
 381         void __iomem *csr_reg;
 382         struct resource res;
 383         struct clk *clk;
 384         u64 denom;
 385         u32 flags = 0;
 386         int rc;
 387 
 388         /* Check if the entry is disabled */
 389         if (!of_device_is_available(np))
 390                 return;
 391 
 392         /* Parse the DTS register for resource */
 393         rc = of_address_to_resource(np, 0, &res);
 394         if (rc != 0) {
 395                 pr_err("no DTS register for %pOF\n", np);
 396                 return;
 397         }
 398         csr_reg = of_iomap(np, 0);
 399         if (!csr_reg) {
 400                 pr_err("Unable to map resource for %pOF\n", np);
 401                 return;
 402         }
 403         of_property_read_string(np, "clock-output-names", &clk_name);
 404 
 405         denom = BIT(XGENE_CLK_PMD_WIDTH);
 406         flags |= XGENE_CLK_PMD_SCALE_INVERTED;
 407 
 408         clk = xgene_register_clk_pmd(NULL, clk_name,
 409                                      of_clk_get_parent_name(np, 0), 0,
 410                                      csr_reg, XGENE_CLK_PMD_SHIFT,
 411                                      XGENE_CLK_PMD_WIDTH, denom,
 412                                      flags, &clk_lock);
 413         if (!IS_ERR(clk)) {
 414                 of_clk_add_provider(np, of_clk_src_simple_get, clk);
 415                 clk_register_clkdev(clk, clk_name, NULL);
 416                 pr_debug("Add %s clock\n", clk_name);
 417         } else {
 418                 if (csr_reg)
 419                         iounmap(csr_reg);
 420         }
 421 }
 422 
 423 /* IP Clock */
 424 struct xgene_dev_parameters {
 425         void __iomem *csr_reg;          /* CSR for IP clock */
 426         u32 reg_clk_offset;             /* Offset to clock enable CSR */
 427         u32 reg_clk_mask;               /* Mask bit for clock enable */
 428         u32 reg_csr_offset;             /* Offset to CSR reset */
 429         u32 reg_csr_mask;               /* Mask bit for disable CSR reset */
 430         void __iomem *divider_reg;      /* CSR for divider */
 431         u32 reg_divider_offset;         /* Offset to divider register */
 432         u32 reg_divider_shift;          /* Bit shift to divider field */
 433         u32 reg_divider_width;          /* Width of the bit to divider field */
 434 };
 435 
 436 struct xgene_clk {
 437         struct clk_hw   hw;
 438         spinlock_t      *lock;
 439         struct xgene_dev_parameters     param;
 440 };
 441 
 442 #define to_xgene_clk(_hw) container_of(_hw, struct xgene_clk, hw)
 443 
 444 static int xgene_clk_enable(struct clk_hw *hw)
 445 {
 446         struct xgene_clk *pclk = to_xgene_clk(hw);
 447         unsigned long flags = 0;
 448         u32 data;
 449 
 450         if (pclk->lock)
 451                 spin_lock_irqsave(pclk->lock, flags);
 452 
 453         if (pclk->param.csr_reg) {
 454                 pr_debug("%s clock enabled\n", clk_hw_get_name(hw));
 455                 /* First enable the clock */
 456                 data = xgene_clk_read(pclk->param.csr_reg +
 457                                         pclk->param.reg_clk_offset);
 458                 data |= pclk->param.reg_clk_mask;
 459                 xgene_clk_write(data, pclk->param.csr_reg +
 460                                         pclk->param.reg_clk_offset);
 461                 pr_debug("%s clk offset 0x%08X mask 0x%08X value 0x%08X\n",
 462                         clk_hw_get_name(hw),
 463                         pclk->param.reg_clk_offset, pclk->param.reg_clk_mask,
 464                         data);
 465 
 466                 /* Second enable the CSR */
 467                 data = xgene_clk_read(pclk->param.csr_reg +
 468                                         pclk->param.reg_csr_offset);
 469                 data &= ~pclk->param.reg_csr_mask;
 470                 xgene_clk_write(data, pclk->param.csr_reg +
 471                                         pclk->param.reg_csr_offset);
 472                 pr_debug("%s csr offset 0x%08X mask 0x%08X value 0x%08X\n",
 473                         clk_hw_get_name(hw),
 474                         pclk->param.reg_csr_offset, pclk->param.reg_csr_mask,
 475                         data);
 476         }
 477 
 478         if (pclk->lock)
 479                 spin_unlock_irqrestore(pclk->lock, flags);
 480 
 481         return 0;
 482 }
 483 
 484 static void xgene_clk_disable(struct clk_hw *hw)
 485 {
 486         struct xgene_clk *pclk = to_xgene_clk(hw);
 487         unsigned long flags = 0;
 488         u32 data;
 489 
 490         if (pclk->lock)
 491                 spin_lock_irqsave(pclk->lock, flags);
 492 
 493         if (pclk->param.csr_reg) {
 494                 pr_debug("%s clock disabled\n", clk_hw_get_name(hw));
 495                 /* First put the CSR in reset */
 496                 data = xgene_clk_read(pclk->param.csr_reg +
 497                                         pclk->param.reg_csr_offset);
 498                 data |= pclk->param.reg_csr_mask;
 499                 xgene_clk_write(data, pclk->param.csr_reg +
 500                                         pclk->param.reg_csr_offset);
 501 
 502                 /* Second disable the clock */
 503                 data = xgene_clk_read(pclk->param.csr_reg +
 504                                         pclk->param.reg_clk_offset);
 505                 data &= ~pclk->param.reg_clk_mask;
 506                 xgene_clk_write(data, pclk->param.csr_reg +
 507                                         pclk->param.reg_clk_offset);
 508         }
 509 
 510         if (pclk->lock)
 511                 spin_unlock_irqrestore(pclk->lock, flags);
 512 }
 513 
 514 static int xgene_clk_is_enabled(struct clk_hw *hw)
 515 {
 516         struct xgene_clk *pclk = to_xgene_clk(hw);
 517         u32 data = 0;
 518 
 519         if (pclk->param.csr_reg) {
 520                 pr_debug("%s clock checking\n", clk_hw_get_name(hw));
 521                 data = xgene_clk_read(pclk->param.csr_reg +
 522                                         pclk->param.reg_clk_offset);
 523                 pr_debug("%s clock is %s\n", clk_hw_get_name(hw),
 524                         data & pclk->param.reg_clk_mask ? "enabled" :
 525                                                         "disabled");
 526         }
 527 
 528         if (!pclk->param.csr_reg)
 529                 return 1;
 530         return data & pclk->param.reg_clk_mask ? 1 : 0;
 531 }
 532 
 533 static unsigned long xgene_clk_recalc_rate(struct clk_hw *hw,
 534                                 unsigned long parent_rate)
 535 {
 536         struct xgene_clk *pclk = to_xgene_clk(hw);
 537         u32 data;
 538 
 539         if (pclk->param.divider_reg) {
 540                 data = xgene_clk_read(pclk->param.divider_reg +
 541                                         pclk->param.reg_divider_offset);
 542                 data >>= pclk->param.reg_divider_shift;
 543                 data &= (1 << pclk->param.reg_divider_width) - 1;
 544 
 545                 pr_debug("%s clock recalc rate %ld parent %ld\n",
 546                         clk_hw_get_name(hw),
 547                         parent_rate / data, parent_rate);
 548 
 549                 return parent_rate / data;
 550         } else {
 551                 pr_debug("%s clock recalc rate %ld parent %ld\n",
 552                         clk_hw_get_name(hw), parent_rate, parent_rate);
 553                 return parent_rate;
 554         }
 555 }
 556 
 557 static int xgene_clk_set_rate(struct clk_hw *hw, unsigned long rate,
 558                                 unsigned long parent_rate)
 559 {
 560         struct xgene_clk *pclk = to_xgene_clk(hw);
 561         unsigned long flags = 0;
 562         u32 data;
 563         u32 divider;
 564         u32 divider_save;
 565 
 566         if (pclk->lock)
 567                 spin_lock_irqsave(pclk->lock, flags);
 568 
 569         if (pclk->param.divider_reg) {
 570                 /* Let's compute the divider */
 571                 if (rate > parent_rate)
 572                         rate = parent_rate;
 573                 divider_save = divider = parent_rate / rate; /* Rounded down */
 574                 divider &= (1 << pclk->param.reg_divider_width) - 1;
 575                 divider <<= pclk->param.reg_divider_shift;
 576 
 577                 /* Set new divider */
 578                 data = xgene_clk_read(pclk->param.divider_reg +
 579                                 pclk->param.reg_divider_offset);
 580                 data &= ~(((1 << pclk->param.reg_divider_width) - 1)
 581                                 << pclk->param.reg_divider_shift);
 582                 data |= divider;
 583                 xgene_clk_write(data, pclk->param.divider_reg +
 584                                         pclk->param.reg_divider_offset);
 585                 pr_debug("%s clock set rate %ld\n", clk_hw_get_name(hw),
 586                         parent_rate / divider_save);
 587         } else {
 588                 divider_save = 1;
 589         }
 590 
 591         if (pclk->lock)
 592                 spin_unlock_irqrestore(pclk->lock, flags);
 593 
 594         return parent_rate / divider_save;
 595 }
 596 
 597 static long xgene_clk_round_rate(struct clk_hw *hw, unsigned long rate,
 598                                 unsigned long *prate)
 599 {
 600         struct xgene_clk *pclk = to_xgene_clk(hw);
 601         unsigned long parent_rate = *prate;
 602         u32 divider;
 603 
 604         if (pclk->param.divider_reg) {
 605                 /* Let's compute the divider */
 606                 if (rate > parent_rate)
 607                         rate = parent_rate;
 608                 divider = parent_rate / rate;   /* Rounded down */
 609         } else {
 610                 divider = 1;
 611         }
 612 
 613         return parent_rate / divider;
 614 }
 615 
 616 static const struct clk_ops xgene_clk_ops = {
 617         .enable = xgene_clk_enable,
 618         .disable = xgene_clk_disable,
 619         .is_enabled = xgene_clk_is_enabled,
 620         .recalc_rate = xgene_clk_recalc_rate,
 621         .set_rate = xgene_clk_set_rate,
 622         .round_rate = xgene_clk_round_rate,
 623 };
 624 
 625 static struct clk *xgene_register_clk(struct device *dev,
 626                 const char *name, const char *parent_name,
 627                 struct xgene_dev_parameters *parameters, spinlock_t *lock)
 628 {
 629         struct xgene_clk *apmclk;
 630         struct clk *clk;
 631         struct clk_init_data init;
 632         int rc;
 633 
 634         /* allocate the APM clock structure */
 635         apmclk = kzalloc(sizeof(*apmclk), GFP_KERNEL);
 636         if (!apmclk)
 637                 return ERR_PTR(-ENOMEM);
 638 
 639         init.name = name;
 640         init.ops = &xgene_clk_ops;
 641         init.flags = 0;
 642         init.parent_names = parent_name ? &parent_name : NULL;
 643         init.num_parents = parent_name ? 1 : 0;
 644 
 645         apmclk->lock = lock;
 646         apmclk->hw.init = &init;
 647         apmclk->param = *parameters;
 648 
 649         /* Register the clock */
 650         clk = clk_register(dev, &apmclk->hw);
 651         if (IS_ERR(clk)) {
 652                 pr_err("%s: could not register clk %s\n", __func__, name);
 653                 kfree(apmclk);
 654                 return clk;
 655         }
 656 
 657         /* Register the clock for lookup */
 658         rc = clk_register_clkdev(clk, name, NULL);
 659         if (rc != 0) {
 660                 pr_err("%s: could not register lookup clk %s\n",
 661                         __func__, name);
 662         }
 663         return clk;
 664 }
 665 
 666 static void __init xgene_devclk_init(struct device_node *np)
 667 {
 668         const char *clk_name = np->full_name;
 669         struct clk *clk;
 670         struct resource res;
 671         int rc;
 672         struct xgene_dev_parameters parameters;
 673         int i;
 674 
 675         /* Check if the entry is disabled */
 676         if (!of_device_is_available(np))
 677                 return;
 678 
 679         /* Parse the DTS register for resource */
 680         parameters.csr_reg = NULL;
 681         parameters.divider_reg = NULL;
 682         for (i = 0; i < 2; i++) {
 683                 void __iomem *map_res;
 684                 rc = of_address_to_resource(np, i, &res);
 685                 if (rc != 0) {
 686                         if (i == 0) {
 687                                 pr_err("no DTS register for %pOF\n", np);
 688                                 return;
 689                         }
 690                         break;
 691                 }
 692                 map_res = of_iomap(np, i);
 693                 if (!map_res) {
 694                         pr_err("Unable to map resource %d for %pOF\n", i, np);
 695                         goto err;
 696                 }
 697                 if (strcmp(res.name, "div-reg") == 0)
 698                         parameters.divider_reg = map_res;
 699                 else /* if (strcmp(res->name, "csr-reg") == 0) */
 700                         parameters.csr_reg = map_res;
 701         }
 702         if (of_property_read_u32(np, "csr-offset", &parameters.reg_csr_offset))
 703                 parameters.reg_csr_offset = 0;
 704         if (of_property_read_u32(np, "csr-mask", &parameters.reg_csr_mask))
 705                 parameters.reg_csr_mask = 0xF;
 706         if (of_property_read_u32(np, "enable-offset",
 707                                 &parameters.reg_clk_offset))
 708                 parameters.reg_clk_offset = 0x8;
 709         if (of_property_read_u32(np, "enable-mask", &parameters.reg_clk_mask))
 710                 parameters.reg_clk_mask = 0xF;
 711         if (of_property_read_u32(np, "divider-offset",
 712                                 &parameters.reg_divider_offset))
 713                 parameters.reg_divider_offset = 0;
 714         if (of_property_read_u32(np, "divider-width",
 715                                 &parameters.reg_divider_width))
 716                 parameters.reg_divider_width = 0;
 717         if (of_property_read_u32(np, "divider-shift",
 718                                 &parameters.reg_divider_shift))
 719                 parameters.reg_divider_shift = 0;
 720         of_property_read_string(np, "clock-output-names", &clk_name);
 721 
 722         clk = xgene_register_clk(NULL, clk_name,
 723                 of_clk_get_parent_name(np, 0), &parameters, &clk_lock);
 724         if (IS_ERR(clk))
 725                 goto err;
 726         pr_debug("Add %s clock\n", clk_name);
 727         rc = of_clk_add_provider(np, of_clk_src_simple_get, clk);
 728         if (rc != 0)
 729                 pr_err("%s: could register provider clk %pOF\n", __func__, np);
 730 
 731         return;
 732 
 733 err:
 734         if (parameters.csr_reg)
 735                 iounmap(parameters.csr_reg);
 736         if (parameters.divider_reg)
 737                 iounmap(parameters.divider_reg);
 738 }
 739 
 740 CLK_OF_DECLARE(xgene_socpll_clock, "apm,xgene-socpll-clock", xgene_socpllclk_init);
 741 CLK_OF_DECLARE(xgene_pcppll_clock, "apm,xgene-pcppll-clock", xgene_pcppllclk_init);
 742 CLK_OF_DECLARE(xgene_pmd_clock, "apm,xgene-pmd-clock", xgene_pmdclk_init);
 743 CLK_OF_DECLARE(xgene_socpll_v2_clock, "apm,xgene-socpll-v2-clock",
 744                xgene_socpllclk_init);
 745 CLK_OF_DECLARE(xgene_pcppll_v2_clock, "apm,xgene-pcppll-v2-clock",
 746                xgene_pcppllclk_init);
 747 CLK_OF_DECLARE(xgene_dev_clock, "apm,xgene-device-clock", xgene_devclk_init);

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