Received: by 2002:a05:6a10:a0d1:0:0:0:0 with SMTP id j17csp3139679pxa; Tue, 18 Aug 2020 07:37:06 -0700 (PDT) X-Google-Smtp-Source: ABdhPJw9wq0+cwFl5srQJDbq/3HtlewzsOK9pO94GBaJ2lBEbZWxUirPlgd1U8+v3tO/Ap9mmKff X-Received: by 2002:a05:6402:22d9:: with SMTP id dm25mr19812271edb.2.1597761425986; Tue, 18 Aug 2020 07:37:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1597761425; cv=none; d=google.com; s=arc-20160816; b=AiIl7YW56Zuwh6Qe2Y9c+mTRfHUFOlnc8q90U8PbKaicY+aHldvA5GQwvsJgnhrdQM o5QjI2BmfWmkoLZ02wv1Usp5uCS2aVaq5rLY+N1P4R4g5MsbyIr3ZGdFT7YVbyq9c0vJ t4uLrGEaMUc+ye2LGYb0W/2ndoBPuYWEtNa0C6eDzqyxKNdfTe8Xu/bNuQ1PJX7HFyhl GogCfKyjuugC5Uuk/jgNhvZVMEFgI5o9M3/CHkJrptJoT61hp1s2BymOiX1o4W0NHYAb vpOWW9i19GEO2rFPjaN/lA3wU9UyU6IP5ctWv7UiHqgbrhkENQj2Ulx+er9SFgRot8S3 E3Qw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:references:in-reply-to:message-id:date :subject:cc:to:from:ironport-sdr:ironport-sdr; bh=6HxABaDIB0hBWDlU61myzu0rQAdvfAG7qsH6VKMKvSk=; b=bb47KDsb0jmbEaSnCX1pZMuqfJTgeUjqob73gjNft0S+P9yR4rQmh3KSpuUhgaFnJe jF79Iqa57wnNNVoTqmv/H/COvdgHhDF7gPcL3lMj/qy/Tpu8SlQVsiDBp2bX4v3qKRYy weowDxrNgLNSg3iYaUihOfs7YXW2BrL5MhaAy7f1JhTU2uP7BgDQZVyt2UMwh6JImJuE ZBNj8W6o5gEM4il2GsCpZcMZh6xSJJJEqTBoMPD9naucWYaF+G6yLaL0ly/4cII4gUyf InaLLVZPxc7WrLFjVkPY4EiXcnof+Vd2Vu4IDMqqoNylYAvVelsysyymw3q4u/YWWxCc AcJg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id u21si14161986edi.143.2020.08.18.07.36.40; Tue, 18 Aug 2020 07:37:05 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727076AbgHROfc (ORCPT + 99 others); Tue, 18 Aug 2020 10:35:32 -0400 Received: from mga14.intel.com ([192.55.52.115]:33372 "EHLO mga14.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1727021AbgHROf2 (ORCPT ); Tue, 18 Aug 2020 10:35:28 -0400 IronPort-SDR: K1RGK9pHmNWDj2C0HwyO58WYaRmd5yGrLSpjbgVZigvoCOgyPw1h0pKwJvVHXdLVDpgjgQlldU R/80KmXbIkYQ== X-IronPort-AV: E=McAfee;i="6000,8403,9716"; a="154170465" X-IronPort-AV: E=Sophos;i="5.76,327,1592895600"; d="scan'208";a="154170465" X-Amp-Result: SKIPPED(no attachment in message) X-Amp-File-Uploaded: False Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga103.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Aug 2020 07:35:27 -0700 IronPort-SDR: MTYXaxlGYh36CC0VKt3NI3NM3kfNAefenASRMLwGCn6FfnXsaHIGulzU5aE9dXDn0JpkS+VLat nDj+DYV/YRAg== X-IronPort-AV: E=Sophos;i="5.76,327,1592895600"; d="scan'208";a="471830419" Received: from bard-ubuntu.sh.intel.com ([10.239.13.33]) by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 Aug 2020 07:35:22 -0700 From: Bard Liao To: alsa-devel@alsa-project.org, vkoul@kernel.org Cc: vinod.koul@linaro.org, linux-kernel@vger.kernel.org, tiwai@suse.de, broonie@kernel.org, gregkh@linuxfoundation.org, jank@cadence.com, srinivas.kandagatla@linaro.org, rander.wang@linux.intel.com, ranjani.sridharan@linux.intel.com, hui.wang@canonical.com, pierre-louis.bossart@linux.intel.com, sanyog.r.kale@intel.com, mengdong.lin@intel.com, bard.liao@intel.com Subject: [PATCH 03/11] soundwire: intel: add multi-link support Date: Tue, 18 Aug 2020 10:41:12 +0800 Message-Id: <20200818024120.20721-4-yung-chuan.liao@linux.intel.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200818024120.20721-1-yung-chuan.liao@linux.intel.com> References: <20200818024120.20721-1-yung-chuan.liao@linux.intel.com> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Pierre-Louis Bossart The multi-link support is enabled with a hardware gsync signal connecting all links. All commands and operations which typically are handled on an SSP boundary will be deferred further and enabled across all links with the 'syncGo' sequence. Signed-off-by: Pierre-Louis Bossart Signed-off-by: Bard Liao --- drivers/soundwire/intel.c | 120 ++++++++++++++++++++++++++++++++++---- 1 file changed, 110 insertions(+), 10 deletions(-) diff --git a/drivers/soundwire/intel.c b/drivers/soundwire/intel.c index c9ba706e20c6..a3aa8ab49285 100644 --- a/drivers/soundwire/intel.c +++ b/drivers/soundwire/intel.c @@ -34,6 +34,7 @@ #define SDW_INTEL_MASTER_DISABLE_PM_RUNTIME BIT(0) #define SDW_INTEL_MASTER_DISABLE_CLOCK_STOP BIT(1) #define SDW_INTEL_MASTER_DISABLE_PM_RUNTIME_IDLE BIT(2) +#define SDW_INTEL_MASTER_DISABLE_MULTI_LINK BIT(3) static int md_flags; module_param_named(sdw_md_flags, md_flags, int, 0444); @@ -555,6 +556,19 @@ static int intel_shim_sync_go_unlocked(struct sdw_intel *sdw) return ret; } +static int intel_shim_sync_go(struct sdw_intel *sdw) +{ + int ret; + + mutex_lock(sdw->link_res->shim_lock); + + ret = intel_shim_sync_go_unlocked(sdw); + + mutex_unlock(sdw->link_res->shim_lock); + + return ret; +} + /* * PDI routines */ @@ -1303,10 +1317,7 @@ static int intel_init(struct sdw_intel *sdw) intel_shim_init(sdw, clock_stop); - if (clock_stop) - return 0; - - return sdw_cdns_init(&sdw->cdns); + return 0; } /* @@ -1372,6 +1383,7 @@ int intel_master_startup(struct platform_device *pdev) struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_bus *bus = &cdns->bus; int link_flags; + bool multi_link; u32 clock_stop_quirks; int ret; @@ -1382,7 +1394,16 @@ int intel_master_startup(struct platform_device *pdev) return 0; } - /* Initialize shim, controller and Cadence IP */ + link_flags = md_flags >> (bus->link_id * 8); + multi_link = !(link_flags & SDW_INTEL_MASTER_DISABLE_MULTI_LINK); + if (!multi_link) { + dev_dbg(dev, "Multi-link is disabled\n"); + bus->multi_link = false; + } else { + bus->multi_link = true; + } + + /* Initialize shim, controller */ ret = intel_init(sdw); if (ret) goto err_init; @@ -1401,12 +1422,33 @@ int intel_master_startup(struct platform_device *pdev) goto err_init; } + /* + * follow recommended programming flows to avoid timeouts when + * gsync is enabled + */ + if (multi_link) + intel_shim_sync_arm(sdw); + + ret = sdw_cdns_init(cdns); + if (ret < 0) { + dev_err(dev, "unable to initialize Cadence IP\n"); + goto err_interrupt; + } + ret = sdw_cdns_exit_reset(cdns); if (ret < 0) { dev_err(dev, "unable to exit bus reset sequence\n"); goto err_interrupt; } + if (multi_link) { + ret = intel_shim_sync_go(sdw); + if (ret < 0) { + dev_err(dev, "sync go failed: %d\n", ret); + goto err_interrupt; + } + } + /* Register DAIs */ ret = intel_register_dai(sdw); if (ret) { @@ -1418,7 +1460,6 @@ int intel_master_startup(struct platform_device *pdev) intel_debugfs_init(sdw); /* Enable runtime PM */ - link_flags = md_flags >> (bus->link_id * 8); if (!(link_flags & SDW_INTEL_MASTER_DISABLE_PM_RUNTIME)) { pm_runtime_set_autosuspend_delay(dev, INTEL_MASTER_SUSPEND_DELAY_MS); @@ -1654,6 +1695,7 @@ static int intel_resume(struct device *dev) struct sdw_intel *sdw = cdns_to_intel(cdns); struct sdw_bus *bus = &cdns->bus; int link_flags; + bool multi_link; int ret; if (bus->prop.hw_disabled) { @@ -1662,6 +1704,9 @@ static int intel_resume(struct device *dev) return 0; } + link_flags = md_flags >> (bus->link_id * 8); + multi_link = !(link_flags & SDW_INTEL_MASTER_DISABLE_MULTI_LINK); + if (pm_runtime_suspended(dev)) { dev_dbg(dev, "%s: pm_runtime status was suspended, forcing active\n", __func__); @@ -1672,6 +1717,7 @@ static int intel_resume(struct device *dev) pm_runtime_enable(dev); link_flags = md_flags >> (bus->link_id * 8); + if (!(link_flags & SDW_INTEL_MASTER_DISABLE_PM_RUNTIME_IDLE)) pm_runtime_idle(dev); } @@ -1694,12 +1740,33 @@ static int intel_resume(struct device *dev) return ret; } + /* + * follow recommended programming flows to avoid timeouts when + * gsync is enabled + */ + if (multi_link) + intel_shim_sync_arm(sdw); + + ret = sdw_cdns_init(&sdw->cdns); + if (ret < 0) { + dev_err(dev, "unable to initialize Cadence IP during resume\n"); + return ret; + } + ret = sdw_cdns_exit_reset(cdns); if (ret < 0) { dev_err(dev, "unable to exit bus reset sequence during resume\n"); return ret; } + if (multi_link) { + ret = intel_shim_sync_go(sdw); + if (ret < 0) { + dev_err(dev, "sync go failed during resume\n"); + return ret; + } + } + /* * after system resume, the pm_runtime suspend() may kick in * during the enumeration, before any children device force the @@ -1722,6 +1789,8 @@ static int intel_resume_runtime(struct device *dev) struct sdw_bus *bus = &cdns->bus; u32 clock_stop_quirks; bool clock_stop0; + int link_flags; + bool multi_link; int status; int ret; @@ -1731,6 +1800,9 @@ static int intel_resume_runtime(struct device *dev) return 0; } + link_flags = md_flags >> (bus->link_id * 8); + multi_link = !(link_flags & SDW_INTEL_MASTER_DISABLE_MULTI_LINK); + clock_stop_quirks = sdw->link_res->clock_stop_quirks; if (clock_stop_quirks & SDW_INTEL_CLK_STOP_TEARDOWN) { @@ -1752,11 +1824,32 @@ static int intel_resume_runtime(struct device *dev) return ret; } + /* + * follow recommended programming flows to avoid + * timeouts when gsync is enabled + */ + if (multi_link) + intel_shim_sync_arm(sdw); + + ret = sdw_cdns_init(&sdw->cdns); + if (ret < 0) { + dev_err(dev, "unable to initialize Cadence IP during resume\n"); + return ret; + } + ret = sdw_cdns_exit_reset(cdns); if (ret < 0) { dev_err(dev, "unable to exit bus reset sequence during resume\n"); return ret; } + + if (multi_link) { + ret = intel_shim_sync_go(sdw); + if (ret < 0) { + dev_err(dev, "sync go failed during resume\n"); + return ret; + } + } } else if (clock_stop_quirks & SDW_INTEL_CLK_STOP_BUS_RESET) { ret = intel_init(sdw); if (ret) { @@ -1773,11 +1866,18 @@ static int intel_resume_runtime(struct device *dev) */ clock_stop0 = sdw_cdns_is_clock_stop(&sdw->cdns); - /* - * make sure all Slaves are tagged as UNATTACHED and - * provide reason for reinitialization - */ if (!clock_stop0) { + + /* + * Re-initialize the IP since it was powered-off + */ + sdw_cdns_init(&sdw->cdns); + + /* + * make sure all Slaves are tagged as UNATTACHED and + * provide reason for reinitialization + */ + status = SDW_UNATTACH_REQUEST_MASTER_RESET; sdw_clear_slave_status(bus, status); } -- 2.17.1