cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

rv770_smc.c (15417B)


      1/*
      2 * Copyright 2011 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
     25#include <linux/firmware.h>
     26
     27#include "radeon.h"
     28#include "rv770d.h"
     29#include "rv770_dpm.h"
     30#include "rv770_smc.h"
     31#include "atom.h"
     32#include "radeon_ucode.h"
     33
     34#define FIRST_SMC_INT_VECT_REG 0xFFD8
     35#define FIRST_INT_VECT_S19     0xFFC0
     36
     37static const u8 rv770_smc_int_vectors[] =
     38{
     39	0x08, 0x10, 0x08, 0x10,
     40	0x08, 0x10, 0x08, 0x10,
     41	0x08, 0x10, 0x08, 0x10,
     42	0x08, 0x10, 0x08, 0x10,
     43	0x08, 0x10, 0x08, 0x10,
     44	0x08, 0x10, 0x08, 0x10,
     45	0x08, 0x10, 0x08, 0x10,
     46	0x08, 0x10, 0x08, 0x10,
     47	0x08, 0x10, 0x08, 0x10,
     48	0x08, 0x10, 0x08, 0x10,
     49	0x08, 0x10, 0x08, 0x10,
     50	0x08, 0x10, 0x08, 0x10,
     51	0x08, 0x10, 0x0C, 0xD7,
     52	0x08, 0x2B, 0x08, 0x10,
     53	0x03, 0x51, 0x03, 0x51,
     54	0x03, 0x51, 0x03, 0x51
     55};
     56
     57static const u8 rv730_smc_int_vectors[] =
     58{
     59	0x08, 0x15, 0x08, 0x15,
     60	0x08, 0x15, 0x08, 0x15,
     61	0x08, 0x15, 0x08, 0x15,
     62	0x08, 0x15, 0x08, 0x15,
     63	0x08, 0x15, 0x08, 0x15,
     64	0x08, 0x15, 0x08, 0x15,
     65	0x08, 0x15, 0x08, 0x15,
     66	0x08, 0x15, 0x08, 0x15,
     67	0x08, 0x15, 0x08, 0x15,
     68	0x08, 0x15, 0x08, 0x15,
     69	0x08, 0x15, 0x08, 0x15,
     70	0x08, 0x15, 0x08, 0x15,
     71	0x08, 0x15, 0x0C, 0xBB,
     72	0x08, 0x30, 0x08, 0x15,
     73	0x03, 0x56, 0x03, 0x56,
     74	0x03, 0x56, 0x03, 0x56
     75};
     76
     77static const u8 rv710_smc_int_vectors[] =
     78{
     79	0x08, 0x04, 0x08, 0x04,
     80	0x08, 0x04, 0x08, 0x04,
     81	0x08, 0x04, 0x08, 0x04,
     82	0x08, 0x04, 0x08, 0x04,
     83	0x08, 0x04, 0x08, 0x04,
     84	0x08, 0x04, 0x08, 0x04,
     85	0x08, 0x04, 0x08, 0x04,
     86	0x08, 0x04, 0x08, 0x04,
     87	0x08, 0x04, 0x08, 0x04,
     88	0x08, 0x04, 0x08, 0x04,
     89	0x08, 0x04, 0x08, 0x04,
     90	0x08, 0x04, 0x08, 0x04,
     91	0x08, 0x04, 0x0C, 0xCB,
     92	0x08, 0x1F, 0x08, 0x04,
     93	0x03, 0x51, 0x03, 0x51,
     94	0x03, 0x51, 0x03, 0x51
     95};
     96
     97static const u8 rv740_smc_int_vectors[] =
     98{
     99	0x08, 0x10, 0x08, 0x10,
    100	0x08, 0x10, 0x08, 0x10,
    101	0x08, 0x10, 0x08, 0x10,
    102	0x08, 0x10, 0x08, 0x10,
    103	0x08, 0x10, 0x08, 0x10,
    104	0x08, 0x10, 0x08, 0x10,
    105	0x08, 0x10, 0x08, 0x10,
    106	0x08, 0x10, 0x08, 0x10,
    107	0x08, 0x10, 0x08, 0x10,
    108	0x08, 0x10, 0x08, 0x10,
    109	0x08, 0x10, 0x08, 0x10,
    110	0x08, 0x10, 0x08, 0x10,
    111	0x08, 0x10, 0x0C, 0xD7,
    112	0x08, 0x2B, 0x08, 0x10,
    113	0x03, 0x51, 0x03, 0x51,
    114	0x03, 0x51, 0x03, 0x51
    115};
    116
    117static const u8 cedar_smc_int_vectors[] =
    118{
    119	0x0B, 0x05, 0x0B, 0x05,
    120	0x0B, 0x05, 0x0B, 0x05,
    121	0x0B, 0x05, 0x0B, 0x05,
    122	0x0B, 0x05, 0x0B, 0x05,
    123	0x0B, 0x05, 0x0B, 0x05,
    124	0x0B, 0x05, 0x0B, 0x05,
    125	0x0B, 0x05, 0x0B, 0x05,
    126	0x0B, 0x05, 0x0B, 0x05,
    127	0x0B, 0x05, 0x0B, 0x05,
    128	0x0B, 0x05, 0x0B, 0x05,
    129	0x0B, 0x05, 0x0B, 0x05,
    130	0x0B, 0x05, 0x0B, 0x05,
    131	0x0B, 0x05, 0x11, 0x8B,
    132	0x0B, 0x20, 0x0B, 0x05,
    133	0x04, 0xF6, 0x04, 0xF6,
    134	0x04, 0xF6, 0x04, 0xF6
    135};
    136
    137static const u8 redwood_smc_int_vectors[] =
    138{
    139	0x0B, 0x05, 0x0B, 0x05,
    140	0x0B, 0x05, 0x0B, 0x05,
    141	0x0B, 0x05, 0x0B, 0x05,
    142	0x0B, 0x05, 0x0B, 0x05,
    143	0x0B, 0x05, 0x0B, 0x05,
    144	0x0B, 0x05, 0x0B, 0x05,
    145	0x0B, 0x05, 0x0B, 0x05,
    146	0x0B, 0x05, 0x0B, 0x05,
    147	0x0B, 0x05, 0x0B, 0x05,
    148	0x0B, 0x05, 0x0B, 0x05,
    149	0x0B, 0x05, 0x0B, 0x05,
    150	0x0B, 0x05, 0x0B, 0x05,
    151	0x0B, 0x05, 0x11, 0x8B,
    152	0x0B, 0x20, 0x0B, 0x05,
    153	0x04, 0xF6, 0x04, 0xF6,
    154	0x04, 0xF6, 0x04, 0xF6
    155};
    156
    157static const u8 juniper_smc_int_vectors[] =
    158{
    159	0x0B, 0x05, 0x0B, 0x05,
    160	0x0B, 0x05, 0x0B, 0x05,
    161	0x0B, 0x05, 0x0B, 0x05,
    162	0x0B, 0x05, 0x0B, 0x05,
    163	0x0B, 0x05, 0x0B, 0x05,
    164	0x0B, 0x05, 0x0B, 0x05,
    165	0x0B, 0x05, 0x0B, 0x05,
    166	0x0B, 0x05, 0x0B, 0x05,
    167	0x0B, 0x05, 0x0B, 0x05,
    168	0x0B, 0x05, 0x0B, 0x05,
    169	0x0B, 0x05, 0x0B, 0x05,
    170	0x0B, 0x05, 0x0B, 0x05,
    171	0x0B, 0x05, 0x11, 0x8B,
    172	0x0B, 0x20, 0x0B, 0x05,
    173	0x04, 0xF6, 0x04, 0xF6,
    174	0x04, 0xF6, 0x04, 0xF6
    175};
    176
    177static const u8 cypress_smc_int_vectors[] =
    178{
    179	0x0B, 0x05, 0x0B, 0x05,
    180	0x0B, 0x05, 0x0B, 0x05,
    181	0x0B, 0x05, 0x0B, 0x05,
    182	0x0B, 0x05, 0x0B, 0x05,
    183	0x0B, 0x05, 0x0B, 0x05,
    184	0x0B, 0x05, 0x0B, 0x05,
    185	0x0B, 0x05, 0x0B, 0x05,
    186	0x0B, 0x05, 0x0B, 0x05,
    187	0x0B, 0x05, 0x0B, 0x05,
    188	0x0B, 0x05, 0x0B, 0x05,
    189	0x0B, 0x05, 0x0B, 0x05,
    190	0x0B, 0x05, 0x0B, 0x05,
    191	0x0B, 0x05, 0x11, 0x8B,
    192	0x0B, 0x20, 0x0B, 0x05,
    193	0x04, 0xF6, 0x04, 0xF6,
    194	0x04, 0xF6, 0x04, 0xF6
    195};
    196
    197static const u8 barts_smc_int_vectors[] =
    198{
    199	0x0C, 0x14, 0x0C, 0x14,
    200	0x0C, 0x14, 0x0C, 0x14,
    201	0x0C, 0x14, 0x0C, 0x14,
    202	0x0C, 0x14, 0x0C, 0x14,
    203	0x0C, 0x14, 0x0C, 0x14,
    204	0x0C, 0x14, 0x0C, 0x14,
    205	0x0C, 0x14, 0x0C, 0x14,
    206	0x0C, 0x14, 0x0C, 0x14,
    207	0x0C, 0x14, 0x0C, 0x14,
    208	0x0C, 0x14, 0x0C, 0x14,
    209	0x0C, 0x14, 0x0C, 0x14,
    210	0x0C, 0x14, 0x0C, 0x14,
    211	0x0C, 0x14, 0x12, 0xAA,
    212	0x0C, 0x2F, 0x15, 0xF6,
    213	0x15, 0xF6, 0x05, 0x0A,
    214	0x05, 0x0A, 0x05, 0x0A
    215};
    216
    217static const u8 turks_smc_int_vectors[] =
    218{
    219	0x0C, 0x14, 0x0C, 0x14,
    220	0x0C, 0x14, 0x0C, 0x14,
    221	0x0C, 0x14, 0x0C, 0x14,
    222	0x0C, 0x14, 0x0C, 0x14,
    223	0x0C, 0x14, 0x0C, 0x14,
    224	0x0C, 0x14, 0x0C, 0x14,
    225	0x0C, 0x14, 0x0C, 0x14,
    226	0x0C, 0x14, 0x0C, 0x14,
    227	0x0C, 0x14, 0x0C, 0x14,
    228	0x0C, 0x14, 0x0C, 0x14,
    229	0x0C, 0x14, 0x0C, 0x14,
    230	0x0C, 0x14, 0x0C, 0x14,
    231	0x0C, 0x14, 0x12, 0xAA,
    232	0x0C, 0x2F, 0x15, 0xF6,
    233	0x15, 0xF6, 0x05, 0x0A,
    234	0x05, 0x0A, 0x05, 0x0A
    235};
    236
    237static const u8 caicos_smc_int_vectors[] =
    238{
    239	0x0C, 0x14, 0x0C, 0x14,
    240	0x0C, 0x14, 0x0C, 0x14,
    241	0x0C, 0x14, 0x0C, 0x14,
    242	0x0C, 0x14, 0x0C, 0x14,
    243	0x0C, 0x14, 0x0C, 0x14,
    244	0x0C, 0x14, 0x0C, 0x14,
    245	0x0C, 0x14, 0x0C, 0x14,
    246	0x0C, 0x14, 0x0C, 0x14,
    247	0x0C, 0x14, 0x0C, 0x14,
    248	0x0C, 0x14, 0x0C, 0x14,
    249	0x0C, 0x14, 0x0C, 0x14,
    250	0x0C, 0x14, 0x0C, 0x14,
    251	0x0C, 0x14, 0x12, 0xAA,
    252	0x0C, 0x2F, 0x15, 0xF6,
    253	0x15, 0xF6, 0x05, 0x0A,
    254	0x05, 0x0A, 0x05, 0x0A
    255};
    256
    257static const u8 cayman_smc_int_vectors[] =
    258{
    259	0x12, 0x05, 0x12, 0x05,
    260	0x12, 0x05, 0x12, 0x05,
    261	0x12, 0x05, 0x12, 0x05,
    262	0x12, 0x05, 0x12, 0x05,
    263	0x12, 0x05, 0x12, 0x05,
    264	0x12, 0x05, 0x12, 0x05,
    265	0x12, 0x05, 0x12, 0x05,
    266	0x12, 0x05, 0x12, 0x05,
    267	0x12, 0x05, 0x12, 0x05,
    268	0x12, 0x05, 0x12, 0x05,
    269	0x12, 0x05, 0x12, 0x05,
    270	0x12, 0x05, 0x12, 0x05,
    271	0x12, 0x05, 0x18, 0xEA,
    272	0x12, 0x20, 0x1C, 0x34,
    273	0x1C, 0x34, 0x08, 0x72,
    274	0x08, 0x72, 0x08, 0x72
    275};
    276
    277static int rv770_set_smc_sram_address(struct radeon_device *rdev,
    278				      u16 smc_address, u16 limit)
    279{
    280	u32 addr;
    281
    282	if (smc_address & 3)
    283		return -EINVAL;
    284	if ((smc_address + 3) > limit)
    285		return -EINVAL;
    286
    287	addr = smc_address;
    288	addr |= SMC_SRAM_AUTO_INC_DIS;
    289
    290	WREG32(SMC_SRAM_ADDR, addr);
    291
    292	return 0;
    293}
    294
    295int rv770_copy_bytes_to_smc(struct radeon_device *rdev,
    296			    u16 smc_start_address, const u8 *src,
    297			    u16 byte_count, u16 limit)
    298{
    299	unsigned long flags;
    300	u32 data, original_data, extra_shift;
    301	u16 addr;
    302	int ret = 0;
    303
    304	if (smc_start_address & 3)
    305		return -EINVAL;
    306	if ((smc_start_address + byte_count) > limit)
    307		return -EINVAL;
    308
    309	addr = smc_start_address;
    310
    311	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
    312	while (byte_count >= 4) {
    313		/* SMC address space is BE */
    314		data = (src[0] << 24) | (src[1] << 16) | (src[2] << 8) | src[3];
    315
    316		ret = rv770_set_smc_sram_address(rdev, addr, limit);
    317		if (ret)
    318			goto done;
    319
    320		WREG32(SMC_SRAM_DATA, data);
    321
    322		src += 4;
    323		byte_count -= 4;
    324		addr += 4;
    325	}
    326
    327	/* RMW for final bytes */
    328	if (byte_count > 0) {
    329		data = 0;
    330
    331		ret = rv770_set_smc_sram_address(rdev, addr, limit);
    332		if (ret)
    333			goto done;
    334
    335		original_data = RREG32(SMC_SRAM_DATA);
    336
    337		extra_shift = 8 * (4 - byte_count);
    338
    339		while (byte_count > 0) {
    340			/* SMC address space is BE */
    341			data = (data << 8) + *src++;
    342			byte_count--;
    343		}
    344
    345		data <<= extra_shift;
    346
    347		data |= (original_data & ~((~0UL) << extra_shift));
    348
    349		ret = rv770_set_smc_sram_address(rdev, addr, limit);
    350		if (ret)
    351			goto done;
    352
    353		WREG32(SMC_SRAM_DATA, data);
    354	}
    355
    356done:
    357	spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
    358
    359	return ret;
    360}
    361
    362static int rv770_program_interrupt_vectors(struct radeon_device *rdev,
    363					   u32 smc_first_vector, const u8 *src,
    364					   u32 byte_count)
    365{
    366	u32 tmp, i;
    367
    368	if (byte_count % 4)
    369		return -EINVAL;
    370
    371	if (smc_first_vector < FIRST_SMC_INT_VECT_REG) {
    372		tmp = FIRST_SMC_INT_VECT_REG - smc_first_vector;
    373
    374		if (tmp > byte_count)
    375			return 0;
    376
    377		byte_count -= tmp;
    378		src += tmp;
    379		smc_first_vector = FIRST_SMC_INT_VECT_REG;
    380	}
    381
    382	for (i = 0; i < byte_count; i += 4) {
    383		/* SMC address space is BE */
    384		tmp = (src[i] << 24) | (src[i + 1] << 16) | (src[i + 2] << 8) | src[i + 3];
    385
    386		WREG32(SMC_ISR_FFD8_FFDB + i, tmp);
    387	}
    388
    389	return 0;
    390}
    391
    392void rv770_start_smc(struct radeon_device *rdev)
    393{
    394	WREG32_P(SMC_IO, SMC_RST_N, ~SMC_RST_N);
    395}
    396
    397void rv770_reset_smc(struct radeon_device *rdev)
    398{
    399	WREG32_P(SMC_IO, 0, ~SMC_RST_N);
    400}
    401
    402void rv770_stop_smc_clock(struct radeon_device *rdev)
    403{
    404	WREG32_P(SMC_IO, 0, ~SMC_CLK_EN);
    405}
    406
    407void rv770_start_smc_clock(struct radeon_device *rdev)
    408{
    409	WREG32_P(SMC_IO, SMC_CLK_EN, ~SMC_CLK_EN);
    410}
    411
    412bool rv770_is_smc_running(struct radeon_device *rdev)
    413{
    414	u32 tmp;
    415
    416	tmp = RREG32(SMC_IO);
    417
    418	if ((tmp & SMC_RST_N) && (tmp & SMC_CLK_EN))
    419		return true;
    420	else
    421		return false;
    422}
    423
    424PPSMC_Result rv770_send_msg_to_smc(struct radeon_device *rdev, PPSMC_Msg msg)
    425{
    426	u32 tmp;
    427	int i;
    428	PPSMC_Result result;
    429
    430	if (!rv770_is_smc_running(rdev))
    431		return PPSMC_Result_Failed;
    432
    433	WREG32_P(SMC_MSG, HOST_SMC_MSG(msg), ~HOST_SMC_MSG_MASK);
    434
    435	for (i = 0; i < rdev->usec_timeout; i++) {
    436		tmp = RREG32(SMC_MSG) & HOST_SMC_RESP_MASK;
    437		tmp >>= HOST_SMC_RESP_SHIFT;
    438		if (tmp != 0)
    439			break;
    440		udelay(1);
    441	}
    442
    443	tmp = RREG32(SMC_MSG) & HOST_SMC_RESP_MASK;
    444	tmp >>= HOST_SMC_RESP_SHIFT;
    445
    446	result = (PPSMC_Result)tmp;
    447	return result;
    448}
    449
    450PPSMC_Result rv770_wait_for_smc_inactive(struct radeon_device *rdev)
    451{
    452	int i;
    453	PPSMC_Result result = PPSMC_Result_OK;
    454
    455	if (!rv770_is_smc_running(rdev))
    456		return result;
    457
    458	for (i = 0; i < rdev->usec_timeout; i++) {
    459		if (RREG32(SMC_IO) & SMC_STOP_MODE)
    460			break;
    461		udelay(1);
    462	}
    463
    464	return result;
    465}
    466
    467static void rv770_clear_smc_sram(struct radeon_device *rdev, u16 limit)
    468{
    469	unsigned long flags;
    470	u16 i;
    471
    472	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
    473	for (i = 0;  i < limit; i += 4) {
    474		rv770_set_smc_sram_address(rdev, i, limit);
    475		WREG32(SMC_SRAM_DATA, 0);
    476	}
    477	spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
    478}
    479
    480int rv770_load_smc_ucode(struct radeon_device *rdev,
    481			 u16 limit)
    482{
    483	int ret;
    484	const u8 *int_vect;
    485	u16 int_vect_start_address;
    486	u16 int_vect_size;
    487	const u8 *ucode_data;
    488	u16 ucode_start_address;
    489	u16 ucode_size;
    490
    491	if (!rdev->smc_fw)
    492		return -EINVAL;
    493
    494	rv770_clear_smc_sram(rdev, limit);
    495
    496	switch (rdev->family) {
    497	case CHIP_RV770:
    498		ucode_start_address = RV770_SMC_UCODE_START;
    499		ucode_size = RV770_SMC_UCODE_SIZE;
    500		int_vect = (const u8 *)&rv770_smc_int_vectors;
    501		int_vect_start_address = RV770_SMC_INT_VECTOR_START;
    502		int_vect_size = RV770_SMC_INT_VECTOR_SIZE;
    503		break;
    504	case CHIP_RV730:
    505		ucode_start_address = RV730_SMC_UCODE_START;
    506		ucode_size = RV730_SMC_UCODE_SIZE;
    507		int_vect = (const u8 *)&rv730_smc_int_vectors;
    508		int_vect_start_address = RV730_SMC_INT_VECTOR_START;
    509		int_vect_size = RV730_SMC_INT_VECTOR_SIZE;
    510		break;
    511	case CHIP_RV710:
    512		ucode_start_address = RV710_SMC_UCODE_START;
    513		ucode_size = RV710_SMC_UCODE_SIZE;
    514		int_vect = (const u8 *)&rv710_smc_int_vectors;
    515		int_vect_start_address = RV710_SMC_INT_VECTOR_START;
    516		int_vect_size = RV710_SMC_INT_VECTOR_SIZE;
    517		break;
    518	case CHIP_RV740:
    519		ucode_start_address = RV740_SMC_UCODE_START;
    520		ucode_size = RV740_SMC_UCODE_SIZE;
    521		int_vect = (const u8 *)&rv740_smc_int_vectors;
    522		int_vect_start_address = RV740_SMC_INT_VECTOR_START;
    523		int_vect_size = RV740_SMC_INT_VECTOR_SIZE;
    524		break;
    525	case CHIP_CEDAR:
    526		ucode_start_address = CEDAR_SMC_UCODE_START;
    527		ucode_size = CEDAR_SMC_UCODE_SIZE;
    528		int_vect = (const u8 *)&cedar_smc_int_vectors;
    529		int_vect_start_address = CEDAR_SMC_INT_VECTOR_START;
    530		int_vect_size = CEDAR_SMC_INT_VECTOR_SIZE;
    531		break;
    532	case CHIP_REDWOOD:
    533		ucode_start_address = REDWOOD_SMC_UCODE_START;
    534		ucode_size = REDWOOD_SMC_UCODE_SIZE;
    535		int_vect = (const u8 *)&redwood_smc_int_vectors;
    536		int_vect_start_address = REDWOOD_SMC_INT_VECTOR_START;
    537		int_vect_size = REDWOOD_SMC_INT_VECTOR_SIZE;
    538		break;
    539	case CHIP_JUNIPER:
    540		ucode_start_address = JUNIPER_SMC_UCODE_START;
    541		ucode_size = JUNIPER_SMC_UCODE_SIZE;
    542		int_vect = (const u8 *)&juniper_smc_int_vectors;
    543		int_vect_start_address = JUNIPER_SMC_INT_VECTOR_START;
    544		int_vect_size = JUNIPER_SMC_INT_VECTOR_SIZE;
    545		break;
    546	case CHIP_CYPRESS:
    547	case CHIP_HEMLOCK:
    548		ucode_start_address = CYPRESS_SMC_UCODE_START;
    549		ucode_size = CYPRESS_SMC_UCODE_SIZE;
    550		int_vect = (const u8 *)&cypress_smc_int_vectors;
    551		int_vect_start_address = CYPRESS_SMC_INT_VECTOR_START;
    552		int_vect_size = CYPRESS_SMC_INT_VECTOR_SIZE;
    553		break;
    554	case CHIP_BARTS:
    555		ucode_start_address = BARTS_SMC_UCODE_START;
    556		ucode_size = BARTS_SMC_UCODE_SIZE;
    557		int_vect = (const u8 *)&barts_smc_int_vectors;
    558		int_vect_start_address = BARTS_SMC_INT_VECTOR_START;
    559		int_vect_size = BARTS_SMC_INT_VECTOR_SIZE;
    560		break;
    561	case CHIP_TURKS:
    562		ucode_start_address = TURKS_SMC_UCODE_START;
    563		ucode_size = TURKS_SMC_UCODE_SIZE;
    564		int_vect = (const u8 *)&turks_smc_int_vectors;
    565		int_vect_start_address = TURKS_SMC_INT_VECTOR_START;
    566		int_vect_size = TURKS_SMC_INT_VECTOR_SIZE;
    567		break;
    568	case CHIP_CAICOS:
    569		ucode_start_address = CAICOS_SMC_UCODE_START;
    570		ucode_size = CAICOS_SMC_UCODE_SIZE;
    571		int_vect = (const u8 *)&caicos_smc_int_vectors;
    572		int_vect_start_address = CAICOS_SMC_INT_VECTOR_START;
    573		int_vect_size = CAICOS_SMC_INT_VECTOR_SIZE;
    574		break;
    575	case CHIP_CAYMAN:
    576		ucode_start_address = CAYMAN_SMC_UCODE_START;
    577		ucode_size = CAYMAN_SMC_UCODE_SIZE;
    578		int_vect = (const u8 *)&cayman_smc_int_vectors;
    579		int_vect_start_address = CAYMAN_SMC_INT_VECTOR_START;
    580		int_vect_size = CAYMAN_SMC_INT_VECTOR_SIZE;
    581		break;
    582	default:
    583		DRM_ERROR("unknown asic in smc ucode loader\n");
    584		BUG();
    585	}
    586
    587	/* load the ucode */
    588	ucode_data = (const u8 *)rdev->smc_fw->data;
    589	ret = rv770_copy_bytes_to_smc(rdev, ucode_start_address,
    590				      ucode_data, ucode_size, limit);
    591	if (ret)
    592		return ret;
    593
    594	/* set up the int vectors */
    595	ret = rv770_program_interrupt_vectors(rdev, int_vect_start_address,
    596					      int_vect, int_vect_size);
    597	if (ret)
    598		return ret;
    599
    600	return 0;
    601}
    602
    603int rv770_read_smc_sram_dword(struct radeon_device *rdev,
    604			      u16 smc_address, u32 *value, u16 limit)
    605{
    606	unsigned long flags;
    607	int ret;
    608
    609	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
    610	ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
    611	if (ret == 0)
    612		*value = RREG32(SMC_SRAM_DATA);
    613	spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
    614
    615	return ret;
    616}
    617
    618int rv770_write_smc_sram_dword(struct radeon_device *rdev,
    619			       u16 smc_address, u32 value, u16 limit)
    620{
    621	unsigned long flags;
    622	int ret;
    623
    624	spin_lock_irqsave(&rdev->smc_idx_lock, flags);
    625	ret = rv770_set_smc_sram_address(rdev, smc_address, limit);
    626	if (ret == 0)
    627		WREG32(SMC_SRAM_DATA, value);
    628	spin_unlock_irqrestore(&rdev->smc_idx_lock, flags);
    629
    630	return ret;
    631}