Lines Matching +full:cache +full:- +full:size
1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2015-2016 Socionext Inc.
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 * uniphier_cache_data - UniPhier outer cache specific data
68 * @line_size: line size in bytes
69 * @range_op_max_size: max size that can be handled by a single range operation
70 * @list: list node to include this level in the whole cache hierarchy
85 * List of the whole outer cache hierarchy. This list is only modified during
91 * __uniphier_cache_sync - perform a sync point for a particular cache level
93 * @data: cache controller specific data
99 data->op_base + UNIPHIER_SSCOPE); in __uniphier_cache_sync()
101 readl_relaxed(data->op_base + UNIPHIER_SSCOPE); in __uniphier_cache_sync()
105 * __uniphier_cache_maint_common - run a queue operation for a particular level
107 * @data: cache controller specific data
109 * @size: data size of range operation (don't care for "all" operation)
110 * @operation: flags to specify the desired cache operation
114 unsigned long size, in __uniphier_cache_maint_common() argument
122 * [1] This outer cache controller is able to accept maintenance in __uniphier_cache_maint_common()
132 * [2] The cache command registers, UNIPHIER_{SSCOQM, SSCOQAD, SSCOQSZ, in __uniphier_cache_maint_common()
145 writel_relaxed(UNIPHIER_SSCOLPQS_EF, data->op_base + UNIPHIER_SSCOLPQS); in __uniphier_cache_maint_common()
148 /* set cache operation */ in __uniphier_cache_maint_common()
150 data->op_base + UNIPHIER_SSCOQM); in __uniphier_cache_maint_common()
154 writel_relaxed(start, data->op_base + UNIPHIER_SSCOQAD); in __uniphier_cache_maint_common()
155 writel_relaxed(size, data->op_base + UNIPHIER_SSCOQSZ); in __uniphier_cache_maint_common()
157 } while (unlikely(readl_relaxed(data->op_base + UNIPHIER_SSCOPPQSEF) & in __uniphier_cache_maint_common()
161 while (likely(readl_relaxed(data->op_base + UNIPHIER_SSCOLPQS) != in __uniphier_cache_maint_common()
181 unsigned long size; in __uniphier_cache_maint_range() local
185 * perform a cache operation for the first cache-line in __uniphier_cache_maint_range()
187 start = start & ~(data->line_size - 1); in __uniphier_cache_maint_range()
189 size = end - start; in __uniphier_cache_maint_range()
191 if (unlikely(size >= (unsigned long)(-data->line_size))) { in __uniphier_cache_maint_range()
192 /* this means cache operation for all range */ in __uniphier_cache_maint_range()
199 * perform a cache operation for the last cache-line in __uniphier_cache_maint_range()
201 size = ALIGN(size, data->line_size); in __uniphier_cache_maint_range()
203 while (size) { in __uniphier_cache_maint_range()
204 unsigned long chunk_size = min_t(unsigned long, size, in __uniphier_cache_maint_range()
205 data->range_op_max_size); in __uniphier_cache_maint_range()
211 size -= chunk_size; in __uniphier_cache_maint_range()
224 writel_relaxed(val, data->ctrl_base + UNIPHIER_SSCC); in __uniphier_cache_enable()
233 writel_relaxed(data->way_mask, data->way_ctrl_base + 4 * cpu); in __uniphier_cache_set_active_ways()
309 { .compatible = "socionext,uniphier-system-cache" },
322 pr_err("L%d: not compatible with uniphier cache\n", in __uniphier_cache_init()
324 return -EINVAL; in __uniphier_cache_init()
327 if (of_property_read_u32(np, "cache-level", &level)) { in __uniphier_cache_init()
328 pr_err("L%d: cache-level is not specified\n", *cache_level); in __uniphier_cache_init()
329 return -EINVAL; in __uniphier_cache_init()
333 pr_err("L%d: cache-level is unexpected value %d\n", in __uniphier_cache_init()
335 return -EINVAL; in __uniphier_cache_init()
338 if (!of_property_read_bool(np, "cache-unified")) { in __uniphier_cache_init()
339 pr_err("L%d: cache-unified is not specified\n", *cache_level); in __uniphier_cache_init()
340 return -EINVAL; in __uniphier_cache_init()
345 return -ENOMEM; in __uniphier_cache_init()
347 if (of_property_read_u32(np, "cache-line-size", &data->line_size) || in __uniphier_cache_init()
348 !is_power_of_2(data->line_size)) { in __uniphier_cache_init()
349 pr_err("L%d: cache-line-size is unspecified or invalid\n", in __uniphier_cache_init()
351 ret = -EINVAL; in __uniphier_cache_init()
355 if (of_property_read_u32(np, "cache-sets", &data->nsets) || in __uniphier_cache_init()
356 !is_power_of_2(data->nsets)) { in __uniphier_cache_init()
357 pr_err("L%d: cache-sets is unspecified or invalid\n", in __uniphier_cache_init()
359 ret = -EINVAL; in __uniphier_cache_init()
363 if (of_property_read_u32(np, "cache-size", &cache_size) || in __uniphier_cache_init()
364 cache_size == 0 || cache_size % (data->nsets * data->line_size)) { in __uniphier_cache_init()
365 pr_err("L%d: cache-size is unspecified or invalid\n", in __uniphier_cache_init()
367 ret = -EINVAL; in __uniphier_cache_init()
371 data->way_mask = GENMASK(cache_size / data->nsets / data->line_size - 1, in __uniphier_cache_init()
374 data->ctrl_base = of_iomap(np, 0); in __uniphier_cache_init()
375 if (!data->ctrl_base) { in __uniphier_cache_init()
377 ret = -ENOMEM; in __uniphier_cache_init()
381 data->rev_base = of_iomap(np, 1); in __uniphier_cache_init()
382 if (!data->rev_base) { in __uniphier_cache_init()
384 ret = -ENOMEM; in __uniphier_cache_init()
388 data->op_base = of_iomap(np, 2); in __uniphier_cache_init()
389 if (!data->op_base) { in __uniphier_cache_init()
391 ret = -ENOMEM; in __uniphier_cache_init()
395 data->way_ctrl_base = data->ctrl_base + 0xc00; in __uniphier_cache_init()
398 u32 revision = readl(data->rev_base + UNIPHIER_SSCID); in __uniphier_cache_init()
400 * The size of range operation is limited to (1 << 22) or less in __uniphier_cache_init()
401 * for PH-sLD8 or older SoCs. in __uniphier_cache_init()
404 data->range_op_max_size = (u32)1 << 22; in __uniphier_cache_init()
412 data->way_ctrl_base = data->ctrl_base + 0x870; in __uniphier_cache_init()
416 data->way_ctrl_base = data->ctrl_base + 0x840; in __uniphier_cache_init()
423 data->range_op_max_size -= data->line_size; in __uniphier_cache_init()
425 INIT_LIST_HEAD(&data->list); in __uniphier_cache_init()
426 list_add_tail(&data->list, &uniphier_cache_list); /* no mutex */ in __uniphier_cache_init()
430 * level cache. Do not roll back even if the initialization of the in __uniphier_cache_init()
431 * next level cache fails because we want to continue with available in __uniphier_cache_init()
432 * cache levels. in __uniphier_cache_init()
443 iounmap(data->op_base); in __uniphier_cache_init()
444 iounmap(data->rev_base); in __uniphier_cache_init()
445 iounmap(data->ctrl_base); in __uniphier_cache_init()
457 /* look for level 2 cache */ in uniphier_cache_init()
459 if (!of_property_read_u32(np, "cache-level", &cache_level) && in uniphier_cache_init()
464 return -ENODEV; in uniphier_cache_init()
475 pr_err("failed to initialize L2 cache\n"); in uniphier_cache_init()
479 cache_level--; in uniphier_cache_init()
492 pr_info("enabled outer cache (cache level: %d)\n", cache_level); in uniphier_cache_init()