1 // SPDX-License-Identifier: GPL-2.0+
3 * (C) Copyright 2019 Cortina Access
4 * Arthur Li <arthur.li@cortina-access.com>
10 #include <asm/global_data.h>
11 #include <linux/libfdt.h>
17 #define SD_CLK_SEL_MASK (0x3)
18 #define SD_DLL_DEFAULT (0x143000)
19 #define SD_SCLK_MAX (200000000)
21 #define SD_CLK_SEL_200MHZ (0x2)
22 #define SD_CLK_SEL_100MHZ (0x1)
23 #define SD_CLK_SEL_50MHZ (0x0)
25 #define IO_DRV_SD_DS_OFFSET (16)
26 #define IO_DRV_SD_DS_MASK (0xff << IO_DRV_SD_DS_OFFSET)
28 #define MIN_FREQ (400000)
30 DECLARE_GLOBAL_DATA_PTR
;
33 struct mmc_config cfg
;
37 struct ca_dwmmc_priv_data
{
38 struct dwmci_host host
;
39 void __iomem
*sd_dll_reg
;
40 void __iomem
*io_drv_reg
;
44 static int ca_dwmci_clksel(struct dwmci_host
*host
)
46 struct ca_dwmmc_priv_data
*priv
= host
->priv
;
47 u32 val
= readl(priv
->sd_dll_reg
);
49 val
&= ~SD_CLK_SEL_MASK
;
50 if (host
->bus_hz
>= 200000000)
51 val
|= SD_CLK_SEL_200MHZ
;
52 else if (host
->bus_hz
>= 100000000)
53 val
|= SD_CLK_SEL_100MHZ
;
55 writel(val
, priv
->sd_dll_reg
);
60 static void ca_dwmci_board_init(struct dwmci_host
*host
)
62 struct ca_dwmmc_priv_data
*priv
= host
->priv
;
63 u32 val
= readl(priv
->io_drv_reg
);
65 writel(SD_DLL_DEFAULT
, priv
->sd_dll_reg
);
67 val
&= ~IO_DRV_SD_DS_MASK
;
69 val
|= priv
->ds
<< IO_DRV_SD_DS_OFFSET
;
70 writel(val
, priv
->io_drv_reg
);
73 unsigned int ca_dwmci_get_mmc_clock(struct dwmci_host
*host
, uint freq
)
75 struct ca_dwmmc_priv_data
*priv
= host
->priv
;
76 u8 sd_clk_sel
= readl(priv
->sd_dll_reg
) & SD_CLK_SEL_MASK
;
80 case SD_CLK_SEL_50MHZ
:
83 case SD_CLK_SEL_100MHZ
:
90 return SD_SCLK_MAX
/ clk_div
/ (host
->div
+ 1);
93 static int ca_dwmmc_of_to_plat(struct udevice
*dev
)
95 struct ca_dwmmc_priv_data
*priv
= dev_get_priv(dev
);
96 struct dwmci_host
*host
= &priv
->host
;
99 host
->name
= dev
->name
;
102 host
->buswidth
= dev_read_u32_default(dev
, "bus-width", 1);
103 host
->bus_hz
= dev_read_u32_default(dev
, "max-frequency", 50000000);
104 priv
->ds
= dev_read_u32_default(dev
, "io_ds", 0x33);
105 host
->fifo_mode
= dev_read_bool(dev
, "fifo-mode");
107 dev_read_u32(dev
, "sd_dll_ctrl", &tmp
);
108 priv
->sd_dll_reg
= map_sysmem((uintptr_t)tmp
, sizeof(uintptr_t));
109 if (!priv
->sd_dll_reg
)
112 dev_read_u32(dev
, "io_drv_ctrl", &tmp
);
113 priv
->io_drv_reg
= map_sysmem((uintptr_t)tmp
, sizeof(uintptr_t));
114 if (!priv
->io_drv_reg
)
117 host
->ioaddr
= dev_read_addr_ptr(dev
);
126 struct dm_mmc_ops ca_dwmci_dm_ops
;
128 static int ca_dwmmc_probe(struct udevice
*dev
)
130 struct ca_mmc_plat
*plat
= dev_get_plat(dev
);
131 struct mmc_uclass_priv
*upriv
= dev_get_uclass_priv(dev
);
132 struct ca_dwmmc_priv_data
*priv
= dev_get_priv(dev
);
133 struct dwmci_host
*host
= &priv
->host
;
135 memcpy(&ca_dwmci_dm_ops
, &dm_dwmci_ops
, sizeof(struct dm_mmc_ops
));
137 dwmci_setup_cfg(&plat
->cfg
, host
, host
->bus_hz
, MIN_FREQ
);
138 if (host
->buswidth
== 1)
139 (&plat
->cfg
)->host_caps
&= ~(MMC_MODE_8BIT
| MMC_MODE_4BIT
);
141 host
->mmc
= &plat
->mmc
;
142 host
->mmc
->priv
= &priv
->host
;
143 upriv
->mmc
= host
->mmc
;
144 host
->mmc
->dev
= dev
;
145 host
->clksel
= ca_dwmci_clksel
;
146 host
->board_init
= ca_dwmci_board_init
;
147 host
->get_mmc_clk
= ca_dwmci_get_mmc_clock
;
149 return dwmci_probe(dev
);
152 static int ca_dwmmc_bind(struct udevice
*dev
)
154 struct ca_mmc_plat
*plat
= dev_get_plat(dev
);
156 return dwmci_bind(dev
, &plat
->mmc
, &plat
->cfg
);
159 static const struct udevice_id ca_dwmmc_ids
[] = {
160 { .compatible
= "cortina,ca-mmc" },
164 U_BOOT_DRIVER(ca_dwmmc_drv
) = {
165 .name
= "cortina_dwmmc",
167 .of_match
= ca_dwmmc_ids
,
168 .of_to_plat
= ca_dwmmc_of_to_plat
,
169 .bind
= ca_dwmmc_bind
,
170 .ops
= &ca_dwmci_dm_ops
,
171 .probe
= ca_dwmmc_probe
,
172 .priv_auto
= sizeof(struct ca_dwmmc_priv_data
),
173 .plat_auto
= sizeof(struct ca_mmc_plat
),