Source
x
* Hence we dispense with the HAS_SECONDARY_PWM and "tell" the original driver
/*
* drivers/pwm/pwm-pxa.c
*
* simple driver for PWM (Pulse Width Modulator) controller
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* 2008-02-13 initial version
* eric miao <eric.miao@marvell.com>
*/
static const struct platform_device_id pwm_id_table[] = {
/* PWM has_secondary_pwm? */
{ "pxa25x-pwm", 0 },
{ "pxa27x-pwm", HAS_SECONDARY_PWM },
{ "pxa168-pwm", 0 },
{ "pxa910-pwm", 0 },
{ },
};
MODULE_DEVICE_TABLE(platform, pwm_id_table);
/* PWM registers and bits definitions */
struct pxa_pwm_chip {
struct pwm_chip chip;
struct device *dev;
struct clk *clk;
void __iomem *mmio_base;
};
static inline struct pxa_pwm_chip *to_pxa_pwm_chip(struct pwm_chip *chip)
{
return container_of(chip, struct pxa_pwm_chip, chip);
}
/*
* period_ns = 10^9 * (PRESCALE + 1) * (PV + 1) / PWM_CLK_RATE
* duty_ns = 10^9 * (PRESCALE + 1) * DC / PWM_CLK_RATE
*/
static int pxa_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
int duty_ns, int period_ns)
{
struct pxa_pwm_chip *pc = to_pxa_pwm_chip(chip);
unsigned long long c;
unsigned long period_cycles, prescale, pv, dc;
unsigned long offset;
int rc;
offset = pwm->hwpwm ? 0x10 : 0;
c = clk_get_rate(pc->clk);
c = c * period_ns;
do_div(c, 1000000000);
period_cycles = c;
if (period_cycles < 1)
period_cycles = 1;
prescale = (period_cycles - 1) / 1024;
pv = period_cycles / (prescale + 1) - 1;
if (prescale > 63)
return -EINVAL;
if (duty_ns == period_ns)
dc = PWMDCR_FD;
else
dc = (pv + 1) * duty_ns / period_ns;
/* NOTE: the clock to PWM has to be enabled first