ARM: socfpga: dts: Add ethernet bindings for SOCFPGA
Subsystems (9)
PATCH v3 1/6 ARM: socfpga: dts: Add ethernet bindings for SOCFPGA
From: Dinh Nguyen <[email protected]>
Add entry for 2nd GMAC controller. Add the correct clocks for the GMAC.
v2:
- Moved "disabled" status to dtsi file
--- arch/arm/boot/dts/socfpga.dtsi | 18 ++++++++++++++++-- arch/arm/boot/dts/socfpga_cyclone5.dts | 13 +++++++++++++ arch/arm/boot/dts/socfpga_vt.dts | 5 +++++ 3 files changed, 34 insertions(+), 2 deletions(-)
arch/arm/boot/dts/socfpga.dtsi +16 -2
@@ -23,6 +23,7 @@ aliases { ethernet0 = &gmac0; + ethernet1 = &gmac1; serial0 = &uart0; serial1 = &uart1; timer0 = &timer0;
@@ -238,13 +239,26 @@ }; }; - gmac0: stmmac at ff700000 { + gmac0: ethernet at ff700000 { compatible = "altr,socfpga-stmmac", "snps,dwmac-3.70a", "snps,dwmac"; reg = <0xff700000 0x2000>; interrupts = <0 115 4>; interrupt-names = "macirq"; mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */ - phy-mode = "gmii"; + clocks = <&emac0_clk>; + clock-names = "stmmaceth"; + status = "disabled"; + }; + + gmac1: ethernet at ff702000 { + compatible = "altr,socfpga-stmmac", "snps,dwmac-3.70a", "snps,dwmac"; + reg = <0xff702000 0x2000>; + interrupts = <0 120 4>; + interrupt-names = "macirq"; + mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */ + clocks = <&emac1_clk>; + clock-names = "stmmaceth"; + status = "disabled"; }; L2: l2-cache at fffef000 {
arch/arm/boot/dts/socfpga_cyclone5.dts +13 -0
@@ -32,6 +32,13 @@ reg = <0x0 0x40000000>; /* 1GB */ }; + aliases { + /* this allow the ethaddr uboot environmnet variable contents + * to be added to the gmac1 device tree blob. + */ + ethernet0 = &gmac1; + }; + soc { clkmgr at ffd04000 { clocks {
@@ -41,6 +48,12 @@ }; }; + ethernet at ff702000 { + phy-mode = "rgmii"; + phy-addr = <0xffffffff>; /* probe for phy addr */ + status = "okay"; + }; + timer0 at ffc08000 { clock-frequency = <100000000>; };
arch/arm/boot/dts/socfpga_vt.dts +5 -0
@@ -41,6 +41,11 @@ }; }; + ethernet at ff700000 { + phy-mode = "gmii"; + status = "okay"; + }; + timer0 at ffc08000 { clock-frequency = <7000000>; };
Signature · 1 line
1.7.9.5
PATCH v3 2/6 ARM: socfpga: dts: Add gate-clock bindings
From: Dinh Nguyen <[email protected]>
Add bindings for "socfpga-gate-clk" clocks. These clocks directly feed the peripherals.
--- .../devicetree/bindings/clock/altr_socfpga.txt | 7 + arch/arm/boot/dts/socfpga.dtsi | 199 ++++++++++++++++++++ 2 files changed, 206 insertions(+)
Documentation/devicetree/bindings/clock/altr_socfpga.txt +7 -0
@@ -9,6 +9,9 @@ Required properties: "altr,socfpga-pll-clock" - for a PLL clock "altr,socfpga-perip-clock" - The peripheral clock divided from the PLL clock. + "altr,socfpga-gate-clk" - Clocks that directly feed peripherals and + can get gated. + - reg : shall be the control register offset from CLOCK_MANAGER's base for the clock. - clocks : shall be the input parent clock phandle for the clock. This is either an oscillator or a pll output.
@@ -16,3 +19,7 @@ Required properties: Optional properties: - fixed-divider : If clocks have a fixed divider value, use this property. +- clk-gate : For "socfpga-gate-clk", clk-gate contains the gating register + and the bit index. +- div-reg : For "socfpga-gate-clk", div-reg contains the divider register, bit shift, + and width.
arch/arm/boot/dts/socfpga.dtsi +199 -0
211 lines not on this page · raw message
Signature · 1 line
1.7.9.5
PATCH v3 3/6 ARM: socfpga: Add support to gate peripheral clocks
In reply to dinguyen at altera.comFrom: Dinh Nguyen <[email protected]>
Add support to gate the clocks that directly feed peripherals. For clocks with multiple parents, add the ability to determine the correct parent, and also set parents. Also add support to calculate and set the clocks' rate.
v3:
- Addressed comments from Pavel
v2:
- Fix space/indent errors
- Add streq for strcmp == 0
--- drivers/clk/socfpga/clk.c | 194 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 185 insertions(+), 9 deletions(-)
drivers/clk/socfpga/clk.c +185 -9
@@ -24,15 +24,17 @@#include <linux/of.h> /* Clock Manager offsets */ -#define CLKMGR_CTRL 0x0 -#define CLKMGR_BYPASS 0x4 +#define CLKMGR_CTRL 0x0 +#define CLKMGR_BYPASS 0x4 +#define CLKMGR_L4SRC 0x70 +#define CLKMGR_PERPLL_SRC 0xAC/* Clock bypass bits */ -#define MAINPLL_BYPASS (1<<0) -#define SDRAMPLL_BYPASS (1<<1) -#define SDRAMPLL_SRC_BYPASS (1<<2) -#define PERPLL_BYPASS (1<<3) -#define PERPLL_SRC_BYPASS (1<<4) +#define MAINPLL_BYPASS (1<<0) +#define SDRAMPLL_BYPASS (1<<1) +#define SDRAMPLL_SRC_BYPASS (1<<2) +#define PERPLL_BYPASS (1<<3) +#define PERPLL_SRC_BYPASS (1<<4)#define SOCFPGA_PLL_BG_PWRDWN 0#define SOCFPGA_PLL_EXT_ENA 1
@@ -41,6 +43,17 @@#define SOCFPGA_PLL_DIVF_SHIFT 3#define SOCFPGA_PLL_DIVQ_MASK 0x003F0000#define SOCFPGA_PLL_DIVQ_SHIFT 16 +#define SOCFGPA_MAX_PARENTS 3 + +#define SOCFPGA_L4_MP_CLK "l4_mp_clk" +#define SOCFPGA_L4_SP_CLK "l4_sp_clk" +#define SOCFPGA_NAND_CLK "nand_clk" +#define SOCFPGA_NAND_X_CLK "nand_x_clk" +#define SOCFPGA_MMC_CLK "mmc_clk" +#define SOCFPGA_DB_CLK "gpio_db_clk" + +#define div_mask (width) ((1 << (width)) - 1) +#define streq (a, b) (strcmp((a), (b)) == 0)extern void __iomem *clk_mgr_base_addr;
@@ -49,6 +62,9 @@ struct socfpga_clk {char *parent_name;char *clk_name;u32 fixed_div; +void __iomem *div_reg; +u32 width;/* only valid if div_reg != 0 */ +u32 shift;/* only valid if div_reg != 0 */ };#define to_socfpga_clk (p) container_of(p, struct socfpga_clk, hw.hw)
@@ -132,8 +148,9 @@ static __init struct clk *socfpga_clk_init(struct device_node *node, socfpga_clk->hw.hw.init = &init; -if (strcmp (clk_name,"main_pll" ) ||strcmp (clk_name,"periph_pll" ) || -strcmp (clk_name,"sdram_pll" )) { +if (streq (clk_name,"main_pll" ) || +streq (clk_name,"periph_pll" ) || +streq (clk_name,"sdram_pll" )) { socfpga_clk->hw.bit_idx =SOCFPGA_PLL_EXT_ENA ; clk_pll_ops.enable = clk_gate_ops.enable; clk_pll_ops.disable = clk_gate_ops.disable;
@@ -148,6 +165,159 @@ static __init struct clk *socfpga_clk_init(struct device_node *node,return clk; } +static u8 socfpga_clk_get_parent (struct clk_hw *hwclk) +{ +u32 l4_src; +u32 perpll_src; + +if (streq (hwclk->init->name,SOCFPGA_L4_MP_CLK )) { + l4_src =readl (clk_mgr_base_addr +CLKMGR_L4SRC ); +return l4_src &=0x1 ; + } +if (streq (hwclk->init->name,SOCFPGA_L4_SP_CLK )) { + l4_src =readl (clk_mgr_base_addr +CLKMGR_L4SRC ); +return !!(l4_src &2 ); + } + + perpll_src =readl (clk_mgr_base_addr +CLKMGR_PERPLL_SRC ); +if (streq (hwclk->init->name,SOCFPGA_MMC_CLK )) +return perpll_src &=0x3 ; +if (streq (hwclk->init->name,SOCFPGA_NAND_CLK ) || +streq (hwclk->init->name,SOCFPGA_NAND_X_CLK )) +return (perpll_src >>2 ) &3 ; + +/* QSPI clock */ +return (perpll_src >>4 ) &3 ; + +} + +static int socfpga_clk_set_parent (struct clk_hw *hwclk,u8 parent) +{ +u32 src_reg; + +if (streq (hwclk->init->name,SOCFPGA_L4_MP_CLK )) { + src_reg =readl (clk_mgr_base_addr +CLKMGR_L4SRC ); + src_reg &= ~0x1 ; + src_reg |= parent; +writel (src_reg, clk_mgr_base_addr +CLKMGR_L4SRC ); + }else if (streq (hwclk->init->name,SOCFPGA_L4_SP_CLK )) { + src_reg =readl (clk_mgr_base_addr +CLKMGR_L4SRC ); + src_reg &= ~0x2 ; + src_reg |= (parent <<1 ); +writel (src_reg, clk_mgr_base_addr +CLKMGR_L4SRC ); + }else { + src_reg =readl (clk_mgr_base_addr +CLKMGR_PERPLL_SRC ); +if (streq (hwclk->init->name,SOCFPGA_MMC_CLK )) { + src_reg &= ~0x3 ; + src_reg |= parent; + }else if (streq (hwclk->init->name,SOCFPGA_NAND_CLK ) || +streq (hwclk->init->name,SOCFPGA_NAND_X_CLK )) { + src_reg &= ~0xC ; + src_reg |= (parent <<2 ); + }else {/* QSPI clock */ + src_reg &= ~0x30 ; + src_reg |= (parent <<4 ); + } +writel (src_reg, clk_mgr_base_addr +CLKMGR_PERPLL_SRC ); + } + +return 0 ; +} + +static unsigned long socfpga_clk_recalc_rate (struct clk_hw *hwclk, +unsigned long parent_rate) +{ +struct socfpga_clk *socfpgaclk =to_socfpga_clk (hwclk); +u32 div =1 , val; + +if (socfpgaclk->fixed_div) + div = socfpgaclk->fixed_div; +else if (socfpgaclk->div_reg) { + val =readl (socfpgaclk->div_reg) >> socfpgaclk->shift; + val &=div_mask (socfpgaclk->width); +if (streq (hwclk->init->name,SOCFPGA_DB_CLK )) + div = val +1 ; +else + div = (1 << val); + } + +return parent_rate / div; +} + +static struct clk_ops gateclk_ops = { + .recalc_rate = socfpga_clk_recalc_rate, + .get_parent = socfpga_clk_get_parent, + .set_parent = socfpga_clk_set_parent, +}; + +static void __init socfpga_gate_clk_init (struct device_node *node, +const struct clk_ops *ops) +{ +u32 clk_gate[2 ]; +u32 div_reg[3 ]; +u32 fixed_div; +struct clk *clk; +struct socfpga_clk *socfpga_clk; +const char *clk_name = node->name; +const char *parent_name[SOCFGPA_MAX_PARENTS ]; +struct clk_init_data init; +int rc; +int i =0 ; + + socfpga_clk =kzalloc (sizeof (*socfpga_clk),GFP_KERNEL ); +if (WARN_ON (!socfpga_clk)) +return ; + + rc =of_property_read_u32_array (node,"clk-gate" , clk_gate,2 ); +if (rc) + clk_gate[0 ] =0 ; + +if (clk_gate[0 ]) { + socfpga_clk->hw.reg = clk_mgr_base_addr + clk_gate[0 ]; + socfpga_clk->hw.bit_idx = clk_gate[1 ]; + + gateclk_ops.enable = clk_gate_ops.enable; + gateclk_ops.disable = clk_gate_ops.disable; + } + + rc =of_property_read_u32 (node,"fixed-divider" , &fixed_div); +if (rc) + socfpga_clk->fixed_div =0 ; +else + socfpga_clk->fixed_div = fixed_div; + + rc =of_property_read_u32_array (node,"div-reg" , div_reg,3 ); +if (!rc) { + socfpga_clk->div_reg = clk_mgr_base_addr + div_reg[0 ]; + socfpga_clk->shift = div_reg[1 ]; + socfpga_clk->width = div_reg[2 ]; + }else { + socfpga_clk->div_reg =0 ; + } + +of_property_read_string (node,"clock-output-names" , &clk_name); + + init.name = clk_name; + init.ops = ops; + init.flags =0 ; +while (i <SOCFGPA_MAX_PARENTS && (parent_name[i] = +of_clk_get_parent_name (node, i)) !=NULL ) + i++; + + init.parent_names = parent_name; + init.num_parents = i; + socfpga_clk->hw.hw.init = &init; + + clk =clk_register (NULL , &socfpga_clk->hw.hw); +if (WARN_ON (IS_ERR (clk))) { +kfree (socfpga_clk); +return ; + } + rc =of_clk_add_provider (node, of_clk_src_simple_get, clk); +if (WARN_ON (rc)) +return ; +} +static void __init socfpga_pll_init (struct device_node *node) {socfpga_clk_init (node, &clk_pll_ops);
@@ -160,6 +330,12 @@ static void __init socfpga_periph_init(struct device_node *node) }CLK_OF_DECLARE (socfpga_periph,"altr,socfpga-perip-clk" , socfpga_periph_init); +static void __init socfpga_gate_init (struct device_node *node) +{ +socfpga_gate_clk_init (node, &gateclk_ops); +} +CLK_OF_DECLARE (socfpga_gate,"altr,socfpga-gate-clk" , socfpga_gate_init); +void __init socfpga_init_clocks (void ) {struct clk *clk;
Signature · 1 line
1.7.9.5
PATCH v3 4/6 ARM: socfpga: Add syscon to be part of socfpga
In reply to dinguyen at altera.comFrom: Dinh Nguyen <[email protected]>
SOCFPGA has a system manager register block can be accessed by using the syscon driver.
--- arch/arm/mach-socfpga/Kconfig | 1 + 1 file changed, 1 insertion(+)
arch/arm/mach-socfpga/Kconfig +1 -0
@@ -13,5 +13,6 @@ config ARCH_SOCFPGA select GPIO_PL061 if GPIOLIB select HAVE_ARM_SCU select HAVE_SMP + select MFD_SYSCON select SPARSE_IRQ select USE_OF
Signature · 1 line
1.7.9.5
PATCH v3 5/6 ARM: socfpga: dts: Add support for SD/MMC
In reply to dinguyen at altera.comFrom: Dinh Nguyen <[email protected]>
Add bindings for SD/MMC for SOCFPGA.
Add "syscon" to the "altr,sys-mgr" binding.
v2:
- Add "syscon" to "altr,sys-mgr"
- Remove pwr-en field
--- .../devicetree/bindings/mmc/socfpga-dw-mshc.txt | 60 ++++++++++++++++++++ arch/arm/boot/dts/socfpga.dtsi | 13 ++++- arch/arm/boot/dts/socfpga_cyclone5.dts | 13 +++++ arch/arm/boot/dts/socfpga_vt.dts | 12 ++++ 4 files changed, 97 insertions(+), 1 deletion(-) create mode 100644 Documentation/devicetree/bindings/mmc/socfpga-dw-mshc.txt
Documentation/devicetree/bindings/mmc/socfpga-dw-mshc.txt new file +60 -0
@@ -0,0 +1,60 @@ +* Altera SOCFPGA specific extensions to the Synopsis Designware Mobile + Storage Host Controller + +Required Properties: + +* compatible: should be + - "altr,socfpga-dw-mshc": for controllers with Altera SOCFPGA + specific extentions. + +* altr,dw-mshc-ciu-div: Specifies the divider value for the card interface + unit (ciu) clock. The value should be (n-1). For Altera's SOCFPGA, the divider + value is fixed at 3, which mean parent_clock/4. + +* altr,dw-mshc-sdr-timing: Specifies the value of CIU clock phase shift value + in transmit mode and CIU clock phase shift value in receive mode for single + data rate mode operation. Refer notes below for the order of the cells and the + valid values. + + Notes for the sdr-timing values: + + The order of the cells should be + - First Cell: CIU clock phase shift value for RX mode, smplsel bits in + the system manager SDMMC control group. + - Second Cell: CIU clock phase shift value for TX mode, drvsel bits in + the system manager SDMMC control group. + + Valid values for SDR CIU clock timing for SOCFPGA: + - valid value for tx phase shift and rx phase shift is 0 to 7. + +Required properties for a slot: + +* bus-width: Data width for card slot. 4-bit or 8-bit data. + +Example: + + The MSHC controller node can be split into two portions, SoC specific and + board specific portions as listed below. + + dwmmc0 at ff704000 { + compatible = "altr,socfpga-dw-mshc"; + reg = <0xff704000 0x1000>; + interrupts = <0 139 4>; + #address-cells = <1>; + #size-cells = <0>; + }; + + dwmmc0 at ff704000 { + num-slots = <1>; + supports-highspeed; + broken-cd; + fifo-depth = <0x400>; + altr,dw-mshc-ciu-div = <3>; + altr,dw-mshc-sdr-timing = <0 3>; + + slot at 0 { + reg = <0>; + bus-width = <4>; + }; + }; +
arch/arm/boot/dts/socfpga.dtsi +12 -1
@@ -468,6 +468,17 @@ cache-level = <2>; }; + mmc: dwmmc0 at ff704000 { + compatible = "altr,socfpga-dw-mshc"; + reg = <0xff704000 0x1000>; + interrupts = <0 139 4>; + fifo-depth = <0x400>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&l4_mp_clk>, <&sdmmc_clk>; + clock-names = "biu", "ciu"; + }; + /* Local timer */ timer at fffec600 { compatible = "arm,cortex-a9-twd-timer";
@@ -521,7 +532,7 @@ }; sysmgr at ffd08000 { - compatible = "altr,sys-mgr"; + compatible = "altr,sys-mgr", "syscon"; reg = <0xffd08000 0x4000>; }; };
arch/arm/boot/dts/socfpga_cyclone5.dts +13 -0
@@ -54,6 +54,19 @@ status = "okay"; }; + dwmmc0 at ff704000 { + num-slots = <1>; + supports-highspeed; + broken-cd; + altr,dw-mshc-ciu-div = <3>; + altr,dw-mshc-sdr-timing = <0 3>; + + slot at 0 { + reg = <0>; + bus-width = <4>; + }; + }; + timer0 at ffc08000 { clock-frequency = <100000000>; };
arch/arm/boot/dts/socfpga_vt.dts +12 -0
@@ -46,6 +46,18 @@ status = "okay"; }; + dwmmc0 at ff704000 { + num-slots = <1>; + supports-highspeed; + broken-cd; + altr,dw-mshc-ciu-div = <3>; + + slot at 0 { + reg = <0>; + bus-width = <4>; + }; + }; + timer0 at ffc08000 { clock-frequency = <7000000>; };
Signature · 1 line
1.7.9.5
PATCH v3 6/6 mmc: dw_mmc: Add support DW SD/MMC driver on SOCFPGA
In reply to dinguyen at altera.comFrom: Dinh Nguyen <[email protected]>
Add platform specific functionality for the DW SD/MMC driver for SoCFPGA. Move SDMMC_CMD_USE_HOLD_REG to dw_mmc.h so other platforms can use this define.
v3:
- Addressed comments from Seugwon, Jaehoon, and Pavel
- Use clk_disable_unprepare/clk_prepare_enable
v2:
- Use syscon and regmap
- Avoid divide by zero
- Remove the need to set PWR_EN
--- drivers/mmc/host/Kconfig | 8 +++ drivers/mmc/host/Makefile | 1 + drivers/mmc/host/dw_mmc-exynos.c | 2 - drivers/mmc/host/dw_mmc-socfpga.c | 139 +++++++++++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.h | 1 + 5 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 drivers/mmc/host/dw_mmc-socfpga.c
drivers/mmc/host/Kconfig +8 -0
@@ -556,6 +556,14 @@ config MMC_DW_EXYNOS Synopsys DesignWare Memory Card Interface driver. Select this option for platforms based on Exynos4 and Exynos5 SoC's. +config MMC_DW_SOCFPGA + tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" + depends on MMC_DW + select MMC_DW_PLTFM + help + This selects support for Altera SoCFPGA specific extensions to the + Synopsys DesignWare Memory Card Interface driver. + config MMC_DW_PCI tristate "Synopsys Designware MCI support on PCI bus" depends on MMC_DW && PCI
drivers/mmc/host/Makefile +1 -0
@@ -42,6 +42,7 @@ obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_MMC_DW) += dw_mmc.o obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o +obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.o
drivers/mmc/host/dw_mmc-exynos.c +0 -2
@@ -31,8 +31,6 @@ SDMMC_CLKSEL_CCLK_DRIVE(y) | \ SDMMC_CLKSEL_CCLK_DIVIDER(z)) -#define SDMMC_CMD_USE_HOLD_REG BIT(29) -#define EXYNOS4210_FIXED_CIU_CLK_DIV 2#define EXYNOS4412_FIXED_CIU_CLK_DIV 4
drivers/mmc/host/dw_mmc-socfpga.c new file +139 -0
139 lines not on this page · raw message
drivers/mmc/host/dw_mmc.h +1 -0
@@ -111,6 +111,7 @@#define SDMMC_INT_ERROR 0xbfc2/* Command register defines */ #define SDMMC_CMD_START BIT(31) +#define SDMMC_CMD_USE_HOLD_REG BIT(29)#define SDMMC_CMD_CCS_EXP BIT(23)#define SDMMC_CMD_CEATA_RD BIT(22)#define SDMMC_CMD_UPD_CLK BIT(21)
Signature · 1 line
1.7.9.5
Jaehoon Chung
maintainerPATCH v3 6/6 mmc: dw_mmc: Add support DW SD/MMC driver on SOCFPGA
Quoted 100 lines · On 05/24/2013 06:36 AM, [email protected] wrote:
From: Dinh Nguyen <[email protected]>
Add platform specific functionality for the DW SD/MMC driver for SoCFPGA. Move
SDMMC_CMD_USE_HOLD_REGtodw_mmc.hso other platforms can use this define.Signed-off-by Dinh Nguyen <[email protected]>CC Seungwon Jeon <[email protected]>CC Jaehoon Chung <[email protected]>CC Arnd Bergmann <[email protected]>CC Olof Johansson <[email protected]>CC Pavel Machek <[email protected]>v3:
- Addressed comments from Seugwon, Jaehoon, and Pavel
- Use clk_disable_unprepare/clk_prepare_enablev2:
- Use syscon and regmap
- Avoid divide by zero
- Remove the need to setPWR_EN--- drivers/mmc/host/Kconfig | 8 +++ drivers/mmc/host/Makefile | 1 + drivers/mmc/host/dw_mmc-exynos.c | 2 - drivers/mmc/host/dw_mmc-socfpga.c | 139 +++++++++++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.h | 1 + 5 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 drivers/mmc/host/dw_mmc-socfpga.cdrivers/mmc/host/Kconfig +8
-0@@ -556,6 +556,14 @@ config MMC_DW_EXYNOS Synopsys DesignWare Memory Card Interface driver. Select this option for platforms based on Exynos4 and Exynos5 SoC's. +config MMC_DW_SOCFPGA + tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" + depends on MMC_DW + select MMC_DW_PLTFM + help + This selects support for Altera SoCFPGA specific extensions to the + Synopsys DesignWare Memory Card Interface driver. + config MMC_DW_PCI tristate "Synopsys Designware MCI support on PCI bus" depends on MMC_DW && PCIdrivers/mmc/host/Makefile +1
-0@@ -42,6 +42,7 @@ obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_MMC_DW) += dw_mmc.o obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o +obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.odrivers/mmc/host/dw_mmc-exynos.c +0
-2@@ -31,8 +31,6 @@ SDMMC_CLKSEL_CCLK_DRIVE(y) | \ SDMMC_CLKSEL_CCLK_DIVIDER(z)) -#define SDMMC_CMD_USE_HOLD_REG BIT(29) -#define EXYNOS4210_FIXED_CIU_CLK_DIV 2#define EXYNOS4412_FIXED_CIU_CLK_DIV 4drivers/mmc/host/dw_mmc-socfpga.c new file +19
-0@@ -0,0 +1,139 @@ +/* +* Altera SoCFPGA Specific Extensions for Synopsys DW Multimedia Card Interface driver +* +* Copyright (C) 2012, Samsung Electronics Co., Ltd. +* Copyright (C) 2013 Altera Corporation +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Taken from dw_mmc-exynos.c +*/ +#include <linux/clk.h> +#include <linux/mfd/syscon.h> +#include <linux/mmc/host.h> +#include <linux/mmc/dw_mmc.h> +#include <linux/module.h> +#include <linux/of.h>
drivers/mmc/host/dw_mmc-socfpga.c line 29
Quoted 10 lines
drivers/mmc/host/dw_mmc-socfpga.c new file +10
-0+#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include "dw_mmc.h" +#include "dw_mmc-pltfm.h" + +#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108 +#define DRV_CLK_PHASE_SHIFT_SEL_MASK 0x7 +#define SYSMGR_SDMMC_CTRL_SET (smplsel, drvsel) \ + ((((smplsel) & 0x38) << 3) | (((drvsel) & 0x7) << 0))
Is it right? 0x38 is already shifted..
(((smplsel & 0x7) << 3) | ((drvsel & 0x7) << 0))
isn't?
Best Regards,
Jaehoon Chung
Quoted 123 lines
drivers/mmc/host/dw_mmc-socfpga.c new file +110
-0+ +/* SOCFPGA implementation specific driver private data */ +struct dw_mci_socfpga_priv_data { +u8 ciu_div;/* card interface unit divisor */ +u32 hs_timing;/* bitmask for CIU clock phase shift */ +struct regmap *sysreg;/* regmap for system manager register */ +}; + +static int dw_mci_socfpga_priv_init (struct dw_mci *host) +{ +struct dw_mci_socfpga_priv_data *priv; + + priv =devm_kzalloc (host->dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) { +dev_err (host->dev,"mem alloc failed for private data\n" ); +return -ENOMEM ; + } + + host->priv = priv; + + priv->sysreg =syscon_regmap_lookup_by_compatible ("altr,sys-mgr" ); +if (IS_ERR (priv->sysreg)) { +dev_err (host->dev,"regmap for altr,sys-mgr lookup failed.\n" ); +return PTR_ERR (priv->sysreg); + } + +return 0 ; +} + +static int dw_mci_socfpga_setup_clock (struct dw_mci *host) +{ +struct dw_mci_socfpga_priv_data *priv = host->priv; + +clk_disable_unprepare (host->ciu_clk); +regmap_write (priv->sysreg,SYSMGR_SDMMCGRP_CTRL_OFFSET , priv->hs_timing); +clk_prepare_enable (host->ciu_clk); + + host->bus_hz /= (priv->ciu_div +1 ); +return 0 ; +} + +static void dw_mci_socfpga_prepare_command (struct dw_mci *host,u32 *cmdr) +{ +struct dw_mci_socfpga_priv_data *priv = host->priv; + +if (priv->hs_timing &DRV_CLK_PHASE_SHIFT_SEL_MASK ) + *cmdr |=SDMMC_CMD_USE_HOLD_REG ; +} + +static int dw_mci_socfpga_parse_dt (struct dw_mci *host) +{ +struct dw_mci_socfpga_priv_data *priv = host->priv; +struct device_node *np = host->dev->of_node; +u32 timing[2 ]; +u32 div =0 ; +int ret; + + ret =of_property_read_u32 (np,"altr,dw-mshc-ciu-div" , &div); +if (ret) +dev_info (host->dev,"No dw-mshc-ciu-div specified, assuming 1" ); + priv->ciu_div = div; + + ret =of_property_read_u32_array (np, +"altr,dw-mshc-sdr-timing" , timing,2 ); +if (ret) +return ret; + + priv->hs_timing =SYSMGR_SDMMC_CTRL_SET (timing[0 ], timing[1 ]); +return 0 ; +} + +static const struct dw_mci_drv_data socfpga_drv_data = { + .init = dw_mci_socfpga_priv_init, + .setup_clock = dw_mci_socfpga_setup_clock, + .prepare_command = dw_mci_socfpga_prepare_command, + .parse_dt = dw_mci_socfpga_parse_dt, +}; + +static const struct of_device_id dw_mci_socfpga_match[] = { + { .compatible ="altr,socfpga-dw-mshc" , + .data = &socfpga_drv_data, }, + {}, +}; +MODULE_DEVICE_TABLE (of, dw_mci_socfpga_match); + +int dw_mci_socfpga_probe (struct platform_device *pdev) +{ +const struct dw_mci_drv_data *drv_data; +const struct of_device_id *match; + + match =of_match_node (dw_mci_socfpga_match, pdev->dev.of_node); + drv_data = match->data; +return dw_mci_pltfm_register (pdev, drv_data); +} + +static struct platform_driver dw_mci_socfpga_pltfm_driver = { + .probe = dw_mci_socfpga_probe, + .remove =__exit_p (dw_mci_pltfm_remove), + .driver = { + .name ="dwmmc_socfpga" , + .of_match_table =of_match_ptr (dw_mci_socfpga_match), + .pm = &dw_mci_pltfm_pmops, + }, +}; + +module_platform_driver (dw_mci_socfpga_pltfm_driver); + +MODULE_DESCRIPTION ("Altera SOCFPGA Specific DW-MSHC Driver Extension" ); +MODULE_LICENSE ("GPL v2" ); +MODULE_ALIAS ("platform:dwmmc-socfpga" );drivers/mmc/host/dw_mmc.h +1
-0@@ -111,6 +111,7 @@#define SDMMC_INT_ERROR 0xbfc2/* Command register defines */ #define SDMMC_CMD_START BIT(31) +#define SDMMC_CMD_USE_HOLD_REG BIT(29)#define SDMMC_CMD_CCS_EXP BIT(23)#define SDMMC_CMD_CEATA_RD BIT(22)#define SDMMC_CMD_UPD_CLK BIT(21)
PATCH v3 6/6 mmc: dw_mmc: Add support DW SD/MMC driver on SOCFPGA
Hi Jaehoon,
Quoted 106 lines · Jaehoon Chung
Quoted 105 lines · dinguyen at altera.com
From: Dinh Nguyen <[email protected]>
Add platform specific functionality for the DW SD/MMC driver for SoCFPGA. Move
SDMMC_CMD_USE_HOLD_REGtodw_mmc.hso other platforms can use this define.Signed-off-by Dinh Nguyen <[email protected]>CC Seungwon Jeon <[email protected]>CC Jaehoon Chung <[email protected]>CC Arnd Bergmann <[email protected]>CC Olof Johansson <[email protected]>CC Pavel Machek <[email protected]>CC linux-mmc at vger.kernel.orgv3:
- Addressed comments from Seugwon, Jaehoon, and Pavel
- Use clk_disable_unprepare/clk_prepare_enablev2:
- Use syscon and regmap
- Avoid divide by zero
- Remove the need to setPWR_EN--- drivers/mmc/host/Kconfig | 8 +++ drivers/mmc/host/Makefile | 1 + drivers/mmc/host/dw_mmc-exynos.c | 2 - drivers/mmc/host/dw_mmc-socfpga.c | 139 +++++++++++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.h | 1 + 5 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 drivers/mmc/host/dw_mmc-socfpga.cdrivers/mmc/host/Kconfig +8
-0@@ -556,6 +556,14 @@ config MMC_DW_EXYNOS Synopsys DesignWare Memory Card Interface driver. Select this option for platforms based on Exynos4 and Exynos5 SoC's. +config MMC_DW_SOCFPGA + tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" + depends on MMC_DW + select MMC_DW_PLTFM + help + This selects support for Altera SoCFPGA specific extensions to the + Synopsys DesignWare Memory Card Interface driver. + config MMC_DW_PCI tristate "Synopsys Designware MCI support on PCI bus" depends on MMC_DW && PCIdrivers/mmc/host/Makefile +1
-0@@ -42,6 +42,7 @@ obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_MMC_DW) += dw_mmc.o obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o +obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.odrivers/mmc/host/dw_mmc-exynos.c +0
-2@@ -31,8 +31,6 @@ SDMMC_CLKSEL_CCLK_DRIVE(y) | \ SDMMC_CLKSEL_CCLK_DIVIDER(z)) -#define SDMMC_CMD_USE_HOLD_REG BIT(29) -#define EXYNOS4210_FIXED_CIU_CLK_DIV 2#define EXYNOS4412_FIXED_CIU_CLK_DIV 4drivers/mmc/host/dw_mmc-socfpga.c new file +24
-0@@ -0,0 +1,139 @@ +/* +* Altera SoCFPGA Specific Extensions for Synopsys DW Multimedia Card Interface driver +* +* Copyright (C) 2012, Samsung Electronics Co., Ltd. +* Copyright (C) 2013 Altera Corporation +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Taken from dw_mmc-exynos.c +*/ +#include <linux/clk.h> +#include <linux/mfd/syscon.h> +#include <linux/mmc/host.h> +#include <linux/mmc/dw_mmc.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include "dw_mmc.h" +#include "dw_mmc-pltfm.h"
Quoted 8 lines
drivers/mmc/host/dw_mmc-socfpga.c line 29
Quoted 5 lines
drivers/mmc/host/dw_mmc-socfpga.c new file +5
-0+ +#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108 +#define DRV_CLK_PHASE_SHIFT_SEL_MASK 0x7 +#define SYSMGR_SDMMC_CTRL_SET (smplsel, drvsel) \ + ((((smplsel) & 0x38) << 3) | (((drvsel) & 0x7) << 0))Is it right?
0x38is already shifted..
(((smplsel &0x7) << 3) | ((drvsel &0x7) << 0))
isn't?
Yes, you're right! Will fix..
thanks,
Dinh
Quoted 127 lines
Best Regards,
Jaehoon ChungQuoted 123 lines
drivers/mmc/host/dw_mmc-socfpga.c new file +110
-0+ +/* SOCFPGA implementation specific driver private data */ +struct dw_mci_socfpga_priv_data { +u8 ciu_div;/* card interface unit divisor */ +u32 hs_timing;/* bitmask for CIU clock phase shift */ +struct regmap *sysreg;/* regmap for system manager register */ +}; + +static int dw_mci_socfpga_priv_init (struct dw_mci *host) +{ +struct dw_mci_socfpga_priv_data *priv; + + priv =devm_kzalloc (host->dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) { +dev_err (host->dev,"mem alloc failed for private data\n" ); +return -ENOMEM ; + } + + host->priv = priv; + + priv->sysreg =syscon_regmap_lookup_by_compatible ("altr,sys-mgr" ); +if (IS_ERR (priv->sysreg)) { +dev_err (host->dev,"regmap for altr,sys-mgr lookup failed.\n" ); +return PTR_ERR (priv->sysreg); + } + +return 0 ; +} + +static int dw_mci_socfpga_setup_clock (struct dw_mci *host) +{ +struct dw_mci_socfpga_priv_data *priv = host->priv; + +clk_disable_unprepare (host->ciu_clk); +regmap_write (priv->sysreg,SYSMGR_SDMMCGRP_CTRL_OFFSET , priv->hs_timing); +clk_prepare_enable (host->ciu_clk); + + host->bus_hz /= (priv->ciu_div +1 ); +return 0 ; +} + +static void dw_mci_socfpga_prepare_command (struct dw_mci *host,u32 *cmdr) +{ +struct dw_mci_socfpga_priv_data *priv = host->priv; + +if (priv->hs_timing &DRV_CLK_PHASE_SHIFT_SEL_MASK ) + *cmdr |=SDMMC_CMD_USE_HOLD_REG ; +} + +static int dw_mci_socfpga_parse_dt (struct dw_mci *host) +{ +struct dw_mci_socfpga_priv_data *priv = host->priv; +struct device_node *np = host->dev->of_node; +u32 timing[2 ]; +u32 div =0 ; +int ret; + + ret =of_property_read_u32 (np,"altr,dw-mshc-ciu-div" , &div); +if (ret) +dev_info (host->dev,"No dw-mshc-ciu-div specified, assuming 1" ); + priv->ciu_div = div; + + ret =of_property_read_u32_array (np, +"altr,dw-mshc-sdr-timing" , timing,2 ); +if (ret) +return ret; + + priv->hs_timing =SYSMGR_SDMMC_CTRL_SET (timing[0 ], timing[1 ]); +return 0 ; +} + +static const struct dw_mci_drv_data socfpga_drv_data = { + .init = dw_mci_socfpga_priv_init, + .setup_clock = dw_mci_socfpga_setup_clock, + .prepare_command = dw_mci_socfpga_prepare_command, + .parse_dt = dw_mci_socfpga_parse_dt, +}; + +static const struct of_device_id dw_mci_socfpga_match[] = { + { .compatible ="altr,socfpga-dw-mshc" , + .data = &socfpga_drv_data, }, + {}, +}; +MODULE_DEVICE_TABLE (of, dw_mci_socfpga_match); + +int dw_mci_socfpga_probe (struct platform_device *pdev) +{ +const struct dw_mci_drv_data *drv_data; +const struct of_device_id *match; + + match =of_match_node (dw_mci_socfpga_match, pdev->dev.of_node); + drv_data = match->data; +return dw_mci_pltfm_register (pdev, drv_data); +} + +static struct platform_driver dw_mci_socfpga_pltfm_driver = { + .probe = dw_mci_socfpga_probe, + .remove =__exit_p (dw_mci_pltfm_remove), + .driver = { + .name ="dwmmc_socfpga" , + .of_match_table =of_match_ptr (dw_mci_socfpga_match), + .pm = &dw_mci_pltfm_pmops, + }, +}; + +module_platform_driver (dw_mci_socfpga_pltfm_driver); + +MODULE_DESCRIPTION ("Altera SOCFPGA Specific DW-MSHC Driver Extension" ); +MODULE_LICENSE ("GPL v2" ); +MODULE_ALIAS ("platform:dwmmc-socfpga" );drivers/mmc/host/dw_mmc.h +1
-0@@ -111,6 +111,7 @@#define SDMMC_INT_ERROR 0xbfc2/* Command register defines */ #define SDMMC_CMD_START BIT(31) +#define SDMMC_CMD_USE_HOLD_REG BIT(29)#define SDMMC_CMD_CCS_EXP BIT(23)#define SDMMC_CMD_CEATA_RD BIT(22)#define SDMMC_CMD_UPD_CLK BIT(21)
PATCH v3 6/6 mmc: dw_mmc: Add support DW SD/MMC driver on SOCFPGA
In reply to dinguyen at altera.comJust one minor comment below.
Quoted 125 lines · Dinh Nguyen
From: Dinh Nguyen <[email protected]>
Add platform specific functionality for the DW SD/MMC driver for SoCFPGA. Move
SDMMC_CMD_USE_HOLD_REGtodw_mmc.hso other platforms can use this define.Signed-off-by Dinh Nguyen <[email protected]>CC Seungwon Jeon <[email protected]>CC Jaehoon Chung <[email protected]>CC Arnd Bergmann <[email protected]>CC Olof Johansson <[email protected]>CC Pavel Machek <[email protected]>CC linux-mmc at vger.kernel.orgv3:
- Addressed comments from Seugwon, Jaehoon, and Pavel
- Use clk_disable_unprepare/clk_prepare_enablev2:
- Use syscon and regmap
- Avoid divide by zero
- Remove the need to setPWR_EN--- drivers/mmc/host/Kconfig | 8 +++ drivers/mmc/host/Makefile | 1 + drivers/mmc/host/dw_mmc-exynos.c | 2 - drivers/mmc/host/dw_mmc-socfpga.c | 139 +++++++++++++++++++++++++++++++++++++ drivers/mmc/host/dw_mmc.h | 1 + 5 files changed, 149 insertions(+), 2 deletions(-) create mode 100644 drivers/mmc/host/dw_mmc-socfpga.cdrivers/mmc/host/Kconfig +8
-0@@ -556,6 +556,14 @@ config MMC_DW_EXYNOS Synopsys DesignWare Memory Card Interface driver. Select this option for platforms based on Exynos4 and Exynos5 SoC's. +config MMC_DW_SOCFPGA + tristate "SOCFPGA specific extensions for Synopsys DW Memory Card Interface" + depends on MMC_DW + select MMC_DW_PLTFM + help + This selects support for Altera SoCFPGA specific extensions to the + Synopsys DesignWare Memory Card Interface driver. + config MMC_DW_PCI tristate "Synopsys Designware MCI support on PCI bus" depends on MMC_DW && PCIdrivers/mmc/host/Makefile +1
-0@@ -42,6 +42,7 @@ obj-$(CONFIG_SDH_BFIN) += bfin_sdh.o obj-$(CONFIG_MMC_DW) += dw_mmc.o obj-$(CONFIG_MMC_DW_PLTFM) += dw_mmc-pltfm.o obj-$(CONFIG_MMC_DW_EXYNOS) += dw_mmc-exynos.o +obj-$(CONFIG_MMC_DW_SOCFPGA) += dw_mmc-socfpga.o obj-$(CONFIG_MMC_DW_PCI) += dw_mmc-pci.o obj-$(CONFIG_MMC_SH_MMCIF) += sh_mmcif.o obj-$(CONFIG_MMC_JZ4740) += jz4740_mmc.odrivers/mmc/host/dw_mmc-exynos.c +0
-2@@ -31,8 +31,6 @@ SDMMC_CLKSEL_CCLK_DRIVE(y) | \ SDMMC_CLKSEL_CCLK_DIVIDER(z)) -#define SDMMC_CMD_USE_HOLD_REG BIT(29) -#define EXYNOS4210_FIXED_CIU_CLK_DIV 2#define EXYNOS4412_FIXED_CIU_CLK_DIV 4drivers/mmc/host/dw_mmc-socfpga.c new file +44
-0@@ -0,0 +1,139 @@ +/* +* Altera SoCFPGA Specific Extensions for Synopsys DW Multimedia Card Interface driver +* +* Copyright (C) 2012, Samsung Electronics Co., Ltd. +* Copyright (C) 2013 Altera Corporation +* +* This program is free software; you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation; either version 2 of the License, or +* (at your option) any later version. +* +* Taken from dw_mmc-exynos.c +*/ +#include <linux/clk.h> +#include <linux/mfd/syscon.h> +#include <linux/mmc/host.h> +#include <linux/mmc/dw_mmc.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> + +#include "dw_mmc.h" +#include "dw_mmc-pltfm.h" + +#define SYSMGR_SDMMCGRP_CTRL_OFFSET 0x108 +#define DRV_CLK_PHASE_SHIFT_SEL_MASK 0x7 +#define SYSMGR_SDMMC_CTRL_SET (smplsel, drvsel) \ + ((((smplsel) & 0x38) << 3) | (((drvsel) & 0x7) << 0)) + +/* SOCFPGA implementation specific driver private data */ +struct dw_mci_socfpga_priv_data { +u8 ciu_div;/* card interface unit divisor */ +u32 hs_timing;/* bitmask for CIU clock phase shift */ +struct regmap *sysreg;/* regmap for system manager register */ +}; + +static int dw_mci_socfpga_priv_init (struct dw_mci *host) +{ +struct dw_mci_socfpga_priv_data *priv; + + priv =devm_kzalloc (host->dev,sizeof (*priv),GFP_KERNEL ); +if (!priv) { +dev_err (host->dev,"mem alloc failed for private data\n" );
drivers/mmc/host/dw_mmc-socfpga.c line 54
Quoted 10 lines
drivers/mmc/host/dw_mmc-socfpga.c new file +10
-0+return -ENOMEM ; + } + + host->priv = priv; + + priv->sysreg =syscon_regmap_lookup_by_compatible ("altr,sys-mgr" ); +if (IS_ERR (priv->sysreg)) { +dev_err (host->dev,"regmap for altr,sys-mgr lookup failed.\n" ); +return PTR_ERR (priv->sysreg); + }
'host->priv = priv;' is expected here after all is done with success.
Thanks,
Seungwon Jeon
Quoted 105 lines
drivers/mmc/host/dw_mmc-socfpga.c new file +85
-0+ +return 0 ; +} + +static int dw_mci_socfpga_setup_clock (struct dw_mci *host) +{ +struct dw_mci_socfpga_priv_data *priv = host->priv; + +clk_disable_unprepare (host->ciu_clk); +regmap_write (priv->sysreg,SYSMGR_SDMMCGRP_CTRL_OFFSET , priv->hs_timing); +clk_prepare_enable (host->ciu_clk); + + host->bus_hz /= (priv->ciu_div +1 ); +return 0 ; +} + +static void dw_mci_socfpga_prepare_command (struct dw_mci *host,u32 *cmdr) +{ +struct dw_mci_socfpga_priv_data *priv = host->priv; + +if (priv->hs_timing &DRV_CLK_PHASE_SHIFT_SEL_MASK ) + *cmdr |=SDMMC_CMD_USE_HOLD_REG ; +} + +static int dw_mci_socfpga_parse_dt (struct dw_mci *host) +{ +struct dw_mci_socfpga_priv_data *priv = host->priv; +struct device_node *np = host->dev->of_node; +u32 timing[2 ]; +u32 div =0 ; +int ret; + + ret =of_property_read_u32 (np,"altr,dw-mshc-ciu-div" , &div); +if (ret) +dev_info (host->dev,"No dw-mshc-ciu-div specified, assuming 1" ); + priv->ciu_div = div; + + ret =of_property_read_u32_array (np, +"altr,dw-mshc-sdr-timing" , timing,2 ); +if (ret) +return ret; + + priv->hs_timing =SYSMGR_SDMMC_CTRL_SET (timing[0 ], timing[1 ]); +return 0 ; +} + +static const struct dw_mci_drv_data socfpga_drv_data = { + .init = dw_mci_socfpga_priv_init, + .setup_clock = dw_mci_socfpga_setup_clock, + .prepare_command = dw_mci_socfpga_prepare_command, + .parse_dt = dw_mci_socfpga_parse_dt, +}; + +static const struct of_device_id dw_mci_socfpga_match[] = { + { .compatible ="altr,socfpga-dw-mshc" , + .data = &socfpga_drv_data, }, + {}, +}; +MODULE_DEVICE_TABLE (of, dw_mci_socfpga_match); + +int dw_mci_socfpga_probe (struct platform_device *pdev) +{ +const struct dw_mci_drv_data *drv_data; +const struct of_device_id *match; + + match =of_match_node (dw_mci_socfpga_match, pdev->dev.of_node); + drv_data = match->data; +return dw_mci_pltfm_register (pdev, drv_data); +} + +static struct platform_driver dw_mci_socfpga_pltfm_driver = { + .probe = dw_mci_socfpga_probe, + .remove =__exit_p (dw_mci_pltfm_remove), + .driver = { + .name ="dwmmc_socfpga" , + .of_match_table =of_match_ptr (dw_mci_socfpga_match), + .pm = &dw_mci_pltfm_pmops, + }, +}; + +module_platform_driver (dw_mci_socfpga_pltfm_driver); + +MODULE_DESCRIPTION ("Altera SOCFPGA Specific DW-MSHC Driver Extension" ); +MODULE_LICENSE ("GPL v2" ); +MODULE_ALIAS ("platform:dwmmc-socfpga" );drivers/mmc/host/dw_mmc.h +1
-1@@ -111,6 +111,7 @@#define SDMMC_INT_ERROR 0xbfc2/* Command register defines */ #define SDMMC_CMD_START BIT(31) +#define SDMMC_CMD_USE_HOLD_REG BIT(29)#define SDMMC_CMD_CCS_EXP BIT(23)#define SDMMC_CMD_CEATA_RD BIT(22)#define SDMMC_CMD_UPD_CLK BIT(21) --1.7.9.5
--
To unsubscribe from this list: send the line "unsubscribe linux-mmc" in the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html