diff options
| -rw-r--r-- | arch/arm/include/asm/arch-socfpga/dwmmc.h | 12 | ||||
| -rw-r--r-- | arch/arm/include/asm/arch-socfpga/system_manager.h | 65 | ||||
| -rw-r--r-- | doc/README.socfpga | 53 | ||||
| -rw-r--r-- | drivers/mmc/Makefile | 1 | ||||
| -rw-r--r-- | drivers/mmc/socfpga_dw_mmc.c | 68 | 
5 files changed, 199 insertions, 0 deletions
| diff --git a/arch/arm/include/asm/arch-socfpga/dwmmc.h b/arch/arm/include/asm/arch-socfpga/dwmmc.h new file mode 100644 index 000000000..945eb646c --- /dev/null +++ b/arch/arm/include/asm/arch-socfpga/dwmmc.h @@ -0,0 +1,12 @@ +/* + * (C) Copyright 2013 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#ifndef	_SOCFPGA_DWMMC_H_ +#define	_SOCFPGA_DWMMC_H_ + +extern int socfpga_dwmmc_init(u32 regbase, int bus_width, int index); + +#endif /* _SOCFPGA_SDMMC_H_ */ diff --git a/arch/arm/include/asm/arch-socfpga/system_manager.h b/arch/arm/include/asm/arch-socfpga/system_manager.h index d965d25ef..838d21053 100644 --- a/arch/arm/include/asm/arch-socfpga/system_manager.h +++ b/arch/arm/include/asm/arch-socfpga/system_manager.h @@ -19,4 +19,69 @@ extern unsigned long sys_mgr_init_table[CONFIG_HPS_PINMUX_NUM];  #define CONFIG_SYSMGR_PINMUXGRP_OFFSET	(0x400) +#define SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel)	\ +	((((drvsel) << 0) & 0x7) | (((smplsel) << 3) & 0x38)) + +struct socfpga_system_manager { +	u32	siliconid1; +	u32	siliconid2; +	u32	_pad_0x8_0xf[2]; +	u32	wddbg; +	u32	bootinfo; +	u32	hpsinfo; +	u32	parityinj; +	u32	fpgaintfgrp_gbl; +	u32	fpgaintfgrp_indiv; +	u32	fpgaintfgrp_module; +	u32	_pad_0x2c_0x2f; +	u32	scanmgrgrp_ctrl; +	u32	_pad_0x34_0x3f[3]; +	u32	frzctrl_vioctrl; +	u32	_pad_0x44_0x4f[3]; +	u32	frzctrl_hioctrl; +	u32	frzctrl_src; +	u32	frzctrl_hwctrl; +	u32	_pad_0x5c_0x5f; +	u32	emacgrp_ctrl; +	u32	emacgrp_l3master; +	u32	_pad_0x68_0x6f[2]; +	u32	dmagrp_ctrl; +	u32	dmagrp_persecurity; +	u32	_pad_0x78_0x7f[2]; +	u32	iswgrp_handoff[8]; +	u32	_pad_0xa0_0xbf[8]; +	u32	romcodegrp_ctrl; +	u32	romcodegrp_cpu1startaddr; +	u32	romcodegrp_initswstate; +	u32	romcodegrp_initswlastld; +	u32	romcodegrp_bootromswstate; +	u32	__pad_0xd4_0xdf[3]; +	u32	romcodegrp_warmramgrp_enable; +	u32	romcodegrp_warmramgrp_datastart; +	u32	romcodegrp_warmramgrp_length; +	u32	romcodegrp_warmramgrp_execution; +	u32	romcodegrp_warmramgrp_crc; +	u32	__pad_0xf4_0xff[3]; +	u32	romhwgrp_ctrl; +	u32	_pad_0x104_0x107; +	u32	sdmmcgrp_ctrl; +	u32	sdmmcgrp_l3master; +	u32	nandgrp_bootstrap; +	u32	nandgrp_l3master; +	u32	usbgrp_l3master; +	u32	_pad_0x11c_0x13f[9]; +	u32	eccgrp_l2; +	u32	eccgrp_ocram; +	u32	eccgrp_usb0; +	u32	eccgrp_usb1; +	u32	eccgrp_emac0; +	u32	eccgrp_emac1; +	u32	eccgrp_dma; +	u32	eccgrp_can0; +	u32	eccgrp_can1; +	u32	eccgrp_nand; +	u32	eccgrp_qspi; +	u32	eccgrp_sdmmc; +}; +  #endif /* _SYSTEM_MANAGER_H_ */ diff --git a/doc/README.socfpga b/doc/README.socfpga new file mode 100644 index 000000000..cfcbbfe37 --- /dev/null +++ b/doc/README.socfpga @@ -0,0 +1,53 @@ + +-------------------------------------------- +SOCFPGA Documentation for U-Boot and SPL +-------------------------------------------- + +This README is about U-Boot and SPL support for Altera's ARM Cortex-A9MPCore +based SOCFPGA. To know more about the hardware itself, please refer to +www.altera.com. + + +-------------------------------------------- +socfpga_dw_mmc +-------------------------------------------- +Here are macro and detailed configuration required to enable DesignWare SDMMC +controller support within SOCFPGA + +#define CONFIG_MMC +-> To enable the SD MMC framework support + +#define CONFIG_SDMMC_BASE		(SOCFPGA_SDMMC_ADDRESS) +-> The base address of CSR register for DesignWare SDMMC controller + +#define CONFIG_GENERIC_MMC +-> Enable the generic MMC driver + +#define CONFIG_SYS_MMC_MAX_BLK_COUNT	256 +-> Using smaller max blk cnt to avoid flooding the limited stack in OCRAM + +#define CONFIG_DWMMC +-> Enable the common DesignWare SDMMC controller framework + +#define CONFIG_SOCFPGA_DWMMC +-> Enable the SOCFPGA specific driver for DesignWare SDMMC controller + +#define CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH		1024 +-> The FIFO depth for SOCFPGA DesignWare SDMMC controller + +#define CONFIG_SOCFPGA_DWMMC_DRVSEL	3 +-> Phase-shifted clock of sdmmc_clk for controller to drive command and data to +the card to meet hold time requirements. SD clock is running at 50MHz and +drvsel is set to shift 135 degrees (3 * 45 degrees). With that, the hold time +is 135 / 360 * 20ns = 7.5ns. + +#define CONFIG_SOCFPGA_DWMMC_SMPSEL	0 +-> Phase-shifted clock of sdmmc_clk used to sample the command and data from +the card + +#define CONFIG_SOCFPGA_DWMMC_BUS_WIDTH	4 +-> Bus width of data line which either 1, 4 or 8 and based on board routing. + +#define CONFIG_SOCFPGA_DWMMC_BUS_HZ	50000000 +-> The clock rate to controller. Do note the controller have a wrapper which +divide the clock from PLL by 4. diff --git a/drivers/mmc/Makefile b/drivers/mmc/Makefile index 1ed26cab3..e793ed994 100644 --- a/drivers/mmc/Makefile +++ b/drivers/mmc/Makefile @@ -28,6 +28,7 @@ obj-$(CONFIG_TEGRA_MMC) += tegra_mmc.o  obj-$(CONFIG_DWMMC) += dw_mmc.o  obj-$(CONFIG_EXYNOS_DWMMC) += exynos_dw_mmc.o  obj-$(CONFIG_ZYNQ_SDHCI) += zynq_sdhci.o +obj-$(CONFIG_SOCFPGA_DWMMC) += socfpga_dw_mmc.o  ifdef CONFIG_SPL_BUILD  obj-$(CONFIG_SPL_MMC_BOOT) += fsl_esdhc_spl.o  else diff --git a/drivers/mmc/socfpga_dw_mmc.c b/drivers/mmc/socfpga_dw_mmc.c new file mode 100644 index 000000000..bc53a5da2 --- /dev/null +++ b/drivers/mmc/socfpga_dw_mmc.c @@ -0,0 +1,68 @@ +/* + * (C) Copyright 2013 Altera Corporation <www.altera.com> + * + * SPDX-License-Identifier:	GPL-2.0+ + */ + +#include <common.h> +#include <malloc.h> +#include <dwmmc.h> +#include <asm/arch/dwmmc.h> +#include <asm/arch/clock_manager.h> +#include <asm/arch/system_manager.h> + +static const struct socfpga_clock_manager *clock_manager_base = +		(void *)SOCFPGA_CLKMGR_ADDRESS; +static const struct socfpga_system_manager *system_manager_base = +		(void *)SOCFPGA_SYSMGR_ADDRESS; + +static char *SOCFPGA_NAME = "SOCFPGA DWMMC"; + +static void socfpga_dwmci_clksel(struct dwmci_host *host) +{ +	unsigned int drvsel; +	unsigned int smplsel; + +	/* Disable SDMMC clock. */ +	clrbits_le32(&clock_manager_base->per_pll_en, +		CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK); + +	/* Configures drv_sel and smpl_sel */ +	drvsel = CONFIG_SOCFPGA_DWMMC_DRVSEL; +	smplsel = CONFIG_SOCFPGA_DWMMC_SMPSEL; + +	debug("%s: drvsel %d smplsel %d\n", __func__, drvsel, smplsel); +	writel(SYSMGR_SDMMC_CTRL_SET(smplsel, drvsel), +		&system_manager_base->sdmmcgrp_ctrl); + +	debug("%s: SYSMGR_SDMMCGRP_CTRL_REG = 0x%x\n", __func__, +		readl(&system_manager_base->sdmmcgrp_ctrl)); + +	/* Enable SDMMC clock */ +	setbits_le32(&clock_manager_base->per_pll_en, +		CLKMGR_PERPLLGRP_EN_SDMMCCLK_MASK); +} + +int socfpga_dwmmc_init(u32 regbase, int bus_width, int index) +{ +	struct dwmci_host *host = NULL; +	host = calloc(sizeof(struct dwmci_host), 1); +	if (!host) { +		printf("dwmci_host calloc fail!\n"); +		return -1; +	} + +	host->name = SOCFPGA_NAME; +	host->ioaddr = (void *)regbase; +	host->buswidth = bus_width; +	host->clksel = socfpga_dwmci_clksel; +	host->dev_index = index; +	/* fixed clock divide by 4 which due to the SDMMC wrapper */ +	host->bus_hz = CONFIG_SOCFPGA_DWMMC_BUS_HZ; +	host->fifoth_val = MSIZE(0x2) | +		RX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2 - 1) | +		TX_WMARK(CONFIG_SOCFPGA_DWMMC_FIFO_DEPTH / 2); + +	return add_dwmci(host, host->bus_hz, 400000); +} + |