1/* 2 * Copyright 2019, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the BSD 2-Clause license. Note that NO WARRANTY is provided. 8 * See "LICENSE_BSD2.txt" for details. 9 * 10 * @TAG(DATA61_BSD) 11 */ 12 13#pragma once 14 15#include <inttypes.h> 16#include <stdint.h> 17#include <errno.h> 18 19#define __PS_IRQ_VALID_ARGS(FUN) do {\ 20 if (!irq_ops) return -EINVAL;\ 21 if (!irq_ops->cookie) return -EINVAL;\ 22 if (!irq_ops->FUN) return -ENOSYS;\ 23} while(0) 24 25#define PS_INVALID_IRQ_ID -1 26 27typedef enum irq_type { 28 PS_NONE, 29 PS_MSI, 30 PS_IOAPIC, 31 PS_INTERRUPT, 32 PS_TRIGGER, 33 PS_PER_CPU, 34 PS_OTHER, 35} irq_type_t; 36 37typedef enum irq_trigger_type { 38 PS_LEVEL_TRIGGERED, 39 PS_EDGE_TRIGGERED, 40} irq_trigger_type_t; 41 42typedef struct { 43 irq_type_t type; 44 union { 45 struct { 46 long ioapic; 47 long pin; 48 long level; 49 long polarity; 50 long vector; 51 } ioapic; 52 struct { 53 long pci_bus; 54 long pci_dev; 55 long pci_func; 56 long handle; 57 long vector; 58 } msi; 59 struct { 60 long number; 61 } irq; 62 struct { 63 long number; 64 long trigger; 65 } trigger; 66 struct { 67 long number; 68 long trigger; 69 long cpu_idx; 70 } cpu; 71 void *other; /* Implementation-specific information. */ 72 }; 73} ps_irq_t; 74 75typedef int irq_id_t; 76 77/* 78 * Acknowledges an interrupt. 79 * 80 * @param ack_data Implementation specific structure containing information needed to ACK an interrupt. 81 * 82 * @return 0 on success, otherwise an error code 83 */ 84typedef int (*ps_irq_acknowledge_fn_t)(void *ack_data); 85 86/* 87 * Callback type that is accepted by implementations of the IRQ interface. The 88 * callback is responsible for acknowledging the interrupt via the supplied 89 * acknowledge function. 90 * 91 * Note that the acknowledge function pointer and its token, 'ack_data' can be 92 * saved and called later. This might be useful in some contexts where you need 93 * to perform some maintenance before acknowledging the IRQ. The lifetime of 94 * the 'ack_data' token lasts until the acknowledge function is called. Thus 95 * you cannot call the acknowledge function again. 96 * 97 * @param data Pointer to data which is passed into the callback function 98 * @param acknowledge_fn Function pointer to an function used to acknowledge an interrupt 99 * @param ack_data Data to be passed to 'acknowledge_fn' 100 */ 101typedef void (*irq_callback_fn_t)(void *data, ps_irq_acknowledge_fn_t acknowledge_fn, void *ack_data); 102 103/* 104 * Registers an interrupt with the interface and allocates data necessary to 105 * keep track of the interrupt. Also associates a callback function with the 106 * interrupt which is called when the interrupt arrives. 107 * 108 * Returns a valid IRQ ID on success that has a value >= 0, otherwise an error 109 * code with a value < 0. 110 * 111 * @param cookie Cookie for the IRQ interface 112 * @param irq Information about the interrupt that is to be registered 113 * @param callback Callback function that is called when the interrupt arrives 114 * @param callback_data Pointer that is to be passed into the callback function 115 * 116 * @return A valid IRQ ID on success that has a value >= 0, otherwise an error code 117 */ 118typedef irq_id_t (*ps_irq_register_fn_t)(void *cookie, ps_irq_t irq, irq_callback_fn_t callback, void *callback_data); 119 120/* 121 * Unregisters a registered interrupt and deallocates any data that was 122 * associated with the registered interrupt. 123 * 124 * @param cookie Cookie for the IRQ interface 125 * @param irq_id An IRQ ID that was allocated by the IRQ interface 126 * 127 * @return 0 on success, otherwise an error code 128 */ 129typedef int (*ps_irq_unregister_fn_t)(void *cookie, irq_id_t irq_id); 130 131typedef struct { 132 void *cookie; 133 ps_irq_register_fn_t irq_register_fn; 134 ps_irq_unregister_fn_t irq_unregister_fn; 135} ps_irq_ops_t; 136 137static inline int ps_irq_register(ps_irq_ops_t *irq_ops, ps_irq_t irq, irq_callback_fn_t callback, void *callback_data) 138{ 139 __PS_IRQ_VALID_ARGS(irq_register_fn); 140 return irq_ops->irq_register_fn(irq_ops->cookie, irq, callback, callback_data); 141} 142 143static inline int ps_irq_unregister(ps_irq_ops_t *irq_ops, irq_id_t irq_id) 144{ 145 __PS_IRQ_VALID_ARGS(irq_unregister_fn); 146 return irq_ops->irq_unregister_fn(irq_ops->cookie, irq_id); 147} 148