Blame view
drivers/mfd/ab3100-core.c
20.2 KB
af873fcec treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-only |
14fa56917 mfd: add U300 AB3... |
2 |
/* |
2071db484 mfd: Use AB3100 M... |
3 |
* Copyright (C) 2007-2010 ST-Ericsson |
14fa56917 mfd: add U300 AB3... |
4 5 6 7 8 9 10 11 12 |
* Low-level core for exclusive access to the AB3100 IC on the I2C bus * and some basic chip-configuration. * Author: Linus Walleij <linus.walleij@stericsson.com> */ #include <linux/i2c.h> #include <linux/mutex.h> #include <linux/list.h> #include <linux/notifier.h> |
5a0e3ad6a include cleanup: ... |
13 |
#include <linux/slab.h> |
14fa56917 mfd: add U300 AB3... |
14 |
#include <linux/err.h> |
4be85fc4f mfd: ab3100-core:... |
15 |
#include <linux/init.h> |
14fa56917 mfd: add U300 AB3... |
16 17 18 |
#include <linux/platform_device.h> #include <linux/device.h> #include <linux/interrupt.h> |
2071db484 mfd: Use AB3100 M... |
19 |
#include <linux/random.h> |
14fa56917 mfd: add U300 AB3... |
20 21 22 |
#include <linux/debugfs.h> #include <linux/seq_file.h> #include <linux/uaccess.h> |
8c96aefbe mfd: Switch AB310... |
23 |
#include <linux/mfd/core.h> |
0fd0013cd mfd: ab3100: Spli... |
24 |
#include <linux/mfd/ab3100.h> |
812f9e9d4 mfd: Renamed ab31... |
25 |
#include <linux/mfd/abx500.h> |
14fa56917 mfd: add U300 AB3... |
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
/* These are the only registers inside AB3100 used in this main file */ /* Interrupt event registers */ #define AB3100_EVENTA1 0x21 #define AB3100_EVENTA2 0x22 #define AB3100_EVENTA3 0x23 /* AB3100 DAC converter registers */ #define AB3100_DIS 0x00 #define AB3100_D0C 0x01 #define AB3100_D1C 0x02 #define AB3100_D2C 0x03 #define AB3100_D3C 0x04 /* Chip ID register */ #define AB3100_CID 0x20 /* AB3100 interrupt registers */ #define AB3100_IMRA1 0x24 #define AB3100_IMRA2 0x25 #define AB3100_IMRA3 0x26 #define AB3100_IMRB1 0x2B #define AB3100_IMRB2 0x2C #define AB3100_IMRB3 0x2D /* System Power Monitoring and control registers */ #define AB3100_MCA 0x2E #define AB3100_MCB 0x2F /* SIM power up */ #define AB3100_SUP 0x50 /* * I2C communication * * The AB3100 is usually assigned address 0x48 (7-bit) * The chip is defined in the platform i2c_board_data section. */ |
fa661258a mfd: AB3100 regis... |
65 |
static int ab3100_get_chip_id(struct device *dev) |
14fa56917 mfd: add U300 AB3... |
66 |
{ |
fa661258a mfd: AB3100 regis... |
67 68 69 |
struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); return (int)ab3100->chip_id; |
14fa56917 mfd: add U300 AB3... |
70 |
} |
14fa56917 mfd: add U300 AB3... |
71 |
|
fa661258a mfd: AB3100 regis... |
72 73 |
static int ab3100_set_register_interruptible(struct ab3100 *ab3100, u8 reg, u8 regval) |
14fa56917 mfd: add U300 AB3... |
74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 |
{ u8 regandval[2] = {reg, regval}; int err; err = mutex_lock_interruptible(&ab3100->access_mutex); if (err) return err; /* * A two-byte write message with the first byte containing the register * number and the second byte containing the value to be written * effectively sets a register in the AB3100. */ err = i2c_master_send(ab3100->i2c_client, regandval, 2); if (err < 0) { dev_err(ab3100->dev, "write error (write register): %d ", err); } else if (err != 2) { dev_err(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
95 96 97 98 |
"write error (write register) " " %d bytes transferred (expected 2) ", |
14fa56917 mfd: add U300 AB3... |
99 100 101 102 103 104 105 |
err); err = -EIO; } else { /* All is well */ err = 0; } mutex_unlock(&ab3100->access_mutex); |
7cdc2b98c mfd: AB3100 propa... |
106 |
return err; |
14fa56917 mfd: add U300 AB3... |
107 |
} |
956f25a67 mfd: AB3100 acces... |
108 |
|
fa661258a mfd: AB3100 regis... |
109 110 111 112 113 114 115 |
static int set_register_interruptible(struct device *dev, u8 bank, u8 reg, u8 value) { struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); return ab3100_set_register_interruptible(ab3100, reg, value); } |
14fa56917 mfd: add U300 AB3... |
116 117 118 119 120 121 122 123 |
/* * The test registers exist at an I2C bus address up one * from the ordinary base. They are not supposed to be used * in production code, but sometimes you have to do that * anyway. It's currently only used from this file so declare * it static and do not export. */ |
956f25a67 mfd: AB3100 acces... |
124 |
static int ab3100_set_test_register_interruptible(struct ab3100 *ab3100, |
14fa56917 mfd: add U300 AB3... |
125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 |
u8 reg, u8 regval) { u8 regandval[2] = {reg, regval}; int err; err = mutex_lock_interruptible(&ab3100->access_mutex); if (err) return err; err = i2c_master_send(ab3100->testreg_client, regandval, 2); if (err < 0) { dev_err(ab3100->dev, "write error (write test register): %d ", err); } else if (err != 2) { dev_err(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
142 143 144 145 |
"write error (write test register) " " %d bytes transferred (expected 2) ", |
14fa56917 mfd: add U300 AB3... |
146 147 148 149 150 151 152 153 154 155 |
err); err = -EIO; } else { /* All is well */ err = 0; } mutex_unlock(&ab3100->access_mutex); return err; } |
fa661258a mfd: AB3100 regis... |
156 |
static int ab3100_get_register_interruptible(struct ab3100 *ab3100, |
8c96aefbe mfd: Switch AB310... |
157 |
u8 reg, u8 *regval) |
14fa56917 mfd: add U300 AB3... |
158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
{ int err; err = mutex_lock_interruptible(&ab3100->access_mutex); if (err) return err; /* * AB3100 require an I2C "stop" command between each message, else * it will not work. The only way of achieveing this with the * message transport layer is to send the read and write messages * separately. */ err = i2c_master_send(ab3100->i2c_client, ®, 1); if (err < 0) { dev_err(ab3100->dev, "write error (send register address): %d ", err); goto get_reg_out_unlock; } else if (err != 1) { dev_err(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
180 181 182 183 |
"write error (send register address) " " %d bytes transferred (expected 1) ", |
14fa56917 mfd: add U300 AB3... |
184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 |
err); err = -EIO; goto get_reg_out_unlock; } else { /* All is well */ err = 0; } err = i2c_master_recv(ab3100->i2c_client, regval, 1); if (err < 0) { dev_err(ab3100->dev, "write error (read register): %d ", err); goto get_reg_out_unlock; } else if (err != 1) { dev_err(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
201 202 203 204 |
"write error (read register) " " %d bytes transferred (expected 1) ", |
14fa56917 mfd: add U300 AB3... |
205 206 207 208 209 210 211 212 213 214 215 216 |
err); err = -EIO; goto get_reg_out_unlock; } else { /* All is well */ err = 0; } get_reg_out_unlock: mutex_unlock(&ab3100->access_mutex); return err; } |
956f25a67 mfd: AB3100 acces... |
217 |
|
fa661258a mfd: AB3100 regis... |
218 |
static int get_register_interruptible(struct device *dev, u8 bank, u8 reg, |
8c96aefbe mfd: Switch AB310... |
219 |
u8 *value) |
fa661258a mfd: AB3100 regis... |
220 221 222 223 224 |
{ struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); return ab3100_get_register_interruptible(ab3100, reg, value); } |
14fa56917 mfd: add U300 AB3... |
225 |
|
fa661258a mfd: AB3100 regis... |
226 |
static int ab3100_get_register_page_interruptible(struct ab3100 *ab3100, |
14fa56917 mfd: add U300 AB3... |
227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 |
u8 first_reg, u8 *regvals, u8 numregs) { int err; if (ab3100->chip_id == 0xa0 || ab3100->chip_id == 0xa1) /* These don't support paged reads */ return -EIO; err = mutex_lock_interruptible(&ab3100->access_mutex); if (err) return err; /* * Paged read also require an I2C "stop" command. */ err = i2c_master_send(ab3100->i2c_client, &first_reg, 1); if (err < 0) { dev_err(ab3100->dev, "write error (send first register address): %d ", err); goto get_reg_page_out_unlock; } else if (err != 1) { dev_err(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
252 253 254 255 |
"write error (send first register address) " " %d bytes transferred (expected 1) ", |
14fa56917 mfd: add U300 AB3... |
256 257 258 259 260 261 262 263 264 265 266 267 268 269 |
err); err = -EIO; goto get_reg_page_out_unlock; } err = i2c_master_recv(ab3100->i2c_client, regvals, numregs); if (err < 0) { dev_err(ab3100->dev, "write error (read register page): %d ", err); goto get_reg_page_out_unlock; } else if (err != numregs) { dev_err(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
270 271 272 273 |
"write error (read register page) " " %d bytes transferred (expected %d) ", |
14fa56917 mfd: add U300 AB3... |
274 275 276 277 278 279 280 281 282 283 284 285 |
err, numregs); err = -EIO; goto get_reg_page_out_unlock; } /* All is well */ err = 0; get_reg_page_out_unlock: mutex_unlock(&ab3100->access_mutex); return err; } |
14fa56917 mfd: add U300 AB3... |
286 |
|
fa661258a mfd: AB3100 regis... |
287 288 289 290 291 292 293 294 |
static int get_register_page_interruptible(struct device *dev, u8 bank, u8 first_reg, u8 *regvals, u8 numregs) { struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); return ab3100_get_register_page_interruptible(ab3100, first_reg, regvals, numregs); } |
956f25a67 mfd: AB3100 acces... |
295 |
|
fa661258a mfd: AB3100 regis... |
296 |
static int ab3100_mask_and_set_register_interruptible(struct ab3100 *ab3100, |
14fa56917 mfd: add U300 AB3... |
297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 |
u8 reg, u8 andmask, u8 ormask) { u8 regandval[2] = {reg, 0}; int err; err = mutex_lock_interruptible(&ab3100->access_mutex); if (err) return err; /* First read out the target register */ err = i2c_master_send(ab3100->i2c_client, ®, 1); if (err < 0) { dev_err(ab3100->dev, "write error (maskset send address): %d ", err); goto get_maskset_unlock; } else if (err != 1) { dev_err(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
316 317 318 319 |
"write error (maskset send address) " " %d bytes transferred (expected 1) ", |
14fa56917 mfd: add U300 AB3... |
320 321 322 323 324 325 326 327 328 329 330 331 332 333 |
err); err = -EIO; goto get_maskset_unlock; } err = i2c_master_recv(ab3100->i2c_client, ®andval[1], 1); if (err < 0) { dev_err(ab3100->dev, "write error (maskset read register): %d ", err); goto get_maskset_unlock; } else if (err != 1) { dev_err(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
334 335 336 337 |
"write error (maskset read register) " " %d bytes transferred (expected 1) ", |
14fa56917 mfd: add U300 AB3... |
338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 |
err); err = -EIO; goto get_maskset_unlock; } /* Modify the register */ regandval[1] &= andmask; regandval[1] |= ormask; /* Write the register */ err = i2c_master_send(ab3100->i2c_client, regandval, 2); if (err < 0) { dev_err(ab3100->dev, "write error (write register): %d ", err); goto get_maskset_unlock; } else if (err != 2) { dev_err(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
357 358 359 360 |
"write error (write register) " " %d bytes transferred (expected 2) ", |
14fa56917 mfd: add U300 AB3... |
361 362 363 364 365 366 367 368 369 370 371 372 |
err); err = -EIO; goto get_maskset_unlock; } /* All is well */ err = 0; get_maskset_unlock: mutex_unlock(&ab3100->access_mutex); return err; } |
956f25a67 mfd: AB3100 acces... |
373 |
|
fa661258a mfd: AB3100 regis... |
374 375 376 377 378 379 380 381 |
static int mask_and_set_register_interruptible(struct device *dev, u8 bank, u8 reg, u8 bitmask, u8 bitvalues) { struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); return ab3100_mask_and_set_register_interruptible(ab3100, reg, bitmask, (bitmask & bitvalues)); } |
14fa56917 mfd: add U300 AB3... |
382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 |
/* * Register a simple callback for handling any AB3100 events. */ int ab3100_event_register(struct ab3100 *ab3100, struct notifier_block *nb) { return blocking_notifier_chain_register(&ab3100->event_subscribers, nb); } EXPORT_SYMBOL(ab3100_event_register); /* * Remove a previously registered callback. */ int ab3100_event_unregister(struct ab3100 *ab3100, struct notifier_block *nb) { |
cd63a8943 mfd: ab3100-core:... |
400 |
return blocking_notifier_chain_unregister(&ab3100->event_subscribers, |
14fa56917 mfd: add U300 AB3... |
401 402 403 |
nb); } EXPORT_SYMBOL(ab3100_event_unregister); |
fa661258a mfd: AB3100 regis... |
404 405 |
static int ab3100_event_registers_startup_state_get(struct device *dev, u8 *event) |
14fa56917 mfd: add U300 AB3... |
406 |
{ |
fa661258a mfd: AB3100 regis... |
407 |
struct ab3100 *ab3100 = dev_get_drvdata(dev->parent); |
15544cab2 mfd: ab3100-core.... |
408 |
|
14fa56917 mfd: add U300 AB3... |
409 410 |
if (!ab3100->startup_events_read) return -EAGAIN; /* Try again later */ |
fa661258a mfd: AB3100 regis... |
411 |
memcpy(event, ab3100->startup_events, 3); |
15544cab2 mfd: ab3100-core.... |
412 |
|
14fa56917 mfd: add U300 AB3... |
413 414 |
return 0; } |
fa661258a mfd: AB3100 regis... |
415 416 417 418 419 420 421 422 423 424 425 426 |
static struct abx500_ops ab3100_ops = { .get_chip_id = ab3100_get_chip_id, .set_register = set_register_interruptible, .get_register = get_register_interruptible, .get_register_page = get_register_page_interruptible, .set_register_page = NULL, .mask_and_set_register = mask_and_set_register_interruptible, .event_registers_startup_state_get = ab3100_event_registers_startup_state_get, .startup_irq_enabled = NULL, }; |
14fa56917 mfd: add U300 AB3... |
427 |
|
0df883df8 mfd: Convert AB31... |
428 429 430 431 432 |
/* * This is a threaded interrupt handler so we can make some * I2C calls etc. */ static irqreturn_t ab3100_irq_handler(int irq, void *data) |
14fa56917 mfd: add U300 AB3... |
433 |
{ |
0df883df8 mfd: Convert AB31... |
434 |
struct ab3100 *ab3100 = data; |
14fa56917 mfd: add U300 AB3... |
435 436 437 |
u8 event_regs[3]; u32 fatevent; int err; |
956f25a67 mfd: AB3100 acces... |
438 |
err = ab3100_get_register_page_interruptible(ab3100, AB3100_EVENTA1, |
14fa56917 mfd: add U300 AB3... |
439 440 |
event_regs, 3); if (err) |
0df883df8 mfd: Convert AB31... |
441 |
goto err_event; |
14fa56917 mfd: add U300 AB3... |
442 443 444 445 446 447 |
fatevent = (event_regs[0] << 16) | (event_regs[1] << 8) | event_regs[2]; if (!ab3100->startup_events_read) { |
fa661258a mfd: AB3100 regis... |
448 449 450 |
ab3100->startup_events[0] = event_regs[0]; ab3100->startup_events[1] = event_regs[1]; ab3100->startup_events[2] = event_regs[2]; |
14fa56917 mfd: add U300 AB3... |
451 452 453 454 455 456 457 458 459 460 461 462 463 464 |
ab3100->startup_events_read = true; } /* * The notified parties will have to mask out the events * they're interested in and react to them. They will be * notified on all events, then they use the fatevent value * to determine if they're interested. */ blocking_notifier_call_chain(&ab3100->event_subscribers, fatevent, NULL); dev_dbg(ab3100->dev, "IRQ Event: 0x%08x ", fatevent); |
0df883df8 mfd: Convert AB31... |
465 |
return IRQ_HANDLED; |
14fa56917 mfd: add U300 AB3... |
466 |
|
0df883df8 mfd: Convert AB31... |
467 |
err_event: |
14fa56917 mfd: add U300 AB3... |
468 |
dev_dbg(ab3100->dev, |
0df883df8 mfd: Convert AB31... |
469 470 |
"error reading event status "); |
14fa56917 mfd: add U300 AB3... |
471 472 473 474 475 476 477 478 479 480 481 482 |
return IRQ_HANDLED; } #ifdef CONFIG_DEBUG_FS /* * Some debugfs entries only exposed if we're using debug */ static int ab3100_registers_print(struct seq_file *s, void *p) { struct ab3100 *ab3100 = s->private; u8 value; u8 reg; |
cd63a8943 mfd: ab3100-core:... |
483 484 |
seq_puts(s, "AB3100 registers: "); |
14fa56917 mfd: add U300 AB3... |
485 486 |
for (reg = 0; reg < 0xff; reg++) { |
956f25a67 mfd: AB3100 acces... |
487 |
ab3100_get_register_interruptible(ab3100, reg, &value); |
14fa56917 mfd: add U300 AB3... |
488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 |
seq_printf(s, "[0x%x]: 0x%x ", reg, value); } return 0; } static int ab3100_registers_open(struct inode *inode, struct file *file) { return single_open(file, ab3100_registers_print, inode->i_private); } static const struct file_operations ab3100_registers_fops = { .open = ab3100_registers_open, .read = seq_read, .llseek = seq_lseek, .release = single_release, .owner = THIS_MODULE, }; struct ab3100_get_set_reg_priv { struct ab3100 *ab3100; bool mode; }; |
dfc3aa722 mfd: fix ab3100 w... |
511 512 513 |
static ssize_t ab3100_get_set_reg(struct file *file, const char __user *user_buf, size_t count, loff_t *ppos) |
14fa56917 mfd: add U300 AB3... |
514 515 516 517 |
{ struct ab3100_get_set_reg_priv *priv = file->private_data; struct ab3100 *ab3100 = priv->ab3100; char buf[32]; |
dfc3aa722 mfd: fix ab3100 w... |
518 |
ssize_t buf_size; |
14fa56917 mfd: add U300 AB3... |
519 |
int regp; |
8420a2413 mfd: Replace stri... |
520 |
u8 user_reg; |
14fa56917 mfd: add U300 AB3... |
521 522 523 524 |
int err; int i = 0; /* Get userspace string and assure termination */ |
54daa5d47 mfd: ab3100-core:... |
525 |
buf_size = min((ssize_t)count, (ssize_t)(sizeof(buf)-1)); |
14fa56917 mfd: add U300 AB3... |
526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 |
if (copy_from_user(buf, user_buf, buf_size)) return -EFAULT; buf[buf_size] = 0; /* * The idea is here to parse a string which is either * "0xnn" for reading a register, or "0xaa 0xbb" for * writing 0xbb to the register 0xaa. First move past * whitespace and then begin to parse the register. */ while ((i < buf_size) && (buf[i] == ' ')) i++; regp = i; /* * Advance pointer to end of string then terminate * the register string. This is needed to satisfy |
8420a2413 mfd: Replace stri... |
543 |
* the kstrtou8() function. |
14fa56917 mfd: add U300 AB3... |
544 545 546 547 |
*/ while ((i < buf_size) && (buf[i] != ' ')) i++; buf[i] = '\0'; |
8420a2413 mfd: Replace stri... |
548 |
err = kstrtou8(&buf[regp], 16, &user_reg); |
14fa56917 mfd: add U300 AB3... |
549 550 |
if (err) return err; |
14fa56917 mfd: add U300 AB3... |
551 552 553 554 |
/* Either we read or we write a register here */ if (!priv->mode) { /* Reading */ |
14fa56917 mfd: add U300 AB3... |
555 |
u8 regvalue; |
8420a2413 mfd: Replace stri... |
556 |
ab3100_get_register_interruptible(ab3100, user_reg, ®value); |
14fa56917 mfd: add U300 AB3... |
557 558 559 560 |
dev_info(ab3100->dev, "debug read AB3100 reg[0x%02x]: 0x%02x ", |
8420a2413 mfd: Replace stri... |
561 |
user_reg, regvalue); |
14fa56917 mfd: add U300 AB3... |
562 563 |
} else { int valp; |
8420a2413 mfd: Replace stri... |
564 |
u8 user_value; |
14fa56917 mfd: add U300 AB3... |
565 566 567 568 569 570 571 572 573 574 575 576 577 578 |
u8 regvalue; /* * Writing, we need some value to write to * the register so keep parsing the string * from userspace. */ i++; while ((i < buf_size) && (buf[i] == ' ')) i++; valp = i; while ((i < buf_size) && (buf[i] != ' ')) i++; buf[i] = '\0'; |
8420a2413 mfd: Replace stri... |
579 |
err = kstrtou8(&buf[valp], 16, &user_value); |
14fa56917 mfd: add U300 AB3... |
580 581 |
if (err) return err; |
14fa56917 mfd: add U300 AB3... |
582 |
|
8420a2413 mfd: Replace stri... |
583 584 |
ab3100_set_register_interruptible(ab3100, user_reg, user_value); ab3100_get_register_interruptible(ab3100, user_reg, ®value); |
14fa56917 mfd: add U300 AB3... |
585 586 |
dev_info(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
587 588 589 590 |
"debug write reg[0x%02x] " " with 0x%02x, after readback: 0x%02x ", |
8420a2413 mfd: Replace stri... |
591 |
user_reg, user_value, regvalue); |
14fa56917 mfd: add U300 AB3... |
592 593 594 595 596 |
} return buf_size; } static const struct file_operations ab3100_get_set_reg_fops = { |
234e34058 simple_open: auto... |
597 |
.open = simple_open, |
14fa56917 mfd: add U300 AB3... |
598 |
.write = ab3100_get_set_reg, |
6038f373a llseek: automatic... |
599 |
.llseek = noop_llseek, |
14fa56917 mfd: add U300 AB3... |
600 |
}; |
14fa56917 mfd: add U300 AB3... |
601 |
static struct ab3100_get_set_reg_priv ab3100_get_priv; |
14fa56917 mfd: add U300 AB3... |
602 |
static struct ab3100_get_set_reg_priv ab3100_set_priv; |
14fa56917 mfd: add U300 AB3... |
603 604 605 |
static void ab3100_setup_debugfs(struct ab3100 *ab3100) { |
efecc3b53 mfd: ab3100: No n... |
606 |
struct dentry *ab3100_dir; |
14fa56917 mfd: add U300 AB3... |
607 608 |
ab3100_dir = debugfs_create_dir("ab3100", NULL); |
efecc3b53 mfd: ab3100: No n... |
609 610 611 |
debugfs_create_file("registers", S_IRUGO, ab3100_dir, ab3100, &ab3100_registers_fops); |
14fa56917 mfd: add U300 AB3... |
612 613 614 |
ab3100_get_priv.ab3100 = ab3100; ab3100_get_priv.mode = false; |
efecc3b53 mfd: ab3100: No n... |
615 616 |
debugfs_create_file("get_reg", S_IWUSR, ab3100_dir, &ab3100_get_priv, &ab3100_get_set_reg_fops); |
14fa56917 mfd: add U300 AB3... |
617 618 619 |
ab3100_set_priv.ab3100 = ab3100; ab3100_set_priv.mode = true; |
efecc3b53 mfd: ab3100: No n... |
620 621 |
debugfs_create_file("set_reg", S_IWUSR, ab3100_dir, &ab3100_set_priv, &ab3100_get_set_reg_fops); |
14fa56917 mfd: add U300 AB3... |
622 |
} |
14fa56917 mfd: add U300 AB3... |
623 624 625 626 |
#else static inline void ab3100_setup_debugfs(struct ab3100 *ab3100) { } |
14fa56917 mfd: add U300 AB3... |
627 628 629 630 631 632 633 634 635 636 637 638 |
#endif /* * Basic set-up, datastructure creation/destruction and I2C interface. * This sets up a default config in the AB3100 chip so that it * will work as expected. */ struct ab3100_init_setting { u8 abreg; u8 setting; }; |
a73e5df16 mfd: remove use o... |
639 |
static const struct ab3100_init_setting ab3100_init_settings[] = { |
14fa56917 mfd: add U300 AB3... |
640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 |
{ .abreg = AB3100_MCA, .setting = 0x01 }, { .abreg = AB3100_MCB, .setting = 0x30 }, { .abreg = AB3100_IMRA1, .setting = 0x00 }, { .abreg = AB3100_IMRA2, .setting = 0xFF }, { .abreg = AB3100_IMRA3, .setting = 0x01 }, { .abreg = AB3100_IMRB1, |
ce290b0e8 mfd: AB3100 alter... |
657 |
.setting = 0xBF |
14fa56917 mfd: add U300 AB3... |
658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 |
}, { .abreg = AB3100_IMRB2, .setting = 0xFF }, { .abreg = AB3100_IMRB3, .setting = 0xFF }, { .abreg = AB3100_SUP, .setting = 0x00 }, { .abreg = AB3100_DIS, .setting = 0xF0 }, { .abreg = AB3100_D0C, .setting = 0x00 }, { .abreg = AB3100_D1C, .setting = 0x00 }, { .abreg = AB3100_D2C, .setting = 0x00 }, { .abreg = AB3100_D3C, .setting = 0x00 }, }; |
f791be492 mfd: remove use o... |
684 |
static int ab3100_setup(struct ab3100 *ab3100) |
14fa56917 mfd: add U300 AB3... |
685 686 687 688 689 |
{ int err = 0; int i; for (i = 0; i < ARRAY_SIZE(ab3100_init_settings); i++) { |
956f25a67 mfd: AB3100 acces... |
690 |
err = ab3100_set_register_interruptible(ab3100, |
14fa56917 mfd: add U300 AB3... |
691 692 693 694 695 696 697 698 |
ab3100_init_settings[i].abreg, ab3100_init_settings[i].setting); if (err) goto exit_no_setup; } /* * Special trick to make the AB3100 use the 32kHz clock (RTC) |
956f25a67 mfd: AB3100 acces... |
699 |
* bit 3 in test register 0x02 is a special, undocumented test |
14fa56917 mfd: add U300 AB3... |
700 701 702 703 |
* register bit that only exist in AB3100 P1E */ if (ab3100->chip_id == 0xc4) { dev_warn(ab3100->dev, |
cd63a8943 mfd: ab3100-core:... |
704 705 |
"AB3100 P1E variant detected forcing chip to 32KHz "); |
fa661258a mfd: AB3100 regis... |
706 707 |
err = ab3100_set_test_register_interruptible(ab3100, 0x02, 0x08); |
14fa56917 mfd: add U300 AB3... |
708 709 710 711 712 |
} exit_no_setup: return err; } |
8c96aefbe mfd: Switch AB310... |
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 |
/* The subdevices of the AB3100 */ static struct mfd_cell ab3100_devs[] = { { .name = "ab3100-dac", .id = -1, }, { .name = "ab3100-leds", .id = -1, }, { .name = "ab3100-power", .id = -1, }, { .name = "ab3100-regulators", |
8735bc2fe regulator: ab3100... |
729 |
.of_compatible = "stericsson,ab3100-regulators", |
8c96aefbe mfd: Switch AB310... |
730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 |
.id = -1, }, { .name = "ab3100-sim", .id = -1, }, { .name = "ab3100-uart", .id = -1, }, { .name = "ab3100-rtc", .id = -1, }, { .name = "ab3100-charger", .id = -1, }, { .name = "ab3100-boost", .id = -1, }, { .name = "ab3100-adc", .id = -1, }, { .name = "ab3100-fuelgauge", .id = -1, }, { .name = "ab3100-vibrator", .id = -1, }, { .name = "ab3100-otp", .id = -1, }, { .name = "ab3100-codec", .id = -1, }, |
14fa56917 mfd: add U300 AB3... |
772 773 774 775 776 777 |
}; struct ab_family_id { u8 id; char *name; }; |
a73e5df16 mfd: remove use o... |
778 |
static const struct ab_family_id ids[] = { |
14fa56917 mfd: add U300 AB3... |
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 |
/* AB3100 */ { .id = 0xc0, .name = "P1A" }, { .id = 0xc1, .name = "P1B" }, { .id = 0xc2, .name = "P1C" }, { .id = 0xc3, .name = "P1D" }, { .id = 0xc4, .name = "P1E" }, { .id = 0xc5, .name = "P1F/R1A" }, { .id = 0xc6, .name = "P1G/R1A" }, { .id = 0xc7, .name = "P2A/R2A" }, { .id = 0xc8, .name = "P2B/R2B" }, /* AB3000 variants, not supported */ { .id = 0xa0 }, { .id = 0xa1 }, { .id = 0xa2 }, { .id = 0xa3 }, { .id = 0xa4 }, { .id = 0xa5 }, { .id = 0xa6 }, { .id = 0xa7 }, /* Terminator */ { .id = 0x00, }, }; |
f791be492 mfd: remove use o... |
831 |
static int ab3100_probe(struct i2c_client *client, |
2524468ee mfd: Move AB3100 ... |
832 |
const struct i2c_device_id *id) |
14fa56917 mfd: add U300 AB3... |
833 834 |
{ struct ab3100 *ab3100; |
d619bc143 regulator: AB3100... |
835 |
struct ab3100_platform_data *ab3100_plf_data = |
334a41ce9 mfd: Use dev_get_... |
836 |
dev_get_platdata(&client->dev); |
14fa56917 mfd: add U300 AB3... |
837 838 |
int err; int i; |
7f0f07ce2 mfd: Use devm all... |
839 |
ab3100 = devm_kzalloc(&client->dev, sizeof(struct ab3100), GFP_KERNEL); |
15544cab2 mfd: ab3100-core.... |
840 |
if (!ab3100) |
14fa56917 mfd: add U300 AB3... |
841 |
return -ENOMEM; |
14fa56917 mfd: add U300 AB3... |
842 843 844 845 846 847 848 849 850 851 852 |
/* Initialize data structure */ mutex_init(&ab3100->access_mutex); BLOCKING_INIT_NOTIFIER_HEAD(&ab3100->event_subscribers); ab3100->i2c_client = client; ab3100->dev = &ab3100->i2c_client->dev; i2c_set_clientdata(client, ab3100); /* Read chip ID register */ |
956f25a67 mfd: AB3100 acces... |
853 854 |
err = ab3100_get_register_interruptible(ab3100, AB3100_CID, &ab3100->chip_id); |
14fa56917 mfd: add U300 AB3... |
855 856 |
if (err) { dev_err(&client->dev, |
cd63a8943 mfd: ab3100-core:... |
857 858 |
"failed to communicate with AB3100 chip "); |
14fa56917 mfd: add U300 AB3... |
859 860 861 862 863 |
goto exit_no_detect; } for (i = 0; ids[i].id != 0x0; i++) { if (ids[i].id == ab3100->chip_id) { |
15544cab2 mfd: ab3100-core.... |
864 |
if (ids[i].name) |
14fa56917 mfd: add U300 AB3... |
865 |
break; |
15544cab2 mfd: ab3100-core.... |
866 867 868 869 |
dev_err(&client->dev, "AB3000 is not supported "); goto exit_no_detect; |
14fa56917 mfd: add U300 AB3... |
870 871 |
} } |
15544cab2 mfd: ab3100-core.... |
872 873 |
snprintf(&ab3100->chip_name[0], sizeof(ab3100->chip_name) - 1, "AB3100 %s", ids[i].name); |
14fa56917 mfd: add U300 AB3... |
874 875 876 877 |
if (ids[i].id == 0x0) { dev_err(&client->dev, "unknown analog baseband chip id: 0x%x ", ab3100->chip_id); |
cd63a8943 mfd: ab3100-core:... |
878 879 880 |
dev_err(&client->dev, "accepting it anyway. Please update the driver. "); |
14fa56917 mfd: add U300 AB3... |
881 882 883 884 885 886 887 888 |
goto exit_no_detect; } dev_info(&client->dev, "Detected chip: %s ", &ab3100->chip_name[0]); /* Attach a second dummy i2c_client to the test register address */ |
f5d5d193c mfd: ab3100-core:... |
889 |
ab3100->testreg_client = i2c_new_dummy_device(client->adapter, |
7f0f07ce2 mfd: Use devm all... |
890 |
client->addr + 1); |
f5d5d193c mfd: ab3100-core:... |
891 892 |
if (IS_ERR(ab3100->testreg_client)) { err = PTR_ERR(ab3100->testreg_client); |
14fa56917 mfd: add U300 AB3... |
893 894 |
goto exit_no_testreg_client; } |
14fa56917 mfd: add U300 AB3... |
895 896 897 |
err = ab3100_setup(ab3100); if (err) goto exit_no_setup; |
7f0f07ce2 mfd: Use devm all... |
898 899 900 |
err = devm_request_threaded_irq(&client->dev, client->irq, NULL, ab3100_irq_handler, IRQF_ONESHOT, "ab3100-core", ab3100); |
14fa56917 mfd: add U300 AB3... |
901 902 |
if (err) goto exit_no_irq; |
fa661258a mfd: AB3100 regis... |
903 904 905 |
err = abx500_register_ops(&client->dev, &ab3100_ops); if (err) goto exit_no_ops; |
8c96aefbe mfd: Switch AB310... |
906 |
/* Set up and register the platform devices. */ |
a771e36e1 mfd: Use mfd cell... |
907 908 909 910 |
for (i = 0; i < ARRAY_SIZE(ab3100_devs); i++) { ab3100_devs[i].platform_data = ab3100_plf_data; ab3100_devs[i].pdata_size = sizeof(struct ab3100_platform_data); } |
14fa56917 mfd: add U300 AB3... |
911 |
|
8c96aefbe mfd: Switch AB310... |
912 |
err = mfd_add_devices(&client->dev, 0, ab3100_devs, |
55692af5e mfd: core: Push i... |
913 |
ARRAY_SIZE(ab3100_devs), NULL, 0, NULL); |
14fa56917 mfd: add U300 AB3... |
914 915 916 917 |
ab3100_setup_debugfs(ab3100); return 0; |
fa661258a mfd: AB3100 regis... |
918 |
exit_no_ops: |
14fa56917 mfd: add U300 AB3... |
919 920 921 922 923 |
exit_no_irq: exit_no_setup: i2c_unregister_device(ab3100->testreg_client); exit_no_testreg_client: exit_no_detect: |
14fa56917 mfd: add U300 AB3... |
924 925 |
return err; } |
14fa56917 mfd: add U300 AB3... |
926 |
static const struct i2c_device_id ab3100_id[] = { |
dcffa1255 mfd: AB3100 drop ... |
927 |
{ "ab3100", 0 }, |
14fa56917 mfd: add U300 AB3... |
928 929 |
{ } }; |
14fa56917 mfd: add U300 AB3... |
930 931 932 |
static struct i2c_driver ab3100_driver = { .driver = { |
4be85fc4f mfd: ab3100-core:... |
933 934 |
.name = "ab3100", .suppress_bind_attrs = true, |
14fa56917 mfd: add U300 AB3... |
935 936 937 |
}, .id_table = ab3100_id, .probe = ab3100_probe, |
14fa56917 mfd: add U300 AB3... |
938 939 940 941 942 943 |
}; static int __init ab3100_i2c_init(void) { return i2c_add_driver(&ab3100_driver); } |
14fa56917 mfd: add U300 AB3... |
944 |
subsys_initcall(ab3100_i2c_init); |