diff options
| -rw-r--r-- | drivers/clk/tegra/clk-pll.c | 60 | ||||
| -rw-r--r-- | drivers/clk/tegra/clk.h | 32 |
2 files changed, 53 insertions, 39 deletions
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c index 85bec1dd87d8..3b778d3c828e 100644 --- a/drivers/clk/tegra/clk-pll.c +++ b/drivers/clk/tegra/clk-pll.c | |||
| @@ -134,15 +134,24 @@ | |||
| 134 | #define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p) | 134 | #define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p) |
| 135 | 135 | ||
| 136 | #define mask(w) ((1 << (w)) - 1) | 136 | #define mask(w) ((1 << (w)) - 1) |
| 137 | #define divm_mask(p) mask(p->divm_width) | 137 | #define divm_mask(p) mask(p->params->div_nmp->divm_width) |
| 138 | #define divn_mask(p) mask(p->divn_width) | 138 | #define divn_mask(p) mask(p->params->div_nmp->divn_width) |
| 139 | #define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \ | 139 | #define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK : \ |
| 140 | mask(p->divp_width)) | 140 | mask(p->params->div_nmp->divp_width)) |
| 141 | 141 | ||
| 142 | #define divm_max(p) (divm_mask(p)) | 142 | #define divm_max(p) (divm_mask(p)) |
| 143 | #define divn_max(p) (divn_mask(p)) | 143 | #define divn_max(p) (divn_mask(p)) |
| 144 | #define divp_max(p) (1 << (divp_mask(p))) | 144 | #define divp_max(p) (1 << (divp_mask(p))) |
| 145 | 145 | ||
| 146 | static struct div_nmp default_nmp = { | ||
| 147 | .divn_shift = PLL_BASE_DIVN_SHIFT, | ||
| 148 | .divn_width = PLL_BASE_DIVN_WIDTH, | ||
| 149 | .divm_shift = PLL_BASE_DIVM_SHIFT, | ||
| 150 | .divm_width = PLL_BASE_DIVM_WIDTH, | ||
| 151 | .divp_shift = PLL_BASE_DIVP_SHIFT, | ||
| 152 | .divp_width = PLL_BASE_DIVP_WIDTH, | ||
| 153 | }; | ||
| 154 | |||
| 146 | static void clk_pll_enable_lock(struct tegra_clk_pll *pll) | 155 | static void clk_pll_enable_lock(struct tegra_clk_pll *pll) |
| 147 | { | 156 | { |
| 148 | u32 val; | 157 | u32 val; |
| @@ -407,12 +416,12 @@ static void _update_pll_mnp(struct tegra_clk_pll *pll, | |||
| 407 | 416 | ||
| 408 | val = pll_readl_base(pll); | 417 | val = pll_readl_base(pll); |
| 409 | 418 | ||
| 410 | val &= ~((divm_mask(pll) << pll->divm_shift) | | 419 | val &= ~((divm_mask(pll) << pll->params->div_nmp->divm_shift) | |
| 411 | (divn_mask(pll) << pll->divn_shift) | | 420 | (divn_mask(pll) << pll->params->div_nmp->divn_shift) | |
| 412 | (divp_mask(pll) << pll->divp_shift)); | 421 | (divp_mask(pll) << pll->params->div_nmp->divp_shift)); |
| 413 | val |= ((cfg->m << pll->divm_shift) | | 422 | val |= ((cfg->m << pll->params->div_nmp->divm_shift) | |
| 414 | (cfg->n << pll->divn_shift) | | 423 | (cfg->n << pll->params->div_nmp->divn_shift) | |
| 415 | (cfg->p << pll->divp_shift)); | 424 | (cfg->p << pll->params->div_nmp->divp_shift)); |
| 416 | 425 | ||
| 417 | pll_writel_base(val, pll); | 426 | pll_writel_base(val, pll); |
| 418 | } | 427 | } |
| @@ -424,9 +433,9 @@ static void _get_pll_mnp(struct tegra_clk_pll *pll, | |||
| 424 | 433 | ||
| 425 | val = pll_readl_base(pll); | 434 | val = pll_readl_base(pll); |
| 426 | 435 | ||
| 427 | cfg->m = (val >> pll->divm_shift) & (divm_mask(pll)); | 436 | cfg->m = (val >> pll->params->div_nmp->divm_shift) & (divm_mask(pll)); |
| 428 | cfg->n = (val >> pll->divn_shift) & (divn_mask(pll)); | 437 | cfg->n = (val >> pll->params->div_nmp->divn_shift) & (divn_mask(pll)); |
| 429 | cfg->p = (val >> pll->divp_shift) & (divp_mask(pll)); | 438 | cfg->p = (val >> pll->params->div_nmp->divp_shift) & (divp_mask(pll)); |
| 430 | } | 439 | } |
| 431 | 440 | ||
| 432 | static void _update_pll_cpcon(struct tegra_clk_pll *pll, | 441 | static void _update_pll_cpcon(struct tegra_clk_pll *pll, |
| @@ -646,9 +655,9 @@ static int clk_plle_enable(struct clk_hw *hw) | |||
| 646 | val = pll_readl_base(pll); | 655 | val = pll_readl_base(pll); |
| 647 | val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); | 656 | val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); |
| 648 | val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); | 657 | val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); |
| 649 | val |= sel.m << pll->divm_shift; | 658 | val |= sel.m << pll->params->div_nmp->divm_shift; |
| 650 | val |= sel.n << pll->divn_shift; | 659 | val |= sel.n << pll->params->div_nmp->divn_shift; |
| 651 | val |= sel.p << pll->divp_shift; | 660 | val |= sel.p << pll->params->div_nmp->divp_shift; |
| 652 | val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; | 661 | val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; |
| 653 | pll_writel_base(val, pll); | 662 | pll_writel_base(val, pll); |
| 654 | } | 663 | } |
| @@ -679,9 +688,9 @@ static unsigned long clk_plle_recalc_rate(struct clk_hw *hw, | |||
| 679 | u32 divn = 0, divm = 0, divp = 0; | 688 | u32 divn = 0, divm = 0, divp = 0; |
| 680 | u64 rate = parent_rate; | 689 | u64 rate = parent_rate; |
| 681 | 690 | ||
| 682 | divp = (val >> pll->divp_shift) & (divp_mask(pll)); | 691 | divp = (val >> pll->params->div_nmp->divp_shift) & (divp_mask(pll)); |
| 683 | divn = (val >> pll->divn_shift) & (divn_mask(pll)); | 692 | divn = (val >> pll->params->div_nmp->divn_shift) & (divn_mask(pll)); |
| 684 | divm = (val >> pll->divm_shift) & (divm_mask(pll)); | 693 | divm = (val >> pll->params->div_nmp->divm_shift) & (divm_mask(pll)); |
| 685 | divm *= divp; | 694 | divm *= divp; |
| 686 | 695 | ||
| 687 | rate *= divn; | 696 | rate *= divn; |
| @@ -902,7 +911,8 @@ static int clk_pllm_set_rate(struct clk_hw *hw, unsigned long rate, | |||
| 902 | 911 | ||
| 903 | val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE); | 912 | val = readl_relaxed(pll->pmc + PMC_PLLM_WB0_OVERRIDE); |
| 904 | val &= ~(divn_mask(pll) | divm_mask(pll)); | 913 | val &= ~(divn_mask(pll) | divm_mask(pll)); |
| 905 | val |= (cfg.m << pll->divm_shift) | (cfg.n << pll->divn_shift); | 914 | val |= (cfg.m << pll->params->div_nmp->divm_shift) | |
| 915 | (cfg.n << pll->params->div_nmp->divn_shift); | ||
| 906 | writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE); | 916 | writel_relaxed(val, pll->pmc + PMC_PLLM_WB0_OVERRIDE); |
| 907 | } else | 917 | } else |
| 908 | _update_pll_mnp(pll, &cfg); | 918 | _update_pll_mnp(pll, &cfg); |
| @@ -1180,8 +1190,8 @@ static int clk_plle_tegra114_enable(struct clk_hw *hw) | |||
| 1180 | val = pll_readl_base(pll); | 1190 | val = pll_readl_base(pll); |
| 1181 | val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); | 1191 | val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll)); |
| 1182 | val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); | 1192 | val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT); |
| 1183 | val |= sel.m << pll->divm_shift; | 1193 | val |= sel.m << pll->params->div_nmp->divm_shift; |
| 1184 | val |= sel.n << pll->divn_shift; | 1194 | val |= sel.n << pll->params->div_nmp->divn_shift; |
| 1185 | val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; | 1195 | val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT; |
| 1186 | pll_writel_base(val, pll); | 1196 | pll_writel_base(val, pll); |
| 1187 | udelay(1); | 1197 | udelay(1); |
| @@ -1242,12 +1252,8 @@ static struct tegra_clk_pll *_tegra_init_pll(void __iomem *clk_base, | |||
| 1242 | pll->flags = pll_flags; | 1252 | pll->flags = pll_flags; |
| 1243 | pll->lock = lock; | 1253 | pll->lock = lock; |
| 1244 | 1254 | ||
| 1245 | pll->divp_shift = PLL_BASE_DIVP_SHIFT; | 1255 | if (!pll_params->div_nmp) |
| 1246 | pll->divp_width = PLL_BASE_DIVP_WIDTH; | 1256 | pll_params->div_nmp = &default_nmp; |
| 1247 | pll->divn_shift = PLL_BASE_DIVN_SHIFT; | ||
| 1248 | pll->divn_width = PLL_BASE_DIVN_WIDTH; | ||
| 1249 | pll->divm_shift = PLL_BASE_DIVM_SHIFT; | ||
| 1250 | pll->divm_width = PLL_BASE_DIVM_WIDTH; | ||
| 1251 | 1257 | ||
| 1252 | return pll; | 1258 | return pll; |
| 1253 | } | 1259 | } |
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h index 11278a80e63e..d70eb2d2957f 100644 --- a/drivers/clk/tegra/clk.h +++ b/drivers/clk/tegra/clk.h | |||
| @@ -128,6 +128,25 @@ struct pdiv_map { | |||
| 128 | }; | 128 | }; |
| 129 | 129 | ||
| 130 | /** | 130 | /** |
| 131 | * struct div_nmp - offset and width of m,n and p fields | ||
| 132 | * | ||
| 133 | * @divn_shift: shift to the feedback divider bit field | ||
| 134 | * @divn_width: width of the feedback divider bit field | ||
| 135 | * @divm_shift: shift to the input divider bit field | ||
| 136 | * @divm_width: width of the input divider bit field | ||
| 137 | * @divp_shift: shift to the post divider bit field | ||
| 138 | * @divp_width: width of the post divider bit field | ||
| 139 | */ | ||
| 140 | struct div_nmp { | ||
| 141 | u8 divn_shift; | ||
| 142 | u8 divn_width; | ||
| 143 | u8 divm_shift; | ||
| 144 | u8 divm_width; | ||
| 145 | u8 divp_shift; | ||
| 146 | u8 divp_width; | ||
| 147 | }; | ||
| 148 | |||
| 149 | /** | ||
| 131 | * struct clk_pll_params - PLL parameters | 150 | * struct clk_pll_params - PLL parameters |
| 132 | * | 151 | * |
| 133 | * @input_min: Minimum input frequency | 152 | * @input_min: Minimum input frequency |
| @@ -166,6 +185,7 @@ struct tegra_clk_pll_params { | |||
| 166 | int lock_delay; | 185 | int lock_delay; |
| 167 | int max_p; | 186 | int max_p; |
| 168 | struct pdiv_map *pdiv_tohw; | 187 | struct pdiv_map *pdiv_tohw; |
| 188 | struct div_nmp *div_nmp; | ||
| 169 | }; | 189 | }; |
| 170 | 190 | ||
| 171 | /** | 191 | /** |
| @@ -179,12 +199,6 @@ struct tegra_clk_pll_params { | |||
| 179 | * @flags: PLL flags | 199 | * @flags: PLL flags |
| 180 | * @fixed_rate: PLL rate if it is fixed | 200 | * @fixed_rate: PLL rate if it is fixed |
| 181 | * @lock: register lock | 201 | * @lock: register lock |
| 182 | * @divn_shift: shift to the feedback divider bit field | ||
| 183 | * @divn_width: width of the feedback divider bit field | ||
| 184 | * @divm_shift: shift to the input divider bit field | ||
| 185 | * @divm_width: width of the input divider bit field | ||
