[U-Boot] [PATCH 3/7] tpm: Add a driver for H1/Cr50

Andy Shevchenko andy.shevchenko at gmail.com
Sat Nov 2 20:50:42 UTC 2019


On Sat, Nov 2, 2019 at 4:01 PM Simon Glass <sjg at chromium.org> wrote:
>
> H1 is a Google security chip present in recent Chromebooks, Pixel phones
> and other devices. Cr50 is the name of the software that runs on H1 in
> Chromebooks.
>
> This chip is used to handle TPM-like functionality and also has quite a
> few additional features.
>
> Add a driver for this.


> +/* Wait for interrupt to indicate TPM is ready */
> +static int cr50_i2c_wait_tpm_ready(struct udevice *dev)
> +{
> +       struct cr50_priv *priv = dev_get_priv(dev);
> +       ulong timeout;
> +       int i;
> +
> +       if (!dm_gpio_is_valid(&priv->ready_gpio)) {
> +               /* Fixed delay if interrupt not supported */
> +               udelay(TIMEOUT_NO_IRQ_US);
> +               return 0;
> +       }
> +
> +       timeout = timer_get_us() + TIMEOUT_IRQ_US;
> +
> +       i = 0;
> +       while (!dm_gpio_get_value(&priv->ready_gpio)) {
> +               i++;
> +               if (timer_get_us() > timeout) {
> +                       printf("Timeout\n");
> +                       /*
> +                        * Use this instead of -ETIMEDOUT which is used by i2c
> +                        */
> +                       return -ETIME;
> +               }
> +       }
> +
> +       return 0;
> +}
> +

Timeout loops look more naturally if they are done as do {} while.
See:

  i = 0;
  do {
    if (dm_gpio_get_value(&priv->ready_gpio))
      return 0;

    i++; /* What is this for? */
  } while (timeout >= timer_get_us());

                    printf("Timeout\n");
                    /*
                     * Use this instead of -ETIMEDOUT which is used by i2c
                     */
                    return -ETIME;
  }

> +static int cr50_i2c_write(struct udevice *dev, u8 addr, const u8 *buffer,
> +                         size_t len)
> +{

> +       u8 buf[len + 1];

VLA?!

> +       int ret;
> +
> +       if (len > CR50_MAX_BUF_SIZE) {
> +               log_err("Length %zd is too large\n", len);
> +               return -E2BIG;
> +       }

> +}

> +static int request_locality(struct udevice *dev, int loc)
> +{
> +       struct cr50_priv *priv = dev_get_priv(dev);
> +       u8 buf = TPM_ACCESS_REQUEST_USE;
> +       ulong timeout;
> +       int ret;
> +
> +       ret = check_locality(dev, loc);
> +       if (ret < 0)
> +               return ret;

> +       else if (ret == loc)

Here 'else' is redundant.

> +               return loc;


> +       timeout = timer_get_us() + TIMEOUT_LONG_US;
> +       while (timer_get_us() < timeout) {

Same comment for timeout loops (btw, there is a chance in a while {}
loop that it won't do even first iteretation).

> +               ret = check_locality(dev, loc);
> +               if (ret < 0)
> +                       return ret;
> +               if (ret == loc) {
> +                       priv->locality = loc;
> +                       log_debug("Set locality to %x\n", loc);
> +                       return loc;
> +               }
> +               udelay(TIMEOUT_SHORT_US);
> +       }
> +       printf("Request locality failed\n");
> +
> +       return -ETIMEDOUT;
> +}

> +       timeout = timer_get_us() + TIMEOUT_LONG_US;
> +       while (timer_get_us() < timeout) {

Ditto for all timeout loop related comments.

> +               if (cr50_i2c_read(dev, tpm_sts(priv->locality),
> +                                 (u8 *)&buf, sizeof(buf)) < 0) {
> +                       udelay(TIMEOUT_SHORT_US);
> +                       continue;
> +               }

> +       timeout = timer_get_us() + TIMEOUT_LONG_US;
> +       do {
> +               ret = cr50_i2c_status(dev);
> +               if (ret)
> +                       goto out_err;
> +               if (!(ret & TPM_STS_COMMAND_READY))
> +                       break;
> +
> +               if (timer_get_us() > timeout)
> +                       goto out_err;
> +
> +               ret = cr50_i2c_ready(dev);
> +               if (ret)
> +                       goto out_err;

> +       } while (1);

Better to have non-infinite loops (i.o.w. loops with understandable
exit conditional).


-- 
With Best Regards,
Andy Shevchenko


More information about the U-Boot mailing list