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:
parent
5d0d16f135
commit
bc1099d2b2
|
@ -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>;
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue