SPI PCS Decoding

1 post / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

After a bit of head scratching yesterday I think I figured out how PCS decoding on the SAMG55 works, and at the same time I think I found an issue (or at least deficiency) with the SPI driver ASF.  I'm mainly looking for someone to confirm that I'm right here and not just doing things incorrectly, and I'll submit a bug report/feature request.

 

In decode mode, the CS0 and CS1 lines are used to drive a 2 to 4 decoder to create 3 PCS lines (CS0 and CS1 both high = no devices selected).  It seems like the ASF is mostly written around non-decoded mode, and while some functions have provisions for it (ex: void spi_select_device() ), most do not, and it requires some hackery to get things working.  

 

The heart of the issue is that the ASF takes an approach where you setup devices ( spi_master_setup_device() ), and they use the device struct member "id" to determine the chip select.  In non-decode mode, you only have devices with ids 0 and 1, which correspond to chip selects 0 and 1, and everything is happy.  When you move to decoded mode, you have devices 0, 1 and 2, but there's still only two configurable chip selects.  Chip select 0 controls devices 0 and 1, and chip select 1 controls device 2.  

So in non-decode mode, you'd do something like this:

 

struct spi_device Device0 = {
	.id = 0
	};
struct spi_device Device1 = {
	.id = 1
};

spi_master_setup_device(SPI_MASTER_BASE, &Device0, SPI_MODE_0, 12000000, 0);
spi_master_setup_device(SPI_MASTER_BASE, &Device1, SPI_MODE_0, 48000000, 0);

and then reference the devices in the various select/deselect/write/read functions.

 

In decode mode you can't call spi_master_setup_device() using a device with an id of 2, and the devices with ids of 0 and 1 will share the same chip select properties, so to make things work you have to create a second set of structs:

 

//Actual devices
struct spi_device Device0 = {
	.id = 0
};
struct spi_device Device1 = {
	.id = 1
};
struct spi_device Device2 = {
	.id = 2
};

//Dummy devices to configure PCS lines
struct spi_device PCS0 = {
	.id = 0
};
struct spi_device PCS1 = {
	.id = 1
};

Then to use it all, you call spi_master_setup_device() with the dummy PCS devices, but the select/deselect/write/read functions with the real devices.  It works, but it doesn't really fit with the structure of the ASF.

 

Am I right in this work around, or is there a simpler way to do things that I'm missing?