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 8682e09ffSMasahiro Yamada #include <linux/bitops.h> 9d9a70368SMasahiro Yamada #include <linux/delay.h> 10*f2ce50b2SMasahiro Yamada #include <linux/kernel.h> 11d9a70368SMasahiro Yamada #include <linux/errno.h> 12682e09ffSMasahiro Yamada #include <linux/io.h> 13682e09ffSMasahiro Yamada #include <linux/sizes.h> 14682e09ffSMasahiro Yamada 15682e09ffSMasahiro Yamada #include "pll.h" 16682e09ffSMasahiro Yamada 17682e09ffSMasahiro Yamada /* PLL type: SSC */ 18682e09ffSMasahiro Yamada #define SC_PLLCTRL_SSC_DK_MASK GENMASK(14, 0) 19682e09ffSMasahiro Yamada #define SC_PLLCTRL_SSC_EN BIT(31) 20682e09ffSMasahiro Yamada #define SC_PLLCTRL2_NRSTDS BIT(28) 21682e09ffSMasahiro Yamada #define SC_PLLCTRL2_SSC_JK_MASK GENMASK(26, 0) 22bc647958SMasahiro Yamada #define SC_PLLCTRL3_REGI_SHIFT 16 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*f2ce50b2SMasahiro Yamada tmp |= DIV_ROUND_CLOSEST(487UL * freq * ssc_rate, divn * 512) & 46682e09ffSMasahiro Yamada SC_PLLCTRL_SSC_DK_MASK; 47682e09ffSMasahiro Yamada writel(tmp, base); 48682e09ffSMasahiro Yamada 49682e09ffSMasahiro Yamada tmp = readl(base + 4); 50682e09ffSMasahiro Yamada tmp &= ~SC_PLLCTRL2_SSC_JK_MASK; 51*f2ce50b2SMasahiro Yamada tmp |= DIV_ROUND_CLOSEST(21431887UL * freq, divn * 512) & 52*f2ce50b2SMasahiro Yamada SC_PLLCTRL2_SSC_JK_MASK; 53c30c44e7SDai Okamura writel(tmp, base + 4); 54682e09ffSMasahiro Yamada 55682e09ffSMasahiro Yamada udelay(50); 56682e09ffSMasahiro Yamada } 57682e09ffSMasahiro Yamada 58682e09ffSMasahiro Yamada tmp = readl(base + 4); /* SSCPLLCTRL2 */ 59682e09ffSMasahiro Yamada tmp |= SC_PLLCTRL2_NRSTDS; 60682e09ffSMasahiro Yamada writel(tmp, base + 4); 61682e09ffSMasahiro Yamada 62682e09ffSMasahiro Yamada iounmap(base); 63682e09ffSMasahiro Yamada 64682e09ffSMasahiro Yamada return 0; 65682e09ffSMasahiro Yamada } 66682e09ffSMasahiro Yamada 67682e09ffSMasahiro Yamada int uniphier_ld20_sscpll_ssc_en(unsigned long reg_base) 68682e09ffSMasahiro Yamada { 69682e09ffSMasahiro Yamada void __iomem *base; 70682e09ffSMasahiro Yamada u32 tmp; 71682e09ffSMasahiro Yamada 72682e09ffSMasahiro Yamada base = ioremap(reg_base, SZ_16); 73682e09ffSMasahiro Yamada if (!base) 74682e09ffSMasahiro Yamada return -ENOMEM; 75682e09ffSMasahiro Yamada 76682e09ffSMasahiro Yamada tmp = readl(base); /* SSCPLLCTRL */ 77682e09ffSMasahiro Yamada tmp |= SC_PLLCTRL_SSC_EN; 78682e09ffSMasahiro Yamada writel(tmp, base); 79682e09ffSMasahiro Yamada 80682e09ffSMasahiro Yamada iounmap(base); 81682e09ffSMasahiro Yamada 82682e09ffSMasahiro Yamada return 0; 83682e09ffSMasahiro Yamada } 84682e09ffSMasahiro Yamada 85bc647958SMasahiro Yamada int uniphier_ld20_sscpll_set_regi(unsigned long reg_base, unsigned regi) 86bc647958SMasahiro Yamada { 87bc647958SMasahiro Yamada void __iomem *base; 88bc647958SMasahiro Yamada u32 tmp; 89bc647958SMasahiro Yamada 90bc647958SMasahiro Yamada base = ioremap(reg_base, SZ_16); 91bc647958SMasahiro Yamada if (!base) 92bc647958SMasahiro Yamada return -ENOMEM; 93bc647958SMasahiro Yamada 944013bbb1SDai Okamura tmp = readl(base + 8); /* SSCPLLCTRL3 */ 95bc647958SMasahiro Yamada tmp &= ~SC_PLLCTRL3_REGI_MASK; 96bc647958SMasahiro Yamada tmp |= regi << SC_PLLCTRL3_REGI_SHIFT; 97bc647958SMasahiro Yamada writel(tmp, base + 8); 98bc647958SMasahiro Yamada 99bc647958SMasahiro Yamada iounmap(base); 100bc647958SMasahiro Yamada 101bc647958SMasahiro Yamada return 0; 102bc647958SMasahiro Yamada } 103bc647958SMasahiro Yamada 104682e09ffSMasahiro Yamada int uniphier_ld20_vpll27_init(unsigned long reg_base) 105682e09ffSMasahiro Yamada { 106682e09ffSMasahiro Yamada void __iomem *base; 107682e09ffSMasahiro Yamada u32 tmp; 108682e09ffSMasahiro Yamada 109682e09ffSMasahiro Yamada base = ioremap(reg_base, SZ_16); 110682e09ffSMasahiro Yamada if (!base) 111682e09ffSMasahiro Yamada return -ENOMEM; 112682e09ffSMasahiro Yamada 113682e09ffSMasahiro Yamada tmp = readl(base); /* VPLL27CTRL */ 114682e09ffSMasahiro Yamada tmp |= SC_VPLL27CTRL_WP; /* write protect off */ 115682e09ffSMasahiro Yamada writel(tmp, base); 116682e09ffSMasahiro Yamada 117682e09ffSMasahiro Yamada tmp = readl(base + 8); /* VPLL27CTRL3 */ 118682e09ffSMasahiro Yamada tmp |= SC_VPLL27CTRL3_K_LD; 119682e09ffSMasahiro Yamada writel(tmp, base + 8); 120682e09ffSMasahiro Yamada 121682e09ffSMasahiro Yamada tmp = readl(base); /* VPLL27CTRL */ 122682e09ffSMasahiro Yamada tmp &= ~SC_VPLL27CTRL_WP; /* write protect on */ 123682e09ffSMasahiro Yamada writel(tmp, base); 124682e09ffSMasahiro Yamada 125682e09ffSMasahiro Yamada iounmap(base); 126682e09ffSMasahiro Yamada 127682e09ffSMasahiro Yamada return 0; 128682e09ffSMasahiro Yamada } 129682e09ffSMasahiro Yamada 130682e09ffSMasahiro Yamada int uniphier_ld20_dspll_init(unsigned long reg_base) 131682e09ffSMasahiro Yamada { 132682e09ffSMasahiro Yamada void __iomem *base; 133682e09ffSMasahiro Yamada u32 tmp; 134682e09ffSMasahiro Yamada 135682e09ffSMasahiro Yamada base = ioremap(reg_base, SZ_16); 136682e09ffSMasahiro Yamada if (!base) 137682e09ffSMasahiro Yamada return -ENOMEM; 138682e09ffSMasahiro Yamada 1394013bbb1SDai Okamura tmp = readl(base + 4); /* DSPLLCTRL2 */ 140682e09ffSMasahiro Yamada tmp |= SC_DSPLLCTRL2_K_LD; 1414013bbb1SDai Okamura writel(tmp, base + 4); 142682e09ffSMasahiro Yamada 143682e09ffSMasahiro Yamada iounmap(base); 144682e09ffSMasahiro Yamada 145682e09ffSMasahiro Yamada return 0; 146682e09ffSMasahiro Yamada } 147