Re: [PATCH 16/16] drivers/fsi: Add GPIO based FSI master

2016-12-12 Thread Christopher Bostic
On Thu, Dec 8, 2016 at 10:12 PM, Jeremy Kerr  wrote:
> Hi Chris,
>
>> +static ssize_t store_scan(struct device *dev,
>> + struct device_attribute *attr,
>> + const char *buf,
>> + size_t count)
>> +{
>> + struct fsi_master_gpio *master = dev_get_drvdata(dev);
>> +
>> + fsi_master_gpio_init(master);
>> +
>> + /* clear out any old scan data if present */
>> + fsi_master_unregister(&master->master);
>> + fsi_master_register(&master->master);
>> +
>> + return count;
>> +}
>> +
>> +static DEVICE_ATTR(scan, 0200, NULL, store_scan);
>
> I think it would make more sense to have the scan attribute populated by
> the fsi core; we want this on all masters, not just GPIO.
>

Hi Jeremy,

Sure, will move that to the core.

> Currently, the only GPIO-master-specific functionality here is the
> fsi_master_gpio_init() - but isn't this something that we can do at
> probe time instead?
>

Yes that can be done at probe time.  Will change.

>> +static int fsi_master_gpio_probe(struct platform_device *pdev)
>> +{
>> + struct fsi_master_gpio *master;
>> + struct gpio_desc *gpio;
>> +
>> + master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL);
>> + if (!master)
>> + return -ENOMEM;
>
> We should be populating master->dev.parent, see
>
>   https://github.com/jk-ozlabs/linux/commit/5225d6c47
>
>

Will make the change.

>> + /* Optional pins */
>> +
>> + gpio = devm_gpiod_get(&pdev->dev, "trans", 0);
>> + if (IS_ERR(gpio))
>> + dev_dbg(&pdev->dev, "probe: failed to get trans pin\n");
>> + else
>> + master->gpio_trans = gpio;
>
> I found devm_gpiod_get_optional(), which might make this a little
> neater.

Will make this change.


Thanks,
Chris

>
> Cheers,
>
>
> Jeremy


Re: [PATCH 16/16] drivers/fsi: Add GPIO based FSI master

2016-12-08 Thread Jeremy Kerr
Hi Chris,

> +static ssize_t store_scan(struct device *dev,
> + struct device_attribute *attr,
> + const char *buf,
> + size_t count)
> +{
> + struct fsi_master_gpio *master = dev_get_drvdata(dev);
> +
> + fsi_master_gpio_init(master);
> +
> + /* clear out any old scan data if present */
> + fsi_master_unregister(&master->master);
> + fsi_master_register(&master->master);
> +
> + return count;
> +}
> +
> +static DEVICE_ATTR(scan, 0200, NULL, store_scan);

I think it would make more sense to have the scan attribute populated by
the fsi core; we want this on all masters, not just GPIO.

Currently, the only GPIO-master-specific functionality here is the
fsi_master_gpio_init() - but isn't this something that we can do at
probe time instead?

> +static int fsi_master_gpio_probe(struct platform_device *pdev)
> +{
> + struct fsi_master_gpio *master;
> + struct gpio_desc *gpio;
> +
> + master = devm_kzalloc(&pdev->dev, sizeof(*master), GFP_KERNEL);
> + if (!master)
> + return -ENOMEM;

We should be populating master->dev.parent, see

  https://github.com/jk-ozlabs/linux/commit/5225d6c47


> + /* Optional pins */
> +
> + gpio = devm_gpiod_get(&pdev->dev, "trans", 0);
> + if (IS_ERR(gpio))
> + dev_dbg(&pdev->dev, "probe: failed to get trans pin\n");
> + else
> + master->gpio_trans = gpio;

I found devm_gpiod_get_optional(), which might make this a little
neater.

Cheers,


Jeremy


[PATCH 16/16] drivers/fsi: Add GPIO based FSI master

2016-12-06 Thread Chris Bostic
From: Chris Bostic 

Implement a FSI master using GPIO.  Will generate FSI protocol for
read and write commands to particular addresses.  Sends master command
and waits for and decodes a slave response.

Includes Jeremy Kerr's original GPIO master base commit.

Signed-off-by: Jeremy Kerr 
Signed-off-by: Chris Bostic 
---
 drivers/fsi/Kconfig   |   7 +
 drivers/fsi/Makefile  |   1 +
 drivers/fsi/fsi-master-gpio.c | 552 ++
 3 files changed, 560 insertions(+)
 create mode 100644 drivers/fsi/fsi-master-gpio.c

diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig
index f065dbe..9530459 100644
--- a/drivers/fsi/Kconfig
+++ b/drivers/fsi/Kconfig
@@ -17,6 +17,13 @@ config FSI_MASTER_FAKE
depends on FSI
---help---
This option enables a fake FSI master driver for debugging.
+
+config FSI_MASTER_GPIO
+   tristate "GPIO-based FSI master"
+   depends on FSI && GPIOLIB
+   ---help---
+   This option enables a FSI master driver using GPIO lines.
+
 endif
 
 endmenu
diff --git a/drivers/fsi/Makefile b/drivers/fsi/Makefile
index 847c00c..2021ce5 100644
--- a/drivers/fsi/Makefile
+++ b/drivers/fsi/Makefile
@@ -1,3 +1,4 @@
 
 obj-$(CONFIG_FSI) += fsi-core.o
 obj-$(CONFIG_FSI_MASTER_FAKE) += fsi-master-fake.o
+obj-$(CONFIG_FSI_MASTER_GPIO) += fsi-master-gpio.o
diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
new file mode 100644
index 000..79cb0b1
--- /dev/null
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -0,0 +1,552 @@
+/*
+ * A FSI master controller, using a simple GPIO bit-banging interface
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "fsi-master.h"
+
+#defineFSI_GPIO_STD_DLY1   /* Standard pin delay in nS */
+#defineFSI_ECHO_DELAY_CLOCKS   16  /* Number clocks for echo delay 
*/
+#defineFSI_PRE_BREAK_CLOCKS50  /* Number clocks to prep for 
break */
+#defineFSI_BREAK_CLOCKS256 /* Number of clocks to issue 
break */
+#defineFSI_POST_BREAK_CLOCKS   16000   /* Number clocks to set up cfam 
*/
+#defineFSI_INIT_CLOCKS 5000/* Clock out any old data */
+#defineFSI_GPIO_STD_DELAY  10  /* Standard GPIO delay in nS */
+   /* todo: adjust down as low as */
+   /* possible or eliminate */
+#defineFSI_GPIO_CMD_DPOLL  0x002AULL
+#defineFSI_GPIO_CMD_DPOLL_SIZE 9
+#defineFSI_GPIO_DPOLL_CLOCKS   100  /* < 21 will cause slave to 
hang */
+#defineFSI_GPIO_CMD_DEFAULT0x2000ULL
+#defineFSI_GPIO_CMD_WRITE  0
+#defineFSI_GPIO_CMD_READ   0x0400ULL
+#defineFSI_GPIO_CMD_SLAVE_MASK 0xC000ULL
+#defineFSI_GPIO_CMD_ADDR_SHIFT 37
+#defineFSI_GPIO_CMD_ADDR_MASK  0x001F
+#defineFSI_GPIO_CMD_SLV_SHIFT  62
+#defineFSI_GPIO_CMD_SIZE_160x0010ULL
+#defineFSI_GPIO_CMD_SIZE_320x0030ULL
+#defineFSI_GPIO_CMD_DT32_SHIFT 4
+#defineFSI_GPIO_CMD_DT16_SHIFT 20
+#defineFSI_GPIO_CMD_DT8_SHIFT  28
+#defineFSI_GPIO_CMD_DFLT_LEN   28
+#defineFSI_GPIO_CMD_CRC_SHIFT  60
+
+/* Bus errors */
+#defineFSI_GPIO_ERR_BUSY   1   /* Slave stuck in busy state */
+#defineFSI_GPIO_RESP_ERRA  2   /* Any (misc) Error */
+#defineFSI_GPIO_RESP_ERRC  3   /* Slave reports master CRC 
error */
+#defineFSI_GPIO_MTOE   4   /* Master time out error */
+#defineFSI_GPIO_CRC_INVAL  5   /* Master reports slave CRC 
error */
+
+/* Normal slave responses */
+#defineFSI_GPIO_RESP_BUSY  1
+#defineFSI_GPIO_RESP_ACK   0
+#defineFSI_GPIO_RESP_ACKD  4
+
+#defineFSI_GPIO_MAX_BUSY   100
+#defineFSI_GPIO_MTOE_COUNT 1000
+#defineFSI_GPIO_DRAIN_BITS 20
+#defineFSI_GPIO_CRC_SIZE   4
+#defineFSI_GPIO_MSG_ID_SIZE2
+#defineFSI_GPIO_MSG_RESPID_SIZE2
+#defineFSI_GPIO_PRIME_SLAVE_CLOCKS 100
+
+static DEFINE_SPINLOCK(fsi_gpio_cmd_lock); /* lock around fsi commands */
+
+struct fsi_master_gpio {
+   struct fsi_master   master;
+   struct gpio_desc*gpio_clk;
+   struct gpio_desc*gpio_data;
+   struct gpio_desc*gpio_trans;/* Voltage translator */
+   struct gpio_desc*gpio_enable;   /* FSI enable */
+   struct gpio_desc*gpio_mux;  /* Mux control */
+};
+
+#define to_fsi_master_gpio(m) container_of(m, struct fsi_master_gpio, master)
+
+struct fsi_gpio_msg {
+   uint64_tmsg;
+   uint8_t bits;
+};
+
+static void clock_toggle(struct fsi_master_gpio *master, int count)
+{
+   int i;
+
+   for (i = 0; i < count; i