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  * 2021-02-02     michael5hzg@gmail.com       adapt to ls1b
10  */
11 
12 
13 #include "ls1b_public.h"
14 #include "ls1b_regs.h"
15 #include "ls1b_gpio.h"
16 #include "ls1b_pin.h"
17 
18 
19 /*
20  * 获取指定gpio的CFG寄存器
21  * @gpio gpio编号
22  * @ret CFG寄存器
23  */
gpio_get_cfg_reg(unsigned int gpio)24 volatile unsigned int *gpio_get_cfg_reg(unsigned int gpio)
25 {
26     volatile unsigned int *gpio_cfgx = NULL;            // GPIO_CFGx寄存器
27     unsigned int port = GPIO_GET_PORT(gpio);
28 
29     switch (port)
30     {
31         case 0:
32             gpio_cfgx = (volatile unsigned int *)LS1B_GPIO_CFG0;
33             break;
34 
35         case 1:
36             gpio_cfgx = (volatile unsigned int *)LS1B_GPIO_CFG1;
37             break;
38         default:
39             gpio_cfgx = NULL;
40             break;
41     }
42 
43     return gpio_cfgx;
44 }
45 
46 
47 /*
48  * 获取指定gpio的EN寄存器
49  * @gpio gpio编号
50  * @ret EN寄存器
51  */
gpio_get_en_reg(unsigned int gpio)52 volatile unsigned int *gpio_get_en_reg(unsigned int gpio)
53 {
54     volatile unsigned int *gpio_enx = NULL;         // GPIO_ENx寄存器
55     unsigned int port = GPIO_GET_PORT(gpio);
56 
57     switch (port)
58     {
59         case 0:
60             gpio_enx = (volatile unsigned int *)LS1B_GPIO_EN0;
61             break;
62 
63         case 1:
64             gpio_enx = (volatile unsigned int *)LS1B_GPIO_EN1;
65             break;
66         default:
67             gpio_enx    = NULL;
68             return gpio_enx;
69     }
70 
71     return gpio_enx;
72 }
73 
74 /*
75  * gpio初始化
76  * @gpio gpio引脚,取值范围[0, 127]
77  * @mode gpio的工作模式(输入、输出)
78  *
79  * 例: 将gpio50初始化为输出
80  * gpio_init(50, gpio_mode_output);
81  */
gpio_init(unsigned int gpio,gpio_mode_t mode)82 void gpio_init(unsigned int gpio, gpio_mode_t mode)
83 {
84     volatile unsigned int *gpio_enx = NULL;        // GPIO_ENx寄存器
85     unsigned int pin = GPIO_GET_PIN(gpio);
86 
87     // 将pin设为普通GPIO
88     pin_set_purpose(gpio, PIN_PURPOSE_GPIO);
89 
90     // 设置gpio工作模式(输入、输出)
91     gpio_enx  = gpio_get_en_reg(gpio);
92     if (gpio_mode_output == mode)       // 输出
93     {
94         reg_clr_one_bit(gpio_enx, pin);
95     }
96     else                                // 输入
97     {
98         reg_set_one_bit(gpio_enx, pin);
99     }
100 
101     return ;
102 }
103 
104 
105 /*
106  * 在指定gpio输出高电平或低电平
107  * @gpio gpio引脚,取值范围[0, 127]
108  * @level 电平值
109  *
110  * 例: 在gpio50上输出低电平
111  * gpio_set(50, gpio_level_low);
112  */
gpio_set(unsigned int gpio,gpio_level_t level)113 void gpio_set(unsigned int gpio, gpio_level_t level)
114 {
115     volatile unsigned int *gpio_outx = NULL;       // GPIO_OUTx寄存器
116     unsigned int port   = GPIO_GET_PORT(gpio);
117     unsigned int pin    = GPIO_GET_PIN(gpio);
118 
119     // 获取寄存器地址
120     switch (port)
121     {
122         case 0:
123             gpio_outx = (volatile unsigned int *)LS1B_GPIO_OUT0;
124             break;
125 
126         case 1:
127             gpio_outx = (volatile unsigned int *)LS1B_GPIO_OUT1;
128             break;
129         default:        // 正确的程序不应该走到这里,直接返回
130             return ;
131     }
132 
133     // 输出
134     if (gpio_level_low == level)
135     {
136         reg_clr_one_bit(gpio_outx, pin);
137     }
138     else
139     {
140         reg_set_one_bit(gpio_outx, pin);
141     }
142 
143     return ;
144 }
145 
146 
147 /*
148  * 读取指定gpio引脚的值
149  * @gpio gpio引脚,取值范围[0,127]
150  *
151  * 例: 读取gpio50引脚上的值
152  * gpio_level_t level;
153  * level = gpio_get(50);
154  */
gpio_get(unsigned int gpio)155 unsigned int gpio_get(unsigned int gpio)
156 {
157     volatile unsigned int *gpio_inx = NULL;        // GPIO_INx寄存器
158     unsigned int port   = GPIO_GET_PORT(gpio);
159     unsigned int pin    = GPIO_GET_PIN(gpio);
160 
161     // 获取寄存器地址
162     switch (port)
163     {
164         case 0:
165             gpio_inx = (volatile unsigned int *)LS1B_GPIO_IN0;
166             break;
167 
168         case 1:
169             gpio_inx = (volatile unsigned int *)LS1B_GPIO_IN1;
170             break;
171         default:        // 正常的流程不应该走到这里,直接返回
172             return 0;
173     }
174 
175     // 读取
176     return reg_get_bit(gpio_inx, pin);
177 }
178 
179 
180 /**
181  * 设置中断类型
182  * @gpio gpio引脚
183  * @type 触发中断的条件。高电平触发、低电平触发、上升沿触发 or 下降沿触发
184  */
gpio_set_irq_type(unsigned int gpio,gpio_irq_type_t type)185 void gpio_set_irq_type(unsigned int gpio, gpio_irq_type_t type)
186 {
187     volatile unsigned int *int_pol = NULL;     // 中断极性选择寄存器
188     volatile unsigned int *int_edge = NULL;    // 中断边沿选择寄存器
189     unsigned int port = GPIO_GET_PORT(gpio);
190     unsigned int pin  = GPIO_GET_PIN(gpio);
191 
192     // 获取寄存器地址
193     switch (port)
194     {
195         case 0:     // GPIO[31:0]
196             int_pol     = (volatile unsigned int *)LS1B_INT2_POL;
197             int_edge    = (volatile unsigned int *)LS1B_INT2_EDGE;
198             break;
199 
200         case 1:     // GPIO[63:32]
201             int_pol     = (volatile unsigned int *)LS1B_INT3_POL;
202             int_edge    = (volatile unsigned int *)LS1B_INT3_EDGE;
203             break;
204 
205     }
206 
207     // 设置中断类型
208     switch (type)
209     {
210         case IRQ_TYPE_EDGE_RISING:
211             *int_pol    |= (1 << pin);
212             *int_edge   |= (1 << pin);
213             break;
214 
215         case IRQ_TYPE_EDGE_FALLING:
216             *int_pol    &= ~(1 << pin);
217             *int_edge   |= (1 << pin);
218             break;
219 
220         case IRQ_TYPE_LEVEL_HIGH:
221             *int_pol    |= (1 << pin);
222             *int_edge   &= ~(1 << pin);
223             break;
224 
225         case IRQ_TYPE_LEVEL_LOW:
226             *int_pol    &= ~(1 << pin);
227             *int_edge   &= ~(1 << pin);
228             break;
229 
230         default:
231             break;
232     }
233 
234     return ;
235 }
236 
237 
238 
239