diff options
Diffstat (limited to 'drivers/soundwire/bus.c')
| -rw-r--r-- | drivers/soundwire/bus.c | 100 | 
1 files changed, 75 insertions, 25 deletions
| diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c index 46885429928a..a9e0aa72654d 100644 --- a/drivers/soundwire/bus.c +++ b/drivers/soundwire/bus.c @@ -44,13 +44,13 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,  	}  	ret = sdw_get_id(bus); -	if (ret) { +	if (ret < 0) {  		dev_err(parent, "Failed to get bus id\n");  		return ret;  	}  	ret = sdw_master_device_add(bus, parent, fwnode); -	if (ret) { +	if (ret < 0) {  		dev_err(parent, "Failed to add master device at link %d\n",  			bus->link_id);  		return ret; @@ -121,7 +121,7 @@ int sdw_bus_master_add(struct sdw_bus *bus, struct device *parent,  	else  		ret = -ENOTSUPP; /* No ACPI/DT so error out */ -	if (ret) { +	if (ret < 0) {  		dev_err(bus->dev, "Finding slaves failed:%d\n", ret);  		return ret;  	} @@ -422,7 +422,7 @@ sdw_bread_no_pm(struct sdw_bus *bus, u16 dev_num, u32 addr)  	ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num,  			   SDW_MSG_FLAG_READ, &buf); -	if (ret) +	if (ret < 0)  		return ret;  	ret = sdw_transfer(bus, &msg); @@ -440,7 +440,7 @@ sdw_bwrite_no_pm(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 value)  	ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num,  			   SDW_MSG_FLAG_WRITE, &value); -	if (ret) +	if (ret < 0)  		return ret;  	return sdw_transfer(bus, &msg); @@ -454,7 +454,7 @@ int sdw_bread_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr)  	ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num,  			   SDW_MSG_FLAG_READ, &buf); -	if (ret) +	if (ret < 0)  		return ret;  	ret = sdw_transfer_unlocked(bus, &msg); @@ -472,7 +472,7 @@ int sdw_bwrite_no_pm_unlocked(struct sdw_bus *bus, u16 dev_num, u32 addr, u8 val  	ret = sdw_fill_msg(&msg, NULL, addr, 1, dev_num,  			   SDW_MSG_FLAG_WRITE, &value); -	if (ret) +	if (ret < 0)  		return ret;  	return sdw_transfer_unlocked(bus, &msg); @@ -593,7 +593,7 @@ EXPORT_SYMBOL(sdw_write);  /* called with bus_lock held */  static struct sdw_slave *sdw_get_slave(struct sdw_bus *bus, int i)  { -	struct sdw_slave *slave = NULL; +	struct sdw_slave *slave;  	list_for_each_entry(slave, &bus->slaves, node) {  		if (slave->dev_num == i) @@ -603,7 +603,7 @@ static struct sdw_slave *sdw_get_slave(struct sdw_bus *bus, int i)  	return NULL;  } -static int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id) +int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id)  {  	if (slave->id.mfg_id != id.mfg_id ||  	    slave->id.part_id != id.part_id || @@ -614,6 +614,7 @@ static int sdw_compare_devid(struct sdw_slave *slave, struct sdw_slave_id id)  	return 0;  } +EXPORT_SYMBOL(sdw_compare_devid);  /* called with bus_lock held */  static int sdw_get_device_num(struct sdw_slave *slave) @@ -698,6 +699,7 @@ void sdw_extract_slave_id(struct sdw_bus *bus,  		"SDW Slave class_id 0x%02x, mfg_id 0x%04x, part_id 0x%04x, unique_id 0x%x, version 0x%x\n",  		id->class_id, id->mfg_id, id->part_id, id->unique_id, id->sdw_version);  } +EXPORT_SYMBOL(sdw_extract_slave_id);  static int sdw_program_device_num(struct sdw_bus *bus)  { @@ -705,7 +707,7 @@ static int sdw_program_device_num(struct sdw_bus *bus)  	struct sdw_slave *slave, *_s;  	struct sdw_slave_id id;  	struct sdw_msg msg; -	bool found = false; +	bool found;  	int count = 0, ret;  	u64 addr; @@ -737,6 +739,7 @@ static int sdw_program_device_num(struct sdw_bus *bus)  		sdw_extract_slave_id(bus, addr, &id); +		found = false;  		/* Now compare with entries */  		list_for_each_entry_safe(slave, _s, &bus->slaves, node) {  			if (sdw_compare_devid(slave, id) == 0) { @@ -749,7 +752,7 @@ static int sdw_program_device_num(struct sdw_bus *bus)  				 * dev_num  				 */  				ret = sdw_assign_device_num(slave); -				if (ret) { +				if (ret < 0) {  					dev_err(bus->dev,  						"Assign dev_num failed:%d\n",  						ret); @@ -875,14 +878,18 @@ static int sdw_slave_clk_stop_prepare(struct sdw_slave *slave,  		if (wake_en)  			val |= SDW_SCP_SYSTEMCTRL_WAKE_UP_EN;  	} else { -		val = sdw_read_no_pm(slave, SDW_SCP_SYSTEMCTRL); - +		ret = sdw_read_no_pm(slave, SDW_SCP_SYSTEMCTRL); +		if (ret < 0) { +			dev_err(&slave->dev, "SDW_SCP_SYSTEMCTRL read failed:%d\n", ret); +			return ret; +		} +		val = ret;  		val &= ~(SDW_SCP_SYSTEMCTRL_CLK_STP_PREP);  	}  	ret = sdw_write_no_pm(slave, SDW_SCP_SYSTEMCTRL, val); -	if (ret != 0) +	if (ret < 0)  		dev_err(&slave->dev,  			"Clock Stop prepare failed for slave: %d", ret); @@ -895,11 +902,15 @@ static int sdw_bus_wait_for_clk_prep_deprep(struct sdw_bus *bus, u16 dev_num)  	int val;  	do { -		val = sdw_bread_no_pm(bus, dev_num, SDW_SCP_STAT) & -			SDW_SCP_STAT_CLK_STP_NF; +		val = sdw_bread_no_pm(bus, dev_num, SDW_SCP_STAT); +		if (val < 0) { +			dev_err(bus->dev, "SDW_SCP_STAT bread failed:%d\n", val); +			return val; +		} +		val &= SDW_SCP_STAT_CLK_STP_NF;  		if (!val) { -			dev_info(bus->dev, "clock stop prep/de-prep done slave:%d", -				 dev_num); +			dev_dbg(bus->dev, "clock stop prep/de-prep done slave:%d", +				dev_num);  			return 0;  		} @@ -1253,6 +1264,7 @@ static int sdw_slave_set_frequency(struct sdw_slave *slave)  static int sdw_initialize_slave(struct sdw_slave *slave)  {  	struct sdw_slave_prop *prop = &slave->prop; +	int status;  	int ret;  	u8 val; @@ -1260,6 +1272,44 @@ static int sdw_initialize_slave(struct sdw_slave *slave)  	if (ret < 0)  		return ret; +	if (slave->bus->prop.quirks & SDW_MASTER_QUIRKS_CLEAR_INITIAL_CLASH) { +		/* Clear bus clash interrupt before enabling interrupt mask */ +		status = sdw_read_no_pm(slave, SDW_SCP_INT1); +		if (status < 0) { +			dev_err(&slave->dev, +				"SDW_SCP_INT1 (BUS_CLASH) read failed:%d\n", status); +			return status; +		} +		if (status & SDW_SCP_INT1_BUS_CLASH) { +			dev_warn(&slave->dev, "Bus clash detected before INT mask is enabled\n"); +			ret = sdw_write_no_pm(slave, SDW_SCP_INT1, SDW_SCP_INT1_BUS_CLASH); +			if (ret < 0) { +				dev_err(&slave->dev, +					"SDW_SCP_INT1 (BUS_CLASH) write failed:%d\n", ret); +				return ret; +			} +		} +	} +	if ((slave->bus->prop.quirks & SDW_MASTER_QUIRKS_CLEAR_INITIAL_PARITY) && +	    !(slave->prop.quirks & SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY)) { +		/* Clear parity interrupt before enabling interrupt mask */ +		status = sdw_read_no_pm(slave, SDW_SCP_INT1); +		if (status < 0) { +			dev_err(&slave->dev, +				"SDW_SCP_INT1 (PARITY) read failed:%d\n", status); +			return status; +		} +		if (status & SDW_SCP_INT1_PARITY) { +			dev_warn(&slave->dev, "PARITY error detected before INT mask is enabled\n"); +			ret = sdw_write_no_pm(slave, SDW_SCP_INT1, SDW_SCP_INT1_PARITY); +			if (ret < 0) { +				dev_err(&slave->dev, +					"SDW_SCP_INT1 (PARITY) write failed:%d\n", ret); +				return ret; +			} +		} +	} +  	/*  	 * Set SCP_INT1_MASK register, typically bus clash and  	 * implementation-defined interrupt mask. The Parity detection @@ -1589,7 +1639,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)  		ret = sdw_read_no_pm(slave, SDW_SCP_INT1);  		if (ret < 0) {  			dev_err(&slave->dev, -				"SDW_SCP_INT1 read failed:%d\n", ret); +				"SDW_SCP_INT1 recheck read failed:%d\n", ret);  			goto io_err;  		}  		_buf = ret; @@ -1597,7 +1647,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)  		ret = sdw_nread_no_pm(slave, SDW_SCP_INTSTAT2, 2, _buf2);  		if (ret < 0) {  			dev_err(&slave->dev, -				"SDW_SCP_INT2/3 read failed:%d\n", ret); +				"SDW_SCP_INT2/3 recheck read failed:%d\n", ret);  			goto io_err;  		} @@ -1605,7 +1655,7 @@ static int sdw_handle_slave_alerts(struct sdw_slave *slave)  			ret = sdw_read_no_pm(slave, SDW_DP0_INT);  			if (ret < 0) {  				dev_err(&slave->dev, -					"SDW_DP0_INT read failed:%d\n", ret); +					"SDW_DP0_INT recheck read failed:%d\n", ret);  				goto io_err;  			}  			sdca_cascade = ret & SDW_DP0_SDCA_CASCADE; @@ -1701,7 +1751,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus,  	if (status[0] == SDW_SLAVE_ATTACHED) {  		dev_dbg(bus->dev, "Slave attached, programming device number\n");  		ret = sdw_program_device_num(bus); -		if (ret) +		if (ret < 0)  			dev_err(bus->dev, "Slave attach failed: %d\n", ret);  		/*  		 * programming a device number will have side effects, @@ -1735,7 +1785,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus,  		case SDW_SLAVE_ALERT:  			ret = sdw_handle_slave_alerts(slave); -			if (ret) +			if (ret < 0)  				dev_err(&slave->dev,  					"Slave %d alert handling failed: %d\n",  					i, ret); @@ -1754,7 +1804,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus,  			attached_initializing = true;  			ret = sdw_initialize_slave(slave); -			if (ret) +			if (ret < 0)  				dev_err(&slave->dev,  					"Slave %d initialization failed: %d\n",  					i, ret); @@ -1768,7 +1818,7 @@ int sdw_handle_slave_status(struct sdw_bus *bus,  		}  		ret = sdw_update_slave_status(slave, status[i]); -		if (ret) +		if (ret < 0)  			dev_err(&slave->dev,  				"Update Slave status failed:%d\n", ret);  		if (attached_initializing) { | 
