Commit 595fa4e3 authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull soundwire updates from Vinod Koul:
 "This is a small update which features a bit of core changes and driver
  updates in Intel and cadence driver.

  Core:

   - sdw_transfer_defer() API change to drop an argument

   - Reset page address rework

   - Export sdw_nwrite_no_pm and sdw_nread_no_pm APIs

  Drivers:

   - Cadence and related intel driver updates for FIFO handling and low
     level msg transfers"

* tag 'soundwire-6.3-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/vkoul/soundwire:
  soundwire: cadence: further simplify low-level xfer_msg_defer() callback
  soundwire: cadence: use directly bus sdw_defer structure
  soundwire: bus: remove sdw_defer argument in sdw_transfer_defer()
  soundwire: stream: use consistent pattern for freeing buffers
  soundwire: bus: Remove unused reset_page_addr() callback
  soundwire: bus: Don't zero page registers after every transaction
  soundwire: bus_type: Avoid lockdep assert in sdw_drv_probe()
  soundwire: stream: Move remaining register accesses over to no_pm
  soundwire: debugfs: Switch to sdw_read_no_pm
  soundwire: Provide build stubs for common functions
  soundwire: bus: export sdw_nwrite_no_pm and sdw_nread_no_pm functions
  soundwire: cadence: remove unused sdw_cdns_master_ops declaration
  soundwire: enable optional clock registers for SoundWire 1.2 devices
  ASoC/soundwire: remove is_sdca boolean property
  soundwire: cadence: Drain the RX FIFO after an IO timeout
  soundwire: cadence: Remove wasted space in response_buf
  soundwire: cadence: Don't overflow the command FIFOs
  soundwire: intel: remove DAI startup/shutdown
parents 8ff99ad0 66f95de7
Loading
Loading
Loading
Loading
+16 −40
Original line number Diff line number Diff line
@@ -225,9 +225,9 @@ static inline int do_transfer(struct sdw_bus *bus, struct sdw_msg *msg)
}

static inline int do_transfer_defer(struct sdw_bus *bus,
				    struct sdw_msg *msg,
				    struct sdw_defer *defer)
				    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;
@@ -237,24 +237,7 @@ static inline int do_transfer_defer(struct sdw_bus *bus,
	init_completion(&defer->complete);

	for (i = 0; i <= retry; i++) {
		resp = bus->ops->xfer_msg_defer(bus, msg, defer);
		ret = find_response_code(resp);
		/* if cmd is ok or ignored return */
		if (ret == 0 || ret == -ENODATA)
			return ret;
	}

	return ret;
}

static int sdw_reset_page(struct sdw_bus *bus, u16 dev_num)
{
	int retry = bus->prop.err_threshold;
	enum sdw_command_response resp;
	int ret = 0, i;

	for (i = 0; i <= retry; i++) {
		resp = bus->ops->reset_page_addr(bus, dev_num);
		resp = bus->ops->xfer_msg_defer(bus);
		ret = find_response_code(resp);
		/* if cmd is ok or ignored return */
		if (ret == 0 || ret == -ENODATA)
@@ -275,9 +258,6 @@ static int sdw_transfer_unlocked(struct sdw_bus *bus, struct sdw_msg *msg)
			(msg->flags & SDW_MSG_FLAG_WRITE) ? "write" : "read",
			msg->addr, msg->len);

	if (msg->page)
		sdw_reset_page(bus, msg->dev_num);

	return ret;
}

@@ -335,26 +315,21 @@ 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
 * @defer: Defer block for signal completion
 *
 * Caller needs to hold the msg_lock lock while calling this
 */
int sdw_transfer_defer(struct sdw_bus *bus, struct sdw_msg *msg,
		       struct sdw_defer *defer)
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, defer);
	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);

	if (msg->page)
		sdw_reset_page(bus, msg->dev_num);

	return ret;
}

@@ -414,8 +389,7 @@ int sdw_fill_msg(struct sdw_msg *msg, struct sdw_slave *slave,
 * all clients need to use the pm versions
 */

static int
sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val)
int sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val)
{
	struct sdw_msg msg;
	int ret;
@@ -430,9 +404,9 @@ sdw_nread_no_pm(struct sdw_slave *slave, u32 addr, size_t count, u8 *val)
		ret = 0;
	return ret;
}
EXPORT_SYMBOL(sdw_nread_no_pm);

static int
sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val)
int sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val)
{
	struct sdw_msg msg;
	int ret;
@@ -447,6 +421,7 @@ sdw_nwrite_no_pm(struct sdw_slave *slave, u32 addr, size_t count, const u8 *val)
		ret = 0;
	return ret;
}
EXPORT_SYMBOL(sdw_nwrite_no_pm);

int sdw_write_no_pm(struct sdw_slave *slave, u32 addr, u8 value)
{
@@ -1214,7 +1189,7 @@ int sdw_configure_dpn_intr(struct sdw_slave *slave,
		val &= ~SDW_DPN_INT_PORT_READY;
	}

	ret = sdw_update(slave, addr, (mask | SDW_DPN_INT_PORT_READY), val);
	ret = sdw_update_no_pm(slave, addr, (mask | SDW_DPN_INT_PORT_READY), val);
	if (ret < 0)
		dev_err(&slave->dev,
			"SDW_DPN_INTMASK write failed:%d\n", val);
@@ -1233,10 +1208,11 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave)

	/*
	 * frequency base and scale registers are required for SDCA
	 * devices. They may also be used for 1.2+/non-SDCA devices,
	 * but we will need a DisCo property to cover this case
	 * devices. They may also be used for 1.2+/non-SDCA devices.
	 * Driver can set the property, we will need a DisCo property
	 * to discover this case from platform firmware.
	 */
	if (!slave->id.class_id)
	if (!slave->id.class_id && !slave->prop.clock_reg_supported)
		return 0;

	if (!mclk_freq) {
@@ -1587,7 +1563,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
		goto io_err;
	}

	if (slave->prop.is_sdca) {
	if (slave->id.class_id) {
		ret = sdw_read_no_pm(slave, SDW_DP0_INT);
		if (ret < 0) {
			dev_err(&slave->dev,
@@ -1724,7 +1700,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)
			goto io_err;
		}

		if (slave->prop.is_sdca) {
		if (slave->id.class_id) {
			ret = sdw_read_no_pm(slave, SDW_DP0_INT);
			if (ret < 0) {
				dev_err(&slave->dev,
+1 −2
Original line number Diff line number Diff line
@@ -151,8 +151,7 @@ int sdw_configure_dpn_intr(struct sdw_slave *slave, int port,
			   bool enable, int mask);

int sdw_transfer(struct sdw_bus *bus, struct sdw_msg *msg);
int sdw_transfer_defer(struct sdw_bus *bus, struct sdw_msg *msg,
		       struct sdw_defer *defer);
int sdw_transfer_defer(struct sdw_bus *bus, struct sdw_msg *msg);

#define SDW_READ_INTR_CLEAR_RETRY	10

+3 −6
Original line number Diff line number Diff line
@@ -105,20 +105,19 @@ static int sdw_drv_probe(struct device *dev)
	if (ret)
		return ret;

	mutex_lock(&slave->sdw_dev_lock);

	ret = drv->probe(slave, id);
	if (ret) {
		name = drv->name;
		if (!name)
			name = drv->driver.name;
		mutex_unlock(&slave->sdw_dev_lock);

		dev_err(dev, "Probe of %s failed: %d\n", name, ret);
		dev_pm_domain_detach(dev, false);
		return ret;
	}

	mutex_lock(&slave->sdw_dev_lock);

	/* device is probed so let's read the properties now */
	if (drv->ops && drv->ops->read_prop)
		drv->ops->read_prop(slave);
@@ -167,14 +166,12 @@ static int sdw_drv_remove(struct device *dev)
	int ret = 0;

	mutex_lock(&slave->sdw_dev_lock);

	slave->probed = false;
	mutex_unlock(&slave->sdw_dev_lock);

	if (drv->remove)
		ret = drv->remove(slave);

	mutex_unlock(&slave->sdw_dev_lock);

	dev_pm_domain_detach(dev, false);

	return ret;
+39 −41
Original line number Diff line number Diff line
@@ -127,7 +127,8 @@ MODULE_PARM_DESC(cdns_mcp_int_mask, "Cadence MCP IntMask");

#define CDNS_MCP_CMD_BASE			0x80
#define CDNS_MCP_RESP_BASE			0x80
#define CDNS_MCP_CMD_LEN			0x20
/* FIFO can hold 8 commands */
#define CDNS_MCP_CMD_LEN			8
#define CDNS_MCP_CMD_WORD_LEN			0x4

#define CDNS_MCP_CMD_SSP_TAG			BIT(31)
@@ -554,6 +555,29 @@ cdns_fill_msg_resp(struct sdw_cdns *cdns,
	return SDW_CMD_OK;
}

static void cdns_read_response(struct sdw_cdns *cdns)
{
	u32 num_resp, cmd_base;
	int i;

	/* RX_FIFO_AVAIL can be 2 entries more than the FIFO size */
	BUILD_BUG_ON(ARRAY_SIZE(cdns->response_buf) < CDNS_MCP_CMD_LEN + 2);

	num_resp = cdns_readl(cdns, CDNS_MCP_FIFOSTAT);
	num_resp &= CDNS_MCP_RX_FIFO_AVAIL;
	if (num_resp > ARRAY_SIZE(cdns->response_buf)) {
		dev_warn(cdns->dev, "RX AVAIL %d too long\n", num_resp);
		num_resp = ARRAY_SIZE(cdns->response_buf);
	}

	cmd_base = CDNS_MCP_CMD_BASE;

	for (i = 0; i < num_resp; i++) {
		cdns->response_buf[i] = cdns_readl(cdns, cmd_base);
		cmd_base += CDNS_MCP_CMD_WORD_LEN;
	}
}

static enum sdw_command_response
_cdns_xfer_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int cmd,
	       int offset, int count, bool defer)
@@ -595,6 +619,10 @@ _cdns_xfer_msg(struct sdw_cdns *cdns, struct sdw_msg *msg, int cmd,
		dev_err(cdns->dev, "IO transfer timed out, cmd %d device %d addr %x len %d\n",
			cmd, msg->dev_num, msg->addr, msg->len);
		msg->len = 0;

		/* Drain anything in the RX_FIFO */
		cdns_read_response(cdns);

		return SDW_CMD_TIMEOUT;
	}

@@ -721,10 +749,11 @@ cdns_xfer_msg(struct sdw_bus *bus, struct sdw_msg *msg)
EXPORT_SYMBOL(cdns_xfer_msg);

enum sdw_command_response
cdns_xfer_msg_defer(struct sdw_bus *bus,
		    struct sdw_msg *msg, struct sdw_defer *defer)
cdns_xfer_msg_defer(struct sdw_bus *bus)
{
	struct sdw_cdns *cdns = bus_to_cdns(bus);
	struct sdw_defer *defer = &bus->defer_msg;
	struct sdw_msg *msg = defer->msg;
	int cmd = 0, ret;

	/* for defer only 1 message is supported */
@@ -735,27 +764,10 @@ cdns_xfer_msg_defer(struct sdw_bus *bus,
	if (ret)
		return SDW_CMD_FAIL_OTHER;

	cdns->defer = defer;
	cdns->defer->length = msg->len;

	return _cdns_xfer_msg(cdns, msg, cmd, 0, msg->len, true);
}
EXPORT_SYMBOL(cdns_xfer_msg_defer);

enum sdw_command_response
cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num)
{
	struct sdw_cdns *cdns = bus_to_cdns(bus);
	struct sdw_msg msg;

	/* Create dummy message with valid device number */
	memset(&msg, 0, sizeof(msg));
	msg.dev_num = dev_num;

	return cdns_program_scp_addr(cdns, &msg);
}
EXPORT_SYMBOL(cdns_reset_page_addr);

u32 cdns_read_ping_status(struct sdw_bus *bus)
{
	struct sdw_cdns *cdns = bus_to_cdns(bus);
@@ -768,22 +780,6 @@ EXPORT_SYMBOL(cdns_read_ping_status);
 * IRQ handling
 */

static void cdns_read_response(struct sdw_cdns *cdns)
{
	u32 num_resp, cmd_base;
	int i;

	num_resp = cdns_readl(cdns, CDNS_MCP_FIFOSTAT);
	num_resp &= CDNS_MCP_RX_FIFO_AVAIL;

	cmd_base = CDNS_MCP_CMD_BASE;

	for (i = 0; i < num_resp; i++) {
		cdns->response_buf[i] = cdns_readl(cdns, cmd_base);
		cmd_base += CDNS_MCP_CMD_WORD_LEN;
	}
}

static int cdns_update_slave_status(struct sdw_cdns *cdns,
				    u64 slave_intstat)
{
@@ -881,13 +877,15 @@ irqreturn_t sdw_cdns_irq(int irq, void *dev_id)
		return IRQ_NONE;

	if (int_status & CDNS_MCP_INT_RX_WL) {
		struct sdw_bus *bus = &cdns->bus;
		struct sdw_defer *defer = &bus->defer_msg;

		cdns_read_response(cdns);

		if (cdns->defer) {
			cdns_fill_msg_resp(cdns, cdns->defer->msg,
					   cdns->defer->length, 0);
			complete(&cdns->defer->complete);
			cdns->defer = NULL;
		if (defer && defer->msg) {
			cdns_fill_msg_resp(cdns, defer->msg,
					   defer->length, 0);
			complete(&defer->complete);
		} else {
			complete(&cdns->tx_complete);
		}
+13 −9
Original line number Diff line number Diff line
@@ -8,6 +8,12 @@
#define SDW_CADENCE_GSYNC_KHZ		4 /* 4 kHz */
#define SDW_CADENCE_GSYNC_HZ		(SDW_CADENCE_GSYNC_KHZ * 1000)

/*
 * The Cadence IP supports up to 32 entries in the FIFO, though implementations
 * can configure the IP to have a smaller FIFO.
 */
#define CDNS_MCP_IP_MAX_CMD_LEN		32

/**
 * struct sdw_cdns_pdi: PDI (Physical Data Interface) instance
 *
@@ -103,7 +109,6 @@ struct sdw_cdns_dai_runtime {
 * @instance: instance number
 * @response_buf: SoundWire response buffer
 * @tx_complete: Tx completion
 * @defer: Defer pointer
 * @ports: Data ports
 * @num_ports: Total number of data ports
 * @pcm: PCM streams
@@ -117,9 +122,13 @@ struct sdw_cdns {
	struct sdw_bus bus;
	unsigned int instance;

	u32 response_buf[0x80];
	/*
	 * The datasheet says the RX FIFO AVAIL can be 2 entries more
	 * than the FIFO capacity, so allow for this.
	 */
	u32 response_buf[CDNS_MCP_IP_MAX_CMD_LEN + 2];

	struct completion tx_complete;
	struct sdw_defer *defer;

	struct sdw_cdns_port *ports;
	int num_ports;
@@ -147,7 +156,6 @@ struct sdw_cdns {
/* Exported symbols */

int sdw_cdns_probe(struct sdw_cdns *cdns);
extern struct sdw_master_ops sdw_cdns_master_ops;

irqreturn_t sdw_cdns_irq(int irq, void *dev_id);
irqreturn_t sdw_cdns_thread(int irq, void *dev_id);
@@ -172,15 +180,11 @@ struct sdw_cdns_pdi *sdw_cdns_alloc_pdi(struct sdw_cdns *cdns,
void sdw_cdns_config_stream(struct sdw_cdns *cdns,
			    u32 ch, u32 dir, struct sdw_cdns_pdi *pdi);

enum sdw_command_response
cdns_reset_page_addr(struct sdw_bus *bus, unsigned int dev_num);

enum sdw_command_response
cdns_xfer_msg(struct sdw_bus *bus, struct sdw_msg *msg);

enum sdw_command_response
cdns_xfer_msg_defer(struct sdw_bus *bus,
		    struct sdw_msg *msg, struct sdw_defer *defer);
cdns_xfer_msg_defer(struct sdw_bus *bus);

u32 cdns_read_ping_status(struct sdw_bus *bus);

Loading