linux/arch/c6x/platforms/plldata.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 *  Port on Texas Instruments TMS320C6x architecture
   4 *
   5 *  Copyright (C) 2011 Texas Instruments Incorporated
   6 *  Author: Mark Salter <msalter@redhat.com>
   7 */
   8#include <linux/kernel.h>
   9#include <linux/delay.h>
  10#include <linux/errno.h>
  11#include <linux/string.h>
  12#include <linux/ioport.h>
  13#include <linux/clkdev.h>
  14#include <linux/of.h>
  15#include <linux/of_address.h>
  16
  17#include <asm/clock.h>
  18#include <asm/setup.h>
  19#include <asm/special_insns.h>
  20#include <asm/irq.h>
  21
  22/*
  23 * Common SoC clock support.
  24 */
  25
  26/* Default input for PLL1 */
  27struct clk clkin1 = {
  28        .name = "clkin1",
  29        .node = LIST_HEAD_INIT(clkin1.node),
  30        .children = LIST_HEAD_INIT(clkin1.children),
  31        .childnode = LIST_HEAD_INIT(clkin1.childnode),
  32};
  33
  34struct pll_data c6x_soc_pll1 = {
  35        .num       = 1,
  36        .sysclks   = {
  37                {
  38                        .name = "pll1",
  39                        .parent = &clkin1,
  40                        .pll_data = &c6x_soc_pll1,
  41                        .flags = CLK_PLL,
  42                },
  43                {
  44                        .name = "pll1_sysclk1",
  45                        .parent = &c6x_soc_pll1.sysclks[0],
  46                        .flags = CLK_PLL,
  47                },
  48                {
  49                        .name = "pll1_sysclk2",
  50                        .parent = &c6x_soc_pll1.sysclks[0],
  51                        .flags = CLK_PLL,
  52                },
  53                {
  54                        .name = "pll1_sysclk3",
  55                        .parent = &c6x_soc_pll1.sysclks[0],
  56                        .flags = CLK_PLL,
  57                },
  58                {
  59                        .name = "pll1_sysclk4",
  60                        .parent = &c6x_soc_pll1.sysclks[0],
  61                        .flags = CLK_PLL,
  62                },
  63                {
  64                        .name = "pll1_sysclk5",
  65                        .parent = &c6x_soc_pll1.sysclks[0],
  66                        .flags = CLK_PLL,
  67                },
  68                {
  69                        .name = "pll1_sysclk6",
  70                        .parent = &c6x_soc_pll1.sysclks[0],
  71                        .flags = CLK_PLL,
  72                },
  73                {
  74                        .name = "pll1_sysclk7",
  75                        .parent = &c6x_soc_pll1.sysclks[0],
  76                        .flags = CLK_PLL,
  77                },
  78                {
  79                        .name = "pll1_sysclk8",
  80                        .parent = &c6x_soc_pll1.sysclks[0],
  81                        .flags = CLK_PLL,
  82                },
  83                {
  84                        .name = "pll1_sysclk9",
  85                        .parent = &c6x_soc_pll1.sysclks[0],
  86                        .flags = CLK_PLL,
  87                },
  88                {
  89                        .name = "pll1_sysclk10",
  90                        .parent = &c6x_soc_pll1.sysclks[0],
  91                        .flags = CLK_PLL,
  92                },
  93                {
  94                        .name = "pll1_sysclk11",
  95                        .parent = &c6x_soc_pll1.sysclks[0],
  96                        .flags = CLK_PLL,
  97                },
  98                {
  99                        .name = "pll1_sysclk12",
 100                        .parent = &c6x_soc_pll1.sysclks[0],
 101                        .flags = CLK_PLL,
 102                },
 103                {
 104                        .name = "pll1_sysclk13",
 105                        .parent = &c6x_soc_pll1.sysclks[0],
 106                        .flags = CLK_PLL,
 107                },
 108                {
 109                        .name = "pll1_sysclk14",
 110                        .parent = &c6x_soc_pll1.sysclks[0],
 111                        .flags = CLK_PLL,
 112                },
 113                {
 114                        .name = "pll1_sysclk15",
 115                        .parent = &c6x_soc_pll1.sysclks[0],
 116                        .flags = CLK_PLL,
 117                },
 118                {
 119                        .name = "pll1_sysclk16",
 120                        .parent = &c6x_soc_pll1.sysclks[0],
 121                        .flags = CLK_PLL,
 122                },
 123        },
 124};
 125
 126/* CPU core clock */
 127struct clk c6x_core_clk = {
 128        .name = "core",
 129};
 130
 131/* miscellaneous IO clocks */
 132struct clk c6x_i2c_clk = {
 133        .name = "i2c",
 134};
 135
 136struct clk c6x_watchdog_clk = {
 137        .name = "watchdog",
 138};
 139
 140struct clk c6x_mcbsp1_clk = {
 141        .name = "mcbsp1",
 142};
 143
 144struct clk c6x_mcbsp2_clk = {
 145        .name = "mcbsp2",
 146};
 147
 148struct clk c6x_mdio_clk = {
 149        .name = "mdio",
 150};
 151
 152
 153#ifdef CONFIG_SOC_TMS320C6455
 154static struct clk_lookup c6455_clks[] = {
 155        CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
 156        CLK(NULL, "pll1_sysclk2", &c6x_soc_pll1.sysclks[2]),
 157        CLK(NULL, "pll1_sysclk3", &c6x_soc_pll1.sysclks[3]),
 158        CLK(NULL, "pll1_sysclk4", &c6x_soc_pll1.sysclks[4]),
 159        CLK(NULL, "pll1_sysclk5", &c6x_soc_pll1.sysclks[5]),
 160        CLK(NULL, "core", &c6x_core_clk),
 161        CLK("i2c_davinci.1", NULL, &c6x_i2c_clk),
 162        CLK("watchdog", NULL, &c6x_watchdog_clk),
 163        CLK("2c81800.mdio", NULL, &c6x_mdio_clk),
 164        CLK("", NULL, NULL)
 165};
 166
 167
 168static void __init c6455_setup_clocks(struct device_node *node)
 169{
 170        struct pll_data *pll = &c6x_soc_pll1;
 171        struct clk *sysclks = pll->sysclks;
 172
 173        pll->flags = PLL_HAS_PRE | PLL_HAS_MUL;
 174
 175        sysclks[2].flags |= FIXED_DIV_PLL;
 176        sysclks[2].div = 3;
 177        sysclks[3].flags |= FIXED_DIV_PLL;
 178        sysclks[3].div = 6;
 179        sysclks[4].div = PLLDIV4;
 180        sysclks[5].div = PLLDIV5;
 181
 182        c6x_core_clk.parent = &sysclks[0];
 183        c6x_i2c_clk.parent = &sysclks[3];
 184        c6x_watchdog_clk.parent = &sysclks[3];
 185        c6x_mdio_clk.parent = &sysclks[3];
 186
 187        c6x_clks_init(c6455_clks);
 188}
 189#endif /* CONFIG_SOC_TMS320C6455 */
 190
 191#ifdef CONFIG_SOC_TMS320C6457
 192static struct clk_lookup c6457_clks[] = {
 193        CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
 194        CLK(NULL, "pll1_sysclk1", &c6x_soc_pll1.sysclks[1]),
 195        CLK(NULL, "pll1_sysclk2", &c6x_soc_pll1.sysclks[2]),
 196        CLK(NULL, "pll1_sysclk3", &c6x_soc_pll1.sysclks[3]),
 197        CLK(NULL, "pll1_sysclk4", &c6x_soc_pll1.sysclks[4]),
 198        CLK(NULL, "pll1_sysclk5", &c6x_soc_pll1.sysclks[5]),
 199        CLK(NULL, "core", &c6x_core_clk),
 200        CLK("i2c_davinci.1", NULL, &c6x_i2c_clk),
 201        CLK("watchdog", NULL, &c6x_watchdog_clk),
 202        CLK("2c81800.mdio", NULL, &c6x_mdio_clk),
 203        CLK("", NULL, NULL)
 204};
 205
 206static void __init c6457_setup_clocks(struct device_node *node)
 207{
 208        struct pll_data *pll = &c6x_soc_pll1;
 209        struct clk *sysclks = pll->sysclks;
 210
 211        pll->flags = PLL_HAS_MUL | PLL_HAS_POST;
 212
 213        sysclks[1].flags |= FIXED_DIV_PLL;
 214        sysclks[1].div = 1;
 215        sysclks[2].flags |= FIXED_DIV_PLL;
 216        sysclks[2].div = 3;
 217        sysclks[3].flags |= FIXED_DIV_PLL;
 218        sysclks[3].div = 6;
 219        sysclks[4].div = PLLDIV4;
 220        sysclks[5].div = PLLDIV5;
 221
 222        c6x_core_clk.parent = &sysclks[1];
 223        c6x_i2c_clk.parent = &sysclks[3];
 224        c6x_watchdog_clk.parent = &sysclks[5];
 225        c6x_mdio_clk.parent = &sysclks[5];
 226
 227        c6x_clks_init(c6457_clks);
 228}
 229#endif /* CONFIG_SOC_TMS320C6455 */
 230
 231#ifdef CONFIG_SOC_TMS320C6472
 232static struct clk_lookup c6472_clks[] = {
 233        CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
 234        CLK(NULL, "pll1_sysclk1", &c6x_soc_pll1.sysclks[1]),
 235        CLK(NULL, "pll1_sysclk2", &c6x_soc_pll1.sysclks[2]),
 236        CLK(NULL, "pll1_sysclk3", &c6x_soc_pll1.sysclks[3]),
 237        CLK(NULL, "pll1_sysclk4", &c6x_soc_pll1.sysclks[4]),
 238        CLK(NULL, "pll1_sysclk5", &c6x_soc_pll1.sysclks[5]),
 239        CLK(NULL, "pll1_sysclk6", &c6x_soc_pll1.sysclks[6]),
 240        CLK(NULL, "pll1_sysclk7", &c6x_soc_pll1.sysclks[7]),
 241        CLK(NULL, "pll1_sysclk8", &c6x_soc_pll1.sysclks[8]),
 242        CLK(NULL, "pll1_sysclk9", &c6x_soc_pll1.sysclks[9]),
 243        CLK(NULL, "pll1_sysclk10", &c6x_soc_pll1.sysclks[10]),
 244        CLK(NULL, "core", &c6x_core_clk),
 245        CLK("i2c_davinci.1", NULL, &c6x_i2c_clk),
 246        CLK("watchdog", NULL, &c6x_watchdog_clk),
 247        CLK("2c81800.mdio", NULL, &c6x_mdio_clk),
 248        CLK("", NULL, NULL)
 249};
 250
 251/* assumptions used for delay loop calculations */
 252#define MIN_CLKIN1_KHz 15625
 253#define MAX_CORE_KHz   700000
 254#define MIN_PLLOUT_KHz MIN_CLKIN1_KHz
 255
 256static void __init c6472_setup_clocks(struct device_node *node)
 257{
 258        struct pll_data *pll = &c6x_soc_pll1;
 259        struct clk *sysclks = pll->sysclks;
 260        int i;
 261
 262        pll->flags = PLL_HAS_MUL;
 263
 264        for (i = 1; i <= 6; i++) {
 265                sysclks[i].flags |= FIXED_DIV_PLL;
 266                sysclks[i].div = 1;
 267        }
 268
 269        sysclks[7].flags |= FIXED_DIV_PLL;
 270        sysclks[7].div = 3;
 271        sysclks[8].flags |= FIXED_DIV_PLL;
 272        sysclks[8].div = 6;
 273        sysclks[9].flags |= FIXED_DIV_PLL;
 274        sysclks[9].div = 2;
 275        sysclks[10].div = PLLDIV10;
 276
 277        c6x_core_clk.parent = &sysclks[get_coreid() + 1];
 278        c6x_i2c_clk.parent = &sysclks[8];
 279        c6x_watchdog_clk.parent = &sysclks[8];
 280        c6x_mdio_clk.parent = &sysclks[5];
 281
 282        c6x_clks_init(c6472_clks);
 283}
 284#endif /* CONFIG_SOC_TMS320C6472 */
 285
 286
 287#ifdef CONFIG_SOC_TMS320C6474
 288static struct clk_lookup c6474_clks[] = {
 289        CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
 290        CLK(NULL, "pll1_sysclk7", &c6x_soc_pll1.sysclks[7]),
 291        CLK(NULL, "pll1_sysclk9", &c6x_soc_pll1.sysclks[9]),
 292        CLK(NULL, "pll1_sysclk10", &c6x_soc_pll1.sysclks[10]),
 293        CLK(NULL, "pll1_sysclk11", &c6x_soc_pll1.sysclks[11]),
 294        CLK(NULL, "pll1_sysclk12", &c6x_soc_pll1.sysclks[12]),
 295        CLK(NULL, "pll1_sysclk13", &c6x_soc_pll1.sysclks[13]),
 296        CLK(NULL, "core", &c6x_core_clk),
 297        CLK("i2c_davinci.1", NULL, &c6x_i2c_clk),
 298        CLK("mcbsp.1", NULL, &c6x_mcbsp1_clk),
 299        CLK("mcbsp.2", NULL, &c6x_mcbsp2_clk),
 300        CLK("watchdog", NULL, &c6x_watchdog_clk),
 301        CLK("2c81800.mdio", NULL, &c6x_mdio_clk),
 302        CLK("", NULL, NULL)
 303};
 304
 305static void __init c6474_setup_clocks(struct device_node *node)
 306{
 307        struct pll_data *pll = &c6x_soc_pll1;
 308        struct clk *sysclks = pll->sysclks;
 309
 310        pll->flags = PLL_HAS_MUL;
 311
 312        sysclks[7].flags |= FIXED_DIV_PLL;
 313        sysclks[7].div = 1;
 314        sysclks[9].flags |= FIXED_DIV_PLL;
 315        sysclks[9].div = 3;
 316        sysclks[10].flags |= FIXED_DIV_PLL;
 317        sysclks[10].div = 6;
 318
 319        sysclks[11].div = PLLDIV11;
 320
 321        sysclks[12].flags |= FIXED_DIV_PLL;
 322        sysclks[12].div = 2;
 323
 324        sysclks[13].div = PLLDIV13;
 325
 326        c6x_core_clk.parent = &sysclks[7];
 327        c6x_i2c_clk.parent = &sysclks[10];
 328        c6x_watchdog_clk.parent = &sysclks[10];
 329        c6x_mcbsp1_clk.parent = &sysclks[10];
 330        c6x_mcbsp2_clk.parent = &sysclks[10];
 331
 332        c6x_clks_init(c6474_clks);
 333}
 334#endif /* CONFIG_SOC_TMS320C6474 */
 335
 336#ifdef CONFIG_SOC_TMS320C6678
 337static struct clk_lookup c6678_clks[] = {
 338        CLK(NULL, "pll1", &c6x_soc_pll1.sysclks[0]),
 339        CLK(NULL, "pll1_refclk", &c6x_soc_pll1.sysclks[1]),
 340        CLK(NULL, "pll1_sysclk2", &c6x_soc_pll1.sysclks[2]),
 341        CLK(NULL, "pll1_sysclk3", &c6x_soc_pll1.sysclks[3]),
 342        CLK(NULL, "pll1_sysclk4", &c6x_soc_pll1.sysclks[4]),
 343        CLK(NULL, "pll1_sysclk5", &c6x_soc_pll1.sysclks[5]),
 344        CLK(NULL, "pll1_sysclk6", &c6x_soc_pll1.sysclks[6]),
 345        CLK(NULL, "pll1_sysclk7", &c6x_soc_pll1.sysclks[7]),
 346        CLK(NULL, "pll1_sysclk8", &c6x_soc_pll1.sysclks[8]),
 347        CLK(NULL, "pll1_sysclk9", &c6x_soc_pll1.sysclks[9]),
 348        CLK(NULL, "pll1_sysclk10", &c6x_soc_pll1.sysclks[10]),
 349        CLK(NULL, "pll1_sysclk11", &c6x_soc_pll1.sysclks[11]),
 350        CLK(NULL, "core", &c6x_core_clk),
 351        CLK("", NULL, NULL)
 352};
 353
 354static void __init c6678_setup_clocks(struct device_node *node)
 355{
 356        struct pll_data *pll = &c6x_soc_pll1;
 357        struct clk *sysclks = pll->sysclks;
 358
 359        pll->flags = PLL_HAS_MUL;
 360
 361        sysclks[1].flags |= FIXED_DIV_PLL;
 362        sysclks[1].div = 1;
 363
 364        sysclks[2].div = PLLDIV2;
 365
 366        sysclks[3].flags |= FIXED_DIV_PLL;
 367        sysclks[3].div = 2;
 368
 369        sysclks[4].flags |= FIXED_DIV_PLL;
 370        sysclks[4].div = 3;
 371
 372        sysclks[5].div = PLLDIV5;
 373
 374        sysclks[6].flags |= FIXED_DIV_PLL;
 375        sysclks[6].div = 64;
 376
 377        sysclks[7].flags |= FIXED_DIV_PLL;
 378        sysclks[7].div = 6;
 379
 380        sysclks[8].div = PLLDIV8;
 381
 382        sysclks[9].flags |= FIXED_DIV_PLL;
 383        sysclks[9].div = 12;
 384
 385        sysclks[10].flags |= FIXED_DIV_PLL;
 386        sysclks[10].div = 3;
 387
 388        sysclks[11].flags |= FIXED_DIV_PLL;
 389        sysclks[11].div = 6;
 390
 391        c6x_core_clk.parent = &sysclks[0];
 392        c6x_i2c_clk.parent = &sysclks[7];
 393
 394        c6x_clks_init(c6678_clks);
 395}
 396#endif /* CONFIG_SOC_TMS320C6678 */
 397
 398static struct of_device_id c6x_clkc_match[] __initdata = {
 399#ifdef CONFIG_SOC_TMS320C6455
 400        { .compatible = "ti,c6455-pll", .data = c6455_setup_clocks },
 401#endif
 402#ifdef CONFIG_SOC_TMS320C6457
 403        { .compatible = "ti,c6457-pll", .data = c6457_setup_clocks },
 404#endif
 405#ifdef CONFIG_SOC_TMS320C6472
 406        { .compatible = "ti,c6472-pll", .data = c6472_setup_clocks },
 407#endif
 408#ifdef CONFIG_SOC_TMS320C6474
 409        { .compatible = "ti,c6474-pll", .data = c6474_setup_clocks },
 410#endif
 411#ifdef CONFIG_SOC_TMS320C6678
 412        { .compatible = "ti,c6678-pll", .data = c6678_setup_clocks },
 413#endif
 414        { .compatible = "ti,c64x+pll" },
 415        {}
 416};
 417
 418void __init c64x_setup_clocks(void)
 419{
 420        void (*__setup_clocks)(struct device_node *np);
 421        struct pll_data *pll = &c6x_soc_pll1;
 422        struct device_node *node;
 423        const struct of_device_id *id;
 424        int err;
 425        u32 val;
 426
 427        node = of_find_matching_node(NULL, c6x_clkc_match);
 428        if (!node)
 429                return;
 430
 431        pll->base = of_iomap(node, 0);
 432        if (!pll->base)
 433                goto out;
 434
 435        err = of_property_read_u32(node, "clock-frequency", &val);
 436        if (err || val == 0) {
 437                pr_err("%pOF: no clock-frequency found! Using %dMHz\n",
 438                       node, (int)val / 1000000);
 439                val = 25000000;
 440        }
 441        clkin1.rate = val;
 442
 443        err = of_property_read_u32(node, "ti,c64x+pll-bypass-delay", &val);
 444        if (err)
 445                val = 5000;
 446        pll->bypass_delay = val;
 447
 448        err = of_property_read_u32(node, "ti,c64x+pll-reset-delay", &val);
 449        if (err)
 450                val = 30000;
 451        pll->reset_delay = val;
 452
 453        err = of_property_read_u32(node, "ti,c64x+pll-lock-delay", &val);
 454        if (err)
 455                val = 30000;
 456        pll->lock_delay = val;
 457
 458        /* id->data is a pointer to SoC-specific setup */
 459        id = of_match_node(c6x_clkc_match, node);
 460        if (id && id->data) {
 461                __setup_clocks = id->data;
 462                __setup_clocks(node);
 463        }
 464
 465out:
 466        of_node_put(node);
 467}
 468