rt-thread-official/bsp/loongson/ls1cdev/drivers/drv_pwm.c

179 lines
4.8 KiB
C

/*
* Copyright (c) 2006-2018, RT-Thread Development Team
*
* SPDX-License-Identifier: Apache-2.0
*
* Change Logs:
* Date Author Notes
* 2018-12-04 Sundm75 the first version
*/
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
#include <rtthread.h>
#include <rtdevice.h>
#include "ls1c.h"
#include "../libraries/ls1c_public.h"
#include "../libraries/ls1c_regs.h"
#include "../libraries/ls1c_clock.h"
#include "../libraries/ls1c_pwm.h"
#include "../libraries/ls1c_pin.h"
#define PWM_CHANNEL_MAX (4) /* 0-3*/
#ifdef RT_USING_PWM
struct rt_ls1c_pwm
{
struct rt_device_pwm parent;
rt_uint32_t period[PWM_CHANNEL_MAX];
rt_uint32_t pulse[PWM_CHANNEL_MAX];
};
static struct rt_ls1c_pwm _ls1c_pwm_device;
static rt_err_t set(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
{
rt_err_t result = RT_EOK;
struct rt_ls1c_pwm *ls1c_pwm_device = (struct rt_ls1c_pwm *)device;
if (configuration->channel > (PWM_CHANNEL_MAX - 1))
{
result = -RT_EIO;
goto _exit;
}
rt_kprintf("drv_pwm.c set channel %d: period: %d, pulse: %d\n", configuration->channel, configuration->period, configuration->pulse);
ls1c_pwm_device->period[configuration->channel] = configuration->period;
ls1c_pwm_device->pulse[configuration->channel] = configuration->pulse;
_exit:
return result;
}
static rt_err_t get(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
{
rt_err_t result = RT_EOK;
struct rt_ls1c_pwm *ls1c_pwm_device = (struct rt_ls1c_pwm *)device;
if (configuration->channel > (PWM_CHANNEL_MAX - 1))
{
result = -RT_EIO;
goto _exit;
}
configuration->period = ls1c_pwm_device->period[configuration->channel];
configuration->pulse = ls1c_pwm_device->pulse[configuration->channel];
rt_kprintf("drv_pwm.c get channel %d: period: %d, pulse: %d\n", configuration->channel, configuration->period, configuration->pulse);
_exit:
return result;
}
static rt_err_t control(struct rt_device_pwm *device, int cmd, void *arg)
{
rt_err_t result = RT_EOK;
struct rt_pwm_configuration * configuration = (struct rt_pwm_configuration *)arg;
rt_kprintf("drv_pwm.c control cmd: %d. \n", cmd);
if (cmd == PWM_CMD_ENABLE)
{
rt_kprintf("PWM_CMD_ENABLE\n");
pwm_info_t pwm_info;
switch ( configuration->channel)
{
case 0:
pwm_info.gpio = LS1C_PWM0_GPIO06;
//pwm_info.gpio = LS1C_PWM0_GPIO04;
break;
case 1:
pwm_info.gpio = LS1C_PWM1_GPIO92;
//pwm_info.gpio = LS1C_PWM1_GPIO05;
break;
case 2:
pwm_info.gpio = LS1C_PWM2_GPIO52;
//pwm_info.gpio = LS1C_PWM2_GPIO46;
break;
case 3:
pwm_info.gpio = LS1C_PWM3_GPIO47;
//pwm_info.gpio = LS1C_PWM3_GPIO53;
break;
default:
break;
}
pwm_info.mode = PWM_MODE_NORMAL;
pwm_info.duty = ( (float)configuration->pulse ) / ((float)configuration->period );
pwm_info.period_ns = configuration->period;
pwm_init(&pwm_info);
pwm_enable(&pwm_info);
}
else if (cmd == PWM_CMD_DISABLE)
{
rt_kprintf("PWM_CMD_DISABLE\n");
pwm_info_t pwm_info;
switch ( configuration->channel)
{
case 0:
pwm_info.gpio = LS1C_PWM0_GPIO06;
//pwm_info.gpio = LS1C_PWM0_GPIO04;
break;
case 1:
pwm_info.gpio = LS1C_PWM1_GPIO92;
//pwm_info.gpio = LS1C_PWM1_GPIO05;
break;
case 2:
pwm_info.gpio = LS1C_PWM2_GPIO52;
//pwm_info.gpio = LS1C_PWM2_GPIO46;
break;
case 3:
pwm_info.gpio = LS1C_PWM3_GPIO47;
//pwm_info.gpio = LS1C_PWM3_GPIO53;
break;
default:
break;
}
pwm_info.mode = PWM_MODE_NORMAL;
pwm_info.duty = ( (float)configuration->pulse ) / ((float)configuration->period );
pwm_info.period_ns = configuration->period;
pwm_init(&pwm_info);
pwm_disable(&pwm_info);
}
else if (cmd == PWM_CMD_SET)
{
rt_kprintf("PWM_CMD_SET\n");
result = set(device, (struct rt_pwm_configuration *)arg);
}
else if (cmd == PWM_CMD_GET)
{
rt_kprintf("PWM_CMD_GET\n");
result = get(device, (struct rt_pwm_configuration *)arg);
}
return result;
}
static const struct rt_pwm_ops pwm_ops =
{
control,
};
int rt_hw_pwm_init(void)
{
int ret = RT_EOK;
/* add pwm initial. */
ret = rt_device_pwm_register(&_ls1c_pwm_device.parent, "pwm", &pwm_ops, RT_NULL);
return ret;
}
INIT_DEVICE_EXPORT(rt_hw_pwm_init);
#endif /*RT_USING_PWM*/