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 424f31c84eSBen Skeggs if (nvkm_msec(device, 2000, 434f31c84eSBen Skeggs if (!(nvkm_rd32(device, 0x001308) & 0x00000100)) 444f31c84eSBen Skeggs break; 454f31c84eSBen Skeggs ) < 0) 464f31c84eSBen Skeggs return -ETIMEDOUT; 474f31c84eSBen Skeggs 484f31c84eSBen Skeggs return 0; 49c39f472eSBen Skeggs } 50c39f472eSBen Skeggs 51c39f472eSBen Skeggs void 525f8824deSBen Skeggs nv50_bus_intr(struct nvkm_subdev *subdev) 53c39f472eSBen Skeggs { 5401d6b956SBen Skeggs struct nvkm_bus *bus = nvkm_bus(subdev); 5514caba44SBen Skeggs struct nvkm_device *device = bus->subdev.device; 5614caba44SBen Skeggs u32 stat = nvkm_rd32(device, 0x001100) & nvkm_rd32(device, 0x001140); 57c39f472eSBen Skeggs 58c39f472eSBen Skeggs if (stat & 0x00000008) { 5914caba44SBen Skeggs u32 addr = nvkm_rd32(device, 0x009084); 6014caba44SBen Skeggs u32 data = nvkm_rd32(device, 0x009088); 61c39f472eSBen Skeggs 6201d6b956SBen Skeggs nv_error(bus, "MMIO %s of 0x%08x FAULT at 0x%06x\n", 63c39f472eSBen Skeggs (addr & 0x00000002) ? "write" : "read", data, 64c39f472eSBen Skeggs (addr & 0x00fffffc)); 65c39f472eSBen Skeggs 66c39f472eSBen Skeggs stat &= ~0x00000008; 6714caba44SBen Skeggs nvkm_wr32(device, 0x001100, 0x00000008); 68c39f472eSBen Skeggs } 69c39f472eSBen Skeggs 70c39f472eSBen Skeggs if (stat & 0x00010000) { 7101d6b956SBen Skeggs subdev = nvkm_subdev(bus, NVDEV_SUBDEV_THERM); 72c39f472eSBen Skeggs if (subdev && subdev->intr) 73c39f472eSBen Skeggs subdev->intr(subdev); 74c39f472eSBen Skeggs stat &= ~0x00010000; 7514caba44SBen Skeggs nvkm_wr32(device, 0x001100, 0x00010000); 76c39f472eSBen Skeggs } 77c39f472eSBen Skeggs 78c39f472eSBen Skeggs if (stat) { 7901d6b956SBen Skeggs nv_error(bus, "unknown intr 0x%08x\n", stat); 8014caba44SBen Skeggs nvkm_mask(device, 0x001140, stat, 0); 81c39f472eSBen Skeggs } 82c39f472eSBen Skeggs } 83c39f472eSBen Skeggs 84c39f472eSBen Skeggs int 855f8824deSBen Skeggs nv50_bus_init(struct nvkm_object *object) 86c39f472eSBen Skeggs { 8701d6b956SBen Skeggs struct nvkm_bus *bus = (void *)object; 8814caba44SBen Skeggs struct nvkm_device *device = bus->subdev.device; 89c39f472eSBen Skeggs int ret; 90c39f472eSBen Skeggs 9101d6b956SBen Skeggs ret = nvkm_bus_init(bus); 92c39f472eSBen Skeggs if (ret) 93c39f472eSBen Skeggs return ret; 94c39f472eSBen Skeggs 9514caba44SBen Skeggs nvkm_wr32(device, 0x001100, 0xffffffff); 9614caba44SBen Skeggs nvkm_wr32(device, 0x001140, 0x00010008); 97c39f472eSBen Skeggs return 0; 98c39f472eSBen Skeggs } 99c39f472eSBen Skeggs 1005f8824deSBen Skeggs struct nvkm_oclass * 101c39f472eSBen Skeggs nv50_bus_oclass = &(struct nv04_bus_impl) { 102c39f472eSBen Skeggs .base.handle = NV_SUBDEV(BUS, 0x50), 1035f8824deSBen Skeggs .base.ofuncs = &(struct nvkm_ofuncs) { 104c39f472eSBen Skeggs .ctor = nv04_bus_ctor, 1055f8824deSBen Skeggs .dtor = _nvkm_bus_dtor, 106c39f472eSBen Skeggs .init = nv50_bus_init, 1075f8824deSBen Skeggs .fini = _nvkm_bus_fini, 108c39f472eSBen Skeggs }, 109c39f472eSBen Skeggs .intr = nv50_bus_intr, 110c39f472eSBen Skeggs .hwsq_exec = nv50_bus_hwsq_exec, 111c39f472eSBen Skeggs .hwsq_size = 64, 112c39f472eSBen Skeggs }.base; 113