From 330c6d3bfa268794bf692165d0f781f1c2d4d83e Mon Sep 17 00:00:00 2001 From: Vincent Mailhol Date: Wed, 24 Nov 2021 10:45:36 +0900 Subject: [PATCH 1/8] can: bittiming: replace CAN units with the generic ones from linux/units.h In [1], we introduced a set of units in linux/can/bittiming.h. Since then, generic SI prefixes were added to linux/units.h in [2]. Those new prefixes can perfectly replace CAN specific ones. This patch replaces all occurrences of the CAN units with their corresponding prefix (from linux/units) and the unit (as a comment) according to below table. CAN units SI metric prefix (from linux/units) + unit (as a comment) ------------------------------------------------------------------------ CAN_KBPS KILO /* BPS */ CAN_MBPS MEGA /* BPS */ CAM_MHZ MEGA /* Hz */ The definition are then removed from linux/can/bittiming.h [1] commit 1d7750760b70 ("can: bittiming: add CAN_KBPS, CAN_MBPS and CAN_MHZ macros") [2] commit 26471d4a6cf8 ("units: Add SI metric prefix definitions") Link: https://lore.kernel.org/all/20211124014536.782550-1-mailhol.vincent@wanadoo.fr Suggested-by: Jimmy Assarsson Suggested-by: Oliver Hartkopp Signed-off-by: Vincent Mailhol Signed-off-by: Marc Kleine-Budde --- drivers/net/can/dev/bittiming.c | 5 +++-- drivers/net/can/usb/etas_es58x/es581_4.c | 5 +++-- drivers/net/can/usb/etas_es58x/es58x_fd.c | 5 +++-- include/linux/can/bittiming.h | 7 ------- 4 files changed, 9 insertions(+), 13 deletions(-) diff --git a/drivers/net/can/dev/bittiming.c b/drivers/net/can/dev/bittiming.c index 0509625c30827..d5fca3bfaf9a3 100644 --- a/drivers/net/can/dev/bittiming.c +++ b/drivers/net/can/dev/bittiming.c @@ -4,6 +4,7 @@ * Copyright (C) 2008-2009 Wolfgang Grandegger */ +#include #include #ifdef CONFIG_CAN_CALC_BITTIMING @@ -81,9 +82,9 @@ int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, if (bt->sample_point) { sample_point_nominal = bt->sample_point; } else { - if (bt->bitrate > 800 * CAN_KBPS) + if (bt->bitrate > 800 * KILO /* BPS */) sample_point_nominal = 750; - else if (bt->bitrate > 500 * CAN_KBPS) + else if (bt->bitrate > 500 * KILO /* BPS */) sample_point_nominal = 800; else sample_point_nominal = 875; diff --git a/drivers/net/can/usb/etas_es58x/es581_4.c b/drivers/net/can/usb/etas_es58x/es581_4.c index 14e360c9f2c9a..1bcdcece5ec72 100644 --- a/drivers/net/can/usb/etas_es58x/es581_4.c +++ b/drivers/net/can/usb/etas_es58x/es581_4.c @@ -10,6 +10,7 @@ */ #include +#include #include #include "es58x_core.h" @@ -469,8 +470,8 @@ const struct es58x_parameters es581_4_param = { .bittiming_const = &es581_4_bittiming_const, .data_bittiming_const = NULL, .tdc_const = NULL, - .bitrate_max = 1 * CAN_MBPS, - .clock = {.freq = 50 * CAN_MHZ}, + .bitrate_max = 1 * MEGA /* BPS */, + .clock = {.freq = 50 * MEGA /* Hz */}, .ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC, .tx_start_of_frame = 0xAFAF, .rx_start_of_frame = 0xFAFA, diff --git a/drivers/net/can/usb/etas_es58x/es58x_fd.c b/drivers/net/can/usb/etas_es58x/es58x_fd.c index 4f0cae29f4d8b..ec87126e1a7df 100644 --- a/drivers/net/can/usb/etas_es58x/es58x_fd.c +++ b/drivers/net/can/usb/etas_es58x/es58x_fd.c @@ -12,6 +12,7 @@ */ #include +#include #include #include "es58x_core.h" @@ -522,8 +523,8 @@ const struct es58x_parameters es58x_fd_param = { * Mbps work in an optimal environment but are not recommended * for production environment. */ - .bitrate_max = 8 * CAN_MBPS, - .clock = {.freq = 80 * CAN_MHZ}, + .bitrate_max = 8 * MEGA /* BPS */, + .clock = {.freq = 80 * MEGA /* Hz */}, .ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO | CAN_CTRLMODE_CC_LEN8_DLC | CAN_CTRLMODE_TDC_AUTO, diff --git a/include/linux/can/bittiming.h b/include/linux/can/bittiming.h index 20b50baf3a02d..a81652d1c6f30 100644 --- a/include/linux/can/bittiming.h +++ b/include/linux/can/bittiming.h @@ -12,13 +12,6 @@ #define CAN_SYNC_SEG 1 -/* Kilobits and Megabits per second */ -#define CAN_KBPS 1000UL -#define CAN_MBPS 1000000UL - -/* Megahertz */ -#define CAN_MHZ 1000000UL - #define CAN_CTRLMODE_TDC_MASK \ (CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL) From d0342ceb78ed86b8ed28afe14d070720667da70f Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 22 Nov 2021 13:46:14 +0300 Subject: [PATCH 2/8] dt-bindings: net: can: add support for Allwinner R40 CAN controller Allwinner R40 (also known as A40i, T3, V40) has a CAN controller. The controller is the same as in earlier A10 and A20 SoCs, but needs reset line to be deasserted before use. This patch Introduces new compatible for R40 CAN controller with required resets property. Link: https://lore.kernel.org/all/20211122104616.537156-2-boger@wirenboard.com Signed-off-by: Evgeny Boger Reviewed-by: Rob Herring Signed-off-by: Marc Kleine-Budde --- .../net/can/allwinner,sun4i-a10-can.yaml | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/Documentation/devicetree/bindings/net/can/allwinner,sun4i-a10-can.yaml b/Documentation/devicetree/bindings/net/can/allwinner,sun4i-a10-can.yaml index a95960ee3feba..c93fe9d3ea824 100644 --- a/Documentation/devicetree/bindings/net/can/allwinner,sun4i-a10-can.yaml +++ b/Documentation/devicetree/bindings/net/can/allwinner,sun4i-a10-can.yaml @@ -17,6 +17,7 @@ properties: - const: allwinner,sun7i-a20-can - const: allwinner,sun4i-a10-can - const: allwinner,sun4i-a10-can + - const: allwinner,sun8i-r40-can reg: maxItems: 1 @@ -27,6 +28,19 @@ properties: clocks: maxItems: 1 + resets: + maxItems: 1 + +if: + properties: + compatible: + contains: + const: allwinner,sun8i-r40-can + +then: + required: + - resets + required: - compatible - reg @@ -47,5 +61,15 @@ examples: interrupts = ; clocks = <&ccu CLK_APB1_CAN>; }; + - | + #define RST_BUS_CAN 68 + #define CLK_BUS_CAN 91 + can1: can@1c2bc00 { + compatible = "allwinner,sun8i-r40-can"; + reg = <0x01c2bc00 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_CAN>; + resets = <&ccu RST_BUS_CAN>; + }; ... From 2c2fd0e68d9e1832d7661f434ee7ddd77bf1b985 Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 22 Nov 2021 13:46:15 +0300 Subject: [PATCH 3/8] can: sun4i_can: add support for R40 CAN controller Allwinner R40 (also known as A40i, T3, V40) has a CAN controller. The controller is the same as in earlier A10 and A20 SoCs, but needs reset line to be deasserted before use. This patch adds a new compatible for R40 CAN controller. Depending on the compatible, reset line can be requested from DT. Link: https://lore.kernel.org/all/20211122104616.537156-3-boger@wirenboard.com Signed-off-by: Evgeny Boger Signed-off-by: Marc Kleine-Budde --- drivers/net/can/sun4i_can.c | 62 +++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/sun4i_can.c b/drivers/net/can/sun4i_can.c index 54aa7c25c4de1..37862e7f6840a 100644 --- a/drivers/net/can/sun4i_can.c +++ b/drivers/net/can/sun4i_can.c @@ -61,6 +61,7 @@ #include #include #include +#include #define DRV_NAME "sun4i_can" @@ -200,10 +201,20 @@ #define SUN4I_CAN_MAX_IRQ 20 #define SUN4I_MODE_MAX_RETRIES 100 +/** + * struct sun4ican_quirks - Differences between SoC variants. + * + * @has_reset: SoC needs reset deasserted. + */ +struct sun4ican_quirks { + bool has_reset; +}; + struct sun4ican_priv { struct can_priv can; void __iomem *base; struct clk *clk; + struct reset_control *reset; spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */ }; @@ -702,6 +713,13 @@ static int sun4ican_open(struct net_device *dev) goto exit_irq; } + /* software reset deassert */ + err = reset_control_deassert(priv->reset); + if (err) { + netdev_err(dev, "could not deassert CAN reset\n"); + goto exit_soft_reset; + } + /* turn on clocking for CAN peripheral block */ err = clk_prepare_enable(priv->clk); if (err) { @@ -723,6 +741,8 @@ static int sun4ican_open(struct net_device *dev) exit_can_start: clk_disable_unprepare(priv->clk); exit_clock: + reset_control_assert(priv->reset); +exit_soft_reset: free_irq(dev->irq, dev); exit_irq: close_candev(dev); @@ -736,6 +756,7 @@ static int sun4ican_close(struct net_device *dev) netif_stop_queue(dev); sun4i_can_stop(dev); clk_disable_unprepare(priv->clk); + reset_control_assert(priv->reset); free_irq(dev->irq, dev); close_candev(dev); @@ -750,9 +771,27 @@ static const struct net_device_ops sun4ican_netdev_ops = { .ndo_start_xmit = sun4ican_start_xmit, }; +static const struct sun4ican_quirks sun4ican_quirks_a10 = { + .has_reset = false, +}; + +static const struct sun4ican_quirks sun4ican_quirks_r40 = { + .has_reset = true, +}; + static const struct of_device_id sun4ican_of_match[] = { - {.compatible = "allwinner,sun4i-a10-can"}, - {}, + { + .compatible = "allwinner,sun4i-a10-can", + .data = &sun4ican_quirks_a10 + }, { + .compatible = "allwinner,sun7i-a20-can", + .data = &sun4ican_quirks_a10 + }, { + .compatible = "allwinner,sun8i-r40-can", + .data = &sun4ican_quirks_r40 + }, { + /* sentinel */ + }, }; MODULE_DEVICE_TABLE(of, sun4ican_of_match); @@ -771,10 +810,28 @@ static int sun4ican_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; struct clk *clk; + struct reset_control *reset = NULL; void __iomem *addr; int err, irq; struct net_device *dev; struct sun4ican_priv *priv; + const struct sun4ican_quirks *quirks; + + quirks = of_device_get_match_data(&pdev->dev); + if (!quirks) { + dev_err(&pdev->dev, "failed to determine the quirks to use\n"); + err = -ENODEV; + goto exit; + } + + if (quirks->has_reset) { + reset = devm_reset_control_get_exclusive(&pdev->dev, NULL); + if (IS_ERR(reset)) { + dev_err(&pdev->dev, "unable to request reset\n"); + err = PTR_ERR(reset); + goto exit; + } + } clk = of_clk_get(np, 0); if (IS_ERR(clk)) { @@ -818,6 +875,7 @@ static int sun4ican_probe(struct platform_device *pdev) CAN_CTRLMODE_3_SAMPLES; priv->base = addr; priv->clk = clk; + priv->reset = reset; spin_lock_init(&priv->cmdreg_lock); platform_set_drvdata(pdev, dev); From 671f852c1bee9bd7138a5c4ad2c88d379cd0a6cb Mon Sep 17 00:00:00 2001 From: Evgeny Boger Date: Mon, 22 Nov 2021 13:46:16 +0300 Subject: [PATCH 4/8] ARM: dts: sun8i: r40: add node for CAN controller Allwinner R40 (also known as A40i, T3, V40) has a CAN controller. The controller is the same as in earlier A10 and A20 SoCs, but needs reset line to be deasserted before use. This patch adds a CAN node and the corresponding pinctrl descriptions. Link: https://lore.kernel.org/all/20211122104616.537156-4-boger@wirenboard.com Signed-off-by: Evgeny Boger Signed-off-by: Marc Kleine-Budde --- arch/arm/boot/dts/sun8i-r40.dtsi | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/arch/arm/boot/dts/sun8i-r40.dtsi b/arch/arm/boot/dts/sun8i-r40.dtsi index 1d87fc0c24ee4..c99c92f008a02 100644 --- a/arch/arm/boot/dts/sun8i-r40.dtsi +++ b/arch/arm/boot/dts/sun8i-r40.dtsi @@ -511,6 +511,16 @@ #interrupt-cells = <3>; #gpio-cells = <3>; + can_ph_pins: can-ph-pins { + pins = "PH20", "PH21"; + function = "can"; + }; + + can_pa_pins: can-pa-pins { + pins = "PA16", "PA17"; + function = "can"; + }; + clk_out_a_pin: clk-out-a-pin { pins = "PI12"; function = "clk_out_a"; @@ -926,6 +936,15 @@ #size-cells = <0>; }; + can0: can@1c2bc00 { + compatible = "allwinner,sun8i-r40-can"; + reg = <0x01c2bc00 0x400>; + interrupts = ; + clocks = <&ccu CLK_BUS_CAN>; + resets = <&ccu RST_BUS_CAN>; + status = "disabled"; + }; + i2c4: i2c@1c2c000 { compatible = "allwinner,sun6i-a31-i2c"; reg = <0x01c2c000 0x400>; From 369cf4e6ac53f1595ef8602a8a984bce9b895ddb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 6 Dec 2021 18:55:39 +0200 Subject: [PATCH 5/8] can: hi311x: hi3110_can_probe(): use devm_clk_get_optional() to get the input clock It's not clear what was the intention of redundant usage of IS_ERR() around the clock pointer since with the error check of devm_clk_get() followed by bailout it can't be invalid, Simplify the code which fetches the input clock by using devm_clk_get_optional(). It will allow to switch to device properties approach in the future. Link: https://lore.kernel.org/all/20211206165542.69887-1-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko Signed-off-by: Marc Kleine-Budde --- drivers/net/can/spi/hi311x.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index 89d9c986a2297..13fb979645cf5 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -835,7 +835,7 @@ static int hi3110_can_probe(struct spi_device *spi) struct clk *clk; int freq, ret; - clk = devm_clk_get(&spi->dev, NULL); + clk = devm_clk_get_optional(&spi->dev, NULL); if (IS_ERR(clk)) { dev_err(&spi->dev, "no CAN clock source defined\n"); return PTR_ERR(clk); @@ -851,11 +851,9 @@ static int hi3110_can_probe(struct spi_device *spi) if (!net) return -ENOMEM; - if (!IS_ERR(clk)) { - ret = clk_prepare_enable(clk); - if (ret) - goto out_free; - } + ret = clk_prepare_enable(clk); + if (ret) + goto out_free; net->netdev_ops = &hi3110_netdev_ops; net->flags |= IFF_ECHO; @@ -938,8 +936,7 @@ static int hi3110_can_probe(struct spi_device *spi) hi3110_power_enable(priv->power, 0); out_clk: - if (!IS_ERR(clk)) - clk_disable_unprepare(clk); + clk_disable_unprepare(clk); out_free: free_candev(net); @@ -957,8 +954,7 @@ static int hi3110_can_remove(struct spi_device *spi) hi3110_power_enable(priv->power, 0); - if (!IS_ERR(priv->clk)) - clk_disable_unprepare(priv->clk); + clk_disable_unprepare(priv->clk); free_candev(net); From 3a1ae63a4d218d0d51646380fe406405660b9a5c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 6 Dec 2021 18:55:40 +0200 Subject: [PATCH 6/8] can: hi311x: hi3110_can_probe(): try to get crystal clock rate from property In some configurations, mainly ACPI-based, the clock frequency of the device is supplied by very well established 'clock-frequency' property. Hence, try to get it from the property at last if no other providers are available. Link: https://lore.kernel.org/all/20211206165542.69887-2-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko Signed-off-by: Marc Kleine-Budde --- drivers/net/can/spi/hi311x.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index 13fb979645cf5..c9efdd10d0f8a 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -830,17 +830,26 @@ static int hi3110_can_probe(struct spi_device *spi) { const struct of_device_id *of_id = of_match_device(hi3110_of_match, &spi->dev); + struct device *dev = &spi->dev; struct net_device *net; struct hi3110_priv *priv; struct clk *clk; - int freq, ret; + u32 freq; + int ret; clk = devm_clk_get_optional(&spi->dev, NULL); if (IS_ERR(clk)) { dev_err(&spi->dev, "no CAN clock source defined\n"); return PTR_ERR(clk); } - freq = clk_get_rate(clk); + + if (clk) { + freq = clk_get_rate(clk); + } else { + ret = device_property_read_u32(dev, "clock-frequency", &freq); + if (ret) + return dev_err_probe(dev, ret, "Failed to get clock-frequency!\n"); + } /* Sanity check */ if (freq > 40000000) From dc64d98aae758b41007f89179f3ec8686ef5136c Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 6 Dec 2021 18:55:41 +0200 Subject: [PATCH 7/8] can: hi311x: hi3110_can_probe(): make use of device property API Make use of device property API in this driver so that both OF based system and ACPI based system can use this driver. Link: https://lore.kernel.org/all/20211206165542.69887-3-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko Signed-off-by: Marc Kleine-Budde --- drivers/net/can/spi/hi311x.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index c9efdd10d0f8a..78044ec24575d 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -25,11 +25,11 @@ #include #include #include +#include #include #include -#include -#include #include +#include #include #include #include @@ -828,11 +828,10 @@ MODULE_DEVICE_TABLE(spi, hi3110_id_table); static int hi3110_can_probe(struct spi_device *spi) { - const struct of_device_id *of_id = of_match_device(hi3110_of_match, - &spi->dev); struct device *dev = &spi->dev; struct net_device *net; struct hi3110_priv *priv; + const void *match; struct clk *clk; u32 freq; int ret; @@ -877,8 +876,9 @@ static int hi3110_can_probe(struct spi_device *spi) CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_BERR_REPORTING; - if (of_id) - priv->model = (enum hi3110_model)(uintptr_t)of_id->data; + match = device_get_match_data(dev); + if (match) + priv->model = (enum hi3110_model)(uintptr_t)match; else priv->model = spi_get_device_id(spi)->driver_data; priv->net = net; From 6a93ea38217706ef8318efba672b960bcd5d0642 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 6 Dec 2021 18:55:42 +0200 Subject: [PATCH 8/8] can: hi311x: hi3110_can_probe(): convert to use dev_err_probe() When deferred the reason is saved for further debugging. Besides that, it's fine to call dev_err_probe() in ->probe() when error code is known. Convert the driver to use dev_err_probe(). Link: https://lore.kernel.org/all/20211206165542.69887-4-andriy.shevchenko@linux.intel.com Signed-off-by: Andy Shevchenko Signed-off-by: Marc Kleine-Budde --- drivers/net/can/spi/hi311x.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/drivers/net/can/spi/hi311x.c b/drivers/net/can/spi/hi311x.c index 78044ec24575d..a17641d36468e 100644 --- a/drivers/net/can/spi/hi311x.c +++ b/drivers/net/can/spi/hi311x.c @@ -837,10 +837,8 @@ static int hi3110_can_probe(struct spi_device *spi) int ret; clk = devm_clk_get_optional(&spi->dev, NULL); - if (IS_ERR(clk)) { - dev_err(&spi->dev, "no CAN clock source defined\n"); - return PTR_ERR(clk); - } + if (IS_ERR(clk)) + return dev_err_probe(dev, PTR_ERR(clk), "no CAN clock source defined\n"); if (clk) { freq = clk_get_rate(clk); @@ -925,9 +923,7 @@ static int hi3110_can_probe(struct spi_device *spi) ret = hi3110_hw_probe(spi); if (ret) { - if (ret == -ENODEV) - dev_err(&spi->dev, "Cannot initialize %x. Wrong wiring?\n", - priv->model); + dev_err_probe(dev, ret, "Cannot initialize %x. Wrong wiring?\n", priv->model); goto error_probe; } hi3110_hw_sleep(spi); @@ -950,8 +946,7 @@ static int hi3110_can_probe(struct spi_device *spi) out_free: free_candev(net); - dev_err(&spi->dev, "Probe failed, err=%d\n", -ret); - return ret; + return dev_err_probe(dev, ret, "Probe failed\n"); } static int hi3110_can_remove(struct spi_device *spi)