File Index
Files and directories
Sign in
FILE

base.c

File preview with syntax highlighting.

linux-6.19.14/drivers/gpu/drm/nouveau/nvkm/subdev/pci/base.c C
  1/*
  2 * Copyright 2015 Red Hat Inc.
  3 *
  4 * Permission is hereby granted, free of charge, to any person obtaining a
  5 * copy of this software and associated documentation files (the "Software"),
  6 * to deal in the Software without restriction, including without limitation
  7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8 * and/or sell copies of the Software, and to permit persons to whom the
  9 * Software is furnished to do so, subject to the following conditions:
 10 *
 11 * The above copyright notice and this permission notice shall be included in
 12 * all copies or substantial portions of the Software.
 13 *
 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
 17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
 18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
 19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 20 * OTHER DEALINGS IN THE SOFTWARE.
 21 *
 22 * Authors: Ben Skeggs <bskeggs@redhat.com>
 23 */
 24#include "priv.h"
 25#include "agp.h"
 26
 27#include <core/option.h>
 28#include <core/pci.h>
 29
 30void
 31nvkm_pci_msi_rearm(struct nvkm_device *device)
 32{
 33	struct nvkm_pci *pci = device->pci;
 34
 35	if (pci && pci->msi)
 36		pci->func->msi_rearm(pci);
 37}
 38
 39u32
 40nvkm_pci_rd32(struct nvkm_pci *pci, u16 addr)
 41{
 42	return nvkm_rd32(pci->subdev.device, pci->func->cfg.addr + addr);
 43}
 44
 45void
 46nvkm_pci_wr08(struct nvkm_pci *pci, u16 addr, u8 data)
 47{
 48	nvkm_wr08(pci->subdev.device, pci->func->cfg.addr + addr, data);
 49}
 50
 51void
 52nvkm_pci_wr32(struct nvkm_pci *pci, u16 addr, u32 data)
 53{
 54	nvkm_wr32(pci->subdev.device, pci->func->cfg.addr + addr, data);
 55}
 56
 57u32
 58nvkm_pci_mask(struct nvkm_pci *pci, u16 addr, u32 mask, u32 value)
 59{
 60	u32 data = nvkm_pci_rd32(pci, addr);
 61	nvkm_pci_wr32(pci, addr, (data & ~mask) | value);
 62	return data;
 63}
 64
 65void
 66nvkm_pci_rom_shadow(struct nvkm_pci *pci, bool shadow)
 67{
 68	u32 data = nvkm_pci_rd32(pci, 0x0050);
 69	if (shadow)
 70		data |=  0x00000001;
 71	else
 72		data &= ~0x00000001;
 73	nvkm_pci_wr32(pci, 0x0050, data);
 74}
 75
 76static int
 77nvkm_pci_fini(struct nvkm_subdev *subdev, enum nvkm_suspend_state suspend)
 78{
 79	struct nvkm_pci *pci = nvkm_pci(subdev);
 80
 81	if (pci->agp.bridge)
 82		nvkm_agp_fini(pci);
 83
 84	return 0;
 85}
 86
 87static int
 88nvkm_pci_preinit(struct nvkm_subdev *subdev)
 89{
 90	struct nvkm_pci *pci = nvkm_pci(subdev);
 91	if (pci->agp.bridge)
 92		nvkm_agp_preinit(pci);
 93	return 0;
 94}
 95
 96static int
 97nvkm_pci_oneinit(struct nvkm_subdev *subdev)
 98{
 99	struct nvkm_pci *pci = nvkm_pci(subdev);
100	int ret;
101
102	if (pci_is_pcie(pci->pdev)) {
103		ret = nvkm_pcie_oneinit(pci);
104		if (ret)
105			return ret;
106	}
107
108	return 0;
109}
110
111static int
112nvkm_pci_init(struct nvkm_subdev *subdev)
113{
114	struct nvkm_pci *pci = nvkm_pci(subdev);
115	int ret;
116
117	if (pci->agp.bridge) {
118		ret = nvkm_agp_init(pci);
119		if (ret)
120			return ret;
121	} else if (pci_is_pcie(pci->pdev)) {
122		nvkm_pcie_init(pci);
123	}
124
125	if (pci->func->init)
126		pci->func->init(pci);
127
128	/* Ensure MSI interrupts are armed, for the case where there are
129	 * already interrupts pending (for whatever reason) at load time.
130	 */
131	if (pci->msi)
132		pci->func->msi_rearm(pci);
133
134	return 0;
135}
136
137static void *
138nvkm_pci_dtor(struct nvkm_subdev *subdev)
139{
140	struct nvkm_pci *pci = nvkm_pci(subdev);
141
142	nvkm_agp_dtor(pci);
143
144	if (pci->msi)
145		pci_disable_msi(pci->pdev);
146
147	return nvkm_pci(subdev);
148}
149
150static const struct nvkm_subdev_func
151nvkm_pci_func = {
152	.dtor = nvkm_pci_dtor,
153	.oneinit = nvkm_pci_oneinit,
154	.preinit = nvkm_pci_preinit,
155	.init = nvkm_pci_init,
156	.fini = nvkm_pci_fini,
157};
158
159int
160nvkm_pci_new_(const struct nvkm_pci_func *func, struct nvkm_device *device,
161	      enum nvkm_subdev_type type, int inst, struct nvkm_pci **ppci)
162{
163	struct nvkm_pci *pci;
164
165	if (!(pci = *ppci = kzalloc(sizeof(**ppci), GFP_KERNEL)))
166		return -ENOMEM;
167	nvkm_subdev_ctor(&nvkm_pci_func, device, type, inst, &pci->subdev);
168	pci->func = func;
169	pci->pdev = device->func->pci(device)->pdev;
170	pci->pcie.speed = -1;
171	pci->pcie.width = -1;
172
173	if (device->type == NVKM_DEVICE_AGP)
174		nvkm_agp_ctor(pci);
175
176	switch (pci->pdev->device & 0x0ff0) {
177	case 0x00f0:
178	case 0x02e0:
179		/* BR02? NFI how these would be handled yet exactly */
180		break;
181	default:
182		switch (device->chipset) {
183		case 0xaa:
184			/* reported broken, nv also disable it */
185			break;
186		default:
187			pci->msi = true;
188			break;
189		}
190	}
191
192#ifdef __BIG_ENDIAN
193	pci->msi = false;
194#endif
195
196	pci->msi = nvkm_boolopt(device->cfgopt, "NvMSI", pci->msi);
197	if (pci->msi && func->msi_rearm) {
198		pci->msi = pci_enable_msi(pci->pdev) == 0;
199		if (pci->msi)
200			nvkm_debug(&pci->subdev, "MSI enabled\n");
201	} else {
202		pci->msi = false;
203	}
204
205	return 0;
206}
~/ Read-only file preview.