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
aspeed_sdhci_irq_ofdata_to_platdata(struct udevice * dev)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
aspeed_sdhci_irq_probe(struct udevice * dev)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, ®s);
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