1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Motorola CPCAP PMIC core driver 4 * 5 * Copyright (C) 2016 Tony Lindgren <tony@atomide.com> 6 */ 7 8 #include <linux/device.h> 9 #include <linux/err.h> 10 #include <linux/interrupt.h> 11 #include <linux/irq.h> 12 #include <linux/kernel.h> 13 #include <linux/module.h> 14 #include <linux/of_device.h> 15 #include <linux/regmap.h> 16 #include <linux/sysfs.h> 17 18 #include <linux/mfd/core.h> 19 #include <linux/mfd/motorola-cpcap.h> 20 #include <linux/spi/spi.h> 21 22 #define CPCAP_NR_IRQ_REG_BANKS 6 23 #define CPCAP_NR_IRQ_CHIPS 3 24 #define CPCAP_REGISTER_SIZE 4 25 #define CPCAP_REGISTER_BITS 16 26 27 struct cpcap_ddata { 28 struct spi_device *spi; 29 struct regmap_irq *irqs; 30 struct regmap_irq_chip_data *irqdata[CPCAP_NR_IRQ_CHIPS]; 31 const struct regmap_config *regmap_conf; 32 struct regmap *regmap; 33 }; 34 35 static int cpcap_sense_irq(struct regmap *regmap, int irq) 36 { 37 int regnum = irq / CPCAP_REGISTER_BITS; 38 int mask = BIT(irq % CPCAP_REGISTER_BITS); 39 int reg = CPCAP_REG_INTS1 + (regnum * CPCAP_REGISTER_SIZE); 40 int err, val; 41 42 if (reg < CPCAP_REG_INTS1 || reg > CPCAP_REG_INTS4) 43 return -EINVAL; 44 45 err = regmap_read(regmap, reg, &val); 46 if (err) 47 return err; 48 49 return !!(val & mask); 50 } 51 52 int cpcap_sense_virq(struct regmap *regmap, int virq) 53 { 54 struct regmap_irq_chip_data *d = irq_get_chip_data(virq); 55 int irq_base = regmap_irq_chip_get_base(d); 56 57 return cpcap_sense_irq(regmap, virq - irq_base); 58 } 59 EXPORT_SYMBOL_GPL(cpcap_sense_virq); 60 61 static int cpcap_check_revision(struct cpcap_ddata *cpcap) 62 { 63 u16 vendor, rev; 64 int ret; 65 66 ret = cpcap_get_vendor(&cpcap->spi->dev, cpcap->regmap, &vendor); 67 if (ret) 68 return ret; 69 70 ret = cpcap_get_revision(&cpcap->spi->dev, cpcap->regmap, &rev); 71 if (ret) 72 return ret; 73 74 dev_info(&cpcap->spi->dev, "CPCAP vendor: %s rev: %i.%i (%x)\n", 75 vendor == CPCAP_VENDOR_ST ? "ST" : "TI", 76 CPCAP_REVISION_MAJOR(rev), CPCAP_REVISION_MINOR(rev), 77 rev); 78 79 if (rev < CPCAP_REVISION_2_1) { 80 dev_info(&cpcap->spi->dev, 81 "Please add old CPCAP revision support as needed\n"); 82 return -ENODEV; 83 } 84 85 return 0; 86 } 87 88 /* 89 * First two irq chips are the two private macro interrupt chips, the third 90 * irq chip is for register banks 1 - 4 and is available for drivers to use. 91 */ 92 static struct regmap_irq_chip cpcap_irq_chip[CPCAP_NR_IRQ_CHIPS] = { 93 { 94 .name = "cpcap-m2", 95 .num_regs = 1, 96 .status_base = CPCAP_REG_MI1, 97 .ack_base = CPCAP_REG_MI1, 98 .mask_base = CPCAP_REG_MIM1, 99 .use_ack = true, 100 .clear_ack = true, 101 }, 102 { 103 .name = "cpcap-m2", 104 .num_regs = 1, 105 .status_base = CPCAP_REG_MI2, 106 .ack_base = CPCAP_REG_MI2, 107 .mask_base = CPCAP_REG_MIM2, 108 .use_ack = true, 109 .clear_ack = true, 110 }, 111 { 112 .name = "cpcap1-4", 113 .num_regs = 4, 114 .status_base = CPCAP_REG_INT1, 115 .ack_base = CPCAP_REG_INT1, 116 .mask_base = CPCAP_REG_INTM1, 117 .use_ack = true, 118 .clear_ack = true, 119 }, 120 }; 121 122 static void cpcap_init_one_regmap_irq(struct cpcap_ddata *cpcap, 123 struct regmap_irq *rirq, 124 int irq_base, int irq) 125 { 126 unsigned int reg_offset; 127 unsigned int bit, mask; 128 129 reg_offset = irq - irq_base; 130 reg_offset /= cpcap->regmap_conf->val_bits; 131 reg_offset *= cpcap->regmap_conf->reg_stride; 132 133 bit = irq % cpcap->regmap_conf->val_bits; 134 mask = (1 << bit); 135 136 rirq->reg_offset = reg_offset; 137 rirq->mask = mask; 138 } 139 140 static int cpcap_init_irq_chip(struct cpcap_ddata *cpcap, int irq_chip, 141 int irq_start, int nr_irqs) 142 { 143 struct regmap_irq_chip *chip = &cpcap_irq_chip[irq_chip]; 144 int i, ret; 145 146 for (i = irq_start; i < irq_start + nr_irqs; i++) { 147 struct regmap_irq *rirq = &cpcap->irqs[i]; 148 149 cpcap_init_one_regmap_irq(cpcap, rirq, irq_start, i); 150 } 151 chip->irqs = &cpcap->irqs[irq_start]; 152 chip->num_irqs = nr_irqs; 153 chip->irq_drv_data = cpcap; 154 155 ret = devm_regmap_add_irq_chip(&cpcap->spi->dev, cpcap->regmap, 156 cpcap->spi->irq, 157 irq_get_trigger_type(cpcap->spi->irq) | 158 IRQF_SHARED, -1, 159 chip, &cpcap->irqdata[irq_chip]); 160 if (ret) { 161 dev_err(&cpcap->spi->dev, "could not add irq chip %i: %i\n", 162 irq_chip, ret); 163 return ret; 164 } 165 166 return 0; 167 } 168 169 static int cpcap_init_irq(struct cpcap_ddata *cpcap) 170 { 171 int ret; 172 173 cpcap->irqs = devm_kzalloc(&cpcap->spi->dev, 174 array3_size(sizeof(*cpcap->irqs), 175 CPCAP_NR_IRQ_REG_BANKS, 176 cpcap->regmap_conf->val_bits), 177 GFP_KERNEL); 178 if (!cpcap->irqs) 179 return -ENOMEM; 180 181 ret = cpcap_init_irq_chip(cpcap, 0, 0, 16); 182 if (ret) 183 return ret; 184 185 ret = cpcap_init_irq_chip(cpcap, 1, 16, 16); 186 if (ret) 187 return ret; 188 189 ret = cpcap_init_irq_chip(cpcap, 2, 32, 64); 190 if (ret) 191 return ret; 192 193 enable_irq_wake(cpcap->spi->irq); 194 195 return 0; 196 } 197 198 static const struct of_device_id cpcap_of_match[] = { 199 { .compatible = "motorola,cpcap", }, 200 { .compatible = "st,6556002", }, 201 {}, 202 }; 203 MODULE_DEVICE_TABLE(of, cpcap_of_match); 204 205 static const struct spi_device_id cpcap_spi_ids[] = { 206 { .name = "cpcap", }, 207 { .name = "6556002", }, 208 {}, 209 }; 210 MODULE_DEVICE_TABLE(spi, cpcap_spi_ids); 211 212 static const struct regmap_config cpcap_regmap_config = { 213 .reg_bits = 16, 214 .reg_stride = 4, 215 .pad_bits = 0, 216 .val_bits = 16, 217 .write_flag_mask = 0x8000, 218 .max_register = CPCAP_REG_ST_TEST2, 219 .cache_type = REGCACHE_NONE, 220 .reg_format_endian = REGMAP_ENDIAN_LITTLE, 221 .val_format_endian = REGMAP_ENDIAN_LITTLE, 222 }; 223 224 #ifdef CONFIG_PM_SLEEP 225 static int cpcap_suspend(struct device *dev) 226 { 227 struct spi_device *spi = to_spi_device(dev); 228 229 disable_irq(spi->irq); 230 231 return 0; 232 } 233 234 static int cpcap_resume(struct device *dev) 235 { 236 struct spi_device *spi = to_spi_device(dev); 237 238 enable_irq(spi->irq); 239 240 return 0; 241 } 242 #endif 243 244 static SIMPLE_DEV_PM_OPS(cpcap_pm, cpcap_suspend, cpcap_resume); 245 246 static const struct mfd_cell cpcap_mfd_devices[] = { 247 { 248 .name = "cpcap_adc", 249 .of_compatible = "motorola,mapphone-cpcap-adc", 250 }, { 251 .name = "cpcap_battery", 252 .of_compatible = "motorola,cpcap-battery", 253 }, { 254 .name = "cpcap-charger", 255 .of_compatible = "motorola,mapphone-cpcap-charger", 256 }, { 257 .name = "cpcap-regulator", 258 .of_compatible = "motorola,mapphone-cpcap-regulator", 259 }, { 260 .name = "cpcap-rtc", 261 .of_compatible = "motorola,cpcap-rtc", 262 }, { 263 .name = "cpcap-pwrbutton", 264 .of_compatible = "motorola,cpcap-pwrbutton", 265 }, { 266 .name = "cpcap-usb-phy", 267 .of_compatible = "motorola,mapphone-cpcap-usb-phy", 268 }, { 269 .name = "cpcap-led", 270 .id = 0, 271 .of_compatible = "motorola,cpcap-led-red", 272 }, { 273 .name = "cpcap-led", 274 .id = 1, 275 .of_compatible = "motorola,cpcap-led-green", 276 }, { 277 .name = "cpcap-led", 278 .id = 2, 279 .of_compatible = "motorola,cpcap-led-blue", 280 }, { 281 .name = "cpcap-led", 282 .id = 3, 283 .of_compatible = "motorola,cpcap-led-adl", 284 }, { 285 .name = "cpcap-led", 286 .id = 4, 287 .of_compatible = "motorola,cpcap-led-cp", 288 }, { 289 .name = "cpcap-codec", 290 } 291 }; 292 293 static int cpcap_probe(struct spi_device *spi) 294 { 295 const struct of_device_id *match; 296 struct cpcap_ddata *cpcap; 297 int ret; 298 299 match = of_match_device(of_match_ptr(cpcap_of_match), &spi->dev); 300 if (!match) 301 return -ENODEV; 302 303 cpcap = devm_kzalloc(&spi->dev, sizeof(*cpcap), GFP_KERNEL); 304 if (!cpcap) 305 return -ENOMEM; 306 307 cpcap->spi = spi; 308 spi_set_drvdata(spi, cpcap); 309 310 spi->bits_per_word = 16; 311 spi->mode = SPI_MODE_0 | SPI_CS_HIGH; 312 313 ret = spi_setup(spi); 314 if (ret) 315 return ret; 316 317 cpcap->regmap_conf = &cpcap_regmap_config; 318 cpcap->regmap = devm_regmap_init_spi(spi, &cpcap_regmap_config); 319 if (IS_ERR(cpcap->regmap)) { 320 ret = PTR_ERR(cpcap->regmap); 321 dev_err(&cpcap->spi->dev, "Failed to initialize regmap: %d\n", 322 ret); 323 324 return ret; 325 } 326 327 ret = cpcap_check_revision(cpcap); 328 if (ret) { 329 dev_err(&cpcap->spi->dev, "Failed to detect CPCAP: %i\n", ret); 330 return ret; 331 } 332 333 ret = cpcap_init_irq(cpcap); 334 if (ret) 335 return ret; 336 337 /* Parent SPI controller uses DMA, CPCAP and child devices do not */ 338 spi->dev.coherent_dma_mask = 0; 339 spi->dev.dma_mask = &spi->dev.coherent_dma_mask; 340 341 return devm_mfd_add_devices(&spi->dev, 0, cpcap_mfd_devices, 342 ARRAY_SIZE(cpcap_mfd_devices), NULL, 0, NULL); 343 } 344 345 static struct spi_driver cpcap_driver = { 346 .driver = { 347 .name = "cpcap-core", 348 .of_match_table = cpcap_of_match, 349 .pm = &cpcap_pm, 350 }, 351 .probe = cpcap_probe, 352 .id_table = cpcap_spi_ids, 353 }; 354 module_spi_driver(cpcap_driver); 355 356 MODULE_ALIAS("platform:cpcap"); 357 MODULE_DESCRIPTION("CPCAP driver"); 358 MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>"); 359 MODULE_LICENSE("GPL v2"); 360