From a777059a3fc13f51e91442ccf043c8e3bcd1c48f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Wed, 22 Jun 2016 14:48:26 +0200 Subject: [PATCH 1/6] spi: Improve DT binding documentation - Add missing verbs and periods, - Add spaces before opening parentheses, - Align list layout, - Correct grammar, - Move "cs-gpios" from the required to the optional properties section, - Remove spaces before tabs. Signed-off-by: Geert Uytterhoeven Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/spi-bus.txt | 35 ++++++++++--------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-bus.txt b/Documentation/devicetree/bindings/spi/spi-bus.txt index 42d595425dfb..17822860cb98 100644 --- a/Documentation/devicetree/bindings/spi/spi-bus.txt +++ b/Documentation/devicetree/bindings/spi/spi-bus.txt @@ -8,11 +8,10 @@ in slave mode. The SPI master node requires the following properties: - #address-cells - number of cells required to define a chip select - address on the SPI bus. + address on the SPI bus. - #size-cells - should be zero. - compatible - name of SPI bus controller following generic names - recommended practice. -- cs-gpios - (optional) gpios chip select. + recommended practice. 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. 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 chip selects. Individual drivers can define additional properties to support describing the chip select layout. -Optional property: -- num-cs : total number of chipselects +Optional properties: +- cs-gpios - gpios chip select. +- num-cs - total number of chipselects. -If cs-gpios is used the number of chip select will automatically increased -with max(cs-gpios > hw cs) +If cs-gpios is used the number of chip selects will be increased automatically +with max(cs-gpios > hw cs). So if for example the controller has 2 CS lines, and the cs-gpios property looks like this: @@ -45,29 +45,30 @@ SPI slave nodes must be children of the SPI master node and can contain the following properties. - reg - (required) chip select address of device. - compatible - (required) name of SPI device following generic names - recommended practice -- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz + recommended practice. +- spi-max-frequency - (required) Maximum SPI clocking speed of device in Hz. - 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 - shifted clock phase (CPHA) mode + shifted clock phase (CPHA) mode. - 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 - 3-wire mode. + 3-wire mode. - spi-lsb-first - (optional) Empty property indicating device requires 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. -- 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. - spi-rx-delay-us - (optional) Microsecond delay after a read transfer. - spi-tx-delay-us - (optional) Microsecond delay after a write transfer. 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 -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. If a gpio chipselect is used for the SPI slave the gpio number will be passed From 0fb7620fba7feb977a5138f8d7f6b42514f81ea9 Mon Sep 17 00:00:00 2001 From: Masanari Iida Date: Wed, 29 Jun 2016 04:33:33 +0900 Subject: [PATCH 2/6] spi: Fix typo in devicetree/bindings/spi This patch fix spelling typos found in Documentation/devicetree/bingings/spi. Signed-off-by: Masanari Iida Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/spi/spi-davinci.txt | 2 +- Documentation/devicetree/bindings/spi/ti_qspi.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/spi/spi-davinci.txt b/Documentation/devicetree/bindings/spi/spi-davinci.txt index d1e914adcf6e..f5916c92fe91 100644 --- a/Documentation/devicetree/bindings/spi/spi-davinci.txt +++ b/Documentation/devicetree/bindings/spi/spi-davinci.txt @@ -21,7 +21,7 @@ Required properties: IP to the interrupt controller within the SoC. Possible values are 0 and 1. Manual says one of the two possible interrupt 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. - clocks: spi clk phandle diff --git a/Documentation/devicetree/bindings/spi/ti_qspi.txt b/Documentation/devicetree/bindings/spi/ti_qspi.txt index 50b14f6b53a3..e65fde4a7388 100644 --- a/Documentation/devicetree/bindings/spi/ti_qspi.txt +++ b/Documentation/devicetree/bindings/spi/ti_qspi.txt @@ -20,7 +20,7 @@ Optional properties: chipselect register and offset of that register. 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 operation. Hence, "spi-cpol" and "spi-cpha" DT properties cannot be specified in the slave nodes of TI QSPI controller without appropriate From 9b96f0704b5ad75ef26085d03934bee21d3362f0 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Sat, 2 Jul 2016 14:12:00 +0530 Subject: [PATCH 3/6] spi: spi-bfin5xx: Remove deprecated create_singlethread_workqueue The workqueue "workqueue" serves as a driver message queue. It has a single work item(&drv_data->pump_messages) and hence doesn't require ordering. Also, it is not being used on a memory reclaim path. Hence, the singlethreaded workqueue has been replaced with the use of system_wq. System workqueues have been able to handle high level of concurrency for a long time now and hence it's not required to have a singlethreaded workqueue just to gain concurrency. Unlike a dedicated per-cpu workqueue created with create_singlethread_workqueue(), system_wq allows multiple work items to overlap executions even on the same CPU; however, a per-cpu workqueue doesn't have any CPU locality or global ordering guarantee unless the target CPU is explicitly specified and thus the increase of local concurrency shouldn't make any difference. Work item has been flushed in bfin_spi_destroy_queue() to ensure that there are no pending tasks while disconnecting the driver. Signed-off-by: Bhaktipriya Shridhar Acked-by: Tejun Heo Signed-off-by: Mark Brown --- drivers/spi/spi-bfin5xx.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-bfin5xx.c b/drivers/spi/spi-bfin5xx.c index 1e91325bf39c..249c7a3677c9 100644 --- a/drivers/spi/spi-bfin5xx.c +++ b/drivers/spi/spi-bfin5xx.c @@ -67,8 +67,6 @@ struct bfin_spi_master_data { /* BFIN hookup */ struct bfin5xx_spi_master *master_info; - /* Driver message queue */ - struct workqueue_struct *workqueue; struct work_struct pump_messages; spinlock_t lock; struct list_head queue; @@ -359,7 +357,7 @@ static void bfin_spi_giveback(struct bfin_spi_master_data *drv_data) drv_data->cur_msg = NULL; drv_data->cur_transfer = 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); msg->state = NULL; @@ -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); 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); @@ -1177,12 +1175,7 @@ static int bfin_spi_init_queue(struct bfin_spi_master_data *drv_data) tasklet_init(&drv_data->pump_transfers, bfin_spi_pump_transfers, (unsigned long)drv_data); - /* init messages workqueue */ 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; } @@ -1204,7 +1197,7 @@ static int bfin_spi_start_queue(struct bfin_spi_master_data *drv_data) drv_data->cur_chip = NULL; spin_unlock_irqrestore(&drv_data->lock, flags); - queue_work(drv_data->workqueue, &drv_data->pump_messages); + schedule_work(&drv_data->pump_messages); return 0; } @@ -1246,7 +1239,7 @@ static int bfin_spi_destroy_queue(struct bfin_spi_master_data *drv_data) if (status != 0) return status; - destroy_workqueue(drv_data->workqueue); + flush_work(&drv_data->pump_messages); return 0; } From eac9837f87017c7a3a6c0a8908fdda66f7f9c076 Mon Sep 17 00:00:00 2001 From: Bhaktipriya Shridhar Date: Sat, 2 Jul 2016 14:29:41 +0530 Subject: [PATCH 4/6] spi: spi-bfin-sport: Remove deprecated create_singlethread_workqueue The workqueue "workqueue" serves as a driver message queue. It has a single work item(&drv_data->pump_messages) and hence doesn't require ordering. Also, it is not being used on a memory reclaim path. Hence, the singlethreaded workqueue has been replaced with the use of system_wq. System workqueues have been able to handle high level of concurrency for a long time now and hence it's not required to have a singlethreaded workqueue just to gain concurrency. Unlike a dedicated per-cpu workqueue created with create_singlethread_workqueue(), system_wq allows multiple work items to overlap executions even on the same CPU; however, a per-cpu workqueue doesn't have any CPU locality or global ordering guarantee unless the target CPU is explicitly specified and thus the increase of local concurrency shouldn't make any difference. Work item has been flushed in bfin_sport_spi_destroy_queue() to ensure that there are no pending tasks while disconnecting the driver. Signed-off-by: Bhaktipriya Shridhar Acked-by: Tejun Heo Signed-off-by: Mark Brown --- drivers/spi/spi-bfin-sport.c | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/drivers/spi/spi-bfin-sport.c b/drivers/spi/spi-bfin-sport.c index 6c967555a56a..01d0ba9c5942 100644 --- a/drivers/spi/spi-bfin-sport.c +++ b/drivers/spi/spi-bfin-sport.c @@ -64,8 +64,6 @@ struct bfin_sport_spi_master_data { /* Pin request list */ u16 *pin_req; - /* Driver message queue */ - struct workqueue_struct *workqueue; struct work_struct pump_messages; spinlock_t lock; struct list_head queue; @@ -300,7 +298,7 @@ bfin_sport_spi_giveback(struct bfin_sport_spi_master_data *drv_data) drv_data->cur_msg = NULL; drv_data->cur_transfer = 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); if (!drv_data->cs_change) @@ -556,7 +554,7 @@ bfin_sport_spi_transfer(struct spi_device *spi, struct spi_message *msg) list_add_tail(&msg->queue, &drv_data->queue); 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); @@ -666,12 +664,7 @@ bfin_sport_spi_init_queue(struct bfin_sport_spi_master_data *drv_data) tasklet_init(&drv_data->pump_transfers, bfin_sport_spi_pump_transfers, (unsigned long)drv_data); - /* init messages workqueue */ 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; } @@ -694,7 +687,7 @@ bfin_sport_spi_start_queue(struct bfin_sport_spi_master_data *drv_data) drv_data->cur_chip = NULL; spin_unlock_irqrestore(&drv_data->lock, flags); - queue_work(drv_data->workqueue, &drv_data->pump_messages); + schedule_work(&drv_data->pump_messages); return 0; } @@ -738,7 +731,7 @@ bfin_sport_spi_destroy_queue(struct bfin_sport_spi_master_data *drv_data) if (status) return status; - destroy_workqueue(drv_data->workqueue); + flush_work(&drv_data->pump_messages); return 0; } From 6acaadc852f10b9f13b665a5798d4f2783317f80 Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Wed, 6 Jul 2016 16:53:12 +0200 Subject: [PATCH 5/6] spi: clps711x: Driver refactor This is a complex patch for refactoring CLPS711X SPI driver. This change adds devicetree support and removes board support. Signed-off-by: Alexander Shiyan Signed-off-by: Arnd Bergmann Signed-off-by: Mark Brown --- drivers/spi/spi-clps711x.c | 69 ++++++++++++++------------------------ 1 file changed, 26 insertions(+), 43 deletions(-) diff --git a/drivers/spi/spi-clps711x.c b/drivers/spi/spi-clps711x.c index 8c30de0315e7..18193df2eba8 100644 --- a/drivers/spi/spi-clps711x.c +++ b/drivers/spi/spi-clps711x.c @@ -1,7 +1,7 @@ /* * CLPS711X SPI bus driver * - * Copyright (C) 2012-2014 Alexander Shiyan + * Copyright (C) 2012-2016 Alexander Shiyan * * 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 @@ -12,7 +12,6 @@ #include #include #include -#include #include #include #include @@ -20,9 +19,8 @@ #include #include #include -#include -#define DRIVER_NAME "spi-clps711x" +#define DRIVER_NAME "clps711x-spi" #define SYNCIO_FRMLEN(x) ((x) << 8) #define SYNCIO_TXFRMEN (1 << 14) @@ -40,6 +38,17 @@ struct spi_clps711x_data { 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 */ 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) static int spi_clps711x_probe(struct platform_device *pdev) { struct spi_clps711x_data *hw; - struct spi_clps711x_pdata *pdata = dev_get_platdata(&pdev->dev); struct spi_master *master; struct resource *res; - int i, 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; - } + int irq, ret; irq = platform_get_irq(pdev, 0); if (irq < 0) @@ -127,40 +125,24 @@ static int spi_clps711x_probe(struct platform_device *pdev) if (!master) return -ENOMEM; - master->cs_gpios = devm_kzalloc(&pdev->dev, sizeof(int) * - pdata->num_chipselect, GFP_KERNEL); - if (!master->cs_gpios) { - ret = -ENOMEM; - goto err_out; - } - - master->bus_num = pdev->id; + master->bus_num = -1; master->mode_bits = SPI_CPHA | SPI_CS_HIGH; 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->prepare_message = spi_clps711x_prepare_message; master->transfer_one = spi_clps711x_transfer_one; 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); if (IS_ERR(hw->spi_clk)) { ret = PTR_ERR(hw->spi_clk); 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)) { ret = PTR_ERR(hw->syscon); goto err_out; @@ -185,14 +167,8 @@ static int spi_clps711x_probe(struct platform_device *pdev) goto err_out; ret = devm_spi_register_master(&pdev->dev, master); - if (!ret) { - dev_info(&pdev->dev, - "SPI bus driver initialized. Master clock %u Hz\n", - master->max_speed_hz); + if (!ret) return 0; - } - - dev_err(&pdev->dev, "Failed to register master\n"); err_out: spi_master_put(master); @@ -200,9 +176,16 @@ err_out: 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 = { .driver = { .name = DRIVER_NAME, + .of_match_table = clps711x_spi_dt_ids, }, .probe = spi_clps711x_probe, }; From ea2ff61ba3f8239483f5cd823ac0113d194b469f Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 6 Jul 2016 16:53:13 +0200 Subject: [PATCH 6/6] spi: add binding for clps711x SPI This documents the binding used by Alexander Shiyan's DT support for the clps711x SPI controller. I've left the file name to match the ARM platform port name "clps711x" for consistency with the other bindings, even though the compatible string refers to the later ep7309 chip. Linux no longer supports the old clps711x and ep72xx product lines, but we still use the name. The entire family is now discontinued by the manufacturer. Signed-off-by: Arnd Bergmann Signed-off-by: Mark Brown --- .../devicetree/bindings/spi/spi-clps711x.txt | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Documentation/devicetree/bindings/spi/spi-clps711x.txt diff --git a/Documentation/devicetree/bindings/spi/spi-clps711x.txt b/Documentation/devicetree/bindings/spi/spi-clps711x.txt new file mode 100644 index 000000000000..4c3ec13f423f --- /dev/null +++ b/Documentation/devicetree/bindings/spi/spi-clps711x.txt @@ -0,0 +1,33 @@ +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>; +}; +