1442d5568SJaehoon Chung /* 2442d5568SJaehoon Chung * (C) Copyright 2012 SAMSUNG Electronics 3442d5568SJaehoon Chung * Jaehoon Chung <jh80.chung@samsung.com> 4442d5568SJaehoon Chung * 5442d5568SJaehoon Chung * This program is free software; you can redistribute it and/or modify 6442d5568SJaehoon Chung * it under the terms of the GNU General Public License as published by 7442d5568SJaehoon Chung * the Free Software Foundation; either version 2 of the License, or 8442d5568SJaehoon Chung * (at your option) any later version. 9442d5568SJaehoon Chung * 10442d5568SJaehoon Chung * This program is distributed in the hope that it will be useful, 11442d5568SJaehoon Chung * but WITHOUT ANY WARRANTY; without even the implied warranty of 12442d5568SJaehoon Chung * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13442d5568SJaehoon Chung * GNU General Public License for more details. 14442d5568SJaehoon Chung * 15442d5568SJaehoon Chung * You should have received a copy of the GNU General Public License 16442d5568SJaehoon Chung * along with this program; if not, write to the Free Software 17442d5568SJaehoon Chung * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 18442d5568SJaehoon Chung */ 19442d5568SJaehoon Chung 20442d5568SJaehoon Chung #include <common.h> 21442d5568SJaehoon Chung #include <malloc.h> 22442d5568SJaehoon Chung #include <sdhci.h> 23442d5568SJaehoon Chung #include <asm/arch/mmc.h> 24442d5568SJaehoon Chung 25442d5568SJaehoon Chung static char *S5P_NAME = "SAMSUNG SDHCI"; 26442d5568SJaehoon Chung static void s5p_sdhci_set_control_reg(struct sdhci_host *host) 27442d5568SJaehoon Chung { 28442d5568SJaehoon Chung unsigned long val, ctrl; 29442d5568SJaehoon Chung /* 30442d5568SJaehoon Chung * SELCLKPADDS[17:16] 31442d5568SJaehoon Chung * 00 = 2mA 32442d5568SJaehoon Chung * 01 = 4mA 33442d5568SJaehoon Chung * 10 = 7mA 34442d5568SJaehoon Chung * 11 = 9mA 35442d5568SJaehoon Chung */ 36442d5568SJaehoon Chung sdhci_writel(host, SDHCI_CTRL4_DRIVE_MASK(0x3), SDHCI_CONTROL4); 37442d5568SJaehoon Chung 38442d5568SJaehoon Chung val = sdhci_readl(host, SDHCI_CONTROL2); 39442d5568SJaehoon Chung val &= SDHCI_CTRL2_SELBASECLK_SHIFT; 40442d5568SJaehoon Chung 41442d5568SJaehoon Chung val |= SDHCI_CTRL2_ENSTAASYNCCLR | 42442d5568SJaehoon Chung SDHCI_CTRL2_ENCMDCNFMSK | 43442d5568SJaehoon Chung SDHCI_CTRL2_ENFBCLKRX | 44442d5568SJaehoon Chung SDHCI_CTRL2_ENCLKOUTHOLD; 45442d5568SJaehoon Chung 46442d5568SJaehoon Chung sdhci_writel(host, val, SDHCI_CONTROL2); 47442d5568SJaehoon Chung 48442d5568SJaehoon Chung /* 49442d5568SJaehoon Chung * FCSEL3[31] FCSEL2[23] FCSEL1[15] FCSEL0[7] 50442d5568SJaehoon Chung * FCSel[1:0] : Rx Feedback Clock Delay Control 51442d5568SJaehoon Chung * Inverter delay means10ns delay if SDCLK 50MHz setting 52442d5568SJaehoon Chung * 01 = Delay1 (basic delay) 53442d5568SJaehoon Chung * 11 = Delay2 (basic delay + 2ns) 54442d5568SJaehoon Chung * 00 = Delay3 (inverter delay) 55442d5568SJaehoon Chung * 10 = Delay4 (inverter delay + 2ns) 56442d5568SJaehoon Chung */ 57*b268660cSJaehoon Chung val = SDHCI_CTRL3_FCSEL0 | SDHCI_CTRL3_FCSEL1; 58442d5568SJaehoon Chung sdhci_writel(host, val, SDHCI_CONTROL3); 59442d5568SJaehoon Chung 60442d5568SJaehoon Chung /* 61442d5568SJaehoon Chung * SELBASECLK[5:4] 62442d5568SJaehoon Chung * 00/01 = HCLK 63442d5568SJaehoon Chung * 10 = EPLL 64442d5568SJaehoon Chung * 11 = XTI or XEXTCLK 65442d5568SJaehoon Chung */ 66442d5568SJaehoon Chung ctrl = sdhci_readl(host, SDHCI_CONTROL2); 67442d5568SJaehoon Chung ctrl &= ~SDHCI_CTRL2_SELBASECLK_MASK(0x3); 68442d5568SJaehoon Chung ctrl |= SDHCI_CTRL2_SELBASECLK_MASK(0x2); 69442d5568SJaehoon Chung sdhci_writel(host, ctrl, SDHCI_CONTROL2); 70442d5568SJaehoon Chung } 71442d5568SJaehoon Chung 72442d5568SJaehoon Chung int s5p_sdhci_init(u32 regbase, u32 max_clk, u32 min_clk, u32 quirks) 73442d5568SJaehoon Chung { 74442d5568SJaehoon Chung struct sdhci_host *host = NULL; 75442d5568SJaehoon Chung host = (struct sdhci_host *)malloc(sizeof(struct sdhci_host)); 76442d5568SJaehoon Chung if (!host) { 77442d5568SJaehoon Chung printf("sdhci__host malloc fail!\n"); 78442d5568SJaehoon Chung return 1; 79442d5568SJaehoon Chung } 80442d5568SJaehoon Chung 81442d5568SJaehoon Chung host->name = S5P_NAME; 82442d5568SJaehoon Chung host->ioaddr = (void *)regbase; 83442d5568SJaehoon Chung host->quirks = quirks; 84442d5568SJaehoon Chung 85*b268660cSJaehoon Chung host->quirks = SDHCI_QUIRK_NO_HISPD_BIT | SDHCI_QUIRK_BROKEN_VOLTAGE | 86*b268660cSJaehoon Chung SDHCI_QUIRK_BROKEN_R1B | SDHCI_QUIRK_32BIT_DMA_ADDR; 87442d5568SJaehoon Chung host->voltages = MMC_VDD_32_33 | MMC_VDD_33_34 | MMC_VDD_165_195; 88442d5568SJaehoon Chung host->version = sdhci_readw(host, SDHCI_HOST_VERSION); 89442d5568SJaehoon Chung 90442d5568SJaehoon Chung host->set_control_reg = &s5p_sdhci_set_control_reg; 91442d5568SJaehoon Chung 92442d5568SJaehoon Chung host->host_caps = MMC_MODE_HC; 93442d5568SJaehoon Chung 94442d5568SJaehoon Chung add_sdhci(host, max_clk, min_clk); 95442d5568SJaehoon Chung return 0; 96442d5568SJaehoon Chung } 97