fsi: Add IBM I2C Responder virtual FSI master
Subsystems (3)
Eddie James
maintainercover fsi: Add IBM I2C Responder virtual FSI master
The I2C Responder (I2CR) is an I2C device that translates I2C commands to CFAM or SCOM operations, effectively implementing an FSI master and bus.
Eddie James (2):
dt-bindings: fsi: Document the IBM I2C Responder virtual FSI master
fsi: Add IBM I2C Responder virtual FSI master
.../devicetree/bindings/fsi/ibm,i2cr.yaml | 42 ++++ drivers/fsi/Kconfig | 9 + drivers/fsi/Makefile | 1 + drivers/fsi/fsi-master-i2cr.c | 225 ++++++++++++++++++ include/trace/events/fsi_master_i2cr.h | 96 ++++++++ 5 files changed, 373 insertions(+) create mode 100644 Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml create mode 100644 drivers/fsi/fsi-master-i2cr.c create mode 100644 include/trace/events/fsi_master_i2cr.h
Signature · 1 line
2.31.1
Eddie James
maintainerPATCH 1/2 dt-bindings: fsi: Document the IBM I2C Responder virtual FSI master
The I2C Responder translates I2C commands to CFAM or SCOM operations, effectively implementing an FSI master.
--- .../devicetree/bindings/fsi/ibm,i2cr.yaml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +42 -0
@@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/fsi/ibm,i2cr.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IBM I2C Responder virtual FSI master + +maintainers: + - Eddie James <[email protected]> + +description: | + This binding describes an I2C device called the I2C Responder (I2CR). The + I2CR translates commands sent over I2C bus to FSI CFAM reads and writes or + SCOM operations. The CFAM access means that the I2CR can act as an FSI + master. + +properties: + compatible: + enum: + - ibm,i2cr + + reg: + maxItems: 1 + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + i2cr@20 { + compatible = "ibm,i2cr"; + reg = <0x20>; + }; + };
Signature · 1 line
2.31.1
Re: [PATCH 1/2] dt-bindings: fsi: Document the IBM I2C Responder virtual FSI master
Quoted 34 lines · Eddie James
The I2C Responder translates I2C commands to CFAM or SCOM operations, effectively implementing an FSI master.
Signed-off-by Eddie James <[email protected]>--- .../devicetree/bindings/fsi/ibm,i2cr.yaml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/fsi/ibm,i2cr.yamlDocumentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +13
-0@@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/fsi/ibm,i2cr.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IBM I2C Responder virtual FSI master + +maintainers: + - Eddie James <[email protected]> + +description: | + This binding describes an I2C device called the I2C Responder(I2CR). The
+ I2CR translates commands sent over I2C bus to FSI CFAM reads and writes or
+ SCOM operations. The CFAM access means that the I2CR can act as an FSI
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml line 21
Quoted 6 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +6
-0+ master. + +properties: + compatible: + enum: + - ibm,i2cr
I think this should be a bit more descriptive and at least mention that it's FSI-related, e.g. ibm,fsi-i2cr? Thoughts?
Quoted 8 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +8
-0+ + reg: + maxItems: 1 + +required: + - compatible + - reg +
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml line 39
Quoted 10 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +10
-0+additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + i2cr@20 { + compatible = "ibm,i2cr";
Change this in accordance with the above.
Andrew
Eddie James
maintainerRe: [PATCH 1/2] dt-bindings: fsi: Document the IBM I2C Responder virtual FSI master
Quoted 37 lines · Andrew Jeffery
Quoted 35 lines · Eddie James
The I2C Responder translates I2C commands to CFAM or SCOM operations, effectively implementing an FSI master.
Signed-off-by Eddie James <[email protected]>--- .../devicetree/bindings/fsi/ibm,i2cr.yaml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+)create mode 100644
Documentation/devicetree/bindings/fsi/ibm,i2cr.yamlDocumentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +13
-0@@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/fsi/ibm,i2cr.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IBM I2C Responder virtual FSI master + +maintainers: + - Eddie James <[email protected]> + +description: | + This binding describes an I2C device called the I2C Responder(I2CR). The
+ I2CR translates commands sent over I2C bus to FSI CFAM reads and writes or
+ SCOM operations. The CFAM access means that the I2CR can act as an FSI
+ master.
Quoted 8 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml line 21
Quoted 5 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +5
-0+ +properties: + compatible: + enum: + - ibm,i2crI think this should be a bit more descriptive and at least mention that it's FSI-related, e.g.
ibm,fsi-i2cr? Thoughts?
Yea that probably makes sense.
Thanks for the suggestion!
Eddie
Quoted 22 lines
Quoted 9 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +8
-0+ + reg: + maxItems: 1 + +required: + - compatible + - reg +Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml line 39
Quoted 10 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +10
-0+additionalProperties: false + +examples: + - | + i2c { + #address-cells = <1>; + #size-cells = <0>; + + i2cr@20 { + compatible = "ibm,i2cr";Change this in accordance with the above.
Andrew
Rob Herring
maintainerRe: [PATCH 1/2] dt-bindings: fsi: Document the IBM I2C Responder virtual FSI master
In reply to Eddie JamesQuoted 9 lines · Eddie James
The I2C Responder translates I2C commands to CFAM or SCOM operations, effectively implementing an FSI master.
Signed-off-by Eddie James <[email protected]>--- .../devicetree/bindings/fsi/ibm,i2cr.yaml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml
My bot found errors running 'make DT_CHECKER_FLAGS=-m dt_binding_check' on your patch (DT_CHECKER_FLAGS is new in v5.13):
yamllint warnings/errors:./Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml:23:4: [error] syntax error: expected <block end>, but found '<block mapping start>' (syntax) ./Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml:24:5: [warning] wrong indentation: expected 5 but found 4 (indentation) ./Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml:33:2: [warning] wrong indentation: expected 2 but found 1 (indentation)
dtschema/dtc warnings/errors:
make[1]: *** Deleting file 'Documentation/devicetree/bindings/fsi/ibm,i2cr.example.dts' Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml:23:4: did not find expected key
make[1]: *** [Documentation/devicetree/bindings/Makefile:26: Documentation/devicetree/bindings/fsi/ibm,i2cr.example.dts] Error 1 make[1]: *** Waiting for unfinished jobs...../Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml:23:4: did not find expected key /builds/robherring/dt-review-ci/linux/Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml: ignoring, error parsing file
make: *** [Makefile:1508: dt_binding_check] Error 2
doc reference errors (make refcheckdocs):
See https://patchwork.ozlabs.org/project/devicetree-bindings/patch/[email protected]
The base for the series is generally the latest rc1. A different dependency should be noted in *this* patch.
If you already ran 'make dt_binding_check' and didn't see the above error(s), then make sure 'yamllint' is installed and dt-schema is up to date:
pip3 install dtschema --upgrade
Please check and re-submit after running the above command yourself. Note that DT_SCHEMA_FILES can be set to your schema file to speed up checking your schema. However, it must be unset to test all examples with your schema.
Re: [PATCH 1/2] dt-bindings: fsi: Document the IBM I2C Responder virtual FSI master
In reply to Eddie JamesQuoted 18 lines · Eddie James
The I2C Responder translates I2C commands to CFAM or SCOM operations, effectively implementing an FSI master.
Signed-off-by Eddie James <[email protected]>--- .../devicetree/bindings/fsi/ibm,i2cr.yaml | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 Documentation/devicetree/bindings/fsi/ibm,i2cr.yamlDocumentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +3
-0@@ -0,0 +1,42 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +---
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml line 13
Quoted 10 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +10
-0+$id: http://devicetree.org/schemas/fsi/ibm,i2cr.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: IBM I2C Responder virtual FSI master + +maintainers: + - Eddie James <[email protected]> + +description: | + This binding describes an I2C device called the I2C Responder (I2CR). The
In the binding, don't write description of the binding. In the binding, write about the hardware. Rephrase it so the hardware is the subject.
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml line 24
Quoted 11 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +11
-0+ I2CR translates commands sent over I2C bus to FSI CFAM reads and writes or + SCOM operations. The CFAM access means that the I2CR can act as an FSI + master. + +properties: + compatible: + enum: + - ibm,i2cr + + reg: + maxItems: 1
Does not look like you tested the bindings. Please run make dt_binding_check (see Documentation/devicetree/bindings/writing-schema.rst for instructions).
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml line 34
Quoted 10 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +10
-0+ +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c {
Use 4 spaces for example indentation.
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml line 42
Quoted 8 lines
Documentation/devicetree/bindings/fsi/ibm,i2cr.yaml new file +8
-0+ #address-cells = <1>; + #size-cells = <0>; + + i2cr@20 { + compatible = "ibm,i2cr"; + reg = <0x20>; + }; + };
Best regards,
Krzysztof
Eddie James
maintainerPATCH 2/2 fsi: Add IBM I2C Responder virtual FSI master
In reply to Eddie JamesThe I2C Responder (I2CR) is an I2C device that translates I2C commands to CFAM or SCOM operations, effectively implementing an FSI master and bus.
--- drivers/fsi/Kconfig | 9 + drivers/fsi/Makefile | 1 + drivers/fsi/fsi-master-i2cr.c | 225 +++++++++++++++++++++++++ include/trace/events/fsi_master_i2cr.h | 96 +++++++++++ 4 files changed, 331 insertions(+) create mode 100644 drivers/fsi/fsi-master-i2cr.c create mode 100644 include/trace/events/fsi_master_i2cr.h
drivers/fsi/Kconfig +9 -0
@@ -62,6 +62,15 @@ config FSI_MASTER_ASPEED Enable it for your BMC kernel in an OpenPower or IBM Power system. +config FSI_MASTER_I2CR + tristate "IBM I2C Responder virtual FSI master" + depends on I2C + help + This option enables a virtual FSI master in order to access a CFAM + behind an IBM I2C Responder (I2CR) chip. The I2CR is an I2C device + that translates I2C commands to CFAM or SCOM operations, effectively + implementing an FSI master and bus. + config FSI_SCOM tristate "SCOM FSI client device driver" help
drivers/fsi/Makefile +1 -0
@@ -4,6 +4,7 @@ obj-$(CONFIG_FSI) += fsi-core.o obj-$(CONFIG_FSI_MASTER_HUB) += fsi-master-hub.o obj-$(CONFIG_FSI_MASTER_ASPEED) += fsi-master-aspeed.o obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o +obj-$(CONFIG_FSI_MASTER_I2CR) += fsi-master-i2cr.o obj-$(CONFIG_FSI_MASTER_AST_CF) += fsi-master-ast-cf.o obj-$(CONFIG_FSI_SCOM) += fsi-scom.o obj-$(CONFIG_FSI_SBEFIFO) += fsi-sbefifo.o
drivers/fsi/fsi-master-i2cr.c new file +225 -0
225 lines not on this page · raw message
include/trace/events/fsi_master_i2cr.h new file +96 -0
96 lines not on this page · raw message
Signature · 1 line
2.31.1
Quoted 107 lines · Eddie James
The I2C Responder (I2CR) is an I2C device that translates I2C commands to CFAM or SCOM operations, effectively implementing an FSI master and bus.
Signed-off-by Eddie James <[email protected]>--- drivers/fsi/Kconfig | 9 + drivers/fsi/Makefile | 1 + drivers/fsi/fsi-master-i2cr.c | 225 +++++++++++++++++++++++++ include/trace/events/fsi_master_i2cr.h | 96 +++++++++++ 4 files changed, 331 insertions(+) create mode 100644 drivers/fsi/fsi-master-i2cr.c create mode 100644 include/trace/events/fsi_master_i2cr.hdrivers/fsi/Kconfig +9
-0@@ -62,6 +62,15 @@ config FSI_MASTER_ASPEED Enable it for your BMC kernel in an OpenPower or IBM Power system. +config FSI_MASTER_I2CR + tristate "IBM I2C Responder virtual FSI master" + depends on I2C + help + This option enables a virtual FSI master in order to access a CFAM + behind an IBM I2C Responder (I2CR) chip. The I2CR is an I2C device + that translates I2C commands to CFAM or SCOM operations, effectively + implementing an FSI master and bus. + config FSI_SCOM tristate "SCOM FSI client device driver" helpdrivers/fsi/Makefile +1
-0@@ -4,6 +4,7 @@ obj-$(CONFIG_FSI) += fsi-core.o obj-$(CONFIG_FSI_MASTER_HUB) += fsi-master-hub.o obj-$(CONFIG_FSI_MASTER_ASPEED) += fsi-master-aspeed.o obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o +obj-$(CONFIG_FSI_MASTER_I2CR) += fsi-master-i2cr.o obj-$(CONFIG_FSI_MASTER_AST_CF) += fsi-master-ast-cf.o obj-$(CONFIG_FSI_SCOM) += fsi-scom.o obj-$(CONFIG_FSI_SBEFIFO) += fsi-sbefifo.odrivers/fsi/fsi-master-i2cr.c new file +54
-0@@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) IBM Corporation 2023 */ + +#include <linux/device.h> +#include <linux/fsi.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/mutex.h> + +#include "fsi-master.h" + +#define CREATE_TRACE_POINTS +#include <trace/events/fsi_master_i2cr.h> + +#define I2CR_ADDRESS_CFAM (a) ((a) >> 2) +#define I2CR_STATUS 0x30001 +#define I2CR_STATUS_ERR BIT_ULL(61) +#define I2CR_ERROR 0x30002 + +struct fsi_master_i2cr { +struct fsi_master master; +struct mutex lock;/* protect HW access */ +struct i2c_client *client; +}; + +static bool i2cr_check_parity (u32 v,bool parity) +{ +u32 i; + +for (i =0 ; i <32 ; ++i) { +if (v & (1 << i)) + parity = !parity; + } + +return parity; +} + +static __be32 i2cr_get_command (u32 address,bool parity) +{ +__be32 command; + + address <<=1 ; + +if (i2cr_check_parity (address, parity)) + address |=1 ; + + command =cpu_to_be32 (address); +trace_i2cr_command ((__force uint32_t )command); + +return command; +} + +static int i2cr_transfer(struct i2c_client *client, u32 address,
Quoted 1 line
__be64*data)
Is there a reason to use __be64 *data here and not void *data, size_t len? We never actually use it as the declared type internally, only cast it to __u8 *.
Quoted 64 lines
drivers/fsi/fsi-master-i2cr.c new file +46
-0+{ +struct i2c_msg msgs[2 ]; +__be32 command; +int ret; + + command =i2cr_get_command (address, true); + msgs[0 ].addr = client->addr; + msgs[0 ].flags =0 ; + msgs[0 ].len =sizeof (command); + msgs[0 ].buf = (__u8 *)&command; + msgs[1 ].addr = client->addr; + msgs[1 ].flags =I2C_M_RD ; + msgs[1 ].len =sizeof (*data); + msgs[1 ].buf = (__u8 *)data; + + ret =i2c_transfer (client->adapter, msgs,2 ); +if (ret ==2 ) +return 0 ; + +trace_i2cr_i2c_error (ret); + +if (ret <0 ) +return ret; + +return -EIO ; +} + +static int i2cr_check_status (struct i2c_client *client) +{ +__be64 status_be =0 ; +u64 status; +int ret; + + ret =i2cr_transfer (client,I2CR_STATUS , &status_be); +if (ret) +return ret; + + status =be64_to_cpu (status_be); +if (status &I2CR_STATUS_ERR ) { +__be64 error_be =0 ; +u64 error; + +i2cr_transfer (client,I2CR_ERROR , &error_be); + error =be64_to_cpu (error_be); +trace_i2cr_status_error (status, error); + dev_err(&client->dev, "status:%016llx error:%016llx\n", status,error);
drivers/fsi/fsi-master-i2cr.c new file +8
-0+return -EREMOTEIO ; + } + +trace_i2cr_status (status); +return 0 ; +} + +static int i2cr_read(struct fsi_master *master, int link, uint8_t id,
uint32_taddr, void *val,drivers/fsi/fsi-master-i2cr.c new file +3
-0+ size_t size) +{ + struct fsi_master_i2cr *i2cr = container_of(master, struct
fsi_master_i2cr, master);drivers/fsi/fsi-master-i2cr.c new file +4
-0+__be64 data =0 ; +int ret; + + if (link || id || (addr & 0xffff0000) || !size || size > 4 || size ==
Quoted 1 line
3)
These size constraints are a bit funky. Instead of !size || size > 4 || size == 3 we write !(size == 1 || size == 2 || size == 4)?
Quoted 30 lines
drivers/fsi/fsi-master-i2cr.c new file +21
-0+return -EINVAL ; + +mutex_lock (&i2cr->lock); + + ret =i2cr_transfer (i2cr->client,I2CR_ADDRESS_CFAM (addr), &data); +if (ret) + goto unlock; + + ret =i2cr_check_status (i2cr->client); +if (ret) + goto unlock; + +trace_i2cr_read (addr, size, (__force uint32_t )data); +memcpy (val, &data, size); + +unlock: +mutex_unlock (&i2cr->lock); +return ret; +} + +static int i2cr_write(struct fsi_master *master, int link, uint8_t id,
uint32_taddr,drivers/fsi/fsi-master-i2cr.c new file +3
-0+ const void *val, size_t size) +{ + struct fsi_master_i2cr *i2cr = container_of(master, struct
fsi_master_i2cr, master);drivers/fsi/fsi-master-i2cr.c new file +4
-0+__be32 data[3 ]; +int ret; + + if (link || id || (addr & 0xffff0000) || !size || size > 4 || size ==
Quoted 1 line
3)
As above
Quoted 5 lines
drivers/fsi/fsi-master-i2cr.c new file +5
-0+return -EINVAL ; + + data[1 ] =0 ; +memcpy (&data[1 ], val, size); + data[0] = i2cr_get_command(I2CR_ADDRESS_CFAM(addr),
drivers/fsi/fsi-master-i2cr.c line 158
Quoted 10 lines
drivers/fsi/fsi-master-i2cr.c new file +10
-0+ i2cr_check_parity((__force u32)data[1], true)); + data[2 ] =0 ; + +mutex_lock (&i2cr->lock); + + ret =i2c_master_send (i2cr->client, (const char *)data,sizeof (data)); +if (ret ==sizeof (data)) { + ret =i2cr_check_status (i2cr->client); +if (!ret) +trace_i2cr_write (addr, size, (__force uint32_t )data[1 ]);
I think we can reduce the amount of __force if we flip the endianness of the data variable?
``` u32 data[3]; __be32 cmd_be; data[1] = 0; memcpy(&data[1], val, size); cmd_be = i2cr_get_command(I2CR_ADDRESS_CFAM(addr), i2cr_check_parity(data[1], true)); data[0] = (__force u32)cmd_be; data[2] = 0; .... trace_i2cr_write(addr, size, data[1]); ```
?
Or define i2cr_check_parity() and the tracepoint in terms of big-endian?
Quoted 39 lines
drivers/fsi/fsi-master-i2cr.c new file +39
-0+ }else { +trace_i2cr_i2c_error (ret); + +if (ret >=0 ) + ret = -EIO ; + } + +mutex_unlock (&i2cr->lock); +return ret; +} + +static int i2cr_probe (struct i2c_client *client) +{ +struct fsi_master_i2cr *i2cr; +int ret; + + i2cr =devm_kzalloc (&client->dev,sizeof (*i2cr),GFP_KERNEL ); +if (!i2cr) +return -ENOMEM ; + + i2cr->master.dev.parent = &client->dev; + i2cr->master.dev.of_node =of_node_get (dev_of_node (&client->dev)); + + i2cr->master.n_links =1 ; + i2cr->master.read = i2cr_read; + i2cr->master.write = i2cr_write; + +mutex_init (&i2cr->lock); + i2cr->client = client; + + ret =fsi_master_register (&i2cr->master); +if (ret) +return ret; + +i2c_set_clientdata (client, i2cr); +return 0 ; +} + +static int i2cr_remove (struct i2c_client *client)
drivers/fsi/fsi-master-i2cr.c line 207
Quoted 10 lines
drivers/fsi/fsi-master-i2cr.c new file +10
-0+{ +struct fsi_master_i2cr *i2cr =i2c_get_clientdata (client); + +fsi_master_unregister (&i2cr->master); + +return 0 ; +} + +static const struct of_device_id i2cr_i2c_ids[] = { + { .compatible ="ibm,i2cr" , },
This may need an update after discussion on the binding patch.
Andrew
Eddie James
maintainerQuoted 105 lines · Andrew Jeffery
Quoted 103 lines · Eddie James
The I2C Responder (I2CR) is an I2C device that translates I2C commands to CFAM or SCOM operations, effectively implementing an FSI master and bus.
Signed-off-by Eddie James <[email protected]>--- drivers/fsi/Kconfig | 9 + drivers/fsi/Makefile | 1 + drivers/fsi/fsi-master-i2cr.c | 225 +++++++++++++++++++++++++ include/trace/events/fsi_master_i2cr.h | 96 +++++++++++ 4 files changed, 331 insertions(+)create mode 100644
drivers/fsi/fsi-master-i2cr.ccreate mode 100644include/trace/events/fsi_master_i2cr.hdrivers/fsi/Kconfig +9
-0@@ -62,6 +62,15 @@ config FSI_MASTER_ASPEED Enable it for your BMC kernel in an OpenPower or IBM Power system. +config FSI_MASTER_I2CR + tristate "IBM I2C Responder virtual FSI master" + depends on I2C + help + This option enables a virtual FSI master in order to access a CFAM + behind an IBM I2C Responder (I2CR) chip. The I2CR is an I2C device + that translates I2C commands to CFAM or SCOM operations, effectively + implementing an FSI master and bus. + config FSI_SCOM tristate "SCOM FSI client device driver" helpdrivers/fsi/Makefile +1
-0@@ -4,6 +4,7 @@ obj-$(CONFIG_FSI) += fsi-core.o obj-$(CONFIG_FSI_MASTER_HUB) += fsi-master-hub.o obj-$(CONFIG_FSI_MASTER_ASPEED) += fsi-master-aspeed.o obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o +obj-$(CONFIG_FSI_MASTER_I2CR) += fsi-master-i2cr.o obj-$(CONFIG_FSI_MASTER_AST_CF) += fsi-master-ast-cf.o obj-$(CONFIG_FSI_SCOM) += fsi-scom.o obj-$(CONFIG_FSI_SBEFIFO) += fsi-sbefifo.odrivers/fsi/fsi-master-i2cr.c new file +50
-0@@ -0,0 +1,225 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) IBM Corporation 2023 */ + +#include <linux/device.h> +#include <linux/fsi.h> +#include <linux/i2c.h> +#include <linux/module.h> +#include <linux/mod_devicetable.h> +#include <linux/mutex.h> + +#include "fsi-master.h" + +#define CREATE_TRACE_POINTS +#include <trace/events/fsi_master_i2cr.h> + +#define I2CR_ADDRESS_CFAM (a) ((a) >> 2) +#define I2CR_STATUS 0x30001 +#define I2CR_STATUS_ERR BIT_ULL(61) +#define I2CR_ERROR 0x30002 + +struct fsi_master_i2cr { +struct fsi_master master; +struct mutex lock;/* protect HW access */ +struct i2c_client *client; +}; + +static bool i2cr_check_parity (u32 v,bool parity) +{ +u32 i; + +for (i =0 ; i <32 ; ++i) { +if (v & (1 << i)) + parity = !parity; + } + +return parity; +} + +static __be32 i2cr_get_command (u32 address,bool parity) +{ +__be32 command; + + address <<=1 ; + +if (i2cr_check_parity (address, parity)) + address |=1 ; + + command =cpu_to_be32 (address); +trace_i2cr_command ((__force uint32_t )command); +
Quoted 8 lines
Quoted 5 lines
drivers/fsi/fsi-master-i2cr.c new file +4
-0+return command; +} + +static int i2cr_transfer(struct i2c_client *client, u32 address,
__be64*data)Is there a reason to use
__be64*data here and notvoid *data, size_t len? We never actually use it as the declared type internally, only cast it to__u8*.
Well, its mostly to ensure the user buffer is at least 8 bytes. We have to read 8 bytes of data, so passing in a length doesn't really make sense?
Quoted 60 lines
Quoted 60 lines
drivers/fsi/fsi-master-i2cr.c new file +46
-0+{ +struct i2c_msg msgs[2 ]; +__be32 command; +int ret; + + command =i2cr_get_command (address, true); + msgs[0 ].addr = client->addr; + msgs[0 ].flags =0 ; + msgs[0 ].len =sizeof (command); + msgs[0 ].buf = (__u8 *)&command; + msgs[1 ].addr = client->addr; + msgs[1 ].flags =I2C_M_RD ; + msgs[1 ].len =sizeof (*data); + msgs[1 ].buf = (__u8 *)data; + + ret =i2c_transfer (client->adapter, msgs,2 ); +if (ret ==2 ) +return 0 ; + +trace_i2cr_i2c_error (ret); + +if (ret <0 ) +return ret; + +return -EIO ; +} + +static int i2cr_check_status (struct i2c_client *client) +{ +__be64 status_be =0 ; +u64 status; +int ret; + + ret =i2cr_transfer (client,I2CR_STATUS , &status_be); +if (ret) +return ret; + + status =be64_to_cpu (status_be); +if (status &I2CR_STATUS_ERR ) { +__be64 error_be =0 ; +u64 error; + +i2cr_transfer (client,I2CR_ERROR , &error_be); + error =be64_to_cpu (error_be); +trace_i2cr_status_error (status, error); + dev_err(&client->dev, "status:%016llx error:%016llx\n", status,error);
drivers/fsi/fsi-master-i2cr.c new file +8
-0+return -EREMOTEIO ; + } + +trace_i2cr_status (status); +return 0 ; +} + +static int i2cr_read(struct fsi_master *master, int link, uint8_t id,
uint32_taddr, void *val,drivers/fsi/fsi-master-i2cr.c new file +3
-0+ size_t size) +{ + struct fsi_master_i2cr *i2cr = container_of(master, struct
Quoted 8 lines
Quoted 6 lines
fsi_master_i2cr, master);drivers/fsi/fsi-master-i2cr.c new file +4
-0+__be64 data =0 ; +int ret; + + if (link || id || (addr & 0xffff0000) || !size || size > 4 || size ==3)
These size constraints are a bit funky. Instead of
!size || size > 4 || size == 3we write!(size == 1 || size == 2 || size == 4)?
Good idea, thanks.
Quoted 66 lines
Quoted 31 lines
drivers/fsi/fsi-master-i2cr.c new file +21
-0+return -EINVAL ; + +mutex_lock (&i2cr->lock); + + ret =i2cr_transfer (i2cr->client,I2CR_ADDRESS_CFAM (addr), &data); +if (ret) + goto unlock; + + ret =i2cr_check_status (i2cr->client); +if (ret) + goto unlock; + +trace_i2cr_read (addr, size, (__force uint32_t )data); +memcpy (val, &data, size); + +unlock: +mutex_unlock (&i2cr->lock); +return ret; +} + +static int i2cr_write(struct fsi_master *master, int link, uint8_t id,
uint32_taddr,drivers/fsi/fsi-master-i2cr.c new file +3
-0+ const void *val, size_t size) +{ + struct fsi_master_i2cr *i2cr = container_of(master, struct
fsi_master_i2cr, master);drivers/fsi/fsi-master-i2cr.c new file +4
-0+__be32 data[3 ]; +int ret; + + if (link || id || (addr & 0xffff0000) || !size || size > 4 || size ==Quoted 1 line
3)
As above
Quoted 5 lines
drivers/fsi/fsi-master-i2cr.c new file +5
-0+return -EINVAL ; + + data[1 ] =0 ; +memcpy (&data[1 ], val, size); + data[0] = i2cr_get_command(I2CR_ADDRESS_CFAM(addr),drivers/fsi/fsi-master-i2cr.c line 158
Quoted 10 lines
drivers/fsi/fsi-master-i2cr.c new file +10
-0+ i2cr_check_parity((__force u32)data[1], true)); + data[2 ] =0 ; + +mutex_lock (&i2cr->lock); + + ret =i2c_master_send (i2cr->client, (const char *)data,sizeof (data)); +if (ret ==sizeof (data)) { + ret =i2cr_check_status (i2cr->client); +if (!ret) +trace_i2cr_write (addr, size, (__force uint32_t )data[1 ]);I think we can reduce the amount of
__forceif we flip the endianness of the data variable?``` u32 data[3]; __be32 cmd_be; data[1] = 0; memcpy(&data[1], val, size); cmd_be = i2cr_get_command(I2CR_ADDRESS_CFAM(addr), i2cr_check_parity(data[1], true)); data[0] = (__force u32)cmd_be; data[2] = 0; .... trace_i2cr_write(addr, size, data[1]); ```
Quoted 3 lines
?
Or define
i2cr_check_parity()and the tracepoint in terms of big-endian?
I think I'll define a struct with the command as __be32 and the data as u32. That should clean it up.
Quoted 43 lines
Quoted 43 lines
drivers/fsi/fsi-master-i2cr.c new file +42
-0+ }else { +trace_i2cr_i2c_error (ret); + +if (ret >=0 ) + ret = -EIO ; + } + +mutex_unlock (&i2cr->lock); +return ret; +} + +static int i2cr_probe (struct i2c_client *client) +{ +struct fsi_master_i2cr *i2cr; +int ret; + + i2cr =devm_kzalloc (&client->dev,sizeof (*i2cr),GFP_KERNEL ); +if (!i2cr) +return -ENOMEM ; + + i2cr->master.dev.parent = &client->dev; + i2cr->master.dev.of_node =of_node_get (dev_of_node (&client->dev)); + + i2cr->master.n_links =1 ; + i2cr->master.read = i2cr_read; + i2cr->master.write = i2cr_write; + +mutex_init (&i2cr->lock); + i2cr->client = client; + + ret =fsi_master_register (&i2cr->master); +if (ret) +return ret; + +i2c_set_clientdata (client, i2cr); +return 0 ; +} + +static int i2cr_remove (struct i2c_client *client) +{ +struct fsi_master_i2cr *i2cr =i2c_get_clientdata (client); +
Quoted 8 lines
drivers/fsi/fsi-master-i2cr.c line 207
Quoted 7 lines
drivers/fsi/fsi-master-i2cr.c new file +7
-0+fsi_master_unregister (&i2cr->master); + +return 0 ; +} + +static const struct of_device_id i2cr_i2c_ids[] = { + { .compatible ="ibm,i2cr" , },This may need an update after discussion on the binding patch.
Yep.
Thanks for the review!
Eddie
Quoted 2 lines
Andrew
kernel test robot
build botI love your patch! Yet something to improve:
Hi Eddie,
I love your patch! Yet something to improve:
[auto build test ERROR on robh/for-next]
[also build test ERROR on linus/master v6.2-rc4 next-20230120] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Eddie-James/dt-bindings-fsi-Document-the-IBM-I2C-Responder-virtual-FSI-master/20230120-014831 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/20230119174714.1486042-3-eajames%40linux.ibm.com patch subject: [PATCH 2/2] fsi: Add IBM I2C Responder virtual FSI master config: alpha-allyesconfig (https://download.01.org/0day-ci/archive/20230120/[email protected]/config) compiler: alpha-linux-gcc (GCC) 12.1.0
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# https://github.com/intel-lab-lkp/linux/commit/1312ba80b81ef02457d213ee6bc6ee80739c3e01
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Eddie-James/dt-bindings-fsi-Document-the-IBM-I2C-Responder-virtual-FSI-master/20230120-014831 git checkout 1312ba80b81ef02457d213ee6bc6ee80739c3e01
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=alpha olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-12.1.0 make.cross W=1 O=build_dir ARCH=alpha SHELL=/bin/bash
If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <[email protected]>
All errors (new ones prefixed by >>):
>> drivers/fsi/fsi-master-i2cr.c:214:19: error: initialization of 'void (*)(struct i2c_client *)' from incompatible pointer type 'int (*)(struct i2c_client *)' [-Werror=incompatible-pointer-types]
214 | .remove = i2cr_remove,
| ^~~~~~~~~~~
drivers/fsi/fsi-master-i2cr.c:214:19: note: (near initialization for 'i2cr_driver.remove')
cc1: some warnings being treated as errors
vim +214 drivers/fsi/fsi-master-i2cr.c
211
212 static struct i2c_driver i2cr_driver = {
213 .probe_new = i2cr_probe,
> 214 .remove = i2cr_remove,
215 .driver = {
216 .name = "i2cr",
217 .of_match_table = i2cr_i2c_ids,
218 },
219 };
220
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests
kernel test robot
build botI love your patch! Yet something to improve:
Hi Eddie,
I love your patch! Yet something to improve:
[auto build test ERROR on robh/for-next]
[also build test ERROR on linus/master v6.2-rc4 next-20230120] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Eddie-James/dt-bindings-fsi-Document-the-IBM-I2C-Responder-virtual-FSI-master/20230120-014831 base: https://git.kernel.org/pub/scm/linux/kernel/git/robh/linux.git for-next patch link: https://lore.kernel.org/r/20230119174714.1486042-3-eajames%40linux.ibm.com patch subject: [PATCH 2/2] fsi: Add IBM I2C Responder virtual FSI master config: arm-randconfig-c002-20230120 (https://download.01.org/0day-ci/archive/20230121/[email protected]/config) compiler: clang version 16.0.0 (https://github.com/llvm/llvm-project 4196ca3278f78c6e19246e54ab0ecb364e37d66a)
reproduce (this is a W=1 build):
wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
chmod +x ~/bin/make.cross
# install arm cross compiling tool for clang build
# apt-get install binutils-arm-linux-gnueabi
# https://github.com/intel-lab-lkp/linux/commit/1312ba80b81ef02457d213ee6bc6ee80739c3e01
git remote add linux-review https://github.com/intel-lab-lkp/linux
git fetch --no-tags linux-review Eddie-James/dt-bindings-fsi-Document-the-IBM-I2C-Responder-virtual-FSI-master/20230120-014831 git checkout 1312ba80b81ef02457d213ee6bc6ee80739c3e01
# save the config file
mkdir build_dir && cp config build_dir/.config
COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm olddefconfig COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross W=1 O=build_dir ARCH=arm SHELL=/bin/bash drivers/fsi/
If you fix the issue, kindly add following tag where applicable | Reported-by: kernel test robot <[email protected]>
All errors (new ones prefixed by >>):
>> drivers/fsi/fsi-master-i2cr.c:214:12: error: incompatible function pointer types initializing 'void (*)(struct i2c_client *)' with an expression of type 'int (struct i2c_client *)' [-Wincompatible-function-pointer-types]
.remove = i2cr_remove,
^~~~~~~~~~~
1 error generated.
vim +214 drivers/fsi/fsi-master-i2cr.c
211
212 static struct i2c_driver i2cr_driver = {
213 .probe_new = i2cr_probe,
> 214 .remove = i2cr_remove,
215 .driver = {
216 .name = "i2cr",
217 .of_match_table = i2cr_i2c_ids,
218 },
219 };
220
Signature · 2 lines
0-DAY CI Kernel Test Service https://github.com/intel/lkp-tests