drivers/spmi/spmi.c
Source file repositories/reference/linux-study-clean/drivers/spmi/spmi.c
File Facts
- System
- Linux kernel
- Corpus path
drivers/spmi/spmi.c- Extension
.c- Size
- 15739 bytes
- Lines
- 626
- Domain
- Driver Families
- Bucket
- drivers/spmi
- Inferred role
- Driver Families: operation-table or driver-model contract
- Status
- pattern implementation candidate
Why This File Exists
Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.
- Defines an operation table; this is where Linux turns generic core objects into subsystem-specific behavior.
- Allocates kernel memory; connect allocation flags and lifetime to context constraints.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
linux/kernel.hlinux/errno.hlinux/idr.hlinux/slab.hlinux/module.hlinux/of.hlinux/of_device.hlinux/platform_device.hlinux/spmi.hlinux/pm_runtime.hdt-bindings/spmi/spmi.htrace/events/spmi.h
Detected Declarations
function spmi_dev_releasefunction spmi_ctrl_releasefunction spmi_device_matchfunction spmi_device_addfunction spmi_device_removefunction spmi_cmdfunction spmi_read_cmdfunction spmi_write_cmdfunction spmi_register_readfunction spmi_ext_register_readfunction spmi_ext_register_readlfunction spmi_register_writefunction spmi_register_zero_writefunction spmi_ext_register_writefunction spmi_ext_register_writelfunction spmi_command_resetfunction spmi_command_sleepfunction spmi_command_wakeupfunction spmi_command_shutdownfunction spmi_drv_probefunction spmi_drv_removefunction spmi_drv_shutdownfunction spmi_drv_ueventfunction spmi_find_device_by_of_nodefunction spmi_device_allocfunction spmi_controller_allocfunction of_spmi_register_devicesfunction for_each_available_child_of_nodefunction spmi_controller_addfunction spmi_ctrl_remove_devicefunction spmi_controller_removefunction __spmi_driver_registerfunction spmi_exitfunction spmi_initexport spmi_device_addexport spmi_device_removeexport spmi_register_readexport spmi_ext_register_readexport spmi_ext_register_readlexport spmi_register_writeexport spmi_register_zero_writeexport spmi_ext_register_writeexport spmi_ext_register_writelexport spmi_command_resetexport spmi_command_sleepexport spmi_command_wakeupexport spmi_command_shutdownexport spmi_find_device_by_of_node
Annotated Snippet
static int spmi_device_match(struct device *dev, const struct device_driver *drv)
{
if (of_driver_match_device(dev, drv))
return 1;
if (drv->name)
return strncmp(dev_name(dev), drv->name,
SPMI_NAME_SIZE) == 0;
return 0;
}
/**
* spmi_device_add() - add a device previously constructed via spmi_device_alloc()
* @sdev: spmi_device to be added
*/
int spmi_device_add(struct spmi_device *sdev)
{
struct spmi_controller *ctrl = sdev->ctrl;
int err;
dev_set_name(&sdev->dev, "%d-%02x", ctrl->nr, sdev->usid);
err = device_add(&sdev->dev);
if (err < 0) {
dev_err(&sdev->dev, "Can't add %s, status %d\n",
dev_name(&sdev->dev), err);
goto err_device_add;
}
dev_dbg(&sdev->dev, "device %s registered\n", dev_name(&sdev->dev));
err_device_add:
return err;
}
EXPORT_SYMBOL_GPL(spmi_device_add);
/**
* spmi_device_remove(): remove an SPMI device
* @sdev: spmi_device to be removed
*/
void spmi_device_remove(struct spmi_device *sdev)
{
device_unregister(&sdev->dev);
}
EXPORT_SYMBOL_GPL(spmi_device_remove);
static inline int
spmi_cmd(struct spmi_controller *ctrl, u8 opcode, u8 sid)
{
int ret;
if (!ctrl || !ctrl->cmd || ctrl->dev.type != &spmi_ctrl_type)
return -EINVAL;
ret = ctrl->cmd(ctrl, opcode, sid);
trace_spmi_cmd(opcode, sid, ret);
return ret;
}
static inline int spmi_read_cmd(struct spmi_controller *ctrl, u8 opcode,
u8 sid, u16 addr, u8 *buf, size_t len)
{
int ret;
if (!ctrl || !ctrl->read_cmd || ctrl->dev.type != &spmi_ctrl_type)
return -EINVAL;
trace_spmi_read_begin(opcode, sid, addr);
ret = ctrl->read_cmd(ctrl, opcode, sid, addr, buf, len);
trace_spmi_read_end(opcode, sid, addr, ret, len, buf);
return ret;
}
static inline int spmi_write_cmd(struct spmi_controller *ctrl, u8 opcode,
u8 sid, u16 addr, const u8 *buf, size_t len)
{
int ret;
if (!ctrl || !ctrl->write_cmd || ctrl->dev.type != &spmi_ctrl_type)
return -EINVAL;
trace_spmi_write_begin(opcode, sid, addr, len, buf);
ret = ctrl->write_cmd(ctrl, opcode, sid, addr, buf, len);
trace_spmi_write_end(opcode, sid, addr, ret);
return ret;
}
/**
* spmi_register_read() - register read
Annotation
- Immediate include surface: `linux/kernel.h`, `linux/errno.h`, `linux/idr.h`, `linux/slab.h`, `linux/module.h`, `linux/of.h`, `linux/of_device.h`, `linux/platform_device.h`.
- Detected declarations: `function spmi_dev_release`, `function spmi_ctrl_release`, `function spmi_device_match`, `function spmi_device_add`, `function spmi_device_remove`, `function spmi_cmd`, `function spmi_read_cmd`, `function spmi_write_cmd`, `function spmi_register_read`, `function spmi_ext_register_read`.
- Atlas domain: Driver Families / drivers/spmi.
- Implementation status: pattern implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.