| 1 | |
| 2 | |
| 3 | * MFD core driver for the Richtek RT5033.
|
| 4 | *
|
| 5 | * RT5033 comprises multiple sub-devices switcing charger, fuel gauge,
|
| 6 | * flash LED, current source, LDO and BUCK regulators.
|
| 7 | *
|
| 8 | * Copyright (C) 2014 Samsung Electronics, Co., Ltd.
|
| 9 | * Author: Beomho Seo <[email protected]>
|
| 10 |
|
| 11 |
|
| 12 | #include <linux/err.h>
|
| 13 | #include <linux/module.h>
|
| 14 | #include <linux/interrupt.h>
|
| 15 | #include <linux/mfd/core.h>
|
| 16 | #include <linux/mfd/rt5033.h>
|
| 17 | #include <linux/mfd/rt5033-private.h>
|
| 18 |
|
| 19 | static const struct regmap_irq rt5033_irqs[] = {
|
| 20 | { .mask = RT5033_PMIC_IRQ_BUCKOCP, },
|
| 21 | { .mask = RT5033_PMIC_IRQ_BUCKLV, },
|
| 22 | { .mask = RT5033_PMIC_IRQ_SAFELDOLV, },
|
| 23 | { .mask = RT5033_PMIC_IRQ_LDOLV, },
|
| 24 | { .mask = RT5033_PMIC_IRQ_OT, },
|
| 25 | { .mask = RT5033_PMIC_IRQ_VDDA_UV, },
|
| 26 | };
|
| 27 |
|
| 28 | static const struct regmap_irq_chip rt5033_irq_chip = {
|
| 29 | .name = "rt5033",
|
| 30 | .status_base = RT5033_REG_PMIC_IRQ_STAT,
|
| 31 | .unmask_base = RT5033_REG_PMIC_IRQ_CTRL,
|
| 32 | .num_regs = 1,
|
| 33 | .irqs = rt5033_irqs,
|
| 34 | .num_irqs = ARRAY_SIZE(rt5033_irqs),
|
| 35 | };
|
| 36 |
|
| 37 | static const struct mfd_cell rt5033_devs[] = {
|
| 38 | { .name = "rt5033-regulator", },
|
| 39 | {
|
| 40 | .name = "rt5033-charger",
|
| 41 | .of_compatible = "richtek,rt5033-charger",
|
| 42 | }, {
|
| 43 | .name = "rt5033-led",
|
| 44 | .of_compatible = "richtek,rt5033-led",
|
| 45 | },
|
| 46 | };
|
| 47 |
|
| 48 | static const struct regmap_config rt5033_regmap_config = {
|
| 49 | .reg_bits = 8,
|
| 50 | .val_bits = 8,
|
| 51 | .max_register = RT5033_REG_END,
|
| 52 | };
|
| 53 |
|
| 54 | static int rt5033_i2c_probe(struct i2c_client *i2c)
|
| 55 | {
|
| 56 | struct rt5033_dev *rt5033;
|
| 57 | unsigned int dev_id, chip_rev;
|
| 58 | int ret;
|
| 59 |
|
| 60 | rt5033 = devm_kzalloc(&i2c->dev, sizeof(*rt5033), GFP_KERNEL);
|
| 61 | if (!rt5033)
|
| 62 | return -ENOMEM;
|
| 63 |
|
| 64 | i2c_set_clientdata(i2c, rt5033);
|
| 65 | rt5033->dev = &i2c->dev;
|
| 66 | rt5033->irq = i2c->irq;
|
| 67 | rt5033->wakeup = true;
|
| 68 |
|
| 69 | rt5033->regmap = devm_regmap_init_i2c(i2c, &rt5033_regmap_config);
|
| 70 | if (IS_ERR(rt5033->regmap)) {
|
| 71 | dev_err(&i2c->dev, "Failed to allocate register map.\n");
|
| 72 | return PTR_ERR(rt5033->regmap);
|
| 73 | }
|
| 74 |
|
| 75 | ret = regmap_read(rt5033->regmap, RT5033_REG_DEVICE_ID, &dev_id);
|
| 76 | if (ret) {
|
| 77 | dev_err(&i2c->dev, "Device not found\n");
|
| 78 | return -ENODEV;
|
| 79 | }
|
| 80 | chip_rev = dev_id & RT5033_CHIP_REV_MASK;
|
| 81 | dev_info(&i2c->dev, "Device found (rev. %d)\n", chip_rev);
|
| 82 |
|
| 83 | ret = devm_regmap_add_irq_chip(rt5033->dev, rt5033->regmap,
|
| 84 | rt5033->irq, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
|
| 85 | 0, &rt5033_irq_chip, &rt5033->irq_data);
|
| 86 | if (ret) {
|
| 87 | dev_err(&i2c->dev, "Failed to request IRQ %d: %d\n",
|
| 88 | rt5033->irq, ret);
|
| 89 | return ret;
|
| 90 | }
|
| 91 |
|
| 92 | ret = devm_mfd_add_devices(rt5033->dev, -1, rt5033_devs,
|
| 93 | ARRAY_SIZE(rt5033_devs), NULL, 0,
|
| 94 | regmap_irq_get_domain(rt5033->irq_data));
|
| 95 | if (ret < 0) {
|
| 96 | dev_err(&i2c->dev, "Failed to add RT5033 child devices.\n");
|
| 97 | return ret;
|
| 98 | }
|
| 99 |
|
| 100 | if (rt5033->wakeup) {
|
| 101 | ret = devm_device_init_wakeup(rt5033->dev);
|
| 102 | if (ret)
|
| 103 | return dev_err_probe(rt5033->dev, ret, "Failed to init wakeup\n");
|
| 104 | }
|
| 105 |
|
| 106 | return 0;
|
| 107 | }
|
| 108 |
|
| 109 | static const struct i2c_device_id rt5033_i2c_id[] = {
|
| 110 | { "rt5033", },
|
| 111 | { }
|
| 112 | };
|
| 113 | MODULE_DEVICE_TABLE(i2c, rt5033_i2c_id);
|
| 114 |
|
| 115 | static const struct of_device_id rt5033_dt_match[] = {
|
| 116 | { .compatible = "richtek,rt5033", },
|
| 117 | { }
|
| 118 | };
|
| 119 | MODULE_DEVICE_TABLE(of, rt5033_dt_match);
|
| 120 |
|
| 121 | static struct i2c_driver rt5033_driver = {
|
| 122 | .driver = {
|
| 123 | .name = "rt5033",
|
| 124 | .of_match_table = rt5033_dt_match,
|
| 125 | },
|
| 126 | .probe = rt5033_i2c_probe,
|
| 127 | .id_table = rt5033_i2c_id,
|
| 128 | };
|
| 129 | module_i2c_driver(rt5033_driver);
|
| 130 |
|
| 131 | MODULE_DESCRIPTION("Richtek RT5033 multi-function core driver");
|
| 132 | MODULE_AUTHOR("Beomho Seo <[email protected]>");
|
| 133 | MODULE_LICENSE("GPL");
|