linux-can.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* Why doesn't the socketcan prio qdisc work for first 10 can frames?
@ 2014-11-27  9:43 Ruan TingQuan (ST-FIR/ENG1-Zhu)
  2014-11-27 11:46 ` Oliver Hartkopp
  0 siblings, 1 reply; 16+ messages in thread
From: Ruan TingQuan (ST-FIR/ENG1-Zhu) @ 2014-11-27  9:43 UTC (permalink / raw)
  To: linux-can@vger.kernel.org

Hello Linux-can-team,

A prio qdisc is created with 8 bands for my different priority sending requirement.  
My test environment: ubuntu 12.04 (kernel 3.11) + PEAK-USB pro (can0 is connect to can1). 
The frame will be send on can0 and receive on can1 (candump)
Below is the setting on can0:
	> ip link set can0 type can bitrate 5000
	> ip link set can1 type can bitrate 5000
	> tc qdisc add dev can0 root handle 1: prio bands 8
	> tc filter add dev $1 parent 1:0 prio 1 basic match canid\(eff 0x1:0x7\) flowid 1:1
	> tc filter add dev $1 parent 1:0 prio 2 basic match canid\(eff 0x2:0x7\) flowid 1:2
	> tc filter add dev $1 parent 1:0 prio 3 basic match canid\(eff 0x3:0x7\) flowid 1:3
	> tc filter add dev $1 parent 1:0 prio 4 basic match canid\(eff 0x4:0x7\) flowid 1:4
	> tc filter add dev $1 parent 1:0 prio 5 basic match canid\(eff 0x5:0x7\) flowid 1:5
	> tc filter add dev $1 parent 1:0 prio 6 basic match canid\(eff 0x6:0x7\) flowid 1:6
	> tc filter add dev $1 parent 1:0 prio 7 basic match canid\(eff 0x7:0x7\) flowid 1:7
	> tc filter add dev $1 parent 1:0 prio 8 basic match canid\(sff 0x0:0x0 eff 0x0:0x0\) flowid 1:8

Then, I made a test program to send 10 frames on can0 socket quickly.
  	can0  81234560   [8]  00 00 00 00 50 50 50 50
  	can0  81234567   [8]  07 07 07 07 4F 4F 4F 4F
  	can0  81234566   [8]  06 06 06 06 4E 4E 4E 4E
  	can0  81234565   [8]  05 05 05 05 4D 4D 4D 4D
	can0  81234564   [8]  04 04 04 04 4C 4C 4C 4C
  	can0  81234563   [8]  03 03 03 03 4B 4B 4B 4B
  	can0  81234562   [8]  02 02 02 02 4A 4A 4A 4A
  	can0  81234561   [8]  01 01 01 01 49 49 49 49
  	can0  81234560   [8]  00 00 00 00 48 48 48 48
  	can0  81234567   [8]  07 07 07 07 47 47 47 47

I expect the frames from can1 with priority sequence high to low:
	can1  01234560   [8]  00 00 00 00 50 50 50 50
	can1  01234561   [8]  01 01 01 01 49 49 49 49  
	can1  01234562   [8]  02 02 02 02 4A 4A 4A 4A
	can1  01234563   [8]  03 03 03 03 4B 4B 4B 4B
	can1  01234564   [8]  04 04 04 04 4C 4C 4C 4C
	can1  01234565   [8]  05 05 05 05 4D 4D 4D 4D
	can1  01234566   [8]  06 06 06 06 4E 4E 4E 4E
	can1  01234567   [8]  07 07 07 07 4F 4F 4F 4F
	can1  01234560   [8]  00 00 00 00 48 48 48 48

But actually, I got the frames with same sequence
	can1  01234560   [8]  00 00 00 00 50 50 50 50
	can1  01234567   [8]  07 07 07 07 4F 4F 4F 4F
	can1  01234566   [8]  06 06 06 06 4E 4E 4E 4E
	can1  01234565   [8]  05 05 05 05 4D 4D 4D 4D
	can1  01234564   [8]  04 04 04 04 4C 4C 4C 4C
	can1  01234563   [8]  03 03 03 03 4B 4B 4B 4B
	can1  01234562   [8]  02 02 02 02 4A 4A 4A 4A
	can1  01234561   [8]  01 01 01 01 49 49 49 49
	can1  01234560   [8]  00 00 00 00 48 48 48 48
	can1  01234567   [8]  07 07 07 07 47 47 47 47
	can1  01234566   [8]  06 06 06 06 46 46 46 46

And I found that just happens for first 10 frames. After that, prio qdisc works fine.
Why? Or What am I missing?

Regards!
Leo Ruan



^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: Why doesn't the socketcan prio qdisc work for first 10 can frames?
  2014-11-27  9:43 Why doesn't the socketcan prio qdisc work for first 10 can frames? Ruan TingQuan (ST-FIR/ENG1-Zhu)
@ 2014-11-27 11:46 ` Oliver Hartkopp
  2014-11-27 17:54   ` CAN implementation on A20 Allwinner Pankajkumar Misra (RBEI/EEA2)
  0 siblings, 1 reply; 16+ messages in thread
From: Oliver Hartkopp @ 2014-11-27 11:46 UTC (permalink / raw)
  To: Ruan TingQuan (ST-FIR/ENG1-Zhu), linux-can@vger.kernel.org

Please try to reduce the tx queue length of the CAN netdevice to 1

E.g.

ip link set can0 txqueuelen 1

Does that help?

Regards,
Oliver

On 27.11.2014 10:43, Ruan TingQuan (ST-FIR/ENG1-Zhu) wrote:
> Hello Linux-can-team,
>
> A prio qdisc is created with 8 bands for my different priority sending requirement.
> My test environment: ubuntu 12.04 (kernel 3.11) + PEAK-USB pro (can0 is connect to can1).
> The frame will be send on can0 and receive on can1 (candump)
> Below is the setting on can0:
> 	> ip link set can0 type can bitrate 5000
> 	> ip link set can1 type can bitrate 5000
> 	> tc qdisc add dev can0 root handle 1: prio bands 8
> 	> tc filter add dev $1 parent 1:0 prio 1 basic match canid\(eff 0x1:0x7\) flowid 1:1
> 	> tc filter add dev $1 parent 1:0 prio 2 basic match canid\(eff 0x2:0x7\) flowid 1:2
> 	> tc filter add dev $1 parent 1:0 prio 3 basic match canid\(eff 0x3:0x7\) flowid 1:3
> 	> tc filter add dev $1 parent 1:0 prio 4 basic match canid\(eff 0x4:0x7\) flowid 1:4
> 	> tc filter add dev $1 parent 1:0 prio 5 basic match canid\(eff 0x5:0x7\) flowid 1:5
> 	> tc filter add dev $1 parent 1:0 prio 6 basic match canid\(eff 0x6:0x7\) flowid 1:6
> 	> tc filter add dev $1 parent 1:0 prio 7 basic match canid\(eff 0x7:0x7\) flowid 1:7
> 	> tc filter add dev $1 parent 1:0 prio 8 basic match canid\(sff 0x0:0x0 eff 0x0:0x0\) flowid 1:8
>
> Then, I made a test program to send 10 frames on can0 socket quickly.
>    	can0  81234560   [8]  00 00 00 00 50 50 50 50
>    	can0  81234567   [8]  07 07 07 07 4F 4F 4F 4F
>    	can0  81234566   [8]  06 06 06 06 4E 4E 4E 4E
>    	can0  81234565   [8]  05 05 05 05 4D 4D 4D 4D
> 	can0  81234564   [8]  04 04 04 04 4C 4C 4C 4C
>    	can0  81234563   [8]  03 03 03 03 4B 4B 4B 4B
>    	can0  81234562   [8]  02 02 02 02 4A 4A 4A 4A
>    	can0  81234561   [8]  01 01 01 01 49 49 49 49
>    	can0  81234560   [8]  00 00 00 00 48 48 48 48
>    	can0  81234567   [8]  07 07 07 07 47 47 47 47
>
> I expect the frames from can1 with priority sequence high to low:
> 	can1  01234560   [8]  00 00 00 00 50 50 50 50
> 	can1  01234561   [8]  01 01 01 01 49 49 49 49
> 	can1  01234562   [8]  02 02 02 02 4A 4A 4A 4A
> 	can1  01234563   [8]  03 03 03 03 4B 4B 4B 4B
> 	can1  01234564   [8]  04 04 04 04 4C 4C 4C 4C
> 	can1  01234565   [8]  05 05 05 05 4D 4D 4D 4D
> 	can1  01234566   [8]  06 06 06 06 4E 4E 4E 4E
> 	can1  01234567   [8]  07 07 07 07 4F 4F 4F 4F
> 	can1  01234560   [8]  00 00 00 00 48 48 48 48
>
> But actually, I got the frames with same sequence
> 	can1  01234560   [8]  00 00 00 00 50 50 50 50
> 	can1  01234567   [8]  07 07 07 07 4F 4F 4F 4F
> 	can1  01234566   [8]  06 06 06 06 4E 4E 4E 4E
> 	can1  01234565   [8]  05 05 05 05 4D 4D 4D 4D
> 	can1  01234564   [8]  04 04 04 04 4C 4C 4C 4C
> 	can1  01234563   [8]  03 03 03 03 4B 4B 4B 4B
> 	can1  01234562   [8]  02 02 02 02 4A 4A 4A 4A
> 	can1  01234561   [8]  01 01 01 01 49 49 49 49
> 	can1  01234560   [8]  00 00 00 00 48 48 48 48
> 	can1  01234567   [8]  07 07 07 07 47 47 47 47
> 	can1  01234566   [8]  06 06 06 06 46 46 46 46
>
> And I found that just happens for first 10 frames. After that, prio qdisc works fine.
> Why? Or What am I missing?
>
> Regards!
> Leo Ruan
>
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-can" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>

^ permalink raw reply	[flat|nested] 16+ messages in thread

* CAN implementation on A20 Allwinner
  2014-11-27 11:46 ` Oliver Hartkopp
@ 2014-11-27 17:54   ` Pankajkumar Misra (RBEI/EEA2)
  2014-11-27 18:28     ` Uwe Bonnes
  0 siblings, 1 reply; 16+ messages in thread
From: Pankajkumar Misra (RBEI/EEA2) @ 2014-11-27 17:54 UTC (permalink / raw)
  To: linux-can@vger.kernel.org

Hello All,

I am currently working on Olimex A20-Olinuxino Micro board.

I am trying to bring-up CAN device available on A20 Allwinner chip at base address 0x01c2BC00.

In initialization I am enabling clock, setting pins for Tx & Rx, IRQ & ISR are set. Interrupt,Tx & Rx enabled.
In transmit frame function, after adding required data into buffer I am setting command to 0x01, which means transmit request set.
But data is never transmitted from the buffer. Can status says "controller in the process of transmitting a msg". But it never transmits.
Interrupt is never generated for tx. ISR is never called. Nothing comes on candump.

One strange thing is that it is not responding to cansend again. i.e. possibly it is going in infinite loop somewhere.

What am I missing !!

Best Regards,
Pankaj

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2014-11-27 17:54   ` CAN implementation on A20 Allwinner Pankajkumar Misra (RBEI/EEA2)
@ 2014-11-27 18:28     ` Uwe Bonnes
       [not found]       ` <58243.88.153.236.115.1417116776.squirrel@webmail.rdts.de>
  0 siblings, 1 reply; 16+ messages in thread
From: Uwe Bonnes @ 2014-11-27 18:28 UTC (permalink / raw)
  To: Pankajkumar Misra (RBEI/EEA2); +Cc: linux-can@vger.kernel.org

>>>>> "Pankajkumar" == Pankajkumar Misra (RBEI/EEA2) <Pankaj.Kumar@in.bosch.com> writes:

    Pankajkumar> Hello All, I am currently working on Olimex A20-Olinuxino
    Pankajkumar> Micro board.

    Pankajkumar> I am trying to bring-up CAN device available on A20
    Pankajkumar> Allwinner chip at base address 0x01c2BC00.

Is there some open documentation about the CAN IP? Can you point me to that
documentation?  I looked hard with A10 some time ago, but didn't find
anything.

Thanks
-- 
Uwe Bonnes                bon@elektron.ikp.physik.tu-darmstadt.de

Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
--------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
       [not found]       ` <58243.88.153.236.115.1417116776.squirrel@webmail.rdts.de>
@ 2014-11-27 19:53         ` Gerhard Bertelsmann
  2014-12-02 12:37           ` Marc Kleine-Budde
  0 siblings, 1 reply; 16+ messages in thread
From: Gerhard Bertelsmann @ 2014-11-27 19:53 UTC (permalink / raw)
  To: Uwe Bonnes, Pankajkumar Misra; +Cc: linux-can@vger.kernel.org

Hi again,

here are some updates:

https://github.com/btolfa/sunxi-can-driver

Regards
Gerd

Am Do, 27.11.2014, 20:32, schrieb Gerhard Bertelsmann:
> Hi,
>
> please have a look at:
>
> https://github.com/plaes/sunxi-can-driver
>
> http://forum.lemaker.org/thread-209-2-1-2.html
> http://forum.lemaker.org/forum.php?mod=attachment&aid=NTY2fDRiNjM1ZTAxfDE0MTcxMTYxNTh8MHwyMDk%3D
>
> Regards,
>
> Gerd
>
>
> Am Do, 27.11.2014, 19:28, schrieb Uwe Bonnes:
>>>>>>> "Pankajkumar" == Pankajkumar Misra (RBEI/EEA2) <Pankaj.Kumar@in.bosch.com> writes:
>>
>>     Pankajkumar> Hello All, I am currently working on Olimex A20-Olinuxino
>>     Pankajkumar> Micro board.
>>
>>     Pankajkumar> I am trying to bring-up CAN device available on A20
>>     Pankajkumar> Allwinner chip at base address 0x01c2BC00.
>>
>> Is there some open documentation about the CAN IP? Can you point me to that
>> documentation?  I looked hard with A10 some time ago, but didn't find
>> anything.
>>
>> Thanks
>> --
>> Uwe Bonnes                bon@elektron.ikp.physik.tu-darmstadt.de
>>
>> Institut fuer Kernphysik  Schlossgartenstrasse 9  64289 Darmstadt
>> --------- Tel. 06151 162516 -------- Fax. 06151 164321 ----------
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-can" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>>
>


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2014-11-27 19:53         ` Gerhard Bertelsmann
@ 2014-12-02 12:37           ` Marc Kleine-Budde
  2015-08-27 13:04             ` Gerhard Bertelsmann
  0 siblings, 1 reply; 16+ messages in thread
From: Marc Kleine-Budde @ 2014-12-02 12:37 UTC (permalink / raw)
  To: info, Uwe Bonnes, Pankajkumar Misra; +Cc: linux-can@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 537 bytes --]

On 11/27/2014 08:53 PM, Gerhard Bertelsmann wrote:
> Hi again,
> 
> here are some updates:
> 
> https://github.com/btolfa/sunxi-can-driver

It it's sja1000 compatible, it should work out of the box with the
existing sja1000 device tree binding.

Marc
-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2014-12-02 12:37           ` Marc Kleine-Budde
@ 2015-08-27 13:04             ` Gerhard Bertelsmann
  2015-08-27 13:23               ` Marc Kleine-Budde
  0 siblings, 1 reply; 16+ messages in thread
From: Gerhard Bertelsmann @ 2015-08-27 13:04 UTC (permalink / raw)
  To: Marc Kleine-Budde; +Cc: Uwe Bonnes, Pankajkumar Misra, linux-can

Hi

Am 2014-12-02 13:37, schrieb Marc Kleine-Budde:
> On 11/27/2014 08:53 PM, Gerhard Bertelsmann wrote:
>> Hi again,
>> 
>> here are some updates:
>> 
>> https://github.com/btolfa/sunxi-can-driver
> 
> It it's sja1000 compatible, it should work out of the box with the
> existing sja1000 device tree binding.

the Allwinner CAN IP is very similar but not exactly a SJA1000, e g. the
registers differ and some are 32 bit wide and not 8 bit.
So the question is: change the sja1000 and the platform file for 
"quirks"
or write a new independent one ?
Which way do you prefer or better: which driver will be accepted for 
mainline ?

> 
> Marc

Regards

Gerd

P.S.: Allwinner A20 Manual - CAN beginning at page 811
https://github.com/allwinner-zh/documents/raw/master/A20/A20_User_Manual_v1.4_20150510.pdf

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2015-08-27 13:04             ` Gerhard Bertelsmann
@ 2015-08-27 13:23               ` Marc Kleine-Budde
  2015-08-27 13:34                 ` Gerhard Bertelsmann
  0 siblings, 1 reply; 16+ messages in thread
From: Marc Kleine-Budde @ 2015-08-27 13:23 UTC (permalink / raw)
  To: Gerhard Bertelsmann; +Cc: Uwe Bonnes, Pankajkumar Misra, linux-can

[-- Attachment #1: Type: text/plain, Size: 1011 bytes --]

On 08/27/2015 03:04 PM, Gerhard Bertelsmann wrote:
>> It it's sja1000 compatible, it should work out of the box with the
>> existing sja1000 device tree binding.
> 
> the Allwinner CAN IP is very similar but not exactly a SJA1000, e g. the
> registers differ and some are 32 bit wide and not 8 bit.

Which are the registers that have the upper 24 bit used?

> So the question is: change the sja1000 and the platform file for 
> "quirks" or write a new independent one ?

Depends on the actual differences, but I'd go for quirks first.

> Which way do you prefer or better: which driver will be accepted for 
> mainline ?

The github driver lacks a proper driver model binding, so that's not
mainline ready.

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2015-08-27 13:23               ` Marc Kleine-Budde
@ 2015-08-27 13:34                 ` Gerhard Bertelsmann
  2015-08-27 13:49                   ` Marc Kleine-Budde
  0 siblings, 1 reply; 16+ messages in thread
From: Gerhard Bertelsmann @ 2015-08-27 13:34 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Uwe Bonnes, Pankajkumar Misra, linux-can, linux-can-owner

Hi Marc,

many thx for your fast answer.

Am 2015-08-27 15:23, schrieb Marc Kleine-Budde:
> On 08/27/2015 03:04 PM, Gerhard Bertelsmann wrote:
>>> It it's sja1000 compatible, it should work out of the box with the
>>> existing sja1000 device tree binding.
>> 
>> the Allwinner CAN IP is very similar but not exactly a SJA1000, e g. 
>> the
>> registers differ and some are 32 bit wide and not 8 bit.
> 
> Which are the registers that have the upper 24 bit used?

CAN_STA_REG  status register
CAN_BUS_TIME bus timing
CAN_REC_REG  errot counter

Some regs also have a different address

> 
>> So the question is: change the sja1000 and the platform file for
>> "quirks" or write a new independent one ?
> 
> Depends on the actual differences, but I'd go for quirks first.
> 
>> Which way do you prefer or better: which driver will be accepted for
>> mainline ?
> 
> The github driver lacks a proper driver model binding, so that's not
> mainline ready.

That would be not a huge problem IMHO ...

> 
> Marc

Gerd

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2015-08-27 13:34                 ` Gerhard Bertelsmann
@ 2015-08-27 13:49                   ` Marc Kleine-Budde
  2015-08-27 14:29                     ` Gerhard Bertelsmann
  0 siblings, 1 reply; 16+ messages in thread
From: Marc Kleine-Budde @ 2015-08-27 13:49 UTC (permalink / raw)
  To: Gerhard Bertelsmann
  Cc: Uwe Bonnes, Pankajkumar Misra, linux-can, linux-can-owner

[-- Attachment #1: Type: text/plain, Size: 573 bytes --]

On 08/27/2015 03:34 PM, Gerhard Bertelsmann wrote:
>> Which are the registers that have the upper 24 bit used?
> 
> CAN_STA_REG  status register
> CAN_BUS_TIME bus timing
> CAN_REC_REG  errot counter

That's ok.

> Some regs also have a different address

Which one? How may?

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2015-08-27 13:49                   ` Marc Kleine-Budde
@ 2015-08-27 14:29                     ` Gerhard Bertelsmann
  2015-08-27 14:37                       ` Marc Kleine-Budde
  0 siblings, 1 reply; 16+ messages in thread
From: Gerhard Bertelsmann @ 2015-08-27 14:29 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Uwe Bonnes, Pankajkumar Misra, linux-can, linux-can-owner

Hi Marc,

Am 2015-08-27 15:49, schrieb Marc Kleine-Budde:
> On 08/27/2015 03:34 PM, Gerhard Bertelsmann wrote:
>>> Which are the registers that have the upper 24 bit used?
>> 
>> CAN_STA_REG  status register
>> CAN_BUS_TIME bus timing
>> CAN_REC_REG  errot counter
> 
> That's ok.
> 
>> Some regs also have a different address
> 
> Which one? How may?

here a quick overview (not a complete list):

   original    address    Allwinner
SJA1000_MOD    0x00   CAN_MOD_SEL    OK
SJA1000_CMR    0x01   CAN_CMD_REG    OK
SJA1000_SR     0x02   CAN_STA_REG    OK but 24 bit (more values)
SJA1000_IR     0x03   CAN_INT_REG    OK
SJA1000_IER    0x04   CAN_INTE_REG   OK
                0x05   CAN_BUS_TIME   NOK also 24 bit
SJA1000_BTR0   0x06   CAN_TEWL       NOK CAN TX error warn limit reg
SJA1000_BTR1   0x07   CAN_ERRC       NOK CAN error counter register
SJA1000_OCR    0x08   CAN_RMCNT      NOK CAN receive message count reg

SJA1000_ALC    0x0B                  NOK
SJA1000_ECC    0x0C                  NOK
SJA1000_EWL    0x0D                  NOK
SJA1000_RXERR  0x0E                  NOK
SJA1000_TXERR  0x0F                  NOK
SJA1000_ACCC0  0x10   CAN_AC0        OK  Reset mode: CAN_ACP_CODE but 32 
bit
SJA1000_ACCC1  0x11   CAN_AM0        NOK Reset mode: CAN_ACP_CODE 32 bit
SJA1000_ACCC2  0x12   CAN_TRBUF2     NOK CAN TX/RX mbuffer 2 reg
SJA1000_ACCC3  0x13   CAN_TRBUF3     NOK CAN TX/RX mbuffer 3 reg
SJA1000_ACCM0  0x14   CAN_TRBUF4     NOK CAN TX/RX mbuffer 4 reg
SJA1000_ACCM1  0x15   CAN_TRBUF5     NOK CAN TX/RX mbuffer 5 reg
SJA1000_ACCM2  0x16   CAN_TRBUF6     NOK CAN TX/RX mbuffer 6 reg
SJA1000_ACCM3  0x17   CAN_TRBUF7     NOK CAN TX/RX mbuffer 7 reg
SJA1000_RMC    0x1D   CAN_TRBUF8     NOK CAN TX/RX mbuffer 8 reg
SJA1000_RBSA   0x1E   CAN_TRBUF9     NOK CAN TX/RX mbuffer 9 reg

more differences than similarities ... A sja1000 module with "quirks" 
makes
no sense to me.

Gerd


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2015-08-27 14:29                     ` Gerhard Bertelsmann
@ 2015-08-27 14:37                       ` Marc Kleine-Budde
  2015-08-28  5:41                         ` Misra Pankaj Kumar (RBEI/EEA2)
  0 siblings, 1 reply; 16+ messages in thread
From: Marc Kleine-Budde @ 2015-08-27 14:37 UTC (permalink / raw)
  To: Gerhard Bertelsmann
  Cc: Uwe Bonnes, Pankajkumar Misra, linux-can, linux-can-owner

[-- Attachment #1: Type: text/plain, Size: 2060 bytes --]

On 08/27/2015 04:29 PM, Gerhard Bertelsmann wrote:
>>> Some regs also have a different address
>>
>> Which one? How may?
> 
> here a quick overview (not a complete list):
> 
>    original    address    Allwinner
> SJA1000_MOD    0x00   CAN_MOD_SEL    OK
> SJA1000_CMR    0x01   CAN_CMD_REG    OK
> SJA1000_SR     0x02   CAN_STA_REG    OK but 24 bit (more values)
> SJA1000_IR     0x03   CAN_INT_REG    OK
> SJA1000_IER    0x04   CAN_INTE_REG   OK
>                 0x05   CAN_BUS_TIME   NOK also 24 bit
> SJA1000_BTR0   0x06   CAN_TEWL       NOK CAN TX error warn limit reg
> SJA1000_BTR1   0x07   CAN_ERRC       NOK CAN error counter register
> SJA1000_OCR    0x08   CAN_RMCNT      NOK CAN receive message count reg
> 
> SJA1000_ALC    0x0B                  NOK
> SJA1000_ECC    0x0C                  NOK
> SJA1000_EWL    0x0D                  NOK
> SJA1000_RXERR  0x0E                  NOK
> SJA1000_TXERR  0x0F                  NOK
> SJA1000_ACCC0  0x10   CAN_AC0        OK  Reset mode: CAN_ACP_CODE but 32 
> bit
> SJA1000_ACCC1  0x11   CAN_AM0        NOK Reset mode: CAN_ACP_CODE 32 bit
> SJA1000_ACCC2  0x12   CAN_TRBUF2     NOK CAN TX/RX mbuffer 2 reg
> SJA1000_ACCC3  0x13   CAN_TRBUF3     NOK CAN TX/RX mbuffer 3 reg
> SJA1000_ACCM0  0x14   CAN_TRBUF4     NOK CAN TX/RX mbuffer 4 reg
> SJA1000_ACCM1  0x15   CAN_TRBUF5     NOK CAN TX/RX mbuffer 5 reg
> SJA1000_ACCM2  0x16   CAN_TRBUF6     NOK CAN TX/RX mbuffer 6 reg
> SJA1000_ACCM3  0x17   CAN_TRBUF7     NOK CAN TX/RX mbuffer 7 reg
> SJA1000_RMC    0x1D   CAN_TRBUF8     NOK CAN TX/RX mbuffer 8 reg
> SJA1000_RBSA   0x1E   CAN_TRBUF9     NOK CAN TX/RX mbuffer 9 reg
> 
> more differences than similarities ... A sja1000 module with "quirks" 
> makes
> no sense to me.

ACK

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* RE: CAN implementation on A20 Allwinner
  2015-08-27 14:37                       ` Marc Kleine-Budde
@ 2015-08-28  5:41                         ` Misra Pankaj Kumar (RBEI/EEA2)
  2015-08-28  6:21                           ` Marc Kleine-Budde
  0 siblings, 1 reply; 16+ messages in thread
From: Misra Pankaj Kumar (RBEI/EEA2) @ 2015-08-28  5:41 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Uwe Bonnes, linux-can-owner@vger.kernel.org, Gerhard Bertelsmann,
	linux-can@vger.kernel.org

Hello Marc,

I have used CAN4Linux package with A20 Allwinner. Its working fine for me.
Its char device implementation.

Best regards
Pankaj

-----Original Message-----
From: Marc Kleine-Budde [mailto:mkl@pengutronix.de] 
Sent: Thursday, August 27, 2015 8:07 PM
To: Gerhard Bertelsmann <info@gerhard-bertelsmann.de>
Cc: Uwe Bonnes <bon@elektron.ikp.physik.tu-darmstadt.de>; Misra Pankaj Kumar (RBEI/EEA2) <Pankaj.Kumar@in.bosch.com>; linux-can@vger.kernel.org; linux-can-owner@vger.kernel.org
Subject: Re: CAN implementation on A20 Allwinner

On 08/27/2015 04:29 PM, Gerhard Bertelsmann wrote:
>>> Some regs also have a different address
>>
>> Which one? How may?
> 
> here a quick overview (not a complete list):
> 
>    original    address    Allwinner
> SJA1000_MOD    0x00   CAN_MOD_SEL    OK
> SJA1000_CMR    0x01   CAN_CMD_REG    OK
> SJA1000_SR     0x02   CAN_STA_REG    OK but 24 bit (more values)
> SJA1000_IR     0x03   CAN_INT_REG    OK
> SJA1000_IER    0x04   CAN_INTE_REG   OK
>                 0x05   CAN_BUS_TIME   NOK also 24 bit
> SJA1000_BTR0   0x06   CAN_TEWL       NOK CAN TX error warn limit reg
> SJA1000_BTR1   0x07   CAN_ERRC       NOK CAN error counter register
> SJA1000_OCR    0x08   CAN_RMCNT      NOK CAN receive message count reg
> 
> SJA1000_ALC    0x0B                  NOK
> SJA1000_ECC    0x0C                  NOK
> SJA1000_EWL    0x0D                  NOK
> SJA1000_RXERR  0x0E                  NOK
> SJA1000_TXERR  0x0F                  NOK
> SJA1000_ACCC0  0x10   CAN_AC0        OK  Reset mode: CAN_ACP_CODE but 32 
> bit
> SJA1000_ACCC1  0x11   CAN_AM0        NOK Reset mode: CAN_ACP_CODE 32 bit
> SJA1000_ACCC2  0x12   CAN_TRBUF2     NOK CAN TX/RX mbuffer 2 reg
> SJA1000_ACCC3  0x13   CAN_TRBUF3     NOK CAN TX/RX mbuffer 3 reg
> SJA1000_ACCM0  0x14   CAN_TRBUF4     NOK CAN TX/RX mbuffer 4 reg
> SJA1000_ACCM1  0x15   CAN_TRBUF5     NOK CAN TX/RX mbuffer 5 reg
> SJA1000_ACCM2  0x16   CAN_TRBUF6     NOK CAN TX/RX mbuffer 6 reg
> SJA1000_ACCM3  0x17   CAN_TRBUF7     NOK CAN TX/RX mbuffer 7 reg
> SJA1000_RMC    0x1D   CAN_TRBUF8     NOK CAN TX/RX mbuffer 8 reg
> SJA1000_RBSA   0x1E   CAN_TRBUF9     NOK CAN TX/RX mbuffer 9 reg
> 
> more differences than similarities ... A sja1000 module with "quirks" 
> makes
> no sense to me.

ACK

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2015-08-28  5:41                         ` Misra Pankaj Kumar (RBEI/EEA2)
@ 2015-08-28  6:21                           ` Marc Kleine-Budde
  2015-08-28  9:22                             ` Gerhard Bertelsmann
  0 siblings, 1 reply; 16+ messages in thread
From: Marc Kleine-Budde @ 2015-08-28  6:21 UTC (permalink / raw)
  To: Misra Pankaj Kumar (RBEI/EEA2)
  Cc: Uwe Bonnes, linux-can-owner@vger.kernel.org, Gerhard Bertelsmann,
	linux-can@vger.kernel.org

[-- Attachment #1: Type: text/plain, Size: 576 bytes --]

On 08/28/2015 07:41 AM, Misra Pankaj Kumar (RBEI/EEA2) wrote:
> I have used CAN4Linux package with A20 Allwinner. Its working fine for me.
> Its char device implementation.

Good. Is the A20 supported bt a generic CAN4Linux SJA1000 driver or is
there a separate driver for it?

regards,
Marc
-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2015-08-28  6:21                           ` Marc Kleine-Budde
@ 2015-08-28  9:22                             ` Gerhard Bertelsmann
  2015-08-28 10:11                               ` Marc Kleine-Budde
  0 siblings, 1 reply; 16+ messages in thread
From: Gerhard Bertelsmann @ 2015-08-28  9:22 UTC (permalink / raw)
  To: Marc Kleine-Budde
  Cc: Misra Pankaj Kumar (RBEI/EEA2), Uwe Bonnes, linux-can-owner,
	linux-can

Hi,
Am 2015-08-28 08:21, schrieb Marc Kleine-Budde:
> On 08/28/2015 07:41 AM, Misra Pankaj Kumar (RBEI/EEA2) wrote:
>> I have used CAN4Linux package with A20 Allwinner. Its working fine for 
>> me.
>> Its char device implementation.
> 
> Good. Is the A20 supported bt a generic CAN4Linux SJA1000 driver or is
> there a separate driver for it?

It's a different driver.

If nobody else has done it already I will refresh the existing sunxi-can 
driver
and fed it to the lions (SocketCAN team) :-)

> 
> regards,
> Marc

Regards

Gerd

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: CAN implementation on A20 Allwinner
  2015-08-28  9:22                             ` Gerhard Bertelsmann
@ 2015-08-28 10:11                               ` Marc Kleine-Budde
  0 siblings, 0 replies; 16+ messages in thread
From: Marc Kleine-Budde @ 2015-08-28 10:11 UTC (permalink / raw)
  To: Gerhard Bertelsmann
  Cc: Misra Pankaj Kumar (RBEI/EEA2), Uwe Bonnes, linux-can-owner,
	linux-can

[-- Attachment #1: Type: text/plain, Size: 25653 bytes --]

On 08/28/2015 11:22 AM, Gerhard Bertelsmann wrote:
> If nobody else has done it already I will refresh the existing
> sunxi-can driver and fed it to the lions (SocketCAN team) :-)

I'll give some comments first - may save some time. General remarks:

- I haven't looked closely at the reset_mode normal_mode switching, but
  this looks racy.
- there are quite some delays in the hot paths of the driver
- add proper driver model, i.e. DT bindings

> /*
> * sun7i_can.c - CAN bus controller driver for sun7i
> *
> * Copyright (c) 2013 Peter Chen
> *
> * Copyright (c) 2013 Inmotion Co,. LTD
> * All right reserved.
> *
> */

This driver is IMHO derived work from the existing sja1000 drivers,
removing the copyrights and the license not considered best practise.

> 
> #include <linux/module.h>
> #include <linux/init.h>
> #include <linux/kernel.h>
> #include <linux/sched.h>
> #include <linux/types.h>
> #include <linux/fcntl.h>
> #include <linux/interrupt.h>
> #include <linux/ptrace.h>
> #include <linux/string.h>
> #include <linux/errno.h>
> #include <linux/netdevice.h>
> #include <linux/if_arp.h>
> #include <linux/if_ether.h>
> #include <linux/skbuff.h>
> #include <linux/delay.h>
> #include <linux/clk.h>
> 
> #include <linux/can/dev.h>
> #include <linux/can/error.h>
> 
> #include <mach/includes.h>
> #include <plat/sys_config.h>
> #include <mach/irqs.h>
> 
> #include "sun7i_can.h"
> 
> #define DRV_NAME "sun7i_can"
> 
> MODULE_AUTHOR("Peter Chen <xingkongcp@gmail.com>");
> MODULE_LICENSE("Dual BSD/GPL");
> MODULE_DESCRIPTION(DRV_NAME "CAN netdevice driver");

move to the end.

> static struct net_device *sun7ican_dev;

not globals please

> static struct can_bittiming_const sun7i_can_bittiming_const = {
>         .name = DRV_NAME,
>         .tseg1_min = 1,
>         .tseg1_max = 16,
>         .tseg2_min = 1,
>         .tseg2_max = 8,
>         .sjw_max = 4,
>         .brp_min = 1,
>         .brp_max = 64,
>         .brp_inc = 1,
> };
> 
> static void sun7i_can_write_cmdreg(struct sun7i_can_priv *priv, u8 val)
> {
>         unsigned long flags;
> 
>         /*
>          * The command register needs some locking and time to settle
>          * the write_reg() operation - especially on SMP systems.
>          */

is this true for the allwinner variant of the IP core?

>         spin_lock_irqsave(&priv->cmdreg_lock, flags);
>         writel(val, CAN_CMD_ADDR);
>         spin_unlock_irqrestore(&priv->cmdreg_lock, flags);
> }
> 
> static int sun7i_can_is_absent(struct sun7i_can_priv *priv)
> {
>         return ((readl(CAN_MSEL_ADDR) & 0xFF) == 0xFF);
> }

This can be removed for a SoC internal IP core.

> 
> static int sun7i_can_probe(struct net_device *dev)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
> 
>         if (sun7i_can_is_absent(priv)) {
>                 printk(KERN_INFO "%s: probing @0x%lX failed\n",
>                  DRV_NAME, dev->base_addr);
>                 return 0;
>         }
>         return -1;

return proper error values

> }
> 
> static void set_reset_mode(struct net_device *dev)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
>         uint32_t status = readl(CAN_MSEL_ADDR);
>         int i;
> 
>         for (i = 0; i < 100; i++) {
>                 /* check reset bit */
>                 if (status & RESET_MODE) {
>                         priv->can.state = CAN_STATE_STOPPED;
>                         return;
>                 }
> 
>                 writel(readl(CAN_MSEL_ADDR) | RESET_MODE, CAN_MSEL_ADDR);        /* select reset mode */
>                 //writel(RESET_MODE, CAN_MSEL_ADDR);        /* select reset mode */
>                 udelay(10);
>                 status = readl(CAN_MSEL_ADDR);
>         }
> 
>         netdev_err(dev, "setting SUN7I_CAN into reset mode failed!\n");
I think you can remove the SUN7I_CAN from the text, as netdev_* prints
all necessary information
> }
> 
> static void set_normal_mode(struct net_device *dev)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
>         unsigned char status = readl(CAN_MSEL_ADDR);
>         int i;
> 
>         for (i = 0; i < 100; i++) {
>                 /* check reset bit */
>                 if ((status & RESET_MODE) == 0) {
>                         priv->can.state = CAN_STATE_ERROR_ACTIVE;												
> 						
> 						/* enable interrupts */
>                         if (priv->can.ctrlmode & CAN_CTRLMODE_BERR_REPORTING) {
> 								writel(0xFFFF, CAN_INTEN_ADDR);
> 						} else {
> 								writel(0xFFFF & ~BERR_IRQ_EN, CAN_INTEN_ADDR);
> 						}
> 											
> 						if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK) {
> 							/* Put device into loopback mode */
> 							writel(readl(CAN_MSEL_ADDR) | LOOPBACK_MODE, CAN_MSEL_ADDR);
> 						} else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY) {
> 							/* Put device into listen-only mode */
> 							writel(readl(CAN_MSEL_ADDR) | LISTEN_ONLY_MODE, CAN_MSEL_ADDR);
> 						}
>                         return;
>                 }
Please use standard coding style.
> 
>                 /* set chip to normal mode */
>                 writel(readl(CAN_MSEL_ADDR) & (~RESET_MODE), CAN_MSEL_ADDR);
>                 udelay(10);
>                 status = readl(CAN_MSEL_ADDR);
>         }
> 
>         netdev_err(dev, "setting SUN7I_CAN into normal mode failed!\n");
> }
> 
> 
> static void sun7i_can_start(struct net_device *dev)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
> 
>         /* leave reset mode */
>         if (priv->can.state != CAN_STATE_STOPPED)
>                 set_reset_mode(dev);
> 
>         /* Clear error counters and error code capture */
>         writel(0x0, CAN_ERRC_ADDR);
> 
>         /* leave reset mode */
>         set_normal_mode(dev);
> }
> 
> static int sun7i_can_set_mode(struct net_device *dev, enum can_mode mode)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
> 
>         if (!priv->open_time)
>                 return -EINVAL;
> 
>         switch (mode) {
>         case CAN_MODE_START:
>                 sun7i_can_start(dev);
>                 if (netif_queue_stopped(dev))
>                         netif_wake_queue(dev);
>                 break;
> 
>         default:
>                 return -EOPNOTSUPP;
>         }
> 
>         return 0;
> }
> 
> static int sun7i_can_set_bittiming(struct net_device *dev)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
>         struct can_bittiming *bt = &priv->can.bittiming;
>         u32 cfg;
> 
>         cfg = ((bt->brp - 1) & 0x3FF)
>                 | (((bt->sjw - 1) & 0x3) << 14)
>                 | (((bt->prop_seg + bt->phase_seg1 - 1) & 0xf) << 16)
>                 | (((bt->phase_seg2 - 1) & 0x7) << 20);
please use standard coding style - move | to the end of the line
>         if (priv->can.ctrlmode & CAN_CTRLMODE_3_SAMPLES)
>                 cfg |= 0x800000;
> 
>         netdev_info(dev, "setting BITTIMING=0x%08x\n", cfg);
> 
>         set_reset_mode(dev);                //CAN_BTIME_ADDR only writable in reset mode

no // comments
>         writel(cfg, CAN_BTIME_ADDR);
>         set_normal_mode(dev);
> 
>         return 0;
> }
> 
> static int sun7i_can_get_berr_counter(const struct net_device *dev,
>                                  struct can_berr_counter *bec)
> {
>         bec->txerr = readl(CAN_ERRC_ADDR) & 0x000F;
>         bec->rxerr = (readl(CAN_ERRC_ADDR) & 0x0F00) >> 16;

only read ERRC_ADDR once

> 
>         return 0;
> }
> 
> /*
> * initialize sun7i_can:
> * - reset chip
> * - set output mode
> * - set baudrate
> * - enable interrupts
> * - start operating mode
> */
> static void chipset_init(struct net_device *dev)
> {
>         u32 temp_irqen;
> 		
>         /* config pins
>          * PH20-TX, PH21-RX :4 */
> 
> 		if (gpio_request_ex("can_para", "can_tx") == 0 || gpio_request_ex("can_para", "can_rx") == 0 ) {
> 			printk(KERN_INFO "can request gpio fail!\n");
>         }

please fix indention
> 
>         //enable clock

>         writel(readl(0xF1C20000 + 0x6C) | (1 << 4), 0xF1C20000 + 0x6C);
please use the common clock framework
> 
>         //set can controller in reset mode
>         set_reset_mode(dev);
> 
>         //enable interrupt
>         temp_irqen = BERR_IRQ_EN | ERR_PASSIVE_IRQ_EN
>                         | OR_IRQ_EN | RX_IRQ_EN;
>         writel(readl(CAN_INTEN_ADDR) | temp_irqen, CAN_INTEN_ADDR);
> 
>         //return to transfer mode
>         set_normal_mode(dev);
> }
> 
> /*
> * transmit a CAN message
> * message layout in the sk_buff should be like this:
> * xx xx xx xx         ff         ll 00 11 22 33 44 55 66 77
> * [ can_id ] [flags] [len] [can data (up to 8 bytes]
> */
> static netdev_tx_t sun7i_can_start_xmit(struct sk_buff *skb,
>                                          struct net_device *dev)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
>         struct can_frame *cf = (struct can_frame *)skb->data;
>         uint8_t dlc;
>         canid_t id;
>         uint32_t temp = 0;
>         uint8_t i;
>         
>         //wait buff ready
>         while (!(readl(CAN_STA_ADDR) & TBUF_RDY));

What are we waiting for here?

> 
>         set_reset_mode(dev);
> 
>         writel(0xffffffff, CAN_ACPM_ADDR);
> 
>         //enter transfer mode
>         set_normal_mode(dev);
> 
>         if (can_dropped_invalid_skb(dev, skb))
>                 return NETDEV_TX_OK;
> 
>         netif_stop_queue(dev);
> 
>         dlc = cf->can_dlc;
>         id = cf->can_id;
> 
>         temp = ((id >> 30) << 6) | dlc;
>         writel(temp, CAN_BUF0_ADDR);
>         if (id & CAN_EFF_FLAG) {/* extern frame */
>                 writel(0xFF & (id >> 21), CAN_BUF1_ADDR);        //id28~21
>                 writel(0xFF & (id >> 13), CAN_BUF2_ADDR);         //id20~13
>                 writel(0xFF & (id >> 5), CAN_BUF3_ADDR);         //id12~5
>                 writel((id & 0x1F) << 3, CAN_BUF4_ADDR);         //id4~0
>                 
>                 for (i = 0; i < dlc; i++) {
>                         writel(cf->data[i], CAN_BUF5_ADDR + i * 4);
>                 }
>         } else {                /* standard frame*/        
>                 writel(0xFF & (id >> 3), CAN_BUF1_ADDR);         //id28~21
>                 writel((id & 0x7) << 5, CAN_BUF2_ADDR);                //id20~13
>                 
>                 for (i = 0; i < dlc; i++) {
>                         writel(cf->data[i], CAN_BUF3_ADDR + i * 4);
>                 }
>         }
> 
>         can_put_echo_skb(skb, dev, 0);
> 
>         while (!(readl(CAN_STA_ADDR) & TBUF_RDY));
What are we waiting for here?
>         sun7i_can_write_cmdreg(priv, TRANS_REQ);
> 
>         return NETDEV_TX_OK;
> }
> 
> static void sun7i_can_rx(struct net_device *dev)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
>         struct net_device_stats *stats = &dev->stats;
>         struct can_frame *cf;
>         struct sk_buff *skb;
>         uint8_t fi;
>         canid_t id;
>         int i;
> 
>         /* create zero'ed CAN frame buffer */
>         skb = alloc_can_skb(dev, &cf);
>         if (skb == NULL)
>                 return;
> 
>         fi = readl(CAN_BUF0_ADDR);
>         cf->can_dlc = get_can_dlc(fi & 0x0F);
>         if (fi >> 7) {
>                 /* extended frame format (EFF) */
>                 id = (readl(CAN_BUF1_ADDR) << 21)        //id28~21
>                  | (readl(CAN_BUF2_ADDR) << 13)        //id20~13
>                  | (readl(CAN_BUF3_ADDR) << 5)        //id12~5
>                  | ((readl(CAN_BUF4_ADDR) >> 3) & 0x1f);        //id4~0
fix coding style
>                 id |= CAN_EFF_FLAG;
> 
>                 if ((fi >> 6) & 0x1) {        /* remote transmission request */
>                 id |= CAN_RTR_FLAG;
>                 } else {
>                         for (i = 0; i < cf->can_dlc; i++)
>                                 cf->data[i] = readl(CAN_BUF5_ADDR + i * 4);
>                 }
>         } else {
>                 /* standard frame format (SFF) */
>                 id = (readl(CAN_BUF1_ADDR) << 3)        //id28~21
>                  | ((readl(CAN_BUF2_ADDR) >> 5) & 0x7);        //id20~18
> 
>                 if ((fi >> 6) & 0x1) {        /* remote transmission request */
>                 id |= CAN_RTR_FLAG;
>                 } else {
>                         for (i = 0; i < cf->can_dlc; i++)
>                                 cf->data[i] = readl(CAN_BUF3_ADDR + i * 4);
>                 }
>         }
> 
>         cf->can_id = id;
> 
>         /* release receive buffer */
>         sun7i_can_write_cmdreg(priv, RELEASE_RBUF);
> 
>         netif_rx(skb);
> 
>         stats->rx_packets++;
>         stats->rx_bytes += cf->can_dlc;

don't touch skb after netif_rx

> }
> 
> static int sun7i_can_err(struct net_device *dev, uint8_t isrc, uint8_t status)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
>         struct net_device_stats *stats = &dev->stats;
>         struct can_frame *cf;
>         struct sk_buff *skb;
>         enum can_state state = priv->can.state;
>         uint32_t ecc, alc;
> 
>         skb = alloc_can_err_skb(dev, &cf);
>         if (skb == NULL)
>                 return -ENOMEM;
> 
>         if (isrc & DATA_ORUNI) {
>                 /* data overrun interrupt */
>                 netdev_dbg(dev, "data overrun interrupt\n");
>                 cf->can_id |= CAN_ERR_CRTL;
>                 cf->data[1] = CAN_ERR_CRTL_RX_OVERFLOW;
>                 stats->rx_over_errors++;
>                 stats->rx_errors++;
>                 sun7i_can_write_cmdreg(priv, CLEAR_DOVERRUN);        /* clear bit */
>         }
> 
>         if (isrc & ERR_WRN) {
>                 /* error warning interrupt */
>                 netdev_dbg(dev, "error warning interrupt\n");
> 
>                 if (status & BUS_OFF) {
>                         state = CAN_STATE_BUS_OFF;
>                         cf->can_id |= CAN_ERR_BUSOFF;
>                         can_bus_off(dev);
>                 } else if (status & ERR_STA) {
>                         state = CAN_STATE_ERROR_WARNING;
>                 } else
>                         state = CAN_STATE_ERROR_ACTIVE;
>         }
>         if (isrc & BUS_ERR) {
>                 /* bus error interrupt */
>                 priv->can.can_stats.bus_error++;
>                 stats->rx_errors++;
> 
>                 ecc = readl(CAN_STA_ADDR);
> 
>                 cf->can_id |= CAN_ERR_PROT | CAN_ERR_BUSERROR;
> 
>                 if(ecc & BIT_ERR)
>                         cf->data[2] |= CAN_ERR_PROT_BIT;
>                 else if (ecc & FORM_ERR)
>                         cf->data[2] |= CAN_ERR_PROT_FORM;
>                 else if (ecc & STUFF_ERR)
>                         cf->data[2] |= CAN_ERR_PROT_STUFF;
>                 else {
>                         cf->data[2] |= CAN_ERR_PROT_UNSPEC;
>                         cf->data[3] = (ecc & ERR_SEG_CODE) >> 16;
>                 }
>                 /* Error occurred during transmission? */
>                 if ((ecc & ERR_DIR) == 0)
>                         cf->data[2] |= CAN_ERR_PROT_TX;
>         }
>         if (isrc & ERR_PASSIVE) {
>                 /* error passive interrupt */
>                 netdev_dbg(dev, "error passive interrupt\n");
>                 if (status & ERR_STA)
>                         state = CAN_STATE_ERROR_PASSIVE;
>                 else
>                         state = CAN_STATE_ERROR_ACTIVE;
>         }
>         if (isrc & ARB_LOST) {
>                 /* arbitration lost interrupt */
>                 netdev_dbg(dev, "arbitration lost interrupt\n");
>                 alc = readl(CAN_STA_ADDR);
>                 priv->can.can_stats.arbitration_lost++;
>                 stats->tx_errors++;
>                 cf->can_id |= CAN_ERR_LOSTARB;
>                 cf->data[0] = (alc & 0x1f) >> 8;
>         }
> 
>         if (state != priv->can.state && (state == CAN_STATE_ERROR_WARNING ||
>                                          state == CAN_STATE_ERROR_PASSIVE)) {
>                 uint8_t rxerr = (readl(CAN_ERRC_ADDR) >> 16) & 0xFF;
>                 uint8_t txerr = readl(CAN_ERRC_ADDR) & 0xFF;
>                 cf->can_id |= CAN_ERR_CRTL;
>                 if (state == CAN_STATE_ERROR_WARNING) {
>                         priv->can.can_stats.error_warning++;
>                         cf->data[1] = (txerr > rxerr) ?
>                                 CAN_ERR_CRTL_TX_WARNING :
>                                 CAN_ERR_CRTL_RX_WARNING;
>                 } else {
>                         priv->can.can_stats.error_passive++;
>                         cf->data[1] = (txerr > rxerr) ?
>                                 CAN_ERR_CRTL_TX_PASSIVE :
>                                 CAN_ERR_CRTL_RX_PASSIVE;
>                 }
>                 cf->data[6] = txerr;
>                 cf->data[7] = rxerr;
>         }
> 
>         priv->can.state = state;
> 
>         netif_rx(skb);
> 
>         stats->rx_packets++;
>         stats->rx_bytes += cf->can_dlc;
> 
>         return 0;
> }
> 
> irqreturn_t sun7i_can_interrupt(int irq, void *dev_id)
> {
>         struct net_device *dev = (struct net_device *)dev_id;
>         struct sun7i_can_priv *priv = netdev_priv(dev);
>         struct net_device_stats *stats = &dev->stats;
>         uint8_t isrc, status;
>         int n = 0;
> 
>         printk(KERN_INFO "sun7ican: capture a interrupt\n");

please remove this message
> 
>         /* Shared interrupts and IRQ off? */
>         if ((readl(CAN_INT_ADDR) & 0xF) == 0x0)
>                 return IRQ_NONE;
> 
>         while ((isrc = readl(CAN_INT_ADDR)) && (n < SUN7I_CAN_MAX_IRQ)) {
>                 n++;
>                 status = readl(CAN_STA_ADDR);
>                 /* check for absent controller due to hw unplug */

this is unlikely on a SoC internal core

>                 if (sun7i_can_is_absent(priv))
>                         return IRQ_NONE;
> 
>                 if (isrc & WAKEUP)
>                         netdev_warn(dev, "wakeup interrupt\n");
> 
>                 if (isrc & TBUF_VLD) {
>                         /* transmission complete interrupt */
>                         stats->tx_bytes += readl(CAN_RBUF_RBACK_START_ADDR) & 0xf;
>                         stats->tx_packets++;
>                         can_get_echo_skb(dev, 0);
>                         netif_wake_queue(dev);
>                 }
>                 if (isrc & RBUF_VLD) {
>                         /* receive interrupt */
>                         while (status & RBUF_RDY) {        //RX buffer is not empty
>                                 sun7i_can_rx(dev);
>                                 status = readl(CAN_STA_ADDR);
>                                 /* check for absent controller */
>                                 if (sun7i_can_is_absent(priv))
>                                         return IRQ_NONE;
>                         }
>                 }
>                 if (isrc & (DATA_ORUNI | ERR_WRN | BUS_ERR | ERR_PASSIVE | ARB_LOST)) {
>                         /* error interrupt */
>                         if (sun7i_can_err(dev, isrc, status))
>                                 break;
>                 }
> 
>                 //clear the interrupt
>                 writel(isrc, CAN_INT_ADDR);
>                 udelay(10);
Why the delay?
>         }
> 
>         if (n >= SUN7I_CAN_MAX_IRQ)
>                 netdev_dbg(dev, "%d messages handled in ISR", n);
> 
>         return (n) ? IRQ_HANDLED : IRQ_NONE;
> }
> EXPORT_SYMBOL_GPL(sun7i_can_interrupt);
why is this function exported?
> 
> static int sun7i_can_open(struct net_device *dev)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
>         int err;
> 
>         /* set chip into reset mode */
>         set_reset_mode(dev);
> 
>         /* common open */
>         err = open_candev(dev);
>         if (err)
>                 return err;
> 
>         /* register interrupt handler, if not done by the device driver */
>         if (!(priv->flags & SUN7I_CAN_CUSTOM_IRQ_HANDLER)) {

As this should be a non modular drive the custon IRQ handler can be removed.

>                 err = request_irq(dev->irq, sun7i_can_interrupt, priv->irq_flags,
>                                  dev->name, (void *)dev);
>                 if (err) {
>                         close_candev(dev);
>                         printk(KERN_INFO "request_irq err:%d\n", err);
>                         return -EAGAIN;
>                 }
>         }
> 
>         /* init and start chi */
>         sun7i_can_start(dev);
>         priv->open_time = jiffies;

remove open_time, too
> 
>         netif_start_queue(dev);
> 
>         return 0;
> }
> 
> static int sun7i_can_close(struct net_device *dev)
> {
>         struct sun7i_can_priv *priv = netdev_priv(dev);
> 
>         netif_stop_queue(dev);
>         set_reset_mode(dev);
> 
>         if (!(priv->flags & SUN7I_CAN_CUSTOM_IRQ_HANDLER))
>                 free_irq(dev->irq, (void *)dev);
> 
>         close_candev(dev);
> 
>         priv->open_time = 0;
> 
>         return 0;
> }
> 
> struct net_device *alloc_sun7icandev(int sizeof_priv)
> {
>         struct net_device *dev;
>         struct sun7i_can_priv *priv;
> 
>         dev = alloc_candev(sizeof(struct sun7i_can_priv) + sizeof_priv,
>                 SUN7I_CAN_ECHO_SKB_MAX);
>         if (!dev)
>                 return NULL;
> 
>         priv = netdev_priv(dev);
> 
>         priv->dev = dev;
>         priv->can.bittiming_const = &sun7i_can_bittiming_const;
>         priv->can.do_set_bittiming = sun7i_can_set_bittiming;
>         priv->can.do_set_mode = sun7i_can_set_mode;
>         priv->can.do_get_berr_counter = sun7i_can_get_berr_counter;
>         priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
>                 CAN_CTRLMODE_LISTENONLY |
>                 CAN_CTRLMODE_3_SAMPLES |
>                 CAN_CTRLMODE_BERR_REPORTING;
> 
>         spin_lock_init(&priv->cmdreg_lock);
> 
>         if (sizeof_priv)
>                 priv->priv = (void *)priv + sizeof(struct sun7i_can_priv);
> 
>         return dev;
> }
> EXPORT_SYMBOL_GPL(alloc_sun7icandev);
> 
> void free_sun7icandev(struct net_device *dev)
> {
>         free_candev(dev);
> }
> EXPORT_SYMBOL_GPL(free_sun7icandev);
> 
> static const struct net_device_ops sun7ican_netdev_ops = {
>        .ndo_open = sun7i_can_open,
>        .ndo_stop = sun7i_can_close,
>        .ndo_start_xmit = sun7i_can_start_xmit,
> };
> 
> int register_sun7icandev(struct net_device *dev)
> {
>         if (!sun7i_can_probe(dev))
>                 return -ENODEV;
> 
>         dev->flags |= IFF_ECHO;        /* support local echo */
>         dev->netdev_ops = &sun7ican_netdev_ops;
> 
>         set_reset_mode(dev);
>         
>         return register_candev(dev);
> }
> EXPORT_SYMBOL_GPL(register_sun7icandev);
> 
> void unregister_sun7icandev(struct net_device *dev)
> {
>         set_reset_mode(dev);
>         unregister_candev(dev);
> }
> EXPORT_SYMBOL_GPL(unregister_sun7icandev);
> 
> static __init int sun7i_can_init(void)
> {
>         struct sun7i_can_priv *priv;
>         int err = 0;
> 		int ret = 0;
> 		int used = 0;
> 		
>         sun7ican_dev = alloc_sun7icandev(0);
>         if(!sun7ican_dev) {
>                 printk(KERN_INFO "alloc sun7icandev fail\n");
>         }
> 	
> 		ret = script_parser_fetch("can_para", "can_used", &used, sizeof (used));
> 		if ( ret || used == 0) {
> 			printk(KERN_INFO "[sun7i-can] Cannot setup CANBus driver, maybe not configured in script.bin?");
> 			goto exit_free;
> 		}

Please add proper DT bindings for this driver.

> 		
>         priv = netdev_priv(sun7ican_dev);
>         sun7ican_dev->irq = SW_INT_IRQNO_CAN;
>         priv->irq_flags = 0;
>         priv->can.clock.freq = clk_get_rate(clk_get(NULL, CLK_MOD_CAN));
>         chipset_init(sun7ican_dev);
>         err = register_sun7icandev(sun7ican_dev);
>         if(err) {
>                 dev_err(&sun7ican_dev->dev, "registering %s failed (err=%d)\n", DRV_NAME, err);
>                 goto exit_free;
>         }
> 
>         dev_info(&sun7ican_dev->dev, "%s device registered (reg_base=0x%08x, irq=%d)\n",
>                  DRV_NAME, CAN_BASE0, sun7ican_dev->irq);
> 
>         printk(KERN_INFO "%s CAN netdevice driver\n", DRV_NAME);
> 
>         return 0;
> 
> exit_free:
>         free_sun7icandev(sun7ican_dev);
> 
>         return err;
> }
> module_init(sun7i_can_init);
> 
> static __exit void sun7i_can_exit(void)
> {
>         unregister_sun7icandev(sun7ican_dev);
>         free_sun7icandev(sun7ican_dev);
> 
>         printk(KERN_INFO "%s: driver removed\n", DRV_NAME);
> }
> module_exit(sun7i_can_exit);

Marc

-- 
Pengutronix e.K.                  | Marc Kleine-Budde           |
Industrial Linux Solutions        | Phone: +49-231-2826-924     |
Vertretung West/Dortmund          | Fax:   +49-5121-206917-5555 |
Amtsgericht Hildesheim, HRA 2686  | http://www.pengutronix.de   |


[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 455 bytes --]

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2015-08-28 10:11 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-27  9:43 Why doesn't the socketcan prio qdisc work for first 10 can frames? Ruan TingQuan (ST-FIR/ENG1-Zhu)
2014-11-27 11:46 ` Oliver Hartkopp
2014-11-27 17:54   ` CAN implementation on A20 Allwinner Pankajkumar Misra (RBEI/EEA2)
2014-11-27 18:28     ` Uwe Bonnes
     [not found]       ` <58243.88.153.236.115.1417116776.squirrel@webmail.rdts.de>
2014-11-27 19:53         ` Gerhard Bertelsmann
2014-12-02 12:37           ` Marc Kleine-Budde
2015-08-27 13:04             ` Gerhard Bertelsmann
2015-08-27 13:23               ` Marc Kleine-Budde
2015-08-27 13:34                 ` Gerhard Bertelsmann
2015-08-27 13:49                   ` Marc Kleine-Budde
2015-08-27 14:29                     ` Gerhard Bertelsmann
2015-08-27 14:37                       ` Marc Kleine-Budde
2015-08-28  5:41                         ` Misra Pankaj Kumar (RBEI/EEA2)
2015-08-28  6:21                           ` Marc Kleine-Budde
2015-08-28  9:22                             ` Gerhard Bertelsmann
2015-08-28 10:11                               ` Marc Kleine-Budde

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).