0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024 #include "priv.h"
0025
0026 #include <core/firmware.h>
0027 #include <subdev/timer.h>
0028
0029 bool
0030 nvkm_pmu_fan_controlled(struct nvkm_device *device)
0031 {
0032 struct nvkm_pmu *pmu = device->pmu;
0033
0034
0035
0036
0037 if (pmu && pmu->func->code.size)
0038 return false;
0039
0040
0041
0042
0043
0044 return (device->chipset >= 0xc0);
0045 }
0046
0047 void
0048 nvkm_pmu_pgob(struct nvkm_pmu *pmu, bool enable)
0049 {
0050 if (pmu && pmu->func->pgob)
0051 pmu->func->pgob(pmu, enable);
0052 }
0053
0054 static void
0055 nvkm_pmu_recv(struct work_struct *work)
0056 {
0057 struct nvkm_pmu *pmu = container_of(work, typeof(*pmu), recv.work);
0058 return pmu->func->recv(pmu);
0059 }
0060
0061 int
0062 nvkm_pmu_send(struct nvkm_pmu *pmu, u32 reply[2],
0063 u32 process, u32 message, u32 data0, u32 data1)
0064 {
0065 if (!pmu || !pmu->func->send)
0066 return -ENODEV;
0067 return pmu->func->send(pmu, reply, process, message, data0, data1);
0068 }
0069
0070 static void
0071 nvkm_pmu_intr(struct nvkm_subdev *subdev)
0072 {
0073 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
0074 if (!pmu->func->intr)
0075 return;
0076 pmu->func->intr(pmu);
0077 }
0078
0079 static int
0080 nvkm_pmu_fini(struct nvkm_subdev *subdev, bool suspend)
0081 {
0082 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
0083
0084 if (pmu->func->fini)
0085 pmu->func->fini(pmu);
0086
0087 flush_work(&pmu->recv.work);
0088
0089 reinit_completion(&pmu->wpr_ready);
0090
0091 nvkm_falcon_cmdq_fini(pmu->lpq);
0092 nvkm_falcon_cmdq_fini(pmu->hpq);
0093 pmu->initmsg_received = false;
0094 return 0;
0095 }
0096
0097 static void
0098 nvkm_pmu_reset(struct nvkm_pmu *pmu)
0099 {
0100 struct nvkm_device *device = pmu->subdev.device;
0101
0102 if (!pmu->func->enabled(pmu))
0103 return;
0104
0105
0106 if (pmu->func->reset)
0107 pmu->func->reset(pmu);
0108
0109
0110 nvkm_msec(device, 2000,
0111 if (!(nvkm_rd32(device, 0x10a10c) & 0x00000006))
0112 break;
0113 );
0114 }
0115
0116 static int
0117 nvkm_pmu_preinit(struct nvkm_subdev *subdev)
0118 {
0119 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
0120 nvkm_pmu_reset(pmu);
0121 return 0;
0122 }
0123
0124 static int
0125 nvkm_pmu_init(struct nvkm_subdev *subdev)
0126 {
0127 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
0128 struct nvkm_device *device = pmu->subdev.device;
0129
0130 if (!pmu->func->init)
0131 return 0;
0132
0133 if (pmu->func->enabled(pmu)) {
0134
0135 nvkm_wr32(device, 0x10a014, 0x0000ffff);
0136 nvkm_msec(device, 2000,
0137 if (!nvkm_rd32(device, 0x10a04c))
0138 break;
0139 );
0140
0141 nvkm_pmu_reset(pmu);
0142 }
0143
0144 return pmu->func->init(pmu);
0145 }
0146
0147 static void *
0148 nvkm_pmu_dtor(struct nvkm_subdev *subdev)
0149 {
0150 struct nvkm_pmu *pmu = nvkm_pmu(subdev);
0151 nvkm_falcon_msgq_del(&pmu->msgq);
0152 nvkm_falcon_cmdq_del(&pmu->lpq);
0153 nvkm_falcon_cmdq_del(&pmu->hpq);
0154 nvkm_falcon_qmgr_del(&pmu->qmgr);
0155 nvkm_falcon_dtor(&pmu->falcon);
0156 mutex_destroy(&pmu->send.mutex);
0157 return nvkm_pmu(subdev);
0158 }
0159
0160 static const struct nvkm_subdev_func
0161 nvkm_pmu = {
0162 .dtor = nvkm_pmu_dtor,
0163 .preinit = nvkm_pmu_preinit,
0164 .init = nvkm_pmu_init,
0165 .fini = nvkm_pmu_fini,
0166 .intr = nvkm_pmu_intr,
0167 };
0168
0169 int
0170 nvkm_pmu_ctor(const struct nvkm_pmu_fwif *fwif, struct nvkm_device *device,
0171 enum nvkm_subdev_type type, int inst, struct nvkm_pmu *pmu)
0172 {
0173 int ret;
0174
0175 nvkm_subdev_ctor(&nvkm_pmu, device, type, inst, &pmu->subdev);
0176
0177 mutex_init(&pmu->send.mutex);
0178
0179 INIT_WORK(&pmu->recv.work, nvkm_pmu_recv);
0180 init_waitqueue_head(&pmu->recv.wait);
0181
0182 fwif = nvkm_firmware_load(&pmu->subdev, fwif, "Pmu", pmu);
0183 if (IS_ERR(fwif))
0184 return PTR_ERR(fwif);
0185
0186 pmu->func = fwif->func;
0187
0188 ret = nvkm_falcon_ctor(pmu->func->flcn, &pmu->subdev, pmu->subdev.name,
0189 0x10a000, &pmu->falcon);
0190 if (ret)
0191 return ret;
0192
0193 if ((ret = nvkm_falcon_qmgr_new(&pmu->falcon, &pmu->qmgr)) ||
0194 (ret = nvkm_falcon_cmdq_new(pmu->qmgr, "hpq", &pmu->hpq)) ||
0195 (ret = nvkm_falcon_cmdq_new(pmu->qmgr, "lpq", &pmu->lpq)) ||
0196 (ret = nvkm_falcon_msgq_new(pmu->qmgr, "msgq", &pmu->msgq)))
0197 return ret;
0198
0199 init_completion(&pmu->wpr_ready);
0200 return 0;
0201 }
0202
0203 int
0204 nvkm_pmu_new_(const struct nvkm_pmu_fwif *fwif, struct nvkm_device *device,
0205 enum nvkm_subdev_type type, int inst, struct nvkm_pmu **ppmu)
0206 {
0207 struct nvkm_pmu *pmu;
0208 if (!(pmu = *ppmu = kzalloc(sizeof(*pmu), GFP_KERNEL)))
0209 return -ENOMEM;
0210 return nvkm_pmu_ctor(fwif, device, type, inst, *ppmu);
0211 }