if (!spi)
return;
- if (spi->dev.of_node)
+ if (spi->dev.of_node) {
of_node_clear_flag(spi->dev.of_node, OF_POPULATED);
+ of_node_put(spi->dev.of_node);
+ }
if (ACPI_COMPANION(&spi->dev))
acpi_device_clear_enumerated(ACPI_COMPANION(&spi->dev));
device_unregister(&spi->dev);
if (!n)
return -EINVAL;
- bi = kzalloc(n * sizeof(*bi), GFP_KERNEL);
+ bi = kcalloc(n, sizeof(*bi), GFP_KERNEL);
if (!bi)
return -ENOMEM;
if (spi->mode & SPI_CS_HIGH)
enable = !enable;
- if (gpio_is_valid(spi->cs_gpio))
+ if (gpio_is_valid(spi->cs_gpio)) {
gpio_set_value(spi->cs_gpio, !enable);
- else if (spi->master->set_cs)
+ /* Some SPI masters need both GPIO CS & slave_select */
+ if ((spi->master->flags & SPI_MASTER_GPIO_SS) &&
+ spi->master->set_cs)
+ spi->master->set_cs(spi, !enable);
+ } else if (spi->master->set_cs) {
spi->master->set_cs(spi, !enable);
+ }
}
#ifdef CONFIG_HAS_DMA
int desc_len;
int sgs;
struct page *vm_page;
+ struct scatterlist *sg;
void *sg_buf;
size_t min;
int i, ret;
if (ret != 0)
return ret;
+ sg = &sgt->sgl[0];
for (i = 0; i < sgs; i++) {
if (vmalloced_buf || kmap_buf) {
sg_free_table(sgt);
return -ENOMEM;
}
- sg_set_page(&sgt->sgl[i], vm_page,
+ sg_set_page(sg, vm_page,
min, offset_in_page(buf));
} else {
min = min_t(size_t, len, desc_len);
sg_buf = buf;
- sg_set_buf(&sgt->sgl[i], sg_buf, min);
+ sg_set_buf(sg, sg_buf, min);
}
buf += min;
len -= min;
+ sg = sg_next(sg);
}
ret = dma_map_sg(dev, sgt->sgl, sgt->nents, dir);
if (master->dma_tx)
tx_dev = master->dma_tx->device->dev;
else
- tx_dev = &master->dev;
+ tx_dev = master->dev.parent;
if (master->dma_rx)
rx_dev = master->dma_rx->device->dev;
else
- rx_dev = &master->dev;
+ rx_dev = master->dev.parent;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (!master->can_dma(master, msg->spi, xfer))
if (master->dma_tx)
tx_dev = master->dma_tx->device->dev;
else
- tx_dev = &master->dev;
+ tx_dev = master->dev.parent;
if (master->dma_rx)
rx_dev = master->dma_rx->device->dev;
else
- rx_dev = &master->dev;
+ rx_dev = master->dev.parent;
list_for_each_entry(xfer, &msg->transfers, transfer_list) {
if (!master->can_dma(master, msg->spi, xfer))
if (msg->status != -EINPROGRESS)
goto out;
- if (xfer->delay_usecs)
- udelay(xfer->delay_usecs);
+ 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->cs_change) {
if (list_is_last(&xfer->transfer_list,
/*-------------------------------------------------------------------------*/
#if defined(CONFIG_OF)
-static struct spi_device *
-of_register_spi_device(struct spi_master *master, struct device_node *nc)
+static int of_spi_parse_dt(struct spi_master *master, struct spi_device *spi,
+ struct device_node *nc)
{
- struct spi_device *spi;
- int rc;
u32 value;
-
- /* Alloc an spi_device */
- spi = spi_alloc_device(master);
- if (!spi) {
- dev_err(&master->dev, "spi_device alloc error for %s\n",
- nc->full_name);
- rc = -ENOMEM;
- goto err_out;
- }
-
- /* Select device driver */
- rc = of_modalias_node(nc, spi->modalias,
- sizeof(spi->modalias));
- if (rc < 0) {
- dev_err(&master->dev, "cannot find modalias for %s\n",
- nc->full_name);
- goto err_out;
- }
+ int rc;
/* Device address */
rc = of_property_read_u32(nc, "reg", &value);
if (rc) {
dev_err(&master->dev, "%s has no valid 'reg' property (%d)\n",
nc->full_name, rc);
- goto err_out;
+ return rc;
}
spi->chip_select = value;
if (rc) {
dev_err(&master->dev, "%s has no valid 'spi-max-frequency' property (%d)\n",
nc->full_name, rc);
- goto err_out;
+ return rc;
}
spi->max_speed_hz = value;
+ return 0;
+}
+
+static struct spi_device *
+of_register_spi_device(struct spi_master *master, struct device_node *nc)
+{
+ struct spi_device *spi;
+ int rc;
+
+ /* Alloc an spi_device */
+ spi = spi_alloc_device(master);
+ if (!spi) {
+ dev_err(&master->dev, "spi_device alloc error for %s\n",
+ nc->full_name);
+ rc = -ENOMEM;
+ goto err_out;
+ }
+
+ /* Select device driver */
+ rc = of_modalias_node(nc, spi->modalias,
+ sizeof(spi->modalias));
+ if (rc < 0) {
+ dev_err(&master->dev, "cannot find modalias for %s\n",
+ nc->full_name);
+ goto err_out;
+ }
+
+ rc = of_spi_parse_dt(master, spi, nc);
+ if (rc)
+ goto err_out;
+
/* Store a pointer to the node in the device structure */
of_node_get(nc);
spi->dev.of_node = nc;
if (rc) {
dev_err(&master->dev, "spi_device register error %s\n",
nc->full_name);
- goto err_out;
+ goto err_of_node_put;
}
return spi;
+err_of_node_put:
+ of_node_put(nc);
err_out:
spi_dev_put(spi);
return ERR_PTR(rc);