Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/clk/bcm/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 60 kB image not shown  

Quelle  clk-bcm2835.c   Sprache: C

 
// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2010,2015 Broadcom
 * Copyright (C) 2012 Stephen Warren
 */


/**
 * DOC: BCM2835 CPRMAN (clock manager for the "audio" domain)
 *
 * The clock tree on the 2835 has several levels.  There's a root
 * oscillator running at 19.2Mhz.  After the oscillator there are 5
 * PLLs, roughly divided as "camera", "ARM", "core", "DSI displays",
 * and "HDMI displays".  Those 5 PLLs each can divide their output to
 * produce up to 4 channels.  Finally, there is the level of clocks to
 * be consumed by other hardware components (like "H264" or "HDMI
 * state machine"), which divide off of some subset of the PLL
 * channels.
 *
 * All of the clocks in the tree are exposed in the DT, because the DT
 * may want to make assignments of the final layer of clocks to the
 * PLL channels, and some components of the hardware will actually
 * skip layers of the tree (for example, the pixel clock comes
 * directly from the PLLH PIX channel without using a CM_*CTL clock
 * generator).
 */


#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/clk.h>
#include <linux/debugfs.h>
#include <linux/delay.h>
#include <linux/io.h>
#include <linux/math.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <dt-bindings/clock/bcm2835.h>

#define CM_PASSWORD  0x5a000000

#define CM_GNRICCTL  0x000
#define CM_GNRICDIV  0x004
define CM_DIV_FRAC_BITS 12
define CM_DIV_FRAC_MASK GENMASK(CM_DIV_FRAC_BITS - 1, 0)

#define CM_VPUCTL  0x008
#define CM_VPUDIV  0x00c
#define CM_SYSCTL  0x010
#define CM_SYSDIV  0x014
#define CM_PERIACTL  0x018
#define CM_PERIADIV  0x01c
#define CM_PERIICTL  0x020
#define CM_PERIIDIV  0x024
#define CM_H264CTL  0x028
#define CM_H264DIV  0x02c
#define CM_ISPCTL  0x030
#define CM_ISPDIV  0x034
#define CM_V3DCTL  0x038
#define CM_V3DDIV  0x03c
#define CM_CAM0CTL  0x040
#define CM_CAM0DIV  0x044
#define CM_CAM1CTL  0x048
#define CM_CAM1DIV  0x04c
#define CM_CCP2CTL  0x050
#define CM_CCP2DIV  0x054
#define CM_DSI0ECTL  0x058
#define CM_DSI0EDIV  0x05c
#define CM_DSI0PCTL  0x060
#define CM_DSI0PDIV  0x064
#define CM_DPICTL  0x068
#define CM_DPIDIV  0x06c
#define CM_GP0CTL  0x070
#define CM_GP0DIV  0x074
#define CM_GP1CTL  0x078
#define CM_GP1DIV  0x07c
#define CM_GP2CTL  0x080
#define CM_GP2DIV  0x084
#define CM_HSMCTL  0x088
#define CM_HSMDIV  0x08c
#define CM_OTPCTL  0x090
#define CM_OTPDIV  0x094
#define CM_PCMCTL  0x098
#define CM_PCMDIV  0x09c
#define CM_PWMCTL  0x0a0
#define CM_PWMDIV  0x0a4
#define CM_SLIMCTL  0x0a8
#define CM_SLIMDIV  0x0ac
#define CM_SMICTL  0x0b0
#define CM_SMIDIV  0x0b4
/* no definition for 0x0b8  and 0x0bc */
#define CM_TCNTCTL  0x0c0
define CM_TCNT_SRC1_SHIFT  12
#define CM_TCNTCNT  0x0c4
#define CM_TECCTL  0x0c8
#define CM_TECDIV  0x0cc
#define CM_TD0CTL  0x0d0
#define CM_TD0DIV  0x0d4
#define CM_TD1CTL  0x0d8
#define CM_TD1DIV  0x0dc
#define CM_TSENSCTL  0x0e0
#define CM_TSENSDIV  0x0e4
#define CM_TIMERCTL  0x0e8
#define CM_TIMERDIV  0x0ec
#define CM_UARTCTL  0x0f0
#define CM_UARTDIV  0x0f4
#define CM_VECCTL  0x0f8
#define CM_VECDIV  0x0fc
#define CM_PULSECTL  0x190
#define CM_PULSEDIV  0x194
#define CM_SDCCTL  0x1a8
#define CM_SDCDIV  0x1ac
#define CM_ARMCTL  0x1b0
#define CM_AVEOCTL  0x1b8
#define CM_AVEODIV  0x1bc
#define CM_EMMCCTL  0x1c0
#define CM_EMMCDIV  0x1c4
#define CM_EMMC2CTL  0x1d0
#define CM_EMMC2DIV  0x1d4

/* General bits for the CM_*CTL regs */
define CM_ENABLE   BIT(4)
define CM_KILL   BIT(5)
define CM_GATE_BIT   6
define CM_GATE   BIT(CM_GATE_BIT)
define CM_BUSY   BIT(7)
define CM_BUSYD   BIT(8)
define CM_FRAC   BIT(9)
define CM_SRC_SHIFT   0
define CM_SRC_BITS   4
define CM_SRC_MASK   0xf
define CM_SRC_GND   0
define CM_SRC_OSC   1
define CM_SRC_TESTDEBUG0  2
define CM_SRC_TESTDEBUG1  3
define CM_SRC_PLLA_CORE  4
define CM_SRC_PLLA_PER  4
define CM_SRC_PLLC_CORE0  5
define CM_SRC_PLLC_PER  5
define CM_SRC_PLLC_CORE1  8
define CM_SRC_PLLD_CORE  6
define CM_SRC_PLLD_PER  6
define CM_SRC_PLLH_AUX  7
define CM_SRC_PLLC_CORE1  8
define CM_SRC_PLLC_CORE2  9

#define CM_OSCCOUNT  0x100

#define CM_PLLA   0x104
define CM_PLL_ANARST   BIT(8)
define CM_PLLA_HOLDPER  BIT(7)
define CM_PLLA_LOADPER  BIT(6)
define CM_PLLA_HOLDCORE  BIT(5)
define CM_PLLA_LOADCORE  BIT(4)
define CM_PLLA_HOLDCCP2  BIT(3)
define CM_PLLA_LOADCCP2  BIT(2)
define CM_PLLA_HOLDDSI0  BIT(1)
define CM_PLLA_LOADDSI0  BIT(0)

#define CM_PLLC   0x108
define CM_PLLC_HOLDPER  BIT(7)
define CM_PLLC_LOADPER  BIT(6)
define CM_PLLC_HOLDCORE2  BIT(5)
define CM_PLLC_LOADCORE2  BIT(4)
define CM_PLLC_HOLDCORE1  BIT(3)
define CM_PLLC_LOADCORE1  BIT(2)
define CM_PLLC_HOLDCORE0  BIT(1)
define CM_PLLC_LOADCORE0  BIT(0)

#define CM_PLLD   0x10c
define CM_PLLD_HOLDPER  BIT(7)
define CM_PLLD_LOADPER  BIT(6)
define CM_PLLD_HOLDCORE  BIT(5)
define CM_PLLD_LOADCORE  BIT(4)
define CM_PLLD_HOLDDSI1  BIT(3)
define CM_PLLD_LOADDSI1  BIT(2)
define CM_PLLD_HOLDDSI0  BIT(1)
define CM_PLLD_LOADDSI0  BIT(0)

#define CM_PLLH   0x110
define CM_PLLH_LOADRCAL  BIT(2)
define CM_PLLH_LOADAUX  BIT(1)
define CM_PLLH_LOADPIX  BIT(0)

#define CM_LOCK   0x114
define CM_LOCK_FLOCKH   BIT(12)
define CM_LOCK_FLOCKD   BIT(11)
define CM_LOCK_FLOCKC   BIT(10)
define CM_LOCK_FLOCKB   BIT(9)
define CM_LOCK_FLOCKA   BIT(8)

#define CM_EVENT  0x118
#define CM_DSI1ECTL  0x158
#define CM_DSI1EDIV  0x15c
#define CM_DSI1PCTL  0x160
#define CM_DSI1PDIV  0x164
#define CM_DFTCTL  0x168
#define CM_DFTDIV  0x16c

#define CM_PLLB   0x170
define CM_PLLB_HOLDARM  BIT(1)
define CM_PLLB_LOADARM  BIT(0)

#define A2W_PLLA_CTRL  0x1100
#define A2W_PLLC_CTRL  0x1120
#define A2W_PLLD_CTRL  0x1140
#define A2W_PLLH_CTRL  0x1160
#define A2W_PLLB_CTRL  0x11e0
define A2W_PLL_CTRL_PRST_DISABLE BIT(17)
define A2W_PLL_CTRL_PWRDN  BIT(16)
define A2W_PLL_CTRL_PDIV_MASK  0x000007000
define A2W_PLL_CTRL_PDIV_SHIFT 12
define A2W_PLL_CTRL_NDIV_MASK  0x0000003ff
define A2W_PLL_CTRL_NDIV_SHIFT 0

#define A2W_PLLA_ANA0  0x1010
#define A2W_PLLC_ANA0  0x1030
#define A2W_PLLD_ANA0  0x1050
#define A2W_PLLH_ANA0  0x1070
#define A2W_PLLB_ANA0  0x10f0

#define A2W_PLL_KA_SHIFT 7
#define A2W_PLL_KA_MASK  GENMASK(9, 7)
#define A2W_PLL_KI_SHIFT 19
#define A2W_PLL_KI_MASK  GENMASK(21, 19)
#define A2W_PLL_KP_SHIFT 15
#define A2W_PLL_KP_MASK  GENMASK(18, 15)

#define A2W_PLLH_KA_SHIFT 19
#define A2W_PLLH_KA_MASK GENMASK(21, 19)
#define A2W_PLLH_KI_LOW_SHIFT 22
#define A2W_PLLH_KI_LOW_MASK GENMASK(23, 22)
#define A2W_PLLH_KI_HIGH_SHIFT 0
#define A2W_PLLH_KI_HIGH_MASK GENMASK(0, 0)
#define A2W_PLLH_KP_SHIFT 1
#define A2W_PLLH_KP_MASK GENMASK(4, 1)

#define A2W_XOSC_CTRL  0x1190
define A2W_XOSC_CTRL_PLLB_ENABLE BIT(7)
define A2W_XOSC_CTRL_PLLA_ENABLE BIT(6)
define A2W_XOSC_CTRL_PLLD_ENABLE BIT(5)
define A2W_XOSC_CTRL_DDR_ENABLE BIT(4)
define A2W_XOSC_CTRL_CPR1_ENABLE BIT(3)
define A2W_XOSC_CTRL_USB_ENABLE BIT(2)
define A2W_XOSC_CTRL_HDMI_ENABLE BIT(1)
define A2W_XOSC_CTRL_PLLC_ENABLE BIT(0)

#define A2W_PLLA_FRAC  0x1200
#define A2W_PLLC_FRAC  0x1220
#define A2W_PLLD_FRAC  0x1240
#define A2W_PLLH_FRAC  0x1260
#define A2W_PLLB_FRAC  0x12e0
define A2W_PLL_FRAC_MASK  ((1 << A2W_PLL_FRAC_BITS) - 1)
define A2W_PLL_FRAC_BITS  20

#define A2W_PLL_CHANNEL_DISABLE  BIT(8)
#define A2W_PLL_DIV_BITS  8
#define A2W_PLL_DIV_SHIFT  0

#define A2W_PLLA_DSI0  0x1300
#define A2W_PLLA_CORE  0x1400
#define A2W_PLLA_PER  0x1500
#define A2W_PLLA_CCP2  0x1600

#define A2W_PLLC_CORE2  0x1320
#define A2W_PLLC_CORE1  0x1420
#define A2W_PLLC_PER  0x1520
#define A2W_PLLC_CORE0  0x1620

#define A2W_PLLD_DSI0  0x1340
#define A2W_PLLD_CORE  0x1440
#define A2W_PLLD_PER  0x1540
#define A2W_PLLD_DSI1  0x1640

#define A2W_PLLH_AUX  0x1360
#define A2W_PLLH_RCAL  0x1460
#define A2W_PLLH_PIX  0x1560
#define A2W_PLLH_STS  0x1660

#define A2W_PLLH_CTRLR  0x1960
#define A2W_PLLH_FRACR  0x1a60
#define A2W_PLLH_AUXR  0x1b60
#define A2W_PLLH_RCALR  0x1c60
#define A2W_PLLH_PIXR  0x1d60
#define A2W_PLLH_STSR  0x1e60

#define A2W_PLLB_ARM  0x13e0
#define A2W_PLLB_SP0  0x14e0
#define A2W_PLLB_SP1  0x15e0
#define A2W_PLLB_SP2  0x16e0

#define LOCK_TIMEOUT_NS  100000000
#define BCM2835_MAX_FB_RATE 1750000000u

#define SOC_BCM2835  BIT(0)
#define SOC_BCM2711  BIT(1)
#define SOC_ALL   (SOC_BCM2835 | SOC_BCM2711)

/*
 * Names of clocks used within the driver that need to be replaced
 * with an external parent's name.  This array is in the order that
 * the clocks node in the DT references external clocks.
 */

static const char *const cprman_parent_names[] = {
 "xosc",
 "dsi0_byte",
 "dsi0_ddr2",
 "dsi0_ddr",
 "dsi1_byte",
 "dsi1_ddr2",
 "dsi1_ddr",
};

struct bcm2835_cprman {
 struct device *dev;
 void __iomem *regs;
 spinlock_t regs_lock; /* spinlock for all clocks */
 unsigned int soc;

 /*
 * Real names of cprman clock parents looked up through
 * of_clk_get_parent_name(), which will be used in the
 * parent_names[] arrays for clock registration.
 */

 const char *real_parent_names[ARRAY_SIZE(cprman_parent_names)];

 /* Must be last */
 struct clk_hw_onecell_data onecell;
};

struct cprman_plat_data {
 unsigned int soc;
};

static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val)
{
 writel(CM_PASSWORD | val, cprman->regs + reg);
}

static inline u32 cprman_read(struct bcm2835_cprman *cprman, u32 reg)
{
 return readl(cprman->regs + reg);
}

/* Does a cycle of measuring a clock through the TCNT clock, which may
 * source from many other clocks in the system.
 */

static unsigned long bcm2835_measure_tcnt_mux(struct bcm2835_cprman *cprman,
           u32 tcnt_mux)
{
 u32 osccount = 19200; /* 1ms */
 u32 count;
 ktime_t timeout;

 spin_lock(&cprman->regs_lock);

 cprman_write(cprman, CM_TCNTCTL, CM_KILL);

 cprman_write(cprman, CM_TCNTCTL,
       (tcnt_mux & CM_SRC_MASK) |
       (tcnt_mux >> CM_SRC_BITS) << CM_TCNT_SRC1_SHIFT);

 cprman_write(cprman, CM_OSCCOUNT, osccount);

 /* do a kind delay at the start */
 mdelay(1);

 /* Finish off whatever is left of OSCCOUNT */
 timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
 while (cprman_read(cprman, CM_OSCCOUNT)) {
  if (ktime_after(ktime_get(), timeout)) {
   dev_err(cprman->dev, "timeout waiting for OSCCOUNT\n");
   count = 0;
   goto out;
  }
  cpu_relax();
 }

 /* Wait for BUSY to clear. */
 timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
 while (cprman_read(cprman, CM_TCNTCTL) & CM_BUSY) {
  if (ktime_after(ktime_get(), timeout)) {
   dev_err(cprman->dev, "timeout waiting for !BUSY\n");
   count = 0;
   goto out;
  }
  cpu_relax();
 }

 count = cprman_read(cprman, CM_TCNTCNT);

 cprman_write(cprman, CM_TCNTCTL, 0);

out:
 spin_unlock(&cprman->regs_lock);

 return count * 1000;
}

static void bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base,
       const struct debugfs_reg32 *regs,
       size_t nregs, struct dentry *dentry)
{
 struct debugfs_regset32 *regset;

 regset = devm_kzalloc(cprman->dev, sizeof(*regset), GFP_KERNEL);
 if (!regset)
  return;

 regset->regs = regs;
 regset->nregs = nregs;
 regset->base = cprman->regs + base;

 debugfs_create_regset32("regdump", S_IRUGO, dentry, regset);
}

struct bcm2835_pll_data {
 const char *name;
 u32 cm_ctrl_reg;
 u32 a2w_ctrl_reg;
 u32 frac_reg;
 u32 ana_reg_base;
 u32 reference_enable_mask;
 /* Bit in CM_LOCK to indicate when the PLL has locked. */
 u32 lock_mask;
 u32 flags;

 const struct bcm2835_pll_ana_bits *ana;

 unsigned long min_rate;
 unsigned long max_rate;
 /*
 * Highest rate for the VCO before we have to use the
 * pre-divide-by-2.
 */

 unsigned long max_fb_rate;
};

struct bcm2835_pll_ana_bits {
 u32 mask0;
 u32 set0;
 u32 mask1;
 u32 set1;
 u32 mask3;
 u32 set3;
 u32 fb_prediv_mask;
};

static const struct bcm2835_pll_ana_bits bcm2835_ana_default = {
 .mask0 = 0,
 .set0 = 0,
 .mask1 = A2W_PLL_KI_MASK | A2W_PLL_KP_MASK,
 .set1 = (2 << A2W_PLL_KI_SHIFT) | (8 << A2W_PLL_KP_SHIFT),
 .mask3 = A2W_PLL_KA_MASK,
 .set3 = (2 << A2W_PLL_KA_SHIFT),
 .fb_prediv_mask = BIT(14),
};

static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = {
 .mask0 = A2W_PLLH_KA_MASK | A2W_PLLH_KI_LOW_MASK,
 .set0 = (2 << A2W_PLLH_KA_SHIFT) | (2 << A2W_PLLH_KI_LOW_SHIFT),
 .mask1 = A2W_PLLH_KI_HIGH_MASK | A2W_PLLH_KP_MASK,
 .set1 = (6 << A2W_PLLH_KP_SHIFT),
 .mask3 = 0,
 .set3 = 0,
 .fb_prediv_mask = BIT(11),
};

struct bcm2835_pll_divider_data {
 const char *name;
 const char *source_pll;

 u32 cm_reg;
 u32 a2w_reg;

 u32 load_mask;
 u32 hold_mask;
 u32 fixed_divider;
 u32 flags;
};

struct bcm2835_clock_data {
 const char *name;

 const char *const *parents;
 int num_mux_parents;

 /* Bitmap encoding which parents accept rate change propagation. */
 unsigned int set_rate_parent;

 u32 ctl_reg;
 u32 div_reg;

 /* Number of integer bits in the divider */
 u32 int_bits;
 /* Number of fractional bits in the divider */
 u32 frac_bits;

 u32 flags;

 bool is_vpu_clock;
 bool is_mash_clock;
 bool low_jitter;

 u32 tcnt_mux;

 bool round_up;
};

struct bcm2835_gate_data {
 const char *name;
 const char *parent;

 u32 ctl_reg;
};

struct bcm2835_pll {
 struct clk_hw hw;
 struct bcm2835_cprman *cprman;
 const struct bcm2835_pll_data *data;
};

static int bcm2835_pll_is_on(struct clk_hw *hw)
{
 struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
 struct bcm2835_cprman *cprman = pll->cprman;
 const struct bcm2835_pll_data *data = pll->data;

 return cprman_read(cprman, data->a2w_ctrl_reg) &
  A2W_PLL_CTRL_PRST_DISABLE;
}

static u32 bcm2835_pll_get_prediv_mask(struct bcm2835_cprman *cprman,
           const struct bcm2835_pll_data *data)
{
 /*
 * On BCM2711 there isn't a pre-divisor available in the PLL feedback
 * loop. Bits 13:14 of ANA1 (PLLA,PLLB,PLLC,PLLD) have been re-purposed
 * for to for VCO RANGE bits.
 */

 if (cprman->soc & SOC_BCM2711)
  return 0;

 return data->ana->fb_prediv_mask;
}

static void bcm2835_pll_choose_ndiv_and_fdiv(unsigned long rate,
          unsigned long parent_rate,
          u32 *ndiv, u32 *fdiv)
{
 u64 div;

 div = (u64)rate << A2W_PLL_FRAC_BITS;
 do_div(div, parent_rate);

 *ndiv = div >> A2W_PLL_FRAC_BITS;
 *fdiv = div & ((1 << A2W_PLL_FRAC_BITS) - 1);
}

static long bcm2835_pll_rate_from_divisors(unsigned long parent_rate,
        u32 ndiv, u32 fdiv, u32 pdiv)
{
 u64 rate;

 if (pdiv == 0)
  return 0;

 rate = (u64)parent_rate * ((ndiv << A2W_PLL_FRAC_BITS) + fdiv);
 do_div(rate, pdiv);
 return rate >> A2W_PLL_FRAC_BITS;
}

static int bcm2835_pll_determine_rate(struct clk_hw *hw,
          struct clk_rate_request *req)
{
 struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
 const struct bcm2835_pll_data *data = pll->data;
 u32 ndiv, fdiv;

 req->rate = clamp(req->rate, data->min_rate, data->max_rate);

 bcm2835_pll_choose_ndiv_and_fdiv(req->rate, req->best_parent_rate,
      &ndiv, &fdiv);

 req->rate = bcm2835_pll_rate_from_divisors(req->best_parent_rate,
         ndiv, fdiv,
         1);

 return 0;
}

static unsigned long bcm2835_pll_get_rate(struct clk_hw *hw,
       unsigned long parent_rate)
{
 struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
 struct bcm2835_cprman *cprman = pll->cprman;
 const struct bcm2835_pll_data *data = pll->data;
 u32 a2wctrl = cprman_read(cprman, data->a2w_ctrl_reg);
 u32 ndiv, pdiv, fdiv;
 bool using_prediv;

 if (parent_rate == 0)
  return 0;

 fdiv = cprman_read(cprman, data->frac_reg) & A2W_PLL_FRAC_MASK;
 ndiv = (a2wctrl & A2W_PLL_CTRL_NDIV_MASK) >> A2W_PLL_CTRL_NDIV_SHIFT;
 pdiv = (a2wctrl & A2W_PLL_CTRL_PDIV_MASK) >> A2W_PLL_CTRL_PDIV_SHIFT;
 using_prediv = cprman_read(cprman, data->ana_reg_base + 4) &
         bcm2835_pll_get_prediv_mask(cprman, data);

 if (using_prediv) {
  ndiv *= 2;
  fdiv *= 2;
 }

 return bcm2835_pll_rate_from_divisors(parent_rate, ndiv, fdiv, pdiv);
}

static void bcm2835_pll_off(struct clk_hw *hw)
{
 struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
 struct bcm2835_cprman *cprman = pll->cprman;
 const struct bcm2835_pll_data *data = pll->data;

 spin_lock(&cprman->regs_lock);
 cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
 cprman_write(cprman, data->a2w_ctrl_reg,
       cprman_read(cprman, data->a2w_ctrl_reg) |
       A2W_PLL_CTRL_PWRDN);
 spin_unlock(&cprman->regs_lock);
}

static int bcm2835_pll_on(struct clk_hw *hw)
{
 struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
 struct bcm2835_cprman *cprman = pll->cprman;
 const struct bcm2835_pll_data *data = pll->data;
 ktime_t timeout;

 cprman_write(cprman, data->a2w_ctrl_reg,
       cprman_read(cprman, data->a2w_ctrl_reg) &
       ~A2W_PLL_CTRL_PWRDN);

 /* Take the PLL out of reset. */
 spin_lock(&cprman->regs_lock);
 cprman_write(cprman, data->cm_ctrl_reg,
       cprman_read(cprman, data->cm_ctrl_reg) & ~CM_PLL_ANARST);
 spin_unlock(&cprman->regs_lock);

 /* Wait for the PLL to lock. */
 timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);
 while (!(cprman_read(cprman, CM_LOCK) & data->lock_mask)) {
  if (ktime_after(ktime_get(), timeout)) {
   dev_err(cprman->dev, "%s: couldn't lock PLL\n",
    clk_hw_get_name(hw));
   return -ETIMEDOUT;
  }

  cpu_relax();
 }

 cprman_write(cprman, data->a2w_ctrl_reg,
       cprman_read(cprman, data->a2w_ctrl_reg) |
       A2W_PLL_CTRL_PRST_DISABLE);

 return 0;
}

static void
bcm2835_pll_write_ana(struct bcm2835_cprman *cprman, u32 ana_reg_base, u32 *ana)
{
 int i;

 /*
 * ANA register setup is done as a series of writes to
 * ANA3-ANA0, in that order.  This lets us write all 4
 * registers as a single cycle of the serdes interface (taking
 * 100 xosc clocks), whereas if we were to update ana0, 1, and
 * 3 individually through their partial-write registers, each
 * would be their own serdes cycle.
 */

 for (i = 3; i >= 0; i--)
  cprman_write(cprman, ana_reg_base + i * 4, ana[i]);
}

static int bcm2835_pll_set_rate(struct clk_hw *hw,
    unsigned long rate, unsigned long parent_rate)
{
 struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
 struct bcm2835_cprman *cprman = pll->cprman;
 const struct bcm2835_pll_data *data = pll->data;
 u32 prediv_mask = bcm2835_pll_get_prediv_mask(cprman, data);
 bool was_using_prediv, use_fb_prediv, do_ana_setup_first;
 u32 ndiv, fdiv, a2w_ctl;
 u32 ana[4];
 int i;

 if (rate > data->max_fb_rate) {
  use_fb_prediv = true;
  rate /= 2;
 } else {
  use_fb_prediv = false;
 }

 bcm2835_pll_choose_ndiv_and_fdiv(rate, parent_rate, &ndiv, &fdiv);

 for (i = 3; i >= 0; i--)
  ana[i] = cprman_read(cprman, data->ana_reg_base + i * 4);

 was_using_prediv = ana[1] & prediv_mask;

 ana[0] &= ~data->ana->mask0;
 ana[0] |= data->ana->set0;
 ana[1] &= ~data->ana->mask1;
 ana[1] |= data->ana->set1;
 ana[3] &= ~data->ana->mask3;
 ana[3] |= data->ana->set3;

 if (was_using_prediv && !use_fb_prediv) {
  ana[1] &= ~prediv_mask;
  do_ana_setup_first = true;
 } else if (!was_using_prediv && use_fb_prediv) {
  ana[1] |= prediv_mask;
  do_ana_setup_first = false;
 } else {
  do_ana_setup_first = true;
 }

 /* Unmask the reference clock from the oscillator. */
 spin_lock(&cprman->regs_lock);
 cprman_write(cprman, A2W_XOSC_CTRL,
       cprman_read(cprman, A2W_XOSC_CTRL) |
       data->reference_enable_mask);
 spin_unlock(&cprman->regs_lock);

 if (do_ana_setup_first)
  bcm2835_pll_write_ana(cprman, data->ana_reg_base, ana);

 /* Set the PLL multiplier from the oscillator. */
 cprman_write(cprman, data->frac_reg, fdiv);

 a2w_ctl = cprman_read(cprman, data->a2w_ctrl_reg);
 a2w_ctl &= ~A2W_PLL_CTRL_NDIV_MASK;
 a2w_ctl |= ndiv << A2W_PLL_CTRL_NDIV_SHIFT;
 a2w_ctl &= ~A2W_PLL_CTRL_PDIV_MASK;
 a2w_ctl |= 1 << A2W_PLL_CTRL_PDIV_SHIFT;
 cprman_write(cprman, data->a2w_ctrl_reg, a2w_ctl);

 if (!do_ana_setup_first)
  bcm2835_pll_write_ana(cprman, data->ana_reg_base, ana);

 return 0;
}

static void bcm2835_pll_debug_init(struct clk_hw *hw,
      struct dentry *dentry)
{
 struct bcm2835_pll *pll = container_of(hw, struct bcm2835_pll, hw);
 struct bcm2835_cprman *cprman = pll->cprman;
 const struct bcm2835_pll_data *data = pll->data;
 struct debugfs_reg32 *regs;

 regs = devm_kcalloc(cprman->dev, 7, sizeof(*regs), GFP_KERNEL);
 if (!regs)
  return;

 regs[0].name = "cm_ctrl";
 regs[0].offset = data->cm_ctrl_reg;
 regs[1].name = "a2w_ctrl";
 regs[1].offset = data->a2w_ctrl_reg;
 regs[2].name = "frac";
 regs[2].offset = data->frac_reg;
 regs[3].name = "ana0";
 regs[3].offset = data->ana_reg_base + 0 * 4;
 regs[4].name = "ana1";
 regs[4].offset = data->ana_reg_base + 1 * 4;
 regs[5].name = "ana2";
 regs[5].offset = data->ana_reg_base + 2 * 4;
 regs[6].name = "ana3";
 regs[6].offset = data->ana_reg_base + 3 * 4;

 bcm2835_debugfs_regset(cprman, 0, regs, 7, dentry);
}

static const struct clk_ops bcm2835_pll_clk_ops = {
 .is_prepared = bcm2835_pll_is_on,
 .prepare = bcm2835_pll_on,
 .unprepare = bcm2835_pll_off,
 .recalc_rate = bcm2835_pll_get_rate,
 .set_rate = bcm2835_pll_set_rate,
 .determine_rate = bcm2835_pll_determine_rate,
 .debug_init = bcm2835_pll_debug_init,
};

struct bcm2835_pll_divider {
 struct clk_divider div;
 struct bcm2835_cprman *cprman;
 const struct bcm2835_pll_divider_data *data;
};

static struct bcm2835_pll_divider *
bcm2835_pll_divider_from_hw(struct clk_hw *hw)
{
 return container_of(hw, struct bcm2835_pll_divider, div.hw);
}

static int bcm2835_pll_divider_is_on(struct clk_hw *hw)
{
 struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
 struct bcm2835_cprman *cprman = divider->cprman;
 const struct bcm2835_pll_divider_data *data = divider->data;

 return !(cprman_read(cprman, data->a2w_reg) & A2W_PLL_CHANNEL_DISABLE);
}

static int bcm2835_pll_divider_determine_rate(struct clk_hw *hw,
           struct clk_rate_request *req)
{
 return clk_divider_ops.determine_rate(hw, req);
}

static unsigned long bcm2835_pll_divider_get_rate(struct clk_hw *hw,
        unsigned long parent_rate)
{
 return clk_divider_ops.recalc_rate(hw, parent_rate);
}

static void bcm2835_pll_divider_off(struct clk_hw *hw)
{
 struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
 struct bcm2835_cprman *cprman = divider->cprman;
 const struct bcm2835_pll_divider_data *data = divider->data;

 spin_lock(&cprman->regs_lock);
 cprman_write(cprman, data->cm_reg,
       (cprman_read(cprman, data->cm_reg) &
        ~data->load_mask) | data->hold_mask);
 cprman_write(cprman, data->a2w_reg,
       cprman_read(cprman, data->a2w_reg) |
       A2W_PLL_CHANNEL_DISABLE);
 spin_unlock(&cprman->regs_lock);
}

static int bcm2835_pll_divider_on(struct clk_hw *hw)
{
 struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
 struct bcm2835_cprman *cprman = divider->cprman;
 const struct bcm2835_pll_divider_data *data = divider->data;

 spin_lock(&cprman->regs_lock);
 cprman_write(cprman, data->a2w_reg,
       cprman_read(cprman, data->a2w_reg) &
       ~A2W_PLL_CHANNEL_DISABLE);

 cprman_write(cprman, data->cm_reg,
       cprman_read(cprman, data->cm_reg) & ~data->hold_mask);
 spin_unlock(&cprman->regs_lock);

 return 0;
}

static int bcm2835_pll_divider_set_rate(struct clk_hw *hw,
     unsigned long rate,
     unsigned long parent_rate)
{
 struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
 struct bcm2835_cprman *cprman = divider->cprman;
 const struct bcm2835_pll_divider_data *data = divider->data;
 u32 cm, div, max_div = 1 << A2W_PLL_DIV_BITS;

 div = DIV_ROUND_UP_ULL(parent_rate, rate);

 div = min(div, max_div);
 if (div == max_div)
  div = 0;

 cprman_write(cprman, data->a2w_reg, div);
 cm = cprman_read(cprman, data->cm_reg);
 cprman_write(cprman, data->cm_reg, cm | data->load_mask);
 cprman_write(cprman, data->cm_reg, cm & ~data->load_mask);

 return 0;
}

static void bcm2835_pll_divider_debug_init(struct clk_hw *hw,
        struct dentry *dentry)
{
 struct bcm2835_pll_divider *divider = bcm2835_pll_divider_from_hw(hw);
 struct bcm2835_cprman *cprman = divider->cprman;
 const struct bcm2835_pll_divider_data *data = divider->data;
 struct debugfs_reg32 *regs;

 regs = devm_kcalloc(cprman->dev, 7, sizeof(*regs), GFP_KERNEL);
 if (!regs)
  return;

 regs[0].name = "cm";
 regs[0].offset = data->cm_reg;
 regs[1].name = "a2w";
 regs[1].offset = data->a2w_reg;

 bcm2835_debugfs_regset(cprman, 0, regs, 2, dentry);
}

static const struct clk_ops bcm2835_pll_divider_clk_ops = {
 .is_prepared = bcm2835_pll_divider_is_on,
 .prepare = bcm2835_pll_divider_on,
 .unprepare = bcm2835_pll_divider_off,
 .recalc_rate = bcm2835_pll_divider_get_rate,
 .set_rate = bcm2835_pll_divider_set_rate,
 .determine_rate = bcm2835_pll_divider_determine_rate,
 .debug_init = bcm2835_pll_divider_debug_init,
};

/*
 * The CM dividers do fixed-point division, so we can't use the
 * generic integer divider code like the PLL dividers do (and we can't
 * fake it by having some fixed shifts preceding it in the clock tree,
 * because we'd run out of bits in a 32-bit unsigned long).
 */

struct bcm2835_clock {
 struct clk_hw hw;
 struct bcm2835_cprman *cprman;
 const struct bcm2835_clock_data *data;
};

static struct bcm2835_clock *bcm2835_clock_from_hw(struct clk_hw *hw)
{
 return container_of(hw, struct bcm2835_clock, hw);
}

static int bcm2835_clock_is_on(struct clk_hw *hw)
{
 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 struct bcm2835_cprman *cprman = clock->cprman;
 const struct bcm2835_clock_data *data = clock->data;

 return (cprman_read(cprman, data->ctl_reg) & CM_ENABLE) != 0;
}

static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
        unsigned long rate,
        unsigned long parent_rate)
{
 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 const struct bcm2835_clock_data *data = clock->data;
 u32 unused_frac_mask =
  GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1;
 u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS;
 u32 div, mindiv, maxdiv;

 do_div(temp, rate);
 div = temp;
 div &= ~unused_frac_mask;

 /* different clamping limits apply for a mash clock */
 if (data->is_mash_clock) {
  /* clamp to min divider of 2 */
  mindiv = 2 << CM_DIV_FRAC_BITS;
  /* clamp to the highest possible integer divider */
  maxdiv = (BIT(data->int_bits) - 1) << CM_DIV_FRAC_BITS;
 } else {
  /* clamp to min divider of 1 */
  mindiv = 1 << CM_DIV_FRAC_BITS;
  /* clamp to the highest possible fractional divider */
  maxdiv = GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
     CM_DIV_FRAC_BITS - data->frac_bits);
 }

 /* apply the clamping  limits */
 div = max_t(u32, div, mindiv);
 div = min_t(u32, div, maxdiv);

 return div;
}

static unsigned long bcm2835_clock_rate_from_divisor(struct bcm2835_clock *clock,
           unsigned long parent_rate,
           u32 div)
{
 const struct bcm2835_clock_data *data = clock->data;
 u64 temp;

 if (data->int_bits == 0 && data->frac_bits == 0)
  return parent_rate;

 /*
 * The divisor is a 12.12 fixed point field, but only some of
 * the bits are populated in any given clock.
 */

 div >>= CM_DIV_FRAC_BITS - data->frac_bits;
 div &= (1 << (data->int_bits + data->frac_bits)) - 1;

 if (div == 0)
  return 0;

 temp = (u64)parent_rate << data->frac_bits;

 do_div(temp, div);

 return temp;
}

static unsigned long bcm2835_round_rate(unsigned long rate)
{
 unsigned long scaler;
 unsigned long limit;

 limit = rate / 100000;

 scaler = 1;
 while (scaler < limit)
  scaler *= 10;

 /*
 * If increasing a clock by less than 0.1% changes it
 * from ..999.. to ..000.., round up.
 */

 if ((rate + scaler - 1) / scaler % 1000 == 0)
  rate = roundup(rate, scaler);

 return rate;
}

static unsigned long bcm2835_clock_get_rate(struct clk_hw *hw,
         unsigned long parent_rate)
{
 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 struct bcm2835_cprman *cprman = clock->cprman;
 const struct bcm2835_clock_data *data = clock->data;
 unsigned long rate;
 u32 div;

 if (data->int_bits == 0 && data->frac_bits == 0)
  return parent_rate;

 div = cprman_read(cprman, data->div_reg);

 rate = bcm2835_clock_rate_from_divisor(clock, parent_rate, div);

 if (data->round_up)
  rate = bcm2835_round_rate(rate);

 return rate;
}

static void bcm2835_clock_wait_busy(struct bcm2835_clock *clock)
{
 struct bcm2835_cprman *cprman = clock->cprman;
 const struct bcm2835_clock_data *data = clock->data;
 ktime_t timeout = ktime_add_ns(ktime_get(), LOCK_TIMEOUT_NS);

 while (cprman_read(cprman, data->ctl_reg) & CM_BUSY) {
  if (ktime_after(ktime_get(), timeout)) {
   dev_err(cprman->dev, "%s: couldn't lock PLL\n",
    clk_hw_get_name(&clock->hw));
   return;
  }
  cpu_relax();
 }
}

static void bcm2835_clock_off(struct clk_hw *hw)
{
 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 struct bcm2835_cprman *cprman = clock->cprman;
 const struct bcm2835_clock_data *data = clock->data;

 spin_lock(&cprman->regs_lock);
 cprman_write(cprman, data->ctl_reg,
       cprman_read(cprman, data->ctl_reg) & ~CM_ENABLE);
 spin_unlock(&cprman->regs_lock);

 /* BUSY will remain high until the divider completes its cycle. */
 bcm2835_clock_wait_busy(clock);
}

static int bcm2835_clock_on(struct clk_hw *hw)
{
 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 struct bcm2835_cprman *cprman = clock->cprman;
 const struct bcm2835_clock_data *data = clock->data;

 spin_lock(&cprman->regs_lock);
 cprman_write(cprman, data->ctl_reg,
       cprman_read(cprman, data->ctl_reg) |
       CM_ENABLE |
       CM_GATE);
 spin_unlock(&cprman->regs_lock);

 /* Debug code to measure the clock once it's turned on to see
 * if it's ticking at the rate we expect.
 */

 if (data->tcnt_mux && false) {
  dev_info(cprman->dev,
    "clk %s: rate %ld, measure %ld\n",
    data->name,
    clk_hw_get_rate(hw),
    bcm2835_measure_tcnt_mux(cprman, data->tcnt_mux));
 }

 return 0;
}

static int bcm2835_clock_set_rate(struct clk_hw *hw,
      unsigned long rate, unsigned long parent_rate)
{
 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 struct bcm2835_cprman *cprman = clock->cprman;
 const struct bcm2835_clock_data *data = clock->data;
 u32 div = bcm2835_clock_choose_div(hw, rate, parent_rate);
 u32 ctl;

 spin_lock(&cprman->regs_lock);

 /*
 * Setting up frac support
 *
 * In principle it is recommended to stop/start the clock first,
 * but as we set CLK_SET_RATE_GATE during registration of the
 * clock this requirement should be take care of by the
 * clk-framework.
 */

 ctl = cprman_read(cprman, data->ctl_reg) & ~CM_FRAC;
 ctl |= (div & CM_DIV_FRAC_MASK) ? CM_FRAC : 0;
 cprman_write(cprman, data->ctl_reg, ctl);

 cprman_write(cprman, data->div_reg, div);

 spin_unlock(&cprman->regs_lock);

 return 0;
}

static bool
bcm2835_clk_is_pllc(struct clk_hw *hw)
{
 if (!hw)
  return false;

 return strncmp(clk_hw_get_name(hw), "pllc", 4) == 0;
}

static unsigned long bcm2835_clock_choose_div_and_prate(struct clk_hw *hw,
       int parent_idx,
       unsigned long rate,
       u32 *div,
       unsigned long *prate,
       unsigned long *avgrate)
{
 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 struct bcm2835_cprman *cprman = clock->cprman;
 const struct bcm2835_clock_data *data = clock->data;
 unsigned long best_rate = 0;
 u32 curdiv, mindiv, maxdiv;
 struct clk_hw *parent;

 parent = clk_hw_get_parent_by_index(hw, parent_idx);

 if (!(BIT(parent_idx) & data->set_rate_parent)) {
  *prate = clk_hw_get_rate(parent);
  *div = bcm2835_clock_choose_div(hw, rate, *prate);

  *avgrate = bcm2835_clock_rate_from_divisor(clock, *prate, *div);

  if (data->low_jitter && (*div & CM_DIV_FRAC_MASK)) {
   unsigned long high, low;
   u32 int_div = *div & ~CM_DIV_FRAC_MASK;

   high = bcm2835_clock_rate_from_divisor(clock, *prate,
              int_div);
   int_div += CM_DIV_FRAC_MASK + 1;
   low = bcm2835_clock_rate_from_divisor(clock, *prate,
             int_div);

   /*
 * Return a value which is the maximum deviation
 * below the ideal rate, for use as a metric.
 */

   return *avgrate - max(*avgrate - low, high - *avgrate);
  }
  return *avgrate;
 }

 if (data->frac_bits)
  dev_warn(cprman->dev,
   "frac bits are not used when propagating rate change");

 /* clamp to min divider of 2 if we're dealing with a mash clock */
 mindiv = data->is_mash_clock ? 2 : 1;
 maxdiv = BIT(data->int_bits) - 1;

 /* TODO: Be smart, and only test a subset of the available divisors. */
 for (curdiv = mindiv; curdiv <= maxdiv; curdiv++) {
  unsigned long tmp_rate;

  tmp_rate = clk_hw_round_rate(parent, rate * curdiv);
  tmp_rate /= curdiv;
  if (curdiv == mindiv ||
      (tmp_rate > best_rate && tmp_rate <= rate))
   best_rate = tmp_rate;

  if (best_rate == rate)
   break;
 }

 *div = curdiv << CM_DIV_FRAC_BITS;
 *prate = curdiv * best_rate;
 *avgrate = best_rate;

 return best_rate;
}

static int bcm2835_clock_determine_rate(struct clk_hw *hw,
     struct clk_rate_request *req)
{
 struct clk_hw *parent, *best_parent = NULL;
 bool current_parent_is_pllc;
 unsigned long rate, best_rate = 0;
 unsigned long prate, best_prate = 0;
 unsigned long avgrate, best_avgrate = 0;
 size_t i;
 u32 div;

 current_parent_is_pllc = bcm2835_clk_is_pllc(clk_hw_get_parent(hw));

 /*
 * Select parent clock that results in the closest but lower rate
 */

 for (i = 0; i < clk_hw_get_num_parents(hw); ++i) {
  parent = clk_hw_get_parent_by_index(hw, i);
  if (!parent)
   continue;

  /*
 * Don't choose a PLLC-derived clock as our parent
 * unless it had been manually set that way.  PLLC's
 * frequency gets adjusted by the firmware due to
 * over-temp or under-voltage conditions, without
 * prior notification to our clock consumer.
 */

  if (bcm2835_clk_is_pllc(parent) && !current_parent_is_pllc)
   continue;

  rate = bcm2835_clock_choose_div_and_prate(hw, i, req->rate,
         &div, &prate,
         &avgrate);
  if (abs(req->rate - rate) < abs(req->rate - best_rate)) {
   best_parent = parent;
   best_prate = prate;
   best_rate = rate;
   best_avgrate = avgrate;
  }
 }

 if (!best_parent)
  return -EINVAL;

 req->best_parent_hw = best_parent;
 req->best_parent_rate = best_prate;

 req->rate = best_avgrate;

 return 0;
}

static int bcm2835_clock_set_parent(struct clk_hw *hw, u8 index)
{
 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 struct bcm2835_cprman *cprman = clock->cprman;
 const struct bcm2835_clock_data *data = clock->data;
 u8 src = (index << CM_SRC_SHIFT) & CM_SRC_MASK;

 cprman_write(cprman, data->ctl_reg, src);
 return 0;
}

static u8 bcm2835_clock_get_parent(struct clk_hw *hw)
{
 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 struct bcm2835_cprman *cprman = clock->cprman;
 const struct bcm2835_clock_data *data = clock->data;
 u32 src = cprman_read(cprman, data->ctl_reg);

 return (src & CM_SRC_MASK) >> CM_SRC_SHIFT;
}

static const struct debugfs_reg32 bcm2835_debugfs_clock_reg32[] = {
 {
  .name = "ctl",
  .offset = 0,
 },
 {
  .name = "div",
  .offset = 4,
 },
};

static void bcm2835_clock_debug_init(struct clk_hw *hw,
        struct dentry *dentry)
{
 struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
 struct bcm2835_cprman *cprman = clock->cprman;
 const struct bcm2835_clock_data *data = clock->data;

 bcm2835_debugfs_regset(cprman, data->ctl_reg,
  bcm2835_debugfs_clock_reg32,
  ARRAY_SIZE(bcm2835_debugfs_clock_reg32),
  dentry);
}

static const struct clk_ops bcm2835_clock_clk_ops = {
 .is_prepared = bcm2835_clock_is_on,
 .prepare = bcm2835_clock_on,
 .unprepare = bcm2835_clock_off,
 .recalc_rate = bcm2835_clock_get_rate,
 .set_rate = bcm2835_clock_set_rate,
 .determine_rate = bcm2835_clock_determine_rate,
 .set_parent = bcm2835_clock_set_parent,
 .get_parent = bcm2835_clock_get_parent,
 .debug_init = bcm2835_clock_debug_init,
};

static int bcm2835_vpu_clock_is_on(struct clk_hw *hw)
{
 return true;
}

/*
 * The VPU clock can never be disabled (it doesn't have an ENABLE
 * bit), so it gets its own set of clock ops.
 */

static const struct clk_ops bcm2835_vpu_clock_clk_ops = {
 .is_prepared = bcm2835_vpu_clock_is_on,
 .recalc_rate = bcm2835_clock_get_rate,
 .set_rate = bcm2835_clock_set_rate,
 .determine_rate = bcm2835_clock_determine_rate,
 .set_parent = bcm2835_clock_set_parent,
 .get_parent = bcm2835_clock_get_parent,
 .debug_init = bcm2835_clock_debug_init,
};

static struct clk_hw *bcm2835_register_pll(struct bcm2835_cprman *cprman,
        const void *data)
{
 const struct bcm2835_pll_data *pll_data = data;
 struct bcm2835_pll *pll;
 struct clk_init_data init;
 int ret;

 memset(&init, 0, sizeof(init));

 /* All of the PLLs derive from the external oscillator. */
 init.parent_names = &cprman->real_parent_names[0];
 init.num_parents = 1;
 init.name = pll_data->name;
 init.ops = &bcm2835_pll_clk_ops;
 init.flags = pll_data->flags | CLK_IGNORE_UNUSED;

 pll = kzalloc(sizeof(*pll), GFP_KERNEL);
 if (!pll)
  return NULL;

 pll->cprman = cprman;
 pll->data = pll_data;
 pll->hw.init = &init;

 ret = devm_clk_hw_register(cprman->dev, &pll->hw);
 if (ret) {
  kfree(pll);
  return NULL;
 }
 return &pll->hw;
}

static struct clk_hw *
bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
        const void *data)
{
 const struct bcm2835_pll_divider_data *divider_data = data;
 struct bcm2835_pll_divider *divider;
 struct clk_init_data init;
 const char *divider_name;
 int ret;

 if (divider_data->fixed_divider != 1) {
  divider_name = devm_kasprintf(cprman->dev, GFP_KERNEL,
           "%s_prediv", divider_data->name);
  if (!divider_name)
   return NULL;
 } else {
  divider_name = divider_data->name;
 }

 memset(&init, 0, sizeof(init));

 init.parent_names = ÷r_data->source_pll;
 init.num_parents = 1;
 init.name = divider_name;
 init.ops = &bcm2835_pll_divider_clk_ops;
 init.flags = divider_data->flags | CLK_IGNORE_UNUSED;

 divider = devm_kzalloc(cprman->dev, sizeof(*divider), GFP_KERNEL);
 if (!divider)
  return NULL;

 divider->div.reg = cprman->regs + divider_data->a2w_reg;
 divider->div.shift = A2W_PLL_DIV_SHIFT;
 divider->div.width = A2W_PLL_DIV_BITS;
 divider->div.flags = CLK_DIVIDER_MAX_AT_ZERO;
 divider->div.lock = &cprman->regs_lock;
 divider->div.hw.init = &init;
 divider->div.table = NULL;

 divider->cprman = cprman;
 divider->data = divider_data;

 ret = devm_clk_hw_register(cprman->dev, ÷r->div.hw);
 if (ret)
  return ERR_PTR(ret);

 /*
 * PLLH's channels have a fixed divide by 10 afterwards, which
 * is what our consumers are actually using.
 */

 if (divider_data->fixed_divider != 1) {
  return clk_hw_register_fixed_factor(cprman->dev,
          divider_data->name,
          divider_name,
          CLK_SET_RATE_PARENT,
          1,
          divider_data->fixed_divider);
 }

 return ÷r->div.hw;
}

static struct clk_hw *bcm2835_register_clock(struct bcm2835_cprman *cprman,
          const void *data)
{
 const struct bcm2835_clock_data *clock_data = data;
 struct bcm2835_clock *clock;
 struct clk_init_data init;
 const char *parents[1 << CM_SRC_BITS];
 size_t i;
 int ret;

 /*
 * Replace our strings referencing parent clocks with the
 * actual clock-output-name of the parent.
 */

 for (i = 0; i < clock_data->num_mux_parents; i++) {
  parents[i] = clock_data->parents[i];

  ret = match_string(cprman_parent_names,
       ARRAY_SIZE(cprman_parent_names),
       parents[i]);
  if (ret >= 0)
   parents[i] = cprman->real_parent_names[ret];
 }

 memset(&init, 0, sizeof(init));
 init.parent_names = parents;
 init.num_parents = clock_data->num_mux_parents;
 init.name = clock_data->name;
 init.flags = clock_data->flags | CLK_IGNORE_UNUSED;

 /*
 * Pass the CLK_SET_RATE_PARENT flag if we are allowed to propagate
 * rate changes on at least of the parents.
 */

 if (clock_data->set_rate_parent)
  init.flags |= CLK_SET_RATE_PARENT;

 if (clock_data->is_vpu_clock) {
  init.ops = &bcm2835_vpu_clock_clk_ops;
 } else {
  init.ops = &bcm2835_clock_clk_ops;
  init.flags |= CLK_SET_RATE_GATE | CLK_SET_PARENT_GATE;

  /* If the clock wasn't actually enabled at boot, it's not
 * critical.
 */

  if (!(cprman_read(cprman, clock_data->ctl_reg) & CM_ENABLE))
   init.flags &= ~CLK_IS_CRITICAL;
 }

 clock = devm_kzalloc(cprman->dev, sizeof(*clock), GFP_KERNEL);
 if (!clock)
  return NULL;

 clock->cprman = cprman;
 clock->data = clock_data;
 clock->hw.init = &init;

 ret = devm_clk_hw_register(cprman->dev, &clock->hw);
 if (ret)
  return ERR_PTR(ret);
 return &clock->hw;
}

static struct clk_hw *bcm2835_register_gate(struct bcm2835_cprman *cprman,
         const void *data)
{
 const struct bcm2835_gate_data *gate_data = data;

 return clk_hw_register_gate(cprman->dev, gate_data->name,
        gate_data->parent,
        CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
        cprman->regs + gate_data->ctl_reg,
        CM_GATE_BIT, 0, &cprman->regs_lock);
}

struct bcm2835_clk_desc {
 struct clk_hw *(*clk_register)(struct bcm2835_cprman *cprman,
           const void *data);
 unsigned int supported;
 const void *data;
};

/* assignment helper macros for different clock types */
#define _REGISTER(f, s, ...) { .clk_register = f, \
          .supported = s,    \
          .data = __VA_ARGS__ }
#define REGISTER_PLL(s, ...) _REGISTER(&bcm2835_register_pll, \
       s,    \
       &(struct bcm2835_pll_data) \
       {__VA_ARGS__})
#define REGISTER_PLL_DIV(s, ...) _REGISTER(&bcm2835_register_pll_divider, \
        s,      \
        &(struct bcm2835_pll_divider_data) \
        {__VA_ARGS__})
#define REGISTER_CLK(s, ...) _REGISTER(&bcm2835_register_clock, \
       s,    \
       &(struct bcm2835_clock_data) \
       {__VA_ARGS__})
#define REGISTER_GATE(s, ...) _REGISTER(&bcm2835_register_gate, \
       s,    \
       &(struct bcm2835_gate_data) \
       {__VA_ARGS__})

/* parent mux arrays plus helper macros */

/* main oscillator parent mux */
static const char *const bcm2835_clock_osc_parents[] = {
 "gnd",
 "xosc",
 "testdebug0",
 "testdebug1"
};

#define REGISTER_OSC_CLK(s, ...) REGISTER_CLK(   \
 s,        \
 .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), \
 .parents = bcm2835_clock_osc_parents,    \
 __VA_ARGS__)

/* main peripheral parent mux */
static const char *const bcm2835_clock_per_parents[] = {
 "gnd",
 "xosc",
 "testdebug0",
 "testdebug1",
 "plla_per",
 "pllc_per",
 "plld_per",
 "pllh_aux",
};

#define REGISTER_PER_CLK(s, ...) REGISTER_CLK(   \
 s,        \
 .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), \
 .parents = bcm2835_clock_per_parents,    \
 __VA_ARGS__)

/*
 * Restrict clock sources for the PCM peripheral to the oscillator and
 * PLLD_PER because other source may have varying rates or be switched
 * off.
 *
 * Prevent other sources from being selected by replacing their names in
 * the list of potential parents with dummy entries (entry index is
 * significant).
 */

static const char *const bcm2835_pcm_per_parents[] = {
 "-",
 "xosc",
 "-",
 "-",
 "-",
 "-",
 "plld_per",
 "-",
};

#define REGISTER_PCM_CLK(s, ...) REGISTER_CLK(   \
 s,        \
 .num_mux_parents = ARRAY_SIZE(bcm2835_pcm_per_parents),  \
 .parents = bcm2835_pcm_per_parents,    \
 __VA_ARGS__)

/* main vpu parent mux */
static const char *const bcm2835_clock_vpu_parents[] = {
 "gnd",
 "xosc",
 "testdebug0",
 "testdebug1",
 "plla_core",
 "pllc_core0",
 "plld_core",
 "pllh_aux",
 "pllc_core1",
 "pllc_core2",
};

#define REGISTER_VPU_CLK(s, ...) REGISTER_CLK(   \
 s,        \
 .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), \
 .parents = bcm2835_clock_vpu_parents,    \
 __VA_ARGS__)

/*
 * DSI parent clocks.  The DSI byte/DDR/DDR2 clocks come from the DSI
 * analog PHY.  The _inv variants are generated internally to cprman,
 * but we don't use them so they aren't hooked up.
 */

static const char *const bcm2835_clock_dsi0_parents[] = {
 "gnd",
 "xosc",
 "testdebug0",
 "testdebug1",
 "dsi0_ddr",
 "dsi0_ddr_inv",
 "dsi0_ddr2",
 "dsi0_ddr2_inv",
 "dsi0_byte",
 "dsi0_byte_inv",
};

static const char *const bcm2835_clock_dsi1_parents[] = {
 "gnd",
 "xosc",
 "testdebug0",
 "testdebug1",
 "dsi1_ddr",
 "dsi1_ddr_inv",
 "dsi1_ddr2",
 "dsi1_ddr2_inv",
 "dsi1_byte",
 "dsi1_byte_inv",
};

#define REGISTER_DSI0_CLK(s, ...) REGISTER_CLK(   \
 s,        \
 .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi0_parents), \
 .parents = bcm2835_clock_dsi0_parents,    \
 __VA_ARGS__)

#define REGISTER_DSI1_CLK(s, ...) REGISTER_CLK(   \
 s,        \
 .num_mux_parents = ARRAY_SIZE(bcm2835_clock_dsi1_parents), \
 .parents = bcm2835_clock_dsi1_parents,    \
 __VA_ARGS__)

/*
 * the real definition of all the pll, pll_dividers and clocks
 * these make use of the above REGISTER_* macros
 */

static const struct bcm2835_clk_desc clk_desc_array[] = {
 /* the PLL + PLL dividers */

 /*
 * PLLA is the auxiliary PLL, used to drive the CCP2
 * (Compact Camera Port 2) transmitter clock.
 *
 * It is in the PX LDO power domain, which is on when the
 * AUDIO domain is on.
 */

 [BCM2835_PLLA]  = REGISTER_PLL(
  SOC_ALL,
  .name = "plla",
  .cm_ctrl_reg = CM_PLLA,
  .a2w_ctrl_reg = A2W_PLLA_CTRL,
  .frac_reg = A2W_PLLA_FRAC,
  .ana_reg_base = A2W_PLLA_ANA0,
  .reference_enable_mask = A2W_XOSC_CTRL_PLLA_ENABLE,
  .lock_mask = CM_LOCK_FLOCKA,

  .ana = &bcm2835_ana_default,

  .min_rate = 600000000u,
  .max_rate = 2400000000u,
  .max_fb_rate = BCM2835_MAX_FB_RATE),
 [BCM2835_PLLA_CORE] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "plla_core",
  .source_pll = "plla",
  .cm_reg = CM_PLLA,
  .a2w_reg = A2W_PLLA_CORE,
  .load_mask = CM_PLLA_LOADCORE,
  .hold_mask = CM_PLLA_HOLDCORE,
  .fixed_divider = 1,
  .flags = CLK_SET_RATE_PARENT),
 [BCM2835_PLLA_PER] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "plla_per",
  .source_pll = "plla",
  .cm_reg = CM_PLLA,
  .a2w_reg = A2W_PLLA_PER,
  .load_mask = CM_PLLA_LOADPER,
  .hold_mask = CM_PLLA_HOLDPER,
  .fixed_divider = 1,
  .flags = CLK_SET_RATE_PARENT),
 [BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "plla_dsi0",
  .source_pll = "plla",
  .cm_reg = CM_PLLA,
  .a2w_reg = A2W_PLLA_DSI0,
  .load_mask = CM_PLLA_LOADDSI0,
  .hold_mask = CM_PLLA_HOLDDSI0,
  .fixed_divider = 1),
 [BCM2835_PLLA_CCP2] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "plla_ccp2",
  .source_pll = "plla",
  .cm_reg = CM_PLLA,
  .a2w_reg = A2W_PLLA_CCP2,
  .load_mask = CM_PLLA_LOADCCP2,
  .hold_mask = CM_PLLA_HOLDCCP2,
  .fixed_divider = 1,
  .flags = CLK_SET_RATE_PARENT),

 /* PLLB is used for the ARM's clock. */
 [BCM2835_PLLB]  = REGISTER_PLL(
  SOC_ALL,
  .name = "pllb",
  .cm_ctrl_reg = CM_PLLB,
  .a2w_ctrl_reg = A2W_PLLB_CTRL,
  .frac_reg = A2W_PLLB_FRAC,
  .ana_reg_base = A2W_PLLB_ANA0,
  .reference_enable_mask = A2W_XOSC_CTRL_PLLB_ENABLE,
  .lock_mask = CM_LOCK_FLOCKB,

  .ana = &bcm2835_ana_default,

  .min_rate = 600000000u,
  .max_rate = 3000000000u,
  .max_fb_rate = BCM2835_MAX_FB_RATE,
  .flags = CLK_GET_RATE_NOCACHE),
 [BCM2835_PLLB_ARM] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "pllb_arm",
  .source_pll = "pllb",
  .cm_reg = CM_PLLB,
  .a2w_reg = A2W_PLLB_ARM,
  .load_mask = CM_PLLB_LOADARM,
  .hold_mask = CM_PLLB_HOLDARM,
  .fixed_divider = 1,
  .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE),

 /*
 * PLLC is the core PLL, used to drive the core VPU clock.
 *
 * It is in the PX LDO power domain, which is on when the
 * AUDIO domain is on.
 */

 [BCM2835_PLLC]  = REGISTER_PLL(
  SOC_ALL,
  .name = "pllc",
  .cm_ctrl_reg = CM_PLLC,
  .a2w_ctrl_reg = A2W_PLLC_CTRL,
  .frac_reg = A2W_PLLC_FRAC,
  .ana_reg_base = A2W_PLLC_ANA0,
  .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
  .lock_mask = CM_LOCK_FLOCKC,

  .ana = &bcm2835_ana_default,

  .min_rate = 600000000u,
  .max_rate = 3000000000u,
  .max_fb_rate = BCM2835_MAX_FB_RATE),
 [BCM2835_PLLC_CORE0] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "pllc_core0",
  .source_pll = "pllc",
  .cm_reg = CM_PLLC,
  .a2w_reg = A2W_PLLC_CORE0,
  .load_mask = CM_PLLC_LOADCORE0,
  .hold_mask = CM_PLLC_HOLDCORE0,
  .fixed_divider = 1,
  .flags = CLK_SET_RATE_PARENT),
 [BCM2835_PLLC_CORE1] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "pllc_core1",
  .source_pll = "pllc",
  .cm_reg = CM_PLLC,
  .a2w_reg = A2W_PLLC_CORE1,
  .load_mask = CM_PLLC_LOADCORE1,
  .hold_mask = CM_PLLC_HOLDCORE1,
  .fixed_divider = 1,
  .flags = CLK_SET_RATE_PARENT),
 [BCM2835_PLLC_CORE2] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "pllc_core2",
  .source_pll = "pllc",
  .cm_reg = CM_PLLC,
  .a2w_reg = A2W_PLLC_CORE2,
  .load_mask = CM_PLLC_LOADCORE2,
  .hold_mask = CM_PLLC_HOLDCORE2,
  .fixed_divider = 1,
  .flags = CLK_SET_RATE_PARENT),
 [BCM2835_PLLC_PER] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "pllc_per",
  .source_pll = "pllc",
  .cm_reg = CM_PLLC,
  .a2w_reg = A2W_PLLC_PER,
  .load_mask = CM_PLLC_LOADPER,
  .hold_mask = CM_PLLC_HOLDPER,
  .fixed_divider = 1,
  .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),

 /*
 * PLLD is the display PLL, used to drive DSI display panels.
 *
 * It is in the PX LDO power domain, which is on when the
 * AUDIO domain is on.
 */

 [BCM2835_PLLD]  = REGISTER_PLL(
  SOC_ALL,
  .name = "plld",
  .cm_ctrl_reg = CM_PLLD,
  .a2w_ctrl_reg = A2W_PLLD_CTRL,
  .frac_reg = A2W_PLLD_FRAC,
  .ana_reg_base = A2W_PLLD_ANA0,
  .reference_enable_mask = A2W_XOSC_CTRL_DDR_ENABLE,
  .lock_mask = CM_LOCK_FLOCKD,

  .ana = &bcm2835_ana_default,

  .min_rate = 600000000u,
  .max_rate = 2400000000u,
  .max_fb_rate = BCM2835_MAX_FB_RATE),
 [BCM2835_PLLD_CORE] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "plld_core",
  .source_pll = "plld",
  .cm_reg = CM_PLLD,
  .a2w_reg = A2W_PLLD_CORE,
  .load_mask = CM_PLLD_LOADCORE,
  .hold_mask = CM_PLLD_HOLDCORE,
  .fixed_divider = 1,
  .flags = CLK_SET_RATE_PARENT),
 /*
 * VPU firmware assumes that PLLD_PER isn't disabled by the ARM core.
 * Otherwise this could cause firmware lookups. That's why we mark
 * it as critical.
 */

 [BCM2835_PLLD_PER] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "plld_per",
  .source_pll = "plld",
  .cm_reg = CM_PLLD,
  .a2w_reg = A2W_PLLD_PER,
  .load_mask = CM_PLLD_LOADPER,
  .hold_mask = CM_PLLD_HOLDPER,
  .fixed_divider = 1,
  .flags = CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
 [BCM2835_PLLD_DSI0] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "plld_dsi0",
  .source_pll = "plld",
  .cm_reg = CM_PLLD,
  .a2w_reg = A2W_PLLD_DSI0,
  .load_mask = CM_PLLD_LOADDSI0,
  .hold_mask = CM_PLLD_HOLDDSI0,
  .fixed_divider = 1),
 [BCM2835_PLLD_DSI1] = REGISTER_PLL_DIV(
  SOC_ALL,
  .name = "plld_dsi1",
  .source_pll = "plld",
  .cm_reg = CM_PLLD,
  .a2w_reg = A2W_PLLD_DSI1,
  .load_mask = CM_PLLD_LOADDSI1,
  .hold_mask = CM_PLLD_HOLDDSI1,
  .fixed_divider = 1),

 /*
 * PLLH is used to supply the pixel clock or the AUX clock for the
 * TV encoder.
 *
 * It is in the HDMI power domain.
 */

 [BCM2835_PLLH]  = REGISTER_PLL(
  SOC_BCM2835,
  "pllh",
  .cm_ctrl_reg = CM_PLLH,
  .a2w_ctrl_reg = A2W_PLLH_CTRL,
  .frac_reg = A2W_PLLH_FRAC,
  .ana_reg_base = A2W_PLLH_ANA0,
  .reference_enable_mask = A2W_XOSC_CTRL_PLLC_ENABLE,
  .lock_mask = CM_LOCK_FLOCKH,

  .ana = &bcm2835_ana_pllh,

  .min_rate = 600000000u,
  .max_rate = 3000000000u,
  .max_fb_rate = BCM2835_MAX_FB_RATE),
 [BCM2835_PLLH_RCAL] = REGISTER_PLL_DIV(
  SOC_BCM2835,
  .name = "pllh_rcal",
  .source_pll = "pllh",
  .cm_reg = CM_PLLH,
  .a2w_reg = A2W_PLLH_RCAL,
  .load_mask = CM_PLLH_LOADRCAL,
  .hold_mask = 0,
  .fixed_divider = 10,
  .flags = CLK_SET_RATE_PARENT),
 [BCM2835_PLLH_AUX] = REGISTER_PLL_DIV(
  SOC_BCM2835,
  .name = "pllh_aux",
  .source_pll = "pllh",
  .cm_reg = CM_PLLH,
  .a2w_reg = A2W_PLLH_AUX,
  .load_mask = CM_PLLH_LOADAUX,
  .hold_mask = 0,
  .fixed_divider = 1,
  .flags = CLK_SET_RATE_PARENT),
 [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV(
  SOC_BCM2835,
  .name = "pllh_pix",
  .source_pll = "pllh",
  .cm_reg = CM_PLLH,
  .a2w_reg = A2W_PLLH_PIX,
  .load_mask = CM_PLLH_LOADPIX,
  .hold_mask = 0,
  .fixed_divider = 10,
  .flags = CLK_SET_RATE_PARENT),

 /* the clocks */

 /* clocks with oscillator parent mux */

 /* One Time Programmable Memory clock.  Maximum 10Mhz. */
 [BCM2835_CLOCK_OTP] = REGISTER_OSC_CLK(
  SOC_ALL,
  .name = "otp",
  .ctl_reg = CM_OTPCTL,
  .div_reg = CM_OTPDIV,
  .int_bits = 4,
  .frac_bits = 0,
  .tcnt_mux = 6),
 /*
 * Used for a 1Mhz clock for the system clocksource, and also used
 * bythe watchdog timer and the camera pulse generator.
 */

 [BCM2835_CLOCK_TIMER] = REGISTER_OSC_CLK(
  SOC_ALL,
  .name = "timer",
  .ctl_reg = CM_TIMERCTL,
  .div_reg = CM_TIMERDIV,
  .int_bits = 6,
  .frac_bits = 12),
 /*
 * Clock for the temperature sensor.
 * Generally run at 2Mhz, max 5Mhz.
 */

 [BCM2835_CLOCK_TSENS] = REGISTER_OSC_CLK(
  SOC_ALL,
  .name = "tsens",
  .ctl_reg = CM_TSENSCTL,
  .div_reg = CM_TSENSDIV,
  .int_bits = 5,
  .frac_bits = 0),
 [BCM2835_CLOCK_TEC] = REGISTER_OSC_CLK(
  SOC_ALL,
  .name = "tec",
  .ctl_reg = CM_TECCTL,
  .div_reg = CM_TECDIV,
  .int_bits = 6,
  .frac_bits = 0),

 /* clocks with vpu parent mux */
 [BCM2835_CLOCK_H264] = REGISTER_VPU_CLK(
  SOC_ALL,
  .name = "h264",
  .ctl_reg = CM_H264CTL,
  .div_reg = CM_H264DIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 1),
 [BCM2835_CLOCK_ISP] = REGISTER_VPU_CLK(
  SOC_ALL,
  .name = "isp",
  .ctl_reg = CM_ISPCTL,
  .div_reg = CM_ISPDIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 2),

 /*
 * Secondary SDRAM clock.  Used for low-voltage modes when the PLL
 * in the SDRAM controller can't be used.
 */

 [BCM2835_CLOCK_SDRAM] = REGISTER_VPU_CLK(
  SOC_ALL,
  .name = "sdram",
  .ctl_reg = CM_SDCCTL,
  .div_reg = CM_SDCDIV,
  .int_bits = 6,
  .frac_bits = 0,
  .tcnt_mux = 3),
 [BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK(
  SOC_ALL,
  .name = "v3d",
  .ctl_reg = CM_V3DCTL,
  .div_reg = CM_V3DDIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 4),
 /*
 * VPU clock.  This doesn't have an enable bit, since it drives
 * the bus for everything else, and is special so it doesn't need
 * to be gated for rate changes.  It is also known as "clk_audio"
 * in various hardware documentation.
 */

 [BCM2835_CLOCK_VPU] = REGISTER_VPU_CLK(
  SOC_ALL,
  .name = "vpu",
  .ctl_reg = CM_VPUCTL,
  .div_reg = CM_VPUDIV,
  .int_bits = 12,
  .frac_bits = 8,
  .flags = CLK_IS_CRITICAL,
  .is_vpu_clock = true,
  .tcnt_mux = 5),

 /* clocks with per parent mux */
 [BCM2835_CLOCK_AVEO] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "aveo",
  .ctl_reg = CM_AVEOCTL,
  .div_reg = CM_AVEODIV,
  .int_bits = 4,
  .frac_bits = 0,
  .tcnt_mux = 38),
 [BCM2835_CLOCK_CAM0] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "cam0",
  .ctl_reg = CM_CAM0CTL,
  .div_reg = CM_CAM0DIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 14),
 [BCM2835_CLOCK_CAM1] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "cam1",
  .ctl_reg = CM_CAM1CTL,
  .div_reg = CM_CAM1DIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 15),
 [BCM2835_CLOCK_DFT] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "dft",
  .ctl_reg = CM_DFTCTL,
  .div_reg = CM_DFTDIV,
  .int_bits = 5,
  .frac_bits = 0),
 [BCM2835_CLOCK_DPI] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "dpi",
  .ctl_reg = CM_DPICTL,
  .div_reg = CM_DPIDIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 17),

 /* Arasan EMMC clock */
 [BCM2835_CLOCK_EMMC] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "emmc",
  .ctl_reg = CM_EMMCCTL,
  .div_reg = CM_EMMCDIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 39),

 /* EMMC2 clock (only available for BCM2711) */
 [BCM2711_CLOCK_EMMC2] = REGISTER_PER_CLK(
  SOC_BCM2711,
  .name = "emmc2",
  .ctl_reg = CM_EMMC2CTL,
  .div_reg = CM_EMMC2DIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 42),

 /* General purpose (GPIO) clocks */
 [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "gp0",
  .ctl_reg = CM_GP0CTL,
  .div_reg = CM_GP0DIV,
  .int_bits = 12,
  .frac_bits = 12,
  .is_mash_clock = true,
  .tcnt_mux = 20),
 [BCM2835_CLOCK_GP1] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "gp1",
  .ctl_reg = CM_GP1CTL,
  .div_reg = CM_GP1DIV,
  .int_bits = 12,
  .frac_bits = 12,
  .flags = CLK_IS_CRITICAL,
  .is_mash_clock = true,
  .tcnt_mux = 21),
 [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "gp2",
  .ctl_reg = CM_GP2CTL,
  .div_reg = CM_GP2DIV,
  .int_bits = 12,
  .frac_bits = 12,
  .flags = CLK_IS_CRITICAL),

 /* HDMI state machine */
 [BCM2835_CLOCK_HSM] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "hsm",
  .ctl_reg = CM_HSMCTL,
  .div_reg = CM_HSMDIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 22),
 [BCM2835_CLOCK_PCM] = REGISTER_PCM_CLK(
  SOC_ALL,
  .name = "pcm",
  .ctl_reg = CM_PCMCTL,
  .div_reg = CM_PCMDIV,
  .int_bits = 12,
  .frac_bits = 12,
  .is_mash_clock = true,
  .low_jitter = true,
  .tcnt_mux = 23),
 [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "pwm",
  .ctl_reg = CM_PWMCTL,
  .div_reg = CM_PWMDIV,
  .int_bits = 12,
  .frac_bits = 12,
  .is_mash_clock = true,
  .tcnt_mux = 24),
 [BCM2835_CLOCK_SLIM] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "slim",
  .ctl_reg = CM_SLIMCTL,
  .div_reg = CM_SLIMDIV,
  .int_bits = 12,
  .frac_bits = 12,
  .is_mash_clock = true,
  .tcnt_mux = 25),
 [BCM2835_CLOCK_SMI] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "smi",
  .ctl_reg = CM_SMICTL,
  .div_reg = CM_SMIDIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 27),
 [BCM2835_CLOCK_UART] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "uart",
  .ctl_reg = CM_UARTCTL,
  .div_reg = CM_UARTDIV,
  .int_bits = 10,
  .frac_bits = 12,
  .tcnt_mux = 28,
  .round_up = true),

 /* TV encoder clock.  Only operating frequency is 108Mhz.  */
 [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "vec",
  .ctl_reg = CM_VECCTL,
  .div_reg = CM_VECDIV,
  .int_bits = 4,
  .frac_bits = 0,
  /*
 * Allow rate change propagation only on PLLH_AUX which is
 * assigned index 7 in the parent array.
 */

  .set_rate_parent = BIT(7),
  .tcnt_mux = 29),

 /* dsi clocks */
 [BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "dsi0e",
  .ctl_reg = CM_DSI0ECTL,
  .div_reg = CM_DSI0EDIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 18),
 [BCM2835_CLOCK_DSI1E] = REGISTER_PER_CLK(
  SOC_ALL,
  .name = "dsi1e",
  .ctl_reg = CM_DSI1ECTL,
  .div_reg = CM_DSI1EDIV,
  .int_bits = 4,
  .frac_bits = 8,
  .tcnt_mux = 19),
 [BCM2835_CLOCK_DSI0P] = REGISTER_DSI0_CLK(
  SOC_ALL,
  .name = "dsi0p",
  .ctl_reg = CM_DSI0PCTL,
  .div_reg = CM_DSI0PDIV,
  .int_bits = 0,
  .frac_bits = 0,
  .tcnt_mux = 12),
 [BCM2835_CLOCK_DSI1P] = REGISTER_DSI1_CLK(
  SOC_ALL,
  .name = "dsi1p",
  .ctl_reg = CM_DSI1PCTL,
  .div_reg = CM_DSI1PDIV,
  .int_bits = 0,
  .frac_bits = 0,
  .tcnt_mux = 13),

 /* the gates */

 /*
 * CM_PERIICTL (and CM_PERIACTL, CM_SYSCTL and CM_VPUCTL if
 * you have the debug bit set in the power manager, which we
 * don't bother exposing) are individual gates off of the
 * non-stop vpu clock.
 */

 [BCM2835_CLOCK_PERI_IMAGE] = REGISTER_GATE(
  SOC_ALL,
  .name = "peri_image",
  .parent = "vpu",
  .ctl_reg = CM_PERIICTL),
};

/*
 * Permanently take a reference on the parent of the SDRAM clock.
 *
 * While the SDRAM is being driven by its dedicated PLL most of the
 * time, there is a little loop running in the firmware that
 * periodically switches the SDRAM to using our CM clock to do PVT
 * recalibration, with the assumption that the previously configured
 * SDRAM parent is still enabled and running.
 */

static int bcm2835_mark_sdc_parent_critical(struct clk *sdc)
{
 struct clk *parent = clk_get_parent(sdc);

 if (IS_ERR(parent))
  return PTR_ERR(parent);

 return clk_prepare_enable(parent);
}

static int bcm2835_clk_probe(struct platform_device *pdev)
{
 struct device *dev = &pdev->dev;
 struct clk_hw **hws;
 struct bcm2835_cprman *cprman;
 const struct bcm2835_clk_desc *desc;
 const size_t asize = ARRAY_SIZE(clk_desc_array);
 const struct cprman_plat_data *pdata;
 size_t i;
 int ret;

 pdata = of_device_get_match_data(&pdev->dev);
 if (!pdata)
  return -ENODEV;

 cprman = devm_kzalloc(dev,
         struct_size(cprman, onecell.hws, asize),
         GFP_KERNEL);
 if (!cprman)
  return -ENOMEM;

 spin_lock_init(&cprman->regs_lock);
 cprman->dev = dev;
 cprman->regs = devm_platform_ioremap_resource(pdev, 0);
 if (IS_ERR(cprman->regs))
  return PTR_ERR(cprman->regs);

 memcpy(cprman->real_parent_names, cprman_parent_names,
        sizeof(cprman_parent_names));
 of_clk_parent_fill(dev->of_node, cprman->real_parent_names,
      ARRAY_SIZE(cprman_parent_names));

 /*
 * Make sure the external oscillator has been registered.
 *
 * The other (DSI) clocks are not present on older device
 * trees, which we still need to support for backwards
 * compatibility.
 */

 if (!cprman->real_parent_names[0])
  return -ENODEV;

 platform_set_drvdata(pdev, cprman);

 cprman->onecell.num = asize;
 cprman->soc = pdata->soc;
 hws = cprman->onecell.hws;

 for (i = 0; i < asize; i++) {
  desc = &clk_desc_array[i];
  if (desc->clk_register && desc->data &&
      (desc->supported & pdata->soc)) {
   hws[i] = desc->clk_register(cprman, desc->data);
  }
 }

 ret = bcm2835_mark_sdc_parent_critical(hws[BCM2835_CLOCK_SDRAM]->clk);
 if (ret)
  return ret;

 return of_clk_add_hw_provider(dev->of_node, of_clk_hw_onecell_get,
          &cprman->onecell);
}

static const struct cprman_plat_data cprman_bcm2835_plat_data = {
 .soc = SOC_BCM2835,
};

static const struct cprman_plat_data cprman_bcm2711_plat_data = {
 .soc = SOC_BCM2711,
};

static const struct of_device_id bcm2835_clk_of_match[] = {
 { .compatible = "brcm,bcm2835-cprman", .data = &cprman_bcm2835_plat_data },
 { .compatible = "brcm,bcm2711-cprman", .data = &cprman_bcm2711_plat_data },
 {}
};
MODULE_DEVICE_TABLE(of, bcm2835_clk_of_match);

static struct platform_driver bcm2835_clk_driver = {
 .driver = {
  .name = "bcm2835-clk",
  .of_match_table = bcm2835_clk_of_match,
 },
 .probe          = bcm2835_clk_probe,
};

builtin_platform_driver(bcm2835_clk_driver);

MODULE_AUTHOR("Eric Anholt ");
MODULE_DESCRIPTION("BCM2835 clock driver");

Messung V0.5
C=96 H=96 G=95

¤ Dauer der Verarbeitung: 0.17 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.