1ebb58dc2SBen Skeggs /* 2ebb58dc2SBen Skeggs * Copyright 2013 Red Hat Inc. 3ebb58dc2SBen Skeggs * 4ebb58dc2SBen Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 5ebb58dc2SBen Skeggs * copy of this software and associated documentation files (the "Software"), 6ebb58dc2SBen Skeggs * to deal in the Software without restriction, including without limitation 7ebb58dc2SBen Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8ebb58dc2SBen Skeggs * and/or sell copies of the Software, and to permit persons to whom the 9ebb58dc2SBen Skeggs * Software is furnished to do so, subject to the following conditions: 10ebb58dc2SBen Skeggs * 11ebb58dc2SBen Skeggs * The above copyright notice and this permission notice shall be included in 12ebb58dc2SBen Skeggs * all copies or substantial portions of the Software. 13ebb58dc2SBen Skeggs * 14ebb58dc2SBen Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15ebb58dc2SBen Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16ebb58dc2SBen Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17ebb58dc2SBen Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18ebb58dc2SBen Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19ebb58dc2SBen Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20ebb58dc2SBen Skeggs * OTHER DEALINGS IN THE SOFTWARE. 21ebb58dc2SBen Skeggs * 22ebb58dc2SBen Skeggs * Authors: Ben Skeggs 23ebb58dc2SBen Skeggs */ 2421b13791SBen Skeggs #define gf110_pmu_code gk104_pmu_code 2521b13791SBen Skeggs #define gf110_pmu_data gk104_pmu_data 26ebb58dc2SBen Skeggs #include "priv.h" 2721b13791SBen Skeggs #include "fuc/gf110.fuc4.h" 28ebb58dc2SBen Skeggs 29205877f9SBen Skeggs #include <core/device.h> 30205877f9SBen Skeggs #include <core/option.h> 31205877f9SBen Skeggs #include <subdev/timer.h> 32205877f9SBen Skeggs 33205877f9SBen Skeggs static void 34bef002e8SBen Skeggs magic_(struct nvkm_device *device, u32 ctrl, int size) 35205877f9SBen Skeggs { 36bef002e8SBen Skeggs nvkm_wr32(device, 0x00c800, 0x00000000); 37bef002e8SBen Skeggs nvkm_wr32(device, 0x00c808, 0x00000000); 38bef002e8SBen Skeggs nvkm_wr32(device, 0x00c800, ctrl); 39bef002e8SBen Skeggs if (nv_wait(device, 0x00c800, 0x40000000, 0x40000000)) { 40205877f9SBen Skeggs while (size--) 41bef002e8SBen Skeggs nvkm_wr32(device, 0x00c804, 0x00000000); 42205877f9SBen Skeggs } 43bef002e8SBen Skeggs nvkm_wr32(device, 0x00c800, 0x00000000); 44205877f9SBen Skeggs } 45205877f9SBen Skeggs 46205877f9SBen Skeggs static void 47bef002e8SBen Skeggs magic(struct nvkm_device *device, u32 ctrl) 48205877f9SBen Skeggs { 49bef002e8SBen Skeggs magic_(device, 0x8000a41f | ctrl, 6); 50bef002e8SBen Skeggs magic_(device, 0x80000421 | ctrl, 1); 51205877f9SBen Skeggs } 52205877f9SBen Skeggs 53ebb58dc2SBen Skeggs static void 5421b13791SBen Skeggs gk104_pmu_pgob(struct nvkm_pmu *pmu, bool enable) 55ebb58dc2SBen Skeggs { 56bef002e8SBen Skeggs struct nvkm_device *device = pmu->subdev.device; 57205877f9SBen Skeggs 58bef002e8SBen Skeggs nvkm_mask(device, 0x000200, 0x00001000, 0x00000000); 59bef002e8SBen Skeggs nvkm_rd32(device, 0x000200); 60bef002e8SBen Skeggs nvkm_mask(device, 0x000200, 0x08000000, 0x08000000); 61ebb58dc2SBen Skeggs msleep(50); 62ebb58dc2SBen Skeggs 63bef002e8SBen Skeggs nvkm_mask(device, 0x10a78c, 0x00000002, 0x00000002); 64bef002e8SBen Skeggs nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000001); 65bef002e8SBen Skeggs nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000000); 66ebb58dc2SBen Skeggs 67bef002e8SBen Skeggs nvkm_mask(device, 0x020004, 0xc0000000, enable ? 0xc0000000 : 0x40000000); 68ebb58dc2SBen Skeggs msleep(50); 69ebb58dc2SBen Skeggs 70bef002e8SBen Skeggs nvkm_mask(device, 0x10a78c, 0x00000002, 0x00000000); 71bef002e8SBen Skeggs nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000001); 72bef002e8SBen Skeggs nvkm_mask(device, 0x10a78c, 0x00000001, 0x00000000); 73ebb58dc2SBen Skeggs 74bef002e8SBen Skeggs nvkm_mask(device, 0x000200, 0x08000000, 0x00000000); 75bef002e8SBen Skeggs nvkm_mask(device, 0x000200, 0x00001000, 0x00001000); 76bef002e8SBen Skeggs nvkm_rd32(device, 0x000200); 77205877f9SBen Skeggs 78d351b856SBen Skeggs if (nv_device_match(device, 0x11fc, 0x17aa, 0x2211) /* Lenovo W541 */ 79d351b856SBen Skeggs || nv_device_match(device, 0x11fc, 0x17aa, 0x221e) /* Lenovo W541 */ 80205877f9SBen Skeggs || nvkm_boolopt(device->cfgopt, "War00C800_0", false)) { 81205877f9SBen Skeggs nv_info(pmu, "hw bug workaround enabled\n"); 82205877f9SBen Skeggs switch (device->chipset) { 83205877f9SBen Skeggs case 0xe4: 84bef002e8SBen Skeggs magic(device, 0x04000000); 85bef002e8SBen Skeggs magic(device, 0x06000000); 86bef002e8SBen Skeggs magic(device, 0x0c000000); 87bef002e8SBen Skeggs magic(device, 0x0e000000); 88205877f9SBen Skeggs break; 89205877f9SBen Skeggs case 0xe6: 90bef002e8SBen Skeggs magic(device, 0x02000000); 91bef002e8SBen Skeggs magic(device, 0x04000000); 92bef002e8SBen Skeggs magic(device, 0x0a000000); 93205877f9SBen Skeggs break; 94205877f9SBen Skeggs case 0xe7: 95bef002e8SBen Skeggs magic(device, 0x02000000); 96205877f9SBen Skeggs break; 97205877f9SBen Skeggs default: 98205877f9SBen Skeggs break; 99205877f9SBen Skeggs } 100205877f9SBen Skeggs } 101ebb58dc2SBen Skeggs } 102ebb58dc2SBen Skeggs 10321b13791SBen Skeggs struct nvkm_oclass * 104ebb58dc2SBen Skeggs gk104_pmu_oclass = &(struct nvkm_pmu_impl) { 105ebb58dc2SBen Skeggs .base.handle = NV_SUBDEV(PMU, 0xe4), 10621b13791SBen Skeggs .base.ofuncs = &(struct nvkm_ofuncs) { 10721b13791SBen Skeggs .ctor = _nvkm_pmu_ctor, 10821b13791SBen Skeggs .dtor = _nvkm_pmu_dtor, 10921b13791SBen Skeggs .init = _nvkm_pmu_init, 11021b13791SBen Skeggs .fini = _nvkm_pmu_fini, 111ebb58dc2SBen Skeggs }, 112ebb58dc2SBen Skeggs .code.data = gk104_pmu_code, 113ebb58dc2SBen Skeggs .code.size = sizeof(gk104_pmu_code), 114ebb58dc2SBen Skeggs .data.data = gk104_pmu_data, 115ebb58dc2SBen Skeggs .data.size = sizeof(gk104_pmu_data), 116ebb58dc2SBen Skeggs .pgob = gk104_pmu_pgob, 117ebb58dc2SBen Skeggs }.base; 118