From: Naveen Kaje <redacted>
Add support to get the device parameters from ACPI. Assume
that the clocks are managed by firmware.
Signed-off-by: Naveen Kaje <redacted>
Signed-off-by: Austin Christ <redacted>
Reviewed-by: sricharan at 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
@@ -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+structqup_i2c_block{intcount;intpos;
@@ -1454,20 +1462,31 @@ nodma:returnqup->irq;}-qup->clk=devm_clk_get(qup->dev,"core");-if(IS_ERR(qup->clk)){-dev_err(qup->dev,"Could not get core clock\n");-returnPTR_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");+returnPTR_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");-returnPTR_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");+returnPTR_ERR(qup->pclk);+}+qup_i2c_enable_clocks(qup);+src_clk_freq=clk_get_rate(qup->clk);}-qup_i2c_enable_clocks(qup);-/**BootloadersmightleaveapendinginterruptoncertainQUP's,*soweresetthecorebeforeregisteringforinterrupts.
--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
From: Naveen Kaje <redacted>
I2C QUP driver relies on SMBus emulation support from the framework.
To handle SMBus block reads, the driver should check I2C_M_RECV_LEN
flag and should read the first byte received as the message length.
The driver configures the QUP hardware to read one byte. Once the
message length is known from this byte, the QUP hardware is configured
to read the rest.
Signed-off-by: Naveen Kaje <redacted>
Signed-off-by: Austin Christ <redacted>
Reviewed-by: sricharan at codeaurora.org
---
drivers/i2c/busses/i2c-qup.c | 68 ++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 65 insertions(+), 3 deletions(-)
Changes:
-v4:
- correct error code
- v3:
- clean up redundant checks
- use constant instead of variable for smbus length field
- v2:
- rework the smbus block read and break into separate function
@@ -517,6 +517,33 @@ static int qup_i2c_get_data_len(struct qup_i2c_dev *qup)returndata_len;}+staticboolqup_i2c_check_msg_len(structi2c_msg*msg)+{+return((msg->flags&I2C_M_RD)&&(msg->flags&I2C_M_RECV_LEN));+}++staticintqup_i2c_set_tags_smb(u16addr,u8*tags,structqup_i2c_dev*qup,+structi2c_msg*msg)+{+intlen=0;++if(msg->len>1){+tags[len++]=QUP_TAG_V2_DATARD_STOP;+tags[len++]=qup_i2c_get_data_len(qup)-1;+}else{+tags[len++]=QUP_TAG_V2_START;+tags[len++]=addr&0xff;++if(msg->flags&I2C_M_TEN)+tags[len++]=addr>>8;++tags[len++]=QUP_TAG_V2_DATARD;+/* Read 1 byte indicating the length of the SMBus message */+tags[len++]=1;+}+returnlen;+}+staticintqup_i2c_set_tags(u8*tags,structqup_i2c_dev*qup,structi2c_msg*msg,intis_dma){
@@ -526,6 +553,10 @@ static int qup_i2c_set_tags(u8 *tags, struct qup_i2c_dev *qup,intlast=(qup->blk.pos==(qup->blk.count-1))&&(qup->is_last);+/* Handle tags for SMBus block read */+if(qup_i2c_check_msg_len(msg))+returnqup_i2c_set_tags_smb(addr,tags,qup,msg);+if(qup->blk.pos==0){tags[len++]=QUP_TAG_V2_START;tags[len++]=addr&0xff;
@@ -1065,9 +1096,17 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,structi2c_msg*msg){u32val;-intidx,pos=0,ret=0,total;+intidx,pos=0,ret=0,total,msg_offset=0;+/*+*Ifthemessagelengthisalreadyreadin+*thefirstbyteofthebuffer,accountfor+*thatbysettingtheoffset+*/+if(qup_i2c_check_msg_len(msg)&&(msg->len>1))+msg_offset=1;total=qup_i2c_get_data_len(qup);+total-=msg_offset;/* 2 extra bytes for read tags */while(pos<(total+2)){
@@ -1087,8 +1126,8 @@ static int qup_i2c_read_fifo_v2(struct qup_i2c_dev *qup,if(pos>=(total+2))gotoout;--msg->buf[qup->pos++]=val&0xff;+msg->buf[qup->pos+msg_offset]=val&0xff;+qup->pos++;}}
@@ -1210,6 +1267,11 @@ static int qup_i2c_xfer(struct i2c_adapter *adap,gotoout;}+if(qup_i2c_check_msg_len(&msgs[idx])){+ret=-EINVAL;+gotoout;+}+if(msgs[idx].flags&I2C_M_RD)ret=qup_i2c_read_one(qup,&msgs[idx]);else
--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
@@ -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;
--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
From: Wolfram Sang <hidden> Date: 2016-06-18 14:13:34
On Wed, Jun 08, 2016 at 12:19:45PM -0600, Austin Christ wrote:
From: Naveen Kaje <redacted>
I2C QUP driver relies on SMBus emulation support from the framework.
To handle SMBus block reads, the driver should check I2C_M_RECV_LEN
flag and should read the first byte received as the message length.
The driver configures the QUP hardware to read one byte. Once the
message length is known from this byte, the QUP hardware is configured
to read the rest.
Signed-off-by: Naveen Kaje <redacted>
Signed-off-by: Austin Christ <redacted>
Reviewed-by: sricharan at codeaurora.org
@@ -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;
@@ -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.
quoted
+ 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.
--
Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
a Linux Foundation Collaborative Project.
From: Timur Tabi <hidden> Date: 2016-06-20 15:03:00
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.
--
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the
Code Aurora Forum, hosted by The Linux Foundation.
From: Mika Westerberg <mika.westerberg@linux.intel.com> Date: 2016-06-20 15:09:20
On Mon, Jun 20, 2016 at 10:00:46AM -0500, Timur Tabi wrote:
Mika Westerberg wrote:
quoted
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.
We plan on submitting documentation via dsd at 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
--
Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
We plan on submitting documentation via dsd at 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
We plan on submitting documentation via dsd at 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 at 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
--
Qualcomm Innovation Center, Inc.
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
a Linux Foundation Collaborative Project
We plan on submitting documentation via dsd at 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 at 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