diff options
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/cacheinfo.c | 2 | ||||
-rw-r--r-- | drivers/base/dd.c | 12 | ||||
-rw-r--r-- | drivers/base/firmware_loader/main.c | 7 | ||||
-rw-r--r-- | drivers/base/platform.c | 11 | ||||
-rw-r--r-- | drivers/base/power/domain.c | 20 | ||||
-rw-r--r-- | drivers/base/power/main.c | 5 | ||||
-rw-r--r-- | drivers/base/regmap/internal.h | 5 | ||||
-rw-r--r-- | drivers/base/regmap/regmap.c | 99 |
8 files changed, 139 insertions, 22 deletions
diff --git a/drivers/base/cacheinfo.c b/drivers/base/cacheinfo.c index 5d5b5988e88b..cf78fa6d470d 100644 --- a/drivers/base/cacheinfo.c +++ b/drivers/base/cacheinfo.c @@ -615,6 +615,8 @@ static int cache_add_dev(unsigned int cpu) this_leaf = this_cpu_ci->info_list + i; if (this_leaf->disable_sysfs) continue; + if (this_leaf->type == CACHE_TYPE_NOCACHE) + break; cache_groups = cache_get_attribute_groups(this_leaf); ci_dev = cpu_device_create(parent, this_leaf, cache_groups, "index%1u", i); diff --git a/drivers/base/dd.c b/drivers/base/dd.c index edfc9f0b1180..169412ee4ae8 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -480,9 +480,11 @@ re_probe: if (ret) goto pinctrl_bind_failed; - ret = dma_configure(dev); - if (ret) - goto dma_failed; + if (dev->bus->dma_configure) { + ret = dev->bus->dma_configure(dev); + if (ret) + goto dma_failed; + } if (driver_sysfs_add(dev)) { printk(KERN_ERR "%s: driver_sysfs_add(%s) failed\n", @@ -537,7 +539,7 @@ re_probe: goto done; probe_failed: - dma_deconfigure(dev); + arch_teardown_dma_ops(dev); dma_failed: if (dev->bus) blocking_notifier_call_chain(&dev->bus->p->bus_notifier, @@ -966,7 +968,7 @@ static void __device_release_driver(struct device *dev, struct device *parent) drv->remove(dev); device_links_driver_cleanup(dev); - dma_deconfigure(dev); + arch_teardown_dma_ops(dev); devres_release_all(dev); dev->driver = NULL; diff --git a/drivers/base/firmware_loader/main.c b/drivers/base/firmware_loader/main.c index b3c0498ee433..8e9213b36e31 100644 --- a/drivers/base/firmware_loader/main.c +++ b/drivers/base/firmware_loader/main.c @@ -226,8 +226,11 @@ static int alloc_lookup_fw_priv(const char *fw_name, } tmp = __allocate_fw_priv(fw_name, fwc, dbuf, size); - if (tmp && !(opt_flags & FW_OPT_NOCACHE)) - list_add(&tmp->list, &fwc->head); + if (tmp) { + INIT_LIST_HEAD(&tmp->list); + if (!(opt_flags & FW_OPT_NOCACHE)) + list_add(&tmp->list, &fwc->head); + } spin_unlock(&fwc->lock); *fw_priv = tmp; diff --git a/drivers/base/platform.c b/drivers/base/platform.c index dff82a3c2caa..23cf4427f425 100644 --- a/drivers/base/platform.c +++ b/drivers/base/platform.c @@ -1180,7 +1180,7 @@ int __init platform_bus_init(void) } #ifndef ARCH_HAS_DMA_GET_REQUIRED_MASK -u64 dma_get_required_mask(struct device *dev) +static u64 dma_default_get_required_mask(struct device *dev) { u32 low_totalram = ((max_pfn - 1) << PAGE_SHIFT); u32 high_totalram = ((max_pfn - 1) >> (32 - PAGE_SHIFT)); @@ -1198,6 +1198,15 @@ u64 dma_get_required_mask(struct device *dev) } return mask; } + +u64 dma_get_required_mask(struct device *dev) +{ + const struct dma_map_ops *ops = get_dma_ops(dev); + + if (ops->get_required_mask) + return ops->get_required_mask(dev); + return dma_default_get_required_mask(dev); +} EXPORT_SYMBOL_GPL(dma_get_required_mask); #endif diff --git a/drivers/base/power/domain.c b/drivers/base/power/domain.c index 4b5714199490..7f38a92b444a 100644 --- a/drivers/base/power/domain.c +++ b/drivers/base/power/domain.c @@ -467,6 +467,10 @@ static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on, return -EAGAIN; } + /* Default to shallowest state. */ + if (!genpd->gov) + genpd->state_idx = 0; + if (genpd->power_off) { int ret; @@ -1687,6 +1691,8 @@ int pm_genpd_init(struct generic_pm_domain *genpd, ret = genpd_set_default_power_state(genpd); if (ret) return ret; + } else if (!gov) { + pr_warn("%s : no governor for states\n", genpd->name); } device_initialize(&genpd->dev); @@ -2478,8 +2484,8 @@ static int genpd_iterate_idle_states(struct device_node *dn, * * Returns the device states parsed from the OF node. The memory for the states * is allocated by this function and is the responsibility of the caller to - * free the memory after use. If no domain idle states is found it returns - * -EINVAL and in case of errors, a negative error code. + * free the memory after use. If any or zero compatible domain idle states is + * found it returns 0 and in case of errors, a negative error code is returned. */ int of_genpd_parse_idle_states(struct device_node *dn, struct genpd_power_state **states, int *n) @@ -2488,8 +2494,14 @@ int of_genpd_parse_idle_states(struct device_node *dn, int ret; ret = genpd_iterate_idle_states(dn, NULL); - if (ret <= 0) - return ret < 0 ? ret : -EINVAL; + if (ret < 0) + return ret; + + if (!ret) { + *states = NULL; + *n = 0; + return 0; + } st = kcalloc(ret, sizeof(*st), GFP_KERNEL); if (!st) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index 3f68e2919dc5..a690fd400260 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -1713,8 +1713,10 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) dpm_wait_for_subordinate(dev, async); - if (async_error) + if (async_error) { + dev->power.direct_complete = false; goto Complete; + } /* * If a device configured to wake up the system from sleep states @@ -1726,6 +1728,7 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) pm_wakeup_event(dev, 0); if (pm_wakeup_pending()) { + dev->power.direct_complete = false; async_error = -EBUSY; goto Complete; } diff --git a/drivers/base/regmap/internal.h b/drivers/base/regmap/internal.h index a6bf34d6394e..a98fced9bff8 100644 --- a/drivers/base/regmap/internal.h +++ b/drivers/base/regmap/internal.h @@ -94,11 +94,13 @@ struct regmap { bool (*readable_reg)(struct device *dev, unsigned int reg); bool (*volatile_reg)(struct device *dev, unsigned int reg); bool (*precious_reg)(struct device *dev, unsigned int reg); + bool (*writeable_noinc_reg)(struct device *dev, unsigned int reg); bool (*readable_noinc_reg)(struct device *dev, unsigned int reg); const struct regmap_access_table *wr_table; const struct regmap_access_table *rd_table; const struct regmap_access_table *volatile_table; const struct regmap_access_table *precious_table; + const struct regmap_access_table *wr_noinc_table; const struct regmap_access_table *rd_noinc_table; int (*reg_read)(void *context, unsigned int reg, unsigned int *val); @@ -149,7 +151,7 @@ struct regmap { /* if set, converts bulk read to single read */ bool use_single_read; - /* if set, converts bulk read to single read */ + /* if set, converts bulk write to single write */ bool use_single_write; /* if set, the device supports multi write mode */ bool can_multi_write; @@ -183,6 +185,7 @@ bool regmap_writeable(struct regmap *map, unsigned int reg); bool regmap_readable(struct regmap *map, unsigned int reg); bool regmap_volatile(struct regmap *map, unsigned int reg); bool regmap_precious(struct regmap *map, unsigned int reg); +bool regmap_writeable_noinc(struct regmap *map, unsigned int reg); bool regmap_readable_noinc(struct regmap *map, unsigned int reg); int _regmap_write(struct regmap *map, unsigned int reg, diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c index 0360a90ad6b6..4f822e087def 100644 --- a/drivers/base/regmap/regmap.c +++ b/drivers/base/regmap/regmap.c @@ -35,6 +35,16 @@ */ #undef LOG_DEVICE +#ifdef LOG_DEVICE +static inline bool regmap_should_log(struct regmap *map) +{ + return (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0); +} +#else +static inline bool regmap_should_log(struct regmap *map) { return false; } +#endif + + static int _regmap_update_bits(struct regmap *map, unsigned int reg, unsigned int mask, unsigned int val, bool *change, bool force_write); @@ -168,6 +178,17 @@ bool regmap_precious(struct regmap *map, unsigned int reg) return false; } +bool regmap_writeable_noinc(struct regmap *map, unsigned int reg) +{ + if (map->writeable_noinc_reg) + return map->writeable_noinc_reg(map->dev, reg); + + if (map->wr_noinc_table) + return regmap_check_range_table(map, reg, map->wr_noinc_table); + + return true; +} + bool regmap_readable_noinc(struct regmap *map, unsigned int reg) { if (map->readable_noinc_reg) @@ -762,8 +783,8 @@ struct regmap *__regmap_init(struct device *dev, map->reg_stride_order = ilog2(map->reg_stride); else map->reg_stride_order = -1; - map->use_single_read = config->use_single_rw || !bus || !bus->read; - map->use_single_write = config->use_single_rw || !bus || !bus->write; + map->use_single_read = config->use_single_read || !bus || !bus->read; + map->use_single_write = config->use_single_write || !bus || !bus->write; map->can_multi_write = config->can_multi_write && bus && bus->write; if (bus) { map->max_raw_read = bus->max_raw_read; @@ -777,11 +798,13 @@ struct regmap *__regmap_init(struct device *dev, map->rd_table = config->rd_table; map->volatile_table = config->volatile_table; map->precious_table = config->precious_table; + map->wr_noinc_table = config->wr_noinc_table; map->rd_noinc_table = config->rd_noinc_table; map->writeable_reg = config->writeable_reg; map->readable_reg = config->readable_reg; map->volatile_reg = config->volatile_reg; map->precious_reg = config->precious_reg; + map->writeable_noinc_reg = config->writeable_noinc_reg; map->readable_noinc_reg = config->readable_noinc_reg; map->cache_type = config->cache_type; @@ -1298,6 +1321,7 @@ int regmap_reinit_cache(struct regmap *map, const struct regmap_config *config) map->readable_reg = config->readable_reg; map->volatile_reg = config->volatile_reg; map->precious_reg = config->precious_reg; + map->writeable_noinc_reg = config->writeable_noinc_reg; map->readable_noinc_reg = config->readable_noinc_reg; map->cache_type = config->cache_type; @@ -1755,10 +1779,8 @@ int _regmap_write(struct regmap *map, unsigned int reg, } } -#ifdef LOG_DEVICE - if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0) + if (regmap_should_log(map)) dev_info(map->dev, "%x <= %x\n", reg, val); -#endif trace_regmap_reg_write(map, reg, val); @@ -1898,6 +1920,69 @@ int regmap_raw_write(struct regmap *map, unsigned int reg, EXPORT_SYMBOL_GPL(regmap_raw_write); /** + * regmap_noinc_write(): Write data from a register without incrementing the + * register number + * + * @map: Register map to write to + * @reg: Register to write to + * @val: Pointer to data buffer + * @val_len: Length of output buffer in bytes. + * + * The regmap API usually assumes that bulk bus write operations will write a + * range of registers. Some devices have certain registers for which a write + * operation can write to an internal FIFO. + * + * The target register must be volatile but registers after it can be + * completely unrelated cacheable registers. + * + * This will attempt multiple writes as required to write val_len bytes. + * + * A value of zero will be returned on success, a negative errno will be + * returned in error cases. + */ +int regmap_noinc_write(struct regmap *map, unsigned int reg, + const void *val, size_t val_len) +{ + size_t write_len; + int ret; + + if (!map->bus) + return -EINVAL; + if (!map->bus->write) + return -ENOTSUPP; + if (val_len % map->format.val_bytes) + return -EINVAL; + if (!IS_ALIGNED(reg, map->reg_stride)) + return -EINVAL; + if (val_len == 0) + return -EINVAL; + + map->lock(map->lock_arg); + + if (!regmap_volatile(map, reg) || !regmap_writeable_noinc(map, reg)) { + ret = -EINVAL; + goto out_unlock; + } + + while (val_len) { + if (map->max_raw_write && map->max_raw_write < val_len) + write_len = map->max_raw_write; + else + write_len = val_len; + ret = _regmap_raw_write(map, reg, val, write_len); + if (ret) + goto out_unlock; + val = ((u8 *)val) + write_len; + val_len -= write_len; + } + +out_unlock: + map->unlock(map->lock_arg); + return ret; +} +EXPORT_SYMBOL_GPL(regmap_noinc_write); + +/** * regmap_field_update_bits_base() - Perform a read/modify/write cycle a * register field. * @@ -2450,10 +2535,8 @@ static int _regmap_read(struct regmap *map, unsigned int reg, ret = map->reg_read(context, reg, val); if (ret == 0) { -#ifdef LOG_DEVICE - if (map->dev && strcmp(dev_name(map->dev), LOG_DEVICE) == 0) + if (regmap_should_log(map)) dev_info(map->dev, "%x => %x\n", reg, *val); -#endif trace_regmap_reg_read(map, reg, *val); |