1*ddaf02d1SJit Loon Lim /* 2*ddaf02d1SJit Loon Lim * Copyright (c) 2022-2023, Intel Corporation. All rights reserved. 3*ddaf02d1SJit Loon Lim * 4*ddaf02d1SJit Loon Lim * SPDX-License-Identifier: BSD-3-Clause 5*ddaf02d1SJit Loon Lim */ 6*ddaf02d1SJit Loon Lim 7*ddaf02d1SJit Loon Lim #include <assert.h> 8*ddaf02d1SJit Loon Lim #include <errno.h> 9*ddaf02d1SJit Loon Lim #include <stdbool.h> 10*ddaf02d1SJit Loon Lim #include <string.h> 11*ddaf02d1SJit Loon Lim 12*ddaf02d1SJit Loon Lim #include <arch_helpers.h> 13*ddaf02d1SJit Loon Lim #include <common/debug.h> 14*ddaf02d1SJit Loon Lim #include <drivers/cadence/cdns_combo_phy.h> 15*ddaf02d1SJit Loon Lim #include <drivers/cadence/cdns_sdmmc.h> 16*ddaf02d1SJit Loon Lim #include <drivers/delay_timer.h> 17*ddaf02d1SJit Loon Lim #include <lib/mmio.h> 18*ddaf02d1SJit Loon Lim #include <lib/utils.h> 19*ddaf02d1SJit Loon Lim 20*ddaf02d1SJit Loon Lim int cdns_sdmmc_write_phy_reg(uint32_t phy_reg_addr, uint32_t phy_reg_addr_value, 21*ddaf02d1SJit Loon Lim uint32_t phy_reg_data, uint32_t phy_reg_data_value) 22*ddaf02d1SJit Loon Lim { 23*ddaf02d1SJit Loon Lim uint32_t data = 0U; 24*ddaf02d1SJit Loon Lim uint32_t value = 0U; 25*ddaf02d1SJit Loon Lim 26*ddaf02d1SJit Loon Lim /* Get PHY register address, write HRS04*/ 27*ddaf02d1SJit Loon Lim value = mmio_read_32(phy_reg_addr); 28*ddaf02d1SJit Loon Lim value &= ~PHY_REG_ADDR_MASK; 29*ddaf02d1SJit Loon Lim value |= phy_reg_addr_value; 30*ddaf02d1SJit Loon Lim mmio_write_32(phy_reg_addr, value); 31*ddaf02d1SJit Loon Lim data = mmio_read_32(phy_reg_addr); 32*ddaf02d1SJit Loon Lim if ((data & PHY_REG_ADDR_MASK) != phy_reg_addr_value) { 33*ddaf02d1SJit Loon Lim ERROR("PHY_REG_ADDR is not set properly\n"); 34*ddaf02d1SJit Loon Lim return -ENXIO; 35*ddaf02d1SJit Loon Lim } 36*ddaf02d1SJit Loon Lim 37*ddaf02d1SJit Loon Lim /* Get PHY register data, write HRS05 */ 38*ddaf02d1SJit Loon Lim value &= ~PHY_REG_DATA_MASK; 39*ddaf02d1SJit Loon Lim value |= phy_reg_data_value; 40*ddaf02d1SJit Loon Lim mmio_write_32(phy_reg_data, value); 41*ddaf02d1SJit Loon Lim data = mmio_read_32(phy_reg_data); 42*ddaf02d1SJit Loon Lim if (data != phy_reg_data_value) { 43*ddaf02d1SJit Loon Lim ERROR("PHY_REG_DATA is not set properly\n"); 44*ddaf02d1SJit Loon Lim return -ENXIO; 45*ddaf02d1SJit Loon Lim } 46*ddaf02d1SJit Loon Lim 47*ddaf02d1SJit Loon Lim return 0; 48*ddaf02d1SJit Loon Lim } 49*ddaf02d1SJit Loon Lim 50*ddaf02d1SJit Loon Lim int cdns_sd_card_detect(void) 51*ddaf02d1SJit Loon Lim { 52*ddaf02d1SJit Loon Lim uint32_t value = 0; 53*ddaf02d1SJit Loon Lim 54*ddaf02d1SJit Loon Lim /* Card detection */ 55*ddaf02d1SJit Loon Lim do { 56*ddaf02d1SJit Loon Lim value = mmio_read_32(SDMMC_CDN(SRS09)); 57*ddaf02d1SJit Loon Lim /* Wait for card insertion. SRS09.CI = 1 */ 58*ddaf02d1SJit Loon Lim } while ((value & (1 << SDMMC_CDN_CI)) == 0); 59*ddaf02d1SJit Loon Lim 60*ddaf02d1SJit Loon Lim if ((value & (1 << SDMMC_CDN_CI)) == 0) { 61*ddaf02d1SJit Loon Lim ERROR("Card does not detect\n"); 62*ddaf02d1SJit Loon Lim return -ENXIO; 63*ddaf02d1SJit Loon Lim } 64*ddaf02d1SJit Loon Lim 65*ddaf02d1SJit Loon Lim return 0; 66*ddaf02d1SJit Loon Lim } 67*ddaf02d1SJit Loon Lim 68*ddaf02d1SJit Loon Lim int cdns_emmc_card_reset(void) 69*ddaf02d1SJit Loon Lim { 70*ddaf02d1SJit Loon Lim uint32_t _status = 0; 71*ddaf02d1SJit Loon Lim 72*ddaf02d1SJit Loon Lim /* Reset embedded card */ 73*ddaf02d1SJit Loon Lim mmio_write_32(SDMMC_CDN(SRS10), (7 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP) | _status); 74*ddaf02d1SJit Loon Lim mdelay(68680); /* ~68680us */ 75*ddaf02d1SJit Loon Lim mmio_write_32(SDMMC_CDN(SRS10), (7 << SDMMC_CDN_BVS) | (0 << SDMMC_CDN_BP)); 76*ddaf02d1SJit Loon Lim udelay(340); /* ~340us */ 77*ddaf02d1SJit Loon Lim 78*ddaf02d1SJit Loon Lim /* Turn on supply voltage */ 79*ddaf02d1SJit Loon Lim /* BVS = 7, BP = 1, BP2 only in UHS2 mode */ 80*ddaf02d1SJit Loon Lim mmio_write_32(SDMMC_CDN(SRS10), (7 << SDMMC_CDN_BVS) | (1 << SDMMC_CDN_BP) | _status); 81*ddaf02d1SJit Loon Lim 82*ddaf02d1SJit Loon Lim return 0; 83*ddaf02d1SJit Loon Lim } 84