static int __init __uniphier_cache_init()

in mm/cache-uniphier.c [313:449]


static int __init __uniphier_cache_init(struct device_node *np,
					unsigned int *cache_level)
{
	struct uniphier_cache_data *data;
	u32 level, cache_size;
	struct device_node *next_np;
	int ret = 0;

	if (!of_match_node(uniphier_cache_match, np)) {
		pr_err("L%d: not compatible with uniphier cache\n",
		       *cache_level);
		return -EINVAL;
	}

	if (of_property_read_u32(np, "cache-level", &level)) {
		pr_err("L%d: cache-level is not specified\n", *cache_level);
		return -EINVAL;
	}

	if (level != *cache_level) {
		pr_err("L%d: cache-level is unexpected value %d\n",
		       *cache_level, level);
		return -EINVAL;
	}

	if (!of_property_read_bool(np, "cache-unified")) {
		pr_err("L%d: cache-unified is not specified\n", *cache_level);
		return -EINVAL;
	}

	data = kzalloc(sizeof(*data), GFP_KERNEL);
	if (!data)
		return -ENOMEM;

	if (of_property_read_u32(np, "cache-line-size", &data->line_size) ||
	    !is_power_of_2(data->line_size)) {
		pr_err("L%d: cache-line-size is unspecified or invalid\n",
		       *cache_level);
		ret = -EINVAL;
		goto err;
	}

	if (of_property_read_u32(np, "cache-sets", &data->nsets) ||
	    !is_power_of_2(data->nsets)) {
		pr_err("L%d: cache-sets is unspecified or invalid\n",
		       *cache_level);
		ret = -EINVAL;
		goto err;
	}

	if (of_property_read_u32(np, "cache-size", &cache_size) ||
	    cache_size == 0 || cache_size % (data->nsets * data->line_size)) {
		pr_err("L%d: cache-size is unspecified or invalid\n",
		       *cache_level);
		ret = -EINVAL;
		goto err;
	}

	data->way_mask = GENMASK(cache_size / data->nsets / data->line_size - 1,
				 0);

	data->ctrl_base = of_iomap(np, 0);
	if (!data->ctrl_base) {
		pr_err("L%d: failed to map control register\n", *cache_level);
		ret = -ENOMEM;
		goto err;
	}

	data->rev_base = of_iomap(np, 1);
	if (!data->rev_base) {
		pr_err("L%d: failed to map revision register\n", *cache_level);
		ret = -ENOMEM;
		goto err;
	}

	data->op_base = of_iomap(np, 2);
	if (!data->op_base) {
		pr_err("L%d: failed to map operation register\n", *cache_level);
		ret = -ENOMEM;
		goto err;
	}

	data->way_ctrl_base = data->ctrl_base + 0xc00;

	if (*cache_level == 2) {
		u32 revision = readl(data->rev_base + UNIPHIER_SSCID);
		/*
		 * The size of range operation is limited to (1 << 22) or less
		 * for PH-sLD8 or older SoCs.
		 */
		if (revision <= 0x16)
			data->range_op_max_size = (u32)1 << 22;

		/*
		 * Unfortunatly, the offset address of active way control base
		 * varies from SoC to SoC.
		 */
		switch (revision) {
		case 0x11:	/* sLD3 */
			data->way_ctrl_base = data->ctrl_base + 0x870;
			break;
		case 0x12:	/* LD4 */
		case 0x16:	/* sld8 */
			data->way_ctrl_base = data->ctrl_base + 0x840;
			break;
		default:
			break;
		}
	}

	data->range_op_max_size -= data->line_size;

	INIT_LIST_HEAD(&data->list);
	list_add_tail(&data->list, &uniphier_cache_list); /* no mutex */

	/*
	 * OK, this level has been successfully initialized.  Look for the next
	 * level cache.  Do not roll back even if the initialization of the
	 * next level cache fails because we want to continue with available
	 * cache levels.
	 */
	next_np = of_find_next_cache_node(np);
	if (next_np) {
		(*cache_level)++;
		ret = __uniphier_cache_init(next_np, cache_level);
	}
	of_node_put(next_np);

	return ret;
err:
	iounmap(data->op_base);
	iounmap(data->rev_base);
	iounmap(data->ctrl_base);
	kfree(data);

	return ret;
}