Changeset adede135 in rtems


Ignore:
Timestamp:
Jul 24, 2018, 11:27:54 AM (16 months ago)
Author:
Sebastian Huber <sebastian.huber@…>
Branches:
master
Children:
581a0f88
Parents:
bd560386
git-author:
Sebastian Huber <sebastian.huber@…> (07/24/18 11:27:54)
git-committer:
Sebastian Huber <sebastian.huber@…> (07/25/18 08:07:44)
Message:

bsp/riscv: Add PLIC support

Update #3433.

Location:
bsps
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • bsps/include/bsp/fatal.h

    rbd560386 radede135  
    148148  RISCV_FATAL_NO_CLINT_REG_IN_DEVICE_TREE,
    149149  RISCV_FATAL_INVALID_HART_REG_IN_DEVICE_TREE,
    150   RISCV_FATAL_INVALID_CLINT_IRQS_EXTENDED_IN_DEVICE_TREE
     150  RISCV_FATAL_INVALID_CLINT_IRQS_EXTENDED_IN_DEVICE_TREE,
     151  RISCV_FATAL_NO_PLIC_REG_IN_DEVICE_TREE,
     152  RISCV_FATAL_INVALID_PLIC_NDEV_IN_DEVICE_TREE,
     153  RISCV_FATAL_TOO_LARGE_PLIC_NDEV_IN_DEVICE_TREE,
     154  RISCV_FATAL_INVALID_INTERRUPT_AFFINITY
    151155} bsp_fatal_code;
    152156
  • bsps/riscv/riscv/include/bsp.h

    rbd560386 radede135  
    4545#endif
    4646
     47#define BSP_FEATURE_IRQ_EXTENSION
     48
    4749#define BSP_FDT_IS_SUPPORTED
    4850
  • bsps/riscv/riscv/include/bsp/irq.h

    rbd560386 radede135  
    4343#include <rtems/irq.h>
    4444#include <rtems/irq-extension.h>
     45#include <rtems/score/processormask.h>
    4546
    4647#define RISCV_INTERRUPT_VECTOR_SOFTWARE 0
     
    5051#define RISCV_INTERRUPT_VECTOR_EXTERNAL(x) ((x) + 2)
    5152
     53#define RISCV_INTERRUPT_VECTOR_IS_EXTERNAL(x) ((x) >= 2)
     54
     55#define RISCV_INTERRUPT_VECTOR_EXTERNAL_TO_INDEX(x) ((x) - 2)
     56
    5257#define BSP_INTERRUPT_VECTOR_MIN 0
    5358
    5459#define BSP_INTERRUPT_VECTOR_MAX RISCV_INTERRUPT_VECTOR_EXTERNAL(RISCV_MAXIMUM_EXTERNAL_INTERRUPTS - 1)
    5560
     61void bsp_interrupt_set_affinity(
     62  rtems_vector_number vector,
     63  const Processor_mask *affinity
     64);
     65
     66void bsp_interrupt_get_affinity(
     67  rtems_vector_number vector,
     68  Processor_mask *affinity
     69);
     70
    5671#endif /* ASM */
    5772
  • bsps/riscv/riscv/irq/irq.c

    rbd560386 radede135  
    4949volatile RISCV_CLINT_regs *riscv_clint;
    5050
     51static volatile RISCV_PLIC_regs *riscv_plic;
     52
     53/*
     54 * The lovely PLIC has an interrupt enable bit per hart for each interrupt
     55 * source.  This makes the interrupt enable/disable a bit difficult.  We have
     56 * to store the interrupt distribution in software.  To keep it simple, we
     57 * support only a one-to-one and one-to-all interrupt to processor
     58 * distribution.  For a one-to-one distribution, the array member must point to
     59 * the enable register block of the corresponding.  For a one-to-all
     60 * distribution, the array member must be NULL.  The array index is the
     61 * external interrupt index minus one (external interrupt index zero is a
     62 * special value, see PLIC documentation).
     63 */
     64static volatile uint32_t *
     65riscv_plic_irq_to_cpu[RISCV_MAXIMUM_EXTERNAL_INTERRUPTS];
     66
     67RTEMS_INTERRUPT_LOCK_DEFINE(static, riscv_plic_lock, "PLIC")
     68
    5169void _RISCV_Interrupt_dispatch(uintptr_t mcause, Per_CPU_Control *cpu_self)
    5270{
     
    6078    bsp_interrupt_handler_dispatch(RISCV_INTERRUPT_VECTOR_TIMER);
    6179  } else if (mcause == (RISCV_INTERRUPT_EXTERNAL_MACHINE << 1)) {
    62     /* TODO: Handle PLIC interrupt */
     80    volatile RISCV_PLIC_hart_regs *plic_hart_regs;
     81    uint32_t interrupt_index;
     82
     83    plic_hart_regs = cpu_self->cpu_per_cpu.plic_hart_regs;
     84
     85    while ((interrupt_index = plic_hart_regs->claim_complete) != 0) {
     86      bsp_interrupt_handler_dispatch(
     87        RISCV_INTERRUPT_VECTOR_EXTERNAL(interrupt_index)
     88      );
     89      plic_hart_regs->claim_complete = interrupt_index;
     90    }
    6391  } else if (mcause == (RISCV_INTERRUPT_SOFTWARE_MACHINE << 1)) {
    6492#ifdef RTEMS_SMP
     
    111139}
    112140
     141static void riscv_plic_init(const void *fdt)
     142{
     143  volatile RISCV_PLIC_regs *plic;
     144  int node;
     145  int i;
     146  const uint32_t *val;
     147  int len;
     148  uint32_t interrupt_index;
     149  uint32_t ndev;
     150  Per_CPU_Control *cpu;
     151
     152  node = fdt_node_offset_by_compatible(fdt, -1, "riscv,plic0");
     153
     154  plic = riscv_fdt_get_address(fdt, node);
     155  if (plic == NULL) {
     156    bsp_fatal(RISCV_FATAL_NO_PLIC_REG_IN_DEVICE_TREE);
     157  }
     158
     159  riscv_plic = plic;
     160
     161  val = fdt_getprop(fdt, node, "riscv,ndev", &len);
     162  if (val == NULL || len != 4) {
     163    bsp_fatal(RISCV_FATAL_INVALID_PLIC_NDEV_IN_DEVICE_TREE);
     164  }
     165
     166  ndev = fdt32_to_cpu(val[0]);
     167  if (ndev > RISCV_MAXIMUM_EXTERNAL_INTERRUPTS) {
     168    bsp_fatal(RISCV_FATAL_TOO_LARGE_PLIC_NDEV_IN_DEVICE_TREE);
     169  }
     170
     171  val = fdt_getprop(fdt, node, "interrupts-extended", &len);
     172
     173  for (i = 0; i < len; i += 8) {
     174    uint32_t hart_index;
     175
     176    hart_index = riscv_get_hart_index_by_phandle(fdt32_to_cpu(val[i / 4]));
     177    if (hart_index >= rtems_configuration_get_maximum_processors()) {
     178      continue;
     179    }
     180
     181    interrupt_index = fdt32_to_cpu(val[i / 4 + 1]);
     182    if (interrupt_index != RISCV_INTERRUPT_EXTERNAL_MACHINE) {
     183      continue;
     184    }
     185
     186    plic->harts[i / 8].priority_threshold = 0;
     187
     188    cpu = _Per_CPU_Get_by_index(hart_index);
     189    cpu->cpu_per_cpu.plic_hart_regs = &plic->harts[i / 8];
     190    cpu->cpu_per_cpu.plic_m_ie = &plic->enable[i / 8][0];
     191  }
     192
     193  cpu = _Per_CPU_Get_by_index(0);
     194
     195  for (interrupt_index = 1; interrupt_index <= ndev; ++interrupt_index) {
     196    plic->priority[interrupt_index] = 1;
     197    riscv_plic_irq_to_cpu[interrupt_index - 1] = cpu->cpu_per_cpu.plic_m_ie;
     198  }
     199
     200  /*
     201   * External M-mode interrupts on secondary processors are enabled in
     202   * bsp_start_on_secondary_processor().
     203   */
     204  set_csr(mie, MIP_MEIP);
     205}
     206
    113207rtems_status_code bsp_interrupt_facility_initialize(void)
    114208{
     
    117211  fdt = bsp_fdt_get();
    118212  riscv_clint_init(fdt);
     213  riscv_plic_init(fdt);
    119214
    120215  return RTEMS_SUCCESSFUL;
     
    123218void bsp_interrupt_vector_enable(rtems_vector_number vector)
    124219{
     220  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
     221
     222  if (RISCV_INTERRUPT_VECTOR_IS_EXTERNAL(vector)) {
     223    uint32_t interrupt_index;
     224    volatile uint32_t *enable;
     225    uint32_t group;
     226    uint32_t bit;
     227    rtems_interrupt_lock_context lock_context;
     228
     229    interrupt_index = RISCV_INTERRUPT_VECTOR_EXTERNAL_TO_INDEX(vector);
     230    enable = riscv_plic_irq_to_cpu[interrupt_index - 1];
     231    group = interrupt_index / 32;
     232    bit = UINT32_C(1) << (interrupt_index % 32);
     233
     234    rtems_interrupt_lock_acquire(&riscv_plic_lock, &lock_context);
     235
     236    if (enable != NULL) {
     237      enable[group] |= bit;
     238    } else {
     239      uint32_t cpu_index;
     240      uint32_t cpu_count;
     241
     242      cpu_count = _SMP_Get_processor_count();
     243
     244      for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
     245        Per_CPU_Control *cpu;
     246
     247        cpu = _Per_CPU_Get_by_index(cpu_index);
     248        enable = cpu->cpu_per_cpu.plic_m_ie;
     249
     250        if (enable != NULL) {
     251          enable[group] |= bit;
     252        }
     253      }
     254    }
     255
     256    rtems_interrupt_lock_release(&riscv_plic_lock, &lock_context);
     257  }
    125258}
    126259
    127260void bsp_interrupt_vector_disable(rtems_vector_number vector)
    128261{
    129 }
     262  bsp_interrupt_assert(bsp_interrupt_is_valid_vector(vector));
     263
     264  if (RISCV_INTERRUPT_VECTOR_IS_EXTERNAL(vector)) {
     265    uint32_t interrupt_index;
     266    volatile uint32_t *enable;
     267    uint32_t group;
     268    uint32_t bit;
     269    rtems_interrupt_lock_context lock_context;
     270
     271    interrupt_index = RISCV_INTERRUPT_VECTOR_EXTERNAL_TO_INDEX(vector);
     272    enable = riscv_plic_irq_to_cpu[interrupt_index - 1];
     273    group = interrupt_index / 32;
     274    bit = UINT32_C(1) << (interrupt_index % 32);
     275
     276    rtems_interrupt_lock_acquire(&riscv_plic_lock, &lock_context);
     277
     278    if (enable != NULL) {
     279      enable[group] &= ~bit;
     280    } else {
     281      uint32_t cpu_index;
     282      uint32_t cpu_count;
     283
     284      cpu_count = _SMP_Get_processor_count();
     285
     286      for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
     287        Per_CPU_Control *cpu;
     288
     289        cpu = _Per_CPU_Get_by_index(cpu_index);
     290        enable = cpu->cpu_per_cpu.plic_m_ie;
     291
     292        if (enable != NULL) {
     293          enable[group] &= ~bit;
     294        }
     295      }
     296    }
     297
     298    rtems_interrupt_lock_release(&riscv_plic_lock, &lock_context);
     299  }
     300}
     301
     302void bsp_interrupt_set_affinity(
     303  rtems_vector_number vector,
     304  const Processor_mask *affinity
     305)
     306{
     307  if (RISCV_INTERRUPT_VECTOR_IS_EXTERNAL(vector)) {
     308    uint32_t interrupt_index;
     309    Processor_mask mask;
     310
     311    interrupt_index = RISCV_INTERRUPT_VECTOR_EXTERNAL_TO_INDEX(vector);
     312
     313    _Processor_mask_And(&mask, affinity, _SMP_Get_online_processors());
     314
     315    if (_Processor_mask_Is_equal(&mask, _SMP_Get_online_processors())) {
     316      riscv_plic_irq_to_cpu[interrupt_index - 1] = NULL;
     317      return;
     318    }
     319
     320    if (_Processor_mask_Count(&mask) == 1) {
     321      uint32_t cpu_index;
     322      Per_CPU_Control *cpu;
     323
     324      cpu_index = _Processor_mask_Find_last_set(&mask) - 1;
     325      cpu = _Per_CPU_Get_by_index(cpu_index);
     326      riscv_plic_irq_to_cpu[interrupt_index - 1] = cpu->cpu_per_cpu.plic_m_ie;
     327      return;
     328    }
     329
     330    bsp_fatal(RISCV_FATAL_INVALID_INTERRUPT_AFFINITY);
     331  }
     332}
     333
     334void bsp_interrupt_get_affinity(
     335  rtems_vector_number vector,
     336  Processor_mask *affinity
     337)
     338{
     339  _Processor_mask_Zero(affinity);
     340
     341  if (RISCV_INTERRUPT_VECTOR_IS_EXTERNAL(vector)) {
     342    uint32_t interrupt_index;
     343    volatile uint32_t *enable;
     344
     345    interrupt_index = RISCV_INTERRUPT_VECTOR_EXTERNAL_TO_INDEX(vector);
     346    enable = riscv_plic_irq_to_cpu[interrupt_index - 1];
     347
     348    if (enable != NULL) {
     349      uint32_t cpu_index;
     350      uint32_t cpu_count;
     351
     352      cpu_count = _SMP_Get_processor_count();
     353
     354      for (cpu_index = 0; cpu_index < cpu_count; ++cpu_index) {
     355        Per_CPU_Control *cpu;
     356
     357        cpu = _Per_CPU_Get_by_index(cpu_index);
     358
     359        if (enable == cpu->cpu_per_cpu.plic_m_ie) {
     360          _Processor_mask_Set(affinity, cpu_index);
     361          break;
     362        }
     363      }
     364    } else {
     365      _Processor_mask_Assign(affinity, _SMP_Get_online_processors());
     366    }
     367  }
     368}
  • bsps/riscv/riscv/start/bspsmp.c

    rbd560386 radede135  
    4141      && _SMP_Should_start_processor(cpu_index_self)
    4242  ) {
    43     set_csr(mie, MIP_MSIP);
     43    set_csr(mie, MIP_MSIP | MIP_MEIP);
    4444    _SMP_Start_multitasking_on_secondary_processor(cpu_self);
    4545  } else {
Note: See TracChangeset for help on using the changeset viewer.