1fb4d8502Sjsg /*
2fb4d8502Sjsg * Copyright 2012-15 Advanced Micro Devices, Inc.
3fb4d8502Sjsg *
4fb4d8502Sjsg * Permission is hereby granted, free of charge, to any person obtaining a
5fb4d8502Sjsg * copy of this software and associated documentation files (the "Software"),
6fb4d8502Sjsg * to deal in the Software without restriction, including without limitation
7fb4d8502Sjsg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8fb4d8502Sjsg * and/or sell copies of the Software, and to permit persons to whom the
9fb4d8502Sjsg * Software is furnished to do so, subject to the following conditions:
10fb4d8502Sjsg *
11fb4d8502Sjsg * The above copyright notice and this permission notice shall be included in
12fb4d8502Sjsg * all copies or substantial portions of the Software.
13fb4d8502Sjsg *
14fb4d8502Sjsg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15fb4d8502Sjsg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16fb4d8502Sjsg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17fb4d8502Sjsg * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18fb4d8502Sjsg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19fb4d8502Sjsg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20fb4d8502Sjsg * OTHER DEALINGS IN THE SOFTWARE.
21fb4d8502Sjsg *
22fb4d8502Sjsg * Authors: AMD
23fb4d8502Sjsg *
24fb4d8502Sjsg */
25fb4d8502Sjsg
26fb4d8502Sjsg #include "dm_services.h"
27fb4d8502Sjsg
28fb4d8502Sjsg #include "include/irq_service_interface.h"
29fb4d8502Sjsg #include "include/logger_interface.h"
30fb4d8502Sjsg
31fb4d8502Sjsg #include "dce110/irq_service_dce110.h"
32fb4d8502Sjsg
33ad8b1aafSjsg #if defined(CONFIG_DRM_AMD_DC_SI)
34ad8b1aafSjsg #include "dce60/irq_service_dce60.h"
35ad8b1aafSjsg #endif
36fb4d8502Sjsg
37fb4d8502Sjsg #include "dce80/irq_service_dce80.h"
38fb4d8502Sjsg #include "dce120/irq_service_dce120.h"
39fb4d8502Sjsg #include "dcn10/irq_service_dcn10.h"
40fb4d8502Sjsg
41fb4d8502Sjsg #include "reg_helper.h"
42fb4d8502Sjsg #include "irq_service.h"
43fb4d8502Sjsg
44fb4d8502Sjsg
45fb4d8502Sjsg
46fb4d8502Sjsg #define CTX \
47fb4d8502Sjsg irq_service->ctx
48fb4d8502Sjsg #define DC_LOGGER \
49fb4d8502Sjsg irq_service->ctx->logger
50fb4d8502Sjsg
dal_irq_service_construct(struct irq_service * irq_service,struct irq_service_init_data * init_data)51fb4d8502Sjsg void dal_irq_service_construct(
52fb4d8502Sjsg struct irq_service *irq_service,
53fb4d8502Sjsg struct irq_service_init_data *init_data)
54fb4d8502Sjsg {
55fb4d8502Sjsg if (!init_data || !init_data->ctx) {
56fb4d8502Sjsg BREAK_TO_DEBUGGER();
57fb4d8502Sjsg return;
58fb4d8502Sjsg }
59fb4d8502Sjsg
60fb4d8502Sjsg irq_service->ctx = init_data->ctx;
61fb4d8502Sjsg }
62fb4d8502Sjsg
dal_irq_service_destroy(struct irq_service ** irq_service)63fb4d8502Sjsg void dal_irq_service_destroy(struct irq_service **irq_service)
64fb4d8502Sjsg {
65fb4d8502Sjsg if (!irq_service || !*irq_service) {
66fb4d8502Sjsg BREAK_TO_DEBUGGER();
67fb4d8502Sjsg return;
68fb4d8502Sjsg }
69fb4d8502Sjsg
70fb4d8502Sjsg kfree(*irq_service);
71fb4d8502Sjsg
72fb4d8502Sjsg *irq_service = NULL;
73fb4d8502Sjsg }
74fb4d8502Sjsg
find_irq_source_info(struct irq_service * irq_service,enum dc_irq_source source)755ca02815Sjsg static const struct irq_source_info *find_irq_source_info(
76fb4d8502Sjsg struct irq_service *irq_service,
77fb4d8502Sjsg enum dc_irq_source source)
78fb4d8502Sjsg {
79fb4d8502Sjsg if (source >= DAL_IRQ_SOURCES_NUMBER || source < DC_IRQ_SOURCE_INVALID)
80fb4d8502Sjsg return NULL;
81fb4d8502Sjsg
82fb4d8502Sjsg return &irq_service->info[source];
83fb4d8502Sjsg }
84fb4d8502Sjsg
dal_irq_service_set_generic(struct irq_service * irq_service,const struct irq_source_info * info,bool enable)85fb4d8502Sjsg void dal_irq_service_set_generic(
86fb4d8502Sjsg struct irq_service *irq_service,
87fb4d8502Sjsg const struct irq_source_info *info,
88fb4d8502Sjsg bool enable)
89fb4d8502Sjsg {
90fb4d8502Sjsg uint32_t addr = info->enable_reg;
91fb4d8502Sjsg uint32_t value = dm_read_reg(irq_service->ctx, addr);
92fb4d8502Sjsg
93fb4d8502Sjsg value = (value & ~info->enable_mask) |
94fb4d8502Sjsg (info->enable_value[enable ? 0 : 1] & info->enable_mask);
95fb4d8502Sjsg dm_write_reg(irq_service->ctx, addr, value);
96fb4d8502Sjsg }
97fb4d8502Sjsg
dal_irq_service_set(struct irq_service * irq_service,enum dc_irq_source source,bool enable)98fb4d8502Sjsg bool dal_irq_service_set(
99fb4d8502Sjsg struct irq_service *irq_service,
100fb4d8502Sjsg enum dc_irq_source source,
101fb4d8502Sjsg bool enable)
102fb4d8502Sjsg {
103fb4d8502Sjsg const struct irq_source_info *info =
104fb4d8502Sjsg find_irq_source_info(irq_service, source);
105fb4d8502Sjsg
106fb4d8502Sjsg if (!info) {
107fb4d8502Sjsg DC_LOG_ERROR("%s: cannot find irq info table entry for %d\n",
108fb4d8502Sjsg __func__,
109fb4d8502Sjsg source);
110fb4d8502Sjsg return false;
111fb4d8502Sjsg }
112fb4d8502Sjsg
113fb4d8502Sjsg dal_irq_service_ack(irq_service, source);
114fb4d8502Sjsg
115*f005ef32Sjsg if (info->funcs && info->funcs->set) {
116*f005ef32Sjsg if (info->funcs->set == dal_irq_service_dummy_set) {
117*f005ef32Sjsg DC_LOG_WARNING("%s: src: %d, st: %d\n", __func__,
118*f005ef32Sjsg source, enable);
119*f005ef32Sjsg ASSERT(0);
120*f005ef32Sjsg }
121*f005ef32Sjsg
122fb4d8502Sjsg return info->funcs->set(irq_service, info, enable);
123*f005ef32Sjsg }
124fb4d8502Sjsg
125fb4d8502Sjsg dal_irq_service_set_generic(irq_service, info, enable);
126fb4d8502Sjsg
127fb4d8502Sjsg return true;
128fb4d8502Sjsg }
129fb4d8502Sjsg
dal_irq_service_ack_generic(struct irq_service * irq_service,const struct irq_source_info * info)130fb4d8502Sjsg void dal_irq_service_ack_generic(
131fb4d8502Sjsg struct irq_service *irq_service,
132fb4d8502Sjsg const struct irq_source_info *info)
133fb4d8502Sjsg {
134fb4d8502Sjsg uint32_t addr = info->ack_reg;
135fb4d8502Sjsg uint32_t value = dm_read_reg(irq_service->ctx, addr);
136fb4d8502Sjsg
137fb4d8502Sjsg value = (value & ~info->ack_mask) |
138fb4d8502Sjsg (info->ack_value & info->ack_mask);
139fb4d8502Sjsg dm_write_reg(irq_service->ctx, addr, value);
140fb4d8502Sjsg }
141fb4d8502Sjsg
dal_irq_service_ack(struct irq_service * irq_service,enum dc_irq_source source)142fb4d8502Sjsg bool dal_irq_service_ack(
143fb4d8502Sjsg struct irq_service *irq_service,
144fb4d8502Sjsg enum dc_irq_source source)
145fb4d8502Sjsg {
146fb4d8502Sjsg const struct irq_source_info *info =
147fb4d8502Sjsg find_irq_source_info(irq_service, source);
148fb4d8502Sjsg
149fb4d8502Sjsg if (!info) {
150fb4d8502Sjsg DC_LOG_ERROR("%s: cannot find irq info table entry for %d\n",
151fb4d8502Sjsg __func__,
152fb4d8502Sjsg source);
153fb4d8502Sjsg return false;
154fb4d8502Sjsg }
155fb4d8502Sjsg
156*f005ef32Sjsg if (info->funcs && info->funcs->ack) {
157*f005ef32Sjsg if (info->funcs->ack == dal_irq_service_dummy_ack) {
158*f005ef32Sjsg DC_LOG_WARNING("%s: src: %d\n", __func__, source);
159*f005ef32Sjsg ASSERT(0);
160*f005ef32Sjsg }
161*f005ef32Sjsg
162fb4d8502Sjsg return info->funcs->ack(irq_service, info);
163*f005ef32Sjsg }
164fb4d8502Sjsg
165fb4d8502Sjsg dal_irq_service_ack_generic(irq_service, info);
166fb4d8502Sjsg
167fb4d8502Sjsg return true;
168fb4d8502Sjsg }
169fb4d8502Sjsg
dal_irq_service_to_irq_source(struct irq_service * irq_service,uint32_t src_id,uint32_t ext_id)170fb4d8502Sjsg enum dc_irq_source dal_irq_service_to_irq_source(
171fb4d8502Sjsg struct irq_service *irq_service,
172fb4d8502Sjsg uint32_t src_id,
173fb4d8502Sjsg uint32_t ext_id)
174fb4d8502Sjsg {
175fb4d8502Sjsg return irq_service->funcs->to_dal_irq_source(
176fb4d8502Sjsg irq_service,
177fb4d8502Sjsg src_id,
178fb4d8502Sjsg ext_id);
179fb4d8502Sjsg }
180