Hi Hugo,

>
> diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
> index 4e84e90..6c2c3c8 100644
> --- a/drivers/misc/Kconfig
> +++ b/drivers/misc/Kconfig
> @@ -500,4 +500,14 @@ config SGI_GRU_DEBUG
>        This option enables addition debugging code for the SGI GRU driver. If
>        you are unsure, say N.
>
> +config FPGALOAD
> +       tristate "FPGA bitstream loader support"

As per the commit text description this is very much specific to
Xilinx, please change the config option name to XILINX_FPGALOAD
please.

> +         This option enables support for the FPGA bitstream loader.
> +

Better if we write "Xilinx FPGA bitstream loader".

> diff --git a/drivers/misc/fpgaload.c b/drivers/misc/fpgaload.c

How about renaming C file to xilinx_fpgaload.c?

> new file mode 100644
> index 0000000..d4f2408
> --- /dev/null
> +++ b/drivers/misc/fpgaload.c
> @@ -0,0 +1,430 @@
> +

> +#include <linux/kernel.h>
> +#include <linux/device.h>
> +#include <linux/module.h>
> +#include <linux/init.h>
> +#include <linux/string.h>
> +#include <linux/err.h>
> +#include <linux/fs.h>
> +#include <linux/fpgaload.h>

Ditto. Prefer xilinux_fpgaload.h.

> +#include <linux/delay.h>
> +
> +#include <asm/gpio.h>
> +
> +#define MODULE_NAME "fpgaload"

Here too...

> +
> +/*
> + * Return value:
> + *   0: Error
> + *   1: Full bitstream
> + *   2: Partial bitstream
> + */

May be you want to document this function with kernel-doc style?

> +static int bitstream_parse_header(const u8 *buffer, size_t length,
> +                                 int fpga_family, size_t payload_full_size)
> +{


> +
> +/*
> + * Bitstreams supported: Full or Partial.
> + * Note: Full bitstream that supports partial bitstream must be generated 
> with
> + * option Persist = true.
> + */

Ditto ?

> +int fpgaload_bitstream_load(const struct fpgaload_t *fpgaload,
> +                           const u8 *data, size_t size,
> +                           int *bitstream_mode)
> +{
> +       int k;
> +       int retval;
> +       int timeout_counter;
> +
> +       *bitstream_mode = bitstream_parse_header(data, size,
> +                                                fpgaload->fpga_family,
> +                                                fpgaload->payload_full_size);
> +       switch (*bitstream_mode) {
> +       case BITSTREAM_MODE_FULL:
> +               DBGMSG("  Bitstream type: FULL");
> +               /* Toggle PROG_B Pin and wait 300nS before proceeding. */
> +               gpio_set_value(fpgaload->program_b, 0);
> +               udelay(1);
> +
> +               /* Confirm that INIT_B is low */
> +               if (gpio_get_value(fpgaload->init_b) != 0) {
> +                       FAILMSG("Error: INIT_B not LOW when PROG is LOW.");
> +                       return -EIO;
> +               }
> +
> +               break;
> +       case BITSTREAM_MODE_PARTIAL:
> +               DBGMSG("  Bitstream type: PARTIAL");
> +               break;
> +       case BITSTREAM_MODE_UNKNOWN:
> +       default:
> +               DBGMSG("  Bitstream type: UNKNOWN");
> +               return -EINVAL;
> +               break;
> +       }
> +
> +       /* For partial bitstream, PROGRAM_B is already high. */
> +       retval = bitstr_load_make_clock(fpgaload, 3);
> +       if (retval < 0)
> +               return retval;
> +
> +       gpio_set_value(fpgaload->program_b, 1);
> +
> +       /* Wait for INIT_B pin to go high. */
> +       timeout_counter = 0;
> +       while ((gpio_get_value(fpgaload->init_b) == 0) &&
> +              (timeout_counter < FPGA_WAIT_TIMEOUT)) {
> +               retval = bitstr_load_make_clock(fpgaload, 3);
> +               if (retval < 0)
> +                       return retval;
> +
> +               timeout_counter++;
> +       }
> +
> +       if (timeout_counter == FPGA_WAIT_TIMEOUT) {
> +               /* Timeout error. */
> +               FAILMSG("Error: timeout while waiting for INIT_B to go 
> HIGH.");
> +               return -EIO;

Better to return -ETIMEDOUT.

> +       }
> +
> +       /* Send actual bitstream data to FPGA one byte at a time. */
> +       for (k = 0; k < size; k += XFER_SIZE) {
> +               retval = fpgaload->write_byte((u8 *) &data[k],
> +                                             XFER_SIZE);
> +               if (retval < 0)
> +                       return retval;
> +
> +#ifdef CHECK_INIT_LOW_DURING_PROG
> +               if (gpio_get_value(fpgaload->init_b) == 0) {
> +                       /* Error if INIT_B goes low during programming. */
> +                       FAILMSG("Error: INIT_B LOW during programming.");
> +                       return -EIO;

Ditto.

> +               }
> +#endif
> +       }
> +
> +       /* Pulse the clock line ten times at the end. */
> +       retval = bitstr_load_make_clock(fpgaload, 10);
> +       if (retval < 0)
> +               return retval;
> +
> +       /* FPGA DONE pin must go high. */
> +       timeout_counter = 0;
> +       while ((gpio_get_value(fpgaload->done) == 0) &&
> +              (timeout_counter < FPGA_WAIT_TIMEOUT))
> +               timeout_counter++;
> +
> +       if (gpio_get_value(fpgaload->done) == 0) {
> +               /* Timeout error. */
> +               FAILMSG("Error: timeout while waiting for DONE to go HIGH.");
> +               return -EIO;

Whatever comes after Ditto.

> +
> +int fpgaload_register(const struct fpgaload_t *fpgaload)
> +{
> +       int retval;
> +
> +       if (fpgaload->write_byte == NULL) {
> +               FAILMSG("Error, fpgaload->write_byte() callback not 
> defined.");
> +               return -EINVAL;
> +       }
> +
> +       /* Configure FPGA PROGRAM_B GPIO. */
> +       retval = gpio_request(fpgaload->program_b, "fpga_program_b");
> +       if (retval == 0) /* FPGA_PROGRAM_B must be initially HIGH. */
> +               retval = gpio_direction_output(fpgaload->program_b, 1);
> +       if (retval != 0)
> +               goto gpio_error;
> +
> +       /* Configure FPGA INIT_B GPIO. */
> +       retval = gpio_request(fpgaload->init_b, "fpga_init_b");
> +       if (retval == 0)
> +               retval = gpio_direction_input(fpgaload->init_b);
> +       if (retval != 0)
> +               goto gpio_error;
> +
> +       /* Configure FPGA DONE GPIO. */
> +       retval = gpio_request(fpgaload->done, "fpga_done");
> +       if (retval == 0)
> +               retval = gpio_direction_input(fpgaload->done);
> +       if (retval != 0)
> +               goto gpio_error;
> +
> +       return 0;
> +
> +gpio_error:
> +       fpgaload_release_gpio(fpgaload);
> +       return retval;
> +}
> +EXPORT_SYMBOL(fpgaload_register);

I think it is not register API, but fpgaload_request_gpio, right? I
don't see typical registration stuff in above API.

> +
> +void fpgaload_unregister(const struct fpgaload_t *fpgaload)
> +{
> +       fpgaload_release_gpio(fpgaload);
> +}
> +EXPORT_SYMBOL(fpgaload_unregister);

Same here...I don't know why this API is needed.

> +
> +int __init fpgaload_init(void)
> +{

This function should be static.

> +       DBGMSG("fpgaload_init()");
> +
> +       return 0;
> +}
> +module_init(fpgaload_init);
> +
> +void __exit fpgaload_exit(void)
> +{

Ditto.

Code looks clean otherwise.

-- 
---Trilok Soni
http://triloksoni.wordpress.com
http://www.linkedin.com/in/triloksoni

_______________________________________________
Davinci-linux-open-source mailing list
[email protected]
http://linux.davincidsp.com/mailman/listinfo/davinci-linux-open-source

Reply via email to