* Re: Adding new CAN driver
From: Uwe Bonnes @ 2016-11-01 9:48 UTC (permalink / raw)
To: Kołłątaj, Remigiusz; +Cc: linux-can
In-Reply-To: <CAKT-o-cZryPfqkU2rOPu1SdEp8imkTke_NzVgwgghOY6RxrZmg@mail.gmail.com>
>>>>> "Kołłątaj," == Kołłątaj, Remigiusz <remigiusz.kollataj@mobica.com> writes:
Kołłątaj,> If you will find this feature reasonable enough I could
Kołłątaj,> probably spend some effort to work on it.
Any news on adding the Microchip CAN driver?
Thanks
--
Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de
Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
--------- Tel. 06151 1623569 ------- Fax. 06151 1623305 ---------
^ permalink raw reply
* Re: Adding new CAN driver
From: Kołłątaj, Remigiusz @ 2016-11-02 7:23 UTC (permalink / raw)
To: Uwe Bonnes; +Cc: linux-can
In-Reply-To: <22552.25820.453841.413376@gargle.gargle.HOWL>
Hi Uwe,
Not sure if you are asking about termination or about the driver
itself, so let me give two answers.
I'll try to send the patch till end of this week. In the meantime you
may still use the driver from the github repository
(https://github.com/rkollataj/mcba_usb). I am keeping it up to date.
I didn't get a chance to work on adding support for termination to
"ip". Before investing any effort I would prefer to get confirmation
from Oliver of Marc that the direction is right. Anyway setting up
termination via sysfs works just fine. It is described in readme file
in repository.
Regards,
Remik
On 1 November 2016 at 10:48, Uwe Bonnes
<bon@elektron.ikp.physik.tu-darmstadt.de> wrote:
>>>>>> "Kołłątaj," == Kołłątaj, Remigiusz <remigiusz.kollataj@mobica.com> writes:
>
> Kołłątaj,> If you will find this feature reasonable enough I could
> Kołłątaj,> probably spend some effort to work on it.
>
> Any news on adding the Microchip CAN driver?
>
> Thanks
> --
> Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de
>
> Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt
> --------- Tel. 06151 1623569 ------- Fax. 06151 1623305 ---------
--
________________________
Remigiusz Kołłątaj
Mobica Ltd
Software Consultant, CTO Team
Tel: +48 91 881 95 18
Skype: remigiusz.kollataj
www.mobica.com
Mobica is a provider of software engineering, testing and consultancy
services based in the UK, Poland and the USA, with a worldwide
customer base. We have a proven track record in delivering innovative
solutions to some of the world’s best-known companies in a range of
sectors including Automotive, Mobile, Semiconductor, Finance, TV,
Marine and Aviation.
^ permalink raw reply
* Re: Adding new CAN driver
From: Marc Kleine-Budde @ 2016-11-02 8:48 UTC (permalink / raw)
To: Kołłątaj, Remigiusz, Uwe Bonnes; +Cc: linux-can, Oliver Hartkopp
In-Reply-To: <CAKT-o-d_tLkZgAuJz7rrRaDPxmi3hDiLmVhLcpjNBc1weDLvyg@mail.gmail.com>
[-- Attachment #1.1: Type: text/plain, Size: 1065 bytes --]
On 11/02/2016 08:23 AM, Kołłątaj, Remigiusz wrote:
> Hi Uwe,
>
> Not sure if you are asking about termination or about the driver
> itself, so let me give two answers.
>
> I'll try to send the patch till end of this week. In the meantime you
> may still use the driver from the github repository
> (https://github.com/rkollataj/mcba_usb). I am keeping it up to date.
>
> I didn't get a chance to work on adding support for termination to
> "ip". Before investing any effort I would prefer to get confirmation
> from Oliver of Marc that the direction is right. Anyway setting up
> termination via sysfs works just fine. It is described in readme file
> in repository.
I'd like to see a netlink interface for this. Oliver what about adding
it to CTRL_MODE?
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
* Re: [PATCH v2 34/37] docs: fix locations of several documents that got moved
From: Pavel Machek @ 2016-11-02 9:31 UTC (permalink / raw)
To: Mauro Carvalho Chehab
Cc: Nicolas Pitre, Linus Walleij, Jaroslav Kysela, Chris Metcalf,
Peter Loeffler, Finn Thain, Yaowei Bai, Jakub Wilk, linux-acpi,
Geert Uytterhoeven, Guenter Roeck, Petr Mladek, Jean Delvare,
linux-pm, Alexander Viro, Andy Lutomirski, Thomas Gleixner,
Karsten Keil, Jiri Kosina, seokhoon.yoon, Li Zefan, Ryan Swan,
Joe Perches, Andrew Morton, Mark
In-Reply-To: <20161019115918.1162d16e@vento.lan>
[-- Attachment #1.1: Type: text/plain, Size: 1794 bytes --]
Hi!
> > Dunno, but kernel-parameters.txt was already quite long... for a file
> > that is referenced quite often. Adding admin-guide/ into the path does
> > not really help.
>
> The big string name starts with Documentation/ :) There are some discussions
> about changing it to doc/ (or docs/). Also, as you said, kernel-parameters
> is already a big name. Perhaps we could use, instead,
> > "kernel-parms".
cmdline?
> If we rename kernel-parameters.rst to kernel-parms.rst, plus the doc/ rename,
> then the string size will actually reduce:
>
> - (see Documentation/kernel-parameters.txt), the minimum possible
> + (see doc/admin-guide/kernel-parms.rst), the minimum possible
>
> > Maybe admin-guide should go directly into Documentation/ , as that's
> > what our users are interested in?
>
> There are several problems if we keep them at Documentation/ dir:
>
> - We'll end by mixing documents already converted to ReST with documents
> not converted yet;
>
> - A rename is needed anyway, as Sphinx only accepts ReST files that end
> with the extension(s) defined at Documentation/conf.py (currently,
> .rst);
>
> - A partial documentation build is made by sub-directory. If we put
> files under /Documentation, there's no way to build just one
> book.
Well, documentation is primarily for users. I'm sure tools can adapt...
> > Plus, I'm not sure how many developers will figure out that process/
> > is what describes kernel patch submission process. We have processes
> > in the kernel, after all...
>
> Do you have a better idea?
development/ ?
Best regards,
Pavel
--
(english) http://www.livejournal.com/~pavelmachek
(cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html
[-- Attachment #1.2: Digital signature --]
[-- Type: application/pgp-signature, Size: 181 bytes --]
[-- Attachment #2: Type: text/plain, Size: 183 bytes --]
_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization
^ permalink raw reply
* Re: Adding new CAN driver
From: Oliver Hartkopp @ 2016-11-02 9:37 UTC (permalink / raw)
To: Marc Kleine-Budde, Kołłątaj, Remigiusz, Uwe Bonnes
Cc: linux-can
In-Reply-To: <ddb4ed13-819f-ad8c-8ce2-da7585a79098@pengutronix.de>
On 11/02/2016 09:48 AM, Marc Kleine-Budde wrote:
> On 11/02/2016 08:23 AM, Kołłątaj, Remigiusz wrote:
>> I didn't get a chance to work on adding support for termination to
>> "ip". Before investing any effort I would prefer to get confirmation
>> from Oliver of Marc that the direction is right. Anyway setting up
>> termination via sysfs works just fine. It is described in readme file
>> in repository.
>
> I'd like to see a netlink interface for this. Oliver what about adding
> it to CTRL_MODE?
I would suggest to create some kind of TRX_MODE configuration instead.
The CTRL_MODE is CAN controller related (layer 2 / bitstream) while the
transceiver is layer 1.
When creating an interface for transceivers we need to take care about
the different power saving modes /and/ the termination.
E.g. when you have a wake-up capable transceiver you may power-down the
entire machine when you put the TRX into sleep mode (and to wait for CAN
traffic to switch on the power supply again).
Additionally some transceivers have the capability to switch on the
power supply only when a specific CAN ID is seen on the CAN bus
(selective wake-up). In fact these transceivers contain a reduced CAN
controller with on-board clock generation to perform this kind of
functionality.
So when we create a new netlink interface for that purpose we need to
take care to provide a proper API.
Best regards,
Oliver
^ permalink raw reply
* Re: [PATCH v2 34/37] docs: fix locations of several documents that got moved
From: Prarit Bhargava @ 2016-11-02 10:08 UTC (permalink / raw)
To: Pavel Machek, Mauro Carvalho Chehab
Cc: Linux Doc Mailing List, Mauro Carvalho Chehab, Jonathan Corbet,
Rafael J. Wysocki, Len Brown, Jens Axboe, Alessandro Zummo,
Alexandre Belloni, Rob Herring, Mark Rutland, Jean Delvare,
Guenter Roeck, Karsten Keil, Mauro Carvalho Chehab,
Steffen Klassert, Greg Kroah-Hartman, Johannes Berg,
Jaroslav Kysela, Takashi Iwai, Paolo Bonzini <pbon>
In-Reply-To: <20161102093154.GC23350@amd>
On 11/02/2016 05:31 AM, Pavel Machek wrote:
> Hi!
>
>>> Dunno, but kernel-parameters.txt was already quite long... for a file
>>> that is referenced quite often. Adding admin-guide/ into the path does
>>> not really help.
>>
>> The big string name starts with Documentation/ :) There are some discussions
>> about changing it to doc/ (or docs/). Also, as you said, kernel-parameters
>> is already a big name. Perhaps we could use, instead,
>>> "kernel-parms".
>
> cmdline?
You would not believe the number of users I've dealt with that have confused
"cmdline/command line" (aka prompt) with "kernel parameter". I go back and edit
customer debug requests to make sure there's no use of cmdline in place of
kernel parameter.
For the love of every customer facing engineer out there, please stop using
cmdline ;).
P.
>
>> If we rename kernel-parameters.rst to kernel-parms.rst, plus the doc/ rename,
>> then the string size will actually reduce:
>>
>> - (see Documentation/kernel-parameters.txt), the minimum possible
>> + (see doc/admin-guide/kernel-parms.rst), the minimum possible
>>
>>> Maybe admin-guide should go directly into Documentation/ , as that's
>>> what our users are interested in?
>>
>> There are several problems if we keep them at Documentation/ dir:
>>
>> - We'll end by mixing documents already converted to ReST with documents
>> not converted yet;
>>
>> - A rename is needed anyway, as Sphinx only accepts ReST files that end
>> with the extension(s) defined at Documentation/conf.py (currently,
>> .rst);
>>
>> - A partial documentation build is made by sub-directory. If we put
>> files under /Documentation, there's no way to build just one
>> book.
>
> Well, documentation is primarily for users. I'm sure tools can adapt...
>
>>> Plus, I'm not sure how many developers will figure out that process/
>>> is what describes kernel patch submission process. We have processes
>>> in the kernel, after all...
>>
>> Do you have a better idea?
>
> development/ ?
>
> Best regards,
> Pavel
>
--
You received this message because you are subscribed to "rtc-linux".
Membership options at http://groups.google.com/group/rtc-linux .
Please read http://groups.google.com/group/rtc-linux/web/checklist
before submitting a driver.
---
You received this message because you are subscribed to the Google Groups "rtc-linux" group.
To unsubscribe from this group and stop receiving emails from it, send an email to rtc-linux+unsubscribe-/JYPxA39Uh5TLH3MbocFF+G/Ez6ZCGd0@public.gmane.org
For more options, visit https://groups.google.com/d/optout.
^ permalink raw reply
* RE: Adding new CAN driver
From: Ramesh Shanmugasundaram @ 2016-11-02 13:38 UTC (permalink / raw)
To: Marc Kleine-Budde, Kołłątaj, Remigiusz, Uwe Bonnes
Cc: linux-can@vger.kernel.org, Oliver Hartkopp
In-Reply-To: <ddb4ed13-819f-ad8c-8ce2-da7585a79098@pengutronix.de>
> On 11/02/2016 08:23 AM, Kołłątaj, Remigiusz wrote:
> > Hi Uwe,
> >
> > Not sure if you are asking about termination or about the driver
> > itself, so let me give two answers.
> >
> > I'll try to send the patch till end of this week. In the meantime you
> > may still use the driver from the github repository
> > (https://github.com/rkollataj/mcba_usb). I am keeping it up to date.
> >
> > I didn't get a chance to work on adding support for termination to
> > "ip". Before investing any effort I would prefer to get confirmation
> > from Oliver of Marc that the direction is right. Anyway setting up
> > termination via sysfs works just fine. It is described in readme file
> > in repository.
>
> I'd like to see a netlink interface for this. Oliver what about adding it
> to CTRL_MODE?
Is it about the CAN bus termination? Why the driver need to be aware of it?
If it needed for some reason shouldn't it be a device tree property of that device/bridge node?
Thanks,
Ramesh
^ permalink raw reply
* Re: Adding new CAN driver
From: Marc Kleine-Budde @ 2016-11-02 13:59 UTC (permalink / raw)
To: Ramesh Shanmugasundaram, Kołłątaj, Remigiusz,
Uwe Bonnes
Cc: linux-can@vger.kernel.org, Oliver Hartkopp
In-Reply-To: <SG2PR06MB10384C09F05B12731B6D7151C3A00@SG2PR06MB1038.apcprd06.prod.outlook.com>
[-- Attachment #1.1: Type: text/plain, Size: 909 bytes --]
On 11/02/2016 02:38 PM, Ramesh Shanmugasundaram wrote:
>> I'd like to see a netlink interface for this. Oliver what about adding it
>> to CTRL_MODE?
>
> Is it about the CAN bus termination?
Yes.
> Why the driver need to be aware of it?
If the termination is part of the CAN interface, someone has to
configure it, this is typically done by the driver.
> If it needed for some reason shouldn't it be a device tree property
> of that device/bridge node?
No - you want to be able to configure it in the system without needing
to change the DT. The DT is used to descrive the hardware, not configure it.
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
* Re: Adding new CAN driver
From: Alexander Stein @ 2016-11-02 14:14 UTC (permalink / raw)
To: Ramesh Shanmugasundaram
Cc: Marc Kleine-Budde, Kołłątaj, Remigiusz, Uwe Bonnes,
linux-can@vger.kernel.org, Oliver Hartkopp
In-Reply-To: <SG2PR06MB10384C09F05B12731B6D7151C3A00@SG2PR06MB1038.apcprd06.prod.outlook.com>
On Wednesday 02 November 2016 13:38:22, Ramesh Shanmugasundaram wrote:
> > > I didn't get a chance to work on adding support for termination to
> > > "ip". Before investing any effort I would prefer to get confirmation
> > > from Oliver of Marc that the direction is right. Anyway setting up
> > > termination via sysfs works just fine. It is described in readme file
> > > in repository.
> >
> >
> > I'd like to see a netlink interface for this. Oliver what about adding it
> > to CTRL_MODE?
>
>
> Is it about the CAN bus termination? Why the driver need to be aware of it?
> If it needed for some reason shouldn't it be a device tree property of that
> device/bridge node?
I would consider this as a feature, which has to be enabled or disabled on
demand dynamically, depending on current physical connection, especially
regarding USB devices. In thise cases there is also no device tree applicable.
Best regards,
Alexander
^ permalink raw reply
* canfdtest missing tx frame
From: Grim, Dennis @ 2016-11-02 15:12 UTC (permalink / raw)
To: linux-can@vger.kernel.org
I'm running canfdtest between two ports of a PEAK PCAN-PCI Express card. The card appears to use the SJA1000. The bus is terminated.
The ports are configured using:
ip link set can0 up type can bitrate 250000
ip link set can1 up type can bitrate 250000
The test is run using:
canfdtest can1
canfdtest -g -v -l 1000 can0
canfdtest aborts at random numbers of test messages sent and received. The number might be less than 10 or might be several hundred. It never reaches 1000.
Here is a typical output:
$ canfdtest -g -v -l 1000 can0
interface = can0, family = 29, type = 3, proto = 1
Databyte 0 mismatch !
expected: 0078: [8] 25 26 27 28 29 2a 2b 2c
received: 0078: [8] 26 27 28 29 2a 2b 2c 2d
Databyte 1 mismatch !
expected: 0078: [8] 25 26 27 28 29 2a 2b 2c
received: 0078: [8] 26 27 28 29 2a 2b 2c 2d
Databyte 2 mismatch !
expected: 0078: [8] 25 26 27 28 29 2a 2b 2c
received: 0078: [8] 26 27 28 29 2a 2b 2c 2d
Databyte 3 mismatch !
expected: 0078: [8] 25 26 27 28 29 2a 2b 2c
received: 0078: [8] 26 27 28 29 2a 2b 2c 2d
Databyte 4 mismatch !
expected: 0078: [8] 25 26 27 28 29 2a 2b 2c
received: 0078: [8] 26 27 28 29 2a 2b 2c 2d
Databyte 5 mismatch !
expected: 0078: [8] 25 26 27 28 29 2a 2b 2c
received: 0078: [8] 26 27 28 29 2a 2b 2c 2d
Databyte 6 mismatch !
expected: 0078: [8] 25 26 27 28 29 2a 2b 2c
received: 0078: [8] 26 27 28 29 2a 2b 2c 2d
Databyte 7 mismatch !
expected: 0078: [8] 25 26 27 28 29 2a 2b 2c
received: 0078: [8] 26 27 28 29 2a 2b 2c 2d
Test messages sent and received: 37
Exiting...
$
PEAK's PCAN-View is running on a separate machine and reports:
61) 2456.3 Rx 0077 8 1E 1F 20 21 22 23 24 25
62) 2456.9 Rx 0078 8 1F 20 21 22 23 24 25 26
63) 2457.4 Rx 0077 8 1F 20 21 22 23 24 25 26
64) 2458.0 Rx 0078 8 20 21 22 23 24 25 26 27
65) 2458.5 Rx 0077 8 20 21 22 23 24 25 26 27
66) 2459.1 Rx 0078 8 21 22 23 24 25 26 27 28
67) 2461.7 Rx 0077 8 21 22 23 24 25 26 27 28
68) 2462.2 Rx 0078 8 22 23 24 25 26 27 28 29
69) 2462.8 Rx 0077 8 22 23 24 25 26 27 28 29
70) 2463.3 Rx 0078 8 23 24 25 26 27 28 29 2A
71) 2463.9 Rx 0077 8 23 24 25 26 27 28 29 2A
72) 2464.5 Rx 0078 8 24 25 26 27 28 29 2A 2B
73) 2466.1 Rx 0077 8 25 26 27 28 29 2A 2B 2C
74) 2466.7 Rx 0078 8 26 27 28 29 2A 2B 2C 2D
75) 2467.2 Rx 0077 8 26 27 28 29 2A 2B 2C 2D
76) 2467.8 Rx 0078 8 27 28 29 2A 2B 2C 2D 2E
77) 2468.3 Rx 0077 8 27 28 29 2A 2B 2C 2D 2E
78) 2468.9 Rx 0078 8 28 29 2A 2B 2C 2D 2E 2F
79) 2469.4 Rx 0077 8 28 29 2A 2B 2C 2D 2E 2F
80) 2470.0 Rx 0078 8 29 2A 2B 2C 2D 2E 2F 30
Note that the following is missing from the above sequence.
0077 8 24 25 26 27 28 29 2A 2B
0078 8 25 26 27 28 29 2A 2B 2C
What might be the issue here?
^ permalink raw reply
* RE: Adding new CAN driver
From: Ramesh Shanmugasundaram @ 2016-11-02 15:49 UTC (permalink / raw)
To: Alexander Stein
Cc: Marc Kleine-Budde, Kołłątaj, Remigiusz, Uwe Bonnes,
linux-can@vger.kernel.org, Oliver Hartkopp
In-Reply-To: <3113364.8FuUfmAlHQ@ws-stein>
> > > > I didn't get a chance to work on adding support for termination to
> > > > "ip". Before investing any effort I would prefer to get
> > > > confirmation from Oliver of Marc that the direction is right.
> > > > Anyway setting up termination via sysfs works just fine. It is
> > > > described in readme file in repository.
> > >
> > >
> > > I'd like to see a netlink interface for this. Oliver what about
> > > adding it to CTRL_MODE?
> >
> >
> > Is it about the CAN bus termination? Why the driver need to be aware of
> it?
> > If it needed for some reason shouldn't it be a device tree property of
> > that device/bridge node?
>
> I would consider this as a feature, which has to be enabled or disabled on
> demand dynamically, depending on current physical connection, especially
> regarding USB devices. In thise cases there is also no device tree
> applicable.
OK. My question was on the lines - "Is the termination information is needed on a register of the CAN device that the driver manages?" There are cases where the termination is provided by the D-sub connector. The controller should just see bus error when improperly terminated. I don't know about USB based devices and please forgive me if this is the norm.
But this is physical layer information as Oliver mentioned. The CAN transceiver may even require some start-up state that may be enabled by setting couple of GPIOs (as on my board). Yes, it is part of the CAN interface configuration but it not part of the CAN controller driver. I think we could map it to Ethernet MAC & PHY case - isn't it?
Thanks,
Ramesh
^ permalink raw reply
* Re: Adding new CAN driver
From: Alexander Stein @ 2016-11-02 16:08 UTC (permalink / raw)
To: Ramesh Shanmugasundaram
Cc: Marc Kleine-Budde, Kołłątaj, Remigiusz, Uwe Bonnes,
linux-can@vger.kernel.org, Oliver Hartkopp
In-Reply-To: <SG2PR06MB1038F0416E850F0C09BC5CCEC3A00@SG2PR06MB1038.apcprd06.prod.outlook.com>
On Wednesday 02 November 2016 15:49:50, Ramesh Shanmugasundaram wrote:
> > > > > I didn't get a chance to work on adding support for termination to
> > > > > "ip". Before investing any effort I would prefer to get
> > > > > confirmation from Oliver of Marc that the direction is right.
> > > > > Anyway setting up termination via sysfs works just fine. It is
> > > > > described in readme file in repository.
> > > >
> > > > I'd like to see a netlink interface for this. Oliver what about
> > > > adding it to CTRL_MODE?
> > >
> > > Is it about the CAN bus termination? Why the driver need to be aware of
> >
> > it?
> >
> > > If it needed for some reason shouldn't it be a device tree property of
> > > that device/bridge node?
> >
> > I would consider this as a feature, which has to be enabled or disabled on
> > demand dynamically, depending on current physical connection, especially
> > regarding USB devices. In thise cases there is also no device tree
> > applicable.
>
> OK. My question was on the lines - "Is the termination information is needed
> on a register of the CAN device that the driver manages?" There are cases
> where the termination is provided by the D-sub connector. The controller
> should just see bus error when improperly terminated. I don't know about
> USB based devices and please forgive me if this is the norm.
No problem, I just wanted to point out that device tree is not suitable in
this case.
> But this is physical layer information as Oliver mentioned. The CAN
> transceiver may even require some start-up state that may be enabled by
> setting couple of GPIOs (as on my board). Yes, it is part of the CAN
> interface configuration but it not part of the CAN controller driver. I
> think we could map it to Ethernet MAC & PHY case - isn't it?
The transceiver might be managed by regulators as done by e.g. flexcan. This
is part of the hardware description, so device tree here is fine.
But in my opinion bus termination is an end user configuration which might
change rather often than not. It might be independent of the controller driver
as e.g. in flexcan, but it might be part of the device as in USB hardware
which requires some specific command to change bus termination.
IMHO it makes no sense to split an USB interface driver into two parts using
the same interface in the end.
Best regards,
Alexander
^ permalink raw reply
* Re: canfdtest missing tx frame
From: Andri Yngvason @ 2016-11-02 16:47 UTC (permalink / raw)
To: Grim, Dennis, linux-can@vger.kernel.org
In-Reply-To: <1579A5A5423CC14B827884B535F8E9513493B8CE@SSCOXCHG2.spray.com>
Quoting Grim, Dennis (2016-11-02 15:12:01)
> I'm running canfdtest between two ports of a PEAK PCAN-PCI Express card. The card appears to use the SJA1000. The bus is terminated.
>
> The ports are configured using:
> ip link set can0 up type can bitrate 250000
> ip link set can1 up type can bitrate 250000
>
> The test is run using:
> canfdtest can1
> canfdtest -g -v -l 1000 can0
>
> canfdtest aborts at random numbers of test messages sent and received. The number might be less than 10 or might be several hundred. It never reaches 1000.
>
[...]
Hi Dennis,
See this thread: http://marc.info/?l=linux-can&m=144785931426968&w=2
Work-around here: http://marc.info/?l=linux-can&m=144908079021623&w=2
PEAK have acknowledged an issue with the firmware, and I assume that they have
fixed the issue in the firmware, and they did post a patch for working around
the issue with older firmware, but no one has followed through on it.
Regards,
Andri
^ permalink raw reply
* Re: Adding new CAN driver
From: Kołłątaj, Remigiusz @ 2016-11-02 18:03 UTC (permalink / raw)
To: Alexander Stein
Cc: Ramesh Shanmugasundaram, Marc Kleine-Budde, Uwe Bonnes,
linux-can@vger.kernel.org, Oliver Hartkopp
In-Reply-To: <1490105.s3iJfGbYsS@ws-stein>
On 2 November 2016 at 17:08, Alexander Stein
<alexander.stein@systec-electronic.com> wrote:
> On Wednesday 02 November 2016 15:49:50, Ramesh Shanmugasundaram wrote:
>> > > > > I didn't get a chance to work on adding support for termination to
>> > > > > "ip". Before investing any effort I would prefer to get
>> > > > > confirmation from Oliver of Marc that the direction is right.
>> > > > > Anyway setting up termination via sysfs works just fine. It is
>> > > > > described in readme file in repository.
>> > > >
>> > > > I'd like to see a netlink interface for this. Oliver what about
>> > > > adding it to CTRL_MODE?
>> > >
>> > > Is it about the CAN bus termination? Why the driver need to be aware of
>> >
>> > it?
>> >
>> > > If it needed for some reason shouldn't it be a device tree property of
>> > > that device/bridge node?
>> >
>> > I would consider this as a feature, which has to be enabled or disabled on
>> > demand dynamically, depending on current physical connection, especially
>> > regarding USB devices. In thise cases there is also no device tree
>> > applicable.
>>
>> OK. My question was on the lines - "Is the termination information is needed
>> on a register of the CAN device that the driver manages?" There are cases
>> where the termination is provided by the D-sub connector. The controller
>> should just see bus error when improperly terminated. I don't know about
>> USB based devices and please forgive me if this is the norm.
>
> No problem, I just wanted to point out that device tree is not suitable in
> this case.
>
>> But this is physical layer information as Oliver mentioned. The CAN
>> transceiver may even require some start-up state that may be enabled by
>> setting couple of GPIOs (as on my board). Yes, it is part of the CAN
>> interface configuration but it not part of the CAN controller driver. I
>> think we could map it to Ethernet MAC & PHY case - isn't it?
>
> The transceiver might be managed by regulators as done by e.g. flexcan. This
> is part of the hardware description, so device tree here is fine.
> But in my opinion bus termination is an end user configuration which might
> change rather often than not. It might be independent of the controller driver
> as e.g. in flexcan, but it might be part of the device as in USB hardware
> which requires some specific command to change bus termination.
> IMHO it makes no sense to split an USB interface driver into two parts using
> the same interface in the end.
I agree that termination is a physical layer setting but to be
specific in case of Microchip's CAN BUS it is neither related to CAN
controller nor transceiver. It is rather device specific - termination
settings are controlled via GPIO pin that just attaches/deattaches
resistor. You can find schematics here:
http://ww1.microchip.com/downloads/en/DeviceDoc/51848B.pdf (CAN RES
line).
I can see that the topic is not as straight forward as I thought in
the beginning. I don't even know if termination is configurable in
different CAN devices. As far as I recall Vector for example provides
physical DB9 gender changer with built-in terminator. Maybe we should
treat Microchip as "special case" and leave termination settings in
sysfs?
>
> Best regards,
> Alexander
Regards,
Remik
^ permalink raw reply
* Re: termination?
From: Kurt Van Dijck @ 2016-11-02 19:41 UTC (permalink / raw)
To: Oliver Hartkopp
Cc: Kołłątaj, Remigiusz, linux-can, Marc Kleine-Budde
In-Reply-To: <ce34a9f7-d310-00aa-6d53-ad08b45cfa3f@hartkopp.net>
> Hi Remik,
>
> On 10/21/2016 08:47 PM, Kołłątaj, Remigiusz wrote:
> >>I was just looking through your code and wondered whether we should support
> >>the termination switching feature via 'ip' tool or via sysfs.
> >>
> >>Just added Marc in CC.
> >>
> >
> >I tried to use 'ip' for setting up termination, but I couldn't find a
> >way. If this is possible I will modify the driver as it seems to be
> >better idea. Could you give me some hints?
>
> No - not now :-)
>
> That's why I wanted to start the discussion whether we should add this kind
> of feature to 'ip'.
selectable 120Ohm termination sounds very familiar, I'm sure I encountered >1
devices in the past offering this, so it's a good thing to discuss.
Looking to the (dis)advantages of both methods, I'd vote for extending
the netlink interface.
Keeping the sysfs interface semantically equal between drivers is hard,
not speaking on the kernel internal issues.
Kurt
^ permalink raw reply
* Re: Adding new CAN driver
From: Oliver Hartkopp @ 2016-11-03 15:50 UTC (permalink / raw)
To: Kołłątaj, Remigiusz, Alexander Stein
Cc: Ramesh Shanmugasundaram, Marc Kleine-Budde, Uwe Bonnes,
linux-can@vger.kernel.org, Kurt Van Dijck
In-Reply-To: <CAKT-o-cJ3UwD=xakh7-hF5101rS2zCa5AHfjBvdRNATJD+Weqw@mail.gmail.com>
On 11/02/2016 07:03 PM, Kołłątaj, Remigiusz wrote:
> On 2 November 2016 at 17:08, Alexander Stein
> <alexander.stein@systec-electronic.com> wrote:
>> On Wednesday 02 November 2016 15:49:50, Ramesh Shanmugasundaram wrote:
>>> But this is physical layer information as Oliver mentioned. The CAN
>>> transceiver may even require some start-up state that may be enabled by
>>> setting couple of GPIOs (as on my board). Yes, it is part of the CAN
>>> interface configuration but it not part of the CAN controller driver. I
>>> think we could map it to Ethernet MAC & PHY case - isn't it?
IIRC there's some mii-tool to configure, view & manipulate
media-independent interface status:
http://man7.org/linux/man-pages/man8/mii-tool.8.html
At least the ethernet people found a way to configure their transceiver
part with this tool.
>> The transceiver might be managed by regulators as done by e.g. flexcan. This
>> is part of the hardware description, so device tree here is fine.
>> But in my opinion bus termination is an end user configuration which might
>> change rather often than not. It might be independent of the controller driver
>> as e.g. in flexcan, but it might be part of the device as in USB hardware
>> which requires some specific command to change bus termination.
>> IMHO it makes no sense to split an USB interface driver into two parts using
>> the same interface in the end.
ack.
> I agree that termination is a physical layer setting but to be
> specific in case of Microchip's CAN BUS it is neither related to CAN
> controller nor transceiver.
So what about creating TWO new netlink configuration options:
diff --git a/include/uapi/linux/can/netlink.h
b/include/uapi/linux/can/netlink.h
index 94ffe0c..8d7c4b9 100644
--- a/include/uapi/linux/can/netlink.h
+++ b/include/uapi/linux/can/netlink.h
@@ -127,6 +127,8 @@ enum {
IFLA_CAN_BERR_COUNTER,
IFLA_CAN_DATA_BITTIMING,
IFLA_CAN_DATA_BITTIMING_CONST,
+ IFLA_CAN_TRX_CTRL,
+ IFLA_CAN_TERMINATION,
__IFLA_CAN_MAX
};
Where IFLA_CAN_TRX_CTRL provides an interface to configure the
transceiver and IFLA_CAN_TERMINATION to configure the termination.
But for IFLA_CAN_TERMINATION we need some possibility to configure
either a set of supported termination resistors (e.g. disabled, 60 Ohms,
120 Ohms, xxx Ohms, ...) or a free termination value (e.g. 1 Ohm - 10
kOhms) following the hardware capabilities of the CAN device.
Therefore a list of values and ranges has to be made available by the
netlink interface before userspace can select some of them.
Both IFLA_CAN_TRX_CTRL and IFLA_CAN_TERMINATION would only be supported
if the CAN device can handle them. Probably a device tree decription
defines a fixed configuration which can be read but not modified.
Any ideas/comments on this?
Regards,
Oliver
^ permalink raw reply related
* Re: Adding new CAN driver
From: Kurt Van Dijck @ 2016-11-03 21:24 UTC (permalink / raw)
To: Oliver Hartkopp
Cc: Kołłątaj, Remigiusz, Alexander Stein,
Ramesh Shanmugasundaram, Marc Kleine-Budde, Uwe Bonnes,
linux-can@vger.kernel.org
In-Reply-To: <5f302213-c072-b6b8-aa78-4bc405dc167d@hartkopp.net>
>
> On 11/02/2016 07:03 PM, Kołłątaj, Remigiusz wrote:
> >On 2 November 2016 at 17:08, Alexander Stein
> ><alexander.stein@systec-electronic.com> wrote:
> >>On Wednesday 02 November 2016 15:49:50, Ramesh Shanmugasundaram wrote:
>
> >>>But this is physical layer information as Oliver mentioned. The CAN
> >>>transceiver may even require some start-up state that may be enabled by
> >>>setting couple of GPIOs (as on my board). Yes, it is part of the CAN
> >>>interface configuration but it not part of the CAN controller driver. I
> >>>think we could map it to Ethernet MAC & PHY case - isn't it?
>
> IIRC there's some mii-tool to configure, view & manipulate media-independent
> interface status:
>
> http://man7.org/linux/man-pages/man8/mii-tool.8.html
>
> At least the ethernet people found a way to configure their transceiver part
> with this tool.
>
> >>The transceiver might be managed by regulators as done by e.g. flexcan. This
> >>is part of the hardware description, so device tree here is fine.
> >>But in my opinion bus termination is an end user configuration which might
> >>change rather often than not. It might be independent of the controller driver
> >>as e.g. in flexcan, but it might be part of the device as in USB hardware
> >>which requires some specific command to change bus termination.
> >>IMHO it makes no sense to split an USB interface driver into two parts using
> >>the same interface in the end.
>
> ack.
>
> >I agree that termination is a physical layer setting but to be
> >specific in case of Microchip's CAN BUS it is neither related to CAN
> >controller nor transceiver.
>
> So what about creating TWO new netlink configuration options:
>
> diff --git a/include/uapi/linux/can/netlink.h
> b/include/uapi/linux/can/netlink.h
> index 94ffe0c..8d7c4b9 100644
> --- a/include/uapi/linux/can/netlink.h
> +++ b/include/uapi/linux/can/netlink.h
> @@ -127,6 +127,8 @@ enum {
> IFLA_CAN_BERR_COUNTER,
> IFLA_CAN_DATA_BITTIMING,
> IFLA_CAN_DATA_BITTIMING_CONST,
> + IFLA_CAN_TRX_CTRL,
> + IFLA_CAN_TERMINATION,
> __IFLA_CAN_MAX
> };
>
> Where IFLA_CAN_TRX_CTRL provides an interface to configure the transceiver
> and IFLA_CAN_TERMINATION to configure the termination.
termination, like bittiming, depends on the physical layer.
Hard to say if it's a user option of a system requirement,
it is similar and should be configurable from userspace (root probably).
>
> But for IFLA_CAN_TERMINATION we need some possibility to configure either a
> set of supported termination resistors (e.g. disabled, 60 Ohms, 120 Ohms,
> xxx Ohms, ...) or a free termination value (e.g. 1 Ohm - 10 kOhms) following
> the hardware capabilities of the CAN device.
> Therefore a list of values and ranges has to be made available by the
> netlink interface before userspace can select some of them.
Instead of trying to foresee the future and allowing any resistor value,
I'd propose to stick to common physical layers. I wasn't aware of any
physical that has a 10KOhm terminting resistor, nor did I see any TRX
supporting it. So an ISO 11898 bus termination should not allow _any_
resistor value?
Maybe next year a brand new physical layer appears, then we'll add
support for that layer? And maybe that layer may support random
termintion resistors (really?), we'll see then.
for now, IFLA_CAN_TERMINATION may be a boolean (or enumeration).
Kind regards,
Kurt
>
> Both IFLA_CAN_TRX_CTRL and IFLA_CAN_TERMINATION would only be supported if
> the CAN device can handle them. Probably a device tree decription defines a
> fixed configuration which can be read but not modified.
For IFLA_CAN_TERMINATION, I don't see added value putting constants in
device tree, since device tree describes the board and termination
depends on the bus beyond the board. So you can't describe in devicetree
that you always want the termination activated in the controller.
Besides that remark on the constant, I agree with you, although I'm not
sure what function would be possible with IFLA_CAN_TRX_CTRL?
Wakeup-gpio? maximum-bitrate (controlled by a 0-100KOhm resistor on
popular phy's?, ...).
Kurt
^ permalink raw reply
* [PATCH] can: mcba_usb: Add support for Microchip CAN BUS Analyzer.
From: Remigiusz Kollataj @ 2016-11-04 8:03 UTC (permalink / raw)
To: linux-can; +Cc: Remigiusz Kollataj
SocketCAN driver for Microchip CAN BUS Analyzer
(http://www.microchip.com/development-tools/)
Main features (v1):
* Basic and extended frames support
* RTR frames support
* Supported hard-coded speeds: 20000, 33333, 50000, 80000, 83333, 100000,
125000, 150000, 175000, 200000, 225000, 250000, 275000, 300000, 500000,
625000, 800000, 1000000.
* Configuration of built-in termination via sysfs
Signed-off-by: Remigiusz Kollataj <remigiusz.kollataj@mobica.com>
---
drivers/net/can/usb/Kconfig | 6 +
drivers/net/can/usb/Makefile | 1 +
drivers/net/can/usb/mcba_usb.c | 1210 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 1217 insertions(+)
create mode 100644 drivers/net/can/usb/mcba_usb.c
diff --git a/drivers/net/can/usb/Kconfig b/drivers/net/can/usb/Kconfig
index 8483a40..2d0313e 100644
--- a/drivers/net/can/usb/Kconfig
+++ b/drivers/net/can/usb/Kconfig
@@ -81,4 +81,10 @@ config CAN_8DEV_USB
This driver supports the USB2CAN interface
from 8 devices (http://www.8devices.com).
+config CAN_MCBA_USB
+ tristate "Microchip CAN BUS Analyzer interface"
+ ---help---
+ This driver supports the CAN BUS Analyzer interface
+ from Microchip (http://www.microchip.com/development-tools/).
+
endmenu
diff --git a/drivers/net/can/usb/Makefile b/drivers/net/can/usb/Makefile
index a64cf98..164453f 100644
--- a/drivers/net/can/usb/Makefile
+++ b/drivers/net/can/usb/Makefile
@@ -8,3 +8,4 @@ obj-$(CONFIG_CAN_GS_USB) += gs_usb.o
obj-$(CONFIG_CAN_KVASER_USB) += kvaser_usb.o
obj-$(CONFIG_CAN_PEAK_USB) += peak_usb/
obj-$(CONFIG_CAN_8DEV_USB) += usb_8dev.o
+obj-$(CONFIG_CAN_MCBA_USB) += mcba_usb.o
diff --git a/drivers/net/can/usb/mcba_usb.c b/drivers/net/can/usb/mcba_usb.c
new file mode 100644
index 0000000..a4fa8ba
--- /dev/null
+++ b/drivers/net/can/usb/mcba_usb.c
@@ -0,0 +1,1210 @@
+/* SocketCAN driver for Microchip CAN BUS Analyzer Tool
+ *
+ * Copyright (C) 2016 Mobica Limited
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published
+ * by the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program.
+ *
+ * This driver is inspired by the 4.6.2 version of net/can/usb/usb_8dev.c
+ */
+
+#include <linux/usb.h>
+#include <linux/can/dev.h>
+
+/* vendor and product id */
+#define MCBA_MODULE_NAME "mcba_usb"
+#define MCBA_VENDOR_ID 0x04d8
+#define MCBA_PRODUCT_ID 0x0a30
+
+/* driver constants */
+#define MCBA_MAX_RX_URBS 20
+#define MCBA_MAX_TX_URBS 20
+#define MCBA_CTX_FREE MCBA_MAX_TX_URBS
+
+/* RX buffer must be bigger than msg size since at the
+ * beggining USB messages are stacked.
+ */
+#define MCBA_USB_RX_BUFF_SIZE 64
+#define MCBA_USB_TX_BUFF_SIZE (sizeof(struct mcba_usb_msg))
+
+/* MCBA endpoint numbers */
+#define MCBA_USB_EP_IN 1
+#define MCBA_USB_EP_OUT 1
+
+/* Not required by driver itself as CANBUS is USB based
+ * Used internally by candev for bitrate calculation
+ */
+#define MCBA_CAN_CLOCK 40000000
+
+/* Microchip command id */
+#define MBCA_CMD_RECEIVE_MESSAGE 0xE3
+#define MBCA_CMD_I_AM_ALIVE_FROM_CAN 0xF5
+#define MBCA_CMD_I_AM_ALIVE_FROM_USB 0xF7
+#define MBCA_CMD_CHANGE_BIT_RATE 0xA1
+#define MBCA_CMD_TRANSMIT_MESSAGE_EV 0xA3
+#define MBCA_CMD_SETUP_TERMINATION_RESISTANCE 0xA8
+#define MBCA_CMD_READ_FW_VERSION 0xA9
+#define MBCA_CMD_NOTHING_TO_SEND 0xFF
+#define MBCA_CMD_TRANSMIT_MESSAGE_RSP 0xE2
+
+/* debug module parameter handling */
+#define MCBA_PARAM_DEBUG_DISABLE 0
+#define MCBA_PARAM_DEBUG_USB 1
+#define MCBA_PARAM_DEBUG_CAN 2
+#define MCBA_IS_USB_DEBUG() (debug & MCBA_PARAM_DEBUG_USB)
+#define MCBA_IS_CAN_DEBUG() (debug & MCBA_PARAM_DEBUG_CAN)
+
+#define MCBA_VER_REQ_USB 1
+#define MCBA_VER_REQ_CAN 2
+
+#define MCBA_CAN_S_SID0_SID2_MASK 0x7
+#define MCBA_CAN_S_SID3_SID10_MASK 0x7F8
+#define MCBA_CAN_S_SID3_SID10_SHIFT 3
+
+#define MCBA_CAN_EID0_EID7_MASK 0xff
+#define MCBA_CAN_EID8_EID15_MASK 0xff00
+#define MCBA_CAN_EID16_EID17_MASK 0x30000
+#define MCBA_CAN_E_SID0_SID2_MASK 0x1c0000
+#define MCBA_CAN_E_SID3_SID10_MASK 0x1fe00000
+#define MCBA_CAN_EID8_EID15_SHIFT 8
+#define MCBA_CAN_EID16_EID17_SHIFT 16
+#define MCBA_CAN_E_SID0_SID2_SHIFT 18
+#define MCBA_CAN_E_SID3_SID10_SHIFT 21
+
+#define MCBA_SIDL_SID0_SID2_MASK 0xe0
+#define MCBA_SIDL_EXID_MASK 0x8
+#define MCBA_SIDL_EID16_EID17_MASK 0x3
+#define MCBA_SIDL_SID0_SID2_SHIFT 5
+
+#define MCBA_DLC_MASK 0xf
+#define MCBA_DLC_RTR_MASK 0x40
+
+#define MCBA_CAN_RTR_MASK 0x40000000
+#define MCBA_CAN_EXID_MASK 0x80000000
+
+#define MCBA_SET_S_SIDL(can_id)\
+(((can_id) & MCBA_CAN_S_SID0_SID2_MASK) << MCBA_SIDL_SID0_SID2_SHIFT)
+
+#define MCBA_SET_E_SIDL(can_id)\
+(((((can_id) & MCBA_CAN_E_SID0_SID2_MASK) >> MCBA_CAN_E_SID0_SID2_SHIFT)\
+<< MCBA_SIDL_SID0_SID2_SHIFT) |\
+(((can_id) & MCBA_CAN_EID16_EID17_MASK) >> MCBA_CAN_EID16_EID17_SHIFT) |\
+MCBA_SIDL_EXID_MASK)
+
+#define MCBA_SET_S_SIDH(can_id)\
+(((can_id) & MCBA_CAN_S_SID3_SID10_MASK) >> MCBA_CAN_S_SID3_SID10_SHIFT)
+
+#define MCBA_SET_E_SIDH(can_id)\
+(((can_id) & MCBA_CAN_E_SID3_SID10_MASK) >> MCBA_CAN_E_SID3_SID10_SHIFT)
+
+#define MCBA_SET_EIDL(can_id)\
+((can_id) & MCBA_CAN_EID0_EID7_MASK)
+
+#define MCBA_SET_EIDH(can_id)\
+(((can_id) & MCBA_CAN_EID8_EID15_MASK) >> MCBA_CAN_EID8_EID15_SHIFT)
+
+#define MCBA_CAN_GET_SID(usb_msg)\
+((((usb_msg)->sidl & MCBA_SIDL_SID0_SID2_MASK) >> MCBA_SIDL_SID0_SID2_SHIFT) |\
+((usb_msg)->sidh << MCBA_CAN_S_SID3_SID10_SHIFT))
+
+#define MCBA_CAN_GET_EID(usb_msg)\
+((((usb_msg)->sidh << MCBA_CAN_E_SID3_SID10_SHIFT) |\
+(((usb_msg)->sidl & MCBA_SIDL_SID0_SID2_MASK) >> MCBA_SIDL_SID0_SID2_SHIFT) \
+<< MCBA_CAN_E_SID0_SID2_SHIFT) |\
+(((usb_msg)->sidl & MCBA_SIDL_EID16_EID17_MASK) \
+<< MCBA_CAN_EID16_EID17_SHIFT) |\
+((usb_msg)->eidh << MCBA_CAN_EID8_EID15_SHIFT) |\
+(usb_msg)->eidl |\
+MCBA_CAN_EXID_MASK)
+
+#define MCBA_RX_IS_EXID(usb_msg) ((usb_msg)->sidl & MCBA_SIDL_EXID_MASK)
+#define MCBA_RX_IS_RTR(usb_msg) ((usb_msg)->dlc & MCBA_DLC_RTR_MASK)
+#define MCBA_TX_IS_EXID(can_frame) ((can_frame)->can_id & MCBA_CAN_EXID_MASK)
+#define MCBA_TX_IS_RTR(can_frame) ((can_frame)->can_id & MCBA_CAN_RTR_MASK)
+
+struct mcba_usb_ctx {
+ struct mcba_priv *priv;
+ u32 ndx;
+ u8 dlc;
+ bool can;
+};
+
+/* Structure to hold all of our device specific stuff */
+struct mcba_priv {
+ struct can_priv can; /* must be the first member */
+ struct sk_buff *echo_skb[MCBA_MAX_TX_URBS];
+ struct mcba_usb_ctx tx_context[MCBA_MAX_TX_URBS];
+
+ struct usb_device *udev;
+ struct net_device *netdev;
+ struct usb_anchor tx_submitted;
+ struct usb_anchor rx_submitted;
+ struct can_berr_counter bec;
+ u8 termination_state;
+ bool usb_ka_first_pass;
+ bool can_ka_first_pass;
+};
+
+/* command frame */
+struct __packed mcba_usb_msg_can {
+ u8 cmd_id;
+ u8 eidh;
+ u8 eidl;
+ u8 sidh;
+ u8 sidl;
+ u8 dlc;
+ u8 data[8];
+ u8 timestamp[4];
+ u8 checksum;
+};
+
+/* command frame */
+struct __packed mcba_usb_msg {
+ u8 cmd_id;
+ u8 unused[18];
+};
+
+struct __packed mcba_usb_msg_ka_usb {
+ u8 cmd_id;
+ u8 termination_state;
+ u8 soft_ver_major;
+ u8 soft_ver_minor;
+ u8 unused[15];
+};
+
+struct __packed mcba_usb_msg_ka_can {
+ u8 cmd_id;
+ u8 tx_err_cnt;
+ u8 rx_err_cnt;
+ u8 rx_buff_ovfl;
+ u8 tx_bus_off;
+ u8 can_bitrate_hi;
+ u8 can_bitrate_lo;
+ u8 rx_lost_lo;
+ u8 rx_lost_hi;
+ u8 can_stat;
+ u8 soft_ver_major;
+ u8 soft_ver_minor;
+ u8 debug_mode;
+ u8 test_complete;
+ u8 test_result;
+ u8 unused[4];
+};
+
+struct __packed mcba_usb_msg_change_bitrate {
+ u8 cmd_id;
+ u8 bitrate_hi;
+ u8 bitrate_lo;
+ u8 unused[16];
+};
+
+struct __packed mcba_usb_msg_terminaton {
+ u8 cmd_id;
+ u8 termination;
+ u8 unused[17];
+};
+
+struct __packed mcba_usb_msg_fw_ver {
+ u8 cmd_id;
+ u8 pic;
+ u8 unused[17];
+};
+
+struct bitrate_settings {
+ struct can_bittiming bt;
+ u16 kbps;
+};
+
+/* Required by can-dev but not for the sake of driver as CANBUS is USB based */
+static const struct can_bittiming_const mcba_bittiming_const = {
+ .name = "mcba_usb",
+ .tseg1_min = 1,
+ .tseg1_max = 8,
+ .tseg2_min = 1,
+ .tseg2_max = 8,
+ .sjw_max = 4,
+ .brp_min = 2,
+ .brp_max = 128,
+ .brp_inc = 2,
+};
+
+/* predefined values hardcoded in device's firmware */
+static const struct bitrate_settings br_settings[] = {
+ {
+ .bt = {
+ .bitrate = 19940,
+ .sample_point = 700,
+ .tq = 2500,
+ .prop_seg = 5,
+ .phase_seg1 = 8,
+ .phase_seg2 = 6,
+ .sjw = 1,
+ .brp = 100,
+ },
+ .kbps = 20
+ },
+ {
+ .bt = {
+ .bitrate = 33333,
+ .sample_point = 680,
+ .tq = 1200,
+ .prop_seg = 8,
+ .phase_seg1 = 8,
+ .phase_seg2 = 8,
+ .sjw = 1,
+ .brp = 48,
+ },
+ .kbps = 33
+ },
+ {
+ .bt = {
+ .bitrate = 50000,
+ .sample_point = 800,
+ .tq = 1000,
+ .prop_seg = 8,
+ .phase_seg1 = 7,
+ .phase_seg2 = 4,
+ .sjw = 1,
+ .brp = 40,
+ },
+ .kbps = 50
+ },
+ {
+ .bt = {
+ .bitrate = 80000,
+ .sample_point = 680,
+ .tq = 500,
+ .prop_seg = 8,
+ .phase_seg1 = 8,
+ .phase_seg2 = 8,
+ .sjw = 1,
+ .brp = 20,
+ },
+ .kbps = 80
+ },
+ {
+ .bt = {
+ .bitrate = 83333,
+ .sample_point = 708,
+ .tq = 500,
+ .prop_seg = 8,
+ .phase_seg1 = 8,
+ .phase_seg2 = 7,
+ .sjw = 1,
+ .brp = 20,
+ },
+ .kbps = 83
+ },
+ {
+ .bt = {
+ .bitrate = 100000,
+ .sample_point = 700,
+ .tq = 1000,
+ .prop_seg = 1,
+ .phase_seg1 = 5,
+ .phase_seg2 = 3,
+ .sjw = 1,
+ .brp = 40,
+ },
+ .kbps = 100
+ },
+ {
+ .bt = {
+ .bitrate = 125000,
+ .sample_point = 600,
+ .tq = 400,
+ .prop_seg = 3,
+ .phase_seg1 = 8,
+ .phase_seg2 = 8,
+ .sjw = 1,
+ .brp = 16,
+ },
+ .kbps = 125
+ },
+ {
+ .bt = {
+ .bitrate = 150375,
+ .sample_point = 789,
+ .tq = 350,
+ .prop_seg = 8,
+ .phase_seg1 = 6,
+ .phase_seg2 = 4,
+ .sjw = 1,
+ .brp = 14,
+ },
+ .kbps = 150
+ },
+
+ {
+ .bt = {
+ .bitrate = 175438,
+ .sample_point = 789,
+ .tq = 300,
+ .prop_seg = 8,
+ .phase_seg1 = 6,
+ .phase_seg2 = 4,
+ .sjw = 1,
+ .brp = 12,
+ },
+ .kbps = 175
+ },
+ {
+ .bt = {
+ .bitrate = 200000,
+ .sample_point = 680,
+ .tq = 200,
+ .prop_seg = 8,
+ .phase_seg1 = 8,
+ .phase_seg2 = 8,
+ .sjw = 1,
+ .brp = 8,
+ },
+ .kbps = 200
+ },
+ {
+ .bt = {
+ .bitrate = 227272,
+ .sample_point = 772,
+ .tq = 200,
+ .prop_seg = 8,
+ .phase_seg1 = 8,
+ .phase_seg2 = 5,
+ .sjw = 1,
+ .brp = 8,
+ },
+ .kbps = 225
+ },
+ {
+ .bt = {
+ .bitrate = 250000,
+ .sample_point = 600,
+ .tq = 200,
+ .prop_seg = 3,
+ .phase_seg1 = 8,
+ .phase_seg2 = 8,
+ .sjw = 1,
+ .brp = 8,
+ },
+ .kbps = 250
+ },
+ {
+ .bt = {
+ .bitrate = 277777,
+ .sample_point = 708,
+ .tq = 150,
+ .prop_seg = 8,
+ .phase_seg1 = 8,
+ .phase_seg2 = 7,
+ .sjw = 1,
+ .brp = 6,
+ },
+ .kbps = 275
+ },
+ {
+ .bt = {
+ .bitrate = 303030,
+ .sample_point = 772,
+ .tq = 150,
+ .prop_seg = 8,
+ .phase_seg1 = 8,
+ .phase_seg2 = 5,
+ .sjw = 1,
+ .brp = 6,
+ },
+ .kbps = 300
+ },
+ {
+ .bt = {
+ .bitrate = 500000,
+ .sample_point = 600,
+ .tq = 100,
+ .prop_seg = 3,
+ .phase_seg1 = 8,
+ .phase_seg2 = 8,
+ .sjw = 1,
+ .brp = 4,
+ },
+ .kbps = 500
+ },
+ {
+ .bt = {
+ .bitrate = 625000,
+ .sample_point = 750,
+ .tq = 200,
+ .prop_seg = 1,
+ .phase_seg1 = 4,
+ .phase_seg2 = 2,
+ .sjw = 1,
+ .brp = 8,
+ },
+ .kbps = 625
+ },
+ {
+ .bt = {
+ .bitrate = 800000,
+ .sample_point = 680,
+ .tq = 50,
+ .prop_seg = 8,
+ .phase_seg1 = 8,
+ .phase_seg2 = 8,
+ .sjw = 1,
+ .brp = 2,
+ },
+ .kbps = 800
+ },
+ {
+ .bt = {
+ .bitrate = 1000000,
+ .sample_point = 600,
+ .tq = 50,
+ .prop_seg = 3,
+ .phase_seg1 = 8,
+ .phase_seg2 = 8,
+ .sjw = 1,
+ .brp = 2,
+ },
+ .kbps = 1000
+ }
+};
+
+static int debug;
+module_param(debug, int, 0664);
+MODULE_PARM_DESC(debug,
+ "Binary flag to control device debug (keep alive) prints in dmesg. 0='Debug prints disabled' "
+ __stringify(MCBA_PARAM_DEBUG_USB) "='PIC_USB debugs enabled' "
+ __stringify(MCBA_PARAM_DEBUG_CAN) "='PIC_CAN debugs enabled'");
+
+static const struct usb_device_id mcba_usb_table[] = {
+ { USB_DEVICE(MCBA_VENDOR_ID, MCBA_PRODUCT_ID) },
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, mcba_usb_table);
+
+static netdev_tx_t mcba_usb_xmit(struct mcba_priv *priv,
+ struct mcba_usb_msg *usb_msg,
+ struct sk_buff *skb);
+static void mcba_usb_xmit_cmd(struct mcba_priv *priv,
+ struct mcba_usb_msg *usb_msg);
+static void mcba_usb_xmit_read_fw_ver(struct mcba_priv *priv, u8 pic);
+static void mcba_usb_xmit_termination(struct mcba_priv *priv, u8 termination);
+static inline void mcba_init_ctx(struct mcba_priv *priv);
+
+static ssize_t termination_show(struct device *dev,
+ struct device_attribute *attr, char *buf)
+{
+ struct net_device *netdev = to_net_dev(dev);
+ struct mcba_priv *priv = netdev_priv(netdev);
+
+ return sprintf(buf, "%hhu\n", priv->termination_state);
+}
+
+static ssize_t termination_store(struct device *dev,
+ struct device_attribute *attr,
+ const char *buf, size_t count)
+{
+ struct net_device *netdev = to_net_dev(dev);
+ struct mcba_priv *priv = netdev_priv(netdev);
+ int tmp = -1;
+ int ret = -1;
+
+ ret = kstrtoint(buf, 10, &tmp);
+
+ if ((ret == 0) && ((tmp == 0) || (tmp == 1))) {
+ priv->termination_state = tmp;
+ mcba_usb_xmit_termination(priv, priv->termination_state);
+ }
+
+ return count;
+}
+
+static struct device_attribute termination_attr = {
+ .attr = {
+ .name = "termination",
+ .mode = 0666 },
+ .show = termination_show,
+ .store = termination_store
+};
+
+static void mcba_usb_process_can(struct mcba_priv *priv,
+ struct mcba_usb_msg_can *msg)
+{
+ struct can_frame *cf;
+ struct sk_buff *skb;
+ struct net_device_stats *stats = &priv->netdev->stats;
+
+ skb = alloc_can_skb(priv->netdev, &cf);
+ if (!skb)
+ return;
+
+ if (MCBA_RX_IS_EXID(msg))
+ cf->can_id = MCBA_CAN_GET_EID(msg);
+ else
+ cf->can_id = MCBA_CAN_GET_SID(msg);
+
+ if (MCBA_RX_IS_RTR(msg))
+ cf->can_id |= MCBA_CAN_RTR_MASK;
+
+ cf->can_dlc = msg->dlc & MCBA_DLC_MASK;
+
+ memcpy(cf->data, msg->data, cf->can_dlc);
+
+ stats->rx_packets++;
+ stats->rx_bytes += cf->can_dlc;
+ netif_rx(skb);
+}
+
+static void mcba_usb_process_ka_usb(struct mcba_priv *priv,
+ struct mcba_usb_msg_ka_usb *msg)
+{
+ if (unlikely(MCBA_IS_USB_DEBUG())) {
+ netdev_info(priv->netdev,
+ "USB_KA: termination %hhu, ver_maj %hhu, soft_min %hhu\n",
+ msg->termination_state, msg->soft_ver_major,
+ msg->soft_ver_minor);
+ }
+
+ if (unlikely(priv->usb_ka_first_pass)) {
+ netdev_info(priv->netdev,
+ "PIC USB version %hhu.%hhu\n",
+ msg->soft_ver_major, msg->soft_ver_minor);
+
+ priv->usb_ka_first_pass = false;
+ }
+
+ priv->termination_state = msg->termination_state;
+}
+
+static void mcba_usb_process_ka_can(struct mcba_priv *priv,
+ struct mcba_usb_msg_ka_can *msg)
+{
+ if (unlikely(MCBA_IS_CAN_DEBUG())) {
+ netdev_info(priv->netdev,
+ "CAN_KA: tx_err_cnt %hhu, rx_err_cnt %hhu, rx_buff_ovfl %hhu, tx_bus_off %hhu, can_bitrate %hu, rx_lost %hu, can_stat %hhu, soft_ver %hhu.%hhu, debug_mode %hhu, test_complete %hhu, test_result %hhu\n",
+ msg->tx_err_cnt, msg->rx_err_cnt, msg->rx_buff_ovfl,
+ msg->tx_bus_off,
+ ((msg->can_bitrate_hi << 8) + msg->can_bitrate_lo),
+ ((msg->rx_lost_hi >> 8) + msg->rx_lost_lo),
+ msg->can_stat, msg->soft_ver_major,
+ msg->soft_ver_minor,
+ msg->debug_mode, msg->test_complete,
+ msg->test_result);
+ }
+
+ if (unlikely(priv->can_ka_first_pass)) {
+ netdev_info(priv->netdev,
+ "PIC CAN version %hhu.%hhu\n",
+ msg->soft_ver_major, msg->soft_ver_minor);
+
+ priv->can_ka_first_pass = false;
+ }
+
+ priv->bec.txerr = msg->tx_err_cnt;
+ priv->bec.rxerr = msg->rx_err_cnt;
+}
+
+static void mcba_usb_process_rx(struct mcba_priv *priv,
+ struct mcba_usb_msg *msg)
+{
+ switch (msg->cmd_id) {
+ case MBCA_CMD_I_AM_ALIVE_FROM_CAN:
+ mcba_usb_process_ka_can(priv,
+ (struct mcba_usb_msg_ka_can *)msg);
+ break;
+
+ case MBCA_CMD_I_AM_ALIVE_FROM_USB:
+ mcba_usb_process_ka_usb(priv,
+ (struct mcba_usb_msg_ka_usb *)msg);
+ break;
+
+ case MBCA_CMD_RECEIVE_MESSAGE:
+ mcba_usb_process_can(priv, (struct mcba_usb_msg_can *)msg);
+ break;
+
+ case MBCA_CMD_NOTHING_TO_SEND:
+ /* Side effect of communication between PIC_USB and PIC_CAN.
+ * PIC_CAN is telling us that it has nothing to send
+ */
+ break;
+
+ case MBCA_CMD_TRANSMIT_MESSAGE_RSP:
+ /* Transmission response from the device containing timestamp */
+ break;
+
+ default:
+ netdev_warn(priv->netdev, "Unsupported msg (0x%hhX)",
+ msg->cmd_id);
+ break;
+ }
+}
+
+/* Callback for reading data from device
+ *
+ * Check urb status, call read function and resubmit urb read operation.
+ */
+static void mcba_usb_read_bulk_callback(struct urb *urb)
+{
+ struct mcba_priv *priv = urb->context;
+ struct net_device *netdev;
+ int retval;
+ int pos = 0;
+
+ netdev = priv->netdev;
+
+ if (!netif_device_present(netdev))
+ return;
+
+ switch (urb->status) {
+ case 0: /* success */
+ break;
+
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+
+ default:
+ netdev_info(netdev, "Rx URB aborted (%d)\n",
+ urb->status);
+
+ goto resubmit_urb;
+ }
+
+ while (pos < urb->actual_length) {
+ struct mcba_usb_msg *msg;
+
+ if (pos + sizeof(struct mcba_usb_msg) > urb->actual_length) {
+ netdev_err(priv->netdev, "format error\n");
+ break;
+ }
+
+ msg = (struct mcba_usb_msg *)(urb->transfer_buffer + pos);
+ mcba_usb_process_rx(priv, msg);
+
+ pos += sizeof(struct mcba_usb_msg);
+ }
+
+resubmit_urb:
+
+ usb_fill_bulk_urb(urb, priv->udev,
+ usb_rcvbulkpipe(priv->udev, MCBA_USB_EP_OUT),
+ urb->transfer_buffer, MCBA_USB_RX_BUFF_SIZE,
+ mcba_usb_read_bulk_callback, priv);
+
+ retval = usb_submit_urb(urb, GFP_ATOMIC);
+
+ if (retval == -ENODEV)
+ netif_device_detach(netdev);
+ else if (retval)
+ netdev_err(netdev, "failed resubmitting read bulk urb: %d\n",
+ retval);
+}
+
+/* Start USB device */
+static int mcba_usb_start(struct mcba_priv *priv)
+{
+ struct net_device *netdev = priv->netdev;
+ int err, i;
+
+ for (i = 0; i < MCBA_MAX_RX_URBS; i++) {
+ struct urb *urb = NULL;
+ u8 *buf;
+
+ /* create a URB, and a buffer for it */
+ urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!urb) {
+ netdev_err(netdev, "No memory left for URBs\n");
+ err = -ENOMEM;
+ break;
+ }
+
+ buf = usb_alloc_coherent(priv->udev, MCBA_USB_RX_BUFF_SIZE,
+ GFP_KERNEL,
+ &urb->transfer_dma);
+ if (!buf) {
+ netdev_err(netdev, "No memory left for USB buffer\n");
+ usb_free_urb(urb);
+ err = -ENOMEM;
+ break;
+ }
+
+ usb_fill_bulk_urb(urb, priv->udev,
+ usb_rcvbulkpipe(priv->udev,
+ MCBA_USB_EP_IN),
+ buf, MCBA_USB_RX_BUFF_SIZE,
+ mcba_usb_read_bulk_callback, priv);
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(urb, &priv->rx_submitted);
+
+ err = usb_submit_urb(urb, GFP_KERNEL);
+ if (err) {
+ usb_unanchor_urb(urb);
+ usb_free_coherent(priv->udev, MCBA_USB_RX_BUFF_SIZE,
+ buf, urb->transfer_dma);
+ usb_free_urb(urb);
+ break;
+ }
+
+ /* Drop reference, USB core will take care of freeing it */
+ usb_free_urb(urb);
+ }
+
+ /* Did we submit any URBs */
+ if (i == 0) {
+ netdev_warn(netdev, "couldn't setup read URBs\n");
+ return err;
+ }
+
+ /* Warn if we've couldn't transmit all the URBs */
+ if (i < MCBA_MAX_RX_URBS)
+ netdev_warn(netdev, "rx performance may be slow\n");
+
+ priv->can.state = CAN_STATE_ERROR_ACTIVE;
+
+ mcba_init_ctx(priv);
+ mcba_usb_xmit_read_fw_ver(priv, MCBA_VER_REQ_USB);
+ mcba_usb_xmit_read_fw_ver(priv, MCBA_VER_REQ_CAN);
+
+ return err;
+}
+
+static inline void mcba_init_ctx(struct mcba_priv *priv)
+{
+ int i = 0;
+
+ for (i = 0; i < MCBA_MAX_TX_URBS; i++)
+ priv->tx_context[i].ndx = MCBA_CTX_FREE;
+}
+
+static inline struct mcba_usb_ctx *mcba_usb_get_free_ctx(struct mcba_priv *priv)
+{
+ int i = 0;
+ struct mcba_usb_ctx *ctx = 0;
+
+ for (i = 0; i < MCBA_MAX_TX_URBS; i++) {
+ if (priv->tx_context[i].ndx == MCBA_CTX_FREE) {
+ ctx = &priv->tx_context[i];
+ ctx->ndx = i;
+ ctx->priv = priv;
+ break;
+ }
+ }
+
+ return ctx;
+}
+
+static inline void mcba_usb_free_ctx(struct mcba_usb_ctx *ctx)
+{
+ ctx->ndx = MCBA_CTX_FREE;
+ ctx->priv = 0;
+ ctx->dlc = 0;
+ ctx->can = false;
+}
+
+static void mcba_usb_write_bulk_callback(struct urb *urb)
+{
+ struct mcba_usb_ctx *ctx = urb->context;
+ struct net_device *netdev;
+
+ WARN_ON(!ctx);
+
+ netdev = ctx->priv->netdev;
+
+ if (ctx->can) {
+ if (!netif_device_present(netdev))
+ return;
+
+ netdev->stats.tx_packets++;
+ netdev->stats.tx_bytes += ctx->dlc;
+
+ can_get_echo_skb(netdev, ctx->ndx);
+
+ netif_wake_queue(netdev);
+ }
+
+ /* free up our allocated buffer */
+ usb_free_coherent(urb->dev, urb->transfer_buffer_length,
+ urb->transfer_buffer, urb->transfer_dma);
+
+ if (urb->status)
+ netdev_info(netdev, "Tx URB aborted (%d)\n",
+ urb->status);
+
+ /* Release context */
+ mcba_usb_free_ctx(ctx);
+}
+
+/* Send data to device */
+static netdev_tx_t mcba_usb_start_xmit(struct sk_buff *skb,
+ struct net_device *netdev)
+{
+ struct mcba_priv *priv = netdev_priv(netdev);
+ struct can_frame *cf = (struct can_frame *)skb->data;
+ struct mcba_usb_msg_can usb_msg;
+
+ usb_msg.cmd_id = MBCA_CMD_TRANSMIT_MESSAGE_EV;
+ memcpy(usb_msg.data, cf->data, sizeof(usb_msg.data));
+
+ if (MCBA_TX_IS_EXID(cf)) {
+ usb_msg.sidl = MCBA_SET_E_SIDL(cf->can_id);
+ usb_msg.sidh = MCBA_SET_E_SIDH(cf->can_id);
+ usb_msg.eidl = MCBA_SET_EIDL(cf->can_id);
+ usb_msg.eidh = MCBA_SET_EIDH(cf->can_id);
+ } else {
+ usb_msg.sidl = MCBA_SET_S_SIDL(cf->can_id);
+ usb_msg.sidh = MCBA_SET_S_SIDH(cf->can_id);
+ usb_msg.eidl = 0;
+ usb_msg.eidh = 0;
+ }
+
+ usb_msg.dlc = cf->can_dlc;
+
+ if (MCBA_TX_IS_RTR(cf))
+ usb_msg.dlc |= MCBA_DLC_RTR_MASK;
+
+ return mcba_usb_xmit(priv, (struct mcba_usb_msg *)&usb_msg, skb);
+}
+
+/* Send data to device */
+static void mcba_usb_xmit_cmd(struct mcba_priv *priv,
+ struct mcba_usb_msg *usb_msg)
+{
+ mcba_usb_xmit(priv, usb_msg, 0);
+}
+
+/* Send data to device */
+static netdev_tx_t mcba_usb_xmit(struct mcba_priv *priv,
+ struct mcba_usb_msg *usb_msg,
+ struct sk_buff *skb)
+{
+ struct net_device_stats *stats = &priv->netdev->stats;
+ struct mcba_usb_ctx *ctx = 0;
+ struct urb *urb;
+ u8 *buf;
+ int err;
+
+ ctx = mcba_usb_get_free_ctx(priv);
+ if (!ctx) {
+ /* Slow down tx path */
+ netif_stop_queue(priv->netdev);
+
+ return NETDEV_TX_BUSY;
+ }
+
+ if (skb) {
+ ctx->dlc = ((struct mcba_usb_msg_can *)usb_msg)->dlc
+ & MCBA_DLC_MASK;
+ can_put_echo_skb(skb, priv->netdev, ctx->ndx);
+ ctx->can = true;
+ } else {
+ ctx->can = false;
+ }
+
+ /* create a URB, and a buffer for it, and copy the data to the URB */
+ urb = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!urb) {
+ netdev_err(priv->netdev, "No memory left for URBs\n");
+ goto nomem;
+ }
+
+ buf = usb_alloc_coherent(priv->udev, MCBA_USB_TX_BUFF_SIZE, GFP_ATOMIC,
+ &urb->transfer_dma);
+ if (!buf) {
+ netdev_err(priv->netdev, "No memory left for USB buffer\n");
+ goto nomembuf;
+ }
+
+ memcpy(buf, usb_msg, MCBA_USB_TX_BUFF_SIZE);
+
+ usb_fill_bulk_urb(urb, priv->udev,
+ usb_sndbulkpipe(priv->udev, MCBA_USB_EP_OUT), buf,
+ MCBA_USB_TX_BUFF_SIZE, mcba_usb_write_bulk_callback,
+ ctx);
+
+ urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ usb_anchor_urb(urb, &priv->tx_submitted);
+
+ err = usb_submit_urb(urb, GFP_ATOMIC);
+ if (unlikely(err))
+ goto failed;
+
+ /* Release our reference to this URB, the USB core will eventually free
+ * it entirely.
+ */
+ usb_free_urb(urb);
+
+ return NETDEV_TX_OK;
+
+failed:
+ usb_unanchor_urb(urb);
+ usb_free_coherent(priv->udev, MCBA_USB_TX_BUFF_SIZE, buf,
+ urb->transfer_dma);
+
+ if (err == -ENODEV)
+ netif_device_detach(priv->netdev);
+ else
+ netdev_warn(priv->netdev, "failed tx_urb %d\n", err);
+
+nomembuf:
+ usb_free_urb(urb);
+
+nomem:
+ can_free_echo_skb(priv->netdev, ctx->ndx);
+ dev_kfree_skb(skb);
+ stats->tx_dropped++;
+
+ return NETDEV_TX_OK;
+}
+
+static void mcba_usb_xmit_change_bitrate(struct mcba_priv *priv, u16 bitrate)
+{
+ struct mcba_usb_msg_change_bitrate usb_msg;
+
+ usb_msg.cmd_id = MBCA_CMD_CHANGE_BIT_RATE;
+ usb_msg.bitrate_hi = (0xff00 & bitrate) >> 8;
+ usb_msg.bitrate_lo = (0xff & bitrate);
+
+ mcba_usb_xmit_cmd(priv, (struct mcba_usb_msg *)&usb_msg);
+}
+
+static void mcba_usb_xmit_read_fw_ver(struct mcba_priv *priv, u8 pic)
+{
+ struct mcba_usb_msg_fw_ver usb_msg;
+
+ usb_msg.cmd_id = MBCA_CMD_READ_FW_VERSION;
+ usb_msg.pic = pic;
+
+ mcba_usb_xmit_cmd(priv, (struct mcba_usb_msg *)&usb_msg);
+}
+
+static void mcba_usb_xmit_termination(struct mcba_priv *priv, u8 termination)
+{
+ struct mcba_usb_msg_terminaton usb_msg;
+
+ usb_msg.cmd_id = MBCA_CMD_SETUP_TERMINATION_RESISTANCE;
+ usb_msg.termination = termination;
+
+ mcba_usb_xmit_cmd(priv, (struct mcba_usb_msg *)&usb_msg);
+}
+
+/* Open USB device */
+static int mcba_usb_open(struct net_device *netdev)
+{
+ int err;
+
+ /* common open */
+ err = open_candev(netdev);
+ if (err)
+ return err;
+
+ can_led_event(netdev, CAN_LED_EVENT_OPEN);
+
+ netif_start_queue(netdev);
+
+ return 0;
+}
+
+static void mcba_urb_unlink(struct mcba_priv *priv)
+{
+ usb_kill_anchored_urbs(&priv->rx_submitted);
+ usb_kill_anchored_urbs(&priv->tx_submitted);
+}
+
+/* Close USB device */
+static int mcba_usb_close(struct net_device *netdev)
+{
+ struct mcba_priv *priv = netdev_priv(netdev);
+
+ priv->can.state = CAN_STATE_STOPPED;
+
+ netif_stop_queue(netdev);
+
+ /* Stop polling */
+ mcba_urb_unlink(priv);
+
+ close_candev(netdev);
+
+ can_led_event(netdev, CAN_LED_EVENT_STOP);
+
+ return 0;
+}
+
+/* Set network device mode
+ *
+ * Maybe we should leave this function empty, because the device
+ * set mode variable with open command.
+ */
+static int mcba_net_set_mode(struct net_device *netdev, enum can_mode mode)
+{
+ return 0;
+}
+
+static int mcba_net_get_berr_counter(const struct net_device *netdev,
+ struct can_berr_counter *bec)
+{
+ struct mcba_priv *priv = netdev_priv(netdev);
+
+ bec->txerr = priv->bec.txerr;
+ bec->rxerr = priv->bec.rxerr;
+
+ return 0;
+}
+
+static const struct net_device_ops mcba_netdev_ops = {
+ .ndo_open = mcba_usb_open,
+ .ndo_stop = mcba_usb_close,
+ .ndo_start_xmit = mcba_usb_start_xmit
+};
+
+/* Microchip CANBUS has hardcoded bittiming values by default.
+ * This function sends request via USB to change the speed and align bittiming
+ * values for presentation purposes only
+ */
+static int mcba_net_set_bittiming(struct net_device *netdev)
+{
+ u8 i;
+ struct mcba_priv *priv = netdev_priv(netdev);
+ struct can_bittiming *bt = &priv->can.bittiming;
+ const struct bitrate_settings *settings = 0;
+ const u8 setting_cnt = sizeof(br_settings) /
+ sizeof(struct bitrate_settings);
+
+ for (i = 0; i < setting_cnt; ++i)
+ if (br_settings[i].bt.bitrate == bt->bitrate)
+ settings = &br_settings[i];
+
+ if (settings) {
+ memcpy(bt, &settings->bt, sizeof(struct can_bittiming));
+
+ /* recalculate bitrate as it may be different than default */
+ bt->bitrate = 1000000000 / ((bt->sjw + bt->prop_seg +
+ bt->phase_seg1 + bt->phase_seg2) *
+ bt->tq);
+
+ mcba_usb_xmit_change_bitrate(priv, settings->kbps);
+ } else {
+ netdev_err(netdev, "Unsupported bittrate (%u). Use one of: 20000, 33333, 50000, 80000, 83333, 100000, 125000, 150000, 175000, 200000, 225000, 250000, 275000, 300000, 500000, 625000, 800000, 1000000\n",
+ bt->bitrate);
+
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int mcba_usb_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct net_device *netdev;
+ struct mcba_priv *priv;
+ int err = -ENOMEM;
+ struct usb_device *usbdev = interface_to_usbdev(intf);
+
+ dev_info(&intf->dev, "Microchip CAN BUS analizer connected\n");
+
+ netdev = alloc_candev(sizeof(struct mcba_priv), MCBA_MAX_TX_URBS);
+ if (!netdev) {
+ dev_err(&intf->dev, "Couldn't alloc candev\n");
+ return -ENOMEM;
+ }
+
+ priv = netdev_priv(netdev);
+
+ priv->udev = usbdev;
+ priv->netdev = netdev;
+ priv->usb_ka_first_pass = true;
+ priv->can_ka_first_pass = true;
+
+ init_usb_anchor(&priv->rx_submitted);
+ init_usb_anchor(&priv->tx_submitted);
+
+ usb_set_intfdata(intf, priv);
+
+ err = mcba_usb_start(priv);
+ if (err) {
+ if (err == -ENODEV)
+ netif_device_detach(priv->netdev);
+
+ netdev_warn(netdev, "couldn't start device: %d\n", err);
+
+ goto cleanup_candev;
+ }
+
+ /* Init CAN device */
+ priv->can.state = CAN_STATE_STOPPED;
+ priv->can.clock.freq = MCBA_CAN_CLOCK;
+ priv->can.bittiming_const = &mcba_bittiming_const;
+ priv->can.do_set_mode = mcba_net_set_mode;
+ priv->can.do_get_berr_counter = mcba_net_get_berr_counter;
+ priv->can.do_set_bittiming = mcba_net_set_bittiming;
+ priv->can.ctrlmode_supported = CAN_CTRLMODE_LOOPBACK |
+ CAN_CTRLMODE_LISTENONLY |
+ CAN_CTRLMODE_ONE_SHOT;
+
+ netdev->netdev_ops = &mcba_netdev_ops;
+
+ netdev->flags |= IFF_ECHO; /* we support local echo */
+
+ SET_NETDEV_DEV(netdev, &intf->dev);
+
+ err = register_candev(netdev);
+ if (err) {
+ netdev_err(netdev,
+ "couldn't register CAN device: %d\n", err);
+ goto cleanup_candev;
+ }
+
+ err = device_create_file(&netdev->dev, &termination_attr);
+ if (err)
+ goto cleanup_unregister_candev;
+
+ return err;
+
+cleanup_unregister_candev:
+ unregister_candev(netdev);
+
+cleanup_candev:
+ free_candev(netdev);
+
+ return err;
+}
+
+/* Called by the usb core when driver is unloaded or device is removed */
+static void mcba_usb_disconnect(struct usb_interface *intf)
+{
+ struct mcba_priv *priv = usb_get_intfdata(intf);
+
+ device_remove_file(&priv->netdev->dev, &termination_attr);
+
+ usb_set_intfdata(intf, NULL);
+
+ if (priv) {
+ netdev_info(priv->netdev, "device disconnected\n");
+
+ unregister_candev(priv->netdev);
+ free_candev(priv->netdev);
+
+ mcba_urb_unlink(priv);
+ }
+}
+
+static struct usb_driver mcba_usb_driver = {
+ .name = MCBA_MODULE_NAME,
+ .probe = mcba_usb_probe,
+ .disconnect = mcba_usb_disconnect,
+ .id_table = mcba_usb_table,
+};
+
+module_usb_driver(mcba_usb_driver);
+
+MODULE_AUTHOR("Remigiusz Kołłątaj <remigiusz.kollataj@mobica.com>");
+MODULE_DESCRIPTION("SocketCAN driver for Microchip CAN BUS Analyzer Tool");
+MODULE_LICENSE("GPL v2");
--
2.10.1
^ permalink raw reply related
* RE: Adding new CAN driver
From: Ramesh Shanmugasundaram @ 2016-11-04 11:06 UTC (permalink / raw)
To: Kurt Van Dijck, Oliver Hartkopp
Cc: Kołłątaj, Remigiusz, Alexander Stein,
Marc Kleine-Budde, Uwe Bonnes, linux-can@vger.kernel.org
In-Reply-To: <20161103212427.GA1677@airbook.vandijck-laurijssen.be>
> > On 11/02/2016 07:03 PM, Kołłątaj, Remigiusz wrote:
> > >On 2 November 2016 at 17:08, Alexander Stein
> > ><alexander.stein@systec-electronic.com> wrote:
> > >>On Wednesday 02 November 2016 15:49:50, Ramesh Shanmugasundaram wrote:
> >
> > >>>But this is physical layer information as Oliver mentioned. The CAN
> > >>>transceiver may even require some start-up state that may be
> > >>>enabled by setting couple of GPIOs (as on my board). Yes, it is
> > >>>part of the CAN interface configuration but it not part of the CAN
> > >>>controller driver. I think we could map it to Ethernet MAC & PHY case
> - isn't it?
> >
> > IIRC there's some mii-tool to configure, view & manipulate
> > media-independent interface status:
> >
> > http://man7.org/linux/man-pages/man8/mii-tool.8.html
> >
> > At least the ethernet people found a way to configure their
> > transceiver part with this tool.
:-)
> >
> > >>The transceiver might be managed by regulators as done by e.g.
> > >>flexcan. This is part of the hardware description, so device tree here
> is fine.
> > >>But in my opinion bus termination is an end user configuration which
> > >>might change rather often than not. It might be independent of the
> > >>controller driver as e.g. in flexcan, but it might be part of the
> > >>device as in USB hardware which requires some specific command to
> change bus termination.
> > >>IMHO it makes no sense to split an USB interface driver into two
> > >>parts using the same interface in the end.
> >
> > ack.
OK
> >
> > >I agree that termination is a physical layer setting but to be
> > >specific in case of Microchip's CAN BUS it is neither related to CAN
> > >controller nor transceiver.
> >
> > So what about creating TWO new netlink configuration options:
> >
> > diff --git a/include/uapi/linux/can/netlink.h
> > b/include/uapi/linux/can/netlink.h
> > index 94ffe0c..8d7c4b9 100644
> > --- a/include/uapi/linux/can/netlink.h
> > +++ b/include/uapi/linux/can/netlink.h
> > @@ -127,6 +127,8 @@ enum {
> > IFLA_CAN_BERR_COUNTER,
> > IFLA_CAN_DATA_BITTIMING,
> > IFLA_CAN_DATA_BITTIMING_CONST,
> > + IFLA_CAN_TRX_CTRL,
Not sure about this.
> > + IFLA_CAN_TERMINATION,
ACK
> > __IFLA_CAN_MAX
> > };
> >
> > Where IFLA_CAN_TRX_CTRL provides an interface to configure the
> > transceiver and IFLA_CAN_TERMINATION to configure the termination.
>
> termination, like bittiming, depends on the physical layer.
It is. However, bittiming is configured "in" controller registers and I don't know if we can say the same for termination. However, it seems like USB drivers (may be with user space app) provide this info as a feature to the user. Wonder how it is done in PCI based CAN cards?
> Hard to say if it's a user option of a system requirement, it is similar
> and should be configurable from userspace (root probably).
>
> >
> > But for IFLA_CAN_TERMINATION we need some possibility to configure
> > either a set of supported termination resistors (e.g. disabled, 60
> > Ohms, 120 Ohms, xxx Ohms, ...) or a free termination value (e.g. 1 Ohm
> > - 10 kOhms) following the hardware capabilities of the CAN device.
> > Therefore a list of values and ranges has to be made available by the
> > netlink interface before userspace can select some of them.
>
> Instead of trying to foresee the future and allowing any resistor value,
> I'd propose to stick to common physical layers. I wasn't aware of any
> physical that has a 10KOhm terminting resistor, nor did I see any TRX
> supporting it. So an ISO 11898 bus termination should not allow _any_
> resistor value?
> Maybe next year a brand new physical layer appears, then we'll add support
> for that layer? And maybe that layer may support random termintion
> resistors (really?), we'll see then.
>
> for now, IFLA_CAN_TERMINATION may be a boolean (or enumeration).
ACK. We could start simple with a bool.
>
> Kind regards,
> Kurt
>
> >
> > Both IFLA_CAN_TRX_CTRL and IFLA_CAN_TERMINATION would only be
> > supported if the CAN device can handle them.
ACK
Probably a device tree
> > decription defines a fixed configuration which can be read but not
> modified.
May be we don't need to report/fill these details if the CAN controller does not manage them?
>
> For IFLA_CAN_TERMINATION, I don't see added value putting constants in
> device tree, since device tree describes the board and termination depends
> on the bus beyond the board. So you can't describe in devicetree that you
> always want the termination activated in the controller.
If the board supports on-board termination and if it is modifiable (on/off - e.g. with GPIO/regulator) for whatever reason, I think it is OK to define the initial state in dev tree. Netlink could report this and modify if it is allowed.
>
> Besides that remark on the constant, I agree with you, although I'm not
> sure what function would be possible with IFLA_CAN_TRX_CTRL?
> Wakeup-gpio? maximum-bitrate (controlled by a 0-100KOhm resistor on
> popular phy's?, ...).
ACK. I think TRX_CTRL could be anything and I wonder if we need to expose this under netdev? It could be as simple as wakeup-gpio to complex policies. As you mentioned there could be a mini-can controller behind the transceiver running own firmware with some default config. So not sure about this option.
Thanks,
Ramesh
^ permalink raw reply
* Problems PEAK CAN SJA1000 CAN interface
From: Rein Appeldoorn @ 2016-11-07 14:15 UTC (permalink / raw)
To: linux-can
Hi all,
We have two of these a linux machine:
http://www.peak-system.com/PCAN-miniPCIe.285.0.html?&L=1
According to http://elinux.org/CAN_Bus , the cards should be
supported. They are getting discovered by the kernel and listed in
ifconfig
$ ifconfig can0
can0 Link encap:UNSPEC HWaddr
00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
UP RUNNING NOARP MTU:16 Metric:1
RX packets:17386379 errors:0 dropped:3 overruns:0 frame:0
TX packets:0 errors:17386373 dropped:3 overruns:0 carrier:3
collisions:0 txqueuelen:10
RX bytes:139091032 (139.0 MB) TX bytes:0 (0.0 B)
Interrupt:16
And it is possible to bring the interface up:
$ ip link set can0 type can bitrate 500000 $ ifconfig can0 up
However, candump and cansend do not seem to work. Another thing I
noticed is that I have a lot of TX errors.
Somebody any ideas? Any help is appreciated!
Thanks,
-Rein
--------------
Some more information:
$ cat /proc/net/can/version
rev 20120528 abi 9
$ lsmod:
slcan 16384 1
can_raw 20480 1
can 45056 1 can_raw
can_dev 24576 1 sja1000
peak_pci 16384 0
sja1000 16384 1 peak_pci
i2c_algo_bit 16384 3 igb,i915,peak_pci
^ permalink raw reply
* Re: Problems PEAK CAN SJA1000 CAN interface
From: Mirza Krak @ 2016-11-07 14:30 UTC (permalink / raw)
To: Rein Appeldoorn; +Cc: linux-can@vger.kernel.org
In-Reply-To: <CAPO0vctcyJMMVJ7BvhGYum+BzbhJ4vK+LM2fPPbVC_S-o=L9Ag@mail.gmail.com>
2016-11-07 15:15 GMT+01:00 Rein Appeldoorn <reinappeldoorn@gmail.com>:
> Hi all,
>
> We have two of these a linux machine:
>
> http://www.peak-system.com/PCAN-miniPCIe.285.0.html?&L=1
>
> According to http://elinux.org/CAN_Bus , the cards should be
> supported. They are getting discovered by the kernel and listed in
> ifconfig
>
> $ ifconfig can0
>
> can0 Link encap:UNSPEC HWaddr
> 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
>
> UP RUNNING NOARP MTU:16 Metric:1
>
> RX packets:17386379 errors:0 dropped:3 overruns:0 frame:0
>
> TX packets:0 errors:17386373 dropped:3 overruns:0 carrier:3
>
> collisions:0 txqueuelen:10
>
> RX bytes:139091032 (139.0 MB) TX bytes:0 (0.0 B)
>
> Interrupt:16
>
> And it is possible to bring the interface up:
>
> $ ip link set can0 type can bitrate 500000 $ ifconfig can0 up
>
> However, candump and cansend do not seem to work. Another thing I
> noticed is that I have a lot of TX errors.
>
> Somebody any ideas? Any help is appreciated!
The output from "ip -d -s link show can0" would be interesting.
What is your physical network setup? How are the CAN busses connected?
My initial though is that you are missing CAN network termination (see
[1]) or do not have a node that ACKs on the bus.
[1]. http://www.ni.com/white-paper/9759/en/
Best Regards
Mirza
^ permalink raw reply
* Re: Problems PEAK CAN SJA1000 CAN interface
From: Wolfgang Grandegger @ 2016-11-07 14:25 UTC (permalink / raw)
To: Rein Appeldoorn, linux-can
In-Reply-To: <CAPO0vctcyJMMVJ7BvhGYum+BzbhJ4vK+LM2fPPbVC_S-o=L9Ag@mail.gmail.com>
Hello,
Am 07.11.2016 um 15:15 schrieb Rein Appeldoorn:
> Hi all,
>
> We have two of these a linux machine:
>
> http://www.peak-system.com/PCAN-miniPCIe.285.0.html?&L=1
>
> According to http://elinux.org/CAN_Bus , the cards should be
> supported. They are getting discovered by the kernel and listed in
> ifconfig
>
> $ ifconfig can0
>
> can0 Link encap:UNSPEC HWaddr
> 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
>
> UP RUNNING NOARP MTU:16 Metric:1
>
> RX packets:17386379 errors:0 dropped:3 overruns:0 frame:0
>
> TX packets:0 errors:17386373 dropped:3 overruns:0 carrier:3
>
> collisions:0 txqueuelen:10
>
> RX bytes:139091032 (139.0 MB) TX bytes:0 (0.0 B)
>
> Interrupt:16
>
> And it is possible to bring the interface up:
>
> $ ip link set can0 type can bitrate 500000 $ ifconfig can0 up
>
> However, candump and cansend do not seem to work. Another thing I
> noticed is that I have a lot of TX errors.
>
> Somebody any ideas? Any help is appreciated!
What does "ip -d -s link show can0" report?
Wolfgang.
^ permalink raw reply
* Re: Problems PEAK CAN SJA1000 CAN interface
From: Mirza Krak @ 2016-11-07 15:06 UTC (permalink / raw)
To: Rein Appeldoorn; +Cc: linux-can@vger.kernel.org
In-Reply-To: <CAPO0vcuV1eVSsPfWxsgXKT36D0ZswR=wBL6mhyE+uF4T7T_smQ@mail.gmail.com>
2016-11-07 15:40 GMT+01:00 Rein Appeldoorn <reinappeldoorn@gmail.com>:
> Hi Mirza, Wolfgang,
>
> Thanks for your quick replies. This is the output of the command:
>
> $ip -d -s link show can0
>
> link/can promiscuity 0
>
> can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
>
> bitrate 500000 sample-point 0.875
>
> tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
>
> sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
>
> clock 8000000
>
> re-started bus-errors arbit-lost error-warn error-pass bus-off
>
> 0 0 0 0 0
> 0
>
> RX: bytes packets errors dropped overrun mcast
>
> 0 0 0 0 0 0
>
> TX: bytes packets errors dropped carrier collsns
>
> 0 0 0 0 0 0
> -Rein
>
Above only shows that you the device is configured and that there has
not been any network activity.
If you are attempting to send data that please run a "cansend" or
similar and then "ip -d -s link show can0".
Best Regards
Mirza
^ permalink raw reply
* Re: Problems PEAK CAN SJA1000 CAN interface
From: Rein Appeldoorn @ 2016-11-07 14:40 UTC (permalink / raw)
To: Mirza Krak; +Cc: linux-can@vger.kernel.org
In-Reply-To: <CALw8SCU6ZRKAbtyfnJ_SELyRnewfUWy0bYamFn-hn_xuYZ8U6w@mail.gmail.com>
Hi Mirza, Wolfgang,
Thanks for your quick replies. This is the output of the command:
$ip -d -s link show can0
link/can promiscuity 0
can state ERROR-ACTIVE (berr-counter tx 0 rx 0) restart-ms 0
bitrate 500000 sample-point 0.875
tq 125 prop-seg 6 phase-seg1 7 phase-seg2 2 sjw 1
sja1000: tseg1 1..16 tseg2 1..8 sjw 1..4 brp 1..64 brp-inc 1
clock 8000000
re-started bus-errors arbit-lost error-warn error-pass bus-off
0 0 0 0 0
0
RX: bytes packets errors dropped overrun mcast
0 0 0 0 0 0
TX: bytes packets errors dropped carrier collsns
0 0 0 0 0 0
-Rein
On Mon, Nov 7, 2016 at 3:30 PM, Mirza Krak <mirza.krak@gmail.com> wrote:
> 2016-11-07 15:15 GMT+01:00 Rein Appeldoorn <reinappeldoorn@gmail.com>:
>> Hi all,
>>
>> We have two of these a linux machine:
>>
>> http://www.peak-system.com/PCAN-miniPCIe.285.0.html?&L=1
>>
>> According to http://elinux.org/CAN_Bus , the cards should be
>> supported. They are getting discovered by the kernel and listed in
>> ifconfig
>>
>> $ ifconfig can0
>>
>> can0 Link encap:UNSPEC HWaddr
>> 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
>>
>> UP RUNNING NOARP MTU:16 Metric:1
>>
>> RX packets:17386379 errors:0 dropped:3 overruns:0 frame:0
>>
>> TX packets:0 errors:17386373 dropped:3 overruns:0 carrier:3
>>
>> collisions:0 txqueuelen:10
>>
>> RX bytes:139091032 (139.0 MB) TX bytes:0 (0.0 B)
>>
>> Interrupt:16
>>
>> And it is possible to bring the interface up:
>>
>> $ ip link set can0 type can bitrate 500000 $ ifconfig can0 up
>>
>> However, candump and cansend do not seem to work. Another thing I
>> noticed is that I have a lot of TX errors.
>>
>> Somebody any ideas? Any help is appreciated!
>
> The output from "ip -d -s link show can0" would be interesting.
>
> What is your physical network setup? How are the CAN busses connected?
>
> My initial though is that you are missing CAN network termination (see
> [1]) or do not have a node that ACKs on the bus.
>
> [1]. http://www.ni.com/white-paper/9759/en/
>
> Best Regards
> Mirza
^ permalink raw reply
* Re: Adding new CAN driver
From: Oliver Hartkopp @ 2016-11-07 21:24 UTC (permalink / raw)
To: Ramesh Shanmugasundaram, Kurt Van Dijck
Cc: Kołłątaj, Remigiusz, Alexander Stein,
Marc Kleine-Budde, Uwe Bonnes, linux-can@vger.kernel.org
In-Reply-To: <SG2PR06MB10381FBE7242FA602F1AC319C3A20@SG2PR06MB1038.apcprd06.prod.outlook.com>
On 11/04/2016 12:06 PM, Ramesh Shanmugasundaram wrote:
>> for now, IFLA_CAN_TERMINATION may be a boolean (or enumeration).
>
> ACK. We could start simple with a bool.
I would suggest to support a variable resistor (varistor) ranging from 1
to 65534 Ohms and a list of discrete termination values as suggested.
diff --git a/include/uapi/linux/can/netlink.h
b/include/uapi/linux/can/netlink.h
index 94ffe0c..a07601a 100644
--- a/include/uapi/linux/can/netlink.h
+++ b/include/uapi/linux/can/netlink.h
@@ -91,6 +91,32 @@ struct can_ctrlmode {
__u32 flags;
};
+/*
+ * CAN hardware-dependent termination resistor constants
+ *
+ * Capabilities shown by ip tool if supported by CAN hardware
+ * Unsupported values are filled with zero (CAN_RESISTOR_INVALID)
+ */
+struct can_termination_const {
+
+ /* range for programmable resistor (if supported) */
+ __u16 range_low; /* lowermost resistor value (Ohm) */
+ __u16 range_high; /* highest resistor value (Ohm) */
+
+ /* array of supported discrete resistor values (Ohm) */
+ __u16 term[8];
+};
+
+/*
+ * CAN termination
+ */
+struct can_termination {
+ __u16 term;
+};
+
+#define CAN_RESISTOR_INVALID 0x0000U /* indicates no value / unsupported */
+#define CAN_RESISTOR_DISABLED 0xFFFFU /* indicates disabled termination */
+
#define CAN_CTRLMODE_LOOPBACK 0x01 /* Loopback mode */
#define CAN_CTRLMODE_LISTENONLY 0x02 /* Listen-only mode */
#define CAN_CTRLMODE_3_SAMPLES 0x04 /* Triple sampling mode */
@@ -127,6 +153,8 @@ enum {
IFLA_CAN_BERR_COUNTER,
IFLA_CAN_DATA_BITTIMING,
IFLA_CAN_DATA_BITTIMING_CONST,
+ IFLA_CAN_TERMINATION,
+ IFLA_CAN_TERMINATION_CONST,
__IFLA_CAN_MAX
};
With this interface the ip tool can get the capabilities of the
termination analogue to the BITTIMING_CONST values.
And it can set the termination with IFLA_CAN_TERMINATION.
The CAN driver would provide a struct can_termination_const - in the
case the CAN interface supports termination control.
E.g. the mcba_usb driver would provide this:
static struct can_termination_const = {
.range_low = CAN_RESISTOR_INVALID;
.range_high = CAN_RESISTOR_INVALID;
.term = { 120, CAN_RESISTOR_DISABLED, CAN_RESISTOR_INVALID };
}
Another driver supporting 60 and 120 Ohms but no possibility to disable
the termination:
static struct can_termination_const = {
.range_low = CAN_RESISTOR_INVALID;
.range_high = CAN_RESISTOR_INVALID;
.term = { 60, 120, CAN_RESISTOR_INVALID };
}
Another driver supporting 60 to 5600 Ohms varistor and the possibility
to disable the termination:
static struct can_termination_const = {
.range_low = 60;
.range_high = 5600;
.term = { CAN_RESISTOR_DISABLED, CAN_RESISTOR_INVALID };
}
These termination capabilities might be provided by device tree
configuration too - although I don't know how this would be done.
What do you think about this kind of configuration interface?
Regards,
Oliver
^ permalink raw reply related
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox