Bug 7267

Summary: unable to switch SPI SS to active-high in a board file
Product: [Build System, Metadata & Runtime] BSPs Reporter: Kevin Shelton <kmshelton>
Component: bsps-oe-coreAssignee: California Sullivan <california.l.sullivan>
Status: RESOLVED FIXED QA Contact:
Severity: normal    
Priority: Medium CC: dvhart
Version: 1.7   
Target Milestone: 2.2   
Hardware: x86   
OS: Multiple   
Whiteboard:
OS type for building Yocto: --- Type of Regression: ---
Verified: Documentation change: Don't know

Description Kevin Shelton 2015-01-29 23:35:16 UTC
End goal is to have a board file that inverts the SPI SS signal.

Building off of the low-speed-spidev.c template, we have found that having 
.mode = SPI_MODE_3 | SPI_CS_HIGH
in the spi_board_info struct does not exercise drivers/spi/spi-pxa2xx.c's gpio_cs_inverted code.  setup_cs gets called, but setup_cs returns before it can set
gpio_cs_inverted because chip_info is NULL

We added the following to our board file:
#include <linux/spi/pxa2xx_spi.h>

static struct pxa2xx_spi_chip mbm = {
  .gpio_cs = 220
};

as well as
  .controller_data = &mbm
to the spi_board_info struct

And the gpio_cs_inverted code now gets exercised, but fails to create a device because it attempts to put gpio 220 (in our 3.17 environment, pin 5 is linux gpio 220) into gpio mode (but it is necessarily set as SPI mode in the fw settings).

test environment:
3.17 yocto kernel
rev 76 uefi
debian userspace
"LPSS & SCC Devices Mode" BIOS option is set to ACPI
Comment 1 Kevin Shelton 2015-02-04 19:38:23 UTC
For spi-pxa2xx.c's gpio_request(chip_info->gpio_cs, "SPI_CS") call in setup_cs to succeed it looks like the mux state of pin 5 (GPIO220 in my environment) will have to change.  How do you change the mux state of a pin (there is an empty page about it on the wiki http://elinux.org/Minnowboard:MaxLPSSSetup)?  Using the option in the BIOS to disable SPI will change the mux state, but of course the other SPI lines will be hosed and the master won't be initialized.
Comment 2 Kevin Shelton 2015-02-06 21:48:35 UTC
I see that drivers/pinctrl/pinctrl-baytrail.c doesn't have any functions to modify mux state consistent with Mathias Nyman's comment here: http://lwn.net/Articles/552203/ "This driver does not touch the pin muxing and expect firmare to set pin muxing and pullup/down properties properly." (I think that is in reference to code that became pinctrl-baytrail.c).

I suspect the pxa2xx can do active-high CS with the mux state at 1, so maybe the checking for mux state 1 in the byt_gpio_request function in pinctrl-baytrail.c should have an exception for the SPI CS pin?  Otherwise this will require a FW cahnge, correct?
Comment 3 Kevin Shelton 2015-02-06 22:59:43 UTC
I was able to validate my SPI device that needs active-high, by inserting a call to writel(0, reg) in drivers/pinctrl/pinctrl-baytrail.c's
byt_gpio_request

What is a clean way to support active-high SPI SS on physical pin 5?  Let me know the best approach and I will try my hand at sending a patch.
Comment 4 Darren Hart 2015-02-06 23:08:20 UTC
(In reply to comment #3)
> I was able to validate my SPI device that needs active-high, by inserting a
> call to writel(0, reg) in drivers/pinctrl/pinctrl-baytrail.c's
> byt_gpio_request
> 
> What is a clean way to support active-high SPI SS on physical pin 5?  Let me
> know the best approach and I will try my hand at sending a patch.

Thank you for the updates Kevin. I've asked Mathias to take a look at this bug and comment.
Comment 5 Darren Hart 2015-05-04 16:22:19 UTC
Moving to 1.9 as we didn't get to this. I'll follow up with Matthias again.
Comment 6 Darren Hart 2015-05-05 16:40:09 UTC
Kevin, does this patch address the issue for you (from Mika W, untested):

diff --git a/drivers/spi/spi-pxa2xx.c b/drivers/spi/spi-pxa2xx.c
index e3223ac75a7c..9729a3ac1407 100644
--- a/drivers/spi/spi-pxa2xx.c
+++ b/drivers/spi/spi-pxa2xx.c
@@ -241,8 +241,12 @@ detection_done:
static void lpss_ssp_cs_control(struct driver_data *drv_data, bool enable)
{
+	const struct spi_device *spi = drv_data->cur_msg->spi;
	u32 value;
+	if (spi->mode & SPI_CS_HIGH)
+		enable = !enable;
+
	value = __lpss_ssp_read_priv(drv_data, SPI_CS_CONTROL);
	if (enable)
		value &= ~SPI_CS_CONTROL_CS_HIGH;
Comment 7 Kevin Shelton 2015-05-05 16:59:28 UTC
Thanks!  Will need a few days to get set back up to test this on hw.  Will update when I have results.
Comment 8 Kevin Shelton 2015-06-02 19:34:03 UTC
won't have access to hw to test this until 6/17, so should have an update around then
Comment 9 Kevin Shelton 2015-08-03 07:02:06 UTC
Alrighty, have hw set back up.

Just after the call to spi_new_device, I get:
[  151.646913] spi spi0.0: failed to request chip select GPIO220
[  151.646923] pxa2xx-spi 80860F0E:00: can't setup spi0.0, status -517

test environment:
clean 4.1 yocto kernel with change to spi-pxa2xx.c applied
rev 76 uefi
debian 8.1 userspace
"LPSS & SCC Devices Mode" BIOS option is set to ACPI

I will test whether my new setup is valid by applying the writel(0, reg) hack to a 3.17 yocto kernel.
Comment 10 Kevin Shelton 2015-08-03 07:36:35 UTC
I see the pin enumeration changed, so I updated from 220 to 476 and things are looking good now (IIUC, the below warning is now expected).  I confirmed I was able to send a message to my SPI device.

[  223.346990] ------------[ cut here ]------------
[  223.347002] WARNING: CPU: 0 PID: 1940 at drivers/pinctrl/intel/pinctrl-baytrail.c:216 byt_gpio_request+0x91/0xe0()
[  223.347005] Modules linked in: [snip](O+) dw_dmac dw_dmac_core i2c_designware_platform i2c_i801 i2c_designware_core spi_pxa2xx_platform
[  223.347025] CPU: 0 PID: 1940 Comm: insmod Tainted: G        W  O    4.1.2+ #5
[  223.347029] Hardware name: Circuitco MinnowBoard MAX B3 PLATFORM/MinnowBoard MAX, BIOS MNW2MAX1.X64.0076.R01.1412081258 12/08/2014
[  223.347033]  ffffffff81bdd760 ffff88006f0f3ae8 ffffffff818eae47 0000000000000007
[  223.347041]  0000000000000000 ffff88006f0f3b28 ffffffff810521c5 ffff88006f0f3b30
[  223.347048]  ffffc9000034a110 ffff88007aa69828 ffff88007aa69908 0000000000000042
[  223.347055] Call Trace:
[  223.347067]  [<ffffffff818eae47>] dump_stack+0x45/0x57
[  223.347075]  [<ffffffff810521c5>] warn_slowpath_common+0x85/0xc0
[  223.347081]  [<ffffffff810522a5>] warn_slowpath_null+0x15/0x20
[  223.347087]  [<ffffffff81339f41>] byt_gpio_request+0x91/0xe0
[  223.347094]  [<ffffffff8133ae22>] __gpiod_request+0x82/0x110
[  223.347101]  [<ffffffff8133d2eb>] gpiod_request+0x4b/0x80
[  223.347107]  [<ffffffff8133da3e>] gpio_request+0x2e/0x40
[  223.347116]  [<ffffffffa0000ef8>] setup+0x358/0x480 [spi_pxa2xx_platform]
[  223.347124]  [<ffffffff815450f3>] spi_setup+0xb3/0x160
[  223.347131]  [<ffffffff81545286>] spi_add_device+0xe6/0x1e0
[  223.347136]  [<ffffffffa0054000>] ? 0xffffffffa0054000
[  223.347143]  [<ffffffff81546feb>] spi_new_device+0x9b/0xf0
[  223.347150]  [<ffffffffa00540cc>] low_speed_spidev_module_init+0xcc/0x13c [nh_display]
[  223.347157]  [<ffffffff810002c4>] do_one_initcall+0x84/0x1b0
[  223.347163]  [<ffffffff818f0489>] ? _cond_resched+0x19/0x20
[  223.347171]  [<ffffffff81164840>] ? kmem_cache_alloc_trace+0x30/0x130
[  223.347179]  [<ffffffff818e949d>] do_init_module+0x5c/0x1bf
[  223.347186]  [<ffffffff810c3d0e>] load_module+0x1cde/0x2000
[  223.347192]  [<ffffffff810c05d0>] ? m_show+0x1a0/0x1a0
[  223.347199]  [<ffffffff810c41c6>] SyS_finit_module+0x76/0x80
[  223.347207]  [<ffffffff818f3d57>] system_call_fastpath+0x12/0x6a
[  223.347212] ---[ end trace 41fc9c2c493de6f3 ]---
[  223.347215] in the baytrail if block
[  223.347225] byt_gpio INT33FC:00: pin 66 forcibly re-configured as GPIO
[  223.349972] low-speed-spidev: dev=ffff880037b9a400
[  223.349980] low-speed-spidev: SPI mode=7
[  223.349984] low-speed-spidev: spidev registered
Comment 11 California Sullivan 2016-05-19 22:24:57 UTC
User claims its fixed.