linux-can-next-for-5.17-20211208
-----BEGIN PGP SIGNATURE----- iQFHBAABCgAxFiEEK3kIWJt9yTYMP3ehqclaivrt76kFAmGwqbcTHG1rbEBwZW5n dXRyb25peC5kZQAKCRCpyVqK+u3vqSGtB/sF8wFDyY50dRG8WQLaeeFIFIZetHni NY6+9ch5xWM6aFDP3ecmGXqZtNaHgeAJVChmyALKs4Sa+5L2F66bGwHHuKu7uG0y 42tz4XSI8B3mZgtVTJ7lKyeu4BismzhJm+iG6I/x3CXo482AxEB2UP53nYssv1vA 8jfjH9gx95sQDXs0WLY2QDvkWS55BgZzpqqcT0K+uqeT+5Ufa2z3oLuCdQbSejNR 3v3kizMp6mBL55z/UbEiR2G7bqZbOtzmAMdhd7g69fKnrav67qnXtyUQpGcOSMWB Y6/xUuwq8JoYVMQfpnzJ1KebW+uwpIyIGL/e8GOLlkVioWWfMqLz5bv0 =7p/y -----END PGP SIGNATURE----- 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.de Signed-off-by: Jakub Kicinski <kuba@kernel.org>
This commit is contained in:
Коммит
a43a072021
|
@ -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 = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||
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 @@
|
|||
#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 = <GIC_SPI 26 IRQ_TYPE_LEVEL_HIGH>;
|
||||
clocks = <&ccu CLK_BUS_CAN>;
|
||||
resets = <&ccu RST_BUS_CAN>;
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
i2c4: i2c@1c2c000 {
|
||||
compatible = "allwinner,sun6i-a31-i2c";
|
||||
reg = <0x01c2c000 0x400>;
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
* Copyright (C) 2008-2009 Wolfgang Grandegger <wg@grandegger.com>
|
||||
*/
|
||||
|
||||
#include <linux/units.h>
|
||||
#include <linux/can/dev.h>
|
||||
|
||||
#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;
|
||||
|
|
|
@ -25,11 +25,11 @@
|
|||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/mod_devicetable.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/netdevice.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/property.h>
|
||||
#include <linux/regulator/consumer.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/spi/spi.h>
|
||||
|
@ -828,19 +828,25 @@ 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;
|
||||
int freq, ret;
|
||||
u32 freq;
|
||||
int ret;
|
||||
|
||||
clk = devm_clk_get(&spi->dev, NULL);
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(&spi->dev, "no CAN clock source defined\n");
|
||||
return PTR_ERR(clk);
|
||||
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");
|
||||
|
||||
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");
|
||||
}
|
||||
freq = clk_get_rate(clk);
|
||||
|
||||
/* Sanity check */
|
||||
if (freq > 40000000)
|
||||
|
@ -851,11 +857,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;
|
||||
|
@ -870,8 +874,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;
|
||||
|
@ -918,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);
|
||||
|
@ -938,14 +941,12 @@ 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);
|
||||
|
||||
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)
|
||||
|
@ -957,8 +958,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);
|
||||
|
||||
|
|
|
@ -61,6 +61,7 @@
|
|||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/units.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#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,
|
||||
|
|
|
@ -12,6 +12,7 @@
|
|||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/units.h>
|
||||
#include <asm/unaligned.h>
|
||||
|
||||
#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,
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче