uboot/drivers/pwm/rk_pwm.c
<<
>>
Prefs
   1/*
   2 * Copyright (c) 2016 Google, Inc
   3 * Written by Simon Glass <sjg@chromium.org>
   4 *
   5 * SPDX-License-Identifier:     GPL-2.0+
   6 */
   7
   8#include <common.h>
   9#include <clk.h>
  10#include <div64.h>
  11#include <dm.h>
  12#include <pwm.h>
  13#include <regmap.h>
  14#include <syscon.h>
  15#include <asm/io.h>
  16#include <asm/arch/pwm.h>
  17#include <power/regulator.h>
  18
  19DECLARE_GLOBAL_DATA_PTR;
  20
  21struct rk_pwm_priv {
  22        struct rk3288_pwm *regs;
  23        ulong freq;
  24};
  25
  26static int rk_pwm_set_config(struct udevice *dev, uint channel, uint period_ns,
  27                             uint duty_ns)
  28{
  29        struct rk_pwm_priv *priv = dev_get_priv(dev);
  30        struct rk3288_pwm *regs = priv->regs;
  31        unsigned long period, duty;
  32
  33        debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns);
  34        writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE |
  35                PWM_CONTINUOUS | PWM_DUTY_POSTIVE | PWM_INACTIVE_POSTIVE |
  36                RK_PWM_DISABLE,
  37                &regs->ctrl);
  38
  39        period = lldiv((uint64_t)(priv->freq / 1000) * period_ns, 1000000);
  40        duty = lldiv((uint64_t)(priv->freq / 1000) * duty_ns, 1000000);
  41
  42        writel(period, &regs->period_hpr);
  43        writel(duty, &regs->duty_lpr);
  44        debug("%s: period=%lu, duty=%lu\n", __func__, period, duty);
  45
  46        return 0;
  47}
  48
  49static int rk_pwm_set_enable(struct udevice *dev, uint channel, bool enable)
  50{
  51        struct rk_pwm_priv *priv = dev_get_priv(dev);
  52        struct rk3288_pwm *regs = priv->regs;
  53
  54        debug("%s: Enable '%s'\n", __func__, dev->name);
  55        clrsetbits_le32(&regs->ctrl, RK_PWM_ENABLE, enable ? RK_PWM_ENABLE : 0);
  56
  57        return 0;
  58}
  59
  60static int rk_pwm_ofdata_to_platdata(struct udevice *dev)
  61{
  62        struct rk_pwm_priv *priv = dev_get_priv(dev);
  63
  64        priv->regs = (struct rk3288_pwm *)dev_get_addr(dev);
  65
  66        return 0;
  67}
  68
  69static int rk_pwm_probe(struct udevice *dev)
  70{
  71        struct rk_pwm_priv *priv = dev_get_priv(dev);
  72        struct clk clk;
  73        int ret = 0;
  74
  75        ret = clk_get_by_index(dev, 0, &clk);
  76        if (ret < 0) {
  77                debug("%s get clock fail!\n", __func__);
  78                return -EINVAL;
  79        }
  80        priv->freq = clk_get_rate(&clk);
  81
  82        return 0;
  83}
  84
  85static const struct pwm_ops rk_pwm_ops = {
  86        .set_config     = rk_pwm_set_config,
  87        .set_enable     = rk_pwm_set_enable,
  88};
  89
  90static const struct udevice_id rk_pwm_ids[] = {
  91        { .compatible = "rockchip,rk3288-pwm" },
  92        { }
  93};
  94
  95U_BOOT_DRIVER(rk_pwm) = {
  96        .name   = "rk_pwm",
  97        .id     = UCLASS_PWM,
  98        .of_match = rk_pwm_ids,
  99        .ops    = &rk_pwm_ops,
 100        .ofdata_to_platdata     = rk_pwm_ofdata_to_platdata,
 101        .probe          = rk_pwm_probe,
 102        .priv_auto_alloc_size   = sizeof(struct rk_pwm_priv),
 103};
 104