linux/drivers/gpu/drm/nouveau/nvkm/subdev/devinit/nv10.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) 2010 Francisco Jerez.
   3 * All Rights Reserved.
   4 *
   5 * Permission is hereby granted, free of charge, to any person obtaining
   6 * a copy of this software and associated documentation files (the
   7 * "Software"), to deal in the Software without restriction, including
   8 * without limitation the rights to use, copy, modify, merge, publish,
   9 * distribute, sublicense, and/or sell copies of the Software, and to
  10 * permit persons to whom the Software is furnished to do so, subject to
  11 * the following conditions:
  12 *
  13 * The above copyright notice and this permission notice (including the
  14 * next paragraph) shall be included in all copies or substantial
  15 * portions of the Software.
  16 *
  17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  18 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
  20 * IN NO EVENT SHALL THE COPYRIGHT OWNER(S) AND/OR ITS SUPPLIERS BE
  21 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
  22 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
  23 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
  24 *
  25 */
  26#include "nv04.h"
  27#include "fbmem.h"
  28
  29#include <subdev/bios.h>
  30#include <subdev/bios/init.h>
  31
  32static void
  33nv10_devinit_meminit(struct nvkm_devinit *init)
  34{
  35        struct nvkm_subdev *subdev = &init->subdev;
  36        struct nvkm_device *device = subdev->device;
  37        static const int mem_width[] = { 0x10, 0x00, 0x20 };
  38        int mem_width_count;
  39        uint32_t patt = 0xdeadbeef;
  40        struct io_mapping *fb;
  41        int i, j, k;
  42
  43        if (device->card_type >= NV_11 && device->chipset >= 0x17)
  44                mem_width_count = 3;
  45        else
  46                mem_width_count = 2;
  47
  48        /* Map the framebuffer aperture */
  49        fb = fbmem_init(device);
  50        if (!fb) {
  51                nvkm_error(subdev, "failed to map fb\n");
  52                return;
  53        }
  54
  55        nvkm_wr32(device, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1);
  56
  57        /* Probe memory bus width */
  58        for (i = 0; i < mem_width_count; i++) {
  59                nvkm_mask(device, NV04_PFB_CFG0, 0x30, mem_width[i]);
  60
  61                for (j = 0; j < 4; j++) {
  62                        for (k = 0; k < 4; k++)
  63                                fbmem_poke(fb, 0x1c, 0);
  64
  65                        fbmem_poke(fb, 0x1c, patt);
  66                        fbmem_poke(fb, 0x3c, 0);
  67
  68                        if (fbmem_peek(fb, 0x1c) == patt)
  69                                goto mem_width_found;
  70                }
  71        }
  72
  73mem_width_found:
  74        patt <<= 1;
  75
  76        /* Probe amount of installed memory */
  77        for (i = 0; i < 4; i++) {
  78                int off = nvkm_rd32(device, 0x10020c) - 0x100000;
  79
  80                fbmem_poke(fb, off, patt);
  81                fbmem_poke(fb, 0, 0);
  82
  83                fbmem_peek(fb, 0);
  84                fbmem_peek(fb, 0);
  85                fbmem_peek(fb, 0);
  86                fbmem_peek(fb, 0);
  87
  88                if (fbmem_peek(fb, off) == patt)
  89                        goto amount_found;
  90        }
  91
  92        /* IC missing - disable the upper half memory space. */
  93        nvkm_mask(device, NV04_PFB_CFG0, 0x1000, 0);
  94
  95amount_found:
  96        fbmem_fini(fb);
  97}
  98
  99static const struct nvkm_devinit_func
 100nv10_devinit = {
 101        .dtor = nv04_devinit_dtor,
 102        .preinit = nv04_devinit_preinit,
 103        .post = nv04_devinit_post,
 104        .meminit = nv10_devinit_meminit,
 105        .pll_set = nv04_devinit_pll_set,
 106};
 107
 108int
 109nv10_devinit_new(struct nvkm_device *device, enum nvkm_subdev_type type, int inst,
 110                 struct nvkm_devinit **pinit)
 111{
 112        return nv04_devinit_new_(&nv10_devinit, device, type, inst, pinit);
 113}
 114