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 <common.h>
11*4af0d7e8SSimon Glass #include <dm.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
pic32_sdhci_get_cd(struct sdhci_host * host)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
pic32_sdhci_probe(struct udevice * dev)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
41e160f7d4SSimon Glass addr = fdtdec_get_addr_size(fdt, dev_of_offset(dev), "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;
48e160f7d4SSimon Glass host->bus_width = fdtdec_get_int(gd->fdt_blob, dev_of_offset(dev),
49102142c9SAndrei Pistirica "bus-width", 4);
505e96217fSJaehoon Chung host->ops = &pic32_sdhci_ops;
51102142c9SAndrei Pistirica
52e160f7d4SSimon Glass ret = fdtdec_get_int_array(gd->fdt_blob, dev_of_offset(dev),
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
596d0e34bfSStefan Herbrechtsmeier host->max_clk = f_min_max[1];
606d0e34bfSStefan Herbrechtsmeier
616d0e34bfSStefan 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