|
@@ -12,9 +12,6 @@
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
* GNU General Public License for more details.
|
|
|
*
|
|
|
- * You should have received a copy of the GNU General Public License
|
|
|
- * along with this program; if not, write to the Free Software
|
|
|
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
*/
|
|
|
|
|
|
/**
|
|
@@ -40,6 +37,7 @@
|
|
|
#include <linux/clk-provider.h>
|
|
|
#include <linux/clkdev.h>
|
|
|
#include <linux/clk/bcm2835.h>
|
|
|
+#include <linux/debugfs.h>
|
|
|
#include <linux/module.h>
|
|
|
#include <linux/of.h>
|
|
|
#include <linux/platform_device.h>
|
|
@@ -51,6 +49,7 @@
|
|
|
#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
|
|
@@ -118,6 +117,8 @@
|
|
|
#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
|
|
|
|
|
@@ -128,6 +129,7 @@
|
|
|
# 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
|
|
@@ -297,11 +299,11 @@
|
|
|
struct bcm2835_cprman {
|
|
|
struct device *dev;
|
|
|
void __iomem *regs;
|
|
|
- spinlock_t regs_lock;
|
|
|
+ spinlock_t regs_lock; /* spinlock for all clocks */
|
|
|
const char *osc_name;
|
|
|
|
|
|
struct clk_onecell_data onecell;
|
|
|
- struct clk *clks[BCM2835_CLOCK_COUNT];
|
|
|
+ struct clk *clks[];
|
|
|
};
|
|
|
|
|
|
static inline void cprman_write(struct bcm2835_cprman *cprman, u32 reg, u32 val)
|
|
@@ -314,6 +316,27 @@ static inline u32 cprman_read(struct bcm2835_cprman *cprman, u32 reg)
|
|
|
return readl(cprman->regs + reg);
|
|
|
}
|
|
|
|
|
|
+static int bcm2835_debugfs_regset(struct bcm2835_cprman *cprman, u32 base,
|
|
|
+ struct debugfs_reg32 *regs, size_t nregs,
|
|
|
+ struct dentry *dentry)
|
|
|
+{
|
|
|
+ struct dentry *regdump;
|
|
|
+ struct debugfs_regset32 *regset;
|
|
|
+
|
|
|
+ regset = devm_kzalloc(cprman->dev, sizeof(*regset), GFP_KERNEL);
|
|
|
+ if (!regset)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ regset->regs = regs;
|
|
|
+ regset->nregs = nregs;
|
|
|
+ regset->base = cprman->regs + base;
|
|
|
+
|
|
|
+ regdump = debugfs_create_regset32("regdump", S_IRUGO, dentry,
|
|
|
+ regset);
|
|
|
+
|
|
|
+ return regdump ? 0 : -ENOMEM;
|
|
|
+}
|
|
|
+
|
|
|
/*
|
|
|
* These are fixed clocks. They're probably not all root clocks and it may
|
|
|
* be possible to turn them on and off but until this is mapped out better
|
|
@@ -394,115 +417,10 @@ static const struct bcm2835_pll_ana_bits bcm2835_ana_pllh = {
|
|
|
.fb_prediv_mask = BIT(11),
|
|
|
};
|
|
|
|
|
|
-/*
|
|
|
- * 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.
|
|
|
- */
|
|
|
-static const struct bcm2835_pll_data bcm2835_plla_data = {
|
|
|
- .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,
|
|
|
-};
|
|
|
-
|
|
|
-/* PLLB is used for the ARM's clock. */
|
|
|
-static const struct bcm2835_pll_data bcm2835_pllb_data = {
|
|
|
- .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,
|
|
|
-};
|
|
|
-
|
|
|
-/*
|
|
|
- * 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.
|
|
|
-*/
|
|
|
-static const struct bcm2835_pll_data bcm2835_pllc_data = {
|
|
|
- .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,
|
|
|
-};
|
|
|
-
|
|
|
-/*
|
|
|
- * 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.
|
|
|
- */
|
|
|
-static const struct bcm2835_pll_data bcm2835_plld_data = {
|
|
|
- .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,
|
|
|
-};
|
|
|
-
|
|
|
-/*
|
|
|
- * PLLH is used to supply the pixel clock or the AUX clock for the TV
|
|
|
- * encoder.
|
|
|
- *
|
|
|
- * It is in the HDMI power domain.
|
|
|
- */
|
|
|
-static const struct bcm2835_pll_data bcm2835_pllh_data = {
|
|
|
- "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,
|
|
|
-};
|
|
|
-
|
|
|
struct bcm2835_pll_divider_data {
|
|
|
const char *name;
|
|
|
- const struct bcm2835_pll_data *source_pll;
|
|
|
+ const char *source_pll;
|
|
|
+
|
|
|
u32 cm_reg;
|
|
|
u32 a2w_reg;
|
|
|
|
|
@@ -511,124 +429,6 @@ struct bcm2835_pll_divider_data {
|
|
|
u32 fixed_divider;
|
|
|
};
|
|
|
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_plla_core_data = {
|
|
|
- .name = "plla_core",
|
|
|
- .source_pll = &bcm2835_plla_data,
|
|
|
- .cm_reg = CM_PLLA,
|
|
|
- .a2w_reg = A2W_PLLA_CORE,
|
|
|
- .load_mask = CM_PLLA_LOADCORE,
|
|
|
- .hold_mask = CM_PLLA_HOLDCORE,
|
|
|
- .fixed_divider = 1,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_plla_per_data = {
|
|
|
- .name = "plla_per",
|
|
|
- .source_pll = &bcm2835_plla_data,
|
|
|
- .cm_reg = CM_PLLA,
|
|
|
- .a2w_reg = A2W_PLLA_PER,
|
|
|
- .load_mask = CM_PLLA_LOADPER,
|
|
|
- .hold_mask = CM_PLLA_HOLDPER,
|
|
|
- .fixed_divider = 1,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_pllb_arm_data = {
|
|
|
- .name = "pllb_arm",
|
|
|
- .source_pll = &bcm2835_pllb_data,
|
|
|
- .cm_reg = CM_PLLB,
|
|
|
- .a2w_reg = A2W_PLLB_ARM,
|
|
|
- .load_mask = CM_PLLB_LOADARM,
|
|
|
- .hold_mask = CM_PLLB_HOLDARM,
|
|
|
- .fixed_divider = 1,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_pllc_core0_data = {
|
|
|
- .name = "pllc_core0",
|
|
|
- .source_pll = &bcm2835_pllc_data,
|
|
|
- .cm_reg = CM_PLLC,
|
|
|
- .a2w_reg = A2W_PLLC_CORE0,
|
|
|
- .load_mask = CM_PLLC_LOADCORE0,
|
|
|
- .hold_mask = CM_PLLC_HOLDCORE0,
|
|
|
- .fixed_divider = 1,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_pllc_core1_data = {
|
|
|
- .name = "pllc_core1", .source_pll = &bcm2835_pllc_data,
|
|
|
- .cm_reg = CM_PLLC, A2W_PLLC_CORE1,
|
|
|
- .load_mask = CM_PLLC_LOADCORE1,
|
|
|
- .hold_mask = CM_PLLC_HOLDCORE1,
|
|
|
- .fixed_divider = 1,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_pllc_core2_data = {
|
|
|
- .name = "pllc_core2",
|
|
|
- .source_pll = &bcm2835_pllc_data,
|
|
|
- .cm_reg = CM_PLLC,
|
|
|
- .a2w_reg = A2W_PLLC_CORE2,
|
|
|
- .load_mask = CM_PLLC_LOADCORE2,
|
|
|
- .hold_mask = CM_PLLC_HOLDCORE2,
|
|
|
- .fixed_divider = 1,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_pllc_per_data = {
|
|
|
- .name = "pllc_per",
|
|
|
- .source_pll = &bcm2835_pllc_data,
|
|
|
- .cm_reg = CM_PLLC,
|
|
|
- .a2w_reg = A2W_PLLC_PER,
|
|
|
- .load_mask = CM_PLLC_LOADPER,
|
|
|
- .hold_mask = CM_PLLC_HOLDPER,
|
|
|
- .fixed_divider = 1,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_plld_core_data = {
|
|
|
- .name = "plld_core",
|
|
|
- .source_pll = &bcm2835_plld_data,
|
|
|
- .cm_reg = CM_PLLD,
|
|
|
- .a2w_reg = A2W_PLLD_CORE,
|
|
|
- .load_mask = CM_PLLD_LOADCORE,
|
|
|
- .hold_mask = CM_PLLD_HOLDCORE,
|
|
|
- .fixed_divider = 1,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_plld_per_data = {
|
|
|
- .name = "plld_per",
|
|
|
- .source_pll = &bcm2835_plld_data,
|
|
|
- .cm_reg = CM_PLLD,
|
|
|
- .a2w_reg = A2W_PLLD_PER,
|
|
|
- .load_mask = CM_PLLD_LOADPER,
|
|
|
- .hold_mask = CM_PLLD_HOLDPER,
|
|
|
- .fixed_divider = 1,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_pllh_rcal_data = {
|
|
|
- .name = "pllh_rcal",
|
|
|
- .source_pll = &bcm2835_pllh_data,
|
|
|
- .cm_reg = CM_PLLH,
|
|
|
- .a2w_reg = A2W_PLLH_RCAL,
|
|
|
- .load_mask = CM_PLLH_LOADRCAL,
|
|
|
- .hold_mask = 0,
|
|
|
- .fixed_divider = 10,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_pllh_aux_data = {
|
|
|
- .name = "pllh_aux",
|
|
|
- .source_pll = &bcm2835_pllh_data,
|
|
|
- .cm_reg = CM_PLLH,
|
|
|
- .a2w_reg = A2W_PLLH_AUX,
|
|
|
- .load_mask = CM_PLLH_LOADAUX,
|
|
|
- .hold_mask = 0,
|
|
|
- .fixed_divider = 10,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_pll_divider_data bcm2835_pllh_pix_data = {
|
|
|
- .name = "pllh_pix",
|
|
|
- .source_pll = &bcm2835_pllh_data,
|
|
|
- .cm_reg = CM_PLLH,
|
|
|
- .a2w_reg = A2W_PLLH_PIX,
|
|
|
- .load_mask = CM_PLLH_LOADPIX,
|
|
|
- .hold_mask = 0,
|
|
|
- .fixed_divider = 10,
|
|
|
-};
|
|
|
-
|
|
|
struct bcm2835_clock_data {
|
|
|
const char *name;
|
|
|
|
|
@@ -644,187 +444,14 @@ struct bcm2835_clock_data {
|
|
|
u32 frac_bits;
|
|
|
|
|
|
bool is_vpu_clock;
|
|
|
+ bool is_mash_clock;
|
|
|
};
|
|
|
|
|
|
-static const char *const bcm2835_clock_per_parents[] = {
|
|
|
- "gnd",
|
|
|
- "xosc",
|
|
|
- "testdebug0",
|
|
|
- "testdebug1",
|
|
|
- "plla_per",
|
|
|
- "pllc_per",
|
|
|
- "plld_per",
|
|
|
- "pllh_aux",
|
|
|
-};
|
|
|
-
|
|
|
-static const char *const bcm2835_clock_vpu_parents[] = {
|
|
|
- "gnd",
|
|
|
- "xosc",
|
|
|
- "testdebug0",
|
|
|
- "testdebug1",
|
|
|
- "plla_core",
|
|
|
- "pllc_core0",
|
|
|
- "plld_core",
|
|
|
- "pllh_aux",
|
|
|
- "pllc_core1",
|
|
|
- "pllc_core2",
|
|
|
-};
|
|
|
-
|
|
|
-static const char *const bcm2835_clock_osc_parents[] = {
|
|
|
- "gnd",
|
|
|
- "xosc",
|
|
|
- "testdebug0",
|
|
|
- "testdebug1"
|
|
|
-};
|
|
|
-
|
|
|
-/*
|
|
|
- * Used for a 1Mhz clock for the system clocksource, and also used by
|
|
|
- * the watchdog timer and the camera pulse generator.
|
|
|
- */
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_timer_data = {
|
|
|
- .name = "timer",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),
|
|
|
- .parents = bcm2835_clock_osc_parents,
|
|
|
- .ctl_reg = CM_TIMERCTL,
|
|
|
- .div_reg = CM_TIMERDIV,
|
|
|
- .int_bits = 6,
|
|
|
- .frac_bits = 12,
|
|
|
-};
|
|
|
-
|
|
|
-/* One Time Programmable Memory clock. Maximum 10Mhz. */
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_otp_data = {
|
|
|
- .name = "otp",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),
|
|
|
- .parents = bcm2835_clock_osc_parents,
|
|
|
- .ctl_reg = CM_OTPCTL,
|
|
|
- .div_reg = CM_OTPDIV,
|
|
|
- .int_bits = 4,
|
|
|
- .frac_bits = 0,
|
|
|
-};
|
|
|
-
|
|
|
-/*
|
|
|
- * 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.
|
|
|
- */
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_vpu_data = {
|
|
|
- .name = "vpu",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
|
|
|
- .parents = bcm2835_clock_vpu_parents,
|
|
|
- .ctl_reg = CM_VPUCTL,
|
|
|
- .div_reg = CM_VPUDIV,
|
|
|
- .int_bits = 12,
|
|
|
- .frac_bits = 8,
|
|
|
- .is_vpu_clock = true,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_v3d_data = {
|
|
|
- .name = "v3d",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
|
|
|
- .parents = bcm2835_clock_vpu_parents,
|
|
|
- .ctl_reg = CM_V3DCTL,
|
|
|
- .div_reg = CM_V3DDIV,
|
|
|
- .int_bits = 4,
|
|
|
- .frac_bits = 8,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_isp_data = {
|
|
|
- .name = "isp",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
|
|
|
- .parents = bcm2835_clock_vpu_parents,
|
|
|
- .ctl_reg = CM_ISPCTL,
|
|
|
- .div_reg = CM_ISPDIV,
|
|
|
- .int_bits = 4,
|
|
|
- .frac_bits = 8,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_h264_data = {
|
|
|
- .name = "h264",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
|
|
|
- .parents = bcm2835_clock_vpu_parents,
|
|
|
- .ctl_reg = CM_H264CTL,
|
|
|
- .div_reg = CM_H264DIV,
|
|
|
- .int_bits = 4,
|
|
|
- .frac_bits = 8,
|
|
|
-};
|
|
|
-
|
|
|
-/* TV encoder clock. Only operating frequency is 108Mhz. */
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_vec_data = {
|
|
|
- .name = "vec",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
|
|
|
- .parents = bcm2835_clock_per_parents,
|
|
|
- .ctl_reg = CM_VECCTL,
|
|
|
- .div_reg = CM_VECDIV,
|
|
|
- .int_bits = 4,
|
|
|
- .frac_bits = 0,
|
|
|
-};
|
|
|
-
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_uart_data = {
|
|
|
- .name = "uart",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
|
|
|
- .parents = bcm2835_clock_per_parents,
|
|
|
- .ctl_reg = CM_UARTCTL,
|
|
|
- .div_reg = CM_UARTDIV,
|
|
|
- .int_bits = 10,
|
|
|
- .frac_bits = 12,
|
|
|
-};
|
|
|
-
|
|
|
-/* HDMI state machine */
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_hsm_data = {
|
|
|
- .name = "hsm",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
|
|
|
- .parents = bcm2835_clock_per_parents,
|
|
|
- .ctl_reg = CM_HSMCTL,
|
|
|
- .div_reg = CM_HSMDIV,
|
|
|
- .int_bits = 4,
|
|
|
- .frac_bits = 8,
|
|
|
-};
|
|
|
-
|
|
|
-/*
|
|
|
- * Secondary SDRAM clock. Used for low-voltage modes when the PLL in
|
|
|
- * the SDRAM controller can't be used.
|
|
|
- */
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_sdram_data = {
|
|
|
- .name = "sdram",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents),
|
|
|
- .parents = bcm2835_clock_vpu_parents,
|
|
|
- .ctl_reg = CM_SDCCTL,
|
|
|
- .div_reg = CM_SDCDIV,
|
|
|
- .int_bits = 6,
|
|
|
- .frac_bits = 0,
|
|
|
-};
|
|
|
-
|
|
|
-/* Clock for the temperature sensor. Generally run at 2Mhz, max 5Mhz. */
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_tsens_data = {
|
|
|
- .name = "tsens",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents),
|
|
|
- .parents = bcm2835_clock_osc_parents,
|
|
|
- .ctl_reg = CM_TSENSCTL,
|
|
|
- .div_reg = CM_TSENSDIV,
|
|
|
- .int_bits = 5,
|
|
|
- .frac_bits = 0,
|
|
|
-};
|
|
|
-
|
|
|
-/* Arasan EMMC clock */
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_emmc_data = {
|
|
|
- .name = "emmc",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
|
|
|
- .parents = bcm2835_clock_per_parents,
|
|
|
- .ctl_reg = CM_EMMCCTL,
|
|
|
- .div_reg = CM_EMMCDIV,
|
|
|
- .int_bits = 4,
|
|
|
- .frac_bits = 8,
|
|
|
-};
|
|
|
+struct bcm2835_gate_data {
|
|
|
+ const char *name;
|
|
|
+ const char *parent;
|
|
|
|
|
|
-static const struct bcm2835_clock_data bcm2835_clock_pwm_data = {
|
|
|
- .name = "pwm",
|
|
|
- .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents),
|
|
|
- .parents = bcm2835_clock_per_parents,
|
|
|
- .ctl_reg = CM_PWMCTL,
|
|
|
- .div_reg = CM_PWMDIV,
|
|
|
- .int_bits = 12,
|
|
|
- .frac_bits = 12,
|
|
|
+ u32 ctl_reg;
|
|
|
};
|
|
|
|
|
|
struct bcm2835_pll {
|
|
@@ -910,8 +537,14 @@ static void bcm2835_pll_off(struct clk_hw *hw)
|
|
|
struct bcm2835_cprman *cprman = pll->cprman;
|
|
|
const struct bcm2835_pll_data *data = pll->data;
|
|
|
|
|
|
- cprman_write(cprman, data->cm_ctrl_reg, CM_PLL_ANARST);
|
|
|
- cprman_write(cprman, data->a2w_ctrl_reg, A2W_PLL_CTRL_PWRDN);
|
|
|
+ spin_lock(&cprman->regs_lock);
|
|
|
+ cprman_write(cprman, data->cm_ctrl_reg,
|
|
|
+ cprman_read(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)
|
|
@@ -1030,6 +663,36 @@ static int bcm2835_pll_set_rate(struct clk_hw *hw,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int 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_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL);
|
|
|
+ if (!regs)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ 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;
|
|
|
+
|
|
|
+ return 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,
|
|
@@ -1037,6 +700,7 @@ static const struct clk_ops bcm2835_pll_clk_ops = {
|
|
|
.recalc_rate = bcm2835_pll_get_rate,
|
|
|
.set_rate = bcm2835_pll_set_rate,
|
|
|
.round_rate = bcm2835_pll_round_rate,
|
|
|
+ .debug_init = bcm2835_pll_debug_init,
|
|
|
};
|
|
|
|
|
|
struct bcm2835_pll_divider {
|
|
@@ -1079,10 +743,12 @@ static void bcm2835_pll_divider_off(struct clk_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, A2W_PLL_CHANNEL_DISABLE);
|
|
|
+ spin_unlock(&cprman->regs_lock);
|
|
|
}
|
|
|
|
|
|
static int bcm2835_pll_divider_on(struct clk_hw *hw)
|
|
@@ -1091,12 +757,14 @@ static int bcm2835_pll_divider_on(struct clk_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;
|
|
|
}
|
|
@@ -1124,6 +792,26 @@ static int bcm2835_pll_divider_set_rate(struct clk_hw *hw,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+static int 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_kzalloc(cprman->dev, 7 * sizeof(*regs), GFP_KERNEL);
|
|
|
+ if (!regs)
|
|
|
+ return -ENOMEM;
|
|
|
+
|
|
|
+ regs[0].name = "cm";
|
|
|
+ regs[0].offset = data->cm_reg;
|
|
|
+ regs[1].name = "a2w";
|
|
|
+ regs[1].offset = data->a2w_reg;
|
|
|
+
|
|
|
+ return 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,
|
|
@@ -1131,6 +819,7 @@ static const struct clk_ops bcm2835_pll_divider_clk_ops = {
|
|
|
.recalc_rate = bcm2835_pll_divider_get_rate,
|
|
|
.set_rate = bcm2835_pll_divider_set_rate,
|
|
|
.round_rate = bcm2835_pll_divider_round_rate,
|
|
|
+ .debug_init = bcm2835_pll_divider_debug_init,
|
|
|
};
|
|
|
|
|
|
/*
|
|
@@ -1170,7 +859,7 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
|
|
|
GENMASK(CM_DIV_FRAC_BITS - data->frac_bits, 0) >> 1;
|
|
|
u64 temp = (u64)parent_rate << CM_DIV_FRAC_BITS;
|
|
|
u64 rem;
|
|
|
- u32 div;
|
|
|
+ u32 div, mindiv, maxdiv;
|
|
|
|
|
|
rem = do_div(temp, rate);
|
|
|
div = temp;
|
|
@@ -1180,10 +869,23 @@ static u32 bcm2835_clock_choose_div(struct clk_hw *hw,
|
|
|
div += unused_frac_mask + 1;
|
|
|
div &= ~unused_frac_mask;
|
|
|
|
|
|
- /* Clamp to the limits. */
|
|
|
- div = max(div, unused_frac_mask + 1);
|
|
|
- div = min_t(u32, div, GENMASK(data->int_bits + CM_DIV_FRAC_BITS - 1,
|
|
|
- CM_DIV_FRAC_BITS - data->frac_bits));
|
|
|
+ /* 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;
|
|
|
}
|
|
@@ -1277,14 +979,31 @@ static int bcm2835_clock_set_rate(struct clk_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, false);
|
|
|
+ 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 int bcm2835_clock_determine_rate(struct clk_hw *hw,
|
|
|
- struct clk_rate_request *req)
|
|
|
+ struct clk_rate_request *req)
|
|
|
{
|
|
|
struct bcm2835_clock *clock = bcm2835_clock_from_hw(hw);
|
|
|
struct clk_hw *parent, *best_parent = NULL;
|
|
@@ -1342,6 +1061,30 @@ static u8 bcm2835_clock_get_parent(struct clk_hw *hw)
|
|
|
return (src & CM_SRC_MASK) >> CM_SRC_SHIFT;
|
|
|
}
|
|
|
|
|
|
+static struct debugfs_reg32 bcm2835_debugfs_clock_reg32[] = {
|
|
|
+ {
|
|
|
+ .name = "ctl",
|
|
|
+ .offset = 0,
|
|
|
+ },
|
|
|
+ {
|
|
|
+ .name = "div",
|
|
|
+ .offset = 4,
|
|
|
+ },
|
|
|
+};
|
|
|
+
|
|
|
+static int 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;
|
|
|
+
|
|
|
+ return 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,
|
|
@@ -1352,6 +1095,7 @@ static const struct clk_ops bcm2835_clock_clk_ops = {
|
|
|
.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)
|
|
@@ -1370,6 +1114,7 @@ static const struct clk_ops bcm2835_vpu_clock_clk_ops = {
|
|
|
.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 *bcm2835_register_pll(struct bcm2835_cprman *cprman,
|
|
@@ -1418,7 +1163,7 @@ bcm2835_register_pll_divider(struct bcm2835_cprman *cprman,
|
|
|
|
|
|
memset(&init, 0, sizeof(init));
|
|
|
|
|
|
- init.parent_names = &data->source_pll->name;
|
|
|
+ init.parent_names = &data->source_pll;
|
|
|
init.num_parents = 1;
|
|
|
init.name = divider_name;
|
|
|
init.ops = &bcm2835_pll_divider_clk_ops;
|
|
@@ -1501,14 +1246,559 @@ static struct clk *bcm2835_register_clock(struct bcm2835_cprman *cprman,
|
|
|
return devm_clk_register(cprman->dev, &clock->hw);
|
|
|
}
|
|
|
|
|
|
+static struct clk *bcm2835_register_gate(struct bcm2835_cprman *cprman,
|
|
|
+ const struct bcm2835_gate_data *data)
|
|
|
+{
|
|
|
+ return clk_register_gate(cprman->dev, data->name, data->parent,
|
|
|
+ CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
|
|
|
+ cprman->regs + data->ctl_reg,
|
|
|
+ CM_GATE_BIT, 0, &cprman->regs_lock);
|
|
|
+}
|
|
|
+
|
|
|
+typedef struct clk *(*bcm2835_clk_register)(struct bcm2835_cprman *cprman,
|
|
|
+ const void *data);
|
|
|
+struct bcm2835_clk_desc {
|
|
|
+ bcm2835_clk_register clk_register;
|
|
|
+ const void *data;
|
|
|
+};
|
|
|
+
|
|
|
+/* assignment helper macros for different clock types */
|
|
|
+#define _REGISTER(f, ...) { .clk_register = (bcm2835_clk_register)f, \
|
|
|
+ .data = __VA_ARGS__ }
|
|
|
+#define REGISTER_PLL(...) _REGISTER(&bcm2835_register_pll, \
|
|
|
+ &(struct bcm2835_pll_data) \
|
|
|
+ {__VA_ARGS__})
|
|
|
+#define REGISTER_PLL_DIV(...) _REGISTER(&bcm2835_register_pll_divider, \
|
|
|
+ &(struct bcm2835_pll_divider_data) \
|
|
|
+ {__VA_ARGS__})
|
|
|
+#define REGISTER_CLK(...) _REGISTER(&bcm2835_register_clock, \
|
|
|
+ &(struct bcm2835_clock_data) \
|
|
|
+ {__VA_ARGS__})
|
|
|
+#define REGISTER_GATE(...) _REGISTER(&bcm2835_register_gate, \
|
|
|
+ &(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(...) REGISTER_CLK( \
|
|
|
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_osc_parents), \
|
|
|
+ .parents = bcm2835_clock_osc_parents, \
|
|
|
+ __VA_ARGS__)
|
|
|
+
|
|
|
+/* main peripherial 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(...) REGISTER_CLK( \
|
|
|
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_per_parents), \
|
|
|
+ .parents = bcm2835_clock_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(...) REGISTER_CLK( \
|
|
|
+ .num_mux_parents = ARRAY_SIZE(bcm2835_clock_vpu_parents), \
|
|
|
+ .parents = bcm2835_clock_vpu_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(
|
|
|
+ .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(
|
|
|
+ .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),
|
|
|
+ [BCM2835_PLLA_PER] = REGISTER_PLL_DIV(
|
|
|
+ .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),
|
|
|
+ [BCM2835_PLLA_DSI0] = REGISTER_PLL_DIV(
|
|
|
+ .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(
|
|
|
+ .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),
|
|
|
+
|
|
|
+ /* PLLB is used for the ARM's clock. */
|
|
|
+ [BCM2835_PLLB] = REGISTER_PLL(
|
|
|
+ .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),
|
|
|
+ [BCM2835_PLLB_ARM] = REGISTER_PLL_DIV(
|
|
|
+ .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),
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 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(
|
|
|
+ .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(
|
|
|
+ .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),
|
|
|
+ [BCM2835_PLLC_CORE1] = REGISTER_PLL_DIV(
|
|
|
+ .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),
|
|
|
+ [BCM2835_PLLC_CORE2] = REGISTER_PLL_DIV(
|
|
|
+ .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),
|
|
|
+ [BCM2835_PLLC_PER] = REGISTER_PLL_DIV(
|
|
|
+ .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),
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 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(
|
|
|
+ .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(
|
|
|
+ .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),
|
|
|
+ [BCM2835_PLLD_PER] = REGISTER_PLL_DIV(
|
|
|
+ .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),
|
|
|
+ [BCM2835_PLLD_DSI0] = REGISTER_PLL_DIV(
|
|
|
+ .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(
|
|
|
+ .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(
|
|
|
+ "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(
|
|
|
+ .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),
|
|
|
+ [BCM2835_PLLH_AUX] = REGISTER_PLL_DIV(
|
|
|
+ .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 = 10),
|
|
|
+ [BCM2835_PLLH_PIX] = REGISTER_PLL_DIV(
|
|
|
+ .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),
|
|
|
+
|
|
|
+ /* the clocks */
|
|
|
+
|
|
|
+ /* clocks with oscillator parent mux */
|
|
|
+
|
|
|
+ /* One Time Programmable Memory clock. Maximum 10Mhz. */
|
|
|
+ [BCM2835_CLOCK_OTP] = REGISTER_OSC_CLK(
|
|
|
+ .name = "otp",
|
|
|
+ .ctl_reg = CM_OTPCTL,
|
|
|
+ .div_reg = CM_OTPDIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 0),
|
|
|
+ /*
|
|
|
+ * 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(
|
|
|
+ .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(
|
|
|
+ .name = "tsens",
|
|
|
+ .ctl_reg = CM_TSENSCTL,
|
|
|
+ .div_reg = CM_TSENSDIV,
|
|
|
+ .int_bits = 5,
|
|
|
+ .frac_bits = 0),
|
|
|
+ [BCM2835_CLOCK_TEC] = REGISTER_OSC_CLK(
|
|
|
+ .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(
|
|
|
+ .name = "h264",
|
|
|
+ .ctl_reg = CM_H264CTL,
|
|
|
+ .div_reg = CM_H264DIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+ [BCM2835_CLOCK_ISP] = REGISTER_VPU_CLK(
|
|
|
+ .name = "isp",
|
|
|
+ .ctl_reg = CM_ISPCTL,
|
|
|
+ .div_reg = CM_ISPDIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+
|
|
|
+ /*
|
|
|
+ * 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(
|
|
|
+ .name = "sdram",
|
|
|
+ .ctl_reg = CM_SDCCTL,
|
|
|
+ .div_reg = CM_SDCDIV,
|
|
|
+ .int_bits = 6,
|
|
|
+ .frac_bits = 0),
|
|
|
+ [BCM2835_CLOCK_V3D] = REGISTER_VPU_CLK(
|
|
|
+ .name = "v3d",
|
|
|
+ .ctl_reg = CM_V3DCTL,
|
|
|
+ .div_reg = CM_V3DDIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+ /*
|
|
|
+ * 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(
|
|
|
+ .name = "vpu",
|
|
|
+ .ctl_reg = CM_VPUCTL,
|
|
|
+ .div_reg = CM_VPUDIV,
|
|
|
+ .int_bits = 12,
|
|
|
+ .frac_bits = 8,
|
|
|
+ .is_vpu_clock = true),
|
|
|
+
|
|
|
+ /* clocks with per parent mux */
|
|
|
+ [BCM2835_CLOCK_AVEO] = REGISTER_PER_CLK(
|
|
|
+ .name = "aveo",
|
|
|
+ .ctl_reg = CM_AVEOCTL,
|
|
|
+ .div_reg = CM_AVEODIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 0),
|
|
|
+ [BCM2835_CLOCK_CAM0] = REGISTER_PER_CLK(
|
|
|
+ .name = "cam0",
|
|
|
+ .ctl_reg = CM_CAM0CTL,
|
|
|
+ .div_reg = CM_CAM0DIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+ [BCM2835_CLOCK_CAM1] = REGISTER_PER_CLK(
|
|
|
+ .name = "cam1",
|
|
|
+ .ctl_reg = CM_CAM1CTL,
|
|
|
+ .div_reg = CM_CAM1DIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+ [BCM2835_CLOCK_DFT] = REGISTER_PER_CLK(
|
|
|
+ .name = "dft",
|
|
|
+ .ctl_reg = CM_DFTCTL,
|
|
|
+ .div_reg = CM_DFTDIV,
|
|
|
+ .int_bits = 5,
|
|
|
+ .frac_bits = 0),
|
|
|
+ [BCM2835_CLOCK_DPI] = REGISTER_PER_CLK(
|
|
|
+ .name = "dpi",
|
|
|
+ .ctl_reg = CM_DPICTL,
|
|
|
+ .div_reg = CM_DPIDIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+
|
|
|
+ /* Arasan EMMC clock */
|
|
|
+ [BCM2835_CLOCK_EMMC] = REGISTER_PER_CLK(
|
|
|
+ .name = "emmc",
|
|
|
+ .ctl_reg = CM_EMMCCTL,
|
|
|
+ .div_reg = CM_EMMCDIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+
|
|
|
+ /* General purpose (GPIO) clocks */
|
|
|
+ [BCM2835_CLOCK_GP0] = REGISTER_PER_CLK(
|
|
|
+ .name = "gp0",
|
|
|
+ .ctl_reg = CM_GP0CTL,
|
|
|
+ .div_reg = CM_GP0DIV,
|
|
|
+ .int_bits = 12,
|
|
|
+ .frac_bits = 12,
|
|
|
+ .is_mash_clock = true),
|
|
|
+ [BCM2835_CLOCK_GP1] = REGISTER_PER_CLK(
|
|
|
+ .name = "gp1",
|
|
|
+ .ctl_reg = CM_GP1CTL,
|
|
|
+ .div_reg = CM_GP1DIV,
|
|
|
+ .int_bits = 12,
|
|
|
+ .frac_bits = 12,
|
|
|
+ .is_mash_clock = true),
|
|
|
+ [BCM2835_CLOCK_GP2] = REGISTER_PER_CLK(
|
|
|
+ .name = "gp2",
|
|
|
+ .ctl_reg = CM_GP2CTL,
|
|
|
+ .div_reg = CM_GP2DIV,
|
|
|
+ .int_bits = 12,
|
|
|
+ .frac_bits = 12),
|
|
|
+
|
|
|
+ /* HDMI state machine */
|
|
|
+ [BCM2835_CLOCK_HSM] = REGISTER_PER_CLK(
|
|
|
+ .name = "hsm",
|
|
|
+ .ctl_reg = CM_HSMCTL,
|
|
|
+ .div_reg = CM_HSMDIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+ [BCM2835_CLOCK_PCM] = REGISTER_PER_CLK(
|
|
|
+ .name = "pcm",
|
|
|
+ .ctl_reg = CM_PCMCTL,
|
|
|
+ .div_reg = CM_PCMDIV,
|
|
|
+ .int_bits = 12,
|
|
|
+ .frac_bits = 12,
|
|
|
+ .is_mash_clock = true),
|
|
|
+ [BCM2835_CLOCK_PWM] = REGISTER_PER_CLK(
|
|
|
+ .name = "pwm",
|
|
|
+ .ctl_reg = CM_PWMCTL,
|
|
|
+ .div_reg = CM_PWMDIV,
|
|
|
+ .int_bits = 12,
|
|
|
+ .frac_bits = 12,
|
|
|
+ .is_mash_clock = true),
|
|
|
+ [BCM2835_CLOCK_SLIM] = REGISTER_PER_CLK(
|
|
|
+ .name = "slim",
|
|
|
+ .ctl_reg = CM_SLIMCTL,
|
|
|
+ .div_reg = CM_SLIMDIV,
|
|
|
+ .int_bits = 12,
|
|
|
+ .frac_bits = 12,
|
|
|
+ .is_mash_clock = true),
|
|
|
+ [BCM2835_CLOCK_SMI] = REGISTER_PER_CLK(
|
|
|
+ .name = "smi",
|
|
|
+ .ctl_reg = CM_SMICTL,
|
|
|
+ .div_reg = CM_SMIDIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+ [BCM2835_CLOCK_UART] = REGISTER_PER_CLK(
|
|
|
+ .name = "uart",
|
|
|
+ .ctl_reg = CM_UARTCTL,
|
|
|
+ .div_reg = CM_UARTDIV,
|
|
|
+ .int_bits = 10,
|
|
|
+ .frac_bits = 12),
|
|
|
+
|
|
|
+ /* TV encoder clock. Only operating frequency is 108Mhz. */
|
|
|
+ [BCM2835_CLOCK_VEC] = REGISTER_PER_CLK(
|
|
|
+ .name = "vec",
|
|
|
+ .ctl_reg = CM_VECCTL,
|
|
|
+ .div_reg = CM_VECDIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 0),
|
|
|
+
|
|
|
+ /* dsi clocks */
|
|
|
+ [BCM2835_CLOCK_DSI0E] = REGISTER_PER_CLK(
|
|
|
+ .name = "dsi0e",
|
|
|
+ .ctl_reg = CM_DSI0ECTL,
|
|
|
+ .div_reg = CM_DSI0EDIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+ [BCM2835_CLOCK_DSI1E] = REGISTER_PER_CLK(
|
|
|
+ .name = "dsi1e",
|
|
|
+ .ctl_reg = CM_DSI1ECTL,
|
|
|
+ .div_reg = CM_DSI1EDIV,
|
|
|
+ .int_bits = 4,
|
|
|
+ .frac_bits = 8),
|
|
|
+
|
|
|
+ /* 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(
|
|
|
+ .name = "peri_image",
|
|
|
+ .parent = "vpu",
|
|
|
+ .ctl_reg = CM_PERIICTL),
|
|
|
+};
|
|
|
+
|
|
|
static int bcm2835_clk_probe(struct platform_device *pdev)
|
|
|
{
|
|
|
struct device *dev = &pdev->dev;
|
|
|
struct clk **clks;
|
|
|
struct bcm2835_cprman *cprman;
|
|
|
struct resource *res;
|
|
|
+ const struct bcm2835_clk_desc *desc;
|
|
|
+ const size_t asize = ARRAY_SIZE(clk_desc_array);
|
|
|
+ size_t i;
|
|
|
|
|
|
- cprman = devm_kzalloc(dev, sizeof(*cprman), GFP_KERNEL);
|
|
|
+ cprman = devm_kzalloc(dev,
|
|
|
+ sizeof(*cprman) + asize * sizeof(*clks),
|
|
|
+ GFP_KERNEL);
|
|
|
if (!cprman)
|
|
|
return -ENOMEM;
|
|
|
|
|
@@ -1525,80 +1815,15 @@ static int bcm2835_clk_probe(struct platform_device *pdev)
|
|
|
|
|
|
platform_set_drvdata(pdev, cprman);
|
|
|
|
|
|
- cprman->onecell.clk_num = BCM2835_CLOCK_COUNT;
|
|
|
+ cprman->onecell.clk_num = asize;
|
|
|
cprman->onecell.clks = cprman->clks;
|
|
|
clks = cprman->clks;
|
|
|
|
|
|
- clks[BCM2835_PLLA] = bcm2835_register_pll(cprman, &bcm2835_plla_data);
|
|
|
- clks[BCM2835_PLLB] = bcm2835_register_pll(cprman, &bcm2835_pllb_data);
|
|
|
- clks[BCM2835_PLLC] = bcm2835_register_pll(cprman, &bcm2835_pllc_data);
|
|
|
- clks[BCM2835_PLLD] = bcm2835_register_pll(cprman, &bcm2835_plld_data);
|
|
|
- clks[BCM2835_PLLH] = bcm2835_register_pll(cprman, &bcm2835_pllh_data);
|
|
|
-
|
|
|
- clks[BCM2835_PLLA_CORE] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_plla_core_data);
|
|
|
- clks[BCM2835_PLLA_PER] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_plla_per_data);
|
|
|
- clks[BCM2835_PLLC_CORE0] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core0_data);
|
|
|
- clks[BCM2835_PLLC_CORE1] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core1_data);
|
|
|
- clks[BCM2835_PLLC_CORE2] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_pllc_core2_data);
|
|
|
- clks[BCM2835_PLLC_PER] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_pllc_per_data);
|
|
|
- clks[BCM2835_PLLD_CORE] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_plld_core_data);
|
|
|
- clks[BCM2835_PLLD_PER] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_plld_per_data);
|
|
|
- clks[BCM2835_PLLH_RCAL] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_pllh_rcal_data);
|
|
|
- clks[BCM2835_PLLH_AUX] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_pllh_aux_data);
|
|
|
- clks[BCM2835_PLLH_PIX] =
|
|
|
- bcm2835_register_pll_divider(cprman, &bcm2835_pllh_pix_data);
|
|
|
-
|
|
|
- clks[BCM2835_CLOCK_TIMER] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_timer_data);
|
|
|
- clks[BCM2835_CLOCK_OTP] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_otp_data);
|
|
|
- clks[BCM2835_CLOCK_TSENS] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_tsens_data);
|
|
|
- clks[BCM2835_CLOCK_VPU] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_vpu_data);
|
|
|
- clks[BCM2835_CLOCK_V3D] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data);
|
|
|
- clks[BCM2835_CLOCK_ISP] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_isp_data);
|
|
|
- clks[BCM2835_CLOCK_H264] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_h264_data);
|
|
|
- clks[BCM2835_CLOCK_V3D] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_v3d_data);
|
|
|
- clks[BCM2835_CLOCK_SDRAM] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_sdram_data);
|
|
|
- clks[BCM2835_CLOCK_UART] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_uart_data);
|
|
|
- clks[BCM2835_CLOCK_VEC] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_vec_data);
|
|
|
- clks[BCM2835_CLOCK_HSM] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_hsm_data);
|
|
|
- clks[BCM2835_CLOCK_EMMC] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_emmc_data);
|
|
|
-
|
|
|
- /*
|
|
|
- * 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.
|
|
|
- */
|
|
|
- clks[BCM2835_CLOCK_PERI_IMAGE] =
|
|
|
- clk_register_gate(dev, "peri_image", "vpu",
|
|
|
- CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE,
|
|
|
- cprman->regs + CM_PERIICTL, CM_GATE_BIT,
|
|
|
- 0, &cprman->regs_lock);
|
|
|
-
|
|
|
- clks[BCM2835_CLOCK_PWM] =
|
|
|
- bcm2835_register_clock(cprman, &bcm2835_clock_pwm_data);
|
|
|
+ for (i = 0; i < asize; i++) {
|
|
|
+ desc = &clk_desc_array[i];
|
|
|
+ if (desc->clk_register && desc->data)
|
|
|
+ clks[i] = desc->clk_register(cprman, desc->data);
|
|
|
+ }
|
|
|
|
|
|
return of_clk_add_provider(dev->of_node, of_clk_src_onecell_get,
|
|
|
&cprman->onecell);
|