1 /*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date Author Notes
8 * 2021-12-13 JasonHu the first version
9 */
10
11 #include <rtthread.h>
12 #include <rtdevice.h>
13
14 #include <sunxi_hal_pwm.h>
15
16 #define PWM_CHANNEL_MAX (8) /* 0-7*/
17
18 #if defined(RT_USING_PWM) && defined(BSP_USING_PWM)
19
20 struct rt_hal_pwm
21 {
22 struct rt_device_pwm parent;
23
24 rt_uint32_t period[PWM_CHANNEL_MAX];
25 rt_uint32_t pulse[PWM_CHANNEL_MAX];
26 rt_uint32_t status;
27 };
28
29 static struct rt_hal_pwm _hal_pwm_device;
30 static struct rt_pwm_configuration configuration = {1, 100000, 100000, RT_TRUE};
31
set(struct rt_device_pwm * device,struct rt_pwm_configuration * configuration)32 static rt_err_t set(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
33 {
34 struct rt_hal_pwm *hal_pwm_device = (struct rt_hal_pwm *)device;
35
36 LOG_D("drv_pwm.c set channel %d: period: %d, pulse: %d\n", configuration->channel, configuration->period, configuration->pulse);
37
38 hal_pwm_device->period[configuration->channel] = configuration->period;
39 hal_pwm_device->pulse[configuration->channel] = configuration->pulse;
40
41 return RT_EOK;
42 }
43
get(struct rt_device_pwm * device,struct rt_pwm_configuration * configuration)44 static rt_err_t get(struct rt_device_pwm *device, struct rt_pwm_configuration *configuration)
45 {
46 struct rt_hal_pwm *hal_pwm_device = (struct rt_hal_pwm *)device;
47
48 configuration->period = hal_pwm_device->period[configuration->channel];
49 configuration->pulse = hal_pwm_device->pulse[configuration->channel];
50 LOG_D("drv_pwm.c get channel %d: period: %d, pulse: %d\n", configuration->channel, configuration->period, configuration->pulse);
51
52 return RT_EOK;
53 }
54
control(struct rt_device_pwm * device,int cmd,void * arg)55 static rt_err_t control(struct rt_device_pwm *device, int cmd, void *arg)
56 {
57 rt_err_t result = RT_EOK;
58 struct rt_pwm_configuration * configuration = (struct rt_pwm_configuration *)arg;
59
60 struct rt_hal_pwm *hal_pwm_device = (struct rt_hal_pwm *)device;
61
62 LOG_D("drv_pwm.c control cmd: %d. \n", cmd);
63
64 if (configuration->channel > (PWM_CHANNEL_MAX - 1))
65 {
66 LOG_E("drv_pwm.c control channel: %d not support! \n", configuration->channel);
67 return -RT_EIO;
68 }
69
70 LOG_D("PWM: channel:%d", configuration->channel);
71
72 if (cmd == PWM_CMD_ENABLE)
73 {
74 LOG_D("PWM_CMD_ENABLE");
75 struct pwm_config pwm_cfg;
76 pwm_cfg.polarity = PWM_POLARITY_NORMAL;
77 pwm_cfg.duty_ns = hal_pwm_device->pulse[configuration->channel];
78 pwm_cfg.period_ns = hal_pwm_device->period[configuration->channel];
79 hal_pwm_device->status = 1;
80 if (hal_pwm_control(configuration->channel, &pwm_cfg) != 0)
81 {
82 result = -RT_EIO;
83 }
84 }
85 else if (cmd == PWM_CMD_DISABLE)
86 {
87 LOG_D("PWM_CMD_DISABLE");
88 struct pwm_config pwm_cfg;
89 pwm_cfg.polarity = PWM_POLARITY_NORMAL;
90 pwm_cfg.duty_ns = 0; /* set as 0 for no duty */
91 pwm_cfg.period_ns = hal_pwm_device->period[configuration->channel];
92 hal_pwm_device->status = 0;
93 if (hal_pwm_control(configuration->channel, &pwm_cfg) != 0)
94 {
95 result = -RT_EIO;
96 }
97 else
98 {
99 hal_pwm_disable_controller(configuration->channel);
100 }
101 }
102 else if (cmd == PWM_CMD_SET)
103 {
104 LOG_D("PWM_CMD_SET");
105 result = set(device, (struct rt_pwm_configuration *)arg);
106 if(hal_pwm_device->status)
107 {
108 struct pwm_config pwm_cfg;
109 pwm_cfg.polarity = PWM_POLARITY_NORMAL;
110 pwm_cfg.duty_ns = hal_pwm_device->pulse[configuration->channel];
111 pwm_cfg.period_ns = hal_pwm_device->period[configuration->channel];
112 if (hal_pwm_control(configuration->channel, &pwm_cfg) != 0)
113 {
114 result = -RT_EIO;
115 }
116 }
117 }
118 else if (cmd == PWM_CMD_GET)
119 {
120 LOG_D("PWM_CMD_GET");
121 result = get(device, (struct rt_pwm_configuration *)arg);
122 }
123
124 return result;
125 }
126
127 static const struct rt_pwm_ops pwm_ops =
128 {
129 control,
130 };
131
rt_hw_pwm_init(void)132 int rt_hw_pwm_init(void)
133 {
134 /* add pwm initial. */
135 if (hal_pwm_init() != 0)
136 {
137 LOG_E("init pwm failed!");
138 return -1;
139 }
140 _hal_pwm_device.status = 0;
141 return rt_device_pwm_register(&_hal_pwm_device.parent, "pwm", &pwm_ops, RT_NULL);
142 }
143 INIT_DEVICE_EXPORT(rt_hw_pwm_init);
144
145 #endif /* RT_USING_PWM && BSP_USING_PWM */
146