diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/core.c | 9 | ||||
-rw-r--r-- | drivers/base/dma-contiguous.c | 2 | ||||
-rw-r--r-- | drivers/base/power/clock_ops.c | 3 | ||||
-rw-r--r-- | drivers/base/power/common.c | 4 | ||||
-rw-r--r-- | drivers/base/power/runtime.c | 13 | ||||
-rw-r--r-- | drivers/base/regmap/regmap-irq.c | 92 |
6 files changed, 90 insertions, 33 deletions
diff --git a/drivers/base/core.c b/drivers/base/core.c index f338037a4f3d..5e6e00bc1652 100644 --- a/drivers/base/core.c +++ b/drivers/base/core.c @@ -1865,6 +1865,7 @@ int __dev_printk(const char *level, const struct device *dev, struct va_format *vaf) { char dict[128]; + const char *level_extra = ""; size_t dictlen = 0; const char *subsys; @@ -1911,10 +1912,14 @@ int __dev_printk(const char *level, const struct device *dev, "DEVICE=+%s:%s", subsys, dev_name(dev)); } skip: + if (level[2]) + level_extra = &level[2]; /* skip past KERN_SOH "L" */ + return printk_emit(0, level[1] - '0', dictlen ? dict : NULL, dictlen, - "%s %s: %pV", - dev_driver_string(dev), dev_name(dev), vaf); + "%s %s: %s%pV", + dev_driver_string(dev), dev_name(dev), + level_extra, vaf); } EXPORT_SYMBOL(__dev_printk); diff --git a/drivers/base/dma-contiguous.c b/drivers/base/dma-contiguous.c index 78efb0306a44..34d94c762a1e 100644 --- a/drivers/base/dma-contiguous.c +++ b/drivers/base/dma-contiguous.c @@ -250,7 +250,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size, return -EINVAL; /* Sanitise input arguments */ - alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order); + alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order); base = ALIGN(base, alignment); size = ALIGN(size, alignment); limit &= ~(alignment - 1); diff --git a/drivers/base/power/clock_ops.c b/drivers/base/power/clock_ops.c index 869d7ff2227f..eb78e9640c4a 100644 --- a/drivers/base/power/clock_ops.c +++ b/drivers/base/power/clock_ops.c @@ -169,8 +169,7 @@ void pm_clk_init(struct device *dev) */ int pm_clk_create(struct device *dev) { - int ret = dev_pm_get_subsys_data(dev); - return ret < 0 ? ret : 0; + return dev_pm_get_subsys_data(dev); } /** diff --git a/drivers/base/power/common.c b/drivers/base/power/common.c index a14085cc613f..39c32529b833 100644 --- a/drivers/base/power/common.c +++ b/drivers/base/power/common.c @@ -24,7 +24,6 @@ int dev_pm_get_subsys_data(struct device *dev) { struct pm_subsys_data *psd; - int ret = 0; psd = kzalloc(sizeof(*psd), GFP_KERNEL); if (!psd) @@ -40,7 +39,6 @@ int dev_pm_get_subsys_data(struct device *dev) dev->power.subsys_data = psd; pm_clk_init(dev); psd = NULL; - ret = 1; } spin_unlock_irq(&dev->power.lock); @@ -48,7 +46,7 @@ int dev_pm_get_subsys_data(struct device *dev) /* kfree() verifies that its argument is nonzero. */ kfree(psd); - return ret; + return 0; } EXPORT_SYMBOL_GPL(dev_pm_get_subsys_data); diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 59894873a3b3..7d9c1cb1c39a 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -147,6 +147,8 @@ static int rpm_check_suspend_allowed(struct device *dev) || (dev->power.request_pending && dev->power.request == RPM_REQ_RESUME)) retval = -EAGAIN; + else if (__dev_pm_qos_read_value(dev) < 0) + retval = -EPERM; else if (dev->power.runtime_status == RPM_SUSPENDED) retval = 1; @@ -388,7 +390,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto repeat; } - dev->power.deferred_resume = false; if (dev->power.no_callbacks) goto no_callback; /* Assume success. */ @@ -403,12 +404,6 @@ static int rpm_suspend(struct device *dev, int rpmflags) goto out; } - if (__dev_pm_qos_read_value(dev) < 0) { - /* Negative PM QoS constraint means "never suspend". */ - retval = -EPERM; - goto out; - } - __update_runtime_status(dev, RPM_SUSPENDING); if (dev->pm_domain) @@ -440,6 +435,7 @@ static int rpm_suspend(struct device *dev, int rpmflags) wake_up_all(&dev->power.wait_queue); if (dev->power.deferred_resume) { + dev->power.deferred_resume = false; rpm_resume(dev, 0); retval = -EAGAIN; goto out; @@ -584,6 +580,7 @@ static int rpm_resume(struct device *dev, int rpmflags) || dev->parent->power.runtime_status == RPM_ACTIVE) { atomic_inc(&dev->parent->power.child_count); spin_unlock(&dev->parent->power.lock); + retval = 1; goto no_callback; /* Assume success. */ } spin_unlock(&dev->parent->power.lock); @@ -664,7 +661,7 @@ static int rpm_resume(struct device *dev, int rpmflags) } wake_up_all(&dev->power.wait_queue); - if (!retval) + if (retval >= 0) rpm_idle(dev, RPM_ASYNC); out: diff --git a/drivers/base/regmap/regmap-irq.c b/drivers/base/regmap/regmap-irq.c index a89734621e51..5b6b1d8e6cc0 100644 --- a/drivers/base/regmap/regmap-irq.c +++ b/drivers/base/regmap/regmap-irq.c @@ -16,12 +16,14 @@ #include <linux/irq.h> #include <linux/interrupt.h> #include <linux/irqdomain.h> +#include <linux/pm_runtime.h> #include <linux/slab.h> #include "internal.h" struct regmap_irq_chip_data { struct mutex lock; + struct irq_chip irq_chip; struct regmap *map; const struct regmap_irq_chip *chip; @@ -59,6 +61,14 @@ static void regmap_irq_sync_unlock(struct irq_data *data) struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data); struct regmap *map = d->map; int i, ret; + u32 reg; + + if (d->chip->runtime_pm) { + ret = pm_runtime_get_sync(map->dev); + if (ret < 0) + dev_err(map->dev, "IRQ sync failed to resume: %d\n", + ret); + } /* * If there's been a change in the mask write it back to the @@ -66,15 +76,22 @@ static void regmap_irq_sync_unlock(struct irq_data *data) * suppress pointless writes. */ for (i = 0; i < d->chip->num_regs; i++) { - ret = regmap_update_bits(d->map, d->chip->mask_base + - (i * map->reg_stride * - d->irq_reg_stride), + reg = d->chip->mask_base + + (i * map->reg_stride * d->irq_reg_stride); + if (d->chip->mask_invert) + ret = regmap_update_bits(d->map, reg, + d->mask_buf_def[i], ~d->mask_buf[i]); + else + ret = regmap_update_bits(d->map, reg, d->mask_buf_def[i], d->mask_buf[i]); if (ret != 0) dev_err(d->map->dev, "Failed to sync masks in %x\n", - d->chip->mask_base + (i * map->reg_stride)); + reg); } + if (d->chip->runtime_pm) + pm_runtime_put(map->dev); + /* If we've changed our wakeup count propagate it to the parent */ if (d->wake_count < 0) for (i = d->wake_count; i < 0; i++) @@ -128,8 +145,7 @@ static int regmap_irq_set_wake(struct irq_data *data, unsigned int on) return 0; } -static struct irq_chip regmap_irq_chip = { - .name = "regmap", +static const struct irq_chip regmap_irq_chip = { .irq_bus_lock = regmap_irq_lock, .irq_bus_sync_unlock = regmap_irq_sync_unlock, .irq_disable = regmap_irq_disable, @@ -144,6 +160,16 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) struct regmap *map = data->map; int ret, i; bool handled = false; + u32 reg; + + if (chip->runtime_pm) { + ret = pm_runtime_get_sync(map->dev); + if (ret < 0) { + dev_err(map->dev, "IRQ thread failed to resume: %d\n", + ret); + return IRQ_NONE; + } + } /* * Ignore masked IRQs and ack if we need to; we ack early so @@ -160,20 +186,20 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) if (ret != 0) { dev_err(map->dev, "Failed to read IRQ status: %d\n", ret); + if (chip->runtime_pm) + pm_runtime_put(map->dev); return IRQ_NONE; } data->status_buf[i] &= ~data->mask_buf[i]; if (data->status_buf[i] && chip->ack_base) { - ret = regmap_write(map, chip->ack_base + - (i * map->reg_stride * - data->irq_reg_stride), - data->status_buf[i]); + reg = chip->ack_base + + (i * map->reg_stride * data->irq_reg_stride); + ret = regmap_write(map, reg, data->status_buf[i]); if (ret != 0) dev_err(map->dev, "Failed to ack 0x%x: %d\n", - chip->ack_base + (i * map->reg_stride), - ret); + reg, ret); } } @@ -185,6 +211,9 @@ static irqreturn_t regmap_irq_thread(int irq, void *d) } } + if (chip->runtime_pm) + pm_runtime_put(map->dev); + if (handled) return IRQ_HANDLED; else @@ -197,7 +226,7 @@ static int regmap_irq_map(struct irq_domain *h, unsigned int virq, struct regmap_irq_chip_data *data = h->host_data; irq_set_chip_data(virq, data); - irq_set_chip_and_handler(virq, ®map_irq_chip, handle_edge_irq); + irq_set_chip(virq, &data->irq_chip); irq_set_nested_thread(virq, 1); /* ARM needs us to explicitly flag the IRQ as valid @@ -238,6 +267,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, struct regmap_irq_chip_data *d; int i; int ret = -ENOMEM; + u32 reg; for (i = 0; i < chip->num_irqs; i++) { if (chip->irqs[i].reg_offset % map->reg_stride) @@ -284,6 +314,13 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, goto err_alloc; } + d->irq_chip = regmap_irq_chip; + d->irq_chip.name = chip->name; + if (!chip->wake_base) { + d->irq_chip.irq_set_wake = NULL; + d->irq_chip.flags |= IRQCHIP_MASK_ON_SUSPEND | + IRQCHIP_SKIP_SET_WAKE; + } d->irq = irq; d->map = map; d->chip = chip; @@ -303,16 +340,37 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags, /* Mask all the interrupts by default */ for (i = 0; i < chip->num_regs; i++) { d->mask_buf[i] = d->mask_buf_def[i]; - ret = regmap_write(map, chip->mask_base + (i * map->reg_stride - * d->irq_reg_stride), - d->mask_buf[i]); + reg = chip->mask_base + + (i * map->reg_stride * d->irq_reg_stride); + if (chip->mask_invert) + ret = regmap_update_bits(map, reg, + d->mask_buf[i], ~d->mask_buf[i]); + else + ret = regmap_update_bits(map, reg, + d->mask_buf[i], d->mask_buf[i]); if (ret != 0) { dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", - chip->mask_base + (i * map->reg_stride), ret); + reg, ret); goto err_alloc; } } + /* Wake is disabled by default */ + if (d->wake_buf) { + for (i = 0; i < chip->num_regs; i++) { + d->wake_buf[i] = d->mask_buf_def[i]; + reg = chip->wake_base + + (i * map->reg_stride * d->irq_reg_stride); + ret = regmap_update_bits(map, reg, d->wake_buf[i], + d->wake_buf[i]); + if (ret != 0) { + dev_err(map->dev, "Failed to set masks in 0x%x: %d\n", + reg, ret); + goto err_alloc; + } + } + } + if (irq_base) d->domain = irq_domain_add_legacy(map->dev->of_node, chip->num_irqs, irq_base, 0, |