81 lines
1.6 KiB
C
81 lines
1.6 KiB
C
#include <io.h>
|
|
#include "pwm.h"
|
|
|
|
static void pwm_set_bits(void* base, u32 offset, unsigned int mask, u32 data)
|
|
{
|
|
void *address = base + offset;
|
|
unsigned int value;
|
|
|
|
value = readl(address);
|
|
value &= ~mask;
|
|
value |= (data & mask);
|
|
writel(value, address);
|
|
}
|
|
|
|
static void get_pwm_clk(unsigned int *clk)
|
|
{
|
|
void *pwm_clock_addr = (void *)PWM_CLOCK_ADDR_BASE;
|
|
unsigned int val = readl(pwm_clock_addr);
|
|
|
|
val = (val >> 8) & 0x3;
|
|
switch (val) {
|
|
case 0:
|
|
*clk = PWM_CLOCK_3M;
|
|
break;
|
|
case 1:
|
|
*clk = PWM_CLOCK_50M;
|
|
break;
|
|
default:
|
|
*clk = PWM_CLOCK_24M;
|
|
break;
|
|
}
|
|
}
|
|
|
|
int pwm_enable(int pwm_id)
|
|
{
|
|
if (pwm_id > PWM_MAX_NUM)
|
|
return -1;
|
|
|
|
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CTRL_ADDR(pwm_id), PWM_ENABLE_MASK, (0x1 << PWM_ENABLE_SHIFT));
|
|
return 0;
|
|
}
|
|
|
|
int pwm_disable(int pwm_id)
|
|
{
|
|
if (pwm_id > PWM_MAX_NUM)
|
|
return -1;
|
|
|
|
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CTRL_ADDR(pwm_id), PWM_ENABLE_MASK, (0x0 << PWM_ENABLE_SHIFT));
|
|
return 0;
|
|
}
|
|
|
|
int pwm_config(int pwm_id, int duty_cycle_us, int period_us)
|
|
{
|
|
unsigned int duty;
|
|
unsigned int period, freq;
|
|
unsigned int clk;
|
|
|
|
if ((pwm_id > PWM_MAX_NUM) || (duty_cycle_us > period_us))
|
|
return -1;
|
|
|
|
get_pwm_clk(&clk);
|
|
|
|
freq = clk/1000000;
|
|
|
|
period = freq * period_us;
|
|
duty = period * duty_cycle_us/period_us;
|
|
|
|
if ((period < 2) || (duty < 1))
|
|
return -1;
|
|
|
|
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CFG_CYCLE_ADDR(pwm_id), PWM_PERIOD_MASK, period);
|
|
|
|
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CFG_HLINT_ADDR(pwm_id), PWM_DUTY_MASK, duty);
|
|
|
|
pwm_set_bits((void *)PWM_ADDR_BASE, PWM_CTRL_ADDR(pwm_id),
|
|
PWM_KEEP_MASK, (0x1 << PWM_KEEP_SHIFT));
|
|
return 0;
|
|
}
|
|
|
|
|