1c39f472eSBen Skeggs /* 2c39f472eSBen Skeggs * Copyright 2012 Nouveau Community 3c39f472eSBen Skeggs * 4c39f472eSBen Skeggs * Permission is hereby granted, free of charge, to any person obtaining a 5c39f472eSBen Skeggs * copy of this software and associated documentation files (the "Software"), 6c39f472eSBen Skeggs * to deal in the Software without restriction, including without limitation 7c39f472eSBen Skeggs * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8c39f472eSBen Skeggs * and/or sell copies of the Software, and to permit persons to whom the 9c39f472eSBen Skeggs * Software is furnished to do so, subject to the following conditions: 10c39f472eSBen Skeggs * 11c39f472eSBen Skeggs * The above copyright notice and this permission notice shall be included in 12c39f472eSBen Skeggs * all copies or substantial portions of the Software. 13c39f472eSBen Skeggs * 14c39f472eSBen Skeggs * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15c39f472eSBen Skeggs * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16c39f472eSBen Skeggs * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17c39f472eSBen Skeggs * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 18c39f472eSBen Skeggs * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 19c39f472eSBen Skeggs * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 20c39f472eSBen Skeggs * OTHER DEALINGS IN THE SOFTWARE. 21c39f472eSBen Skeggs * 22c39f472eSBen Skeggs * Authors: Martin Peres <martin.peres@labri.fr> 23c39f472eSBen Skeggs * Ben Skeggs 24c39f472eSBen Skeggs */ 255f8824deSBen Skeggs #include "nv04.h" 26c39f472eSBen Skeggs 27c39f472eSBen Skeggs #include <subdev/timer.h> 28c39f472eSBen Skeggs 29c39f472eSBen Skeggs static int 3001d6b956SBen Skeggs nv50_bus_hwsq_exec(struct nvkm_bus *bus, u32 *data, u32 size) 31c39f472eSBen Skeggs { 3214caba44SBen Skeggs struct nvkm_device *device = bus->subdev.device; 33c39f472eSBen Skeggs int i; 34c39f472eSBen Skeggs 3514caba44SBen Skeggs nvkm_mask(device, 0x001098, 0x00000008, 0x00000000); 3614caba44SBen Skeggs nvkm_wr32(device, 0x001304, 0x00000000); 37c39f472eSBen Skeggs for (i = 0; i < size; i++) 3814caba44SBen Skeggs nvkm_wr32(device, 0x001400 + (i * 4), data[i]); 3914caba44SBen Skeggs nvkm_mask(device, 0x001098, 0x00000018, 0x00000018); 4014caba44SBen Skeggs nvkm_wr32(device, 0x00130c, 0x00000003); 41c39f472eSBen Skeggs 4201d6b956SBen Skeggs return nv_wait(bus, 0x001308, 0x00000100, 0x00000000) ? 0 : -ETIMEDOUT; 43c39f472eSBen Skeggs } 44c39f472eSBen Skeggs 45c39f472eSBen Skeggs void 465f8824deSBen Skeggs nv50_bus_intr(struct nvkm_subdev *subdev) 47c39f472eSBen Skeggs { 4801d6b956SBen Skeggs struct nvkm_bus *bus = nvkm_bus(subdev); 4914caba44SBen Skeggs struct nvkm_device *device = bus->subdev.device; 5014caba44SBen Skeggs u32 stat = nvkm_rd32(device, 0x001100) & nvkm_rd32(device, 0x001140); 51c39f472eSBen Skeggs 52c39f472eSBen Skeggs if (stat & 0x00000008) { 5314caba44SBen Skeggs u32 addr = nvkm_rd32(device, 0x009084); 5414caba44SBen Skeggs u32 data = nvkm_rd32(device, 0x009088); 55c39f472eSBen Skeggs 5601d6b956SBen Skeggs nv_error(bus, "MMIO %s of 0x%08x FAULT at 0x%06x\n", 57c39f472eSBen Skeggs (addr & 0x00000002) ? "write" : "read", data, 58c39f472eSBen Skeggs (addr & 0x00fffffc)); 59c39f472eSBen Skeggs 60c39f472eSBen Skeggs stat &= ~0x00000008; 6114caba44SBen Skeggs nvkm_wr32(device, 0x001100, 0x00000008); 62c39f472eSBen Skeggs } 63c39f472eSBen Skeggs 64c39f472eSBen Skeggs if (stat & 0x00010000) { 6501d6b956SBen Skeggs subdev = nvkm_subdev(bus, NVDEV_SUBDEV_THERM); 66c39f472eSBen Skeggs if (subdev && subdev->intr) 67c39f472eSBen Skeggs subdev->intr(subdev); 68c39f472eSBen Skeggs stat &= ~0x00010000; 6914caba44SBen Skeggs nvkm_wr32(device, 0x001100, 0x00010000); 70c39f472eSBen Skeggs } 71c39f472eSBen Skeggs 72c39f472eSBen Skeggs if (stat) { 7301d6b956SBen Skeggs nv_error(bus, "unknown intr 0x%08x\n", stat); 7414caba44SBen Skeggs nvkm_mask(device, 0x001140, stat, 0); 75c39f472eSBen Skeggs } 76c39f472eSBen Skeggs } 77c39f472eSBen Skeggs 78c39f472eSBen Skeggs int 795f8824deSBen Skeggs nv50_bus_init(struct nvkm_object *object) 80c39f472eSBen Skeggs { 8101d6b956SBen Skeggs struct nvkm_bus *bus = (void *)object; 8214caba44SBen Skeggs struct nvkm_device *device = bus->subdev.device; 83c39f472eSBen Skeggs int ret; 84c39f472eSBen Skeggs 8501d6b956SBen Skeggs ret = nvkm_bus_init(bus); 86c39f472eSBen Skeggs if (ret) 87c39f472eSBen Skeggs return ret; 88c39f472eSBen Skeggs 8914caba44SBen Skeggs nvkm_wr32(device, 0x001100, 0xffffffff); 9014caba44SBen Skeggs nvkm_wr32(device, 0x001140, 0x00010008); 91c39f472eSBen Skeggs return 0; 92c39f472eSBen Skeggs } 93c39f472eSBen Skeggs 945f8824deSBen Skeggs struct nvkm_oclass * 95c39f472eSBen Skeggs nv50_bus_oclass = &(struct nv04_bus_impl) { 96c39f472eSBen Skeggs .base.handle = NV_SUBDEV(BUS, 0x50), 975f8824deSBen Skeggs .base.ofuncs = &(struct nvkm_ofuncs) { 98c39f472eSBen Skeggs .ctor = nv04_bus_ctor, 995f8824deSBen Skeggs .dtor = _nvkm_bus_dtor, 100c39f472eSBen Skeggs .init = nv50_bus_init, 1015f8824deSBen Skeggs .fini = _nvkm_bus_fini, 102c39f472eSBen Skeggs }, 103c39f472eSBen Skeggs .intr = nv50_bus_intr, 104c39f472eSBen Skeggs .hwsq_exec = nv50_bus_hwsq_exec, 105c39f472eSBen Skeggs .hwsq_size = 64, 106c39f472eSBen Skeggs }.base; 107