xref: /openbsd-src/sys/dev/pci/drm/amd/display/dc/irq/irq_service.c (revision f005ef32267c16bdb134f0e9fa4477dbe07c263a)
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