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>
This commit is contained in:
Benjamin Herrenschmidt 2018-05-08 11:06:38 +10:00
parent 5d0d16f135
commit bc1099d2b2
4 changed files with 19 additions and 4 deletions

View File

@ -52,6 +52,7 @@
compatible = "fsi-master-gpio", "fsi-master";
#address-cells = <2>;
#size-cells = <0>;
no-gpio-delays;
clock-gpios = <&gpio ASPEED_GPIO(AA, 0) GPIO_ACTIVE_HIGH>;
data-gpios = <&gpio ASPEED_GPIO(AA, 2) GPIO_ACTIVE_HIGH>;

View File

@ -153,6 +153,7 @@
compatible = "fsi-master-gpio", "fsi-master";
#address-cells = <2>;
#size-cells = <0>;
no-gpio-delays;
clock-gpios = <&gpio ASPEED_GPIO(AA, 0) GPIO_ACTIVE_HIGH>;
data-gpios = <&gpio ASPEED_GPIO(E, 0) GPIO_ACTIVE_HIGH>;

View File

@ -91,6 +91,7 @@
compatible = "fsi-master-gpio", "fsi-master";
#address-cells = <2>;
#size-cells = <0>;
no-gpio-delays;
trans-gpios = <&gpio ASPEED_GPIO(O, 6) GPIO_ACTIVE_HIGH>;
enable-gpios = <&gpio ASPEED_GPIO(D, 0) GPIO_ACTIVE_HIGH>;

View File

@ -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;