Loading Documentation/devicetree/bindings/arm/msm/clock-controller-v2.txt +71 −0 Original line number Diff line number Diff line Loading @@ -654,3 +654,74 @@ pcie0_reset_clk: pcie0_reset_clk { compatible = "qcom,reset-clk"; qcom,base-offset = <GCC_PCIE0_BCR>; }; ***************************************************************************** "qcom,alpha-pll" Alpha PLL clocks are a type of PLL which produces an output rate of output = input * ( L + a * 2 ^-40). Required Properties: - compatible: "qcom,alpha-pll-20t", "qcom,alpha-pll-20p" - qcom,base-offset: Register offset from top level clock controller. Recommended Properties: - qcom,clk-fmax: See "General Optional Properties" - qcom,supply-group: See "General Optional Properties" - qcom,parent: See "General Optional Properties" Optional Properties: - qcom,output-enable: Masked PLL output setting. - qcom,post-div-config: Masked post divider setting. cci_pll: cci_pll { compatible = "qcom,alpha-pll-20p"; qcom,base-offset = <CCI_PLL_MODE>; qcom,parent = <&ao_xo>; qcom,supply-group = <&mmss_vdd_dig>; qcom,clk-fmax = <FMAX_LOW 1000000000>; qcom,output-enable = <0x9>; qcom,post-div-config = <0x100>; }; ***************************************************************************** "qcom,fixed-alpha-pll" This particular instance of alpha-pll allows setting a rate once at bootup, after which the rate is immutable. Required Properties: - compatible: "qcom,fixed-alpha-pll-20t", "qcom,fixed-alpha-pll-20p" - qcom,base-offset: Register offset from top level clock controller. - qcom,pll-config-rate: Indicates that the pll should be configured to a fixed rate at initialization. - qcom,output-enable: Masked PLL output setting. Recommended Properties: - qcom,clk-fmax: See "General Optional Properties" - qcom,supply-group: See "General Optional Properties" - qcom,parent: See "General Optional Properties" Optional Properties: - qcom,fsm-en-bit: Indicates that the pll is votable; the timing between the steps to enable the pll is handled by a fsm. - qcom,fsm-en-offset: Register offset for the vote register. If fsm-en-bit is defined, this property is required. - qcom,post-div-config: Masked post divider setting. mmpll8: mmpll8 { compatible = "qcom,fixed-alpha-pll-20p"; qcom,base-offset = <MMSS_MMPLL8_MODE>; qcom,pll-config-rate = <1050000000>; qcom,parent = <&mmsscc_xo>; qcom,supply-group = <&mmss_vdd_dig>; qcom,clk-fmax = <FMAX_LOWER 650000000>, <FMAX_LOW 650000000>, <FMAX_NOM 1300000000>, <FMAX_TURBO 1300000000>; qcom,output-enable = <0x1>; }; drivers/clk/qcom/clock-alpha-pll.c +140 −0 Original line number Diff line number Diff line Loading @@ -12,12 +12,15 @@ * */ #define pr_fmt(fmt) "%s: " fmt, __func__ #include <linux/kernel.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> #include <soc/qcom/clock-alpha-pll.h> #include <soc/qcom/msm-clock-controller.h> #include "clock.h" Loading Loading @@ -454,3 +457,140 @@ struct clk_ops clk_ops_fixed_alpha_pll = { .handoff = alpha_pll_handoff, }; static struct alpha_pll_masks masks_20nm_p = { .lock_mask = BIT(31), .active_mask = BIT(30), .vco_mask = BM(21, 20) >> 20, .vco_shift = 20, .alpha_en_mask = BIT(24), .output_mask = 0xF, .post_div_mask = 0xF00, }; static struct alpha_pll_vco_tbl vco_20nm_p[] = { VCO(3, 250000000, 500000000), VCO(2, 500000000, 1000000000), VCO(1, 1000000000, 1500000000), VCO(0, 1500000000, 2000000000), }; static struct alpha_pll_masks masks_20nm_t = { .lock_mask = BIT(31), .alpha_en_mask = BIT(24), .output_mask = 0xf, }; static struct alpha_pll_vco_tbl vco_20nm_t[] = { VCO(0, 500000000, 1250000000), }; static struct alpha_pll_clk *alpha_pll_dt_parser(struct device *dev, struct device_node *np) { struct alpha_pll_clk *pll; struct msmclk_data *drv; pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); if (!pll) { dt_err(np, "memory alloc failure\n"); return ERR_PTR(-ENOMEM); } if (of_property_read_u32(np, "qcom,base-offset", &pll->offset)) { dt_err(np, "missing qcom,base-offset\n"); return ERR_PTR(-EINVAL); } /* Optional property */ of_property_read_u32(np, "qcom,post-div-config", &pll->post_div_config); pll->masks = devm_kzalloc(dev, sizeof(*pll->masks), GFP_KERNEL); if (!pll->masks) { dt_err(np, "memory alloc failure\n"); return ERR_PTR(-ENOMEM); } if (of_device_is_compatible(np, "qcom,fixed-alpha-pll-20p") || of_device_is_compatible(np, "qcom,alpha-pll-20p")) { *pll->masks = masks_20nm_p; pll->vco_tbl = vco_20nm_p; pll->num_vco = ARRAY_SIZE(vco_20nm_p); } else if (of_device_is_compatible(np, "qcom,fixed-alpha-pll-20t") || of_device_is_compatible(np, "qcom,alpha-pll-20t")) { *pll->masks = masks_20nm_t; pll->vco_tbl = vco_20nm_t; pll->num_vco = ARRAY_SIZE(vco_20nm_t); } else { dt_err(np, "unexpected compatible string\n"); return ERR_PTR(-EINVAL); } drv = msmclk_parse_phandle(dev, np->parent->phandle); if (IS_ERR_OR_NULL(drv)) return ERR_CAST(drv); pll->base = &drv->base; return pll; } static void *variable_rate_alpha_pll_dt_parser(struct device *dev, struct device_node *np) { struct alpha_pll_clk *pll; pll = alpha_pll_dt_parser(dev, np); if (IS_ERR(pll)) return pll; /* Optional Property */ of_property_read_u32(np, "qcom,output-enable", &pll->enable_config); pll->c.ops = &clk_ops_alpha_pll; return msmclk_generic_clk_init(dev, np, &pll->c); } static void *fixed_rate_alpha_pll_dt_parser(struct device *dev, struct device_node *np) { struct alpha_pll_clk *pll; int rc; u32 val; pll = alpha_pll_dt_parser(dev, np); if (IS_ERR(pll)) return pll; rc = of_property_read_u32(np, "qcom,pll-config-rate", &val); if (rc) { dt_err(np, "missing qcom,pll-config-rate\n"); return ERR_PTR(-EINVAL); } pll->c.rate = val; rc = of_property_read_u32(np, "qcom,output-enable", &pll->enable_config); if (rc) { dt_err(np, "missing qcom,output-enable\n"); return ERR_PTR(-EINVAL); } /* Optional Property */ rc = of_property_read_u32(np, "qcom,fsm-en-bit", &val); if (!rc) { rc = of_property_read_u32(np, "qcom,fsm-en-offset", &pll->fsm_reg_offset); if (rc) { dt_err(np, "missing qcom,fsm-en-offset\n"); return ERR_PTR(-EINVAL); } pll->fsm_en_mask = BIT(val); } pll->c.ops = &clk_ops_fixed_alpha_pll; return msmclk_generic_clk_init(dev, np, &pll->c); } MSMCLK_PARSER(fixed_rate_alpha_pll_dt_parser, "qcom,fixed-alpha-pll-20p", 0); MSMCLK_PARSER(fixed_rate_alpha_pll_dt_parser, "qcom,fixed-alpha-pll-20t", 1); MSMCLK_PARSER(variable_rate_alpha_pll_dt_parser, "qcom,alpha-pll-20p", 0); MSMCLK_PARSER(variable_rate_alpha_pll_dt_parser, "qcom,alpha-pll-20t", 1); include/soc/qcom/clock-alpha-pll.h +3 −3 Original line number Diff line number Diff line Loading @@ -44,11 +44,11 @@ struct alpha_pll_vco_tbl { struct alpha_pll_clk { struct alpha_pll_masks *masks; void *const __iomem *base; const u32 offset; u32 offset; /* if fsm_en_mask is set, config PLL to FSM mode */ const u32 fsm_reg_offset; const u32 fsm_en_mask; u32 fsm_reg_offset; u32 fsm_en_mask; u32 enable_config; /* bitmask of outputs to be enabled */ u32 post_div_config; /* masked post divider setting */ Loading Loading
Documentation/devicetree/bindings/arm/msm/clock-controller-v2.txt +71 −0 Original line number Diff line number Diff line Loading @@ -654,3 +654,74 @@ pcie0_reset_clk: pcie0_reset_clk { compatible = "qcom,reset-clk"; qcom,base-offset = <GCC_PCIE0_BCR>; }; ***************************************************************************** "qcom,alpha-pll" Alpha PLL clocks are a type of PLL which produces an output rate of output = input * ( L + a * 2 ^-40). Required Properties: - compatible: "qcom,alpha-pll-20t", "qcom,alpha-pll-20p" - qcom,base-offset: Register offset from top level clock controller. Recommended Properties: - qcom,clk-fmax: See "General Optional Properties" - qcom,supply-group: See "General Optional Properties" - qcom,parent: See "General Optional Properties" Optional Properties: - qcom,output-enable: Masked PLL output setting. - qcom,post-div-config: Masked post divider setting. cci_pll: cci_pll { compatible = "qcom,alpha-pll-20p"; qcom,base-offset = <CCI_PLL_MODE>; qcom,parent = <&ao_xo>; qcom,supply-group = <&mmss_vdd_dig>; qcom,clk-fmax = <FMAX_LOW 1000000000>; qcom,output-enable = <0x9>; qcom,post-div-config = <0x100>; }; ***************************************************************************** "qcom,fixed-alpha-pll" This particular instance of alpha-pll allows setting a rate once at bootup, after which the rate is immutable. Required Properties: - compatible: "qcom,fixed-alpha-pll-20t", "qcom,fixed-alpha-pll-20p" - qcom,base-offset: Register offset from top level clock controller. - qcom,pll-config-rate: Indicates that the pll should be configured to a fixed rate at initialization. - qcom,output-enable: Masked PLL output setting. Recommended Properties: - qcom,clk-fmax: See "General Optional Properties" - qcom,supply-group: See "General Optional Properties" - qcom,parent: See "General Optional Properties" Optional Properties: - qcom,fsm-en-bit: Indicates that the pll is votable; the timing between the steps to enable the pll is handled by a fsm. - qcom,fsm-en-offset: Register offset for the vote register. If fsm-en-bit is defined, this property is required. - qcom,post-div-config: Masked post divider setting. mmpll8: mmpll8 { compatible = "qcom,fixed-alpha-pll-20p"; qcom,base-offset = <MMSS_MMPLL8_MODE>; qcom,pll-config-rate = <1050000000>; qcom,parent = <&mmsscc_xo>; qcom,supply-group = <&mmss_vdd_dig>; qcom,clk-fmax = <FMAX_LOWER 650000000>, <FMAX_LOW 650000000>, <FMAX_NOM 1300000000>, <FMAX_TURBO 1300000000>; qcom,output-enable = <0x1>; };
drivers/clk/qcom/clock-alpha-pll.c +140 −0 Original line number Diff line number Diff line Loading @@ -12,12 +12,15 @@ * */ #define pr_fmt(fmt) "%s: " fmt, __func__ #include <linux/kernel.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/clk.h> #include <linux/io.h> #include <soc/qcom/clock-alpha-pll.h> #include <soc/qcom/msm-clock-controller.h> #include "clock.h" Loading Loading @@ -454,3 +457,140 @@ struct clk_ops clk_ops_fixed_alpha_pll = { .handoff = alpha_pll_handoff, }; static struct alpha_pll_masks masks_20nm_p = { .lock_mask = BIT(31), .active_mask = BIT(30), .vco_mask = BM(21, 20) >> 20, .vco_shift = 20, .alpha_en_mask = BIT(24), .output_mask = 0xF, .post_div_mask = 0xF00, }; static struct alpha_pll_vco_tbl vco_20nm_p[] = { VCO(3, 250000000, 500000000), VCO(2, 500000000, 1000000000), VCO(1, 1000000000, 1500000000), VCO(0, 1500000000, 2000000000), }; static struct alpha_pll_masks masks_20nm_t = { .lock_mask = BIT(31), .alpha_en_mask = BIT(24), .output_mask = 0xf, }; static struct alpha_pll_vco_tbl vco_20nm_t[] = { VCO(0, 500000000, 1250000000), }; static struct alpha_pll_clk *alpha_pll_dt_parser(struct device *dev, struct device_node *np) { struct alpha_pll_clk *pll; struct msmclk_data *drv; pll = devm_kzalloc(dev, sizeof(*pll), GFP_KERNEL); if (!pll) { dt_err(np, "memory alloc failure\n"); return ERR_PTR(-ENOMEM); } if (of_property_read_u32(np, "qcom,base-offset", &pll->offset)) { dt_err(np, "missing qcom,base-offset\n"); return ERR_PTR(-EINVAL); } /* Optional property */ of_property_read_u32(np, "qcom,post-div-config", &pll->post_div_config); pll->masks = devm_kzalloc(dev, sizeof(*pll->masks), GFP_KERNEL); if (!pll->masks) { dt_err(np, "memory alloc failure\n"); return ERR_PTR(-ENOMEM); } if (of_device_is_compatible(np, "qcom,fixed-alpha-pll-20p") || of_device_is_compatible(np, "qcom,alpha-pll-20p")) { *pll->masks = masks_20nm_p; pll->vco_tbl = vco_20nm_p; pll->num_vco = ARRAY_SIZE(vco_20nm_p); } else if (of_device_is_compatible(np, "qcom,fixed-alpha-pll-20t") || of_device_is_compatible(np, "qcom,alpha-pll-20t")) { *pll->masks = masks_20nm_t; pll->vco_tbl = vco_20nm_t; pll->num_vco = ARRAY_SIZE(vco_20nm_t); } else { dt_err(np, "unexpected compatible string\n"); return ERR_PTR(-EINVAL); } drv = msmclk_parse_phandle(dev, np->parent->phandle); if (IS_ERR_OR_NULL(drv)) return ERR_CAST(drv); pll->base = &drv->base; return pll; } static void *variable_rate_alpha_pll_dt_parser(struct device *dev, struct device_node *np) { struct alpha_pll_clk *pll; pll = alpha_pll_dt_parser(dev, np); if (IS_ERR(pll)) return pll; /* Optional Property */ of_property_read_u32(np, "qcom,output-enable", &pll->enable_config); pll->c.ops = &clk_ops_alpha_pll; return msmclk_generic_clk_init(dev, np, &pll->c); } static void *fixed_rate_alpha_pll_dt_parser(struct device *dev, struct device_node *np) { struct alpha_pll_clk *pll; int rc; u32 val; pll = alpha_pll_dt_parser(dev, np); if (IS_ERR(pll)) return pll; rc = of_property_read_u32(np, "qcom,pll-config-rate", &val); if (rc) { dt_err(np, "missing qcom,pll-config-rate\n"); return ERR_PTR(-EINVAL); } pll->c.rate = val; rc = of_property_read_u32(np, "qcom,output-enable", &pll->enable_config); if (rc) { dt_err(np, "missing qcom,output-enable\n"); return ERR_PTR(-EINVAL); } /* Optional Property */ rc = of_property_read_u32(np, "qcom,fsm-en-bit", &val); if (!rc) { rc = of_property_read_u32(np, "qcom,fsm-en-offset", &pll->fsm_reg_offset); if (rc) { dt_err(np, "missing qcom,fsm-en-offset\n"); return ERR_PTR(-EINVAL); } pll->fsm_en_mask = BIT(val); } pll->c.ops = &clk_ops_fixed_alpha_pll; return msmclk_generic_clk_init(dev, np, &pll->c); } MSMCLK_PARSER(fixed_rate_alpha_pll_dt_parser, "qcom,fixed-alpha-pll-20p", 0); MSMCLK_PARSER(fixed_rate_alpha_pll_dt_parser, "qcom,fixed-alpha-pll-20t", 1); MSMCLK_PARSER(variable_rate_alpha_pll_dt_parser, "qcom,alpha-pll-20p", 0); MSMCLK_PARSER(variable_rate_alpha_pll_dt_parser, "qcom,alpha-pll-20t", 1);
include/soc/qcom/clock-alpha-pll.h +3 −3 Original line number Diff line number Diff line Loading @@ -44,11 +44,11 @@ struct alpha_pll_vco_tbl { struct alpha_pll_clk { struct alpha_pll_masks *masks; void *const __iomem *base; const u32 offset; u32 offset; /* if fsm_en_mask is set, config PLL to FSM mode */ const u32 fsm_reg_offset; const u32 fsm_en_mask; u32 fsm_reg_offset; u32 fsm_en_mask; u32 enable_config; /* bitmask of outputs to be enabled */ u32 post_div_config; /* masked post divider setting */ Loading