]> git.kernelconcepts.de Git - karo-tx-linux.git/commitdiff
drivers/fsi: Use asynchronous slave mode
authorJeremy Kerr <jk@ozlabs.org>
Tue, 6 Jun 2017 21:08:58 +0000 (16:08 -0500)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Fri, 9 Jun 2017 09:52:09 +0000 (11:52 +0200)
For slaves that are behind a software-clocked master, we want FSI CFAMs
to run asynchronously to the FSI clock, so set up our slaves to be in
async mode.

Signed-off-by: Jeremy Kerr <jk@ozlabs.org>
Signed-off-by: Christopher Bostic <cbostic@linux.vnet.ibm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/fsi/fsi-core.c
drivers/fsi/fsi-master-gpio.c
drivers/fsi/fsi-master.h

index c9ff8d3b3f031e8cfb826795a466f8eab9a235de..b56f4ed5c4885fd63d3abf351f1944a59e19d129 100644 (file)
@@ -49,6 +49,7 @@ static const int engine_page_size = 0x400;
 #define FSI_SMODE              0x0     /* R/W: Mode register */
 #define FSI_SISC               0x8     /* R/W: Interrupt condition */
 #define FSI_SSTAT              0x14    /* R  : Slave status */
+#define FSI_LLMODE             0x100   /* R/W: Link layer mode register */
 
 /*
  * SMODE fields
@@ -64,6 +65,11 @@ static const int engine_page_size = 0x400;
 #define FSI_SMODE_LBCRR_SHIFT  8               /* Clk ratio shift */
 #define FSI_SMODE_LBCRR_MASK   0xf             /* Clk ratio mask */
 
+/*
+ * LLMODE fields
+ */
+#define FSI_LLMODE_ASYNC       0x1
+
 #define FSI_SLAVE_SIZE_23b             0x800000
 
 static DEFINE_IDA(master_ida);
@@ -557,8 +563,8 @@ static void fsi_slave_release(struct device *dev)
 
 static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
 {
+       uint32_t chip_id, llmode;
        struct fsi_slave *slave;
-       uint32_t chip_id;
        uint8_t crc;
        int rc;
 
@@ -594,6 +600,20 @@ static int fsi_slave_init(struct fsi_master *master, int link, uint8_t id)
                return -ENODEV;
        }
 
+       /* If we're behind a master that doesn't provide a self-running bus
+        * clock, put the slave into async mode
+        */
+       if (master->flags & FSI_MASTER_FLAG_SWCLOCK) {
+               llmode = cpu_to_be32(FSI_LLMODE_ASYNC);
+               rc = fsi_master_write(master, link, id,
+                               FSI_SLAVE_BASE + FSI_LLMODE,
+                               &llmode, sizeof(llmode));
+               if (rc)
+                       dev_warn(&master->dev,
+                               "can't set llmode on slave:%02x:%02x %d\n",
+                               link, id, rc);
+       }
+
        /* We can communicate with a slave; create the slave device and
         * register.
         */
index a5d6e705b3c59006cf02f077485c3ecac52beedb..ae26187685080563b78f5a16b92baba587a5a89b 100644 (file)
@@ -554,6 +554,7 @@ static int fsi_master_gpio_probe(struct platform_device *pdev)
        master->gpio_mux = gpio;
 
        master->master.n_links = 1;
+       master->master.flags = FSI_MASTER_FLAG_SWCLOCK;
        master->master.read = fsi_master_gpio_read;
        master->master.write = fsi_master_gpio_write;
        master->master.term = fsi_master_gpio_term;
index 7764b0079d2827326e1ccd3b6e2720b2957e24ab..12f7b119567da4d4a5fd988e45165b81cc8acefb 100644 (file)
@@ -19,6 +19,8 @@
 
 #include <linux/device.h>
 
+#define FSI_MASTER_FLAG_SWCLOCK                0x1
+
 struct fsi_master {
        struct device   dev;
        int             idx;