// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)// Copyright(c) 2015-17 Intel Corporation. #include <linux/acpi.h>#include <linux/delay.h>#include <linux/pm_runtime.h>#include <linux/soundwire/sdw_registers.h>#include <linux/soundwire/sdw.h>#include <linux/soundwire/sdw_type.h>#include <linux/string_choices.h>#include "bus.h"#include "irq.h"#include "sysfs_local.h" static DEFINE_IDA(sdw_bus_ida); static int sdw_get_id(struct sdw_bus *bus){ int rc = ida_alloc(&sdw_bus_ida, GFP_KERNEL); if (rc < 0) return rc; bus->id = rc; if (bus->controller_id == -1) bus->controller_id = rc; return 0;} /** * sdw_bus_master_add() - add a bus Master instance * @bus: bus instance * @parent: parent device * @fwnode: firmware node handle * * Initializes the bus instance, read properties and create child * devices. */int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, struct fwnode_handle *fwnode){ struct sdw_master_prop *prop = NULL; int ret; if (!parent) { pr_err("SoundWire parent device is not set\n"); return -ENODEV; } ret = sdw_get_id(bus); if (ret < 0) { dev_err(parent, "Failed to get bus id\n"); return ret; } ida_init(&bus->slave_ida); ret = sdw_master_device_add(bus, parent, fwnode); if (ret < 0) { dev_err(parent, "Failed to add master device at link %d\n", bus->link_id); return ret; } if (!bus->ops) { dev_err(bus->dev, "SoundWire Bus ops are not set\n"); return -EINVAL; } if (!bus->compute_params) { dev_err(bus->dev, "Bandwidth allocation not configured, compute_params no set\n"); return -EINVAL; } /* * Give each bus_lock and msg_lock a unique key so that lockdep won't * trigger a deadlock warning when the locks of several buses are * grabbed during configuration of a multi-bus stream. */ lockdep_register_key(&bus->msg_lock_key); __mutex_init(&bus->msg_lock, "msg_lock", &bus->msg_lock_key); lockdep_register_key(&bus->bus_lock_key); __mutex_init(&bus->bus_lock, "bus_lock", &bus->bus_lock_key); INIT_LIST_HEAD(&bus->slaves); INIT_LIST_HEAD(&bus->m_rt_list); /* * Initialize multi_link flag */ bus->multi_link = false; if (bus->ops->read_prop) { ret = bus->ops->read_prop(bus); if (ret < 0) { dev_err(bus->dev, "Bus read properties failed:%d\n", ret); return ret; } } sdw_bus_debugfs_init(bus); /* * Device numbers in SoundWire are 0 through 15. Enumeration device * number (0), Broadcast device number (15), Group numbers (12 and * 13) and Master device number (14) are not used for assignment so * mask these and other higher bits. */ /* Set higher order bits */ *bus->assigned = ~GENMASK(SDW_BROADCAST_DEV_NUM, SDW_ENUM_DEV_NUM); /* Set enumeration device number and broadcast device number */ set_bit(SDW_ENUM_DEV_NUM, bus->assigned); set_bit(SDW_BROADCAST_DEV_NUM, bus->assigned); /* Set group device numbers and master device number */ set_bit(SDW_GROUP12_DEV_NUM, bus->assigned); set_bit(SDW_GROUP13_DEV_NUM, bus->assigned); set_bit(SDW_MASTER_DEV_NUM, bus->assigned); ret = sdw_irq_create(bus, fwnode); if (ret) return ret; /* * SDW is an enumerable bus, but devices can be powered off. So, * they won't be able to report as present. * * Create Slave devices based on Slaves described in * the respective firmware (ACPI/DT) */ if (IS_ENABLED(CONFIG_ACPI) && ACPI_HANDLE(bus->dev)) ret = sdw_acpi_find_slaves(bus); else if (IS_ENABLED(CONFIG_OF) && bus->dev->of_node) ret = sdw_of_find_slaves(bus); else ret = -ENOTSUPP; /* No ACPI/DT so error out */ if (ret < 0) { dev_err(bus->dev, "Finding slaves failed:%d\n", ret); sdw_irq_delete(bus); return ret; } /* * Initialize clock values based on Master properties. The max * frequency is read from max_clk_freq property. Current assumption * is that the bus will start at highest clock frequency when * powered on. * * Default active bank will be 0 as out of reset the Slaves have * to start with bank 0 (Table 40 of Spec) */ prop = &bus->prop; bus->params.max_dr_freq = prop->max_clk_freq * SDW_DOUBLE_RATE_FACTOR; bus->params.curr_dr_freq = bus->params.max_dr_freq; bus->params.curr_bank = SDW_BANK0; bus->params.next_bank = SDW_BANK1; return 0;}EXPORT_SYMBOL(sdw_bus_master_add); static int sdw_delete_slave(struct device *dev, void *data){ struct sdw_slave *slave = dev_to_sdw_dev(dev); struct sdw_bus *bus = slave->bus; pm_runtime_disable(dev); sdw_slave_debugfs_exit(slave); mutex_lock(&bus->bus_lock); if (slave->dev_num) { /* clear dev_num if assigned */ clear_bit(slave->dev_num, bus->assigned); if (bus->ops && bus->ops->put_device_num) bus->ops->put_device_num(bus, slave); } list_del_init(&slave->node); mutex_unlock(&bus->bus_lock); device_unregister(dev); return 0;} /** * sdw_bus_master_delete() - delete the bus master instance * @bus: bus to be deleted * * Remove the instance, delete the child devices. */void sdw_bus_master_delete(struct sdw_bus *bus){ device_for_each_child(bus->dev, NULL, sdw_delete_slave); sdw_irq_delete(bus); sdw_master_device_del(bus); sdw_bus_debugfs_exit(bus); lockdep_unregister_key(&bus->bus_lock_key); lockdep_unregister_key(&bus->msg_lock_key); ida_free(&sdw_bus_ida, bus->id);}EXPORT_SYMBOL(sdw_bus_master_delete); /* * SDW IO Calls */ static inline int find_response_code(enum sdw_command_response resp){ switch (resp) { case SDW_CMD_OK: return 0; case SDW_CMD_IGNORED: return -ENODATA; case SDW_CMD_TIMEOUT: return -ETIMEDOUT; default: return -EIO; }} static inline int do_transfer(struct sdw_bus *bus, struct sdw_msg *msg){ int retry = bus->prop.err_threshold; enum sdw_command_response resp; int ret = 0, i; for (i = 0; i <= retry; i++) { resp = bus->ops->xfer_msg(bus, msg); ret = find_response_code(resp); /* if cmd is ok or ignored return */ if (ret == 0 || ret == -ENODATA) return ret; } return ret;} static inline int do_transfer_defer(struct sdw_bus *bus, struct sdw_msg *msg){ struct sdw_defer *defer = &bus->defer_msg; int retry = bus->prop.err_threshold; enum sdw_command_response resp; int ret = 0, i; defer->msg = msg; defer->length = msg->len; init_completion(&defer->complete); for (i = 0; i <= retry; i++) { resp = bus->ops->xfer_msg_defer(bus); ret = find_response_code(resp); /* if cmd is ok or ignored return */ if (ret == 0 || ret == -ENODATA) return ret; } return ret;} static int sdw_transfer_unlocked(struct sdw_bus *bus, struct sdw_msg *msg){ int ret; ret = do_transfer(bus, msg); if (ret != 0 && ret != -ENODATA) dev_err(bus->dev, "trf on Slave %d failed:%d %s addr %x count %d\n", msg->dev_num, ret, str_write_read(msg->flags & SDW_MSG_FLAG_WRITE), msg->addr, msg->len); return ret;} /** * sdw_transfer() - Synchronous transfer message to a SDW Slave device * @bus: SDW bus * @msg: SDW message to be xfered */int sdw_transfer(struct sdw_bus *bus, struct sdw_msg *msg){ int ret; mutex_lock(&bus->msg_lock); ret = sdw_transfer_unlocked(bus, msg); mutex_unlock(&bus->msg_lock); return ret;} /** * sdw_show_ping_status() - Direct report of PING status, to be used by Peripheral drivers * @bus: SDW bus * @sync_delay: Delay before reading status */void sdw_show_ping_status(struct sdw_bus *bus, bool sync_delay){ u32 status; if (!bus->ops->read_ping_status) return; /* * wait for peripheral to sync if desired. 10-15ms should be more than * enough in most cases. */ if (sync_delay) usleep_range(10000, 15000); mutex_lock(&bus->msg_lock); status = bus->ops->read_ping_status(bus); mutex_unlock(&bus->msg_lock); if (!status) dev_warn(bus->dev, "%s: no peripherals attached\n", __func__); else dev_dbg(bus->dev, "PING status: %#x\n", status);}EXPORT_SYMBOL(sdw_show_ping_status); /** * sdw_transfer_defer() - Asynchronously transfer message to a SDW Slave device * @bus: SDW bus * @msg: SDW message to be xfered * * Caller needs to hold the msg_lock lock while calling this */int sdw_transfer_defer(struct sdw_bus *bus, struct sdw_msg *msg){ int ret; if (!bus->ops->xfer_msg_defer) return -ENOTSUPP; ret = do_transfer_defer(bus, msg); if (ret != 0 && ret != -ENODATA) dev_err(bus->dev, "Defer trf on Slave %d failed:%d\n", msg->dev_num, ret); return ret;} int sdw_fill_msg(struct sdw_msg *msg, struct sdw_slave *slave, u32 addr, size_t count, u16 dev_num, u8 flags, u8 *buf){ memset(msg, 0, sizeof(*msg)); msg->addr = addr; /* addr is 16 bit and truncated here */ msg->len = count; msg->dev_num = dev_num; msg->flags = flags; msg->buf = buf; if (addr < SDW_REG_NO_PAGE) /* no paging area */ return 0; if (addr >= SDW_REG_MAX) { /* illegal addr */ pr_err("SDW: Invalid address %x passed\n", addr); return -EINVAL; } if (addr < SDW_REG_OPTIONAL_PAGE) { /* 32k but no page */ if (slave && !slave->prop.paging_support) return 0; /* no need for else as that will fall-through to paging */ } /* paging mandatory */ if (dev_num == SDW_ENUM_DEV_NUM || dev_num == SDW_BROADCAST_DEV_NUM) { pr_err("SDW: Invalid device for paging :%d\n", dev_num); return -EINVAL; } if (!slave) { pr_err("SDW: No slave for paging addr\n"); return -EINVAL; } if (!slave->prop.paging_support) { dev_err(&slave->dev, "address %x needs paging but no support\n", addr); return -EINVAL; } msg->addr_page1 = FIELD_GET(SDW_SCP_ADDRPAGE1_MASK, addr); msg->addr_page2 = FIELD_GET(SDW_SCP_ADDRPAGE2_MASK, addr); msg->addr |= BIT(15); msg->page = true; return 0;} /* * Read/Write IO functions. */ static int sdw_ntransfer_no_pm(struct sdw_slave *slave, u32 addr, u8 flags, size_t count, u8 *val){ struct sdw_msg msg; size_t size; int ret; while (count) { // Only handle bytes up to next page boundary size = min_t(size_t, count, (SDW_REGADDR + 1) - (addr & SDW_REGADDR)); ret = sdw_fill_msg(&msg, slave, addr, size, slave->dev_num, flags, val); if (ret < 0) return ret; ret = sdw_transfer(slave->bus, &msg); if (ret < 0 && !slave->is_mockup_device) return ret; addr += size; val += size; count -= size; } return 0;} /** * sdw_nread_no_pm() - Read "n" contiguous SDW Slave registers with no PM * @slave: SDW Slave * @addr: Register address * @count: length * @val: Buffer for values to be read * * Note that if the message crosses a page boundary each page will be * transferred under a separate invocation of the msg_lock. */int sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val){ return sdw_ntransfer_no_pm(slave, addr, SDW_MSG_FLAG_READ, count, val);}EXPORT_SYMBOL(sdw_nread_no_pm); /** * sdw_nwrite_no_pm() - Write "n" contiguous SDW Slave registers with no PM * @slave: SDW Slave * @addr: Register address * @count: length * @val: Buffer for values to be written * * Note that if the message crosses a page boundary each page will be * transferred under a separate invocation of the msg_lock. */int sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val){ return sdw_ntransfer_no_pm(slave, addr, SDW_MSG_FLAG_WRITE, count, (u8 *)val);}EXPORT_SYMBOL(sdw_nwrite_no_pm); /** * sdw_write_no_pm() - Write a SDW Slave register with no PM * @slave: SDW Slave * @addr: Register address * @value: Register value */int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value){ return sdw_nwrite_no_pm(slave, addr, 1, &value);}EXPORT_SYMBOL(sdw_write_no_pm); static intsdw_bread_no_pm(struct sdw_bus *bus, u16 dev_num, u32 addr){ struct sdw_msg msg; u8 buf; int ret; ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num, SDW_MSG_FLAG_READ, &buf); if (ret < 0) return ret; ret = sdw_transfer(bus, &msg); if (ret < 0) return ret; Lines 1–500 of 2106. Load more
// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) // Copyright(c) 2015-17 Intel Corporation. #include <linux/acpi.h> #include <linux/delay.h> #include <linux/pm_runtime.h> #include <linux/soundwire/sdw_registers.h> #include <linux/soundwire/sdw.h> #include <linux/soundwire/sdw_type.h> #include <linux/string_choices.h> #include "bus.h" #include "irq.h" #include "sysfs_local.h" static DEFINE_IDA(sdw_bus_ida); static int sdw_get_id(struct sdw_bus *bus) { int rc = ida_alloc(&sdw_bus_ida, GFP_KERNEL); if (rc < 0) return rc; bus->id = rc; if (bus->controller_id == -1) bus->controller_id = rc; return 0; } /** * sdw_bus_master_add() - add a bus Master instance * @bus: bus instance * @parent: parent device * @fwnode: firmware node handle * * Initializes the bus instance, read properties and create child * devices. */ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent, struct fwnode_handle *fwnode) { struct sdw_master_prop *prop = NULL; int ret; if (!parent) { pr_err("SoundWire parent device is not set\n"); return -ENODEV; } ret = sdw_get_id(bus); if (ret < 0) { dev_err(parent, "Failed to get bus id\n"); return ret; } ida_init(&bus->slave_ida); ret = sdw_master_device_add(bus, parent, fwnode); if (ret < 0) { dev_err(parent, "Failed to add master device at link %d\n", bus->link_id); return ret; } if (!bus->ops) { dev_err(bus->dev, "SoundWire Bus ops are not set\n"); return -EINVAL; } if (!bus->compute_params) { dev_err(bus->dev, "Bandwidth allocation not configured, compute_params no set\n"); return -EINVAL; } /* * Give each bus_lock and msg_lock a unique key so that lockdep won't * trigger a deadlock warning when the locks of several buses are * grabbed during configuration of a multi-bus stream. */ lockdep_register_key(&bus->msg_lock_key); __mutex_init(&bus->msg_lock, "msg_lock", &bus->msg_lock_key); lockdep_register_key(&bus->bus_lock_key); __mutex_init(&bus->bus_lock, "bus_lock", &bus->bus_lock_key); INIT_LIST_HEAD(&bus->slaves); INIT_LIST_HEAD(&bus->m_rt_list); /* * Initialize multi_link flag */ bus->multi_link = false; if (bus->ops->read_prop) { ret = bus->ops->read_prop(bus); if (ret < 0) { dev_err(bus->dev, "Bus read properties failed:%d\n", ret); return ret; } } sdw_bus_debugfs_init(bus); /* * Device numbers in SoundWire are 0 through 15. Enumeration device * number (0), Broadcast device number (15), Group numbers (12 and * 13) and Master device number (14) are not used for assignment so * mask these and other higher bits. */ /* Set higher order bits */ *bus->assigned = ~GENMASK(SDW_BROADCAST_DEV_NUM, SDW_ENUM_DEV_NUM); /* Set enumeration device number and broadcast device number */ set_bit(SDW_ENUM_DEV_NUM, bus->assigned); set_bit(SDW_BROADCAST_DEV_NUM, bus->assigned); /* Set group device numbers and master device number */ set_bit(SDW_GROUP12_DEV_NUM, bus->assigned); set_bit(SDW_GROUP13_DEV_NUM, bus->assigned); set_bit(SDW_MASTER_DEV_NUM, bus->assigned); ret = sdw_irq_create(bus, fwnode); if (ret) return ret; /* * SDW is an enumerable bus, but devices can be powered off. So, * they won't be able to report as present. * * Create Slave devices based on Slaves described in * the respective firmware (ACPI/DT) */ if (IS_ENABLED(CONFIG_ACPI) && ACPI_HANDLE(bus->dev)) ret = sdw_acpi_find_slaves(bus); else if (IS_ENABLED(CONFIG_OF) && bus->dev->of_node) ret = sdw_of_find_slaves(bus); else ret = -ENOTSUPP; /* No ACPI/DT so error out */ if (ret < 0) { dev_err(bus->dev, "Finding slaves failed:%d\n", ret); sdw_irq_delete(bus); return ret; } /* * Initialize clock values based on Master properties. The max * frequency is read from max_clk_freq property. Current assumption * is that the bus will start at highest clock frequency when * powered on. * * Default active bank will be 0 as out of reset the Slaves have * to start with bank 0 (Table 40 of Spec) */ prop = &bus->prop; bus->params.max_dr_freq = prop->max_clk_freq * SDW_DOUBLE_RATE_FACTOR; bus->params.curr_dr_freq = bus->params.max_dr_freq; bus->params.curr_bank = SDW_BANK0; bus->params.next_bank = SDW_BANK1; return 0; } EXPORT_SYMBOL(sdw_bus_master_add); static int sdw_delete_slave(struct device *dev, void *data) { struct sdw_slave *slave = dev_to_sdw_dev(dev); struct sdw_bus *bus = slave->bus; pm_runtime_disable(dev); sdw_slave_debugfs_exit(slave); mutex_lock(&bus->bus_lock); if (slave->dev_num) { /* clear dev_num if assigned */ clear_bit(slave->dev_num, bus->assigned); if (bus->ops && bus->ops->put_device_num) bus->ops->put_device_num(bus, slave); } list_del_init(&slave->node); mutex_unlock(&bus->bus_lock); device_unregister(dev); return 0; } /** * sdw_bus_master_delete() - delete the bus master instance * @bus: bus to be deleted * * Remove the instance, delete the child devices. */ void sdw_bus_master_delete(struct sdw_bus *bus) { device_for_each_child(bus->dev, NULL, sdw_delete_slave); sdw_irq_delete(bus); sdw_master_device_del(bus); sdw_bus_debugfs_exit(bus); lockdep_unregister_key(&bus->bus_lock_key); lockdep_unregister_key(&bus->msg_lock_key); ida_free(&sdw_bus_ida, bus->id); } EXPORT_SYMBOL(sdw_bus_master_delete); /* * SDW IO Calls */ static inline int find_response_code(enum sdw_command_response resp) { switch (resp) { case SDW_CMD_OK: return 0; case SDW_CMD_IGNORED: return -ENODATA; case SDW_CMD_TIMEOUT: return -ETIMEDOUT; default: return -EIO; } } static inline int do_transfer(struct sdw_bus *bus, struct sdw_msg *msg) { int retry = bus->prop.err_threshold; enum sdw_command_response resp; int ret = 0, i; for (i = 0; i <= retry; i++) { resp = bus->ops->xfer_msg(bus, msg); ret = find_response_code(resp); /* if cmd is ok or ignored return */ if (ret == 0 || ret == -ENODATA) return ret; } return ret; } static inline int do_transfer_defer(struct sdw_bus *bus, struct sdw_msg *msg) { struct sdw_defer *defer = &bus->defer_msg; int retry = bus->prop.err_threshold; enum sdw_command_response resp; int ret = 0, i; defer->msg = msg; defer->length = msg->len; init_completion(&defer->complete); for (i = 0; i <= retry; i++) { resp = bus->ops->xfer_msg_defer(bus); ret = find_response_code(resp); /* if cmd is ok or ignored return */ if (ret == 0 || ret == -ENODATA) return ret; } return ret; } static int sdw_transfer_unlocked(struct sdw_bus *bus, struct sdw_msg *msg) { int ret; ret = do_transfer(bus, msg); if (ret != 0 && ret != -ENODATA) dev_err(bus->dev, "trf on Slave %d failed:%d %s addr %x count %d\n", msg->dev_num, ret, str_write_read(msg->flags & SDW_MSG_FLAG_WRITE), msg->addr, msg->len); return ret; } /** * sdw_transfer() - Synchronous transfer message to a SDW Slave device * @bus: SDW bus * @msg: SDW message to be xfered */ int sdw_transfer(struct sdw_bus *bus, struct sdw_msg *msg) { int ret; mutex_lock(&bus->msg_lock); ret = sdw_transfer_unlocked(bus, msg); mutex_unlock(&bus->msg_lock); return ret; } /** * sdw_show_ping_status() - Direct report of PING status, to be used by Peripheral drivers * @bus: SDW bus * @sync_delay: Delay before reading status */ void sdw_show_ping_status(struct sdw_bus *bus, bool sync_delay) { u32 status; if (!bus->ops->read_ping_status) return; /* * wait for peripheral to sync if desired. 10-15ms should be more than * enough in most cases. */ if (sync_delay) usleep_range(10000, 15000); mutex_lock(&bus->msg_lock); status = bus->ops->read_ping_status(bus); mutex_unlock(&bus->msg_lock); if (!status) dev_warn(bus->dev, "%s: no peripherals attached\n", __func__); else dev_dbg(bus->dev, "PING status: %#x\n", status); } EXPORT_SYMBOL(sdw_show_ping_status); /** * sdw_transfer_defer() - Asynchronously transfer message to a SDW Slave device * @bus: SDW bus * @msg: SDW message to be xfered * * Caller needs to hold the msg_lock lock while calling this */ int sdw_transfer_defer(struct sdw_bus *bus, struct sdw_msg *msg) { int ret; if (!bus->ops->xfer_msg_defer) return -ENOTSUPP; ret = do_transfer_defer(bus, msg); if (ret != 0 && ret != -ENODATA) dev_err(bus->dev, "Defer trf on Slave %d failed:%d\n", msg->dev_num, ret); return ret; } int sdw_fill_msg(struct sdw_msg *msg, struct sdw_slave *slave, u32 addr, size_t count, u16 dev_num, u8 flags, u8 *buf) { memset(msg, 0, sizeof(*msg)); msg->addr = addr; /* addr is 16 bit and truncated here */ msg->len = count; msg->dev_num = dev_num; msg->flags = flags; msg->buf = buf; if (addr < SDW_REG_NO_PAGE) /* no paging area */ return 0; if (addr >= SDW_REG_MAX) { /* illegal addr */ pr_err("SDW: Invalid address %x passed\n", addr); return -EINVAL; } if (addr < SDW_REG_OPTIONAL_PAGE) { /* 32k but no page */ if (slave && !slave->prop.paging_support) return 0; /* no need for else as that will fall-through to paging */ } /* paging mandatory */ if (dev_num == SDW_ENUM_DEV_NUM || dev_num == SDW_BROADCAST_DEV_NUM) { pr_err("SDW: Invalid device for paging :%d\n", dev_num); return -EINVAL; } if (!slave) { pr_err("SDW: No slave for paging addr\n"); return -EINVAL; } if (!slave->prop.paging_support) { dev_err(&slave->dev, "address %x needs paging but no support\n", addr); return -EINVAL; } msg->addr_page1 = FIELD_GET(SDW_SCP_ADDRPAGE1_MASK, addr); msg->addr_page2 = FIELD_GET(SDW_SCP_ADDRPAGE2_MASK, addr); msg->addr |= BIT(15); msg->page = true; return 0; } /* * Read/Write IO functions. */ static int sdw_ntransfer_no_pm(struct sdw_slave *slave, u32 addr, u8 flags, size_t count, u8 *val) { struct sdw_msg msg; size_t size; int ret; while (count) { // Only handle bytes up to next page boundary size = min_t(size_t, count, (SDW_REGADDR + 1) - (addr & SDW_REGADDR)); ret = sdw_fill_msg(&msg, slave, addr, size, slave->dev_num, flags, val); if (ret < 0) return ret; ret = sdw_transfer(slave->bus, &msg); if (ret < 0 && !slave->is_mockup_device) return ret; addr += size; val += size; count -= size; } return 0; } /** * sdw_nread_no_pm() - Read "n" contiguous SDW Slave registers with no PM * @slave: SDW Slave * @addr: Register address * @count: length * @val: Buffer for values to be read * * Note that if the message crosses a page boundary each page will be * transferred under a separate invocation of the msg_lock. */ int sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val) { return sdw_ntransfer_no_pm(slave, addr, SDW_MSG_FLAG_READ, count, val); } EXPORT_SYMBOL(sdw_nread_no_pm); /** * sdw_nwrite_no_pm() - Write "n" contiguous SDW Slave registers with no PM * @slave: SDW Slave * @addr: Register address * @count: length * @val: Buffer for values to be written * * Note that if the message crosses a page boundary each page will be * transferred under a separate invocation of the msg_lock. */ int sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val) { return sdw_ntransfer_no_pm(slave, addr, SDW_MSG_FLAG_WRITE, count, (u8 *)val); } EXPORT_SYMBOL(sdw_nwrite_no_pm); /** * sdw_write_no_pm() - Write a SDW Slave register with no PM * @slave: SDW Slave * @addr: Register address * @value: Register value */ int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value) { return sdw_nwrite_no_pm(slave, addr, 1, &value); } EXPORT_SYMBOL(sdw_write_no_pm); static int sdw_bread_no_pm(struct sdw_bus *bus, u16 dev_num, u32 addr) { struct sdw_msg msg; u8 buf; int ret; ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num, SDW_MSG_FLAG_READ, &buf); if (ret < 0) return ret; ret = sdw_transfer(bus, &msg); if (ret < 0) return ret;