if (eb->is_42x && (cs_index > 7)) {
dev_err(eb->dev, "invalid chipselect %u, we only support 0-7\n",
cs_index); return;
} if (eb->is_43x && (cs_index > 3)) {
dev_err(eb->dev, "invalid chipselect %u, we only support 0-3\n",
cs_index); return;
}
/* Several chip selects can be joined into one device */ if (cs_size > IXP4XX_EXP_STRIDE)
cur_cssize = IXP4XX_EXP_STRIDE; else
cur_cssize = cs_size;
/* * The following will read/modify/write the configuration for one * chipselect, attempting to leave the boot defaults in place unless * something is explicitly defined.
*/
regmap_read(eb->rmap, IXP4XX_EXP_TIMING_CS0 +
IXP4XX_EXP_TIMING_STRIDE * cs_index, &cs_cfg);
dev_info(eb->dev, "CS%d at %#08x, size %#08x, config before: %#08x\n",
cs_index, eb->bus_base + IXP4XX_EXP_STRIDE * cs_index,
cur_cssize, cs_cfg);
for (i = 0; i < ARRAY_SIZE(ixp4xx_exp_tim_props); i++) { conststruct ixp4xx_exp_tim_prop *ip = &ixp4xx_exp_tim_props[i];
/* All are regular u32 values */
ret = of_property_read_u32(np, ip->prop, &val); if (ret) continue;
/* Handle bools (single bits) first */ if (ip->max == 1) { if (val)
cs_cfg |= ip->mask; else
cs_cfg &= ~ip->mask;
dev_info(eb->dev, "CS%d %s %s\n", cs_index,
val ? "enabled" : "disabled",
ip->prop); continue;
}
if (val > ip->max) {
dev_err(eb->dev, "CS%d too high value for %s: %u, capped at %u\n",
cs_index, ip->prop, val, ip->max);
val = ip->max;
} /* This assumes max value fills all the assigned bits (and it does) */
cs_cfg &= ~ip->mask;
cs_cfg |= (val << ip->shift);
dev_info(eb->dev, "CS%d set %s to %u\n", cs_index, ip->prop, val);
}
ret = of_property_read_u32(np, "intel,ixp4xx-eb-cycle-type", &val); if (!ret) { if (val > 3) {
dev_err(eb->dev, "illegal cycle type %d\n", val); return;
}
dev_info(eb->dev, "CS%d set cycle type %d\n", cs_index, val);
cs_cfg &= ~IXP4XX_EXP_CYC_TYPE_MASK;
cs_cfg |= val << IXP4XX_EXP_CYC_TYPE_SHIFT;
}
if (eb->is_43x) { /* Should always be zero */
cs_cfg &= ~IXP4XX_EXP_WORD; /* * This bit for Intel strata flash is currently unused, but let's * report it if we find one.
*/ if (cs_cfg & IXP43X_EXP_SYNC_INTEL)
dev_info(eb->dev, "claims to be Intel strata flash\n");
}
cs_cfg |= IXP4XX_EXP_CS_EN;
regmap_write(eb->rmap,
IXP4XX_EXP_TIMING_CS0 + IXP4XX_EXP_TIMING_STRIDE * cs_index,
cs_cfg);
dev_info(eb->dev, "CS%d wrote %#08x into CS config\n", cs_index, cs_cfg);
/* * If several chip selects are joined together into one big * device area, we call ourselves recursively for each successive * chip select. For a 32MB flash chip this results in two calls * for example.
*/ if (cs_size > IXP4XX_EXP_STRIDE)
ixp4xx_exp_setup_chipselect(eb, np,
cs_index + 1,
cs_size - IXP4XX_EXP_STRIDE);
}
staticvoid ixp4xx_exp_setup_child(struct ixp4xx_eb *eb, struct device_node *np)
{
u32 cs_sizes[IXP4XX_EXP_NUM_CS]; int num_regs;
u32 csindex;
u32 cssize; int ret; int i;
num_regs = of_property_count_elems_of_size(np, "reg", IXP4XX_OF_REG_SIZE); if (num_regs <= 0) return;
dev_dbg(eb->dev, "child %s has %d register sets\n",
of_node_full_name(np), num_regs);
for (i = 0; i < num_regs; i++) {
u32 rbase, rsize;
ret = of_property_read_u32_index(np, "reg",
i * IXP4XX_OF_REG_SIZE, &csindex); if (ret) break;
ret = of_property_read_u32_index(np, "reg",
i * IXP4XX_OF_REG_SIZE + 1, &rbase); if (ret) break;
ret = of_property_read_u32_index(np, "reg",
i * IXP4XX_OF_REG_SIZE + 2, &rsize); if (ret) break;
if (csindex >= IXP4XX_EXP_NUM_CS) {
dev_err(eb->dev, "illegal CS %d\n", csindex); continue;
} /* * The memory window always starts from CS base so we need to add * the start and size to get to the size from the start of the CS * base. For example if CS0 is at 0x50000000 and the reg is * <0 0xe40000 0x40000> the size is e80000. * * Roof this if we have several regs setting the same CS.
*/
cssize = rbase + rsize;
dev_dbg(eb->dev, "CS%d size %#08x\n", csindex, cssize); if (cs_sizes[csindex] < cssize)
cs_sizes[csindex] = cssize;
}
for (csindex = 0; csindex < IXP4XX_EXP_NUM_CS; csindex++) {
cssize = cs_sizes[csindex]; if (!cssize) continue; /* Just this one, so set it up and return */
ixp4xx_exp_setup_chipselect(eb, np, csindex, cssize);
}
}
eb->rmap = syscon_node_to_regmap(np); if (IS_ERR(eb->rmap)) return dev_err_probe(dev, PTR_ERR(eb->rmap), "no regmap\n");
/* We check that the regmap work only on first read */
ret = regmap_read(eb->rmap, IXP4XX_EXP_CNFG0, &val); if (ret) return dev_err_probe(dev, ret, "cannot read regmap\n"); if (val & IXP4XX_EXP_CNFG0_MEM_MAP)
eb->bus_base = IXP4XX_EXP_BOOT_BASE; else
eb->bus_base = IXP4XX_EXP_NORMAL_BASE;
dev_info(dev, "expansion bus at %08x\n", eb->bus_base);
if (eb->is_43x) { /* Check some fuses */
regmap_read(eb->rmap, IXP43X_EXP_UNIT_FUSE_RESET, &val); switch (FIELD_GET(IXP43x_EXP_FUSE_SPEED_MASK, val)) { case 0:
dev_info(dev, "IXP43x at 533 MHz\n"); break; case 1:
dev_info(dev, "IXP43x at 400 MHz\n"); break; case 2:
dev_info(dev, "IXP43x at 667 MHz\n"); break; default:
dev_info(dev, "IXP43x unknown speed\n"); break;
}
}
/* Walk over the child nodes and see what chipselects we use */
for_each_available_child_of_node(np, child) {
ixp4xx_exp_setup_child(eb, child); /* We have at least one child */
have_children = true;
}
if (have_children) return of_platform_default_populate(np, NULL, dev);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.