X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=drivers%2Fspi%2Fspi.c;h=147ca28faedf29d4837c2ffa8e4f99916c98cfbb;hb=0dd998469638fbcb10ca379e8894e227d9a5cb22;hp=926b68aa45d3ed2053bbc128a16d5935d8108be8;hpb=c2b43854aad9e52b422e6c6342a1da2261f98fa5;p=platform%2Fkernel%2Flinux-rpi.git diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c index 926b68a..147ca28 100644 --- a/drivers/spi/spi.c +++ b/drivers/spi/spi.c @@ -451,6 +451,47 @@ int __spi_register_driver(struct module *owner, struct spi_driver *sdrv) { sdrv->driver.owner = owner; sdrv->driver.bus = &spi_bus_type; + + /* + * For Really Good Reasons we use spi: modaliases not of: + * modaliases for DT so module autoloading won't work if we + * don't have a spi_device_id as well as a compatible string. + */ + if (sdrv->driver.of_match_table) { + const struct of_device_id *of_id; + + for (of_id = sdrv->driver.of_match_table; of_id->compatible[0]; + of_id++) { + const char *of_name; + + /* Strip off any vendor prefix */ + of_name = strnchr(of_id->compatible, + sizeof(of_id->compatible), ','); + if (of_name) + of_name++; + else + of_name = of_id->compatible; + + if (sdrv->id_table) { + const struct spi_device_id *spi_id; + + for (spi_id = sdrv->id_table; spi_id->name[0]; + spi_id++) + if (strcmp(spi_id->name, of_name) == 0) + break; + + if (spi_id->name[0]) + continue; + } else { + if (strcmp(sdrv->driver.name, of_name) == 0) + continue; + } + + pr_warn("SPI driver %s has no spi_device_id for %s\n", + sdrv->driver.name, of_id->compatible); + } + } + return driver_register(&sdrv->driver); } EXPORT_SYMBOL_GPL(__spi_register_driver); @@ -827,12 +868,9 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) spi->controller->last_cs_enable = enable; spi->controller->last_cs_mode_high = spi->mode & SPI_CS_HIGH; - if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || - !spi->controller->set_cs_timing) { - if (activate) - spi_delay_exec(&spi->cs_setup, NULL); - else - spi_delay_exec(&spi->cs_hold, NULL); + if ((spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || + !spi->controller->set_cs_timing) && !activate) { + spi_delay_exec(&spi->cs_hold, NULL); } if (spi->mode & SPI_CS_HIGH) @@ -874,7 +912,9 @@ static void spi_set_cs(struct spi_device *spi, bool enable, bool force) if (spi->cs_gpiod || gpio_is_valid(spi->cs_gpio) || !spi->controller->set_cs_timing) { - if (!activate) + if (activate) + spi_delay_exec(&spi->cs_setup, NULL); + else spi_delay_exec(&spi->cs_inactive, NULL); } } @@ -902,10 +942,10 @@ int spi_map_buf(struct spi_controller *ctlr, struct device *dev, int i, ret; if (vmalloced_buf || kmap_buf) { - desc_len = min_t(int, max_seg_size, PAGE_SIZE); + desc_len = min_t(unsigned long, max_seg_size, PAGE_SIZE); sgs = DIV_ROUND_UP(len + offset_in_page(buf), desc_len); } else if (virt_addr_valid(buf)) { - desc_len = min_t(int, max_seg_size, ctlr->max_dma_len); + desc_len = min_t(size_t, max_seg_size, ctlr->max_dma_len); sgs = DIV_ROUND_UP(len, desc_len); } else { return -EINVAL; @@ -1032,11 +1072,15 @@ static int __spi_unmap_msg(struct spi_controller *ctlr, struct spi_message *msg) if (ctlr->dma_tx) tx_dev = ctlr->dma_tx->device->dev; + else if (ctlr->dma_map_dev) + tx_dev = ctlr->dma_map_dev; else tx_dev = ctlr->dev.parent; if (ctlr->dma_rx) rx_dev = ctlr->dma_rx->device->dev; + else if (ctlr->dma_map_dev) + rx_dev = ctlr->dma_map_dev; else rx_dev = ctlr->dev.parent; @@ -2905,9 +2949,9 @@ free_bus_id: } EXPORT_SYMBOL_GPL(spi_register_controller); -static void devm_spi_unregister(void *ctlr) +static void devm_spi_unregister(struct device *dev, void *res) { - spi_unregister_controller(ctlr); + spi_unregister_controller(*(struct spi_controller **)res); } /** @@ -2926,13 +2970,22 @@ static void devm_spi_unregister(void *ctlr) int devm_spi_register_controller(struct device *dev, struct spi_controller *ctlr) { + struct spi_controller **ptr; int ret; + ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL); + if (!ptr) + return -ENOMEM; + ret = spi_register_controller(ctlr); - if (ret) - return ret; + if (!ret) { + *ptr = ctlr; + devres_add(dev, ptr); + } else { + devres_free(ptr); + } - return devm_add_action_or_reset(dev, devm_spi_unregister, ctlr); + return ret; } EXPORT_SYMBOL_GPL(devm_spi_register_controller); @@ -2979,12 +3032,6 @@ void spi_unregister_controller(struct spi_controller *ctlr) device_del(&ctlr->dev); - /* Release the last reference on the controller if its driver - * has not yet been converted to devm_spi_alloc_master/slave(). - */ - if (!ctlr->devm_allocated) - put_device(&ctlr->dev); - /* free bus id */ mutex_lock(&board_lock); if (found == ctlr) @@ -2993,6 +3040,12 @@ void spi_unregister_controller(struct spi_controller *ctlr) if (IS_ENABLED(CONFIG_SPI_DYNAMIC)) mutex_unlock(&ctlr->add_lock); + + /* Release the last reference on the controller if its driver + * has not yet been converted to devm_spi_alloc_master/slave(). + */ + if (!ctlr->devm_allocated) + put_device(&ctlr->dev); } EXPORT_SYMBOL_GPL(spi_unregister_controller); @@ -3425,6 +3478,7 @@ static int __spi_validate_bits_per_word(struct spi_controller *ctlr, */ int spi_setup(struct spi_device *spi) { + struct spi_controller *ctlr = spi->controller; unsigned bad_bits, ugly_bits; int status; @@ -3446,6 +3500,14 @@ int spi_setup(struct spi_device *spi) (SPI_TX_DUAL | SPI_TX_QUAD | SPI_TX_OCTAL | SPI_RX_DUAL | SPI_RX_QUAD | SPI_RX_OCTAL))) return -EINVAL; + + if (ctlr->use_gpio_descriptors && ctlr->cs_gpiods && + ctlr->cs_gpiods[spi->chip_select] && !(spi->mode & SPI_CS_HIGH)) { + dev_dbg(&spi->dev, + "setup: forcing CS_HIGH (use_gpio_descriptors)\n"); + spi->mode |= SPI_CS_HIGH; + } + /* help drivers fail *cleanly* when they need options * that aren't supported with their current controller * SPI_CS_WORD has a fallback software implementation,