Message ID | 1526962900-20683-2-git-send-email-sayalil@codeaurora.org |
---|---|
State | Changes Requested, archived |
Headers | show |
Series | [RFC,1/3] scsi: ufs: set the device reference clock setting | expand |
On Tue, May 22, 2018 at 09:51:38AM +0530, Sayali Lokhande wrote: > From: Subhash Jadavani <subhashj@codeaurora.org> > > UFS host supplies the reference clock to UFS device and UFS device > specification allows host to provide one of the 4 frequencies (19.2 MHz, > 26 MHz, 38.4 MHz, 52 MHz) for reference clock. Host should set the > device reference clock frequency setting in the device based on what > frequency it is supplying to UFS device. > > Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> > [cang@codeaurora.org: Resolved trivial merge conflicts] > Signed-off-by: Can Guo <cang@codeaurora.org> > Signed-off-by: Sayali Lokhande <sayalil@codeaurora.org> > --- > .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 8 +++ > drivers/scsi/ufs/ufs.h | 9 ++++ > drivers/scsi/ufs/ufshcd-pltfrm.c | 20 ++++++++ > drivers/scsi/ufs/ufshcd.c | 60 ++++++++++++++++++++++ > drivers/scsi/ufs/ufshcd.h | 2 + > 5 files changed, 99 insertions(+) > > diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt > index c39dfef..ac94220 100644 > --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt > +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt > @@ -41,6 +41,12 @@ Optional properties: > -lanes-per-direction : number of lanes available per direction - either 1 or 2. > Note that it is assume same number of lanes is used both > directions at once. If not specified, default is 2 lanes per direction. > +- dev-ref-clk-freq : Specify the device reference clock frequency, must be one of the following: > + 0: 19.2 MHz > + 1: 26 MHz > + 2: 38.4 MHz > + 3: 52 MHz > + Defaults to 26 MHz if not specified. You already have "ref_clk", can't you just read its frequency? Rob -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Hi Rob, For UFS provisioning, all we need is ref_clk to be set to 19.2MHz before actual descriptor write happens. So I can actually avoid parsing it via DT and use REF_CLK_FREQ_19_2_MHZ from enum ref_clk_freq (which is already added in my current implementation). Thanks, Sayali -----Original Message----- From: Rob Herring [mailto:robh@kernel.org] Sent: Thursday, May 24, 2018 12:19 AM To: Sayali Lokhande <sayalil@codeaurora.org> Cc: subhashj@codeaurora.org; cang@codeaurora.org; vivek.gautam@codeaurora.org; rnayak@codeaurora.org; vinholikatti@gmail.com; jejb@linux.vnet.ibm.com; martin.petersen@oracle.com; asutoshd@codeaurora.org; linux-scsi@vger.kernel.org; Mark Rutland <mark.rutland@arm.com>; Mathieu Malaterre <malat@debian.org>; open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS <devicetree@vger.kernel.org>; open list <linux-kernel@vger.kernel.org> Subject: Re: [PATCH RFC 1/3] scsi: ufs: set the device reference clock setting On Tue, May 22, 2018 at 09:51:38AM +0530, Sayali Lokhande wrote: > From: Subhash Jadavani <subhashj@codeaurora.org> > > UFS host supplies the reference clock to UFS device and UFS device > specification allows host to provide one of the 4 frequencies (19.2 > MHz, > 26 MHz, 38.4 MHz, 52 MHz) for reference clock. Host should set the > device reference clock frequency setting in the device based on what > frequency it is supplying to UFS device. > > Signed-off-by: Subhash Jadavani <subhashj@codeaurora.org> > [cang@codeaurora.org: Resolved trivial merge conflicts] > Signed-off-by: Can Guo <cang@codeaurora.org> > Signed-off-by: Sayali Lokhande <sayalil@codeaurora.org> > --- > .../devicetree/bindings/ufs/ufshcd-pltfrm.txt | 8 +++ > drivers/scsi/ufs/ufs.h | 9 ++++ > drivers/scsi/ufs/ufshcd-pltfrm.c | 20 ++++++++ > drivers/scsi/ufs/ufshcd.c | 60 ++++++++++++++++++++++ > drivers/scsi/ufs/ufshcd.h | 2 + > 5 files changed, 99 insertions(+) > > diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt > b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt > index c39dfef..ac94220 100644 > --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt > +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt > @@ -41,6 +41,12 @@ Optional properties: > -lanes-per-direction : number of lanes available per direction - either 1 or 2. > Note that it is assume same number of lanes is used both > directions at once. If not specified, default is 2 lanes per direction. > +- dev-ref-clk-freq : Specify the device reference clock frequency, must be one of the following: > + 0: 19.2 MHz > + 1: 26 MHz > + 2: 38.4 MHz > + 3: 52 MHz > + Defaults to 26 MHz if not specified. You already have "ref_clk", can't you just read its frequency? Rob -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
diff --git a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt index c39dfef..ac94220 100644 --- a/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt +++ b/Documentation/devicetree/bindings/ufs/ufshcd-pltfrm.txt @@ -41,6 +41,12 @@ Optional properties: -lanes-per-direction : number of lanes available per direction - either 1 or 2. Note that it is assume same number of lanes is used both directions at once. If not specified, default is 2 lanes per direction. +- dev-ref-clk-freq : Specify the device reference clock frequency, must be one of the following: + 0: 19.2 MHz + 1: 26 MHz + 2: 38.4 MHz + 3: 52 MHz + Defaults to 26 MHz if not specified. Note: If above properties are not defined it can be assumed that the supply regulators or clocks are always on. @@ -66,4 +72,6 @@ Example: freq-table-hz = <100000000 200000000>, <0 0>, <0 0>; phys = <&ufsphy1>; phy-names = "ufsphy"; + dev-ref-clk-freq = <0>; /* reference clock freq: 19.2 MHz */ }; + diff --git a/drivers/scsi/ufs/ufs.h b/drivers/scsi/ufs/ufs.h index 14e5bf7..e15deb0 100644 --- a/drivers/scsi/ufs/ufs.h +++ b/drivers/scsi/ufs/ufs.h @@ -378,6 +378,15 @@ enum query_opcode { UPIU_QUERY_OPCODE_TOGGLE_FLAG = 0x8, }; +/* bRefClkFreq attribute values */ +enum ref_clk_freq { + REF_CLK_FREQ_19_2_MHZ = 0x0, + REF_CLK_FREQ_26_MHZ = 0x1, + REF_CLK_FREQ_38_4_MHZ = 0x2, + REF_CLK_FREQ_52_MHZ = 0x3, + REF_CLK_FREQ_MAX = REF_CLK_FREQ_52_MHZ, +}; + /* Query response result code */ enum { QUERY_RESULT_SUCCESS = 0x00, diff --git a/drivers/scsi/ufs/ufshcd-pltfrm.c b/drivers/scsi/ufs/ufshcd-pltfrm.c index e82bde0..b70838b 100644 --- a/drivers/scsi/ufs/ufshcd-pltfrm.c +++ b/drivers/scsi/ufs/ufshcd-pltfrm.c @@ -221,6 +221,24 @@ static int ufshcd_parse_regulator_info(struct ufs_hba *hba) return err; } +static void ufshcd_parse_dev_ref_clk_freq(struct ufs_hba *hba) +{ + struct device *dev = hba->dev; + struct device_node *np = dev->of_node; + int ret; + + if (!np) + return; + + ret = of_property_read_u32(np, "dev-ref-clk-freq", + &hba->dev_ref_clk_freq); + if (ret || + (hba->dev_ref_clk_freq < 0) || + (hba->dev_ref_clk_freq > REF_CLK_FREQ_52_MHZ)) + /* default setting */ + hba->dev_ref_clk_freq = REF_CLK_FREQ_26_MHZ; +} + #ifdef CONFIG_PM /** * ufshcd_pltfrm_suspend - suspend power management function @@ -343,6 +361,8 @@ int ufshcd_pltfrm_init(struct platform_device *pdev, pm_runtime_set_active(&pdev->dev); pm_runtime_enable(&pdev->dev); + ufshcd_parse_dev_ref_clk_freq(hba); + ufshcd_init_lanes_per_dir(hba); err = ufshcd_init(hba, mmio_base, irq); diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c5b1bf1..1ab882f 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6297,6 +6297,61 @@ static void ufshcd_def_desc_sizes(struct ufs_hba *hba) } /** + * ufshcd_set_dev_ref_clk - set the device bRefClkFreq + * @hba: per-adapter instance + * + * Read the current value of the bRefClkFreq attribute from device and update it + * if host is supplying different reference clock frequency than one mentioned + * in bRefClkFreq attribute. + * + * Returns zero on success, non-zero error value on failure. + */ +static int ufshcd_set_dev_ref_clk(struct ufs_hba *hba) +{ + int err = 0; + int ref_clk = -1; + static const char * const ref_clk_freqs[] = {"19.2 MHz", "26 MHz", + "38.4 MHz", "52 MHz"}; + + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_READ_ATTR, + QUERY_ATTR_IDN_REF_CLK_FREQ, 0, 0, &ref_clk); + + if (err) { + dev_err(hba->dev, "%s: failed reading bRefClkFreq. err = %d\n", + __func__, err); + goto out; + } + + if ((ref_clk < 0) || (ref_clk > REF_CLK_FREQ_52_MHZ)) { + dev_err(hba->dev, "%s: invalid ref_clk setting = %d\n", + __func__, ref_clk); + err = -EINVAL; + goto out; + } + + if (ref_clk == hba->dev_ref_clk_freq) + goto out; /* nothing to update */ + + err = ufshcd_query_attr_retry(hba, UPIU_QUERY_OPCODE_WRITE_ATTR, + QUERY_ATTR_IDN_REF_CLK_FREQ, 0, 0, + &hba->dev_ref_clk_freq); + + if (err) + dev_err(hba->dev, "%s: bRefClkFreq setting to %s failed\n", + __func__, ref_clk_freqs[hba->dev_ref_clk_freq]); + else + /* + * It is good to print this out here to debug any later failures + * related to gear switch. + */ + dev_info(hba->dev, "%s: bRefClkFreq setting to %s succeeded\n", + __func__, ref_clk_freqs[hba->dev_ref_clk_freq]); + +out: + return err; +} + +/** * ufshcd_probe_hba - probe hba to detect device and initialize * @hba: per-adapter instance * @@ -6361,6 +6416,11 @@ static int ufshcd_probe_hba(struct ufs_hba *hba) "%s: Failed getting max supported power mode\n", __func__); } else { + /* + * Set the right value to bRefClkFreq before attempting to + * switch to HS gears. + */ + ufshcd_set_dev_ref_clk(hba); ret = ufshcd_config_pwr_mode(hba, &hba->max_pwr_info.info); if (ret) { dev_err(hba->dev, "%s: Failed setting power mode, err = %d\n", diff --git a/drivers/scsi/ufs/ufshcd.h b/drivers/scsi/ufs/ufshcd.h index 8110dcd..0dcf113 100644 --- a/drivers/scsi/ufs/ufshcd.h +++ b/drivers/scsi/ufs/ufshcd.h @@ -549,6 +549,8 @@ struct ufs_hba { unsigned int irq; bool is_irq_enabled; + u32 dev_ref_clk_freq; + /* Interrupt aggregation support is broken */ #define UFSHCD_QUIRK_BROKEN_INTR_AGGR 0x1