From 61ca6adb1fc93622bb85acc18b6ce4f620c8c690 Mon Sep 17 00:00:00 2001 From: Phil Elwell Date: Wed, 24 Jun 2015 14:10:44 +0100 Subject: [PATCH] spi-bcm2835: Support pin groups other than 7-11 The spi-bcm2835 driver automatically uses GPIO chip-selects due to some unreliability of the native ones. In doing so it chooses the same pins as the native chip-selects would use, but the existing code always uses pins 7 and 8, wherever the SPI function is mapped. Search the pinctrl group assigned to the driver for pins that correspond to native chip-selects, and use those for GPIO chip- selects. Signed-off-by: Phil Elwell --- drivers/spi/spi-bcm2835.c | 45 ++++++++++++++++++++++++++++++++------- 1 file changed, 37 insertions(+), 8 deletions(-) --- a/drivers/spi/spi-bcm2835.c +++ b/drivers/spi/spi-bcm2835.c @@ -687,6 +687,8 @@ static int bcm2835_spi_setup(struct spi_ { int err; struct gpio_chip *chip; + struct device_node *pins; + u32 pingroup_index; /* * sanity checking the native-chipselects */ @@ -703,15 +705,42 @@ static int bcm2835_spi_setup(struct spi_ "setup: only two native chip-selects are supported\n"); return -EINVAL; } - /* now translate native cs to GPIO */ - /* get the gpio chip for the base */ - chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); - if (!chip) - return 0; + /* now translate native cs to GPIO */ + /* first look for chip select pins in the devices pin groups */ + for (pingroup_index = 0; + (pins = of_parse_phandle(spi->master->dev.of_node, + "pinctrl-0", + pingroup_index)) != 0; + pingroup_index++) { + u32 pin; + u32 pin_index; + for (pin_index = 0; + of_property_read_u32_index(pins, + "brcm,pins", + pin_index, + &pin) == 0; + pin_index++) { + if (((spi->chip_select == 0) && + ((pin == 8) || (pin == 36) || (pin == 46))) || + ((spi->chip_select == 1) && + ((pin == 7) || (pin == 35)))) { + spi->cs_gpio = pin; + break; + } + } + of_node_put(pins); + } + /* if that fails, assume GPIOs 7-11 are used */ + if (!gpio_is_valid(spi->cs_gpio) ) { + /* get the gpio chip for the base */ + chip = gpiochip_find("pinctrl-bcm2835", chip_match_name); + if (!chip) + return 0; - /* and calculate the real CS */ - spi->cs_gpio = chip->base + 8 - spi->chip_select; + /* and calculate the real CS */ + spi->cs_gpio = chip->base + 8 - spi->chip_select; + } /* and set up the "mode" and level */ dev_info(&spi->dev, "setting up native-CS%i as GPIO %i\n",