Lines Matching +full:right +full:- +full:aligned
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 */
37 #define UNIPHIER_SSCOPE_CM_FLUSH_PREFETCH 0x9 /* flush p-fetch buf */
61 * struct uniphier_cache_data - UniPhier outer cache specific data
93 * __uniphier_cache_sync - perform a sync point for a particular cache level
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
138 * register, UNIPHIER_SSCOQM, holds the access right and it is released in __uniphier_cache_maint_common()
140 * is holding the access right, other CPUs fail to register operations. in __uniphier_cache_maint_common()
141 * One CPU should not hold the access right for a long time, so local in __uniphier_cache_maint_common()
147 writel_relaxed(UNIPHIER_SSCOLPQS_EF, data->op_base + UNIPHIER_SSCOLPQS); 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()
186 * If the start address is not aligned, in __uniphier_cache_maint_range()
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()
200 * If the end address is not aligned, 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" },
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()
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()
461 if (!of_property_read_u32(np, "cache-level", &cache_level) && in uniphier_cache_init()
466 return -ENODEV; in uniphier_cache_init()
481 cache_level--; in uniphier_cache_init()