2010-11-04 05:00:24 Clarification in SPIDEV driver
Shyam sundar (INDIA)
Message: 95548
I am using spidev device driver(spidev0.6) for configuring a codec
The slave select goes low only when a data transfer happens from the blackfin(master) to codec(slave).How can I make the slave select line to go low untill all the control words are transmitted to the codec? (The codec chip is not being provided with the option to read back what was being configured). The codec works fine in the vdsp environment.Around 40% of the time I am not able to configure the codec successfully.
The following is the userspace code I am using to configure the codec
/******CONFIGURE SPI INTERFACE SENDING CONTROL WORDS CLOCK FOR CODEC*******/
printf("Configuring codec through SPI........\n");
spi_fd = open(device, O_RDWR);
if (spi_fd < 0)
{
close(sport1_fd);
printf("can't open SPI device");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
{
close(sport1_fd);
printf("can't set SPI mode");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
{
close(sport1_fd);
printf("can't get SPI mode");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
{
close(sport1_fd);
printf("can't set bits per word for SPI");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
{
close(sport1_fd);
printf("can't get bits per word for SPI");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
{
close(sport1_fd);
printf("can't set max speed hz for SPI");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
{
close(sport1_fd);
printf("can't get max speed hz for SPI");
return -1;
}
printf("spi mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
/****SEND THE CONTROL WORDS FOR CODEC THROUGH SPI INTERFACE****/
write(spi_fd,control_word_buf,8);
close(spi_fd);
close(sport1_fd);
QuoteReplyEditDelete
2010-11-04 05:44:52 Re: Clarification in SPIDEV driver
Aaron Wu (CHINA)
Message: 95550
The CS line toggles once every SPI data transfer unit, this looks fine and should be compliant with the SPI timming chart. Do you think keeping the CS line permanently low will help in your case? if so think about connecting a resistor of low value like 100 Ohm between the CS line and ground then have a try.
QuoteReplyEditDelete
2010-11-04 07:21:28 Re: Clarification in SPIDEV driver
Shyam sundar (INDIA)
Message: 95556
Hi Aaron.
I could have done that, but I do have other SPI devices,Hence I dont want the CS line to be permanently connected to go low. I just want to ensure the CS line remains low just before the config data is transmitted and goes back to high after the config data is transmitted.So how can control this CS line?
QuoteReplyEditDelete
2010-11-04 22:56:16 Re: Clarification in SPIDEV driver
Aaron Wu (CHINA)
Message: 95576
Are you using the general SPI or SPI over SPORT?
In my understanding, the SPI protocol requires the CS line to toggle between each transfer words, and this is the default behavior of our SPI driver. From your description I guess the permanent low for CS line is required by your codec timming chart right?
I think you can try to configure this as needed, from the hardware reference manual this should be configurable, copy part of it for your reference:
Slave Select Value (FLGx) bits
When a PFx pin is configured as a slave select output, the FLGx bits
can determine the value driven onto the output. If the CPHA bit in
SPI_CTL is set, the output value is set by software control of the
FLGx bits. The SPI protocol permits the slave select line to either
remain asserted (low) or be deasserted between transferred words.
The user must set or clear the appropriate FLGx bits. For example,
to drive PF3 as a slave select, FLS3 in SPI_FLG must be set. Clearing
FLG3 in SPI_FLG drives PF3 low; setting FLG3 drives PF3 high. The
PF3 pin can be cycled high and low between transfers by setting
and clearing FLG3. Otherwise, PF3 remains active (low) between
transfers.
If CPHA = 0, the SPI hardware sets the output value and the FLGx
bits are ignored. The SPI protocol requires that the slave select be
deasserted between transferred words. In this case, the SPI hardware
controls the pins. For example, to use PF3 as a slave select pin,
it is only necessary to set the FLS3 bit in SPI_FLG. It is not necessary
to write to the FLG3 bit, because the SPI hardware automatically
drives the PF3 pin.
QuoteReplyEditDelete
2010-11-05 03:38:34 Re: Clarification in SPIDEV driver
Aaron Wu (CHINA)
Message: 95586
one more thing, if the "CS pamerment low" is required by your device timming chart, I think the quick way to verify is to connect a resistor to ground as I suggested in the previous post, as the standard SPI framework in Linux does not support this from software I think.
For you consideration of multiple SPI devices in your system, I think it does not matter. As for SPI bus, each CS line is dedicately assigned to a single device only, multiple devices are connected to different CS lines, so hardware reworking the CS line to your codec is safe for other SPI devices.
QuoteReplyEditDelete
2010-11-05 13:05:38 Re: Clarification in SPIDEV driver
Wojtek Skulski (UNITED STATES)
Message: 95596
The resistor to ground will only work if the CS line is tristated when the devices is deselected. In case the CS line is actively driven, it will overcome the resistor when it is driven HIGH. I do not know which is the case in Blackfin hardware, but I would be somewhat surprised to learn that the CS is left floating when the device is not selected. If this was the case then one would need a pullpup for every SPI device.
QuoteReplyEditDelete
2010-11-07 21:03:34 Re: Clarification in SPIDEV driver
Aaron Wu (CHINA)
Message: 95615
Hi,
What's the latest status?
It's just a quick test for you to decide if the CS line should really be "always low" during bytes transfer in your case, as this does not confirm with the standard protocol.
If it really need to be "always low", then you need to hack the spi driver to meet the requirement, or use GPIO to achive it instead of the hardware SPI module.
QuoteReplyEditDelete
2010-11-07 22:32:27 Re: Clarification in SPIDEV driver
Sonic Zhang (CHINA)
Message: 95620
You best choice for non stantard SPI device is to separate it from other standard SPI devices under Linux SPI framework. Connect it to SPI over SPORT and write your own SPI over SPORT driver.
QuoteReplyEditDelete
2010-11-09 01:43:31 Re: Clarification in SPIDEV driver
Shyam sundar (INDIA)
Message: 95678
Sorry for reverting back lately,
I am using the normal SPI and not SPI over sport.
I am trying to configure the codec through the SPI, the codec's requirement for the master clock is accomplished using thethe serial clock generated by SPORT1 and the data samples to the codec are given through SPORT0.
When the codec gets configured, I do have a probing pin on the codec chip which will read 1.1 V when it gets configured.The codec fails to get configured for around 30% of the time. I am trying to analyse if there is any issues in the timings.
My doubt is if I enable the slave line permanently through hardware, will it not corrupt the codec chip configuration due to some junk data?
QuoteReplyEditDelete
2010-11-09 02:25:45 Re: Clarification in SPIDEV driver
Mike Frysinger (UNITED STATES)
Message: 95679
please read the documentation in the spidev.h header. create an array of spi transfers, set the cs_change field as you need, and then do a single SPI_IOC_MESSAGE() ioctl.
if you need a certain SPI mode where the Blackfin SPI master controls the CS via hardware, then use it in GPIO CS mode instead as documented in the wiki:
docs.blackfin.uclinux.org/doku.php?id=spi#device_resources
QuoteReplyEditDelete
2010-11-09 02:26:15 Re: Clarification in SPIDEV driver
Mike Frysinger (UNITED STATES)
Message: 95680
also, this is a Linux issue, not u-boot. please select the correct forum in the future when posting questions. ive moved it for you this time.
QuoteReplyEditDelete
2010-11-09 23:00:33 Re: Clarification in SPIDEV driver
Sonic Zhang (CHINA)
Message: 95718
"Nonstandard SPI" here means your SPI device doens't obey the SPI protocol used by kernel SPI framework, no matter you connect it to SPI or SPORT.
QuoteReplyEditDelete
2010-11-10 03:26:56 Re: Clarification in SPIDEV driver
Shyam sundar (INDIA)
Message: 95734
Thanks to all,
Please rectify,if I am wrong
So if the user wants to control the slave select manually then, we need to set chip_select = 0 and add a cs_gpio to our controller_data. i.e, if I want to use spidev0.6 then in the path uClinux-dist/linux-2.6.x/arch/blackfin/mach-bf537/boards/stamp.c the following lines should be present. Then the user can use the GPIO driver to make the slave select line go high or low accordingly.
#if defined(CONFIG_BFIN_SPI_CODEC)
static struct bfin5xx_spi_chip spi_codec_chip_info = {
.enable_dma = 1, /* use dma transfer with this chip*/
.bits_per_word = 16,
.cs_gpio = GPIO_PF04
};
#endif
static struct spi_board_info bfin_spi_board_info[] __initdata = {
#if defined(CONFIG_BFIN_SPI_CODEC)
{
.modalias = "spidev", /* Name of spi_driver for this device */
.max_speed_hz = 3250000, /* max spi clock (SCK) speed in HZ */
.bus_num = 0, /* Framework bus number */
.chip_select = 0, /* Framework chip select. */
.platform_data = NULL, /* No spi_driver specific config */
.controller_data = &spi_codec_chip_info,
},
#endif
}
QuoteReplyEditDelete
2010-11-10 04:02:50 Re: Clarification in SPIDEV driver
Sonic Zhang (CHINA)
Message: 95735
The spi_bfin5xx always driver the CS automatically no matter which kind of CS PIN you enabled. Because the kernel SPI framework driver doesn't allow manual CS control by upper level users.
Your only choice is to write your own SPI char driver out of the SPI framework.
QuoteReplyEditDelete
2010-11-10 04:09:58 Re: Clarification in SPIDEV driver
Mike Frysinger (UNITED STATES)
Message: 95736
if our SPI master driver doesnt respect spi_transfer.cs_change, then our driver is broken. but both our masters support it.
QuoteReplyEditDelete
2010-11-10 04:41:54 Re: Clarification in SPIDEV driver
Sonic Zhang (CHINA)
Message: 95742
But, the customer wants to low the CS during all messages transfered through SPI, according to his sample code. The cs_change only toggles the CS between transfers within a message, other than between messages.
If the customer can bundle all messages into one message with several transfers, cs_change can be an option.
QuoteReplyEditDelete
2010-11-10 04:44:14 Re: Clarification in SPIDEV driver
Sonic Zhang (CHINA)
Message: 95743
OK. Look again, it seems the customer want to send only one buffer? If so, the setting cs_change = 0 is the solution.
QuoteReplyEditDelete
2010-11-10 04:52:34 Re: Clarification in SPIDEV driver
Mike Frysinger (UNITED STATES)
Message: 95744
which is what i suggested
blackfin.uclinux.org/gf/forummessage/95679
QuoteReplyEditDelete
2010-11-10 05:30:36 Re: Clarification in SPIDEV driver
Shyam sundar (INDIA)
Message: 95746
Ooops, I am getting little confused with the discussions going on here
Sonic Zhang says that user will not have the manual control of the slave select pin.
So what is the use of setting chip_select = 0 and add a cs_gpio to in the controller_data, when you can directly specify the the slave line using chip_select?
QuoteReplyEditDelete
2010-11-10 05:38:29 Re: Clarification in SPIDEV driver
Shyam sundar (INDIA)
Message: 95747
Does my assumption as posted in the following link,holds true??
blackfin.uclinux.org/gf/forummessage/95734
QuoteReplyEditDelete
2010-11-10 05:54:05 Re: Clarification in SPIDEV driver
Aaron Wu (CHINA)
Message: 95748
Could you try Mike's suggestion and check if it will solve your problem? If not please probe the waveform of the SPI interface with a oscilloscope and compare it with the expected one specified in your codec specificaiton or the working ones in other situation you mentioned, tell us the difference and let's go on to figure out a solution.
QuoteReplyEditDelete
2010-11-10 09:22:54 Re: Clarification in SPIDEV driver
Shyam sundar (INDIA)
Message: 95750
Before Mike's suggestion I had earlier used SPI_IOC_MESSAGE() ioctl to write the config words for the codec. During that time I was using SPI in SPI_MODE_0 mode. In this mode, I was seeing the slave select line going high between the transfer words.When I used SPI_MODE_1 mode, I saw the slave select line going low at the start of the data transfer and then high when all the data was transfered. This I think, is the behaviour of the standard SPI protocol.
I will try to use the settings which I have posted in the forum as suggested by Mike and revert back !!
QuoteReplyEditDelete
2010-11-11 06:54:24 Re: Clarification in SPIDEV driver
Shyam sundar (INDIA)
Message: 95773
I am not able to control the slave select manually :(c ! This is the code I am using in the userspace.
Do i need to control the slave select (gpio pf4) in the spidev driver? I am using SPI in SPI_MODE_1
sleep(4);
pf4_fd = open("/dev/gpio4",O_WRONLY);
write(pf4_fd,&set_low,1);
sleep(2);
/******CONFIGURE SPI INTERFACE SENDING CONTROL WORDS CLOCK FOR CODEC*******/
printf("Configuring codec through SPI........\n");
spi_fd = open(device, O_RDWR);
if (spi_fd < 0)
{
close(sport1_fd);
printf("can't open SPI device");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_WR_MODE, &mode);
if (ret == -1)
{
close(sport1_fd);
printf("can't set SPI mode");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_RD_MODE, &mode);
if (ret == -1)
{
close(sport1_fd);
printf("can't get SPI mode");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret == -1)
{
close(sport1_fd);
printf("can't set bits per word for SPI");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
if (ret == -1)
{
close(sport1_fd);
printf("can't get bits per word for SPI");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret == -1)
{
close(sport1_fd);
printf("can't set max speed hz for SPI");
return -1;
}
ret = ioctl(spi_fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
if (ret == -1)
{
close(sport1_fd);
printf("can't get max speed hz for SPI");
return -1;
}
printf("spi mode: %d\n", mode);
printf("bits per word: %d\n", bits);
printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000);
/****SEND THE CONTROL WORDS FOR CODEC THROUGH SPI INTERFACE****/
sleep(1);
tx_codec_ctl_word(spi_fd);
sleep(4);
write(pf4_fd,&set_high,1);
close(spi_fd);
close(pf4_fd);
close(sport1_fd);
static void tx_codec_ctl_word(int fd)
{
int ret;
uint8_t tx[] = {0x88,0x84,0x25,0x89,};
uint8_t rx[ARRAY_SIZE(tx)] = {0, };
struct spi_ioc_transfer tr = {
.tx_buf = (unsigned long)tx,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret == 1)
{
close(spi_fd);
close(sport1_fd);
printf("can't send spi message");
}
}
QuoteReplyEditDelete
2010-11-11 09:48:10 Re: Clarification in SPIDEV driver
Mike Frysinger (UNITED STATES)
Message: 95776
you cannot use a pin as both GPIO and slave CS at the same time. forget about driving the GPIO manually for now.
QuoteReplyEditDelete
2010-11-12 07:22:11 Re: Clarification in SPIDEV driver
Rob Maris (GERMANY)
Message: 95801
Shyam, which version of Linux are you using? I have to emphasize that the wiki information only applies to recent linux (from 2.6.34 on, yet into distribution version 2010. There have been introduced signicant changes in how to specify the gpio-mode GPIO.
Add .cs_change = 0 into your 'tr' struct definition.
QuoteReplyEditDelete
2011-05-12 12:33:10 Re: Clarification in SPIDEV driver
Ciaran Watterson (IRELAND)
Message: 100619
"if our SPI master driver doesnt respect spi_transfer.cs_change, then our driver is broken. but both our masters support it."
I've been doing some testing of spidev recently, and as far as I can make out it doesn't except when a GPIO CS is used. This is on a BF-527.
"So what is the use of setting chip_select = 0 and add a cs_gpio to in the controller_data, when you can directly specify the the slave line using chip_select?"
The Chip Select pin is used as a GPIO, with software, still controlled by the spi_bfin5xx driver. In the latest version cs_gpio is no longer exposed. As explained in the wiki:
.chip_select = GPIO_XXX + MAX_CTRL_CS
But not mentioned in the wiki: for your spi master
.num_chipselect = MAX_CTRL_CS + MAX_BLACKFIN_GPIOS;
IMO the other way was better. My tests were done using the SPI_IOC_MESSAGE() ioctl method. Using this method, I think the mode you want can be achieved. A falling edge at the start of tx and rising edge only when all the bytes have been written, possibly in several batches. I've attached a scope capture in case I misunderstood the mode being discussed.
ucLin_SPI_GPIO.png
QuoteReplyEditDelete
2011-05-12 12:38:31 Re: Clarification in SPIDEV driver
Mike Frysinger (UNITED STATES)
Message: 100620
the old way of "hiding" the CS from the common code via .cs_gpio is simply not possible. the common code detects and rejects this behavior.