Add a simple driver which implements the standard PWM uclass interface. Signed-off-by: Simon Glass <sjg@chromium.org>master
parent
fc760cb8c4
commit
0e23fd81a5
@ -0,0 +1,41 @@ |
||||
/*
|
||||
* (C) Copyright 2016 Google, Inc |
||||
* (C) Copyright 2008-2014 Rockchip Electronics |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#ifndef _ASM_ARCH_PWM_H |
||||
#define _ASM_ARCH_PWM_H |
||||
|
||||
struct rk3288_pwm { |
||||
u32 cnt; |
||||
u32 period_hpr; |
||||
u32 duty_lpr; |
||||
u32 ctrl; |
||||
}; |
||||
check_member(rk3288_pwm, ctrl, 0xc); |
||||
|
||||
#define RK_PWM_DISABLE (0 << 0) |
||||
#define RK_PWM_ENABLE (1 << 0) |
||||
|
||||
#define PWM_ONE_SHOT (0 << 1) |
||||
#define PWM_CONTINUOUS (1 << 1) |
||||
#define RK_PWM_CAPTURE (1 << 2) |
||||
|
||||
#define PWM_DUTY_POSTIVE (1 << 3) |
||||
#define PWM_DUTY_NEGATIVE (0 << 3) |
||||
|
||||
#define PWM_INACTIVE_POSTIVE (1 << 4) |
||||
#define PWM_INACTIVE_NEGATIVE (0 << 4) |
||||
|
||||
#define PWM_OUTPUT_LEFT (0 << 5) |
||||
#define PWM_OUTPUT_CENTER (1 << 5) |
||||
|
||||
#define PWM_LP_ENABLE (1 << 8) |
||||
#define PWM_LP_DISABLE (0 << 8) |
||||
|
||||
#define PWM_SEL_SCALE_CLK (1 << 9) |
||||
#define PWM_SEL_SRC_CLK (0 << 9) |
||||
|
||||
#endif |
@ -0,0 +1,103 @@ |
||||
/*
|
||||
* Copyright (c) 2016 Google, Inc |
||||
* Written by Simon Glass <sjg@chromium.org> |
||||
* |
||||
* SPDX-License-Identifier: GPL-2.0+ |
||||
*/ |
||||
|
||||
#include <common.h> |
||||
#include <div64.h> |
||||
#include <dm.h> |
||||
#include <pwm.h> |
||||
#include <regmap.h> |
||||
#include <syscon.h> |
||||
#include <asm/io.h> |
||||
#include <asm/arch/clock.h> |
||||
#include <asm/arch/cru_rk3288.h> |
||||
#include <asm/arch/grf_rk3288.h> |
||||
#include <asm/arch/pwm.h> |
||||
#include <power/regulator.h> |
||||
|
||||
DECLARE_GLOBAL_DATA_PTR; |
||||
|
||||
struct rk_pwm_priv { |
||||
struct rk3288_pwm *regs; |
||||
struct rk3288_grf *grf; |
||||
}; |
||||
|
||||
static int rk_pwm_set_config(struct udevice *dev, uint channel, uint period_ns, |
||||
uint duty_ns) |
||||
{ |
||||
struct rk_pwm_priv *priv = dev_get_priv(dev); |
||||
struct rk3288_pwm *regs = priv->regs; |
||||
unsigned long period, duty; |
||||
|
||||
debug("%s: period_ns=%u, duty_ns=%u\n", __func__, period_ns, duty_ns); |
||||
writel(PWM_SEL_SRC_CLK | PWM_OUTPUT_LEFT | PWM_LP_DISABLE | |
||||
PWM_CONTINUOUS | PWM_DUTY_POSTIVE | PWM_INACTIVE_POSTIVE | |
||||
RK_PWM_DISABLE, |
||||
®s->ctrl); |
||||
|
||||
period = lldiv((uint64_t)(PD_BUS_PCLK_HZ / 1000) * period_ns, 1000000); |
||||
duty = lldiv((uint64_t)(PD_BUS_PCLK_HZ / 1000) * duty_ns, 1000000); |
||||
|
||||
writel(period, ®s->period_hpr); |
||||
writel(duty, ®s->duty_lpr); |
||||
debug("%s: period=%lu, duty=%lu\n", __func__, period, duty); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int rk_pwm_set_enable(struct udevice *dev, uint channel, bool enable) |
||||
{ |
||||
struct rk_pwm_priv *priv = dev_get_priv(dev); |
||||
struct rk3288_pwm *regs = priv->regs; |
||||
|
||||
debug("%s: Enable '%s'\n", __func__, dev->name); |
||||
clrsetbits_le32(®s->ctrl, RK_PWM_ENABLE, enable ? RK_PWM_ENABLE : 0); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int rk_pwm_ofdata_to_platdata(struct udevice *dev) |
||||
{ |
||||
struct rk_pwm_priv *priv = dev_get_priv(dev); |
||||
struct regmap *map; |
||||
|
||||
priv->regs = (struct rk3288_pwm *)dev_get_addr(dev); |
||||
map = syscon_get_regmap_by_driver_data(ROCKCHIP_SYSCON_GRF); |
||||
if (IS_ERR(map)) |
||||
return PTR_ERR(map); |
||||
priv->grf = regmap_get_range(map, 0); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static int rk_pwm_probe(struct udevice *dev) |
||||
{ |
||||
struct rk_pwm_priv *priv = dev_get_priv(dev); |
||||
|
||||
rk_setreg(&priv->grf->soc_con2, 1 << 0); |
||||
|
||||
return 0; |
||||
} |
||||
|
||||
static const struct pwm_ops rk_pwm_ops = { |
||||
.set_config = rk_pwm_set_config, |
||||
.set_enable = rk_pwm_set_enable, |
||||
}; |
||||
|
||||
static const struct udevice_id rk_pwm_ids[] = { |
||||
{ .compatible = "rockchip,rk3288-pwm" }, |
||||
{ } |
||||
}; |
||||
|
||||
U_BOOT_DRIVER(rk_pwm) = { |
||||
.name = "rk_pwm", |
||||
.id = UCLASS_PWM, |
||||
.of_match = rk_pwm_ids, |
||||
.ops = &rk_pwm_ops, |
||||
.ofdata_to_platdata = rk_pwm_ofdata_to_platdata, |
||||
.probe = rk_pwm_probe, |
||||
.priv_auto_alloc_size = sizeof(struct rk_pwm_priv), |
||||
}; |
Loading…
Reference in new issue