Commit ea9972df authored by Mark Brown's avatar Mark Brown

Merge remote-tracking branches 'spi/topic/bfin-sport', 'spi/topic/bfin5xx',...

Merge remote-tracking branches 'spi/topic/bfin-sport', 'spi/topic/bfin5xx', 'spi/topic/clps711x', 'spi/topic/doc' and 'spi/topic/dt' into spi-next
...@@ -12,7 +12,6 @@ The SPI master node requires the following properties: ...@@ -12,7 +12,6 @@ The SPI master node requires the following properties:
- #size-cells - should be zero. - #size-cells - should be zero.
- compatible - name of SPI bus controller following generic names - compatible - name of SPI bus controller following generic names
recommended practice. recommended practice.
- cs-gpios - (optional) gpios chip select.
No other properties are required in the SPI bus node. It is assumed No other properties are required in the SPI bus node. It is assumed
that a driver for an SPI bus device will understand that it is an SPI bus. that a driver for an SPI bus device will understand that it is an SPI bus.
However, the binding does not attempt to define the specific method for However, the binding does not attempt to define the specific method for
...@@ -22,11 +21,12 @@ assumption that board specific platform code will be used to manage ...@@ -22,11 +21,12 @@ assumption that board specific platform code will be used to manage
chip selects. Individual drivers can define additional properties to chip selects. Individual drivers can define additional properties to
support describing the chip select layout. support describing the chip select layout.
Optional property: Optional properties:
- num-cs : total number of chipselects - cs-gpios - gpios chip select.
- num-cs - total number of chipselects.
If cs-gpios is used the number of chip select will automatically increased If cs-gpios is used the number of chip selects will be increased automatically
with max(cs-gpios > hw cs) with max(cs-gpios > hw cs).
So if for example the controller has 2 CS lines, and the cs-gpios So if for example the controller has 2 CS lines, and the cs-gpios
property looks like this: property looks like this:
...@@ -45,29 +45,30 @@ SPI slave nodes must be children of the SPI master node and can ...@@ -45,29 +45,30 @@ SPI slave nodes must be children of the SPI master node and can
contain the following properties. contain the following properties.
- reg - (required) chip select address of device. - reg - (required) chip select address of device.
- compatible - (required) name of SPI device following generic names - compatible - (required) name of SPI device following generic names
recommended practice recommended practice.
- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz - spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz.
- spi-cpol - (optional) Empty property indicating device requires - spi-cpol - (optional) Empty property indicating device requires
inverse clock polarity (CPOL) mode inverse clock polarity (CPOL) mode.
- spi-cpha - (optional) Empty property indicating device requires - spi-cpha - (optional) Empty property indicating device requires
shifted clock phase (CPHA) mode shifted clock phase (CPHA) mode.
- spi-cs-high - (optional) Empty property indicating device requires - spi-cs-high - (optional) Empty property indicating device requires
chip select active high chip select active high.
- spi-3wire - (optional) Empty property indicating device requires - spi-3wire - (optional) Empty property indicating device requires
3-wire mode. 3-wire mode.
- spi-lsb-first - (optional) Empty property indicating device requires - spi-lsb-first - (optional) Empty property indicating device requires
LSB first mode. LSB first mode.
- spi-tx-bus-width - (optional) The bus width(number of data wires) that - spi-tx-bus-width - (optional) The bus width (number of data wires) that is
used for MOSI. Defaults to 1 if not present. used for MOSI. Defaults to 1 if not present.
- spi-rx-bus-width - (optional) The bus width(number of data wires) that - spi-rx-bus-width - (optional) The bus width (number of data wires) that is
used for MISO. Defaults to 1 if not present. used for MISO. Defaults to 1 if not present.
- spi-rx-delay-us - (optional) Microsecond delay after a read transfer. - spi-rx-delay-us - (optional) Microsecond delay after a read transfer.
- spi-tx-delay-us - (optional) Microsecond delay after a write transfer. - spi-tx-delay-us - (optional) Microsecond delay after a write transfer.
Some SPI controllers and devices support Dual and Quad SPI transfer mode. Some SPI controllers and devices support Dual and Quad SPI transfer mode.
It allows data in the SPI system to be transferred in 2 wires(DUAL) or 4 wires(QUAD). It allows data in the SPI system to be transferred using 2 wires (DUAL) or 4
wires (QUAD).
Now the value that spi-tx-bus-width and spi-rx-bus-width can receive is Now the value that spi-tx-bus-width and spi-rx-bus-width can receive is
only 1(SINGLE), 2(DUAL) and 4(QUAD). only 1 (SINGLE), 2 (DUAL) and 4 (QUAD).
Dual/Quad mode is not allowed when 3-wire mode is used. Dual/Quad mode is not allowed when 3-wire mode is used.
If a gpio chipselect is used for the SPI slave the gpio number will be passed If a gpio chipselect is used for the SPI slave the gpio number will be passed
......
Serial Peripheral Interface on Cirrus Logic CL-PS71xx, EP72xx, EP73xx
Required properties
- #address-cells: must be <1>
- #size-cells: must be <0>
- compatible: should include "cirrus,ep7209-spi"
- reg: Address and length of one register range
- interrupts: one interrupt line
- clocks: One entry, refers to the SPI bus clock
- cs-gpios: Specifies the gpio pins to be used for chipselects.
See: Documentation/devicetree/bindings/spi/spi-bus.txt
An additional register is present in the system controller,
which is assumed to be in the same device tree, with and marked
as compatible with "cirrus,ep7209-syscon3".
Example:
spi@80000500 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "cirrus,ep7209-spi";
reg = <0x80000500 0x4>;
interrupts = <15>;
clocks = <&clks CLPS711X_CLK_SPI>;
status = "disabled";
};
syscon3: syscon@80002200 {
compatible = "cirrus,ep7209-syscon3", "syscon";
reg = <0x80002200 0x40>;
};
...@@ -21,7 +21,7 @@ Required properties: ...@@ -21,7 +21,7 @@ Required properties:
IP to the interrupt controller within the SoC. Possible values IP to the interrupt controller within the SoC. Possible values
are 0 and 1. Manual says one of the two possible interrupt are 0 and 1. Manual says one of the two possible interrupt
lines can be tied to the interrupt controller. Set this lines can be tied to the interrupt controller. Set this
based on a specifc SoC configuration. based on a specific SoC configuration.
- interrupts: interrupt number mapped to CPU. - interrupts: interrupt number mapped to CPU.
- clocks: spi clk phandle - clocks: spi clk phandle
......
...@@ -20,7 +20,7 @@ Optional properties: ...@@ -20,7 +20,7 @@ Optional properties:
chipselect register and offset of that register. chipselect register and offset of that register.
NOTE: TI QSPI controller requires different pinmux and IODelay NOTE: TI QSPI controller requires different pinmux and IODelay
paramaters for Mode-0 and Mode-3 operations, which needs to be set up by parameters for Mode-0 and Mode-3 operations, which needs to be set up by
the bootloader (U-Boot). Default configuration only supports Mode-0 the bootloader (U-Boot). Default configuration only supports Mode-0
operation. Hence, "spi-cpol" and "spi-cpha" DT properties cannot be operation. Hence, "spi-cpol" and "spi-cpha" DT properties cannot be
specified in the slave nodes of TI QSPI controller without appropriate specified in the slave nodes of TI QSPI controller without appropriate
......
...@@ -64,8 +64,6 @@ struct bfin_sport_spi_master_data { ...@@ -64,8 +64,6 @@ struct bfin_sport_spi_master_data {
/* Pin request list */ /* Pin request list */
u16 *pin_req; u16 *pin_req;
/* Driver message queue */
struct workqueue_struct *workqueue;
struct work_struct pump_messages; struct work_struct pump_messages;
spinlock_t lock; spinlock_t lock;
struct list_head queue; struct list_head queue;
...@@ -300,7 +298,7 @@ bfin_sport_spi_giveback(struct bfin_sport_spi_master_data *drv_data) ...@@ -300,7 +298,7 @@ bfin_sport_spi_giveback(struct bfin_sport_spi_master_data *drv_data)
drv_data->cur_msg = NULL; drv_data->cur_msg = NULL;
drv_data->cur_transfer = NULL; drv_data->cur_transfer = NULL;
drv_data->cur_chip = NULL; drv_data->cur_chip = NULL;
queue_work(drv_data->workqueue, &drv_data->pump_messages); schedule_work(&drv_data->pump_messages);
spin_unlock_irqrestore(&drv_data->lock, flags); spin_unlock_irqrestore(&drv_data->lock, flags);
if (!drv_data->cs_change) if (!drv_data->cs_change)
...@@ -556,7 +554,7 @@ bfin_sport_spi_transfer(struct spi_device *spi, struct spi_message *msg) ...@@ -556,7 +554,7 @@ bfin_sport_spi_transfer(struct spi_device *spi, struct spi_message *msg)
list_add_tail(&msg->queue, &drv_data->queue); list_add_tail(&msg->queue, &drv_data->queue);
if (drv_data->run && !drv_data->busy) if (drv_data->run && !drv_data->busy)
queue_work(drv_data->workqueue, &drv_data->pump_messages); schedule_work(&drv_data->pump_messages);
spin_unlock_irqrestore(&drv_data->lock, flags); spin_unlock_irqrestore(&drv_data->lock, flags);
...@@ -666,12 +664,7 @@ bfin_sport_spi_init_queue(struct bfin_sport_spi_master_data *drv_data) ...@@ -666,12 +664,7 @@ bfin_sport_spi_init_queue(struct bfin_sport_spi_master_data *drv_data)
tasklet_init(&drv_data->pump_transfers, tasklet_init(&drv_data->pump_transfers,
bfin_sport_spi_pump_transfers, (unsigned long)drv_data); bfin_sport_spi_pump_transfers, (unsigned long)drv_data);
/* init messages workqueue */
INIT_WORK(&drv_data->pump_messages, bfin_sport_spi_pump_messages); INIT_WORK(&drv_data->pump_messages, bfin_sport_spi_pump_messages);
drv_data->workqueue =
create_singlethread_workqueue(dev_name(drv_data->master->dev.parent));
if (drv_data->workqueue == NULL)
return -EBUSY;
return 0; return 0;
} }
...@@ -694,7 +687,7 @@ bfin_sport_spi_start_queue(struct bfin_sport_spi_master_data *drv_data) ...@@ -694,7 +687,7 @@ bfin_sport_spi_start_queue(struct bfin_sport_spi_master_data *drv_data)
drv_data->cur_chip = NULL; drv_data->cur_chip = NULL;
spin_unlock_irqrestore(&drv_data->lock, flags); spin_unlock_irqrestore(&drv_data->lock, flags);
queue_work(drv_data->workqueue, &drv_data->pump_messages); schedule_work(&drv_data->pump_messages);
return 0; return 0;
} }
...@@ -738,7 +731,7 @@ bfin_sport_spi_destroy_queue(struct bfin_sport_spi_master_data *drv_data) ...@@ -738,7 +731,7 @@ bfin_sport_spi_destroy_queue(struct bfin_sport_spi_master_data *drv_data)
if (status) if (status)
return status; return status;
destroy_workqueue(drv_data->workqueue); flush_work(&drv_data->pump_messages);
return 0; return 0;
} }
......
...@@ -67,8 +67,6 @@ struct bfin_spi_master_data { ...@@ -67,8 +67,6 @@ struct bfin_spi_master_data {
/* BFIN hookup */ /* BFIN hookup */
struct bfin5xx_spi_master *master_info; struct bfin5xx_spi_master *master_info;
/* Driver message queue */
struct workqueue_struct *workqueue;
struct work_struct pump_messages; struct work_struct pump_messages;
spinlock_t lock; spinlock_t lock;
struct list_head queue; struct list_head queue;
...@@ -359,7 +357,7 @@ static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data) ...@@ -359,7 +357,7 @@ static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data)
drv_data->cur_msg = NULL; drv_data->cur_msg = NULL;
drv_data->cur_transfer = NULL; drv_data->cur_transfer = NULL;
drv_data->cur_chip = NULL; drv_data->cur_chip = NULL;
queue_work(drv_data->workqueue, &drv_data->pump_messages); schedule_work(&drv_data->pump_messages);
spin_unlock_irqrestore(&drv_data->lock, flags); spin_unlock_irqrestore(&drv_data->lock, flags);
msg->state = NULL; msg->state = NULL;
...@@ -946,7 +944,7 @@ static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg) ...@@ -946,7 +944,7 @@ static int bfin_spi_transfer(struct spi_device *spi, struct spi_message *msg)
list_add_tail(&msg->queue, &drv_data->queue); list_add_tail(&msg->queue, &drv_data->queue);
if (drv_data->running && !drv_data->busy) if (drv_data->running && !drv_data->busy)
queue_work(drv_data->workqueue, &drv_data->pump_messages); schedule_work(&drv_data->pump_messages);
spin_unlock_irqrestore(&drv_data->lock, flags); spin_unlock_irqrestore(&drv_data->lock, flags);
...@@ -1177,12 +1175,7 @@ static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data) ...@@ -1177,12 +1175,7 @@ static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data)
tasklet_init(&drv_data->pump_transfers, tasklet_init(&drv_data->pump_transfers,
bfin_spi_pump_transfers, (unsigned long)drv_data); bfin_spi_pump_transfers, (unsigned long)drv_data);
/* init messages workqueue */
INIT_WORK(&drv_data->pump_messages, bfin_spi_pump_messages); INIT_WORK(&drv_data->pump_messages, bfin_spi_pump_messages);
drv_data->workqueue = create_singlethread_workqueue(
dev_name(drv_data->master->dev.parent));
if (drv_data->workqueue == NULL)
return -EBUSY;
return 0; return 0;
} }
...@@ -1204,7 +1197,7 @@ static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data) ...@@ -1204,7 +1197,7 @@ static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data)
drv_data->cur_chip = NULL; drv_data->cur_chip = NULL;
spin_unlock_irqrestore(&drv_data->lock, flags); spin_unlock_irqrestore(&drv_data->lock, flags);
queue_work(drv_data->workqueue, &drv_data->pump_messages); schedule_work(&drv_data->pump_messages);
return 0; return 0;
} }
...@@ -1246,7 +1239,7 @@ static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data) ...@@ -1246,7 +1239,7 @@ static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data)
if (status != 0) if (status != 0)
return status; return status;
destroy_workqueue(drv_data->workqueue); flush_work(&drv_data->pump_messages);
return 0; return 0;
} }
......
/* /*
* CLPS711X SPI bus driver * CLPS711X SPI bus driver
* *
* Copyright (C) 2012-2014 Alexander Shiyan <shc_work@mail.ru> * Copyright (C) 2012-2016 Alexander Shiyan <shc_work@mail.ru>
* *
* This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
...@@ -12,7 +12,6 @@ ...@@ -12,7 +12,6 @@
#include <linux/io.h> #include <linux/io.h>
#include <linux/clk.h> #include <linux/clk.h>
#include <linux/gpio.h> #include <linux/gpio.h>
#include <linux/delay.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
...@@ -20,9 +19,8 @@ ...@@ -20,9 +19,8 @@
#include <linux/mfd/syscon.h> #include <linux/mfd/syscon.h>
#include <linux/mfd/syscon/clps711x.h> #include <linux/mfd/syscon/clps711x.h>
#include <linux/spi/spi.h> #include <linux/spi/spi.h>
#include <linux/platform_data/spi-clps711x.h>
#define DRIVER_NAME "spi-clps711x" #define DRIVER_NAME "clps711x-spi"
#define SYNCIO_FRMLEN(x) ((x) << 8) #define SYNCIO_FRMLEN(x) ((x) << 8)
#define SYNCIO_TXFRMEN (1 << 14) #define SYNCIO_TXFRMEN (1 << 14)
...@@ -40,6 +38,17 @@ struct spi_clps711x_data { ...@@ -40,6 +38,17 @@ struct spi_clps711x_data {
static int spi_clps711x_setup(struct spi_device *spi) static int spi_clps711x_setup(struct spi_device *spi)
{ {
if (!spi->controller_state) {
int ret;
ret = devm_gpio_request(&spi->master->dev, spi->cs_gpio,
dev_name(&spi->master->dev));
if (ret)
return ret;
spi->controller_state = spi;
}
/* We are expect that SPI-device is not selected */ /* We are expect that SPI-device is not selected */
gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH)); gpio_direction_output(spi->cs_gpio, !(spi->mode & SPI_CS_HIGH));
...@@ -104,20 +113,9 @@ static irqreturn_t spi_clps711x_isr(int irq, void *dev_id) ...@@ -104,20 +113,9 @@ static irqreturn_t spi_clps711x_isr(int irq, void *dev_id)
static int spi_clps711x_probe(struct platform_device *pdev) static int spi_clps711x_probe(struct platform_device *pdev)
{ {
struct spi_clps711x_data *hw; struct spi_clps711x_data *hw;
struct spi_clps711x_pdata *pdata = dev_get_platdata(&pdev->dev);
struct spi_master *master; struct spi_master *master;
struct resource *res; struct resource *res;
int i, irq, ret; int irq, ret;
if (!pdata) {
dev_err(&pdev->dev, "No platform data supplied\n");
return -EINVAL;
}
if (pdata->num_chipselect < 1) {
dev_err(&pdev->dev, "At least one CS must be defined\n");
return -EINVAL;
}
irq = platform_get_irq(pdev, 0); irq = platform_get_irq(pdev, 0);
if (irq < 0) if (irq < 0)
...@@ -127,40 +125,24 @@ static int spi_clps711x_probe(struct platform_device *pdev) ...@@ -127,40 +125,24 @@ static int spi_clps711x_probe(struct platform_device *pdev)
if (!master) if (!master)
return -ENOMEM; return -ENOMEM;
master->cs_gpios = devm_kzalloc(&pdev->dev, sizeof(int) * master->bus_num = -1;
pdata->num_chipselect, GFP_KERNEL);
if (!master->cs_gpios) {
ret = -ENOMEM;
goto err_out;
}
master->bus_num = pdev->id;
master->mode_bits = SPI_CPHA | SPI_CS_HIGH; master->mode_bits = SPI_CPHA | SPI_CS_HIGH;
master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8); master->bits_per_word_mask = SPI_BPW_RANGE_MASK(1, 8);
master->num_chipselect = pdata->num_chipselect; master->dev.of_node = pdev->dev.of_node;
master->setup = spi_clps711x_setup; master->setup = spi_clps711x_setup;
master->prepare_message = spi_clps711x_prepare_message; master->prepare_message = spi_clps711x_prepare_message;
master->transfer_one = spi_clps711x_transfer_one; master->transfer_one = spi_clps711x_transfer_one;
hw = spi_master_get_devdata(master); hw = spi_master_get_devdata(master);
for (i = 0; i < master->num_chipselect; i++) {
master->cs_gpios[i] = pdata->chipselect[i];
ret = devm_gpio_request(&pdev->dev, master->cs_gpios[i],
DRIVER_NAME);
if (ret) {
dev_err(&pdev->dev, "Can't get CS GPIO %i\n", i);
goto err_out;
}
}
hw->spi_clk = devm_clk_get(&pdev->dev, NULL); hw->spi_clk = devm_clk_get(&pdev->dev, NULL);
if (IS_ERR(hw->spi_clk)) { if (IS_ERR(hw->spi_clk)) {
ret = PTR_ERR(hw->spi_clk); ret = PTR_ERR(hw->spi_clk);
goto err_out; goto err_out;
} }
hw->syscon = syscon_regmap_lookup_by_pdevname("syscon.3"); hw->syscon =
syscon_regmap_lookup_by_compatible("cirrus,ep7209-syscon3");
if (IS_ERR(hw->syscon)) { if (IS_ERR(hw->syscon)) {
ret = PTR_ERR(hw->syscon); ret = PTR_ERR(hw->syscon);
goto err_out; goto err_out;
...@@ -185,14 +167,8 @@ static int spi_clps711x_probe(struct platform_device *pdev) ...@@ -185,14 +167,8 @@ static int spi_clps711x_probe(struct platform_device *pdev)
goto err_out; goto err_out;
ret = devm_spi_register_master(&pdev->dev, master); ret = devm_spi_register_master(&pdev->dev, master);
if (!ret) { if (!ret)
dev_info(&pdev->dev,
"SPI bus driver initialized. Master clock %u Hz\n",
master->max_speed_hz);
return 0; return 0;
}
dev_err(&pdev->dev, "Failed to register master\n");
err_out: err_out:
spi_master_put(master); spi_master_put(master);
...@@ -200,9 +176,16 @@ static int spi_clps711x_probe(struct platform_device *pdev) ...@@ -200,9 +176,16 @@ static int spi_clps711x_probe(struct platform_device *pdev)
return ret; return ret;
} }
static const struct of_device_id clps711x_spi_dt_ids[] = {
{ .compatible = "cirrus,ep7209-spi", },
{ }
};
MODULE_DEVICE_TABLE(of, clps711x_spi_dt_ids);
static struct platform_driver clps711x_spi_driver = { static struct platform_driver clps711x_spi_driver = {
.driver = { .driver = {
.name = DRIVER_NAME, .name = DRIVER_NAME,
.of_match_table = clps711x_spi_dt_ids,
}, },
.probe = spi_clps711x_probe, .probe = spi_clps711x_probe,
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment