rt-thread-official/bsp/loongson/ls1cdev/libraries/ls1c_pwm.c

202 lines
4.6 KiB
C
Raw Normal View History

/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2017-09-06 <EFBFBD><EFBFBD>Ϊ<EFBFBD><EFBFBD> first version
*/
// <20><>װӲ<D7B0><D3B2>pwm<77>ӿ<EFBFBD>
#include "ls1c_public.h"
#include "ls1c_pin.h"
#include "ls1c_pwm.h"
#include "ls1c_clock.h"
#include "ls1c_regs.h"
// pwm<77><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
#define PWM_MAX_PERIOD (0xFFFFFF) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
/*
* <EFBFBD><EFBFBD><EFBFBD><EFBFBD>gpio<EFBFBD><EFBFBD>ȡ<EFBFBD><EFBFBD>Ӧpwm<EFBFBD>Ļ<EFBFBD><EFBFBD><EFBFBD>ַ
* @gpio pwm<EFBFBD><EFBFBD><EFBFBD><EFBFBD>
* @ret pwm<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ַ
*/
unsigned int pwm_get_reg_base(unsigned int gpio)
{
unsigned int reg_base = 0;
switch (gpio)
{
case LS1C_PWM0_GPIO06:
case LS1C_PWM0_GPIO04:
reg_base = LS1C_REG_BASE_PWM0;
break;
case LS1C_PWM1_GPIO92:
case LS1C_PWM1_GPIO05:
reg_base = LS1C_REG_BASE_PWM1;
break;
case LS1C_PWM2_GPIO52:
case LS1C_PWM2_GPIO46:
reg_base = LS1C_REG_BASE_PWM2;
break;
case LS1C_PWM3_GPIO47:
case LS1C_PWM3_GPIO53:
reg_base = LS1C_REG_BASE_PWM3;
break;
}
return reg_base;
}
/*
* <EFBFBD><EFBFBD>ֹpwm
* @pwm_info PWMn<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD>Ϣ
*/
void pwm_disable(pwm_info_t *pwm_info)
{
unsigned int pwm_reg_base = 0;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (NULL == pwm_info)
{
return ;
}
pwm_reg_base = pwm_get_reg_base(pwm_info->gpio);
reg_write_32(0, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CTRL));
return ;
}
/*
* ʹ<EFBFBD><EFBFBD>PWM
* @pwm_info PWMn<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD>Ϣ
*/
void pwm_enable(pwm_info_t *pwm_info)
{
unsigned int pwm_reg_base = 0;
unsigned int ctrl = 0;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
if (NULL == pwm_info)
{
return ;
}
// <20><>ȡ<EFBFBD><C8A1><EFBFBD><EFBFBD>ַ
pwm_reg_base = pwm_get_reg_base(pwm_info->gpio);
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
reg_write_32(0, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CNTR));
// <20><><EFBFBD>ÿ<EFBFBD><C3BF>ƼĴ<C6BC><C4B4><EFBFBD>
ctrl = (0 << LS1C_PWM_INT_LRC_EN)
| (0 << LS1C_PWM_INT_HRC_EN)
| (0 << LS1C_PWM_CNTR_RST)
| (0 << LS1C_PWM_INT_SR)
| (0 << LS1C_PWM_INTEN)
| (0 << LS1C_PWM_OE)
| (1 << LS1C_PWM_CNT_EN);
if (PWM_MODE_PULSE == pwm_info->mode) // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
ctrl |= (1 << LS1C_PWM_SINGLE);
}
else // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
{
ctrl &= ~(1 << LS1C_PWM_SINGLE);
}
reg_write_32(ctrl, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CTRL));
return ;
}
/*
* <EFBFBD><EFBFBD>ʼ<EFBFBD><EFBFBD>PWMn
* @pwm_info PWMn<EFBFBD><EFBFBD><EFBFBD><EFBFBD>ϸ<EFBFBD><EFBFBD>Ϣ
*/
void pwm_init(pwm_info_t *pwm_info)
{
unsigned int gpio;
unsigned long pwm_clk = 0; // pwmģ<6D><C4A3><EFBFBD><EFBFBD>ʱ<EFBFBD><CAB1>Ƶ<EFBFBD><C6B5>
unsigned long tmp = 0;
unsigned int pwm_reg_base = 0;
unsigned long period = 0;
// <20>ж<EFBFBD><D0B6><EFBFBD><EFBFBD><EFBFBD>
if (NULL == pwm_info)
{
// <20><><EFBFBD>ηǷ<CEB7><C7B7><EFBFBD><EFBFBD><EFBFBD>ֱ<EFBFBD>ӷ<EFBFBD><D3B7><EFBFBD>
return ;
}
gpio = pwm_info->gpio;
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>Ӧ<EFBFBD><D3A6><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>pwm<77><6D><EFBFBD><EFBFBD><EFBFBD><EFBFBD>gpio
pin_set_purpose(gpio, PIN_PURPOSE_OTHER);
// <20><><EFBFBD><EFBFBD>
switch (gpio)
{
// <20><><EFBFBD><EFBFBD>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>
case LS1C_PWM0_GPIO06:
case LS1C_PWM1_GPIO92:
break;
case LS1C_PWM0_GPIO04: // gpio04<30>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pin_set_remap(LS1C_PWM0_GPIO04, PIN_REMAP_THIRD);
break;
case LS1C_PWM1_GPIO05: // gpio05<30>ĵ<EFBFBD><C4B5><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pin_set_remap(LS1C_PWM1_GPIO05, PIN_REMAP_THIRD);
break;
case LS1C_PWM2_GPIO52: // gpio52<35>ĵ<EFBFBD><C4B5>ĸ<EFBFBD><C4B8><EFBFBD>
pin_set_remap(LS1C_PWM2_GPIO52, PIN_REMAP_FOURTH);
break;
case LS1C_PWM2_GPIO46: // gpio46<34>ĵ<EFBFBD><C4B5>ĸ<EFBFBD><C4B8><EFBFBD>
pin_set_remap(LS1C_PWM2_GPIO46, PIN_REMAP_FOURTH);
break;
case LS1C_PWM3_GPIO47: // gpio47<34>ĵ<EFBFBD><C4B5>ĸ<EFBFBD><C4B8><EFBFBD>
pin_set_remap(LS1C_PWM3_GPIO47, PIN_REMAP_FOURTH);
break;
case LS1C_PWM3_GPIO53: // gpio53<35>ĵ<EFBFBD><C4B5>ĸ<EFBFBD><C4B8><EFBFBD>
pin_set_remap(LS1C_PWM3_GPIO53, PIN_REMAP_FOURTH);
break;
default:
break;
}
// <20><><EFBFBD><EFBFBD>ռ<EFBFBD>ձȺ<D5B1>pwm<77><6D><EFBFBD>ڼ<EFBFBD><DABC><EFBFBD><EFBFBD>Ĵ<EFBFBD><C4B4><EFBFBD>HRC<52><43>LRC<52><43>ֵ
// <20><><EFBFBD><EFBFBD>64λ<34><CEBB><EFBFBD><EFBFBD><EFBFBD>ˣ<EFBFBD>ֻ<EFBFBD>ܵõ<DCB5><C3B5><EFBFBD>32λ<32><CEBB>linux<75><78>ȴ<EFBFBD><C8B4><EFBFBD>Եõ<D4B5>64λ<34><CEBB><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// <20>ݲ<EFBFBD><DDB2><EFBFBD><EFBFBD><EFBFBD>ԭ<EFBFBD><D4AD><EFBFBD><EFBFBD><EFBFBD>ø<EFBFBD><C3B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pwm_clk = clk_get_apb_rate();
period = (1.0 * pwm_clk * pwm_info->period_ns) / 1000000000;
period = MIN(period, PWM_MAX_PERIOD); // <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ڲ<EFBFBD><DAB2>ܳ<EFBFBD><DCB3><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ֵ
tmp = period - (period * pwm_info->duty);
// д<>Ĵ<EFBFBD><C4B4><EFBFBD>HRC<52><43>LRC
pwm_reg_base = pwm_get_reg_base(gpio);
reg_write_32(--tmp, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_HRC));
reg_write_32(--period, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_LRC));
// д<><D0B4><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
pwm_enable(pwm_info);
return ;
}