diff options
20 files changed, 3026 insertions, 232 deletions
diff --git a/0001-ARM-davinci-uart-move-to-devid-based-clk_get.patch b/0001-ARM-davinci-uart-move-to-devid-based-clk_get.patch new file mode 100644 index 000000000..0e5b12d42 --- /dev/null +++ b/0001-ARM-davinci-uart-move-to-devid-based-clk_get.patch @@ -0,0 +1,724 @@ +From da41a8e42998c4bff8b19ee3d9fdfed6a5951c3f Mon Sep 17 00:00:00 2001 +From: "Manjunathappa, Prakash" <prakash.pm@ti.com> +Date: Wed, 19 Jun 2013 14:45:38 +0530 +Subject: [PATCH 01/13] ARM: davinci: uart: move to devid based clk_get + +For modules having single clock, clk_get should be done with dev_id. +But current davinci implementation handles multiple instances +of the UART devices with single platform_device_register. Hence clk_get +is based on con_id rather than dev_id, this is not correct. Do +platform_device_register for each instance and clk_get on dev_id. + +Signed-off-by: Manjunathappa, Prakash <prakash.pm@ti.com> +Signed-off-by: Sekhar Nori <nsekhar@ti.com> +--- + arch/arm/mach-davinci/da830.c | 8 ++-- + arch/arm/mach-davinci/da850.c | 8 ++-- + arch/arm/mach-davinci/devices-da8xx.c | 42 +++++++++++++++++---- + arch/arm/mach-davinci/devices-tnetv107x.c | 37 +++++++++++++++--- + arch/arm/mach-davinci/dm355.c | 52 ++++++++++++++++++++------ + arch/arm/mach-davinci/dm365.c | 38 +++++++++++++------ + arch/arm/mach-davinci/dm644x.c | 52 ++++++++++++++++++++------ + arch/arm/mach-davinci/dm646x.c | 52 ++++++++++++++++++++------ + arch/arm/mach-davinci/include/mach/da8xx.h | 2 +- + arch/arm/mach-davinci/include/mach/tnetv107x.h | 2 +- + arch/arm/mach-davinci/serial.c | 19 ++++++---- + arch/arm/mach-davinci/tnetv107x.c | 8 ++-- + 12 files changed, 239 insertions(+), 81 deletions(-) + +diff --git a/arch/arm/mach-davinci/da830.c b/arch/arm/mach-davinci/da830.c +index abbaf02..a3ffd52 100644 +--- a/arch/arm/mach-davinci/da830.c ++++ b/arch/arm/mach-davinci/da830.c +@@ -395,9 +395,9 @@ static struct clk_lookup da830_clks[] = { + CLK(NULL, "tptc0", &tptc0_clk), + CLK(NULL, "tptc1", &tptc1_clk), + CLK("da830-mmc.0", NULL, &mmcsd_clk), +- CLK(NULL, "uart0", &uart0_clk), +- CLK(NULL, "uart1", &uart1_clk), +- CLK(NULL, "uart2", &uart2_clk), ++ CLK("serial8250.0", NULL, &uart0_clk), ++ CLK("serial8250.1", NULL, &uart1_clk), ++ CLK("serial8250.2", NULL, &uart2_clk), + CLK("spi_davinci.0", NULL, &spi0_clk), + CLK("spi_davinci.1", NULL, &spi1_clk), + CLK(NULL, "ecap0", &ecap0_clk), +@@ -1199,7 +1199,7 @@ static struct davinci_soc_info davinci_soc_info_da830 = { + .gpio_base = DA8XX_GPIO_BASE, + .gpio_num = 128, + .gpio_irq = IRQ_DA8XX_GPIO0, +- .serial_dev = &da8xx_serial_device, ++ .serial_dev = da8xx_serial_device, + .emac_pdata = &da8xx_emac_pdata, + }; + +diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c +index a0d4f60..d4274ab 100644 +--- a/arch/arm/mach-davinci/da850.c ++++ b/arch/arm/mach-davinci/da850.c +@@ -451,9 +451,9 @@ static struct clk_lookup da850_clks[] = { + CLK(NULL, "tpcc1", &tpcc1_clk), + CLK(NULL, "tptc2", &tptc2_clk), + CLK("pruss_uio", "pruss", &pruss_clk), +- CLK(NULL, "uart0", &uart0_clk), +- CLK(NULL, "uart1", &uart1_clk), +- CLK(NULL, "uart2", &uart2_clk), ++ CLK("serial8250.0", NULL, &uart0_clk), ++ CLK("serial8250.1", NULL, &uart1_clk), ++ CLK("serial8250.2", NULL, &uart2_clk), + CLK(NULL, "aintc", &aintc_clk), + CLK(NULL, "gpio", &gpio_clk), + CLK("i2c_davinci.2", NULL, &i2c1_clk), +@@ -1301,7 +1301,7 @@ static struct davinci_soc_info davinci_soc_info_da850 = { + .gpio_base = DA8XX_GPIO_BASE, + .gpio_num = 144, + .gpio_irq = IRQ_DA8XX_GPIO0, +- .serial_dev = &da8xx_serial_device, ++ .serial_dev = da8xx_serial_device, + .emac_pdata = &da8xx_emac_pdata, + .sram_dma = DA8XX_SHARED_RAM_BASE, + .sram_len = SZ_128K, +diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c +index 71a46a3..280f67d 100644 +--- a/arch/arm/mach-davinci/devices-da8xx.c ++++ b/arch/arm/mach-davinci/devices-da8xx.c +@@ -68,7 +68,7 @@ + void __iomem *da8xx_syscfg0_base; + void __iomem *da8xx_syscfg1_base; + +-static struct plat_serial8250_port da8xx_serial_pdata[] = { ++static struct plat_serial8250_port da8xx_serial0_pdata[] = { + { + .mapbase = DA8XX_UART0_BASE, + .irq = IRQ_DA8XX_UARTINT0, +@@ -78,6 +78,11 @@ static struct plat_serial8250_port da8xx_serial_pdata[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port da8xx_serial1_pdata[] = { ++ { + .mapbase = DA8XX_UART1_BASE, + .irq = IRQ_DA8XX_UARTINT1, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -86,6 +91,11 @@ static struct plat_serial8250_port da8xx_serial_pdata[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port da8xx_serial2_pdata[] = { ++ { + .mapbase = DA8XX_UART2_BASE, + .irq = IRQ_DA8XX_UARTINT2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -95,15 +105,33 @@ static struct plat_serial8250_port da8xx_serial_pdata[] = { + }, + { + .flags = 0, +- }, ++ } + }; + +-struct platform_device da8xx_serial_device = { +- .name = "serial8250", +- .id = PLAT8250_DEV_PLATFORM, +- .dev = { +- .platform_data = da8xx_serial_pdata, ++struct platform_device da8xx_serial_device[] = { ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = da8xx_serial0_pdata, ++ } ++ }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM1, ++ .dev = { ++ .platform_data = da8xx_serial1_pdata, ++ } + }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM2, ++ .dev = { ++ .platform_data = da8xx_serial2_pdata, ++ } ++ }, ++ { ++ } + }; + + static s8 da8xx_queue_tc_mapping[][2] = { +diff --git a/arch/arm/mach-davinci/devices-tnetv107x.c b/arch/arm/mach-davinci/devices-tnetv107x.c +index 128cb9a..fc4a0fe 100644 +--- a/arch/arm/mach-davinci/devices-tnetv107x.c ++++ b/arch/arm/mach-davinci/devices-tnetv107x.c +@@ -126,7 +126,7 @@ static struct platform_device edma_device = { + .dev.platform_data = tnetv107x_edma_info, + }; + +-static struct plat_serial8250_port serial_data[] = { ++static struct plat_serial8250_port serial0_platform_data[] = { + { + .mapbase = TNETV107X_UART0_BASE, + .irq = IRQ_TNETV107X_UART0, +@@ -137,6 +137,11 @@ static struct plat_serial8250_port serial_data[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port serial1_platform_data[] = { ++ { + .mapbase = TNETV107X_UART1_BASE, + .irq = IRQ_TNETV107X_UART1, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -146,6 +151,11 @@ static struct plat_serial8250_port serial_data[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port serial2_platform_data[] = { ++ { + .mapbase = TNETV107X_UART2_BASE, + .irq = IRQ_TNETV107X_UART2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -156,13 +166,28 @@ static struct plat_serial8250_port serial_data[] = { + }, + { + .flags = 0, +- }, ++ } + }; + +-struct platform_device tnetv107x_serial_device = { +- .name = "serial8250", +- .id = PLAT8250_DEV_PLATFORM, +- .dev.platform_data = serial_data, ++ ++struct platform_device tnetv107x_serial_device[] = { ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev.platform_data = serial0_platform_data, ++ }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM1, ++ .dev.platform_data = serial1_platform_data, ++ }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM2, ++ .dev.platform_data = serial2_platform_data, ++ }, ++ { ++ } + }; + + static struct resource mmc0_resources[] = { +diff --git a/arch/arm/mach-davinci/dm355.c b/arch/arm/mach-davinci/dm355.c +index 86100d1..1701a2d 100644 +--- a/arch/arm/mach-davinci/dm355.c ++++ b/arch/arm/mach-davinci/dm355.c +@@ -357,9 +357,9 @@ static struct clk_lookup dm355_clks[] = { + CLK(NULL, "clkout3", &clkout3_clk), + CLK(NULL, "arm", &arm_clk), + CLK(NULL, "mjcp", &mjcp_clk), +- CLK(NULL, "uart0", &uart0_clk), +- CLK(NULL, "uart1", &uart1_clk), +- CLK(NULL, "uart2", &uart2_clk), ++ CLK("serial8250.0", NULL, &uart0_clk), ++ CLK("serial8250.1", NULL, &uart1_clk), ++ CLK("serial8250.2", NULL, &uart2_clk), + CLK("i2c_davinci.1", NULL, &i2c_clk), + CLK("davinci-mcbsp.0", NULL, &asp0_clk), + CLK("davinci-mcbsp.1", NULL, &asp1_clk), +@@ -922,7 +922,7 @@ static struct davinci_timer_info dm355_timer_info = { + .clocksource_id = T0_TOP, + }; + +-static struct plat_serial8250_port dm355_serial_platform_data[] = { ++static struct plat_serial8250_port dm355_serial0_platform_data[] = { + { + .mapbase = DAVINCI_UART0_BASE, + .irq = IRQ_UARTINT0, +@@ -932,6 +932,11 @@ static struct plat_serial8250_port dm355_serial_platform_data[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port dm355_serial1_platform_data[] = { ++ { + .mapbase = DAVINCI_UART1_BASE, + .irq = IRQ_UARTINT1, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -940,6 +945,11 @@ static struct plat_serial8250_port dm355_serial_platform_data[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port dm355_serial2_platform_data[] = { ++ { + .mapbase = DM355_UART2_BASE, + .irq = IRQ_DM355_UARTINT2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -948,16 +958,34 @@ static struct plat_serial8250_port dm355_serial_platform_data[] = { + .regshift = 2, + }, + { +- .flags = 0 +- }, ++ .flags = 0, ++ } + }; + +-static struct platform_device dm355_serial_device = { +- .name = "serial8250", +- .id = PLAT8250_DEV_PLATFORM, +- .dev = { +- .platform_data = dm355_serial_platform_data, ++static struct platform_device dm355_serial_device[] = { ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = dm355_serial0_platform_data, ++ } ++ }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM1, ++ .dev = { ++ .platform_data = dm355_serial1_platform_data, ++ } + }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM2, ++ .dev = { ++ .platform_data = dm355_serial2_platform_data, ++ } ++ }, ++ { ++ } + }; + + static struct davinci_soc_info davinci_soc_info_dm355 = { +@@ -981,7 +1009,7 @@ static struct davinci_soc_info davinci_soc_info_dm355 = { + .gpio_base = DAVINCI_GPIO_BASE, + .gpio_num = 104, + .gpio_irq = IRQ_DM355_GPIOBNK0, +- .serial_dev = &dm355_serial_device, ++ .serial_dev = dm355_serial_device, + .sram_dma = 0x00010000, + .sram_len = SZ_32K, + }; +diff --git a/arch/arm/mach-davinci/dm365.c b/arch/arm/mach-davinci/dm365.c +index dad2802..5b3a1bc 100644 +--- a/arch/arm/mach-davinci/dm365.c ++++ b/arch/arm/mach-davinci/dm365.c +@@ -455,8 +455,8 @@ static struct clk_lookup dm365_clks[] = { + CLK("vpss", "master", &vpss_master_clk), + CLK("vpss", "slave", &vpss_slave_clk), + CLK(NULL, "arm", &arm_clk), +- CLK(NULL, "uart0", &uart0_clk), +- CLK(NULL, "uart1", &uart1_clk), ++ CLK("serial8250.0", NULL, &uart0_clk), ++ CLK("serial8250.1", NULL, &uart1_clk), + CLK("i2c_davinci.1", NULL, &i2c_clk), + CLK("da830-mmc.0", NULL, &mmcsd0_clk), + CLK("da830-mmc.1", NULL, &mmcsd1_clk), +@@ -1041,7 +1041,7 @@ static struct davinci_timer_info dm365_timer_info = { + + #define DM365_UART1_BASE (IO_PHYS + 0x106000) + +-static struct plat_serial8250_port dm365_serial_platform_data[] = { ++static struct plat_serial8250_port dm365_serial0_platform_data[] = { + { + .mapbase = DAVINCI_UART0_BASE, + .irq = IRQ_UARTINT0, +@@ -1051,6 +1051,11 @@ static struct plat_serial8250_port dm365_serial_platform_data[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port dm365_serial1_platform_data[] = { ++ { + .mapbase = DM365_UART1_BASE, + .irq = IRQ_UARTINT1, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -1059,16 +1064,27 @@ static struct plat_serial8250_port dm365_serial_platform_data[] = { + .regshift = 2, + }, + { +- .flags = 0 +- }, ++ .flags = 0, ++ } + }; + +-static struct platform_device dm365_serial_device = { +- .name = "serial8250", +- .id = PLAT8250_DEV_PLATFORM, +- .dev = { +- .platform_data = dm365_serial_platform_data, ++static struct platform_device dm365_serial_device[] = { ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = dm365_serial0_platform_data, ++ } ++ }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM1, ++ .dev = { ++ .platform_data = dm365_serial1_platform_data, ++ } + }, ++ { ++ } + }; + + static struct davinci_soc_info davinci_soc_info_dm365 = { +@@ -1093,7 +1109,7 @@ static struct davinci_soc_info davinci_soc_info_dm365 = { + .gpio_num = 104, + .gpio_irq = IRQ_DM365_GPIO0, + .gpio_unbanked = 8, /* really 16 ... skip muxed GPIOs */ +- .serial_dev = &dm365_serial_device, ++ .serial_dev = dm365_serial_device, + .emac_pdata = &dm365_emac_pdata, + .sram_dma = 0x00010000, + .sram_len = SZ_32K, +diff --git a/arch/arm/mach-davinci/dm644x.c b/arch/arm/mach-davinci/dm644x.c +index a49d182..490eb8c 100644 +--- a/arch/arm/mach-davinci/dm644x.c ++++ b/arch/arm/mach-davinci/dm644x.c +@@ -303,9 +303,9 @@ static struct clk_lookup dm644x_clks[] = { + CLK("vpss", "master", &vpss_master_clk), + CLK("vpss", "slave", &vpss_slave_clk), + CLK(NULL, "arm", &arm_clk), +- CLK(NULL, "uart0", &uart0_clk), +- CLK(NULL, "uart1", &uart1_clk), +- CLK(NULL, "uart2", &uart2_clk), ++ CLK("serial8250.0", NULL, &uart0_clk), ++ CLK("serial8250.1", NULL, &uart1_clk), ++ CLK("serial8250.2", NULL, &uart2_clk), + CLK("davinci_emac.1", NULL, &emac_clk), + CLK("i2c_davinci.1", NULL, &i2c_clk), + CLK("palm_bk3710", NULL, &ide_clk), +@@ -813,7 +813,7 @@ static struct davinci_timer_info dm644x_timer_info = { + .clocksource_id = T0_TOP, + }; + +-static struct plat_serial8250_port dm644x_serial_platform_data[] = { ++static struct plat_serial8250_port dm644x_serial0_platform_data[] = { + { + .mapbase = DAVINCI_UART0_BASE, + .irq = IRQ_UARTINT0, +@@ -823,6 +823,11 @@ static struct plat_serial8250_port dm644x_serial_platform_data[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port dm644x_serial1_platform_data[] = { ++ { + .mapbase = DAVINCI_UART1_BASE, + .irq = IRQ_UARTINT1, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -831,6 +836,11 @@ static struct plat_serial8250_port dm644x_serial_platform_data[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port dm644x_serial2_platform_data[] = { ++ { + .mapbase = DAVINCI_UART2_BASE, + .irq = IRQ_UARTINT2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -839,16 +849,34 @@ static struct plat_serial8250_port dm644x_serial_platform_data[] = { + .regshift = 2, + }, + { +- .flags = 0 +- }, ++ .flags = 0, ++ } + }; + +-static struct platform_device dm644x_serial_device = { +- .name = "serial8250", +- .id = PLAT8250_DEV_PLATFORM, +- .dev = { +- .platform_data = dm644x_serial_platform_data, ++static struct platform_device dm644x_serial_device[] = { ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = dm644x_serial0_platform_data, ++ } + }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM1, ++ .dev = { ++ .platform_data = dm644x_serial1_platform_data, ++ } ++ }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM2, ++ .dev = { ++ .platform_data = dm644x_serial2_platform_data, ++ } ++ }, ++ { ++ } + }; + + static struct davinci_soc_info davinci_soc_info_dm644x = { +@@ -872,7 +900,7 @@ static struct davinci_soc_info davinci_soc_info_dm644x = { + .gpio_base = DAVINCI_GPIO_BASE, + .gpio_num = 71, + .gpio_irq = IRQ_GPIOBNK0, +- .serial_dev = &dm644x_serial_device, ++ .serial_dev = dm644x_serial_device, + .emac_pdata = &dm644x_emac_pdata, + .sram_dma = 0x00008000, + .sram_len = SZ_16K, +diff --git a/arch/arm/mach-davinci/dm646x.c b/arch/arm/mach-davinci/dm646x.c +index d1259e8..23609b1 100644 +--- a/arch/arm/mach-davinci/dm646x.c ++++ b/arch/arm/mach-davinci/dm646x.c +@@ -342,9 +342,9 @@ static struct clk_lookup dm646x_clks[] = { + CLK(NULL, "edma_tc1", &edma_tc1_clk), + CLK(NULL, "edma_tc2", &edma_tc2_clk), + CLK(NULL, "edma_tc3", &edma_tc3_clk), +- CLK(NULL, "uart0", &uart0_clk), +- CLK(NULL, "uart1", &uart1_clk), +- CLK(NULL, "uart2", &uart2_clk), ++ CLK("serial8250.0", NULL, &uart0_clk), ++ CLK("serial8250.1", NULL, &uart1_clk), ++ CLK("serial8250.2", NULL, &uart2_clk), + CLK("i2c_davinci.1", NULL, &i2c_clk), + CLK(NULL, "gpio", &gpio_clk), + CLK("davinci-mcasp.0", NULL, &mcasp0_clk), +@@ -790,7 +790,7 @@ static struct davinci_timer_info dm646x_timer_info = { + .clocksource_id = T0_TOP, + }; + +-static struct plat_serial8250_port dm646x_serial_platform_data[] = { ++static struct plat_serial8250_port dm646x_serial0_platform_data[] = { + { + .mapbase = DAVINCI_UART0_BASE, + .irq = IRQ_UARTINT0, +@@ -800,6 +800,11 @@ static struct plat_serial8250_port dm646x_serial_platform_data[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port dm646x_serial1_platform_data[] = { ++ { + .mapbase = DAVINCI_UART1_BASE, + .irq = IRQ_UARTINT1, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -808,6 +813,11 @@ static struct plat_serial8250_port dm646x_serial_platform_data[] = { + .regshift = 2, + }, + { ++ .flags = 0, ++ } ++}; ++static struct plat_serial8250_port dm646x_serial2_platform_data[] = { ++ { + .mapbase = DAVINCI_UART2_BASE, + .irq = IRQ_DM646X_UARTINT2, + .flags = UPF_BOOT_AUTOCONF | UPF_SKIP_TEST | +@@ -816,16 +826,34 @@ static struct plat_serial8250_port dm646x_serial_platform_data[] = { + .regshift = 2, + }, + { +- .flags = 0 +- }, ++ .flags = 0, ++ } + }; + +-static struct platform_device dm646x_serial_device = { +- .name = "serial8250", +- .id = PLAT8250_DEV_PLATFORM, +- .dev = { +- .platform_data = dm646x_serial_platform_data, ++static struct platform_device dm646x_serial_device[] = { ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM, ++ .dev = { ++ .platform_data = dm646x_serial0_platform_data, ++ } ++ }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM1, ++ .dev = { ++ .platform_data = dm646x_serial1_platform_data, ++ } + }, ++ { ++ .name = "serial8250", ++ .id = PLAT8250_DEV_PLATFORM2, ++ .dev = { ++ .platform_data = dm646x_serial2_platform_data, ++ } ++ }, ++ { ++ } + }; + + static struct davinci_soc_info davinci_soc_info_dm646x = { +@@ -849,7 +877,7 @@ static struct davinci_soc_info davinci_soc_info_dm646x = { + .gpio_base = DAVINCI_GPIO_BASE, + .gpio_num = 43, /* Only 33 usable */ + .gpio_irq = IRQ_DM646X_GPIOBNK0, +- .serial_dev = &dm646x_serial_device, ++ .serial_dev = dm646x_serial_device, + .emac_pdata = &dm646x_emac_pdata, + .sram_dma = 0x10010000, + .sram_len = SZ_32K, +diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h +index 7b41a5e..aae5307 100644 +--- a/arch/arm/mach-davinci/include/mach/da8xx.h ++++ b/arch/arm/mach-davinci/include/mach/da8xx.h +@@ -111,7 +111,7 @@ void da8xx_restart(enum reboot_mode mode, const char *cmd); + void da8xx_rproc_reserve_cma(void); + int da8xx_register_rproc(void); + +-extern struct platform_device da8xx_serial_device; ++extern struct platform_device da8xx_serial_device[]; + extern struct emac_platform_data da8xx_emac_pdata; + extern struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata; + extern struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata; +diff --git a/arch/arm/mach-davinci/include/mach/tnetv107x.h b/arch/arm/mach-davinci/include/mach/tnetv107x.h +index 16314c6..beb7c0e 100644 +--- a/arch/arm/mach-davinci/include/mach/tnetv107x.h ++++ b/arch/arm/mach-davinci/include/mach/tnetv107x.h +@@ -50,7 +50,7 @@ struct tnetv107x_device_info { + }; + + extern struct platform_device tnetv107x_wdt_device; +-extern struct platform_device tnetv107x_serial_device; ++extern struct platform_device tnetv107x_serial_device[]; + + extern void tnetv107x_init(void); + extern void tnetv107x_devices_init(struct tnetv107x_device_info *); +diff --git a/arch/arm/mach-davinci/serial.c b/arch/arm/mach-davinci/serial.c +index f262581..57e6150 100644 +--- a/arch/arm/mach-davinci/serial.c ++++ b/arch/arm/mach-davinci/serial.c +@@ -76,7 +76,7 @@ int __init davinci_serial_setup_clk(unsigned instance, unsigned int *rate) + char name[16]; + struct clk *clk; + struct davinci_soc_info *soc_info = &davinci_soc_info; +- struct device *dev = &soc_info->serial_dev->dev; ++ struct device *dev = &soc_info->serial_dev[instance].dev; + + sprintf(name, "uart%d", instance); + clk = clk_get(dev, name); +@@ -96,19 +96,25 @@ int __init davinci_serial_setup_clk(unsigned instance, unsigned int *rate) + + int __init davinci_serial_init(struct davinci_uart_config *info) + { +- int i, ret; ++ int i, ret = 0; + struct davinci_soc_info *soc_info = &davinci_soc_info; +- struct device *dev = &soc_info->serial_dev->dev; +- struct plat_serial8250_port *p = dev->platform_data; ++ struct device *dev; ++ struct plat_serial8250_port *p; + + /* + * Make sure the serial ports are muxed on at this point. + * You have to mux them off in device drivers later on if not needed. + */ +- for (i = 0; p->flags; i++, p++) { ++ for (i = 0; soc_info->serial_dev[i].dev.platform_data != NULL; i++) { ++ dev = &soc_info->serial_dev[i].dev; ++ p = dev->platform_data; + if (!(info->enabled_uarts & (1 << i))) + continue; + ++ ret = platform_device_register(&soc_info->serial_dev[i]); ++ if (ret) ++ continue; ++ + ret = davinci_serial_setup_clk(i, &p->uartclk); + if (ret) + continue; +@@ -125,6 +131,5 @@ int __init davinci_serial_init(struct davinci_uart_config *info) + if (p->membase && p->type != PORT_AR7) + davinci_serial_reset(p); + } +- +- return platform_device_register(soc_info->serial_dev); ++ return ret; + } +diff --git a/arch/arm/mach-davinci/tnetv107x.c b/arch/arm/mach-davinci/tnetv107x.c +index 4545667..f4d7fbb 100644 +--- a/arch/arm/mach-davinci/tnetv107x.c ++++ b/arch/arm/mach-davinci/tnetv107x.c +@@ -264,7 +264,7 @@ static struct clk_lookup clks[] = { + CLK(NULL, "clk_chipcfg", &clk_chipcfg), + CLK("tnetv107x-ts.0", NULL, &clk_tsc), + CLK(NULL, "clk_rom", &clk_rom), +- CLK(NULL, "uart2", &clk_uart2), ++ CLK("serial8250.2", NULL, &clk_uart2), + CLK(NULL, "clk_pktsec", &clk_pktsec), + CLK("tnetv107x-rng.0", NULL, &clk_rng), + CLK("tnetv107x-pka.0", NULL, &clk_pka), +@@ -274,8 +274,8 @@ static struct clk_lookup clks[] = { + CLK(NULL, "clk_gpio", &clk_gpio), + CLK(NULL, "clk_mdio", &clk_mdio), + CLK("dm6441-mmc.0", NULL, &clk_sdio0), +- CLK(NULL, "uart0", &clk_uart0), +- CLK(NULL, "uart1", &clk_uart1), ++ CLK("serial8250.0", NULL, &clk_uart0), ++ CLK("serial8250.1", NULL, &clk_uart1), + CLK(NULL, "timer0", &clk_timer0), + CLK(NULL, "timer1", &clk_timer1), + CLK("tnetv107x_wdt.0", NULL, &clk_wdt_arm), +@@ -757,7 +757,7 @@ static struct davinci_soc_info tnetv107x_soc_info = { + .gpio_type = GPIO_TYPE_TNETV107X, + .gpio_num = TNETV107X_N_GPIO, + .timer_info = &timer_info, +- .serial_dev = &tnetv107x_serial_device, ++ .serial_dev = tnetv107x_serial_device, + }; + + void __init tnetv107x_init(void) +-- +1.8.2.1 + diff --git a/0001-am335x-dts-Add-beaglebone-black-DTS.patch b/0001-am335x-dts-Add-beaglebone-black-DTS.patch new file mode 100644 index 000000000..f1044324e --- /dev/null +++ b/0001-am335x-dts-Add-beaglebone-black-DTS.patch @@ -0,0 +1,323 @@ +From 35bd7cf94f2680c4674c1df72f9ab322f393a9c2 Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou <panto@antoniou-consulting.com> +Date: Fri, 28 Jun 2013 14:18:08 +0300 +Subject: [PATCH 1/4] am335x: dts: Add beaglebone black DTS + +Added the beaglebone black's DTS file. Note that at some point in +time we'll switch to using a common black.dtsi file. + +Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com> +--- + arch/arm/boot/dts/Makefile | 3 +- + arch/arm/boot/dts/am335x-boneblack.dts | 285 +++++++++++++++++++++++++++++++++ + 2 files changed, 287 insertions(+), 1 deletion(-) + create mode 100644 arch/arm/boot/dts/am335x-boneblack.dts + +diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 641b3c9a..1b60731 100644 +--- a/arch/arm/boot/dts/Makefile ++++ b/arch/arm/boot/dts/Makefile +@@ -173,7 +173,8 @@ dtb-$(CONFIG_ARCH_OMAP2PLUS) += omap2420-h4.dtb \ + am335x-bone.dtb \ + am3517-evm.dtb \ + am3517_mt_ventoux.dtb \ +- am43x-epos-evm.dtb ++ am43x-epos-evm.dtb \ ++ am335x-boneblack.dtb + dtb-$(CONFIG_ARCH_ORION5X) += orion5x-lacie-ethernet-disk-mini-v2.dtb + dtb-$(CONFIG_ARCH_PRIMA2) += prima2-evb.dtb + dtb-$(CONFIG_ARCH_U8500) += snowball.dtb \ +diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts +new file mode 100644 +index 0000000..75a924d +--- /dev/null ++++ b/arch/arm/boot/dts/am335x-boneblack.dts +@@ -0,0 +1,285 @@ ++/* ++ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License version 2 as ++ * published by the Free Software Foundation. ++ */ ++/dts-v1/; ++ ++#include "am33xx.dtsi" ++ ++/ { ++ model = "TI AM335x BeagleBone"; ++ compatible = "ti,am335x-bone", "ti,am33xx"; ++ ++ cpus { ++ cpu@0 { ++ cpu0-supply = <&dcdc2_reg>; ++ ++ /* ++ * To consider voltage drop between PMIC and SoC, ++ * tolerance value is reduced to 2% from 4% and ++ * voltage value is increased as a precaution. ++ */ ++ operating-points = < ++ /* kHz uV */ ++ 1000000 1350000 ++ 800000 1300000 ++ 600000 1112000 ++ 300000 969000 ++ >; ++ }; ++ }; ++ ++ memory { ++ device_type = "memory"; ++ reg = <0x80000000 0x20000000>; /* 512 MB */ ++ }; ++ ++ am33xx_pinmux: pinmux@44e10800 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&clkout2_pin>; ++ ++ user_leds_s0: user_leds_s0 { ++ pinctrl-single,pins = < ++ 0x54 (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a5.gpio1_21 */ ++ 0x58 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a6.gpio1_22 */ ++ 0x5c (PIN_OUTPUT_PULLDOWN | MUX_MODE7) /* gpmc_a7.gpio1_23 */ ++ 0x60 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a8.gpio1_24 */ ++ >; ++ }; ++ ++ i2c0_pins: pinmux_i2c0_pins { ++ pinctrl-single,pins = < ++ 0x188 (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_sda.i2c0_sda */ ++ 0x18c (PIN_INPUT_PULLUP | MUX_MODE0) /* i2c0_scl.i2c0_scl */ ++ >; ++ }; ++ ++ uart0_pins: pinmux_uart0_pins { ++ pinctrl-single,pins = < ++ 0x170 (PIN_INPUT_PULLUP | MUX_MODE0) /* uart0_rxd.uart0_rxd */ ++ 0x174 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* uart0_txd.uart0_txd */ ++ >; ++ }; ++ ++ clkout2_pin: pinmux_clkout2_pin { ++ pinctrl-single,pins = < ++ 0x1b4 (PIN_OUTPUT_PULLDOWN | MUX_MODE3) /* xdma_event_intr1.clkout2 */ ++ >; ++ }; ++ ++ cpsw_default: cpsw_default { ++ pinctrl-single,pins = < ++ /* Slave 1 */ ++ 0x110 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxerr.mii1_rxerr */ ++ 0x114 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txen.mii1_txen */ ++ 0x118 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxdv.mii1_rxdv */ ++ 0x11c (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd3.mii1_txd3 */ ++ 0x120 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd2.mii1_txd2 */ ++ 0x124 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd1.mii1_txd1 */ ++ 0x128 (PIN_OUTPUT_PULLDOWN | MUX_MODE0) /* mii1_txd0.mii1_txd0 */ ++ 0x12c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_txclk.mii1_txclk */ ++ 0x130 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxclk.mii1_rxclk */ ++ 0x134 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd3.mii1_rxd3 */ ++ 0x138 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd2.mii1_rxd2 */ ++ 0x13c (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd1.mii1_rxd1 */ ++ 0x140 (PIN_INPUT_PULLUP | MUX_MODE0) /* mii1_rxd0.mii1_rxd0 */ ++ >; ++ }; ++ ++ cpsw_sleep: cpsw_sleep { ++ pinctrl-single,pins = < ++ /* Slave 1 reset value */ ++ 0x110 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x114 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x118 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x11c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x120 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x124 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x128 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x12c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x130 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x134 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x138 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x13c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x140 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ >; ++ }; ++ ++ davinci_mdio_default: davinci_mdio_default { ++ pinctrl-single,pins = < ++ /* MDIO */ ++ 0x148 (PIN_INPUT_PULLUP | SLEWCTRL_FAST | MUX_MODE0) /* mdio_data.mdio_data */ ++ 0x14c (PIN_OUTPUT_PULLUP | MUX_MODE0) /* mdio_clk.mdio_clk */ ++ >; ++ }; ++ ++ davinci_mdio_sleep: davinci_mdio_sleep { ++ pinctrl-single,pins = < ++ /* MDIO reset value */ ++ 0x148 (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) ++ >; ++ }; ++ ++ emmc_pins: pinmux_emmc_pins { ++ pinctrl-single,pins = < ++ 0x80 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn1.mmc1_clk */ ++ 0x84 (PIN_INPUT_PULLUP | MUX_MODE2) /* gpmc_csn2.mmc1_cmd */ ++ 0x00 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad0.mmc1_dat0 */ ++ 0x04 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad1.mmc1_dat1 */ ++ 0x08 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad2.mmc1_dat2 */ ++ 0x0c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad3.mmc1_dat3 */ ++ 0x10 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad4.mmc1_dat4 */ ++ 0x14 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad5.mmc1_dat5 */ ++ 0x18 (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad6.mmc1_dat6 */ ++ 0x1c (PIN_INPUT_PULLUP | MUX_MODE1) /* gpmc_ad7.mmc1_dat7 */ ++ /* eMMC_RSTn */ ++ 0x50 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a4.gpio1_20 */ ++ >; ++ }; ++ }; ++ ++ ocp { ++ uart0: serial@44e09000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&uart0_pins>; ++ ++ status = "okay"; ++ }; ++ ++ i2c0: i2c@44e0b000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c0_pins>; ++ ++ status = "okay"; ++ clock-frequency = <400000>; ++ ++ tps: tps@24 { ++ reg = <0x24>; ++ }; ++ ++ }; ++ }; ++ ++ leds { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&user_leds_s0>; ++ ++ compatible = "gpio-leds"; ++ ++ led@2 { ++ label = "beaglebone:blue:heartbeat"; ++ gpios = <&gpio1 21 0>; ++ linux,default-trigger = "heartbeat"; ++ default-state = "off"; ++ }; ++ ++ led@3 { ++ label = "beaglebone:blue:mmc0"; ++ gpios = <&gpio1 22 GPIO_ACTIVE_HIGH>; ++ linux,default-trigger = "mmc0"; ++ default-state = "off"; ++ }; ++ ++ led@4 { ++ label = "beaglebone:blue:usr2"; ++ gpios = <&gpio1 23 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ ++ led@5 { ++ label = "beaglebone:blue:usr3"; ++ gpios = <&gpio1 24 GPIO_ACTIVE_HIGH>; ++ default-state = "off"; ++ }; ++ }; ++ ++ vmmcsd_fixed: fixedregulator@0 { ++ compatible = "regulator-fixed"; ++ regulator-name = "vmmcsd_fixed"; ++ regulator-min-microvolt = <3300000>; ++ regulator-max-microvolt = <3300000>; ++ }; ++ ++}; ++ ++/include/ "tps65217.dtsi" ++ ++&tps { ++ regulators { ++ dcdc1_reg: regulator@0 { ++ regulator-always-on; ++ }; ++ ++ dcdc2_reg: regulator@1 { ++ /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ ++ regulator-name = "vdd_mpu"; ++ regulator-min-microvolt = <925000>; ++ regulator-max-microvolt = <1325000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ dcdc3_reg: regulator@2 { ++ /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ ++ regulator-name = "vdd_core"; ++ regulator-min-microvolt = <925000>; ++ regulator-max-microvolt = <1150000>; ++ regulator-boot-on; ++ regulator-always-on; ++ }; ++ ++ ldo1_reg: regulator@3 { ++ regulator-always-on; ++ }; ++ ++ ldo2_reg: regulator@4 { ++ regulator-always-on; ++ }; ++ ++ ldo3_reg: regulator@5 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <1800000>; /* orig 3.3V*/ ++ regulator-always-on; ++ }; ++ ++ ldo4_reg: regulator@6 { ++ regulator-always-on; ++ }; ++ }; ++}; ++ ++&cpsw_emac0 { ++ phy_id = <&davinci_mdio>, <0>; ++}; ++ ++&cpsw_emac1 { ++ phy_id = <&davinci_mdio>, <1>; ++}; ++ ++&mac { ++ pinctrl-names = "default", "sleep"; ++ pinctrl-0 = <&cpsw_default>; ++ pinctrl-1 = <&cpsw_sleep>; ++}; ++ ++&mmc1 { ++ status = "okay"; ++ vmmc-supply = <&vmmcsd_fixed>; ++ ti,vcc-aux-disable-is-sleep; ++}; ++ ++&mmc2 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&emmc_pins>; ++ vmmc-supply = <&ldo3_reg>; ++ bus-width = <8>; ++ ti,non-removable; ++ status = "okay"; ++ ti,vcc-aux-disable-is-sleep; ++ ++ reset-gpio = <&gpio1 20 GPIO_ACTIVE_HIGH>; ++}; +-- +1.8.2.1 + diff --git a/0001-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch b/0001-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch new file mode 100644 index 000000000..2c7bc63cd --- /dev/null +++ b/0001-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch @@ -0,0 +1,34 @@ +From 9e6eeee6a1e0477f237dee5015c982296a91403f Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou <panto@antoniou-consulting.com> +Date: Fri, 26 Oct 2012 15:48:00 +0300 +Subject: [PATCH 1/2] omap-hsmmc: Correct usage of of_find_node_by_name + +of_find_node_by_name expect to have the parent node reference taken. +--- + drivers/mmc/host/omap_hsmmc.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c +index 91e2954..8ab4a93 100644 +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -1949,6 +1949,16 @@ static int omap_hsmmc_probe(struct platform_device *pdev) + * as we want. */ + mmc->max_segs = 1024; + ++ /* Eventually we should get our max_segs limitation for EDMA by ++ * querying the dmaengine API */ ++ if (pdev->dev.of_node) { ++ struct device_node *parent = of_node_get(pdev->dev.of_node->parent); ++ struct device_node *node; ++ node = of_find_node_by_name(parent, "edma"); ++ if (node) ++ mmc->max_segs = 16; ++ } ++ + mmc->max_blk_size = 512; /* Block Length at max can be 1024 */ + mmc->max_blk_count = 0xFFFF; /* No. of Blocks is 16 bits */ + mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count; +-- +1.8.2.1 + diff --git a/0001-reset-Add-driver-for-gpio-controlled-reset-pins.patch b/0001-reset-Add-driver-for-gpio-controlled-reset-pins.patch new file mode 100644 index 000000000..e5661aef1 --- /dev/null +++ b/0001-reset-Add-driver-for-gpio-controlled-reset-pins.patch @@ -0,0 +1,265 @@ +From 31bacc8256b3ddb19269a3a1c74b0ba3851d1e19 Mon Sep 17 00:00:00 2001 +From: Philipp Zabel <p.zabel@pengutronix.de> +Date: Tue, 28 May 2013 17:06:15 +0200 +Subject: [PATCH] reset: Add driver for gpio-controlled reset pins + +This driver implements a reset controller device that toggle a gpio +connected to a reset pin of a peripheral IC. The delay between assertion +and de-assertion of the reset signal can be configured via device tree. + +Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de> +Reviewed-by: Stephen Warren <swarren@nvidia.com> +--- + .../devicetree/bindings/reset/gpio-reset.txt | 35 +++++ + drivers/reset/Kconfig | 11 ++ + drivers/reset/Makefile | 1 + + drivers/reset/gpio-reset.c | 169 +++++++++++++++++++++ + 4 files changed, 216 insertions(+) + create mode 100644 Documentation/devicetree/bindings/reset/gpio-reset.txt + create mode 100644 drivers/reset/gpio-reset.c + +diff --git a/Documentation/devicetree/bindings/reset/gpio-reset.txt b/Documentation/devicetree/bindings/reset/gpio-reset.txt +new file mode 100644 +index 0000000..bca5348 +--- /dev/null ++++ b/Documentation/devicetree/bindings/reset/gpio-reset.txt +@@ -0,0 +1,35 @@ ++GPIO reset controller ++===================== ++ ++A GPIO reset controller controls a single GPIO that is connected to the reset ++pin of a peripheral IC. Please also refer to reset.txt in this directory for ++common reset controller binding usage. ++ ++Required properties: ++- compatible: Should be "gpio-reset" ++- reset-gpios: A gpio used as reset line. The gpio specifier for this property ++ depends on the gpio controller that provides the gpio. ++- #reset-cells: 0, see below ++ ++Optional properties: ++- reset-delay-us: delay in microseconds. The gpio reset line will be asserted for ++ this duration to reset. ++- initially-in-reset: boolean. If not set, the initial state should be a ++ deasserted reset line. If this property exists, the ++ reset line should be kept in reset. ++ ++example: ++ ++sii902x_reset: gpio-reset { ++ compatible = "gpio-reset"; ++ reset-gpios = <&gpio5 0 GPIO_ACTIVE_LOW>; ++ reset-delay-us = <10000>; ++ initially-in-reset; ++ #reset-cells = <0>; ++}; ++ ++/* Device with nRESET pin connected to GPIO5_0 */ ++sii902x@39 { ++ /* ... */ ++ resets = <&sii902x_reset>; /* active-low GPIO5_0, 10 ms delay */ ++}; +diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig +index c9d04f7..1a862df 100644 +--- a/drivers/reset/Kconfig ++++ b/drivers/reset/Kconfig +@@ -11,3 +11,14 @@ menuconfig RESET_CONTROLLER + via GPIOs or SoC-internal reset controller modules. + + If unsure, say no. ++ ++if RESET_CONTROLLER ++ ++config RESET_GPIO ++ tristate "GPIO reset controller support" ++ depends on GPIOLIB && OF ++ help ++ This driver provides support for reset lines that are controlled ++ directly by GPIOs. ++ ++endif +diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile +index 1e2d83f..b854f20 100644 +--- a/drivers/reset/Makefile ++++ b/drivers/reset/Makefile +@@ -1 +1,2 @@ + obj-$(CONFIG_RESET_CONTROLLER) += core.o ++obj-$(CONFIG_RESET_GPIO) += gpio-reset.o +diff --git a/drivers/reset/gpio-reset.c b/drivers/reset/gpio-reset.c +new file mode 100644 +index 0000000..acc1076 +--- /dev/null ++++ b/drivers/reset/gpio-reset.c +@@ -0,0 +1,169 @@ ++/* ++ * GPIO Reset Controller driver ++ * ++ * Copyright 2013 Philipp Zabel, Pengutronix ++ * ++ * 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. ++ */ ++#include <linux/delay.h> ++#include <linux/err.h> ++#include <linux/gpio.h> ++#include <linux/module.h> ++#include <linux/of_gpio.h> ++#include <linux/platform_device.h> ++#include <linux/reset-controller.h> ++ ++struct gpio_reset_data { ++ struct reset_controller_dev rcdev; ++ unsigned int gpio; ++ bool active_low; ++ u32 delay_us; ++}; ++ ++static void __gpio_reset_set(struct reset_controller_dev *rcdev, int asserted) ++{ ++ struct gpio_reset_data *drvdata = container_of(rcdev, ++ struct gpio_reset_data, rcdev); ++ int value = asserted; ++ ++ if (drvdata->active_low) ++ value = !value; ++ ++ gpio_set_value(drvdata->gpio, value); ++} ++ ++static int gpio_reset(struct reset_controller_dev *rcdev, unsigned long id) ++{ ++ struct gpio_reset_data *drvdata = container_of(rcdev, ++ struct gpio_reset_data, rcdev); ++ ++ if (drvdata->delay_us < 0) ++ return -ENOSYS; ++ ++ __gpio_reset_set(rcdev, 1); ++ udelay(drvdata->delay_us); ++ __gpio_reset_set(rcdev, 0); ++ ++ return 0; ++} ++ ++static int gpio_reset_assert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ __gpio_reset_set(rcdev, 1); ++ ++ return 0; ++} ++ ++static int gpio_reset_deassert(struct reset_controller_dev *rcdev, ++ unsigned long id) ++{ ++ __gpio_reset_set(rcdev, 0); ++ ++ return 0; ++} ++ ++static struct reset_control_ops gpio_reset_ops = { ++ .reset = gpio_reset, ++ .assert = gpio_reset_assert, ++ .deassert = gpio_reset_deassert, ++}; ++ ++static int of_gpio_reset_xlate(struct reset_controller_dev *rcdev, ++ const struct of_phandle_args *reset_spec) ++{ ++ if (WARN_ON(reset_spec->args_count != 0)) ++ return -EINVAL; ++ ++ return 0; ++} ++ ++static int gpio_reset_probe(struct platform_device *pdev) ++{ ++ struct device_node *np = pdev->dev.of_node; ++ struct gpio_reset_data *drvdata; ++ enum of_gpio_flags flags; ++ unsigned long gpio_flags; ++ bool initially_in_reset; ++ int ret; ++ ++ drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); ++ if (drvdata == NULL) ++ return -ENOMEM; ++ ++ if (of_gpio_named_count(np, "reset-gpios") != 1) ++ return -EINVAL; ++ ++ drvdata->gpio = of_get_named_gpio_flags(np, "reset-gpios", 0, &flags); ++ if (drvdata->gpio == -EPROBE_DEFER) { ++ return drvdata->gpio; ++ } else if (!gpio_is_valid(drvdata->gpio)) { ++ dev_err(&pdev->dev, "invalid reset gpio: %d\n", drvdata->gpio); ++ return drvdata->gpio; ++ } ++ ++ drvdata->active_low = flags & OF_GPIO_ACTIVE_LOW; ++ ++ ret = of_property_read_u32(np, "reset-delay-us", &drvdata->delay_us); ++ if (ret < 0) ++ return ret; ++ ++ initially_in_reset = of_property_read_bool(np, "initially-in-reset"); ++ if (drvdata->active_low ^ initially_in_reset) ++ gpio_flags = GPIOF_OUT_INIT_HIGH; ++ else ++ gpio_flags = GPIOF_OUT_INIT_LOW; ++ ++ ret = devm_gpio_request_one(&pdev->dev, drvdata->gpio, gpio_flags, NULL); ++ if (ret < 0) { ++ dev_err(&pdev->dev, "failed to request gpio %d: %d\n", ++ drvdata->gpio, ret); ++ return ret; ++ } ++ ++ drvdata->rcdev.of_node = np; ++ drvdata->rcdev.owner = THIS_MODULE; ++ drvdata->rcdev.nr_resets = 1; ++ drvdata->rcdev.ops = &gpio_reset_ops; ++ drvdata->rcdev.of_xlate = of_gpio_reset_xlate; ++ reset_controller_register(&drvdata->rcdev); ++ ++ platform_set_drvdata(pdev, drvdata); ++ ++ return 0; ++} ++ ++static int gpio_reset_remove(struct platform_device *pdev) ++{ ++ struct gpio_reset_data *drvdata = platform_get_drvdata(pdev); ++ ++ reset_controller_unregister(&drvdata->rcdev); ++ ++ return 0; ++} ++ ++static struct of_device_id gpio_reset_dt_ids[] = { ++ { .compatible = "gpio-reset" }, ++ { } ++}; ++ ++static struct platform_driver gpio_reset_driver = { ++ .probe = gpio_reset_probe, ++ .remove = gpio_reset_remove, ++ .driver = { ++ .name = "gpio-reset", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(gpio_reset_dt_ids), ++ }, ++}; ++ ++module_platform_driver(gpio_reset_driver); ++ ++MODULE_AUTHOR("Philipp Zabel <p.zabel@pengutronix.de>"); ++MODULE_DESCRIPTION("gpio reset controller"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:gpio-reset"); ++MODULE_DEVICE_TABLE(of, gpio_reset_dt_ids); +-- +1.8.2.1 + diff --git a/0002-dma-edma-add-device_slave_sg_limits-support.patch b/0002-dma-edma-add-device_slave_sg_limits-support.patch new file mode 100644 index 000000000..419b3203b --- /dev/null +++ b/0002-dma-edma-add-device_slave_sg_limits-support.patch @@ -0,0 +1,76 @@ +From 6077fbf31d4263222eb1815f1c4edf67e90a3434 Mon Sep 17 00:00:00 2001 +From: Matt Porter <mporter@ti.com> +Date: Wed, 6 Mar 2013 19:56:06 +0000 +Subject: [PATCH 02/13] dma: edma: add device_slave_sg_limits() support + +Implement device_slave_sg_limits(). + +EDMA has a finite set of PaRAM slots available for linking a +multi-segment SG transfer. In order to prevent any one channel +from consuming all PaRAM slots to fulfill a large SG transfer, +the driver reports a static per-channel max number of SG segments +it will handle. + +The maximum size of an SG segment is limited by the addr_width +and maxburst of a given transfer request. These values are +provided by the client driver and used to calculate and return +the maximum segment length. + +Signed-off-by: Matt Porter <mporter@ti.com> +Signed-off-by: Joel A Fernandes <joelagnel@ti.com> +--- + drivers/dma/edma.c | 17 +++++++++++++++++ + 1 file changed, 17 insertions(+) + +diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c +index 5f3e532..e008ed2 100644 +--- a/drivers/dma/edma.c ++++ b/drivers/dma/edma.c +@@ -70,6 +70,7 @@ struct edma_chan { + bool alloced; + int slot[EDMA_MAX_SLOTS]; + struct dma_slave_config cfg; ++ struct dma_slave_sg_limits sg_limits; + }; + + struct edma_cc { +@@ -462,6 +463,20 @@ static void edma_issue_pending(struct dma_chan *chan) + spin_unlock_irqrestore(&echan->vchan.lock, flags); + } + ++static struct dma_slave_sg_limits ++*edma_get_slave_sg_limits(struct dma_chan *chan, ++ enum dma_slave_buswidth addr_width, ++ u32 maxburst) ++{ ++ struct edma_chan *echan; ++ ++ echan = to_edma_chan(chan); ++ echan->sg_limits.max_seg_len = ++ (SZ_64K - 1) * addr_width * maxburst; ++ ++ return &echan->sg_limits; ++} ++ + static size_t edma_desc_size(struct edma_desc *edesc) + { + int i; +@@ -521,6 +536,7 @@ static void __init edma_chan_init(struct edma_cc *ecc, + echan->ch_num = EDMA_CTLR_CHAN(ecc->ctlr, i); + echan->ecc = ecc; + echan->vchan.desc_free = edma_desc_free; ++ echan->sg_limits.max_seg_nr = MAX_NR_SG; + + vchan_init(&echan->vchan, dma); + +@@ -537,6 +553,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma, + dma->device_alloc_chan_resources = edma_alloc_chan_resources; + dma->device_free_chan_resources = edma_free_chan_resources; + dma->device_issue_pending = edma_issue_pending; ++ dma->device_slave_sg_limits = edma_get_slave_sg_limits; + dma->device_tx_status = edma_tx_status; + dma->device_control = edma_control; + dma->dev = dev; +-- +1.8.2.1 + diff --git a/0002-dts-beaglebone-Add-I2C-definitions-for-EEPROMs-capes.patch b/0002-dts-beaglebone-Add-I2C-definitions-for-EEPROMs-capes.patch new file mode 100644 index 000000000..8493d1606 --- /dev/null +++ b/0002-dts-beaglebone-Add-I2C-definitions-for-EEPROMs-capes.patch @@ -0,0 +1,142 @@ +From e3c9bd680440e6216a86184687968a3939c06160 Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou <panto@antoniou-consulting.com> +Date: Fri, 28 Jun 2013 18:39:55 +0300 +Subject: [PATCH 2/4] dts: beaglebone: Add I2C definitions for EEPROMs & capes + +Add the I2C definitions for the EEPROM devices on the baseboard +and on the possibly connected capes. + +Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com> +--- + arch/arm/boot/dts/am335x-bone.dts | 44 ++++++++++++++++++++++++++++++++++ + arch/arm/boot/dts/am335x-boneblack.dts | 44 ++++++++++++++++++++++++++++++++++ + 2 files changed, 88 insertions(+) + +diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts +index b8debea..15c9643 100644 +--- a/arch/arm/boot/dts/am335x-bone.dts ++++ b/arch/arm/boot/dts/am335x-bone.dts +@@ -110,6 +110,18 @@ + 0x14c (PIN_INPUT_PULLDOWN | MUX_MODE7) + >; + }; ++ i2c0_pins: pinmux_i2c0_pins { ++ pinctrl-single,pins = < ++ 0x188 0x70 /* i2c0_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */ ++ 0x18c 0x70 /* i2c0_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */ ++ >; ++ }; ++ i2c2_pins: pinmux_i2c2_pins { ++ pinctrl-single,pins = < ++ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */ ++ 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */ ++ >; ++ }; + }; + + ocp { +@@ -131,7 +143,39 @@ + reg = <0x24>; + }; + ++ baseboard_eeprom: baseboard_eeprom@50 { ++ compatible = "at,24c256"; ++ reg = <0x50>; ++ }; + }; ++ ++ i2c2: i2c@4819c000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++ status = "okay"; ++ clock-frequency = <100000>; ++ ++ cape_eeprom0: cape_eeprom0@54 { ++ compatible = "at,24c256"; ++ reg = <0x54>; ++ }; ++ ++ cape_eeprom1: cape_eeprom1@55 { ++ compatible = "at,24c256"; ++ reg = <0x55>; ++ }; ++ ++ cape_eeprom2: cape_eeprom2@56 { ++ compatible = "at,24c256"; ++ reg = <0x56>; ++ }; ++ ++ cape_eeprom3: cape_eeprom3@57 { ++ compatible = "at,24c256"; ++ reg = <0x57>; ++ }; ++ }; ++ + }; + + leds { +diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts +index 75a924d..9e453b6 100644 +--- a/arch/arm/boot/dts/am335x-boneblack.dts ++++ b/arch/arm/boot/dts/am335x-boneblack.dts +@@ -140,6 +140,19 @@ + 0x50 (PIN_OUTPUT_PULLUP | MUX_MODE7) /* gpmc_a4.gpio1_20 */ + >; + }; ++ ++ i2c0_pins: pinmux_i2c0_pins { ++ pinctrl-single,pins = < ++ 0x188 0x70 /* i2c0_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */ ++ 0x18c 0x70 /* i2c0_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE0 */ ++ >; ++ }; ++ i2c2_pins: pinmux_i2c2_pins { ++ pinctrl-single,pins = < ++ 0x178 0x73 /* uart1_ctsn.i2c2_sda, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */ ++ 0x17c 0x73 /* uart1_rtsn.i2c2_scl, SLEWCTRL_SLOW | INPUT_PULLUP | MODE3 */ ++ >; ++ }; + }; + + ocp { +@@ -161,6 +174,37 @@ + reg = <0x24>; + }; + ++ baseboard_eeprom: baseboard_eeprom@50 { ++ compatible = "at,24c256"; ++ reg = <0x50>; ++ }; ++ }; ++ ++ i2c2: i2c@4819c000 { ++ pinctrl-names = "default"; ++ pinctrl-0 = <&i2c2_pins>; ++ status = "okay"; ++ clock-frequency = <100000>; ++ ++ cape_eeprom0: cape_eeprom0@54 { ++ compatible = "at,24c256"; ++ reg = <0x54>; ++ }; ++ ++ cape_eeprom1: cape_eeprom1@55 { ++ compatible = "at,24c256"; ++ reg = <0x55>; ++ }; ++ ++ cape_eeprom2: cape_eeprom2@56 { ++ compatible = "at,24c256"; ++ reg = <0x56>; ++ }; ++ ++ cape_eeprom3: cape_eeprom3@57 { ++ compatible = "at,24c256"; ++ reg = <0x57>; ++ }; + }; + }; + +-- +1.8.2.1 + diff --git a/0002-omap_hsmmc-Add-reset-gpio.patch b/0002-omap_hsmmc-Add-reset-gpio.patch new file mode 100644 index 000000000..ea686e78e --- /dev/null +++ b/0002-omap_hsmmc-Add-reset-gpio.patch @@ -0,0 +1,138 @@ +From 364d4535955f21a8ce13e969aedde946a2d566b8 Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou <panto@antoniou-consulting.com> +Date: Fri, 30 Nov 2012 12:18:16 +0200 +Subject: [PATCH 2/2] omap_hsmmc: Add reset gpio + +Add a gpio property for controlling reset of the mmc device. +eMMC on the beaglebone black requires it. + +Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com> +--- + drivers/mmc/host/omap_hsmmc.c | 40 +++++++++++++++++++++++++++++++++- + include/linux/platform_data/mmc-omap.h | 3 +++ + 2 files changed, 42 insertions(+), 1 deletion(-) + +diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c +index 8ab4a93..1fe7469 100644 +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -40,6 +40,8 @@ + #include <linux/pinctrl/consumer.h> + #include <linux/pm_runtime.h> + #include <linux/platform_data/mmc-omap.h> ++#include <linux/pinctrl/consumer.h> ++#include <linux/err.h> + + /* OMAP HSMMC Host Controller Registers */ + #define OMAP_HSMMC_SYSSTATUS 0x0014 +@@ -396,6 +398,7 @@ static inline int omap_hsmmc_have_reg(void) + static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) + { + int ret; ++ unsigned long flags; + + if (gpio_is_valid(pdata->slots[0].switch_pin)) { + if (pdata->slots[0].cover) +@@ -425,6 +428,24 @@ static int omap_hsmmc_gpio_init(struct omap_mmc_platform_data *pdata) + } else + pdata->slots[0].gpio_wp = -EINVAL; + ++ if (gpio_is_valid(pdata->slots[0].gpio_reset)) { ++ flags = pdata->slots[0].gpio_reset_active_low ? ++ GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH; ++ ret = gpio_request_one(pdata->slots[0].gpio_reset, flags, ++ "mmc_reset"); ++ if (ret) ++ goto err_free_wp; ++ ++ /* hold reset */ ++ udelay(pdata->slots[0].gpio_reset_hold_us); ++ ++ gpio_set_value(pdata->slots[0].gpio_reset, ++ !pdata->slots[0].gpio_reset_active_low); ++ ++ } else ++ pdata->slots[0].gpio_reset = -EINVAL; ++ ++ + return 0; + + err_free_wp: +@@ -438,6 +459,8 @@ err_free_sp: + + static void omap_hsmmc_gpio_free(struct omap_mmc_platform_data *pdata) + { ++ if (gpio_is_valid(pdata->slots[0].gpio_reset)) ++ gpio_free(pdata->slots[0].gpio_reset); + if (gpio_is_valid(pdata->slots[0].gpio_wp)) + gpio_free(pdata->slots[0].gpio_wp); + if (gpio_is_valid(pdata->slots[0].switch_pin)) +@@ -792,7 +815,7 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, + * ac, bc, adtc, bcr. Only commands ending an open ended transfer need + * a val of 0x3, rest 0x0. + */ +- if (cmd == host->mrq->stop) ++ if (host->mrq && cmd == host->mrq->stop) + cmdtype = 0x3; + + cmdreg = (cmd->opcode << 24) | (resptype << 16) | (cmdtype << 22); +@@ -835,6 +858,8 @@ static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_req + int completed; + unsigned long flags; + ++ BUG_ON(mrq == NULL); ++ + spin_lock_irqsave(&host->irq_lock, flags); + + host->req_flags &= ~RQF_REQ_IN_PROGRESS; +@@ -1775,6 +1800,7 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) + struct device_node *np = dev->of_node; + u32 bus_width, max_freq; + int cd_gpio, wp_gpio; ++ enum of_gpio_flags reset_flags; + + cd_gpio = of_get_named_gpio(np, "cd-gpios", 0); + wp_gpio = of_get_named_gpio(np, "wp-gpios", 0); +@@ -1792,6 +1818,14 @@ static struct omap_mmc_platform_data *of_get_hsmmc_pdata(struct device *dev) + pdata->nr_slots = 1; + pdata->slots[0].switch_pin = cd_gpio; + pdata->slots[0].gpio_wp = wp_gpio; ++ reset_flags = 0; ++ pdata->slots[0].gpio_reset = of_get_named_gpio_flags(np, ++ "reset-gpios", 0, &reset_flags); ++ pdata->slots[0].gpio_reset_active_low = ++ (reset_flags & OF_GPIO_ACTIVE_LOW) != 0; ++ pdata->slots[0].gpio_reset_hold_us = 100; /* default */ ++ of_property_read_u32(np, "reset-gpio-hold-us", ++ &pdata->slots[0].gpio_reset_hold_us); + + if (of_find_property(np, "ti,non-removable", NULL)) { + pdata->slots[0].nonremovable = true; +@@ -1858,6 +1892,10 @@ static int omap_hsmmc_probe(struct platform_device *pdev) + return -ENXIO; + } + ++ pinctrl = devm_pinctrl_get_select_default(&pdev->dev); ++ if (IS_ERR(pinctrl)) ++ dev_warn(&pdev->dev, "unable to select pin group\n"); ++ + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + irq = platform_get_irq(pdev, 0); + if (res == NULL || irq < 0) +diff --git a/include/linux/platform_data/mmc-omap.h b/include/linux/platform_data/mmc-omap.h +index 2bf1b30..d548994 100644 +--- a/include/linux/platform_data/mmc-omap.h ++++ b/include/linux/platform_data/mmc-omap.h +@@ -115,6 +115,9 @@ struct omap_mmc_platform_data { + + int switch_pin; /* gpio (card detect) */ + int gpio_wp; /* gpio (write protect) */ ++ int gpio_reset; /* gpio (reset) */ ++ int gpio_reset_active_low; /* 1 if reset is active low */ ++ u32 gpio_reset_hold_us; /* time to hold in us */ + + int (*set_bus_mode)(struct device *dev, int slot, int bus_mode); + int (*set_power)(struct device *dev, int slot, +-- +1.8.2.1 + diff --git a/0003-dmaengine-add-dma_get_slave_sg_limits.patch b/0003-dmaengine-add-dma_get_slave_sg_limits.patch new file mode 100644 index 000000000..61bcdb36e --- /dev/null +++ b/0003-dmaengine-add-dma_get_slave_sg_limits.patch @@ -0,0 +1,94 @@ +From c8ff7a795bf883c61b7d7f506b0bb7796db6cb01 Mon Sep 17 00:00:00 2001 +From: Matt Porter <mporter@ti.com> +Date: Wed, 6 Mar 2013 19:56:05 +0000 +Subject: [PATCH 03/13] dmaengine: add dma_get_slave_sg_limits() + +Add a dmaengine API to retrieve slave SG transfer limits. + +The API is optionally implemented by dmaengine drivers and when +unimplemented will return a NULL pointer. A client driver using +this API provides the required dma channel, address width, and +burst size of the transfer. dma_get_slave_sg_limits() returns an +SG limits structure with the maximum number and size of SG segments +that the given channel can handle. + +Signed-off-by: Matt Porter <mporter@ti.com> +Signed-off-by: Joel A Fernandes <joelagnel@ti.com> +--- + include/linux/dmaengine.h | 39 +++++++++++++++++++++++++++++++++++++++ + 1 file changed, 39 insertions(+) + +diff --git a/include/linux/dmaengine.h b/include/linux/dmaengine.h +index cb286b1..d71fe5d 100644 +--- a/include/linux/dmaengine.h ++++ b/include/linux/dmaengine.h +@@ -370,6 +370,18 @@ struct dma_slave_config { + unsigned int slave_id; + }; + ++/* struct dma_slave_sg_limits - expose SG transfer limits of a channel ++ * ++ * @max_seg_nr: maximum number of SG segments supported on a SG/SLAVE ++ * channel (0 for no maximum or not a SG/SLAVE channel) ++ * @max_seg_len: maximum length of SG segments supported on a SG/SLAVE ++ * channel (0 for no maximum or not a SG/SLAVE channel) ++ */ ++struct dma_slave_sg_limits { ++ u32 max_seg_nr; ++ u32 max_seg_len; ++}; ++ + static inline const char *dma_chan_name(struct dma_chan *chan) + { + return dev_name(&chan->dev->device); +@@ -532,6 +544,7 @@ struct dma_tx_state { + * struct with auxiliary transfer status information, otherwise the call + * will just return a simple status code + * @device_issue_pending: push pending transactions to hardware ++ * @device_slave_sg_limits: return the slave SG capabilities + */ + struct dma_device { + +@@ -597,6 +610,9 @@ struct dma_device { + dma_cookie_t cookie, + struct dma_tx_state *txstate); + void (*device_issue_pending)(struct dma_chan *chan); ++ struct dma_slave_sg_limits *(*device_slave_sg_limits)( ++ struct dma_chan *chan, enum dma_slave_buswidth addr_width, ++ u32 maxburst); + }; + + static inline int dmaengine_device_control(struct dma_chan *chan, +@@ -958,6 +974,29 @@ dma_set_tx_state(struct dma_tx_state *st, dma_cookie_t last, dma_cookie_t used, + } + } + ++/** ++ * dma_get_slave_sg_limits - get DMAC SG transfer capabilities ++ * @chan: target DMA channel ++ * @addr_width: address width of the DMA transfer ++ * @maxburst: maximum DMA transfer burst size ++ * ++ * Get SG transfer capabilities for a specified channel. If the dmaengine ++ * driver does not implement SG transfer capabilities then NULL is ++ * returned. ++ */ ++static inline struct dma_slave_sg_limits ++*dma_get_slave_sg_limits(struct dma_chan *chan, ++ enum dma_slave_buswidth addr_width, ++ u32 maxburst) ++{ ++ if (chan->device->device_slave_sg_limits) ++ return chan->device->device_slave_sg_limits(chan, ++ addr_width, ++ maxburst); ++ ++ return NULL; ++} ++ + enum dma_status dma_sync_wait(struct dma_chan *chan, dma_cookie_t cookie); + #ifdef CONFIG_DMA_ENGINE + enum dma_status dma_wait_for_async_tx(struct dma_async_tx_descriptor *tx); +-- +1.8.2.1 + diff --git a/0004-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch b/0004-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch new file mode 100644 index 000000000..d6f98e16d --- /dev/null +++ b/0004-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch @@ -0,0 +1,48 @@ +From e1e06db0fb0ae8cfc2b3dc9c08b3237a050e2789 Mon Sep 17 00:00:00 2001 +From: Matt Porter <mporter@ti.com> +Date: Thu, 7 Mar 2013 04:16:38 +0000 +Subject: [PATCH 04/13] mmc: omap_hsmmc: set max_segs based on dma engine + limits + +The EDMA DMAC has a hardware limitation that prevents supporting +scatter gather lists with any number of segments. The DMA Engine +API reports the maximum number of segments a channel can support +via the optional dma_get_slave_sg_limits() API. If the max_nr_segs +limit is present, the value is used to configure mmc->max_segs +appropriately. + +Signed-off-by: Matt Porter <mporter@ti.com> +Acked-by: Tony Lindgren <tony@atomide.com> +--- + drivers/mmc/host/omap_hsmmc.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c +index 1865321..1f9ff97 100644 +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -1776,6 +1776,7 @@ static int omap_hsmmc_probe(struct platform_device *pdev) + const struct of_device_id *match; + dma_cap_mask_t mask; + unsigned tx_req, rx_req; ++ struct dma_slave_sg_limits *dma_sg_limits; + struct pinctrl *pinctrl; + + match = of_match_device(of_match_ptr(omap_mmc_of_match), &pdev->dev); +@@ -1952,6 +1953,13 @@ static int omap_hsmmc_probe(struct platform_device *pdev) + goto err_irq; + } + ++ /* Some DMA Engines only handle a limited number of SG segments */ ++ dma_sg_limits = dma_get_slave_sg_limits(host->rx_chan, ++ DMA_SLAVE_BUSWIDTH_4_BYTES, ++ mmc->max_blk_size / 4); ++ if (dma_sg_limits && dma_sg_limits->max_seg_nr) ++ mmc->max_segs = dma_sg_limits->max_seg_nr; ++ + /* Request IRQ for MMC operations */ + ret = request_irq(host->irq, omap_hsmmc_irq, 0, + mmc_hostname(mmc), host); +-- +1.8.2.1 + diff --git a/0005-da8xx-config-Enable-MMC-and-FS-options.patch b/0005-da8xx-config-Enable-MMC-and-FS-options.patch new file mode 100644 index 000000000..d94e500d0 --- /dev/null +++ b/0005-da8xx-config-Enable-MMC-and-FS-options.patch @@ -0,0 +1,33 @@ +From bb43e18a5c1626fadb8674b287224905358751be Mon Sep 17 00:00:00 2001 +From: Joel A Fernandes <agnel.joel@gmail.com> +Date: Thu, 20 Jun 2013 15:07:40 -0500 +Subject: [PATCH 05/13] da8xx: config: Enable MMC and FS options + +Required to get OMAP-L1 EVM access MMC and mount rootfs + +Signed-off-by: Joel A Fernandes <joelagnel@ti.com> +--- + arch/arm/configs/da8xx_omapl_defconfig | 3 +++ + 1 file changed, 3 insertions(+) + +diff --git a/arch/arm/configs/da8xx_omapl_defconfig b/arch/arm/configs/da8xx_omapl_defconfig +index 1571bea..9b50e6c 100644 +--- a/arch/arm/configs/da8xx_omapl_defconfig ++++ b/arch/arm/configs/da8xx_omapl_defconfig +@@ -106,6 +106,7 @@ CONFIG_DMADEVICES=y + CONFIG_TI_EDMA=y + CONFIG_EXT2_FS=y + CONFIG_EXT3_FS=y ++CONFIG_EXT4_FS=y + CONFIG_XFS_FS=m + CONFIG_INOTIFY=y + CONFIG_AUTOFS4_FS=m +@@ -137,3 +138,5 @@ CONFIG_DEBUG_ERRORS=y + # CONFIG_CRYPTO_HW is not set + CONFIG_CRC_CCITT=m + CONFIG_CRC_T10DIF=m ++CONFIG_MMC=y ++CONFIG_MMC_DAVINCI=y +-- +1.8.2.1 + diff --git a/0006-ARM-dts-add-AM33XX-EDMA-support.patch b/0006-ARM-dts-add-AM33XX-EDMA-support.patch new file mode 100644 index 000000000..c5c4266bc --- /dev/null +++ b/0006-ARM-dts-add-AM33XX-EDMA-support.patch @@ -0,0 +1,44 @@ +From b9e4382015c702fbc1be1753074fce93a0965ac0 Mon Sep 17 00:00:00 2001 +From: Matt Porter <mdp@ti.com> +Date: Mon, 27 May 2013 21:52:12 -0500 +Subject: [PATCH 06/13] ARM: dts: add AM33XX EDMA support + +Adds AM33XX EDMA support to the am33xx.dtsi as documented in +Documentation/devicetree/bindings/dma/ti-edma.txt + +Joel: Drop DT entries that are non-hardware-description for now as discussed in [1] + +[1] https://patchwork.kernel.org/patch/2226761/ + +Signed-off-by: Matt Porter <mporter@ti.com> +Signed-off-by: Joel A Fernandes <joelagnel@ti.com> +--- + arch/arm/boot/dts/am33xx.dtsi | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi +index 38b446b..784f774 100644 +--- a/arch/arm/boot/dts/am33xx.dtsi ++++ b/arch/arm/boot/dts/am33xx.dtsi +@@ -96,6 +96,18 @@ + reg = <0x48200000 0x1000>; + }; + ++ edma: edma@49000000 { ++ compatible = "ti,edma3"; ++ ti,hwmods = "tpcc", "tptc0", "tptc1", "tptc2"; ++ reg = <0x49000000 0x10000>, ++ <0x44e10f90 0x10>; ++ interrupts = <12 13 14>; ++ #dma-cells = <1>; ++ dma-channels = <64>; ++ ti,edma-regions = <4>; ++ ti,edma-slots = <256>; ++ }; ++ + gpio0: gpio@44e07000 { + compatible = "ti,omap4-gpio"; + ti,hwmods = "gpio1"; +-- +1.8.2.1 + diff --git a/0007-ARM-dts-add-AM33XX-SPI-DMA-support.patch b/0007-ARM-dts-add-AM33XX-SPI-DMA-support.patch new file mode 100644 index 000000000..6716bfbc2 --- /dev/null +++ b/0007-ARM-dts-add-AM33XX-SPI-DMA-support.patch @@ -0,0 +1,44 @@ +From 16649496dc8c4334ab72a0a5a407953e3dcf4c83 Mon Sep 17 00:00:00 2001 +From: Matt Porter <mporter@ti.com> +Date: Thu, 10 Jan 2013 19:09:50 -0500 +Subject: [PATCH 07/13] ARM: dts: add AM33XX SPI DMA support + +Adds DMA resources to the AM33XX SPI nodes. + +Signed-off-by: Matt Porter <mporter@ti.com> +Signed-off-by: Joel A Fernandes <joelagnel@ti.com> +--- + arch/arm/boot/dts/am33xx.dtsi | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi +index 784f774..0fdb949 100644 +--- a/arch/arm/boot/dts/am33xx.dtsi ++++ b/arch/arm/boot/dts/am33xx.dtsi +@@ -331,6 +331,11 @@ + interrupts = <65>; + ti,spi-num-cs = <2>; + ti,hwmods = "spi0"; ++ dmas = <&edma 16 ++ &edma 17 ++ &edma 18 ++ &edma 19>; ++ dma-names = "tx0", "rx0", "tx1", "rx1"; + status = "disabled"; + }; + +@@ -342,6 +347,11 @@ + interrupts = <125>; + ti,spi-num-cs = <2>; + ti,hwmods = "spi1"; ++ dmas = <&edma 42 ++ &edma 43 ++ &edma 44 ++ &edma 45>; ++ dma-names = "tx0", "rx0", "tx1", "rx1"; + status = "disabled"; + }; + +-- +1.8.2.1 + diff --git a/0008-ARM-dts-add-AM33XX-MMC-support.patch b/0008-ARM-dts-add-AM33XX-MMC-support.patch new file mode 100644 index 000000000..23c2244db --- /dev/null +++ b/0008-ARM-dts-add-AM33XX-MMC-support.patch @@ -0,0 +1,191 @@ +From 1aa00b457ea36f6eeb78b66be076e16a2d3fafe0 Mon Sep 17 00:00:00 2001 +From: Matt Porter <mporter@ti.com> +Date: Thu, 7 Mar 2013 04:16:39 +0000 +Subject: [PATCH 08/13] ARM: dts: add AM33XX MMC support + +Adds AM33XX MMC support for am335x-bone, am335x-evm, and +am335x-evmsk. + +Also added is the DMA binding definitions based on the generic +DMA request binding. + +Changes to DTS: +Interrupt and reg added by: Joel Fernandes <joelf@ti.com> +Compatible added by Balaji TK <balajitk@ti.com> +ti,needs-special-hs-handling added by Gururaja Hebbar <gururaja.hebbar@ti.com> + +Signed-off-by: Matt Porter <mporter@ti.com> +Acked-by: Tony Lindgren <tony@atomide.com> +Signed-off-by: Joel Fernandes <joelf@ti.com> + +Conflicts: + arch/arm/boot/dts/am335x-evmsk.dts +--- + .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 26 ++++++++++++++- + arch/arm/boot/dts/am335x-bone.dts | 7 ++++ + arch/arm/boot/dts/am335x-evm.dts | 7 ++++ + arch/arm/boot/dts/am335x-evmsk.dts | 7 ++++ + arch/arm/boot/dts/am33xx.dtsi | 38 ++++++++++++++++++++++ + 5 files changed, 84 insertions(+), 1 deletion(-) + +diff --git a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +index ed271fc..8c8908a 100644 +--- a/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt ++++ b/Documentation/devicetree/bindings/mmc/ti-omap-hsmmc.txt +@@ -20,8 +20,29 @@ ti,dual-volt: boolean, supports dual voltage cards + ti,non-removable: non-removable slot (like eMMC) + ti,needs-special-reset: Requires a special softreset sequence + ti,needs-special-hs-handling: HSMMC IP needs special setting for handling High Speed ++dmas: List of DMA specifiers with the controller specific format ++as described in the generic DMA client binding. A tx and rx ++specifier is required. ++dma-names: List of DMA request names. These strings correspond ++1:1 with the DMA specifiers listed in dmas. The string naming is ++to be "rx" and "tx" for RX and TX DMA requests, respectively. ++ ++Examples: ++ ++[hwmod populated DMA resources] ++ ++ mmc1: mmc@0x4809c000 { ++ compatible = "ti,omap4-hsmmc"; ++ reg = <0x4809c000 0x400>; ++ ti,hwmods = "mmc1"; ++ ti,dual-volt; ++ bus-width = <4>; ++ vmmc-supply = <&vmmc>; /* phandle to regulator node */ ++ ti,non-removable; ++ }; ++ ++[generic DMA request binding] + +-Example: + mmc1: mmc@0x4809c000 { + compatible = "ti,omap4-hsmmc"; + reg = <0x4809c000 0x400>; +@@ -30,4 +51,7 @@ Example: + bus-width = <4>; + vmmc-supply = <&vmmc>; /* phandle to regulator node */ + ti,non-removable; ++ dmas = <&edma 24 ++ &edma 25>; ++ dma-names = "tx", "rx"; + }; +diff --git a/arch/arm/boot/dts/am335x-bone.dts b/arch/arm/boot/dts/am335x-bone.dts +index 444b4ed..b8debea 100644 +--- a/arch/arm/boot/dts/am335x-bone.dts ++++ b/arch/arm/boot/dts/am335x-bone.dts +@@ -203,6 +203,8 @@ + }; + + ldo3_reg: regulator@5 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + +@@ -234,3 +236,8 @@ + pinctrl-0 = <&davinci_mdio_default>; + pinctrl-1 = <&davinci_mdio_sleep>; + }; ++ ++&mmc1 { ++ status = "okay"; ++ vmmc-supply = <&ldo3_reg>; ++}; +diff --git a/arch/arm/boot/dts/am335x-evm.dts b/arch/arm/boot/dts/am335x-evm.dts +index 3aee1a4..44e69d9 100644 +--- a/arch/arm/boot/dts/am335x-evm.dts ++++ b/arch/arm/boot/dts/am335x-evm.dts +@@ -448,6 +448,8 @@ + }; + + vmmc_reg: regulator@12 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +@@ -488,3 +490,8 @@ + ti,adc-channels = <4 5 6 7>; + }; + }; ++ ++&mmc1 { ++ status = "okay"; ++ vmmc-supply = <&vmmc_reg>; ++}; +diff --git a/arch/arm/boot/dts/am335x-evmsk.dts b/arch/arm/boot/dts/am335x-evmsk.dts +index 0c8ad17..4e355d6 100644 +--- a/arch/arm/boot/dts/am335x-evmsk.dts ++++ b/arch/arm/boot/dts/am335x-evmsk.dts +@@ -376,6 +376,8 @@ + }; + + vmmc_reg: regulator@12 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + }; +@@ -402,3 +404,8 @@ + phy_id = <&davinci_mdio>, <1>; + phy-mode = "rgmii-txid"; + }; ++ ++&mmc1 { ++ status = "okay"; ++ vmmc-supply = <&vmmc_reg>; ++}; +diff --git a/arch/arm/boot/dts/am33xx.dtsi b/arch/arm/boot/dts/am33xx.dtsi +index 0fdb949..969c81b 100644 +--- a/arch/arm/boot/dts/am33xx.dtsi ++++ b/arch/arm/boot/dts/am33xx.dtsi +@@ -236,6 +236,44 @@ + status = "disabled"; + }; + ++ mmc1: mmc@48060000 { ++ compatible = "ti,omap4-hsmmc"; ++ ti,hwmods = "mmc1"; ++ ti,dual-volt; ++ ti,needs-special-reset; ++ ti,needs-special-hs-handling; ++ dmas = <&edma 24 ++ &edma 25>; ++ dma-names = "tx", "rx"; ++ interrupts = <64>; ++ interrupt-parent = <&intc>; ++ reg = <0x48060000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ mmc2: mmc@481d8000 { ++ compatible = "ti,omap4-hsmmc"; ++ ti,hwmods = "mmc2"; ++ ti,needs-special-reset; ++ dmas = <&edma 2 ++ &edma 3>; ++ dma-names = "tx", "rx"; ++ interrupts = <28>; ++ interrupt-parent = <&intc>; ++ reg = <0x481d8000 0x1000>; ++ status = "disabled"; ++ }; ++ ++ mmc3: mmc@47810000 { ++ compatible = "ti,omap4-hsmmc"; ++ ti,hwmods = "mmc3"; ++ ti,needs-special-reset; ++ interrupts = <29>; ++ interrupt-parent = <&intc>; ++ reg = <0x47810000 0x1000>; ++ status = "disabled"; ++ }; ++ + wdt2: wdt@44e35000 { + compatible = "ti,omap3-wdt"; + ti,hwmods = "wd_timer2"; +-- +1.8.2.1 + diff --git a/0009-DMA-EDMA-Split-out-PaRAM-set-calculations-into-its-o.patch b/0009-DMA-EDMA-Split-out-PaRAM-set-calculations-into-its-o.patch new file mode 100644 index 000000000..8bef684a5 --- /dev/null +++ b/0009-DMA-EDMA-Split-out-PaRAM-set-calculations-into-its-o.patch @@ -0,0 +1,271 @@ +From 14c120151d8ae2e335dd8728c88d6cd1a52863c8 Mon Sep 17 00:00:00 2001 +From: Joel Fernandes <joelf@ti.com> +Date: Tue, 25 Jun 2013 09:35:33 -0500 +Subject: [PATCH 09/13] DMA: EDMA: Split out PaRAM set calculations into its + own function + +PaRAM set calculation is abstracted into its own function to +enable better reuse for other DMA cases. Currently it only +implements the Slave case. + +This provides a much cleaner abstraction to the internals of the +PaRAM set. However, any PaRAM attributes that are not common to +all DMA types must be set separately. This function only calculates +the most-common attributes. + +Also added comments clarifying A-sync case calculations. + +Signed-off-by: Joel Fernandes <joelf@ti.com> +--- + drivers/dma/edma.c | 197 ++++++++++++++++++++++++++++++++++------------------- + 1 file changed, 126 insertions(+), 71 deletions(-) + +diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c +index e008ed2..87b7e2b 100644 +--- a/drivers/dma/edma.c ++++ b/drivers/dma/edma.c +@@ -211,6 +211,116 @@ static int edma_control(struct dma_chan *chan, enum dma_ctrl_cmd cmd, + return ret; + } + ++/* ++ * A clean implementation of a PaRAM set configuration abstraction ++ * @chan: Channel who's PaRAM set we're configuring ++ * @src_addr: Source address of the DMA ++ * @dst_addr: Destination address of the DMA ++ * @burst: In units of dev_width, how much to send ++ * @dev_width: How much is the dev_width ++ * @dma_length: Total length of the DMA transfer ++ * @direction: Direction of the transfer ++ */ ++static int edma_config_pset(struct dma_chan *chan, struct edmacc_param *pset, ++ dma_addr_t src_addr, dma_addr_t dst_addr, u32 burst, ++ enum dma_slave_buswidth dev_width, unsigned int dma_length, ++ enum dma_transfer_direction direction) ++{ ++ struct edma_chan *echan = to_edma_chan(chan); ++ struct device *dev = chan->device->dev; ++ int acnt, bcnt, ccnt, cidx; ++ int src_bidx, dst_bidx, src_cidx, dst_cidx; ++ int absync; ++ ++ acnt = dev_width; ++ /* ++ * If the maxburst is equal to the fifo width, use ++ * A-synced transfers. This allows for large contiguous ++ * buffer transfers using only one PaRAM set. ++ */ ++ if (burst == 1) { ++ absync = false; ++ /* ++ * For the A-sync case, bcnt and ccnt are the remainder ++ * and quotient respectively of the division of: ++ * (dma_length / acnt) by (SZ_64K -1). This is so ++ * that in case bcnt over flows, we have ccnt to use. ++ * Note: In A-sync tranfer only, bcntrld is used, but it ++ * only applies for sg_dma_len(sg) >= SZ_64K. ++ * In this case, the best way adopted is- bccnt for the ++ * first frame will be the remainder below. Then for ++ * every successive frame, bcnt will be SZ_64K-1. This ++ * is assured as bcntrld = 0xffff in end of function. ++ */ ++ ccnt = dma_length / acnt / (SZ_64K - 1); ++ bcnt = dma_length / acnt - ccnt * (SZ_64K - 1); ++ /* ++ * If bcnt is non-zero, we have a remainder and hence an ++ * extra frame to transfer, so increment ccnt. ++ */ ++ if (bcnt) ++ ccnt++; ++ else ++ bcnt = SZ_64K - 1; ++ cidx = acnt; ++ /* ++ * If maxburst is greater than the fifo address_width, ++ * use AB-synced transfers where A count is the fifo ++ * address_width and B count is the maxburst. In this ++ * case, we are limited to transfers of C count frames ++ * of (address_width * maxburst) where C count is limited ++ * to SZ_64K-1. This places an upper bound on the length ++ * of an SG segment that can be handled. ++ */ ++ } else { ++ absync = true; ++ bcnt = burst; ++ ccnt = dma_length / (acnt * bcnt); ++ if (ccnt > (SZ_64K - 1)) { ++ dev_err(dev, "Exceeded max SG segment size\n"); ++ return -EINVAL; ++ } ++ cidx = acnt * bcnt; ++ } ++ ++ if (direction == DMA_MEM_TO_DEV) { ++ src_bidx = acnt; ++ src_cidx = cidx; ++ dst_bidx = 0; ++ dst_cidx = 0; ++ } else if (direction == DMA_DEV_TO_MEM) { ++ src_bidx = 0; ++ src_cidx = 0; ++ dst_bidx = acnt; ++ dst_cidx = cidx; ++ } else { ++ dev_err(dev, "%s: direction not implemented yet\n", __func__); ++ return -EINVAL; ++ } ++ ++ pset->opt = EDMA_TCC(EDMA_CHAN_SLOT(echan->ch_num)); ++ /* Configure A or AB synchronized transfers */ ++ if (absync) ++ pset->opt |= SYNCDIM; ++ ++ pset->src = src_addr; ++ pset->dst = dst_addr; ++ ++ pset->src_dst_bidx = (dst_bidx << 16) | src_bidx; ++ pset->src_dst_cidx = (dst_cidx << 16) | src_cidx; ++ ++ pset->a_b_cnt = bcnt << 16 | acnt; ++ pset->ccnt = ccnt; ++ /* ++ * Only time when (bcntrld) auto reload is required is for ++ * A-sync case, and in this case, a requirement of reload value ++ * of SZ_64K-1 only is assured. 'link' is initially set to NULL ++ * and then later will be populated by edma_execute. ++ */ ++ pset->link_bcntrld = 0xffffffff; ++ return absync; ++} ++ + static struct dma_async_tx_descriptor *edma_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction, +@@ -219,23 +329,21 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( + struct edma_chan *echan = to_edma_chan(chan); + struct device *dev = chan->device->dev; + struct edma_desc *edesc; +- dma_addr_t dev_addr; ++ dma_addr_t src_addr = 0, dst_addr = 0; + enum dma_slave_buswidth dev_width; + u32 burst; + struct scatterlist *sg; +- int i; +- int acnt, bcnt, ccnt, src, dst, cidx; +- int src_bidx, dst_bidx, src_cidx, dst_cidx; ++ int i, ret; + + if (unlikely(!echan || !sgl || !sg_len)) + return NULL; + + if (direction == DMA_DEV_TO_MEM) { +- dev_addr = echan->cfg.src_addr; ++ src_addr = echan->cfg.src_addr; + dev_width = echan->cfg.src_addr_width; + burst = echan->cfg.src_maxburst; + } else if (direction == DMA_MEM_TO_DEV) { +- dev_addr = echan->cfg.dst_addr; ++ dst_addr = echan->cfg.dst_addr; + dev_width = echan->cfg.dst_addr_width; + burst = echan->cfg.dst_maxburst; + } else { +@@ -263,7 +371,14 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( + + edesc->pset_nr = sg_len; + ++ /* Configure PaRAM sets for each SG */ + for_each_sg(sgl, sg, sg_len, i) { ++ /* Get address for each SG */ ++ if (direction == DMA_DEV_TO_MEM) ++ dst_addr = sg_dma_address(sg); ++ else ++ src_addr = sg_dma_address(sg); ++ + /* Allocate a PaRAM slot, if needed */ + if (echan->slot[i] < 0) { + echan->slot[i] = +@@ -275,76 +390,16 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( + } + } + +- acnt = dev_width; ++ ret = edma_config_pset(chan, &edesc->pset[i], src_addr, dst_addr, ++ burst, dev_width, sg_dma_len(sg), direction); ++ if(ret < 0) ++ return NULL; + +- /* +- * If the maxburst is equal to the fifo width, use +- * A-synced transfers. This allows for large contiguous +- * buffer transfers using only one PaRAM set. +- */ +- if (burst == 1) { +- edesc->absync = false; +- ccnt = sg_dma_len(sg) / acnt / (SZ_64K - 1); +- bcnt = sg_dma_len(sg) / acnt - ccnt * (SZ_64K - 1); +- if (bcnt) +- ccnt++; +- else +- bcnt = SZ_64K - 1; +- cidx = acnt; +- /* +- * If maxburst is greater than the fifo address_width, +- * use AB-synced transfers where A count is the fifo +- * address_width and B count is the maxburst. In this +- * case, we are limited to transfers of C count frames +- * of (address_width * maxburst) where C count is limited +- * to SZ_64K-1. This places an upper bound on the length +- * of an SG segment that can be handled. +- */ +- } else { +- edesc->absync = true; +- bcnt = burst; +- ccnt = sg_dma_len(sg) / (acnt * bcnt); +- if (ccnt > (SZ_64K - 1)) { +- dev_err(dev, "Exceeded max SG segment size\n"); +- return NULL; +- } +- cidx = acnt * bcnt; +- } ++ edesc->absync = ret; + +- if (direction == DMA_MEM_TO_DEV) { +- src = sg_dma_address(sg); +- dst = dev_addr; +- src_bidx = acnt; +- src_cidx = cidx; +- dst_bidx = 0; +- dst_cidx = 0; +- } else { +- src = dev_addr; +- dst = sg_dma_address(sg); +- src_bidx = 0; +- src_cidx = 0; +- dst_bidx = acnt; +- dst_cidx = cidx; +- } +- +- edesc->pset[i].opt = EDMA_TCC(EDMA_CHAN_SLOT(echan->ch_num)); +- /* Configure A or AB synchronized transfers */ +- if (edesc->absync) +- edesc->pset[i].opt |= SYNCDIM; + /* If this is the last set, enable completion interrupt flag */ + if (i == sg_len - 1) + edesc->pset[i].opt |= TCINTEN; +- +- edesc->pset[i].src = src; +- edesc->pset[i].dst = dst; +- +- edesc->pset[i].src_dst_bidx = (dst_bidx << 16) | src_bidx; +- edesc->pset[i].src_dst_cidx = (dst_cidx << 16) | src_cidx; +- +- edesc->pset[i].a_b_cnt = bcnt << 16 | acnt; +- edesc->pset[i].ccnt = ccnt; +- edesc->pset[i].link_bcntrld = 0xffffffff; +- + } + + return vchan_tx_prep(&echan->vchan, &edesc->vdesc, tx_flags); +-- +1.8.2.1 + diff --git a/0010-DMA-EDMA-Add-support-for-Cyclic-DMA.patch b/0010-DMA-EDMA-Add-support-for-Cyclic-DMA.patch new file mode 100644 index 000000000..4c981943a --- /dev/null +++ b/0010-DMA-EDMA-Add-support-for-Cyclic-DMA.patch @@ -0,0 +1,130 @@ +From caf38f4702a75c7ba13d5d80d902812c5faa8501 Mon Sep 17 00:00:00 2001 +From: Joel Fernandes <joelf@ti.com> +Date: Thu, 27 Jun 2013 20:18:52 -0500 +Subject: [PATCH 10/13] DMA: EDMA: Add support for Cyclic DMA + +Using the PaRAM configuration function that we split for reuse by the +different DMA types, we implement Cyclic DMA support. +For the cyclic case, we pass different configuration paramters to this +function, and add all the Cyclic-specific code separately. +Callbacks are handled transparently as usual by the virt-dma layer. +Linking is handled the same way as the slave SG case. + +Signed-off-by: Joel Fernandes <joelf@ti.com> +--- + drivers/dma/edma.c | 85 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 85 insertions(+) + +diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c +index 87b7e2b..cec9a12 100644 +--- a/drivers/dma/edma.c ++++ b/drivers/dma/edma.c +@@ -321,6 +321,88 @@ static int edma_config_pset(struct dma_chan *chan, struct edmacc_param *pset, + return absync; + } + ++static struct dma_async_tx_descriptor *edma_prep_dma_cyclic( ++ struct dma_chan *chan, dma_addr_t buf_addr, size_t buf_len, ++ size_t period_len, enum dma_transfer_direction direction, unsigned long flags, ++ void *context) ++{ ++ struct edma_chan *echan = to_edma_chan(chan); ++ struct device *dev = chan->device->dev; ++ struct edma_desc *edesc; ++ dma_addr_t src_addr, dst_addr; ++ enum dma_slave_buswidth dev_width; ++ u32 burst; ++ int i, ret, nr_periods; ++ ++ if (unlikely(!echan || !buf_len || !period_len)) ++ return NULL; ++ ++ if (direction == DMA_DEV_TO_MEM) { ++ src_addr = echan->cfg.src_addr; ++ dst_addr = buf_addr; ++ dev_width = echan->cfg.src_addr_width; ++ burst = echan->cfg.src_maxburst; ++ } else if (direction == DMA_MEM_TO_DEV) { ++ src_addr = buf_addr; ++ dst_addr = echan->cfg.dst_addr; ++ dev_width = echan->cfg.dst_addr_width; ++ burst = echan->cfg.dst_maxburst; ++ } else { ++ dev_err(dev, "%s: bad direction?\n", __func__); ++ return NULL; ++ } ++ ++ if (dev_width == DMA_SLAVE_BUSWIDTH_UNDEFINED) { ++ dev_err(dev, "Undefined slave buswidth\n"); ++ return NULL; ++ } ++ ++ if(unlikely(period_len % buf_len)) { ++ dev_err(dev, "Period should be multiple of Buf length\n"); ++ return NULL; ++ } ++ ++ nr_periods = period_len / buf_len; ++ ++ edesc = kzalloc(sizeof(*edesc) + nr_periods * ++ sizeof(edesc->pset[0]), GFP_ATOMIC); ++ if (!edesc) { ++ dev_dbg(dev, "Failed to allocate a descriptor\n"); ++ return NULL; ++ } ++ ++ edesc->pset_nr = nr_periods; ++ ++ for(i = 0; i < nr_periods; i++) { ++ /* Allocate a PaRAM slot, if needed */ ++ if (echan->slot[i] < 0) { ++ echan->slot[i] = ++ edma_alloc_slot(EDMA_CTLR(echan->ch_num), ++ EDMA_SLOT_ANY); ++ if (echan->slot[i] < 0) { ++ dev_err(dev, "Failed to allocate slot\n"); ++ return NULL; ++ } ++ } ++ ++ if (direction == DMA_DEV_TO_MEM) ++ dst_addr += period_len; ++ else ++ src_addr += period_len; ++ ++ ret = edma_config_pset(chan, &edesc->pset[i], src_addr, dst_addr, ++ burst, dev_width, period_len, direction); ++ if(ret < 0) ++ return NULL; ++ ++ edesc->absync = ret; ++ if (i == nr_periods - 1) ++ edesc->pset[i].opt |= TCINTEN; ++ } ++ /* TODO tx_flags (last parameter) needs to be investigated...\n" */ ++ return vchan_tx_prep(&echan->vchan, &edesc->vdesc, 0); ++} ++ + static struct dma_async_tx_descriptor *edma_prep_slave_sg( + struct dma_chan *chan, struct scatterlist *sgl, + unsigned int sg_len, enum dma_transfer_direction direction, +@@ -424,6 +506,8 @@ static void edma_callback(unsigned ch_num, u16 ch_status, void *data) + edesc = echan->edesc; + if (edesc) { + edma_execute(echan); ++ /* Note: that desc->callback must be setup by EDMA users so that ++ the virt-dma layer calls their callback on vchan_cookie_complete() */ + vchan_cookie_complete(&edesc->vdesc); + } + +@@ -605,6 +689,7 @@ static void edma_dma_init(struct edma_cc *ecc, struct dma_device *dma, + struct device *dev) + { + dma->device_prep_slave_sg = edma_prep_slave_sg; ++ dma->device_prep_dma_cyclic = edma_prep_dma_cyclic; + dma->device_alloc_chan_resources = edma_alloc_chan_resources; + dma->device_free_chan_resources = edma_free_chan_resources; + dma->device_issue_pending = edma_issue_pending; +-- +1.8.2.1 + diff --git a/0011-sound-soc-soc-dmaengine-pcm-Add-support-for-new-DMAE.patch b/0011-sound-soc-soc-dmaengine-pcm-Add-support-for-new-DMAE.patch new file mode 100644 index 000000000..f5f7ce88c --- /dev/null +++ b/0011-sound-soc-soc-dmaengine-pcm-Add-support-for-new-DMAE.patch @@ -0,0 +1,60 @@ +From e85ad9182c962bb095beb435e98fde612a4ef88d Mon Sep 17 00:00:00 2001 +From: Joel Fernandes <joelf@ti.com> +Date: Wed, 3 Jul 2013 17:29:44 -0500 +Subject: [PATCH 11/13] sound: soc: soc-dmaengine-pcm: Add support for new + DMAEngine request API + +Formerly these resources were coming HWMOD on OMAP-like SoCs. With the +impending removal of HWMOD data, drivers are being converted to use the +"of-dma" method of requesting DMA channels which from DT and can be obtained +using the dma_request_slave_channel API. Add support to the soc-dmaengine-pcm +helpers so that we can fetch and open channels using this method. + +Signed-off-by: Joel Fernandes <joelf@ti.com> +--- + sound/soc/soc-dmaengine-pcm.c | 22 ++++++++++++++++++++++ + 1 file changed, 22 insertions(+) + +diff --git a/sound/soc/soc-dmaengine-pcm.c b/sound/soc/soc-dmaengine-pcm.c +index aa924d9..461fe4f 100644 +--- a/sound/soc/soc-dmaengine-pcm.c ++++ b/sound/soc/soc-dmaengine-pcm.c +@@ -276,6 +276,16 @@ struct dma_chan *snd_dmaengine_pcm_request_channel(dma_filter_fn filter_fn, + } + EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_channel); + ++struct dma_chan *snd_dmaengine_pcm_request_slave_channel( ++ struct snd_pcm_substream *substream, char *name) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct device *dev = snd_soc_dai_get_drvdata(rtd->cpu_dai); ++ ++ return dma_request_slave_channel(dev, name); ++} ++EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_request_slave_channel); ++ + /** + * snd_dmaengine_pcm_open - Open a dmaengine based PCM substream + * @substream: PCM substream +@@ -334,6 +344,18 @@ int snd_dmaengine_pcm_open_request_chan(struct snd_pcm_substream *substream, + } + EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_chan); + ++int snd_dmaengine_pcm_open_request_slave_chan(struct snd_pcm_substream *substream, char *name) ++{ ++ if(substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { ++ return snd_dmaengine_pcm_open(substream, ++ snd_dmaengine_pcm_request_slave_channel(substream, "tx")); ++ } else { ++ return snd_dmaengine_pcm_open(substream, ++ snd_dmaengine_pcm_request_slave_channel(substream, "rx")); ++ } ++} ++EXPORT_SYMBOL_GPL(snd_dmaengine_pcm_open_request_slave_chan); ++ + /** + * snd_dmaengine_pcm_close - Close a dmaengine based PCM substream + * @substream: PCM substream +-- +1.8.2.1 + diff --git a/0012-mmc-omap_hsmmc-Fix-the-crashes-due-to-the-interrupts.patch b/0012-mmc-omap_hsmmc-Fix-the-crashes-due-to-the-interrupts.patch new file mode 100644 index 000000000..1c83398d0 --- /dev/null +++ b/0012-mmc-omap_hsmmc-Fix-the-crashes-due-to-the-interrupts.patch @@ -0,0 +1,303 @@ +From b13c0c62ddf7a3a7d5b96fed8ea80f21f3bb2dad Mon Sep 17 00:00:00 2001 +From: Pantelis Antoniou <panto@antoniou-consulting.com> +Date: Wed, 17 Jul 2013 20:00:13 +0300 +Subject: [PATCH 12/13] mmc: omap_hsmmc: Fix the crashes due to the interrupts + racing + +--- + drivers/mmc/host/omap_hsmmc.c | 120 +++++++++++++++++++++++++++++++----------- + 1 file changed, 88 insertions(+), 32 deletions(-) + +diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c +index 1f9ff97..91e2954 100644 +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -171,7 +171,7 @@ struct omap_hsmmc_host { + unsigned char power_mode; + int suspended; + int irq; +- int use_dma, dma_ch; ++ int use_dma; + struct dma_chan *tx_chan; + struct dma_chan *rx_chan; + int slot_id; +@@ -180,10 +180,15 @@ struct omap_hsmmc_host { + int protect_card; + int reqs_blocked; + int use_reg; +- int req_in_progress; + struct omap_hsmmc_next next_data; + + struct omap_mmc_platform_data *pdata; ++ ++ unsigned int req_flags; ++#define RQF_REQ_IN_PROGRESS (1 << 0) ++#define RQF_DMA_IN_PROGRESS (1 << 1) ++#define RQF_REQ_DONE (1 << 2) ++#define RQF_DMA_DONE (1 << 3) + }; + + static int omap_hsmmc_card_detect(struct device *dev, int slot) +@@ -803,7 +808,8 @@ omap_hsmmc_start_command(struct omap_hsmmc_host *host, struct mmc_command *cmd, + if (host->use_dma) + cmdreg |= DMAE; + +- host->req_in_progress = 1; ++ host->req_flags |= RQF_REQ_IN_PROGRESS; ++ host->req_flags &= ~RQF_REQ_DONE; + + OMAP_HSMMC_WRITE(host->base, ARG, cmd->arg); + OMAP_HSMMC_WRITE(host->base, CMD, cmdreg); +@@ -826,19 +832,34 @@ static struct dma_chan *omap_hsmmc_get_dma_chan(struct omap_hsmmc_host *host, + + static void omap_hsmmc_request_done(struct omap_hsmmc_host *host, struct mmc_request *mrq) + { +- int dma_ch; ++ int completed; + unsigned long flags; + + spin_lock_irqsave(&host->irq_lock, flags); +- host->req_in_progress = 0; +- dma_ch = host->dma_ch; +- spin_unlock_irqrestore(&host->irq_lock, flags); ++ ++ host->req_flags &= ~RQF_REQ_IN_PROGRESS; ++ host->req_flags |= RQF_REQ_DONE; ++ ++ /* completed? */ ++ if (mrq->data && host->use_dma) ++ completed = (host->req_flags & RQF_DMA_DONE) == RQF_DMA_DONE; ++ else ++ completed = 1; + + omap_hsmmc_disable_irq(host); ++ + /* Do not complete the request if DMA is still in progress */ +- if (mrq->data && host->use_dma && dma_ch != -1) ++ if (!completed) { ++ spin_unlock_irqrestore(&host->irq_lock, flags); ++ pr_debug("%s: not completed!\n", __func__); + return; ++ } ++ ++ /* clear the flags now */ ++ host->req_flags &= ~(RQF_REQ_DONE | RQF_DMA_DONE); + host->mrq = NULL; ++ spin_unlock_irqrestore(&host->irq_lock, flags); ++ + mmc_request_done(host->mmc, mrq); + } + +@@ -855,6 +876,7 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) + if (host->cmd && host->cmd->opcode == 6 && + host->response_busy) { + host->response_busy = 0; ++ pr_debug("%s: response_busy = 0\n", __func__); + return; + } + +@@ -870,9 +892,11 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) + data->bytes_xfered = 0; + + if (!data->stop) { ++ pr_debug("%s: calling omap_hsmmc_request_done\n", __func__); + omap_hsmmc_request_done(host, data->mrq); + return; + } ++ pr_debug("%s: calling omap_hsmmc_start_command\n", __func__); + omap_hsmmc_start_command(host, data->stop, NULL); + } + +@@ -882,6 +906,8 @@ omap_hsmmc_xfer_done(struct omap_hsmmc_host *host, struct mmc_data *data) + static void + omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) + { ++ unsigned long flags; ++ + host->cmd = NULL; + + if (cmd->flags & MMC_RSP_PRESENT) { +@@ -898,6 +924,18 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) + } + if ((host->data == NULL && !host->response_busy) || cmd->error) + omap_hsmmc_request_done(host, cmd->mrq); ++ else { ++ spin_lock_irqsave(&host->irq_lock, flags); ++ /* we use DMA, and DMA is completed - kick the can */ ++ if ((host->req_flags & RQF_DMA_DONE) != 0) { ++ host->req_flags &= ~(RQF_REQ_IN_PROGRESS | RQF_REQ_DONE | RQF_DMA_DONE); ++ host->mrq = NULL; ++ mmc_request_done(host->mmc, cmd->mrq); ++ } else { ++ pr_debug("%s: not calling omap_hsmmc_request_done!\n", __func__); ++ } ++ spin_unlock_irqrestore(&host->irq_lock, flags); ++ } + } + + /* +@@ -905,17 +943,19 @@ omap_hsmmc_cmd_done(struct omap_hsmmc_host *host, struct mmc_command *cmd) + */ + static void omap_hsmmc_dma_cleanup(struct omap_hsmmc_host *host, int errno) + { +- int dma_ch; ++ int dma_in_progress; + unsigned long flags; + + host->data->error = errno; + + spin_lock_irqsave(&host->irq_lock, flags); +- dma_ch = host->dma_ch; +- host->dma_ch = -1; ++ dma_in_progress = host->use_dma && ++ (host->req_flags & RQF_DMA_IN_PROGRESS) != 0; ++ host->req_flags &= ~RQF_DMA_IN_PROGRESS; ++ host->req_flags |= RQF_DMA_DONE; + spin_unlock_irqrestore(&host->irq_lock, flags); + +- if (host->use_dma && dma_ch != -1) { ++ if (dma_in_progress) { + struct dma_chan *chan = omap_hsmmc_get_dma_chan(host, host->data); + + dmaengine_terminate_all(chan); +@@ -1005,16 +1045,22 @@ static void hsmmc_command_incomplete(struct omap_hsmmc_host *host, + int err, int end_cmd) + { + if (end_cmd) { ++ pr_debug("%s end_cmd\n", __func__); + omap_hsmmc_reset_controller_fsm(host, SRC); + if (host->cmd) + host->cmd->error = err; + } + + if (host->data) { ++ pr_debug("%s host->data; resetting dma\n", __func__); + omap_hsmmc_reset_controller_fsm(host, SRD); + omap_hsmmc_dma_cleanup(host, err); +- } else if (host->mrq && host->mrq->cmd) ++ } else if (host->mrq && host->mrq->cmd) { ++ pr_debug("%s error\n", __func__); + host->mrq->cmd->error = err; ++ } else { ++ pr_debug("%s nothing\n", __func__); ++ } + } + + static void omap_hsmmc_do_irq(struct omap_hsmmc_host *host, int status) +@@ -1055,13 +1101,13 @@ static irqreturn_t omap_hsmmc_irq(int irq, void *dev_id) + struct omap_hsmmc_host *host = dev_id; + int status; + +- status = OMAP_HSMMC_READ(host->base, STAT); +- while (status & INT_EN_MASK && host->req_in_progress) { +- omap_hsmmc_do_irq(host, status); ++ while ((status = OMAP_HSMMC_READ(host->base, STAT)) & INT_EN_MASK) { ++ ++ if (host->req_flags & RQF_REQ_IN_PROGRESS) ++ omap_hsmmc_do_irq(host, status); + + /* Flush posted write */ + OMAP_HSMMC_WRITE(host->base, STAT, status); +- status = OMAP_HSMMC_READ(host->base, STAT); + } + + return IRQ_HANDLED; +@@ -1199,13 +1245,15 @@ static irqreturn_t omap_hsmmc_detect(int irq, void *dev_id) + static void omap_hsmmc_dma_callback(void *param) + { + struct omap_hsmmc_host *host = param; ++ struct mmc_request *mrq = host->mrq; + struct dma_chan *chan; + struct mmc_data *data; +- int req_in_progress; ++ int completed; + + spin_lock_irq(&host->irq_lock); +- if (host->dma_ch < 0) { ++ if ((host->req_flags & RQF_DMA_IN_PROGRESS) == 0) { + spin_unlock_irq(&host->irq_lock); ++ pr_debug("%s: No DMA in progress!\n", __func__); + return; + } + +@@ -1216,17 +1264,22 @@ static void omap_hsmmc_dma_callback(void *param) + data->sg, data->sg_len, + omap_hsmmc_get_dma_dir(host, data)); + +- req_in_progress = host->req_in_progress; +- host->dma_ch = -1; +- spin_unlock_irq(&host->irq_lock); ++ host->req_flags &= ~RQF_DMA_IN_PROGRESS; ++ host->req_flags |= RQF_DMA_DONE; + +- /* If DMA has finished after TC, complete the request */ +- if (!req_in_progress) { +- struct mmc_request *mrq = host->mrq; ++ completed = (host->req_flags & RQF_REQ_DONE) != 0; + +- host->mrq = NULL; +- mmc_request_done(host->mmc, mrq); ++ if (!completed) { ++ spin_unlock_irq(&host->irq_lock); ++ pr_debug("%s: not completed\n", __func__); ++ return; + } ++ ++ host->req_flags &= ~(RQF_REQ_DONE | RQF_DMA_DONE); ++ host->mrq = NULL; ++ spin_unlock_irq(&host->irq_lock); ++ ++ mmc_request_done(host->mmc, mrq); + } + + static int omap_hsmmc_pre_dma_transfer(struct omap_hsmmc_host *host, +@@ -1294,7 +1347,7 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, + */ + return -EINVAL; + +- BUG_ON(host->dma_ch != -1); ++ BUG_ON((host->req_flags & RQF_DMA_IN_PROGRESS) != 0); + + chan = omap_hsmmc_get_dma_chan(host, data); + +@@ -1328,7 +1381,7 @@ static int omap_hsmmc_start_dma_transfer(struct omap_hsmmc_host *host, + /* Does not fail */ + dmaengine_submit(tx); + +- host->dma_ch = 1; ++ host->req_flags |= RQF_DMA_IN_PROGRESS; + + dma_async_issue_pending(chan); + +@@ -1448,8 +1501,11 @@ static void omap_hsmmc_request(struct mmc_host *mmc, struct mmc_request *req) + struct omap_hsmmc_host *host = mmc_priv(mmc); + int err; + +- BUG_ON(host->req_in_progress); +- BUG_ON(host->dma_ch != -1); ++ BUG_ON((host->req_flags & RQF_REQ_IN_PROGRESS) != 0); ++ BUG_ON((host->req_flags & RQF_REQ_DONE) != 0); ++ BUG_ON((host->req_flags & RQF_DMA_IN_PROGRESS) != 0); ++ BUG_ON((host->req_flags & RQF_DMA_DONE) != 0); ++ + if (host->protect_card) { + if (host->reqs_blocked < 3) { + /* +@@ -1826,13 +1882,13 @@ static int omap_hsmmc_probe(struct platform_device *pdev) + host->pdata = pdata; + host->dev = &pdev->dev; + host->use_dma = 1; +- host->dma_ch = -1; + host->irq = irq; + host->slot_id = 0; + host->mapbase = res->start + pdata->reg_offset; + host->base = ioremap(host->mapbase, SZ_4K); + host->power_mode = MMC_POWER_OFF; + host->next_data.cookie = 1; ++ host->req_flags = 0; + + platform_set_drvdata(pdev, host); + +-- +1.8.2.1 + diff --git a/0013-ARM-EDMA-Fix-clearing-of-unused-list-for-DT-DMA-reso.patch b/0013-ARM-EDMA-Fix-clearing-of-unused-list-for-DT-DMA-reso.patch new file mode 100644 index 000000000..50d22184e --- /dev/null +++ b/0013-ARM-EDMA-Fix-clearing-of-unused-list-for-DT-DMA-reso.patch @@ -0,0 +1,65 @@ +From c845f409541688e339c6b86b1eeea5f7110821d2 Mon Sep 17 00:00:00 2001 +From: Joel Fernandes <joelf@ti.com> +Date: Mon, 22 Jul 2013 12:49:17 -0500 +Subject: [PATCH 13/13] ARM: EDMA: Fix clearing of unused list for DT DMA + resources + +HWMOD removal for MMC is breaking edma_start as the events are being manually +triggered due to unused channel list not being clear, Thanks to Balaji TK for +finding this issue. + +This patch fixes the issue, by reading the "dmas" property from the DT node if +it exists and clearing the bits in the unused channel list. + +Cc: Balaji T K <balajitk@ti.com> +Cc: Pantel Antoniou <panto@antoniou-consulting.com> +Signed-off-by: Joel Fernandes <joelf@ti.com> +--- + arch/arm/common/edma.c | 31 +++++++++++++++++++++++-------- + 1 file changed, 23 insertions(+), 8 deletions(-) + +diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c +index 39ad030..18159d7 100644 +--- a/arch/arm/common/edma.c ++++ b/arch/arm/common/edma.c +@@ -560,14 +560,29 @@ static int reserve_contiguous_slots(int ctlr, unsigned int id, + static int prepare_unused_channel_list(struct device *dev, void *data) + { + struct platform_device *pdev = to_platform_device(dev); +- int i, ctlr; +- +- for (i = 0; i < pdev->num_resources; i++) { +- if ((pdev->resource[i].flags & IORESOURCE_DMA) && +- (int)pdev->resource[i].start >= 0) { +- ctlr = EDMA_CTLR(pdev->resource[i].start); +- clear_bit(EDMA_CHAN_SLOT(pdev->resource[i].start), +- edma_cc[ctlr]->edma_unused); ++ int i = 0, ctlr; ++ u32 dma_chan; ++ __be32 *dma_chan_p; ++ struct property *prop; ++ ++ if (dev->of_node) { ++ of_property_for_each_u32(dev->of_node, "dmas", prop, \ ++ dma_chan_p, dma_chan) { ++ if (i++ & 1) { ++ ctlr = EDMA_CTLR(dma_chan); ++ clear_bit(EDMA_CHAN_SLOT(dma_chan), ++ edma_cc[ctlr]->edma_unused); ++ } ++ } ++ } else { ++ for (; i < pdev->num_resources; i++) { ++ if ((pdev->resource[i].flags & IORESOURCE_DMA) && ++ (int)pdev->resource[i].start >= 0) { ++ ctlr = EDMA_CTLR(pdev->resource[i].start); ++ clear_bit(EDMA_CHAN_SLOT( ++ pdev->resource[i].start), ++ edma_cc[ctlr]->edma_unused); ++ } + } + } + +-- +1.8.2.1 + diff --git a/arm-am33xx-bbb-dts.patch b/arm-am33xx-bbb-dts.patch deleted file mode 100644 index b9b9fc475..000000000 --- a/arm-am33xx-bbb-dts.patch +++ /dev/null @@ -1,230 +0,0 @@ -From 227cadff47a2b00e91deb5b54f1fd551808d42ae Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou <panto@antoniou-consulting.com> -Date: Fri, 28 Jun 2013 14:18:08 +0300 -Subject: [PATCH 1/3] am335x: dts: Add beaglebone black DTS - -Added the beaglebone black's DTS file. Note that at some point in -time we'll switch to using a common black.dtsi file. - -Signed-off-by: Pantelis Antoniou <panto@antoniou-consulting.com> ---- - arch/arm/boot/dts/Makefile | 3 +- - arch/arm/boot/dts/am335x-boneblack.dts | 196 +++++++++++++++++++++++++++++++++ - 2 files changed, 198 insertions(+), 1 deletion(-) - create mode 100644 arch/arm/boot/dts/am335x-boneblack.dts - -diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile ---- a/arch/arm/boot/dts/Makefile.orig 2013-07-17 11:51:55.510389342 +0100 -+++ b/arch/arm/boot/dts/Makefile 2013-07-17 11:55:09.492689175 +0100 -@@ -172,6 +172,7 @@ - am335x-evm.dtb \ - am335x-evmsk.dtb \ - am335x-bone.dtb \ -+ am335x-boneblack.dtb \ - am3517-evm.dtb \ - am3517_mt_ventoux.dtb \ - am43x-epos-evm.dtb -diff --git a/arch/arm/boot/dts/am335x-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts -new file mode 100644 -index 0000000..d21e223 ---- /dev/null -+++ b/arch/arm/boot/dts/am335x-boneblack.dts -@@ -0,0 +1,196 @@ -+/* -+ * Copyright (C) 2012 Texas Instruments Incorporated - http://www.ti.com/ -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+/dts-v1/; -+ -+/include/ "am33xx.dtsi" -+ -+/ { -+ model = "TI AM335x BeagleBone"; -+ compatible = "ti,am335x-bone", "ti,am33xx"; -+ -+ cpus { -+ cpu@0 { -+ cpu0-supply = <&dcdc2_reg>; -+ -+ /* -+ * To consider voltage drop between PMIC and SoC, -+ * tolerance value is reduced to 2% from 4% and -+ * voltage value is increased as a precaution. -+ */ -+ operating-points = < -+ /* kHz uV */ -+ 1000000 1350000 -+ 800000 1300000 -+ 600000 1112000 -+ 300000 969000 -+ >; -+ }; -+ }; -+ -+ memory { -+ device_type = "memory"; -+ reg = <0x80000000 0x10000000>; /* 256 MB */ -+ }; -+ -+ am33xx_pinmux: pinmux@44e10800 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&user_leds_s0>; -+ -+ user_leds_s0: user_leds_s0 { -+ pinctrl-single,pins = < -+ 0x54 0x7 /* gpmc_a5.gpio1_21, OUTPUT | MODE7 */ -+ 0x58 0x17 /* gpmc_a6.gpio1_22, OUTPUT_PULLUP | MODE7 */ -+ 0x5c 0x7 /* gpmc_a7.gpio1_23, OUTPUT | MODE7 */ -+ 0x60 0x17 /* gpmc_a8.gpio1_24, OUTPUT_PULLUP | MODE7 */ -+ >; -+ }; -+ -+ emmc2_pins: pinmux_emmc2_pins { -+ pinctrl-single,pins = < -+ 0x80 0x32 /* gpmc_csn1.mmc1_clk, INPUT_PULLUP | MODE2 */ -+ 0x84 0x32 /* gpmc_csn2.mmc1_cmd, INPUT_PULLUP | MODE2 */ -+ 0x00 0x31 /* gpmc_ad0.mmc1_dat0, INPUT_PULLUP | MODE1 */ -+ 0x04 0x31 /* gpmc_ad1.mmc1_dat1, INPUT_PULLUP | MODE1 */ -+ 0x08 0x31 /* gpmc_ad2.mmc1_dat2, INPUT_PULLUP | MODE1 */ -+ 0x0c 0x31 /* gpmc_ad3.mmc1_dat3, INPUT_PULLUP | MODE1 */ -+ 0x10 0x31 /* gpmc_ad4.mmc1_dat4, INPUT_PULLUP | MODE1 */ -+ 0x14 0x31 /* gpmc_ad5.mmc1_dat5, INPUT_PULLUP | MODE1 */ -+ 0x18 0x31 /* gpmc_ad6.mmc1_dat6, INPUT_PULLUP | MODE1 */ -+ 0x1c 0x31 /* gpmc_ad7.mmc1_dat7, INPUT_PULLUP | MODE1 */ -+ /* eMMC_RSTn */ -+ 0x50 0x17 /* gpmc_a4.gpio1_20, OUTPUT | MODE7 | PULLUP */ -+ >; -+ }; -+ }; -+ -+ ocp { -+ uart1: serial@44e09000 { -+ status = "okay"; -+ }; -+ -+ i2c0: i2c@44e0b000 { -+ status = "okay"; -+ clock-frequency = <400000>; -+ -+ tps: tps@24 { -+ reg = <0x24>; -+ }; -+ -+ }; -+ }; -+ -+ leds { -+ compatible = "gpio-leds"; -+ -+ led@2 { -+ label = "beaglebone:green:heartbeat"; -+ gpios = <&gpio1 21 0>; -+ linux,default-trigger = "heartbeat"; -+ default-state = "off"; -+ }; -+ -+ led@3 { -+ label = "beaglebone:green:mmc0"; -+ gpios = <&gpio1 22 0>; -+ linux,default-trigger = "mmc0"; -+ default-state = "off"; -+ }; -+ -+ led@4 { -+ label = "beaglebone:green:usr2"; -+ gpios = <&gpio1 23 0>; -+ default-state = "off"; -+ }; -+ -+ led@5 { -+ label = "beaglebone:green:usr3"; -+ gpios = <&gpio1 24 0>; -+ default-state = "off"; -+ }; -+ }; -+ -+ vmmcsd_fixed: fixedregulator@0 { -+ compatible = "regulator-fixed"; -+ regulator-name = "vmmcsd_fixed"; -+ regulator-min-microvolt = <3300000>; -+ regulator-max-microvolt = <3300000>; -+ }; -+ -+}; -+ -+/include/ "tps65217.dtsi" -+ -+&tps { -+ regulators { -+ dcdc1_reg: regulator@0 { -+ regulator-always-on; -+ }; -+ -+ dcdc2_reg: regulator@1 { -+ /* VDD_MPU voltage limits 0.95V - 1.26V with +/-4% tolerance */ -+ regulator-name = "vdd_mpu"; -+ regulator-min-microvolt = <925000>; -+ regulator-max-microvolt = <1325000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ dcdc3_reg: regulator@2 { -+ /* VDD_CORE voltage limits 0.95V - 1.1V with +/-4% tolerance */ -+ regulator-name = "vdd_core"; -+ regulator-min-microvolt = <925000>; -+ regulator-max-microvolt = <1150000>; -+ regulator-boot-on; -+ regulator-always-on; -+ }; -+ -+ ldo1_reg: regulator@3 { -+ regulator-always-on; -+ }; -+ -+ ldo2_reg: regulator@4 { -+ regulator-always-on; -+ }; -+ -+ ldo3_reg: regulator@5 { -+ regulator-min-microvolt = <1800000>; -+ regulator-max-microvolt = <1800000>; /* orig 3.3V*/ -+ regulator-always-on; -+ }; -+ -+ ldo4_reg: regulator@6 { -+ regulator-always-on; -+ }; -+ }; -+}; -+ -+&cpsw_emac0 { -+ phy_id = <&davinci_mdio>, <0>; -+}; -+ -+&cpsw_emac1 { -+ phy_id = <&davinci_mdio>, <1>; -+}; -+ -+&mmc1 { -+ status = "okay"; -+ vmmc-supply = <&vmmcsd_fixed>; -+ ti,vcc-aux-disable-is-sleep; -+}; -+ -+&mmc2 { -+ pinctrl-names = "default"; -+ pinctrl-0 = <&emmc2_pins>; /* wrong numbering */ -+ vmmc-supply = <&ldo3_reg>; -+ bus-width = <8>; -+ ti,non-removable; -+ status = "okay"; -+ ti,vcc-aux-disable-is-sleep; -+ -+ reset-gpio = <&gpio1 20 0x00>; -+}; --- -1.8.2.1 diff --git a/kernel.spec b/kernel.spec index 0df654c72..d03fdcca5 100644 --- a/kernel.spec +++ b/kernel.spec @@ -719,7 +719,25 @@ Patch21030: arm-wandboard-quad.patch Patch21031: arm-imx-fixsound.patch # AM33xx -Patch21040: arm-am33xx-bbb-dts.patch +Patch21040: 0001-reset-Add-driver-for-gpio-controlled-reset-pins.patch +Patch21041: 0001-ARM-davinci-uart-move-to-devid-based-clk_get.patch +Patch21042: 0002-dma-edma-add-device_slave_sg_limits-support.patch +Patch21043: 0003-dmaengine-add-dma_get_slave_sg_limits.patch +Patch21044: 0004-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch +Patch21045: 0005-da8xx-config-Enable-MMC-and-FS-options.patch +Patch21046: 0006-ARM-dts-add-AM33XX-EDMA-support.patch +Patch21047: 0007-ARM-dts-add-AM33XX-SPI-DMA-support.patch +Patch21048: 0008-ARM-dts-add-AM33XX-MMC-support.patch +Patch21049: 0009-DMA-EDMA-Split-out-PaRAM-set-calculations-into-its-o.patch +Patch21050: 0010-DMA-EDMA-Add-support-for-Cyclic-DMA.patch +Patch21051: 0011-sound-soc-soc-dmaengine-pcm-Add-support-for-new-DMAE.patch +Patch21052: 0012-mmc-omap_hsmmc-Fix-the-crashes-due-to-the-interrupts.patch +Patch21053: 0013-ARM-EDMA-Fix-clearing-of-unused-list-for-DT-DMA-reso.patch +Patch21054: 0001-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch +Patch21055: 0002-omap_hsmmc-Add-reset-gpio.patch +Patch21056: 0001-am335x-dts-Add-beaglebone-black-DTS.patch +Patch21057: 0002-dts-beaglebone-Add-I2C-definitions-for-EEPROMs-capes.patch + #rhbz 754518 Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -1328,7 +1346,24 @@ ApplyPatch arm-wandboard-quad.patch ApplyPatch arm-imx-fixsound.patch # Fix OMAP and AM33xx (BeagleBone) -#pplyPatch arm-am33xx-bbb-dts.patch +ApplyPatch 0001-reset-Add-driver-for-gpio-controlled-reset-pins.patch +ApplyPatch 0001-ARM-davinci-uart-move-to-devid-based-clk_get.patch +ApplyPatch 0002-dma-edma-add-device_slave_sg_limits-support.patch +ApplyPatch 0003-dmaengine-add-dma_get_slave_sg_limits.patch +ApplyPatch 0004-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch +ApplyPatch 0005-da8xx-config-Enable-MMC-and-FS-options.patch +ApplyPatch 0006-ARM-dts-add-AM33XX-EDMA-support.patch +ApplyPatch 0007-ARM-dts-add-AM33XX-SPI-DMA-support.patch +ApplyPatch 0008-ARM-dts-add-AM33XX-MMC-support.patch +ApplyPatch 0009-DMA-EDMA-Split-out-PaRAM-set-calculations-into-its-o.patch +ApplyPatch 0010-DMA-EDMA-Add-support-for-Cyclic-DMA.patch +ApplyPatch 0011-sound-soc-soc-dmaengine-pcm-Add-support-for-new-DMAE.patch +ApplyPatch 0012-mmc-omap_hsmmc-Fix-the-crashes-due-to-the-interrupts.patch +ApplyPatch 0013-ARM-EDMA-Fix-clearing-of-unused-list-for-DT-DMA-reso.patch +ApplyPatch 0001-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch +ApplyPatch 0002-omap_hsmmc-Add-reset-gpio.patch +ApplyPatch 0001-am335x-dts-Add-beaglebone-black-DTS.patch +ApplyPatch 0002-dts-beaglebone-Add-I2C-definitions-for-EEPROMs-capes.patch # # bugfixes to drivers and filesystems @@ -2282,6 +2317,10 @@ fi # ||----w | # || || %changelog +* Wed Sep 4 2013 Peter Robinson <pbrobinson@fedoraproject.org> +- Add patch set to fix MMC on AM33xx +- Add support for BeagleBone Black (very basic!) + * Wed Sep 04 2013 Josh Boyer <jwboyer@fedoraproject.org> - 3.12.0-0.rc0.git1.1 - Linux v3.11-351-g1ccfd5e - Reenable debugging options. |