uboot/drivers/pwm/sandbox_pwm.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2015 Google, Inc
   4 * Written by Simon Glass <sjg@chromium.org>
   5 */
   6
   7#include <common.h>
   8#include <dm.h>
   9#include <errno.h>
  10#include <pwm.h>
  11#include <asm/test.h>
  12
  13enum {
  14        NUM_CHANNELS    = 3,
  15};
  16
  17/**
  18 * struct sandbox_pwm_chan - a sandbox PWM channel
  19 *
  20 * @period_ns: Period of the PWM in nanoseconds
  21 * @duty_ns: Current duty cycle of the PWM in nanoseconds
  22 * @enable: true if the PWM is enabled
  23 * @polarity: true if the PWM polarity is active high
  24 */
  25struct sandbox_pwm_chan {
  26        uint period_ns;
  27        uint duty_ns;
  28        bool enable;
  29        bool polarity;
  30};
  31
  32struct sandbox_pwm_priv {
  33        struct sandbox_pwm_chan chan[NUM_CHANNELS];
  34};
  35
  36int sandbox_pwm_get_config(struct udevice *dev, uint channel, uint *period_nsp,
  37                           uint *duty_nsp, bool *enablep, bool *polarityp)
  38{
  39        struct sandbox_pwm_priv *priv = dev_get_priv(dev);
  40        struct sandbox_pwm_chan *chan;
  41
  42        if (channel >= NUM_CHANNELS)
  43                return -ENOSPC;
  44        chan = &priv->chan[channel];
  45        *period_nsp = chan->period_ns;
  46        *duty_nsp = chan->duty_ns;
  47        *enablep = chan->enable;
  48        *polarityp = chan->polarity;
  49
  50        return 0;
  51}
  52
  53static int sandbox_pwm_set_config(struct udevice *dev, uint channel,
  54                                  uint period_ns, uint duty_ns)
  55{
  56        struct sandbox_pwm_priv *priv = dev_get_priv(dev);
  57        struct sandbox_pwm_chan *chan;
  58
  59        if (channel >= NUM_CHANNELS)
  60                return -ENOSPC;
  61        chan = &priv->chan[channel];
  62
  63        if (channel == 2) {
  64                /* Pretend to have some fixed period */
  65                chan->period_ns = 4096;
  66                chan->duty_ns =  duty_ns * 4096 / period_ns;
  67        } else {
  68                chan->period_ns = period_ns;
  69                chan->duty_ns = duty_ns;
  70        }
  71
  72        return 0;
  73}
  74
  75static int sandbox_pwm_set_enable(struct udevice *dev, uint channel,
  76                                  bool enable)
  77{
  78        struct sandbox_pwm_priv *priv = dev_get_priv(dev);
  79        struct sandbox_pwm_chan *chan;
  80
  81        if (channel >= NUM_CHANNELS)
  82                return -ENOSPC;
  83        chan = &priv->chan[channel];
  84        chan->enable = enable;
  85
  86        return 0;
  87}
  88
  89static int sandbox_pwm_set_invert(struct udevice *dev, uint channel,
  90                                  bool polarity)
  91{
  92        struct sandbox_pwm_priv *priv = dev_get_priv(dev);
  93        struct sandbox_pwm_chan *chan;
  94
  95        if (channel >= NUM_CHANNELS)
  96                return -ENOSPC;
  97        chan = &priv->chan[channel];
  98        chan->polarity = polarity;
  99
 100        return 0;
 101}
 102
 103static const struct pwm_ops sandbox_pwm_ops = {
 104        .set_config     = sandbox_pwm_set_config,
 105        .set_enable     = sandbox_pwm_set_enable,
 106        .set_invert     = sandbox_pwm_set_invert,
 107};
 108
 109static const struct udevice_id sandbox_pwm_ids[] = {
 110        { .compatible = "sandbox,pwm" },
 111        { }
 112};
 113
 114U_BOOT_DRIVER(warm_pwm_sandbox) = {
 115        .name           = "pwm_sandbox",
 116        .id             = UCLASS_PWM,
 117        .of_match       = sandbox_pwm_ids,
 118        .ops            = &sandbox_pwm_ops,
 119        .priv_auto      = sizeof(struct sandbox_pwm_priv),
 120};
 121