Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

spmi: Linux driver framework for SPMI

System Power Management Interface (SPMI) is a specification
developed by the MIPI (Mobile Industry Process Interface) Alliance
optimized for the real time control of Power Management ICs (PMIC).

SPMI is a two-wire serial interface that supports up to 4 master
devices and up to 16 logical slaves.

The framework supports message APIs, multiple busses (1 controller
per bus) and multiple clients/slave devices per controller.

Signed-off-by: Kenneth Heitke <kheitke@codeaurora.org>
Signed-off-by: Michael Bohan <mbohan@codeaurora.org>
Signed-off-by: Josh Cartwright <joshc@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Kenneth Heitke and committed by
Greg Kroah-Hartman
5a86bf34 a2a720e1

+842
+2
drivers/Kconfig
··· 52 52 53 53 source "drivers/spi/Kconfig" 54 54 55 + source "drivers/spmi/Kconfig" 56 + 55 57 source "drivers/hsi/Kconfig" 56 58 57 59 source "drivers/pps/Kconfig"
+1
drivers/Makefile
··· 66 66 obj-$(CONFIG_TARGET_CORE) += target/ 67 67 obj-$(CONFIG_MTD) += mtd/ 68 68 obj-$(CONFIG_SPI) += spi/ 69 + obj-$(CONFIG_SPMI) += spmi/ 69 70 obj-y += hsi/ 70 71 obj-y += net/ 71 72 obj-$(CONFIG_ATM) += atm/
+9
drivers/spmi/Kconfig
··· 1 + # 2 + # SPMI driver configuration 3 + # 4 + menuconfig SPMI 5 + tristate "SPMI support" 6 + help 7 + SPMI (System Power Management Interface) is a two-wire 8 + serial interface between baseband and application processors 9 + and Power Management Integrated Circuits (PMIC).
+4
drivers/spmi/Makefile
··· 1 + # 2 + # Makefile for kernel SPMI framework. 3 + # 4 + obj-$(CONFIG_SPMI) += spmi.o
+609
drivers/spmi/spmi.c
··· 1 + /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 and 5 + * only version 2 as published by the Free Software Foundation. 6 + * 7 + * This program is distributed in the hope that it will be useful, 8 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 + * GNU General Public License for more details. 11 + */ 12 + #include <linux/kernel.h> 13 + #include <linux/errno.h> 14 + #include <linux/idr.h> 15 + #include <linux/slab.h> 16 + #include <linux/module.h> 17 + #include <linux/of.h> 18 + #include <linux/of_device.h> 19 + #include <linux/platform_device.h> 20 + #include <linux/spmi.h> 21 + #include <linux/module.h> 22 + #include <linux/pm_runtime.h> 23 + 24 + #include <dt-bindings/spmi/spmi.h> 25 + 26 + static DEFINE_IDA(ctrl_ida); 27 + 28 + static void spmi_dev_release(struct device *dev) 29 + { 30 + struct spmi_device *sdev = to_spmi_device(dev); 31 + kfree(sdev); 32 + } 33 + 34 + static const struct device_type spmi_dev_type = { 35 + .release = spmi_dev_release, 36 + }; 37 + 38 + static void spmi_ctrl_release(struct device *dev) 39 + { 40 + struct spmi_controller *ctrl = to_spmi_controller(dev); 41 + ida_simple_remove(&ctrl_ida, ctrl->nr); 42 + kfree(ctrl); 43 + } 44 + 45 + static const struct device_type spmi_ctrl_type = { 46 + .release = spmi_ctrl_release, 47 + }; 48 + 49 + #ifdef CONFIG_PM_RUNTIME 50 + static int spmi_runtime_suspend(struct device *dev) 51 + { 52 + struct spmi_device *sdev = to_spmi_device(dev); 53 + int err; 54 + 55 + err = pm_generic_runtime_suspend(dev); 56 + if (err) 57 + return err; 58 + 59 + return spmi_command_sleep(sdev); 60 + } 61 + 62 + static int spmi_runtime_resume(struct device *dev) 63 + { 64 + struct spmi_device *sdev = to_spmi_device(dev); 65 + int err; 66 + 67 + err = spmi_command_wakeup(sdev); 68 + if (err) 69 + return err; 70 + 71 + return pm_generic_runtime_resume(dev); 72 + } 73 + #endif 74 + 75 + static const struct dev_pm_ops spmi_pm_ops = { 76 + SET_RUNTIME_PM_OPS( 77 + spmi_runtime_suspend, 78 + spmi_runtime_resume, 79 + NULL 80 + ) 81 + }; 82 + 83 + static int spmi_device_match(struct device *dev, struct device_driver *drv) 84 + { 85 + if (of_driver_match_device(dev, drv)) 86 + return 1; 87 + 88 + if (drv->name) 89 + return strncmp(dev_name(dev), drv->name, 90 + SPMI_NAME_SIZE) == 0; 91 + 92 + return 0; 93 + } 94 + 95 + /** 96 + * spmi_device_add() - add a device previously constructed via spmi_device_alloc() 97 + * @sdev: spmi_device to be added 98 + */ 99 + int spmi_device_add(struct spmi_device *sdev) 100 + { 101 + struct spmi_controller *ctrl = sdev->ctrl; 102 + int err; 103 + 104 + dev_set_name(&sdev->dev, "%d-%02x", ctrl->nr, sdev->usid); 105 + 106 + err = device_add(&sdev->dev); 107 + if (err < 0) { 108 + dev_err(&sdev->dev, "Can't add %s, status %d\n", 109 + dev_name(&sdev->dev), err); 110 + goto err_device_add; 111 + } 112 + 113 + dev_dbg(&sdev->dev, "device %s registered\n", dev_name(&sdev->dev)); 114 + 115 + err_device_add: 116 + return err; 117 + } 118 + EXPORT_SYMBOL_GPL(spmi_device_add); 119 + 120 + /** 121 + * spmi_device_remove(): remove an SPMI device 122 + * @sdev: spmi_device to be removed 123 + */ 124 + void spmi_device_remove(struct spmi_device *sdev) 125 + { 126 + device_unregister(&sdev->dev); 127 + } 128 + EXPORT_SYMBOL_GPL(spmi_device_remove); 129 + 130 + static inline int 131 + spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid) 132 + { 133 + if (!ctrl || !ctrl->cmd || ctrl->dev.type != &spmi_ctrl_type) 134 + return -EINVAL; 135 + 136 + return ctrl->cmd(ctrl, opcode, sid); 137 + } 138 + 139 + static inline int spmi_read_cmd(struct spmi_controller *ctrl, u8 opcode, 140 + u8 sid, u16 addr, u8 *buf, size_t len) 141 + { 142 + if (!ctrl || !ctrl->read_cmd || ctrl->dev.type != &spmi_ctrl_type) 143 + return -EINVAL; 144 + 145 + return ctrl->read_cmd(ctrl, opcode, sid, addr, buf, len); 146 + } 147 + 148 + static inline int spmi_write_cmd(struct spmi_controller *ctrl, u8 opcode, 149 + u8 sid, u16 addr, const u8 *buf, size_t len) 150 + { 151 + if (!ctrl || !ctrl->write_cmd || ctrl->dev.type != &spmi_ctrl_type) 152 + return -EINVAL; 153 + 154 + return ctrl->write_cmd(ctrl, opcode, sid, addr, buf, len); 155 + } 156 + 157 + /** 158 + * spmi_register_read() - register read 159 + * @sdev: SPMI device. 160 + * @addr: slave register address (5-bit address). 161 + * @buf: buffer to be populated with data from the Slave. 162 + * 163 + * Reads 1 byte of data from a Slave device register. 164 + */ 165 + int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf) 166 + { 167 + /* 5-bit register address */ 168 + if (addr > 0x1F) 169 + return -EINVAL; 170 + 171 + return spmi_read_cmd(sdev->ctrl, SPMI_CMD_READ, sdev->usid, addr, 172 + buf, 1); 173 + } 174 + EXPORT_SYMBOL_GPL(spmi_register_read); 175 + 176 + /** 177 + * spmi_ext_register_read() - extended register read 178 + * @sdev: SPMI device. 179 + * @addr: slave register address (8-bit address). 180 + * @buf: buffer to be populated with data from the Slave. 181 + * @len: the request number of bytes to read (up to 16 bytes). 182 + * 183 + * Reads up to 16 bytes of data from the extended register space on a 184 + * Slave device. 185 + */ 186 + int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf, 187 + size_t len) 188 + { 189 + /* 8-bit register address, up to 16 bytes */ 190 + if (len == 0 || len > 16) 191 + return -EINVAL; 192 + 193 + return spmi_read_cmd(sdev->ctrl, SPMI_CMD_EXT_READ, sdev->usid, addr, 194 + buf, len); 195 + } 196 + EXPORT_SYMBOL_GPL(spmi_ext_register_read); 197 + 198 + /** 199 + * spmi_ext_register_readl() - extended register read long 200 + * @sdev: SPMI device. 201 + * @addr: slave register address (16-bit address). 202 + * @buf: buffer to be populated with data from the Slave. 203 + * @len: the request number of bytes to read (up to 8 bytes). 204 + * 205 + * Reads up to 8 bytes of data from the extended register space on a 206 + * Slave device using 16-bit address. 207 + */ 208 + int spmi_ext_register_readl(struct spmi_device *sdev, u16 addr, u8 *buf, 209 + size_t len) 210 + { 211 + /* 16-bit register address, up to 8 bytes */ 212 + if (len == 0 || len > 8) 213 + return -EINVAL; 214 + 215 + return spmi_read_cmd(sdev->ctrl, SPMI_CMD_EXT_READL, sdev->usid, addr, 216 + buf, len); 217 + } 218 + EXPORT_SYMBOL_GPL(spmi_ext_register_readl); 219 + 220 + /** 221 + * spmi_register_write() - register write 222 + * @sdev: SPMI device 223 + * @addr: slave register address (5-bit address). 224 + * @data: buffer containing the data to be transferred to the Slave. 225 + * 226 + * Writes 1 byte of data to a Slave device register. 227 + */ 228 + int spmi_register_write(struct spmi_device *sdev, u8 addr, u8 data) 229 + { 230 + /* 5-bit register address */ 231 + if (addr > 0x1F) 232 + return -EINVAL; 233 + 234 + return spmi_write_cmd(sdev->ctrl, SPMI_CMD_WRITE, sdev->usid, addr, 235 + &data, 1); 236 + } 237 + EXPORT_SYMBOL_GPL(spmi_register_write); 238 + 239 + /** 240 + * spmi_register_zero_write() - register zero write 241 + * @sdev: SPMI device. 242 + * @data: the data to be written to register 0 (7-bits). 243 + * 244 + * Writes data to register 0 of the Slave device. 245 + */ 246 + int spmi_register_zero_write(struct spmi_device *sdev, u8 data) 247 + { 248 + return spmi_write_cmd(sdev->ctrl, SPMI_CMD_ZERO_WRITE, sdev->usid, 0, 249 + &data, 1); 250 + } 251 + EXPORT_SYMBOL_GPL(spmi_register_zero_write); 252 + 253 + /** 254 + * spmi_ext_register_write() - extended register write 255 + * @sdev: SPMI device. 256 + * @addr: slave register address (8-bit address). 257 + * @buf: buffer containing the data to be transferred to the Slave. 258 + * @len: the request number of bytes to read (up to 16 bytes). 259 + * 260 + * Writes up to 16 bytes of data to the extended register space of a 261 + * Slave device. 262 + */ 263 + int spmi_ext_register_write(struct spmi_device *sdev, u8 addr, const u8 *buf, 264 + size_t len) 265 + { 266 + /* 8-bit register address, up to 16 bytes */ 267 + if (len == 0 || len > 16) 268 + return -EINVAL; 269 + 270 + return spmi_write_cmd(sdev->ctrl, SPMI_CMD_EXT_WRITE, sdev->usid, addr, 271 + buf, len); 272 + } 273 + EXPORT_SYMBOL_GPL(spmi_ext_register_write); 274 + 275 + /** 276 + * spmi_ext_register_writel() - extended register write long 277 + * @sdev: SPMI device. 278 + * @addr: slave register address (16-bit address). 279 + * @buf: buffer containing the data to be transferred to the Slave. 280 + * @len: the request number of bytes to read (up to 8 bytes). 281 + * 282 + * Writes up to 8 bytes of data to the extended register space of a 283 + * Slave device using 16-bit address. 284 + */ 285 + int spmi_ext_register_writel(struct spmi_device *sdev, u16 addr, const u8 *buf, 286 + size_t len) 287 + { 288 + /* 4-bit Slave Identifier, 16-bit register address, up to 8 bytes */ 289 + if (len == 0 || len > 8) 290 + return -EINVAL; 291 + 292 + return spmi_write_cmd(sdev->ctrl, SPMI_CMD_EXT_WRITEL, sdev->usid, 293 + addr, buf, len); 294 + } 295 + EXPORT_SYMBOL_GPL(spmi_ext_register_writel); 296 + 297 + /** 298 + * spmi_command_reset() - sends RESET command to the specified slave 299 + * @sdev: SPMI device. 300 + * 301 + * The Reset command initializes the Slave and forces all registers to 302 + * their reset values. The Slave shall enter the STARTUP state after 303 + * receiving a Reset command. 304 + */ 305 + int spmi_command_reset(struct spmi_device *sdev) 306 + { 307 + return spmi_cmd(sdev->ctrl, SPMI_CMD_RESET, sdev->usid); 308 + } 309 + EXPORT_SYMBOL_GPL(spmi_command_reset); 310 + 311 + /** 312 + * spmi_command_sleep() - sends SLEEP command to the specified SPMI device 313 + * @sdev: SPMI device. 314 + * 315 + * The Sleep command causes the Slave to enter the user defined SLEEP state. 316 + */ 317 + int spmi_command_sleep(struct spmi_device *sdev) 318 + { 319 + return spmi_cmd(sdev->ctrl, SPMI_CMD_SLEEP, sdev->usid); 320 + } 321 + EXPORT_SYMBOL_GPL(spmi_command_sleep); 322 + 323 + /** 324 + * spmi_command_wakeup() - sends WAKEUP command to the specified SPMI device 325 + * @sdev: SPMI device. 326 + * 327 + * The Wakeup command causes the Slave to move from the SLEEP state to 328 + * the ACTIVE state. 329 + */ 330 + int spmi_command_wakeup(struct spmi_device *sdev) 331 + { 332 + return spmi_cmd(sdev->ctrl, SPMI_CMD_WAKEUP, sdev->usid); 333 + } 334 + EXPORT_SYMBOL_GPL(spmi_command_wakeup); 335 + 336 + /** 337 + * spmi_command_shutdown() - sends SHUTDOWN command to the specified SPMI device 338 + * @sdev: SPMI device. 339 + * 340 + * The Shutdown command causes the Slave to enter the SHUTDOWN state. 341 + */ 342 + int spmi_command_shutdown(struct spmi_device *sdev) 343 + { 344 + return spmi_cmd(sdev->ctrl, SPMI_CMD_SHUTDOWN, sdev->usid); 345 + } 346 + EXPORT_SYMBOL_GPL(spmi_command_shutdown); 347 + 348 + static int spmi_drv_probe(struct device *dev) 349 + { 350 + const struct spmi_driver *sdrv = to_spmi_driver(dev->driver); 351 + struct spmi_device *sdev = to_spmi_device(dev); 352 + int err; 353 + 354 + /* Ensure the slave is in ACTIVE state */ 355 + err = spmi_command_wakeup(sdev); 356 + if (err) 357 + goto fail_wakeup; 358 + 359 + pm_runtime_get_noresume(dev); 360 + pm_runtime_set_active(dev); 361 + pm_runtime_enable(dev); 362 + 363 + err = sdrv->probe(sdev); 364 + if (err) 365 + goto fail_probe; 366 + 367 + return 0; 368 + 369 + fail_probe: 370 + pm_runtime_disable(dev); 371 + pm_runtime_set_suspended(dev); 372 + pm_runtime_put_noidle(dev); 373 + fail_wakeup: 374 + return err; 375 + } 376 + 377 + static int spmi_drv_remove(struct device *dev) 378 + { 379 + const struct spmi_driver *sdrv = to_spmi_driver(dev->driver); 380 + 381 + pm_runtime_get_sync(dev); 382 + sdrv->remove(to_spmi_device(dev)); 383 + pm_runtime_put_noidle(dev); 384 + 385 + pm_runtime_disable(dev); 386 + pm_runtime_set_suspended(dev); 387 + pm_runtime_put_noidle(dev); 388 + return 0; 389 + } 390 + 391 + static struct bus_type spmi_bus_type = { 392 + .name = "spmi", 393 + .match = spmi_device_match, 394 + .pm = &spmi_pm_ops, 395 + .probe = spmi_drv_probe, 396 + .remove = spmi_drv_remove, 397 + }; 398 + 399 + /** 400 + * spmi_controller_alloc() - Allocate a new SPMI device 401 + * @ctrl: associated controller 402 + * 403 + * Caller is responsible for either calling spmi_device_add() to add the 404 + * newly allocated controller, or calling spmi_device_put() to discard it. 405 + */ 406 + struct spmi_device *spmi_device_alloc(struct spmi_controller *ctrl) 407 + { 408 + struct spmi_device *sdev; 409 + 410 + sdev = kzalloc(sizeof(*sdev), GFP_KERNEL); 411 + if (!sdev) 412 + return NULL; 413 + 414 + sdev->ctrl = ctrl; 415 + device_initialize(&sdev->dev); 416 + sdev->dev.parent = &ctrl->dev; 417 + sdev->dev.bus = &spmi_bus_type; 418 + sdev->dev.type = &spmi_dev_type; 419 + return sdev; 420 + } 421 + EXPORT_SYMBOL_GPL(spmi_device_alloc); 422 + 423 + /** 424 + * spmi_controller_alloc() - Allocate a new SPMI controller 425 + * @parent: parent device 426 + * @size: size of private data 427 + * 428 + * Caller is responsible for either calling spmi_controller_add() to add the 429 + * newly allocated controller, or calling spmi_controller_put() to discard it. 430 + * The allocated private data region may be accessed via 431 + * spmi_controller_get_drvdata() 432 + */ 433 + struct spmi_controller *spmi_controller_alloc(struct device *parent, 434 + size_t size) 435 + { 436 + struct spmi_controller *ctrl; 437 + int id; 438 + 439 + if (WARN_ON(!parent)) 440 + return NULL; 441 + 442 + ctrl = kzalloc(sizeof(*ctrl) + size, GFP_KERNEL); 443 + if (!ctrl) 444 + return NULL; 445 + 446 + device_initialize(&ctrl->dev); 447 + ctrl->dev.type = &spmi_ctrl_type; 448 + ctrl->dev.bus = &spmi_bus_type; 449 + ctrl->dev.parent = parent; 450 + ctrl->dev.of_node = parent->of_node; 451 + spmi_controller_set_drvdata(ctrl, &ctrl[1]); 452 + 453 + id = ida_simple_get(&ctrl_ida, 0, 0, GFP_KERNEL); 454 + if (id < 0) { 455 + dev_err(parent, 456 + "unable to allocate SPMI controller identifier.\n"); 457 + spmi_controller_put(ctrl); 458 + return NULL; 459 + } 460 + 461 + ctrl->nr = id; 462 + dev_set_name(&ctrl->dev, "spmi-%d", id); 463 + 464 + dev_dbg(&ctrl->dev, "allocated controller 0x%p id %d\n", ctrl, id); 465 + return ctrl; 466 + } 467 + EXPORT_SYMBOL_GPL(spmi_controller_alloc); 468 + 469 + static void of_spmi_register_devices(struct spmi_controller *ctrl) 470 + { 471 + struct device_node *node; 472 + int err; 473 + 474 + if (!ctrl->dev.of_node) 475 + return; 476 + 477 + for_each_available_child_of_node(ctrl->dev.of_node, node) { 478 + struct spmi_device *sdev; 479 + u32 reg[2]; 480 + 481 + dev_dbg(&ctrl->dev, "adding child %s\n", node->full_name); 482 + 483 + err = of_property_read_u32_array(node, "reg", reg, 2); 484 + if (err) { 485 + dev_err(&ctrl->dev, 486 + "node %s err (%d) does not have 'reg' property\n", 487 + node->full_name, err); 488 + continue; 489 + } 490 + 491 + if (reg[1] != SPMI_USID) { 492 + dev_err(&ctrl->dev, 493 + "node %s contains unsupported 'reg' entry\n", 494 + node->full_name); 495 + continue; 496 + } 497 + 498 + if (reg[0] >= SPMI_MAX_SLAVE_ID) { 499 + dev_err(&ctrl->dev, 500 + "invalid usid on node %s\n", 501 + node->full_name); 502 + continue; 503 + } 504 + 505 + dev_dbg(&ctrl->dev, "read usid %02x\n", reg[0]); 506 + 507 + sdev = spmi_device_alloc(ctrl); 508 + if (!sdev) 509 + continue; 510 + 511 + sdev->dev.of_node = node; 512 + sdev->usid = (u8) reg[0]; 513 + 514 + err = spmi_device_add(sdev); 515 + if (err) { 516 + dev_err(&sdev->dev, 517 + "failure adding device. status %d\n", err); 518 + spmi_device_put(sdev); 519 + } 520 + } 521 + } 522 + 523 + /** 524 + * spmi_controller_add() - Add an SPMI controller 525 + * @ctrl: controller to be registered. 526 + * 527 + * Register a controller previously allocated via spmi_controller_alloc() with 528 + * the SPMI core. 529 + */ 530 + int spmi_controller_add(struct spmi_controller *ctrl) 531 + { 532 + int ret; 533 + 534 + /* Can't register until after driver model init */ 535 + if (WARN_ON(!spmi_bus_type.p)) 536 + return -EAGAIN; 537 + 538 + ret = device_add(&ctrl->dev); 539 + if (ret) 540 + return ret; 541 + 542 + if (IS_ENABLED(CONFIG_OF)) 543 + of_spmi_register_devices(ctrl); 544 + 545 + dev_dbg(&ctrl->dev, "spmi-%d registered: dev:%p\n", 546 + ctrl->nr, &ctrl->dev); 547 + 548 + return 0; 549 + }; 550 + EXPORT_SYMBOL_GPL(spmi_controller_add); 551 + 552 + /* Remove a device associated with a controller */ 553 + static int spmi_ctrl_remove_device(struct device *dev, void *data) 554 + { 555 + struct spmi_device *spmidev = to_spmi_device(dev); 556 + if (dev->type == &spmi_dev_type) 557 + spmi_device_remove(spmidev); 558 + return 0; 559 + } 560 + 561 + /** 562 + * spmi_controller_remove(): remove an SPMI controller 563 + * @ctrl: controller to remove 564 + * 565 + * Remove a SPMI controller. Caller is responsible for calling 566 + * spmi_controller_put() to discard the allocated controller. 567 + */ 568 + void spmi_controller_remove(struct spmi_controller *ctrl) 569 + { 570 + int dummy; 571 + 572 + if (!ctrl) 573 + return; 574 + 575 + dummy = device_for_each_child(&ctrl->dev, NULL, 576 + spmi_ctrl_remove_device); 577 + device_del(&ctrl->dev); 578 + } 579 + EXPORT_SYMBOL_GPL(spmi_controller_remove); 580 + 581 + /** 582 + * spmi_driver_register() - Register client driver with SPMI core 583 + * @sdrv: client driver to be associated with client-device. 584 + * 585 + * This API will register the client driver with the SPMI framework. 586 + * It is typically called from the driver's module-init function. 587 + */ 588 + int spmi_driver_register(struct spmi_driver *sdrv) 589 + { 590 + sdrv->driver.bus = &spmi_bus_type; 591 + return driver_register(&sdrv->driver); 592 + } 593 + EXPORT_SYMBOL_GPL(spmi_driver_register); 594 + 595 + static void __exit spmi_exit(void) 596 + { 597 + bus_unregister(&spmi_bus_type); 598 + } 599 + module_exit(spmi_exit); 600 + 601 + static int __init spmi_init(void) 602 + { 603 + return bus_register(&spmi_bus_type); 604 + } 605 + postcore_initcall(spmi_init); 606 + 607 + MODULE_LICENSE("GPL v2"); 608 + MODULE_DESCRIPTION("SPMI module"); 609 + MODULE_ALIAS("platform:spmi");
+18
include/dt-bindings/spmi/spmi.h
··· 1 + /* Copyright (c) 2013, The Linux Foundation. All rights reserved. 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 and 5 + * only version 2 as published by the Free Software Foundation. 6 + * 7 + * This program is distributed in the hope that it will be useful, 8 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 + * GNU General Public License for more details. 11 + */ 12 + #ifndef __DT_BINDINGS_SPMI_H 13 + #define __DT_BINDINGS_SPMI_H 14 + 15 + #define SPMI_USID 0 16 + #define SPMI_GSID 1 17 + 18 + #endif
+8
include/linux/mod_devicetable.h
··· 432 432 kernel_ulong_t driver_data; /* Data private to the driver */ 433 433 }; 434 434 435 + #define SPMI_NAME_SIZE 32 436 + #define SPMI_MODULE_PREFIX "spmi:" 437 + 438 + struct spmi_device_id { 439 + char name[SPMI_NAME_SIZE]; 440 + kernel_ulong_t driver_data; /* Data private to the driver */ 441 + }; 442 + 435 443 /* dmi */ 436 444 enum dmi_field { 437 445 DMI_NONE,
+191
include/linux/spmi.h
··· 1 + /* Copyright (c) 2012-2013, The Linux Foundation. All rights reserved. 2 + * 3 + * This program is free software; you can redistribute it and/or modify 4 + * it under the terms of the GNU General Public License version 2 and 5 + * only version 2 as published by the Free Software Foundation. 6 + * 7 + * This program is distributed in the hope that it will be useful, 8 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 9 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 10 + * GNU General Public License for more details. 11 + */ 12 + #ifndef _LINUX_SPMI_H 13 + #define _LINUX_SPMI_H 14 + 15 + #include <linux/types.h> 16 + #include <linux/device.h> 17 + #include <linux/mod_devicetable.h> 18 + 19 + /* Maximum slave identifier */ 20 + #define SPMI_MAX_SLAVE_ID 16 21 + 22 + /* SPMI Commands */ 23 + #define SPMI_CMD_EXT_WRITE 0x00 24 + #define SPMI_CMD_RESET 0x10 25 + #define SPMI_CMD_SLEEP 0x11 26 + #define SPMI_CMD_SHUTDOWN 0x12 27 + #define SPMI_CMD_WAKEUP 0x13 28 + #define SPMI_CMD_AUTHENTICATE 0x14 29 + #define SPMI_CMD_MSTR_READ 0x15 30 + #define SPMI_CMD_MSTR_WRITE 0x16 31 + #define SPMI_CMD_TRANSFER_BUS_OWNERSHIP 0x1A 32 + #define SPMI_CMD_DDB_MASTER_READ 0x1B 33 + #define SPMI_CMD_DDB_SLAVE_READ 0x1C 34 + #define SPMI_CMD_EXT_READ 0x20 35 + #define SPMI_CMD_EXT_WRITEL 0x30 36 + #define SPMI_CMD_EXT_READL 0x38 37 + #define SPMI_CMD_WRITE 0x40 38 + #define SPMI_CMD_READ 0x60 39 + #define SPMI_CMD_ZERO_WRITE 0x80 40 + 41 + /** 42 + * struct spmi_device - Basic representation of an SPMI device 43 + * @dev: Driver model representation of the device. 44 + * @ctrl: SPMI controller managing the bus hosting this device. 45 + * @usid: This devices' Unique Slave IDentifier. 46 + */ 47 + struct spmi_device { 48 + struct device dev; 49 + struct spmi_controller *ctrl; 50 + u8 usid; 51 + }; 52 + 53 + static inline struct spmi_device *to_spmi_device(struct device *d) 54 + { 55 + return container_of(d, struct spmi_device, dev); 56 + } 57 + 58 + static inline void *spmi_device_get_drvdata(const struct spmi_device *sdev) 59 + { 60 + return dev_get_drvdata(&sdev->dev); 61 + } 62 + 63 + static inline void spmi_device_set_drvdata(struct spmi_device *sdev, void *data) 64 + { 65 + dev_set_drvdata(&sdev->dev, data); 66 + } 67 + 68 + struct spmi_device *spmi_device_alloc(struct spmi_controller *ctrl); 69 + 70 + static inline void spmi_device_put(struct spmi_device *sdev) 71 + { 72 + if (sdev) 73 + put_device(&sdev->dev); 74 + } 75 + 76 + int spmi_device_add(struct spmi_device *sdev); 77 + 78 + void spmi_device_remove(struct spmi_device *sdev); 79 + 80 + /** 81 + * struct spmi_controller - interface to the SPMI master controller 82 + * @dev: Driver model representation of the device. 83 + * @nr: board-specific number identifier for this controller/bus 84 + * @cmd: sends a non-data command sequence on the SPMI bus. 85 + * @read_cmd: sends a register read command sequence on the SPMI bus. 86 + * @write_cmd: sends a register write command sequence on the SPMI bus. 87 + */ 88 + struct spmi_controller { 89 + struct device dev; 90 + unsigned int nr; 91 + int (*cmd)(struct spmi_controller *ctrl, u8 opcode, u8 sid); 92 + int (*read_cmd)(struct spmi_controller *ctrl, u8 opcode, 93 + u8 sid, u16 addr, u8 *buf, size_t len); 94 + int (*write_cmd)(struct spmi_controller *ctrl, u8 opcode, 95 + u8 sid, u16 addr, const u8 *buf, size_t len); 96 + }; 97 + 98 + static inline struct spmi_controller *to_spmi_controller(struct device *d) 99 + { 100 + return container_of(d, struct spmi_controller, dev); 101 + } 102 + 103 + static inline 104 + void *spmi_controller_get_drvdata(const struct spmi_controller *ctrl) 105 + { 106 + return dev_get_drvdata(&ctrl->dev); 107 + } 108 + 109 + static inline void spmi_controller_set_drvdata(struct spmi_controller *ctrl, 110 + void *data) 111 + { 112 + dev_set_drvdata(&ctrl->dev, data); 113 + } 114 + 115 + struct spmi_controller *spmi_controller_alloc(struct device *parent, 116 + size_t size); 117 + 118 + /** 119 + * spmi_controller_put() - decrement controller refcount 120 + * @ctrl SPMI controller. 121 + */ 122 + static inline void spmi_controller_put(struct spmi_controller *ctrl) 123 + { 124 + if (ctrl) 125 + put_device(&ctrl->dev); 126 + } 127 + 128 + int spmi_controller_add(struct spmi_controller *ctrl); 129 + void spmi_controller_remove(struct spmi_controller *ctrl); 130 + 131 + /** 132 + * struct spmi_driver - SPMI slave device driver 133 + * @driver: SPMI device drivers should initialize name and owner field of 134 + * this structure. 135 + * @probe: binds this driver to a SPMI device. 136 + * @remove: unbinds this driver from the SPMI device. 137 + * @shutdown: standard shutdown callback used during powerdown/halt. 138 + * @suspend: standard suspend callback used during system suspend. 139 + * @resume: standard resume callback used during system resume. 140 + * 141 + * If PM runtime support is desired for a slave, a device driver can call 142 + * pm_runtime_put() from their probe() routine (and a balancing 143 + * pm_runtime_get() in remove()). PM runtime support for a slave is 144 + * implemented by issuing a SLEEP command to the slave on runtime_suspend(), 145 + * transitioning the slave into the SLEEP state. On runtime_resume(), a WAKEUP 146 + * command is sent to the slave to bring it back to ACTIVE. 147 + */ 148 + struct spmi_driver { 149 + struct device_driver driver; 150 + int (*probe)(struct spmi_device *sdev); 151 + void (*remove)(struct spmi_device *sdev); 152 + }; 153 + 154 + static inline struct spmi_driver *to_spmi_driver(struct device_driver *d) 155 + { 156 + return container_of(d, struct spmi_driver, driver); 157 + } 158 + 159 + int spmi_driver_register(struct spmi_driver *sdrv); 160 + 161 + /** 162 + * spmi_driver_unregister() - unregister an SPMI client driver 163 + * @sdrv: the driver to unregister 164 + */ 165 + static inline void spmi_driver_unregister(struct spmi_driver *sdrv) 166 + { 167 + if (sdrv) 168 + driver_unregister(&sdrv->driver); 169 + } 170 + 171 + #define module_spmi_driver(__spmi_driver) \ 172 + module_driver(__spmi_driver, spmi_driver_register, \ 173 + spmi_driver_unregister) 174 + 175 + int spmi_register_read(struct spmi_device *sdev, u8 addr, u8 *buf); 176 + int spmi_ext_register_read(struct spmi_device *sdev, u8 addr, u8 *buf, 177 + size_t len); 178 + int spmi_ext_register_readl(struct spmi_device *sdev, u16 addr, u8 *buf, 179 + size_t len); 180 + int spmi_register_write(struct spmi_device *sdev, u8 addr, u8 data); 181 + int spmi_register_zero_write(struct spmi_device *sdev, u8 data); 182 + int spmi_ext_register_write(struct spmi_device *sdev, u8 addr, 183 + const u8 *buf, size_t len); 184 + int spmi_ext_register_writel(struct spmi_device *sdev, u16 addr, 185 + const u8 *buf, size_t len); 186 + int spmi_command_reset(struct spmi_device *sdev); 187 + int spmi_command_sleep(struct spmi_device *sdev); 188 + int spmi_command_wakeup(struct spmi_device *sdev); 189 + int spmi_command_shutdown(struct spmi_device *sdev); 190 + 191 + #endif