Browse Source

Merge branch 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci

* 'davinci-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/khilman/linux-davinci: (50 commits)
  davinci: fix remaining board support after io_pgoffst removal
  davinci: mityomapl138: make file local data static
  arm/davinci: remove duplicated include
  davinci: Initial support for Omapl138-Hawkboard
  davinci: MityDSP-L138/MityARM-1808 read MAC address from I2C Prom
  davinci: add tnetv107x touchscreen platform device
  input: add driver for tnetv107x touchscreen controller
  davinci: add keypad config for tnetv107x evm board
  davinci: add tnetv107x keypad platform device
  input: add driver for tnetv107x on-chip keypad controller
  net: davinci_emac: cleanup unused cpdma code
  net: davinci_emac: switch to new cpdma layer
  net: davinci_emac: separate out cpdma code
  net: davinci_emac: cleanup unused mdio emac code
  omap: cleanup unused davinci mdio arch code
  davinci: cleanup mdio arch code and switch to phy_id
  net: davinci_emac: switch to new mdio
  omap: add mdio platform devices
  davinci: add mdio platform devices
  net: davinci_emac: separate out davinci mdio
  ...

Fix up trivial conflict in drivers/input/keyboard/Kconfig (two entries
added next to each other - one from the davinci merge, one from the
input merge)
Linus Torvalds 14 years ago
parent
commit
72e58063d6
51 changed files with 3714 additions and 983 deletions
  1. 2 2
      MAINTAINERS
  2. 3 0
      arch/arm/configs/da8xx_omapl_defconfig
  3. 46 30
      arch/arm/mach-davinci/Kconfig
  4. 3 1
      arch/arm/mach-davinci/Makefile
  5. 133 0
      arch/arm/mach-davinci/aemif.c
  6. 18 6
      arch/arm/mach-davinci/board-da830-evm.c
  7. 72 20
      arch/arm/mach-davinci/board-da850-evm.c
  8. 5 6
      arch/arm/mach-davinci/board-dm365-evm.c
  9. 14 6
      arch/arm/mach-davinci/board-dm644x-evm.c
  10. 16 5
      arch/arm/mach-davinci/board-dm646x-evm.c
  11. 422 0
      arch/arm/mach-davinci/board-mityomapl138.c
  12. 2 5
      arch/arm/mach-davinci/board-neuros-osd2.c
  13. 62 0
      arch/arm/mach-davinci/board-omapl138-hawk.c
  14. 2 5
      arch/arm/mach-davinci/board-sffsdr.c
  15. 56 0
      arch/arm/mach-davinci/board-tnetv107x-evm.c
  16. 74 1
      arch/arm/mach-davinci/clock.c
  17. 5 0
      arch/arm/mach-davinci/clock.h
  18. 26 2
      arch/arm/mach-davinci/cpufreq.c
  19. 39 37
      arch/arm/mach-davinci/da850.c
  20. 66 4
      arch/arm/mach-davinci/devices-da8xx.c
  21. 50 0
      arch/arm/mach-davinci/devices-tnetv107x.c
  22. 1 1
      arch/arm/mach-davinci/devices.c
  23. 21 2
      arch/arm/mach-davinci/dm365.c
  24. 21 2
      arch/arm/mach-davinci/dm644x.c
  25. 20 2
      arch/arm/mach-davinci/dm646x.c
  26. 6 2
      arch/arm/mach-davinci/dma.c
  27. 36 0
      arch/arm/mach-davinci/include/mach/aemif.h
  28. 3 4
      arch/arm/mach-davinci/include/mach/da8xx.h
  29. 1 1
      arch/arm/mach-davinci/include/mach/dm365.h
  30. 1 1
      arch/arm/mach-davinci/include/mach/dm644x.h
  31. 1 1
      arch/arm/mach-davinci/include/mach/dm646x.h
  32. 3 3
      arch/arm/mach-davinci/include/mach/nand.h
  33. 1 0
      arch/arm/mach-davinci/include/mach/psc.h
  34. 3 0
      arch/arm/mach-davinci/include/mach/tnetv107x.h
  35. 2 0
      arch/arm/mach-davinci/include/mach/uncompress.h
  36. 9 2
      arch/arm/mach-davinci/tnetv107x.c
  37. 26 5
      arch/arm/mach-omap2/board-am3517evm.c
  38. 9 0
      drivers/input/keyboard/Kconfig
  39. 1 0
      drivers/input/keyboard/Makefile
  40. 340 0
      drivers/input/keyboard/tnetv107x-keypad.c
  41. 9 0
      drivers/input/touchscreen/Kconfig
  42. 1 0
      drivers/input/touchscreen/Makefile
  43. 396 0
      drivers/input/touchscreen/tnetv107x-ts.c
  44. 23 38
      drivers/mtd/nand/davinci_nand.c
  45. 21 0
      drivers/net/Kconfig
  46. 2 0
      drivers/net/Makefile
  47. 965 0
      drivers/net/davinci_cpdma.c
  48. 108 0
      drivers/net/davinci_cpdma.h
  49. 80 786
      drivers/net/davinci_emac.c
  50. 475 0
      drivers/net/davinci_mdio.c
  51. 13 3
      include/linux/davinci_emac.h

+ 2 - 2
MAINTAINERS

@@ -5388,8 +5388,8 @@ F:	drivers/*/*s3c2410*
 F:	drivers/*/*/*s3c2410*
 F:	drivers/*/*/*s3c2410*
 
 
 TI DAVINCI MACHINE SUPPORT
 TI DAVINCI MACHINE SUPPORT
-P:	Kevin Hilman
-M:	davinci-linux-open-source@linux.davincidsp.com
+M:	Kevin Hilman <khilman@deeprootsystems.com>
+L:	davinci-linux-open-source@linux.davincidsp.com (subscribers-only)
 Q:	http://patchwork.kernel.org/project/linux-davinci/list/
 Q:	http://patchwork.kernel.org/project/linux-davinci/list/
 S:	Supported
 S:	Supported
 F:	arch/arm/mach-davinci
 F:	arch/arm/mach-davinci

+ 3 - 0
arch/arm/configs/da8xx_omapl_defconfig

@@ -17,6 +17,8 @@ CONFIG_MODVERSIONS=y
 CONFIG_ARCH_DAVINCI=y
 CONFIG_ARCH_DAVINCI=y
 CONFIG_ARCH_DAVINCI_DA830=y
 CONFIG_ARCH_DAVINCI_DA830=y
 CONFIG_ARCH_DAVINCI_DA850=y
 CONFIG_ARCH_DAVINCI_DA850=y
+CONFIG_MACH_MITYOMAPL138=y
+CONFIG_MACH_OMAPL138_HAWKBOARD=y
 CONFIG_DAVINCI_RESET_CLOCKS=y
 CONFIG_DAVINCI_RESET_CLOCKS=y
 CONFIG_NO_HZ=y
 CONFIG_NO_HZ=y
 CONFIG_HIGH_RES_TIMERS=y
 CONFIG_HIGH_RES_TIMERS=y
@@ -79,6 +81,7 @@ CONFIG_I2C_DAVINCI=y
 # CONFIG_HWMON is not set
 # CONFIG_HWMON is not set
 CONFIG_WATCHDOG=y
 CONFIG_WATCHDOG=y
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR=y
+CONFIG_REGULATOR_DUMMY=y
 CONFIG_REGULATOR_TPS6507X=y
 CONFIG_REGULATOR_TPS6507X=y
 CONFIG_FB=y
 CONFIG_FB=y
 CONFIG_FB_DA8XX=y
 CONFIG_FB_DA8XX=y

+ 46 - 30
arch/arm/mach-davinci/Kconfig

@@ -20,23 +20,23 @@ config ARCH_DAVINCI_DM644x
 	select ARCH_DAVINCI_DMx
 	select ARCH_DAVINCI_DMx
 
 
 config ARCH_DAVINCI_DM355
 config ARCH_DAVINCI_DM355
-        bool "DaVinci 355 based system"
+	bool "DaVinci 355 based system"
 	select AINTC
 	select AINTC
 	select ARCH_DAVINCI_DMx
 	select ARCH_DAVINCI_DMx
 
 
 config ARCH_DAVINCI_DM646x
 config ARCH_DAVINCI_DM646x
-        bool "DaVinci 646x based system"
+	bool "DaVinci 646x based system"
 	select AINTC
 	select AINTC
 	select ARCH_DAVINCI_DMx
 	select ARCH_DAVINCI_DMx
 
 
 config ARCH_DAVINCI_DA830
 config ARCH_DAVINCI_DA830
-        bool "DA830/OMAP-L137 based system"
+	bool "DA830/OMAP-L137/AM17x based system"
 	select CP_INTC
 	select CP_INTC
 	select ARCH_DAVINCI_DA8XX
 	select ARCH_DAVINCI_DA8XX
 	select CPU_DCACHE_WRITETHROUGH # needed on silicon revs 1.0, 1.1
 	select CPU_DCACHE_WRITETHROUGH # needed on silicon revs 1.0, 1.1
 
 
 config ARCH_DAVINCI_DA850
 config ARCH_DAVINCI_DA850
-	bool "DA850/OMAP-L138 based system"
+	bool "DA850/OMAP-L138/AM18x based system"
 	select CP_INTC
 	select CP_INTC
 	select ARCH_DAVINCI_DA8XX
 	select ARCH_DAVINCI_DA8XX
 	select ARCH_HAS_CPUFREQ
 	select ARCH_HAS_CPUFREQ
@@ -115,21 +115,21 @@ config MACH_DAVINCI_DM365_EVM
 	  for development is a DM365 EVM
 	  for development is a DM365 EVM
 
 
 config MACH_DAVINCI_DA830_EVM
 config MACH_DAVINCI_DA830_EVM
-	bool "TI DA830/OMAP-L137 Reference Platform"
+	bool "TI DA830/OMAP-L137/AM17x Reference Platform"
 	default ARCH_DAVINCI_DA830
 	default ARCH_DAVINCI_DA830
 	depends on ARCH_DAVINCI_DA830
 	depends on ARCH_DAVINCI_DA830
 	select GPIO_PCF857X
 	select GPIO_PCF857X
 	help
 	help
-	  Say Y here to select the TI DA830/OMAP-L137 Evaluation Module.
+	  Say Y here to select the TI DA830/OMAP-L137/AM17x Evaluation Module.
 
 
 choice
 choice
-	prompt "Select DA830/OMAP-L137 UI board peripheral"
+	prompt "Select DA830/OMAP-L137/AM17x UI board peripheral"
 	depends on MACH_DAVINCI_DA830_EVM
 	depends on MACH_DAVINCI_DA830_EVM
 	help
 	help
-	  The presence of UI card on the DA830/OMAP-L137 EVM is detected
-	  automatically based on successful probe of the I2C based GPIO
-	  expander on that board. This option selected in this menu has
-	  an effect only in case of a successful UI card detection.
+	  The presence of UI card on the DA830/OMAP-L137/AM17x EVM is
+	  detected automatically based on successful probe of the I2C
+	  based GPIO expander on that board. This option selected in this
+	  menu has an effect only in case of a successful UI card detection.
 
 
 config DA830_UI_LCD
 config DA830_UI_LCD
 	bool "LCD"
 	bool "LCD"
@@ -140,23 +140,23 @@ config DA830_UI_LCD
 config DA830_UI_NAND
 config DA830_UI_NAND
 	bool "NAND flash"
 	bool "NAND flash"
 	help
 	help
-	  Say Y here to use the NAND flash.  Do not forget to setup
+	  Say Y here to use the NAND flash. Do not forget to setup
 	  the switch correctly.
 	  the switch correctly.
 endchoice
 endchoice
 
 
 config MACH_DAVINCI_DA850_EVM
 config MACH_DAVINCI_DA850_EVM
-	bool "TI DA850/OMAP-L138 Reference Platform"
+	bool "TI DA850/OMAP-L138/AM18x Reference Platform"
 	default ARCH_DAVINCI_DA850
 	default ARCH_DAVINCI_DA850
 	depends on ARCH_DAVINCI_DA850
 	depends on ARCH_DAVINCI_DA850
 	select GPIO_PCA953X
 	select GPIO_PCA953X
 	help
 	help
-	  Say Y here to select the TI DA850/OMAP-L138 Evaluation Module.
+	  Say Y here to select the TI DA850/OMAP-L138/AM18x Evaluation Module.
 
 
 choice
 choice
 	prompt "Select peripherals connected to expander on UI board"
 	prompt "Select peripherals connected to expander on UI board"
 	depends on MACH_DAVINCI_DA850_EVM
 	depends on MACH_DAVINCI_DA850_EVM
 	help
 	help
-	  The presence of User Interface (UI) card on the DA850/OMAP-L138
+	  The presence of User Interface (UI) card on the DA850/OMAP-L138/AM18x
 	  EVM is detected automatically based on successful probe of the I2C
 	  EVM is detected automatically based on successful probe of the I2C
 	  based GPIO expander on that card. This option selected in this
 	  based GPIO expander on that card. This option selected in this
 	  menu has an effect only in case of a successful UI card detection.
 	  menu has an effect only in case of a successful UI card detection.
@@ -165,13 +165,13 @@ config DA850_UI_NONE
 	bool "No peripheral is enabled"
 	bool "No peripheral is enabled"
 	help
 	help
 	  Say Y if you do not want to enable any of the peripherals connected
 	  Say Y if you do not want to enable any of the peripherals connected
-	  to TCA6416 expander on DA850/OMAP-L138 EVM UI card
+	  to TCA6416 expander on DA850/OMAP-L138/AM18x EVM UI card
 
 
 config DA850_UI_RMII
 config DA850_UI_RMII
 	bool "RMII Ethernet PHY"
 	bool "RMII Ethernet PHY"
 	help
 	help
-	  Say Y if you want to use the RMII PHY on the DA850/OMAP-L138 EVM.
-	  This PHY is found on the UI daughter card that is supplied with
+	  Say Y if you want to use the RMII PHY on the DA850/OMAP-L138/AM18x
+	  EVM. This PHY is found on the UI daughter card that is supplied with
 	  the EVM.
 	  the EVM.
 	  NOTE: Please take care while choosing this option, MII PHY will
 	  NOTE: Please take care while choosing this option, MII PHY will
 	  not be functional if RMII mode is selected.
 	  not be functional if RMII mode is selected.
@@ -185,6 +185,22 @@ config MACH_TNETV107X
 	help
 	help
 	  Say Y here to select the TI TNETV107X Evaluation Module.
 	  Say Y here to select the TI TNETV107X Evaluation Module.
 
 
+config MACH_MITYOMAPL138
+	bool "Critical Link MityDSP-L138/MityARM-1808 SoM"
+	depends on ARCH_DAVINCI_DA850
+	help
+	  Say Y here to select the Critical Link MityDSP-L138/MityARM-1808
+	  System on Module.  Information on this SoM may be found at
+	  http://www.mitydsp.com
+
+config MACH_OMAPL138_HAWKBOARD
+	bool "TI AM1808 / OMAPL-138 Hawkboard platform"
+	depends on ARCH_DAVINCI_DA850
+	help
+	  Say Y here to select the TI AM1808 / OMAPL-138 Hawkboard platform .
+	  Information of this board may be found at
+	  http://www.hawkboard.org/
+
 config DAVINCI_MUX
 config DAVINCI_MUX
 	bool "DAVINCI multiplexing support"
 	bool "DAVINCI multiplexing support"
 	depends on ARCH_DAVINCI
 	depends on ARCH_DAVINCI
@@ -195,20 +211,20 @@ config DAVINCI_MUX
 	  say Y.
 	  say Y.
 
 
 config DAVINCI_MUX_DEBUG
 config DAVINCI_MUX_DEBUG
-        bool "Multiplexing debug output"
-        depends on DAVINCI_MUX
-        help
-          Makes the multiplexing functions print out a lot of debug info.
-          This is useful if you want to find out the correct values of the
-          multiplexing registers.
+	bool "Multiplexing debug output"
+	depends on DAVINCI_MUX
+	help
+	  Makes the multiplexing functions print out a lot of debug info.
+	  This is useful if you want to find out the correct values of the
+	  multiplexing registers.
 
 
 config DAVINCI_MUX_WARNINGS
 config DAVINCI_MUX_WARNINGS
-        bool "Warn about pins the bootloader didn't set up"
-        depends on DAVINCI_MUX
-        help
-          Choose Y here to warn whenever driver initialization logic needs
-          to change the pin multiplexing setup.  When there are no warnings
-          printed, it's safe to deselect DAVINCI_MUX for your product.
+	bool "Warn about pins the bootloader didn't set up"
+	depends on DAVINCI_MUX
+	help
+	  Choose Y here to warn whenever driver initialization logic needs
+	  to change the pin multiplexing setup. When there are no warnings
+	  printed, it's safe to deselect DAVINCI_MUX for your product.
 
 
 config DAVINCI_RESET_CLOCKS
 config DAVINCI_RESET_CLOCKS
 	bool "Reset unused clocks during boot"
 	bool "Reset unused clocks during boot"

+ 3 - 1
arch/arm/mach-davinci/Makefile

@@ -5,7 +5,7 @@
 
 
 # Common objects
 # Common objects
 obj-y 			:= time.o clock.o serial.o io.o psc.o \
 obj-y 			:= time.o clock.o serial.o io.o psc.o \
-			   gpio.o dma.o usb.o common.o sram.o
+			   gpio.o dma.o usb.o common.o sram.o aemif.o
 
 
 obj-$(CONFIG_DAVINCI_MUX)		+= mux.o
 obj-$(CONFIG_DAVINCI_MUX)		+= mux.o
 
 
@@ -33,6 +33,8 @@ obj-$(CONFIG_MACH_DAVINCI_DM365_EVM)	+= board-dm365-evm.o
 obj-$(CONFIG_MACH_DAVINCI_DA830_EVM)	+= board-da830-evm.o
 obj-$(CONFIG_MACH_DAVINCI_DA830_EVM)	+= board-da830-evm.o
 obj-$(CONFIG_MACH_DAVINCI_DA850_EVM)	+= board-da850-evm.o
 obj-$(CONFIG_MACH_DAVINCI_DA850_EVM)	+= board-da850-evm.o
 obj-$(CONFIG_MACH_TNETV107X)		+= board-tnetv107x-evm.o
 obj-$(CONFIG_MACH_TNETV107X)		+= board-tnetv107x-evm.o
+obj-$(CONFIG_MACH_MITYOMAPL138)		+= board-mityomapl138.o
+obj-$(CONFIG_MACH_OMAPL138_HAWKBOARD)	+= board-omapl138-hawk.o
 
 
 # Power Management
 # Power Management
 obj-$(CONFIG_CPU_FREQ)			+= cpufreq.o
 obj-$(CONFIG_CPU_FREQ)			+= cpufreq.o

+ 133 - 0
arch/arm/mach-davinci/aemif.c

@@ -0,0 +1,133 @@
+/*
+ * AEMIF support for DaVinci SoCs
+ *
+ * Copyright (C) 2010 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.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/time.h>
+
+#include <mach/aemif.h>
+
+/* Timing value configuration */
+
+#define TA(x)		((x) << 2)
+#define RHOLD(x)	((x) << 4)
+#define RSTROBE(x)	((x) << 7)
+#define RSETUP(x)	((x) << 13)
+#define WHOLD(x)	((x) << 17)
+#define WSTROBE(x)	((x) << 20)
+#define WSETUP(x)	((x) << 26)
+
+#define TA_MAX		0x3
+#define RHOLD_MAX	0x7
+#define RSTROBE_MAX	0x3f
+#define RSETUP_MAX	0xf
+#define WHOLD_MAX	0x7
+#define WSTROBE_MAX	0x3f
+#define WSETUP_MAX	0xf
+
+#define TIMING_MASK	(TA(TA_MAX) | \
+				RHOLD(RHOLD_MAX) | \
+				RSTROBE(RSTROBE_MAX) |	\
+				RSETUP(RSETUP_MAX) | \
+				WHOLD(WHOLD_MAX) | \
+				WSTROBE(WSTROBE_MAX) | \
+				WSETUP(WSETUP_MAX))
+
+/*
+ * aemif_calc_rate - calculate timing data.
+ * @wanted: The cycle time needed in nanoseconds.
+ * @clk: The input clock rate in kHz.
+ * @max: The maximum divider value that can be programmed.
+ *
+ * On success, returns the calculated timing value minus 1 for easy
+ * programming into AEMIF timing registers, else negative errno.
+ */
+static int aemif_calc_rate(int wanted, unsigned long clk, int max)
+{
+	int result;
+
+	result = DIV_ROUND_UP((wanted * clk), NSEC_PER_MSEC) - 1;
+
+	pr_debug("%s: result %d from %ld, %d\n", __func__, result, clk, wanted);
+
+	/* It is generally OK to have a more relaxed timing than requested... */
+	if (result < 0)
+		result = 0;
+
+	/* ... But configuring tighter timings is not an option. */
+	else if (result > max)
+		result = -EINVAL;
+
+	return result;
+}
+
+/**
+ * davinci_aemif_setup_timing - setup timing values for a given AEMIF interface
+ * @t: timing values to be progammed
+ * @base: The virtual base address of the AEMIF interface
+ * @cs: chip-select to program the timing values for
+ *
+ * This function programs the given timing values (in real clock) into the
+ * AEMIF registers taking the AEMIF clock into account.
+ *
+ * This function does not use any locking while programming the AEMIF
+ * because it is expected that there is only one user of a given
+ * chip-select.
+ *
+ * Returns 0 on success, else negative errno.
+ */
+int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
+					void __iomem *base, unsigned cs)
+{
+	unsigned set, val;
+	unsigned ta, rhold, rstrobe, rsetup, whold, wstrobe, wsetup;
+	unsigned offset = A1CR_OFFSET + cs * 4;
+	struct clk *aemif_clk;
+	unsigned long clkrate;
+
+	if (!t)
+		return 0;	/* Nothing to do */
+
+	aemif_clk = clk_get(NULL, "aemif");
+	if (IS_ERR(aemif_clk))
+		return PTR_ERR(aemif_clk);
+
+	clkrate = clk_get_rate(aemif_clk);
+
+	clkrate /= 1000;	/* turn clock into kHz for ease of use */
+
+	ta	= aemif_calc_rate(t->ta, clkrate, TA_MAX);
+	rhold	= aemif_calc_rate(t->rhold, clkrate, RHOLD_MAX);
+	rstrobe	= aemif_calc_rate(t->rstrobe, clkrate, RSTROBE_MAX);
+	rsetup	= aemif_calc_rate(t->rsetup, clkrate, RSETUP_MAX);
+	whold	= aemif_calc_rate(t->whold, clkrate, WHOLD_MAX);
+	wstrobe	= aemif_calc_rate(t->wstrobe, clkrate, WSTROBE_MAX);
+	wsetup	= aemif_calc_rate(t->wsetup, clkrate, WSETUP_MAX);
+
+	if (ta < 0 || rhold < 0 || rstrobe < 0 || rsetup < 0 ||
+			whold < 0 || wstrobe < 0 || wsetup < 0) {
+		pr_err("%s: cannot get suitable timings\n", __func__);
+		return -EINVAL;
+	}
+
+	set = TA(ta) | RHOLD(rhold) | RSTROBE(rstrobe) | RSETUP(rsetup) |
+		WHOLD(whold) | WSTROBE(wstrobe) | WSETUP(wsetup);
+
+	val = __raw_readl(base + offset);
+	val &= ~TIMING_MASK;
+	val |= set;
+	__raw_writel(val, base + offset);
+
+	return 0;
+}
+EXPORT_SYMBOL(davinci_aemif_setup_timing);

+ 18 - 6
arch/arm/mach-davinci/board-da830-evm.c

@@ -29,10 +29,9 @@
 #include <mach/nand.h>
 #include <mach/nand.h>
 #include <mach/da8xx.h>
 #include <mach/da8xx.h>
 #include <mach/usb.h>
 #include <mach/usb.h>
+#include <mach/aemif.h>
 
 
-#define DA830_EVM_PHY_MASK		0x0
-#define DA830_EVM_MDIO_FREQUENCY	2200000	/* PHY bus frequency */
-
+#define DA830_EVM_PHY_ID		""
 /*
 /*
  * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4].
  * USB1 VBUS is controlled by GPIO1[15], over-current is reported on GPIO2[4].
  */
  */
@@ -360,6 +359,16 @@ static struct nand_bbt_descr da830_evm_nand_bbt_mirror_descr = {
 	.pattern	= da830_evm_nand_mirror_pattern
 	.pattern	= da830_evm_nand_mirror_pattern
 };
 };
 
 
+static struct davinci_aemif_timing da830_evm_nandflash_timing = {
+	.wsetup         = 24,
+	.wstrobe        = 21,
+	.whold          = 14,
+	.rsetup         = 19,
+	.rstrobe        = 50,
+	.rhold          = 0,
+	.ta             = 20,
+};
+
 static struct davinci_nand_pdata da830_evm_nand_pdata = {
 static struct davinci_nand_pdata da830_evm_nand_pdata = {
 	.parts		= da830_evm_nand_partitions,
 	.parts		= da830_evm_nand_partitions,
 	.nr_parts	= ARRAY_SIZE(da830_evm_nand_partitions),
 	.nr_parts	= ARRAY_SIZE(da830_evm_nand_partitions),
@@ -368,6 +377,7 @@ static struct davinci_nand_pdata da830_evm_nand_pdata = {
 	.options	= NAND_USE_FLASH_BBT,
 	.options	= NAND_USE_FLASH_BBT,
 	.bbt_td		= &da830_evm_nand_bbt_main_descr,
 	.bbt_td		= &da830_evm_nand_bbt_main_descr,
 	.bbt_md		= &da830_evm_nand_bbt_mirror_descr,
 	.bbt_md		= &da830_evm_nand_bbt_mirror_descr,
+	.timing         = &da830_evm_nandflash_timing,
 };
 };
 
 
 static struct resource da830_evm_nand_resources[] = {
 static struct resource da830_evm_nand_resources[] = {
@@ -546,9 +556,8 @@ static __init void da830_evm_init(void)
 
 
 	da830_evm_usb_init();
 	da830_evm_usb_init();
 
 
-	soc_info->emac_pdata->phy_mask = DA830_EVM_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = DA830_EVM_MDIO_FREQUENCY;
 	soc_info->emac_pdata->rmii_en = 1;
 	soc_info->emac_pdata->rmii_en = 1;
+	soc_info->emac_pdata->phy_id = DA830_EVM_PHY_ID;
 
 
 	ret = davinci_cfg_reg_list(da830_cpgmac_pins);
 	ret = davinci_cfg_reg_list(da830_cpgmac_pins);
 	if (ret)
 	if (ret)
@@ -586,6 +595,9 @@ static __init void da830_evm_init(void)
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 static int __init da830_evm_console_init(void)
 static int __init da830_evm_console_init(void)
 {
 {
+	if (!machine_is_davinci_da830_evm())
+		return 0;
+
 	return add_preferred_console("ttyS", 2, "115200");
 	return add_preferred_console("ttyS", 2, "115200");
 }
 }
 console_initcall(da830_evm_console_init);
 console_initcall(da830_evm_console_init);
@@ -596,7 +608,7 @@ static void __init da830_evm_map_io(void)
 	da830_init();
 	da830_init();
 }
 }
 
 
-MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137 EVM")
+MACHINE_START(DAVINCI_DA830_EVM, "DaVinci DA830/OMAP-L137/AM17x EVM")
 	.boot_params	= (DA8XX_DDR_BASE + 0x100),
 	.boot_params	= (DA8XX_DDR_BASE + 0x100),
 	.map_io		= da830_evm_map_io,
 	.map_io		= da830_evm_map_io,
 	.init_irq	= cp_intc_init,
 	.init_irq	= cp_intc_init,

+ 72 - 20
arch/arm/mach-davinci/board-da850-evm.c

@@ -26,7 +26,6 @@
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/physmap.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/machine.h>
 #include <linux/regulator/tps6507x.h>
 #include <linux/regulator/tps6507x.h>
-#include <linux/mfd/tps6507x.h>
 #include <linux/input/tps6507x-ts.h>
 #include <linux/input/tps6507x-ts.h>
 
 
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
@@ -36,10 +35,9 @@
 #include <mach/da8xx.h>
 #include <mach/da8xx.h>
 #include <mach/nand.h>
 #include <mach/nand.h>
 #include <mach/mux.h>
 #include <mach/mux.h>
+#include <mach/aemif.h>
 
 
-#define DA850_EVM_PHY_MASK		0x1
-#define DA850_EVM_MDIO_FREQUENCY	2200000 /* PHY bus frequency */
-
+#define DA850_EVM_PHY_ID		"0:00"
 #define DA850_LCD_PWR_PIN		GPIO_TO_PIN(2, 8)
 #define DA850_LCD_PWR_PIN		GPIO_TO_PIN(2, 8)
 #define DA850_LCD_BL_PIN		GPIO_TO_PIN(2, 15)
 #define DA850_LCD_BL_PIN		GPIO_TO_PIN(2, 15)
 
 
@@ -110,7 +108,7 @@ static struct platform_device da850_pm_device = {
  * to boot, using TI's tools to install the secondary boot loader
  * to boot, using TI's tools to install the secondary boot loader
  * (UBL) and U-Boot.
  * (UBL) and U-Boot.
  */
  */
-struct mtd_partition da850_evm_nandflash_partition[] = {
+static struct mtd_partition da850_evm_nandflash_partition[] = {
 	{
 	{
 		.name		= "u-boot env",
 		.name		= "u-boot env",
 		.offset		= 0,
 		.offset		= 0,
@@ -143,12 +141,23 @@ struct mtd_partition da850_evm_nandflash_partition[] = {
 	},
 	},
 };
 };
 
 
+static struct davinci_aemif_timing da850_evm_nandflash_timing = {
+	.wsetup		= 24,
+	.wstrobe	= 21,
+	.whold		= 14,
+	.rsetup		= 19,
+	.rstrobe	= 50,
+	.rhold		= 0,
+	.ta		= 20,
+};
+
 static struct davinci_nand_pdata da850_evm_nandflash_data = {
 static struct davinci_nand_pdata da850_evm_nandflash_data = {
 	.parts		= da850_evm_nandflash_partition,
 	.parts		= da850_evm_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(da850_evm_nandflash_partition),
 	.nr_parts	= ARRAY_SIZE(da850_evm_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_bits	= 4,
 	.ecc_bits	= 4,
 	.options	= NAND_USE_FLASH_BBT,
 	.options	= NAND_USE_FLASH_BBT,
+	.timing		= &da850_evm_nandflash_timing,
 };
 };
 
 
 static struct resource da850_evm_nandflash_resource[] = {
 static struct resource da850_evm_nandflash_resource[] = {
@@ -196,6 +205,30 @@ static void __init da850_evm_init_nor(void)
 	iounmap(aemif_addr);
 	iounmap(aemif_addr);
 }
 }
 
 
+static const short da850_evm_nand_pins[] = {
+	DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
+	DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7,
+	DA850_EMA_A_1, DA850_EMA_A_2, DA850_NEMA_CS_3, DA850_NEMA_CS_4,
+	DA850_NEMA_WE, DA850_NEMA_OE,
+	-1
+};
+
+static const short da850_evm_nor_pins[] = {
+	DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2,
+	DA850_NEMA_WE, DA850_NEMA_OE, DA850_EMA_D_0, DA850_EMA_D_1,
+	DA850_EMA_D_2, DA850_EMA_D_3, DA850_EMA_D_4, DA850_EMA_D_5,
+	DA850_EMA_D_6, DA850_EMA_D_7, DA850_EMA_D_8, DA850_EMA_D_9,
+	DA850_EMA_D_10, DA850_EMA_D_11, DA850_EMA_D_12, DA850_EMA_D_13,
+	DA850_EMA_D_14, DA850_EMA_D_15, DA850_EMA_A_0, DA850_EMA_A_1,
+	DA850_EMA_A_2, DA850_EMA_A_3, DA850_EMA_A_4, DA850_EMA_A_5,
+	DA850_EMA_A_6, DA850_EMA_A_7, DA850_EMA_A_8, DA850_EMA_A_9,
+	DA850_EMA_A_10, DA850_EMA_A_11, DA850_EMA_A_12, DA850_EMA_A_13,
+	DA850_EMA_A_14, DA850_EMA_A_15, DA850_EMA_A_16, DA850_EMA_A_17,
+	DA850_EMA_A_18, DA850_EMA_A_19, DA850_EMA_A_20, DA850_EMA_A_21,
+	DA850_EMA_A_22, DA850_EMA_A_23,
+	-1
+};
+
 static u32 ui_card_detected;
 static u32 ui_card_detected;
 
 
 #if defined(CONFIG_MMC_DAVINCI) || \
 #if defined(CONFIG_MMC_DAVINCI) || \
@@ -205,17 +238,17 @@ static u32 ui_card_detected;
 #define HAS_MMC 0
 #define HAS_MMC 0
 #endif
 #endif
 
 
-static __init void da850_evm_setup_nor_nand(void)
+static inline void da850_evm_setup_nor_nand(void)
 {
 {
 	int ret = 0;
 	int ret = 0;
 
 
 	if (ui_card_detected & !HAS_MMC) {
 	if (ui_card_detected & !HAS_MMC) {
-		ret = davinci_cfg_reg_list(da850_nand_pins);
+		ret = davinci_cfg_reg_list(da850_evm_nand_pins);
 		if (ret)
 		if (ret)
 			pr_warning("da850_evm_init: nand mux setup failed: "
 			pr_warning("da850_evm_init: nand mux setup failed: "
 					"%d\n", ret);
 					"%d\n", ret);
 
 
-		ret = davinci_cfg_reg_list(da850_nor_pins);
+		ret = davinci_cfg_reg_list(da850_evm_nor_pins);
 		if (ret)
 		if (ret)
 			pr_warning("da850_evm_init: nor mux setup failed: %d\n",
 			pr_warning("da850_evm_init: nor mux setup failed: %d\n",
 				ret);
 				ret);
@@ -406,7 +439,7 @@ static int da850_lcd_hw_init(void)
 /* TPS65070 voltage regulator support */
 /* TPS65070 voltage regulator support */
 
 
 /* 3.3V */
 /* 3.3V */
-struct regulator_consumer_supply tps65070_dcdc1_consumers[] = {
+static struct regulator_consumer_supply tps65070_dcdc1_consumers[] = {
 	{
 	{
 		.supply = "usb0_vdda33",
 		.supply = "usb0_vdda33",
 	},
 	},
@@ -416,7 +449,7 @@ struct regulator_consumer_supply tps65070_dcdc1_consumers[] = {
 };
 };
 
 
 /* 3.3V or 1.8V */
 /* 3.3V or 1.8V */
-struct regulator_consumer_supply tps65070_dcdc2_consumers[] = {
+static struct regulator_consumer_supply tps65070_dcdc2_consumers[] = {
 	{
 	{
 		.supply = "dvdd3318_a",
 		.supply = "dvdd3318_a",
 	},
 	},
@@ -429,14 +462,14 @@ struct regulator_consumer_supply tps65070_dcdc2_consumers[] = {
 };
 };
 
 
 /* 1.2V */
 /* 1.2V */
-struct regulator_consumer_supply tps65070_dcdc3_consumers[] = {
+static struct regulator_consumer_supply tps65070_dcdc3_consumers[] = {
 	{
 	{
 		.supply = "cvdd",
 		.supply = "cvdd",
 	},
 	},
 };
 };
 
 
 /* 1.8V LDO */
 /* 1.8V LDO */
-struct regulator_consumer_supply tps65070_ldo1_consumers[] = {
+static struct regulator_consumer_supply tps65070_ldo1_consumers[] = {
 	{
 	{
 		.supply = "sata_vddr",
 		.supply = "sata_vddr",
 	},
 	},
@@ -452,7 +485,7 @@ struct regulator_consumer_supply tps65070_ldo1_consumers[] = {
 };
 };
 
 
 /* 1.2V LDO */
 /* 1.2V LDO */
-struct regulator_consumer_supply tps65070_ldo2_consumers[] = {
+static struct regulator_consumer_supply tps65070_ldo2_consumers[] = {
 	{
 	{
 		.supply = "sata_vdd",
 		.supply = "sata_vdd",
 	},
 	},
@@ -475,7 +508,7 @@ static struct tps6507x_reg_platform_data tps6507x_platform_data = {
 	.defdcdc_default = true,
 	.defdcdc_default = true,
 };
 };
 
 
-struct regulator_init_data tps65070_regulator_data[] = {
+static struct regulator_init_data tps65070_regulator_data[] = {
 	/* dcdc1 */
 	/* dcdc1 */
 	{
 	{
 		.constraints = {
 		.constraints = {
@@ -576,6 +609,23 @@ static const short da850_evm_lcdc_pins[] = {
 	-1
 	-1
 };
 };
 
 
+static const short da850_evm_mii_pins[] = {
+	DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
+	DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
+	DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
+	DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
+	DA850_MDIO_D,
+	-1
+};
+
+static const short da850_evm_rmii_pins[] = {
+	DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
+	DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1,
+	DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK,
+	DA850_MDIO_D,
+	-1
+};
+
 static int __init da850_evm_config_emac(void)
 static int __init da850_evm_config_emac(void)
 {
 {
 	void __iomem *cfg_chip3_base;
 	void __iomem *cfg_chip3_base;
@@ -593,12 +643,12 @@ static int __init da850_evm_config_emac(void)
 
 
 	if (rmii_en) {
 	if (rmii_en) {
 		val |= BIT(8);
 		val |= BIT(8);
-		ret = davinci_cfg_reg_list(da850_rmii_pins);
+		ret = davinci_cfg_reg_list(da850_evm_rmii_pins);
 		pr_info("EMAC: RMII PHY configured, MII PHY will not be"
 		pr_info("EMAC: RMII PHY configured, MII PHY will not be"
 							" functional\n");
 							" functional\n");
 	} else {
 	} else {
 		val &= ~BIT(8);
 		val &= ~BIT(8);
-		ret = davinci_cfg_reg_list(da850_cpgmac_pins);
+		ret = davinci_cfg_reg_list(da850_evm_mii_pins);
 		pr_info("EMAC: MII PHY configured, RMII PHY will not be"
 		pr_info("EMAC: MII PHY configured, RMII PHY will not be"
 							" functional\n");
 							" functional\n");
 	}
 	}
@@ -625,8 +675,7 @@ static int __init da850_evm_config_emac(void)
 	/* Enable/Disable MII MDIO clock */
 	/* Enable/Disable MII MDIO clock */
 	gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en);
 	gpio_direction_output(DA850_MII_MDIO_CLKEN_PIN, rmii_en);
 
 
-	soc_info->emac_pdata->phy_mask = DA850_EVM_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = DA850_EVM_MDIO_FREQUENCY;
+	soc_info->emac_pdata->phy_id = DA850_EVM_PHY_ID;
 
 
 	ret = da8xx_register_emac();
 	ret = da8xx_register_emac();
 	if (ret)
 	if (ret)
@@ -787,7 +836,7 @@ static __init void da850_evm_init(void)
 	if (ret)
 	if (ret)
 		pr_warning("da850_evm_init: rtc setup failed: %d\n", ret);
 		pr_warning("da850_evm_init: rtc setup failed: %d\n", ret);
 
 
-	ret = da850_register_cpufreq();
+	ret = da850_register_cpufreq("pll0_sysclk3");
 	if (ret)
 	if (ret)
 		pr_warning("da850_evm_init: cpufreq registration failed: %d\n",
 		pr_warning("da850_evm_init: cpufreq registration failed: %d\n",
 				ret);
 				ret);
@@ -806,6 +855,9 @@ static __init void da850_evm_init(void)
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 #ifdef CONFIG_SERIAL_8250_CONSOLE
 static int __init da850_evm_console_init(void)
 static int __init da850_evm_console_init(void)
 {
 {
+	if (!machine_is_davinci_da850_evm())
+		return 0;
+
 	return add_preferred_console("ttyS", 2, "115200");
 	return add_preferred_console("ttyS", 2, "115200");
 }
 }
 console_initcall(da850_evm_console_init);
 console_initcall(da850_evm_console_init);
@@ -816,7 +868,7 @@ static void __init da850_evm_map_io(void)
 	da850_init();
 	da850_init();
 }
 }
 
 
-MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138 EVM")
+MACHINE_START(DAVINCI_DA850_EVM, "DaVinci DA850/OMAP-L138/AM18x EVM")
 	.boot_params	= (DA8XX_DDR_BASE + 0x100),
 	.boot_params	= (DA8XX_DDR_BASE + 0x100),
 	.map_io		= da850_evm_map_io,
 	.map_io		= da850_evm_map_io,
 	.init_irq	= cp_intc_init,
 	.init_irq	= cp_intc_init,

+ 5 - 6
arch/arm/mach-davinci/board-dm365-evm.c

@@ -54,9 +54,7 @@ static inline int have_tvp7002(void)
 	return 0;
 	return 0;
 }
 }
 
 
-#define DM365_EVM_PHY_MASK		(0x2)
-#define DM365_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
-
+#define DM365_EVM_PHY_ID		"0:01"
 /*
 /*
  * A MAX-II CPLD is used for various board control functions.
  * A MAX-II CPLD is used for various board control functions.
  */
  */
@@ -175,7 +173,9 @@ static struct at24_platform_data eeprom_info = {
 	.context	= (void *)0x7f00,
 	.context	= (void *)0x7f00,
 };
 };
 
 
-static struct snd_platform_data dm365_evm_snd_data;
+static struct snd_platform_data dm365_evm_snd_data = {
+	.asp_chan_q = EVENTQ_3,
+};
 
 
 static struct i2c_board_info i2c_info[] = {
 static struct i2c_board_info i2c_info[] = {
 	{
 	{
@@ -533,8 +533,7 @@ fail:
 
 
 		/* ... and ENET ... */
 		/* ... and ENET ... */
 		dm365evm_emac_configure();
 		dm365evm_emac_configure();
-		soc_info->emac_pdata->phy_mask = DM365_EVM_PHY_MASK;
-		soc_info->emac_pdata->mdio_max_freq = DM365_EVM_MDIO_FREQUENCY;
+		soc_info->emac_pdata->phy_id = DM365_EVM_PHY_ID;
 		resets &= ~BIT(3);
 		resets &= ~BIT(3);
 
 
 		/* ... and AIC33 */
 		/* ... and AIC33 */

+ 14 - 6
arch/arm/mach-davinci/board-dm644x-evm.c

@@ -37,10 +37,9 @@
 #include <mach/nand.h>
 #include <mach/nand.h>
 #include <mach/mmc.h>
 #include <mach/mmc.h>
 #include <mach/usb.h>
 #include <mach/usb.h>
+#include <mach/aemif.h>
 
 
-#define DM644X_EVM_PHY_MASK		(0x2)
-#define DM644X_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
-
+#define DM644X_EVM_PHY_ID		"0:01"
 #define LXT971_PHY_ID	(0x001378e2)
 #define LXT971_PHY_ID	(0x001378e2)
 #define LXT971_PHY_MASK	(0xfffffff0)
 #define LXT971_PHY_MASK	(0xfffffff0)
 
 
@@ -137,11 +136,22 @@ static struct mtd_partition davinci_evm_nandflash_partition[] = {
 	 */
 	 */
 };
 };
 
 
+static struct davinci_aemif_timing davinci_evm_nandflash_timing = {
+	.wsetup		= 20,
+	.wstrobe	= 40,
+	.whold		= 20,
+	.rsetup		= 10,
+	.rstrobe	= 40,
+	.rhold		= 10,
+	.ta		= 40,
+};
+
 static struct davinci_nand_pdata davinci_evm_nandflash_data = {
 static struct davinci_nand_pdata davinci_evm_nandflash_data = {
 	.parts		= davinci_evm_nandflash_partition,
 	.parts		= davinci_evm_nandflash_partition,
 	.nr_parts	= ARRAY_SIZE(davinci_evm_nandflash_partition),
 	.nr_parts	= ARRAY_SIZE(davinci_evm_nandflash_partition),
 	.ecc_mode	= NAND_ECC_HW,
 	.ecc_mode	= NAND_ECC_HW,
 	.options	= NAND_USE_FLASH_BBT,
 	.options	= NAND_USE_FLASH_BBT,
+	.timing		= &davinci_evm_nandflash_timing,
 };
 };
 
 
 static struct resource davinci_evm_nandflash_resource[] = {
 static struct resource davinci_evm_nandflash_resource[] = {
@@ -695,9 +705,7 @@ static __init void davinci_evm_init(void)
 	davinci_serial_init(&uart_config);
 	davinci_serial_init(&uart_config);
 	dm644x_init_asp(&dm644x_evm_snd_data);
 	dm644x_init_asp(&dm644x_evm_snd_data);
 
 
-	soc_info->emac_pdata->phy_mask = DM644X_EVM_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = DM644X_EVM_MDIO_FREQUENCY;
-
+	soc_info->emac_pdata->phy_id = DM644X_EVM_PHY_ID;
 	/* Register the fixup for PHY on DaVinci */
 	/* Register the fixup for PHY on DaVinci */
 	phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
 	phy_register_fixup_for_uid(LXT971_PHY_ID, LXT971_PHY_MASK,
 					davinci_phy_fixup);
 					davinci_phy_fixup);

+ 16 - 5
arch/arm/mach-davinci/board-dm646x-evm.c

@@ -42,6 +42,7 @@
 #include <mach/nand.h>
 #include <mach/nand.h>
 #include <mach/clock.h>
 #include <mach/clock.h>
 #include <mach/cdce949.h>
 #include <mach/cdce949.h>
+#include <mach/aemif.h>
 
 
 #include "clock.h"
 #include "clock.h"
 
 
@@ -71,6 +72,16 @@ static struct mtd_partition davinci_nand_partitions[] = {
 	}
 	}
 };
 };
 
 
+static struct davinci_aemif_timing dm6467tevm_nandflash_timing = {
+	.wsetup		= 29,
+	.wstrobe	= 24,
+	.whold		= 14,
+	.rsetup		= 19,
+	.rstrobe	= 33,
+	.rhold		= 0,
+	.ta		= 29,
+};
+
 static struct davinci_nand_pdata davinci_nand_data = {
 static struct davinci_nand_pdata davinci_nand_data = {
 	.mask_cle 		= 0x80000,
 	.mask_cle 		= 0x80000,
 	.mask_ale 		= 0x40000,
 	.mask_ale 		= 0x40000,
@@ -718,9 +729,7 @@ static struct davinci_uart_config uart_config __initdata = {
 	.enabled_uarts = (1 << 0),
 	.enabled_uarts = (1 << 0),
 };
 };
 
 
-#define DM646X_EVM_PHY_MASK		(0x2)
-#define DM646X_EVM_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
-
+#define DM646X_EVM_PHY_ID		"0:01"
 /*
 /*
  * The following EDMA channels/slots are not being used by drivers (for
  * The following EDMA channels/slots are not being used by drivers (for
  * example: Timer, GPIO, UART events etc) on dm646x, hence they are being
  * example: Timer, GPIO, UART events etc) on dm646x, hence they are being
@@ -763,6 +772,9 @@ static __init void evm_init(void)
 	dm646x_init_mcasp0(&dm646x_evm_snd_data[0]);
 	dm646x_init_mcasp0(&dm646x_evm_snd_data[0]);
 	dm646x_init_mcasp1(&dm646x_evm_snd_data[1]);
 	dm646x_init_mcasp1(&dm646x_evm_snd_data[1]);
 
 
+	if (machine_is_davinci_dm6467tevm())
+		davinci_nand_data.timing = &dm6467tevm_nandflash_timing;
+
 	platform_device_register(&davinci_nand_device);
 	platform_device_register(&davinci_nand_device);
 
 
 	dm646x_init_edma(dm646x_edma_rsv);
 	dm646x_init_edma(dm646x_edma_rsv);
@@ -770,8 +782,7 @@ static __init void evm_init(void)
 	if (HAS_ATA)
 	if (HAS_ATA)
 		davinci_init_ide();
 		davinci_init_ide();
 
 
-	soc_info->emac_pdata->phy_mask = DM646X_EVM_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = DM646X_EVM_MDIO_FREQUENCY;
+	soc_info->emac_pdata->phy_id = DM646X_EVM_PHY_ID;
 }
 }
 
 
 #define DM646X_EVM_REF_FREQ		27000000
 #define DM646X_EVM_REF_FREQ		27000000

+ 422 - 0
arch/arm/mach-davinci/board-mityomapl138.c

@@ -0,0 +1,422 @@
+/*
+ * Critical Link MityOMAP-L138 SoM
+ *
+ * Copyright (C) 2010 Critical Link LLC - http://www.criticallink.com
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of
+ * any kind, whether express or implied.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/platform_device.h>
+#include <linux/mtd/partitions.h>
+#include <linux/regulator/machine.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+#include <linux/etherdevice.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+#include <mach/common.h>
+#include <mach/cp_intc.h>
+#include <mach/da8xx.h>
+#include <mach/nand.h>
+#include <mach/mux.h>
+
+#define MITYOMAPL138_PHY_ID		"0:03"
+
+#define FACTORY_CONFIG_MAGIC	0x012C0138
+#define FACTORY_CONFIG_VERSION	0x00010001
+
+/* Data Held in On-Board I2C device */
+struct factory_config {
+	u32	magic;
+	u32	version;
+	u8	mac[6];
+	u32	fpga_type;
+	u32	spare;
+	u32	serialnumber;
+	char	partnum[32];
+};
+
+static struct factory_config factory_config;
+
+static void read_factory_config(struct memory_accessor *a, void *context)
+{
+	int ret;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	ret = a->read(a, (char *)&factory_config, 0, sizeof(factory_config));
+	if (ret != sizeof(struct factory_config)) {
+		pr_warning("MityOMAPL138: Read Factory Config Failed: %d\n",
+				ret);
+		return;
+	}
+
+	if (factory_config.magic != FACTORY_CONFIG_MAGIC) {
+		pr_warning("MityOMAPL138: Factory Config Magic Wrong (%X)\n",
+				factory_config.magic);
+		return;
+	}
+
+	if (factory_config.version != FACTORY_CONFIG_VERSION) {
+		pr_warning("MityOMAPL138: Factory Config Version Wrong (%X)\n",
+				factory_config.version);
+		return;
+	}
+
+	pr_info("MityOMAPL138: Found MAC = %pM\n", factory_config.mac);
+	pr_info("MityOMAPL138: Part Number = %s\n", factory_config.partnum);
+	if (is_valid_ether_addr(factory_config.mac))
+		memcpy(soc_info->emac_pdata->mac_addr,
+			factory_config.mac, ETH_ALEN);
+	else
+		pr_warning("MityOMAPL138: Invalid MAC found "
+				"in factory config block\n");
+}
+
+static struct at24_platform_data mityomapl138_fd_chip = {
+	.byte_len	= 256,
+	.page_size	= 8,
+	.flags		= AT24_FLAG_READONLY | AT24_FLAG_IRUGO,
+	.setup		= read_factory_config,
+	.context	= NULL,
+};
+
+static struct davinci_i2c_platform_data mityomap_i2c_0_pdata = {
+	.bus_freq	= 100,	/* kHz */
+	.bus_delay	= 0,	/* usec */
+};
+
+/* TPS65023 voltage regulator support */
+/* 1.2V Core */
+static struct regulator_consumer_supply tps65023_dcdc1_consumers[] = {
+	{
+		.supply = "cvdd",
+	},
+};
+
+/* 1.8V */
+static struct regulator_consumer_supply tps65023_dcdc2_consumers[] = {
+	{
+		.supply = "usb0_vdda18",
+	},
+	{
+		.supply = "usb1_vdda18",
+	},
+	{
+		.supply = "ddr_dvdd18",
+	},
+	{
+		.supply = "sata_vddr",
+	},
+};
+
+/* 1.2V */
+static struct regulator_consumer_supply tps65023_dcdc3_consumers[] = {
+	{
+		.supply = "sata_vdd",
+	},
+	{
+		.supply = "usb_cvdd",
+	},
+	{
+		.supply = "pll0_vdda",
+	},
+	{
+		.supply = "pll1_vdda",
+	},
+};
+
+/* 1.8V Aux LDO, not used */
+static struct regulator_consumer_supply tps65023_ldo1_consumers[] = {
+	{
+		.supply = "1.8v_aux",
+	},
+};
+
+/* FPGA VCC Aux (2.5 or 3.3) LDO */
+static struct regulator_consumer_supply tps65023_ldo2_consumers[] = {
+	{
+		.supply = "vccaux",
+	},
+};
+
+static struct regulator_init_data tps65023_regulator_data[] = {
+	/* dcdc1 */
+	{
+		.constraints = {
+			.min_uV = 1150000,
+			.max_uV = 1350000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS,
+			.boot_on = 1,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc1_consumers),
+		.consumer_supplies = tps65023_dcdc1_consumers,
+	},
+	/* dcdc2 */
+	{
+		.constraints = {
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+			.boot_on = 1,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc2_consumers),
+		.consumer_supplies = tps65023_dcdc2_consumers,
+	},
+	/* dcdc3 */
+	{
+		.constraints = {
+			.min_uV = 1200000,
+			.max_uV = 1200000,
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+			.boot_on = 1,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(tps65023_dcdc3_consumers),
+		.consumer_supplies = tps65023_dcdc3_consumers,
+	},
+	/* ldo1 */
+	{
+		.constraints = {
+			.min_uV = 1800000,
+			.max_uV = 1800000,
+			.valid_ops_mask = REGULATOR_CHANGE_STATUS,
+			.boot_on = 1,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(tps65023_ldo1_consumers),
+		.consumer_supplies = tps65023_ldo1_consumers,
+	},
+	/* ldo2 */
+	{
+		.constraints = {
+			.min_uV = 2500000,
+			.max_uV = 3300000,
+			.valid_ops_mask = REGULATOR_CHANGE_VOLTAGE |
+					  REGULATOR_CHANGE_STATUS,
+			.boot_on = 1,
+		},
+		.num_consumer_supplies = ARRAY_SIZE(tps65023_ldo2_consumers),
+		.consumer_supplies = tps65023_ldo2_consumers,
+	},
+};
+
+static struct i2c_board_info __initdata mityomap_tps65023_info[] = {
+	{
+		I2C_BOARD_INFO("tps65023", 0x48),
+		.platform_data = &tps65023_regulator_data[0],
+	},
+	{
+		I2C_BOARD_INFO("24c02", 0x50),
+		.platform_data = &mityomapl138_fd_chip,
+	},
+};
+
+static int __init pmic_tps65023_init(void)
+{
+	return i2c_register_board_info(1, mityomap_tps65023_info,
+					ARRAY_SIZE(mityomap_tps65023_info));
+}
+
+/*
+ * MityDSP-L138 includes a 256 MByte large-page NAND flash
+ * (128K blocks).
+ */
+static struct mtd_partition mityomapl138_nandflash_partition[] = {
+	{
+		.name		= "rootfs",
+		.offset		= 0,
+		.size		= SZ_128M,
+		.mask_flags	= 0, /* MTD_WRITEABLE, */
+	},
+	{
+		.name		= "homefs",
+		.offset		= MTDPART_OFS_APPEND,
+		.size		= MTDPART_SIZ_FULL,
+		.mask_flags	= 0,
+	},
+};
+
+static struct davinci_nand_pdata mityomapl138_nandflash_data = {
+	.parts		= mityomapl138_nandflash_partition,
+	.nr_parts	= ARRAY_SIZE(mityomapl138_nandflash_partition),
+	.ecc_mode	= NAND_ECC_HW,
+	.options	= NAND_USE_FLASH_BBT | NAND_BUSWIDTH_16,
+	.ecc_bits	= 1, /* 4 bit mode is not supported with 16 bit NAND */
+};
+
+static struct resource mityomapl138_nandflash_resource[] = {
+	{
+		.start	= DA8XX_AEMIF_CS3_BASE,
+		.end	= DA8XX_AEMIF_CS3_BASE + SZ_512K + 2 * SZ_1K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= DA8XX_AEMIF_CTL_BASE,
+		.end	= DA8XX_AEMIF_CTL_BASE + SZ_32K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device mityomapl138_nandflash_device = {
+	.name		= "davinci_nand",
+	.id		= 0,
+	.dev		= {
+		.platform_data	= &mityomapl138_nandflash_data,
+	},
+	.num_resources	= ARRAY_SIZE(mityomapl138_nandflash_resource),
+	.resource	= mityomapl138_nandflash_resource,
+};
+
+static struct platform_device *mityomapl138_devices[] __initdata = {
+	&mityomapl138_nandflash_device,
+};
+
+static void __init mityomapl138_setup_nand(void)
+{
+	platform_add_devices(mityomapl138_devices,
+				 ARRAY_SIZE(mityomapl138_devices));
+}
+
+static struct davinci_uart_config mityomapl138_uart_config __initdata = {
+	.enabled_uarts = 0x7,
+};
+
+static const short mityomap_mii_pins[] = {
+	DA850_MII_TXEN, DA850_MII_TXCLK, DA850_MII_COL, DA850_MII_TXD_3,
+	DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
+	DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
+	DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
+	DA850_MDIO_D,
+	-1
+};
+
+static const short mityomap_rmii_pins[] = {
+	DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
+	DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1,
+	DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK,
+	DA850_MDIO_D,
+	-1
+};
+
+static void __init mityomapl138_config_emac(void)
+{
+	void __iomem *cfg_chip3_base;
+	int ret;
+	u32 val;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	soc_info->emac_pdata->rmii_en = 0; /* hardcoded for now */
+
+	cfg_chip3_base = DA8XX_SYSCFG0_VIRT(DA8XX_CFGCHIP3_REG);
+	val = __raw_readl(cfg_chip3_base);
+
+	if (soc_info->emac_pdata->rmii_en) {
+		val |= BIT(8);
+		ret = davinci_cfg_reg_list(mityomap_rmii_pins);
+		pr_info("RMII PHY configured\n");
+	} else {
+		val &= ~BIT(8);
+		ret = davinci_cfg_reg_list(mityomap_mii_pins);
+		pr_info("MII PHY configured\n");
+	}
+
+	if (ret) {
+		pr_warning("mii/rmii mux setup failed: %d\n", ret);
+		return;
+	}
+
+	/* configure the CFGCHIP3 register for RMII or MII */
+	__raw_writel(val, cfg_chip3_base);
+
+	soc_info->emac_pdata->phy_id = MITYOMAPL138_PHY_ID;
+
+	ret = da8xx_register_emac();
+	if (ret)
+		pr_warning("emac registration failed: %d\n", ret);
+}
+
+static struct davinci_pm_config da850_pm_pdata = {
+	.sleepcount = 128,
+};
+
+static struct platform_device da850_pm_device = {
+	.name	= "pm-davinci",
+	.dev = {
+		.platform_data  = &da850_pm_pdata,
+	},
+	.id	= -1,
+};
+
+static void __init mityomapl138_init(void)
+{
+	int ret;
+
+	/* for now, no special EDMA channels are reserved */
+	ret = da850_register_edma(NULL);
+	if (ret)
+		pr_warning("edma registration failed: %d\n", ret);
+
+	ret = da8xx_register_watchdog();
+	if (ret)
+		pr_warning("watchdog registration failed: %d\n", ret);
+
+	davinci_serial_init(&mityomapl138_uart_config);
+
+	ret = da8xx_register_i2c(0, &mityomap_i2c_0_pdata);
+	if (ret)
+		pr_warning("i2c0 registration failed: %d\n", ret);
+
+	ret = pmic_tps65023_init();
+	if (ret)
+		pr_warning("TPS65023 PMIC init failed: %d\n", ret);
+
+	mityomapl138_setup_nand();
+
+	mityomapl138_config_emac();
+
+	ret = da8xx_register_rtc();
+	if (ret)
+		pr_warning("rtc setup failed: %d\n", ret);
+
+	ret = da850_register_cpufreq("pll0_sysclk3");
+	if (ret)
+		pr_warning("cpufreq registration failed: %d\n", ret);
+
+	ret = da8xx_register_cpuidle();
+	if (ret)
+		pr_warning("cpuidle registration failed: %d\n", ret);
+
+	ret = da850_register_pm(&da850_pm_device);
+	if (ret)
+		pr_warning("da850_evm_init: suspend registration failed: %d\n",
+				ret);
+}
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static int __init mityomapl138_console_init(void)
+{
+	if (!machine_is_mityomapl138())
+		return 0;
+
+	return add_preferred_console("ttyS", 1, "115200");
+}
+console_initcall(mityomapl138_console_init);
+#endif
+
+static void __init mityomapl138_map_io(void)
+{
+	da850_init();
+}
+
+MACHINE_START(MITYOMAPL138, "MityDSP-L138/MityARM-1808")
+	.boot_params	= (DA8XX_DDR_BASE + 0x100),
+	.map_io		= mityomapl138_map_io,
+	.init_irq	= cp_intc_init,
+	.timer		= &davinci_timer,
+	.init_machine	= mityomapl138_init,
+MACHINE_END

+ 2 - 5
arch/arm/mach-davinci/board-neuros-osd2.c

@@ -39,9 +39,7 @@
 #include <mach/mmc.h>
 #include <mach/mmc.h>
 #include <mach/usb.h>
 #include <mach/usb.h>
 
 
-#define NEUROS_OSD2_PHY_MASK		0x2
-#define NEUROS_OSD2_MDIO_FREQUENCY	2200000 /* PHY bus frequency */
-
+#define NEUROS_OSD2_PHY_ID		"0:01"
 #define LXT971_PHY_ID			0x001378e2
 #define LXT971_PHY_ID			0x001378e2
 #define LXT971_PHY_MASK			0xfffffff0
 #define LXT971_PHY_MASK			0xfffffff0
 
 
@@ -252,8 +250,7 @@ static __init void davinci_ntosd2_init(void)
 	davinci_serial_init(&uart_config);
 	davinci_serial_init(&uart_config);
 	dm644x_init_asp(&dm644x_ntosd2_snd_data);
 	dm644x_init_asp(&dm644x_ntosd2_snd_data);
 
 
-	soc_info->emac_pdata->phy_mask = NEUROS_OSD2_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = NEUROS_OSD2_MDIO_FREQUENCY;
+	soc_info->emac_pdata->phy_id = NEUROS_OSD2_PHY_ID;
 
 
 	davinci_setup_usb(1000, 8);
 	davinci_setup_usb(1000, 8);
 	/*
 	/*

+ 62 - 0
arch/arm/mach-davinci/board-omapl138-hawk.c

@@ -0,0 +1,62 @@
+/*
+ * Hawkboard.org based on TI's OMAP-L138 Platform
+ *
+ * Initial code: Syed Mohammed Khasim
+ *
+ * Copyright (C) 2009 Texas Instruments Incorporated - http://www.ti.com
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of
+ * any kind, whether express or implied.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/console.h>
+#include <linux/gpio.h>
+
+#include <asm/mach-types.h>
+#include <asm/mach/arch.h>
+
+#include <mach/cp_intc.h>
+#include <mach/da8xx.h>
+
+static struct davinci_uart_config omapl138_hawk_uart_config __initdata = {
+	.enabled_uarts = 0x7,
+};
+
+static __init void omapl138_hawk_init(void)
+{
+	int ret;
+
+	davinci_serial_init(&omapl138_hawk_uart_config);
+
+	ret = da8xx_register_watchdog();
+	if (ret)
+		pr_warning("omapl138_hawk_init: "
+			"watchdog registration failed: %d\n",
+			ret);
+}
+
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+static int __init omapl138_hawk_console_init(void)
+{
+	if (!machine_is_omapl138_hawkboard())
+		return 0;
+
+	return add_preferred_console("ttyS", 2, "115200");
+}
+console_initcall(omapl138_hawk_console_init);
+#endif
+
+static void __init omapl138_hawk_map_io(void)
+{
+	da850_init();
+}
+
+MACHINE_START(OMAPL138_HAWKBOARD, "AM18x/OMAP-L138 Hawkboard")
+	.boot_params	= (DA8XX_DDR_BASE + 0x100),
+	.map_io		= omapl138_hawk_map_io,
+	.init_irq	= cp_intc_init,
+	.timer		= &davinci_timer,
+	.init_machine	= omapl138_hawk_init,
+MACHINE_END

+ 2 - 5
arch/arm/mach-davinci/board-sffsdr.c

@@ -42,9 +42,7 @@
 #include <mach/mux.h>
 #include <mach/mux.h>
 #include <mach/usb.h>
 #include <mach/usb.h>
 
 
-#define SFFSDR_PHY_MASK		(0x2)
-#define SFFSDR_MDIO_FREQUENCY	(2200000) /* PHY bus frequency */
-
+#define SFFSDR_PHY_ID		"0:01"
 static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
 static struct mtd_partition davinci_sffsdr_nandflash_partition[] = {
 	/* U-Boot Environment: Block 0
 	/* U-Boot Environment: Block 0
 	 * UBL:                Block 1
 	 * UBL:                Block 1
@@ -143,8 +141,7 @@ static __init void davinci_sffsdr_init(void)
 			     ARRAY_SIZE(davinci_sffsdr_devices));
 			     ARRAY_SIZE(davinci_sffsdr_devices));
 	sffsdr_init_i2c();
 	sffsdr_init_i2c();
 	davinci_serial_init(&uart_config);
 	davinci_serial_init(&uart_config);
-	soc_info->emac_pdata->phy_mask = SFFSDR_PHY_MASK;
-	soc_info->emac_pdata->mdio_max_freq = SFFSDR_MDIO_FREQUENCY;
+	soc_info->emac_pdata->phy_id = SFFSDR_PHY_ID;
 	davinci_setup_usb(0, 0); /* We support only peripheral mode. */
 	davinci_setup_usb(0, 0); /* We support only peripheral mode. */
 
 
 	/* mux VLYNQ pins */
 	/* mux VLYNQ pins */

+ 56 - 0
arch/arm/mach-davinci/board-tnetv107x-evm.c

@@ -23,6 +23,9 @@
 #include <linux/ratelimit.h>
 #include <linux/ratelimit.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/partitions.h>
 #include <linux/mtd/partitions.h>
+#include <linux/input.h>
+#include <linux/input/matrix_keypad.h>
+
 #include <asm/mach/arch.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
 
 
@@ -141,10 +144,63 @@ static struct davinci_uart_config serial_config __initconst = {
 	.enabled_uarts	= BIT(1),
 	.enabled_uarts	= BIT(1),
 };
 };
 
 
+static const uint32_t keymap[] = {
+	KEY(0, 0, KEY_NUMERIC_1),
+	KEY(0, 1, KEY_NUMERIC_2),
+	KEY(0, 2, KEY_NUMERIC_3),
+	KEY(0, 3, KEY_FN_F1),
+	KEY(0, 4, KEY_MENU),
+
+	KEY(1, 0, KEY_NUMERIC_4),
+	KEY(1, 1, KEY_NUMERIC_5),
+	KEY(1, 2, KEY_NUMERIC_6),
+	KEY(1, 3, KEY_UP),
+	KEY(1, 4, KEY_FN_F2),
+
+	KEY(2, 0, KEY_NUMERIC_7),
+	KEY(2, 1, KEY_NUMERIC_8),
+	KEY(2, 2, KEY_NUMERIC_9),
+	KEY(2, 3, KEY_LEFT),
+	KEY(2, 4, KEY_ENTER),
+
+	KEY(3, 0, KEY_NUMERIC_STAR),
+	KEY(3, 1, KEY_NUMERIC_0),
+	KEY(3, 2, KEY_NUMERIC_POUND),
+	KEY(3, 3, KEY_DOWN),
+	KEY(3, 4, KEY_RIGHT),
+
+	KEY(4, 0, KEY_FN_F3),
+	KEY(4, 1, KEY_FN_F4),
+	KEY(4, 2, KEY_MUTE),
+	KEY(4, 3, KEY_HOME),
+	KEY(4, 4, KEY_BACK),
+
+	KEY(5, 0, KEY_VOLUMEDOWN),
+	KEY(5, 1, KEY_VOLUMEUP),
+	KEY(5, 2, KEY_F1),
+	KEY(5, 3, KEY_F2),
+	KEY(5, 4, KEY_F3),
+};
+
+static const struct matrix_keymap_data keymap_data = {
+	.keymap		= keymap,
+	.keymap_size	= ARRAY_SIZE(keymap),
+};
+
+static struct matrix_keypad_platform_data keypad_config = {
+	.keymap_data	= &keymap_data,
+	.num_row_gpios	= 6,
+	.num_col_gpios	= 5,
+	.debounce_ms	= 0, /* minimum */
+	.active_low	= 0, /* pull up realization */
+	.no_autorepeat	= 0,
+};
+
 static struct tnetv107x_device_info evm_device_info __initconst = {
 static struct tnetv107x_device_info evm_device_info __initconst = {
 	.serial_config		= &serial_config,
 	.serial_config		= &serial_config,
 	.mmc_config[1]		= &mmc_config,	/* controller 1 */
 	.mmc_config[1]		= &mmc_config,	/* controller 1 */
 	.nand_config[0]		= &nand_config,	/* chip select 0 */
 	.nand_config[0]		= &nand_config,	/* chip select 0 */
+	.keypad_config		= &keypad_config,
 };
 };
 
 
 static __init void tnetv107x_evm_board_init(void)
 static __init void tnetv107x_evm_board_init(void)

+ 74 - 1
arch/arm/mach-davinci/clock.c

@@ -236,7 +236,7 @@ static int __init clk_disable_unused(void)
 		if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc))
 		if (!davinci_psc_is_clk_active(ck->gpsc, ck->lpsc))
 			continue;
 			continue;
 
 
-		pr_info("Clocks: disable unused %s\n", ck->name);
+		pr_debug("Clocks: disable unused %s\n", ck->name);
 
 
 		davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc,
 		davinci_psc_config(psc_domain(ck), ck->gpsc, ck->lpsc,
 				(ck->flags & PSC_SWRSTDISABLE) ?
 				(ck->flags & PSC_SWRSTDISABLE) ?
@@ -287,6 +287,79 @@ static unsigned long clk_sysclk_recalc(struct clk *clk)
 	return rate;
 	return rate;
 }
 }
 
 
+int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate)
+{
+	unsigned v;
+	struct pll_data *pll;
+	unsigned long input;
+	unsigned ratio = 0;
+
+	/* If this is the PLL base clock, wrong function to call */
+	if (clk->pll_data)
+		return -EINVAL;
+
+	/* There must be a parent... */
+	if (WARN_ON(!clk->parent))
+		return -EINVAL;
+
+	/* ... the parent must be a PLL... */
+	if (WARN_ON(!clk->parent->pll_data))
+		return -EINVAL;
+
+	/* ... and this clock must have a divider. */
+	if (WARN_ON(!clk->div_reg))
+		return -EINVAL;
+
+	pll = clk->parent->pll_data;
+
+	input = clk->parent->rate;
+
+	/* If pre-PLL, source clock is before the multiplier and divider(s) */
+	if (clk->flags & PRE_PLL)
+		input = pll->input_rate;
+
+	if (input > rate) {
+		/*
+		 * Can afford to provide an output little higher than requested
+		 * only if maximum rate supported by hardware on this sysclk
+		 * is known.
+		 */
+		if (clk->maxrate) {
+			ratio = DIV_ROUND_CLOSEST(input, rate);
+			if (input / ratio > clk->maxrate)
+				ratio = 0;
+		}
+
+		if (ratio == 0)
+			ratio = DIV_ROUND_UP(input, rate);
+
+		ratio--;
+	}
+
+	if (ratio > PLLDIV_RATIO_MASK)
+		return -EINVAL;
+
+	do {
+		v = __raw_readl(pll->base + PLLSTAT);
+	} while (v & PLLSTAT_GOSTAT);
+
+	v = __raw_readl(pll->base + clk->div_reg);
+	v &= ~PLLDIV_RATIO_MASK;
+	v |= ratio | PLLDIV_EN;
+	__raw_writel(v, pll->base + clk->div_reg);
+
+	v = __raw_readl(pll->base + PLLCMD);
+	v |= PLLCMD_GOSET;
+	__raw_writel(v, pll->base + PLLCMD);
+
+	do {
+		v = __raw_readl(pll->base + PLLSTAT);
+	} while (v & PLLSTAT_GOSTAT);
+
+	return 0;
+}
+EXPORT_SYMBOL(davinci_set_sysclk_rate);
+
 static unsigned long clk_leafclk_recalc(struct clk *clk)
 static unsigned long clk_leafclk_recalc(struct clk *clk)
 {
 {
 	if (WARN_ON(!clk->parent))
 	if (WARN_ON(!clk->parent))

+ 5 - 0
arch/arm/mach-davinci/clock.h

@@ -70,6 +70,9 @@
 #include <linux/list.h>
 #include <linux/list.h>
 #include <asm/clkdev.h>
 #include <asm/clkdev.h>
 
 
+#define PLLSTAT_GOSTAT	BIT(0)
+#define PLLCMD_GOSET	BIT(0)
+
 struct pll_data {
 struct pll_data {
 	u32 phys_base;
 	u32 phys_base;
 	void __iomem *base;
 	void __iomem *base;
@@ -86,6 +89,7 @@ struct clk {
 	struct module		*owner;
 	struct module		*owner;
 	const char		*name;
 	const char		*name;
 	unsigned long		rate;
 	unsigned long		rate;
+	unsigned long		maxrate;	/* H/W supported max rate */
 	u8			usecount;
 	u8			usecount;
 	u8			lpsc;
 	u8			lpsc;
 	u8			gpsc;
 	u8			gpsc;
@@ -118,6 +122,7 @@ struct clk {
 int davinci_clk_init(struct clk_lookup *clocks);
 int davinci_clk_init(struct clk_lookup *clocks);
 int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
 int davinci_set_pllrate(struct pll_data *pll, unsigned int prediv,
 				unsigned int mult, unsigned int postdiv);
 				unsigned int mult, unsigned int postdiv);
+int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate);
 
 
 extern struct platform_device davinci_wdt_device;
 extern struct platform_device davinci_wdt_device;
 extern void davinci_watchdog_reset(struct platform_device *);
 extern void davinci_watchdog_reset(struct platform_device *);

+ 26 - 2
arch/arm/mach-davinci/cpufreq.c

@@ -34,6 +34,8 @@
 struct davinci_cpufreq {
 struct davinci_cpufreq {
 	struct device *dev;
 	struct device *dev;
 	struct clk *armclk;
 	struct clk *armclk;
+	struct clk *asyncclk;
+	unsigned long asyncrate;
 };
 };
 static struct davinci_cpufreq cpufreq;
 static struct davinci_cpufreq cpufreq;
 
 
@@ -104,15 +106,27 @@ static int davinci_target(struct cpufreq_policy *policy,
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 	cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
 
 
 	/* if moving to higher frequency, up the voltage beforehand */
 	/* if moving to higher frequency, up the voltage beforehand */
-	if (pdata->set_voltage && freqs.new > freqs.old)
-		pdata->set_voltage(idx);
+	if (pdata->set_voltage && freqs.new > freqs.old) {
+		ret = pdata->set_voltage(idx);
+		if (ret)
+			goto out;
+	}
 
 
 	ret = clk_set_rate(armclk, idx);
 	ret = clk_set_rate(armclk, idx);
+	if (ret)
+		goto out;
+
+	if (cpufreq.asyncclk) {
+		ret = clk_set_rate(cpufreq.asyncclk, cpufreq.asyncrate);
+		if (ret)
+			goto out;
+	}
 
 
 	/* if moving to lower freq, lower the voltage after lowering freq */
 	/* if moving to lower freq, lower the voltage after lowering freq */
 	if (pdata->set_voltage && freqs.new < freqs.old)
 	if (pdata->set_voltage && freqs.new < freqs.old)
 		pdata->set_voltage(idx);
 		pdata->set_voltage(idx);
 
 
+out:
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 	cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
 
 
 	return ret;
 	return ret;
@@ -185,6 +199,7 @@ static struct cpufreq_driver davinci_driver = {
 static int __init davinci_cpufreq_probe(struct platform_device *pdev)
 static int __init davinci_cpufreq_probe(struct platform_device *pdev)
 {
 {
 	struct davinci_cpufreq_config *pdata = pdev->dev.platform_data;
 	struct davinci_cpufreq_config *pdata = pdev->dev.platform_data;
+	struct clk *asyncclk;
 
 
 	if (!pdata)
 	if (!pdata)
 		return -EINVAL;
 		return -EINVAL;
@@ -199,6 +214,12 @@ static int __init davinci_cpufreq_probe(struct platform_device *pdev)
 		return PTR_ERR(cpufreq.armclk);
 		return PTR_ERR(cpufreq.armclk);
 	}
 	}
 
 
+	asyncclk = clk_get(cpufreq.dev, "async");
+	if (!IS_ERR(asyncclk)) {
+		cpufreq.asyncclk = asyncclk;
+		cpufreq.asyncrate = clk_get_rate(asyncclk);
+	}
+
 	return cpufreq_register_driver(&davinci_driver);
 	return cpufreq_register_driver(&davinci_driver);
 }
 }
 
 
@@ -206,6 +227,9 @@ static int __exit davinci_cpufreq_remove(struct platform_device *pdev)
 {
 {
 	clk_put(cpufreq.armclk);
 	clk_put(cpufreq.armclk);
 
 
+	if (cpufreq.asyncclk)
+		clk_put(cpufreq.asyncclk);
+
 	return cpufreq_unregister_driver(&davinci_driver);
 	return cpufreq_unregister_driver(&davinci_driver);
 }
 }
 
 

+ 39 - 37
arch/arm/mach-davinci/da850.c

@@ -86,6 +86,8 @@ static struct clk pll0_sysclk3 = {
 	.parent		= &pll0_clk,
 	.parent		= &pll0_clk,
 	.flags		= CLK_PLL,
 	.flags		= CLK_PLL,
 	.div_reg	= PLLDIV3,
 	.div_reg	= PLLDIV3,
+	.set_rate	= davinci_set_sysclk_rate,
+	.maxrate	= 100000000,
 };
 };
 
 
 static struct clk pll0_sysclk4 = {
 static struct clk pll0_sysclk4 = {
@@ -323,12 +325,19 @@ static struct clk lcdc_clk = {
 	.gpsc		= 1,
 	.gpsc		= 1,
 };
 };
 
 
-static struct clk mmcsd_clk = {
-	.name		= "mmcsd",
+static struct clk mmcsd0_clk = {
+	.name		= "mmcsd0",
 	.parent		= &pll0_sysclk2,
 	.parent		= &pll0_sysclk2,
 	.lpsc		= DA8XX_LPSC0_MMC_SD,
 	.lpsc		= DA8XX_LPSC0_MMC_SD,
 };
 };
 
 
+static struct clk mmcsd1_clk = {
+	.name		= "mmcsd1",
+	.parent		= &pll0_sysclk2,
+	.lpsc		= DA850_LPSC1_MMC_SD1,
+	.gpsc		= 1,
+};
+
 static struct clk aemif_clk = {
 static struct clk aemif_clk = {
 	.name		= "aemif",
 	.name		= "aemif",
 	.parent		= &pll0_sysclk3,
 	.parent		= &pll0_sysclk3,
@@ -375,7 +384,8 @@ static struct clk_lookup da850_clks[] = {
 	CLK("davinci_emac.1",	NULL,		&emac_clk),
 	CLK("davinci_emac.1",	NULL,		&emac_clk),
 	CLK("davinci-mcasp.0",	NULL,		&mcasp_clk),
 	CLK("davinci-mcasp.0",	NULL,		&mcasp_clk),
 	CLK("da8xx_lcdc.0",	NULL,		&lcdc_clk),
 	CLK("da8xx_lcdc.0",	NULL,		&lcdc_clk),
-	CLK("davinci_mmc.0",	NULL,		&mmcsd_clk),
+	CLK("davinci_mmc.0",	NULL,		&mmcsd0_clk),
+	CLK("davinci_mmc.1",	NULL,		&mmcsd1_clk),
 	CLK(NULL,		"aemif",	&aemif_clk),
 	CLK(NULL,		"aemif",	&aemif_clk),
 	CLK(NULL,		NULL,		NULL),
 	CLK(NULL,		NULL,		NULL),
 };
 };
@@ -572,15 +582,9 @@ const short da850_cpgmac_pins[] __initdata = {
 	DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
 	DA850_MII_TXD_2, DA850_MII_TXD_1, DA850_MII_TXD_0, DA850_MII_RXER,
 	DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
 	DA850_MII_CRS, DA850_MII_RXCLK, DA850_MII_RXDV, DA850_MII_RXD_3,
 	DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
 	DA850_MII_RXD_2, DA850_MII_RXD_1, DA850_MII_RXD_0, DA850_MDIO_CLK,
-	DA850_MDIO_D,
-	-1
-};
-
-const short da850_rmii_pins[] __initdata = {
-	DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
-	DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1,
-	DA850_RMII_RXER, DA850_RMII_MHZ_50_CLK, DA850_MDIO_CLK,
-	DA850_MDIO_D,
+	DA850_MDIO_D, DA850_RMII_TXD_0, DA850_RMII_TXD_1, DA850_RMII_TXEN,
+	DA850_RMII_CRS_DV, DA850_RMII_RXD_0, DA850_RMII_RXD_1, DA850_RMII_RXER,
+	DA850_RMII_MHZ_50_CLK,
 	-1
 	-1
 };
 };
 
 
@@ -607,27 +611,19 @@ const short da850_mmcsd0_pins[] __initdata = {
 	-1
 	-1
 };
 };
 
 
-const short da850_nand_pins[] __initdata = {
-	DA850_EMA_D_7, DA850_EMA_D_6, DA850_EMA_D_5, DA850_EMA_D_4,
-	DA850_EMA_D_3, DA850_EMA_D_2, DA850_EMA_D_1, DA850_EMA_D_0,
-	DA850_EMA_A_1, DA850_EMA_A_2, DA850_NEMA_CS_3, DA850_NEMA_CS_4,
-	DA850_NEMA_WE, DA850_NEMA_OE,
-	-1
-};
-
-const short da850_nor_pins[] __initdata = {
+const short da850_emif25_pins[] __initdata = {
 	DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2,
 	DA850_EMA_BA_1, DA850_EMA_CLK, DA850_EMA_WAIT_1, DA850_NEMA_CS_2,
-	DA850_NEMA_WE, DA850_NEMA_OE, DA850_EMA_D_0, DA850_EMA_D_1,
-	DA850_EMA_D_2, DA850_EMA_D_3, DA850_EMA_D_4, DA850_EMA_D_5,
-	DA850_EMA_D_6, DA850_EMA_D_7, DA850_EMA_D_8, DA850_EMA_D_9,
-	DA850_EMA_D_10, DA850_EMA_D_11, DA850_EMA_D_12, DA850_EMA_D_13,
-	DA850_EMA_D_14, DA850_EMA_D_15, DA850_EMA_A_0, DA850_EMA_A_1,
-	DA850_EMA_A_2, DA850_EMA_A_3, DA850_EMA_A_4, DA850_EMA_A_5,
-	DA850_EMA_A_6, DA850_EMA_A_7, DA850_EMA_A_8, DA850_EMA_A_9,
-	DA850_EMA_A_10, DA850_EMA_A_11, DA850_EMA_A_12, DA850_EMA_A_13,
-	DA850_EMA_A_14, DA850_EMA_A_15, DA850_EMA_A_16, DA850_EMA_A_17,
-	DA850_EMA_A_18, DA850_EMA_A_19, DA850_EMA_A_20, DA850_EMA_A_21,
-	DA850_EMA_A_22, DA850_EMA_A_23,
+	DA850_NEMA_CS_3, DA850_NEMA_CS_4, DA850_NEMA_WE, DA850_NEMA_OE,
+	DA850_EMA_D_0, DA850_EMA_D_1, DA850_EMA_D_2, DA850_EMA_D_3,
+	DA850_EMA_D_4, DA850_EMA_D_5, DA850_EMA_D_6, DA850_EMA_D_7,
+	DA850_EMA_D_8, DA850_EMA_D_9, DA850_EMA_D_10, DA850_EMA_D_11,
+	DA850_EMA_D_12, DA850_EMA_D_13, DA850_EMA_D_14, DA850_EMA_D_15,
+	DA850_EMA_A_0, DA850_EMA_A_1, DA850_EMA_A_2, DA850_EMA_A_3,
+	DA850_EMA_A_4, DA850_EMA_A_5, DA850_EMA_A_6, DA850_EMA_A_7,
+	DA850_EMA_A_8, DA850_EMA_A_9, DA850_EMA_A_10, DA850_EMA_A_11,
+	DA850_EMA_A_12, DA850_EMA_A_13, DA850_EMA_A_14, DA850_EMA_A_15,
+	DA850_EMA_A_16, DA850_EMA_A_17, DA850_EMA_A_18, DA850_EMA_A_19,
+	DA850_EMA_A_20, DA850_EMA_A_21, DA850_EMA_A_22, DA850_EMA_A_23,
 	-1
 	-1
 };
 };
 
 
@@ -851,7 +847,7 @@ static const struct da850_opp da850_opp_300 = {
 	.prediv		= 1,
 	.prediv		= 1,
 	.mult		= 25,
 	.mult		= 25,
 	.postdiv	= 2,
 	.postdiv	= 2,
-	.cvdd_min	= 1140000,
+	.cvdd_min	= 1200000,
 	.cvdd_max	= 1320000,
 	.cvdd_max	= 1320000,
 };
 };
 
 
@@ -860,7 +856,7 @@ static const struct da850_opp da850_opp_200 = {
 	.prediv		= 1,
 	.prediv		= 1,
 	.mult		= 25,
 	.mult		= 25,
 	.postdiv	= 3,
 	.postdiv	= 3,
-	.cvdd_min	= 1050000,
+	.cvdd_min	= 1100000,
 	.cvdd_max	= 1160000,
 	.cvdd_max	= 1160000,
 };
 };
 
 
@@ -869,7 +865,7 @@ static const struct da850_opp da850_opp_96 = {
 	.prediv		= 1,
 	.prediv		= 1,
 	.mult		= 20,
 	.mult		= 20,
 	.postdiv	= 5,
 	.postdiv	= 5,
-	.cvdd_min	= 950000,
+	.cvdd_min	= 1000000,
 	.cvdd_max	= 1050000,
 	.cvdd_max	= 1050000,
 };
 };
 
 
@@ -929,10 +925,16 @@ static struct platform_device da850_cpufreq_device = {
 	.dev = {
 	.dev = {
 		.platform_data	= &cpufreq_info,
 		.platform_data	= &cpufreq_info,
 	},
 	},
+	.id = -1,
 };
 };
 
 
-int __init da850_register_cpufreq(void)
+int __init da850_register_cpufreq(char *async_clk)
 {
 {
+	/* cpufreq driver can help keep an "async" clock constant */
+	if (async_clk)
+		clk_add_alias("async", da850_cpufreq_device.name,
+							async_clk, NULL);
+
 	return platform_device_register(&da850_cpufreq_device);
 	return platform_device_register(&da850_cpufreq_device);
 }
 }
 
 
@@ -983,7 +985,7 @@ static int da850_set_pll0rate(struct clk *clk, unsigned long index)
 	return 0;
 	return 0;
 }
 }
 #else
 #else
-int __init da850_register_cpufreq(void)
+int __init da850_register_cpufreq(char *async_clk)
 {
 {
 	return 0;
 	return 0;
 }
 }

+ 66 - 4
arch/arm/mach-davinci/devices-da8xx.c

@@ -24,6 +24,7 @@
 #include "clock.h"
 #include "clock.h"
 
 
 #define DA8XX_TPCC_BASE			0x01c00000
 #define DA8XX_TPCC_BASE			0x01c00000
+#define DA850_MMCSD1_BASE		0x01e1b000
 #define DA850_TPCC1_BASE		0x01e30000
 #define DA850_TPCC1_BASE		0x01e30000
 #define DA8XX_TPTC0_BASE		0x01c08000
 #define DA8XX_TPTC0_BASE		0x01c08000
 #define DA8XX_TPTC1_BASE		0x01c08400
 #define DA8XX_TPTC1_BASE		0x01c08400
@@ -41,7 +42,6 @@
 #define DA8XX_EMAC_CTRL_REG_OFFSET	0x3000
 #define DA8XX_EMAC_CTRL_REG_OFFSET	0x3000
 #define DA8XX_EMAC_MOD_REG_OFFSET	0x2000
 #define DA8XX_EMAC_MOD_REG_OFFSET	0x2000
 #define DA8XX_EMAC_RAM_OFFSET		0x0000
 #define DA8XX_EMAC_RAM_OFFSET		0x0000
-#define DA8XX_MDIO_REG_OFFSET		0x4000
 #define DA8XX_EMAC_CTRL_RAM_SIZE	SZ_8K
 #define DA8XX_EMAC_CTRL_RAM_SIZE	SZ_8K
 
 
 void __iomem *da8xx_syscfg0_base;
 void __iomem *da8xx_syscfg0_base;
@@ -351,7 +351,7 @@ int __init da8xx_register_watchdog(void)
 static struct resource da8xx_emac_resources[] = {
 static struct resource da8xx_emac_resources[] = {
 	{
 	{
 		.start	= DA8XX_EMAC_CPPI_PORT_BASE,
 		.start	= DA8XX_EMAC_CPPI_PORT_BASE,
-		.end	= DA8XX_EMAC_CPPI_PORT_BASE + 0x5000 - 1,
+		.end	= DA8XX_EMAC_CPPI_PORT_BASE + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 		.flags	= IORESOURCE_MEM,
 	},
 	},
 	{
 	{
@@ -380,7 +380,6 @@ struct emac_platform_data da8xx_emac_pdata = {
 	.ctrl_reg_offset	= DA8XX_EMAC_CTRL_REG_OFFSET,
 	.ctrl_reg_offset	= DA8XX_EMAC_CTRL_REG_OFFSET,
 	.ctrl_mod_reg_offset	= DA8XX_EMAC_MOD_REG_OFFSET,
 	.ctrl_mod_reg_offset	= DA8XX_EMAC_MOD_REG_OFFSET,
 	.ctrl_ram_offset	= DA8XX_EMAC_RAM_OFFSET,
 	.ctrl_ram_offset	= DA8XX_EMAC_RAM_OFFSET,
-	.mdio_reg_offset	= DA8XX_MDIO_REG_OFFSET,
 	.ctrl_ram_size		= DA8XX_EMAC_CTRL_RAM_SIZE,
 	.ctrl_ram_size		= DA8XX_EMAC_CTRL_RAM_SIZE,
 	.version		= EMAC_VERSION_2,
 	.version		= EMAC_VERSION_2,
 };
 };
@@ -395,9 +394,34 @@ static struct platform_device da8xx_emac_device = {
 	.resource	= da8xx_emac_resources,
 	.resource	= da8xx_emac_resources,
 };
 };
 
 
+static struct resource da8xx_mdio_resources[] = {
+	{
+		.start	= DA8XX_EMAC_MDIO_BASE,
+		.end	= DA8XX_EMAC_MDIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device da8xx_mdio_device = {
+	.name		= "davinci_mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(da8xx_mdio_resources),
+	.resource	= da8xx_mdio_resources,
+};
+
 int __init da8xx_register_emac(void)
 int __init da8xx_register_emac(void)
 {
 {
-	return platform_device_register(&da8xx_emac_device);
+	int ret;
+
+	ret = platform_device_register(&da8xx_mdio_device);
+	if (ret < 0)
+		return ret;
+	ret = platform_device_register(&da8xx_emac_device);
+	if (ret < 0)
+		return ret;
+	ret = clk_add_alias(NULL, dev_name(&da8xx_mdio_device.dev),
+			    NULL, &da8xx_emac_device.dev);
+	return ret;
 }
 }
 
 
 static struct resource da830_mcasp1_resources[] = {
 static struct resource da830_mcasp1_resources[] = {
@@ -566,6 +590,44 @@ int __init da8xx_register_mmcsd0(struct davinci_mmc_config *config)
 	return platform_device_register(&da8xx_mmcsd0_device);
 	return platform_device_register(&da8xx_mmcsd0_device);
 }
 }
 
 
+#ifdef CONFIG_ARCH_DAVINCI_DA850
+static struct resource da850_mmcsd1_resources[] = {
+	{		/* registers */
+		.start	= DA850_MMCSD1_BASE,
+		.end	= DA850_MMCSD1_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	{		/* interrupt */
+		.start	= IRQ_DA850_MMCSDINT0_1,
+		.end	= IRQ_DA850_MMCSDINT0_1,
+		.flags	= IORESOURCE_IRQ,
+	},
+	{		/* DMA RX */
+		.start	= EDMA_CTLR_CHAN(1, 28),
+		.end	= EDMA_CTLR_CHAN(1, 28),
+		.flags	= IORESOURCE_DMA,
+	},
+	{		/* DMA TX */
+		.start	= EDMA_CTLR_CHAN(1, 29),
+		.end	= EDMA_CTLR_CHAN(1, 29),
+		.flags	= IORESOURCE_DMA,
+	},
+};
+
+static struct platform_device da850_mmcsd1_device = {
+	.name		= "davinci_mmc",
+	.id		= 1,
+	.num_resources	= ARRAY_SIZE(da850_mmcsd1_resources),
+	.resource	= da850_mmcsd1_resources,
+};
+
+int __init da850_register_mmcsd1(struct davinci_mmc_config *config)
+{
+	da850_mmcsd1_device.dev.platform_data = config;
+	return platform_device_register(&da850_mmcsd1_device);
+}
+#endif
+
 static struct resource da8xx_rtc_resources[] = {
 static struct resource da8xx_rtc_resources[] = {
 	{
 	{
 		.start		= DA8XX_RTC_BASE,
 		.start		= DA8XX_RTC_BASE,

+ 50 - 0
arch/arm/mach-davinci/devices-tnetv107x.c

@@ -31,8 +31,10 @@
 #define TNETV107X_TPTC0_BASE			0x01c10000
 #define TNETV107X_TPTC0_BASE			0x01c10000
 #define TNETV107X_TPTC1_BASE			0x01c10400
 #define TNETV107X_TPTC1_BASE			0x01c10400
 #define TNETV107X_WDOG_BASE			0x08086700
 #define TNETV107X_WDOG_BASE			0x08086700
+#define TNETV107X_TSC_BASE			0x08088500
 #define TNETV107X_SDIO0_BASE			0x08088700
 #define TNETV107X_SDIO0_BASE			0x08088700
 #define TNETV107X_SDIO1_BASE			0x08088800
 #define TNETV107X_SDIO1_BASE			0x08088800
+#define TNETV107X_KEYPAD_BASE			0x08088a00
 #define TNETV107X_ASYNC_EMIF_CNTRL_BASE		0x08200000
 #define TNETV107X_ASYNC_EMIF_CNTRL_BASE		0x08200000
 #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE	0x30000000
 #define TNETV107X_ASYNC_EMIF_DATA_CE0_BASE	0x30000000
 #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE	0x40000000
 #define TNETV107X_ASYNC_EMIF_DATA_CE1_BASE	0x40000000
@@ -298,12 +300,55 @@ static int __init nand_init(int chipsel, struct davinci_nand_pdata *data)
 	return platform_device_register(pdev);
 	return platform_device_register(pdev);
 }
 }
 
 
+static struct resource keypad_resources[] = {
+	{
+		.start	= TNETV107X_KEYPAD_BASE,
+		.end	= TNETV107X_KEYPAD_BASE + 0xff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_TNETV107X_KEYPAD,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "press",
+	},
+	{
+		.start	= IRQ_TNETV107X_KEYPAD_FREE,
+		.flags	= IORESOURCE_IRQ,
+		.name	= "release",
+	},
+};
+
+static struct platform_device keypad_device = {
+	.name		= "tnetv107x-keypad",
+	.num_resources	= ARRAY_SIZE(keypad_resources),
+	.resource	= keypad_resources,
+};
+
+static struct resource tsc_resources[] = {
+	{
+		.start	= TNETV107X_TSC_BASE,
+		.end	= TNETV107X_TSC_BASE + 0xff,
+		.flags	= IORESOURCE_MEM,
+	},
+	{
+		.start	= IRQ_TNETV107X_TSC,
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tsc_device = {
+	.name		= "tnetv107x-ts",
+	.num_resources	= ARRAY_SIZE(tsc_resources),
+	.resource	= tsc_resources,
+};
+
 void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 {
 {
 	int i;
 	int i;
 
 
 	platform_device_register(&edma_device);
 	platform_device_register(&edma_device);
 	platform_device_register(&tnetv107x_wdt_device);
 	platform_device_register(&tnetv107x_wdt_device);
+	platform_device_register(&tsc_device);
 
 
 	if (info->serial_config)
 	if (info->serial_config)
 		davinci_serial_init(info->serial_config);
 		davinci_serial_init(info->serial_config);
@@ -317,4 +362,9 @@ void __init tnetv107x_devices_init(struct tnetv107x_device_info *info)
 	for (i = 0; i < 4; i++)
 	for (i = 0; i < 4; i++)
 		if (info->nand_config[i])
 		if (info->nand_config[i])
 			nand_init(i, info->nand_config[i]);
 			nand_init(i, info->nand_config[i]);
+
+	if (info->keypad_config) {
+		keypad_device.dev.platform_data = info->keypad_config;
+		platform_device_register(&keypad_device);
+	}
 }
 }

+ 1 - 1
arch/arm/mach-davinci/devices.c

@@ -213,7 +213,7 @@ void __init davinci_setup_mmc(int module, struct davinci_mmc_config *config)
 				IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + 0x7c);
 				IO_ADDRESS(DAVINCI_SYSTEM_MODULE_BASE + 0x7c);
 
 
 			/* Configure pull down control */
 			/* Configure pull down control */
-			__raw_writel((__raw_readl(pupdctl1) & ~0x400),
+			__raw_writel((__raw_readl(pupdctl1) & ~0xfc0),
 					pupdctl1);
 					pupdctl1);
 
 
 			mmcsd1_resources[0].start = DM365_MMCSD1_BASE;
 			mmcsd1_resources[0].start = DM365_MMCSD1_BASE;

+ 21 - 2
arch/arm/mach-davinci/dm365.c

@@ -691,7 +691,6 @@ static struct emac_platform_data dm365_emac_pdata = {
 	.ctrl_reg_offset	= DM365_EMAC_CNTRL_OFFSET,
 	.ctrl_reg_offset	= DM365_EMAC_CNTRL_OFFSET,
 	.ctrl_mod_reg_offset	= DM365_EMAC_CNTRL_MOD_OFFSET,
 	.ctrl_mod_reg_offset	= DM365_EMAC_CNTRL_MOD_OFFSET,
 	.ctrl_ram_offset	= DM365_EMAC_CNTRL_RAM_OFFSET,
 	.ctrl_ram_offset	= DM365_EMAC_CNTRL_RAM_OFFSET,
-	.mdio_reg_offset	= DM365_EMAC_MDIO_OFFSET,
 	.ctrl_ram_size		= DM365_EMAC_CNTRL_RAM_SIZE,
 	.ctrl_ram_size		= DM365_EMAC_CNTRL_RAM_SIZE,
 	.version		= EMAC_VERSION_2,
 	.version		= EMAC_VERSION_2,
 };
 };
@@ -699,7 +698,7 @@ static struct emac_platform_data dm365_emac_pdata = {
 static struct resource dm365_emac_resources[] = {
 static struct resource dm365_emac_resources[] = {
 	{
 	{
 		.start	= DM365_EMAC_BASE,
 		.start	= DM365_EMAC_BASE,
-		.end	= DM365_EMAC_BASE + 0x47ff,
+		.end	= DM365_EMAC_BASE + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 		.flags	= IORESOURCE_MEM,
 	},
 	},
 	{
 	{
@@ -734,6 +733,21 @@ static struct platform_device dm365_emac_device = {
 	.resource	= dm365_emac_resources,
 	.resource	= dm365_emac_resources,
 };
 };
 
 
+static struct resource dm365_mdio_resources[] = {
+	{
+		.start	= DM365_EMAC_MDIO_BASE,
+		.end	= DM365_EMAC_MDIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device dm365_mdio_device = {
+	.name		= "davinci_mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(dm365_mdio_resources),
+	.resource	= dm365_mdio_resources,
+};
+
 static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = {
 static u8 dm365_default_priorities[DAVINCI_N_AINTC_IRQ] = {
 	[IRQ_VDINT0]			= 2,
 	[IRQ_VDINT0]			= 2,
 	[IRQ_VDINT1]			= 6,
 	[IRQ_VDINT1]			= 6,
@@ -1219,7 +1233,12 @@ static int __init dm365_init_devices(void)
 
 
 	davinci_cfg_reg(DM365_INT_EDMA_CC);
 	davinci_cfg_reg(DM365_INT_EDMA_CC);
 	platform_device_register(&dm365_edma_device);
 	platform_device_register(&dm365_edma_device);
+
+	platform_device_register(&dm365_mdio_device);
 	platform_device_register(&dm365_emac_device);
 	platform_device_register(&dm365_emac_device);
+	clk_add_alias(NULL, dev_name(&dm365_mdio_device.dev),
+		      NULL, &dm365_emac_device.dev);
+
 	/* Add isif clock alias */
 	/* Add isif clock alias */
 	clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL);
 	clk_add_alias("master", dm365_isif_dev.name, "vpss_master", NULL);
 	platform_device_register(&dm365_vpss_device);
 	platform_device_register(&dm365_vpss_device);

+ 21 - 2
arch/arm/mach-davinci/dm644x.c

@@ -322,7 +322,6 @@ static struct emac_platform_data dm644x_emac_pdata = {
 	.ctrl_reg_offset	= DM644X_EMAC_CNTRL_OFFSET,
 	.ctrl_reg_offset	= DM644X_EMAC_CNTRL_OFFSET,
 	.ctrl_mod_reg_offset	= DM644X_EMAC_CNTRL_MOD_OFFSET,
 	.ctrl_mod_reg_offset	= DM644X_EMAC_CNTRL_MOD_OFFSET,
 	.ctrl_ram_offset	= DM644X_EMAC_CNTRL_RAM_OFFSET,
 	.ctrl_ram_offset	= DM644X_EMAC_CNTRL_RAM_OFFSET,
-	.mdio_reg_offset	= DM644X_EMAC_MDIO_OFFSET,
 	.ctrl_ram_size		= DM644X_EMAC_CNTRL_RAM_SIZE,
 	.ctrl_ram_size		= DM644X_EMAC_CNTRL_RAM_SIZE,
 	.version		= EMAC_VERSION_1,
 	.version		= EMAC_VERSION_1,
 };
 };
@@ -330,7 +329,7 @@ static struct emac_platform_data dm644x_emac_pdata = {
 static struct resource dm644x_emac_resources[] = {
 static struct resource dm644x_emac_resources[] = {
 	{
 	{
 		.start	= DM644X_EMAC_BASE,
 		.start	= DM644X_EMAC_BASE,
-		.end	= DM644X_EMAC_BASE + 0x47ff,
+		.end	= DM644X_EMAC_BASE + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 		.flags	= IORESOURCE_MEM,
 	},
 	},
 	{
 	{
@@ -350,6 +349,21 @@ static struct platform_device dm644x_emac_device = {
        .resource	= dm644x_emac_resources,
        .resource	= dm644x_emac_resources,
 };
 };
 
 
+static struct resource dm644x_mdio_resources[] = {
+	{
+		.start	= DM644X_EMAC_MDIO_BASE,
+		.end	= DM644X_EMAC_MDIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device dm644x_mdio_device = {
+	.name		= "davinci_mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(dm644x_mdio_resources),
+	.resource	= dm644x_mdio_resources,
+};
+
 /*
 /*
  * Device specific mux setup
  * Device specific mux setup
  *
  *
@@ -776,7 +790,12 @@ static int __init dm644x_init_devices(void)
 	clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL);
 	clk_add_alias("master", dm644x_ccdc_dev.name, "vpss_master", NULL);
 	clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL);
 	clk_add_alias("slave", dm644x_ccdc_dev.name, "vpss_slave", NULL);
 	platform_device_register(&dm644x_edma_device);
 	platform_device_register(&dm644x_edma_device);
+
+	platform_device_register(&dm644x_mdio_device);
 	platform_device_register(&dm644x_emac_device);
 	platform_device_register(&dm644x_emac_device);
+	clk_add_alias(NULL, dev_name(&dm644x_mdio_device.dev),
+		      NULL, &dm644x_emac_device.dev);
+
 	platform_device_register(&dm644x_vpss_device);
 	platform_device_register(&dm644x_vpss_device);
 	platform_device_register(&dm644x_ccdc_dev);
 	platform_device_register(&dm644x_ccdc_dev);
 	platform_device_register(&vpfe_capture_dev);
 	platform_device_register(&vpfe_capture_dev);

+ 20 - 2
arch/arm/mach-davinci/dm646x.c

@@ -358,7 +358,6 @@ static struct emac_platform_data dm646x_emac_pdata = {
 	.ctrl_reg_offset	= DM646X_EMAC_CNTRL_OFFSET,
 	.ctrl_reg_offset	= DM646X_EMAC_CNTRL_OFFSET,
 	.ctrl_mod_reg_offset	= DM646X_EMAC_CNTRL_MOD_OFFSET,
 	.ctrl_mod_reg_offset	= DM646X_EMAC_CNTRL_MOD_OFFSET,
 	.ctrl_ram_offset	= DM646X_EMAC_CNTRL_RAM_OFFSET,
 	.ctrl_ram_offset	= DM646X_EMAC_CNTRL_RAM_OFFSET,
-	.mdio_reg_offset	= DM646X_EMAC_MDIO_OFFSET,
 	.ctrl_ram_size		= DM646X_EMAC_CNTRL_RAM_SIZE,
 	.ctrl_ram_size		= DM646X_EMAC_CNTRL_RAM_SIZE,
 	.version		= EMAC_VERSION_2,
 	.version		= EMAC_VERSION_2,
 };
 };
@@ -366,7 +365,7 @@ static struct emac_platform_data dm646x_emac_pdata = {
 static struct resource dm646x_emac_resources[] = {
 static struct resource dm646x_emac_resources[] = {
 	{
 	{
 		.start	= DM646X_EMAC_BASE,
 		.start	= DM646X_EMAC_BASE,
-		.end	= DM646X_EMAC_BASE + 0x47ff,
+		.end	= DM646X_EMAC_BASE + SZ_16K - 1,
 		.flags	= IORESOURCE_MEM,
 		.flags	= IORESOURCE_MEM,
 	},
 	},
 	{
 	{
@@ -401,6 +400,21 @@ static struct platform_device dm646x_emac_device = {
 	.resource	= dm646x_emac_resources,
 	.resource	= dm646x_emac_resources,
 };
 };
 
 
+static struct resource dm646x_mdio_resources[] = {
+	{
+		.start	= DM646X_EMAC_MDIO_BASE,
+		.end	= DM646X_EMAC_MDIO_BASE + SZ_4K - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device dm646x_mdio_device = {
+	.name		= "davinci_mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(dm646x_mdio_resources),
+	.resource	= dm646x_mdio_resources,
+};
+
 /*
 /*
  * Device specific mux setup
  * Device specific mux setup
  *
  *
@@ -896,7 +910,11 @@ static int __init dm646x_init_devices(void)
 	if (!cpu_is_davinci_dm646x())
 	if (!cpu_is_davinci_dm646x())
 		return 0;
 		return 0;
 
 
+	platform_device_register(&dm646x_mdio_device);
 	platform_device_register(&dm646x_emac_device);
 	platform_device_register(&dm646x_emac_device);
+	clk_add_alias(NULL, dev_name(&dm646x_mdio_device.dev),
+		      NULL, &dm646x_emac_device.dev);
+
 	return 0;
 	return 0;
 }
 }
 postcore_initcall(dm646x_init_devices);
 postcore_initcall(dm646x_init_devices);

+ 6 - 2
arch/arm/mach-davinci/dma.c

@@ -354,10 +354,12 @@ static int irq2ctlr(int irq)
 static irqreturn_t dma_irq_handler(int irq, void *data)
 static irqreturn_t dma_irq_handler(int irq, void *data)
 {
 {
 	int i;
 	int i;
-	unsigned ctlr;
+	int ctlr;
 	unsigned int cnt = 0;
 	unsigned int cnt = 0;
 
 
 	ctlr = irq2ctlr(irq);
 	ctlr = irq2ctlr(irq);
+	if (ctlr < 0)
+		return IRQ_NONE;
 
 
 	dev_dbg(data, "dma_irq_handler\n");
 	dev_dbg(data, "dma_irq_handler\n");
 
 
@@ -408,10 +410,12 @@ static irqreturn_t dma_irq_handler(int irq, void *data)
 static irqreturn_t dma_ccerr_handler(int irq, void *data)
 static irqreturn_t dma_ccerr_handler(int irq, void *data)
 {
 {
 	int i;
 	int i;
-	unsigned ctlr;
+	int ctlr;
 	unsigned int cnt = 0;
 	unsigned int cnt = 0;
 
 
 	ctlr = irq2ctlr(irq);
 	ctlr = irq2ctlr(irq);
+	if (ctlr < 0)
+		return IRQ_NONE;
 
 
 	dev_dbg(data, "dma_ccerr_handler\n");
 	dev_dbg(data, "dma_ccerr_handler\n");
 
 

+ 36 - 0
arch/arm/mach-davinci/include/mach/aemif.h

@@ -0,0 +1,36 @@
+/*
+ * TI DaVinci AEMIF support
+ *
+ * Copyright 2010 (C) Texas Instruments, Inc. http://www.ti.com/
+ *
+ * This file is licensed under the terms of the GNU General Public License
+ * version 2. This program is licensed "as is" without any warranty of any
+ * kind, whether express or implied.
+ */
+#ifndef _MACH_DAVINCI_AEMIF_H
+#define _MACH_DAVINCI_AEMIF_H
+
+#define NRCSR_OFFSET		0x00
+#define AWCCR_OFFSET		0x04
+#define A1CR_OFFSET		0x10
+
+#define ACR_ASIZE_MASK		0x3
+#define ACR_EW_MASK		BIT(30)
+#define ACR_SS_MASK		BIT(31)
+
+/* All timings in nanoseconds */
+struct davinci_aemif_timing {
+	u8	wsetup;
+	u8	wstrobe;
+	u8	whold;
+
+	u8	rsetup;
+	u8	rstrobe;
+	u8	rhold;
+
+	u8	ta;
+};
+
+int davinci_aemif_setup_timing(struct davinci_aemif_timing *t,
+					void __iomem *base, unsigned cs);
+#endif

+ 3 - 4
arch/arm/mach-davinci/include/mach/da8xx.h

@@ -76,9 +76,10 @@ int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
 int da8xx_register_emac(void);
 int da8xx_register_emac(void);
 int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
 int da8xx_register_lcdc(struct da8xx_lcdc_platform_data *pdata);
 int da8xx_register_mmcsd0(struct davinci_mmc_config *config);
 int da8xx_register_mmcsd0(struct davinci_mmc_config *config);
+int da850_register_mmcsd1(struct davinci_mmc_config *config);
 void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata);
 void __init da8xx_register_mcasp(int id, struct snd_platform_data *pdata);
 int da8xx_register_rtc(void);
 int da8xx_register_rtc(void);
-int da850_register_cpufreq(void);
+int da850_register_cpufreq(char *async_clk);
 int da8xx_register_cpuidle(void);
 int da8xx_register_cpuidle(void);
 void __iomem * __init da8xx_get_mem_ctlr(void);
 void __iomem * __init da8xx_get_mem_ctlr(void);
 int da850_register_pm(struct platform_device *pdev);
 int da850_register_pm(struct platform_device *pdev);
@@ -121,11 +122,9 @@ extern const short da850_uart2_pins[];
 extern const short da850_i2c0_pins[];
 extern const short da850_i2c0_pins[];
 extern const short da850_i2c1_pins[];
 extern const short da850_i2c1_pins[];
 extern const short da850_cpgmac_pins[];
 extern const short da850_cpgmac_pins[];
-extern const short da850_rmii_pins[];
 extern const short da850_mcasp_pins[];
 extern const short da850_mcasp_pins[];
 extern const short da850_lcdcntl_pins[];
 extern const short da850_lcdcntl_pins[];
 extern const short da850_mmcsd0_pins[];
 extern const short da850_mmcsd0_pins[];
-extern const short da850_nand_pins[];
-extern const short da850_nor_pins[];
+extern const short da850_emif25_pins[];
 
 
 #endif /* __ASM_ARCH_DAVINCI_DA8XX_H */
 #endif /* __ASM_ARCH_DAVINCI_DA8XX_H */

+ 1 - 1
arch/arm/mach-davinci/include/mach/dm365.h

@@ -21,10 +21,10 @@
 #include <media/davinci/vpfe_capture.h>
 #include <media/davinci/vpfe_capture.h>
 
 
 #define DM365_EMAC_BASE			(0x01D07000)
 #define DM365_EMAC_BASE			(0x01D07000)
+#define DM365_EMAC_MDIO_BASE		(DM365_EMAC_BASE + 0x4000)
 #define DM365_EMAC_CNTRL_OFFSET		(0x0000)
 #define DM365_EMAC_CNTRL_OFFSET		(0x0000)
 #define DM365_EMAC_CNTRL_MOD_OFFSET	(0x3000)
 #define DM365_EMAC_CNTRL_MOD_OFFSET	(0x3000)
 #define DM365_EMAC_CNTRL_RAM_OFFSET	(0x1000)
 #define DM365_EMAC_CNTRL_RAM_OFFSET	(0x1000)
-#define DM365_EMAC_MDIO_OFFSET		(0x4000)
 #define DM365_EMAC_CNTRL_RAM_SIZE	(0x2000)
 #define DM365_EMAC_CNTRL_RAM_SIZE	(0x2000)
 
 
 /* Base of key scan register bank */
 /* Base of key scan register bank */

+ 1 - 1
arch/arm/mach-davinci/include/mach/dm644x.h

@@ -28,10 +28,10 @@
 #include <media/davinci/vpfe_capture.h>
 #include <media/davinci/vpfe_capture.h>
 
 
 #define DM644X_EMAC_BASE		(0x01C80000)
 #define DM644X_EMAC_BASE		(0x01C80000)
+#define DM644X_EMAC_MDIO_BASE		(DM644X_EMAC_BASE + 0x4000)
 #define DM644X_EMAC_CNTRL_OFFSET	(0x0000)
 #define DM644X_EMAC_CNTRL_OFFSET	(0x0000)
 #define DM644X_EMAC_CNTRL_MOD_OFFSET	(0x1000)
 #define DM644X_EMAC_CNTRL_MOD_OFFSET	(0x1000)
 #define DM644X_EMAC_CNTRL_RAM_OFFSET	(0x2000)
 #define DM644X_EMAC_CNTRL_RAM_OFFSET	(0x2000)
-#define DM644X_EMAC_MDIO_OFFSET		(0x4000)
 #define DM644X_EMAC_CNTRL_RAM_SIZE	(0x2000)
 #define DM644X_EMAC_CNTRL_RAM_SIZE	(0x2000)
 
 
 #define DM644X_ASYNC_EMIF_CONTROL_BASE	0x01E00000
 #define DM644X_ASYNC_EMIF_CONTROL_BASE	0x01E00000

+ 1 - 1
arch/arm/mach-davinci/include/mach/dm646x.h

@@ -19,10 +19,10 @@
 #include <linux/davinci_emac.h>
 #include <linux/davinci_emac.h>
 
 
 #define DM646X_EMAC_BASE		(0x01C80000)
 #define DM646X_EMAC_BASE		(0x01C80000)
+#define DM646X_EMAC_MDIO_BASE		(DM646X_EMAC_BASE + 0x4000)
 #define DM646X_EMAC_CNTRL_OFFSET	(0x0000)
 #define DM646X_EMAC_CNTRL_OFFSET	(0x0000)
 #define DM646X_EMAC_CNTRL_MOD_OFFSET	(0x1000)
 #define DM646X_EMAC_CNTRL_MOD_OFFSET	(0x1000)
 #define DM646X_EMAC_CNTRL_RAM_OFFSET	(0x2000)
 #define DM646X_EMAC_CNTRL_RAM_OFFSET	(0x2000)
-#define DM646X_EMAC_MDIO_OFFSET		(0x4000)
 #define DM646X_EMAC_CNTRL_RAM_SIZE	(0x2000)
 #define DM646X_EMAC_CNTRL_RAM_SIZE	(0x2000)
 
 
 #define DM646X_ASYNC_EMIF_CONTROL_BASE	0x20008000
 #define DM646X_ASYNC_EMIF_CONTROL_BASE	0x20008000

+ 3 - 3
arch/arm/mach-davinci/include/mach/nand.h

@@ -30,9 +30,6 @@
 
 
 #include <linux/mtd/nand.h>
 #include <linux/mtd/nand.h>
 
 
-#define NRCSR_OFFSET		0x00
-#define AWCCR_OFFSET		0x04
-#define A1CR_OFFSET		0x10
 #define NANDFCR_OFFSET		0x60
 #define NANDFCR_OFFSET		0x60
 #define NANDFSR_OFFSET		0x64
 #define NANDFSR_OFFSET		0x64
 #define NANDF1ECC_OFFSET	0x70
 #define NANDF1ECC_OFFSET	0x70
@@ -83,6 +80,9 @@ struct davinci_nand_pdata {		/* platform_data */
 	/* Main and mirror bbt descriptor overrides */
 	/* Main and mirror bbt descriptor overrides */
 	struct nand_bbt_descr	*bbt_td;
 	struct nand_bbt_descr	*bbt_td;
 	struct nand_bbt_descr	*bbt_md;
 	struct nand_bbt_descr	*bbt_md;
+
+	/* Access timings */
+	struct davinci_aemif_timing	*timing;
 };
 };
 
 
 #endif	/* __ARCH_ARM_DAVINCI_NAND_H */
 #endif	/* __ARCH_ARM_DAVINCI_NAND_H */

+ 1 - 0
arch/arm/mach-davinci/include/mach/psc.h

@@ -172,6 +172,7 @@
 #define DA8XX_LPSC1_UART2		13
 #define DA8XX_LPSC1_UART2		13
 #define DA8XX_LPSC1_LCDC		16
 #define DA8XX_LPSC1_LCDC		16
 #define DA8XX_LPSC1_PWM			17
 #define DA8XX_LPSC1_PWM			17
+#define DA850_LPSC1_MMC_SD1		18
 #define DA8XX_LPSC1_ECAP		20
 #define DA8XX_LPSC1_ECAP		20
 #define DA830_LPSC1_EQEP		21
 #define DA830_LPSC1_EQEP		21
 #define DA850_LPSC1_TPTC2		21
 #define DA850_LPSC1_TPTC2		21

+ 3 - 0
arch/arm/mach-davinci/include/mach/tnetv107x.h

@@ -33,6 +33,8 @@
 #ifndef __ASSEMBLY__
 #ifndef __ASSEMBLY__
 
 
 #include <linux/serial_8250.h>
 #include <linux/serial_8250.h>
+#include <linux/input/matrix_keypad.h>
+
 #include <mach/mmc.h>
 #include <mach/mmc.h>
 #include <mach/nand.h>
 #include <mach/nand.h>
 #include <mach/serial.h>
 #include <mach/serial.h>
@@ -41,6 +43,7 @@ struct tnetv107x_device_info {
 	struct davinci_uart_config	*serial_config;
 	struct davinci_uart_config	*serial_config;
 	struct davinci_mmc_config	*mmc_config[2];  /* 2 controllers */
 	struct davinci_mmc_config	*mmc_config[2];  /* 2 controllers */
 	struct davinci_nand_pdata	*nand_config[4]; /* 4 chipsels */
 	struct davinci_nand_pdata	*nand_config[4]; /* 4 chipsels */
+	struct matrix_keypad_platform_data *keypad_config;
 };
 };
 
 
 extern struct platform_device tnetv107x_wdt_device;
 extern struct platform_device tnetv107x_wdt_device;

+ 2 - 0
arch/arm/mach-davinci/include/mach/uncompress.h

@@ -88,6 +88,8 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
 		/* DA8xx boards */
 		/* DA8xx boards */
 		DEBUG_LL_DA8XX(davinci_da830_evm,	2);
 		DEBUG_LL_DA8XX(davinci_da830_evm,	2);
 		DEBUG_LL_DA8XX(davinci_da850_evm,	2);
 		DEBUG_LL_DA8XX(davinci_da850_evm,	2);
+		DEBUG_LL_DA8XX(mityomapl138,		1);
+		DEBUG_LL_DA8XX(omapl138_hawkboard,	2);
 
 
 		/* TNETV107x boards */
 		/* TNETV107x boards */
 		DEBUG_LL_TNETV107X(tnetv107x,		1);
 		DEBUG_LL_TNETV107X(tnetv107x,		1);

+ 9 - 2
arch/arm/mach-davinci/tnetv107x.c

@@ -104,7 +104,7 @@ static u32 pll_ext_freq[] = {
 };
 };
 
 
 /* PSC control registers */
 /* PSC control registers */
-static u32 psc_regs[] __initconst = { TNETV107X_PSC_BASE };
+static u32 psc_regs[] = { TNETV107X_PSC_BASE };
 
 
 /* Host map for interrupt controller */
 /* Host map for interrupt controller */
 static u32 intc_host_map[] = { 0x01010000, 0x01010101, -1 };
 static u32 intc_host_map[] = { 0x01010000, 0x01010101, -1 };
@@ -581,7 +581,14 @@ static struct davinci_id ids[] = {
 		.part_no	= 0xb8a1,
 		.part_no	= 0xb8a1,
 		.manufacturer	= 0x017,
 		.manufacturer	= 0x017,
 		.cpu_id		= DAVINCI_CPU_ID_TNETV107X,
 		.cpu_id		= DAVINCI_CPU_ID_TNETV107X,
-		.name		= "tnetv107x rev1.0",
+		.name		= "tnetv107x rev 1.0",
+	},
+	{
+		.variant	= 0x1,
+		.part_no	= 0xb8a1,
+		.manufacturer	= 0x017,
+		.cpu_id		= DAVINCI_CPU_ID_TNETV107X,
+		.name		= "tnetv107x rev 1.1/1.2",
 	},
 	},
 };
 };
 
 

+ 26 - 5
arch/arm/mach-omap2/board-am3517evm.c

@@ -18,6 +18,7 @@
 
 
 #include <linux/kernel.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/init.h>
+#include <linux/clk.h>
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/gpio.h>
 #include <linux/gpio.h>
 #include <linux/i2c/pca953x.h>
 #include <linux/i2c/pca953x.h>
@@ -38,19 +39,37 @@
 
 
 #include "mux.h"
 #include "mux.h"
 
 
-#define AM35XX_EVM_PHY_MASK		(0xF)
 #define AM35XX_EVM_MDIO_FREQUENCY	(1000000)
 #define AM35XX_EVM_MDIO_FREQUENCY	(1000000)
 
 
+static struct mdio_platform_data am3517_evm_mdio_pdata = {
+	.bus_freq	= AM35XX_EVM_MDIO_FREQUENCY,
+};
+
+static struct resource am3517_mdio_resources[] = {
+	{
+		.start  = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET,
+		.end    = AM35XX_IPSS_EMAC_BASE + AM35XX_EMAC_MDIO_OFFSET +
+			  SZ_4K - 1,
+		.flags  = IORESOURCE_MEM,
+	},
+};
+
+static struct platform_device am3517_mdio_device = {
+	.name		= "davinci_mdio",
+	.id		= 0,
+	.num_resources	= ARRAY_SIZE(am3517_mdio_resources),
+	.resource	= am3517_mdio_resources,
+	.dev.platform_data = &am3517_evm_mdio_pdata,
+};
+
 static struct emac_platform_data am3517_evm_emac_pdata = {
 static struct emac_platform_data am3517_evm_emac_pdata = {
-	.phy_mask	= AM35XX_EVM_PHY_MASK,
-	.mdio_max_freq	= AM35XX_EVM_MDIO_FREQUENCY,
 	.rmii_en	= 1,
 	.rmii_en	= 1,
 };
 };
 
 
 static struct resource am3517_emac_resources[] = {
 static struct resource am3517_emac_resources[] = {
 	{
 	{
 		.start  = AM35XX_IPSS_EMAC_BASE,
 		.start  = AM35XX_IPSS_EMAC_BASE,
-		.end    = AM35XX_IPSS_EMAC_BASE + 0x3FFFF,
+		.end    = AM35XX_IPSS_EMAC_BASE + 0x2FFFF,
 		.flags  = IORESOURCE_MEM,
 		.flags  = IORESOURCE_MEM,
 	},
 	},
 	{
 	{
@@ -113,7 +132,6 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
 	pdata->ctrl_reg_offset		= AM35XX_EMAC_CNTRL_OFFSET;
 	pdata->ctrl_reg_offset		= AM35XX_EMAC_CNTRL_OFFSET;
 	pdata->ctrl_mod_reg_offset	= AM35XX_EMAC_CNTRL_MOD_OFFSET;
 	pdata->ctrl_mod_reg_offset	= AM35XX_EMAC_CNTRL_MOD_OFFSET;
 	pdata->ctrl_ram_offset		= AM35XX_EMAC_CNTRL_RAM_OFFSET;
 	pdata->ctrl_ram_offset		= AM35XX_EMAC_CNTRL_RAM_OFFSET;
-	pdata->mdio_reg_offset		= AM35XX_EMAC_MDIO_OFFSET;
 	pdata->ctrl_ram_size		= AM35XX_EMAC_CNTRL_RAM_SIZE;
 	pdata->ctrl_ram_size		= AM35XX_EMAC_CNTRL_RAM_SIZE;
 	pdata->version			= EMAC_VERSION_2;
 	pdata->version			= EMAC_VERSION_2;
 	pdata->hw_ram_addr		= AM35XX_EMAC_HW_RAM_ADDR;
 	pdata->hw_ram_addr		= AM35XX_EMAC_HW_RAM_ADDR;
@@ -121,6 +139,9 @@ void am3517_evm_ethernet_init(struct emac_platform_data *pdata)
 	pdata->interrupt_disable	= am3517_disable_ethernet_int;
 	pdata->interrupt_disable	= am3517_disable_ethernet_int;
 	am3517_emac_device.dev.platform_data	= pdata;
 	am3517_emac_device.dev.platform_data	= pdata;
 	platform_device_register(&am3517_emac_device);
 	platform_device_register(&am3517_emac_device);
+	platform_device_register(&am3517_mdio_device);
+	clk_add_alias(NULL, dev_name(&am3517_mdio_device.dev),
+		      NULL, &am3517_emac_device.dev);
 
 
 	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
 	regval = omap_ctrl_readl(AM35XX_CONTROL_IP_SW_RESET);
 	regval = regval & (~(AM35XX_CPGMACSS_SW_RST));
 	regval = regval & (~(AM35XX_CPGMACSS_SW_RST));

+ 9 - 0
drivers/input/keyboard/Kconfig

@@ -443,6 +443,15 @@ config KEYBOARD_OMAP4
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called omap4-keypad.
 	  module will be called omap4-keypad.
 
 
+config KEYBOARD_TNETV107X
+	tristate "TI TNETV107X keypad support"
+	depends on ARCH_DAVINCI_TNETV107X
+	help
+	  Say Y here if you want to use the TNETV107X keypad.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tnetv107x-keypad.
+
 config KEYBOARD_TWL4030
 config KEYBOARD_TWL4030
 	tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
 	tristate "TI TWL4030/TWL5030/TPS659x0 keypad support"
 	depends on TWL4030_CORE
 	depends on TWL4030_CORE

+ 1 - 0
drivers/input/keyboard/Makefile

@@ -40,6 +40,7 @@ obj-$(CONFIG_KEYBOARD_SH_KEYSC)		+= sh_keysc.o
 obj-$(CONFIG_KEYBOARD_STMPE)		+= stmpe-keypad.o
 obj-$(CONFIG_KEYBOARD_STMPE)		+= stmpe-keypad.o
 obj-$(CONFIG_KEYBOARD_STOWAWAY)		+= stowaway.o
 obj-$(CONFIG_KEYBOARD_STOWAWAY)		+= stowaway.o
 obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
 obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
+obj-$(CONFIG_KEYBOARD_TNETV107X)	+= tnetv107x-keypad.o
 obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_TWL4030)		+= twl4030_keypad.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_W90P910)		+= w90p910_keypad.o
 obj-$(CONFIG_KEYBOARD_W90P910)		+= w90p910_keypad.o

+ 340 - 0
drivers/input/keyboard/tnetv107x-keypad.c

@@ -0,0 +1,340 @@
+/*
+ * Texas Instruments TNETV107X Keypad Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * 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 <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/input/matrix_keypad.h>
+
+#define BITS(x)			(BIT(x) - 1)
+
+#define KEYPAD_ROWS		9
+#define KEYPAD_COLS		9
+
+#define DEBOUNCE_MIN		0x400ul
+#define DEBOUNCE_MAX		0x3ffffffful
+
+struct keypad_regs {
+	u32	rev;
+	u32	mode;
+	u32	mask;
+	u32	pol;
+	u32	dclock;
+	u32	rclock;
+	u32	stable_cnt;
+	u32	in_en;
+	u32	out;
+	u32	out_en;
+	u32	in;
+	u32	lock;
+	u32	pres[3];
+};
+
+#define keypad_read(kp, reg)		__raw_readl(&(kp)->regs->reg)
+#define keypad_write(kp, reg, val)	__raw_writel(val, &(kp)->regs->reg)
+
+struct keypad_data {
+	struct input_dev		*input_dev;
+	struct resource			*res;
+	struct keypad_regs __iomem	*regs;
+	struct clk			*clk;
+	struct device			*dev;
+	spinlock_t			lock;
+	u32				irq_press;
+	u32				irq_release;
+	int				rows, cols, row_shift;
+	int				debounce_ms, active_low;
+	u32				prev_keys[3];
+	unsigned short			keycodes[];
+};
+
+static irqreturn_t keypad_irq(int irq, void *data)
+{
+	struct keypad_data *kp = data;
+	int i, bit, val, row, col, code;
+	unsigned long flags;
+	u32 curr_keys[3];
+	u32 change;
+
+	spin_lock_irqsave(&kp->lock, flags);
+
+	memset(curr_keys, 0, sizeof(curr_keys));
+	if (irq == kp->irq_press)
+		for (i = 0; i < 3; i++)
+			curr_keys[i] = keypad_read(kp, pres[i]);
+
+	for (i = 0; i < 3; i++) {
+		change = curr_keys[i] ^ kp->prev_keys[i];
+
+		while (change) {
+			bit     = fls(change) - 1;
+			change ^= BIT(bit);
+			val     = curr_keys[i] & BIT(bit);
+			bit    += i * 32;
+			row     = bit / KEYPAD_COLS;
+			col     = bit % KEYPAD_COLS;
+
+			code = MATRIX_SCAN_CODE(row, col, kp->row_shift);
+			input_event(kp->input_dev, EV_MSC, MSC_SCAN, code);
+			input_report_key(kp->input_dev, kp->keycodes[code],
+					 val);
+		}
+	}
+	input_sync(kp->input_dev);
+	memcpy(kp->prev_keys, curr_keys, sizeof(curr_keys));
+
+	if (irq == kp->irq_press)
+		keypad_write(kp, lock, 0); /* Allow hardware updates */
+
+	spin_unlock_irqrestore(&kp->lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+static int keypad_start(struct input_dev *dev)
+{
+	struct keypad_data *kp = input_get_drvdata(dev);
+	unsigned long mask, debounce, clk_rate_khz;
+	unsigned long flags;
+
+	clk_enable(kp->clk);
+	clk_rate_khz = clk_get_rate(kp->clk) / 1000;
+
+	spin_lock_irqsave(&kp->lock, flags);
+
+	/* Initialize device registers */
+	keypad_write(kp, mode, 0);
+
+	mask  = BITS(kp->rows) << KEYPAD_COLS;
+	mask |= BITS(kp->cols);
+	keypad_write(kp, mask, ~mask);
+
+	keypad_write(kp, pol, kp->active_low ? 0 : 0x3ffff);
+	keypad_write(kp, stable_cnt, 3);
+
+	debounce = kp->debounce_ms * clk_rate_khz;
+	debounce = clamp(debounce, DEBOUNCE_MIN, DEBOUNCE_MAX);
+	keypad_write(kp, dclock, debounce);
+	keypad_write(kp, rclock, 4 * debounce);
+
+	keypad_write(kp, in_en, 1);
+
+	spin_unlock_irqrestore(&kp->lock, flags);
+
+	return 0;
+}
+
+static void keypad_stop(struct input_dev *dev)
+{
+	struct keypad_data *kp = input_get_drvdata(dev);
+
+	synchronize_irq(kp->irq_press);
+	synchronize_irq(kp->irq_release);
+	clk_disable(kp->clk);
+}
+
+static int __devinit keypad_probe(struct platform_device *pdev)
+{
+	const struct matrix_keypad_platform_data *pdata;
+	const struct matrix_keymap_data *keymap_data;
+	struct device *dev = &pdev->dev;
+	struct keypad_data *kp;
+	int error = 0, sz, row_shift;
+	u32 rev = 0;
+
+	pdata = pdev->dev.platform_data;
+	if (!pdata) {
+		dev_err(dev, "cannot find device data\n");
+		return -EINVAL;
+	}
+
+	keymap_data = pdata->keymap_data;
+	if (!keymap_data) {
+		dev_err(dev, "cannot find keymap data\n");
+		return -EINVAL;
+	}
+
+	row_shift = get_count_order(pdata->num_col_gpios);
+	sz  = offsetof(struct keypad_data, keycodes);
+	sz += (pdata->num_row_gpios << row_shift) * sizeof(kp->keycodes[0]);
+	kp = kzalloc(sz, GFP_KERNEL);
+	if (!kp) {
+		dev_err(dev, "cannot allocate device info\n");
+		return -ENOMEM;
+	}
+
+	kp->dev  = dev;
+	kp->rows = pdata->num_row_gpios;
+	kp->cols = pdata->num_col_gpios;
+	kp->row_shift = row_shift;
+	platform_set_drvdata(pdev, kp);
+	spin_lock_init(&kp->lock);
+
+	kp->irq_press   = platform_get_irq_byname(pdev, "press");
+	kp->irq_release = platform_get_irq_byname(pdev, "release");
+	if (kp->irq_press < 0 || kp->irq_release < 0) {
+		dev_err(dev, "cannot determine device interrupts\n");
+		error = -ENODEV;
+		goto error_res;
+	}
+
+	kp->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!kp->res) {
+		dev_err(dev, "cannot determine register area\n");
+		error = -ENODEV;
+		goto error_res;
+	}
+
+	if (!request_mem_region(kp->res->start, resource_size(kp->res),
+				pdev->name)) {
+		dev_err(dev, "cannot claim register memory\n");
+		kp->res = NULL;
+		error = -EINVAL;
+		goto error_res;
+	}
+
+	kp->regs = ioremap(kp->res->start, resource_size(kp->res));
+	if (!kp->regs) {
+		dev_err(dev, "cannot map register memory\n");
+		error = -ENOMEM;
+		goto error_map;
+	}
+
+	kp->clk = clk_get(dev, NULL);
+	if (!kp->clk) {
+		dev_err(dev, "cannot claim device clock\n");
+		error = -EINVAL;
+		goto error_clk;
+	}
+
+	error = request_threaded_irq(kp->irq_press, NULL, keypad_irq, 0,
+				     dev_name(dev), kp);
+	if (error < 0) {
+		dev_err(kp->dev, "Could not allocate keypad press key irq\n");
+		goto error_irq_press;
+	}
+
+	error = request_threaded_irq(kp->irq_release, NULL, keypad_irq, 0,
+				     dev_name(dev), kp);
+	if (error < 0) {
+		dev_err(kp->dev, "Could not allocate keypad release key irq\n");
+		goto error_irq_release;
+	}
+
+	kp->input_dev = input_allocate_device();
+	if (!kp->input_dev) {
+		dev_err(dev, "cannot allocate input device\n");
+		error = -ENOMEM;
+		goto error_input;
+	}
+	input_set_drvdata(kp->input_dev, kp);
+
+	kp->input_dev->name	  = pdev->name;
+	kp->input_dev->dev.parent = &pdev->dev;
+	kp->input_dev->open	  = keypad_start;
+	kp->input_dev->close	  = keypad_stop;
+	kp->input_dev->evbit[0]	  = BIT_MASK(EV_KEY);
+	if (!pdata->no_autorepeat)
+		kp->input_dev->evbit[0] |= BIT_MASK(EV_REP);
+
+	clk_enable(kp->clk);
+	rev = keypad_read(kp, rev);
+	kp->input_dev->id.bustype = BUS_HOST;
+	kp->input_dev->id.product = ((rev >>  8) & 0x07);
+	kp->input_dev->id.version = ((rev >> 16) & 0xfff);
+	clk_disable(kp->clk);
+
+	kp->input_dev->keycode     = kp->keycodes;
+	kp->input_dev->keycodesize = sizeof(kp->keycodes[0]);
+	kp->input_dev->keycodemax  = kp->rows << kp->row_shift;
+
+	matrix_keypad_build_keymap(keymap_data, kp->row_shift, kp->keycodes,
+				   kp->input_dev->keybit);
+
+	input_set_capability(kp->input_dev, EV_MSC, MSC_SCAN);
+
+	error = input_register_device(kp->input_dev);
+	if (error < 0) {
+		dev_err(dev, "Could not register input device\n");
+		goto error_reg;
+	}
+
+	return 0;
+
+
+error_reg:
+	input_free_device(kp->input_dev);
+error_input:
+	free_irq(kp->irq_release, kp);
+error_irq_release:
+	free_irq(kp->irq_press, kp);
+error_irq_press:
+	clk_put(kp->clk);
+error_clk:
+	iounmap(kp->regs);
+error_map:
+	release_mem_region(kp->res->start, resource_size(kp->res));
+error_res:
+	platform_set_drvdata(pdev, NULL);
+	kfree(kp);
+	return error;
+}
+
+static int __devexit keypad_remove(struct platform_device *pdev)
+{
+	struct keypad_data *kp = platform_get_drvdata(pdev);
+
+	free_irq(kp->irq_press, kp);
+	free_irq(kp->irq_release, kp);
+	input_unregister_device(kp->input_dev);
+	clk_put(kp->clk);
+	iounmap(kp->regs);
+	release_mem_region(kp->res->start, resource_size(kp->res));
+	platform_set_drvdata(pdev, NULL);
+	kfree(kp);
+
+	return 0;
+}
+
+static struct platform_driver keypad_driver = {
+	.probe		= keypad_probe,
+	.remove		= __devexit_p(keypad_remove),
+	.driver.name	= "tnetv107x-keypad",
+	.driver.owner	= THIS_MODULE,
+};
+
+static int __init keypad_init(void)
+{
+	return platform_driver_register(&keypad_driver);
+}
+
+static void __exit keypad_exit(void)
+{
+	platform_driver_unregister(&keypad_driver);
+}
+
+module_init(keypad_init);
+module_exit(keypad_exit);
+
+MODULE_AUTHOR("Cyril Chemparathy");
+MODULE_DESCRIPTION("TNETV107X Keypad Driver");
+MODULE_ALIAS("platform: tnetv107x-keypad");
+MODULE_LICENSE("GPL");

+ 9 - 0
drivers/input/touchscreen/Kconfig

@@ -362,6 +362,15 @@ config TOUCHSCREEN_MIGOR
 	  To compile this driver as a module, choose M here: the
 	  To compile this driver as a module, choose M here: the
 	  module will be called migor_ts.
 	  module will be called migor_ts.
 
 
+config TOUCHSCREEN_TNETV107X
+	tristate "TI TNETV107X touchscreen support"
+	depends on ARCH_DAVINCI_TNETV107X
+	help
+	  Say Y here if you want to use the TNETV107X touchscreen.
+
+	  To compile this driver as a module, choose M here: the
+	  module will be called tnetv107x-ts.
+
 config TOUCHSCREEN_TOUCHRIGHT
 config TOUCHSCREEN_TOUCHRIGHT
 	tristate "Touchright serial touchscreen"
 	tristate "Touchright serial touchscreen"
 	select SERIO
 	select SERIO

+ 1 - 0
drivers/input/touchscreen/Makefile

@@ -40,6 +40,7 @@ obj-$(CONFIG_TOUCHSCREEN_PENMOUNT)	+= penmount.o
 obj-$(CONFIG_TOUCHSCREEN_QT602240)	+= qt602240_ts.o
 obj-$(CONFIG_TOUCHSCREEN_QT602240)	+= qt602240_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_S3C2410)	+= s3c2410_ts.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)		+= stmpe-ts.o
 obj-$(CONFIG_TOUCHSCREEN_STMPE)		+= stmpe-ts.o
+obj-$(CONFIG_TOUCHSCREEN_TNETV107X)	+= tnetv107x-ts.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHIT213)	+= touchit213.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHRIGHT)	+= touchright.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o
 obj-$(CONFIG_TOUCHSCREEN_TOUCHWIN)	+= touchwin.o

+ 396 - 0
drivers/input/touchscreen/tnetv107x-ts.c

@@ -0,0 +1,396 @@
+/*
+ * Texas Instruments TNETV107X Touchscreen Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * 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 <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/ctype.h>
+#include <linux/io.h>
+#include <linux/clk.h>
+
+#include <mach/tnetv107x.h>
+
+#define TSC_PENUP_POLL		(HZ / 5)
+#define IDLE_TIMEOUT		100 /* msec */
+
+/*
+ * The first and last samples of a touch interval are usually garbage and need
+ * to be filtered out with these devices.  The following definitions control
+ * the number of samples skipped.
+ */
+#define TSC_HEAD_SKIP		1
+#define TSC_TAIL_SKIP		1
+#define TSC_SKIP		(TSC_HEAD_SKIP + TSC_TAIL_SKIP + 1)
+#define TSC_SAMPLES		(TSC_SKIP + 1)
+
+/* Register Offsets */
+struct tsc_regs {
+	u32	rev;
+	u32	tscm;
+	u32	bwcm;
+	u32	swc;
+	u32	adcchnl;
+	u32	adcdata;
+	u32	chval[4];
+};
+
+/* TSC Mode Configuration Register (tscm) bits */
+#define WMODE		BIT(0)
+#define TSKIND		BIT(1)
+#define ZMEASURE_EN	BIT(2)
+#define IDLE		BIT(3)
+#define TSC_EN		BIT(4)
+#define STOP		BIT(5)
+#define ONE_SHOT	BIT(6)
+#define SINGLE		BIT(7)
+#define AVG		BIT(8)
+#define AVGNUM(x)	(((x) & 0x03) <<  9)
+#define PVSTC(x)	(((x) & 0x07) << 11)
+#define PON		BIT(14)
+#define PONBG		BIT(15)
+#define AFERST		BIT(16)
+
+/* ADC DATA Capture Register bits */
+#define DATA_VALID	BIT(16)
+
+/* Register Access Macros */
+#define tsc_read(ts, reg)		__raw_readl(&(ts)->regs->reg)
+#define tsc_write(ts, reg, val)		__raw_writel(val, &(ts)->regs->reg);
+#define tsc_set_bits(ts, reg, val)	\
+	tsc_write(ts, reg, tsc_read(ts, reg) | (val))
+#define tsc_clr_bits(ts, reg, val)	\
+	tsc_write(ts, reg, tsc_read(ts, reg) & ~(val))
+
+struct sample {
+	int x, y, p;
+};
+
+struct tsc_data {
+	struct input_dev		*input_dev;
+	struct resource			*res;
+	struct tsc_regs __iomem		*regs;
+	struct timer_list		timer;
+	spinlock_t			lock;
+	struct clk			*clk;
+	struct device			*dev;
+	int				sample_count;
+	struct sample			samples[TSC_SAMPLES];
+	int				tsc_irq;
+};
+
+static int tsc_read_sample(struct tsc_data *ts, struct sample* sample)
+{
+	int	x, y, z1, z2, t, p = 0;
+	u32	val;
+
+	val = tsc_read(ts, chval[0]);
+	if (val & DATA_VALID)
+		x = val & 0xffff;
+	else
+		return -EINVAL;
+
+	y  = tsc_read(ts, chval[1]) & 0xffff;
+	z1 = tsc_read(ts, chval[2]) & 0xffff;
+	z2 = tsc_read(ts, chval[3]) & 0xffff;
+
+	if (z1) {
+		t = ((600 * x) * (z2 - z1));
+		p = t / (u32) (z1 << 12);
+		if (p < 0)
+			p = 0;
+	}
+
+	sample->x  = x;
+	sample->y  = y;
+	sample->p  = p;
+
+	return 0;
+}
+
+static void tsc_poll(unsigned long data)
+{
+	struct tsc_data *ts = (struct tsc_data *)data;
+	unsigned long flags;
+	int i, val, x, y, p;
+
+	spin_lock_irqsave(&ts->lock, flags);
+
+	if (ts->sample_count >= TSC_SKIP) {
+		input_report_abs(ts->input_dev, ABS_PRESSURE, 0);
+		input_report_key(ts->input_dev, BTN_TOUCH, 0);
+		input_sync(ts->input_dev);
+	} else if (ts->sample_count > 0) {
+		/*
+		 * A touch event lasted less than our skip count.  Salvage and
+		 * report anyway.
+		 */
+		for (i = 0, val = 0; i < ts->sample_count; i++)
+			val += ts->samples[i].x;
+		x = val / ts->sample_count;
+
+		for (i = 0, val = 0; i < ts->sample_count; i++)
+			val += ts->samples[i].y;
+		y = val / ts->sample_count;
+
+		for (i = 0, val = 0; i < ts->sample_count; i++)
+			val += ts->samples[i].p;
+		p = val / ts->sample_count;
+
+		input_report_abs(ts->input_dev, ABS_X, x);
+		input_report_abs(ts->input_dev, ABS_Y, y);
+		input_report_abs(ts->input_dev, ABS_PRESSURE, p);
+		input_report_key(ts->input_dev, BTN_TOUCH, 1);
+		input_sync(ts->input_dev);
+	}
+
+	ts->sample_count = 0;
+
+	spin_unlock_irqrestore(&ts->lock, flags);
+}
+
+static irqreturn_t tsc_irq(int irq, void *dev_id)
+{
+	struct tsc_data *ts = (struct tsc_data *)dev_id;
+	struct sample *sample;
+	int index;
+
+	spin_lock(&ts->lock);
+
+	index = ts->sample_count % TSC_SAMPLES;
+	sample = &ts->samples[index];
+	if (tsc_read_sample(ts, sample) < 0)
+		goto out;
+
+	if (++ts->sample_count >= TSC_SKIP) {
+		index = (ts->sample_count - TSC_TAIL_SKIP - 1) % TSC_SAMPLES;
+		sample = &ts->samples[index];
+
+		input_report_abs(ts->input_dev, ABS_X, sample->x);
+		input_report_abs(ts->input_dev, ABS_Y, sample->y);
+		input_report_abs(ts->input_dev, ABS_PRESSURE, sample->p);
+		if (ts->sample_count == TSC_SKIP)
+			input_report_key(ts->input_dev, BTN_TOUCH, 1);
+		input_sync(ts->input_dev);
+	}
+	mod_timer(&ts->timer, jiffies + TSC_PENUP_POLL);
+out:
+	spin_unlock(&ts->lock);
+	return IRQ_HANDLED;
+}
+
+static int tsc_start(struct input_dev *dev)
+{
+	struct tsc_data *ts = input_get_drvdata(dev);
+	unsigned long timeout = jiffies + msecs_to_jiffies(IDLE_TIMEOUT);
+	u32 val;
+
+	clk_enable(ts->clk);
+
+	/* Go to idle mode, before any initialization */
+	while (time_after(timeout, jiffies)) {
+		if (tsc_read(ts, tscm) & IDLE)
+			break;
+	}
+
+	if (time_before(timeout, jiffies)) {
+		dev_warn(ts->dev, "timeout waiting for idle\n");
+		clk_disable(ts->clk);
+		return -EIO;
+	}
+
+	/* Configure TSC Control register*/
+	val = (PONBG | PON | PVSTC(4) | ONE_SHOT | ZMEASURE_EN);
+	tsc_write(ts, tscm, val);
+
+	/* Bring TSC out of reset: Clear AFE reset bit */
+	val &= ~(AFERST);
+	tsc_write(ts, tscm, val);
+
+	/* Configure all pins for hardware control*/
+	tsc_write(ts, bwcm, 0);
+
+	/* Finally enable the TSC */
+	tsc_set_bits(ts, tscm, TSC_EN);
+
+	return 0;
+}
+
+static void tsc_stop(struct input_dev *dev)
+{
+	struct tsc_data *ts = input_get_drvdata(dev);
+
+	tsc_clr_bits(ts, tscm, TSC_EN);
+	synchronize_irq(ts->tsc_irq);
+	del_timer_sync(&ts->timer);
+	clk_disable(ts->clk);
+}
+
+static int __devinit tsc_probe(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct tsc_data *ts;
+	int error = 0;
+	u32 rev = 0;
+
+	ts = kzalloc(sizeof(struct tsc_data), GFP_KERNEL);
+	if (!ts) {
+		dev_err(dev, "cannot allocate device info\n");
+		return -ENOMEM;
+	}
+
+	ts->dev = dev;
+	spin_lock_init(&ts->lock);
+	setup_timer(&ts->timer, tsc_poll, (unsigned long)ts);
+	platform_set_drvdata(pdev, ts);
+
+	ts->tsc_irq = platform_get_irq(pdev, 0);
+	if (ts->tsc_irq < 0) {
+		dev_err(dev, "cannot determine device interrupt\n");
+		error = -ENODEV;
+		goto error_res;
+	}
+
+	ts->res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!ts->res) {
+		dev_err(dev, "cannot determine register area\n");
+		error = -ENODEV;
+		goto error_res;
+	}
+
+	if (!request_mem_region(ts->res->start, resource_size(ts->res),
+				pdev->name)) {
+		dev_err(dev, "cannot claim register memory\n");
+		ts->res = NULL;
+		error = -EINVAL;
+		goto error_res;
+	}
+
+	ts->regs = ioremap(ts->res->start, resource_size(ts->res));
+	if (!ts->regs) {
+		dev_err(dev, "cannot map register memory\n");
+		error = -ENOMEM;
+		goto error_map;
+	}
+
+	ts->clk = clk_get(dev, NULL);
+	if (!ts->clk) {
+		dev_err(dev, "cannot claim device clock\n");
+		error = -EINVAL;
+		goto error_clk;
+	}
+
+	error = request_threaded_irq(ts->tsc_irq, NULL, tsc_irq, 0,
+				     dev_name(dev), ts);
+	if (error < 0) {
+		dev_err(ts->dev, "Could not allocate ts irq\n");
+		goto error_irq;
+	}
+
+	ts->input_dev = input_allocate_device();
+	if (!ts->input_dev) {
+		dev_err(dev, "cannot allocate input device\n");
+		error = -ENOMEM;
+		goto error_input;
+	}
+	input_set_drvdata(ts->input_dev, ts);
+
+	ts->input_dev->name       = pdev->name;
+	ts->input_dev->id.bustype = BUS_HOST;
+	ts->input_dev->dev.parent = &pdev->dev;
+	ts->input_dev->open	  = tsc_start;
+	ts->input_dev->close	  = tsc_stop;
+
+	clk_enable(ts->clk);
+	rev = tsc_read(ts, rev);
+	ts->input_dev->id.product = ((rev >>  8) & 0x07);
+	ts->input_dev->id.version = ((rev >> 16) & 0xfff);
+	clk_disable(ts->clk);
+
+	__set_bit(EV_KEY,    ts->input_dev->evbit);
+	__set_bit(EV_ABS,    ts->input_dev->evbit);
+	__set_bit(BTN_TOUCH, ts->input_dev->keybit);
+
+	input_set_abs_params(ts->input_dev, ABS_X, 0, 0xffff, 5, 0);
+	input_set_abs_params(ts->input_dev, ABS_Y, 0, 0xffff, 5, 0);
+	input_set_abs_params(ts->input_dev, ABS_PRESSURE, 0, 4095, 128, 0);
+
+	error = input_register_device(ts->input_dev);
+	if (error < 0) {
+		dev_err(dev, "failed input device registration\n");
+		goto error_reg;
+	}
+
+	return 0;
+
+error_reg:
+	input_free_device(ts->input_dev);
+error_input:
+	free_irq(ts->tsc_irq, ts);
+error_irq:
+	clk_put(ts->clk);
+error_clk:
+	iounmap(ts->regs);
+error_map:
+	release_mem_region(ts->res->start, resource_size(ts->res));
+error_res:
+	platform_set_drvdata(pdev, NULL);
+	kfree(ts);
+
+	return error;
+}
+
+static int __devexit tsc_remove(struct platform_device *pdev)
+{
+	struct tsc_data *ts = platform_get_drvdata(pdev);
+
+	input_unregister_device(ts->input_dev);
+	free_irq(ts->tsc_irq, ts);
+	clk_put(ts->clk);
+	iounmap(ts->regs);
+	release_mem_region(ts->res->start, resource_size(ts->res));
+	platform_set_drvdata(pdev, NULL);
+	kfree(ts);
+
+	return 0;
+}
+
+static struct platform_driver tsc_driver = {
+	.probe		= tsc_probe,
+	.remove		= __devexit_p(tsc_remove),
+	.driver.name	= "tnetv107x-ts",
+	.driver.owner	= THIS_MODULE,
+};
+
+static int __init tsc_init(void)
+{
+	return platform_driver_register(&tsc_driver);
+}
+
+static void __exit tsc_exit(void)
+{
+	platform_driver_unregister(&tsc_driver);
+}
+
+module_init(tsc_init);
+module_exit(tsc_exit);
+
+MODULE_AUTHOR("Cyril Chemparathy");
+MODULE_DESCRIPTION("TNETV107X Touchscreen Driver");
+MODULE_ALIAS("platform: tnetv107x-ts");
+MODULE_LICENSE("GPL");

+ 23 - 38
drivers/mtd/nand/davinci_nand.c

@@ -35,6 +35,7 @@
 #include <linux/slab.h>
 #include <linux/slab.h>
 
 
 #include <mach/nand.h>
 #include <mach/nand.h>
+#include <mach/aemif.h>
 
 
 #include <asm/mach-types.h>
 #include <asm/mach-types.h>
 
 
@@ -74,6 +75,8 @@ struct davinci_nand_info {
 	uint32_t		mask_cle;
 	uint32_t		mask_cle;
 
 
 	uint32_t		core_chipsel;
 	uint32_t		core_chipsel;
+
+	struct davinci_aemif_timing	*timing;
 };
 };
 
 
 static DEFINE_SPINLOCK(davinci_nand_lock);
 static DEFINE_SPINLOCK(davinci_nand_lock);
@@ -478,36 +481,6 @@ static int nand_davinci_dev_ready(struct mtd_info *mtd)
 	return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
 	return davinci_nand_readl(info, NANDFSR_OFFSET) & BIT(0);
 }
 }
 
 
-static void __init nand_dm6446evm_flash_init(struct davinci_nand_info *info)
-{
-	uint32_t regval, a1cr;
-
-	/*
-	 * NAND FLASH timings @ PLL1 == 459 MHz
-	 *  - AEMIF.CLK freq   = PLL1/6 = 459/6 = 76.5 MHz
-	 *  - AEMIF.CLK period = 1/76.5 MHz = 13.1 ns
-	 */
-	regval = 0
-		| (0 << 31)           /* selectStrobe */
-		| (0 << 30)           /* extWait (never with NAND) */
-		| (1 << 26)           /* writeSetup      10 ns */
-		| (3 << 20)           /* writeStrobe     40 ns */
-		| (1 << 17)           /* writeHold       10 ns */
-		| (0 << 13)           /* readSetup       10 ns */
-		| (3 << 7)            /* readStrobe      60 ns */
-		| (0 << 4)            /* readHold        10 ns */
-		| (3 << 2)            /* turnAround      ?? ns */
-		| (0 << 0)            /* asyncSize       8-bit bus */
-		;
-	a1cr = davinci_nand_readl(info, A1CR_OFFSET);
-	if (a1cr != regval) {
-		dev_dbg(info->dev, "Warning: NAND config: Set A1CR " \
-		       "reg to 0x%08x, was 0x%08x, should be done by " \
-		       "bootloader.\n", regval, a1cr);
-		davinci_nand_writel(info, A1CR_OFFSET, regval);
-	}
-}
-
 /*----------------------------------------------------------------------*/
 /*----------------------------------------------------------------------*/
 
 
 /* An ECC layout for using 4-bit ECC with small-page flash, storing
 /* An ECC layout for using 4-bit ECC with small-page flash, storing
@@ -611,6 +584,7 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
 	info->chip.options	= pdata->options;
 	info->chip.options	= pdata->options;
 	info->chip.bbt_td	= pdata->bbt_td;
 	info->chip.bbt_td	= pdata->bbt_td;
 	info->chip.bbt_md	= pdata->bbt_md;
 	info->chip.bbt_md	= pdata->bbt_md;
+	info->timing		= pdata->timing;
 
 
 	info->ioaddr		= (uint32_t __force) vaddr;
 	info->ioaddr		= (uint32_t __force) vaddr;
 
 
@@ -688,15 +662,25 @@ static int __init nand_davinci_probe(struct platform_device *pdev)
 		goto err_clk_enable;
 		goto err_clk_enable;
 	}
 	}
 
 
-	/* EMIF timings should normally be set by the boot loader,
-	 * especially after boot-from-NAND.  The *only* reason to
-	 * have this special casing for the DM6446 EVM is to work
-	 * with boot-from-NOR ... with CS0 manually re-jumpered
-	 * (after startup) so it addresses the NAND flash, not NOR.
-	 * Even for dev boards, that's unusually rude...
+	/*
+	 * Setup Async configuration register in case we did not boot from
+	 * NAND and so bootloader did not bother to set it up.
 	 */
 	 */
-	if (machine_is_davinci_evm())
-		nand_dm6446evm_flash_init(info);
+	val = davinci_nand_readl(info, A1CR_OFFSET + info->core_chipsel * 4);
+
+	/* Extended Wait is not valid and Select Strobe mode is not used */
+	val &= ~(ACR_ASIZE_MASK | ACR_EW_MASK | ACR_SS_MASK);
+	if (info->chip.options & NAND_BUSWIDTH_16)
+		val |= 0x1;
+
+	davinci_nand_writel(info, A1CR_OFFSET + info->core_chipsel * 4, val);
+
+	ret = davinci_aemif_setup_timing(info->timing, info->base,
+							info->core_chipsel);
+	if (ret < 0) {
+		dev_dbg(&pdev->dev, "NAND timing values setup fail\n");
+		goto err_timing;
+	}
 
 
 	spin_lock_irq(&davinci_nand_lock);
 	spin_lock_irq(&davinci_nand_lock);
 
 
@@ -809,6 +793,7 @@ syndrome_done:
 	return 0;
 	return 0;
 
 
 err_scan:
 err_scan:
+err_timing:
 	clk_disable(info->clk);
 	clk_disable(info->clk);
 
 
 err_clk_enable:
 err_clk_enable:

+ 21 - 0
drivers/net/Kconfig

@@ -954,6 +954,8 @@ config NET_NETX
 config TI_DAVINCI_EMAC
 config TI_DAVINCI_EMAC
 	tristate "TI DaVinci EMAC Support"
 	tristate "TI DaVinci EMAC Support"
 	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
 	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+	select TI_DAVINCI_MDIO
+	select TI_DAVINCI_CPDMA
 	select PHYLIB
 	select PHYLIB
 	help
 	help
 	  This driver supports TI's DaVinci Ethernet .
 	  This driver supports TI's DaVinci Ethernet .
@@ -961,6 +963,25 @@ config TI_DAVINCI_EMAC
 	  To compile this driver as a module, choose M here: the module
 	  To compile this driver as a module, choose M here: the module
 	  will be called davinci_emac_driver.  This is recommended.
 	  will be called davinci_emac_driver.  This is recommended.
 
 
+config TI_DAVINCI_MDIO
+	tristate "TI DaVinci MDIO Support"
+	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+	select PHYLIB
+	help
+	  This driver supports TI's DaVinci MDIO module.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called davinci_mdio.  This is recommended.
+
+config TI_DAVINCI_CPDMA
+	tristate "TI DaVinci CPDMA Support"
+	depends on ARM && ( ARCH_DAVINCI || ARCH_OMAP3 )
+	help
+	  This driver supports TI's DaVinci CPDMA dma engine.
+
+	  To compile this driver as a module, choose M here: the module
+	  will be called davinci_cpdma.  This is recommended.
+
 config DM9000
 config DM9000
 	tristate "DM9000 support"
 	tristate "DM9000 support"
 	depends on ARM || BLACKFIN || MIPS
 	depends on ARM || BLACKFIN || MIPS

+ 2 - 0
drivers/net/Makefile

@@ -7,6 +7,8 @@ obj-$(CONFIG_MDIO) += mdio.o
 obj-$(CONFIG_PHYLIB) += phy/
 obj-$(CONFIG_PHYLIB) += phy/
 
 
 obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
 obj-$(CONFIG_TI_DAVINCI_EMAC) += davinci_emac.o
+obj-$(CONFIG_TI_DAVINCI_MDIO) += davinci_mdio.o
+obj-$(CONFIG_TI_DAVINCI_CPDMA) += davinci_cpdma.o
 
 
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_E1000) += e1000/
 obj-$(CONFIG_E1000E) += e1000e/
 obj-$(CONFIG_E1000E) += e1000e/

+ 965 - 0
drivers/net/davinci_cpdma.c

@@ -0,0 +1,965 @@
+/*
+ * Texas Instruments CPDMA Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * 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 <linux/kernel.h>
+#include <linux/spinlock.h>
+#include <linux/device.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+#include <linux/dma-mapping.h>
+#include <linux/io.h>
+
+#include "davinci_cpdma.h"
+
+/* DMA Registers */
+#define CPDMA_TXIDVER		0x00
+#define CPDMA_TXCONTROL		0x04
+#define CPDMA_TXTEARDOWN	0x08
+#define CPDMA_RXIDVER		0x10
+#define CPDMA_RXCONTROL		0x14
+#define CPDMA_SOFTRESET		0x1c
+#define CPDMA_RXTEARDOWN	0x18
+#define CPDMA_TXINTSTATRAW	0x80
+#define CPDMA_TXINTSTATMASKED	0x84
+#define CPDMA_TXINTMASKSET	0x88
+#define CPDMA_TXINTMASKCLEAR	0x8c
+#define CPDMA_MACINVECTOR	0x90
+#define CPDMA_MACEOIVECTOR	0x94
+#define CPDMA_RXINTSTATRAW	0xa0
+#define CPDMA_RXINTSTATMASKED	0xa4
+#define CPDMA_RXINTMASKSET	0xa8
+#define CPDMA_RXINTMASKCLEAR	0xac
+#define CPDMA_DMAINTSTATRAW	0xb0
+#define CPDMA_DMAINTSTATMASKED	0xb4
+#define CPDMA_DMAINTMASKSET	0xb8
+#define CPDMA_DMAINTMASKCLEAR	0xbc
+#define CPDMA_DMAINT_HOSTERR	BIT(1)
+
+/* the following exist only if has_ext_regs is set */
+#define CPDMA_DMACONTROL	0x20
+#define CPDMA_DMASTATUS		0x24
+#define CPDMA_RXBUFFOFS		0x28
+#define CPDMA_EM_CONTROL	0x2c
+
+/* Descriptor mode bits */
+#define CPDMA_DESC_SOP		BIT(31)
+#define CPDMA_DESC_EOP		BIT(30)
+#define CPDMA_DESC_OWNER	BIT(29)
+#define CPDMA_DESC_EOQ		BIT(28)
+#define CPDMA_DESC_TD_COMPLETE	BIT(27)
+#define CPDMA_DESC_PASS_CRC	BIT(26)
+
+#define CPDMA_TEARDOWN_VALUE	0xfffffffc
+
+struct cpdma_desc {
+	/* hardware fields */
+	u32			hw_next;
+	u32			hw_buffer;
+	u32			hw_len;
+	u32			hw_mode;
+	/* software fields */
+	void			*sw_token;
+	u32			sw_buffer;
+	u32			sw_len;
+};
+
+struct cpdma_desc_pool {
+	u32			phys;
+	void __iomem		*iomap;		/* ioremap map */
+	void			*cpumap;	/* dma_alloc map */
+	int			desc_size, mem_size;
+	int			num_desc, used_desc;
+	unsigned long		*bitmap;
+	struct device		*dev;
+	spinlock_t		lock;
+};
+
+enum cpdma_state {
+	CPDMA_STATE_IDLE,
+	CPDMA_STATE_ACTIVE,
+	CPDMA_STATE_TEARDOWN,
+};
+
+const char *cpdma_state_str[] = { "idle", "active", "teardown" };
+
+struct cpdma_ctlr {
+	enum cpdma_state	state;
+	struct cpdma_params	params;
+	struct device		*dev;
+	struct cpdma_desc_pool	*pool;
+	spinlock_t		lock;
+	struct cpdma_chan	*channels[2 * CPDMA_MAX_CHANNELS];
+};
+
+struct cpdma_chan {
+	enum cpdma_state		state;
+	struct cpdma_ctlr		*ctlr;
+	int				chan_num;
+	spinlock_t			lock;
+	struct cpdma_desc __iomem	*head, *tail;
+	int				count;
+	void __iomem			*hdp, *cp, *rxfree;
+	u32				mask;
+	cpdma_handler_fn		handler;
+	enum dma_data_direction		dir;
+	struct cpdma_chan_stats		stats;
+	/* offsets into dmaregs */
+	int	int_set, int_clear, td;
+};
+
+/* The following make access to common cpdma_ctlr params more readable */
+#define dmaregs		params.dmaregs
+#define num_chan	params.num_chan
+
+/* various accessors */
+#define dma_reg_read(ctlr, ofs)		__raw_readl((ctlr)->dmaregs + (ofs))
+#define chan_read(chan, fld)		__raw_readl((chan)->fld)
+#define desc_read(desc, fld)		__raw_readl(&(desc)->fld)
+#define dma_reg_write(ctlr, ofs, v)	__raw_writel(v, (ctlr)->dmaregs + (ofs))
+#define chan_write(chan, fld, v)	__raw_writel(v, (chan)->fld)
+#define desc_write(desc, fld, v)	__raw_writel((u32)(v), &(desc)->fld)
+
+/*
+ * Utility constructs for a cpdma descriptor pool.  Some devices (e.g. davinci
+ * emac) have dedicated on-chip memory for these descriptors.  Some other
+ * devices (e.g. cpsw switches) use plain old memory.  Descriptor pools
+ * abstract out these details
+ */
+static struct cpdma_desc_pool *
+cpdma_desc_pool_create(struct device *dev, u32 phys, int size, int align)
+{
+	int bitmap_size;
+	struct cpdma_desc_pool *pool;
+
+	pool = kzalloc(sizeof(*pool), GFP_KERNEL);
+	if (!pool)
+		return NULL;
+
+	spin_lock_init(&pool->lock);
+
+	pool->dev	= dev;
+	pool->mem_size	= size;
+	pool->desc_size	= ALIGN(sizeof(struct cpdma_desc), align);
+	pool->num_desc	= size / pool->desc_size;
+
+	bitmap_size  = (pool->num_desc / BITS_PER_LONG) * sizeof(long);
+	pool->bitmap = kzalloc(bitmap_size, GFP_KERNEL);
+	if (!pool->bitmap)
+		goto fail;
+
+	if (phys) {
+		pool->phys  = phys;
+		pool->iomap = ioremap(phys, size);
+	} else {
+		pool->cpumap = dma_alloc_coherent(dev, size, &pool->phys,
+						  GFP_KERNEL);
+		pool->iomap = (void __force __iomem *)pool->cpumap;
+	}
+
+	if (pool->iomap)
+		return pool;
+
+fail:
+	kfree(pool->bitmap);
+	kfree(pool);
+	return NULL;
+}
+
+static void cpdma_desc_pool_destroy(struct cpdma_desc_pool *pool)
+{
+	unsigned long flags;
+
+	if (!pool)
+		return;
+
+	spin_lock_irqsave(&pool->lock, flags);
+	WARN_ON(pool->used_desc);
+	kfree(pool->bitmap);
+	if (pool->cpumap) {
+		dma_free_coherent(pool->dev, pool->mem_size, pool->cpumap,
+				  pool->phys);
+	} else {
+		iounmap(pool->iomap);
+	}
+	spin_unlock_irqrestore(&pool->lock, flags);
+	kfree(pool);
+}
+
+static inline dma_addr_t desc_phys(struct cpdma_desc_pool *pool,
+		  struct cpdma_desc __iomem *desc)
+{
+	if (!desc)
+		return 0;
+	return pool->phys + (__force dma_addr_t)desc -
+			    (__force dma_addr_t)pool->iomap;
+}
+
+static inline struct cpdma_desc __iomem *
+desc_from_phys(struct cpdma_desc_pool *pool, dma_addr_t dma)
+{
+	return dma ? pool->iomap + dma - pool->phys : NULL;
+}
+
+static struct cpdma_desc __iomem *
+cpdma_desc_alloc(struct cpdma_desc_pool *pool, int num_desc)
+{
+	unsigned long flags;
+	int index;
+	struct cpdma_desc __iomem *desc = NULL;
+
+	spin_lock_irqsave(&pool->lock, flags);
+
+	index = bitmap_find_next_zero_area(pool->bitmap, pool->num_desc, 0,
+					   num_desc, 0);
+	if (index < pool->num_desc) {
+		bitmap_set(pool->bitmap, index, num_desc);
+		desc = pool->iomap + pool->desc_size * index;
+		pool->used_desc++;
+	}
+
+	spin_unlock_irqrestore(&pool->lock, flags);
+	return desc;
+}
+
+static void cpdma_desc_free(struct cpdma_desc_pool *pool,
+			    struct cpdma_desc __iomem *desc, int num_desc)
+{
+	unsigned long flags, index;
+
+	index = ((unsigned long)desc - (unsigned long)pool->iomap) /
+		pool->desc_size;
+	spin_lock_irqsave(&pool->lock, flags);
+	bitmap_clear(pool->bitmap, index, num_desc);
+	pool->used_desc--;
+	spin_unlock_irqrestore(&pool->lock, flags);
+}
+
+struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params)
+{
+	struct cpdma_ctlr *ctlr;
+
+	ctlr = kzalloc(sizeof(*ctlr), GFP_KERNEL);
+	if (!ctlr)
+		return NULL;
+
+	ctlr->state = CPDMA_STATE_IDLE;
+	ctlr->params = *params;
+	ctlr->dev = params->dev;
+	spin_lock_init(&ctlr->lock);
+
+	ctlr->pool = cpdma_desc_pool_create(ctlr->dev,
+					    ctlr->params.desc_mem_phys,
+					    ctlr->params.desc_mem_size,
+					    ctlr->params.desc_align);
+	if (!ctlr->pool) {
+		kfree(ctlr);
+		return NULL;
+	}
+
+	if (WARN_ON(ctlr->num_chan > CPDMA_MAX_CHANNELS))
+		ctlr->num_chan = CPDMA_MAX_CHANNELS;
+	return ctlr;
+}
+
+int cpdma_ctlr_start(struct cpdma_ctlr *ctlr)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	if (ctlr->state != CPDMA_STATE_IDLE) {
+		spin_unlock_irqrestore(&ctlr->lock, flags);
+		return -EBUSY;
+	}
+
+	if (ctlr->params.has_soft_reset) {
+		unsigned long timeout = jiffies + HZ/10;
+
+		dma_reg_write(ctlr, CPDMA_SOFTRESET, 1);
+		while (time_before(jiffies, timeout)) {
+			if (dma_reg_read(ctlr, CPDMA_SOFTRESET) == 0)
+				break;
+		}
+		WARN_ON(!time_before(jiffies, timeout));
+	}
+
+	for (i = 0; i < ctlr->num_chan; i++) {
+		__raw_writel(0, ctlr->params.txhdp + 4 * i);
+		__raw_writel(0, ctlr->params.rxhdp + 4 * i);
+		__raw_writel(0, ctlr->params.txcp + 4 * i);
+		__raw_writel(0, ctlr->params.rxcp + 4 * i);
+	}
+
+	dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
+	dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
+
+	dma_reg_write(ctlr, CPDMA_TXCONTROL, 1);
+	dma_reg_write(ctlr, CPDMA_RXCONTROL, 1);
+
+	ctlr->state = CPDMA_STATE_ACTIVE;
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+		if (ctlr->channels[i])
+			cpdma_chan_start(ctlr->channels[i]);
+	}
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return 0;
+}
+
+int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr)
+{
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	if (ctlr->state != CPDMA_STATE_ACTIVE) {
+		spin_unlock_irqrestore(&ctlr->lock, flags);
+		return -EINVAL;
+	}
+
+	ctlr->state = CPDMA_STATE_TEARDOWN;
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+		if (ctlr->channels[i])
+			cpdma_chan_stop(ctlr->channels[i]);
+	}
+
+	dma_reg_write(ctlr, CPDMA_RXINTMASKCLEAR, 0xffffffff);
+	dma_reg_write(ctlr, CPDMA_TXINTMASKCLEAR, 0xffffffff);
+
+	dma_reg_write(ctlr, CPDMA_TXCONTROL, 0);
+	dma_reg_write(ctlr, CPDMA_RXCONTROL, 0);
+
+	ctlr->state = CPDMA_STATE_IDLE;
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return 0;
+}
+
+int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr)
+{
+	struct device *dev = ctlr->dev;
+	unsigned long flags;
+	int i;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	dev_info(dev, "CPDMA: state: %s", cpdma_state_str[ctlr->state]);
+
+	dev_info(dev, "CPDMA: txidver: %x",
+		 dma_reg_read(ctlr, CPDMA_TXIDVER));
+	dev_info(dev, "CPDMA: txcontrol: %x",
+		 dma_reg_read(ctlr, CPDMA_TXCONTROL));
+	dev_info(dev, "CPDMA: txteardown: %x",
+		 dma_reg_read(ctlr, CPDMA_TXTEARDOWN));
+	dev_info(dev, "CPDMA: rxidver: %x",
+		 dma_reg_read(ctlr, CPDMA_RXIDVER));
+	dev_info(dev, "CPDMA: rxcontrol: %x",
+		 dma_reg_read(ctlr, CPDMA_RXCONTROL));
+	dev_info(dev, "CPDMA: softreset: %x",
+		 dma_reg_read(ctlr, CPDMA_SOFTRESET));
+	dev_info(dev, "CPDMA: rxteardown: %x",
+		 dma_reg_read(ctlr, CPDMA_RXTEARDOWN));
+	dev_info(dev, "CPDMA: txintstatraw: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTSTATRAW));
+	dev_info(dev, "CPDMA: txintstatmasked: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTSTATMASKED));
+	dev_info(dev, "CPDMA: txintmaskset: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTMASKSET));
+	dev_info(dev, "CPDMA: txintmaskclear: %x",
+		 dma_reg_read(ctlr, CPDMA_TXINTMASKCLEAR));
+	dev_info(dev, "CPDMA: macinvector: %x",
+		 dma_reg_read(ctlr, CPDMA_MACINVECTOR));
+	dev_info(dev, "CPDMA: maceoivector: %x",
+		 dma_reg_read(ctlr, CPDMA_MACEOIVECTOR));
+	dev_info(dev, "CPDMA: rxintstatraw: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTSTATRAW));
+	dev_info(dev, "CPDMA: rxintstatmasked: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTSTATMASKED));
+	dev_info(dev, "CPDMA: rxintmaskset: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTMASKSET));
+	dev_info(dev, "CPDMA: rxintmaskclear: %x",
+		 dma_reg_read(ctlr, CPDMA_RXINTMASKCLEAR));
+	dev_info(dev, "CPDMA: dmaintstatraw: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTSTATRAW));
+	dev_info(dev, "CPDMA: dmaintstatmasked: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTSTATMASKED));
+	dev_info(dev, "CPDMA: dmaintmaskset: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTMASKSET));
+	dev_info(dev, "CPDMA: dmaintmaskclear: %x",
+		 dma_reg_read(ctlr, CPDMA_DMAINTMASKCLEAR));
+
+	if (!ctlr->params.has_ext_regs) {
+		dev_info(dev, "CPDMA: dmacontrol: %x",
+			 dma_reg_read(ctlr, CPDMA_DMACONTROL));
+		dev_info(dev, "CPDMA: dmastatus: %x",
+			 dma_reg_read(ctlr, CPDMA_DMASTATUS));
+		dev_info(dev, "CPDMA: rxbuffofs: %x",
+			 dma_reg_read(ctlr, CPDMA_RXBUFFOFS));
+	}
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++)
+		if (ctlr->channels[i])
+			cpdma_chan_dump(ctlr->channels[i]);
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return 0;
+}
+
+int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr)
+{
+	unsigned long flags;
+	int ret = 0, i;
+
+	if (!ctlr)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	if (ctlr->state != CPDMA_STATE_IDLE)
+		cpdma_ctlr_stop(ctlr);
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+		if (ctlr->channels[i])
+			cpdma_chan_destroy(ctlr->channels[i]);
+	}
+
+	cpdma_desc_pool_destroy(ctlr->pool);
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	kfree(ctlr);
+	return ret;
+}
+
+int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable)
+{
+	unsigned long flags;
+	int i, reg;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	if (ctlr->state != CPDMA_STATE_ACTIVE) {
+		spin_unlock_irqrestore(&ctlr->lock, flags);
+		return -EINVAL;
+	}
+
+	reg = enable ? CPDMA_DMAINTMASKSET : CPDMA_DMAINTMASKCLEAR;
+	dma_reg_write(ctlr, reg, CPDMA_DMAINT_HOSTERR);
+
+	for (i = 0; i < ARRAY_SIZE(ctlr->channels); i++) {
+		if (ctlr->channels[i])
+			cpdma_chan_int_ctrl(ctlr->channels[i], enable);
+	}
+
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return 0;
+}
+
+void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr)
+{
+	dma_reg_write(ctlr, CPDMA_MACEOIVECTOR, 0);
+}
+
+struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
+				     cpdma_handler_fn handler)
+{
+	struct cpdma_chan *chan;
+	int ret, offset = (chan_num % CPDMA_MAX_CHANNELS) * 4;
+	unsigned long flags;
+
+	if (__chan_linear(chan_num) >= ctlr->num_chan)
+		return NULL;
+
+	ret = -ENOMEM;
+	chan = kzalloc(sizeof(*chan), GFP_KERNEL);
+	if (!chan)
+		goto err_chan_alloc;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	ret = -EBUSY;
+	if (ctlr->channels[chan_num])
+		goto err_chan_busy;
+
+	chan->ctlr	= ctlr;
+	chan->state	= CPDMA_STATE_IDLE;
+	chan->chan_num	= chan_num;
+	chan->handler	= handler;
+
+	if (is_rx_chan(chan)) {
+		chan->hdp	= ctlr->params.rxhdp + offset;
+		chan->cp	= ctlr->params.rxcp + offset;
+		chan->rxfree	= ctlr->params.rxfree + offset;
+		chan->int_set	= CPDMA_RXINTMASKSET;
+		chan->int_clear	= CPDMA_RXINTMASKCLEAR;
+		chan->td	= CPDMA_RXTEARDOWN;
+		chan->dir	= DMA_FROM_DEVICE;
+	} else {
+		chan->hdp	= ctlr->params.txhdp + offset;
+		chan->cp	= ctlr->params.txcp + offset;
+		chan->int_set	= CPDMA_TXINTMASKSET;
+		chan->int_clear	= CPDMA_TXINTMASKCLEAR;
+		chan->td	= CPDMA_TXTEARDOWN;
+		chan->dir	= DMA_TO_DEVICE;
+	}
+	chan->mask = BIT(chan_linear(chan));
+
+	spin_lock_init(&chan->lock);
+
+	ctlr->channels[chan_num] = chan;
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return chan;
+
+err_chan_busy:
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	kfree(chan);
+err_chan_alloc:
+	return ERR_PTR(ret);
+}
+
+int cpdma_chan_destroy(struct cpdma_chan *chan)
+{
+	struct cpdma_ctlr *ctlr = chan->ctlr;
+	unsigned long flags;
+
+	if (!chan)
+		return -EINVAL;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+	if (chan->state != CPDMA_STATE_IDLE)
+		cpdma_chan_stop(chan);
+	ctlr->channels[chan->chan_num] = NULL;
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	kfree(chan);
+	return 0;
+}
+
+int cpdma_chan_get_stats(struct cpdma_chan *chan,
+			 struct cpdma_chan_stats *stats)
+{
+	unsigned long flags;
+	if (!chan)
+		return -EINVAL;
+	spin_lock_irqsave(&chan->lock, flags);
+	memcpy(stats, &chan->stats, sizeof(*stats));
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return 0;
+}
+
+int cpdma_chan_dump(struct cpdma_chan *chan)
+{
+	unsigned long flags;
+	struct device *dev = chan->ctlr->dev;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	dev_info(dev, "channel %d (%s %d) state %s",
+		 chan->chan_num, is_rx_chan(chan) ? "rx" : "tx",
+		 chan_linear(chan), cpdma_state_str[chan->state]);
+	dev_info(dev, "\thdp: %x\n", chan_read(chan, hdp));
+	dev_info(dev, "\tcp: %x\n", chan_read(chan, cp));
+	if (chan->rxfree) {
+		dev_info(dev, "\trxfree: %x\n",
+			 chan_read(chan, rxfree));
+	}
+
+	dev_info(dev, "\tstats head_enqueue: %d\n",
+		 chan->stats.head_enqueue);
+	dev_info(dev, "\tstats tail_enqueue: %d\n",
+		 chan->stats.tail_enqueue);
+	dev_info(dev, "\tstats pad_enqueue: %d\n",
+		 chan->stats.pad_enqueue);
+	dev_info(dev, "\tstats misqueued: %d\n",
+		 chan->stats.misqueued);
+	dev_info(dev, "\tstats desc_alloc_fail: %d\n",
+		 chan->stats.desc_alloc_fail);
+	dev_info(dev, "\tstats pad_alloc_fail: %d\n",
+		 chan->stats.pad_alloc_fail);
+	dev_info(dev, "\tstats runt_receive_buff: %d\n",
+		 chan->stats.runt_receive_buff);
+	dev_info(dev, "\tstats runt_transmit_buff: %d\n",
+		 chan->stats.runt_transmit_buff);
+	dev_info(dev, "\tstats empty_dequeue: %d\n",
+		 chan->stats.empty_dequeue);
+	dev_info(dev, "\tstats busy_dequeue: %d\n",
+		 chan->stats.busy_dequeue);
+	dev_info(dev, "\tstats good_dequeue: %d\n",
+		 chan->stats.good_dequeue);
+	dev_info(dev, "\tstats requeue: %d\n",
+		 chan->stats.requeue);
+	dev_info(dev, "\tstats teardown_dequeue: %d\n",
+		 chan->stats.teardown_dequeue);
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return 0;
+}
+
+static void __cpdma_chan_submit(struct cpdma_chan *chan,
+				struct cpdma_desc __iomem *desc)
+{
+	struct cpdma_ctlr		*ctlr = chan->ctlr;
+	struct cpdma_desc __iomem	*prev = chan->tail;
+	struct cpdma_desc_pool		*pool = ctlr->pool;
+	dma_addr_t			desc_dma;
+	u32				mode;
+
+	desc_dma = desc_phys(pool, desc);
+
+	/* simple case - idle channel */
+	if (!chan->head) {
+		chan->stats.head_enqueue++;
+		chan->head = desc;
+		chan->tail = desc;
+		if (chan->state == CPDMA_STATE_ACTIVE)
+			chan_write(chan, hdp, desc_dma);
+		return;
+	}
+
+	/* first chain the descriptor at the tail of the list */
+	desc_write(prev, hw_next, desc_dma);
+	chan->tail = desc;
+	chan->stats.tail_enqueue++;
+
+	/* next check if EOQ has been triggered already */
+	mode = desc_read(prev, hw_mode);
+	if (((mode & (CPDMA_DESC_EOQ | CPDMA_DESC_OWNER)) == CPDMA_DESC_EOQ) &&
+	    (chan->state == CPDMA_STATE_ACTIVE)) {
+		desc_write(prev, hw_mode, mode & ~CPDMA_DESC_EOQ);
+		chan_write(chan, hdp, desc_dma);
+		chan->stats.misqueued++;
+	}
+}
+
+int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
+		      int len, gfp_t gfp_mask)
+{
+	struct cpdma_ctlr		*ctlr = chan->ctlr;
+	struct cpdma_desc __iomem	*desc;
+	dma_addr_t			buffer;
+	unsigned long			flags;
+	u32				mode;
+	int				ret = 0;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	if (chan->state == CPDMA_STATE_TEARDOWN) {
+		ret = -EINVAL;
+		goto unlock_ret;
+	}
+
+	desc = cpdma_desc_alloc(ctlr->pool, 1);
+	if (!desc) {
+		chan->stats.desc_alloc_fail++;
+		ret = -ENOMEM;
+		goto unlock_ret;
+	}
+
+	if (len < ctlr->params.min_packet_size) {
+		len = ctlr->params.min_packet_size;
+		chan->stats.runt_transmit_buff++;
+	}
+
+	buffer = dma_map_single(ctlr->dev, data, len, chan->dir);
+	mode = CPDMA_DESC_OWNER | CPDMA_DESC_SOP | CPDMA_DESC_EOP;
+
+	desc_write(desc, hw_next,   0);
+	desc_write(desc, hw_buffer, buffer);
+	desc_write(desc, hw_len,    len);
+	desc_write(desc, hw_mode,   mode | len);
+	desc_write(desc, sw_token,  token);
+	desc_write(desc, sw_buffer, buffer);
+	desc_write(desc, sw_len,    len);
+
+	__cpdma_chan_submit(chan, desc);
+
+	if (chan->state == CPDMA_STATE_ACTIVE && chan->rxfree)
+		chan_write(chan, rxfree, 1);
+
+	chan->count++;
+
+unlock_ret:
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return ret;
+}
+
+static void __cpdma_chan_free(struct cpdma_chan *chan,
+			      struct cpdma_desc __iomem *desc,
+			      int outlen, int status)
+{
+	struct cpdma_ctlr		*ctlr = chan->ctlr;
+	struct cpdma_desc_pool		*pool = ctlr->pool;
+	dma_addr_t			buff_dma;
+	int				origlen;
+	void				*token;
+
+	token      = (void *)desc_read(desc, sw_token);
+	buff_dma   = desc_read(desc, sw_buffer);
+	origlen    = desc_read(desc, sw_len);
+
+	dma_unmap_single(ctlr->dev, buff_dma, origlen, chan->dir);
+	cpdma_desc_free(pool, desc, 1);
+	(*chan->handler)(token, outlen, status);
+}
+
+static int __cpdma_chan_process(struct cpdma_chan *chan)
+{
+	struct cpdma_ctlr		*ctlr = chan->ctlr;
+	struct cpdma_desc __iomem	*desc;
+	int				status, outlen;
+	struct cpdma_desc_pool		*pool = ctlr->pool;
+	dma_addr_t			desc_dma;
+	unsigned long			flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+
+	desc = chan->head;
+	if (!desc) {
+		chan->stats.empty_dequeue++;
+		status = -ENOENT;
+		goto unlock_ret;
+	}
+	desc_dma = desc_phys(pool, desc);
+
+	status	= __raw_readl(&desc->hw_mode);
+	outlen	= status & 0x7ff;
+	if (status & CPDMA_DESC_OWNER) {
+		chan->stats.busy_dequeue++;
+		status = -EBUSY;
+		goto unlock_ret;
+	}
+	status	= status & (CPDMA_DESC_EOQ | CPDMA_DESC_TD_COMPLETE);
+
+	chan->head = desc_from_phys(pool, desc_read(desc, hw_next));
+	chan_write(chan, cp, desc_dma);
+	chan->count--;
+	chan->stats.good_dequeue++;
+
+	if (status & CPDMA_DESC_EOQ) {
+		chan->stats.requeue++;
+		chan_write(chan, hdp, desc_phys(pool, chan->head));
+	}
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	__cpdma_chan_free(chan, desc, outlen, status);
+	return status;
+
+unlock_ret:
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return status;
+}
+
+int cpdma_chan_process(struct cpdma_chan *chan, int quota)
+{
+	int used = 0, ret = 0;
+
+	if (chan->state != CPDMA_STATE_ACTIVE)
+		return -EINVAL;
+
+	while (used < quota) {
+		ret = __cpdma_chan_process(chan);
+		if (ret < 0)
+			break;
+		used++;
+	}
+	return used;
+}
+
+int cpdma_chan_start(struct cpdma_chan *chan)
+{
+	struct cpdma_ctlr	*ctlr = chan->ctlr;
+	struct cpdma_desc_pool	*pool = ctlr->pool;
+	unsigned long		flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	if (chan->state != CPDMA_STATE_IDLE) {
+		spin_unlock_irqrestore(&chan->lock, flags);
+		return -EBUSY;
+	}
+	if (ctlr->state != CPDMA_STATE_ACTIVE) {
+		spin_unlock_irqrestore(&chan->lock, flags);
+		return -EINVAL;
+	}
+	dma_reg_write(ctlr, chan->int_set, chan->mask);
+	chan->state = CPDMA_STATE_ACTIVE;
+	if (chan->head) {
+		chan_write(chan, hdp, desc_phys(pool, chan->head));
+		if (chan->rxfree)
+			chan_write(chan, rxfree, chan->count);
+	}
+
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return 0;
+}
+
+int cpdma_chan_stop(struct cpdma_chan *chan)
+{
+	struct cpdma_ctlr	*ctlr = chan->ctlr;
+	struct cpdma_desc_pool	*pool = ctlr->pool;
+	unsigned long		flags;
+	int			ret;
+	unsigned long		timeout;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	if (chan->state != CPDMA_STATE_ACTIVE) {
+		spin_unlock_irqrestore(&chan->lock, flags);
+		return -EINVAL;
+	}
+
+	chan->state = CPDMA_STATE_TEARDOWN;
+	dma_reg_write(ctlr, chan->int_clear, chan->mask);
+
+	/* trigger teardown */
+	dma_reg_write(ctlr, chan->td, chan->chan_num);
+
+	/* wait for teardown complete */
+	timeout = jiffies + HZ/10;	/* 100 msec */
+	while (time_before(jiffies, timeout)) {
+		u32 cp = chan_read(chan, cp);
+		if ((cp & CPDMA_TEARDOWN_VALUE) == CPDMA_TEARDOWN_VALUE)
+			break;
+		cpu_relax();
+	}
+	WARN_ON(!time_before(jiffies, timeout));
+	chan_write(chan, cp, CPDMA_TEARDOWN_VALUE);
+
+	/* handle completed packets */
+	do {
+		ret = __cpdma_chan_process(chan);
+		if (ret < 0)
+			break;
+	} while ((ret & CPDMA_DESC_TD_COMPLETE) == 0);
+
+	/* remaining packets haven't been tx/rx'ed, clean them up */
+	while (chan->head) {
+		struct cpdma_desc __iomem *desc = chan->head;
+		dma_addr_t next_dma;
+
+		next_dma = desc_read(desc, hw_next);
+		chan->head = desc_from_phys(pool, next_dma);
+		chan->stats.teardown_dequeue++;
+
+		/* issue callback without locks held */
+		spin_unlock_irqrestore(&chan->lock, flags);
+		__cpdma_chan_free(chan, desc, 0, -ENOSYS);
+		spin_lock_irqsave(&chan->lock, flags);
+	}
+
+	chan->state = CPDMA_STATE_IDLE;
+	spin_unlock_irqrestore(&chan->lock, flags);
+	return 0;
+}
+
+int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&chan->lock, flags);
+	if (chan->state != CPDMA_STATE_ACTIVE) {
+		spin_unlock_irqrestore(&chan->lock, flags);
+		return -EINVAL;
+	}
+
+	dma_reg_write(chan->ctlr, enable ? chan->int_set : chan->int_clear,
+		      chan->mask);
+	spin_unlock_irqrestore(&chan->lock, flags);
+
+	return 0;
+}
+
+struct cpdma_control_info {
+	u32		reg;
+	u32		shift, mask;
+	int		access;
+#define ACCESS_RO	BIT(0)
+#define ACCESS_WO	BIT(1)
+#define ACCESS_RW	(ACCESS_RO | ACCESS_WO)
+};
+
+struct cpdma_control_info controls[] = {
+	[CPDMA_CMD_IDLE]	  = {CPDMA_DMACONTROL,	3,  1,      ACCESS_WO},
+	[CPDMA_COPY_ERROR_FRAMES] = {CPDMA_DMACONTROL,	4,  1,      ACCESS_RW},
+	[CPDMA_RX_OFF_LEN_UPDATE] = {CPDMA_DMACONTROL,	2,  1,      ACCESS_RW},
+	[CPDMA_RX_OWNERSHIP_FLIP] = {CPDMA_DMACONTROL,	1,  1,      ACCESS_RW},
+	[CPDMA_TX_PRIO_FIXED]	  = {CPDMA_DMACONTROL,	0,  1,      ACCESS_RW},
+	[CPDMA_STAT_IDLE]	  = {CPDMA_DMASTATUS,	31, 1,      ACCESS_RO},
+	[CPDMA_STAT_TX_ERR_CODE]  = {CPDMA_DMASTATUS,	20, 0xf,    ACCESS_RW},
+	[CPDMA_STAT_TX_ERR_CHAN]  = {CPDMA_DMASTATUS,	16, 0x7,    ACCESS_RW},
+	[CPDMA_STAT_RX_ERR_CODE]  = {CPDMA_DMASTATUS,	12, 0xf,    ACCESS_RW},
+	[CPDMA_STAT_RX_ERR_CHAN]  = {CPDMA_DMASTATUS,	8,  0x7,    ACCESS_RW},
+	[CPDMA_RX_BUFFER_OFFSET]  = {CPDMA_RXBUFFOFS,	0,  0xffff, ACCESS_RW},
+};
+
+int cpdma_control_get(struct cpdma_ctlr *ctlr, int control)
+{
+	unsigned long flags;
+	struct cpdma_control_info *info = &controls[control];
+	int ret;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	ret = -ENOTSUPP;
+	if (!ctlr->params.has_ext_regs)
+		goto unlock_ret;
+
+	ret = -EINVAL;
+	if (ctlr->state != CPDMA_STATE_ACTIVE)
+		goto unlock_ret;
+
+	ret = -ENOENT;
+	if (control < 0 || control >= ARRAY_SIZE(controls))
+		goto unlock_ret;
+
+	ret = -EPERM;
+	if ((info->access & ACCESS_RO) != ACCESS_RO)
+		goto unlock_ret;
+
+	ret = (dma_reg_read(ctlr, info->reg) >> info->shift) & info->mask;
+
+unlock_ret:
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return ret;
+}
+
+int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value)
+{
+	unsigned long flags;
+	struct cpdma_control_info *info = &controls[control];
+	int ret;
+	u32 val;
+
+	spin_lock_irqsave(&ctlr->lock, flags);
+
+	ret = -ENOTSUPP;
+	if (!ctlr->params.has_ext_regs)
+		goto unlock_ret;
+
+	ret = -EINVAL;
+	if (ctlr->state != CPDMA_STATE_ACTIVE)
+		goto unlock_ret;
+
+	ret = -ENOENT;
+	if (control < 0 || control >= ARRAY_SIZE(controls))
+		goto unlock_ret;
+
+	ret = -EPERM;
+	if ((info->access & ACCESS_WO) != ACCESS_WO)
+		goto unlock_ret;
+
+	val  = dma_reg_read(ctlr, info->reg);
+	val &= ~(info->mask << info->shift);
+	val |= (value & info->mask) << info->shift;
+	dma_reg_write(ctlr, info->reg, val);
+	ret = 0;
+
+unlock_ret:
+	spin_unlock_irqrestore(&ctlr->lock, flags);
+	return ret;
+}

+ 108 - 0
drivers/net/davinci_cpdma.h

@@ -0,0 +1,108 @@
+/*
+ * Texas Instruments CPDMA Driver
+ *
+ * Copyright (C) 2010 Texas Instruments
+ *
+ * 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.
+ */
+#ifndef __DAVINCI_CPDMA_H__
+#define __DAVINCI_CPDMA_H__
+
+#define CPDMA_MAX_CHANNELS	BITS_PER_LONG
+
+#define tx_chan_num(chan)	(chan)
+#define rx_chan_num(chan)	((chan) + CPDMA_MAX_CHANNELS)
+#define is_rx_chan(chan)	((chan)->chan_num >= CPDMA_MAX_CHANNELS)
+#define is_tx_chan(chan)	(!is_rx_chan(chan))
+#define __chan_linear(chan_num)	((chan_num) & (CPDMA_MAX_CHANNELS - 1))
+#define chan_linear(chan)	__chan_linear((chan)->chan_num)
+
+struct cpdma_params {
+	struct device		*dev;
+	void __iomem		*dmaregs;
+	void __iomem		*txhdp, *rxhdp, *txcp, *rxcp;
+	void __iomem		*rxthresh, *rxfree;
+	int			num_chan;
+	bool			has_soft_reset;
+	int			min_packet_size;
+	u32			desc_mem_phys;
+	int			desc_mem_size;
+	int			desc_align;
+
+	/*
+	 * Some instances of embedded cpdma controllers have extra control and
+	 * status registers.  The following flag enables access to these
+	 * "extended" registers.
+	 */
+	bool			has_ext_regs;
+};
+
+struct cpdma_chan_stats {
+	u32			head_enqueue;
+	u32			tail_enqueue;
+	u32			pad_enqueue;
+	u32			misqueued;
+	u32			desc_alloc_fail;
+	u32			pad_alloc_fail;
+	u32			runt_receive_buff;
+	u32			runt_transmit_buff;
+	u32			empty_dequeue;
+	u32			busy_dequeue;
+	u32			good_dequeue;
+	u32			requeue;
+	u32			teardown_dequeue;
+};
+
+struct cpdma_ctlr;
+struct cpdma_chan;
+
+typedef void (*cpdma_handler_fn)(void *token, int len, int status);
+
+struct cpdma_ctlr *cpdma_ctlr_create(struct cpdma_params *params);
+int cpdma_ctlr_destroy(struct cpdma_ctlr *ctlr);
+int cpdma_ctlr_start(struct cpdma_ctlr *ctlr);
+int cpdma_ctlr_stop(struct cpdma_ctlr *ctlr);
+int cpdma_ctlr_dump(struct cpdma_ctlr *ctlr);
+
+struct cpdma_chan *cpdma_chan_create(struct cpdma_ctlr *ctlr, int chan_num,
+				     cpdma_handler_fn handler);
+int cpdma_chan_destroy(struct cpdma_chan *chan);
+int cpdma_chan_start(struct cpdma_chan *chan);
+int cpdma_chan_stop(struct cpdma_chan *chan);
+int cpdma_chan_dump(struct cpdma_chan *chan);
+
+int cpdma_chan_get_stats(struct cpdma_chan *chan,
+			 struct cpdma_chan_stats *stats);
+int cpdma_chan_submit(struct cpdma_chan *chan, void *token, void *data,
+		      int len, gfp_t gfp_mask);
+int cpdma_chan_process(struct cpdma_chan *chan, int quota);
+
+int cpdma_ctlr_int_ctrl(struct cpdma_ctlr *ctlr, bool enable);
+void cpdma_ctlr_eoi(struct cpdma_ctlr *ctlr);
+int cpdma_chan_int_ctrl(struct cpdma_chan *chan, bool enable);
+
+enum cpdma_control {
+	CPDMA_CMD_IDLE,			/* write-only */
+	CPDMA_COPY_ERROR_FRAMES,	/* read-write */
+	CPDMA_RX_OFF_LEN_UPDATE,	/* read-write */
+	CPDMA_RX_OWNERSHIP_FLIP,	/* read-write */
+	CPDMA_TX_PRIO_FIXED,		/* read-write */
+	CPDMA_STAT_IDLE,		/* read-only */
+	CPDMA_STAT_TX_ERR_CHAN,		/* read-only */
+	CPDMA_STAT_TX_ERR_CODE,		/* read-only */
+	CPDMA_STAT_RX_ERR_CHAN,		/* read-only */
+	CPDMA_STAT_RX_ERR_CODE,		/* read-only */
+	CPDMA_RX_BUFFER_OFFSET,		/* read-write */
+};
+
+int cpdma_control_get(struct cpdma_ctlr *ctlr, int control);
+int cpdma_control_set(struct cpdma_ctlr *ctlr, int control, int value);
+
+#endif

File diff suppressed because it is too large
+ 80 - 786
drivers/net/davinci_emac.c


+ 475 - 0
drivers/net/davinci_mdio.c

@@ -0,0 +1,475 @@
+/*
+ * DaVinci MDIO Module driver
+ *
+ * Copyright (C) 2010 Texas Instruments.
+ *
+ * Shamelessly ripped out of davinci_emac.c, original copyrights follow:
+ *
+ * Copyright (C) 2009 Texas Instruments.
+ *
+ * ---------------------------------------------------------------------------
+ *
+ * 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.
+ * ---------------------------------------------------------------------------
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/phy.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/davinci_emac.h>
+
+/*
+ * This timeout definition is a worst-case ultra defensive measure against
+ * unexpected controller lock ups.  Ideally, we should never ever hit this
+ * scenario in practice.
+ */
+#define MDIO_TIMEOUT		100 /* msecs */
+
+#define PHY_REG_MASK		0x1f
+#define PHY_ID_MASK		0x1f
+
+#define DEF_OUT_FREQ		2200000		/* 2.2 MHz */
+
+struct davinci_mdio_regs {
+	u32	version;
+	u32	control;
+#define CONTROL_IDLE		BIT(31)
+#define CONTROL_ENABLE		BIT(30)
+#define CONTROL_MAX_DIV		(0xff)
+
+	u32	alive;
+	u32	link;
+	u32	linkintraw;
+	u32	linkintmasked;
+	u32	__reserved_0[2];
+	u32	userintraw;
+	u32	userintmasked;
+	u32	userintmaskset;
+	u32	userintmaskclr;
+	u32	__reserved_1[20];
+
+	struct {
+		u32	access;
+#define USERACCESS_GO		BIT(31)
+#define USERACCESS_WRITE	BIT(30)
+#define USERACCESS_ACK		BIT(29)
+#define USERACCESS_READ		(0)
+#define USERACCESS_DATA		(0xffff)
+
+		u32	physel;
+	}	user[0];
+};
+
+struct mdio_platform_data default_pdata = {
+	.bus_freq = DEF_OUT_FREQ,
+};
+
+struct davinci_mdio_data {
+	struct mdio_platform_data pdata;
+	struct davinci_mdio_regs __iomem *regs;
+	spinlock_t	lock;
+	struct clk	*clk;
+	struct device	*dev;
+	struct mii_bus	*bus;
+	bool		suspended;
+	unsigned long	access_time; /* jiffies */
+};
+
+static void __davinci_mdio_reset(struct davinci_mdio_data *data)
+{
+	u32 mdio_in, div, mdio_out_khz, access_time;
+
+	mdio_in = clk_get_rate(data->clk);
+	div = (mdio_in / data->pdata.bus_freq) - 1;
+	if (div > CONTROL_MAX_DIV)
+		div = CONTROL_MAX_DIV;
+
+	/* set enable and clock divider */
+	__raw_writel(div | CONTROL_ENABLE, &data->regs->control);
+
+	/*
+	 * One mdio transaction consists of:
+	 *	32 bits of preamble
+	 *	32 bits of transferred data
+	 *	24 bits of bus yield (not needed unless shared?)
+	 */
+	mdio_out_khz = mdio_in / (1000 * (div + 1));
+	access_time  = (88 * 1000) / mdio_out_khz;
+
+	/*
+	 * In the worst case, we could be kicking off a user-access immediately
+	 * after the mdio bus scan state-machine triggered its own read.  If
+	 * so, our request could get deferred by one access cycle.  We
+	 * defensively allow for 4 access cycles.
+	 */
+	data->access_time = usecs_to_jiffies(access_time * 4);
+	if (!data->access_time)
+		data->access_time = 1;
+}
+
+static int davinci_mdio_reset(struct mii_bus *bus)
+{
+	struct davinci_mdio_data *data = bus->priv;
+	u32 phy_mask, ver;
+
+	__davinci_mdio_reset(data);
+
+	/* wait for scan logic to settle */
+	msleep(PHY_MAX_ADDR * data->access_time);
+
+	/* dump hardware version info */
+	ver = __raw_readl(&data->regs->version);
+	dev_info(data->dev, "davinci mdio revision %d.%d\n",
+		 (ver >> 8) & 0xff, ver & 0xff);
+
+	/* get phy mask from the alive register */
+	phy_mask = __raw_readl(&data->regs->alive);
+	if (phy_mask) {
+		/* restrict mdio bus to live phys only */
+		dev_info(data->dev, "detected phy mask %x\n", ~phy_mask);
+		phy_mask = ~phy_mask;
+	} else {
+		/* desperately scan all phys */
+		dev_warn(data->dev, "no live phy, scanning all\n");
+		phy_mask = 0;
+	}
+	data->bus->phy_mask = phy_mask;
+
+	return 0;
+}
+
+/* wait until hardware is ready for another user access */
+static inline int wait_for_user_access(struct davinci_mdio_data *data)
+{
+	struct davinci_mdio_regs __iomem *regs = data->regs;
+	unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
+	u32 reg;
+
+	while (time_after(timeout, jiffies)) {
+		reg = __raw_readl(&regs->user[0].access);
+		if ((reg & USERACCESS_GO) == 0)
+			return 0;
+
+		reg = __raw_readl(&regs->control);
+		if ((reg & CONTROL_IDLE) == 0)
+			continue;
+
+		/*
+		 * An emac soft_reset may have clobbered the mdio controller's
+		 * state machine.  We need to reset and retry the current
+		 * operation
+		 */
+		dev_warn(data->dev, "resetting idled controller\n");
+		__davinci_mdio_reset(data);
+		return -EAGAIN;
+	}
+	dev_err(data->dev, "timed out waiting for user access\n");
+	return -ETIMEDOUT;
+}
+
+/* wait until hardware state machine is idle */
+static inline int wait_for_idle(struct davinci_mdio_data *data)
+{
+	struct davinci_mdio_regs __iomem *regs = data->regs;
+	unsigned long timeout = jiffies + msecs_to_jiffies(MDIO_TIMEOUT);
+
+	while (time_after(timeout, jiffies)) {
+		if (__raw_readl(&regs->control) & CONTROL_IDLE)
+			return 0;
+	}
+	dev_err(data->dev, "timed out waiting for idle\n");
+	return -ETIMEDOUT;
+}
+
+static int davinci_mdio_read(struct mii_bus *bus, int phy_id, int phy_reg)
+{
+	struct davinci_mdio_data *data = bus->priv;
+	u32 reg;
+	int ret;
+
+	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+		return -EINVAL;
+
+	spin_lock(&data->lock);
+
+	if (data->suspended) {
+		spin_unlock(&data->lock);
+		return -ENODEV;
+	}
+
+	reg = (USERACCESS_GO | USERACCESS_READ | (phy_reg << 21) |
+	       (phy_id << 16));
+
+	while (1) {
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		if (ret < 0)
+			break;
+
+		__raw_writel(reg, &data->regs->user[0].access);
+
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		if (ret < 0)
+			break;
+
+		reg = __raw_readl(&data->regs->user[0].access);
+		ret = (reg & USERACCESS_ACK) ? (reg & USERACCESS_DATA) : -EIO;
+		break;
+	}
+
+	spin_unlock(&data->lock);
+
+	return ret;
+}
+
+static int davinci_mdio_write(struct mii_bus *bus, int phy_id,
+			      int phy_reg, u16 phy_data)
+{
+	struct davinci_mdio_data *data = bus->priv;
+	u32 reg;
+	int ret;
+
+	if (phy_reg & ~PHY_REG_MASK || phy_id & ~PHY_ID_MASK)
+		return -EINVAL;
+
+	spin_lock(&data->lock);
+
+	if (data->suspended) {
+		spin_unlock(&data->lock);
+		return -ENODEV;
+	}
+
+	reg = (USERACCESS_GO | USERACCESS_WRITE | (phy_reg << 21) |
+		   (phy_id << 16) | (phy_data & USERACCESS_DATA));
+
+	while (1) {
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		if (ret < 0)
+			break;
+
+		__raw_writel(reg, &data->regs->user[0].access);
+
+		ret = wait_for_user_access(data);
+		if (ret == -EAGAIN)
+			continue;
+		break;
+	}
+
+	spin_unlock(&data->lock);
+
+	return 0;
+}
+
+static int __devinit davinci_mdio_probe(struct platform_device *pdev)
+{
+	struct mdio_platform_data *pdata = pdev->dev.platform_data;
+	struct device *dev = &pdev->dev;
+	struct davinci_mdio_data *data;
+	struct resource *res;
+	struct phy_device *phy;
+	int ret, addr;
+
+	data = kzalloc(sizeof(*data), GFP_KERNEL);
+	if (!data) {
+		dev_err(dev, "failed to alloc device data\n");
+		return -ENOMEM;
+	}
+
+	data->pdata = pdata ? (*pdata) : default_pdata;
+
+	data->bus = mdiobus_alloc();
+	if (!data->bus) {
+		dev_err(dev, "failed to alloc mii bus\n");
+		ret = -ENOMEM;
+		goto bail_out;
+	}
+
+	data->bus->name		= dev_name(dev);
+	data->bus->read		= davinci_mdio_read,
+	data->bus->write	= davinci_mdio_write,
+	data->bus->reset	= davinci_mdio_reset,
+	data->bus->parent	= dev;
+	data->bus->priv		= data;
+	snprintf(data->bus->id, MII_BUS_ID_SIZE, "%x", pdev->id);
+
+	data->clk = clk_get(dev, NULL);
+	if (IS_ERR(data->clk)) {
+		data->clk = NULL;
+		dev_err(dev, "failed to get device clock\n");
+		ret = PTR_ERR(data->clk);
+		goto bail_out;
+	}
+
+	clk_enable(data->clk);
+
+	dev_set_drvdata(dev, data);
+	data->dev = dev;
+	spin_lock_init(&data->lock);
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!res) {
+		dev_err(dev, "could not find register map resource\n");
+		ret = -ENOENT;
+		goto bail_out;
+	}
+
+	res = devm_request_mem_region(dev, res->start, resource_size(res),
+					    dev_name(dev));
+	if (!res) {
+		dev_err(dev, "could not allocate register map resource\n");
+		ret = -ENXIO;
+		goto bail_out;
+	}
+
+	data->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
+	if (!data->regs) {
+		dev_err(dev, "could not map mdio registers\n");
+		ret = -ENOMEM;
+		goto bail_out;
+	}
+
+	/* register the mii bus */
+	ret = mdiobus_register(data->bus);
+	if (ret)
+		goto bail_out;
+
+	/* scan and dump the bus */
+	for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
+		phy = data->bus->phy_map[addr];
+		if (phy) {
+			dev_info(dev, "phy[%d]: device %s, driver %s\n",
+				 phy->addr, dev_name(&phy->dev),
+				 phy->drv ? phy->drv->name : "unknown");
+		}
+	}
+
+	return 0;
+
+bail_out:
+	if (data->bus)
+		mdiobus_free(data->bus);
+
+	if (data->clk) {
+		clk_disable(data->clk);
+		clk_put(data->clk);
+	}
+
+	kfree(data);
+
+	return ret;
+}
+
+static int __devexit davinci_mdio_remove(struct platform_device *pdev)
+{
+	struct device *dev = &pdev->dev;
+	struct davinci_mdio_data *data = dev_get_drvdata(dev);
+
+	if (data->bus)
+		mdiobus_free(data->bus);
+
+	if (data->clk) {
+		clk_disable(data->clk);
+		clk_put(data->clk);
+	}
+
+	dev_set_drvdata(dev, NULL);
+
+	kfree(data);
+
+	return 0;
+}
+
+static int davinci_mdio_suspend(struct device *dev)
+{
+	struct davinci_mdio_data *data = dev_get_drvdata(dev);
+	u32 ctrl;
+
+	spin_lock(&data->lock);
+
+	/* shutdown the scan state machine */
+	ctrl = __raw_readl(&data->regs->control);
+	ctrl &= ~CONTROL_ENABLE;
+	__raw_writel(ctrl, &data->regs->control);
+	wait_for_idle(data);
+
+	if (data->clk)
+		clk_disable(data->clk);
+
+	data->suspended = true;
+	spin_unlock(&data->lock);
+
+	return 0;
+}
+
+static int davinci_mdio_resume(struct device *dev)
+{
+	struct davinci_mdio_data *data = dev_get_drvdata(dev);
+	u32 ctrl;
+
+	spin_lock(&data->lock);
+	if (data->clk)
+		clk_enable(data->clk);
+
+	/* restart the scan state machine */
+	ctrl = __raw_readl(&data->regs->control);
+	ctrl |= CONTROL_ENABLE;
+	__raw_writel(ctrl, &data->regs->control);
+
+	data->suspended = false;
+	spin_unlock(&data->lock);
+
+	return 0;
+}
+
+static const struct dev_pm_ops davinci_mdio_pm_ops = {
+	.suspend	= davinci_mdio_suspend,
+	.resume		= davinci_mdio_resume,
+};
+
+static struct platform_driver davinci_mdio_driver = {
+	.driver = {
+		.name	 = "davinci_mdio",
+		.owner	 = THIS_MODULE,
+		.pm	 = &davinci_mdio_pm_ops,
+	},
+	.probe = davinci_mdio_probe,
+	.remove = __devexit_p(davinci_mdio_remove),
+};
+
+static int __init davinci_mdio_init(void)
+{
+	return platform_driver_register(&davinci_mdio_driver);
+}
+device_initcall(davinci_mdio_init);
+
+static void __exit davinci_mdio_exit(void)
+{
+	platform_driver_unregister(&davinci_mdio_driver);
+}
+module_exit(davinci_mdio_exit);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("DaVinci MDIO driver");

+ 13 - 3
include/linux/davinci_emac.h

@@ -14,16 +14,26 @@
 #include <linux/if_ether.h>
 #include <linux/if_ether.h>
 #include <linux/memory.h>
 #include <linux/memory.h>
 
 
+struct mdio_platform_data {
+	unsigned long		bus_freq;
+};
+
 struct emac_platform_data {
 struct emac_platform_data {
 	char mac_addr[ETH_ALEN];
 	char mac_addr[ETH_ALEN];
 	u32 ctrl_reg_offset;
 	u32 ctrl_reg_offset;
 	u32 ctrl_mod_reg_offset;
 	u32 ctrl_mod_reg_offset;
 	u32 ctrl_ram_offset;
 	u32 ctrl_ram_offset;
 	u32 hw_ram_addr;
 	u32 hw_ram_addr;
-	u32 mdio_reg_offset;
 	u32 ctrl_ram_size;
 	u32 ctrl_ram_size;
-	u32 phy_mask;
-	u32 mdio_max_freq;
+
+	/*
+	 * phy_id can be one of the following:
+	 *   - NULL		: use the first phy on the bus,
+	 *   - ""		: force to 100/full, no mdio control
+	 *   - "<bus>:<addr>"	: use the specified bus and phy
+	 */
+	const char *phy_id;
+
 	u8 rmii_en;
 	u8 rmii_en;
 	u8 version;
 	u8 version;
 	void (*interrupt_enable) (void);
 	void (*interrupt_enable) (void);

Some files were not shown because too many files changed in this diff