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