]> Git Repo - linux.git/commitdiff
Merge remote-tracking branches 'regmap/topic/64bit' and 'regmap/topic/irq-type' into...
authorMark Brown <[email protected]>
Tue, 5 Jan 2016 19:07:17 +0000 (19:07 +0000)
committerMark Brown <[email protected]>
Tue, 5 Jan 2016 19:07:17 +0000 (19:07 +0000)
1  2  3 
drivers/base/regmap/regcache.c
drivers/base/regmap/regmap-irq.c
drivers/base/regmap/regmap.c
include/linux/regmap.h

index 60aeaad7fb69bd168197ce6a5e19058bcf3ac985,1c0210aa2573124d34dc49e8abe28cef78e23730,4c07802986b2c92862e1f0242eebddcb42e2b45d..348be3a354108eb2533587dabed9495e9c324b5a
@@@@ -100,25 -100,15 -100,15 +100,25 @@@@ int regcache_init(struct regmap *map, c
        int i;
        void *tmp_buf;
   
 --     for (i = 0; i < config->num_reg_defaults; i++)
 --             if (config->reg_defaults[i].reg % map->reg_stride)
 --                     return -EINVAL;
 --
        if (map->cache_type == REGCACHE_NONE) {
 ++             if (config->reg_defaults || config->num_reg_defaults_raw)
 ++                     dev_warn(map->dev,
 ++                              "No cache used with register defaults set!\n");
 ++
                map->cache_bypass = true;
                return 0;
        }
   
 ++     if (config->reg_defaults && !config->num_reg_defaults) {
 ++             dev_err(map->dev,
 ++                      "Register defaults are set without the number!\n");
 ++             return -EINVAL;
 ++     }
 ++
 ++     for (i = 0; i < config->num_reg_defaults; i++)
 ++             if (config->reg_defaults[i].reg % map->reg_stride)
 ++                     return -EINVAL;
 ++
        for (i = 0; i < ARRAY_SIZE(cache_types); i++)
                if (cache_types[i]->type == map->cache_type)
                        break;
         * a copy of it.
         */
        if (config->reg_defaults) {
 --             if (!map->num_reg_defaults)
 --                     return -EINVAL;
                tmp_buf = kmemdup(config->reg_defaults, map->num_reg_defaults *
                                  sizeof(struct reg_default), GFP_KERNEL);
                if (!tmp_buf)
@@@@ -543,19 -535,30 -535,19 +543,30 @@@@ bool regcache_set_val(struct regmap *ma
        switch (map->cache_word_size) {
        case 1: {
                u8 *cache = base;
+ +
                cache[idx] = val;
                break;
        }
        case 2: {
                u16 *cache = base;
+ +
                cache[idx] = val;
                break;
        }
        case 4: {
                u32 *cache = base;
+ +
+ +             cache[idx] = val;
+ +             break;
+ +     }
+ +#ifdef CONFIG_64BIT
+ +     case 8: {
+ +             u64 *cache = base;
+ +
                cache[idx] = val;
                break;
        }
+ +#endif
        default:
                BUG();
        }
@@@@ -576,16 -579,26 -568,16 +587,26 @@@@ unsigned int regcache_get_val(struct re
        switch (map->cache_word_size) {
        case 1: {
                const u8 *cache = base;
+ +
                return cache[idx];
        }
        case 2: {
                const u16 *cache = base;
+ +
                return cache[idx];
        }
        case 4: {
                const u32 *cache = base;
+ +
+ +             return cache[idx];
+ +     }
+ +#ifdef CONFIG_64BIT
+ +     case 8: {
+ +             const u64 *cache = base;
+ +
                return cache[idx];
        }
+ +#endif
        default:
                BUG();
        }
index 4d2cb21254aaca8cfe64eba1333ac28a8902a49e,8d16db533527362efa638f67b69673607d069327,dbe7a0d15a26693db214e1270be5f470796e0b6b..9b0d202414d065bf6e03a6f39bb33c9925dee4db
@@@@ -39,8 -39,8 -39,11 +39,11 @@@@ struct regmap_irq_chip_data 
        unsigned int *mask_buf;
        unsigned int *mask_buf_def;
        unsigned int *wake_buf;
++      unsigned int *type_buf;
++      unsigned int *type_buf_def;
   
        unsigned int irq_reg_stride;
++      unsigned int type_reg_stride;
   };
   
   static inline const
@@@@ -144,6 -144,6 -147,22 +147,22 @@@@ static void regmap_irq_sync_unlock(stru
                }
        }
   
++      for (i = 0; i < d->chip->num_type_reg; i++) {
++              if (!d->type_buf_def[i])
++                      continue;
++              reg = d->chip->type_base +
++                      (i * map->reg_stride * d->type_reg_stride);
++              if (d->chip->type_invert)
++                      ret = regmap_update_bits(d->map, reg,
++                              d->type_buf_def[i], ~d->type_buf[i]);
++              else
++                      ret = regmap_update_bits(d->map, reg,
++                              d->type_buf_def[i], d->type_buf[i]);
++              if (ret != 0)
++                      dev_err(d->map->dev, "Failed to sync type in %x\n",
++                              reg);
++      }
++ 
        if (d->chip->runtime_pm)
                pm_runtime_put(map->dev);
   
@@@@ -178,6 -178,6 -197,38 +197,38 @@@@ static void regmap_irq_disable(struct i
        d->mask_buf[irq_data->reg_offset / map->reg_stride] |= irq_data->mask;
   }
   
++ static int regmap_irq_set_type(struct irq_data *data, unsigned int type)
++ {
++      struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
++      struct regmap *map = d->map;
++      const struct regmap_irq *irq_data = irq_to_regmap_irq(d, data->hwirq);
++      int reg = irq_data->type_reg_offset / map->reg_stride;
++ 
++      if (!(irq_data->type_rising_mask | irq_data->type_falling_mask))
++              return 0;
++ 
++      d->type_buf[reg] &= ~(irq_data->type_falling_mask |
++                                      irq_data->type_rising_mask);
++      switch (type) {
++      case IRQ_TYPE_EDGE_FALLING:
++              d->type_buf[reg] |= irq_data->type_falling_mask;
++              break;
++ 
++      case IRQ_TYPE_EDGE_RISING:
++              d->type_buf[reg] |= irq_data->type_rising_mask;
++              break;
++ 
++      case IRQ_TYPE_EDGE_BOTH:
++              d->type_buf[reg] |= (irq_data->type_falling_mask |
++                                      irq_data->type_rising_mask);
++              break;
++ 
++      default:
++              return -EINVAL;
++      }
++      return 0;
++ }
++ 
   static int regmap_irq_set_wake(struct irq_data *data, unsigned int on)
   {
        struct regmap_irq_chip_data *d = irq_data_get_irq_chip_data(data);
@@@@ -204,6 -204,6 -255,7 +255,7 @@@@ static const struct irq_chip regmap_irq
        .irq_bus_sync_unlock    = regmap_irq_sync_unlock,
        .irq_disable            = regmap_irq_disable,
        .irq_enable             = regmap_irq_enable,
++      .irq_set_type           = regmap_irq_set_type,
        .irq_set_wake           = regmap_irq_set_wake,
   };
   
@@@@ -386,28 -386,28 -438,40 +438,40 @@@@ int regmap_add_irq_chip(struct regmap *
        if (!d)
                return -ENOMEM;
   
 --     d->status_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
 ++     d->status_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
                                GFP_KERNEL);
        if (!d->status_buf)
                goto err_alloc;
   
 --     d->mask_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
 ++     d->mask_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
                              GFP_KERNEL);
        if (!d->mask_buf)
                goto err_alloc;
   
 --     d->mask_buf_def = kzalloc(sizeof(unsigned int) * chip->num_regs,
 ++     d->mask_buf_def = kcalloc(chip->num_regs, sizeof(unsigned int),
                                  GFP_KERNEL);
        if (!d->mask_buf_def)
                goto err_alloc;
   
        if (chip->wake_base) {
 --             d->wake_buf = kzalloc(sizeof(unsigned int) * chip->num_regs,
 ++             d->wake_buf = kcalloc(chip->num_regs, sizeof(unsigned int),
                                      GFP_KERNEL);
                if (!d->wake_buf)
                        goto err_alloc;
        }
   
++      if (chip->num_type_reg) {
++              d->type_buf_def = kcalloc(chip->num_type_reg,
++                                      sizeof(unsigned int), GFP_KERNEL);
++              if (!d->type_buf_def)
++                      goto err_alloc;
++ 
++              d->type_buf = kcalloc(chip->num_type_reg, sizeof(unsigned int),
++                                    GFP_KERNEL);
++              if (!d->type_buf)
++                      goto err_alloc;
++      }
++ 
        d->irq_chip = regmap_irq_chip;
        d->irq_chip.name = chip->name;
        d->irq = irq;
        else
                d->irq_reg_stride = 1;
   
++      if (chip->type_reg_stride)
++              d->type_reg_stride = chip->type_reg_stride;
++      else
++              d->type_reg_stride = 1;
++ 
        if (!map->use_single_read && map->reg_stride == 1 &&
            d->irq_reg_stride == 1) {
 --             d->status_reg_buf = kmalloc(map->format.val_bytes *
 --                                         chip->num_regs, GFP_KERNEL);
 ++             d->status_reg_buf = kmalloc_array(chip->num_regs,
 ++                                               map->format.val_bytes,
 ++                                               GFP_KERNEL);
                if (!d->status_reg_buf)
                        goto err_alloc;
        }
                }
        }
   
++      if (chip->num_type_reg) {
++              for (i = 0; i < chip->num_irqs; i++) {
++                      reg = chip->irqs[i].type_reg_offset / map->reg_stride;
++                      d->type_buf_def[reg] |= chip->irqs[i].type_rising_mask |
++                                      chip->irqs[i].type_falling_mask;
++              }
++              for (i = 0; i < chip->num_type_reg; ++i) {
++                      if (!d->type_buf_def[i])
++                              continue;
++ 
++                      reg = chip->type_base +
++                              (i * map->reg_stride * d->type_reg_stride);
++                      if (chip->type_invert)
++                              ret = regmap_update_bits(map, reg,
++                                      d->type_buf_def[i], 0xFF);
++                      else
++                              ret = regmap_update_bits(map, reg,
++                                      d->type_buf_def[i], 0x0);
++                      if (ret != 0) {
++                              dev_err(map->dev,
++                                      "Failed to set type in 0x%x: %x\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,
   err_domain:
        /* Should really dispose of the domain but... */
   err_alloc:
++      kfree(d->type_buf);
++      kfree(d->type_buf_def);
        kfree(d->wake_buf);
        kfree(d->mask_buf_def);
        kfree(d->mask_buf);
@@@@ -565,6 -564,6 -662,8 +663,8 @@@@ void regmap_del_irq_chip(int irq, struc
   
        free_irq(irq, d);
        irq_domain_remove(d->domain);
++      kfree(d->type_buf);
++      kfree(d->type_buf_def);
        kfree(d->wake_buf);
        kfree(d->mask_buf_def);
        kfree(d->mask_buf);
index a8f6dd9457be80d656924394fe08d399b63f86e7,d27fe2f0182ed9118f4e8afc1f340972797e6ee0,4ac63c0e50c7e6a446847b7a29567834d4a5b073..ee54e841de4ad69c96ecb7897ddc04e889e8c702
@@@@ -245,6 -245,28 -245,6 +245,28 @@@@ static void regmap_format_32_native(voi
        *(u32 *)buf = val << shift;
   }
   
+ +#ifdef CONFIG_64BIT
+ +static void regmap_format_64_be(void *buf, unsigned int val, unsigned int shift)
+ +{
+ +     __be64 *b = buf;
+ +
+ +     b[0] = cpu_to_be64((u64)val << shift);
+ +}
+ +
+ +static void regmap_format_64_le(void *buf, unsigned int val, unsigned int shift)
+ +{
+ +     __le64 *b = buf;
+ +
+ +     b[0] = cpu_to_le64((u64)val << shift);
+ +}
+ +
+ +static void regmap_format_64_native(void *buf, unsigned int val,
+ +                                 unsigned int shift)
+ +{
+ +     *(u64 *)buf = (u64)val << shift;
+ +}
+ +#endif
+ +
   static void regmap_parse_inplace_noop(void *buf)
   {
   }
@@@@ -332,6 -354,41 -332,6 +354,41 @@@@ static unsigned int regmap_parse_32_nat
        return *(u32 *)buf;
   }
   
+ +#ifdef CONFIG_64BIT
+ +static unsigned int regmap_parse_64_be(const void *buf)
+ +{
+ +     const __be64 *b = buf;
+ +
+ +     return be64_to_cpu(b[0]);
+ +}
+ +
+ +static unsigned int regmap_parse_64_le(const void *buf)
+ +{
+ +     const __le64 *b = buf;
+ +
+ +     return le64_to_cpu(b[0]);
+ +}
+ +
+ +static void regmap_parse_64_be_inplace(void *buf)
+ +{
+ +     __be64 *b = buf;
+ +
+ +     b[0] = be64_to_cpu(b[0]);
+ +}
+ +
+ +static void regmap_parse_64_le_inplace(void *buf)
+ +{
+ +     __le64 *b = buf;
+ +
+ +     b[0] = le64_to_cpu(b[0]);
+ +}
+ +
+ +static unsigned int regmap_parse_64_native(const void *buf)
+ +{
+ +     return *(u64 *)buf;
+ +}
+ +#endif
+ +
   static void regmap_lock_mutex(void *__map)
   {
        struct regmap *map = __map;
@@@@ -712,6 -769,21 -712,6 +769,21 @@@@ struct regmap *__regmap_init(struct dev
                }
                break;
   
+ +#ifdef CONFIG_64BIT
+ +     case 64:
+ +             switch (reg_endian) {
+ +             case REGMAP_ENDIAN_BIG:
+ +                     map->format.format_reg = regmap_format_64_be;
+ +                     break;
+ +             case REGMAP_ENDIAN_NATIVE:
+ +                     map->format.format_reg = regmap_format_64_native;
+ +                     break;
+ +             default:
+ +                     goto err_map;
+ +             }
+ +             break;
+ +#endif
+ +
        default:
                goto err_map;
        }
                        goto err_map;
                }
                break;
+ +#ifdef CONFIG_64BIT
+ +     case 64:
+ +             switch (val_endian) {
+ +             case REGMAP_ENDIAN_BIG:
+ +                     map->format.format_val = regmap_format_64_be;
+ +                     map->format.parse_val = regmap_parse_64_be;
+ +                     map->format.parse_inplace = regmap_parse_64_be_inplace;
+ +                     break;
+ +             case REGMAP_ENDIAN_LITTLE:
+ +                     map->format.format_val = regmap_format_64_le;
+ +                     map->format.parse_val = regmap_parse_64_le;
+ +                     map->format.parse_inplace = regmap_parse_64_le_inplace;
+ +                     break;
+ +             case REGMAP_ENDIAN_NATIVE:
+ +                     map->format.format_val = regmap_format_64_native;
+ +                     map->format.parse_val = regmap_parse_64_native;
+ +                     break;
+ +             default:
+ +                     goto err_map;
+ +             }
+ +             break;
+ +#endif
        }
   
        if (map->format.format_write) {
@@@@ -1513,7 -1607,7 -1513,7 +1607,7 @@@@ int regmap_write(struct regmap *map, un
   {
        int ret;
   
 --     if (reg % map->reg_stride)
 ++     if (!IS_ALIGNED(reg, map->reg_stride))
                return -EINVAL;
   
        map->lock(map->lock_arg);
@@@@ -1540,7 -1634,7 -1540,7 +1634,7 @@@@ int regmap_write_async(struct regmap *m
   {
        int ret;
   
 --     if (reg % map->reg_stride)
 ++     if (!IS_ALIGNED(reg, map->reg_stride))
                return -EINVAL;
   
        map->lock(map->lock_arg);
@@@@ -1714,7 -1808,7 -1714,7 +1808,7 @@@@ int regmap_bulk_write(struct regmap *ma
   
        if (map->bus && !map->format.parse_inplace)
                return -EINVAL;
 --     if (reg % map->reg_stride)
 ++     if (!IS_ALIGNED(reg, map->reg_stride))
                return -EINVAL;
   
        /*
@@@@ -1983,7 -2077,7 -1983,7 +2077,7 @@@@ static int _regmap_multi_reg_write(stru
                        int reg = regs[i].reg;
                        if (!map->writeable_reg(map->dev, reg))
                                return -EINVAL;
 --                     if (reg % map->reg_stride)
 ++                     if (!IS_ALIGNED(reg, map->reg_stride))
                                return -EINVAL;
                }
   
@@@@ -2133,7 -2227,7 -2133,7 +2227,7 @@@@ int regmap_raw_write_async(struct regma
   
        if (val_len % map->format.val_bytes)
                return -EINVAL;
 --     if (reg % map->reg_stride)
 ++     if (!IS_ALIGNED(reg, map->reg_stride))
                return -EINVAL;
   
        map->lock(map->lock_arg);
@@@@ -2260,7 -2354,7 -2260,7 +2354,7 @@@@ int regmap_read(struct regmap *map, uns
   {
        int ret;
   
 --     if (reg % map->reg_stride)
 ++     if (!IS_ALIGNED(reg, map->reg_stride))
                return -EINVAL;
   
        map->lock(map->lock_arg);
@@@@ -2296,7 -2390,7 -2296,7 +2390,7 @@@@ int regmap_raw_read(struct regmap *map
                return -EINVAL;
        if (val_len % map->format.val_bytes)
                return -EINVAL;
 --     if (reg % map->reg_stride)
 ++     if (!IS_ALIGNED(reg, map->reg_stride))
                return -EINVAL;
        if (val_count == 0)
                return -EINVAL;
@@@@ -2414,7 -2508,7 -2414,7 +2508,7 @@@@ int regmap_bulk_read(struct regmap *map
        size_t val_bytes = map->format.val_bytes;
        bool vol = regmap_volatile_range(map, reg, val_count);
   
 --     if (reg % map->reg_stride)
 ++     if (!IS_ALIGNED(reg, map->reg_stride))
                return -EINVAL;
   
        if (map->bus && map->format.parse_inplace && (vol || map->cache_type == REGCACHE_NONE)) {
                                 * we assume that the values are native
                                 * endian.
                                 */
+ +#ifdef CONFIG_64BIT
+ +                             u64 *u64 = val;
+ +#endif
                                u32 *u32 = val;
                                u16 *u16 = val;
                                u8 *u8 = val;
   
                                switch (map->format.val_bytes) {
+ +#ifdef CONFIG_64BIT
+ +                             case 8:
+ +                                     u64[i] = ival;
+ +                                     break;
+ +#endif
                                case 4:
                                        u32[i] = ival;
                                        break;
diff --combined include/linux/regmap.h
index 4d9a1a04647b003ec5d04e64d2c4c6892dc48681,d68bb402120e2c1a6d640720ef384663ceaefebe,95b6636d3a599a2908a2bb668fca4c76d1309de1..18394343f4891a42dc986e4a17e9c9ebb0b747ee
@@@@ -788,10 -788,10 -788,16 +788,16 @@@@ int regmap_fields_update_bits(struct re
    *
    * @reg_offset: Offset of the status/mask register within the bank
    * @mask:       Mask used to flag/control the register.
++  * @type_reg_offset: Offset register for the irq type setting.
++  * @type_rising_mask: Mask bit to configure RISING type irq.
++  * @type_falling_mask: Mask bit to configure FALLING type irq.
    */
   struct regmap_irq {
        unsigned int reg_offset;
        unsigned int mask;
++      unsigned int type_reg_offset;
++      unsigned int type_rising_mask;
++      unsigned int type_falling_mask;
   };
   
   #define REGMAP_IRQ_REG(_irq, _off, _mask)            \
    * @ack_base:    Base ack address. If zero then the chip is clear on read.
    *               Using zero value is possible with @use_ack bit.
    * @wake_base:   Base address for wake enables.  If zero unsupported.
++  * @type_base:   Base address for irq type.  If zero unsupported.
    * @irq_reg_stride:  Stride to use for chips where registers are not contiguous.
    * @init_ack_masked: Ack all masked interrupts once during initalization.
    * @mask_invert: Inverted mask register: cleared bits are masked out.
    * @use_ack:     Use @ack register even if it is zero.
    * @ack_invert:  Inverted ack register: cleared bits for ack.
    * @wake_invert: Inverted wake register: cleared bits are wake enabled.
++  * @type_invert: Invert the type flags.
    * @runtime_pm:  Hold a runtime PM lock on the device when accessing it.
    *
    * @num_regs:    Number of registers in each control bank.
    * @irqs:        Descriptors for individual IRQs.  Interrupt numbers are
    *               assigned based on the index in the array of the interrupt.
    * @num_irqs:    Number of descriptors.
++  * @num_type_reg:    Number of type registers.
++  * @type_reg_stride: Stride to use for chips where type registers are not
++  *                   contiguous.
    */
   struct regmap_irq_chip {
        const char *name;
        unsigned int unmask_base;
        unsigned int ack_base;
        unsigned int wake_base;
++      unsigned int type_base;
        unsigned int irq_reg_stride;
        bool init_ack_masked:1;
        bool mask_invert:1;
        bool ack_invert:1;
        bool wake_invert:1;
        bool runtime_pm:1;
++      bool type_invert:1;
   
        int num_regs;
   
        const struct regmap_irq *irqs;
        int num_irqs;
++ 
++      int num_type_reg;
++      unsigned int type_reg_stride;
   };
   
   struct regmap_irq_chip_data;
@@@@ -1021,7 -1021,7 -1037,7 +1037,7 @@@@ static inline void regmap_async_complet
   }
   
   static inline int regmap_register_patch(struct regmap *map,
 --                                     const struct reg_default *regs,
 ++                                     const struct reg_sequence *regs,
                                        int num_regs)
   {
        WARN_ONCE(1, "regmap API is disabled");
This page took 0.094087 seconds and 4 git commands to generate.