0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026 #include "nv04.h"
0027 #include "fbmem.h"
0028
0029 #include <subdev/bios.h>
0030 #include <subdev/bios/init.h>
0031
0032 static void
0033 nv10_devinit_meminit(struct nvkm_devinit *init)
0034 {
0035 struct nvkm_subdev *subdev = &init->subdev;
0036 struct nvkm_device *device = subdev->device;
0037 static const int mem_width[] = { 0x10, 0x00, 0x20 };
0038 int mem_width_count;
0039 uint32_t patt = 0xdeadbeef;
0040 struct io_mapping *fb;
0041 int i, j, k;
0042
0043 if (device->card_type >= NV_11 && device->chipset >= 0x17)
0044 mem_width_count = 3;
0045 else
0046 mem_width_count = 2;
0047
0048
0049 fb = fbmem_init(device);
0050 if (!fb) {
0051 nvkm_error(subdev, "failed to map fb\n");
0052 return;
0053 }
0054
0055 nvkm_wr32(device, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1);
0056
0057
0058 for (i = 0; i < mem_width_count; i++) {
0059 nvkm_mask(device, NV04_PFB_CFG0, 0x30, mem_width[i]);
0060
0061 for (j = 0; j < 4; j++) {
0062 for (k = 0; k < 4; k++)
0063 fbmem_poke(fb, 0x1c, 0);
0064
0065 fbmem_poke(fb, 0x1c, patt);
0066 fbmem_poke(fb, 0x3c, 0);
0067
0068 if (fbmem_peek(fb, 0x1c) == patt)
0069 goto mem_width_found;
0070 }
0071 }
0072
0073 mem_width_found:
0074 patt <<= 1;
0075
0076
0077 for (i = 0; i < 4; i++) {
0078 int off = nvkm_rd32(device, 0x10020c) - 0x100000;
0079
0080 fbmem_poke(fb, off, patt);
0081 fbmem_poke(fb, 0, 0);
0082
0083 fbmem_peek(fb, 0);
0084 fbmem_peek(fb, 0);
0085 fbmem_peek(fb, 0);
0086 fbmem_peek(fb, 0);
0087
0088 if (fbmem_peek(fb, off) == patt)
0089 goto amount_found;
0090 }
0091
0092
0093 nvkm_mask(device, NV04_PFB_CFG0, 0x1000, 0);
0094
0095 amount_found:
0096 fbmem_fini(fb);
0097 }
0098
0099 static const struct nvkm_devinit_func
0100 nv10_devinit = {
0101 .dtor = nv04_devinit_dtor,
0102 .preinit = nv04_devinit_preinit,
0103 .post = nv04_devinit_post,
0104 .meminit = nv10_devinit_meminit,
0105 .pll_set = nv04_devinit_pll_set,
0106 };
0107
0108 int
0109 nv10_devinit_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
0110 struct nvkm_devinit **pinit)
0111 {
0112 return nv04_devinit_new_(&nv10_devinit, device, type, inst, pinit);
0113 }