0001
0002
0003
0004
0005
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
0024
0025
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
0060 static DEFINE_SPINLOCK(src_lock);
0061
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
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 { }
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
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
0124 val |= SRC_XTALCR_SXTALDIS;
0125 pr_info("disabling SXTALO\n");
0126 }
0127 if (of_property_read_bool(np, "disable-mxtalo")) {
0128
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
0139
0140
0141
0142 struct clk_pll {
0143 struct clk_hw hw;
0144 int id;
0145 };
0146
0147
0148
0149
0150
0151
0152
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
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
0293
0294
0295
0296
0297
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
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
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
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
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
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);