.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0 |
---|
1 | 2 | /* |
---|
2 | 3 | * EBI driver for Atmel chips |
---|
3 | 4 | * inspired by the fsl weim bus driver |
---|
4 | 5 | * |
---|
5 | 6 | * Copyright (C) 2013 Jean-Jacques Hiblot <jjhiblot@traphandler.com> |
---|
6 | | - * |
---|
7 | | - * This file is licensed under the terms of the GNU General Public |
---|
8 | | - * License version 2. This program is licensed "as is" without any |
---|
9 | | - * warranty of any kind, whether express or implied. |
---|
10 | 7 | */ |
---|
11 | 8 | |
---|
12 | 9 | #include <linux/clk.h> |
---|
.. | .. |
---|
17 | 14 | #include <linux/init.h> |
---|
18 | 15 | #include <linux/of_device.h> |
---|
19 | 16 | #include <linux/regmap.h> |
---|
| 17 | +#include <soc/at91/atmel-sfr.h> |
---|
| 18 | + |
---|
| 19 | +#define AT91_EBI_NUM_CS 8 |
---|
20 | 20 | |
---|
21 | 21 | struct atmel_ebi_dev_config { |
---|
22 | 22 | int cs; |
---|
.. | .. |
---|
36 | 36 | struct atmel_ebi_caps { |
---|
37 | 37 | unsigned int available_cs; |
---|
38 | 38 | unsigned int ebi_csa_offs; |
---|
| 39 | + const char *regmap_name; |
---|
39 | 40 | void (*get_config)(struct atmel_ebi_dev *ebid, |
---|
40 | 41 | struct atmel_ebi_dev_config *conf); |
---|
41 | 42 | int (*xlate_config)(struct atmel_ebi_dev *ebid, |
---|
.. | .. |
---|
47 | 48 | |
---|
48 | 49 | struct atmel_ebi { |
---|
49 | 50 | struct clk *clk; |
---|
50 | | - struct regmap *matrix; |
---|
| 51 | + struct regmap *regmap; |
---|
51 | 52 | struct { |
---|
52 | 53 | struct regmap *regmap; |
---|
53 | 54 | struct clk *clk; |
---|
.. | .. |
---|
312 | 313 | if (ret) |
---|
313 | 314 | return ret; |
---|
314 | 315 | |
---|
315 | | - if (cs >= AT91_MATRIX_EBI_NUM_CS || |
---|
| 316 | + if (cs >= AT91_EBI_NUM_CS || |
---|
316 | 317 | !(ebi->caps->available_cs & BIT(cs))) { |
---|
317 | 318 | dev_err(dev, "invalid reg property in %pOF\n", np); |
---|
318 | 319 | return -EINVAL; |
---|
.. | .. |
---|
327 | 328 | return -EINVAL; |
---|
328 | 329 | } |
---|
329 | 330 | |
---|
330 | | - ebid = devm_kzalloc(ebi->dev, |
---|
331 | | - sizeof(*ebid) + (numcs * sizeof(*ebid->configs)), |
---|
| 331 | + ebid = devm_kzalloc(ebi->dev, struct_size(ebid, configs, numcs), |
---|
332 | 332 | GFP_KERNEL); |
---|
333 | 333 | if (!ebid) |
---|
334 | 334 | return -ENOMEM; |
---|
.. | .. |
---|
343 | 343 | apply = true; |
---|
344 | 344 | |
---|
345 | 345 | i = 0; |
---|
346 | | - for_each_set_bit(cs, &cslines, AT91_MATRIX_EBI_NUM_CS) { |
---|
| 346 | + for_each_set_bit(cs, &cslines, AT91_EBI_NUM_CS) { |
---|
347 | 347 | ebid->configs[i].cs = cs; |
---|
348 | 348 | |
---|
349 | 349 | if (apply) { |
---|
.. | .. |
---|
358 | 358 | * one "atmel,smc-" property is present. |
---|
359 | 359 | */ |
---|
360 | 360 | if (ebi->caps->ebi_csa_offs && apply) |
---|
361 | | - regmap_update_bits(ebi->matrix, |
---|
| 361 | + regmap_update_bits(ebi->regmap, |
---|
362 | 362 | ebi->caps->ebi_csa_offs, |
---|
363 | 363 | BIT(cs), 0); |
---|
364 | 364 | |
---|
.. | .. |
---|
373 | 373 | static const struct atmel_ebi_caps at91sam9260_ebi_caps = { |
---|
374 | 374 | .available_cs = 0xff, |
---|
375 | 375 | .ebi_csa_offs = AT91SAM9260_MATRIX_EBICSA, |
---|
| 376 | + .regmap_name = "atmel,matrix", |
---|
376 | 377 | .get_config = at91sam9_ebi_get_config, |
---|
377 | 378 | .xlate_config = atmel_ebi_xslate_smc_config, |
---|
378 | 379 | .apply_config = at91sam9_ebi_apply_config, |
---|
.. | .. |
---|
381 | 382 | static const struct atmel_ebi_caps at91sam9261_ebi_caps = { |
---|
382 | 383 | .available_cs = 0xff, |
---|
383 | 384 | .ebi_csa_offs = AT91SAM9261_MATRIX_EBICSA, |
---|
| 385 | + .regmap_name = "atmel,matrix", |
---|
384 | 386 | .get_config = at91sam9_ebi_get_config, |
---|
385 | 387 | .xlate_config = atmel_ebi_xslate_smc_config, |
---|
386 | 388 | .apply_config = at91sam9_ebi_apply_config, |
---|
.. | .. |
---|
389 | 391 | static const struct atmel_ebi_caps at91sam9263_ebi0_caps = { |
---|
390 | 392 | .available_cs = 0x3f, |
---|
391 | 393 | .ebi_csa_offs = AT91SAM9263_MATRIX_EBI0CSA, |
---|
| 394 | + .regmap_name = "atmel,matrix", |
---|
392 | 395 | .get_config = at91sam9_ebi_get_config, |
---|
393 | 396 | .xlate_config = atmel_ebi_xslate_smc_config, |
---|
394 | 397 | .apply_config = at91sam9_ebi_apply_config, |
---|
.. | .. |
---|
397 | 400 | static const struct atmel_ebi_caps at91sam9263_ebi1_caps = { |
---|
398 | 401 | .available_cs = 0x7, |
---|
399 | 402 | .ebi_csa_offs = AT91SAM9263_MATRIX_EBI1CSA, |
---|
| 403 | + .regmap_name = "atmel,matrix", |
---|
400 | 404 | .get_config = at91sam9_ebi_get_config, |
---|
401 | 405 | .xlate_config = atmel_ebi_xslate_smc_config, |
---|
402 | 406 | .apply_config = at91sam9_ebi_apply_config, |
---|
.. | .. |
---|
405 | 409 | static const struct atmel_ebi_caps at91sam9rl_ebi_caps = { |
---|
406 | 410 | .available_cs = 0x3f, |
---|
407 | 411 | .ebi_csa_offs = AT91SAM9RL_MATRIX_EBICSA, |
---|
| 412 | + .regmap_name = "atmel,matrix", |
---|
408 | 413 | .get_config = at91sam9_ebi_get_config, |
---|
409 | 414 | .xlate_config = atmel_ebi_xslate_smc_config, |
---|
410 | 415 | .apply_config = at91sam9_ebi_apply_config, |
---|
.. | .. |
---|
413 | 418 | static const struct atmel_ebi_caps at91sam9g45_ebi_caps = { |
---|
414 | 419 | .available_cs = 0x3f, |
---|
415 | 420 | .ebi_csa_offs = AT91SAM9G45_MATRIX_EBICSA, |
---|
| 421 | + .regmap_name = "atmel,matrix", |
---|
416 | 422 | .get_config = at91sam9_ebi_get_config, |
---|
417 | 423 | .xlate_config = atmel_ebi_xslate_smc_config, |
---|
418 | 424 | .apply_config = at91sam9_ebi_apply_config, |
---|
.. | .. |
---|
421 | 427 | static const struct atmel_ebi_caps at91sam9x5_ebi_caps = { |
---|
422 | 428 | .available_cs = 0x3f, |
---|
423 | 429 | .ebi_csa_offs = AT91SAM9X5_MATRIX_EBICSA, |
---|
| 430 | + .regmap_name = "atmel,matrix", |
---|
424 | 431 | .get_config = at91sam9_ebi_get_config, |
---|
425 | 432 | .xlate_config = atmel_ebi_xslate_smc_config, |
---|
426 | 433 | .apply_config = at91sam9_ebi_apply_config, |
---|
.. | .. |
---|
431 | 438 | .get_config = sama5_ebi_get_config, |
---|
432 | 439 | .xlate_config = atmel_ebi_xslate_smc_config, |
---|
433 | 440 | .apply_config = sama5_ebi_apply_config, |
---|
| 441 | +}; |
---|
| 442 | + |
---|
| 443 | +static const struct atmel_ebi_caps sam9x60_ebi_caps = { |
---|
| 444 | + .available_cs = 0x3f, |
---|
| 445 | + .ebi_csa_offs = AT91_SFR_CCFG_EBICSA, |
---|
| 446 | + .regmap_name = "microchip,sfr", |
---|
| 447 | + .get_config = at91sam9_ebi_get_config, |
---|
| 448 | + .xlate_config = atmel_ebi_xslate_smc_config, |
---|
| 449 | + .apply_config = at91sam9_ebi_apply_config, |
---|
434 | 450 | }; |
---|
435 | 451 | |
---|
436 | 452 | static const struct of_device_id atmel_ebi_id_table[] = { |
---|
.. | .. |
---|
465 | 481 | { |
---|
466 | 482 | .compatible = "atmel,sama5d3-ebi", |
---|
467 | 483 | .data = &sama5d3_ebi_caps, |
---|
| 484 | + }, |
---|
| 485 | + { |
---|
| 486 | + .compatible = "microchip,sam9x60-ebi", |
---|
| 487 | + .data = &sam9x60_ebi_caps, |
---|
468 | 488 | }, |
---|
469 | 489 | { /* sentinel */ } |
---|
470 | 490 | }; |
---|
.. | .. |
---|
524 | 544 | smc_np = of_parse_phandle(dev->of_node, "atmel,smc", 0); |
---|
525 | 545 | |
---|
526 | 546 | ebi->smc.regmap = syscon_node_to_regmap(smc_np); |
---|
527 | | - if (IS_ERR(ebi->smc.regmap)) |
---|
528 | | - return PTR_ERR(ebi->smc.regmap); |
---|
| 547 | + if (IS_ERR(ebi->smc.regmap)) { |
---|
| 548 | + ret = PTR_ERR(ebi->smc.regmap); |
---|
| 549 | + goto put_node; |
---|
| 550 | + } |
---|
529 | 551 | |
---|
530 | 552 | ebi->smc.layout = atmel_hsmc_get_reg_layout(smc_np); |
---|
531 | | - if (IS_ERR(ebi->smc.layout)) |
---|
532 | | - return PTR_ERR(ebi->smc.layout); |
---|
| 553 | + if (IS_ERR(ebi->smc.layout)) { |
---|
| 554 | + ret = PTR_ERR(ebi->smc.layout); |
---|
| 555 | + goto put_node; |
---|
| 556 | + } |
---|
533 | 557 | |
---|
534 | 558 | ebi->smc.clk = of_clk_get(smc_np, 0); |
---|
535 | 559 | if (IS_ERR(ebi->smc.clk)) { |
---|
536 | | - if (PTR_ERR(ebi->smc.clk) != -ENOENT) |
---|
537 | | - return PTR_ERR(ebi->smc.clk); |
---|
| 560 | + if (PTR_ERR(ebi->smc.clk) != -ENOENT) { |
---|
| 561 | + ret = PTR_ERR(ebi->smc.clk); |
---|
| 562 | + goto put_node; |
---|
| 563 | + } |
---|
538 | 564 | |
---|
539 | 565 | ebi->smc.clk = NULL; |
---|
540 | 566 | } |
---|
| 567 | + of_node_put(smc_np); |
---|
541 | 568 | ret = clk_prepare_enable(ebi->smc.clk); |
---|
542 | 569 | if (ret) |
---|
543 | 570 | return ret; |
---|
544 | 571 | |
---|
545 | 572 | /* |
---|
546 | 573 | * The sama5d3 does not provide an EBICSA register and thus does need |
---|
547 | | - * to access the matrix registers. |
---|
| 574 | + * to access it. |
---|
548 | 575 | */ |
---|
549 | 576 | if (ebi->caps->ebi_csa_offs) { |
---|
550 | | - ebi->matrix = |
---|
551 | | - syscon_regmap_lookup_by_phandle(np, "atmel,matrix"); |
---|
552 | | - if (IS_ERR(ebi->matrix)) |
---|
553 | | - return PTR_ERR(ebi->matrix); |
---|
| 577 | + ebi->regmap = |
---|
| 578 | + syscon_regmap_lookup_by_phandle(np, |
---|
| 579 | + ebi->caps->regmap_name); |
---|
| 580 | + if (IS_ERR(ebi->regmap)) |
---|
| 581 | + return PTR_ERR(ebi->regmap); |
---|
554 | 582 | } |
---|
555 | 583 | |
---|
556 | 584 | ret = of_property_read_u32(np, "#address-cells", &val); |
---|
.. | .. |
---|
587 | 615 | } |
---|
588 | 616 | |
---|
589 | 617 | return of_platform_populate(np, NULL, NULL, dev); |
---|
| 618 | + |
---|
| 619 | +put_node: |
---|
| 620 | + of_node_put(smc_np); |
---|
| 621 | + return ret; |
---|
590 | 622 | } |
---|
591 | 623 | |
---|
592 | 624 | static __maybe_unused int atmel_ebi_resume(struct device *dev) |
---|