| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2013 Boris BREZILLON <b.brezillon@overkiz.com> |
|---|
| 3 | | - * |
|---|
| 4 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 5 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 6 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 7 | | - * (at your option) any later version. |
|---|
| 8 | | - * |
|---|
| 9 | 4 | */ |
|---|
| 10 | 5 | |
|---|
| 11 | 6 | #include <linux/clk-provider.h> |
|---|
| .. | .. |
|---|
| 33 | 28 | #define PLL_COUNT_SHIFT 8 |
|---|
| 34 | 29 | #define PLL_OUT_SHIFT 14 |
|---|
| 35 | 30 | #define PLL_MAX_ID 1 |
|---|
| 36 | | - |
|---|
| 37 | | -struct clk_pll_characteristics { |
|---|
| 38 | | - struct clk_range input; |
|---|
| 39 | | - int num_output; |
|---|
| 40 | | - struct clk_range *output; |
|---|
| 41 | | - u16 *icpll; |
|---|
| 42 | | - u8 *out; |
|---|
| 43 | | -}; |
|---|
| 44 | | - |
|---|
| 45 | | -struct clk_pll_layout { |
|---|
| 46 | | - u32 pllr_mask; |
|---|
| 47 | | - u16 mul_mask; |
|---|
| 48 | | - u8 mul_shift; |
|---|
| 49 | | -}; |
|---|
| 50 | 31 | |
|---|
| 51 | 32 | #define to_clk_pll(hw) container_of(hw, struct clk_pll, hw) |
|---|
| 52 | 33 | |
|---|
| .. | .. |
|---|
| 288 | 269 | .set_rate = clk_pll_set_rate, |
|---|
| 289 | 270 | }; |
|---|
| 290 | 271 | |
|---|
| 291 | | -static struct clk_hw * __init |
|---|
| 272 | +struct clk_hw * __init |
|---|
| 292 | 273 | at91_clk_register_pll(struct regmap *regmap, const char *name, |
|---|
| 293 | 274 | const char *parent_name, u8 id, |
|---|
| 294 | 275 | const struct clk_pll_layout *layout, |
|---|
| .. | .. |
|---|
| 296 | 277 | { |
|---|
| 297 | 278 | struct clk_pll *pll; |
|---|
| 298 | 279 | struct clk_hw *hw; |
|---|
| 299 | | - struct clk_init_data init = {}; |
|---|
| 280 | + struct clk_init_data init; |
|---|
| 300 | 281 | int offset = PLL_REG(id); |
|---|
| 301 | 282 | unsigned int pllr; |
|---|
| 302 | 283 | int ret; |
|---|
| .. | .. |
|---|
| 334 | 315 | } |
|---|
| 335 | 316 | |
|---|
| 336 | 317 | |
|---|
| 337 | | -static const struct clk_pll_layout at91rm9200_pll_layout = { |
|---|
| 318 | +const struct clk_pll_layout at91rm9200_pll_layout = { |
|---|
| 338 | 319 | .pllr_mask = 0x7FFFFFF, |
|---|
| 339 | 320 | .mul_shift = 16, |
|---|
| 340 | 321 | .mul_mask = 0x7FF, |
|---|
| 341 | 322 | }; |
|---|
| 342 | 323 | |
|---|
| 343 | | -static const struct clk_pll_layout at91sam9g45_pll_layout = { |
|---|
| 324 | +const struct clk_pll_layout at91sam9g45_pll_layout = { |
|---|
| 344 | 325 | .pllr_mask = 0xFFFFFF, |
|---|
| 345 | 326 | .mul_shift = 16, |
|---|
| 346 | 327 | .mul_mask = 0xFF, |
|---|
| 347 | 328 | }; |
|---|
| 348 | 329 | |
|---|
| 349 | | -static const struct clk_pll_layout at91sam9g20_pllb_layout = { |
|---|
| 330 | +const struct clk_pll_layout at91sam9g20_pllb_layout = { |
|---|
| 350 | 331 | .pllr_mask = 0x3FFFFF, |
|---|
| 351 | 332 | .mul_shift = 16, |
|---|
| 352 | 333 | .mul_mask = 0x3F, |
|---|
| 353 | 334 | }; |
|---|
| 354 | 335 | |
|---|
| 355 | | -static const struct clk_pll_layout sama5d3_pll_layout = { |
|---|
| 336 | +const struct clk_pll_layout sama5d3_pll_layout = { |
|---|
| 356 | 337 | .pllr_mask = 0x1FFFFFF, |
|---|
| 357 | 338 | .mul_shift = 18, |
|---|
| 358 | 339 | .mul_mask = 0x7F, |
|---|
| 359 | 340 | }; |
|---|
| 360 | | - |
|---|
| 361 | | - |
|---|
| 362 | | -static struct clk_pll_characteristics * __init |
|---|
| 363 | | -of_at91_clk_pll_get_characteristics(struct device_node *np) |
|---|
| 364 | | -{ |
|---|
| 365 | | - int i; |
|---|
| 366 | | - int offset; |
|---|
| 367 | | - u32 tmp; |
|---|
| 368 | | - int num_output; |
|---|
| 369 | | - u32 num_cells; |
|---|
| 370 | | - struct clk_range input; |
|---|
| 371 | | - struct clk_range *output; |
|---|
| 372 | | - u8 *out = NULL; |
|---|
| 373 | | - u16 *icpll = NULL; |
|---|
| 374 | | - struct clk_pll_characteristics *characteristics; |
|---|
| 375 | | - |
|---|
| 376 | | - if (of_at91_get_clk_range(np, "atmel,clk-input-range", &input)) |
|---|
| 377 | | - return NULL; |
|---|
| 378 | | - |
|---|
| 379 | | - if (of_property_read_u32(np, "#atmel,pll-clk-output-range-cells", |
|---|
| 380 | | - &num_cells)) |
|---|
| 381 | | - return NULL; |
|---|
| 382 | | - |
|---|
| 383 | | - if (num_cells < 2 || num_cells > 4) |
|---|
| 384 | | - return NULL; |
|---|
| 385 | | - |
|---|
| 386 | | - if (!of_get_property(np, "atmel,pll-clk-output-ranges", &tmp)) |
|---|
| 387 | | - return NULL; |
|---|
| 388 | | - num_output = tmp / (sizeof(u32) * num_cells); |
|---|
| 389 | | - |
|---|
| 390 | | - characteristics = kzalloc(sizeof(*characteristics), GFP_KERNEL); |
|---|
| 391 | | - if (!characteristics) |
|---|
| 392 | | - return NULL; |
|---|
| 393 | | - |
|---|
| 394 | | - output = kcalloc(num_output, sizeof(*output), GFP_KERNEL); |
|---|
| 395 | | - if (!output) |
|---|
| 396 | | - goto out_free_characteristics; |
|---|
| 397 | | - |
|---|
| 398 | | - if (num_cells > 2) { |
|---|
| 399 | | - out = kcalloc(num_output, sizeof(*out), GFP_KERNEL); |
|---|
| 400 | | - if (!out) |
|---|
| 401 | | - goto out_free_output; |
|---|
| 402 | | - } |
|---|
| 403 | | - |
|---|
| 404 | | - if (num_cells > 3) { |
|---|
| 405 | | - icpll = kcalloc(num_output, sizeof(*icpll), GFP_KERNEL); |
|---|
| 406 | | - if (!icpll) |
|---|
| 407 | | - goto out_free_output; |
|---|
| 408 | | - } |
|---|
| 409 | | - |
|---|
| 410 | | - for (i = 0; i < num_output; i++) { |
|---|
| 411 | | - offset = i * num_cells; |
|---|
| 412 | | - if (of_property_read_u32_index(np, |
|---|
| 413 | | - "atmel,pll-clk-output-ranges", |
|---|
| 414 | | - offset, &tmp)) |
|---|
| 415 | | - goto out_free_output; |
|---|
| 416 | | - output[i].min = tmp; |
|---|
| 417 | | - if (of_property_read_u32_index(np, |
|---|
| 418 | | - "atmel,pll-clk-output-ranges", |
|---|
| 419 | | - offset + 1, &tmp)) |
|---|
| 420 | | - goto out_free_output; |
|---|
| 421 | | - output[i].max = tmp; |
|---|
| 422 | | - |
|---|
| 423 | | - if (num_cells == 2) |
|---|
| 424 | | - continue; |
|---|
| 425 | | - |
|---|
| 426 | | - if (of_property_read_u32_index(np, |
|---|
| 427 | | - "atmel,pll-clk-output-ranges", |
|---|
| 428 | | - offset + 2, &tmp)) |
|---|
| 429 | | - goto out_free_output; |
|---|
| 430 | | - out[i] = tmp; |
|---|
| 431 | | - |
|---|
| 432 | | - if (num_cells == 3) |
|---|
| 433 | | - continue; |
|---|
| 434 | | - |
|---|
| 435 | | - if (of_property_read_u32_index(np, |
|---|
| 436 | | - "atmel,pll-clk-output-ranges", |
|---|
| 437 | | - offset + 3, &tmp)) |
|---|
| 438 | | - goto out_free_output; |
|---|
| 439 | | - icpll[i] = tmp; |
|---|
| 440 | | - } |
|---|
| 441 | | - |
|---|
| 442 | | - characteristics->input = input; |
|---|
| 443 | | - characteristics->num_output = num_output; |
|---|
| 444 | | - characteristics->output = output; |
|---|
| 445 | | - characteristics->out = out; |
|---|
| 446 | | - characteristics->icpll = icpll; |
|---|
| 447 | | - return characteristics; |
|---|
| 448 | | - |
|---|
| 449 | | -out_free_output: |
|---|
| 450 | | - kfree(icpll); |
|---|
| 451 | | - kfree(out); |
|---|
| 452 | | - kfree(output); |
|---|
| 453 | | -out_free_characteristics: |
|---|
| 454 | | - kfree(characteristics); |
|---|
| 455 | | - return NULL; |
|---|
| 456 | | -} |
|---|
| 457 | | - |
|---|
| 458 | | -static void __init |
|---|
| 459 | | -of_at91_clk_pll_setup(struct device_node *np, |
|---|
| 460 | | - const struct clk_pll_layout *layout) |
|---|
| 461 | | -{ |
|---|
| 462 | | - u32 id; |
|---|
| 463 | | - struct clk_hw *hw; |
|---|
| 464 | | - struct regmap *regmap; |
|---|
| 465 | | - const char *parent_name; |
|---|
| 466 | | - const char *name = np->name; |
|---|
| 467 | | - struct clk_pll_characteristics *characteristics; |
|---|
| 468 | | - |
|---|
| 469 | | - if (of_property_read_u32(np, "reg", &id)) |
|---|
| 470 | | - return; |
|---|
| 471 | | - |
|---|
| 472 | | - parent_name = of_clk_get_parent_name(np, 0); |
|---|
| 473 | | - |
|---|
| 474 | | - of_property_read_string(np, "clock-output-names", &name); |
|---|
| 475 | | - |
|---|
| 476 | | - regmap = syscon_node_to_regmap(of_get_parent(np)); |
|---|
| 477 | | - if (IS_ERR(regmap)) |
|---|
| 478 | | - return; |
|---|
| 479 | | - |
|---|
| 480 | | - characteristics = of_at91_clk_pll_get_characteristics(np); |
|---|
| 481 | | - if (!characteristics) |
|---|
| 482 | | - return; |
|---|
| 483 | | - |
|---|
| 484 | | - hw = at91_clk_register_pll(regmap, name, parent_name, id, layout, |
|---|
| 485 | | - characteristics); |
|---|
| 486 | | - if (IS_ERR(hw)) |
|---|
| 487 | | - goto out_free_characteristics; |
|---|
| 488 | | - |
|---|
| 489 | | - of_clk_add_hw_provider(np, of_clk_hw_simple_get, hw); |
|---|
| 490 | | - return; |
|---|
| 491 | | - |
|---|
| 492 | | -out_free_characteristics: |
|---|
| 493 | | - kfree(characteristics); |
|---|
| 494 | | -} |
|---|
| 495 | | - |
|---|
| 496 | | -static void __init of_at91rm9200_clk_pll_setup(struct device_node *np) |
|---|
| 497 | | -{ |
|---|
| 498 | | - of_at91_clk_pll_setup(np, &at91rm9200_pll_layout); |
|---|
| 499 | | -} |
|---|
| 500 | | -CLK_OF_DECLARE(at91rm9200_clk_pll, "atmel,at91rm9200-clk-pll", |
|---|
| 501 | | - of_at91rm9200_clk_pll_setup); |
|---|
| 502 | | - |
|---|
| 503 | | -static void __init of_at91sam9g45_clk_pll_setup(struct device_node *np) |
|---|
| 504 | | -{ |
|---|
| 505 | | - of_at91_clk_pll_setup(np, &at91sam9g45_pll_layout); |
|---|
| 506 | | -} |
|---|
| 507 | | -CLK_OF_DECLARE(at91sam9g45_clk_pll, "atmel,at91sam9g45-clk-pll", |
|---|
| 508 | | - of_at91sam9g45_clk_pll_setup); |
|---|
| 509 | | - |
|---|
| 510 | | -static void __init of_at91sam9g20_clk_pllb_setup(struct device_node *np) |
|---|
| 511 | | -{ |
|---|
| 512 | | - of_at91_clk_pll_setup(np, &at91sam9g20_pllb_layout); |
|---|
| 513 | | -} |
|---|
| 514 | | -CLK_OF_DECLARE(at91sam9g20_clk_pllb, "atmel,at91sam9g20-clk-pllb", |
|---|
| 515 | | - of_at91sam9g20_clk_pllb_setup); |
|---|
| 516 | | - |
|---|
| 517 | | -static void __init of_sama5d3_clk_pll_setup(struct device_node *np) |
|---|
| 518 | | -{ |
|---|
| 519 | | - of_at91_clk_pll_setup(np, &sama5d3_pll_layout); |
|---|
| 520 | | -} |
|---|
| 521 | | -CLK_OF_DECLARE(sama5d3_clk_pll, "atmel,sama5d3-clk-pll", |
|---|
| 522 | | - of_sama5d3_clk_pll_setup); |
|---|