diff options
| author | Alex Deucher <alexander.deucher@amd.com> | 2012-03-20 17:18:21 -0400 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2012-03-21 02:55:54 -0400 |
| commit | 347e7592beb0abd56a11ec16ca8aba9f60681f13 (patch) | |
| tree | 2ba16548950e2ede2c31859133c6977f2837b5f5 | |
| parent | 2ece2e8b7d02040a59bc2f3a7f192c0521e2b867 (diff) | |
drm/radeon/kms: Add support for RLC init on SI
RLC handles the interrupt controller and other tasks
on the GPU.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
| -rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 13 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/si.c | 132 | ||||
| -rw-r--r-- | drivers/gpu/drm/radeon/sid.h | 17 |
3 files changed, 162 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index f1c2f58e5724..8275b4184adb 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
| @@ -772,6 +772,18 @@ struct r600_blit { | |||
| 772 | 772 | ||
| 773 | void r600_blit_suspend(struct radeon_device *rdev); | 773 | void r600_blit_suspend(struct radeon_device *rdev); |
| 774 | 774 | ||
| 775 | /* | ||
| 776 | * SI RLC stuff | ||
| 777 | */ | ||
| 778 | struct si_rlc { | ||
| 779 | /* for power gating */ | ||
| 780 | struct radeon_bo *save_restore_obj; | ||
| 781 | uint64_t save_restore_gpu_addr; | ||
| 782 | /* for clear state */ | ||
| 783 | struct radeon_bo *clear_state_obj; | ||
| 784 | uint64_t clear_state_gpu_addr; | ||
| 785 | }; | ||
| 786 | |||
| 775 | int radeon_ib_get(struct radeon_device *rdev, int ring, | 787 | int radeon_ib_get(struct radeon_device *rdev, int ring, |
| 776 | struct radeon_ib **ib, unsigned size); | 788 | struct radeon_ib **ib, unsigned size); |
| 777 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib); | 789 | void radeon_ib_free(struct radeon_device *rdev, struct radeon_ib **ib); |
| @@ -1532,6 +1544,7 @@ struct radeon_device { | |||
| 1532 | struct r600_vram_scratch vram_scratch; | 1544 | struct r600_vram_scratch vram_scratch; |
| 1533 | int msi_enabled; /* msi enabled */ | 1545 | int msi_enabled; /* msi enabled */ |
| 1534 | struct r600_ih ih; /* r6/700 interrupt ring */ | 1546 | struct r600_ih ih; /* r6/700 interrupt ring */ |
| 1547 | struct si_rlc rlc; | ||
| 1535 | struct work_struct hotplug_work; | 1548 | struct work_struct hotplug_work; |
| 1536 | int num_crtc; /* number of crtcs */ | 1549 | int num_crtc; /* number of crtcs */ |
| 1537 | struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ | 1550 | struct mutex dc_hw_i2c_mutex; /* display controller hw i2c mutex */ |
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c index 408119a810ce..4252cd0ab64b 100644 --- a/drivers/gpu/drm/radeon/si.c +++ b/drivers/gpu/drm/radeon/si.c | |||
| @@ -2940,3 +2940,135 @@ void si_vm_tlb_flush(struct radeon_device *rdev, struct radeon_vm *vm) | |||
| 2940 | WREG32(VM_INVALIDATE_REQUEST, 1 << vm->id); | 2940 | WREG32(VM_INVALIDATE_REQUEST, 1 << vm->id); |
| 2941 | } | 2941 | } |
| 2942 | 2942 | ||
| 2943 | /* | ||
| 2944 | * RLC | ||
| 2945 | */ | ||
| 2946 | static void si_rlc_fini(struct radeon_device *rdev) | ||
| 2947 | { | ||
| 2948 | int r; | ||
| 2949 | |||
| 2950 | /* save restore block */ | ||
| 2951 | if (rdev->rlc.save_restore_obj) { | ||
| 2952 | r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); | ||
| 2953 | if (unlikely(r != 0)) | ||
| 2954 | dev_warn(rdev->dev, "(%d) reserve RLC sr bo failed\n", r); | ||
| 2955 | radeon_bo_unpin(rdev->rlc.save_restore_obj); | ||
| 2956 | radeon_bo_unreserve(rdev->rlc.save_restore_obj); | ||
| 2957 | |||
| 2958 | radeon_bo_unref(&rdev->rlc.save_restore_obj); | ||
| 2959 | rdev->rlc.save_restore_obj = NULL; | ||
| 2960 | } | ||
| 2961 | |||
| 2962 | /* clear state block */ | ||
| 2963 | if (rdev->rlc.clear_state_obj) { | ||
| 2964 | r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false); | ||
| 2965 | if (unlikely(r != 0)) | ||
| 2966 | dev_warn(rdev->dev, "(%d) reserve RLC c bo failed\n", r); | ||
| 2967 | radeon_bo_unpin(rdev->rlc.clear_state_obj); | ||
| 2968 | radeon_bo_unreserve(rdev->rlc.clear_state_obj); | ||
| 2969 | |||
| 2970 | radeon_bo_unref(&rdev->rlc.clear_state_obj); | ||
| 2971 | rdev->rlc.clear_state_obj = NULL; | ||
| 2972 | } | ||
| 2973 | } | ||
| 2974 | |||
| 2975 | static int si_rlc_init(struct radeon_device *rdev) | ||
| 2976 | { | ||
| 2977 | int r; | ||
| 2978 | |||
| 2979 | /* save restore block */ | ||
| 2980 | if (rdev->rlc.save_restore_obj == NULL) { | ||
| 2981 | r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, | ||
| 2982 | RADEON_GEM_DOMAIN_VRAM, &rdev->rlc.save_restore_obj); | ||
| 2983 | if (r) { | ||
| 2984 | dev_warn(rdev->dev, "(%d) create RLC sr bo failed\n", r); | ||
| 2985 | return r; | ||
| 2986 | } | ||
| 2987 | } | ||
| 2988 | |||
| 2989 | r = radeon_bo_reserve(rdev->rlc.save_restore_obj, false); | ||
| 2990 | if (unlikely(r != 0)) { | ||
| 2991 | si_rlc_fini(rdev); | ||
| 2992 | return r; | ||
| 2993 | } | ||
| 2994 | r = radeon_bo_pin(rdev->rlc.save_restore_obj, RADEON_GEM_DOMAIN_VRAM, | ||
| 2995 | &rdev->rlc.save_restore_gpu_addr); | ||
| 2996 | if (r) { | ||
| 2997 | radeon_bo_unreserve(rdev->rlc.save_restore_obj); | ||
| 2998 | dev_warn(rdev->dev, "(%d) pin RLC sr bo failed\n", r); | ||
| 2999 | si_rlc_fini(rdev); | ||
| 3000 | return r; | ||
| 3001 | } | ||
| 3002 | |||
| 3003 | /* clear state block */ | ||
| 3004 | if (rdev->rlc.clear_state_obj == NULL) { | ||
| 3005 | r = radeon_bo_create(rdev, RADEON_GPU_PAGE_SIZE, PAGE_SIZE, true, | ||
| 3006 | RADEON_GEM_DOMAIN_VRAM, &rdev->rlc.clear_state_obj); | ||
| 3007 | if (r) { | ||
| 3008 | dev_warn(rdev->dev, "(%d) create RLC c bo failed\n", r); | ||
| 3009 | si_rlc_fini(rdev); | ||
| 3010 | return r; | ||
| 3011 | } | ||
| 3012 | } | ||
| 3013 | r = radeon_bo_reserve(rdev->rlc.clear_state_obj, false); | ||
| 3014 | if (unlikely(r != 0)) { | ||
| 3015 | si_rlc_fini(rdev); | ||
| 3016 | return r; | ||
| 3017 | } | ||
| 3018 | r = radeon_bo_pin(rdev->rlc.clear_state_obj, RADEON_GEM_DOMAIN_VRAM, | ||
| 3019 | &rdev->rlc.clear_state_gpu_addr); | ||
| 3020 | if (r) { | ||
| 3021 | |||
| 3022 | radeon_bo_unreserve(rdev->rlc.clear_state_obj); | ||
| 3023 | dev_warn(rdev->dev, "(%d) pin RLC c bo failed\n", r); | ||
| 3024 | si_rlc_fini(rdev); | ||
| 3025 | return r; | ||
| 3026 | } | ||
| 3027 | |||
| 3028 | return 0; | ||
| 3029 | } | ||
| 3030 | |||
| 3031 | static void si_rlc_stop(struct radeon_device *rdev) | ||
| 3032 | { | ||
| 3033 | WREG32(RLC_CNTL, 0); | ||
| 3034 | } | ||
| 3035 | |||
| 3036 | static void si_rlc_start(struct radeon_device *rdev) | ||
| 3037 | { | ||
| 3038 | WREG32(RLC_CNTL, RLC_ENABLE); | ||
| 3039 | } | ||
| 3040 | |||
| 3041 | static int si_rlc_resume(struct radeon_device *rdev) | ||
| 3042 | { | ||
| 3043 | u32 i; | ||
| 3044 | const __be32 *fw_data; | ||
| 3045 | |||
| 3046 | if (!rdev->rlc_fw) | ||
| 3047 | return -EINVAL; | ||
| 3048 | |||
| 3049 | si_rlc_stop(rdev); | ||
| 3050 | |||
| 3051 | WREG32(RLC_RL_BASE, 0); | ||
| 3052 | WREG32(RLC_RL_SIZE, 0); | ||
| 3053 | WREG32(RLC_LB_CNTL, 0); | ||
| 3054 | WREG32(RLC_LB_CNTR_MAX, 0xffffffff); | ||
| 3055 | WREG32(RLC_LB_CNTR_INIT, 0); | ||
| 3056 | |||
| 3057 | WREG32(RLC_SAVE_AND_RESTORE_BASE, rdev->rlc.save_restore_gpu_addr >> 8); | ||
| 3058 | WREG32(RLC_CLEAR_STATE_RESTORE_BASE, rdev->rlc.clear_state_gpu_addr >> 8); | ||
| 3059 | |||
| 3060 | WREG32(RLC_MC_CNTL, 0); | ||
| 3061 | WREG32(RLC_UCODE_CNTL, 0); | ||
| 3062 | |||
| 3063 | fw_data = (const __be32 *)rdev->rlc_fw->data; | ||
| 3064 | for (i = 0; i < SI_RLC_UCODE_SIZE; i++) { | ||
| 3065 | WREG32(RLC_UCODE_ADDR, i); | ||
| 3066 | WREG32(RLC_UCODE_DATA, be32_to_cpup(fw_data++)); | ||
| 3067 | } | ||
| 3068 | WREG32(RLC_UCODE_ADDR, 0); | ||
| 3069 | |||
| 3070 | si_rlc_start(rdev); | ||
| 3071 | |||
| 3072 | return 0; | ||
| 3073 | } | ||
| 3074 | |||
diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 904c4fd031f9..78b5649aeceb 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h | |||
| @@ -513,6 +513,23 @@ | |||
| 513 | 513 | ||
| 514 | #define CP_DEBUG 0xC1FC | 514 | #define CP_DEBUG 0xC1FC |
| 515 | 515 | ||
| 516 | #define RLC_CNTL 0xC300 | ||
| 517 | # define RLC_ENABLE (1 << 0) | ||
| 518 | #define RLC_RL_BASE 0xC304 | ||
| 519 | #define RLC_RL_SIZE 0xC308 | ||
| 520 | #define RLC_LB_CNTL 0xC30C | ||
| 521 | #define RLC_SAVE_AND_RESTORE_BASE 0xC310 | ||
| 522 | #define RLC_LB_CNTR_MAX 0xC314 | ||
| 523 | #define RLC_LB_CNTR_INIT 0xC318 | ||
| 524 | |||
| 525 | #define RLC_CLEAR_STATE_RESTORE_BASE 0xC320 | ||
| 526 | |||
| 527 | #define RLC_UCODE_ADDR | ||
