0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "dm_services.h"
0027
0028 #include "include/irq_service_interface.h"
0029 #include "include/logger_interface.h"
0030
0031 #include "dce110/irq_service_dce110.h"
0032
0033 #if defined(CONFIG_DRM_AMD_DC_SI)
0034 #include "dce60/irq_service_dce60.h"
0035 #endif
0036
0037 #include "dce80/irq_service_dce80.h"
0038 #include "dce120/irq_service_dce120.h"
0039 #include "dcn10/irq_service_dcn10.h"
0040
0041 #include "reg_helper.h"
0042 #include "irq_service.h"
0043
0044
0045
0046 #define CTX \
0047 irq_service->ctx
0048 #define DC_LOGGER \
0049 irq_service->ctx->logger
0050
0051 void dal_irq_service_construct(
0052 struct irq_service *irq_service,
0053 struct irq_service_init_data *init_data)
0054 {
0055 if (!init_data || !init_data->ctx) {
0056 BREAK_TO_DEBUGGER();
0057 return;
0058 }
0059
0060 irq_service->ctx = init_data->ctx;
0061 }
0062
0063 void dal_irq_service_destroy(struct irq_service **irq_service)
0064 {
0065 if (!irq_service || !*irq_service) {
0066 BREAK_TO_DEBUGGER();
0067 return;
0068 }
0069
0070 kfree(*irq_service);
0071
0072 *irq_service = NULL;
0073 }
0074
0075 static const struct irq_source_info *find_irq_source_info(
0076 struct irq_service *irq_service,
0077 enum dc_irq_source source)
0078 {
0079 if (source >= DAL_IRQ_SOURCES_NUMBER || source < DC_IRQ_SOURCE_INVALID)
0080 return NULL;
0081
0082 return &irq_service->info[source];
0083 }
0084
0085 void dal_irq_service_set_generic(
0086 struct irq_service *irq_service,
0087 const struct irq_source_info *info,
0088 bool enable)
0089 {
0090 uint32_t addr = info->enable_reg;
0091 uint32_t value = dm_read_reg(irq_service->ctx, addr);
0092
0093 value = (value & ~info->enable_mask) |
0094 (info->enable_value[enable ? 0 : 1] & info->enable_mask);
0095 dm_write_reg(irq_service->ctx, addr, value);
0096 }
0097
0098 bool dal_irq_service_set(
0099 struct irq_service *irq_service,
0100 enum dc_irq_source source,
0101 bool enable)
0102 {
0103 const struct irq_source_info *info =
0104 find_irq_source_info(irq_service, source);
0105
0106 if (!info) {
0107 DC_LOG_ERROR("%s: cannot find irq info table entry for %d\n",
0108 __func__,
0109 source);
0110 return false;
0111 }
0112
0113 dal_irq_service_ack(irq_service, source);
0114
0115 if (info->funcs && info->funcs->set)
0116 return info->funcs->set(irq_service, info, enable);
0117
0118 dal_irq_service_set_generic(irq_service, info, enable);
0119
0120 return true;
0121 }
0122
0123 void dal_irq_service_ack_generic(
0124 struct irq_service *irq_service,
0125 const struct irq_source_info *info)
0126 {
0127 uint32_t addr = info->ack_reg;
0128 uint32_t value = dm_read_reg(irq_service->ctx, addr);
0129
0130 value = (value & ~info->ack_mask) |
0131 (info->ack_value & info->ack_mask);
0132 dm_write_reg(irq_service->ctx, addr, value);
0133 }
0134
0135 bool dal_irq_service_ack(
0136 struct irq_service *irq_service,
0137 enum dc_irq_source source)
0138 {
0139 const struct irq_source_info *info =
0140 find_irq_source_info(irq_service, source);
0141
0142 if (!info) {
0143 DC_LOG_ERROR("%s: cannot find irq info table entry for %d\n",
0144 __func__,
0145 source);
0146 return false;
0147 }
0148
0149 if (info->funcs && info->funcs->ack)
0150 return info->funcs->ack(irq_service, info);
0151
0152 dal_irq_service_ack_generic(irq_service, info);
0153
0154 return true;
0155 }
0156
0157 enum dc_irq_source dal_irq_service_to_irq_source(
0158 struct irq_service *irq_service,
0159 uint32_t src_id,
0160 uint32_t ext_id)
0161 {
0162 return irq_service->funcs->to_dal_irq_source(
0163 irq_service,
0164 src_id,
0165 ext_id);
0166 }