Lines Matching +full:has +full:- +full:interrupt +full:- +full:mask +full:- +full:reg
2 * Copyright (c) 2017 Jean-Paul Etienne <fractalclone@gmail.com>
6 * SPDX-License-Identifier: Apache-2.0
12 * @brief Platform Level Interrupt Controller (PLIC) driver
13 * for RISC-V processors
34 * https://github.com/riscv/riscv-plic-spec
54 /* PLIC registers are 32-bit memory-mapped */
82 mem_addr_t reg; member
133 const struct plic_config *config = dev->config; in get_plic_enabled_size()
135 return local_irq_to_reg_index(config->nr_irqs) + 1; in get_plic_enabled_size()
140 const struct plic_config *config = dev->config; in get_hart_context()
142 return config->hart_context[hartid]; in get_hart_context()
148 const struct plic_data *data = dev->data; in get_irq_cpumask()
150 return data->irq_cpumask[local_irq]; in get_irq_cpumask()
161 const struct plic_config *config = dev->config; in get_context_en_addr()
171 return config->irq_en + get_hart_context(dev, hartid) * CONTEXT_ENABLE_SIZE; in get_context_en_addr()
176 const struct plic_config *config = dev->config; in get_claim_complete_addr()
182 return config->reg + get_hart_context(dev, arch_proc_id()) * CONTEXT_SIZE + CONTEXT_CLAIM; in get_claim_complete_addr()
187 const struct plic_config *config = dev->config; in get_threshold_priority_addr()
196 return config->reg + (get_hart_context(dev, hartid) * CONTEXT_SIZE); in get_threshold_priority_addr()
201 const struct plic_config *config = dev->config; in local_irq_to_irq()
203 return irq_to_level_2(local_irq) | config->irq; in local_irq_to_irq()
209 const struct plic_config *config = dev->config; in get_pending_reg()
211 return config->pend + local_irq_to_reg_offset(local_irq); in get_pending_reg()
239 * @param dev PLIC-instance device
240 * @param local_irq PLIC-instance IRQ number to add to the trigger
246 const struct plic_config *config = dev->config; in riscv_plic_irq_trig_val()
247 mem_addr_t trig_addr = config->trig + local_irq_to_reg_offset(local_irq); in riscv_plic_irq_trig_val()
250 return sys_read32(trig_addr) & GENMASK(offset + CONFIG_PLIC_TRIG_TYPE_BITWIDTH - 1, offset); in riscv_plic_irq_trig_val()
272 * @brief Enable a riscv PLIC-specific interrupt line
274 * This routine enables a RISCV PLIC-specific interrupt line.
284 struct plic_data *data = dev->data; in riscv_plic_irq_enable()
285 k_spinlock_key_t key = k_spin_lock(&data->lock); in riscv_plic_irq_enable()
289 k_spin_unlock(&data->lock, key); in riscv_plic_irq_enable()
293 * @brief Disable a riscv PLIC-specific interrupt line
295 * This routine disables a RISCV PLIC-specific interrupt line.
305 struct plic_data *data = dev->data; in riscv_plic_irq_disable()
306 k_spinlock_key_t key = k_spin_lock(&data->lock); in riscv_plic_irq_disable()
310 k_spin_unlock(&data->lock, key); in riscv_plic_irq_disable()
335 * @brief Check if a riscv PLIC-specific interrupt line is enabled
337 * This routine checks if a RISCV PLIC-specific interrupt line is enabled.
345 struct plic_data *data = dev->data; in riscv_plic_irq_is_enabled()
349 K_SPINLOCK(&data->lock) { in riscv_plic_irq_is_enabled()
357 * @brief Set priority of a riscv PLIC-specific interrupt line
359 * This routine set the priority of a RISCV PLIC-specific interrupt line.
361 * the priority of an interrupt whenever CONFIG_RISCV_HAS_PLIC variable is set.
369 const struct plic_config *config = dev->config; in riscv_plic_set_priority()
371 mem_addr_t prio_addr = config->prio + (local_irq * sizeof(uint32_t)); in riscv_plic_set_priority()
373 if (priority > config->max_prio) { in riscv_plic_set_priority()
374 priority = config->max_prio; in riscv_plic_set_priority()
394 * @brief Get riscv PLIC-specific interrupt line causing an interrupt
396 * This routine returns the RISCV PLIC-specific interrupt line causing an
397 * interrupt.
399 * @param dev Optional device pointer to get the interrupt line's controller
401 * @return PLIC-specific interrupt line causing an interrupt.
405 return save_irq[arch_curr_cpu()->id]; in riscv_plic_get_irq()
409 * @brief Get riscv PLIC causing an interrupt
411 * This routine returns the RISCV PLIC device causing an interrupt.
413 * @return PLIC device causing an interrupt.
417 return save_dev[arch_curr_cpu()->id]; in riscv_plic_get_dev()
422 * @brief Set riscv PLIC-specific interrupt enable by cpu bitmask
430 struct plic_data *data = dev->data; in riscv_plic_irq_set_affinity()
431 __maybe_unused const struct plic_config *config = dev->config; in riscv_plic_irq_set_affinity()
435 if (local_irq >= config->nr_irqs) { in riscv_plic_irq_set_affinity()
437 return -EINVAL; in riscv_plic_irq_set_affinity()
442 return -EINVAL; in riscv_plic_irq_set_affinity()
445 key = k_spin_lock(&data->lock); in riscv_plic_irq_set_affinity()
447 data->irq_cpumask[local_irq] = (plic_cpumask_t)cpumask; in riscv_plic_irq_set_affinity()
453 k_spin_unlock(&data->lock, key); in riscv_plic_irq_set_affinity()
461 * If there's more than one core, irq_count points to a 2D-array: irq_count[NUM_CPUs + 1][nr_irqs]
464 * CPU 0 [0 ... nr_irqs - 1]
465 * CPU 1 [0 ... nr_irqs - 1]
466 * TOTAL [0 ... nr_irqs - 1]
471 const struct plic_config *config = dev->config; in get_irq_hit_count_cpu()
472 const struct plic_data *data = dev->data; in get_irq_hit_count_cpu()
476 offset = cpu * config->nr_irqs + local_irq; in get_irq_hit_count_cpu()
479 return &data->stats.irq_count[offset]; in get_irq_hit_count_cpu()
484 const struct plic_config *config = dev->config; in get_irq_hit_count_total()
485 const struct plic_data *data = dev->data; in get_irq_hit_count_total()
489 offset = arch_num_cpus() * config->nr_irqs + local_irq; in get_irq_hit_count_total()
492 return &data->stats.irq_count[offset]; in get_irq_hit_count_total()
498 const struct plic_config *config = dev->config; in plic_irq_handler()
501 uint32_t cpu_id = arch_curr_cpu()->id; in plic_irq_handler()
502 /* Get the IRQ number generating the interrupt */ in plic_irq_handler()
519 * Note: Because PLIC only supports multicast of interrupt, all enabled in plic_irq_handler()
520 * targets will receive interrupt notification. Only the fastest target in plic_irq_handler()
521 * will claim this interrupt, and other targets will claim ID 0 if in plic_irq_handler()
522 * no other pending interrupt now. in plic_irq_handler()
524 * (by RISC-V Privileged Architecture v1.10) in plic_irq_handler()
543 if ((local_irq == 0U) || (local_irq >= config->nr_irqs)) { in plic_irq_handler()
550 * Edge-triggered interrupts have to be acknowledged first before in plic_irq_handler()
551 * getting handled so that we don't miss on the next edge-triggered interrupt. in plic_irq_handler()
559 ite = &config->isr_table[local_irq]; in plic_irq_handler()
560 ite->isr(ite->arg); in plic_irq_handler()
564 * PLIC controller that the IRQ has been handled in plic_irq_handler()
568 /* Handle only if level-triggered */ in plic_irq_handler()
578 * @brief Initialize the Platform Level Interrupt Controller
586 const struct plic_config *config = dev->config; in plic_init()
588 mem_addr_t prio_addr = config->prio; in plic_init()
604 /* Set priority of each interrupt line to 0 initially */ in plic_init()
605 for (uint32_t i = 0; i < config->nr_irqs; i++) { in plic_init()
610 config->irq_config_func(); in plic_init()
624 return -ENODEV; in parse_device()
641 const struct plic_config *config = dev->config; in cmd_stats_get()
661 for (int i = 0; i < config->nr_irqs; i++) { in cmd_stats_get()
682 symtab_find_symbol_name((uintptr_t)config->isr_table[i].isr, NULL); in cmd_stats_get()
684 shell_fprintf(sh, SHELL_NORMAL, "\t%s(%p)\n", name, config->isr_table[i].arg); in cmd_stats_get()
686 shell_fprintf(sh, SHELL_NORMAL, "\t%p(%p)\n", (void *)config->isr_table[i].isr, in cmd_stats_get()
687 config->isr_table[i].arg); in cmd_stats_get()
704 const struct plic_data *data = dev->data; in cmd_stats_clear()
705 const struct plic_config *config = dev->config; in cmd_stats_clear()
706 struct plic_stats stat = data->stats; in cmd_stats_clear()
709 config->nr_irqs * in cmd_stats_clear()
714 shell_print(sh, "Cleared stats of %s.\n", dev->name); in cmd_stats_clear()
725 uint32_t local_irq, irq, mask; in cmd_affinity_set() local
728 const struct plic_config *config = dev->config; in cmd_affinity_set()
739 if (local_irq >= config->nr_irqs) { in cmd_affinity_set()
740 shell_error(sh, "local_irq (%d) > nr_irqs (%d)", local_irq, config->nr_irqs); in cmd_affinity_set()
741 return -EINVAL; in cmd_affinity_set()
744 mask = (uint32_t)shell_strtol(argv[3], 16, &rc); in cmd_affinity_set()
749 if ((mask & ~BIT_MASK(arch_num_cpus())) != 0) { in cmd_affinity_set()
750 shell_error(sh, "cpumask: 0x%X num_cpus: %d", mask, arch_num_cpus()); in cmd_affinity_set()
751 return -EINVAL; in cmd_affinity_set()
756 riscv_plic_irq_set_affinity(irq, mask); in cmd_affinity_set()
757 shell_print(sh, "IRQ %d affinity set to 0x%X", local_irq, mask); in cmd_affinity_set()
759 for (local_irq = 1; local_irq <= config->nr_irqs; local_irq++) { in cmd_affinity_set()
761 riscv_plic_irq_set_affinity(irq, mask); in cmd_affinity_set()
763 shell_print(sh, "All IRQ affinity set to 0x%X", mask); in cmd_affinity_set()
775 const struct plic_config *config = dev->config; in cmd_affinity_get()
781 shell_print(sh, " IRQ MASK"); in cmd_affinity_get()
783 for (uint32_t local_irq = 0; local_irq < config->nr_irqs; local_irq++) { in cmd_affinity_get()
793 if (local_irq >= config->nr_irqs) { in cmd_affinity_get()
795 config->nr_irqs); in cmd_affinity_get()
796 return -EINVAL; in cmd_affinity_get()
809 const struct device *dev = shell_device_lookup(idx, "interrupt-controller"); in device_name_get()
811 entry->syntax = (dev != NULL) ? dev->name : NULL; in device_name_get()
812 entry->handler = NULL; in device_name_get()
813 entry->help = NULL; in device_name_get()
814 entry->subcmd = NULL; in device_name_get()
879 [0 ...(PLIC_MIN_IRQ_NUM(n) - 1)] = CONFIG_PLIC_IRQ_AFFINITY_MASK, \
915 .reg = PLIC_BASE_ADDR(n) + CONTEXT_BASE, \