2018-05-06 17:58:06 -04:00
|
|
|
// SPDX-License-Identifier: GPL-2.0+
|
2016-02-18 19:52:48 +09:00
|
|
|
/*
|
2016-07-19 21:56:13 +09:00
|
|
|
* Copyright (C) 2016 Socionext Inc.
|
|
|
|
* Author: Masahiro Yamada <yamada.masahiro@socionext.com>
|
2016-02-18 19:52:48 +09:00
|
|
|
*/
|
|
|
|
|
|
|
|
#include <common.h>
|
|
|
|
#include <clk.h>
|
|
|
|
#include <fdtdec.h>
|
2020-02-03 07:36:16 -07:00
|
|
|
#include <malloc.h>
|
2016-02-18 19:52:48 +09:00
|
|
|
#include <mmc.h>
|
2017-05-17 17:18:03 -06:00
|
|
|
#include <dm.h>
|
2020-02-03 07:36:16 -07:00
|
|
|
#include <dm/device_compat.h>
|
2016-02-18 19:52:48 +09:00
|
|
|
#include <linux/compat.h>
|
2017-08-26 00:50:17 +09:00
|
|
|
#include <linux/dma-direction.h>
|
2016-02-18 19:52:48 +09:00
|
|
|
#include <linux/io.h>
|
2016-03-24 22:32:42 +09:00
|
|
|
#include <linux/sizes.h>
|
2017-09-15 21:10:54 +02:00
|
|
|
#include <power/regulator.h>
|
2016-02-18 19:52:48 +09:00
|
|
|
#include <asm/unaligned.h>
|
|
|
|
|
2018-04-13 23:51:33 +02:00
|
|
|
#include "tmio-common.h"
|
2016-08-25 14:52:36 +09:00
|
|
|
|
|
|
|
static const struct dm_mmc_ops uniphier_sd_ops = {
|
2018-04-13 23:51:33 +02:00
|
|
|
.send_cmd = tmio_sd_send_cmd,
|
|
|
|
.set_ios = tmio_sd_set_ios,
|
|
|
|
.get_cd = tmio_sd_get_cd,
|
2016-08-25 14:52:36 +09:00
|
|
|
};
|
|
|
|
|
2016-02-18 19:52:48 +09:00
|
|
|
static const struct udevice_id uniphier_sd_match[] = {
|
2018-09-10 12:58:35 +09:00
|
|
|
{ .compatible = "socionext,uniphier-sd-v2.91" },
|
|
|
|
{ .compatible = "socionext,uniphier-sd-v3.1" },
|
|
|
|
{ .compatible = "socionext,uniphier-sd-v3.1.1" },
|
2016-02-18 19:52:48 +09:00
|
|
|
{ /* sentinel */ }
|
|
|
|
};
|
|
|
|
|
2018-06-13 08:02:55 +02:00
|
|
|
static ulong uniphier_sd_clk_get_rate(struct tmio_sd_priv *priv)
|
|
|
|
{
|
|
|
|
#if CONFIG_IS_ENABLED(CLK)
|
|
|
|
return clk_get_rate(&priv->clk);
|
|
|
|
#elif CONFIG_SPL_BUILD
|
|
|
|
return 100000000;
|
|
|
|
#else
|
|
|
|
return 0;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-04-08 17:45:23 +02:00
|
|
|
static int uniphier_sd_probe(struct udevice *dev)
|
|
|
|
{
|
2018-04-20 18:14:24 +09:00
|
|
|
struct tmio_sd_priv *priv = dev_get_priv(dev);
|
2018-06-13 08:02:55 +02:00
|
|
|
|
|
|
|
priv->clk_get_rate = uniphier_sd_clk_get_rate;
|
2019-01-11 23:45:54 +01:00
|
|
|
priv->read_poll_flag = TMIO_SD_DMA_INFO1_END_RD2;
|
2018-06-13 08:02:55 +02:00
|
|
|
|
2018-04-20 18:14:25 +09:00
|
|
|
#ifndef CONFIG_SPL_BUILD
|
2018-04-20 18:14:24 +09:00
|
|
|
int ret;
|
|
|
|
|
2018-06-13 08:02:55 +02:00
|
|
|
ret = clk_get_by_index(dev, 0, &priv->clk);
|
2018-04-20 18:14:24 +09:00
|
|
|
if (ret < 0) {
|
|
|
|
dev_err(dev, "failed to get host clock\n");
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set to max rate */
|
2018-06-13 08:02:55 +02:00
|
|
|
ret = clk_set_rate(&priv->clk, ULONG_MAX);
|
|
|
|
if (ret < 0) {
|
2018-04-20 18:14:24 +09:00
|
|
|
dev_err(dev, "failed to set rate for host clock\n");
|
2018-06-13 08:02:55 +02:00
|
|
|
clk_free(&priv->clk);
|
|
|
|
return ret;
|
2018-04-20 18:14:24 +09:00
|
|
|
}
|
|
|
|
|
2018-06-13 08:02:55 +02:00
|
|
|
ret = clk_enable(&priv->clk);
|
2018-04-20 18:14:24 +09:00
|
|
|
if (ret) {
|
|
|
|
dev_err(dev, "failed to enable host clock\n");
|
|
|
|
return ret;
|
|
|
|
}
|
2018-04-20 18:14:25 +09:00
|
|
|
#endif
|
2018-04-20 18:14:24 +09:00
|
|
|
|
2018-04-13 23:51:33 +02:00
|
|
|
return tmio_sd_probe(dev, 0);
|
2018-04-08 17:45:23 +02:00
|
|
|
}
|
|
|
|
|
2016-02-18 19:52:48 +09:00
|
|
|
U_BOOT_DRIVER(uniphier_mmc) = {
|
|
|
|
.name = "uniphier-mmc",
|
|
|
|
.id = UCLASS_MMC,
|
|
|
|
.of_match = uniphier_sd_match,
|
2018-04-13 23:51:33 +02:00
|
|
|
.bind = tmio_sd_bind,
|
2018-04-08 17:45:23 +02:00
|
|
|
.probe = uniphier_sd_probe,
|
2020-12-03 16:55:17 -07:00
|
|
|
.priv_auto = sizeof(struct tmio_sd_priv),
|
2020-12-03 16:55:18 -07:00
|
|
|
.plat_auto = sizeof(struct tmio_sd_plat),
|
2016-08-25 14:52:35 +09:00
|
|
|
.ops = &uniphier_sd_ops,
|
2016-02-18 19:52:48 +09:00
|
|
|
};
|