summaryrefslogtreecommitdiffstats
path: root/drivers/fsi/fsi-master-gpio.c
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-05-08 11:06:38 +1000
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2018-06-12 14:04:41 +1000
commitbc1099d2b2519fa0f6c7613d8de398df8438a36b (patch)
tree98cb568b10bff23b977ea82be4b8b804f34f5412 /drivers/fsi/fsi-master-gpio.c
parent5d0d16f135c0cb7a12e417cbe12b271524ce4d40 (diff)
downloadlinux-bc1099d2b2519fa0f6c7613d8de398df8438a36b.tar.gz
linux-bc1099d2b2519fa0f6c7613d8de398df8438a36b.tar.bz2
linux-bc1099d2b2519fa0f6c7613d8de398df8438a36b.zip
fsi/fsi-master-gpio: Add "no-gpio-delays" option
This adds support for an optional device-tree property that makes the driver skip all the delays around clocking the GPIOs and set it in the device-tree of common POWER9 based OpenPower platforms. This useful on chips like the AST2500 where the GPIO block is running at a fairly low clock frequency (25Mhz typically). In this case, the delays are unnecessary and due to the low precision of the timers, actually quite harmful in terms of performance. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org> Reviewed-by: Christopher Bostic <cbostic@linux.vnet.ibm.com> Tested-by: Joel Stanley <joel@jms.id.au>
Diffstat (limited to 'drivers/fsi/fsi-master-gpio.c')
-rw-r--r--drivers/fsi/fsi-master-gpio.c20
1 files changed, 16 insertions, 4 deletions
diff --git a/drivers/fsi/fsi-master-gpio.c b/drivers/fsi/fsi-master-gpio.c
index d6508bbad1fb..c82bbd35276e 100644
--- a/drivers/fsi/fsi-master-gpio.c
+++ b/drivers/fsi/fsi-master-gpio.c
@@ -62,6 +62,7 @@ struct fsi_master_gpio {
struct gpio_desc *gpio_enable; /* FSI enable */
struct gpio_desc *gpio_mux; /* Mux control */
bool external_mode;
+ bool no_delays;
};
#define CREATE_TRACE_POINTS
@@ -79,9 +80,11 @@ static void clock_toggle(struct fsi_master_gpio *master, int count)
int i;
for (i = 0; i < count; i++) {
- ndelay(FSI_GPIO_STD_DLY);
+ if (!master->no_delays)
+ ndelay(FSI_GPIO_STD_DLY);
gpiod_set_value(master->gpio_clk, 0);
- ndelay(FSI_GPIO_STD_DLY);
+ if (!master->no_delays)
+ ndelay(FSI_GPIO_STD_DLY);
gpiod_set_value(master->gpio_clk, 1);
}
}
@@ -90,10 +93,12 @@ static int sda_clock_in(struct fsi_master_gpio *master)
{
int in;
- ndelay(FSI_GPIO_STD_DLY);
+ if (!master->no_delays)
+ ndelay(FSI_GPIO_STD_DLY);
gpiod_set_value(master->gpio_clk, 0);
in = gpiod_get_value(master->gpio_data);
- ndelay(FSI_GPIO_STD_DLY);
+ if (!master->no_delays)
+ ndelay(FSI_GPIO_STD_DLY);
gpiod_set_value(master->gpio_clk, 1);
return in ? 1 : 0;
}
@@ -677,6 +682,13 @@ static int fsi_master_gpio_probe(struct platform_device *pdev)
}
master->gpio_mux = gpio;
+ /*
+ * Check if GPIO block is slow enought that no extra delays
+ * are necessary. This improves performance on ast2500 by
+ * an order of magnitude.
+ */
+ master->no_delays = device_property_present(&pdev->dev, "no-gpio-delays");
+
master->master.n_links = 1;
master->master.flags = FSI_MASTER_FLAG_SWCLOCK;
master->master.read = fsi_master_gpio_read;