1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (C) ASPEED Technology Inc.
4  */
5 
6 #include <common.h>
7 #include <clk.h>
8 #include <dm.h>
9 #include <errno.h>
10 #include <fdtdec.h>
11 #include <asm/io.h>
12 #include <linux/io.h>
13 #include <linux/ioport.h>
14 
15 #define TIMING_PHASE_OFFSET 0xf4
16 #define SDHCI140_SLOT_0_MIRROR_OFFSET 0x10
17 #define SDHCI240_SLOT_0_MIRROR_OFFSET 0x20
18 #define SDHCI140_SLOT_0_CAP_REG_1_OFFSET 0x140
19 #define SDHCI240_SLOT_0_CAP_REG_1_OFFSET 0x240
20 
21 struct aspeed_sdhci_general_reg {
22 	u32 genreal_info;
23 	u32 debounce_setting;
24 	u32 bus_setting;
25 };
26 
27 struct aspeed_sdhci_general_data {
28 	struct aspeed_sdhci_general_reg *regs;
29 	struct clk_bulk clks;
30 };
31 
32 static int aspeed_sdhci_irq_ofdata_to_platdata(struct udevice *dev)
33 {
34 	struct aspeed_sdhci_general_data *priv = dev_get_priv(dev);
35 
36 	return clk_get_bulk(dev, &priv->clks);
37 }
38 
39 static int aspeed_sdhci_irq_probe(struct udevice *dev)
40 {
41 	struct aspeed_sdhci_general_data *priv = dev_get_priv(dev);
42 	int ret = 0;
43 	struct resource regs;
44 	void __iomem  *sdhci_ctrl_base;
45 	u32 timing_phase;
46 	u32 reg_val;
47 
48 	debug("%s(dev=%p) \n", __func__, dev);
49 
50 	ret = clk_enable_bulk(&priv->clks);
51 	if (ret) {
52 		pr_debug("fail enable sdhci clk \n");
53 		return ret;
54 	}
55 
56 	ret = dev_read_resource(dev, 0, &regs);
57 	if (ret < 0)
58 		return ret;
59 
60 	sdhci_ctrl_base = (void __iomem  *)regs.start;
61 
62 	timing_phase = dev_read_u32_default(dev, "timing-phase", 0);
63 	writel(timing_phase, sdhci_ctrl_base + TIMING_PHASE_OFFSET);
64 
65 	if (dev_read_bool(dev, "sdhci_hs200")) {
66 		reg_val = readl(sdhci_ctrl_base + SDHCI140_SLOT_0_CAP_REG_1_OFFSET);
67 		/* support 1.8V */
68 		reg_val |= BIT(26);
69 		writel(reg_val, sdhci_ctrl_base + SDHCI140_SLOT_0_MIRROR_OFFSET);
70 		reg_val = readl(sdhci_ctrl_base + SDHCI240_SLOT_0_CAP_REG_1_OFFSET);
71 		/* support 1.8V */
72 		reg_val |= BIT(26);
73 		writel(reg_val, sdhci_ctrl_base + SDHCI240_SLOT_0_MIRROR_OFFSET);
74 	}
75 
76 	return 0;
77 }
78 
79 static const struct udevice_id aspeed_sdhci_irq_ids[] = {
80 	{ .compatible = "aspeed,aspeed-sdhci-irq" },
81 	{ .compatible = "aspeed,aspeed-emmc-irq" },
82 	{ }
83 };
84 
85 U_BOOT_DRIVER(aspeed_sdhci_ic) = {
86 	.name		= "aspeed_sdhci_ic",
87 	.id			= UCLASS_MISC,
88 	.of_match	= aspeed_sdhci_irq_ids,
89 	.probe		= aspeed_sdhci_irq_probe,
90 	.ofdata_to_platdata = aspeed_sdhci_irq_ofdata_to_platdata,
91 	.priv_auto_alloc_size = sizeof(struct aspeed_sdhci_general_data),
92 };
93