Merge branches 'acpi-glue', 'acpi-osl', 'acpi-processor' and 'acpi-cppc'
[linux-2.6-microblaze.git] / drivers / acpi / cppc_acpi.c
index bc14547..903528f 100644 (file)
@@ -100,6 +100,16 @@ static DEFINE_PER_CPU(struct cpc_desc *, cpc_desc_ptr);
                                (cpc)->cpc_entry.reg.space_id ==        \
                                ACPI_ADR_SPACE_PLATFORM_COMM)
 
+/* Check if a CPC register is in SystemMemory */
+#define CPC_IN_SYSTEM_MEMORY(cpc) ((cpc)->type == ACPI_TYPE_BUFFER &&  \
+                               (cpc)->cpc_entry.reg.space_id ==        \
+                               ACPI_ADR_SPACE_SYSTEM_MEMORY)
+
+/* Check if a CPC register is in SystemIo */
+#define CPC_IN_SYSTEM_IO(cpc) ((cpc)->type == ACPI_TYPE_BUFFER &&      \
+                               (cpc)->cpc_entry.reg.space_id ==        \
+                               ACPI_ADR_SPACE_SYSTEM_IO)
+
 /* Evaluates to True if reg is a NULL register descriptor */
 #define IS_NULL_REG(reg) ((reg)->space_id ==  ACPI_ADR_SPACE_SYSTEM_MEMORY && \
                                (reg)->address == 0 &&                  \
@@ -305,7 +315,7 @@ static int send_pcc_cmd(int pcc_ss_id, u16 cmd)
                goto end;
        }
 
-       /* wait for completion and check for PCC errro bit */
+       /* wait for completion and check for PCC error bit */
        ret = check_pcc_chan(pcc_ss_id, true);
 
        if (pcc_ss_data->pcc_mrtt)
@@ -424,6 +434,24 @@ bool acpi_cpc_valid(void)
 }
 EXPORT_SYMBOL_GPL(acpi_cpc_valid);
 
+bool cppc_allow_fast_switch(void)
+{
+       struct cpc_register_resource *desired_reg;
+       struct cpc_desc *cpc_ptr;
+       int cpu;
+
+       for_each_possible_cpu(cpu) {
+               cpc_ptr = per_cpu(cpc_desc_ptr, cpu);
+               desired_reg = &cpc_ptr->cpc_regs[DESIRED_PERF];
+               if (!CPC_IN_SYSTEM_MEMORY(desired_reg) &&
+                               !CPC_IN_SYSTEM_IO(desired_reg))
+                       return false;
+       }
+
+       return true;
+}
+EXPORT_SYMBOL_GPL(cppc_allow_fast_switch);
+
 /**
  * acpi_get_psd_map - Map the CPUs in the freq domain of a given cpu
  * @cpu: Find all CPUs that share a domain with cpu.
@@ -736,6 +764,11 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
                                if (gas_t->address) {
                                        void __iomem *addr;
 
+                                       if (!osc_cpc_flexible_adr_space_confirmed) {
+                                               pr_debug("Flexible address space capability not supported\n");
+                                               goto out_free;
+                                       }
+
                                        addr = ioremap(gas_t->address, gas_t->bit_width/8);
                                        if (!addr)
                                                goto out_free;
@@ -758,6 +791,10 @@ int acpi_cppc_processor_probe(struct acpi_processor *pr)
                                                 gas_t->address);
                                        goto out_free;
                                }
+                               if (!osc_cpc_flexible_adr_space_confirmed) {
+                                       pr_debug("Flexible address space capability not supported\n");
+                                       goto out_free;
+                               }
                        } else {
                                if (gas_t->space_id != ACPI_ADR_SPACE_FIXED_HARDWARE || !cpc_ffh_supported()) {
                                        /* Support only PCC, SystemMemory, SystemIO, and FFH type regs. */
@@ -1447,6 +1484,9 @@ EXPORT_SYMBOL_GPL(cppc_set_perf);
  * transition latency for performance change requests. The closest we have
  * is the timing information from the PCCT tables which provides the info
  * on the number and frequency of PCC commands the platform can handle.
+ *
+ * If desired_reg is in the SystemMemory or SystemIo ACPI address space,
+ * then assume there is no latency.
  */
 unsigned int cppc_get_transition_latency(int cpu_num)
 {
@@ -1472,7 +1512,9 @@ unsigned int cppc_get_transition_latency(int cpu_num)
                return CPUFREQ_ETERNAL;
 
        desired_reg = &cpc_desc->cpc_regs[DESIRED_PERF];
-       if (!CPC_IN_PCC(desired_reg))
+       if (CPC_IN_SYSTEM_MEMORY(desired_reg) || CPC_IN_SYSTEM_IO(desired_reg))
+               return 0;
+       else if (!CPC_IN_PCC(desired_reg))
                return CPUFREQ_ETERNAL;
 
        if (pcc_ss_id < 0)