13e55b53bSBen Skeggs /*
23e55b53bSBen Skeggs * Copyright 2015 Red Hat Inc.
33e55b53bSBen Skeggs *
43e55b53bSBen Skeggs * Permission is hereby granted, free of charge, to any person obtaining a
53e55b53bSBen Skeggs * copy of this software and associated documentation files (the "Software"),
63e55b53bSBen Skeggs * to deal in the Software without restriction, including without limitation
73e55b53bSBen Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83e55b53bSBen Skeggs * and/or sell copies of the Software, and to permit persons to whom the
93e55b53bSBen Skeggs * Software is furnished to do so, subject to the following conditions:
103e55b53bSBen Skeggs *
113e55b53bSBen Skeggs * The above copyright notice and this permission notice shall be included in
123e55b53bSBen Skeggs * all copies or substantial portions of the Software.
133e55b53bSBen Skeggs *
143e55b53bSBen Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
153e55b53bSBen Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
163e55b53bSBen Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
173e55b53bSBen Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
183e55b53bSBen Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
193e55b53bSBen Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
203e55b53bSBen Skeggs * OTHER DEALINGS IN THE SOFTWARE.
213e55b53bSBen Skeggs *
223e55b53bSBen Skeggs * Authors: Ben Skeggs <bskeggs@redhat.com>
233e55b53bSBen Skeggs */
243e55b53bSBen Skeggs #include "priv.h"
253e55b53bSBen Skeggs
263e55b53bSBen Skeggs #include <core/pci.h>
273e55b53bSBen Skeggs
285cca4bdcSKarol Herbst static int
g84_pcie_version_supported(struct nvkm_pci * pci)295cca4bdcSKarol Herbst g84_pcie_version_supported(struct nvkm_pci *pci)
305cca4bdcSKarol Herbst {
315cca4bdcSKarol Herbst /* g84 and g86 report wrong information about what they support */
325cca4bdcSKarol Herbst return 1;
335cca4bdcSKarol Herbst }
345cca4bdcSKarol Herbst
355cca4bdcSKarol Herbst int
g84_pcie_version(struct nvkm_pci * pci)365cca4bdcSKarol Herbst g84_pcie_version(struct nvkm_pci *pci)
375cca4bdcSKarol Herbst {
385cca4bdcSKarol Herbst struct nvkm_device *device = pci->subdev.device;
395cca4bdcSKarol Herbst return (nvkm_rd32(device, 0x00154c) & 0x1) + 1;
405cca4bdcSKarol Herbst }
415cca4bdcSKarol Herbst
425cca4bdcSKarol Herbst void
g84_pcie_set_version(struct nvkm_pci * pci,u8 ver)435cca4bdcSKarol Herbst g84_pcie_set_version(struct nvkm_pci *pci, u8 ver)
445cca4bdcSKarol Herbst {
455cca4bdcSKarol Herbst struct nvkm_device *device = pci->subdev.device;
465cca4bdcSKarol Herbst nvkm_mask(device, 0x00154c, 0x1, (ver >= 2 ? 0x1 : 0x0));
475cca4bdcSKarol Herbst }
485cca4bdcSKarol Herbst
495cca4bdcSKarol Herbst static void
g84_pcie_set_cap_speed(struct nvkm_pci * pci,bool full_speed)505cca4bdcSKarol Herbst g84_pcie_set_cap_speed(struct nvkm_pci *pci, bool full_speed)
515cca4bdcSKarol Herbst {
525cca4bdcSKarol Herbst struct nvkm_device *device = pci->subdev.device;
535cca4bdcSKarol Herbst nvkm_mask(device, 0x00154c, 0x80, full_speed ? 0x80 : 0x0);
545cca4bdcSKarol Herbst }
555cca4bdcSKarol Herbst
565cca4bdcSKarol Herbst enum nvkm_pcie_speed
g84_pcie_cur_speed(struct nvkm_pci * pci)575cca4bdcSKarol Herbst g84_pcie_cur_speed(struct nvkm_pci *pci)
585cca4bdcSKarol Herbst {
595cca4bdcSKarol Herbst u32 reg_v = nvkm_pci_rd32(pci, 0x88) & 0x30000;
605cca4bdcSKarol Herbst switch (reg_v) {
615cca4bdcSKarol Herbst case 0x30000:
625cca4bdcSKarol Herbst return NVKM_PCIE_SPEED_8_0;
635cca4bdcSKarol Herbst case 0x20000:
645cca4bdcSKarol Herbst return NVKM_PCIE_SPEED_5_0;
655cca4bdcSKarol Herbst case 0x10000:
665cca4bdcSKarol Herbst default:
675cca4bdcSKarol Herbst return NVKM_PCIE_SPEED_2_5;
685cca4bdcSKarol Herbst }
695cca4bdcSKarol Herbst }
705cca4bdcSKarol Herbst
715cca4bdcSKarol Herbst enum nvkm_pcie_speed
g84_pcie_max_speed(struct nvkm_pci * pci)725cca4bdcSKarol Herbst g84_pcie_max_speed(struct nvkm_pci *pci)
735cca4bdcSKarol Herbst {
745cca4bdcSKarol Herbst u32 reg_v = nvkm_pci_rd32(pci, 0x460) & 0x3300;
755cca4bdcSKarol Herbst if (reg_v == 0x2200)
765cca4bdcSKarol Herbst return NVKM_PCIE_SPEED_5_0;
775cca4bdcSKarol Herbst return NVKM_PCIE_SPEED_2_5;
785cca4bdcSKarol Herbst }
795cca4bdcSKarol Herbst
805cca4bdcSKarol Herbst void
g84_pcie_set_link_speed(struct nvkm_pci * pci,enum nvkm_pcie_speed speed)815cca4bdcSKarol Herbst g84_pcie_set_link_speed(struct nvkm_pci *pci, enum nvkm_pcie_speed speed)
825cca4bdcSKarol Herbst {
835cca4bdcSKarol Herbst u32 mask_value;
845cca4bdcSKarol Herbst
855cca4bdcSKarol Herbst if (speed == NVKM_PCIE_SPEED_5_0)
865cca4bdcSKarol Herbst mask_value = 0x20;
875cca4bdcSKarol Herbst else
885cca4bdcSKarol Herbst mask_value = 0x10;
895cca4bdcSKarol Herbst
905cca4bdcSKarol Herbst nvkm_pci_mask(pci, 0x460, 0x30, mask_value);
915cca4bdcSKarol Herbst nvkm_pci_mask(pci, 0x460, 0x1, 0x1);
925cca4bdcSKarol Herbst }
935cca4bdcSKarol Herbst
945cca4bdcSKarol Herbst int
g84_pcie_set_link(struct nvkm_pci * pci,enum nvkm_pcie_speed speed,u8 width)955cca4bdcSKarol Herbst g84_pcie_set_link(struct nvkm_pci *pci, enum nvkm_pcie_speed speed, u8 width)
965cca4bdcSKarol Herbst {
975cca4bdcSKarol Herbst g84_pcie_set_cap_speed(pci, speed == NVKM_PCIE_SPEED_5_0);
985cca4bdcSKarol Herbst g84_pcie_set_link_speed(pci, speed);
995cca4bdcSKarol Herbst return 0;
1005cca4bdcSKarol Herbst }
1015cca4bdcSKarol Herbst
1025d5b43f5SPierre Moreau void
g84_pci_init(struct nvkm_pci * pci)1035d5b43f5SPierre Moreau g84_pci_init(struct nvkm_pci *pci)
1045d5b43f5SPierre Moreau {
1055d5b43f5SPierre Moreau /* The following only concerns PCIe cards. */
1065d5b43f5SPierre Moreau if (!pci_is_pcie(pci->pdev))
1075d5b43f5SPierre Moreau return;
1085d5b43f5SPierre Moreau
1095d5b43f5SPierre Moreau /* Tag field is 8-bit long, regardless of EXT_TAG.
1105d5b43f5SPierre Moreau * However, if EXT_TAG is disabled, only the lower 5 bits of the tag
1115d5b43f5SPierre Moreau * field should be used, limiting the number of request to 32.
1125d5b43f5SPierre Moreau *
1135d5b43f5SPierre Moreau * Apparently, 0x041c stores some limit on the number of requests
1145d5b43f5SPierre Moreau * possible, so if EXT_TAG is disabled, limit that requests number to
1155d5b43f5SPierre Moreau * 32
1165d5b43f5SPierre Moreau *
1175d5b43f5SPierre Moreau * Fixes fdo#86537
1185d5b43f5SPierre Moreau */
1195d5b43f5SPierre Moreau if (nvkm_pci_rd32(pci, 0x007c) & 0x00000020)
1205d5b43f5SPierre Moreau nvkm_pci_mask(pci, 0x0080, 0x00000100, 0x00000100);
1215d5b43f5SPierre Moreau else
1225d5b43f5SPierre Moreau nvkm_pci_mask(pci, 0x041c, 0x00000060, 0x00000000);
1235d5b43f5SPierre Moreau }
1245d5b43f5SPierre Moreau
1255cca4bdcSKarol Herbst int
g84_pcie_init(struct nvkm_pci * pci)1265cca4bdcSKarol Herbst g84_pcie_init(struct nvkm_pci *pci)
1275cca4bdcSKarol Herbst {
1285cca4bdcSKarol Herbst bool full_speed = g84_pcie_cur_speed(pci) == NVKM_PCIE_SPEED_5_0;
1295cca4bdcSKarol Herbst g84_pcie_set_cap_speed(pci, full_speed);
1305cca4bdcSKarol Herbst return 0;
1315cca4bdcSKarol Herbst }
1325cca4bdcSKarol Herbst
1333e55b53bSBen Skeggs static const struct nvkm_pci_func
1343e55b53bSBen Skeggs g84_pci_func = {
1355d5b43f5SPierre Moreau .init = g84_pci_init,
1363e55b53bSBen Skeggs .rd32 = nv40_pci_rd32,
1373e55b53bSBen Skeggs .wr08 = nv40_pci_wr08,
1383e55b53bSBen Skeggs .wr32 = nv40_pci_wr32,
139c4266a9cSBen Skeggs .msi_rearm = nv46_pci_msi_rearm,
1405cca4bdcSKarol Herbst
1415cca4bdcSKarol Herbst .pcie.init = g84_pcie_init,
1425cca4bdcSKarol Herbst .pcie.set_link = g84_pcie_set_link,
1435cca4bdcSKarol Herbst
1445cca4bdcSKarol Herbst .pcie.max_speed = g84_pcie_max_speed,
1455cca4bdcSKarol Herbst .pcie.cur_speed = g84_pcie_cur_speed,
1465cca4bdcSKarol Herbst
1475cca4bdcSKarol Herbst .pcie.set_version = g84_pcie_set_version,
1485cca4bdcSKarol Herbst .pcie.version = g84_pcie_version,
1495cca4bdcSKarol Herbst .pcie.version_supported = g84_pcie_version_supported,
1503e55b53bSBen Skeggs };
1513e55b53bSBen Skeggs
1523e55b53bSBen Skeggs int
g84_pci_new(struct nvkm_device * device,enum nvkm_subdev_type type,int inst,struct nvkm_pci ** ppci)153*9b70cd54SBen Skeggs g84_pci_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
154*9b70cd54SBen Skeggs struct nvkm_pci **ppci)
1553e55b53bSBen Skeggs {
156*9b70cd54SBen Skeggs return nvkm_pci_new_(&g84_pci_func, device, type, inst, ppci);
1573e55b53bSBen Skeggs }
158