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 deleted file mode 100644 index 0e5b12d42..000000000 --- a/0001-ARM-davinci-uart-move-to-devid-based-clk_get.patch +++ /dev/null @@ -1,724 +0,0 @@ -From da41a8e42998c4bff8b19ee3d9fdfed6a5951c3f Mon Sep 17 00:00:00 2001 -From: "Manjunathappa, Prakash" -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 -Signed-off-by: Sekhar Nori ---- - 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 deleted file mode 100644 index f1044324e..000000000 --- a/0001-am335x-dts-Add-beaglebone-black-DTS.patch +++ /dev/null @@ -1,323 +0,0 @@ -From 35bd7cf94f2680c4674c1df72f9ab322f393a9c2 Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou -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 ---- - 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 deleted file mode 100644 index 2c7bc63cd..000000000 --- a/0001-omap-hsmmc-Correct-usage-of-of_find_node_by_name.patch +++ /dev/null @@ -1,34 +0,0 @@ -From 9e6eeee6a1e0477f237dee5015c982296a91403f Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou -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 deleted file mode 100644 index e5661aef1..000000000 --- a/0001-reset-Add-driver-for-gpio-controlled-reset-pins.patch +++ /dev/null @@ -1,265 +0,0 @@ -From 31bacc8256b3ddb19269a3a1c74b0ba3851d1e19 Mon Sep 17 00:00:00 2001 -From: Philipp Zabel -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 -Reviewed-by: Stephen Warren ---- - .../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 -+#include -+#include -+#include -+#include -+#include -+#include -+ -+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 "); -+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 deleted file mode 100644 index 419b3203b..000000000 --- a/0002-dma-edma-add-device_slave_sg_limits-support.patch +++ /dev/null @@ -1,76 +0,0 @@ -From 6077fbf31d4263222eb1815f1c4edf67e90a3434 Mon Sep 17 00:00:00 2001 -From: Matt Porter -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 -Signed-off-by: Joel A Fernandes ---- - 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 deleted file mode 100644 index 8493d1606..000000000 --- a/0002-dts-beaglebone-Add-I2C-definitions-for-EEPROMs-capes.patch +++ /dev/null @@ -1,142 +0,0 @@ -From e3c9bd680440e6216a86184687968a3939c06160 Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou -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 ---- - 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 deleted file mode 100644 index ea686e78e..000000000 --- a/0002-omap_hsmmc-Add-reset-gpio.patch +++ /dev/null @@ -1,138 +0,0 @@ -From 364d4535955f21a8ce13e969aedde946a2d566b8 Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou -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 ---- - 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 - #include - #include -+#include -+#include - - /* 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 deleted file mode 100644 index 61bcdb36e..000000000 --- a/0003-dmaengine-add-dma_get_slave_sg_limits.patch +++ /dev/null @@ -1,94 +0,0 @@ -From c8ff7a795bf883c61b7d7f506b0bb7796db6cb01 Mon Sep 17 00:00:00 2001 -From: Matt Porter -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 -Signed-off-by: Joel A Fernandes ---- - 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 deleted file mode 100644 index d6f98e16d..000000000 --- a/0004-mmc-omap_hsmmc-set-max_segs-based-on-dma-engine-limi.patch +++ /dev/null @@ -1,48 +0,0 @@ -From e1e06db0fb0ae8cfc2b3dc9c08b3237a050e2789 Mon Sep 17 00:00:00 2001 -From: Matt Porter -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 -Acked-by: Tony Lindgren ---- - 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 deleted file mode 100644 index d94e500d0..000000000 --- a/0005-da8xx-config-Enable-MMC-and-FS-options.patch +++ /dev/null @@ -1,33 +0,0 @@ -From bb43e18a5c1626fadb8674b287224905358751be Mon Sep 17 00:00:00 2001 -From: Joel A Fernandes -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 ---- - 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 deleted file mode 100644 index c5c4266bc..000000000 --- a/0006-ARM-dts-add-AM33XX-EDMA-support.patch +++ /dev/null @@ -1,44 +0,0 @@ -From b9e4382015c702fbc1be1753074fce93a0965ac0 Mon Sep 17 00:00:00 2001 -From: Matt Porter -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 -Signed-off-by: Joel A Fernandes ---- - 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 deleted file mode 100644 index 6716bfbc2..000000000 --- a/0007-ARM-dts-add-AM33XX-SPI-DMA-support.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 16649496dc8c4334ab72a0a5a407953e3dcf4c83 Mon Sep 17 00:00:00 2001 -From: Matt Porter -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 -Signed-off-by: Joel A Fernandes ---- - 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 deleted file mode 100644 index 23c2244db..000000000 --- a/0008-ARM-dts-add-AM33XX-MMC-support.patch +++ /dev/null @@ -1,191 +0,0 @@ -From 1aa00b457ea36f6eeb78b66be076e16a2d3fafe0 Mon Sep 17 00:00:00 2001 -From: Matt Porter -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 -Compatible added by Balaji TK -ti,needs-special-hs-handling added by Gururaja Hebbar - -Signed-off-by: Matt Porter -Acked-by: Tony Lindgren -Signed-off-by: Joel Fernandes - -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 deleted file mode 100644 index 8bef684a5..000000000 --- a/0009-DMA-EDMA-Split-out-PaRAM-set-calculations-into-its-o.patch +++ /dev/null @@ -1,271 +0,0 @@ -From 14c120151d8ae2e335dd8728c88d6cd1a52863c8 Mon Sep 17 00:00:00 2001 -From: Joel Fernandes -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 ---- - 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 deleted file mode 100644 index 4c981943a..000000000 --- a/0010-DMA-EDMA-Add-support-for-Cyclic-DMA.patch +++ /dev/null @@ -1,130 +0,0 @@ -From caf38f4702a75c7ba13d5d80d902812c5faa8501 Mon Sep 17 00:00:00 2001 -From: Joel Fernandes -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 ---- - 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 deleted file mode 100644 index f5f7ce88c..000000000 --- a/0011-sound-soc-soc-dmaengine-pcm-Add-support-for-new-DMAE.patch +++ /dev/null @@ -1,60 +0,0 @@ -From e85ad9182c962bb095beb435e98fde612a4ef88d Mon Sep 17 00:00:00 2001 -From: Joel Fernandes -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 ---- - 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 deleted file mode 100644 index 1c83398d0..000000000 --- a/0012-mmc-omap_hsmmc-Fix-the-crashes-due-to-the-interrupts.patch +++ /dev/null @@ -1,303 +0,0 @@ -From b13c0c62ddf7a3a7d5b96fed8ea80f21f3bb2dad Mon Sep 17 00:00:00 2001 -From: Pantelis Antoniou -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 deleted file mode 100644 index 50d22184e..000000000 --- a/0013-ARM-EDMA-Fix-clearing-of-unused-list-for-DT-DMA-reso.patch +++ /dev/null @@ -1,65 +0,0 @@ -From c845f409541688e339c6b86b1eeea5f7110821d2 Mon Sep 17 00:00:00 2001 -From: Joel Fernandes -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 -Cc: Pantel Antoniou -Signed-off-by: Joel Fernandes ---- - 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/am335x-bone.patch b/am335x-bone.patch new file mode 100644 index 000000000..a76dc40b9 --- /dev/null +++ b/am335x-bone.patch @@ -0,0 +1,6260 @@ + .../devicetree/bindings/mmc/ti-omap-hsmmc.txt | 26 +- + .../devicetree/bindings/reset/gpio-reset.txt | 35 ++ + arch/arm/boot/dts/Makefile | 3 +- + arch/arm/boot/dts/am335x-bone.dts | 126 +++++ + arch/arm/boot/dts/am335x-boneblack.dts | 403 ++++++++++++++++ + arch/arm/boot/dts/am335x-evm.dts | 7 + + arch/arm/boot/dts/am335x-evmsk.dts | 7 + + arch/arm/boot/dts/am33xx.dtsi | 60 +++ + arch/arm/common/edma.c | 31 +- + arch/arm/configs/da8xx_omapl_defconfig | 3 + + 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 +- + arch/arm/mach-omap2/Makefile | 3 + + arch/arm/mach-omap2/am33xx-cpsw.c | 94 ++++ + arch/arm/mach-omap2/board-omap3beagle.c | 4 +- + arch/arm/mach-omap2/board-omap3evm.c | 4 +- + arch/arm/mach-omap2/board-omap3pandora.c | 2 +- + arch/arm/mach-omap2/control.h | 4 + + arch/arm/mach-omap2/omap_device.c | 232 +++++---- + arch/arm/mach-omap2/omap_hwmod.c | 8 +- + arch/arm/mach-omap2/usb-host.c | 10 +- + drivers/base/platform.c | 122 +++-- + drivers/dma/edma.c | 299 +++++++++--- + drivers/gpu/drm/i2c/tda998x_drv.c | 518 ++++++++++++++++++--- + drivers/gpu/drm/tilcdc/tilcdc_crtc.c | 71 ++- + drivers/gpu/drm/tilcdc/tilcdc_drv.h | 5 +- + drivers/gpu/drm/tilcdc/tilcdc_panel.c | 49 +- + drivers/gpu/drm/tilcdc/tilcdc_slave.c | 65 ++- + drivers/misc/eeprom/at24.c | 23 + + drivers/mmc/host/omap_hsmmc.c | 178 +++++-- + drivers/of/device.c | 3 + + drivers/of/of_i2c.c | 104 +++-- + drivers/pinctrl/pinctrl-single.c | 12 +- + drivers/reset/Kconfig | 11 + + drivers/reset/Makefile | 1 + + drivers/reset/gpio-reset.c | 169 +++++++ + drivers/usb/Makefile | 2 +- + drivers/usb/dwc3/dwc3-exynos.c | 8 +- + drivers/usb/dwc3/dwc3-pci.c | 8 +- + drivers/usb/gadget/Kconfig | 2 - + drivers/usb/host/Kconfig | 1 - + drivers/usb/musb/am35x.c | 2 +- + drivers/usb/musb/blackfin.c | 2 +- + drivers/usb/musb/da8xx.c | 2 +- + drivers/usb/musb/davinci.c | 2 +- + drivers/usb/musb/musb_dsps.c | 2 +- + drivers/usb/musb/tusb6010.c | 2 +- + drivers/usb/phy/Kconfig | 48 +- + drivers/usb/phy/Makefile | 4 +- + drivers/usb/phy/am35x-phy-control.h | 21 + + drivers/usb/phy/phy-am335x-control.c | 137 ++++++ + drivers/usb/phy/phy-am335x.c | 99 ++++ + drivers/usb/phy/phy-generic.c | 309 ++++++++++++ + drivers/usb/phy/phy-generic.h | 20 + + drivers/usb/phy/phy-nop.c | 292 ------------ + include/drm/i2c/tda998x.h | 23 + + include/linux/dmaengine.h | 39 ++ + include/linux/i2c/eeprom.h | 59 +++ + include/linux/of_i2c.h | 11 + + include/linux/platform_data/mmc-omap.h | 3 + + include/linux/platform_device.h | 4 + + include/linux/usb/nop-usb-xceiv.h | 29 -- + include/linux/usb/usb_phy_gen_xceiv.h | 29 ++ + sound/soc/soc-dmaengine-pcm.c | 22 + + 74 files changed, 3315 insertions(+), 879 deletions(-) + +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/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/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile +index 641b3c9..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-bone.dts b/arch/arm/boot/dts/am335x-bone.dts +index 444b4ed..0741775 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 { +@@ -166,6 +210,81 @@ + default-state = "off"; + }; + }; ++ ++ bone_capemgr { ++ compatible = "ti,bone-capemgr"; ++ status = "okay"; ++ ++ eeprom = <&baseboard_eeprom>; ++ ++ baseboardmaps { ++ baseboard_beaglebone: board@0 { ++ board-name = "A335BONE"; ++ compatible-name = "ti,beaglebone"; ++ }; ++ ++ baseboard_beaglebone_black: board@1 { ++ board-name = "A335BNLT"; ++ compatible-name = "ti,beaglebone-black"; ++ }; ++ }; ++ ++ slots { ++ slot@0 { ++ eeprom = <&cape_eeprom0>; ++ }; ++ ++ slot@1 { ++ eeprom = <&cape_eeprom1>; ++ }; ++ ++ slot@2 { ++ eeprom = <&cape_eeprom2>; ++ }; ++ ++ slot@3 { ++ eeprom = <&cape_eeprom3>; ++ }; ++ ++ /* Beaglebone black has it soldered on */ ++ slot@100 { ++ ti,cape-override; ++ priority = <1>; ++ compatible = "ti,beaglebone-black"; ++ board-name = "Bone-LT-eMMC-2G"; ++ version = "00A0"; ++ manufacturer = "Texas Instruments"; ++ part-number = "BB-BONE-EMMC-2G"; ++ }; ++ ++ /* Beaglebone black has it soldered on */ ++ slot@101 { ++ ti,cape-override; ++ priority = <1>; ++ compatible = "ti,beaglebone-black"; ++ board-name = "Bone-Black-HDMI"; ++ version = "00A0"; ++ manufacturer = "Texas Instruments"; ++ part-number = "BB-BONELT-HDMI"; ++ }; ++ ++ /* Beaglebone black has it soldered on (but no audio) */ ++ slot@102 { ++ ti,cape-override; ++ priority = <2>; ++ compatible = "ti,beaglebone-black"; ++ board-name = "Bone-Black-HDMIN"; ++ version = "00A0"; ++ manufacturer = "Texas Instruments"; ++ part-number = "BB-BONELT-HDMIN"; ++ }; ++ }; ++ ++ /* mapping between board names and dtb objects */ ++ capemaps { ++ /* capemaps are only needed for special cases */ ++ }; ++ }; + }; + + /include/ "tps65217.dtsi" +@@ -203,6 +322,8 @@ + }; + + ldo3_reg: regulator@5 { ++ regulator-min-microvolt = <1800000>; ++ regulator-max-microvolt = <3300000>; + regulator-always-on; + }; + +@@ -234,3 +355,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-boneblack.dts b/arch/arm/boot/dts/am335x-boneblack.dts +new file mode 100644 +index 0000000..2ea9d5d +--- /dev/null ++++ b/arch/arm/boot/dts/am335x-boneblack.dts +@@ -0,0 +1,403 @@ ++/* ++ * 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 */ ++ >; ++ }; ++ ++ 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 { ++ 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>; ++ }; ++ ++ 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 { ++ 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>; ++ }; ++ ++ bone_capemgr { ++ compatible = "ti,bone-capemgr"; ++ status = "okay"; ++ ++ eeprom = <&baseboard_eeprom>; ++ ++ baseboardmaps { ++ baseboard_beaglebone: board@0 { ++ board-name = "A335BONE"; ++ compatible-name = "ti,beaglebone"; ++ }; ++ ++ baseboard_beaglebone_black: board@1 { ++ board-name = "A335BNLT"; ++ compatible-name = "ti,beaglebone-black"; ++ }; ++ }; ++ ++ slots { ++ slot@0 { ++ eeprom = <&cape_eeprom0>; ++ }; ++ ++ slot@1 { ++ eeprom = <&cape_eeprom1>; ++ }; ++ ++ slot@2 { ++ eeprom = <&cape_eeprom2>; ++ }; ++ ++ slot@3 { ++ eeprom = <&cape_eeprom3>; ++ }; ++ ++ /* Beaglebone black has it soldered on */ ++ slot@100 { ++ ti,cape-override; ++ priority = <1>; ++ compatible = "ti,beaglebone-black"; ++ board-name = "Bone-LT-eMMC-2G"; ++ version = "00A0"; ++ manufacturer = "Texas Instruments"; ++ part-number = "BB-BONE-EMMC-2G"; ++ }; ++ ++ /* Beaglebone black has it soldered on */ ++ slot@101 { ++ ti,cape-override; ++ priority = <1>; ++ compatible = "ti,beaglebone-black"; ++ board-name = "Bone-Black-HDMI"; ++ version = "00A0"; ++ manufacturer = "Texas Instruments"; ++ part-number = "BB-BONELT-HDMI"; ++ }; ++ ++ /* Beaglebone black has it soldered on (but no audio) */ ++ slot@102 { ++ ti,cape-override; ++ priority = <2>; ++ compatible = "ti,beaglebone-black"; ++ board-name = "Bone-Black-HDMIN"; ++ version = "00A0"; ++ manufacturer = "Texas Instruments"; ++ part-number = "BB-BONELT-HDMIN"; ++ }; ++ }; ++ ++ /* mapping between board names and dtb objects */ ++ capemaps { ++ /* capemaps are only needed for special cases */ ++ }; ++ }; ++}; ++ ++/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>; ++}; +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 38b446b..969c81b 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"; +@@ -224,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"; +@@ -319,6 +369,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"; + }; + +@@ -330,6 +385,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"; + }; + +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); ++ } + } + } + +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 +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) +diff --git a/arch/arm/mach-omap2/Makefile b/arch/arm/mach-omap2/Makefile +index d4f6715..7c0ef46 100644 +--- a/arch/arm/mach-omap2/Makefile ++++ b/arch/arm/mach-omap2/Makefile +@@ -295,4 +295,7 @@ endif + emac-$(CONFIG_TI_DAVINCI_EMAC) := am35xx-emac.o + obj-y += $(emac-m) $(emac-y) + ++cpsw-$(CONFIG_TI_CPSW) := am33xx-cpsw.o ++obj-y += $(cpsw-m) $(cpsw-y) ++ + obj-y += common-board-devices.o twl-common.o dss-common.o +diff --git a/arch/arm/mach-omap2/am33xx-cpsw.c b/arch/arm/mach-omap2/am33xx-cpsw.c +new file mode 100644 +index 0000000..5a674d9 +--- /dev/null ++++ b/arch/arm/mach-omap2/am33xx-cpsw.c +@@ -0,0 +1,94 @@ ++/* ++ * am335x specific cpsw dt fixups ++ * ++ * 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 version 2. ++ * ++ * This program is distributed "as is" WITHOUT ANY WARRANTY of any ++ * kind, whether express or implied; without even the implied warranty ++ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++ ++#include "soc.h" ++#include "control.h" ++ ++/** ++ * am33xx_dt_cpsw_set_mac_from_efuse - Add mac-address property using ++ * ethernet hwaddr from efuse ++ * @np: Pointer to the cpsw slave to set mac address of ++ * @idx: Mac address index to use from efuse ++ */ ++static void am33xx_dt_cpsw_set_mac_from_efuse(struct device_node *np, int idx) ++{ ++ struct property *prop; ++ u32 lo, hi; ++ u8 *mac; ++ ++ switch (idx) { ++ case 0: ++ lo = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID0_LOW); ++ hi = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID0_HIGH); ++ break; ++ ++ case 1: ++ lo = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID1_LOW); ++ hi = omap_ctrl_readl(AM33XX_CONTROL_MAC_ID1_HIGH); ++ break; ++ ++ default: ++ pr_err("cpsw.%d: too many slaves found\n", idx); ++ return; ++ } ++ ++ prop = kzalloc(sizeof(*prop) + ETH_ALEN, GFP_KERNEL); ++ if (!prop) ++ return; ++ ++ prop->value = prop + 1; ++ prop->length = ETH_ALEN; ++ prop->name = kstrdup("mac-address", GFP_KERNEL); ++ if (!prop->name) { ++ kfree(prop); ++ return; ++ } ++ ++ mac = prop->value; ++ ++ mac[0] = hi; ++ mac[1] = hi >> 8; ++ mac[2] = hi >> 16; ++ mac[3] = hi >> 24; ++ mac[4] = lo; ++ mac[5] = lo >> 8; ++ ++ of_update_property(np, prop); ++ ++ pr_info("cpsw.%d: No hwaddr in dt. Using %pM from efuse\n", idx, mac); ++} ++ ++static int __init am33xx_dt_cpsw_mac_fixup(void) ++{ ++ struct device_node *np, *slave; ++ int idx = 0; ++ ++ if (!soc_is_am33xx()) ++ return -ENODEV; ++ ++ for_each_compatible_node(np, NULL, "ti,cpsw") ++ for_each_node_by_name(slave, "slave") { ++ if (!of_get_mac_address(slave)) ++ am33xx_dt_cpsw_set_mac_from_efuse(slave, idx); ++ idx++; ++ } ++ ++ return 0; ++} ++arch_initcall(am33xx_dt_cpsw_mac_fixup); +diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c +index 04c1165..1c6ae5f 100644 +--- a/arch/arm/mach-omap2/board-omap3beagle.c ++++ b/arch/arm/mach-omap2/board-omap3beagle.c +@@ -33,7 +33,7 @@ + #include + #include + #include +-#include ++#include + + #include + #include +@@ -279,7 +279,7 @@ static struct regulator_consumer_supply beagle_vsim_supply[] = { + static struct gpio_led gpio_leds[]; + + /* PHY's VCC regulator might be added later, so flag that we need it */ +-static struct nop_usb_xceiv_platform_data hsusb2_phy_data = { ++static struct usb_phy_gen_xceiv_platform_data hsusb2_phy_data = { + .needs_vcc = true, + }; + +diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c +index 8c02626..52bdddd 100644 +--- a/arch/arm/mach-omap2/board-omap3evm.c ++++ b/arch/arm/mach-omap2/board-omap3evm.c +@@ -33,7 +33,7 @@ + #include + #include + #include +-#include ++#include + #include + + #include +@@ -468,7 +468,7 @@ struct wl12xx_platform_data omap3evm_wlan_data __initdata = { + static struct regulator_consumer_supply omap3evm_vaux2_supplies[] = { + REGULATOR_SUPPLY("VDD_CSIPHY1", "omap3isp"), /* OMAP ISP */ + REGULATOR_SUPPLY("VDD_CSIPHY2", "omap3isp"), /* OMAP ISP */ +- REGULATOR_SUPPLY("vcc", "nop_usb_xceiv.2"), /* hsusb port 2 */ ++ REGULATOR_SUPPLY("vcc", "usb_phy_gen_xceiv.2"), /* hsusb port 2 */ + REGULATOR_SUPPLY("vaux2", NULL), + }; + +diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c +index b1547a0..d2b455e 100644 +--- a/arch/arm/mach-omap2/board-omap3pandora.c ++++ b/arch/arm/mach-omap2/board-omap3pandora.c +@@ -352,7 +352,7 @@ static struct regulator_consumer_supply pandora_vcc_lcd_supply[] = { + }; + + static struct regulator_consumer_supply pandora_usb_phy_supply[] = { +- REGULATOR_SUPPLY("vcc", "nop_usb_xceiv.2"), /* hsusb port 2 */ ++ REGULATOR_SUPPLY("vcc", "usb_phy_gen_xceiv.2"), /* hsusb port 2 */ + }; + + /* ads7846 on SPI and 2 nub controllers on I2C */ +diff --git a/arch/arm/mach-omap2/control.h b/arch/arm/mach-omap2/control.h +index f7d7c2e..5d684b7 100644 +--- a/arch/arm/mach-omap2/control.h ++++ b/arch/arm/mach-omap2/control.h +@@ -352,6 +352,10 @@ + /* AM33XX CONTROL_STATUS register */ + #define AM33XX_CONTROL_STATUS 0x040 + #define AM33XX_CONTROL_SEC_CLK_CTRL 0x1bc ++#define AM33XX_CONTROL_MAC_ID0_LOW 0x630 ++#define AM33XX_CONTROL_MAC_ID0_HIGH 0x634 ++#define AM33XX_CONTROL_MAC_ID1_LOW 0x638 ++#define AM33XX_CONTROL_MAC_ID1_HIGH 0x63c + + /* AM33XX CONTROL_STATUS bitfields (partial) */ + #define AM33XX_CONTROL_STATUS_SYSBOOT1_SHIFT 22 +diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c +index f99f68e..dc7a56d 100644 +--- a/arch/arm/mach-omap2/omap_device.c ++++ b/arch/arm/mach-omap2/omap_device.c +@@ -330,30 +330,156 @@ static int omap_device_fill_resources(struct omap_device *od, + } + + /** +- * _od_fill_dma_resources - fill in array of struct resource with dma resources ++ * omap_device_fixup_resources - Fix platform device resources + * @od: struct omap_device * +- * @res: pointer to an array of struct resource to be filled in +- * +- * Populate one or more empty struct resource pointed to by @res with +- * the dma resource data for this omap_device @od. Used by +- * omap_device_alloc() after calling omap_device_count_resources(). +- * +- * Ideally this function would not be needed at all. If we have +- * mechanism to get dma resources from DT. + * +- * Returns 0. ++ * Fixup the platform device resources so that the resources ++ * from the hwmods are included for. + */ +-static int _od_fill_dma_resources(struct omap_device *od, +- struct resource *res) ++static int omap_device_fixup_resources(struct omap_device *od) + { +- int i, r; ++ struct platform_device *pdev = od->pdev; ++ int i, j, ret, res_count; ++ struct resource *res, *r, *rnew, *rn; ++ unsigned long type; + +- for (i = 0; i < od->hwmods_cnt; i++) { +- r = omap_hwmod_fill_dma_resources(od->hwmods[i], res); +- res += r; ++ /* ++ * DT Boot: ++ * OF framework will construct the resource structure (currently ++ * does for MEM & IRQ resource) and we should respect/use these ++ * resources, killing hwmod dependency. ++ * If pdev->num_resources > 0, we assume that MEM & IRQ resources ++ * have been allocated by OF layer already (through DTB). ++ * ++ * Non-DT Boot: ++ * Here, pdev->num_resources = 0, and we should get all the ++ * resources from hwmod. ++ * ++ * TODO: Once DMA resource is available from OF layer, we should ++ * kill filling any resources from hwmod. ++ */ ++ ++ /* count number of resources hwmod provides */ ++ res_count = omap_device_count_resources(od, IORESOURCE_IRQ | ++ IORESOURCE_DMA | IORESOURCE_MEM); ++ ++ /* if no resources from hwmod, we're done already */ ++ if (res_count == 0) ++ return 0; ++ ++ /* Allocate resources memory to account for all hwmod resources */ ++ res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL); ++ if (!res) { ++ ret = -ENOMEM; ++ goto fail_no_res; ++ } ++ ++ /* fill all the resources */ ++ ret = omap_device_fill_resources(od, res); ++ if (ret != 0) ++ goto fail_no_fill; ++ ++ /* ++ * If pdev->num_resources > 0, then assume that, ++ * MEM and IRQ resources will only come from DT and only ++ * fill DMA resource from hwmod layer. ++ */ ++ if (pdev->num_resources > 0) { ++ ++ dev_dbg(&pdev->dev, "%s(): resources allocated %d hwmod #%d\n", ++ __func__, pdev->num_resources, res_count); ++ ++ /* find number of resources needing to be inserted */ ++ for (i = 0, j = 0, r = res; i < res_count; i++, r++) { ++ type = resource_type(r); ++ if (type == IORESOURCE_DMA) ++ j++; ++ } ++ ++ /* no need to insert anything, just return */ ++ if (j == 0) { ++ kfree(res); ++ return 0; ++ } ++ ++ /* we need to insert j additional resources */ ++ rnew = kzalloc(sizeof(*rnew) * ++ (pdev->num_resources + j), GFP_KERNEL); ++ if (rnew == NULL) ++ goto fail_no_rnew; ++ ++ /* ++ * Unlink any resources from any lists. ++ * This is important since the copying destroys any ++ * linkage ++ */ ++ for (i = 0, r = pdev->resource; ++ i < pdev->num_resources; i++, r++) { ++ ++ if (!r->parent) ++ continue; ++ ++ dev_dbg(&pdev->dev, ++ "Releasing resource %p\n", r); ++ release_resource(r); ++ r->parent = NULL; ++ r->sibling = NULL; ++ r->child = NULL; ++ } ++ ++ memcpy(rnew, pdev->resource, ++ sizeof(*rnew) * pdev->num_resources); ++ ++ /* now append the resources from the hwmods */ ++ rn = rnew + pdev->num_resources; ++ for (i = 0, r = res; i < res_count; i++, r++) { ++ ++ type = resource_type(r); ++ if (type != IORESOURCE_DMA) ++ continue; ++ ++ /* append the hwmod resource */ ++ memcpy(rn, r, sizeof(*r)); ++ ++ /* make sure these are zeroed out */ ++ rn->parent = NULL; ++ rn->child = NULL; ++ rn->sibling = NULL; ++ ++ rn++; ++ } ++ kfree(res); /* we don't need res anymore */ ++ ++ /* this is our new resource table */ ++ res = rnew; ++ res_count = j + pdev->num_resources; ++ ++ } else { ++ dev_dbg(&pdev->dev, "%s(): using resources from hwmod %d\n", ++ __func__, res_count); + } + ++ ret = platform_device_add_resources(pdev, res, res_count); ++ kfree(res); ++ ++ /* failed to add the resources? */ ++ if (ret != 0) ++ return ret; ++ ++ /* finally link all the resources again */ ++ ret = platform_device_link_resources(pdev); ++ if (ret != 0) ++ return ret; ++ + return 0; ++ ++fail_no_rnew: ++ /* nothing */ ++fail_no_fill: ++ kfree(res); ++ ++fail_no_res: ++ return ret; + } + + /** +@@ -373,9 +499,8 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev, + { + int ret = -ENOMEM; + struct omap_device *od; +- struct resource *res = NULL; +- int i, res_count; + struct omap_hwmod **hwmods; ++ int i; + + od = kzalloc(sizeof(struct omap_device), GFP_KERNEL); + if (!od) { +@@ -385,79 +510,18 @@ struct omap_device *omap_device_alloc(struct platform_device *pdev, + od->hwmods_cnt = oh_cnt; + + hwmods = kmemdup(ohs, sizeof(struct omap_hwmod *) * oh_cnt, GFP_KERNEL); +- if (!hwmods) ++ if (!hwmods) { ++ ret = -ENOMEM; + goto oda_exit2; ++ } + + od->hwmods = hwmods; + od->pdev = pdev; + +- /* +- * Non-DT Boot: +- * Here, pdev->num_resources = 0, and we should get all the +- * resources from hwmod. +- * +- * DT Boot: +- * OF framework will construct the resource structure (currently +- * does for MEM & IRQ resource) and we should respect/use these +- * resources, killing hwmod dependency. +- * If pdev->num_resources > 0, we assume that MEM & IRQ resources +- * have been allocated by OF layer already (through DTB). +- * As preparation for the future we examine the OF provided resources +- * to see if we have DMA resources provided already. In this case +- * there is no need to update the resources for the device, we use the +- * OF provided ones. +- * +- * TODO: Once DMA resource is available from OF layer, we should +- * kill filling any resources from hwmod. +- */ +- if (!pdev->num_resources) { +- /* Count all resources for the device */ +- res_count = omap_device_count_resources(od, IORESOURCE_IRQ | +- IORESOURCE_DMA | +- IORESOURCE_MEM); +- } else { +- /* Take a look if we already have DMA resource via DT */ +- for (i = 0; i < pdev->num_resources; i++) { +- struct resource *r = &pdev->resource[i]; +- +- /* We have it, no need to touch the resources */ +- if (r->flags == IORESOURCE_DMA) +- goto have_everything; +- } +- /* Count only DMA resources for the device */ +- res_count = omap_device_count_resources(od, IORESOURCE_DMA); +- /* The device has no DMA resource, no need for update */ +- if (!res_count) +- goto have_everything; +- +- res_count += pdev->num_resources; +- } +- +- /* Allocate resources memory to account for new resources */ +- res = kzalloc(sizeof(struct resource) * res_count, GFP_KERNEL); +- if (!res) +- goto oda_exit3; +- +- if (!pdev->num_resources) { +- dev_dbg(&pdev->dev, "%s: using %d resources from hwmod\n", +- __func__, res_count); +- omap_device_fill_resources(od, res); +- } else { +- dev_dbg(&pdev->dev, +- "%s: appending %d DMA resources from hwmod\n", +- __func__, res_count - pdev->num_resources); +- memcpy(res, pdev->resource, +- sizeof(struct resource) * pdev->num_resources); +- _od_fill_dma_resources(od, &res[pdev->num_resources]); +- } +- +- ret = platform_device_add_resources(pdev, res, res_count); +- kfree(res); +- +- if (ret) ++ ret = omap_device_fixup_resources(od); ++ if (ret != 0) + goto oda_exit3; + +-have_everything: + pdev->archdata.od = od; + + for (i = 0; i < oh_cnt; i++) { +diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c +index 7f4db12..b887451 100644 +--- a/arch/arm/mach-omap2/omap_hwmod.c ++++ b/arch/arm/mach-omap2/omap_hwmod.c +@@ -784,7 +784,9 @@ static int _init_interface_clks(struct omap_hwmod *oh) + if (IS_ERR(c)) { + pr_warning("omap_hwmod: %s: cannot clk_get interface_clk %s\n", + oh->name, os->clk); +- ret = -EINVAL; ++ if (ret == 0) ++ ret = -EINVAL; ++ continue; + } + os->_clk = c; + /* +@@ -820,7 +822,9 @@ static int _init_opt_clks(struct omap_hwmod *oh) + if (IS_ERR(c)) { + pr_warning("omap_hwmod: %s: cannot clk_get opt_clk %s\n", + oh->name, oc->clk); +- ret = -EINVAL; ++ if (ret == 0) ++ ret = -EINVAL; ++ continue; + } + oc->_clk = c; + /* +diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c +index 2eb19d4..e83a6a4 100644 +--- a/arch/arm/mach-omap2/usb-host.c ++++ b/arch/arm/mach-omap2/usb-host.c +@@ -28,7 +28,7 @@ + #include + #include + #include +-#include ++#include + + #include "soc.h" + #include "omap_device.h" +@@ -349,7 +349,7 @@ static struct fixed_voltage_config hsusb_reg_config = { + /* .init_data filled later */ + }; + +-static const char *nop_name = "nop_usb_xceiv"; /* NOP PHY driver */ ++static const char *nop_name = "usb_phy_gen_xceiv"; /* NOP PHY driver */ + static const char *reg_name = "reg-fixed-voltage"; /* Regulator driver */ + + /** +@@ -460,9 +460,9 @@ int usbhs_init_phys(struct usbhs_phy_data *phy, int num_phys) + pdevinfo.name = nop_name; + pdevinfo.id = phy->port; + pdevinfo.data = phy->platform_data; +- pdevinfo.size_data = sizeof(struct nop_usb_xceiv_platform_data); +- +- scnprintf(phy_id, MAX_STR, "nop_usb_xceiv.%d", ++ pdevinfo.size_data = ++ sizeof(struct usb_phy_gen_xceiv_platform_data); ++ scnprintf(phy_id, MAX_STR, "usb_phy_gen_xceiv.%d", + phy->port); + pdev = platform_device_register_full(&pdevinfo); + if (IS_ERR(pdev)) { +diff --git a/drivers/base/platform.c b/drivers/base/platform.c +index 3c3197a..65c774c 100644 +--- a/drivers/base/platform.c ++++ b/drivers/base/platform.c +@@ -267,6 +267,80 @@ int platform_device_add_data(struct platform_device *pdev, const void *data, + } + EXPORT_SYMBOL_GPL(platform_device_add_data); + ++static struct resource *platform_device_parent_resource( ++ struct platform_device *pdev, struct resource *r) ++{ ++ unsigned long type; ++ ++ if (r->parent) ++ return r->parent; ++ ++ type = resource_type(r); ++ switch (type) { ++ case IORESOURCE_MEM: ++ return &iomem_resource; ++ case IORESOURCE_IO: ++ return &ioport_resource; ++ /* TODO: What about the other resources? */ ++ default: ++ break; ++ } ++ pr_debug("%s: no parent for resource %p type 0x%lx\n", ++ dev_name(&pdev->dev), r, resource_type(r)); ++ return NULL; ++} ++ ++int platform_device_unlink_resources(struct platform_device *pdev) ++{ ++ struct resource *r; ++ int i; ++ ++ for (i = pdev->num_resources - 1; i >= 0; i--) { ++ r = &pdev->resource[i]; ++ if (r->parent == NULL) ++ continue; ++ release_resource(r); ++ } ++ return 0; ++} ++EXPORT_SYMBOL_GPL(platform_device_unlink_resources); ++ ++int platform_device_link_resources(struct platform_device *pdev) ++{ ++ int i; ++ struct resource *p, *r; ++ ++ for (i = 0; i < pdev->num_resources; i++) { ++ r = &pdev->resource[i]; ++ ++ if (r->name == NULL) ++ r->name = dev_name(&pdev->dev); ++ ++ /* already linked */ ++ if (r->parent != NULL) ++ continue; ++ ++ p = platform_device_parent_resource(pdev, r); ++ if (p && insert_resource(p, r)) { ++ pr_err("%s: failed to claim resource %d\n", ++ dev_name(&pdev->dev), i); ++ goto fail; ++ } ++ } ++ ++ return 0; ++ ++fail: ++ while (--i >= 0) { ++ r = &pdev->resource[i]; ++ if (r->parent == NULL) ++ continue; ++ release_resource(r); ++ } ++ return -EBUSY; ++} ++EXPORT_SYMBOL_GPL(platform_device_link_resources); ++ + /** + * platform_device_add - add a platform device to device hierarchy + * @pdev: platform device we're adding +@@ -276,7 +350,7 @@ EXPORT_SYMBOL_GPL(platform_device_add_data); + */ + int platform_device_add(struct platform_device *pdev) + { +- int i, ret; ++ int ret; + + if (!pdev) + return -EINVAL; +@@ -308,26 +382,10 @@ int platform_device_add(struct platform_device *pdev) + break; + } + +- for (i = 0; i < pdev->num_resources; i++) { +- struct resource *p, *r = &pdev->resource[i]; +- +- if (r->name == NULL) +- r->name = dev_name(&pdev->dev); +- +- p = r->parent; +- if (!p) { +- if (resource_type(r) == IORESOURCE_MEM) +- p = &iomem_resource; +- else if (resource_type(r) == IORESOURCE_IO) +- p = &ioport_resource; +- } +- +- if (p && insert_resource(p, r)) { +- dev_err(&pdev->dev, "failed to claim resource %d\n", i); +- ret = -EBUSY; +- goto failed; +- } +- } ++ /* make sure the resources are linked properly */ ++ ret = platform_device_link_resources(pdev); ++ if (ret != 0) ++ goto failed_res; + + pr_debug("Registering platform device '%s'. Parent at %s\n", + dev_name(&pdev->dev), dev_name(pdev->dev.parent)); +@@ -336,20 +394,14 @@ int platform_device_add(struct platform_device *pdev) + if (ret == 0) + return ret; + +- failed: ++ platform_device_unlink_resources(pdev); ++ ++ failed_res: + if (pdev->id_auto) { + ida_simple_remove(&platform_devid_ida, pdev->id); + pdev->id = PLATFORM_DEVID_AUTO; + } + +- while (--i >= 0) { +- struct resource *r = &pdev->resource[i]; +- unsigned long type = resource_type(r); +- +- if (type == IORESOURCE_MEM || type == IORESOURCE_IO) +- release_resource(r); +- } +- + err_out: + return ret; + } +@@ -365,8 +417,6 @@ EXPORT_SYMBOL_GPL(platform_device_add); + */ + void platform_device_del(struct platform_device *pdev) + { +- int i; +- + if (pdev) { + device_del(&pdev->dev); + +@@ -375,13 +425,7 @@ void platform_device_del(struct platform_device *pdev) + pdev->id = PLATFORM_DEVID_AUTO; + } + +- for (i = 0; i < pdev->num_resources; i++) { +- struct resource *r = &pdev->resource[i]; +- unsigned long type = resource_type(r); +- +- if (type == IORESOURCE_MEM || type == IORESOURCE_IO) +- release_resource(r); +- } ++ platform_device_unlink_resources(pdev); + } + } + EXPORT_SYMBOL_GPL(platform_device_del); +diff --git a/drivers/dma/edma.c b/drivers/dma/edma.c +index 5f3e532..cec9a12 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 { +@@ -210,6 +211,198 @@ 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_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, +@@ -218,23 +411,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 { +@@ -262,7 +453,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] = +@@ -274,76 +472,16 @@ static struct dma_async_tx_descriptor *edma_prep_slave_sg( + } + } + +- 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) { +- 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; +- } ++ 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 (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->absync = ret; + +- 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); +@@ -368,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); + } + +@@ -462,6 +602,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 +675,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); + +@@ -534,9 +689,11 @@ 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; ++ 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; +diff --git a/drivers/gpu/drm/i2c/tda998x_drv.c b/drivers/gpu/drm/i2c/tda998x_drv.c +index e68b58a..967d0c3 100644 +--- a/drivers/gpu/drm/i2c/tda998x_drv.c ++++ b/drivers/gpu/drm/i2c/tda998x_drv.c +@@ -23,7 +23,7 @@ + #include + #include + #include +- ++#include + + #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__) + +@@ -32,6 +32,11 @@ struct tda998x_priv { + uint16_t rev; + uint8_t current_page; + int dpms; ++ bool is_hdmi_sink; ++ u8 vip_cntrl_0; ++ u8 vip_cntrl_1; ++ u8 vip_cntrl_2; ++ struct tda998x_encoder_params params; + }; + + #define to_tda998x_priv(x) ((struct tda998x_priv *)to_encoder_slave(x)->slave_priv) +@@ -68,10 +73,13 @@ struct tda998x_priv { + # define I2C_MASTER_DIS_MM (1 << 0) + # define I2C_MASTER_DIS_FILT (1 << 1) + # define I2C_MASTER_APP_STRT_LAT (1 << 2) ++#define REG_FEAT_POWERDOWN REG(0x00, 0x0e) /* read/write */ ++# define FEAT_POWERDOWN_SPDIF (1 << 3) + #define REG_INT_FLAGS_0 REG(0x00, 0x0f) /* read/write */ + #define REG_INT_FLAGS_1 REG(0x00, 0x10) /* read/write */ + #define REG_INT_FLAGS_2 REG(0x00, 0x11) /* read/write */ + # define INT_FLAGS_2_EDID_BLK_RD (1 << 1) ++#define REG_ENA_ACLK REG(0x00, 0x16) /* read/write */ + #define REG_ENA_VP_0 REG(0x00, 0x18) /* read/write */ + #define REG_ENA_VP_1 REG(0x00, 0x19) /* read/write */ + #define REG_ENA_VP_2 REG(0x00, 0x1a) /* read/write */ +@@ -110,6 +118,8 @@ struct tda998x_priv { + #define REG_VIP_CNTRL_5 REG(0x00, 0x25) /* write */ + # define VIP_CNTRL_5_CKCASE (1 << 0) + # define VIP_CNTRL_5_SP_CNT(x) (((x) & 3) << 1) ++#define REG_MUX_AP REG(0x00, 0x26) /* read/write */ ++#define REG_MUX_VP_VIP_OUT REG(0x00, 0x27) /* read/write */ + #define REG_MAT_CONTRL REG(0x00, 0x80) /* write */ + # define MAT_CONTRL_MAT_SC(x) (((x) & 3) << 0) + # define MAT_CONTRL_MAT_BP (1 << 2) +@@ -130,8 +140,12 @@ struct tda998x_priv { + #define REG_VS_LINE_END_1_LSB REG(0x00, 0xae) /* write */ + #define REG_VS_PIX_END_1_MSB REG(0x00, 0xaf) /* write */ + #define REG_VS_PIX_END_1_LSB REG(0x00, 0xb0) /* write */ ++#define REG_VS_LINE_STRT_2_MSB REG(0x00, 0xb1) /* write */ ++#define REG_VS_LINE_STRT_2_LSB REG(0x00, 0xb2) /* write */ + #define REG_VS_PIX_STRT_2_MSB REG(0x00, 0xb3) /* write */ + #define REG_VS_PIX_STRT_2_LSB REG(0x00, 0xb4) /* write */ ++#define REG_VS_LINE_END_2_MSB REG(0x00, 0xb5) /* write */ ++#define REG_VS_LINE_END_2_LSB REG(0x00, 0xb6) /* write */ + #define REG_VS_PIX_END_2_MSB REG(0x00, 0xb7) /* write */ + #define REG_VS_PIX_END_2_LSB REG(0x00, 0xb8) /* write */ + #define REG_HS_PIX_START_MSB REG(0x00, 0xb9) /* write */ +@@ -142,21 +156,29 @@ struct tda998x_priv { + #define REG_VWIN_START_1_LSB REG(0x00, 0xbe) /* write */ + #define REG_VWIN_END_1_MSB REG(0x00, 0xbf) /* write */ + #define REG_VWIN_END_1_LSB REG(0x00, 0xc0) /* write */ ++#define REG_VWIN_START_2_MSB REG(0x00, 0xc1) /* write */ ++#define REG_VWIN_START_2_LSB REG(0x00, 0xc2) /* write */ ++#define REG_VWIN_END_2_MSB REG(0x00, 0xc3) /* write */ ++#define REG_VWIN_END_2_LSB REG(0x00, 0xc4) /* write */ + #define REG_DE_START_MSB REG(0x00, 0xc5) /* write */ + #define REG_DE_START_LSB REG(0x00, 0xc6) /* write */ + #define REG_DE_STOP_MSB REG(0x00, 0xc7) /* write */ + #define REG_DE_STOP_LSB REG(0x00, 0xc8) /* write */ + #define REG_TBG_CNTRL_0 REG(0x00, 0xca) /* write */ ++# define TBG_CNTRL_0_TOP_TGL (1 << 0) ++# define TBG_CNTRL_0_TOP_SEL (1 << 1) ++# define TBG_CNTRL_0_DE_EXT (1 << 2) ++# define TBG_CNTRL_0_TOP_EXT (1 << 3) + # define TBG_CNTRL_0_FRAME_DIS (1 << 5) + # define TBG_CNTRL_0_SYNC_MTHD (1 << 6) + # define TBG_CNTRL_0_SYNC_ONCE (1 << 7) + #define REG_TBG_CNTRL_1 REG(0x00, 0xcb) /* write */ +-# define TBG_CNTRL_1_VH_TGL_0 (1 << 0) +-# define TBG_CNTRL_1_VH_TGL_1 (1 << 1) +-# define TBG_CNTRL_1_VH_TGL_2 (1 << 2) +-# define TBG_CNTRL_1_VHX_EXT_DE (1 << 3) +-# define TBG_CNTRL_1_VHX_EXT_HS (1 << 4) +-# define TBG_CNTRL_1_VHX_EXT_VS (1 << 5) ++# define TBG_CNTRL_1_H_TGL (1 << 0) ++# define TBG_CNTRL_1_V_TGL (1 << 1) ++# define TBG_CNTRL_1_TGL_EN (1 << 2) ++# define TBG_CNTRL_1_X_EXT (1 << 3) ++# define TBG_CNTRL_1_H_EXT (1 << 4) ++# define TBG_CNTRL_1_V_EXT (1 << 5) + # define TBG_CNTRL_1_DWIN_DIS (1 << 6) + #define REG_ENABLE_SPACE REG(0x00, 0xd6) /* write */ + #define REG_HVF_CNTRL_0 REG(0x00, 0xe4) /* write */ +@@ -171,6 +193,12 @@ struct tda998x_priv { + # define HVF_CNTRL_1_PAD(x) (((x) & 3) << 4) + # define HVF_CNTRL_1_SEMI_PLANAR (1 << 6) + #define REG_RPT_CNTRL REG(0x00, 0xf0) /* write */ ++#define REG_I2S_FORMAT REG(0x00, 0xfc) /* read/write */ ++# define I2S_FORMAT(x) (((x) & 3) << 0) ++#define REG_AIP_CLKSEL REG(0x00, 0xfd) /* write */ ++# define AIP_CLKSEL_FS(x) (((x) & 3) << 0) ++# define AIP_CLKSEL_CLK_POL(x) (((x) & 1) << 2) ++# define AIP_CLKSEL_AIP(x) (((x) & 7) << 3) + + + /* Page 02h: PLL settings */ +@@ -212,6 +240,11 @@ struct tda998x_priv { + + + /* Page 10h: information frames and packets */ ++#define REG_IF1_HB0 REG(0x10, 0x20) /* read/write */ ++#define REG_IF2_HB0 REG(0x10, 0x40) /* read/write */ ++#define REG_IF3_HB0 REG(0x10, 0x60) /* read/write */ ++#define REG_IF4_HB0 REG(0x10, 0x80) /* read/write */ ++#define REG_IF5_HB0 REG(0x10, 0xa0) /* read/write */ + + + /* Page 11h: audio settings and content info packets */ +@@ -221,14 +254,39 @@ struct tda998x_priv { + # define AIP_CNTRL_0_LAYOUT (1 << 2) + # define AIP_CNTRL_0_ACR_MAN (1 << 5) + # define AIP_CNTRL_0_RST_CTS (1 << 6) ++#define REG_CA_I2S REG(0x11, 0x01) /* read/write */ ++# define CA_I2S_CA_I2S(x) (((x) & 31) << 0) ++# define CA_I2S_HBR_CHSTAT (1 << 6) ++#define REG_LATENCY_RD REG(0x11, 0x04) /* read/write */ ++#define REG_ACR_CTS_0 REG(0x11, 0x05) /* read/write */ ++#define REG_ACR_CTS_1 REG(0x11, 0x06) /* read/write */ ++#define REG_ACR_CTS_2 REG(0x11, 0x07) /* read/write */ ++#define REG_ACR_N_0 REG(0x11, 0x08) /* read/write */ ++#define REG_ACR_N_1 REG(0x11, 0x09) /* read/write */ ++#define REG_ACR_N_2 REG(0x11, 0x0a) /* read/write */ ++#define REG_CTS_N REG(0x11, 0x0c) /* read/write */ ++# define CTS_N_K(x) (((x) & 7) << 0) ++# define CTS_N_M(x) (((x) & 3) << 4) + #define REG_ENC_CNTRL REG(0x11, 0x0d) /* read/write */ + # define ENC_CNTRL_RST_ENC (1 << 0) + # define ENC_CNTRL_RST_SEL (1 << 1) + # define ENC_CNTRL_CTL_CODE(x) (((x) & 3) << 2) ++#define REG_DIP_FLAGS REG(0x11, 0x0e) /* read/write */ ++# define DIP_FLAGS_ACR (1 << 0) ++# define DIP_FLAGS_GC (1 << 1) ++#define REG_DIP_IF_FLAGS REG(0x11, 0x0f) /* read/write */ ++# define DIP_IF_FLAGS_IF1 (1 << 1) ++# define DIP_IF_FLAGS_IF2 (1 << 2) ++# define DIP_IF_FLAGS_IF3 (1 << 3) ++# define DIP_IF_FLAGS_IF4 (1 << 4) ++# define DIP_IF_FLAGS_IF5 (1 << 5) ++#define REG_CH_STAT_B(x) REG(0x11, 0x14 + (x)) /* read/write */ + + + /* Page 12h: HDCP and OTP */ + #define REG_TX3 REG(0x12, 0x9a) /* read/write */ ++#define REG_TX4 REG(0x12, 0x9b) /* read/write */ ++# define TX4_PD_RAM (1 << 1) + #define REG_TX33 REG(0x12, 0xb8) /* read/write */ + # define TX33_HDMI (1 << 1) + +@@ -338,6 +396,23 @@ fail: + return ret; + } + ++static void ++reg_write_range(struct drm_encoder *encoder, uint16_t reg, uint8_t *p, int cnt) ++{ ++ struct i2c_client *client = drm_i2c_encoder_get_client(encoder); ++ uint8_t buf[cnt+1]; ++ int ret; ++ ++ buf[0] = REG2ADDR(reg); ++ memcpy(&buf[1], p, cnt); ++ ++ set_page(encoder, reg); ++ ++ ret = i2c_master_send(client, buf, cnt + 1); ++ if (ret < 0) ++ dev_err(&client->dev, "Error %d writing to 0x%x\n", ret, reg); ++} ++ + static uint8_t + reg_read(struct drm_encoder *encoder, uint16_t reg) + { +@@ -415,11 +490,192 @@ tda998x_reset(struct drm_encoder *encoder) + reg_write(encoder, REG_PLL_SCG2, 0x10); + } + ++static uint8_t tda998x_cksum(uint8_t *buf, size_t bytes) ++{ ++ uint8_t sum = 0; ++ ++ while (bytes--) ++ sum += *buf++; ++ return (255 - sum) + 1; ++} ++ ++#define HB(x) (x) ++#define PB(x) (HB(2) + 1 + (x)) ++ ++static void ++tda998x_write_if(struct drm_encoder *encoder, uint8_t bit, uint16_t addr, ++ uint8_t *buf, size_t size) ++{ ++ buf[PB(0)] = tda998x_cksum(buf, size); ++ ++ reg_clear(encoder, REG_DIP_IF_FLAGS, bit); ++ reg_write_range(encoder, addr, buf, size); ++ reg_set(encoder, REG_DIP_IF_FLAGS, bit); ++} ++ ++static void ++tda998x_write_aif(struct drm_encoder *encoder, struct tda998x_encoder_params *p) ++{ ++ uint8_t buf[PB(5) + 1]; ++ ++ buf[HB(0)] = 0x84; ++ buf[HB(1)] = 0x01; ++ buf[HB(2)] = 10; ++ buf[PB(0)] = 0; ++ buf[PB(1)] = p->audio_frame[1] & 0x07; /* CC */ ++ buf[PB(2)] = p->audio_frame[2] & 0x1c; /* SF */ ++ buf[PB(4)] = p->audio_frame[4]; ++ buf[PB(5)] = p->audio_frame[5] & 0xf8; /* DM_INH + LSV */ ++ ++ tda998x_write_if(encoder, DIP_IF_FLAGS_IF4, REG_IF4_HB0, buf, ++ sizeof(buf)); ++} ++ ++static void ++tda998x_write_avi(struct drm_encoder *encoder, struct drm_display_mode *mode) ++{ ++ uint8_t buf[PB(13) + 1]; ++ ++ memset(buf, 0, sizeof(buf)); ++ buf[HB(0)] = 0x82; ++ buf[HB(1)] = 0x02; ++ buf[HB(2)] = 13; ++ buf[PB(4)] = drm_match_cea_mode(mode); ++ ++ tda998x_write_if(encoder, DIP_IF_FLAGS_IF2, REG_IF2_HB0, buf, ++ sizeof(buf)); ++} ++ ++static void tda998x_audio_mute(struct drm_encoder *encoder, bool on) ++{ ++ if (on) { ++ reg_set(encoder, REG_SOFTRESET, SOFTRESET_AUDIO); ++ reg_clear(encoder, REG_SOFTRESET, SOFTRESET_AUDIO); ++ reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO); ++ } else { ++ reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO); ++ } ++} ++ ++static void ++tda998x_configure_audio(struct drm_encoder *encoder, struct tda998x_encoder_params *p) ++{ ++ uint8_t buf[6], clksel_aip, clksel_fs, ca_i2s, cts_n; ++ uint32_t n; ++ ++ /* SetAudioPortConfig */ ++ reg_write(encoder, REG_ENA_AP, p->audio_cfg); ++ /* SetAudioClockPortConfig */ ++ reg_write(encoder, REG_ENA_ACLK, p->audio_clk_cfg); ++ ++ /* ++ * layout = channelAllocation ? 1 : 0; ++ * AudioInSetConfig(format, i2sFormat, channelAllocation, ++ * HDMITX_CHAN_NO_CHANGE, HDMITX_CLKPOLDSD_NO_CHANGE, ++ * HDMITX_SWAPDSD_NO_CHANGE, layout, HDMITX_LATENCY_CURRENT, ++ * dstRate) ++ */ ++ switch (p->audio_format) { ++ case AFMT_SPDIF: ++ reg_write(encoder, REG_MUX_AP, 0x40); ++ clksel_aip = AIP_CLKSEL_AIP(0); ++ /* FS64SPDIF */ ++ clksel_fs = AIP_CLKSEL_FS(2); ++ cts_n = CTS_N_M(3) | CTS_N_K(3); ++ ca_i2s = 0; ++ break; ++ ++ case AFMT_I2S: ++ reg_write(encoder, REG_MUX_AP, 0x64); ++ clksel_aip = AIP_CLKSEL_AIP(1); ++ /* ACLK */ ++ clksel_fs = AIP_CLKSEL_FS(0); ++ cts_n = CTS_N_M(3) | CTS_N_K(3); ++ ca_i2s = CA_I2S_CA_I2S(0 /* channel allocation */); ++ break; ++ } ++ ++ reg_write(encoder, REG_AIP_CLKSEL, clksel_aip); ++// reg_write(encoder, REG_CA_I2S, ca_i2s); ++// reg_write(encoder, REG_I2S_FORMAT, I2S_FORMAT(0 /* i2s format */)); ++ reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_LAYOUT); ++ /* latency? */ ++ ++ /* get video format */ ++ ++ /* ++ * ctsRef = HDMITX_CTSREF_FS64SPDIF, uCtsX = HDMITX_CTSX_64 ++ * AudioInSetCts(ctsRef, rate, VidFmt, vOutFreq, ++ * HDMITX_CTS_AUTO, uCtsX, HDMITX_CTSK_USE_CTSX, ++ * HDMITX_CTSMTS_USE_CTSX, dstRate) ++ */ ++ /* Auto CTS */ ++ reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_ACR_MAN); ++ reg_write(encoder, REG_CTS_N, cts_n); ++ reg_write(encoder, REG_AUDIO_DIV, 3); ++ ++ /* ++ * This is the approximate value of N, which happens to be ++ * the recommended values for non-coherent clocks. ++ */ ++ n = 128 * p->audio_sample_rate / 1000; ++ ++ /* Write the CTS and N values */ ++ buf[0] = 0x44; ++ buf[1] = 0x42; ++ buf[2] = 0x01; ++ buf[3] = n; ++ buf[4] = n >> 8; ++ buf[5] = n >> 16; ++ reg_write_range(encoder, REG_ACR_CTS_0, buf, 6); ++ ++ /* Set CTS clock reference */ ++ reg_write(encoder, REG_AIP_CLKSEL, clksel_aip | clksel_fs); ++ ++ /* Reset CTS generator */ ++ reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS); ++ reg_clear(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_CTS); ++ ++ /* Write the channel status */ ++ buf[0] = 0x04; ++ buf[1] = 0x00; ++ buf[2] = 0x00; ++ buf[3] = 0xf1; ++ reg_write_range(encoder, REG_CH_STAT_B(0), buf, 4); ++ ++ tda998x_audio_mute(encoder, true); ++ mdelay(20); ++ tda998x_audio_mute(encoder, false); ++ ++ /* Write the audio information packet */ ++ tda998x_write_aif(encoder, p); ++} ++ + /* DRM encoder functions */ + + static void + tda998x_encoder_set_config(struct drm_encoder *encoder, void *params) + { ++ struct tda998x_priv *priv = to_tda998x_priv(encoder); ++ struct tda998x_encoder_params *p = params; ++ ++ priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(p->swap_a) | ++ (p->mirr_a ? VIP_CNTRL_0_MIRR_A : 0) | ++ VIP_CNTRL_0_SWAP_B(p->swap_b) | ++ (p->mirr_b ? VIP_CNTRL_0_MIRR_B : 0); ++ priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(p->swap_c) | ++ (p->mirr_c ? VIP_CNTRL_1_MIRR_C : 0) | ++ VIP_CNTRL_1_SWAP_D(p->swap_d) | ++ (p->mirr_d ? VIP_CNTRL_1_MIRR_D : 0); ++ priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(p->swap_e) | ++ (p->mirr_e ? VIP_CNTRL_2_MIRR_E : 0) | ++ VIP_CNTRL_2_SWAP_F(p->swap_f) | ++ (p->mirr_f ? VIP_CNTRL_2_MIRR_F : 0); ++ ++ priv->params = *p; ++ ++ if (p->audio_cfg) ++ tda998x_configure_audio(encoder, p); + } + + static void +@@ -436,22 +692,22 @@ tda998x_encoder_dpms(struct drm_encoder *encoder, int mode) + + switch (mode) { + case DRM_MODE_DPMS_ON: ++ /* Write the default value MUX register */ ++ reg_write(encoder, REG_MUX_VP_VIP_OUT, 0x24); + /* enable audio and video ports */ +- reg_write(encoder, REG_ENA_AP, 0xff); ++// reg_write(encoder, REG_ENA_AP, priv->ena_ap); ++// reg_write(encoder, REG_ENA_ACLK, priv->ena_aclk); + reg_write(encoder, REG_ENA_VP_0, 0xff); + reg_write(encoder, REG_ENA_VP_1, 0xff); + reg_write(encoder, REG_ENA_VP_2, 0xff); + /* set muxing after enabling ports: */ +- reg_write(encoder, REG_VIP_CNTRL_0, +- VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3)); +- reg_write(encoder, REG_VIP_CNTRL_1, +- VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1)); +- reg_write(encoder, REG_VIP_CNTRL_2, +- VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5)); ++ reg_write(encoder, REG_VIP_CNTRL_0, priv->vip_cntrl_0); ++ reg_write(encoder, REG_VIP_CNTRL_1, priv->vip_cntrl_1); ++ reg_write(encoder, REG_VIP_CNTRL_2, priv->vip_cntrl_2); + break; + case DRM_MODE_DPMS_OFF: + /* disable audio and video ports */ +- reg_write(encoder, REG_ENA_AP, 0x00); ++// reg_write(encoder, REG_ENA_AP, 0x00); + reg_write(encoder, REG_ENA_VP_0, 0x00); + reg_write(encoder, REG_ENA_VP_1, 0x00); + reg_write(encoder, REG_ENA_VP_2, 0x00); +@@ -494,42 +750,77 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, + struct drm_display_mode *adjusted_mode) + { + struct tda998x_priv *priv = to_tda998x_priv(encoder); +- uint16_t hs_start, hs_end, line_start, line_end; +- uint16_t vwin_start, vwin_end, de_start, de_end; +- uint16_t ref_pix, ref_line, pix_start2; ++ uint16_t ref_pix, ref_line, n_pix, n_line; ++ uint16_t hs_pix_s, hs_pix_e; ++ uint16_t vs1_pix_s, vs1_pix_e, vs1_line_s, vs1_line_e; ++ uint16_t vs2_pix_s, vs2_pix_e, vs2_line_s, vs2_line_e; ++ uint16_t vwin1_line_s, vwin1_line_e; ++ uint16_t vwin2_line_s, vwin2_line_e; ++ uint16_t de_pix_s, de_pix_e; + uint8_t reg, div, rep; + +- hs_start = mode->hsync_start - mode->hdisplay; +- hs_end = mode->hsync_end - mode->hdisplay; +- line_start = 1; +- line_end = 1 + mode->vsync_end - mode->vsync_start; +- vwin_start = mode->vtotal - mode->vsync_start; +- vwin_end = vwin_start + mode->vdisplay; +- de_start = mode->htotal - mode->hdisplay; +- de_end = mode->htotal; +- +- pix_start2 = 0; +- if (mode->flags & DRM_MODE_FLAG_INTERLACE) +- pix_start2 = (mode->htotal / 2) + hs_start; +- +- /* TODO how is this value calculated? It is 2 for all common +- * formats in the tables in out of tree nxp driver (assuming +- * I've properly deciphered their byzantine table system) ++ /* ++ * Internally TDA998x is using ITU-R BT.656 style sync but ++ * we get VESA style sync. TDA998x is using a reference pixel ++ * relative to ITU to sync to the input frame and for output ++ * sync generation. ++ * ++ * Now there is some issues to take care of: ++ * - HDMI data islands require sync-before-active ++ * - TDA998x register values must be > 0 to be enabled ++ * - REFLINE needs an additional offset of +1 ++ * - REFPIX needs an addtional offset of +1 for UYUV and +3 for RGB ++ * ++ * So we add +1 to all horizontal and vertical register values, ++ * plus an additional +3 for REFPIX as we are using RGB input only. + */ +- ref_line = 2; ++ n_pix = mode->htotal; ++ n_line = mode->vtotal; + +- /* this might changes for other color formats from the CRTC: */ +- ref_pix = 3 + hs_start; ++ ref_pix = 3 + mode->hsync_start - mode->hdisplay; + +- div = 148500 / mode->clock; ++ /* ++ * handle issue on TILCDC where it is outputing ++ * non-VESA compliant sync signals the workaround ++ * forces us to invert the HSYNC, so need to adjust display to ++ * the left by hskew pixels, provided by the tilcdc driver ++ */ ++ if(adjusted_mode && adjusted_mode->flags & DRM_MODE_FLAG_HSKEW) ++ ref_pix += adjusted_mode->hskew; ++ ++ de_pix_s = mode->htotal - mode->hdisplay; ++ de_pix_e = de_pix_s + mode->hdisplay; ++ hs_pix_s = mode->hsync_start - mode->hdisplay; ++ hs_pix_e = hs_pix_s + mode->hsync_end - mode->hsync_start; ++ ++ if ((mode->flags & DRM_MODE_FLAG_INTERLACE) == 0) { ++ ref_line = 1 + mode->vsync_start - mode->vdisplay; ++ vwin1_line_s = mode->vtotal - mode->vdisplay - 1; ++ vwin1_line_e = vwin1_line_s + mode->vdisplay; ++ vs1_pix_s = vs1_pix_e = hs_pix_s; ++ vs1_line_s = mode->vsync_start - mode->vdisplay; ++ vs1_line_e = vs1_line_s + ++ mode->vsync_end - mode->vsync_start; ++ vwin2_line_s = vwin2_line_e = 0; ++ vs2_pix_s = vs2_pix_e = 0; ++ vs2_line_s = vs2_line_e = 0; ++ } else { ++ ref_line = 1 + (mode->vsync_start - mode->vdisplay)/2; ++ vwin1_line_s = (mode->vtotal - mode->vdisplay)/2; ++ vwin1_line_e = vwin1_line_s + mode->vdisplay/2; ++ vs1_pix_s = vs1_pix_e = hs_pix_s; ++ vs1_line_s = (mode->vsync_start - mode->vdisplay)/2; ++ vs1_line_e = vs1_line_s + ++ (mode->vsync_end - mode->vsync_start)/2; ++ vwin2_line_s = vwin1_line_s + mode->vtotal/2; ++ vwin2_line_e = vwin2_line_s + mode->vdisplay/2; ++ vs2_pix_s = vs2_pix_e = hs_pix_s + mode->htotal/2; ++ vs2_line_s = vs1_line_s + mode->vtotal/2 ; ++ vs2_line_e = vs2_line_s + ++ (mode->vsync_end - mode->vsync_start)/2; ++ } + +- DBG("clock=%d, div=%u", mode->clock, div); +- DBG("hs_start=%u, hs_end=%u, line_start=%u, line_end=%u", +- hs_start, hs_end, line_start, line_end); +- DBG("vwin_start=%u, vwin_end=%u, de_start=%u, de_end=%u", +- vwin_start, vwin_end, de_start, de_end); +- DBG("ref_line=%u, ref_pix=%u, pix_start2=%u", +- ref_line, ref_pix, pix_start2); ++ div = 148500 / mode->clock; + + /* mute the audio FIFO: */ + reg_set(encoder, REG_AIP_CNTRL_0, AIP_CNTRL_0_RST_FIFO); +@@ -561,9 +852,6 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, + reg_write(encoder, REG_PLL_SERIAL_2, PLL_SERIAL_2_SRL_NOSC(div) | + PLL_SERIAL_2_SRL_PR(rep)); + +- reg_write16(encoder, REG_VS_PIX_STRT_2_MSB, pix_start2); +- reg_write16(encoder, REG_VS_PIX_END_2_MSB, pix_start2); +- + /* set color matrix bypass flag: */ + reg_set(encoder, REG_MAT_CONTRL, MAT_CONTRL_MAT_BP); + +@@ -572,47 +860,74 @@ tda998x_encoder_mode_set(struct drm_encoder *encoder, + + reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_MTHD); + ++ /* ++ * Sync on rising HSYNC/VSYNC ++ */ + reg_write(encoder, REG_VIP_CNTRL_3, 0); + reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_SYNC_HS); ++ ++ /* ++ * TDA19988 requires high-active sync at input stage, ++ * so invert low-active sync provided by master encoder here ++ */ ++ if (mode->flags & DRM_MODE_FLAG_NHSYNC) ++ reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL); + if (mode->flags & DRM_MODE_FLAG_NVSYNC) + reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_V_TGL); + ++ /* ++ * Always generate sync polarity relative to input sync and ++ * revert input stage toggled sync at output stage ++ */ ++ reg = TBG_CNTRL_1_TGL_EN; + if (mode->flags & DRM_MODE_FLAG_NHSYNC) +- reg_set(encoder, REG_VIP_CNTRL_3, VIP_CNTRL_3_H_TGL); ++ reg |= TBG_CNTRL_1_H_TGL; ++ if (mode->flags & DRM_MODE_FLAG_NVSYNC) ++ reg |= TBG_CNTRL_1_V_TGL; ++ reg_write(encoder, REG_TBG_CNTRL_1, reg); + + reg_write(encoder, REG_VIDFORMAT, 0x00); +- reg_write16(encoder, REG_NPIX_MSB, mode->hdisplay - 1); +- reg_write16(encoder, REG_NLINE_MSB, mode->vdisplay - 1); +- reg_write16(encoder, REG_VS_LINE_STRT_1_MSB, line_start); +- reg_write16(encoder, REG_VS_LINE_END_1_MSB, line_end); +- reg_write16(encoder, REG_VS_PIX_STRT_1_MSB, hs_start); +- reg_write16(encoder, REG_VS_PIX_END_1_MSB, hs_start); +- reg_write16(encoder, REG_HS_PIX_START_MSB, hs_start); +- reg_write16(encoder, REG_HS_PIX_STOP_MSB, hs_end); +- reg_write16(encoder, REG_VWIN_START_1_MSB, vwin_start); +- reg_write16(encoder, REG_VWIN_END_1_MSB, vwin_end); +- reg_write16(encoder, REG_DE_START_MSB, de_start); +- reg_write16(encoder, REG_DE_STOP_MSB, de_end); ++ reg_write16(encoder, REG_REFPIX_MSB, ref_pix); ++ reg_write16(encoder, REG_REFLINE_MSB, ref_line); ++ reg_write16(encoder, REG_NPIX_MSB, n_pix); ++ reg_write16(encoder, REG_NLINE_MSB, n_line); ++ reg_write16(encoder, REG_VS_LINE_STRT_1_MSB, vs1_line_s); ++ reg_write16(encoder, REG_VS_PIX_STRT_1_MSB, vs1_pix_s); ++ reg_write16(encoder, REG_VS_LINE_END_1_MSB, vs1_line_e); ++ reg_write16(encoder, REG_VS_PIX_END_1_MSB, vs1_pix_e); ++ reg_write16(encoder, REG_VS_LINE_STRT_2_MSB, vs2_line_s); ++ reg_write16(encoder, REG_VS_PIX_STRT_2_MSB, vs2_pix_s); ++ reg_write16(encoder, REG_VS_LINE_END_2_MSB, vs2_line_e); ++ reg_write16(encoder, REG_VS_PIX_END_2_MSB, vs2_pix_e); ++ reg_write16(encoder, REG_HS_PIX_START_MSB, hs_pix_s); ++ reg_write16(encoder, REG_HS_PIX_STOP_MSB, hs_pix_e); ++ reg_write16(encoder, REG_VWIN_START_1_MSB, vwin1_line_s); ++ reg_write16(encoder, REG_VWIN_END_1_MSB, vwin1_line_e); ++ reg_write16(encoder, REG_VWIN_START_2_MSB, vwin2_line_s); ++ reg_write16(encoder, REG_VWIN_END_2_MSB, vwin2_line_e); ++ reg_write16(encoder, REG_DE_START_MSB, de_pix_s); ++ reg_write16(encoder, REG_DE_STOP_MSB, de_pix_e); + + if (priv->rev == TDA19988) { + /* let incoming pixels fill the active space (if any) */ + reg_write(encoder, REG_ENABLE_SPACE, 0x01); + } + +- reg_write16(encoder, REG_REFPIX_MSB, ref_pix); +- reg_write16(encoder, REG_REFLINE_MSB, ref_line); +- +- reg = TBG_CNTRL_1_VHX_EXT_DE | +- TBG_CNTRL_1_VHX_EXT_HS | +- TBG_CNTRL_1_VHX_EXT_VS | +- TBG_CNTRL_1_DWIN_DIS | /* HDCP off */ +- TBG_CNTRL_1_VH_TGL_2; +- if (mode->flags & (DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC)) +- reg |= TBG_CNTRL_1_VH_TGL_0; +- reg_set(encoder, REG_TBG_CNTRL_1, reg); +- + /* must be last register set: */ + reg_clear(encoder, REG_TBG_CNTRL_0, TBG_CNTRL_0_SYNC_ONCE); ++ ++ /* Only setup the info frames if the sink is HDMI */ ++ if (priv->is_hdmi_sink) { ++ /* We need to turn HDMI HDCP stuff on to get audio through */ ++ reg_clear(encoder, REG_TBG_CNTRL_1, TBG_CNTRL_1_DWIN_DIS); ++ reg_write(encoder, REG_ENC_CNTRL, ENC_CNTRL_CTL_CODE(1)); ++ reg_set(encoder, REG_TX33, TX33_HDMI); ++ ++ tda998x_write_avi(encoder, adjusted_mode); ++ ++ if (priv->params.audio_cfg) ++ tda998x_configure_audio(encoder, &priv->params); ++ } + } + + static enum drm_connector_status +@@ -673,6 +988,7 @@ read_edid_block(struct drm_encoder *encoder, uint8_t *buf, int blk) + static uint8_t * + do_get_edid(struct drm_encoder *encoder) + { ++ struct tda998x_priv *priv = to_tda998x_priv(encoder); + int j = 0, valid_extensions = 0; + uint8_t *block, *new; + bool print_bad_edid = drm_debug & DRM_UT_KMS; +@@ -680,6 +996,9 @@ do_get_edid(struct drm_encoder *encoder) + if ((block = kmalloc(EDID_LENGTH, GFP_KERNEL)) == NULL) + return NULL; + ++ if (priv->rev == TDA19988) ++ reg_clear(encoder, REG_TX4, TX4_PD_RAM); ++ + /* base block fetch */ + if (read_edid_block(encoder, block, 0)) + goto fail; +@@ -689,7 +1008,7 @@ do_get_edid(struct drm_encoder *encoder) + + /* if there's no extensions, we're done */ + if (block[0x7e] == 0) +- return block; ++ goto done; + + new = krealloc(block, (block[0x7e] + 1) * EDID_LENGTH, GFP_KERNEL); + if (!new) +@@ -716,9 +1035,15 @@ do_get_edid(struct drm_encoder *encoder) + block = new; + } + ++done: ++ if (priv->rev == TDA19988) ++ reg_set(encoder, REG_TX4, TX4_PD_RAM); ++ + return block; + + fail: ++ if (priv->rev == TDA19988) ++ reg_set(encoder, REG_TX4, TX4_PD_RAM); + dev_warn(encoder->dev->dev, "failed to read EDID\n"); + kfree(block); + return NULL; +@@ -728,12 +1053,14 @@ static int + tda998x_encoder_get_modes(struct drm_encoder *encoder, + struct drm_connector *connector) + { ++ struct tda998x_priv *priv = to_tda998x_priv(encoder); + struct edid *edid = (struct edid *)do_get_edid(encoder); + int n = 0; + + if (edid) { + drm_mode_connector_update_edid_property(connector, edid); + n = drm_add_edid_modes(connector, edid); ++ priv->is_hdmi_sink = drm_detect_hdmi_monitor(edid); + kfree(edid); + } + +@@ -795,6 +1122,40 @@ tda998x_remove(struct i2c_client *client) + return 0; + } + ++static ssize_t i2c_read_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct drm_encoder *encoder = dev_get_drvdata(dev); ++ unsigned int page, addr; ++ unsigned char val; ++ ++ sscanf(buf, "%x %x", &page, &addr); ++ ++ val = reg_read(encoder, REG(page, addr)); ++ ++ printk("i2c read %02x @ page:%02x address:%02x\n", val, page, addr); ++ return size; ++} ++ ++static ssize_t i2c_write_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t size) ++{ ++ struct drm_encoder *encoder = dev_get_drvdata(dev); ++ unsigned int page, addr, mask, val; ++ unsigned char rval; ++ ++ sscanf(buf, "%x %x %x %x", &page, &addr, &mask, &val); ++ ++ rval = reg_read(encoder, REG(page, addr)); ++ rval &= ~mask; ++ rval |= val & mask; ++ reg_write(encoder, REG(page, addr), rval); ++ ++ printk("i2c write %02x @ page:%02x address:%02x\n", rval, page, addr); ++ return size; ++} ++ ++static DEVICE_ATTR(i2c_read, S_IWUSR, NULL, i2c_read_store); ++static DEVICE_ATTR(i2c_write, S_IWUSR, NULL, i2c_write_store); ++ + static int + tda998x_encoder_init(struct i2c_client *client, + struct drm_device *dev, +@@ -802,11 +1163,20 @@ tda998x_encoder_init(struct i2c_client *client, + { + struct drm_encoder *encoder = &encoder_slave->base; + struct tda998x_priv *priv; ++/* debug */ ++ device_create_file(&client->dev, &dev_attr_i2c_read); ++ device_create_file(&client->dev, &dev_attr_i2c_write); ++ dev_set_drvdata(&client->dev, encoder); ++/* debug end */ + + priv = kzalloc(sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; + ++ priv->vip_cntrl_0 = VIP_CNTRL_0_SWAP_A(2) | VIP_CNTRL_0_SWAP_B(3); ++ priv->vip_cntrl_1 = VIP_CNTRL_1_SWAP_C(0) | VIP_CNTRL_1_SWAP_D(1); ++ priv->vip_cntrl_2 = VIP_CNTRL_2_SWAP_E(4) | VIP_CNTRL_2_SWAP_F(5); ++ + priv->current_page = 0; + priv->cec = i2c_new_dummy(client->adapter, 0x34); + priv->dpms = DRM_MODE_DPMS_OFF; +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +index 7418dcd..2aab53e 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_crtc.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_crtc.c +@@ -69,7 +69,6 @@ static void set_scanout(struct drm_crtc *crtc, int n) + struct tilcdc_crtc *tilcdc_crtc = to_tilcdc_crtc(crtc); + struct drm_device *dev = crtc->dev; + +- pm_runtime_get_sync(dev->dev); + tilcdc_write(dev, base_reg[n], tilcdc_crtc->start); + tilcdc_write(dev, ceil_reg[n], tilcdc_crtc->end); + if (tilcdc_crtc->scanout[n]) { +@@ -85,7 +84,6 @@ static void set_scanout(struct drm_crtc *crtc, int n) + tilcdc_crtc->scanout[n] = crtc->fb; + drm_framebuffer_reference(tilcdc_crtc->scanout[n]); + tilcdc_crtc->dirty &= ~stat[n]; +- pm_runtime_put_sync(dev->dev); + } + + static void update_scanout(struct drm_crtc *crtc) +@@ -168,7 +166,9 @@ static int tilcdc_crtc_page_flip(struct drm_crtc *crtc, + + crtc->fb = fb; + tilcdc_crtc->event = event; ++ pm_runtime_get_sync(dev->dev); + update_scanout(crtc); ++ pm_runtime_put_sync(dev->dev); + + return 0; + } +@@ -379,7 +379,12 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, + else + tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_SYNC_EDGE); + +- if (mode->flags & DRM_MODE_FLAG_NHSYNC) ++ /* ++ * use value from adjusted_mode here as this might have been changed as part ++ * of the fixup for NXP TDA998x to solve the issue where tilcdc timings are ++ * not VESA compliant ++ */ ++ if (adjusted_mode->flags & DRM_MODE_FLAG_NHSYNC) + tilcdc_set(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); + else + tilcdc_clear(dev, LCDC_RASTER_TIMING_2_REG, LCDC_INVERT_HSYNC); +@@ -406,7 +411,11 @@ static int tilcdc_crtc_mode_set(struct drm_crtc *crtc, + static int tilcdc_crtc_mode_set_base(struct drm_crtc *crtc, int x, int y, + struct drm_framebuffer *old_fb) + { ++ struct drm_device *dev = crtc->dev; ++ ++ pm_runtime_get_sync(dev->dev); + update_scanout(crtc); ++ pm_runtime_put_sync(dev->dev); + return 0; + } + +@@ -686,3 +695,59 @@ fail: + tilcdc_crtc_destroy(crtc); + return NULL; + } ++ ++struct tilcdc_panel_info *tilcdc_of_get_panel_info(struct device_node *np) ++{ ++ struct device_node *info_np; ++ struct tilcdc_panel_info *info; ++ int ret = 0; ++ ++ if (!np) ++ return NULL; ++ ++ info_np = of_get_child_by_name(np, "panel-info"); ++ if (!info_np) { ++ pr_err("%s: could not find panel-info node\n", ++ of_node_full_name(np)); ++ return NULL; ++ } ++ ++ info = kzalloc(sizeof(*info), GFP_KERNEL); ++ if (!info) { ++ pr_err("%s: allocation failed\n", ++ of_node_full_name(np)); ++ goto err_no_mem; ++ } ++ ++ ret |= of_property_read_u32(info_np, "ac-bias", &info->ac_bias); ++ ret |= of_property_read_u32(info_np, "ac-bias-intrpt", &info->ac_bias_intrpt); ++ ret |= of_property_read_u32(info_np, "dma-burst-sz", &info->dma_burst_sz); ++ ret |= of_property_read_u32(info_np, "bpp", &info->bpp); ++ ret |= of_property_read_u32(info_np, "fdd", &info->fdd); ++ ret |= of_property_read_u32(info_np, "sync-edge", &info->sync_edge); ++ ret |= of_property_read_u32(info_np, "sync-ctrl", &info->sync_ctrl); ++ ret |= of_property_read_u32(info_np, "raster-order", &info->raster_order); ++ ret |= of_property_read_u32(info_np, "fifo-th", &info->fifo_th); ++ ++ /* optional: */ ++ info->tft_alt_mode = of_property_read_bool(info_np, "tft-alt-mode"); ++ info->invert_pxl_clk = of_property_read_bool(info_np, "invert-pxl-clk"); ++ ++ if (ret) { ++ pr_err("%s: error reading panel-info properties\n", ++ of_node_full_name(info_np)); ++ goto err_bad_prop; ++ } ++ ++ /* release ref */ ++ of_node_put(info_np); ++ ++ return info; ++ ++err_bad_prop: ++ kfree(info); ++err_no_mem: ++ of_node_put(info_np); ++ return NULL; ++} ++ +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.h b/drivers/gpu/drm/tilcdc/tilcdc_drv.h +index 0938036..f5f00f1 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.h ++++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.h +@@ -43,7 +43,7 @@ + * with optimized DDR & EMIF settings tweaked 1920x1080@24 appears to + * be supportable + */ +-#define TILCDC_DEFAULT_MAX_BANDWIDTH (1280*1024*60) ++#define TILCDC_DEFAULT_MAX_BANDWIDTH (1680*1050*60) + + + struct tilcdc_drm_private { +@@ -170,4 +170,7 @@ void tilcdc_crtc_set_panel_info(struct drm_crtc *crtc, + int tilcdc_crtc_mode_valid(struct drm_crtc *crtc, struct drm_display_mode *mode); + int tilcdc_crtc_max_width(struct drm_crtc *crtc); + ++/* OF helper for reading panel info */ ++struct tilcdc_panel_info *tilcdc_of_get_panel_info(struct device_node *np); ++ + #endif /* __TILCDC_DRV_H__ */ +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_panel.c b/drivers/gpu/drm/tilcdc/tilcdc_panel.c +index 86c6732..284c9ee 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_panel.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_panel.c +@@ -304,53 +304,6 @@ static const struct tilcdc_module_ops panel_module_ops = { + * Device: + */ + +-/* maybe move this somewhere common if it is needed by other outputs? */ +-static struct tilcdc_panel_info *of_get_panel_info(struct device_node *np) +-{ +- struct device_node *info_np; +- struct tilcdc_panel_info *info; +- int ret = 0; +- +- if (!np) { +- pr_err("%s: no devicenode given\n", __func__); +- return NULL; +- } +- +- info_np = of_get_child_by_name(np, "panel-info"); +- if (!info_np) { +- pr_err("%s: could not find panel-info node\n", __func__); +- return NULL; +- } +- +- info = kzalloc(sizeof(*info), GFP_KERNEL); +- if (!info) { +- pr_err("%s: allocation failed\n", __func__); +- return NULL; +- } +- +- ret |= of_property_read_u32(info_np, "ac-bias", &info->ac_bias); +- ret |= of_property_read_u32(info_np, "ac-bias-intrpt", &info->ac_bias_intrpt); +- ret |= of_property_read_u32(info_np, "dma-burst-sz", &info->dma_burst_sz); +- ret |= of_property_read_u32(info_np, "bpp", &info->bpp); +- ret |= of_property_read_u32(info_np, "fdd", &info->fdd); +- ret |= of_property_read_u32(info_np, "sync-edge", &info->sync_edge); +- ret |= of_property_read_u32(info_np, "sync-ctrl", &info->sync_ctrl); +- ret |= of_property_read_u32(info_np, "raster-order", &info->raster_order); +- ret |= of_property_read_u32(info_np, "fifo-th", &info->fifo_th); +- +- /* optional: */ +- info->tft_alt_mode = of_property_read_bool(info_np, "tft-alt-mode"); +- info->invert_pxl_clk = of_property_read_bool(info_np, "invert-pxl-clk"); +- +- if (ret) { +- pr_err("%s: error reading panel-info properties\n", __func__); +- kfree(info); +- return NULL; +- } +- +- return info; +-} +- + static struct of_device_id panel_of_match[]; + + static int panel_probe(struct platform_device *pdev) +@@ -387,7 +340,7 @@ static int panel_probe(struct platform_device *pdev) + goto fail; + } + +- panel_mod->info = of_get_panel_info(node); ++ panel_mod->info = tilcdc_of_get_panel_info(node); + if (!panel_mod->info) { + dev_err(&pdev->dev, "could not get panel info\n"); + goto fail; +diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c +index dfffaf0..4bdc9ba 100644 +--- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c ++++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c +@@ -25,23 +25,11 @@ + + struct slave_module { + struct tilcdc_module base; ++ struct tilcdc_panel_info *info; + struct i2c_adapter *i2c; + }; + #define to_slave_module(x) container_of(x, struct slave_module, base) + +-static const struct tilcdc_panel_info slave_info = { +- .bpp = 16, +- .ac_bias = 255, +- .ac_bias_intrpt = 0, +- .dma_burst_sz = 16, +- .fdd = 0x80, +- .tft_alt_mode = 0, +- .sync_edge = 0, +- .sync_ctrl = 1, +- .raster_order = 0, +-}; +- +- + /* + * Encoder: + */ +@@ -69,17 +57,38 @@ static void slave_encoder_destroy(struct drm_encoder *encoder) + + static void slave_encoder_prepare(struct drm_encoder *encoder) + { ++ struct slave_encoder *slave_encoder = to_slave_encoder(encoder); ++ + drm_i2c_encoder_prepare(encoder); +- tilcdc_crtc_set_panel_info(encoder->crtc, &slave_info); ++ tilcdc_crtc_set_panel_info(encoder->crtc, slave_encoder->mod->info); ++} ++ ++static bool slave_encoder_fixup(struct drm_encoder *encoder, ++ const struct drm_display_mode *mode, ++ struct drm_display_mode *adjusted_mode) ++{ ++ adjusted_mode->hskew = mode->hsync_end - mode->hsync_start; ++ adjusted_mode->flags |= DRM_MODE_FLAG_HSKEW; ++ ++ if(mode->flags & DRM_MODE_FLAG_NHSYNC) { ++ adjusted_mode->flags |= DRM_MODE_FLAG_PHSYNC; ++ adjusted_mode->flags &= ~DRM_MODE_FLAG_NHSYNC; ++ } else { ++ adjusted_mode->flags |= DRM_MODE_FLAG_NHSYNC; ++ adjusted_mode->flags &= ~DRM_MODE_FLAG_PHSYNC; ++ } ++ ++ return drm_i2c_encoder_mode_fixup(encoder, mode, adjusted_mode); + } + ++ + static const struct drm_encoder_funcs slave_encoder_funcs = { + .destroy = slave_encoder_destroy, + }; + + static const struct drm_encoder_helper_funcs slave_encoder_helper_funcs = { + .dpms = drm_i2c_encoder_dpms, +- .mode_fixup = drm_i2c_encoder_mode_fixup, ++ .mode_fixup = slave_encoder_fixup, + .prepare = slave_encoder_prepare, + .commit = drm_i2c_encoder_commit, + .mode_set = drm_i2c_encoder_mode_set, +@@ -276,6 +285,7 @@ static void slave_destroy(struct tilcdc_module *mod) + struct slave_module *slave_mod = to_slave_module(mod); + + tilcdc_module_cleanup(mod); ++ kfree(slave_mod->info); + kfree(slave_mod); + } + +@@ -330,13 +340,25 @@ static int slave_probe(struct platform_device *pdev) + return ret; + } + +- slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL); +- if (!slave_mod) +- return -ENOMEM; ++ slave_mod = devm_kzalloc(&pdev->dev, sizeof(*slave_mod), GFP_KERNEL); ++ if (!slave_mod) { ++ tilcdc_slave_probedefer(false); ++ dev_err(&pdev->dev, "could not allocate slave_mod\n"); ++ return -ENOMEM; ++ } ++ ++ platform_set_drvdata(pdev, slave_mod); ++ ++ slave_mod->info = tilcdc_of_get_panel_info(node); ++ if (!slave_mod->info) { ++ tilcdc_slave_probedefer(false); ++ dev_err(&pdev->dev, "could not get panel info\n"); ++ return ret; ++ } + + mod = &slave_mod->base; + +- mod->preferred_bpp = slave_info.bpp; ++ mod->preferred_bpp = slave_mod->info->bpp; + + slave_mod->i2c = slavei2c; + +@@ -353,6 +375,11 @@ static int slave_probe(struct platform_device *pdev) + + static int slave_remove(struct platform_device *pdev) + { ++ struct slave_module *slave_mod = platform_get_drvdata(pdev); ++ ++ put_device(&slave_mod->i2c->dev); ++ kfree(slave_mod->info); ++ + return 0; + } + +diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c +index 5d4fd69..7e0474d 100644 +--- a/drivers/misc/eeprom/at24.c ++++ b/drivers/misc/eeprom/at24.c +@@ -23,6 +23,7 @@ + #include + #include + #include ++#include + + /* + * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable. +@@ -658,6 +659,27 @@ static int at24_remove(struct i2c_client *client) + return 0; + } + ++static int at24_command(struct i2c_client *client, unsigned int cmd, void *arg) ++{ ++ struct at24_data *at24; ++ const struct memory_accessor **maccp; ++ ++ /* only supporting a single command */ ++ if (cmd != I2C_EEPROM_GET_MEMORY_ACCESSOR) ++ return -ENOTSUPP; ++ ++ /* rudimentary check */ ++ if (arg == NULL) ++ return -EINVAL; ++ ++ at24 = i2c_get_clientdata(client); ++ ++ maccp = arg; ++ *maccp = &at24->macc; ++ ++ return 0; ++} ++ + /*-------------------------------------------------------------------------*/ + + static struct i2c_driver at24_driver = { +@@ -668,6 +690,7 @@ static struct i2c_driver at24_driver = { + .probe = at24_probe, + .remove = at24_remove, + .id_table = at24_ids, ++ .command = at24_command, + }; + + static int __init at24_init(void) +diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c +index 1865321..1fe7469 100644 +--- a/drivers/mmc/host/omap_hsmmc.c ++++ b/drivers/mmc/host/omap_hsmmc.c +@@ -40,6 +40,8 @@ + #include + #include + #include ++#include ++#include + + /* OMAP HSMMC Host Controller Registers */ + #define OMAP_HSMMC_SYSSTATUS 0x0014 +@@ -171,7 +173,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 +182,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) +@@ -391,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) +@@ -420,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: +@@ -433,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)) +@@ -787,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); +@@ -803,7 +831,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 +855,36 @@ 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; + ++ BUG_ON(mrq == NULL); ++ + 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 +901,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 +917,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 +931,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 +949,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 +968,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 +1070,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 +1126,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 +1270,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 +1289,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 +1372,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 +1406,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 +1526,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) { + /* +@@ -1719,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); +@@ -1736,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; +@@ -1776,6 +1866,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); +@@ -1801,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) +@@ -1825,13 +1920,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); + +@@ -1892,6 +1987,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; +@@ -1952,6 +2057,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); +diff --git a/drivers/of/device.c b/drivers/of/device.c +index f685e55..b4b95c6 100644 +--- a/drivers/of/device.c ++++ b/drivers/of/device.c +@@ -63,6 +63,9 @@ int of_device_add(struct platform_device *ofdev) + if (!ofdev->dev.parent) + set_dev_node(&ofdev->dev, of_node_to_nid(ofdev->dev.of_node)); + ++ /* make sure we add the resources to the appropriate lists */ ++ platform_device_link_resources(ofdev); ++ + return device_add(&ofdev->dev); + } + +diff --git a/drivers/of/of_i2c.c b/drivers/of/of_i2c.c +index b667264..116a5e0 100644 +--- a/drivers/of/of_i2c.c ++++ b/drivers/of/of_i2c.c +@@ -17,10 +17,64 @@ + #include + #include + #include ++#include ++ ++struct i2c_client * ++of_i2c_register_device(struct i2c_adapter *adap, ++ struct device_node *node) ++{ ++ struct i2c_client *result; ++ struct i2c_board_info info = {}; ++ struct dev_archdata dev_ad = {}; ++ const __be32 *addr; ++ int len; ++ ++ dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); ++ ++ if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { ++ dev_err(&adap->dev, "of_i2c: modalias failure on %s\n", ++ node->full_name); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ addr = of_get_property(node, "reg", &len); ++ if (!addr || (len < sizeof(int))) { ++ dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", ++ node->full_name); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ info.addr = be32_to_cpup(addr); ++ if (info.addr > (1 << 10) - 1) { ++ dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", ++ info.addr, node->full_name); ++ return ERR_PTR(-EINVAL); ++ } ++ ++ info.irq = irq_of_parse_and_map(node, 0); ++ info.of_node = of_node_get(node); ++ info.archdata = &dev_ad; ++ ++ if (of_get_property(node, "wakeup-source", NULL)) ++ info.flags |= I2C_CLIENT_WAKE; ++ ++ request_module("%s%s", I2C_MODULE_PREFIX, info.type); ++ ++ result = i2c_new_device(adap, &info); ++ if (result == NULL) { ++ dev_err(&adap->dev, "of_i2c: Failure registering %s\n", ++ node->full_name); ++ of_node_put(node); ++ irq_dispose_mapping(info.irq); ++ return ERR_PTR(-ENODEV); ++ } ++ ++ return result; ++} ++EXPORT_SYMBOL(of_i2c_register_device); + + void of_i2c_register_devices(struct i2c_adapter *adap) + { +- void *result; + struct device_node *node; + + /* Only register child devices if the adapter has a node pointer set */ +@@ -29,52 +83,8 @@ void of_i2c_register_devices(struct i2c_adapter *adap) + + dev_dbg(&adap->dev, "of_i2c: walking child nodes\n"); + +- for_each_available_child_of_node(adap->dev.of_node, node) { +- struct i2c_board_info info = {}; +- struct dev_archdata dev_ad = {}; +- const __be32 *addr; +- int len; +- +- dev_dbg(&adap->dev, "of_i2c: register %s\n", node->full_name); +- +- if (of_modalias_node(node, info.type, sizeof(info.type)) < 0) { +- dev_err(&adap->dev, "of_i2c: modalias failure on %s\n", +- node->full_name); +- continue; +- } +- +- addr = of_get_property(node, "reg", &len); +- if (!addr || (len < sizeof(int))) { +- dev_err(&adap->dev, "of_i2c: invalid reg on %s\n", +- node->full_name); +- continue; +- } +- +- info.addr = be32_to_cpup(addr); +- if (info.addr > (1 << 10) - 1) { +- dev_err(&adap->dev, "of_i2c: invalid addr=%x on %s\n", +- info.addr, node->full_name); +- continue; +- } +- +- info.irq = irq_of_parse_and_map(node, 0); +- info.of_node = of_node_get(node); +- info.archdata = &dev_ad; +- +- if (of_get_property(node, "wakeup-source", NULL)) +- info.flags |= I2C_CLIENT_WAKE; +- +- request_module("%s%s", I2C_MODULE_PREFIX, info.type); +- +- result = i2c_new_device(adap, &info); +- if (result == NULL) { +- dev_err(&adap->dev, "of_i2c: Failure registering %s\n", +- node->full_name); +- of_node_put(node); +- irq_dispose_mapping(info.irq); +- continue; +- } +- } ++ for_each_available_child_of_node(adap->dev.of_node, node) ++ of_i2c_register_device(adap, node); + } + EXPORT_SYMBOL(of_i2c_register_devices); + +diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c +index 7323cca..ff08c27 100644 +--- a/drivers/pinctrl/pinctrl-single.c ++++ b/drivers/pinctrl/pinctrl-single.c +@@ -1662,7 +1662,17 @@ static struct platform_driver pcs_driver = { + #endif + }; + +-module_platform_driver(pcs_driver); ++static int __init pcs_init(void) ++{ ++ return platform_driver_register(&pcs_driver); ++} ++postcore_initcall(pcs_init); ++ ++static void __exit pcs_exit(void) ++{ ++ platform_driver_unregister(&pcs_driver); ++} ++module_exit(pcs_exit); + + MODULE_AUTHOR("Tony Lindgren "); + MODULE_DESCRIPTION("One-register-per-pin type device tree based pinctrl driver"); +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 ++#include ++#include ++#include ++#include ++#include ++#include ++ ++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 "); ++MODULE_DESCRIPTION("gpio reset controller"); ++MODULE_LICENSE("GPL"); ++MODULE_ALIAS("platform:gpio-reset"); ++MODULE_DEVICE_TABLE(of, gpio_reset_dt_ids); +diff --git a/drivers/usb/Makefile b/drivers/usb/Makefile +index 238c5d4..2b3132e 100644 +--- a/drivers/usb/Makefile ++++ b/drivers/usb/Makefile +@@ -45,7 +45,7 @@ obj-$(CONFIG_USB_MICROTEK) += image/ + obj-$(CONFIG_USB_SERIAL) += serial/ + + obj-$(CONFIG_USB) += misc/ +-obj-$(CONFIG_USB_PHY) += phy/ ++obj-$(CONFIG_USB_SUPPORT) += phy/ + obj-$(CONFIG_EARLY_PRINTK_DBGP) += early/ + + obj-$(CONFIG_USB_ATM) += atm/ +diff --git a/drivers/usb/dwc3/dwc3-exynos.c b/drivers/usb/dwc3/dwc3-exynos.c +index 8ce9d7f..a179c5a 100644 +--- a/drivers/usb/dwc3/dwc3-exynos.c ++++ b/drivers/usb/dwc3/dwc3-exynos.c +@@ -20,7 +20,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + +@@ -34,13 +34,13 @@ struct dwc3_exynos { + + static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos) + { +- struct nop_usb_xceiv_platform_data pdata; ++ struct usb_phy_gen_xceiv_platform_data pdata; + struct platform_device *pdev; + int ret; + + memset(&pdata, 0x00, sizeof(pdata)); + +- pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO); ++ pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO); + if (!pdev) + return -ENOMEM; + +@@ -51,7 +51,7 @@ static int dwc3_exynos_register_phys(struct dwc3_exynos *exynos) + if (ret) + goto err1; + +- pdev = platform_device_alloc("nop_usb_xceiv", PLATFORM_DEVID_AUTO); ++ pdev = platform_device_alloc("usb_phy_gen_xceiv", PLATFORM_DEVID_AUTO); + if (!pdev) { + ret = -ENOMEM; + goto err1; +diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c +index ed07ec0..87ea3d5 100644 +--- a/drivers/usb/dwc3/dwc3-pci.c ++++ b/drivers/usb/dwc3/dwc3-pci.c +@@ -43,7 +43,7 @@ + #include + + #include +-#include ++#include + + /* FIXME define these in */ + #define PCI_VENDOR_ID_SYNOPSYS 0x16c3 +@@ -58,13 +58,13 @@ struct dwc3_pci { + + static int dwc3_pci_register_phys(struct dwc3_pci *glue) + { +- struct nop_usb_xceiv_platform_data pdata; ++ struct usb_phy_gen_xceiv_platform_data pdata; + struct platform_device *pdev; + int ret; + + memset(&pdata, 0x00, sizeof(pdata)); + +- pdev = platform_device_alloc("nop_usb_xceiv", 0); ++ pdev = platform_device_alloc("usb_phy_gen_xceiv", 0); + if (!pdev) + return -ENOMEM; + +@@ -75,7 +75,7 @@ static int dwc3_pci_register_phys(struct dwc3_pci *glue) + if (ret) + goto err1; + +- pdev = platform_device_alloc("nop_usb_xceiv", 1); ++ pdev = platform_device_alloc("usb_phy_gen_xceiv", 1); + if (!pdev) { + ret = -ENOMEM; + goto err1; +diff --git a/drivers/usb/gadget/Kconfig b/drivers/usb/gadget/Kconfig +index 8e93683..7ec7283 100644 +--- a/drivers/usb/gadget/Kconfig ++++ b/drivers/usb/gadget/Kconfig +@@ -144,7 +144,6 @@ config USB_AT91 + config USB_LPC32XX + tristate "LPC32XX USB Peripheral Controller" + depends on ARCH_LPC32XX +- depends on USB_PHY + select USB_ISP1301 + help + This option selects the USB device controller in the LPC32xx SoC. +@@ -206,7 +205,6 @@ config USB_FOTG210_UDC + config USB_OMAP + tristate "OMAP USB Device Controller" + depends on ARCH_OMAP1 +- depends on USB_PHY + select ISP1301_OMAP if MACH_OMAP_H2 || MACH_OMAP_H3 || MACH_OMAP_H4_OTG + help + Many Texas Instruments OMAP processors have flexible full +diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig +index 4263d01..3102b52 100644 +--- a/drivers/usb/host/Kconfig ++++ b/drivers/usb/host/Kconfig +@@ -186,7 +186,6 @@ config USB_EHCI_HCD_AT91 + config USB_EHCI_MSM + tristate "Support for Qualcomm QSD/MSM on-chip EHCI USB controller" + depends on ARCH_MSM +- depends on USB_PHY + select USB_EHCI_ROOT_HUB_TT + select USB_MSM_OTG + ---help--- +diff --git a/drivers/usb/musb/am35x.c b/drivers/usb/musb/am35x.c +index 2231850..5733a20 100644 +--- a/drivers/usb/musb/am35x.c ++++ b/drivers/usb/musb/am35x.c +@@ -33,7 +33,7 @@ + #include + #include + #include +-#include ++#include + #include + + #include "musb_core.h" +diff --git a/drivers/usb/musb/blackfin.c b/drivers/usb/musb/blackfin.c +index 6ba8439..195e966 100644 +--- a/drivers/usb/musb/blackfin.c ++++ b/drivers/usb/musb/blackfin.c +@@ -19,7 +19,7 @@ + #include + #include + #include +-#include ++#include + + #include + +diff --git a/drivers/usb/musb/da8xx.c b/drivers/usb/musb/da8xx.c +index 0da6f64..ccc6b63 100644 +--- a/drivers/usb/musb/da8xx.c ++++ b/drivers/usb/musb/da8xx.c +@@ -33,7 +33,7 @@ + #include + #include + #include +-#include ++#include + + #include + #include +diff --git a/drivers/usb/musb/davinci.c b/drivers/usb/musb/davinci.c +index f8aeaf2..91f300e 100644 +--- a/drivers/usb/musb/davinci.c ++++ b/drivers/usb/musb/davinci.c +@@ -33,7 +33,7 @@ + #include + #include + #include +-#include ++#include + + #include + #include +diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c +index 5233804..55fe3c2 100644 +--- a/drivers/usb/musb/musb_dsps.c ++++ b/drivers/usb/musb/musb_dsps.c +@@ -36,7 +36,7 @@ + #include + #include + #include +-#include ++#include + #include + #include + +diff --git a/drivers/usb/musb/tusb6010.c b/drivers/usb/musb/tusb6010.c +index 6f8a9ca..c642f09 100644 +--- a/drivers/usb/musb/tusb6010.c ++++ b/drivers/usb/musb/tusb6010.c +@@ -25,7 +25,7 @@ + #include + #include + #include +-#include ++#include + + #include "musb_core.h" + +diff --git a/drivers/usb/phy/Kconfig b/drivers/usb/phy/Kconfig +index 3622fff..f41c3e1 100644 +--- a/drivers/usb/phy/Kconfig ++++ b/drivers/usb/phy/Kconfig +@@ -1,22 +1,10 @@ + # + # Physical Layer USB driver configuration + # +-menuconfig USB_PHY +- bool "USB Physical Layer drivers" +- help +- Most USB controllers have the physical layer signalling part +- (commonly called a PHY) built in. However, dual-role devices +- (a.k.a. USB on-the-go) which support being USB master or slave +- with the same connector often use an external PHY. +- +- The drivers in this submenu add support for such PHY devices. +- They are not needed for standard master-only (or the vast +- majority of slave-only) USB interfaces. ++menu "USB Physical Layer drivers" + +- If you're not sure if this applies to you, it probably doesn't; +- say N here. +- +-if USB_PHY ++config USB_PHY ++ def_bool n + + # + # USB Transceiver Drivers +@@ -24,6 +12,7 @@ if USB_PHY + config AB8500_USB + tristate "AB8500 USB Transceiver Driver" + depends on AB8500_CORE ++ select USB_PHY + help + Enable this to support the USB OTG transceiver in AB8500 chip. + This transceiver supports high and full speed devices plus, +@@ -33,12 +22,14 @@ config FSL_USB2_OTG + bool "Freescale USB OTG Transceiver Driver" + depends on USB_EHCI_FSL && USB_FSL_USB2 && PM_RUNTIME + select USB_OTG ++ select USB_PHY + help + Enable this to support Freescale USB OTG transceiver. + + config ISP1301_OMAP + tristate "Philips ISP1301 with OMAP OTG" + depends on I2C && ARCH_OMAP_OTG ++ select USB_PHY + help + If you say yes here you get support for the Philips ISP1301 + USB-On-The-Go transceiver working with the OMAP OTG controller. +@@ -52,12 +43,14 @@ config ISP1301_OMAP + config MV_U3D_PHY + bool "Marvell USB 3.0 PHY controller Driver" + depends on CPU_MMP3 ++ select USB_PHY + help + Enable this to support Marvell USB 3.0 phy controller for Marvell + SoC. + + config NOP_USB_XCEIV + tristate "NOP USB Transceiver Driver" ++ select USB_PHY + help + This driver is to be used by all the usb transceiver which are either + built-in with usb ip or which are autonomous and doesn't require any +@@ -76,6 +69,7 @@ config OMAP_USB2 + tristate "OMAP USB2 PHY Driver" + depends on ARCH_OMAP2PLUS + select OMAP_CONTROL_USB ++ select USB_PHY + help + Enable this to support the transceiver that is part of SOC. This + driver takes care of all the PHY functionality apart from comparator. +@@ -85,12 +79,25 @@ config OMAP_USB2 + config OMAP_USB3 + tristate "OMAP USB3 PHY Driver" + select OMAP_CONTROL_USB ++ select USB_PHY + help + Enable this to support the USB3 PHY that is part of SOC. This + driver takes care of all the PHY functionality apart from comparator. + This driver interacts with the "OMAP Control USB Driver" to power + on/off the PHY. + ++config AM335X_CONTROL_USB ++ tristate ++ ++config AM335X_PHY_USB ++ tristate "AM335x USB PHY Driver" ++ select USB_PHY ++ select AM335X_CONTROL_USB ++ select NOP_USB_XCEIV ++ help ++ This driver provides PHY support for that phy which part for the ++ AM335x SoC. ++ + config SAMSUNG_USBPHY + tristate + help +@@ -101,6 +108,7 @@ config SAMSUNG_USBPHY + config SAMSUNG_USB2PHY + tristate "Samsung USB 2.0 PHY controller Driver" + select SAMSUNG_USBPHY ++ select USB_PHY + help + Enable this to support Samsung USB 2.0 (High Speed) PHY controller + driver for Samsung SoCs. +@@ -108,6 +116,7 @@ config SAMSUNG_USB2PHY + config SAMSUNG_USB3PHY + tristate "Samsung USB 3.0 PHY controller Driver" + select SAMSUNG_USBPHY ++ select USB_PHY + help + Enable this to support Samsung USB 3.0 (Super Speed) phy controller + for samsung SoCs. +@@ -115,6 +124,7 @@ config SAMSUNG_USB3PHY + config TWL4030_USB + tristate "TWL4030 USB Transceiver Driver" + depends on TWL4030_CORE && REGULATOR_TWL4030 && USB_MUSB_OMAP2PLUS ++ select USB_PHY + help + Enable this to support the USB OTG transceiver on TWL4030 + family chips (including the TWL5030 and TPS659x0 devices). +@@ -135,6 +145,7 @@ config TWL6030_USB + config USB_GPIO_VBUS + tristate "GPIO based peripheral-only VBUS sensing 'transceiver'" + depends on GPIOLIB ++ select USB_PHY + help + Provides simple GPIO VBUS sensing for controllers with an + internal transceiver via the usb_phy interface, and +@@ -145,6 +156,7 @@ config USB_ISP1301 + tristate "NXP ISP1301 USB transceiver support" + depends on USB || USB_GADGET + depends on I2C ++ select USB_PHY + help + Say Y here to add support for the NXP ISP1301 USB transceiver driver. + This chip is typically used as USB transceiver for USB host, gadget +@@ -156,6 +168,7 @@ config USB_ISP1301 + config USB_MSM_OTG + tristate "OTG support for Qualcomm on-chip USB controller" + depends on (USB || USB_GADGET) && ARCH_MSM ++ select USB_PHY + help + Enable this to support the USB OTG transceiver on MSM chips. It + handles PHY initialization, clock management, and workarounds +@@ -169,6 +182,7 @@ config USB_MV_OTG + tristate "Marvell USB OTG support" + depends on USB_EHCI_MV && USB_MV_UDC && PM_RUNTIME + select USB_OTG ++ select USB_PHY + help + Say Y here if you want to build Marvell USB OTG transciever + driver in kernel (including PXA and MMP series). This driver +@@ -180,6 +194,7 @@ config USB_MXS_PHY + tristate "Freescale MXS USB PHY support" + depends on ARCH_MXC || ARCH_MXS + select STMP_DEVICE ++ select USB_PHY + help + Enable this to support the Freescale MXS USB PHY. + +@@ -188,6 +203,7 @@ config USB_MXS_PHY + config USB_RCAR_PHY + tristate "Renesas R-Car USB PHY support" + depends on USB || USB_GADGET ++ select USB_PHY + help + Say Y here to add support for the Renesas R-Car USB common PHY driver. + This chip is typically used as USB PHY for USB host, gadget. +@@ -210,4 +226,4 @@ config USB_ULPI_VIEWPORT + Provides read/write operations to the ULPI phy register set for + controllers with a viewport register (e.g. Chipidea/ARC controllers). + +-endif # USB_PHY ++endmenu +diff --git a/drivers/usb/phy/Makefile b/drivers/usb/phy/Makefile +index 070eca3..dae321d 100644 +--- a/drivers/usb/phy/Makefile ++++ b/drivers/usb/phy/Makefile +@@ -14,8 +14,10 @@ phy-fsl-usb2-objs := phy-fsl-usb.o phy-fsm-usb.o + obj-$(CONFIG_FSL_USB2_OTG) += phy-fsl-usb2.o + obj-$(CONFIG_ISP1301_OMAP) += phy-isp1301-omap.o + obj-$(CONFIG_MV_U3D_PHY) += phy-mv-u3d-usb.o +-obj-$(CONFIG_NOP_USB_XCEIV) += phy-nop.o ++obj-$(CONFIG_NOP_USB_XCEIV) += phy-generic.o + obj-$(CONFIG_OMAP_CONTROL_USB) += phy-omap-control.o ++obj-$(CONFIG_AM335X_CONTROL_USB) += phy-am335x-control.o ++obj-$(CONFIG_AM335X_PHY_USB) += phy-am335x.o + obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o + obj-$(CONFIG_OMAP_USB3) += phy-omap-usb3.o + obj-$(CONFIG_SAMSUNG_USBPHY) += phy-samsung-usb.o +diff --git a/drivers/usb/phy/am35x-phy-control.h b/drivers/usb/phy/am35x-phy-control.h +new file mode 100644 +index 0000000..b96594d +--- /dev/null ++++ b/drivers/usb/phy/am35x-phy-control.h +@@ -0,0 +1,21 @@ ++#ifndef _AM335x_PHY_CONTROL_H_ ++#define _AM335x_PHY_CONTROL_H_ ++ ++struct phy_control { ++ void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on); ++ void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on); ++}; ++ ++static inline void phy_ctrl_power(struct phy_control *phy_ctrl, u32 id, bool on) ++{ ++ phy_ctrl->phy_power(phy_ctrl, id, on); ++} ++ ++static inline void phy_ctrl_wkup(struct phy_control *phy_ctrl, u32 id, bool on) ++{ ++ phy_ctrl->phy_wkup(phy_ctrl, id, on); ++} ++ ++struct phy_control *am335x_get_phy_control(struct device *dev); ++ ++#endif +diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c +new file mode 100644 +index 0000000..22cf07d +--- /dev/null ++++ b/drivers/usb/phy/phy-am335x-control.c +@@ -0,0 +1,137 @@ ++#include ++#include ++#include ++#include ++#include ++ ++struct phy_control { ++ void (*phy_power)(struct phy_control *phy_ctrl, u32 id, bool on); ++ void (*phy_wkup)(struct phy_control *phy_ctrl, u32 id, bool on); ++}; ++ ++struct am335x_control_usb { ++ struct device *dev; ++ void __iomem *phy_reg; ++ void __iomem *wkup; ++ spinlock_t lock; ++ struct phy_control phy_ctrl; ++}; ++ ++#define AM335X_USB0_CTRL 0x0 ++#define AM335X_USB1_CTRL 0x8 ++#define AM335x_USB_WKUP 0x0 ++ ++#define USBPHY_CM_PWRDN (1 << 0) ++#define USBPHY_OTG_PWRDN (1 << 1) ++#define USBPHY_OTGVDET_EN (1 << 19) ++#define USBPHY_OTGSESSEND_EN (1 << 20) ++ ++static void am335x_phy_power(struct phy_control *phy_ctrl, u32 id, bool on) ++{ ++ struct am335x_control_usb *usb_ctrl; ++ u32 val; ++ u32 reg; ++ ++ usb_ctrl = container_of(phy_ctrl, struct am335x_control_usb, phy_ctrl); ++ ++ switch (id) { ++ case 0: ++ reg = AM335X_USB0_CTRL; ++ break; ++ case 1: ++ reg = AM335X_USB1_CTRL; ++ break; ++ default: ++ WARN_ON(1); ++ return; ++ } ++ ++ val = readl(usb_ctrl->phy_reg + reg); ++ if (on) { ++ val &= ~(USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN); ++ val |= USBPHY_OTGVDET_EN | USBPHY_OTGSESSEND_EN; ++ } else { ++ val |= USBPHY_CM_PWRDN | USBPHY_OTG_PWRDN; ++ } ++ ++ writel(val, usb_ctrl->phy_reg + reg); ++} ++ ++static const struct phy_control ctrl_am335x = { ++ .phy_power = am335x_phy_power, ++}; ++ ++static const struct of_device_id omap_control_usb_id_table[] = { ++ { .compatible = "ti,am335x-usb-ctrl-module", .data = &ctrl_am335x }, ++ {} ++}; ++MODULE_DEVICE_TABLE(of, omap_control_usb_id_table); ++ ++static struct platform_driver am335x_control_driver; ++static int match(struct device *dev, void *data) ++{ ++ struct device_node *node = (struct device_node *)data; ++ return dev->of_node == node && ++ dev->driver == &am335x_control_driver.driver; ++} ++ ++struct phy_control *am335x_get_phy_control(struct device *dev) ++{ ++ struct device_node *node; ++ struct am335x_control_usb *ctrl_usb; ++ ++ node = of_parse_phandle(dev->of_node, "ti,ctrl_mod", 0); ++ if (!node) ++ return NULL; ++ ++ dev = bus_find_device(&platform_bus_type, NULL, node, match); ++ ctrl_usb = dev_get_drvdata(dev); ++ if (!ctrl_usb) ++ return NULL; ++ return &ctrl_usb->phy_ctrl; ++} ++EXPORT_SYMBOL_GPL(am335x_get_phy_control); ++ ++static int am335x_control_usb_probe(struct platform_device *pdev) ++{ ++ struct resource *res; ++ struct am335x_control_usb *ctrl_usb; ++ const struct of_device_id *of_id; ++ const struct phy_control *phy_ctrl; ++ ++ of_id = of_match_node(omap_control_usb_id_table, pdev->dev.of_node); ++ if (!of_id) ++ return -EINVAL; ++ ++ phy_ctrl = of_id->data; ++ ++ ctrl_usb = devm_kzalloc(&pdev->dev, sizeof(*ctrl_usb), GFP_KERNEL); ++ if (!ctrl_usb) { ++ dev_err(&pdev->dev, "unable to alloc memory for control usb\n"); ++ return -ENOMEM; ++ } ++ ++ ctrl_usb->dev = &pdev->dev; ++ ++ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "phy_ctrl"); ++ ctrl_usb->phy_reg = devm_ioremap_resource(&pdev->dev, res); ++ if (IS_ERR(ctrl_usb->phy_reg)) ++ return PTR_ERR(ctrl_usb->phy_reg); ++ spin_lock_init(&ctrl_usb->lock); ++ ctrl_usb->phy_ctrl = *phy_ctrl; ++ ++ dev_set_drvdata(ctrl_usb->dev, ctrl_usb); ++ return 0; ++} ++ ++static struct platform_driver am335x_control_driver = { ++ .probe = am335x_control_usb_probe, ++ .driver = { ++ .name = "am335x-control-usb", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(omap_control_usb_id_table), ++ }, ++}; ++ ++module_platform_driver(am335x_control_driver); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c +new file mode 100644 +index 0000000..c4d614d +--- /dev/null ++++ b/drivers/usb/phy/phy-am335x.c +@@ -0,0 +1,99 @@ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "am35x-phy-control.h" ++#include "phy-generic.h" ++ ++struct am335x_phy { ++ struct usb_phy_gen_xceiv usb_phy_gen; ++ struct phy_control *phy_ctrl; ++ int id; ++}; ++ ++static int am335x_init(struct usb_phy *phy) ++{ ++ struct am335x_phy *am_phy = dev_get_drvdata(phy->dev); ++ ++ phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, true); ++ return 0; ++} ++ ++static void am335x_shutdown(struct usb_phy *phy) ++{ ++ struct am335x_phy *am_phy = dev_get_drvdata(phy->dev); ++ ++ phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, false); ++} ++ ++static int am335x_phy_probe(struct platform_device *pdev) ++{ ++ struct am335x_phy *am_phy; ++ struct device *dev = &pdev->dev; ++ int ret; ++ ++ am_phy = devm_kzalloc(dev, sizeof(*am_phy), GFP_KERNEL); ++ if (!am_phy) ++ return -ENOMEM; ++ ++ am_phy->phy_ctrl = am335x_get_phy_control(dev); ++ if (!am_phy->phy_ctrl) ++ return -EPROBE_DEFER; ++ am_phy->id = of_alias_get_id(pdev->dev.of_node, "phy"); ++ if (am_phy->id < 0) { ++ dev_err(&pdev->dev, "Missing PHY id: %d\n", am_phy->id); ++ return am_phy->id; ++ } ++ ++ ret = usb_phy_gen_create_phy(dev, &am_phy->usb_phy_gen, ++ USB_PHY_TYPE_USB2, 0, false, false); ++ if (ret) ++ return ret; ++ ++ ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy); ++ if (ret) ++ goto err_add; ++ am_phy->usb_phy_gen.phy.init = am335x_init; ++ am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown; ++ ++ platform_set_drvdata(pdev, am_phy); ++ return 0; ++ ++err_add: ++ usb_phy_gen_cleanup_phy(&am_phy->usb_phy_gen); ++ return ret; ++} ++ ++static int am335x_phy_remove(struct platform_device *pdev) ++{ ++ struct am335x_phy *am_phy = platform_get_drvdata(pdev); ++ ++ usb_remove_phy(&am_phy->usb_phy_gen.phy); ++ return 0; ++} ++ ++static const struct of_device_id am335x_phy_ids[] = { ++ { .compatible = "ti,am335x-usb-phy" }, ++ { } ++}; ++MODULE_DEVICE_TABLE(of, am335x_phy_ids); ++ ++static struct platform_driver am335x_phy_driver = { ++ .probe = am335x_phy_probe, ++ .remove = am335x_phy_remove, ++ .driver = { ++ .name = "am335x-phy-driver", ++ .owner = THIS_MODULE, ++ .of_match_table = of_match_ptr(am335x_phy_ids), ++ }, ++}; ++ ++module_platform_driver(am335x_phy_driver); ++MODULE_LICENSE("GPL v2"); +diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c +new file mode 100644 +index 0000000..efe59f3 +--- /dev/null ++++ b/drivers/usb/phy/phy-generic.c +@@ -0,0 +1,309 @@ ++/* ++ * drivers/usb/otg/nop-usb-xceiv.c ++ * ++ * NOP USB transceiver for all USB transceiver which are either built-in ++ * into USB IP or which are mostly autonomous. ++ * ++ * Copyright (C) 2009 Texas Instruments Inc ++ * Author: Ajay Kumar Gupta ++ * ++ * 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. ++ * ++ * This program is distributed in the hope that it will be useful, ++ * but WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++ * GNU General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. ++ * ++ * Current status: ++ * This provides a "nop" transceiver for PHYs which are ++ * autonomous such as isp1504, isp1707, etc. ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "phy-generic.h" ++ ++static struct platform_device *pd; ++ ++void usb_nop_xceiv_register(void) ++{ ++ if (pd) ++ return; ++ pd = platform_device_register_simple("usb_phy_gen_xceiv", -1, NULL, 0); ++ if (!pd) { ++ pr_err("Unable to register generic usb transceiver\n"); ++ return; ++ } ++} ++EXPORT_SYMBOL(usb_nop_xceiv_register); ++ ++void usb_nop_xceiv_unregister(void) ++{ ++ platform_device_unregister(pd); ++ pd = NULL; ++} ++EXPORT_SYMBOL(usb_nop_xceiv_unregister); ++ ++static int nop_set_suspend(struct usb_phy *x, int suspend) ++{ ++ return 0; ++} ++ ++int usb_gen_phy_init(struct usb_phy *phy) ++{ ++ struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev); ++ ++ if (!IS_ERR(nop->vcc)) { ++ if (regulator_enable(nop->vcc)) ++ dev_err(phy->dev, "Failed to enable power\n"); ++ } ++ ++ if (!IS_ERR(nop->clk)) ++ clk_enable(nop->clk); ++ ++ if (!IS_ERR(nop->reset)) { ++ /* De-assert RESET */ ++ if (regulator_enable(nop->reset)) ++ dev_err(phy->dev, "Failed to de-assert reset\n"); ++ } ++ ++ return 0; ++} ++EXPORT_SYMBOL_GPL(usb_gen_phy_init); ++ ++void usb_gen_phy_shutdown(struct usb_phy *phy) ++{ ++ struct usb_phy_gen_xceiv *nop = dev_get_drvdata(phy->dev); ++ ++ if (!IS_ERR(nop->reset)) { ++ /* Assert RESET */ ++ if (regulator_disable(nop->reset)) ++ dev_err(phy->dev, "Failed to assert reset\n"); ++ } ++ ++ if (!IS_ERR(nop->clk)) ++ clk_disable(nop->clk); ++ ++ if (!IS_ERR(nop->vcc)) { ++ if (regulator_disable(nop->vcc)) ++ dev_err(phy->dev, "Failed to disable power\n"); ++ } ++} ++EXPORT_SYMBOL_GPL(usb_gen_phy_shutdown); ++ ++static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) ++{ ++ if (!otg) ++ return -ENODEV; ++ ++ if (!gadget) { ++ otg->gadget = NULL; ++ return -ENODEV; ++ } ++ ++ otg->gadget = gadget; ++ otg->phy->state = OTG_STATE_B_IDLE; ++ return 0; ++} ++ ++static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) ++{ ++ if (!otg) ++ return -ENODEV; ++ ++ if (!host) { ++ otg->host = NULL; ++ return -ENODEV; ++ } ++ ++ otg->host = host; ++ return 0; ++} ++ ++int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, ++ enum usb_phy_type type, u32 clk_rate, bool needs_vcc, ++ bool needs_reset) ++{ ++ int err; ++ ++ nop->phy.otg = devm_kzalloc(dev, sizeof(*nop->phy.otg), ++ GFP_KERNEL); ++ if (!nop->phy.otg) ++ return -ENOMEM; ++ ++ nop->clk = devm_clk_get(dev, "main_clk"); ++ if (IS_ERR(nop->clk)) { ++ dev_dbg(dev, "Can't get phy clock: %ld\n", ++ PTR_ERR(nop->clk)); ++ } ++ ++ if (!IS_ERR(nop->clk) && clk_rate) { ++ err = clk_set_rate(nop->clk, clk_rate); ++ if (err) { ++ dev_err(dev, "Error setting clock rate\n"); ++ return err; ++ } ++ } ++ ++ if (!IS_ERR(nop->clk)) { ++ err = clk_prepare(nop->clk); ++ if (err) { ++ dev_err(dev, "Error preparing clock\n"); ++ return err; ++ } ++ } ++ ++ nop->vcc = devm_regulator_get(dev, "vcc"); ++ if (IS_ERR(nop->vcc)) { ++ dev_dbg(dev, "Error getting vcc regulator: %ld\n", ++ PTR_ERR(nop->vcc)); ++ if (needs_vcc) ++ return -EPROBE_DEFER; ++ } ++ ++ nop->reset = devm_regulator_get(dev, "reset"); ++ if (IS_ERR(nop->reset)) { ++ dev_dbg(dev, "Error getting reset regulator: %ld\n", ++ PTR_ERR(nop->reset)); ++ if (needs_reset) ++ return -EPROBE_DEFER; ++ } ++ ++ nop->dev = dev; ++ nop->phy.dev = nop->dev; ++ nop->phy.label = "nop-xceiv"; ++ nop->phy.set_suspend = nop_set_suspend; ++ nop->phy.state = OTG_STATE_UNDEFINED; ++ nop->phy.type = type; ++ ++ nop->phy.otg->phy = &nop->phy; ++ nop->phy.otg->set_host = nop_set_host; ++ nop->phy.otg->set_peripheral = nop_set_peripheral; ++ ++ ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier); ++ return 0; ++} ++EXPORT_SYMBOL_GPL(usb_phy_gen_create_phy); ++ ++void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop) ++{ ++ if (!IS_ERR(nop->clk)) ++ clk_unprepare(nop->clk); ++} ++EXPORT_SYMBOL_GPL(usb_phy_gen_cleanup_phy); ++ ++static int usb_phy_gen_xceiv_probe(struct platform_device *pdev) ++{ ++ struct device *dev = &pdev->dev; ++ struct usb_phy_gen_xceiv_platform_data *pdata = ++ dev_get_platdata(&pdev->dev); ++ struct usb_phy_gen_xceiv *nop; ++ enum usb_phy_type type = USB_PHY_TYPE_USB2; ++ int err; ++ u32 clk_rate = 0; ++ bool needs_vcc = false; ++ bool needs_reset = false; ++ ++ if (dev->of_node) { ++ struct device_node *node = dev->of_node; ++ ++ if (of_property_read_u32(node, "clock-frequency", &clk_rate)) ++ clk_rate = 0; ++ ++ needs_vcc = of_property_read_bool(node, "vcc-supply"); ++ needs_reset = of_property_read_bool(node, "reset-supply"); ++ ++ } else if (pdata) { ++ type = pdata->type; ++ clk_rate = pdata->clk_rate; ++ needs_vcc = pdata->needs_vcc; ++ needs_reset = pdata->needs_reset; ++ } ++ ++ nop = devm_kzalloc(dev, sizeof(*nop), GFP_KERNEL); ++ if (!nop) ++ return -ENOMEM; ++ ++ ++ err = usb_phy_gen_create_phy(dev, nop, type, clk_rate, needs_vcc, ++ needs_reset); ++ if (err) ++ return err; ++ ++ nop->phy.init = usb_gen_phy_init; ++ nop->phy.shutdown = usb_gen_phy_shutdown; ++ ++ err = usb_add_phy_dev(&nop->phy); ++ if (err) { ++ dev_err(&pdev->dev, "can't register transceiver, err: %d\n", ++ err); ++ goto err_add; ++ } ++ ++ platform_set_drvdata(pdev, nop); ++ ++ return 0; ++ ++err_add: ++ usb_phy_gen_cleanup_phy(nop); ++ return err; ++} ++ ++static int usb_phy_gen_xceiv_remove(struct platform_device *pdev) ++{ ++ struct usb_phy_gen_xceiv *nop = platform_get_drvdata(pdev); ++ ++ usb_phy_gen_cleanup_phy(nop); ++ usb_remove_phy(&nop->phy); ++ ++ return 0; ++} ++ ++static const struct of_device_id nop_xceiv_dt_ids[] = { ++ { .compatible = "usb-nop-xceiv" }, ++ { } ++}; ++ ++MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids); ++ ++static struct platform_driver usb_phy_gen_xceiv_driver = { ++ .probe = usb_phy_gen_xceiv_probe, ++ .remove = usb_phy_gen_xceiv_remove, ++ .driver = { ++ .name = "usb_phy_gen_xceiv", ++ .owner = THIS_MODULE, ++ .of_match_table = nop_xceiv_dt_ids, ++ }, ++}; ++ ++static int __init usb_phy_gen_xceiv_init(void) ++{ ++ return platform_driver_register(&usb_phy_gen_xceiv_driver); ++} ++subsys_initcall(usb_phy_gen_xceiv_init); ++ ++static void __exit usb_phy_gen_xceiv_exit(void) ++{ ++ platform_driver_unregister(&usb_phy_gen_xceiv_driver); ++} ++module_exit(usb_phy_gen_xceiv_exit); ++ ++MODULE_ALIAS("platform:usb_phy_gen_xceiv"); ++MODULE_AUTHOR("Texas Instruments Inc"); ++MODULE_DESCRIPTION("NOP USB Transceiver driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/usb/phy/phy-generic.h b/drivers/usb/phy/phy-generic.h +new file mode 100644 +index 0000000..61687d5 +--- /dev/null ++++ b/drivers/usb/phy/phy-generic.h +@@ -0,0 +1,20 @@ ++#ifndef _PHY_GENERIC_H_ ++#define _PHY_GENERIC_H_ ++ ++struct usb_phy_gen_xceiv { ++ struct usb_phy phy; ++ struct device *dev; ++ struct clk *clk; ++ struct regulator *vcc; ++ struct regulator *reset; ++}; ++ ++int usb_gen_phy_init(struct usb_phy *phy); ++void usb_gen_phy_shutdown(struct usb_phy *phy); ++ ++int usb_phy_gen_create_phy(struct device *dev, struct usb_phy_gen_xceiv *nop, ++ enum usb_phy_type type, u32 clk_rate, bool needs_vcc, ++ bool needs_reset); ++void usb_phy_gen_cleanup_phy(struct usb_phy_gen_xceiv *nop); ++ ++#endif +diff --git a/drivers/usb/phy/phy-nop.c b/drivers/usb/phy/phy-nop.c +deleted file mode 100644 +index 55445e5d..0000000 +--- a/drivers/usb/phy/phy-nop.c ++++ /dev/null +@@ -1,292 +0,0 @@ +-/* +- * drivers/usb/otg/nop-usb-xceiv.c +- * +- * NOP USB transceiver for all USB transceiver which are either built-in +- * into USB IP or which are mostly autonomous. +- * +- * Copyright (C) 2009 Texas Instruments Inc +- * Author: Ajay Kumar Gupta +- * +- * 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. +- * +- * This program is distributed in the hope that it will be useful, +- * but WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +- * GNU General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +- * +- * Current status: +- * This provides a "nop" transceiver for PHYs which are +- * autonomous such as isp1504, isp1707, etc. +- */ +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-struct nop_usb_xceiv { +- struct usb_phy phy; +- struct device *dev; +- struct clk *clk; +- struct regulator *vcc; +- struct regulator *reset; +-}; +- +-static struct platform_device *pd; +- +-void usb_nop_xceiv_register(void) +-{ +- if (pd) +- return; +- pd = platform_device_register_simple("nop_usb_xceiv", -1, NULL, 0); +- if (!pd) { +- printk(KERN_ERR "Unable to register usb nop transceiver\n"); +- return; +- } +-} +-EXPORT_SYMBOL(usb_nop_xceiv_register); +- +-void usb_nop_xceiv_unregister(void) +-{ +- platform_device_unregister(pd); +- pd = NULL; +-} +-EXPORT_SYMBOL(usb_nop_xceiv_unregister); +- +-static int nop_set_suspend(struct usb_phy *x, int suspend) +-{ +- return 0; +-} +- +-static int nop_init(struct usb_phy *phy) +-{ +- struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev); +- +- if (!IS_ERR(nop->vcc)) { +- if (regulator_enable(nop->vcc)) +- dev_err(phy->dev, "Failed to enable power\n"); +- } +- +- if (!IS_ERR(nop->clk)) +- clk_enable(nop->clk); +- +- if (!IS_ERR(nop->reset)) { +- /* De-assert RESET */ +- if (regulator_enable(nop->reset)) +- dev_err(phy->dev, "Failed to de-assert reset\n"); +- } +- +- return 0; +-} +- +-static void nop_shutdown(struct usb_phy *phy) +-{ +- struct nop_usb_xceiv *nop = dev_get_drvdata(phy->dev); +- +- if (!IS_ERR(nop->reset)) { +- /* Assert RESET */ +- if (regulator_disable(nop->reset)) +- dev_err(phy->dev, "Failed to assert reset\n"); +- } +- +- if (!IS_ERR(nop->clk)) +- clk_disable(nop->clk); +- +- if (!IS_ERR(nop->vcc)) { +- if (regulator_disable(nop->vcc)) +- dev_err(phy->dev, "Failed to disable power\n"); +- } +-} +- +-static int nop_set_peripheral(struct usb_otg *otg, struct usb_gadget *gadget) +-{ +- if (!otg) +- return -ENODEV; +- +- if (!gadget) { +- otg->gadget = NULL; +- return -ENODEV; +- } +- +- otg->gadget = gadget; +- otg->phy->state = OTG_STATE_B_IDLE; +- return 0; +-} +- +-static int nop_set_host(struct usb_otg *otg, struct usb_bus *host) +-{ +- if (!otg) +- return -ENODEV; +- +- if (!host) { +- otg->host = NULL; +- return -ENODEV; +- } +- +- otg->host = host; +- return 0; +-} +- +-static int nop_usb_xceiv_probe(struct platform_device *pdev) +-{ +- struct device *dev = &pdev->dev; +- struct nop_usb_xceiv_platform_data *pdata = pdev->dev.platform_data; +- struct nop_usb_xceiv *nop; +- enum usb_phy_type type = USB_PHY_TYPE_USB2; +- int err; +- u32 clk_rate = 0; +- bool needs_vcc = false; +- bool needs_reset = false; +- +- nop = devm_kzalloc(&pdev->dev, sizeof(*nop), GFP_KERNEL); +- if (!nop) +- return -ENOMEM; +- +- nop->phy.otg = devm_kzalloc(&pdev->dev, sizeof(*nop->phy.otg), +- GFP_KERNEL); +- if (!nop->phy.otg) +- return -ENOMEM; +- +- if (dev->of_node) { +- struct device_node *node = dev->of_node; +- +- if (of_property_read_u32(node, "clock-frequency", &clk_rate)) +- clk_rate = 0; +- +- needs_vcc = of_property_read_bool(node, "vcc-supply"); +- needs_reset = of_property_read_bool(node, "reset-supply"); +- +- } else if (pdata) { +- type = pdata->type; +- clk_rate = pdata->clk_rate; +- needs_vcc = pdata->needs_vcc; +- needs_reset = pdata->needs_reset; +- } +- +- nop->clk = devm_clk_get(&pdev->dev, "main_clk"); +- if (IS_ERR(nop->clk)) { +- dev_dbg(&pdev->dev, "Can't get phy clock: %ld\n", +- PTR_ERR(nop->clk)); +- } +- +- if (!IS_ERR(nop->clk) && clk_rate) { +- err = clk_set_rate(nop->clk, clk_rate); +- if (err) { +- dev_err(&pdev->dev, "Error setting clock rate\n"); +- return err; +- } +- } +- +- if (!IS_ERR(nop->clk)) { +- err = clk_prepare(nop->clk); +- if (err) { +- dev_err(&pdev->dev, "Error preparing clock\n"); +- return err; +- } +- } +- +- nop->vcc = devm_regulator_get(&pdev->dev, "vcc"); +- if (IS_ERR(nop->vcc)) { +- dev_dbg(&pdev->dev, "Error getting vcc regulator: %ld\n", +- PTR_ERR(nop->vcc)); +- if (needs_vcc) +- return -EPROBE_DEFER; +- } +- +- nop->reset = devm_regulator_get(&pdev->dev, "reset"); +- if (IS_ERR(nop->reset)) { +- dev_dbg(&pdev->dev, "Error getting reset regulator: %ld\n", +- PTR_ERR(nop->reset)); +- if (needs_reset) +- return -EPROBE_DEFER; +- } +- +- nop->dev = &pdev->dev; +- nop->phy.dev = nop->dev; +- nop->phy.label = "nop-xceiv"; +- nop->phy.set_suspend = nop_set_suspend; +- nop->phy.init = nop_init; +- nop->phy.shutdown = nop_shutdown; +- nop->phy.state = OTG_STATE_UNDEFINED; +- nop->phy.type = type; +- +- nop->phy.otg->phy = &nop->phy; +- nop->phy.otg->set_host = nop_set_host; +- nop->phy.otg->set_peripheral = nop_set_peripheral; +- +- err = usb_add_phy_dev(&nop->phy); +- if (err) { +- dev_err(&pdev->dev, "can't register transceiver, err: %d\n", +- err); +- goto err_add; +- } +- +- platform_set_drvdata(pdev, nop); +- +- ATOMIC_INIT_NOTIFIER_HEAD(&nop->phy.notifier); +- +- return 0; +- +-err_add: +- if (!IS_ERR(nop->clk)) +- clk_unprepare(nop->clk); +- return err; +-} +- +-static int nop_usb_xceiv_remove(struct platform_device *pdev) +-{ +- struct nop_usb_xceiv *nop = platform_get_drvdata(pdev); +- +- if (!IS_ERR(nop->clk)) +- clk_unprepare(nop->clk); +- +- usb_remove_phy(&nop->phy); +- +- return 0; +-} +- +-static const struct of_device_id nop_xceiv_dt_ids[] = { +- { .compatible = "usb-nop-xceiv" }, +- { } +-}; +- +-MODULE_DEVICE_TABLE(of, nop_xceiv_dt_ids); +- +-static struct platform_driver nop_usb_xceiv_driver = { +- .probe = nop_usb_xceiv_probe, +- .remove = nop_usb_xceiv_remove, +- .driver = { +- .name = "nop_usb_xceiv", +- .owner = THIS_MODULE, +- .of_match_table = nop_xceiv_dt_ids, +- }, +-}; +- +-static int __init nop_usb_xceiv_init(void) +-{ +- return platform_driver_register(&nop_usb_xceiv_driver); +-} +-subsys_initcall(nop_usb_xceiv_init); +- +-static void __exit nop_usb_xceiv_exit(void) +-{ +- platform_driver_unregister(&nop_usb_xceiv_driver); +-} +-module_exit(nop_usb_xceiv_exit); +- +-MODULE_ALIAS("platform:nop_usb_xceiv"); +-MODULE_AUTHOR("Texas Instruments Inc"); +-MODULE_DESCRIPTION("NOP USB Transceiver driver"); +-MODULE_LICENSE("GPL"); +diff --git a/include/drm/i2c/tda998x.h b/include/drm/i2c/tda998x.h +new file mode 100644 +index 0000000..41f799f +--- /dev/null ++++ b/include/drm/i2c/tda998x.h +@@ -0,0 +1,23 @@ ++#ifndef __TDA998X_H__ ++#define __TDA998X_H__ ++ ++enum tda998x_audio_format { ++ AFMT_I2S, ++ AFMT_SPDIF, ++}; ++ ++struct tda998x_encoder_params { ++ int audio_cfg; ++ int audio_clk_cfg; ++ enum tda998x_audio_format audio_format; ++ int audio_sample_rate; ++ char audio_frame[6]; ++ int swap_a, mirr_a; ++ int swap_b, mirr_b; ++ int swap_c, mirr_c; ++ int swap_d, mirr_d; ++ int swap_e, mirr_e; ++ int swap_f, mirr_f; ++}; ++ ++#endif +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); +diff --git a/include/linux/i2c/eeprom.h b/include/linux/i2c/eeprom.h +new file mode 100644 +index 0000000..1393980 +--- /dev/null ++++ b/include/linux/i2c/eeprom.h +@@ -0,0 +1,59 @@ ++/* ++ * i2c/eeprom.h ++ * ++ * In-kernel interface for accessing eeprom memory. ++ * ++ * Copyright (C) 2012 Texas Instruments Inc. ++ * Pantelis Antoniou ++ * ++ * 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. ++ */ ++#ifndef I2C_EEPROM_H ++#define I2C_EEPROM_H ++ ++#include ++#include ++#include ++#include ++ ++/* ++ * The method called in the client is ++ * ++ * int command(struct i2c_client *client, unsigned int cmd, void *arg); ++ * ++ * A single command is supported, which returns a pointer to the memory ++ * accessor already available, but which was only accessible via platform ++ * callbacks. We can't use platform callbacks anymore for device tree ++ * platforms, hence this interface. ++ * ++ */ ++ ++/* interface commands */ ++#define I2C_EEPROM_GET_MEMORY_ACCESSOR 1 ++ ++static inline struct memory_accessor * ++i2c_eeprom_get_memory_accessor(struct i2c_client *client) ++{ ++ int ret; ++ struct memory_accessor *macc; ++ ++ /* verify that the i2c client's driver has a command method */ ++ if (!client || !client->driver || !client->driver->command) ++ return ERR_PTR(-ENOTSUPP); ++ ++ macc = NULL; ++ ret = client->driver->command(client, I2C_EEPROM_GET_MEMORY_ACCESSOR, ++ &macc); ++ if (ret != 0) ++ return ERR_PTR(ret); ++ ++ if (macc == NULL) ++ return ERR_PTR(-ENOTSUPP); ++ ++ return macc; ++} ++ ++#endif +diff --git a/include/linux/of_i2c.h b/include/linux/of_i2c.h +index cfb545c..53fca8f 100644 +--- a/include/linux/of_i2c.h ++++ b/include/linux/of_i2c.h +@@ -15,6 +15,9 @@ + #if defined(CONFIG_OF_I2C) || defined(CONFIG_OF_I2C_MODULE) + #include + ++struct i2c_client * ++of_i2c_register_device(struct i2c_adapter *adap, struct device_node *node); ++ + extern void of_i2c_register_devices(struct i2c_adapter *adap); + + /* must call put_device() when done with returned i2c_client device */ +@@ -25,6 +28,14 @@ extern struct i2c_adapter *of_find_i2c_adapter_by_node( + struct device_node *node); + + #else ++ ++static inline struct i2c_client * ++of_i2c_register_device(struct i2c_adapter *adap, ++ struct device_node *node) ++{ ++ return ERR_PTR(-ENODEV); ++} ++ + static inline void of_i2c_register_devices(struct i2c_adapter *adap) + { + return; +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, +diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h +index ce8e4ff..fb3dbce 100644 +--- a/include/linux/platform_device.h ++++ b/include/linux/platform_device.h +@@ -325,4 +325,8 @@ extern int platform_pm_restore(struct device *dev); + #define USE_PLATFORM_PM_SLEEP_OPS + #endif + ++/* helper functions for resource list managment */ ++int platform_device_unlink_resources(struct platform_device *pdev); ++int platform_device_link_resources(struct platform_device *pdev); ++ + #endif /* _PLATFORM_DEVICE_H_ */ +diff --git a/include/linux/usb/nop-usb-xceiv.h b/include/linux/usb/nop-usb-xceiv.h +deleted file mode 100644 +index 148d351..0000000 +--- a/include/linux/usb/nop-usb-xceiv.h ++++ /dev/null +@@ -1,29 +0,0 @@ +-#ifndef __LINUX_USB_NOP_XCEIV_H +-#define __LINUX_USB_NOP_XCEIV_H +- +-#include +- +-struct nop_usb_xceiv_platform_data { +- enum usb_phy_type type; +- unsigned long clk_rate; +- +- /* if set fails with -EPROBE_DEFER if can't get regulator */ +- unsigned int needs_vcc:1; +- unsigned int needs_reset:1; +-}; +- +-#if defined(CONFIG_NOP_USB_XCEIV) || (defined(CONFIG_NOP_USB_XCEIV_MODULE) && defined(MODULE)) +-/* sometimes transceivers are accessed only through e.g. ULPI */ +-extern void usb_nop_xceiv_register(void); +-extern void usb_nop_xceiv_unregister(void); +-#else +-static inline void usb_nop_xceiv_register(void) +-{ +-} +- +-static inline void usb_nop_xceiv_unregister(void) +-{ +-} +-#endif +- +-#endif /* __LINUX_USB_NOP_XCEIV_H */ +diff --git a/include/linux/usb/usb_phy_gen_xceiv.h b/include/linux/usb/usb_phy_gen_xceiv.h +new file mode 100644 +index 0000000..f9a7e7b +--- /dev/null ++++ b/include/linux/usb/usb_phy_gen_xceiv.h +@@ -0,0 +1,29 @@ ++#ifndef __LINUX_USB_NOP_XCEIV_H ++#define __LINUX_USB_NOP_XCEIV_H ++ ++#include ++ ++struct usb_phy_gen_xceiv_platform_data { ++ enum usb_phy_type type; ++ unsigned long clk_rate; ++ ++ /* if set fails with -EPROBE_DEFER if can't get regulator */ ++ unsigned int needs_vcc:1; ++ unsigned int needs_reset:1; ++}; ++ ++#if IS_ENABLED(CONFIG_NOP_USB_XCEIV) ++/* sometimes transceivers are accessed only through e.g. ULPI */ ++extern void usb_nop_xceiv_register(void); ++extern void usb_nop_xceiv_unregister(void); ++#else ++static inline void usb_nop_xceiv_register(void) ++{ ++} ++ ++static inline void usb_nop_xceiv_unregister(void) ++{ ++} ++#endif ++ ++#endif /* __LINUX_USB_NOP_XCEIV_H */ +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 diff --git a/config-arm-generic b/config-arm-generic index 738bfa148..68b1c56da 100644 --- a/config-arm-generic +++ b/config-arm-generic @@ -47,7 +47,7 @@ CONFIG_OF_DEVICE=y CONFIG_OF_EARLY_FLATTREE=y CONFIG_OF_FLATTREE=y CONFIG_OF_GPIO=y -CONFIG_OF_I2C=m +CONFIG_OF_I2C=y CONFIG_OF_IRQ=y CONFIG_OF_MDIO=m CONFIG_OF_MTD=y @@ -102,3 +102,29 @@ CONFIG_SMC911X=m # CONFIG_LEDS_RENESAS_TPU is not set # CONFIG_LOCK_STAT is not set # CONFIG_PCIEPORTBUS is not set + +CONFIG_I2C=y + +### turn off things which make no sense on embedded SoC + +# core + +# CONFIG_INFINIBAND is not set +# CONFIG_ISDN is not set + +# netdrv + +# CONFIG_NET_VENDOR_DEC is not set +# CONFIG_NET_VENDOR_CHELSIO is not set +# CONFIG_NET_VENDOR_EXAR is not set +# CONFIG_NET_VENDOR_INTEL is not set +# CONFIG_NET_VENDOR_MELLANOX is not set + +# scsi + +# CONFIG_BLK_DEV_3W_XXXX_RAID is not set +# CONFIG_SCSI_3W_SAS is not set +# CONFIG_SCSI_PM8001 is not set +# CONFIG_SCSI_IPS is not set +# CONFIG_SCSI_CXGB3_ISCSI is not set +# CONFIG_SCSI_CXGB4_ISCSI is not set diff --git a/config-arm64 b/config-arm64 index 02730203c..46cf8306d 100644 --- a/config-arm64 +++ b/config-arm64 @@ -81,3 +81,33 @@ CONFIG_VM_EVENT_COUNTERS=y # dma issues in headers # CONFIG_PARPORT_PC is not set # CONFIG_VGA_CONSOLE is not set + +# CONFIG_CHARGER_MAX8997 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_S2MPS11 is not set +# CONFIG_LEDS_MAX8997 is not set +# CONFIG_RTC_DRV_MAX8997 is not set +# CONFIG_EXTCON_MAX8997 is not set +# CONFIG_MFD_MAX8997 is not set +# CONFIG_MFD_SEC_CORE is not set diff --git a/config-armv7 b/config-armv7 index 533b1be01..bc2788b3a 100644 --- a/config-armv7 +++ b/config-armv7 @@ -116,10 +116,10 @@ CONFIG_TWL4030_WATCHDOG=m CONFIG_TI_ST=m CONFIG_TI_EDMA=y CONFIG_TI_DAC7512=m -CONFIG_TI_DAVINCI_EMAC=m -CONFIG_TI_DAVINCI_MDIO=m -CONFIG_TI_DAVINCI_CPDMA=m -CONFIG_TI_CPSW=m +CONFIG_TI_DAVINCI_EMAC=y +CONFIG_TI_DAVINCI_MDIO=y +CONFIG_TI_DAVINCI_CPDMA=y +CONFIG_TI_CPSW=y CONFIG_TI_CPTS=y CONFIG_TI_EMIF=m CONFIG_REGULATOR_TI_ABB=y @@ -142,7 +142,7 @@ CONFIG_TWL6030_PWM=m CONFIG_TWL6040_CORE=y CONFIG_CLK_TWL6040=m CONFIG_OMAP_INTERCONNECT=m -CONFIG_MFD_TI_AM335X_TSCADC=m +CONFIG_MFD_TI_AM335X_TSCADC=y CONFIG_MFD_OMAP_USB_HOST=y CONFIG_MTD_ONENAND_OMAP2=m CONFIG_HDQ_MASTER_OMAP=m @@ -154,11 +154,12 @@ CONFIG_OMAP_USB3=m CONFIG_USB_EHCI_HCD_OMAP=m CONFIG_USB_OHCI_HCD_PLATFORM=m CONFIG_USB_OHCI_HCD_OMAP3=y -CONFIG_USB_MUSB_AM35X=m -CONFIG_USB_MUSB_OMAP2PLUS=m -CONFIG_USB_MUSB_HDRC=m -CONFIG_USB_GADGET_MUSB_HDRC=m -# CONFIG_MUSB_PIO_ONLY is not set +CONFIG_USB_MUSB_AM35X=y +CONFIG_USB_TI_CPPI41_DMA=y +CONFIG_AM335X_PHY_USB=y +# CONFIG_USB_MUSB_OMAP2PLUS is not set +CONFIG_USB_MUSB_HDRC=y +# CONFIG_USB_GADGET_MUSB_HDRC is not set # CONFIG_USB_MUSB_DEBUG is not set CONFIG_OMAP_CONTROL_USB=m CONFIG_MMC_OMAP=y @@ -598,7 +599,7 @@ CONFIG_REGULATOR_MAX8952=m CONFIG_REGULATOR_MAX8973=m # usb gadget -CONFIG_USB_GADGET=m +CONFIG_USB_GADGET=y CONFIG_USB_GADGET_VBUS_DRAW=100 CONFIG_USB_GADGET_STORAGE_NUM_BUFFERS=2 # CONFIG_USB_FSL_USB2 is not set diff --git a/config-armv7-generic b/config-armv7-generic index d16b7ea2e..9b6defb47 100644 --- a/config-armv7-generic +++ b/config-armv7-generic @@ -307,7 +307,7 @@ CONFIG_RTC_DRV_TPS65910=m CONFIG_RTC_DRV_TPS80031=m # Regulators -ONFIG_REGULATOR=y +CONFIG_REGULATOR=y CONFIG_RFKILL_REGULATOR=m CONFIG_CHARGER_MANAGER=y # CONFIG_REGULATOR_DUMMY is not set diff --git a/config-armv7-lpae b/config-armv7-lpae index 831f662fc..16aa0edc7 100644 --- a/config-armv7-lpae +++ b/config-armv7-lpae @@ -134,3 +134,31 @@ CONFIG_S3C_LOWLEVEL_UART_PORT=1 # CONFIG_S3C2410_WATCHDOG is not set # CONFIG_MMC_SDHCI_S3C is not set # CONFIG_TEGRA_HOST1X is not set + +# CONFIG_CHARGER_MAX8997 is not set +# CONFIG_MFD_AS3711 is not set +# CONFIG_PMIC_ADP5520 is not set +# CONFIG_MFD_AAT2870_CORE is not set +# CONFIG_PMIC_DA903X is not set +# CONFIG_MFD_DA9052_I2C is not set +# CONFIG_MFD_DA9055 is not set +# CONFIG_MFD_88PM800 is not set +# CONFIG_MFD_88PM805 is not set +# CONFIG_MFD_MAX77686 is not set +# CONFIG_MFD_MAX77693 is not set +# CONFIG_MFD_MAX8907 is not set +# CONFIG_MFD_RC5T583 is not set +# CONFIG_MFD_SMSC is not set +# CONFIG_MFD_LP8788 is not set +# CONFIG_MFD_PALMAS is not set +# CONFIG_MFD_TPS65090 is not set +# CONFIG_MFD_TPS65910 is not set +# CONFIG_MFD_TPS65912_I2C is not set +# CONFIG_MFD_TPS80031 is not set +# CONFIG_TWL4030_CORE is not set +# CONFIG_TWL6040_CORE is not set +# CONFIG_REGULATOR_LP872X is not set +# CONFIG_REGULATOR_S2MPS11 is not set +# CONFIG_LEDS_MAX8997 is not set +# CONFIG_RTC_DRV_MAX8997 is not set +# CONFIG_EXTCON_MAX8997 is not set diff --git a/config-generic b/config-generic index 4f21bedcf..681b22309 100644 --- a/config-generic +++ b/config-generic @@ -4863,3 +4863,5 @@ CONFIG_FMC_CHARDEV=m # CONFIG_CRYPTO_KEY_TYPE is not set # CONFIG_PGP_LIBRARY is not set # CONFIG_PGP_PRELOAD is not set + +# CONFIG_AM335X_PHY_USB is not set diff --git a/kernel.spec b/kernel.spec index 1f648d887..dbc0788c6 100644 --- a/kernel.spec +++ b/kernel.spec @@ -62,7 +62,7 @@ Summary: The Linux kernel # For non-released -rc kernels, this will be appended after the rcX and # gitX tags, so a 3 here would become part of release "0.rcX.gitX.3" # -%global baserelease 301 +%global baserelease 302 %global fedora_build %{baserelease} # base_sublevel is the kernel version we're starting with and patching @@ -716,24 +716,7 @@ Patch21030: arm-wandboard-quad.patch # https://git.kernel.org/cgit/linux/kernel/git/broonie/sound.git/patch/?id=3f1a91aa25579ba5e7268a47a73d2a83e4802c62 # AM33xx -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 +Patch21100: am335x-bone.patch #rhbz 754518 Patch21235: scsi-sd_revalidate_disk-prevent-NULL-ptr-deref.patch @@ -1382,24 +1365,7 @@ ApplyPatch arm-tegra-usb-no-reset-linux33.patch ApplyPatch arm-wandboard-quad.patch # Fix OMAP and AM33xx (BeagleBone) -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 +ApplyPatch am335x-bone.patch # # bugfixes to drivers and filesystems @@ -2394,6 +2360,11 @@ fi # ||----w | # || || %changelog +* Fri Oct 11 2013 Kyle McMartin - 3.11.4-302 +- Enable Beaglebone Black support, drop split up patches in favour of a + git patch. +- Fix up some config options to make BBB work better. + * Fri Oct 11 2013 Josh Boyer - Fix segfault in cpupower set (rhbz 1000439)