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