1 /**
2 * @file hal_sdhost.c
3 * @author ALLWINNERTECH IOT WLAN Team
4 */
5
6 /*
7 * Copyright (C) 2017 ALLWINNERTECH TECHNOLOGY CO., LTD. All rights reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright
15 * notice, this list of conditions and the following disclaimer in the
16 * documentation and/or other materials provided with the
17 * distribution.
18 * 3. Neither the name of ALLWINNERTECH TECHNOLOGY CO., LTD. nor the names of
19 * its contributors may be used to endorse or promote products derived
20 * from this software without specific prior written permission.
21 *
22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
23 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
25 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
26 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
27 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
28 * LIMITED TO, )|hhst->sdio_irq_maskPROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
32 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33 */
34
35 #include <hal_gpio.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #ifndef CONFIG_KERNEL_FREERTOS
39 #include <log.h>
40 #endif
41 #include "_sdhost.h"
42 #include "_sd_define.h"
43
44 #ifndef SDC_MAX_PIN_NUM
45 #define SDC_MAX_PIN_NUM 13
46 #endif
47
48 typedef struct
49 {
50 uint32_t *pin;
51 uint8_t pin_num : 3;
52 uint8_t pin_mux : 3;
53 uint8_t pin_drv : 2;
54 } sdmmc_pin_t;
55
56 static sdmmc_pin_t sunxi_sdmmc_pin[4];
57
58
sdmmc_pinctl_set_from_cfg(struct mmc_host * host,char * sdc_str,uint32_t pin_num)59 int32_t sdmmc_pinctl_set_from_cfg(struct mmc_host *host, char *sdc_str, uint32_t pin_num)
60 {
61 #ifdef HAL_SetPin
62 int32_t ret = 0;
63 user_gpio_set_t gpiocfg[SDC_MAX_PIN_NUM] = {0};
64 int i = 0;
65 int gpio_num = 0;
66 if (pin_num > SDC_MAX_PIN_NUM) {
67 SDC_LOGE("pin num over %d\n", SDC_MAX_PIN_NUM);
68 return ret;
69 }
70
71 ret = Hal_Cfg_GetGPIOSecData(sdc_str, gpiocfg, pin_num);
72 if(ret < 0) {
73 SDC_LOGE("%s not has pin setting on sys_config.fex\n", sdc_str);
74 return ret;
75 }
76
77 for (i = 0;i < pin_num; i++) {
78 SDC_LOGD("name %s,port %d,port_num %d,mul_sel %d, pull %d, drv_level %d\n",\
79 gpiocfg[i].gpio_name, gpiocfg[i].port, gpiocfg[i].port_num, \
80 gpiocfg[i].mul_sel, gpiocfg[i].pull, gpiocfg[i].drv_level);
81 }
82
83 for(i = 0; i< pin_num; i++ ) {
84 gpio_num = (gpiocfg[i].port - 1) * PINS_PER_BANK + gpiocfg[i].port_num;
85 ret = hal_gpio_pinmux_set_function(gpio_num, gpiocfg[i].mul_sel);
86 if (ret) {
87 SDC_LOGE(
88 "[sdmmc %s] PIN%lu set function failed! return %d\n",
89 sdc_str, gpio_num, ret);
90 return -1;
91 }
92
93 ret = hal_gpio_set_driving_level(gpio_num, gpiocfg[i].drv_level);
94 if (ret) {
95 SDC_LOGE(
96 "[sdmmc %s] PIN%lu set driving level failed! return %d\n",
97 sdc_str, gpio_num, ret);
98 return -1;
99 }
100 ret = hal_gpio_set_pull(gpio_num, gpiocfg[i].pull);
101 if (ret) {
102 SDC_LOGE(
103 "[sdmmc %s] PIN%lu set driving level failed! return %d\n",
104 sdc_str, gpio_num, ret);
105 return -1;
106 }
107 }
108 return ret;
109 #else
110 SDC_LOGN("unsupport sys fex %d\n");
111 return -1;
112 #endif
113 }
114
115
sdmmc_pinctrl_init(struct mmc_host * host)116 uint32_t sdmmc_pinctrl_init(struct mmc_host *host)
117 {
118 uint8_t i;
119 uint32_t flags = 0;
120 int ret;
121 uint32_t host_id = host->sdc_id;
122
123 switch (host_id) {
124 case 0:
125 ret = sdmmc_pinctl_set_from_cfg(host, "sdc0", SDC0_NUM);
126 if(ret < 0) {
127 sunxi_sdmmc_pin[host_id].pin_num = SDC0_NUM;
128 sunxi_sdmmc_pin[host_id].pin_mux = SDMMC_MUXSEL;
129 sunxi_sdmmc_pin[host_id].pin_drv = SDMMC_DRVSEL;
130 sunxi_sdmmc_pin[host_id].pin = malloc(sizeof(uint32_t) * SDC0_NUM);
131 sunxi_sdmmc_pin[host_id].pin[0] = SDC0_CLK;
132 sunxi_sdmmc_pin[host_id].pin[1] = SDC0_CMD;
133 sunxi_sdmmc_pin[host_id].pin[2] = SDC0_D0;
134 sunxi_sdmmc_pin[host_id].pin[3] = SDC0_D1;
135 sunxi_sdmmc_pin[host_id].pin[4] = SDC0_D2;
136 sunxi_sdmmc_pin[host_id].pin[5] = SDC0_D3;
137 SDC_LOGE("sdmmc%ld use default pin setting\n", host_id);
138 } else {
139 SDC_LOGD("sdmmc%ld use pin setting on sys_config.fex\n", host_id);
140 goto out;
141 }
142 break;
143 case 1:
144 if (host->param.pwr_mode == POWER_MODE_330) {
145 hal_gpio_sel_vol_mode(SDC1_D0, POWER_MODE_330);
146 } else {
147 hal_gpio_sel_vol_mode(SDC1_D0, POWER_MODE_180);
148 }
149 ret = sdmmc_pinctl_set_from_cfg(host, "sdc1", SDC1_NUM);
150 if(ret < 0) {
151 sunxi_sdmmc_pin[host_id].pin_num = SDC1_NUM;
152 sunxi_sdmmc_pin[host_id].pin_mux = SDMMC_MUXSEL;
153 sunxi_sdmmc_pin[host_id].pin_drv = SDMMC_DRVSEL;
154 sunxi_sdmmc_pin[host_id].pin = malloc(sizeof(uint32_t) * SDC1_NUM);
155 sunxi_sdmmc_pin[host_id].pin[0] = SDC1_CLK;
156 sunxi_sdmmc_pin[host_id].pin[1] = SDC1_CMD;
157 sunxi_sdmmc_pin[host_id].pin[2] = SDC1_D0;
158 // sunxi_sdmmc_pin[host_id].pin[3] = SDC1_D1;
159 // sunxi_sdmmc_pin[host_id].pin[4] = SDC1_D2;
160 // sunxi_sdmmc_pin[host_id].pin[5] = SDC1_D3;
161 SDC_LOGE("sdmmc%ld use default pin setting\n", host_id);
162 } else {
163 SDC_LOGD("sdmmc%ld use pin setting on sys_config.fex\n", host_id);
164 goto out;
165 }
166 break;
167 default:
168 SDC_LOGE("sdmmc%ld is invalid\n", host_id);
169 return -1;
170
171 }
172
173 for (i = 0; i < sunxi_sdmmc_pin[host_id].pin_num; i++)
174 {
175 ret = hal_gpio_pinmux_set_function(sunxi_sdmmc_pin[host_id].pin[i], sunxi_sdmmc_pin[host_id].pin_mux);
176 if (ret)
177 {
178 SDC_LOGE(
179 "[sdmmc%ld] PIN%lu set function failed! return %d\n",
180 host_id, sunxi_sdmmc_pin[host_id].pin[i], ret);
181 return -1;
182 }
183 ret = hal_gpio_set_driving_level(sunxi_sdmmc_pin[host_id].pin[i], sunxi_sdmmc_pin[host_id].pin_drv);
184 if (ret)
185 {
186 SDC_LOGE(
187 "[sdmmc%ld] PIN%lu set driving level failed! return %d\n",
188 host_id, sunxi_sdmmc_pin[host_id].pin[i], ret);
189 return -1;
190 }
191 ret = hal_gpio_set_pull(sunxi_sdmmc_pin[host_id].pin[i], GPIO_PULL_UP);
192 // ret = drv_gpio_set_pull_state(sunxi_sdmmc_pin[host_id].pin[i], DRV_GPIO_PULL_DOWN_DISABLE);
193 }
194 out:
195 return 0;
196 }
197
mmc_gpiod_request_cd_irq(struct mmc_host * host)198 int mmc_gpiod_request_cd_irq(struct mmc_host *host)
199 {
200 uint32_t irq;
201 int ret = 0;
202 gpio_pull_status_t pull_state;
203 gpio_direction_t gpio_direction;
204 gpio_data_t gpio_data;
205
206 host->cd_gpio_pin = SDC0_DET;
207 /*set gpio detect-clk 24M*/
208 hal_gpio_set_debounce(host->cd_gpio_pin, 1);
209 ret = hal_gpio_to_irq(host->cd_gpio_pin, &irq);
210 if (ret < 0)
211 {
212 SDC_LOGE("gpio to irq error, error num: %d\n", ret);
213 return ret;
214 }
215
216 /*set pin mux*/
217 ret = hal_gpio_pinmux_set_function(host->cd_gpio_pin, 0);
218 ret = hal_gpio_set_driving_level(host->cd_gpio_pin, 3);
219 ret = hal_gpio_set_pull(host->cd_gpio_pin, 1);
220 if (ret < 0)
221 {
222 SDC_LOGE("set pin mux error!\n");
223 return -1;
224 }
225
226 host->cd_irq = irq;
227 ret = hal_gpio_irq_request(irq, host->cd_gpio_isr, IRQ_TYPE_EDGE_BOTH, host);
228 if (ret < 0)
229 {
230 SDC_LOGE("request irq error, irq num:%lu error num: %d\n", (unsigned long)irq, ret);
231 return ret;
232 }
233
234 #if 0
235 ret = drv_gpio_irq_enable(irq);
236 if (ret < 0)
237 {
238 printf("request irq error, error num: %d\n", ret);
239 return ret;
240 }
241 ret = drv_gpio_irq_disable(irq);
242 if (ret < 0)
243 {
244 printf("disable irq error, irq num:%lu,error num: %d\n", irq, ret);
245 return ret;
246 }
247
248 ret = drv_gpio_irq_free(irq);
249 if (ret < 0)
250 {
251 printf("free irq error, error num: %d\n", ret);
252 return ret;
253 }
254 #endif
255 return ret;
256 }
257
258