static void ixp4xx_exp_setup_chipselect()

in intel-ixp4xx-eb.c [156:283]


static void ixp4xx_exp_setup_chipselect(struct ixp4xx_eb *eb,
					struct device_node *np,
					u32 cs_index,
					u32 cs_size)
{
	u32 cs_cfg;
	u32 val;
	u32 cur_cssize;
	u32 cs_order;
	int ret;
	int i;

	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);

	/* Size set-up first align to 2^9 .. 2^24 */
	cur_cssize = roundup_pow_of_two(cur_cssize);
	if (cur_cssize < 512)
		cur_cssize = 512;
	cs_order = ilog2(cur_cssize);
	if (cs_order < 9 || cs_order > 24) {
		dev_err(eb->dev, "illegal size order %d\n", cs_order);
		return;
	}
	dev_dbg(eb->dev, "CS%d size order: %d\n", cs_index, cs_order);
	cs_cfg &= ~(IXP4XX_EXP_SIZE_MASK);
	cs_cfg |= ((cs_order - 9) << IXP4XX_EXP_SIZE_SHIFT);

	for (i = 0; i < ARRAY_SIZE(ixp4xx_exp_tim_props); i++) {
		const struct 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_42x)
		cs_cfg &= ~IXP42X_RESERVED;
	if (eb->is_43x) {
		cs_cfg &= ~IXP43X_RESERVED;
		/*
		 * 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);
}