1 /*
2  * Copyright (C) 2015-2020 Alibaba Group Holding Limited
3  */
4 
5 #include <drv/pwm.h>
6 #include <aos/pwm_core.h>
7 #include "hal_pwm.h"
8 #include "hal_gpio.h"
9 #include "hal_trace.h"
10 #include "hal_iomux.h"
11 #include "hal_cmu.h"
12 #include "pmu.h"
13 
14 #define NS_PER_SEC (1000000000UL)
15 #define DIV_ROUND_CLOSEST(x, divisor)(          \
16 {                                               \
17     typeof(x) __x = x;                          \
18     typeof(divisor) __d = divisor;              \
19     (((typeof(x))-1) > 0 ||                     \
20      ((typeof(divisor))-1) > 0 ||               \
21      (((__x) > 0) == ((__d) > 0))) ?            \
22         (((__x) + ((__d) / 2)) / (__d)) :       \
23         (((__x) - ((__d) / 2)) / (__d));        \
24 }                                               \
25 )
26 typedef struct {
27     aos_pwm_t aos_pwm;
28     void *priv;
29 } haas1000_pwm_t;
30 
31 #define _HAL_PWM_MAX_NUM 4
32 static struct HAL_IOMUX_PIN_FUNCTION_MAP pinmux_pwm[_HAL_PWM_MAX_NUM] = {
33     { HAL_IOMUX_PIN_P2_6, HAL_IOMUX_FUNC_PWM0, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENALBE },
34     { HAL_IOMUX_PIN_P2_7, HAL_IOMUX_FUNC_PWM1, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENALBE },
35     { HAL_IOMUX_PIN_P2_4, HAL_IOMUX_FUNC_PWM2, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENALBE },
36     { HAL_IOMUX_PIN_P2_5, HAL_IOMUX_FUNC_PWM3, HAL_IOMUX_PIN_VOLTAGE_VIO, HAL_IOMUX_PIN_PULLUP_ENALBE },
37 };
38 
39 static uint8_t pwm_chan[_HAL_PWM_MAX_NUM] = {0};
haas1000_pwm_uninit(haas1000_pwm_t * pwm)40 static void haas1000_pwm_uninit(haas1000_pwm_t *pwm)
41 {
42     return;
43 }
44 
haas1000_pwm_out_config(haas1000_pwm_t * pwm,uint32_t channel,uint32_t period_ns,uint32_t pulse_width_ns,csi_pwm_polarity_t polarity)45 int haas1000_pwm_out_config(haas1000_pwm_t *pwm, uint32_t channel, uint32_t period_ns,
46                             uint32_t pulse_width_ns, csi_pwm_polarity_t polarity)
47 {
48     struct HAL_PWM_CFG_T cfg;
49 
50     if (channel >= _HAL_PWM_MAX_NUM)
51             return 0;
52     if (pwm_chan[channel] == 0) {
53         hal_iomux_init(&pinmux_pwm[channel], 1);
54         hal_gpio_pin_set_dir(pinmux_pwm[channel].pin, HAL_GPIO_DIR_OUT, 1);
55     }
56     pwm_chan[channel] = 1;
57     if (period_ns == 0) {
58         hal_pwm_disable(channel);
59     } else {
60         cfg.freq = DIV_ROUND_CLOSEST(NS_PER_SEC, period_ns);
61         cfg.ratio = DIV_ROUND_CLOSEST(((uint64_t)pulse_width_ns) * 100, period_ns);
62         cfg.inv = polarity;
63         cfg.sleep_on = false;
64         hal_pwm_enable(channel, &cfg);
65     }
66     return 0;
67 }
68 
haas1000_pwm_out_start(haas1000_pwm_t * pwm_dev,uint32_t channel)69 static int haas1000_pwm_out_start(haas1000_pwm_t *pwm_dev, uint32_t channel)
70 {
71     return 0;
72 }
73 
haas1000_pwm_out_stop(haas1000_pwm_t * pwm_dev,uint32_t channel)74 static int haas1000_pwm_out_stop(haas1000_pwm_t *pwm_dev, uint32_t channel)
75 {
76     uint32_t pwm_chan = channel;
77     hal_pwm_disable(pwm_chan);
78     return 0;
79 }
80 
haas1000_pwm_unregister(aos_pwm_t * pwm)81 static void haas1000_pwm_unregister(aos_pwm_t *pwm)
82 {
83     haas1000_pwm_t *pwm_dev = aos_container_of(pwm, haas1000_pwm_t, aos_pwm);
84 
85     haas1000_pwm_uninit(pwm_dev);
86 }
87 
haas1000_pwm_startup(aos_pwm_t * pwm)88 static int haas1000_pwm_startup(aos_pwm_t *pwm)
89 {
90     return 0;
91 }
92 
haas1000_pwm_shutdown(aos_pwm_t * pwm)93 static void haas1000_pwm_shutdown(aos_pwm_t *pwm)
94 {
95     haas1000_pwm_t *pwm_dev = aos_container_of(pwm, haas1000_pwm_t, aos_pwm);
96     haas1000_pwm_out_stop(pwm_dev, pwm_dev->aos_pwm.dev.id);
97 }
98 
haas1000_pwm_apply(aos_pwm_t * pwm,aos_pwm_attr_t const * attr)99 static int haas1000_pwm_apply(aos_pwm_t *pwm, aos_pwm_attr_t const *attr)
100 {
101     uint32_t period;
102     uint32_t duty_cycle;
103 
104     haas1000_pwm_t *pwm_dev = aos_container_of(pwm, haas1000_pwm_t, aos_pwm);
105     period = attr->period;
106     duty_cycle = attr->duty_cycle;
107     haas1000_pwm_out_config(pwm_dev, pwm_dev->aos_pwm.dev.id,
108                             period, duty_cycle, attr->polarity);
109     if (attr->enabled)
110         haas1000_pwm_out_start(pwm_dev, pwm_dev->aos_pwm.dev.id);
111     else
112         haas1000_pwm_out_stop(pwm_dev, pwm_dev->aos_pwm.dev.id);
113     return 0;
114 }
115 
116 static const aos_pwm_ops_t haas1000_pwm_ops = {
117     .unregister = haas1000_pwm_unregister,
118     .apply      = haas1000_pwm_apply,
119     .shutdown   = haas1000_pwm_shutdown,
120     .startup    = haas1000_pwm_startup
121 };
haas1000_pwm_init(void)122 static int haas1000_pwm_init(void)
123 {
124     int ret;
125     static haas1000_pwm_t pwm_dev[CONFIG_PWM_NUM];
126     int i;
127     for (i = 0; i < CONFIG_PWM_NUM; i++) {
128         pwm_dev[i].aos_pwm.dev.id = i;
129         pwm_dev[i].aos_pwm.ops = &haas1000_pwm_ops;
130         ret = aos_pwm_register(&(pwm_dev[i].aos_pwm));
131         if  (ret != 0) {
132             return ret;
133         }
134     }
135     return 0;
136 }
137 
138 LEVEL1_DRIVER_ENTRY(haas1000_pwm_init)
139