Merge tag 'soc-drivers-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc

Pull SoC driver updates from Arnd Bergmann:
 "The driver updates again are all over the place with many minor fixes
  going into platform specific code. The most notable changes are:

   - Support for Microchip pic64gx system controllers
   - Work on cleaning up devicetree bindings for SoC drivers, and
     converting them into the new format
   - Lots of smaller changes for Qualcomm SoC drivers, including support
     for a number of newly supported chips
   - reset controller API cleanups and a new driver for Cix Sky1
   - Reworks of the Tegra PMC and CBB drivers, along with a change to
     how individual Tegra SoCs get selected in Kconfig and BPMP firmware
     driver updates including a refresh of the ABI header to match the
     version used by firmware
   - STM32 updates to the firewall bus driver and support for the debug
     bus through OP-TEE
   - SCMI firmware driver improvements for reliability, in particular
     for dealing with broken firmware interrupts
   - Memory driver updates for Tegra, and a patch to remove the unused
     Baikal T1 driver"

* tag 'soc-drivers-7.1' of git://git.kernel.org/pub/scm/linux/kernel/git/soc/soc: (193 commits)
  firmware: arm_ffa: Use the correct buffer size during RXTX_MAP
  firmware: qcom: scm: Allow QSEECOM on Lenovo IdeaCentre Mini X
  clk: spear: fix resource leak in clk_register_vco_pll()
  reset: rzv2h-usb2phy: Add support for VBUS mux controller registration
  reset: rzv2h-usb2phy: Convert to regmap API
  dt-bindings: reset: renesas,rzv2h-usb2phy: Document RZ/G3E USB2PHY reset
  dt-bindings: reset: renesas,rzv2h-usb2phy: Add '#mux-state-cells' property
  soc: microchip: add mpfs gpio interrupt mux driver
  dt-bindings: soc: microchip: document PolarFire SoC's gpio interrupt mux
  gpio: mpfs: Add interrupt support
  soc: qcom: ubwc: add helpers to get programmable values
  soc: qcom: ubwc: add helper to get min_acc length
  firmware: qcom: scm: Register gunyah watchdog device
  soc: qcom: socinfo: Add SoC ID for SA8650P
  dt-bindings: arm: qcom,ids: Add SoC ID for SA8650P
  firmware: qcom: scm: Allow QSEECOM on Mahua CRD
  soc: qcom: wcnss: simplify allocation of req
  soc: qcom: pd-mapper: Add support for Eliza
  soc: qcom: aoss: compare against normalized cooling state
  soc: qcom: llcc: fix v1 SB syndrome register offset
  ...
This commit is contained in:
Linus Torvalds
2026-04-16 20:34:34 -07:00
148 changed files with 9034 additions and 2647 deletions

View File

@@ -2078,7 +2078,7 @@ static int __init ffa_init(void)
ret = ffa_rxtx_map(virt_to_phys(drv_info->tx_buffer),
virt_to_phys(drv_info->rx_buffer),
rxtx_bufsz / FFA_PAGE_SIZE);
PAGE_ALIGN(rxtx_bufsz) / FFA_PAGE_SIZE);
if (ret) {
pr_err("failed to register FFA RxTx buffers\n");
goto free_pages;

View File

@@ -7,6 +7,7 @@
#define pr_fmt(fmt) "SCMI Notifications BASE - " fmt
#include <linux/math.h>
#include <linux/module.h>
#include <linux/scmi_protocol.h>
@@ -219,8 +220,7 @@ scmi_base_implementation_list_get(const struct scmi_protocol_handle *ph,
}
real_list_sz = t->rx.len - sizeof(u32);
calc_list_sz = (1 + (loop_num_ret - 1) / sizeof(u32)) *
sizeof(u32);
calc_list_sz = round_up(loop_num_ret, sizeof(u32));
if (calc_list_sz != real_list_sz) {
dev_warn(dev,
"Malformed reply - real_sz:%zd calc_sz:%u (loop_num_ret:%d)\n",

View File

@@ -235,6 +235,9 @@ struct scmi_transport_ops {
* to have an execution latency lesser-equal to the threshold
* should be considered for atomic mode operation: such
* decision is finally left up to the SCMI drivers.
* @no_completion_irq: Flag to indicate that this transport has no completion
* interrupt and has to be polled. This is similar to the
* force_polling below, except this is set via DT property.
* @force_polling: Flag to force this whole transport to use SCMI core polling
* mechanism instead of completion interrupts even if available.
* @sync_cmds_completed_on_ret: Flag to indicate that the transport assures
@@ -254,6 +257,7 @@ struct scmi_desc {
int max_msg;
int max_msg_size;
unsigned int atomic_threshold;
bool no_completion_irq;
const bool force_polling;
const bool sync_cmds_completed_on_ret;
const bool atomic_enabled;

View File

@@ -2735,6 +2735,7 @@ static int scmi_chan_setup(struct scmi_info *info, struct device_node *of_node,
cinfo->is_p2a = !tx;
cinfo->rx_timeout_ms = info->desc->max_rx_timeout_ms;
cinfo->max_msg_size = info->desc->max_msg_size;
cinfo->no_completion_irq = info->desc->no_completion_irq;
/* Create a unique name for this transport device */
snprintf(name, 32, "__scmi_transport_device_%s_%02X",
@@ -3150,6 +3151,9 @@ static const struct scmi_desc *scmi_transport_setup(struct device *dev)
if (ret && ret != -EINVAL)
dev_err(dev, "Malformed arm,max-msg DT property.\n");
trans->desc.no_completion_irq = of_property_read_bool(dev->of_node,
"arm,no-completion-irq");
dev_info(dev,
"SCMI max-rx-timeout: %dms / max-msg-size: %dbytes / max-msg: %d\n",
trans->desc.max_rx_timeout_ms, trans->desc.max_msg_size,

View File

@@ -20,10 +20,10 @@
* named as _qn.
*/
#define SCMI_QUIRK(_qn, _blk) \
do { \
({ \
if (static_branch_unlikely(&(scmi_quirk_ ## _qn))) \
(_blk); \
} while (0)
})
void scmi_quirks_initialize(void);
void scmi_quirks_enable(struct device *dev, const char *vend,
@@ -34,10 +34,10 @@ void scmi_quirks_enable(struct device *dev, const char *vend,
#define DECLARE_SCMI_QUIRK(_qn)
/* Force quirks compilation even when SCMI Quirks are disabled */
#define SCMI_QUIRK(_qn, _blk) \
do { \
({ \
if (0) \
(_blk); \
} while (0)
})
static inline void scmi_quirks_initialize(void) { }
static inline void scmi_quirks_enable(struct device *dev, const char *vend,

View File

@@ -699,20 +699,18 @@ static DEFINE_MUTEX(__qcuefi_lock);
static int qcuefi_set_reference(struct qcuefi_client *qcuefi)
{
mutex_lock(&__qcuefi_lock);
guard(mutex)(&__qcuefi_lock);
if (qcuefi && __qcuefi) {
mutex_unlock(&__qcuefi_lock);
if (qcuefi && __qcuefi)
return -EEXIST;
}
__qcuefi = qcuefi;
mutex_unlock(&__qcuefi_lock);
return 0;
}
static struct qcuefi_client *qcuefi_acquire(void)
__acquires(__qcuefi_lock)
{
mutex_lock(&__qcuefi_lock);
if (!__qcuefi) {
@@ -723,6 +721,7 @@ static struct qcuefi_client *qcuefi_acquire(void)
}
static void qcuefi_release(void)
__releases(__qcuefi_lock)
{
mutex_unlock(&__qcuefi_lock);
}

View File

@@ -199,19 +199,18 @@ static int qcom_scm_bw_enable(void)
if (!__scm->path)
return 0;
mutex_lock(&__scm->scm_bw_lock);
guard(mutex)(&__scm->scm_bw_lock);
if (!__scm->scm_vote_count) {
ret = icc_set_bw(__scm->path, 0, UINT_MAX);
if (ret < 0) {
dev_err(__scm->dev, "failed to set bandwidth request\n");
goto err_bw;
return ret;
}
}
__scm->scm_vote_count++;
err_bw:
mutex_unlock(&__scm->scm_bw_lock);
return ret;
return 0;
}
static void qcom_scm_bw_disable(void)
@@ -923,14 +922,13 @@ struct resource_table *qcom_scm_pas_get_rsc_table(struct qcom_scm_pas_context *c
goto free_input_rt;
}
tbl_ptr = kzalloc(size, GFP_KERNEL);
tbl_ptr = kmemdup(output_rt_tzm, size, GFP_KERNEL);
if (!tbl_ptr) {
qcom_tzmem_free(output_rt_tzm);
ret = -ENOMEM;
goto free_input_rt;
}
memcpy(tbl_ptr, output_rt_tzm, size);
*output_rt_size = size;
qcom_tzmem_free(output_rt_tzm);
@@ -2290,15 +2288,18 @@ EXPORT_SYMBOL_GPL(qcom_scm_qseecom_app_send);
*/
static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
{ .compatible = "asus,vivobook-s15" },
{ .compatible = "asus,vivobook-s15-x1p4" },
{ .compatible = "asus,zenbook-a14-ux3407qa" },
{ .compatible = "asus,zenbook-a14-ux3407ra" },
{ .compatible = "dell,inspiron-14-plus-7441" },
{ .compatible = "dell,latitude-7455" },
{ .compatible = "dell,xps13-9345" },
{ .compatible = "ecs,liva-qc710" },
{ .compatible = "hp,elitebook-ultra-g1q" },
{ .compatible = "hp,omnibook-x14" },
{ .compatible = "huawei,gaokun3" },
{ .compatible = "lenovo,flex-5g" },
{ .compatible = "lenovo,ideacentre-mini-01q8x10" },
{ .compatible = "lenovo,thinkbook-16" },
{ .compatible = "lenovo,thinkpad-t14s" },
{ .compatible = "lenovo,thinkpad-x13s", },
@@ -2309,7 +2310,10 @@ static const struct of_device_id qcom_scm_qseecom_allowlist[] __maybe_unused = {
{ .compatible = "microsoft,denali", },
{ .compatible = "microsoft,romulus13", },
{ .compatible = "microsoft,romulus15", },
{ .compatible = "qcom,glymur-crd" },
{ .compatible = "qcom,hamoa-iot-evk" },
{ .compatible = "qcom,mahua-crd" },
{ .compatible = "qcom,purwa-iot-evk" },
{ .compatible = "qcom,sc8180x-primus" },
{ .compatible = "qcom,x1e001de-devkit" },
{ .compatible = "qcom,x1e80100-crd" },
@@ -2467,6 +2471,56 @@ int qcom_scm_qtee_callback_response(phys_addr_t buf, size_t buf_size,
}
EXPORT_SYMBOL(qcom_scm_qtee_callback_response);
static void qcom_scm_gunyah_wdt_free(void *data)
{
struct platform_device *gunyah_wdt_dev = data;
platform_device_unregister(gunyah_wdt_dev);
}
static void qcom_scm_gunyah_wdt_init(struct qcom_scm *scm)
{
struct platform_device *gunyah_wdt_dev;
struct device_node *np;
bool of_wdt_available;
int i;
static const uuid_t gunyah_uuid = UUID_INIT(0xc1d58fcd, 0xa453, 0x5fdb,
0x92, 0x65, 0xce, 0x36,
0x67, 0x3d, 0x5f, 0x14);
static const char * const of_wdt_compatible[] = {
"qcom,kpss-wdt",
"arm,sbsa-gwdt",
};
/* Bail out if we are not running under Gunyah */
if (!IS_ENABLED(CONFIG_HAVE_ARM_SMCCC_DISCOVERY) ||
!arm_smccc_hypervisor_has_uuid(&gunyah_uuid))
return;
/*
* Gunyah emulates either of Qualcomm watchdog or ARM SBSA watchdog on
* newer platforms. Bail out if we find them in the devicetree.
*/
for (i = 0; i < ARRAY_SIZE(of_wdt_compatible); i++) {
np = of_find_compatible_node(NULL, NULL, of_wdt_compatible[i]);
of_wdt_available = of_device_is_available(np);
of_node_put(np);
if (of_wdt_available)
return;
}
gunyah_wdt_dev = platform_device_register_simple("gunyah-wdt", -1,
NULL, 0);
if (IS_ERR(gunyah_wdt_dev)) {
dev_err(scm->dev, "Failed to register Gunyah watchdog device: %ld\n",
PTR_ERR(gunyah_wdt_dev));
return;
}
devm_add_action_or_reset(scm->dev, qcom_scm_gunyah_wdt_free,
gunyah_wdt_dev);
}
static void qcom_scm_qtee_free(void *data)
{
struct platform_device *qtee_dev = data;
@@ -2811,6 +2865,9 @@ static int qcom_scm_probe(struct platform_device *pdev)
/* Initialize the QTEE object interface. */
qcom_scm_qtee_init(scm);
/* Initialize the Gunyah watchdog platform device. */
qcom_scm_gunyah_wdt_init(scm);
return 0;
}

View File

@@ -5,6 +5,7 @@
* Copyright 2025 Linaro Ltd.
*/
#include <linux/array_size.h>
#include <linux/bitfield.h>
#include <linux/firmware/samsung/exynos-acpm-protocol.h>
#include <linux/ktime.h>
@@ -24,12 +25,12 @@ static void acpm_dvfs_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
unsigned int acpm_chan_id, bool response)
{
xfer->acpm_chan_id = acpm_chan_id;
xfer->txcnt = cmdlen;
xfer->txd = cmd;
xfer->txlen = cmdlen;
if (response) {
xfer->rxcnt = cmdlen;
xfer->rxd = cmd;
xfer->rxlen = cmdlen;
}
}
@@ -42,7 +43,7 @@ static void acpm_dvfs_init_set_rate_cmd(u32 cmd[4], unsigned int clk_id,
cmd[3] = ktime_to_ms(ktime_get());
}
int acpm_dvfs_set_rate(const struct acpm_handle *handle,
int acpm_dvfs_set_rate(struct acpm_handle *handle,
unsigned int acpm_chan_id, unsigned int clk_id,
unsigned long rate)
{
@@ -50,7 +51,7 @@ int acpm_dvfs_set_rate(const struct acpm_handle *handle,
u32 cmd[4];
acpm_dvfs_init_set_rate_cmd(cmd, clk_id, rate);
acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, false);
acpm_dvfs_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id, false);
return acpm_do_xfer(handle, &xfer);
}
@@ -62,7 +63,7 @@ static void acpm_dvfs_init_get_rate_cmd(u32 cmd[4], unsigned int clk_id)
cmd[3] = ktime_to_ms(ktime_get());
}
unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
unsigned long acpm_dvfs_get_rate(struct acpm_handle *handle,
unsigned int acpm_chan_id, unsigned int clk_id)
{
struct acpm_xfer xfer;
@@ -70,7 +71,7 @@ unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
int ret;
acpm_dvfs_init_get_rate_cmd(cmd, clk_id);
acpm_dvfs_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id, true);
acpm_dvfs_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id, true);
ret = acpm_do_xfer(handle, &xfer);
if (ret)

View File

@@ -11,10 +11,10 @@
struct acpm_handle;
int acpm_dvfs_set_rate(const struct acpm_handle *handle,
int acpm_dvfs_set_rate(struct acpm_handle *handle,
unsigned int acpm_chan_id, unsigned int id,
unsigned long rate);
unsigned long acpm_dvfs_get_rate(const struct acpm_handle *handle,
unsigned long acpm_dvfs_get_rate(struct acpm_handle *handle,
unsigned int acpm_chan_id,
unsigned int clk_id);

View File

@@ -41,7 +41,7 @@ static const int acpm_pmic_linux_errmap[] = {
[2] = -EACCES, /* Write register can't be accessed or issues to access it. */
};
static int acpm_pmic_to_linux_err(int err)
static int acpm_pmic_to_linux_err(unsigned int err)
{
if (err >= 0 && err < ARRAY_SIZE(acpm_pmic_linux_errmap))
return acpm_pmic_linux_errmap[err];
@@ -63,8 +63,8 @@ static void acpm_pmic_set_xfer(struct acpm_xfer *xfer, u32 *cmd, size_t cmdlen,
{
xfer->txd = cmd;
xfer->rxd = cmd;
xfer->txlen = cmdlen;
xfer->rxlen = cmdlen;
xfer->txcnt = cmdlen;
xfer->rxcnt = cmdlen;
xfer->acpm_chan_id = acpm_chan_id;
}
@@ -77,7 +77,7 @@ static void acpm_pmic_init_read_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan)
cmd[3] = ktime_to_ms(ktime_get());
}
int acpm_pmic_read_reg(const struct acpm_handle *handle,
int acpm_pmic_read_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 *buf)
{
@@ -86,7 +86,7 @@ int acpm_pmic_read_reg(const struct acpm_handle *handle,
int ret;
acpm_pmic_init_read_cmd(cmd, type, reg, chan);
acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -107,7 +107,7 @@ static void acpm_pmic_init_bulk_read_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan,
FIELD_PREP(ACPM_PMIC_VALUE, count);
}
int acpm_pmic_bulk_read(const struct acpm_handle *handle,
int acpm_pmic_bulk_read(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 count, u8 *buf)
{
@@ -119,7 +119,7 @@ int acpm_pmic_bulk_read(const struct acpm_handle *handle,
return -EINVAL;
acpm_pmic_init_bulk_read_cmd(cmd, type, reg, chan, count);
acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -150,7 +150,7 @@ static void acpm_pmic_init_write_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan,
cmd[3] = ktime_to_ms(ktime_get());
}
int acpm_pmic_write_reg(const struct acpm_handle *handle,
int acpm_pmic_write_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 value)
{
@@ -159,7 +159,7 @@ int acpm_pmic_write_reg(const struct acpm_handle *handle,
int ret;
acpm_pmic_init_write_cmd(cmd, type, reg, chan, value);
acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -187,7 +187,7 @@ static void acpm_pmic_init_bulk_write_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan,
}
}
int acpm_pmic_bulk_write(const struct acpm_handle *handle,
int acpm_pmic_bulk_write(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 count, const u8 *buf)
{
@@ -199,7 +199,7 @@ int acpm_pmic_bulk_write(const struct acpm_handle *handle,
return -EINVAL;
acpm_pmic_init_bulk_write_cmd(cmd, type, reg, chan, count, buf);
acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)
@@ -220,7 +220,7 @@ static void acpm_pmic_init_update_cmd(u32 cmd[4], u8 type, u8 reg, u8 chan,
cmd[3] = ktime_to_ms(ktime_get());
}
int acpm_pmic_update_reg(const struct acpm_handle *handle,
int acpm_pmic_update_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 value, u8 mask)
{
@@ -229,7 +229,7 @@ int acpm_pmic_update_reg(const struct acpm_handle *handle,
int ret;
acpm_pmic_init_update_cmd(cmd, type, reg, chan, value, mask);
acpm_pmic_set_xfer(&xfer, cmd, sizeof(cmd), acpm_chan_id);
acpm_pmic_set_xfer(&xfer, cmd, ARRAY_SIZE(cmd), acpm_chan_id);
ret = acpm_do_xfer(handle, &xfer);
if (ret)

View File

@@ -11,19 +11,19 @@
struct acpm_handle;
int acpm_pmic_read_reg(const struct acpm_handle *handle,
int acpm_pmic_read_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 *buf);
int acpm_pmic_bulk_read(const struct acpm_handle *handle,
int acpm_pmic_bulk_read(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 count, u8 *buf);
int acpm_pmic_write_reg(const struct acpm_handle *handle,
int acpm_pmic_write_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 value);
int acpm_pmic_bulk_write(const struct acpm_handle *handle,
int acpm_pmic_bulk_write(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 count, const u8 *buf);
int acpm_pmic_update_reg(const struct acpm_handle *handle,
int acpm_pmic_update_reg(struct acpm_handle *handle,
unsigned int acpm_chan_id, u8 type, u8 reg, u8 chan,
u8 value, u8 mask);
#endif /* __EXYNOS_ACPM_PMIC_H__ */

View File

@@ -205,7 +205,7 @@ static void acpm_get_saved_rx(struct acpm_chan *achan,
rx_seqnum = FIELD_GET(ACPM_PROTOCOL_SEQNUM, rx_data->cmd[0]);
if (rx_seqnum == tx_seqnum) {
memcpy(xfer->rxd, rx_data->cmd, xfer->rxlen);
memcpy(xfer->rxd, rx_data->cmd, xfer->rxcnt * sizeof(*xfer->rxd));
clear_bit(rx_seqnum - 1, achan->bitmap_seqnum);
}
}
@@ -258,8 +258,7 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
if (rx_data->response) {
if (rx_seqnum == tx_seqnum) {
__ioread32_copy(xfer->rxd, addr,
xfer->rxlen / 4);
__ioread32_copy(xfer->rxd, addr, xfer->rxcnt);
rx_set = true;
clear_bit(seqnum, achan->bitmap_seqnum);
} else {
@@ -269,8 +268,7 @@ static int acpm_get_rx(struct acpm_chan *achan, const struct acpm_xfer *xfer)
* clear yet the bitmap. It will be cleared
* after the response is copied to the request.
*/
__ioread32_copy(rx_data->cmd, addr,
xfer->rxlen / 4);
__ioread32_copy(rx_data->cmd, addr, xfer->rxcnt);
}
} else {
clear_bit(seqnum, achan->bitmap_seqnum);
@@ -412,7 +410,7 @@ static int acpm_wait_for_message_response(struct acpm_chan *achan,
*
* Return: 0 on success, -errno otherwise.
*/
int acpm_do_xfer(const struct acpm_handle *handle, const struct acpm_xfer *xfer)
int acpm_do_xfer(struct acpm_handle *handle, const struct acpm_xfer *xfer)
{
struct acpm_info *acpm = handle_to_acpm_info(handle);
struct exynos_mbox_msg msg;
@@ -425,7 +423,9 @@ int acpm_do_xfer(const struct acpm_handle *handle, const struct acpm_xfer *xfer)
achan = &acpm->chans[xfer->acpm_chan_id];
if (!xfer->txd || xfer->txlen > achan->mlen || xfer->rxlen > achan->mlen)
if (!xfer->txd ||
(xfer->txcnt * sizeof(*xfer->txd) > achan->mlen) ||
(xfer->rxcnt * sizeof(*xfer->rxd) > achan->mlen))
return -EINVAL;
if (!achan->poll_completion) {
@@ -448,7 +448,7 @@ int acpm_do_xfer(const struct acpm_handle *handle, const struct acpm_xfer *xfer)
/* Write TX command. */
__iowrite32_copy(achan->tx.base + achan->mlen * tx_front,
xfer->txd, xfer->txlen / 4);
xfer->txd, xfer->txcnt);
/* Advance TX front. */
writel(idx, achan->tx.front);
@@ -674,7 +674,7 @@ static int acpm_probe(struct platform_device *pdev)
* acpm_handle_put() - release the handle acquired by acpm_get_by_phandle.
* @handle: Handle acquired by acpm_get_by_phandle.
*/
static void acpm_handle_put(const struct acpm_handle *handle)
static void acpm_handle_put(struct acpm_handle *handle)
{
struct acpm_info *acpm = handle_to_acpm_info(handle);
struct device *dev = acpm->dev;
@@ -700,9 +700,11 @@ static void devm_acpm_release(struct device *dev, void *res)
* @np: ACPM device tree node.
*
* Return: pointer to handle on success, ERR_PTR(-errno) otherwise.
*
* Note: handle CANNOT be pointer to const
*/
static const struct acpm_handle *acpm_get_by_node(struct device *dev,
struct device_node *np)
static struct acpm_handle *acpm_get_by_node(struct device *dev,
struct device_node *np)
{
struct platform_device *pdev;
struct device_link *link;
@@ -743,10 +745,10 @@ static const struct acpm_handle *acpm_get_by_node(struct device *dev,
*
* Return: pointer to handle on success, ERR_PTR(-errno) otherwise.
*/
const struct acpm_handle *devm_acpm_get_by_node(struct device *dev,
struct device_node *np)
struct acpm_handle *devm_acpm_get_by_node(struct device *dev,
struct device_node *np)
{
const struct acpm_handle **ptr, *handle;
struct acpm_handle **ptr, *handle;
ptr = devres_alloc(devm_acpm_release, sizeof(*ptr), GFP_KERNEL);
if (!ptr)

View File

@@ -8,16 +8,16 @@
#define __EXYNOS_ACPM_H__
struct acpm_xfer {
const u32 *txd;
u32 *rxd;
size_t txlen;
size_t rxlen;
const u32 *txd __counted_by_ptr(txcnt);
u32 *rxd __counted_by_ptr(rxcnt);
size_t txcnt;
size_t rxcnt;
unsigned int acpm_chan_id;
};
struct acpm_handle;
int acpm_do_xfer(const struct acpm_handle *handle,
int acpm_do_xfer(struct acpm_handle *handle,
const struct acpm_xfer *xfer);
#endif /* __EXYNOS_ACPM_H__ */

View File

@@ -32,6 +32,40 @@ channel_to_ops(struct tegra_bpmp_channel *channel)
return bpmp->soc->ops;
}
struct tegra_bpmp *tegra_bpmp_get_with_id(struct device *dev, unsigned int *id)
{
struct platform_device *pdev;
struct of_phandle_args args;
struct tegra_bpmp *bpmp;
int err;
err = __of_parse_phandle_with_args(dev->of_node, "nvidia,bpmp", NULL,
1, 0, &args);
if (err < 0)
return ERR_PTR(err);
pdev = of_find_device_by_node(args.np);
if (!pdev) {
bpmp = ERR_PTR(-ENODEV);
goto put;
}
bpmp = platform_get_drvdata(pdev);
if (!bpmp) {
bpmp = ERR_PTR(-EPROBE_DEFER);
put_device(&pdev->dev);
goto put;
}
if (id)
*id = args.args[0];
put:
of_node_put(args.np);
return bpmp;
}
EXPORT_SYMBOL_GPL(tegra_bpmp_get_with_id);
struct tegra_bpmp *tegra_bpmp_get(struct device *dev)
{
struct platform_device *pdev;