2 * (C) Copyright 2013 Altera Corporation <www.altera.com>
4 * SPDX-License-Identifier: GPL-2.0+
8 #include <asm/arch/clock_manager.h>
9 #include <asm/arch/system_manager.h>
15 #include <linux/err.h>
18 DECLARE_GLOBAL_DATA_PTR
;
20 static const struct socfpga_clock_manager
*clock_manager_base
=
21 (void *)SOCFPGA_CLKMGR_ADDRESS
;
22 static const struct socfpga_system_manager
*system_manager_base
=
23 (void *)SOCFPGA_SYSMGR_ADDRESS
;
25 /* socfpga implmentation specific driver private data */
26 struct dwmci_socfpga_priv_data
{
27 struct dwmci_host host
;
32 static void socfpga_dwmci_clksel(struct dwmci_host
*host
)
34 struct dwmci_socfpga_priv_data
*priv
= host
->priv
;
35 u32 sdmmc_mask
= ((priv
->smplsel
& 0x7) << SYSMGR_SDMMC_SMPLSEL_SHIFT
) |
36 ((priv
->drvsel
& 0x7) << SYSMGR_SDMMC_DRVSEL_SHIFT
);
38 /* Disable SDMMC clock. */
39 clrbits_le32(&clock_manager_base
->per_pll
.en
,
40 CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK
);
42 debug("%s: drvsel %d smplsel %d\n", __func__
,
43 priv
->drvsel
, priv
->smplsel
);
44 writel(sdmmc_mask
, &system_manager_base
->sdmmcgrp_ctrl
);
46 debug("%s: SYSMGR_SDMMCGRP_CTRL_REG = 0x%x\n", __func__
,
47 readl(&system_manager_base
->sdmmcgrp_ctrl
));
49 /* Enable SDMMC clock */
50 setbits_le32(&clock_manager_base
->per_pll
.en
,
51 CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK
);
54 static int socfpga_dwmmc_ofdata_to_platdata(struct udevice
*dev
)
56 /* FIXME: probe from DT eventually too/ */
57 const unsigned long clk
= cm_get_mmc_controller_clk_hz();
59 struct dwmci_socfpga_priv_data
*priv
= dev_get_priv(dev
);
60 struct dwmci_host
*host
= &priv
->host
;
64 printf("DWMMC: MMC clock is zero!");
68 fifo_depth
= fdtdec_get_int(gd
->fdt_blob
, dev
->of_offset
,
71 printf("DWMMC: Can't get FIFO depth\n");
75 host
->name
= dev
->name
;
76 host
->ioaddr
= (void *)dev_get_addr(dev
);
77 host
->buswidth
= fdtdec_get_int(gd
->fdt_blob
, dev
->of_offset
,
79 host
->clksel
= socfpga_dwmci_clksel
;
82 * TODO(sjg@chromium.org): Remove the need for this hack.
83 * We only have one dwmmc block on gen5 SoCFPGA.
86 /* Fixed clock divide by 4 which due to the SDMMC wrapper */
88 host
->fifoth_val
= MSIZE(0x2) |
89 RX_WMARK(fifo_depth
/ 2 - 1) | TX_WMARK(fifo_depth
/ 2);
90 priv
->drvsel
= fdtdec_get_uint(gd
->fdt_blob
, dev
->of_offset
,
92 priv
->smplsel
= fdtdec_get_uint(gd
->fdt_blob
, dev
->of_offset
,
99 static int socfpga_dwmmc_probe(struct udevice
*dev
)
101 struct mmc_uclass_priv
*upriv
= dev_get_uclass_priv(dev
);
102 struct dwmci_socfpga_priv_data
*priv
= dev_get_priv(dev
);
103 struct dwmci_host
*host
= &priv
->host
;
106 ret
= add_dwmci(host
, host
->bus_hz
, 400000);
110 upriv
->mmc
= host
->mmc
;
111 host
->mmc
->dev
= dev
;
116 static const struct udevice_id socfpga_dwmmc_ids
[] = {
117 { .compatible
= "altr,socfpga-dw-mshc" },
121 U_BOOT_DRIVER(socfpga_dwmmc_drv
) = {
122 .name
= "socfpga_dwmmc",
124 .of_match
= socfpga_dwmmc_ids
,
125 .ofdata_to_platdata
= socfpga_dwmmc_ofdata_to_platdata
,
126 .probe
= socfpga_dwmmc_probe
,
127 .priv_auto_alloc_size
= sizeof(struct dwmci_socfpga_priv_data
),