1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Support of SDHCI for Microchip PIC32 SoC. 4 * 5 * Copyright (C) 2015 Microchip Technology Inc. 6 * Andrei Pistirica <andrei.pistirica@microchip.com> 7 */ 8 9 #include <common.h> 10 #include <dm.h> 11 #include <sdhci.h> 12 #include <linux/errno.h> 13 #include <mach/pic32.h> 14 15 DECLARE_GLOBAL_DATA_PTR; 16 17 static int pic32_sdhci_get_cd(struct sdhci_host *host) 18 { 19 /* PIC32 SDHCI CD errata: 20 * - set CD_TEST and clear CD_TEST_INS bit 21 */ 22 sdhci_writeb(host, SDHCI_CTRL_CD_TEST, SDHCI_HOST_CONTROL); 23 24 return 0; 25 } 26 27 static const struct sdhci_ops pic32_sdhci_ops = { 28 .get_cd = pic32_sdhci_get_cd, 29 }; 30 31 static int pic32_sdhci_probe(struct udevice *dev) 32 { 33 struct sdhci_host *host = dev_get_priv(dev); 34 const void *fdt = gd->fdt_blob; 35 u32 f_min_max[2]; 36 fdt_addr_t addr; 37 fdt_size_t size; 38 int ret; 39 40 addr = fdtdec_get_addr_size(fdt, dev_of_offset(dev), "reg", &size); 41 if (addr == FDT_ADDR_T_NONE) 42 return -EINVAL; 43 44 host->ioaddr = ioremap(addr, size); 45 host->name = dev->name; 46 host->quirks = SDHCI_QUIRK_NO_HISPD_BIT; 47 host->bus_width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev), 48 "bus-width", 4); 49 host->ops = &pic32_sdhci_ops; 50 51 ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev), 52 "clock-freq-min-max", f_min_max, 2); 53 if (ret) { 54 printf("sdhci: clock-freq-min-max not found\n"); 55 return ret; 56 } 57 58 host->max_clk = f_min_max[1]; 59 60 ret = add_sdhci(host, 0, f_min_max[0]); 61 if (ret) 62 return ret; 63 host->mmc->dev = dev; 64 65 return 0; 66 } 67 68 static const struct udevice_id pic32_sdhci_ids[] = { 69 { .compatible = "microchip,pic32mzda-sdhci" }, 70 { } 71 }; 72 73 U_BOOT_DRIVER(pic32_sdhci_drv) = { 74 .name = "pic32_sdhci", 75 .id = UCLASS_MMC, 76 .of_match = pic32_sdhci_ids, 77 .probe = pic32_sdhci_probe, 78 .priv_auto_alloc_size = sizeof(struct sdhci_host), 79 }; 80