Lines Matching +full:uniphier +full:- +full:system +full:- +full:cache
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2015-2016 Socionext Inc.
7 #define pr_fmt(fmt) "uniphier: " fmt
15 #include <asm/hardware/cache-uniphier.h>
21 #define UNIPHIER_SSCC_ACT BIT(19) /* Inst-Data separate */
23 #define UNIPHIER_SSCC_PRD BIT(17) /* enable pre-fetch */
24 #define UNIPHIER_SSCC_ON BIT(0) /* enable cache */
32 #define UNIPHIER_SSCOPE 0x244 /* Cache Operation Primitive Entry */
37 #define UNIPHIER_SSCOPE_CM_FLUSH_PREFETCH 0x9 /* flush p-fetch buf */
38 #define UNIPHIER_SSCOQM 0x248 /* Cache Operation Queue Mode */
46 #define UNIPHIER_SSCOQAD 0x24c /* Cache Operation Queue Address */
47 #define UNIPHIER_SSCOQSZ 0x250 /* Cache Operation Queue Size */
48 #define UNIPHIER_SSCOPPQSEF 0x25c /* Cache Operation Queue Set Complete*/
51 #define UNIPHIER_SSCOLPQS 0x260 /* Cache Operation Queue Status */
61 * struct uniphier_cache_data - UniPhier outer cache specific data
72 * @list: list node to include this level in the whole cache hierarchy
87 * List of the whole outer cache hierarchy. This list is only modified during
93 * __uniphier_cache_sync - perform a sync point for a particular cache level
95 * @data: cache controller specific data
101 data->op_base + UNIPHIER_SSCOPE); in __uniphier_cache_sync()
103 readl_relaxed(data->op_base + UNIPHIER_SSCOPE); in __uniphier_cache_sync()
107 * __uniphier_cache_maint_common - run a queue operation for a particular level
109 * @data: cache controller specific data
112 * @operation: flags to specify the desired cache operation
124 * [1] This outer cache controller is able to accept maintenance in __uniphier_cache_maint_common()
125 * operations from multiple CPUs at a time in an SMP system; if a in __uniphier_cache_maint_common()
134 * [2] The cache command registers, UNIPHIER_{SSCOQM, SSCOQAD, SSCOQSZ, in __uniphier_cache_maint_common()
147 writel_relaxed(UNIPHIER_SSCOLPQS_EF, data->op_base + UNIPHIER_SSCOLPQS); in __uniphier_cache_maint_common()
150 /* set cache operation */ in __uniphier_cache_maint_common()
152 data->op_base + UNIPHIER_SSCOQM); in __uniphier_cache_maint_common()
156 writel_relaxed(start, data->op_base + UNIPHIER_SSCOQAD); in __uniphier_cache_maint_common()
157 writel_relaxed(size, data->op_base + UNIPHIER_SSCOQSZ); in __uniphier_cache_maint_common()
159 } while (unlikely(readl_relaxed(data->op_base + UNIPHIER_SSCOPPQSEF) & in __uniphier_cache_maint_common()
163 while (likely(readl_relaxed(data->op_base + UNIPHIER_SSCOLPQS) != in __uniphier_cache_maint_common()
187 * perform a cache operation for the first cache-line in __uniphier_cache_maint_range()
189 start = start & ~(data->line_size - 1); in __uniphier_cache_maint_range()
191 size = end - start; in __uniphier_cache_maint_range()
193 if (unlikely(size >= (unsigned long)(-data->line_size))) { in __uniphier_cache_maint_range()
194 /* this means cache operation for all range */ in __uniphier_cache_maint_range()
201 * perform a cache operation for the last cache-line in __uniphier_cache_maint_range()
203 size = ALIGN(size, data->line_size); in __uniphier_cache_maint_range()
207 data->range_op_max_size); in __uniphier_cache_maint_range()
213 size -= chunk_size; in __uniphier_cache_maint_range()
226 writel_relaxed(val, data->ctrl_base + UNIPHIER_SSCC); in __uniphier_cache_enable()
235 writel_relaxed(data->way_mask, data->way_ctrl_base + 4 * cpu); in __uniphier_cache_set_active_ways()
311 { .compatible = "socionext,uniphier-system-cache" },
324 pr_err("L%d: not compatible with uniphier cache\n", in __uniphier_cache_init()
326 return -EINVAL; in __uniphier_cache_init()
329 if (of_property_read_u32(np, "cache-level", &level)) { in __uniphier_cache_init()
330 pr_err("L%d: cache-level is not specified\n", *cache_level); in __uniphier_cache_init()
331 return -EINVAL; in __uniphier_cache_init()
335 pr_err("L%d: cache-level is unexpected value %d\n", in __uniphier_cache_init()
337 return -EINVAL; in __uniphier_cache_init()
340 if (!of_property_read_bool(np, "cache-unified")) { in __uniphier_cache_init()
341 pr_err("L%d: cache-unified is not specified\n", *cache_level); in __uniphier_cache_init()
342 return -EINVAL; in __uniphier_cache_init()
347 return -ENOMEM; in __uniphier_cache_init()
349 if (of_property_read_u32(np, "cache-line-size", &data->line_size) || in __uniphier_cache_init()
350 !is_power_of_2(data->line_size)) { in __uniphier_cache_init()
351 pr_err("L%d: cache-line-size is unspecified or invalid\n", in __uniphier_cache_init()
353 ret = -EINVAL; in __uniphier_cache_init()
357 if (of_property_read_u32(np, "cache-sets", &data->nsets) || in __uniphier_cache_init()
358 !is_power_of_2(data->nsets)) { in __uniphier_cache_init()
359 pr_err("L%d: cache-sets is unspecified or invalid\n", in __uniphier_cache_init()
361 ret = -EINVAL; in __uniphier_cache_init()
365 if (of_property_read_u32(np, "cache-size", &cache_size) || in __uniphier_cache_init()
366 cache_size == 0 || cache_size % (data->nsets * data->line_size)) { in __uniphier_cache_init()
367 pr_err("L%d: cache-size is unspecified or invalid\n", in __uniphier_cache_init()
369 ret = -EINVAL; in __uniphier_cache_init()
373 data->way_mask = GENMASK(cache_size / data->nsets / data->line_size - 1, in __uniphier_cache_init()
376 data->ctrl_base = of_iomap(np, 0); in __uniphier_cache_init()
377 if (!data->ctrl_base) { in __uniphier_cache_init()
379 ret = -ENOMEM; in __uniphier_cache_init()
383 data->rev_base = of_iomap(np, 1); in __uniphier_cache_init()
384 if (!data->rev_base) { in __uniphier_cache_init()
386 ret = -ENOMEM; in __uniphier_cache_init()
390 data->op_base = of_iomap(np, 2); in __uniphier_cache_init()
391 if (!data->op_base) { in __uniphier_cache_init()
393 ret = -ENOMEM; in __uniphier_cache_init()
397 data->way_ctrl_base = data->ctrl_base + 0xc00; in __uniphier_cache_init()
400 u32 revision = readl(data->rev_base + UNIPHIER_SSCID); in __uniphier_cache_init()
403 * for PH-sLD8 or older SoCs. in __uniphier_cache_init()
406 data->range_op_max_size = (u32)1 << 22; in __uniphier_cache_init()
414 data->way_ctrl_base = data->ctrl_base + 0x870; in __uniphier_cache_init()
418 data->way_ctrl_base = data->ctrl_base + 0x840; in __uniphier_cache_init()
425 data->range_op_max_size -= data->line_size; in __uniphier_cache_init()
427 INIT_LIST_HEAD(&data->list); in __uniphier_cache_init()
428 list_add_tail(&data->list, &uniphier_cache_list); /* no mutex */ in __uniphier_cache_init()
432 * level cache. Do not roll back even if the initialization of the in __uniphier_cache_init()
433 * next level cache fails because we want to continue with available in __uniphier_cache_init()
434 * cache levels. in __uniphier_cache_init()
445 iounmap(data->op_base); in __uniphier_cache_init()
446 iounmap(data->rev_base); in __uniphier_cache_init()
447 iounmap(data->ctrl_base); in __uniphier_cache_init()
459 /* look for level 2 cache */ in uniphier_cache_init()
461 if (!of_property_read_u32(np, "cache-level", &cache_level) && in uniphier_cache_init()
466 return -ENODEV; in uniphier_cache_init()
477 pr_err("failed to initialize L2 cache\n"); in uniphier_cache_init()
481 cache_level--; in uniphier_cache_init()
494 pr_info("enabled outer cache (cache level: %d)\n", cache_level); in uniphier_cache_init()