Commit cd50b70c authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'pm+acpi-3.20-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm

Pull one more batch of power management and ACPI updates from Rafael Wysocki:
 "These are mostly fixes on top of the previously merged recent PM and
  ACPI material.

  First, one commit that broke the ACPI LPSS (Low-Power Subsystem)
  driver on a Dell box is reverted and there are two stable-candidate
  fixes for that driver.  Another fix cleans up two recently added ACPI
  EC messages that look odd and the printk level of a noisy debug
  message in the core ACPI resources handling code is reduced.

  In addition to that we have two stable-candidate fixes for the s3c
  cpufreq driver, two cpuidle powernv driver updates related to Device
  Trees and a PNP subsystem cleanup that will allow us to get rid of
  some old ugliness going forward.  Also there is a new blacklist entry
  for the ACPI backlight code.

  Specifics:

   - Revert a recent ACPI LPSS driver commit that prevented the touchpad
     driver from loading on Dell XPS13 (Jarkko Nikula).

   - Make the ACPI LPSS driver disable the I2C controllers and deassert
     SPI host controllers resets at startup on Intel BayTrail and
     Braswell SoCs in case they have been left in wrong states by the
     platform firmware which then may casuse fatal controller driver
     failures during resume from hibernation (Mika Westerberg).

   - Make two recently added ACPI EC messages look better (Scot Doyle).

   - Reduce the printk level of a recently added debug message related
     to ACPI resources that may become noisy in some cases (Rafael J
     Wysocki).

   - Add a new ACPI backlight blacklist entry for Samsung Series 9
     (900X3C/900X3D/900X3E/900X4C/900X4D) laptops where the native
     backlight interface doesn't work while the ACPI based one does
     (Jens Reyer).

   - Make the PNP sybsystem's core code use __request_region() followed
     by __release_region() instead of __check_region() which then will
     allow us to get rid of the latter as it has no more users (Jakub
     Sitnicki).

   - Fix a build breakage and an issue with two __init functions that
     may be called after initialization in the s3c cpufreq driver (Arnd
     Bergmann).

   - Make the powernv cpuidle driver read target_residency values for
     idle states from a Device Tree (as we have the suitable DT bindings
     for that now) and improve the parsing of the powermgmt DT node in
     that driver (Preeti U Murthy)"

* tag 'pm+acpi-3.20-rc1-3' of git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm:
  cpuidle: powernv: Avoid endianness conversions while parsing DT
  cpufreq: s3c: remove last use of resume_clocks callback
  cpufreq: s3c: remove incorrect __init annotations
  ACPI / LPSS: Deassert resets for SPI host controllers on Braswell
  ACPI / LPSS: Always disable I2C host controllers
  ACPI / resources: Change pr_info() to pr_debug() for debug information
  ACPI / video: Disable native backlight on Samsung Series 9 laptops
  cpuidle: powernv: Read target_residency value of idle states from DT if available
  Revert "ACPI / LPSS: Remove non-existing clock control from Intel Lynxpoint I2C"
  ACPI / EC: Remove non-standard log emphasis
  PNP: Switch from __check_region() to __request_region()
parents 2bfedd1d 3466b547
...@@ -105,7 +105,7 @@ static void lpss_uart_setup(struct lpss_private_data *pdata) ...@@ -105,7 +105,7 @@ static void lpss_uart_setup(struct lpss_private_data *pdata)
} }
} }
static void byt_i2c_setup(struct lpss_private_data *pdata) static void lpss_deassert_reset(struct lpss_private_data *pdata)
{ {
unsigned int offset; unsigned int offset;
u32 val; u32 val;
...@@ -114,9 +114,18 @@ static void byt_i2c_setup(struct lpss_private_data *pdata) ...@@ -114,9 +114,18 @@ static void byt_i2c_setup(struct lpss_private_data *pdata)
val = readl(pdata->mmio_base + offset); val = readl(pdata->mmio_base + offset);
val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC; val |= LPSS_RESETS_RESET_APB | LPSS_RESETS_RESET_FUNC;
writel(val, pdata->mmio_base + offset); writel(val, pdata->mmio_base + offset);
}
#define LPSS_I2C_ENABLE 0x6c
static void byt_i2c_setup(struct lpss_private_data *pdata)
{
lpss_deassert_reset(pdata);
if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset)) if (readl(pdata->mmio_base + pdata->dev_desc->prv_offset))
pdata->fixed_clk_rate = 133000000; pdata->fixed_clk_rate = 133000000;
writel(0, pdata->mmio_base + LPSS_I2C_ENABLE);
} }
static struct lpss_device_desc lpt_dev_desc = { static struct lpss_device_desc lpt_dev_desc = {
...@@ -125,7 +134,7 @@ static struct lpss_device_desc lpt_dev_desc = { ...@@ -125,7 +134,7 @@ static struct lpss_device_desc lpt_dev_desc = {
}; };
static struct lpss_device_desc lpt_i2c_dev_desc = { static struct lpss_device_desc lpt_i2c_dev_desc = {
.flags = LPSS_CLK | LPSS_LTR, .flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_LTR,
.prv_offset = 0x800, .prv_offset = 0x800,
}; };
...@@ -166,6 +175,12 @@ static struct lpss_device_desc byt_i2c_dev_desc = { ...@@ -166,6 +175,12 @@ static struct lpss_device_desc byt_i2c_dev_desc = {
.setup = byt_i2c_setup, .setup = byt_i2c_setup,
}; };
static struct lpss_device_desc bsw_spi_dev_desc = {
.flags = LPSS_CLK | LPSS_CLK_GATE | LPSS_CLK_DIVIDER | LPSS_SAVE_CTX,
.prv_offset = 0x400,
.setup = lpss_deassert_reset,
};
#else #else
#define LPSS_ADDR(desc) (0UL) #define LPSS_ADDR(desc) (0UL)
...@@ -198,7 +213,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = { ...@@ -198,7 +213,7 @@ static const struct acpi_device_id acpi_lpss_device_ids[] = {
/* Braswell LPSS devices */ /* Braswell LPSS devices */
{ "80862288", LPSS_ADDR(byt_pwm_dev_desc) }, { "80862288", LPSS_ADDR(byt_pwm_dev_desc) },
{ "8086228A", LPSS_ADDR(byt_uart_dev_desc) }, { "8086228A", LPSS_ADDR(byt_uart_dev_desc) },
{ "8086228E", LPSS_ADDR(byt_spi_dev_desc) }, { "8086228E", LPSS_ADDR(bsw_spi_dev_desc) },
{ "808622C1", LPSS_ADDR(byt_i2c_dev_desc) }, { "808622C1", LPSS_ADDR(byt_i2c_dev_desc) },
{ "INT3430", LPSS_ADDR(lpt_dev_desc) }, { "INT3430", LPSS_ADDR(lpt_dev_desc) },
......
...@@ -680,7 +680,7 @@ static void acpi_ec_start(struct acpi_ec *ec, bool resuming) ...@@ -680,7 +680,7 @@ static void acpi_ec_start(struct acpi_ec *ec, bool resuming)
/* Enable GPE for event processing (SCI_EVT=1) */ /* Enable GPE for event processing (SCI_EVT=1) */
if (!resuming) if (!resuming)
acpi_ec_submit_request(ec); acpi_ec_submit_request(ec);
pr_info("+++++ EC started +++++\n"); pr_debug("EC started\n");
} }
spin_unlock_irqrestore(&ec->lock, flags); spin_unlock_irqrestore(&ec->lock, flags);
} }
...@@ -712,7 +712,7 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending) ...@@ -712,7 +712,7 @@ static void acpi_ec_stop(struct acpi_ec *ec, bool suspending)
acpi_ec_complete_request(ec); acpi_ec_complete_request(ec);
clear_bit(EC_FLAGS_STARTED, &ec->flags); clear_bit(EC_FLAGS_STARTED, &ec->flags);
clear_bit(EC_FLAGS_STOPPED, &ec->flags); clear_bit(EC_FLAGS_STOPPED, &ec->flags);
pr_info("+++++ EC stopped +++++\n"); pr_debug("EC stopped\n");
} }
spin_unlock_irqrestore(&ec->lock, flags); spin_unlock_irqrestore(&ec->lock, flags);
} }
......
...@@ -46,7 +46,7 @@ static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io) ...@@ -46,7 +46,7 @@ static bool acpi_dev_resource_len_valid(u64 start, u64 end, u64 len, bool io)
if (len && reslen && reslen == len && start <= end) if (len && reslen && reslen == len && start <= end)
return true; return true;
pr_info("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n", pr_debug("ACPI: invalid or unassigned resource %s [%016llx - %016llx] length [%016llx]\n",
io ? "io" : "mem", start, end, len); io ? "io" : "mem", start, end, len);
return false; return false;
......
...@@ -540,6 +540,15 @@ static struct dmi_system_id video_dmi_table[] __initdata = { ...@@ -540,6 +540,15 @@ static struct dmi_system_id video_dmi_table[] __initdata = {
DMI_MATCH(DMI_PRODUCT_NAME, "730U3E/740U3E"), DMI_MATCH(DMI_PRODUCT_NAME, "730U3E/740U3E"),
}, },
}, },
{
/* https://bugs.freedesktop.org/show_bug.cgi?id=87286 */
.callback = video_disable_native_backlight,
.ident = "SAMSUNG 900X3C/900X3D/900X3E/900X4C/900X4D",
.matches = {
DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
DMI_MATCH(DMI_PRODUCT_NAME, "900X3C/900X3D/900X3E/900X4C/900X4D"),
},
},
{ {
/* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */ /* https://bugzilla.redhat.com/show_bug.cgi?id=1163574 */
......
...@@ -263,7 +263,7 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy, ...@@ -263,7 +263,7 @@ static int s3c2416_cpufreq_set_target(struct cpufreq_policy *policy,
} }
#ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE #ifdef CONFIG_ARM_S3C2416_CPUFREQ_VCORESCALE
static void __init s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq) static void s3c2416_cpufreq_cfg_regulator(struct s3c2416_data *s3c_freq)
{ {
int count, v, i, found; int count, v, i, found;
struct cpufreq_frequency_table *pos; struct cpufreq_frequency_table *pos;
...@@ -333,7 +333,7 @@ static struct notifier_block s3c2416_cpufreq_reboot_notifier = { ...@@ -333,7 +333,7 @@ static struct notifier_block s3c2416_cpufreq_reboot_notifier = {
.notifier_call = s3c2416_cpufreq_reboot_notifier_evt, .notifier_call = s3c2416_cpufreq_reboot_notifier_evt,
}; };
static int __init s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy) static int s3c2416_cpufreq_driver_init(struct cpufreq_policy *policy)
{ {
struct s3c2416_data *s3c_freq = &s3c2416_cpufreq; struct s3c2416_data *s3c_freq = &s3c2416_cpufreq;
struct cpufreq_frequency_table *pos; struct cpufreq_frequency_table *pos;
......
...@@ -144,11 +144,6 @@ static void s3c_cpufreq_setfvco(struct s3c_cpufreq_config *cfg) ...@@ -144,11 +144,6 @@ static void s3c_cpufreq_setfvco(struct s3c_cpufreq_config *cfg)
(cfg->info->set_fvco)(cfg); (cfg->info->set_fvco)(cfg);
} }
static inline void s3c_cpufreq_resume_clocks(void)
{
cpu_cur.info->resume_clocks();
}
static inline void s3c_cpufreq_updateclk(struct clk *clk, static inline void s3c_cpufreq_updateclk(struct clk *clk,
unsigned int freq) unsigned int freq)
{ {
...@@ -417,9 +412,6 @@ static int s3c_cpufreq_resume(struct cpufreq_policy *policy) ...@@ -417,9 +412,6 @@ static int s3c_cpufreq_resume(struct cpufreq_policy *policy)
last_target = ~0; /* invalidate last_target setting */ last_target = ~0; /* invalidate last_target setting */
/* first, find out what speed we resumed at. */
s3c_cpufreq_resume_clocks();
/* whilst we will be called later on, we try and re-set the /* whilst we will be called later on, we try and re-set the
* cpu frequencies as soon as possible so that we do not end * cpu frequencies as soon as possible so that we do not end
* up resuming devices and then immediately having to re-set * up resuming devices and then immediately having to re-set
...@@ -454,7 +446,7 @@ static struct cpufreq_driver s3c24xx_driver = { ...@@ -454,7 +446,7 @@ static struct cpufreq_driver s3c24xx_driver = {
}; };
int __init s3c_cpufreq_register(struct s3c_cpufreq_info *info) int s3c_cpufreq_register(struct s3c_cpufreq_info *info)
{ {
if (!info || !info->name) { if (!info || !info->name) {
printk(KERN_ERR "%s: failed to pass valid information\n", printk(KERN_ERR "%s: failed to pass valid information\n",
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
#include <linux/notifier.h> #include <linux/notifier.h>
#include <linux/clockchips.h> #include <linux/clockchips.h>
#include <linux/of.h> #include <linux/of.h>
#include <linux/slab.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/firmware.h> #include <asm/firmware.h>
...@@ -158,70 +159,83 @@ static int powernv_add_idle_states(void) ...@@ -158,70 +159,83 @@ static int powernv_add_idle_states(void)
struct device_node *power_mgt; struct device_node *power_mgt;
int nr_idle_states = 1; /* Snooze */ int nr_idle_states = 1; /* Snooze */
int dt_idle_states; int dt_idle_states;
const __be32 *idle_state_flags; u32 *latency_ns, *residency_ns, *flags;
const __be32 *idle_state_latency; int i, rc;
u32 len_flags, flags, latency_ns;
int i;
/* Currently we have snooze statically defined */ /* Currently we have snooze statically defined */
power_mgt = of_find_node_by_path("/ibm,opal/power-mgt"); power_mgt = of_find_node_by_path("/ibm,opal/power-mgt");
if (!power_mgt) { if (!power_mgt) {
pr_warn("opal: PowerMgmt Node not found\n"); pr_warn("opal: PowerMgmt Node not found\n");
return nr_idle_states; goto out;
} }
idle_state_flags = of_get_property(power_mgt, "ibm,cpu-idle-state-flags", &len_flags); /* Read values of any property to determine the num of idle states */
if (!idle_state_flags) { dt_idle_states = of_property_count_u32_elems(power_mgt, "ibm,cpu-idle-state-flags");
pr_warn("DT-PowerMgmt: missing ibm,cpu-idle-state-flags\n"); if (dt_idle_states < 0) {
return nr_idle_states; pr_warn("cpuidle-powernv: no idle states found in the DT\n");
goto out;
} }
idle_state_latency = of_get_property(power_mgt, flags = kzalloc(sizeof(*flags) * dt_idle_states, GFP_KERNEL);
"ibm,cpu-idle-state-latencies-ns", NULL); if (of_property_read_u32_array(power_mgt,
if (!idle_state_latency) { "ibm,cpu-idle-state-flags", flags, dt_idle_states)) {
pr_warn("DT-PowerMgmt: missing ibm,cpu-idle-state-latencies-ns\n"); pr_warn("cpuidle-powernv : missing ibm,cpu-idle-state-flags in DT\n");
return nr_idle_states; goto out_free_flags;
} }
dt_idle_states = len_flags / sizeof(u32); latency_ns = kzalloc(sizeof(*latency_ns) * dt_idle_states, GFP_KERNEL);
rc = of_property_read_u32_array(power_mgt,
"ibm,cpu-idle-state-latencies-ns", latency_ns, dt_idle_states);
if (rc) {
pr_warn("cpuidle-powernv: missing ibm,cpu-idle-state-latencies-ns in DT\n");
goto out_free_latency;
}
for (i = 0; i < dt_idle_states; i++) { residency_ns = kzalloc(sizeof(*residency_ns) * dt_idle_states, GFP_KERNEL);
rc = of_property_read_u32_array(power_mgt,
"ibm,cpu-idle-state-residency-ns", residency_ns, dt_idle_states);
flags = be32_to_cpu(idle_state_flags[i]); for (i = 0; i < dt_idle_states; i++) {
/* Cpuidle accepts exit_latency in us and we estimate /*
* target residency to be 10x exit_latency * Cpuidle accepts exit_latency and target_residency in us.
* Use default target_residency values if f/w does not expose it.
*/ */
latency_ns = be32_to_cpu(idle_state_latency[i]); if (flags[i] & OPAL_PM_NAP_ENABLED) {
if (flags & OPAL_PM_NAP_ENABLED) {
/* Add NAP state */ /* Add NAP state */
strcpy(powernv_states[nr_idle_states].name, "Nap"); strcpy(powernv_states[nr_idle_states].name, "Nap");
strcpy(powernv_states[nr_idle_states].desc, "Nap"); strcpy(powernv_states[nr_idle_states].desc, "Nap");
powernv_states[nr_idle_states].flags = 0; powernv_states[nr_idle_states].flags = 0;
powernv_states[nr_idle_states].exit_latency = powernv_states[nr_idle_states].target_residency = 100;
((unsigned int)latency_ns) / 1000;
powernv_states[nr_idle_states].target_residency =
((unsigned int)latency_ns / 100);
powernv_states[nr_idle_states].enter = &nap_loop; powernv_states[nr_idle_states].enter = &nap_loop;
nr_idle_states++; } else if (flags[i] & OPAL_PM_SLEEP_ENABLED ||
} flags[i] & OPAL_PM_SLEEP_ENABLED_ER1) {
if (flags & OPAL_PM_SLEEP_ENABLED ||
flags & OPAL_PM_SLEEP_ENABLED_ER1) {
/* Add FASTSLEEP state */ /* Add FASTSLEEP state */
strcpy(powernv_states[nr_idle_states].name, "FastSleep"); strcpy(powernv_states[nr_idle_states].name, "FastSleep");
strcpy(powernv_states[nr_idle_states].desc, "FastSleep"); strcpy(powernv_states[nr_idle_states].desc, "FastSleep");
powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP; powernv_states[nr_idle_states].flags = CPUIDLE_FLAG_TIMER_STOP;
powernv_states[nr_idle_states].target_residency = 300000;
powernv_states[nr_idle_states].enter = &fastsleep_loop;
}
powernv_states[nr_idle_states].exit_latency = powernv_states[nr_idle_states].exit_latency =
((unsigned int)latency_ns) / 1000; ((unsigned int)latency_ns[i]) / 1000;
if (!rc) {
powernv_states[nr_idle_states].target_residency = powernv_states[nr_idle_states].target_residency =
((unsigned int)latency_ns / 100); ((unsigned int)residency_ns[i]) / 1000;
powernv_states[nr_idle_states].enter = &fastsleep_loop;
nr_idle_states++;
} }
nr_idle_states++;
} }
kfree(residency_ns);
out_free_latency:
kfree(latency_ns);
out_free_flags:
kfree(flags);
out:
return nr_idle_states; return nr_idle_states;
} }
......
...@@ -179,8 +179,9 @@ int pnp_check_port(struct pnp_dev *dev, struct resource *res) ...@@ -179,8 +179,9 @@ int pnp_check_port(struct pnp_dev *dev, struct resource *res)
/* check if the resource is already in use, skip if the /* check if the resource is already in use, skip if the
* device is active because it itself may be in use */ * device is active because it itself may be in use */
if (!dev->active) { if (!dev->active) {
if (__check_region(&ioport_resource, *port, length(port, end))) if (!request_region(*port, length(port, end), "pnp"))
return 0; return 0;
release_region(*port, length(port, end));
} }
/* check if the resource is reserved */ /* check if the resource is reserved */
...@@ -241,8 +242,9 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res) ...@@ -241,8 +242,9 @@ int pnp_check_mem(struct pnp_dev *dev, struct resource *res)
/* check if the resource is already in use, skip if the /* check if the resource is already in use, skip if the
* device is active because it itself may be in use */ * device is active because it itself may be in use */
if (!dev->active) { if (!dev->active) {
if (check_mem_region(*addr, length(addr, end))) if (!request_mem_region(*addr, length(addr, end), "pnp"))
return 0; return 0;
release_mem_region(*addr, length(addr, end));
} }
/* check if the resource is reserved */ /* check if the resource is reserved */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment