Source
x
/*
* PWM framework driver for Cirrus Logic EP93xx
*
* Copyright (c) 2009 Matthieu Crapet <mcrapet@gmail.com>
* Copyright (c) 2009, 2013 H Hartley Sweeten <hsweeten@visionengravers.com>
*
* EP9301/02 have only one channel:
* platform device ep93xx-pwm.1 - PWMOUT1 (EGPIO14)
*
* EP9307 has only one channel:
* platform device ep93xx-pwm.0 - PWMOUT
*
* EP9312/15 have two channels:
* platform device ep93xx-pwm.0 - PWMOUT
* platform device ep93xx-pwm.1 - PWMOUT1 (EGPIO14)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version
* 2 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
/* for ep93xx_pwm_{acquire,release}_gpio() */
struct ep93xx_pwm {
void __iomem *base;
struct clk *clk;
struct pwm_chip chip;
};
static inline struct ep93xx_pwm *to_ep93xx_pwm(struct pwm_chip *chip)
{
return container_of(chip, struct ep93xx_pwm, chip);
}
static int ep93xx_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct platform_device *pdev = to_platform_device(chip->dev);
return ep93xx_pwm_acquire_gpio(pdev);
}
static void ep93xx_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
{
struct platform_device *pdev = to_platform_device(chip->dev);
ep93xx_pwm_release_gpio(pdev);
}
static int ep93xx_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
{
struct ep93xx_pwm *ep93xx_pwm = to_ep93xx_pwm(chip);
void __iomem *base = ep93xx_pwm->base;
unsigned long long c;
unsigned long period_cycles;
unsigned long duty_cycles;
unsigned long term;
int ret = 0;
/*
* The clock needs to be enabled to access the PWM registers.
* Configuration can be changed at any time.
*/
if (!pwm_is_enabled(pwm)) {
ret = clk_enable(ep93xx_pwm->clk);
if (ret)
return ret;
}
c = clk_get_rate(ep93xx_pwm->clk);
c *= period_ns;