diff mbox

[v4,1/2] i2c: qup: add ACPI support

Message ID 1465409985-17113-1-git-send-email-austinwc@codeaurora.org
State Changes Requested
Headers show

Commit Message

Christ, Austin June 8, 2016, 6:19 p.m. UTC
From: Naveen Kaje <nkaje@codeaurora.org>

Add support to get the device parameters from ACPI. Assume
that the clocks are managed by firmware.

Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
Signed-off-by: Austin Christ <austinwc@codeaurora.org>
Reviewed-by: sricharan@codeaurora.org
---
 drivers/i2c/busses/i2c-qup.c | 59 ++++++++++++++++++++++++++++++++------------
 1 file changed, 43 insertions(+), 16 deletions(-)

Changes:
- v4:
 - remove warning for fall back to default clock frequency
- v3:
 - clean up unused variable
- v2:
 - clean up redundant checks and variables

Comments

Arnd Bergmann June 8, 2016, 9:02 p.m. UTC | #1
On Wednesday, June 8, 2016 12:19:44 PM CEST Austin Christ wrote:
> +               ret = device_property_read_u32(qup->dev,
> +                               "src-clock-hz", &src_clk_freq);
> +               if (ret) {
> +                       dev_warn(qup->dev, "using default src-clock-hz %d",
> +                               DEFAULT_SRC_CLK);
> +                       src_clk_freq = DEFAULT_SRC_CLK;
> +               }
> 

Where is this property documented?

	Arnd

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
kernel test robot June 9, 2016, 1:51 p.m. UTC | #2
Hi,

[auto build test ERROR on wsa/i2c/for-next]
[also build test ERROR on v4.7-rc2 next-20160609]
[if your patch is applied to the wrong git tree, please drop us a note to help improve the system]

url:    https://github.com/0day-ci/linux/commits/Austin-Christ/i2c-qup-add-ACPI-support/20160609-022325
base:   https://git.kernel.org/pub/scm/linux/kernel/git/wsa/linux i2c/for-next
config: arm64-allmodconfig (attached as .config)
compiler: aarch64-linux-gnu-gcc (Debian 5.3.1-8) 5.3.1 20160205
reproduce:
        wget https://git.kernel.org/cgit/linux/kernel/git/wfg/lkp-tests.git/plain/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        make.cross ARCH=arm64 

All errors (new ones prefixed by >>):

   In file included from drivers/i2c/busses/i2c-qup.c:27:0:
>> drivers/i2c/busses/i2c-qup.c:1665:27: error: 'qup_i2c_acpi_ids' undeclared here (not in a function)
    MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids);
                              ^
   include/linux/module.h:223:21: note: in definition of macro 'MODULE_DEVICE_TABLE'
    extern const typeof(name) __mod_##type##__##name##_device_table  \
                        ^
   include/linux/module.h:223:27: error: '__mod_acpi__qup_i2c_acpi_ids_device_table' aliased to undefined symbol 'qup_i2c_acpi_ids'
    extern const typeof(name) __mod_##type##__##name##_device_table  \
                              ^
   drivers/i2c/busses/i2c-qup.c:1665:1: note: in expansion of macro 'MODULE_DEVICE_TABLE'
    MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids);
    ^

vim +/qup_i2c_acpi_ids +1665 drivers/i2c/busses/i2c-qup.c

  1659	
  1660	#if IS_ENABLED(CONFIG_ACPI)
  1661	static const struct acpi_device_id qup_i2c_acpi_match[] = {
  1662		{ "QCOM8010"},
  1663		{ },
  1664	};
> 1665	MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids);
  1666	#endif
  1667	
  1668	static struct platform_driver qup_i2c_driver = {

---
0-DAY kernel test infrastructure                Open Source Technology Center
https://lists.01.org/pipermail/kbuild-all                   Intel Corporation
Wolfram Sang June 18, 2016, 2:10 p.m. UTC | #3
On Wed, Jun 08, 2016 at 12:19:44PM -0600, Austin Christ wrote:
> From: Naveen Kaje <nkaje@codeaurora.org>
> 
> Add support to get the device parameters from ACPI. Assume
> that the clocks are managed by firmware.

Adding Mika to CC: Can you have a look at the ACPI binding? Looks ok to
me...

> 
> Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
> Signed-off-by: Austin Christ <austinwc@codeaurora.org>
> Reviewed-by: sricharan@codeaurora.org

Please add a name before the email address

> ---
>  drivers/i2c/busses/i2c-qup.c | 59 ++++++++++++++++++++++++++++++++------------
>  1 file changed, 43 insertions(+), 16 deletions(-)
> 
> Changes:
> - v4:
>  - remove warning for fall back to default clock frequency
> - v3:
>  - clean up unused variable
> - v2:
>  - clean up redundant checks and variables
> 
> diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
> index dddd4da..0f23d58 100644
> --- a/drivers/i2c/busses/i2c-qup.c
> +++ b/drivers/i2c/busses/i2c-qup.c
> @@ -29,6 +29,7 @@
>  #include <linux/platform_device.h>
>  #include <linux/pm_runtime.h>
>  #include <linux/scatterlist.h>
> +#include <linux/acpi.h>

Keep includes sorted.

>  
>  /* QUP Registers */
>  #define QUP_CONFIG		0x000
> @@ -132,6 +133,10 @@
>  /* Max timeout in ms for 32k bytes */
>  #define TOUT_MAX			300
>  
> +/* Default values. Use these if FW query fails */
> +#define DEFAULT_CLK_FREQ 100000
> +#define DEFAULT_SRC_CLK 20000000
> +
>  struct qup_i2c_block {
>  	int	count;
>  	int	pos;
> @@ -1354,14 +1359,13 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
>  static int qup_i2c_probe(struct platform_device *pdev)
>  {
>  	static const int blk_sizes[] = {4, 16, 32};
> -	struct device_node *node = pdev->dev.of_node;
>  	struct qup_i2c_dev *qup;
>  	unsigned long one_bit_t;
>  	struct resource *res;
>  	u32 io_mode, hw_ver, size;
>  	int ret, fs_div, hs_div;
> -	int src_clk_freq;
> -	u32 clk_freq = 100000;
> +	u32 src_clk_freq = 0;
> +	u32 clk_freq = DEFAULT_CLK_FREQ;
>  	int blocks;
>  
>  	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
> @@ -1372,7 +1376,11 @@ static int qup_i2c_probe(struct platform_device *pdev)
>  	init_completion(&qup->xfer);
>  	platform_set_drvdata(pdev, qup);
>  
> -	of_property_read_u32(node, "clock-frequency", &clk_freq);
> +	ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
> +	if (ret) {
> +		dev_notice(qup->dev, "using default clock-frequency %d",
> +			DEFAULT_CLK_FREQ);
> +	}
>  
>  	if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
>  		qup->adap.algo = &qup_i2c_algo;
> @@ -1454,20 +1462,31 @@ nodma:
>  		return qup->irq;
>  	}
>  
> -	qup->clk = devm_clk_get(qup->dev, "core");
> -	if (IS_ERR(qup->clk)) {
> -		dev_err(qup->dev, "Could not get core clock\n");
> -		return PTR_ERR(qup->clk);
> -	}
> +	if (ACPI_HANDLE(qup->dev)) {
> +		ret = device_property_read_u32(qup->dev,
> +				"src-clock-hz", &src_clk_freq);
> +		if (ret) {
> +			dev_warn(qup->dev, "using default src-clock-hz %d",
> +				DEFAULT_SRC_CLK);
> +			src_clk_freq = DEFAULT_SRC_CLK;
> +		}
> +		ACPI_COMPANION_SET(&qup->adap.dev, ACPI_COMPANION(qup->dev));
> +	} else {
> +		qup->clk = devm_clk_get(qup->dev, "core");
> +		if (IS_ERR(qup->clk)) {
> +			dev_err(qup->dev, "Could not get core clock\n");
> +			return PTR_ERR(qup->clk);
> +		}
>  
> -	qup->pclk = devm_clk_get(qup->dev, "iface");
> -	if (IS_ERR(qup->pclk)) {
> -		dev_err(qup->dev, "Could not get iface clock\n");
> -		return PTR_ERR(qup->pclk);
> +		qup->pclk = devm_clk_get(qup->dev, "iface");
> +		if (IS_ERR(qup->pclk)) {
> +			dev_err(qup->dev, "Could not get iface clock\n");
> +			return PTR_ERR(qup->pclk);
> +		}
> +		qup_i2c_enable_clocks(qup);
> +		src_clk_freq = clk_get_rate(qup->clk);
>  	}
>  
> -	qup_i2c_enable_clocks(qup);
> -
>  	/*
>  	 * Bootloaders might leave a pending interrupt on certain QUP's,
>  	 * so we reset the core before registering for interrupts.
> @@ -1514,7 +1533,6 @@ nodma:
>  	size = QUP_INPUT_FIFO_SIZE(io_mode);
>  	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
>  
> -	src_clk_freq = clk_get_rate(qup->clk);
>  	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
>  	hs_div = 3;
>  	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
> @@ -1639,6 +1657,14 @@ static const struct of_device_id qup_i2c_dt_match[] = {
>  };
>  MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
>  
> +#if IS_ENABLED(CONFIG_ACPI)
> +static const struct acpi_device_id qup_i2c_acpi_match[] = {
> +	{ "QCOM8010"},
> +	{ },
> +};
> +MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids);
> +#endif
> +
>  static struct platform_driver qup_i2c_driver = {
>  	.probe  = qup_i2c_probe,
>  	.remove = qup_i2c_remove,
> @@ -1646,6 +1672,7 @@ static struct platform_driver qup_i2c_driver = {
>  		.name = "i2c_qup",
>  		.pm = &qup_i2c_qup_pm_ops,
>  		.of_match_table = qup_i2c_dt_match,
> +		.acpi_match_table = ACPI_PTR(qup_i2c_acpi_match),
>  	},
>  };
>  
> -- 
> Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> a Linux Foundation Collaborative Project.
>
Mika Westerberg June 20, 2016, 8:24 a.m. UTC | #4
On Sat, Jun 18, 2016 at 04:10:34PM +0200, Wolfram Sang wrote:
> On Wed, Jun 08, 2016 at 12:19:44PM -0600, Austin Christ wrote:
> > From: Naveen Kaje <nkaje@codeaurora.org>
> > 
> > Add support to get the device parameters from ACPI. Assume
> > that the clocks are managed by firmware.
> 
> Adding Mika to CC: Can you have a look at the ACPI binding? Looks ok to
> me...
> 
> > 
> > Signed-off-by: Naveen Kaje <nkaje@codeaurora.org>
> > Signed-off-by: Austin Christ <austinwc@codeaurora.org>
> > Reviewed-by: sricharan@codeaurora.org
> 
> Please add a name before the email address
> 
> > ---
> >  drivers/i2c/busses/i2c-qup.c | 59 ++++++++++++++++++++++++++++++++------------
> >  1 file changed, 43 insertions(+), 16 deletions(-)
> > 
> > Changes:
> > - v4:
> >  - remove warning for fall back to default clock frequency
> > - v3:
> >  - clean up unused variable
> > - v2:
> >  - clean up redundant checks and variables
> > 
> > diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
> > index dddd4da..0f23d58 100644
> > --- a/drivers/i2c/busses/i2c-qup.c
> > +++ b/drivers/i2c/busses/i2c-qup.c
> > @@ -29,6 +29,7 @@
> >  #include <linux/platform_device.h>
> >  #include <linux/pm_runtime.h>
> >  #include <linux/scatterlist.h>
> > +#include <linux/acpi.h>
> 
> Keep includes sorted.
> 
> >  
> >  /* QUP Registers */
> >  #define QUP_CONFIG		0x000
> > @@ -132,6 +133,10 @@
> >  /* Max timeout in ms for 32k bytes */
> >  #define TOUT_MAX			300
> >  
> > +/* Default values. Use these if FW query fails */
> > +#define DEFAULT_CLK_FREQ 100000
> > +#define DEFAULT_SRC_CLK 20000000
> > +
> >  struct qup_i2c_block {
> >  	int	count;
> >  	int	pos;
> > @@ -1354,14 +1359,13 @@ static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
> >  static int qup_i2c_probe(struct platform_device *pdev)
> >  {
> >  	static const int blk_sizes[] = {4, 16, 32};
> > -	struct device_node *node = pdev->dev.of_node;
> >  	struct qup_i2c_dev *qup;
> >  	unsigned long one_bit_t;
> >  	struct resource *res;
> >  	u32 io_mode, hw_ver, size;
> >  	int ret, fs_div, hs_div;
> > -	int src_clk_freq;
> > -	u32 clk_freq = 100000;
> > +	u32 src_clk_freq = 0;
> > +	u32 clk_freq = DEFAULT_CLK_FREQ;
> >  	int blocks;
> >  
> >  	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
> > @@ -1372,7 +1376,11 @@ static int qup_i2c_probe(struct platform_device *pdev)
> >  	init_completion(&qup->xfer);
> >  	platform_set_drvdata(pdev, qup);
> >  
> > -	of_property_read_u32(node, "clock-frequency", &clk_freq);
> > +	ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
> > +	if (ret) {
> > +		dev_notice(qup->dev, "using default clock-frequency %d",
> > +			DEFAULT_CLK_FREQ);
> > +	}
> >  
> >  	if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
> >  		qup->adap.algo = &qup_i2c_algo;
> > @@ -1454,20 +1462,31 @@ nodma:
> >  		return qup->irq;
> >  	}
> >  
> > -	qup->clk = devm_clk_get(qup->dev, "core");
> > -	if (IS_ERR(qup->clk)) {
> > -		dev_err(qup->dev, "Could not get core clock\n");
> > -		return PTR_ERR(qup->clk);
> > -	}
> > +	if (ACPI_HANDLE(qup->dev)) {

Use has_acpi_companion() if you need to.

> > +		ret = device_property_read_u32(qup->dev,
> > +				"src-clock-hz", &src_clk_freq);

Alternatively you can make qup_i2c_acpi_probe() which creates clock for
you based on the ACPI ID of the device. Then you do not need to have
these custom properties just because ACPI does not have native support
for clocks.

Ideally if one uses device_property_* API it should not need to
distinguish between DT/ACPI/whatnot.

> > +		if (ret) {
> > +			dev_warn(qup->dev, "using default src-clock-hz %d",
> > +				DEFAULT_SRC_CLK);

Why this is warning?

> > +			src_clk_freq = DEFAULT_SRC_CLK;
> > +		}

> > +		ACPI_COMPANION_SET(&qup->adap.dev, ACPI_COMPANION(qup->dev));
> > +	} else {
> > +		qup->clk = devm_clk_get(qup->dev, "core");
> > +		if (IS_ERR(qup->clk)) {
> > +			dev_err(qup->dev, "Could not get core clock\n");
> > +			return PTR_ERR(qup->clk);
> > +		}
> >  
> > -	qup->pclk = devm_clk_get(qup->dev, "iface");
> > -	if (IS_ERR(qup->pclk)) {
> > -		dev_err(qup->dev, "Could not get iface clock\n");
> > -		return PTR_ERR(qup->pclk);
> > +		qup->pclk = devm_clk_get(qup->dev, "iface");
> > +		if (IS_ERR(qup->pclk)) {
> > +			dev_err(qup->dev, "Could not get iface clock\n");
> > +			return PTR_ERR(qup->pclk);
> > +		}
> > +		qup_i2c_enable_clocks(qup);
> > +		src_clk_freq = clk_get_rate(qup->clk);
> >  	}
> >  
> > -	qup_i2c_enable_clocks(qup);
> > -
> >  	/*
> >  	 * Bootloaders might leave a pending interrupt on certain QUP's,
> >  	 * so we reset the core before registering for interrupts.
> > @@ -1514,7 +1533,6 @@ nodma:
> >  	size = QUP_INPUT_FIFO_SIZE(io_mode);
> >  	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
> >  
> > -	src_clk_freq = clk_get_rate(qup->clk);
> >  	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
> >  	hs_div = 3;
> >  	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
> > @@ -1639,6 +1657,14 @@ static const struct of_device_id qup_i2c_dt_match[] = {
> >  };
> >  MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
> >  
> > +#if IS_ENABLED(CONFIG_ACPI)
> > +static const struct acpi_device_id qup_i2c_acpi_match[] = {
> > +	{ "QCOM8010"},
> > +	{ },
> > +};
> > +MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids);
> > +#endif
> > +
> >  static struct platform_driver qup_i2c_driver = {
> >  	.probe  = qup_i2c_probe,
> >  	.remove = qup_i2c_remove,
> > @@ -1646,6 +1672,7 @@ static struct platform_driver qup_i2c_driver = {
> >  		.name = "i2c_qup",
> >  		.pm = &qup_i2c_qup_pm_ops,
> >  		.of_match_table = qup_i2c_dt_match,
> > +		.acpi_match_table = ACPI_PTR(qup_i2c_acpi_match),
> >  	},
> >  };
> >  
> > -- 
> > Qualcomm Innovation Center, Inc.
> > The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
> > a Linux Foundation Collaborative Project.
> > 


--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Timur Tabi June 20, 2016, 3 p.m. UTC | #5
Mika Westerberg wrote:
> Use has_acpi_companion() if you need to.

Is has_acpi_companion() the preferred alternative to ACPI_HANDLE()?  We 
frequently need to write code that does something different on ACPI vs 
DT, and there doesn't appear to be much consistency on how that's handled.
Mika Westerberg June 20, 2016, 3:07 p.m. UTC | #6
On Mon, Jun 20, 2016 at 10:00:46AM -0500, Timur Tabi wrote:
> Mika Westerberg wrote:
> > Use has_acpi_companion() if you need to.
> 
> Is has_acpi_companion() the preferred alternative to ACPI_HANDLE()?  We
> frequently need to write code that does something different on ACPI vs DT,
> and there doesn't appear to be much consistency on how that's handled.

Yes, that's the preferred one.
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christopher Covington June 30, 2016, 11:35 a.m. UTC | #7
Hi Arnd,

On 06/08/2016 05:02 PM, Arnd Bergmann wrote:
> On Wednesday, June 8, 2016 12:19:44 PM CEST Austin Christ wrote:
>> +               ret = device_property_read_u32(qup->dev,
>> +                               "src-clock-hz", &src_clk_freq);
>> +               if (ret) {
>> +                       dev_warn(qup->dev, "using default src-clock-hz %d",
>> +                               DEFAULT_SRC_CLK);
>> +                       src_clk_freq = DEFAULT_SRC_CLK;
>> +               }
>>
> 
> Where is this property documented?

We plan on submitting documentation via dsd@acpica.org to
https://github.com/ahs3/dsd once it is operational. As I understand it
the project is brand new. It may take several months to begin accepting
submissions. In the mean time, we could potentially include
documentation in a reply to this thread, the cover of the next series, a
wiki page on codeaurora.org, a file in Documentation (perhaps to be
replaced by ACPICA style imports of the OS-neutral DSD project or a git
submodule) or potentially other means. Please let us know what you think
is sufficient.

Thanks,
Cov
Arnd Bergmann June 30, 2016, 11:52 a.m. UTC | #8
On Thursday, June 30, 2016 7:35:14 AM CEST Christopher Covington wrote:
> Hi Arnd,
> 
> On 06/08/2016 05:02 PM, Arnd Bergmann wrote:
> > On Wednesday, June 8, 2016 12:19:44 PM CEST Austin Christ wrote:
> >> +               ret = device_property_read_u32(qup->dev,
> >> +                               "src-clock-hz", &src_clk_freq);
> >> +               if (ret) {
> >> +                       dev_warn(qup->dev, "using default src-clock-hz %d",
> >> +                               DEFAULT_SRC_CLK);
> >> +                       src_clk_freq = DEFAULT_SRC_CLK;
> >> +               }
> >>
> > 
> > Where is this property documented?
> 
> We plan on submitting documentation via dsd@acpica.org to
> https://github.com/ahs3/dsd once it is operational. As I understand it
> the project is brand new. It may take several months to begin accepting
> submissions. In the mean time, we could potentially include
> documentation in a reply to this thread, the cover of the next series, a
> wiki page on codeaurora.org, a file in Documentation (perhaps to be
> replaced by ACPICA style imports of the OS-neutral DSD project or a git
> submodule) or potentially other means. Please let us know what you think
> is sufficient.

As you are reusing part of the DT binding, it seems appropriate to put
the documentation for this into the binding documentation in the kernel.

Not sure what the devicetree maintainers think about that though.

	Arnd

--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Christopher Covington June 30, 2016, 6:50 p.m. UTC | #9
Hi Arnd,

On 06/30/2016 07:52 AM, Arnd Bergmann wrote:
> On Thursday, June 30, 2016 7:35:14 AM CEST Christopher Covington wrote:
>> Hi Arnd,
>>
>> On 06/08/2016 05:02 PM, Arnd Bergmann wrote:
>>> On Wednesday, June 8, 2016 12:19:44 PM CEST Austin Christ wrote:
>>>> +               ret = device_property_read_u32(qup->dev,
>>>> +                               "src-clock-hz", &src_clk_freq);
>>>> +               if (ret) {
>>>> +                       dev_warn(qup->dev, "using default src-clock-hz %d",
>>>> +                               DEFAULT_SRC_CLK);
>>>> +                       src_clk_freq = DEFAULT_SRC_CLK;
>>>> +               }
>>>>
>>>
>>> Where is this property documented?
>>
>> We plan on submitting documentation via dsd@acpica.org to
>> https://github.com/ahs3/dsd once it is operational. As I understand it
>> the project is brand new. It may take several months to begin accepting
>> submissions. In the mean time, we could potentially include
>> documentation in a reply to this thread, the cover of the next series, a
>> wiki page on codeaurora.org, a file in Documentation (perhaps to be
>> replaced by ACPICA style imports of the OS-neutral DSD project or a git
>> submodule) or potentially other means. Please let us know what you think
>> is sufficient.
> 
> As you are reusing part of the DT binding, it seems appropriate to put
> the documentation for this into the binding documentation in the kernel.

My understanding is that in the device tree case, the input/source clock
frequency is assumed to be run-time managed through Global Clock
Controller (GCC) code and the common clock framework.

drivers/i2c/busses/i2c-qup.c:1549

src_clk_freq = clk_get_rate(qup->clk);

So a given I2C device tree entry points to the GCC device tree entry,
but there isn't an explicit, fixed input/source clock frequency value.

arch/arm64/boot/dts/qcom/msm8916.dtsi:310

blsp_i2c2: i2c@78b6000 {
        compatible = "qcom,i2c-qup-v2.2.1";
        reg = <0x78b6000 0x1000>;
        interrupts = <GIC_SPI 96 0>;
        clocks = <&gcc GCC_BLSP1_AHB_CLK>,
                <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>;
        clock-names = "iface", "core";
        pinctrl-names = "default", "sleep";
        pinctrl-0 = <&i2c2_default>;
        pinctrl-1 = <&i2c2_sleep>;
        #address-cells = <1>;
        #size-cells = <0>;
        status = "disabled";
};

On the other hand, when ACPI is in use, the driver assumes a fixed
input/source clock frequency value, which it tries to look up as a
device property.

(I'm out of my depth here, so somebody please correct me if I've
described this wrong.)

Thanks,
Cov
Arnd Bergmann July 1, 2016, 9:57 a.m. UTC | #10
On Thursday, June 30, 2016 2:50:44 PM CEST Christopher Covington wrote:
> Hi Arnd,
> 
> On 06/30/2016 07:52 AM, Arnd Bergmann wrote:
> > On Thursday, June 30, 2016 7:35:14 AM CEST Christopher Covington wrote:
> >> Hi Arnd,
> >>
> >> On 06/08/2016 05:02 PM, Arnd Bergmann wrote:
> >>> On Wednesday, June 8, 2016 12:19:44 PM CEST Austin Christ wrote:
> >>>> +               ret = device_property_read_u32(qup->dev,
> >>>> +                               "src-clock-hz", &src_clk_freq);
> >>>> +               if (ret) {
> >>>> +                       dev_warn(qup->dev, "using default src-clock-hz %d",
> >>>> +                               DEFAULT_SRC_CLK);
> >>>> +                       src_clk_freq = DEFAULT_SRC_CLK;
> >>>> +               }
> >>>>
> >>>
> >>> Where is this property documented?
> >>
> >> We plan on submitting documentation via dsd@acpica.org to
> >> https://github.com/ahs3/dsd once it is operational. As I understand it
> >> the project is brand new. It may take several months to begin accepting
> >> submissions. In the mean time, we could potentially include
> >> documentation in a reply to this thread, the cover of the next series, a
> >> wiki page on codeaurora.org, a file in Documentation (perhaps to be
> >> replaced by ACPICA style imports of the OS-neutral DSD project or a git
> >> submodule) or potentially other means. Please let us know what you think
> >> is sufficient.
> > 
> > As you are reusing part of the DT binding, it seems appropriate to put
> > the documentation for this into the binding documentation in the kernel.
> 
> My understanding is that in the device tree case, the input/source clock
> frequency is assumed to be run-time managed through Global Clock
> Controller (GCC) code and the common clock framework.
> 
> drivers/i2c/busses/i2c-qup.c:1549
> 
> src_clk_freq = clk_get_rate(qup->clk);
> 
> So a given I2C device tree entry points to the GCC device tree entry,
> but there isn't an explicit, fixed input/source clock frequency value.

Correct.

> arch/arm64/boot/dts/qcom/msm8916.dtsi:310
> 
> blsp_i2c2: i2c@78b6000 {
>         compatible = "qcom,i2c-qup-v2.2.1";
>         reg = <0x78b6000 0x1000>;
>         interrupts = <GIC_SPI 96 0>;
>         clocks = <&gcc GCC_BLSP1_AHB_CLK>,
>                 <&gcc GCC_BLSP1_QUP2_I2C_APPS_CLK>;
>         clock-names = "iface", "core";
>         pinctrl-names = "default", "sleep";
>         pinctrl-0 = <&i2c2_default>;
>         pinctrl-1 = <&i2c2_sleep>;
>         #address-cells = <1>;
>         #size-cells = <0>;
>         status = "disabled";
> };
> 
> On the other hand, when ACPI is in use, the driver assumes a fixed
> input/source clock frequency value, which it tries to look up as a
> device property.

Also correct.
 
> (I'm out of my depth here, so somebody please correct me if I've
> described this wrong.)

What I'm saying was that the binding file could just document both
cases as alternatives. We prefer to specify the clocks directly
when using a dtb, but for the driver one of the two is ok, and
the ACPI documentation will already have to refer to the DT binding
for the other properties, so I think it makes sense to describe
both the "clocks" and "src-clock-hz" properties in the same document
as optional properties and clarify that at least one of the two
is requried.

Note that we have traditionally used "clock-frequency" as the
property name for the input clock frequency in DT bindings that
predate the generic clock handling (e.g. 8250 uarts on IBM Power
servers), so we could use the same here.

	Arnd
--
To unsubscribe from this list: send the line "unsubscribe linux-i2c" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
diff mbox

Patch

diff --git a/drivers/i2c/busses/i2c-qup.c b/drivers/i2c/busses/i2c-qup.c
index dddd4da..0f23d58 100644
--- a/drivers/i2c/busses/i2c-qup.c
+++ b/drivers/i2c/busses/i2c-qup.c
@@ -29,6 +29,7 @@ 
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/scatterlist.h>
+#include <linux/acpi.h>
 
 /* QUP Registers */
 #define QUP_CONFIG		0x000
@@ -132,6 +133,10 @@ 
 /* Max timeout in ms for 32k bytes */
 #define TOUT_MAX			300
 
+/* Default values. Use these if FW query fails */
+#define DEFAULT_CLK_FREQ 100000
+#define DEFAULT_SRC_CLK 20000000
+
 struct qup_i2c_block {
 	int	count;
 	int	pos;
@@ -1354,14 +1359,13 @@  static void qup_i2c_disable_clocks(struct qup_i2c_dev *qup)
 static int qup_i2c_probe(struct platform_device *pdev)
 {
 	static const int blk_sizes[] = {4, 16, 32};
-	struct device_node *node = pdev->dev.of_node;
 	struct qup_i2c_dev *qup;
 	unsigned long one_bit_t;
 	struct resource *res;
 	u32 io_mode, hw_ver, size;
 	int ret, fs_div, hs_div;
-	int src_clk_freq;
-	u32 clk_freq = 100000;
+	u32 src_clk_freq = 0;
+	u32 clk_freq = DEFAULT_CLK_FREQ;
 	int blocks;
 
 	qup = devm_kzalloc(&pdev->dev, sizeof(*qup), GFP_KERNEL);
@@ -1372,7 +1376,11 @@  static int qup_i2c_probe(struct platform_device *pdev)
 	init_completion(&qup->xfer);
 	platform_set_drvdata(pdev, qup);
 
-	of_property_read_u32(node, "clock-frequency", &clk_freq);
+	ret = device_property_read_u32(qup->dev, "clock-frequency", &clk_freq);
+	if (ret) {
+		dev_notice(qup->dev, "using default clock-frequency %d",
+			DEFAULT_CLK_FREQ);
+	}
 
 	if (of_device_is_compatible(pdev->dev.of_node, "qcom,i2c-qup-v1.1.1")) {
 		qup->adap.algo = &qup_i2c_algo;
@@ -1454,20 +1462,31 @@  nodma:
 		return qup->irq;
 	}
 
-	qup->clk = devm_clk_get(qup->dev, "core");
-	if (IS_ERR(qup->clk)) {
-		dev_err(qup->dev, "Could not get core clock\n");
-		return PTR_ERR(qup->clk);
-	}
+	if (ACPI_HANDLE(qup->dev)) {
+		ret = device_property_read_u32(qup->dev,
+				"src-clock-hz", &src_clk_freq);
+		if (ret) {
+			dev_warn(qup->dev, "using default src-clock-hz %d",
+				DEFAULT_SRC_CLK);
+			src_clk_freq = DEFAULT_SRC_CLK;
+		}
+		ACPI_COMPANION_SET(&qup->adap.dev, ACPI_COMPANION(qup->dev));
+	} else {
+		qup->clk = devm_clk_get(qup->dev, "core");
+		if (IS_ERR(qup->clk)) {
+			dev_err(qup->dev, "Could not get core clock\n");
+			return PTR_ERR(qup->clk);
+		}
 
-	qup->pclk = devm_clk_get(qup->dev, "iface");
-	if (IS_ERR(qup->pclk)) {
-		dev_err(qup->dev, "Could not get iface clock\n");
-		return PTR_ERR(qup->pclk);
+		qup->pclk = devm_clk_get(qup->dev, "iface");
+		if (IS_ERR(qup->pclk)) {
+			dev_err(qup->dev, "Could not get iface clock\n");
+			return PTR_ERR(qup->pclk);
+		}
+		qup_i2c_enable_clocks(qup);
+		src_clk_freq = clk_get_rate(qup->clk);
 	}
 
-	qup_i2c_enable_clocks(qup);
-
 	/*
 	 * Bootloaders might leave a pending interrupt on certain QUP's,
 	 * so we reset the core before registering for interrupts.
@@ -1514,7 +1533,6 @@  nodma:
 	size = QUP_INPUT_FIFO_SIZE(io_mode);
 	qup->in_fifo_sz = qup->in_blk_sz * (2 << size);
 
-	src_clk_freq = clk_get_rate(qup->clk);
 	fs_div = ((src_clk_freq / clk_freq) / 2) - 3;
 	hs_div = 3;
 	qup->clk_ctl = (hs_div << 8) | (fs_div & 0xff);
@@ -1639,6 +1657,14 @@  static const struct of_device_id qup_i2c_dt_match[] = {
 };
 MODULE_DEVICE_TABLE(of, qup_i2c_dt_match);
 
+#if IS_ENABLED(CONFIG_ACPI)
+static const struct acpi_device_id qup_i2c_acpi_match[] = {
+	{ "QCOM8010"},
+	{ },
+};
+MODULE_DEVICE_TABLE(acpi, qup_i2c_acpi_ids);
+#endif
+
 static struct platform_driver qup_i2c_driver = {
 	.probe  = qup_i2c_probe,
 	.remove = qup_i2c_remove,
@@ -1646,6 +1672,7 @@  static struct platform_driver qup_i2c_driver = {
 		.name = "i2c_qup",
 		.pm = &qup_i2c_qup_pm_ops,
 		.of_match_table = qup_i2c_dt_match,
+		.acpi_match_table = ACPI_PTR(qup_i2c_acpi_match),
 	},
 };