linux/drivers/gpu/drm/nouveau/core/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
  27#include <subdev/vga.h>
  28
  29#include "fbmem.h"
  30#include "priv.h"
  31
  32struct nv10_devinit_priv {
  33        struct nouveau_devinit base;
  34        u8 owner;
  35};
  36
  37static void
  38nv10_devinit_meminit(struct nouveau_devinit *devinit)
  39{
  40        struct nv10_devinit_priv *priv = (void *)devinit;
  41        const int mem_width[] = { 0x10, 0x00, 0x20 };
  42        const int mem_width_count = nv_device(priv)->chipset >= 0x17 ? 3 : 2;
  43        uint32_t patt = 0xdeadbeef;
  44        struct io_mapping *fb;
  45        int i, j, k;
  46
  47        /* Map the framebuffer aperture */
  48        fb = fbmem_init(nv_device(priv)->pdev);
  49        if (!fb) {
  50                nv_error(priv, "failed to map fb\n");
  51                return;
  52        }
  53
  54        nv_wr32(priv, NV10_PFB_REFCTRL, NV10_PFB_REFCTRL_VALID_1);
  55
  56        /* Probe memory bus width */
  57        for (i = 0; i < mem_width_count; i++) {
  58                nv_mask(priv, NV04_PFB_CFG0, 0x30, mem_width[i]);
  59
  60                for (j = 0; j < 4; j++) {
  61                        for (k = 0; k < 4; k++)
  62                                fbmem_poke(fb, 0x1c, 0);
  63
  64                        fbmem_poke(fb, 0x1c, patt);
  65                        fbmem_poke(fb, 0x3c, 0);
  66
  67                        if (fbmem_peek(fb, 0x1c) == patt)
  68                                goto mem_width_found;
  69                }
  70        }
  71
  72mem_width_found:
  73        patt <<= 1;
  74
  75        /* Probe amount of installed memory */
  76        for (i = 0; i < 4; i++) {
  77                int off = nv_rd32(priv, 0x10020c) - 0x100000;
  78
  79                fbmem_poke(fb, off, patt);
  80                fbmem_poke(fb, 0, 0);
  81
  82                fbmem_peek(fb, 0);
  83                fbmem_peek(fb, 0);
  84                fbmem_peek(fb, 0);
  85                fbmem_peek(fb, 0);
  86
  87                if (fbmem_peek(fb, off) == patt)
  88                        goto amount_found;
  89        }
  90
  91        /* IC missing - disable the upper half memory space. */
  92        nv_mask(priv, NV04_PFB_CFG0, 0x1000, 0);
  93
  94amount_found:
  95        fbmem_fini(fb);
  96}
  97
  98static int
  99nv10_devinit_ctor(struct nouveau_object *parent, struct nouveau_object *engine,
 100                  struct nouveau_oclass *oclass, void *data, u32 size,
 101                  struct nouveau_object **pobject)
 102{
 103        struct nv10_devinit_priv *priv;
 104        int ret;
 105
 106        ret = nouveau_devinit_create(parent, engine, oclass, &priv);
 107        *pobject = nv_object(priv);
 108        if (ret)
 109                return ret;
 110
 111        priv->base.meminit = nv10_devinit_meminit;
 112        priv->base.pll_set = nv04_devinit_pll_set;
 113        return 0;
 114}
 115
 116struct nouveau_oclass
 117nv10_devinit_oclass = {
 118        .handle = NV_SUBDEV(DEVINIT, 0x10),
 119        .ofuncs = &(struct nouveau_ofuncs) {
 120                .ctor = nv10_devinit_ctor,
 121                .dtor = nv04_devinit_dtor,
 122                .init = nv04_devinit_init,
 123                .fini = nv04_devinit_fini,
 124        },
 125};
 126