root/drivers/mfd/pcf50633-core.c

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

DEFINITIONS

This source file includes following definitions.
  1. pcf50633_read_block
  2. pcf50633_write_block
  3. pcf50633_reg_read
  4. pcf50633_reg_write
  5. pcf50633_reg_set_bit_mask
  6. pcf50633_reg_clear_bits
  7. show_dump_regs
  8. show_resume_reason
  9. pcf50633_client_dev_register
  10. pcf50633_suspend
  11. pcf50633_resume
  12. pcf50633_probe
  13. pcf50633_remove
  14. pcf50633_init
  15. pcf50633_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /* NXP PCF50633 Power Management Unit (PMU) driver
   3  *
   4  * (C) 2006-2008 by Openmoko, Inc.
   5  * Author: Harald Welte <laforge@openmoko.org>
   6  *         Balaji Rao <balajirrao@openmoko.org>
   7  * All rights reserved.
   8  */
   9 
  10 #include <linux/kernel.h>
  11 #include <linux/device.h>
  12 #include <linux/sysfs.h>
  13 #include <linux/module.h>
  14 #include <linux/types.h>
  15 #include <linux/interrupt.h>
  16 #include <linux/workqueue.h>
  17 #include <linux/platform_device.h>
  18 #include <linux/i2c.h>
  19 #include <linux/pm.h>
  20 #include <linux/slab.h>
  21 #include <linux/regmap.h>
  22 #include <linux/err.h>
  23 
  24 #include <linux/mfd/pcf50633/core.h>
  25 
  26 /* Read a block of up to 32 regs  */
  27 int pcf50633_read_block(struct pcf50633 *pcf, u8 reg,
  28                                         int nr_regs, u8 *data)
  29 {
  30         int ret;
  31 
  32         ret = regmap_raw_read(pcf->regmap, reg, data, nr_regs);
  33         if (ret != 0)
  34                 return ret;
  35 
  36         return nr_regs;
  37 }
  38 EXPORT_SYMBOL_GPL(pcf50633_read_block);
  39 
  40 /* Write a block of up to 32 regs  */
  41 int pcf50633_write_block(struct pcf50633 *pcf , u8 reg,
  42                                         int nr_regs, u8 *data)
  43 {
  44         return regmap_raw_write(pcf->regmap, reg, data, nr_regs);
  45 }
  46 EXPORT_SYMBOL_GPL(pcf50633_write_block);
  47 
  48 u8 pcf50633_reg_read(struct pcf50633 *pcf, u8 reg)
  49 {
  50         unsigned int val;
  51         int ret;
  52 
  53         ret = regmap_read(pcf->regmap, reg, &val);
  54         if (ret < 0)
  55                 return -1;
  56 
  57         return val;
  58 }
  59 EXPORT_SYMBOL_GPL(pcf50633_reg_read);
  60 
  61 int pcf50633_reg_write(struct pcf50633 *pcf, u8 reg, u8 val)
  62 {
  63         return regmap_write(pcf->regmap, reg, val);
  64 }
  65 EXPORT_SYMBOL_GPL(pcf50633_reg_write);
  66 
  67 int pcf50633_reg_set_bit_mask(struct pcf50633 *pcf, u8 reg, u8 mask, u8 val)
  68 {
  69         return regmap_update_bits(pcf->regmap, reg, mask, val);
  70 }
  71 EXPORT_SYMBOL_GPL(pcf50633_reg_set_bit_mask);
  72 
  73 int pcf50633_reg_clear_bits(struct pcf50633 *pcf, u8 reg, u8 val)
  74 {
  75         return regmap_update_bits(pcf->regmap, reg, val, 0);
  76 }
  77 EXPORT_SYMBOL_GPL(pcf50633_reg_clear_bits);
  78 
  79 /* sysfs attributes */
  80 static ssize_t show_dump_regs(struct device *dev, struct device_attribute *attr,
  81                             char *buf)
  82 {
  83         struct pcf50633 *pcf = dev_get_drvdata(dev);
  84         u8 dump[16];
  85         int n, n1, idx = 0;
  86         char *buf1 = buf;
  87         static u8 address_no_read[] = { /* must be ascending */
  88                 PCF50633_REG_INT1,
  89                 PCF50633_REG_INT2,
  90                 PCF50633_REG_INT3,
  91                 PCF50633_REG_INT4,
  92                 PCF50633_REG_INT5,
  93                 0 /* terminator */
  94         };
  95 
  96         for (n = 0; n < 256; n += sizeof(dump)) {
  97                 for (n1 = 0; n1 < sizeof(dump); n1++)
  98                         if (n == address_no_read[idx]) {
  99                                 idx++;
 100                                 dump[n1] = 0x00;
 101                         } else
 102                                 dump[n1] = pcf50633_reg_read(pcf, n + n1);
 103 
 104                 buf1 += sprintf(buf1, "%*ph\n", (int)sizeof(dump), dump);
 105         }
 106 
 107         return buf1 - buf;
 108 }
 109 static DEVICE_ATTR(dump_regs, 0400, show_dump_regs, NULL);
 110 
 111 static ssize_t show_resume_reason(struct device *dev,
 112                                 struct device_attribute *attr, char *buf)
 113 {
 114         struct pcf50633 *pcf = dev_get_drvdata(dev);
 115         int n;
 116 
 117         n = sprintf(buf, "%02x%02x%02x%02x%02x\n",
 118                                 pcf->resume_reason[0],
 119                                 pcf->resume_reason[1],
 120                                 pcf->resume_reason[2],
 121                                 pcf->resume_reason[3],
 122                                 pcf->resume_reason[4]);
 123 
 124         return n;
 125 }
 126 static DEVICE_ATTR(resume_reason, 0400, show_resume_reason, NULL);
 127 
 128 static struct attribute *pcf_sysfs_entries[] = {
 129         &dev_attr_dump_regs.attr,
 130         &dev_attr_resume_reason.attr,
 131         NULL,
 132 };
 133 
 134 static struct attribute_group pcf_attr_group = {
 135         .name   = NULL,                 /* put in device directory */
 136         .attrs  = pcf_sysfs_entries,
 137 };
 138 
 139 static void
 140 pcf50633_client_dev_register(struct pcf50633 *pcf, const char *name,
 141                                                 struct platform_device **pdev)
 142 {
 143         int ret;
 144 
 145         *pdev = platform_device_alloc(name, -1);
 146         if (!*pdev) {
 147                 dev_err(pcf->dev, "Failed to allocate %s\n", name);
 148                 return;
 149         }
 150 
 151         (*pdev)->dev.parent = pcf->dev;
 152 
 153         ret = platform_device_add(*pdev);
 154         if (ret) {
 155                 dev_err(pcf->dev, "Failed to register %s: %d\n", name, ret);
 156                 platform_device_put(*pdev);
 157                 *pdev = NULL;
 158         }
 159 }
 160 
 161 #ifdef CONFIG_PM_SLEEP
 162 static int pcf50633_suspend(struct device *dev)
 163 {
 164         struct i2c_client *client = to_i2c_client(dev);
 165         struct pcf50633 *pcf = i2c_get_clientdata(client);
 166 
 167         return pcf50633_irq_suspend(pcf);
 168 }
 169 
 170 static int pcf50633_resume(struct device *dev)
 171 {
 172         struct i2c_client *client = to_i2c_client(dev);
 173         struct pcf50633 *pcf = i2c_get_clientdata(client);
 174 
 175         return pcf50633_irq_resume(pcf);
 176 }
 177 #endif
 178 
 179 static SIMPLE_DEV_PM_OPS(pcf50633_pm, pcf50633_suspend, pcf50633_resume);
 180 
 181 static const struct regmap_config pcf50633_regmap_config = {
 182         .reg_bits = 8,
 183         .val_bits = 8,
 184 };
 185 
 186 static int pcf50633_probe(struct i2c_client *client,
 187                                 const struct i2c_device_id *ids)
 188 {
 189         struct pcf50633 *pcf;
 190         struct platform_device *pdev;
 191         struct pcf50633_platform_data *pdata = dev_get_platdata(&client->dev);
 192         int i, j, ret;
 193         int version, variant;
 194 
 195         if (!client->irq) {
 196                 dev_err(&client->dev, "Missing IRQ\n");
 197                 return -ENOENT;
 198         }
 199 
 200         pcf = devm_kzalloc(&client->dev, sizeof(*pcf), GFP_KERNEL);
 201         if (!pcf)
 202                 return -ENOMEM;
 203 
 204         i2c_set_clientdata(client, pcf);
 205         pcf->dev = &client->dev;
 206         pcf->pdata = pdata;
 207 
 208         mutex_init(&pcf->lock);
 209 
 210         pcf->regmap = devm_regmap_init_i2c(client, &pcf50633_regmap_config);
 211         if (IS_ERR(pcf->regmap)) {
 212                 ret = PTR_ERR(pcf->regmap);
 213                 dev_err(pcf->dev, "Failed to allocate register map: %d\n", ret);
 214                 return ret;
 215         }
 216 
 217         version = pcf50633_reg_read(pcf, 0);
 218         variant = pcf50633_reg_read(pcf, 1);
 219         if (version < 0 || variant < 0) {
 220                 dev_err(pcf->dev, "Unable to probe pcf50633\n");
 221                 ret = -ENODEV;
 222                 return ret;
 223         }
 224 
 225         dev_info(pcf->dev, "Probed device version %d variant %d\n",
 226                                                         version, variant);
 227 
 228         pcf50633_irq_init(pcf, client->irq);
 229 
 230         /* Create sub devices */
 231         pcf50633_client_dev_register(pcf, "pcf50633-input", &pcf->input_pdev);
 232         pcf50633_client_dev_register(pcf, "pcf50633-rtc", &pcf->rtc_pdev);
 233         pcf50633_client_dev_register(pcf, "pcf50633-mbc", &pcf->mbc_pdev);
 234         pcf50633_client_dev_register(pcf, "pcf50633-adc", &pcf->adc_pdev);
 235         pcf50633_client_dev_register(pcf, "pcf50633-backlight", &pcf->bl_pdev);
 236 
 237 
 238         for (i = 0; i < PCF50633_NUM_REGULATORS; i++) {
 239                 pdev = platform_device_alloc("pcf50633-regulator", i);
 240                 if (!pdev) {
 241                         ret = -ENOMEM;
 242                         goto err2;
 243                 }
 244 
 245                 pdev->dev.parent = pcf->dev;
 246                 ret = platform_device_add_data(pdev, &pdata->reg_init_data[i],
 247                                                sizeof(pdata->reg_init_data[i]));
 248                 if (ret)
 249                         goto err;
 250 
 251                 ret = platform_device_add(pdev);
 252                 if (ret)
 253                         goto err;
 254 
 255                 pcf->regulator_pdev[i] = pdev;
 256         }
 257 
 258         ret = sysfs_create_group(&client->dev.kobj, &pcf_attr_group);
 259         if (ret)
 260                 dev_warn(pcf->dev, "error creating sysfs entries\n");
 261 
 262         if (pdata->probe_done)
 263                 pdata->probe_done(pcf);
 264 
 265         return 0;
 266 
 267 err:
 268         platform_device_put(pdev);
 269 err2:
 270         for (j = 0; j < i; j++)
 271                 platform_device_put(pcf->regulator_pdev[j]);
 272 
 273         return ret;
 274 }
 275 
 276 static int pcf50633_remove(struct i2c_client *client)
 277 {
 278         struct pcf50633 *pcf = i2c_get_clientdata(client);
 279         int i;
 280 
 281         sysfs_remove_group(&client->dev.kobj, &pcf_attr_group);
 282         pcf50633_irq_free(pcf);
 283 
 284         platform_device_unregister(pcf->input_pdev);
 285         platform_device_unregister(pcf->rtc_pdev);
 286         platform_device_unregister(pcf->mbc_pdev);
 287         platform_device_unregister(pcf->adc_pdev);
 288         platform_device_unregister(pcf->bl_pdev);
 289 
 290         for (i = 0; i < PCF50633_NUM_REGULATORS; i++)
 291                 platform_device_unregister(pcf->regulator_pdev[i]);
 292 
 293         return 0;
 294 }
 295 
 296 static const struct i2c_device_id pcf50633_id_table[] = {
 297         {"pcf50633", 0x73},
 298         {/* end of list */}
 299 };
 300 MODULE_DEVICE_TABLE(i2c, pcf50633_id_table);
 301 
 302 static struct i2c_driver pcf50633_driver = {
 303         .driver = {
 304                 .name   = "pcf50633",
 305                 .pm     = &pcf50633_pm,
 306         },
 307         .id_table = pcf50633_id_table,
 308         .probe = pcf50633_probe,
 309         .remove = pcf50633_remove,
 310 };
 311 
 312 static int __init pcf50633_init(void)
 313 {
 314         return i2c_add_driver(&pcf50633_driver);
 315 }
 316 
 317 static void __exit pcf50633_exit(void)
 318 {
 319         i2c_del_driver(&pcf50633_driver);
 320 }
 321 
 322 MODULE_DESCRIPTION("I2C chip driver for NXP PCF50633 PMU");
 323 MODULE_AUTHOR("Harald Welte <laforge@openmoko.org>");
 324 MODULE_LICENSE("GPL");
 325 
 326 subsys_initcall(pcf50633_init);
 327 module_exit(pcf50633_exit);

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