Mcp2515 CANbus modul and wrong clock 5500000 instead of 8000000

Khadas VIM3, Ubuntu, 20.04 fenix build 1.0.11

Hi all,
I have a problem with clock with mcp2515 module.
Driver wrong identify crystal clock and define as value 5,5Mhz (5500000).
I searched one in the code of driver but i hope the value have to be setting another way.

Could you be so kind and help me about this one? Maybe in define overlays? I trying many combination but unsuccessful.

Many thanks!

Every combination I’ve got:

root@DZT-1-4RECO01:/home/khadas# ip -details link show can0
3: can0: <NOARP,UP,LOWER_UP,ECHO> mtu 16 qdisc pfifo_fast state UP mode DEFAULT group default qlen 65536
link/can promiscuity 0
can state ERROR-ACTIVE restart-ms 100
bitrate 500000 sample-point 0.818
tq 181 prop-seg 4 phase-seg1 4 phase-seg2 2 sjw 1
mcp251x: tseg1 3…16 tseg2 2…8 sjw 1…4 brp 1…64 brp-inc 1
clock 5500000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535

The code of drive is:

Blockquote

.
static int mcp251x_can_probe(struct spi_device *spi)
{
const struct of_device_id *of_id = of_match_device(mcp251x_of_match,
&spi->dev);
// struct mcp251x_platform_data *pdata = dev_get_platdata(&spi->dev);
struct net_device *net;
struct mcp251x_priv *priv;
struct clk *clk;
int freq, ret;

/* clk = devm_clk_get(&spi->dev, NULL);
if (IS_ERR(clk)) {
if (pdata)
freq = pdata->oscillator_frequency;
else
return PTR_ERR(clk);
} else {
freq = clk_get_rate(clk);
}*/

freq = 11000000;

    /* Sanity check */
    if (freq < 1000000 || freq > 25000000)
            return -ERANGE;

    /* Allocate can/net device */
    net = alloc_candev(sizeof(struct mcp251x_priv), TX_ECHO_SKB_MAX);
    if (!net)
            return -ENOMEM;

    if (!IS_ERR(clk)) {
            ret = clk_prepare_enable(clk);
            if (ret)
                    goto out_free;
    }



    net->netdev_ops = &mcp251x_netdev_ops;
    net->flags |= IFF_ECHO;

    priv = netdev_priv(net);
    priv->can.bittiming_const = &mcp251x_bittiming_const;
    priv->can.do_set_mode = mcp251x_do_set_mode;

priv->can.clock.freq = freq / 2;

    priv->can.ctrlmode_supported = CAN_CTRLMODE_3_SAMPLES |
            CAN_CTRLMODE_LOOPBACK | CAN_CTRLMODE_LISTENONLY;
    if (of_id)
            priv->model = (enum mcp251x_model)of_id->data;
    else
            priv->model = spi_get_device_id(spi)->driver_data;
    priv->net = net;
    priv->clk = clk;

Blockquote

@necone hi,
You can configure the clock frequency of MCP2515 in the device tree.

Add the following patch modifications::

diff --git a/arch/arm64/boot/dts/amlogic/overlays/kvim3/can.dts b/arch/arm64/boot/dts/amlogic/overlays/kvim3/can.dts
index 9a63c14595a8..61659630327e 100644
--- a/arch/arm64/boot/dts/amlogic/overlays/kvim3/can.dts
+++ b/arch/arm64/boot/dts/amlogic/overlays/kvim3/can.dts
@@ -12,9 +12,10 @@
                        status = "okay";

                        can0: mcp2515@0 {
-                               spi-max-frequency = <2000000>;
+                               spi-max-frequency = <10000000>;
                                compatible = "microchip,mcp2515";
                                reg = <0>;
+                               clocks = <16000000>;
                                int-gpio = <&gpio GPIOA_15 GPIO_ACTIVE_LOW>;
                                status = "okay";
                        };
diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c
index ac826c50462f..d21f3b4d0416 100644
--- a/drivers/net/can/spi/mcp251x.c
+++ b/drivers/net/can/spi/mcp251x.c
@@ -1051,7 +1051,8 @@ static int mcp251x_can_probe(struct spi_device *spi)
        struct net_device *net;
        struct mcp251x_priv *priv;
        struct clk *clk;
-       int freq, ret;
+       int ret;
+       unsigned int freq;

 /*     clk = devm_clk_get(&spi->dev, NULL);
        if (IS_ERR(clk)) {
@@ -1062,7 +1063,8 @@ static int mcp251x_can_probe(struct spi_device *spi)
        } else {
                freq = clk_get_rate(clk);
        }*/
-       freq = 11000000;
+//     freq = 11000000;
+       of_property_read_u32(spi->dev.of_node, "clocks", &freq);

        /* Sanity check */
        if (freq < 1000000 || freq > 25000000)

Test results:

khadas@Khadas:~$  ip -details link show can0
3: can0: <NOARP,ECHO> mtu 16 qdisc noop state DOWN mode DEFAULT group default qlen 10
    link/can  promiscuity 0 
    can state STOPPED restart-ms 0 
          mcp251x: tseg1 3..16 tseg2 2..8 sjw 1..4 brp 1..64 brp-inc 1
          clock 8000000 numtxqueues 1 numrxqueues 1 gso_max_size 65536 gso_max_segs 65535 

clock is 8000000.

2 Likes

Hi Jack,
Superb! Thank you very much! I’ts look like function solution.
Yesterday I can reach some resolut, but I apply different workaround. I modify “freq = 11000000” and rewrite to 16000000.
I don’t know what solution is most clear, but it’s function and w’re happy :slight_smile:
It’s important that the solution can google one :grinning:

Again, thank you and have a nice day!

@necone hi,
Nice,
No problem, please give me a like!!!
The follow-up will provide you with better service.
Thank you! :smile:

1 Like

I did it :wink:
One more think. Could you so kind and help me how I deploy my compilled kernel to another device instead of whole process imaging? Suffices the link :slight_smile:
THX!

@necone
You should back up your firmware first,
Refer to the following link:

1 Like

Yes we use one. But the device is out of house :frowning:
I search metod how to kernel with mcp2515 patch deploy remotely.
Anyway many thanks!

make kernel
make kernel-deb

upload one and:
sudo dpkg -i linux-dtb-amlogig-4.9_1.0.11_arm64.deb

sudo dpkg -i linux-image-amlogic-4.9_1.0.11_arm64.deb

sudo dpkg -i linux-headers-amlogic-4.9_1.0.11_arm64.deb

Cheers :wink: