aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBoris Brezillon <boris.brezillon@free-electrons.com>2017-01-27 04:10:37 -0500
committerAlexandre Belloni <alexandre.belloni@free-electrons.com>2017-01-27 04:15:56 -0500
commit987e079ecab7298cf5d5b43473d25bc31006e0e0 (patch)
tree64f9827c0605f6393dcca0cf38b7fd3e2e25e66b
parent427456e4772caf155c20604a60265dbc5a126267 (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.c46
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);