spi_s3c24xx: fix clock rate calculation
[safe/jmp/linux-2.6] / drivers / spi / spi.c
index 3734dc9..70845cc 100644 (file)
@@ -47,7 +47,7 @@ modalias_show(struct device *dev, struct device_attribute *a, char *buf)
 {
        const struct spi_device *spi = to_spi_device(dev);
 
-       return snprintf(buf, BUS_ID_SIZE + 1, "%s\n", spi->modalias);
+       return sprintf(buf, "%s\n", spi->modalias);
 }
 
 static struct device_attribute spi_dev_attrs[] = {
@@ -63,7 +63,7 @@ static int spi_match_device(struct device *dev, struct device_driver *drv)
 {
        const struct spi_device *spi = to_spi_device(dev);
 
-       return strncmp(spi->modalias, drv->name, BUS_ID_SIZE) == 0;
+       return strcmp(spi->modalias, drv->name) == 0;
 }
 
 static int spi_uevent(struct device *dev, struct kobj_uevent_env *env)
@@ -243,8 +243,7 @@ int spi_add_device(struct spi_device *spi)
        }
 
        /* Set the bus ID string */
-       snprintf(spi->dev.bus_id, sizeof spi->dev.bus_id,
-                       "%s.%u", spi->master->dev.bus_id,
+       dev_set_name(&spi->dev, "%s.%u", dev_name(&spi->master->dev),
                        spi->chip_select);
 
 
@@ -254,7 +253,7 @@ int spi_add_device(struct spi_device *spi)
         */
        mutex_lock(&spi_add_lock);
 
-       if (bus_find_device_by_name(&spi_bus_type, NULL, spi->dev.bus_id)
+       if (bus_find_device_by_name(&spi_bus_type, NULL, dev_name(&spi->dev))
                        != NULL) {
                dev_err(dev, "chipselect %d already in use\n",
                                spi->chip_select);
@@ -266,10 +265,10 @@ int spi_add_device(struct spi_device *spi)
         * normally rely on the device being setup.  Devices
         * using SPI_CS_HIGH can't coexist well otherwise...
         */
-       status = spi->master->setup(spi);
+       status = spi_setup(spi);
        if (status < 0) {
                dev_err(dev, "can't %s %s, status %d\n",
-                               "setup", spi->dev.bus_id, status);
+                               "setup", dev_name(&spi->dev), status);
                goto done;
        }
 
@@ -277,9 +276,9 @@ int spi_add_device(struct spi_device *spi)
        status = device_add(&spi->dev);
        if (status < 0)
                dev_err(dev, "can't %s %s, status %d\n",
-                               "add", spi->dev.bus_id, status);
+                               "add", dev_name(&spi->dev), status);
        else
-               dev_dbg(dev, "registered child %s\n", spi->dev.bus_id);
+               dev_dbg(dev, "registered child %s\n", dev_name(&spi->dev));
 
 done:
        mutex_unlock(&spi_add_lock);
@@ -504,12 +503,11 @@ int spi_register_master(struct spi_master *master)
        /* register the device, then userspace will see it.
         * registration fails if the bus ID is in use.
         */
-       snprintf(master->dev.bus_id, sizeof master->dev.bus_id,
-               "spi%u", master->bus_num);
+       dev_set_name(&master->dev, "spi%u", master->bus_num);
        status = device_add(&master->dev);
        if (status < 0)
                goto done;
-       dev_dbg(dev, "registered master %s%s\n", master->dev.bus_id,
+       dev_dbg(dev, "registered master %s%s\n", dev_name(&master->dev),
                        dynamic ? " (dynamic)" : "");
 
        /* populate children from any spi device tables */
@@ -585,6 +583,70 @@ EXPORT_SYMBOL_GPL(spi_busnum_to_master);
 
 /*-------------------------------------------------------------------------*/
 
+/* Core methods for SPI master protocol drivers.  Some of the
+ * other core methods are currently defined as inline functions.
+ */
+
+/**
+ * spi_setup - setup SPI mode and clock rate
+ * @spi: the device whose settings are being modified
+ * Context: can sleep, and no requests are queued to the device
+ *
+ * SPI protocol drivers may need to update the transfer mode if the
+ * device doesn't work with its default.  They may likewise need
+ * to update clock rates or word sizes from initial values.  This function
+ * changes those settings, and must be called from a context that can sleep.
+ * Except for SPI_CS_HIGH, which takes effect immediately, the changes take
+ * effect the next time the device is selected and data is transferred to
+ * or from it.  When this function returns, the spi device is deselected.
+ *
+ * Note that this call will fail if the protocol driver specifies an option
+ * that the underlying controller or its driver does not support.  For
+ * example, not all hardware supports wire transfers using nine bit words,
+ * LSB-first wire encoding, or active-high chipselects.
+ */
+int spi_setup(struct spi_device *spi)
+{
+       unsigned        bad_bits;
+       int             status;
+
+       /* help drivers fail *cleanly* when they need options
+        * that aren't supported with their current master
+        */
+       bad_bits = spi->mode & ~spi->master->mode_bits;
+       if (bad_bits) {
+               dev_dbg(&spi->dev, "setup: unsupported mode bits %x\n",
+                       bad_bits);
+               return -EINVAL;
+       }
+
+       if (!spi->bits_per_word)
+               spi->bits_per_word = 8;
+
+       status = spi->master->setup(spi);
+
+       dev_dbg(&spi->dev, "setup mode %d, %s%s%s%s"
+                               "%u bits/w, %u Hz max --> %d\n",
+                       (int) (spi->mode & (SPI_CPOL | SPI_CPHA)),
+                       (spi->mode & SPI_CS_HIGH) ? "cs_high, " : "",
+                       (spi->mode & SPI_LSB_FIRST) ? "lsb, " : "",
+                       (spi->mode & SPI_3WIRE) ? "3wire, " : "",
+                       (spi->mode & SPI_LOOP) ? "loopback, " : "",
+                       spi->bits_per_word, spi->max_speed_hz,
+                       status);
+
+       return status;
+}
+EXPORT_SYMBOL_GPL(spi_setup);
+
+
+/*-------------------------------------------------------------------------*/
+
+/* Utility methods for SPI master protocol drivers, layered on
+ * top of the core.  Some other utility methods are defined as
+ * inline functions.
+ */
+
 static void spi_complete(void *arg)
 {
        complete(arg);
@@ -638,8 +700,8 @@ static u8   *buf;
  * @spi: device with which data will be exchanged
  * @txbuf: data to be written (need not be dma-safe)
  * @n_tx: size of txbuf, in bytes
- * @rxbuf: buffer into which data will be read
- * @n_rx: size of rxbuf, in bytes (need not be dma-safe)
+ * @rxbuf: buffer into which data will be read (need not be dma-safe)
+ * @n_rx: size of rxbuf, in bytes
  * Context: can sleep
  *
  * This performs a half duplex MicroWire style transaction with the
@@ -660,7 +722,7 @@ int spi_write_then_read(struct spi_device *spi,
 
        int                     status;
        struct spi_message      message;
-       struct spi_transfer     x;
+       struct spi_transfer     x[2];
        u8                      *local_buf;
 
        /* Use preallocated DMA-safe buffer.  We can't avoid copying here,
@@ -671,9 +733,15 @@ int spi_write_then_read(struct spi_device *spi,
                return -EINVAL;
 
        spi_message_init(&message);
-       memset(&x, 0, sizeof x);
-       x.len = n_tx + n_rx;
-       spi_message_add_tail(&x, &message);
+       memset(x, 0, sizeof x);
+       if (n_tx) {
+               x[0].len = n_tx;
+               spi_message_add_tail(&x[0], &message);
+       }
+       if (n_rx) {
+               x[1].len = n_rx;
+               spi_message_add_tail(&x[1], &message);
+       }
 
        /* ... unless someone else is using the pre-allocated buffer */
        if (!mutex_trylock(&lock)) {
@@ -684,15 +752,15 @@ int spi_write_then_read(struct spi_device *spi,
                local_buf = buf;
 
        memcpy(local_buf, txbuf, n_tx);
-       x.tx_buf = local_buf;
-       x.rx_buf = local_buf;
+       x[0].tx_buf = local_buf;
+       x[1].rx_buf = local_buf + n_tx;
 
        /* do the i/o */
        status = spi_sync(spi, &message);
        if (status == 0)
-               memcpy(rxbuf, x.rx_buf + n_tx, n_rx);
+               memcpy(rxbuf, x[1].rx_buf, n_rx);
 
-       if (x.tx_buf == buf)
+       if (x[0].tx_buf == buf)
                mutex_unlock(&lock);
        else
                kfree(local_buf);