The following series of patches add support for CAN transceivers.
TCAN1042 has a standby signal that needs to be pulled high for
sending/receiving messages[1]. TCAN1043 has a enable signal along with
standby signal that needs to be pulled up for sending/receiving
messages[2], and other combinations of the two lines can be used to put the
transceiver in different states to reduce power consumption. On boards
like the AM654-idk and J721e-evm these signals are controlled using gpios.
Patch 1 rewords the comment that restricts max_link_rate attribute to have
units of Mbps.
Patch 2 adds an API for devm_of_phy_optional_get_by_index
Patch 3 models the transceiver as a phy device tree node with properties
for max bit rate supported, gpio properties for indicating gpio pin numbers
to which standby and enable signals are connected.
Patch 4 adds a generic driver to support CAN transceivers.
Patches 5 & 6 add support for implementing the transceiver as a phy of
m_can_platform driver.
changes since v1:
- Added patch 1 (in v2) that rewords the comment that restrict
max_link_rate attribute to have units of Mbps.
- Added patch 2 (in v2) that adds an API for
devm_of_phy_optional_get_by_index
- Patch 1 (in v1)
- updated MAINTAINERS file
- Patch 2 (in v1)
- replaced m_can with CAN to make the driver independent of CAN driver
- Added prefix CAN_TRANSCEIVER for EN_PRESENT and STB_PRESENT
- Added new line before return statements in power_on() and power_off
- Added error handling patch for devm_kzalloc()
- used the max_link_rate attribute directly instead of dividing it by
1000000
- removed the spaces before GPIOD_OUT_LOW in devm_gpiod_get()
- Corrected requested value for standby-gpios to GPIOD_OUT_HIGH
- Updated MAINTAINERS file
- Patch 3 (in v1)
- replaced minItems with maxItems
- Removed phy-names property as there is only one phy
- Patch 4 (in v1)
- replaced dev_warn with dev_info when no transceiver is found
- Added struct phy * field in m_can_classdev struct
- moved phy_power_on and phy_power_off to m_can_open and m_can_close
respectively
- Moved the check for max_bit_rate to generice transceiver driver
[1] - https://www.ti.com/lit/ds/symlink/tcan1042h.pdf
[2] - https://www.ti.com/lit/ds/symlink/tcan1043-q1.pdf
Aswath Govindraju (4):
phy: core: Reword the comment specifying the units of max_link_rate to
be Mbps
phy: Add API for devm_of_phy_optional_get_by_index
dt-bindings: phy: Add binding for TI TCAN104x CAN transceivers
phy: phy-can-transceiver: Add support for generic CAN transceiver
driver
Faiz Abbas (2):
dt-bindings: net: can: Document transceiver implementation as phy
can: m_can: Add support for transceiver as phy
.../bindings/net/can/bosch,m_can.yaml | 3 +
.../bindings/phy/ti,tcan104x-can.yaml | 56 +++++++
MAINTAINERS | 2 +
drivers/net/can/m_can/m_can.c | 18 +++
drivers/net/can/m_can/m_can.h | 2 +
drivers/net/can/m_can/m_can_platform.c | 15 ++
drivers/phy/Kconfig | 9 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-can-transceiver.c | 146 ++++++++++++++++++
drivers/phy/phy-core.c | 26 ++++
include/linux/phy/phy.h | 4 +-
11 files changed, 281 insertions(+), 1 deletion(-)
create mode 100644 Documentation/devicetree/bindings/phy/ti,tcan104x-can.yaml
create mode 100644 drivers/phy/phy-can-transceiver.c
--
2.17.1
Add API for devm_of_phy_optional_get_by_index, to obtain a reference to an
optional phy by index.
Signed-off-by: Aswath Govindraju <redacted>
---
drivers/phy/phy-core.c | 26 ++++++++++++++++++++++++++
include/linux/phy/phy.h | 2 ++
2 files changed, 28 insertions(+)
In some subsystems (eg. CAN, SPI), the max link rate supported can be less
than 1 Mbps and if the unit for max_link_rate is Mbps then it can't be
used. Therefore, leave the decision of units to be used, to the producer
and consumer.
Signed-off-by: Aswath Govindraju <redacted>
---
include/linux/phy/phy.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
@@ -0,0 +1,56 @@+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)+%YAML1.2+---+$id:"http://devicetree.org/schemas/phy/ti,tcan104x-can.yaml#"+$schema:"http://devicetree.org/meta-schemas/core.yaml#"++title:TCAN104x CAN TRANSCEIVER PHY++maintainers:+-Aswath Govindraju <a-govindraju@ti.com>++properties:+$nodename:+pattern:"^tcan104x-phy"++compatible:+enum:+-ti,tcan1042+-ti,tcan1043++'#phy-cells':+const:0++standby-gpios:+description:+gpio node to toggle standby signal on transceiver+maxItems:1++enable-gpios:+description:+gpio node to toggle enable signal on transceiver+maxItems:1++max-bitrate:+$ref:/schemas/types.yaml#/definitions/uint32+description:+max bit rate supported in bps+minimum:1++required:+-compatible+-'#phy-cells'++additionalProperties:false++examples:+-|+#include <dt-bindings/gpio/gpio.h>++transceiver1:tcan104x-phy {+compatible = "ti,tcan1043";+#phy-cells = <0>;+max-bitrate = <5000000>;+standby-gpios = <&wakeup_gpio1 16 GPIO_ACTIVE_LOW>;+enable-gpios = <&main_gpio1 67 GPIO_ACTIVE_LOW>;+};
The driver adds support for generic CAN transceivers. Currently
the modes supported by this driver are standby and normal modes for TI
TCAN1042 and TCAN1043 CAN transceivers.
The transceiver is modelled as a phy with pins controlled by gpios, to put
the transceiver in various device functional modes. It also gets the phy
attribute max_link_rate for the usage of CAN drivers.
Signed-off-by: Aswath Govindraju <redacted>
---
MAINTAINERS | 1 +
drivers/phy/Kconfig | 9 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-can-transceiver.c | 146 ++++++++++++++++++++++++++++++
4 files changed, 157 insertions(+)
create mode 100644 drivers/phy/phy-can-transceiver.c
@@ -0,0 +1,146 @@+// SPDX-License-Identifier: GPL-2.0+/*+*phy-can-transceiver.c-phydriverforCANtransceivers+*+*Copyright(C)2021TexasInstrumentsIncorporated-http://www.ti.com+*+*/+#include<linux/phy/phy.h>+#include<linux/platform_device.h>+#include<linux/module.h>+#include<linux/gpio.h>+#include<linux/gpio/consumer.h>++structcan_transceiver_data{+u32flags;+#define CAN_TRANSCEIVER_STB_PRESENT BIT(0)+#define CAN_TRANSCEIVER_EN_PRESENT BIT(1)+};++structcan_transceiver_phy{+structphy*generic_phy;+structgpio_desc*standby_gpio;+structgpio_desc*enable_gpio;+};++/* Power on function */+staticintcan_transceiver_phy_power_on(structphy*phy)+{+structcan_transceiver_phy*can_transceiver_phy=phy_get_drvdata(phy);++if(can_transceiver_phy->standby_gpio)+gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio,0);+if(can_transceiver_phy->enable_gpio)+gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio,1);++return0;+}++/* Power off function */+staticintcan_transceiver_phy_power_off(structphy*phy)+{+structcan_transceiver_phy*can_transceiver_phy=phy_get_drvdata(phy);++if(can_transceiver_phy->standby_gpio)+gpiod_set_value_cansleep(can_transceiver_phy->standby_gpio,1);+if(can_transceiver_phy->enable_gpio)+gpiod_set_value_cansleep(can_transceiver_phy->enable_gpio,0);++return0;+}++staticconststructphy_opscan_transceiver_phy_ops={+.power_on=can_transceiver_phy_power_on,+.power_off=can_transceiver_phy_power_off,+.owner=THIS_MODULE,+};++staticconststructcan_transceiver_datatcan1042_drvdata={+.flags=CAN_TRANSCEIVER_STB_PRESENT,+};++staticconststructcan_transceiver_datatcan1043_drvdata={+.flags=CAN_TRANSCEIVER_STB_PRESENT|CAN_TRANSCEIVER_EN_PRESENT,+};++staticconststructof_device_idcan_transceiver_phy_ids[]={+{+.compatible="ti,tcan1042",+.data=&tcan1042_drvdata+},+{+.compatible="ti,tcan1043",+.data=&tcan1043_drvdata+},+{}+};+MODULE_DEVICE_TABLE(of,can_transceiver_phy_ids);++intcan_transceiver_phy_probe(structplatform_device*pdev)+{+structphy_provider*phy_provider;+structdevice*dev=&pdev->dev;+structcan_transceiver_phy*can_transceiver_phy;+conststructcan_transceiver_data*drvdata;+conststructof_device_id*match;+structphy*phy;+structgpio_desc*standby_gpio;+structgpio_desc*enable_gpio;+u32max_bitrate=0;++can_transceiver_phy=devm_kzalloc(dev,sizeof(structcan_transceiver_phy),GFP_KERNEL);+if(!can_transceiver_phy)+return-ENOMEM;++match=of_match_node(can_transceiver_phy_ids,pdev->dev.of_node);+drvdata=match->data;++phy=devm_phy_create(dev,dev->of_node,+&can_transceiver_phy_ops);+if(IS_ERR(phy)){+dev_err(dev,"failed to create can transceiver phy\n");+returnPTR_ERR(phy);+}++device_property_read_u32(dev,"max-bitrate",&max_bitrate);+if(!max_bitrate)+dev_warn(dev,"Invalid value for transceiver max bitrate. Ignoring bitrate limit\n");+phy->attrs.max_link_rate=max_bitrate;++can_transceiver_phy->generic_phy=phy;++if(drvdata->flags&CAN_TRANSCEIVER_STB_PRESENT){+standby_gpio=devm_gpiod_get(dev,"standby",GPIOD_OUT_HIGH);+if(IS_ERR(standby_gpio))+returnPTR_ERR(standby_gpio);+can_transceiver_phy->standby_gpio=standby_gpio;+}++if(drvdata->flags&CAN_TRANSCEIVER_EN_PRESENT){+enable_gpio=devm_gpiod_get(dev,"enable",GPIOD_OUT_LOW);+if(IS_ERR(enable_gpio))+returnPTR_ERR(enable_gpio);+can_transceiver_phy->enable_gpio=enable_gpio;+}++phy_set_drvdata(can_transceiver_phy->generic_phy,can_transceiver_phy);++phy_provider=devm_of_phy_provider_register(dev,of_phy_simple_xlate);++returnPTR_ERR_OR_ZERO(phy_provider);+}++staticstructplatform_drivercan_transceiver_phy_driver={+.probe=can_transceiver_phy_probe,+.driver={+.name="can-transceiver-phy",+.of_match_table=can_transceiver_phy_ids,+},+};++module_platform_driver(can_transceiver_phy_driver);++MODULE_AUTHOR("Faiz Abbas <faiz_abbas@ti.com>");+MODULE_AUTHOR("Aswath Govindraju <a-govindraju@ti.com>");+MODULE_DESCRIPTION("CAN TRANSCEIVER PHY driver");+MODULE_LICENSE("GPL v2");
From: Faiz Abbas <redacted>
Some transceivers need a configuration step (for example, pulling the
standby or enable lines) for them to start sending messages. The
transceiver can be implemented as a phy with the configuration done in the
phy driver. The bit rate limitation can the be obtained by the driver using
the phy node.
Document the above implementation in the bosch mcan bindings
Signed-off-by: Faiz Abbas <redacted>
Signed-off-by: Aswath Govindraju <redacted>
---
Documentation/devicetree/bindings/net/can/bosch,m_can.yaml | 3 +++
1 file changed, 3 insertions(+)
AFAICS the enable gpio is active high.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung West/Dortmund | Phone: +49-231-2826-924 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
From: Marc Kleine-Budde <mkl@pengutronix.de> Date: 2021-04-14 15:39:48
On 14.04.2021 19:35:19, Aswath Govindraju wrote:
quoted hunk
The driver adds support for generic CAN transceivers. Currently
the modes supported by this driver are standby and normal modes for TI
TCAN1042 and TCAN1043 CAN transceivers.
The transceiver is modelled as a phy with pins controlled by gpios, to put
the transceiver in various device functional modes. It also gets the phy
attribute max_link_rate for the usage of CAN drivers.
Signed-off-by: Aswath Govindraju <redacted>
---
MAINTAINERS | 1 +
drivers/phy/Kconfig | 9 ++
drivers/phy/Makefile | 1 +
drivers/phy/phy-can-transceiver.c | 146 ++++++++++++++++++++++++++++++
4 files changed, 157 insertions(+)
create mode 100644 drivers/phy/phy-can-transceiver.c
I'm not sure how the phy framework handles this, but I assume it's
alphabetically sorted, too.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung West/Dortmund | Phone: +49-231-2826-924 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
From: Marc Kleine-Budde <mkl@pengutronix.de> Date: 2021-04-14 15:43:40
On 14.04.2021 19:35:15, Aswath Govindraju wrote:
The following series of patches add support for CAN transceivers.
TCAN1042 has a standby signal that needs to be pulled high for
sending/receiving messages[1]. TCAN1043 has a enable signal along with
standby signal that needs to be pulled up for sending/receiving
messages[2], and other combinations of the two lines can be used to put the
transceiver in different states to reduce power consumption. On boards
like the AM654-idk and J721e-evm these signals are controlled using gpios.
Patch 1 rewords the comment that restricts max_link_rate attribute to have
units of Mbps.
Patch 2 adds an API for devm_of_phy_optional_get_by_index
You probably want to split this into 2 or even 3 separate series. The
first one would be patches 1+2 then 3+4 they can go via the phy tree.
Patches 5+6 can go via linux-can-next
Patch 3 models the transceiver as a phy device tree node with properties
for max bit rate supported, gpio properties for indicating gpio pin numbers
to which standby and enable signals are connected.
Patch 4 adds a generic driver to support CAN transceivers.
Patches 5 & 6 add support for implementing the transceiver as a phy of
m_can_platform driver.
regards,
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung West/Dortmund | Phone: +49-231-2826-924 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
Can you ensure that the 1042 has only the standby gpio and the 1043 has both?
In the driver, it is the way the flags have been set for ti,tcan1042 and
ti,tcan1043.
I was wondering if we would enforce in the DT the 1042 has exactly one
the standby GPIO and the 1043 has exactly the standby and the enable
GPIO.
On the other hand the HW might have pulled one or the other pin high or
low and only one of the pins is connected to a GPIO.
@@ -0,0 +1,56 @@+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)+%YAML1.2+---+$id:"http://devicetree.org/schemas/phy/ti,tcan104x-can.yaml#"+$schema:"http://devicetree.org/meta-schemas/core.yaml#"++title:TCAN104x CAN TRANSCEIVER PHY++maintainers:+-Aswath Govindraju <a-govindraju@ti.com>
Can you create a maintainers entry for this file with your address?
I don't see this being done for other phy yamls in the
Documentation/devicetree/bindings/phy folder. Also,
scripts/get_maintainer.pl is giving the names of maintainers after
reading the yaml files too.
Thanks,
Aswath
Can you ensure that the 1042 has only the standby gpio and the 1043 has both?
In the driver, it is the way the flags have been set for ti,tcan1042 and
ti,tcan1043.
I was wondering if we would enforce in the DT the 1042 has exactly one
the standby GPIO and the 1043 has exactly the standby and the enable
GPIO.
On the other hand the HW might have pulled one or the other pin high or
low and only one of the pins is connected to a GPIO.
Can you create a maintainers entry for this file with your address?
I don't see this being done for other phy yamls in the
Documentation/devicetree/bindings/phy folder. Also,
scripts/get_maintainer.pl is giving the names of maintainers after
reading the yaml files too.
Nice! Clever script.
Marc
--
Pengutronix e.K. | Marc Kleine-Budde |
Embedded Linux | https://www.pengutronix.de |
Vertretung West/Dortmund | Phone: +49-231-2826-924 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |