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