and the properties used by the sdhci-pxav2 and sdhci-pxav3 drivers.
Required properties:
-- compatible: Should be "mrvl,pxav2-mmc" or "mrvl,pxav3-mmc".
+- compatible: Should be "mrvl,pxav2-mmc", "mrvl,pxav3-mmc" or
+ "marvell,armada-380-sdhci".
+- reg:
+ * for "mrvl,pxav2-mmc" and "mrvl,pxav3-mmc", one register area for
+ the SDHCI registers.
+ * for "marvell,armada-380-sdhci", two register areas. The first one
+ for the SDHCI registers themselves, and the second one for the
+ AXI/Mbus bridge registers of the SDHCI unit.
Optional properties:
- mrvl,clk-delay-cycles: Specify a number of cycles to delay for tuning.
non-removable;
mrvl,clk-delay-cycles = <31>;
};
+
+sdhci@d8000 {
+ compatible = "marvell,armada-380-sdhci";
+ reg = <0xd8000 0x1000>, <0xdc000 0x100>;
+ interrupts = <0 25 0x4>;
+ clocks = <&gateclk 17>;
+ mrvl,clk-delay-cycles = <0x1F>;
+};
#include <linux/of_gpio.h>
#include <linux/pm.h>
#include <linux/pm_runtime.h>
+#include <linux/mbus.h>
#include "sdhci.h"
#include "sdhci-pltfm.h"
#define SDCE_MISC_INT (1<<2)
#define SDCE_MISC_INT_EN (1<<1)
+/*
+ * These registers are relative to the second register region, for the
+ * MBus bridge.
+ */
+#define SDHCI_WINDOW_CTRL(i) (0x80 + ((i) << 3))
+#define SDHCI_WINDOW_BASE(i) (0x84 + ((i) << 3))
+#define SDHCI_MAX_WIN_NUM 8
+
+static int mv_conf_mbus_windows(struct platform_device *pdev,
+ const struct mbus_dram_target_info *dram)
+{
+ int i;
+ void __iomem *regs;
+ struct resource *res;
+
+ if (!dram) {
+ dev_err(&pdev->dev, "no mbus dram info\n");
+ return -EINVAL;
+ }
+
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+ if (!res) {
+ dev_err(&pdev->dev, "cannot get mbus registers\n");
+ return -EINVAL;
+ }
+
+ regs = ioremap(res->start, resource_size(res));
+ if (!regs) {
+ dev_err(&pdev->dev, "cannot map mbus registers\n");
+ return -ENOMEM;
+ }
+
+ for (i = 0; i < SDHCI_MAX_WIN_NUM; i++) {
+ writel(0, regs + SDHCI_WINDOW_CTRL(i));
+ writel(0, regs + SDHCI_WINDOW_BASE(i));
+ }
+
+ for (i = 0; i < dram->num_cs; i++) {
+ const struct mbus_dram_window *cs = dram->cs + i;
+
+ /* Write size, attributes and target id to control register */
+ writel(((cs->size - 1) & 0xffff0000) |
+ (cs->mbus_attr << 8) |
+ (dram->mbus_dram_target_id << 4) | 1,
+ regs + SDHCI_WINDOW_CTRL(i));
+ /* Write base address to base register */
+ writel(cs->base, regs + SDHCI_WINDOW_BASE(i));
+ }
+
+ iounmap(regs);
+
+ return 0;
+}
+
static void pxav3_set_private_registers(struct sdhci_host *host, u8 mask)
{
struct platform_device *pdev = to_platform_device(mmc_dev(host->mmc));
{
.compatible = "mrvl,pxav3-mmc",
},
+ {
+ .compatible = "marvell,armada-380-sdhci",
+ },
{},
};
MODULE_DEVICE_TABLE(of, sdhci_pxav3_of_match);
struct sdhci_pltfm_host *pltfm_host;
struct sdhci_pxa_platdata *pdata = pdev->dev.platform_data;
struct device *dev = &pdev->dev;
+ struct device_node *np = pdev->dev.of_node;
struct sdhci_host *host = NULL;
struct sdhci_pxa *pxa = NULL;
const struct of_device_id *match;
kfree(pxa);
return PTR_ERR(host);
}
+
+ if (of_device_is_compatible(np, "marvell,armada-380-sdhci")) {
+ ret = mv_conf_mbus_windows(pdev, mv_mbus_dram_info());
+ if (ret < 0)
+ goto err_mbus_win;
+ }
+
+
pltfm_host = sdhci_priv(host);
pltfm_host->priv = pxa;
clk_disable_unprepare(clk);
clk_put(clk);
err_clk_get:
+err_mbus_win:
sdhci_pltfm_free(pdev);
kfree(pxa);
return ret;