0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019 #include <linux/err.h>
0020 #include <linux/i2c.h>
0021 #include <linux/irq.h>
0022 #include <linux/slab.h>
0023 #include <linux/mutex.h>
0024 #include <linux/module.h>
0025 #include <linux/regmap.h>
0026 #include <linux/mfd/core.h>
0027 #include <linux/mfd/retu.h>
0028 #include <linux/interrupt.h>
0029 #include <linux/moduleparam.h>
0030
0031
0032 #define RETU_REG_ASICR 0x00
0033 #define RETU_REG_ASICR_VILMA (1 << 7)
0034 #define RETU_REG_IDR 0x01
0035 #define RETU_REG_IMR 0x02
0036 #define TAHVO_REG_IMR 0x03
0037
0038
0039 #define RETU_INT_PWR 0
0040
0041 struct retu_dev {
0042 struct regmap *regmap;
0043 struct device *dev;
0044 struct mutex mutex;
0045 struct regmap_irq_chip_data *irq_data;
0046 };
0047
0048 static const struct resource retu_pwrbutton_res[] = {
0049 {
0050 .name = "retu-pwrbutton",
0051 .start = RETU_INT_PWR,
0052 .end = RETU_INT_PWR,
0053 .flags = IORESOURCE_IRQ,
0054 },
0055 };
0056
0057 static const struct mfd_cell retu_devs[] = {
0058 {
0059 .name = "retu-wdt"
0060 },
0061 {
0062 .name = "retu-pwrbutton",
0063 .resources = retu_pwrbutton_res,
0064 .num_resources = ARRAY_SIZE(retu_pwrbutton_res),
0065 }
0066 };
0067
0068 static struct regmap_irq retu_irqs[] = {
0069 [RETU_INT_PWR] = {
0070 .mask = 1 << RETU_INT_PWR,
0071 }
0072 };
0073
0074 static struct regmap_irq_chip retu_irq_chip = {
0075 .name = "RETU",
0076 .irqs = retu_irqs,
0077 .num_irqs = ARRAY_SIZE(retu_irqs),
0078 .num_regs = 1,
0079 .status_base = RETU_REG_IDR,
0080 .mask_base = RETU_REG_IMR,
0081 .ack_base = RETU_REG_IDR,
0082 };
0083
0084
0085 static struct retu_dev *retu_pm_power_off;
0086
0087 static const struct resource tahvo_usb_res[] = {
0088 {
0089 .name = "tahvo-usb",
0090 .start = TAHVO_INT_VBUS,
0091 .end = TAHVO_INT_VBUS,
0092 .flags = IORESOURCE_IRQ,
0093 },
0094 };
0095
0096 static const struct mfd_cell tahvo_devs[] = {
0097 {
0098 .name = "tahvo-usb",
0099 .resources = tahvo_usb_res,
0100 .num_resources = ARRAY_SIZE(tahvo_usb_res),
0101 },
0102 };
0103
0104 static struct regmap_irq tahvo_irqs[] = {
0105 [TAHVO_INT_VBUS] = {
0106 .mask = 1 << TAHVO_INT_VBUS,
0107 }
0108 };
0109
0110 static struct regmap_irq_chip tahvo_irq_chip = {
0111 .name = "TAHVO",
0112 .irqs = tahvo_irqs,
0113 .num_irqs = ARRAY_SIZE(tahvo_irqs),
0114 .num_regs = 1,
0115 .status_base = RETU_REG_IDR,
0116 .mask_base = TAHVO_REG_IMR,
0117 .ack_base = RETU_REG_IDR,
0118 };
0119
0120 static const struct retu_data {
0121 char *chip_name;
0122 char *companion_name;
0123 struct regmap_irq_chip *irq_chip;
0124 const struct mfd_cell *children;
0125 int nchildren;
0126 } retu_data[] = {
0127 [0] = {
0128 .chip_name = "Retu",
0129 .companion_name = "Vilma",
0130 .irq_chip = &retu_irq_chip,
0131 .children = retu_devs,
0132 .nchildren = ARRAY_SIZE(retu_devs),
0133 },
0134 [1] = {
0135 .chip_name = "Tahvo",
0136 .companion_name = "Betty",
0137 .irq_chip = &tahvo_irq_chip,
0138 .children = tahvo_devs,
0139 .nchildren = ARRAY_SIZE(tahvo_devs),
0140 }
0141 };
0142
0143 int retu_read(struct retu_dev *rdev, u8 reg)
0144 {
0145 int ret;
0146 int value;
0147
0148 mutex_lock(&rdev->mutex);
0149 ret = regmap_read(rdev->regmap, reg, &value);
0150 mutex_unlock(&rdev->mutex);
0151
0152 return ret ? ret : value;
0153 }
0154 EXPORT_SYMBOL_GPL(retu_read);
0155
0156 int retu_write(struct retu_dev *rdev, u8 reg, u16 data)
0157 {
0158 int ret;
0159
0160 mutex_lock(&rdev->mutex);
0161 ret = regmap_write(rdev->regmap, reg, data);
0162 mutex_unlock(&rdev->mutex);
0163
0164 return ret;
0165 }
0166 EXPORT_SYMBOL_GPL(retu_write);
0167
0168 static void retu_power_off(void)
0169 {
0170 struct retu_dev *rdev = retu_pm_power_off;
0171 int reg;
0172
0173 mutex_lock(&retu_pm_power_off->mutex);
0174
0175
0176 regmap_read(rdev->regmap, RETU_REG_CC1, ®);
0177 regmap_write(rdev->regmap, RETU_REG_CC1, reg | 2);
0178
0179
0180 regmap_write(rdev->regmap, RETU_REG_WATCHDOG, 0);
0181
0182
0183 for (;;)
0184 cpu_relax();
0185
0186 mutex_unlock(&retu_pm_power_off->mutex);
0187 }
0188
0189 static int retu_regmap_read(void *context, const void *reg, size_t reg_size,
0190 void *val, size_t val_size)
0191 {
0192 int ret;
0193 struct device *dev = context;
0194 struct i2c_client *i2c = to_i2c_client(dev);
0195
0196 BUG_ON(reg_size != 1 || val_size != 2);
0197
0198 ret = i2c_smbus_read_word_data(i2c, *(u8 const *)reg);
0199 if (ret < 0)
0200 return ret;
0201
0202 *(u16 *)val = ret;
0203 return 0;
0204 }
0205
0206 static int retu_regmap_write(void *context, const void *data, size_t count)
0207 {
0208 u8 reg;
0209 u16 val;
0210 struct device *dev = context;
0211 struct i2c_client *i2c = to_i2c_client(dev);
0212
0213 BUG_ON(count != sizeof(reg) + sizeof(val));
0214 memcpy(®, data, sizeof(reg));
0215 memcpy(&val, data + sizeof(reg), sizeof(val));
0216 return i2c_smbus_write_word_data(i2c, reg, val);
0217 }
0218
0219 static struct regmap_bus retu_bus = {
0220 .read = retu_regmap_read,
0221 .write = retu_regmap_write,
0222 .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
0223 };
0224
0225 static const struct regmap_config retu_config = {
0226 .reg_bits = 8,
0227 .val_bits = 16,
0228 };
0229
0230 static int retu_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
0231 {
0232 struct retu_data const *rdat;
0233 struct retu_dev *rdev;
0234 int ret;
0235
0236 if (i2c->addr > ARRAY_SIZE(retu_data))
0237 return -ENODEV;
0238 rdat = &retu_data[i2c->addr - 1];
0239
0240 rdev = devm_kzalloc(&i2c->dev, sizeof(*rdev), GFP_KERNEL);
0241 if (rdev == NULL)
0242 return -ENOMEM;
0243
0244 i2c_set_clientdata(i2c, rdev);
0245 rdev->dev = &i2c->dev;
0246 mutex_init(&rdev->mutex);
0247 rdev->regmap = devm_regmap_init(&i2c->dev, &retu_bus, &i2c->dev,
0248 &retu_config);
0249 if (IS_ERR(rdev->regmap))
0250 return PTR_ERR(rdev->regmap);
0251
0252 ret = retu_read(rdev, RETU_REG_ASICR);
0253 if (ret < 0) {
0254 dev_err(rdev->dev, "could not read %s revision: %d\n",
0255 rdat->chip_name, ret);
0256 return ret;
0257 }
0258
0259 dev_info(rdev->dev, "%s%s%s v%d.%d found\n", rdat->chip_name,
0260 (ret & RETU_REG_ASICR_VILMA) ? " & " : "",
0261 (ret & RETU_REG_ASICR_VILMA) ? rdat->companion_name : "",
0262 (ret >> 4) & 0x7, ret & 0xf);
0263
0264
0265 ret = retu_write(rdev, rdat->irq_chip->mask_base, 0xffff);
0266 if (ret < 0)
0267 return ret;
0268
0269 ret = regmap_add_irq_chip(rdev->regmap, i2c->irq, IRQF_ONESHOT, -1,
0270 rdat->irq_chip, &rdev->irq_data);
0271 if (ret < 0)
0272 return ret;
0273
0274 ret = mfd_add_devices(rdev->dev, -1, rdat->children, rdat->nchildren,
0275 NULL, regmap_irq_chip_get_base(rdev->irq_data),
0276 NULL);
0277 if (ret < 0) {
0278 regmap_del_irq_chip(i2c->irq, rdev->irq_data);
0279 return ret;
0280 }
0281
0282 if (i2c->addr == 1 && !pm_power_off) {
0283 retu_pm_power_off = rdev;
0284 pm_power_off = retu_power_off;
0285 }
0286
0287 return 0;
0288 }
0289
0290 static int retu_remove(struct i2c_client *i2c)
0291 {
0292 struct retu_dev *rdev = i2c_get_clientdata(i2c);
0293
0294 if (retu_pm_power_off == rdev) {
0295 pm_power_off = NULL;
0296 retu_pm_power_off = NULL;
0297 }
0298 mfd_remove_devices(rdev->dev);
0299 regmap_del_irq_chip(i2c->irq, rdev->irq_data);
0300
0301 return 0;
0302 }
0303
0304 static const struct i2c_device_id retu_id[] = {
0305 { "retu", 0 },
0306 { "tahvo", 0 },
0307 { }
0308 };
0309 MODULE_DEVICE_TABLE(i2c, retu_id);
0310
0311 static const struct of_device_id retu_of_match[] = {
0312 { .compatible = "nokia,retu" },
0313 { .compatible = "nokia,tahvo" },
0314 { }
0315 };
0316 MODULE_DEVICE_TABLE(of, retu_of_match);
0317
0318 static struct i2c_driver retu_driver = {
0319 .driver = {
0320 .name = "retu-mfd",
0321 .of_match_table = retu_of_match,
0322 },
0323 .probe = retu_probe,
0324 .remove = retu_remove,
0325 .id_table = retu_id,
0326 };
0327 module_i2c_driver(retu_driver);
0328
0329 MODULE_DESCRIPTION("Retu MFD driver");
0330 MODULE_AUTHOR("Juha Yrjölä");
0331 MODULE_AUTHOR("David Weinehall");
0332 MODULE_AUTHOR("Mikko Ylinen");
0333 MODULE_AUTHOR("Aaro Koskinen <aaro.koskinen@iki.fi>");
0334 MODULE_LICENSE("GPL");