drm/radeon/kms: add dpm support for evergreen (v4)

This adds dpm support for evergreen asics.  This includes:
- clockgating
- dynamic engine clock scaling
- dynamic memory clock scaling
- dynamic voltage scaling
- dynamic pcie gen1/gen2 switching (requires additional acpi support)

Set radeon.dpm=1 to enable.

v2: reduce stack usage, rename ulv struct
v3: fix thermal interrupt check notices by Jerome
v4: fix state enable

Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
diff --git a/drivers/gpu/drm/radeon/rv770_smc.c b/drivers/gpu/drm/radeon/rv770_smc.c
index 8e07153..168aedb 100644
--- a/drivers/gpu/drm/radeon/rv770_smc.c
+++ b/drivers/gpu/drm/radeon/rv770_smc.c
@@ -114,6 +114,86 @@
 	0x03, 0x51, 0x03, 0x51
 };
 
+static const u8 cedar_smc_int_vectors[] =
+{
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x11, 0x8B,
+	0x0B, 0x20, 0x0B, 0x05,
+	0x04, 0xF6, 0x04, 0xF6,
+	0x04, 0xF6, 0x04, 0xF6
+};
+
+static const u8 redwood_smc_int_vectors[] =
+{
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x11, 0x8B,
+	0x0B, 0x20, 0x0B, 0x05,
+	0x04, 0xF6, 0x04, 0xF6,
+	0x04, 0xF6, 0x04, 0xF6
+};
+
+static const u8 juniper_smc_int_vectors[] =
+{
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x11, 0x8B,
+	0x0B, 0x20, 0x0B, 0x05,
+	0x04, 0xF6, 0x04, 0xF6,
+	0x04, 0xF6, 0x04, 0xF6
+};
+
+static const u8 cypress_smc_int_vectors[] =
+{
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x0B, 0x05,
+	0x0B, 0x05, 0x11, 0x8B,
+	0x0B, 0x20, 0x0B, 0x05,
+	0x04, 0xF6, 0x04, 0xF6,
+	0x04, 0xF6, 0x04, 0xF6
+};
+
 int rv770_set_smc_sram_address(struct radeon_device *rdev,
 			       u16 smc_address, u16 limit)
 {
@@ -354,6 +434,35 @@
 		int_vect_start_address = RV740_SMC_INT_VECTOR_START;
 		int_vect_size = RV740_SMC_INT_VECTOR_SIZE;
 		break;
+	case CHIP_CEDAR:
+		ucode_start_address = CEDAR_SMC_UCODE_START;
+		ucode_size = CEDAR_SMC_UCODE_SIZE;
+		int_vect = (const u8 *)&cedar_smc_int_vectors;
+		int_vect_start_address = CEDAR_SMC_INT_VECTOR_START;
+		int_vect_size = CEDAR_SMC_INT_VECTOR_SIZE;
+		break;
+	case CHIP_REDWOOD:
+		ucode_start_address = REDWOOD_SMC_UCODE_START;
+		ucode_size = REDWOOD_SMC_UCODE_SIZE;
+		int_vect = (const u8 *)&redwood_smc_int_vectors;
+		int_vect_start_address = REDWOOD_SMC_INT_VECTOR_START;
+		int_vect_size = REDWOOD_SMC_INT_VECTOR_SIZE;
+		break;
+	case CHIP_JUNIPER:
+		ucode_start_address = JUNIPER_SMC_UCODE_START;
+		ucode_size = JUNIPER_SMC_UCODE_SIZE;
+		int_vect = (const u8 *)&juniper_smc_int_vectors;
+		int_vect_start_address = JUNIPER_SMC_INT_VECTOR_START;
+		int_vect_size = JUNIPER_SMC_INT_VECTOR_SIZE;
+		break;
+	case CHIP_CYPRESS:
+	case CHIP_HEMLOCK:
+		ucode_start_address = CYPRESS_SMC_UCODE_START;
+		ucode_size = CYPRESS_SMC_UCODE_SIZE;
+		int_vect = (const u8 *)&cypress_smc_int_vectors;
+		int_vect_start_address = CYPRESS_SMC_INT_VECTOR_START;
+		int_vect_size = CYPRESS_SMC_INT_VECTOR_SIZE;
+		break;
 	default:
 		DRM_ERROR("unknown asic in smc ucode loader\n");
 		BUG();