1 /*
2  * Copyright (c) 2006-2018, RT-Thread Development Team
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  *
6  * Change Logs:
7  * Date           Author       Notes
8  * 2017-09-06     ��Ϊ��       first version
9  */
10 
11 // ��װӲ��pwm�ӿ�
12 
13 #include "ls1c_public.h"
14 #include "ls1c_pin.h"
15 #include "ls1c_pwm.h"
16 #include "ls1c_clock.h"
17 #include "ls1c_regs.h"
18 
19 // pwm���������
20 #define PWM_MAX_PERIOD                  (0xFFFFFF)      // ��������ֵ
21 
22 /*
23  * ����gpio��ȡ��Ӧpwm�Ļ���ַ
24  * @gpio pwm����
25  * @ret pwm����ַ
26  */
pwm_get_reg_base(unsigned int gpio)27 unsigned int pwm_get_reg_base(unsigned int gpio)
28 {
29     unsigned int reg_base = 0;
30 
31     switch (gpio)
32     {
33         case LS1C_PWM0_GPIO06:
34         case LS1C_PWM0_GPIO04:
35             reg_base = LS1C_REG_BASE_PWM0;
36             break;
37 
38         case LS1C_PWM1_GPIO92:
39         case LS1C_PWM1_GPIO05:
40             reg_base = LS1C_REG_BASE_PWM1;
41             break;
42 
43         case LS1C_PWM2_GPIO52:
44         case LS1C_PWM2_GPIO46:
45             reg_base = LS1C_REG_BASE_PWM2;
46             break;
47 
48         case LS1C_PWM3_GPIO47:
49         case LS1C_PWM3_GPIO53:
50             reg_base = LS1C_REG_BASE_PWM3;
51             break;
52     }
53 
54     return reg_base;
55 }
56 
57 
58 /*
59  * ��ֹpwm
60  * @pwm_info PWMn����ϸ��Ϣ
61  */
pwm_disable(pwm_info_t * pwm_info)62 void pwm_disable(pwm_info_t *pwm_info)
63 {
64     unsigned int pwm_reg_base = 0;
65 
66     // ������
67     if (NULL == pwm_info)
68     {
69         return ;
70     }
71 
72     pwm_reg_base = pwm_get_reg_base(pwm_info->gpio);
73     reg_write_32(0, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CTRL));
74 
75     return ;
76 }
77 
78 
79 
80 /*
81  * ʹ��PWM
82  * @pwm_info PWMn����ϸ��Ϣ
83  */
pwm_enable(pwm_info_t * pwm_info)84 void pwm_enable(pwm_info_t *pwm_info)
85 {
86     unsigned int pwm_reg_base = 0;
87     unsigned int ctrl = 0;
88 
89     // ������
90     if (NULL == pwm_info)
91     {
92         return ;
93     }
94 
95     // ��ȡ����ַ
96     pwm_reg_base = pwm_get_reg_base(pwm_info->gpio);
97 
98     // ���������
99     reg_write_32(0, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CNTR));
100 
101     // ���ÿ��ƼĴ���
102     ctrl = (0 << LS1C_PWM_INT_LRC_EN)
103            | (0 << LS1C_PWM_INT_HRC_EN)
104            | (0 << LS1C_PWM_CNTR_RST)
105            | (0 << LS1C_PWM_INT_SR)
106            | (0 << LS1C_PWM_INTEN)
107            | (0 << LS1C_PWM_OE)
108            | (1 << LS1C_PWM_CNT_EN);
109     if (PWM_MODE_PULSE == pwm_info->mode)     // ������
110     {
111         ctrl |= (1 << LS1C_PWM_SINGLE);
112     }
113     else                            // ��������
114     {
115         ctrl &= ~(1 << LS1C_PWM_SINGLE);
116     }
117     reg_write_32(ctrl, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_CTRL));
118 
119     return ;
120 }
121 
122 
123 
124 /*
125  * ��ʼ��PWMn
126  * @pwm_info PWMn����ϸ��Ϣ
127  */
pwm_init(pwm_info_t * pwm_info)128 void pwm_init(pwm_info_t *pwm_info)
129 {
130     unsigned int gpio;
131     unsigned long pwm_clk = 0;          // pwmģ���ʱ��Ƶ��
132     unsigned long tmp = 0;
133     unsigned int pwm_reg_base = 0;
134     unsigned long period = 0;
135 
136     // �ж����
137     if (NULL == pwm_info)
138     {
139         // ��ηǷ�����ֱ�ӷ���
140         return ;
141     }
142     gpio = pwm_info->gpio;
143 
144     // ������Ӧ��������pwm������gpio
145     pin_set_purpose(gpio, PIN_PURPOSE_OTHER);
146 
147     // ����
148     switch (gpio)
149     {
150         // ����Ҫ����
151         case LS1C_PWM0_GPIO06:
152         case LS1C_PWM1_GPIO92:
153             break;
154 
155         case LS1C_PWM0_GPIO04:          // gpio04�ĵ�������
156             pin_set_remap(LS1C_PWM0_GPIO04, PIN_REMAP_THIRD);
157             break;
158 
159         case LS1C_PWM1_GPIO05:          // gpio05�ĵ�������
160             pin_set_remap(LS1C_PWM1_GPIO05, PIN_REMAP_THIRD);
161             break;
162 
163         case LS1C_PWM2_GPIO52:          // gpio52�ĵ��ĸ���
164             pin_set_remap(LS1C_PWM2_GPIO52, PIN_REMAP_FOURTH);
165             break;
166 
167         case LS1C_PWM2_GPIO46:          // gpio46�ĵ��ĸ���
168             pin_set_remap(LS1C_PWM2_GPIO46, PIN_REMAP_FOURTH);
169             break;
170 
171         case LS1C_PWM3_GPIO47:          // gpio47�ĵ��ĸ���
172             pin_set_remap(LS1C_PWM3_GPIO47, PIN_REMAP_FOURTH);
173             break;
174 
175         case LS1C_PWM3_GPIO53:          // gpio53�ĵ��ĸ���
176             pin_set_remap(LS1C_PWM3_GPIO53, PIN_REMAP_FOURTH);
177             break;
178 
179         default:
180             break;
181     }
182 
183     // ����ռ�ձȺ�pwm���ڼ���Ĵ���HRC��LRC��ֵ
184     // ����64λ����ˣ�ֻ�ܵõ���32λ��linux��ȴ���Եõ�64λ�����
185     // �ݲ����ԭ���ø����������
186     pwm_clk = clk_get_apb_rate();
187     period = (1.0 * pwm_clk * pwm_info->period_ns) / 1000000000;
188     period = MIN(period, PWM_MAX_PERIOD);       // �������ڲ��ܳ������ֵ
189     tmp = period - (period * pwm_info->duty);
190 
191     // д�Ĵ���HRC��LRC
192     pwm_reg_base = pwm_get_reg_base(gpio);
193     reg_write_32(--tmp, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_HRC));
194     reg_write_32(--period, (volatile unsigned int *)(pwm_reg_base + LS1C_PWM_LRC));
195 
196     // д��������
197     pwm_enable(pwm_info);
198 
199     return ;
200 }
201 
202