1// Copyright 2018 The Fuchsia Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include <inttypes.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <unistd.h>
10
11#include <sys/param.h>
12#include <ddk/device.h>
13#include <ddk/debug.h>
14#include <ddk/protocol/sdmmc.h>
15#include <ddk/protocol/sdio.h>
16
17#include <zircon/process.h>
18#include <zircon/threads.h>
19
20#include "sdmmc.h"
21#include "sdio.h"
22
23static zx_status_t sdio_rw_byte(sdmmc_device_t *dev, bool write, uint8_t fn_idx, uint32_t addr,
24                                uint8_t write_byte, uint8_t *read_byte) {
25    if (!sdio_fn_idx_valid(fn_idx)) {
26        return ZX_ERR_INVALID_ARGS;
27    }
28    read_byte = write ? NULL : read_byte;
29    write_byte = write ? write_byte : 0;
30    return sdio_io_rw_direct(dev, write, fn_idx, addr, write_byte, read_byte);
31}
32
33static zx_status_t sdio_read_after_write_byte(sdmmc_device_t *dev, uint8_t fn_idx, uint32_t addr,
34                                              uint8_t write_byte, uint8_t *read_byte) {
35    if (!sdio_fn_idx_valid(fn_idx)) {
36        return ZX_ERR_INVALID_ARGS;
37    }
38    return sdio_io_rw_direct(dev, true, fn_idx, addr, write_byte, read_byte);
39}
40
41zx_status_t sdio_rw_data(void *ctx, uint8_t fn_idx, sdio_rw_txn_t *txn) {
42    if (!sdio_fn_idx_valid(fn_idx)) {
43        return ZX_ERR_INVALID_ARGS;
44    }
45
46    sdmmc_device_t *dev = ctx;
47    zx_status_t st = ZX_OK;
48    uint32_t addr = txn->addr;
49    uint32_t data_size = txn->data_size;
50    bool use_dma = txn->use_dma;
51
52    // Single byte reads at some addresses are stuck when using io_rw_extended.
53    // Use io_rw_direct whenever possible.
54    if (!use_dma && data_size == 1) {
55        return sdio_rw_byte(dev, txn->write, fn_idx, addr,
56                            *(uintptr_t*)(txn->virt), txn->virt);
57    }
58
59    if ((data_size % 4) != 0) {
60        //TODO(ravoorir): This is definitely needed for PIO mode. Astro has
61        //a hardware bug about not supporting DMA. We end up doing non-dma
62        //transfers on astro.For now restrict the size for dma requests as well.
63        zxlogf(ERROR, "sdio_rw_data: data size is not a multiple of 4\n");
64        return ZX_ERR_NOT_SUPPORTED;
65    }
66    bool dma_supported = sdmmc_use_dma(dev);
67    void *buf = use_dma ? NULL : txn->virt;
68    zx_handle_t dma_vmo = use_dma ? txn->dma_vmo : ZX_HANDLE_INVALID;
69    uint64_t buf_offset = txn->buf_offset;
70
71    if (txn->use_dma && !dma_supported) {
72        // host does not support dma
73        st = zx_vmar_map(zx_vmar_root_self(),
74                         ZX_VM_PERM_READ | ZX_VM_PERM_WRITE,
75                         0, txn->dma_vmo, txn->buf_offset, data_size,
76                         (uintptr_t*)&buf);
77        if (st != ZX_OK) {
78            zxlogf(TRACE, "sdio_rw_data: vmo map error %d\n", st);
79            return ZX_ERR_IO;
80        }
81        use_dma = false;
82        dma_vmo = ZX_HANDLE_INVALID;
83        buf_offset = 0; //set it to 0 since we mapped starting from offset.
84    }
85
86    bool mbs = (dev->sdio_dev.hw_info.caps) & SDIO_CARD_MULTI_BLOCK;
87    uint32_t func_blk_size = (dev->sdio_dev.funcs[fn_idx]).cur_blk_size;
88    uint32_t rem_blocks = (func_blk_size == 0) ? 0 : (data_size / func_blk_size);
89    uint32_t data_processed = 0;
90    while (rem_blocks > 0) {
91        uint32_t num_blocks = 1;
92        if (mbs) {
93            uint32_t max_host_blocks;
94            max_host_blocks = use_dma ? ((dev->host_info.max_transfer_size) / func_blk_size) :
95                                      ((dev->host_info.max_transfer_size_non_dma) / func_blk_size);
96            // multiblock is supported, determine max number of blocks per cmd
97            num_blocks = MIN(MIN(SDIO_IO_RW_EXTD_MAX_BLKS_PER_CMD, max_host_blocks), rem_blocks);
98        }
99        st = sdio_io_rw_extended(dev, txn->write, fn_idx, addr, txn->incr, num_blocks,
100                                 func_blk_size, use_dma, buf, dma_vmo,
101                                 buf_offset + data_processed);
102        if (st != ZX_OK) {
103            zxlogf(ERROR, "sdio_rw_data: Error %sing data.func: %d status: %d\n",
104                   txn->write ? "writ" : "read", fn_idx, st);
105            return st;
106        }
107        rem_blocks -= num_blocks;
108        data_processed += num_blocks * func_blk_size;
109        if (txn->incr) {
110            addr += data_processed;
111        }
112    }
113
114    if (data_processed < data_size) {
115        // process remaining data.
116        st = sdio_io_rw_extended(dev, txn->write, fn_idx, addr, txn->incr,
117                                 1, (data_size - data_processed), use_dma, buf, dma_vmo,
118                                 buf_offset + data_processed);
119    }
120
121    if (txn->use_dma && !dma_supported) {
122        zx_vmar_unmap(zx_vmar_root_self(), (uintptr_t)buf, data_size);
123    }
124
125    return st;
126}
127
128static zx_status_t sdio_read_data32(sdmmc_device_t *dev, uint8_t fn_idx, uint32_t addr,
129                                    uint32_t *dword) {
130    sdio_rw_txn_t txn;
131    txn.addr = addr;
132    txn.write = false;
133    txn.virt = dword;
134    txn.data_size = 4;
135    txn.incr = true;
136    txn.use_dma = false;
137    txn.buf_offset = 0;
138    return sdio_rw_data(dev, fn_idx, &txn);
139}
140
141static zx_status_t sdio_write_data32(sdmmc_device_t *dev, uint8_t fn_idx, uint32_t addr,
142                                     uint32_t dword) {
143    sdio_rw_txn_t txn;
144    txn.addr = addr;
145    txn.write = true;
146    txn.virt = (void *)&dword;
147    txn.data_size = 4;
148    txn.incr = true;
149    txn.use_dma = false;
150    txn.buf_offset = 0;
151    return sdio_rw_data(dev, fn_idx, &txn);
152}
153
154static zx_status_t sdio_read_data16(sdmmc_device_t *dev, uint8_t fn_idx, uint32_t addr,
155                                    uint16_t *word) {
156    uint8_t byte1 = 0, byte2 = 0;
157    zx_status_t st = sdio_rw_byte(dev, false, 0, addr, 0, &byte1);
158    if (st != ZX_OK) {
159        zxlogf(ERROR, "sdio_read_data16: Error reading from addr:0x%x, retcode: %d\n", addr, st);
160        return st;
161    }
162
163    st = sdio_rw_byte(dev, false, 0, addr + 1, 0, &byte2);
164    if (st != ZX_OK) {
165        zxlogf(ERROR, "sdio_read_data16: Error reading from addr:0x%x, retcode: %d\n", addr + 1,
166               st);
167        return st;
168    }
169
170    *word = byte2 << 8 | byte1;
171    return ZX_OK;
172}
173
174static zx_status_t sdio_write_data16(sdmmc_device_t *dev, uint8_t fn_idx, uint32_t addr,
175                                     uint16_t word) {
176    zx_status_t st = sdio_rw_byte(dev, true, 0, addr, word & 0xff, NULL);
177    if (st != ZX_OK) {
178        zxlogf(ERROR, "sdio_write_data16: Error writing to addr:0x%x, retcode: %d\n", addr, st);
179        return st;
180    }
181
182    st = sdio_rw_byte(dev, true, 0, addr + 1, (word >> 8) & 0xff, NULL);
183    if (st != ZX_OK) {
184        zxlogf(ERROR, "sdio_write_data16: Error writing to addr:0x%x, retcode: %d\n", addr + 1,
185               st);
186        return st;
187    }
188
189    return ZX_OK;
190}
191
192zx_status_t sdio_get_device_hw_info(void *ctx, sdio_hw_info_t *dev_info) {
193    sdmmc_device_t *dev = ctx;
194    sdio_device_t *sdio_dev = &(dev->sdio_dev);
195    memcpy(&(dev_info->dev_hw_info), &(sdio_dev->hw_info), sizeof(sdio_device_hw_info_t));
196    for (size_t i = 0; i < sdio_dev->hw_info.num_funcs; i++) {
197        memcpy(&(dev_info->funcs_hw_info[i]), &(sdio_dev->funcs[i].hw_info),
198                 sizeof(sdio_func_hw_info_t));
199    }
200    dev_info->host_max_transfer_size = dev->host_info.max_transfer_size;
201    return ZX_OK;
202}
203
204static uint32_t sdio_read_tuple_body(uint8_t *t_body, size_t start, size_t numbytes) {
205    uint32_t res = 0;
206
207    for (size_t i = start; i < (start + numbytes); i++) {
208        res |= t_body[i] << ((i - start)* 8);
209    }
210    return res;
211}
212
213static zx_status_t sdio_process_cccr(sdmmc_device_t *dev) {
214    uint8_t cccr_vsn, sdio_vsn, vsn_info, bus_speed, card_caps, uhs_caps, drv_strength;
215
216    //version info
217    zx_status_t status = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_CCCR_SDIO_VER_ADDR, 0, &vsn_info);
218    if (status != ZX_OK) {
219        zxlogf(ERROR, "sdio_process_cccr: Error reading CCCR reg: %d\n", status);
220        return status;
221    }
222    cccr_vsn = get_bits(vsn_info, SDIO_CIA_CCCR_CCCR_VER_MASK, SDIO_CIA_CCCR_CCCR_VER_LOC);
223    sdio_vsn = get_bits(vsn_info, SDIO_CIA_CCCR_SDIO_VER_MASK, SDIO_CIA_CCCR_SDIO_VER_LOC);
224    if ((cccr_vsn < SDIO_CCCR_FORMAT_VER_3) || (sdio_vsn < SDIO_SDIO_VER_3)) {
225        return ZX_ERR_NOT_SUPPORTED;
226    }
227    dev->sdio_dev.hw_info.cccr_vsn = cccr_vsn;
228    dev->sdio_dev.hw_info.sdio_vsn = sdio_vsn;
229
230    //card capabilities
231    status = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_CARD_CAPS_ADDR, 0, &card_caps);
232    if (status != ZX_OK) {
233        zxlogf(ERROR, "sdio_process_cccr: Error reading CAPS reg: %d\n", status);
234        return status;
235    }
236    dev->sdio_dev.hw_info.caps = 0;
237    if (card_caps & SDIO_CIA_CCCR_CARD_CAP_SMB) {
238        dev->sdio_dev.hw_info.caps |= SDIO_CARD_MULTI_BLOCK;
239    }
240    if (card_caps & SDIO_CIA_CCCR_CARD_CAP_LSC) {
241        dev->sdio_dev.hw_info.caps |= SDIO_CARD_LOW_SPEED;
242    }
243    if (card_caps & SDIO_CIA_CCCR_CARD_CAP_4BLS) {
244        dev->sdio_dev.hw_info.caps |= SDIO_CARD_4BIT_BUS;
245    }
246
247    //speed
248    status = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_BUS_SPEED_SEL_ADDR, 0, &bus_speed);
249    if (status != ZX_OK) {
250        zxlogf(ERROR, "sdio_process_cccr: Error reading SPEED reg: %d\n", status);
251        return status;
252    }
253    if (bus_speed & SDIO_CIA_CCCR_BUS_SPEED_SEL_SHS) {
254        dev->sdio_dev.hw_info.caps |= SDIO_CARD_HIGH_SPEED;
255    }
256
257    // Is UHS supported?
258    status = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_UHS_SUPPORT_ADDR, 0, &uhs_caps);
259    if (status != ZX_OK) {
260        zxlogf(ERROR, "sdio_process_cccr: Error reading SPEED reg: %d\n", status);
261        return status;
262    }
263    if (uhs_caps & SDIO_CIA_CCCR_UHS_SDR50) {
264        dev->sdio_dev.hw_info.caps |= SDIO_CARD_UHS_SDR50;
265    }
266    if (uhs_caps & SDIO_CIA_CCCR_UHS_SDR104) {
267        dev->sdio_dev.hw_info.caps |= SDIO_CARD_UHS_SDR104;
268    }
269    if (uhs_caps & SDIO_CIA_CCCR_UHS_DDR50) {
270        dev->sdio_dev.hw_info.caps |= SDIO_CARD_UHS_DDR50;
271    }
272
273    //drv_strength
274    status = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_DRV_STRENGTH_ADDR, 0,
275                               &drv_strength);
276    if (status != ZX_OK) {
277        zxlogf(ERROR, "sdio_process_cccr: Error reading SPEED reg: %d\n", status);
278        return status;
279    }
280    if (drv_strength & SDIO_CIA_CCCR_DRV_STRENGTH_SDTA) {
281        dev->sdio_dev.hw_info.caps |= SDIO_DRIVER_TYPE_A;
282    }
283    if (drv_strength & SDIO_CIA_CCCR_DRV_STRENGTH_SDTB) {
284        dev->sdio_dev.hw_info.caps |= SDIO_DRIVER_TYPE_B;
285    }
286    if (drv_strength & SDIO_CIA_CCCR_DRV_STRENGTH_SDTD) {
287        dev->sdio_dev.hw_info.caps |= SDIO_DRIVER_TYPE_D;
288    }
289    return status;
290}
291
292static zx_status_t sdio_parse_func_ext_tuple(sdmmc_device_t* dev, uint32_t fn_idx,
293                                             sdio_func_tuple_t *tup) {
294    sdio_function_t *func = &(dev->sdio_dev.funcs[fn_idx]);
295    if (fn_idx == 0) {
296        if (tup->t_body_size < SDIO_CIS_TPL_FUNC0_FUNCE_MIN_BDY_SZ) {
297            return ZX_ERR_IO;
298        }
299        func->hw_info.max_blk_size = sdio_read_tuple_body(tup->t_body,
300                                                  SDIO_CIS_TPL_FUNCE_FUNC0_MAX_BLK_SIZE_LOC, 2);
301        func->hw_info.max_blk_size = MIN(dev->host_info.max_transfer_size,
302                                         func->hw_info.max_blk_size);
303        uint8_t speed_val = get_bits_u8(tup->t_body[3], SDIO_CIS_TPL_FUNCE_MAX_TRAN_SPEED_VAL_MASK,
304                                        SDIO_CIS_TPL_FUNCE_MAX_TRAN_SPEED_VAL_LOC);
305        uint8_t speed_unit = get_bits_u8(tup->t_body[3],
306                                         SDIO_CIS_TPL_FUNCE_MAX_TRAN_SPEED_UNIT_MASK,
307                                         SDIO_CIS_TPL_FUNCE_MAX_TRAN_SPEED_UNIT_LOC);
308        func->hw_info.max_tran_speed = sdio_cis_tpl_funce_tran_speed_val[speed_val] *
309                               sdio_cis_tpl_funce_tran_speed_unit[speed_unit];
310        return ZX_OK;
311    }
312
313    if (tup->t_body_size < SDIO_CIS_TPL_FUNCx_FUNCE_MIN_BDY_SZ) {
314        zxlogf(ERROR, "sdio_parse_func_ext: Invalid body size: %d for func_ext tuple\n",
315               tup->t_body_size);
316        return ZX_ERR_IO;
317    }
318    func->hw_info.max_blk_size =  sdio_read_tuple_body(tup->t_body,
319                                               SDIO_CIS_TPL_FUNCE_FUNCx_MAX_BLK_SIZE_LOC, 2);
320    return ZX_OK;
321}
322
323static zx_status_t sdio_parse_mfid_tuple(sdmmc_device_t* dev, uint32_t fn_idx,
324                                         sdio_func_tuple_t *tup) {
325    if (tup->t_body_size < SDIO_CIS_TPL_MANFID_MIN_BDY_SZ) {
326        return ZX_ERR_IO;
327    }
328    sdio_function_t *func = &(dev->sdio_dev.funcs[fn_idx]);
329    func->hw_info.manufacturer_id = sdio_read_tuple_body(tup->t_body, 0, 2);
330    func->hw_info.product_id = sdio_read_tuple_body(tup->t_body, 2, 2);
331    return ZX_OK;
332}
333
334static zx_status_t sdio_parse_fn_tuple(sdmmc_device_t* dev, uint32_t fn_idx,
335                                       sdio_func_tuple_t *tup) {
336    zx_status_t st = ZX_OK;
337    switch (tup->t_code) {
338        case SDIO_CIS_TPL_CODE_MANFID:
339          st = sdio_parse_mfid_tuple(dev, fn_idx, tup);
340          break;
341        case SDIO_CIS_TPL_CODE_FUNCE:
342          st = sdio_parse_func_ext_tuple(dev, fn_idx, tup);
343          break;
344        default:
345          break;
346    }
347    return st;
348}
349
350static zx_status_t sdio_process_cis(sdmmc_device_t* dev, uint32_t fn_idx) {
351    zx_status_t st = ZX_OK;
352
353    if (fn_idx >= SDIO_MAX_FUNCS) {
354        return ZX_ERR_INVALID_ARGS;
355    }
356    uint32_t cis_ptr = 0;
357    for (size_t i = 0; i < SDIO_CIS_ADDRESS_SIZE; i++) {
358        uint8_t addr;
359        st = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_FBR_BASE_ADDR(fn_idx) +
360                               SDIO_CIA_FBR_CIS_ADDR + i, 0, &addr);
361        if (st != ZX_OK) {
362            zxlogf(ERROR, "sdio: Error reading CIS of CCCR reg: %d\n", st);
363            return st;
364        }
365        cis_ptr |= addr << (i * 8);
366    }
367    if (!cis_ptr) {
368        zxlogf(ERROR, "sdio: CIS address is invalid\n");
369        return ZX_ERR_IO;
370    }
371
372    while (true) {
373        uint8_t t_code, t_link;
374        sdio_func_tuple_t cur_tup;
375        st = sdio_io_rw_direct(dev, false, 0, cis_ptr + SDIO_CIS_TPL_FRMT_TCODE_OFF,
376                               0, &t_code);
377        if (st != ZX_OK) {
378            zxlogf(ERROR, "sdio: Error reading tuple code for fn %d\n", fn_idx);
379            break;
380        }
381        // Ignore null tuples
382        if (t_code == SDIO_CIS_TPL_CODE_NULL) {
383            cis_ptr++;
384            continue;
385        }
386        if (t_code == SDIO_CIS_TPL_CODE_END) {
387            break;
388        }
389        st = sdio_io_rw_direct(dev, false, 0, cis_ptr + SDIO_CIS_TPL_FRMT_TLINK_OFF,
390                               0, &t_link);
391        if (st != ZX_OK) {
392            zxlogf(ERROR, "sdio: Error reading tuple size for fn %d\n", fn_idx);
393            break;
394        }
395        if (t_link == SDIO_CIS_TPL_LINK_END) {
396            break;
397        }
398
399        cur_tup.t_code = t_code;
400        cur_tup.t_body_size = t_link;
401        cur_tup.t_body = NULL;
402        cur_tup.t_body = calloc(1, t_link);
403        if (!(cur_tup.t_body)) {
404            st = ZX_ERR_NO_MEMORY;
405            break;
406        }
407
408        cis_ptr += SDIO_CIS_TPL_FRMT_TBODY_OFF;
409        for (size_t i = 0; i < t_link; i++, cis_ptr++) {
410            st = sdio_io_rw_direct(dev, false, 0, cis_ptr, 0, &(cur_tup.t_body[i]));
411            if (st != ZX_OK) {
412                zxlogf(ERROR, "sdio: Error reading tuple body for fn %d\n", fn_idx);
413                free(cur_tup.t_body);
414                return st;
415            }
416        }
417        sdio_parse_fn_tuple(dev, fn_idx, &cur_tup);
418        free(cur_tup.t_body);
419    }
420    return st;
421}
422
423static zx_status_t sdio_switch_freq(sdmmc_device_t* dev, uint32_t new_freq) {
424    zx_status_t st;
425    if ((st = sdmmc_set_bus_freq(&dev->host, new_freq)) != ZX_OK) {
426        zxlogf(ERROR, "sdio: Error while switching host bus frequency, retcode = %d\n", st);
427        return st;
428    }
429    dev->clock_rate = new_freq;
430    return ZX_OK;
431}
432
433static zx_status_t sdio_switch_hs(sdmmc_device_t *dev) {
434    zx_status_t st = ZX_OK;
435    uint8_t speed = 0;
436
437    if (!(dev->sdio_dev.hw_info.caps & SDIO_CARD_HIGH_SPEED)) {
438        zxlogf(ERROR, "sdio: High speed not supported, retcode = %d\n", st);
439        return ZX_ERR_NOT_SUPPORTED;
440    }
441    st = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_BUS_SPEED_SEL_ADDR, 0, &speed);
442    if (st != ZX_OK) {
443        zxlogf(ERROR, "sdio: Error while reading CCCR reg, retcode = %d\n", st);
444        return st;
445    }
446    update_bits_u8(&speed, SDIO_CIA_CCCR_BUS_SPEED_BSS_MASK, SDIO_CIA_CCCR_BUS_SPEED_BSS_LOC,
447                   SDIO_BUS_SPEED_EN_HS);
448    st = sdio_io_rw_direct(dev, true, 0, SDIO_CIA_CCCR_BUS_SPEED_SEL_ADDR, speed, NULL);
449    if (st != ZX_OK) {
450        zxlogf(ERROR, "sdio: Error while writing to CCCR reg, retcode = %d\n", st);
451        return st;
452    }
453    // Switch the host timing
454    if ((st = sdmmc_set_timing(&dev->host, SDMMC_TIMING_HS)) != ZX_OK) {
455        zxlogf(ERROR, "sdio: failed to switch to hs timing on host : %d\n", st);
456        return st;
457    }
458
459    if ((st = sdio_switch_freq(dev, SDIO_HS_MAX_FREQ)) != ZX_OK) {
460        zxlogf(ERROR, "sdio: failed to switch to hs timing on host : %d\n", st);
461        return st;
462    }
463    return st;
464}
465
466static zx_status_t sdio_switch_uhs(sdmmc_device_t *dev) {
467    zx_status_t st = ZX_OK;
468    uint8_t speed = 0;
469    uint32_t hw_caps = dev->sdio_dev.hw_info.caps;
470
471    uint32_t new_freq = SDIO_DEFAULT_FREQ;
472    uint8_t select_speed = SDIO_BUS_SPEED_SDR50;
473    sdmmc_timing_t timing = SDMMC_TIMING_SDR50;
474
475    st = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_BUS_SPEED_SEL_ADDR, 0, &speed);
476    if (st != ZX_OK) {
477        zxlogf(ERROR, "sdio: Error while reading CCCR reg, retcode = %d\n", st);
478        return st;
479    }
480
481    if (hw_caps & SDIO_CARD_UHS_SDR104) {
482        select_speed = SDIO_BUS_SPEED_SDR104;
483        timing = SDMMC_TIMING_SDR104;
484        new_freq = SDIO_UHS_SDR104_MAX_FREQ;
485    } else if (hw_caps & SDIO_CARD_UHS_SDR50) {
486        select_speed = SDIO_BUS_SPEED_SDR50;
487        timing = SDMMC_TIMING_SDR50;
488        new_freq = SDIO_UHS_SDR50_MAX_FREQ;
489    } else if (hw_caps & SDIO_CARD_UHS_DDR50) {
490        select_speed = SDIO_BUS_SPEED_DDR50;
491        timing = SDMMC_TIMING_DDR50;
492        new_freq = SDIO_UHS_DDR50_MAX_FREQ;
493    } else {
494        return ZX_ERR_NOT_SUPPORTED;
495    }
496
497    update_bits_u8(&speed, SDIO_CIA_CCCR_BUS_SPEED_BSS_MASK, SDIO_CIA_CCCR_BUS_SPEED_BSS_LOC,
498                   select_speed);
499
500    st = sdio_io_rw_direct(dev, true, 0, SDIO_CIA_CCCR_BUS_SPEED_SEL_ADDR, speed, NULL);
501    if (st != ZX_OK) {
502        zxlogf(ERROR, "sdio: Error while writing to CCCR reg, retcode = %d\n", st);
503        return st;
504    }
505    // Switch the host timing
506    if ((st = sdmmc_set_timing(&dev->host, timing)) != ZX_OK) {
507        zxlogf(ERROR, "sdio: failed to switch to hs timing on host : %d\n", st);
508        return st;
509    }
510
511    if ((st = sdio_switch_freq(dev, new_freq)) != ZX_OK) {
512        zxlogf(ERROR, "sdio: failed to switch to hs timing on host : %d\n", st);
513        return st;
514    }
515    return st;
516}
517
518static zx_status_t sdio_enable_4bit_bus(sdmmc_device_t *dev) {
519    zx_status_t st = ZX_OK;
520    if ((dev->sdio_dev.hw_info.caps & SDIO_CARD_LOW_SPEED) &&
521        !(dev->sdio_dev.hw_info.caps & SDIO_CARD_4BIT_BUS)) {
522        zxlogf(ERROR, "sdio: Switching to 4-bit bus unsupported\n");
523        return ZX_ERR_NOT_SUPPORTED;
524    }
525    uint8_t bus_ctrl_reg;
526    if ((st = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_BUS_INTF_CTRL_ADDR, 0,
527                                &bus_ctrl_reg)) != ZX_OK) {
528        zxlogf(INFO, "sdio: Error reading the current bus width\n");
529        return st;
530    }
531    update_bits_u8(&bus_ctrl_reg, SDIO_CIA_CCCR_INTF_CTRL_BW_MASK, SDIO_CIA_CCCR_INTF_CTRL_BW_LOC,
532                    SDIO_BW_4BIT);
533    if ((st = sdio_io_rw_direct(dev, true, 0, SDIO_CIA_CCCR_BUS_INTF_CTRL_ADDR, bus_ctrl_reg,
534                                NULL)) != ZX_OK) {
535        zxlogf(ERROR, "sdio: Error while switching the bus width\n");
536        return st;
537    }
538    if ((st = sdmmc_set_bus_width(&dev->host, SDMMC_BUS_WIDTH_4)) != ZX_OK) {
539          zxlogf(ERROR, "sdio: failed to switch the host bus width to %d, retcode = %d\n",
540                 SDMMC_BUS_WIDTH_4, st);
541          return ZX_ERR_INTERNAL;
542    }
543
544    dev->bus_width = SDMMC_BUS_WIDTH_4;
545    return ZX_OK;
546}
547
548static zx_status_t sdio_switch_bus_width(sdmmc_device_t *dev, uint32_t bw) {
549    zx_status_t st = ZX_OK;
550    if (bw != SDIO_BW_1BIT && bw != SDIO_BW_4BIT) {
551        return ZX_ERR_NOT_SUPPORTED;
552    }
553    if (bw == SDIO_BW_4BIT) {
554        if ((st = sdio_enable_4bit_bus(dev)) != ZX_OK) {
555            return st;
556        }
557    }
558    return ZX_OK;
559}
560
561static zx_status_t sdio_process_fbr(sdmmc_device_t *dev, uint8_t fn_idx) {
562    zx_status_t st = ZX_OK;
563    uint8_t fbr, fn_intf_code;
564
565    sdio_function_t *func = &(dev->sdio_dev.funcs[fn_idx]);
566    if ((st = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_FBR_BASE_ADDR(fn_idx) +
567                                SDIO_CIA_FBR_STD_IF_CODE_ADDR, 0, &fbr)) != ZX_OK) {
568        zxlogf(ERROR, "sdio: Error reading intf code: %d\n", st);
569        return st;
570    }
571    fn_intf_code = get_bits_u8(fbr, SDIO_CIA_FBR_STD_IF_CODE_MASK, SDIO_CIA_FBR_STD_IF_CODE_LOC);
572    if (fn_intf_code == SDIO_CIA_FBR_STD_IF_CODE_MASK) {
573        // fn_code > 0Eh
574        if ((st = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_FBR_BASE_ADDR(fn_idx) +
575                                    SDIO_CIA_FBR_STD_IF_CODE_EXT_ADDR, 0,
576                                    &fn_intf_code)) != ZX_OK) {
577            zxlogf(ERROR, "sdio: Error while reading the extended intf code %d\n", st);
578            return st;
579        }
580    }
581    func->hw_info.fn_intf_code = fn_intf_code;
582    return ZX_OK;
583}
584
585zx_status_t sdio_get_cur_block_size(void *ctx, uint8_t fn_idx,
586                                    uint16_t *cur_blk_size) {
587    sdmmc_device_t *dev = ctx;
588
589    zx_status_t st = sdio_read_data16(dev, 0,
590                                      SDIO_CIA_FBR_BASE_ADDR(fn_idx) + SDIO_CIA_FBR_BLK_SIZE_ADDR,
591                                      cur_blk_size);
592    if (st != ZX_OK) {
593        zxlogf(ERROR, "sdio_get_cur_block_size: Failed to get block size for fn: %d ret: %d\n",
594               fn_idx, st);
595    }
596    return st;
597}
598
599zx_status_t sdio_modify_block_size(void *ctx, uint8_t fn_idx, uint16_t blk_size,
600                                         bool set_default) {
601    zx_status_t st = ZX_OK;
602    sdmmc_device_t *dev = ctx;
603
604    sdio_function_t *func = &(dev->sdio_dev.funcs[fn_idx]);
605    if (set_default) {
606        blk_size = func->hw_info.max_blk_size;
607    }
608
609    if (blk_size > func->hw_info.max_blk_size) {
610        return ZX_ERR_INVALID_ARGS;
611    }
612
613    if (func->cur_blk_size == blk_size) {
614        return ZX_OK;
615    }
616
617    st = sdio_write_data16(dev, 0, SDIO_CIA_FBR_BASE_ADDR(fn_idx) + SDIO_CIA_FBR_BLK_SIZE_ADDR,
618                           blk_size);
619    if (st != ZX_OK) {
620        zxlogf(ERROR, "sdio_modify_block_size: Error setting blk size.fn: %d blk_sz: %d ret: %d\n",
621               fn_idx, blk_size, st);
622        return st;
623    }
624
625    func->cur_blk_size = blk_size;
626    return st;
627}
628
629zx_status_t sdio_enable_function(void *ctx, uint8_t fn_idx) {
630    uint8_t ioex_reg = 0;
631    zx_status_t st = ZX_OK;
632    sdmmc_device_t *dev = ctx;
633
634    if (!sdio_fn_idx_valid(fn_idx)) {
635        return ZX_ERR_INVALID_ARGS;
636    }
637
638    sdio_function_t *func = &(dev->sdio_dev.funcs[fn_idx]);
639    if (func->enabled) {
640        return ZX_OK;
641    }
642    if ((st = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_IOEx_EN_FUNC_ADDR, 0,
643                                &ioex_reg)) != ZX_OK) {
644        zxlogf(ERROR, "sdio_enable_function: Error enabling func:%d status:%d\n",
645               fn_idx, st);
646        return st;
647    }
648
649    ioex_reg |= (1 << fn_idx);
650    if ((st = sdio_io_rw_direct(dev, true, 0, SDIO_CIA_CCCR_IOEx_EN_FUNC_ADDR, ioex_reg, NULL))
651        != ZX_OK) {
652        zxlogf(ERROR, "sdio_enable_function: Error enabling func:%d status:%d\n",
653               fn_idx, st);
654        return st;
655    }
656    //wait for the device to enable the func.
657    usleep(10 * 1000);
658    if ((st = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_IOEx_EN_FUNC_ADDR, 0,
659                                &ioex_reg)) != ZX_OK) {
660        zxlogf(ERROR, "sdio_enable_function: Error enabling func:%d status:%d\n",
661               fn_idx, st);
662        return st;
663    }
664
665    if (!(ioex_reg & (1 << fn_idx))) {
666        st = ZX_ERR_IO;
667        zxlogf(ERROR, "sdio_enable_function: Failed to enable func %d\n", fn_idx);
668        return st;
669    }
670
671    func->enabled = true;
672    zxlogf(TRACE, "sdio_enable_function: Func %d is enabled\n", fn_idx);
673    return st;
674}
675
676zx_status_t sdio_disable_function(void *ctx, uint8_t fn_idx) {
677    uint8_t ioex_reg = 0;
678    zx_status_t st = ZX_OK;
679    sdmmc_device_t *dev = ctx;
680
681    if (!sdio_fn_idx_valid(fn_idx)) {
682        return ZX_ERR_INVALID_ARGS;
683    }
684
685    sdio_function_t *func = &(dev->sdio_dev.funcs[fn_idx]);
686    if (!func->enabled) {
687        zxlogf(ERROR, "sdio_disable_function: Func %d is not enabled\n", fn_idx);
688        return ZX_ERR_IO;
689    }
690
691    if ((st = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_IOEx_EN_FUNC_ADDR, 0,
692                                &ioex_reg)) != ZX_OK) {
693        zxlogf(ERROR, "sdio_disable_function: Error reading IOEx reg. func: %d status: %d\n",
694               fn_idx, st);
695        return st;
696    }
697
698    ioex_reg &= ~(1 << fn_idx);
699    if ((st = sdio_io_rw_direct(dev, true, 0, SDIO_CIA_CCCR_IOEx_EN_FUNC_ADDR, ioex_reg, NULL))
700        != ZX_OK) {
701        zxlogf(ERROR, "sdio_disable_function: Error writing IOEx reg. func: %d status:%d\n",
702               fn_idx, st);
703        return st;
704    }
705
706    func->enabled = false;
707    zxlogf(TRACE, "sdio_disable_function: Function %d is disabled\n", fn_idx);
708    return st;
709}
710
711static zx_status_t sdio_init_func(sdmmc_device_t *dev, uint8_t fn_idx) {
712    zx_status_t st = ZX_OK;
713
714    if ((st = sdio_process_fbr(dev, fn_idx)) != ZX_OK) {
715        return st;
716    }
717
718    if ((st = sdio_process_cis(dev, fn_idx)) != ZX_OK) {
719        return st;
720    }
721
722    // Enable all func for now. Should move to wifi driver ?
723    if ((st = sdio_enable_function(dev, fn_idx)) != ZX_OK) {
724        return st;
725    }
726
727    // Set default block size
728    if ((st = sdio_modify_block_size(dev, fn_idx, 0, true)) != ZX_OK) {
729        return st;
730    }
731
732    return st;
733}
734
735zx_status_t sdmmc_sdio_reset(sdmmc_device_t* dev) {
736    zx_status_t st = ZX_OK;
737    uint8_t abort_byte;
738
739    st = sdio_io_rw_direct(dev, false, 0, SDIO_CIA_CCCR_ASx_ABORT_SEL_CR_ADDR, 0, &abort_byte);
740    if (st != ZX_OK) {
741        abort_byte = SDIO_CIA_CCCR_ASx_ABORT_SOFT_RESET;
742    } else {
743        abort_byte |= SDIO_CIA_CCCR_ASx_ABORT_SOFT_RESET;
744    }
745    return sdio_io_rw_direct(dev, true, 0, SDIO_CIA_CCCR_ASx_ABORT_SEL_CR_ADDR, abort_byte, NULL);
746}
747
748
749zx_status_t sdmmc_probe_sdio(sdmmc_device_t* dev) {
750    zx_status_t st = sdmmc_sdio_reset(dev);
751
752    if ((st = sdmmc_go_idle(dev)) != ZX_OK) {
753      zxlogf(ERROR, "sdmmc: SDMMC_GO_IDLE_STATE failed, retcode = %d\n", st);
754      return st;
755    }
756
757    uint32_t ocr;
758    if ((st = sdio_send_op_cond(dev, 0, &ocr)) != ZX_OK) {
759        zxlogf(ERROR, "sdmmc_probe_sdio: SDIO_SEND_OP_COND failed, retcode = %d\n", st);
760        return st;
761    }
762    //Select voltage 3.3 V. Also request for 1.8V. Section 3.2 SDIO spec
763    if (ocr & SDIO_SEND_OP_COND_IO_OCR_33V) {
764        uint32_t new_ocr = SDIO_SEND_OP_COND_IO_OCR_33V | SDIO_SEND_OP_COND_CMD_S18R;
765        if ((st = sdio_send_op_cond(dev, new_ocr, &ocr)) != ZX_OK) {
766            zxlogf(ERROR, "sdmmc_probe_sdio: SDIO_SEND_OP_COND failed, retcode = %d\n", st);
767            return st;
768        }
769    }
770    if (ocr & SDIO_SEND_OP_COND_RESP_MEM_PRESENT) {
771        //Combo cards not supported
772        zxlogf(ERROR, "sdmmc_probe_sdio: Combo card not supported\n");
773        return ZX_ERR_NOT_SUPPORTED;
774    }
775    dev->type = SDMMC_TYPE_SDIO;
776    dev->signal_voltage = SDMMC_VOLTAGE_180;
777    dev->sdio_dev.hw_info.num_funcs = get_bits(ocr, SDIO_SEND_OP_COND_RESP_NUM_FUNC_MASK,
778                                               SDIO_SEND_OP_COND_RESP_NUM_FUNC_LOC);
779    uint16_t addr = 0;
780    if ((st = sd_send_relative_addr(dev, &addr)) != ZX_OK) {
781        zxlogf(ERROR, "sdmcc_probe_sdio: SD_SEND_RELATIVE_ADDR failed, retcode = %d\n", st);
782        return st;
783    }
784    dev->rca = addr;
785    if ((st = mmc_select_card(dev)) != ZX_OK) {
786        zxlogf(ERROR, "sdmmc_probe_sdio: MMC_SELECT_CARD failed, retcode = %d\n", st);
787        return st;
788    }
789
790    if ((st = sdio_process_cccr(dev)) != ZX_OK) {
791        zxlogf(ERROR, "sdmmc_probe_sdio: Read CCCR failed, retcode = %d\n", st);
792        return st;
793    }
794
795    //Read CIS to get max block size
796    if ((st = sdio_process_cis(dev, 0)) != ZX_OK) {
797        zxlogf(ERROR, "sdmmc_probe_sdio: Read CIS failed, retcode = %d\n", st);
798        return st;
799    }
800
801    if (ocr & SDIO_SEND_OP_COND_RESP_S18A) {
802        if ((st = sd_switch_uhs_voltage(dev, ocr)) != ZX_OK) {
803            zxlogf(INFO, "Failed to switch voltage to 1.8V\n");
804            return st;
805        }
806    }
807
808    //TODO(ravoorir):Re-enable ultra high speed when wifi stack is more stable.
809    /* if (sdio_is_uhs_supported(dev->sdio_dev.hw_info.caps)) {
810        if ((st = sdio_switch_bus_width(dev, SDIO_BW_4BIT)) != ZX_OK) {
811            zxlogf(ERROR, "sdmmc_probe_sdio: Swtiching to 4-bit bus width failed, retcode = %d\n",
812                   st);
813            goto high_speed;
814        }
815        if ((st = sdio_switch_uhs(dev)) != ZX_OK) {
816            zxlogf(ERROR, "sdmmc_probe_sdio: Switching to high speed failed, retcode = %d\n", st);
817            goto high_speed;
818        }
819        uint32_t hw_caps = dev->sdio_dev.hw_info.caps;
820
821        if ((hw_caps & SDIO_CARD_UHS_SDR104) || (hw_caps & SDIO_CARD_UHS_SDR50)) {
822            st = sdmmc_perform_tuning(&dev->host, SD_SEND_TUNING_BLOCK);
823            if (st != ZX_OK) {
824                zxlogf(ERROR, "mmc: tuning failed %d\n", st);
825                goto high_speed;
826            }
827        }
828        goto complete;
829    }
830
831high_speed: */
832    if (dev->sdio_dev.hw_info.caps & SDIO_CARD_HIGH_SPEED) {
833        if ((st = sdio_switch_hs(dev)) != ZX_OK) {
834            zxlogf(ERROR, "sdmmc_probe_sdio: Switching to high speed failed, retcode = %d\n", st);
835            goto default_speed;
836        }
837
838        if ((st = sdio_switch_bus_width(dev, SDIO_BW_4BIT)) != ZX_OK) {
839            zxlogf(ERROR, "sdmmc_probe_sdio: Swtiching to 4-bit bus width failed, retcode = %d\n",
840                   st);
841            goto default_speed;
842        }
843        goto complete;
844    }
845
846default_speed:
847    if ((st = sdio_switch_freq(dev, SDIO_DEFAULT_FREQ)) != ZX_OK) {
848        zxlogf(ERROR, "sdmmc_probe_sdio: Switch freq retcode = %d\n", st);
849        return st;
850    }
851
852complete:
853    sdio_modify_block_size(dev, 0, 0, true);
854    // 0 is the common function. Already initialized
855    for (size_t i = 1; i < dev->sdio_dev.hw_info.num_funcs; i++) {
856        st = sdio_init_func(dev, i);
857    }
858
859    zxlogf(INFO, "sdmmc_probe_sdio: sdio device initialized successfully\n");
860    zxlogf(INFO, "          Manufacturer: 0x%x\n", dev->sdio_dev.funcs[0].hw_info.manufacturer_id);
861    zxlogf(INFO, "          Product: 0x%x\n", dev->sdio_dev.funcs[0].hw_info.product_id);
862    zxlogf(INFO, "          cccr vsn: 0x%x\n", dev->sdio_dev.hw_info.cccr_vsn);
863    zxlogf(INFO, "          SDIO vsn: 0x%x\n", dev->sdio_dev.hw_info.sdio_vsn);
864    zxlogf(INFO, "          num funcs: %d\n", dev->sdio_dev.hw_info.num_funcs);
865    return ZX_OK;
866}
867