xref: /openbmc/u-boot/drivers/mmc/pic32_sdhci.c (revision e8f80a5a)
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