Re: [PATCH v6 19/23] drivers/fsi: Add GPIO based FSI master
On 5/10/17 8:58 PM, Jeremy Kerr wrote: Hi Chris, I don't think we'd want this per master. The lock is for the 'top' master issuing commands. Only the top master can initiate any transactions on the bus to any devices connected downstream. Downstream masters such as hub masters, etc... cannot initiate a command. I think what Joel meant there was that we have it per *GPIO* master; if there are two GPIO masters on a system, there's no need to provide mutual exclusion to each (separate) set of GPIOs. To implement this, we'd just move the lock into struct fsi_master_gpio. Hi Jeremy, Understand now -will make the change. Thanks -Chris Cheers, Jeremy
Re: [PATCH v6 19/23] drivers/fsi: Add GPIO based FSI master
On 5/10/17 8:58 PM, Jeremy Kerr wrote: Hi Chris, I don't think we'd want this per master. The lock is for the 'top' master issuing commands. Only the top master can initiate any transactions on the bus to any devices connected downstream. Downstream masters such as hub masters, etc... cannot initiate a command. I think what Joel meant there was that we have it per *GPIO* master; if there are two GPIO masters on a system, there's no need to provide mutual exclusion to each (separate) set of GPIOs. To implement this, we'd just move the lock into struct fsi_master_gpio. Hi Jeremy, Understand now -will make the change. Thanks -Chris Cheers, Jeremy
Re: [PATCH v6 19/23] drivers/fsi: Add GPIO based FSI master
Hi Chris, > I don't think we'd want this per master. The lock is for the 'top' > master issuing commands. Only the top master can initiate any > transactions on the bus to any devices connected downstream. Downstream > masters such as hub masters, etc... cannot initiate a command. I think what Joel meant there was that we have it per *GPIO* master; if there are two GPIO masters on a system, there's no need to provide mutual exclusion to each (separate) set of GPIOs. To implement this, we'd just move the lock into struct fsi_master_gpio. Cheers, Jeremy
Re: [PATCH v6 19/23] drivers/fsi: Add GPIO based FSI master
Hi Chris, > I don't think we'd want this per master. The lock is for the 'top' > master issuing commands. Only the top master can initiate any > transactions on the bus to any devices connected downstream. Downstream > masters such as hub masters, etc... cannot initiate a command. I think what Joel meant there was that we have it per *GPIO* master; if there are two GPIO masters on a system, there's no need to provide mutual exclusion to each (separate) set of GPIOs. To implement this, we'd just move the lock into struct fsi_master_gpio. Cheers, Jeremy
Re: [PATCH v6 19/23] drivers/fsi: Add GPIO based FSI master
On 5/10/17 2:30 AM, Joel Stanley wrote: Hi Chris, On Tue, Apr 11, 2017 at 5:17 AM, Christopher Bosticwrote: 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 changes from Edward A. James and Jeremy Kerr . I think the series is looking good. I've done a bunch of testing on some machines, and it worked for me. I've got a few comments and things to be clarified below. Signed-off-by: Edward A. James Signed-off-by: Jeremy Kerr Signed-off-by: Chris Bostic Signed-off-by: Joel Stanley --- drivers/fsi/Kconfig | 11 + drivers/fsi/Makefile | 1 + drivers/fsi/fsi-master-gpio.c | 610 ++ 3 files changed, 622 insertions(+) create mode 100644 drivers/fsi/fsi-master-gpio.c diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig index 04c1a0e..448bc3b 100644 --- a/drivers/fsi/Kconfig +++ b/drivers/fsi/Kconfig @@ -9,4 +9,15 @@ config FSI ---help--- FSI - the FRU Support Interface - is a simple bus for low-level access to POWER-based hardware. + +if FSI + +config FSI_MASTER_GPIO + tristate "GPIO-based FSI master" + depends on 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 db0e5e7..ed28ac0 100644 --- a/drivers/fsi/Makefile +++ b/drivers/fsi/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_FSI) += fsi-core.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..9fedfaf --- /dev/null +++ b/drivers/fsi/fsi-master-gpio.c @@ -0,0 +1,610 @@ +/* + * A FSI master controller, using a simple GPIO bit-banging interface + */ + +#include +#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 0x2 +#defineFSI_GPIO_CMD_TERM 0x3f +#define FSI_GPIO_CMD_ABS_AR0x4 + +#defineFSI_GPIO_DPOLL_CLOCKS 100 /* < 21 will cause slave to hang */ + +/* 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 */ Should this be per-master? Hi Joel, I don't think we'd want this per master. The lock is for the 'top' master issuing commands. Only the top master can initiate any transactions on the bus to any devices connected downstream. Downstream masters such as hub masters, etc... cannot initiate a command. + +struct fsi_master_gpio { + struct fsi_master master; + struct device *dev; + 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 { +
Re: [PATCH v6 19/23] drivers/fsi: Add GPIO based FSI master
On 5/10/17 2:30 AM, Joel Stanley wrote: Hi Chris, On Tue, Apr 11, 2017 at 5:17 AM, Christopher Bostic wrote: 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 changes from Edward A. James and Jeremy Kerr . I think the series is looking good. I've done a bunch of testing on some machines, and it worked for me. I've got a few comments and things to be clarified below. Signed-off-by: Edward A. James Signed-off-by: Jeremy Kerr Signed-off-by: Chris Bostic Signed-off-by: Joel Stanley --- drivers/fsi/Kconfig | 11 + drivers/fsi/Makefile | 1 + drivers/fsi/fsi-master-gpio.c | 610 ++ 3 files changed, 622 insertions(+) create mode 100644 drivers/fsi/fsi-master-gpio.c diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig index 04c1a0e..448bc3b 100644 --- a/drivers/fsi/Kconfig +++ b/drivers/fsi/Kconfig @@ -9,4 +9,15 @@ config FSI ---help--- FSI - the FRU Support Interface - is a simple bus for low-level access to POWER-based hardware. + +if FSI + +config FSI_MASTER_GPIO + tristate "GPIO-based FSI master" + depends on 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 db0e5e7..ed28ac0 100644 --- a/drivers/fsi/Makefile +++ b/drivers/fsi/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_FSI) += fsi-core.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..9fedfaf --- /dev/null +++ b/drivers/fsi/fsi-master-gpio.c @@ -0,0 +1,610 @@ +/* + * A FSI master controller, using a simple GPIO bit-banging interface + */ + +#include +#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 0x2 +#defineFSI_GPIO_CMD_TERM 0x3f +#define FSI_GPIO_CMD_ABS_AR0x4 + +#defineFSI_GPIO_DPOLL_CLOCKS 100 /* < 21 will cause slave to hang */ + +/* 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 */ Should this be per-master? Hi Joel, I don't think we'd want this per master. The lock is for the 'top' master issuing commands. Only the top master can initiate any transactions on the bus to any devices connected downstream. Downstream masters such as hub masters, etc... cannot initiate a command. + +struct fsi_master_gpio { + struct fsi_master master; + struct device *dev; + 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;
Re: [PATCH v6 19/23] drivers/fsi: Add GPIO based FSI master
Hi Chris, On Tue, Apr 11, 2017 at 5:17 AM, Christopher Bosticwrote: > 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 changes from Edward A. James and Jeremy > Kerr . I think the series is looking good. I've done a bunch of testing on some machines, and it worked for me. I've got a few comments and things to be clarified below. > > Signed-off-by: Edward A. James > Signed-off-by: Jeremy Kerr > Signed-off-by: Chris Bostic > Signed-off-by: Joel Stanley > --- > drivers/fsi/Kconfig | 11 + > drivers/fsi/Makefile | 1 + > drivers/fsi/fsi-master-gpio.c | 610 > ++ > 3 files changed, 622 insertions(+) > create mode 100644 drivers/fsi/fsi-master-gpio.c > > diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig > index 04c1a0e..448bc3b 100644 > --- a/drivers/fsi/Kconfig > +++ b/drivers/fsi/Kconfig > @@ -9,4 +9,15 @@ config FSI > ---help--- > FSI - the FRU Support Interface - is a simple bus for low-level > access to POWER-based hardware. > + > +if FSI > + > +config FSI_MASTER_GPIO > + tristate "GPIO-based FSI master" > + depends on 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 db0e5e7..ed28ac0 100644 > --- a/drivers/fsi/Makefile > +++ b/drivers/fsi/Makefile > @@ -1,2 +1,3 @@ > > obj-$(CONFIG_FSI) += fsi-core.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..9fedfaf > --- /dev/null > +++ b/drivers/fsi/fsi-master-gpio.c > @@ -0,0 +1,610 @@ > +/* > + * A FSI master controller, using a simple GPIO bit-banging interface > + */ > + > +#include > +#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 0x2 > +#defineFSI_GPIO_CMD_TERM 0x3f > +#define FSI_GPIO_CMD_ABS_AR0x4 > + > +#defineFSI_GPIO_DPOLL_CLOCKS 100 /* < 21 will cause slave to > hang */ > + > +/* 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 */ Should this be per-master? > + > +struct fsi_master_gpio { > + struct fsi_master master; > + struct device *dev; > + 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
Re: [PATCH v6 19/23] drivers/fsi: Add GPIO based FSI master
Hi Chris, On Tue, Apr 11, 2017 at 5:17 AM, Christopher Bostic wrote: > 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 changes from Edward A. James and Jeremy > Kerr . I think the series is looking good. I've done a bunch of testing on some machines, and it worked for me. I've got a few comments and things to be clarified below. > > Signed-off-by: Edward A. James > Signed-off-by: Jeremy Kerr > Signed-off-by: Chris Bostic > Signed-off-by: Joel Stanley > --- > drivers/fsi/Kconfig | 11 + > drivers/fsi/Makefile | 1 + > drivers/fsi/fsi-master-gpio.c | 610 > ++ > 3 files changed, 622 insertions(+) > create mode 100644 drivers/fsi/fsi-master-gpio.c > > diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig > index 04c1a0e..448bc3b 100644 > --- a/drivers/fsi/Kconfig > +++ b/drivers/fsi/Kconfig > @@ -9,4 +9,15 @@ config FSI > ---help--- > FSI - the FRU Support Interface - is a simple bus for low-level > access to POWER-based hardware. > + > +if FSI > + > +config FSI_MASTER_GPIO > + tristate "GPIO-based FSI master" > + depends on 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 db0e5e7..ed28ac0 100644 > --- a/drivers/fsi/Makefile > +++ b/drivers/fsi/Makefile > @@ -1,2 +1,3 @@ > > obj-$(CONFIG_FSI) += fsi-core.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..9fedfaf > --- /dev/null > +++ b/drivers/fsi/fsi-master-gpio.c > @@ -0,0 +1,610 @@ > +/* > + * A FSI master controller, using a simple GPIO bit-banging interface > + */ > + > +#include > +#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 0x2 > +#defineFSI_GPIO_CMD_TERM 0x3f > +#define FSI_GPIO_CMD_ABS_AR0x4 > + > +#defineFSI_GPIO_DPOLL_CLOCKS 100 /* < 21 will cause slave to > hang */ > + > +/* 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 */ Should this be per-master? > + > +struct fsi_master_gpio { > + struct fsi_master master; > + struct device *dev; > + 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++) { > + ndelay(FSI_GPIO_STD_DLY); > +
[PATCH v6 19/23] drivers/fsi: Add GPIO based FSI master
From: Chris BosticImplement 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 changes from Edward A. James and Jeremy Kerr . Signed-off-by: Edward A. James Signed-off-by: Jeremy Kerr Signed-off-by: Chris Bostic Signed-off-by: Joel Stanley --- drivers/fsi/Kconfig | 11 + drivers/fsi/Makefile | 1 + drivers/fsi/fsi-master-gpio.c | 610 ++ 3 files changed, 622 insertions(+) create mode 100644 drivers/fsi/fsi-master-gpio.c diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig index 04c1a0e..448bc3b 100644 --- a/drivers/fsi/Kconfig +++ b/drivers/fsi/Kconfig @@ -9,4 +9,15 @@ config FSI ---help--- FSI - the FRU Support Interface - is a simple bus for low-level access to POWER-based hardware. + +if FSI + +config FSI_MASTER_GPIO + tristate "GPIO-based FSI master" + depends on 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 db0e5e7..ed28ac0 100644 --- a/drivers/fsi/Makefile +++ b/drivers/fsi/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_FSI) += fsi-core.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..9fedfaf --- /dev/null +++ b/drivers/fsi/fsi-master-gpio.c @@ -0,0 +1,610 @@ +/* + * A FSI master controller, using a simple GPIO bit-banging interface + */ + +#include +#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 0x2 +#defineFSI_GPIO_CMD_TERM 0x3f +#define FSI_GPIO_CMD_ABS_AR0x4 + +#defineFSI_GPIO_DPOLL_CLOCKS 100 /* < 21 will cause slave to hang */ + +/* 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 device *dev; + 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++) { + ndelay(FSI_GPIO_STD_DLY); + gpiod_set_value(master->gpio_clk, 0); + ndelay(FSI_GPIO_STD_DLY); + gpiod_set_value(master->gpio_clk, 1); + } +} + +static int sda_in(struct fsi_master_gpio *master) +{ + int in; + + ndelay(FSI_GPIO_STD_DLY); + in = gpiod_get_value(master->gpio_data); + return in ? 1 : 0; +} + +static void sda_out(struct fsi_master_gpio *master, int
[PATCH v6 19/23] drivers/fsi: Add GPIO based FSI master
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 changes from Edward A. James and Jeremy Kerr . Signed-off-by: Edward A. James Signed-off-by: Jeremy Kerr Signed-off-by: Chris Bostic Signed-off-by: Joel Stanley --- drivers/fsi/Kconfig | 11 + drivers/fsi/Makefile | 1 + drivers/fsi/fsi-master-gpio.c | 610 ++ 3 files changed, 622 insertions(+) create mode 100644 drivers/fsi/fsi-master-gpio.c diff --git a/drivers/fsi/Kconfig b/drivers/fsi/Kconfig index 04c1a0e..448bc3b 100644 --- a/drivers/fsi/Kconfig +++ b/drivers/fsi/Kconfig @@ -9,4 +9,15 @@ config FSI ---help--- FSI - the FRU Support Interface - is a simple bus for low-level access to POWER-based hardware. + +if FSI + +config FSI_MASTER_GPIO + tristate "GPIO-based FSI master" + depends on 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 db0e5e7..ed28ac0 100644 --- a/drivers/fsi/Makefile +++ b/drivers/fsi/Makefile @@ -1,2 +1,3 @@ obj-$(CONFIG_FSI) += fsi-core.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..9fedfaf --- /dev/null +++ b/drivers/fsi/fsi-master-gpio.c @@ -0,0 +1,610 @@ +/* + * A FSI master controller, using a simple GPIO bit-banging interface + */ + +#include +#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 0x2 +#defineFSI_GPIO_CMD_TERM 0x3f +#define FSI_GPIO_CMD_ABS_AR0x4 + +#defineFSI_GPIO_DPOLL_CLOCKS 100 /* < 21 will cause slave to hang */ + +/* 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 device *dev; + 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++) { + ndelay(FSI_GPIO_STD_DLY); + gpiod_set_value(master->gpio_clk, 0); + ndelay(FSI_GPIO_STD_DLY); + gpiod_set_value(master->gpio_clk, 1); + } +} + +static int sda_in(struct fsi_master_gpio *master) +{ + int in; + + ndelay(FSI_GPIO_STD_DLY); + in = gpiod_get_value(master->gpio_data); + return in ? 1 : 0; +} + +static void sda_out(struct fsi_master_gpio *master, int value) +{ + gpiod_set_value(master->gpio_data, value); +} + +static void set_sda_input(struct fsi_master_gpio *master) +{ +