Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Nomadik clock implementation
0004  * Copyright (C) 2013 ST-Ericsson AB
0005  * Author: Linus Walleij <linus.walleij@linaro.org>
0006  */
0007 
0008 #define pr_fmt(fmt) "Nomadik SRC clocks: " fmt
0009 
0010 #include <linux/bitops.h>
0011 #include <linux/slab.h>
0012 #include <linux/err.h>
0013 #include <linux/io.h>
0014 #include <linux/clk-provider.h>
0015 #include <linux/of.h>
0016 #include <linux/of_address.h>
0017 #include <linux/debugfs.h>
0018 #include <linux/seq_file.h>
0019 #include <linux/spinlock.h>
0020 #include <linux/reboot.h>
0021 
0022 /*
0023  * The Nomadik clock tree is described in the STN8815A12 DB V4.2
0024  * reference manual for the chip, page 94 ff.
0025  * Clock IDs are in the STn8815 Reference Manual table 3, page 27.
0026  */
0027 
0028 #define SRC_CR          0x00U
0029 #define SRC_CR_T0_ENSEL     BIT(15)
0030 #define SRC_CR_T1_ENSEL     BIT(17)
0031 #define SRC_CR_T2_ENSEL     BIT(19)
0032 #define SRC_CR_T3_ENSEL     BIT(21)
0033 #define SRC_CR_T4_ENSEL     BIT(23)
0034 #define SRC_CR_T5_ENSEL     BIT(25)
0035 #define SRC_CR_T6_ENSEL     BIT(27)
0036 #define SRC_CR_T7_ENSEL     BIT(29)
0037 #define SRC_XTALCR      0x0CU
0038 #define SRC_XTALCR_XTALTIMEN    BIT(20)
0039 #define SRC_XTALCR_SXTALDIS BIT(19)
0040 #define SRC_XTALCR_MXTALSTAT    BIT(2)
0041 #define SRC_XTALCR_MXTALEN  BIT(1)
0042 #define SRC_XTALCR_MXTALOVER    BIT(0)
0043 #define SRC_PLLCR       0x10U
0044 #define SRC_PLLCR_PLLTIMEN  BIT(29)
0045 #define SRC_PLLCR_PLL2EN    BIT(28)
0046 #define SRC_PLLCR_PLL1STAT  BIT(2)
0047 #define SRC_PLLCR_PLL1EN    BIT(1)
0048 #define SRC_PLLCR_PLL1OVER  BIT(0)
0049 #define SRC_PLLFR       0x14U
0050 #define SRC_PCKEN0      0x24U
0051 #define SRC_PCKDIS0     0x28U
0052 #define SRC_PCKENSR0        0x2CU
0053 #define SRC_PCKSR0      0x30U
0054 #define SRC_PCKEN1      0x34U
0055 #define SRC_PCKDIS1     0x38U
0056 #define SRC_PCKENSR1        0x3CU
0057 #define SRC_PCKSR1      0x40U
0058 
0059 /* Lock protecting the SRC_CR register */
0060 static DEFINE_SPINLOCK(src_lock);
0061 /* Base address of the SRC */
0062 static void __iomem *src_base;
0063 
0064 static int nomadik_clk_reboot_handler(struct notifier_block *this,
0065                 unsigned long code,
0066                 void *unused)
0067 {
0068     u32 val;
0069 
0070     /* The main chrystal need to be enabled for reboot to work */
0071     val = readl(src_base + SRC_XTALCR);
0072     val &= ~SRC_XTALCR_MXTALOVER;
0073     val |= SRC_XTALCR_MXTALEN;
0074     pr_crit("force-enabling MXTALO\n");
0075     writel(val, src_base + SRC_XTALCR);
0076     return NOTIFY_OK;
0077 }
0078 
0079 static struct notifier_block nomadik_clk_reboot_notifier = {
0080     .notifier_call = nomadik_clk_reboot_handler,
0081 };
0082 
0083 static const struct of_device_id nomadik_src_match[] __initconst = {
0084     { .compatible = "stericsson,nomadik-src" },
0085     { /* sentinel */ }
0086 };
0087 
0088 static void __init nomadik_src_init(void)
0089 {
0090     struct device_node *np;
0091     u32 val;
0092 
0093     np = of_find_matching_node(NULL, nomadik_src_match);
0094     if (!np) {
0095         pr_crit("no matching node for SRC, aborting clock init\n");
0096         return;
0097     }
0098     src_base = of_iomap(np, 0);
0099     if (!src_base) {
0100         pr_err("%s: must have src parent node with REGS (%pOFn)\n",
0101                __func__, np);
0102         return;
0103     }
0104 
0105     /* Set all timers to use the 2.4 MHz TIMCLK */
0106     val = readl(src_base + SRC_CR);
0107     val |= SRC_CR_T0_ENSEL;
0108     val |= SRC_CR_T1_ENSEL;
0109     val |= SRC_CR_T2_ENSEL;
0110     val |= SRC_CR_T3_ENSEL;
0111     val |= SRC_CR_T4_ENSEL;
0112     val |= SRC_CR_T5_ENSEL;
0113     val |= SRC_CR_T6_ENSEL;
0114     val |= SRC_CR_T7_ENSEL;
0115     writel(val, src_base + SRC_CR);
0116 
0117     val = readl(src_base + SRC_XTALCR);
0118     pr_info("SXTALO is %s\n",
0119         (val & SRC_XTALCR_SXTALDIS) ? "disabled" : "enabled");
0120     pr_info("MXTAL is %s\n",
0121         (val & SRC_XTALCR_MXTALSTAT) ? "enabled" : "disabled");
0122     if (of_property_read_bool(np, "disable-sxtalo")) {
0123         /* The machine uses an external oscillator circuit */
0124         val |= SRC_XTALCR_SXTALDIS;
0125         pr_info("disabling SXTALO\n");
0126     }
0127     if (of_property_read_bool(np, "disable-mxtalo")) {
0128         /* Disable this too: also run by external oscillator */
0129         val |= SRC_XTALCR_MXTALOVER;
0130         val &= ~SRC_XTALCR_MXTALEN;
0131         pr_info("disabling MXTALO\n");
0132     }
0133     writel(val, src_base + SRC_XTALCR);
0134     register_reboot_notifier(&nomadik_clk_reboot_notifier);
0135 }
0136 
0137 /**
0138  * struct clk_pll1 - Nomadik PLL1 clock
0139  * @hw: corresponding clock hardware entry
0140  * @id: PLL instance: 1 or 2
0141  */
0142 struct clk_pll {
0143     struct clk_hw hw;
0144     int id;
0145 };
0146 
0147 /**
0148  * struct clk_src - Nomadik src clock
0149  * @hw: corresponding clock hardware entry
0150  * @id: the clock ID
0151  * @group1: true if the clock is in group1, else it is in group0
0152  * @clkbit: bit 0...31 corresponding to the clock in each clock register
0153  */
0154 struct clk_src {
0155     struct clk_hw hw;
0156     int id;
0157     bool group1;
0158     u32 clkbit;
0159 };
0160 
0161 #define to_pll(_hw) container_of(_hw, struct clk_pll, hw)
0162 #define to_src(_hw) container_of(_hw, struct clk_src, hw)
0163 
0164 static int pll_clk_enable(struct clk_hw *hw)
0165 {
0166     struct clk_pll *pll = to_pll(hw);
0167     u32 val;
0168 
0169     spin_lock(&src_lock);
0170     val = readl(src_base + SRC_PLLCR);
0171     if (pll->id == 1) {
0172         if (val & SRC_PLLCR_PLL1OVER) {
0173             val |= SRC_PLLCR_PLL1EN;
0174             writel(val, src_base + SRC_PLLCR);
0175         }
0176     } else if (pll->id == 2) {
0177         val |= SRC_PLLCR_PLL2EN;
0178         writel(val, src_base + SRC_PLLCR);
0179     }
0180     spin_unlock(&src_lock);
0181     return 0;
0182 }
0183 
0184 static void pll_clk_disable(struct clk_hw *hw)
0185 {
0186     struct clk_pll *pll = to_pll(hw);
0187     u32 val;
0188 
0189     spin_lock(&src_lock);
0190     val = readl(src_base + SRC_PLLCR);
0191     if (pll->id == 1) {
0192         if (val & SRC_PLLCR_PLL1OVER) {
0193             val &= ~SRC_PLLCR_PLL1EN;
0194             writel(val, src_base + SRC_PLLCR);
0195         }
0196     } else if (pll->id == 2) {
0197         val &= ~SRC_PLLCR_PLL2EN;
0198         writel(val, src_base + SRC_PLLCR);
0199     }
0200     spin_unlock(&src_lock);
0201 }
0202 
0203 static int pll_clk_is_enabled(struct clk_hw *hw)
0204 {
0205     struct clk_pll *pll = to_pll(hw);
0206     u32 val;
0207 
0208     val = readl(src_base + SRC_PLLCR);
0209     if (pll->id == 1) {
0210         if (val & SRC_PLLCR_PLL1OVER)
0211             return !!(val & SRC_PLLCR_PLL1EN);
0212     } else if (pll->id == 2) {
0213         return !!(val & SRC_PLLCR_PLL2EN);
0214     }
0215     return 1;
0216 }
0217 
0218 static unsigned long pll_clk_recalc_rate(struct clk_hw *hw,
0219                       unsigned long parent_rate)
0220 {
0221     struct clk_pll *pll = to_pll(hw);
0222     u32 val;
0223 
0224     val = readl(src_base + SRC_PLLFR);
0225 
0226     if (pll->id == 1) {
0227         u8 mul;
0228         u8 div;
0229 
0230         mul = (val >> 8) & 0x3FU;
0231         mul += 2;
0232         div = val & 0x07U;
0233         return (parent_rate * mul) >> div;
0234     }
0235 
0236     if (pll->id == 2) {
0237         u8 mul;
0238 
0239         mul = (val >> 24) & 0x3FU;
0240         mul += 2;
0241         return (parent_rate * mul);
0242     }
0243 
0244     /* Unknown PLL */
0245     return 0;
0246 }
0247 
0248 
0249 static const struct clk_ops pll_clk_ops = {
0250     .enable = pll_clk_enable,
0251     .disable = pll_clk_disable,
0252     .is_enabled = pll_clk_is_enabled,
0253     .recalc_rate = pll_clk_recalc_rate,
0254 };
0255 
0256 static struct clk_hw * __init
0257 pll_clk_register(struct device *dev, const char *name,
0258          const char *parent_name, u32 id)
0259 {
0260     int ret;
0261     struct clk_pll *pll;
0262     struct clk_init_data init;
0263 
0264     if (id != 1 && id != 2) {
0265         pr_err("%s: the Nomadik has only PLL 1 & 2\n", __func__);
0266         return ERR_PTR(-EINVAL);
0267     }
0268 
0269     pll = kzalloc(sizeof(*pll), GFP_KERNEL);
0270     if (!pll)
0271         return ERR_PTR(-ENOMEM);
0272 
0273     init.name = name;
0274     init.ops = &pll_clk_ops;
0275     init.parent_names = (parent_name ? &parent_name : NULL);
0276     init.num_parents = (parent_name ? 1 : 0);
0277     pll->hw.init = &init;
0278     pll->id = id;
0279 
0280     pr_debug("register PLL1 clock \"%s\"\n", name);
0281 
0282     ret = clk_hw_register(dev, &pll->hw);
0283     if (ret) {
0284         kfree(pll);
0285         return ERR_PTR(ret);
0286     }
0287 
0288     return &pll->hw;
0289 }
0290 
0291 /*
0292  * The Nomadik SRC clocks are gated, but not in the sense that
0293  * you read-modify-write a register. Instead there are separate
0294  * clock enable and clock disable registers. Writing a '1' bit in
0295  * the enable register for a certain clock ungates that clock without
0296  * affecting the other clocks. The disable register works the opposite
0297  * way.
0298  */
0299 
0300 static int src_clk_enable(struct clk_hw *hw)
0301 {
0302     struct clk_src *sclk = to_src(hw);
0303     u32 enreg = sclk->group1 ? SRC_PCKEN1 : SRC_PCKEN0;
0304     u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
0305 
0306     writel(sclk->clkbit, src_base + enreg);
0307     /* spin until enabled */
0308     while (!(readl(src_base + sreg) & sclk->clkbit))
0309         cpu_relax();
0310     return 0;
0311 }
0312 
0313 static void src_clk_disable(struct clk_hw *hw)
0314 {
0315     struct clk_src *sclk = to_src(hw);
0316     u32 disreg = sclk->group1 ? SRC_PCKDIS1 : SRC_PCKDIS0;
0317     u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
0318 
0319     writel(sclk->clkbit, src_base + disreg);
0320     /* spin until disabled */
0321     while (readl(src_base + sreg) & sclk->clkbit)
0322         cpu_relax();
0323 }
0324 
0325 static int src_clk_is_enabled(struct clk_hw *hw)
0326 {
0327     struct clk_src *sclk = to_src(hw);
0328     u32 sreg = sclk->group1 ? SRC_PCKSR1 : SRC_PCKSR0;
0329     u32 val = readl(src_base + sreg);
0330 
0331     return !!(val & sclk->clkbit);
0332 }
0333 
0334 static unsigned long
0335 src_clk_recalc_rate(struct clk_hw *hw,
0336             unsigned long parent_rate)
0337 {
0338     return parent_rate;
0339 }
0340 
0341 static const struct clk_ops src_clk_ops = {
0342     .enable = src_clk_enable,
0343     .disable = src_clk_disable,
0344     .is_enabled = src_clk_is_enabled,
0345     .recalc_rate = src_clk_recalc_rate,
0346 };
0347 
0348 static struct clk_hw * __init
0349 src_clk_register(struct device *dev, const char *name,
0350          const char *parent_name, u8 id)
0351 {
0352     int ret;
0353     struct clk_src *sclk;
0354     struct clk_init_data init;
0355 
0356     sclk = kzalloc(sizeof(*sclk), GFP_KERNEL);
0357     if (!sclk)
0358         return ERR_PTR(-ENOMEM);
0359 
0360     init.name = name;
0361     init.ops = &src_clk_ops;
0362     /* Do not force-disable the static SDRAM controller */
0363     if (id == 2)
0364         init.flags = CLK_IGNORE_UNUSED;
0365     else
0366         init.flags = 0;
0367     init.parent_names = (parent_name ? &parent_name : NULL);
0368     init.num_parents = (parent_name ? 1 : 0);
0369     sclk->hw.init = &init;
0370     sclk->id = id;
0371     sclk->group1 = (id > 31);
0372     sclk->clkbit = BIT(id & 0x1f);
0373 
0374     pr_debug("register clock \"%s\" ID: %d group: %d bits: %08x\n",
0375          name, id, sclk->group1, sclk->clkbit);
0376 
0377     ret = clk_hw_register(dev, &sclk->hw);
0378     if (ret) {
0379         kfree(sclk);
0380         return ERR_PTR(ret);
0381     }
0382 
0383     return &sclk->hw;
0384 }
0385 
0386 #ifdef CONFIG_DEBUG_FS
0387 
0388 static u32 src_pcksr0_boot;
0389 static u32 src_pcksr1_boot;
0390 
0391 static const char * const src_clk_names[] = {
0392     "HCLKDMA0  ",
0393     "HCLKSMC   ",
0394     "HCLKSDRAM ",
0395     "HCLKDMA1  ",
0396     "HCLKCLCD  ",
0397     "PCLKIRDA  ",
0398     "PCLKSSP   ",
0399     "PCLKUART0 ",
0400     "PCLKSDI   ",
0401     "PCLKI2C0  ",
0402     "PCLKI2C1  ",
0403     "PCLKUART1 ",
0404     "PCLMSP0   ",
0405     "HCLKUSB   ",
0406     "HCLKDIF   ",
0407     "HCLKSAA   ",
0408     "HCLKSVA   ",
0409     "PCLKHSI   ",
0410     "PCLKXTI   ",
0411     "PCLKUART2 ",
0412     "PCLKMSP1  ",
0413     "PCLKMSP2  ",
0414     "PCLKOWM   ",
0415     "HCLKHPI   ",
0416     "PCLKSKE   ",
0417     "PCLKHSEM  ",
0418     "HCLK3D    ",
0419     "HCLKHASH  ",
0420     "HCLKCRYP  ",
0421     "PCLKMSHC  ",
0422     "HCLKUSBM  ",
0423     "HCLKRNG   ",
0424     "RESERVED  ",
0425     "RESERVED  ",
0426     "RESERVED  ",
0427     "RESERVED  ",
0428     "CLDCLK    ",
0429     "IRDACLK   ",
0430     "SSPICLK   ",
0431     "UART0CLK  ",
0432     "SDICLK    ",
0433     "I2C0CLK   ",
0434     "I2C1CLK   ",
0435     "UART1CLK  ",
0436     "MSPCLK0   ",
0437     "USBCLK    ",
0438     "DIFCLK    ",
0439     "IPI2CCLK  ",
0440     "IPBMCCLK  ",
0441     "HSICLKRX  ",
0442     "HSICLKTX  ",
0443     "UART2CLK  ",
0444     "MSPCLK1   ",
0445     "MSPCLK2   ",
0446     "OWMCLK    ",
0447     "RESERVED  ",
0448     "SKECLK    ",
0449     "RESERVED  ",
0450     "3DCLK     ",
0451     "PCLKMSP3  ",
0452     "MSPCLK3   ",
0453     "MSHCCLK   ",
0454     "USBMCLK   ",
0455     "RNGCCLK   ",
0456 };
0457 
0458 static int nomadik_src_clk_debugfs_show(struct seq_file *s, void *what)
0459 {
0460     int i;
0461     u32 src_pcksr0 = readl(src_base + SRC_PCKSR0);
0462     u32 src_pcksr1 = readl(src_base + SRC_PCKSR1);
0463     u32 src_pckensr0 = readl(src_base + SRC_PCKENSR0);
0464     u32 src_pckensr1 = readl(src_base + SRC_PCKENSR1);
0465 
0466     seq_puts(s, "Clock:      Boot:   Now:    Request: ASKED:\n");
0467     for (i = 0; i < ARRAY_SIZE(src_clk_names); i++) {
0468         u32 pcksrb = (i < 0x20) ? src_pcksr0_boot : src_pcksr1_boot;
0469         u32 pcksr = (i < 0x20) ? src_pcksr0 : src_pcksr1;
0470         u32 pckreq = (i < 0x20) ? src_pckensr0 : src_pckensr1;
0471         u32 mask = BIT(i & 0x1f);
0472 
0473         seq_printf(s, "%s  %s     %s     %s\n",
0474                src_clk_names[i],
0475                (pcksrb & mask) ? "on " : "off",
0476                (pcksr & mask) ? "on " : "off",
0477                (pckreq & mask) ? "on " : "off");
0478     }
0479     return 0;
0480 }
0481 
0482 DEFINE_SHOW_ATTRIBUTE(nomadik_src_clk_debugfs);
0483 
0484 static int __init nomadik_src_clk_init_debugfs(void)
0485 {
0486     /* Vital for multiplatform */
0487     if (!src_base)
0488         return -ENODEV;
0489     src_pcksr0_boot = readl(src_base + SRC_PCKSR0);
0490     src_pcksr1_boot = readl(src_base + SRC_PCKSR1);
0491     debugfs_create_file("nomadik-src-clk", S_IFREG | S_IRUGO,
0492                 NULL, NULL, &nomadik_src_clk_debugfs_fops);
0493     return 0;
0494 }
0495 device_initcall(nomadik_src_clk_init_debugfs);
0496 
0497 #endif
0498 
0499 static void __init of_nomadik_pll_setup(struct device_node *np)
0500 {
0501     struct clk_hw *hw;
0502     const char *clk_name = np->name;
0503     const char *parent_name;
0504     u32 pll_id;
0505 
0506     if (!src_base)
0507         nomadik_src_init();
0508 
0509     if (of_property_read_u32(np, "pll-id", &pll_id)) {
0510         pr_err("%s: PLL \"%s\" missing pll-id property\n",
0511             __func__, clk_name);
0512         return;
0513     }
0514     parent_name = of_clk_get_parent_name(np, 0);
0515     hw = pll_clk_register(NULL, clk_name, parent_name, pll_id);
0516     if (!IS_ERR(hw))
0517         of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0518 }
0519 CLK_OF_DECLARE(nomadik_pll_clk,
0520     "st,nomadik-pll-clock", of_nomadik_pll_setup);
0521 
0522 static void __init of_nomadik_hclk_setup(struct device_node *np)
0523 {
0524     struct clk_hw *hw;
0525     const char *clk_name = np->name;
0526     const char *parent_name;
0527 
0528     if (!src_base)
0529         nomadik_src_init();
0530 
0531     parent_name = of_clk_get_parent_name(np, 0);
0532     /*
0533      * The HCLK divides PLL1 with 1 (passthru), 2, 3 or 4.
0534      */
0535     hw = clk_hw_register_divider(NULL, clk_name, parent_name,
0536                0, src_base + SRC_CR,
0537                13, 2,
0538                CLK_DIVIDER_ONE_BASED | CLK_DIVIDER_ALLOW_ZERO,
0539                &src_lock);
0540     if (!IS_ERR(hw))
0541         of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0542 }
0543 CLK_OF_DECLARE(nomadik_hclk_clk,
0544     "st,nomadik-hclk-clock", of_nomadik_hclk_setup);
0545 
0546 static void __init of_nomadik_src_clk_setup(struct device_node *np)
0547 {
0548     struct clk_hw *hw;
0549     const char *clk_name = np->name;
0550     const char *parent_name;
0551     u32 clk_id;
0552 
0553     if (!src_base)
0554         nomadik_src_init();
0555 
0556     if (of_property_read_u32(np, "clock-id", &clk_id)) {
0557         pr_err("%s: SRC clock \"%s\" missing clock-id property\n",
0558             __func__, clk_name);
0559         return;
0560     }
0561     parent_name = of_clk_get_parent_name(np, 0);
0562     hw = src_clk_register(NULL, clk_name, parent_name, clk_id);
0563     if (!IS_ERR(hw))
0564         of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw);
0565 }
0566 CLK_OF_DECLARE(nomadik_src_clk,
0567     "st,nomadik-src-clock", of_nomadik_src_clk_setup);