root/drivers/mfd/si476x-prop.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. si476x_core_element_is_in_array
  2. si476x_core_element_is_in_range
  3. si476x_core_is_valid_property_a10
  4. si476x_core_is_valid_property_a20
  5. si476x_core_is_valid_property_a30
  6. si476x_core_is_valid_property
  7. si476x_core_is_readonly_property
  8. si476x_core_regmap_readable_register
  9. si476x_core_regmap_writable_register
  10. si476x_core_regmap_write
  11. si476x_core_regmap_read
  12. devm_regmap_init_si476x

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * drivers/mfd/si476x-prop.c -- Subroutines to access
   4  * properties of si476x chips
   5  *
   6  * Copyright (C) 2012 Innovative Converged Devices(ICD)
   7  * Copyright (C) 2013 Andrey Smirnov
   8  *
   9  * Author: Andrey Smirnov <andrew.smirnov@gmail.com>
  10  */
  11 #include <linux/module.h>
  12 
  13 #include <linux/mfd/si476x-core.h>
  14 
  15 struct si476x_property_range {
  16         u16 low, high;
  17 };
  18 
  19 static bool si476x_core_element_is_in_array(u16 element,
  20                                             const u16 array[],
  21                                             size_t size)
  22 {
  23         int i;
  24 
  25         for (i = 0; i < size; i++)
  26                 if (element == array[i])
  27                         return true;
  28 
  29         return false;
  30 }
  31 
  32 static bool si476x_core_element_is_in_range(u16 element,
  33                                             const struct si476x_property_range range[],
  34                                             size_t size)
  35 {
  36         int i;
  37 
  38         for (i = 0; i < size; i++)
  39                 if (element <= range[i].high && element >= range[i].low)
  40                         return true;
  41 
  42         return false;
  43 }
  44 
  45 static bool si476x_core_is_valid_property_a10(struct si476x_core *core,
  46                                               u16 property)
  47 {
  48         static const u16 valid_properties[] = {
  49                 0x0000,
  50                 0x0500, 0x0501,
  51                 0x0600,
  52                 0x0709, 0x070C, 0x070D, 0x70E, 0x710,
  53                 0x0718,
  54                 0x1207, 0x1208,
  55                 0x2007,
  56                 0x2300,
  57         };
  58 
  59         static const struct si476x_property_range valid_ranges[] = {
  60                 { 0x0200, 0x0203 },
  61                 { 0x0300, 0x0303 },
  62                 { 0x0400, 0x0404 },
  63                 { 0x0700, 0x0707 },
  64                 { 0x1100, 0x1102 },
  65                 { 0x1200, 0x1204 },
  66                 { 0x1300, 0x1306 },
  67                 { 0x2000, 0x2005 },
  68                 { 0x2100, 0x2104 },
  69                 { 0x2106, 0x2106 },
  70                 { 0x2200, 0x220E },
  71                 { 0x3100, 0x3104 },
  72                 { 0x3207, 0x320F },
  73                 { 0x3300, 0x3304 },
  74                 { 0x3500, 0x3517 },
  75                 { 0x3600, 0x3617 },
  76                 { 0x3700, 0x3717 },
  77                 { 0x4000, 0x4003 },
  78         };
  79 
  80         return  si476x_core_element_is_in_range(property, valid_ranges,
  81                                                 ARRAY_SIZE(valid_ranges)) ||
  82                 si476x_core_element_is_in_array(property, valid_properties,
  83                                                 ARRAY_SIZE(valid_properties));
  84 }
  85 
  86 static bool si476x_core_is_valid_property_a20(struct si476x_core *core,
  87                                               u16 property)
  88 {
  89         static const u16 valid_properties[] = {
  90                 0x071B,
  91                 0x1006,
  92                 0x2210,
  93                 0x3401,
  94         };
  95 
  96         static const struct si476x_property_range valid_ranges[] = {
  97                 { 0x2215, 0x2219 },
  98         };
  99 
 100         return  si476x_core_is_valid_property_a10(core, property) ||
 101                 si476x_core_element_is_in_range(property, valid_ranges,
 102                                                 ARRAY_SIZE(valid_ranges))  ||
 103                 si476x_core_element_is_in_array(property, valid_properties,
 104                                                 ARRAY_SIZE(valid_properties));
 105 }
 106 
 107 static bool si476x_core_is_valid_property_a30(struct si476x_core *core,
 108                                               u16 property)
 109 {
 110         static const u16 valid_properties[] = {
 111                 0x071C, 0x071D,
 112                 0x1007, 0x1008,
 113                 0x220F, 0x2214,
 114                 0x2301,
 115                 0x3105, 0x3106,
 116                 0x3402,
 117         };
 118 
 119         static const struct si476x_property_range valid_ranges[] = {
 120                 { 0x0405, 0x0411 },
 121                 { 0x2008, 0x200B },
 122                 { 0x2220, 0x2223 },
 123                 { 0x3100, 0x3106 },
 124         };
 125 
 126         return  si476x_core_is_valid_property_a20(core, property) ||
 127                 si476x_core_element_is_in_range(property, valid_ranges,
 128                                                 ARRAY_SIZE(valid_ranges)) ||
 129                 si476x_core_element_is_in_array(property, valid_properties,
 130                                                 ARRAY_SIZE(valid_properties));
 131 }
 132 
 133 typedef bool (*valid_property_pred_t) (struct si476x_core *, u16);
 134 
 135 static bool si476x_core_is_valid_property(struct si476x_core *core,
 136                                           u16 property)
 137 {
 138         static const valid_property_pred_t is_valid_property[] = {
 139                 [SI476X_REVISION_A10] = si476x_core_is_valid_property_a10,
 140                 [SI476X_REVISION_A20] = si476x_core_is_valid_property_a20,
 141                 [SI476X_REVISION_A30] = si476x_core_is_valid_property_a30,
 142         };
 143 
 144         BUG_ON(core->revision > SI476X_REVISION_A30 ||
 145                core->revision == -1);
 146         return is_valid_property[core->revision](core, property);
 147 }
 148 
 149 
 150 static bool si476x_core_is_readonly_property(struct si476x_core *core,
 151                                              u16 property)
 152 {
 153         BUG_ON(core->revision > SI476X_REVISION_A30 ||
 154                core->revision == -1);
 155 
 156         switch (core->revision) {
 157         case SI476X_REVISION_A10:
 158                 return (property == 0x3200);
 159         case SI476X_REVISION_A20:
 160                 return (property == 0x1006 ||
 161                         property == 0x2210 ||
 162                         property == 0x3200);
 163         case SI476X_REVISION_A30:
 164                 return false;
 165         }
 166 
 167         return false;
 168 }
 169 
 170 static bool si476x_core_regmap_readable_register(struct device *dev,
 171                                                  unsigned int reg)
 172 {
 173         struct i2c_client *client = to_i2c_client(dev);
 174         struct si476x_core *core = i2c_get_clientdata(client);
 175 
 176         return si476x_core_is_valid_property(core, (u16) reg);
 177 
 178 }
 179 
 180 static bool si476x_core_regmap_writable_register(struct device *dev,
 181                                                  unsigned int reg)
 182 {
 183         struct i2c_client *client = to_i2c_client(dev);
 184         struct si476x_core *core = i2c_get_clientdata(client);
 185 
 186         return si476x_core_is_valid_property(core, (u16) reg) &&
 187                 !si476x_core_is_readonly_property(core, (u16) reg);
 188 }
 189 
 190 
 191 static int si476x_core_regmap_write(void *context, unsigned int reg,
 192                                     unsigned int val)
 193 {
 194         return si476x_core_cmd_set_property(context, reg, val);
 195 }
 196 
 197 static int si476x_core_regmap_read(void *context, unsigned int reg,
 198                                    unsigned *val)
 199 {
 200         struct si476x_core *core = context;
 201         int err;
 202 
 203         err = si476x_core_cmd_get_property(core, reg);
 204         if (err < 0)
 205                 return err;
 206 
 207         *val = err;
 208 
 209         return 0;
 210 }
 211 
 212 
 213 static const struct regmap_config si476x_regmap_config = {
 214         .reg_bits = 16,
 215         .val_bits = 16,
 216 
 217         .max_register = 0x4003,
 218 
 219         .writeable_reg = si476x_core_regmap_writable_register,
 220         .readable_reg = si476x_core_regmap_readable_register,
 221 
 222         .reg_read = si476x_core_regmap_read,
 223         .reg_write = si476x_core_regmap_write,
 224 
 225         .cache_type = REGCACHE_RBTREE,
 226 };
 227 
 228 struct regmap *devm_regmap_init_si476x(struct si476x_core *core)
 229 {
 230         return devm_regmap_init(&core->client->dev, NULL,
 231                                 core, &si476x_regmap_config);
 232 }
 233 EXPORT_SYMBOL_GPL(devm_regmap_init_si476x);

/* [<][>][^][v][top][bottom][index][help] */