2 * Copyright (C) 2015 Atmel Corporation
3 * Wenyou.Yang <wenyou.yang@atmel.com>
5 * SPDX-License-Identifier: GPL-2.0+
13 #include <asm/arch/clk.h>
15 #define ATMEL_SDHC_MIN_FREQ 400000
18 int atmel_sdhci_init(void *regbase
, u32 id
)
20 struct sdhci_host
*host
;
21 u32 max_clk
, min_clk
= ATMEL_SDHC_MIN_FREQ
;
23 host
= (struct sdhci_host
*)calloc(1, sizeof(struct sdhci_host
));
25 printf("%s: sdhci_host calloc failed\n", __func__
);
29 host
->name
= "atmel_sdhci";
30 host
->ioaddr
= regbase
;
31 host
->quirks
= SDHCI_QUIRK_WAIT_SEND_CMD
;
32 max_clk
= at91_get_periph_generated_clk(id
);
34 printf("%s: Failed to get the proper clock\n", __func__
);
38 host
->max_clk
= max_clk
;
40 add_sdhci(host
, 0, min_clk
);
47 DECLARE_GLOBAL_DATA_PTR
;
49 struct atmel_sdhci_plat
{
50 struct mmc_config cfg
;
54 static int atmel_sdhci_probe(struct udevice
*dev
)
56 struct mmc_uclass_priv
*upriv
= dev_get_uclass_priv(dev
);
57 struct atmel_sdhci_plat
*plat
= dev_get_platdata(dev
);
58 struct sdhci_host
*host
= dev_get_priv(dev
);
61 u32 clk_base
, clk_mul
;
66 ret
= clk_get_by_index(dev
, 0, &clk
);
70 ret
= clk_enable(&clk
);
74 host
->name
= dev
->name
;
75 host
->ioaddr
= (void *)devfdt_get_addr(dev
);
77 host
->quirks
= SDHCI_QUIRK_WAIT_SEND_CMD
;
78 host
->bus_width
= fdtdec_get_int(gd
->fdt_blob
, dev_of_offset(dev
),
81 caps
= sdhci_readl(host
, SDHCI_CAPABILITIES
);
82 clk_base
= (caps
& SDHCI_CLOCK_V3_BASE_MASK
) >> SDHCI_CLOCK_BASE_SHIFT
;
83 caps_1
= sdhci_readl(host
, SDHCI_CAPABILITIES_1
);
84 clk_mul
= (caps_1
& SDHCI_CLOCK_MUL_MASK
) >> SDHCI_CLOCK_MUL_SHIFT
;
85 gck_rate
= clk_base
* 1000000 * (clk_mul
+ 1);
87 ret
= clk_get_by_index(dev
, 1, &clk
);
91 ret
= clk_set_rate(&clk
, gck_rate
);
95 max_clk
= clk_get_rate(&clk
);
99 host
->max_clk
= max_clk
;
101 ret
= sdhci_setup_cfg(&plat
->cfg
, host
, 0, ATMEL_SDHC_MIN_FREQ
);
105 host
->mmc
= &plat
->mmc
;
106 host
->mmc
->dev
= dev
;
107 host
->mmc
->priv
= host
;
108 upriv
->mmc
= host
->mmc
;
112 return sdhci_probe(dev
);
115 static int atmel_sdhci_bind(struct udevice
*dev
)
117 struct atmel_sdhci_plat
*plat
= dev_get_platdata(dev
);
119 return sdhci_bind(dev
, &plat
->mmc
, &plat
->cfg
);
122 static const struct udevice_id atmel_sdhci_ids
[] = {
123 { .compatible
= "atmel,sama5d2-sdhci" },
127 U_BOOT_DRIVER(atmel_sdhci_drv
) = {
128 .name
= "atmel_sdhci",
130 .of_match
= atmel_sdhci_ids
,
132 .bind
= atmel_sdhci_bind
,
133 .probe
= atmel_sdhci_probe
,
134 .priv_auto_alloc_size
= sizeof(struct sdhci_host
),
135 .platdata_auto_alloc_size
= sizeof(struct atmel_sdhci_plat
),