Discussion:
USB to SPI driver for MCP2210
Daniel Santos
2013-04-08 20:59:00 UTC
Permalink
Hello!

My bother & I are working on a project where we're planning on using
these inexpensive Microchip MCP2210 USB to SPI bridge w/ GPIO devices.
Mathew King at Trilithic started a driver and kindly released it on
github (https://github.com/MathewKing/mcp2210-linux), but he wont be
using the chip or developing the driver further, so I'm picking it up
(and with his blessings even! :) However, rather than a driver written
specifically for our product, I would like a generic or abstract MCP2210
driver that can be re-used by others. So how do I go about this?

I'm still pretty new to Linux device drivers & the device driver model,
so there may be existing abstractions & libraries that I'm just not yet
aware of. We're not planning on changing the USB vendor/product ID (as
I'm sure many users of this chip will opt) and each or our devices can
have different hardware & wirings attached to the MCP2210. Since SPI
devices cannot be auto-configured, we plan to probe as follows:

* In the USB probe, examine the iProduct string to match our specific
product (maybe iManufacturer as well) and if it matches, to bind to the
device.
* The MCP2210 has 9 GP pins that can each be used as either an SPI chip
select, GPIO or a "dedicated function" (power LED, interrupt input line,
etc.). Once bound, we can examine the "power-up chip settings" (section
3.1.7 in the datasheet --
http://ww1.microchip.com/downloads/en/DeviceDoc/22288A.pdf) and treat
that as the specification as to how each GP pin is used in this device.
* Finally, retrieve the (previously stored) data from the 256 bytes of
user non-volatile EEPROM. On this, we plan to store the device
information that each of the GP pins configured for SPI CS lines are
connected as well as the use for any GPIO lines. (Pins configured for
"dedicated function" need no other information.)

I'm not yet settled on the exact mechanism, format, etc. for this
"device information" on the EEPROM, but between this and what the driver
knows it must specify unambiguously what devices are connected to what
CS pins, how to talk to them (timings, etc.). So once we know what
we're connected to and how to talk to it, we can do our SPI probe.

While I anticipate this to work great for my stuff, it would be absurd
to impose this schema on somebody else using this chip (with the
original vendor/product id or not). Thus, I'm not sure how to go about
coding the MCP2210 driver as an abstract interface to take care of the
details of this device, accepting an external configuration during the
USB probe and exposing what is actually needed to other drivers (or
*cringe* userspace), rending the code both attractive and reusable.
Here are the things I've thought of:

1. Discover that the kernel already contains an abstraction layer for an
x to SPI bridge device and that I just need to write an MCP2210 driver
for it!
2. Create my own abstract x to SPI bridge API (or "KPI") and then
implement my MCP2210 driver as a provider for said API -- not a very
attractive option for my expertise level! Not that I can't do it, I
just question how attractive it will be for to others to use. :)
3. Write the MCP2210 driver code as a generic C library used to *create*
other drivers, but not create a specific MCP2210 driver, and then
implement my driver using the generic MCP2210 driver library.

Obviously, by far, option 1 would be the best! Also, I'm intentionally
ignoring userspace options via generic-hid (there is already a
user-space library for using this chip --
https://github.com/kerrydwong/MCP2210-Library). If somebody strongly
feels that there's merit to doing this from userspace, please speak up. :)

Other options, opinions and/or advice would be greatly appreciated!

Thanks,
Daniel Santos
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Greg KH
2013-04-09 05:15:11 UTC
Permalink
Post by Daniel Santos
1. Discover that the kernel already contains an abstraction layer
for an x to SPI bridge device and that I just need to write an
MCP2210 driver for it!
We have lots of SPI drivers in the kernel already, but no USB ones that
I know of. It shouldn't be hard to create a driver for this that lives
under drivers/spi/ and follows the api that it needs there.

You might want to ask the Linux SPI developers about this if you have
more information, they can help you better then we can.

good luck,

greg k-h
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Daniel Santos
2013-04-09 18:24:55 UTC
Permalink
Post by Greg KH
Post by Daniel Santos
1. Discover that the kernel already contains an abstraction layer
for an x to SPI bridge device and that I just need to write an
MCP2210 driver for it!
We have lots of SPI drivers in the kernel already, but no USB ones that
I know of. It shouldn't be hard to create a driver for this that lives
under drivers/spi/ and follows the api that it needs there.
You might want to ask the Linux SPI developers about this if you have
more information, they can help you better then we can.
Ahh, thanks. Is there a linux-spi mailing list somewhere? I didn't find
one on vger.kernel.org.

Thanks!
Daniel

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Greg KH
2013-04-09 18:52:19 UTC
Permalink
Post by Daniel Santos
Post by Greg KH
Post by Daniel Santos
1. Discover that the kernel already contains an abstraction layer
for an x to SPI bridge device and that I just need to write an
MCP2210 driver for it!
We have lots of SPI drivers in the kernel already, but no USB ones that
I know of. It shouldn't be hard to create a driver for this that lives
under drivers/spi/ and follows the api that it needs there.
You might want to ask the Linux SPI developers about this if you have
more information, they can help you better then we can.
Ahh, thanks. Is there a linux-spi mailing list somewhere? I didn't
find one on vger.kernel.org.
Look in the MAINTAINERS file (hint, it's at
spi-devel-general-5NWGOfrQmneRv+***@public.gmane.org)

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Felipe Balbi
2013-04-09 17:07:52 UTC
Permalink
Hi,
Post by Daniel Santos
My bother & I are working on a project where we're planning on using
these inexpensive Microchip MCP2210 USB to SPI bridge w/ GPIO
devices. Mathew King at Trilithic started a driver and kindly
released it on github (https://github.com/MathewKing/mcp2210-linux),
but he wont be using the chip or developing the driver further, so
I'm picking it up (and with his blessings even! :) However, rather
than a driver written specifically for our product, I would like a
generic or abstract MCP2210 driver that can be re-used by others. So
how do I go about this?
I'm not sure you can. There is no standardization wrt USB to SPI
bridges, so your device implements a proprietary protocol (even if
simple).
Post by Daniel Santos
I'm still pretty new to Linux device drivers & the device driver
model, so there may be existing abstractions & libraries that I'm
just not yet aware of. We're not planning on changing the USB
vendor/product ID (as I'm sure many users of this chip will opt) and
each or our devices can have different hardware & wirings attached to
the MCP2210. Since SPI devices cannot be auto-configured, we plan to
this might cause problems. If everybody has the same idVendor/idProduct
pair but functionality is different... ugh
Post by Daniel Santos
* In the USB probe, examine the iProduct string to match our specific
product (maybe iManufacturer as well) and if it matches, to bind to
the device.
no, you want to match idVendor and idProduct. No need to match strings.
Post by Daniel Santos
* The MCP2210 has 9 GP pins that can each be used as either an SPI
chip select, GPIO or a "dedicated function" (power LED, interrupt
input line, etc.). Once bound, we can examine the "power-up chip
settings" (section 3.1.7 in the datasheet --
http://ww1.microchip.com/downloads/en/DeviceDoc/22288A.pdf) and treat
that as the specification as to how each GP pin is used in this device.
oh, so this is actually a multifunction device. What you might be
looking for is a core driver which registers itself with the MFD layer
(drivers/mfd) and exposes clients based on some parameters passed to it
through e.g. pinctrl framework.

You can have at least three children:

. an SPI bus
. a GPIO/IRQ chip
. LED

Your core driver would instantiate each of those children devices based
on what's the requested state of the pin.
Post by Daniel Santos
* Finally, retrieve the (previously stored) data from the 256 bytes
of user non-volatile EEPROM. On this, we plan to store the device
information that each of the GP pins configured for SPI CS lines are
connected as well as the use for any GPIO lines. (Pins configured
for "dedicated function" need no other information.)
is this mandatory, or something you decided to do ? If it's mandatory to
program pin assignment like that, then you can very easily figure out
how to use that information to instantiate proper children during your
core driver's probe routine.

If it's not mandatory, then it gets tricky to support multiple users.
Can users write whatever they want to EEPROM or is there a specified
format ?

In any case, there are ways to make it work, just some are easier to
code then the others ;-)
--
balbi
Daniel Santos
2013-04-09 19:00:46 UTC
Permalink
Post by Felipe Balbi
Hi,
Post by Daniel Santos
My bother & I are working on a project where we're planning on using
these inexpensive Microchip MCP2210 USB to SPI bridge w/ GPIO
devices. Mathew King at Trilithic started a driver and kindly
released it on github (https://github.com/MathewKing/mcp2210-linux),
but he wont be using the chip or developing the driver further, so
I'm picking it up (and with his blessings even! :) However, rather
than a driver written specifically for our product, I would like a
generic or abstract MCP2210 driver that can be re-used by others. So
how do I go about this?
I'm not sure you can. There is no standardization wrt USB to SPI
bridges, so your device implements a proprietary protocol (even if
simple).
Post by Daniel Santos
I'm still pretty new to Linux device drivers & the device driver
model, so there may be existing abstractions & libraries that I'm
just not yet aware of. We're not planning on changing the USB
vendor/product ID (as I'm sure many users of this chip will opt) and
each or our devices can have different hardware & wirings attached to
the MCP2210. Since SPI devices cannot be auto-configured, we plan to
this might cause problems. If everybody has the same idVendor/idProduct
pair but functionality is different... ugh
Well, we don't have the $3500 for a vendor id. :( I presume that others
may do the same thing, hopefully mostly with DIY-type of projects.
Post by Felipe Balbi
Post by Daniel Santos
* In the USB probe, examine the iProduct string to match our specific
product (maybe iManufacturer as well) and if it matches, to bind to
the device.
no, you want to match idVendor and idProduct. No need to match strings.
Post by Daniel Santos
* The MCP2210 has 9 GP pins that can each be used as either an SPI
chip select, GPIO or a "dedicated function" (power LED, interrupt
input line, etc.). Once bound, we can examine the "power-up chip
settings" (section 3.1.7 in the datasheet --
http://ww1.microchip.com/downloads/en/DeviceDoc/22288A.pdf) and treat
that as the specification as to how each GP pin is used in this device.
oh, so this is actually a multifunction device. What you might be
looking for is a core driver which registers itself with the MFD layer
(drivers/mfd) and exposes clients based on some parameters passed to it
through e.g. pinctrl framework.
w00t! Thanks! I think this is the "device class" (not sure if that's
the correct term) I'm looking for. Yes, I suppose this is a
"multi-function device", since it exposes both an SPI master with a few
chip selects as well as GPIO and some other random functionality.
Post by Felipe Balbi
. an SPI bus
. a GPIO/IRQ chip
. LED
Your core driver would instantiate each of those children devices based
on what's the requested state of the pin.
Post by Daniel Santos
* Finally, retrieve the (previously stored) data from the 256 bytes
of user non-volatile EEPROM. On this, we plan to store the device
information that each of the GP pins configured for SPI CS lines are
connected as well as the use for any GPIO lines. (Pins configured
for "dedicated function" need no other information.)
is this mandatory, or something you decided to do ? If it's mandatory to
program pin assignment like that, then you can very easily figure out
how to use that information to instantiate proper children during your
core driver's probe routine.
Well, I guess I need to be more clear about this. I'm talking about 3
separate entities really:

1. the MCP2210 chip its self,
2. the hardware device that I'm creating that makes use of this chip and
3. any hardware devices that others may create with it.

So one idea of how to do this is to have generic MCP2210 driver that
does pretty much nothing by its self (not 100% sure how this should
work). Then, I would have a driver for my device, that would use the
generic MCP2210 driver to manage all of the communication with the
MCP2210 and I would simply feed it my hardware configuration (wiring,
SPI timings, etc.), causing it to expose SPI devices, GPIO lines, LEDs,
etc. as you described. Then, a 3rd party could do the same (hopefully,
they will modify the idVendor & idProduct though. :) I suppose there's
room for an MCP2210 userspace driver that utilizes the generic one to
interface with the chip and just provides an interface to userspace, but
I'm not personally interested in such a thing myself.

So I'm thinking that with my own driver, I would look for the idVendor
and idProduct of the unmodified MCP2210 (because I'm a poor bastard) and
then -ENODEV unless the product & mfg strings also match. Then, I can
read the EEPROM to cook up my config. (One complexity is that our
device can have various features & hardware present or not, so that's
another reason for us to stick the hardware setup in the EEPROM.)

Does that make sense? Also, the "generic driver" then becomes more of a
library than an actual driver, huh?
I presume
Post by Felipe Balbi
If it's not mandatory, then it gets tricky to support multiple users.
Can users write whatever they want to EEPROM or is there a specified
format ?
The MCP2210 allows you to write-protect the persistent settings
(including the EEPROM contents) with a password or just permanently lock
them. You have to issue USB commands to alter the EEPROM and I don't
plan on exposing that to userspace from the driver for my product. So
if anybody changes them, its their own damn fault. :)
Post by Felipe Balbi
In any case, there are ways to make it work, just some are easier to
code then the others ;-)
Well this helps a great deal, thank you! I want to try to keep this
simple, but I also would like it to be re-usable. There are currently
USB to serial, 1-wire and I think i2c in the kernel already and I would
expect this class of device will become more prevalent in the future.

Daniel

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Robert Schwebel
2013-04-09 19:06:06 UTC
Permalink
Post by Daniel Santos
Well, we don't have the $3500 for a vendor id. :( I presume that
others may do the same thing, hopefully mostly with DIY-type of
projects.
Do you know this one:
http://wiki.openmoko.org/wiki/USB_Product_IDs#USB_Vendor_and_Product_IDs

rsc
--
Pengutronix e.K. | |
Industrial Linux Solutions | http://www.pengutronix.de/ |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 |
Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-5555 |
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Daniel Santos
2013-04-09 21:57:32 UTC
Permalink
Post by Robert Schwebel
Post by Daniel Santos
Well, we don't have the $3500 for a vendor id. :( I presume that
others may do the same thing, hopefully mostly with DIY-type of
projects.
http://wiki.openmoko.org/wiki/USB_Product_IDs#USB_Vendor_and_Product_IDs
rsc
ooooooh, shiny! Thanks Robert!

Daniel
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-***@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Felipe Balbi
2013-04-10 08:46:33 UTC
Permalink
Hi,
Post by Daniel Santos
Post by Felipe Balbi
Post by Daniel Santos
My bother & I are working on a project where we're planning on using
these inexpensive Microchip MCP2210 USB to SPI bridge w/ GPIO
devices. Mathew King at Trilithic started a driver and kindly
released it on github (https://github.com/MathewKing/mcp2210-linux),
but he wont be using the chip or developing the driver further, so
I'm picking it up (and with his blessings even! :) However, rather
than a driver written specifically for our product, I would like a
generic or abstract MCP2210 driver that can be re-used by others. So
how do I go about this?
I'm not sure you can. There is no standardization wrt USB to SPI
bridges, so your device implements a proprietary protocol (even if
simple).
Post by Daniel Santos
I'm still pretty new to Linux device drivers & the device driver
model, so there may be existing abstractions & libraries that I'm
just not yet aware of. We're not planning on changing the USB
vendor/product ID (as I'm sure many users of this chip will opt) and
each or our devices can have different hardware & wirings attached to
the MCP2210. Since SPI devices cannot be auto-configured, we plan to
this might cause problems. If everybody has the same idVendor/idProduct
pair but functionality is different... ugh
Well, we don't have the $3500 for a vendor id. :( I presume that
others may do the same thing, hopefully mostly with DIY-type of
projects.
heh :-)
Post by Daniel Santos
Post by Felipe Balbi
Your core driver would instantiate each of those children devices based
on what's the requested state of the pin.
Post by Daniel Santos
* Finally, retrieve the (previously stored) data from the 256 bytes
of user non-volatile EEPROM. On this, we plan to store the device
information that each of the GP pins configured for SPI CS lines are
connected as well as the use for any GPIO lines. (Pins configured
for "dedicated function" need no other information.)
is this mandatory, or something you decided to do ? If it's mandatory to
program pin assignment like that, then you can very easily figure out
how to use that information to instantiate proper children during your
core driver's probe routine.
Well, I guess I need to be more clear about this. I'm talking about
1. the MCP2210 chip its self,
2. the hardware device that I'm creating that makes use of this chip and
3. any hardware devices that others may create with it.
So one idea of how to do this is to have generic MCP2210 driver that
does pretty much nothing by its self (not 100% sure how this should
work). Then, I would have a driver for my device, that would use the
generic MCP2210 driver to manage all of the communication with the
MCP2210 and I would simply feed it my hardware configuration (wiring,
SPI timings, etc.), causing it to expose SPI devices, GPIO lines,
LEDs, etc. as you described. Then, a 3rd party could do the same
(hopefully, they will modify the idVendor & idProduct though. :) I
suppose there's room for an MCP2210 userspace driver that utilizes
the generic one to interface with the chip and just provides an
interface to userspace, but I'm not personally interested in such a
thing myself.
So I'm thinking that with my own driver, I would look for the
idVendor and idProduct of the unmodified MCP2210 (because I'm a poor
bastard) and then -ENODEV unless the product & mfg strings also
no need to look for it, just use the id_table to match your idVendor and
idProduct. Driver model will make sure to bind your device properly so
you can assume that if your probe() has been called, it's because driver
model has found idVendor/idProduct properly.
Post by Daniel Santos
match. Then, I can read the EEPROM to cook up my config. (One
complexity is that our device can have various features & hardware
present or not, so that's another reason for us to stick the hardware
setup in the EEPROM.)
alright.
Post by Daniel Santos
Does that make sense? Also, the "generic driver" then becomes more of
a library than an actual driver, huh?
I think it should still be a driver, just an MFD driver.
Post by Daniel Santos
Post by Felipe Balbi
If it's not mandatory, then it gets tricky to support multiple users.
Can users write whatever they want to EEPROM or is there a specified
format ?
The MCP2210 allows you to write-protect the persistent settings
(including the EEPROM contents) with a password or just permanently
lock them. You have to issue USB commands to alter the EEPROM and I
don't plan on exposing that to userspace from the driver for my
product. So if anybody changes them, its their own damn fault. :)
right on ;-)
Post by Daniel Santos
Post by Felipe Balbi
In any case, there are ways to make it work, just some are easier to
code then the others ;-)
Well this helps a great deal, thank you! I want to try to keep this
simple, but I also would like it to be re-usable. There are
currently USB to serial, 1-wire and I think i2c in the kernel already
and I would expect this class of device will become more prevalent in
the future.
my suggestion would be: write it very simple, if in the future some
similar device comes around, then we think about re-factoring and making
it more generic ;-)
--
balbi
Loading...