diff options
author | Boris Brezillon <boris.brezillon@free-electrons.com> | 2017-01-27 04:10:37 -0500 |
---|---|---|
committer | Alexandre Belloni <alexandre.belloni@free-electrons.com> | 2017-01-27 04:15:56 -0500 |
commit | 987e079ecab7298cf5d5b43473d25bc31006e0e0 (patch) | |
tree | 64f9827c0605f6393dcca0cf38b7fd3e2e25e66b | |
parent | 427456e4772caf155c20604a60265dbc5a126267 (diff) |
memory: atmel-ebi: Properly handle multiple reference to the same CS
Some devices are defining several sub-ranges within the same CS iomem
range. In this case, we should not duplicate the EBI device config.
Signed-off-by: Boris Brezillon <boris.brezillon@free-electrons.com>
Signed-off-by: Alexandre Belloni <alexandre.belloni@free-electrons.com>
-rw-r--r-- | drivers/memory/atmel-ebi.c | 46 |
1 files changed, 27 insertions, 19 deletions
diff --git a/drivers/memory/atmel-ebi.c b/drivers/memory/atmel-ebi.c index 2c4c9a1978bc..46657eaaedf6 100644 --- a/drivers/memory/atmel-ebi.c +++ b/drivers/memory/atmel-ebi.c | |||
@@ -449,12 +449,31 @@ static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np, | |||
449 | struct at91_ebi_dev_config conf = { }; | 449 | struct at91_ebi_dev_config conf = { }; |
450 | struct device *dev = ebi->dev; | 450 | struct device *dev = ebi->dev; |
451 | struct at91_ebi_dev *ebid; | 451 | struct at91_ebi_dev *ebid; |
452 | int ret, numcs = 0, i; | 452 | unsigned long cslines = 0; |
453 | int ret, numcs = 0, nentries, i; | ||
453 | bool apply = false; | 454 | bool apply = false; |
455 | u32 cs; | ||
454 | 456 | ||
455 | numcs = of_property_count_elems_of_size(np, "reg", | 457 | nentries = of_property_count_elems_of_size(np, "reg", |
456 | reg_cells * sizeof(u32)); | 458 | reg_cells * sizeof(u32)); |
457 | if (numcs <= 0) { | 459 | for (i = 0; i < nentries; i++) { |
460 | ret = of_property_read_u32_index(np, "reg", i * reg_cells, | ||
461 | &cs); | ||
462 | if (ret) | ||
463 | return ret; | ||
464 | |||
465 | if (cs >= AT91_MATRIX_EBI_NUM_CS || | ||
466 | !(ebi->caps->available_cs & BIT(cs))) { | ||
467 | dev_err(dev, "invalid reg property in %s\n", | ||
468 | np->full_name); | ||
469 | return -EINVAL; | ||
470 | } | ||
471 | |||
472 | if (!test_and_set_bit(cs, &cslines)) | ||
473 | numcs++; | ||
474 | } | ||
475 | |||
476 | if (!numcs) { | ||
458 | dev_err(dev, "invalid reg property in %s\n", np->full_name); | 477 | dev_err(dev, "invalid reg property in %s\n", np->full_name); |
459 | return -EINVAL; | 478 | return -EINVAL; |
460 | } | 479 | } |
@@ -473,21 +492,8 @@ static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np, | |||
473 | else if (ret) | 492 | else if (ret) |
474 | apply = true; | 493 | apply = true; |
475 | 494 | ||
476 | for (i = 0; i < numcs; i++) { | 495 | i = 0; |
477 | u32 cs; | 496 | for_each_set_bit(cs, &cslines, AT91_MATRIX_EBI_NUM_CS) { |
478 | |||
479 | ret = of_property_read_u32_index(np, "reg", i * reg_cells, | ||
480 | &cs); | ||
481 | if (ret) | ||
482 | return ret; | ||
483 | |||
484 | if (cs > AT91_MATRIX_EBI_NUM_CS || | ||
485 | !(ebi->caps->available_cs & BIT(cs))) { | ||
486 | dev_err(dev, "invalid reg property in %s\n", | ||
487 | np->full_name); | ||
488 | return -EINVAL; | ||
489 | } | ||
490 | |||
491 | ebid->configs[i].cs = cs; | 497 | ebid->configs[i].cs = cs; |
492 | 498 | ||
493 | if (apply) { | 499 | if (apply) { |
@@ -506,6 +512,8 @@ static int at91_ebi_dev_setup(struct at91_ebi *ebi, struct device_node *np, | |||
506 | if (ebi->ebi_csa && apply) | 512 | if (ebi->ebi_csa && apply) |
507 | regmap_field_update_bits(ebi->ebi_csa, | 513 | regmap_field_update_bits(ebi->ebi_csa, |
508 | BIT(cs), 0); | 514 | BIT(cs), 0); |
515 | |||
516 | i++; | ||
509 | } | 517 | } |
510 | 518 | ||
511 | list_add_tail(&ebid->node, &ebi->devs); | 519 | list_add_tail(&ebid->node, &ebi->devs); |