Commit 4c9818d8 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull soundwire updates from Vinod Koul:
 "This features AMD soundwire controller driver, a bunch of Intel
  changes for future platform support, sdw API updates etc:

   - Support for AMD soundwire controller

   - Intel driver updates to support future platforms

   - Core API sdw_nread/nwrite_no_pm updates to handle page boundaries"

* tag 'soundwire-6.4-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire: (38 commits)
  soundwire: intel_auxdevice: improve pm_prepare step
  soundwire: bus: Fix unbalanced pm_runtime_put() causing usage count underflow
  soundwire: intel: don't save hw_params for use in prepare
  soundwire: bus: Update sdw_nread/nwrite_no_pm to handle page boundaries
  soundwire: bus: Update kernel doc for no_pm functions
  soundwire: bus: Remove now outdated comments on no_pm IO
  soundwire: stream: uniquify dev_err() logs
  soundwire: stream: remove bus->dev from logs on multiple buses
  soundwire: amd: add pm_prepare callback and pm ops support
  soundwire: amd: handle SoundWire wake enable interrupt
  soundwire: amd: add runtime pm ops for AMD SoundWire manager driver
  soundwire: amd: add SoundWire manager interrupt handling
  soundwire: amd: enable build for AMD SoundWire manager driver
  soundwire: amd: register SoundWire manager dai ops
  soundwire: amd: Add support for AMD Manager driver
  soundwire: export sdw_compute_slave_ports() function
  soundwire: stream: restore cumulative bus bandwidth when compute_params callback failed
  soundwire: bandwidth allocation: Use hweight32() to calculate set bits
  soundwire: qcom: gracefully handle too many ports in DT
  soundwire: qcom: define hardcoded version magic numbers
  ...
parents 54bdf8a3 67572c8d
Loading
Loading
Loading
Loading
+10 −0
Original line number Diff line number Diff line
@@ -18,6 +18,16 @@ if SOUNDWIRE

comment "SoundWire Devices"

config SOUNDWIRE_AMD
	tristate "AMD SoundWire Manager driver"
	select SOUNDWIRE_GENERIC_ALLOCATION
	depends on ACPI && SND_SOC
	help
	  SoundWire AMD Manager driver.
	  If you have an AMD platform which has a SoundWire Manager then
	  enable this config option to get the SoundWire support for that
	  device.

config SOUNDWIRE_CADENCE
	tristate

+6 −1
Original line number Diff line number Diff line
@@ -15,12 +15,17 @@ ifdef CONFIG_DEBUG_FS
soundwire-bus-y += debugfs.o
endif

#AMD driver
soundwire-amd-y :=	amd_manager.o
obj-$(CONFIG_SOUNDWIRE_AMD) += soundwire-amd.o

#Cadence Objs
soundwire-cadence-y := cadence_master.o
obj-$(CONFIG_SOUNDWIRE_CADENCE) += soundwire-cadence.o

#Intel driver
soundwire-intel-y :=	intel.o intel_auxdevice.o intel_init.o dmi-quirks.o
soundwire-intel-y :=	intel.o intel_auxdevice.o intel_init.o dmi-quirks.o \
			intel_bus_common.o
obj-$(CONFIG_SOUNDWIRE_INTEL) += soundwire-intel.o

#Qualcomm driver
+1208 −0

File added.

Preview size limit exceeded, changes collapsed.

+258 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (C) 2023 Advanced Micro Devices, Inc. All rights reserved.
 */

#ifndef __AMD_MANAGER_H
#define __AMD_MANAGER_H

#include <linux/soundwire/sdw_amd.h>

#define SDW_MANAGER_REG_OFFSET				0xc00
#define AMD_SDW_DEFAULT_ROWS				50
#define AMD_SDW_DEFAULT_COLUMNS				10
#define ACP_PAD_PULLDOWN_CTRL				0x0001448
#define ACP_SW_PAD_KEEPER_EN				0x0001454
#define ACP_SW0_WAKE_EN					0x0001458
#define ACP_EXTERNAL_INTR_CNTL0				0x0001a04
#define ACP_EXTERNAL_INTR_STAT0				0x0001a0c
#define ACP_EXTERNAL_INTR_CNTL(i)			(ACP_EXTERNAL_INTR_CNTL0 + ((i) * 4))
#define ACP_EXTERNAL_INTR_STAT(i)			(ACP_EXTERNAL_INTR_STAT0 + ((i) * 4))
#define ACP_SW_WAKE_EN(i)				(ACP_SW0_WAKE_EN + ((i) * 8))

#define ACP_SW_EN					0x0003000
#define ACP_SW_EN_STATUS				0x0003004
#define ACP_SW_FRAMESIZE				0x0003008
#define ACP_SW_SSP_COUNTER				0x000300c
#define ACP_SW_AUDIO0_TX_EN				0x0003010
#define ACP_SW_AUDIO0_TX_EN_STATUS			0x0003014
#define ACP_SW_AUDIO0_TX_FRAME_FORMAT			0x0003018
#define ACP_SW_AUDIO0_TX_SAMPLEINTERVAL			0x000301c
#define ACP_SW_AUDIO0_TX_HCTRL_DP0			0x0003020
#define ACP_SW_AUDIO0_TX_HCTRL_DP1			0x0003024
#define ACP_SW_AUDIO0_TX_HCTRL_DP2			0x0003028
#define ACP_SW_AUDIO0_TX_HCTRL_DP3			0x000302c
#define ACP_SW_AUDIO0_TX_OFFSET_DP0			0x0003030
#define ACP_SW_AUDIO0_TX_OFFSET_DP1			0x0003034
#define ACP_SW_AUDIO0_TX_OFFSET_DP2			0x0003038
#define ACP_SW_AUDIO0_TX_OFFSET_DP3			0x000303c
#define ACP_SW_AUDIO0_TX_CHANNEL_ENABLE_DP0		0x0003040
#define ACP_SW_AUDIO0_TX_CHANNEL_ENABLE_DP1		0x0003044
#define ACP_SW_AUDIO0_TX_CHANNEL_ENABLE_DP2		0x0003048
#define ACP_SW_AUDIO0_TX_CHANNEL_ENABLE_DP3		0x000304c
#define ACP_SW_AUDIO1_TX_EN				0x0003050
#define ACP_SW_AUDIO1_TX_EN_STATUS			0x0003054
#define ACP_SW_AUDIO1_TX_FRAME_FORMAT			0x0003058
#define ACP_SW_AUDIO1_TX_SAMPLEINTERVAL			0x000305c
#define ACP_SW_AUDIO1_TX_HCTRL				0x0003060
#define ACP_SW_AUDIO1_TX_OFFSET				0x0003064
#define ACP_SW_AUDIO1_TX_CHANNEL_ENABLE_DP0		0x0003068
#define ACP_SW_AUDIO2_TX_EN				0x000306c
#define ACP_SW_AUDIO2_TX_EN_STATUS			0x0003070
#define ACP_SW_AUDIO2_TX_FRAME_FORMAT			0x0003074
#define ACP_SW_AUDIO2_TX_SAMPLEINTERVAL			0x0003078
#define ACP_SW_AUDIO2_TX_HCTRL				0x000307c
#define ACP_SW_AUDIO2_TX_OFFSET				0x0003080
#define ACP_SW_AUDIO2_TX_CHANNEL_ENABLE_DP0		0x0003084
#define ACP_SW_AUDIO0_RX_EN				0x0003088
#define ACP_SW_AUDIO0_RX_EN_STATUS			0x000308c
#define ACP_SW_AUDIO0_RX_FRAME_FORMAT			0x0003090
#define ACP_SW_AUDIO0_RX_SAMPLEINTERVAL			0x0003094
#define ACP_SW_AUDIO0_RX_HCTRL_DP0			0x0003098
#define ACP_SW_AUDIO0_RX_HCTRL_DP1			0x000309c
#define ACP_SW_AUDIO0_RX_HCTRL_DP2			0x0003100
#define ACP_SW_AUDIO0_RX_HCTRL_DP3			0x0003104
#define ACP_SW_AUDIO0_RX_OFFSET_DP0			0x0003108
#define ACP_SW_AUDIO0_RX_OFFSET_DP1			0x000310c
#define ACP_SW_AUDIO0_RX_OFFSET_DP2			0x0003110
#define ACP_SW_AUDIO0_RX_OFFSET_DP3			0x0003114
#define ACP_SW_AUDIO0_RX_CHANNEL_ENABLE_DP0		0x0003118
#define ACP_SW_AUDIO0_RX_CHANNEL_ENABLE_DP1		0x000311c
#define ACP_SW_AUDIO0_RX_CHANNEL_ENABLE_DP2		0x0003120
#define ACP_SW_AUDIO0_RX_CHANNEL_ENABLE_DP3		0x0003124
#define ACP_SW_AUDIO1_RX_EN				0x0003128
#define ACP_SW_AUDIO1_RX_EN_STATUS			0x000312c
#define ACP_SW_AUDIO1_RX_FRAME_FORMAT			0x0003130
#define ACP_SW_AUDIO1_RX_SAMPLEINTERVAL			0x0003134
#define ACP_SW_AUDIO1_RX_HCTRL				0x0003138
#define ACP_SW_AUDIO1_RX_OFFSET				0x000313c
#define ACP_SW_AUDIO1_RX_CHANNEL_ENABLE_DP0		0x0003140
#define ACP_SW_AUDIO2_RX_EN				0x0003144
#define ACP_SW_AUDIO2_RX_EN_STATUS			0x0003148
#define ACP_SW_AUDIO2_RX_FRAME_FORMAT			0x000314c
#define ACP_SW_AUDIO2_RX_SAMPLEINTERVAL			0x0003150
#define ACP_SW_AUDIO2_RX_HCTRL				0x0003154
#define ACP_SW_AUDIO2_RX_OFFSET				0x0003158
#define ACP_SW_AUDIO2_RX_CHANNEL_ENABLE_DP0		0x000315c
#define ACP_SW_BPT_PORT_EN				0x0003160
#define ACP_SW_BPT_PORT_EN_STATUS			0x0003164
#define ACP_SW_BPT_PORT_FRAME_FORMAT			0x0003168
#define ACP_SW_BPT_PORT_SAMPLEINTERVAL			0x000316c
#define ACP_SW_BPT_PORT_HCTRL				0x0003170
#define ACP_SW_BPT_PORT_OFFSET				0x0003174
#define ACP_SW_BPT_PORT_CHANNEL_ENABLE			0x0003178
#define ACP_SW_BPT_PORT_FIRST_BYTE_ADDR			0x000317c
#define ACP_SW_CLK_RESUME_CTRL				0x0003180
#define ACP_SW_CLK_RESUME_DELAY_CNTR			0x0003184
#define ACP_SW_BUS_RESET_CTRL				0x0003188
#define ACP_SW_PRBS_ERR_STATUS				0x000318c
#define ACP_SW_IMM_CMD_UPPER_WORD			0x0003230
#define ACP_SW_IMM_CMD_LOWER_QWORD			0x0003234
#define ACP_SW_IMM_RESP_UPPER_WORD			0x0003238
#define ACP_SW_IMM_RESP_LOWER_QWORD			0x000323c
#define ACP_SW_IMM_CMD_STS				0x0003240
#define ACP_SW_BRA_BASE_ADDRESS				0x0003244
#define ACP_SW_BRA_TRANSFER_SIZE			0x0003248
#define ACP_SW_BRA_DMA_BUSY				0x000324c
#define ACP_SW_BRA_RESP					0x0003250
#define ACP_SW_BRA_RESP_FRAME_ADDR			0x0003254
#define ACP_SW_BRA_CURRENT_TRANSFER_SIZE		0x0003258
#define ACP_SW_STATE_CHANGE_STATUS_0TO7			0x000325c
#define ACP_SW_STATE_CHANGE_STATUS_8TO11		0x0003260
#define ACP_SW_STATE_CHANGE_STATUS_MASK_0TO7		0x0003264
#define ACP_SW_STATE_CHANGE_STATUS_MASK_8TO11		0x0003268
#define ACP_SW_CLK_FREQUENCY_CTRL			0x000326c
#define ACP_SW_ERROR_INTR_MASK				0x0003270
#define ACP_SW_PHY_TEST_MODE_DATA_OFF			0x0003274

#define ACP_DELAY_US					10
#define AMD_SDW_TIMEOUT					1000
#define AMD_SDW_DEFAULT_CLK_FREQ			12000000

#define AMD_SDW_MCP_RESP_ACK				BIT(0)
#define AMD_SDW_MCP_RESP_NACK				BIT(1)
#define AMD_SDW_MCP_RESP_RDATA				GENMASK(14, 7)

#define AMD_SDW_MCP_CMD_SSP_TAG				BIT(31)
#define AMD_SDW_MCP_CMD_COMMAND				GENMASK(14, 12)
#define AMD_SDW_MCP_CMD_DEV_ADDR			GENMASK(11, 8)
#define AMD_SDW_MCP_CMD_REG_ADDR_HIGH			GENMASK(7, 0)
#define AMD_SDW_MCP_CMD_REG_ADDR_LOW			GENMASK(31, 24)
#define AMD_SDW_MCP_CMD_REG_DATA			GENMASK(14, 7)
#define AMD_SDW_MCP_SLAVE_STAT_0_3			GENMASK(14, 7)
#define AMD_SDW_MCP_SLAVE_STAT_4_11			GENMASK_ULL(39, 24)
#define AMD_SDW_MCP_SLAVE_STATUS_MASK			GENMASK(1, 0)
#define AMD_SDW_MCP_SLAVE_STATUS_BITS			GENMASK(3, 2)
#define AMD_SDW_MCP_SLAVE_STATUS_8TO_11			GENMASK_ULL(15, 0)
#define AMD_SDW_MCP_SLAVE_STATUS_VALID_MASK(x)		BIT(((x) * 4))
#define AMD_SDW_MCP_SLAVE_STAT_SHIFT_MASK(x)		(((x) * 4) + 1)

#define AMD_SDW_MASTER_SUSPEND_DELAY_MS			2000
#define AMD_SDW_QUIRK_MASK_BUS_ENABLE			BIT(0)

#define AMD_SDW_IMM_RES_VALID		1
#define AMD_SDW_IMM_CMD_BUSY		2
#define AMD_SDW_ENABLE			1
#define AMD_SDW_DISABLE			0
#define AMD_SDW_BUS_RESET_CLEAR_REQ	0
#define AMD_SDW_BUS_RESET_REQ		1
#define AMD_SDW_BUS_RESET_DONE		2
#define AMD_SDW_BUS_BASE_FREQ		24000000

#define AMD_SDW0_EXT_INTR_MASK		0x200000
#define AMD_SDW1_EXT_INTR_MASK		4
#define AMD_SDW_IRQ_MASK_0TO7		0x77777777
#define AMD_SDW_IRQ_MASK_8TO11		0x000d7777
#define AMD_SDW_IRQ_ERROR_MASK		0xff
#define AMD_SDW_MAX_FREQ_NUM		1
#define AMD_SDW0_MAX_TX_PORTS		3
#define AMD_SDW0_MAX_RX_PORTS		3
#define AMD_SDW1_MAX_TX_PORTS		1
#define AMD_SDW1_MAX_RX_PORTS		1
#define AMD_SDW0_MAX_DAI		6
#define AMD_SDW1_MAX_DAI		2
#define AMD_SDW_SLAVE_0_ATTACHED	5
#define AMD_SDW_SSP_COUNTER_VAL		3

#define AMD_DPN_FRAME_FMT_PFM				GENMASK(1, 0)
#define AMD_DPN_FRAME_FMT_PDM				GENMASK(3, 2)
#define AMD_DPN_FRAME_FMT_BLK_PKG_MODE			BIT(4)
#define AMD_DPN_FRAME_FMT_BLK_GRP_CTRL			GENMASK(6, 5)
#define AMD_DPN_FRAME_FMT_WORD_LEN			GENMASK(12, 7)
#define AMD_DPN_FRAME_FMT_PCM_OR_PDM			BIT(13)
#define AMD_DPN_HCTRL_HSTOP				GENMASK(3, 0)
#define AMD_DPN_HCTRL_HSTART				GENMASK(7, 4)
#define AMD_DPN_OFFSET_CTRL_1				GENMASK(7, 0)
#define AMD_DPN_OFFSET_CTRL_2				GENMASK(15, 8)
#define AMD_DPN_CH_EN_LCTRL				GENMASK(2, 0)
#define AMD_DPN_CH_EN_CHMASK				GENMASK(10, 3)
#define AMD_SDW_STAT_MAX_RETRY_COUNT			100
#define AMD_SDW0_PAD_PULLDOWN_CTRL_ENABLE_MASK		0x7f9f
#define AMD_SDW1_PAD_PULLDOWN_CTRL_ENABLE_MASK		0x7ffa
#define AMD_SDW0_PAD_PULLDOWN_CTRL_DISABLE_MASK		0x60
#define AMD_SDW1_PAD_PULLDOWN_CTRL_DISABLE_MASK		5
#define AMD_SDW0_PAD_KEEPER_EN_MASK			1
#define AMD_SDW1_PAD_KEEPER_EN_MASK			0x10
#define AMD_SDW0_PAD_KEEPER_DISABLE_MASK		0x1e
#define AMD_SDW1_PAD_KEEPER_DISABLE_MASK		0xf
#define AMD_SDW_PREQ_INTR_STAT				BIT(19)
#define AMD_SDW_CLK_STOP_DONE				1
#define AMD_SDW_CLK_RESUME_REQ				2
#define AMD_SDW_CLK_RESUME_DONE				3
#define AMD_SDW_WAKE_STAT_MASK				BIT(16)

static u32 amd_sdw_freq_tbl[AMD_SDW_MAX_FREQ_NUM] = {
	AMD_SDW_DEFAULT_CLK_FREQ,
};

struct sdw_manager_dp_reg {
	u32 frame_fmt_reg;
	u32 sample_int_reg;
	u32 hctrl_dp0_reg;
	u32 offset_reg;
	u32 lane_ctrl_ch_en_reg;
};

/*
 * SDW0 Manager instance registers  6 CPU DAI (3 TX & 3 RX Ports)
 * whereas SDW1  Manager Instance registers 2 CPU DAI (one TX & one RX port)
 * Below is the CPU DAI <->Manager port number mapping
 * i.e SDW0 Pin0 -> port number 0 -> AUDIO0 TX
 *     SDW0 Pin1 -> Port number 1 -> AUDIO1 TX
 *     SDW0 Pin2 -> Port number 2 -> AUDIO2 TX
 *     SDW0 Pin3 -> port number 3 -> AUDIO0 RX
 *     SDW0 Pin4 -> Port number 4 -> AUDIO1 RX
 *     SDW0 Pin5 -> Port number 5 -> AUDIO2 RX
 *  Whereas for SDW1 instance
 *  SDW1 Pin0 -> port number 0 -> AUDIO1 TX
 *  SDW1 Pin1 -> Port number 1 -> AUDIO1 RX
 *  Same mapping should be used for programming DMA controller registers in SoundWire DMA driver.
 * i.e if AUDIO0 TX channel is selected then we need to use AUDIO0 TX registers for DMA programming
 * in SoundWire DMA driver.
 */

static struct sdw_manager_dp_reg sdw0_manager_dp_reg[AMD_SDW0_MAX_DAI] =  {
	{ACP_SW_AUDIO0_TX_FRAME_FORMAT, ACP_SW_AUDIO0_TX_SAMPLEINTERVAL, ACP_SW_AUDIO0_TX_HCTRL_DP0,
	 ACP_SW_AUDIO0_TX_OFFSET_DP0, ACP_SW_AUDIO0_TX_CHANNEL_ENABLE_DP0},
	{ACP_SW_AUDIO1_TX_FRAME_FORMAT, ACP_SW_AUDIO1_TX_SAMPLEINTERVAL, ACP_SW_AUDIO1_TX_HCTRL,
	 ACP_SW_AUDIO1_TX_OFFSET, ACP_SW_AUDIO1_TX_CHANNEL_ENABLE_DP0},
	{ACP_SW_AUDIO2_TX_FRAME_FORMAT, ACP_SW_AUDIO2_TX_SAMPLEINTERVAL, ACP_SW_AUDIO2_TX_HCTRL,
	 ACP_SW_AUDIO2_TX_OFFSET, ACP_SW_AUDIO2_TX_CHANNEL_ENABLE_DP0},
	{ACP_SW_AUDIO0_RX_FRAME_FORMAT, ACP_SW_AUDIO0_RX_SAMPLEINTERVAL, ACP_SW_AUDIO0_RX_HCTRL_DP0,
	 ACP_SW_AUDIO0_RX_OFFSET_DP0, ACP_SW_AUDIO0_RX_CHANNEL_ENABLE_DP0},
	{ACP_SW_AUDIO1_RX_FRAME_FORMAT, ACP_SW_AUDIO1_RX_SAMPLEINTERVAL, ACP_SW_AUDIO1_RX_HCTRL,
	 ACP_SW_AUDIO1_RX_OFFSET, ACP_SW_AUDIO1_RX_CHANNEL_ENABLE_DP0},
	{ACP_SW_AUDIO2_RX_FRAME_FORMAT, ACP_SW_AUDIO2_RX_SAMPLEINTERVAL, ACP_SW_AUDIO2_RX_HCTRL,
	 ACP_SW_AUDIO2_RX_OFFSET, ACP_SW_AUDIO2_RX_CHANNEL_ENABLE_DP0},
};

static struct sdw_manager_dp_reg sdw1_manager_dp_reg[AMD_SDW1_MAX_DAI] =  {
	{ACP_SW_AUDIO1_TX_FRAME_FORMAT, ACP_SW_AUDIO1_TX_SAMPLEINTERVAL, ACP_SW_AUDIO1_TX_HCTRL,
	 ACP_SW_AUDIO1_TX_OFFSET, ACP_SW_AUDIO1_TX_CHANNEL_ENABLE_DP0},
	{ACP_SW_AUDIO1_RX_FRAME_FORMAT, ACP_SW_AUDIO1_RX_SAMPLEINTERVAL, ACP_SW_AUDIO1_RX_HCTRL,
	 ACP_SW_AUDIO1_RX_OFFSET, ACP_SW_AUDIO1_RX_CHANNEL_ENABLE_DP0}
};

static struct sdw_manager_reg_mask sdw_manager_reg_mask_array[2] =  {
	{
		AMD_SDW0_PAD_KEEPER_EN_MASK,
		AMD_SDW0_PAD_PULLDOWN_CTRL_ENABLE_MASK,
		AMD_SDW0_EXT_INTR_MASK
	},
	{
		AMD_SDW1_PAD_KEEPER_EN_MASK,
		AMD_SDW1_PAD_PULLDOWN_CTRL_ENABLE_MASK,
		AMD_SDW1_EXT_INTR_MASK
	}
};
#endif
+83 −29
Original line number Diff line number Diff line
@@ -384,45 +384,73 @@ int sdw_fill_msg(struct sdw_msg *msg, struct sdw_slave *slave,

/*
 * Read/Write IO functions.
 * no_pm versions can only be called by the bus, e.g. while enumerating or
 * handling suspend-resume sequences.
 * all clients need to use the pm versions
 */

int sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val)
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;

	ret = sdw_fill_msg(&msg, slave, addr, count,
			   slave->dev_num, SDW_MSG_FLAG_READ, val);
	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 (slave->is_mockup_device)
		ret = 0;
		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)
{
	struct sdw_msg msg;
	int ret;

	ret = sdw_fill_msg(&msg, slave, addr, count,
			   slave->dev_num, SDW_MSG_FLAG_WRITE, (u8 *)val);
	if (ret < 0)
		return ret;

	ret = sdw_transfer(slave->bus, &msg);
	if (slave->is_mockup_device)
		ret = 0;
	return ret;
	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);
@@ -495,6 +523,11 @@ int sdw_bwrite_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 val
}
EXPORT_SYMBOL(sdw_bwrite_no_pm_unlocked);

/**
 * sdw_read_no_pm() - Read a SDW Slave register with no PM
 * @slave: SDW Slave
 * @addr: Register address
 */
int sdw_read_no_pm(struct sdw_slave *slave, u32 addr)
{
	u8 buf;
@@ -541,14 +574,21 @@ EXPORT_SYMBOL(sdw_update);
 * @addr: Register address
 * @count: length
 * @val: Buffer for values to be read
 *
 * This version of the function will take a PM reference to the slave
 * device.
 * 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(struct sdw_slave *slave, u32 addr, size_t count, u8 *val)
{
	int ret;

	ret = pm_runtime_resume_and_get(&slave->dev);
	if (ret < 0 && ret != -EACCES)
	ret = pm_runtime_get_sync(&slave->dev);
	if (ret < 0 && ret != -EACCES) {
		pm_runtime_put_noidle(&slave->dev);
		return ret;
	}

	ret = sdw_nread_no_pm(slave, addr, count, val);

@@ -565,14 +605,21 @@ EXPORT_SYMBOL(sdw_nread);
 * @addr: Register address
 * @count: length
 * @val: Buffer for values to be written
 *
 * This version of the function will take a PM reference to the slave
 * device.
 * 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(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val)
{
	int ret;

	ret = pm_runtime_resume_and_get(&slave->dev);
	if (ret < 0 && ret != -EACCES)
	ret = pm_runtime_get_sync(&slave->dev);
	if (ret < 0 && ret != -EACCES) {
		pm_runtime_put_noidle(&slave->dev);
		return ret;
	}

	ret = sdw_nwrite_no_pm(slave, addr, count, val);

@@ -587,6 +634,9 @@ EXPORT_SYMBOL(sdw_nwrite);
 * sdw_read() - Read a SDW Slave register
 * @slave: SDW Slave
 * @addr: Register address
 *
 * This version of the function will take a PM reference to the slave
 * device.
 */
int sdw_read(struct sdw_slave *slave, u32 addr)
{
@@ -606,6 +656,9 @@ EXPORT_SYMBOL(sdw_read);
 * @slave: SDW Slave
 * @addr: Register address
 * @value: Register value
 *
 * This version of the function will take a PM reference to the slave
 * device.
 */
int sdw_write(struct sdw_slave *slave, u32 addr, u8 value)
{
@@ -1541,9 +1594,10 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)

	sdw_modify_slave_status(slave, SDW_SLAVE_ALERT);

	ret = pm_runtime_resume_and_get(&slave->dev);
	ret = pm_runtime_get_sync(&slave->dev);
	if (ret < 0 && ret != -EACCES) {
		dev_err(&slave->dev, "Failed to resume device: %d\n", ret);
		pm_runtime_put_noidle(&slave->dev);
		return ret;
	}

Loading