]> git.kernelconcepts.de Git - karo-tx-linux.git/blobdiff - include/linux/regmap.h
Merge remote-tracking branch 'regmap/topic/table' into regmap-next
[karo-tx-linux.git] / include / linux / regmap.h
index e3bcc3f4dcb8426c4e5e487016417e0e43113666..b7e95bf942c9ce8936f61c61efb0261f9c09ad37 100644 (file)
@@ -19,6 +19,7 @@
 struct module;
 struct device;
 struct i2c_client;
+struct irq_domain;
 struct spi_device;
 struct regmap;
 struct regmap_range_cfg;
@@ -53,6 +54,39 @@ enum regmap_endian {
        REGMAP_ENDIAN_NATIVE,
 };
 
+/**
+ * A register range, used for access related checks
+ * (readable/writeable/volatile/precious checks)
+ *
+ * @range_min: address of first register
+ * @range_max: address of last register
+ */
+struct regmap_range {
+       unsigned int range_min;
+       unsigned int range_max;
+};
+
+/*
+ * A table of ranges including some yes ranges and some no ranges.
+ * If a register belongs to a no_range, the corresponding check function
+ * will return false. If a register belongs to a yes range, the corresponding
+ * check function will return true. "no_ranges" are searched first.
+ *
+ * @yes_ranges : pointer to an array of regmap ranges used as "yes ranges"
+ * @n_yes_ranges: size of the above array
+ * @no_ranges: pointer to an array of regmap ranges used as "no ranges"
+ * @n_no_ranges: size of the above array
+ */
+struct regmap_access_table {
+       const struct regmap_range *yes_ranges;
+       unsigned int n_yes_ranges;
+       const struct regmap_range *no_ranges;
+       unsigned int n_no_ranges;
+};
+
+typedef void (*regmap_lock)(void *);
+typedef void (*regmap_unlock)(void *);
+
 /**
  * Configuration for the register map of a device.
  *
@@ -67,16 +101,39 @@ enum regmap_endian {
  * @val_bits: Number of bits in a register value, mandatory.
  *
  * @writeable_reg: Optional callback returning true if the register
- *                 can be written to.
+ *                can be written to. If this field is NULL but wr_table
+ *                (see below) is not, the check is performed on such table
+ *                 (a register is writeable if it belongs to one of the ranges
+ *                  specified by wr_table).
  * @readable_reg: Optional callback returning true if the register
- *                can be read from.
+ *               can be read from. If this field is NULL but rd_table
+ *                (see below) is not, the check is performed on such table
+ *                 (a register is readable if it belongs to one of the ranges
+ *                  specified by rd_table).
  * @volatile_reg: Optional callback returning true if the register
- *                value can't be cached.
+ *               value can't be cached. If this field is NULL but
+ *               volatile_table (see below) is not, the check is performed on
+ *                such table (a register is volatile if it belongs to one of
+ *                the ranges specified by volatile_table).
  * @precious_reg: Optional callback returning true if the rgister
- *                should not be read outside of a call from the driver
- *                (eg, a clear on read interrupt status register).
+ *               should not be read outside of a call from the driver
+ *               (eg, a clear on read interrupt status register). If this
+ *                field is NULL but precious_table (see below) is not, the
+ *                check is performed on such table (a register is precious if
+ *                it belongs to one of the ranges specified by precious_table).
+ * @lock:        Optional lock callback (overrides regmap's default lock
+ *               function, based on spinlock or mutex).
+ * @unlock:      As above for unlocking.
+ * @lock_arg:    this field is passed as the only argument of lock/unlock
+ *               functions (ignored in case regular lock/unlock functions
+ *               are not overridden).
  *
  * @max_register: Optional, specifies the maximum valid register index.
+ * @wr_table:     Optional, points to a struct regmap_access_table specifying
+ *                valid ranges for write access.
+ * @rd_table:     As above, for read access.
+ * @volatile_table: As above, for volatile registers.
+ * @precious_table: As above, for precious registers.
  * @reg_defaults: Power on reset values for registers (for use with
  *                register cache support).
  * @num_reg_defaults: Number of elements in reg_defaults.
@@ -116,8 +173,15 @@ struct regmap_config {
        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);
+       regmap_lock lock;
+       regmap_unlock unlock;
+       void *lock_arg;
 
        unsigned int max_register;
+       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 reg_default *reg_defaults;
        unsigned int num_reg_defaults;
        enum regcache_type cache_type;
@@ -133,7 +197,7 @@ struct regmap_config {
        enum regmap_endian val_format_endian;
 
        const struct regmap_range_cfg *ranges;
-       unsigned int n_ranges;
+       unsigned int num_ranges;
 };
 
 /**
@@ -142,6 +206,8 @@ struct regmap_config {
  *     1. page selector register update;
  *     2. access through data window registers.
  *
+ * @name: Descriptive name for diagnostics
+ *
  * @range_min: Address of the lowest register address in virtual range.
  * @range_max: Address of the highest register in virtual range.
  *
@@ -153,6 +219,8 @@ struct regmap_config {
  * @window_len: Number of registers in data window.
  */
 struct regmap_range_cfg {
+       const char *name;
+
        /* Registers of virtual address range */
        unsigned int range_min;
        unsigned int range_max;
@@ -181,7 +249,9 @@ typedef void (*regmap_hw_free_context)(void *context);
  * Description of a hardware bus for the register map infrastructure.
  *
  * @fast_io: Register IO is fast. Use a spinlock instead of a mutex
- *           to perform locking.
+ *          to perform locking. This field is ignored if custom lock/unlock
+ *          functions are used (see fields lock/unlock of
+ *          struct regmap_config).
  * @write: Write operation.
  * @gather_write: Write operation with split register/value, return -ENOTSUPP
  *                if not implemented  on a given device.
@@ -262,6 +332,16 @@ void regcache_mark_dirty(struct regmap *map);
 int regmap_register_patch(struct regmap *map, const struct reg_default *regs,
                          int num_regs);
 
+static inline bool regmap_reg_in_range(unsigned int reg,
+                                      const struct regmap_range *range)
+{
+       return reg >= range->range_min && reg <= range->range_max;
+}
+
+bool regmap_reg_in_ranges(unsigned int reg,
+                         const struct regmap_range *ranges,
+                         unsigned int nranges);
+
 /**
  * Description of an IRQ for the generic regmap irq_chip.
  *
@@ -317,6 +397,7 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
 void regmap_del_irq_chip(int irq, struct regmap_irq_chip_data *data);
 int regmap_irq_chip_get_base(struct regmap_irq_chip_data *data);
 int regmap_irq_get_virq(struct regmap_irq_chip_data *data, int irq);
+struct irq_domain *regmap_irq_get_domain(struct regmap_irq_chip_data *data);
 
 #else