|
@@ -96,6 +96,7 @@ struct orion_spi {
|
|
|
struct clk *clk;
|
|
|
struct clk *axi_clk;
|
|
|
const struct orion_spi_dev *devdata;
|
|
|
+ int unused_hw_gpio;
|
|
|
|
|
|
struct orion_direct_acc direct_access[ORION_NUM_CHIPSELECTS];
|
|
|
};
|
|
@@ -324,13 +325,13 @@ static void orion_spi_set_cs(struct spi_device *spi, bool enable)
|
|
|
struct orion_spi *orion_spi;
|
|
|
int cs;
|
|
|
|
|
|
+ orion_spi = spi_master_get_devdata(spi->master);
|
|
|
+
|
|
|
if (gpio_is_valid(spi->cs_gpio))
|
|
|
- cs = 0;
|
|
|
+ cs = orion_spi->unused_hw_gpio;
|
|
|
else
|
|
|
cs = spi->chip_select;
|
|
|
|
|
|
- orion_spi = spi_master_get_devdata(spi->master);
|
|
|
-
|
|
|
orion_spi_clrbits(orion_spi, ORION_SPI_IF_CTRL_REG, ORION_SPI_CS_MASK);
|
|
|
orion_spi_setbits(orion_spi, ORION_SPI_IF_CTRL_REG,
|
|
|
ORION_SPI_CS(cs));
|
|
@@ -498,6 +499,9 @@ static int orion_spi_transfer_one(struct spi_master *master,
|
|
|
|
|
|
static int orion_spi_setup(struct spi_device *spi)
|
|
|
{
|
|
|
+ if (gpio_is_valid(spi->cs_gpio)) {
|
|
|
+ gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
|
|
|
+ }
|
|
|
return orion_spi_setup_transfer(spi, NULL);
|
|
|
}
|
|
|
|
|
@@ -620,6 +624,7 @@ static int orion_spi_probe(struct platform_device *pdev)
|
|
|
|
|
|
spi = spi_master_get_devdata(master);
|
|
|
spi->master = master;
|
|
|
+ spi->unused_hw_gpio = -1;
|
|
|
|
|
|
of_id = of_match_device(orion_spi_of_match_table, &pdev->dev);
|
|
|
devdata = (of_id) ? of_id->data : &orion_spi_dev_data;
|
|
@@ -731,8 +736,44 @@ static int orion_spi_probe(struct platform_device *pdev)
|
|
|
if (status < 0)
|
|
|
goto out_rel_pm;
|
|
|
|
|
|
+ if (master->cs_gpios) {
|
|
|
+ int i;
|
|
|
+ for (i = 0; i < master->num_chipselect; ++i) {
|
|
|
+ char *gpio_name;
|
|
|
+
|
|
|
+ if (!gpio_is_valid(master->cs_gpios[i])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ gpio_name = devm_kasprintf(&pdev->dev, GFP_KERNEL,
|
|
|
+ "%s-CS%d", dev_name(&pdev->dev), i);
|
|
|
+ if (!gpio_name) {
|
|
|
+ status = -ENOMEM;
|
|
|
+ goto out_rel_master;
|
|
|
+ }
|
|
|
+
|
|
|
+ status = devm_gpio_request(&pdev->dev,
|
|
|
+ master->cs_gpios[i], gpio_name);
|
|
|
+ if (status) {
|
|
|
+ dev_err(&pdev->dev,
|
|
|
+ "Can't request GPIO for CS %d\n",
|
|
|
+ master->cs_gpios[i]);
|
|
|
+ goto out_rel_master;
|
|
|
+ }
|
|
|
+ if (spi->unused_hw_gpio == -1) {
|
|
|
+ dev_info(&pdev->dev,
|
|
|
+ "Selected unused HW CS#%d "
|
|
|
+ "for any GPIO CSes\n", i);
|
|
|
+ spi->unused_hw_gpio = i;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
return status;
|
|
|
|
|
|
+out_rel_master:
|
|
|
+ spi_unregister_master(master);
|
|
|
out_rel_pm:
|
|
|
pm_runtime_disable(&pdev->dev);
|
|
|
out_rel_axi_clk:
|