linux/drivers/gpu/drm/radeon/ni.c
<<
>>
Prefs
   1/*
   2 * Copyright 2010 Advanced Micro Devices, Inc.
   3 *
   4 * Permission is hereby granted, free of charge, to any person obtaining a
   5 * copy of this software and associated documentation files (the "Software"),
   6 * to deal in the Software without restriction, including without limitation
   7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
   8 * and/or sell copies of the Software, and to permit persons to whom the
   9 * Software is furnished to do so, subject to the following conditions:
  10 *
  11 * The above copyright notice and this permission notice shall be included in
  12 * all copies or substantial portions of the Software.
  13 *
  14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
  17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
  18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  20 * OTHER DEALINGS IN THE SOFTWARE.
  21 *
  22 * Authors: Alex Deucher
  23 */
  24#include <linux/firmware.h>
  25#include <linux/platform_device.h>
  26#include <linux/slab.h>
  27#include "drmP.h"
  28#include "radeon.h"
  29#include "radeon_asic.h"
  30#include "radeon_drm.h"
  31#include "nid.h"
  32#include "atom.h"
  33#include "ni_reg.h"
  34
  35#define EVERGREEN_PFP_UCODE_SIZE 1120
  36#define EVERGREEN_PM4_UCODE_SIZE 1376
  37#define EVERGREEN_RLC_UCODE_SIZE 768
  38#define BTC_MC_UCODE_SIZE 6024
  39
  40/* Firmware Names */
  41MODULE_FIRMWARE("radeon/BARTS_pfp.bin");
  42MODULE_FIRMWARE("radeon/BARTS_me.bin");
  43MODULE_FIRMWARE("radeon/BARTS_mc.bin");
  44MODULE_FIRMWARE("radeon/BTC_rlc.bin");
  45MODULE_FIRMWARE("radeon/TURKS_pfp.bin");
  46MODULE_FIRMWARE("radeon/TURKS_me.bin");
  47MODULE_FIRMWARE("radeon/TURKS_mc.bin");
  48MODULE_FIRMWARE("radeon/CAICOS_pfp.bin");
  49MODULE_FIRMWARE("radeon/CAICOS_me.bin");
  50MODULE_FIRMWARE("radeon/CAICOS_mc.bin");
  51
  52#define BTC_IO_MC_REGS_SIZE 29
  53
  54static const u32 barts_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
  55        {0x00000077, 0xff010100},
  56        {0x00000078, 0x00000000},
  57        {0x00000079, 0x00001434},
  58        {0x0000007a, 0xcc08ec08},
  59        {0x0000007b, 0x00040000},
  60        {0x0000007c, 0x000080c0},
  61        {0x0000007d, 0x09000000},
  62        {0x0000007e, 0x00210404},
  63        {0x00000081, 0x08a8e800},
  64        {0x00000082, 0x00030444},
  65        {0x00000083, 0x00000000},
  66        {0x00000085, 0x00000001},
  67        {0x00000086, 0x00000002},
  68        {0x00000087, 0x48490000},
  69        {0x00000088, 0x20244647},
  70        {0x00000089, 0x00000005},
  71        {0x0000008b, 0x66030000},
  72        {0x0000008c, 0x00006603},
  73        {0x0000008d, 0x00000100},
  74        {0x0000008f, 0x00001c0a},
  75        {0x00000090, 0xff000001},
  76        {0x00000094, 0x00101101},
  77        {0x00000095, 0x00000fff},
  78        {0x00000096, 0x00116fff},
  79        {0x00000097, 0x60010000},
  80        {0x00000098, 0x10010000},
  81        {0x00000099, 0x00006000},
  82        {0x0000009a, 0x00001000},
  83        {0x0000009f, 0x00946a00}
  84};
  85
  86static const u32 turks_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
  87        {0x00000077, 0xff010100},
  88        {0x00000078, 0x00000000},
  89        {0x00000079, 0x00001434},
  90        {0x0000007a, 0xcc08ec08},
  91        {0x0000007b, 0x00040000},
  92        {0x0000007c, 0x000080c0},
  93        {0x0000007d, 0x09000000},
  94        {0x0000007e, 0x00210404},
  95        {0x00000081, 0x08a8e800},
  96        {0x00000082, 0x00030444},
  97        {0x00000083, 0x00000000},
  98        {0x00000085, 0x00000001},
  99        {0x00000086, 0x00000002},
 100        {0x00000087, 0x48490000},
 101        {0x00000088, 0x20244647},
 102        {0x00000089, 0x00000005},
 103        {0x0000008b, 0x66030000},
 104        {0x0000008c, 0x00006603},
 105        {0x0000008d, 0x00000100},
 106        {0x0000008f, 0x00001c0a},
 107        {0x00000090, 0xff000001},
 108        {0x00000094, 0x00101101},
 109        {0x00000095, 0x00000fff},
 110        {0x00000096, 0x00116fff},
 111        {0x00000097, 0x60010000},
 112        {0x00000098, 0x10010000},
 113        {0x00000099, 0x00006000},
 114        {0x0000009a, 0x00001000},
 115        {0x0000009f, 0x00936a00}
 116};
 117
 118static const u32 caicos_io_mc_regs[BTC_IO_MC_REGS_SIZE][2] = {
 119        {0x00000077, 0xff010100},
 120        {0x00000078, 0x00000000},
 121        {0x00000079, 0x00001434},
 122        {0x0000007a, 0xcc08ec08},
 123        {0x0000007b, 0x00040000},
 124        {0x0000007c, 0x000080c0},
 125        {0x0000007d, 0x09000000},
 126        {0x0000007e, 0x00210404},
 127        {0x00000081, 0x08a8e800},
 128        {0x00000082, 0x00030444},
 129        {0x00000083, 0x00000000},
 130        {0x00000085, 0x00000001},
 131        {0x00000086, 0x00000002},
 132        {0x00000087, 0x48490000},
 133        {0x00000088, 0x20244647},
 134        {0x00000089, 0x00000005},
 135        {0x0000008b, 0x66030000},
 136        {0x0000008c, 0x00006603},
 137        {0x0000008d, 0x00000100},
 138        {0x0000008f, 0x00001c0a},
 139        {0x00000090, 0xff000001},
 140        {0x00000094, 0x00101101},
 141        {0x00000095, 0x00000fff},
 142        {0x00000096, 0x00116fff},
 143        {0x00000097, 0x60010000},
 144        {0x00000098, 0x10010000},
 145        {0x00000099, 0x00006000},
 146        {0x0000009a, 0x00001000},
 147        {0x0000009f, 0x00916a00}
 148};
 149
 150int btc_mc_load_microcode(struct radeon_device *rdev)
 151{
 152        const __be32 *fw_data;
 153        u32 mem_type, running, blackout = 0;
 154        u32 *io_mc_regs;
 155        int i;
 156
 157        if (!rdev->mc_fw)
 158                return -EINVAL;
 159
 160        switch (rdev->family) {
 161        case CHIP_BARTS:
 162                io_mc_regs = (u32 *)&barts_io_mc_regs;
 163                break;
 164        case CHIP_TURKS:
 165                io_mc_regs = (u32 *)&turks_io_mc_regs;
 166                break;
 167        case CHIP_CAICOS:
 168        default:
 169                io_mc_regs = (u32 *)&caicos_io_mc_regs;
 170                break;
 171        }
 172
 173        mem_type = (RREG32(MC_SEQ_MISC0) & MC_SEQ_MISC0_GDDR5_MASK) >> MC_SEQ_MISC0_GDDR5_SHIFT;
 174        running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
 175
 176        if ((mem_type == MC_SEQ_MISC0_GDDR5_VALUE) && (running == 0)) {
 177                if (running) {
 178                        blackout = RREG32(MC_SHARED_BLACKOUT_CNTL);
 179                        WREG32(MC_SHARED_BLACKOUT_CNTL, 1);
 180                }
 181
 182                /* reset the engine and set to writable */
 183                WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
 184                WREG32(MC_SEQ_SUP_CNTL, 0x00000010);
 185
 186                /* load mc io regs */
 187                for (i = 0; i < BTC_IO_MC_REGS_SIZE; i++) {
 188                        WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
 189                        WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
 190                }
 191                /* load the MC ucode */
 192                fw_data = (const __be32 *)rdev->mc_fw->data;
 193                for (i = 0; i < BTC_MC_UCODE_SIZE; i++)
 194                        WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
 195
 196                /* put the engine back into the active state */
 197                WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
 198                WREG32(MC_SEQ_SUP_CNTL, 0x00000004);
 199                WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
 200
 201                /* wait for training to complete */
 202                while (!(RREG32(MC_IO_PAD_CNTL_D0) & MEM_FALL_OUT_CMD))
 203                        udelay(10);
 204
 205                if (running)
 206                        WREG32(MC_SHARED_BLACKOUT_CNTL, blackout);
 207        }
 208
 209        return 0;
 210}
 211
 212int ni_init_microcode(struct radeon_device *rdev)
 213{
 214        struct platform_device *pdev;
 215        const char *chip_name;
 216        const char *rlc_chip_name;
 217        size_t pfp_req_size, me_req_size, rlc_req_size, mc_req_size;
 218        char fw_name[30];
 219        int err;
 220
 221        DRM_DEBUG("\n");
 222
 223        pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0);
 224        err = IS_ERR(pdev);
 225        if (err) {
 226                printk(KERN_ERR "radeon_cp: Failed to register firmware\n");
 227                return -EINVAL;
 228        }
 229
 230        switch (rdev->family) {
 231        case CHIP_BARTS:
 232                chip_name = "BARTS";
 233                rlc_chip_name = "BTC";
 234                break;
 235        case CHIP_TURKS:
 236                chip_name = "TURKS";
 237                rlc_chip_name = "BTC";
 238                break;
 239        case CHIP_CAICOS:
 240                chip_name = "CAICOS";
 241                rlc_chip_name = "BTC";
 242                break;
 243        default: BUG();
 244        }
 245
 246        pfp_req_size = EVERGREEN_PFP_UCODE_SIZE * 4;
 247        me_req_size = EVERGREEN_PM4_UCODE_SIZE * 4;
 248        rlc_req_size = EVERGREEN_RLC_UCODE_SIZE * 4;
 249        mc_req_size = BTC_MC_UCODE_SIZE * 4;
 250
 251        DRM_INFO("Loading %s Microcode\n", chip_name);
 252
 253        snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
 254        err = request_firmware(&rdev->pfp_fw, fw_name, &pdev->dev);
 255        if (err)
 256                goto out;
 257        if (rdev->pfp_fw->size != pfp_req_size) {
 258                printk(KERN_ERR
 259                       "ni_cp: Bogus length %zu in firmware \"%s\"\n",
 260                       rdev->pfp_fw->size, fw_name);
 261                err = -EINVAL;
 262                goto out;
 263        }
 264
 265        snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
 266        err = request_firmware(&rdev->me_fw, fw_name, &pdev->dev);
 267        if (err)
 268                goto out;
 269        if (rdev->me_fw->size != me_req_size) {
 270                printk(KERN_ERR
 271                       "ni_cp: Bogus length %zu in firmware \"%s\"\n",
 272                       rdev->me_fw->size, fw_name);
 273                err = -EINVAL;
 274        }
 275
 276        snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", rlc_chip_name);
 277        err = request_firmware(&rdev->rlc_fw, fw_name, &pdev->dev);
 278        if (err)
 279                goto out;
 280        if (rdev->rlc_fw->size != rlc_req_size) {
 281                printk(KERN_ERR
 282                       "ni_rlc: Bogus length %zu in firmware \"%s\"\n",
 283                       rdev->rlc_fw->size, fw_name);
 284                err = -EINVAL;
 285        }
 286
 287        snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
 288        err = request_firmware(&rdev->mc_fw, fw_name, &pdev->dev);
 289        if (err)
 290                goto out;
 291        if (rdev->mc_fw->size != mc_req_size) {
 292                printk(KERN_ERR
 293                       "ni_mc: Bogus length %zu in firmware \"%s\"\n",
 294                       rdev->mc_fw->size, fw_name);
 295                err = -EINVAL;
 296        }
 297out:
 298        platform_device_unregister(pdev);
 299
 300        if (err) {
 301                if (err != -EINVAL)
 302                        printk(KERN_ERR
 303                               "ni_cp: Failed to load firmware \"%s\"\n",
 304                               fw_name);
 305                release_firmware(rdev->pfp_fw);
 306                rdev->pfp_fw = NULL;
 307                release_firmware(rdev->me_fw);
 308                rdev->me_fw = NULL;
 309                release_firmware(rdev->rlc_fw);
 310                rdev->rlc_fw = NULL;
 311                release_firmware(rdev->mc_fw);
 312                rdev->mc_fw = NULL;
 313        }
 314        return err;
 315}
 316
 317