Merge remote-tracking branch 'spi/topic/pump-rt' into spi-next
[linux-block.git] / drivers / spi / spi.c
index 18f70e4bbb3186b0c68fe8f6c19c3acc0b8153ed..91673351bcf396bc69a8026a5ed6496bd2422d7f 100644 (file)
@@ -1090,6 +1090,60 @@ static int spi_transfer_wait(struct spi_controller *ctlr,
        return 0;
 }
 
+static void _spi_transfer_delay_ns(u32 ns)
+{
+       if (!ns)
+               return;
+       if (ns <= 1000) {
+               ndelay(ns);
+       } else {
+               u32 us = DIV_ROUND_UP(ns, 1000);
+
+               if (us <= 10)
+                       udelay(us);
+               else
+                       usleep_range(us, us + DIV_ROUND_UP(us, 10));
+       }
+}
+
+static void _spi_transfer_cs_change_delay(struct spi_message *msg,
+                                         struct spi_transfer *xfer)
+{
+       u32 delay = xfer->cs_change_delay;
+       u32 unit = xfer->cs_change_delay_unit;
+       u32 hz;
+
+       /* return early on "fast" mode - for everything but USECS */
+       if (!delay && unit != SPI_DELAY_UNIT_USECS)
+               return;
+
+       switch (unit) {
+       case SPI_DELAY_UNIT_USECS:
+               /* for compatibility use default of 10us */
+               if (!delay)
+                       delay = 10000;
+               else
+                       delay *= 1000;
+               break;
+       case SPI_DELAY_UNIT_NSECS: /* nothing to do here */
+               break;
+       case SPI_DELAY_UNIT_SCK:
+               /* if there is no effective speed know, then approximate
+                * by underestimating with half the requested hz
+                */
+               hz = xfer->effective_speed_hz ?: xfer->speed_hz / 2;
+               delay *= DIV_ROUND_UP(1000000000, hz);
+               break;
+       default:
+               dev_err_once(&msg->spi->dev,
+                            "Use of unsupported delay unit %i, using default of 10us\n",
+                            xfer->cs_change_delay_unit);
+               delay = 10000;
+       }
+       /* now sleep for the requested amount of time */
+       _spi_transfer_delay_ns(delay);
+}
+
 /*
  * spi_transfer_one_message - Default implementation of transfer_one_message()
  *
@@ -1148,14 +1202,8 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
                if (msg->status != -EINPROGRESS)
                        goto out;
 
-               if (xfer->delay_usecs) {
-                       u16 us = xfer->delay_usecs;
-
-                       if (us <= 10)
-                               udelay(us);
-                       else
-                               usleep_range(us, us + DIV_ROUND_UP(us, 10));
-               }
+               if (xfer->delay_usecs)
+                       _spi_transfer_delay_ns(xfer->delay_usecs * 1000);
 
                if (xfer->cs_change) {
                        if (list_is_last(&xfer->transfer_list,
@@ -1163,7 +1211,7 @@ static int spi_transfer_one_message(struct spi_controller *ctlr,
                                keep_cs = true;
                        } else {
                                spi_set_cs(msg->spi, false);
-                               udelay(10);
+                               _spi_transfer_cs_change_delay(msg, xfer);
                                spi_set_cs(msg->spi, true);
                        }
                }
@@ -1181,10 +1229,10 @@ out:
        if (msg->status && ctlr->handle_err)
                ctlr->handle_err(ctlr, msg);
 
-       spi_finalize_current_message(ctlr);
-
        spi_res_release(ctlr, msg);
 
+       spi_finalize_current_message(ctlr);
+
        return ret;
 }
 
@@ -1307,10 +1355,15 @@ static void __spi_pump_messages(struct spi_controller *ctlr, bool in_kthread)
                ret = ctlr->prepare_transfer_hardware(ctlr);
                if (ret) {
                        dev_err(&ctlr->dev,
-                               "failed to prepare transfer hardware\n");
+                               "failed to prepare transfer hardware: %d\n",
+                               ret);
 
                        if (ctlr->auto_runtime_pm)
                                pm_runtime_put(ctlr->dev.parent);
+
+                       ctlr->cur_msg->status = ret;
+                       spi_finalize_current_message(ctlr);
+
                        mutex_unlock(&ctlr->io_mutex);
                        return;
                }
@@ -1818,9 +1871,18 @@ static void of_register_spi_devices(struct spi_controller *ctlr) { }
 #endif
 
 #ifdef CONFIG_ACPI
-static void acpi_spi_parse_apple_properties(struct spi_device *spi)
+struct acpi_spi_lookup {
+       struct spi_controller   *ctlr;
+       u32                     max_speed_hz;
+       u32                     mode;
+       int                     irq;
+       u8                      bits_per_word;
+       u8                      chip_select;
+};
+
+static void acpi_spi_parse_apple_properties(struct acpi_device *dev,
+                                           struct acpi_spi_lookup *lookup)
 {
-       struct acpi_device *dev = ACPI_COMPANION(&spi->dev);
        const union acpi_object *obj;
 
        if (!x86_apple_machine)
@@ -1828,35 +1890,46 @@ static void acpi_spi_parse_apple_properties(struct spi_device *spi)
 
        if (!acpi_dev_get_property(dev, "spiSclkPeriod", ACPI_TYPE_BUFFER, &obj)
            && obj->buffer.length >= 4)
-               spi->max_speed_hz  = NSEC_PER_SEC / *(u32 *)obj->buffer.pointer;
+               lookup->max_speed_hz  = NSEC_PER_SEC / *(u32 *)obj->buffer.pointer;
 
        if (!acpi_dev_get_property(dev, "spiWordSize", ACPI_TYPE_BUFFER, &obj)
            && obj->buffer.length == 8)
-               spi->bits_per_word = *(u64 *)obj->buffer.pointer;
+               lookup->bits_per_word = *(u64 *)obj->buffer.pointer;
 
        if (!acpi_dev_get_property(dev, "spiBitOrder", ACPI_TYPE_BUFFER, &obj)
            && obj->buffer.length == 8 && !*(u64 *)obj->buffer.pointer)
-               spi->mode |= SPI_LSB_FIRST;
+               lookup->mode |= SPI_LSB_FIRST;
 
        if (!acpi_dev_get_property(dev, "spiSPO", ACPI_TYPE_BUFFER, &obj)
            && obj->buffer.length == 8 &&  *(u64 *)obj->buffer.pointer)
-               spi->mode |= SPI_CPOL;
+               lookup->mode |= SPI_CPOL;
 
        if (!acpi_dev_get_property(dev, "spiSPH", ACPI_TYPE_BUFFER, &obj)
            && obj->buffer.length == 8 &&  *(u64 *)obj->buffer.pointer)
-               spi->mode |= SPI_CPHA;
+               lookup->mode |= SPI_CPHA;
 }
 
 static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
 {
-       struct spi_device *spi = data;
-       struct spi_controller *ctlr = spi->controller;
+       struct acpi_spi_lookup *lookup = data;
+       struct spi_controller *ctlr = lookup->ctlr;
 
        if (ares->type == ACPI_RESOURCE_TYPE_SERIAL_BUS) {
                struct acpi_resource_spi_serialbus *sb;
+               acpi_handle parent_handle;
+               acpi_status status;
 
                sb = &ares->data.spi_serial_bus;
                if (sb->type == ACPI_RESOURCE_SERIAL_TYPE_SPI) {
+
+                       status = acpi_get_handle(NULL,
+                                                sb->resource_source.string_ptr,
+                                                &parent_handle);
+
+                       if (ACPI_FAILURE(status) ||
+                           ACPI_HANDLE(ctlr->dev.parent) != parent_handle)
+                               return -ENODEV;
+
                        /*
                         * ACPI DeviceSelection numbering is handled by the
                         * host controller driver in Windows and can vary
@@ -1869,25 +1942,25 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
                                                sb->device_selection);
                                if (cs < 0)
                                        return cs;
-                               spi->chip_select = cs;
+                               lookup->chip_select = cs;
                        } else {
-                               spi->chip_select = sb->device_selection;
+                               lookup->chip_select = sb->device_selection;
                        }
 
-                       spi->max_speed_hz = sb->connection_speed;
+                       lookup->max_speed_hz = sb->connection_speed;
 
                        if (sb->clock_phase == ACPI_SPI_SECOND_PHASE)
-                               spi->mode |= SPI_CPHA;
+                               lookup->mode |= SPI_CPHA;
                        if (sb->clock_polarity == ACPI_SPI_START_HIGH)
-                               spi->mode |= SPI_CPOL;
+                               lookup->mode |= SPI_CPOL;
                        if (sb->device_polarity == ACPI_SPI_ACTIVE_HIGH)
-                               spi->mode |= SPI_CS_HIGH;
+                               lookup->mode |= SPI_CS_HIGH;
                }
-       } else if (spi->irq < 0) {
+       } else if (lookup->irq < 0) {
                struct resource r;
 
                if (acpi_dev_resource_interrupt(ares, 0, &r))
-                       spi->irq = r.start;
+                       lookup->irq = r.start;
        }
 
        /* Always tell the ACPI core to skip this resource */
@@ -1897,7 +1970,9 @@ static int acpi_spi_add_resource(struct acpi_resource *ares, void *data)
 static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,
                                            struct acpi_device *adev)
 {
+       acpi_handle parent_handle = NULL;
        struct list_head resource_list;
+       struct acpi_spi_lookup lookup = {};
        struct spi_device *spi;
        int ret;
 
@@ -1905,28 +1980,42 @@ static acpi_status acpi_register_spi_device(struct spi_controller *ctlr,
            acpi_device_enumerated(adev))
                return AE_OK;
 
-       spi = spi_alloc_device(ctlr);
-       if (!spi) {
-               dev_err(&ctlr->dev, "failed to allocate SPI device for %s\n",
-                       dev_name(&adev->dev));
-               return AE_NO_MEMORY;
-       }
-
-       ACPI_COMPANION_SET(&spi->dev, adev);
-       spi->irq = -1;
+       lookup.ctlr             = ctlr;
+       lookup.irq              = -1;
 
        INIT_LIST_HEAD(&resource_list);
        ret = acpi_dev_get_resources(adev, &resource_list,
-                                    acpi_spi_add_resource, spi);
+                                    acpi_spi_add_resource, &lookup);
        acpi_dev_free_resource_list(&resource_list);
 
-       acpi_spi_parse_apple_properties(spi);
+       if (ret < 0)
+               /* found SPI in _CRS but it points to another controller */
+               return AE_OK;
 
-       if (ret < 0 || !spi->max_speed_hz) {
-               spi_dev_put(spi);
+       if (!lookup.max_speed_hz &&
+           !ACPI_FAILURE(acpi_get_parent(adev->handle, &parent_handle)) &&
+           ACPI_HANDLE(ctlr->dev.parent) == parent_handle) {
+               /* Apple does not use _CRS but nested devices for SPI slaves */
+               acpi_spi_parse_apple_properties(adev, &lookup);
+       }
+
+       if (!lookup.max_speed_hz)
                return AE_OK;
+
+       spi = spi_alloc_device(ctlr);
+       if (!spi) {
+               dev_err(&ctlr->dev, "failed to allocate SPI device for %s\n",
+                       dev_name(&adev->dev));
+               return AE_NO_MEMORY;
        }
 
+       ACPI_COMPANION_SET(&spi->dev, adev);
+       spi->max_speed_hz       = lookup.max_speed_hz;
+       spi->mode               = lookup.mode;
+       spi->irq                = lookup.irq;
+       spi->bits_per_word      = lookup.bits_per_word;
+       spi->chip_select        = lookup.chip_select;
+
        acpi_set_modalias(adev, acpi_device_hid(adev), spi->modalias,
                          sizeof(spi->modalias));
 
@@ -1958,6 +2047,8 @@ static acpi_status acpi_spi_add_device(acpi_handle handle, u32 level,
        return acpi_register_spi_device(ctlr, adev);
 }
 
+#define SPI_ACPI_ENUMERATE_MAX_DEPTH           32
+
 static void acpi_register_spi_devices(struct spi_controller *ctlr)
 {
        acpi_status status;
@@ -1967,7 +2058,8 @@ static void acpi_register_spi_devices(struct spi_controller *ctlr)
        if (!handle)
                return;
 
-       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, handle, 1,
+       status = acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
+                                    SPI_ACPI_ENUMERATE_MAX_DEPTH,
                                     acpi_spi_add_device, NULL, ctlr, NULL);
        if (ACPI_FAILURE(status))
                dev_warn(&ctlr->dev, "failed to enumerate SPI slaves\n");
@@ -2300,11 +2392,6 @@ int spi_register_controller(struct spi_controller *ctlr)
        if (status)
                return status;
 
-       /* even if it's just one always-selected device, there must
-        * be at least one chipselect
-        */
-       if (ctlr->num_chipselect == 0)
-               return -EINVAL;
        if (ctlr->bus_num >= 0) {
                /* devices with a fixed bus num must check-in with the num */
                mutex_lock(&board_lock);
@@ -2375,6 +2462,13 @@ int spi_register_controller(struct spi_controller *ctlr)
                }
        }
 
+       /*
+        * Even if it's just one always-selected device, there must
+        * be at least one chipselect.
+        */
+       if (!ctlr->num_chipselect)
+               return -EINVAL;
+
        status = device_add(&ctlr->dev);
        if (status < 0) {
                /* free bus id */
@@ -2484,7 +2578,6 @@ void spi_unregister_controller(struct spi_controller *ctlr)
 {
        struct spi_controller *found;
        int id = ctlr->bus_num;
-       int dummy;
 
        /* First make sure that this controller was ever added */
        mutex_lock(&board_lock);
@@ -2498,7 +2591,7 @@ void spi_unregister_controller(struct spi_controller *ctlr)
        list_del(&ctlr->list);
        mutex_unlock(&board_lock);
 
-       dummy = device_for_each_child(&ctlr->dev, NULL, __unregister);
+       device_for_each_child(&ctlr->dev, NULL, __unregister);
        device_unregister(&ctlr->dev);
        /* free bus id */
        mutex_lock(&board_lock);
@@ -2647,12 +2740,9 @@ EXPORT_SYMBOL_GPL(spi_res_add);
  */
 void spi_res_release(struct spi_controller *ctlr, struct spi_message *message)
 {
-       struct spi_res *res;
-
-       while (!list_empty(&message->resources)) {
-               res = list_last_entry(&message->resources,
-                                     struct spi_res, entry);
+       struct spi_res *res, *tmp;
 
+       list_for_each_entry_safe_reverse(res, tmp, &message->resources, entry) {
                if (res->release)
                        res->release(ctlr, message, res->data);
 
@@ -2716,8 +2806,7 @@ struct spi_replaced_transfers *spi_replace_transfers(
 
        /* allocate the structure using spi_res */
        rxfer = spi_res_alloc(msg->spi, __spi_replace_transfers_release,
-                             insert * sizeof(struct spi_transfer)
-                             + sizeof(struct spi_replaced_transfers)
+                             struct_size(rxfer, inserted_transfers, insert)
                              + extradatasize,
                              gfp);
        if (!rxfer)
@@ -3102,6 +3191,7 @@ static int __spi_validate(struct spi_device *spi, struct spi_message *message)
         */
        message->frame_length = 0;
        list_for_each_entry(xfer, &message->transfers, transfer_list) {
+               xfer->effective_speed_hz = 0;
                message->frame_length += xfer->len;
                if (!xfer->bits_per_word)
                        xfer->bits_per_word = spi->bits_per_word;
@@ -3781,4 +3871,3 @@ err0:
  * include needing to have boardinfo data structures be much more public.
  */
 postcore_initcall(spi_init);
-