1682e09ffSMasahiro Yamada /* 2682e09ffSMasahiro Yamada * Copyright (C) 2016 Socionext Inc. 3682e09ffSMasahiro Yamada * Author: Masahiro Yamada <yamada.masahiro@socionext.com> 4682e09ffSMasahiro Yamada * 5682e09ffSMasahiro Yamada * SPDX-License-Identifier: GPL-2.0+ 6682e09ffSMasahiro Yamada */ 7682e09ffSMasahiro Yamada 8*7f8e7539SMasahiro Yamada #include <linux/bitfield.h> 9682e09ffSMasahiro Yamada #include <linux/bitops.h> 10d9a70368SMasahiro Yamada #include <linux/delay.h> 11f2ce50b2SMasahiro Yamada #include <linux/kernel.h> 12d9a70368SMasahiro Yamada #include <linux/errno.h> 13682e09ffSMasahiro Yamada #include <linux/io.h> 14682e09ffSMasahiro Yamada #include <linux/sizes.h> 15682e09ffSMasahiro Yamada 16682e09ffSMasahiro Yamada #include "pll.h" 17682e09ffSMasahiro Yamada 18682e09ffSMasahiro Yamada /* PLL type: SSC */ 19682e09ffSMasahiro Yamada #define SC_PLLCTRL_SSC_DK_MASK GENMASK(14, 0) 20682e09ffSMasahiro Yamada #define SC_PLLCTRL_SSC_EN BIT(31) 21682e09ffSMasahiro Yamada #define SC_PLLCTRL2_NRSTDS BIT(28) 22682e09ffSMasahiro Yamada #define SC_PLLCTRL2_SSC_JK_MASK GENMASK(26, 0) 23bc647958SMasahiro Yamada #define SC_PLLCTRL3_REGI_MASK GENMASK(19, 16) 24682e09ffSMasahiro Yamada 25682e09ffSMasahiro Yamada /* PLL type: VPLL27 */ 26682e09ffSMasahiro Yamada #define SC_VPLL27CTRL_WP BIT(0) 27682e09ffSMasahiro Yamada #define SC_VPLL27CTRL3_K_LD BIT(28) 28682e09ffSMasahiro Yamada 29682e09ffSMasahiro Yamada /* PLL type: DSPLL */ 30682e09ffSMasahiro Yamada #define SC_DSPLLCTRL2_K_LD BIT(28) 31682e09ffSMasahiro Yamada 32682e09ffSMasahiro Yamada int uniphier_ld20_sscpll_init(unsigned long reg_base, unsigned int freq, 33682e09ffSMasahiro Yamada unsigned int ssc_rate, unsigned int divn) 34682e09ffSMasahiro Yamada { 35682e09ffSMasahiro Yamada void __iomem *base; 36682e09ffSMasahiro Yamada u32 tmp; 37682e09ffSMasahiro Yamada 38682e09ffSMasahiro Yamada base = ioremap(reg_base, SZ_16); 39682e09ffSMasahiro Yamada if (!base) 40682e09ffSMasahiro Yamada return -ENOMEM; 41682e09ffSMasahiro Yamada 42682e09ffSMasahiro Yamada if (freq != UNIPHIER_PLL_FREQ_DEFAULT) { 43682e09ffSMasahiro Yamada tmp = readl(base); /* SSCPLLCTRL */ 44682e09ffSMasahiro Yamada tmp &= ~SC_PLLCTRL_SSC_DK_MASK; 45*7f8e7539SMasahiro Yamada tmp |= FIELD_PREP(SC_PLLCTRL_SSC_DK_MASK, 46*7f8e7539SMasahiro Yamada DIV_ROUND_CLOSEST(487UL * freq * ssc_rate, 47*7f8e7539SMasahiro Yamada divn * 512)); 48682e09ffSMasahiro Yamada writel(tmp, base); 49682e09ffSMasahiro Yamada 50682e09ffSMasahiro Yamada tmp = readl(base + 4); 51682e09ffSMasahiro Yamada tmp &= ~SC_PLLCTRL2_SSC_JK_MASK; 52*7f8e7539SMasahiro Yamada tmp |= FIELD_PREP(SC_PLLCTRL2_SSC_JK_MASK, 53*7f8e7539SMasahiro Yamada DIV_ROUND_CLOSEST(21431887UL * freq, 54*7f8e7539SMasahiro Yamada divn * 512)); 55c30c44e7SDai Okamura writel(tmp, base + 4); 56682e09ffSMasahiro Yamada 57682e09ffSMasahiro Yamada udelay(50); 58682e09ffSMasahiro Yamada } 59682e09ffSMasahiro Yamada 60682e09ffSMasahiro Yamada tmp = readl(base + 4); /* SSCPLLCTRL2 */ 61682e09ffSMasahiro Yamada tmp |= SC_PLLCTRL2_NRSTDS; 62682e09ffSMasahiro Yamada writel(tmp, base + 4); 63682e09ffSMasahiro Yamada 64682e09ffSMasahiro Yamada iounmap(base); 65682e09ffSMasahiro Yamada 66682e09ffSMasahiro Yamada return 0; 67682e09ffSMasahiro Yamada } 68682e09ffSMasahiro Yamada 69682e09ffSMasahiro Yamada int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base) 70682e09ffSMasahiro Yamada { 71682e09ffSMasahiro Yamada void __iomem *base; 72682e09ffSMasahiro Yamada u32 tmp; 73682e09ffSMasahiro Yamada 74682e09ffSMasahiro Yamada base = ioremap(reg_base, SZ_16); 75682e09ffSMasahiro Yamada if (!base) 76682e09ffSMasahiro Yamada return -ENOMEM; 77682e09ffSMasahiro Yamada 78682e09ffSMasahiro Yamada tmp = readl(base); /* SSCPLLCTRL */ 79682e09ffSMasahiro Yamada tmp |= SC_PLLCTRL_SSC_EN; 80682e09ffSMasahiro Yamada writel(tmp, base); 81682e09ffSMasahiro Yamada 82682e09ffSMasahiro Yamada iounmap(base); 83682e09ffSMasahiro Yamada 84682e09ffSMasahiro Yamada return 0; 85682e09ffSMasahiro Yamada } 86682e09ffSMasahiro Yamada 87bc647958SMasahiro Yamada int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi) 88bc647958SMasahiro Yamada { 89bc647958SMasahiro Yamada void __iomem *base; 90bc647958SMasahiro Yamada u32 tmp; 91bc647958SMasahiro Yamada 92bc647958SMasahiro Yamada base = ioremap(reg_base, SZ_16); 93bc647958SMasahiro Yamada if (!base) 94bc647958SMasahiro Yamada return -ENOMEM; 95bc647958SMasahiro Yamada 964013bbb1SDai Okamura tmp = readl(base + 8); /* SSCPLLCTRL3 */ 97bc647958SMasahiro Yamada tmp &= ~SC_PLLCTRL3_REGI_MASK; 98*7f8e7539SMasahiro Yamada tmp |= FIELD_PREP(SC_PLLCTRL3_REGI_MASK, regi); 99bc647958SMasahiro Yamada writel(tmp, base + 8); 100bc647958SMasahiro Yamada 101bc647958SMasahiro Yamada iounmap(base); 102bc647958SMasahiro Yamada 103bc647958SMasahiro Yamada return 0; 104bc647958SMasahiro Yamada } 105bc647958SMasahiro Yamada 106682e09ffSMasahiro Yamada int uniphier_ld20_vpll27_init(unsigned long reg_base) 107682e09ffSMasahiro Yamada { 108682e09ffSMasahiro Yamada void __iomem *base; 109682e09ffSMasahiro Yamada u32 tmp; 110682e09ffSMasahiro Yamada 111682e09ffSMasahiro Yamada base = ioremap(reg_base, SZ_16); 112682e09ffSMasahiro Yamada if (!base) 113682e09ffSMasahiro Yamada return -ENOMEM; 114682e09ffSMasahiro Yamada 115682e09ffSMasahiro Yamada tmp = readl(base); /* VPLL27CTRL */ 116682e09ffSMasahiro Yamada tmp |= SC_VPLL27CTRL_WP; /* write protect off */ 117682e09ffSMasahiro Yamada writel(tmp, base); 118682e09ffSMasahiro Yamada 119682e09ffSMasahiro Yamada tmp = readl(base + 8); /* VPLL27CTRL3 */ 120682e09ffSMasahiro Yamada tmp |= SC_VPLL27CTRL3_K_LD; 121682e09ffSMasahiro Yamada writel(tmp, base + 8); 122682e09ffSMasahiro Yamada 123682e09ffSMasahiro Yamada tmp = readl(base); /* VPLL27CTRL */ 124682e09ffSMasahiro Yamada tmp &= ~SC_VPLL27CTRL_WP; /* write protect on */ 125682e09ffSMasahiro Yamada writel(tmp, base); 126682e09ffSMasahiro Yamada 127682e09ffSMasahiro Yamada iounmap(base); 128682e09ffSMasahiro Yamada 129682e09ffSMasahiro Yamada return 0; 130682e09ffSMasahiro Yamada } 131682e09ffSMasahiro Yamada 132682e09ffSMasahiro Yamada int uniphier_ld20_dspll_init(unsigned long reg_base) 133682e09ffSMasahiro Yamada { 134682e09ffSMasahiro Yamada void __iomem *base; 135682e09ffSMasahiro Yamada u32 tmp; 136682e09ffSMasahiro Yamada 137682e09ffSMasahiro Yamada base = ioremap(reg_base, SZ_16); 138682e09ffSMasahiro Yamada if (!base) 139682e09ffSMasahiro Yamada return -ENOMEM; 140682e09ffSMasahiro Yamada 1414013bbb1SDai Okamura tmp = readl(base + 4); /* DSPLLCTRL2 */ 142682e09ffSMasahiro Yamada tmp |= SC_DSPLLCTRL2_K_LD; 1434013bbb1SDai Okamura writel(tmp, base + 4); 144682e09ffSMasahiro Yamada 145682e09ffSMasahiro Yamada iounmap(base); 146682e09ffSMasahiro Yamada 147682e09ffSMasahiro Yamada return 0; 148682e09ffSMasahiro Yamada } 149