xref: /openbmc/u-boot/drivers/mmc/aspeed_sdhci_ic.c (revision 125f2e11f0b1f726a662ea0abaaf1ba111827377)
16f6f06c1Sryan_chen // SPDX-License-Identifier: GPL-2.0+
26f6f06c1Sryan_chen /*
36f6f06c1Sryan_chen  * Copyright (C) ASPEED Technology Inc.
46f6f06c1Sryan_chen  */
56f6f06c1Sryan_chen 
66f6f06c1Sryan_chen #include <common.h>
76f6f06c1Sryan_chen #include <clk.h>
86f6f06c1Sryan_chen #include <dm.h>
96f6f06c1Sryan_chen #include <errno.h>
106f6f06c1Sryan_chen #include <fdtdec.h>
116f6f06c1Sryan_chen #include <asm/io.h>
12730fd353SChin-Ting Kuo #include <linux/io.h>
13730fd353SChin-Ting Kuo #include <linux/ioport.h>
14730fd353SChin-Ting Kuo 
15730fd353SChin-Ting Kuo #define TIMING_PHASE_OFFSET 0xf4
16*125f2e11SChin-Ting Kuo #define SDHCI140_SLOT_0_MIRROR_OFFSET 0x10
17*125f2e11SChin-Ting Kuo #define SDHCI240_SLOT_0_MIRROR_OFFSET 0x20
18*125f2e11SChin-Ting Kuo #define SDHCI140_SLOT_0_CAP_REG_1_OFFSET 0x140
19*125f2e11SChin-Ting Kuo #define SDHCI240_SLOT_0_CAP_REG_1_OFFSET 0x240
206f6f06c1Sryan_chen 
216f6f06c1Sryan_chen struct aspeed_sdhci_general_reg {
226f6f06c1Sryan_chen 	u32 genreal_info;
236f6f06c1Sryan_chen 	u32 debounce_setting;
246f6f06c1Sryan_chen 	u32 bus_setting;
256f6f06c1Sryan_chen };
266f6f06c1Sryan_chen 
276f6f06c1Sryan_chen struct aspeed_sdhci_general_data {
286f6f06c1Sryan_chen 	struct aspeed_sdhci_general_reg *regs;
296f6f06c1Sryan_chen 	struct clk_bulk clks;
306f6f06c1Sryan_chen };
316f6f06c1Sryan_chen 
aspeed_sdhci_irq_ofdata_to_platdata(struct udevice * dev)326f6f06c1Sryan_chen static int aspeed_sdhci_irq_ofdata_to_platdata(struct udevice *dev)
336f6f06c1Sryan_chen {
346f6f06c1Sryan_chen 	struct aspeed_sdhci_general_data *priv = dev_get_priv(dev);
356f6f06c1Sryan_chen 
366f6f06c1Sryan_chen 	return clk_get_bulk(dev, &priv->clks);
376f6f06c1Sryan_chen }
386f6f06c1Sryan_chen 
aspeed_sdhci_irq_probe(struct udevice * dev)396f6f06c1Sryan_chen static int aspeed_sdhci_irq_probe(struct udevice *dev)
406f6f06c1Sryan_chen {
416f6f06c1Sryan_chen 	struct aspeed_sdhci_general_data *priv = dev_get_priv(dev);
426f6f06c1Sryan_chen 	int ret = 0;
43730fd353SChin-Ting Kuo 	struct resource regs;
44730fd353SChin-Ting Kuo 	void __iomem  *sdhci_ctrl_base;
45730fd353SChin-Ting Kuo 	u32 timing_phase;
46*125f2e11SChin-Ting Kuo 	u32 reg_val;
476f6f06c1Sryan_chen 
486f6f06c1Sryan_chen 	debug("%s(dev=%p) \n", __func__, dev);
496f6f06c1Sryan_chen 
506f6f06c1Sryan_chen 	ret = clk_enable_bulk(&priv->clks);
516f6f06c1Sryan_chen 	if (ret) {
526f6f06c1Sryan_chen 		pr_debug("fail enable sdhci clk \n");
536f6f06c1Sryan_chen 		return ret;
546f6f06c1Sryan_chen 	}
556f6f06c1Sryan_chen 
56730fd353SChin-Ting Kuo 	ret = dev_read_resource(dev, 0, &regs);
57730fd353SChin-Ting Kuo 	if (ret < 0)
58730fd353SChin-Ting Kuo 		return ret;
59730fd353SChin-Ting Kuo 
60730fd353SChin-Ting Kuo 	sdhci_ctrl_base = (void __iomem  *)regs.start;
61730fd353SChin-Ting Kuo 
62730fd353SChin-Ting Kuo 	timing_phase = dev_read_u32_default(dev, "timing-phase", 0);
63730fd353SChin-Ting Kuo 	writel(timing_phase, sdhci_ctrl_base + TIMING_PHASE_OFFSET);
64730fd353SChin-Ting Kuo 
65*125f2e11SChin-Ting Kuo 	if (dev_read_bool(dev, "sdhci_hs200")) {
66*125f2e11SChin-Ting Kuo 		reg_val = readl(sdhci_ctrl_base + SDHCI140_SLOT_0_CAP_REG_1_OFFSET);
67*125f2e11SChin-Ting Kuo 		/* support 1.8V */
68*125f2e11SChin-Ting Kuo 		reg_val |= BIT(26);
69*125f2e11SChin-Ting Kuo 		writel(reg_val, sdhci_ctrl_base + SDHCI140_SLOT_0_MIRROR_OFFSET);
70*125f2e11SChin-Ting Kuo 		reg_val = readl(sdhci_ctrl_base + SDHCI240_SLOT_0_CAP_REG_1_OFFSET);
71*125f2e11SChin-Ting Kuo 		/* support 1.8V */
72*125f2e11SChin-Ting Kuo 		reg_val |= BIT(26);
73*125f2e11SChin-Ting Kuo 		writel(reg_val, sdhci_ctrl_base + SDHCI240_SLOT_0_MIRROR_OFFSET);
74*125f2e11SChin-Ting Kuo 	}
75*125f2e11SChin-Ting Kuo 
766f6f06c1Sryan_chen 	return 0;
776f6f06c1Sryan_chen }
786f6f06c1Sryan_chen 
796f6f06c1Sryan_chen static const struct udevice_id aspeed_sdhci_irq_ids[] = {
806f6f06c1Sryan_chen 	{ .compatible = "aspeed,aspeed-sdhci-irq" },
81f51926eeSryan_chen 	{ .compatible = "aspeed,aspeed-emmc-irq" },
826f6f06c1Sryan_chen 	{ }
836f6f06c1Sryan_chen };
846f6f06c1Sryan_chen 
856f6f06c1Sryan_chen U_BOOT_DRIVER(aspeed_sdhci_ic) = {
866f6f06c1Sryan_chen 	.name		= "aspeed_sdhci_ic",
876f6f06c1Sryan_chen 	.id			= UCLASS_MISC,
886f6f06c1Sryan_chen 	.of_match	= aspeed_sdhci_irq_ids,
896f6f06c1Sryan_chen 	.probe		= aspeed_sdhci_irq_probe,
906f6f06c1Sryan_chen 	.ofdata_to_platdata = aspeed_sdhci_irq_ofdata_to_platdata,
916f6f06c1Sryan_chen 	.priv_auto_alloc_size = sizeof(struct aspeed_sdhci_general_data),
926f6f06c1Sryan_chen };
93