1102142c9SAndrei Pistirica /* 2102142c9SAndrei Pistirica * Support of SDHCI for Microchip PIC32 SoC. 3102142c9SAndrei Pistirica * 4102142c9SAndrei Pistirica * Copyright (C) 2015 Microchip Technology Inc. 5102142c9SAndrei Pistirica * Andrei Pistirica <andrei.pistirica@microchip.com> 6102142c9SAndrei Pistirica * 7102142c9SAndrei Pistirica * SPDX-License-Identifier: GPL-2.0+ 8102142c9SAndrei Pistirica */ 9102142c9SAndrei Pistirica 10102142c9SAndrei Pistirica #include <dm.h> 11102142c9SAndrei Pistirica #include <common.h> 12102142c9SAndrei Pistirica #include <sdhci.h> 131221ce45SMasahiro Yamada #include <linux/errno.h> 14102142c9SAndrei Pistirica #include <mach/pic32.h> 15102142c9SAndrei Pistirica 16102142c9SAndrei Pistirica DECLARE_GLOBAL_DATA_PTR; 17102142c9SAndrei Pistirica 182cd44e1eSMasahiro Yamada static int pic32_sdhci_get_cd(struct sdhci_host *host) 195e96217fSJaehoon Chung { 205e96217fSJaehoon Chung /* PIC32 SDHCI CD errata: 215e96217fSJaehoon Chung * - set CD_TEST and clear CD_TEST_INS bit 225e96217fSJaehoon Chung */ 235e96217fSJaehoon Chung sdhci_writeb(host, SDHCI_CTRL_CD_TEST, SDHCI_HOST_CONTROL); 245e96217fSJaehoon Chung 255e96217fSJaehoon Chung return 0; 265e96217fSJaehoon Chung } 275e96217fSJaehoon Chung 285e96217fSJaehoon Chung static const struct sdhci_ops pic32_sdhci_ops = { 292cd44e1eSMasahiro Yamada .get_cd = pic32_sdhci_get_cd, 305e96217fSJaehoon Chung }; 315e96217fSJaehoon Chung 32102142c9SAndrei Pistirica static int pic32_sdhci_probe(struct udevice *dev) 33102142c9SAndrei Pistirica { 34102142c9SAndrei Pistirica struct sdhci_host *host = dev_get_priv(dev); 35102142c9SAndrei Pistirica const void *fdt = gd->fdt_blob; 36102142c9SAndrei Pistirica u32 f_min_max[2]; 37102142c9SAndrei Pistirica fdt_addr_t addr; 38102142c9SAndrei Pistirica fdt_size_t size; 39102142c9SAndrei Pistirica int ret; 40102142c9SAndrei Pistirica 41102142c9SAndrei Pistirica addr = fdtdec_get_addr_size(fdt, dev->of_offset, "reg", &size); 42102142c9SAndrei Pistirica if (addr == FDT_ADDR_T_NONE) 43102142c9SAndrei Pistirica return -EINVAL; 44102142c9SAndrei Pistirica 45102142c9SAndrei Pistirica host->ioaddr = ioremap(addr, size); 46cacd1d2fSMasahiro Yamada host->name = dev->name; 476f88a3a5SJaehoon Chung host->quirks = SDHCI_QUIRK_NO_HISPD_BIT; 48102142c9SAndrei Pistirica host->bus_width = fdtdec_get_int(gd->fdt_blob, dev->of_offset, 49102142c9SAndrei Pistirica "bus-width", 4); 505e96217fSJaehoon Chung host->ops = &pic32_sdhci_ops; 51102142c9SAndrei Pistirica 52102142c9SAndrei Pistirica ret = fdtdec_get_int_array(gd->fdt_blob, dev->of_offset, 53102142c9SAndrei Pistirica "clock-freq-min-max", f_min_max, 2); 54102142c9SAndrei Pistirica if (ret) { 55102142c9SAndrei Pistirica printf("sdhci: clock-freq-min-max not found\n"); 56102142c9SAndrei Pistirica return ret; 57102142c9SAndrei Pistirica } 58102142c9SAndrei Pistirica 59*6d0e34bfSStefan Herbrechtsmeier host->max_clk = f_min_max[1]; 60*6d0e34bfSStefan Herbrechtsmeier 61*6d0e34bfSStefan Herbrechtsmeier ret = add_sdhci(host, 0, f_min_max[0]); 62cffe5d86SSimon Glass if (ret) 63cffe5d86SSimon Glass return ret; 64cffe5d86SSimon Glass host->mmc->dev = dev; 65cffe5d86SSimon Glass 66cffe5d86SSimon Glass return 0; 67102142c9SAndrei Pistirica } 68102142c9SAndrei Pistirica 69102142c9SAndrei Pistirica static const struct udevice_id pic32_sdhci_ids[] = { 70102142c9SAndrei Pistirica { .compatible = "microchip,pic32mzda-sdhci" }, 71102142c9SAndrei Pistirica { } 72102142c9SAndrei Pistirica }; 73102142c9SAndrei Pistirica 74102142c9SAndrei Pistirica U_BOOT_DRIVER(pic32_sdhci_drv) = { 75102142c9SAndrei Pistirica .name = "pic32_sdhci", 76102142c9SAndrei Pistirica .id = UCLASS_MMC, 77102142c9SAndrei Pistirica .of_match = pic32_sdhci_ids, 78102142c9SAndrei Pistirica .probe = pic32_sdhci_probe, 79102142c9SAndrei Pistirica .priv_auto_alloc_size = sizeof(struct sdhci_host), 80102142c9SAndrei Pistirica }; 81