Commit a43a0720 authored by Jakub Kicinski's avatar Jakub Kicinski

Merge tag 'linux-can-next-for-5.17-20211208' of...

Merge tag 'linux-can-next-for-5.17-20211208' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next

Marc Kleine-Budde says:

====================
can-next 2021-12-08

The first patch is by Vincent Mailhol and replaces the custom CAN
units with generic one form linux/units.h.

The next 3 patches are by Evgeny Boger and add Allwinner R40 support
to the sun4i CAN driver.

Andy Shevchenko contributes 4 patches to the hi311x CAN driver,
consisting of cleanups and converting the driver to the device
property API.

* tag 'linux-can-next-for-5.17-20211208' of git://git.kernel.org/pub/scm/linux/kernel/git/mkl/linux-can-next:
  can: hi311x: hi3110_can_probe(): convert to use dev_err_probe()
  can: hi311x: hi3110_can_probe(): make use of device property API
  can: hi311x: hi3110_can_probe(): try to get crystal clock rate from property
  can: hi311x: hi3110_can_probe(): use devm_clk_get_optional() to get the input clock
  ARM: dts: sun8i: r40: add node for CAN controller
  can: sun4i_can: add support for R40 CAN controller
  dt-bindings: net: can: add support for Allwinner R40 CAN controller
  can: bittiming: replace CAN units with the generic ones from linux/units.h
====================

Link: https://lore.kernel.org/r/20211208125055.223141-1-mkl@pengutronix.deSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parents 3a262c71 6a93ea38
...@@ -17,6 +17,7 @@ properties: ...@@ -17,6 +17,7 @@ properties:
- const: allwinner,sun7i-a20-can - const: allwinner,sun7i-a20-can
- const: allwinner,sun4i-a10-can - const: allwinner,sun4i-a10-can
- const: allwinner,sun4i-a10-can - const: allwinner,sun4i-a10-can
- const: allwinner,sun8i-r40-can
reg: reg:
maxItems: 1 maxItems: 1
...@@ -27,6 +28,19 @@ properties: ...@@ -27,6 +28,19 @@ properties:
clocks: clocks:
maxItems: 1 maxItems: 1
resets:
maxItems: 1
if:
properties:
compatible:
contains:
const: allwinner,sun8i-r40-can
then:
required:
- resets
required: required:
- compatible - compatible
- reg - reg
...@@ -47,5 +61,15 @@ examples: ...@@ -47,5 +61,15 @@ examples:
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>; interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_APB1_CAN>; 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 = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_CAN>;
resets = <&ccu RST_BUS_CAN>;
};
... ...
...@@ -511,6 +511,16 @@ pio: pinctrl@1c20800 { ...@@ -511,6 +511,16 @@ pio: pinctrl@1c20800 {
#interrupt-cells = <3>; #interrupt-cells = <3>;
#gpio-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 { clk_out_a_pin: clk-out-a-pin {
pins = "PI12"; pins = "PI12";
function = "clk_out_a"; function = "clk_out_a";
...@@ -926,6 +936,15 @@ i2c3: i2c@1c2b800 { ...@@ -926,6 +936,15 @@ i2c3: i2c@1c2b800 {
#size-cells = <0>; #size-cells = <0>;
}; };
can0: can@1c2bc00 {
compatible = "allwinner,sun8i-r40-can";
reg = <0x01c2bc00 0x400>;
interrupts = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&ccu CLK_BUS_CAN>;
resets = <&ccu RST_BUS_CAN>;
status = "disabled";
};
i2c4: i2c@1c2c000 { i2c4: i2c@1c2c000 {
compatible = "allwinner,sun6i-a31-i2c"; compatible = "allwinner,sun6i-a31-i2c";
reg = <0x01c2c000 0x400>; reg = <0x01c2c000 0x400>;
......
...@@ -4,6 +4,7 @@ ...@@ -4,6 +4,7 @@
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com> * Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
*/ */
#include <linux/units.h>
#include <linux/can/dev.h> #include <linux/can/dev.h>
#ifdef CONFIG_CAN_CALC_BITTIMING #ifdef CONFIG_CAN_CALC_BITTIMING
...@@ -81,9 +82,9 @@ int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt, ...@@ -81,9 +82,9 @@ int can_calc_bittiming(struct net_device *dev, struct can_bittiming *bt,
if (bt->sample_point) { if (bt->sample_point) {
sample_point_nominal = bt->sample_point; sample_point_nominal = bt->sample_point;
} else { } else {
if (bt->bitrate > 800 * CAN_KBPS) if (bt->bitrate > 800 * KILO /* BPS */)
sample_point_nominal = 750; sample_point_nominal = 750;
else if (bt->bitrate > 500 * CAN_KBPS) else if (bt->bitrate > 500 * KILO /* BPS */)
sample_point_nominal = 800; sample_point_nominal = 800;
else else
sample_point_nominal = 875; sample_point_nominal = 875;
......
...@@ -25,11 +25,11 @@ ...@@ -25,11 +25,11 @@
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/netdevice.h> #include <linux/netdevice.h>
#include <linux/of.h>
#include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/property.h>
#include <linux/regulator/consumer.h> #include <linux/regulator/consumer.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
...@@ -828,19 +828,25 @@ MODULE_DEVICE_TABLE(spi, hi3110_id_table); ...@@ -828,19 +828,25 @@ MODULE_DEVICE_TABLE(spi, hi3110_id_table);
static int hi3110_can_probe(struct spi_device *spi) static int hi3110_can_probe(struct spi_device *spi)
{ {
const struct of_device_id *of_id = of_match_device(hi3110_of_match, struct device *dev = &spi->dev;
&spi->dev);
struct net_device *net; struct net_device *net;
struct hi3110_priv *priv; struct hi3110_priv *priv;
const void *match;
struct clk *clk; struct clk *clk;
int freq, ret; u32 freq;
int ret;
clk = devm_clk_get_optional(&spi->dev, NULL);
if (IS_ERR(clk))
return dev_err_probe(dev, PTR_ERR(clk), "no CAN clock source defined\n");
clk = devm_clk_get(&spi->dev, NULL); if (clk) {
if (IS_ERR(clk)) { freq = clk_get_rate(clk);
dev_err(&spi->dev, "no CAN clock source defined\n"); } else {
return PTR_ERR(clk); ret = device_property_read_u32(dev, "clock-frequency", &freq);
if (ret)
return dev_err_probe(dev, ret, "Failed to get clock-frequency!\n");
} }
freq = clk_get_rate(clk);
/* Sanity check */ /* Sanity check */
if (freq > 40000000) if (freq > 40000000)
...@@ -851,11 +857,9 @@ static int hi3110_can_probe(struct spi_device *spi) ...@@ -851,11 +857,9 @@ static int hi3110_can_probe(struct spi_device *spi)
if (!net) if (!net)
return -ENOMEM; return -ENOMEM;
if (!IS_ERR(clk)) { ret = clk_prepare_enable(clk);
ret = clk_prepare_enable(clk); if (ret)
if (ret) goto out_free;
goto out_free;
}
net->netdev_ops = &hi3110_netdev_ops; net->netdev_ops = &hi3110_netdev_ops;
net->flags |= IFF_ECHO; net->flags |= IFF_ECHO;
...@@ -870,8 +874,9 @@ static int hi3110_can_probe(struct spi_device *spi) ...@@ -870,8 +874,9 @@ static int hi3110_can_probe(struct spi_device *spi)
CAN_CTRLMODE_LISTENONLY | CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_BERR_REPORTING; CAN_CTRLMODE_BERR_REPORTING;
if (of_id) match = device_get_match_data(dev);
priv->model = (enum hi3110_model)(uintptr_t)of_id->data; if (match)
priv->model = (enum hi3110_model)(uintptr_t)match;
else else
priv->model = spi_get_device_id(spi)->driver_data; priv->model = spi_get_device_id(spi)->driver_data;
priv->net = net; priv->net = net;
...@@ -918,9 +923,7 @@ static int hi3110_can_probe(struct spi_device *spi) ...@@ -918,9 +923,7 @@ static int hi3110_can_probe(struct spi_device *spi)
ret = hi3110_hw_probe(spi); ret = hi3110_hw_probe(spi);
if (ret) { if (ret) {
if (ret == -ENODEV) dev_err_probe(dev, ret, "Cannot initialize %x. Wrong wiring?\n", priv->model);
dev_err(&spi->dev, "Cannot initialize %x. Wrong wiring?\n",
priv->model);
goto error_probe; goto error_probe;
} }
hi3110_hw_sleep(spi); hi3110_hw_sleep(spi);
...@@ -938,14 +941,12 @@ static int hi3110_can_probe(struct spi_device *spi) ...@@ -938,14 +941,12 @@ static int hi3110_can_probe(struct spi_device *spi)
hi3110_power_enable(priv->power, 0); hi3110_power_enable(priv->power, 0);
out_clk: out_clk:
if (!IS_ERR(clk)) clk_disable_unprepare(clk);
clk_disable_unprepare(clk);
out_free: out_free:
free_candev(net); free_candev(net);
dev_err(&spi->dev, "Probe failed, err=%d\n", -ret); return dev_err_probe(dev, ret, "Probe failed\n");
return ret;
} }
static int hi3110_can_remove(struct spi_device *spi) static int hi3110_can_remove(struct spi_device *spi)
...@@ -957,8 +958,7 @@ static int hi3110_can_remove(struct spi_device *spi) ...@@ -957,8 +958,7 @@ static int hi3110_can_remove(struct spi_device *spi)
hi3110_power_enable(priv->power, 0); hi3110_power_enable(priv->power, 0);
if (!IS_ERR(priv->clk)) clk_disable_unprepare(priv->clk);
clk_disable_unprepare(priv->clk);
free_candev(net); free_candev(net);
......
...@@ -61,6 +61,7 @@ ...@@ -61,6 +61,7 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_device.h> #include <linux/of_device.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/reset.h>
#define DRV_NAME "sun4i_can" #define DRV_NAME "sun4i_can"
...@@ -200,10 +201,20 @@ ...@@ -200,10 +201,20 @@
#define SUN4I_CAN_MAX_IRQ 20 #define SUN4I_CAN_MAX_IRQ 20
#define SUN4I_MODE_MAX_RETRIES 100 #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 sun4ican_priv {
struct can_priv can; struct can_priv can;
void __iomem *base; void __iomem *base;
struct clk *clk; struct clk *clk;
struct reset_control *reset;
spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */ spinlock_t cmdreg_lock; /* lock for concurrent cmd register writes */
}; };
...@@ -702,6 +713,13 @@ static int sun4ican_open(struct net_device *dev) ...@@ -702,6 +713,13 @@ static int sun4ican_open(struct net_device *dev)
goto exit_irq; 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 */ /* turn on clocking for CAN peripheral block */
err = clk_prepare_enable(priv->clk); err = clk_prepare_enable(priv->clk);
if (err) { if (err) {
...@@ -723,6 +741,8 @@ static int sun4ican_open(struct net_device *dev) ...@@ -723,6 +741,8 @@ static int sun4ican_open(struct net_device *dev)
exit_can_start: exit_can_start:
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
exit_clock: exit_clock:
reset_control_assert(priv->reset);
exit_soft_reset:
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
exit_irq: exit_irq:
close_candev(dev); close_candev(dev);
...@@ -736,6 +756,7 @@ static int sun4ican_close(struct net_device *dev) ...@@ -736,6 +756,7 @@ static int sun4ican_close(struct net_device *dev)
netif_stop_queue(dev); netif_stop_queue(dev);
sun4i_can_stop(dev); sun4i_can_stop(dev);
clk_disable_unprepare(priv->clk); clk_disable_unprepare(priv->clk);
reset_control_assert(priv->reset);
free_irq(dev->irq, dev); free_irq(dev->irq, dev);
close_candev(dev); close_candev(dev);
...@@ -750,9 +771,27 @@ static const struct net_device_ops sun4ican_netdev_ops = { ...@@ -750,9 +771,27 @@ static const struct net_device_ops sun4ican_netdev_ops = {
.ndo_start_xmit = sun4ican_start_xmit, .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[] = { 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); MODULE_DEVICE_TABLE(of, sun4ican_of_match);
...@@ -771,10 +810,28 @@ static int sun4ican_probe(struct platform_device *pdev) ...@@ -771,10 +810,28 @@ static int sun4ican_probe(struct platform_device *pdev)
{ {
struct device_node *np = pdev->dev.of_node; struct device_node *np = pdev->dev.of_node;
struct clk *clk; struct clk *clk;
struct reset_control *reset = NULL;
void __iomem *addr; void __iomem *addr;
int err, irq; int err, irq;
struct net_device *dev; struct net_device *dev;
struct sun4ican_priv *priv; 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); clk = of_clk_get(np, 0);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
...@@ -818,6 +875,7 @@ static int sun4ican_probe(struct platform_device *pdev) ...@@ -818,6 +875,7 @@ static int sun4ican_probe(struct platform_device *pdev)
CAN_CTRLMODE_3_SAMPLES; CAN_CTRLMODE_3_SAMPLES;
priv->base = addr; priv->base = addr;
priv->clk = clk; priv->clk = clk;
priv->reset = reset;
spin_lock_init(&priv->cmdreg_lock); spin_lock_init(&priv->cmdreg_lock);
platform_set_drvdata(pdev, dev); platform_set_drvdata(pdev, dev);
......
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/units.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "es58x_core.h" #include "es58x_core.h"
...@@ -469,8 +470,8 @@ const struct es58x_parameters es581_4_param = { ...@@ -469,8 +470,8 @@ const struct es58x_parameters es581_4_param = {
.bittiming_const = &es581_4_bittiming_const, .bittiming_const = &es581_4_bittiming_const,
.data_bittiming_const = NULL, .data_bittiming_const = NULL,
.tdc_const = NULL, .tdc_const = NULL,
.bitrate_max = 1 * CAN_MBPS, .bitrate_max = 1 * MEGA /* BPS */,
.clock = {.freq = 50 * CAN_MHZ}, .clock = {.freq = 50 * MEGA /* Hz */},
.ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC, .ctrlmode_supported = CAN_CTRLMODE_CC_LEN8_DLC,
.tx_start_of_frame = 0xAFAF, .tx_start_of_frame = 0xAFAF,
.rx_start_of_frame = 0xFAFA, .rx_start_of_frame = 0xFAFA,
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
*/ */
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/units.h>
#include <asm/unaligned.h> #include <asm/unaligned.h>
#include "es58x_core.h" #include "es58x_core.h"
...@@ -522,8 +523,8 @@ const struct es58x_parameters es58x_fd_param = { ...@@ -522,8 +523,8 @@ const struct es58x_parameters es58x_fd_param = {
* Mbps work in an optimal environment but are not recommended * Mbps work in an optimal environment but are not recommended
* for production environment. * for production environment.
*/ */
.bitrate_max = 8 * CAN_MBPS, .bitrate_max = 8 * MEGA /* BPS */,
.clock = {.freq = 80 * CAN_MHZ}, .clock = {.freq = 80 * MEGA /* Hz */},
.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY | .ctrlmode_supported = CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY |
CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO | CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_FD | CAN_CTRLMODE_FD_NON_ISO |
CAN_CTRLMODE_CC_LEN8_DLC | CAN_CTRLMODE_TDC_AUTO, CAN_CTRLMODE_CC_LEN8_DLC | CAN_CTRLMODE_TDC_AUTO,
......
...@@ -12,13 +12,6 @@ ...@@ -12,13 +12,6 @@
#define CAN_SYNC_SEG 1 #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 \ #define CAN_CTRLMODE_TDC_MASK \
(CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL) (CAN_CTRLMODE_TDC_AUTO | CAN_CTRLMODE_TDC_MANUAL)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment