On Mon, 2016-07-04 at 17:07 +0100, Dan O'Donovan wrote:
> +static int cpld_reg_update(struct up_board_cpld *cpld)
> +{
> +     u64 dir_reg_verify = 0;
> +     int i;
> +
> +     /* Reset the CPLD internal counters */
> +     gpiod_set_value(cpld->reset_gpio.soc_gpiod, 0);
> +     gpiod_set_value(cpld->reset_gpio.soc_gpiod, 1);
> +
> +     /*
> +      * Update the CPLD dir register
> +      * data_in will be sampled on each rising edge of the strobe
> signal
> +      */
> +     for (i = cpld->dir_reg_size - 1; i >= 0; i--) {
> +             gpiod_set_value(cpld->strobe_gpio.soc_gpiod, 0);
> +             gpiod_set_value(cpld->data_in_gpio.soc_gpiod,
> +                             (cpld->dir_reg >> i) & 0x1);
> +             gpiod_set_value(cpld->strobe_gpio.soc_gpiod, 1);
> +     }
> +
> +     /*
> +      * Read back and verify the value
> +      * data_out will be set on each rising edge of the strobe
> signal
> +      */
> +     for (i = cpld->dir_reg_size - 1; i >= 0; i--) {
> +             int data_out;
> +
> +             gpiod_set_value(cpld->strobe_gpio.soc_gpiod, 0);
> +             gpiod_set_value(cpld->strobe_gpio.soc_gpiod, 1);
> +             data_out = gpiod_get_value(cpld-
> >data_out_gpio.soc_gpiod);
> +             dir_reg_verify |= (u64)data_out << i;
> +     }
> +
> +     if (dir_reg_verify != cpld->dir_reg) {
> +             pr_err("CPLD verify error (expected: %llX, actual:
> %llX)\n",
> +                    cpld->dir_reg, dir_reg_verify);

dev_err();

> +             return -EIO;
> +     }
> +
> +     /* Issue a dummy STB cycle to latch the dir register updates
> */
> +     gpiod_set_value(cpld->strobe_gpio.soc_gpiod, 0);
> +     gpiod_set_value(cpld->strobe_gpio.soc_gpiod, 1);
> +
> +     return 0;
> +}
> +
> +/**
> + * up_board_cpld_reg_set_bit() - update CPLD configuration
> + * @cpld:    CPLD internal context info reference
> + * @offset:  bit offset in CPLD register to set
> + * @value:   boolean value to set in CPLD register bit selected
> by offset
> + *
> + * Return:   Returns 0 if successful, or negative error value
> otherwise
> + */
> +static int up_board_cpld_reg_set_bit(struct up_board_cpld *cpld,
> +                                  unsigned int offset, int value)
> +{
> +     u64 old_regval;
> +     int ret = 0;
> +
> +     spin_lock(&cpld->lock);
> +
> +     old_regval = cpld->dir_reg;
> +
> +     if (value)
> +             cpld->dir_reg |= 1ULL << offset;
> +     else
> +             cpld->dir_reg &= ~(1ULL << offset);
> +
> +     /* Only update the CPLD register if it has changed */
> +     if (cpld->dir_reg != old_regval)
> +             ret = cpld_reg_update(cpld);
> +
> +     spin_unlock(&cpld->lock);

Seems to me as though cpld_reg_update() could be quite lengthy. Would a
mutex be a better choice here ?


> +static int up_board_cpld_setup(struct up_board_cpld *cpld)
> +{
> +     struct up_board_gpio_info *cpld_gpios[] = {
> +             &cpld->strobe_gpio,
> +             &cpld->reset_gpio,
> +             &cpld->data_in_gpio,
> +             &cpld->data_out_gpio,
> +             &cpld->oe_gpio,
> +     };
> +     int i, ret;
> +
> +     spin_lock_init(&cpld->lock);
> +
> +     /* Initialise the CPLD config input GPIOs as outputs,
> initially low */
> +     for (i = 0; i < ARRAY_SIZE(cpld_gpios); i++) {
> +             struct up_board_gpio_info *gpio = cpld_gpios[i];
> +
> +             ret = up_board_soc_gpio_setup(cpld, gpio);
> +             if (ret)
> +                     return ret;
> +
> +             ret = devm_gpio_request_one(cpld->dev, gpio-
> >soc_gpio,
> +                                         gpio->soc_gpio_flags,
> +                                         dev_name(cpld->dev));
> +             if (ret)
> +                     return ret;
> +     }
> +
> +     /* Load initial CPLD configuration (all pins set for GPIO
> input) */
> +     ret = cpld_reg_update(cpld);
> +     if (ret) {

devm_gpio_free() ?

---
bod

Reply via email to