Merge tag 'mxs-soc-3.9' of git://git.linaro.org/people/shawnguo/linux-2.6 into next/soc

From Shawn Guo:
mxs soc changes for 3.9

 - A couple of optimization on timer
 - Some updates on mxs_defconfig

* tag 'mxs-soc-3.9' of git://git.linaro.org/people/shawnguo/linux-2.6:
  ARM: mxs_defconfig: Select CONFIG_DEVTMPFS_MOUNT
  ARM: mxs: decrease mxs_clockevent_device.min_delta_ns to 2 clock cycles
  ARM: mxs: use apbx bus clock to drive the timers on timrotv2
  ARM: mxs: Update mxs_defconfig
diff --git a/Documentation/device-mapper/dm-raid.txt b/Documentation/device-mapper/dm-raid.txt
index 728c38c..56fb62b 100644
--- a/Documentation/device-mapper/dm-raid.txt
+++ b/Documentation/device-mapper/dm-raid.txt
@@ -141,3 +141,4 @@
 1.2.0	Handle creation of arrays that contain failed devices.
 1.3.0	Added support for RAID 10
 1.3.1	Allow device replacement/rebuild for RAID 10
+1.3.2   Fix/improve redundancy checking for RAID10
diff --git a/Documentation/devicetree/bindings/arm/sirf.txt b/Documentation/devicetree/bindings/arm/sirf.txt
index 1881e1c..c6ba6d3 100644
--- a/Documentation/devicetree/bindings/arm/sirf.txt
+++ b/Documentation/devicetree/bindings/arm/sirf.txt
@@ -1,3 +1,9 @@
-prima2 "cb" evaluation board
+CSR SiRFprimaII and SiRFmarco device tree bindings.
+========================================
+
 Required root node properties:
-    - compatible = "sirf,prima2-cb", "sirf,prima2";
+    - compatible:
+    - "sirf,prima2-cb" : prima2 "cb" evaluation board
+    - "sirf,marco-cb" : marco "cb" evaluation board
+    - "sirf,prima2" : prima2 device based board
+    - "sirf,marco" : marco device based board
diff --git a/Documentation/devicetree/bindings/arm/vt8500.txt b/Documentation/devicetree/bindings/arm/vt8500.txt
index d657832..87dc1dd 100644
--- a/Documentation/devicetree/bindings/arm/vt8500.txt
+++ b/Documentation/devicetree/bindings/arm/vt8500.txt
@@ -12,3 +12,11 @@
 Boards with the Wondermedia WM8650 SoC shall have the following properties:
 Required root node property:
 compatible = "wm,wm8650";
+
+Boards with the Wondermedia WM8750 SoC shall have the following properties:
+Required root node property:
+compatible = "wm,wm8750";
+
+Boards with the Wondermedia WM8850 SoC shall have the following properties:
+Required root node property:
+compatible = "wm,wm8850";
diff --git a/Documentation/devicetree/bindings/clock/imx31-clock.txt b/Documentation/devicetree/bindings/clock/imx31-clock.txt
new file mode 100644
index 0000000..19df842c
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/imx31-clock.txt
@@ -0,0 +1,91 @@
+* Clock bindings for Freescale i.MX31
+
+Required properties:
+- compatible: Should be "fsl,imx31-ccm"
+- reg: Address and length of the register set
+- interrupts: Should contain CCM interrupt
+- #clock-cells: Should be <1>
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell.  The following is a full list of i.MX31
+clocks and IDs.
+
+	Clock		    ID
+	-----------------------
+	dummy	             0
+	ckih                 1
+	ckil                 2
+	mpll                 3
+	spll                 4
+	upll                 5
+	mcu_main             6
+	hsp                  7
+	ahb                  8
+	nfc                  9
+	ipg                  10
+	per_div              11
+	per                  12
+	csi_sel              13
+	fir_sel              14
+	csi_div              15
+	usb_div_pre          16
+	usb_div_post         17
+	fir_div_pre          18
+	fir_div_post         19
+	sdhc1_gate           20
+	sdhc2_gate           21
+	gpt_gate             22
+	epit1_gate           23
+	epit2_gate           24
+	iim_gate             25
+	ata_gate             26
+	sdma_gate            27
+	cspi3_gate           28
+	rng_gate             29
+	uart1_gate           30
+	uart2_gate           31
+	ssi1_gate            32
+	i2c1_gate            33
+	i2c2_gate            34
+	i2c3_gate            35
+	hantro_gate          36
+	mstick1_gate         37
+	mstick2_gate         38
+	csi_gate             39
+	rtc_gate             40
+	wdog_gate            41
+	pwm_gate             42
+	sim_gate             43
+	ect_gate             44
+	usb_gate             45
+	kpp_gate             46
+	ipu_gate             47
+	uart3_gate           48
+	uart4_gate           49
+	uart5_gate           50
+	owire_gate           51
+	ssi2_gate            52
+	cspi1_gate           53
+	cspi2_gate           54
+	gacc_gate            55
+	emi_gate             56
+	rtic_gate            57
+	firi_gate            58
+
+Examples:
+
+clks: ccm@53f80000{
+	compatible = "fsl,imx31-ccm";
+	reg = <0x53f80000 0x4000>;
+	interrupts = <0 31 0x04 0 53 0x04>;
+	#clock-cells = <1>;
+};
+
+uart1: serial@43f90000 {
+	compatible = "fsl,imx31-uart", "fsl,imx21-uart";
+	reg = <0x43f90000 0x4000>;
+	interrupts = <45>;
+	clocks = <&clks 10>, <&clks 30>;
+	clock-names = "ipg", "per";
+	status = "disabled";
+};
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt
new file mode 100644
index 0000000..0921fac
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra20-car.txt
@@ -0,0 +1,205 @@
+NVIDIA Tegra20 Clock And Reset Controller
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
+for muxing and gating Tegra's clocks, and setting their rates.
+
+Required properties :
+- compatible : Should be "nvidia,tegra20-car"
+- reg : Should contain CAR registers location and length
+- clocks : Should contain phandle and clock specifiers for two clocks:
+  the 32 KHz "32k_in", and the board-specific oscillator "osc".
+- #clock-cells : Should be 1.
+  In clock consumers, this cell represents the clock ID exposed by the CAR.
+
+  The first 96 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+  registers. These IDs often match those in the CAR's RST_DEVICES registers,
+  but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+  this case, those clocks are assigned IDs above 95 in order to highlight
+  this issue. Implementations that interpret these clock IDs as bit values
+  within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+  explicitly handle these special cases.
+
+  The balance of the clocks controlled by the CAR are assigned IDs of 96 and
+  above.
+
+  0	cpu
+  1	unassigned
+  2	unassigned
+  3	ac97
+  4	rtc
+  5	tmr
+  6	uart1
+  7	unassigned	(register bit affects uart2 and vfir)
+  8	gpio
+  9	sdmmc2
+  10	unassigned	(register bit affects spdif_in and spdif_out)
+  11	i2s1
+  12	i2c1
+  13	ndflash
+  14	sdmmc1
+  15	sdmmc4
+  16	twc
+  17	pwm
+  18	i2s2
+  19	epp
+  20	unassigned	(register bit affects vi and vi_sensor)
+  21	2d
+  22	usbd
+  23	isp
+  24	3d
+  25	ide
+  26	disp2
+  27	disp1
+  28	host1x
+  29	vcp
+  30	unassigned
+  31	cache2
+
+  32	mem
+  33	ahbdma
+  34	apbdma
+  35	unassigned
+  36	kbc
+  37	stat_mon
+  38	pmc
+  39	fuse
+  40	kfuse
+  41	sbc1
+  42	snor
+  43	spi1
+  44	sbc2
+  45	xio
+  46	sbc3
+  47	dvc
+  48	dsi
+  49	unassigned	(register bit affects tvo and cve)
+  50	mipi
+  51	hdmi
+  52	csi
+  53	tvdac
+  54	i2c2
+  55	uart3
+  56	unassigned
+  57	emc
+  58	usb2
+  59	usb3
+  60	mpe
+  61	vde
+  62	bsea
+  63	bsev
+
+  64	speedo
+  65	uart4
+  66	uart5
+  67	i2c3
+  68	sbc4
+  69	sdmmc3
+  70	pcie
+  71	owr
+  72	afi
+  73	csite
+  74	unassigned
+  75	avpucq
+  76	la
+  77	unassigned
+  78	unassigned
+  79	unassigned
+  80	unassigned
+  81	unassigned
+  82	unassigned
+  83	unassigned
+  84	irama
+  85	iramb
+  86	iramc
+  87	iramd
+  88	cram2
+  89	audio_2x	a/k/a audio_2x_sync_clk
+  90	clk_d
+  91	unassigned
+  92	sus
+  93	cdev1
+  94	cdev2
+  95	unassigned
+
+  96	uart2
+  97	vfir
+  98	spdif_in
+  99	spdif_out
+  100	vi
+  101	vi_sensor
+  102	tvo
+  103	cve
+  104	osc
+  105	clk_32k		a/k/a clk_s
+  106	clk_m
+  107	sclk
+  108	cclk
+  109	hclk
+  110	pclk
+  111	blink
+  112	pll_a
+  113	pll_a_out0
+  114	pll_c
+  115	pll_c_out1
+  116	pll_d
+  117	pll_d_out0
+  118	pll_e
+  119	pll_m
+  120	pll_m_out1
+  121	pll_p
+  122	pll_p_out1
+  123	pll_p_out2
+  124	pll_p_out3
+  125	pll_p_out4
+  126	pll_s
+  127	pll_u
+  128	pll_x
+  129	cop		a/k/a avp
+  130	audio		a/k/a audio_sync_clk
+  131	pll_ref
+  132	twd
+
+Example SoC include file:
+
+/ {
+	tegra_car: clock {
+		compatible = "nvidia,tegra20-car";
+		reg = <0x60006000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	usb@c5004000 {
+		clocks = <&tegra_car 58>; /* usb2 */
+	};
+};
+
+Example board file:
+
+/ {
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc: clock@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <12000000>;
+		};
+
+		clk_32k: clock@1 {
+			compatible = "fixed-clock";
+			reg = <1>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	&tegra_car {
+		clocks = <&clk_32k> <&osc>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt b/Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt
new file mode 100644
index 0000000..f3da3be
--- /dev/null
+++ b/Documentation/devicetree/bindings/clock/nvidia,tegra30-car.txt
@@ -0,0 +1,262 @@
+NVIDIA Tegra30 Clock And Reset Controller
+
+This binding uses the common clock binding:
+Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+The CAR (Clock And Reset) Controller on Tegra is the HW module responsible
+for muxing and gating Tegra's clocks, and setting their rates.
+
+Required properties :
+- compatible : Should be "nvidia,tegra30-car"
+- reg : Should contain CAR registers location and length
+- clocks : Should contain phandle and clock specifiers for two clocks:
+  the 32 KHz "32k_in", and the board-specific oscillator "osc".
+- #clock-cells : Should be 1.
+  In clock consumers, this cell represents the clock ID exposed by the CAR.
+
+  The first 130 clocks are numbered to match the bits in the CAR's CLK_OUT_ENB
+  registers. These IDs often match those in the CAR's RST_DEVICES registers,
+  but not in all cases. Some bits in CLK_OUT_ENB affect multiple clocks. In
+  this case, those clocks are assigned IDs above 160 in order to highlight
+  this issue. Implementations that interpret these clock IDs as bit values
+  within the CLK_OUT_ENB or RST_DEVICES registers should be careful to
+  explicitly handle these special cases.
+
+  The balance of the clocks controlled by the CAR are assigned IDs of 160 and
+  above.
+
+  0	cpu
+  1	unassigned
+  2	unassigned
+  3	unassigned
+  4	rtc
+  5	timer
+  6	uarta
+  7	unassigned	(register bit affects uartb and vfir)
+  8	gpio
+  9	sdmmc2
+  10	unassigned	(register bit affects spdif_in and spdif_out)
+  11	i2s1
+  12	i2c1
+  13	ndflash
+  14	sdmmc1
+  15	sdmmc4
+  16	unassigned
+  17	pwm
+  18	i2s2
+  19	epp
+  20	unassigned	(register bit affects vi and vi_sensor)
+  21	2d
+  22	usbd
+  23	isp
+  24	3d
+  25	unassigned
+  26	disp2
+  27	disp1
+  28	host1x
+  29	vcp
+  30	i2s0
+  31	cop_cache
+
+  32	mc
+  33	ahbdma
+  34	apbdma
+  35	unassigned
+  36	kbc
+  37	statmon
+  38	pmc
+  39	unassigned	(register bit affects fuse and fuse_burn)
+  40	kfuse
+  41	sbc1
+  42	nor
+  43	unassigned
+  44	sbc2
+  45	unassigned
+  46	sbc3
+  47	i2c5
+  48	dsia
+  49	unassigned	(register bit affects cve and tvo)
+  50	mipi
+  51	hdmi
+  52	csi
+  53	tvdac
+  54	i2c2
+  55	uartc
+  56	unassigned
+  57	emc
+  58	usb2
+  59	usb3
+  60	mpe
+  61	vde
+  62	bsea
+  63	bsev
+
+  64	speedo
+  65	uartd
+  66	uarte
+  67	i2c3
+  68	sbc4
+  69	sdmmc3
+  70	pcie
+  71	owr
+  72	afi
+  73	csite
+  74	pciex
+  75	avpucq
+  76	la
+  77	unassigned
+  78	unassigned
+  79	dtv
+  80	ndspeed
+  81	i2cslow
+  82	dsib
+  83	unassigned
+  84	irama
+  85	iramb
+  86	iramc
+  87	iramd
+  88	cram2
+  89	unassigned
+  90	audio_2x	a/k/a audio_2x_sync_clk
+  91	unassigned
+  92	csus
+  93	cdev2
+  94	cdev1
+  95	unassigned
+
+  96	cpu_g
+  97	cpu_lp
+  98	3d2
+  99	mselect
+  100	tsensor
+  101	i2s3
+  102	i2s4
+  103	i2c4
+  104	sbc5
+  105	sbc6
+  106	d_audio
+  107	apbif
+  108	dam0
+  109	dam1
+  110	dam2
+  111	hda2codec_2x
+  112	atomics
+  113	audio0_2x
+  114	audio1_2x
+  115	audio2_2x
+  116	audio3_2x
+  117	audio4_2x
+  118	audio5_2x
+  119	actmon
+  120	extern1
+  121	extern2
+  122	extern3
+  123	sata_oob
+  124	sata
+  125	hda
+  127	se
+  128	hda2hdmi
+  129	sata_cold
+
+  160	uartb
+  161	vfir
+  162	spdif_in
+  163	spdif_out
+  164	vi
+  165	vi_sensor
+  166	fuse
+  167	fuse_burn
+  168	cve
+  169	tvo
+
+  170	clk_32k
+  171	clk_m
+  172	clk_m_div2
+  173	clk_m_div4
+  174	pll_ref
+  175	pll_c
+  176	pll_c_out1
+  177	pll_m
+  178	pll_m_out1
+  179	pll_p
+  180	pll_p_out1
+  181	pll_p_out2
+  182	pll_p_out3
+  183	pll_p_out4
+  184	pll_a
+  185	pll_a_out0
+  186	pll_d
+  187	pll_d_out0
+  188	pll_d2
+  189	pll_d2_out0
+  190	pll_u
+  191	pll_x
+  192	pll_x_out0
+  193	pll_e
+  194	spdif_in_sync
+  195	i2s0_sync
+  196	i2s1_sync
+  197	i2s2_sync
+  198	i2s3_sync
+  199	i2s4_sync
+  200	vimclk
+  201	audio0
+  202	audio1
+  203	audio2
+  204	audio3
+  205	audio4
+  206	audio5
+  207	clk_out_1 (extern1)
+  208	clk_out_2 (extern2)
+  209	clk_out_3 (extern3)
+  210	sclk
+  211	blink
+  212	cclk_g
+  213	cclk_lp
+  214	twd
+  215	cml0
+  216	cml1
+  217	hclk
+  218	pclk
+
+Example SoC include file:
+
+/ {
+	tegra_car: clock {
+		compatible = "nvidia,tegra30-car";
+		reg = <0x60006000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	usb@c5004000 {
+		clocks = <&tegra_car 58>; /* usb2 */
+	};
+};
+
+Example board file:
+
+/ {
+	clocks {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		osc: clock@0 {
+			compatible = "fixed-clock";
+			reg = <0>;
+			#clock-cells = <0>;
+			clock-frequency = <12000000>;
+		};
+
+		clk_32k: clock@1 {
+			compatible = "fixed-clock";
+			reg = <1>;
+			#clock-cells = <0>;
+			clock-frequency = <32768>;
+		};
+	};
+
+	&tegra_car {
+		clocks = <&clk_32k> <&osc>;
+	};
+};
diff --git a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
index 3a26812..bc50899 100644
--- a/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
+++ b/Documentation/devicetree/bindings/pinctrl/atmel,at91-pinctrl.txt
@@ -81,7 +81,8 @@
 Required properties for pin configuration node:
 - atmel,pins: 4 integers array, represents a group of pins mux and config
   setting. The format is atmel,pins = <PIN_BANK PIN_BANK_NUM PERIPH CONFIG>.
-  The PERIPH 0 means gpio.
+  The PERIPH 0 means gpio, PERIPH 1 is periph A, PERIPH 2 is periph B...
+  PIN_BANK 0 is pioA, PIN_BANK 1 is pioB...
 
 Bits used for CONFIG:
 PULL_UP		(1 << 0): indicate this pin need a pull up.
@@ -126,7 +127,7 @@
 		pinctrl_dbgu: dbgu-0 {
 			atmel,pins =
 				<1 14 0x1 0x0	/* PB14 periph A */
-				 1 15 0x1 0x1>;	/* PB15 periph with pullup */
+				 1 15 0x1 0x1>;	/* PB15 periph A with pullup */
 		};
 	};
 };
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
index e9b005d..34c9528 100644
--- a/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-ehci.txt
@@ -11,6 +11,7 @@
  - phy_type : Should be one of "ulpi" or "utmi".
  - nvidia,vbus-gpio : If present, specifies a gpio that needs to be
    activated for the bus to be powered.
+ - nvidia,phy : phandle of the PHY instance, the controller is connected to.
 
 Required properties for phy_type == ulpi:
   - nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
@@ -27,3 +28,5 @@
     registers are accessed through the APB_MISC base address instead of
     the USB controller. Since this is a legacy issue it probably does not
     warrant a compatible string of its own.
+  - nvidia,needs-double-reset : boolean is to be set for some of the Tegra2
+    USB ports, which need reset twice due to hardware issues.
diff --git a/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
new file mode 100644
index 0000000..6bdaba2
--- /dev/null
+++ b/Documentation/devicetree/bindings/usb/nvidia,tegra20-usb-phy.txt
@@ -0,0 +1,17 @@
+Tegra SOC USB PHY
+
+The device node for Tegra SOC USB PHY:
+
+Required properties :
+ - compatible : Should be "nvidia,tegra20-usb-phy".
+ - reg : Address and length of the register set for the USB PHY interface.
+ - phy_type : Should be one of "ulpi" or "utmi".
+
+Required properties for phy_type == ulpi:
+  - nvidia,phy-reset-gpio : The GPIO used to reset the PHY.
+
+Optional properties:
+  - nvidia,has-legacy-mode : boolean indicates whether this controller can
+    operate in legacy mode (as APX 2500 / 2600). In legacy mode some
+    registers are accessed through the APB_MISC base address instead of
+    the USB controller.
\ No newline at end of file
diff --git a/Documentation/filesystems/f2fs.txt b/Documentation/filesystems/f2fs.txt
index 8fbd8b4..dcf338e 100644
--- a/Documentation/filesystems/f2fs.txt
+++ b/Documentation/filesystems/f2fs.txt
@@ -175,9 +175,9 @@
                                             align with the zone size <-|
                  |-> align with the segment size
      _________________________________________________________________________
-    |            |            |    Node     |   Segment   |   Segment  |      |
-    | Superblock | Checkpoint |   Address   |    Info.    |   Summary  | Main |
-    |    (SB)    |   (CP)     | Table (NAT) | Table (SIT) | Area (SSA) |      |
+    |            |            |   Segment   |    Node     |   Segment  |      |
+    | Superblock | Checkpoint |    Info.    |   Address   |   Summary  | Main |
+    |    (SB)    |   (CP)     | Table (SIT) | Table (NAT) | Area (SSA) |      |
     |____________|_____2______|______N______|______N______|______N_____|__N___|
                                                                        .      .
                                                              .                .
@@ -200,14 +200,14 @@
  : It contains file system information, bitmaps for valid NAT/SIT sets, orphan
    inode lists, and summary entries of current active segments.
 
-- Node Address Table (NAT)
- : It is composed of a block address table for all the node blocks stored in
-   Main area.
-
 - Segment Information Table (SIT)
  : It contains segment information such as valid block count and bitmap for the
    validity of all the blocks.
 
+- Node Address Table (NAT)
+ : It is composed of a block address table for all the node blocks stored in
+   Main area.
+
 - Segment Summary Area (SSA)
  : It contains summary entries which contains the owner information of all the
    data and node blocks stored in Main area.
@@ -236,13 +236,13 @@
 valid, as shown as below.
 
   +--------+----------+---------+
-  |   CP   |    NAT   |   SIT   |
+  |   CP   |    SIT   |   NAT   |
   +--------+----------+---------+
   .         .          .          .
   .            .              .              .
   .               .                 .                 .
   +-------+-------+--------+--------+--------+--------+
-  | CP #0 | CP #1 | NAT #0 | NAT #1 | SIT #0 | SIT #1 |
+  | CP #0 | CP #1 | SIT #0 | SIT #1 | NAT #0 | NAT #1 |
   +-------+-------+--------+--------+--------+--------+
      |             ^                          ^
      |             |                          |
diff --git a/Documentation/hid/hid-sensor.txt b/Documentation/hid/hid-sensor.txt
old mode 100755
new mode 100644
diff --git a/Documentation/x86/boot.txt b/Documentation/x86/boot.txt
index 406d82d..3edb4c2 100644
--- a/Documentation/x86/boot.txt
+++ b/Documentation/x86/boot.txt
@@ -57,6 +57,10 @@
 Protocol 2.11:	(Kernel 3.6) Added a field for offset of EFI handover
 		protocol entry point.
 
+Protocol 2.12:	(Kernel 3.9) Added the xloadflags field and extension fields
+	 	to struct boot_params for for loading bzImage and ramdisk
+		above 4G in 64bit.
+
 **** MEMORY LAYOUT
 
 The traditional memory map for the kernel loader, used for Image or
@@ -182,7 +186,7 @@
 0230/4	2.05+	kernel_alignment Physical addr alignment required for kernel
 0234/1	2.05+	relocatable_kernel Whether kernel is relocatable or not
 0235/1	2.10+	min_alignment	Minimum alignment, as a power of two
-0236/2	N/A	pad3		Unused
+0236/2	2.12+	xloadflags	Boot protocol option flags
 0238/4	2.06+	cmdline_size	Maximum size of the kernel command line
 023C/4	2.07+	hardware_subarch Hardware subarchitecture
 0240/8	2.07+	hardware_subarch_data Subarchitecture-specific data
@@ -582,6 +586,27 @@
   misaligned kernel.  Therefore, a loader should typically try each
   power-of-two alignment from kernel_alignment down to this alignment.
 
+Field name:     xloadflags
+Type:           read
+Offset/size:    0x236/2
+Protocol:       2.12+
+
+  This field is a bitmask.
+
+  Bit 0 (read):	XLF_KERNEL_64
+	- If 1, this kernel has the legacy 64-bit entry point at 0x200.
+
+  Bit 1 (read): XLF_CAN_BE_LOADED_ABOVE_4G
+        - If 1, kernel/boot_params/cmdline/ramdisk can be above 4G.
+
+  Bit 2 (read):	XLF_EFI_HANDOVER_32
+	- If 1, the kernel supports the 32-bit EFI handoff entry point
+          given at handover_offset.
+
+  Bit 3 (read): XLF_EFI_HANDOVER_64
+	- If 1, the kernel supports the 64-bit EFI handoff entry point
+          given at handover_offset + 0x200.
+
 Field name:	cmdline_size
 Type:		read
 Offset/size:	0x238/4
diff --git a/Documentation/x86/zero-page.txt b/Documentation/x86/zero-page.txt
index cf5437d..199f453 100644
--- a/Documentation/x86/zero-page.txt
+++ b/Documentation/x86/zero-page.txt
@@ -19,6 +19,9 @@
 090/010	ALL	hd1_info	hd1 disk parameter, OBSOLETE!!
 0A0/010	ALL	sys_desc_table	System description table (struct sys_desc_table)
 0B0/010	ALL	olpc_ofw_header	OLPC's OpenFirmware CIF and friends
+0C0/004	ALL	ext_ramdisk_image ramdisk_image high 32bits
+0C4/004	ALL	ext_ramdisk_size  ramdisk_size high 32bits
+0C8/004	ALL	ext_cmd_line_ptr  cmd_line_ptr high 32bits
 140/080	ALL	edid_info	Video mode setup (struct edid_info)
 1C0/020	ALL	efi_info	EFI 32 information (struct efi_info)
 1E0/004	ALL	alk_mem_k	Alternative mem check, in KB
@@ -27,6 +30,7 @@
 1E9/001	ALL	eddbuf_entries	Number of entries in eddbuf (below)
 1EA/001	ALL	edd_mbr_sig_buf_entries	Number of entries in edd_mbr_sig_buffer
 				(below)
+1EF/001	ALL	sentinel	Used to detect broken bootloaders
 290/040	ALL	edd_mbr_sig_buffer EDD MBR signatures
 2D0/A00	ALL	e820_map	E820 memory map table
 				(array of struct e820entry)
diff --git a/MAINTAINERS b/MAINTAINERS
index 915564e..43dbae1 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -228,7 +228,7 @@
 F:	drivers/platform/x86/acerhdf.c
 
 ACER WMI LAPTOP EXTRAS
-M:	Joey Lee <jlee@novell.com>
+M:	"Lee, Chun-Yi" <jlee@suse.com>
 L:	platform-driver-x86@vger.kernel.org
 S:	Maintained
 F:	drivers/platform/x86/acer-wmi.c
@@ -648,7 +648,7 @@
 
 ARM SUB-ARCHITECTURES
 L:	linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
-S:	MAINTAINED
+S:	Maintained
 F:	arch/arm/mach-*/
 F:	arch/arm/plat-*/
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc.git
@@ -1351,6 +1351,14 @@
 S:	Supported
 F:	drivers/net/wireless/ath/ath9k/
 
+WILOCITY WIL6210 WIRELESS DRIVER
+M:	Vladimir Kondratiev <qca_vkondrat@qca.qualcomm.com>
+L:	linux-wireless@vger.kernel.org
+L:	wil6210@qca.qualcomm.com
+S:	Supported
+W:	http://wireless.kernel.org/en/users/Drivers/wil6210
+F:	drivers/net/wireless/ath/wil6210/
+
 CARL9170 LINUX COMMUNITY WIRELESS DRIVER
 M:	Christian Lamparter <chunkeey@googlemail.com>
 L:	linux-wireless@vger.kernel.org
@@ -1964,9 +1972,9 @@
 F:	drivers/usb/host/ohci-ep93xx.c
 
 CIRRUS LOGIC CS4270 SOUND DRIVER
-M:	Timur Tabi <timur@freescale.com>
+M:	Timur Tabi <timur@tabi.org>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
-S:	Supported
+S:	Odd Fixes
 F:	sound/soc/codecs/cs4270*
 
 CLEANCACHE API
@@ -2958,7 +2966,7 @@
 F:	drivers/net/ethernet/i825xx/eexpress.*
 
 ETHERNET BRIDGE
-M:	Stephen Hemminger <shemminger@vyatta.com>
+M:	Stephen Hemminger <stephen@networkplumber.org>
 L:	bridge@lists.linux-foundation.org
 L:	netdev@vger.kernel.org
 W:	http://www.linuxfoundation.org/en/Net:Bridge
@@ -3183,9 +3191,9 @@
 F:	include/uapi/linux/fb.h
 
 FREESCALE DIU FRAMEBUFFER DRIVER
-M:	Timur Tabi <timur@freescale.com>
+M:	Timur Tabi <timur@tabi.org>
 L:	linux-fbdev@vger.kernel.org
-S:	Supported
+S:	Maintained
 F:	drivers/video/fsl-diu-fb.*
 
 FREESCALE DMA DRIVER
@@ -3220,9 +3228,8 @@
 F:	include/linux/fs_enet_pd.h
 
 FREESCALE QUICC ENGINE LIBRARY
-M:	Timur Tabi <timur@freescale.com>
 L:	linuxppc-dev@lists.ozlabs.org
-S:	Supported
+S:	Orphan
 F:	arch/powerpc/sysdev/qe_lib/
 F:	arch/powerpc/include/asm/*qe.h
 
@@ -3241,16 +3248,16 @@
 F:	drivers/net/ethernet/freescale/ucc_geth*
 
 FREESCALE QUICC ENGINE UCC UART DRIVER
-M:	Timur Tabi <timur@freescale.com>
+M:	Timur Tabi <timur@tabi.org>
 L:	linuxppc-dev@lists.ozlabs.org
-S:	Supported
+S:	Maintained
 F:	drivers/tty/serial/ucc_uart.c
 
 FREESCALE SOC SOUND DRIVERS
-M:	Timur Tabi <timur@freescale.com>
+M:	Timur Tabi <timur@tabi.org>
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:	linuxppc-dev@lists.ozlabs.org
-S:	Supported
+S:	Maintained
 F:	sound/soc/fsl/fsl*
 F:	sound/soc/fsl/mpc8610_hpcd.c
 
@@ -4209,6 +4216,7 @@
 S:	Maintained
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git irq/core
 F:	kernel/irq/
+F:	drivers/irqchip/
 
 IRQ DOMAINS (IRQ NUMBER MAPPING LIBRARY)
 M:	Benjamin Herrenschmidt <benh@kernel.crashing.org>
@@ -4898,7 +4906,7 @@
 
 MARVELL GIGABIT ETHERNET DRIVERS (skge/sky2)
 M:	Mirko Lindner <mlindner@marvell.com>
-M:	Stephen Hemminger <shemminger@vyatta.com>
+M:	Stephen Hemminger <stephen@networkplumber.org>
 L:	netdev@vger.kernel.org
 S:	Maintained
 F:	drivers/net/ethernet/marvell/sk*
@@ -5077,7 +5085,7 @@
 F:	drivers/media/radio/radio-mr800.c
 
 MSI LAPTOP SUPPORT
-M:	"Lee, Chun-Yi" <jlee@novell.com>
+M:	"Lee, Chun-Yi" <jlee@suse.com>
 L:	platform-driver-x86@vger.kernel.org
 S:	Maintained
 F:	drivers/platform/x86/msi-laptop.c
@@ -5173,7 +5181,7 @@
 F:	drivers/infiniband/hw/nes/
 
 NETEM NETWORK EMULATOR
-M:	Stephen Hemminger <shemminger@vyatta.com>
+M:	Stephen Hemminger <stephen@networkplumber.org>
 L:	netem@lists.linux-foundation.org
 S:	Maintained
 F:	net/sched/sch_netem.c
@@ -5507,8 +5515,7 @@
 M:	Paul Walmsley <paul@pwsan.com>
 L:	linux-omap@vger.kernel.org
 S:	Maintained
-F:	arch/arm/mach-omap2/omap_hwmod.c
-F:	arch/arm/plat-omap/include/plat/omap_hwmod.h
+F:	arch/arm/mach-omap2/omap_hwmod.*
 
 OMAP HWMOD DATA FOR OMAP4-BASED DEVICES
 M:	Benoît Cousson <b-cousson@ti.com>
@@ -6579,7 +6586,7 @@
 F:	include/media/s3c_camif.h
 
 SERIAL DRIVERS
-M:	Alan Cox <alan@linux.intel.com>
+M:	Greg Kroah-Hartman <gregkh@linuxfoundation.org>
 L:	linux-serial@vger.kernel.org
 S:	Maintained
 F:	drivers/tty/serial
@@ -7082,7 +7089,7 @@
 F:	sound/
 
 SOUND - SOC LAYER / DYNAMIC AUDIO POWER MANAGEMENT (ASoC)
-M:	Liam Girdwood <lrg@ti.com>
+M:	Liam Girdwood <lgirdwood@gmail.com>
 M:	Mark Brown <broonie@opensource.wolfsonmicro.com>
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound.git
 L:	alsa-devel@alsa-project.org (moderated for non-subscribers)
@@ -7334,7 +7341,7 @@
 F:	drivers/staging/speakup/
 
 STAGING - TI DSP BRIDGE DRIVERS
-M:	Omar Ramirez Luna <omar.ramirez@ti.com>
+M:	Omar Ramirez Luna <omar.ramirez@copitl.com>
 S:	Odd Fixes
 F:	drivers/staging/tidspbridge/
 
@@ -8526,7 +8533,7 @@
 F:	arch/x86/
 
 X86 PLATFORM DRIVERS
-M:	Matthew Garrett <mjg@redhat.com>
+M:	Matthew Garrett <matthew.garrett@nebula.com>
 L:	platform-driver-x86@vger.kernel.org
 T:	git git://git.kernel.org/pub/scm/linux/kernel/git/mjg59/platform-drivers-x86.git
 S:	Maintained
diff --git a/Makefile b/Makefile
index a1667c4..54dfde5 100644
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 3
 PATCHLEVEL = 8
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
-NAME = Terrified Chipmunk
+EXTRAVERSION = -rc6
+NAME = Unicycling Gorilla
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
@@ -169,7 +169,7 @@
 				  -e s/arm.*/arm/ -e s/sa110/arm/ \
 				  -e s/s390x/s390/ -e s/parisc64/parisc/ \
 				  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-				  -e s/sh[234].*/sh/ )
+				  -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
 
 # Cross compiling and selecting different set of gcc/bin-utils
 # ---------------------------------------------------------------------------
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index 67874b8..2ec4ff3 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -393,6 +393,7 @@
 config ARCH_SIRF
 	bool "CSR SiRF"
 	select ARCH_REQUIRE_GPIOLIB
+	select AUTO_ZRELADDR
 	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_IRQ_CHIP
@@ -640,8 +641,10 @@
 config ARCH_TEGRA
 	bool "NVIDIA Tegra"
 	select ARCH_HAS_CPUFREQ
+	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
 	select CLKSRC_MMIO
+	select CLKSRC_OF
 	select COMMON_CLK
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_GPIO
@@ -949,22 +952,6 @@
 	help
 	  Support for TI's OMAP platform (OMAP1/2/3/4).
 
-config ARCH_VT8500_SINGLE
-	bool "VIA/WonderMedia 85xx"
-	select ARCH_HAS_CPUFREQ
-	select ARCH_REQUIRE_GPIOLIB
-	select CLKDEV_LOOKUP
-	select COMMON_CLK
-	select CPU_ARM926T
-	select GENERIC_CLOCKEVENTS
-	select GENERIC_GPIO
-	select HAVE_CLK
-	select MULTI_IRQ_HANDLER
-	select SPARSE_IRQ
-	select USE_OF
-	help
-	  Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
-
 endchoice
 
 menu "Multiple platform selection"
diff --git a/arch/arm/Kconfig.debug b/arch/arm/Kconfig.debug
index 661030d..305ceb8 100644
--- a/arch/arm/Kconfig.debug
+++ b/arch/arm/Kconfig.debug
@@ -205,12 +205,19 @@
 		  Say Y here if you want kernel low-level debugging support
 		  on i.MX28.
 
-	config DEBUG_IMX31_IMX35_UART
-		bool "i.MX31 and i.MX35 Debug UART"
-		depends on SOC_IMX31 || SOC_IMX35
+	config DEBUG_IMX31_UART
+		bool "i.MX31 Debug UART"
+		depends on SOC_IMX31
 		help
 		  Say Y here if you want kernel low-level debugging support
-		  on i.MX31 or i.MX35.
+		  on i.MX31.
+
+	config DEBUG_IMX35_UART
+		bool "i.MX35 Debug UART"
+		depends on SOC_IMX35
+		help
+		  Say Y here if you want kernel low-level debugging support
+		  on i.MX35.
 
 	config DEBUG_IMX51_UART
 		bool "i.MX51 Debug UART"
@@ -219,12 +226,12 @@
 		  Say Y here if you want kernel low-level debugging support
 		  on i.MX51.
 
-	config DEBUG_IMX50_IMX53_UART
-		bool "i.MX50 and i.MX53 Debug UART"
-		depends on SOC_IMX50 || SOC_IMX53
+	config DEBUG_IMX53_UART
+		bool "i.MX53 Debug UART"
+		depends on SOC_IMX53
 		help
 		  Say Y here if you want kernel low-level debugging support
-		  on i.MX50 or i.MX53.
+		  on i.MX53.
 
 	config DEBUG_IMX6Q_UART
 		bool "i.MX6Q Debug UART"
@@ -386,6 +393,20 @@
 		  Say Y here if you want kernel low-level debugging support
 		  on Tegra based platforms.
 
+	config DEBUG_SIRFPRIMA2_UART1
+		bool "Kernel low-level debugging messages via SiRFprimaII UART1"
+		depends on ARCH_PRIMA2
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the uart1 port on SiRFprimaII devices.
+
+	config DEBUG_SIRFMARCO_UART1
+		bool "Kernel low-level debugging messages via SiRFmarco UART1"
+		depends on ARCH_MARCO
+		help
+		  Say Y here if you want the debug print routines to direct
+		  their output to the uart1 port on SiRFmarco devices.
+
 	config DEBUG_VEXPRESS_UART0_DETECT
 		bool "Autodetect UART0 on Versatile Express Cortex-A core tiles"
 		depends on ARCH_VEXPRESS && CPU_CP15_MMU
@@ -412,6 +433,13 @@
 		  of the tiles using the RS1 memory map, including all new A-class
 		  core tiles, FPGA-based SMMs and software models.
 
+	config DEBUG_VT8500_UART0
+		bool "Use UART0 on VIA/Wondermedia SoCs"
+		depends on ARCH_VT8500
+		help
+		  This option selects UART0 on VIA/Wondermedia System-on-a-chip
+		  devices, including VT8500, WM8505, WM8650 and WM8850.
+
 	config DEBUG_LL_UART_NONE
 		bool "No low-level debugging UART"
 		depends on !ARCH_MULTIPLATFORM
@@ -450,11 +478,16 @@
 
 endchoice
 
-config DEBUG_IMX6Q_UART_PORT
-	int "i.MX6Q Debug UART Port (1-5)" if DEBUG_IMX6Q_UART
-	range 1 5
+config DEBUG_IMX_UART_PORT
+	int "i.MX Debug UART Port Selection" if DEBUG_IMX1_UART || \
+						DEBUG_IMX25_UART || \
+						DEBUG_IMX21_IMX27_UART || \
+						DEBUG_IMX31_UART || \
+						DEBUG_IMX35_UART || \
+						DEBUG_IMX51_UART || \
+						DEBUG_IMX50_IMX53_UART || \
+						DEBUG_IMX6Q_UART
 	default 1
-	depends on SOC_IMX6Q
 	help
 	  Choose UART port on which kernel low-level debug messages
 	  should be output.
@@ -495,9 +528,10 @@
 	default "debug/imx.S" if DEBUG_IMX1_UART || \
 				 DEBUG_IMX25_UART || \
 				 DEBUG_IMX21_IMX27_UART || \
-				 DEBUG_IMX31_IMX35_UART || \
+				 DEBUG_IMX31_UART || \
+				 DEBUG_IMX35_UART || \
 				 DEBUG_IMX51_UART || \
-				 DEBUG_IMX50_IMX53_UART ||\
+				 DEBUG_IMX53_UART ||\
 				 DEBUG_IMX6Q_UART
 	default "debug/highbank.S" if DEBUG_HIGHBANK_UART
 	default "debug/mvebu.S" if DEBUG_MVEBU_UART
@@ -506,6 +540,7 @@
 	default "debug/sunxi.S" if DEBUG_SUNXI_UART0 || DEBUG_SUNXI_UART1
 	default "debug/vexpress.S" if DEBUG_VEXPRESS_UART0_DETECT || \
 		DEBUG_VEXPRESS_UART0_CA9 || DEBUG_VEXPRESS_UART0_RS1
+	default "debug/vt8500.S" if DEBUG_VT8500_UART0
 	default "debug/tegra.S" if DEBUG_TEGRA_UART
 	default "debug/zynq.S" if DEBUG_ZYNQ_UART0 || DEBUG_ZYNQ_UART1
 	default "mach/debug-macro.S"
diff --git a/arch/arm/boot/dts/Makefile b/arch/arm/boot/dts/Makefile
index e44da40..2e7a7e2 100644
--- a/arch/arm/boot/dts/Makefile
+++ b/arch/arm/boot/dts/Makefile
@@ -73,6 +73,7 @@
 	kirkwood-ts219-6281.dtb \
 	kirkwood-ts219-6282.dtb \
 	kirkwood-openblocks_a6.dtb
+dtb-$(CONFIG_ARCH_MARCO) += marco-evb.dtb
 dtb-$(CONFIG_ARCH_MSM) += msm8660-surf.dtb \
 	msm8960-cdp.dtb
 dtb-$(CONFIG_ARCH_MVEBU) += armada-370-db.dtb \
@@ -143,7 +144,9 @@
 	tegra20-ventana.dtb \
 	tegra20-whistler.dtb \
 	tegra30-cardhu-a02.dtb \
-	tegra30-cardhu-a04.dtb
+	tegra30-cardhu-a04.dtb \
+	tegra114-dalmore.dtb \
+	tegra114-pluto.dtb
 dtb-$(CONFIG_ARCH_VEXPRESS) += vexpress-v2p-ca5s.dtb \
 	vexpress-v2p-ca9.dtb \
 	vexpress-v2p-ca15-tc1.dtb \
@@ -151,10 +154,12 @@
 	xenvm-4.2.dtb
 dtb-$(CONFIG_ARCH_VT8500) += vt8500-bv07.dtb \
 	wm8505-ref.dtb \
-	wm8650-mid.dtb
+	wm8650-mid.dtb \
+	wm8850-w70v2.dtb
 dtb-$(CONFIG_ARCH_ZYNQ) += zynq-zc702.dtb
 
 targets += dtbs
+targets += $(dtb-y)
 endif
 
 # *.dtb used to be generated in the directory above. Clean out the
diff --git a/arch/arm/boot/dts/armada-370-db.dts b/arch/arm/boot/dts/armada-370-db.dts
index 0004402..9b82fac 100644
--- a/arch/arm/boot/dts/armada-370-db.dts
+++ b/arch/arm/boot/dts/armada-370-db.dts
@@ -26,7 +26,7 @@
 
 	memory {
 		device_type = "memory";
-		reg = <0x00000000 0x20000000>; /* 512 MB */
+		reg = <0x00000000 0x40000000>; /* 1 GB */
 	};
 
 	soc {
diff --git a/arch/arm/boot/dts/armada-xp-mv78230.dtsi b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
index 271855a..e041f42 100644
--- a/arch/arm/boot/dts/armada-xp-mv78230.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78230.dtsi
@@ -50,27 +50,25 @@
 		};
 
 		gpio0: gpio@d0018100 {
-			compatible = "marvell,armadaxp-gpio";
-			reg = <0xd0018100 0x40>,
-			    <0xd0018800 0x30>;
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018100 0x40>;
 			ngpios = <32>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupts-cells = <2>;
-			interrupts = <16>, <17>, <18>, <19>;
+			interrupts = <82>, <83>, <84>, <85>;
 		};
 
 		gpio1: gpio@d0018140 {
-			compatible = "marvell,armadaxp-gpio";
-			reg = <0xd0018140 0x40>,
-			    <0xd0018840 0x30>;
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018140 0x40>;
 			ngpios = <17>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupts-cells = <2>;
-			interrupts = <20>, <21>, <22>;
+			interrupts = <87>, <88>, <89>;
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/armada-xp-mv78260.dtsi b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
index 1c1937d..9e23bd8 100644
--- a/arch/arm/boot/dts/armada-xp-mv78260.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78260.dtsi
@@ -51,39 +51,36 @@
 		};
 
 		gpio0: gpio@d0018100 {
-			compatible = "marvell,armadaxp-gpio";
-			reg = <0xd0018100 0x40>,
-			    <0xd0018800 0x30>;
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018100 0x40>;
 			ngpios = <32>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupts-cells = <2>;
-			interrupts = <16>, <17>, <18>, <19>;
+			interrupts = <82>, <83>, <84>, <85>;
 		};
 
 		gpio1: gpio@d0018140 {
-			compatible = "marvell,armadaxp-gpio";
-			reg = <0xd0018140 0x40>,
-			    <0xd0018840 0x30>;
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018140 0x40>;
 			ngpios = <32>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupts-cells = <2>;
-			interrupts = <20>, <21>, <22>, <23>;
+			interrupts = <87>, <88>, <89>, <90>;
 		};
 
 		gpio2: gpio@d0018180 {
-			compatible = "marvell,armadaxp-gpio";
-			reg = <0xd0018180 0x40>,
-			    <0xd0018870 0x30>;
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018180 0x40>;
 			ngpios = <3>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupts-cells = <2>;
-			interrupts = <24>;
+			interrupts = <91>;
 		};
 
 		ethernet@d0034000 {
diff --git a/arch/arm/boot/dts/armada-xp-mv78460.dtsi b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
index 4905cf3..9659661 100644
--- a/arch/arm/boot/dts/armada-xp-mv78460.dtsi
+++ b/arch/arm/boot/dts/armada-xp-mv78460.dtsi
@@ -66,39 +66,36 @@
 		};
 
 		gpio0: gpio@d0018100 {
-			compatible = "marvell,armadaxp-gpio";
-			reg = <0xd0018100 0x40>,
-			    <0xd0018800 0x30>;
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018100 0x40>;
 			ngpios = <32>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupts-cells = <2>;
-			interrupts = <16>, <17>, <18>, <19>;
+			interrupts = <82>, <83>, <84>, <85>;
 		};
 
 		gpio1: gpio@d0018140 {
-			compatible = "marvell,armadaxp-gpio";
-			reg = <0xd0018140 0x40>,
-			    <0xd0018840 0x30>;
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018140 0x40>;
 			ngpios = <32>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupts-cells = <2>;
-			interrupts = <20>, <21>, <22>, <23>;
+			interrupts = <87>, <88>, <89>, <90>;
 		};
 
 		gpio2: gpio@d0018180 {
-			compatible = "marvell,armadaxp-gpio";
-			reg = <0xd0018180 0x40>,
-			    <0xd0018870 0x30>;
+			compatible = "marvell,orion-gpio";
+			reg = <0xd0018180 0x40>;
 			ngpios = <3>;
 			gpio-controller;
 			#gpio-cells = <2>;
 			interrupt-controller;
 			#interrupts-cells = <2>;
-			interrupts = <24>;
+			interrupts = <91>;
 		};
 
 		ethernet@d0034000 {
diff --git a/arch/arm/boot/dts/at91rm9200.dtsi b/arch/arm/boot/dts/at91rm9200.dtsi
index e154f24..222047f 100644
--- a/arch/arm/boot/dts/at91rm9200.dtsi
+++ b/arch/arm/boot/dts/at91rm9200.dtsi
@@ -336,8 +336,8 @@
 
 	i2c@0 {
 		compatible = "i2c-gpio";
-		gpios = <&pioA 23 0 /* sda */
-			 &pioA 24 0 /* scl */
+		gpios = <&pioA 25 0 /* sda */
+			 &pioA 26 0 /* scl */
 			>;
 		i2c-gpio,sda-open-drain;
 		i2c-gpio,scl-open-drain;
diff --git a/arch/arm/boot/dts/at91sam9260.dtsi b/arch/arm/boot/dts/at91sam9260.dtsi
index 68bccf4..cb7bcc5 100644
--- a/arch/arm/boot/dts/at91sam9260.dtsi
+++ b/arch/arm/boot/dts/at91sam9260.dtsi
@@ -306,6 +306,22 @@
 					};
 				};
 
+				ssc0 {
+					pinctrl_ssc0_tx: ssc0_tx-0 {
+						atmel,pins =
+							<1 16 0x1 0x0	/* PB16 periph A */
+							 1 17 0x1 0x0	/* PB17 periph A */
+							 1 18 0x1 0x0>;	/* PB18 periph A */
+					};
+
+					pinctrl_ssc0_rx: ssc0_rx-0 {
+						atmel,pins =
+							<1 19 0x1 0x0	/* PB19 periph A */
+							 1 20 0x1 0x0	/* PB20 periph A */
+							 1 21 0x1 0x0>;	/* PB21 periph A */
+					};
+				};
+
 				pioA: gpio@fffff400 {
 					compatible = "atmel,at91rm9200-gpio";
 					reg = <0xfffff400 0x200>;
@@ -450,6 +466,8 @@
 				compatible = "atmel,at91rm9200-ssc";
 				reg = <0xfffbc000 0x4000>;
 				interrupts = <14 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
 				status = "disabled";
 			};
 
diff --git a/arch/arm/boot/dts/at91sam9263.dtsi b/arch/arm/boot/dts/at91sam9263.dtsi
index 32ec62c..271d4de 100644
--- a/arch/arm/boot/dts/at91sam9263.dtsi
+++ b/arch/arm/boot/dts/at91sam9263.dtsi
@@ -271,6 +271,38 @@
 					};
 				};
 
+				ssc0 {
+					pinctrl_ssc0_tx: ssc0_tx-0 {
+						atmel,pins =
+							<1 0 0x2 0x0	/* PB0 periph B */
+							 1 1 0x2 0x0	/* PB1 periph B */
+							 1 2 0x2 0x0>;	/* PB2 periph B */
+					};
+
+					pinctrl_ssc0_rx: ssc0_rx-0 {
+						atmel,pins =
+							<1 3 0x2 0x0	/* PB3 periph B */
+							 1 4 0x2 0x0	/* PB4 periph B */
+							 1 5 0x2 0x0>;	/* PB5 periph B */
+					};
+				};
+
+				ssc1 {
+					pinctrl_ssc1_tx: ssc1_tx-0 {
+						atmel,pins =
+							<1 6 0x1 0x0	/* PB6 periph A */
+							 1 7 0x1 0x0	/* PB7 periph A */
+							 1 8 0x1 0x0>;	/* PB8 periph A */
+					};
+
+					pinctrl_ssc1_rx: ssc1_rx-0 {
+						atmel,pins =
+							<1 9 0x1 0x0	/* PB9 periph A */
+							 1 10 0x1 0x0	/* PB10 periph A */
+							 1 11 0x1 0x0>;	/* PB11 periph A */
+					};
+				};
+
 				pioA: gpio@fffff200 {
 					compatible = "atmel,at91rm9200-gpio";
 					reg = <0xfffff200 0x200>;
@@ -368,6 +400,8 @@
 				compatible = "atmel,at91rm9200-ssc";
 				reg = <0xfff98000 0x4000>;
 				interrupts = <16 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
 				status = "disabled";
 			};
 
@@ -375,6 +409,8 @@
 				compatible = "atmel,at91rm9200-ssc";
 				reg = <0xfff9c000 0x4000>;
 				interrupts = <17 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
 				status = "disabled";
 			};
 
diff --git a/arch/arm/boot/dts/at91sam9g45.dtsi b/arch/arm/boot/dts/at91sam9g45.dtsi
index 231858f..6b1d4ca 100644
--- a/arch/arm/boot/dts/at91sam9g45.dtsi
+++ b/arch/arm/boot/dts/at91sam9g45.dtsi
@@ -290,6 +290,38 @@
 					};
 				};
 
+				ssc0 {
+					pinctrl_ssc0_tx: ssc0_tx-0 {
+						atmel,pins =
+							<3 0 0x1 0x0	/* PD0 periph A */
+							 3 1 0x1 0x0	/* PD1 periph A */
+							 3 2 0x1 0x0>;	/* PD2 periph A */
+					};
+
+					pinctrl_ssc0_rx: ssc0_rx-0 {
+						atmel,pins =
+							<3 3 0x1 0x0	/* PD3 periph A */
+							 3 4 0x1 0x0	/* PD4 periph A */
+							 3 5 0x1 0x0>;	/* PD5 periph A */
+					};
+				};
+
+				ssc1 {
+					pinctrl_ssc1_tx: ssc1_tx-0 {
+						atmel,pins =
+							<3 10 0x1 0x0	/* PD10 periph A */
+							 3 11 0x1 0x0	/* PD11 periph A */
+							 3 12 0x1 0x0>;	/* PD12 periph A */
+					};
+
+					pinctrl_ssc1_rx: ssc1_rx-0 {
+						atmel,pins =
+							<3 13 0x1 0x0	/* PD13 periph A */
+							 3 14 0x1 0x0	/* PD14 periph A */
+							 3 15 0x1 0x0>;	/* PD15 periph A */
+					};
+				};
+
 				pioA: gpio@fffff200 {
 					compatible = "atmel,at91rm9200-gpio";
 					reg = <0xfffff200 0x200>;
@@ -425,6 +457,8 @@
 				compatible = "atmel,at91sam9g45-ssc";
 				reg = <0xfff9c000 0x4000>;
 				interrupts = <16 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
 				status = "disabled";
 			};
 
@@ -432,6 +466,8 @@
 				compatible = "atmel,at91sam9g45-ssc";
 				reg = <0xfffa0000 0x4000>;
 				interrupts = <17 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_ssc1_tx &pinctrl_ssc1_rx>;
 				status = "disabled";
 			};
 
diff --git a/arch/arm/boot/dts/at91sam9n12.dtsi b/arch/arm/boot/dts/at91sam9n12.dtsi
index e9efb34..80e29c6 100644
--- a/arch/arm/boot/dts/at91sam9n12.dtsi
+++ b/arch/arm/boot/dts/at91sam9n12.dtsi
@@ -28,6 +28,7 @@
 		tcb1 = &tcb1;
 		i2c0 = &i2c0;
 		i2c1 = &i2c1;
+		ssc0 = &ssc0;
 	};
 	cpus {
 		cpu@0 {
@@ -244,6 +245,22 @@
 					};
 				};
 
+				ssc0 {
+					pinctrl_ssc0_tx: ssc0_tx-0 {
+						atmel,pins =
+							<0 24 0x2 0x0	/* PA24 periph B */
+							 0 25 0x2 0x0	/* PA25 periph B */
+							 0 26 0x2 0x0>;	/* PA26 periph B */
+					};
+
+					pinctrl_ssc0_rx: ssc0_rx-0 {
+						atmel,pins =
+							<0 27 0x2 0x0	/* PA27 periph B */
+							 0 28 0x2 0x0	/* PA28 periph B */
+							 0 29 0x2 0x0>;	/* PA29 periph B */
+					};
+				};
+
 				pioA: gpio@fffff400 {
 					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
 					reg = <0xfffff400 0x200>;
@@ -294,6 +311,15 @@
 				status = "disabled";
 			};
 
+			ssc0: ssc@f0010000 {
+				compatible = "atmel,at91sam9g45-ssc";
+				reg = <0xf0010000 0x4000>;
+				interrupts = <28 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+				status = "disabled";
+			};
+
 			usart0: serial@f801c000 {
 				compatible = "atmel,at91sam9260-usart";
 				reg = <0xf801c000 0x4000>;
diff --git a/arch/arm/boot/dts/at91sam9x5.dtsi b/arch/arm/boot/dts/at91sam9x5.dtsi
index 40ac3a4..8ecca69 100644
--- a/arch/arm/boot/dts/at91sam9x5.dtsi
+++ b/arch/arm/boot/dts/at91sam9x5.dtsi
@@ -88,13 +88,6 @@
 				interrupts = <1 4 7>;
 			};
 
-			ssc0: ssc@f0010000 {
-				compatible = "atmel,at91sam9g45-ssc";
-				reg = <0xf0010000 0x4000>;
-				interrupts = <28 4 5>;
-				status = "disabled";
-			};
-
 			tcb0: timer@f8008000 {
 				compatible = "atmel,at91sam9x5-tcb";
 				reg = <0xf8008000 0x100>;
@@ -150,6 +143,11 @@
 						atmel,pins =
 							<0 3 0x1 0x0>;	/* PA3 periph A */
 					};
+
+					pinctrl_usart0_sck: usart0_sck-0 {
+						atmel,pins =
+							<0 4 0x1 0x0>;	/* PA4 periph A */
+					};
 				};
 
 				usart1 {
@@ -161,12 +159,17 @@
 
 					pinctrl_usart1_rts: usart1_rts-0 {
 						atmel,pins =
-							<3 27 0x3 0x0>;	/* PC27 periph C */
+							<2 27 0x3 0x0>;	/* PC27 periph C */
 					};
 
 					pinctrl_usart1_cts: usart1_cts-0 {
 						atmel,pins =
-							<3 28 0x3 0x0>;	/* PC28 periph C */
+							<2 28 0x3 0x0>;	/* PC28 periph C */
+					};
+
+					pinctrl_usart1_sck: usart1_sck-0 {
+						atmel,pins =
+							<2 28 0x3 0x0>;	/* PC29 periph C */
 					};
 				};
 
@@ -179,46 +182,56 @@
 
 					pinctrl_uart2_rts: uart2_rts-0 {
 						atmel,pins =
-							<0 0 0x2 0x0>;	/* PB0 periph B */
+							<1 0 0x2 0x0>;	/* PB0 periph B */
 					};
 
 					pinctrl_uart2_cts: uart2_cts-0 {
 						atmel,pins =
-							<0 1 0x2 0x0>;	/* PB1 periph B */
+							<1 1 0x2 0x0>;	/* PB1 periph B */
+					};
+
+					pinctrl_usart2_sck: usart2_sck-0 {
+						atmel,pins =
+							<1 2 0x2 0x0>;	/* PB2 periph B */
 					};
 				};
 
 				usart3 {
 					pinctrl_uart3: usart3-0 {
 						atmel,pins =
-							<3 23 0x2 0x1	/* PC22 periph B with pullup */
-							 3 23 0x2 0x0>;	/* PC23 periph B */
+							<2 23 0x2 0x1	/* PC22 periph B with pullup */
+							 2 23 0x2 0x0>;	/* PC23 periph B */
 					};
 
 					pinctrl_usart3_rts: usart3_rts-0 {
 						atmel,pins =
-							<3 24 0x2 0x0>;	/* PC24 periph B */
+							<2 24 0x2 0x0>;	/* PC24 periph B */
 					};
 
 					pinctrl_usart3_cts: usart3_cts-0 {
 						atmel,pins =
-							<3 25 0x2 0x0>;	/* PC25 periph B */
+							<2 25 0x2 0x0>;	/* PC25 periph B */
+					};
+
+					pinctrl_usart3_sck: usart3_sck-0 {
+						atmel,pins =
+							<2 26 0x2 0x0>;	/* PC26 periph B */
 					};
 				};
 
 				uart0 {
 					pinctrl_uart0: uart0-0 {
 						atmel,pins =
-							<3 8 0x3 0x0	/* PC8 periph C */
-							 3 9 0x3 0x1>;	/* PC9 periph C with pullup */
+							<2 8 0x3 0x0	/* PC8 periph C */
+							 2 9 0x3 0x1>;	/* PC9 periph C with pullup */
 					};
 				};
 
 				uart1 {
 					pinctrl_uart1: uart1-0 {
 						atmel,pins =
-							<3 16 0x3 0x0	/* PC16 periph C */
-							 3 17 0x3 0x1>;	/* PC17 periph C with pullup */
+							<2 16 0x3 0x0	/* PC16 periph C */
+							 2 17 0x3 0x1>;	/* PC17 periph C with pullup */
 					};
 				};
 
@@ -247,14 +260,14 @@
 
 					pinctrl_macb0_rmii_mii: macb0_rmii_mii-0 {
 						atmel,pins =
-							<1 8 0x1 0x0	/* PA8 periph A */
-							 1 11 0x1 0x0	/* PA11 periph A */
-							 1 12 0x1 0x0	/* PA12 periph A */
-							 1 13 0x1 0x0	/* PA13 periph A */
-							 1 14 0x1 0x0	/* PA14 periph A */
-							 1 15 0x1 0x0	/* PA15 periph A */
-							 1 16 0x1 0x0	/* PA16 periph A */
-							 1 17 0x1 0x0>;	/* PA17 periph A */
+							<1 8 0x1 0x0	/* PB8 periph A */
+							 1 11 0x1 0x0	/* PB11 periph A */
+							 1 12 0x1 0x0	/* PB12 periph A */
+							 1 13 0x1 0x0	/* PB13 periph A */
+							 1 14 0x1 0x0	/* PB14 periph A */
+							 1 15 0x1 0x0	/* PB15 periph A */
+							 1 16 0x1 0x0	/* PB16 periph A */
+							 1 17 0x1 0x0>;	/* PB17 periph A */
 					};
 				};
 
@@ -290,6 +303,22 @@
 					};
 				};
 
+				ssc0 {
+					pinctrl_ssc0_tx: ssc0_tx-0 {
+						atmel,pins =
+							<0 24 0x2 0x0	/* PA24 periph B */
+							 0 25 0x2 0x0	/* PA25 periph B */
+							 0 26 0x2 0x0>;	/* PA26 periph B */
+					};
+
+					pinctrl_ssc0_rx: ssc0_rx-0 {
+						atmel,pins =
+							<0 27 0x2 0x0	/* PA27 periph B */
+							 0 28 0x2 0x0	/* PA28 periph B */
+							 0 29 0x2 0x0>;	/* PA29 periph B */
+					};
+				};
+
 				pioA: gpio@fffff400 {
 					compatible = "atmel,at91sam9x5-gpio", "atmel,at91rm9200-gpio";
 					reg = <0xfffff400 0x200>;
@@ -333,6 +362,15 @@
 				};
 			};
 
+			ssc0: ssc@f0010000 {
+				compatible = "atmel,at91sam9g45-ssc";
+				reg = <0xf0010000 0x4000>;
+				interrupts = <28 4 5>;
+				pinctrl-names = "default";
+				pinctrl-0 = <&pinctrl_ssc0_tx &pinctrl_ssc0_rx>;
+				status = "disabled";
+			};
+
 			mmc0: mmc@f0008000 {
 				compatible = "atmel,hsmci";
 				reg = <0xf0008000 0x600>;
diff --git a/arch/arm/boot/dts/cros5250-common.dtsi b/arch/arm/boot/dts/cros5250-common.dtsi
index fddd174..46c0980 100644
--- a/arch/arm/boot/dts/cros5250-common.dtsi
+++ b/arch/arm/boot/dts/cros5250-common.dtsi
@@ -96,8 +96,8 @@
 		fifo-depth = <0x80>;
 		card-detect-delay = <200>;
 		samsung,dw-mshc-ciu-div = <3>;
-		samsung,dw-mshc-sdr-timing = <2 3 3>;
-		samsung,dw-mshc-ddr-timing = <1 2 3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
 
 		slot@0 {
 			reg = <0>;
@@ -120,8 +120,8 @@
 		fifo-depth = <0x80>;
 		card-detect-delay = <200>;
 		samsung,dw-mshc-ciu-div = <3>;
-		samsung,dw-mshc-sdr-timing = <2 3 3>;
-		samsung,dw-mshc-ddr-timing = <1 2 3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
 
 		slot@0 {
 			reg = <0>;
@@ -141,8 +141,8 @@
 		fifo-depth = <0x80>;
 		card-detect-delay = <200>;
 		samsung,dw-mshc-ciu-div = <3>;
-		samsung,dw-mshc-sdr-timing = <2 3 3>;
-		samsung,dw-mshc-ddr-timing = <1 2 3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
 
 		slot@0 {
 			reg = <0>;
diff --git a/arch/arm/boot/dts/dove-cubox.dts b/arch/arm/boot/dts/dove-cubox.dts
index fed7d3f..cdee96f 100644
--- a/arch/arm/boot/dts/dove-cubox.dts
+++ b/arch/arm/boot/dts/dove-cubox.dts
@@ -26,10 +26,15 @@
 };
 
 &uart0 { status = "okay"; };
-&sdio0 { status = "okay"; };
 &sata0 { status = "okay"; };
 &i2c0 { status = "okay"; };
 
+&sdio0 {
+	status = "okay";
+	/* sdio0 card detect is connected to wrong pin on CuBox */
+	cd-gpios = <&gpio0 12 1>;
+};
+
 &spi0 {
 	status = "okay";
 
@@ -42,9 +47,14 @@
 };
 
 &pinctrl {
-	pinctrl-0 = <&pmx_gpio_18>;
+	pinctrl-0 = <&pmx_gpio_12 &pmx_gpio_18>;
 	pinctrl-names = "default";
 
+	pmx_gpio_12: pmx-gpio-12 {
+		marvell,pins = "mpp12";
+		marvell,function = "gpio";
+	};
+
 	pmx_gpio_18: pmx-gpio-18 {
 		marvell,pins = "mpp18";
 		marvell,function = "gpio";
diff --git a/arch/arm/boot/dts/dove.dtsi b/arch/arm/boot/dts/dove.dtsi
index 42eac1f..740630f 100644
--- a/arch/arm/boot/dts/dove.dtsi
+++ b/arch/arm/boot/dts/dove.dtsi
@@ -93,6 +93,7 @@
 			reg = <0xd0400 0x20>;
 			ngpios = <32>;
 			interrupt-controller;
+			#interrupt-cells = <2>;
 			interrupts = <12>, <13>, <14>, <60>;
 		};
 
@@ -103,6 +104,7 @@
 			reg = <0xd0420 0x20>;
 			ngpios = <32>;
 			interrupt-controller;
+			#interrupt-cells = <2>;
 			interrupts = <61>;
 		};
 
diff --git a/arch/arm/boot/dts/emev2.dtsi b/arch/arm/boot/dts/emev2.dtsi
index eb504a6..c8a8c08 100644
--- a/arch/arm/boot/dts/emev2.dtsi
+++ b/arch/arm/boot/dts/emev2.dtsi
@@ -15,11 +15,18 @@
 	interrupt-parent = <&gic>;
 
 	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
 		cpu@0 {
+			device_type = "cpu";
 			compatible = "arm,cortex-a9";
+			reg = <0>;
 		};
 		cpu@1 {
+			device_type = "cpu";
 			compatible = "arm,cortex-a9";
+			reg = <1>;
 		};
 	};
 
diff --git a/arch/arm/boot/dts/exynos5250-smdk5250.dts b/arch/arm/boot/dts/exynos5250-smdk5250.dts
index 942d576..e05b18f 100644
--- a/arch/arm/boot/dts/exynos5250-smdk5250.dts
+++ b/arch/arm/boot/dts/exynos5250-smdk5250.dts
@@ -115,8 +115,8 @@
 		fifo-depth = <0x80>;
 		card-detect-delay = <200>;
 		samsung,dw-mshc-ciu-div = <3>;
-		samsung,dw-mshc-sdr-timing = <2 3 3>;
-		samsung,dw-mshc-ddr-timing = <1 2 3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
 
 		slot@0 {
 			reg = <0>;
@@ -139,8 +139,8 @@
 		fifo-depth = <0x80>;
 		card-detect-delay = <200>;
 		samsung,dw-mshc-ciu-div = <3>;
-		samsung,dw-mshc-sdr-timing = <2 3 3>;
-		samsung,dw-mshc-ddr-timing = <1 2 3>;
+		samsung,dw-mshc-sdr-timing = <2 3>;
+		samsung,dw-mshc-ddr-timing = <1 2>;
 
 		slot@0 {
 			reg = <0>;
diff --git a/arch/arm/boot/dts/imx31.dtsi b/arch/arm/boot/dts/imx31.dtsi
index eef7099..454c2d1 100644
--- a/arch/arm/boot/dts/imx31.dtsi
+++ b/arch/arm/boot/dts/imx31.dtsi
@@ -45,6 +45,8 @@
 				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
 				reg = <0x43f90000 0x4000>;
 				interrupts = <45>;
+				clocks = <&clks 10>, <&clks 30>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
@@ -52,12 +54,16 @@
 				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
 				reg = <0x43f94000 0x4000>;
 				interrupts = <32>;
+				clocks = <&clks 10>, <&clks 31>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 
 			uart4: serial@43fb0000 {
 				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
 				reg = <0x43fb0000 0x4000>;
+				clocks = <&clks 10>, <&clks 49>;
+				clock-names = "ipg", "per";
 				interrupts = <46>;
 				status = "disabled";
 			};
@@ -66,6 +72,8 @@
 				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
 				reg = <0x43fb4000 0x4000>;
 				interrupts = <47>;
+				clocks = <&clks 10>, <&clks 50>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
 		};
@@ -81,8 +89,17 @@
 				compatible = "fsl,imx31-uart", "fsl,imx21-uart";
 				reg = <0x5000c000 0x4000>;
 				interrupts = <18>;
+				clocks = <&clks 10>, <&clks 48>;
+				clock-names = "ipg", "per";
 				status = "disabled";
 			};
+
+			clks: ccm@53f80000{
+				compatible = "fsl,imx31-ccm";
+				reg = <0x53f80000 0x4000>;
+				interrupts = <0 31 0x04 0 53 0x04>;
+				#clock-cells = <1>;
+			};
 		};
 	};
 };
diff --git a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
index 9bc6785..77d21ab 100644
--- a/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
+++ b/arch/arm/boot/dts/kirkwood-ns2-common.dtsi
@@ -1,4 +1,5 @@
 /include/ "kirkwood.dtsi"
+/include/ "kirkwood-6281.dtsi"
 
 / {
 	chosen {
@@ -6,6 +7,21 @@
 	};
 
 	ocp@f1000000 {
+		pinctrl: pinctrl@10000 {
+			pinctrl-0 = < &pmx_spi &pmx_twsi0 &pmx_uart0
+					&pmx_ns2_sata0 &pmx_ns2_sata1>;
+			pinctrl-names = "default";
+
+			pmx_ns2_sata0: pmx-ns2-sata0 {
+				marvell,pins = "mpp21";
+				marvell,function = "sata0";
+			};
+			pmx_ns2_sata1: pmx-ns2-sata1 {
+				marvell,pins = "mpp20";
+				marvell,function = "sata1";
+			};
+		};
+
 		serial@12000 {
 			clock-frequency = <166666667>;
 			status = "okay";
diff --git a/arch/arm/boot/dts/kirkwood.dtsi b/arch/arm/boot/dts/kirkwood.dtsi
index 110d6cb..d6ab442 100644
--- a/arch/arm/boot/dts/kirkwood.dtsi
+++ b/arch/arm/boot/dts/kirkwood.dtsi
@@ -36,6 +36,7 @@
 			reg = <0x10100 0x40>;
 			ngpios = <32>;
 			interrupt-controller;
+			#interrupt-cells = <2>;
 			interrupts = <35>, <36>, <37>, <38>;
 		};
 
@@ -46,6 +47,7 @@
 			reg = <0x10140 0x40>;
 			ngpios = <18>;
 			interrupt-controller;
+			#interrupt-cells = <2>;
 			interrupts = <39>, <40>, <41>;
 		};
 
diff --git a/arch/arm/boot/dts/kizbox.dts b/arch/arm/boot/dts/kizbox.dts
index e8814fe..b4dc3ed 100644
--- a/arch/arm/boot/dts/kizbox.dts
+++ b/arch/arm/boot/dts/kizbox.dts
@@ -48,6 +48,8 @@
 
 			macb0: ethernet@fffc4000 {
 				phy-mode = "mii";
+				pinctrl-0 = <&pinctrl_macb_rmii
+				             &pinctrl_macb_rmii_mii_alt>;
 				status = "okay";
 			};
 
diff --git a/arch/arm/boot/dts/marco-evb.dts b/arch/arm/boot/dts/marco-evb.dts
new file mode 100644
index 0000000..5130aea
--- /dev/null
+++ b/arch/arm/boot/dts/marco-evb.dts
@@ -0,0 +1,54 @@
+/*
+ * DTS file for CSR SiRFmarco Evaluation Board
+ *
+ * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/dts-v1/;
+
+/include/ "marco.dtsi"
+
+/ {
+	model = "CSR SiRFmarco Evaluation Board";
+	compatible = "sirf,marco-cb", "sirf,marco";
+
+	memory {
+		reg = <0x40000000 0x60000000>;
+	};
+
+	axi {
+		peri-iobg {
+			uart1: uart@cc060000 {
+				status = "okay";
+			};
+			uart2: uart@cc070000 {
+				status = "okay";
+			};
+			i2c0: i2c@cc0e0000 {
+			      status = "okay";
+			      fpga-cpld@4d {
+				      compatible = "sirf,fpga-cpld";
+				      reg = <0x4d>;
+			      };
+			};
+			spi1: spi@cc170000 {
+				status = "okay";
+				pinctrl-names = "default";
+				pinctrl-0 = <&spi1_pins_a>;
+				spi@0 {
+					compatible = "spidev";
+					reg = <0>;
+					spi-max-frequency = <1000000>;
+				};
+			};
+			pci-iobg {
+				sd0: sdhci@cd000000 {
+					bus-width = <8>;
+					status = "okay";
+				};
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/marco.dtsi b/arch/arm/boot/dts/marco.dtsi
new file mode 100644
index 0000000..1579c34
--- /dev/null
+++ b/arch/arm/boot/dts/marco.dtsi
@@ -0,0 +1,756 @@
+/*
+ * DTS file for CSR SiRFmarco SoC
+ *
+ * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+/include/ "skeleton.dtsi"
+/ {
+	compatible = "sirf,marco";
+	#address-cells = <1>;
+	#size-cells = <1>;
+	interrupt-parent = <&gic>;
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
+	axi {
+		compatible = "simple-bus";
+		#address-cells = <1>;
+		#size-cells = <1>;
+		ranges = <0x40000000 0x40000000 0xa0000000>;
+
+		l2-cache-controller@c0030000 {
+			compatible = "sirf,marco-pl310-cache", "arm,pl310-cache";
+			reg = <0xc0030000 0x1000>;
+			interrupts = <0 59 0>;
+			arm,tag-latency = <1 1 1>;
+			arm,data-latency = <1 1 1>;
+			arm,filter-ranges = <0x40000000 0x80000000>;
+		};
+
+		gic: interrupt-controller@c0011000 {
+			compatible = "arm,cortex-a9-gic";
+			interrupt-controller;
+			#interrupt-cells = <3>;
+			reg = <0xc0011000 0x1000>,
+			      <0xc0010100 0x0100>;
+		};
+
+		rstc-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xc2000000 0xc2000000 0x1000000>;
+
+			reset-controller@c2000000 {
+				compatible = "sirf,marco-rstc";
+				reg = <0xc2000000 0x10000>;
+			};
+		};
+
+		sys-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xc3000000 0xc3000000 0x1000000>;
+
+			clock-controller@c3000000 {
+				compatible = "sirf,marco-clkc";
+				reg = <0xc3000000 0x1000>;
+				interrupts = <0 3 0>;
+			};
+
+			rsc-controller@c3010000 {
+				compatible = "sirf,marco-rsc";
+				reg = <0xc3010000 0x1000>;
+			};
+		};
+
+		mem-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xc4000000 0xc4000000 0x1000000>;
+
+			memory-controller@c4000000 {
+				compatible = "sirf,marco-memc";
+				reg = <0xc4000000 0x10000>;
+				interrupts = <0 27 0>;
+			};
+		};
+
+		disp-iobg0 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xc5000000 0xc5000000 0x1000000>;
+
+			display0@c5000000 {
+				compatible = "sirf,marco-lcd";
+				reg = <0xc5000000 0x10000>;
+				interrupts = <0 30 0>;
+			};
+
+			vpp0@c5010000 {
+				compatible = "sirf,marco-vpp";
+				reg = <0xc5010000 0x10000>;
+				interrupts = <0 31 0>;
+			};
+		};
+
+		disp-iobg1 {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xc6000000 0xc6000000 0x1000000>;
+
+			display1@c6000000 {
+				compatible = "sirf,marco-lcd";
+				reg = <0xc6000000 0x10000>;
+				interrupts = <0 62 0>;
+			};
+
+			vpp1@c6010000 {
+				compatible = "sirf,marco-vpp";
+				reg = <0xc6010000 0x10000>;
+				interrupts = <0 63 0>;
+			};
+		};
+
+		graphics-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xc8000000 0xc8000000 0x1000000>;
+
+			graphics@c8000000 {
+				compatible = "powervr,sgx540";
+				reg = <0xc8000000 0x1000000>;
+				interrupts = <0 6 0>;
+			};
+		};
+
+		multimedia-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xc9000000 0xc9000000 0x1000000>;
+
+			multimedia@a0000000 {
+				compatible = "sirf,marco-video-codec";
+				reg = <0xc9000000 0x1000000>;
+				interrupts = <0 5 0>;
+			};
+		};
+
+		dsp-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xca000000 0xca000000 0x2000000>;
+
+			dspif@ca000000 {
+				compatible = "sirf,marco-dspif";
+				reg = <0xca000000 0x10000>;
+				interrupts = <0 9 0>;
+			};
+
+			gps@ca010000 {
+				compatible = "sirf,marco-gps";
+				reg = <0xca010000 0x10000>;
+				interrupts = <0 7 0>;
+			};
+
+			dsp@cb000000 {
+				compatible = "sirf,marco-dsp";
+				reg = <0xcb000000 0x1000000>;
+				interrupts = <0 8 0>;
+			};
+		};
+
+		peri-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xcc000000 0xcc000000 0x2000000>;
+
+			timer@cc020000 {
+				compatible = "sirf,marco-tick";
+				reg = <0xcc020000 0x1000>;
+				interrupts = <0 0 0>,
+					   <0 1 0>,
+					   <0 2 0>,
+					   <0 49 0>,
+					   <0 50 0>,
+					   <0 51 0>;
+			};
+
+			nand@cc030000 {
+				compatible = "sirf,marco-nand";
+				reg = <0xcc030000 0x10000>;
+				interrupts = <0 41 0>;
+			};
+
+			audio@cc040000 {
+				compatible = "sirf,marco-audio";
+				reg = <0xcc040000 0x10000>;
+				interrupts = <0 35 0>;
+			};
+
+			uart0: uart@cc050000 {
+				cell-index = <0>;
+				compatible = "sirf,marco-uart";
+				reg = <0xcc050000 0x1000>;
+				interrupts = <0 17 0>;
+				fifosize = <128>;
+				status = "disabled";
+			};
+
+			uart1: uart@cc060000 {
+				cell-index = <1>;
+				compatible = "sirf,marco-uart";
+				reg = <0xcc060000 0x1000>;
+				interrupts = <0 18 0>;
+				fifosize = <32>;
+				status = "disabled";
+			};
+
+			uart2: uart@cc070000 {
+				cell-index = <2>;
+				compatible = "sirf,marco-uart";
+				reg = <0xcc070000 0x1000>;
+				interrupts = <0 19 0>;
+				fifosize = <128>;
+				status = "disabled";
+			};
+
+			uart3: uart@cc190000 {
+				cell-index = <3>;
+				compatible = "sirf,marco-uart";
+				reg = <0xcc190000 0x1000>;
+				interrupts = <0 66 0>;
+				fifosize = <128>;
+				status = "disabled";
+			};
+
+			uart4: uart@cc1a0000 {
+				cell-index = <4>;
+				compatible = "sirf,marco-uart";
+				reg = <0xcc1a0000 0x1000>;
+				interrupts = <0 69 0>;
+				fifosize = <128>;
+				status = "disabled";
+			};
+
+			usp0: usp@cc080000 {
+				cell-index = <0>;
+				compatible = "sirf,marco-usp";
+				reg = <0xcc080000 0x10000>;
+				interrupts = <0 20 0>;
+				status = "disabled";
+			};
+
+			usp1: usp@cc090000 {
+				cell-index = <1>;
+				compatible = "sirf,marco-usp";
+				reg = <0xcc090000 0x10000>;
+				interrupts = <0 21 0>;
+				status = "disabled";
+			};
+
+			usp2: usp@cc0a0000 {
+				cell-index = <2>;
+				compatible = "sirf,marco-usp";
+				reg = <0xcc0a0000 0x10000>;
+				interrupts = <0 22 0>;
+				status = "disabled";
+			};
+
+			dmac0: dma-controller@cc0b0000 {
+				cell-index = <0>;
+				compatible = "sirf,marco-dmac";
+				reg = <0xcc0b0000 0x10000>;
+				interrupts = <0 12 0>;
+			};
+
+			dmac1: dma-controller@cc160000 {
+				cell-index = <1>;
+				compatible = "sirf,marco-dmac";
+				reg = <0xcc160000 0x10000>;
+				interrupts = <0 13 0>;
+			};
+
+			vip@cc0c0000 {
+				compatible = "sirf,marco-vip";
+				reg = <0xcc0c0000 0x10000>;
+			};
+
+			spi0: spi@cc0d0000 {
+				cell-index = <0>;
+				compatible = "sirf,marco-spi";
+				reg = <0xcc0d0000 0x10000>;
+				interrupts = <0 15 0>;
+				sirf,spi-num-chipselects = <1>;
+				cs-gpios = <&gpio 0 0>;
+				sirf,spi-dma-rx-channel = <25>;
+				sirf,spi-dma-tx-channel = <20>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			spi1: spi@cc170000 {
+				cell-index = <1>;
+				compatible = "sirf,marco-spi";
+				reg = <0xcc170000 0x10000>;
+				interrupts = <0 16 0>;
+				sirf,spi-num-chipselects = <1>;
+				cs-gpios = <&gpio 0 0>;
+				sirf,spi-dma-rx-channel = <12>;
+				sirf,spi-dma-tx-channel = <13>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c0: i2c@cc0e0000 {
+				cell-index = <0>;
+				compatible = "sirf,marco-i2c";
+				reg = <0xcc0e0000 0x10000>;
+				interrupts = <0 24 0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			i2c1: i2c@cc0f0000 {
+				cell-index = <1>;
+				compatible = "sirf,marco-i2c";
+				reg = <0xcc0f0000 0x10000>;
+				interrupts = <0 25 0>;
+				#address-cells = <1>;
+				#size-cells = <0>;
+				status = "disabled";
+			};
+
+			tsc@cc110000 {
+				compatible = "sirf,marco-tsc";
+				reg = <0xcc110000 0x10000>;
+				interrupts = <0 33 0>;
+			};
+
+			gpio: pinctrl@cc120000 {
+				#gpio-cells = <2>;
+				#interrupt-cells = <2>;
+				compatible = "sirf,marco-pinctrl";
+				reg = <0xcc120000 0x10000>;
+				interrupts = <0 43 0>,
+					   <0 44 0>,
+					   <0 45 0>,
+					   <0 46 0>,
+					   <0 47 0>;
+				gpio-controller;
+				interrupt-controller;
+
+				lcd_16pins_a: lcd0_0 {
+					lcd {
+						sirf,pins = "lcd_16bitsgrp";
+						sirf,function = "lcd_16bits";
+					};
+				};
+				lcd_18pins_a: lcd0_1 {
+					lcd {
+						sirf,pins = "lcd_18bitsgrp";
+						sirf,function = "lcd_18bits";
+					};
+				};
+				lcd_24pins_a: lcd0_2 {
+					lcd {
+						sirf,pins = "lcd_24bitsgrp";
+						sirf,function = "lcd_24bits";
+					};
+				};
+				lcdrom_pins_a: lcdrom0_0 {
+					lcd {
+						sirf,pins = "lcdromgrp";
+						sirf,function = "lcdrom";
+					};
+				};
+				uart0_pins_a: uart0_0 {
+					uart {
+						sirf,pins = "uart0grp";
+						sirf,function = "uart0";
+					};
+				};
+				uart1_pins_a: uart1_0 {
+					uart {
+						sirf,pins = "uart1grp";
+						sirf,function = "uart1";
+					};
+				};
+				uart2_pins_a: uart2_0 {
+					uart {
+						sirf,pins = "uart2grp";
+						sirf,function = "uart2";
+					};
+				};
+				uart2_noflow_pins_a: uart2_1 {
+					uart {
+						sirf,pins = "uart2_nostreamctrlgrp";
+						sirf,function = "uart2_nostreamctrl";
+					};
+				};
+				spi0_pins_a: spi0_0 {
+					spi {
+						sirf,pins = "spi0grp";
+						sirf,function = "spi0";
+					};
+				};
+				spi1_pins_a: spi1_0 {
+					spi {
+						sirf,pins = "spi1grp";
+						sirf,function = "spi1";
+					};
+				};
+				i2c0_pins_a: i2c0_0 {
+					i2c {
+						sirf,pins = "i2c0grp";
+						sirf,function = "i2c0";
+					};
+				};
+				i2c1_pins_a: i2c1_0 {
+					i2c {
+						sirf,pins = "i2c1grp";
+						sirf,function = "i2c1";
+					};
+				};
+				pwm0_pins_a: pwm0_0 {
+				        pwm {
+				                sirf,pins = "pwm0grp";
+				                sirf,function = "pwm0";
+				        };
+				};
+				pwm1_pins_a: pwm1_0 {
+				        pwm {
+				                sirf,pins = "pwm1grp";
+				                sirf,function = "pwm1";
+				        };
+				};
+				pwm2_pins_a: pwm2_0 {
+				        pwm {
+				                sirf,pins = "pwm2grp";
+				                sirf,function = "pwm2";
+				        };
+				};
+				pwm3_pins_a: pwm3_0 {
+				        pwm {
+				                sirf,pins = "pwm3grp";
+				                sirf,function = "pwm3";
+				        };
+				};
+				gps_pins_a: gps_0 {
+				        gps {
+				                sirf,pins = "gpsgrp";
+				                sirf,function = "gps";
+				        };
+				};
+				vip_pins_a: vip_0 {
+				        vip {
+				                sirf,pins = "vipgrp";
+				                sirf,function = "vip";
+				        };
+				};
+				sdmmc0_pins_a: sdmmc0_0 {
+				        sdmmc0 {
+				                sirf,pins = "sdmmc0grp";
+				                sirf,function = "sdmmc0";
+				        };
+				};
+				sdmmc1_pins_a: sdmmc1_0 {
+				        sdmmc1 {
+				                sirf,pins = "sdmmc1grp";
+				                sirf,function = "sdmmc1";
+				        };
+				};
+				sdmmc2_pins_a: sdmmc2_0 {
+				        sdmmc2 {
+				                sirf,pins = "sdmmc2grp";
+				                sirf,function = "sdmmc2";
+				        };
+				};
+				sdmmc3_pins_a: sdmmc3_0 {
+				        sdmmc3 {
+				                sirf,pins = "sdmmc3grp";
+				                sirf,function = "sdmmc3";
+				        };
+				};
+				sdmmc4_pins_a: sdmmc4_0 {
+				        sdmmc4 {
+				                sirf,pins = "sdmmc4grp";
+				                sirf,function = "sdmmc4";
+				        };
+				};
+				sdmmc5_pins_a: sdmmc5_0 {
+				        sdmmc5 {
+				                sirf,pins = "sdmmc5grp";
+				                sirf,function = "sdmmc5";
+				        };
+				};
+				i2s_pins_a: i2s_0 {
+				        i2s {
+				                sirf,pins = "i2sgrp";
+				                sirf,function = "i2s";
+				        };
+				};
+				ac97_pins_a: ac97_0 {
+				        ac97 {
+				                sirf,pins = "ac97grp";
+				                sirf,function = "ac97";
+				        };
+				};
+				nand_pins_a: nand_0 {
+				        nand {
+				                sirf,pins = "nandgrp";
+				                sirf,function = "nand";
+				        };
+				};
+				usp0_pins_a: usp0_0 {
+				        usp0 {
+				                sirf,pins = "usp0grp";
+				                sirf,function = "usp0";
+				        };
+				};
+				usp1_pins_a: usp1_0 {
+				        usp1 {
+				                sirf,pins = "usp1grp";
+				                sirf,function = "usp1";
+				        };
+				};
+				usp2_pins_a: usp2_0 {
+				        usp2 {
+				                sirf,pins = "usp2grp";
+				                sirf,function = "usp2";
+				        };
+				};
+				usb0_utmi_drvbus_pins_a: usb0_utmi_drvbus_0 {
+				        usb0_utmi_drvbus {
+				                sirf,pins = "usb0_utmi_drvbusgrp";
+				                sirf,function = "usb0_utmi_drvbus";
+				        };
+				};
+				usb1_utmi_drvbus_pins_a: usb1_utmi_drvbus_0 {
+				        usb1_utmi_drvbus {
+				                sirf,pins = "usb1_utmi_drvbusgrp";
+				                sirf,function = "usb1_utmi_drvbus";
+				        };
+				};
+				warm_rst_pins_a: warm_rst_0 {
+				        warm_rst {
+				                sirf,pins = "warm_rstgrp";
+				                sirf,function = "warm_rst";
+				        };
+				};
+				pulse_count_pins_a: pulse_count_0 {
+				        pulse_count {
+				                sirf,pins = "pulse_countgrp";
+				                sirf,function = "pulse_count";
+				        };
+				};
+				cko0_rst_pins_a: cko0_rst_0 {
+				        cko0_rst {
+				                sirf,pins = "cko0_rstgrp";
+				                sirf,function = "cko0_rst";
+				        };
+				};
+				cko1_rst_pins_a: cko1_rst_0 {
+				        cko1_rst {
+				                sirf,pins = "cko1_rstgrp";
+				                sirf,function = "cko1_rst";
+				        };
+				};
+			};
+
+			pwm@cc130000 {
+				compatible = "sirf,marco-pwm";
+				reg = <0xcc130000 0x10000>;
+			};
+
+			efusesys@cc140000 {
+				compatible = "sirf,marco-efuse";
+				reg = <0xcc140000 0x10000>;
+			};
+
+			pulsec@cc150000 {
+				compatible = "sirf,marco-pulsec";
+				reg = <0xcc150000 0x10000>;
+				interrupts = <0 48 0>;
+			};
+
+			pci-iobg {
+				compatible = "sirf,marco-pciiobg", "simple-bus";
+				#address-cells = <1>;
+				#size-cells = <1>;
+				ranges = <0xcd000000 0xcd000000 0x1000000>;
+
+				sd0: sdhci@cd000000 {
+					cell-index = <0>;
+					compatible = "sirf,marco-sdhc";
+					reg = <0xcd000000 0x100000>;
+					interrupts = <0 38 0>;
+					status = "disabled";
+				};
+
+				sd1: sdhci@cd100000 {
+					cell-index = <1>;
+					compatible = "sirf,marco-sdhc";
+					reg = <0xcd100000 0x100000>;
+					interrupts = <0 38 0>;
+					status = "disabled";
+				};
+
+				sd2: sdhci@cd200000 {
+					cell-index = <2>;
+					compatible = "sirf,marco-sdhc";
+					reg = <0xcd200000 0x100000>;
+					interrupts = <0 23 0>;
+					status = "disabled";
+				};
+
+				sd3: sdhci@cd300000 {
+					cell-index = <3>;
+					compatible = "sirf,marco-sdhc";
+					reg = <0xcd300000 0x100000>;
+					interrupts = <0 23 0>;
+					status = "disabled";
+				};
+
+				sd4: sdhci@cd400000 {
+					cell-index = <4>;
+					compatible = "sirf,marco-sdhc";
+					reg = <0xcd400000 0x100000>;
+					interrupts = <0 39 0>;
+					status = "disabled";
+				};
+
+				sd5: sdhci@cd500000 {
+					cell-index = <5>;
+					compatible = "sirf,marco-sdhc";
+					reg = <0xcd500000 0x100000>;
+					interrupts = <0 39 0>;
+					status = "disabled";
+				};
+
+				pci-copy@cd900000 {
+					compatible = "sirf,marco-pcicp";
+					reg = <0xcd900000 0x100000>;
+					interrupts = <0 40 0>;
+				};
+
+				rom-interface@cda00000 {
+					compatible = "sirf,marco-romif";
+					reg = <0xcda00000 0x100000>;
+				};
+			};
+		};
+
+		rtc-iobg {
+			compatible = "sirf,marco-rtciobg", "sirf-marco-rtciobg-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			reg = <0xc1000000 0x10000>;
+
+			gpsrtc@1000 {
+				compatible = "sirf,marco-gpsrtc";
+				reg = <0x1000 0x1000>;
+				interrupts = <0 55 0>,
+					   <0 56 0>,
+					   <0 57 0>;
+			};
+
+			sysrtc@2000 {
+				compatible = "sirf,marco-sysrtc";
+				reg = <0x2000 0x1000>;
+				interrupts = <0 52 0>,
+					   <0 53 0>,
+					   <0 54 0>;
+			};
+
+			pwrc@3000 {
+				compatible = "sirf,marco-pwrc";
+				reg = <0x3000 0x1000>;
+				interrupts = <0 32 0>;
+			};
+		};
+
+		uus-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xce000000 0xce000000 0x1000000>;
+
+			usb0: usb@ce000000 {
+				compatible = "chipidea,ci13611a-marco";
+				reg = <0xce000000 0x10000>;
+				interrupts = <0 10 0>;
+			};
+
+			usb1: usb@ce010000 {
+				compatible = "chipidea,ci13611a-marco";
+				reg = <0xce010000 0x10000>;
+				interrupts = <0 11 0>;
+			};
+
+			security@ce020000 {
+				compatible = "sirf,marco-security";
+				reg = <0xce020000 0x10000>;
+				interrupts = <0 42 0>;
+			};
+		};
+
+		can-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xd0000000 0xd0000000 0x1000000>;
+
+			can0: can@d0000000 {
+				compatible = "sirf,marco-can";
+				reg = <0xd0000000 0x10000>;
+			};
+
+			can1: can@d0010000 {
+				compatible = "sirf,marco-can";
+				reg = <0xd0010000 0x10000>;
+			};
+		};
+
+		lvds-iobg {
+			compatible = "simple-bus";
+			#address-cells = <1>;
+			#size-cells = <1>;
+			ranges = <0xd1000000 0xd1000000 0x1000000>;
+
+			lvds@d1000000 {
+				compatible = "sirf,marco-lvds";
+				reg = <0xd1000000 0x10000>;
+				interrupts = <0 64 0>;
+			};
+		};
+	};
+};
diff --git a/arch/arm/boot/dts/sh73a0-reference.dtsi b/arch/arm/boot/dts/sh73a0-reference.dtsi
new file mode 100644
index 0000000..d4bb012
--- /dev/null
+++ b/arch/arm/boot/dts/sh73a0-reference.dtsi
@@ -0,0 +1,24 @@
+/*
+ * Device Tree Source for the SH73A0 SoC
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * 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/ "sh73a0.dtsi"
+
+/ {
+	compatible = "renesas,sh73a0";
+
+	mmcif: mmcif@0x10010000 {
+		compatible = "renesas,sh-mmcif";
+		reg = <0xe6bd0000 0x100>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 140 0x4
+			      0 141 0x4>;
+		reg-io-width = <4>;
+	};
+};
diff --git a/arch/arm/boot/dts/sh73a0.dtsi b/arch/arm/boot/dts/sh73a0.dtsi
new file mode 100644
index 0000000..8a59465
--- /dev/null
+++ b/arch/arm/boot/dts/sh73a0.dtsi
@@ -0,0 +1,100 @@
+/*
+ * Device Tree Source for the SH73A0 SoC
+ *
+ * Copyright (C) 2012 Renesas Solutions Corp.
+ *
+ * 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/ "skeleton.dtsi"
+
+/ {
+	compatible = "renesas,sh73a0";
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
+	gic: interrupt-controller@f0001000 {
+		compatible = "arm,cortex-a9-gic";
+		#interrupt-cells = <3>;
+		#address-cells = <1>;
+		interrupt-controller;
+		reg = <0xf0001000 0x1000>,
+		      <0xf0000100 0x100>;
+	};
+
+	i2c0: i2c@0xe6820000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0xe6820000 0x425>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 167 0x4
+			      0 168 0x4
+			      0 169 0x4
+			      0 170 0x4>;
+	};
+
+	i2c1: i2c@0xe6822000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0xe6822000 0x425>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 51 0x4
+			      0 52 0x4
+			      0 53 0x4
+			      0 54 0x4>;
+	};
+
+	i2c2: i2c@0xe6824000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0xe6824000 0x425>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 171 0x4
+			      0 172 0x4
+			      0 173 0x4
+			      0 174 0x4>;
+	};
+
+	i2c3: i2c@0xe6826000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0xe6826000 0x425>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 183 0x4
+			      0 184 0x4
+			      0 185 0x4
+			      0 186 0x4>;
+	};
+
+	i2c4: i2c@0xe6828000 {
+		#address-cells = <1>;
+		#size-cells = <0>;
+		compatible = "renesas,rmobile-iic";
+		reg = <0xe6828000 0x425>;
+		interrupt-parent = <&gic>;
+		interrupts = <0 187 0x4
+			      0 188 0x4
+			      0 189 0x4
+			      0 190 0x4>;
+	};
+};
diff --git a/arch/arm/boot/dts/sunxi.dtsi b/arch/arm/boot/dts/sunxi.dtsi
index 8bbc2bf..8b36abe 100644
--- a/arch/arm/boot/dts/sunxi.dtsi
+++ b/arch/arm/boot/dts/sunxi.dtsi
@@ -60,19 +60,21 @@
 		};
 
 		uart0: uart@01c28000 {
-			compatible = "ns8250";
+			compatible = "snps,dw-apb-uart";
 			reg = <0x01c28000 0x400>;
 			interrupts = <1>;
 			reg-shift = <2>;
+			reg-io-width = <4>;
 			clock-frequency = <24000000>;
 			status = "disabled";
 		};
 
 		uart1: uart@01c28400 {
-			compatible = "ns8250";
+			compatible = "snps,dw-apb-uart";
 			reg = <0x01c28400 0x400>;
 			interrupts = <2>;
 			reg-shift = <2>;
+			reg-io-width = <4>;
 			clock-frequency = <24000000>;
 			status = "disabled";
 		};
diff --git a/arch/arm/boot/dts/tegra114-dalmore.dts b/arch/arm/boot/dts/tegra114-dalmore.dts
new file mode 100644
index 0000000..a30aca6
--- /dev/null
+++ b/arch/arm/boot/dts/tegra114-dalmore.dts
@@ -0,0 +1,21 @@
+/dts-v1/;
+
+/include/ "tegra114.dtsi"
+
+/ {
+	model = "NVIDIA Tegra114 Dalmore evaluation board";
+	compatible = "nvidia,dalmore", "nvidia,tegra114";
+
+	memory {
+		reg = <0x80000000 0x40000000>;
+	};
+
+	serial@70006300 {
+		status = "okay";
+		clock-frequency = <408000000>;
+	};
+
+	pmc {
+		nvidia,invert-interrupt;
+	};
+};
diff --git a/arch/arm/boot/dts/tegra114-pluto.dts b/arch/arm/boot/dts/tegra114-pluto.dts
new file mode 100644
index 0000000..9bea8f5
--- /dev/null
+++ b/arch/arm/boot/dts/tegra114-pluto.dts
@@ -0,0 +1,21 @@
+/dts-v1/;
+
+/include/ "tegra114.dtsi"
+
+/ {
+	model = "NVIDIA Tegra114 Pluto evaluation board";
+	compatible = "nvidia,pluto", "nvidia,tegra114";
+
+	memory {
+		reg = <0x80000000 0x40000000>;
+	};
+
+	serial@70006300 {
+		status = "okay";
+		clock-frequency = <408000000>;
+	};
+
+	pmc {
+		nvidia,invert-interrupt;
+	};
+};
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
new file mode 100644
index 0000000..1dfaf28
--- /dev/null
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -0,0 +1,153 @@
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "nvidia,tegra114";
+	interrupt-parent = <&gic>;
+
+	gic: interrupt-controller {
+		compatible = "arm,cortex-a15-gic";
+		#interrupt-cells = <3>;
+		interrupt-controller;
+		reg = <0x50041000 0x1000>,
+		      <0x50042000 0x1000>,
+		      <0x50044000 0x2000>,
+		      <0x50046000 0x2000>;
+		interrupts = <1 9 0xf04>;
+	};
+
+	timer@60005000 {
+		compatible = "nvidia,tegra114-timer", "nvidia,tegra20-timer";
+		reg = <0x60005000 0x400>;
+		interrupts = <0 0 0x04
+			      0 1 0x04
+			      0 41 0x04
+			      0 42 0x04
+			      0 121 0x04
+			      0 122 0x04>;
+	};
+
+	tegra_car: clock {
+		compatible = "nvidia,tegra114-car, nvidia,tegra30-car";
+		reg = <0x60006000 0x1000>;
+		#clock-cells = <1>;
+	};
+
+	ahb: ahb {
+		compatible = "nvidia,tegra114-ahb", "nvidia,tegra30-ahb";
+		reg = <0x6000c004 0x14c>;
+	};
+
+	gpio: gpio {
+		compatible = "nvidia,tegra114-gpio", "nvidia,tegra30-gpio";
+		reg = <0x6000d000 0x1000>;
+		interrupts = <0 32 0x04
+			      0 33 0x04
+			      0 34 0x04
+			      0 35 0x04
+			      0 55 0x04
+			      0 87 0x04
+			      0 89 0x04
+			      0 125 0x04>;
+		#gpio-cells = <2>;
+		gpio-controller;
+		#interrupt-cells = <2>;
+		interrupt-controller;
+	};
+
+	pinmux: pinmux {
+		compatible = "nvidia,tegra114-pinmux";
+		reg = <0x70000868 0x148		/* Pad control registers */
+		       0x70003000 0x40c>;	/* Mux registers */
+	};
+
+	serial@70006000 {
+		compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+		reg = <0x70006000 0x40>;
+		reg-shift = <2>;
+		interrupts = <0 36 0x04>;
+		status = "disabled";
+	};
+
+	serial@70006040 {
+		compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+		reg = <0x70006040 0x40>;
+		reg-shift = <2>;
+		interrupts = <0 37 0x04>;
+		status = "disabled";
+	};
+
+	serial@70006200 {
+		compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+		reg = <0x70006200 0x100>;
+		reg-shift = <2>;
+		interrupts = <0 46 0x04>;
+		status = "disabled";
+	};
+
+	serial@70006300 {
+		compatible = "nvidia,tegra114-uart", "nvidia,tegra20-uart";
+		reg = <0x70006300 0x100>;
+		reg-shift = <2>;
+		interrupts = <0 90 0x04>;
+		status = "disabled";
+	};
+
+	rtc {
+		compatible = "nvidia,tegra114-rtc", "nvidia,tegra20-rtc";
+		reg = <0x7000e000 0x100>;
+		interrupts = <0 2 0x04>;
+	};
+
+	pmc {
+		compatible = "nvidia,tegra114-pmc", "nvidia,tegra30-pmc";
+		reg = <0x7000e400 0x400>;
+	};
+
+	iommu {
+		compatible = "nvidia,tegra114-smmu", "nvidia,tegra30-smmu";
+		reg = <0x7000f010 0x02c
+		       0x7000f1f0 0x010
+		       0x7000f228 0x074>;
+		nvidia,#asids = <4>;
+		dma-window = <0 0x40000000>;
+		nvidia,swgroups = <0x18659fe>;
+		nvidia,ahb = <&ahb>;
+	};
+
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <1>;
+		};
+
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <2>;
+		};
+
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a15";
+			reg = <3>;
+		};
+	};
+
+	timer {
+		compatible = "arm,armv7-timer";
+		interrupts = <1 13 0xf08>,
+			     <1 14 0xf08>,
+			     <1 11 0xf08>,
+			     <1 10 0xf08>;
+	};
+};
diff --git a/arch/arm/boot/dts/tegra20-harmony.dts b/arch/arm/boot/dts/tegra20-harmony.dts
index 43eb72a..2b41697 100644
--- a/arch/arm/boot/dts/tegra20-harmony.dts
+++ b/arch/arm/boot/dts/tegra20-harmony.dts
@@ -432,6 +432,10 @@
 		status = "okay";
 	};
 
+	usb-phy@c5004400 {
+		nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+	};
+
 	sdhci@c8000200 {
 		status = "okay";
 		cd-gpios = <&gpio 69 0>; /* gpio PI5 */
diff --git a/arch/arm/boot/dts/tegra20-paz00.dts b/arch/arm/boot/dts/tegra20-paz00.dts
index 6a93d14..11b30db 100644
--- a/arch/arm/boot/dts/tegra20-paz00.dts
+++ b/arch/arm/boot/dts/tegra20-paz00.dts
@@ -266,6 +266,8 @@
 		clock-frequency = <80000>;
 		request-gpios = <&gpio 170 0>; /* gpio PV2 */
 		slave-addr = <138>;
+		clocks = <&tegra_car 67>, <&tegra_car 124>;
+		clock-names = "div-clk", "fast-clk";
 	};
 
 	i2c@7000d000 {
@@ -418,6 +420,10 @@
 		status = "okay";
 	};
 
+	usb-phy@c5004400 {
+		nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
+	};
+
 	sdhci@c8000000 {
 		status = "okay";
 		cd-gpios = <&gpio 173 0>; /* gpio PV5 */
diff --git a/arch/arm/boot/dts/tegra20-seaboard.dts b/arch/arm/boot/dts/tegra20-seaboard.dts
index 4204598..607bf0c 100644
--- a/arch/arm/boot/dts/tegra20-seaboard.dts
+++ b/arch/arm/boot/dts/tegra20-seaboard.dts
@@ -561,6 +561,10 @@
 		status = "okay";
 	};
 
+	usb-phy@c5004400 {
+		nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+	};
+
 	sdhci@c8000000 {
 		status = "okay";
 		power-gpios = <&gpio 86 0>; /* gpio PK6 */
diff --git a/arch/arm/boot/dts/tegra20-trimslice.dts b/arch/arm/boot/dts/tegra20-trimslice.dts
index b70b4cb..e47cf6a 100644
--- a/arch/arm/boot/dts/tegra20-trimslice.dts
+++ b/arch/arm/boot/dts/tegra20-trimslice.dts
@@ -310,6 +310,10 @@
 		status = "okay";
 	};
 
+	usb-phy@c5004400 {
+		nvidia,phy-reset-gpio = <&gpio 168 0>; /* gpio PV0 */
+	};
+
 	sdhci@c8000000 {
 		status = "okay";
 		bus-width = <4>;
diff --git a/arch/arm/boot/dts/tegra20-ventana.dts b/arch/arm/boot/dts/tegra20-ventana.dts
index adc4754..f6c61d1 100644
--- a/arch/arm/boot/dts/tegra20-ventana.dts
+++ b/arch/arm/boot/dts/tegra20-ventana.dts
@@ -497,6 +497,10 @@
 		status = "okay";
 	};
 
+	usb-phy@c5004400 {
+		nvidia,phy-reset-gpio = <&gpio 169 0>; /* gpio PV1 */
+	};
+
 	sdhci@c8000000 {
 		status = "okay";
 		power-gpios = <&gpio 86 0>; /* gpio PK6 */
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index b8effa1..2e7c83c 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -9,6 +9,7 @@
 		reg = <0x50000000 0x00024000>;
 		interrupts = <0 65 0x04   /* mpcore syncpt */
 			      0 67 0x04>; /* mpcore general */
+		clocks = <&tegra_car 28>;
 
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -19,41 +20,49 @@
 			compatible = "nvidia,tegra20-mpe";
 			reg = <0x54040000 0x00040000>;
 			interrupts = <0 68 0x04>;
+			clocks = <&tegra_car 60>;
 		};
 
 		vi {
 			compatible = "nvidia,tegra20-vi";
 			reg = <0x54080000 0x00040000>;
 			interrupts = <0 69 0x04>;
+			clocks = <&tegra_car 100>;
 		};
 
 		epp {
 			compatible = "nvidia,tegra20-epp";
 			reg = <0x540c0000 0x00040000>;
 			interrupts = <0 70 0x04>;
+			clocks = <&tegra_car 19>;
 		};
 
 		isp {
 			compatible = "nvidia,tegra20-isp";
 			reg = <0x54100000 0x00040000>;
 			interrupts = <0 71 0x04>;
+			clocks = <&tegra_car 23>;
 		};
 
 		gr2d {
 			compatible = "nvidia,tegra20-gr2d";
 			reg = <0x54140000 0x00040000>;
 			interrupts = <0 72 0x04>;
+			clocks = <&tegra_car 21>;
 		};
 
 		gr3d {
 			compatible = "nvidia,tegra20-gr3d";
 			reg = <0x54180000 0x00040000>;
+			clocks = <&tegra_car 24>;
 		};
 
 		dc@54200000 {
 			compatible = "nvidia,tegra20-dc";
 			reg = <0x54200000 0x00040000>;
 			interrupts = <0 73 0x04>;
+			clocks = <&tegra_car 27>, <&tegra_car 121>;
+			clock-names = "disp1", "parent";
 
 			rgb {
 				status = "disabled";
@@ -64,6 +73,8 @@
 			compatible = "nvidia,tegra20-dc";
 			reg = <0x54240000 0x00040000>;
 			interrupts = <0 74 0x04>;
+			clocks = <&tegra_car 26>, <&tegra_car 121>;
+			clock-names = "disp2", "parent";
 
 			rgb {
 				status = "disabled";
@@ -74,6 +85,8 @@
 			compatible = "nvidia,tegra20-hdmi";
 			reg = <0x54280000 0x00040000>;
 			interrupts = <0 75 0x04>;
+			clocks = <&tegra_car 51>, <&tegra_car 117>;
+			clock-names = "hdmi", "parent";
 			status = "disabled";
 		};
 
@@ -81,12 +94,14 @@
 			compatible = "nvidia,tegra20-tvo";
 			reg = <0x542c0000 0x00040000>;
 			interrupts = <0 76 0x04>;
+			clocks = <&tegra_car 102>;
 			status = "disabled";
 		};
 
 		dsi {
 			compatible = "nvidia,tegra20-dsi";
 			reg = <0x54300000 0x00040000>;
+			clocks = <&tegra_car 48>;
 			status = "disabled";
 		};
 	};
@@ -123,6 +138,12 @@
 			      0 42 0x04>;
 	};
 
+	tegra_car: clock {
+		compatible = "nvidia,tegra20-car";
+		reg = <0x60006000 0x1000>;
+		#clock-cells = <1>;
+	};
+
 	apbdma: dma {
 		compatible = "nvidia,tegra20-apbdma";
 		reg = <0x6000a000 0x1200>;
@@ -142,6 +163,7 @@
 			      0 117 0x04
 			      0 118 0x04
 			      0 119 0x04>;
+		clocks = <&tegra_car 34>;
 	};
 
 	ahb {
@@ -183,6 +205,7 @@
 		reg = <0x70002800 0x200>;
 		interrupts = <0 13 0x04>;
 		nvidia,dma-request-selector = <&apbdma 2>;
+		clocks = <&tegra_car 11>;
 		status = "disabled";
 	};
 
@@ -191,6 +214,7 @@
 		reg = <0x70002a00 0x200>;
 		interrupts = <0 3 0x04>;
 		nvidia,dma-request-selector = <&apbdma 1>;
+		clocks = <&tegra_car 18>;
 		status = "disabled";
 	};
 
@@ -199,6 +223,7 @@
 		reg = <0x70006000 0x40>;
 		reg-shift = <2>;
 		interrupts = <0 36 0x04>;
+		clocks = <&tegra_car 6>;
 		status = "disabled";
 	};
 
@@ -207,6 +232,7 @@
 		reg = <0x70006040 0x40>;
 		reg-shift = <2>;
 		interrupts = <0 37 0x04>;
+		clocks = <&tegra_car 96>;
 		status = "disabled";
 	};
 
@@ -215,6 +241,7 @@
 		reg = <0x70006200 0x100>;
 		reg-shift = <2>;
 		interrupts = <0 46 0x04>;
+		clocks = <&tegra_car 55>;
 		status = "disabled";
 	};
 
@@ -223,6 +250,7 @@
 		reg = <0x70006300 0x100>;
 		reg-shift = <2>;
 		interrupts = <0 90 0x04>;
+		clocks = <&tegra_car 65>;
 		status = "disabled";
 	};
 
@@ -231,6 +259,7 @@
 		reg = <0x70006400 0x100>;
 		reg-shift = <2>;
 		interrupts = <0 91 0x04>;
+		clocks = <&tegra_car 66>;
 		status = "disabled";
 	};
 
@@ -238,6 +267,7 @@
 		compatible = "nvidia,tegra20-pwm";
 		reg = <0x7000a000 0x100>;
 		#pwm-cells = <2>;
+		clocks = <&tegra_car 17>;
 	};
 
 	rtc {
@@ -252,6 +282,8 @@
 		interrupts = <0 38 0x04>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 12>, <&tegra_car 124>;
+		clock-names = "div-clk", "fast-clk";
 		status = "disabled";
 	};
 
@@ -262,6 +294,7 @@
 		nvidia,dma-request-selector = <&apbdma 11>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 43>;
 		status = "disabled";
 	};
 
@@ -271,6 +304,8 @@
 		interrupts = <0 84 0x04>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 54>, <&tegra_car 124>;
+		clock-names = "div-clk", "fast-clk";
 		status = "disabled";
 	};
 
@@ -280,6 +315,8 @@
 		interrupts = <0 92 0x04>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 67>, <&tegra_car 124>;
+		clock-names = "div-clk", "fast-clk";
 		status = "disabled";
 	};
 
@@ -289,6 +326,8 @@
 		interrupts = <0 53 0x04>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 47>, <&tegra_car 124>;
+		clock-names = "div-clk", "fast-clk";
 		status = "disabled";
 	};
 
@@ -299,6 +338,7 @@
 		nvidia,dma-request-selector = <&apbdma 15>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 41>;
 		status = "disabled";
 	};
 
@@ -309,6 +349,7 @@
 		nvidia,dma-request-selector = <&apbdma 16>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 44>;
 		status = "disabled";
 	};
 
@@ -319,6 +360,7 @@
 		nvidia,dma-request-selector = <&apbdma 17>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 46>;
 		status = "disabled";
 	};
 
@@ -329,6 +371,7 @@
 		nvidia,dma-request-selector = <&apbdma 18>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 68>;
 		status = "disabled";
 	};
 
@@ -357,12 +400,40 @@
 		#size-cells = <0>;
 	};
 
+	phy1: usb-phy@c5000400 {
+		compatible = "nvidia,tegra20-usb-phy";
+		reg = <0xc5000400 0x3c00>;
+		phy_type = "utmi";
+		nvidia,has-legacy-mode;
+		clocks = <&tegra_car 22>, <&tegra_car 127>;
+		clock-names = "phy", "pll_u";
+	};
+
+	phy2: usb-phy@c5004400 {
+		compatible = "nvidia,tegra20-usb-phy";
+		reg = <0xc5004400 0x3c00>;
+		phy_type = "ulpi";
+		clocks = <&tegra_car 94>, <&tegra_car 127>;
+		clock-names = "phy", "pll_u";
+	};
+
+	phy3: usb-phy@c5008400 {
+		compatible = "nvidia,tegra20-usb-phy";
+		reg = <0xc5008400 0x3C00>;
+		phy_type = "utmi";
+		clocks = <&tegra_car 22>, <&tegra_car 127>;
+		clock-names = "phy", "pll_u";
+	};
+
 	usb@c5000000 {
 		compatible = "nvidia,tegra20-ehci", "usb-ehci";
 		reg = <0xc5000000 0x4000>;
 		interrupts = <0 20 0x04>;
 		phy_type = "utmi";
 		nvidia,has-legacy-mode;
+		clocks = <&tegra_car 22>;
+		nvidia,needs-double-reset;
+		nvidia,phy = <&phy1>;
 		status = "disabled";
 	};
 
@@ -371,6 +442,8 @@
 		reg = <0xc5004000 0x4000>;
 		interrupts = <0 21 0x04>;
 		phy_type = "ulpi";
+		clocks = <&tegra_car 58>;
+		nvidia,phy = <&phy2>;
 		status = "disabled";
 	};
 
@@ -379,6 +452,8 @@
 		reg = <0xc5008000 0x4000>;
 		interrupts = <0 97 0x04>;
 		phy_type = "utmi";
+		clocks = <&tegra_car 59>;
+		nvidia,phy = <&phy3>;
 		status = "disabled";
 	};
 
@@ -386,6 +461,7 @@
 		compatible = "nvidia,tegra20-sdhci";
 		reg = <0xc8000000 0x200>;
 		interrupts = <0 14 0x04>;
+		clocks = <&tegra_car 14>;
 		status = "disabled";
 	};
 
@@ -393,6 +469,7 @@
 		compatible = "nvidia,tegra20-sdhci";
 		reg = <0xc8000200 0x200>;
 		interrupts = <0 15 0x04>;
+		clocks = <&tegra_car 9>;
 		status = "disabled";
 	};
 
@@ -400,6 +477,7 @@
 		compatible = "nvidia,tegra20-sdhci";
 		reg = <0xc8000400 0x200>;
 		interrupts = <0 19 0x04>;
+		clocks = <&tegra_car 69>;
 		status = "disabled";
 	};
 
@@ -407,9 +485,27 @@
 		compatible = "nvidia,tegra20-sdhci";
 		reg = <0xc8000600 0x200>;
 		interrupts = <0 31 0x04>;
+		clocks = <&tegra_car 15>;
 		status = "disabled";
 	};
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+	};
+
 	pmu {
 		compatible = "arm,cortex-a9-pmu";
 		interrupts = <0 56 0x04
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index 529fdb8..2de8b91 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -9,6 +9,7 @@
 		reg = <0x50000000 0x00024000>;
 		interrupts = <0 65 0x04   /* mpcore syncpt */
 			      0 67 0x04>; /* mpcore general */
+		clocks = <&tegra_car 28>;
 
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -19,41 +20,50 @@
 			compatible = "nvidia,tegra30-mpe";
 			reg = <0x54040000 0x00040000>;
 			interrupts = <0 68 0x04>;
+			clocks = <&tegra_car 60>;
 		};
 
 		vi {
 			compatible = "nvidia,tegra30-vi";
 			reg = <0x54080000 0x00040000>;
 			interrupts = <0 69 0x04>;
+			clocks = <&tegra_car 164>;
 		};
 
 		epp {
 			compatible = "nvidia,tegra30-epp";
 			reg = <0x540c0000 0x00040000>;
 			interrupts = <0 70 0x04>;
+			clocks = <&tegra_car 19>;
 		};
 
 		isp {
 			compatible = "nvidia,tegra30-isp";
 			reg = <0x54100000 0x00040000>;
 			interrupts = <0 71 0x04>;
+			clocks = <&tegra_car 23>;
 		};
 
 		gr2d {
 			compatible = "nvidia,tegra30-gr2d";
 			reg = <0x54140000 0x00040000>;
 			interrupts = <0 72 0x04>;
+			clocks = <&tegra_car 21>;
 		};
 
 		gr3d {
 			compatible = "nvidia,tegra30-gr3d";
 			reg = <0x54180000 0x00040000>;
+			clocks = <&tegra_car 24 &tegra_car 98>;
+			clock-names = "3d", "3d2";
 		};
 
 		dc@54200000 {
 			compatible = "nvidia,tegra30-dc";
 			reg = <0x54200000 0x00040000>;
 			interrupts = <0 73 0x04>;
+			clocks = <&tegra_car 27>, <&tegra_car 179>;
+			clock-names = "disp1", "parent";
 
 			rgb {
 				status = "disabled";
@@ -64,6 +74,8 @@
 			compatible = "nvidia,tegra30-dc";
 			reg = <0x54240000 0x00040000>;
 			interrupts = <0 74 0x04>;
+			clocks = <&tegra_car 26>, <&tegra_car 179>;
+			clock-names = "disp2", "parent";
 
 			rgb {
 				status = "disabled";
@@ -74,6 +86,8 @@
 			compatible = "nvidia,tegra30-hdmi";
 			reg = <0x54280000 0x00040000>;
 			interrupts = <0 75 0x04>;
+			clocks = <&tegra_car 51>, <&tegra_car 189>;
+			clock-names = "hdmi", "parent";
 			status = "disabled";
 		};
 
@@ -81,12 +95,14 @@
 			compatible = "nvidia,tegra30-tvo";
 			reg = <0x542c0000 0x00040000>;
 			interrupts = <0 76 0x04>;
+			clocks = <&tegra_car 169>;
 			status = "disabled";
 		};
 
 		dsi {
 			compatible = "nvidia,tegra30-dsi";
 			reg = <0x54300000 0x00040000>;
+			clocks = <&tegra_car 48>;
 			status = "disabled";
 		};
 	};
@@ -125,6 +141,12 @@
 			      0 122 0x04>;
 	};
 
+	tegra_car: clock {
+		compatible = "nvidia,tegra30-car";
+		reg = <0x60006000 0x1000>;
+		#clock-cells = <1>;
+	};
+
 	apbdma: dma {
 		compatible = "nvidia,tegra30-apbdma", "nvidia,tegra20-apbdma";
 		reg = <0x6000a000 0x1400>;
@@ -160,6 +182,7 @@
 			      0 141 0x04
 			      0 142 0x04
 			      0 143 0x04>;
+		clocks = <&tegra_car 34>;
 	};
 
 	ahb: ahb {
@@ -195,6 +218,7 @@
 		reg = <0x70006000 0x40>;
 		reg-shift = <2>;
 		interrupts = <0 36 0x04>;
+		clocks = <&tegra_car 6>;
 		status = "disabled";
 	};
 
@@ -203,6 +227,7 @@
 		reg = <0x70006040 0x40>;
 		reg-shift = <2>;
 		interrupts = <0 37 0x04>;
+		clocks = <&tegra_car 160>;
 		status = "disabled";
 	};
 
@@ -211,6 +236,7 @@
 		reg = <0x70006200 0x100>;
 		reg-shift = <2>;
 		interrupts = <0 46 0x04>;
+		clocks = <&tegra_car 55>;
 		status = "disabled";
 	};
 
@@ -219,6 +245,7 @@
 		reg = <0x70006300 0x100>;
 		reg-shift = <2>;
 		interrupts = <0 90 0x04>;
+		clocks = <&tegra_car 65>;
 		status = "disabled";
 	};
 
@@ -227,6 +254,7 @@
 		reg = <0x70006400 0x100>;
 		reg-shift = <2>;
 		interrupts = <0 91 0x04>;
+		clocks = <&tegra_car 66>;
 		status = "disabled";
 	};
 
@@ -234,6 +262,7 @@
 		compatible = "nvidia,tegra30-pwm", "nvidia,tegra20-pwm";
 		reg = <0x7000a000 0x100>;
 		#pwm-cells = <2>;
+		clocks = <&tegra_car 17>;
 	};
 
 	rtc {
@@ -248,6 +277,8 @@
 		interrupts = <0 38 0x04>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 12>, <&tegra_car 182>;
+		clock-names = "div-clk", "fast-clk";
 		status = "disabled";
 	};
 
@@ -257,6 +288,8 @@
 		interrupts = <0 84 0x04>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 54>, <&tegra_car 182>;
+		clock-names = "div-clk", "fast-clk";
 		status = "disabled";
 	};
 
@@ -266,6 +299,8 @@
 		interrupts = <0 92 0x04>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 67>, <&tegra_car 182>;
+		clock-names = "div-clk", "fast-clk";
 		status = "disabled";
 	};
 
@@ -275,6 +310,8 @@
 		interrupts = <0 120 0x04>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 103>, <&tegra_car 182>;
+		clock-names = "div-clk", "fast-clk";
 		status = "disabled";
 	};
 
@@ -284,6 +321,8 @@
 		interrupts = <0 53 0x04>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 47>, <&tegra_car 182>;
+		clock-names = "div-clk", "fast-clk";
 		status = "disabled";
 	};
 
@@ -294,6 +333,7 @@
 		nvidia,dma-request-selector = <&apbdma 15>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 41>;
 		status = "disabled";
 	};
 
@@ -304,6 +344,7 @@
 		nvidia,dma-request-selector = <&apbdma 16>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 44>;
 		status = "disabled";
 	};
 
@@ -314,6 +355,7 @@
 		nvidia,dma-request-selector = <&apbdma 17>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 46>;
 		status = "disabled";
 	};
 
@@ -324,6 +366,7 @@
 		nvidia,dma-request-selector = <&apbdma 18>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 68>;
 		status = "disabled";
 	};
 
@@ -334,6 +377,7 @@
 		nvidia,dma-request-selector = <&apbdma 27>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 104>;
 		status = "disabled";
 	};
 
@@ -344,6 +388,7 @@
 		nvidia,dma-request-selector = <&apbdma 28>;
 		#address-cells = <1>;
 		#size-cells = <0>;
+		clocks = <&tegra_car 105>;
 		status = "disabled";
 	};
 
@@ -377,7 +422,13 @@
 		       0x70080200 0x100>;
 		interrupts = <0 103 0x04>;
 		nvidia,dma-request-selector = <&apbdma 1>;
-
+		clocks = <&tegra_car 106>, <&tegra_car 107>, <&tegra_car 30>,
+			 <&tegra_car 11>, <&tegra_car 18>, <&tegra_car 101>,
+			 <&tegra_car 102>, <&tegra_car 108>, <&tegra_car 109>,
+			 <&tegra_car 110>, <&tegra_car 162>;
+		clock-names = "d_audio", "apbif", "i2s0", "i2s1", "i2s2",
+			      "i2s3", "i2s4", "dam0", "dam1", "dam2",
+			      "spdif_in";
 		ranges;
 		#address-cells = <1>;
 		#size-cells = <1>;
@@ -386,6 +437,7 @@
 			compatible = "nvidia,tegra30-i2s";
 			reg = <0x70080300 0x100>;
 			nvidia,ahub-cif-ids = <4 4>;
+			clocks = <&tegra_car 30>;
 			status = "disabled";
 		};
 
@@ -393,6 +445,7 @@
 			compatible = "nvidia,tegra30-i2s";
 			reg = <0x70080400 0x100>;
 			nvidia,ahub-cif-ids = <5 5>;
+			clocks = <&tegra_car 11>;
 			status = "disabled";
 		};
 
@@ -400,6 +453,7 @@
 			compatible = "nvidia,tegra30-i2s";
 			reg = <0x70080500 0x100>;
 			nvidia,ahub-cif-ids = <6 6>;
+			clocks = <&tegra_car 18>;
 			status = "disabled";
 		};
 
@@ -407,6 +461,7 @@
 			compatible = "nvidia,tegra30-i2s";
 			reg = <0x70080600 0x100>;
 			nvidia,ahub-cif-ids = <7 7>;
+			clocks = <&tegra_car 101>;
 			status = "disabled";
 		};
 
@@ -414,6 +469,7 @@
 			compatible = "nvidia,tegra30-i2s";
 			reg = <0x70080700 0x100>;
 			nvidia,ahub-cif-ids = <8 8>;
+			clocks = <&tegra_car 102>;
 			status = "disabled";
 		};
 	};
@@ -422,6 +478,7 @@
 		compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
 		reg = <0x78000000 0x200>;
 		interrupts = <0 14 0x04>;
+		clocks = <&tegra_car 14>;
 		status = "disabled";
 	};
 
@@ -429,6 +486,7 @@
 		compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
 		reg = <0x78000200 0x200>;
 		interrupts = <0 15 0x04>;
+		clocks = <&tegra_car 9>;
 		status = "disabled";
 	};
 
@@ -436,6 +494,7 @@
 		compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
 		reg = <0x78000400 0x200>;
 		interrupts = <0 19 0x04>;
+		clocks = <&tegra_car 69>;
 		status = "disabled";
 	};
 
@@ -443,9 +502,39 @@
 		compatible = "nvidia,tegra30-sdhci", "nvidia,tegra20-sdhci";
 		reg = <0x78000600 0x200>;
 		interrupts = <0 31 0x04>;
+		clocks = <&tegra_car 15>;
 		status = "disabled";
 	};
 
+	cpus {
+		#address-cells = <1>;
+		#size-cells = <0>;
+
+		cpu@0 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <0>;
+		};
+
+		cpu@1 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <1>;
+		};
+
+		cpu@2 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <2>;
+		};
+
+		cpu@3 {
+			device_type = "cpu";
+			compatible = "arm,cortex-a9";
+			reg = <3>;
+		};
+	};
+
 	pmu {
 		compatible = "arm,cortex-a9-pmu";
 		interrupts = <0 144 0x04
diff --git a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
index 1fc405a..cf8071a 100644
--- a/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
+++ b/arch/arm/boot/dts/vexpress-v2p-ca15_a7.dts
@@ -45,7 +45,6 @@
 			reg = <1>;
 		};
 
-/* A7s disabled till big.LITTLE patches are available...
 		cpu2: cpu@2 {
 			device_type = "cpu";
 			compatible = "arm,cortex-a7";
@@ -63,7 +62,6 @@
 			compatible = "arm,cortex-a7";
 			reg = <0x102>;
 		};
-*/
 	};
 
 	memory@80000000 {
diff --git a/arch/arm/boot/dts/wm8850-w70v2.dts b/arch/arm/boot/dts/wm8850-w70v2.dts
new file mode 100644
index 0000000..fcc660c
--- /dev/null
+++ b/arch/arm/boot/dts/wm8850-w70v2.dts
@@ -0,0 +1,47 @@
+/*
+ * wm8850-w70v2.dts
+ *  - Device tree file for Wondermedia WM8850 Tablet
+ *  - 'W70-V2' mainboard
+ *  - HongLianYing 'HLY070ML268-21A' 7" LCD panel
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/dts-v1/;
+/include/ "wm8850.dtsi"
+
+/ {
+	model = "Wondermedia WM8850-W70v2 Tablet";
+
+	/*
+	 * Display node is based on Sascha Hauer's patch on dri-devel.
+	 * Added a bpp property to calculate the size of the framebuffer
+	 * until the binding is formalized.
+	 */
+	display: display@0 {
+		modes {
+			mode0: mode@0 {
+				hactive = <800>;
+				vactive = <480>;
+				hback-porch = <88>;
+				hfront-porch = <40>;
+				hsync-len = <0>;
+				vback-porch = <32>;
+				vfront-porch = <11>;
+				vsync-len = <1>;
+				clock = <0>;	/* unused but required */
+				bpp = <16>;	/* non-standard but required */
+			};
+		};
+	};
+
+	backlight {
+		compatible = "pwm-backlight";
+		pwms = <&pwm 0 50000 1>;	/* duty inverted */
+
+		brightness-levels = <0 40 60 80 100 130 190 255>;
+		default-brightness-level = <5>;
+	};
+};
diff --git a/arch/arm/boot/dts/wm8850.dtsi b/arch/arm/boot/dts/wm8850.dtsi
new file mode 100644
index 0000000..e8cbfdc
--- /dev/null
+++ b/arch/arm/boot/dts/wm8850.dtsi
@@ -0,0 +1,224 @@
+/*
+ * wm8850.dtsi - Device tree file for Wondermedia WM8850 SoC
+ *
+ * Copyright (C) 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * Licensed under GPLv2 or later
+ */
+
+/include/ "skeleton.dtsi"
+
+/ {
+	compatible = "wm,wm8850";
+
+	aliases {
+		serial0 = &uart0;
+		serial1 = &uart1;
+		serial2 = &uart2;
+		serial3 = &uart3;
+	};
+
+	soc {
+		#address-cells = <1>;
+		#size-cells = <1>;
+		compatible = "simple-bus";
+		ranges;
+		interrupt-parent = <&intc0>;
+
+		intc0: interrupt-controller@d8140000 {
+			compatible = "via,vt8500-intc";
+			interrupt-controller;
+			reg = <0xd8140000 0x10000>;
+			#interrupt-cells = <1>;
+		};
+
+		/* Secondary IC cascaded to intc0 */
+		intc1: interrupt-controller@d8150000 {
+			compatible = "via,vt8500-intc";
+			interrupt-controller;
+			#interrupt-cells = <1>;
+			reg = <0xD8150000 0x10000>;
+			interrupts = <56 57 58 59 60 61 62 63>;
+		};
+
+		gpio: gpio-controller@d8110000 {
+			compatible = "wm,wm8650-gpio";
+			gpio-controller;
+			reg = <0xd8110000 0x10000>;
+			#gpio-cells = <3>;
+		};
+
+		pmc@d8130000 {
+			compatible = "via,vt8500-pmc";
+			reg = <0xd8130000 0x1000>;
+
+			clocks {
+				#address-cells = <1>;
+				#size-cells = <0>;
+
+				ref25: ref25M {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <25000000>;
+				};
+
+				ref24: ref24M {
+					#clock-cells = <0>;
+					compatible = "fixed-clock";
+					clock-frequency = <24000000>;
+				};
+
+				plla: plla {
+					#clock-cells = <0>;
+					compatible = "wm,wm8750-pll-clock";
+					clocks = <&ref25>;
+					reg = <0x200>;
+				};
+
+				pllb: pllb {
+					#clock-cells = <0>;
+					compatible = "wm,wm8750-pll-clock";
+					clocks = <&ref25>;
+					reg = <0x204>;
+				};
+
+				clkuart0: uart0 {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&ref24>;
+					enable-reg = <0x254>;
+					enable-bit = <24>;
+				};
+
+				clkuart1: uart1 {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&ref24>;
+					enable-reg = <0x254>;
+					enable-bit = <25>;
+				};
+
+                                clkuart2: uart2 {
+                                        #clock-cells = <0>;
+                                        compatible = "via,vt8500-device-clock";
+                                        clocks = <&ref24>;
+                                        enable-reg = <0x254>;
+                                        enable-bit = <26>;
+                                };
+
+                                clkuart3: uart3 {
+                                        #clock-cells = <0>;
+                                        compatible = "via,vt8500-device-clock";
+                                        clocks = <&ref24>;
+                                        enable-reg = <0x254>;
+                                        enable-bit = <27>;
+                                };
+
+				clkpwm: pwm {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&pllb>;
+					divisor-reg = <0x350>;
+					enable-reg = <0x250>;
+					enable-bit = <17>;
+				};
+
+				clksdhc: sdhc {
+					#clock-cells = <0>;
+					compatible = "via,vt8500-device-clock";
+					clocks = <&pllb>;
+					divisor-reg = <0x330>;
+					divisor-mask = <0x3f>;
+					enable-reg = <0x250>;
+					enable-bit = <0>;
+				};
+			};
+		};
+
+		fb@d8051700 {
+			compatible = "wm,wm8505-fb";
+			reg = <0xd8051700 0x200>;
+			display = <&display>;
+			default-mode = <&mode0>;
+		};
+
+		ge_rops@d8050400 {
+			compatible = "wm,prizm-ge-rops";
+			reg = <0xd8050400 0x100>;
+		};
+
+		pwm: pwm@d8220000 {
+			#pwm-cells = <3>;
+			compatible = "via,vt8500-pwm";
+			reg = <0xd8220000 0x100>;
+			clocks = <&clkpwm>;
+		};
+
+		timer@d8130100 {
+			compatible = "via,vt8500-timer";
+			reg = <0xd8130100 0x28>;
+			interrupts = <36>;
+		};
+
+		ehci@d8007900 {
+			compatible = "via,vt8500-ehci";
+			reg = <0xd8007900 0x200>;
+			interrupts = <26>;
+		};
+
+		uhci@d8007b00 {
+			compatible = "platform-uhci";
+			reg = <0xd8007b00 0x200>;
+			interrupts = <26>;
+		};
+
+		uhci@d8008d00 {
+			compatible = "platform-uhci";
+			reg = <0xd8008d00 0x200>;
+			interrupts = <26>;
+		};
+
+		uart0: uart@d8200000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd8200000 0x1040>;
+			interrupts = <32>;
+			clocks = <&clkuart0>;
+		};
+
+		uart1: uart@d82b0000 {
+			compatible = "via,vt8500-uart";
+			reg = <0xd82b0000 0x1040>;
+			interrupts = <33>;
+			clocks = <&clkuart1>;
+		};
+
+                uart2: uart@d8210000 {
+                        compatible = "via,vt8500-uart";
+                        reg = <0xd8210000 0x1040>;
+                        interrupts = <47>;
+                        clocks = <&clkuart2>;
+                };
+
+                uart3: uart@d82c0000 {
+                        compatible = "via,vt8500-uart";
+                        reg = <0xd82c0000 0x1040>;
+                        interrupts = <50>;
+                        clocks = <&clkuart3>;
+                };
+
+		rtc@d8100000 {
+			compatible = "via,vt8500-rtc";
+			reg = <0xd8100000 0x10000>;
+			interrupts = <48>;
+		};
+
+		sdhc@d800a000 {
+			compatible = "wm,wm8505-sdhc";
+			reg = <0xd800a000 0x1000>;
+			interrupts = <20 21>;
+			clocks = <&clksdhc>;
+			bus-width = <4>;
+			sdon-inverted;
+		};
+	};
+};
diff --git a/arch/arm/common/Kconfig b/arch/arm/common/Kconfig
index 45ceeb0..9353184 100644
--- a/arch/arm/common/Kconfig
+++ b/arch/arm/common/Kconfig
@@ -1,26 +1,3 @@
-config ARM_GIC
-	bool
-	select IRQ_DOMAIN
-	select MULTI_IRQ_HANDLER
-
-config GIC_NON_BANKED
-	bool
-
-config ARM_VIC
-	bool
-	select IRQ_DOMAIN
-	select MULTI_IRQ_HANDLER
-
-config ARM_VIC_NR
-	int
-	default 4 if ARCH_S5PV210
-	default 3 if ARCH_S5PC100
-	default 2
-	depends on ARM_VIC
-	help
-	  The maximum number of VICs available in the system, for
-	  power management.
-
 config ICST
 	bool
 
diff --git a/arch/arm/common/Makefile b/arch/arm/common/Makefile
index e8a4e58..dc8dd0d 100644
--- a/arch/arm/common/Makefile
+++ b/arch/arm/common/Makefile
@@ -2,8 +2,6 @@
 # Makefile for the linux kernel.
 #
 
-obj-$(CONFIG_ARM_GIC)		+= gic.o
-obj-$(CONFIG_ARM_VIC)		+= vic.o
 obj-$(CONFIG_ICST)		+= icst.o
 obj-$(CONFIG_SA1111)		+= sa1111.o
 obj-$(CONFIG_PCI_HOST_VIA82C505) += via82c505.o
diff --git a/arch/arm/configs/at91_dt_defconfig b/arch/arm/configs/at91_dt_defconfig
index b175577..1ea9590 100644
--- a/arch/arm/configs/at91_dt_defconfig
+++ b/arch/arm/configs/at91_dt_defconfig
@@ -19,6 +19,7 @@
 CONFIG_SOC_AT91SAM9263=y
 CONFIG_SOC_AT91SAM9G45=y
 CONFIG_SOC_AT91SAM9X5=y
+CONFIG_SOC_AT91SAM9N12=y
 CONFIG_MACH_AT91SAM_DT=y
 CONFIG_AT91_PROGRAMMABLE_CLOCKS=y
 CONFIG_AT91_TIMER_HZ=128
@@ -31,7 +32,7 @@
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_ARM_APPENDED_DTB=y
 CONFIG_ARM_ATAG_DTB_COMPAT=y
-CONFIG_CMDLINE="mem=128M console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
+CONFIG_CMDLINE="console=ttyS0,115200 initrd=0x21100000,25165824 root=/dev/ram0 rw"
 CONFIG_KEXEC=y
 CONFIG_AUTO_ZRELADDR=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
diff --git a/arch/arm/configs/imx_v6_v7_defconfig b/arch/arm/configs/imx_v6_v7_defconfig
index 6966713..0a39667 100644
--- a/arch/arm/configs/imx_v6_v7_defconfig
+++ b/arch/arm/configs/imx_v6_v7_defconfig
@@ -19,6 +19,7 @@
 CONFIG_ARCH_MXC=y
 CONFIG_ARCH_MULTI_V6=y
 CONFIG_ARCH_MULTI_V7=y
+CONFIG_MACH_IMX31_DT=y
 CONFIG_MACH_MX31LILLY=y
 CONFIG_MACH_MX31LITE=y
 CONFIG_MACH_PCM037=y
@@ -32,7 +33,6 @@
 CONFIG_MACH_MX35_3DS=y
 CONFIG_MACH_VPR200=y
 CONFIG_MACH_IMX51_DT=y
-CONFIG_MACH_MX51_3DS=y
 CONFIG_MACH_EUKREA_CPUIMX51SD=y
 CONFIG_SOC_IMX53=y
 CONFIG_SOC_IMX6Q=y
@@ -151,6 +151,7 @@
 CONFIG_REGULATOR=y
 CONFIG_REGULATOR_FIXED_VOLTAGE=y
 CONFIG_REGULATOR_DA9052=y
+CONFIG_REGULATOR_ANATOP=y
 CONFIG_REGULATOR_MC13783=y
 CONFIG_REGULATOR_MC13892=y
 CONFIG_MEDIA_SUPPORT=y
@@ -159,6 +160,7 @@
 CONFIG_MEDIA_CAMERA_SUPPORT=y
 CONFIG_SOC_CAMERA=y
 CONFIG_SOC_CAMERA_OV2640=y
+CONFIG_DRM=y
 CONFIG_VIDEO_MX3=y
 CONFIG_FB=y
 CONFIG_LCD_PLATFORM=y
@@ -197,9 +199,14 @@
 CONFIG_RTC_INTF_DEV_UIE_EMUL=y
 CONFIG_RTC_DRV_MC13XXX=y
 CONFIG_RTC_DRV_MXC=y
+CONFIG_RTC_DRV_SNVS=y
 CONFIG_DMADEVICES=y
 CONFIG_IMX_SDMA=y
 CONFIG_MXS_DMA=y
+CONFIG_STAGING=y
+CONFIG_DRM_IMX=y
+CONFIG_DRM_IMX_IPUV3_CORE=y
+CONFIG_DRM_IMX_IPUV3=y
 CONFIG_COMMON_CLK_DEBUG=y
 # CONFIG_IOMMU_SUPPORT is not set
 CONFIG_EXT2_FS=y
diff --git a/arch/arm/configs/kirkwood_defconfig b/arch/arm/configs/kirkwood_defconfig
index 93f3794..13482ea 100644
--- a/arch/arm/configs/kirkwood_defconfig
+++ b/arch/arm/configs/kirkwood_defconfig
@@ -56,6 +56,7 @@
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
 CONFIG_CPU_IDLE=y
+CONFIG_CPU_IDLE_KIRKWOOD=y
 CONFIG_NET=y
 CONFIG_PACKET=y
 CONFIG_UNIX=y
diff --git a/arch/arm/configs/mvebu_defconfig b/arch/arm/configs/mvebu_defconfig
index b5bc96c..cbd91bc 100644
--- a/arch/arm/configs/mvebu_defconfig
+++ b/arch/arm/configs/mvebu_defconfig
@@ -33,6 +33,8 @@
 CONFIG_MARVELL_PHY=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
+CONFIG_I2C=y
+CONFIG_I2C_MV64XXX=y
 CONFIG_SERIAL_8250_DW=y
 CONFIG_GPIOLIB=y
 CONFIG_GPIO_SYSFS=y
diff --git a/arch/arm/configs/prima2_defconfig b/arch/arm/configs/prima2_defconfig
index 6a936c7..002a1ce 100644
--- a/arch/arm/configs/prima2_defconfig
+++ b/arch/arm/configs/prima2_defconfig
@@ -11,6 +11,9 @@
 CONFIG_BSD_DISKLABEL=y
 CONFIG_SOLARIS_X86_PARTITION=y
 CONFIG_ARCH_SIRF=y
+# CONFIG_SWP_EMULATE is not set
+CONFIG_SMP=y
+CONFIG_SCHED_MC=y
 CONFIG_PREEMPT=y
 CONFIG_AEABI=y
 CONFIG_KEXEC=y
diff --git a/arch/arm/include/asm/cputype.h b/arch/arm/include/asm/cputype.h
index a59dcb5..ad41ec2 100644
--- a/arch/arm/include/asm/cputype.h
+++ b/arch/arm/include/asm/cputype.h
@@ -64,6 +64,24 @@
 #define read_cpuid_ext(reg) 0
 #endif
 
+#define ARM_CPU_IMP_ARM			0x41
+#define ARM_CPU_IMP_INTEL		0x69
+
+#define ARM_CPU_PART_ARM1136		0xB360
+#define ARM_CPU_PART_ARM1156		0xB560
+#define ARM_CPU_PART_ARM1176		0xB760
+#define ARM_CPU_PART_ARM11MPCORE	0xB020
+#define ARM_CPU_PART_CORTEX_A8		0xC080
+#define ARM_CPU_PART_CORTEX_A9		0xC090
+#define ARM_CPU_PART_CORTEX_A5		0xC050
+#define ARM_CPU_PART_CORTEX_A15		0xC0F0
+#define ARM_CPU_PART_CORTEX_A7		0xC070
+
+#define ARM_CPU_XSCALE_ARCH_MASK	0xe000
+#define ARM_CPU_XSCALE_ARCH_V1		0x2000
+#define ARM_CPU_XSCALE_ARCH_V2		0x4000
+#define ARM_CPU_XSCALE_ARCH_V3		0x6000
+
 /*
  * The CPU ID never changes at run time, so we might as well tell the
  * compiler that it's constant.  Use this function to read the CPU ID
@@ -74,6 +92,21 @@
 	return read_cpuid(CPUID_ID);
 }
 
+static inline unsigned int __attribute_const__ read_cpuid_implementor(void)
+{
+	return (read_cpuid_id() & 0xFF000000) >> 24;
+}
+
+static inline unsigned int __attribute_const__ read_cpuid_part_number(void)
+{
+	return read_cpuid_id() & 0xFFF0;
+}
+
+static inline unsigned int __attribute_const__ xscale_cpu_arch_version(void)
+{
+	return read_cpuid_part_number() & ARM_CPU_XSCALE_ARCH_MASK;
+}
+
 static inline unsigned int __attribute_const__ read_cpuid_cachetype(void)
 {
 	return read_cpuid(CPUID_CACHETYPE);
diff --git a/arch/arm/include/asm/mach/arch.h b/arch/arm/include/asm/mach/arch.h
index 917d4fc..308ad7d 100644
--- a/arch/arm/include/asm/mach/arch.h
+++ b/arch/arm/include/asm/mach/arch.h
@@ -12,7 +12,6 @@
 
 struct tag;
 struct meminfo;
-struct sys_timer;
 struct pt_regs;
 struct smp_operations;
 #ifdef CONFIG_SMP
@@ -48,7 +47,7 @@
 	void			(*map_io)(void);/* IO mapping function	*/
 	void			(*init_early)(void);
 	void			(*init_irq)(void);
-	struct sys_timer	*timer;		/* system tick timer	*/
+	void			(*init_time)(void);
 	void			(*init_machine)(void);
 	void			(*init_late)(void);
 #ifdef CONFIG_MULTI_IRQ_HANDLER
diff --git a/arch/arm/include/asm/mach/irq.h b/arch/arm/include/asm/mach/irq.h
index 15cb035..18c8830 100644
--- a/arch/arm/include/asm/mach/irq.h
+++ b/arch/arm/include/asm/mach/irq.h
@@ -22,6 +22,7 @@
 
 #ifdef CONFIG_MULTI_IRQ_HANDLER
 extern void (*handle_arch_irq)(struct pt_regs *);
+extern void set_handle_irq(void (*handle_irq)(struct pt_regs *));
 #endif
 
 /*
diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index 6ca945f..90c12e1 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/arch/arm/include/asm/mach/time.h
@@ -10,36 +10,6 @@
 #ifndef __ASM_ARM_MACH_TIME_H
 #define __ASM_ARM_MACH_TIME_H
 
-/*
- * This is our kernel timer structure.
- *
- * - init
- *   Initialise the kernels jiffy timer source, claim interrupt
- *   using setup_irq.  This is called early on during initialisation
- *   while interrupts are still disabled on the local CPU.
- * - suspend
- *   Suspend the kernel jiffy timer source, if necessary.  This
- *   is called with interrupts disabled, after all normal devices
- *   have been suspended.  If no action is required, set this to
- *   NULL.
- * - resume
- *   Resume the kernel jiffy timer source, if necessary.  This
- *   is called with interrupts disabled before any normal devices
- *   are resumed.  If no action is required, set this to NULL.
- * - offset
- *   Return the timer offset in microseconds since the last timer
- *   interrupt.  Note: this must take account of any unprocessed
- *   timer interrupt which may be pending.
- */
-struct sys_timer {
-	void			(*init)(void);
-	void			(*suspend)(void);
-	void			(*resume)(void);
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
-	unsigned long		(*offset)(void);
-#endif
-};
-
 extern void timer_tick(void);
 
 struct timespec;
diff --git a/arch/arm/include/asm/smp_scu.h b/arch/arm/include/asm/smp_scu.h
index 4eb6d00..006f026 100644
--- a/arch/arm/include/asm/smp_scu.h
+++ b/arch/arm/include/asm/smp_scu.h
@@ -6,6 +6,23 @@
 #define SCU_PM_POWEROFF	3
 
 #ifndef __ASSEMBLER__
+
+#include <asm/cputype.h>
+
+static inline bool scu_a9_has_base(void)
+{
+	return read_cpuid_part_number() == ARM_CPU_PART_CORTEX_A9;
+}
+
+static inline unsigned long scu_a9_get_base(void)
+{
+	unsigned long pa;
+
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (pa));
+
+	return pa;
+}
+
 unsigned int scu_get_core_count(void __iomem *);
 void scu_enable(void __iomem *);
 int scu_power_mode(void __iomem *, unsigned int);
diff --git a/arch/arm/include/debug/imx-uart.h b/arch/arm/include/debug/imx-uart.h
new file mode 100644
index 0000000..91d38e3
--- /dev/null
+++ b/arch/arm/include/debug/imx-uart.h
@@ -0,0 +1,88 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * 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.
+ */
+
+#ifndef __DEBUG_IMX_UART_H
+#define __DEBUG_IMX_UART_H
+
+#define IMX1_UART1_BASE_ADDR	0x00206000
+#define IMX1_UART2_BASE_ADDR	0x00207000
+#define IMX1_UART_BASE_ADDR(n)	IMX1_UART##n##_BASE_ADDR
+#define IMX1_UART_BASE(n)	IMX1_UART_BASE_ADDR(n)
+
+#define IMX21_UART1_BASE_ADDR	0x1000a000
+#define IMX21_UART2_BASE_ADDR	0x1000b000
+#define IMX21_UART3_BASE_ADDR	0x1000c000
+#define IMX21_UART4_BASE_ADDR	0x1000d000
+#define IMX21_UART_BASE_ADDR(n)	IMX21_UART##n##_BASE_ADDR
+#define IMX21_UART_BASE(n)	IMX21_UART_BASE_ADDR(n)
+
+#define IMX25_UART1_BASE_ADDR	0x43f90000
+#define IMX25_UART2_BASE_ADDR	0x43f94000
+#define IMX25_UART3_BASE_ADDR	0x5000c000
+#define IMX25_UART4_BASE_ADDR	0x50008000
+#define IMX25_UART5_BASE_ADDR	0x5002c000
+#define IMX25_UART_BASE_ADDR(n)	IMX25_UART##n##_BASE_ADDR
+#define IMX25_UART_BASE(n)	IMX25_UART_BASE_ADDR(n)
+
+#define IMX31_UART1_BASE_ADDR	0x43f90000
+#define IMX31_UART2_BASE_ADDR	0x43f94000
+#define IMX31_UART3_BASE_ADDR	0x5000c000
+#define IMX31_UART4_BASE_ADDR	0x43fb0000
+#define IMX31_UART5_BASE_ADDR	0x43fb4000
+#define IMX31_UART_BASE_ADDR(n)	IMX31_UART##n##_BASE_ADDR
+#define IMX31_UART_BASE(n)	IMX31_UART_BASE_ADDR(n)
+
+#define IMX35_UART1_BASE_ADDR	0x43f90000
+#define IMX35_UART2_BASE_ADDR	0x43f94000
+#define IMX35_UART3_BASE_ADDR	0x5000c000
+#define IMX35_UART_BASE_ADDR(n)	IMX35_UART##n##_BASE_ADDR
+#define IMX35_UART_BASE(n)	IMX35_UART_BASE_ADDR(n)
+
+#define IMX51_UART1_BASE_ADDR	0x73fbc000
+#define IMX51_UART2_BASE_ADDR	0x73fc0000
+#define IMX51_UART3_BASE_ADDR	0x7000c000
+#define IMX51_UART_BASE_ADDR(n)	IMX51_UART##n##_BASE_ADDR
+#define IMX51_UART_BASE(n)	IMX51_UART_BASE_ADDR(n)
+
+#define IMX53_UART1_BASE_ADDR	0x53fbc000
+#define IMX53_UART2_BASE_ADDR	0x53fc0000
+#define IMX53_UART3_BASE_ADDR	0x5000c000
+#define IMX53_UART4_BASE_ADDR	0x53ff0000
+#define IMX53_UART5_BASE_ADDR	0x63f90000
+#define IMX53_UART_BASE_ADDR(n)	IMX53_UART##n##_BASE_ADDR
+#define IMX53_UART_BASE(n)	IMX53_UART_BASE_ADDR(n)
+
+#define IMX6Q_UART1_BASE_ADDR	0x02020000
+#define IMX6Q_UART2_BASE_ADDR	0x021e8000
+#define IMX6Q_UART3_BASE_ADDR	0x021ec000
+#define IMX6Q_UART4_BASE_ADDR	0x021f0000
+#define IMX6Q_UART5_BASE_ADDR	0x021f4000
+#define IMX6Q_UART_BASE_ADDR(n)	IMX6Q_UART##n##_BASE_ADDR
+#define IMX6Q_UART_BASE(n)	IMX6Q_UART_BASE_ADDR(n)
+
+#define IMX_DEBUG_UART_BASE(soc) soc##_UART_BASE(CONFIG_DEBUG_IMX_UART_PORT)
+
+#ifdef CONFIG_DEBUG_IMX1_UART
+#define UART_PADDR	IMX_DEBUG_UART_BASE(IMX1)
+#elif defined(CONFIG_DEBUG_IMX21_IMX27_UART)
+#define UART_PADDR	IMX_DEBUG_UART_BASE(IMX21)
+#elif defined(CONFIG_DEBUG_IMX25_UART)
+#define UART_PADDR	IMX_DEBUG_UART_BASE(IMX25)
+#elif defined(CONFIG_DEBUG_IMX31_UART)
+#define UART_PADDR	IMX_DEBUG_UART_BASE(IMX31)
+#elif defined(CONFIG_DEBUG_IMX35_UART)
+#define UART_PADDR	IMX_DEBUG_UART_BASE(IMX35)
+#elif defined(CONFIG_DEBUG_IMX51_UART)
+#define UART_PADDR	IMX_DEBUG_UART_BASE(IMX51)
+#elif defined(CONFIG_DEBUG_IMX53_UART)
+#define UART_PADDR	IMX_DEBUG_UART_BASE(IMX53)
+#elif defined(CONFIG_DEBUG_IMX6Q_UART)
+#define UART_PADDR	IMX_DEBUG_UART_BASE(IMX6Q)
+#endif
+
+#endif /* __DEBUG_IMX_UART_H */
diff --git a/arch/arm/include/debug/imx.S b/arch/arm/include/debug/imx.S
index 0c4e17d..619d8cc 100644
--- a/arch/arm/include/debug/imx.S
+++ b/arch/arm/include/debug/imx.S
@@ -10,35 +10,8 @@
  * published by the Free Software Foundation.
  *
  */
-#define IMX6Q_UART1_BASE_ADDR	0x02020000
-#define IMX6Q_UART2_BASE_ADDR	0x021e8000
-#define IMX6Q_UART3_BASE_ADDR	0x021ec000
-#define IMX6Q_UART4_BASE_ADDR	0x021f0000
-#define IMX6Q_UART5_BASE_ADDR	0x021f4000
 
-/*
- * IMX6Q_UART_BASE_ADDR is put in the middle to force the expansion
- * of IMX6Q_UART##n##_BASE_ADDR.
- */
-#define IMX6Q_UART_BASE_ADDR(n)	IMX6Q_UART##n##_BASE_ADDR
-#define IMX6Q_UART_BASE(n)	IMX6Q_UART_BASE_ADDR(n)
-#define IMX6Q_DEBUG_UART_BASE	IMX6Q_UART_BASE(CONFIG_DEBUG_IMX6Q_UART_PORT)
-
-#ifdef CONFIG_DEBUG_IMX1_UART
-#define UART_PADDR	0x00206000
-#elif defined (CONFIG_DEBUG_IMX25_UART)
-#define UART_PADDR	0x43f90000
-#elif defined (CONFIG_DEBUG_IMX21_IMX27_UART)
-#define UART_PADDR	0x1000a000
-#elif defined (CONFIG_DEBUG_IMX31_IMX35_UART)
-#define UART_PADDR	0x43f90000
-#elif defined (CONFIG_DEBUG_IMX51_UART)
-#define UART_PADDR	0x73fbc000
-#elif defined (CONFIG_DEBUG_IMX50_IMX53_UART)
-#define UART_PADDR	0x53fbc000
-#elif defined (CONFIG_DEBUG_IMX6Q_UART)
-#define UART_PADDR	IMX6Q_DEBUG_UART_BASE
-#endif
+#include "imx-uart.h"
 
 /*
  * FIXME: This is a copy of IMX_IO_P2V in hardware.h, and needs to
diff --git a/arch/arm/include/debug/vt8500.S b/arch/arm/include/debug/vt8500.S
new file mode 100644
index 0000000..0e0ca08
--- /dev/null
+++ b/arch/arm/include/debug/vt8500.S
@@ -0,0 +1,37 @@
+/* 
+ * Debugging macro include header
+ *
+ *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
+ *    Moved from arch/arm/mach-vt8500/include/mach/debug-macro.S
+ *    Minor changes for readability.
+ *
+ * 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.
+ */
+
+#define DEBUG_LL_PHYS_BASE		0xD8000000
+#define DEBUG_LL_VIRT_BASE		0xF8000000
+#define DEBUG_LL_UART_OFFSET		0x00200000
+
+#if defined(CONFIG_DEBUG_VT8500_UART0)
+	.macro	addruart, rp, rv, tmp
+	mov	\rp,      #DEBUG_LL_UART_OFFSET
+	orr	\rv, \rp, #DEBUG_LL_VIRT_BASE
+	orr	\rp, \rp, #DEBUG_LL_PHYS_BASE
+	.endm
+
+	.macro	senduart,rd,rx
+	strb	\rd, [\rx, #0]
+	.endm
+
+	.macro	busyuart,rd,rx
+1001:	ldr	\rd, [\rx, #0x1c]
+	ands	\rd, \rd, #0x2
+	bne	1001b
+	.endm
+
+	.macro	waituart,rd,rx
+	.endm
+
+#endif
diff --git a/arch/arm/kernel/debug.S b/arch/arm/kernel/debug.S
index 6809200..14f7c3b 100644
--- a/arch/arm/kernel/debug.S
+++ b/arch/arm/kernel/debug.S
@@ -100,12 +100,14 @@
 		b	1b
 ENDPROC(printch)
 
+#ifdef CONFIG_MMU
 ENTRY(debug_ll_addr)
 		addruart r2, r3, ip
 		str	r2, [r0]
 		str	r3, [r1]
 		mov	pc, lr
 ENDPROC(debug_ll_addr)
+#endif
 
 #else
 
diff --git a/arch/arm/kernel/head.S b/arch/arm/kernel/head.S
index 4eee351..486a15a 100644
--- a/arch/arm/kernel/head.S
+++ b/arch/arm/kernel/head.S
@@ -246,6 +246,7 @@
 
 	/*
 	 * Then map boot params address in r2 if specified.
+	 * We map 2 sections in case the ATAGs/DTB crosses a section boundary.
 	 */
 	mov	r0, r2, lsr #SECTION_SHIFT
 	movs	r0, r0, lsl #SECTION_SHIFT
@@ -253,6 +254,8 @@
 	addne	r3, r3, #PAGE_OFFSET
 	addne	r3, r4, r3, lsr #(SECTION_SHIFT - PMD_ORDER)
 	orrne	r6, r7, r0
+	strne	r6, [r3], #1 << PMD_ORDER
+	addne	r6, r6, #1 << SECTION_SHIFT
 	strne	r6, [r3]
 
 #ifdef CONFIG_DEBUG_LL
@@ -331,7 +334,7 @@
 	 * as it has already been validated by the primary processor.
 	 */
 #ifdef CONFIG_ARM_VIRT_EXT
-	bl	__hyp_stub_install
+	bl	__hyp_stub_install_secondary
 #endif
 	safe_svcmode_maskall r9
 
diff --git a/arch/arm/kernel/hyp-stub.S b/arch/arm/kernel/hyp-stub.S
index 65b2417..1315c4c 100644
--- a/arch/arm/kernel/hyp-stub.S
+++ b/arch/arm/kernel/hyp-stub.S
@@ -99,7 +99,7 @@
 	 * immediately.
 	 */
 	compare_cpu_mode_with_primary	r4, r5, r6, r7
-	bxne	lr
+	movne	pc, lr
 
 	/*
 	 * Once we have given up on one CPU, we do not try to install the
@@ -111,7 +111,7 @@
 	 */
 
 	cmp	r4, #HYP_MODE
-	bxne	lr			@ give up if the CPU is not in HYP mode
+	movne	pc, lr			@ give up if the CPU is not in HYP mode
 
 /*
  * Configure HSCTLR to set correct exception endianness/instruction set
@@ -120,7 +120,8 @@
  * Eventually, CPU-specific code might be needed -- assume not for now
  *
  * This code relies on the "eret" instruction to synchronize the
- * various coprocessor accesses.
+ * various coprocessor accesses. This is done when we switch to SVC
+ * (see safe_svcmode_maskall).
  */
 	@ Now install the hypervisor stub:
 	adr	r7, __hyp_stub_vectors
@@ -155,14 +156,7 @@
 1:
 #endif
 
-	bic	r7, r4, #MODE_MASK
-	orr	r7, r7, #SVC_MODE
-THUMB(	orr	r7, r7, #PSR_T_BIT	)
-	msr	spsr_cxsf, r7		@ This is SPSR_hyp.
-
-	__MSR_ELR_HYP(14)		@ msr elr_hyp, lr
-	__ERET				@ return, switching to SVC mode
-					@ The boot CPU mode is left in r4.
+	bx	lr			@ The boot CPU mode is left in r4.
 ENDPROC(__hyp_stub_install_secondary)
 
 __hyp_stub_do_trap:
@@ -200,7 +194,7 @@
 	@ fall through
 ENTRY(__hyp_set_vectors)
 	__HVC(0)
-	bx	lr
+	mov	pc, lr
 ENDPROC(__hyp_set_vectors)
 
 #ifndef ZIMAGE
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 8961650..8e4ef4c 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -117,6 +117,16 @@
 	machine_desc->init_irq();
 }
 
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+void __init set_handle_irq(void (*handle_irq)(struct pt_regs *))
+{
+	if (handle_arch_irq)
+		return;
+
+	handle_arch_irq = handle_irq;
+}
+#endif
+
 #ifdef CONFIG_SPARSE_IRQ
 int __init arch_probe_nr_irqs(void)
 {
diff --git a/arch/arm/kernel/perf_event.c b/arch/arm/kernel/perf_event.c
index f9e8657..31e0eb3 100644
--- a/arch/arm/kernel/perf_event.c
+++ b/arch/arm/kernel/perf_event.c
@@ -149,12 +149,6 @@
 static void
 armpmu_read(struct perf_event *event)
 {
-	struct hw_perf_event *hwc = &event->hw;
-
-	/* Don't read disabled counters! */
-	if (hwc->idx < 0)
-		return;
-
 	armpmu_event_update(event);
 }
 
@@ -207,8 +201,6 @@
 	struct hw_perf_event *hwc = &event->hw;
 	int idx = hwc->idx;
 
-	WARN_ON(idx < 0);
-
 	armpmu_stop(event, PERF_EF_UPDATE);
 	hw_events->events[idx] = NULL;
 	clear_bit(idx, hw_events->used_mask);
@@ -358,7 +350,7 @@
 {
 	struct arm_pmu *armpmu = to_arm_pmu(event->pmu);
 	struct hw_perf_event *hwc = &event->hw;
-	int mapping, err;
+	int mapping;
 
 	mapping = armpmu->map_event(event);
 
@@ -407,14 +399,12 @@
 		local64_set(&hwc->period_left, hwc->sample_period);
 	}
 
-	err = 0;
 	if (event->group_leader != event) {
-		err = validate_group(event);
-		if (err)
+		if (validate_group(event) != 0);
 			return -EINVAL;
 	}
 
-	return err;
+	return 0;
 }
 
 static int armpmu_event_init(struct perf_event *event)
diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index 5f66206..1f2740e 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -147,7 +147,7 @@
 	cpu_pmu->free_irq	= cpu_pmu_free_irq;
 
 	/* Ensure the PMU has sane values out of reset. */
-	if (cpu_pmu && cpu_pmu->reset)
+	if (cpu_pmu->reset)
 		on_each_cpu(cpu_pmu->reset, cpu_pmu, 1);
 }
 
@@ -201,48 +201,46 @@
 static int probe_current_pmu(struct arm_pmu *pmu)
 {
 	int cpu = get_cpu();
-	unsigned long cpuid = read_cpuid_id();
-	unsigned long implementor = (cpuid & 0xFF000000) >> 24;
-	unsigned long part_number = (cpuid & 0xFFF0);
+	unsigned long implementor = read_cpuid_implementor();
+	unsigned long part_number = read_cpuid_part_number();
 	int ret = -ENODEV;
 
 	pr_info("probing PMU on CPU %d\n", cpu);
 
 	/* ARM Ltd CPUs. */
-	if (0x41 == implementor) {
+	if (implementor == ARM_CPU_IMP_ARM) {
 		switch (part_number) {
-		case 0xB360:	/* ARM1136 */
-		case 0xB560:	/* ARM1156 */
-		case 0xB760:	/* ARM1176 */
+		case ARM_CPU_PART_ARM1136:
+		case ARM_CPU_PART_ARM1156:
+		case ARM_CPU_PART_ARM1176:
 			ret = armv6pmu_init(pmu);
 			break;
-		case 0xB020:	/* ARM11mpcore */
+		case ARM_CPU_PART_ARM11MPCORE:
 			ret = armv6mpcore_pmu_init(pmu);
 			break;
-		case 0xC080:	/* Cortex-A8 */
+		case ARM_CPU_PART_CORTEX_A8:
 			ret = armv7_a8_pmu_init(pmu);
 			break;
-		case 0xC090:	/* Cortex-A9 */
+		case ARM_CPU_PART_CORTEX_A9:
 			ret = armv7_a9_pmu_init(pmu);
 			break;
-		case 0xC050:	/* Cortex-A5 */
+		case ARM_CPU_PART_CORTEX_A5:
 			ret = armv7_a5_pmu_init(pmu);
 			break;
-		case 0xC0F0:	/* Cortex-A15 */
+		case ARM_CPU_PART_CORTEX_A15:
 			ret = armv7_a15_pmu_init(pmu);
 			break;
-		case 0xC070:	/* Cortex-A7 */
+		case ARM_CPU_PART_CORTEX_A7:
 			ret = armv7_a7_pmu_init(pmu);
 			break;
 		}
 	/* Intel CPUs [xscale]. */
-	} else if (0x69 == implementor) {
-		part_number = (cpuid >> 13) & 0x7;
-		switch (part_number) {
-		case 1:
+	} else if (implementor == ARM_CPU_IMP_INTEL) {
+		switch (xscale_cpu_arch_version()) {
+		case ARM_CPU_XSCALE_ARCH_V1:
 			ret = xscale1pmu_init(pmu);
 			break;
-		case 2:
+		case ARM_CPU_XSCALE_ARCH_V2:
 			ret = xscale2pmu_init(pmu);
 			break;
 		}
@@ -279,17 +277,22 @@
 	}
 
 	if (ret) {
-		pr_info("failed to register PMU devices!");
-		kfree(pmu);
-		return ret;
+		pr_info("failed to probe PMU!");
+		goto out_free;
 	}
 
 	cpu_pmu = pmu;
 	cpu_pmu->plat_device = pdev;
 	cpu_pmu_init(cpu_pmu);
-	armpmu_register(cpu_pmu, PERF_TYPE_RAW);
+	ret = armpmu_register(cpu_pmu, PERF_TYPE_RAW);
 
-	return 0;
+	if (!ret)
+		return 0;
+
+out_free:
+	pr_info("failed to register PMU devices!");
+	kfree(pmu);
+	return ret;
 }
 
 static struct platform_driver cpu_pmu_driver = {
diff --git a/arch/arm/kernel/perf_event_v6.c b/arch/arm/kernel/perf_event_v6.c
index 041d052..03664b0 100644
--- a/arch/arm/kernel/perf_event_v6.c
+++ b/arch/arm/kernel/perf_event_v6.c
@@ -106,7 +106,7 @@
 		},
 		[C(OP_WRITE)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV6_PERFCTR_ICACHE_MISS,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_PREFETCH)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
@@ -259,7 +259,7 @@
 		},
 		[C(OP_WRITE)] = {
 			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]    = ARMV6MPCORE_PERFCTR_ICACHE_MISS,
+			[C(RESULT_MISS)]    = CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_PREFETCH)] = {
 			[C(RESULT_ACCESS)]  = CACHE_OP_UNSUPPORTED,
diff --git a/arch/arm/kernel/perf_event_v7.c b/arch/arm/kernel/perf_event_v7.c
index 4fbc757..8c79a9e 100644
--- a/arch/arm/kernel/perf_event_v7.c
+++ b/arch/arm/kernel/perf_event_v7.c
@@ -157,8 +157,8 @@
 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
 		},
 		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_A8_PERFCTR_L1_ICACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_PREFETCH)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
@@ -282,7 +282,7 @@
 		},
 		[C(OP_WRITE)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_PREFETCH)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
@@ -399,8 +399,8 @@
 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
 		},
 		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		/*
 		 * The prefetch counters don't differentiate between the I
@@ -527,8 +527,8 @@
 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
 		},
 		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_PREFETCH)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
@@ -651,8 +651,8 @@
 			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
 		},
 		[C(OP_WRITE)] = {
-			[C(RESULT_ACCESS)]	= ARMV7_PERFCTR_L1_ICACHE_ACCESS,
-			[C(RESULT_MISS)]	= ARMV7_PERFCTR_L1_ICACHE_REFILL,
+			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_PREFETCH)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
diff --git a/arch/arm/kernel/perf_event_xscale.c b/arch/arm/kernel/perf_event_xscale.c
index 2b0fe30..63990c4 100644
--- a/arch/arm/kernel/perf_event_xscale.c
+++ b/arch/arm/kernel/perf_event_xscale.c
@@ -83,7 +83,7 @@
 		},
 		[C(OP_WRITE)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
-			[C(RESULT_MISS)]	= XSCALE_PERFCTR_ICACHE_MISS,
+			[C(RESULT_MISS)]	= CACHE_OP_UNSUPPORTED,
 		},
 		[C(OP_PREFETCH)] = {
 			[C(RESULT_ACCESS)]	= CACHE_OP_UNSUPPORTED,
diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 84f4cbf..3fc96db 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -416,7 +416,8 @@
 
 void __init set_smp_cross_call(void (*fn)(const struct cpumask *, unsigned int))
 {
-	smp_cross_call = fn;
+	if (!smp_cross_call)
+		smp_cross_call = fn;
 }
 
 void arch_send_call_function_ipi_mask(const struct cpumask *mask)
diff --git a/arch/arm/kernel/smp_twd.c b/arch/arm/kernel/smp_twd.c
index 49f335d..dc9bb014 100644
--- a/arch/arm/kernel/smp_twd.c
+++ b/arch/arm/kernel/smp_twd.c
@@ -24,7 +24,6 @@
 
 #include <asm/smp_twd.h>
 #include <asm/localtimer.h>
-#include <asm/hardware/gic.h>
 
 /* set up by the platform code */
 static void __iomem *twd_base;
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 09be0c3..955d92d 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -21,7 +21,6 @@
 #include <linux/timex.h>
 #include <linux/errno.h>
 #include <linux/profile.h>
-#include <linux/syscore_ops.h>
 #include <linux/timer.h>
 #include <linux/irq.h>
 
@@ -31,11 +30,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 
-/*
- * Our system timer.
- */
-static struct sys_timer *system_timer;
-
 #if defined(CONFIG_RTC_DRV_CMOS) || defined(CONFIG_RTC_DRV_CMOS_MODULE) || \
     defined(CONFIG_NVRAM) || defined(CONFIG_NVRAM_MODULE)
 /* this needs a better home */
@@ -69,16 +63,6 @@
 EXPORT_SYMBOL(profile_pc);
 #endif
 
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
-u32 arch_gettimeoffset(void)
-{
-	if (system_timer->offset != NULL)
-		return system_timer->offset() * 1000;
-
-	return 0;
-}
-#endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */
-
 #ifndef CONFIG_GENERIC_CLOCKEVENTS
 /*
  * Kernel system timer support.
@@ -129,43 +113,8 @@
 	return -EINVAL;
 }
 
-#if defined(CONFIG_PM) && !defined(CONFIG_GENERIC_CLOCKEVENTS)
-static int timer_suspend(void)
-{
-	if (system_timer->suspend)
-		system_timer->suspend();
-
-	return 0;
-}
-
-static void timer_resume(void)
-{
-	if (system_timer->resume)
-		system_timer->resume();
-}
-#else
-#define timer_suspend NULL
-#define timer_resume NULL
-#endif
-
-static struct syscore_ops timer_syscore_ops = {
-	.suspend	= timer_suspend,
-	.resume		= timer_resume,
-};
-
-static int __init timer_init_syscore_ops(void)
-{
-	register_syscore_ops(&timer_syscore_ops);
-
-	return 0;
-}
-
-device_initcall(timer_init_syscore_ops);
-
 void __init time_init(void)
 {
-	system_timer = machine_desc->timer;
-	system_timer->init();
+	machine_desc->init_time();
 	sched_clock_postinit();
 }
-
diff --git a/arch/arm/mach-at91/at91rm9200_time.c b/arch/arm/mach-at91/at91rm9200_time.c
index 20a28ac..2acdff4 100644
--- a/arch/arm/mach-at91/at91rm9200_time.c
+++ b/arch/arm/mach-at91/at91rm9200_time.c
@@ -271,8 +271,3 @@
 	/* register clocksource */
 	clocksource_register_hz(&clk32k, AT91_SLOW_CLOCK);
 }
-
-struct sys_timer at91rm9200_timer = {
-	.init		= at91rm9200_timer_init,
-};
-
diff --git a/arch/arm/mach-at91/at91sam926x_time.c b/arch/arm/mach-at91/at91sam926x_time.c
index 358412f..3a4bc2e 100644
--- a/arch/arm/mach-at91/at91sam926x_time.c
+++ b/arch/arm/mach-at91/at91sam926x_time.c
@@ -104,12 +104,38 @@
 	}
 }
 
+static void at91sam926x_pit_suspend(struct clock_event_device *cedev)
+{
+	/* Disable timer */
+	pit_write(AT91_PIT_MR, 0);
+}
+
+static void at91sam926x_pit_reset(void)
+{
+	/* Disable timer and irqs */
+	pit_write(AT91_PIT_MR, 0);
+
+	/* Clear any pending interrupts, wait for PIT to stop counting */
+	while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0)
+		cpu_relax();
+
+	/* Start PIT but don't enable IRQ */
+	pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
+}
+
+static void at91sam926x_pit_resume(struct clock_event_device *cedev)
+{
+	at91sam926x_pit_reset();
+}
+
 static struct clock_event_device pit_clkevt = {
 	.name		= "pit",
 	.features	= CLOCK_EVT_FEAT_PERIODIC,
 	.shift		= 32,
 	.rating		= 100,
 	.set_mode	= pit_clkevt_mode,
+	.suspend	= at91sam926x_pit_suspend,
+	.resume		= at91sam926x_pit_resume,
 };
 
 
@@ -150,19 +176,6 @@
 	.irq		= NR_IRQS_LEGACY + AT91_ID_SYS,
 };
 
-static void at91sam926x_pit_reset(void)
-{
-	/* Disable timer and irqs */
-	pit_write(AT91_PIT_MR, 0);
-
-	/* Clear any pending interrupts, wait for PIT to stop counting */
-	while (PIT_CPIV(pit_read(AT91_PIT_PIVR)) != 0)
-		cpu_relax();
-
-	/* Start PIT but don't enable IRQ */
-	pit_write(AT91_PIT_MR, (pit_cycle - 1) | AT91_PIT_PITEN);
-}
-
 #ifdef CONFIG_OF
 static struct of_device_id pit_timer_ids[] = {
 	{ .compatible = "atmel,at91sam9260-pit" },
@@ -211,7 +224,7 @@
 /*
  * Set up both clocksource and clockevent support.
  */
-static void __init at91sam926x_pit_init(void)
+void __init at91sam926x_pit_init(void)
 {
 	unsigned long	pit_rate;
 	unsigned	bits;
@@ -250,12 +263,6 @@
 	clockevents_register_device(&pit_clkevt);
 }
 
-static void at91sam926x_pit_suspend(void)
-{
-	/* Disable timer */
-	pit_write(AT91_PIT_MR, 0);
-}
-
 void __init at91sam926x_ioremap_pit(u32 addr)
 {
 #if defined(CONFIG_OF)
@@ -272,9 +279,3 @@
 	if (!pit_base_addr)
 		panic("Impossible to ioremap PIT\n");
 }
-
-struct sys_timer at91sam926x_timer = {
-	.init		= at91sam926x_pit_init,
-	.suspend	= at91sam926x_pit_suspend,
-	.resume		= at91sam926x_pit_reset,
-};
diff --git a/arch/arm/mach-at91/at91x40_time.c b/arch/arm/mach-at91/at91x40_time.c
index 0e57e44..0c07a44 100644
--- a/arch/arm/mach-at91/at91x40_time.c
+++ b/arch/arm/mach-at91/at91x40_time.c
@@ -42,9 +42,10 @@
 #define	AT91_TC_CLK1BASE	0x40
 #define	AT91_TC_CLK2BASE	0x80
 
-static unsigned long at91x40_gettimeoffset(void)
+static u32 at91x40_gettimeoffset(void)
 {
-	return (at91_tc_read(AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 / (AT91X40_MASTER_CLOCK / 128));
+	return (at91_tc_read(AT91_TC_CLK1BASE + AT91_TC_CV) * 1000000 /
+		(AT91X40_MASTER_CLOCK / 128)) * 1000;
 }
 
 static irqreturn_t at91x40_timer_interrupt(int irq, void *dev_id)
@@ -64,6 +65,8 @@
 {
 	unsigned int v;
 
+	arch_gettimeoffset = at91x40_gettimeoffset;
+
 	at91_tc_write(AT91_TC_BCR, 0);
 	v = at91_tc_read(AT91_TC_BMR);
 	v = (v & ~AT91_TC_TC1XC1S) | AT91_TC_TC1XC1S_NONE;
@@ -79,9 +82,3 @@
 
 	at91_tc_write(AT91_TC_CLK1BASE + AT91_TC_CCR, (AT91_TC_SWTRG | AT91_TC_CLKEN));
 }
-
-struct sys_timer at91x40_timer = {
-	.init	= at91x40_timer_init,
-	.offset	= at91x40_gettimeoffset,
-};
-
diff --git a/arch/arm/mach-at91/board-1arm.c b/arch/arm/mach-at91/board-1arm.c
index b99b575..35ab632 100644
--- a/arch/arm/mach-at91/board-1arm.c
+++ b/arch/arm/mach-at91/board-1arm.c
@@ -90,7 +90,7 @@
 
 MACHINE_START(ONEARM, "Ajeco 1ARM single board computer")
 	/* Maintainer: Lennert Buytenhek <buytenh@wantstofly.org> */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= onearm_init_early,
diff --git a/arch/arm/mach-at91/board-afeb-9260v1.c b/arch/arm/mach-at91/board-afeb-9260v1.c
index 854b979..f95e31c 100644
--- a/arch/arm/mach-at91/board-afeb-9260v1.c
+++ b/arch/arm/mach-at91/board-afeb-9260v1.c
@@ -210,7 +210,7 @@
 
 MACHINE_START(AFEB9260, "Custom afeb9260 board")
 	/* Maintainer: Sergey Lapin <slapin@ossfans.org> */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= afeb9260_init_early,
diff --git a/arch/arm/mach-at91/board-cam60.c b/arch/arm/mach-at91/board-cam60.c
index 28a18ce..ade948b 100644
--- a/arch/arm/mach-at91/board-cam60.c
+++ b/arch/arm/mach-at91/board-cam60.c
@@ -187,7 +187,7 @@
 
 MACHINE_START(CAM60, "KwikByte CAM60")
 	/* Maintainer: KwikByte */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= cam60_init_early,
diff --git a/arch/arm/mach-at91/board-carmeva.c b/arch/arm/mach-at91/board-carmeva.c
index c17bb53..9298305 100644
--- a/arch/arm/mach-at91/board-carmeva.c
+++ b/arch/arm/mach-at91/board-carmeva.c
@@ -157,7 +157,7 @@
 
 MACHINE_START(CARMEVA, "Carmeva")
 	/* Maintainer: Conitec Datasystems */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= carmeva_init_early,
diff --git a/arch/arm/mach-at91/board-cpu9krea.c b/arch/arm/mach-at91/board-cpu9krea.c
index 8474324..008527e 100644
--- a/arch/arm/mach-at91/board-cpu9krea.c
+++ b/arch/arm/mach-at91/board-cpu9krea.c
@@ -374,7 +374,7 @@
 MACHINE_START(CPUAT9G20, "Eukrea CPU9G20")
 #endif
 	/* Maintainer: Eric Benard - EUKREA Electromatique */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= cpu9krea_init_early,
diff --git a/arch/arm/mach-at91/board-cpuat91.c b/arch/arm/mach-at91/board-cpuat91.c
index 2a7af78..42f1353 100644
--- a/arch/arm/mach-at91/board-cpuat91.c
+++ b/arch/arm/mach-at91/board-cpuat91.c
@@ -178,7 +178,7 @@
 
 MACHINE_START(CPUAT91, "Eukrea")
 	/* Maintainer: Eric Benard - EUKREA Electromatique */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= cpuat91_init_early,
diff --git a/arch/arm/mach-at91/board-csb337.c b/arch/arm/mach-at91/board-csb337.c
index 48a531e..e5fde215 100644
--- a/arch/arm/mach-at91/board-csb337.c
+++ b/arch/arm/mach-at91/board-csb337.c
@@ -251,7 +251,7 @@
 
 MACHINE_START(CSB337, "Cogent CSB337")
 	/* Maintainer: Bill Gatliff */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= csb337_init_early,
diff --git a/arch/arm/mach-at91/board-csb637.c b/arch/arm/mach-at91/board-csb637.c
index ec0f3ab..fdf1106 100644
--- a/arch/arm/mach-at91/board-csb637.c
+++ b/arch/arm/mach-at91/board-csb637.c
@@ -132,7 +132,7 @@
 
 MACHINE_START(CSB637, "Cogent CSB637")
 	/* Maintainer: Bill Gatliff */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= csb637_init_early,
diff --git a/arch/arm/mach-at91/board-dt.c b/arch/arm/mach-at91/board-dt.c
index 881170c..8db3013 100644
--- a/arch/arm/mach-at91/board-dt.c
+++ b/arch/arm/mach-at91/board-dt.c
@@ -49,7 +49,7 @@
 
 DT_MACHINE_START(at91sam_dt, "Atmel AT91SAM (Device Tree)")
 	/* Maintainer: Atmel */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= at91_dt_initialize,
diff --git a/arch/arm/mach-at91/board-eb01.c b/arch/arm/mach-at91/board-eb01.c
index b489388..becf0a6 100644
--- a/arch/arm/mach-at91/board-eb01.c
+++ b/arch/arm/mach-at91/board-eb01.c
@@ -44,7 +44,7 @@
 
 MACHINE_START(AT91EB01, "Atmel AT91 EB01")
 	/* Maintainer: Greg Ungerer <gerg@snapgear.com> */
-	.timer		= &at91x40_timer,
+	.init_time	= at91x40_timer_init,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= at91eb01_init_early,
 	.init_irq	= at91eb01_init_irq,
diff --git a/arch/arm/mach-at91/board-eb9200.c b/arch/arm/mach-at91/board-eb9200.c
index 9f5e71c..f9be816 100644
--- a/arch/arm/mach-at91/board-eb9200.c
+++ b/arch/arm/mach-at91/board-eb9200.c
@@ -116,7 +116,7 @@
 }
 
 MACHINE_START(ATEB9200, "Embest ATEB9200")
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= eb9200_init_early,
diff --git a/arch/arm/mach-at91/board-ecbat91.c b/arch/arm/mach-at91/board-ecbat91.c
index ef69e0e..b2fcd71 100644
--- a/arch/arm/mach-at91/board-ecbat91.c
+++ b/arch/arm/mach-at91/board-ecbat91.c
@@ -181,7 +181,7 @@
 
 MACHINE_START(ECBAT91, "emQbit's ECB_AT91")
 	/* Maintainer: emQbit.com */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ecb_at91init_early,
diff --git a/arch/arm/mach-at91/board-eco920.c b/arch/arm/mach-at91/board-eco920.c
index 50f3d37..77de410 100644
--- a/arch/arm/mach-at91/board-eco920.c
+++ b/arch/arm/mach-at91/board-eco920.c
@@ -149,7 +149,7 @@
 
 MACHINE_START(ECO920, "eco920")
 	/* Maintainer: Sascha Hauer */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= eco920_init_early,
diff --git a/arch/arm/mach-at91/board-flexibity.c b/arch/arm/mach-at91/board-flexibity.c
index 5d44eba..737c085 100644
--- a/arch/arm/mach-at91/board-flexibity.c
+++ b/arch/arm/mach-at91/board-flexibity.c
@@ -159,7 +159,7 @@
 
 MACHINE_START(FLEXIBITY, "Flexibity Connect")
 	/* Maintainer: Maxim Osipov */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= flexibity_init_early,
diff --git a/arch/arm/mach-at91/board-foxg20.c b/arch/arm/mach-at91/board-foxg20.c
index 191d37c..2ea7059 100644
--- a/arch/arm/mach-at91/board-foxg20.c
+++ b/arch/arm/mach-at91/board-foxg20.c
@@ -261,7 +261,7 @@
 
 MACHINE_START(ACMENETUSFOXG20, "Acme Systems srl FOX Board G20")
 	/* Maintainer: Sergio Tanzilli */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= foxg20_init_early,
diff --git a/arch/arm/mach-at91/board-gsia18s.c b/arch/arm/mach-at91/board-gsia18s.c
index 23a2fa1..c1d61d2 100644
--- a/arch/arm/mach-at91/board-gsia18s.c
+++ b/arch/arm/mach-at91/board-gsia18s.c
@@ -574,7 +574,7 @@
 }
 
 MACHINE_START(GSIA18S, "GS_IA18_S")
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= gsia18s_init_early,
diff --git a/arch/arm/mach-at91/board-kafa.c b/arch/arm/mach-at91/board-kafa.c
index 9a43d1e..88e2f5d 100644
--- a/arch/arm/mach-at91/board-kafa.c
+++ b/arch/arm/mach-at91/board-kafa.c
@@ -103,7 +103,7 @@
 
 MACHINE_START(KAFA, "Sperry-Sun KAFA")
 	/* Maintainer: Sergei Sharonov */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= kafa_init_early,
diff --git a/arch/arm/mach-at91/board-kb9202.c b/arch/arm/mach-at91/board-kb9202.c
index f168bec..0c519d9 100644
--- a/arch/arm/mach-at91/board-kb9202.c
+++ b/arch/arm/mach-at91/board-kb9202.c
@@ -149,7 +149,7 @@
 
 MACHINE_START(KB9200, "KB920x")
 	/* Maintainer: KwikByte, Inc. */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= kb9202_init_early,
diff --git a/arch/arm/mach-at91/board-neocore926.c b/arch/arm/mach-at91/board-neocore926.c
index bc7a1c4..5b4760f 100644
--- a/arch/arm/mach-at91/board-neocore926.c
+++ b/arch/arm/mach-at91/board-neocore926.c
@@ -378,7 +378,7 @@
 
 MACHINE_START(NEOCORE926, "ADENEO NEOCORE 926")
 	/* Maintainer: ADENEO */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= neocore926_init_early,
diff --git a/arch/arm/mach-at91/board-pcontrol-g20.c b/arch/arm/mach-at91/board-pcontrol-g20.c
index 0299554..65c0d6b 100644
--- a/arch/arm/mach-at91/board-pcontrol-g20.c
+++ b/arch/arm/mach-at91/board-pcontrol-g20.c
@@ -217,7 +217,7 @@
 
 MACHINE_START(PCONTROL_G20, "PControl G20")
 	/* Maintainer: pgsellmann@portner-elektronik.at */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= pcontrol_g20_init_early,
diff --git a/arch/arm/mach-at91/board-picotux200.c b/arch/arm/mach-at91/board-picotux200.c
index 4938f1c..ab2b2ec 100644
--- a/arch/arm/mach-at91/board-picotux200.c
+++ b/arch/arm/mach-at91/board-picotux200.c
@@ -119,7 +119,7 @@
 
 MACHINE_START(PICOTUX2XX, "picotux 200")
 	/* Maintainer: Kleinhenz Elektronik GmbH */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= picotux200_init_early,
diff --git a/arch/arm/mach-at91/board-qil-a9260.c b/arch/arm/mach-at91/board-qil-a9260.c
index 33b1628..aa3bc9b 100644
--- a/arch/arm/mach-at91/board-qil-a9260.c
+++ b/arch/arm/mach-at91/board-qil-a9260.c
@@ -257,7 +257,7 @@
 
 MACHINE_START(QIL_A9260, "CALAO QIL_A9260")
 	/* Maintainer: calao-systems */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
diff --git a/arch/arm/mach-at91/board-rm9200-dt.c b/arch/arm/mach-at91/board-rm9200-dt.c
index 5f9ce3d..3fcb662 100644
--- a/arch/arm/mach-at91/board-rm9200-dt.c
+++ b/arch/arm/mach-at91/board-rm9200-dt.c
@@ -47,7 +47,7 @@
 };
 
 DT_MACHINE_START(at91rm9200_dt, "Atmel AT91RM9200 (Device Tree)")
-	.timer		= &at91rm9200_timer,
+	.init_time      = at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= at91rm9200_dt_initialize,
diff --git a/arch/arm/mach-at91/board-rm9200dk.c b/arch/arm/mach-at91/board-rm9200dk.c
index 9e5061b..690541b 100644
--- a/arch/arm/mach-at91/board-rm9200dk.c
+++ b/arch/arm/mach-at91/board-rm9200dk.c
@@ -219,7 +219,7 @@
 
 MACHINE_START(AT91RM9200DK, "Atmel AT91RM9200-DK")
 	/* Maintainer: SAN People/Atmel */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= dk_init_early,
diff --git a/arch/arm/mach-at91/board-rm9200ek.c b/arch/arm/mach-at91/board-rm9200ek.c
index 58277db..8b17dad 100644
--- a/arch/arm/mach-at91/board-rm9200ek.c
+++ b/arch/arm/mach-at91/board-rm9200ek.c
@@ -186,7 +186,7 @@
 
 MACHINE_START(AT91RM9200EK, "Atmel AT91RM9200-EK")
 	/* Maintainer: SAN People/Atmel */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
diff --git a/arch/arm/mach-at91/board-rsi-ews.c b/arch/arm/mach-at91/board-rsi-ews.c
index 2e8b833..f6d7f19 100644
--- a/arch/arm/mach-at91/board-rsi-ews.c
+++ b/arch/arm/mach-at91/board-rsi-ews.c
@@ -222,7 +222,7 @@
 
 MACHINE_START(RSI_EWS, "RSI EWS")
 	/* Maintainer: Josef Holzmayr <holzmayr@rsi-elektrotechnik.de> */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= rsi_ews_init_early,
diff --git a/arch/arm/mach-at91/board-sam9-l9260.c b/arch/arm/mach-at91/board-sam9-l9260.c
index b75fbf6..43ee4dc 100644
--- a/arch/arm/mach-at91/board-sam9-l9260.c
+++ b/arch/arm/mach-at91/board-sam9-l9260.c
@@ -218,7 +218,7 @@
 
 MACHINE_START(SAM9_L9260, "Olimex SAM9-L9260")
 	/* Maintainer: Olimex */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9260ek.c b/arch/arm/mach-at91/board-sam9260ek.c
index f0135cd..0b153c8 100644
--- a/arch/arm/mach-at91/board-sam9260ek.c
+++ b/arch/arm/mach-at91/board-sam9260ek.c
@@ -343,7 +343,7 @@
 
 MACHINE_START(AT91SAM9260EK, "Atmel AT91SAM9260-EK")
 	/* Maintainer: Atmel */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9261ek.c b/arch/arm/mach-at91/board-sam9261ek.c
index 13ebaa8..b446645 100644
--- a/arch/arm/mach-at91/board-sam9261ek.c
+++ b/arch/arm/mach-at91/board-sam9261ek.c
@@ -612,7 +612,7 @@
 MACHINE_START(AT91SAM9G10EK, "Atmel AT91SAM9G10-EK")
 #endif
 	/* Maintainer: Atmel */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9263ek.c b/arch/arm/mach-at91/board-sam9263ek.c
index 89b9608..3284df0 100644
--- a/arch/arm/mach-at91/board-sam9263ek.c
+++ b/arch/arm/mach-at91/board-sam9263ek.c
@@ -443,7 +443,7 @@
 
 MACHINE_START(AT91SAM9263EK, "Atmel AT91SAM9263-EK")
 	/* Maintainer: Atmel */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9g20ek.c b/arch/arm/mach-at91/board-sam9g20ek.c
index 1b7dd9f..f9cd1f2 100644
--- a/arch/arm/mach-at91/board-sam9g20ek.c
+++ b/arch/arm/mach-at91/board-sam9g20ek.c
@@ -409,7 +409,7 @@
 
 MACHINE_START(AT91SAM9G20EK, "Atmel AT91SAM9G20-EK")
 	/* Maintainer: Atmel */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
@@ -419,7 +419,7 @@
 
 MACHINE_START(AT91SAM9G20EK_2MMC, "Atmel AT91SAM9G20-EK 2 MMC Slot Mod")
 	/* Maintainer: Atmel */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9m10g45ek.c b/arch/arm/mach-at91/board-sam9m10g45ek.c
index e4cc375..2a94896 100644
--- a/arch/arm/mach-at91/board-sam9m10g45ek.c
+++ b/arch/arm/mach-at91/board-sam9m10g45ek.c
@@ -502,7 +502,7 @@
 
 MACHINE_START(AT91SAM9M10G45EK, "Atmel AT91SAM9M10G45-EK")
 	/* Maintainer: Atmel */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
diff --git a/arch/arm/mach-at91/board-sam9rlek.c b/arch/arm/mach-at91/board-sam9rlek.c
index 377a109..aa265dc 100644
--- a/arch/arm/mach-at91/board-sam9rlek.c
+++ b/arch/arm/mach-at91/board-sam9rlek.c
@@ -320,7 +320,7 @@
 
 MACHINE_START(AT91SAM9RLEK, "Atmel AT91SAM9RL-EK")
 	/* Maintainer: Atmel */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
diff --git a/arch/arm/mach-at91/board-snapper9260.c b/arch/arm/mach-at91/board-snapper9260.c
index 9877150..3aaa978 100644
--- a/arch/arm/mach-at91/board-snapper9260.c
+++ b/arch/arm/mach-at91/board-snapper9260.c
@@ -177,7 +177,7 @@
 }
 
 MACHINE_START(SNAPPER_9260, "Bluewater Systems Snapper 9260/9G20 module")
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= snapper9260_init_early,
diff --git a/arch/arm/mach-at91/board-stamp9g20.c b/arch/arm/mach-at91/board-stamp9g20.c
index 48a962b..a033b8d 100644
--- a/arch/arm/mach-at91/board-stamp9g20.c
+++ b/arch/arm/mach-at91/board-stamp9g20.c
@@ -272,7 +272,7 @@
 
 MACHINE_START(PORTUXG20, "taskit PortuxG20")
 	/* Maintainer: taskit GmbH */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= stamp9g20_init_early,
@@ -282,7 +282,7 @@
 
 MACHINE_START(STAMP9G20, "taskit Stamp9G20")
 	/* Maintainer: taskit GmbH */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= stamp9g20_init_early,
diff --git a/arch/arm/mach-at91/board-usb-a926x.c b/arch/arm/mach-at91/board-usb-a926x.c
index c1060f9..2487d94 100644
--- a/arch/arm/mach-at91/board-usb-a926x.c
+++ b/arch/arm/mach-at91/board-usb-a926x.c
@@ -355,7 +355,7 @@
 
 MACHINE_START(USB_A9263, "CALAO USB_A9263")
 	/* Maintainer: calao-systems */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
@@ -365,7 +365,7 @@
 
 MACHINE_START(USB_A9260, "CALAO USB_A9260")
 	/* Maintainer: calao-systems */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
@@ -375,7 +375,7 @@
 
 MACHINE_START(USB_A9G20, "CALAO USB_A92G0")
 	/* Maintainer: Jean-Christophe PLAGNIOL-VILLARD */
-	.timer		= &at91sam926x_timer,
+	.init_time	= at91sam926x_pit_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= ek_init_early,
diff --git a/arch/arm/mach-at91/board-yl-9200.c b/arch/arm/mach-at91/board-yl-9200.c
index 8673aeb..be08377 100644
--- a/arch/arm/mach-at91/board-yl-9200.c
+++ b/arch/arm/mach-at91/board-yl-9200.c
@@ -587,7 +587,7 @@
 
 MACHINE_START(YL9200, "uCdragon YL-9200")
 	/* Maintainer: S.Birtles */
-	.timer		= &at91rm9200_timer,
+	.init_time	= at91rm9200_timer_init,
 	.map_io		= at91_map_io,
 	.handle_irq	= at91_aic_handle_irq,
 	.init_early	= yl9200_init_early,
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index fc593d6..78ab065 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -36,12 +36,11 @@
 
 
  /* Timer */
-struct sys_timer;
 extern void at91rm9200_ioremap_st(u32 addr);
-extern struct sys_timer at91rm9200_timer;
+extern void at91rm9200_timer_init(void);
 extern void at91sam926x_ioremap_pit(u32 addr);
-extern struct sys_timer at91sam926x_timer;
-extern struct sys_timer at91x40_timer;
+extern void at91sam926x_pit_init(void);
+extern void at91x40_timer_init(void);
 
  /* Clocks */
 #ifdef CONFIG_AT91_PMC_UNIT
diff --git a/arch/arm/mach-at91/setup.c b/arch/arm/mach-at91/setup.c
index 9ee866c..4b67847 100644
--- a/arch/arm/mach-at91/setup.c
+++ b/arch/arm/mach-at91/setup.c
@@ -105,6 +105,8 @@
 	switch (socid) {
 	case ARCH_ID_AT91RM9200:
 		at91_soc_initdata.type = AT91_SOC_RM9200;
+		if (at91_soc_initdata.subtype == AT91_SOC_SUBTYPE_NONE)
+			at91_soc_initdata.subtype = AT91_SOC_RM9200_BGA;
 		at91_boot_soc = at91rm9200_soc;
 		break;
 
diff --git a/arch/arm/mach-bcm/board_bcm.c b/arch/arm/mach-bcm/board_bcm.c
index 3a62f1b..f0f9aba 100644
--- a/arch/arm/mach-bcm/board_bcm.c
+++ b/arch/arm/mach-bcm/board_bcm.c
@@ -11,34 +11,19 @@
  * GNU General Public License for more details.
  */
 
-#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/init.h>
 #include <linux/device.h>
 #include <linux/platform_device.h>
+#include <linux/irqchip.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
-
 #include <asm/mach/time.h>
 
-static const struct of_device_id irq_match[] = {
-	{.compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-	{}
-};
-
 static void timer_init(void)
 {
 }
 
-static struct sys_timer timer = {
-	.init = timer_init,
-};
-
-static void __init init_irq(void)
-{
-	of_irq_init(irq_match);
-}
 
 static void __init board_init(void)
 {
@@ -49,9 +34,8 @@
 static const char * const bcm11351_dt_compat[] = { "bcm,bcm11351", NULL, };
 
 DT_MACHINE_START(BCM11351_DT, "Broadcom Application Processor")
-	.init_irq = init_irq,
-	.timer = &timer,
+	.init_irq = irqchip_init,
+	.init_time = timer_init,
 	.init_machine = board_init,
 	.dt_compat = bcm11351_dt_compat,
-	.handle_irq = gic_handle_irq,
 MACHINE_END
diff --git a/arch/arm/mach-bcm2835/bcm2835.c b/arch/arm/mach-bcm2835/bcm2835.c
index f0d739f..1a446a1 100644
--- a/arch/arm/mach-bcm2835/bcm2835.c
+++ b/arch/arm/mach-bcm2835/bcm2835.c
@@ -26,11 +26,13 @@
 #include <mach/bcm2835_soc.h>
 
 #define PM_RSTC				0x1c
+#define PM_RSTS				0x20
 #define PM_WDOG				0x24
 
 #define PM_PASSWORD			0x5a000000
 #define PM_RSTC_WRCFG_MASK		0x00000030
 #define PM_RSTC_WRCFG_FULL_RESET	0x00000020
+#define PM_RSTS_HADWRH_SET		0x00000040
 
 static void __iomem *wdt_regs;
 
@@ -67,6 +69,29 @@
 	mdelay(1);
 }
 
+/*
+ * We can't really power off, but if we do the normal reset scheme, and
+ * indicate to bootcode.bin not to reboot, then most of the chip will be
+ * powered off.
+ */
+static void bcm2835_power_off(void)
+{
+	u32 val;
+
+	/*
+	 * We set the watchdog hard reset bit here to distinguish this reset
+	 * from the normal (full) reset. bootcode.bin will not reboot after a
+	 * hard reset.
+	 */
+	val = readl_relaxed(wdt_regs + PM_RSTS);
+	val &= ~PM_RSTC_WRCFG_MASK;
+	val |= PM_PASSWORD | PM_RSTS_HADWRH_SET;
+	writel_relaxed(val, wdt_regs + PM_RSTS);
+
+	/* Continue with normal reset mechanism */
+	bcm2835_restart(0, "");
+}
+
 static struct map_desc io_map __initdata = {
 	.virtual = BCM2835_PERIPH_VIRT,
 	.pfn = __phys_to_pfn(BCM2835_PERIPH_PHYS),
@@ -84,6 +109,9 @@
 	int ret;
 
 	bcm2835_setup_restart();
+	if (wdt_regs)
+		pm_power_off = bcm2835_power_off;
+
 	bcm2835_init_clocks();
 
 	ret = of_platform_populate(NULL, of_default_bus_match_table, NULL,
@@ -104,7 +132,7 @@
 	.init_irq = bcm2835_init_irq,
 	.handle_irq = bcm2835_handle_irq,
 	.init_machine = bcm2835_init,
-	.timer = &bcm2835_timer,
+	.init_time = bcm2835_timer_init,
 	.restart = bcm2835_restart,
 	.dt_compat = bcm2835_compat
 MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-autcpu12.c b/arch/arm/mach-clps711x/board-autcpu12.c
index 3fbf43f..f385847 100644
--- a/arch/arm/mach-clps711x/board-autcpu12.c
+++ b/arch/arm/mach-clps711x/board-autcpu12.c
@@ -170,7 +170,7 @@
 	.nr_irqs	= CLPS711X_NR_IRQS,
 	.map_io		= clps711x_map_io,
 	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
+	.init_time	= clps711x_timer_init,
 	.init_machine	= autcpu12_init,
 	.init_late	= autcpu12_init_late,
 	.handle_irq	= clps711x_handle_irq,
diff --git a/arch/arm/mach-clps711x/board-cdb89712.c b/arch/arm/mach-clps711x/board-cdb89712.c
index 60900dd..baab7da 100644
--- a/arch/arm/mach-clps711x/board-cdb89712.c
+++ b/arch/arm/mach-clps711x/board-cdb89712.c
@@ -140,7 +140,7 @@
 	.nr_irqs	= CLPS711X_NR_IRQS,
 	.map_io		= clps711x_map_io,
 	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
+	.init_time	= clps711x_timer_init,
 	.init_machine	= cdb89712_init,
 	.handle_irq	= clps711x_handle_irq,
 	.restart	= clps711x_restart,
diff --git a/arch/arm/mach-clps711x/board-clep7312.c b/arch/arm/mach-clps711x/board-clep7312.c
index 0b32a48..014aa3c 100644
--- a/arch/arm/mach-clps711x/board-clep7312.c
+++ b/arch/arm/mach-clps711x/board-clep7312.c
@@ -40,7 +40,7 @@
 	.fixup		= fixup_clep7312,
 	.map_io		= clps711x_map_io,
 	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
+	.init_time	= clps711x_timer_init,
 	.handle_irq	= clps711x_handle_irq,
 	.restart	= clps711x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-edb7211.c b/arch/arm/mach-clps711x/board-edb7211.c
index 71aa5cf..5f928e9 100644
--- a/arch/arm/mach-clps711x/board-edb7211.c
+++ b/arch/arm/mach-clps711x/board-edb7211.c
@@ -173,7 +173,7 @@
 	.reserve	= edb7211_reserve,
 	.map_io		= edb7211_map_io,
 	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
+	.init_time	= clps711x_timer_init,
 	.init_machine	= edb7211_init,
 	.handle_irq	= clps711x_handle_irq,
 	.restart	= clps711x_restart,
diff --git a/arch/arm/mach-clps711x/board-fortunet.c b/arch/arm/mach-clps711x/board-fortunet.c
index 7d01255..c5675ef 100644
--- a/arch/arm/mach-clps711x/board-fortunet.c
+++ b/arch/arm/mach-clps711x/board-fortunet.c
@@ -78,7 +78,7 @@
 	.fixup		= fortunet_fixup,
 	.map_io		= clps711x_map_io,
 	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
+	.init_time	= clps711x_timer_init,
 	.handle_irq	= clps711x_handle_irq,
 	.restart	= clps711x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-clps711x/board-p720t.c b/arch/arm/mach-clps711x/board-p720t.c
index 1518fc8..8d3ee67 100644
--- a/arch/arm/mach-clps711x/board-p720t.c
+++ b/arch/arm/mach-clps711x/board-p720t.c
@@ -224,7 +224,7 @@
 	.map_io		= p720t_map_io,
 	.init_early	= p720t_init_early,
 	.init_irq	= clps711x_init_irq,
-	.timer		= &clps711x_timer,
+	.init_time	= clps711x_timer_init,
 	.init_machine	= p720t_init,
 	.init_late	= p720t_init_late,
 	.handle_irq	= clps711x_handle_irq,
diff --git a/arch/arm/mach-clps711x/common.c b/arch/arm/mach-clps711x/common.c
index e046439..20ff50f 100644
--- a/arch/arm/mach-clps711x/common.c
+++ b/arch/arm/mach-clps711x/common.c
@@ -282,7 +282,7 @@
 	clk_register_clkdev(clk, name, NULL);
 }
 
-static void __init clps711x_timer_init(void)
+void __init clps711x_timer_init(void)
 {
 	int osc, ext, pll, cpu, bus, timl, timh, uart, spi;
 	u32 tmp;
@@ -345,10 +345,6 @@
 	setup_irq(IRQ_TC2OI, &clps711x_timer_irq);
 }
 
-struct sys_timer clps711x_timer = {
-	.init		= clps711x_timer_init,
-};
-
 void clps711x_restart(char mode, const char *cmd)
 {
 	soft_restart(0);
diff --git a/arch/arm/mach-clps711x/common.h b/arch/arm/mach-clps711x/common.h
index b7c0c75..f84a729 100644
--- a/arch/arm/mach-clps711x/common.h
+++ b/arch/arm/mach-clps711x/common.h
@@ -8,10 +8,8 @@
 #define CLPS711X_NR_GPIO	(4 * 8 + 3)
 #define CLPS711X_GPIO(prt, bit)	((prt) * 8 + (bit))
 
-struct sys_timer;
-
 extern void clps711x_map_io(void);
 extern void clps711x_init_irq(void);
+extern void clps711x_timer_init(void);
 extern void clps711x_handle_irq(struct pt_regs *regs);
 extern void clps711x_restart(char mode, const char *cmd);
-extern struct sys_timer clps711x_timer;
diff --git a/arch/arm/mach-cns3xxx/cns3420vb.c b/arch/arm/mach-cns3xxx/cns3420vb.c
index ae30539..a71867e 100644
--- a/arch/arm/mach-cns3xxx/cns3420vb.c
+++ b/arch/arm/mach-cns3xxx/cns3420vb.c
@@ -28,7 +28,6 @@
 #include <linux/usb/ohci_pdriver.h>
 #include <asm/setup.h>
 #include <asm/mach-types.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
@@ -250,8 +249,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= cns3420_map_io,
 	.init_irq	= cns3xxx_init_irq,
-	.timer		= &cns3xxx_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= cns3xxx_timer_init,
 	.init_machine	= cns3420_init,
 	.restart	= cns3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-cns3xxx/core.c b/arch/arm/mach-cns3xxx/core.c
index 3eb74d1..e698f26 100644
--- a/arch/arm/mach-cns3xxx/core.c
+++ b/arch/arm/mach-cns3xxx/core.c
@@ -12,10 +12,10 @@
 #include <linux/interrupt.h>
 #include <linux/clockchips.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/mach/irq.h>
-#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <mach/cns3xxx.h>
 #include "core.h"
@@ -228,17 +228,13 @@
 	cns3xxx_clockevents_init(timer_irq);
 }
 
-static void __init cns3xxx_timer_init(void)
+void __init cns3xxx_timer_init(void)
 {
 	cns3xxx_tmr1 = IOMEM(CNS3XXX_TIMER1_2_3_BASE_VIRT);
 
 	__cns3xxx_timer_init(IRQ_CNS3XXX_TIMER0);
 }
 
-struct sys_timer cns3xxx_timer = {
-	.init = cns3xxx_timer_init,
-};
-
 #ifdef CONFIG_CACHE_L2X0
 
 void __init cns3xxx_l2x0_init(void)
diff --git a/arch/arm/mach-cns3xxx/core.h b/arch/arm/mach-cns3xxx/core.h
index 4894b8c..b23b17b 100644
--- a/arch/arm/mach-cns3xxx/core.h
+++ b/arch/arm/mach-cns3xxx/core.h
@@ -11,7 +11,7 @@
 #ifndef __CNS3XXX_CORE_H
 #define __CNS3XXX_CORE_H
 
-extern struct sys_timer cns3xxx_timer;
+extern void cns3xxx_timer_init(void);
 
 #ifdef CONFIG_CACHE_L2X0
 void __init cns3xxx_l2x0_init(void);
diff --git a/arch/arm/mach-davinci/board-da830-evm.c b/arch/arm/mach-davinci/board-da830-evm.c
index 95b5e10..6da25ee 100644
--- a/arch/arm/mach-davinci/board-da830-evm.c
+++ b/arch/arm/mach-davinci/board-da830-evm.c
@@ -652,8 +652,13 @@
 	if (ret)
 		pr_warning("da830_evm_init: rtc setup failed: %d\n", ret);
 
-	ret = da8xx_register_spi(0, da830evm_spi_info,
-				 ARRAY_SIZE(da830evm_spi_info));
+	ret = spi_register_board_info(da830evm_spi_info,
+				      ARRAY_SIZE(da830evm_spi_info));
+	if (ret)
+		pr_warn("%s: spi info registration failed: %d\n", __func__,
+			ret);
+
+	ret = da8xx_register_spi_bus(0, ARRAY_SIZE(da830evm_spi_info));
 	if (ret)
 		pr_warning("da830_evm_init: spi 0 registration failed: %d\n",
 			   ret);
@@ -679,7 +684,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= da830_evm_map_io,
 	.init_irq	= cp_intc_init,
-	.timer		= &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine	= da830_evm_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-da850-evm.c b/arch/arm/mach-davinci/board-da850-evm.c
index 0299915..3a76a47 100644
--- a/arch/arm/mach-davinci/board-da850-evm.c
+++ b/arch/arm/mach-davinci/board-da850-evm.c
@@ -1565,8 +1565,13 @@
 
 	da850_vpif_init();
 
-	ret = da8xx_register_spi(1, da850evm_spi_info,
-				 ARRAY_SIZE(da850evm_spi_info));
+	ret = spi_register_board_info(da850evm_spi_info,
+				      ARRAY_SIZE(da850evm_spi_info));
+	if (ret)
+		pr_warn("%s: spi info registration failed: %d\n", __func__,
+			ret);
+
+	ret = da8xx_register_spi_bus(1, ARRAY_SIZE(da850evm_spi_info));
 	if (ret)
 		pr_warning("da850_evm_init: spi 1 registration failed: %d\n",
 				ret);
@@ -1599,7 +1604,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= da850_evm_map_io,
 	.init_irq	= cp_intc_init,
-	.timer		= &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine	= da850_evm_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-dm355-evm.c b/arch/arm/mach-davinci/board-dm355-evm.c
index cdf8d07..147b8e1 100644
--- a/arch/arm/mach-davinci/board-dm355-evm.c
+++ b/arch/arm/mach-davinci/board-dm355-evm.c
@@ -355,7 +355,7 @@
 	.atag_offset  = 0x100,
 	.map_io	      = dm355_evm_map_io,
 	.init_irq     = davinci_irq_init,
-	.timer	      = &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine = dm355_evm_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-dm355-leopard.c b/arch/arm/mach-davinci/board-dm355-leopard.c
index d419545..dff4ddc 100644
--- a/arch/arm/mach-davinci/board-dm355-leopard.c
+++ b/arch/arm/mach-davinci/board-dm355-leopard.c
@@ -274,7 +274,7 @@
 	.atag_offset  = 0x100,
 	.map_io	      = dm355_leopard_map_io,
 	.init_irq     = davinci_irq_init,
-	.timer	      = &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine = dm355_leopard_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-dm365-evm.c b/arch/arm/mach-davinci/board-dm365-evm.c
index 5d49c75..c2d4958 100644
--- a/arch/arm/mach-davinci/board-dm365-evm.c
+++ b/arch/arm/mach-davinci/board-dm365-evm.c
@@ -616,7 +616,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= dm365_evm_map_io,
 	.init_irq	= davinci_irq_init,
-	.timer		= &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine	= dm365_evm_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-dm644x-evm.c b/arch/arm/mach-davinci/board-dm644x-evm.c
index f5e018d..e4a16f9 100644
--- a/arch/arm/mach-davinci/board-dm644x-evm.c
+++ b/arch/arm/mach-davinci/board-dm644x-evm.c
@@ -825,7 +825,7 @@
 	.atag_offset  = 0x100,
 	.map_io	      = davinci_evm_map_io,
 	.init_irq     = davinci_irq_init,
-	.timer	      = &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine = davinci_evm_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-dm646x-evm.c b/arch/arm/mach-davinci/board-dm646x-evm.c
index 6e2f163..de7adff 100644
--- a/arch/arm/mach-davinci/board-dm646x-evm.c
+++ b/arch/arm/mach-davinci/board-dm646x-evm.c
@@ -818,7 +818,7 @@
 	.atag_offset  = 0x100,
 	.map_io       = davinci_map_io,
 	.init_irq     = davinci_irq_init,
-	.timer        = &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine = evm_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
@@ -829,7 +829,7 @@
 	.atag_offset  = 0x100,
 	.map_io       = davinci_map_io,
 	.init_irq     = davinci_irq_init,
-	.timer        = &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine = evm_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-mityomapl138.c b/arch/arm/mach-davinci/board-mityomapl138.c
index 43e4a0d..9549d53 100644
--- a/arch/arm/mach-davinci/board-mityomapl138.c
+++ b/arch/arm/mach-davinci/board-mityomapl138.c
@@ -529,8 +529,13 @@
 
 	mityomapl138_setup_nand();
 
-	ret = da8xx_register_spi(1, mityomapl138_spi_flash_info,
-			       ARRAY_SIZE(mityomapl138_spi_flash_info));
+	ret = spi_register_board_info(mityomapl138_spi_flash_info,
+				      ARRAY_SIZE(mityomapl138_spi_flash_info));
+	if (ret)
+		pr_warn("spi info registration failed: %d\n", ret);
+
+	ret = da8xx_register_spi_bus(1,
+				     ARRAY_SIZE(mityomapl138_spi_flash_info));
 	if (ret)
 		pr_warning("spi 1 registration failed: %d\n", ret);
 
@@ -570,7 +575,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= mityomapl138_map_io,
 	.init_irq	= cp_intc_init,
-	.timer		= &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine	= mityomapl138_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-neuros-osd2.c b/arch/arm/mach-davinci/board-neuros-osd2.c
index 3e3e3af..1c98107 100644
--- a/arch/arm/mach-davinci/board-neuros-osd2.c
+++ b/arch/arm/mach-davinci/board-neuros-osd2.c
@@ -237,7 +237,7 @@
 	.atag_offset	= 0x100,
 	.map_io		 = davinci_ntosd2_map_io,
 	.init_irq	= davinci_irq_init,
-	.timer		= &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine = davinci_ntosd2_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-omapl138-hawk.c b/arch/arm/mach-davinci/board-omapl138-hawk.c
index dc1208e..deb3922 100644
--- a/arch/arm/mach-davinci/board-omapl138-hawk.c
+++ b/arch/arm/mach-davinci/board-omapl138-hawk.c
@@ -341,7 +341,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= omapl138_hawk_map_io,
 	.init_irq	= cp_intc_init,
-	.timer		= &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine	= omapl138_hawk_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-sffsdr.c b/arch/arm/mach-davinci/board-sffsdr.c
index 6957787..739be7e 100644
--- a/arch/arm/mach-davinci/board-sffsdr.c
+++ b/arch/arm/mach-davinci/board-sffsdr.c
@@ -155,7 +155,7 @@
 	.atag_offset  = 0x100,
 	.map_io	      = davinci_sffsdr_map_io,
 	.init_irq     = davinci_irq_init,
-	.timer	      = &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine = davinci_sffsdr_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/board-tnetv107x-evm.c b/arch/arm/mach-davinci/board-tnetv107x-evm.c
index be30997..4f41602 100644
--- a/arch/arm/mach-davinci/board-tnetv107x-evm.c
+++ b/arch/arm/mach-davinci/board-tnetv107x-evm.c
@@ -280,7 +280,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= tnetv107x_init,
 	.init_irq	= cp_intc_init,
-	.timer		= &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine	= tnetv107x_evm_board_init,
 	.init_late	= davinci_init_late,
 	.dma_zone_size	= SZ_128M,
diff --git a/arch/arm/mach-davinci/clock.c b/arch/arm/mach-davinci/clock.c
index 34668ea..d458558 100644
--- a/arch/arm/mach-davinci/clock.c
+++ b/arch/arm/mach-davinci/clock.c
@@ -52,6 +52,40 @@
 		__clk_disable(clk->parent);
 }
 
+int davinci_clk_reset(struct clk *clk, bool reset)
+{
+	unsigned long flags;
+
+	if (clk == NULL || IS_ERR(clk))
+		return -EINVAL;
+
+	spin_lock_irqsave(&clockfw_lock, flags);
+	if (clk->flags & CLK_PSC)
+		davinci_psc_reset(clk->gpsc, clk->lpsc, reset);
+	spin_unlock_irqrestore(&clockfw_lock, flags);
+
+	return 0;
+}
+EXPORT_SYMBOL(davinci_clk_reset);
+
+int davinci_clk_reset_assert(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk) || !clk->reset)
+		return -EINVAL;
+
+	return clk->reset(clk, true);
+}
+EXPORT_SYMBOL(davinci_clk_reset_assert);
+
+int davinci_clk_reset_deassert(struct clk *clk)
+{
+	if (clk == NULL || IS_ERR(clk) || !clk->reset)
+		return -EINVAL;
+
+	return clk->reset(clk, false);
+}
+EXPORT_SYMBOL(davinci_clk_reset_deassert);
+
 int clk_enable(struct clk *clk)
 {
 	unsigned long flags;
@@ -535,7 +569,7 @@
 }
 
 int __init davinci_clk_init(struct clk_lookup *clocks)
-  {
+{
 	struct clk_lookup *c;
 	struct clk *clk;
 	size_t num_clocks = 0;
@@ -576,6 +610,9 @@
 		if (clk->lpsc)
 			clk->flags |= CLK_PSC;
 
+		if (clk->flags & PSC_LRST)
+			clk->reset = davinci_clk_reset;
+
 		clk_register(clk);
 		num_clocks++;
 
diff --git a/arch/arm/mach-davinci/clock.h b/arch/arm/mach-davinci/clock.h
index 46f0f1b..8694b39 100644
--- a/arch/arm/mach-davinci/clock.h
+++ b/arch/arm/mach-davinci/clock.h
@@ -103,6 +103,7 @@
 	unsigned long (*recalc) (struct clk *);
 	int (*set_rate) (struct clk *clk, unsigned long rate);
 	int (*round_rate) (struct clk *clk, unsigned long rate);
+	int (*reset) (struct clk *clk, bool reset);
 };
 
 /* Clock flags: SoC-specific flags start at BIT(16) */
@@ -112,6 +113,7 @@
 #define PRE_PLL			BIT(4) /* source is before PLL mult/div */
 #define PSC_SWRSTDISABLE	BIT(5) /* Disable state is SwRstDisable */
 #define PSC_FORCE		BIT(6) /* Force module state transtition */
+#define PSC_LRST		BIT(8) /* Use local reset on enable/disable */
 
 #define CLK(dev, con, ck) 	\
 	{			\
@@ -126,6 +128,7 @@
 int davinci_set_sysclk_rate(struct clk *clk, unsigned long rate);
 int davinci_set_refclk_rate(unsigned long rate);
 int davinci_simple_set_rate(struct clk *clk, unsigned long rate);
+int davinci_clk_reset(struct clk *clk, bool reset);
 
 extern struct platform_device davinci_wdt_device;
 extern void davinci_watchdog_reset(struct platform_device *);
diff --git a/arch/arm/mach-davinci/da850.c b/arch/arm/mach-davinci/da850.c
index 6b9154e..0c4a26d 100644
--- a/arch/arm/mach-davinci/da850.c
+++ b/arch/arm/mach-davinci/da850.c
@@ -76,6 +76,13 @@
 	.flags		= CLK_PLL | PRE_PLL,
 };
 
+static struct clk pll0_sysclk1 = {
+	.name		= "pll0_sysclk1",
+	.parent		= &pll0_clk,
+	.flags		= CLK_PLL,
+	.div_reg	= PLLDIV1,
+};
+
 static struct clk pll0_sysclk2 = {
 	.name		= "pll0_sysclk2",
 	.parent		= &pll0_clk,
@@ -368,10 +375,19 @@
 	.flags		= PSC_FORCE,
 };
 
+static struct clk dsp_clk = {
+	.name		= "dsp",
+	.parent		= &pll0_sysclk1,
+	.domain		= DAVINCI_GPSC_DSPDOMAIN,
+	.lpsc		= DA8XX_LPSC0_GEM,
+	.flags		= PSC_LRST | PSC_FORCE,
+};
+
 static struct clk_lookup da850_clks[] = {
 	CLK(NULL,		"ref",		&ref_clk),
 	CLK(NULL,		"pll0",		&pll0_clk),
 	CLK(NULL,		"pll0_aux",	&pll0_aux_clk),
+	CLK(NULL,		"pll0_sysclk1",	&pll0_sysclk1),
 	CLK(NULL,		"pll0_sysclk2",	&pll0_sysclk2),
 	CLK(NULL,		"pll0_sysclk3",	&pll0_sysclk3),
 	CLK(NULL,		"pll0_sysclk4",	&pll0_sysclk4),
@@ -413,6 +429,7 @@
 	CLK("spi_davinci.1",	NULL,		&spi1_clk),
 	CLK("vpif",		NULL,		&vpif_clk),
 	CLK("ahci",		NULL,		&sata_clk),
+	CLK("davinci-rproc.0",	NULL,		&dsp_clk),
 	CLK(NULL,		NULL,		NULL),
 };
 
diff --git a/arch/arm/mach-davinci/da8xx-dt.c b/arch/arm/mach-davinci/da8xx-dt.c
index 37c27af..9a7c76e 100644
--- a/arch/arm/mach-davinci/da8xx-dt.c
+++ b/arch/arm/mach-davinci/da8xx-dt.c
@@ -56,7 +56,7 @@
 DT_MACHINE_START(DA850_DT, "Generic DA850/OMAP-L138/AM18x")
 	.map_io		= da850_init,
 	.init_irq	= da8xx_init_irq,
-	.timer		= &davinci_timer,
+	.init_time	= davinci_timer_init,
 	.init_machine	= da850_init_machine,
 	.dt_compat	= da850_boards_compat,
 	.init_late	= davinci_init_late,
diff --git a/arch/arm/mach-davinci/devices-da8xx.c b/arch/arm/mach-davinci/devices-da8xx.c
index 2d5502d..aa402bc 100644
--- a/arch/arm/mach-davinci/devices-da8xx.c
+++ b/arch/arm/mach-davinci/devices-da8xx.c
@@ -751,7 +751,7 @@
 
 	da8xx_ddr2_ctlr_base = ioremap(DA8XX_DDR2_CTL_BASE, SZ_32K);
 	if (!da8xx_ddr2_ctlr_base)
-		pr_warning("%s: Unable to map DDR2 controller",	__func__);
+		pr_warn("%s: Unable to map DDR2 controller", __func__);
 
 	return da8xx_ddr2_ctlr_base;
 }
@@ -832,7 +832,7 @@
 	},
 };
 
-struct davinci_spi_platform_data da8xx_spi_pdata[] = {
+static struct davinci_spi_platform_data da8xx_spi_pdata[] = {
 	[0] = {
 		.version	= SPI_VERSION_2,
 		.intr_line	= 1,
@@ -866,20 +866,12 @@
 	},
 };
 
-int __init da8xx_register_spi(int instance, const struct spi_board_info *info,
-			      unsigned len)
+int __init da8xx_register_spi_bus(int instance, unsigned num_chipselect)
 {
-	int ret;
-
 	if (instance < 0 || instance > 1)
 		return -EINVAL;
 
-	ret = spi_register_board_info(info, len);
-	if (ret)
-		pr_warning("%s: failed to register board info for spi %d :"
-			   " %d\n", __func__, instance, ret);
-
-	da8xx_spi_pdata[instance].num_chipselect = len;
+	da8xx_spi_pdata[instance].num_chipselect = num_chipselect;
 
 	if (instance == 1 && cpu_is_davinci_da850()) {
 		da8xx_spi1_resources[0].start = DA850_SPI1_BASE;
diff --git a/arch/arm/mach-davinci/include/mach/clock.h b/arch/arm/mach-davinci/include/mach/clock.h
index a3b0402..3e8af6a 100644
--- a/arch/arm/mach-davinci/include/mach/clock.h
+++ b/arch/arm/mach-davinci/include/mach/clock.h
@@ -18,4 +18,7 @@
 extern int clk_register(struct clk *clk);
 extern void clk_unregister(struct clk *clk);
 
+int davinci_clk_reset_assert(struct clk *c);
+int davinci_clk_reset_deassert(struct clk *c);
+
 #endif
diff --git a/arch/arm/mach-davinci/include/mach/common.h b/arch/arm/mach-davinci/include/mach/common.h
index 046c723..b124b77 100644
--- a/arch/arm/mach-davinci/include/mach/common.h
+++ b/arch/arm/mach-davinci/include/mach/common.h
@@ -15,9 +15,7 @@
 #include <linux/compiler.h>
 #include <linux/types.h>
 
-struct sys_timer;
-
-extern struct sys_timer davinci_timer;
+extern void davinci_timer_init(void);
 
 extern void davinci_irq_init(void);
 extern void __iomem *davinci_intc_base;
diff --git a/arch/arm/mach-davinci/include/mach/da8xx.h b/arch/arm/mach-davinci/include/mach/da8xx.h
index 700d311..1b14aea 100644
--- a/arch/arm/mach-davinci/include/mach/da8xx.h
+++ b/arch/arm/mach-davinci/include/mach/da8xx.h
@@ -82,8 +82,7 @@
 int da830_register_edma(struct edma_rsv_info *rsv);
 int da850_register_edma(struct edma_rsv_info *rsv[2]);
 int da8xx_register_i2c(int instance, struct davinci_i2c_platform_data *pdata);
-int da8xx_register_spi(int instance,
-		const struct spi_board_info *info, unsigned len);
+int da8xx_register_spi_bus(int instance, unsigned num_chipselect);
 int da8xx_register_watchdog(void);
 int da8xx_register_usb20(unsigned mA, unsigned potpgt);
 int da8xx_register_usb11(struct da8xx_ohci_root_hub *pdata);
@@ -110,7 +109,6 @@
 extern struct emac_platform_data da8xx_emac_pdata;
 extern struct da8xx_lcdc_platform_data sharp_lcd035q3dg01_pdata;
 extern struct da8xx_lcdc_platform_data sharp_lk043t1dg01_pdata;
-extern struct davinci_spi_platform_data da8xx_spi_pdata[];
 
 extern struct platform_device da8xx_wdt_device;
 
diff --git a/arch/arm/mach-davinci/include/mach/psc.h b/arch/arm/mach-davinci/include/mach/psc.h
index 40a0027..0a22710 100644
--- a/arch/arm/mach-davinci/include/mach/psc.h
+++ b/arch/arm/mach-davinci/include/mach/psc.h
@@ -246,6 +246,7 @@
 
 #define MDSTAT_STATE_MASK	0x3f
 #define PDSTAT_STATE_MASK	0x1f
+#define MDCTL_LRST		BIT(8)
 #define MDCTL_FORCE		BIT(31)
 #define PDCTL_NEXT		BIT(0)
 #define PDCTL_EPCGOOD		BIT(8)
@@ -253,6 +254,8 @@
 #ifndef __ASSEMBLER__
 
 extern int davinci_psc_is_clk_active(unsigned int ctlr, unsigned int id);
+extern void davinci_psc_reset(unsigned int ctlr, unsigned int id,
+		bool reset);
 extern void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 		unsigned int id, bool enable, u32 flags);
 
diff --git a/arch/arm/mach-davinci/psc.c b/arch/arm/mach-davinci/psc.c
index d7e210f..82fdc69 100644
--- a/arch/arm/mach-davinci/psc.c
+++ b/arch/arm/mach-davinci/psc.c
@@ -35,7 +35,7 @@
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
 
 	if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
-		pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
+		pr_warn("PSC: Bad psc data: 0x%x[%d]\n",
 				(int)soc_info->psc_bases, ctlr);
 		return 0;
 	}
@@ -48,6 +48,31 @@
 	return mdstat & BIT(12);
 }
 
+/* Control "reset" line associated with PSC domain */
+void davinci_psc_reset(unsigned int ctlr, unsigned int id, bool reset)
+{
+	u32 mdctl;
+	void __iomem *psc_base;
+	struct davinci_soc_info *soc_info = &davinci_soc_info;
+
+	if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
+		pr_warn("PSC: Bad psc data: 0x%x[%d]\n",
+				(int)soc_info->psc_bases, ctlr);
+		return;
+	}
+
+	psc_base = ioremap(soc_info->psc_bases[ctlr], SZ_4K);
+
+	mdctl = readl(psc_base + MDCTL + 4 * id);
+	if (reset)
+		mdctl &= ~MDCTL_LRST;
+	else
+		mdctl |= MDCTL_LRST;
+	writel(mdctl, psc_base + MDCTL + 4 * id);
+
+	iounmap(psc_base);
+}
+
 /* Enable or disable a PSC domain */
 void davinci_psc_config(unsigned int domain, unsigned int ctlr,
 		unsigned int id, bool enable, u32 flags)
@@ -58,7 +83,7 @@
 	u32 next_state = PSC_STATE_ENABLE;
 
 	if (!soc_info->psc_bases || (ctlr >= soc_info->psc_bases_num)) {
-		pr_warning("PSC: Bad psc data: 0x%x[%d]\n",
+		pr_warn("PSC: Bad psc data: 0x%x[%d]\n",
 				(int)soc_info->psc_bases, ctlr);
 		return;
 	}
diff --git a/arch/arm/mach-davinci/time.c b/arch/arm/mach-davinci/time.c
index 9847938..bad361e 100644
--- a/arch/arm/mach-davinci/time.c
+++ b/arch/arm/mach-davinci/time.c
@@ -337,7 +337,7 @@
 };
 
 
-static void __init davinci_timer_init(void)
+void __init davinci_timer_init(void)
 {
 	struct clk *timer_clk;
 	struct davinci_soc_info *soc_info = &davinci_soc_info;
@@ -410,11 +410,6 @@
 		timer32_config(&timers[i]);
 }
 
-struct sys_timer davinci_timer = {
-	.init   = davinci_timer_init,
-};
-
-
 /* reset board using watchdog timer */
 void davinci_watchdog_reset(struct platform_device *pdev)
 {
diff --git a/arch/arm/mach-dove/cm-a510.c b/arch/arm/mach-dove/cm-a510.c
index 792b4e2..0dc39cf 100644
--- a/arch/arm/mach-dove/cm-a510.c
+++ b/arch/arm/mach-dove/cm-a510.c
@@ -92,6 +92,6 @@
 	.map_io		= dove_map_io,
 	.init_early	= dove_init_early,
 	.init_irq	= dove_init_irq,
-	.timer		= &dove_timer,
+	.init_time	= dove_timer_init,
 	.restart	= dove_restart,
 MACHINE_END
diff --git a/arch/arm/mach-dove/common.c b/arch/arm/mach-dove/common.c
index 89f4f99..0c7911b 100644
--- a/arch/arm/mach-dove/common.c
+++ b/arch/arm/mach-dove/common.c
@@ -242,17 +242,13 @@
 	return 166666667;
 }
 
-static void __init dove_timer_init(void)
+void __init dove_timer_init(void)
 {
 	dove_tclk = dove_find_tclk();
 	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
 			IRQ_DOVE_BRIDGE, dove_tclk);
 }
 
-struct sys_timer dove_timer = {
-	.init = dove_timer_init,
-};
-
 /*****************************************************************************
  * Cryptographic Engines and Security Accelerator (CESA)
  ****************************************************************************/
@@ -454,7 +450,7 @@
 	.map_io		= dove_map_io,
 	.init_early	= dove_init_early,
 	.init_irq	= orion_dt_init_irq,
-	.timer		= &dove_timer,
+	.init_time	= dove_timer_init,
 	.init_machine	= dove_dt_init,
 	.restart	= dove_restart,
 	.dt_compat	= dove_dt_board_compat,
diff --git a/arch/arm/mach-dove/common.h b/arch/arm/mach-dove/common.h
index 1a23340..ee59fba 100644
--- a/arch/arm/mach-dove/common.h
+++ b/arch/arm/mach-dove/common.h
@@ -14,7 +14,7 @@
 struct mv643xx_eth_platform_data;
 struct mv_sata_platform_data;
 
-extern struct sys_timer dove_timer;
+extern void dove_timer_init(void);
 
 /*
  * Basic Dove init functions used early by machine-setup.
diff --git a/arch/arm/mach-dove/dove-db-setup.c b/arch/arm/mach-dove/dove-db-setup.c
index bc2867f..76e26f9 100644
--- a/arch/arm/mach-dove/dove-db-setup.c
+++ b/arch/arm/mach-dove/dove-db-setup.c
@@ -98,6 +98,6 @@
 	.map_io		= dove_map_io,
 	.init_early	= dove_init_early,
 	.init_irq	= dove_init_irq,
-	.timer		= &dove_timer,
+	.init_time	= dove_timer_init,
 	.restart	= dove_restart,
 MACHINE_END
diff --git a/arch/arm/mach-ebsa110/core.c b/arch/arm/mach-ebsa110/core.c
index f0fe6b5..b13cc74 100644
--- a/arch/arm/mach-ebsa110/core.c
+++ b/arch/arm/mach-ebsa110/core.c
@@ -158,7 +158,7 @@
  * interrupt, then the PIT counter will roll over (ie, be negative).
  * This actually works out to be convenient.
  */
-static unsigned long ebsa110_gettimeoffset(void)
+static u32 ebsa110_gettimeoffset(void)
 {
 	unsigned long offset, count;
 
@@ -181,7 +181,7 @@
 	 */
 	offset = offset * (1000000 / HZ) / COUNT;
 
-	return offset;
+	return offset * 1000;
 }
 
 static irqreturn_t
@@ -213,8 +213,10 @@
 /*
  * Set up timer interrupt.
  */
-static void __init ebsa110_timer_init(void)
+void __init ebsa110_timer_init(void)
 {
+	arch_gettimeoffset = ebsa110_gettimeoffset;
+
 	/*
 	 * Timer 1, mode 2, LSB/MSB
 	 */
@@ -225,11 +227,6 @@
 	setup_irq(IRQ_EBSA110_TIMER0, &ebsa110_timer_irq);
 }
 
-static struct sys_timer ebsa110_timer = {
-	.init		= ebsa110_timer_init,
-	.offset		= ebsa110_gettimeoffset,
-};
-
 static struct plat_serial8250_port serial_platform_data[] = {
 	{
 		.iobase		= 0x3f8,
@@ -328,6 +325,6 @@
 	.map_io		= ebsa110_map_io,
 	.init_early	= ebsa110_init_early,
 	.init_irq	= ebsa110_init_irq,
-	.timer		= &ebsa110_timer,
+	.init_time	= ebsa110_timer_init,
 	.restart	= ebsa110_restart,
 MACHINE_END
diff --git a/arch/arm/mach-ep93xx/adssphere.c b/arch/arm/mach-ep93xx/adssphere.c
index 41383bf..bda6c3a 100644
--- a/arch/arm/mach-ep93xx/adssphere.c
+++ b/arch/arm/mach-ep93xx/adssphere.c
@@ -17,7 +17,6 @@
 
 #include <mach/hardware.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -39,8 +38,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= adssphere_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
diff --git a/arch/arm/mach-ep93xx/core.c b/arch/arm/mach-ep93xx/core.c
index e85bf17..c49ed3d 100644
--- a/arch/arm/mach-ep93xx/core.c
+++ b/arch/arm/mach-ep93xx/core.c
@@ -34,6 +34,7 @@
 #include <linux/i2c-gpio.h>
 #include <linux/spi/spi.h>
 #include <linux/export.h>
+#include <linux/irqchip/arm-vic.h>
 
 #include <mach/hardware.h>
 #include <linux/platform_data/video-ep93xx.h>
@@ -44,8 +45,6 @@
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
 
-#include <asm/hardware/vic.h>
-
 #include "soc.h"
 
 /*************************************************************************
@@ -140,11 +139,29 @@
 	.handler	= ep93xx_timer_interrupt,
 };
 
-static void __init ep93xx_timer_init(void)
+static u32 ep93xx_gettimeoffset(void)
+{
+	int offset;
+
+	offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
+
+	/*
+	 * Timer 4 is based on a 983.04 kHz reference clock,
+	 * so dividing by 983040 gives the fraction of a second,
+	 * so dividing by 0.983040 converts to uS.
+	 * Refactor the calculation to avoid overflow.
+	 * Finally, multiply by 1000 to give nS.
+	 */
+	return (offset + (53 * offset / 3072)) * 1000;
+}
+
+void __init ep93xx_timer_init(void)
 {
 	u32 tmode = EP93XX_TIMER123_CONTROL_MODE |
 		    EP93XX_TIMER123_CONTROL_CLKSEL;
 
+	arch_gettimeoffset = ep93xx_gettimeoffset;
+
 	/* Enable periodic HZ timer.  */
 	__raw_writel(tmode, EP93XX_TIMER1_CONTROL);
 	__raw_writel(TIMER1_RELOAD, EP93XX_TIMER1_LOAD);
@@ -158,21 +175,6 @@
 	setup_irq(IRQ_EP93XX_TIMER1, &ep93xx_timer_irq);
 }
 
-static unsigned long ep93xx_gettimeoffset(void)
-{
-	int offset;
-
-	offset = __raw_readl(EP93XX_TIMER4_VALUE_LOW) - last_jiffy_time;
-
-	/* Calculate (1000000 / 983040) * offset.  */
-	return offset + (53 * offset / 3072);
-}
-
-struct sys_timer ep93xx_timer = {
-	.init		= ep93xx_timer_init,
-	.offset		= ep93xx_gettimeoffset,
-};
-
 
 /*************************************************************************
  * EP93xx IRQ handling
diff --git a/arch/arm/mach-ep93xx/edb93xx.c b/arch/arm/mach-ep93xx/edb93xx.c
index b8f53d5..27b14ae 100644
--- a/arch/arm/mach-ep93xx/edb93xx.c
+++ b/arch/arm/mach-ep93xx/edb93xx.c
@@ -39,7 +39,6 @@
 #include <linux/platform_data/spi-ep93xx.h>
 #include <mach/gpio-ep93xx.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -276,8 +275,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= edb93xx_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
@@ -290,8 +288,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= edb93xx_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
@@ -304,8 +301,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= edb93xx_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
@@ -318,8 +314,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= edb93xx_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
@@ -332,8 +327,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= edb93xx_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
@@ -346,8 +340,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= edb93xx_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
@@ -360,8 +353,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= edb93xx_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
@@ -374,8 +366,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= edb93xx_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
diff --git a/arch/arm/mach-ep93xx/gesbc9312.c b/arch/arm/mach-ep93xx/gesbc9312.c
index 7fd705b..0cca5b1 100644
--- a/arch/arm/mach-ep93xx/gesbc9312.c
+++ b/arch/arm/mach-ep93xx/gesbc9312.c
@@ -17,7 +17,6 @@
 
 #include <mach/hardware.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -39,8 +38,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= gesbc9312_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
diff --git a/arch/arm/mach-ep93xx/include/mach/platform.h b/arch/arm/mach-ep93xx/include/mach/platform.h
index 33a5122..a14e1b3 100644
--- a/arch/arm/mach-ep93xx/include/mach/platform.h
+++ b/arch/arm/mach-ep93xx/include/mach/platform.h
@@ -53,7 +53,7 @@
 void ep93xx_ide_release_gpio(struct platform_device *pdev);
 
 void ep93xx_init_devices(void);
-extern struct sys_timer ep93xx_timer;
+extern void ep93xx_timer_init(void);
 
 void ep93xx_restart(char, const char *);
 void ep93xx_init_late(void);
diff --git a/arch/arm/mach-ep93xx/micro9.c b/arch/arm/mach-ep93xx/micro9.c
index 3d7cdab..373583c 100644
--- a/arch/arm/mach-ep93xx/micro9.c
+++ b/arch/arm/mach-ep93xx/micro9.c
@@ -18,7 +18,6 @@
 
 #include <mach/hardware.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -82,8 +81,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= micro9_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
@@ -96,8 +94,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= micro9_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
@@ -110,8 +107,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= micro9_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
@@ -124,8 +120,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= micro9_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
diff --git a/arch/arm/mach-ep93xx/simone.c b/arch/arm/mach-ep93xx/simone.c
index 0eb3f17..36f22c1 100644
--- a/arch/arm/mach-ep93xx/simone.c
+++ b/arch/arm/mach-ep93xx/simone.c
@@ -25,7 +25,6 @@
 #include <linux/platform_data/video-ep93xx.h>
 #include <mach/gpio-ep93xx.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -83,8 +82,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= simone_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
diff --git a/arch/arm/mach-ep93xx/snappercl15.c b/arch/arm/mach-ep93xx/snappercl15.c
index 50043ee..aa86f86 100644
--- a/arch/arm/mach-ep93xx/snappercl15.c
+++ b/arch/arm/mach-ep93xx/snappercl15.c
@@ -31,7 +31,6 @@
 #include <linux/platform_data/video-ep93xx.h>
 #include <mach/gpio-ep93xx.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -176,8 +175,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ep93xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer 		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= snappercl15_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
diff --git a/arch/arm/mach-ep93xx/ts72xx.c b/arch/arm/mach-ep93xx/ts72xx.c
index 3c4c233..61f4b5d 100644
--- a/arch/arm/mach-ep93xx/ts72xx.c
+++ b/arch/arm/mach-ep93xx/ts72xx.c
@@ -22,7 +22,6 @@
 
 #include <mach/hardware.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
@@ -246,8 +245,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= ts72xx_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= ts72xx_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
diff --git a/arch/arm/mach-ep93xx/vision_ep9307.c b/arch/arm/mach-ep93xx/vision_ep9307.c
index ba92e25..605956f 100644
--- a/arch/arm/mach-ep93xx/vision_ep9307.c
+++ b/arch/arm/mach-ep93xx/vision_ep9307.c
@@ -34,7 +34,6 @@
 #include <linux/platform_data/spi-ep93xx.h>
 #include <mach/gpio-ep93xx.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
@@ -364,8 +363,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= vision_map_io,
 	.init_irq	= ep93xx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &ep93xx_timer,
+	.init_time	= ep93xx_timer_init,
 	.init_machine	= vision_init_machine,
 	.init_late	= ep93xx_init_late,
 	.restart	= ep93xx_restart,
diff --git a/arch/arm/mach-exynos/common.c b/arch/arm/mach-exynos/common.c
index 1a89824..4ea80bc 100644
--- a/arch/arm/mach-exynos/common.c
+++ b/arch/arm/mach-exynos/common.c
@@ -22,12 +22,13 @@
 #include <linux/of_irq.h>
 #include <linux/export.h>
 #include <linux/irqdomain.h>
+#include <linux/irqchip.h>
 #include <linux/of_address.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include <asm/proc-fns.h>
 #include <asm/exception.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
 #include <asm/cacheflush.h>
@@ -644,8 +645,6 @@
 }
 
 static const struct of_device_id exynos_dt_irq_match[] = {
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-	{ .compatible = "arm,cortex-a15-gic", .data = gic_of_init, },
 	{ .compatible = "samsung,exynos4210-combiner",
 			.data = combiner_of_init, },
 	{},
@@ -661,8 +660,10 @@
 	if (!of_have_populated_dt())
 		gic_init_bases(0, IRQ_PPI(0), S5P_VA_GIC_DIST, S5P_VA_GIC_CPU, gic_bank_offset, NULL);
 #ifdef CONFIG_OF
-	else
+	else {
+		irqchip_init();
 		of_irq_init(exynos_dt_irq_match);
+	}
 #endif
 
 	if (!of_have_populated_dt())
@@ -679,6 +680,7 @@
 void __init exynos5_init_irq(void)
 {
 #ifdef CONFIG_OF
+	irqchip_init();
 	of_irq_init(exynos_dt_irq_match);
 #endif
 	/*
diff --git a/arch/arm/mach-exynos/common.h b/arch/arm/mach-exynos/common.h
index 04744f9..12f2f11 100644
--- a/arch/arm/mach-exynos/common.h
+++ b/arch/arm/mach-exynos/common.h
@@ -12,7 +12,7 @@
 #ifndef __ARCH_ARM_MACH_EXYNOS_COMMON_H
 #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
 
-extern struct sys_timer exynos4_timer;
+extern void exynos4_timer_init(void);
 
 struct map_desc;
 void exynos_init_io(struct map_desc *mach_desc, int size);
diff --git a/arch/arm/mach-exynos/include/mach/regs-irq.h b/arch/arm/mach-exynos/include/mach/regs-irq.h
index 9c7b4bf..f2b5050 100644
--- a/arch/arm/mach-exynos/include/mach/regs-irq.h
+++ b/arch/arm/mach-exynos/include/mach/regs-irq.h
@@ -13,7 +13,7 @@
 #ifndef __ASM_ARCH_REGS_IRQ_H
 #define __ASM_ARCH_REGS_IRQ_H __FILE__
 
-#include <asm/hardware/gic.h>
+#include <linux/irqchip/arm-gic.h>
 #include <mach/map.h>
 
 #endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-exynos/mach-armlex4210.c b/arch/arm/mach-exynos/mach-armlex4210.c
index b938f9f..685f291 100644
--- a/arch/arm/mach-exynos/mach-armlex4210.c
+++ b/arch/arm/mach-exynos/mach-armlex4210.c
@@ -16,7 +16,6 @@
 #include <linux/smsc911x.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 
 #include <plat/cpu.h>
@@ -201,9 +200,8 @@
 	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= armlex4210_map_io,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= armlex4210_machine_init,
 	.init_late	= exynos_init_late,
-	.timer		= &exynos4_timer,
+	.init_time	= exynos4_timer_init,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-exynos4-dt.c b/arch/arm/mach-exynos/mach-exynos4-dt.c
index 92757ff..112d10e 100644
--- a/arch/arm/mach-exynos/mach-exynos4-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos4-dt.c
@@ -15,7 +15,6 @@
 #include <linux/serial_core.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 #include <mach/map.h>
 
 #include <plat/cpu.h>
@@ -107,10 +106,9 @@
 	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= exynos4_dt_map_io,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= exynos4_dt_machine_init,
 	.init_late	= exynos_init_late,
-	.timer		= &exynos4_timer,
+	.init_time	= exynos4_timer_init,
 	.dt_compat	= exynos4_dt_compat,
 	.restart        = exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-exynos5-dt.c b/arch/arm/mach-exynos/mach-exynos5-dt.c
index e99d3d8..0deeecf 100644
--- a/arch/arm/mach-exynos/mach-exynos5-dt.c
+++ b/arch/arm/mach-exynos/mach-exynos5-dt.c
@@ -16,7 +16,6 @@
 #include <linux/io.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 #include <mach/map.h>
 #include <mach/regs-pmu.h>
 
@@ -179,10 +178,9 @@
 	.init_irq	= exynos5_init_irq,
 	.smp		= smp_ops(exynos_smp_ops),
 	.map_io		= exynos5_dt_map_io,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= exynos5_dt_machine_init,
 	.init_late	= exynos_init_late,
-	.timer		= &exynos4_timer,
+	.init_time	= exynos4_timer_init,
 	.dt_compat	= exynos5_dt_compat,
 	.restart        = exynos5_restart,
 	.reserve	= exynos5_reserve,
diff --git a/arch/arm/mach-exynos/mach-nuri.c b/arch/arm/mach-exynos/mach-nuri.c
index 27d4ed8..b8b3fbf 100644
--- a/arch/arm/mach-exynos/mach-nuri.c
+++ b/arch/arm/mach-exynos/mach-nuri.c
@@ -39,7 +39,6 @@
 #include <media/v4l2-mediabus.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 
 #include <plat/adc.h>
@@ -1379,10 +1378,9 @@
 	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= nuri_map_io,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= nuri_machine_init,
 	.init_late	= exynos_init_late,
-	.timer		= &exynos4_timer,
+	.init_time	= exynos4_timer_init,
 	.reserve        = &nuri_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-origen.c b/arch/arm/mach-exynos/mach-origen.c
index 5e34b9c..579d2d1 100644
--- a/arch/arm/mach-exynos/mach-origen.c
+++ b/arch/arm/mach-exynos/mach-origen.c
@@ -29,7 +29,6 @@
 #include <linux/platform_data/usb-exynos.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 
 #include <video/platform_lcd.h>
@@ -814,10 +813,9 @@
 	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= origen_map_io,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= origen_machine_init,
 	.init_late	= exynos_init_late,
-	.timer		= &exynos4_timer,
+	.init_time	= exynos4_timer_init,
 	.reserve	= &origen_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-smdk4x12.c b/arch/arm/mach-exynos/mach-smdk4x12.c
index ae6da40..fe61496 100644
--- a/arch/arm/mach-exynos/mach-smdk4x12.c
+++ b/arch/arm/mach-exynos/mach-smdk4x12.c
@@ -25,7 +25,6 @@
 #include <linux/platform_data/s3c-hsotg.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 
 #include <video/samsung_fimd.h>
@@ -376,9 +375,8 @@
 	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdk4x12_map_io,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= smdk4x12_machine_init,
-	.timer		= &exynos4_timer,
+	.init_time	= exynos4_timer_init,
 	.restart	= exynos4_restart,
 	.reserve	= &smdk4x12_reserve,
 MACHINE_END
@@ -390,10 +388,9 @@
 	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdk4x12_map_io,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= smdk4x12_machine_init,
 	.init_late	= exynos_init_late,
-	.timer		= &exynos4_timer,
+	.init_time	= exynos4_timer_init,
 	.restart	= exynos4_restart,
 	.reserve	= &smdk4x12_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-smdkv310.c b/arch/arm/mach-exynos/mach-smdkv310.c
index 35548e3..d716729 100644
--- a/arch/arm/mach-exynos/mach-smdkv310.c
+++ b/arch/arm/mach-exynos/mach-smdkv310.c
@@ -26,7 +26,6 @@
 #include <linux/platform_data/usb-exynos.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 
 #include <video/platform_lcd.h>
@@ -423,9 +422,8 @@
 	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdkv310_map_io,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= smdkv310_machine_init,
-	.timer		= &exynos4_timer,
+	.init_time	= exynos4_timer_init,
 	.reserve	= &smdkv310_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
@@ -436,10 +434,9 @@
 	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= smdkv310_map_io,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= smdkv310_machine_init,
 	.init_late	= exynos_init_late,
-	.timer		= &exynos4_timer,
+	.init_time	= exynos4_timer_init,
 	.reserve	= &smdkv310_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mach-universal_c210.c b/arch/arm/mach-exynos/mach-universal_c210.c
index 9e3340f..c9d33a4 100644
--- a/arch/arm/mach-exynos/mach-universal_c210.c
+++ b/arch/arm/mach-exynos/mach-universal_c210.c
@@ -29,7 +29,6 @@
 #include <drm/exynos_drm.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 
 #include <video/samsung_fimd.h>
@@ -1151,10 +1150,9 @@
 	.smp		= smp_ops(exynos_smp_ops),
 	.init_irq	= exynos4_init_irq,
 	.map_io		= universal_map_io,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= universal_machine_init,
 	.init_late	= exynos_init_late,
-	.timer		= &s5p_timer,
+	.init_time	= s5p_timer_init,
 	.reserve        = &universal_reserve,
 	.restart	= exynos4_restart,
 MACHINE_END
diff --git a/arch/arm/mach-exynos/mct.c b/arch/arm/mach-exynos/mct.c
index 070d51e..c9d6650 100644
--- a/arch/arm/mach-exynos/mct.c
+++ b/arch/arm/mach-exynos/mct.c
@@ -22,7 +22,6 @@
 #include <linux/of.h>
 
 #include <asm/arch_timer.h>
-#include <asm/hardware/gic.h>
 #include <asm/localtimer.h>
 
 #include <plat/cpu.h>
@@ -468,7 +467,7 @@
 #endif /* CONFIG_LOCAL_TIMERS */
 }
 
-static void __init exynos_timer_init(void)
+void __init exynos4_timer_init(void)
 {
 	if (soc_is_exynos5440()) {
 		arch_timer_of_register();
@@ -484,7 +483,3 @@
 	exynos4_clocksource_init();
 	exynos4_clockevent_init();
 }
-
-struct sys_timer exynos4_timer = {
-	.init		= exynos_timer_init,
-};
diff --git a/arch/arm/mach-exynos/platsmp.c b/arch/arm/mach-exynos/platsmp.c
index c5c840e..60f7c5b 100644
--- a/arch/arm/mach-exynos/platsmp.c
+++ b/arch/arm/mach-exynos/platsmp.c
@@ -20,9 +20,9 @@
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include <asm/cacheflush.h>
-#include <asm/hardware/gic.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 
@@ -149,7 +149,7 @@
 
 		__raw_writel(virt_to_phys(exynos4_secondary_startup),
 							cpu_boot_reg(phys_cpu));
-		gic_raise_softirq(cpumask_of(cpu), 0);
+		arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 
 		if (pen_release == -1)
 			break;
@@ -190,8 +190,6 @@
 
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
 
 static void __init exynos_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-footbridge/cats-hw.c b/arch/arm/mach-footbridge/cats-hw.c
index 25b4536..6987a09 100644
--- a/arch/arm/mach-footbridge/cats-hw.c
+++ b/arch/arm/mach-footbridge/cats-hw.c
@@ -90,6 +90,6 @@
 	.fixup		= fixup_cats,
 	.map_io		= footbridge_map_io,
 	.init_irq	= footbridge_init_irq,
-	.timer		= &isa_timer,
+	.init_time	= isa_timer_init,
 	.restart	= footbridge_restart,
 MACHINE_END
diff --git a/arch/arm/mach-footbridge/common.h b/arch/arm/mach-footbridge/common.h
index c9767b89..a846e50 100644
--- a/arch/arm/mach-footbridge/common.h
+++ b/arch/arm/mach-footbridge/common.h
@@ -1,6 +1,6 @@
 
-extern struct sys_timer footbridge_timer;
-extern struct sys_timer isa_timer;
+extern void footbridge_timer_init(void);
+extern void isa_timer_init(void);
 
 extern void isa_rtc_init(void);
 
diff --git a/arch/arm/mach-footbridge/dc21285-timer.c b/arch/arm/mach-footbridge/dc21285-timer.c
index a9918b6..9ee78f7 100644
--- a/arch/arm/mach-footbridge/dc21285-timer.c
+++ b/arch/arm/mach-footbridge/dc21285-timer.c
@@ -93,7 +93,7 @@
 /*
  * Set up timer interrupt.
  */
-static void __init footbridge_timer_init(void)
+void __init footbridge_timer_init(void)
 {
 	struct clock_event_device *ce = &ckevt_dc21285;
 
@@ -104,7 +104,3 @@
 	ce->cpumask = cpumask_of(smp_processor_id());
 	clockevents_config_and_register(ce, mem_fclk_21285, 0x4, 0xffffff);
 }
-
-struct sys_timer footbridge_timer = {
-	.init		= footbridge_timer_init,
-};
diff --git a/arch/arm/mach-footbridge/ebsa285.c b/arch/arm/mach-footbridge/ebsa285.c
index b09551e..b082435 100644
--- a/arch/arm/mach-footbridge/ebsa285.c
+++ b/arch/arm/mach-footbridge/ebsa285.c
@@ -101,7 +101,7 @@
 	.video_end	= 0x000bffff,
 	.map_io		= footbridge_map_io,
 	.init_irq	= footbridge_init_irq,
-	.timer		= &footbridge_timer,
+	.init_time	= footbridge_timer_init,
 	.restart	= footbridge_restart,
 MACHINE_END
 
diff --git a/arch/arm/mach-footbridge/isa-timer.c b/arch/arm/mach-footbridge/isa-timer.c
index c40bb41..d9301dd 100644
--- a/arch/arm/mach-footbridge/isa-timer.c
+++ b/arch/arm/mach-footbridge/isa-timer.c
@@ -31,14 +31,10 @@
 	.dev_id		= &i8253_clockevent,
 };
 
-static void __init isa_timer_init(void)
+void __init isa_timer_init(void)
 {
 	clocksource_i8253_init();
 
 	setup_irq(i8253_clockevent.irq, &pit_timer_irq);
 	clockevent_i8253_init(false);
 }
-
-struct sys_timer isa_timer = {
-	.init		= isa_timer_init,
-};
diff --git a/arch/arm/mach-footbridge/netwinder-hw.c b/arch/arm/mach-footbridge/netwinder-hw.c
index d2d1433..90ea23f 100644
--- a/arch/arm/mach-footbridge/netwinder-hw.c
+++ b/arch/arm/mach-footbridge/netwinder-hw.c
@@ -766,6 +766,6 @@
 	.fixup		= fixup_netwinder,
 	.map_io		= footbridge_map_io,
 	.init_irq	= footbridge_init_irq,
-	.timer		= &isa_timer,
+	.init_time	= isa_timer_init,
 	.restart	= netwinder_restart,
 MACHINE_END
diff --git a/arch/arm/mach-footbridge/personal.c b/arch/arm/mach-footbridge/personal.c
index e1e9990..7bdeabd 100644
--- a/arch/arm/mach-footbridge/personal.c
+++ b/arch/arm/mach-footbridge/personal.c
@@ -18,7 +18,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= footbridge_map_io,
 	.init_irq	= footbridge_init_irq,
-	.timer		= &footbridge_timer,
+	.init_time	= footbridge_timer_init,
 	.restart	= footbridge_restart,
 MACHINE_END
 
diff --git a/arch/arm/mach-gemini/board-nas4220b.c b/arch/arm/mach-gemini/board-nas4220b.c
index 5927d3c..08bd650 100644
--- a/arch/arm/mach-gemini/board-nas4220b.c
+++ b/arch/arm/mach-gemini/board-nas4220b.c
@@ -31,10 +31,6 @@
 
 #include "common.h"
 
-static struct sys_timer ib4220b_timer = {
-	.init	= gemini_timer_init,
-};
-
 static struct gpio_led ib4220b_leds[] = {
 	{
 		.name			= "nas4220b:orange:hdd",
@@ -105,6 +101,6 @@
 	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
-	.timer		= &ib4220b_timer,
+	.init_time	= gemini_timer_init,
 	.init_machine	= ib4220b_init,
 MACHINE_END
diff --git a/arch/arm/mach-gemini/board-rut1xx.c b/arch/arm/mach-gemini/board-rut1xx.c
index cd7437a..fa0a363 100644
--- a/arch/arm/mach-gemini/board-rut1xx.c
+++ b/arch/arm/mach-gemini/board-rut1xx.c
@@ -71,10 +71,6 @@
 	},
 };
 
-static struct sys_timer rut1xx_timer = {
-	.init	= gemini_timer_init,
-};
-
 static void __init rut1xx_init(void)
 {
 	gemini_gpio_init();
@@ -89,6 +85,6 @@
 	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
-	.timer		= &rut1xx_timer,
+	.init_time	= gemini_timer_init,
 	.init_machine	= rut1xx_init,
 MACHINE_END
diff --git a/arch/arm/mach-gemini/board-wbd111.c b/arch/arm/mach-gemini/board-wbd111.c
index a367880..3321cd6 100644
--- a/arch/arm/mach-gemini/board-wbd111.c
+++ b/arch/arm/mach-gemini/board-wbd111.c
@@ -80,10 +80,6 @@
 	},
 };
 
-static struct sys_timer wbd111_timer = {
-	.init	= gemini_timer_init,
-};
-
 static struct mtd_partition wbd111_partitions[] = {
 	{
 		.name		= "RedBoot",
@@ -132,6 +128,6 @@
 	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
-	.timer		= &wbd111_timer,
+	.init_time	= gemini_timer_init,
 	.init_machine	= wbd111_init,
 MACHINE_END
diff --git a/arch/arm/mach-gemini/board-wbd222.c b/arch/arm/mach-gemini/board-wbd222.c
index f382811..fe33c82 100644
--- a/arch/arm/mach-gemini/board-wbd222.c
+++ b/arch/arm/mach-gemini/board-wbd222.c
@@ -80,10 +80,6 @@
 	},
 };
 
-static struct sys_timer wbd222_timer = {
-	.init	= gemini_timer_init,
-};
-
 static struct mtd_partition wbd222_partitions[] = {
 	{
 		.name		= "RedBoot",
@@ -132,6 +128,6 @@
 	.atag_offset	= 0x100,
 	.map_io		= gemini_map_io,
 	.init_irq	= gemini_init_irq,
-	.timer		= &wbd222_timer,
+	.init_time	= gemini_timer_init,
 	.init_machine	= wbd222_init,
 MACHINE_END
diff --git a/arch/arm/mach-h720x/common.c b/arch/arm/mach-h720x/common.c
index aa1331e..17ef91f 100644
--- a/arch/arm/mach-h720x/common.c
+++ b/arch/arm/mach-h720x/common.c
@@ -42,12 +42,12 @@
 }
 
 /*
- * Return usecs since last timer reload
+ * Return nsecs since last timer reload
  * (timercount * (usecs perjiffie)) / (ticks per jiffie)
  */
-unsigned long h720x_gettimeoffset(void)
+u32 h720x_gettimeoffset(void)
 {
-	return (CPU_REG (TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH;
+	return ((CPU_REG(TIMER_VIRT, TM0_COUNT) * tick_usec) / LATCH) * 1000;
 }
 
 /*
diff --git a/arch/arm/mach-h720x/common.h b/arch/arm/mach-h720x/common.h
index 2489537..7e73841 100644
--- a/arch/arm/mach-h720x/common.h
+++ b/arch/arm/mach-h720x/common.h
@@ -13,18 +13,18 @@
  *
  */
 
-extern unsigned long h720x_gettimeoffset(void);
+extern u32 h720x_gettimeoffset(void);
 extern void __init h720x_init_irq(void);
 extern void __init h720x_map_io(void);
 extern void h720x_restart(char, const char *);
 
 #ifdef CONFIG_ARCH_H7202
-extern struct sys_timer h7202_timer;
+extern void h7202_timer_init(void);
 extern void __init init_hw_h7202(void);
 extern void __init h7202_init_irq(void);
 extern void __init h7202_init_time(void);
 #endif
 
 #ifdef CONFIG_ARCH_H7201
-extern struct sys_timer h7201_timer;
+extern void h7201_timer_init(void);
 #endif
diff --git a/arch/arm/mach-h720x/cpu-h7201.c b/arch/arm/mach-h720x/cpu-h7201.c
index 24df2a3..13c7412 100644
--- a/arch/arm/mach-h720x/cpu-h7201.c
+++ b/arch/arm/mach-h720x/cpu-h7201.c
@@ -44,8 +44,10 @@
 /*
  * Setup TIMER0 as system timer
  */
-void __init h7201_init_time(void)
+void __init h7201_timer_init(void)
 {
+	arch_gettimeoffset = h720x_gettimeoffset;
+
 	CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
 	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
 	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
@@ -53,8 +55,3 @@
 
 	setup_irq(IRQ_TIMER0, &h7201_timer_irq);
 }
-
-struct sys_timer h7201_timer = {
-	.init		= h7201_init_time,
-	.offset		= h720x_gettimeoffset,
-};
diff --git a/arch/arm/mach-h720x/cpu-h7202.c b/arch/arm/mach-h720x/cpu-h7202.c
index c37d570..e2ae7e8 100644
--- a/arch/arm/mach-h720x/cpu-h7202.c
+++ b/arch/arm/mach-h720x/cpu-h7202.c
@@ -178,8 +178,10 @@
 /*
  * Setup TIMER0 as system timer
  */
-void __init h7202_init_time(void)
+void __init h7202_timer_init(void)
 {
+	arch_gettimeoffset = h720x_gettimeoffset;
+
 	CPU_REG (TIMER_VIRT, TM0_PERIOD) = LATCH;
 	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_RESET;
 	CPU_REG (TIMER_VIRT, TM0_CTRL) = TM_REPEAT | TM_START;
@@ -188,11 +190,6 @@
 	setup_irq(IRQ_TIMER0, &h7202_timer_irq);
 }
 
-struct sys_timer h7202_timer = {
-	.init		= h7202_init_time,
-	.offset		= h720x_gettimeoffset,
-};
-
 void __init h7202_init_irq (void)
 {
 	int 	irq;
diff --git a/arch/arm/mach-h720x/h7201-eval.c b/arch/arm/mach-h720x/h7201-eval.c
index 5fdb20c..4fdeb68 100644
--- a/arch/arm/mach-h720x/h7201-eval.c
+++ b/arch/arm/mach-h720x/h7201-eval.c
@@ -32,7 +32,7 @@
 	.atag_offset	= 0x1000,
 	.map_io		= h720x_map_io,
 	.init_irq	= h720x_init_irq,
-	.timer		= &h7201_timer,
+	.init_time	= h7201_timer_init,
 	.dma_zone_size	= SZ_256M,
 	.restart	= h720x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-h720x/h7202-eval.c b/arch/arm/mach-h720x/h7202-eval.c
index 1696730..f68e967 100644
--- a/arch/arm/mach-h720x/h7202-eval.c
+++ b/arch/arm/mach-h720x/h7202-eval.c
@@ -74,7 +74,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= h720x_map_io,
 	.init_irq	= h7202_init_irq,
-	.timer		= &h7202_timer,
+	.init_time	= h7202_timer_init,
 	.init_machine	= init_eval_h7202,
 	.dma_zone_size	= SZ_256M,
 	.restart	= h720x_restart,
diff --git a/arch/arm/mach-highbank/highbank.c b/arch/arm/mach-highbank/highbank.c
index 981dc1e..fd630bc 100644
--- a/arch/arm/mach-highbank/highbank.c
+++ b/arch/arm/mach-highbank/highbank.c
@@ -18,6 +18,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_irq.h>
@@ -32,7 +33,6 @@
 #include <asm/smp_twd.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/timer-sp.h>
-#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -66,12 +66,6 @@
 			  HB_JUMP_TABLE_PHYS(cpu) + 15);
 }
 
-const static struct of_device_id irq_match[] = {
-	{ .compatible = "arm,cortex-a15-gic", .data = gic_of_init, },
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-	{}
-};
-
 #ifdef CONFIG_CACHE_L2X0
 static void highbank_l2x0_disable(void)
 {
@@ -82,7 +76,7 @@
 
 static void __init highbank_init_irq(void)
 {
-	of_irq_init(irq_match);
+	irqchip_init();
 
 	if (of_find_compatible_node(NULL, NULL, "arm,cortex-a9"))
 		highbank_scu_map_io();
@@ -129,10 +123,6 @@
 	arch_timer_sched_clock_init();
 }
 
-static struct sys_timer highbank_timer = {
-	.init = highbank_timer_init,
-};
-
 static void highbank_power_off(void)
 {
 	highbank_set_pwr_shutdown();
@@ -209,8 +199,7 @@
 	.smp		= smp_ops(highbank_smp_ops),
 	.map_io		= debug_ll_io_init,
 	.init_irq	= highbank_init_irq,
-	.timer		= &highbank_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= highbank_timer_init,
 	.init_machine	= highbank_init,
 	.dt_compat	= highbank_match,
 	.restart	= highbank_restart,
diff --git a/arch/arm/mach-highbank/platsmp.c b/arch/arm/mach-highbank/platsmp.c
index 4ecc864..8797a70 100644
--- a/arch/arm/mach-highbank/platsmp.c
+++ b/arch/arm/mach-highbank/platsmp.c
@@ -17,9 +17,9 @@
 #include <linux/init.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include <asm/smp_scu.h>
-#include <asm/hardware/gic.h>
 
 #include "core.h"
 
@@ -33,7 +33,7 @@
 static int __cpuinit highbank_boot_secondary(unsigned int cpu, struct task_struct *idle)
 {
 	highbank_set_cpu_jump(cpu, secondary_startup);
-	gic_raise_softirq(cpumask_of(cpu), 0);
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 	return 0;
 }
 
@@ -56,8 +56,6 @@
 
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
 
 static void __init highbank_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-imx/Kconfig b/arch/arm/mach-imx/Kconfig
index 3e628fd..7b11d33 100644
--- a/arch/arm/mach-imx/Kconfig
+++ b/arch/arm/mach-imx/Kconfig
@@ -95,9 +95,6 @@
 config ARCH_MX5
 	bool
 
-config ARCH_MX50
-	bool
-
 config ARCH_MX51
 	bool
 
@@ -164,11 +161,6 @@
 	select CPU_V7
 	select MXC_TZIC
 
-config SOC_IMX50
-	bool
-	select ARCH_MX50
-	select SOC_IMX5
-
 config	SOC_IMX51
 	bool
 	select ARCH_MX5
@@ -738,25 +730,10 @@
 
 if ARCH_MULTI_V7
 
-comment "i.MX5 platforms:"
-
-config MACH_MX50_RDP
-	bool "Support MX50 reference design platform"
-	depends on BROKEN
-	select IMX_HAVE_PLATFORM_IMX_I2C
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	select SOC_IMX50
-	help
-	  Include support for MX50 reference design platform (RDP) board. This
-	  includes specific configurations for the board and its peripherals.
-
 comment "i.MX51 machines:"
 
 config MACH_IMX51_DT
 	bool "Support i.MX51 platforms from device tree"
-	select MACH_MX51_BABBAGE
 	select SOC_IMX51
 	help
 	  Include support for Freescale i.MX51 based platforms
@@ -777,19 +754,6 @@
 	  u-boot. This includes specific configurations for the board and its
 	  peripherals.
 
-config MACH_MX51_3DS
-	bool "Support MX51PDK (3DS)"
-	select IMX_HAVE_PLATFORM_IMX2_WDT
-	select IMX_HAVE_PLATFORM_IMX_KEYPAD
-	select IMX_HAVE_PLATFORM_IMX_UART
-	select IMX_HAVE_PLATFORM_SDHCI_ESDHC_IMX
-	select IMX_HAVE_PLATFORM_SPI_IMX
-	select MXC_DEBUG_BOARD
-	select SOC_IMX51
-	help
-	  Include support for MX51PDK (3DS) platform. This includes specific
-	  configurations for the board and its peripherals.
-
 config MACH_EUKREA_CPUIMX51SD
 	bool "Support Eukrea CPUIMX51SD module"
 	select IMX_HAVE_PLATFORM_FSL_USB2_UDC
@@ -851,6 +815,7 @@
 	select HAVE_CAN_FLEXCAN if CAN
 	select HAVE_IMX_GPC
 	select HAVE_IMX_MMDC
+	select HAVE_IMX_SRC
 	select HAVE_SMP
 	select MFD_SYSCON
 	select PINCTRL
diff --git a/arch/arm/mach-imx/Makefile b/arch/arm/mach-imx/Makefile
index 0634b31..c4ce090 100644
--- a/arch/arm/mach-imx/Makefile
+++ b/arch/arm/mach-imx/Makefile
@@ -28,7 +28,11 @@
 obj-$(CONFIG_MXC_USE_EPIT) += epit.o
 obj-$(CONFIG_MXC_DEBUG_BOARD) += 3ds_debugboard.o
 obj-$(CONFIG_CPU_FREQ_IMX)    += cpufreq.o
-obj-$(CONFIG_CPU_IDLE) += cpuidle.o
+
+ifeq ($(CONFIG_CPU_IDLE),y)
+obj-y += cpuidle.o
+obj-$(CONFIG_SOC_IMX6Q) += cpuidle-imx6q.o
+endif
 
 ifdef CONFIG_SND_IMX_SOC
 obj-y += ssi-fiq.o
@@ -88,7 +92,6 @@
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD35_BASEBOARD) += eukrea_mbimxsd35-baseboard.o
 obj-$(CONFIG_MACH_VPR200) += mach-vpr200.o
 
-obj-$(CONFIG_DEBUG_LL) += lluart.o
 obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
 obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
 obj-$(CONFIG_HAVE_IMX_SRC) += src.o
@@ -103,10 +106,8 @@
 
 # i.MX5 based machines
 obj-$(CONFIG_MACH_MX51_BABBAGE) += mach-mx51_babbage.o
-obj-$(CONFIG_MACH_MX51_3DS) += mach-mx51_3ds.o
 obj-$(CONFIG_MACH_EUKREA_CPUIMX51SD) += mach-cpuimx51sd.o
 obj-$(CONFIG_MACH_EUKREA_MBIMXSD51_BASEBOARD) += eukrea_mbimxsd51-baseboard.o
-obj-$(CONFIG_MACH_MX50_RDP) += mach-mx50_rdp.o
 
 obj-$(CONFIG_MACH_IMX51_DT) += imx51-dt.o
 obj-$(CONFIG_SOC_IMX53) += mach-imx53.o
diff --git a/arch/arm/mach-imx/Makefile.boot b/arch/arm/mach-imx/Makefile.boot
index b27815d..41ba1bb 100644
--- a/arch/arm/mach-imx/Makefile.boot
+++ b/arch/arm/mach-imx/Makefile.boot
@@ -22,10 +22,6 @@
 params_phys-$(CONFIG_SOC_IMX35)	:= 0x80000100
 initrd_phys-$(CONFIG_SOC_IMX35)	:= 0x80800000
 
-zreladdr-$(CONFIG_SOC_IMX50)	+= 0x70008000
-params_phys-$(CONFIG_SOC_IMX50)	:= 0x70000100
-initrd_phys-$(CONFIG_SOC_IMX50)	:= 0x70800000
-
 zreladdr-$(CONFIG_SOC_IMX51)	+= 0x90008000
 params_phys-$(CONFIG_SOC_IMX51)	:= 0x90000100
 initrd_phys-$(CONFIG_SOC_IMX51)	:= 0x90800000
diff --git a/arch/arm/mach-imx/clk-imx25.c b/arch/arm/mach-imx/clk-imx25.c
index b197aa7..2c570cd 100644
--- a/arch/arm/mach-imx/clk-imx25.c
+++ b/arch/arm/mach-imx/clk-imx25.c
@@ -254,9 +254,9 @@
 	clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
 	clk_register_clkdev(clk[usbotg_ahb], "ahb", "mxc-ehci.2");
 	clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
-	clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
-	clk_register_clkdev(clk[usbotg_ahb], "ahb", "fsl-usb2-udc");
-	clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
+	clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27");
+	clk_register_clkdev(clk[usbotg_ahb], "ahb", "imx-udc-mx27");
+	clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
 	clk_register_clkdev(clk[nfc_ipg_per], NULL, "imx25-nand.0");
 	/* i.mx25 has the i.mx35 type cspi */
 	clk_register_clkdev(clk[cspi1_ipg], NULL, "imx35-cspi.0");
diff --git a/arch/arm/mach-imx/clk-imx27.c b/arch/arm/mach-imx/clk-imx27.c
index 4c1d1e4..d24b0d6 100644
--- a/arch/arm/mach-imx/clk-imx27.c
+++ b/arch/arm/mach-imx/clk-imx27.c
@@ -62,7 +62,7 @@
 	"32k", "usb_div", "dptc",
 };
 
-static const char *ssi_sel_clks[] = { "spll", "mpll", };
+static const char *ssi_sel_clks[] = { "spll_gate", "mpll", };
 
 enum mx27_clks {
 	dummy, ckih, ckil, mpll, spll, mpll_main2, ahb, ipg, nfc_div, per1_div,
@@ -82,7 +82,7 @@
 	csi_ahb_gate, brom_ahb_gate, ata_ahb_gate, wdog_ipg_gate, usb_ipg_gate,
 	uart6_ipg_gate, uart5_ipg_gate, uart4_ipg_gate, uart3_ipg_gate,
 	uart2_ipg_gate, uart1_ipg_gate, ckih_div1p5, fpm, mpll_osc_sel,
-	mpll_sel, clk_max
+	mpll_sel, spll_gate, clk_max
 };
 
 static struct clk *clk[clk_max];
@@ -104,6 +104,7 @@
 			ARRAY_SIZE(mpll_sel_clks));
 	clk[mpll] = imx_clk_pllv1("mpll", "mpll_sel", CCM_MPCTL0);
 	clk[spll] = imx_clk_pllv1("spll", "ckih", CCM_SPCTL0);
+	clk[spll_gate] = imx_clk_gate("spll_gate", "spll", CCM_CSCR, 1);
 	clk[mpll_main2] = imx_clk_fixed_factor("mpll_main2", "mpll", 2, 3);
 
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0) {
@@ -121,7 +122,7 @@
 	clk[per4_div] = imx_clk_divider("per4_div", "mpll_main2", CCM_PCDR1, 24, 6);
 	clk[vpu_sel] = imx_clk_mux("vpu_sel", CCM_CSCR, 21, 1, vpu_sel_clks, ARRAY_SIZE(vpu_sel_clks));
 	clk[vpu_div] = imx_clk_divider("vpu_div", "vpu_sel", CCM_PCDR0, 10, 6);
-	clk[usb_div] = imx_clk_divider("usb_div", "spll", CCM_CSCR, 28, 3);
+	clk[usb_div] = imx_clk_divider("usb_div", "spll_gate", CCM_CSCR, 28, 3);
 	clk[cpu_sel] = imx_clk_mux("cpu_sel", CCM_CSCR, 15, 1, cpu_sel_clks, ARRAY_SIZE(cpu_sel_clks));
 	clk[clko_sel] = imx_clk_mux("clko_sel", CCM_CCSR, 0, 5, clko_sel_clks, ARRAY_SIZE(clko_sel_clks));
 	if (mx27_revision() >= IMX_CHIP_REVISION_2_0)
@@ -236,9 +237,9 @@
 	clk_register_clkdev(clk[lcdc_ahb_gate], "ahb", "imx21-fb.0");
 	clk_register_clkdev(clk[csi_ahb_gate], "ahb", "imx27-camera.0");
 	clk_register_clkdev(clk[per4_gate], "per", "imx27-camera.0");
-	clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
-	clk_register_clkdev(clk[usb_ipg_gate], "ipg", "fsl-usb2-udc");
-	clk_register_clkdev(clk[usb_ahb_gate], "ahb", "fsl-usb2-udc");
+	clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
+	clk_register_clkdev(clk[usb_ipg_gate], "ipg", "imx-udc-mx27");
+	clk_register_clkdev(clk[usb_ahb_gate], "ahb", "imx-udc-mx27");
 	clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.0");
 	clk_register_clkdev(clk[usb_ipg_gate], "ipg", "mxc-ehci.0");
 	clk_register_clkdev(clk[usb_ahb_gate], "ahb", "mxc-ehci.0");
diff --git a/arch/arm/mach-imx/clk-imx31.c b/arch/arm/mach-imx/clk-imx31.c
index 8be64e0..b5b65f3 100644
--- a/arch/arm/mach-imx/clk-imx31.c
+++ b/arch/arm/mach-imx/clk-imx31.c
@@ -34,8 +34,8 @@
 static const char *fir_sel[] = { "mcu_main", "upll", "spll" };
 
 enum mx31_clks {
-	ckih, ckil, mpll, spll, upll, mcu_main, hsp, ahb, nfc, ipg, per_div,
-	per, csi, fir, csi_div, usb_div_pre, usb_div_post, fir_div_pre,
+	dummy, ckih, ckil, mpll, spll, upll, mcu_main, hsp, ahb, nfc, ipg,
+	per_div, per, csi, fir, csi_div, usb_div_pre, usb_div_post, fir_div_pre,
 	fir_div_post, sdhc1_gate, sdhc2_gate, gpt_gate, epit1_gate, epit2_gate,
 	iim_gate, ata_gate, sdma_gate, cspi3_gate, rng_gate, uart1_gate,
 	uart2_gate, ssi1_gate, i2c1_gate, i2c2_gate, i2c3_gate, hantro_gate,
@@ -46,12 +46,15 @@
 };
 
 static struct clk *clk[clk_max];
+static struct clk_onecell_data clk_data;
 
 int __init mx31_clocks_init(unsigned long fref)
 {
 	void __iomem *base = MX31_IO_ADDRESS(MX31_CCM_BASE_ADDR);
 	int i;
+	struct device_node *np;
 
+	clk[dummy] = imx_clk_fixed("dummy", 0);
 	clk[ckih] = imx_clk_fixed("ckih", fref);
 	clk[ckil] = imx_clk_fixed("ckil", 32768);
 	clk[mpll] = imx_clk_pllv1("mpll", "ckih", base + MXC_CCM_MPCTL);
@@ -116,6 +119,14 @@
 			pr_err("imx31 clk %d: register failed with %ld\n",
 				i, PTR_ERR(clk[i]));
 
+	np = of_find_compatible_node(NULL, NULL, "fsl,imx31-ccm");
+
+	if (np) {
+		clk_data.clks = clk;
+		clk_data.clk_num = ARRAY_SIZE(clk);
+		of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+	}
+
 	clk_register_clkdev(clk[gpt_gate], "per", "imx-gpt.0");
 	clk_register_clkdev(clk[ipg], "ipg", "imx-gpt.0");
 	clk_register_clkdev(clk[cspi1_gate], NULL, "imx31-cspi.0");
@@ -139,9 +150,9 @@
 	clk_register_clkdev(clk[usb_div_post], "per", "mxc-ehci.2");
 	clk_register_clkdev(clk[usb_gate], "ahb", "mxc-ehci.2");
 	clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
-	clk_register_clkdev(clk[usb_div_post], "per", "fsl-usb2-udc");
-	clk_register_clkdev(clk[usb_gate], "ahb", "fsl-usb2-udc");
-	clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
+	clk_register_clkdev(clk[usb_div_post], "per", "imx-udc-mx27");
+	clk_register_clkdev(clk[usb_gate], "ahb", "imx-udc-mx27");
+	clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27");
 	clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
 	/* i.mx31 has the i.mx21 type uart */
 	clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0");
diff --git a/arch/arm/mach-imx/clk-imx35.c b/arch/arm/mach-imx/clk-imx35.c
index 66f3d65..74e3a34 100644
--- a/arch/arm/mach-imx/clk-imx35.c
+++ b/arch/arm/mach-imx/clk-imx35.c
@@ -67,13 +67,13 @@
 
 static struct clk *clk[clk_max];
 
-int __init mx35_clocks_init()
+int __init mx35_clocks_init(void)
 {
 	void __iomem *base = MX35_IO_ADDRESS(MX35_CCM_BASE_ADDR);
 	u32 pdr0, consumer_sel, hsp_sel;
 	struct arm_ahb_div *aad;
 	unsigned char *hsp_div;
-	int i;
+	u32 i;
 
 	pdr0 = __raw_readl(base + MXC_CCM_PDR0);
 	consumer_sel = (pdr0 >> 16) & 0xf;
@@ -251,9 +251,9 @@
 	clk_register_clkdev(clk[usb_div], "per", "mxc-ehci.2");
 	clk_register_clkdev(clk[ipg], "ipg", "mxc-ehci.2");
 	clk_register_clkdev(clk[usbotg_gate], "ahb", "mxc-ehci.2");
-	clk_register_clkdev(clk[usb_div], "per", "fsl-usb2-udc");
-	clk_register_clkdev(clk[ipg], "ipg", "fsl-usb2-udc");
-	clk_register_clkdev(clk[usbotg_gate], "ahb", "fsl-usb2-udc");
+	clk_register_clkdev(clk[usb_div], "per", "imx-udc-mx27");
+	clk_register_clkdev(clk[ipg], "ipg", "imx-udc-mx27");
+	clk_register_clkdev(clk[usbotg_gate], "ahb", "imx-udc-mx27");
 	clk_register_clkdev(clk[wdog_gate], NULL, "imx2-wdt.0");
 	clk_register_clkdev(clk[nfc_div], NULL, "imx25-nand.0");
 	clk_register_clkdev(clk[csi_gate], NULL, "mx3-camera.0");
diff --git a/arch/arm/mach-imx/clk-imx51-imx53.c b/arch/arm/mach-imx/clk-imx51-imx53.c
index 579023f..fb7cb84 100644
--- a/arch/arm/mach-imx/clk-imx51-imx53.c
+++ b/arch/arm/mach-imx/clk-imx51-imx53.c
@@ -269,9 +269,9 @@
 	clk_register_clkdev(clk[usboh3_per_gate], "per", "mxc-ehci.2");
 	clk_register_clkdev(clk[usboh3_gate], "ipg", "mxc-ehci.2");
 	clk_register_clkdev(clk[usboh3_gate], "ahb", "mxc-ehci.2");
-	clk_register_clkdev(clk[usboh3_per_gate], "per", "fsl-usb2-udc");
-	clk_register_clkdev(clk[usboh3_gate], "ipg", "fsl-usb2-udc");
-	clk_register_clkdev(clk[usboh3_gate], "ahb", "fsl-usb2-udc");
+	clk_register_clkdev(clk[usboh3_per_gate], "per", "imx-udc-mx51");
+	clk_register_clkdev(clk[usboh3_gate], "ipg", "imx-udc-mx51");
+	clk_register_clkdev(clk[usboh3_gate], "ahb", "imx-udc-mx51");
 	clk_register_clkdev(clk[nfc_gate], NULL, "imx51-nand");
 	clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
 	clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
diff --git a/arch/arm/mach-imx/clk-imx6q.c b/arch/arm/mach-imx/clk-imx6q.c
index 7f2c10c..540138c 100644
--- a/arch/arm/mach-imx/clk-imx6q.c
+++ b/arch/arm/mach-imx/clk-imx6q.c
@@ -54,9 +54,18 @@
 #define BM_CLPCR_MASK_SCU_IDLE		(0x1 << 26)
 #define BM_CLPCR_MASK_L2CC_IDLE		(0x1 << 27)
 
+#define CGPR				0x64
+#define BM_CGPR_CHICKEN_BIT		(0x1 << 17)
+
 static void __iomem *ccm_base;
 
-void __init imx6q_clock_map_io(void) { }
+void imx6q_set_chicken_bit(void)
+{
+	u32 val = readl_relaxed(ccm_base + CGPR);
+
+	val |= BM_CGPR_CHICKEN_BIT;
+	writel_relaxed(val, ccm_base + CGPR);
+}
 
 int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode)
 {
@@ -68,6 +77,7 @@
 		break;
 	case WAIT_UNCLOCKED:
 		val |= 0x1 << BP_CLPCR_LPM;
+		val |= BM_CLPCR_ARM_CLK_DIS_ON_LPM;
 		break;
 	case STOP_POWER_ON:
 		val |= 0x2 << BP_CLPCR_LPM;
@@ -436,6 +446,9 @@
 	for (i = 0; i < ARRAY_SIZE(clks_init_on); i++)
 		clk_prepare_enable(clk[clks_init_on[i]]);
 
+	/* Set initial power mode */
+	imx6q_set_lpm(WAIT_CLOCKED);
+
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpt");
 	base = of_iomap(np, 0);
 	WARN_ON(!base);
diff --git a/arch/arm/mach-imx/common.h b/arch/arm/mach-imx/common.h
index 7191ab4..5a800bf 100644
--- a/arch/arm/mach-imx/common.h
+++ b/arch/arm/mach-imx/common.h
@@ -21,7 +21,6 @@
 extern void mx27_map_io(void);
 extern void mx31_map_io(void);
 extern void mx35_map_io(void);
-extern void mx50_map_io(void);
 extern void mx51_map_io(void);
 extern void mx53_map_io(void);
 extern void imx1_init_early(void);
@@ -30,7 +29,6 @@
 extern void imx27_init_early(void);
 extern void imx31_init_early(void);
 extern void imx35_init_early(void);
-extern void imx50_init_early(void);
 extern void imx51_init_early(void);
 extern void imx53_init_early(void);
 extern void mxc_init_irq(void __iomem *);
@@ -41,7 +39,6 @@
 extern void mx27_init_irq(void);
 extern void mx31_init_irq(void);
 extern void mx35_init_irq(void);
-extern void mx50_init_irq(void);
 extern void mx51_init_irq(void);
 extern void mx53_init_irq(void);
 extern void imx1_soc_init(void);
@@ -50,7 +47,6 @@
 extern void imx27_soc_init(void);
 extern void imx31_soc_init(void);
 extern void imx35_soc_init(void);
-extern void imx50_soc_init(void);
 extern void imx51_soc_init(void);
 extern void imx51_init_late(void);
 extern void imx53_init_late(void);
@@ -109,27 +105,22 @@
 #define imx27_handle_irq avic_handle_irq
 #define imx31_handle_irq avic_handle_irq
 #define imx35_handle_irq avic_handle_irq
-#define imx50_handle_irq tzic_handle_irq
 #define imx51_handle_irq tzic_handle_irq
 #define imx53_handle_irq tzic_handle_irq
-#define imx6q_handle_irq gic_handle_irq
 
 extern void imx_enable_cpu(int cpu, bool enable);
 extern void imx_set_cpu_jump(int cpu, void *jump_addr);
-#ifdef CONFIG_DEBUG_LL
-extern void imx_lluart_map_io(void);
-#else
-static inline void imx_lluart_map_io(void) {}
-#endif
 extern void v7_cpu_resume(void);
 extern u32 *pl310_get_save_ptr(void);
 #ifdef CONFIG_SMP
 extern void v7_secondary_startup(void);
 extern void imx_scu_map_io(void);
 extern void imx_smp_prepare(void);
+extern void imx_scu_standby_enable(void);
 #else
 static inline void imx_scu_map_io(void) {}
 static inline void imx_smp_prepare(void) {}
+static inline void imx_scu_standby_enable(void) {}
 #endif
 extern void imx_enable_cpu(int cpu, bool enable);
 extern void imx_set_cpu_jump(int cpu, void *jump_addr);
@@ -139,9 +130,10 @@
 extern void imx_gpc_pre_suspend(void);
 extern void imx_gpc_post_resume(void);
 extern int imx6q_set_lpm(enum mxc_cpu_pwr_mode mode);
-extern void imx6q_clock_map_io(void);
+extern void imx6q_set_chicken_bit(void);
 
 extern void imx_cpu_die(unsigned int cpu);
+extern int imx_cpu_kill(unsigned int cpu);
 
 #ifdef CONFIG_PM
 extern void imx6q_pm_init(void);
diff --git a/arch/arm/mach-imx/cpu-imx5.c b/arch/arm/mach-imx/cpu-imx5.c
index d887600..d7ce722 100644
--- a/arch/arm/mach-imx/cpu-imx5.c
+++ b/arch/arm/mach-imx/cpu-imx5.c
@@ -22,7 +22,6 @@
 static int mx5_cpu_rev = -1;
 
 #define IIM_SREV 0x24
-#define MX50_HW_ADADIG_DIGPROG	0xB0
 
 static int get_mx51_srev(void)
 {
@@ -108,41 +107,3 @@
 	return mx5_cpu_rev;
 }
 EXPORT_SYMBOL(mx53_revision);
-
-static int get_mx50_srev(void)
-{
-	void __iomem *anatop = ioremap(MX50_ANATOP_BASE_ADDR, SZ_8K);
-	u32 rev;
-
-	if (!anatop) {
-		mx5_cpu_rev = -EINVAL;
-		return 0;
-	}
-
-	rev = readl(anatop + MX50_HW_ADADIG_DIGPROG);
-	rev &= 0xff;
-
-	iounmap(anatop);
-	if (rev == 0x0)
-		return IMX_CHIP_REVISION_1_0;
-	else if (rev == 0x1)
-		return IMX_CHIP_REVISION_1_1;
-	return 0;
-}
-
-/*
- * Returns:
- *	the silicon revision of the cpu
- *	-EINVAL - not a mx50
- */
-int mx50_revision(void)
-{
-	if (!cpu_is_mx50())
-		return -EINVAL;
-
-	if (mx5_cpu_rev == -1)
-		mx5_cpu_rev = get_mx50_srev();
-
-	return mx5_cpu_rev;
-}
-EXPORT_SYMBOL(mx50_revision);
diff --git a/arch/arm/mach-imx/cpuidle-imx6q.c b/arch/arm/mach-imx/cpuidle-imx6q.c
new file mode 100644
index 0000000..d533e26
--- /dev/null
+++ b/arch/arm/mach-imx/cpuidle-imx6q.c
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 Freescale Semiconductor, Inc.
+ *
+ * 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/clockchips.h>
+#include <linux/cpuidle.h>
+#include <linux/module.h>
+#include <asm/cpuidle.h>
+#include <asm/proc-fns.h>
+
+#include "common.h"
+#include "cpuidle.h"
+
+static atomic_t master = ATOMIC_INIT(0);
+static DEFINE_SPINLOCK(master_lock);
+
+static int imx6q_enter_wait(struct cpuidle_device *dev,
+			    struct cpuidle_driver *drv, int index)
+{
+	int cpu = dev->cpu;
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &cpu);
+
+	if (atomic_inc_return(&master) == num_online_cpus()) {
+		/*
+		 * With this lock, we prevent other cpu to exit and enter
+		 * this function again and become the master.
+		 */
+		if (!spin_trylock(&master_lock))
+			goto idle;
+		imx6q_set_lpm(WAIT_UNCLOCKED);
+		cpu_do_idle();
+		imx6q_set_lpm(WAIT_CLOCKED);
+		spin_unlock(&master_lock);
+		goto done;
+	}
+
+idle:
+	cpu_do_idle();
+done:
+	atomic_dec(&master);
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &cpu);
+
+	return index;
+}
+
+/*
+ * For each cpu, setup the broadcast timer because local timer
+ * stops for the states other than WFI.
+ */
+static void imx6q_setup_broadcast_timer(void *arg)
+{
+	int cpu = smp_processor_id();
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ON, &cpu);
+}
+
+static struct cpuidle_driver imx6q_cpuidle_driver = {
+	.name = "imx6q_cpuidle",
+	.owner = THIS_MODULE,
+	.en_core_tk_irqen = 1,
+	.states = {
+		/* WFI */
+		ARM_CPUIDLE_WFI_STATE,
+		/* WAIT */
+		{
+			.exit_latency = 50,
+			.target_residency = 75,
+			.flags = CPUIDLE_FLAG_TIME_VALID,
+			.enter = imx6q_enter_wait,
+			.name = "WAIT",
+			.desc = "Clock off",
+		},
+	},
+	.state_count = 2,
+	.safe_state_index = 0,
+};
+
+int __init imx6q_cpuidle_init(void)
+{
+	/* Need to enable SCU standby for entering WAIT modes */
+	imx_scu_standby_enable();
+
+	/* Set chicken bit to get a reliable WAIT mode support */
+	imx6q_set_chicken_bit();
+
+	/* Configure the broadcast timer on each cpu */
+	on_each_cpu(imx6q_setup_broadcast_timer, NULL, 1);
+
+	return imx_cpuidle_init(&imx6q_cpuidle_driver);
+}
diff --git a/arch/arm/mach-imx/cpuidle.h b/arch/arm/mach-imx/cpuidle.h
index bc932d1..e092d13 100644
--- a/arch/arm/mach-imx/cpuidle.h
+++ b/arch/arm/mach-imx/cpuidle.h
@@ -14,9 +14,14 @@
 
 #ifdef CONFIG_CPU_IDLE
 extern int imx_cpuidle_init(struct cpuidle_driver *drv);
+extern int imx6q_cpuidle_init(void);
 #else
 static inline int imx_cpuidle_init(struct cpuidle_driver *drv)
 {
 	return -ENODEV;
 }
+static inline int imx6q_cpuidle_init(void)
+{
+	return -ENODEV;
+}
 #endif
diff --git a/arch/arm/mach-imx/devices-imx50.h b/arch/arm/mach-imx/devices-imx50.h
deleted file mode 100644
index 2c29039..0000000
--- a/arch/arm/mach-imx/devices-imx50.h
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include "devices/devices-common.h"
-
-extern const struct imx_imx_uart_1irq_data imx50_imx_uart_data[];
-#define imx50_add_imx_uart(id, pdata)	\
-	imx_add_imx_uart_1irq(&imx50_imx_uart_data[id], pdata)
-
-extern const struct imx_fec_data imx50_fec_data;
-#define imx50_add_fec(pdata)	\
-	imx_add_fec(&imx50_fec_data, pdata)
-
-extern const struct imx_imx_i2c_data imx50_imx_i2c_data[];
-#define imx50_add_imx_i2c(id, pdata)	\
-	imx_add_imx_i2c(&imx50_imx_i2c_data[id], pdata)
diff --git a/arch/arm/mach-imx/devices/Kconfig b/arch/arm/mach-imx/devices/Kconfig
index 9a8f1ca..9b9ba1f 100644
--- a/arch/arm/mach-imx/devices/Kconfig
+++ b/arch/arm/mach-imx/devices/Kconfig
@@ -1,6 +1,6 @@
 config IMX_HAVE_PLATFORM_FEC
 	bool
-	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX50 || SOC_IMX51 || SOC_IMX53
+	default y if ARCH_MX25 || SOC_IMX27 || SOC_IMX35 || SOC_IMX51 || SOC_IMX53
 
 config IMX_HAVE_PLATFORM_FLEXCAN
 	bool
diff --git a/arch/arm/mach-imx/devices/devices-common.h b/arch/arm/mach-imx/devices/devices-common.h
index 6277baf..9bd5777 100644
--- a/arch/arm/mach-imx/devices/devices-common.h
+++ b/arch/arm/mach-imx/devices/devices-common.h
@@ -63,6 +63,7 @@
 
 #include <linux/fsl_devices.h>
 struct imx_fsl_usb2_udc_data {
+	const char *devid;
 	resource_size_t iobase;
 	resource_size_t irq;
 };
diff --git a/arch/arm/mach-imx/devices/platform-fec.c b/arch/arm/mach-imx/devices/platform-fec.c
index 2cb188a..63eba08 100644
--- a/arch/arm/mach-imx/devices/platform-fec.c
+++ b/arch/arm/mach-imx/devices/platform-fec.c
@@ -35,12 +35,6 @@
 	imx_fec_data_entry_single(MX35, "imx27-fec");
 #endif
 
-#ifdef CONFIG_SOC_IMX50
-/* i.mx50 has the i.mx25 type fec */
-const struct imx_fec_data imx50_fec_data __initconst =
-	imx_fec_data_entry_single(MX50, "imx25-fec");
-#endif
-
 #ifdef CONFIG_SOC_IMX51
 /* i.mx51 has the i.mx27 type fec */
 const struct imx_fec_data imx51_fec_data __initconst =
diff --git a/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c b/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
index 37e4439..3c06bd9 100644
--- a/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
+++ b/arch/arm/mach-imx/devices/platform-fsl-usb2-udc.c
@@ -11,35 +11,36 @@
 #include "../hardware.h"
 #include "devices-common.h"
 
-#define imx_fsl_usb2_udc_data_entry_single(soc)				\
+#define imx_fsl_usb2_udc_data_entry_single(soc, _devid)			\
 	{								\
+		.devid = _devid,					\
 		.iobase = soc ## _USB_OTG_BASE_ADDR,			\
 		.irq = soc ## _INT_USB_OTG,				\
 	}
 
 #ifdef CONFIG_SOC_IMX25
 const struct imx_fsl_usb2_udc_data imx25_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX25);
+	imx_fsl_usb2_udc_data_entry_single(MX25, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX25 */
 
 #ifdef CONFIG_SOC_IMX27
 const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX27);
+	imx_fsl_usb2_udc_data_entry_single(MX27, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX27 */
 
 #ifdef CONFIG_SOC_IMX31
 const struct imx_fsl_usb2_udc_data imx31_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX31);
+	imx_fsl_usb2_udc_data_entry_single(MX31, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX31 */
 
 #ifdef CONFIG_SOC_IMX35
 const struct imx_fsl_usb2_udc_data imx35_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX35);
+	imx_fsl_usb2_udc_data_entry_single(MX35, "imx-udc-mx27");
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
 #ifdef CONFIG_SOC_IMX51
 const struct imx_fsl_usb2_udc_data imx51_fsl_usb2_udc_data __initconst =
-	imx_fsl_usb2_udc_data_entry_single(MX51);
+	imx_fsl_usb2_udc_data_entry_single(MX51, "imx-udc-mx51");
 #endif
 
 struct platform_device *__init imx_add_fsl_usb2_udc(
@@ -57,7 +58,7 @@
 			.flags = IORESOURCE_IRQ,
 		},
 	};
-	return imx_add_platform_device_dmamask("fsl-usb2-udc", -1,
+	return imx_add_platform_device_dmamask(data->devid, -1,
 			res, ARRAY_SIZE(res),
 			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
diff --git a/arch/arm/mach-imx/devices/platform-imx-fb.c b/arch/arm/mach-imx/devices/platform-imx-fb.c
index 10b0ed3..25a47c6 100644
--- a/arch/arm/mach-imx/devices/platform-imx-fb.c
+++ b/arch/arm/mach-imx/devices/platform-imx-fb.c
@@ -54,7 +54,7 @@
 			.flags = IORESOURCE_IRQ,
 		},
 	};
-	return imx_add_platform_device_dmamask("imx-fb", 0,
+	return imx_add_platform_device_dmamask(data->devid, 0,
 			res, ARRAY_SIZE(res),
 			pdata, sizeof(*pdata), DMA_BIT_MASK(32));
 }
diff --git a/arch/arm/mach-imx/devices/platform-imx-i2c.c b/arch/arm/mach-imx/devices/platform-imx-i2c.c
index 8e30e57..57d342e 100644
--- a/arch/arm/mach-imx/devices/platform-imx-i2c.c
+++ b/arch/arm/mach-imx/devices/platform-imx-i2c.c
@@ -70,16 +70,6 @@
 };
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX50
-const struct imx_imx_i2c_data imx50_imx_i2c_data[] __initconst = {
-#define imx50_imx_i2c_data_entry(_id, _hwid)				\
-	imx_imx_i2c_data_entry(MX50, "imx21-i2c", _id, _hwid, SZ_4K)
-	imx50_imx_i2c_data_entry(0, 1),
-	imx50_imx_i2c_data_entry(1, 2),
-	imx50_imx_i2c_data_entry(2, 3),
-};
-#endif /* ifdef CONFIG_SOC_IMX51 */
-
 #ifdef CONFIG_SOC_IMX51
 const struct imx_imx_i2c_data imx51_imx_i2c_data[] __initconst = {
 #define imx51_imx_i2c_data_entry(_id, _hwid)				\
diff --git a/arch/arm/mach-imx/devices/platform-imx-uart.c b/arch/arm/mach-imx/devices/platform-imx-uart.c
index 67bf866a..faac4aa 100644
--- a/arch/arm/mach-imx/devices/platform-imx-uart.c
+++ b/arch/arm/mach-imx/devices/platform-imx-uart.c
@@ -94,18 +94,6 @@
 };
 #endif /* ifdef CONFIG_SOC_IMX35 */
 
-#ifdef CONFIG_SOC_IMX50
-const struct imx_imx_uart_1irq_data imx50_imx_uart_data[] __initconst = {
-#define imx50_imx_uart_data_entry(_id, _hwid)				\
-	imx_imx_uart_1irq_data_entry(MX50, _id, _hwid, SZ_4K)
-	imx50_imx_uart_data_entry(0, 1),
-	imx50_imx_uart_data_entry(1, 2),
-	imx50_imx_uart_data_entry(2, 3),
-	imx50_imx_uart_data_entry(3, 4),
-	imx50_imx_uart_data_entry(4, 5),
-};
-#endif /* ifdef CONFIG_SOC_IMX50 */
-
 #ifdef CONFIG_SOC_IMX51
 const struct imx_imx_uart_1irq_data imx51_imx_uart_data[] __initconst = {
 #define imx51_imx_uart_data_entry(_id, _hwid)				\
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index e1537f9..a96ccc7 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -15,7 +15,7 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
-#include <asm/hardware/gic.h>
+#include <linux/irqchip/arm-gic.h>
 
 #define GPC_IMR1		0x008
 #define GPC_PGC_CPU_PDN		0x2a0
@@ -101,11 +101,16 @@
 void __init imx_gpc_init(void)
 {
 	struct device_node *np;
+	int i;
 
 	np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-gpc");
 	gpc_base = of_iomap(np, 0);
 	WARN_ON(!gpc_base);
 
+	/* Initially mask all interrupts */
+	for (i = 0; i < IMR_NUM; i++)
+		writel_relaxed(~0, gpc_base + GPC_IMR1 + i * 4);
+
 	/* Register GPC as the secondary interrupt controller behind GIC */
 	gic_arch_extn.irq_mask = imx_gpc_irq_mask;
 	gic_arch_extn.irq_unmask = imx_gpc_irq_unmask;
diff --git a/arch/arm/mach-imx/hardware.h b/arch/arm/mach-imx/hardware.h
index 3ce7fa3..911e9b31 100644
--- a/arch/arm/mach-imx/hardware.h
+++ b/arch/arm/mach-imx/hardware.h
@@ -72,11 +72,6 @@
  *	AVIC	0x68000000+0x100000	->	0xf5800000+0x100000
  *	X_MEMC	0xb8000000+0x010000	->	0xf5c00000+0x010000
  *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
- * mx50:
- *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
- *	AIPS1	0x53f00000+0x100000	->	0xf5700000+0x100000
- *	SPBA0	0x50000000+0x100000	->	0xf5400000+0x100000
- *	AIPS2	0x63f00000+0x100000	->	0xf5300000+0x100000
  * mx51:
  *	TZIC	0x0fffc000+0x004000	->	0xf4bfc000+0x004000
  *	IRAM	0x1ffe0000+0x020000	->	0xf4fe0000+0x020000
@@ -108,7 +103,6 @@
 #include "mxc.h"
 
 #include "mx6q.h"
-#include "mx50.h"
 #include "mx51.h"
 #include "mx53.h"
 #include "mx3x.h"
diff --git a/arch/arm/mach-imx/hotplug.c b/arch/arm/mach-imx/hotplug.c
index 3dec962..7bc5fe1 100644
--- a/arch/arm/mach-imx/hotplug.c
+++ b/arch/arm/mach-imx/hotplug.c
@@ -46,9 +46,11 @@
 void imx_cpu_die(unsigned int cpu)
 {
 	cpu_enter_lowpower();
-	imx_enable_cpu(cpu, false);
+	cpu_do_idle();
+}
 
-	/* spin here until hardware takes it down */
-	while (1)
-		;
+int imx_cpu_kill(unsigned int cpu)
+{
+	imx_enable_cpu(cpu, false);
+	return 1;
 }
diff --git a/arch/arm/mach-imx/imx25-dt.c b/arch/arm/mach-imx/imx25-dt.c
index e17dfbc..03b65e5 100644
--- a/arch/arm/mach-imx/imx25-dt.c
+++ b/arch/arm/mach-imx/imx25-dt.c
@@ -22,15 +22,6 @@
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static void __init imx25_timer_init(void)
-{
-	mx25_clocks_init_dt();
-}
-
-static struct sys_timer imx25_timer = {
-	.init = imx25_timer_init,
-};
-
 static const char * const imx25_dt_board_compat[] __initconst = {
 	"fsl,imx25",
 	NULL
@@ -41,7 +32,7 @@
 	.init_early	= imx25_init_early,
 	.init_irq	= mx25_init_irq,
 	.handle_irq	= imx25_handle_irq,
-	.timer		= &imx25_timer,
+	.init_time	= imx25_timer_init,
 	.init_machine	= imx25_dt_init,
 	.dt_compat	= imx25_dt_board_compat,
 	.restart	= mxc_restart,
diff --git a/arch/arm/mach-imx/imx27-dt.c b/arch/arm/mach-imx/imx27-dt.c
index ebfae96..c915a49 100644
--- a/arch/arm/mach-imx/imx27-dt.c
+++ b/arch/arm/mach-imx/imx27-dt.c
@@ -39,26 +39,22 @@
 			     imx27_auxdata_lookup, NULL);
 }
 
-static void __init imx27_timer_init(void)
-{
-	mx27_clocks_init_dt();
-}
-
-static struct sys_timer imx27_timer = {
-	.init = imx27_timer_init,
-};
-
 static const char * const imx27_dt_board_compat[] __initconst = {
 	"fsl,imx27",
 	NULL
 };
 
+static void __init imx27_timer_init(void)
+{
+	mx27_clocks_init_dt();
+}
+
 DT_MACHINE_START(IMX27_DT, "Freescale i.MX27 (Device Tree Support)")
 	.map_io		= mx27_map_io,
 	.init_early	= imx27_init_early,
 	.init_irq	= mx27_init_irq,
 	.handle_irq	= imx27_handle_irq,
-	.timer		= &imx27_timer,
+	.init_time	= imx27_timer_init,
 	.init_machine	= imx27_dt_init,
 	.dt_compat	= imx27_dt_board_compat,
 	.restart	= mxc_restart,
diff --git a/arch/arm/mach-imx/imx31-dt.c b/arch/arm/mach-imx/imx31-dt.c
index af476de..00737eb 100644
--- a/arch/arm/mach-imx/imx31-dt.c
+++ b/arch/arm/mach-imx/imx31-dt.c
@@ -18,35 +18,11 @@
 #include "common.h"
 #include "mx31.h"
 
-static const struct of_dev_auxdata imx31_auxdata_lookup[] __initconst = {
-	OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART1_BASE_ADDR,
-			"imx21-uart.0", NULL),
-	OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART2_BASE_ADDR,
-			"imx21-uart.1", NULL),
-	OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART3_BASE_ADDR,
-			"imx21-uart.2", NULL),
-	OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART4_BASE_ADDR,
-			"imx21-uart.3", NULL),
-	OF_DEV_AUXDATA("fsl,imx31-uart", MX31_UART5_BASE_ADDR,
-			"imx21-uart.4", NULL),
-	{ /* sentinel */ }
-};
-
 static void __init imx31_dt_init(void)
 {
-	of_platform_populate(NULL, of_default_bus_match_table,
-			     imx31_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static void __init imx31_timer_init(void)
-{
-	mx31_clocks_init_dt();
-}
-
-static struct sys_timer imx31_timer = {
-	.init = imx31_timer_init,
-};
-
 static const char *imx31_dt_board_compat[] __initdata = {
 	"fsl,imx31",
 	NULL
@@ -57,7 +33,7 @@
 	.init_early	= imx31_init_early,
 	.init_irq	= mx31_init_irq,
 	.handle_irq	= imx31_handle_irq,
-	.timer		= &imx31_timer,
+	.init_time	= mx31_clocks_init_dt,
 	.init_machine	= imx31_dt_init,
 	.dt_compat	= imx31_dt_board_compat,
 	.restart	= mxc_restart,
diff --git a/arch/arm/mach-imx/imx51-dt.c b/arch/arm/mach-imx/imx51-dt.c
index 5ffa40c..e2926a8 100644
--- a/arch/arm/mach-imx/imx51-dt.c
+++ b/arch/arm/mach-imx/imx51-dt.c
@@ -24,26 +24,22 @@
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static void __init imx51_timer_init(void)
-{
-	mx51_clocks_init_dt();
-}
-
-static struct sys_timer imx51_timer = {
-	.init = imx51_timer_init,
-};
-
 static const char *imx51_dt_board_compat[] __initdata = {
 	"fsl,imx51",
 	NULL
 };
 
+static void __init imx51_timer_init(void)
+{
+	mx51_clocks_init_dt();
+}
+
 DT_MACHINE_START(IMX51_DT, "Freescale i.MX51 (Device Tree Support)")
 	.map_io		= mx51_map_io,
 	.init_early	= imx51_init_early,
 	.init_irq	= mx51_init_irq,
 	.handle_irq	= imx51_handle_irq,
-	.timer		= &imx51_timer,
+	.init_time	= imx51_timer_init,
 	.init_machine	= imx51_dt_init,
 	.init_late	= imx51_init_late,
 	.dt_compat	= imx51_dt_board_compat,
diff --git a/arch/arm/mach-imx/iomux-mx50.h b/arch/arm/mach-imx/iomux-mx50.h
deleted file mode 100644
index 00f56e0..0000000
--- a/arch/arm/mach-imx/iomux-mx50.h
+++ /dev/null
@@ -1,977 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#ifndef __MACH_IOMUX_MX50_H__
-#define __MACH_IOMUX_MX50_H__
-
-#include "iomux-v3.h"
-
-#define MX50_ELCDIF_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
-
-#define MX50_SD_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_PUS_47K_UP | PAD_CTL_DSE_HIGH)
-
-#define MX50_UART_PAD_CTRL	(PAD_CTL_DSE_HIGH | PAD_CTL_PKE)
-
-#define MX50_I2C_PAD_CTRL	(PAD_CTL_ODE | PAD_CTL_DSE_HIGH | \
-					PAD_CTL_PUS_100K_UP | PAD_CTL_HYS)
-
-#define MX50_USB_PAD_CTRL	(PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_DSE_HIGH | PAD_CTL_PUS_47K_UP)
-
-#define MX50_FEC_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_PUS_22K_UP | PAD_CTL_ODE | \
-					PAD_CTL_DSE_HIGH)
-
-#define MX50_OWIRE_PAD_CTRL	(PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_PUS_100K_UP | PAD_CTL_ODE | \
-					PAD_CTL_DSE_HIGH | PAD_CTL_SRE_FAST)
-
-#define MX50_KEYPAD_CTRL        (PAD_CTL_HYS | PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_PUS_100K_UP | PAD_CTL_DSE_HIGH)
-
-#define MX50_CSPI_SS_PAD	(PAD_CTL_PKE | PAD_CTL_PUE | \
-					PAD_CTL_PUS_22K_UP | PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_COL0__KEY_COL0	IOMUX_PAD(0x2CC, 0x20, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL0__GPIO_4_0	IOMUX_PAD(0x2CC, 0x20, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL0__NANDF_CLE	IOMUX_PAD(0x2CC, 0x20, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_ROW0__KEY_ROW0	IOMUX_PAD(0x2D0, 0x24, 0, 0x0, 0, MX50_KEYPAD_CTRL)
-#define MX50_PAD_KEY_ROW0__GPIO_4_1	IOMUX_PAD(0x2D0, 0x24, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_ROW0__NANDF_ALE	IOMUX_PAD(0x2D0, 0x24, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_COL1__KEY_COL1	IOMUX_PAD(0x2D4, 0x28, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL1__GPIO_4_2	IOMUX_PAD(0x2D4, 0x28, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL1__NANDF_CE0	IOMUX_PAD(0x2D4, 0x28, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_ROW1__KEY_ROW1	IOMUX_PAD(0x2D8, 0x2C, 0, 0x0, 0, MX50_KEYPAD_CTRL)
-#define MX50_PAD_KEY_ROW1__GPIO_4_3	IOMUX_PAD(0x2D8, 0x2C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_ROW1__NANDF_CE1	IOMUX_PAD(0x2D8, 0x2C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_COL2__KEY_COL2	IOMUX_PAD(0x2DC, 0x30, 0, 0x0, 0, MX50_KEYPAD_CTRL)
-#define MX50_PAD_KEY_COL2__GPIO_4_4	IOMUX_PAD(0x2DC, 0x30, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL2__NANDF_CE2	IOMUX_PAD(0x2DC, 0x30, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_ROW2__KEY_ROW2	IOMUX_PAD(0x2E0, 0x34, 0, 0x0, 0, MX50_KEYPAD_CTRL)
-#define MX50_PAD_KEY_ROW2__GPIO_4_5	IOMUX_PAD(0x2E0, 0x34, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_ROW2__NANDF_CE3	IOMUX_PAD(0x2E0, 0x34, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_KEY_COL3__KEY_COL3	IOMUX_PAD(0x2E4, 0x38, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL3__GPIO_4_6	IOMUX_PAD(0x2E4, 0x38, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_COL3__NANDF_READY	IOMUX_PAD(0x2E4, 0x38, 2, 0x7b4, 0, PAD_CTL_PKE | \
-							PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
-#define MX50_PAD_KEY_COL3__SDMA_EXT0	IOMUX_PAD(0x2E4, 0x38, 6, 0x7b8, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_KEY_ROW3__KEY_ROW3	IOMUX_PAD(0x2E8, 0x3C, 0, 0x0, 0, MX50_KEYPAD_CTRL)
-#define MX50_PAD_KEY_ROW3__GPIO_4_7	IOMUX_PAD(0x2E8, 0x3C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_KEY_ROW3__NANDF_DQS	IOMUX_PAD(0x2E8, 0x3C, 2, 0x7b0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_KEY_ROW3__SDMA_EXT1	IOMUX_PAD(0x2E8, 0x3C, 6, 0x7bc, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_I2C1_SCL__I2C1_SCL	IOMUX_PAD(0x2EC, 0x40, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C1_SCL__GPIO_6_18	IOMUX_PAD(0x2EC, 0x40, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C1_SCL__UART2_TXD	IOMUX_PAD(0x2EC, 0x40, 2, 0x0, 0, MX50_UART_PAD_CTRL)
-
-#define MX50_PAD_I2C1_SDA__I2C1_SDA	IOMUX_PAD(0x2F0, 0x44, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C1_SDA__GPIO_6_19	IOMUX_PAD(0x2F0, 0x44, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C1_SDA__UART2_RXD	IOMUX_PAD(0x2F0, 0x44, 2, 0x7cc, 1, MX50_UART_PAD_CTRL)
-
-#define MX50_PAD_I2C2_SCL__I2C2_SCL	IOMUX_PAD(0x2F4, 0x48, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C2_SCL__GPIO_6_20	IOMUX_PAD(0x2F4, 0x48, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C2_SCL__UART2_CTS	IOMUX_PAD(0x2F4, 0x48, 2, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_I2C2_SCL__DCDC_OK	IOMUX_PAD(0x2F4, 0x48, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_I2C2_SDA__I2C2_SDA	IOMUX_PAD(0x2F8, 0x4C, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C2_SDA__GPIO_6_21	IOMUX_PAD(0x2F8, 0x4C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C2_SDA__UART2_RTS	IOMUX_PAD(0x2F8, 0x4C, 2, 0x7c8, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_I2C2_SDA__PWRSTABLE	IOMUX_PAD(0x2F8, 0x4C, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_I2C3_SCL__I2C3_SCL	IOMUX_PAD(0x2FC, 0x50, IOMUX_CONFIG_SION, 0x0, 0, \
-							MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C3_SCL__GPIO_6_22	IOMUX_PAD(0x2FC, 0x50, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SCL__FEC_MDC	IOMUX_PAD(0x2FC, 0x50, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_I2C3_SCL__PMIC_RDY	IOMUX_PAD(0x2FC, 0x50, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SCL__GPT_CAPIN1	IOMUX_PAD(0x2FC, 0x50, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SCL__USBOTG_OC	IOMUX_PAD(0x2FC, 0x50, 7, 0x7E8, 0, MX50_USB_PAD_CTRL)
-
-#define MX50_PAD_I2C3_SDA__I2C3_SDA	IOMUX_PAD(0x300, 0x54, IOMUX_CONFIG_SION, 0x0, 0, \
-								MX50_I2C_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__GPIO_6_23	IOMUX_PAD(0x300, 0x54, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__FEC_MDIO	IOMUX_PAD(0x300, 0x54, 2, 0x774, 0, MX50_FEC_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__PWRFAIL_INT	IOMUX_PAD(0x300, 0x54, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__ALARM_DEB	IOMUX_PAD(0x300, 0x54, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__GPT_CAPIN1	IOMUX_PAD(0x300, 0x54, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_I2C3_SDA__USBOTG_PWR	IOMUX_PAD(0x300, 0x54, 7, 0x0, 0, \
-							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_PWM1__PWM1_PWMO	IOMUX_PAD(0x304, 0x58, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM1__GPIO_6_24	IOMUX_PAD(0x304, 0x58, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM1__USBOTG_OC	IOMUX_PAD(0x304, 0x58, 2, 0x7E8, 1, MX50_USB_PAD_CTRL)
-#define MX50_PAD_PWM1__GPT_CMPOUT1	IOMUX_PAD(0x304, 0x58, 5, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PWM2__PWM2_PWMO	IOMUX_PAD(0x308, 0x5C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM2__GPIO_6_25	IOMUX_PAD(0x308, 0x5C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM2__USBOTG_PWR	IOMUX_PAD(0x308, 0x5C, 2, 0x0, 0, \
-							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
-#define MX50_PAD_PWM2__DCDC_PWM		IOMUX_PAD(0x308, 0x5C, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM2__GPT_CMPOUT2	IOMUX_PAD(0x308, 0x5C, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_PWM2__ANY_PU_RST	IOMUX_PAD(0x308, 0x5C, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_OWIRE__OWIRE		IOMUX_PAD(0x30C, 0x60, 0, 0x0, 0, MX50_OWIRE_PAD_CTRL)
-#define MX50_PAD_OWIRE__GPIO_6_26	IOMUX_PAD(0x30C, 0x60, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_OWIRE__USBH1_OC	IOMUX_PAD(0x30C, 0x60, 2, 0x0, 0, MX50_USB_PAD_CTRL)
-#define MX50_PAD_OWIRE__SSI_EXT1_CLK	IOMUX_PAD(0x30C, 0x60, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_OWIRE__EPDC_PWRIRQ	IOMUX_PAD(0x30C, 0x60, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_OWIRE__GPT_CMPOUT3	IOMUX_PAD(0x30C, 0x60, 5, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPITO__EPITO		IOMUX_PAD(0x310, 0x64, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPITO__GPIO_6_27	IOMUX_PAD(0x310, 0x64, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPITO__USBH1_PWR	IOMUX_PAD(0x310, 0x64, 2, 0x0, 0, \
-							PAD_CTL_PKE | PAD_CTL_DSE_HIGH)
-#define MX50_PAD_EPITO__SSI_EXT2_CLK	IOMUX_PAD(0x310, 0x64, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPITO__TOG_EN		IOMUX_PAD(0x310, 0x64, 4, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPITO__GPT_CLKIN	IOMUX_PAD(0x310, 0x64, 5, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_WDOG__WDOG		IOMUX_PAD(0x314, 0x68, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_WDOG__GPIO_6_28	IOMUX_PAD(0x314, 0x68, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_WDOG__WDOG_RST		IOMUX_PAD(0x314, 0x68, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_WDOG__XTAL32K		IOMUX_PAD(0x314, 0x68, 6, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SSI_TXFS__SSI_TXFS	IOMUX_PAD(0x318, 0x6C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_TXFS__GPIO_6_0	IOMUX_PAD(0x318, 0x6C, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SSI_TXC__SSI_TXC	IOMUX_PAD(0x31C, 0x70, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_TXC__GPIO_6_1	IOMUX_PAD(0x31C, 0x70, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SSI_TXD__SSI_TXD	IOMUX_PAD(0x320, 0x74, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_TXD__GPIO_6_2	IOMUX_PAD(0x320, 0x74, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_TXD__CSPI_RDY	IOMUX_PAD(0x320, 0x74, 4, 0x6e8, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SSI_RXD__SSI_RXD	IOMUX_PAD(0x324, 0x78, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXD__GPIO_6_3	IOMUX_PAD(0x324, 0x78, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXD__CSPI_SS3	IOMUX_PAD(0x324, 0x78, 4, 0x6f4, 0, MX50_CSPI_SS_PAD)
-
-#define MX50_PAD_SSI_RXFS__AUD3_RXFS	IOMUX_PAD(0x328, 0x7C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXFS__GPIO_6_4	IOMUX_PAD(0x328, 0x7C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXFS__UART5_TXD	IOMUX_PAD(0x328, 0x7C, 2, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_SSI_RXFS__WEIM_D6	IOMUX_PAD(0x328, 0x7C, 3, 0x804, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXFS__CSPI_SS2	IOMUX_PAD(0x328, 0x7C, 4, 0x6f0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_SSI_RXFS__FEC_COL	IOMUX_PAD(0x328, 0x7C, 5, 0x770, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SSI_RXFS__FEC_MDC	IOMUX_PAD(0x328, 0x7C, 6, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_SSI_RXC__AUD3_RXC	IOMUX_PAD(0x32C, 0x80, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXC__GPIO_6_5	IOMUX_PAD(0x32C, 0x80, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXC__UART5_RXD	IOMUX_PAD(0x32C, 0x80, 2, 0x7e4, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_SSI_RXC__WEIM_D7	IOMUX_PAD(0x32C, 0x80, 3, 0x808, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXC__CSPI_SS1	IOMUX_PAD(0x32C, 0x80, 4, 0x6ec, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_SSI_RXC__FEC_RX_CLK	IOMUX_PAD(0x32C, 0x80, 5, 0x780, 0, NO_PAD_CTRL)
-#define MX50_PAD_SSI_RXC__FEC_MDIO	IOMUX_PAD(0x32C, 0x80, 6, 0x774, 1, MX50_FEC_PAD_CTRL)
-
-#define MX50_PAD_UART1_TXD__UART1_TXD	IOMUX_PAD(0x330, 0x84, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_TXD__GPIO_6_6	IOMUX_PAD(0x330, 0x84, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_UART1_RXD__UART1_RXD	IOMUX_PAD(0x334, 0x88, 0, 0x7c4, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_RXD__GPIO_6_7	IOMUX_PAD(0x334, 0x88, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_UART1_CTS__UART1_CTS	IOMUX_PAD(0x338, 0x8C, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_CTS__GPIO_6_8	IOMUX_PAD(0x338, 0x8C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART1_CTS__UART5_TXD	IOMUX_PAD(0x338, 0x8C, 2, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_CTS__SD4_D4	IOMUX_PAD(0x338, 0x8C, 4, 0x760, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART1_CTS__SD4_CMD	IOMUX_PAD(0x338, 0x8C, 5, 0x74c, 0, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART1_RTS__UART1_RTS	IOMUX_PAD(0x33C, 0x90, 0, 0x7c0, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__GPIO_6_9	IOMUX_PAD(0x33C, 0x90, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__UART5_RXD	IOMUX_PAD(0x33C, 0x90, 2, 0x7e4, 3, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__SD4_D5	IOMUX_PAD(0x33C, 0x90, 4, 0x764, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART1_RTS__SD4_CLK	IOMUX_PAD(0x33C, 0x90, 5, 0x748, 0, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART2_TXD__UART2_TXD	IOMUX_PAD(0x340, 0x94, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART2_TXD__GPIO_6_10	IOMUX_PAD(0x340, 0x94, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART2_TXD__SD4_D6	IOMUX_PAD(0x340, 0x94, 4, 0x768, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART2_TXD__SD4_D4	IOMUX_PAD(0x340, 0x94, 5, 0x760, 1, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART2_RXD__UART2_RXD	IOMUX_PAD(0x344, 0x98, 0, 0x7cc, 3, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART2_RXD__GPIO_6_11	IOMUX_PAD(0x344, 0x98, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART2_RXD__SD4_D7	IOMUX_PAD(0x344, 0x98, 4, 0x76c, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART2_RXD__SD4_D5	IOMUX_PAD(0x344, 0x98, 5, 0x764, 1, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART2_CTS__UART2_CTS	IOMUX_PAD(0x348, 0x9C, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART2_CTS__GPIO_6_12	IOMUX_PAD(0x348, 0x9C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART2_CTS__SD4_CMD	IOMUX_PAD(0x348, 0x9C, 4, 0x74c, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART2_CTS__SD4_D6	IOMUX_PAD(0x348, 0x9C, 5, 0x768, 1, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART2_RTS__UART2_RTS	IOMUX_PAD(0x34C, 0xA0, 0, 0x7c8, 3, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART2_RTS__GPIO_6_13	IOMUX_PAD(0x34C, 0xA0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART2_RTS__SD4_CLK	IOMUX_PAD(0x34C, 0xA0, 4, 0x748, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART2_RTS__SD4_D7	IOMUX_PAD(0x34C, 0xA0, 5, 0x76c, 1, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_UART3_TXD__UART3_TXD	IOMUX_PAD(0x350, 0xA4, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART3_TXD__GPIO_6_14	IOMUX_PAD(0x350, 0xA4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART3_TXD__SD1_D4	IOMUX_PAD(0x350, 0xA4, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_TXD__SD4_D0	IOMUX_PAD(0x350, 0xA4, 4, 0x750, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_TXD__SD2_WP	IOMUX_PAD(0x350, 0xA4, 5, 0x744, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_TXD__WEIM_D12	IOMUX_PAD(0x350, 0xA4, 6, 0x81c, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_UART3_RXD__UART3_RXD	IOMUX_PAD(0x354, 0xA8, 0, 0x7d4, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART3_RXD__GPIO_6_15	IOMUX_PAD(0x354, 0xA8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART3_RXD__SD1_D5	IOMUX_PAD(0x354, 0xA8, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_RXD__SD4_D1	IOMUX_PAD(0x354, 0xA8, 4, 0x754, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_RXD__SD2_CD	IOMUX_PAD(0x354, 0xA8, 5, 0x740, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART3_RXD__WEIM_D13	IOMUX_PAD(0x354, 0xA8, 6, 0x820, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_UART4_TXD__UART4_TXD	IOMUX_PAD(0x358, 0xAC, 0, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__GPIO_6_16	IOMUX_PAD(0x358, 0xAC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__UART3_CTS	IOMUX_PAD(0x358, 0xAC, 2, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__SD1_D6	IOMUX_PAD(0x358, 0xAC, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__SD4_D2	IOMUX_PAD(0x358, 0xAC, 4, 0x758, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__SD2_LCTL	IOMUX_PAD(0x358, 0xAC, 5, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_TXD__WEIM_D14	IOMUX_PAD(0x358, 0xAC, 6, 0x824, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_UART4_RXD__UART4_RXD	IOMUX_PAD(0x35C, 0xB0, 0, 0x7dc, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__GPIO_6_17	IOMUX_PAD(0x35C, 0xB0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__UART3_RTS	IOMUX_PAD(0x35C, 0xB0, 2, 0x7d0, 1, MX50_UART_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__SD1_D7	IOMUX_PAD(0x35C, 0xB0, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__SD4_D3	IOMUX_PAD(0x35C, 0xB0, 4, 0x75c, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__SD1_LCTL	IOMUX_PAD(0x35C, 0xB0, 5, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_UART4_RXD__WEIM_D15	IOMUX_PAD(0x35C, 0xB0, 6, 0x828, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_CSPI_SCLK__CSPI_SCLK	IOMUX_PAD(0x360, 0xB4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_CSPI_SCLK__GPIO_4_8	IOMUX_PAD(0x360, 0xB4, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_CSPI_MOSI__CSPI_MOSI	IOMUX_PAD(0x364, 0xB8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_CSPI_MOSI__GPIO_4_9	IOMUX_PAD(0x364, 0xB8, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_CSPI_MISO__CSPI_MISO	IOMUX_PAD(0x368, 0xBC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_CSPI_MISO__GPIO_4_10	IOMUX_PAD(0x368, 0xBC, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_CSPI_SS0__CSPI_SS0	IOMUX_PAD(0x36C, 0xC0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_CSPI_SS0__GPIO_4_11	IOMUX_PAD(0x36C, 0xC0, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI1_SCLK__ECSPI1_SCLK	IOMUX_PAD(0x370, 0xC4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__GPIO_4_12		IOMUX_PAD(0x370, 0xC4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__CSPI_RDY		IOMUX_PAD(0x370, 0xC4, 2, 0x6e8, 1, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__ECSPI2_RDY	IOMUX_PAD(0x370, 0xC4, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__UART3_RTS		IOMUX_PAD(0x370, 0xC4, 4, 0x7d0, 2, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__EPDC_SDCE6	IOMUX_PAD(0x370, 0xC4, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SCLK__WEIM_D8		IOMUX_PAD(0x370, 0xC4, 7, 0x80c, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI1_MOSI__ECSPI1_MOSI	IOMUX_PAD(0x374, 0xC8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MOSI__GPIO_4_13		IOMUX_PAD(0x374, 0xC8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MOSI__CSPI_SS1		IOMUX_PAD(0x374, 0xC8, 2, 0x6ec, 1, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_MOSI__ECSPI2_SS1	IOMUX_PAD(0x374, 0xC8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_MOSI__UART3_CTS		IOMUX_PAD(0x374, 0xC8, 4, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MOSI__EPDC_SDCE7	IOMUX_PAD(0x374, 0xC8, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MOSI__WEIM_D9		IOMUX_PAD(0x374, 0xC8, 7, 0x810, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI1_MISO__ECSPI1_MISO	IOMUX_PAD(0x378, 0xCC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MISO__GPIO_4_14		IOMUX_PAD(0x378, 0xCC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MISO__CSPI_SS2		IOMUX_PAD(0x378, 0xCC, 2, 0x6f0, 1, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_MISO__ECSPI2_SS2	IOMUX_PAD(0x378, 0xCC, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_MISO__UART4_RTS		IOMUX_PAD(0x378, 0xCC, 4, 0x7d8, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MISO__EPDC_SDCE8	IOMUX_PAD(0x378, 0xCC, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_MISO__WEIM_D10		IOMUX_PAD(0x378, 0xCC, 7, 0x814, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI1_SS0__ECSPI1_SS0		IOMUX_PAD(0x37C, 0xD0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_SS0__GPIO_4_15		IOMUX_PAD(0x37C, 0xD0, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
-#define MX50_PAD_ECSPI1_SS0__CSPI_SS3		IOMUX_PAD(0x37C, 0xD0, 2, 0x6f4, 1, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_SS0__ECSPI2_SS3		IOMUX_PAD(0x37C, 0xD0, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI1_SS0__UART4_CTS		IOMUX_PAD(0x37C, 0xD0, 4, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SS0__EPDC_SDCE9		IOMUX_PAD(0x37C, 0xD0, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI1_SS0__WEIM_D11		IOMUX_PAD(0x37C, 0xD0, 7, 0x818, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI2_SCLK__ECSPI2_SCLK	IOMUX_PAD(0x380, 0xD4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__GPIO_4_16		IOMUX_PAD(0x380, 0xD4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__ELCDIF_WR		IOMUX_PAD(0x380, 0xD4, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__ECSPI1_RDY	IOMUX_PAD(0x380, 0xD4, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__UART5_RTS		IOMUX_PAD(0x380, 0xD4, 4, 0x7e0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__ELCDIF_DOTCLK	IOMUX_PAD(0x380, 0xD4, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__NANDF_CEN4	IOMUX_PAD(0x380, 0xD4, 6, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SCLK__WEIM_D8		IOMUX_PAD(0x380, 0xD4, 7, 0x80c, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI2_MOSI__ECSPI2_MOSI	IOMUX_PAD(0x384, 0xD8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__GPIO_4_17		IOMUX_PAD(0x384, 0xD8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__ELCDIF_RD		IOMUX_PAD(0x384, 0xD8, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__ECSPI1_SS1	IOMUX_PAD(0x384, 0xD8, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_MOSI__UART5_CTS		IOMUX_PAD(0x384, 0xD8, 4, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__ELCDIF_EN		IOMUX_PAD(0x384, 0xD8, 5, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__NANDF_CEN5	IOMUX_PAD(0x384, 0xD8, 6, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MOSI__WEIM_D9		IOMUX_PAD(0x384, 0xD8, 7, 0x810, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI2_MISO__ECSPI2_MISO	IOMUX_PAD(0x388, 0xDC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__GPIO_4_18		IOMUX_PAD(0x388, 0xDC, 1, 0x0, 0, PAD_CTL_PUS_100K_UP)
-#define MX50_PAD_ECSPI2_MISO__ELCDIF_RS		IOMUX_PAD(0x388, 0xDC, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__ECSPI1_SS2	IOMUX_PAD(0x388, 0xDC, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_MISO__UART5_TXD		IOMUX_PAD(0x388, 0xDC, 4, 0x0, 0, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__ELCDIF_VSYNC	IOMUX_PAD(0x388, 0xDC, 5, 0x73c, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__NANDF_CEN6	IOMUX_PAD(0x388, 0xDC, 6, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_MISO__WEIM_D10		IOMUX_PAD(0x388, 0xDC, 7, 0x814, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_ECSPI2_SS0__ECSPI2_SS0		IOMUX_PAD(0x38C, 0xE0, 0, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_SS0__GPIO_4_19		IOMUX_PAD(0x38C, 0xE0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SS0__ELCDIF_CS		IOMUX_PAD(0x38C, 0xE0, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SS0__ECSPI1_SS3		IOMUX_PAD(0x38C, 0xE0, 3, 0x0, 0, MX50_CSPI_SS_PAD)
-#define MX50_PAD_ECSPI2_SS0__UART5_RXD		IOMUX_PAD(0x38C, 0xE0, 4, 0x7e4, 5, MX50_UART_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SS0__ELCDIF_HSYNC	IOMUX_PAD(0x38C, 0xE0, 5, 0x6f8, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SS0__NANDF_CEN7		IOMUX_PAD(0x38C, 0xE0, 6, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_ECSPI2_SS0__WEIM_D11		IOMUX_PAD(0x38C, 0xE0, 7, 0x818, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_CLK__SD1_CLK	IOMUX_PAD(0x390, 0xE4, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_CLK__GPIO_5_0	IOMUX_PAD(0x390, 0xE4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD1_CLK__CLKO		IOMUX_PAD(0x390, 0xE4, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_CMD__SD1_CMD	IOMUX_PAD(0x394, 0xE8, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_CMD__GPIO_5_1	IOMUX_PAD(0x394, 0xE8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD1_CMD__CLKO2		IOMUX_PAD(0x394, 0xE8, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_D0__SD1_D0		IOMUX_PAD(0x398, 0xEC, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_D0__GPIO_5_2	IOMUX_PAD(0x398, 0xEC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD1_D0__PLL1_BYP	IOMUX_PAD(0x398, 0xEC, 7, 0x6dc, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_D1__SD1_D1		IOMUX_PAD(0x39C, 0xF0, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_D1__GPIO_5_3	IOMUX_PAD(0x39C, 0xF0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD1_D1__PLL2_BYP	IOMUX_PAD(0x39C, 0xF0, 7, 0x6e0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_D2__SD1_D2		IOMUX_PAD(0x3A0, 0xF4, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_D2__GPIO_5_4	IOMUX_PAD(0x3A0, 0xF4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD1_D2__PLL3_BYP	IOMUX_PAD(0x3A0, 0xF4, 7, 0x6e4, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD1_D3__SD1_D3		IOMUX_PAD(0x3A4, 0xF8, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD1_D3__GPIO_5_5	IOMUX_PAD(0x3A4, 0xF8, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_CLK__SD2_CLK	IOMUX_PAD(0x3A8, 0xFC, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_CLK__GPIO_5_6	IOMUX_PAD(0x3A8, 0xFC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_CLK__MSHC_SCLK	IOMUX_PAD(0x3A8, 0xFC, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_SD2_CMD__SD2_CMD	IOMUX_PAD(0x3AC, 0x100, IOMUX_CONFIG_SION, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_CMD__GPIO_5_7	IOMUX_PAD(0x3AC, 0x100, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_CMD__MSHC_BS	IOMUX_PAD(0x3AC, 0x100, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-
-#define MX50_PAD_SD2_D0__SD2_D0		IOMUX_PAD(0x3B0, 0x104, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D0__GPIO_5_8	IOMUX_PAD(0x3B0, 0x104, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D0__MSHC_D0	IOMUX_PAD(0x3B0, 0x104, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D0__KEY_COL4	IOMUX_PAD(0x3B0, 0x104, 3, 0x790, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D1__SD2_D1		IOMUX_PAD(0x3B4, 0x108, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D1__GPIO_5_9	IOMUX_PAD(0x3B4, 0x108, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D1__MSHC_D1	IOMUX_PAD(0x3B4, 0x108, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D1__KEY_ROW4	IOMUX_PAD(0x3B4, 0x108, 3, 0x7a0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D2__SD2_D2		IOMUX_PAD(0x3B8, 0x10C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D2__GPIO_5_10	IOMUX_PAD(0x3B8, 0x10C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D2__MSHC_D2	IOMUX_PAD(0x3B8, 0x10C, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D2__KEY_COL5	IOMUX_PAD(0x3B8, 0x10C, 3, 0x794, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D3__SD2_D3		IOMUX_PAD(0x3BC, 0x110, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D3__GPIO_5_11	IOMUX_PAD(0x3BC, 0x110, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D3__MSHC_D3	IOMUX_PAD(0x3BC, 0x110, 2, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D3__KEY_ROW5	IOMUX_PAD(0x3BC, 0x110, 3, 0x7a4, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D4__SD2_D4		IOMUX_PAD(0x3C0, 0x114, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D4__GPIO_5_12	IOMUX_PAD(0x3C0, 0x114, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D4__AUD4_RXFS	IOMUX_PAD(0x3C0, 0x114, 2, 0x6d0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D4__KEY_COL6	IOMUX_PAD(0x3C0, 0x114, 3, 0x798, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D4__WEIM_D0	IOMUX_PAD(0x3C0, 0x114, 4, 0x7ec, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D4__CCM_OUT0	IOMUX_PAD(0x3C0, 0x114, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D5__SD2_D5		IOMUX_PAD(0x3C4, 0x118, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D5__GPIO_5_13	IOMUX_PAD(0x3C4, 0x118, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D5__AUD4_RXC	IOMUX_PAD(0x3C4, 0x118, 2, 0x6cc, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D5__KEY_ROW6	IOMUX_PAD(0x3C4, 0x118, 3, 0x7a8, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D5__WEIM_D1	IOMUX_PAD(0x3C4, 0x118, 4, 0x7f0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D5__CCM_OUT1	IOMUX_PAD(0x3C4, 0x118, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D6__SD2_D6		IOMUX_PAD(0x3C8, 0x11C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D6__GPIO_5_14	IOMUX_PAD(0x3C8, 0x11C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D6__AUD4_RXD	IOMUX_PAD(0x3C8, 0x11C, 2, 0x6c4, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D6__KEY_COL7	IOMUX_PAD(0x3C8, 0x11C, 3, 0x79c, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D6__WEIM_D2	IOMUX_PAD(0x3C8, 0x11C, 4, 0x7f4, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D6__CCM_OUT2	IOMUX_PAD(0x3C8, 0x11C, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_D7__SD2_D7		IOMUX_PAD(0x3CC, 0x120, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_D7__GPIO_5_15	IOMUX_PAD(0x3CC, 0x120, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D7__AUD4_TXFS	IOMUX_PAD(0x3CC, 0x120, 2, 0x6d8, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D7__KEY_ROW7	IOMUX_PAD(0x3CC, 0x120, 3, 0x7ac, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D7__WEIM_D3	IOMUX_PAD(0x3CC, 0x120, 4, 0x7f8, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_D7__CCM_STOP	IOMUX_PAD(0x3CC, 0x120, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_WP__SD2_WP		IOMUX_PAD(0x3D0, 0x124, 0, 0x744, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_WP__GPIO_5_16	IOMUX_PAD(0x3D0, 0x124, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_WP__AUD4_TXD	IOMUX_PAD(0x3D0, 0x124, 2, 0x6c8, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_WP__WEIM_D4	IOMUX_PAD(0x3D0, 0x124, 4, 0x7fc, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_WP__CCM_WAIT	IOMUX_PAD(0x3D0, 0x124, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD2_CD__SD2_CD		IOMUX_PAD(0x3D4, 0x128, 0, 0x740, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD2_CD__GPIO_5_17	IOMUX_PAD(0x3D4, 0x128, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_CD__AUD4_TXC	IOMUX_PAD(0x3D4, 0x128, 2, 0x6d4, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_CD__WEIM_D5	IOMUX_PAD(0x3D4, 0x128, 4, 0x800, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD2_CD__CCM_REF_EN	IOMUX_PAD(0x3D4, 0x128, 7, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_ON_REQ__PMIC_ON_REQ	IOMUX_PAD(0x3D8, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_STBY_REQ__PMIC_STBY_REQ	IOMUX_PAD(0x3DC, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_PORT_B__PMIC_PORT_B	IOMUX_PAD(0x3E0, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_BOOT_MODE1__PMIC_BOOT_MODE1	IOMUX_PAD(0x3E4, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_RESET_IN_B__PMIC_RESET_IN_B	IOMUX_PAD(0x3E8, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_BOOT_MODE0__PMIC_BOOT_MODE0	IOMUX_PAD(0x3EC, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_TEST_MODE__PMIC_TEST_MODE	IOMUX_PAD(0x3F0, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_TMS__PMIC_JTAG_TMS	IOMUX_PAD(0x3F4, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_MOD__PMIC_JTAG_MOD	IOMUX_PAD(0x3F8, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_TRSTB__PMIC_JTAG_TRSTB	IOMUX_PAD(0x3FC, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_TDI__PMIC_JTAG_TDI	IOMUX_PAD(0x400, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_TCK__PMIC_JTAG_TCK	IOMUX_PAD(0x404, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_PMIC_JTAG_TDO__PMIC_JTAG_TDO	IOMUX_PAD(0x408, 0, 0, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D0__DISP_D0	IOMUX_PAD(0x40C, 0x12C, 0, 0x6fc, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D0__GPIO_2_0	IOMUX_PAD(0x40C, 0x12C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D0__FEC_TXCLK	IOMUX_PAD(0x40C, 0x12C, 2, 0x78c, 0, PAD_CTL_HYS | PAD_CTL_PKE)
-
-#define MX50_PAD_DISP_D1__DISP_D1	IOMUX_PAD(0x410, 0x130, 0, 0x700, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D1__GPIO_2_1	IOMUX_PAD(0x410, 0x130, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D1__FEC_RX_ER	IOMUX_PAD(0x410, 0x130, 2, 0x788, 0, PAD_CTL_HYS | PAD_CTL_PKE)
-#define MX50_PAD_DISP_D1__WEIM_A17	IOMUX_PAD(0x410, 0x130, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D2__DISP_D2	IOMUX_PAD(0x414, 0x134, 0, 0x704, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D2__GPIO_2_2	IOMUX_PAD(0x414, 0x134, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D2__FEC_RX_DV	IOMUX_PAD(0x414, 0x134, 2, 0x784, 0, PAD_CTL_HYS | PAD_CTL_PKE)
-#define MX50_PAD_DISP_D2__WEIM_A18	IOMUX_PAD(0x414, 0x134, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D3__DISP_D3	IOMUX_PAD(0x418, 0x138, 0, 0x708, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D3__GPIO_2_3	IOMUX_PAD(0x418, 0x138, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D3__FEC_RXD1	IOMUX_PAD(0x418, 0x138, 2, 0x77C, 0, PAD_CTL_HYS | PAD_CTL_PKE)
-#define MX50_PAD_DISP_D3__WEIM_A19	IOMUX_PAD(0x418, 0x138, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D3__FEC_COL	IOMUX_PAD(0x418, 0x138, 4, 0x770, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D4__DISP_D4	IOMUX_PAD(0x41C, 0x13C, 0, 0x70c, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D4__GPIO_2_4	IOMUX_PAD(0x41C, 0x13C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D4__FEC_RXD0	IOMUX_PAD(0x41C, 0x13C, 2, 0x778, 0, PAD_CTL_HYS | PAD_CTL_PKE)
-#define MX50_PAD_DISP_D4__WEIM_A20	IOMUX_PAD(0x41C, 0x13C, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D5__DISP_D5	IOMUX_PAD(0x420, 0x140, 0, 0x710, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D5__GPIO_2_5	IOMUX_PAD(0x420, 0x140, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D5__FEC_TX_EN	IOMUX_PAD(0x420, 0x140, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_DISP_D5__WEIM_A21	IOMUX_PAD(0x420, 0x140, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D6__DISP_D6	IOMUX_PAD(0x424, 0x144, 0, 0x714, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D6__GPIO_2_6	IOMUX_PAD(0x424, 0x144, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D6__FEC_TXD1	IOMUX_PAD(0x424, 0x144, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_DISP_D6__WEIM_A22	IOMUX_PAD(0x424, 0x144, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D6__FEC_RX_CLK	IOMUX_PAD(0x424, 0x144, 4, 0x780, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D7__DISP_D7	IOMUX_PAD(0x428, 0x148, 0, 0x718, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D7__GPIO_2_7	IOMUX_PAD(0x428, 0x148, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D7__FEC_TXD0	IOMUX_PAD(0x428, 0x148, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_DISP_D7__WEIM_A23	IOMUX_PAD(0x428, 0x148, 3, 0x0, 0, NO_PAD_CTRL)
-
-
-#define MX50_PAD_DISP_WR__ELCDIF_WR	IOMUX_PAD(0x42C, 0x14C, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_WR__GPIO_2_16	IOMUX_PAD(0x42C, 0x14C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_WR__ELCDIF_PIXCLK	IOMUX_PAD(0x42C, 0x14C, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_WR__WEIM_A24	IOMUX_PAD(0x42C, 0x14C, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_RD__ELCDIF_RD	IOMUX_PAD(0x430, 0x150, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_RD__GPIO_2_19	IOMUX_PAD(0x430, 0x150, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_RD__ELCDIF_EN	IOMUX_PAD(0x430, 0x150, 2, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_RD__WEIM_A25	IOMUX_PAD(0x430, 0x150, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_RS__ELCDIF_RS	IOMUX_PAD(0x434, 0x154, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_RS__GPIO_2_17	IOMUX_PAD(0x434, 0x154, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_RS__ELCDIF_VSYNC	IOMUX_PAD(0x434, 0x154, 2, 0x73c, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_RS__WEIM_A26	IOMUX_PAD(0x434, 0x154, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_CS__ELCDIF_CS	IOMUX_PAD(0x438, 0x158, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_CS__GPIO_2_21	IOMUX_PAD(0x438, 0x158, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_CS__ELCDIF_HSYNC	IOMUX_PAD(0x438, 0x158, 2, 0x6f8, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_CS__WEIM_A27	IOMUX_PAD(0x438, 0x158, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_CS__WEIM_CS3	IOMUX_PAD(0x438, 0x158, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_BUSY__ELCDIF_HSYNC	IOMUX_PAD(0x43C, 0x15C, 0, 0x6f8, 2, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_BUSY__GPIO_2_18		IOMUX_PAD(0x43C, 0x15C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_BUSY__WEIM_CS3		IOMUX_PAD(0x43C, 0x15C, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_RESET__ELCDIF_RST	IOMUX_PAD(0x440, 0x160, 0, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_RESET__GPIO_2_20	IOMUX_PAD(0x440, 0x160, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_RESET__WEIM_CS3	IOMUX_PAD(0x440, 0x160, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_CMD__SD3_CMD	IOMUX_PAD(0x444, 0x164, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_CMD__GPIO_5_18	IOMUX_PAD(0x444, 0x164, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_CMD__NANDF_WRN	IOMUX_PAD(0x444, 0x164, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_CMD__SSP_CMD	IOMUX_PAD(0x444, 0x164, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_CLK__SD3_CLK	IOMUX_PAD(0x448, 0x168, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_CLK__GPIO_5_19	IOMUX_PAD(0x448, 0x168, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_CLK__NANDF_RDN	IOMUX_PAD(0x448, 0x168, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_CLK__SSP_CLK	IOMUX_PAD(0x448, 0x168, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D0__SD3_D0		IOMUX_PAD(0x44C, 0x16C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D0__GPIO_5_20	IOMUX_PAD(0x44C, 0x16C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D0__NANDF_D4	IOMUX_PAD(0x44C, 0x16C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D0__SSP_D0		IOMUX_PAD(0x44C, 0x16C, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD3_D0__PLL1_BYP	IOMUX_PAD(0x44C, 0x16C, 7, 0x6dc, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D1__SD3_D1		IOMUX_PAD(0x450, 0x170, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D1__GPIO_5_21	IOMUX_PAD(0x450, 0x170, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D1__NANDF_D5	IOMUX_PAD(0x450, 0x170, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D1__PLL2_BYP	IOMUX_PAD(0x450, 0x170, 7, 0x6e0, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D2__SD3_D2		IOMUX_PAD(0x454, 0x174, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D2__GPIO_5_22	IOMUX_PAD(0x454, 0x174, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D2__NANDF_D6	IOMUX_PAD(0x454, 0x174, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D2__SSP_D2		IOMUX_PAD(0x454, 0x174, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD3_D2__PLL3_BYP	IOMUX_PAD(0x454, 0x174, 7, 0x6e4, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D3__SD3_D3		IOMUX_PAD(0x458, 0x178, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D3__GPIO_5_23	IOMUX_PAD(0x458, 0x178, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D3__NANDF_D7	IOMUX_PAD(0x458, 0x178, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D3__SSP_D3		IOMUX_PAD(0x458, 0x178, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D4__SD3_D4		IOMUX_PAD(0x45C, 0x17C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D4__GPIO_5_24	IOMUX_PAD(0x45C, 0x17C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D4__NANDF_D0	IOMUX_PAD(0x45C, 0x17C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D4__SSP_D4		IOMUX_PAD(0x45C, 0x17C, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D5__SD3_D5		IOMUX_PAD(0x460, 0x180, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D5__GPIO_5_25	IOMUX_PAD(0x460, 0x180, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D5__NANDF_D1	IOMUX_PAD(0x460, 0x180, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D5__SSP_D5		IOMUX_PAD(0x460, 0x180, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D6__SD3_D6		IOMUX_PAD(0x464, 0x184, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D6__GPIO_5_26	IOMUX_PAD(0x464, 0x184, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D6__NANDF_D2	IOMUX_PAD(0x464, 0x184, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D6__SSP_D6		IOMUX_PAD(0x464, 0x184, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_D7__SD3_D7		IOMUX_PAD(0x468, 0x188, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_D7__GPIO_5_27	IOMUX_PAD(0x468, 0x188, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_D7__NANDF_D3	IOMUX_PAD(0x468, 0x188, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_D7__SSP_D7		IOMUX_PAD(0x468, 0x188, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_SD3_WP__SD3_WP		IOMUX_PAD(0x46C, 0x18C, 0, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_WP__GPIO_5_28	IOMUX_PAD(0x46C, 0x18C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_SD3_WP__NANDF_RESETN	IOMUX_PAD(0x46C, 0x18C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_SD3_WP__SSP_CD		IOMUX_PAD(0x46C, 0x18C, 3, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_SD3_WP__SD4_LCTL	IOMUX_PAD(0x46C, 0x18C, 4, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_SD3_WP__WEIM_CS3	IOMUX_PAD(0x46C, 0x18C, 5, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D8__DISP_D8	IOMUX_PAD(0x470, 0x190, 0, 0x71c, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D8__GPIO_2_8	IOMUX_PAD(0x470, 0x190, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D8__NANDF_CLE	IOMUX_PAD(0x470, 0x190, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D8__SD1_LCTL	IOMUX_PAD(0x470, 0x190, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D8__SD4_CMD	IOMUX_PAD(0x470, 0x190, 4, 0x74c, 2, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D8__KEY_COL4	IOMUX_PAD(0x470, 0x190, 5, 0x790, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D8__FEC_TX_CLK	IOMUX_PAD(0x470, 0x190, 6, 0x78c, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D9__DISP_D9	IOMUX_PAD(0x474, 0x194, 0, 0x720, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D9__GPIO_2_9	IOMUX_PAD(0x474, 0x194, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D9__NANDF_ALE	IOMUX_PAD(0x474, 0x194, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D9__SD2_LCTL	IOMUX_PAD(0x474, 0x194, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D9__SD4_CLK	IOMUX_PAD(0x474, 0x194, 4, 0x748, 2, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D9__KEY_ROW4	IOMUX_PAD(0x474, 0x194, 5, 0x7a0, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D9__FEC_RX_ER	IOMUX_PAD(0x474, 0x194, 6, 0x788, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D10__DISP_D10	IOMUX_PAD(0x478, 0x198, 0, 0x724, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D10__GPIO_2_10	IOMUX_PAD(0x478, 0x198, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D10__NANDF_CEN0	IOMUX_PAD(0x478, 0x198, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D10__SD3_LCTL	IOMUX_PAD(0x478, 0x198, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D10__SD4_D0	IOMUX_PAD(0x478, 0x198, 4, 0x750, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D10__KEY_COL5	IOMUX_PAD(0x478, 0x198, 5, 0x794, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D10__FEC_RX_DV	IOMUX_PAD(0x478, 0x198, 6, 0x784, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D11__DISP_D11	IOMUX_PAD(0x47C, 0x19C, 0, 0x728, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D11__GPIO_2_11	IOMUX_PAD(0x47C, 0x19C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D11__NANDF_CEN1	IOMUX_PAD(0x47C, 0x19C, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D11__SD4_D1	IOMUX_PAD(0x47C, 0x19C, 4, 0x754, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D11__KEY_ROW5	IOMUX_PAD(0x47C, 0x19C, 5, 0x7a4, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D11__FEC_RDAT1	IOMUX_PAD(0x47C, 0x19C, 6, 0x77c, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D12__DISP_D12	IOMUX_PAD(0x480, 0x1A0, 0, 0x72c, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D12__GPIO_2_12	IOMUX_PAD(0x480, 0x1A0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D12__NANDF_CEN2	IOMUX_PAD(0x480, 0x1A0, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D12__SD1_CD	IOMUX_PAD(0x480, 0x1A0, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D12__SD4_D2	IOMUX_PAD(0x480, 0x1A0, 4, 0x758, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D12__KEY_COL6	IOMUX_PAD(0x480, 0x1A0, 5, 0x798, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D12__FEC_RDAT0	IOMUX_PAD(0x480, 0x1A0, 6, 0x778, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D13__DISP_D13	IOMUX_PAD(0x484, 0x1A4, 0, 0x730, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D13__GPIO_2_13	IOMUX_PAD(0x484, 0x1A4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D13__NANDF_CEN3	IOMUX_PAD(0x484, 0x1A4, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D13__SD3_CD	IOMUX_PAD(0x484, 0x1A4, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D13__SD4_D3	IOMUX_PAD(0x484, 0x1A4, 4, 0x75c, 1, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D13__KEY_ROW6	IOMUX_PAD(0x484, 0x1A4, 5, 0x7a8, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D13__FEC_TX_EN	IOMUX_PAD(0x484, 0x1A4, 6, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D14__DISP_D14	IOMUX_PAD(0x488, 0x1A8, 0, 0x734, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D14__GPIO_2_14	IOMUX_PAD(0x488, 0x1A8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D14__NANDF_RDY0	IOMUX_PAD(0x488, 0x1A8, 2, 0x7b4, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D14__SD1_WP	IOMUX_PAD(0x488, 0x1A8, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D14__SD4_WP	IOMUX_PAD(0x488, 0x1A8, 4, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D14__KEY_COL7	IOMUX_PAD(0x488, 0x1A8, 5, 0x79c, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D14__FEC_TDAT1	IOMUX_PAD(0x488, 0x1A8, 6, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_DISP_D15__DISP_D15	IOMUX_PAD(0x48C, 0x1AC, 0, 0x738, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_DISP_D15__GPIO_2_15	IOMUX_PAD(0x48C, 0x1AC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D15__NANDF_DQS	IOMUX_PAD(0x48C, 0x1AC, 2, 0x7b0, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D15__SD3_RST	IOMUX_PAD(0x48C, 0x1AC, 3, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D15__SD4_CD	IOMUX_PAD(0x48C, 0x1AC, 4, 0x0, 0, MX50_SD_PAD_CTRL)
-#define MX50_PAD_DISP_D15__KEY_ROW7	IOMUX_PAD(0x48C, 0x1AC, 5, 0x7ac, 1, NO_PAD_CTRL)
-#define MX50_PAD_DISP_D15__FEC_TDAT0	IOMUX_PAD(0x48C, 0x1AC, 6, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D0__EPDC_D0	IOMUX_PAD(0x54C, 0x1B0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D0__GPIO_3_0	IOMUX_PAD(0x54C, 0x1B0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D0__WEIM_D0	IOMUX_PAD(0x54C, 0x1B0, 2, 0x7ec, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D0__ELCDIF_RS	IOMUX_PAD(0x54C, 0x1B0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D0__ELCDIF_PIXCLK	IOMUX_PAD(0x54C, 0x1B0, 4, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D1__EPDC_D1	IOMUX_PAD(0x550, 0x1B4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D1__GPIO_3_1	IOMUX_PAD(0x550, 0x1B4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D1__WEIM_D1	IOMUX_PAD(0x550, 0x1B4, 2, 0x7f0, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D1__ELCDIF_CS	IOMUX_PAD(0x550, 0x1B4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D1__ELCDIF_EN	IOMUX_PAD(0x550, 0x1B4, 4, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D2__EPDC_D2	IOMUX_PAD(0x554, 0x1B8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D2__GPIO_3_2	IOMUX_PAD(0x554, 0x1B8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D2__WEIM_D2	IOMUX_PAD(0x554, 0x1B8, 2, 0x7f4, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D2__ELCDIF_WR	IOMUX_PAD(0x554, 0x1B8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D2__ELCDIF_VSYNC	IOMUX_PAD(0x554, 0x1B8, 4, 0x73c, 2, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D3__EPDC_D3	IOMUX_PAD(0x558, 0x1BC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D3__GPIO_3_3	IOMUX_PAD(0x558, 0x1BC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D3__WEIM_D3	IOMUX_PAD(0x558, 0x1BC, 2, 0x7f8, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D3__ELCDIF_RD	IOMUX_PAD(0x558, 0x1BC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D3__ELCDIF_HSYNC	IOMUX_PAD(0x558, 0x1BC, 4, 0x6f8, 3, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D4__EPDC_D4	IOMUX_PAD(0x55C, 0x1C0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D4__GPIO_3_4	IOMUX_PAD(0x55C, 0x1C0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D4__WEIM_D4	IOMUX_PAD(0x55C, 0x1C0, 2, 0x7fc, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D5__EPDC_D5	IOMUX_PAD(0x560, 0x1C4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D5__GPIO_3_5	IOMUX_PAD(0x560, 0x1C4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D5__WEIM_D5	IOMUX_PAD(0x560, 0x1C4, 2, 0x800, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D6__EPDC_D6	IOMUX_PAD(0x564, 0x1C8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D6__GPIO_3_6	IOMUX_PAD(0x564, 0x1C8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D6__WEIM_D6	IOMUX_PAD(0x564, 0x1C8, 2, 0x804, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D7__EPDC_D7	IOMUX_PAD(0x568, 0x1CC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D7__GPIO_3_7	IOMUX_PAD(0x568, 0x1CC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D7__WEIM_D7	IOMUX_PAD(0x568, 0x1CC, 2, 0x808, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D8__EPDC_D8	IOMUX_PAD(0x56C, 0x1D0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D8__GPIO_3_8	IOMUX_PAD(0x56C, 0x1D0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D8__WEIM_D8	IOMUX_PAD(0x56C, 0x1D0, 2, 0x80c, 2, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D8__ELCDIF_D24	IOMUX_PAD(0x56C, 0x1D0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D9__EPDC_D9	IOMUX_PAD(0x570, 0x1D4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D9__GPIO_3_9	IOMUX_PAD(0x570, 0x1D4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D9__WEIM_D9	IOMUX_PAD(0x570, 0x1D4, 2, 0x810, 2, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D9__ELCDIF_D25	IOMUX_PAD(0x570, 0x1D4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D10__EPDC_D10	IOMUX_PAD(0x574, 0x1D8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D10__GPIO_3_10	IOMUX_PAD(0x574, 0x1D8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D10__WEIM_D10	IOMUX_PAD(0x574, 0x1D8, 2, 0x814, 2, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D10__ELCDIF_D26	IOMUX_PAD(0x574, 0x1D8, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D11__EPDC_D11	IOMUX_PAD(0x578, 0x1DC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D11__GPIO_3_11	IOMUX_PAD(0x578, 0x1DC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D11__WEIM_D11	IOMUX_PAD(0x578, 0x1DC, 2, 0x818, 2, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D11__ELCDIF_D27	IOMUX_PAD(0x578, 0x1DC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D12__EPDC_D12	IOMUX_PAD(0x57C, 0x1E0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D12__GPIO_3_12	IOMUX_PAD(0x57C, 0x1E0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D12__WEIM_D12	IOMUX_PAD(0x57C, 0x1E0, 2, 0x81c, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D12__ELCDIF_D28	IOMUX_PAD(0x57C, 0x1E0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D13__EPDC_D13	IOMUX_PAD(0x580, 0x1E4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D13__GPIO_3_13	IOMUX_PAD(0x580, 0x1E4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D13__WEIM_D13	IOMUX_PAD(0x580, 0x1E4, 2, 0x820, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D13__ELCDIF_D29	IOMUX_PAD(0x580, 0x1E4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D14__EPDC_D14	IOMUX_PAD(0x584, 0x1E8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D14__GPIO_3_14	IOMUX_PAD(0x584, 0x1E8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D14__WEIM_D14	IOMUX_PAD(0x584, 0x1E8, 2, 0x824, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D14__ELCDIF_D30	IOMUX_PAD(0x584, 0x1E8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D14__AUD6_TXD	IOMUX_PAD(0x584, 0x1E8, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_D15__EPDC_D15	IOMUX_PAD(0x588, 0x1EC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D15__GPIO_3_15	IOMUX_PAD(0x588, 0x1EC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D15__WEIM_D15	IOMUX_PAD(0x588, 0x1EC, 2, 0x828, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_D15__ELCDIF_D31	IOMUX_PAD(0x588, 0x1EC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_D15__AUD6_TXC	IOMUX_PAD(0x588, 0x1EC, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_GDCLK__EPDC_GDCLK	IOMUX_PAD(0x58C, 0x1F0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDCLK__GPIO_3_16	IOMUX_PAD(0x58C, 0x1F0, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDCLK__WEIM_D16	IOMUX_PAD(0x58C, 0x1F0, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDCLK__ELCDIF_D16	IOMUX_PAD(0x58C, 0x1F0, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_GDCLK__AUD6_TXFS	IOMUX_PAD(0x58C, 0x1F0, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_GDSP__EPDC_GDSP	IOMUX_PAD(0x590, 0x1F4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDSP__GPIO_3_17	IOMUX_PAD(0x590, 0x1F4, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDSP__WEIM_D17	IOMUX_PAD(0x590, 0x1F4, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDSP__ELCDIF_D17	IOMUX_PAD(0x590, 0x1F4, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_GDSP__AUD6_RXD	IOMUX_PAD(0x590, 0x1F4, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_GDOE__EPDC_GDOE	IOMUX_PAD(0x594, 0x1F8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDOE__GPIO_3_18	IOMUX_PAD(0x594, 0x1F8, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDOE__WEIM_D18	IOMUX_PAD(0x594, 0x1F8, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDOE__ELCDIF_D18	IOMUX_PAD(0x594, 0x1F8, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_GDOE__AUD6_RXC	IOMUX_PAD(0x594, 0x1F8, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_GDRL__EPDC_GDRL	IOMUX_PAD(0x598, 0x1FC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDRL__GPIO_3_19	IOMUX_PAD(0x598, 0x1FC, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDRL__WEIM_D19	IOMUX_PAD(0x598, 0x1FC, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_GDRL__ELCDIF_D19	IOMUX_PAD(0x598, 0x1FC, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_GDRL__AUD6_RXFS	IOMUX_PAD(0x598, 0x1FC, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCLK__EPDC_SDCLK	IOMUX_PAD(0x59C, 0x200, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLK__GPIO_3_20	IOMUX_PAD(0x59C, 0x200, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLK__WEIM_D20	IOMUX_PAD(0x59C, 0x200, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLK__ELCDIF_D20	IOMUX_PAD(0x59C, 0x200, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLK__AUD5_TXD	IOMUX_PAD(0x59C, 0x200, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDOEZ__EPDC_SDOEZ	IOMUX_PAD(0x5A0, 0x204, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOEZ__GPIO_3_21	IOMUX_PAD(0x5A0, 0x204, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOEZ__WEIM_D21	IOMUX_PAD(0x5A0, 0x204, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOEZ__ELCDIF_D21	IOMUX_PAD(0x5A0, 0x204, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOEZ__AUD5_TXC	IOMUX_PAD(0x5A0, 0x204, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDOED__EPDC_SDOED	IOMUX_PAD(0x5A4, 0x208, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOED__GPIO_3_22	IOMUX_PAD(0x5A4, 0x208, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOED__WEIM_D22	IOMUX_PAD(0x5A4, 0x208, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOED__ELCDIF_D22	IOMUX_PAD(0x5A4, 0x208, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOED__AUD5_TXFS	IOMUX_PAD(0x5A4, 0x208, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDOE__EPDC_SDOE	IOMUX_PAD(0x5A8, 0x20C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOE__GPIO_3_23	IOMUX_PAD(0x5A8, 0x20C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOE__WEIM_D23	IOMUX_PAD(0x5A8, 0x20C, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOE__ELCDIF_D23	IOMUX_PAD(0x5A8, 0x20C, 3, 0x0, 0, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDOE__AUD5_RXD	IOMUX_PAD(0x5A8, 0x20C, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDLE__EPDC_SDLE	IOMUX_PAD(0x5AC, 0x210, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDLE__GPIO_3_24	IOMUX_PAD(0x5AC, 0x210, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDLE__WEIM_D24	IOMUX_PAD(0x5AC, 0x210, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDLE__ELCDIF_D8	IOMUX_PAD(0x5AC, 0x210, 3, 0x71c, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDLE__AUD5_RXC	IOMUX_PAD(0x5AC, 0x210, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCLKN__EPDC_SDCLKN	IOMUX_PAD(0x5B0, 0x214, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLKN__GPIO_3_25		IOMUX_PAD(0x5B0, 0x214, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLKN__WEIM_D25		IOMUX_PAD(0x5B0, 0x214, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLKN__ELCDIF_D9		IOMUX_PAD(0x5B0, 0x214, 3, 0x720, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCLKN__AUD5_RXFS		IOMUX_PAD(0x5B0, 0x214, 4, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDSHR__EPDC_SDSHR	IOMUX_PAD(0x5B4, 0x218, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDSHR__GPIO_3_26	IOMUX_PAD(0x5B4, 0x218, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDSHR__WEIM_D26	IOMUX_PAD(0x5B4, 0x218, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDSHR__ELCDIF_D10	IOMUX_PAD(0x5B4, 0x218, 3, 0x724, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_SDSHR__AUD4_TXD	IOMUX_PAD(0x5B4, 0x218, 4, 0x6c8, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRCOM__EPDC_PWRCOM	IOMUX_PAD(0x5B8, 0x21C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCOM__GPIO_3_27		IOMUX_PAD(0x5B8, 0x21C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCOM__WEIM_D27		IOMUX_PAD(0x5B8, 0x21C, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCOM__ELCDIF_D11	IOMUX_PAD(0x5B8, 0x21C, 3, 0x728, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCOM__AUD4_TXC		IOMUX_PAD(0x5B8, 0x21C, 4, 0x6d4, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRSTAT__EPDC_PWRSTAT	IOMUX_PAD(0x5BC, 0x220, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRSTAT__GPIO_3_28	IOMUX_PAD(0x5BC, 0x220, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRSTAT__WEIM_D28		IOMUX_PAD(0x5BC, 0x220, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRSTAT__ELCDIF_D12	IOMUX_PAD(0x5BC, 0x220, 3, 0x72c, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRSTAT__AUD4_TXFS	IOMUX_PAD(0x5BC, 0x220, 4, 0x6d8, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRCTRL0__EPDC_PWRCTRL0	IOMUX_PAD(0x5C0, 0x224, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL0__GPIO_3_29	IOMUX_PAD(0x5C0, 0x224, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL0__WEIM_D29	IOMUX_PAD(0x5C0, 0x224, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL0__ELCDIF_D13	IOMUX_PAD(0x5C0, 0x224, 3, 0x730, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL0__AUD4_RXD	IOMUX_PAD(0x5C0, 0x224, 4, 0x6c4, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRCTRL1__EPDC_PWRCTRL1	IOMUX_PAD(0x5C4, 0x228, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL1__GPIO_3_30	IOMUX_PAD(0x5C4, 0x228, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL1__WEIM_D30	IOMUX_PAD(0x5C4, 0x228, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL1__ELCDIF_D14	IOMUX_PAD(0x5C4, 0x228, 3, 0x734, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL1__AUD4_RXC	IOMUX_PAD(0x5C4, 0x228, 4, 0x6cc, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRCTRL2__EPDC_PWRCTRL2	IOMUX_PAD(0x5C8, 0x22C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL2__GPIO_3_31	IOMUX_PAD(0x5C8, 0x22C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL2__WEIM_D31	IOMUX_PAD(0x5C8, 0x22C, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL2__ELCDIF_D15	IOMUX_PAD(0x5C8, 0x22C, 3, 0x738, 1, MX50_ELCDIF_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL2__AUD4_RXFS	IOMUX_PAD(0x5C8, 0x22C, 4, 0x6d0, 1, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL2__SDMA_EXT0	IOMUX_PAD(0x5C8, 0x22C, 6, 0x7b8, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_PWRCTRL3__PWRCTRL3	IOMUX_PAD(0x5CC, 0x230, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL3__GPIO_4_20	IOMUX_PAD(0x5CC, 0x230, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL3__WEIM_EB2	IOMUX_PAD(0x5CC, 0x230, 2, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_PWRCTRL3__SDMA_EXT1	IOMUX_PAD(0x5CC, 0x230, 6, 0x7bc, 1, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_VCOM0__EPDC_VCOM0	IOMUX_PAD(0x5D0, 0x234, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_VCOM0__GPIO_4_21	IOMUX_PAD(0x5D0, 0x234, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_VCOM0__WEIM_EB3	IOMUX_PAD(0x5D0, 0x234, 2, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_VCOM1__EPDC_VCOM1	IOMUX_PAD(0x5D4, 0x238, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_VCOM1__GPIO_4_22	IOMUX_PAD(0x5D4, 0x238, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_VCOM1__WEIM_CS3	IOMUX_PAD(0x5D4, 0x238, 2, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EPDC_BDR0__EPDC_BDR0	IOMUX_PAD(0x5D8, 0x23C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_BDR0__GPIO_4_23	IOMUX_PAD(0x5D8, 0x23C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_BDR0__ELCDIF_D7	IOMUX_PAD(0x5D8, 0x23C, 3, 0x718, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_BDR1__EPDC_BDR1	IOMUX_PAD(0x5DC, 0x240, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_BDR1__GPIO_4_24	IOMUX_PAD(0x5DC, 0x240, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_BDR1__ELCDIF_D6	IOMUX_PAD(0x5DC, 0x240, 3, 0x714, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE0__EPDC_SDCE0	IOMUX_PAD(0x5E0, 0x244, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE0__GPIO_4_25	IOMUX_PAD(0x5E0, 0x244, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE0__ELCDIF_D5	IOMUX_PAD(0x5E0, 0x244, 3, 0x710, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE1__EPDC_SDCE1	IOMUX_PAD(0x5E4, 0x248, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE1__GPIO_4_26	IOMUX_PAD(0x5E4, 0x248, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE1__ELCDIF_D4	IOMUX_PAD(0x5E4, 0x248, 2, 0x70c, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE2__EPDC_SDCE2		IOMUX_PAD(0x5E8, 0x24C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE2__GPIO_4_27		IOMUX_PAD(0x5E8, 0x24C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE2__ELCDIF_DAT3	IOMUX_PAD(0x5E8, 0x24C, 3, 0x708, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE3__EPDC_SDCE3	IOMUX_PAD(0x5EC, 0x250, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE3__GPIO_4_28	IOMUX_PAD(0x5EC, 0x250, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE3__ELCDIF_D2	IOMUX_PAD(0x5EC, 0x250, 3, 0x704, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE4__EPDC_SDCE4	IOMUX_PAD(0x5F0, 0x254, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE4__GPIO_4_29	IOMUX_PAD(0x5F0, 0x254, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE4__ELCDIF_D1	IOMUX_PAD(0x5F0, 0x254, 3, 0x700, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EPDC_SDCE5__EPDC_SDCE5	IOMUX_PAD(0x5F4, 0x258, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE5__GPIO_4_30	IOMUX_PAD(0x5F4, 0x258, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EPDC_SDCE5__ELCDIF_D0	IOMUX_PAD(0x5F4, 0x258, 3, 0x6fc, 1, MX50_ELCDIF_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA0__WEIM_A0	IOMUX_PAD(0x5F8, 0x25C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA0__GPIO_1_0	IOMUX_PAD(0x5F8, 0x25C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA0__KEY_COL4	IOMUX_PAD(0x5f8, 0x25C, 3, 0x790, 2, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA1__WEIM_A1	IOMUX_PAD(0x5FC, 0x260, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA1__GPIO_1_1	IOMUX_PAD(0x5FC, 0x260, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA1__KEY_ROW4	IOMUX_PAD(0x5fc, 0x260, 3, 0x7a0, 2, MX50_KEYPAD_CTRL)
-
-#define MX50_PAD_EIM_DA2__WEIM_A2	IOMUX_PAD(0x600, 0x264, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA2__GPIO_1_2	IOMUX_PAD(0x600, 0x264, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA2__KEY_COL5	IOMUX_PAD(0x600, 0x264, 3, 0x794, 2, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA3__WEIM_A3	IOMUX_PAD(0x604, 0x268, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA3__GPIO_1_3	IOMUX_PAD(0x604, 0x268, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA3__KEY_ROW5	IOMUX_PAD(0x604, 0x268, 3, 0x7a4, 2, MX50_KEYPAD_CTRL)
-
-#define MX50_PAD_EIM_DA4__WEIM_A4	IOMUX_PAD(0x608, 0x26C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA4__GPIO_1_4	IOMUX_PAD(0x608, 0x26C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA4__KEY_COL6	IOMUX_PAD(0x608, 0x26C, 3, 0x798, 2, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA5__WEIM_A5	IOMUX_PAD(0x60C, 0x270, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA5__GPIO_1_5	IOMUX_PAD(0x60C, 0x270, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA5__KEY_ROW6	IOMUX_PAD(0x60C, 0x270, 3, 0x7a8, 2, MX50_KEYPAD_CTRL)
-
-#define MX50_PAD_EIM_DA6__WEIM_A6	IOMUX_PAD(0x610, 0x274, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA6__GPIO_1_6	IOMUX_PAD(0x610, 0x274, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA6__KEY_COL7	IOMUX_PAD(0x610, 0x274, 3, 0x79c, 2, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA7__WEIM_A7	IOMUX_PAD(0x614, 0x278, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA7__GPIO_1_7	IOMUX_PAD(0x614, 0x278, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA7__KEY_ROW7	IOMUX_PAD(0x614, 0x278, 3, 0x7ac, 2, MX50_KEYPAD_CTRL)
-
-#define MX50_PAD_EIM_DA8__WEIM_A8	IOMUX_PAD(0x618, 0x27C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA8__GPIO_1_8	IOMUX_PAD(0x618, 0x27C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA8__NANDF_CLE	IOMUX_PAD(0x618, 0x27C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_EIM_DA9__WEIM_A9	IOMUX_PAD(0x61C, 0x280, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA9__GPIO_1_9	IOMUX_PAD(0x61C, 0x280, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA9__NANDF_ALE	IOMUX_PAD(0x61C, 0x280, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_EIM_DA10__WEIM_A10	IOMUX_PAD(0x620, 0x284, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA10__GPIO_1_10	IOMUX_PAD(0x620, 0x284, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA10__NANDF_CE0	IOMUX_PAD(0x620, 0x284, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_EIM_DA11__WEIM_A11	IOMUX_PAD(0x624, 0x288, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA11__GPIO_1_11	IOMUX_PAD(0x624, 0x288, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA11__NANDF_CE1	IOMUX_PAD(0x624, 0x288, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-
-#define MX50_PAD_EIM_DA12__WEIM_A12	IOMUX_PAD(0x628, 0x28C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA12__GPIO_1_12	IOMUX_PAD(0x628, 0x28C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA12__NANDF_CE2	IOMUX_PAD(0x628, 0x28C, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_EIM_DA12__EPDC_SDCE6	IOMUX_PAD(0x628, 0x28C, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA13__WEIM_A13	IOMUX_PAD(0x62C, 0x290, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA13__GPIO_1_13	IOMUX_PAD(0x62C, 0x290, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA13__NANDF_CE3	IOMUX_PAD(0x62C, 0x290, 2, 0x0, 0, PAD_CTL_DSE_HIGH)
-#define MX50_PIN_EIM_DA13__EPDC_SDCE7	IOMUX_PAD(0x62C, 0x290, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA14__WEIM_A14	IOMUX_PAD(0x630, 0x294, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA14__GPIO_1_14	IOMUX_PAD(0x630, 0x294, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA14__NANDF_READY	IOMUX_PAD(0x630, 0x294, 2, 0x7B4, 2, PAD_CTL_PKE | \
-							PAD_CTL_PUE | PAD_CTL_PUS_100K_UP)
-#define MX50_PAD_EIM_DA14__EPDC_SDCE8	IOMUX_PAD(0x630, 0x294, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_DA15__WEIM_A15	IOMUX_PAD(0x634, 0x298, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_DA15__GPIO_1_15	IOMUX_PAD(0x634, 0x298, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PIN_EIM_DA15__NANDF_DQS	IOMUX_PAD(0x634, 0x298, 2, 0x7B0, 2, PAD_CTL_DSE_HIGH)
-#define MX50_PAD_EIM_DA15__EPDC_SDCE9	IOMUX_PAD(0x634, 0x298, 3, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_CS2__WEIM_CS2	IOMUX_PAD(0x638, 0x29C, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_CS2__GPIO_1_16	IOMUX_PAD(0x638, 0x29C, 1, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_CS2__WEIM_A27	IOMUX_PAD(0x638, 0x29C, 2, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_CS1__WEIM_CS1	IOMUX_PAD(0x63C, 0x2A0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_CS1__GPIO_1_17	IOMUX_PAD(0x63C, 0x2A0, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_CS0__WEIM_CS0	IOMUX_PAD(0x640, 0x2A4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_CS0__GPIO_1_18	IOMUX_PAD(0x640, 0x2A4, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_EB0__WEIM_EB0	IOMUX_PAD(0x644, 0x2A8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_EB0__GPIO_1_19	IOMUX_PAD(0x644, 0x2A8, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_EB1__WEIM_EB1	IOMUX_PAD(0x648, 0x2AC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_EB1__GPIO_1_20	IOMUX_PAD(0x648, 0x2AC, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_WAIT__WEIM_WAIT	IOMUX_PAD(0x64C, 0x2B0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_WAIT__GPIO_1_21	IOMUX_PAD(0x64C, 0x2B0, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_BCLK__WEIM_BCLK	IOMUX_PAD(0x650, 0x2B4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_BCLK__GPIO_1_22	IOMUX_PAD(0x650, 0x2B4, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_RDY__WEIM_RDY	IOMUX_PAD(0x654, 0x2B8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_RDY__GPIO_1_23	IOMUX_PAD(0x654, 0x2B8, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_OE__WEIM_OE	IOMUX_PAD(0x658, 0x2BC, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_OE__GPIO_1_24	IOMUX_PAD(0x658, 0x2BC, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_RW__WEIM_RW	IOMUX_PAD(0x65C, 0x2C0, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_RW__GPIO_1_25	IOMUX_PAD(0x65C, 0x2C0, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_LBA__WEIM_LBA	IOMUX_PAD(0x660, 0x2C4, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_LBA__GPIO_1_26	IOMUX_PAD(0x660, 0x2C4, 1, 0x0, 0, NO_PAD_CTRL)
-
-#define MX50_PAD_EIM_CRE__WEIM_CRE	IOMUX_PAD(0x664, 0x2C8, 0, 0x0, 0, NO_PAD_CTRL)
-#define MX50_PAD_EIM_CRE__GPIO_1_27	IOMUX_PAD(0x664, 0x2C8, 1, 0x0, 0, NO_PAD_CTRL)
-
-#endif /* __MACH_IOMUX_MX50_H__ */
diff --git a/arch/arm/mach-imx/iram_alloc.c b/arch/arm/mach-imx/iram_alloc.c
index 6c80424..e05cf40 100644
--- a/arch/arm/mach-imx/iram_alloc.c
+++ b/arch/arm/mach-imx/iram_alloc.c
@@ -22,8 +22,7 @@
 #include <linux/module.h>
 #include <linux/spinlock.h>
 #include <linux/genalloc.h>
-
-#include "iram.h"
+#include "linux/platform_data/imx-iram.h"
 
 static unsigned long iram_phys_base;
 static void __iomem *iram_virt_base;
diff --git a/arch/arm/mach-imx/lluart.c b/arch/arm/mach-imx/lluart.c
deleted file mode 100644
index 2fdc9bf..0000000
--- a/arch/arm/mach-imx/lluart.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright 2011 Freescale Semiconductor, Inc.
- * Copyright 2011 Linaro Ltd.
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/init.h>
-#include <asm/page.h>
-#include <asm/sizes.h>
-#include <asm/mach/map.h>
-
-#include "hardware.h"
-
-#define IMX6Q_UART1_BASE_ADDR	0x02020000
-#define IMX6Q_UART2_BASE_ADDR	0x021e8000
-#define IMX6Q_UART3_BASE_ADDR	0x021ec000
-#define IMX6Q_UART4_BASE_ADDR	0x021f0000
-#define IMX6Q_UART5_BASE_ADDR	0x021f4000
-
-/*
- * IMX6Q_UART_BASE_ADDR is put in the middle to force the expansion
- * of IMX6Q_UART##n##_BASE_ADDR.
- */
-#define IMX6Q_UART_BASE_ADDR(n)	IMX6Q_UART##n##_BASE_ADDR
-#define IMX6Q_UART_BASE(n)	IMX6Q_UART_BASE_ADDR(n)
-#define IMX6Q_DEBUG_UART_BASE	IMX6Q_UART_BASE(CONFIG_DEBUG_IMX6Q_UART_PORT)
-
-static struct map_desc imx_lluart_desc = {
-#ifdef CONFIG_DEBUG_IMX6Q_UART
-	.virtual	= IMX_IO_P2V(IMX6Q_DEBUG_UART_BASE),
-	.pfn		= __phys_to_pfn(IMX6Q_DEBUG_UART_BASE),
-	.length		= 0x4000,
-	.type		= MT_DEVICE,
-#endif
-};
-
-void __init imx_lluart_map_io(void)
-{
-	if (imx_lluart_desc.virtual)
-		iotable_init(&imx_lluart_desc, 1);
-}
diff --git a/arch/arm/mach-imx/mach-apf9328.c b/arch/arm/mach-imx/mach-apf9328.c
index 5c9bd2c..067580b 100644
--- a/arch/arm/mach-imx/mach-apf9328.c
+++ b/arch/arm/mach-imx/mach-apf9328.c
@@ -137,17 +137,13 @@
 	mx1_clocks_init(32768);
 }
 
-static struct sys_timer apf9328_timer = {
-	.init	= apf9328_timer_init,
-};
-
 MACHINE_START(APF9328, "Armadeus APF9328")
 	/* Maintainer: Gwenhael Goavec-Merou, ARMadeus Systems */
 	.map_io       = mx1_map_io,
 	.init_early   = imx1_init_early,
 	.init_irq     = mx1_init_irq,
 	.handle_irq   = imx1_handle_irq,
-	.timer        = &apf9328_timer,
+	.init_time	= apf9328_timer_init,
 	.init_machine = apf9328_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-armadillo5x0.c b/arch/arm/mach-imx/mach-armadillo5x0.c
index 59bd6b0..368a6e3 100644
--- a/arch/arm/mach-imx/mach-armadillo5x0.c
+++ b/arch/arm/mach-imx/mach-armadillo5x0.c
@@ -557,10 +557,6 @@
 	mx31_clocks_init(26000000);
 }
 
-static struct sys_timer armadillo5x0_timer = {
-	.init	= armadillo5x0_timer_init,
-};
-
 MACHINE_START(ARMADILLO5X0, "Armadillo-500")
 	/* Maintainer: Alberto Panizzo  */
 	.atag_offset = 0x100,
@@ -568,7 +564,7 @@
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
 	.handle_irq = imx31_handle_irq,
-	.timer = &armadillo5x0_timer,
+	.init_time	= armadillo5x0_timer_init,
 	.init_machine = armadillo5x0_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-bug.c b/arch/arm/mach-imx/mach-bug.c
index 3a39d5a..2d00476 100644
--- a/arch/arm/mach-imx/mach-bug.c
+++ b/arch/arm/mach-imx/mach-bug.c
@@ -53,16 +53,12 @@
 	mx31_clocks_init(26000000);
 }
 
-static struct sys_timer bug_timer = {
-	.init = bug_timer_init,
-};
-
 MACHINE_START(BUG, "BugLabs BUGBase")
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
 	.handle_irq = imx31_handle_irq,
-	.timer = &bug_timer,
+	.init_time	= bug_timer_init,
 	.init_machine = bug_board_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx27.c b/arch/arm/mach-imx/mach-cpuimx27.c
index 12a3706..1465593 100644
--- a/arch/arm/mach-imx/mach-cpuimx27.c
+++ b/arch/arm/mach-imx/mach-cpuimx27.c
@@ -309,17 +309,13 @@
 	mx27_clocks_init(26000000);
 }
 
-static struct sys_timer eukrea_cpuimx27_timer = {
-	.init = eukrea_cpuimx27_timer_init,
-};
-
 MACHINE_START(EUKREA_CPUIMX27, "EUKREA CPUIMX27")
 	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
 	.handle_irq = imx27_handle_irq,
-	.timer = &eukrea_cpuimx27_timer,
+	.init_time	= eukrea_cpuimx27_timer_init,
 	.init_machine = eukrea_cpuimx27_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx35.c b/arch/arm/mach-imx/mach-cpuimx35.c
index 5a31bf8..771362d 100644
--- a/arch/arm/mach-imx/mach-cpuimx35.c
+++ b/arch/arm/mach-imx/mach-cpuimx35.c
@@ -193,10 +193,6 @@
 	mx35_clocks_init();
 }
 
-static struct sys_timer eukrea_cpuimx35_timer = {
-	.init	= eukrea_cpuimx35_timer_init,
-};
-
 MACHINE_START(EUKREA_CPUIMX35SD, "Eukrea CPUIMX35")
 	/* Maintainer: Eukrea Electromatique */
 	.atag_offset = 0x100,
@@ -204,7 +200,7 @@
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
 	.handle_irq = imx35_handle_irq,
-	.timer = &eukrea_cpuimx35_timer,
+	.init_time	= eukrea_cpuimx35_timer_init,
 	.init_machine = eukrea_cpuimx35_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-cpuimx51sd.c b/arch/arm/mach-imx/mach-cpuimx51sd.c
index b727de0..9b73932 100644
--- a/arch/arm/mach-imx/mach-cpuimx51sd.c
+++ b/arch/arm/mach-imx/mach-cpuimx51sd.c
@@ -355,10 +355,6 @@
 	mx51_clocks_init(32768, 24000000, 22579200, 0);
 }
 
-static struct sys_timer mxc_timer = {
-	.init	= eukrea_cpuimx51sd_timer_init,
-};
-
 MACHINE_START(EUKREA_CPUIMX51SD, "Eukrea CPUIMX51SD")
 	/* Maintainer: Eric Bénard <eric@eukrea.com> */
 	.atag_offset = 0x100,
@@ -366,7 +362,7 @@
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
 	.handle_irq = imx51_handle_irq,
-	.timer = &mxc_timer,
+	.init_time	= eukrea_cpuimx51sd_timer_init,
 	.init_machine = eukrea_cpuimx51sd_init,
 	.init_late	= imx51_init_late,
 	.restart	= mxc_restart,
diff --git a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
index 75027a5..4bf4544 100644
--- a/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
+++ b/arch/arm/mach-imx/mach-eukrea_cpuimx25.c
@@ -159,10 +159,6 @@
 	mx25_clocks_init();
 }
 
-static struct sys_timer eukrea_cpuimx25_timer = {
-	.init   = eukrea_cpuimx25_timer_init,
-};
-
 MACHINE_START(EUKREA_CPUIMX25SD, "Eukrea CPUIMX25")
 	/* Maintainer: Eukrea Electromatique */
 	.atag_offset = 0x100,
@@ -170,7 +166,7 @@
 	.init_early = imx25_init_early,
 	.init_irq = mx25_init_irq,
 	.handle_irq = imx25_handle_irq,
-	.timer = &eukrea_cpuimx25_timer,
+	.init_time = eukrea_cpuimx25_timer_init,
 	.init_machine = eukrea_cpuimx25_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
index 318bd8d..29ac8ee6 100644
--- a/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
+++ b/arch/arm/mach-imx/mach-imx27_visstrim_m10.c
@@ -598,10 +598,6 @@
 	mx27_clocks_init((unsigned long)25000000);
 }
 
-static struct sys_timer visstrim_m10_timer = {
-	.init	= visstrim_m10_timer_init,
-};
-
 MACHINE_START(IMX27_VISSTRIM_M10, "Vista Silicon Visstrim_M10")
 	.atag_offset = 0x100,
 	.reserve = visstrim_reserve,
@@ -609,7 +605,7 @@
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
 	.handle_irq = imx27_handle_irq,
-	.timer = &visstrim_m10_timer,
+	.init_time	= visstrim_m10_timer_init,
 	.init_machine = visstrim_m10_board_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27ipcam.c b/arch/arm/mach-imx/mach-imx27ipcam.c
index 53a8601..1a851ae 100644
--- a/arch/arm/mach-imx/mach-imx27ipcam.c
+++ b/arch/arm/mach-imx/mach-imx27ipcam.c
@@ -65,10 +65,6 @@
 	mx27_clocks_init(25000000);
 }
 
-static struct sys_timer mx27ipcam_timer = {
-	.init	= mx27ipcam_timer_init,
-};
-
 MACHINE_START(IMX27IPCAM, "Freescale IMX27IPCAM")
 	/* maintainer: Freescale Semiconductor, Inc. */
 	.atag_offset = 0x100,
@@ -76,7 +72,7 @@
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
 	.handle_irq = imx27_handle_irq,
-	.timer = &mx27ipcam_timer,
+	.init_time	= mx27ipcam_timer_init,
 	.init_machine = mx27ipcam_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx27lite.c b/arch/arm/mach-imx/mach-imx27lite.c
index fc8dce9..3da2e3e 100644
--- a/arch/arm/mach-imx/mach-imx27lite.c
+++ b/arch/arm/mach-imx/mach-imx27lite.c
@@ -72,17 +72,13 @@
 	mx27_clocks_init(26000000);
 }
 
-static struct sys_timer mx27lite_timer = {
-	.init	= mx27lite_timer_init,
-};
-
 MACHINE_START(IMX27LITE, "LogicPD i.MX27LITE")
 	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
 	.handle_irq = imx27_handle_irq,
-	.timer = &mx27lite_timer,
+	.init_time	= mx27lite_timer_init,
 	.init_machine = mx27lite_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-imx53.c b/arch/arm/mach-imx/mach-imx53.c
index 860284d..f579c61 100644
--- a/arch/arm/mach-imx/mach-imx53.c
+++ b/arch/arm/mach-imx/mach-imx53.c
@@ -44,26 +44,22 @@
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
-static void __init imx53_timer_init(void)
-{
-	mx53_clocks_init_dt();
-}
-
-static struct sys_timer imx53_timer = {
-	.init = imx53_timer_init,
-};
-
 static const char *imx53_dt_board_compat[] __initdata = {
 	"fsl,imx53",
 	NULL
 };
 
+static void __init imx53_timer_init(void)
+{
+	mx53_clocks_init_dt();
+}
+
 DT_MACHINE_START(IMX53_DT, "Freescale i.MX53 (Device Tree Support)")
 	.map_io		= mx53_map_io,
 	.init_early	= imx53_init_early,
 	.init_irq	= mx53_init_irq,
 	.handle_irq	= imx53_handle_irq,
-	.timer		= &imx53_timer,
+	.init_time	= imx53_timer_init,
 	.init_machine	= imx53_dt_init,
 	.init_late	= imx53_init_late,
 	.dt_compat	= imx53_dt_board_compat,
diff --git a/arch/arm/mach-imx/mach-imx6q.c b/arch/arm/mach-imx/mach-imx6q.c
index 4eb1b3a..1786b2d 100644
--- a/arch/arm/mach-imx/mach-imx6q.c
+++ b/arch/arm/mach-imx/mach-imx6q.c
@@ -12,12 +12,12 @@
 
 #include <linux/clk.h>
 #include <linux/clkdev.h>
-#include <linux/cpuidle.h>
 #include <linux/delay.h>
 #include <linux/export.h>
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
@@ -26,11 +26,10 @@
 #include <linux/regmap.h>
 #include <linux/micrel_phy.h>
 #include <linux/mfd/syscon.h>
-#include <asm/cpuidle.h>
 #include <asm/smp_twd.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
+#include <asm/mach/map.h>
 #include <asm/mach/time.h>
 #include <asm/system_misc.h>
 
@@ -201,37 +200,28 @@
 	imx6q_1588_init();
 }
 
-static struct cpuidle_driver imx6q_cpuidle_driver = {
-	.name			= "imx6q_cpuidle",
-	.owner			= THIS_MODULE,
-	.en_core_tk_irqen	= 1,
-	.states[0]		= ARM_CPUIDLE_WFI_STATE,
-	.state_count		= 1,
-};
-
 static void __init imx6q_init_late(void)
 {
-	imx_cpuidle_init(&imx6q_cpuidle_driver);
+	/*
+	 * WAIT mode is broken on TO 1.0 and 1.1, so there is no point
+	 * to run cpuidle on them.
+	 */
+	if (imx6q_revision() > IMX_CHIP_REVISION_1_1)
+		imx6q_cpuidle_init();
 }
 
 static void __init imx6q_map_io(void)
 {
-	imx_lluart_map_io();
+	debug_ll_io_init();
 	imx_scu_map_io();
-	imx6q_clock_map_io();
 }
 
-static const struct of_device_id imx6q_irq_match[] __initconst = {
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-	{ /* sentinel */ }
-};
-
 static void __init imx6q_init_irq(void)
 {
 	l2x0_of_init(0, ~0UL);
 	imx_src_init();
 	imx_gpc_init();
-	of_irq_init(imx6q_irq_match);
+	irqchip_init();
 }
 
 static void __init imx6q_timer_init(void)
@@ -241,10 +231,6 @@
 	imx_print_silicon_rev("i.MX6Q", imx6q_revision());
 }
 
-static struct sys_timer imx6q_timer = {
-	.init = imx6q_timer_init,
-};
-
 static const char *imx6q_dt_compat[] __initdata = {
 	"fsl,imx6q",
 	NULL,
@@ -254,8 +240,7 @@
 	.smp		= smp_ops(imx_smp_ops),
 	.map_io		= imx6q_map_io,
 	.init_irq	= imx6q_init_irq,
-	.handle_irq	= imx6q_handle_irq,
-	.timer		= &imx6q_timer,
+	.init_time	= imx6q_timer_init,
 	.init_machine	= imx6q_init_machine,
 	.init_late      = imx6q_init_late,
 	.dt_compat	= imx6q_dt_compat,
diff --git a/arch/arm/mach-imx/mach-kzm_arm11_01.c b/arch/arm/mach-imx/mach-kzm_arm11_01.c
index 2e536ea5..c7bc41d 100644
--- a/arch/arm/mach-imx/mach-kzm_arm11_01.c
+++ b/arch/arm/mach-imx/mach-kzm_arm11_01.c
@@ -284,17 +284,13 @@
 	mx31_clocks_init(26000000);
 }
 
-static struct sys_timer kzm_timer = {
-	.init = kzm_timer_init,
-};
-
 MACHINE_START(KZM_ARM11_01, "Kyoto Microcomputer Co., Ltd. KZM-ARM11-01")
 	.atag_offset = 0x100,
 	.map_io = kzm_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
 	.handle_irq = imx31_handle_irq,
-	.timer = &kzm_timer,
+	.init_time	= kzm_timer_init,
 	.init_machine = kzm_board_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx1ads.c b/arch/arm/mach-imx/mach-mx1ads.c
index 06b4837..9f883e4 100644
--- a/arch/arm/mach-imx/mach-mx1ads.c
+++ b/arch/arm/mach-imx/mach-mx1ads.c
@@ -132,10 +132,6 @@
 	mx1_clocks_init(32000);
 }
 
-static struct sys_timer mx1ads_timer = {
-	.init	= mx1ads_timer_init,
-};
-
 MACHINE_START(MX1ADS, "Freescale MX1ADS")
 	/* Maintainer: Sascha Hauer, Pengutronix */
 	.atag_offset = 0x100,
@@ -143,7 +139,7 @@
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
 	.handle_irq = imx1_handle_irq,
-	.timer = &mx1ads_timer,
+	.init_time	= mx1ads_timer_init,
 	.init_machine = mx1ads_init,
 	.restart	= mxc_restart,
 MACHINE_END
@@ -154,7 +150,7 @@
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
 	.handle_irq = imx1_handle_irq,
-	.timer = &mx1ads_timer,
+	.init_time	= mx1ads_timer_init,
 	.init_machine = mx1ads_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx21ads.c b/arch/arm/mach-imx/mach-mx21ads.c
index 6adb313..a06aa4d 100644
--- a/arch/arm/mach-imx/mach-mx21ads.c
+++ b/arch/arm/mach-imx/mach-mx21ads.c
@@ -318,10 +318,6 @@
 	mx21_clocks_init(32768, 26000000);
 }
 
-static struct sys_timer mx21ads_timer = {
-	.init	= mx21ads_timer_init,
-};
-
 MACHINE_START(MX21ADS, "Freescale i.MX21ADS")
 	/* maintainer: Freescale Semiconductor, Inc. */
 	.atag_offset = 0x100,
@@ -329,7 +325,7 @@
 	.init_early = imx21_init_early,
 	.init_irq = mx21_init_irq,
 	.handle_irq = imx21_handle_irq,
-	.timer = &mx21ads_timer,
+	.init_time	= mx21ads_timer_init,
 	.init_machine = mx21ads_board_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx25_3ds.c b/arch/arm/mach-imx/mach-mx25_3ds.c
index b1b03aa..8bcda68 100644
--- a/arch/arm/mach-imx/mach-mx25_3ds.c
+++ b/arch/arm/mach-imx/mach-mx25_3ds.c
@@ -257,10 +257,6 @@
 	mx25_clocks_init();
 }
 
-static struct sys_timer mx25pdk_timer = {
-	.init   = mx25pdk_timer_init,
-};
-
 MACHINE_START(MX25_3DS, "Freescale MX25PDK (3DS)")
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.atag_offset = 0x100,
@@ -268,7 +264,7 @@
 	.init_early = imx25_init_early,
 	.init_irq = mx25_init_irq,
 	.handle_irq = imx25_handle_irq,
-	.timer = &mx25pdk_timer,
+	.init_time	= mx25pdk_timer_init,
 	.init_machine = mx25pdk_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx27_3ds.c b/arch/arm/mach-imx/mach-mx27_3ds.c
index d0e547f..25b3e4c 100644
--- a/arch/arm/mach-imx/mach-mx27_3ds.c
+++ b/arch/arm/mach-imx/mach-mx27_3ds.c
@@ -538,10 +538,6 @@
 	mx27_clocks_init(26000000);
 }
 
-static struct sys_timer mx27pdk_timer = {
-	.init	= mx27pdk_timer_init,
-};
-
 MACHINE_START(MX27_3DS, "Freescale MX27PDK")
 	/* maintainer: Freescale Semiconductor, Inc. */
 	.atag_offset = 0x100,
@@ -549,7 +545,7 @@
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
 	.handle_irq = imx27_handle_irq,
-	.timer = &mx27pdk_timer,
+	.init_time	= mx27pdk_timer_init,
 	.init_machine = mx27pdk_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx27ads.c b/arch/arm/mach-imx/mach-mx27ads.c
index 3d036f5..9821b824 100644
--- a/arch/arm/mach-imx/mach-mx27ads.c
+++ b/arch/arm/mach-imx/mach-mx27ads.c
@@ -323,10 +323,6 @@
 	mx27_clocks_init(fref);
 }
 
-static struct sys_timer mx27ads_timer = {
-	.init	= mx27ads_timer_init,
-};
-
 static struct map_desc mx27ads_io_desc[] __initdata = {
 	{
 		.virtual = PBC_BASE_ADDRESS,
@@ -349,7 +345,7 @@
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
 	.handle_irq = imx27_handle_irq,
-	.timer = &mx27ads_timer,
+	.init_time	= mx27ads_timer_init,
 	.init_machine = mx27ads_board_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31_3ds.c b/arch/arm/mach-imx/mach-mx31_3ds.c
index bc301be..1ed9161 100644
--- a/arch/arm/mach-imx/mach-mx31_3ds.c
+++ b/arch/arm/mach-imx/mach-mx31_3ds.c
@@ -762,10 +762,6 @@
 	mx31_clocks_init(26000000);
 }
 
-static struct sys_timer mx31_3ds_timer = {
-	.init	= mx31_3ds_timer_init,
-};
-
 static void __init mx31_3ds_reserve(void)
 {
 	/* reserve MX31_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */
@@ -780,7 +776,7 @@
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
 	.handle_irq = imx31_handle_irq,
-	.timer = &mx31_3ds_timer,
+	.init_time	= mx31_3ds_timer_init,
 	.init_machine = mx31_3ds_init,
 	.reserve = mx31_3ds_reserve,
 	.restart	= mxc_restart,
diff --git a/arch/arm/mach-imx/mach-mx31ads.c b/arch/arm/mach-imx/mach-mx31ads.c
index 8b56f88..daf8889 100644
--- a/arch/arm/mach-imx/mach-mx31ads.c
+++ b/arch/arm/mach-imx/mach-mx31ads.c
@@ -576,10 +576,6 @@
 	mx31_clocks_init(26000000);
 }
 
-static struct sys_timer mx31ads_timer = {
-	.init	= mx31ads_timer_init,
-};
-
 MACHINE_START(MX31ADS, "Freescale MX31ADS")
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.atag_offset = 0x100,
@@ -587,7 +583,7 @@
 	.init_early = imx31_init_early,
 	.init_irq = mx31ads_init_irq,
 	.handle_irq = imx31_handle_irq,
-	.timer = &mx31ads_timer,
+	.init_time	= mx31ads_timer_init,
 	.init_machine = mx31ads_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31lilly.c b/arch/arm/mach-imx/mach-mx31lilly.c
index 08b9965..832b1e2 100644
--- a/arch/arm/mach-imx/mach-mx31lilly.c
+++ b/arch/arm/mach-imx/mach-mx31lilly.c
@@ -303,17 +303,13 @@
 	mx31_clocks_init(26000000);
 }
 
-static struct sys_timer mx31lilly_timer = {
-	.init	= mx31lilly_timer_init,
-};
-
 MACHINE_START(LILLY1131, "INCO startec LILLY-1131")
 	.atag_offset = 0x100,
 	.map_io = mx31_map_io,
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
 	.handle_irq = imx31_handle_irq,
-	.timer = &mx31lilly_timer,
+	.init_time	= mx31lilly_timer_init,
 	.init_machine = mx31lilly_board_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31lite.c b/arch/arm/mach-imx/mach-mx31lite.c
index bdcd92e..bea0729 100644
--- a/arch/arm/mach-imx/mach-mx31lite.c
+++ b/arch/arm/mach-imx/mach-mx31lite.c
@@ -285,10 +285,6 @@
 	mx31_clocks_init(26000000);
 }
 
-static struct sys_timer mx31lite_timer = {
-	.init	= mx31lite_timer_init,
-};
-
 MACHINE_START(MX31LITE, "LogicPD i.MX31 SOM")
 	/* Maintainer: Freescale Semiconductor, Inc. */
 	.atag_offset = 0x100,
@@ -296,7 +292,7 @@
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
 	.handle_irq = imx31_handle_irq,
-	.timer = &mx31lite_timer,
+	.init_time	= mx31lite_timer_init,
 	.init_machine = mx31lite_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx31moboard.c b/arch/arm/mach-imx/mach-mx31moboard.c
index 2517cfa..dae4cd7 100644
--- a/arch/arm/mach-imx/mach-mx31moboard.c
+++ b/arch/arm/mach-imx/mach-mx31moboard.c
@@ -596,10 +596,6 @@
 	mx31_clocks_init(26000000);
 }
 
-static struct sys_timer mx31moboard_timer = {
-	.init	= mx31moboard_timer_init,
-};
-
 static void __init mx31moboard_reserve(void)
 {
 	/* reserve 4 MiB for mx3-camera */
@@ -615,7 +611,7 @@
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
 	.handle_irq = imx31_handle_irq,
-	.timer = &mx31moboard_timer,
+	.init_time	= mx31moboard_timer_init,
 	.init_machine = mx31moboard_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx35_3ds.c b/arch/arm/mach-imx/mach-mx35_3ds.c
index 5277da4..a42f4f0 100644
--- a/arch/arm/mach-imx/mach-mx35_3ds.c
+++ b/arch/arm/mach-imx/mach-mx35_3ds.c
@@ -602,10 +602,6 @@
 	mx35_clocks_init();
 }
 
-static struct sys_timer mx35pdk_timer = {
-	.init	= mx35pdk_timer_init,
-};
-
 static void __init mx35_3ds_reserve(void)
 {
 	/* reserve MX35_3DS_CAMERA_BUF_SIZE bytes for mx3-camera */
@@ -620,7 +616,7 @@
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
 	.handle_irq = imx35_handle_irq,
-	.timer = &mx35pdk_timer,
+	.init_time	= mx35pdk_timer_init,
 	.init_machine = mx35_3ds_init,
 	.reserve = mx35_3ds_reserve,
 	.restart	= mxc_restart,
diff --git a/arch/arm/mach-imx/mach-mx50_rdp.c b/arch/arm/mach-imx/mach-mx50_rdp.c
deleted file mode 100644
index 0c1f88a..0000000
--- a/arch/arm/mach-imx/mach-mx50_rdp.c
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
- * Copyright (C) 2010 Freescale Semiconductor, Inc. All Rights Reserved.
- */
-
-/*
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/gpio.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-
-#include <asm/irq.h>
-#include <asm/setup.h>
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "common.h"
-#include "devices-imx50.h"
-#include "hardware.h"
-#include "iomux-mx50.h"
-
-#define FEC_EN		IMX_GPIO_NR(6, 23)
-#define FEC_RESET_B	IMX_GPIO_NR(4, 12)
-
-static iomux_v3_cfg_t mx50_rdp_pads[] __initdata = {
-	/* SD1 */
-	MX50_PAD_ECSPI2_SS0__GPIO_4_19,
-	MX50_PAD_EIM_CRE__GPIO_1_27,
-	MX50_PAD_SD1_CMD__SD1_CMD,
-
-	MX50_PAD_SD1_CLK__SD1_CLK,
-	MX50_PAD_SD1_D0__SD1_D0,
-	MX50_PAD_SD1_D1__SD1_D1,
-	MX50_PAD_SD1_D2__SD1_D2,
-	MX50_PAD_SD1_D3__SD1_D3,
-
-	/* SD2 */
-	MX50_PAD_SD2_CD__GPIO_5_17,
-	MX50_PAD_SD2_WP__GPIO_5_16,
-	MX50_PAD_SD2_CMD__SD2_CMD,
-	MX50_PAD_SD2_CLK__SD2_CLK,
-	MX50_PAD_SD2_D0__SD2_D0,
-	MX50_PAD_SD2_D1__SD2_D1,
-	MX50_PAD_SD2_D2__SD2_D2,
-	MX50_PAD_SD2_D3__SD2_D3,
-	MX50_PAD_SD2_D4__SD2_D4,
-	MX50_PAD_SD2_D5__SD2_D5,
-	MX50_PAD_SD2_D6__SD2_D6,
-	MX50_PAD_SD2_D7__SD2_D7,
-
-	/* SD3 */
-	MX50_PAD_SD3_CMD__SD3_CMD,
-	MX50_PAD_SD3_CLK__SD3_CLK,
-	MX50_PAD_SD3_D0__SD3_D0,
-	MX50_PAD_SD3_D1__SD3_D1,
-	MX50_PAD_SD3_D2__SD3_D2,
-	MX50_PAD_SD3_D3__SD3_D3,
-	MX50_PAD_SD3_D4__SD3_D4,
-	MX50_PAD_SD3_D5__SD3_D5,
-	MX50_PAD_SD3_D6__SD3_D6,
-	MX50_PAD_SD3_D7__SD3_D7,
-
-	/* PWR_INT */
-	MX50_PAD_ECSPI2_MISO__GPIO_4_18,
-
-	/* UART pad setting */
-	MX50_PAD_UART1_TXD__UART1_TXD,
-	MX50_PAD_UART1_RXD__UART1_RXD,
-	MX50_PAD_UART1_RTS__UART1_RTS,
-	MX50_PAD_UART2_TXD__UART2_TXD,
-	MX50_PAD_UART2_RXD__UART2_RXD,
-	MX50_PAD_UART2_CTS__UART2_CTS,
-	MX50_PAD_UART2_RTS__UART2_RTS,
-
-	MX50_PAD_I2C1_SCL__I2C1_SCL,
-	MX50_PAD_I2C1_SDA__I2C1_SDA,
-	MX50_PAD_I2C2_SCL__I2C2_SCL,
-	MX50_PAD_I2C2_SDA__I2C2_SDA,
-
-	MX50_PAD_EPITO__USBH1_PWR,
-	/* Need to comment below line if
-	 * one needs to debug owire.
-	 */
-	MX50_PAD_OWIRE__USBH1_OC,
-	/* using gpio to control otg pwr */
-	MX50_PAD_PWM2__GPIO_6_25,
-	MX50_PAD_I2C3_SCL__USBOTG_OC,
-
-	MX50_PAD_SSI_RXC__FEC_MDIO,
-	MX50_PAD_SSI_RXFS__FEC_MDC,
-	MX50_PAD_DISP_D0__FEC_TXCLK,
-	MX50_PAD_DISP_D1__FEC_RX_ER,
-	MX50_PAD_DISP_D2__FEC_RX_DV,
-	MX50_PAD_DISP_D3__FEC_RXD1,
-	MX50_PAD_DISP_D4__FEC_RXD0,
-	MX50_PAD_DISP_D5__FEC_TX_EN,
-	MX50_PAD_DISP_D6__FEC_TXD1,
-	MX50_PAD_DISP_D7__FEC_TXD0,
-	MX50_PAD_I2C3_SDA__GPIO_6_23,
-	MX50_PAD_ECSPI1_SCLK__GPIO_4_12,
-
-	MX50_PAD_CSPI_SS0__CSPI_SS0,
-	MX50_PAD_ECSPI1_MOSI__CSPI_SS1,
-	MX50_PAD_CSPI_MOSI__CSPI_MOSI,
-	MX50_PAD_CSPI_MISO__CSPI_MISO,
-
-	/* SGTL500_OSC_EN */
-	MX50_PAD_UART1_CTS__GPIO_6_8,
-
-	/* SGTL_AMP_SHDN */
-	MX50_PAD_UART3_RXD__GPIO_6_15,
-
-	/* Keypad */
-	MX50_PAD_KEY_COL0__KEY_COL0,
-	MX50_PAD_KEY_ROW0__KEY_ROW0,
-	MX50_PAD_KEY_COL1__KEY_COL1,
-	MX50_PAD_KEY_ROW1__KEY_ROW1,
-	MX50_PAD_KEY_COL2__KEY_COL2,
-	MX50_PAD_KEY_ROW2__KEY_ROW2,
-	MX50_PAD_KEY_COL3__KEY_COL3,
-	MX50_PAD_KEY_ROW3__KEY_ROW3,
-	MX50_PAD_EIM_DA0__KEY_COL4,
-	MX50_PAD_EIM_DA1__KEY_ROW4,
-	MX50_PAD_EIM_DA2__KEY_COL5,
-	MX50_PAD_EIM_DA3__KEY_ROW5,
-	MX50_PAD_EIM_DA4__KEY_COL6,
-	MX50_PAD_EIM_DA5__KEY_ROW6,
-	MX50_PAD_EIM_DA6__KEY_COL7,
-	MX50_PAD_EIM_DA7__KEY_ROW7,
-	/*EIM pads */
-	MX50_PAD_EIM_DA8__GPIO_1_8,
-	MX50_PAD_EIM_DA9__GPIO_1_9,
-	MX50_PAD_EIM_DA10__GPIO_1_10,
-	MX50_PAD_EIM_DA11__GPIO_1_11,
-	MX50_PAD_EIM_DA12__GPIO_1_12,
-	MX50_PAD_EIM_DA13__GPIO_1_13,
-	MX50_PAD_EIM_DA14__GPIO_1_14,
-	MX50_PAD_EIM_DA15__GPIO_1_15,
-	MX50_PAD_EIM_CS2__GPIO_1_16,
-	MX50_PAD_EIM_CS1__GPIO_1_17,
-	MX50_PAD_EIM_CS0__GPIO_1_18,
-	MX50_PAD_EIM_EB0__GPIO_1_19,
-	MX50_PAD_EIM_EB1__GPIO_1_20,
-	MX50_PAD_EIM_WAIT__GPIO_1_21,
-	MX50_PAD_EIM_BCLK__GPIO_1_22,
-	MX50_PAD_EIM_RDY__GPIO_1_23,
-	MX50_PAD_EIM_OE__GPIO_1_24,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static const struct fec_platform_data fec_data __initconst = {
-	.phy = PHY_INTERFACE_MODE_RMII,
-};
-
-static inline void mx50_rdp_fec_reset(void)
-{
-	gpio_request(FEC_EN, "fec-en");
-	gpio_direction_output(FEC_EN, 0);
-	gpio_request(FEC_RESET_B, "fec-reset_b");
-	gpio_direction_output(FEC_RESET_B, 0);
-	msleep(1);
-	gpio_set_value(FEC_RESET_B, 1);
-}
-
-static const struct imxi2c_platform_data i2c_data __initconst = {
-	.bitrate = 100000,
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mx50_rdp_board_init(void)
-{
-	imx50_soc_init();
-
-	mxc_iomux_v3_setup_multiple_pads(mx50_rdp_pads,
-					ARRAY_SIZE(mx50_rdp_pads));
-
-	imx50_add_imx_uart(0, &uart_pdata);
-	imx50_add_imx_uart(1, &uart_pdata);
-	mx50_rdp_fec_reset();
-	imx50_add_fec(&fec_data);
-	imx50_add_imx_i2c(0, &i2c_data);
-	imx50_add_imx_i2c(1, &i2c_data);
-	imx50_add_imx_i2c(2, &i2c_data);
-}
-
-static void __init mx50_rdp_timer_init(void)
-{
-	mx50_clocks_init(32768, 24000000, 22579200);
-}
-
-static struct sys_timer mx50_rdp_timer = {
-	.init	= mx50_rdp_timer_init,
-};
-
-MACHINE_START(MX50_RDP, "Freescale MX50 Reference Design Platform")
-	.map_io = mx50_map_io,
-	.init_early = imx50_init_early,
-	.init_irq = mx50_init_irq,
-	.handle_irq = imx50_handle_irq,
-	.timer = &mx50_rdp_timer,
-	.init_machine = mx50_rdp_board_init,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_3ds.c b/arch/arm/mach-imx/mach-mx51_3ds.c
deleted file mode 100644
index abc25bd..0000000
--- a/arch/arm/mach-imx/mach-mx51_3ds.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/*
- * Copyright 2008-2009 Freescale Semiconductor, Inc. All Rights Reserved.
- * Copyright (C) 2010 Jason Wang <jason77.wang@gmail.com>
- *
- * The code contained herein is licensed under the GNU General Public
- * License. You may obtain a copy of the GNU General Public License
- * Version 2 or later at the following locations:
- *
- * http://www.opensource.org/licenses/gpl-license.html
- * http://www.gnu.org/copyleft/gpl.html
- */
-
-#include <linux/irq.h>
-#include <linux/platform_device.h>
-#include <linux/spi/spi.h>
-#include <linux/gpio.h>
-
-#include <asm/mach-types.h>
-#include <asm/mach/arch.h>
-#include <asm/mach/time.h>
-
-#include "3ds_debugboard.h"
-#include "common.h"
-#include "devices-imx51.h"
-#include "hardware.h"
-#include "iomux-mx51.h"
-
-#define MX51_3DS_ECSPI2_CS	(GPIO_PORTC + 28)
-
-static iomux_v3_cfg_t mx51_3ds_pads[] = {
-	/* UART1 */
-	MX51_PAD_UART1_RXD__UART1_RXD,
-	MX51_PAD_UART1_TXD__UART1_TXD,
-	MX51_PAD_UART1_RTS__UART1_RTS,
-	MX51_PAD_UART1_CTS__UART1_CTS,
-
-	/* UART2 */
-	MX51_PAD_UART2_RXD__UART2_RXD,
-	MX51_PAD_UART2_TXD__UART2_TXD,
-	MX51_PAD_EIM_D25__UART2_CTS,
-	MX51_PAD_EIM_D26__UART2_RTS,
-
-	/* UART3 */
-	MX51_PAD_UART3_RXD__UART3_RXD,
-	MX51_PAD_UART3_TXD__UART3_TXD,
-	MX51_PAD_EIM_D24__UART3_CTS,
-	MX51_PAD_EIM_D27__UART3_RTS,
-
-	/* CPLD PARENT IRQ PIN */
-	MX51_PAD_GPIO1_6__GPIO1_6,
-
-	/* KPP */
-	MX51_PAD_KEY_ROW0__KEY_ROW0,
-	MX51_PAD_KEY_ROW1__KEY_ROW1,
-	MX51_PAD_KEY_ROW2__KEY_ROW2,
-	MX51_PAD_KEY_ROW3__KEY_ROW3,
-	MX51_PAD_KEY_COL0__KEY_COL0,
-	MX51_PAD_KEY_COL1__KEY_COL1,
-	MX51_PAD_KEY_COL2__KEY_COL2,
-	MX51_PAD_KEY_COL3__KEY_COL3,
-	MX51_PAD_KEY_COL4__KEY_COL4,
-	MX51_PAD_KEY_COL5__KEY_COL5,
-
-	/* eCSPI2 */
-	MX51_PAD_NANDF_RB2__ECSPI2_SCLK,
-	MX51_PAD_NANDF_RB3__ECSPI2_MISO,
-	MX51_PAD_NANDF_D15__ECSPI2_MOSI,
-	MX51_PAD_NANDF_D12__GPIO3_28,
-};
-
-/* Serial ports */
-static const struct imxuart_platform_data uart_pdata __initconst = {
-	.flags = IMXUART_HAVE_RTSCTS,
-};
-
-static int mx51_3ds_board_keymap[] = {
-	KEY(0, 0, KEY_1),
-	KEY(0, 1, KEY_2),
-	KEY(0, 2, KEY_3),
-	KEY(0, 3, KEY_F1),
-	KEY(0, 4, KEY_UP),
-	KEY(0, 5, KEY_F2),
-
-	KEY(1, 0, KEY_4),
-	KEY(1, 1, KEY_5),
-	KEY(1, 2, KEY_6),
-	KEY(1, 3, KEY_LEFT),
-	KEY(1, 4, KEY_SELECT),
-	KEY(1, 5, KEY_RIGHT),
-
-	KEY(2, 0, KEY_7),
-	KEY(2, 1, KEY_8),
-	KEY(2, 2, KEY_9),
-	KEY(2, 3, KEY_F3),
-	KEY(2, 4, KEY_DOWN),
-	KEY(2, 5, KEY_F4),
-
-	KEY(3, 0, KEY_0),
-	KEY(3, 1, KEY_OK),
-	KEY(3, 2, KEY_ESC),
-	KEY(3, 3, KEY_ENTER),
-	KEY(3, 4, KEY_MENU),
-	KEY(3, 5, KEY_BACK)
-};
-
-static const struct matrix_keymap_data mx51_3ds_map_data __initconst = {
-	.keymap		= mx51_3ds_board_keymap,
-	.keymap_size	= ARRAY_SIZE(mx51_3ds_board_keymap),
-};
-
-static int mx51_3ds_spi2_cs[] = {
-	MXC_SPI_CS(0),
-	MX51_3DS_ECSPI2_CS,
-};
-
-static const struct spi_imx_master mx51_3ds_ecspi2_pdata __initconst = {
-	.chipselect	= mx51_3ds_spi2_cs,
-	.num_chipselect	= ARRAY_SIZE(mx51_3ds_spi2_cs),
-};
-
-static struct spi_board_info mx51_3ds_spi_nor_device[] = {
-	{
-	 .modalias = "m25p80",
-	 .max_speed_hz = 25000000,	/* max spi clock (SCK) speed in HZ */
-	 .bus_num = 1,
-	 .chip_select = 1,
-	 .mode = SPI_MODE_0,
-	 .platform_data = NULL,},
-};
-
-/*
- * Board specific initialization.
- */
-static void __init mx51_3ds_init(void)
-{
-	imx51_soc_init();
-
-	mxc_iomux_v3_setup_multiple_pads(mx51_3ds_pads,
-					ARRAY_SIZE(mx51_3ds_pads));
-
-	imx51_add_imx_uart(0, &uart_pdata);
-	imx51_add_imx_uart(1, &uart_pdata);
-	imx51_add_imx_uart(2, &uart_pdata);
-
-	imx51_add_ecspi(1, &mx51_3ds_ecspi2_pdata);
-	spi_register_board_info(mx51_3ds_spi_nor_device,
-				ARRAY_SIZE(mx51_3ds_spi_nor_device));
-
-	if (mxc_expio_init(MX51_CS5_BASE_ADDR, IMX_GPIO_NR(1, 6)))
-		printk(KERN_WARNING "Init of the debugboard failed, all "
-				    "devices on the board are unusable.\n");
-
-	imx51_add_sdhci_esdhc_imx(0, NULL);
-	imx51_add_imx_keypad(&mx51_3ds_map_data);
-	imx51_add_imx2_wdt(0);
-}
-
-static void __init mx51_3ds_timer_init(void)
-{
-	mx51_clocks_init(32768, 24000000, 22579200, 0);
-}
-
-static struct sys_timer mx51_3ds_timer = {
-	.init = mx51_3ds_timer_init,
-};
-
-MACHINE_START(MX51_3DS, "Freescale MX51 3-Stack Board")
-	/* Maintainer: Freescale Semiconductor, Inc. */
-	.atag_offset = 0x100,
-	.map_io = mx51_map_io,
-	.init_early = imx51_init_early,
-	.init_irq = mx51_init_irq,
-	.handle_irq = imx51_handle_irq,
-	.timer = &mx51_3ds_timer,
-	.init_machine = mx51_3ds_init,
-	.init_late	= imx51_init_late,
-	.restart	= mxc_restart,
-MACHINE_END
diff --git a/arch/arm/mach-imx/mach-mx51_babbage.c b/arch/arm/mach-imx/mach-mx51_babbage.c
index d9a84ca..6c4d7fe 100644
--- a/arch/arm/mach-imx/mach-mx51_babbage.c
+++ b/arch/arm/mach-imx/mach-mx51_babbage.c
@@ -418,10 +418,6 @@
 	mx51_clocks_init(32768, 24000000, 22579200, 0);
 }
 
-static struct sys_timer mx51_babbage_timer = {
-	.init = mx51_babbage_timer_init,
-};
-
 MACHINE_START(MX51_BABBAGE, "Freescale MX51 Babbage Board")
 	/* Maintainer: Amit Kucheria <amit.kucheria@canonical.com> */
 	.atag_offset = 0x100,
@@ -429,7 +425,7 @@
 	.init_early = imx51_init_early,
 	.init_irq = mx51_init_irq,
 	.handle_irq = imx51_handle_irq,
-	.timer = &mx51_babbage_timer,
+	.init_time	= mx51_babbage_timer_init,
 	.init_machine = mx51_babbage_init,
 	.init_late	= imx51_init_late,
 	.restart	= mxc_restart,
diff --git a/arch/arm/mach-imx/mach-mxt_td60.c b/arch/arm/mach-imx/mach-mxt_td60.c
index f4a8c7e..a27faab 100644
--- a/arch/arm/mach-imx/mach-mxt_td60.c
+++ b/arch/arm/mach-imx/mach-mxt_td60.c
@@ -261,10 +261,6 @@
 	mx27_clocks_init(26000000);
 }
 
-static struct sys_timer mxt_td60_timer = {
-	.init	= mxt_td60_timer_init,
-};
-
 MACHINE_START(MXT_TD60, "Maxtrack i-MXT TD60")
 	/* maintainer: Maxtrack Industrial */
 	.atag_offset = 0x100,
@@ -272,7 +268,7 @@
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
 	.handle_irq = imx27_handle_irq,
-	.timer = &mxt_td60_timer,
+	.init_time	= mxt_td60_timer_init,
 	.init_machine = mxt_td60_board_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pca100.c b/arch/arm/mach-imx/mach-pca100.c
index eee369f..b8b15bb 100644
--- a/arch/arm/mach-imx/mach-pca100.c
+++ b/arch/arm/mach-imx/mach-pca100.c
@@ -416,10 +416,6 @@
 	mx27_clocks_init(26000000);
 }
 
-static struct sys_timer pca100_timer = {
-	.init = pca100_timer_init,
-};
-
 MACHINE_START(PCA100, "phyCARD-i.MX27")
 	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
@@ -427,6 +423,6 @@
 	.init_irq = mx27_init_irq,
 	.handle_irq = imx27_handle_irq,
 	.init_machine = pca100_init,
-	.timer = &pca100_timer,
+	.init_time	= pca100_timer_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pcm037.c b/arch/arm/mach-imx/mach-pcm037.c
index 547fef1..bc0261e 100644
--- a/arch/arm/mach-imx/mach-pcm037.c
+++ b/arch/arm/mach-imx/mach-pcm037.c
@@ -685,10 +685,6 @@
 	mx31_clocks_init(26000000);
 }
 
-static struct sys_timer pcm037_timer = {
-	.init	= pcm037_timer_init,
-};
-
 static void __init pcm037_reserve(void)
 {
 	/* reserve 4 MiB for mx3-camera */
@@ -709,7 +705,7 @@
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
 	.handle_irq = imx31_handle_irq,
-	.timer = &pcm037_timer,
+	.init_time	= pcm037_timer_init,
 	.init_machine = pcm037_init,
 	.init_late = pcm037_init_late,
 	.restart	= mxc_restart,
diff --git a/arch/arm/mach-imx/mach-pcm038.c b/arch/arm/mach-imx/mach-pcm038.c
index 4aa0d07..e805ac2 100644
--- a/arch/arm/mach-imx/mach-pcm038.c
+++ b/arch/arm/mach-imx/mach-pcm038.c
@@ -346,17 +346,13 @@
 	mx27_clocks_init(26000000);
 }
 
-static struct sys_timer pcm038_timer = {
-	.init = pcm038_timer_init,
-};
-
 MACHINE_START(PCM038, "phyCORE-i.MX27")
 	.atag_offset = 0x100,
 	.map_io = mx27_map_io,
 	.init_early = imx27_init_early,
 	.init_irq = mx27_init_irq,
 	.handle_irq = imx27_handle_irq,
-	.timer = &pcm038_timer,
+	.init_time	= pcm038_timer_init,
 	.init_machine = pcm038_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-pcm043.c b/arch/arm/mach-imx/mach-pcm043.c
index 9244544..8ed533f 100644
--- a/arch/arm/mach-imx/mach-pcm043.c
+++ b/arch/arm/mach-imx/mach-pcm043.c
@@ -394,10 +394,6 @@
 	mx35_clocks_init();
 }
 
-static struct sys_timer pcm043_timer = {
-	.init	= pcm043_timer_init,
-};
-
 MACHINE_START(PCM043, "Phytec Phycore pcm043")
 	/* Maintainer: Pengutronix */
 	.atag_offset = 0x100,
@@ -405,7 +401,7 @@
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
 	.handle_irq = imx35_handle_irq,
-	.timer = &pcm043_timer,
+	.init_time = pcm043_timer_init,
 	.init_machine = pcm043_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-qong.c b/arch/arm/mach-imx/mach-qong.c
index 96d9a91..22af27e 100644
--- a/arch/arm/mach-imx/mach-qong.c
+++ b/arch/arm/mach-imx/mach-qong.c
@@ -260,10 +260,6 @@
 	mx31_clocks_init(26000000);
 }
 
-static struct sys_timer qong_timer = {
-	.init	= qong_timer_init,
-};
-
 MACHINE_START(QONG, "Dave/DENX QongEVB-LITE")
 	/* Maintainer: DENX Software Engineering GmbH */
 	.atag_offset = 0x100,
@@ -271,7 +267,7 @@
 	.init_early = imx31_init_early,
 	.init_irq = mx31_init_irq,
 	.handle_irq = imx31_handle_irq,
-	.timer = &qong_timer,
+	.init_time	= qong_timer_init,
 	.init_machine = qong_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-scb9328.c b/arch/arm/mach-imx/mach-scb9328.c
index fc97040..b0fa10d 100644
--- a/arch/arm/mach-imx/mach-scb9328.c
+++ b/arch/arm/mach-imx/mach-scb9328.c
@@ -131,10 +131,6 @@
 	mx1_clocks_init(32000);
 }
 
-static struct sys_timer scb9328_timer = {
-	.init	= scb9328_timer_init,
-};
-
 MACHINE_START(SCB9328, "Synertronixx scb9328")
 	/* Sascha Hauer */
 	.atag_offset = 100,
@@ -142,7 +138,7 @@
 	.init_early = imx1_init_early,
 	.init_irq = mx1_init_irq,
 	.handle_irq = imx1_handle_irq,
-	.timer = &scb9328_timer,
+	.init_time	= scb9328_timer_init,
 	.init_machine = scb9328_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mach-vpr200.c b/arch/arm/mach-imx/mach-vpr200.c
index 3aecf91..0910761e 100644
--- a/arch/arm/mach-imx/mach-vpr200.c
+++ b/arch/arm/mach-imx/mach-vpr200.c
@@ -305,17 +305,13 @@
 	mx35_clocks_init();
 }
 
-static struct sys_timer vpr200_timer = {
-	.init	= vpr200_timer_init,
-};
-
 MACHINE_START(VPR200, "VPR200")
 	/* Maintainer: Creative Product Design */
 	.map_io = mx35_map_io,
 	.init_early = imx35_init_early,
 	.init_irq = mx35_init_irq,
 	.handle_irq = imx35_handle_irq,
-	.timer = &vpr200_timer,
+	.init_time = vpr200_timer_init,
 	.init_machine = vpr200_board_init,
 	.restart	= mxc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-imx/mm-imx5.c b/arch/arm/mach-imx/mm-imx5.c
index 79d71cf..cf34994 100644
--- a/arch/arm/mach-imx/mm-imx5.c
+++ b/arch/arm/mach-imx/mm-imx5.c
@@ -24,16 +24,6 @@
 #include "iomux-v3.h"
 
 /*
- * Define the MX50 memory map.
- */
-static struct map_desc mx50_io_desc[] __initdata = {
-	imx_map_entry(MX50, TZIC, MT_DEVICE),
-	imx_map_entry(MX50, SPBA0, MT_DEVICE),
-	imx_map_entry(MX50, AIPS1, MT_DEVICE),
-	imx_map_entry(MX50, AIPS2, MT_DEVICE),
-};
-
-/*
  * Define the MX51 memory map.
  */
 static struct map_desc mx51_io_desc[] __initdata = {
@@ -59,11 +49,6 @@
  * system startup to create static physical to virtual memory mappings
  * for the IO modules.
  */
-void __init mx50_map_io(void)
-{
-	iotable_init(mx50_io_desc, ARRAY_SIZE(mx50_io_desc));
-}
-
 void __init mx51_map_io(void)
 {
 	iotable_init(mx51_io_desc, ARRAY_SIZE(mx51_io_desc));
@@ -74,13 +59,6 @@
 	iotable_init(mx53_io_desc, ARRAY_SIZE(mx53_io_desc));
 }
 
-void __init imx50_init_early(void)
-{
-	mxc_set_cpu_type(MXC_CPU_MX50);
-	mxc_iomux_v3_init(MX50_IO_ADDRESS(MX50_IOMUXC_BASE_ADDR));
-	mxc_arch_reset_init(MX50_IO_ADDRESS(MX50_WDOG_BASE_ADDR));
-}
-
 /*
  * The MIPI HSC unit has been removed from the i.MX51 Reference Manual by
  * the Freescale marketing division. However this did not remove the
@@ -115,11 +93,6 @@
 	mxc_arch_reset_init(MX53_IO_ADDRESS(MX53_WDOG1_BASE_ADDR));
 }
 
-void __init mx50_init_irq(void)
-{
-	tzic_init_irq(MX50_IO_ADDRESS(MX50_TZIC_BASE_ADDR));
-}
-
 void __init mx51_init_irq(void)
 {
 	tzic_init_irq(MX51_IO_ADDRESS(MX51_TZIC_BASE_ADDR));
@@ -148,31 +121,10 @@
 	.script_addrs = &imx51_sdma_script,
 };
 
-static const struct resource imx50_audmux_res[] __initconst = {
-	DEFINE_RES_MEM(MX50_AUDMUX_BASE_ADDR, SZ_16K),
-};
-
 static const struct resource imx51_audmux_res[] __initconst = {
 	DEFINE_RES_MEM(MX51_AUDMUX_BASE_ADDR, SZ_16K),
 };
 
-void __init imx50_soc_init(void)
-{
-	mxc_device_init();
-
-	/* i.mx50 has the i.mx35 type gpio */
-	mxc_register_gpio("imx35-gpio", 0, MX50_GPIO1_BASE_ADDR, SZ_16K, MX50_INT_GPIO1_LOW, MX50_INT_GPIO1_HIGH);
-	mxc_register_gpio("imx35-gpio", 1, MX50_GPIO2_BASE_ADDR, SZ_16K, MX50_INT_GPIO2_LOW, MX50_INT_GPIO2_HIGH);
-	mxc_register_gpio("imx35-gpio", 2, MX50_GPIO3_BASE_ADDR, SZ_16K, MX50_INT_GPIO3_LOW, MX50_INT_GPIO3_HIGH);
-	mxc_register_gpio("imx35-gpio", 3, MX50_GPIO4_BASE_ADDR, SZ_16K, MX50_INT_GPIO4_LOW, MX50_INT_GPIO4_HIGH);
-	mxc_register_gpio("imx35-gpio", 4, MX50_GPIO5_BASE_ADDR, SZ_16K, MX50_INT_GPIO5_LOW, MX50_INT_GPIO5_HIGH);
-	mxc_register_gpio("imx35-gpio", 5, MX50_GPIO6_BASE_ADDR, SZ_16K, MX50_INT_GPIO6_LOW, MX50_INT_GPIO6_HIGH);
-
-	/* i.mx50 has the i.mx31 type audmux */
-	platform_device_register_simple("imx31-audmux", 0, imx50_audmux_res,
-					ARRAY_SIZE(imx50_audmux_res));
-}
-
 void __init imx51_soc_init(void)
 {
 	mxc_device_init();
diff --git a/arch/arm/mach-imx/mx50.h b/arch/arm/mach-imx/mx50.h
deleted file mode 100644
index 09ac19c..0000000
--- a/arch/arm/mach-imx/mx50.h
+++ /dev/null
@@ -1,290 +0,0 @@
-#ifndef __MACH_MX50_H__
-#define __MACH_MX50_H__
-
-/*
- * IROM
- */
-#define MX50_IROM_BASE_ADDR		0x0
-#define MX50_IROM_SIZE			SZ_64K
-
-/* TZIC */
-#define MX50_TZIC_BASE_ADDR		0x0fffc000
-#define MX50_TZIC_SIZE			SZ_16K
-
-/*
- * IRAM
- */
-#define MX50_IRAM_BASE_ADDR	0xf8000000	/* internal ram */
-#define MX50_IRAM_PARTITIONS	16
-#define MX50_IRAM_SIZE		(MX50_IRAM_PARTITIONS * SZ_8K)	/* 128KB */
-
-/*
- * Databahn
- */
-#define MX50_DATABAHN_BASE_ADDR			0x14000000
-
-/*
- * Graphics Memory of GPU
- */
-#define MX50_GPU2D_BASE_ADDR		0x20000000
-
-#define MX50_DEBUG_BASE_ADDR		0x40000000
-#define MX50_DEBUG_SIZE			SZ_1M
-#define MX50_ETB_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00001000)
-#define MX50_ETM_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00002000)
-#define MX50_TPIU_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00003000)
-#define MX50_CTI0_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00004000)
-#define MX50_CTI1_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00005000)
-#define MX50_CTI2_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00006000)
-#define MX50_CTI3_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x00007000)
-#define MX50_CORTEX_DBG_BASE_ADDR	(MX50_DEBUG_BASE_ADDR + 0x00008000)
-
-#define MX50_APBHDMA_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01000000)
-#define MX50_OCOTP_CTRL_BASE_ADDR	(MX50_DEBUG_BASE_ADDR + 0x01002000)
-#define MX50_DIGCTL_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01004000)
-#define MX50_GPMI_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01006000)
-#define MX50_BCH_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01008000)
-#define MX50_ELCDIF_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100a000)
-#define MX50_EPXP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100c000)
-#define MX50_DCP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x0100e000)
-#define MX50_EPDC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01010000)
-#define MX50_QOSC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01012000)
-#define MX50_PERFMON_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01014000)
-#define MX50_SSP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01016000)
-#define MX50_ANATOP_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x01018000)
-#define MX50_NIC_BASE_ADDR		(MX50_DEBUG_BASE_ADDR + 0x08000000)
-
-/*
- * SPBA global module enabled #0
- */
-#define MX50_SPBA0_BASE_ADDR		0x50000000
-#define MX50_SPBA0_SIZE			SZ_1M
-
-#define MX50_MMC_SDHC1_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00004000)
-#define MX50_MMC_SDHC2_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00008000)
-#define MX50_UART3_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x0000c000)
-#define MX50_CSPI1_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x00010000)
-#define MX50_SSI2_BASE_ADDR		(MX50_SPBA0_BASE_ADDR + 0x00014000)
-#define MX50_MMC_SDHC3_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00020000)
-#define MX50_MMC_SDHC4_BASE_ADDR	(MX50_SPBA0_BASE_ADDR + 0x00024000)
-
-/*
- * AIPS 1
- */
-#define MX50_AIPS1_BASE_ADDR	0x53f00000
-#define MX50_AIPS1_SIZE		SZ_1M
-
-#define MX50_OTG_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00080000)
-#define MX50_GPIO1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00084000)
-#define MX50_GPIO2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00088000)
-#define MX50_GPIO3_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x0008c000)
-#define MX50_GPIO4_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00090000)
-#define MX50_KPP_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00094000)
-#define MX50_WDOG_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x00098000)
-#define MX50_GPT1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a0000)
-#define MX50_SRTC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a4000)
-#define MX50_IOMUXC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000a8000)
-#define MX50_EPIT1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000ac000)
-#define MX50_PWM1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000b4000)
-#define MX50_PWM2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000b8000)
-#define MX50_UART1_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000bc000)
-#define MX50_UART2_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000c0000)
-#define MX50_SRC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d0000)
-#define MX50_CCM_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d4000)
-#define MX50_GPC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000d8000)
-#define MX50_GPIO5_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000dc000)
-#define MX50_GPIO6_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000e0000)
-#define MX50_I2C3_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000ec000)
-#define MX50_UART4_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f0000)
-
-#define MX50_MSHC_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f4000)
-#define MX50_RNGB_BASE_ADDR	(MX50_AIPS1_BASE_ADDR + 0x000f8000)
-
-/*
- * AIPS 2
- */
-#define MX50_AIPS2_BASE_ADDR	0x63f00000
-#define MX50_AIPS2_SIZE		SZ_1M
-
-#define MX50_PLL1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00080000)
-#define MX50_PLL2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00084000)
-#define MX50_PLL3_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00088000)
-#define MX50_UART5_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00090000)
-#define MX50_AHBMAX_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x00094000)
-#define MX50_ARM_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000a0000)
-#define MX50_OWIRE_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000a4000)
-#define MX50_CSPI2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000ac000)
-#define MX50_SDMA_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000b0000)
-#define MX50_ROMCP_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000b8000)
-#define MX50_CSPI3_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c0000)
-#define MX50_I2C2_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c4000)
-#define MX50_I2C1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000c8000)
-#define MX50_SSI1_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000cc000)
-#define MX50_AUDMUX_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000d0000)
-#define MX50_WEIM_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000d8000)
-#define MX50_FEC_BASE_ADDR	(MX50_AIPS2_BASE_ADDR + 0x000ec000)
-
-/*
- * Memory regions and CS
- */
-#define MX50_CSD0_BASE_ADDR		0x70000000
-#define MX50_CSD1_BASE_ADDR		0xb0000000
-#define MX50_CS0_BASE_ADDR		0xf0000000
-
-#define MX50_IO_P2V(x)			IMX_IO_P2V(x)
-#define MX50_IO_ADDRESS(x)		IOMEM(MX50_IO_P2V(x))
-
-/*
- * defines for SPBA modules
- */
-#define MX50_SPBA_SDHC1		0x04
-#define MX50_SPBA_SDHC2		0x08
-#define MX50_SPBA_UART3		0x0c
-#define MX50_SPBA_CSPI1		0x10
-#define MX50_SPBA_SSI2		0x14
-#define MX50_SPBA_SDHC3		0x20
-#define MX50_SPBA_SDHC4		0x24
-#define MX50_SPBA_SPDIF		0x28
-#define MX50_SPBA_ATA		0x30
-#define MX50_SPBA_SLIM		0x34
-#define MX50_SPBA_HSI2C		0x38
-#define MX50_SPBA_CTRL		0x3c
-
-/*
- * DMA request assignments
- */
-#define MX50_DMA_REQ_GPC		1
-#define MX50_DMA_REQ_ATA_UART4_RX	2
-#define MX50_DMA_REQ_ATA_UART4_TX	3
-#define MX50_DMA_REQ_CSPI1_RX		6
-#define MX50_DMA_REQ_CSPI1_TX		7
-#define MX50_DMA_REQ_CSPI2_RX		8
-#define MX50_DMA_REQ_CSPI2_TX		9
-#define MX50_DMA_REQ_I2C3_SDHC3		10
-#define MX50_DMA_REQ_SDHC4		11
-#define MX50_DMA_REQ_UART2_FIRI_RX	12
-#define MX50_DMA_REQ_UART2_FIRI_TX	13
-#define MX50_DMA_REQ_EXT0		14
-#define MX50_DMA_REQ_EXT1		15
-#define MX50_DMA_REQ_UART5_RX		16
-#define MX50_DMA_REQ_UART5_TX		17
-#define MX50_DMA_REQ_UART1_RX		18
-#define MX50_DMA_REQ_UART1_TX		19
-#define MX50_DMA_REQ_I2C1_SDHC1		20
-#define MX50_DMA_REQ_I2C2_SDHC2		21
-#define MX50_DMA_REQ_SSI2_RX2		22
-#define MX50_DMA_REQ_SSI2_TX2		23
-#define MX50_DMA_REQ_SSI2_RX1		24
-#define MX50_DMA_REQ_SSI2_TX1		25
-#define MX50_DMA_REQ_SSI1_RX2		26
-#define MX50_DMA_REQ_SSI1_TX2		27
-#define MX50_DMA_REQ_SSI1_RX1		28
-#define MX50_DMA_REQ_SSI1_TX1		29
-#define MX50_DMA_REQ_CSPI_RX		38
-#define MX50_DMA_REQ_CSPI_TX		39
-#define MX50_DMA_REQ_UART3_RX		42
-#define MX50_DMA_REQ_UART3_TX		43
-
-/*
- * Interrupt numbers
- */
-#include <asm/irq.h>
-#define MX50_INT_MMC_SDHC1	(NR_IRQS_LEGACY + 1)
-#define MX50_INT_MMC_SDHC2	(NR_IRQS_LEGACY + 2)
-#define MX50_INT_MMC_SDHC3	(NR_IRQS_LEGACY + 3)
-#define MX50_INT_MMC_SDHC4	(NR_IRQS_LEGACY + 4)
-#define MX50_INT_DAP		(NR_IRQS_LEGACY + 5)
-#define MX50_INT_SDMA		(NR_IRQS_LEGACY + 6)
-#define MX50_INT_IOMUX		(NR_IRQS_LEGACY + 7)
-#define MX50_INT_UART4		(NR_IRQS_LEGACY + 13)
-#define MX50_INT_USB_H1		(NR_IRQS_LEGACY + 14)
-#define MX50_INT_USB_OTG	(NR_IRQS_LEGACY + 18)
-#define MX50_INT_DATABAHN	(NR_IRQS_LEGACY + 19)
-#define MX50_INT_ELCDIF		(NR_IRQS_LEGACY + 20)
-#define MX50_INT_EPXP		(NR_IRQS_LEGACY + 21)
-#define MX50_INT_SRTC_NTZ	(NR_IRQS_LEGACY + 24)
-#define MX50_INT_SRTC_TZ	(NR_IRQS_LEGACY + 25)
-#define MX50_INT_EPDC		(NR_IRQS_LEGACY + 27)
-#define MX50_INT_NIC		(NR_IRQS_LEGACY + 28)
-#define MX50_INT_SSI1		(NR_IRQS_LEGACY + 29)
-#define MX50_INT_SSI2		(NR_IRQS_LEGACY + 30)
-#define MX50_INT_UART1		(NR_IRQS_LEGACY + 31)
-#define MX50_INT_UART2		(NR_IRQS_LEGACY + 32)
-#define MX50_INT_UART3		(NR_IRQS_LEGACY + 33)
-#define MX50_INT_RESV34		(NR_IRQS_LEGACY + 34)
-#define MX50_INT_RESV35		(NR_IRQS_LEGACY + 35)
-#define MX50_INT_CSPI1		(NR_IRQS_LEGACY + 36)
-#define MX50_INT_CSPI2		(NR_IRQS_LEGACY + 37)
-#define MX50_INT_CSPI		(NR_IRQS_LEGACY + 38)
-#define MX50_INT_GPT		(NR_IRQS_LEGACY + 39)
-#define MX50_INT_EPIT1		(NR_IRQS_LEGACY + 40)
-#define MX50_INT_GPIO1_INT7	(NR_IRQS_LEGACY + 42)
-#define MX50_INT_GPIO1_INT6	(NR_IRQS_LEGACY + 43)
-#define MX50_INT_GPIO1_INT5	(NR_IRQS_LEGACY + 44)
-#define MX50_INT_GPIO1_INT4	(NR_IRQS_LEGACY + 45)
-#define MX50_INT_GPIO1_INT3	(NR_IRQS_LEGACY + 46)
-#define MX50_INT_GPIO1_INT2	(NR_IRQS_LEGACY + 47)
-#define MX50_INT_GPIO1_INT1	(NR_IRQS_LEGACY + 48)
-#define MX50_INT_GPIO1_INT0	(NR_IRQS_LEGACY + 49)
-#define MX50_INT_GPIO1_LOW	(NR_IRQS_LEGACY + 50)
-#define MX50_INT_GPIO1_HIGH	(NR_IRQS_LEGACY + 51)
-#define MX50_INT_GPIO2_LOW	(NR_IRQS_LEGACY + 52)
-#define MX50_INT_GPIO2_HIGH	(NR_IRQS_LEGACY + 53)
-#define MX50_INT_GPIO3_LOW	(NR_IRQS_LEGACY + 54)
-#define MX50_INT_GPIO3_HIGH	(NR_IRQS_LEGACY + 55)
-#define MX50_INT_GPIO4_LOW	(NR_IRQS_LEGACY + 56)
-#define MX50_INT_GPIO4_HIGH	(NR_IRQS_LEGACY + 57)
-#define MX50_INT_WDOG1		(NR_IRQS_LEGACY + 58)
-#define MX50_INT_KPP		(NR_IRQS_LEGACY + 60)
-#define MX50_INT_PWM1		(NR_IRQS_LEGACY + 61)
-#define MX50_INT_I2C1		(NR_IRQS_LEGACY + 62)
-#define MX50_INT_I2C2		(NR_IRQS_LEGACY + 63)
-#define MX50_INT_I2C3		(NR_IRQS_LEGACY + 64)
-#define MX50_INT_RESV65		(NR_IRQS_LEGACY + 65)
-#define MX50_INT_DCDC		(NR_IRQS_LEGACY + 66)
-#define MX50_INT_THERMAL_ALARM	(NR_IRQS_LEGACY + 67)
-#define MX50_INT_ANA3		(NR_IRQS_LEGACY + 68)
-#define MX50_INT_ANA4		(NR_IRQS_LEGACY + 69)
-#define MX50_INT_CCM1		(NR_IRQS_LEGACY + 71)
-#define MX50_INT_CCM2		(NR_IRQS_LEGACY + 72)
-#define MX50_INT_GPC1		(NR_IRQS_LEGACY + 73)
-#define MX50_INT_GPC2		(NR_IRQS_LEGACY + 74)
-#define MX50_INT_SRC		(NR_IRQS_LEGACY + 75)
-#define MX50_INT_NM		(NR_IRQS_LEGACY + 76)
-#define MX50_INT_PMU		(NR_IRQS_LEGACY + 77)
-#define MX50_INT_CTI_IRQ	(NR_IRQS_LEGACY + 78)
-#define MX50_INT_CTI1_TG0	(NR_IRQS_LEGACY + 79)
-#define MX50_INT_CTI1_TG1	(NR_IRQS_LEGACY + 80)
-#define MX50_INT_GPU2_IRQ	(NR_IRQS_LEGACY + 84)
-#define MX50_INT_GPU2_BUSY	(NR_IRQS_LEGACY + 85)
-#define MX50_INT_UART5		(NR_IRQS_LEGACY + 86)
-#define MX50_INT_FEC		(NR_IRQS_LEGACY + 87)
-#define MX50_INT_OWIRE		(NR_IRQS_LEGACY + 88)
-#define MX50_INT_CTI1_TG2	(NR_IRQS_LEGACY + 89)
-#define MX50_INT_SJC		(NR_IRQS_LEGACY + 90)
-#define MX50_INT_DCP_CHAN1_3	(NR_IRQS_LEGACY + 91)
-#define MX50_INT_DCP_CHAN0	(NR_IRQS_LEGACY + 92)
-#define MX50_INT_PWM2		(NR_IRQS_LEGACY + 94)
-#define MX50_INT_RNGB		(NR_IRQS_LEGACY + 97)
-#define MX50_INT_CTI1_TG3	(NR_IRQS_LEGACY + 98)
-#define MX50_INT_RAWNAND_BCH	(NR_IRQS_LEGACY + 100)
-#define MX50_INT_RAWNAND_GPMI	(NR_IRQS_LEGACY + 102)
-#define MX50_INT_GPIO5_LOW	(NR_IRQS_LEGACY + 103)
-#define MX50_INT_GPIO5_HIGH	(NR_IRQS_LEGACY + 104)
-#define MX50_INT_GPIO6_LOW	(NR_IRQS_LEGACY + 105)
-#define MX50_INT_GPIO6_HIGH	(NR_IRQS_LEGACY + 106)
-#define MX50_INT_MSHC		(NR_IRQS_LEGACY + 109)
-#define MX50_INT_APBHDMA_CHAN0	(NR_IRQS_LEGACY + 110)
-#define MX50_INT_APBHDMA_CHAN1	(NR_IRQS_LEGACY + 111)
-#define MX50_INT_APBHDMA_CHAN2	(NR_IRQS_LEGACY + 112)
-#define MX50_INT_APBHDMA_CHAN3	(NR_IRQS_LEGACY + 113)
-#define MX50_INT_APBHDMA_CHAN4	(NR_IRQS_LEGACY + 114)
-#define MX50_INT_APBHDMA_CHAN5	(NR_IRQS_LEGACY + 115)
-#define MX50_INT_APBHDMA_CHAN6	(NR_IRQS_LEGACY + 116)
-#define MX50_INT_APBHDMA_CHAN7	(NR_IRQS_LEGACY + 117)
-
-#if !defined(__ASSEMBLY__) && !defined(__MXC_BOOT_UNCOMPRESS)
-extern int mx50_revision(void);
-#endif
-
-#endif /* ifndef __MACH_MX50_H__ */
diff --git a/arch/arm/mach-imx/mxc.h b/arch/arm/mach-imx/mxc.h
index d782983..7dce17a 100644
--- a/arch/arm/mach-imx/mxc.h
+++ b/arch/arm/mach-imx/mxc.h
@@ -32,7 +32,6 @@
 #define MXC_CPU_MX27		27
 #define MXC_CPU_MX31		31
 #define MXC_CPU_MX35		35
-#define MXC_CPU_MX50		50
 #define MXC_CPU_MX51		51
 #define MXC_CPU_MX53		53
 
@@ -126,18 +125,6 @@
 # define cpu_is_mx35()		(0)
 #endif
 
-#ifdef CONFIG_SOC_IMX50
-# ifdef mxc_cpu_type
-#  undef mxc_cpu_type
-#  define mxc_cpu_type __mxc_cpu_type
-# else
-#  define mxc_cpu_type MXC_CPU_MX50
-# endif
-# define cpu_is_mx50()		(mxc_cpu_type == MXC_CPU_MX50)
-#else
-# define cpu_is_mx50()		(0)
-#endif
-
 #ifdef CONFIG_SOC_IMX51
 # ifdef mxc_cpu_type
 #  undef mxc_cpu_type
diff --git a/arch/arm/mach-imx/platsmp.c b/arch/arm/mach-imx/platsmp.c
index 3777b80..7c0b03f 100644
--- a/arch/arm/mach-imx/platsmp.c
+++ b/arch/arm/mach-imx/platsmp.c
@@ -12,14 +12,16 @@
 
 #include <linux/init.h>
 #include <linux/smp.h>
+#include <linux/irqchip/arm-gic.h>
 #include <asm/page.h>
 #include <asm/smp_scu.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 
 #include "common.h"
 #include "hardware.h"
 
+#define SCU_STANDBY_ENABLE	(1 << 5)
+
 static void __iomem *scu_base;
 
 static struct map_desc scu_io_desc __initdata = {
@@ -42,6 +44,14 @@
 	scu_base = IMX_IO_ADDRESS(base);
 }
 
+void imx_scu_standby_enable(void)
+{
+	u32 val = readl_relaxed(scu_base);
+
+	val |= SCU_STANDBY_ENABLE;
+	writel_relaxed(val, scu_base);
+}
+
 static void __cpuinit imx_secondary_init(unsigned int cpu)
 {
 	/*
@@ -71,8 +81,6 @@
 
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
 
 void imx_smp_prepare(void)
@@ -92,5 +100,6 @@
 	.smp_boot_secondary	= imx_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_die		= imx_cpu_die,
+	.cpu_kill		= imx_cpu_kill,
 #endif
 };
diff --git a/arch/arm/mach-imx/pm-imx5.c b/arch/arm/mach-imx/pm-imx5.c
index 2e063c2..f67fd7e 100644
--- a/arch/arm/mach-imx/pm-imx5.c
+++ b/arch/arm/mach-imx/pm-imx5.c
@@ -34,7 +34,7 @@
 
 /*
  * set cpu low power mode before WFI instruction. This function is called
- * mx5 because it can be used for mx50, mx51, and mx53.
+ * mx5 because it can be used for mx51, and mx53.
  */
 static void mx5_cpu_lp_set(enum mxc_cpu_pwr_mode mode)
 {
@@ -85,10 +85,7 @@
 	__raw_writel(plat_lpc, MXC_CORTEXA8_PLAT_LPC);
 	__raw_writel(ccm_clpcr, MXC_CCM_CLPCR);
 	__raw_writel(arm_srpgcr, MXC_SRPG_ARM_SRPGCR);
-
-	/* Enable NEON SRPG for all but MX50TO1.0. */
-	if (mx50_revision() != IMX_CHIP_REVISION_1_0)
-		__raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
+	__raw_writel(arm_srpgcr, MXC_SRPG_NEON_SRPGCR);
 
 	if (stop_mode) {
 		empgc0 |= MXC_SRPGCR_PCR;
diff --git a/arch/arm/mach-imx/pm-imx6q.c b/arch/arm/mach-imx/pm-imx6q.c
index a17543d..ee42d20 100644
--- a/arch/arm/mach-imx/pm-imx6q.c
+++ b/arch/arm/mach-imx/pm-imx6q.c
@@ -41,6 +41,7 @@
 		cpu_suspend(0, imx6q_suspend_finish);
 		imx_smp_prepare();
 		imx_gpc_post_resume();
+		imx6q_set_lpm(WAIT_CLOCKED);
 		break;
 	default:
 		return -EINVAL;
diff --git a/arch/arm/mach-imx/time.c b/arch/arm/mach-imx/time.c
index 62769df..fea9131 100644
--- a/arch/arm/mach-imx/time.c
+++ b/arch/arm/mach-imx/time.c
@@ -152,7 +152,8 @@
 
 	__raw_writel(tcmp, timer_base + V2_TCMP);
 
-	return (int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ?
+	return evt < 0x7fffffff &&
+		(int)(tcmp - __raw_readl(timer_base + V2_TCN)) < 0 ?
 				-ETIME : 0;
 }
 
diff --git a/arch/arm/mach-integrator/integrator_ap.c b/arch/arm/mach-integrator/integrator_ap.c
index 11e2a41..78f1b38 100644
--- a/arch/arm/mach-integrator/integrator_ap.c
+++ b/arch/arm/mach-integrator/integrator_ap.c
@@ -425,7 +425,7 @@
 
 #ifdef CONFIG_OF
 
-static void __init ap_init_timer_of(void)
+static void __init ap_of_timer_init(void)
 {
 	struct device_node *node;
 	const char *path;
@@ -464,10 +464,6 @@
 	integrator_clockevent_init(rate, base, irq);
 }
 
-static struct sys_timer ap_of_timer = {
-	.init		= ap_init_timer_of,
-};
-
 static const struct of_device_id fpga_irq_of_match[] __initconst = {
 	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
 	{ /* Sentinel */ }
@@ -586,7 +582,7 @@
 	.init_early	= ap_init_early,
 	.init_irq	= ap_init_irq_of,
 	.handle_irq	= fpga_handle_irq,
-	.timer		= &ap_of_timer,
+	.init_time	= ap_of_timer_init,
 	.init_machine	= ap_init_of,
 	.restart	= integrator_restart,
 	.dt_compat      = ap_dt_board_compat,
@@ -638,7 +634,7 @@
 	.resource	= &cfi_flash_resource,
 };
 
-static void __init ap_init_timer(void)
+static void __init ap_timer_init(void)
 {
 	struct clk *clk;
 	unsigned long rate;
@@ -657,10 +653,6 @@
 				IRQ_TIMERINT1);
 }
 
-static struct sys_timer ap_timer = {
-	.init		= ap_init_timer,
-};
-
 #define INTEGRATOR_SC_VALID_INT	0x003fffff
 
 static void __init ap_init_irq(void)
@@ -716,7 +708,7 @@
 	.init_early	= ap_init_early,
 	.init_irq	= ap_init_irq,
 	.handle_irq	= fpga_handle_irq,
-	.timer		= &ap_timer,
+	.init_time	= ap_timer_init,
 	.init_machine	= ap_init,
 	.restart	= integrator_restart,
 MACHINE_END
diff --git a/arch/arm/mach-integrator/integrator_cp.c b/arch/arm/mach-integrator/integrator_cp.c
index 7322838..4cef9a0 100644
--- a/arch/arm/mach-integrator/integrator_cp.c
+++ b/arch/arm/mach-integrator/integrator_cp.c
@@ -251,7 +251,7 @@
 
 #ifdef CONFIG_OF
 
-static void __init intcp_timer_init_of(void)
+static void __init cp_of_timer_init(void)
 {
 	struct device_node *node;
 	const char *path;
@@ -283,10 +283,6 @@
 	sp804_clockevents_init(base, irq, node->name);
 }
 
-static struct sys_timer cp_of_timer = {
-	.init		= intcp_timer_init_of,
-};
-
 static const struct of_device_id fpga_irq_of_match[] __initconst = {
 	{ .compatible = "arm,versatile-fpga-irq", .data = fpga_irq_of_init, },
 	{ /* Sentinel */ }
@@ -390,7 +386,7 @@
 	.init_early	= intcp_init_early,
 	.init_irq	= intcp_init_irq_of,
 	.handle_irq	= fpga_handle_irq,
-	.timer		= &cp_of_timer,
+	.init_time	= cp_of_timer_init,
 	.init_machine	= intcp_init_of,
 	.restart	= integrator_restart,
 	.dt_compat      = intcp_dt_board_compat,
@@ -512,7 +508,7 @@
 #define TIMER1_VA_BASE __io_address(INTEGRATOR_TIMER1_BASE)
 #define TIMER2_VA_BASE __io_address(INTEGRATOR_TIMER2_BASE)
 
-static void __init intcp_timer_init(void)
+static void __init cp_timer_init(void)
 {
 	writel(0, TIMER0_VA_BASE + TIMER_CTRL);
 	writel(0, TIMER1_VA_BASE + TIMER_CTRL);
@@ -522,10 +518,6 @@
 	sp804_clockevents_init(TIMER1_VA_BASE, IRQ_TIMERINT1, "timer1");
 }
 
-static struct sys_timer cp_timer = {
-	.init		= intcp_timer_init,
-};
-
 #define INTEGRATOR_CP_MMC_IRQS	{ IRQ_CP_MMCIINT0, IRQ_CP_MMCIINT1 }
 #define INTEGRATOR_CP_AACI_IRQS	{ IRQ_CP_AACIINT }
 
@@ -565,7 +557,7 @@
 	.init_early	= intcp_init_early,
 	.init_irq	= intcp_init_irq,
 	.handle_irq	= fpga_handle_irq,
-	.timer		= &cp_timer,
+	.init_time	= cp_timer_init,
 	.init_machine	= intcp_init,
 	.restart	= integrator_restart,
 MACHINE_END
diff --git a/arch/arm/mach-integrator/pci_v3.c b/arch/arm/mach-integrator/pci_v3.c
index be50e79..e7fcea7 100644
--- a/arch/arm/mach-integrator/pci_v3.c
+++ b/arch/arm/mach-integrator/pci_v3.c
@@ -475,13 +475,12 @@
 {
 	int ret = 0;
 
+	if (!ap_syscon_base)
+		return -EINVAL;
+
 	if (nr == 0) {
 		sys->mem_offset = PHYS_PCI_MEM_BASE;
 		ret = pci_v3_setup_resources(sys);
-		/* Remap the Integrator system controller */
-		ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
-		if (!ap_syscon_base)
-			return -EINVAL;
 	}
 
 	return ret;
@@ -497,6 +496,13 @@
 	unsigned int temp;
 	int ret;
 
+	/* Remap the Integrator system controller */
+	ap_syscon_base = ioremap(INTEGRATOR_SC_BASE, 0x100);
+	if (!ap_syscon_base) {
+		pr_err("unable to remap the AP syscon for PCIv3\n");
+		return;
+	}
+
 	pcibios_min_mem = 0x00100000;
 
 	/*
diff --git a/arch/arm/mach-iop13xx/iq81340mc.c b/arch/arm/mach-iop13xx/iq81340mc.c
index e3f3e7d..02a8228 100644
--- a/arch/arm/mach-iop13xx/iq81340mc.c
+++ b/arch/arm/mach-iop13xx/iq81340mc.c
@@ -84,17 +84,13 @@
 	iop_init_time(bus_freq);
 }
 
-static struct sys_timer iq81340mc_timer = {
-       .init       = iq81340mc_timer_init,
-};
-
 MACHINE_START(IQ81340MC, "Intel IQ81340MC")
 	/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
 	.atag_offset    = 0x100,
 	.init_early     = iop13xx_init_early,
 	.map_io         = iop13xx_map_io,
 	.init_irq       = iop13xx_init_irq,
-	.timer          = &iq81340mc_timer,
+	.init_time	= iq81340mc_timer_init,
 	.init_machine   = iq81340mc_init,
 	.restart	= iop13xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-iop13xx/iq81340sc.c b/arch/arm/mach-iop13xx/iq81340sc.c
index e947441..1b80f10 100644
--- a/arch/arm/mach-iop13xx/iq81340sc.c
+++ b/arch/arm/mach-iop13xx/iq81340sc.c
@@ -86,17 +86,13 @@
 	iop_init_time(bus_freq);
 }
 
-static struct sys_timer iq81340sc_timer = {
-       .init       = iq81340sc_timer_init,
-};
-
 MACHINE_START(IQ81340SC, "Intel IQ81340SC")
 	/* Maintainer: Dan Williams <dan.j.williams@intel.com> */
 	.atag_offset    = 0x100,
 	.init_early     = iop13xx_init_early,
 	.map_io         = iop13xx_map_io,
 	.init_irq       = iop13xx_init_irq,
-	.timer          = &iq81340sc_timer,
+	.init_time	= iq81340sc_timer_init,
 	.init_machine   = iq81340sc_init,
 	.restart	= iop13xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-iop32x/em7210.c b/arch/arm/mach-iop32x/em7210.c
index 9f369f0..31fbb6c 100644
--- a/arch/arm/mach-iop32x/em7210.c
+++ b/arch/arm/mach-iop32x/em7210.c
@@ -40,10 +40,6 @@
 	iop_init_time(200000000);
 }
 
-static struct sys_timer em7210_timer = {
-	.init		= em7210_timer_init,
-};
-
 /*
  * EM7210 RTC
  */
@@ -205,7 +201,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= em7210_map_io,
 	.init_irq	= iop32x_init_irq,
-	.timer		= &em7210_timer,
+	.init_time	= em7210_timer_init,
 	.init_machine	= em7210_init_machine,
 	.restart	= iop3xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-iop32x/glantank.c b/arch/arm/mach-iop32x/glantank.c
index 02e20c3..ac30470 100644
--- a/arch/arm/mach-iop32x/glantank.c
+++ b/arch/arm/mach-iop32x/glantank.c
@@ -44,10 +44,6 @@
 	iop_init_time(200000000);
 }
 
-static struct sys_timer glantank_timer = {
-	.init		= glantank_timer_init,
-};
-
 
 /*
  * GLAN Tank I/O.
@@ -209,7 +205,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= glantank_map_io,
 	.init_irq	= iop32x_init_irq,
-	.timer		= &glantank_timer,
+	.init_time	= glantank_timer_init,
 	.init_machine	= glantank_init_machine,
 	.restart	= iop3xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-iop32x/iq31244.c b/arch/arm/mach-iop32x/iq31244.c
index ddd1c7e..f2cd296 100644
--- a/arch/arm/mach-iop32x/iq31244.c
+++ b/arch/arm/mach-iop32x/iq31244.c
@@ -75,10 +75,6 @@
 	}
 }
 
-static struct sys_timer iq31244_timer = {
-	.init		= iq31244_timer_init,
-};
-
 
 /*
  * IQ31244 I/O.
@@ -314,7 +310,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= iq31244_map_io,
 	.init_irq	= iop32x_init_irq,
-	.timer		= &iq31244_timer,
+	.init_time	= iq31244_timer_init,
 	.init_machine	= iq31244_init_machine,
 	.restart	= iop3xx_restart,
 MACHINE_END
@@ -329,7 +325,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= iq31244_map_io,
 	.init_irq	= iop32x_init_irq,
-	.timer		= &iq31244_timer,
+	.init_time	= iq31244_timer_init,
 	.init_machine	= iq31244_init_machine,
 	.restart	= iop3xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-iop32x/iq80321.c b/arch/arm/mach-iop32x/iq80321.c
index bf155e6..015435d 100644
--- a/arch/arm/mach-iop32x/iq80321.c
+++ b/arch/arm/mach-iop32x/iq80321.c
@@ -43,10 +43,6 @@
 	iop_init_time(200000000);
 }
 
-static struct sys_timer iq80321_timer = {
-	.init		= iq80321_timer_init,
-};
-
 
 /*
  * IQ80321 I/O.
@@ -188,7 +184,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= iq80321_map_io,
 	.init_irq	= iop32x_init_irq,
-	.timer		= &iq80321_timer,
+	.init_time	= iq80321_timer_init,
 	.init_machine	= iq80321_init_machine,
 	.restart	= iop3xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-iop32x/n2100.c b/arch/arm/mach-iop32x/n2100.c
index 5a7ae91..ea0984a 100644
--- a/arch/arm/mach-iop32x/n2100.c
+++ b/arch/arm/mach-iop32x/n2100.c
@@ -50,10 +50,6 @@
 	iop_init_time(198000000);
 }
 
-static struct sys_timer n2100_timer = {
-	.init		= n2100_timer_init,
-};
-
 
 /*
  * N2100 I/O.
@@ -337,7 +333,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= n2100_map_io,
 	.init_irq	= iop32x_init_irq,
-	.timer		= &n2100_timer,
+	.init_time	= n2100_timer_init,
 	.init_machine	= n2100_init_machine,
 	.restart	= n2100_restart,
 MACHINE_END
diff --git a/arch/arm/mach-iop33x/iq80331.c b/arch/arm/mach-iop33x/iq80331.c
index e74a7de..c43304a 100644
--- a/arch/arm/mach-iop33x/iq80331.c
+++ b/arch/arm/mach-iop33x/iq80331.c
@@ -45,10 +45,6 @@
 		iop_init_time(266000000);
 }
 
-static struct sys_timer iq80331_timer = {
-	.init		= iq80331_timer_init,
-};
-
 
 /*
  * IQ80331 PCI.
@@ -143,7 +139,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= iop3xx_map_io,
 	.init_irq	= iop33x_init_irq,
-	.timer		= &iq80331_timer,
+	.init_time	= iq80331_timer_init,
 	.init_machine	= iq80331_init_machine,
 	.restart	= iop3xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-iop33x/iq80332.c b/arch/arm/mach-iop33x/iq80332.c
index e2f5bee..8192987 100644
--- a/arch/arm/mach-iop33x/iq80332.c
+++ b/arch/arm/mach-iop33x/iq80332.c
@@ -45,10 +45,6 @@
 		iop_init_time(266000000);
 }
 
-static struct sys_timer iq80332_timer = {
-	.init		= iq80332_timer_init,
-};
-
 
 /*
  * IQ80332 PCI.
@@ -143,7 +139,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= iop3xx_map_io,
 	.init_irq	= iop33x_init_irq,
-	.timer		= &iq80332_timer,
+	.init_time	= iq80332_timer_init,
 	.init_machine	= iq80332_init_machine,
 	.restart	= iop3xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/avila-setup.c b/arch/arm/mach-ixp4xx/avila-setup.c
index 90e42e9..6beec15 100644
--- a/arch/arm/mach-ixp4xx/avila-setup.c
+++ b/arch/arm/mach-ixp4xx/avila-setup.c
@@ -167,7 +167,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= avila_init,
 #if defined(CONFIG_PCI)
@@ -187,7 +187,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= avila_init,
 #if defined(CONFIG_PCI)
diff --git a/arch/arm/mach-ixp4xx/common.c b/arch/arm/mach-ixp4xx/common.c
index 65ff98c..1dbeb7c 100644
--- a/arch/arm/mach-ixp4xx/common.c
+++ b/arch/arm/mach-ixp4xx/common.c
@@ -307,10 +307,6 @@
 	ixp4xx_clockevent_init();
 }
 
-struct sys_timer ixp4xx_timer = {
-	.init		= ixp4xx_timer_init,
-};
-
 static struct pxa2xx_udc_mach_info ixp4xx_udc_info;
 
 void __init ixp4xx_set_udc_info(struct pxa2xx_udc_mach_info *info)
diff --git a/arch/arm/mach-ixp4xx/coyote-setup.c b/arch/arm/mach-ixp4xx/coyote-setup.c
index 1b83110..820cae8 100644
--- a/arch/arm/mach-ixp4xx/coyote-setup.c
+++ b/arch/arm/mach-ixp4xx/coyote-setup.c
@@ -112,7 +112,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= coyote_init,
 #if defined(CONFIG_PCI)
@@ -132,7 +132,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= coyote_init,
 	.restart	= ixp4xx_restart,
diff --git a/arch/arm/mach-ixp4xx/dsmg600-setup.c b/arch/arm/mach-ixp4xx/dsmg600-setup.c
index 97a0af8..5d413f8 100644
--- a/arch/arm/mach-ixp4xx/dsmg600-setup.c
+++ b/arch/arm/mach-ixp4xx/dsmg600-setup.c
@@ -226,10 +226,6 @@
     ixp4xx_timer_init();
 }
 
-static struct sys_timer dsmg600_timer = {
-    .init   = dsmg600_timer_init,
-};
-
 static void __init dsmg600_init(void)
 {
 	ixp4xx_sys_init();
@@ -282,7 +278,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer          = &dsmg600_timer,
+	.init_time	= dsmg600_timer_init,
 	.init_machine	= dsmg600_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff --git a/arch/arm/mach-ixp4xx/fsg-setup.c b/arch/arm/mach-ixp4xx/fsg-setup.c
index 9175a25..429966b7 100644
--- a/arch/arm/mach-ixp4xx/fsg-setup.c
+++ b/arch/arm/mach-ixp4xx/fsg-setup.c
@@ -272,7 +272,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= fsg_init,
 #if defined(CONFIG_PCI)
diff --git a/arch/arm/mach-ixp4xx/gateway7001-setup.c b/arch/arm/mach-ixp4xx/gateway7001-setup.c
index 033c717..3d24b3f 100644
--- a/arch/arm/mach-ixp4xx/gateway7001-setup.c
+++ b/arch/arm/mach-ixp4xx/gateway7001-setup.c
@@ -99,7 +99,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= gateway7001_init,
 #if defined(CONFIG_PCI)
diff --git a/arch/arm/mach-ixp4xx/goramo_mlr.c b/arch/arm/mach-ixp4xx/goramo_mlr.c
index 53b8348..e54ff49 100644
--- a/arch/arm/mach-ixp4xx/goramo_mlr.c
+++ b/arch/arm/mach-ixp4xx/goramo_mlr.c
@@ -498,7 +498,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= gmlr_init,
 #if defined(CONFIG_PCI)
diff --git a/arch/arm/mach-ixp4xx/gtwx5715-setup.c b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
index 18ebc6b..16a1299 100644
--- a/arch/arm/mach-ixp4xx/gtwx5715-setup.c
+++ b/arch/arm/mach-ixp4xx/gtwx5715-setup.c
@@ -167,7 +167,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= gtwx5715_init,
 #if defined(CONFIG_PCI)
diff --git a/arch/arm/mach-ixp4xx/include/mach/platform.h b/arch/arm/mach-ixp4xx/include/mach/platform.h
index 5bce94a..db5afb6 100644
--- a/arch/arm/mach-ixp4xx/include/mach/platform.h
+++ b/arch/arm/mach-ixp4xx/include/mach/platform.h
@@ -89,8 +89,6 @@
 	void __iomem	*cs1;
 };
 
-struct sys_timer;
-
 #define IXP4XX_ETH_NPEA		0x00
 #define IXP4XX_ETH_NPEB		0x10
 #define IXP4XX_ETH_NPEC		0x20
@@ -125,7 +123,6 @@
 extern void ixp4xx_init_irq(void);
 extern void ixp4xx_sys_init(void);
 extern void ixp4xx_timer_init(void);
-extern struct sys_timer ixp4xx_timer;
 extern void ixp4xx_restart(char, const char *);
 extern void ixp4xx_pci_preinit(void);
 struct pci_sys_data;
diff --git a/arch/arm/mach-ixp4xx/ixdp425-setup.c b/arch/arm/mach-ixp4xx/ixdp425-setup.c
index 108a9d3..22d688b 100644
--- a/arch/arm/mach-ixp4xx/ixdp425-setup.c
+++ b/arch/arm/mach-ixp4xx/ixdp425-setup.c
@@ -252,7 +252,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
@@ -268,7 +268,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
@@ -283,7 +283,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
@@ -298,7 +298,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= ixdp425_init,
 #if defined(CONFIG_PCI)
diff --git a/arch/arm/mach-ixp4xx/nas100d-setup.c b/arch/arm/mach-ixp4xx/nas100d-setup.c
index 33cb095..ed667ce 100644
--- a/arch/arm/mach-ixp4xx/nas100d-setup.c
+++ b/arch/arm/mach-ixp4xx/nas100d-setup.c
@@ -317,7 +317,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer          = &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.init_machine	= nas100d_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff --git a/arch/arm/mach-ixp4xx/nslu2-setup.c b/arch/arm/mach-ixp4xx/nslu2-setup.c
index e2903fa..7e55236 100644
--- a/arch/arm/mach-ixp4xx/nslu2-setup.c
+++ b/arch/arm/mach-ixp4xx/nslu2-setup.c
@@ -232,10 +232,6 @@
     ixp4xx_timer_init();
 }
 
-static struct sys_timer nslu2_timer = {
-    .init   = nslu2_timer_init,
-};
-
 static void __init nslu2_init(void)
 {
 	uint8_t __iomem *f;
@@ -303,7 +299,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer          = &nslu2_timer,
+	.init_time	= nslu2_timer_init,
 	.init_machine	= nslu2_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
diff --git a/arch/arm/mach-ixp4xx/omixp-setup.c b/arch/arm/mach-ixp4xx/omixp-setup.c
index 158ddb7..46a89f5 100644
--- a/arch/arm/mach-ixp4xx/omixp-setup.c
+++ b/arch/arm/mach-ixp4xx/omixp-setup.c
@@ -245,7 +245,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer          = &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.init_machine	= omixp_init,
 	.restart	= ixp4xx_restart,
 MACHINE_END
@@ -257,7 +257,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer          = &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.init_machine	= omixp_init,
 #if defined(CONFIG_PCI)
 	.dma_zone_size	= SZ_64M,
@@ -272,7 +272,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer          = &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.init_machine	= omixp_init,
 	.restart	= ixp4xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-ixp4xx/vulcan-setup.c b/arch/arm/mach-ixp4xx/vulcan-setup.c
index 2798f43..d42730a 100644
--- a/arch/arm/mach-ixp4xx/vulcan-setup.c
+++ b/arch/arm/mach-ixp4xx/vulcan-setup.c
@@ -239,7 +239,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= vulcan_init,
 #if defined(CONFIG_PCI)
diff --git a/arch/arm/mach-ixp4xx/wg302v2-setup.c b/arch/arm/mach-ixp4xx/wg302v2-setup.c
index a785175..8f9ea2f 100644
--- a/arch/arm/mach-ixp4xx/wg302v2-setup.c
+++ b/arch/arm/mach-ixp4xx/wg302v2-setup.c
@@ -100,7 +100,7 @@
 	.map_io		= ixp4xx_map_io,
 	.init_early	= ixp4xx_init_early,
 	.init_irq	= ixp4xx_init_irq,
-	.timer		= &ixp4xx_timer,
+	.init_time	= ixp4xx_timer_init,
 	.atag_offset	= 0x100,
 	.init_machine	= wg302v2_init,
 #if defined(CONFIG_PCI)
diff --git a/arch/arm/mach-kirkwood/Makefile b/arch/arm/mach-kirkwood/Makefile
index 8d2e5a9..d665309 100644
--- a/arch/arm/mach-kirkwood/Makefile
+++ b/arch/arm/mach-kirkwood/Makefile
@@ -19,7 +19,6 @@
 obj-$(CONFIG_MACH_NET5BIG_V2)		+= netxbig_v2-setup.o lacie_v2-common.o
 obj-$(CONFIG_MACH_T5325)		+= t5325-setup.o
 
-obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
 obj-$(CONFIG_ARCH_KIRKWOOD_DT)		+= board-dt.o
 obj-$(CONFIG_MACH_DREAMPLUG_DT)		+= board-dreamplug.o
 obj-$(CONFIG_MACH_ICONNECT_DT)		+= board-iconnect.o
diff --git a/arch/arm/mach-kirkwood/board-dt.c b/arch/arm/mach-kirkwood/board-dt.c
index de4fd2b..95cc04d 100644
--- a/arch/arm/mach-kirkwood/board-dt.c
+++ b/arch/arm/mach-kirkwood/board-dt.c
@@ -98,6 +98,8 @@
 	/* Setup root of clk tree */
 	kirkwood_of_clk_init();
 
+	kirkwood_cpuidle_init();
+
 #ifdef CONFIG_KEXEC
 	kexec_reinit = kirkwood_enable_pcie;
 #endif
@@ -183,7 +185,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= orion_dt_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.init_machine	= kirkwood_dt_init,
 	.restart	= kirkwood_restart,
 	.dt_compat	= kirkwood_dt_board_compat,
diff --git a/arch/arm/mach-kirkwood/board-ns2.c b/arch/arm/mach-kirkwood/board-ns2.c
index 8821720..f4632a8 100644
--- a/arch/arm/mach-kirkwood/board-ns2.c
+++ b/arch/arm/mach-kirkwood/board-ns2.c
@@ -18,47 +18,11 @@
 #include <linux/gpio.h>
 #include <linux/of.h>
 #include "common.h"
-#include "mpp.h"
 
 static struct mv643xx_eth_platform_data ns2_ge00_data = {
 	.phy_addr	= MV643XX_ETH_PHY_ADDR(8),
 };
 
-static unsigned int ns2_mpp_config[] __initdata = {
-	MPP0_SPI_SCn,
-	MPP1_SPI_MOSI,
-	MPP2_SPI_SCK,
-	MPP3_SPI_MISO,
-	MPP4_NF_IO6,
-	MPP5_NF_IO7,
-	MPP6_SYSRST_OUTn,
-	MPP7_GPO,		/* Fan speed (bit 1) */
-	MPP8_TW0_SDA,
-	MPP9_TW0_SCK,
-	MPP10_UART0_TXD,
-	MPP11_UART0_RXD,
-	MPP12_GPO,		/* Red led */
-	MPP14_GPIO,		/* USB fuse */
-	MPP16_GPIO,		/* SATA 0 power */
-	MPP17_GPIO,		/* SATA 1 power */
-	MPP18_NF_IO0,
-	MPP19_NF_IO1,
-	MPP20_SATA1_ACTn,
-	MPP21_SATA0_ACTn,
-	MPP22_GPIO,		/* Fan speed (bit 0) */
-	MPP23_GPIO,		/* Fan power */
-	MPP24_GPIO,		/* USB mode select */
-	MPP25_GPIO,		/* Fan rotation fail */
-	MPP26_GPIO,		/* USB device vbus */
-	MPP28_GPIO,		/* USB enable host vbus */
-	MPP29_GPIO,		/* Blue led (slow register) */
-	MPP30_GPIO,		/* Blue led (command register) */
-	MPP31_GPIO,		/* Board power off */
-	MPP32_GPIO,		/* Power button (0 = Released, 1 = Pushed) */
-	MPP33_GPO,		/* Fan speed (bit 2) */
-	0
-};
-
 #define NS2_GPIO_POWER_OFF	31
 
 static void ns2_power_off(void)
@@ -71,8 +35,6 @@
 	/*
 	 * Basic setup. Needs to be called early.
 	 */
-	kirkwood_mpp_conf(ns2_mpp_config);
-
 	if (of_machine_is_compatible("lacie,netspace_lite_v2") ||
 	    of_machine_is_compatible("lacie,netspace_mini_v2"))
 		ns2_ge00_data.phy_addr = MV643XX_ETH_PHY_ADDR(0);
diff --git a/arch/arm/mach-kirkwood/common.c b/arch/arm/mach-kirkwood/common.c
index bac21a5..49792a0 100644
--- a/arch/arm/mach-kirkwood/common.c
+++ b/arch/arm/mach-kirkwood/common.c
@@ -499,6 +499,28 @@
 	orion_wdt_init();
 }
 
+/*****************************************************************************
+ * CPU idle
+ ****************************************************************************/
+static struct resource kirkwood_cpuidle_resource[] = {
+	{
+		.flags	= IORESOURCE_MEM,
+		.start	= DDR_OPERATION_BASE,
+		.end	= DDR_OPERATION_BASE + 3,
+	},
+};
+
+static struct platform_device kirkwood_cpuidle = {
+	.name		= "kirkwood_cpuidle",
+	.id		= -1,
+	.resource	= kirkwood_cpuidle_resource,
+	.num_resources	= 1,
+};
+
+void __init kirkwood_cpuidle_init(void)
+{
+	platform_device_register(&kirkwood_cpuidle);
+}
 
 /*****************************************************************************
  * Time handling
@@ -530,7 +552,7 @@
 	return 166666667;
 }
 
-static void __init kirkwood_timer_init(void)
+void __init kirkwood_timer_init(void)
 {
 	kirkwood_tclk = kirkwood_find_tclk();
 
@@ -538,10 +560,6 @@
 			IRQ_KIRKWOOD_BRIDGE, kirkwood_tclk);
 }
 
-struct sys_timer kirkwood_timer = {
-	.init = kirkwood_timer_init,
-};
-
 /*****************************************************************************
  * Audio
  ****************************************************************************/
@@ -671,6 +689,7 @@
 	kirkwood_xor1_init();
 	kirkwood_crypto_init();
 
+	kirkwood_cpuidle_init();
 #ifdef CONFIG_KEXEC
 	kexec_reinit = kirkwood_enable_pcie;
 #endif
diff --git a/arch/arm/mach-kirkwood/common.h b/arch/arm/mach-kirkwood/common.h
index 5ffa57f..e956d02 100644
--- a/arch/arm/mach-kirkwood/common.h
+++ b/arch/arm/mach-kirkwood/common.h
@@ -50,6 +50,7 @@
 void kirkwood_nand_init_rnb(struct mtd_partition *parts, int nr_parts,
 			    int (*dev_ready)(struct mtd_info *));
 void kirkwood_audio_init(void);
+void kirkwood_cpuidle_init(void);
 void kirkwood_restart(char, const char *);
 void kirkwood_clk_init(void);
 
@@ -156,7 +157,7 @@
 void kirkwood_crypto_init(void);
 
 extern int kirkwood_tclk;
-extern struct sys_timer kirkwood_timer;
+extern void kirkwood_timer_init(void);
 
 #define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
 
diff --git a/arch/arm/mach-kirkwood/d2net_v2-setup.c b/arch/arm/mach-kirkwood/d2net_v2-setup.c
index 2c1a453..4534180 100644
--- a/arch/arm/mach-kirkwood/d2net_v2-setup.c
+++ b/arch/arm/mach-kirkwood/d2net_v2-setup.c
@@ -226,6 +226,6 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
index c49b177..5a369fe 100644
--- a/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
+++ b/arch/arm/mach-kirkwood/db88f6281-bp-setup.c
@@ -103,6 +103,6 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/dockstar-setup.c b/arch/arm/mach-kirkwood/dockstar-setup.c
index 791a98f..77f98f2 100644
--- a/arch/arm/mach-kirkwood/dockstar-setup.c
+++ b/arch/arm/mach-kirkwood/dockstar-setup.c
@@ -107,6 +107,6 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/guruplug-setup.c b/arch/arm/mach-kirkwood/guruplug-setup.c
index 7cb55f9..1c6e736 100644
--- a/arch/arm/mach-kirkwood/guruplug-setup.c
+++ b/arch/arm/mach-kirkwood/guruplug-setup.c
@@ -126,6 +126,6 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/include/mach/kirkwood.h b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
index 041653a..a05563a 100644
--- a/arch/arm/mach-kirkwood/include/mach/kirkwood.h
+++ b/arch/arm/mach-kirkwood/include/mach/kirkwood.h
@@ -60,8 +60,9 @@
  * Register Map
  */
 #define DDR_VIRT_BASE		(KIRKWOOD_REGS_VIRT_BASE + 0x00000)
+#define DDR_PHYS_BASE		(KIRKWOOD_REGS_PHYS_BASE + 0x00000)
 #define  DDR_WINDOW_CPU_BASE	(DDR_VIRT_BASE + 0x1500)
-#define DDR_OPERATION_BASE	(DDR_VIRT_BASE + 0x1418)
+#define DDR_OPERATION_BASE	(DDR_PHYS_BASE + 0x1418)
 
 #define DEV_BUS_PHYS_BASE	(KIRKWOOD_REGS_PHYS_BASE + 0x10000)
 #define DEV_BUS_VIRT_BASE	(KIRKWOOD_REGS_VIRT_BASE + 0x10000)
diff --git a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
index 6d8364a..ba384b9 100644
--- a/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
+++ b/arch/arm/mach-kirkwood/mv88f6281gtw_ge-setup.c
@@ -167,6 +167,6 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/netspace_v2-setup.c b/arch/arm/mach-kirkwood/netspace_v2-setup.c
index 728e86d..3b70661 100644
--- a/arch/arm/mach-kirkwood/netspace_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netspace_v2-setup.c
@@ -263,7 +263,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
 #endif
@@ -275,7 +275,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
 #endif
@@ -287,7 +287,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-kirkwood/netxbig_v2-setup.c b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
index a3b0914..913d032 100644
--- a/arch/arm/mach-kirkwood/netxbig_v2-setup.c
+++ b/arch/arm/mach-kirkwood/netxbig_v2-setup.c
@@ -404,7 +404,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
 #endif
@@ -416,7 +416,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-kirkwood/openrd-setup.c b/arch/arm/mach-kirkwood/openrd-setup.c
index 7e81e9b..8ddd69f 100644
--- a/arch/arm/mach-kirkwood/openrd-setup.c
+++ b/arch/arm/mach-kirkwood/openrd-setup.c
@@ -221,7 +221,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
 #endif
@@ -234,7 +234,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
 #endif
@@ -247,7 +247,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-kirkwood/pcie.c b/arch/arm/mach-kirkwood/pcie.c
index a1c3ab6..d96ad4c 100644
--- a/arch/arm/mach-kirkwood/pcie.c
+++ b/arch/arm/mach-kirkwood/pcie.c
@@ -247,13 +247,9 @@
 
 static void __init add_pcie_port(int index, void __iomem *base)
 {
-	pr_info("Kirkwood PCIe port %d: ", index);
-
-	if (orion_pcie_link_up(base)) {
-		pr_info("link up\n");
-		pcie_port_map[num_pcie_ports++] = index;
-	} else
-		pr_info("link down, ignoring\n");
+	pcie_port_map[num_pcie_ports++] = index;
+	pr_info("Kirkwood PCIe port %d: link %s\n", index,
+		orion_pcie_link_up(base) ? "up" : "down");
 }
 
 void __init kirkwood_pcie_init(unsigned int portmask)
diff --git a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
index 19072c8..e4fd312 100644
--- a/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6192-nas-setup.c
@@ -84,6 +84,6 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/rd88f6281-setup.c b/arch/arm/mach-kirkwood/rd88f6281-setup.c
index 9717101..c7d93b4 100644
--- a/arch/arm/mach-kirkwood/rd88f6281-setup.c
+++ b/arch/arm/mach-kirkwood/rd88f6281-setup.c
@@ -120,6 +120,6 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/sheevaplug-setup.c b/arch/arm/mach-kirkwood/sheevaplug-setup.c
index 8a17594..55b68fa 100644
--- a/arch/arm/mach-kirkwood/sheevaplug-setup.c
+++ b/arch/arm/mach-kirkwood/sheevaplug-setup.c
@@ -143,7 +143,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
 #endif
@@ -155,7 +155,7 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-kirkwood/t5325-setup.c b/arch/arm/mach-kirkwood/t5325-setup.c
index f2daf71..8736f8c 100644
--- a/arch/arm/mach-kirkwood/t5325-setup.c
+++ b/arch/arm/mach-kirkwood/t5325-setup.c
@@ -211,6 +211,6 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/ts219-setup.c b/arch/arm/mach-kirkwood/ts219-setup.c
index 73e2b6c..283abff 100644
--- a/arch/arm/mach-kirkwood/ts219-setup.c
+++ b/arch/arm/mach-kirkwood/ts219-setup.c
@@ -137,6 +137,6 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
diff --git a/arch/arm/mach-kirkwood/ts41x-setup.c b/arch/arm/mach-kirkwood/ts41x-setup.c
index e4c6127..81d5858 100644
--- a/arch/arm/mach-kirkwood/ts41x-setup.c
+++ b/arch/arm/mach-kirkwood/ts41x-setup.c
@@ -181,6 +181,6 @@
 	.map_io		= kirkwood_map_io,
 	.init_early	= kirkwood_init_early,
 	.init_irq	= kirkwood_init_irq,
-	.timer		= &kirkwood_timer,
+	.init_time	= kirkwood_timer_init,
 	.restart	= kirkwood_restart,
 MACHINE_END
diff --git a/arch/arm/mach-ks8695/board-acs5k.c b/arch/arm/mach-ks8695/board-acs5k.c
index b0c306c..456d638 100644
--- a/arch/arm/mach-ks8695/board-acs5k.c
+++ b/arch/arm/mach-ks8695/board-acs5k.c
@@ -227,6 +227,6 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= acs5k_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart	= ks8695_restart,
 MACHINE_END
diff --git a/arch/arm/mach-ks8695/board-dsm320.c b/arch/arm/mach-ks8695/board-dsm320.c
index e0d36ce..d37c218 100644
--- a/arch/arm/mach-ks8695/board-dsm320.c
+++ b/arch/arm/mach-ks8695/board-dsm320.c
@@ -125,6 +125,6 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= dsm320_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart	= ks8695_restart,
 MACHINE_END
diff --git a/arch/arm/mach-ks8695/board-micrel.c b/arch/arm/mach-ks8695/board-micrel.c
index a827072..3acbdfd 100644
--- a/arch/arm/mach-ks8695/board-micrel.c
+++ b/arch/arm/mach-ks8695/board-micrel.c
@@ -57,6 +57,6 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= micrel_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart	= ks8695_restart,
 MACHINE_END
diff --git a/arch/arm/mach-ks8695/board-og.c b/arch/arm/mach-ks8695/board-og.c
index 1623ba4..002bc61 100644
--- a/arch/arm/mach-ks8695/board-og.c
+++ b/arch/arm/mach-ks8695/board-og.c
@@ -145,7 +145,7 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= og_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart        = ks8695_restart,
 MACHINE_END
 #endif
@@ -157,7 +157,7 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= og_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart        = ks8695_restart,
 MACHINE_END
 #endif
@@ -169,7 +169,7 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= og_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart        = ks8695_restart,
 MACHINE_END
 #endif
@@ -181,7 +181,7 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= og_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart        = ks8695_restart,
 MACHINE_END
 #endif
@@ -193,7 +193,7 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= og_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart        = ks8695_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-ks8695/board-sg.c b/arch/arm/mach-ks8695/board-sg.c
index f35b98b..fdf2352 100644
--- a/arch/arm/mach-ks8695/board-sg.c
+++ b/arch/arm/mach-ks8695/board-sg.c
@@ -91,7 +91,7 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= sg_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart	= ks8695_restart,
 MACHINE_END
 #endif
@@ -103,7 +103,7 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= sg_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart	= ks8695_restart,
 MACHINE_END
 #endif
@@ -115,7 +115,7 @@
 	.map_io		= ks8695_map_io,
 	.init_irq	= ks8695_init_irq,
 	.init_machine	= sg_init,
-	.timer		= &ks8695_timer,
+	.init_time	= ks8695_timer_init,
 	.restart	= ks8695_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-ks8695/generic.h b/arch/arm/mach-ks8695/generic.h
index f8bdb11..6e97ce4 100644
--- a/arch/arm/mach-ks8695/generic.h
+++ b/arch/arm/mach-ks8695/generic.h
@@ -13,4 +13,4 @@
 extern __init void ks8695_map_io(void);
 extern __init void ks8695_init_irq(void);
 extern void ks8695_restart(char, const char *);
-extern struct sys_timer ks8695_timer;
+extern void ks8695_timer_init(void);
diff --git a/arch/arm/mach-ks8695/time.c b/arch/arm/mach-ks8695/time.c
index 46c84bc..c272a386 100644
--- a/arch/arm/mach-ks8695/time.c
+++ b/arch/arm/mach-ks8695/time.c
@@ -146,7 +146,7 @@
 					0xFFFFFFFFU);
 }
 
-static void __init ks8695_timer_init (void)
+void __init ks8695_timer_init(void)
 {
 	ks8695_timer_setup();
 
@@ -154,10 +154,6 @@
 	setup_irq(KS8695_IRQ_TIMER1, &ks8695_timer_irq);
 }
 
-struct sys_timer ks8695_timer = {
-	.init		= ks8695_timer_init,
-};
-
 void ks8695_restart(char mode, const char *cmd)
 {
 	unsigned int reg;
diff --git a/arch/arm/mach-lpc32xx/common.h b/arch/arm/mach-lpc32xx/common.h
index afeac3b..e0b2606 100644
--- a/arch/arm/mach-lpc32xx/common.h
+++ b/arch/arm/mach-lpc32xx/common.h
@@ -25,7 +25,7 @@
 /*
  * Other arch specific structures and functions
  */
-extern struct sys_timer lpc32xx_timer;
+extern void lpc32xx_timer_init(void);
 extern void __init lpc32xx_init_irq(void);
 extern void __init lpc32xx_map_io(void);
 extern void __init lpc32xx_serial_init(void);
diff --git a/arch/arm/mach-lpc32xx/phy3250.c b/arch/arm/mach-lpc32xx/phy3250.c
index e8ff4c3..c1cd5a9 100644
--- a/arch/arm/mach-lpc32xx/phy3250.c
+++ b/arch/arm/mach-lpc32xx/phy3250.c
@@ -263,7 +263,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= lpc32xx_map_io,
 	.init_irq	= lpc32xx_init_irq,
-	.timer		= &lpc32xx_timer,
+	.init_time	= lpc32xx_timer_init,
 	.init_machine	= lpc3250_machine_init,
 	.dt_compat	= lpc32xx_dt_compat,
 	.restart	= lpc23xx_restart,
diff --git a/arch/arm/mach-lpc32xx/timer.c b/arch/arm/mach-lpc32xx/timer.c
index 502b3c6..20eab63 100644
--- a/arch/arm/mach-lpc32xx/timer.c
+++ b/arch/arm/mach-lpc32xx/timer.c
@@ -99,7 +99,7 @@
  * clocks need to be enabled here manually and then tagged as used in
  * the clock driver initialization
  */
-static void __init lpc32xx_timer_init(void)
+void __init lpc32xx_timer_init(void)
 {
 	u32 clkrate, pllreg;
 
@@ -154,8 +154,3 @@
 	clocksource_mmio_init(LPC32XX_TIMER_TC(LPC32XX_TIMER1_BASE),
 		"lpc32xx_clksrc", clkrate, 300, 32, clocksource_mmio_readl_up);
 }
-
-struct sys_timer lpc32xx_timer = {
-	.init		= &lpc32xx_timer_init,
-};
-
diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index e5dba9c..9f64d56 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -262,7 +262,7 @@
 	.map_io		= mmp_map_io,
 	.nr_irqs	= MMP_NR_IRQS,
 	.init_irq       = pxa168_init_irq,
-	.timer          = &pxa168_timer,
+	.init_time	= pxa168_timer_init,
 	.init_machine   = common_init,
 	.restart	= pxa168_restart,
 MACHINE_END
@@ -271,7 +271,7 @@
 	.map_io		= mmp_map_io,
 	.nr_irqs	= MMP_NR_IRQS,
 	.init_irq       = pxa168_init_irq,
-	.timer          = &pxa168_timer,
+	.init_time	= pxa168_timer_init,
 	.init_machine   = common_init,
 	.restart	= pxa168_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/avengers_lite.c b/arch/arm/mach-mmp/avengers_lite.c
index 603542a..1f94957 100644
--- a/arch/arm/mach-mmp/avengers_lite.c
+++ b/arch/arm/mach-mmp/avengers_lite.c
@@ -45,7 +45,7 @@
 	.map_io		= mmp_map_io,
 	.nr_irqs	= MMP_NR_IRQS,
 	.init_irq       = pxa168_init_irq,
-	.timer          = &pxa168_timer,
+	.init_time	= pxa168_timer_init,
 	.init_machine   = avengers_lite_init,
 	.restart	= pxa168_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/brownstone.c b/arch/arm/mach-mmp/brownstone.c
index 5cb769c..2358011 100644
--- a/arch/arm/mach-mmp/brownstone.c
+++ b/arch/arm/mach-mmp/brownstone.c
@@ -218,7 +218,7 @@
 	.map_io		= mmp_map_io,
 	.nr_irqs	= BROWNSTONE_NR_IRQS,
 	.init_irq	= mmp2_init_irq,
-	.timer		= &mmp2_timer,
+	.init_time	= mmp2_timer_init,
 	.init_machine	= brownstone_init,
 	.restart	= mmp_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/common.h b/arch/arm/mach-mmp/common.h
index bd45327..0bdc50b 100644
--- a/arch/arm/mach-mmp/common.h
+++ b/arch/arm/mach-mmp/common.h
@@ -1,7 +1,5 @@
 #define ARRAY_AND_SIZE(x)	(x), ARRAY_SIZE(x)
 
-struct sys_timer;
-
 extern void timer_init(int irq);
 
 extern void __init icu_init_irq(void);
diff --git a/arch/arm/mach-mmp/flint.c b/arch/arm/mach-mmp/flint.c
index 8059cc0..754c352 100644
--- a/arch/arm/mach-mmp/flint.c
+++ b/arch/arm/mach-mmp/flint.c
@@ -121,7 +121,7 @@
 	.map_io		= mmp_map_io,
 	.nr_irqs	= FLINT_NR_IRQS,
 	.init_irq       = mmp2_init_irq,
-	.timer          = &mmp2_timer,
+	.init_time	= mmp2_timer_init,
 	.init_machine   = flint_init,
 	.restart	= mmp_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/gplugd.c b/arch/arm/mach-mmp/gplugd.c
index 5c3d61e..d1e2d59 100644
--- a/arch/arm/mach-mmp/gplugd.c
+++ b/arch/arm/mach-mmp/gplugd.c
@@ -194,7 +194,7 @@
 	.map_io		= mmp_map_io,
 	.nr_irqs	= MMP_NR_IRQS,
 	.init_irq       = pxa168_init_irq,
-	.timer          = &pxa168_timer,
+	.init_time	= pxa168_timer_init,
 	.init_machine   = gplugd_init,
 	.restart	= pxa168_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/include/mach/mmp2.h b/arch/arm/mach-mmp/include/mach/mmp2.h
index c4ca4d1..0764f4e 100644
--- a/arch/arm/mach-mmp/include/mach/mmp2.h
+++ b/arch/arm/mach-mmp/include/mach/mmp2.h
@@ -3,9 +3,7 @@
 
 #include <linux/platform_data/pxa_sdhci.h>
 
-struct sys_timer;
-
-extern struct sys_timer mmp2_timer;
+extern void mmp2_timer_init(void);
 extern void __init mmp2_init_icu(void);
 extern void __init mmp2_init_irq(void);
 extern void mmp2_clear_pmic_int(void);
diff --git a/arch/arm/mach-mmp/include/mach/pxa168.h b/arch/arm/mach-mmp/include/mach/pxa168.h
index 37632d9..7ed1df2 100644
--- a/arch/arm/mach-mmp/include/mach/pxa168.h
+++ b/arch/arm/mach-mmp/include/mach/pxa168.h
@@ -1,9 +1,7 @@
 #ifndef __ASM_MACH_PXA168_H
 #define __ASM_MACH_PXA168_H
 
-struct sys_timer;
-
-extern struct sys_timer pxa168_timer;
+extern void pxa168_timer_init(void);
 extern void __init pxa168_init_irq(void);
 extern void pxa168_restart(char, const char *);
 extern void pxa168_clear_keypad_wakeup(void);
diff --git a/arch/arm/mach-mmp/include/mach/pxa910.h b/arch/arm/mach-mmp/include/mach/pxa910.h
index 3b58a3b..eff31ab 100644
--- a/arch/arm/mach-mmp/include/mach/pxa910.h
+++ b/arch/arm/mach-mmp/include/mach/pxa910.h
@@ -1,9 +1,7 @@
 #ifndef __ASM_MACH_PXA910_H
 #define __ASM_MACH_PXA910_H
 
-struct sys_timer;
-
-extern struct sys_timer pxa910_timer;
+extern void pxa910_timer_init(void);
 extern void __init pxa910_init_irq(void);
 
 #include <linux/i2c.h>
diff --git a/arch/arm/mach-mmp/jasper.c b/arch/arm/mach-mmp/jasper.c
index ff73249..66634fd 100644
--- a/arch/arm/mach-mmp/jasper.c
+++ b/arch/arm/mach-mmp/jasper.c
@@ -174,7 +174,7 @@
 	.map_io		= mmp_map_io,
 	.nr_irqs	= JASPER_NR_IRQS,
 	.init_irq       = mmp2_init_irq,
-	.timer          = &mmp2_timer,
+	.init_time	= mmp2_timer_init,
 	.init_machine   = jasper_init,
 	.restart	= mmp_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/mmp-dt.c b/arch/arm/mach-mmp/mmp-dt.c
index 033cc31..d063efa 100644
--- a/arch/arm/mach-mmp/mmp-dt.c
+++ b/arch/arm/mach-mmp/mmp-dt.c
@@ -22,10 +22,6 @@
 extern void __init mmp_dt_irq_init(void);
 extern void __init mmp_dt_init_timer(void);
 
-static struct sys_timer mmp_dt_timer = {
-	.init	= mmp_dt_init_timer,
-};
-
 static const struct of_dev_auxdata pxa168_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.0", NULL),
 	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4018000, "pxa2xx-uart.1", NULL),
@@ -69,7 +65,7 @@
 DT_MACHINE_START(PXA168_DT, "Marvell PXA168 (Device Tree Support)")
 	.map_io		= mmp_map_io,
 	.init_irq	= mmp_dt_irq_init,
-	.timer		= &mmp_dt_timer,
+	.init_time	= mmp_dt_init_timer,
 	.init_machine	= pxa168_dt_init,
 	.dt_compat	= mmp_dt_board_compat,
 MACHINE_END
@@ -77,7 +73,7 @@
 DT_MACHINE_START(PXA910_DT, "Marvell PXA910 (Device Tree Support)")
 	.map_io		= mmp_map_io,
 	.init_irq	= mmp_dt_irq_init,
-	.timer		= &mmp_dt_timer,
+	.init_time	= mmp_dt_init_timer,
 	.init_machine	= pxa910_dt_init,
 	.dt_compat	= mmp_dt_board_compat,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/mmp2-dt.c b/arch/arm/mach-mmp/mmp2-dt.c
index 535a5ed..fad431a 100644
--- a/arch/arm/mach-mmp/mmp2-dt.c
+++ b/arch/arm/mach-mmp/mmp2-dt.c
@@ -24,10 +24,6 @@
 extern void __init mmp_dt_irq_init(void);
 extern void __init mmp_dt_init_timer(void);
 
-static struct sys_timer mmp_dt_timer = {
-	.init	= mmp_dt_init_timer,
-};
-
 static const struct of_dev_auxdata mmp2_auxdata_lookup[] __initconst = {
 	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4030000, "pxa2xx-uart.0", NULL),
 	OF_DEV_AUXDATA("mrvl,mmp-uart", 0xd4017000, "pxa2xx-uart.1", NULL),
@@ -54,7 +50,7 @@
 DT_MACHINE_START(MMP2_DT, "Marvell MMP2 (Device Tree Support)")
 	.map_io		= mmp_map_io,
 	.init_irq	= mmp_dt_irq_init,
-	.timer		= &mmp_dt_timer,
+	.init_time	= mmp_dt_init_timer,
 	.init_machine	= mmp2_dt_init,
 	.dt_compat	= mmp2_dt_board_compat,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/mmp2.c b/arch/arm/mach-mmp/mmp2.c
index 3a3768c..d94d114 100644
--- a/arch/arm/mach-mmp/mmp2.c
+++ b/arch/arm/mach-mmp/mmp2.c
@@ -114,7 +114,7 @@
 
 #define APBC_TIMERS	APBC_REG(0x024)
 
-static void __init mmp2_timer_init(void)
+void __init mmp2_timer_init(void)
 {
 	unsigned long clk_rst;
 
@@ -130,10 +130,6 @@
 	timer_init(IRQ_MMP2_TIMER1);
 }
 
-struct sys_timer mmp2_timer = {
-	.init	= mmp2_timer_init,
-};
-
 /* on-chip devices */
 MMP2_DEVICE(uart1, "pxa2xx-uart", 0, UART1, 0xd4030000, 0x30, 4, 5);
 MMP2_DEVICE(uart2, "pxa2xx-uart", 1, UART2, 0xd4017000, 0x30, 20, 21);
diff --git a/arch/arm/mach-mmp/pxa168.c b/arch/arm/mach-mmp/pxa168.c
index b7f074f..9bc7b86 100644
--- a/arch/arm/mach-mmp/pxa168.c
+++ b/arch/arm/mach-mmp/pxa168.c
@@ -67,7 +67,7 @@
 #define TIMER_CLK_RST	(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3))
 #define APBC_TIMERS	APBC_REG(0x34)
 
-static void __init pxa168_timer_init(void)
+void __init pxa168_timer_init(void)
 {
 	/* this is early, we have to initialize the CCU registers by
 	 * ourselves instead of using clk_* API. Clock rate is defined
@@ -81,10 +81,6 @@
 	timer_init(IRQ_PXA168_TIMER1);
 }
 
-struct sys_timer pxa168_timer = {
-	.init	= pxa168_timer_init,
-};
-
 void pxa168_clear_keypad_wakeup(void)
 {
 	uint32_t val;
diff --git a/arch/arm/mach-mmp/pxa910.c b/arch/arm/mach-mmp/pxa910.c
index 8b1e16f..c6a89f1 100644
--- a/arch/arm/mach-mmp/pxa910.c
+++ b/arch/arm/mach-mmp/pxa910.c
@@ -101,7 +101,7 @@
 #define TIMER_CLK_RST	(APBC_APBCLK | APBC_FNCLK | APBC_FNCLKSEL(3))
 #define APBC_TIMERS	APBC_REG(0x34)
 
-static void __init pxa910_timer_init(void)
+void __init pxa910_timer_init(void)
 {
 	/* reset and configure */
 	__raw_writel(APBC_APBCLK | APBC_RST, APBC_TIMERS);
@@ -110,10 +110,6 @@
 	timer_init(IRQ_PXA910_AP1_TIMER1);
 }
 
-struct sys_timer pxa910_timer = {
-	.init	= pxa910_timer_init,
-};
-
 /* on-chip devices */
 
 /* NOTE: there are totally 3 UARTs on PXA910:
diff --git a/arch/arm/mach-mmp/tavorevb.c b/arch/arm/mach-mmp/tavorevb.c
index b28f908..4c127d2 100644
--- a/arch/arm/mach-mmp/tavorevb.c
+++ b/arch/arm/mach-mmp/tavorevb.c
@@ -103,7 +103,7 @@
 	.map_io		= mmp_map_io,
 	.nr_irqs	= MMP_NR_IRQS,
 	.init_irq       = pxa910_init_irq,
-	.timer          = &pxa910_timer,
+	.init_time	= pxa910_timer_init,
 	.init_machine   = tavorevb_init,
 	.restart	= mmp_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c
index dd30ea7..8609967 100644
--- a/arch/arm/mach-mmp/teton_bga.c
+++ b/arch/arm/mach-mmp/teton_bga.c
@@ -86,7 +86,7 @@
 	.map_io		= mmp_map_io,
 	.nr_irqs	= MMP_NR_IRQS,
 	.init_irq       = pxa168_init_irq,
-	.timer          = &pxa168_timer,
+	.init_time	= pxa168_timer_init,
 	.init_machine   = teton_bga_init,
 	.restart	= pxa168_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mmp/ttc_dkb.c b/arch/arm/mach-mmp/ttc_dkb.c
index ce55fd8..6e47490 100644
--- a/arch/arm/mach-mmp/ttc_dkb.c
+++ b/arch/arm/mach-mmp/ttc_dkb.c
@@ -218,7 +218,7 @@
 	.map_io		= mmp_map_io,
 	.nr_irqs	= TTCDKB_NR_IRQS,
 	.init_irq       = pxa910_init_irq,
-	.timer          = &pxa910_timer,
+	.init_time	= pxa910_timer_init,
 	.init_machine   = ttc_dkb_init,
 	.restart	= mmp_restart,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-dt-8660.c b/arch/arm/mach-msm/board-dt-8660.c
index b5b4de2..7dcfc53 100644
--- a/arch/arm/mach-msm/board-dt-8660.c
+++ b/arch/arm/mach-msm/board-dt-8660.c
@@ -11,26 +11,15 @@
  */
 
 #include <linux/init.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
-#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 
 #include <mach/board.h>
 #include "common.h"
 
-static const struct of_device_id msm_dt_gic_match[] __initconst = {
-	{ .compatible = "qcom,msm-8660-qgic", .data = gic_of_init },
-	{}
-};
-
-static void __init msm8x60_init_irq(void)
-{
-	of_irq_init(msm_dt_gic_match);
-}
-
 static void __init msm8x60_init_late(void)
 {
 	smd_debugfs_init();
@@ -55,10 +44,9 @@
 DT_MACHINE_START(MSM_DT, "Qualcomm MSM (Flattened Device Tree)")
 	.smp = smp_ops(msm_smp_ops),
 	.map_io = msm_map_msm8x60_io,
-	.init_irq = msm8x60_init_irq,
-	.handle_irq = gic_handle_irq,
+	.init_irq = irqchip_init,
 	.init_machine = msm8x60_dt_init,
 	.init_late = msm8x60_init_late,
-	.timer = &msm_dt_timer,
+	.init_time	= msm_dt_timer_init,
 	.dt_compat = msm8x60_fluid_match,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-dt-8960.c b/arch/arm/mach-msm/board-dt-8960.c
index 4490edb..7301936 100644
--- a/arch/arm/mach-msm/board-dt-8960.c
+++ b/arch/arm/mach-msm/board-dt-8960.c
@@ -11,24 +11,13 @@
  */
 
 #include <linux/init.h>
-#include <linux/of_irq.h>
+#include <linux/irqchip.h>
 #include <linux/of_platform.h>
 
-#include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 
 #include "common.h"
 
-static const struct of_device_id msm_dt_gic_match[] __initconst = {
-	{ .compatible = "qcom,msm-qgic2", .data = gic_of_init },
-	{ }
-};
-
-static void __init msm_dt_init_irq(void)
-{
-	of_irq_init(msm_dt_gic_match);
-}
-
 static void __init msm_dt_init(void)
 {
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
@@ -42,9 +31,8 @@
 DT_MACHINE_START(MSM8960_DT, "Qualcomm MSM (Flattened Device Tree)")
 	.smp = smp_ops(msm_smp_ops),
 	.map_io = msm_map_msm8960_io,
-	.init_irq = msm_dt_init_irq,
-	.timer = &msm_dt_timer,
+	.init_irq = irqchip_init,
+	.init_time	= msm_dt_timer_init,
 	.init_machine = msm_dt_init,
 	.dt_compat = msm8960_dt_match,
-	.handle_irq = gic_handle_irq,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-halibut.c b/arch/arm/mach-msm/board-halibut.c
index 6ce542e..84d720a 100644
--- a/arch/arm/mach-msm/board-halibut.c
+++ b/arch/arm/mach-msm/board-halibut.c
@@ -106,5 +106,5 @@
 	.init_irq	= halibut_init_irq,
 	.init_machine	= halibut_init,
 	.init_late	= halibut_init_late,
-	.timer		= &msm7x01_timer,
+	.init_time	= msm7x01_timer_init,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-mahimahi.c b/arch/arm/mach-msm/board-mahimahi.c
index df00bc0..30c3496 100644
--- a/arch/arm/mach-msm/board-mahimahi.c
+++ b/arch/arm/mach-msm/board-mahimahi.c
@@ -75,7 +75,7 @@
 	smd_debugfs_init();
 }
 
-extern struct sys_timer msm_timer;
+void msm_timer_init(void);
 
 MACHINE_START(MAHIMAHI, "mahimahi")
 	.atag_offset	= 0x100,
@@ -84,5 +84,5 @@
 	.init_irq	= msm_init_irq,
 	.init_machine	= mahimahi_init,
 	.init_late	= mahimahi_init_late,
-	.timer		= &msm_timer,
+	.init_time	= msm_timer_init,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-msm7x30.c b/arch/arm/mach-msm/board-msm7x30.c
index effa6f4..7bc3f82 100644
--- a/arch/arm/mach-msm/board-msm7x30.c
+++ b/arch/arm/mach-msm/board-msm7x30.c
@@ -131,7 +131,7 @@
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
 	.init_late = msm7x30_init_late,
-	.timer = &msm7x30_timer,
+	.init_time	= msm7x30_timer_init,
 MACHINE_END
 
 MACHINE_START(MSM7X30_FFA, "QCT MSM7X30 FFA")
@@ -142,7 +142,7 @@
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
 	.init_late = msm7x30_init_late,
-	.timer = &msm7x30_timer,
+	.init_time	= msm7x30_timer_init,
 MACHINE_END
 
 MACHINE_START(MSM7X30_FLUID, "QCT MSM7X30 FLUID")
@@ -153,5 +153,5 @@
 	.init_irq = msm7x30_init_irq,
 	.init_machine = msm7x30_init,
 	.init_late = msm7x30_init_late,
-	.timer = &msm7x30_timer,
+	.init_time	= msm7x30_timer_init,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-qsd8x50.c b/arch/arm/mach-msm/board-qsd8x50.c
index 2448fcf..686e794 100644
--- a/arch/arm/mach-msm/board-qsd8x50.c
+++ b/arch/arm/mach-msm/board-qsd8x50.c
@@ -200,7 +200,7 @@
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
 	.init_late = qsd8x50_init_late,
-	.timer = &qsd8x50_timer,
+	.init_time	= qsd8x50_timer_init,
 MACHINE_END
 
 MACHINE_START(QSD8X50A_ST1_5, "QCT QSD8X50A ST1.5")
@@ -209,5 +209,5 @@
 	.init_irq = qsd8x50_init_irq,
 	.init_machine = qsd8x50_init,
 	.init_late = qsd8x50_init_late,
-	.timer = &qsd8x50_timer,
+	.init_time	= qsd8x50_timer_init,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-sapphire.c b/arch/arm/mach-msm/board-sapphire.c
index b7b0fc7..7073011 100644
--- a/arch/arm/mach-msm/board-sapphire.c
+++ b/arch/arm/mach-msm/board-sapphire.c
@@ -53,7 +53,7 @@
 	&msm_device_uart3,
 };
 
-extern struct sys_timer msm_timer;
+void msm_timer_init(void);
 
 static void __init sapphire_init_irq(void)
 {
@@ -113,5 +113,5 @@
 	.init_irq       = sapphire_init_irq,
 	.init_machine   = sapphire_init,
 	.init_late      = sapphire_init_late,
-	.timer          = &msm_timer,
+	.init_time	= msm_timer_init,
 MACHINE_END
diff --git a/arch/arm/mach-msm/board-trout.c b/arch/arm/mach-msm/board-trout.c
index 4ba0800..919bfa3 100644
--- a/arch/arm/mach-msm/board-trout.c
+++ b/arch/arm/mach-msm/board-trout.c
@@ -110,5 +110,5 @@
 	.init_irq	= trout_init_irq,
 	.init_machine	= trout_init,
 	.init_late	= trout_init_late,
-	.timer		= &msm7x01_timer,
+	.init_time	= msm7x01_timer_init,
 MACHINE_END
diff --git a/arch/arm/mach-msm/common.h b/arch/arm/mach-msm/common.h
index 633a7159..ce8215a 100644
--- a/arch/arm/mach-msm/common.h
+++ b/arch/arm/mach-msm/common.h
@@ -12,10 +12,10 @@
 #ifndef __MACH_COMMON_H
 #define __MACH_COMMON_H
 
-extern struct sys_timer msm7x01_timer;
-extern struct sys_timer msm7x30_timer;
-extern struct sys_timer msm_dt_timer;
-extern struct sys_timer qsd8x50_timer;
+extern void msm7x01_timer_init(void);
+extern void msm7x30_timer_init(void);
+extern void msm_dt_timer_init(void);
+extern void qsd8x50_timer_init(void);
 
 extern void msm_map_common_io(void);
 extern void msm_map_msm7x30_io(void);
diff --git a/arch/arm/mach-msm/platsmp.c b/arch/arm/mach-msm/platsmp.c
index 7ed69b69..42932865 100644
--- a/arch/arm/mach-msm/platsmp.c
+++ b/arch/arm/mach-msm/platsmp.c
@@ -15,8 +15,8 @@
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 
-#include <asm/hardware/gic.h>
 #include <asm/cacheflush.h>
 #include <asm/cputype.h>
 #include <asm/mach-types.h>
@@ -115,7 +115,7 @@
 	 * the boot monitor to read the system wide flags register,
 	 * and branch to the address found there.
 	 */
-	gic_raise_softirq(cpumask_of(cpu), 0);
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
@@ -153,8 +153,6 @@
 
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
-
-        set_smp_cross_call(gic_raise_softirq);
 }
 
 static void __init msm_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-msm/timer.c b/arch/arm/mach-msm/timer.c
index b9e7449..2969027 100644
--- a/arch/arm/mach-msm/timer.c
+++ b/arch/arm/mach-msm/timer.c
@@ -25,7 +25,6 @@
 #include <linux/of_irq.h>
 
 #include <asm/mach/time.h>
-#include <asm/hardware/gic.h>
 #include <asm/localtimer.h>
 #include <asm/sched_clock.h>
 
@@ -225,7 +224,7 @@
 	{ },
 };
 
-static void __init msm_dt_timer_init(void)
+void __init msm_dt_timer_init(void)
 {
 	struct device_node *np;
 	u32 freq;
@@ -292,10 +291,6 @@
 
 	msm_timer_init(freq, 32, irq, !!percpu_offset);
 }
-
-struct sys_timer msm_dt_timer = {
-	.init = msm_dt_timer_init
-};
 #endif
 
 static int __init msm_timer_map(phys_addr_t event, phys_addr_t source)
@@ -313,7 +308,7 @@
 	return 0;
 }
 
-static void __init msm7x01_timer_init(void)
+void __init msm7x01_timer_init(void)
 {
 	struct clocksource *cs = &msm_clocksource;
 
@@ -326,28 +321,16 @@
 			false);
 }
 
-struct sys_timer msm7x01_timer = {
-	.init = msm7x01_timer_init
-};
-
-static void __init msm7x30_timer_init(void)
+void __init msm7x30_timer_init(void)
 {
 	if (msm_timer_map(0xc0100004, 0xc0100024))
 		return;
 	msm_timer_init(24576000 / 4, 32, 1, false);
 }
 
-struct sys_timer msm7x30_timer = {
-	.init = msm7x30_timer_init
-};
-
-static void __init qsd8x50_timer_init(void)
+void __init qsd8x50_timer_init(void)
 {
 	if (msm_timer_map(0xAC100000, 0xAC100010))
 		return;
 	msm_timer_init(19200000 / 4, 32, 7, false);
 }
-
-struct sys_timer qsd8x50_timer = {
-	.init = qsd8x50_timer_init
-};
diff --git a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
index ee74ec9..1f2ef98 100644
--- a/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
+++ b/arch/arm/mach-mv78xx0/buffalo-wxl-setup.c
@@ -150,6 +150,6 @@
 	.map_io		= mv78xx0_map_io,
 	.init_early	= mv78xx0_init_early,
 	.init_irq	= mv78xx0_init_irq,
-	.timer		= &mv78xx0_timer,
+	.init_time	= mv78xx0_timer_init,
 	.restart	= mv78xx0_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mv78xx0/common.c b/arch/arm/mach-mv78xx0/common.c
index d0cb485..0efa1449 100644
--- a/arch/arm/mach-mv78xx0/common.c
+++ b/arch/arm/mach-mv78xx0/common.c
@@ -336,16 +336,12 @@
 	orion_time_set_base(TIMER_VIRT_BASE);
 }
 
-static void __init_refok mv78xx0_timer_init(void)
+void __init_refok mv78xx0_timer_init(void)
 {
 	orion_time_init(BRIDGE_VIRT_BASE, BRIDGE_INT_TIMER1_CLR,
 			IRQ_MV78XX0_TIMER_1, get_tclk());
 }
 
-struct sys_timer mv78xx0_timer = {
-	.init = mv78xx0_timer_init,
-};
-
 
 /*****************************************************************************
  * General
diff --git a/arch/arm/mach-mv78xx0/common.h b/arch/arm/mach-mv78xx0/common.h
index 507c767..5e9485b 100644
--- a/arch/arm/mach-mv78xx0/common.h
+++ b/arch/arm/mach-mv78xx0/common.h
@@ -47,7 +47,7 @@
 void mv78xx0_i2c_init(void);
 void mv78xx0_restart(char, const char *);
 
-extern struct sys_timer mv78xx0_timer;
+extern void mv78xx0_timer_init(void);
 
 
 #endif
diff --git a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
index 4d6d48b..4e0f22b 100644
--- a/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
+++ b/arch/arm/mach-mv78xx0/db78x00-bp-setup.c
@@ -98,6 +98,6 @@
 	.map_io		= mv78xx0_map_io,
 	.init_early	= mv78xx0_init_early,
 	.init_irq	= mv78xx0_init_irq,
-	.timer		= &mv78xx0_timer,
+	.init_time	= mv78xx0_timer_init,
 	.restart	= mv78xx0_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
index 9a88270..d2d06f3 100644
--- a/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
+++ b/arch/arm/mach-mv78xx0/rd78x00-masa-setup.c
@@ -83,6 +83,6 @@
 	.map_io		= mv78xx0_map_io,
 	.init_early	= mv78xx0_init_early,
 	.init_irq	= mv78xx0_init_irq,
-	.timer		= &mv78xx0_timer,
+	.init_time	= mv78xx0_timer_init,
 	.restart	= mv78xx0_restart,
 MACHINE_END
diff --git a/arch/arm/mach-mvebu/Makefile b/arch/arm/mach-mvebu/Makefile
index 5dcb369..99df4df 100644
--- a/arch/arm/mach-mvebu/Makefile
+++ b/arch/arm/mach-mvebu/Makefile
@@ -1,6 +1,8 @@
 ccflags-$(CONFIG_ARCH_MULTIPLATFORM) := -I$(srctree)/$(src)/include \
 	-I$(srctree)/arch/arm/plat-orion/include
 
+AFLAGS_coherency_ll.o		:= -Wa,-march=armv7-a
+
 obj-y += system-controller.o
 obj-$(CONFIG_MACH_ARMADA_370_XP) += armada-370-xp.o irq-armada-370-xp.o addr-map.o coherency.o coherency_ll.o pmsu.o
 obj-$(CONFIG_SMP)                += platsmp.o headsmp.o
diff --git a/arch/arm/mach-mvebu/armada-370-xp.c b/arch/arm/mach-mvebu/armada-370-xp.c
index 7434b5e..a5ea616d 100644
--- a/arch/arm/mach-mvebu/armada-370-xp.c
+++ b/arch/arm/mach-mvebu/armada-370-xp.c
@@ -56,10 +56,6 @@
 	init_dma_coherent_pool_size(SZ_1M);
 }
 
-struct sys_timer armada_370_xp_timer = {
-	.init		= armada_370_xp_timer_and_clk_init,
-};
-
 static void __init armada_370_xp_dt_init(void)
 {
 	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
@@ -78,7 +74,7 @@
 	.init_early	= armada_370_xp_init_early,
 	.init_irq	= armada_370_xp_init_irq,
 	.handle_irq     = armada_370_xp_handle_irq,
-	.timer		= &armada_370_xp_timer,
+	.init_time	= armada_370_xp_timer_and_clk_init,
 	.restart	= mvebu_restart,
 	.dt_compat	= armada_370_xp_dt_compat,
 MACHINE_END
diff --git a/arch/arm/mach-mxs/mach-mxs.c b/arch/arm/mach-mxs/mach-mxs.c
index c66129b..5fad7ce 100644
--- a/arch/arm/mach-mxs/mach-mxs.c
+++ b/arch/arm/mach-mxs/mach-mxs.c
@@ -163,19 +163,11 @@
 	mx23_clocks_init();
 }
 
-static struct sys_timer imx23_timer = {
-	.init = imx23_timer_init,
-};
-
 static void __init imx28_timer_init(void)
 {
 	mx28_clocks_init();
 }
 
-static struct sys_timer imx28_timer = {
-	.init = imx28_timer_init,
-};
-
 enum mac_oui {
 	OUI_FSL,
 	OUI_DENX,
@@ -446,7 +438,7 @@
 	.map_io		= mx23_map_io,
 	.init_irq	= icoll_init_irq,
 	.handle_irq	= icoll_handle_irq,
-	.timer		= &imx23_timer,
+	.init_time	= imx23_timer_init,
 	.init_machine	= mxs_machine_init,
 	.dt_compat	= imx23_dt_compat,
 	.restart	= mxs_restart,
@@ -456,7 +448,7 @@
 	.map_io		= mx28_map_io,
 	.init_irq	= icoll_init_irq,
 	.handle_irq	= icoll_handle_irq,
-	.timer		= &imx28_timer,
+	.init_time	= imx28_timer_init,
 	.init_machine	= mxs_machine_init,
 	.dt_compat	= imx28_dt_compat,
 	.restart	= mxs_restart,
diff --git a/arch/arm/mach-netx/generic.c b/arch/arm/mach-netx/generic.c
index aa62746..27c2cb7 100644
--- a/arch/arm/mach-netx/generic.c
+++ b/arch/arm/mach-netx/generic.c
@@ -23,9 +23,9 @@
 #include <linux/module.h>
 #include <linux/platform_device.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-vic.h>
 #include <mach/hardware.h>
 #include <asm/mach/map.h>
-#include <asm/hardware/vic.h>
 #include <mach/netx-regs.h>
 #include <asm/mach/irq.h>
 
diff --git a/arch/arm/mach-netx/generic.h b/arch/arm/mach-netx/generic.h
index 9b91511..768b26b 100644
--- a/arch/arm/mach-netx/generic.h
+++ b/arch/arm/mach-netx/generic.h
@@ -21,5 +21,4 @@
 extern void __init netx_init_irq(void);
 extern void netx_restart(char, const char *);
 
-struct sys_timer;
-extern struct sys_timer netx_timer;
+extern void netx_timer_init(void);
diff --git a/arch/arm/mach-netx/nxdb500.c b/arch/arm/mach-netx/nxdb500.c
index 8b781ff..9b558eb 100644
--- a/arch/arm/mach-netx/nxdb500.c
+++ b/arch/arm/mach-netx/nxdb500.c
@@ -28,7 +28,6 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/hardware/vic.h>
 #include <mach/netx-regs.h>
 #include <linux/platform_data/eth-netx.h>
 
@@ -204,8 +203,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &netx_timer,
+	.init_time	= netx_timer_init,
 	.init_machine	= nxdb500_init,
 	.restart	= netx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-netx/nxdkn.c b/arch/arm/mach-netx/nxdkn.c
index b26dbce..a5e86cd 100644
--- a/arch/arm/mach-netx/nxdkn.c
+++ b/arch/arm/mach-netx/nxdkn.c
@@ -28,7 +28,6 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/hardware/vic.h>
 #include <mach/netx-regs.h>
 #include <linux/platform_data/eth-netx.h>
 
@@ -97,8 +96,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &netx_timer,
+	.init_time	= netx_timer_init,
 	.init_machine	= nxdkn_init,
 	.restart	= netx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-netx/nxeb500hmi.c b/arch/arm/mach-netx/nxeb500hmi.c
index 257382e..ad17885 100644
--- a/arch/arm/mach-netx/nxeb500hmi.c
+++ b/arch/arm/mach-netx/nxeb500hmi.c
@@ -28,7 +28,6 @@
 #include <mach/hardware.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/hardware/vic.h>
 #include <mach/netx-regs.h>
 #include <linux/platform_data/eth-netx.h>
 
@@ -181,8 +180,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= netx_map_io,
 	.init_irq	= netx_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &netx_timer,
+	.init_time	= netx_timer_init,
 	.init_machine	= nxeb500hmi_init,
 	.restart	= netx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-netx/time.c b/arch/arm/mach-netx/time.c
index d780a93..6df42e6 100644
--- a/arch/arm/mach-netx/time.c
+++ b/arch/arm/mach-netx/time.c
@@ -106,7 +106,7 @@
 /*
  * Set up timer interrupt
  */
-static void __init netx_timer_init(void)
+void __init netx_timer_init(void)
 {
 	/* disable timer initially */
 	writel(0, NETX_GPIO_COUNTER_CTRL(0));
@@ -145,7 +145,3 @@
 	clockevents_config_and_register(&netx_clockevent, CLOCK_TICK_RATE,
 					0xa00, 0xfffffffe);
 }
-
-struct sys_timer netx_timer = {
-	.init		= netx_timer_init,
-};
diff --git a/arch/arm/mach-nomadik/board-nhk8815.c b/arch/arm/mach-nomadik/board-nhk8815.c
index 9f19069..aaed48d 100644
--- a/arch/arm/mach-nomadik/board-nhk8815.c
+++ b/arch/arm/mach-nomadik/board-nhk8815.c
@@ -27,7 +27,6 @@
 #include <linux/pinctrl/machine.h>
 #include <linux/platform_data/pinctrl-nomadik.h>
 #include <linux/platform_data/clocksource-nomadik-mtu.h>
-#include <asm/hardware/vic.h>
 #include <asm/sizes.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -267,10 +266,6 @@
 	nmdk_timer_init(io_p2v(NOMADIK_MTU0_BASE), IRQ_MTU0);
 }
 
-static struct sys_timer nomadik_timer = {
-	.init	= nomadik_timer_init,
-};
-
 static struct i2c_board_info __initdata nhk8815_i2c0_devices[] = {
 	{
 		I2C_BOARD_INFO("stw4811", 0x2d),
@@ -352,8 +347,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= cpu8815_map_io,
 	.init_irq	= cpu8815_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &nomadik_timer,
+	.init_time	= nomadik_timer_init,
 	.init_machine	= nhk8815_platform_init,
 	.restart	= cpu8815_restart,
 MACHINE_END
diff --git a/arch/arm/mach-nomadik/cpu-8815.c b/arch/arm/mach-nomadik/cpu-8815.c
index 1273931..35140467 100644
--- a/arch/arm/mach-nomadik/cpu-8815.c
+++ b/arch/arm/mach-nomadik/cpu-8815.c
@@ -25,13 +25,13 @@
 #include <linux/slab.h>
 #include <linux/irq.h>
 #include <linux/dma-mapping.h>
+#include <linux/irqchip/arm-vic.h>
 #include <linux/platform_data/clk-nomadik.h>
 #include <linux/platform_data/pinctrl-nomadik.h>
 
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <asm/mach/map.h>
-#include <asm/hardware/vic.h>
 
 #include <asm/cacheflush.h>
 #include <asm/hardware/cache-l2x0.h>
diff --git a/arch/arm/mach-omap1/board-ams-delta.c b/arch/arm/mach-omap1/board-ams-delta.c
index 2e98a3a..2aab761 100644
--- a/arch/arm/mach-omap1/board-ams-delta.c
+++ b/arch/arm/mach-omap1/board-ams-delta.c
@@ -628,6 +628,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= ams_delta_init,
 	.init_late	= ams_delta_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-fsample.c b/arch/arm/mach-omap1/board-fsample.c
index 560a7dc..702d580 100644
--- a/arch/arm/mach-omap1/board-fsample.c
+++ b/arch/arm/mach-omap1/board-fsample.c
@@ -364,6 +364,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_fsample_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-generic.c b/arch/arm/mach-omap1/board-generic.c
index 608e7d2..e1d9171 100644
--- a/arch/arm/mach-omap1/board-generic.c
+++ b/arch/arm/mach-omap1/board-generic.c
@@ -84,6 +84,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_generic_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h2.c b/arch/arm/mach-omap1/board-h2.c
index 2274bd6..0dac3d2 100644
--- a/arch/arm/mach-omap1/board-h2.c
+++ b/arch/arm/mach-omap1/board-h2.c
@@ -461,6 +461,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= h2_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-h3.c b/arch/arm/mach-omap1/board-h3.c
index 1051935..816ecd1 100644
--- a/arch/arm/mach-omap1/board-h3.c
+++ b/arch/arm/mach-omap1/board-h3.c
@@ -454,6 +454,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= h3_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-htcherald.c b/arch/arm/mach-omap1/board-htcherald.c
index 356f816..35a2379 100644
--- a/arch/arm/mach-omap1/board-htcherald.c
+++ b/arch/arm/mach-omap1/board-htcherald.c
@@ -603,6 +603,6 @@
 	.init_irq       = omap1_init_irq,
 	.init_machine   = htcherald_init,
 	.init_late	= omap1_init_late,
-	.timer          = &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-innovator.c b/arch/arm/mach-omap1/board-innovator.c
index f8033fa..bd5f02e 100644
--- a/arch/arm/mach-omap1/board-innovator.c
+++ b/arch/arm/mach-omap1/board-innovator.c
@@ -458,6 +458,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= innovator_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-nokia770.c b/arch/arm/mach-omap1/board-nokia770.c
index 24d2f2d..4695ca7 100644
--- a/arch/arm/mach-omap1/board-nokia770.c
+++ b/arch/arm/mach-omap1/board-nokia770.c
@@ -242,6 +242,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_nokia770_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-osk.c b/arch/arm/mach-omap1/board-osk.c
index 872ea47..a7ce692 100644
--- a/arch/arm/mach-omap1/board-osk.c
+++ b/arch/arm/mach-omap1/board-osk.c
@@ -609,6 +609,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= osk_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmte.c b/arch/arm/mach-omap1/board-palmte.c
index c33dceb..845a1a7 100644
--- a/arch/arm/mach-omap1/board-palmte.c
+++ b/arch/arm/mach-omap1/board-palmte.c
@@ -268,6 +268,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmte_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmtt.c b/arch/arm/mach-omap1/board-palmtt.c
index 2948b0e..65a4a3e 100644
--- a/arch/arm/mach-omap1/board-palmtt.c
+++ b/arch/arm/mach-omap1/board-palmtt.c
@@ -314,6 +314,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmtt_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-palmz71.c b/arch/arm/mach-omap1/board-palmz71.c
index 7a05895..01c9700 100644
--- a/arch/arm/mach-omap1/board-palmz71.c
+++ b/arch/arm/mach-omap1/board-palmz71.c
@@ -330,6 +330,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_palmz71_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-perseus2.c b/arch/arm/mach-omap1/board-perseus2.c
index 27f8d12..8b2f712 100644
--- a/arch/arm/mach-omap1/board-perseus2.c
+++ b/arch/arm/mach-omap1/board-perseus2.c
@@ -326,6 +326,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_perseus2_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-sx1.c b/arch/arm/mach-omap1/board-sx1.c
index 20ed52a..9732a98 100644
--- a/arch/arm/mach-omap1/board-sx1.c
+++ b/arch/arm/mach-omap1/board-sx1.c
@@ -407,6 +407,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= omap_sx1_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= omap1_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/board-voiceblue.c b/arch/arm/mach-omap1/board-voiceblue.c
index abf705f..6c116e1 100644
--- a/arch/arm/mach-omap1/board-voiceblue.c
+++ b/arch/arm/mach-omap1/board-voiceblue.c
@@ -289,6 +289,6 @@
 	.init_irq	= omap1_init_irq,
 	.init_machine	= voiceblue_init,
 	.init_late	= omap1_init_late,
-	.timer		= &omap1_timer,
+	.init_time	= omap1_timer_init,
 	.restart	= voiceblue_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap1/common.h b/arch/arm/mach-omap1/common.h
index b53e085..fb18831 100644
--- a/arch/arm/mach-omap1/common.h
+++ b/arch/arm/mach-omap1/common.h
@@ -75,7 +75,7 @@
 extern void omap1_nand_cmd_ctl(struct mtd_info *mtd, int cmd,
 			       unsigned int ctrl);
 
-extern struct sys_timer omap1_timer;
+extern void omap1_timer_init(void);
 #ifdef CONFIG_OMAP_32K_TIMER
 extern int omap_32k_timer_init(void);
 #else
diff --git a/arch/arm/mach-omap1/time.c b/arch/arm/mach-omap1/time.c
index 5b7c556..726ec23 100644
--- a/arch/arm/mach-omap1/time.c
+++ b/arch/arm/mach-omap1/time.c
@@ -229,12 +229,8 @@
  * Timer initialization
  * ---------------------------------------------------------------------------
  */
-static void __init omap1_timer_init(void)
+void __init omap1_timer_init(void)
 {
 	if (omap_32k_timer_init() != 0)
 		omap_mpu_timer_init();
 }
-
-struct sys_timer omap1_timer = {
-	.init		= omap1_timer_init,
-};
diff --git a/arch/arm/mach-omap2/am35xx-emac.c b/arch/arm/mach-omap2/am35xx-emac.c
index af11dcd..a00d391 100644
--- a/arch/arm/mach-omap2/am35xx-emac.c
+++ b/arch/arm/mach-omap2/am35xx-emac.c
@@ -63,7 +63,7 @@
 	struct platform_device *pdev;
 
 	pdev = omap_device_build(oh->class->name, 0, oh, pdata, pdata_len,
-				 NULL, 0, false);
+				 false);
 	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n",
 		     oh->class->name, oh->name);
diff --git a/arch/arm/mach-omap2/board-2430sdp.c b/arch/arm/mach-omap2/board-2430sdp.c
index 4815ea6..5f41396 100644
--- a/arch/arm/mach-omap2/board-2430sdp.c
+++ b/arch/arm/mach-omap2/board-2430sdp.c
@@ -284,6 +284,6 @@
 	.handle_irq	= omap2_intc_handle_irq,
 	.init_machine	= omap_2430sdp_init,
 	.init_late	= omap2430_init_late,
-	.timer		= &omap2_timer,
+	.init_time	= omap2_sync32k_timer_init,
 	.restart	= omap2xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-3430sdp.c b/arch/arm/mach-omap2/board-3430sdp.c
index bb73afc..8e2513f6 100644
--- a/arch/arm/mach-omap2/board-3430sdp.c
+++ b/arch/arm/mach-omap2/board-3430sdp.c
@@ -597,6 +597,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_3430sdp_init,
 	.init_late	= omap3430_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-3630sdp.c b/arch/arm/mach-omap2/board-3630sdp.c
index 050aaa7..3384627 100644
--- a/arch/arm/mach-omap2/board-3630sdp.c
+++ b/arch/arm/mach-omap2/board-3630sdp.c
@@ -211,6 +211,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_sdp_init,
 	.init_late	= omap3630_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-4430sdp.c b/arch/arm/mach-omap2/board-4430sdp.c
index 1cc6696..f8eeef4 100644
--- a/arch/arm/mach-omap2/board-4430sdp.c
+++ b/arch/arm/mach-omap2/board-4430sdp.c
@@ -26,10 +26,10 @@
 #include <linux/regulator/fixed.h>
 #include <linux/leds.h>
 #include <linux/leds_pwm.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/omap4-keypad.h>
 #include <linux/usb/musb.h>
 
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -722,9 +722,8 @@
 	.map_io		= omap4_map_io,
 	.init_early	= omap4430_init_early,
 	.init_irq	= gic_init_irq,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= omap_4430sdp_init,
 	.init_late	= omap4430_init_late,
-	.timer		= &omap4_timer,
+	.init_time	= omap4_local_timer_init,
 	.restart	= omap44xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-am3517crane.c b/arch/arm/mach-omap2/board-am3517crane.c
index 51b96a1..07f0be2 100644
--- a/arch/arm/mach-omap2/board-am3517crane.c
+++ b/arch/arm/mach-omap2/board-am3517crane.c
@@ -92,6 +92,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= am3517_crane_init,
 	.init_late	= am35xx_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-am3517evm.c b/arch/arm/mach-omap2/board-am3517evm.c
index f81a303..6f5b2a0 100644
--- a/arch/arm/mach-omap2/board-am3517evm.c
+++ b/arch/arm/mach-omap2/board-am3517evm.c
@@ -393,6 +393,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= am3517_evm_init,
 	.init_late	= am35xx_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-apollon.c b/arch/arm/mach-omap2/board-apollon.c
index 5d0a61f..3a6ca74 100644
--- a/arch/arm/mach-omap2/board-apollon.c
+++ b/arch/arm/mach-omap2/board-apollon.c
@@ -337,6 +337,6 @@
 	.handle_irq	= omap2_intc_handle_irq,
 	.init_machine	= omap_apollon_init,
 	.init_late	= omap2420_init_late,
-	.timer		= &omap2_timer,
+	.init_time	= omap2_sync32k_timer_init,
 	.restart	= omap2xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-cm-t35.c b/arch/arm/mach-omap2/board-cm-t35.c
index b3102c2..68647c3 100644
--- a/arch/arm/mach-omap2/board-cm-t35.c
+++ b/arch/arm/mach-omap2/board-cm-t35.c
@@ -751,7 +751,7 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= cm_t35_init,
 	.init_late	= omap35xx_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
 
@@ -764,6 +764,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= cm_t3730_init,
 	.init_late     = omap3630_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-cm-t3517.c b/arch/arm/mach-omap2/board-cm-t3517.c
index ebbc2ad..6a9529a 100644
--- a/arch/arm/mach-omap2/board-cm-t3517.c
+++ b/arch/arm/mach-omap2/board-cm-t3517.c
@@ -297,6 +297,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= cm_t3517_init,
 	.init_late	= am35xx_init_late,
-	.timer		= &omap3_gp_timer,
+	.init_time	= omap3_gp_gptimer_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-devkit8000.c b/arch/arm/mach-omap2/board-devkit8000.c
index 12865af..0b1d8f7 100644
--- a/arch/arm/mach-omap2/board-devkit8000.c
+++ b/arch/arm/mach-omap2/board-devkit8000.c
@@ -643,6 +643,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= devkit8000_init,
 	.init_late	= omap35xx_init_late,
-	.timer		= &omap3_secure_timer,
+	.init_time	= omap3_secure_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c
index 53cb380b..2590463 100644
--- a/arch/arm/mach-omap2/board-generic.c
+++ b/arch/arm/mach-omap2/board-generic.c
@@ -16,7 +16,6 @@
 #include <linux/of_platform.h>
 #include <linux/irqdomain.h>
 
-#include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 
 #include "common.h"
@@ -65,7 +64,7 @@
 	.init_irq	= omap_intc_of_init,
 	.handle_irq	= omap2_intc_handle_irq,
 	.init_machine	= omap_generic_init,
-	.timer		= &omap2_timer,
+	.init_time	= omap2_sync32k_timer_init,
 	.dt_compat	= omap242x_boards_compat,
 	.restart	= omap2xxx_restart,
 MACHINE_END
@@ -84,7 +83,7 @@
 	.init_irq	= omap_intc_of_init,
 	.handle_irq	= omap2_intc_handle_irq,
 	.init_machine	= omap_generic_init,
-	.timer		= &omap2_timer,
+	.init_time	= omap2_sync32k_timer_init,
 	.dt_compat	= omap243x_boards_compat,
 	.restart	= omap2xxx_restart,
 MACHINE_END
@@ -103,7 +102,7 @@
 	.init_irq	= omap_intc_of_init,
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_generic_init,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.dt_compat	= omap3_boards_compat,
 	.restart	= omap3xxx_restart,
 MACHINE_END
@@ -120,7 +119,7 @@
 	.init_irq	= omap_intc_of_init,
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_generic_init,
-	.timer		= &omap3_secure_timer,
+	.init_time	= omap3_secure_sync32k_timer_init,
 	.dt_compat	= omap3_gp_boards_compat,
 	.restart	= omap3xxx_restart,
 MACHINE_END
@@ -139,7 +138,7 @@
 	.init_irq	= omap_intc_of_init,
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_generic_init,
-	.timer		= &omap3_am33xx_timer,
+	.init_time	= omap3_am33xx_gptimer_timer_init,
 	.dt_compat	= am33xx_boards_compat,
 MACHINE_END
 #endif
@@ -156,10 +155,9 @@
 	.map_io		= omap4_map_io,
 	.init_early	= omap4430_init_early,
 	.init_irq	= omap_gic_of_init,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= omap_generic_init,
 	.init_late	= omap4430_init_late,
-	.timer		= &omap4_timer,
+	.init_time	= omap4_local_timer_init,
 	.dt_compat	= omap4_boards_compat,
 	.restart	= omap44xx_restart,
 MACHINE_END
@@ -177,9 +175,8 @@
 	.map_io		= omap5_map_io,
 	.init_early	= omap5_init_early,
 	.init_irq	= omap_gic_of_init,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= omap_generic_init,
-	.timer		= &omap5_timer,
+	.init_time	= omap5_realtime_timer_init,
 	.dt_compat	= omap5_boards_compat,
 	.restart	= omap44xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-h4.c b/arch/arm/mach-omap2/board-h4.c
index 3be1311..812c829 100644
--- a/arch/arm/mach-omap2/board-h4.c
+++ b/arch/arm/mach-omap2/board-h4.c
@@ -342,6 +342,6 @@
 	.handle_irq	= omap2_intc_handle_irq,
 	.init_machine	= omap_h4_init,
 	.init_late	= omap2420_init_late,
-	.timer		= &omap2_timer,
+	.init_time	= omap2_sync32k_timer_init,
 	.restart	= omap2xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-igep0020.c b/arch/arm/mach-omap2/board-igep0020.c
index 0f24cb8..5b44764 100644
--- a/arch/arm/mach-omap2/board-igep0020.c
+++ b/arch/arm/mach-omap2/board-igep0020.c
@@ -655,7 +655,7 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= igep_init,
 	.init_late	= omap35xx_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
 
@@ -668,6 +668,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= igep_init,
 	.init_late	= omap35xx_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ldp.c b/arch/arm/mach-omap2/board-ldp.c
index 0869f4f..ff440c0 100644
--- a/arch/arm/mach-omap2/board-ldp.c
+++ b/arch/arm/mach-omap2/board-ldp.c
@@ -435,6 +435,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_ldp_init,
 	.init_late	= omap3430_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-n8x0.c b/arch/arm/mach-omap2/board-n8x0.c
index 0abb30f..f6eeb87 100644
--- a/arch/arm/mach-omap2/board-n8x0.c
+++ b/arch/arm/mach-omap2/board-n8x0.c
@@ -731,7 +731,7 @@
 	.handle_irq	= omap2_intc_handle_irq,
 	.init_machine	= n8x0_init_machine,
 	.init_late	= omap2420_init_late,
-	.timer		= &omap2_timer,
+	.init_time	= omap2_sync32k_timer_init,
 	.restart	= omap2xxx_restart,
 MACHINE_END
 
@@ -744,7 +744,7 @@
 	.handle_irq	= omap2_intc_handle_irq,
 	.init_machine	= n8x0_init_machine,
 	.init_late	= omap2420_init_late,
-	.timer		= &omap2_timer,
+	.init_time	= omap2_sync32k_timer_init,
 	.restart	= omap2xxx_restart,
 MACHINE_END
 
@@ -757,6 +757,6 @@
 	.handle_irq	= omap2_intc_handle_irq,
 	.init_machine	= n8x0_init_machine,
 	.init_late	= omap2420_init_late,
-	.timer		= &omap2_timer,
+	.init_time	= omap2_sync32k_timer_init,
 	.restart	= omap2xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3beagle.c b/arch/arm/mach-omap2/board-omap3beagle.c
index 22c483d..b81b458 100644
--- a/arch/arm/mach-omap2/board-omap3beagle.c
+++ b/arch/arm/mach-omap2/board-omap3beagle.c
@@ -544,6 +544,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap3_beagle_init,
 	.init_late	= omap3_init_late,
-	.timer		= &omap3_secure_timer,
+	.init_time	= omap3_secure_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3evm.c b/arch/arm/mach-omap2/board-omap3evm.c
index 3985f35..f2f636b 100644
--- a/arch/arm/mach-omap2/board-omap3evm.c
+++ b/arch/arm/mach-omap2/board-omap3evm.c
@@ -757,6 +757,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap3_evm_init,
 	.init_late	= omap35xx_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3logic.c b/arch/arm/mach-omap2/board-omap3logic.c
index 2a065ba..0fba43a 100644
--- a/arch/arm/mach-omap2/board-omap3logic.c
+++ b/arch/arm/mach-omap2/board-omap3logic.c
@@ -231,7 +231,7 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap3logic_init,
 	.init_late	= omap35xx_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
 
@@ -244,6 +244,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap3logic_init,
 	.init_late	= omap35xx_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3pandora.c b/arch/arm/mach-omap2/board-omap3pandora.c
index a53a668..12e1816 100644
--- a/arch/arm/mach-omap2/board-omap3pandora.c
+++ b/arch/arm/mach-omap2/board-omap3pandora.c
@@ -618,6 +618,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap3pandora_init,
 	.init_late	= omap35xx_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3stalker.c b/arch/arm/mach-omap2/board-omap3stalker.c
index 53a6cbc..13ee405 100644
--- a/arch/arm/mach-omap2/board-omap3stalker.c
+++ b/arch/arm/mach-omap2/board-omap3stalker.c
@@ -427,6 +427,6 @@
 	.handle_irq		= omap3_intc_handle_irq,
 	.init_machine		= omap3_stalker_init,
 	.init_late		= omap35xx_init_late,
-	.timer			= &omap3_secure_timer,
+	.init_time		= omap3_secure_sync32k_timer_init,
 	.restart		= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap3touchbook.c b/arch/arm/mach-omap2/board-omap3touchbook.c
index 263cb9c..36c455c 100644
--- a/arch/arm/mach-omap2/board-omap3touchbook.c
+++ b/arch/arm/mach-omap2/board-omap3touchbook.c
@@ -386,6 +386,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap3_touchbook_init,
 	.init_late	= omap3430_init_late,
-	.timer		= &omap3_secure_timer,
+	.init_time	= omap3_secure_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-omap4panda.c b/arch/arm/mach-omap2/board-omap4panda.c
index 5c8e9ce..b623179 100644
--- a/arch/arm/mach-omap2/board-omap4panda.c
+++ b/arch/arm/mach-omap2/board-omap4panda.c
@@ -31,9 +31,9 @@
 #include <linux/ti_wilink_st.h>
 #include <linux/usb/musb.h>
 #include <linux/wl12xx.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/omap-abe-twl6040.h>
 
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -397,6 +397,12 @@
 		  OMAP_PULL_ENA),
 	OMAP4_MUX(ABE_MCBSP1_FSX, OMAP_MUX_MODE0 | OMAP_PIN_INPUT),
 
+	/* UART2 - BT/FM/GPS shared transport */
+	OMAP4_MUX(UART2_CTS,	OMAP_PIN_INPUT	| OMAP_MUX_MODE0),
+	OMAP4_MUX(UART2_RTS,	OMAP_PIN_OUTPUT	| OMAP_MUX_MODE0),
+	OMAP4_MUX(UART2_RX,	OMAP_PIN_INPUT	| OMAP_MUX_MODE0),
+	OMAP4_MUX(UART2_TX,	OMAP_PIN_OUTPUT	| OMAP_MUX_MODE0),
+
 	{ .reg_offset = OMAP_MUX_TERMINATOR },
 };
 
@@ -453,9 +459,8 @@
 	.map_io		= omap4_map_io,
 	.init_early	= omap4430_init_early,
 	.init_irq	= gic_init_irq,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= omap4_panda_init,
 	.init_late	= omap4430_init_late,
-	.timer		= &omap4_timer,
+	.init_time	= omap4_local_timer_init,
 	.restart	= omap44xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-overo.c b/arch/arm/mach-omap2/board-overo.c
index c8fde3e..233a37d 100644
--- a/arch/arm/mach-omap2/board-overo.c
+++ b/arch/arm/mach-omap2/board-overo.c
@@ -551,6 +551,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= overo_init,
 	.init_late	= omap35xx_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rm680.c b/arch/arm/mach-omap2/board-rm680.c
index 0c777b7..386a2dd 100644
--- a/arch/arm/mach-omap2/board-rm680.c
+++ b/arch/arm/mach-omap2/board-rm680.c
@@ -147,7 +147,7 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= rm680_init,
 	.init_late	= omap3630_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
 
@@ -160,6 +160,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= rm680_init,
 	.init_late	= omap3630_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-rx51.c b/arch/arm/mach-omap2/board-rx51.c
index d0374ea..f7c4616 100644
--- a/arch/arm/mach-omap2/board-rx51.c
+++ b/arch/arm/mach-omap2/board-rx51.c
@@ -123,6 +123,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= rx51_init,
 	.init_late	= omap3430_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/board-ti8168evm.c b/arch/arm/mach-omap2/board-ti8168evm.c
index 1a3e056..6273c28 100644
--- a/arch/arm/mach-omap2/board-ti8168evm.c
+++ b/arch/arm/mach-omap2/board-ti8168evm.c
@@ -43,7 +43,7 @@
 	.map_io		= ti81xx_map_io,
 	.init_early	= ti81xx_init_early,
 	.init_irq	= ti81xx_init_irq,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.init_machine	= ti81xx_evm_init,
 	.init_late	= ti81xx_init_late,
 	.restart	= omap44xx_restart,
@@ -55,7 +55,7 @@
 	.map_io		= ti81xx_map_io,
 	.init_early	= ti81xx_init_early,
 	.init_irq	= ti81xx_init_irq,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.init_machine	= ti81xx_evm_init,
 	.init_late	= ti81xx_init_late,
 	.restart	= omap44xx_restart,
diff --git a/arch/arm/mach-omap2/board-zoom.c b/arch/arm/mach-omap2/board-zoom.c
index d7fa31e..d257cf1 100644
--- a/arch/arm/mach-omap2/board-zoom.c
+++ b/arch/arm/mach-omap2/board-zoom.c
@@ -137,7 +137,7 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_zoom_init,
 	.init_late	= omap3430_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
 
@@ -150,6 +150,6 @@
 	.handle_irq	= omap3_intc_handle_irq,
 	.init_machine	= omap_zoom_init,
 	.init_late	= omap3630_init_late,
-	.timer		= &omap3_timer,
+	.init_time	= omap3_sync32k_timer_init,
 	.restart	= omap3xxx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-omap2/cclock2420_data.c b/arch/arm/mach-omap2/cclock2420_data.c
index 7e5febe..0f0a97c 100644
--- a/arch/arm/mach-omap2/cclock2420_data.c
+++ b/arch/arm/mach-omap2/cclock2420_data.c
@@ -622,15 +622,10 @@
 
 DEFINE_STRUCT_CLK(gpios_fck, gpios_fck_parent_names, aes_ick_ops);
 
-static struct clk wu_l4_ick;
-
-DEFINE_STRUCT_CLK_HW_OMAP(wu_l4_ick, "wkup_clkdm");
-DEFINE_STRUCT_CLK(wu_l4_ick, dpll_ck_parent_names, core_ck_ops);
-
 static struct clk gpios_ick;
 
 static const char *gpios_ick_parent_names[] = {
-	"wu_l4_ick",
+	"sys_ck",
 };
 
 static struct clk_hw_omap gpios_ick_hw = {
@@ -1682,13 +1677,6 @@
 
 DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops);
 
-static struct clk wdt1_osc_ck;
-
-static const struct clk_ops wdt1_osc_ck_ops = {};
-
-DEFINE_STRUCT_CLK_HW_OMAP(wdt1_osc_ck, NULL);
-DEFINE_STRUCT_CLK(wdt1_osc_ck, sys_ck_parent_names, wdt1_osc_ck_ops);
-
 static struct clk wdt3_fck;
 
 static struct clk_hw_omap wdt3_fck_hw = {
@@ -1767,7 +1755,6 @@
 	CLK(NULL,	"func_96m_ck",	&func_96m_ck,	CK_242X),
 	CLK(NULL,	"func_48m_ck",	&func_48m_ck,	CK_242X),
 	CLK(NULL,	"func_12m_ck",	&func_12m_ck,	CK_242X),
-	CLK(NULL,	"ck_wdt1_osc",	&wdt1_osc_ck,	CK_242X),
 	CLK(NULL,	"sys_clkout_src", &sys_clkout_src, CK_242X),
 	CLK(NULL,	"sys_clkout",	&sys_clkout,	CK_242X),
 	CLK(NULL,	"sys_clkout2_src", &sys_clkout2_src, CK_242X),
@@ -1797,7 +1784,6 @@
 	/* L4 domain clocks */
 	CLK(NULL,	"l4_ck",	&l4_ck,		CK_242X),
 	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_242X),
-	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_242X),
 	/* virtual meta-group clock */
 	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_242X),
 	/* general l4 interface ck, multi-parent functional clk */
@@ -1935,6 +1921,8 @@
 			omap2_init_clk_hw_omap_clocks(c->lk.clk);
 	}
 
+	omap2xxx_clkt_vps_late_init();
+
 	omap2_clk_disable_autoidle_all();
 
 	omap2_clk_enable_init_clocks(enable_init_clks,
diff --git a/arch/arm/mach-omap2/cclock2430_data.c b/arch/arm/mach-omap2/cclock2430_data.c
index eda079b..aed8f74 100644
--- a/arch/arm/mach-omap2/cclock2430_data.c
+++ b/arch/arm/mach-omap2/cclock2430_data.c
@@ -601,15 +601,10 @@
 
 DEFINE_STRUCT_CLK(gpios_fck, gpio5_fck_parent_names, aes_ick_ops);
 
-static struct clk wu_l4_ick;
-
-DEFINE_STRUCT_CLK_HW_OMAP(wu_l4_ick, "wkup_clkdm");
-DEFINE_STRUCT_CLK(wu_l4_ick, dpll_ck_parent_names, core_ck_ops);
-
 static struct clk gpios_ick;
 
 static const char *gpios_ick_parent_names[] = {
-	"wu_l4_ick",
+	"sys_ck",
 };
 
 static struct clk_hw_omap gpios_ick_hw = {
@@ -1811,13 +1806,6 @@
 
 DEFINE_STRUCT_CLK(wdt1_ick, gpios_ick_parent_names, aes_ick_ops);
 
-static struct clk wdt1_osc_ck;
-
-static const struct clk_ops wdt1_osc_ck_ops = {};
-
-DEFINE_STRUCT_CLK_HW_OMAP(wdt1_osc_ck, NULL);
-DEFINE_STRUCT_CLK(wdt1_osc_ck, sys_ck_parent_names, wdt1_osc_ck_ops);
-
 static struct clk wdt4_fck;
 
 static struct clk_hw_omap wdt4_fck_hw = {
@@ -1869,7 +1857,6 @@
 	CLK(NULL,	"func_96m_ck",	&func_96m_ck,	CK_243X),
 	CLK(NULL,	"func_48m_ck",	&func_48m_ck,	CK_243X),
 	CLK(NULL,	"func_12m_ck",	&func_12m_ck,	CK_243X),
-	CLK(NULL,	"ck_wdt1_osc",	&wdt1_osc_ck,	CK_243X),
 	CLK(NULL,	"sys_clkout_src", &sys_clkout_src, CK_243X),
 	CLK(NULL,	"sys_clkout",	&sys_clkout,	CK_243X),
 	CLK(NULL,	"emul_ck",	&emul_ck,	CK_243X),
@@ -1898,7 +1885,6 @@
 	/* L4 domain clocks */
 	CLK(NULL,	"l4_ck",	&l4_ck,		CK_243X),
 	CLK(NULL,	"ssi_l4_ick",	&ssi_l4_ick,	CK_243X),
-	CLK(NULL,	"wu_l4_ick",	&wu_l4_ick,	CK_243X),
 	/* virtual meta-group clock */
 	CLK(NULL,	"virt_prcm_set", &virt_prcm_set, CK_243X),
 	/* general l4 interface ck, multi-parent functional clk */
@@ -2050,6 +2036,8 @@
 			omap2_init_clk_hw_omap_clocks(c->lk.clk);
 	}
 
+	omap2xxx_clkt_vps_late_init();
+
 	omap2_clk_disable_autoidle_all();
 
 	omap2_clk_enable_init_clocks(enable_init_clks,
diff --git a/arch/arm/mach-omap2/cclock44xx_data.c b/arch/arm/mach-omap2/cclock44xx_data.c
index 5789a5e..cebe2b3 100644
--- a/arch/arm/mach-omap2/cclock44xx_data.c
+++ b/arch/arm/mach-omap2/cclock44xx_data.c
@@ -16,6 +16,10 @@
  * XXX Some of the ES1 clocks have been removed/changed; once support
  * is added for discriminating clocks by ES level, these should be added back
  * in.
+ *
+ * XXX All of the remaining MODULEMODE clock nodes should be removed
+ * once the drivers are updated to use pm_runtime or to use the appropriate
+ * upstream clock node for rate/parent selection.
  */
 
 #include <linux/kernel.h>
@@ -315,7 +319,7 @@
 		   OMAP4430_CM_DIV_M2_DPLL_ABE, OMAP4430_DPLL_CLKOUT_DIV_SHIFT,
 		   OMAP4430_DPLL_CLKOUT_DIV_WIDTH, CLK_DIVIDER_ONE_BASED, NULL);
 
-static const struct clk_ops dmic_fck_ops = {
+static const struct clk_ops dpll_hsd_ops = {
 	.enable		= &omap2_dflt_clk_enable,
 	.disable	= &omap2_dflt_clk_disable,
 	.is_enabled	= &omap2_dflt_clk_is_enabled,
@@ -325,6 +329,12 @@
 	.init		= &omap2_init_clk_clkdm,
 };
 
+static const struct clk_ops func_dmic_abe_gfclk_ops = {
+	.recalc_rate	= &omap2_clksel_recalc,
+	.get_parent	= &omap2_clksel_find_parent_index,
+	.set_parent	= &omap2_clksel_set_parent,
+};
+
 static const char *dpll_core_m3x2_ck_parents[] = {
 	"dpll_core_x2_ck",
 };
@@ -340,7 +350,7 @@
 			 OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
 			 OMAP4430_CM_DIV_M3_DPLL_CORE,
 			 OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, NULL,
-			 dpll_core_m3x2_ck_parents, dmic_fck_ops);
+			 dpll_core_m3x2_ck_parents, dpll_hsd_ops);
 
 DEFINE_CLK_OMAP_HSDIVIDER(dpll_core_m7x2_ck, "dpll_core_x2_ck",
 			  &dpll_core_x2_ck, 0x0, OMAP4430_CM_DIV_M7_DPLL_CORE,
@@ -547,7 +557,7 @@
 			 OMAP4430_DPLL_CLKOUTHIF_DIV_MASK,
 			 OMAP4430_CM_DIV_M3_DPLL_PER,
 			 OMAP4430_DPLL_CLKOUTHIF_GATE_CTRL_SHIFT, NULL,
-			 dpll_per_m3x2_ck_parents, dmic_fck_ops);
+			 dpll_per_m3x2_ck_parents, dpll_hsd_ops);
 
 DEFINE_CLK_OMAP_HSDIVIDER(dpll_per_m4x2_ck, "dpll_per_x2_ck", &dpll_per_x2_ck,
 			  0x0, OMAP4430_CM_DIV_M4_DPLL_PER,
@@ -749,10 +759,6 @@
 		OMAP4430_CM_L4SEC_AES2_CLKCTRL,
 		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
 
-DEFINE_CLK_GATE(aess_fck, "aess_fclk", &aess_fclk, 0x0,
-		OMAP4430_CM1_ABE_AESS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
-		0x0, NULL);
-
 DEFINE_CLK_GATE(bandgap_fclk, "sys_32k_ck", &sys_32k_ck, 0x0,
 		OMAP4430_CM_WKUP_BANDGAP_CLKCTRL,
 		OMAP4430_OPTFCLKEN_BGAP_32K_SHIFT, 0x0, NULL);
@@ -774,11 +780,6 @@
 		OMAP4460_OPTFCLKEN_TS_FCLK_SHIFT,
 		0x0, NULL);
 
-DEFINE_CLK_GATE(des3des_fck, "l4_div_ck", &l4_div_ck, 0x0,
-		OMAP4430_CM_L4SEC_DES3DES_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT,
-		0x0, NULL);
-
 static const char *dmic_sync_mux_ck_parents[] = {
 	"abe_24m_fclk", "syc_clk_div_ck", "func_24m_clk",
 };
@@ -795,23 +796,13 @@
 	{ .parent = NULL },
 };
 
-static const char *dmic_fck_parents[] = {
+static const char *func_dmic_abe_gfclk_parents[] = {
 	"dmic_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
 };
 
-/* Merged func_dmic_abe_gfclk into dmic */
-static struct clk dmic_fck;
-
-DEFINE_CLK_OMAP_MUX_GATE(dmic_fck, "abe_clkdm", func_dmic_abe_gfclk_sel,
-			 OMAP4430_CM1_ABE_DMIC_CLKCTRL,
-			 OMAP4430_CLKSEL_SOURCE_MASK,
-			 OMAP4430_CM1_ABE_DMIC_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 dmic_fck_parents, dmic_fck_ops);
-
-DEFINE_CLK_GATE(dsp_fck, "dpll_iva_m4x2_ck", &dpll_iva_m4x2_ck, 0x0,
-		OMAP4430_CM_TESLA_TESLA_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
+DEFINE_CLK_OMAP_MUX(func_dmic_abe_gfclk, "abe_clkdm", func_dmic_abe_gfclk_sel,
+		    OMAP4430_CM1_ABE_DMIC_CLKCTRL, OMAP4430_CLKSEL_SOURCE_MASK,
+		    func_dmic_abe_gfclk_parents, func_dmic_abe_gfclk_ops);
 
 DEFINE_CLK_GATE(dss_sys_clk, "syc_clk_div_ck", &syc_clk_div_ck, 0x0,
 		OMAP4430_CM_DSS_DSS_CLKCTRL,
@@ -833,177 +824,57 @@
 		OMAP4430_CM_DSS_DSS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
 		0x0, NULL);
 
-DEFINE_CLK_GATE(efuse_ctrl_cust_fck, "sys_clkin_ck", &sys_clkin_ck, 0x0,
-		OMAP4430_CM_CEFUSE_CEFUSE_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(emif1_fck, "ddrphy_ck", &ddrphy_ck, 0x0,
-		OMAP4430_CM_MEMIF_EMIF_1_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(emif2_fck, "ddrphy_ck", &ddrphy_ck, 0x0,
-		OMAP4430_CM_MEMIF_EMIF_2_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
 DEFINE_CLK_DIVIDER(fdif_fck, "dpll_per_m4x2_ck", &dpll_per_m4x2_ck, 0x0,
 		   OMAP4430_CM_CAM_FDIF_CLKCTRL, OMAP4430_CLKSEL_FCLK_SHIFT,
 		   OMAP4430_CLKSEL_FCLK_WIDTH, CLK_DIVIDER_POWER_OF_TWO, NULL);
 
-DEFINE_CLK_GATE(fpka_fck, "l4_div_ck", &l4_div_ck, 0x0,
-		OMAP4430_CM_L4SEC_PKAEIP29_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
 DEFINE_CLK_GATE(gpio1_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
 		OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
 		OMAP4430_OPTFCLKEN_DBCLK_SHIFT,	0x0, NULL);
 
-DEFINE_CLK_GATE(gpio1_ick, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck, 0x0,
-		OMAP4430_CM_WKUP_GPIO1_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
 DEFINE_CLK_GATE(gpio2_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
 		OMAP4430_CM_L4PER_GPIO2_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
 		0x0, NULL);
 
-DEFINE_CLK_GATE(gpio2_ick, "l4_div_ck", &l4_div_ck, 0x0,
-		OMAP4430_CM_L4PER_GPIO2_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
 DEFINE_CLK_GATE(gpio3_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
 		OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
 		OMAP4430_OPTFCLKEN_DBCLK_SHIFT, 0x0, NULL);
 
-DEFINE_CLK_GATE(gpio3_ick, "l4_div_ck", &l4_div_ck, 0x0,
-		OMAP4430_CM_L4PER_GPIO3_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
 DEFINE_CLK_GATE(gpio4_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
 		OMAP4430_CM_L4PER_GPIO4_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
 		0x0, NULL);
 
-DEFINE_CLK_GATE(gpio4_ick, "l4_div_ck", &l4_div_ck, 0x0,
-		OMAP4430_CM_L4PER_GPIO4_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
 DEFINE_CLK_GATE(gpio5_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
 		OMAP4430_CM_L4PER_GPIO5_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
 		0x0, NULL);
 
-DEFINE_CLK_GATE(gpio5_ick, "l4_div_ck", &l4_div_ck, 0x0,
-		OMAP4430_CM_L4PER_GPIO5_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
 DEFINE_CLK_GATE(gpio6_dbclk, "sys_32k_ck", &sys_32k_ck, 0x0,
 		OMAP4430_CM_L4PER_GPIO6_CLKCTRL, OMAP4430_OPTFCLKEN_DBCLK_SHIFT,
 		0x0, NULL);
 
-DEFINE_CLK_GATE(gpio6_ick, "l4_div_ck", &l4_div_ck, 0x0,
-		OMAP4430_CM_L4PER_GPIO6_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(gpmc_ick, "l3_div_ck", &l3_div_ck, 0x0,
-		OMAP4430_CM_L3_2_GPMC_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
-		0x0, NULL);
-
 static const struct clksel sgx_clk_mux_sel[] = {
 	{ .parent = &dpll_core_m7x2_ck, .rates = div_1_0_rates },
 	{ .parent = &dpll_per_m7x2_ck, .rates = div_1_1_rates },
 	{ .parent = NULL },
 };
 
-static const char *gpu_fck_parents[] = {
+static const char *sgx_clk_mux_parents[] = {
 	"dpll_core_m7x2_ck", "dpll_per_m7x2_ck",
 };
 
-/* Merged sgx_clk_mux into gpu */
-DEFINE_CLK_OMAP_MUX_GATE(gpu_fck, "l3_gfx_clkdm", sgx_clk_mux_sel,
-			 OMAP4430_CM_GFX_GFX_CLKCTRL,
-			 OMAP4430_CLKSEL_SGX_FCLK_MASK,
-			 OMAP4430_CM_GFX_GFX_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 gpu_fck_parents, dmic_fck_ops);
-
-DEFINE_CLK_GATE(hdq1w_fck, "func_12m_fclk", &func_12m_fclk, 0x0,
-		OMAP4430_CM_L4PER_HDQ1W_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+DEFINE_CLK_OMAP_MUX(sgx_clk_mux, "l3_gfx_clkdm", sgx_clk_mux_sel,
+		    OMAP4430_CM_GFX_GFX_CLKCTRL, OMAP4430_CLKSEL_SGX_FCLK_MASK,
+		    sgx_clk_mux_parents, func_dmic_abe_gfclk_ops);
 
 DEFINE_CLK_DIVIDER(hsi_fck, "dpll_per_m2x2_ck", &dpll_per_m2x2_ck, 0x0,
 		   OMAP4430_CM_L3INIT_HSI_CLKCTRL, OMAP4430_CLKSEL_24_25_SHIFT,
 		   OMAP4430_CLKSEL_24_25_WIDTH, CLK_DIVIDER_POWER_OF_TWO,
 		   NULL);
 
-DEFINE_CLK_GATE(i2c1_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
-		OMAP4430_CM_L4PER_I2C1_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(i2c2_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
-		OMAP4430_CM_L4PER_I2C2_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(i2c3_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
-		OMAP4430_CM_L4PER_I2C3_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(i2c4_fck, "func_96m_fclk", &func_96m_fclk, 0x0,
-		OMAP4430_CM_L4PER_I2C4_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(ipu_fck, "ducati_clk_mux_ck", &ducati_clk_mux_ck, 0x0,
-		OMAP4430_CM_DUCATI_DUCATI_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
 DEFINE_CLK_GATE(iss_ctrlclk, "func_96m_fclk", &func_96m_fclk, 0x0,
 		OMAP4430_CM_CAM_ISS_CLKCTRL, OMAP4430_OPTFCLKEN_CTRLCLK_SHIFT,
 		0x0, NULL);
 
-DEFINE_CLK_GATE(iss_fck, "ducati_clk_mux_ck", &ducati_clk_mux_ck, 0x0,
-		OMAP4430_CM_CAM_ISS_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
-		0x0, NULL);
-
-DEFINE_CLK_GATE(iva_fck, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, 0x0,
-		OMAP4430_CM_IVAHD_IVAHD_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(kbd_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
-		OMAP4430_CM_WKUP_KEYBOARD_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-static struct clk l3_instr_ick;
-
-static const char *l3_instr_ick_parent_names[] = {
-	"l3_div_ck",
-};
-
-static const struct clk_ops l3_instr_ick_ops = {
-	.enable		= &omap2_dflt_clk_enable,
-	.disable	= &omap2_dflt_clk_disable,
-	.is_enabled	= &omap2_dflt_clk_is_enabled,
-	.init		= &omap2_init_clk_clkdm,
-};
-
-static struct clk_hw_omap l3_instr_ick_hw = {
-	.hw = {
-		.clk = &l3_instr_ick,
-	},
-	.enable_reg	= OMAP4430_CM_L3INSTR_L3_INSTR_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL_SHIFT,
-	.clkdm_name	= "l3_instr_clkdm",
-};
-
-DEFINE_STRUCT_CLK(l3_instr_ick, l3_instr_ick_parent_names, l3_instr_ick_ops);
-
-static struct clk l3_main_3_ick;
-static struct clk_hw_omap l3_main_3_ick_hw = {
-	.hw = {
-		.clk = &l3_main_3_ick,
-	},
-	.enable_reg	= OMAP4430_CM_L3INSTR_L3_3_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL_SHIFT,
-	.clkdm_name	= "l3_instr_clkdm",
-};
-
-DEFINE_STRUCT_CLK(l3_main_3_ick, l3_instr_ick_parent_names, l3_instr_ick_ops);
-
 DEFINE_CLK_MUX(mcasp_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
 	       OMAP4430_CM1_ABE_MCASP_CLKCTRL,
 	       OMAP4430_CLKSEL_INTERNAL_SOURCE_SHIFT,
@@ -1016,17 +887,13 @@
 	{ .parent = NULL },
 };
 
-static const char *mcasp_fck_parents[] = {
+static const char *func_mcasp_abe_gfclk_parents[] = {
 	"mcasp_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
 };
 
-/* Merged func_mcasp_abe_gfclk into mcasp */
-DEFINE_CLK_OMAP_MUX_GATE(mcasp_fck, "abe_clkdm", func_mcasp_abe_gfclk_sel,
-			 OMAP4430_CM1_ABE_MCASP_CLKCTRL,
-			 OMAP4430_CLKSEL_SOURCE_MASK,
-			 OMAP4430_CM1_ABE_MCASP_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 mcasp_fck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(func_mcasp_abe_gfclk, "abe_clkdm", func_mcasp_abe_gfclk_sel,
+		    OMAP4430_CM1_ABE_MCASP_CLKCTRL, OMAP4430_CLKSEL_SOURCE_MASK,
+		    func_mcasp_abe_gfclk_parents, func_dmic_abe_gfclk_ops);
 
 DEFINE_CLK_MUX(mcbsp1_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
 	       OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
@@ -1040,17 +907,14 @@
 	{ .parent = NULL },
 };
 
-static const char *mcbsp1_fck_parents[] = {
+static const char *func_mcbsp1_gfclk_parents[] = {
 	"mcbsp1_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
 };
 
-/* Merged func_mcbsp1_gfclk into mcbsp1 */
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp1_fck, "abe_clkdm", func_mcbsp1_gfclk_sel,
-			 OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
-			 OMAP4430_CLKSEL_SOURCE_MASK,
-			 OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 mcbsp1_fck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(func_mcbsp1_gfclk, "abe_clkdm", func_mcbsp1_gfclk_sel,
+		    OMAP4430_CM1_ABE_MCBSP1_CLKCTRL,
+		    OMAP4430_CLKSEL_SOURCE_MASK, func_mcbsp1_gfclk_parents,
+		    func_dmic_abe_gfclk_ops);
 
 DEFINE_CLK_MUX(mcbsp2_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
 	       OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
@@ -1064,17 +928,14 @@
 	{ .parent = NULL },
 };
 
-static const char *mcbsp2_fck_parents[] = {
+static const char *func_mcbsp2_gfclk_parents[] = {
 	"mcbsp2_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
 };
 
-/* Merged func_mcbsp2_gfclk into mcbsp2 */
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp2_fck, "abe_clkdm", func_mcbsp2_gfclk_sel,
-			 OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
-			 OMAP4430_CLKSEL_SOURCE_MASK,
-			 OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 mcbsp2_fck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(func_mcbsp2_gfclk, "abe_clkdm", func_mcbsp2_gfclk_sel,
+		    OMAP4430_CM1_ABE_MCBSP2_CLKCTRL,
+		    OMAP4430_CLKSEL_SOURCE_MASK, func_mcbsp2_gfclk_parents,
+		    func_dmic_abe_gfclk_ops);
 
 DEFINE_CLK_MUX(mcbsp3_sync_mux_ck, dmic_sync_mux_ck_parents, NULL, 0x0,
 	       OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
@@ -1088,17 +949,14 @@
 	{ .parent = NULL },
 };
 
-static const char *mcbsp3_fck_parents[] = {
+static const char *func_mcbsp3_gfclk_parents[] = {
 	"mcbsp3_sync_mux_ck", "pad_clks_ck", "slimbus_clk",
 };
 
-/* Merged func_mcbsp3_gfclk into mcbsp3 */
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp3_fck, "abe_clkdm", func_mcbsp3_gfclk_sel,
-			 OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
-			 OMAP4430_CLKSEL_SOURCE_MASK,
-			 OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 mcbsp3_fck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(func_mcbsp3_gfclk, "abe_clkdm", func_mcbsp3_gfclk_sel,
+		    OMAP4430_CM1_ABE_MCBSP3_CLKCTRL,
+		    OMAP4430_CLKSEL_SOURCE_MASK, func_mcbsp3_gfclk_parents,
+		    func_dmic_abe_gfclk_ops);
 
 static const char *mcbsp4_sync_mux_ck_parents[] = {
 	"func_96m_fclk", "per_abe_nc_fclk",
@@ -1115,37 +973,14 @@
 	{ .parent = NULL },
 };
 
-static const char *mcbsp4_fck_parents[] = {
+static const char *per_mcbsp4_gfclk_parents[] = {
 	"mcbsp4_sync_mux_ck", "pad_clks_ck",
 };
 
-/* Merged per_mcbsp4_gfclk into mcbsp4 */
-DEFINE_CLK_OMAP_MUX_GATE(mcbsp4_fck, "l4_per_clkdm", per_mcbsp4_gfclk_sel,
-			 OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
-			 OMAP4430_CLKSEL_SOURCE_24_24_MASK,
-			 OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 mcbsp4_fck_parents, dmic_fck_ops);
-
-DEFINE_CLK_GATE(mcpdm_fck, "pad_clks_ck", &pad_clks_ck, 0x0,
-		OMAP4430_CM1_ABE_PDM_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
-		0x0, NULL);
-
-DEFINE_CLK_GATE(mcspi1_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_MCSPI1_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(mcspi2_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_MCSPI2_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(mcspi3_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_MCSPI3_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(mcspi4_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_MCSPI4_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+DEFINE_CLK_OMAP_MUX(per_mcbsp4_gfclk, "l4_per_clkdm", per_mcbsp4_gfclk_sel,
+		    OMAP4430_CM_L4PER_MCBSP4_CLKCTRL,
+		    OMAP4430_CLKSEL_SOURCE_24_24_MASK, per_mcbsp4_gfclk_parents,
+		    func_dmic_abe_gfclk_ops);
 
 static const struct clksel hsmmc1_fclk_sel[] = {
 	{ .parent = &func_64m_fclk, .rates = div_1_0_rates },
@@ -1153,69 +988,22 @@
 	{ .parent = NULL },
 };
 
-static const char *mmc1_fck_parents[] = {
+static const char *hsmmc1_fclk_parents[] = {
 	"func_64m_fclk", "func_96m_fclk",
 };
 
-/* Merged hsmmc1_fclk into mmc1 */
-DEFINE_CLK_OMAP_MUX_GATE(mmc1_fck, "l3_init_clkdm", hsmmc1_fclk_sel,
-			 OMAP4430_CM_L3INIT_MMC1_CLKCTRL, OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM_L3INIT_MMC1_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 mmc1_fck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(hsmmc1_fclk, "l3_init_clkdm", hsmmc1_fclk_sel,
+		    OMAP4430_CM_L3INIT_MMC1_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops);
 
-/* Merged hsmmc2_fclk into mmc2 */
-DEFINE_CLK_OMAP_MUX_GATE(mmc2_fck, "l3_init_clkdm", hsmmc1_fclk_sel,
-			 OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM_L3INIT_MMC2_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 mmc1_fck_parents, dmic_fck_ops);
-
-DEFINE_CLK_GATE(mmc3_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_MMCSD3_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(mmc4_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_MMCSD4_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(mmc5_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_MMCSD5_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(ocp2scp_usb_phy_phy_48m, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
-		OMAP4430_OPTFCLKEN_PHY_48M_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(ocp2scp_usb_phy_ick, "l4_div_ck", &l4_div_ck, 0x0,
-		OMAP4430_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL,
-		OMAP4430_MODULEMODE_HWCTRL_SHIFT, 0x0, NULL);
-
-static struct clk ocp_wp_noc_ick;
-
-static struct clk_hw_omap ocp_wp_noc_ick_hw = {
-	.hw = {
-		.clk = &ocp_wp_noc_ick,
-	},
-	.enable_reg	= OMAP4430_CM_L3INSTR_OCP_WP1_CLKCTRL,
-	.enable_bit	= OMAP4430_MODULEMODE_HWCTRL_SHIFT,
-	.clkdm_name	= "l3_instr_clkdm",
-};
-
-DEFINE_STRUCT_CLK(ocp_wp_noc_ick, l3_instr_ick_parent_names, l3_instr_ick_ops);
-
-DEFINE_CLK_GATE(rng_ick, "l4_div_ck", &l4_div_ck, 0x0,
-		OMAP4430_CM_L4SEC_RNG_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
-		0x0, NULL);
+DEFINE_CLK_OMAP_MUX(hsmmc2_fclk, "l3_init_clkdm", hsmmc1_fclk_sel,
+		    OMAP4430_CM_L3INIT_MMC2_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    hsmmc1_fclk_parents, func_dmic_abe_gfclk_ops);
 
 DEFINE_CLK_GATE(sha2md5_fck, "l3_div_ck", &l3_div_ck, 0x0,
 		OMAP4430_CM_L4SEC_SHA2MD51_CLKCTRL,
 		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
 
-DEFINE_CLK_GATE(sl2if_ick, "dpll_iva_m5x2_ck", &dpll_iva_m5x2_ck, 0x0,
-		OMAP4430_CM_IVAHD_SL2_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
-		0x0, NULL);
-
 DEFINE_CLK_GATE(slimbus1_fclk_1, "func_24m_clk", &func_24m_clk, 0x0,
 		OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
 		OMAP4430_OPTFCLKEN_FCLK1_SHIFT, 0x0, NULL);
@@ -1232,10 +1020,6 @@
 		OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
 		OMAP4430_OPTFCLKEN_SLIMBUS_CLK_11_11_SHIFT, 0x0, NULL);
 
-DEFINE_CLK_GATE(slimbus1_fck, "ocp_abe_iclk", &ocp_abe_iclk, 0x0,
-		OMAP4430_CM1_ABE_SLIMBUS_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
 DEFINE_CLK_GATE(slimbus2_fclk_1, "per_abe_24m_fclk", &per_abe_24m_fclk, 0x0,
 		OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
 		OMAP4430_OPTFCLKEN_PERABE24M_GFCLK_SHIFT, 0x0, NULL);
@@ -1249,10 +1033,6 @@
 		OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
 		OMAP4430_OPTFCLKEN_SLIMBUS_CLK_SHIFT, 0x0, NULL);
 
-DEFINE_CLK_GATE(slimbus2_fck, "l4_div_ck", &l4_div_ck, 0x0,
-		OMAP4430_CM_L4PER_SLIMBUS2_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
 DEFINE_CLK_GATE(smartreflex_core_fck, "l4_wkup_clk_mux_ck", &l4_wkup_clk_mux_ck,
 		0x0, OMAP4430_CM_ALWON_SR_CORE_CLKCTRL,
 		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
@@ -1271,52 +1051,35 @@
 	{ .parent = NULL },
 };
 
-/* Merged dmt1_clk_mux into timer1 */
-DEFINE_CLK_OMAP_MUX_GATE(timer1_fck, "l4_wkup_clkdm", dmt1_clk_mux_sel,
-			 OMAP4430_CM_WKUP_TIMER1_CLKCTRL, OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM_WKUP_TIMER1_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(dmt1_clk_mux, "l4_wkup_clkdm", dmt1_clk_mux_sel,
+		    OMAP4430_CM_WKUP_TIMER1_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    abe_dpll_bypass_clk_mux_ck_parents,
+		    func_dmic_abe_gfclk_ops);
 
-/* Merged cm2_dm10_mux into timer10 */
-DEFINE_CLK_OMAP_MUX_GATE(timer10_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
-			 OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
-			 OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(cm2_dm10_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
+		    OMAP4430_CM_L4PER_DMTIMER10_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    abe_dpll_bypass_clk_mux_ck_parents,
+		    func_dmic_abe_gfclk_ops);
 
-/* Merged cm2_dm11_mux into timer11 */
-DEFINE_CLK_OMAP_MUX_GATE(timer11_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
-			 OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
-			 OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(cm2_dm11_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
+		    OMAP4430_CM_L4PER_DMTIMER11_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    abe_dpll_bypass_clk_mux_ck_parents,
+		    func_dmic_abe_gfclk_ops);
 
-/* Merged cm2_dm2_mux into timer2 */
-DEFINE_CLK_OMAP_MUX_GATE(timer2_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
-			 OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
-			 OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(cm2_dm2_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
+		    OMAP4430_CM_L4PER_DMTIMER2_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    abe_dpll_bypass_clk_mux_ck_parents,
+		    func_dmic_abe_gfclk_ops);
 
-/* Merged cm2_dm3_mux into timer3 */
-DEFINE_CLK_OMAP_MUX_GATE(timer3_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
-			 OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
-			 OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(cm2_dm3_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
+		    OMAP4430_CM_L4PER_DMTIMER3_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    abe_dpll_bypass_clk_mux_ck_parents,
+		    func_dmic_abe_gfclk_ops);
 
-/* Merged cm2_dm4_mux into timer4 */
-DEFINE_CLK_OMAP_MUX_GATE(timer4_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
-			 OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
-			 OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(cm2_dm4_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
+		    OMAP4430_CM_L4PER_DMTIMER4_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    abe_dpll_bypass_clk_mux_ck_parents,
+		    func_dmic_abe_gfclk_ops);
 
 static const struct clksel timer5_sync_mux_sel[] = {
 	{ .parent = &syc_clk_div_ck, .rates = div_1_0_rates },
@@ -1324,61 +1087,30 @@
 	{ .parent = NULL },
 };
 
-static const char *timer5_fck_parents[] = {
+static const char *timer5_sync_mux_parents[] = {
 	"syc_clk_div_ck", "sys_32k_ck",
 };
 
-/* Merged timer5_sync_mux into timer5 */
-DEFINE_CLK_OMAP_MUX_GATE(timer5_fck, "abe_clkdm", timer5_sync_mux_sel,
-			 OMAP4430_CM1_ABE_TIMER5_CLKCTRL, OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM1_ABE_TIMER5_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 timer5_fck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(timer5_sync_mux, "abe_clkdm", timer5_sync_mux_sel,
+		    OMAP4430_CM1_ABE_TIMER5_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    timer5_sync_mux_parents, func_dmic_abe_gfclk_ops);
 
-/* Merged timer6_sync_mux into timer6 */
-DEFINE_CLK_OMAP_MUX_GATE(timer6_fck, "abe_clkdm", timer5_sync_mux_sel,
-			 OMAP4430_CM1_ABE_TIMER6_CLKCTRL, OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM1_ABE_TIMER6_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 timer5_fck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(timer6_sync_mux, "abe_clkdm", timer5_sync_mux_sel,
+		    OMAP4430_CM1_ABE_TIMER6_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    timer5_sync_mux_parents, func_dmic_abe_gfclk_ops);
 
-/* Merged timer7_sync_mux into timer7 */
-DEFINE_CLK_OMAP_MUX_GATE(timer7_fck, "abe_clkdm", timer5_sync_mux_sel,
-			 OMAP4430_CM1_ABE_TIMER7_CLKCTRL, OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM1_ABE_TIMER7_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 timer5_fck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(timer7_sync_mux, "abe_clkdm", timer5_sync_mux_sel,
+		    OMAP4430_CM1_ABE_TIMER7_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    timer5_sync_mux_parents, func_dmic_abe_gfclk_ops);
 
-/* Merged timer8_sync_mux into timer8 */
-DEFINE_CLK_OMAP_MUX_GATE(timer8_fck, "abe_clkdm", timer5_sync_mux_sel,
-			 OMAP4430_CM1_ABE_TIMER8_CLKCTRL, OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM1_ABE_TIMER8_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 timer5_fck_parents, dmic_fck_ops);
+DEFINE_CLK_OMAP_MUX(timer8_sync_mux, "abe_clkdm", timer5_sync_mux_sel,
+		    OMAP4430_CM1_ABE_TIMER8_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    timer5_sync_mux_parents, func_dmic_abe_gfclk_ops);
 
-/* Merged cm2_dm9_mux into timer9 */
-DEFINE_CLK_OMAP_MUX_GATE(timer9_fck, "l4_per_clkdm", dmt1_clk_mux_sel,
-			 OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
-			 OMAP4430_CLKSEL_MASK,
-			 OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL,
-			 OMAP4430_MODULEMODE_SWCTRL_SHIFT, NULL,
-			 abe_dpll_bypass_clk_mux_ck_parents, dmic_fck_ops);
-
-DEFINE_CLK_GATE(uart1_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_UART1_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(uart2_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_UART2_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(uart3_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_UART3_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
-
-DEFINE_CLK_GATE(uart4_fck, "func_48m_fclk", &func_48m_fclk, 0x0,
-		OMAP4430_CM_L4PER_UART4_CLKCTRL,
-		OMAP4430_MODULEMODE_SWCTRL_SHIFT, 0x0, NULL);
+DEFINE_CLK_OMAP_MUX(cm2_dm9_mux, "l4_per_clkdm", dmt1_clk_mux_sel,
+		    OMAP4430_CM_L4PER_DMTIMER9_CLKCTRL, OMAP4430_CLKSEL_MASK,
+		    abe_dpll_bypass_clk_mux_ck_parents,
+		    func_dmic_abe_gfclk_ops);
 
 static struct clk usb_host_fs_fck;
 
@@ -1512,18 +1244,6 @@
 		OMAP4430_CM_WKUP_USIM_CLKCTRL, OMAP4430_OPTFCLKEN_FCLK_SHIFT,
 		0x0, NULL);
 
-DEFINE_CLK_GATE(usim_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
-		OMAP4430_CM_WKUP_USIM_CLKCTRL, OMAP4430_MODULEMODE_HWCTRL_SHIFT,
-		0x0, NULL);
-
-DEFINE_CLK_GATE(wd_timer2_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
-		OMAP4430_CM_WKUP_WDT2_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
-		0x0, NULL);
-
-DEFINE_CLK_GATE(wd_timer3_fck, "sys_32k_ck", &sys_32k_ck, 0x0,
-		OMAP4430_CM1_ABE_WDT3_CLKCTRL, OMAP4430_MODULEMODE_SWCTRL_SHIFT,
-		0x0, NULL);
-
 /* Remaining optional clocks */
 static const char *pmd_stm_clock_mux_ck_parents[] = {
 	"sys_clkin_ck", "dpll_core_m6x2_ck", "tie_low_clock_ck",
@@ -1774,106 +1494,61 @@
 	CLK(NULL,	"syc_clk_div_ck",		&syc_clk_div_ck,	CK_443X),
 	CLK(NULL,	"aes1_fck",			&aes1_fck,	CK_443X),
 	CLK(NULL,	"aes2_fck",			&aes2_fck,	CK_443X),
-	CLK(NULL,	"aess_fck",			&aess_fck,	CK_443X),
 	CLK(NULL,	"bandgap_fclk",			&bandgap_fclk,	CK_443X),
 	CLK(NULL,	"div_ts_ck",			&div_ts_ck,	CK_446X),
 	CLK(NULL,	"bandgap_ts_fclk",		&bandgap_ts_fclk,	CK_446X),
-	CLK(NULL,	"des3des_fck",			&des3des_fck,	CK_443X),
 	CLK(NULL,	"dmic_sync_mux_ck",		&dmic_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"dmic_fck",			&dmic_fck,	CK_443X),
-	CLK(NULL,	"dsp_fck",			&dsp_fck,	CK_443X),
+	CLK(NULL,	"func_dmic_abe_gfclk",			&func_dmic_abe_gfclk,	CK_443X),
 	CLK(NULL,	"dss_sys_clk",			&dss_sys_clk,	CK_443X),
 	CLK(NULL,	"dss_tv_clk",			&dss_tv_clk,	CK_443X),
 	CLK(NULL,	"dss_dss_clk",			&dss_dss_clk,	CK_443X),
 	CLK(NULL,	"dss_48mhz_clk",		&dss_48mhz_clk,	CK_443X),
 	CLK(NULL,	"dss_fck",			&dss_fck,	CK_443X),
 	CLK("omapdss_dss",	"ick",			&dss_fck,	CK_443X),
-	CLK(NULL,	"efuse_ctrl_cust_fck",		&efuse_ctrl_cust_fck,	CK_443X),
-	CLK(NULL,	"emif1_fck",			&emif1_fck,	CK_443X),
-	CLK(NULL,	"emif2_fck",			&emif2_fck,	CK_443X),
 	CLK(NULL,	"fdif_fck",			&fdif_fck,	CK_443X),
-	CLK(NULL,	"fpka_fck",			&fpka_fck,	CK_443X),
 	CLK(NULL,	"gpio1_dbclk",			&gpio1_dbclk,	CK_443X),
-	CLK(NULL,	"gpio1_ick",			&gpio1_ick,	CK_443X),
 	CLK(NULL,	"gpio2_dbclk",			&gpio2_dbclk,	CK_443X),
-	CLK(NULL,	"gpio2_ick",			&gpio2_ick,	CK_443X),
 	CLK(NULL,	"gpio3_dbclk",			&gpio3_dbclk,	CK_443X),
-	CLK(NULL,	"gpio3_ick",			&gpio3_ick,	CK_443X),
 	CLK(NULL,	"gpio4_dbclk",			&gpio4_dbclk,	CK_443X),
-	CLK(NULL,	"gpio4_ick",			&gpio4_ick,	CK_443X),
 	CLK(NULL,	"gpio5_dbclk",			&gpio5_dbclk,	CK_443X),
-	CLK(NULL,	"gpio5_ick",			&gpio5_ick,	CK_443X),
 	CLK(NULL,	"gpio6_dbclk",			&gpio6_dbclk,	CK_443X),
-	CLK(NULL,	"gpio6_ick",			&gpio6_ick,	CK_443X),
-	CLK(NULL,	"gpmc_ick",			&gpmc_ick,	CK_443X),
-	CLK(NULL,	"gpu_fck",			&gpu_fck,	CK_443X),
-	CLK(NULL,	"hdq1w_fck",			&hdq1w_fck,	CK_443X),
+	CLK(NULL,	"sgx_clk_mux",			&sgx_clk_mux,	CK_443X),
 	CLK(NULL,	"hsi_fck",			&hsi_fck,	CK_443X),
-	CLK(NULL,	"i2c1_fck",			&i2c1_fck,	CK_443X),
-	CLK(NULL,	"i2c2_fck",			&i2c2_fck,	CK_443X),
-	CLK(NULL,	"i2c3_fck",			&i2c3_fck,	CK_443X),
-	CLK(NULL,	"i2c4_fck",			&i2c4_fck,	CK_443X),
-	CLK(NULL,	"ipu_fck",			&ipu_fck,	CK_443X),
 	CLK(NULL,	"iss_ctrlclk",			&iss_ctrlclk,	CK_443X),
-	CLK(NULL,	"iss_fck",			&iss_fck,	CK_443X),
-	CLK(NULL,	"iva_fck",			&iva_fck,	CK_443X),
-	CLK(NULL,	"kbd_fck",			&kbd_fck,	CK_443X),
-	CLK(NULL,	"l3_instr_ick",			&l3_instr_ick,	CK_443X),
-	CLK(NULL,	"l3_main_3_ick",		&l3_main_3_ick,	CK_443X),
 	CLK(NULL,	"mcasp_sync_mux_ck",		&mcasp_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"mcasp_fck",			&mcasp_fck,	CK_443X),
+	CLK(NULL,	"func_mcasp_abe_gfclk",			&func_mcasp_abe_gfclk,	CK_443X),
 	CLK(NULL,	"mcbsp1_sync_mux_ck",		&mcbsp1_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"mcbsp1_fck",			&mcbsp1_fck,	CK_443X),
+	CLK(NULL,	"func_mcbsp1_gfclk",			&func_mcbsp1_gfclk,	CK_443X),
 	CLK(NULL,	"mcbsp2_sync_mux_ck",		&mcbsp2_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"mcbsp2_fck",			&mcbsp2_fck,	CK_443X),
+	CLK(NULL,	"func_mcbsp2_gfclk",			&func_mcbsp2_gfclk,	CK_443X),
 	CLK(NULL,	"mcbsp3_sync_mux_ck",		&mcbsp3_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"mcbsp3_fck",			&mcbsp3_fck,	CK_443X),
+	CLK(NULL,	"func_mcbsp3_gfclk",			&func_mcbsp3_gfclk,	CK_443X),
 	CLK(NULL,	"mcbsp4_sync_mux_ck",		&mcbsp4_sync_mux_ck,	CK_443X),
-	CLK(NULL,	"mcbsp4_fck",			&mcbsp4_fck,	CK_443X),
-	CLK(NULL,	"mcpdm_fck",			&mcpdm_fck,	CK_443X),
-	CLK(NULL,	"mcspi1_fck",			&mcspi1_fck,	CK_443X),
-	CLK(NULL,	"mcspi2_fck",			&mcspi2_fck,	CK_443X),
-	CLK(NULL,	"mcspi3_fck",			&mcspi3_fck,	CK_443X),
-	CLK(NULL,	"mcspi4_fck",			&mcspi4_fck,	CK_443X),
-	CLK(NULL,	"mmc1_fck",			&mmc1_fck,	CK_443X),
-	CLK(NULL,	"mmc2_fck",			&mmc2_fck,	CK_443X),
-	CLK(NULL,	"mmc3_fck",			&mmc3_fck,	CK_443X),
-	CLK(NULL,	"mmc4_fck",			&mmc4_fck,	CK_443X),
-	CLK(NULL,	"mmc5_fck",			&mmc5_fck,	CK_443X),
-	CLK(NULL,	"ocp2scp_usb_phy_phy_48m",	&ocp2scp_usb_phy_phy_48m,	CK_443X),
-	CLK(NULL,	"ocp2scp_usb_phy_ick",		&ocp2scp_usb_phy_ick,	CK_443X),
-	CLK(NULL,	"ocp_wp_noc_ick",		&ocp_wp_noc_ick,	CK_443X),
-	CLK(NULL,	"rng_ick",			&rng_ick,	CK_443X),
-	CLK("omap_rng",	"ick",				&rng_ick,	CK_443X),
+	CLK(NULL,	"per_mcbsp4_gfclk",			&per_mcbsp4_gfclk,	CK_443X),
+	CLK(NULL,	"hsmmc1_fclk",			&hsmmc1_fclk,	CK_443X),
+	CLK(NULL,	"hsmmc2_fclk",			&hsmmc2_fclk,	CK_443X),
 	CLK(NULL,	"sha2md5_fck",			&sha2md5_fck,	CK_443X),
-	CLK(NULL,	"sl2if_ick",			&sl2if_ick,	CK_443X),
 	CLK(NULL,	"slimbus1_fclk_1",		&slimbus1_fclk_1,	CK_443X),
 	CLK(NULL,	"slimbus1_fclk_0",		&slimbus1_fclk_0,	CK_443X),
 	CLK(NULL,	"slimbus1_fclk_2",		&slimbus1_fclk_2,	CK_443X),
 	CLK(NULL,	"slimbus1_slimbus_clk",		&slimbus1_slimbus_clk,	CK_443X),
-	CLK(NULL,	"slimbus1_fck",			&slimbus1_fck,	CK_443X),
 	CLK(NULL,	"slimbus2_fclk_1",		&slimbus2_fclk_1,	CK_443X),
 	CLK(NULL,	"slimbus2_fclk_0",		&slimbus2_fclk_0,	CK_443X),
 	CLK(NULL,	"slimbus2_slimbus_clk",		&slimbus2_slimbus_clk,	CK_443X),
-	CLK(NULL,	"slimbus2_fck",			&slimbus2_fck,	CK_443X),
 	CLK(NULL,	"smartreflex_core_fck",		&smartreflex_core_fck,	CK_443X),
 	CLK(NULL,	"smartreflex_iva_fck",		&smartreflex_iva_fck,	CK_443X),
 	CLK(NULL,	"smartreflex_mpu_fck",		&smartreflex_mpu_fck,	CK_443X),
-	CLK(NULL,	"timer1_fck",			&timer1_fck,	CK_443X),
-	CLK(NULL,	"timer10_fck",			&timer10_fck,	CK_443X),
-	CLK(NULL,	"timer11_fck",			&timer11_fck,	CK_443X),
-	CLK(NULL,	"timer2_fck",			&timer2_fck,	CK_443X),
-	CLK(NULL,	"timer3_fck",			&timer3_fck,	CK_443X),
-	CLK(NULL,	"timer4_fck",			&timer4_fck,	CK_443X),
-	CLK(NULL,	"timer5_fck",			&timer5_fck,	CK_443X),
-	CLK(NULL,	"timer6_fck",			&timer6_fck,	CK_443X),
-	CLK(NULL,	"timer7_fck",			&timer7_fck,	CK_443X),
-	CLK(NULL,	"timer8_fck",			&timer8_fck,	CK_443X),
-	CLK(NULL,	"timer9_fck",			&timer9_fck,	CK_443X),
-	CLK(NULL,	"uart1_fck",			&uart1_fck,	CK_443X),
-	CLK(NULL,	"uart2_fck",			&uart2_fck,	CK_443X),
-	CLK(NULL,	"uart3_fck",			&uart3_fck,	CK_443X),
-	CLK(NULL,	"uart4_fck",			&uart4_fck,	CK_443X),
+	CLK(NULL,	"dmt1_clk_mux",			&dmt1_clk_mux,	CK_443X),
+	CLK(NULL,	"cm2_dm10_mux",			&cm2_dm10_mux,	CK_443X),
+	CLK(NULL,	"cm2_dm11_mux",			&cm2_dm11_mux,	CK_443X),
+	CLK(NULL,	"cm2_dm2_mux",			&cm2_dm2_mux,	CK_443X),
+	CLK(NULL,	"cm2_dm3_mux",			&cm2_dm3_mux,	CK_443X),
+	CLK(NULL,	"cm2_dm4_mux",			&cm2_dm4_mux,	CK_443X),
+	CLK(NULL,	"timer5_sync_mux",		&timer5_sync_mux,	CK_443X),
+	CLK(NULL,	"timer6_sync_mux",			&timer6_sync_mux,	CK_443X),
+	CLK(NULL,	"timer7_sync_mux",			&timer7_sync_mux,	CK_443X),
+	CLK(NULL,	"timer8_sync_mux",			&timer8_sync_mux,	CK_443X),
+	CLK(NULL,	"cm2_dm9_mux",			&cm2_dm9_mux,	CK_443X),
 	CLK(NULL,	"usb_host_fs_fck",		&usb_host_fs_fck,	CK_443X),
 	CLK("usbhs_omap",	"fs_fck",		&usb_host_fs_fck,	CK_443X),
 	CLK(NULL,	"utmi_p1_gfclk",		&utmi_p1_gfclk,	CK_443X),
@@ -1901,9 +1576,6 @@
 	CLK("usbhs_tll",	"usbtll_ick",		&usb_tll_hs_ick,	CK_443X),
 	CLK(NULL,	"usim_ck",			&usim_ck,	CK_443X),
 	CLK(NULL,	"usim_fclk",			&usim_fclk,	CK_443X),
-	CLK(NULL,	"usim_fck",			&usim_fck,	CK_443X),
-	CLK(NULL,	"wd_timer2_fck",		&wd_timer2_fck,	CK_443X),
-	CLK(NULL,	"wd_timer3_fck",		&wd_timer3_fck,	CK_443X),
 	CLK(NULL,	"pmd_stm_clock_mux_ck",		&pmd_stm_clock_mux_ck,	CK_443X),
 	CLK(NULL,	"pmd_trace_clk_mux_ck",		&pmd_trace_clk_mux_ck,	CK_443X),
 	CLK(NULL,	"stm_clk_div_ck",		&stm_clk_div_ck,	CK_443X),
@@ -1980,15 +1652,6 @@
 	CLK(NULL,	"cpufreq_ck",	&dpll_mpu_ck,	CK_443X),
 };
 
-static const char *enable_init_clks[] = {
-	"emif1_fck",
-	"emif2_fck",
-	"gpmc_ick",
-	"l3_instr_ick",
-	"l3_main_3_ick",
-	"ocp_wp_noc_ick",
-};
-
 int __init omap4xxx_clk_init(void)
 {
 	u32 cpu_clkflg;
@@ -2019,21 +1682,17 @@
 
 	omap2_clk_disable_autoidle_all();
 
-	omap2_clk_enable_init_clocks(enable_init_clks,
-				     ARRAY_SIZE(enable_init_clks));
-
 	/*
 	 * On OMAP4460 the ABE DPLL fails to turn on if in idle low-power
 	 * state when turning the ABE clock domain. Workaround this by
 	 * locking the ABE DPLL on boot.
+	 * Lock the ABE DPLL in any case to avoid issues with audio.
 	 */
-	if (cpu_is_omap446x()) {
-		rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck);
-		if (!rc)
-			rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ);
-		if (rc)
-			pr_err("%s: failed to configure ABE DPLL!\n", __func__);
-	}
+	rc = clk_set_parent(&abe_dpll_refclk_mux_ck, &sys_32k_ck);
+	if (!rc)
+		rc = clk_set_rate(&dpll_abe_ck, OMAP4_DPLL_ABE_DEFFREQ);
+	if (rc)
+		pr_err("%s: failed to configure ABE DPLL!\n", __func__);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/clockdomain.c b/arch/arm/mach-omap2/clockdomain.c
index 7faf82d..2da3b5e 100644
--- a/arch/arm/mach-omap2/clockdomain.c
+++ b/arch/arm/mach-omap2/clockdomain.c
@@ -92,8 +92,6 @@
 
 	pwrdm_add_clkdm(pwrdm, clkdm);
 
-	spin_lock_init(&clkdm->lock);
-
 	pr_debug("clockdomain: registered %s\n", clkdm->name);
 
 	return 0;
@@ -122,7 +120,7 @@
 	return cd;
 }
 
-/*
+/**
  * _autodep_lookup - resolve autodep clkdm names to clkdm pointers; store
  * @autodep: struct clkdm_autodep * to resolve
  *
@@ -154,66 +152,6 @@
 	autodep->clkdm.ptr = clkdm;
 }
 
-/*
- * _clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable
- * @clkdm: struct clockdomain *
- *
- * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
- * in hardware-supervised mode.  Meant to be called from clock framework
- * when a clock inside clockdomain 'clkdm' is enabled.	No return value.
- *
- * XXX autodeps are deprecated and should be removed at the earliest
- * opportunity
- */
-void _clkdm_add_autodeps(struct clockdomain *clkdm)
-{
-	struct clkdm_autodep *autodep;
-
-	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
-		return;
-
-	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
-		if (IS_ERR(autodep->clkdm.ptr))
-			continue;
-
-		pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n",
-			 clkdm->name, autodep->clkdm.ptr->name);
-
-		clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr);
-		clkdm_add_wkdep(clkdm, autodep->clkdm.ptr);
-	}
-}
-
-/*
- * _clkdm_add_autodeps - remove auto sleepdeps/wkdeps from clkdm
- * @clkdm: struct clockdomain *
- *
- * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
- * in hardware-supervised mode.  Meant to be called from clock framework
- * when a clock inside clockdomain 'clkdm' is disabled.  No return value.
- *
- * XXX autodeps are deprecated and should be removed at the earliest
- * opportunity
- */
-void _clkdm_del_autodeps(struct clockdomain *clkdm)
-{
-	struct clkdm_autodep *autodep;
-
-	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
-		return;
-
-	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
-		if (IS_ERR(autodep->clkdm.ptr))
-			continue;
-
-		pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n",
-			 clkdm->name, autodep->clkdm.ptr->name);
-
-		clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr);
-		clkdm_del_wkdep(clkdm, autodep->clkdm.ptr);
-	}
-}
-
 /**
  * _resolve_clkdm_deps() - resolve clkdm_names in @clkdm_deps to clkdms
  * @clkdm: clockdomain that we are resolving dependencies for
@@ -238,6 +176,184 @@
 	}
 }
 
+/**
+ * _clkdm_add_wkdep - add a wakeup dependency from clkdm2 to clkdm1 (lockless)
+ * @clkdm1: wake this struct clockdomain * up (dependent)
+ * @clkdm2: when this struct clockdomain * wakes up (source)
+ *
+ * When the clockdomain represented by @clkdm2 wakes up, wake up
+ * @clkdm1. Implemented in hardware on the OMAP, this feature is
+ * designed to reduce wakeup latency of the dependent clockdomain @clkdm1.
+ * Returns -EINVAL if presented with invalid clockdomain pointers,
+ * -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or 0 upon
+ * success.
+ */
+static int _clkdm_add_wkdep(struct clockdomain *clkdm1,
+			    struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+	int ret = 0;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
+		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
+		return ret;
+	}
+
+	cd->wkdep_usecount++;
+	if (cd->wkdep_usecount == 1) {
+		pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
+
+		ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
+	}
+
+	return ret;
+}
+
+/**
+ * _clkdm_del_wkdep - remove a wakeup dep from clkdm2 to clkdm1 (lockless)
+ * @clkdm1: wake this struct clockdomain * up (dependent)
+ * @clkdm2: when this struct clockdomain * wakes up (source)
+ *
+ * Remove a wakeup dependency causing @clkdm1 to wake up when @clkdm2
+ * wakes up.  Returns -EINVAL if presented with invalid clockdomain
+ * pointers, -ENOENT if @clkdm2 cannot wake up clkdm1 in hardware, or
+ * 0 upon success.
+ */
+static int _clkdm_del_wkdep(struct clockdomain *clkdm1,
+			    struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+	int ret = 0;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
+		ret = -EINVAL;
+
+	if (ret) {
+		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
+		return ret;
+	}
+
+	cd->wkdep_usecount--;
+	if (cd->wkdep_usecount == 0) {
+		pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n",
+			 clkdm1->name, clkdm2->name);
+
+		ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
+	}
+
+	return ret;
+}
+
+/**
+ * _clkdm_add_sleepdep - add a sleep dependency from clkdm2 to clkdm1 (lockless)
+ * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
+ * @clkdm2: when this struct clockdomain * is active (source)
+ *
+ * Prevent @clkdm1 from automatically going inactive (and then to
+ * retention or off) if @clkdm2 is active.  Returns -EINVAL if
+ * presented with invalid clockdomain pointers or called on a machine
+ * that does not support software-configurable hardware sleep
+ * dependencies, -ENOENT if the specified dependency cannot be set in
+ * hardware, or 0 upon success.
+ */
+static int _clkdm_add_sleepdep(struct clockdomain *clkdm1,
+			       struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+	int ret = 0;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
+		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
+			 clkdm1->name, clkdm2->name);
+		return ret;
+	}
+
+	cd->sleepdep_usecount++;
+	if (cd->sleepdep_usecount == 1) {
+		pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
+			 clkdm1->name, clkdm2->name);
+
+		ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
+	}
+
+	return ret;
+}
+
+/**
+ * _clkdm_del_sleepdep - remove a sleep dep from clkdm2 to clkdm1 (lockless)
+ * @clkdm1: prevent this struct clockdomain * from sleeping (dependent)
+ * @clkdm2: when this struct clockdomain * is active (source)
+ *
+ * Allow @clkdm1 to automatically go inactive (and then to retention or
+ * off), independent of the activity state of @clkdm2.  Returns -EINVAL
+ * if presented with invalid clockdomain pointers or called on a machine
+ * that does not support software-configurable hardware sleep dependencies,
+ * -ENOENT if the specified dependency cannot be cleared in hardware, or
+ * 0 upon success.
+ */
+static int _clkdm_del_sleepdep(struct clockdomain *clkdm1,
+			       struct clockdomain *clkdm2)
+{
+	struct clkdm_dep *cd;
+	int ret = 0;
+
+	if (!clkdm1 || !clkdm2)
+		return -EINVAL;
+
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
+	if (IS_ERR(cd))
+		ret = PTR_ERR(cd);
+
+	if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
+		ret = -EINVAL;
+
+	if (ret) {
+		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
+			 clkdm1->name, clkdm2->name);
+		return ret;
+	}
+
+	cd->sleepdep_usecount--;
+	if (cd->sleepdep_usecount == 0) {
+		pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n",
+			 clkdm1->name, clkdm2->name);
+
+		ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
+	}
+
+	return ret;
+}
+
 /* Public functions */
 
 /**
@@ -456,30 +572,18 @@
 int clkdm_add_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-	int ret = 0;
+	int ret;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
 	if (IS_ERR(cd))
-		ret = PTR_ERR(cd);
+		return PTR_ERR(cd);
 
-	if (!arch_clkdm || !arch_clkdm->clkdm_add_wkdep)
-		ret = -EINVAL;
-
-	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
-			 clkdm1->name, clkdm2->name);
-		return ret;
-	}
-
-	if (atomic_inc_return(&cd->wkdep_usecount) == 1) {
-		pr_debug("clockdomain: hardware will wake up %s when %s wakes up\n",
-			 clkdm1->name, clkdm2->name);
-
-		ret = arch_clkdm->clkdm_add_wkdep(clkdm1, clkdm2);
-	}
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_add_wkdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
 
 	return ret;
 }
@@ -497,30 +601,18 @@
 int clkdm_del_wkdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-	int ret = 0;
+	int ret;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
 	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
 	if (IS_ERR(cd))
-		ret = PTR_ERR(cd);
+		return PTR_ERR(cd);
 
-	if (!arch_clkdm || !arch_clkdm->clkdm_del_wkdep)
-		ret = -EINVAL;
-
-	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear wake up of %s when %s wakes up\n",
-			 clkdm1->name, clkdm2->name);
-		return ret;
-	}
-
-	if (atomic_dec_return(&cd->wkdep_usecount) == 0) {
-		pr_debug("clockdomain: hardware will no longer wake up %s after %s wakes up\n",
-			 clkdm1->name, clkdm2->name);
-
-		ret = arch_clkdm->clkdm_del_wkdep(clkdm1, clkdm2);
-	}
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_del_wkdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
 
 	return ret;
 }
@@ -560,7 +652,7 @@
 		return ret;
 	}
 
-	/* XXX It's faster to return the atomic wkdep_usecount */
+	/* XXX It's faster to return the wkdep_usecount */
 	return arch_clkdm->clkdm_read_wkdep(clkdm1, clkdm2);
 }
 
@@ -600,30 +692,18 @@
 int clkdm_add_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-	int ret = 0;
+	int ret;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
-	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
 	if (IS_ERR(cd))
-		ret = PTR_ERR(cd);
+		return PTR_ERR(cd);
 
-	if (!arch_clkdm || !arch_clkdm->clkdm_add_sleepdep)
-		ret = -EINVAL;
-
-	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
-			 clkdm1->name, clkdm2->name);
-		return ret;
-	}
-
-	if (atomic_inc_return(&cd->sleepdep_usecount) == 1) {
-		pr_debug("clockdomain: will prevent %s from sleeping if %s is active\n",
-			 clkdm1->name, clkdm2->name);
-
-		ret = arch_clkdm->clkdm_add_sleepdep(clkdm1, clkdm2);
-	}
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_add_sleepdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
 
 	return ret;
 }
@@ -643,30 +723,18 @@
 int clkdm_del_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2)
 {
 	struct clkdm_dep *cd;
-	int ret = 0;
+	int ret;
 
 	if (!clkdm1 || !clkdm2)
 		return -EINVAL;
 
-	cd = _clkdm_deps_lookup(clkdm2, clkdm1->sleepdep_srcs);
+	cd = _clkdm_deps_lookup(clkdm2, clkdm1->wkdep_srcs);
 	if (IS_ERR(cd))
-		ret = PTR_ERR(cd);
+		return PTR_ERR(cd);
 
-	if (!arch_clkdm || !arch_clkdm->clkdm_del_sleepdep)
-		ret = -EINVAL;
-
-	if (ret) {
-		pr_debug("clockdomain: hardware cannot set/clear sleep dependency affecting %s from %s\n",
-			 clkdm1->name, clkdm2->name);
-		return ret;
-	}
-
-	if (atomic_dec_return(&cd->sleepdep_usecount) == 0) {
-		pr_debug("clockdomain: will no longer prevent %s from sleeping if %s is active\n",
-			 clkdm1->name, clkdm2->name);
-
-		ret = arch_clkdm->clkdm_del_sleepdep(clkdm1, clkdm2);
-	}
+	pwrdm_lock(cd->clkdm->pwrdm.ptr);
+	ret = _clkdm_del_sleepdep(clkdm1, clkdm2);
+	pwrdm_unlock(cd->clkdm->pwrdm.ptr);
 
 	return ret;
 }
@@ -708,7 +776,7 @@
 		return ret;
 	}
 
-	/* XXX It's faster to return the atomic sleepdep_usecount */
+	/* XXX It's faster to return the sleepdep_usecount */
 	return arch_clkdm->clkdm_read_sleepdep(clkdm1, clkdm2);
 }
 
@@ -734,18 +802,17 @@
 }
 
 /**
- * clkdm_sleep - force clockdomain sleep transition
+ * clkdm_sleep_nolock - force clockdomain sleep transition (lockless)
  * @clkdm: struct clockdomain *
  *
  * Instruct the CM to force a sleep transition on the specified
- * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if
- * clockdomain does not support software-initiated sleep; 0 upon
- * success.
+ * clockdomain @clkdm.  Only for use by the powerdomain code.  Returns
+ * -EINVAL if @clkdm is NULL or if clockdomain does not support
+ * software-initiated sleep; 0 upon success.
  */
-int clkdm_sleep(struct clockdomain *clkdm)
+int clkdm_sleep_nolock(struct clockdomain *clkdm)
 {
 	int ret;
-	unsigned long flags;
 
 	if (!clkdm)
 		return -EINVAL;
@@ -761,26 +828,45 @@
 
 	pr_debug("clockdomain: forcing sleep on %s\n", clkdm->name);
 
-	spin_lock_irqsave(&clkdm->lock, flags);
 	clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
 	ret = arch_clkdm->clkdm_sleep(clkdm);
-	spin_unlock_irqrestore(&clkdm->lock, flags);
+	ret |= pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+
 	return ret;
 }
 
 /**
- * clkdm_wakeup - force clockdomain wakeup transition
+ * clkdm_sleep - force clockdomain sleep transition
+ * @clkdm: struct clockdomain *
+ *
+ * Instruct the CM to force a sleep transition on the specified
+ * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if
+ * clockdomain does not support software-initiated sleep; 0 upon
+ * success.
+ */
+int clkdm_sleep(struct clockdomain *clkdm)
+{
+	int ret;
+
+	pwrdm_lock(clkdm->pwrdm.ptr);
+	ret = clkdm_sleep_nolock(clkdm);
+	pwrdm_unlock(clkdm->pwrdm.ptr);
+
+	return ret;
+}
+
+/**
+ * clkdm_wakeup_nolock - force clockdomain wakeup transition (lockless)
  * @clkdm: struct clockdomain *
  *
  * Instruct the CM to force a wakeup transition on the specified
- * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if the
- * clockdomain does not support software-controlled wakeup; 0 upon
- * success.
+ * clockdomain @clkdm.  Only for use by the powerdomain code.  Returns
+ * -EINVAL if @clkdm is NULL or if the clockdomain does not support
+ * software-controlled wakeup; 0 upon success.
  */
-int clkdm_wakeup(struct clockdomain *clkdm)
+int clkdm_wakeup_nolock(struct clockdomain *clkdm)
 {
 	int ret;
-	unsigned long flags;
 
 	if (!clkdm)
 		return -EINVAL;
@@ -796,28 +882,46 @@
 
 	pr_debug("clockdomain: forcing wakeup on %s\n", clkdm->name);
 
-	spin_lock_irqsave(&clkdm->lock, flags);
 	clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
 	ret = arch_clkdm->clkdm_wakeup(clkdm);
-	ret |= pwrdm_state_switch(clkdm->pwrdm.ptr);
-	spin_unlock_irqrestore(&clkdm->lock, flags);
+	ret |= pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+
 	return ret;
 }
 
 /**
- * clkdm_allow_idle - enable hwsup idle transitions for clkdm
+ * clkdm_wakeup - force clockdomain wakeup transition
  * @clkdm: struct clockdomain *
  *
- * Allow the hardware to automatically switch the clockdomain @clkdm into
- * active or idle states, as needed by downstream clocks.  If the
+ * Instruct the CM to force a wakeup transition on the specified
+ * clockdomain @clkdm.  Returns -EINVAL if @clkdm is NULL or if the
+ * clockdomain does not support software-controlled wakeup; 0 upon
+ * success.
+ */
+int clkdm_wakeup(struct clockdomain *clkdm)
+{
+	int ret;
+
+	pwrdm_lock(clkdm->pwrdm.ptr);
+	ret = clkdm_wakeup_nolock(clkdm);
+	pwrdm_unlock(clkdm->pwrdm.ptr);
+
+	return ret;
+}
+
+/**
+ * clkdm_allow_idle_nolock - enable hwsup idle transitions for clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Allow the hardware to automatically switch the clockdomain @clkdm
+ * into active or idle states, as needed by downstream clocks.  If the
  * clockdomain has any downstream clocks enabled in the clock
  * framework, wkdep/sleepdep autodependencies are added; this is so
- * device drivers can read and write to the device.  No return value.
+ * device drivers can read and write to the device.  Only for use by
+ * the powerdomain code.  No return value.
  */
-void clkdm_allow_idle(struct clockdomain *clkdm)
+void clkdm_allow_idle_nolock(struct clockdomain *clkdm)
 {
-	unsigned long flags;
-
 	if (!clkdm)
 		return;
 
@@ -833,11 +937,26 @@
 	pr_debug("clockdomain: enabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
-	spin_lock_irqsave(&clkdm->lock, flags);
 	clkdm->_flags |= _CLKDM_FLAG_HWSUP_ENABLED;
 	arch_clkdm->clkdm_allow_idle(clkdm);
-	pwrdm_state_switch(clkdm->pwrdm.ptr);
-	spin_unlock_irqrestore(&clkdm->lock, flags);
+	pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+}
+
+/**
+ * clkdm_allow_idle - enable hwsup idle transitions for clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Allow the hardware to automatically switch the clockdomain @clkdm into
+ * active or idle states, as needed by downstream clocks.  If the
+ * clockdomain has any downstream clocks enabled in the clock
+ * framework, wkdep/sleepdep autodependencies are added; this is so
+ * device drivers can read and write to the device.  No return value.
+ */
+void clkdm_allow_idle(struct clockdomain *clkdm)
+{
+	pwrdm_lock(clkdm->pwrdm.ptr);
+	clkdm_allow_idle_nolock(clkdm);
+	pwrdm_unlock(clkdm->pwrdm.ptr);
 }
 
 /**
@@ -847,12 +966,11 @@
  * Prevent the hardware from automatically switching the clockdomain
  * @clkdm into inactive or idle states.  If the clockdomain has
  * downstream clocks enabled in the clock framework, wkdep/sleepdep
- * autodependencies are removed.  No return value.
+ * autodependencies are removed.  Only for use by the powerdomain
+ * code.  No return value.
  */
-void clkdm_deny_idle(struct clockdomain *clkdm)
+void clkdm_deny_idle_nolock(struct clockdomain *clkdm)
 {
-	unsigned long flags;
-
 	if (!clkdm)
 		return;
 
@@ -868,11 +986,25 @@
 	pr_debug("clockdomain: disabling automatic idle transitions for %s\n",
 		 clkdm->name);
 
-	spin_lock_irqsave(&clkdm->lock, flags);
 	clkdm->_flags &= ~_CLKDM_FLAG_HWSUP_ENABLED;
 	arch_clkdm->clkdm_deny_idle(clkdm);
-	pwrdm_state_switch(clkdm->pwrdm.ptr);
-	spin_unlock_irqrestore(&clkdm->lock, flags);
+	pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+}
+
+/**
+ * clkdm_deny_idle - disable hwsup idle transitions for clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Prevent the hardware from automatically switching the clockdomain
+ * @clkdm into inactive or idle states.  If the clockdomain has
+ * downstream clocks enabled in the clock framework, wkdep/sleepdep
+ * autodependencies are removed.  No return value.
+ */
+void clkdm_deny_idle(struct clockdomain *clkdm)
+{
+	pwrdm_lock(clkdm->pwrdm.ptr);
+	clkdm_deny_idle_nolock(clkdm);
+	pwrdm_unlock(clkdm->pwrdm.ptr);
 }
 
 /**
@@ -889,14 +1021,11 @@
 bool clkdm_in_hwsup(struct clockdomain *clkdm)
 {
 	bool ret;
-	unsigned long flags;
 
 	if (!clkdm)
 		return false;
 
-	spin_lock_irqsave(&clkdm->lock, flags);
 	ret = (clkdm->_flags & _CLKDM_FLAG_HWSUP_ENABLED) ? true : false;
-	spin_unlock_irqrestore(&clkdm->lock, flags);
 
 	return ret;
 }
@@ -918,30 +1047,91 @@
 	return (clkdm->flags & CLKDM_MISSING_IDLE_REPORTING) ? true : false;
 }
 
+/* Public autodep handling functions (deprecated) */
+
+/**
+ * clkdm_add_autodeps - add auto sleepdeps/wkdeps to clkdm upon clock enable
+ * @clkdm: struct clockdomain *
+ *
+ * Add the "autodep" sleep & wakeup dependencies to clockdomain 'clkdm'
+ * in hardware-supervised mode.  Meant to be called from clock framework
+ * when a clock inside clockdomain 'clkdm' is enabled.	No return value.
+ *
+ * XXX autodeps are deprecated and should be removed at the earliest
+ * opportunity
+ */
+void clkdm_add_autodeps(struct clockdomain *clkdm)
+{
+	struct clkdm_autodep *autodep;
+
+	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
+		return;
+
+	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
+		if (IS_ERR(autodep->clkdm.ptr))
+			continue;
+
+		pr_debug("clockdomain: %s: adding %s sleepdep/wkdep\n",
+			 clkdm->name, autodep->clkdm.ptr->name);
+
+		_clkdm_add_sleepdep(clkdm, autodep->clkdm.ptr);
+		_clkdm_add_wkdep(clkdm, autodep->clkdm.ptr);
+	}
+}
+
+/**
+ * clkdm_del_autodeps - remove auto sleepdeps/wkdeps from clkdm
+ * @clkdm: struct clockdomain *
+ *
+ * Remove the "autodep" sleep & wakeup dependencies from clockdomain 'clkdm'
+ * in hardware-supervised mode.  Meant to be called from clock framework
+ * when a clock inside clockdomain 'clkdm' is disabled.  No return value.
+ *
+ * XXX autodeps are deprecated and should be removed at the earliest
+ * opportunity
+ */
+void clkdm_del_autodeps(struct clockdomain *clkdm)
+{
+	struct clkdm_autodep *autodep;
+
+	if (!autodeps || clkdm->flags & CLKDM_NO_AUTODEPS)
+		return;
+
+	for (autodep = autodeps; autodep->clkdm.ptr; autodep++) {
+		if (IS_ERR(autodep->clkdm.ptr))
+			continue;
+
+		pr_debug("clockdomain: %s: removing %s sleepdep/wkdep\n",
+			 clkdm->name, autodep->clkdm.ptr->name);
+
+		_clkdm_del_sleepdep(clkdm, autodep->clkdm.ptr);
+		_clkdm_del_wkdep(clkdm, autodep->clkdm.ptr);
+	}
+}
+
 /* Clockdomain-to-clock/hwmod framework interface code */
 
 static int _clkdm_clk_hwmod_enable(struct clockdomain *clkdm)
 {
-	unsigned long flags;
-
 	if (!clkdm || !arch_clkdm || !arch_clkdm->clkdm_clk_enable)
 		return -EINVAL;
 
-	spin_lock_irqsave(&clkdm->lock, flags);
+	pwrdm_lock(clkdm->pwrdm.ptr);
 
 	/*
 	 * For arch's with no autodeps, clkcm_clk_enable
 	 * should be called for every clock instance or hwmod that is
 	 * enabled, so the clkdm can be force woken up.
 	 */
-	if ((atomic_inc_return(&clkdm->usecount) > 1) && autodeps) {
-		spin_unlock_irqrestore(&clkdm->lock, flags);
+	clkdm->usecount++;
+	if (clkdm->usecount > 1 && autodeps) {
+		pwrdm_unlock(clkdm->pwrdm.ptr);
 		return 0;
 	}
 
 	arch_clkdm->clkdm_clk_enable(clkdm);
-	pwrdm_state_switch(clkdm->pwrdm.ptr);
-	spin_unlock_irqrestore(&clkdm->lock, flags);
+	pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+	pwrdm_unlock(clkdm->pwrdm.ptr);
 
 	pr_debug("clockdomain: %s: enabled\n", clkdm->name);
 
@@ -990,36 +1180,34 @@
  */
 int clkdm_clk_disable(struct clockdomain *clkdm, struct clk *clk)
 {
-	unsigned long flags;
-
 	if (!clkdm || !clk || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
 		return -EINVAL;
 
-	spin_lock_irqsave(&clkdm->lock, flags);
+	pwrdm_lock(clkdm->pwrdm.ptr);
 
 	/* corner case: disabling unused clocks */
-	if ((__clk_get_enable_count(clk) == 0) &&
-	    (atomic_read(&clkdm->usecount) == 0))
+	if ((__clk_get_enable_count(clk) == 0) && clkdm->usecount == 0)
 		goto ccd_exit;
 
-	if (atomic_read(&clkdm->usecount) == 0) {
-		spin_unlock_irqrestore(&clkdm->lock, flags);
+	if (clkdm->usecount == 0) {
+		pwrdm_unlock(clkdm->pwrdm.ptr);
 		WARN_ON(1); /* underflow */
 		return -ERANGE;
 	}
 
-	if (atomic_dec_return(&clkdm->usecount) > 0) {
-		spin_unlock_irqrestore(&clkdm->lock, flags);
+	clkdm->usecount--;
+	if (clkdm->usecount > 0) {
+		pwrdm_unlock(clkdm->pwrdm.ptr);
 		return 0;
 	}
 
 	arch_clkdm->clkdm_clk_disable(clkdm);
-	pwrdm_state_switch(clkdm->pwrdm.ptr);
+	pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
 
 	pr_debug("clockdomain: %s: disabled\n", clkdm->name);
 
 ccd_exit:
-	spin_unlock_irqrestore(&clkdm->lock, flags);
+	pwrdm_unlock(clkdm->pwrdm.ptr);
 
 	return 0;
 }
@@ -1072,8 +1260,6 @@
  */
 int clkdm_hwmod_disable(struct clockdomain *clkdm, struct omap_hwmod *oh)
 {
-	unsigned long flags;
-
 	/* The clkdm attribute does not exist yet prior OMAP4 */
 	if (cpu_is_omap24xx() || cpu_is_omap34xx())
 		return 0;
@@ -1086,22 +1272,23 @@
 	if (!clkdm || !oh || !arch_clkdm || !arch_clkdm->clkdm_clk_disable)
 		return -EINVAL;
 
-	spin_lock_irqsave(&clkdm->lock, flags);
+	pwrdm_lock(clkdm->pwrdm.ptr);
 
-	if (atomic_read(&clkdm->usecount) == 0) {
-		spin_unlock_irqrestore(&clkdm->lock, flags);
+	if (clkdm->usecount == 0) {
+		pwrdm_unlock(clkdm->pwrdm.ptr);
 		WARN_ON(1); /* underflow */
 		return -ERANGE;
 	}
 
-	if (atomic_dec_return(&clkdm->usecount) > 0) {
-		spin_unlock_irqrestore(&clkdm->lock, flags);
+	clkdm->usecount--;
+	if (clkdm->usecount > 0) {
+		pwrdm_unlock(clkdm->pwrdm.ptr);
 		return 0;
 	}
 
 	arch_clkdm->clkdm_clk_disable(clkdm);
-	pwrdm_state_switch(clkdm->pwrdm.ptr);
-	spin_unlock_irqrestore(&clkdm->lock, flags);
+	pwrdm_state_switch_nolock(clkdm->pwrdm.ptr);
+	pwrdm_unlock(clkdm->pwrdm.ptr);
 
 	pr_debug("clockdomain: %s: disabled\n", clkdm->name);
 
diff --git a/arch/arm/mach-omap2/clockdomain.h b/arch/arm/mach-omap2/clockdomain.h
index bc42446..2da3765 100644
--- a/arch/arm/mach-omap2/clockdomain.h
+++ b/arch/arm/mach-omap2/clockdomain.h
@@ -15,7 +15,6 @@
 #define __ARCH_ARM_MACH_OMAP2_CLOCKDOMAIN_H
 
 #include <linux/init.h>
-#include <linux/spinlock.h>
 
 #include "powerdomain.h"
 #include "clock.h"
@@ -92,8 +91,8 @@
 struct clkdm_dep {
 	const char *clkdm_name;
 	struct clockdomain *clkdm;
-	atomic_t wkdep_usecount;
-	atomic_t sleepdep_usecount;
+	s16 wkdep_usecount;
+	s16 sleepdep_usecount;
 };
 
 /* Possible flags for struct clockdomain._flags */
@@ -137,9 +136,8 @@
 	const u16 clkdm_offs;
 	struct clkdm_dep *wkdep_srcs;
 	struct clkdm_dep *sleepdep_srcs;
-	atomic_t usecount;
+	int usecount;
 	struct list_head node;
-	spinlock_t lock;
 };
 
 /**
@@ -196,12 +194,16 @@
 int clkdm_read_sleepdep(struct clockdomain *clkdm1, struct clockdomain *clkdm2);
 int clkdm_clear_all_sleepdeps(struct clockdomain *clkdm);
 
+void clkdm_allow_idle_nolock(struct clockdomain *clkdm);
 void clkdm_allow_idle(struct clockdomain *clkdm);
+void clkdm_deny_idle_nolock(struct clockdomain *clkdm);
 void clkdm_deny_idle(struct clockdomain *clkdm);
 bool clkdm_in_hwsup(struct clockdomain *clkdm);
 bool clkdm_missing_idle_reporting(struct clockdomain *clkdm);
 
+int clkdm_wakeup_nolock(struct clockdomain *clkdm);
 int clkdm_wakeup(struct clockdomain *clkdm);
+int clkdm_sleep_nolock(struct clockdomain *clkdm);
 int clkdm_sleep(struct clockdomain *clkdm);
 
 int clkdm_clk_enable(struct clockdomain *clkdm, struct clk *clk);
@@ -214,8 +216,9 @@
 extern void __init omap3xxx_clockdomains_init(void);
 extern void __init am33xx_clockdomains_init(void);
 extern void __init omap44xx_clockdomains_init(void);
-extern void _clkdm_add_autodeps(struct clockdomain *clkdm);
-extern void _clkdm_del_autodeps(struct clockdomain *clkdm);
+
+extern void clkdm_add_autodeps(struct clockdomain *clkdm);
+extern void clkdm_del_autodeps(struct clockdomain *clkdm);
 
 extern struct clkdm_ops omap2_clkdm_operations;
 extern struct clkdm_ops omap3_clkdm_operations;
diff --git a/arch/arm/mach-omap2/cm2xxx.c b/arch/arm/mach-omap2/cm2xxx.c
index db65069..6774a53 100644
--- a/arch/arm/mach-omap2/cm2xxx.c
+++ b/arch/arm/mach-omap2/cm2xxx.c
@@ -273,9 +273,6 @@
 
 static void omap2xxx_clkdm_allow_idle(struct clockdomain *clkdm)
 {
-	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_add_autodeps(clkdm);
-
 	omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 				       clkdm->clktrctrl_mask);
 }
@@ -284,9 +281,6 @@
 {
 	omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					clkdm->clktrctrl_mask);
-
-	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_del_autodeps(clkdm);
 }
 
 static int omap2xxx_clkdm_clk_enable(struct clockdomain *clkdm)
@@ -298,18 +292,8 @@
 
 	hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					      clkdm->clktrctrl_mask);
-
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-		_clkdm_add_autodeps(clkdm);
-		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	} else {
-		if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
-			omap2xxx_clkdm_wakeup(clkdm);
-	}
+	if (!hwsup && clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+		omap2xxx_clkdm_wakeup(clkdm);
 
 	return 0;
 }
@@ -324,17 +308,8 @@
 	hwsup = omap2xxx_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					      clkdm->clktrctrl_mask);
 
-	if (hwsup) {
-		/* Disable HW transitions when we are changing deps */
-		omap2xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-						clkdm->clktrctrl_mask);
-		_clkdm_del_autodeps(clkdm);
-		omap2xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
-					       clkdm->clktrctrl_mask);
-	} else {
-		if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
-			omap2xxx_clkdm_sleep(clkdm);
-	}
+	if (!hwsup && clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+		omap2xxx_clkdm_sleep(clkdm);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/cm3xxx.c b/arch/arm/mach-omap2/cm3xxx.c
index c2086f2..9061c30 100644
--- a/arch/arm/mach-omap2/cm3xxx.c
+++ b/arch/arm/mach-omap2/cm3xxx.c
@@ -186,7 +186,7 @@
 			continue; /* only happens if data is erroneous */
 
 		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->sleepdep_usecount, 0);
+		cd->sleepdep_usecount = 0;
 	}
 	omap2_cm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
 				    OMAP3430_CM_SLEEPDEP);
@@ -209,8 +209,8 @@
 
 static void omap3xxx_clkdm_allow_idle(struct clockdomain *clkdm)
 {
-	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_add_autodeps(clkdm);
+	if (clkdm->usecount > 0)
+		clkdm_add_autodeps(clkdm);
 
 	omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 				       clkdm->clktrctrl_mask);
@@ -221,8 +221,8 @@
 	omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					clkdm->clktrctrl_mask);
 
-	if (atomic_read(&clkdm->usecount) > 0)
-		_clkdm_del_autodeps(clkdm);
+	if (clkdm->usecount > 0)
+		clkdm_del_autodeps(clkdm);
 }
 
 static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
@@ -250,7 +250,7 @@
 		/* Disable HW transitions when we are changing deps */
 		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 						clkdm->clktrctrl_mask);
-		_clkdm_add_autodeps(clkdm);
+		clkdm_add_autodeps(clkdm);
 		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					       clkdm->clktrctrl_mask);
 	} else {
@@ -287,7 +287,7 @@
 		/* Disable HW transitions when we are changing deps */
 		omap3xxx_cm_clkdm_disable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 						clkdm->clktrctrl_mask);
-		_clkdm_del_autodeps(clkdm);
+		clkdm_del_autodeps(clkdm);
 		omap3xxx_cm_clkdm_enable_hwsup(clkdm->pwrdm.ptr->prcm_offs,
 					       clkdm->clktrctrl_mask);
 	} else {
diff --git a/arch/arm/mach-omap2/cminst44xx.c b/arch/arm/mach-omap2/cminst44xx.c
index 7f9a464..f0290f5 100644
--- a/arch/arm/mach-omap2/cminst44xx.c
+++ b/arch/arm/mach-omap2/cminst44xx.c
@@ -393,7 +393,7 @@
 			continue; /* only happens if data is erroneous */
 
 		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
+		cd->wkdep_usecount = 0;
 	}
 
 	omap4_cminst_clear_inst_reg_bits(mask, clkdm->prcm_partition,
diff --git a/arch/arm/mach-omap2/common.h b/arch/arm/mach-omap2/common.h
index 948bcaa..b435027 100644
--- a/arch/arm/mach-omap2/common.h
+++ b/arch/arm/mach-omap2/common.h
@@ -79,13 +79,13 @@
 
 extern void omap2_init_common_infrastructure(void);
 
-extern struct sys_timer omap2_timer;
-extern struct sys_timer omap3_timer;
-extern struct sys_timer omap3_secure_timer;
-extern struct sys_timer omap3_gp_timer;
-extern struct sys_timer omap3_am33xx_timer;
-extern struct sys_timer omap4_timer;
-extern struct sys_timer omap5_timer;
+extern void omap2_sync32k_timer_init(void);
+extern void omap3_sync32k_timer_init(void);
+extern void omap3_secure_sync32k_timer_init(void);
+extern void omap3_gp_gptimer_timer_init(void);
+extern void omap3_am33xx_gptimer_timer_init(void);
+extern void omap4_local_timer_init(void);
+extern void omap5_realtime_timer_init(void);
 
 void omap2420_init_early(void);
 void omap2430_init_early(void);
diff --git a/arch/arm/mach-omap2/cpuidle34xx.c b/arch/arm/mach-omap2/cpuidle34xx.c
index 22590db..80392fc 100644
--- a/arch/arm/mach-omap2/cpuidle34xx.c
+++ b/arch/arm/mach-omap2/cpuidle34xx.c
@@ -36,40 +36,66 @@
 
 /* Mach specific information to be recorded in the C-state driver_data */
 struct omap3_idle_statedata {
-	u32 mpu_state;
-	u32 core_state;
+	u8 mpu_state;
+	u8 core_state;
+	u8 per_min_state;
+	u8 flags;
 };
 
 static struct powerdomain *mpu_pd, *core_pd, *per_pd, *cam_pd;
 
+/*
+ * Possible flag bits for struct omap3_idle_statedata.flags:
+ *
+ * OMAP_CPUIDLE_CX_NO_CLKDM_IDLE: don't allow the MPU clockdomain to go
+ *    inactive.  This in turn prevents the MPU DPLL from entering autoidle
+ *    mode, so wakeup latency is greatly reduced, at the cost of additional
+ *    energy consumption.  This also prevents the CORE clockdomain from
+ *    entering idle.
+ */
+#define OMAP_CPUIDLE_CX_NO_CLKDM_IDLE		BIT(0)
+
+/*
+ * Prevent PER OFF if CORE is not in RETention or OFF as this would
+ * disable PER wakeups completely.
+ */
 static struct omap3_idle_statedata omap3_idle_data[] = {
 	{
 		.mpu_state = PWRDM_POWER_ON,
 		.core_state = PWRDM_POWER_ON,
+		/* In C1 do not allow PER state lower than CORE state */
+		.per_min_state = PWRDM_POWER_ON,
+		.flags = OMAP_CPUIDLE_CX_NO_CLKDM_IDLE,
 	},
 	{
 		.mpu_state = PWRDM_POWER_ON,
 		.core_state = PWRDM_POWER_ON,
+		.per_min_state = PWRDM_POWER_RET,
 	},
 	{
 		.mpu_state = PWRDM_POWER_RET,
 		.core_state = PWRDM_POWER_ON,
+		.per_min_state = PWRDM_POWER_RET,
 	},
 	{
 		.mpu_state = PWRDM_POWER_OFF,
 		.core_state = PWRDM_POWER_ON,
+		.per_min_state = PWRDM_POWER_RET,
 	},
 	{
 		.mpu_state = PWRDM_POWER_RET,
 		.core_state = PWRDM_POWER_RET,
+		.per_min_state = PWRDM_POWER_OFF,
 	},
 	{
 		.mpu_state = PWRDM_POWER_OFF,
 		.core_state = PWRDM_POWER_RET,
+		.per_min_state = PWRDM_POWER_OFF,
 	},
 	{
 		.mpu_state = PWRDM_POWER_OFF,
 		.core_state = PWRDM_POWER_OFF,
+		.per_min_state = PWRDM_POWER_OFF,
 	},
 };
 
@@ -80,27 +106,25 @@
 				int index)
 {
 	struct omap3_idle_statedata *cx = &omap3_idle_data[index];
-	u32 mpu_state = cx->mpu_state, core_state = cx->core_state;
 
 	local_fiq_disable();
 
-	pwrdm_set_next_pwrst(mpu_pd, mpu_state);
-	pwrdm_set_next_pwrst(core_pd, core_state);
-
 	if (omap_irq_pending() || need_resched())
 		goto return_sleep_time;
 
 	/* Deny idle for C1 */
-	if (index == 0) {
+	if (cx->flags & OMAP_CPUIDLE_CX_NO_CLKDM_IDLE) {
 		clkdm_deny_idle(mpu_pd->pwrdm_clkdms[0]);
-		clkdm_deny_idle(core_pd->pwrdm_clkdms[0]);
+	} else {
+		pwrdm_set_next_pwrst(mpu_pd, cx->mpu_state);
+		pwrdm_set_next_pwrst(core_pd, cx->core_state);
 	}
 
 	/*
 	 * Call idle CPU PM enter notifier chain so that
 	 * VFP context is saved.
 	 */
-	if (mpu_state == PWRDM_POWER_OFF)
+	if (cx->mpu_state == PWRDM_POWER_OFF)
 		cpu_pm_enter();
 
 	/* Execute ARM wfi */
@@ -110,17 +134,15 @@
 	 * Call idle CPU PM enter notifier chain to restore
 	 * VFP context.
 	 */
-	if (pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF)
+	if (cx->mpu_state == PWRDM_POWER_OFF &&
+	    pwrdm_read_prev_pwrst(mpu_pd) == PWRDM_POWER_OFF)
 		cpu_pm_exit();
 
 	/* Re-allow idle for C1 */
-	if (index == 0) {
+	if (cx->flags & OMAP_CPUIDLE_CX_NO_CLKDM_IDLE)
 		clkdm_allow_idle(mpu_pd->pwrdm_clkdms[0]);
-		clkdm_allow_idle(core_pd->pwrdm_clkdms[0]);
-	}
 
 return_sleep_time:
-
 	local_fiq_enable();
 
 	return index;
@@ -185,7 +207,7 @@
 	 * Start search from the next (lower) state.
 	 */
 	for (idx = index - 1; idx >= 0; idx--) {
-		cx =  &omap3_idle_data[idx];
+		cx = &omap3_idle_data[idx];
 		if ((cx->mpu_state >= mpu_deepest_state) &&
 		    (cx->core_state >= core_deepest_state)) {
 			next_index = idx;
@@ -209,10 +231,9 @@
 			       struct cpuidle_driver *drv,
 			       int index)
 {
-	int new_state_idx;
-	u32 core_next_state, per_next_state = 0, per_saved_state = 0;
+	int new_state_idx, ret;
+	u8 per_next_state, per_saved_state;
 	struct omap3_idle_statedata *cx;
-	int ret;
 
 	/*
 	 * Use only C1 if CAM is active.
@@ -233,25 +254,13 @@
 
 	/* Program PER state */
 	cx = &omap3_idle_data[new_state_idx];
-	core_next_state = cx->core_state;
-	per_next_state = per_saved_state = pwrdm_read_next_pwrst(per_pd);
-	if (new_state_idx == 0) {
-		/* In C1 do not allow PER state lower than CORE state */
-		if (per_next_state < core_next_state)
-			per_next_state = core_next_state;
-	} else {
-		/*
-		 * Prevent PER OFF if CORE is not in RETention or OFF as this
-		 * would disable PER wakeups completely.
-		 */
-		if ((per_next_state == PWRDM_POWER_OFF) &&
-		    (core_next_state > PWRDM_POWER_RET))
-			per_next_state = PWRDM_POWER_RET;
-	}
 
-	/* Are we changing PER target state? */
-	if (per_next_state != per_saved_state)
+	per_next_state = pwrdm_read_next_pwrst(per_pd);
+	per_saved_state = per_next_state;
+	if (per_next_state < cx->per_min_state) {
+		per_next_state = cx->per_min_state;
 		pwrdm_set_next_pwrst(per_pd, per_next_state);
+	}
 
 	ret = omap3_enter_idle(dev, drv, new_state_idx);
 
diff --git a/arch/arm/mach-omap2/devices.c b/arch/arm/mach-omap2/devices.c
index 5e304d0..d8a0cc3 100644
--- a/arch/arm/mach-omap2/devices.c
+++ b/arch/arm/mach-omap2/devices.c
@@ -61,8 +61,7 @@
 	if (!oh)
 		pr_err("could not look up %s\n", oh_name);
 
-	pdev = omap_device_build("omap_l3_smx", 0, oh, NULL, 0,
-							   NULL, 0, 0);
+	pdev = omap_device_build("omap_l3_smx", 0, oh, NULL, 0);
 
 	WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
 
@@ -96,8 +95,7 @@
 			pr_err("could not look up %s\n", oh_name);
 	}
 
-	pdev = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL,
-						     0, NULL, 0, 0);
+	pdev = omap_device_build_ss("omap_l3_noc", 0, oh, 3, NULL, 0);
 
 	WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
 
@@ -273,7 +271,7 @@
 	keypad_data = sdp4430_keypad_data;
 
 	pdev = omap_device_build(name, id, oh, keypad_data,
-			sizeof(struct omap4_keypad_platform_data), NULL, 0, 0);
+				 sizeof(struct omap4_keypad_platform_data));
 
 	if (IS_ERR(pdev)) {
 		WARN(1, "Can't build omap_device for %s:%s.\n",
@@ -297,7 +295,7 @@
 		return;
 	}
 
-	pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0, NULL, 0, 0);
+	pdev = omap_device_build("omap-mailbox", -1, oh, NULL, 0);
 	WARN(IS_ERR(pdev), "%s: could not build device, err %ld\n",
 						__func__, PTR_ERR(pdev));
 }
@@ -337,7 +335,7 @@
 		return;
 	}
 
-	pdev = omap_device_build("omap-mcpdm", -1, oh, NULL, 0, NULL, 0, 0);
+	pdev = omap_device_build("omap-mcpdm", -1, oh, NULL, 0);
 	WARN(IS_ERR(pdev), "Can't build omap_device for omap-mcpdm.\n");
 }
 #else
@@ -358,7 +356,7 @@
 		return;
 	}
 
-	pdev = omap_device_build("omap-dmic", -1, oh, NULL, 0, NULL, 0, 0);
+	pdev = omap_device_build("omap-dmic", -1, oh, NULL, 0);
 	WARN(IS_ERR(pdev), "Can't build omap_device for omap-dmic.\n");
 }
 #else
@@ -384,8 +382,7 @@
 		return;
 	}
 
-	pdev = omap_device_build("omap-hdmi-audio-dai",
-		-1, oh, NULL, 0, NULL, 0, 0);
+	pdev = omap_device_build("omap-hdmi-audio-dai", -1, oh, NULL, 0, 0);
 	WARN(IS_ERR(pdev),
 	     "Can't build omap_device for omap-hdmi-audio-dai.\n");
 
@@ -429,8 +426,7 @@
 	}
 
 	spi_num++;
-	pdev = omap_device_build(name, spi_num, oh, pdata,
-				sizeof(*pdata),	NULL, 0, 0);
+	pdev = omap_device_build(name, spi_num, oh, pdata, sizeof(*pdata));
 	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s\n",
 				name, oh->name);
 	kfree(pdata);
@@ -460,7 +456,7 @@
 	if (!oh)
 		return;
 
-	pdev = omap_device_build("omap_rng", -1, oh, NULL, 0, NULL, 0, 0);
+	pdev = omap_device_build("omap_rng", -1, oh, NULL, 0);
 	WARN(IS_ERR(pdev), "Can't build omap_device for omap_rng\n");
 }
 
@@ -639,7 +635,7 @@
 	return cnt;
 }
 
-static void omap_init_ocp2scp(void)
+static void __init omap_init_ocp2scp(void)
 {
 	struct omap_hwmod	*oh;
 	struct platform_device	*pdev;
@@ -689,8 +685,7 @@
 
 	pdata->dev_cnt	= dev_cnt;
 
-	pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(*pdata), NULL,
-								0, false);
+	pdev = omap_device_build(name, bus_id, oh, pdata, sizeof(*pdata));
 	if (IS_ERR(pdev)) {
 		pr_err("Could not build omap_device for %s %s\n",
 						name, oh_name);
diff --git a/arch/arm/mach-omap2/display.c b/arch/arm/mach-omap2/display.c
index cc75aaf..ff37be1 100644
--- a/arch/arm/mach-omap2/display.c
+++ b/arch/arm/mach-omap2/display.c
@@ -226,7 +226,7 @@
 		dev_set_name(&pdev->dev, "%s", pdev->name);
 
 	ohs[0] = oh;
-	od = omap_device_alloc(pdev, ohs, 1, NULL, 0);
+	od = omap_device_alloc(pdev, ohs, 1);
 	if (IS_ERR(od)) {
 		pr_err("Could not alloc omap_device for %s\n", pdev_name);
 		r = -ENOMEM;
diff --git a/arch/arm/mach-omap2/dma.c b/arch/arm/mach-omap2/dma.c
index 612b982..491c5c8 100644
--- a/arch/arm/mach-omap2/dma.c
+++ b/arch/arm/mach-omap2/dma.c
@@ -248,7 +248,7 @@
 
 	p->errata		= configure_dma_errata();
 
-	pdev = omap_device_build(name, 0, oh, p, sizeof(*p), NULL, 0, 0);
+	pdev = omap_device_build(name, 0, oh, p, sizeof(*p));
 	kfree(p);
 	if (IS_ERR(pdev)) {
 		pr_err("%s: Can't build omap_device for %s:%s.\n",
diff --git a/arch/arm/mach-omap2/drm.c b/arch/arm/mach-omap2/drm.c
index 4c7566c..4d8d1a5 100644
--- a/arch/arm/mach-omap2/drm.c
+++ b/arch/arm/mach-omap2/drm.c
@@ -25,6 +25,7 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/omap_drm.h>
 
+#include "soc.h"
 #include "omap_device.h"
 #include "omap_hwmod.h"
 
@@ -50,13 +51,12 @@
 	oh = omap_hwmod_lookup("dmm");
 
 	if (oh) {
-		pdev = omap_device_build(oh->name, -1, oh, NULL, 0, NULL, 0,
-					false);
+		pdev = omap_device_build(oh->name, -1, oh, NULL, 0);
 		WARN(IS_ERR(pdev), "Could not build omap_device for %s\n",
 			oh->name);
 	}
 
-	platform_data.omaprev = GET_OMAP_REVISION();
+	platform_data.omaprev = GET_OMAP_TYPE;
 
 	return platform_device_register(&omap_drm_device);
 
diff --git a/arch/arm/mach-omap2/gpio.c b/arch/arm/mach-omap2/gpio.c
index 399acab..482ade1 100644
--- a/arch/arm/mach-omap2/gpio.c
+++ b/arch/arm/mach-omap2/gpio.c
@@ -131,8 +131,7 @@
 	pwrdm = omap_hwmod_get_pwrdm(oh);
 	pdata->loses_context = pwrdm_can_ever_lose_context(pwrdm);
 
-	pdev = omap_device_build(name, id - 1, oh, pdata,
-				sizeof(*pdata),	NULL, 0, false);
+	pdev = omap_device_build(name, id - 1, oh, pdata, sizeof(*pdata));
 	kfree(pdata);
 
 	if (IS_ERR(pdev)) {
diff --git a/arch/arm/mach-omap2/gpmc.c b/arch/arm/mach-omap2/gpmc.c
index 8033cb7..bc07833 100644
--- a/arch/arm/mach-omap2/gpmc.c
+++ b/arch/arm/mach-omap2/gpmc.c
@@ -1220,7 +1220,7 @@
 		return -ENODEV;
 	}
 
-	pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0, NULL, 0, 0);
+	pdev = omap_device_build(DEVICE_NAME, -1, oh, NULL, 0);
 	WARN(IS_ERR(pdev), "could not build omap_device for %s\n", oh_name);
 
 	return IS_ERR(pdev) ? PTR_ERR(pdev) : 0;
diff --git a/arch/arm/mach-omap2/hdq1w.c b/arch/arm/mach-omap2/hdq1w.c
index ab7bf18..b7aa8ba 100644
--- a/arch/arm/mach-omap2/hdq1w.c
+++ b/arch/arm/mach-omap2/hdq1w.c
@@ -87,7 +87,7 @@
 	if (!oh)
 		return 0;
 
-	pdev = omap_device_build(devname, id, oh, NULL, 0, NULL, 0, 0);
+	pdev = omap_device_build(devname, id, oh, NULL, 0);
 	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
 	     devname, oh->name);
 
diff --git a/arch/arm/mach-omap2/hsmmc.c b/arch/arm/mach-omap2/hsmmc.c
index 4a96433..2ef1f87 100644
--- a/arch/arm/mach-omap2/hsmmc.c
+++ b/arch/arm/mach-omap2/hsmmc.c
@@ -522,7 +522,7 @@
 	}
 	dev_set_name(&pdev->dev, "%s.%d", pdev->name, pdev->id);
 
-	od = omap_device_alloc(pdev, ohs, 1, NULL, 0);
+	od = omap_device_alloc(pdev, ohs, 1);
 	if (IS_ERR(od)) {
 		pr_err("Could not allocate od for %s\n", name);
 		goto put_pdev;
diff --git a/arch/arm/mach-omap2/hwspinlock.c b/arch/arm/mach-omap2/hwspinlock.c
index 1df9b5f..c368890 100644
--- a/arch/arm/mach-omap2/hwspinlock.c
+++ b/arch/arm/mach-omap2/hwspinlock.c
@@ -46,8 +46,7 @@
 		return -EINVAL;
 
 	pdev = omap_device_build(dev_name, 0, oh, &omap_hwspinlock_pdata,
-				sizeof(struct hwspinlock_pdata),
-				NULL, 0, false);
+				sizeof(struct hwspinlock_pdata));
 	if (IS_ERR(pdev)) {
 		pr_err("Can't build omap_device for %s:%s\n", dev_name,
 								oh_name);
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
index b9074dd..c11a23f 100644
--- a/arch/arm/mach-omap2/i2c.c
+++ b/arch/arm/mach-omap2/i2c.c
@@ -178,8 +178,7 @@
 	if (cpu_is_omap34xx())
 		pdata->set_mpu_wkup_lat = omap_pm_set_max_mpu_wakeup_lat_compat;
 	pdev = omap_device_build(name, bus_id, oh, pdata,
-			sizeof(struct omap_i2c_bus_platform_data),
-			NULL, 0, 0);
+				 sizeof(struct omap_i2c_bus_platform_data));
 	WARN(IS_ERR(pdev), "Could not build omap_device for %s\n", name);
 
 	return PTR_RET(pdev);
diff --git a/arch/arm/mach-omap2/mcbsp.c b/arch/arm/mach-omap2/mcbsp.c
index df49f2a4..4535804 100644
--- a/arch/arm/mach-omap2/mcbsp.c
+++ b/arch/arm/mach-omap2/mcbsp.c
@@ -101,7 +101,7 @@
 		count++;
 	}
 	pdev = omap_device_build_ss(name, id, oh_device, count, pdata,
-				sizeof(*pdata), NULL, 0, false);
+				    sizeof(*pdata));
 	kfree(pdata);
 	if (IS_ERR(pdev))  {
 		pr_err("%s: Can't build omap_device for %s:%s.\n", __func__,
diff --git a/arch/arm/mach-omap2/msdi.c b/arch/arm/mach-omap2/msdi.c
index aafdd4c..c52d8b4 100644
--- a/arch/arm/mach-omap2/msdi.c
+++ b/arch/arm/mach-omap2/msdi.c
@@ -150,7 +150,7 @@
 		return;
 	}
 	pdev = omap_device_build(dev_name, id, oh, mmc_data[0],
-				 sizeof(struct omap_mmc_platform_data), NULL, 0, 0);
+				 sizeof(struct omap_mmc_platform_data));
 	if (IS_ERR(pdev))
 		WARN(1, "Can'd build omap_device for %s:%s.\n",
 					dev_name, oh->name);
diff --git a/arch/arm/mach-omap2/omap-iommu.c b/arch/arm/mach-omap2/omap-iommu.c
index 6da4f7a..f7f38c7 100644
--- a/arch/arm/mach-omap2/omap-iommu.c
+++ b/arch/arm/mach-omap2/omap-iommu.c
@@ -41,8 +41,7 @@
 		pdata->deassert_reset = omap_device_deassert_hardreset;
 	}
 
-	pdev = omap_device_build("omap-iommu", i, oh, pdata, sizeof(*pdata),
-				NULL, 0, 0);
+	pdev = omap_device_build("omap-iommu", i, oh, pdata, sizeof(*pdata));
 
 	kfree(pdata);
 
diff --git a/arch/arm/mach-omap2/omap-mpuss-lowpower.c b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
index aac46bf..8bcb64b 100644
--- a/arch/arm/mach-omap2/omap-mpuss-lowpower.c
+++ b/arch/arm/mach-omap2/omap-mpuss-lowpower.c
@@ -87,37 +87,6 @@
 }
 
 /*
- * Set the CPUx powerdomain's previous power state
- */
-static inline void set_cpu_next_pwrst(unsigned int cpu_id,
-				unsigned int power_state)
-{
-	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
-
-	pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
-}
-
-/*
- * Read CPU's previous power state
- */
-static inline unsigned int read_cpu_prev_pwrst(unsigned int cpu_id)
-{
-	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
-
-	return pwrdm_read_prev_pwrst(pm_info->pwrdm);
-}
-
-/*
- * Clear the CPUx powerdomain's previous power state
- */
-static inline void clear_cpu_prev_pwrst(unsigned int cpu_id)
-{
-	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu_id);
-
-	pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
-}
-
-/*
  * Store the SCU power status value to scratchpad memory
  */
 static void scu_pwrst_prepare(unsigned int cpu_id, unsigned int cpu_state)
@@ -230,6 +199,7 @@
  */
 int omap4_enter_lowpower(unsigned int cpu, unsigned int power_state)
 {
+	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
 	unsigned int save_state = 0;
 	unsigned int wakeup_cpu;
 
@@ -268,7 +238,7 @@
 		save_state = 2;
 
 	cpu_clear_prev_logic_pwrst(cpu);
-	set_cpu_next_pwrst(cpu, power_state);
+	pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
 	set_cpu_wakeup_addr(cpu, virt_to_phys(omap4_cpu_resume));
 	scu_pwrst_prepare(cpu, power_state);
 	l2x0_pwrst_prepare(cpu, save_state);
@@ -286,7 +256,7 @@
 	 * domain transition
 	 */
 	wakeup_cpu = smp_processor_id();
-	set_cpu_next_pwrst(wakeup_cpu, PWRDM_POWER_ON);
+	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
 
 	pwrdm_post_transition(NULL);
 
@@ -300,8 +270,8 @@
  */
 int __cpuinit omap4_hotplug_cpu(unsigned int cpu, unsigned int power_state)
 {
-	unsigned int cpu_state = 0;
 	struct omap4_cpu_pm_info *pm_info = &per_cpu(omap4_pm_info, cpu);
+	unsigned int cpu_state = 0;
 
 	if (omap_rev() == OMAP4430_REV_ES1_0)
 		return -ENXIO;
@@ -309,8 +279,8 @@
 	if (power_state == PWRDM_POWER_OFF)
 		cpu_state = 1;
 
-	clear_cpu_prev_pwrst(cpu);
-	set_cpu_next_pwrst(cpu, power_state);
+	pwrdm_clear_all_prev_pwrst(pm_info->pwrdm);
+	pwrdm_set_next_pwrst(pm_info->pwrdm, power_state);
 	set_cpu_wakeup_addr(cpu, virt_to_phys(pm_info->secondary_startup));
 	scu_pwrst_prepare(cpu, power_state);
 
@@ -321,7 +291,7 @@
 	 */
 	omap4_finish_suspend(cpu_state);
 
-	set_cpu_next_pwrst(cpu, PWRDM_POWER_ON);
+	pwrdm_set_next_pwrst(pm_info->pwrdm, PWRDM_POWER_ON);
 	return 0;
 }
 
diff --git a/arch/arm/mach-omap2/omap-smp.c b/arch/arm/mach-omap2/omap-smp.c
index cd42d92..d972721 100644
--- a/arch/arm/mach-omap2/omap-smp.c
+++ b/arch/arm/mach-omap2/omap-smp.c
@@ -19,9 +19,9 @@
 #include <linux/device.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include <asm/cacheflush.h>
-#include <asm/hardware/gic.h>
 #include <asm/smp_scu.h>
 
 #include "omap-secure.h"
@@ -157,7 +157,7 @@
 		booted = true;
 	}
 
-	gic_raise_softirq(cpumask_of(cpu), 0);
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 
 	/*
 	 * Now the secondary core is starting up let it run its
@@ -215,7 +215,7 @@
 		 * Currently we can't call ioremap here because
 		 * SoC detection won't work until after init_early.
 		 */
-		scu_base =  OMAP2_L4_IO_ADDRESS(OMAP44XX_SCU_BASE);
+		scu_base =  OMAP2_L4_IO_ADDRESS(scu_a9_get_base());
 		BUG_ON(!scu_base);
 		ncores = scu_get_core_count(scu_base);
 	} else if (cpu_id == CPU_CORTEX_A15) {
@@ -231,8 +231,6 @@
 
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
 
 static void __init omap4_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-omap2/omap-wakeupgen.c b/arch/arm/mach-omap2/omap-wakeupgen.c
index 5d3b4f4..8c5b5e3 100644
--- a/arch/arm/mach-omap2/omap-wakeupgen.c
+++ b/arch/arm/mach-omap2/omap-wakeupgen.c
@@ -24,8 +24,7 @@
 #include <linux/cpu.h>
 #include <linux/notifier.h>
 #include <linux/cpu_pm.h>
-
-#include <asm/hardware/gic.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include "omap-wakeupgen.h"
 #include "omap-secure.h"
diff --git a/arch/arm/mach-omap2/omap4-common.c b/arch/arm/mach-omap2/omap4-common.c
index 6897ae2..5470948 100644
--- a/arch/arm/mach-omap2/omap4-common.c
+++ b/arch/arm/mach-omap2/omap4-common.c
@@ -15,13 +15,14 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/platform_device.h>
 #include <linux/memblock.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/export.h>
+#include <linux/irqchip/arm-gic.h>
 
-#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/mach/map.h>
 #include <asm/memblock.h>
@@ -255,16 +256,10 @@
 }
 early_initcall(omap4_sar_ram_init);
 
-static struct of_device_id irq_match[] __initdata = {
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-	{ .compatible = "arm,cortex-a15-gic", .data = gic_of_init, },
-	{ }
-};
-
 void __init omap_gic_of_init(void)
 {
 	omap_wakeupgen_init();
-	of_irq_init(irq_match);
+	irqchip_init();
 }
 
 #if defined(CONFIG_MMC_OMAP_HS) || defined(CONFIG_MMC_OMAP_HS_MODULE)
diff --git a/arch/arm/mach-omap2/omap44xx.h b/arch/arm/mach-omap2/omap44xx.h
index 43b927b..8a515bb 100644
--- a/arch/arm/mach-omap2/omap44xx.h
+++ b/arch/arm/mach-omap2/omap44xx.h
@@ -40,7 +40,6 @@
 #define OMAP44XX_GIC_DIST_BASE		0x48241000
 #define OMAP44XX_GIC_CPU_BASE		0x48240100
 #define OMAP44XX_IRQ_GIC_START		32
-#define OMAP44XX_SCU_BASE		0x48240000
 #define OMAP44XX_LOCAL_TWD_BASE		0x48240600
 #define OMAP44XX_L2CACHE_BASE		0x48242000
 #define OMAP44XX_WKUPGEN_BASE		0x48281000
diff --git a/arch/arm/mach-omap2/omap_device.c b/arch/arm/mach-omap2/omap_device.c
index e065daa..6ee3ad3 100644
--- a/arch/arm/mach-omap2/omap_device.c
+++ b/arch/arm/mach-omap2/omap_device.c
@@ -17,68 +17,15 @@
  * to control power management and interconnect properties of their
  * devices.
  *
- * In the medium- to long-term, this code should either be
- * a) implemented via arch-specific pointers in platform_data
- * or
- * b) implemented as a proper omap_bus/omap_device in Linux, no more
- *    platform_data func pointers
+ * In the medium- to long-term, this code should be implemented as a
+ * proper omap_bus/omap_device in Linux, no more platform_data func
+ * pointers
  *
  *
- * Guidelines for usage by driver authors:
- *
- * 1. These functions are intended to be used by device drivers via
- * function pointers in struct platform_data.  As an example,
- * omap_device_enable() should be passed to the driver as
- *
- * struct foo_driver_platform_data {
- * ...
- *      int (*device_enable)(struct platform_device *pdev);
- * ...
- * }
- *
- * Note that the generic "device_enable" name is used, rather than
- * "omap_device_enable".  This is so other architectures can pass in their
- * own enable/disable functions here.
- *
- * This should be populated during device setup:
- *
- * ...
- * pdata->device_enable = omap_device_enable;
- * ...
- *
- * 2. Drivers should first check to ensure the function pointer is not null
- * before calling it, as in:
- *
- * if (pdata->device_enable)
- *     pdata->device_enable(pdev);
- *
- * This allows other architectures that don't use similar device_enable()/
- * device_shutdown() functions to execute normally.
- *
- * ...
- *
- * Suggested usage by device drivers:
- *
- * During device initialization:
- * device_enable()
- *
- * During device idle:
- * (save remaining device context if necessary)
- * device_idle();
- *
- * During device resume:
- * device_enable();
- * (restore context if necessary)
- *
- * During device shutdown:
- * device_shutdown()
- * (device must be reinitialized at this point to use it again)
- *
  */
 #undef DEBUG
 
 #include <linux/kernel.h>
-#include <linux/export.h>
 #include <linux/platform_device.h>
 #include <linux/slab.h>
 #include <linux/err.h>
@@ -92,155 +39,8 @@
 #include "omap_device.h"
 #include "omap_hwmod.h"
 
-/* These parameters are passed to _omap_device_{de,}activate() */
-#define USE_WAKEUP_LAT			0
-#define IGNORE_WAKEUP_LAT		1
-
-static int omap_early_device_register(struct platform_device *pdev);
-
-static struct omap_device_pm_latency omap_default_latency[] = {
-	{
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func   = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	}
-};
-
 /* Private functions */
 
-/**
- * _omap_device_activate - increase device readiness
- * @od: struct omap_device *
- * @ignore_lat: increase to latency target (0) or full readiness (1)?
- *
- * Increase readiness of omap_device @od (thus decreasing device
- * wakeup latency, but consuming more power).  If @ignore_lat is
- * IGNORE_WAKEUP_LAT, make the omap_device fully active.  Otherwise,
- * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup
- * latency is greater than the requested maximum wakeup latency, step
- * backwards in the omap_device_pm_latency table to ensure the
- * device's maximum wakeup latency is less than or equal to the
- * requested maximum wakeup latency.  Returns 0.
- */
-static int _omap_device_activate(struct omap_device *od, u8 ignore_lat)
-{
-	struct timespec a, b, c;
-
-	dev_dbg(&od->pdev->dev, "omap_device: activating\n");
-
-	while (od->pm_lat_level > 0) {
-		struct omap_device_pm_latency *odpl;
-		unsigned long long act_lat = 0;
-
-		od->pm_lat_level--;
-
-		odpl = od->pm_lats + od->pm_lat_level;
-
-		if (!ignore_lat &&
-		    (od->dev_wakeup_lat <= od->_dev_wakeup_lat_limit))
-			break;
-
-		read_persistent_clock(&a);
-
-		/* XXX check return code */
-		odpl->activate_func(od);
-
-		read_persistent_clock(&b);
-
-		c = timespec_sub(b, a);
-		act_lat = timespec_to_ns(&c);
-
-		dev_dbg(&od->pdev->dev,
-			"omap_device: pm_lat %d: activate: elapsed time %llu nsec\n",
-			od->pm_lat_level, act_lat);
-
-		if (act_lat > odpl->activate_lat) {
-			odpl->activate_lat_worst = act_lat;
-			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
-				odpl->activate_lat = act_lat;
-				dev_dbg(&od->pdev->dev,
-					"new worst case activate latency %d: %llu\n",
-					od->pm_lat_level, act_lat);
-			} else
-				dev_warn(&od->pdev->dev,
-					 "activate latency %d higher than expected. (%llu > %d)\n",
-					 od->pm_lat_level, act_lat,
-					 odpl->activate_lat);
-		}
-
-		od->dev_wakeup_lat -= odpl->activate_lat;
-	}
-
-	return 0;
-}
-
-/**
- * _omap_device_deactivate - decrease device readiness
- * @od: struct omap_device *
- * @ignore_lat: decrease to latency target (0) or full inactivity (1)?
- *
- * Decrease readiness of omap_device @od (thus increasing device
- * wakeup latency, but conserving power).  If @ignore_lat is
- * IGNORE_WAKEUP_LAT, make the omap_device fully inactive.  Otherwise,
- * if @ignore_lat is USE_WAKEUP_LAT, and the device's maximum wakeup
- * latency is less than the requested maximum wakeup latency, step
- * forwards in the omap_device_pm_latency table to ensure the device's
- * maximum wakeup latency is less than or equal to the requested
- * maximum wakeup latency.  Returns 0.
- */
-static int _omap_device_deactivate(struct omap_device *od, u8 ignore_lat)
-{
-	struct timespec a, b, c;
-
-	dev_dbg(&od->pdev->dev, "omap_device: deactivating\n");
-
-	while (od->pm_lat_level < od->pm_lats_cnt) {
-		struct omap_device_pm_latency *odpl;
-		unsigned long long deact_lat = 0;
-
-		odpl = od->pm_lats + od->pm_lat_level;
-
-		if (!ignore_lat &&
-		    ((od->dev_wakeup_lat + odpl->activate_lat) >
-		     od->_dev_wakeup_lat_limit))
-			break;
-
-		read_persistent_clock(&a);
-
-		/* XXX check return code */
-		odpl->deactivate_func(od);
-
-		read_persistent_clock(&b);
-
-		c = timespec_sub(b, a);
-		deact_lat = timespec_to_ns(&c);
-
-		dev_dbg(&od->pdev->dev,
-			"omap_device: pm_lat %d: deactivate: elapsed time %llu nsec\n",
-			od->pm_lat_level, deact_lat);
-
-		if (deact_lat > odpl->deactivate_lat) {
-			odpl->deactivate_lat_worst = deact_lat;
-			if (odpl->flags & OMAP_DEVICE_LATENCY_AUTO_ADJUST) {
-				odpl->deactivate_lat = deact_lat;
-				dev_dbg(&od->pdev->dev,
-					"new worst case deactivate latency %d: %llu\n",
-					od->pm_lat_level, deact_lat);
-			} else
-				dev_warn(&od->pdev->dev,
-					 "deactivate latency %d higher than expected. (%llu > %d)\n",
-					 od->pm_lat_level, deact_lat,
-					 odpl->deactivate_lat);
-		}
-
-		od->dev_wakeup_lat += odpl->activate_lat;
-
-		od->pm_lat_level++;
-	}
-
-	return 0;
-}
-
 static void _add_clkdev(struct omap_device *od, const char *clk_alias,
 		       const char *clk_name)
 {
@@ -315,9 +115,6 @@
  * @oh: ptr to the single omap_hwmod that backs this omap_device
  * @pdata: platform_data ptr to associate with the platform_device
  * @pdata_len: amount of memory pointed to by @pdata
- * @pm_lats: pointer to a omap_device_pm_latency array for this device
- * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
- * @is_early_device: should the device be registered as an early device or not
  *
  * Function for building an omap_device already registered from device-tree
  *
@@ -356,7 +153,7 @@
 		hwmods[i] = oh;
 	}
 
-	od = omap_device_alloc(pdev, hwmods, oh_cnt, NULL, 0);
+	od = omap_device_alloc(pdev, hwmods, oh_cnt);
 	if (!od) {
 		dev_err(&pdev->dev, "Cannot allocate omap_device for :%s\n",
 			oh_name);
@@ -407,6 +204,39 @@
 	return NOTIFY_DONE;
 }
 
+/**
+ * _omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods
+ * @od: struct omap_device *od
+ *
+ * Enable all underlying hwmods.  Returns 0.
+ */
+static int _omap_device_enable_hwmods(struct omap_device *od)
+{
+	int i;
+
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_enable(od->hwmods[i]);
+
+	/* XXX pass along return value here? */
+	return 0;
+}
+
+/**
+ * _omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
+ * @od: struct omap_device *od
+ *
+ * Idle all underlying hwmods.  Returns 0.
+ */
+static int _omap_device_idle_hwmods(struct omap_device *od)
+{
+	int i;
+
+	for (i = 0; i < od->hwmods_cnt; i++)
+		omap_hwmod_idle(od->hwmods[i]);
+
+	/* XXX pass along return value here? */
+	return 0;
+}
 
 /* Public functions for use by core code */
 
@@ -526,18 +356,14 @@
  * @oh: ptr to the single omap_hwmod that backs this omap_device
  * @pdata: platform_data ptr to associate with the platform_device
  * @pdata_len: amount of memory pointed to by @pdata
- * @pm_lats: pointer to a omap_device_pm_latency array for this device
- * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
  *
  * Convenience function for allocating an omap_device structure and filling
- * hwmods, resources and pm_latency attributes.
+ * hwmods, and resources.
  *
  * Returns an struct omap_device pointer or ERR_PTR() on error;
  */
 struct omap_device *omap_device_alloc(struct platform_device *pdev,
-					struct omap_hwmod **ohs, int oh_cnt,
-					struct omap_device_pm_latency *pm_lats,
-					int pm_lats_cnt)
+					struct omap_hwmod **ohs, int oh_cnt)
 {
 	int ret = -ENOMEM;
 	struct omap_device *od;
@@ -626,18 +452,6 @@
 		goto oda_exit3;
 
 have_everything:
-	if (!pm_lats) {
-		pm_lats = omap_default_latency;
-		pm_lats_cnt = ARRAY_SIZE(omap_default_latency);
-	}
-
-	od->pm_lats_cnt = pm_lats_cnt;
-	od->pm_lats = kmemdup(pm_lats,
-			sizeof(struct omap_device_pm_latency) * pm_lats_cnt,
-			GFP_KERNEL);
-	if (!od->pm_lats)
-		goto oda_exit3;
-
 	pdev->archdata.od = od;
 
 	for (i = 0; i < oh_cnt; i++) {
@@ -663,7 +477,6 @@
 		return;
 
 	od->pdev->archdata.od = NULL;
-	kfree(od->pm_lats);
 	kfree(od->hwmods);
 	kfree(od);
 }
@@ -675,9 +488,6 @@
  * @oh: ptr to the single omap_hwmod that backs this omap_device
  * @pdata: platform_data ptr to associate with the platform_device
  * @pdata_len: amount of memory pointed to by @pdata
- * @pm_lats: pointer to a omap_device_pm_latency array for this device
- * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
- * @is_early_device: should the device be registered as an early device or not
  *
  * Convenience function for building and registering a single
  * omap_device record, which in turn builds and registers a
@@ -685,11 +495,10 @@
  * information.  Returns ERR_PTR(-EINVAL) if @oh is NULL; otherwise,
  * passes along the return value of omap_device_build_ss().
  */
-struct platform_device __init *omap_device_build(const char *pdev_name, int pdev_id,
-				      struct omap_hwmod *oh, void *pdata,
-				      int pdata_len,
-				      struct omap_device_pm_latency *pm_lats,
-				      int pm_lats_cnt, int is_early_device)
+struct platform_device __init *omap_device_build(const char *pdev_name,
+						 int pdev_id,
+						 struct omap_hwmod *oh,
+						 void *pdata, int pdata_len)
 {
 	struct omap_hwmod *ohs[] = { oh };
 
@@ -697,8 +506,7 @@
 		return ERR_PTR(-EINVAL);
 
 	return omap_device_build_ss(pdev_name, pdev_id, ohs, 1, pdata,
-				    pdata_len, pm_lats, pm_lats_cnt,
-				    is_early_device);
+				    pdata_len);
 }
 
 /**
@@ -708,9 +516,6 @@
  * @oh: ptr to the single omap_hwmod that backs this omap_device
  * @pdata: platform_data ptr to associate with the platform_device
  * @pdata_len: amount of memory pointed to by @pdata
- * @pm_lats: pointer to a omap_device_pm_latency array for this device
- * @pm_lats_cnt: ARRAY_SIZE() of @pm_lats
- * @is_early_device: should the device be registered as an early device or not
  *
  * Convenience function for building and registering an omap_device
  * subsystem record.  Subsystem records consist of multiple
@@ -718,11 +523,11 @@
  * platform_device record.  Returns an ERR_PTR() on error, or passes
  * along the return value of omap_device_register().
  */
-struct platform_device __init *omap_device_build_ss(const char *pdev_name, int pdev_id,
-					 struct omap_hwmod **ohs, int oh_cnt,
-					 void *pdata, int pdata_len,
-					 struct omap_device_pm_latency *pm_lats,
-					 int pm_lats_cnt, int is_early_device)
+struct platform_device __init *omap_device_build_ss(const char *pdev_name,
+						    int pdev_id,
+						    struct omap_hwmod **ohs,
+						    int oh_cnt, void *pdata,
+						    int pdata_len)
 {
 	int ret = -ENOMEM;
 	struct platform_device *pdev;
@@ -746,7 +551,7 @@
 	else
 		dev_set_name(&pdev->dev, "%s", pdev->name);
 
-	od = omap_device_alloc(pdev, ohs, oh_cnt, pm_lats, pm_lats_cnt);
+	od = omap_device_alloc(pdev, ohs, oh_cnt);
 	if (IS_ERR(od))
 		goto odbs_exit1;
 
@@ -754,10 +559,7 @@
 	if (ret)
 		goto odbs_exit2;
 
-	if (is_early_device)
-		ret = omap_early_device_register(pdev);
-	else
-		ret = omap_device_register(pdev);
+	ret = omap_device_register(pdev);
 	if (ret)
 		goto odbs_exit2;
 
@@ -774,24 +576,6 @@
 	return ERR_PTR(ret);
 }
 
-/**
- * omap_early_device_register - register an omap_device as an early platform
- * device.
- * @od: struct omap_device * to register
- *
- * Register the omap_device structure.  This currently just calls
- * platform_early_add_device() on the underlying platform_device.
- * Returns 0 by default.
- */
-static int __init omap_early_device_register(struct platform_device *pdev)
-{
-	struct platform_device *devices[1];
-
-	devices[0] = pdev;
-	early_platform_add_devices(devices, 1);
-	return 0;
-}
-
 #ifdef CONFIG_PM_RUNTIME
 static int _od_runtime_suspend(struct device *dev)
 {
@@ -902,10 +686,9 @@
  * to be accessible and ready to operate.  This generally involves
  * enabling clocks, setting SYSCONFIG registers; and in the future may
  * involve remuxing pins.  Device drivers should call this function
- * (through platform_data function pointers) where they would normally
- * enable clocks, etc.  Returns -EINVAL if called when the omap_device
- * is already enabled, or passes along the return value of
- * _omap_device_activate().
+ * indirectly via pm_runtime_get*().  Returns -EINVAL if called when
+ * the omap_device is already enabled, or passes along the return
+ * value of _omap_device_enable_hwmods().
  */
 int omap_device_enable(struct platform_device *pdev)
 {
@@ -921,14 +704,8 @@
 		return -EINVAL;
 	}
 
-	/* Enable everything if we're enabling this device from scratch */
-	if (od->_state == OMAP_DEVICE_STATE_UNKNOWN)
-		od->pm_lat_level = od->pm_lats_cnt;
+	ret = _omap_device_enable_hwmods(od);
 
-	ret = _omap_device_activate(od, IGNORE_WAKEUP_LAT);
-
-	od->dev_wakeup_lat = 0;
-	od->_dev_wakeup_lat_limit = UINT_MAX;
 	od->_state = OMAP_DEVICE_STATE_ENABLED;
 
 	return ret;
@@ -938,14 +715,10 @@
  * omap_device_idle - idle an omap_device
  * @od: struct omap_device * to idle
  *
- * Idle omap_device @od by calling as many .deactivate_func() entries
- * in the omap_device's pm_lats table as is possible without exceeding
- * the device's maximum wakeup latency limit, pm_lat_limit.  Device
- * drivers should call this function (through platform_data function
- * pointers) where they would normally disable clocks after operations
- * complete, etc..  Returns -EINVAL if the omap_device is not
+ * Idle omap_device @od.  Device drivers call this function indirectly
+ * via pm_runtime_put*().  Returns -EINVAL if the omap_device is not
  * currently enabled, or passes along the return value of
- * _omap_device_deactivate().
+ * _omap_device_idle_hwmods().
  */
 int omap_device_idle(struct platform_device *pdev)
 {
@@ -961,7 +734,7 @@
 		return -EINVAL;
 	}
 
-	ret = _omap_device_deactivate(od, USE_WAKEUP_LAT);
+	ret = _omap_device_idle_hwmods(od);
 
 	od->_state = OMAP_DEVICE_STATE_IDLE;
 
@@ -969,42 +742,6 @@
 }
 
 /**
- * omap_device_shutdown - shut down an omap_device
- * @od: struct omap_device * to shut down
- *
- * Shut down omap_device @od by calling all .deactivate_func() entries
- * in the omap_device's pm_lats table and then shutting down all of
- * the underlying omap_hwmods.  Used when a device is being "removed"
- * or a device driver is being unloaded.  Returns -EINVAL if the
- * omap_device is not currently enabled or idle, or passes along the
- * return value of _omap_device_deactivate().
- */
-int omap_device_shutdown(struct platform_device *pdev)
-{
-	int ret, i;
-	struct omap_device *od;
-
-	od = to_omap_device(pdev);
-
-	if (od->_state != OMAP_DEVICE_STATE_ENABLED &&
-	    od->_state != OMAP_DEVICE_STATE_IDLE) {
-		dev_warn(&pdev->dev,
-			 "omap_device: %s() called from invalid state %d\n",
-			 __func__, od->_state);
-		return -EINVAL;
-	}
-
-	ret = _omap_device_deactivate(od, IGNORE_WAKEUP_LAT);
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		omap_hwmod_shutdown(od->hwmods[i]);
-
-	od->_state = OMAP_DEVICE_STATE_SHUTDOWN;
-
-	return ret;
-}
-
-/**
  * omap_device_assert_hardreset - set a device's hardreset line
  * @pdev: struct platform_device * to reset
  * @name: const char * name of the reset line
@@ -1060,86 +797,6 @@
 }
 
 /**
- * omap_device_align_pm_lat - activate/deactivate device to match wakeup lat lim
- * @od: struct omap_device *
- *
- * When a device's maximum wakeup latency limit changes, call some of
- * the .activate_func or .deactivate_func function pointers in the
- * omap_device's pm_lats array to ensure that the device's maximum
- * wakeup latency is less than or equal to the new latency limit.
- * Intended to be called by OMAP PM code whenever a device's maximum
- * wakeup latency limit changes (e.g., via
- * omap_pm_set_dev_wakeup_lat()).  Returns 0 if nothing needs to be
- * done (e.g., if the omap_device is not currently idle, or if the
- * wakeup latency is already current with the new limit) or passes
- * along the return value of _omap_device_deactivate() or
- * _omap_device_activate().
- */
-int omap_device_align_pm_lat(struct platform_device *pdev,
-			     u32 new_wakeup_lat_limit)
-{
-	int ret = -EINVAL;
-	struct omap_device *od;
-
-	od = to_omap_device(pdev);
-
-	if (new_wakeup_lat_limit == od->dev_wakeup_lat)
-		return 0;
-
-	od->_dev_wakeup_lat_limit = new_wakeup_lat_limit;
-
-	if (od->_state != OMAP_DEVICE_STATE_IDLE)
-		return 0;
-	else if (new_wakeup_lat_limit > od->dev_wakeup_lat)
-		ret = _omap_device_deactivate(od, USE_WAKEUP_LAT);
-	else if (new_wakeup_lat_limit < od->dev_wakeup_lat)
-		ret = _omap_device_activate(od, USE_WAKEUP_LAT);
-
-	return ret;
-}
-
-/**
- * omap_device_get_pwrdm - return the powerdomain * associated with @od
- * @od: struct omap_device *
- *
- * Return the powerdomain associated with the first underlying
- * omap_hwmod for this omap_device.  Intended for use by core OMAP PM
- * code.  Returns NULL on error or a struct powerdomain * upon
- * success.
- */
-struct powerdomain *omap_device_get_pwrdm(struct omap_device *od)
-{
-	/*
-	 * XXX Assumes that all omap_hwmod powerdomains are identical.
-	 * This may not necessarily be true.  There should be a sanity
-	 * check in here to WARN() if any difference appears.
-	 */
-	if (!od->hwmods_cnt)
-		return NULL;
-
-	return omap_hwmod_get_pwrdm(od->hwmods[0]);
-}
-
-/**
- * omap_device_get_mpu_rt_va - return the MPU's virtual addr for the hwmod base
- * @od: struct omap_device *
- *
- * Return the MPU's virtual address for the base of the hwmod, from
- * the ioremap() that the hwmod code does.  Only valid if there is one
- * hwmod associated with this device.  Returns NULL if there are zero
- * or more than one hwmods associated with this omap_device;
- * otherwise, passes along the return value from
- * omap_hwmod_get_mpu_rt_va().
- */
-void __iomem *omap_device_get_rt_va(struct omap_device *od)
-{
-	if (od->hwmods_cnt != 1)
-		return NULL;
-
-	return omap_hwmod_get_mpu_rt_va(od->hwmods[0]);
-}
-
-/**
  * omap_device_get_by_hwmod_name() - convert a hwmod name to
  * device pointer.
  * @oh_name: name of the hwmod device
@@ -1173,82 +830,6 @@
 
 	return &oh->od->pdev->dev;
 }
-EXPORT_SYMBOL(omap_device_get_by_hwmod_name);
-
-/*
- * Public functions intended for use in omap_device_pm_latency
- * .activate_func and .deactivate_func function pointers
- */
-
-/**
- * omap_device_enable_hwmods - call omap_hwmod_enable() on all hwmods
- * @od: struct omap_device *od
- *
- * Enable all underlying hwmods.  Returns 0.
- */
-int omap_device_enable_hwmods(struct omap_device *od)
-{
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		omap_hwmod_enable(od->hwmods[i]);
-
-	/* XXX pass along return value here? */
-	return 0;
-}
-
-/**
- * omap_device_idle_hwmods - call omap_hwmod_idle() on all hwmods
- * @od: struct omap_device *od
- *
- * Idle all underlying hwmods.  Returns 0.
- */
-int omap_device_idle_hwmods(struct omap_device *od)
-{
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		omap_hwmod_idle(od->hwmods[i]);
-
-	/* XXX pass along return value here? */
-	return 0;
-}
-
-/**
- * omap_device_disable_clocks - disable all main and interface clocks
- * @od: struct omap_device *od
- *
- * Disable the main functional clock and interface clock for all of the
- * omap_hwmods associated with the omap_device.  Returns 0.
- */
-int omap_device_disable_clocks(struct omap_device *od)
-{
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		omap_hwmod_disable_clocks(od->hwmods[i]);
-
-	/* XXX pass along return value here? */
-	return 0;
-}
-
-/**
- * omap_device_enable_clocks - enable all main and interface clocks
- * @od: struct omap_device *od
- *
- * Enable the main functional clock and interface clock for all of the
- * omap_hwmods associated with the omap_device.  Returns 0.
- */
-int omap_device_enable_clocks(struct omap_device *od)
-{
-	int i;
-
-	for (i = 0; i < od->hwmods_cnt; i++)
-		omap_hwmod_enable_clocks(od->hwmods[i]);
-
-	/* XXX pass along return value here? */
-	return 0;
-}
 
 static struct notifier_block platform_nb = {
 	.notifier_call = _omap_device_notifier_call,
diff --git a/arch/arm/mach-omap2/omap_device.h b/arch/arm/mach-omap2/omap_device.h
index 0933c59..044c31d 100644
--- a/arch/arm/mach-omap2/omap_device.h
+++ b/arch/arm/mach-omap2/omap_device.h
@@ -13,20 +13,12 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  *
- * Eventually this type of functionality should either be
- * a) implemented via arch-specific pointers in platform_device
- * or
- * b) implemented as a proper omap_bus/omap_device in Linux, no more
- *    platform_device
+ * This type of functionality should be implemented as a proper
+ * omap_bus/omap_device in Linux.
  *
  * omap_device differs from omap_hwmod in that it includes external
  * (e.g., board- and system-level) integration details.  omap_hwmod
  * stores hardware data that is invariant for a given OMAP chip.
- *
- * To do:
- * - GPIO integration
- * - regulator integration
- *
  */
 #ifndef __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_DEVICE_H
 #define __ARCH_ARM_PLAT_OMAP_INCLUDE_MACH_OMAP_DEVICE_H
@@ -45,19 +37,14 @@
 #define OMAP_DEVICE_STATE_SHUTDOWN	3
 
 /* omap_device.flags values */
-#define OMAP_DEVICE_SUSPENDED BIT(0)
-#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND BIT(1)
+#define OMAP_DEVICE_SUSPENDED		BIT(0)
+#define OMAP_DEVICE_NO_IDLE_ON_SUSPEND	BIT(1)
 
 /**
  * struct omap_device - omap_device wrapper for platform_devices
  * @pdev: platform_device
  * @hwmods: (one .. many per omap_device)
  * @hwmods_cnt: ARRAY_SIZE() of @hwmods
- * @pm_lats: ptr to an omap_device_pm_latency table
- * @pm_lats_cnt: ARRAY_SIZE() of what is passed to @pm_lats
- * @pm_lat_level: array index of the last odpl entry executed - -1 if never
- * @dev_wakeup_lat: dev wakeup latency in nanoseconds
- * @_dev_wakeup_lat_limit: dev wakeup latency limit in nsec - set by OMAP PM
  * @_state: one of OMAP_DEVICE_STATE_* (see above)
  * @flags: device flags
  * @_driver_status: one of BUS_NOTIFY_*_DRIVER from <linux/device.h>
@@ -71,12 +58,7 @@
 struct omap_device {
 	struct platform_device		*pdev;
 	struct omap_hwmod		**hwmods;
-	struct omap_device_pm_latency	*pm_lats;
-	u32				dev_wakeup_lat;
-	u32				_dev_wakeup_lat_limit;
 	unsigned long			_driver_status;
-	u8				pm_lats_cnt;
-	s8				pm_lat_level;
 	u8				hwmods_cnt;
 	u8				_state;
 	u8                              flags;
@@ -86,36 +68,25 @@
 
 int omap_device_enable(struct platform_device *pdev);
 int omap_device_idle(struct platform_device *pdev);
-int omap_device_shutdown(struct platform_device *pdev);
 
 /* Core code interface */
 
 struct platform_device *omap_device_build(const char *pdev_name, int pdev_id,
-				      struct omap_hwmod *oh, void *pdata,
-				      int pdata_len,
-				      struct omap_device_pm_latency *pm_lats,
-				      int pm_lats_cnt, int is_early_device);
+					  struct omap_hwmod *oh, void *pdata,
+					  int pdata_len);
 
 struct platform_device *omap_device_build_ss(const char *pdev_name, int pdev_id,
 					 struct omap_hwmod **oh, int oh_cnt,
-					 void *pdata, int pdata_len,
-					 struct omap_device_pm_latency *pm_lats,
-					 int pm_lats_cnt, int is_early_device);
+					 void *pdata, int pdata_len);
 
 struct omap_device *omap_device_alloc(struct platform_device *pdev,
-				      struct omap_hwmod **ohs, int oh_cnt,
-				      struct omap_device_pm_latency *pm_lats,
-				      int pm_lats_cnt);
+				      struct omap_hwmod **ohs, int oh_cnt);
 void omap_device_delete(struct omap_device *od);
 int omap_device_register(struct platform_device *pdev);
 
-void __iomem *omap_device_get_rt_va(struct omap_device *od);
 struct device *omap_device_get_by_hwmod_name(const char *oh_name);
 
 /* OMAP PM interface */
-int omap_device_align_pm_lat(struct platform_device *pdev,
-			     u32 new_wakeup_lat_limit);
-struct powerdomain *omap_device_get_pwrdm(struct omap_device *od);
 int omap_device_get_context_loss_count(struct platform_device *pdev);
 
 /* Other */
@@ -124,40 +95,6 @@
 				 const char *name);
 int omap_device_deassert_hardreset(struct platform_device *pdev,
 				 const char *name);
-int omap_device_idle_hwmods(struct omap_device *od);
-int omap_device_enable_hwmods(struct omap_device *od);
-
-int omap_device_disable_clocks(struct omap_device *od);
-int omap_device_enable_clocks(struct omap_device *od);
-
-/*
- * Entries should be kept in latency order ascending
- *
- * deact_lat is the maximum number of microseconds required to complete
- * deactivate_func() at the device's slowest OPP.
- *
- * act_lat is the maximum number of microseconds required to complete
- * activate_func() at the device's slowest OPP.
- *
- * This will result in some suboptimal power management decisions at fast
- * OPPs, but avoids having to recompute all device power management decisions
- * if the system shifts from a fast OPP to a slow OPP (in order to meet
- * latency requirements).
- *
- * XXX should deactivate_func/activate_func() take platform_device pointers
- * rather than omap_device pointers?
- */
-struct omap_device_pm_latency {
-	u32 deactivate_lat;
-	u32 deactivate_lat_worst;
-	int (*deactivate_func)(struct omap_device *od);
-	u32 activate_lat;
-	u32 activate_lat_worst;
-	int (*activate_func)(struct omap_device *od);
-	u32 flags;
-};
-
-#define OMAP_DEVICE_LATENCY_AUTO_ADJUST BIT(1)
 
 /* Get omap_device pointer from platform_device pointer */
 static inline struct omap_device *to_omap_device(struct platform_device *pdev)
diff --git a/arch/arm/mach-omap2/omap_hwmod.c b/arch/arm/mach-omap2/omap_hwmod.c
index 4653efb..6804d47 100644
--- a/arch/arm/mach-omap2/omap_hwmod.c
+++ b/arch/arm/mach-omap2/omap_hwmod.c
@@ -139,6 +139,8 @@
 #include <linux/slab.h>
 #include <linux/bootmem.h>
 
+#include <asm/system_misc.h>
+
 #include "clock.h"
 #include "omap_hwmod.h"
 
@@ -2134,6 +2136,8 @@
 	_enable_clocks(oh);
 	if (soc_ops.enable_module)
 		soc_ops.enable_module(oh);
+	if (oh->flags & HWMOD_BLOCK_WFI)
+		disable_hlt();
 
 	if (soc_ops.update_context_lost)
 		soc_ops.update_context_lost(oh);
@@ -2195,6 +2199,8 @@
 		_idle_sysc(oh);
 	_del_initiator_dep(oh, mpu_oh);
 
+	if (oh->flags & HWMOD_BLOCK_WFI)
+		enable_hlt();
 	if (soc_ops.disable_module)
 		soc_ops.disable_module(oh);
 
@@ -2303,6 +2309,8 @@
 	if (oh->_state == _HWMOD_STATE_ENABLED) {
 		_del_initiator_dep(oh, mpu_oh);
 		/* XXX what about the other system initiators here? dma, dsp */
+		if (oh->flags & HWMOD_BLOCK_WFI)
+			enable_hlt();
 		if (soc_ops.disable_module)
 			soc_ops.disable_module(oh);
 		_disable_clocks(oh);
diff --git a/arch/arm/mach-omap2/omap_hwmod.h b/arch/arm/mach-omap2/omap_hwmod.h
index 3ae852a..80c00e7 100644
--- a/arch/arm/mach-omap2/omap_hwmod.h
+++ b/arch/arm/mach-omap2/omap_hwmod.h
@@ -451,6 +451,14 @@
  *     enabled.  This prevents the hwmod code from being able to
  *     enable and reset the IP block early.  XXX Eventually it should
  *     be possible to query the clock framework for this information.
+ * HWMOD_BLOCK_WFI: Some OMAP peripherals apparently don't work
+ *     correctly if the MPU is allowed to go idle while the
+ *     peripherals are active.  This is apparently true for the I2C on
+ *     OMAP2420, and also the EMAC on AM3517/3505.  It's unlikely that
+ *     this is really true -- we're probably not configuring something
+ *     correctly, or this is being abused to deal with some PM latency
+ *     issues -- but we're currently suffering from a shortage of
+ *     folks who are able to track these issues down properly.
  */
 #define HWMOD_SWSUP_SIDLE			(1 << 0)
 #define HWMOD_SWSUP_MSTANDBY			(1 << 1)
@@ -462,6 +470,7 @@
 #define HWMOD_CONTROL_OPT_CLKS_IN_RESET		(1 << 7)
 #define HWMOD_16BIT_REG				(1 << 8)
 #define HWMOD_EXT_OPT_MAIN_CLK			(1 << 9)
+#define HWMOD_BLOCK_WFI				(1 << 10)
 
 /*
  * omap_hwmod._int_flags definitions
diff --git a/arch/arm/mach-omap2/omap_hwmod_2420_data.c b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
index b5efe58..6a764af 100644
--- a/arch/arm/mach-omap2/omap_hwmod_2420_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_2420_data.c
@@ -121,7 +121,12 @@
 	},
 	.class		= &i2c_class,
 	.dev_attr	= &i2c_dev_attr,
-	.flags		= HWMOD_16BIT_REG,
+	/*
+	 * From mach-omap2/pm24xx.c: "Putting MPU into the WFI state
+	 * while a transfer is active seems to cause the I2C block to
+	 * timeout. Why? Good question."
+	 */
+	.flags		= (HWMOD_16BIT_REG | HWMOD_BLOCK_WFI),
 };
 
 /* I2C2 */
diff --git a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
index 129d508..a1849a8 100644
--- a/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
+++ b/arch/arm/mach-omap2/omap_hwmod_44xx_data.c
@@ -616,7 +616,7 @@
 	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_dmic_irqs,
 	.sdma_reqs	= omap44xx_dmic_sdma_reqs,
-	.main_clk	= "dmic_fck",
+	.main_clk	= "func_dmic_abe_gfclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_DMIC_CLKCTRL_OFFSET,
@@ -1161,7 +1161,7 @@
 	.class		= &omap44xx_gpio_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
 	.mpu_irqs	= omap44xx_gpio1_irqs,
-	.main_clk	= "gpio1_ick",
+	.main_clk	= "l4_wkup_clk_mux_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_WKUP_GPIO1_CLKCTRL_OFFSET,
@@ -1190,7 +1190,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio2_irqs,
-	.main_clk	= "gpio2_ick",
+	.main_clk	= "l4_div_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_GPIO2_CLKCTRL_OFFSET,
@@ -1219,7 +1219,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio3_irqs,
-	.main_clk	= "gpio3_ick",
+	.main_clk	= "l4_div_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_GPIO3_CLKCTRL_OFFSET,
@@ -1248,7 +1248,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio4_irqs,
-	.main_clk	= "gpio4_ick",
+	.main_clk	= "l4_div_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_GPIO4_CLKCTRL_OFFSET,
@@ -1277,7 +1277,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio5_irqs,
-	.main_clk	= "gpio5_ick",
+	.main_clk	= "l4_div_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_GPIO5_CLKCTRL_OFFSET,
@@ -1306,7 +1306,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_CONTROL_OPT_CLKS_IN_RESET,
 	.mpu_irqs	= omap44xx_gpio6_irqs,
-	.main_clk	= "gpio6_ick",
+	.main_clk	= "l4_div_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_GPIO6_CLKCTRL_OFFSET,
@@ -1405,7 +1405,7 @@
 	.class		= &omap44xx_gpu_hwmod_class,
 	.clkdm_name	= "l3_gfx_clkdm",
 	.mpu_irqs	= omap44xx_gpu_irqs,
-	.main_clk	= "gpu_fck",
+	.main_clk	= "sgx_clk_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_GFX_GFX_CLKCTRL_OFFSET,
@@ -1446,7 +1446,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_INIT_NO_RESET, /* XXX temporary */
 	.mpu_irqs	= omap44xx_hdq1w_irqs,
-	.main_clk	= "hdq1w_fck",
+	.main_clk	= "func_12m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_HDQ1W_CLKCTRL_OFFSET,
@@ -1550,7 +1550,7 @@
 	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c1_irqs,
 	.sdma_reqs	= omap44xx_i2c1_sdma_reqs,
-	.main_clk	= "i2c1_fck",
+	.main_clk	= "func_96m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_I2C1_CLKCTRL_OFFSET,
@@ -1580,7 +1580,7 @@
 	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c2_irqs,
 	.sdma_reqs	= omap44xx_i2c2_sdma_reqs,
-	.main_clk	= "i2c2_fck",
+	.main_clk	= "func_96m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_I2C2_CLKCTRL_OFFSET,
@@ -1610,7 +1610,7 @@
 	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c3_irqs,
 	.sdma_reqs	= omap44xx_i2c3_sdma_reqs,
-	.main_clk	= "i2c3_fck",
+	.main_clk	= "func_96m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_I2C3_CLKCTRL_OFFSET,
@@ -1640,7 +1640,7 @@
 	.flags		= HWMOD_16BIT_REG | HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_i2c4_irqs,
 	.sdma_reqs	= omap44xx_i2c4_sdma_reqs,
-	.main_clk	= "i2c4_fck",
+	.main_clk	= "func_96m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_I2C4_CLKCTRL_OFFSET,
@@ -1743,7 +1743,7 @@
 	.clkdm_name	= "iss_clkdm",
 	.mpu_irqs	= omap44xx_iss_irqs,
 	.sdma_reqs	= omap44xx_iss_sdma_reqs,
-	.main_clk	= "iss_fck",
+	.main_clk	= "ducati_clk_mux_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_CAM_ISS_CLKCTRL_OFFSET,
@@ -1785,7 +1785,7 @@
 	.mpu_irqs	= omap44xx_iva_irqs,
 	.rst_lines	= omap44xx_iva_resets,
 	.rst_lines_cnt	= ARRAY_SIZE(omap44xx_iva_resets),
-	.main_clk	= "iva_fck",
+	.main_clk	= "dpll_iva_m5x2_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_IVAHD_IVAHD_CLKCTRL_OFFSET,
@@ -1829,7 +1829,7 @@
 	.class		= &omap44xx_kbd_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
 	.mpu_irqs	= omap44xx_kbd_irqs,
-	.main_clk	= "kbd_fck",
+	.main_clk	= "sys_32k_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_WKUP_KEYBOARD_CLKCTRL_OFFSET,
@@ -1920,7 +1920,7 @@
 	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_mcasp_irqs,
 	.sdma_reqs	= omap44xx_mcasp_sdma_reqs,
-	.main_clk	= "mcasp_fck",
+	.main_clk	= "func_mcasp_abe_gfclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_MCASP_CLKCTRL_OFFSET,
@@ -1972,7 +1972,7 @@
 	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_mcbsp1_irqs,
 	.sdma_reqs	= omap44xx_mcbsp1_sdma_reqs,
-	.main_clk	= "mcbsp1_fck",
+	.main_clk	= "func_mcbsp1_gfclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_MCBSP1_CLKCTRL_OFFSET,
@@ -2007,7 +2007,7 @@
 	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_mcbsp2_irqs,
 	.sdma_reqs	= omap44xx_mcbsp2_sdma_reqs,
-	.main_clk	= "mcbsp2_fck",
+	.main_clk	= "func_mcbsp2_gfclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_MCBSP2_CLKCTRL_OFFSET,
@@ -2042,7 +2042,7 @@
 	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_mcbsp3_irqs,
 	.sdma_reqs	= omap44xx_mcbsp3_sdma_reqs,
-	.main_clk	= "mcbsp3_fck",
+	.main_clk	= "func_mcbsp3_gfclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_MCBSP3_CLKCTRL_OFFSET,
@@ -2077,7 +2077,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mcbsp4_irqs,
 	.sdma_reqs	= omap44xx_mcbsp4_sdma_reqs,
-	.main_clk	= "mcbsp4_fck",
+	.main_clk	= "per_mcbsp4_gfclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_MCBSP4_CLKCTRL_OFFSET,
@@ -2132,11 +2132,15 @@
 	 * currently reset very early during boot, before I2C is
 	 * available, so it doesn't seem that we have any choice in
 	 * the kernel other than to avoid resetting it.
+	 *
+	 * Also, McPDM needs to be configured to NO_IDLE mode when it
+	 * is in used otherwise vital clocks will be gated which
+	 * results 'slow motion' audio playback.
 	 */
-	.flags		= HWMOD_EXT_OPT_MAIN_CLK,
+	.flags		= HWMOD_EXT_OPT_MAIN_CLK | HWMOD_SWSUP_SIDLE,
 	.mpu_irqs	= omap44xx_mcpdm_irqs,
 	.sdma_reqs	= omap44xx_mcpdm_sdma_reqs,
-	.main_clk	= "mcpdm_fck",
+	.main_clk	= "pad_clks_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_PDM_CLKCTRL_OFFSET,
@@ -2197,7 +2201,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mcspi1_irqs,
 	.sdma_reqs	= omap44xx_mcspi1_sdma_reqs,
-	.main_clk	= "mcspi1_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_MCSPI1_CLKCTRL_OFFSET,
@@ -2233,7 +2237,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mcspi2_irqs,
 	.sdma_reqs	= omap44xx_mcspi2_sdma_reqs,
-	.main_clk	= "mcspi2_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_MCSPI2_CLKCTRL_OFFSET,
@@ -2269,7 +2273,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mcspi3_irqs,
 	.sdma_reqs	= omap44xx_mcspi3_sdma_reqs,
-	.main_clk	= "mcspi3_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_MCSPI3_CLKCTRL_OFFSET,
@@ -2303,7 +2307,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mcspi4_irqs,
 	.sdma_reqs	= omap44xx_mcspi4_sdma_reqs,
-	.main_clk	= "mcspi4_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_MCSPI4_CLKCTRL_OFFSET,
@@ -2359,7 +2363,7 @@
 	.clkdm_name	= "l3_init_clkdm",
 	.mpu_irqs	= omap44xx_mmc1_irqs,
 	.sdma_reqs	= omap44xx_mmc1_sdma_reqs,
-	.main_clk	= "mmc1_fck",
+	.main_clk	= "hsmmc1_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L3INIT_MMC1_CLKCTRL_OFFSET,
@@ -2388,7 +2392,7 @@
 	.clkdm_name	= "l3_init_clkdm",
 	.mpu_irqs	= omap44xx_mmc2_irqs,
 	.sdma_reqs	= omap44xx_mmc2_sdma_reqs,
-	.main_clk	= "mmc2_fck",
+	.main_clk	= "hsmmc2_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L3INIT_MMC2_CLKCTRL_OFFSET,
@@ -2416,7 +2420,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mmc3_irqs,
 	.sdma_reqs	= omap44xx_mmc3_sdma_reqs,
-	.main_clk	= "mmc3_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_MMCSD3_CLKCTRL_OFFSET,
@@ -2444,7 +2448,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mmc4_irqs,
 	.sdma_reqs	= omap44xx_mmc4_sdma_reqs,
-	.main_clk	= "mmc4_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_MMCSD4_CLKCTRL_OFFSET,
@@ -2472,7 +2476,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_mmc5_irqs,
 	.sdma_reqs	= omap44xx_mmc5_sdma_reqs,
-	.main_clk	= "mmc5_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_MMCSD5_CLKCTRL_OFFSET,
@@ -2721,7 +2725,7 @@
 	.name		= "ocp2scp_usb_phy",
 	.class		= &omap44xx_ocp2scp_hwmod_class,
 	.clkdm_name	= "l3_init_clkdm",
-	.main_clk	= "ocp2scp_usb_phy_phy_48m",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L3INIT_USBPHYOCP2SCP_CLKCTRL_OFFSET,
@@ -3158,7 +3162,7 @@
 	.clkdm_name	= "l4_wkup_clkdm",
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_timer1_irqs,
-	.main_clk	= "timer1_fck",
+	.main_clk	= "dmt1_clk_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_WKUP_TIMER1_CLKCTRL_OFFSET,
@@ -3181,7 +3185,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_timer2_irqs,
-	.main_clk	= "timer2_fck",
+	.main_clk	= "cm2_dm2_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER2_CLKCTRL_OFFSET,
@@ -3202,7 +3206,7 @@
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_timer3_irqs,
-	.main_clk	= "timer3_fck",
+	.main_clk	= "cm2_dm3_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER3_CLKCTRL_OFFSET,
@@ -3223,7 +3227,7 @@
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_timer4_irqs,
-	.main_clk	= "timer4_fck",
+	.main_clk	= "cm2_dm4_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER4_CLKCTRL_OFFSET,
@@ -3244,7 +3248,7 @@
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_timer5_irqs,
-	.main_clk	= "timer5_fck",
+	.main_clk	= "timer5_sync_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_TIMER5_CLKCTRL_OFFSET,
@@ -3266,8 +3270,7 @@
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_timer6_irqs,
-
-	.main_clk	= "timer6_fck",
+	.main_clk	= "timer6_sync_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_TIMER6_CLKCTRL_OFFSET,
@@ -3289,7 +3292,7 @@
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_timer7_irqs,
-	.main_clk	= "timer7_fck",
+	.main_clk	= "timer7_sync_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_TIMER7_CLKCTRL_OFFSET,
@@ -3311,7 +3314,7 @@
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_timer8_irqs,
-	.main_clk	= "timer8_fck",
+	.main_clk	= "timer8_sync_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_TIMER8_CLKCTRL_OFFSET,
@@ -3333,7 +3336,7 @@
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_timer9_irqs,
-	.main_clk	= "timer9_fck",
+	.main_clk	= "cm2_dm9_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER9_CLKCTRL_OFFSET,
@@ -3356,7 +3359,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.flags		= HWMOD_SET_DEFAULT_CLOCKACT,
 	.mpu_irqs	= omap44xx_timer10_irqs,
-	.main_clk	= "timer10_fck",
+	.main_clk	= "cm2_dm10_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER10_CLKCTRL_OFFSET,
@@ -3378,7 +3381,7 @@
 	.class		= &omap44xx_timer_hwmod_class,
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_timer11_irqs,
-	.main_clk	= "timer11_fck",
+	.main_clk	= "cm2_dm11_mux",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_DMTIMER11_CLKCTRL_OFFSET,
@@ -3429,7 +3432,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_uart1_irqs,
 	.sdma_reqs	= omap44xx_uart1_sdma_reqs,
-	.main_clk	= "uart1_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_UART1_CLKCTRL_OFFSET,
@@ -3457,7 +3460,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_uart2_irqs,
 	.sdma_reqs	= omap44xx_uart2_sdma_reqs,
-	.main_clk	= "uart2_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_UART2_CLKCTRL_OFFSET,
@@ -3486,7 +3489,7 @@
 	.flags		= HWMOD_INIT_NO_IDLE | HWMOD_INIT_NO_RESET,
 	.mpu_irqs	= omap44xx_uart3_irqs,
 	.sdma_reqs	= omap44xx_uart3_sdma_reqs,
-	.main_clk	= "uart3_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_UART3_CLKCTRL_OFFSET,
@@ -3514,7 +3517,7 @@
 	.clkdm_name	= "l4_per_clkdm",
 	.mpu_irqs	= omap44xx_uart4_irqs,
 	.sdma_reqs	= omap44xx_uart4_sdma_reqs,
-	.main_clk	= "uart4_fck",
+	.main_clk	= "func_48m_fclk",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_L4PER_UART4_CLKCTRL_OFFSET,
@@ -3793,7 +3796,7 @@
 	.class		= &omap44xx_wd_timer_hwmod_class,
 	.clkdm_name	= "l4_wkup_clkdm",
 	.mpu_irqs	= omap44xx_wd_timer2_irqs,
-	.main_clk	= "wd_timer2_fck",
+	.main_clk	= "sys_32k_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM_WKUP_WDT2_CLKCTRL_OFFSET,
@@ -3814,7 +3817,7 @@
 	.class		= &omap44xx_wd_timer_hwmod_class,
 	.clkdm_name	= "abe_clkdm",
 	.mpu_irqs	= omap44xx_wd_timer3_irqs,
-	.main_clk	= "wd_timer3_fck",
+	.main_clk	= "sys_32k_ck",
 	.prcm = {
 		.omap4 = {
 			.clkctrl_offs = OMAP4_CM1_ABE_WDT3_CLKCTRL_OFFSET,
diff --git a/arch/arm/mach-omap2/pm-debug.c b/arch/arm/mach-omap2/pm-debug.c
index e2c291f..6db89ae 100644
--- a/arch/arm/mach-omap2/pm-debug.c
+++ b/arch/arm/mach-omap2/pm-debug.c
@@ -83,10 +83,8 @@
 		strncmp(clkdm->name, "dpll", 4) == 0)
 		return 0;
 
-	seq_printf(s, "%s->%s (%d)", clkdm->name,
-			clkdm->pwrdm.ptr->name,
-			atomic_read(&clkdm->usecount));
-	seq_printf(s, "\n");
+	seq_printf(s, "%s->%s (%d)\n", clkdm->name, clkdm->pwrdm.ptr->name,
+		   clkdm->usecount);
 
 	return 0;
 }
diff --git a/arch/arm/mach-omap2/pm.c b/arch/arm/mach-omap2/pm.c
index f4b3143..9a9be3c 100644
--- a/arch/arm/mach-omap2/pm.c
+++ b/arch/arm/mach-omap2/pm.c
@@ -32,8 +32,6 @@
 #include "pm.h"
 #include "twl-common.h"
 
-static struct omap_device_pm_latency *pm_lats;
-
 /*
  * omap_pm_suspend: points to a function that does the SoC-specific
  * suspend work
@@ -82,7 +80,7 @@
 		 __func__, name))
 		return -ENODEV;
 
-	pdev = omap_device_build(oh->name, 0, oh, NULL, 0, pm_lats, 0, false);
+	pdev = omap_device_build(oh->name, 0, oh, NULL, 0);
 	if (WARN(IS_ERR(pdev), "%s: could not build omap_device for %s\n",
 		 __func__, name))
 		return -ENODEV;
@@ -108,80 +106,19 @@
 	}
 }
 
-/* Types of sleep_switch used in omap_set_pwrdm_state */
-#define FORCEWAKEUP_SWITCH	0
-#define LOWPOWERSTATE_SWITCH	1
-
 int __init omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused)
 {
+	/* XXX The usecount test is racy */
 	if ((clkdm->flags & CLKDM_CAN_ENABLE_AUTO) &&
 	    !(clkdm->flags & CLKDM_MISSING_IDLE_REPORTING))
 		clkdm_allow_idle(clkdm);
 	else if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP &&
-		 atomic_read(&clkdm->usecount) == 0)
+		 clkdm->usecount == 0)
 		clkdm_sleep(clkdm);
 	return 0;
 }
 
 /*
- * This sets pwrdm state (other than mpu & core. Currently only ON &
- * RET are supported.
- */
-int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 pwrst)
-{
-	u8 curr_pwrst, next_pwrst;
-	int sleep_switch = -1, ret = 0, hwsup = 0;
-
-	if (!pwrdm || IS_ERR(pwrdm))
-		return -EINVAL;
-
-	while (!(pwrdm->pwrsts & (1 << pwrst))) {
-		if (pwrst == PWRDM_POWER_OFF)
-			return ret;
-		pwrst--;
-	}
-
-	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
-	if (next_pwrst == pwrst)
-		return ret;
-
-	curr_pwrst = pwrdm_read_pwrst(pwrdm);
-	if (curr_pwrst < PWRDM_POWER_ON) {
-		if ((curr_pwrst > pwrst) &&
-			(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE)) {
-			sleep_switch = LOWPOWERSTATE_SWITCH;
-		} else {
-			hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
-			clkdm_wakeup(pwrdm->pwrdm_clkdms[0]);
-			sleep_switch = FORCEWAKEUP_SWITCH;
-		}
-	}
-
-	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
-	if (ret)
-		pr_err("%s: unable to set power state of powerdomain: %s\n",
-		       __func__, pwrdm->name);
-
-	switch (sleep_switch) {
-	case FORCEWAKEUP_SWITCH:
-		if (hwsup)
-			clkdm_allow_idle(pwrdm->pwrdm_clkdms[0]);
-		else
-			clkdm_sleep(pwrdm->pwrdm_clkdms[0]);
-		break;
-	case LOWPOWERSTATE_SWITCH:
-		pwrdm_set_lowpwrstchange(pwrdm);
-		pwrdm_wait_transition(pwrdm);
-		pwrdm_state_switch(pwrdm);
-		break;
-	}
-
-	return ret;
-}
-
-
-
-/*
  * This API is to be called during init to set the various voltage
  * domains to the voltage as per the opp table. Typically we boot up
  * at the nominal voltage. So this function finds out the rate of
diff --git a/arch/arm/mach-omap2/pm.h b/arch/arm/mach-omap2/pm.h
index c22503b..7bdd22a 100644
--- a/arch/arm/mach-omap2/pm.h
+++ b/arch/arm/mach-omap2/pm.h
@@ -33,7 +33,6 @@
 extern void *omap3_secure_ram_storage;
 extern void omap3_pm_off_mode_enable(int);
 extern void omap_sram_idle(void);
-extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u32 state);
 extern int omap_pm_clkdms_setup(struct clockdomain *clkdm, void *unused);
 extern int (*omap_pm_suspend)(void);
 
diff --git a/arch/arm/mach-omap2/pm24xx.c b/arch/arm/mach-omap2/pm24xx.c
index c333fa6..b2a4df6 100644
--- a/arch/arm/mach-omap2/pm24xx.c
+++ b/arch/arm/mach-omap2/pm24xx.c
@@ -90,11 +90,7 @@
 	omap2_prm_write_mod_reg(0xffffffff, CORE_MOD, OMAP24XX_PM_WKST2);
 	omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
 
-	/*
-	 * Set MPU powerdomain's next power state to RETENTION;
-	 * preserve logic state during retention
-	 */
-	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
+	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
 	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
 
 	/* Workaround to kill USB */
@@ -137,17 +133,12 @@
 	/* Mask future PRCM-to-MPU interrupts */
 	omap2_prm_write_mod_reg(0x0, OCP_MOD, OMAP2_PRCM_IRQSTATUS_MPU_OFFSET);
 
+	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
+	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_ON);
+
 	return 0;
 }
 
-static int omap2_i2c_active(void)
-{
-	u32 l;
-
-	l = omap2_cm_read_mod_reg(CORE_MOD, CM_FCLKEN1);
-	return l & (OMAP2420_EN_I2C2_MASK | OMAP2420_EN_I2C1_MASK);
-}
-
 static int sti_console_enabled;
 
 static int omap2_allow_mpu_retention(void)
@@ -172,11 +163,6 @@
 
 static void omap2_enter_mpu_retention(void)
 {
-	/* Putting MPU into the WFI state while a transfer is active
-	 * seems to cause the I2C block to timeout. Why? Good question. */
-	if (omap2_i2c_active())
-		return;
-
 	/* The peripherals seem not to be able to wake up the MPU when
 	 * it is in retention mode. */
 	if (omap2_allow_mpu_retention()) {
@@ -186,17 +172,16 @@
 		omap2_prm_write_mod_reg(0xffffffff, WKUP_MOD, PM_WKST);
 
 		/* Try to enter MPU retention */
-		omap2_prm_write_mod_reg((0x01 << OMAP_POWERSTATE_SHIFT) |
-				  OMAP_LOGICRETSTATE_MASK,
-				  MPU_MOD, OMAP2_PM_PWSTCTRL);
+		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
+
 	} else {
 		/* Block MPU retention */
-
-		omap2_prm_write_mod_reg(OMAP_LOGICRETSTATE_MASK, MPU_MOD,
-						 OMAP2_PM_PWSTCTRL);
+		pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
 	}
 
 	omap2_sram_idle();
+
+	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_ON);
 }
 
 static int omap2_can_sleep(void)
@@ -251,25 +236,17 @@
 	for (i = 0; i < num_mem_banks; i++)
 		pwrdm_set_mem_retst(core_pwrdm, i, PWRDM_POWER_RET);
 
-	/* Set CORE powerdomain's next power state to RETENTION */
-	pwrdm_set_next_pwrst(core_pwrdm, PWRDM_POWER_RET);
+	pwrdm_set_logic_retst(core_pwrdm, PWRDM_POWER_RET);
 
-	/*
-	 * Set MPU powerdomain's next power state to RETENTION;
-	 * preserve logic state during retention
-	 */
 	pwrdm_set_logic_retst(mpu_pwrdm, PWRDM_POWER_RET);
-	pwrdm_set_next_pwrst(mpu_pwrdm, PWRDM_POWER_RET);
 
 	/* Force-power down DSP, GFX powerdomains */
 
 	pwrdm = clkdm_get_pwrdm(dsp_clkdm);
 	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
-	clkdm_sleep(dsp_clkdm);
 
 	pwrdm = clkdm_get_pwrdm(gfx_clkdm);
 	pwrdm_set_next_pwrst(pwrdm, PWRDM_POWER_OFF);
-	clkdm_sleep(gfx_clkdm);
 
 	/* Enable hardware-supervised idle for all clkdms */
 	clkdm_for_each(omap_pm_clkdms_setup, NULL);
diff --git a/arch/arm/mach-omap2/pmu.c b/arch/arm/mach-omap2/pmu.c
index eb78ae7..0ef4d6a 100644
--- a/arch/arm/mach-omap2/pmu.c
+++ b/arch/arm/mach-omap2/pmu.c
@@ -48,8 +48,7 @@
 		}
 	}
 
-	omap_pmu_dev = omap_device_build_ss(dev_name, -1, oh, oh_num, NULL, 0,
-					    NULL, 0, 0);
+	omap_pmu_dev = omap_device_build_ss(dev_name, -1, oh, oh_num, NULL, 0);
 	WARN(IS_ERR(omap_pmu_dev), "Can't build omap_device for %s.\n",
 	     dev_name);
 
diff --git a/arch/arm/mach-omap2/powerdomain.c b/arch/arm/mach-omap2/powerdomain.c
index dea62a9..8e61d80 100644
--- a/arch/arm/mach-omap2/powerdomain.c
+++ b/arch/arm/mach-omap2/powerdomain.c
@@ -19,6 +19,7 @@
 #include <linux/list.h>
 #include <linux/errno.h>
 #include <linux/string.h>
+#include <linux/spinlock.h>
 #include <trace/events/power.h>
 
 #include "cm2xxx_3xxx.h"
@@ -42,6 +43,16 @@
 	PWRDM_STATE_PREV,
 };
 
+/*
+ * Types of sleep_switch used internally in omap_set_pwrdm_state()
+ * and its associated static functions
+ *
+ * XXX Better documentation is needed here
+ */
+#define ALREADYACTIVE_SWITCH		0
+#define FORCEWAKEUP_SWITCH		1
+#define LOWPOWERSTATE_SWITCH		2
+#define ERROR_SWITCH			3
 
 /* pwrdm_list contains all registered struct powerdomains */
 static LIST_HEAD(pwrdm_list);
@@ -101,6 +112,7 @@
 	pwrdm->voltdm.ptr = voltdm;
 	INIT_LIST_HEAD(&pwrdm->voltdm_node);
 	voltdm_add_pwrdm(voltdm, pwrdm);
+	spin_lock_init(&pwrdm->_lock);
 
 	list_add(&pwrdm->node, &pwrdm_list);
 
@@ -112,7 +124,7 @@
 	for (i = 0; i < pwrdm->banks; i++)
 		pwrdm->ret_mem_off_counter[i] = 0;
 
-	pwrdm_wait_transition(pwrdm);
+	arch_pwrdm->pwrdm_wait_transition(pwrdm);
 	pwrdm->state = pwrdm_read_pwrst(pwrdm);
 	pwrdm->state_counter[pwrdm->state] = 1;
 
@@ -143,7 +155,7 @@
 static int _pwrdm_state_switch(struct powerdomain *pwrdm, int flag)
 {
 
-	int prev, state, trace_state = 0;
+	int prev, next, state, trace_state = 0;
 
 	if (pwrdm == NULL)
 		return -EINVAL;
@@ -164,9 +176,10 @@
 		 * If the power domain did not hit the desired state,
 		 * generate a trace event with both the desired and hit states
 		 */
-		if (state != prev) {
+		next = pwrdm_read_next_pwrst(pwrdm);
+		if (next != prev) {
 			trace_state = (PWRDM_TRACE_STATES_FLAG |
-				       ((state & OMAP_POWERSTATE_MASK) << 8) |
+				       ((next & OMAP_POWERSTATE_MASK) << 8) |
 				       ((prev & OMAP_POWERSTATE_MASK) << 0));
 			trace_power_domain_target(pwrdm->name, trace_state,
 						  smp_processor_id());
@@ -199,6 +212,80 @@
 	return 0;
 }
 
+/**
+ * _pwrdm_save_clkdm_state_and_activate - prepare for power state change
+ * @pwrdm: struct powerdomain * to operate on
+ * @curr_pwrst: current power state of @pwrdm
+ * @pwrst: power state to switch to
+ * @hwsup: ptr to a bool to return whether the clkdm is hardware-supervised
+ *
+ * Determine whether the powerdomain needs to be turned on before
+ * attempting to switch power states.  Called by
+ * omap_set_pwrdm_state().  NOTE that if the powerdomain contains
+ * multiple clockdomains, this code assumes that the first clockdomain
+ * supports software-supervised wakeup mode - potentially a problem.
+ * Returns the power state switch mode currently in use (see the
+ * "Types of sleep_switch" comment above).
+ */
+static u8 _pwrdm_save_clkdm_state_and_activate(struct powerdomain *pwrdm,
+					       u8 curr_pwrst, u8 pwrst,
+					       bool *hwsup)
+{
+	u8 sleep_switch;
+
+	if (curr_pwrst < 0) {
+		WARN_ON(1);
+		sleep_switch = ERROR_SWITCH;
+	} else if (curr_pwrst < PWRDM_POWER_ON) {
+		if (curr_pwrst > pwrst &&
+		    pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
+		    arch_pwrdm->pwrdm_set_lowpwrstchange) {
+			sleep_switch = LOWPOWERSTATE_SWITCH;
+		} else {
+			*hwsup = clkdm_in_hwsup(pwrdm->pwrdm_clkdms[0]);
+			clkdm_wakeup_nolock(pwrdm->pwrdm_clkdms[0]);
+			sleep_switch = FORCEWAKEUP_SWITCH;
+		}
+	} else {
+		sleep_switch = ALREADYACTIVE_SWITCH;
+	}
+
+	return sleep_switch;
+}
+
+/**
+ * _pwrdm_restore_clkdm_state - restore the clkdm hwsup state after pwrst change
+ * @pwrdm: struct powerdomain * to operate on
+ * @sleep_switch: return value from _pwrdm_save_clkdm_state_and_activate()
+ * @hwsup: should @pwrdm's first clockdomain be set to hardware-supervised mode?
+ *
+ * Restore the clockdomain state perturbed by
+ * _pwrdm_save_clkdm_state_and_activate(), and call the power state
+ * bookkeeping code.  Called by omap_set_pwrdm_state().  NOTE that if
+ * the powerdomain contains multiple clockdomains, this assumes that
+ * the first associated clockdomain supports either
+ * hardware-supervised idle control in the register, or
+ * software-supervised sleep.  No return value.
+ */
+static void _pwrdm_restore_clkdm_state(struct powerdomain *pwrdm,
+				       u8 sleep_switch, bool hwsup)
+{
+	switch (sleep_switch) {
+	case FORCEWAKEUP_SWITCH:
+		if (hwsup)
+			clkdm_allow_idle_nolock(pwrdm->pwrdm_clkdms[0]);
+		else
+			clkdm_sleep_nolock(pwrdm->pwrdm_clkdms[0]);
+		break;
+	case LOWPOWERSTATE_SWITCH:
+		if (pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE &&
+		    arch_pwrdm->pwrdm_set_lowpwrstchange)
+			arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
+		pwrdm_state_switch_nolock(pwrdm);
+		break;
+	}
+}
+
 /* Public functions */
 
 /**
@@ -275,6 +362,30 @@
 }
 
 /**
+ * pwrdm_lock - acquire a Linux spinlock on a powerdomain
+ * @pwrdm: struct powerdomain * to lock
+ *
+ * Acquire the powerdomain spinlock on @pwrdm.  No return value.
+ */
+void pwrdm_lock(struct powerdomain *pwrdm)
+	__acquires(&pwrdm->_lock)
+{
+	spin_lock_irqsave(&pwrdm->_lock, pwrdm->_lock_flags);
+}
+
+/**
+ * pwrdm_unlock - release a Linux spinlock on a powerdomain
+ * @pwrdm: struct powerdomain * to unlock
+ *
+ * Release the powerdomain spinlock on @pwrdm.  No return value.
+ */
+void pwrdm_unlock(struct powerdomain *pwrdm)
+	__releases(&pwrdm->_lock)
+{
+	spin_unlock_irqrestore(&pwrdm->_lock, pwrdm->_lock_flags);
+}
+
+/**
  * pwrdm_lookup - look up a powerdomain by name, return a pointer
  * @name: name of powerdomain
  *
@@ -920,69 +1031,31 @@
 	return (pwrdm && pwrdm->flags & PWRDM_HAS_HDWR_SAR) ? 1 : 0;
 }
 
-/**
- * pwrdm_set_lowpwrstchange - Request a low power state change
- * @pwrdm: struct powerdomain *
- *
- * Allows a powerdomain to transtion to a lower power sleep state
- * from an existing sleep state without waking up the powerdomain.
- * Returns -EINVAL if the powerdomain pointer is null or if the
- * powerdomain does not support LOWPOWERSTATECHANGE, or returns 0
- * upon success.
- */
-int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm)
-{
-	int ret = -EINVAL;
-
-	if (!pwrdm)
-		return -EINVAL;
-
-	if (!(pwrdm->flags & PWRDM_HAS_LOWPOWERSTATECHANGE))
-		return -EINVAL;
-
-	pr_debug("powerdomain: %s: setting LOWPOWERSTATECHANGE bit\n",
-		 pwrdm->name);
-
-	if (arch_pwrdm && arch_pwrdm->pwrdm_set_lowpwrstchange)
-		ret = arch_pwrdm->pwrdm_set_lowpwrstchange(pwrdm);
-
-	return ret;
-}
-
-/**
- * pwrdm_wait_transition - wait for powerdomain power transition to finish
- * @pwrdm: struct powerdomain * to wait for
- *
- * If the powerdomain @pwrdm is in the process of a state transition,
- * spin until it completes the power transition, or until an iteration
- * bailout value is reached. Returns -EINVAL if the powerdomain
- * pointer is null, -EAGAIN if the bailout value was reached, or
- * returns 0 upon success.
- */
-int pwrdm_wait_transition(struct powerdomain *pwrdm)
-{
-	int ret = -EINVAL;
-
-	if (!pwrdm)
-		return -EINVAL;
-
-	if (arch_pwrdm && arch_pwrdm->pwrdm_wait_transition)
-		ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
-
-	return ret;
-}
-
-int pwrdm_state_switch(struct powerdomain *pwrdm)
+int pwrdm_state_switch_nolock(struct powerdomain *pwrdm)
 {
 	int ret;
 
-	ret = pwrdm_wait_transition(pwrdm);
+	if (!pwrdm || !arch_pwrdm)
+		return -EINVAL;
+
+	ret = arch_pwrdm->pwrdm_wait_transition(pwrdm);
 	if (!ret)
 		ret = _pwrdm_state_switch(pwrdm, PWRDM_STATE_NOW);
 
 	return ret;
 }
 
+int __deprecated pwrdm_state_switch(struct powerdomain *pwrdm)
+{
+	int ret;
+
+	pwrdm_lock(pwrdm);
+	ret = pwrdm_state_switch_nolock(pwrdm);
+	pwrdm_unlock(pwrdm);
+
+	return ret;
+}
+
 int pwrdm_pre_transition(struct powerdomain *pwrdm)
 {
 	if (pwrdm)
@@ -1004,6 +1077,61 @@
 }
 
 /**
+ * omap_set_pwrdm_state - change a powerdomain's current power state
+ * @pwrdm: struct powerdomain * to change the power state of
+ * @pwrst: power state to change to
+ *
+ * Change the current hardware power state of the powerdomain
+ * represented by @pwrdm to the power state represented by @pwrst.
+ * Returns -EINVAL if @pwrdm is null or invalid or if the
+ * powerdomain's current power state could not be read, or returns 0
+ * upon success or if @pwrdm does not support @pwrst or any
+ * lower-power state.  XXX Should not return 0 if the @pwrdm does not
+ * support @pwrst or any lower-power state: this should be an error.
+ */
+int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 pwrst)
+{
+	u8 curr_pwrst, next_pwrst, sleep_switch;
+	int ret = 0;
+	bool hwsup = false;
+
+	if (!pwrdm || IS_ERR(pwrdm))
+		return -EINVAL;
+
+	while (!(pwrdm->pwrsts & (1 << pwrst))) {
+		if (pwrst == PWRDM_POWER_OFF)
+			return ret;
+		pwrst--;
+	}
+
+	pwrdm_lock(pwrdm);
+
+	curr_pwrst = pwrdm_read_pwrst(pwrdm);
+	next_pwrst = pwrdm_read_next_pwrst(pwrdm);
+	if (curr_pwrst == pwrst && next_pwrst == pwrst)
+		goto osps_out;
+
+	sleep_switch = _pwrdm_save_clkdm_state_and_activate(pwrdm, curr_pwrst,
+							    pwrst, &hwsup);
+	if (sleep_switch == ERROR_SWITCH) {
+		ret = -EINVAL;
+		goto osps_out;
+	}
+
+	ret = pwrdm_set_next_pwrst(pwrdm, pwrst);
+	if (ret)
+		pr_err("%s: unable to set power state of powerdomain: %s\n",
+		       __func__, pwrdm->name);
+
+	_pwrdm_restore_clkdm_state(pwrdm, sleep_switch, hwsup);
+
+osps_out:
+	pwrdm_unlock(pwrdm);
+
+	return ret;
+}
+
+/**
  * pwrdm_get_context_loss_count - get powerdomain's context loss count
  * @pwrdm: struct powerdomain * to wait for
  *
diff --git a/arch/arm/mach-omap2/powerdomain.h b/arch/arm/mach-omap2/powerdomain.h
index 5277d56eb..140c360 100644
--- a/arch/arm/mach-omap2/powerdomain.h
+++ b/arch/arm/mach-omap2/powerdomain.h
@@ -19,8 +19,7 @@
 
 #include <linux/types.h>
 #include <linux/list.h>
-
-#include <linux/atomic.h>
+#include <linux/spinlock.h>
 
 #include "voltage.h"
 
@@ -44,18 +43,20 @@
 #define PWRSTS_OFF_RET_ON	(PWRSTS_OFF_RET | PWRSTS_ON)
 
 
-/* Powerdomain flags */
-#define PWRDM_HAS_HDWR_SAR	(1 << 0) /* hardware save-and-restore support */
-#define PWRDM_HAS_MPU_QUIRK	(1 << 1) /* MPU pwr domain has MEM bank 0 bits
-					  * in MEM bank 1 position. This is
-					  * true for OMAP3430
-					  */
-#define PWRDM_HAS_LOWPOWERSTATECHANGE	(1 << 2) /*
-						  * support to transition from a
-						  * sleep state to a lower sleep
-						  * state without waking up the
-						  * powerdomain
-						  */
+/*
+ * Powerdomain flags (struct powerdomain.flags)
+ *
+ * PWRDM_HAS_HDWR_SAR - powerdomain has hardware save-and-restore support
+ *
+ * PWRDM_HAS_MPU_QUIRK - MPU pwr domain has MEM bank 0 bits in MEM
+ * bank 1 position. This is true for OMAP3430
+ *
+ * PWRDM_HAS_LOWPOWERSTATECHANGE - can transition from a sleep state
+ * to a lower sleep state without waking up the powerdomain
+ */
+#define PWRDM_HAS_HDWR_SAR		BIT(0)
+#define PWRDM_HAS_MPU_QUIRK		BIT(1)
+#define PWRDM_HAS_LOWPOWERSTATECHANGE	BIT(2)
 
 /*
  * Number of memory banks that are power-controllable.	On OMAP4430, the
@@ -103,6 +104,8 @@
  * @state_counter:
  * @timer:
  * @state_timer:
+ * @_lock: spinlock used to serialize powerdomain and some clockdomain ops
+ * @_lock_flags: stored flags when @_lock is taken
  *
  * @prcm_partition possible values are defined in mach-omap2/prcm44xx.h.
  */
@@ -127,7 +130,8 @@
 	unsigned state_counter[PWRDM_MAX_PWRSTS];
 	unsigned ret_logic_off_counter;
 	unsigned ret_mem_off_counter[PWRDM_MAX_MEM_BANKS];
-
+	spinlock_t _lock;
+	unsigned long _lock_flags;
 	const u8 pwrstctrl_offs;
 	const u8 pwrstst_offs;
 	const u32 logicretstate_mask;
@@ -162,6 +166,16 @@
  * @pwrdm_disable_hdwr_sar: Disable Hardware Save-Restore feature for a pd
  * @pwrdm_set_lowpwrstchange: Enable pd transitions from a shallow to deep sleep
  * @pwrdm_wait_transition: Wait for a pd state transition to complete
+ *
+ * Regarding @pwrdm_set_lowpwrstchange: On the OMAP2 and 3-family
+ * chips, a powerdomain's power state is not allowed to directly
+ * transition from one low-power state (e.g., CSWR) to another
+ * low-power state (e.g., OFF) without first waking up the
+ * powerdomain.  This wastes energy.  So OMAP4 chips support the
+ * ability to transition a powerdomain power state directly from one
+ * low-power state to another.  The function pointed to by
+ * @pwrdm_set_lowpwrstchange is intended to configure the OMAP4
+ * hardware powerdomain state machine to enable this feature.
  */
 struct pwrdm_ops {
 	int	(*pwrdm_set_next_pwrst)(struct powerdomain *pwrdm, u8 pwrst);
@@ -225,15 +239,15 @@
 int pwrdm_disable_hdwr_sar(struct powerdomain *pwrdm);
 bool pwrdm_has_hdwr_sar(struct powerdomain *pwrdm);
 
-int pwrdm_wait_transition(struct powerdomain *pwrdm);
-
+int pwrdm_state_switch_nolock(struct powerdomain *pwrdm);
 int pwrdm_state_switch(struct powerdomain *pwrdm);
 int pwrdm_pre_transition(struct powerdomain *pwrdm);
 int pwrdm_post_transition(struct powerdomain *pwrdm);
-int pwrdm_set_lowpwrstchange(struct powerdomain *pwrdm);
 int pwrdm_get_context_loss_count(struct powerdomain *pwrdm);
 bool pwrdm_can_ever_lose_context(struct powerdomain *pwrdm);
 
+extern int omap_set_pwrdm_state(struct powerdomain *pwrdm, u8 state);
+
 extern void omap242x_powerdomains_init(void);
 extern void omap243x_powerdomains_init(void);
 extern void omap3xxx_powerdomains_init(void);
@@ -253,5 +267,7 @@
 extern struct powerdomain wkup_omap2_pwrdm;
 extern struct powerdomain gfx_omap2_pwrdm;
 
+extern void pwrdm_lock(struct powerdomain *pwrdm);
+extern void pwrdm_unlock(struct powerdomain *pwrdm);
 
 #endif
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
index d3a5399..7b946f1 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_3xxx_data.c
@@ -54,12 +54,12 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 struct powerdomain wkup_omap2_pwrdm = {
 	.name		= "wkup_pwrdm",
 	.prcm_offs	= WKUP_MOD,
 	.pwrsts		= PWRSTS_ON,
-	.voltdm         = { .name = "wakeup" },
+	.voltdm		= { .name = "wakeup" },
 };
diff --git a/arch/arm/mach-omap2/powerdomains2xxx_data.c b/arch/arm/mach-omap2/powerdomains2xxx_data.c
index ba520d4..578eef8 100644
--- a/arch/arm/mach-omap2/powerdomains2xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains2xxx_data.c
@@ -38,7 +38,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain mpu_24xx_pwrdm = {
@@ -53,13 +53,14 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain core_24xx_pwrdm = {
 	.name		  = "core_pwrdm",
 	.prcm_offs	  = CORE_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
+	.pwrsts_logic_ret = PWRSTS_RET,
 	.banks		  = 3,
 	.pwrsts_mem_ret	  = {
 		[0] = PWRSTS_OFF_RET,	 /* MEM1RETSTATE */
@@ -71,7 +72,7 @@
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 		[2] = PWRSTS_OFF_RET_ON, /* MEM3ONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 
@@ -93,7 +94,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 /*
diff --git a/arch/arm/mach-omap2/powerdomains3xxx_data.c b/arch/arm/mach-omap2/powerdomains3xxx_data.c
index 8b23d23..f0e14e9 100644
--- a/arch/arm/mach-omap2/powerdomains3xxx_data.c
+++ b/arch/arm/mach-omap2/powerdomains3xxx_data.c
@@ -50,7 +50,7 @@
 		[2] = PWRSTS_OFF_ON,
 		[3] = PWRSTS_ON,
 	},
-	.voltdm           = { .name = "mpu_iva" },
+	.voltdm		  = { .name = "mpu_iva" },
 };
 
 static struct powerdomain mpu_3xxx_pwrdm = {
@@ -66,7 +66,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_OFF_ON,
 	},
-	.voltdm           = { .name = "mpu_iva" },
+	.voltdm		  = { .name = "mpu_iva" },
 };
 
 static struct powerdomain mpu_am35x_pwrdm = {
@@ -82,7 +82,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,
 	},
-	.voltdm           = { .name = "mpu_iva" },
+	.voltdm		  = { .name = "mpu_iva" },
 };
 
 /*
@@ -109,7 +109,7 @@
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain core_3xxx_es3_1_pwrdm = {
@@ -131,7 +131,7 @@
 		[0] = PWRSTS_OFF_RET_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_OFF_RET_ON, /* MEM2ONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain core_am35x_pwrdm = {
@@ -148,7 +148,7 @@
 		[0] = PWRSTS_ON, /* MEM1ONSTATE */
 		[1] = PWRSTS_ON, /* MEM2ONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain dss_pwrdm = {
@@ -163,7 +163,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain dss_am35x_pwrdm = {
@@ -178,7 +178,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 /*
@@ -199,7 +199,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain sgx_am35x_pwrdm = {
@@ -214,7 +214,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain cam_pwrdm = {
@@ -229,7 +229,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain per_pwrdm = {
@@ -244,7 +244,7 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain per_am35x_pwrdm = {
@@ -259,13 +259,13 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain emu_pwrdm = {
 	.name		= "emu_pwrdm",
 	.prcm_offs	= OMAP3430_EMU_MOD,
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain neon_pwrdm = {
@@ -273,7 +273,7 @@
 	.prcm_offs	  = OMAP3430_NEON_MOD,
 	.pwrsts		  = PWRSTS_OFF_RET_ON,
 	.pwrsts_logic_ret = PWRSTS_RET,
-	.voltdm           = { .name = "mpu_iva" },
+	.voltdm		  = { .name = "mpu_iva" },
 };
 
 static struct powerdomain neon_am35x_pwrdm = {
@@ -281,7 +281,7 @@
 	.prcm_offs	  = OMAP3430_NEON_MOD,
 	.pwrsts		  = PWRSTS_ON,
 	.pwrsts_logic_ret = PWRSTS_ON,
-	.voltdm           = { .name = "mpu_iva" },
+	.voltdm		  = { .name = "mpu_iva" },
 };
 
 static struct powerdomain usbhost_pwrdm = {
@@ -303,37 +303,37 @@
 	.pwrsts_mem_on	  = {
 		[0] = PWRSTS_ON,  /* MEMONSTATE */
 	},
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain dpll1_pwrdm = {
 	.name		= "dpll1_pwrdm",
 	.prcm_offs	= MPU_MOD,
-	.voltdm           = { .name = "mpu_iva" },
+	.voltdm		  = { .name = "mpu_iva" },
 };
 
 static struct powerdomain dpll2_pwrdm = {
 	.name		= "dpll2_pwrdm",
 	.prcm_offs	= OMAP3430_IVA2_MOD,
-	.voltdm           = { .name = "mpu_iva" },
+	.voltdm		  = { .name = "mpu_iva" },
 };
 
 static struct powerdomain dpll3_pwrdm = {
 	.name		= "dpll3_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain dpll4_pwrdm = {
 	.name		= "dpll4_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 static struct powerdomain dpll5_pwrdm = {
 	.name		= "dpll5_pwrdm",
 	.prcm_offs	= PLL_MOD,
-	.voltdm           = { .name = "core" },
+	.voltdm		  = { .name = "core" },
 };
 
 /* As powerdomains are added or removed above, this list must also be changed */
diff --git a/arch/arm/mach-omap2/prm2xxx_3xxx.c b/arch/arm/mach-omap2/prm2xxx_3xxx.c
index a3e121f..947f6ad 100644
--- a/arch/arm/mach-omap2/prm2xxx_3xxx.c
+++ b/arch/arm/mach-omap2/prm2xxx_3xxx.c
@@ -210,6 +210,7 @@
 					     PM_WKDEP, (1 << clkdm2->dep_bit));
 }
 
+/* XXX Caller must hold the clkdm's powerdomain lock */
 int omap2_clkdm_clear_all_wkdeps(struct clockdomain *clkdm)
 {
 	struct clkdm_dep *cd;
@@ -221,7 +222,7 @@
 
 		/* PRM accesses are slow, so minimize them */
 		mask |= 1 << cd->clkdm->dep_bit;
-		atomic_set(&cd->wkdep_usecount, 0);
+		cd->wkdep_usecount = 0;
 	}
 
 	omap2_prm_clear_mod_reg_bits(mask, clkdm->pwrdm.ptr->prcm_offs,
diff --git a/arch/arm/mach-omap2/serial.c b/arch/arm/mach-omap2/serial.c
index 04fdbc4..d01c373 100644
--- a/arch/arm/mach-omap2/serial.c
+++ b/arch/arm/mach-omap2/serial.c
@@ -316,8 +316,7 @@
 	if (WARN_ON(!oh))
 		return;
 
-	pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size,
-				 NULL, 0, false);
+	pdev = omap_device_build(name, uart->num, oh, pdata, pdata_size);
 	if (IS_ERR(pdev)) {
 		WARN(1, "Could not build omap_device for %s: %s.\n", name,
 		     oh->name);
diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c
index b9753fe..bb829e0 100644
--- a/arch/arm/mach-omap2/sr_device.c
+++ b/arch/arm/mach-omap2/sr_device.c
@@ -152,8 +152,7 @@
 
 	sr_data->enable_on_init = sr_enable_on_init;
 
-	pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data),
-				 NULL, 0, 0);
+	pdev = omap_device_build(name, i, oh, sr_data, sizeof(*sr_data), 0);
 	if (IS_ERR(pdev))
 		pr_warning("%s: Could not build omap_device for %s: %s.\n\n",
 			__func__, name, oh->name);
diff --git a/arch/arm/mach-omap2/timer.c b/arch/arm/mach-omap2/timer.c
index 3e2ffdb..6d1f7b1 100644
--- a/arch/arm/mach-omap2/timer.c
+++ b/arch/arm/mach-omap2/timer.c
@@ -164,15 +164,11 @@
 	struct device_node *np;
 
 	for_each_matching_node(np, match) {
-		if (!of_device_is_available(np)) {
-			of_node_put(np);
+		if (!of_device_is_available(np))
 			continue;
-		}
 
-		if (property && !of_get_property(np, property, NULL)) {
-			of_node_put(np);
+		if (property && !of_get_property(np, property, NULL))
 			continue;
-		}
 
 		of_add_property(np, &device_disabled);
 		return np;
@@ -549,7 +545,7 @@
 
 #define OMAP_SYS_GP_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop,	\
 			       clksrc_nr, clksrc_src)			\
-static void __init omap##name##_gptimer_timer_init(void)		\
+void __init omap##name##_gptimer_timer_init(void)			\
 {									\
 	omap_dmtimer_init();						\
 	omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);	\
@@ -558,7 +554,7 @@
 
 #define OMAP_SYS_32K_TIMER_INIT(name, clkev_nr, clkev_src, clkev_prop,	\
 				clksrc_nr, clksrc_src)			\
-static void __init omap##name##_sync32k_timer_init(void)		\
+void __init omap##name##_sync32k_timer_init(void)		\
 {									\
 	omap_dmtimer_init();						\
 	omap2_gp_clockevent_init((clkev_nr), clkev_src, clkev_prop);	\
@@ -569,33 +565,23 @@
 		omap2_sync32k_clocksource_init();			\
 }
 
-#define OMAP_SYS_TIMER(name, clksrc)					\
-struct sys_timer omap##name##_timer = {					\
-	.init	= omap##name##_##clksrc##_timer_init,			\
-};
-
 #ifdef CONFIG_ARCH_OMAP2
 OMAP_SYS_32K_TIMER_INIT(2, 1, OMAP2_32K_SOURCE, "ti,timer-alwon",
 			2, OMAP2_MPU_SOURCE);
-OMAP_SYS_TIMER(2, sync32k);
 #endif /* CONFIG_ARCH_OMAP2 */
 
 #ifdef CONFIG_ARCH_OMAP3
 OMAP_SYS_32K_TIMER_INIT(3, 1, OMAP3_32K_SOURCE, "ti,timer-alwon",
 			2, OMAP3_MPU_SOURCE);
-OMAP_SYS_TIMER(3, sync32k);
 OMAP_SYS_32K_TIMER_INIT(3_secure, 12, OMAP3_32K_SOURCE, "ti,timer-secure",
 			2, OMAP3_MPU_SOURCE);
-OMAP_SYS_TIMER(3_secure, sync32k);
 OMAP_SYS_GP_TIMER_INIT(3_gp, 1, OMAP3_MPU_SOURCE, "ti,timer-alwon",
 		       2, OMAP3_MPU_SOURCE);
-OMAP_SYS_TIMER(3_gp, gptimer);
 #endif /* CONFIG_ARCH_OMAP3 */
 
 #ifdef CONFIG_SOC_AM33XX
 OMAP_SYS_GP_TIMER_INIT(3_am33xx, 1, OMAP4_MPU_SOURCE, "ti,timer-alwon",
 		       2, OMAP4_MPU_SOURCE);
-OMAP_SYS_TIMER(3_am33xx, gptimer);
 #endif /* CONFIG_SOC_AM33XX */
 
 #ifdef CONFIG_ARCH_OMAP4
@@ -603,7 +589,7 @@
 			2, OMAP4_MPU_SOURCE);
 #ifdef CONFIG_LOCAL_TIMERS
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, OMAP44XX_LOCAL_TWD_BASE, 29);
-static void __init omap4_local_timer_init(void)
+void __init omap4_local_timer_init(void)
 {
 	omap4_sync32k_timer_init();
 	/* Local timers are not supprted on OMAP4430 ES1.0 */
@@ -621,18 +607,17 @@
 	}
 }
 #else /* CONFIG_LOCAL_TIMERS */
-static void __init omap4_local_timer_init(void)
+void __init omap4_local_timer_init(void)
 {
 	omap4_sync32k_timer_init();
 }
 #endif /* CONFIG_LOCAL_TIMERS */
-OMAP_SYS_TIMER(4, local);
 #endif /* CONFIG_ARCH_OMAP4 */
 
 #ifdef CONFIG_SOC_OMAP5
 OMAP_SYS_32K_TIMER_INIT(5, 1, OMAP4_32K_SOURCE, "ti,timer-alwon",
 			2, OMAP4_MPU_SOURCE);
-static void __init omap5_realtime_timer_init(void)
+void __init omap5_realtime_timer_init(void)
 {
 	int err;
 
@@ -643,7 +628,6 @@
 	if (err)
 		pr_err("%s: arch_timer_register failed %d\n", __func__, err);
 }
-OMAP_SYS_TIMER(5, realtime);
 #endif /* CONFIG_SOC_OMAP5 */
 
 /**
@@ -699,8 +683,7 @@
 	pdata->timer_errata = omap_dm_timer_get_errata();
 	pdata->get_context_loss_count = omap_pm_get_dev_context_loss_count;
 
-	pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata),
-				 NULL, 0, 0);
+	pdev = omap_device_build(name, id, oh, pdata, sizeof(*pdata));
 
 	if (IS_ERR(pdev)) {
 		pr_err("%s: Can't build omap_device for %s: %s.\n",
diff --git a/arch/arm/mach-omap2/usb-host.c b/arch/arm/mach-omap2/usb-host.c
index 2e44e8a..99f04de 100644
--- a/arch/arm/mach-omap2/usb-host.c
+++ b/arch/arm/mach-omap2/usb-host.c
@@ -42,14 +42,6 @@
 static struct ehci_hcd_omap_platform_data	ehci_data;
 static struct ohci_hcd_omap_platform_data	ohci_data;
 
-static struct omap_device_pm_latency omap_uhhtll_latency[] = {
-	  {
-		.deactivate_func = omap_device_idle_hwmods,
-		.activate_func	 = omap_device_enable_hwmods,
-		.flags = OMAP_DEVICE_LATENCY_AUTO_ADJUST,
-	  },
-};
-
 /* MUX settings for EHCI pins */
 /*
  * setup_ehci_io_mux - initialize IO pad mux for USBHOST
@@ -530,9 +522,7 @@
 	}
 
 	pdev = omap_device_build(OMAP_USBTLL_DEVICE, bus_id, tll_hwm,
-				&usbtll_data, sizeof(usbtll_data),
-				omap_uhhtll_latency,
-				ARRAY_SIZE(omap_uhhtll_latency), false);
+				 &usbtll_data, sizeof(usbtll_data));
 	if (IS_ERR(pdev)) {
 		pr_err("Could not build hwmod device %s\n",
 		       USBHS_TLL_HWMODNAME);
@@ -540,9 +530,7 @@
 	}
 
 	pdev = omap_device_build(OMAP_USBHS_DEVICE, bus_id, uhh_hwm,
-				&usbhs_data, sizeof(usbhs_data),
-				omap_uhhtll_latency,
-				ARRAY_SIZE(omap_uhhtll_latency), false);
+				&usbhs_data, sizeof(usbhs_data));
 	if (IS_ERR(pdev)) {
 		pr_err("Could not build hwmod devices %s\n",
 		       USBHS_UHH_HWMODNAME);
diff --git a/arch/arm/mach-omap2/usb-musb.c b/arch/arm/mach-omap2/usb-musb.c
index 7b33b37..8c4de27 100644
--- a/arch/arm/mach-omap2/usb-musb.c
+++ b/arch/arm/mach-omap2/usb-musb.c
@@ -102,7 +102,7 @@
                 return;
 
 	pdev = omap_device_build(name, bus_id, oh, &musb_plat,
-			       sizeof(musb_plat), NULL, 0, false);
+				 sizeof(musb_plat));
 	if (IS_ERR(pdev)) {
 		pr_err("Could not build omap_device for %s %s\n",
 						name, oh_name);
diff --git a/arch/arm/mach-omap2/wd_timer.c b/arch/arm/mach-omap2/wd_timer.c
index 7c2b4ed..910243f 100644
--- a/arch/arm/mach-omap2/wd_timer.c
+++ b/arch/arm/mach-omap2/wd_timer.c
@@ -124,8 +124,7 @@
 	pdata.read_reset_sources = prm_read_reset_sources;
 
 	pdev = omap_device_build(dev_name, id, oh, &pdata,
-				 sizeof(struct omap_wd_timer_platform_data),
-				 NULL, 0, 0);
+				 sizeof(struct omap_wd_timer_platform_data));
 	WARN(IS_ERR(pdev), "Can't build omap_device for %s:%s.\n",
 	     dev_name, oh->name);
 	return 0;
diff --git a/arch/arm/mach-orion5x/board-dt.c b/arch/arm/mach-orion5x/board-dt.c
index 32e5c21..35a8014 100644
--- a/arch/arm/mach-orion5x/board-dt.c
+++ b/arch/arm/mach-orion5x/board-dt.c
@@ -72,7 +72,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion_dt_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.init_machine	= orion5x_dt_init,
 	.restart	= orion5x_restart,
 	.dt_compat	= orion5x_dt_compat,
diff --git a/arch/arm/mach-orion5x/common.c b/arch/arm/mach-orion5x/common.c
index 550f923..d068f14 100644
--- a/arch/arm/mach-orion5x/common.c
+++ b/arch/arm/mach-orion5x/common.c
@@ -217,7 +217,7 @@
 	return 166666667;
 }
 
-static void __init orion5x_timer_init(void)
+void __init orion5x_timer_init(void)
 {
 	orion5x_tclk = orion5x_find_tclk();
 
@@ -225,10 +225,6 @@
 			IRQ_ORION5X_BRIDGE, orion5x_tclk);
 }
 
-struct sys_timer orion5x_timer = {
-	.init = orion5x_timer_init,
-};
-
 
 /*****************************************************************************
  * General
diff --git a/arch/arm/mach-orion5x/common.h b/arch/arm/mach-orion5x/common.h
index 7db5cdd..e603457 100644
--- a/arch/arm/mach-orion5x/common.h
+++ b/arch/arm/mach-orion5x/common.h
@@ -15,7 +15,7 @@
 void orion5x_id(u32 *dev, u32 *rev, char **dev_name);
 void clk_init(void);
 extern int orion5x_tclk;
-extern struct sys_timer orion5x_timer;
+extern void orion5x_timer_init(void);
 
 /*
  * Enumerations and functions for Orion windows mapping. Used by Orion core
diff --git a/arch/arm/mach-orion5x/d2net-setup.c b/arch/arm/mach-orion5x/d2net-setup.c
index e3629c0..57d0af7 100644
--- a/arch/arm/mach-orion5x/d2net-setup.c
+++ b/arch/arm/mach-orion5x/d2net-setup.c
@@ -342,7 +342,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
@@ -355,7 +355,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/db88f5281-setup.c b/arch/arm/mach-orion5x/db88f5281-setup.c
index 41fe2b1..7666564 100644
--- a/arch/arm/mach-orion5x/db88f5281-setup.c
+++ b/arch/arm/mach-orion5x/db88f5281-setup.c
@@ -362,6 +362,6 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/dns323-setup.c b/arch/arm/mach-orion5x/dns323-setup.c
index e533588..6eb1732 100644
--- a/arch/arm/mach-orion5x/dns323-setup.c
+++ b/arch/arm/mach-orion5x/dns323-setup.c
@@ -714,7 +714,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/kurobox_pro-setup.c b/arch/arm/mach-orion5x/kurobox_pro-setup.c
index f1ae10a..b984035 100644
--- a/arch/arm/mach-orion5x/kurobox_pro-setup.c
+++ b/arch/arm/mach-orion5x/kurobox_pro-setup.c
@@ -383,7 +383,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
@@ -397,7 +397,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/ls-chl-setup.c b/arch/arm/mach-orion5x/ls-chl-setup.c
index 0c9e413..044da5b 100644
--- a/arch/arm/mach-orion5x/ls-chl-setup.c
+++ b/arch/arm/mach-orion5x/ls-chl-setup.c
@@ -322,7 +322,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/ls_hgl-setup.c b/arch/arm/mach-orion5x/ls_hgl-setup.c
index c1b5d8a..d49f934 100644
--- a/arch/arm/mach-orion5x/ls_hgl-setup.c
+++ b/arch/arm/mach-orion5x/ls_hgl-setup.c
@@ -269,7 +269,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/lsmini-setup.c b/arch/arm/mach-orion5x/lsmini-setup.c
index 949eaa8..8e3965c 100644
--- a/arch/arm/mach-orion5x/lsmini-setup.c
+++ b/arch/arm/mach-orion5x/lsmini-setup.c
@@ -271,7 +271,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/mss2-setup.c b/arch/arm/mach-orion5x/mss2-setup.c
index 1c16d04..0ec94a1 100644
--- a/arch/arm/mach-orion5x/mss2-setup.c
+++ b/arch/arm/mach-orion5x/mss2-setup.c
@@ -265,7 +265,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/mv2120-setup.c b/arch/arm/mach-orion5x/mv2120-setup.c
index c87fde4..18143f2 100644
--- a/arch/arm/mach-orion5x/mv2120-setup.c
+++ b/arch/arm/mach-orion5x/mv2120-setup.c
@@ -233,7 +233,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/net2big-setup.c b/arch/arm/mach-orion5x/net2big-setup.c
index 3506f16..282e503 100644
--- a/arch/arm/mach-orion5x/net2big-setup.c
+++ b/arch/arm/mach-orion5x/net2big-setup.c
@@ -425,7 +425,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
index 9b1c953..d6e72f67 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-fxo-setup.c
@@ -171,7 +171,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
index 51ba2b8..c8b7913 100644
--- a/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5181l-ge-setup.c
@@ -183,7 +183,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/rd88f5182-setup.c b/arch/arm/mach-orion5x/rd88f5182-setup.c
index 0a56b94..f9e1567 100644
--- a/arch/arm/mach-orion5x/rd88f5182-setup.c
+++ b/arch/arm/mach-orion5x/rd88f5182-setup.c
@@ -281,6 +281,6 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
index ed50910..78a1e6a 100644
--- a/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
+++ b/arch/arm/mach-orion5x/rd88f6183ap-ge-setup.c
@@ -123,7 +123,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/terastation_pro2-setup.c b/arch/arm/mach-orion5x/terastation_pro2-setup.c
index 90e571d..acc0877 100644
--- a/arch/arm/mach-orion5x/terastation_pro2-setup.c
+++ b/arch/arm/mach-orion5x/terastation_pro2-setup.c
@@ -361,7 +361,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/ts209-setup.c b/arch/arm/mach-orion5x/ts209-setup.c
index b184f68..9c17f0c 100644
--- a/arch/arm/mach-orion5x/ts209-setup.c
+++ b/arch/arm/mach-orion5x/ts209-setup.c
@@ -326,7 +326,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/ts409-setup.c b/arch/arm/mach-orion5x/ts409-setup.c
index a5c2e64..8cc5ab6 100644
--- a/arch/arm/mach-orion5x/ts409-setup.c
+++ b/arch/arm/mach-orion5x/ts409-setup.c
@@ -315,7 +315,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/ts78xx-setup.c b/arch/arm/mach-orion5x/ts78xx-setup.c
index b0727dc..e960855 100644
--- a/arch/arm/mach-orion5x/ts78xx-setup.c
+++ b/arch/arm/mach-orion5x/ts78xx-setup.c
@@ -619,6 +619,6 @@
 	.map_io		= ts78xx_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/wnr854t-setup.c b/arch/arm/mach-orion5x/wnr854t-setup.c
index 754c12b..66552ca 100644
--- a/arch/arm/mach-orion5x/wnr854t-setup.c
+++ b/arch/arm/mach-orion5x/wnr854t-setup.c
@@ -176,7 +176,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-orion5x/wrt350n-v2-setup.c b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
index 45c2125..2c5408e 100644
--- a/arch/arm/mach-orion5x/wrt350n-v2-setup.c
+++ b/arch/arm/mach-orion5x/wrt350n-v2-setup.c
@@ -264,7 +264,7 @@
 	.map_io		= orion5x_map_io,
 	.init_early	= orion5x_init_early,
 	.init_irq	= orion5x_init_irq,
-	.timer		= &orion5x_timer,
+	.init_time	= orion5x_timer_init,
 	.fixup		= tag_fixup_mem32,
 	.restart	= orion5x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-picoxcell/common.c b/arch/arm/mach-picoxcell/common.c
index f6c0849..70b441a 100644
--- a/arch/arm/mach-picoxcell/common.c
+++ b/arch/arm/mach-picoxcell/common.c
@@ -9,6 +9,7 @@
  */
 #include <linux/delay.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/irqdomain.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -17,7 +18,6 @@
 #include <linux/dw_apb_timer.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/vic.h>
 #include <asm/mach/map.h>
 
 #include "common.h"
@@ -70,16 +70,6 @@
 	NULL
 };
 
-static const struct of_device_id vic_of_match[] __initconst = {
-	{ .compatible = "arm,pl192-vic", .data = vic_of_init, },
-	{ /* Sentinel */ }
-};
-
-static void __init picoxcell_init_irq(void)
-{
-	of_irq_init(vic_of_match);
-}
-
 static void picoxcell_wdt_restart(char mode, const char *cmd)
 {
 	/*
@@ -97,9 +87,8 @@
 DT_MACHINE_START(PICOXCELL, "Picochip picoXcell")
 	.map_io		= picoxcell_map_io,
 	.nr_irqs	= NR_IRQS_LEGACY,
-	.init_irq	= picoxcell_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &dw_apb_timer,
+	.init_irq	= irqchip_init,
+	.init_time	= dw_apb_timer_init,
 	.init_machine	= picoxcell_init_machine,
 	.dt_compat	= picoxcell_dt_match,
 	.restart	= picoxcell_wdt_restart,
diff --git a/arch/arm/mach-picoxcell/common.h b/arch/arm/mach-picoxcell/common.h
index a65cb02..481b42a 100644
--- a/arch/arm/mach-picoxcell/common.h
+++ b/arch/arm/mach-picoxcell/common.h
@@ -12,6 +12,6 @@
 
 #include <asm/mach/time.h>
 
-extern struct sys_timer dw_apb_timer;
+extern void dw_apb_timer_init(void);
 
 #endif /* __PICOXCELL_COMMON_H__ */
diff --git a/arch/arm/mach-prima2/Kconfig b/arch/arm/mach-prima2/Kconfig
index 558ccfb..4f7379f 100644
--- a/arch/arm/mach-prima2/Kconfig
+++ b/arch/arm/mach-prima2/Kconfig
@@ -11,6 +11,16 @@
 	help
           Support for CSR SiRFSoC ARM Cortex A9 Platform
 
+config ARCH_MARCO
+	bool "CSR SiRFSoC MARCO ARM Cortex A9 Platform"
+	default y
+	select ARM_GIC
+	select CPU_V7
+	select HAVE_SMP
+	select SMP_ON_UP
+	help
+          Support for CSR SiRFSoC ARM Cortex A9 Platform
+
 endmenu
 
 config SIRF_IRQ
diff --git a/arch/arm/mach-prima2/Makefile b/arch/arm/mach-prima2/Makefile
index fc9ce22..bfe360c 100644
--- a/arch/arm/mach-prima2/Makefile
+++ b/arch/arm/mach-prima2/Makefile
@@ -1,4 +1,3 @@
-obj-y := timer.o
 obj-y += rstc.o
 obj-y += common.o
 obj-y += rtciobrg.o
@@ -6,3 +5,7 @@
 obj-$(CONFIG_CACHE_L2X0) += l2x0.o
 obj-$(CONFIG_SUSPEND) += pm.o sleep.o
 obj-$(CONFIG_SIRF_IRQ) += irq.o
+obj-$(CONFIG_SMP) += platsmp.o headsmp.o
+obj-$(CONFIG_HOTPLUG_CPU)  += hotplug.o
+obj-$(CONFIG_ARCH_PRIMA2) += timer-prima2.o
+obj-$(CONFIG_ARCH_MARCO) += timer-marco.o
diff --git a/arch/arm/mach-prima2/common.c b/arch/arm/mach-prima2/common.c
index f25a541..2d57aa4 100644
--- a/arch/arm/mach-prima2/common.c
+++ b/arch/arm/mach-prima2/common.c
@@ -8,6 +8,7 @@
 
 #include <linux/init.h>
 #include <linux/kernel.h>
+#include <linux/irqchip.h>
 #include <asm/sizes.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -30,6 +31,12 @@
 	sirfsoc_pm_init();
 }
 
+static __init void sirfsoc_map_io(void)
+{
+	sirfsoc_map_lluart();
+	sirfsoc_map_scu();
+}
+
 #ifdef CONFIG_ARCH_PRIMA2
 static const char *prima2_dt_match[] __initdata = {
        "sirf,prima2",
@@ -38,9 +45,12 @@
 
 DT_MACHINE_START(PRIMA2_DT, "Generic PRIMA2 (Flattened Device Tree)")
 	/* Maintainer: Barry Song <baohua.song@csr.com> */
-	.map_io         = sirfsoc_map_lluart,
+	.map_io         = sirfsoc_map_io,
 	.init_irq	= sirfsoc_of_irq_init,
-	.timer		= &sirfsoc_timer,
+	.init_time	= sirfsoc_prima2_timer_init,
+#ifdef CONFIG_MULTI_IRQ_HANDLER
+	.handle_irq     = sirfsoc_handle_irq,
+#endif
 	.dma_zone_size	= SZ_256M,
 	.init_machine	= sirfsoc_mach_init,
 	.init_late	= sirfsoc_init_late,
@@ -48,3 +58,22 @@
 	.restart	= sirfsoc_restart,
 MACHINE_END
 #endif
+
+#ifdef CONFIG_ARCH_MARCO
+static const char *marco_dt_match[] __initdata = {
+	"sirf,marco",
+	NULL
+};
+
+DT_MACHINE_START(MARCO_DT, "Generic MARCO (Flattened Device Tree)")
+	/* Maintainer: Barry Song <baohua.song@csr.com> */
+	.smp            = smp_ops(sirfsoc_smp_ops),
+	.map_io         = sirfsoc_map_io,
+	.init_irq	= irqchip_init,
+	.init_time	= sirfsoc_marco_timer_init,
+	.init_machine	= sirfsoc_mach_init,
+	.init_late	= sirfsoc_init_late,
+	.dt_compat      = marco_dt_match,
+	.restart	= sirfsoc_restart,
+MACHINE_END
+#endif
diff --git a/arch/arm/mach-prima2/common.h b/arch/arm/mach-prima2/common.h
index 60d826f..b7c26b6 100644
--- a/arch/arm/mach-prima2/common.h
+++ b/arch/arm/mach-prima2/common.h
@@ -11,12 +11,19 @@
 
 #include <linux/init.h>
 #include <asm/mach/time.h>
+#include <asm/exception.h>
 
-extern struct sys_timer sirfsoc_timer;
+extern void sirfsoc_prima2_timer_init(void);
+extern void sirfsoc_marco_timer_init(void);
+
+extern struct smp_operations   sirfsoc_smp_ops;
+extern void sirfsoc_secondary_startup(void);
+extern void sirfsoc_cpu_die(unsigned int cpu);
 
 extern void __init sirfsoc_of_irq_init(void);
 extern void __init sirfsoc_of_clk_init(void);
 extern void sirfsoc_restart(char, const char *);
+extern asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs);
 
 #ifndef CONFIG_DEBUG_LL
 static inline void sirfsoc_map_lluart(void)  {}
@@ -24,6 +31,12 @@
 extern void __init sirfsoc_map_lluart(void);
 #endif
 
+#ifndef CONFIG_SMP
+static inline void sirfsoc_map_scu(void) {}
+#else
+extern void sirfsoc_map_scu(void);
+#endif
+
 #ifdef CONFIG_SUSPEND
 extern int sirfsoc_pm_init(void);
 #else
diff --git a/arch/arm/mach-prima2/headsmp.S b/arch/arm/mach-prima2/headsmp.S
new file mode 100644
index 0000000..6ec19d5
--- /dev/null
+++ b/arch/arm/mach-prima2/headsmp.S
@@ -0,0 +1,79 @@
+/*
+ * Entry of the second core for CSR Marco dual-core SMP SoCs
+ *
+ * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+	__INIT
+/*
+ * Cold boot and hardware reset show different behaviour,
+ * system will be always panic if we warm-reset the board
+ * Here we invalidate L1 of CPU1 to make sure there isn't
+ * uninitialized data written into memory later
+ */
+ENTRY(v7_invalidate_l1)
+	mov	r0, #0
+	mcr	p15, 0, r0, c7, c5, 0	@ invalidate I cache
+	mcr	p15, 2, r0, c0, c0, 0
+	mrc	p15, 1, r0, c0, c0, 0
+
+	ldr	r1, =0x7fff
+	and	r2, r1, r0, lsr #13
+
+	ldr	r1, =0x3ff
+
+	and	r3, r1, r0, lsr #3	@ NumWays - 1
+	add	r2, r2, #1		@ NumSets
+
+	and	r0, r0, #0x7
+	add	r0, r0, #4	@ SetShift
+
+	clz	r1, r3		@ WayShift
+	add	r4, r3, #1	@ NumWays
+1:	sub	r2, r2, #1	@ NumSets--
+	mov	r3, r4		@ Temp = NumWays
+2:	subs	r3, r3, #1	@ Temp--
+	mov	r5, r3, lsl r1
+	mov	r6, r2, lsl r0
+	orr	r5, r5, r6	@ Reg = (Temp<<WayShift)|(NumSets<<SetShift)
+	mcr	p15, 0, r5, c7, c6, 2
+	bgt	2b
+	cmp	r2, #0
+	bgt	1b
+	dsb
+	isb
+	mov	pc, lr
+ENDPROC(v7_invalidate_l1)
+
+/*
+ * SIRFSOC specific entry point for secondary CPUs.  This provides
+ * a "holding pen" into which all secondary cores are held until we're
+ * ready for them to initialise.
+ */
+ENTRY(sirfsoc_secondary_startup)
+	bl v7_invalidate_l1
+        mrc     p15, 0, r0, c0, c0, 5
+        and     r0, r0, #15
+        adr     r4, 1f
+        ldmia   r4, {r5, r6}
+        sub     r4, r4, r5
+        add     r6, r6, r4
+pen:    ldr     r7, [r6]
+        cmp     r7, r0
+        bne     pen
+
+        /*
+         * we've been released from the holding pen: secondary_stack
+         * should now contain the SVC stack for this core
+         */
+        b       secondary_startup
+ENDPROC(sirfsoc_secondary_startup)
+
+        .align
+1:      .long   .
+        .long   pen_release
diff --git a/arch/arm/mach-prima2/hotplug.c b/arch/arm/mach-prima2/hotplug.c
new file mode 100644
index 0000000..97c1ee5
--- /dev/null
+++ b/arch/arm/mach-prima2/hotplug.c
@@ -0,0 +1,41 @@
+/*
+ * CPU hotplug support for CSR Marco dual-core SMP SoCs
+ *
+ * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/smp.h>
+
+#include <asm/cacheflush.h>
+#include <asm/smp_plat.h>
+
+static inline void platform_do_lowpower(unsigned int cpu)
+{
+	flush_cache_all();
+
+	/* we put the platform to just WFI */
+	for (;;) {
+		__asm__ __volatile__("dsb\n\t" "wfi\n\t"
+			: : : "memory");
+		if (pen_release == cpu_logical_map(cpu)) {
+			/*
+			 * OK, proper wakeup, we're done
+			 */
+			break;
+		}
+	}
+}
+
+/*
+ * platform-specific code to shutdown a CPU
+ *
+ * Called with IRQs disabled
+ */
+void sirfsoc_cpu_die(unsigned int cpu)
+{
+	platform_do_lowpower(cpu);
+}
diff --git a/arch/arm/mach-prima2/include/mach/irqs.h b/arch/arm/mach-prima2/include/mach/irqs.h
index f6014a0..b778a0f 100644
--- a/arch/arm/mach-prima2/include/mach/irqs.h
+++ b/arch/arm/mach-prima2/include/mach/irqs.h
@@ -10,8 +10,8 @@
 #define __ASM_ARCH_IRQS_H
 
 #define SIRFSOC_INTENAL_IRQ_START  0
-#define SIRFSOC_INTENAL_IRQ_END    59
+#define SIRFSOC_INTENAL_IRQ_END    127
 #define SIRFSOC_GPIO_IRQ_START     (SIRFSOC_INTENAL_IRQ_END + 1)
-#define NR_IRQS	220
+#define NR_IRQS	288
 
 #endif
diff --git a/arch/arm/mach-prima2/include/mach/uart.h b/arch/arm/mach-prima2/include/mach/uart.h
index c98b4d5..c10510d 100644
--- a/arch/arm/mach-prima2/include/mach/uart.h
+++ b/arch/arm/mach-prima2/include/mach/uart.h
@@ -10,7 +10,13 @@
 #define __MACH_PRIMA2_SIRFSOC_UART_H
 
 /* UART-1: used as serial debug port */
+#if defined(CONFIG_DEBUG_SIRFPRIMA2_UART1)
 #define SIRFSOC_UART1_PA_BASE          0xb0060000
+#elif defined(CONFIG_DEBUG_SIRFMARCO_UART1)
+#define SIRFSOC_UART1_PA_BASE          0xcc060000
+#else
+#define SIRFSOC_UART1_PA_BASE          0
+#endif
 #define SIRFSOC_UART1_VA_BASE          SIRFSOC_VA(0x060000)
 #define SIRFSOC_UART1_SIZE		SZ_4K
 
diff --git a/arch/arm/mach-prima2/include/mach/uncompress.h b/arch/arm/mach-prima2/include/mach/uncompress.h
index 0c898fc..15f3edc 100644
--- a/arch/arm/mach-prima2/include/mach/uncompress.h
+++ b/arch/arm/mach-prima2/include/mach/uncompress.h
@@ -25,6 +25,9 @@
 	 * during kernel decompression, all mappings are flat:
 	 *  virt_addr == phys_addr
 	 */
+	if (!SIRFSOC_UART1_PA_BASE)
+		return;
+
 	while (__raw_readl((void __iomem *)SIRFSOC_UART1_PA_BASE + SIRFSOC_UART_TXFIFO_STATUS)
 		& SIRFSOC_UART1_TXFIFO_FULL)
 		barrier();
diff --git a/arch/arm/mach-prima2/irq.c b/arch/arm/mach-prima2/irq.c
index 7dee917..6c0f3e9 100644
--- a/arch/arm/mach-prima2/irq.c
+++ b/arch/arm/mach-prima2/irq.c
@@ -9,17 +9,19 @@
 #include <linux/init.h>
 #include <linux/io.h>
 #include <linux/irq.h>
-#include <mach/hardware.h>
-#include <asm/mach/irq.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/irqdomain.h>
 #include <linux/syscore_ops.h>
+#include <asm/mach/irq.h>
+#include <asm/exception.h>
+#include <mach/hardware.h>
 
 #define SIRFSOC_INT_RISC_MASK0          0x0018
 #define SIRFSOC_INT_RISC_MASK1          0x001C
 #define SIRFSOC_INT_RISC_LEVEL0         0x0020
 #define SIRFSOC_INT_RISC_LEVEL1         0x0024
+#define SIRFSOC_INIT_IRQ_ID		0x0038
 
 void __iomem *sirfsoc_intc_base;
 
@@ -52,6 +54,16 @@
 	writel_relaxed(0, sirfsoc_intc_base + SIRFSOC_INT_RISC_MASK1);
 }
 
+asmlinkage void __exception_irq_entry sirfsoc_handle_irq(struct pt_regs *regs)
+{
+	u32 irqstat, irqnr;
+
+	irqstat = readl_relaxed(sirfsoc_intc_base + SIRFSOC_INIT_IRQ_ID);
+	irqnr = irqstat & 0xff;
+
+	handle_IRQ(irqnr, regs);
+}
+
 static struct of_device_id intc_ids[]  = {
 	{ .compatible = "sirf,prima2-intc" },
 	{},
diff --git a/arch/arm/mach-prima2/l2x0.c b/arch/arm/mach-prima2/l2x0.c
index c998377..cbcbe9c 100644
--- a/arch/arm/mach-prima2/l2x0.c
+++ b/arch/arm/mach-prima2/l2x0.c
@@ -11,19 +11,38 @@
 #include <linux/of.h>
 #include <asm/hardware/cache-l2x0.h>
 
-static struct of_device_id prima2_l2x0_ids[]  = {
-	{ .compatible = "sirf,prima2-pl310-cache" },
+struct l2x0_aux
+{
+	u32 val;
+	u32 mask;
+};
+
+static struct l2x0_aux prima2_l2x0_aux __initconst = {
+	.val = 2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT,
+	.mask =	0,
+};
+
+static struct l2x0_aux marco_l2x0_aux __initconst = {
+	.val = (2 << L2X0_AUX_CTRL_WAY_SIZE_SHIFT) |
+		(1 << L2X0_AUX_CTRL_ASSOCIATIVITY_SHIFT),
+	.mask = L2X0_AUX_CTRL_MASK,
+};
+
+static struct of_device_id sirf_l2x0_ids[] __initconst = {
+	{ .compatible = "sirf,prima2-pl310-cache", .data = &prima2_l2x0_aux, },
+	{ .compatible = "sirf,marco-pl310-cache", .data = &marco_l2x0_aux, },
 	{},
 };
 
 static int __init sirfsoc_l2x0_init(void)
 {
 	struct device_node *np;
+	const struct l2x0_aux *aux;
 
-	np = of_find_matching_node(NULL, prima2_l2x0_ids);
+	np = of_find_matching_node(NULL, sirf_l2x0_ids);
 	if (np) {
-		pr_info("Initializing prima2 L2 cache\n");
-		return l2x0_of_init(0x40000, 0);
+		aux = of_match_node(sirf_l2x0_ids, np)->data;
+		return l2x0_of_init(aux->val, aux->mask);
 	}
 
 	return 0;
diff --git a/arch/arm/mach-prima2/platsmp.c b/arch/arm/mach-prima2/platsmp.c
new file mode 100644
index 0000000..4b78831
--- /dev/null
+++ b/arch/arm/mach-prima2/platsmp.c
@@ -0,0 +1,157 @@
+/*
+ * plat smp support for CSR Marco dual-core SMP SoCs
+ *
+ * Copyright (c) 2012 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/init.h>
+#include <linux/smp.h>
+#include <linux/delay.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/irqchip/arm-gic.h>
+#include <asm/page.h>
+#include <asm/mach/map.h>
+#include <asm/smp_plat.h>
+#include <asm/smp_scu.h>
+#include <asm/cacheflush.h>
+#include <asm/cputype.h>
+#include <mach/map.h>
+
+#include "common.h"
+
+static void __iomem *scu_base;
+static void __iomem *rsc_base;
+
+static DEFINE_SPINLOCK(boot_lock);
+
+static struct map_desc scu_io_desc __initdata = {
+	.length		= SZ_4K,
+	.type		= MT_DEVICE,
+};
+
+void __init sirfsoc_map_scu(void)
+{
+	unsigned long base;
+
+	/* Get SCU base */
+	asm("mrc p15, 4, %0, c15, c0, 0" : "=r" (base));
+
+	scu_io_desc.virtual = SIRFSOC_VA(base);
+	scu_io_desc.pfn = __phys_to_pfn(base);
+	iotable_init(&scu_io_desc, 1);
+
+	scu_base = (void __iomem *)SIRFSOC_VA(base);
+}
+
+static void __cpuinit sirfsoc_secondary_init(unsigned int cpu)
+{
+	/*
+	 * if any interrupts are already enabled for the primary
+	 * core (e.g. timer irq), then they will not have been enabled
+	 * for us: do so
+	 */
+	gic_secondary_init(0);
+
+	/*
+	 * let the primary processor know we're out of the
+	 * pen, then head off into the C entry point
+	 */
+	pen_release = -1;
+	smp_wmb();
+
+	/*
+	 * Synchronise with the boot thread.
+	 */
+	spin_lock(&boot_lock);
+	spin_unlock(&boot_lock);
+}
+
+static struct of_device_id rsc_ids[]  = {
+	{ .compatible = "sirf,marco-rsc" },
+	{},
+};
+
+static int __cpuinit sirfsoc_boot_secondary(unsigned int cpu, struct task_struct *idle)
+{
+	unsigned long timeout;
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, rsc_ids);
+	if (!np)
+		return -ENODEV;
+
+	rsc_base = of_iomap(np, 0);
+	if (!rsc_base)
+		return -ENOMEM;
+
+	/*
+	 * write the address of secondary startup into the sram register
+	 * at offset 0x2C, then write the magic number 0x3CAF5D62 to the
+	 * RSC register at offset 0x28, which is what boot rom code is
+	 * waiting for. This would wake up the secondary core from WFE
+	 */
+#define SIRFSOC_CPU1_JUMPADDR_OFFSET 0x2C
+	__raw_writel(virt_to_phys(sirfsoc_secondary_startup),
+		rsc_base + SIRFSOC_CPU1_JUMPADDR_OFFSET);
+
+#define SIRFSOC_CPU1_WAKEMAGIC_OFFSET 0x28
+	__raw_writel(0x3CAF5D62,
+		rsc_base + SIRFSOC_CPU1_WAKEMAGIC_OFFSET);
+
+	/* make sure write buffer is drained */
+	mb();
+
+	spin_lock(&boot_lock);
+
+	/*
+	 * The secondary processor is waiting to be released from
+	 * the holding pen - release it, then wait for it to flag
+	 * that it has been released by resetting pen_release.
+	 *
+	 * Note that "pen_release" is the hardware CPU ID, whereas
+	 * "cpu" is Linux's internal ID.
+	 */
+	pen_release = cpu_logical_map(cpu);
+	__cpuc_flush_dcache_area((void *)&pen_release, sizeof(pen_release));
+	outer_clean_range(__pa(&pen_release), __pa(&pen_release + 1));
+
+	/*
+	 * Send the secondary CPU SEV, thereby causing the boot monitor to read
+	 * the JUMPADDR and WAKEMAGIC, and branch to the address found there.
+	 */
+	dsb_sev();
+
+	timeout = jiffies + (1 * HZ);
+	while (time_before(jiffies, timeout)) {
+		smp_rmb();
+		if (pen_release == -1)
+			break;
+
+		udelay(10);
+	}
+
+	/*
+	 * now the secondary core is starting up let it run its
+	 * calibrations, then wait for it to finish
+	 */
+	spin_unlock(&boot_lock);
+
+	return pen_release != -1 ? -ENOSYS : 0;
+}
+
+static void __init sirfsoc_smp_prepare_cpus(unsigned int max_cpus)
+{
+	scu_enable(scu_base);
+}
+
+struct smp_operations sirfsoc_smp_ops __initdata = {
+        .smp_prepare_cpus       = sirfsoc_smp_prepare_cpus,
+        .smp_secondary_init     = sirfsoc_secondary_init,
+        .smp_boot_secondary     = sirfsoc_boot_secondary,
+#ifdef CONFIG_HOTPLUG_CPU
+	.cpu_die                = sirfsoc_cpu_die,
+#endif
+};
diff --git a/arch/arm/mach-prima2/rstc.c b/arch/arm/mach-prima2/rstc.c
index 762adb7..435019c 100644
--- a/arch/arm/mach-prima2/rstc.c
+++ b/arch/arm/mach-prima2/rstc.c
@@ -19,6 +19,7 @@
 
 static struct of_device_id rstc_ids[]  = {
 	{ .compatible = "sirf,prima2-rstc" },
+	{ .compatible = "sirf,marco-rstc" },
 	{},
 };
 
@@ -42,27 +43,37 @@
 
 int sirfsoc_reset_device(struct device *dev)
 {
-	const unsigned int *prop = of_get_property(dev->of_node, "reset-bit", NULL);
-	unsigned int reset_bit;
+	u32 reset_bit;
 
-	if (!prop)
-		return -ENODEV;
-
-	reset_bit = be32_to_cpup(prop);
+	if (of_property_read_u32(dev->of_node, "reset-bit", &reset_bit))
+		return -EINVAL;
 
 	mutex_lock(&rstc_lock);
 
-	/*
-	 * Writing 1 to this bit resets corresponding block. Writing 0 to this
-	 * bit de-asserts reset signal of the corresponding block.
-	 * datasheet doesn't require explicit delay between the set and clear
-	 * of reset bit. it could be shorter if tests pass.
-	 */
-	writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit,
-		sirfsoc_rstc_base + (reset_bit / 32) * 4);
-	msleep(10);
-	writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit,
-		sirfsoc_rstc_base + (reset_bit / 32) * 4);
+	if (of_device_is_compatible(dev->of_node, "sirf,prima2-rstc")) {
+		/*
+		 * Writing 1 to this bit resets corresponding block. Writing 0 to this
+		 * bit de-asserts reset signal of the corresponding block.
+		 * datasheet doesn't require explicit delay between the set and clear
+		 * of reset bit. it could be shorter if tests pass.
+		 */
+		writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) | reset_bit,
+			sirfsoc_rstc_base + (reset_bit / 32) * 4);
+		msleep(10);
+		writel(readl(sirfsoc_rstc_base + (reset_bit / 32) * 4) & ~reset_bit,
+			sirfsoc_rstc_base + (reset_bit / 32) * 4);
+	} else {
+		/*
+		 * For MARCO and POLO
+		 * Writing 1 to SET register resets corresponding block. Writing 1 to CLEAR
+		 * register de-asserts reset signal of the corresponding block.
+		 * datasheet doesn't require explicit delay between the set and clear
+		 * of reset bit. it could be shorter if tests pass.
+		 */
+		writel(reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8);
+		msleep(10);
+		writel(reset_bit, sirfsoc_rstc_base + (reset_bit / 32) * 8 + 4);
+	}
 
 	mutex_unlock(&rstc_lock);
 
diff --git a/arch/arm/mach-prima2/rtciobrg.c b/arch/arm/mach-prima2/rtciobrg.c
index 5573536..9f2da2e 100644
--- a/arch/arm/mach-prima2/rtciobrg.c
+++ b/arch/arm/mach-prima2/rtciobrg.c
@@ -104,6 +104,7 @@
 
 static const struct of_device_id rtciobrg_ids[] = {
 	{ .compatible = "sirf,prima2-rtciobg" },
+	{ .compatible = "sirf,marco-rtciobg" },
 	{}
 };
 
diff --git a/arch/arm/mach-prima2/timer-marco.c b/arch/arm/mach-prima2/timer-marco.c
new file mode 100644
index 0000000..f4eea2e
--- /dev/null
+++ b/arch/arm/mach-prima2/timer-marco.c
@@ -0,0 +1,316 @@
+/*
+ * System timer for CSR SiRFprimaII
+ *
+ * Copyright (c) 2011 Cambridge Silicon Radio Limited, a CSR plc group company.
+ *
+ * Licensed under GPLv2 or later.
+ */
+
+#include <linux/kernel.h>
+#include <linux/interrupt.h>
+#include <linux/clockchips.h>
+#include <linux/clocksource.h>
+#include <linux/bitops.h>
+#include <linux/irq.h>
+#include <linux/clk.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+#include <linux/of_irq.h>
+#include <linux/of_address.h>
+#include <asm/sched_clock.h>
+#include <asm/localtimer.h>
+#include <asm/mach/time.h>
+
+#include "common.h"
+
+#define SIRFSOC_TIMER_32COUNTER_0_CTRL			0x0000
+#define SIRFSOC_TIMER_32COUNTER_1_CTRL			0x0004
+#define SIRFSOC_TIMER_MATCH_0				0x0018
+#define SIRFSOC_TIMER_MATCH_1				0x001c
+#define SIRFSOC_TIMER_COUNTER_0				0x0048
+#define SIRFSOC_TIMER_COUNTER_1				0x004c
+#define SIRFSOC_TIMER_INTR_STATUS			0x0060
+#define SIRFSOC_TIMER_WATCHDOG_EN			0x0064
+#define SIRFSOC_TIMER_64COUNTER_CTRL			0x0068
+#define SIRFSOC_TIMER_64COUNTER_LO			0x006c
+#define SIRFSOC_TIMER_64COUNTER_HI			0x0070
+#define SIRFSOC_TIMER_64COUNTER_LOAD_LO			0x0074
+#define SIRFSOC_TIMER_64COUNTER_LOAD_HI			0x0078
+#define SIRFSOC_TIMER_64COUNTER_RLATCHED_LO		0x007c
+#define SIRFSOC_TIMER_64COUNTER_RLATCHED_HI		0x0080
+
+#define SIRFSOC_TIMER_REG_CNT 6
+
+static const u32 sirfsoc_timer_reg_list[SIRFSOC_TIMER_REG_CNT] = {
+	SIRFSOC_TIMER_WATCHDOG_EN,
+	SIRFSOC_TIMER_32COUNTER_0_CTRL,
+	SIRFSOC_TIMER_32COUNTER_1_CTRL,
+	SIRFSOC_TIMER_64COUNTER_CTRL,
+	SIRFSOC_TIMER_64COUNTER_RLATCHED_LO,
+	SIRFSOC_TIMER_64COUNTER_RLATCHED_HI,
+};
+
+static u32 sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT];
+
+static void __iomem *sirfsoc_timer_base;
+static void __init sirfsoc_of_timer_map(void);
+
+/* disable count and interrupt */
+static inline void sirfsoc_timer_count_disable(int idx)
+{
+	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) & ~0x7,
+		sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
+}
+
+/* enable count and interrupt */
+static inline void sirfsoc_timer_count_enable(int idx)
+{
+	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx) | 0x7,
+		sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL + 4 * idx);
+}
+
+/* timer interrupt handler */
+static irqreturn_t sirfsoc_timer_interrupt(int irq, void *dev_id)
+{
+	struct clock_event_device *ce = dev_id;
+	int cpu = smp_processor_id();
+
+	/* clear timer interrupt */
+	writel_relaxed(BIT(cpu), sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
+
+	if (ce->mode == CLOCK_EVT_MODE_ONESHOT)
+		sirfsoc_timer_count_disable(cpu);
+
+	ce->event_handler(ce);
+
+	return IRQ_HANDLED;
+}
+
+/* read 64-bit timer counter */
+static cycle_t sirfsoc_timer_read(struct clocksource *cs)
+{
+	u64 cycles;
+
+	writel_relaxed((readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
+			BIT(0)) & ~BIT(1), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
+
+	cycles = readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_HI);
+	cycles = (cycles << 32) | readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_RLATCHED_LO);
+
+	return cycles;
+}
+
+static int sirfsoc_timer_set_next_event(unsigned long delta,
+	struct clock_event_device *ce)
+{
+	int cpu = smp_processor_id();
+
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0 +
+		4 * cpu);
+	writel_relaxed(delta, sirfsoc_timer_base + SIRFSOC_TIMER_MATCH_0 +
+		4 * cpu);
+
+	/* enable the tick */
+	sirfsoc_timer_count_enable(cpu);
+
+	return 0;
+}
+
+static void sirfsoc_timer_set_mode(enum clock_event_mode mode,
+	struct clock_event_device *ce)
+{
+	switch (mode) {
+	case CLOCK_EVT_MODE_ONESHOT:
+		/* enable in set_next_event */
+		break;
+	default:
+		break;
+	}
+
+	sirfsoc_timer_count_disable(smp_processor_id());
+}
+
+static void sirfsoc_clocksource_suspend(struct clocksource *cs)
+{
+	int i;
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT; i++)
+		sirfsoc_timer_reg_val[i] = readl_relaxed(sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+}
+
+static void sirfsoc_clocksource_resume(struct clocksource *cs)
+{
+	int i;
+
+	for (i = 0; i < SIRFSOC_TIMER_REG_CNT - 2; i++)
+		writel_relaxed(sirfsoc_timer_reg_val[i], sirfsoc_timer_base + sirfsoc_timer_reg_list[i]);
+
+	writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 2],
+		sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
+	writel_relaxed(sirfsoc_timer_reg_val[SIRFSOC_TIMER_REG_CNT - 1],
+		sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
+
+	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
+		BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
+}
+
+static struct clock_event_device sirfsoc_clockevent = {
+	.name = "sirfsoc_clockevent",
+	.rating = 200,
+	.features = CLOCK_EVT_FEAT_ONESHOT,
+	.set_mode = sirfsoc_timer_set_mode,
+	.set_next_event = sirfsoc_timer_set_next_event,
+};
+
+static struct clocksource sirfsoc_clocksource = {
+	.name = "sirfsoc_clocksource",
+	.rating = 200,
+	.mask = CLOCKSOURCE_MASK(64),
+	.flags = CLOCK_SOURCE_IS_CONTINUOUS,
+	.read = sirfsoc_timer_read,
+	.suspend = sirfsoc_clocksource_suspend,
+	.resume = sirfsoc_clocksource_resume,
+};
+
+static struct irqaction sirfsoc_timer_irq = {
+	.name = "sirfsoc_timer0",
+	.flags = IRQF_TIMER | IRQF_NOBALANCING,
+	.handler = sirfsoc_timer_interrupt,
+	.dev_id = &sirfsoc_clockevent,
+};
+
+#ifdef CONFIG_LOCAL_TIMERS
+
+static struct irqaction sirfsoc_timer1_irq = {
+	.name = "sirfsoc_timer1",
+	.flags = IRQF_TIMER | IRQF_NOBALANCING,
+	.handler = sirfsoc_timer_interrupt,
+};
+
+static int __cpuinit sirfsoc_local_timer_setup(struct clock_event_device *ce)
+{
+	/* Use existing clock_event for cpu 0 */
+	if (!smp_processor_id())
+		return 0;
+
+	ce->irq = sirfsoc_timer1_irq.irq;
+	ce->name = "local_timer";
+	ce->features = sirfsoc_clockevent.features;
+	ce->rating = sirfsoc_clockevent.rating;
+	ce->set_mode = sirfsoc_timer_set_mode;
+	ce->set_next_event = sirfsoc_timer_set_next_event;
+	ce->shift = sirfsoc_clockevent.shift;
+	ce->mult = sirfsoc_clockevent.mult;
+	ce->max_delta_ns = sirfsoc_clockevent.max_delta_ns;
+	ce->min_delta_ns = sirfsoc_clockevent.min_delta_ns;
+
+	sirfsoc_timer1_irq.dev_id = ce;
+	BUG_ON(setup_irq(ce->irq, &sirfsoc_timer1_irq));
+	irq_set_affinity(sirfsoc_timer1_irq.irq, cpumask_of(1));
+
+	clockevents_register_device(ce);
+	return 0;
+}
+
+static void sirfsoc_local_timer_stop(struct clock_event_device *ce)
+{
+	sirfsoc_timer_count_disable(1);
+
+	remove_irq(sirfsoc_timer1_irq.irq, &sirfsoc_timer1_irq);
+}
+
+static struct local_timer_ops sirfsoc_local_timer_ops __cpuinitdata = {
+	.setup	= sirfsoc_local_timer_setup,
+	.stop	= sirfsoc_local_timer_stop,
+};
+#endif /* CONFIG_LOCAL_TIMERS */
+
+static void __init sirfsoc_clockevent_init(void)
+{
+	clockevents_calc_mult_shift(&sirfsoc_clockevent, CLOCK_TICK_RATE, 60);
+
+	sirfsoc_clockevent.max_delta_ns =
+		clockevent_delta2ns(-2, &sirfsoc_clockevent);
+	sirfsoc_clockevent.min_delta_ns =
+		clockevent_delta2ns(2, &sirfsoc_clockevent);
+
+	sirfsoc_clockevent.cpumask = cpumask_of(0);
+	clockevents_register_device(&sirfsoc_clockevent);
+#ifdef CONFIG_LOCAL_TIMERS
+	local_timer_register(&sirfsoc_local_timer_ops);
+#endif
+}
+
+/* initialize the kernel jiffy timer source */
+void __init sirfsoc_marco_timer_init(void)
+{
+	unsigned long rate;
+	u32 timer_div;
+	struct clk *clk;
+
+	/* initialize clocking early, we want to set the OS timer */
+	sirfsoc_of_clk_init();
+
+	/* timer's input clock is io clock */
+	clk = clk_get_sys("io", NULL);
+
+	BUG_ON(IS_ERR(clk));
+	rate = clk_get_rate(clk);
+
+	BUG_ON(rate < CLOCK_TICK_RATE);
+	BUG_ON(rate % CLOCK_TICK_RATE);
+
+	sirfsoc_of_timer_map();
+
+	/* Initialize the timer dividers */
+	timer_div = rate / CLOCK_TICK_RATE - 1;
+	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
+	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_0_CTRL);
+	writel_relaxed(timer_div << 16, sirfsoc_timer_base + SIRFSOC_TIMER_32COUNTER_1_CTRL);
+
+	/* Initialize timer counters to 0 */
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_LO);
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_LOAD_HI);
+	writel_relaxed(readl_relaxed(sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL) |
+		BIT(1) | BIT(0), sirfsoc_timer_base + SIRFSOC_TIMER_64COUNTER_CTRL);
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_0);
+	writel_relaxed(0, sirfsoc_timer_base + SIRFSOC_TIMER_COUNTER_1);
+
+	/* Clear all interrupts */
+	writel_relaxed(0xFFFF, sirfsoc_timer_base + SIRFSOC_TIMER_INTR_STATUS);
+
+	BUG_ON(clocksource_register_hz(&sirfsoc_clocksource, CLOCK_TICK_RATE));
+
+	BUG_ON(setup_irq(sirfsoc_timer_irq.irq, &sirfsoc_timer_irq));
+
+	sirfsoc_clockevent_init();
+}
+
+static struct of_device_id timer_ids[] = {
+	{ .compatible = "sirf,marco-tick" },
+	{},
+};
+
+static void __init sirfsoc_of_timer_map(void)
+{
+	struct device_node *np;
+
+	np = of_find_matching_node(NULL, timer_ids);
+	if (!np)
+		return;
+	sirfsoc_timer_base = of_iomap(np, 0);
+	if (!sirfsoc_timer_base)
+		panic("unable to map timer cpu registers\n");
+
+	sirfsoc_timer_irq.irq = irq_of_parse_and_map(np, 0);
+	if (!sirfsoc_timer_irq.irq)
+		panic("No irq passed for timer0 via DT\n");
+
+#ifdef CONFIG_LOCAL_TIMERS
+	sirfsoc_timer1_irq.irq = irq_of_parse_and_map(np, 1);
+	if (!sirfsoc_timer1_irq.irq)
+		panic("No irq passed for timer1 via DT\n");
+#endif
+
+	of_node_put(np);
+}
diff --git a/arch/arm/mach-prima2/timer.c b/arch/arm/mach-prima2/timer-prima2.c
similarity index 97%
rename from arch/arm/mach-prima2/timer.c
rename to arch/arm/mach-prima2/timer-prima2.c
index 4f69e67..6da584f 100644
--- a/arch/arm/mach-prima2/timer.c
+++ b/arch/arm/mach-prima2/timer-prima2.c
@@ -181,7 +181,7 @@
 }
 
 /* initialize the kernel jiffy timer source */
-static void __init sirfsoc_timer_init(void)
+void __init sirfsoc_prima2_timer_init(void)
 {
 	unsigned long rate;
 	struct clk *clk;
@@ -227,7 +227,7 @@
 
 	np = of_find_matching_node(NULL, timer_ids);
 	if (!np)
-		panic("unable to find compatible timer node in dtb\n");
+		return;
 	sirfsoc_timer_base = of_iomap(np, 0);
 	if (!sirfsoc_timer_base)
 		panic("unable to map timer cpu registers\n");
@@ -239,7 +239,3 @@
 
 	of_node_put(np);
 }
-
-struct sys_timer sirfsoc_timer = {
-	.init = sirfsoc_timer_init,
-};
diff --git a/arch/arm/mach-pxa/balloon3.c b/arch/arm/mach-pxa/balloon3.c
index 2082293..2f71b3f 100644
--- a/arch/arm/mach-pxa/balloon3.c
+++ b/arch/arm/mach-pxa/balloon3.c
@@ -822,7 +822,7 @@
 	.nr_irqs	= BALLOON3_NR_IRQS,
 	.init_irq	= balloon3_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= balloon3_init,
 	.atag_offset	= 0x100,
 	.restart	= pxa_restart,
diff --git a/arch/arm/mach-pxa/capc7117.c b/arch/arm/mach-pxa/capc7117.c
index 9a8760b..c092730 100644
--- a/arch/arm/mach-pxa/capc7117.c
+++ b/arch/arm/mach-pxa/capc7117.c
@@ -153,7 +153,7 @@
 	.nr_irqs = PXA_NR_IRQS,
 	.init_irq = pxa3xx_init_irq,
 	.handle_irq = pxa3xx_handle_irq,
-	.timer = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine = capc7117_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/cm-x2xx.c b/arch/arm/mach-pxa/cm-x2xx.c
index a103c8f..bb99f59 100644
--- a/arch/arm/mach-pxa/cm-x2xx.c
+++ b/arch/arm/mach-pxa/cm-x2xx.c
@@ -520,7 +520,7 @@
 	.init_irq	= cmx2xx_init_irq,
 	/* NOTE: pxa25x_handle_irq() works on PXA27x w/o camera support */
 	.handle_irq	= pxa25x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= cmx2xx_init,
 #ifdef CONFIG_PCI
 	.dma_zone_size	= SZ_64M,
diff --git a/arch/arm/mach-pxa/cm-x300.c b/arch/arm/mach-pxa/cm-x300.c
index cc2b23a..8091aac 100644
--- a/arch/arm/mach-pxa/cm-x300.c
+++ b/arch/arm/mach-pxa/cm-x300.c
@@ -854,7 +854,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= cm_x300_init,
 	.fixup		= cm_x300_fixup,
 	.restart	= pxa_restart,
diff --git a/arch/arm/mach-pxa/colibri-pxa270.c b/arch/arm/mach-pxa/colibri-pxa270.c
index b2f227d..5f9d930 100644
--- a/arch/arm/mach-pxa/colibri-pxa270.c
+++ b/arch/arm/mach-pxa/colibri-pxa270.c
@@ -313,7 +313,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 
@@ -324,7 +324,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 
diff --git a/arch/arm/mach-pxa/colibri-pxa300.c b/arch/arm/mach-pxa/colibri-pxa300.c
index a9c9c16..f1a1ac1 100644
--- a/arch/arm/mach-pxa/colibri-pxa300.c
+++ b/arch/arm/mach-pxa/colibri-pxa300.c
@@ -189,7 +189,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 
diff --git a/arch/arm/mach-pxa/colibri-pxa320.c b/arch/arm/mach-pxa/colibri-pxa320.c
index 25515cd..f6cc8b0 100644
--- a/arch/arm/mach-pxa/colibri-pxa320.c
+++ b/arch/arm/mach-pxa/colibri-pxa320.c
@@ -259,7 +259,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 
diff --git a/arch/arm/mach-pxa/corgi.c b/arch/arm/mach-pxa/corgi.c
index 7c83f52..a5b8fead 100644
--- a/arch/arm/mach-pxa/corgi.c
+++ b/arch/arm/mach-pxa/corgi.c
@@ -733,7 +733,7 @@
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
 	.init_machine	= corgi_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= corgi_restart,
 MACHINE_END
 #endif
@@ -746,7 +746,7 @@
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
 	.init_machine	= corgi_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= corgi_restart,
 MACHINE_END
 #endif
@@ -759,7 +759,7 @@
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
 	.init_machine	= corgi_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= corgi_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-pxa/csb726.c b/arch/arm/mach-pxa/csb726.c
index 7039f44..fadfff8 100644
--- a/arch/arm/mach-pxa/csb726.c
+++ b/arch/arm/mach-pxa/csb726.c
@@ -278,6 +278,6 @@
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
 	.init_machine   = csb726_init,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/em-x270.c b/arch/arm/mach-pxa/em-x270.c
index 1b64114..446563a 100644
--- a/arch/arm/mach-pxa/em-x270.c
+++ b/arch/arm/mach-pxa/em-x270.c
@@ -1298,7 +1298,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= em_x270_init,
 	.restart	= pxa_restart,
 MACHINE_END
@@ -1309,7 +1309,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= em_x270_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/eseries.c b/arch/arm/mach-pxa/eseries.c
index be2ee9b..8280ebc 100644
--- a/arch/arm/mach-pxa/eseries.c
+++ b/arch/arm/mach-pxa/eseries.c
@@ -195,7 +195,7 @@
 	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e330_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 #endif
@@ -246,7 +246,7 @@
 	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e350_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 #endif
@@ -370,7 +370,7 @@
 	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e400_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 #endif
@@ -566,7 +566,7 @@
 	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e740_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 #endif
@@ -765,7 +765,7 @@
 	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e750_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 #endif
@@ -977,7 +977,7 @@
 	.handle_irq	= pxa25x_handle_irq,
 	.fixup		= eseries_fixup,
 	.init_machine	= e800_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-pxa/ezx.c b/arch/arm/mach-pxa/ezx.c
index dc58fa0..dca1070 100644
--- a/arch/arm/mach-pxa/ezx.c
+++ b/arch/arm/mach-pxa/ezx.c
@@ -802,7 +802,7 @@
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine   = a780_init,
 	.restart	= pxa_restart,
 MACHINE_END
@@ -869,7 +869,7 @@
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine   = e680_init,
 	.restart	= pxa_restart,
 MACHINE_END
@@ -936,7 +936,7 @@
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine   = a1200_init,
 	.restart	= pxa_restart,
 MACHINE_END
@@ -1128,7 +1128,7 @@
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine   = a910_init,
 	.restart	= pxa_restart,
 MACHINE_END
@@ -1195,7 +1195,7 @@
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine   = e6_init,
 	.restart	= pxa_restart,
 MACHINE_END
@@ -1236,7 +1236,7 @@
 	.nr_irqs	= EZX_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine   = e2_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/generic.h b/arch/arm/mach-pxa/generic.h
index 42d5cca..fd7ea39 100644
--- a/arch/arm/mach-pxa/generic.h
+++ b/arch/arm/mach-pxa/generic.h
@@ -10,9 +10,8 @@
  */
 
 struct irq_data;
-struct sys_timer;
 
-extern struct sys_timer pxa_timer;
+extern void pxa_timer_init(void);
 
 extern void __init pxa_map_io(void);
 
diff --git a/arch/arm/mach-pxa/gumstix.c b/arch/arm/mach-pxa/gumstix.c
index 60755a6..00b92da 100644
--- a/arch/arm/mach-pxa/gumstix.c
+++ b/arch/arm/mach-pxa/gumstix.c
@@ -238,7 +238,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= gumstix_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/h5000.c b/arch/arm/mach-pxa/h5000.c
index e7dec58..875ec33 100644
--- a/arch/arm/mach-pxa/h5000.c
+++ b/arch/arm/mach-pxa/h5000.c
@@ -208,7 +208,7 @@
 	.nr_irqs = PXA_NR_IRQS,
 	.init_irq = pxa25x_init_irq,
 	.handle_irq = pxa25x_handle_irq,
-	.timer = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine = h5000_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/himalaya.c b/arch/arm/mach-pxa/himalaya.c
index 2962de8..7a8d749 100644
--- a/arch/arm/mach-pxa/himalaya.c
+++ b/arch/arm/mach-pxa/himalaya.c
@@ -164,6 +164,6 @@
 	.init_irq = pxa25x_init_irq,
 	.handle_irq = pxa25x_handle_irq,
 	.init_machine = himalaya_init,
-	.timer = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/hx4700.c b/arch/arm/mach-pxa/hx4700.c
index e2c6391..133109e 100644
--- a/arch/arm/mach-pxa/hx4700.c
+++ b/arch/arm/mach-pxa/hx4700.c
@@ -900,6 +900,6 @@
 	.init_irq     = pxa27x_init_irq,
 	.handle_irq     = pxa27x_handle_irq,
 	.init_machine = hx4700_init,
-	.timer        = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/icontrol.c b/arch/arm/mach-pxa/icontrol.c
index 1d02eab..fe31bfc 100644
--- a/arch/arm/mach-pxa/icontrol.c
+++ b/arch/arm/mach-pxa/icontrol.c
@@ -196,7 +196,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= icontrol_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/idp.c b/arch/arm/mach-pxa/idp.c
index 64507cd..343c4e3 100644
--- a/arch/arm/mach-pxa/idp.c
+++ b/arch/arm/mach-pxa/idp.c
@@ -279,7 +279,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= idp_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
index a611ad3..b6132aa 100644
--- a/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
+++ b/arch/arm/mach-pxa/include/mach/mfp-pxa27x.h
@@ -463,6 +463,9 @@
 	GPIO76_LCD_PCLK,	\
 	GPIO77_LCD_BIAS
 
+/* these enable a work-around for a hw bug in pxa27x during ac97 warm reset */
+#define GPIO113_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO113, AF0, DEFAULT)
+#define GPIO95_AC97_nRESET_GPIO_HIGH MFP_CFG_OUT(GPIO95, AF0, DEFAULT)
 
 extern int keypad_set_wake(unsigned int on);
 #endif /* __ASM_ARCH_MFP_PXA27X_H */
diff --git a/arch/arm/mach-pxa/littleton.c b/arch/arm/mach-pxa/littleton.c
index 402874f..e848c46 100644
--- a/arch/arm/mach-pxa/littleton.c
+++ b/arch/arm/mach-pxa/littleton.c
@@ -443,7 +443,7 @@
 	.nr_irqs	= LITTLETON_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= littleton_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/lpd270.c b/arch/arm/mach-pxa/lpd270.c
index 1a63eaa..1255ee0 100644
--- a/arch/arm/mach-pxa/lpd270.c
+++ b/arch/arm/mach-pxa/lpd270.c
@@ -503,7 +503,7 @@
 	.nr_irqs	= LPD270_NR_IRQS,
 	.init_irq	= lpd270_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= lpd270_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/lubbock.c b/arch/arm/mach-pxa/lubbock.c
index 553056d..d8a1be6 100644
--- a/arch/arm/mach-pxa/lubbock.c
+++ b/arch/arm/mach-pxa/lubbock.c
@@ -650,7 +650,7 @@
 	.nr_irqs	= LUBBOCK_NR_IRQS,
 	.init_irq	= lubbock_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= lubbock_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/magician.c b/arch/arm/mach-pxa/magician.c
index f792240..f44532f 100644
--- a/arch/arm/mach-pxa/magician.c
+++ b/arch/arm/mach-pxa/magician.c
@@ -774,6 +774,6 @@
 	.init_irq = pxa27x_init_irq,
 	.handle_irq = pxa27x_handle_irq,
 	.init_machine = magician_init,
-	.timer = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c
index f27a61e..7a12c1b 100644
--- a/arch/arm/mach-pxa/mainstone.c
+++ b/arch/arm/mach-pxa/mainstone.c
@@ -714,7 +714,7 @@
 	.nr_irqs	= MAINSTONE_NR_IRQS,
 	.init_irq	= mainstone_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= mainstone_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/mioa701.c b/arch/arm/mach-pxa/mioa701.c
index 2831308..f8979b94 100644
--- a/arch/arm/mach-pxa/mioa701.c
+++ b/arch/arm/mach-pxa/mioa701.c
@@ -762,6 +762,6 @@
 	.init_irq	= &pxa27x_init_irq,
 	.handle_irq	= &pxa27x_handle_irq,
 	.init_machine	= mioa701_machine_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= mioa701_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/mp900.c b/arch/arm/mach-pxa/mp900.c
index 152efbf..854f1f5 100644
--- a/arch/arm/mach-pxa/mp900.c
+++ b/arch/arm/mach-pxa/mp900.c
@@ -93,7 +93,7 @@
 /* Maintainer - Michael Petchkovsky <mkpetch@internode.on.net> */
 MACHINE_START(NEC_MP900, "MobilePro900/C")
 	.atag_offset	= 0x220100,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.map_io		= pxa25x_map_io,
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
diff --git a/arch/arm/mach-pxa/palmld.c b/arch/arm/mach-pxa/palmld.c
index 8bcc96e..909b713 100644
--- a/arch/arm/mach-pxa/palmld.c
+++ b/arch/arm/mach-pxa/palmld.c
@@ -347,7 +347,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= palmld_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmt5.c b/arch/arm/mach-pxa/palmt5.c
index 5ca7b90..5033fd0 100644
--- a/arch/arm/mach-pxa/palmt5.c
+++ b/arch/arm/mach-pxa/palmt5.c
@@ -208,7 +208,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= palmt5_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmtc.c b/arch/arm/mach-pxa/palmtc.c
index ca924cf..100b176f 100644
--- a/arch/arm/mach-pxa/palmtc.c
+++ b/arch/arm/mach-pxa/palmtc.c
@@ -542,7 +542,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= palmtc_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmte2.c b/arch/arm/mach-pxa/palmte2.c
index 32e0d79..0742721 100644
--- a/arch/arm/mach-pxa/palmte2.c
+++ b/arch/arm/mach-pxa/palmte2.c
@@ -363,7 +363,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= palmte2_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmtreo.c b/arch/arm/mach-pxa/palmtreo.c
index 3f3c48f..d17bda2 100644
--- a/arch/arm/mach-pxa/palmtreo.c
+++ b/arch/arm/mach-pxa/palmtreo.c
@@ -451,7 +451,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine   = treo680_init,
 	.restart	= pxa_restart,
 MACHINE_END
@@ -465,7 +465,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq       = pxa27x_init_irq,
 	.handle_irq       = pxa27x_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= centro_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmtx.c b/arch/arm/mach-pxa/palmtx.c
index 8b43666..627c93a 100644
--- a/arch/arm/mach-pxa/palmtx.c
+++ b/arch/arm/mach-pxa/palmtx.c
@@ -366,7 +366,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= palmtx_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/palmz72.c b/arch/arm/mach-pxa/palmz72.c
index 8cdd4f5..18b7fcd 100644
--- a/arch/arm/mach-pxa/palmz72.c
+++ b/arch/arm/mach-pxa/palmz72.c
@@ -404,7 +404,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= palmz72_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/pcm027.c b/arch/arm/mach-pxa/pcm027.c
index fe90544..69918c7 100644
--- a/arch/arm/mach-pxa/pcm027.c
+++ b/arch/arm/mach-pxa/pcm027.c
@@ -263,7 +263,7 @@
 	.nr_irqs	= PCM027_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= pcm027_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/poodle.c b/arch/arm/mach-pxa/poodle.c
index 2910bb9..50ccd5f 100644
--- a/arch/arm/mach-pxa/poodle.c
+++ b/arch/arm/mach-pxa/poodle.c
@@ -469,7 +469,7 @@
 	.nr_irqs	= POODLE_NR_IRQS,	/* 4 for LoCoMo */
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= poodle_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/pxa-dt.c b/arch/arm/mach-pxa/pxa-dt.c
index c9192ce..3835979 100644
--- a/arch/arm/mach-pxa/pxa-dt.c
+++ b/arch/arm/mach-pxa/pxa-dt.c
@@ -55,7 +55,7 @@
 	.map_io		= pxa3xx_map_io,
 	.init_irq	= pxa3xx_dt_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 	.init_machine	= pxa3xx_dt_init,
 	.dt_compat	= pxa3xx_dt_board_compat,
diff --git a/arch/arm/mach-pxa/pxa27x.c b/arch/arm/mach-pxa/pxa27x.c
index 8047ee0..616cb87 100644
--- a/arch/arm/mach-pxa/pxa27x.c
+++ b/arch/arm/mach-pxa/pxa27x.c
@@ -47,9 +47,9 @@
 EXPORT_SYMBOL(pxa27x_clear_otgph);
 
 static unsigned long ac97_reset_config[] = {
-	GPIO113_GPIO,
+	GPIO113_AC97_nRESET_GPIO_HIGH,
 	GPIO113_AC97_nRESET,
-	GPIO95_GPIO,
+	GPIO95_AC97_nRESET_GPIO_HIGH,
 	GPIO95_AC97_nRESET,
 };
 
diff --git a/arch/arm/mach-pxa/raumfeld.c b/arch/arm/mach-pxa/raumfeld.c
index 25b08bfa..af41888 100644
--- a/arch/arm/mach-pxa/raumfeld.c
+++ b/arch/arm/mach-pxa/raumfeld.c
@@ -1095,7 +1095,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 #endif
@@ -1108,7 +1108,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 #endif
@@ -1121,7 +1121,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-pxa/saar.c b/arch/arm/mach-pxa/saar.c
index 08d87a5..710c493 100644
--- a/arch/arm/mach-pxa/saar.c
+++ b/arch/arm/mach-pxa/saar.c
@@ -601,7 +601,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq       = pxa3xx_init_irq,
 	.handle_irq       = pxa3xx_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine   = saar_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/spitz.c b/arch/arm/mach-pxa/spitz.c
index 2073f0e..f90aa27 100644
--- a/arch/arm/mach-pxa/spitz.c
+++ b/arch/arm/mach-pxa/spitz.c
@@ -986,7 +986,7 @@
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
 	.init_machine	= spitz_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= spitz_restart,
 MACHINE_END
 #endif
@@ -1000,7 +1000,7 @@
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
 	.init_machine	= spitz_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= spitz_restart,
 MACHINE_END
 #endif
@@ -1014,7 +1014,7 @@
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
 	.init_machine	= spitz_init,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= spitz_restart,
 MACHINE_END
 #endif
diff --git a/arch/arm/mach-pxa/stargate2.c b/arch/arm/mach-pxa/stargate2.c
index 456560b..88fde43 100644
--- a/arch/arm/mach-pxa/stargate2.c
+++ b/arch/arm/mach-pxa/stargate2.c
@@ -1006,7 +1006,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= imote2_init,
 	.atag_offset	= 0x100,
 	.restart	= pxa_restart,
@@ -1019,7 +1019,7 @@
 	.nr_irqs = STARGATE_NR_IRQS,
 	.init_irq = pxa27x_init_irq,
 	.handle_irq = pxa27x_handle_irq,
-	.timer = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine = stargate2_init,
 	.atag_offset = 0x100,
 	.restart	= pxa_restart,
diff --git a/arch/arm/mach-pxa/tavorevb.c b/arch/arm/mach-pxa/tavorevb.c
index 1a25f8a..f55979c 100644
--- a/arch/arm/mach-pxa/tavorevb.c
+++ b/arch/arm/mach-pxa/tavorevb.c
@@ -494,7 +494,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq       = pxa3xx_init_irq,
 	.handle_irq       = pxa3xx_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine   = tavorevb_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/time.c b/arch/arm/mach-pxa/time.c
index 08cc47f..8f1ee92 100644
--- a/arch/arm/mach-pxa/time.c
+++ b/arch/arm/mach-pxa/time.c
@@ -89,44 +89,10 @@
 	}
 }
 
-static struct clock_event_device ckevt_pxa_osmr0 = {
-	.name		= "osmr0",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.set_next_event	= pxa_osmr0_set_next_event,
-	.set_mode	= pxa_osmr0_set_mode,
-};
-
-static struct irqaction pxa_ost0_irq = {
-	.name		= "ost0",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= pxa_ost0_interrupt,
-	.dev_id		= &ckevt_pxa_osmr0,
-};
-
-static void __init pxa_timer_init(void)
-{
-	unsigned long clock_tick_rate = get_clock_tick_rate();
-
-	writel_relaxed(0, OIER);
-	writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
-
-	setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate);
-
-	ckevt_pxa_osmr0.cpumask = cpumask_of(0);
-
-	setup_irq(IRQ_OST0, &pxa_ost0_irq);
-
-	clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32,
-		clocksource_mmio_readl_up);
-	clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate,
-					MIN_OSCR_DELTA * 2, 0x7fffffff);
-}
-
 #ifdef CONFIG_PM
 static unsigned long osmr[4], oier, oscr;
 
-static void pxa_timer_suspend(void)
+static void pxa_timer_suspend(struct clock_event_device *cedev)
 {
 	osmr[0] = readl_relaxed(OSMR0);
 	osmr[1] = readl_relaxed(OSMR1);
@@ -136,7 +102,7 @@
 	oscr = readl_relaxed(OSCR);
 }
 
-static void pxa_timer_resume(void)
+static void pxa_timer_resume(struct clock_event_device *cedev)
 {
 	/*
 	 * Ensure that we have at least MIN_OSCR_DELTA between match
@@ -159,8 +125,38 @@
 #define pxa_timer_resume NULL
 #endif
 
-struct sys_timer pxa_timer = {
-	.init		= pxa_timer_init,
+static struct clock_event_device ckevt_pxa_osmr0 = {
+	.name		= "osmr0",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.set_next_event	= pxa_osmr0_set_next_event,
+	.set_mode	= pxa_osmr0_set_mode,
 	.suspend	= pxa_timer_suspend,
 	.resume		= pxa_timer_resume,
 };
+
+static struct irqaction pxa_ost0_irq = {
+	.name		= "ost0",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= pxa_ost0_interrupt,
+	.dev_id		= &ckevt_pxa_osmr0,
+};
+
+void __init pxa_timer_init(void)
+{
+	unsigned long clock_tick_rate = get_clock_tick_rate();
+
+	writel_relaxed(0, OIER);
+	writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
+
+	setup_sched_clock(pxa_read_sched_clock, 32, clock_tick_rate);
+
+	ckevt_pxa_osmr0.cpumask = cpumask_of(0);
+
+	setup_irq(IRQ_OST0, &pxa_ost0_irq);
+
+	clocksource_mmio_init(OSCR, "oscr0", clock_tick_rate, 200, 32,
+		clocksource_mmio_readl_up);
+	clockevents_config_and_register(&ckevt_pxa_osmr0, clock_tick_rate,
+		MIN_OSCR_DELTA * 2, 0x7fffffff);
+}
diff --git a/arch/arm/mach-pxa/tosa.c b/arch/arm/mach-pxa/tosa.c
index 233629e..9e7998d 100644
--- a/arch/arm/mach-pxa/tosa.c
+++ b/arch/arm/mach-pxa/tosa.c
@@ -982,6 +982,6 @@
 	.init_irq       = pxa25x_init_irq,
 	.handle_irq       = pxa25x_handle_irq,
 	.init_machine   = tosa_init,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= tosa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/trizeps4.c b/arch/arm/mach-pxa/trizeps4.c
index fbbcbed..c580434 100644
--- a/arch/arm/mach-pxa/trizeps4.c
+++ b/arch/arm/mach-pxa/trizeps4.c
@@ -561,7 +561,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 
@@ -573,6 +573,6 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/viper.c b/arch/arm/mach-pxa/viper.c
index c773e4d..9c363c0 100644
--- a/arch/arm/mach-pxa/viper.c
+++ b/arch/arm/mach-pxa/viper.c
@@ -997,7 +997,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= viper_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
-	.timer          = &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= viper_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/vpac270.c b/arch/arm/mach-pxa/vpac270.c
index 491b6c9..aa89488 100644
--- a/arch/arm/mach-pxa/vpac270.c
+++ b/arch/arm/mach-pxa/vpac270.c
@@ -719,7 +719,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= vpac270_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/xcep.c b/arch/arm/mach-pxa/xcep.c
index 4275713..13b1d45 100644
--- a/arch/arm/mach-pxa/xcep.c
+++ b/arch/arm/mach-pxa/xcep.c
@@ -185,7 +185,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa25x_init_irq,
 	.handle_irq	= pxa25x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.restart	= pxa_restart,
 MACHINE_END
 
diff --git a/arch/arm/mach-pxa/z2.c b/arch/arm/mach-pxa/z2.c
index 97529fa..989903a 100644
--- a/arch/arm/mach-pxa/z2.c
+++ b/arch/arm/mach-pxa/z2.c
@@ -722,7 +722,7 @@
 	.nr_irqs	= PXA_NR_IRQS,
 	.init_irq	= pxa27x_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= z2_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/zeus.c b/arch/arm/mach-pxa/zeus.c
index abd3aa1..f5d4364 100644
--- a/arch/arm/mach-pxa/zeus.c
+++ b/arch/arm/mach-pxa/zeus.c
@@ -910,7 +910,7 @@
 	.nr_irqs	= ZEUS_NR_IRQS,
 	.init_irq	= zeus_init_irq,
 	.handle_irq	= pxa27x_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= zeus_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-pxa/zylonite.c b/arch/arm/mach-pxa/zylonite.c
index 226279f..1f00d65 100644
--- a/arch/arm/mach-pxa/zylonite.c
+++ b/arch/arm/mach-pxa/zylonite.c
@@ -428,7 +428,7 @@
 	.nr_irqs	= ZYLONITE_NR_IRQS,
 	.init_irq	= pxa3xx_init_irq,
 	.handle_irq	= pxa3xx_handle_irq,
-	.timer		= &pxa_timer,
+	.init_time	= pxa_timer_init,
 	.init_machine	= zylonite_init,
 	.restart	= pxa_restart,
 MACHINE_END
diff --git a/arch/arm/mach-realview/core.c b/arch/arm/mach-realview/core.c
index 6824674..1d5ee5c 100644
--- a/arch/arm/mach-realview/core.c
+++ b/arch/arm/mach-realview/core.c
@@ -42,7 +42,6 @@
 #include <asm/mach/irq.h>
 #include <asm/mach/map.h>
 
-#include <asm/hardware/gic.h>
 
 #include <mach/platform.h>
 #include <mach/irqs.h>
diff --git a/arch/arm/mach-realview/platsmp.c b/arch/arm/mach-realview/platsmp.c
index 300f706..98e3052 100644
--- a/arch/arm/mach-realview/platsmp.c
+++ b/arch/arm/mach-realview/platsmp.c
@@ -14,7 +14,6 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/smp_scu.h>
 
@@ -59,8 +58,6 @@
 
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
 
 static void __init realview_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-realview/realview_eb.c b/arch/arm/mach-realview/realview_eb.c
index 28511d4..5b1c8bf 100644
--- a/arch/arm/mach-realview/realview_eb.c
+++ b/arch/arm/mach-realview/realview_eb.c
@@ -27,13 +27,13 @@
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/clk-realview.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/pgtable.h>
-#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/smp_twd.h>
 
@@ -418,10 +418,6 @@
 	realview_eb_twd_init();
 }
 
-static struct sys_timer realview_eb_timer = {
-	.init		= realview_eb_timer_init,
-};
-
 static void realview_eb_restart(char mode, const char *cmd)
 {
 	void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL);
@@ -472,8 +468,7 @@
 	.map_io		= realview_eb_map_io,
 	.init_early	= realview_init_early,
 	.init_irq	= gic_init_irq,
-	.timer		= &realview_eb_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= realview_eb_timer_init,
 	.init_machine	= realview_eb_init,
 #ifdef CONFIG_ZONE_DMA
 	.dma_zone_size	= SZ_256M,
diff --git a/arch/arm/mach-realview/realview_pb1176.c b/arch/arm/mach-realview/realview_pb1176.c
index 07d6672..d5e83a1 100644
--- a/arch/arm/mach-realview/realview_pb1176.c
+++ b/arch/arm/mach-realview/realview_pb1176.c
@@ -29,13 +29,13 @@
 #include <linux/mtd/physmap.h>
 #include <linux/mtd/partitions.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/clk-realview.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/pgtable.h>
-#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 
 #include <asm/mach/arch.h>
@@ -329,10 +329,6 @@
 	realview_timer_init(IRQ_DC1176_TIMER0);
 }
 
-static struct sys_timer realview_pb1176_timer = {
-	.init		= realview_pb1176_timer_init,
-};
-
 static void realview_pb1176_restart(char mode, const char *cmd)
 {
 	void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL);
@@ -384,8 +380,7 @@
 	.map_io		= realview_pb1176_map_io,
 	.init_early	= realview_init_early,
 	.init_irq	= gic_init_irq,
-	.timer		= &realview_pb1176_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= realview_pb1176_timer_init,
 	.init_machine	= realview_pb1176_init,
 #ifdef CONFIG_ZONE_DMA
 	.dma_zone_size	= SZ_256M,
diff --git a/arch/arm/mach-realview/realview_pb11mp.c b/arch/arm/mach-realview/realview_pb11mp.c
index 7ed53d7..c3cfe21 100644
--- a/arch/arm/mach-realview/realview_pb11mp.c
+++ b/arch/arm/mach-realview/realview_pb11mp.c
@@ -27,13 +27,13 @@
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/clk-realview.h>
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/pgtable.h>
-#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/smp_twd.h>
 
@@ -316,10 +316,6 @@
 	realview_pb11mp_twd_init();
 }
 
-static struct sys_timer realview_pb11mp_timer = {
-	.init		= realview_pb11mp_timer_init,
-};
-
 static void realview_pb11mp_restart(char mode, const char *cmd)
 {
 	void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL);
@@ -367,8 +363,7 @@
 	.map_io		= realview_pb11mp_map_io,
 	.init_early	= realview_init_early,
 	.init_irq	= gic_init_irq,
-	.timer		= &realview_pb11mp_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= realview_pb11mp_timer_init,
 	.init_machine	= realview_pb11mp_init,
 #ifdef CONFIG_ZONE_DMA
 	.dma_zone_size	= SZ_256M,
diff --git a/arch/arm/mach-realview/realview_pba8.c b/arch/arm/mach-realview/realview_pba8.c
index 9992431..dde652a 100644
--- a/arch/arm/mach-realview/realview_pba8.c
+++ b/arch/arm/mach-realview/realview_pba8.c
@@ -27,12 +27,12 @@
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/clk-realview.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/pgtable.h>
-#include <asm/hardware/gic.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -264,10 +264,6 @@
 	realview_timer_init(IRQ_PBA8_TIMER0_1);
 }
 
-static struct sys_timer realview_pba8_timer = {
-	.init		= realview_pba8_timer_init,
-};
-
 static void realview_pba8_restart(char mode, const char *cmd)
 {
 	void __iomem *reset_ctrl = __io_address(REALVIEW_SYS_RESETCTL);
@@ -308,8 +304,7 @@
 	.map_io		= realview_pba8_map_io,
 	.init_early	= realview_init_early,
 	.init_irq	= gic_init_irq,
-	.timer		= &realview_pba8_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= realview_pba8_timer_init,
 	.init_machine	= realview_pba8_init,
 #ifdef CONFIG_ZONE_DMA
 	.dma_zone_size	= SZ_256M,
diff --git a/arch/arm/mach-realview/realview_pbx.c b/arch/arm/mach-realview/realview_pbx.c
index 4f486f0..54f0185 100644
--- a/arch/arm/mach-realview/realview_pbx.c
+++ b/arch/arm/mach-realview/realview_pbx.c
@@ -26,13 +26,13 @@
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/clk-realview.h>
 
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 #include <asm/smp_twd.h>
 #include <asm/pgtable.h>
-#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 
 #include <asm/mach/arch.h>
@@ -324,10 +324,6 @@
 	realview_pbx_twd_init();
 }
 
-static struct sys_timer realview_pbx_timer = {
-	.init		= realview_pbx_timer_init,
-};
-
 static void realview_pbx_fixup(struct tag *tags, char **from,
 			       struct meminfo *meminfo)
 {
@@ -404,8 +400,7 @@
 	.map_io		= realview_pbx_map_io,
 	.init_early	= realview_init_early,
 	.init_irq	= gic_init_irq,
-	.timer		= &realview_pbx_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= realview_pbx_timer_init,
 	.init_machine	= realview_pbx_init,
 #ifdef CONFIG_ZONE_DMA
 	.dma_zone_size	= SZ_256M,
diff --git a/arch/arm/mach-rpc/riscpc.c b/arch/arm/mach-rpc/riscpc.c
index f3fa259c..a302cf5 100644
--- a/arch/arm/mach-rpc/riscpc.c
+++ b/arch/arm/mach-rpc/riscpc.c
@@ -211,7 +211,7 @@
 	soft_restart(0);
 }
 
-extern struct sys_timer ioc_timer;
+void ioc_timer_init(void);
 
 MACHINE_START(RISCPC, "Acorn-RiscPC")
 	/* Maintainer: Russell King */
@@ -220,6 +220,6 @@
 	.reserve_lp1	= 1,
 	.map_io		= rpc_map_io,
 	.init_irq	= rpc_init_irq,
-	.timer		= &ioc_timer,
+	.init_time	= ioc_timer_init,
 	.restart	= rpc_restart,
 MACHINE_END
diff --git a/arch/arm/mach-rpc/time.c b/arch/arm/mach-rpc/time.c
index 581fca9..9a6def1 100644
--- a/arch/arm/mach-rpc/time.c
+++ b/arch/arm/mach-rpc/time.c
@@ -24,7 +24,7 @@
 
 #include <asm/mach/time.h>
 
-unsigned long ioc_timer_gettimeoffset(void)
+static u32 ioc_timer_gettimeoffset(void)
 {
 	unsigned int count1, count2, status;
 	long offset;
@@ -56,7 +56,7 @@
 	}
 
 	offset = (LATCH - offset) * (tick_nsec / 1000);
-	return (offset + LATCH/2) / LATCH;
+	return ((offset + LATCH/2) / LATCH) * 1000;
 }
 
 void __init ioctime_init(void)
@@ -82,14 +82,9 @@
 /*
  * Set up timer interrupt.
  */
-static void __init ioc_timer_init(void)
+void __init ioc_timer_init(void)
 {
+	arch_gettimeoffset = ioc_timer_gettimeoffset;
 	ioctime_init();
 	setup_irq(IRQ_TIMER0, &ioc_timer_irq);
 }
-
-struct sys_timer ioc_timer = {
-	.init		= ioc_timer_init,
-	.offset		= ioc_timer_gettimeoffset,
-};
-
diff --git a/arch/arm/mach-s3c24xx/mach-amlm5900.c b/arch/arm/mach-s3c24xx/mach-amlm5900.c
index f4ad99c..0e0279e 100644
--- a/arch/arm/mach-s3c24xx/mach-amlm5900.c
+++ b/arch/arm/mach-s3c24xx/mach-amlm5900.c
@@ -237,6 +237,6 @@
 	.map_io		= amlm5900_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= amlm5900_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-anubis.c b/arch/arm/mach-s3c24xx/mach-anubis.c
index 1ee8c46..85eefab 100644
--- a/arch/arm/mach-s3c24xx/mach-anubis.c
+++ b/arch/arm/mach-s3c24xx/mach-anubis.c
@@ -448,6 +448,6 @@
 	.map_io		= anubis_map_io,
 	.init_machine	= anubis_init,
 	.init_irq	= s3c24xx_init_irq,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-at2440evb.c b/arch/arm/mach-s3c24xx/mach-at2440evb.c
index 00381fe..b31c4aa 100644
--- a/arch/arm/mach-s3c24xx/mach-at2440evb.c
+++ b/arch/arm/mach-s3c24xx/mach-at2440evb.c
@@ -210,6 +210,6 @@
 	.map_io		= at2440evb_map_io,
 	.init_machine	= at2440evb_init,
 	.init_irq	= s3c24xx_init_irq,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-bast.c b/arch/arm/mach-s3c24xx/mach-bast.c
index 6a30ce7..526964c 100644
--- a/arch/arm/mach-s3c24xx/mach-bast.c
+++ b/arch/arm/mach-s3c24xx/mach-bast.c
@@ -612,6 +612,6 @@
 	.map_io		= bast_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= bast_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-gta02.c b/arch/arm/mach-s3c24xx/mach-gta02.c
index 973b87c..fb5d3b3 100644
--- a/arch/arm/mach-s3c24xx/mach-gta02.c
+++ b/arch/arm/mach-s3c24xx/mach-gta02.c
@@ -595,6 +595,6 @@
 	.map_io		= gta02_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= gta02_machine_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-h1940.c b/arch/arm/mach-s3c24xx/mach-h1940.c
index b23dd1b..2eb09e2 100644
--- a/arch/arm/mach-s3c24xx/mach-h1940.c
+++ b/arch/arm/mach-s3c24xx/mach-h1940.c
@@ -746,6 +746,6 @@
 	.reserve	= h1940_reserve,
 	.init_irq	= h1940_init_irq,
 	.init_machine	= h1940_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-jive.c b/arch/arm/mach-s3c24xx/mach-jive.c
index c9954e2..d7a1725 100644
--- a/arch/arm/mach-s3c24xx/mach-jive.c
+++ b/arch/arm/mach-s3c24xx/mach-jive.c
@@ -661,6 +661,6 @@
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= jive_map_io,
 	.init_machine	= jive_machine_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2412_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-mini2440.c b/arch/arm/mach-s3c24xx/mach-mini2440.c
index a31d5b8..2db09ade 100644
--- a/arch/arm/mach-s3c24xx/mach-mini2440.c
+++ b/arch/arm/mach-s3c24xx/mach-mini2440.c
@@ -688,6 +688,6 @@
 	.map_io		= mini2440_map_io,
 	.init_machine	= mini2440_init,
 	.init_irq	= s3c24xx_init_irq,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-n30.c b/arch/arm/mach-s3c24xx/mach-n30.c
index c53a9bf..d9d04b2 100644
--- a/arch/arm/mach-s3c24xx/mach-n30.c
+++ b/arch/arm/mach-s3c24xx/mach-n30.c
@@ -589,7 +589,7 @@
 				Ben Dooks <ben-linux@fluff.org>
 	*/
 	.atag_offset	= 0x100,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.init_machine	= n30_init,
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= n30_map_io,
@@ -600,7 +600,7 @@
 	/* Maintainer: Christer Weinigel <christer@weinigel.se>
 	*/
 	.atag_offset	= 0x100,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.init_machine	= n30_init,
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= n30_map_io,
diff --git a/arch/arm/mach-s3c24xx/mach-nexcoder.c b/arch/arm/mach-s3c24xx/mach-nexcoder.c
index a2b92b0..a454e24 100644
--- a/arch/arm/mach-s3c24xx/mach-nexcoder.c
+++ b/arch/arm/mach-s3c24xx/mach-nexcoder.c
@@ -153,6 +153,6 @@
 	.map_io		= nexcoder_map_io,
 	.init_machine	= nexcoder_init,
 	.init_irq	= s3c24xx_init_irq,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-osiris.c b/arch/arm/mach-s3c24xx/mach-osiris.c
index bb36d83..ba0f5b5 100644
--- a/arch/arm/mach-s3c24xx/mach-osiris.c
+++ b/arch/arm/mach-s3c24xx/mach-osiris.c
@@ -428,6 +428,6 @@
 	.map_io		= osiris_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= osiris_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-otom.c b/arch/arm/mach-s3c24xx/mach-otom.c
index bca39f0..e0fdae9 100644
--- a/arch/arm/mach-s3c24xx/mach-otom.c
+++ b/arch/arm/mach-s3c24xx/mach-otom.c
@@ -118,6 +118,6 @@
 	.map_io		= otom11_map_io,
 	.init_machine	= otom11_init,
 	.init_irq	= s3c24xx_init_irq,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-qt2410.c b/arch/arm/mach-s3c24xx/mach-qt2410.c
index 7b6ba13..56175f0 100644
--- a/arch/arm/mach-s3c24xx/mach-qt2410.c
+++ b/arch/arm/mach-s3c24xx/mach-qt2410.c
@@ -343,6 +343,6 @@
 	.map_io		= qt2410_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= qt2410_machine_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-rx1950.c b/arch/arm/mach-s3c24xx/mach-rx1950.c
index 0606f2f..e14ec71 100644
--- a/arch/arm/mach-s3c24xx/mach-rx1950.c
+++ b/arch/arm/mach-s3c24xx/mach-rx1950.c
@@ -814,6 +814,6 @@
 	.reserve	= rx1950_reserve,
 	.init_irq = s3c24xx_init_irq,
 	.init_machine = rx1950_init_machine,
-	.timer = &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-rx3715.c b/arch/arm/mach-s3c24xx/mach-rx3715.c
index dacbb9a..d00caa8 100644
--- a/arch/arm/mach-s3c24xx/mach-rx3715.c
+++ b/arch/arm/mach-s3c24xx/mach-rx3715.c
@@ -212,6 +212,6 @@
 	.reserve	= rx3715_reserve,
 	.init_irq	= rx3715_init_irq,
 	.init_machine	= rx3715_init_machine,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2410.c b/arch/arm/mach-s3c24xx/mach-smdk2410.c
index 82796b9..e184bfa 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2410.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2410.c
@@ -117,6 +117,6 @@
 	.map_io		= smdk2410_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= smdk2410_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2413.c b/arch/arm/mach-s3c24xx/mach-smdk2413.c
index ce99fd8..69f356e 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2413.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2413.c
@@ -133,7 +133,7 @@
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2413_map_io,
 	.init_machine	= smdk2413_machine_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2412_restart,
 MACHINE_END
 
@@ -145,7 +145,7 @@
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2413_map_io,
 	.init_machine	= smdk2413_machine_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2412_restart,
 MACHINE_END
 
@@ -157,6 +157,6 @@
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2413_map_io,
 	.init_machine	= smdk2413_machine_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2412_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2416.c b/arch/arm/mach-s3c24xx/mach-smdk2416.c
index f30d7fc..fe160c7 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2416.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2416.c
@@ -254,6 +254,6 @@
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2416_map_io,
 	.init_machine	= smdk2416_machine_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2416_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2440.c b/arch/arm/mach-s3c24xx/mach-smdk2440.c
index b7ff882..a8fdafe 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2440.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2440.c
@@ -182,6 +182,6 @@
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2440_map_io,
 	.init_machine	= smdk2440_machine_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c244x_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-smdk2443.c b/arch/arm/mach-s3c24xx/mach-smdk2443.c
index 2568656..7830d70 100644
--- a/arch/arm/mach-s3c24xx/mach-smdk2443.c
+++ b/arch/arm/mach-s3c24xx/mach-smdk2443.c
@@ -144,6 +144,6 @@
 	.init_irq	= s3c24xx_init_irq,
 	.map_io		= smdk2443_map_io,
 	.init_machine	= smdk2443_machine_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2443_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-tct_hammer.c b/arch/arm/mach-s3c24xx/mach-tct_hammer.c
index 495bf5c..24b3d79 100644
--- a/arch/arm/mach-s3c24xx/mach-tct_hammer.c
+++ b/arch/arm/mach-s3c24xx/mach-tct_hammer.c
@@ -149,6 +149,6 @@
 	.map_io		= tct_hammer_map_io,
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= tct_hammer_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-vr1000.c b/arch/arm/mach-s3c24xx/mach-vr1000.c
index 14d5b12..dda21a0 100644
--- a/arch/arm/mach-s3c24xx/mach-vr1000.c
+++ b/arch/arm/mach-s3c24xx/mach-vr1000.c
@@ -357,6 +357,6 @@
 	.map_io		= vr1000_map_io,
 	.init_machine	= vr1000_init,
 	.init_irq	= s3c24xx_init_irq,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2410_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c24xx/mach-vstms.c b/arch/arm/mach-s3c24xx/mach-vstms.c
index f1d44ae..7fe7d4f 100644
--- a/arch/arm/mach-s3c24xx/mach-vstms.c
+++ b/arch/arm/mach-s3c24xx/mach-vstms.c
@@ -161,6 +161,6 @@
 	.init_irq	= s3c24xx_init_irq,
 	.init_machine	= vstms_init,
 	.map_io		= vstms_map_io,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c2412_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/common.c b/arch/arm/mach-s3c64xx/common.c
index aef303b..0b9c0ba 100644
--- a/arch/arm/mach-s3c64xx/common.c
+++ b/arch/arm/mach-s3c64xx/common.c
@@ -25,10 +25,10 @@
 #include <linux/dma-mapping.h>
 #include <linux/irq.h>
 #include <linux/gpio.h>
+#include <linux/irqchip/arm-vic.h>
 
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
-#include <asm/hardware/vic.h>
 #include <asm/system_misc.h>
 
 #include <mach/map.h>
diff --git a/arch/arm/mach-s3c64xx/include/mach/regs-irq.h b/arch/arm/mach-s3c64xx/include/mach/regs-irq.h
index bcce68a..6a112789 100644
--- a/arch/arm/mach-s3c64xx/include/mach/regs-irq.h
+++ b/arch/arm/mach-s3c64xx/include/mach/regs-irq.h
@@ -15,6 +15,5 @@
 #ifndef __ASM_ARCH_REGS_IRQ_H
 #define __ASM_ARCH_REGS_IRQ_H __FILE__
 
-#include <asm/hardware/vic.h>
 
 #endif /* __ASM_ARCH_6400_REGS_IRQ_H */
diff --git a/arch/arm/mach-s3c64xx/include/mach/tick.h b/arch/arm/mach-s3c64xx/include/mach/tick.h
index ebe18a9..db9c1b1 100644
--- a/arch/arm/mach-s3c64xx/include/mach/tick.h
+++ b/arch/arm/mach-s3c64xx/include/mach/tick.h
@@ -15,6 +15,8 @@
 #ifndef __ASM_ARCH_TICK_H
 #define __ASM_ARCH_TICK_H __FILE__
 
+#include <linux/irqchip/arm-vic.h>
+
 /* note, the timer interrutps turn up in 2 places, the vic and then
  * the timer block. We take the VIC as the base at the moment.
  */
diff --git a/arch/arm/mach-s3c64xx/mach-anw6410.c b/arch/arm/mach-s3c64xx/mach-anw6410.c
index 99e82ac..afeae0b 100644
--- a/arch/arm/mach-s3c64xx/mach-anw6410.c
+++ b/arch/arm/mach-s3c64xx/mach-anw6410.c
@@ -31,7 +31,6 @@
 #include <video/platform_lcd.h>
 #include <video/samsung_fimd.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -230,10 +229,9 @@
 	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6410_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= anw6410_map_io,
 	.init_machine	= anw6410_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410-module.c b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
index 553059f..755c0bb 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410-module.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410-module.c
@@ -47,7 +47,7 @@
 		.bus_num	= 0,
 		.chip_select	= 0,
 		.mode		= SPI_MODE_0,
-		.irq		= S3C_EINT(5),
+		.irq		= S3C_EINT(4),
 		.controller_data = &wm0010_spi_csinfo,
 		.platform_data = &wm0010_pdata,
 	},
diff --git a/arch/arm/mach-s3c64xx/mach-crag6410.c b/arch/arm/mach-s3c64xx/mach-crag6410.c
index bf6311a..5b6adc7 100644
--- a/arch/arm/mach-s3c64xx/mach-crag6410.c
+++ b/arch/arm/mach-s3c64xx/mach-crag6410.c
@@ -42,7 +42,6 @@
 
 #include <sound/wm1250-ev1.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach-types.h>
 
@@ -867,10 +866,9 @@
 	/* Maintainer: Mark Brown <broonie@opensource.wolfsonmicro.com> */
 	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= crag6410_map_io,
 	.init_machine	= crag6410_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-hmt.c b/arch/arm/mach-s3c64xx/mach-hmt.c
index 2b14489..7212eb9 100644
--- a/arch/arm/mach-s3c64xx/mach-hmt.c
+++ b/arch/arm/mach-s3c64xx/mach-hmt.c
@@ -30,7 +30,6 @@
 #include <mach/hardware.h>
 #include <mach/map.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
@@ -273,10 +272,9 @@
 	/* Maintainer: Peter Korsgaard <jacmet@sunsite.dk> */
 	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= hmt_map_io,
 	.init_machine	= hmt_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-mini6410.c b/arch/arm/mach-s3c64xx/mach-mini6410.c
index 07c349c..e173e6e 100644
--- a/arch/arm/mach-s3c64xx/mach-mini6410.c
+++ b/arch/arm/mach-s3c64xx/mach-mini6410.c
@@ -24,7 +24,6 @@
 #include <linux/serial_core.h>
 #include <linux/types.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -352,10 +351,9 @@
 	/* Maintainer: Darius Augulis <augulis.darius@gmail.com> */
 	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= mini6410_map_io,
 	.init_machine	= mini6410_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-ncp.c b/arch/arm/mach-s3c64xx/mach-ncp.c
index e5f9a79..8d3cedd 100644
--- a/arch/arm/mach-s3c64xx/mach-ncp.c
+++ b/arch/arm/mach-s3c64xx/mach-ncp.c
@@ -26,7 +26,6 @@
 #include <video/platform_lcd.h>
 #include <video/samsung_fimd.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -101,10 +100,9 @@
 	/* Maintainer: Samsung Electronics */
 	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= ncp_map_io,
 	.init_machine	= ncp_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-real6410.c b/arch/arm/mach-s3c64xx/mach-real6410.c
index 7476f7c..4d0d47a 100644
--- a/arch/arm/mach-s3c64xx/mach-real6410.c
+++ b/arch/arm/mach-s3c64xx/mach-real6410.c
@@ -25,7 +25,6 @@
 #include <linux/serial_core.h>
 #include <linux/types.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
@@ -331,10 +330,9 @@
 	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6410_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= real6410_map_io,
 	.init_machine	= real6410_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smartq5.c b/arch/arm/mach-s3c64xx/mach-smartq5.c
index 96d6da2..ca2afcf 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq5.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq5.c
@@ -17,7 +17,6 @@
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -153,10 +152,9 @@
 	/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
 	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= smartq_map_io,
 	.init_machine	= smartq5_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smartq7.c b/arch/arm/mach-s3c64xx/mach-smartq7.c
index 7d1167b..37bb0c6 100644
--- a/arch/arm/mach-s3c64xx/mach-smartq7.c
+++ b/arch/arm/mach-s3c64xx/mach-smartq7.c
@@ -17,7 +17,6 @@
 #include <linux/leds.h>
 #include <linux/platform_device.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -169,10 +168,9 @@
 	/* Maintainer: Maurus Cuelenaere <mcuelenaere AT gmail DOT com> */
 	.atag_offset	= 0x100,
 	.init_irq	= s3c6410_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= smartq_map_io,
 	.init_machine	= smartq7_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6400.c b/arch/arm/mach-s3c64xx/mach-smdk6400.c
index a928fae..a392869 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6400.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6400.c
@@ -22,7 +22,6 @@
 
 #include <asm/mach-types.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -90,10 +89,9 @@
 	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6400_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= smdk6400_map_io,
 	.init_machine	= smdk6400_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/mach-smdk6410.c b/arch/arm/mach-s3c64xx/mach-smdk6410.c
index 574a9ee..1663d10 100644
--- a/arch/arm/mach-s3c64xx/mach-smdk6410.c
+++ b/arch/arm/mach-s3c64xx/mach-smdk6410.c
@@ -45,7 +45,6 @@
 #include <video/platform_lcd.h>
 #include <video/samsung_fimd.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/irq.h>
@@ -700,10 +699,9 @@
 	.atag_offset	= 0x100,
 
 	.init_irq	= s3c6410_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= smdk6410_map_io,
 	.init_machine	= smdk6410_machine_init,
 	.init_late	= s3c64xx_init_late,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s3c64xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s3c64xx/pm.c b/arch/arm/mach-s3c64xx/pm.c
index 7feb426..d2e1a16 100644
--- a/arch/arm/mach-s3c64xx/pm.c
+++ b/arch/arm/mach-s3c64xx/pm.c
@@ -338,8 +338,10 @@
 	for (i = 0; i < ARRAY_SIZE(s3c64xx_pm_domains); i++)
 		pm_genpd_init(&s3c64xx_pm_domains[i]->pd, NULL, false);
 
+#ifdef CONFIG_S3C_DEV_FB
 	if (dev_get_platdata(&s3c_device_fb.dev))
 		pm_genpd_add_device(&s3c64xx_pm_f.pd, &s3c_device_fb.dev);
+#endif
 
 	return 0;
 }
diff --git a/arch/arm/mach-s5p64x0/include/mach/regs-irq.h b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
index 4aaebda..d60397d 100644
--- a/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
+++ b/arch/arm/mach-s5p64x0/include/mach/regs-irq.h
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_REGS_IRQ_H
 #define __ASM_ARCH_REGS_IRQ_H __FILE__
 
-#include <asm/hardware/vic.h>
 #include <mach/map.h>
 
 #endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5p64x0/include/mach/tick.h b/arch/arm/mach-s5p64x0/include/mach/tick.h
deleted file mode 100644
index 00aa7f1..0000000
--- a/arch/arm/mach-s5p64x0/include/mach/tick.h
+++ /dev/null
@@ -1,29 +0,0 @@
-/* linux/arch/arm/mach-s5p64x0/include/mach/tick.h
- *
- * Copyright (c) 2009-2010 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com
- *
- * Copyright 2008 Openmoko, Inc.
- * Copyright 2008 Simtec Electronics
- *	http://armlinux.simtec.co.uk/
- *	Ben Dooks <ben@simtec.co.uk>
- *
- * S5P64X0 - Timer tick support definitions
- *
- * 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.
-*/
-
-#ifndef __ASM_ARCH_TICK_H
-#define __ASM_ARCH_TICK_H __FILE__
-
-static inline u32 s3c24xx_ostimer_pending(void)
-{
-	u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
-	return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));
-}
-
-#define TICK_MAX	(0xffffffff)
-
-#endif /* __ASM_ARCH_TICK_H */
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6440.c b/arch/arm/mach-s5p64x0/mach-smdk6440.c
index 1af8235..a40d5eb 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6440.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6440.c
@@ -29,7 +29,6 @@
 #include <video/platform_lcd.h>
 #include <video/samsung_fimd.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/irq.h>
@@ -272,9 +271,8 @@
 	.atag_offset	= 0x100,
 
 	.init_irq	= s5p6440_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= smdk6440_map_io,
 	.init_machine	= smdk6440_machine_init,
-	.timer		= &s5p_timer,
+	.init_time	= s5p_timer_init,
 	.restart	= s5p64x0_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5p64x0/mach-smdk6450.c b/arch/arm/mach-s5p64x0/mach-smdk6450.c
index 62526cc..703e576 100644
--- a/arch/arm/mach-s5p64x0/mach-smdk6450.c
+++ b/arch/arm/mach-s5p64x0/mach-smdk6450.c
@@ -29,7 +29,6 @@
 #include <video/platform_lcd.h>
 #include <video/samsung_fimd.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/irq.h>
@@ -291,9 +290,8 @@
 	.atag_offset	= 0x100,
 
 	.init_irq	= s5p6450_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= smdk6450_map_io,
 	.init_machine	= smdk6450_machine_init,
-	.timer		= &s5p_timer,
+	.init_time	= s5p_timer_init,
 	.restart	= s5p64x0_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5pc100/include/mach/regs-irq.h b/arch/arm/mach-s5pc100/include/mach/regs-irq.h
index 4d9036d..7616278 100644
--- a/arch/arm/mach-s5pc100/include/mach/regs-irq.h
+++ b/arch/arm/mach-s5pc100/include/mach/regs-irq.h
@@ -14,6 +14,5 @@
 #define __ASM_ARCH_REGS_IRQ_H __FILE__
 
 #include <mach/map.h>
-#include <asm/hardware/vic.h>
 
 #endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5pc100/include/mach/tick.h b/arch/arm/mach-s5pc100/include/mach/tick.h
index 20f6873..0af8e41 100644
--- a/arch/arm/mach-s5pc100/include/mach/tick.h
+++ b/arch/arm/mach-s5pc100/include/mach/tick.h
@@ -15,6 +15,8 @@
 #ifndef __ASM_ARCH_TICK_H
 #define __ASM_ARCH_TICK_H __FILE__
 
+#include <linux/irqchip/arm-vic.h>
+
 /* note, the timer interrutps turn up in 2 places, the vic and then
  * the timer block. We take the VIC as the base at the moment.
  */
diff --git a/arch/arm/mach-s5pc100/mach-smdkc100.c b/arch/arm/mach-s5pc100/mach-smdkc100.c
index 9abe95e..185a195 100644
--- a/arch/arm/mach-s5pc100/mach-smdkc100.c
+++ b/arch/arm/mach-s5pc100/mach-smdkc100.c
@@ -25,7 +25,6 @@
 #include <linux/input.h>
 #include <linux/pwm_backlight.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
@@ -254,9 +253,8 @@
 	/* Maintainer: Byungho Min <bhmin@samsung.com> */
 	.atag_offset	= 0x100,
 	.init_irq	= s5pc100_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= smdkc100_map_io,
 	.init_machine	= smdkc100_machine_init,
-	.timer		= &s3c24xx_timer,
+	.init_time	= s3c24xx_timer_init,
 	.restart	= s5pc100_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/include/mach/regs-irq.h b/arch/arm/mach-s5pv210/include/mach/regs-irq.h
index 5c3b104..d8bc1e6 100644
--- a/arch/arm/mach-s5pv210/include/mach/regs-irq.h
+++ b/arch/arm/mach-s5pv210/include/mach/regs-irq.h
@@ -13,7 +13,6 @@
 #ifndef __ASM_ARCH_REGS_IRQ_H
 #define __ASM_ARCH_REGS_IRQ_H __FILE__
 
-#include <asm/hardware/vic.h>
 #include <mach/map.h>
 
 #endif /* __ASM_ARCH_REGS_IRQ_H */
diff --git a/arch/arm/mach-s5pv210/include/mach/tick.h b/arch/arm/mach-s5pv210/include/mach/tick.h
deleted file mode 100644
index 7993b36..0000000
--- a/arch/arm/mach-s5pv210/include/mach/tick.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/* linux/arch/arm/mach-s5pv210/include/mach/tick.h
- *
- * Copyright (c) 2009 Samsung Electronics Co., Ltd.
- *		http://www.samsung.com/
- *
- * Based on arch/arm/mach-s3c6400/include/mach/tick.h
- *
- * S5PV210 - Timer tick support definitions
- *
- * 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.
-*/
-
-#ifndef __ASM_ARCH_TICK_H
-#define __ASM_ARCH_TICK_H __FILE__
-
-static inline u32 s3c24xx_ostimer_pending(void)
-{
-	u32 pend = __raw_readl(VA_VIC0 + VIC_RAW_STATUS);
-	return pend & (1 << (IRQ_TIMER4_VIC - S5P_IRQ_VIC0(0)));
-}
-
-#define TICK_MAX	(0xffffffff)
-
-#endif /* __ASM_ARCH_TICK_H */
diff --git a/arch/arm/mach-s5pv210/mach-aquila.c b/arch/arm/mach-s5pv210/mach-aquila.c
index ee9fa5c..11900a8 100644
--- a/arch/arm/mach-s5pv210/mach-aquila.c
+++ b/arch/arm/mach-s5pv210/mach-aquila.c
@@ -22,7 +22,6 @@
 #include <linux/input.h>
 #include <linux/gpio.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
@@ -685,9 +684,8 @@
 	   Kyungmin Park <kyungmin.park@samsung.com> */
 	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= aquila_map_io,
 	.init_machine	= aquila_machine_init,
-	.timer		= &s5p_timer,
+	.init_time	= s5p_timer_init,
 	.restart	= s5pv210_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-goni.c b/arch/arm/mach-s5pv210/mach-goni.c
index c72b310..5704815 100644
--- a/arch/arm/mach-s5pv210/mach-goni.c
+++ b/arch/arm/mach-s5pv210/mach-goni.c
@@ -29,7 +29,6 @@
 #include <linux/interrupt.h>
 #include <linux/platform_data/s3c-hsotg.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
@@ -972,10 +971,9 @@
 	/* Maintainers: Kyungmin Park <kyungmin.park@samsung.com> */
 	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= goni_map_io,
 	.init_machine	= goni_machine_init,
-	.timer		= &s5p_timer,
+	.init_time	= s5p_timer_init,
 	.reserve	= &goni_reserve,
 	.restart	= s5pv210_restart,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkc110.c b/arch/arm/mach-s5pv210/mach-smdkc110.c
index f1f3bd3..28bd024 100644
--- a/arch/arm/mach-s5pv210/mach-smdkc110.c
+++ b/arch/arm/mach-s5pv210/mach-smdkc110.c
@@ -15,7 +15,6 @@
 #include <linux/i2c.h>
 #include <linux/device.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
@@ -152,10 +151,9 @@
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
 	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= smdkc110_map_io,
 	.init_machine	= smdkc110_machine_init,
-	.timer		= &s5p_timer,
+	.init_time	= s5p_timer_init,
 	.restart	= s5pv210_restart,
 	.reserve	= &smdkc110_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-smdkv210.c b/arch/arm/mach-s5pv210/mach-smdkv210.c
index 6bc8404..3c73f36 100644
--- a/arch/arm/mach-s5pv210/mach-smdkv210.c
+++ b/arch/arm/mach-s5pv210/mach-smdkv210.c
@@ -21,7 +21,6 @@
 #include <linux/pwm_backlight.h>
 #include <linux/platform_data/s3c-hsotg.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
@@ -328,10 +327,9 @@
 	/* Maintainer: Kukjin Kim <kgene.kim@samsung.com> */
 	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= smdkv210_map_io,
 	.init_machine	= smdkv210_machine_init,
-	.timer		= &s5p_timer,
+	.init_time	= s5p_timer_init,
 	.restart	= s5pv210_restart,
 	.reserve	= &smdkv210_reserve,
 MACHINE_END
diff --git a/arch/arm/mach-s5pv210/mach-torbreck.c b/arch/arm/mach-s5pv210/mach-torbreck.c
index 18785cb..2d4c553 100644
--- a/arch/arm/mach-s5pv210/mach-torbreck.c
+++ b/arch/arm/mach-s5pv210/mach-torbreck.c
@@ -14,7 +14,6 @@
 #include <linux/init.h>
 #include <linux/serial_core.h>
 
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/setup.h>
@@ -129,9 +128,8 @@
 	/* Maintainer: Hyunchul Ko <ghcstop@gmail.com> */
 	.atag_offset	= 0x100,
 	.init_irq	= s5pv210_init_irq,
-	.handle_irq	= vic_handle_irq,
 	.map_io		= torbreck_map_io,
 	.init_machine	= torbreck_machine_init,
-	.timer		= &s5p_timer,
+	.init_time	= s5p_timer_init,
 	.restart	= s5pv210_restart,
 MACHINE_END
diff --git a/arch/arm/mach-sa1100/assabet.c b/arch/arm/mach-sa1100/assabet.c
index 9a23739..b38d252 100644
--- a/arch/arm/mach-sa1100/assabet.c
+++ b/arch/arm/mach-sa1100/assabet.c
@@ -621,7 +621,7 @@
 	.map_io		= assabet_map_io,
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.init_machine	= assabet_init,
 	.init_late	= sa11x0_init_late,
 #ifdef CONFIG_SA1111
diff --git a/arch/arm/mach-sa1100/badge4.c b/arch/arm/mach-sa1100/badge4.c
index b2dadf3..63361b6 100644
--- a/arch/arm/mach-sa1100/badge4.c
+++ b/arch/arm/mach-sa1100/badge4.c
@@ -336,7 +336,7 @@
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
 	.init_late	= sa11x0_init_late,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 #ifdef CONFIG_SA1111
 	.dma_zone_size	= SZ_1M,
 #endif
diff --git a/arch/arm/mach-sa1100/cerf.c b/arch/arm/mach-sa1100/cerf.c
index 304bca4..2d25ece 100644
--- a/arch/arm/mach-sa1100/cerf.c
+++ b/arch/arm/mach-sa1100/cerf.c
@@ -174,7 +174,7 @@
 	.map_io		= cerf_map_io,
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= cerf_init_irq,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.init_machine	= cerf_init,
 	.init_late	= sa11x0_init_late,
 	.restart	= sa11x0_restart,
diff --git a/arch/arm/mach-sa1100/collie.c b/arch/arm/mach-sa1100/collie.c
index 45f424f..612a456 100644
--- a/arch/arm/mach-sa1100/collie.c
+++ b/arch/arm/mach-sa1100/collie.c
@@ -399,7 +399,7 @@
 	.map_io		= collie_map_io,
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.init_machine	= collie_init,
 	.init_late	= sa11x0_init_late,
 	.restart	= sa11x0_restart,
diff --git a/arch/arm/mach-sa1100/generic.h b/arch/arm/mach-sa1100/generic.h
index a5b7c13..2abc6a1 100644
--- a/arch/arm/mach-sa1100/generic.h
+++ b/arch/arm/mach-sa1100/generic.h
@@ -4,9 +4,7 @@
  * Author: Nicolas Pitre
  */
 
-struct sys_timer;
-
-extern struct sys_timer sa1100_timer;
+extern void sa1100_timer_init(void);
 extern void __init sa1100_map_io(void);
 extern void __init sa1100_init_irq(void);
 extern void __init sa1100_init_gpio(void);
diff --git a/arch/arm/mach-sa1100/h3100.c b/arch/arm/mach-sa1100/h3100.c
index e1571ea..b8f2b15 100644
--- a/arch/arm/mach-sa1100/h3100.c
+++ b/arch/arm/mach-sa1100/h3100.c
@@ -108,7 +108,7 @@
 	.map_io		= h3100_map_io,
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.init_machine	= h3100_mach_init,
 	.init_late	= sa11x0_init_late,
 	.restart	= sa11x0_restart,
diff --git a/arch/arm/mach-sa1100/h3600.c b/arch/arm/mach-sa1100/h3600.c
index ba7a290..b8dc5bd 100644
--- a/arch/arm/mach-sa1100/h3600.c
+++ b/arch/arm/mach-sa1100/h3600.c
@@ -158,7 +158,7 @@
 	.map_io		= h3600_map_io,
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.init_machine	= h3600_mach_init,
 	.init_late	= sa11x0_init_late,
 	.restart	= sa11x0_restart,
diff --git a/arch/arm/mach-sa1100/hackkit.c b/arch/arm/mach-sa1100/hackkit.c
index d005939..643d5f2 100644
--- a/arch/arm/mach-sa1100/hackkit.c
+++ b/arch/arm/mach-sa1100/hackkit.c
@@ -229,7 +229,7 @@
 	.map_io		= hackkit_map_io,
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.init_machine	= hackkit_init,
 	.init_late	= sa11x0_init_late,
 	.restart	= sa11x0_restart,
diff --git a/arch/arm/mach-sa1100/jornada720.c b/arch/arm/mach-sa1100/jornada720.c
index 35cfc42..c0b1f5b 100644
--- a/arch/arm/mach-sa1100/jornada720.c
+++ b/arch/arm/mach-sa1100/jornada720.c
@@ -346,7 +346,7 @@
 	.map_io		= jornada720_map_io,
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.init_machine	= jornada720_mach_init,
 	.init_late	= sa11x0_init_late,
 #ifdef CONFIG_SA1111
diff --git a/arch/arm/mach-sa1100/lart.c b/arch/arm/mach-sa1100/lart.c
index f69f78f..a899176 100644
--- a/arch/arm/mach-sa1100/lart.c
+++ b/arch/arm/mach-sa1100/lart.c
@@ -174,6 +174,6 @@
 	.init_irq	= sa1100_init_irq,
 	.init_machine	= lart_init,
 	.init_late	= sa11x0_init_late,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.restart	= sa11x0_restart,
 MACHINE_END
diff --git a/arch/arm/mach-sa1100/nanoengine.c b/arch/arm/mach-sa1100/nanoengine.c
index 102e08f..f1cb378 100644
--- a/arch/arm/mach-sa1100/nanoengine.c
+++ b/arch/arm/mach-sa1100/nanoengine.c
@@ -110,7 +110,7 @@
 	.map_io		= nanoengine_map_io,
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.init_machine	= nanoengine_init,
 	.init_late	= sa11x0_init_late,
 	.restart	= sa11x0_restart,
diff --git a/arch/arm/mach-sa1100/pleb.c b/arch/arm/mach-sa1100/pleb.c
index c51bb63..0912618 100644
--- a/arch/arm/mach-sa1100/pleb.c
+++ b/arch/arm/mach-sa1100/pleb.c
@@ -133,7 +133,7 @@
 	.map_io		= pleb_map_io,
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.init_machine   = pleb_init,
 	.init_late	= sa11x0_init_late,
 	.restart	= sa11x0_restart,
diff --git a/arch/arm/mach-sa1100/shannon.c b/arch/arm/mach-sa1100/shannon.c
index 6460d25..c8866bc 100644
--- a/arch/arm/mach-sa1100/shannon.c
+++ b/arch/arm/mach-sa1100/shannon.c
@@ -102,7 +102,7 @@
 	.map_io		= shannon_map_io,
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.init_machine	= shannon_init,
 	.init_late	= sa11x0_init_late,
 	.restart	= sa11x0_restart,
diff --git a/arch/arm/mach-sa1100/simpad.c b/arch/arm/mach-sa1100/simpad.c
index 6d65f65..bcbc945 100644
--- a/arch/arm/mach-sa1100/simpad.c
+++ b/arch/arm/mach-sa1100/simpad.c
@@ -396,6 +396,6 @@
 	.nr_irqs	= SA1100_NR_IRQS,
 	.init_irq	= sa1100_init_irq,
 	.init_late	= sa11x0_init_late,
-	.timer		= &sa1100_timer,
+	.init_time	= sa1100_timer_init,
 	.restart	= sa11x0_restart,
 MACHINE_END
diff --git a/arch/arm/mach-sa1100/time.c b/arch/arm/mach-sa1100/time.c
index 6e980da..a59a13a 100644
--- a/arch/arm/mach-sa1100/time.c
+++ b/arch/arm/mach-sa1100/time.c
@@ -69,42 +69,10 @@
 	}
 }
 
-static struct clock_event_device ckevt_sa1100_osmr0 = {
-	.name		= "osmr0",
-	.features	= CLOCK_EVT_FEAT_ONESHOT,
-	.rating		= 200,
-	.set_next_event	= sa1100_osmr0_set_next_event,
-	.set_mode	= sa1100_osmr0_set_mode,
-};
-
-static struct irqaction sa1100_timer_irq = {
-	.name		= "ost0",
-	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
-	.handler	= sa1100_ost0_interrupt,
-	.dev_id		= &ckevt_sa1100_osmr0,
-};
-
-static void __init sa1100_timer_init(void)
-{
-	writel_relaxed(0, OIER);
-	writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
-
-	setup_sched_clock(sa1100_read_sched_clock, 32, 3686400);
-
-	ckevt_sa1100_osmr0.cpumask = cpumask_of(0);
-
-	setup_irq(IRQ_OST0, &sa1100_timer_irq);
-
-	clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32,
-		clocksource_mmio_readl_up);
-	clockevents_config_and_register(&ckevt_sa1100_osmr0, 3686400,
-					MIN_OSCR_DELTA * 2, 0x7fffffff);
-}
-
 #ifdef CONFIG_PM
 unsigned long osmr[4], oier;
 
-static void sa1100_timer_suspend(void)
+static void sa1100_timer_suspend(struct clock_event_device *cedev)
 {
 	osmr[0] = readl_relaxed(OSMR0);
 	osmr[1] = readl_relaxed(OSMR1);
@@ -113,7 +81,7 @@
 	oier = readl_relaxed(OIER);
 }
 
-static void sa1100_timer_resume(void)
+static void sa1100_timer_resume(struct clock_event_device *cedev)
 {
 	writel_relaxed(0x0f, OSSR);
 	writel_relaxed(osmr[0], OSMR0);
@@ -132,8 +100,36 @@
 #define sa1100_timer_resume NULL
 #endif
 
-struct sys_timer sa1100_timer = {
-	.init		= sa1100_timer_init,
+static struct clock_event_device ckevt_sa1100_osmr0 = {
+	.name		= "osmr0",
+	.features	= CLOCK_EVT_FEAT_ONESHOT,
+	.rating		= 200,
+	.set_next_event	= sa1100_osmr0_set_next_event,
+	.set_mode	= sa1100_osmr0_set_mode,
 	.suspend	= sa1100_timer_suspend,
 	.resume		= sa1100_timer_resume,
 };
+
+static struct irqaction sa1100_timer_irq = {
+	.name		= "ost0",
+	.flags		= IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
+	.handler	= sa1100_ost0_interrupt,
+	.dev_id		= &ckevt_sa1100_osmr0,
+};
+
+void __init sa1100_timer_init(void)
+{
+	writel_relaxed(0, OIER);
+	writel_relaxed(OSSR_M0 | OSSR_M1 | OSSR_M2 | OSSR_M3, OSSR);
+
+	setup_sched_clock(sa1100_read_sched_clock, 32, 3686400);
+
+	ckevt_sa1100_osmr0.cpumask = cpumask_of(0);
+
+	setup_irq(IRQ_OST0, &sa1100_timer_irq);
+
+	clocksource_mmio_init(OSCR, "oscr", CLOCK_TICK_RATE, 200, 32,
+		clocksource_mmio_readl_up);
+	clockevents_config_and_register(&ckevt_sa1100_osmr0, 3686400,
+					MIN_OSCR_DELTA * 2, 0x7fffffff);
+}
diff --git a/arch/arm/mach-shark/core.c b/arch/arm/mach-shark/core.c
index 9ad2e97..b63dec8 100644
--- a/arch/arm/mach-shark/core.c
+++ b/arch/arm/mach-shark/core.c
@@ -128,10 +128,6 @@
 	setup_irq(IRQ_TIMER, &shark_timer_irq);
 }
 
-static struct sys_timer shark_timer = {
-	.init		= shark_timer_init,
-};
-
 static void shark_init_early(void)
 {
 	disable_hlt();
@@ -142,7 +138,7 @@
 	.atag_offset	= 0x3000,
 	.init_early	= shark_init_early,
 	.init_irq	= shark_init_irq,
-	.timer		= &shark_timer,
+	.init_time	= shark_timer_init,
 	.dma_zone_size	= SZ_4M,
 	.restart	= shark_restart,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/Makefile b/arch/arm/mach-shmobile/Makefile
index 0b71479..700e662 100644
--- a/arch/arm/mach-shmobile/Makefile
+++ b/arch/arm/mach-shmobile/Makefile
@@ -15,7 +15,7 @@
 # SMP objects
 smp-y				:= platsmp.o headsmp.o
 smp-$(CONFIG_HOTPLUG_CPU)	+= hotplug.o
-smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o
+smp-$(CONFIG_ARCH_SH73A0)	+= smp-sh73a0.o headsmp-sh73a0.o
 smp-$(CONFIG_ARCH_R8A7779)	+= smp-r8a7779.o
 smp-$(CONFIG_ARCH_EMEV2)	+= smp-emev2.o
 
@@ -37,6 +37,7 @@
 obj-$(CONFIG_ARCH_SH7372)	+= pm-sh7372.o sleep-sh7372.o
 obj-$(CONFIG_ARCH_R8A7740)	+= pm-r8a7740.o
 obj-$(CONFIG_ARCH_R8A7779)	+= pm-r8a7779.o
+obj-$(CONFIG_ARCH_SH73A0)	+= pm-sh73a0.o
 
 # Board objects
 obj-$(CONFIG_MACH_AP4EVB)	+= board-ap4evb.o
diff --git a/arch/arm/mach-shmobile/board-ag5evm.c b/arch/arm/mach-shmobile/board-ag5evm.c
index 032d108..705bc63 100644
--- a/arch/arm/mach-shmobile/board-ag5evm.c
+++ b/arch/arm/mach-shmobile/board-ag5evm.c
@@ -40,6 +40,7 @@
 #include <linux/mmc/sh_mobile_sdhi.h>
 #include <linux/mfd/tmio.h>
 #include <linux/sh_clk.h>
+#include <linux/irqchip/arm-gic.h>
 #include <video/sh_mobile_lcdc.h>
 #include <video/sh_mipi_dsi.h>
 #include <sound/sh_fsi.h>
@@ -49,7 +50,6 @@
 #include <mach/common.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/traps.h>
 
@@ -668,8 +668,7 @@
 	.init_early	= sh73a0_add_early_devices,
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= sh73a0_init_irq,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= ag5evm_init,
 	.init_late	= shmobile_init_late,
-	.timer		= &shmobile_timer,
+	.init_time	= sh73a0_earlytimer_init,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-ap4evb.c b/arch/arm/mach-shmobile/board-ap4evb.c
index 99ef190..c1d4ab6 100644
--- a/arch/arm/mach-shmobile/board-ap4evb.c
+++ b/arch/arm/mach-shmobile/board-ap4evb.c
@@ -1350,5 +1350,5 @@
 	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= ap4evb_init,
 	.init_late	= sh7372_pm_init_late,
-	.timer		= &shmobile_timer,
+	.init_time	= sh7372_earlytimer_init,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-armadillo800eva.c b/arch/arm/mach-shmobile/board-armadillo800eva.c
index 5353adf..6573137 100644
--- a/arch/arm/mach-shmobile/board-armadillo800eva.c
+++ b/arch/arm/mach-shmobile/board-armadillo800eva.c
@@ -1181,6 +1181,8 @@
 	rmobile_add_device_to_domain("A4LC", &hdmi_lcdc_device);
 	if (usb)
 		rmobile_add_device_to_domain("A3SP", usb);
+
+	r8a7740_pm_init();
 }
 
 static void __init eva_earlytimer_init(void)
@@ -1192,9 +1194,6 @@
 static void __init eva_add_early_devices(void)
 {
 	r8a7740_add_early_devices();
-
-	/* override timer setup with board-specific code */
-	shmobile_timer.init = eva_earlytimer_init;
 }
 
 #define RESCNT2 IOMEM(0xe6188020)
@@ -1216,7 +1215,7 @@
 	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= eva_init,
 	.init_late	= shmobile_init_late,
-	.timer		= &shmobile_timer,
+	.init_time	= eva_earlytimer_init,
 	.dt_compat	= eva_boards_compat_dt,
 	.restart	= eva_restart,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-bonito.c b/arch/arm/mach-shmobile/board-bonito.c
index cb8c994..331b7ce 100644
--- a/arch/arm/mach-shmobile/board-bonito.c
+++ b/arch/arm/mach-shmobile/board-bonito.c
@@ -499,9 +499,6 @@
 static void __init bonito_add_early_devices(void)
 {
 	r8a7740_add_early_devices();
-
-	/* override timer setup with board-specific code */
-	shmobile_timer.init = bonito_earlytimer_init;
 }
 
 MACHINE_START(BONITO, "bonito")
@@ -511,5 +508,5 @@
 	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= bonito_init,
 	.init_late	= shmobile_init_late,
-	.timer		= &shmobile_timer,
+	.init_time	= bonito_earlytimer_init,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kota2.c b/arch/arm/mach-shmobile/board-kota2.c
index bf88f9a..d759a9c 100644
--- a/arch/arm/mach-shmobile/board-kota2.c
+++ b/arch/arm/mach-shmobile/board-kota2.c
@@ -35,6 +35,7 @@
 #include <linux/input/sh_keysc.h>
 #include <linux/gpio_keys.h>
 #include <linux/leds.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/leds-renesas-tpu.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
@@ -47,7 +48,6 @@
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
-#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 #include <asm/traps.h>
 
@@ -550,8 +550,7 @@
 	.init_early	= sh73a0_add_early_devices,
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= sh73a0_init_irq,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= kota2_init,
 	.init_late	= shmobile_init_late,
-	.timer		= &shmobile_timer,
+	.init_time	= sh73a0_earlytimer_init,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9d.c b/arch/arm/mach-shmobile/board-kzm9d.c
index b52bc0d..c254782 100644
--- a/arch/arm/mach-shmobile/board-kzm9d.c
+++ b/arch/arm/mach-shmobile/board-kzm9d.c
@@ -28,7 +28,6 @@
 #include <mach/emev2.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 
 /* Dummy supplies, where voltage doesn't matter */
 static struct regulator_consumer_supply dummy_supplies[] = {
@@ -89,9 +88,8 @@
 	.init_early	= emev2_add_early_devices,
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= emev2_init_irq,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= kzm9d_add_standard_devices,
 	.init_late	= shmobile_init_late,
-	.timer		= &shmobile_timer,
+	.init_time	= shmobile_timer_init,
 	.dt_compat	= kzm9d_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-kzm9g.c b/arch/arm/mach-shmobile/board-kzm9g.c
index c02448d..363c6ed 100644
--- a/arch/arm/mach-shmobile/board-kzm9g.c
+++ b/arch/arm/mach-shmobile/board-kzm9g.c
@@ -25,6 +25,7 @@
 #include <linux/i2c.h>
 #include <linux/i2c/pcf857x.h>
 #include <linux/input.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sh_mmcif.h>
 #include <linux/mmc/sh_mobile_sdhi.h>
@@ -42,7 +43,6 @@
 #include <mach/sh73a0.h>
 #include <mach/common.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <video/sh_mobile_lcdc.h>
@@ -772,6 +772,8 @@
 
 	sh73a0_add_standard_devices();
 	platform_add_devices(kzm_devices, ARRAY_SIZE(kzm_devices));
+
+	sh73a0_pm_init();
 }
 
 static void kzm9g_restart(char mode, const char *cmd)
@@ -792,10 +794,9 @@
 	.init_early	= sh73a0_add_early_devices,
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= sh73a0_init_irq,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= kzm_init,
 	.init_late	= shmobile_init_late,
-	.timer		= &shmobile_timer,
+	.init_time	= sh73a0_earlytimer_init,
 	.restart	= kzm9g_restart,
 	.dt_compat	= kzm9g_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-mackerel.c b/arch/arm/mach-shmobile/board-mackerel.c
index 2fed62f..fe4917f 100644
--- a/arch/arm/mach-shmobile/board-mackerel.c
+++ b/arch/arm/mach-shmobile/board-mackerel.c
@@ -1593,6 +1593,6 @@
 	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= mackerel_init,
 	.init_late	= sh7372_pm_init_late,
-	.timer		= &shmobile_timer,
+	.init_time	= sh7372_earlytimer_init,
 	.dt_compat  = mackerel_boards_compat_dt,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/board-marzen.c b/arch/arm/mach-shmobile/board-marzen.c
index 449f928..cdcb799 100644
--- a/arch/arm/mach-shmobile/board-marzen.c
+++ b/arch/arm/mach-shmobile/board-marzen.c
@@ -44,7 +44,6 @@
 #include <mach/irqs.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 #include <asm/traps.h>
 
 /* Fixed 3.3V regulator to be used by SDHI0 */
@@ -382,8 +381,7 @@
 	.init_early	= r8a7779_add_early_devices,
 	.nr_irqs	= NR_IRQS_LEGACY,
 	.init_irq	= r8a7779_init_irq,
-	.handle_irq	= gic_handle_irq,
 	.init_machine	= marzen_init,
 	.init_late	= marzen_init_late,
-	.timer		= &shmobile_timer,
+	.init_time	= r8a7779_earlytimer_init,
 MACHINE_END
diff --git a/arch/arm/mach-shmobile/clock-r8a7740.c b/arch/arm/mach-shmobile/clock-r8a7740.c
index eac49d5..19ce885 100644
--- a/arch/arm/mach-shmobile/clock-r8a7740.c
+++ b/arch/arm/mach-shmobile/clock-r8a7740.c
@@ -581,10 +581,14 @@
 
 	/* MSTP32 clocks */
 	CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0",	&mstp_clks[MSTP100]),
-	CLKDEV_DEV_ID("sh_tmu.1",		&mstp_clks[MSTP111]),
+	CLKDEV_DEV_ID("sh_tmu.3",		&mstp_clks[MSTP111]),
+	CLKDEV_DEV_ID("sh_tmu.4",		&mstp_clks[MSTP111]),
+	CLKDEV_DEV_ID("sh_tmu.5",		&mstp_clks[MSTP111]),
 	CLKDEV_DEV_ID("i2c-sh_mobile.0",	&mstp_clks[MSTP116]),
 	CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1",	&mstp_clks[MSTP117]),
 	CLKDEV_DEV_ID("sh_tmu.0",		&mstp_clks[MSTP125]),
+	CLKDEV_DEV_ID("sh_tmu.1",		&mstp_clks[MSTP125]),
+	CLKDEV_DEV_ID("sh_tmu.2",		&mstp_clks[MSTP125]),
 	CLKDEV_DEV_ID("sh_mobile_ceu.0",	&mstp_clks[MSTP127]),
 	CLKDEV_DEV_ID("sh_mobile_ceu.1",	&mstp_clks[MSTP128]),
 
diff --git a/arch/arm/mach-shmobile/clock-r8a7779.c b/arch/arm/mach-shmobile/clock-r8a7779.c
index c019609..202370d 100644
--- a/arch/arm/mach-shmobile/clock-r8a7779.c
+++ b/arch/arm/mach-shmobile/clock-r8a7779.c
@@ -161,7 +161,8 @@
 	CLKDEV_DEV_ID("ehci-platform.0", &mstp_clks[MSTP100]), /* USB EHCI port0/1 */
 	CLKDEV_DEV_ID("ohci-platform.0", &mstp_clks[MSTP100]), /* USB OHCI port0/1 */
 	CLKDEV_DEV_ID("sh_tmu.0", &mstp_clks[MSTP016]), /* TMU00 */
-	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP016]), /* TMU01 */
+	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP015]), /* TMU01 */
+	CLKDEV_DEV_ID("sh_tmu.2", &mstp_clks[MSTP014]), /* TMU02 */
 	CLKDEV_DEV_ID("i2c-rcar.0", &mstp_clks[MSTP030]), /* I2C0 */
 	CLKDEV_DEV_ID("i2c-rcar.1", &mstp_clks[MSTP029]), /* I2C1 */
 	CLKDEV_DEV_ID("i2c-rcar.2", &mstp_clks[MSTP028]), /* I2C2 */
diff --git a/arch/arm/mach-shmobile/clock-sh7372.c b/arch/arm/mach-shmobile/clock-sh7372.c
index 3ca6757b..45d21fe 100644
--- a/arch/arm/mach-shmobile/clock-sh7372.c
+++ b/arch/arm/mach-shmobile/clock-sh7372.c
@@ -544,6 +544,7 @@
 
 	/* MSTP32 clocks */
 	CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* IIC2 */
+	CLKDEV_DEV_ID("fff30000.i2c", &mstp_clks[MSTP001]), /* IIC2 */
 	CLKDEV_DEV_ID("spi_sh_msiof.0", &mstp_clks[MSTP000]), /* MSIOF0 */
 	CLKDEV_DEV_ID("uio_pdrv_genirq.4", &mstp_clks[MSTP131]), /* VEU3 */
 	CLKDEV_DEV_ID("uio_pdrv_genirq.3", &mstp_clks[MSTP130]), /* VEU2 */
@@ -556,6 +557,7 @@
 	CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX0 */
 	CLKDEV_DEV_ID("sh_mobile_lcdc_fb.1", &mstp_clks[MSTP117]), /* LCDC1 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* IIC0 */
+	CLKDEV_DEV_ID("fff20000.i2c", &mstp_clks[MSTP116]), /* IIC0 */
 	CLKDEV_DEV_ID("sh_mobile_meram.0", &mstp_clks[MSTP113]), /* MERAM */
 	CLKDEV_DEV_ID("uio_pdrv_genirq.5", &mstp_clks[MSTP106]), /* JPU */
 	CLKDEV_DEV_ID("uio_pdrv_genirq.0", &mstp_clks[MSTP101]), /* VPU */
@@ -577,18 +579,25 @@
 	CLKDEV_DEV_ID("sh-sci.4", &mstp_clks[MSTP200]), /* SCIFA4 */
 	CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI2 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* IIC1 */
+	CLKDEV_DEV_ID("e6c20000.i2c", &mstp_clks[MSTP323]), /* IIC1 */
 	CLKDEV_DEV_ID("r8a66597_hcd.0", &mstp_clks[MSTP322]), /* USB0 */
 	CLKDEV_DEV_ID("r8a66597_udc.0", &mstp_clks[MSTP322]), /* USB0 */
 	CLKDEV_DEV_ID("renesas_usbhs.0", &mstp_clks[MSTP322]), /* USB0 */
 	CLKDEV_DEV_ID("sh_flctl.0", &mstp_clks[MSTP315]), /* FLCTL */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
+	CLKDEV_DEV_ID("e6850000.sdhi", &mstp_clks[MSTP314]), /* SDHI0 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
+	CLKDEV_DEV_ID("e6860000.sdhi", &mstp_clks[MSTP313]), /* SDHI1 */
 	CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMC */
+	CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMC */
 	CLKDEV_DEV_ID("sh-mipi-dsi.1", &mstp_clks[MSTP423]), /* DSITX1 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP415]), /* SDHI2 */
+	CLKDEV_DEV_ID("e6870000.sdhi", &mstp_clks[MSTP415]), /* SDHI2 */
 	CLKDEV_DEV_ID("sh-mobile-hdmi", &mstp_clks[MSTP413]), /* HDMI */
 	CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* IIC3 */
+	CLKDEV_DEV_ID("e6d20000.i2c", &mstp_clks[MSTP411]), /* IIC3 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* IIC4 */
+	CLKDEV_DEV_ID("e6d30000.i2c", &mstp_clks[MSTP410]), /* IIC4 */
 	CLKDEV_DEV_ID("sh-dma-engine.4", &mstp_clks[MSTP407]), /* USB-DMAC1 */
 	CLKDEV_DEV_ID("r8a66597_hcd.1", &mstp_clks[MSTP406]), /* USB1 */
 	CLKDEV_DEV_ID("r8a66597_udc.1", &mstp_clks[MSTP406]), /* USB1 */
diff --git a/arch/arm/mach-shmobile/clock-sh73a0.c b/arch/arm/mach-shmobile/clock-sh73a0.c
index 516ff7f..afa5423 100644
--- a/arch/arm/mach-shmobile/clock-sh73a0.c
+++ b/arch/arm/mach-shmobile/clock-sh73a0.c
@@ -264,17 +264,17 @@
 	SH_CLK_DIV4(&pll1_clk, _reg, _bit, _mask, _flags)
 
 static struct clk div4_clks[DIV4_NR] = {
-	[DIV4_I] = DIV4(FRQCRA, 20, 0xfff, CLK_ENABLE_ON_INIT),
-	[DIV4_ZG] = DIV4(FRQCRA, 16, 0xbff, CLK_ENABLE_ON_INIT),
-	[DIV4_M3] = DIV4(FRQCRA, 12, 0xfff, CLK_ENABLE_ON_INIT),
-	[DIV4_B] = DIV4(FRQCRA, 8, 0xfff, CLK_ENABLE_ON_INIT),
-	[DIV4_M1] = DIV4(FRQCRA, 4, 0xfff, 0),
-	[DIV4_M2] = DIV4(FRQCRA, 0, 0xfff, 0),
-	[DIV4_Z] = DIV4(FRQCRB, 24, 0xbff, 0),
-	[DIV4_ZTR] = DIV4(FRQCRB, 20, 0xfff, 0),
-	[DIV4_ZT] = DIV4(FRQCRB, 16, 0xfff, 0),
-	[DIV4_ZX] = DIV4(FRQCRB, 12, 0xfff, 0),
-	[DIV4_HP] = DIV4(FRQCRB, 4, 0xfff, 0),
+	[DIV4_I] = DIV4(FRQCRA, 20, 0xdff, CLK_ENABLE_ON_INIT),
+	[DIV4_ZG] = DIV4(FRQCRA, 16, 0xd7f, CLK_ENABLE_ON_INIT),
+	[DIV4_M3] = DIV4(FRQCRA, 12, 0x1dff, CLK_ENABLE_ON_INIT),
+	[DIV4_B] = DIV4(FRQCRA, 8, 0xdff, CLK_ENABLE_ON_INIT),
+	[DIV4_M1] = DIV4(FRQCRA, 4, 0x1dff, 0),
+	[DIV4_M2] = DIV4(FRQCRA, 0, 0x1dff, 0),
+	[DIV4_Z] = DIV4(FRQCRB, 24, 0x97f, 0),
+	[DIV4_ZTR] = DIV4(FRQCRB, 20, 0xdff, 0),
+	[DIV4_ZT] = DIV4(FRQCRB, 16, 0xdff, 0),
+	[DIV4_ZX] = DIV4(FRQCRB, 12, 0xdff, 0),
+	[DIV4_HP] = DIV4(FRQCRB, 4, 0xdff, 0),
 };
 
 enum { DIV6_VCK1, DIV6_VCK2, DIV6_VCK3, DIV6_ZB1,
@@ -525,6 +525,13 @@
 	[MSTP403] = MSTP(&r_clk, SMSTPCR4, 3, 0), /* KEYSC */
 };
 
+/* The lookups structure below includes duplicate entries for some clocks
+ * with alternate names.
+ * - The traditional name used when a device is initialised with platform data
+ * - The name used when a device is initialised using device tree
+ * The longer-term aim is to remove these duplicates, and indeed the
+ * lookups table entirely, by describing clocks using device tree.
+ */
 static struct clk_lookup lookups[] = {
 	/* main clocks */
 	CLKDEV_CON_ID("r_clk", &r_clk),
@@ -545,6 +552,7 @@
 
 	/* MSTP32 clocks */
 	CLKDEV_DEV_ID("i2c-sh_mobile.2", &mstp_clks[MSTP001]), /* I2C2 */
+	CLKDEV_DEV_ID("e6824000.i2c", &mstp_clks[MSTP001]), /* I2C2 */
 	CLKDEV_DEV_ID("sh_mobile_ceu.1", &mstp_clks[MSTP129]), /* CEU1 */
 	CLKDEV_DEV_ID("sh-mobile-csi2.1", &mstp_clks[MSTP128]), /* CSI2-RX1 */
 	CLKDEV_DEV_ID("sh_mobile_ceu.0", &mstp_clks[MSTP127]), /* CEU0 */
@@ -553,6 +561,7 @@
 	CLKDEV_DEV_ID("sh_tmu.1", &mstp_clks[MSTP125]), /* TMU01 */
 	CLKDEV_DEV_ID("sh-mipi-dsi.0", &mstp_clks[MSTP118]), /* DSITX */
 	CLKDEV_DEV_ID("i2c-sh_mobile.0", &mstp_clks[MSTP116]), /* I2C0 */
+	CLKDEV_DEV_ID("e6820000.i2c", &mstp_clks[MSTP116]), /* I2C0 */
 	CLKDEV_DEV_ID("sh_mobile_lcdc_fb.0", &mstp_clks[MSTP100]), /* LCDC0 */
 	CLKDEV_DEV_ID("sh-sci.7", &mstp_clks[MSTP219]), /* SCIFA7 */
 	CLKDEV_DEV_ID("sh-dma-engine.0", &mstp_clks[MSTP218]), /* SY-DMAC */
@@ -569,17 +578,21 @@
 	CLKDEV_DEV_ID("sh_fsi2", &mstp_clks[MSTP328]), /* FSI */
 	CLKDEV_DEV_ID("sh_irda.0", &mstp_clks[MSTP325]), /* IrDA */
 	CLKDEV_DEV_ID("i2c-sh_mobile.1", &mstp_clks[MSTP323]), /* I2C1 */
+	CLKDEV_DEV_ID("e6822000.i2c", &mstp_clks[MSTP323]), /* I2C1 */
 	CLKDEV_DEV_ID("renesas_usbhs", &mstp_clks[MSTP322]), /* USB */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.0", &mstp_clks[MSTP314]), /* SDHI0 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.1", &mstp_clks[MSTP313]), /* SDHI1 */
 	CLKDEV_DEV_ID("sh_mmcif.0", &mstp_clks[MSTP312]), /* MMCIF0 */
+	CLKDEV_DEV_ID("e6bd0000.mmcif", &mstp_clks[MSTP312]), /* MMCIF0 */
 	CLKDEV_DEV_ID("sh_mobile_sdhi.2", &mstp_clks[MSTP311]), /* SDHI2 */
 	CLKDEV_DEV_ID("leds-renesas-tpu.12", &mstp_clks[MSTP303]), /* TPU1 */
 	CLKDEV_DEV_ID("leds-renesas-tpu.21", &mstp_clks[MSTP302]), /* TPU2 */
 	CLKDEV_DEV_ID("leds-renesas-tpu.30", &mstp_clks[MSTP301]), /* TPU3 */
 	CLKDEV_DEV_ID("leds-renesas-tpu.41", &mstp_clks[MSTP300]), /* TPU4 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.3", &mstp_clks[MSTP411]), /* I2C3 */
+	CLKDEV_DEV_ID("e6826000.i2c", &mstp_clks[MSTP411]), /* I2C3 */
 	CLKDEV_DEV_ID("i2c-sh_mobile.4", &mstp_clks[MSTP410]), /* I2C4 */
+	CLKDEV_DEV_ID("e6828000.i2c", &mstp_clks[MSTP410]), /* I2C4 */
 	CLKDEV_DEV_ID("sh_keysc.0", &mstp_clks[MSTP403]), /* KEYSC */
 };
 
diff --git a/arch/arm/mach-shmobile/headsmp-sh73a0.S b/arch/arm/mach-shmobile/headsmp-sh73a0.S
new file mode 100644
index 0000000..bec4c0d
--- /dev/null
+++ b/arch/arm/mach-shmobile/headsmp-sh73a0.S
@@ -0,0 +1,50 @@
+/*
+ * SMP support for SoC sh73a0
+ *
+ * Copyright (C) 2012 Bastian Hecht
+ *
+ * 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., 59 Temple Place, Suite 330, Boston,
+ * MA 02111-1307 USA
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+#include <asm/memory.h>
+
+	__CPUINIT
+/*
+ * Reset vector for secondary CPUs.
+ *
+ * First we turn on L1 cache coherency for our CPU. Then we jump to
+ * shmobile_invalidate_start that invalidates the cache and hands over control
+ * to the common ARM startup code.
+ * This function will be mapped to address 0 by the SBAR register.
+ * A normal branch is out of range here so we need a long jump. We jump to
+ * the physical address as the MMU is still turned off.
+ */
+	.align	12
+ENTRY(sh73a0_secondary_vector)
+	mrc     p15, 0, r0, c0, c0, 5	@ read MIPDR
+	and	r0, r0, #3		@ mask out cpu ID
+	lsl	r0, r0, #3		@ we will shift by cpu_id * 8 bits
+	mov	r1, #0xf0000000		@ SCU base address
+	ldr	r2, [r1, #8]		@ SCU Power Status Register
+	mov	r3, #3
+	bic	r2, r2, r3, lsl r0	@ Clear bits of our CPU (Run Mode)
+	str	r2, [r1, #8]		@ write back
+
+	ldr	pc, 1f
+1:	.long shmobile_invalidate_start - PAGE_OFFSET + PLAT_PHYS_OFFSET
+ENDPROC(sh73a0_secondary_vector)
diff --git a/arch/arm/mach-shmobile/hotplug.c b/arch/arm/mach-shmobile/hotplug.c
index b09a0bd..a1524e3 100644
--- a/arch/arm/mach-shmobile/hotplug.c
+++ b/arch/arm/mach-shmobile/hotplug.c
@@ -56,6 +56,12 @@
 	return cpu == 0 ? -EPERM : 0;
 }
 
+int shmobile_cpu_disable_any(unsigned int cpu)
+{
+	cpumask_clear_cpu(cpu, &dead_cpus);
+	return 0;
+}
+
 int shmobile_cpu_is_dead(unsigned int cpu)
 {
 	return cpumask_test_cpu(cpu, &dead_cpus);
diff --git a/arch/arm/mach-shmobile/include/mach/common.h b/arch/arm/mach-shmobile/include/mach/common.h
index dfeca79..e48606d 100644
--- a/arch/arm/mach-shmobile/include/mach/common.h
+++ b/arch/arm/mach-shmobile/include/mach/common.h
@@ -2,7 +2,7 @@
 #define __ARCH_MACH_COMMON_H
 
 extern void shmobile_earlytimer_init(void);
-extern struct sys_timer shmobile_timer;
+extern void shmobile_timer_init(void);
 extern void shmobile_setup_delay(unsigned int max_cpu_core_mhz,
 			 unsigned int mult, unsigned int div);
 struct twd_local_timer;
@@ -20,8 +20,11 @@
 
 extern void sh7372_init_irq(void);
 extern void sh7372_map_io(void);
+extern void sh7372_earlytimer_init(void);
 extern void sh7372_add_early_devices(void);
 extern void sh7372_add_standard_devices(void);
+extern void sh7372_add_early_devices_dt(void);
+extern void sh7372_add_standard_devices_dt(void);
 extern void sh7372_clock_init(void);
 extern void sh7372_pinmux_init(void);
 extern void sh7372_pm_init(void);
@@ -31,11 +34,17 @@
 extern struct clk sh7372_extal2_clk;
 
 extern void sh73a0_init_irq(void);
+extern void sh73a0_init_irq_dt(void);
 extern void sh73a0_map_io(void);
+extern void sh73a0_earlytimer_init(void);
 extern void sh73a0_add_early_devices(void);
+extern void sh73a0_add_early_devices_dt(void);
 extern void sh73a0_add_standard_devices(void);
+extern void sh73a0_add_standard_devices_dt(void);
 extern void sh73a0_clock_init(void);
 extern void sh73a0_pinmux_init(void);
+extern void sh73a0_pm_init(void);
+extern void sh73a0_secondary_vector(void);
 extern struct clk sh73a0_extal1_clk;
 extern struct clk sh73a0_extal2_clk;
 extern struct clk sh73a0_extcki_clk;
@@ -47,9 +56,11 @@
 extern void r8a7740_add_standard_devices(void);
 extern void r8a7740_clock_init(u8 md_ck);
 extern void r8a7740_pinmux_init(void);
+extern void r8a7740_pm_init(void);
 
 extern void r8a7779_init_irq(void);
 extern void r8a7779_map_io(void);
+extern void r8a7779_earlytimer_init(void);
 extern void r8a7779_add_early_devices(void);
 extern void r8a7779_add_standard_devices(void);
 extern void r8a7779_clock_init(void);
@@ -73,6 +84,7 @@
 
 extern void shmobile_cpu_die(unsigned int cpu);
 extern int shmobile_cpu_disable(unsigned int cpu);
+extern int shmobile_cpu_disable_any(unsigned int cpu);
 
 #ifdef CONFIG_HOTPLUG_CPU
 extern int shmobile_cpu_is_dead(unsigned int cpu);
diff --git a/arch/arm/mach-shmobile/intc-r8a7779.c b/arch/arm/mach-shmobile/intc-r8a7779.c
index ef66f1a..8807c27 100644
--- a/arch/arm/mach-shmobile/intc-r8a7779.c
+++ b/arch/arm/mach-shmobile/intc-r8a7779.c
@@ -22,10 +22,10 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 #include <mach/common.h>
 #include <mach/intc.h>
 #include <mach/r8a7779.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
diff --git a/arch/arm/mach-shmobile/intc-sh73a0.c b/arch/arm/mach-shmobile/intc-sh73a0.c
index f0c5e51..91faba6 100644
--- a/arch/arm/mach-shmobile/intc-sh73a0.c
+++ b/arch/arm/mach-shmobile/intc-sh73a0.c
@@ -23,10 +23,11 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/sh_intc.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
 #include <mach/intc.h>
 #include <mach/irqs.h>
 #include <mach/sh73a0.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -315,11 +316,6 @@
 	return irq_cbp(irq_set_type, to_intca_reloc_irq(data), type);
 }
 
-static int intca_gic_set_wake(struct irq_data *data, unsigned int on)
-{
-	return irq_cbp(irq_set_wake, to_intca_reloc_irq(data), on);
-}
-
 #ifdef CONFIG_SMP
 static int intca_gic_set_affinity(struct irq_data *data,
 				  const struct cpumask *cpumask,
@@ -339,7 +335,7 @@
 	.irq_disable		= intca_gic_disable,
 	.irq_shutdown		= intca_gic_disable,
 	.irq_set_type		= intca_gic_set_type,
-	.irq_set_wake		= intca_gic_set_wake,
+	.irq_set_wake		= sh73a0_set_wake,
 #ifdef CONFIG_SMP
 	.irq_set_affinity	= intca_gic_set_affinity,
 #endif
@@ -464,3 +460,11 @@
 	sh73a0_pint1_cascade.handler = sh73a0_pint1_demux;
 	setup_irq(gic_spi(34), &sh73a0_pint1_cascade);
 }
+
+#ifdef CONFIG_OF
+void __init sh73a0_init_irq_dt(void)
+{
+	irqchip_init();
+	gic_arch_extn.irq_set_wake = sh73a0_set_wake;
+}
+#endif
diff --git a/arch/arm/mach-shmobile/platsmp.c b/arch/arm/mach-shmobile/platsmp.c
index ed8d235..1f958d7 100644
--- a/arch/arm/mach-shmobile/platsmp.c
+++ b/arch/arm/mach-shmobile/platsmp.c
@@ -12,7 +12,6 @@
  */
 #include <linux/init.h>
 #include <linux/smp.h>
-#include <asm/hardware/gic.h>
 
 void __init shmobile_smp_init_cpus(unsigned int ncores)
 {
@@ -26,6 +25,4 @@
 
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
diff --git a/arch/arm/mach-shmobile/pm-r8a7740.c b/arch/arm/mach-shmobile/pm-r8a7740.c
index 21e5316d..40b87aa 100644
--- a/arch/arm/mach-shmobile/pm-r8a7740.c
+++ b/arch/arm/mach-shmobile/pm-r8a7740.c
@@ -9,7 +9,9 @@
  * for more details.
  */
 #include <linux/console.h>
+#include <linux/suspend.h>
 #include <mach/pm-rmobile.h>
+#include <mach/common.h>
 
 #ifdef CONFIG_PM
 static int r8a7740_pd_a4s_suspend(void)
@@ -58,3 +60,23 @@
 }
 
 #endif /* CONFIG_PM */
+
+#ifdef CONFIG_SUSPEND
+static int r8a7740_enter_suspend(suspend_state_t suspend_state)
+{
+	cpu_do_idle();
+	return 0;
+}
+
+static void r8a7740_suspend_init(void)
+{
+	shmobile_suspend_ops.enter = r8a7740_enter_suspend;
+}
+#else
+static void r8a7740_suspend_init(void) {}
+#endif
+
+void __init r8a7740_pm_init(void)
+{
+	r8a7740_suspend_init();
+}
diff --git a/arch/arm/mach-shmobile/pm-sh73a0.c b/arch/arm/mach-shmobile/pm-sh73a0.c
new file mode 100644
index 0000000..99086e9
--- /dev/null
+++ b/arch/arm/mach-shmobile/pm-sh73a0.c
@@ -0,0 +1,32 @@
+/*
+ * sh73a0 Power management support
+ *
+ *  Copyright (C) 2012 Bastian Hecht <hechtb+renesas@gmail.com>
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License.  See the file "COPYING" in the main directory of this archive
+ * for more details.
+ */
+
+#include <linux/suspend.h>
+#include <mach/common.h>
+
+#ifdef CONFIG_SUSPEND
+static int sh73a0_enter_suspend(suspend_state_t suspend_state)
+{
+	cpu_do_idle();
+	return 0;
+}
+
+static void sh73a0_suspend_init(void)
+{
+	shmobile_suspend_ops.enter = sh73a0_enter_suspend;
+}
+#else
+static void sh73a0_suspend_init(void) {}
+#endif
+
+void __init sh73a0_pm_init(void)
+{
+	sh73a0_suspend_init();
+}
diff --git a/arch/arm/mach-shmobile/setup-emev2.c b/arch/arm/mach-shmobile/setup-emev2.c
index a47beeb..47662a5 100644
--- a/arch/arm/mach-shmobile/setup-emev2.c
+++ b/arch/arm/mach-shmobile/setup-emev2.c
@@ -20,13 +20,14 @@
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
 #include <linux/platform_device.h>
 #include <linux/platform_data/gpio-em.h>
 #include <linux/of_platform.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/io.h>
-#include <linux/of_irq.h>
+#include <linux/irqchip/arm-gic.h>
 #include <mach/hardware.h>
 #include <mach/common.h>
 #include <mach/emev2.h>
@@ -35,7 +36,6 @@
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <asm/mach/time.h>
-#include <asm/hardware/gic.h>
 
 static struct map_desc emev2_io_desc[] __initdata = {
 #ifdef CONFIG_SMP
@@ -445,29 +445,18 @@
 			     emev2_auxdata_lookup, NULL);
 }
 
-static const struct of_device_id emev2_dt_irq_match[] = {
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-	{},
-};
-
 static const char *emev2_boards_compat_dt[] __initdata = {
 	"renesas,emev2",
 	NULL,
 };
 
-void __init emev2_init_irq_dt(void)
-{
-	of_irq_init(emev2_dt_irq_match);
-}
-
 DT_MACHINE_START(EMEV2_DT, "Generic Emma Mobile EV2 (Flattened Device Tree)")
 	.smp		= smp_ops(emev2_smp_ops),
 	.init_early	= emev2_init_delay,
 	.nr_irqs	= NR_IRQS_LEGACY,
-	.init_irq	= emev2_init_irq_dt,
-	.handle_irq	= gic_handle_irq,
+	.init_irq	= irqchip_init,
 	.init_machine	= emev2_add_standard_devices_dt,
-	.timer		= &shmobile_timer,
+	.init_time	= shmobile_timer_init,
 	.dt_compat	= emev2_boards_compat_dt,
 MACHINE_END
 
diff --git a/arch/arm/mach-shmobile/setup-r8a7740.c b/arch/arm/mach-shmobile/setup-r8a7740.c
index 0952224..847567d 100644
--- a/arch/arm/mach-shmobile/setup-r8a7740.c
+++ b/arch/arm/mach-shmobile/setup-r8a7740.c
@@ -27,7 +27,6 @@
 #include <linux/serial_sci.h>
 #include <linux/sh_dma.h>
 #include <linux/sh_timer.h>
-#include <linux/dma-mapping.h>
 #include <mach/dma-register.h>
 #include <mach/r8a7740.h>
 #include <mach/pm-rmobile.h>
@@ -262,6 +261,97 @@
 	.num_resources	= ARRAY_SIZE(cmt10_resources),
 };
 
+/* TMU */
+static struct sh_timer_config tmu00_platform_data = {
+	.name = "TMU00",
+	.channel_offset = 0x4,
+	.timer_bit = 0,
+	.clockevent_rating = 200,
+};
+
+static struct resource tmu00_resources[] = {
+	[0] = {
+		.name	= "TMU00",
+		.start	= 0xfff80008,
+		.end	= 0xfff80014 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= intcs_evt2irq(0xe80),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu00_device = {
+	.name		= "sh_tmu",
+	.id		= 0,
+	.dev = {
+		.platform_data	= &tmu00_platform_data,
+	},
+	.resource	= tmu00_resources,
+	.num_resources	= ARRAY_SIZE(tmu00_resources),
+};
+
+static struct sh_timer_config tmu01_platform_data = {
+	.name = "TMU01",
+	.channel_offset = 0x10,
+	.timer_bit = 1,
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu01_resources[] = {
+	[0] = {
+		.name	= "TMU01",
+		.start	= 0xfff80014,
+		.end	= 0xfff80020 - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= intcs_evt2irq(0xea0),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu01_device = {
+	.name		= "sh_tmu",
+	.id		= 1,
+	.dev = {
+		.platform_data	= &tmu01_platform_data,
+	},
+	.resource	= tmu01_resources,
+	.num_resources	= ARRAY_SIZE(tmu01_resources),
+};
+
+static struct sh_timer_config tmu02_platform_data = {
+	.name = "TMU02",
+	.channel_offset = 0x1C,
+	.timer_bit = 2,
+	.clocksource_rating = 200,
+};
+
+static struct resource tmu02_resources[] = {
+	[0] = {
+		.name	= "TMU02",
+		.start	= 0xfff80020,
+		.end	= 0xfff8002C - 1,
+		.flags	= IORESOURCE_MEM,
+	},
+	[1] = {
+		.start	= intcs_evt2irq(0xec0),
+		.flags	= IORESOURCE_IRQ,
+	},
+};
+
+static struct platform_device tmu02_device = {
+	.name		= "sh_tmu",
+	.id		= 2,
+	.dev = {
+		.platform_data	= &tmu02_platform_data,
+	},
+	.resource	= tmu02_resources,
+	.num_resources	= ARRAY_SIZE(tmu02_resources),
+};
+
 static struct platform_device *r8a7740_early_devices[] __initdata = {
 	&scif0_device,
 	&scif1_device,
@@ -273,6 +363,9 @@
 	&scif7_device,
 	&scifb_device,
 	&cmt10_device,
+	&tmu00_device,
+	&tmu01_device,
+	&tmu02_device,
 };
 
 /* DMA */
@@ -705,12 +798,6 @@
 	rmobile_add_device_to_domain("A3SP",	&i2c1_device);
 }
 
-static void __init r8a7740_earlytimer_init(void)
-{
-	r8a7740_clock_init(0);
-	shmobile_earlytimer_init();
-}
-
 void __init r8a7740_add_early_devices(void)
 {
 	early_platform_add_devices(r8a7740_early_devices,
@@ -718,9 +805,6 @@
 
 	/* setup early console here as well */
 	shmobile_setup_console();
-
-	/* override timer setup with soc-specific code */
-	shmobile_timer.init = r8a7740_earlytimer_init;
 }
 
 #ifdef CONFIG_USE_OF
@@ -763,7 +847,7 @@
 	.init_irq	= r8a7740_init_irq,
 	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= r8a7740_add_standard_devices_dt,
-	.timer		= &shmobile_timer,
+	.init_time	= shmobile_timer_init,
 	.dt_compat	= r8a7740_boards_compat_dt,
 MACHINE_END
 
diff --git a/arch/arm/mach-shmobile/setup-r8a7779.c b/arch/arm/mach-shmobile/setup-r8a7779.c
index 7a1ad4f..7e87ab3 100644
--- a/arch/arm/mach-shmobile/setup-r8a7779.c
+++ b/arch/arm/mach-shmobile/setup-r8a7779.c
@@ -66,8 +66,7 @@
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= { gic_spi(88), gic_spi(88),
-			    gic_spi(88), gic_spi(88) },
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(88)),
 };
 
 static struct platform_device scif0_device = {
@@ -84,8 +83,7 @@
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= { gic_spi(89), gic_spi(89),
-			    gic_spi(89), gic_spi(89) },
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(89)),
 };
 
 static struct platform_device scif1_device = {
@@ -102,8 +100,7 @@
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= { gic_spi(90), gic_spi(90),
-			    gic_spi(90), gic_spi(90) },
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(90)),
 };
 
 static struct platform_device scif2_device = {
@@ -120,8 +117,7 @@
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= { gic_spi(91), gic_spi(91),
-			    gic_spi(91), gic_spi(91) },
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(91)),
 };
 
 static struct platform_device scif3_device = {
@@ -138,8 +134,7 @@
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= { gic_spi(92), gic_spi(92),
-			    gic_spi(92), gic_spi(92) },
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(92)),
 };
 
 static struct platform_device scif4_device = {
@@ -156,8 +151,7 @@
 	.scscr		= SCSCR_RE | SCSCR_TE | SCSCR_CKE1,
 	.scbrr_algo_id	= SCBRR_ALGO_2,
 	.type		= PORT_SCIF,
-	.irqs		= { gic_spi(93), gic_spi(93),
-			    gic_spi(93), gic_spi(93) },
+	.irqs		= SCIx_IRQ_MUXED(gic_spi(93)),
 };
 
 static struct platform_device scif5_device = {
@@ -339,7 +333,7 @@
 /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
 void __init __weak r8a7779_register_twd(void) { }
 
-static void __init r8a7779_earlytimer_init(void)
+void __init r8a7779_earlytimer_init(void)
 {
 	r8a7779_clock_init();
 	shmobile_earlytimer_init();
@@ -366,7 +360,4 @@
 	 * As a final step pass earlyprint=sh-sci.2,115200 on the kernel
 	 * command line in case of the marzen board.
 	 */
-
-	/* override timer setup with soc-specific code */
-	shmobile_timer.init = r8a7779_earlytimer_init;
 }
diff --git a/arch/arm/mach-shmobile/setup-sh7372.c b/arch/arm/mach-shmobile/setup-sh7372.c
index c917882..191ae72 100644
--- a/arch/arm/mach-shmobile/setup-sh7372.c
+++ b/arch/arm/mach-shmobile/setup-sh7372.c
@@ -1054,7 +1054,7 @@
 				       ARRAY_SIZE(domain_devices));
 }
 
-static void __init sh7372_earlytimer_init(void)
+void __init sh7372_earlytimer_init(void)
 {
 	sh7372_clock_init();
 	shmobile_earlytimer_init();
@@ -1067,9 +1067,6 @@
 
 	/* setup early console here as well */
 	shmobile_setup_console();
-
-	/* override timer setup with soc-specific code */
-	shmobile_timer.init = sh7372_earlytimer_init;
 }
 
 #ifdef CONFIG_USE_OF
@@ -1113,7 +1110,7 @@
 	.init_irq	= sh7372_init_irq,
 	.handle_irq	= shmobile_handle_irq_intc,
 	.init_machine	= sh7372_add_standard_devices_dt,
-	.timer		= &shmobile_timer,
+	.init_time	= shmobile_timer_init,
 	.dt_compat	= sh7372_boards_compat_dt,
 MACHINE_END
 
diff --git a/arch/arm/mach-shmobile/setup-sh73a0.c b/arch/arm/mach-shmobile/setup-sh73a0.c
index db99a4a..f7ecb0b 100644
--- a/arch/arm/mach-shmobile/setup-sh73a0.c
+++ b/arch/arm/mach-shmobile/setup-sh73a0.c
@@ -23,6 +23,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/platform_device.h>
+#include <linux/of_platform.h>
 #include <linux/delay.h>
 #include <linux/input.h>
 #include <linux/io.h>
@@ -754,7 +755,7 @@
 	.resource	= pmu_resources,
 };
 
-static struct platform_device *sh73a0_early_devices[] __initdata = {
+static struct platform_device *sh73a0_early_devices_dt[] __initdata = {
 	&scif0_device,
 	&scif1_device,
 	&scif2_device,
@@ -765,6 +766,9 @@
 	&scif7_device,
 	&scif8_device,
 	&cmt10_device,
+};
+
+static struct platform_device *sh73a0_early_devices[] __initdata = {
 	&tmu00_device,
 	&tmu01_device,
 };
@@ -787,6 +791,8 @@
 	/* Clear software reset bit on SY-DMAC module */
 	__raw_writel(__raw_readl(SRCR2) & ~(1 << 18), SRCR2);
 
+	platform_add_devices(sh73a0_early_devices_dt,
+			    ARRAY_SIZE(sh73a0_early_devices_dt));
 	platform_add_devices(sh73a0_early_devices,
 			    ARRAY_SIZE(sh73a0_early_devices));
 	platform_add_devices(sh73a0_late_devices,
@@ -796,7 +802,7 @@
 /* do nothing for !CONFIG_SMP or !CONFIG_HAVE_TWD */
 void __init __weak sh73a0_register_twd(void) { }
 
-static void __init sh73a0_earlytimer_init(void)
+void __init sh73a0_earlytimer_init(void)
 {
 	sh73a0_clock_init();
 	shmobile_earlytimer_init();
@@ -805,12 +811,63 @@
 
 void __init sh73a0_add_early_devices(void)
 {
+	early_platform_add_devices(sh73a0_early_devices_dt,
+				   ARRAY_SIZE(sh73a0_early_devices_dt));
 	early_platform_add_devices(sh73a0_early_devices,
 				   ARRAY_SIZE(sh73a0_early_devices));
 
 	/* setup early console here as well */
 	shmobile_setup_console();
-
-	/* override timer setup with soc-specific code */
-	shmobile_timer.init = sh73a0_earlytimer_init;
 }
+
+#ifdef CONFIG_USE_OF
+
+/* Please note that the clock initialisation shcheme used in
+ * sh73a0_add_early_devices_dt() and sh73a0_add_standard_devices_dt()
+ * does not work with SMP as there is a yet to be resolved lock-up in
+ * workqueue initialisation.
+ *
+ * CONFIG_SMP should be disabled when using this code.
+ */
+
+void __init sh73a0_add_early_devices_dt(void)
+{
+	shmobile_setup_delay(1196, 44, 46); /* Cortex-A9 @ 1196MHz */
+
+	early_platform_add_devices(sh73a0_early_devices_dt,
+				   ARRAY_SIZE(sh73a0_early_devices_dt));
+
+	/* setup early console here as well */
+	shmobile_setup_console();
+}
+
+static const struct of_dev_auxdata sh73a0_auxdata_lookup[] __initconst = {
+	{},
+};
+
+void __init sh73a0_add_standard_devices_dt(void)
+{
+	/* clocks are setup late during boot in the case of DT */
+	sh73a0_clock_init();
+
+	platform_add_devices(sh73a0_early_devices_dt,
+			     ARRAY_SIZE(sh73a0_early_devices_dt));
+	of_platform_populate(NULL, of_default_bus_match_table,
+			     sh73a0_auxdata_lookup, NULL);
+}
+
+static const char *sh73a0_boards_compat_dt[] __initdata = {
+	"renesas,sh73a0",
+	NULL,
+};
+
+DT_MACHINE_START(SH73A0_DT, "Generic SH73A0 (Flattened Device Tree)")
+	.map_io		= sh73a0_map_io,
+	.init_early	= sh73a0_add_early_devices_dt,
+	.nr_irqs	= NR_IRQS_LEGACY,
+	.init_irq	= sh73a0_init_irq_dt,
+	.init_machine	= sh73a0_add_standard_devices_dt,
+	.init_time	= shmobile_timer_init,
+	.dt_compat	= sh73a0_boards_compat_dt,
+MACHINE_END
+#endif /* CONFIG_USE_OF */
diff --git a/arch/arm/mach-shmobile/sleep-sh7372.S b/arch/arm/mach-shmobile/sleep-sh7372.S
index 1d56467..a9df53b 100644
--- a/arch/arm/mach-shmobile/sleep-sh7372.S
+++ b/arch/arm/mach-shmobile/sleep-sh7372.S
@@ -59,17 +59,19 @@
 	mcr	p15, 0, r0, c1, c0, 0
 	isb
 
+	/*
+	 * Clean and invalidate data cache again.
+	 */
+	ldr	r1, kernel_flush
+	blx	r1
+
 	/* disable L2 cache in the aux control register */
 	mrc     p15, 0, r10, c1, c0, 1
 	bic     r10, r10, #2
 	mcr     p15, 0, r10, c1, c0, 1
+	isb
 
 	/*
-	 * Invalidate data cache again.
-	 */
-	ldr	r1, kernel_flush
-	blx	r1
-	/*
 	 * The kernel doesn't interwork: v7_flush_dcache_all in particluar will
 	 * always return in Thumb state when CONFIG_THUMB2_KERNEL is enabled.
 	 * This sequence switches back to ARM.  Note that .align may insert a
diff --git a/arch/arm/mach-shmobile/smp-emev2.c b/arch/arm/mach-shmobile/smp-emev2.c
index f674562..953eb1f 100644
--- a/arch/arm/mach-shmobile/smp-emev2.c
+++ b/arch/arm/mach-shmobile/smp-emev2.c
@@ -23,11 +23,11 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/irqchip/arm-gic.h>
 #include <mach/common.h>
 #include <mach/emev2.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
-#include <asm/hardware/gic.h>
 #include <asm/cacheflush.h>
 
 #define EMEV2_SCU_BASE 0x1e000000
@@ -100,7 +100,7 @@
 	/* Tell ROM loader about our vector (in headsmp.S) */
 	emev2_set_boot_vector(__pa(shmobile_secondary_vector));
 
-	gic_raise_softirq(cpumask_of(cpu), 0);
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 	return 0;
 }
 
diff --git a/arch/arm/mach-shmobile/smp-r8a7779.c b/arch/arm/mach-shmobile/smp-r8a7779.c
index 2ce6af9..3a4acf2 100644
--- a/arch/arm/mach-shmobile/smp-r8a7779.c
+++ b/arch/arm/mach-shmobile/smp-r8a7779.c
@@ -23,12 +23,12 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/irqchip/arm-gic.h>
 #include <mach/common.h>
 #include <mach/r8a7779.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
-#include <asm/hardware/gic.h>
 
 #define AVECR IOMEM(0xfe700040)
 
diff --git a/arch/arm/mach-shmobile/smp-sh73a0.c b/arch/arm/mach-shmobile/smp-sh73a0.c
index 624f00f..acb46a9 100644
--- a/arch/arm/mach-shmobile/smp-sh73a0.c
+++ b/arch/arm/mach-shmobile/smp-sh73a0.c
@@ -23,12 +23,13 @@
 #include <linux/spinlock.h>
 #include <linux/io.h>
 #include <linux/delay.h>
+#include <linux/irqchip/arm-gic.h>
 #include <mach/common.h>
+#include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 #include <mach/sh73a0.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
-#include <asm/hardware/gic.h>
 
 #define WUPCR		IOMEM(0xe6151010)
 #define SRESCR		IOMEM(0xe6151018)
@@ -36,14 +37,13 @@
 #define SBAR		IOMEM(0xe6180020)
 #define APARMBAREA	IOMEM(0xe6f10020)
 
+#define PSTR_SHUTDOWN_MODE	3
+
 static void __iomem *scu_base_addr(void)
 {
 	return (void __iomem *)0xf0000000;
 }
 
-static DEFINE_SPINLOCK(scu_lock);
-static unsigned long tmp;
-
 #ifdef CONFIG_HAVE_ARM_TWD
 static DEFINE_TWD_LOCAL_TIMER(twd_local_timer, 0xf0000600, 29);
 void __init sh73a0_register_twd(void)
@@ -52,20 +52,6 @@
 }
 #endif
 
-static void modify_scu_cpu_psr(unsigned long set, unsigned long clr)
-{
-	void __iomem *scu_base = scu_base_addr();
-
-	spin_lock(&scu_lock);
-	tmp = __raw_readl(scu_base + 8);
-	tmp &= ~clr;
-	tmp |= set;
-	spin_unlock(&scu_lock);
-
-	/* disable cache coherency after releasing the lock */
-	__raw_writel(tmp, scu_base + 8);
-}
-
 static unsigned int __init sh73a0_get_core_count(void)
 {
 	void __iomem *scu_base = scu_base_addr();
@@ -82,9 +68,6 @@
 {
 	cpu = cpu_logical_map(cpu);
 
-	/* enable cache coherency */
-	modify_scu_cpu_psr(0, 3 << (cpu * 8));
-
 	if (((__raw_readl(PSTR) >> (4 * cpu)) & 3) == 3)
 		__raw_writel(1 << cpu, WUPCR);	/* wake up */
 	else
@@ -95,16 +78,14 @@
 
 static void __init sh73a0_smp_prepare_cpus(unsigned int max_cpus)
 {
-	int cpu = cpu_logical_map(0);
-
 	scu_enable(scu_base_addr());
 
-	/* Map the reset vector (in headsmp.S) */
+	/* Map the reset vector (in headsmp-sh73a0.S) */
 	__raw_writel(0, APARMBAREA);      /* 4k */
-	__raw_writel(__pa(shmobile_secondary_vector), SBAR);
+	__raw_writel(__pa(sh73a0_secondary_vector), SBAR);
 
-	/* enable cache coherency on CPU0 */
-	modify_scu_cpu_psr(0, 3 << (cpu * 8));
+	/* enable cache coherency on booting CPU */
+	scu_power_mode(scu_base_addr(), SCU_PM_NORMAL);
 }
 
 static void __init sh73a0_smp_init_cpus(void)
@@ -114,16 +95,20 @@
 	shmobile_smp_init_cpus(ncores);
 }
 
-static int __maybe_unused sh73a0_cpu_kill(unsigned int cpu)
+#ifdef CONFIG_HOTPLUG_CPU
+static int sh73a0_cpu_kill(unsigned int cpu)
 {
-	int k;
 
-	/* this function is running on another CPU than the offline target,
-	 * here we need wait for shutdown code in platform_cpu_die() to
-	 * finish before asking SoC-specific code to power off the CPU core.
+	int k;
+	u32 pstr;
+
+	/*
+	 * wait until the power status register confirms the shutdown of the
+	 * offline target
 	 */
 	for (k = 0; k < 1000; k++) {
-		if (shmobile_cpu_is_dead(cpu))
+		pstr = (__raw_readl(PSTR) >> (4 * cpu)) & 3;
+		if (pstr == PSTR_SHUTDOWN_MODE)
 			return 1;
 
 		mdelay(1);
@@ -132,6 +117,23 @@
 	return 0;
 }
 
+static void sh73a0_cpu_die(unsigned int cpu)
+{
+	/*
+	 * The ARM MPcore does not issue a cache coherency request for the L1
+	 * cache when powering off single CPUs. We must take care of this and
+	 * further caches.
+	 */
+	dsb();
+	flush_cache_all();
+
+	/* Set power off mode. This takes the CPU out of the MP cluster */
+	scu_power_mode(scu_base_addr(), SCU_PM_POWEROFF);
+
+	/* Enter shutdown mode */
+	cpu_do_idle();
+}
+#endif /* CONFIG_HOTPLUG_CPU */
 
 struct smp_operations sh73a0_smp_ops __initdata = {
 	.smp_init_cpus		= sh73a0_smp_init_cpus,
@@ -140,7 +142,7 @@
 	.smp_boot_secondary	= sh73a0_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
 	.cpu_kill		= sh73a0_cpu_kill,
-	.cpu_die		= shmobile_cpu_die,
-	.cpu_disable		= shmobile_cpu_disable,
+	.cpu_die		= sh73a0_cpu_die,
+	.cpu_disable		= shmobile_cpu_disable_any,
 #endif
 };
diff --git a/arch/arm/mach-shmobile/timer.c b/arch/arm/mach-shmobile/timer.c
index a689197..3d16d4d 100644
--- a/arch/arm/mach-shmobile/timer.c
+++ b/arch/arm/mach-shmobile/timer.c
@@ -20,6 +20,7 @@
  */
 #include <linux/platform_device.h>
 #include <linux/delay.h>
+#include <asm/arch_timer.h>
 #include <asm/mach/time.h>
 #include <asm/smp_twd.h>
 
@@ -60,10 +61,8 @@
 	late_time_init = shmobile_late_time_init;
 }
 
-static void __init shmobile_timer_init(void)
+void __init shmobile_timer_init(void)
 {
+	arch_timer_of_register();
+	arch_timer_sched_clock_init();
 }
-
-struct sys_timer shmobile_timer = {
-	.init		= shmobile_timer_init,
-};
diff --git a/arch/arm/mach-socfpga/platsmp.c b/arch/arm/mach-socfpga/platsmp.c
index 68dd1b6..4e9e69d 100644
--- a/arch/arm/mach-socfpga/platsmp.c
+++ b/arch/arm/mach-socfpga/platsmp.c
@@ -22,9 +22,9 @@
 #include <linux/io.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include <asm/cacheflush.h>
-#include <asm/hardware/gic.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_plat.h>
 
@@ -83,8 +83,6 @@
 
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
 
 static void __init socfpga_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-socfpga/socfpga.c b/arch/arm/mach-socfpga/socfpga.c
index 6732924..27d6846 100644
--- a/arch/arm/mach-socfpga/socfpga.c
+++ b/arch/arm/mach-socfpga/socfpga.c
@@ -15,12 +15,12 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 #include <linux/dw_apb_timer.h>
+#include <linux/irqchip.h>
 #include <linux/of_address.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
 
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
@@ -62,11 +62,6 @@
 	early_printk("Early printk initialized\n");
 }
 
-const static struct of_device_id irq_match[] = {
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-	{}
-};
-
 void __init socfpga_sysmgr_init(void)
 {
 	struct device_node *np;
@@ -78,9 +73,9 @@
 	rst_manager_base_addr = of_iomap(np, 0);
 }
 
-static void __init gic_init_irq(void)
+static void __init socfpga_init_irq(void)
 {
-	of_irq_init(irq_match);
+	irqchip_init();
 	socfpga_sysmgr_init();
 }
 
@@ -105,9 +100,8 @@
 DT_MACHINE_START(SOCFPGA, "Altera SOCFPGA")
 	.smp		= smp_ops(socfpga_smp_ops),
 	.map_io		= socfpga_map_io,
-	.init_irq	= gic_init_irq,
-	.handle_irq     = gic_handle_irq,
-	.timer		= &dw_apb_timer,
+	.init_irq	= socfpga_init_irq,
+	.init_time	= dw_apb_timer_init,
 	.init_machine	= socfpga_cyclone5_init,
 	.restart	= socfpga_cyclone5_restart,
 	.dt_compat	= altera_dt_match,
diff --git a/arch/arm/mach-spear13xx/include/mach/generic.h b/arch/arm/mach-spear13xx/include/mach/generic.h
index c33f4d9..633e678 100644
--- a/arch/arm/mach-spear13xx/include/mach/generic.h
+++ b/arch/arm/mach-spear13xx/include/mach/generic.h
@@ -18,7 +18,7 @@
 #include <asm/mach/time.h>
 
 /* Add spear13xx structure declarations here */
-extern struct sys_timer spear13xx_timer;
+extern void spear13xx_timer_init(void);
 extern struct pl022_ssp_controller pl022_plat_data;
 extern struct dw_dma_platform_data dmac_plat_data;
 extern struct dw_dma_slave cf_dma_priv;
@@ -28,7 +28,6 @@
 /* Add spear13xx family function declarations here */
 void __init spear_setup_of_timer(void);
 void __init spear13xx_map_io(void);
-void __init spear13xx_dt_init_irq(void);
 void __init spear13xx_l2x0_init(void);
 bool dw_dma_filter(struct dma_chan *chan, void *slave);
 void spear_restart(char, const char *);
diff --git a/arch/arm/mach-spear13xx/platsmp.c b/arch/arm/mach-spear13xx/platsmp.c
index 2eaa3fa..af4ade6 100644
--- a/arch/arm/mach-spear13xx/platsmp.c
+++ b/arch/arm/mach-spear13xx/platsmp.c
@@ -15,8 +15,8 @@
 #include <linux/jiffies.h>
 #include <linux/io.h>
 #include <linux/smp.h>
+#include <linux/irqchip/arm-gic.h>
 #include <asm/cacheflush.h>
-#include <asm/hardware/gic.h>
 #include <asm/smp_scu.h>
 #include <mach/spear.h>
 #include <mach/generic.h>
@@ -104,8 +104,6 @@
 
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
 
 static void __init spear13xx_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-spear13xx/spear1310.c b/arch/arm/mach-spear13xx/spear1310.c
index 02f4724..56214d1 100644
--- a/arch/arm/mach-spear13xx/spear1310.c
+++ b/arch/arm/mach-spear13xx/spear1310.c
@@ -14,9 +14,9 @@
 #define pr_fmt(fmt) "SPEAr1310: " fmt
 
 #include <linux/amba/pl022.h>
+#include <linux/irqchip.h>
 #include <linux/of_platform.h>
 #include <linux/pata_arasan_cf_data.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 #include <mach/generic.h>
@@ -90,9 +90,8 @@
 DT_MACHINE_START(SPEAR1310_DT, "ST SPEAr1310 SoC with Flattened Device Tree")
 	.smp		=	smp_ops(spear13xx_smp_ops),
 	.map_io		=	spear1310_map_io,
-	.init_irq	=	spear13xx_dt_init_irq,
-	.handle_irq	=	gic_handle_irq,
-	.timer		=	&spear13xx_timer,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear13xx_timer_init,
 	.init_machine	=	spear1310_dt_init,
 	.restart	=	spear_restart,
 	.dt_compat	=	spear1310_dt_board_compat,
diff --git a/arch/arm/mach-spear13xx/spear1340.c b/arch/arm/mach-spear13xx/spear1340.c
index 081014f..9a28beb 100644
--- a/arch/arm/mach-spear13xx/spear1340.c
+++ b/arch/arm/mach-spear13xx/spear1340.c
@@ -18,7 +18,7 @@
 #include <linux/delay.h>
 #include <linux/dw_dmac.h>
 #include <linux/of_platform.h>
-#include <asm/hardware/gic.h>
+#include <linux/irqchip.h>
 #include <asm/mach/arch.h>
 #include <mach/dma.h>
 #include <mach/generic.h>
@@ -184,9 +184,8 @@
 DT_MACHINE_START(SPEAR1340_DT, "ST SPEAr1340 SoC with Flattened Device Tree")
 	.smp		=	smp_ops(spear13xx_smp_ops),
 	.map_io		=	spear13xx_map_io,
-	.init_irq	=	spear13xx_dt_init_irq,
-	.handle_irq	=	gic_handle_irq,
-	.timer		=	&spear13xx_timer,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear13xx_timer_init,
 	.init_machine	=	spear1340_dt_init,
 	.restart	=	spear_restart,
 	.dt_compat	=	spear1340_dt_board_compat,
diff --git a/arch/arm/mach-spear13xx/spear13xx.c b/arch/arm/mach-spear13xx/spear13xx.c
index c4af775..c7d2b4a 100644
--- a/arch/arm/mach-spear13xx/spear13xx.c
+++ b/arch/arm/mach-spear13xx/spear13xx.c
@@ -17,9 +17,8 @@
 #include <linux/clk.h>
 #include <linux/dw_dmac.h>
 #include <linux/err.h>
-#include <linux/of_irq.h>
+#include <linux/of.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 #include <asm/smp_twd.h>
 #include <mach/dma.h>
@@ -153,7 +152,7 @@
 		pr_err("%s: Unknown machine\n", __func__);
 }
 
-static void __init spear13xx_timer_init(void)
+void __init spear13xx_timer_init(void)
 {
 	char pclk_name[] = "osc_24m_clk";
 	struct clk *gpt_clk, *pclk;
@@ -182,17 +181,3 @@
 	spear_setup_of_timer();
 	twd_local_timer_of_register();
 }
-
-struct sys_timer spear13xx_timer = {
-	.init = spear13xx_timer_init,
-};
-
-static const struct of_device_id gic_of_match[] __initconst = {
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init },
-	{ /* Sentinel */ }
-};
-
-void __init spear13xx_dt_init_irq(void)
-{
-	of_irq_init(gic_of_match);
-}
diff --git a/arch/arm/mach-spear3xx/include/mach/generic.h b/arch/arm/mach-spear3xx/include/mach/generic.h
index ce19113..df31079 100644
--- a/arch/arm/mach-spear3xx/include/mach/generic.h
+++ b/arch/arm/mach-spear3xx/include/mach/generic.h
@@ -22,7 +22,7 @@
 #include <asm/mach/map.h>
 
 /* Add spear3xx family device structure declarations here */
-extern struct sys_timer spear3xx_timer;
+extern void spear3xx_timer_init(void);
 extern struct pl022_ssp_controller pl022_plat_data;
 extern struct pl08x_platform_data pl080_plat_data;
 
@@ -30,7 +30,6 @@
 void __init spear_setup_of_timer(void);
 void __init spear3xx_clk_init(void);
 void __init spear3xx_map_io(void);
-void __init spear3xx_dt_init_irq(void);
 
 void spear_restart(char, const char *);
 
diff --git a/arch/arm/mach-spear3xx/spear300.c b/arch/arm/mach-spear3xx/spear300.c
index a69cbfd..bbc9b7e 100644
--- a/arch/arm/mach-spear3xx/spear300.c
+++ b/arch/arm/mach-spear3xx/spear300.c
@@ -14,8 +14,8 @@
 #define pr_fmt(fmt) "SPEAr300: " fmt
 
 #include <linux/amba/pl08x.h>
+#include <linux/irqchip.h>
 #include <linux/of_platform.h>
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
@@ -212,9 +212,8 @@
 
 DT_MACHINE_START(SPEAR300_DT, "ST SPEAr300 SoC with Flattened Device Tree")
 	.map_io		=	spear300_map_io,
-	.init_irq	=	spear3xx_dt_init_irq,
-	.handle_irq	=	vic_handle_irq,
-	.timer		=	&spear3xx_timer,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear3xx_timer_init,
 	.init_machine	=	spear300_dt_init,
 	.restart	=	spear_restart,
 	.dt_compat	=	spear300_dt_board_compat,
diff --git a/arch/arm/mach-spear3xx/spear310.c b/arch/arm/mach-spear3xx/spear310.c
index b963ebb..c13a434 100644
--- a/arch/arm/mach-spear3xx/spear310.c
+++ b/arch/arm/mach-spear3xx/spear310.c
@@ -15,8 +15,8 @@
 
 #include <linux/amba/pl08x.h>
 #include <linux/amba/serial.h>
+#include <linux/irqchip.h>
 #include <linux/of_platform.h>
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
@@ -254,9 +254,8 @@
 
 DT_MACHINE_START(SPEAR310_DT, "ST SPEAr310 SoC with Flattened Device Tree")
 	.map_io		=	spear310_map_io,
-	.init_irq	=	spear3xx_dt_init_irq,
-	.handle_irq	=	vic_handle_irq,
-	.timer		=	&spear3xx_timer,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear3xx_timer_init,
 	.init_machine	=	spear310_dt_init,
 	.restart	=	spear_restart,
 	.dt_compat	=	spear310_dt_board_compat,
diff --git a/arch/arm/mach-spear3xx/spear320.c b/arch/arm/mach-spear3xx/spear320.c
index 66e3a0c..e1c7707 100644
--- a/arch/arm/mach-spear3xx/spear320.c
+++ b/arch/arm/mach-spear3xx/spear320.c
@@ -16,8 +16,8 @@
 #include <linux/amba/pl022.h>
 #include <linux/amba/pl08x.h>
 #include <linux/amba/serial.h>
+#include <linux/irqchip.h>
 #include <linux/of_platform.h>
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
@@ -268,9 +268,8 @@
 
 DT_MACHINE_START(SPEAR320_DT, "ST SPEAr320 SoC with Flattened Device Tree")
 	.map_io		=	spear320_map_io,
-	.init_irq	=	spear3xx_dt_init_irq,
-	.handle_irq	=	vic_handle_irq,
-	.timer		=	&spear3xx_timer,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear3xx_timer_init,
 	.init_machine	=	spear320_dt_init,
 	.restart	=	spear_restart,
 	.dt_compat	=	spear320_dt_board_compat,
diff --git a/arch/arm/mach-spear3xx/spear3xx.c b/arch/arm/mach-spear3xx/spear3xx.c
index 38fe95d..b2ba516 100644
--- a/arch/arm/mach-spear3xx/spear3xx.c
+++ b/arch/arm/mach-spear3xx/spear3xx.c
@@ -15,11 +15,8 @@
 
 #include <linux/amba/pl022.h>
 #include <linux/amba/pl08x.h>
-#include <linux/irqchip/spear-shirq.h>
-#include <linux/of_irq.h>
 #include <linux/io.h>
 #include <asm/hardware/pl080.h>
-#include <asm/hardware/vic.h>
 #include <plat/pl080.h>
 #include <mach/generic.h>
 #include <mach/spear.h>
@@ -87,7 +84,7 @@
 	iotable_init(spear3xx_io_desc, ARRAY_SIZE(spear3xx_io_desc));
 }
 
-static void __init spear3xx_timer_init(void)
+void __init spear3xx_timer_init(void)
 {
 	char pclk_name[] = "pll3_clk";
 	struct clk *gpt_clk, *pclk;
@@ -115,20 +112,3 @@
 
 	spear_setup_of_timer();
 }
-
-struct sys_timer spear3xx_timer = {
-	.init = spear3xx_timer_init,
-};
-
-static const struct of_device_id vic_of_match[] __initconst = {
-	{ .compatible = "arm,pl190-vic", .data = vic_of_init, },
-	{ .compatible = "st,spear300-shirq", .data = spear300_shirq_of_init, },
-	{ .compatible = "st,spear310-shirq", .data = spear310_shirq_of_init, },
-	{ .compatible = "st,spear320-shirq", .data = spear320_shirq_of_init, },
-	{ /* Sentinel */ }
-};
-
-void __init spear3xx_dt_init_irq(void)
-{
-	of_irq_init(vic_of_match);
-}
diff --git a/arch/arm/mach-spear6xx/spear6xx.c b/arch/arm/mach-spear6xx/spear6xx.c
index 5a5a52d..b8bd33c 100644
--- a/arch/arm/mach-spear6xx/spear6xx.c
+++ b/arch/arm/mach-spear6xx/spear6xx.c
@@ -16,12 +16,11 @@
 #include <linux/amba/pl08x.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/irqchip.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
-#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <asm/hardware/pl080.h>
-#include <asm/hardware/vic.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/mach/map.h>
@@ -374,7 +373,7 @@
 	iotable_init(spear6xx_io_desc, ARRAY_SIZE(spear6xx_io_desc));
 }
 
-static void __init spear6xx_timer_init(void)
+void __init spear6xx_timer_init(void)
 {
 	char pclk_name[] = "pll3_clk";
 	struct clk *gpt_clk, *pclk;
@@ -403,10 +402,6 @@
 	spear_setup_of_timer();
 }
 
-struct sys_timer spear6xx_timer = {
-	.init = spear6xx_timer_init,
-};
-
 /* Add auxdata to pass platform data */
 struct of_dev_auxdata spear6xx_auxdata_lookup[] __initdata = {
 	OF_DEV_AUXDATA("arm,pl080", SPEAR6XX_ICM3_DMA_BASE, NULL,
@@ -425,21 +420,10 @@
 	NULL
 };
 
-static const struct of_device_id vic_of_match[] __initconst = {
-	{ .compatible = "arm,pl190-vic", .data = vic_of_init, },
-	{ /* Sentinel */ }
-};
-
-static void __init spear6xx_dt_init_irq(void)
-{
-	of_irq_init(vic_of_match);
-}
-
 DT_MACHINE_START(SPEAR600_DT, "ST SPEAr600 (Flattened Device Tree)")
 	.map_io		=	spear6xx_map_io,
-	.init_irq	=	spear6xx_dt_init_irq,
-	.handle_irq	=	vic_handle_irq,
-	.timer		=	&spear6xx_timer,
+	.init_irq	=	irqchip_init,
+	.init_time	=	spear6xx_timer_init,
 	.init_machine	=	spear600_dt_init,
 	.restart	=	spear_restart,
 	.dt_compat	=	spear600_dt_board_compat,
diff --git a/arch/arm/mach-sunxi/sunxi.c b/arch/arm/mach-sunxi/sunxi.c
index 1dc8a92..fb8fbce 100644
--- a/arch/arm/mach-sunxi/sunxi.c
+++ b/arch/arm/mach-sunxi/sunxi.c
@@ -21,8 +21,6 @@
 
 #include <linux/irqchip/sunxi.h>
 
-#include <asm/hardware/vic.h>
-
 #include <asm/mach/arch.h>
 #include <asm/mach/map.h>
 
@@ -91,6 +89,6 @@
 	.init_irq	= sunxi_init_irq,
 	.handle_irq	= sunxi_handle_irq,
 	.restart	= sunxi_restart,
-	.timer		= &sunxi_timer,
+	.init_time	= &sunxi_timer_init,
 	.dt_compat	= sunxi_board_dt_compat,
 MACHINE_END
diff --git a/arch/arm/mach-tegra/Kconfig b/arch/arm/mach-tegra/Kconfig
index b442f15..d1c4893 100644
--- a/arch/arm/mach-tegra/Kconfig
+++ b/arch/arm/mach-tegra/Kconfig
@@ -4,11 +4,11 @@
 
 config ARCH_TEGRA_2x_SOC
 	bool "Enable support for Tegra20 family"
-	select ARCH_REQUIRE_GPIOLIB
+	select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
 	select ARM_ERRATA_720789
-	select ARM_ERRATA_742230
+	select ARM_ERRATA_742230 if SMP
 	select ARM_ERRATA_751472
-	select ARM_ERRATA_754327
+	select ARM_ERRATA_754327 if SMP
 	select ARM_ERRATA_764369 if SMP
 	select ARM_GIC
 	select CPU_FREQ_TABLE if CPU_FREQ
@@ -26,7 +26,6 @@
 
 config ARCH_TEGRA_3x_SOC
 	bool "Enable support for Tegra30 family"
-	select ARCH_REQUIRE_GPIOLIB
 	select ARM_ERRATA_743622
 	select ARM_ERRATA_751472
 	select ARM_ERRATA_754322
@@ -44,6 +43,18 @@
 	  Support for NVIDIA Tegra T30 processor family, based on the
 	  ARM CortexA9MP CPU and the ARM PL310 L2 cache controller
 
+config ARCH_TEGRA_114_SOC
+	bool "Enable support for Tegra114 family"
+	select ARM_ARCH_TIMER
+	select ARM_GIC
+	select ARM_L1_CACHE_SHIFT_6
+	select CPU_V7
+	select PINCTRL
+	select PINCTRL_TEGRA114
+	help
+	  Support for NVIDIA Tegra T114 processor family, based on the
+	  ARM CortexA15MP CPU
+
 config TEGRA_PCI
 	bool "PCI Express support"
 	depends on ARCH_TEGRA_2x_SOC
diff --git a/arch/arm/mach-tegra/Makefile b/arch/arm/mach-tegra/Makefile
index 0979e8b..f6b46ae 100644
--- a/arch/arm/mach-tegra/Makefile
+++ b/arch/arm/mach-tegra/Makefile
@@ -1,39 +1,38 @@
 obj-y                                   += common.o
 obj-y                                   += io.o
 obj-y                                   += irq.o
-obj-y                                   += clock.o
-obj-y                                   += timer.o
 obj-y					+= fuse.o
 obj-y					+= pmc.o
 obj-y					+= flowctrl.o
 obj-y					+= powergate.o
 obj-y					+= apbio.o
 obj-y					+= pm.o
+obj-y					+= reset.o
+obj-y					+= reset-handler.o
+obj-y					+= sleep.o
 obj-$(CONFIG_CPU_IDLE)			+= cpuidle.o
-obj-$(CONFIG_CPU_IDLE)			+= sleep.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks.o
-obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += tegra20_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra20_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= tegra2_emc.o
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= sleep-tegra20.o
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= cpuidle-tegra20.o
 endif
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks.o
-obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_clocks_data.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= tegra30_speedo.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= sleep-tegra30.o
 ifeq ($(CONFIG_CPU_IDLE),y)
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= cpuidle-tegra30.o
 endif
 obj-$(CONFIG_SMP)			+= platsmp.o headsmp.o
-obj-$(CONFIG_SMP)                       += reset.o
 obj-$(CONFIG_HOTPLUG_CPU)               += hotplug.o
 obj-$(CONFIG_CPU_FREQ)                  += cpu-tegra.o
 obj-$(CONFIG_TEGRA_PCI)			+= pcie.o
 
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-dt-tegra20.o
 obj-$(CONFIG_ARCH_TEGRA_3x_SOC)		+= board-dt-tegra30.o
+obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= board-dt-tegra114.o
+ifeq ($(CONFIG_CPU_IDLE),y)
+obj-$(CONFIG_ARCH_TEGRA_114_SOC)	+= cpuidle-tegra114.o
+endif
 
 obj-$(CONFIG_ARCH_TEGRA_2x_SOC)		+= board-harmony-pcie.o
 
diff --git a/arch/arm/mach-tegra/apbio.c b/arch/arm/mach-tegra/apbio.c
index d091675..d7aa52e 100644
--- a/arch/arm/mach-tegra/apbio.c
+++ b/arch/arm/mach-tegra/apbio.c
@@ -38,7 +38,7 @@
 static struct dma_chan *tegra_apb_dma_chan;
 static struct dma_slave_config dma_sconfig;
 
-bool tegra_apb_dma_init(void)
+static bool tegra_apb_dma_init(void)
 {
 	dma_cap_mask_t mask;
 
diff --git a/arch/arm/mach-tegra/board-dt-tegra114.c b/arch/arm/mach-tegra/board-dt-tegra114.c
new file mode 100644
index 0000000..085d636
--- /dev/null
+++ b/arch/arm/mach-tegra/board-dt-tegra114.c
@@ -0,0 +1,46 @@
+/*
+ * NVIDIA Tegra114 device tree board support
+ *
+ * Copyright (C) 2013 NVIDIA Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * 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.
+ *
+ */
+
+#include <linux/of.h>
+#include <linux/of_platform.h>
+#include <linux/clocksource.h>
+
+#include <asm/mach/arch.h>
+
+#include "board.h"
+#include "common.h"
+
+static void __init tegra114_dt_init(void)
+{
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
+}
+
+static const char * const tegra114_dt_board_compat[] = {
+	"nvidia,tegra114",
+	NULL,
+};
+
+DT_MACHINE_START(TEGRA114_DT, "NVIDIA Tegra114 (Flattened Device Tree)")
+	.smp		= smp_ops(tegra_smp_ops),
+	.map_io		= tegra_map_common_io,
+	.init_early	= tegra114_init_early,
+	.init_irq	= tegra_dt_init_irq,
+	.init_time	= clocksource_of_init,
+	.init_machine	= tegra114_dt_init,
+	.init_late	= tegra_init_late,
+	.restart	= tegra_assert_system_reset,
+	.dt_compat	= tegra114_dt_board_compat,
+MACHINE_END
diff --git a/arch/arm/mach-tegra/board-dt-tegra20.c b/arch/arm/mach-tegra/board-dt-tegra20.c
index 734d9cc..a0edf25 100644
--- a/arch/arm/mach-tegra/board-dt-tegra20.c
+++ b/arch/arm/mach-tegra/board-dt-tegra20.c
@@ -15,6 +15,7 @@
  *
  */
 
+#include <linux/clocksource.h>
 #include <linux/kernel.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
@@ -25,7 +26,6 @@
 #include <linux/of.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
-#include <linux/of_irq.h>
 #include <linux/of_platform.h>
 #include <linux/pda_power.h>
 #include <linux/platform_data/tegra_usb.h>
@@ -34,106 +34,51 @@
 #include <linux/i2c-tegra.h>
 #include <linux/usb/tegra_usb_phy.h>
 
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/setup.h>
 
 #include "board.h"
-#include "clock.h"
 #include "common.h"
 #include "iomap.h"
 
-struct tegra_ehci_platform_data tegra_ehci1_pdata = {
+static struct tegra_ehci_platform_data tegra_ehci1_pdata = {
 	.operating_mode = TEGRA_USB_OTG,
 	.power_down_on_bus_suspend = 1,
 	.vbus_gpio = -1,
 };
 
-struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
+static struct tegra_ulpi_config tegra_ehci2_ulpi_phy_config = {
 	.reset_gpio = -1,
 	.clk = "cdev2",
 };
 
-struct tegra_ehci_platform_data tegra_ehci2_pdata = {
+static struct tegra_ehci_platform_data tegra_ehci2_pdata = {
 	.phy_config = &tegra_ehci2_ulpi_phy_config,
 	.operating_mode = TEGRA_USB_HOST,
 	.power_down_on_bus_suspend = 1,
 	.vbus_gpio = -1,
 };
 
-struct tegra_ehci_platform_data tegra_ehci3_pdata = {
+static struct tegra_ehci_platform_data tegra_ehci3_pdata = {
 	.operating_mode = TEGRA_USB_HOST,
 	.power_down_on_bus_suspend = 1,
 	.vbus_gpio = -1,
 };
 
-struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC1_BASE, "sdhci-tegra.0", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC2_BASE, "sdhci-tegra.1", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC3_BASE, "sdhci-tegra.2", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", TEGRA_SDMMC4_BASE, "sdhci-tegra.3", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C_BASE, "tegra-i2c.0", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C2_BASE, "tegra-i2c.1", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2c", TEGRA_I2C3_BASE, "tegra-i2c.2", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2c-dvc", TEGRA_DVC_BASE, "tegra-i2c.3", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S1_BASE, "tegra20-i2s.0", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2s", TEGRA_I2S2_BASE, "tegra20-i2s.1", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-das", TEGRA_APB_MISC_DAS_BASE, "tegra20-das", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB_BASE, "tegra-ehci.0",
+static struct of_dev_auxdata tegra20_auxdata_lookup[] __initdata = {
+	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5000000, "tegra-ehci.0",
 		       &tegra_ehci1_pdata),
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB2_BASE, "tegra-ehci.1",
+	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5004000, "tegra-ehci.1",
 		       &tegra_ehci2_pdata),
-	OF_DEV_AUXDATA("nvidia,tegra20-ehci", TEGRA_USB3_BASE, "tegra-ehci.2",
+	OF_DEV_AUXDATA("nvidia,tegra20-ehci", 0xC5008000, "tegra-ehci.2",
 		       &tegra_ehci3_pdata),
-	OF_DEV_AUXDATA("nvidia,tegra20-apbdma", TEGRA_APB_DMA_BASE, "tegra-apbdma", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-sflash", 0x7000c380, "spi", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D400, "spi_tegra.0", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D600, "spi_tegra.1", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000D800, "spi_tegra.2", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-slink", 0x7000DA00, "spi_tegra.3", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-host1x", 0x50000000, "host1x", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-dc", 0x54200000, "tegradc.0", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-dc", 0x54240000, "tegradc.1", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-hdmi", 0x54280000, "hdmi", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-dsi", 0x54300000, "dsi", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-tvo", 0x542c0000, "tvo", NULL),
 	{}
 };
 
-static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
-	/* name		parent		rate		enabled */
-	{ "uarta",	"pll_p",	216000000,	true },
-	{ "uartd",	"pll_p",	216000000,	true },
-	{ "usbd",	"clk_m",	12000000,	false },
-	{ "usb2",	"clk_m",	12000000,	false },
-	{ "usb3",	"clk_m",	12000000,	false },
-	{ "pll_a",      "pll_p_out1",   56448000,       true },
-	{ "pll_a_out0", "pll_a",        11289600,       true },
-	{ "cdev1",      NULL,           0,              true },
-	{ "blink",      "clk_32k",      32768,          true },
-	{ "i2s1",       "pll_a_out0",   11289600,       false},
-	{ "i2s2",       "pll_a_out0",   11289600,       false},
-	{ "sdmmc1",	"pll_p",	48000000,	false},
-	{ "sdmmc3",	"pll_p",	48000000,	false},
-	{ "sdmmc4",	"pll_p",	48000000,	false},
-	{ "spi",	"pll_p",	20000000,	false },
-	{ "sbc1",	"pll_p",	100000000,	false },
-	{ "sbc2",	"pll_p",	100000000,	false },
-	{ "sbc3",	"pll_p",	100000000,	false },
-	{ "sbc4",	"pll_p",	100000000,	false },
-	{ "host1x",	"pll_c",	150000000,	false },
-	{ "disp1",	"pll_p",	600000000,	false },
-	{ "disp2",	"pll_p",	600000000,	false },
-	{ NULL,		NULL,		0,		0},
-};
-
 static void __init tegra_dt_init(void)
 {
-	tegra_clk_init_from_table(tegra_dt_clk_init_table);
-
 	/*
 	 * Finished with the static registrations now; fill in the missing
 	 * devices
@@ -202,8 +147,7 @@
 	.smp		= smp_ops(tegra_smp_ops),
 	.init_early	= tegra20_init_early,
 	.init_irq	= tegra_dt_init_irq,
-	.handle_irq	= gic_handle_irq,
-	.timer		= &tegra_sys_timer,
+	.init_time	= clocksource_of_init,
 	.init_machine	= tegra_dt_init,
 	.init_late	= tegra_dt_init_late,
 	.restart	= tegra_assert_system_reset,
diff --git a/arch/arm/mach-tegra/board-dt-tegra30.c b/arch/arm/mach-tegra/board-dt-tegra30.c
index 6497d12..bf68567 100644
--- a/arch/arm/mach-tegra/board-dt-tegra30.c
+++ b/arch/arm/mach-tegra/board-dt-tegra30.c
@@ -23,6 +23,7 @@
  *
  */
 
+#include <linux/clocksource.h>
 #include <linux/kernel.h>
 #include <linux/of.h>
 #include <linux/of_address.h>
@@ -31,75 +32,14 @@
 #include <linux/of_platform.h>
 
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 
 #include "board.h"
-#include "clock.h"
 #include "common.h"
 #include "iomap.h"
 
-struct of_dev_auxdata tegra30_auxdata_lookup[] __initdata = {
-	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000000, "sdhci-tegra.0", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000200, "sdhci-tegra.1", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000400, "sdhci-tegra.2", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-sdhci", 0x78000600, "sdhci-tegra.3", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C000, "tegra-i2c.0", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C400, "tegra-i2c.1", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C500, "tegra-i2c.2", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000C700, "tegra-i2c.3", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra20-i2c", 0x7000D000, "tegra-i2c.4", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-ahub", 0x70080000, "tegra30-ahub", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-apbdma", 0x6000a000, "tegra-apbdma", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-pwm", TEGRA_PWFM_BASE, "tegra-pwm", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D400, "spi_tegra.0", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D600, "spi_tegra.1", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000D800, "spi_tegra.2", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DA00, "spi_tegra.3", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DC00, "spi_tegra.4", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-slink", 0x7000DE00, "spi_tegra.5", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-host1x", 0x50000000, "host1x", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-dc", 0x54200000, "tegradc.0", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-dc", 0x54240000, "tegradc.1", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-hdmi", 0x54280000, "hdmi", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-dsi", 0x54300000, "dsi", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-tvo", 0x542c0000, "tvo", NULL),
-	{}
-};
-
-static __initdata struct tegra_clk_init_table tegra_dt_clk_init_table[] = {
-	/* name		parent		rate		enabled */
-	{ "uarta",	"pll_p",	408000000,	true },
-	{ "pll_a",	"pll_p_out1",	564480000,	true },
-	{ "pll_a_out0",	"pll_a",	11289600,	true },
-	{ "extern1",	"pll_a_out0",	0,		true },
-	{ "clk_out_1",	"extern1",	0,		true },
-	{ "blink",	"clk_32k",	32768,		true },
-	{ "i2s0",	"pll_a_out0",	11289600,	false},
-	{ "i2s1",	"pll_a_out0",	11289600,	false},
-	{ "i2s2",	"pll_a_out0",	11289600,	false},
-	{ "i2s3",	"pll_a_out0",	11289600,	false},
-	{ "i2s4",	"pll_a_out0",	11289600,	false},
-	{ "sdmmc1",	"pll_p",	48000000,	false},
-	{ "sdmmc3",	"pll_p",	48000000,	false},
-	{ "sdmmc4",	"pll_p",	48000000,	false},
-	{ "sbc1",	"pll_p",	100000000,	false},
-	{ "sbc2",	"pll_p",	100000000,	false},
-	{ "sbc3",	"pll_p",	100000000,	false},
-	{ "sbc4",	"pll_p",	100000000,	false},
-	{ "sbc5",	"pll_p",	100000000,	false},
-	{ "sbc6",	"pll_p",	100000000,	false},
-	{ "host1x",	"pll_c",	150000000,	false},
-	{ "disp1",	"pll_p",	600000000,	false},
-	{ "disp2",	"pll_p",	600000000,	false},
-	{ NULL,		NULL,		0,		0},
-};
-
 static void __init tegra30_dt_init(void)
 {
-	tegra_clk_init_from_table(tegra_dt_clk_init_table);
-
-	of_platform_populate(NULL, of_default_bus_match_table,
-				tegra30_auxdata_lookup, NULL);
+	of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
 }
 
 static const char *tegra30_dt_board_compat[] = {
@@ -112,8 +52,7 @@
 	.map_io		= tegra_map_common_io,
 	.init_early	= tegra30_init_early,
 	.init_irq	= tegra_dt_init_irq,
-	.handle_irq	= gic_handle_irq,
-	.timer		= &tegra_sys_timer,
+	.init_time	= clocksource_of_init,
 	.init_machine	= tegra30_dt_init,
 	.init_late	= tegra_init_late,
 	.restart	= tegra_assert_system_reset,
diff --git a/arch/arm/mach-tegra/board.h b/arch/arm/mach-tegra/board.h
index 91fbe73..86851c8 100644
--- a/arch/arm/mach-tegra/board.h
+++ b/arch/arm/mach-tegra/board.h
@@ -1,6 +1,7 @@
 /*
  * arch/arm/mach-tegra/board.h
  *
+ * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
  * Copyright (C) 2010 Google, Inc.
  *
  * Author:
@@ -27,6 +28,7 @@
 
 void __init tegra20_init_early(void);
 void __init tegra30_init_early(void);
+void __init tegra114_init_early(void);
 void __init tegra_map_common_io(void);
 void __init tegra_init_irq(void);
 void __init tegra_dt_init_irq(void);
@@ -55,5 +57,4 @@
 
 void __init tegra_paz00_wifikill_init(void);
 
-extern struct sys_timer tegra_sys_timer;
 #endif
diff --git a/arch/arm/mach-tegra/clock.c b/arch/arm/mach-tegra/clock.c
deleted file mode 100644
index 867bf8b..0000000
--- a/arch/arm/mach-tegra/clock.c
+++ /dev/null
@@ -1,166 +0,0 @@
-/*
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/clk.h>
-#include <linux/clkdev.h>
-#include <linux/init.h>
-#include <linux/list.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/seq_file.h>
-#include <linux/slab.h>
-
-#include "board.h"
-#include "clock.h"
-#include "tegra_cpu_car.h"
-
-/* Global data of Tegra CPU CAR ops */
-struct tegra_cpu_car_ops *tegra_cpu_car_ops;
-
-/*
- * Locking:
- *
- * An additional mutex, clock_list_lock, is used to protect the list of all
- * clocks.
- *
- */
-static DEFINE_MUTEX(clock_list_lock);
-static LIST_HEAD(clocks);
-
-void tegra_clk_add(struct clk *clk)
-{
-	struct clk_tegra *c = to_clk_tegra(__clk_get_hw(clk));
-
-	mutex_lock(&clock_list_lock);
-	list_add(&c->node, &clocks);
-	mutex_unlock(&clock_list_lock);
-}
-
-struct clk *tegra_get_clock_by_name(const char *name)
-{
-	struct clk_tegra *c;
-	struct clk *ret = NULL;
-	mutex_lock(&clock_list_lock);
-	list_for_each_entry(c, &clocks, node) {
-		if (strcmp(__clk_get_name(c->hw.clk), name) == 0) {
-			ret = c->hw.clk;
-			break;
-		}
-	}
-	mutex_unlock(&clock_list_lock);
-	return ret;
-}
-
-static int tegra_clk_init_one_from_table(struct tegra_clk_init_table *table)
-{
-	struct clk *c;
-	struct clk *p;
-	struct clk *parent;
-
-	int ret = 0;
-
-	c = tegra_get_clock_by_name(table->name);
-
-	if (!c) {
-		pr_warn("Unable to initialize clock %s\n",
-			table->name);
-		return -ENODEV;
-	}
-
-	parent = clk_get_parent(c);
-
-	if (table->parent) {
-		p = tegra_get_clock_by_name(table->parent);
-		if (!p) {
-			pr_warn("Unable to find parent %s of clock %s\n",
-				table->parent, table->name);
-			return -ENODEV;
-		}
-
-		if (parent != p) {
-			ret = clk_set_parent(c, p);
-			if (ret) {
-				pr_warn("Unable to set parent %s of clock %s: %d\n",
-					table->parent, table->name, ret);
-				return -EINVAL;
-			}
-		}
-	}
-
-	if (table->rate && table->rate != clk_get_rate(c)) {
-		ret = clk_set_rate(c, table->rate);
-		if (ret) {
-			pr_warn("Unable to set clock %s to rate %lu: %d\n",
-				table->name, table->rate, ret);
-			return -EINVAL;
-		}
-	}
-
-	if (table->enabled) {
-		ret = clk_prepare_enable(c);
-		if (ret) {
-			pr_warn("Unable to enable clock %s: %d\n",
-				table->name, ret);
-			return -EINVAL;
-		}
-	}
-
-	return 0;
-}
-
-void tegra_clk_init_from_table(struct tegra_clk_init_table *table)
-{
-	for (; table->name; table++)
-		tegra_clk_init_one_from_table(table);
-}
-
-void tegra_periph_reset_deassert(struct clk *c)
-{
-	struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
-	BUG_ON(!clk->reset);
-	clk->reset(__clk_get_hw(c), false);
-}
-EXPORT_SYMBOL(tegra_periph_reset_deassert);
-
-void tegra_periph_reset_assert(struct clk *c)
-{
-	struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
-	BUG_ON(!clk->reset);
-	clk->reset(__clk_get_hw(c), true);
-}
-EXPORT_SYMBOL(tegra_periph_reset_assert);
-
-/* Several extended clock configuration bits (e.g., clock routing, clock
- * phase control) are included in PLL and peripheral clock source
- * registers. */
-int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting)
-{
-	int ret = 0;
-	struct clk_tegra *clk = to_clk_tegra(__clk_get_hw(c));
-
-	if (!clk->clk_cfg_ex) {
-		ret = -ENOSYS;
-		goto out;
-	}
-	ret = clk->clk_cfg_ex(__clk_get_hw(c), p, setting);
-
-out:
-	return ret;
-}
diff --git a/arch/arm/mach-tegra/clock.h b/arch/arm/mach-tegra/clock.h
deleted file mode 100644
index 2aa37f5..0000000
--- a/arch/arm/mach-tegra/clock.h
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/clock.h
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef __MACH_TEGRA_CLOCK_H
-#define __MACH_TEGRA_CLOCK_H
-
-#include <linux/clk-provider.h>
-#include <linux/clkdev.h>
-#include <linux/list.h>
-
-#include <mach/clk.h>
-
-#define DIV_BUS			(1 << 0)
-#define DIV_U71			(1 << 1)
-#define DIV_U71_FIXED		(1 << 2)
-#define DIV_2			(1 << 3)
-#define DIV_U16			(1 << 4)
-#define PLL_FIXED		(1 << 5)
-#define PLL_HAS_CPCON		(1 << 6)
-#define MUX			(1 << 7)
-#define PLLD			(1 << 8)
-#define PERIPH_NO_RESET		(1 << 9)
-#define PERIPH_NO_ENB		(1 << 10)
-#define PERIPH_EMC_ENB		(1 << 11)
-#define PERIPH_MANUAL_RESET	(1 << 12)
-#define PLL_ALT_MISC_REG	(1 << 13)
-#define PLLU			(1 << 14)
-#define PLLX                    (1 << 15)
-#define MUX_PWM                 (1 << 16)
-#define MUX8                    (1 << 17)
-#define DIV_U71_UART            (1 << 18)
-#define MUX_CLK_OUT             (1 << 19)
-#define PLLM                    (1 << 20)
-#define DIV_U71_INT             (1 << 21)
-#define DIV_U71_IDLE            (1 << 22)
-#define ENABLE_ON_INIT		(1 << 28)
-#define PERIPH_ON_APB           (1 << 29)
-
-struct clk_tegra;
-#define to_clk_tegra(_hw) container_of(_hw, struct clk_tegra, hw)
-
-struct clk_mux_sel {
-	struct clk	*input;
-	u32		value;
-};
-
-struct clk_pll_freq_table {
-	unsigned long	input_rate;
-	unsigned long	output_rate;
-	u16		n;
-	u16		m;
-	u8		p;
-	u8		cpcon;
-};
-
-enum clk_state {
-	UNINITIALIZED = 0,
-	ON,
-	OFF,
-};
-
-struct clk_tegra {
-	/* node for master clocks list */
-	struct list_head	node;	/* node for list of all clocks */
-	struct clk_lookup	lookup;
-	struct clk_hw		hw;
-
-	bool			set;
-	unsigned long		fixed_rate;
-	unsigned long		max_rate;
-	unsigned long		min_rate;
-	u32			flags;
-	const char		*name;
-
-	enum clk_state		state;
-	u32			div;
-	u32			mul;
-
-	u32				reg;
-	u32				reg_shift;
-
-	struct list_head		shared_bus_list;
-
-	union {
-		struct {
-			unsigned int			clk_num;
-		} periph;
-		struct {
-			unsigned long			input_min;
-			unsigned long			input_max;
-			unsigned long			cf_min;
-			unsigned long			cf_max;
-			unsigned long			vco_min;
-			unsigned long			vco_max;
-			const struct clk_pll_freq_table	*freq_table;
-			int				lock_delay;
-			unsigned long			fixed_rate;
-		} pll;
-		struct {
-			u32				sel;
-			u32				reg_mask;
-		} mux;
-		struct {
-			struct clk			*main;
-			struct clk			*backup;
-		} cpu;
-		struct {
-			struct list_head		node;
-			bool				enabled;
-			unsigned long			rate;
-		} shared_bus_user;
-	} u;
-
-	void (*reset)(struct clk_hw *, bool);
-	int (*clk_cfg_ex)(struct clk_hw *, enum tegra_clk_ex_param, u32);
-};
-
-struct clk_duplicate {
-	const char *name;
-	struct clk_lookup lookup;
-};
-
-struct tegra_clk_init_table {
-	const char *name;
-	const char *parent;
-	unsigned long rate;
-	bool enabled;
-};
-
-void tegra_clk_add(struct clk *c);
-void tegra2_init_clocks(void);
-void tegra30_init_clocks(void);
-struct clk *tegra_get_clock_by_name(const char *name);
-void tegra_clk_init_from_table(struct tegra_clk_init_table *table);
-
-#endif
diff --git a/arch/arm/mach-tegra/common.c b/arch/arm/mach-tegra/common.c
index d54cfc5..5449a3f 100644
--- a/arch/arm/mach-tegra/common.c
+++ b/arch/arm/mach-tegra/common.c
@@ -1,6 +1,7 @@
 /*
  * arch/arm/mach-tegra/common.c
  *
+ * Copyright (c) 2013 NVIDIA Corporation. All rights reserved.
  * Copyright (C) 2010 Google, Inc.
  *
  * Author:
@@ -21,15 +22,14 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
-#include <linux/of_irq.h>
+#include <linux/irqchip.h>
+#include <linux/clk/tegra.h>
 
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/gic.h>
 
 #include <mach/powergate.h>
 
 #include "board.h"
-#include "clock.h"
 #include "common.h"
 #include "fuse.h"
 #include "iomap.h"
@@ -37,6 +37,7 @@
 #include "apbio.h"
 #include "sleep.h"
 #include "pm.h"
+#include "reset.h"
 
 /*
  * Storage for debug-macro.S's state.
@@ -57,15 +58,11 @@
 };
 
 #ifdef CONFIG_OF
-static const struct of_device_id tegra_dt_irq_match[] __initconst = {
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init },
-	{ }
-};
-
 void __init tegra_dt_init_irq(void)
 {
+	tegra_clocks_init();
 	tegra_init_irq();
-	of_irq_init(tegra_dt_irq_match);
+	irqchip_init();
 }
 #endif
 
@@ -79,43 +76,6 @@
 	writel_relaxed(reg, reset);
 }
 
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-static __initdata struct tegra_clk_init_table tegra20_clk_init_table[] = {
-	/* name		parent		rate		enabled */
-	{ "clk_m",	NULL,		0,		true },
-	{ "pll_p",	"clk_m",	216000000,	true },
-	{ "pll_p_out1",	"pll_p",	28800000,	true },
-	{ "pll_p_out2",	"pll_p",	48000000,	true },
-	{ "pll_p_out3",	"pll_p",	72000000,	true },
-	{ "pll_p_out4",	"pll_p",	24000000,	true },
-	{ "pll_c",	"clk_m",	600000000,	true },
-	{ "pll_c_out1",	"pll_c",	120000000,	true },
-	{ "sclk",	"pll_c_out1",	120000000,	true },
-	{ "hclk",	"sclk",		120000000,	true },
-	{ "pclk",	"hclk",		60000000,	true },
-	{ "csite",	NULL,		0,		true },
-	{ "emc",	NULL,		0,		true },
-	{ "cpu",	NULL,		0,		true },
-	{ NULL,		NULL,		0,		0},
-};
-#endif
-
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-static __initdata struct tegra_clk_init_table tegra30_clk_init_table[] = {
-	/* name		parent		rate		enabled */
-	{ "clk_m",	NULL,		0,		true },
-	{ "pll_p",	"pll_ref",	408000000,	true },
-	{ "pll_p_out1",	"pll_p",	9600000,	true },
-	{ "pll_p_out4",	"pll_p",	102000000,	true },
-	{ "sclk",	"pll_p_out4",	102000000,	true },
-	{ "hclk",	"sclk",		102000000,	true },
-	{ "pclk",	"hclk",		51000000,	true },
-	{ "csite",	NULL,		0,		true },
-	{ NULL,		NULL,		0,		0},
-};
-#endif
-
-
 static void __init tegra_init_cache(void)
 {
 #ifdef CONFIG_CACHE_L2X0
@@ -134,33 +94,39 @@
 
 }
 
+static void __init tegra_init_early(void)
+{
+	tegra_cpu_reset_handler_init();
+	tegra_apb_io_init();
+	tegra_init_fuse();
+	tegra_init_cache();
+	tegra_pmc_init();
+	tegra_powergate_init();
+}
+
 #ifdef CONFIG_ARCH_TEGRA_2x_SOC
 void __init tegra20_init_early(void)
 {
-	tegra_apb_io_init();
-	tegra_init_fuse();
-	tegra2_init_clocks();
-	tegra_clk_init_from_table(tegra20_clk_init_table);
-	tegra_init_cache();
-	tegra_pmc_init();
-	tegra_powergate_init();
+	tegra_init_early();
 	tegra20_hotplug_init();
 }
 #endif
+
 #ifdef CONFIG_ARCH_TEGRA_3x_SOC
 void __init tegra30_init_early(void)
 {
-	tegra_apb_io_init();
-	tegra_init_fuse();
-	tegra30_init_clocks();
-	tegra_clk_init_from_table(tegra30_clk_init_table);
-	tegra_init_cache();
-	tegra_pmc_init();
-	tegra_powergate_init();
+	tegra_init_early();
 	tegra30_hotplug_init();
 }
 #endif
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+void __init tegra114_init_early(void)
+{
+	tegra_init_early();
+}
+#endif
+
 void __init tegra_init_late(void)
 {
 	tegra_powergate_debugfs_init();
diff --git a/arch/arm/mach-tegra/common.h b/arch/arm/mach-tegra/common.h
index 02f71b4..32f8eb3 100644
--- a/arch/arm/mach-tegra/common.h
+++ b/arch/arm/mach-tegra/common.h
@@ -1,4 +1,5 @@
 extern struct smp_operations tegra_smp_ops;
 
+extern int tegra_cpu_kill(unsigned int cpu);
 extern void tegra_cpu_die(unsigned int cpu);
 extern int tegra_cpu_disable(unsigned int cpu);
diff --git a/arch/arm/mach-tegra/cpu-tegra.c b/arch/arm/mach-tegra/cpu-tegra.c
index a74d3c7..ebffed6 100644
--- a/arch/arm/mach-tegra/cpu-tegra.c
+++ b/arch/arm/mach-tegra/cpu-tegra.c
@@ -214,24 +214,6 @@
 	if (policy->cpu >= NUM_CPUS)
 		return -EINVAL;
 
-	cpu_clk = clk_get_sys(NULL, "cpu");
-	if (IS_ERR(cpu_clk))
-		return PTR_ERR(cpu_clk);
-
-	pll_x_clk = clk_get_sys(NULL, "pll_x");
-	if (IS_ERR(pll_x_clk))
-		return PTR_ERR(pll_x_clk);
-
-	pll_p_clk = clk_get_sys(NULL, "pll_p");
-	if (IS_ERR(pll_p_clk))
-		return PTR_ERR(pll_p_clk);
-
-	emc_clk = clk_get_sys("cpu", "emc");
-	if (IS_ERR(emc_clk)) {
-		clk_put(cpu_clk);
-		return PTR_ERR(emc_clk);
-	}
-
 	clk_prepare_enable(emc_clk);
 	clk_prepare_enable(cpu_clk);
 
@@ -256,8 +238,6 @@
 {
 	cpufreq_frequency_table_cpuinfo(policy, freq_table);
 	clk_disable_unprepare(emc_clk);
-	clk_put(emc_clk);
-	clk_put(cpu_clk);
 	return 0;
 }
 
@@ -278,12 +258,32 @@
 
 static int __init tegra_cpufreq_init(void)
 {
+	cpu_clk = clk_get_sys(NULL, "cpu");
+	if (IS_ERR(cpu_clk))
+		return PTR_ERR(cpu_clk);
+
+	pll_x_clk = clk_get_sys(NULL, "pll_x");
+	if (IS_ERR(pll_x_clk))
+		return PTR_ERR(pll_x_clk);
+
+	pll_p_clk = clk_get_sys(NULL, "pll_p_cclk");
+	if (IS_ERR(pll_p_clk))
+		return PTR_ERR(pll_p_clk);
+
+	emc_clk = clk_get_sys("cpu", "emc");
+	if (IS_ERR(emc_clk)) {
+		clk_put(cpu_clk);
+		return PTR_ERR(emc_clk);
+	}
+
 	return cpufreq_register_driver(&tegra_cpufreq_driver);
 }
 
 static void __exit tegra_cpufreq_exit(void)
 {
         cpufreq_unregister_driver(&tegra_cpufreq_driver);
+	clk_put(emc_clk);
+	clk_put(cpu_clk);
 }
 
 
diff --git a/arch/arm/mach-tegra/cpuidle-tegra114.c b/arch/arm/mach-tegra/cpuidle-tegra114.c
new file mode 100644
index 0000000..0f4e8c4
--- /dev/null
+++ b/arch/arm/mach-tegra/cpuidle-tegra114.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2013, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/cpuidle.h>
+
+#include <asm/cpuidle.h>
+
+static struct cpuidle_driver tegra_idle_driver = {
+	.name = "tegra_idle",
+	.owner = THIS_MODULE,
+	.en_core_tk_irqen = 1,
+	.state_count = 1,
+	.states = {
+		[0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
+	},
+};
+
+static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
+
+int __init tegra114_cpuidle_init(void)
+{
+	int ret;
+	unsigned int cpu;
+	struct cpuidle_device *dev;
+	struct cpuidle_driver *drv = &tegra_idle_driver;
+
+	ret = cpuidle_register_driver(&tegra_idle_driver);
+	if (ret) {
+		pr_err("CPUidle driver registration failed\n");
+		return ret;
+	}
+
+	for_each_possible_cpu(cpu) {
+		dev = &per_cpu(tegra_idle_device, cpu);
+		dev->cpu = cpu;
+
+		dev->state_count = drv->state_count;
+		ret = cpuidle_register_device(dev);
+		if (ret) {
+			pr_err("CPU%u: CPUidle device registration failed\n",
+				cpu);
+			return ret;
+		}
+	}
+	return 0;
+}
diff --git a/arch/arm/mach-tegra/cpuidle-tegra20.c b/arch/arm/mach-tegra/cpuidle-tegra20.c
index d32e8b0..825ced4 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra20.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra20.c
@@ -22,21 +22,199 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/cpuidle.h>
+#include <linux/cpu_pm.h>
+#include <linux/clockchips.h>
+#include <linux/clk/tegra.h>
 
 #include <asm/cpuidle.h>
+#include <asm/proc-fns.h>
+#include <asm/suspend.h>
+#include <asm/smp_plat.h>
+
+#include "pm.h"
+#include "sleep.h"
+#include "iomap.h"
+#include "irq.h"
+#include "flowctrl.h"
+
+#ifdef CONFIG_PM_SLEEP
+static bool abort_flag;
+static atomic_t abort_barrier;
+static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
+				    struct cpuidle_driver *drv,
+				    int index);
+#endif
+
+static struct cpuidle_state tegra_idle_states[] = {
+	[0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
+#ifdef CONFIG_PM_SLEEP
+	[1] = {
+		.enter			= tegra20_idle_lp2_coupled,
+		.exit_latency		= 5000,
+		.target_residency	= 10000,
+		.power_usage		= 0,
+		.flags			= CPUIDLE_FLAG_TIME_VALID |
+					  CPUIDLE_FLAG_COUPLED,
+		.name			= "powered-down",
+		.desc			= "CPU power gated",
+	},
+#endif
+};
 
 static struct cpuidle_driver tegra_idle_driver = {
 	.name = "tegra_idle",
 	.owner = THIS_MODULE,
 	.en_core_tk_irqen = 1,
-	.state_count = 1,
-	.states = {
-		[0] = ARM_CPUIDLE_WFI_STATE_PWR(600),
-	},
 };
 
 static DEFINE_PER_CPU(struct cpuidle_device, tegra_idle_device);
 
+#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_SMP
+static void __iomem *pmc = IO_ADDRESS(TEGRA_PMC_BASE);
+
+static int tegra20_reset_sleeping_cpu_1(void)
+{
+	int ret = 0;
+
+	tegra_pen_lock();
+
+	if (readl(pmc + PMC_SCRATCH41) == CPU_RESETTABLE)
+		tegra20_cpu_shutdown(1);
+	else
+		ret = -EINVAL;
+
+	tegra_pen_unlock();
+
+	return ret;
+}
+
+static void tegra20_wake_cpu1_from_reset(void)
+{
+	tegra_pen_lock();
+
+	tegra20_cpu_clear_resettable();
+
+	/* enable cpu clock on cpu */
+	tegra_enable_cpu_clock(1);
+
+	/* take the CPU out of reset */
+	tegra_cpu_out_of_reset(1);
+
+	/* unhalt the cpu */
+	flowctrl_write_cpu_halt(1, 0);
+
+	tegra_pen_unlock();
+}
+
+static int tegra20_reset_cpu_1(void)
+{
+	if (!cpu_online(1) || !tegra20_reset_sleeping_cpu_1())
+		return 0;
+
+	tegra20_wake_cpu1_from_reset();
+	return -EBUSY;
+}
+#else
+static inline void tegra20_wake_cpu1_from_reset(void)
+{
+}
+
+static inline int tegra20_reset_cpu_1(void)
+{
+	return 0;
+}
+#endif
+
+static bool tegra20_cpu_cluster_power_down(struct cpuidle_device *dev,
+					   struct cpuidle_driver *drv,
+					   int index)
+{
+	struct cpuidle_state *state = &drv->states[index];
+	u32 cpu_on_time = state->exit_latency;
+	u32 cpu_off_time = state->target_residency - state->exit_latency;
+
+	while (tegra20_cpu_is_resettable_soon())
+		cpu_relax();
+
+	if (tegra20_reset_cpu_1() || !tegra_cpu_rail_off_ready())
+		return false;
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+
+	tegra_idle_lp2_last(cpu_on_time, cpu_off_time);
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+
+	if (cpu_online(1))
+		tegra20_wake_cpu1_from_reset();
+
+	return true;
+}
+
+#ifdef CONFIG_SMP
+static bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev,
+					 struct cpuidle_driver *drv,
+					 int index)
+{
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_ENTER, &dev->cpu);
+
+	cpu_suspend(0, tegra20_sleep_cpu_secondary_finish);
+
+	tegra20_cpu_clear_resettable();
+
+	clockevents_notify(CLOCK_EVT_NOTIFY_BROADCAST_EXIT, &dev->cpu);
+
+	return true;
+}
+#else
+static inline bool tegra20_idle_enter_lp2_cpu_1(struct cpuidle_device *dev,
+						struct cpuidle_driver *drv,
+						int index)
+{
+	return true;
+}
+#endif
+
+static int tegra20_idle_lp2_coupled(struct cpuidle_device *dev,
+				    struct cpuidle_driver *drv,
+				    int index)
+{
+	u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu;
+	bool entered_lp2 = false;
+
+	if (tegra_pending_sgi())
+		ACCESS_ONCE(abort_flag) = true;
+
+	cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
+
+	if (abort_flag) {
+		cpuidle_coupled_parallel_barrier(dev, &abort_barrier);
+		abort_flag = false;	/* clean flag for next coming */
+		return -EINTR;
+	}
+
+	local_fiq_disable();
+
+	tegra_set_cpu_in_lp2(cpu);
+	cpu_pm_enter();
+
+	if (cpu == 0)
+		entered_lp2 = tegra20_cpu_cluster_power_down(dev, drv, index);
+	else
+		entered_lp2 = tegra20_idle_enter_lp2_cpu_1(dev, drv, index);
+
+	cpu_pm_exit();
+	tegra_clear_cpu_in_lp2(cpu);
+
+	local_fiq_enable();
+
+	smp_rmb();
+
+	return entered_lp2 ? index : 0;
+}
+#endif
+
 int __init tegra20_cpuidle_init(void)
 {
 	int ret;
@@ -44,6 +222,14 @@
 	struct cpuidle_device *dev;
 	struct cpuidle_driver *drv = &tegra_idle_driver;
 
+#ifdef CONFIG_PM_SLEEP
+	tegra_tear_down_cpu = tegra20_tear_down_cpu;
+#endif
+
+	drv->state_count = ARRAY_SIZE(tegra_idle_states);
+	memcpy(drv->states, tegra_idle_states,
+			drv->state_count * sizeof(drv->states[0]));
+
 	ret = cpuidle_register_driver(&tegra_idle_driver);
 	if (ret) {
 		pr_err("CPUidle driver registration failed\n");
@@ -53,6 +239,9 @@
 	for_each_possible_cpu(cpu) {
 		dev = &per_cpu(tegra_idle_device, cpu);
 		dev->cpu = cpu;
+#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
+		dev->coupled_cpus = *cpu_possible_mask;
+#endif
 
 		dev->state_count = drv->state_count;
 		ret = cpuidle_register_device(dev);
diff --git a/arch/arm/mach-tegra/cpuidle-tegra30.c b/arch/arm/mach-tegra/cpuidle-tegra30.c
index 5e8cbf5..8b50cf4 100644
--- a/arch/arm/mach-tegra/cpuidle-tegra30.c
+++ b/arch/arm/mach-tegra/cpuidle-tegra30.c
@@ -24,6 +24,7 @@
 #include <linux/cpuidle.h>
 #include <linux/cpu_pm.h>
 #include <linux/clockchips.h>
+#include <linux/clk/tegra.h>
 
 #include <asm/cpuidle.h>
 #include <asm/proc-fns.h>
@@ -32,7 +33,6 @@
 
 #include "pm.h"
 #include "sleep.h"
-#include "tegra_cpu_car.h"
 
 #ifdef CONFIG_PM_SLEEP
 static int tegra30_idle_lp2(struct cpuidle_device *dev,
@@ -121,9 +121,9 @@
 }
 #endif
 
-static int __cpuinit tegra30_idle_lp2(struct cpuidle_device *dev,
-				      struct cpuidle_driver *drv,
-				      int index)
+static int tegra30_idle_lp2(struct cpuidle_device *dev,
+			    struct cpuidle_driver *drv,
+			    int index)
 {
 	u32 cpu = is_smp() ? cpu_logical_map(dev->cpu) : dev->cpu;
 	bool entered_lp2 = false;
diff --git a/arch/arm/mach-tegra/cpuidle.c b/arch/arm/mach-tegra/cpuidle.c
index d065139..4b744c4 100644
--- a/arch/arm/mach-tegra/cpuidle.c
+++ b/arch/arm/mach-tegra/cpuidle.c
@@ -38,6 +38,9 @@
 	case TEGRA30:
 		ret = tegra30_cpuidle_init();
 		break;
+	case TEGRA114:
+		ret = tegra114_cpuidle_init();
+		break;
 	default:
 		ret = -ENODEV;
 		break;
diff --git a/arch/arm/mach-tegra/cpuidle.h b/arch/arm/mach-tegra/cpuidle.h
index 496204d..d733f75d 100644
--- a/arch/arm/mach-tegra/cpuidle.h
+++ b/arch/arm/mach-tegra/cpuidle.h
@@ -29,4 +29,10 @@
 static inline int tegra30_cpuidle_init(void) { return -ENODEV; }
 #endif
 
+#ifdef CONFIG_ARCH_TEGRA_114_SOC
+int tegra114_cpuidle_init(void);
+#else
+static inline int tegra114_cpuidle_init(void) { return -ENODEV; }
+#endif
+
 #endif
diff --git a/arch/arm/mach-tegra/flowctrl.c b/arch/arm/mach-tegra/flowctrl.c
index a2250dd..b477ef3 100644
--- a/arch/arm/mach-tegra/flowctrl.c
+++ b/arch/arm/mach-tegra/flowctrl.c
@@ -25,15 +25,16 @@
 
 #include "flowctrl.h"
 #include "iomap.h"
+#include "fuse.h"
 
-u8 flowctrl_offset_halt_cpu[] = {
+static u8 flowctrl_offset_halt_cpu[] = {
 	FLOW_CTRL_HALT_CPU0_EVENTS,
 	FLOW_CTRL_HALT_CPU1_EVENTS,
 	FLOW_CTRL_HALT_CPU1_EVENTS + 8,
 	FLOW_CTRL_HALT_CPU1_EVENTS + 16,
 };
 
-u8 flowctrl_offset_cpu_csr[] = {
+static u8 flowctrl_offset_cpu_csr[] = {
 	FLOW_CTRL_CPU0_CSR,
 	FLOW_CTRL_CPU1_CSR,
 	FLOW_CTRL_CPU1_CSR + 8,
@@ -75,11 +76,26 @@
 	int i;
 
 	reg = flowctrl_read_cpu_csr(cpuid);
-	reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;	/* clear wfe bitmap */
-	reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;	/* clear wfi bitmap */
+	switch (tegra_chip_id) {
+	case TEGRA20:
+		/* clear wfe bitmap */
+		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
+		/* clear wfi bitmap */
+		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
+		/* pwr gating on wfe */
+		reg |= TEGRA20_FLOW_CTRL_CSR_WFE_CPU0 << cpuid;
+		break;
+	case TEGRA30:
+		/* clear wfe bitmap */
+		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
+		/* clear wfi bitmap */
+		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;
+		/* pwr gating on wfi */
+		reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid;
+		break;
+	}
 	reg |= FLOW_CTRL_CSR_INTR_FLAG;			/* clear intr flag */
 	reg |= FLOW_CTRL_CSR_EVENT_FLAG;		/* clear event flag */
-	reg |= TEGRA30_FLOW_CTRL_CSR_WFI_CPU0 << cpuid;	/* pwr gating on wfi */
 	reg |= FLOW_CTRL_CSR_ENABLE;			/* pwr gating */
 	flowctrl_write_cpu_csr(cpuid, reg);
 
@@ -99,8 +115,20 @@
 
 	/* Disable powergating via flow controller for CPU0 */
 	reg = flowctrl_read_cpu_csr(cpuid);
-	reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;	/* clear wfe bitmap */
-	reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;	/* clear wfi bitmap */
+	switch (tegra_chip_id) {
+	case TEGRA20:
+		/* clear wfe bitmap */
+		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP;
+		/* clear wfi bitmap */
+		reg &= ~TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP;
+		break;
+	case TEGRA30:
+		/* clear wfe bitmap */
+		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP;
+		/* clear wfi bitmap */
+		reg &= ~TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP;
+		break;
+	}
 	reg &= ~FLOW_CTRL_CSR_ENABLE;			/* clear enable */
 	reg |= FLOW_CTRL_CSR_INTR_FLAG;			/* clear intr */
 	reg |= FLOW_CTRL_CSR_EVENT_FLAG;		/* clear event */
diff --git a/arch/arm/mach-tegra/flowctrl.h b/arch/arm/mach-tegra/flowctrl.h
index 0798dec..67eab56 100644
--- a/arch/arm/mach-tegra/flowctrl.h
+++ b/arch/arm/mach-tegra/flowctrl.h
@@ -34,6 +34,10 @@
 #define FLOW_CTRL_HALT_CPU1_EVENTS	0x14
 #define FLOW_CTRL_CPU1_CSR		0x18
 
+#define TEGRA20_FLOW_CTRL_CSR_WFE_CPU0		(1 << 4)
+#define TEGRA20_FLOW_CTRL_CSR_WFE_BITMAP	(3 << 4)
+#define TEGRA20_FLOW_CTRL_CSR_WFI_BITMAP	0
+
 #define TEGRA30_FLOW_CTRL_CSR_WFI_CPU0		(1 << 8)
 #define TEGRA30_FLOW_CTRL_CSR_WFE_BITMAP	(0xF << 4)
 #define TEGRA30_FLOW_CTRL_CSR_WFI_BITMAP	(0xF << 8)
diff --git a/arch/arm/mach-tegra/fuse.c b/arch/arm/mach-tegra/fuse.c
index 8121742..f7db078 100644
--- a/arch/arm/mach-tegra/fuse.c
+++ b/arch/arm/mach-tegra/fuse.c
@@ -20,6 +20,7 @@
 #include <linux/kernel.h>
 #include <linux/io.h>
 #include <linux/export.h>
+#include <linux/tegra-soc.h>
 
 #include "fuse.h"
 #include "iomap.h"
@@ -105,6 +106,11 @@
 	tegra_core_process_id = (reg >> 12) & 3;
 }
 
+u32 tegra_read_chipid(void)
+{
+	return readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
+}
+
 void tegra_init_fuse(void)
 {
 	u32 id;
@@ -119,7 +125,7 @@
 	reg = tegra_apb_readl(TEGRA_APB_MISC_BASE + STRAP_OPT);
 	tegra_bct_strapping = (reg & RAM_ID_MASK) >> RAM_CODE_SHIFT;
 
-	id = readl_relaxed(IO_ADDRESS(TEGRA_APB_MISC_BASE) + 0x804);
+	id = tegra_read_chipid();
 	tegra_chip_id = (id >> 8) & 0xff;
 
 	switch (tegra_chip_id) {
diff --git a/arch/arm/mach-tegra/fuse.h b/arch/arm/mach-tegra/fuse.h
index ff1383d..da78434 100644
--- a/arch/arm/mach-tegra/fuse.h
+++ b/arch/arm/mach-tegra/fuse.h
@@ -37,6 +37,7 @@
 
 #define TEGRA20		0x20
 #define TEGRA30		0x30
+#define TEGRA114	0x35
 
 extern int tegra_sku_id;
 extern int tegra_cpu_process_id;
diff --git a/arch/arm/mach-tegra/headsmp.S b/arch/arm/mach-tegra/headsmp.S
index 4a317fa..b283481 100644
--- a/arch/arm/mach-tegra/headsmp.S
+++ b/arch/arm/mach-tegra/headsmp.S
@@ -1,22 +1,9 @@
 #include <linux/linkage.h>
 #include <linux/init.h>
 
-#include <asm/cache.h>
-#include <asm/asm-offsets.h>
-#include <asm/hardware/cache-l2x0.h>
-
-#include "flowctrl.h"
-#include "iomap.h"
-#include "reset.h"
 #include "sleep.h"
 
-#define APB_MISC_GP_HIDREV	0x804
-#define PMC_SCRATCH41	0x140
-
-#define RESET_DATA(x)	((TEGRA_RESET_##x)*4)
-
         .section ".text.head", "ax"
-	__CPUINIT
 
 /*
  * Tegra specific entry point for secondary CPUs.
@@ -61,7 +48,6 @@
         mov     pc, lr
 ENDPROC(v7_invalidate_l1)
 
-
 ENTRY(tegra_secondary_startup)
         bl      v7_invalidate_l1
 	/* Enable coresight */
@@ -69,210 +55,3 @@
 	mcr	p14, 0, r0, c7, c12, 6
         b       secondary_startup
 ENDPROC(tegra_secondary_startup)
-
-#ifdef CONFIG_PM_SLEEP
-/*
- *	tegra_resume
- *
- *	  CPU boot vector when restarting the a CPU following
- *	  an LP2 transition. Also branched to by LP0 and LP1 resume after
- *	  re-enabling sdram.
- */
-ENTRY(tegra_resume)
-	bl	v7_invalidate_l1
-	/* Enable coresight */
-	mov32	r0, 0xC5ACCE55
-	mcr	p14, 0, r0, c7, c12, 6
-
-	cpu_id	r0
-	cmp	r0, #0				@ CPU0?
-	bne	cpu_resume			@ no
-
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-	/* Are we on Tegra20? */
-	mov32	r6, TEGRA_APB_MISC_BASE
-	ldr	r0, [r6, #APB_MISC_GP_HIDREV]
-	and	r0, r0, #0xff00
-	cmp	r0, #(0x20 << 8)
-	beq	1f				@ Yes
-	/* Clear the flow controller flags for this CPU. */
-	mov32	r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR	@ CPU0 CSR
-	ldr	r1, [r2]
-	/* Clear event & intr flag */
-	orr	r1, r1, \
-		#FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
-	movw	r0, #0x0FFD	@ enable, cluster_switch, immed, & bitmaps
-	bic	r1, r1, r0
-	str	r1, [r2]
-1:
-#endif
-
-#ifdef CONFIG_HAVE_ARM_SCU
-	/* enable SCU */
-	mov32	r0, TEGRA_ARM_PERIF_BASE
-	ldr	r1, [r0]
-	orr	r1, r1, #1
-	str	r1, [r0]
-#endif
-
-	/* L2 cache resume & re-enable */
-	l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
-
-	b	cpu_resume
-ENDPROC(tegra_resume)
-#endif
-
-#ifdef CONFIG_CACHE_L2X0
-	.globl	l2x0_saved_regs_addr
-l2x0_saved_regs_addr:
-	.long	0
-#endif
-
-	.align L1_CACHE_SHIFT
-ENTRY(__tegra_cpu_reset_handler_start)
-
-/*
- * __tegra_cpu_reset_handler:
- *
- * Common handler for all CPU reset events.
- *
- * Register usage within the reset handler:
- *
- *      R7  = CPU present (to the OS) mask
- *      R8  = CPU in LP1 state mask
- *      R9  = CPU in LP2 state mask
- *      R10 = CPU number
- *      R11 = CPU mask
- *      R12 = pointer to reset handler data
- *
- * NOTE: This code is copied to IRAM. All code and data accesses
- *       must be position-independent.
- */
-
-	.align L1_CACHE_SHIFT
-ENTRY(__tegra_cpu_reset_handler)
-
-	cpsid	aif, 0x13			@ SVC mode, interrupts disabled
-	mrc	p15, 0, r10, c0, c0, 5		@ MPIDR
-	and	r10, r10, #0x3			@ R10 = CPU number
-	mov	r11, #1
-	mov	r11, r11, lsl r10  		@ R11 = CPU mask
-	adr	r12, __tegra_cpu_reset_handler_data
-
-#ifdef CONFIG_SMP
-	/* Does the OS know about this CPU? */
-	ldr	r7, [r12, #RESET_DATA(MASK_PRESENT)]
-	tst	r7, r11 			@ if !present
-	bleq	__die				@ CPU not present (to OS)
-#endif
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-	/* Are we on Tegra20? */
-	mov32	r6, TEGRA_APB_MISC_BASE
-	ldr	r0, [r6, #APB_MISC_GP_HIDREV]
-	and	r0, r0, #0xff00
-	cmp	r0, #(0x20 << 8)
-	bne	1f
-	/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
-	mov32	r6, TEGRA_PMC_BASE
-	mov	r0, #0
-	cmp	r10, #0
-	strne	r0, [r6, #PMC_SCRATCH41]
-1:
-#endif
-
-	/* Waking up from LP2? */
-	ldr	r9, [r12, #RESET_DATA(MASK_LP2)]
-	tst	r9, r11				@ if in_lp2
-	beq	__is_not_lp2
-	ldr	lr, [r12, #RESET_DATA(STARTUP_LP2)]
-	cmp	lr, #0
-	bleq	__die				@ no LP2 startup handler
-	bx	lr
-
-__is_not_lp2:
-
-#ifdef CONFIG_SMP
-	/*
-	 * Can only be secondary boot (initial or hotplug) but CPU 0
-	 * cannot be here.
-	 */
-	cmp	r10, #0
-	bleq	__die				@ CPU0 cannot be here
-	ldr	lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
-	cmp	lr, #0
-	bleq	__die				@ no secondary startup handler
-	bx	lr
-#endif
-
-/*
- * We don't know why the CPU reset. Just kill it.
- * The LR register will contain the address we died at + 4.
- */
-
-__die:
-	sub	lr, lr, #4
-	mov32	r7, TEGRA_PMC_BASE
-	str	lr, [r7, #PMC_SCRATCH41]
-
-	mov32	r7, TEGRA_CLK_RESET_BASE
-
-	/* Are we on Tegra20? */
-	mov32	r6, TEGRA_APB_MISC_BASE
-	ldr	r0, [r6, #APB_MISC_GP_HIDREV]
-	and	r0, r0, #0xff00
-	cmp	r0, #(0x20 << 8)
-	bne	1f
-
-#ifdef CONFIG_ARCH_TEGRA_2x_SOC
-	mov32	r0, 0x1111
-	mov	r1, r0, lsl r10
-	str	r1, [r7, #0x340]		@ CLK_RST_CPU_CMPLX_SET
-#endif
-1:
-#ifdef CONFIG_ARCH_TEGRA_3x_SOC
-	mov32	r6, TEGRA_FLOW_CTRL_BASE
-
-	cmp	r10, #0
-	moveq	r1, #FLOW_CTRL_HALT_CPU0_EVENTS
-	moveq	r2, #FLOW_CTRL_CPU0_CSR
-	movne	r1, r10, lsl #3
-	addne	r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
-	addne	r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
-
-	/* Clear CPU "event" and "interrupt" flags and power gate
-	   it when halting but not before it is in the "WFI" state. */
-	ldr	r0, [r6, +r2]
-	orr	r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
-	orr	r0, r0, #FLOW_CTRL_CSR_ENABLE
-	str	r0, [r6, +r2]
-
-	/* Unconditionally halt this CPU */
-	mov	r0, #FLOW_CTRL_WAITEVENT
-	str	r0, [r6, +r1]
-	ldr	r0, [r6, +r1]			@ memory barrier
-
-	dsb
-	isb
-	wfi					@ CPU should be power gated here
-
-	/* If the CPU didn't power gate above just kill it's clock. */
-
-	mov	r0, r11, lsl #8
-	str	r0, [r7, #348]			@ CLK_CPU_CMPLX_SET
-#endif
-
-	/* If the CPU still isn't dead, just spin here. */
-	b	.
-ENDPROC(__tegra_cpu_reset_handler)
-
-	.align L1_CACHE_SHIFT
-	.type	__tegra_cpu_reset_handler_data, %object
-	.globl	__tegra_cpu_reset_handler_data
-__tegra_cpu_reset_handler_data:
-	.rept	TEGRA_RESET_DATA_SIZE
-	.long	0
-	.endr
-	.align L1_CACHE_SHIFT
-
-ENTRY(__tegra_cpu_reset_handler_end)
diff --git a/arch/arm/mach-tegra/hotplug.c b/arch/arm/mach-tegra/hotplug.c
index dca5141..a599f6e 100644
--- a/arch/arm/mach-tegra/hotplug.c
+++ b/arch/arm/mach-tegra/hotplug.c
@@ -10,15 +10,26 @@
  */
 #include <linux/kernel.h>
 #include <linux/smp.h>
+#include <linux/clk/tegra.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
 
 #include "sleep.h"
-#include "tegra_cpu_car.h"
 
 static void (*tegra_hotplug_shutdown)(void);
 
+int tegra_cpu_kill(unsigned cpu)
+{
+	cpu = cpu_logical_map(cpu);
+
+	/* Clock gate the CPU */
+	tegra_wait_cpu_in_reset(cpu);
+	tegra_disable_cpu_clock(cpu);
+
+	return 1;
+}
+
 /*
  * platform-specific code to shutdown a CPU
  *
@@ -26,18 +37,12 @@
  */
 void __ref tegra_cpu_die(unsigned int cpu)
 {
-	cpu = cpu_logical_map(cpu);
-
-	/* Flush the L1 data cache. */
-	flush_cache_all();
+	/* Clean L1 data cache */
+	tegra_disable_clean_inv_dcache();
 
 	/* Shut down the current CPU. */
 	tegra_hotplug_shutdown();
 
-	/* Clock gate the CPU */
-	tegra_wait_cpu_in_reset(cpu);
-	tegra_disable_cpu_clock(cpu);
-
 	/* Should never return here. */
 	BUG();
 }
diff --git a/arch/arm/mach-tegra/include/mach/clk.h b/arch/arm/mach-tegra/include/mach/clk.h
deleted file mode 100644
index 95f3a54..0000000
--- a/arch/arm/mach-tegra/include/mach/clk.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * arch/arm/mach-tegra/include/mach/clk.h
- *
- * Copyright (C) 2010 Google, Inc.
- *
- * Author:
- *	Erik Gilling <konkers@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#ifndef __MACH_CLK_H
-#define __MACH_CLK_H
-
-struct clk;
-
-enum tegra_clk_ex_param {
-	TEGRA_CLK_VI_INP_SEL,
-	TEGRA_CLK_DTV_INVERT,
-	TEGRA_CLK_NAND_PAD_DIV2_ENB,
-	TEGRA_CLK_PLLD_CSI_OUT_ENB,
-	TEGRA_CLK_PLLD_DSI_OUT_ENB,
-	TEGRA_CLK_PLLD_MIPI_MUX_SEL,
-};
-
-void tegra_periph_reset_deassert(struct clk *c);
-void tegra_periph_reset_assert(struct clk *c);
-
-#ifndef CONFIG_COMMON_CLK
-unsigned long clk_get_rate_all_locked(struct clk *c);
-#endif
-
-void tegra2_sdmmc_tap_delay(struct clk *c, int delay);
-int tegra_clk_cfg_ex(struct clk *c, enum tegra_clk_ex_param p, u32 setting);
-
-#endif
diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
index db8be51..399fbca 100644
--- a/arch/arm/mach-tegra/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -240,15 +240,6 @@
 #define TEGRA_CSITE_BASE		0x70040000
 #define TEGRA_CSITE_SIZE		SZ_256K
 
-#define TEGRA_USB_BASE			0xC5000000
-#define TEGRA_USB_SIZE			SZ_16K
-
-#define TEGRA_USB2_BASE			0xC5004000
-#define TEGRA_USB2_SIZE			SZ_16K
-
-#define TEGRA_USB3_BASE			0xC5008000
-#define TEGRA_USB3_SIZE			SZ_16K
-
 #define TEGRA_SDMMC1_BASE		0xC8000000
 #define TEGRA_SDMMC1_SIZE		SZ_512
 
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index b7886f1..1952e82 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -22,8 +22,7 @@
 #include <linux/irq.h>
 #include <linux/io.h>
 #include <linux/of.h>
-
-#include <asm/hardware/gic.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include "board.h"
 #include "iomap.h"
@@ -45,6 +44,8 @@
 
 #define FIRST_LEGACY_IRQ 32
 
+#define SGI_MASK 0xFFFF
+
 static int num_ictlrs;
 
 static void __iomem *ictlr_reg_base[] = {
@@ -55,6 +56,19 @@
 	IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),
 };
 
+bool tegra_pending_sgi(void)
+{
+	u32 pending_set;
+	void __iomem *distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE);
+
+	pending_set = readl_relaxed(distbase + GIC_DIST_PENDING_SET);
+
+	if (pending_set & SGI_MASK)
+		return true;
+
+	return false;
+}
+
 static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
 {
 	void __iomem *base;
diff --git a/arch/arm/mach-tegra/irq.h b/arch/arm/mach-tegra/irq.h
new file mode 100644
index 0000000..5142649
--- /dev/null
+++ b/arch/arm/mach-tegra/irq.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEGRA_IRQ_H
+#define __TEGRA_IRQ_H
+
+bool tegra_pending_sgi(void);
+
+#endif
diff --git a/arch/arm/mach-tegra/pcie.c b/arch/arm/mach-tegra/pcie.c
index bffcd64..b60165f 100644
--- a/arch/arm/mach-tegra/pcie.c
+++ b/arch/arm/mach-tegra/pcie.c
@@ -33,11 +33,11 @@
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/export.h>
+#include <linux/clk/tegra.h>
 
 #include <asm/sizes.h>
 #include <asm/mach/pci.h>
 
-#include <mach/clk.h>
 #include <mach/powergate.h>
 
 #include "board.h"
diff --git a/arch/arm/mach-tegra/platsmp.c b/arch/arm/mach-tegra/platsmp.c
index 1b926df..2c6b3d5 100644
--- a/arch/arm/mach-tegra/platsmp.c
+++ b/arch/arm/mach-tegra/platsmp.c
@@ -18,25 +18,26 @@
 #include <linux/jiffies.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
+#include <linux/clk/tegra.h>
 
 #include <asm/cacheflush.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach-types.h>
 #include <asm/smp_scu.h>
+#include <asm/smp_plat.h>
 
 #include <mach/powergate.h>
 
 #include "fuse.h"
 #include "flowctrl.h"
 #include "reset.h"
-#include "tegra_cpu_car.h"
 
 #include "common.h"
 #include "iomap.h"
 
 extern void tegra_secondary_startup(void);
 
-static void __iomem *scu_base = IO_ADDRESS(TEGRA_ARM_PERIF_BASE);
+static cpumask_t tegra_cpu_init_mask;
 
 #define EVP_CPU_RESET_VECTOR \
 	(IO_ADDRESS(TEGRA_EXCEPTION_VECTORS_BASE) + 0x100)
@@ -50,6 +51,7 @@
 	 */
 	gic_secondary_init(0);
 
+	cpumask_set_cpu(cpu, &tegra_cpu_init_mask);
 }
 
 static int tegra20_power_up_cpu(unsigned int cpu)
@@ -72,14 +74,42 @@
 	if (pwrgateid < 0)
 		return pwrgateid;
 
-	/* If this is the first boot, toggle powergates directly. */
+	/*
+	 * The power up sequence of cold boot CPU and warm boot CPU
+	 * was different.
+	 *
+	 * For warm boot CPU that was resumed from CPU hotplug, the
+	 * power will be resumed automatically after un-halting the
+	 * flow controller of the warm boot CPU. We need to wait for
+	 * the confirmaiton that the CPU is powered then removing
+	 * the IO clamps.
+	 * For cold boot CPU, do not wait. After the cold boot CPU be
+	 * booted, it will run to tegra_secondary_init() and set
+	 * tegra_cpu_init_mask which influences what tegra30_power_up_cpu()
+	 * next time around.
+	 */
+	if (cpumask_test_cpu(cpu, &tegra_cpu_init_mask)) {
+		timeout = jiffies + msecs_to_jiffies(50);
+		do {
+			if (!tegra_powergate_is_powered(pwrgateid))
+				goto remove_clamps;
+			udelay(10);
+		} while (time_before(jiffies, timeout));
+	}
+
+	/*
+	 * The power status of the cold boot CPU is power gated as
+	 * default. To power up the cold boot CPU, the power should
+	 * be un-gated by un-toggling the power gate register
+	 * manually.
+	 */
 	if (!tegra_powergate_is_powered(pwrgateid)) {
 		ret = tegra_powergate_power_on(pwrgateid);
 		if (ret)
 			return ret;
 
 		/* Wait for the power to come up. */
-		timeout = jiffies + 10*HZ;
+		timeout = jiffies + msecs_to_jiffies(100);
 		while (tegra_powergate_is_powered(pwrgateid)) {
 			if (time_after(jiffies, timeout))
 				return -ETIMEDOUT;
@@ -87,6 +117,7 @@
 		}
 	}
 
+remove_clamps:
 	/* CPU partition is powered. Enable the CPU clock. */
 	tegra_enable_cpu_clock(cpu);
 	udelay(10);
@@ -105,6 +136,8 @@
 {
 	int status;
 
+	cpu = cpu_logical_map(cpu);
+
 	/*
 	 * Force the CPU into reset. The CPU must remain in reset when the
 	 * flow controller state is cleared (which will cause the flow
@@ -143,38 +176,21 @@
 	return status;
 }
 
-/*
- * Initialise the CPU possible map early - this describes the CPUs
- * which may be present or become present in the system.
- */
-static void __init tegra_smp_init_cpus(void)
-{
-	unsigned int i, ncores = scu_get_core_count(scu_base);
-
-	if (ncores > nr_cpu_ids) {
-		pr_warn("SMP: %u cores greater than maximum (%u), clipping\n",
-			ncores, nr_cpu_ids);
-		ncores = nr_cpu_ids;
-	}
-
-	for (i = 0; i < ncores; i++)
-		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
-}
-
 static void __init tegra_smp_prepare_cpus(unsigned int max_cpus)
 {
-	tegra_cpu_reset_handler_init();
-	scu_enable(scu_base);
+	/* Always mark the boot CPU (CPU0) as initialized. */
+	cpumask_set_cpu(0, &tegra_cpu_init_mask);
+
+	if (scu_a9_has_base())
+		scu_enable(IO_ADDRESS(scu_a9_get_base()));
 }
 
 struct smp_operations tegra_smp_ops __initdata = {
-	.smp_init_cpus		= tegra_smp_init_cpus,
 	.smp_prepare_cpus	= tegra_smp_prepare_cpus,
 	.smp_secondary_init	= tegra_secondary_init,
 	.smp_boot_secondary	= tegra_boot_secondary,
 #ifdef CONFIG_HOTPLUG_CPU
+	.cpu_kill		= tegra_cpu_kill,
 	.cpu_die		= tegra_cpu_die,
 	.cpu_disable		= tegra_cpu_disable,
 #endif
diff --git a/arch/arm/mach-tegra/pm.c b/arch/arm/mach-tegra/pm.c
index 1b11707..523604d 100644
--- a/arch/arm/mach-tegra/pm.c
+++ b/arch/arm/mach-tegra/pm.c
@@ -24,6 +24,7 @@
 #include <linux/cpu_pm.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/clk/tegra.h>
 
 #include <asm/smp_plat.h>
 #include <asm/cacheflush.h>
@@ -35,8 +36,8 @@
 #include "iomap.h"
 #include "reset.h"
 #include "flowctrl.h"
+#include "fuse.h"
 #include "sleep.h"
-#include "tegra_cpu_car.h"
 
 #define TEGRA_POWER_CPU_PWRREQ_OE	(1 << 16)  /* CPU pwr req enable */
 
@@ -148,7 +149,7 @@
 	save_cpu_arch_register();
 }
 
-void __cpuinit tegra_clear_cpu_in_lp2(int phy_cpu_id)
+void tegra_clear_cpu_in_lp2(int phy_cpu_id)
 {
 	u32 *cpu_in_lp2 = tegra_cpu_lp2_mask;
 
@@ -160,7 +161,7 @@
 	spin_unlock(&tegra_lp2_lock);
 }
 
-bool __cpuinit tegra_set_cpu_in_lp2(int phy_cpu_id)
+bool tegra_set_cpu_in_lp2(int phy_cpu_id)
 {
 	bool last_cpu = false;
 	cpumask_t *cpu_lp2_mask = tegra_cpu_lp2_mask;
@@ -173,6 +174,8 @@
 
 	if ((phy_cpu_id == 0) && cpumask_equal(cpu_lp2_mask, cpu_online_mask))
 		last_cpu = true;
+	else if (tegra_chip_id == TEGRA20 && phy_cpu_id == 1)
+		tegra20_cpu_set_resettable_soon();
 
 	spin_unlock(&tegra_lp2_lock);
 	return last_cpu;
diff --git a/arch/arm/mach-tegra/powergate.c b/arch/arm/mach-tegra/powergate.c
index 2cc1185..c6bc8f8 100644
--- a/arch/arm/mach-tegra/powergate.c
+++ b/arch/arm/mach-tegra/powergate.c
@@ -26,8 +26,8 @@
 #include <linux/io.h>
 #include <linux/seq_file.h>
 #include <linux/spinlock.h>
+#include <linux/clk/tegra.h>
 
-#include <mach/clk.h>
 #include <mach/powergate.h>
 
 #include "fuse.h"
diff --git a/arch/arm/mach-tegra/reset-handler.S b/arch/arm/mach-tegra/reset-handler.S
new file mode 100644
index 0000000..54382ce
--- /dev/null
+++ b/arch/arm/mach-tegra/reset-handler.S
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2012, NVIDIA Corporation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/linkage.h>
+#include <linux/init.h>
+
+#include <asm/cache.h>
+#include <asm/asm-offsets.h>
+#include <asm/hardware/cache-l2x0.h>
+
+#include "flowctrl.h"
+#include "iomap.h"
+#include "reset.h"
+#include "sleep.h"
+
+#define APB_MISC_GP_HIDREV	0x804
+#define PMC_SCRATCH41	0x140
+
+#define RESET_DATA(x)	((TEGRA_RESET_##x)*4)
+
+#ifdef CONFIG_PM_SLEEP
+/*
+ *	tegra_resume
+ *
+ *	  CPU boot vector when restarting the a CPU following
+ *	  an LP2 transition. Also branched to by LP0 and LP1 resume after
+ *	  re-enabling sdram.
+ */
+ENTRY(tegra_resume)
+	bl	v7_invalidate_l1
+	/* Enable coresight */
+	mov32	r0, 0xC5ACCE55
+	mcr	p14, 0, r0, c7, c12, 6
+
+	cpu_id	r0
+	cmp	r0, #0				@ CPU0?
+	bne	cpu_resume			@ no
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+	/* Are we on Tegra20? */
+	mov32	r6, TEGRA_APB_MISC_BASE
+	ldr	r0, [r6, #APB_MISC_GP_HIDREV]
+	and	r0, r0, #0xff00
+	cmp	r0, #(0x20 << 8)
+	beq	1f				@ Yes
+	/* Clear the flow controller flags for this CPU. */
+	mov32	r2, TEGRA_FLOW_CTRL_BASE + FLOW_CTRL_CPU0_CSR	@ CPU0 CSR
+	ldr	r1, [r2]
+	/* Clear event & intr flag */
+	orr	r1, r1, \
+		#FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
+	movw	r0, #0x0FFD	@ enable, cluster_switch, immed, & bitmaps
+	bic	r1, r1, r0
+	str	r1, [r2]
+1:
+#endif
+
+#ifdef CONFIG_HAVE_ARM_SCU
+	/* enable SCU */
+	mov32	r0, TEGRA_ARM_PERIF_BASE
+	ldr	r1, [r0]
+	orr	r1, r1, #1
+	str	r1, [r0]
+#endif
+
+	/* L2 cache resume & re-enable */
+	l2_cache_resume r0, r1, r2, l2x0_saved_regs_addr
+
+	b	cpu_resume
+ENDPROC(tegra_resume)
+#endif
+
+#ifdef CONFIG_CACHE_L2X0
+	.globl	l2x0_saved_regs_addr
+l2x0_saved_regs_addr:
+	.long	0
+#endif
+
+	.align L1_CACHE_SHIFT
+ENTRY(__tegra_cpu_reset_handler_start)
+
+/*
+ * __tegra_cpu_reset_handler:
+ *
+ * Common handler for all CPU reset events.
+ *
+ * Register usage within the reset handler:
+ *
+ *      R7  = CPU present (to the OS) mask
+ *      R8  = CPU in LP1 state mask
+ *      R9  = CPU in LP2 state mask
+ *      R10 = CPU number
+ *      R11 = CPU mask
+ *      R12 = pointer to reset handler data
+ *
+ * NOTE: This code is copied to IRAM. All code and data accesses
+ *       must be position-independent.
+ */
+
+	.align L1_CACHE_SHIFT
+ENTRY(__tegra_cpu_reset_handler)
+
+	cpsid	aif, 0x13			@ SVC mode, interrupts disabled
+	mrc	p15, 0, r10, c0, c0, 5		@ MPIDR
+	and	r10, r10, #0x3			@ R10 = CPU number
+	mov	r11, #1
+	mov	r11, r11, lsl r10  		@ R11 = CPU mask
+	adr	r12, __tegra_cpu_reset_handler_data
+
+#ifdef CONFIG_SMP
+	/* Does the OS know about this CPU? */
+	ldr	r7, [r12, #RESET_DATA(MASK_PRESENT)]
+	tst	r7, r11 			@ if !present
+	bleq	__die				@ CPU not present (to OS)
+#endif
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+	/* Are we on Tegra20? */
+	mov32	r6, TEGRA_APB_MISC_BASE
+	ldr	r0, [r6, #APB_MISC_GP_HIDREV]
+	and	r0, r0, #0xff00
+	cmp	r0, #(0x20 << 8)
+	bne	1f
+	/* If not CPU0, don't let CPU0 reset CPU1 now that CPU1 is coming up. */
+	mov32	r6, TEGRA_PMC_BASE
+	mov	r0, #0
+	cmp	r10, #0
+	strne	r0, [r6, #PMC_SCRATCH41]
+1:
+#endif
+
+	/* Waking up from LP2? */
+	ldr	r9, [r12, #RESET_DATA(MASK_LP2)]
+	tst	r9, r11				@ if in_lp2
+	beq	__is_not_lp2
+	ldr	lr, [r12, #RESET_DATA(STARTUP_LP2)]
+	cmp	lr, #0
+	bleq	__die				@ no LP2 startup handler
+	bx	lr
+
+__is_not_lp2:
+
+#ifdef CONFIG_SMP
+	/*
+	 * Can only be secondary boot (initial or hotplug) but CPU 0
+	 * cannot be here.
+	 */
+	cmp	r10, #0
+	bleq	__die				@ CPU0 cannot be here
+	ldr	lr, [r12, #RESET_DATA(STARTUP_SECONDARY)]
+	cmp	lr, #0
+	bleq	__die				@ no secondary startup handler
+	bx	lr
+#endif
+
+/*
+ * We don't know why the CPU reset. Just kill it.
+ * The LR register will contain the address we died at + 4.
+ */
+
+__die:
+	sub	lr, lr, #4
+	mov32	r7, TEGRA_PMC_BASE
+	str	lr, [r7, #PMC_SCRATCH41]
+
+	mov32	r7, TEGRA_CLK_RESET_BASE
+
+	/* Are we on Tegra20? */
+	mov32	r6, TEGRA_APB_MISC_BASE
+	ldr	r0, [r6, #APB_MISC_GP_HIDREV]
+	and	r0, r0, #0xff00
+	cmp	r0, #(0x20 << 8)
+	bne	1f
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+	mov32	r0, 0x1111
+	mov	r1, r0, lsl r10
+	str	r1, [r7, #0x340]		@ CLK_RST_CPU_CMPLX_SET
+#endif
+1:
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+	mov32	r6, TEGRA_FLOW_CTRL_BASE
+
+	cmp	r10, #0
+	moveq	r1, #FLOW_CTRL_HALT_CPU0_EVENTS
+	moveq	r2, #FLOW_CTRL_CPU0_CSR
+	movne	r1, r10, lsl #3
+	addne	r2, r1, #(FLOW_CTRL_CPU1_CSR-8)
+	addne	r1, r1, #(FLOW_CTRL_HALT_CPU1_EVENTS-8)
+
+	/* Clear CPU "event" and "interrupt" flags and power gate
+	   it when halting but not before it is in the "WFI" state. */
+	ldr	r0, [r6, +r2]
+	orr	r0, r0, #FLOW_CTRL_CSR_INTR_FLAG | FLOW_CTRL_CSR_EVENT_FLAG
+	orr	r0, r0, #FLOW_CTRL_CSR_ENABLE
+	str	r0, [r6, +r2]
+
+	/* Unconditionally halt this CPU */
+	mov	r0, #FLOW_CTRL_WAITEVENT
+	str	r0, [r6, +r1]
+	ldr	r0, [r6, +r1]			@ memory barrier
+
+	dsb
+	isb
+	wfi					@ CPU should be power gated here
+
+	/* If the CPU didn't power gate above just kill it's clock. */
+
+	mov	r0, r11, lsl #8
+	str	r0, [r7, #348]			@ CLK_CPU_CMPLX_SET
+#endif
+
+	/* If the CPU still isn't dead, just spin here. */
+	b	.
+ENDPROC(__tegra_cpu_reset_handler)
+
+	.align L1_CACHE_SHIFT
+	.type	__tegra_cpu_reset_handler_data, %object
+	.globl	__tegra_cpu_reset_handler_data
+__tegra_cpu_reset_handler_data:
+	.rept	TEGRA_RESET_DATA_SIZE
+	.long	0
+	.endr
+	.align L1_CACHE_SHIFT
+
+ENTRY(__tegra_cpu_reset_handler_end)
diff --git a/arch/arm/mach-tegra/reset.c b/arch/arm/mach-tegra/reset.c
index 3fd89ec..1ac434e 100644
--- a/arch/arm/mach-tegra/reset.c
+++ b/arch/arm/mach-tegra/reset.c
@@ -75,7 +75,7 @@
 
 #ifdef CONFIG_SMP
 	__tegra_cpu_reset_handler_data[TEGRA_RESET_MASK_PRESENT] =
-		*((u32 *)cpu_present_mask);
+		*((u32 *)cpu_possible_mask);
 	__tegra_cpu_reset_handler_data[TEGRA_RESET_STARTUP_SECONDARY] =
 		virt_to_phys((void *)tegra_secondary_startup);
 #endif
diff --git a/arch/arm/mach-tegra/sleep-tegra20.S b/arch/arm/mach-tegra/sleep-tegra20.S
index 72ce709..9f6bfaf 100644
--- a/arch/arm/mach-tegra/sleep-tegra20.S
+++ b/arch/arm/mach-tegra/sleep-tegra20.S
@@ -21,6 +21,8 @@
 #include <linux/linkage.h>
 
 #include <asm/assembler.h>
+#include <asm/proc-fns.h>
+#include <asm/cp15.h>
 
 #include "sleep.h"
 #include "flowctrl.h"
@@ -33,9 +35,6 @@
  * should never return
  */
 ENTRY(tegra20_hotplug_shutdown)
-	/* Turn off SMP coherency */
-	exit_smp r4, r5
-
 	/* Put this CPU down */
 	cpu_id	r0
 	bl	tegra20_cpu_shutdown
@@ -58,6 +57,9 @@
 ENTRY(tegra20_cpu_shutdown)
 	cmp	r0, #0
 	moveq	pc, lr			@ must not be called for CPU 0
+	mov32	r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
+	mov	r12, #CPU_RESETTABLE
+	str	r12, [r1]
 
 	cpu_to_halt_reg r1, r0
 	ldr	r3, =TEGRA_FLOW_CTRL_VIRT
@@ -78,3 +80,198 @@
 	mov	pc, lr
 ENDPROC(tegra20_cpu_shutdown)
 #endif
+
+#ifdef CONFIG_PM_SLEEP
+/*
+ * tegra_pen_lock
+ *
+ * spinlock implementation with no atomic test-and-set and no coherence
+ * using Peterson's algorithm on strongly-ordered registers
+ * used to synchronize a cpu waking up from wfi with entering lp2 on idle
+ *
+ * The reference link of Peterson's algorithm:
+ * http://en.wikipedia.org/wiki/Peterson's_algorithm
+ *
+ * SCRATCH37 = r1 = !turn (inverted from Peterson's algorithm)
+ * on cpu 0:
+ * r2 = flag[0] (in SCRATCH38)
+ * r3 = flag[1] (in SCRATCH39)
+ * on cpu1:
+ * r2 = flag[1] (in SCRATCH39)
+ * r3 = flag[0] (in SCRATCH38)
+ *
+ * must be called with MMU on
+ * corrupts r0-r3, r12
+ */
+ENTRY(tegra_pen_lock)
+	mov32	r3, TEGRA_PMC_VIRT
+	cpu_id	r0
+	add	r1, r3, #PMC_SCRATCH37
+	cmp	r0, #0
+	addeq	r2, r3, #PMC_SCRATCH38
+	addeq	r3, r3, #PMC_SCRATCH39
+	addne	r2, r3, #PMC_SCRATCH39
+	addne	r3, r3, #PMC_SCRATCH38
+
+	mov	r12, #1
+	str	r12, [r2]		@ flag[cpu] = 1
+	dsb
+	str	r12, [r1]		@ !turn = cpu
+1:	dsb
+	ldr	r12, [r3]
+	cmp	r12, #1			@ flag[!cpu] == 1?
+	ldreq	r12, [r1]
+	cmpeq	r12, r0			@ !turn == cpu?
+	beq	1b			@ while !turn == cpu && flag[!cpu] == 1
+
+	mov	pc, lr			@ locked
+ENDPROC(tegra_pen_lock)
+
+ENTRY(tegra_pen_unlock)
+	dsb
+	mov32	r3, TEGRA_PMC_VIRT
+	cpu_id	r0
+	cmp	r0, #0
+	addeq	r2, r3, #PMC_SCRATCH38
+	addne	r2, r3, #PMC_SCRATCH39
+	mov	r12, #0
+	str	r12, [r2]
+	mov     pc, lr
+ENDPROC(tegra_pen_unlock)
+
+/*
+ * tegra20_cpu_clear_resettable(void)
+ *
+ * Called to clear the "resettable soon" flag in PMC_SCRATCH41 when
+ * it is expected that the secondary CPU will be idle soon.
+ */
+ENTRY(tegra20_cpu_clear_resettable)
+	mov32	r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
+	mov	r12, #CPU_NOT_RESETTABLE
+	str	r12, [r1]
+	mov	pc, lr
+ENDPROC(tegra20_cpu_clear_resettable)
+
+/*
+ * tegra20_cpu_set_resettable_soon(void)
+ *
+ * Called to set the "resettable soon" flag in PMC_SCRATCH41 when
+ * it is expected that the secondary CPU will be idle soon.
+ */
+ENTRY(tegra20_cpu_set_resettable_soon)
+	mov32	r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
+	mov	r12, #CPU_RESETTABLE_SOON
+	str	r12, [r1]
+	mov	pc, lr
+ENDPROC(tegra20_cpu_set_resettable_soon)
+
+/*
+ * tegra20_cpu_is_resettable_soon(void)
+ *
+ * Returns true if the "resettable soon" flag in PMC_SCRATCH41 has been
+ * set because it is expected that the secondary CPU will be idle soon.
+ */
+ENTRY(tegra20_cpu_is_resettable_soon)
+	mov32	r1, TEGRA_PMC_VIRT + PMC_SCRATCH41
+	ldr	r12, [r1]
+	cmp	r12, #CPU_RESETTABLE_SOON
+	moveq	r0, #1
+	movne	r0, #0
+	mov	pc, lr
+ENDPROC(tegra20_cpu_is_resettable_soon)
+
+/*
+ * tegra20_sleep_cpu_secondary_finish(unsigned long v2p)
+ *
+ * Enters WFI on secondary CPU by exiting coherency.
+ */
+ENTRY(tegra20_sleep_cpu_secondary_finish)
+	stmfd	sp!, {r4-r11, lr}
+
+	mrc	p15, 0, r11, c1, c0, 1  @ save actlr before exiting coherency
+
+	/* Flush and disable the L1 data cache */
+	bl	tegra_disable_clean_inv_dcache
+
+	mov32	r0, TEGRA_PMC_VIRT + PMC_SCRATCH41
+	mov	r3, #CPU_RESETTABLE
+	str	r3, [r0]
+
+	bl	cpu_do_idle
+
+	/*
+	 * cpu may be reset while in wfi, which will return through
+	 * tegra_resume to cpu_resume
+	 * or interrupt may wake wfi, which will return here
+	 * cpu state is unchanged - MMU is on, cache is on, coherency
+	 * is off, and the data cache is off
+	 *
+	 * r11 contains the original actlr
+	 */
+
+	bl	tegra_pen_lock
+
+	mov32	r3, TEGRA_PMC_VIRT
+	add	r0, r3, #PMC_SCRATCH41
+	mov	r3, #CPU_NOT_RESETTABLE
+	str	r3, [r0]
+
+	bl	tegra_pen_unlock
+
+	/* Re-enable the data cache */
+	mrc	p15, 0, r10, c1, c0, 0
+	orr	r10, r10, #CR_C
+	mcr	p15, 0, r10, c1, c0, 0
+	isb
+
+	mcr	p15, 0, r11, c1, c0, 1	@ reenable coherency
+
+	/* Invalidate the TLBs & BTAC */
+	mov	r1, #0
+	mcr	p15, 0, r1, c8, c3, 0	@ invalidate shared TLBs
+	mcr	p15, 0, r1, c7, c1, 6	@ invalidate shared BTAC
+	dsb
+	isb
+
+	/* the cpu was running with coherency disabled,
+	 * caches may be out of date */
+	bl	v7_flush_kern_cache_louis
+
+	ldmfd	sp!, {r4 - r11, pc}
+ENDPROC(tegra20_sleep_cpu_secondary_finish)
+
+/*
+ * tegra20_tear_down_cpu
+ *
+ * Switches the CPU cluster to PLL-P and enters sleep.
+ */
+ENTRY(tegra20_tear_down_cpu)
+	bl	tegra_switch_cpu_to_pllp
+	b	tegra20_enter_sleep
+ENDPROC(tegra20_tear_down_cpu)
+
+/*
+ * tegra20_enter_sleep
+ *
+ * uses flow controller to enter sleep state
+ * executes from IRAM with SDRAM in selfrefresh when target state is LP0 or LP1
+ * executes from SDRAM with target state is LP2
+ */
+tegra20_enter_sleep:
+	mov32   r6, TEGRA_FLOW_CTRL_BASE
+
+	mov     r0, #FLOW_CTRL_WAIT_FOR_INTERRUPT
+	orr	r0, r0, #FLOW_CTRL_HALT_CPU_IRQ | FLOW_CTRL_HALT_CPU_FIQ
+	cpu_id	r1
+	cpu_to_halt_reg r1, r1
+	str	r0, [r6, r1]
+	dsb
+	ldr	r0, [r6, r1] /* memory barrier */
+
+halted:
+	dsb
+	wfe	/* CPU should be power gated here */
+	isb
+	b	halted
+
+#endif
diff --git a/arch/arm/mach-tegra/sleep-tegra30.S b/arch/arm/mach-tegra/sleep-tegra30.S
index 562a8e7..63a15bd 100644
--- a/arch/arm/mach-tegra/sleep-tegra30.S
+++ b/arch/arm/mach-tegra/sleep-tegra30.S
@@ -32,9 +32,6 @@
  * Should never return.
  */
 ENTRY(tegra30_hotplug_shutdown)
-	/* Turn off SMP coherency */
-	exit_smp r4, r5
-
 	/* Powergate this CPU */
 	mov	r0, #TEGRA30_POWER_HOTPLUG_SHUTDOWN
 	bl	tegra30_cpu_shutdown
diff --git a/arch/arm/mach-tegra/sleep.S b/arch/arm/mach-tegra/sleep.S
index 26afa7c..364d845 100644
--- a/arch/arm/mach-tegra/sleep.S
+++ b/arch/arm/mach-tegra/sleep.S
@@ -34,7 +34,10 @@
 #include "flowctrl.h"
 #include "sleep.h"
 
-#ifdef CONFIG_PM_SLEEP
+#define CLK_RESET_CCLK_BURST	0x20
+#define CLK_RESET_CCLK_DIVIDER  0x24
+
+#if defined(CONFIG_HOTPLUG_CPU) || defined(CONFIG_PM_SLEEP)
 /*
  * tegra_disable_clean_inv_dcache
  *
@@ -60,7 +63,9 @@
 
 	ldmfd	sp!, {r0, r4-r5, r7, r9-r11, pc}
 ENDPROC(tegra_disable_clean_inv_dcache)
+#endif
 
+#ifdef CONFIG_PM_SLEEP
 /*
  * tegra_sleep_cpu_finish(unsigned long v2p)
  *
@@ -108,4 +113,20 @@
 	mov	pc, r0
 ENDPROC(tegra_shut_off_mmu)
 	.popsection
+
+/*
+ * tegra_switch_cpu_to_pllp
+ *
+ * In LP2 the normal cpu clock pllx will be turned off. Switch the CPU to pllp
+ */
+ENTRY(tegra_switch_cpu_to_pllp)
+	/* in LP2 idle (SDRAM active), set the CPU burst policy to PLLP */
+	mov32	r5, TEGRA_CLK_RESET_BASE
+	mov	r0, #(2 << 28)			@ burst policy = run mode
+	orr	r0, r0, #(4 << 4)		@ use PLLP in run mode burst
+	str	r0, [r5, #CLK_RESET_CCLK_BURST]
+	mov	r0, #0
+	str	r0, [r5, #CLK_RESET_CCLK_DIVIDER]
+	mov	pc, lr
+ENDPROC(tegra_switch_cpu_to_pllp)
 #endif
diff --git a/arch/arm/mach-tegra/sleep.h b/arch/arm/mach-tegra/sleep.h
index 9821ee7..4ffae54 100644
--- a/arch/arm/mach-tegra/sleep.h
+++ b/arch/arm/mach-tegra/sleep.h
@@ -25,6 +25,19 @@
 					+ IO_PPSB_VIRT)
 #define TEGRA_CLK_RESET_VIRT (TEGRA_CLK_RESET_BASE - IO_PPSB_PHYS \
 					+ IO_PPSB_VIRT)
+#define TEGRA_PMC_VIRT	(TEGRA_PMC_BASE - IO_APB_PHYS + IO_APB_VIRT)
+
+/* PMC_SCRATCH37-39 and 41 are used for tegra_pen_lock and idle */
+#define PMC_SCRATCH37	0x130
+#define PMC_SCRATCH38	0x134
+#define PMC_SCRATCH39	0x138
+#define PMC_SCRATCH41	0x140
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+#define CPU_RESETTABLE		2
+#define CPU_RESETTABLE_SOON	1
+#define CPU_NOT_RESETTABLE	0
+#endif
 
 #ifdef __ASSEMBLY__
 /* returns the offset of the flow controller halt register for a cpu */
@@ -104,8 +117,11 @@
 .endm
 #endif /* CONFIG_CACHE_L2X0 */
 #else
+void tegra_pen_lock(void);
+void tegra_pen_unlock(void);
 void tegra_resume(void);
 int tegra_sleep_cpu_finish(unsigned long);
+void tegra_disable_clean_inv_dcache(void);
 
 #ifdef CONFIG_HOTPLUG_CPU
 void tegra20_hotplug_init(void);
@@ -115,6 +131,17 @@
 static inline void tegra30_hotplug_init(void) {}
 #endif
 
+void tegra20_cpu_shutdown(int cpu);
+int tegra20_cpu_is_resettable_soon(void);
+void tegra20_cpu_clear_resettable(void);
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+void tegra20_cpu_set_resettable_soon(void);
+#else
+static inline void tegra20_cpu_set_resettable_soon(void) {}
+#endif
+
+int tegra20_sleep_cpu_secondary_finish(unsigned long);
+void tegra20_tear_down_cpu(void);
 int tegra30_sleep_cpu_secondary_finish(unsigned long);
 void tegra30_tear_down_cpu(void);
 
diff --git a/arch/arm/mach-tegra/tegra20_clocks.c b/arch/arm/mach-tegra/tegra20_clocks.c
deleted file mode 100644
index 4eb6bc8..0000000
--- a/arch/arm/mach-tegra/tegra20_clocks.c
+++ /dev/null
@@ -1,1623 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra20_clocks.c
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2010-2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clkdev.h>
-#include <linux/clk.h>
-
-#include "clock.h"
-#include "fuse.h"
-#include "iomap.h"
-#include "tegra2_emc.h"
-#include "tegra_cpu_car.h"
-
-#define RST_DEVICES			0x004
-#define RST_DEVICES_SET			0x300
-#define RST_DEVICES_CLR			0x304
-#define RST_DEVICES_NUM			3
-
-#define CLK_OUT_ENB			0x010
-#define CLK_OUT_ENB_SET			0x320
-#define CLK_OUT_ENB_CLR			0x324
-#define CLK_OUT_ENB_NUM			3
-
-#define CLK_MASK_ARM			0x44
-#define MISC_CLK_ENB			0x48
-
-#define OSC_CTRL			0x50
-#define OSC_CTRL_OSC_FREQ_MASK		(3<<30)
-#define OSC_CTRL_OSC_FREQ_13MHZ		(0<<30)
-#define OSC_CTRL_OSC_FREQ_19_2MHZ	(1<<30)
-#define OSC_CTRL_OSC_FREQ_12MHZ		(2<<30)
-#define OSC_CTRL_OSC_FREQ_26MHZ		(3<<30)
-#define OSC_CTRL_MASK			(0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
-
-#define OSC_FREQ_DET			0x58
-#define OSC_FREQ_DET_TRIG		(1<<31)
-
-#define OSC_FREQ_DET_STATUS		0x5C
-#define OSC_FREQ_DET_BUSY		(1<<31)
-#define OSC_FREQ_DET_CNT_MASK		0xFFFF
-
-#define PERIPH_CLK_SOURCE_I2S1		0x100
-#define PERIPH_CLK_SOURCE_EMC		0x19c
-#define PERIPH_CLK_SOURCE_OSC		0x1fc
-#define PERIPH_CLK_SOURCE_NUM \
-	((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
-
-#define PERIPH_CLK_SOURCE_MASK		(3<<30)
-#define PERIPH_CLK_SOURCE_SHIFT		30
-#define PERIPH_CLK_SOURCE_PWM_MASK	(7<<28)
-#define PERIPH_CLK_SOURCE_PWM_SHIFT	28
-#define PERIPH_CLK_SOURCE_ENABLE	(1<<28)
-#define PERIPH_CLK_SOURCE_DIVU71_MASK	0xFF
-#define PERIPH_CLK_SOURCE_DIVU16_MASK	0xFFFF
-#define PERIPH_CLK_SOURCE_DIV_SHIFT	0
-
-#define SDMMC_CLK_INT_FB_SEL		(1 << 23)
-#define SDMMC_CLK_INT_FB_DLY_SHIFT	16
-#define SDMMC_CLK_INT_FB_DLY_MASK	(0xF << SDMMC_CLK_INT_FB_DLY_SHIFT)
-
-#define PLL_BASE			0x0
-#define PLL_BASE_BYPASS			(1<<31)
-#define PLL_BASE_ENABLE			(1<<30)
-#define PLL_BASE_REF_ENABLE		(1<<29)
-#define PLL_BASE_OVERRIDE		(1<<28)
-#define PLL_BASE_DIVP_MASK		(0x7<<20)
-#define PLL_BASE_DIVP_SHIFT		20
-#define PLL_BASE_DIVN_MASK		(0x3FF<<8)
-#define PLL_BASE_DIVN_SHIFT		8
-#define PLL_BASE_DIVM_MASK		(0x1F)
-#define PLL_BASE_DIVM_SHIFT		0
-
-#define PLL_OUT_RATIO_MASK		(0xFF<<8)
-#define PLL_OUT_RATIO_SHIFT		8
-#define PLL_OUT_OVERRIDE		(1<<2)
-#define PLL_OUT_CLKEN			(1<<1)
-#define PLL_OUT_RESET_DISABLE		(1<<0)
-
-#define PLL_MISC(c) (((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
-
-#define PLL_MISC_DCCON_SHIFT		20
-#define PLL_MISC_CPCON_SHIFT		8
-#define PLL_MISC_CPCON_MASK		(0xF<<PLL_MISC_CPCON_SHIFT)
-#define PLL_MISC_LFCON_SHIFT		4
-#define PLL_MISC_LFCON_MASK		(0xF<<PLL_MISC_LFCON_SHIFT)
-#define PLL_MISC_VCOCON_SHIFT		0
-#define PLL_MISC_VCOCON_MASK		(0xF<<PLL_MISC_VCOCON_SHIFT)
-
-#define PLLU_BASE_POST_DIV		(1<<20)
-
-#define PLLD_MISC_CLKENABLE		(1<<30)
-#define PLLD_MISC_DIV_RST		(1<<23)
-#define PLLD_MISC_DCCON_SHIFT		12
-
-#define PLLE_MISC_READY			(1 << 15)
-
-#define PERIPH_CLK_TO_ENB_REG(c)	((c->u.periph.clk_num / 32) * 4)
-#define PERIPH_CLK_TO_ENB_SET_REG(c)	((c->u.periph.clk_num / 32) * 8)
-#define PERIPH_CLK_TO_ENB_BIT(c)	(1 << (c->u.periph.clk_num % 32))
-
-#define SUPER_CLK_MUX			0x00
-#define SUPER_STATE_SHIFT		28
-#define SUPER_STATE_MASK		(0xF << SUPER_STATE_SHIFT)
-#define SUPER_STATE_STANDBY		(0x0 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_IDLE		(0x1 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_RUN			(0x2 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_IRQ			(0x3 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_FIQ			(0x4 << SUPER_STATE_SHIFT)
-#define SUPER_SOURCE_MASK		0xF
-#define	SUPER_FIQ_SOURCE_SHIFT		12
-#define	SUPER_IRQ_SOURCE_SHIFT		8
-#define	SUPER_RUN_SOURCE_SHIFT		4
-#define	SUPER_IDLE_SOURCE_SHIFT		0
-
-#define SUPER_CLK_DIVIDER		0x04
-
-#define BUS_CLK_DISABLE			(1<<3)
-#define BUS_CLK_DIV_MASK		0x3
-
-#define PMC_CTRL			0x0
- #define PMC_CTRL_BLINK_ENB		(1 << 7)
-
-#define PMC_DPD_PADS_ORIDE		0x1c
- #define PMC_DPD_PADS_ORIDE_BLINK_ENB	(1 << 20)
-
-#define PMC_BLINK_TIMER_DATA_ON_SHIFT	0
-#define PMC_BLINK_TIMER_DATA_ON_MASK	0x7fff
-#define PMC_BLINK_TIMER_ENB		(1 << 15)
-#define PMC_BLINK_TIMER_DATA_OFF_SHIFT	16
-#define PMC_BLINK_TIMER_DATA_OFF_MASK	0xffff
-
-/* Tegra CPU clock and reset control regs */
-#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX		0x4c
-#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET	0x340
-#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR	0x344
-
-#define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
-#define CPU_RESET(cpu)	(0x1111ul << (cpu))
-
-static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
-static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
-
-/*
- * Some clocks share a register with other clocks.  Any clock op that
- * non-atomically modifies a register used by another clock must lock
- * clock_register_lock first.
- */
-static DEFINE_SPINLOCK(clock_register_lock);
-
-/*
- * Some peripheral clocks share an enable bit, so refcount the enable bits
- * in registers CLK_ENABLE_L, CLK_ENABLE_H, and CLK_ENABLE_U
- */
-static int tegra_periph_clk_enable_refcount[3 * 32];
-
-#define clk_writel(value, reg) \
-	__raw_writel(value, reg_clk_base + (reg))
-#define clk_readl(reg) \
-	__raw_readl(reg_clk_base + (reg))
-#define pmc_writel(value, reg) \
-	__raw_writel(value, reg_pmc_base + (reg))
-#define pmc_readl(reg) \
-	__raw_readl(reg_pmc_base + (reg))
-
-static unsigned long clk_measure_input_freq(void)
-{
-	u32 clock_autodetect;
-	clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
-	do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
-	clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
-	if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
-		return 12000000;
-	} else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
-		return 13000000;
-	} else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
-		return 19200000;
-	} else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
-		return 26000000;
-	} else {
-		pr_err("%s: Unexpected clock autodetect value %d",
-						__func__, clock_autodetect);
-		BUG();
-		return 0;
-	}
-}
-
-static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate)
-{
-	s64 divider_u71 = parent_rate * 2;
-	divider_u71 += rate - 1;
-	do_div(divider_u71, rate);
-
-	if (divider_u71 - 2 < 0)
-		return 0;
-
-	if (divider_u71 - 2 > 255)
-		return -EINVAL;
-
-	return divider_u71 - 2;
-}
-
-static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
-{
-	s64 divider_u16;
-
-	divider_u16 = parent_rate;
-	divider_u16 += rate - 1;
-	do_div(divider_u16, rate);
-
-	if (divider_u16 - 1 < 0)
-		return 0;
-
-	if (divider_u16 - 1 > 0xFFFF)
-		return -EINVAL;
-
-	return divider_u16 - 1;
-}
-
-static unsigned long tegra_clk_fixed_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	return to_clk_tegra(hw)->fixed_rate;
-}
-
-struct clk_ops tegra_clk_32k_ops = {
-	.recalc_rate = tegra_clk_fixed_recalc_rate,
-};
-
-/* clk_m functions */
-static unsigned long tegra20_clk_m_recalc_rate(struct clk_hw *hw,
-			unsigned long prate)
-{
-	if (!to_clk_tegra(hw)->fixed_rate)
-		to_clk_tegra(hw)->fixed_rate = clk_measure_input_freq();
-	return to_clk_tegra(hw)->fixed_rate;
-}
-
-static void tegra20_clk_m_init(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 osc_ctrl = clk_readl(OSC_CTRL);
-	u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK;
-
-	switch (c->fixed_rate) {
-	case 12000000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
-		break;
-	case 13000000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
-		break;
-	case 19200000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
-		break;
-	case 26000000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
-		break;
-	default:
-		BUG();
-	}
-	clk_writel(auto_clock_control, OSC_CTRL);
-}
-
-struct clk_ops tegra_clk_m_ops = {
-	.init = tegra20_clk_m_init,
-	.recalc_rate = tegra20_clk_m_recalc_rate,
-};
-
-/* super clock functions */
-/* "super clocks" on tegra have two-stage muxes and a clock skipping
- * super divider.  We will ignore the clock skipping divider, since we
- * can't lower the voltage when using the clock skip, but we can if we
- * lower the PLL frequency.
- */
-static int tegra20_super_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	val = clk_readl(c->reg + SUPER_CLK_MUX);
-	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
-		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
-	c->state = ON;
-	return c->state;
-}
-
-static int tegra20_super_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
-	return 0;
-}
-
-static void tegra20_super_clk_disable(struct clk_hw *hw)
-{
-	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
-
-	/* oops - don't disable the CPU clock! */
-	BUG();
-}
-
-static u8 tegra20_super_clk_get_parent(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	int val = clk_readl(c->reg + SUPER_CLK_MUX);
-	int source;
-	int shift;
-
-	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
-		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
-	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
-		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
-	source = (val >> shift) & SUPER_SOURCE_MASK;
-	return source;
-}
-
-static int tegra20_super_clk_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg + SUPER_CLK_MUX);
-	int shift;
-
-	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
-		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
-	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
-		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
-	val &= ~(SUPER_SOURCE_MASK << shift);
-	val |= index << shift;
-
-	clk_writel(val, c->reg);
-
-	return 0;
-}
-
-/* FIX ME: Need to switch parents to change the source PLL rate */
-static unsigned long tegra20_super_clk_recalc_rate(struct clk_hw *hw,
-			unsigned long prate)
-{
-	return prate;
-}
-
-static long tegra20_super_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	return *prate;
-}
-
-static int tegra20_super_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	return 0;
-}
-
-struct clk_ops tegra_super_ops = {
-	.is_enabled = tegra20_super_clk_is_enabled,
-	.enable = tegra20_super_clk_enable,
-	.disable = tegra20_super_clk_disable,
-	.set_parent = tegra20_super_clk_set_parent,
-	.get_parent = tegra20_super_clk_get_parent,
-	.set_rate = tegra20_super_clk_set_rate,
-	.round_rate = tegra20_super_clk_round_rate,
-	.recalc_rate = tegra20_super_clk_recalc_rate,
-};
-
-static unsigned long tegra20_twd_clk_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = parent_rate;
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-
-	return rate;
-}
-
-struct clk_ops tegra_twd_ops = {
-	.recalc_rate = tegra20_twd_clk_recalc_rate,
-};
-
-static u8 tegra20_cop_clk_get_parent(struct clk_hw *hw)
-{
-	return 0;
-}
-
-struct clk_ops tegra_cop_ops = {
-	.get_parent = tegra20_cop_clk_get_parent,
-};
-
-/* virtual cop clock functions. Used to acquire the fake 'cop' clock to
- * reset the COP block (i.e. AVP) */
-void tegra2_cop_clk_reset(struct clk_hw *hw, bool assert)
-{
-	unsigned long reg = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
-
-	pr_debug("%s %s\n", __func__, assert ? "assert" : "deassert");
-	clk_writel(1 << 1, reg);
-}
-
-/* bus clock functions */
-static int tegra20_bus_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-
-	c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
-	return c->state;
-}
-
-static int tegra20_bus_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long flags;
-	u32 val;
-
-	spin_lock_irqsave(&clock_register_lock, flags);
-
-	val = clk_readl(c->reg);
-	val &= ~(BUS_CLK_DISABLE << c->reg_shift);
-	clk_writel(val, c->reg);
-
-	spin_unlock_irqrestore(&clock_register_lock, flags);
-
-	return 0;
-}
-
-static void tegra20_bus_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long flags;
-	u32 val;
-
-	spin_lock_irqsave(&clock_register_lock, flags);
-
-	val = clk_readl(c->reg);
-	val |= BUS_CLK_DISABLE << c->reg_shift;
-	clk_writel(val, c->reg);
-
-	spin_unlock_irqrestore(&clock_register_lock, flags);
-}
-
-static unsigned long tegra20_bus_clk_recalc_rate(struct clk_hw *hw,
-			unsigned long prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-	u64 rate = prate;
-
-	c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
-	c->mul = 1;
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-	return rate;
-}
-
-static int tegra20_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	int ret = -EINVAL;
-	unsigned long flags;
-	u32 val;
-	int i;
-
-	spin_lock_irqsave(&clock_register_lock, flags);
-
-	val = clk_readl(c->reg);
-	for (i = 1; i <= 4; i++) {
-		if (rate == parent_rate / i) {
-			val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
-			val |= (i - 1) << c->reg_shift;
-			clk_writel(val, c->reg);
-			c->div = i;
-			c->mul = 1;
-			ret = 0;
-			break;
-		}
-	}
-
-	spin_unlock_irqrestore(&clock_register_lock, flags);
-
-	return ret;
-}
-
-static long tegra20_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	unsigned long parent_rate = *prate;
-	s64 divider;
-
-	if (rate >= parent_rate)
-		return rate;
-
-	divider = parent_rate;
-	divider += rate - 1;
-	do_div(divider, rate);
-
-	if (divider < 0)
-		return divider;
-
-	if (divider > 4)
-		divider = 4;
-	do_div(parent_rate, divider);
-
-	return parent_rate;
-}
-
-struct clk_ops tegra_bus_ops = {
-	.is_enabled = tegra20_bus_clk_is_enabled,
-	.enable = tegra20_bus_clk_enable,
-	.disable = tegra20_bus_clk_disable,
-	.set_rate = tegra20_bus_clk_set_rate,
-	.round_rate = tegra20_bus_clk_round_rate,
-	.recalc_rate = tegra20_bus_clk_recalc_rate,
-};
-
-/* Blink output functions */
-static int tegra20_blink_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	val = pmc_readl(PMC_CTRL);
-	c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
-	return c->state;
-}
-
-static unsigned long tegra20_blink_clk_recalc_rate(struct clk_hw *hw,
-			unsigned long prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = prate;
-	u32 val;
-
-	c->mul = 1;
-	val = pmc_readl(c->reg);
-
-	if (val & PMC_BLINK_TIMER_ENB) {
-		unsigned int on_off;
-
-		on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
-			PMC_BLINK_TIMER_DATA_ON_MASK;
-		val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
-		val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
-		on_off += val;
-		/* each tick in the blink timer is 4 32KHz clocks */
-		c->div = on_off * 4;
-	} else {
-		c->div = 1;
-	}
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-	return rate;
-}
-
-static int tegra20_blink_clk_enable(struct clk_hw *hw)
-{
-	u32 val;
-
-	val = pmc_readl(PMC_DPD_PADS_ORIDE);
-	pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
-
-	val = pmc_readl(PMC_CTRL);
-	pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
-
-	return 0;
-}
-
-static void tegra20_blink_clk_disable(struct clk_hw *hw)
-{
-	u32 val;
-
-	val = pmc_readl(PMC_CTRL);
-	pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL);
-
-	val = pmc_readl(PMC_DPD_PADS_ORIDE);
-	pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
-}
-
-static int tegra20_blink_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	if (rate >= parent_rate) {
-		c->div = 1;
-		pmc_writel(0, c->reg);
-	} else {
-		unsigned int on_off;
-		u32 val;
-
-		on_off = DIV_ROUND_UP(parent_rate / 8, rate);
-		c->div = on_off * 8;
-
-		val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
-			PMC_BLINK_TIMER_DATA_ON_SHIFT;
-		on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK;
-		on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
-		val |= on_off;
-		val |= PMC_BLINK_TIMER_ENB;
-		pmc_writel(val, c->reg);
-	}
-
-	return 0;
-}
-
-static long tegra20_blink_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	int div;
-	int mul;
-	long round_rate = *prate;
-
-	mul = 1;
-
-	if (rate >= *prate) {
-		div = 1;
-	} else {
-		div = DIV_ROUND_UP(*prate / 8, rate);
-		div *= 8;
-	}
-
-	round_rate *= mul;
-	round_rate += div - 1;
-	do_div(round_rate, div);
-
-	return round_rate;
-}
-
-struct clk_ops tegra_blink_clk_ops = {
-	.is_enabled = tegra20_blink_clk_is_enabled,
-	.enable = tegra20_blink_clk_enable,
-	.disable = tegra20_blink_clk_disable,
-	.set_rate = tegra20_blink_clk_set_rate,
-	.round_rate = tegra20_blink_clk_round_rate,
-	.recalc_rate = tegra20_blink_clk_recalc_rate,
-};
-
-/* PLL Functions */
-static int tegra20_pll_clk_wait_for_lock(struct clk_tegra *c)
-{
-	udelay(c->u.pll.lock_delay);
-	return 0;
-}
-
-static int tegra20_pll_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg + PLL_BASE);
-
-	c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
-	return c->state;
-}
-
-static unsigned long tegra20_pll_clk_recalc_rate(struct clk_hw *hw,
-				unsigned long prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg + PLL_BASE);
-	u64 rate = prate;
-
-	if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
-		const struct clk_pll_freq_table *sel;
-		for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
-			if (sel->input_rate == prate &&
-				sel->output_rate == c->u.pll.fixed_rate) {
-				c->mul = sel->n;
-				c->div = sel->m * sel->p;
-				break;
-			}
-		}
-		pr_err("Clock %s has unknown fixed frequency\n",
-			__clk_get_name(hw->clk));
-		BUG();
-	} else if (val & PLL_BASE_BYPASS) {
-		c->mul = 1;
-		c->div = 1;
-	} else {
-		c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
-		c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
-		if (c->flags & PLLU)
-			c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
-		else
-			c->div *= (val & PLL_BASE_DIVP_MASK) ? 2 : 1;
-	}
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-	return rate;
-}
-
-static int tegra20_pll_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
-
-	val = clk_readl(c->reg + PLL_BASE);
-	val &= ~PLL_BASE_BYPASS;
-	val |= PLL_BASE_ENABLE;
-	clk_writel(val, c->reg + PLL_BASE);
-
-	tegra20_pll_clk_wait_for_lock(c);
-
-	return 0;
-}
-
-static void tegra20_pll_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
-
-	val = clk_readl(c->reg);
-	val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
-	clk_writel(val, c->reg);
-}
-
-static int tegra20_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long input_rate = parent_rate;
-	const struct clk_pll_freq_table *sel;
-	u32 val;
-
-	pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
-
-	if (c->flags & PLL_FIXED) {
-		int ret = 0;
-		if (rate != c->u.pll.fixed_rate) {
-			pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
-				__func__, __clk_get_name(hw->clk),
-				c->u.pll.fixed_rate, rate);
-			ret = -EINVAL;
-		}
-		return ret;
-	}
-
-	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
-		if (sel->input_rate == input_rate && sel->output_rate == rate) {
-			c->mul = sel->n;
-			c->div = sel->m * sel->p;
-
-			val = clk_readl(c->reg + PLL_BASE);
-			if (c->flags & PLL_FIXED)
-				val |= PLL_BASE_OVERRIDE;
-			val &= ~(PLL_BASE_DIVP_MASK | PLL_BASE_DIVN_MASK |
-				 PLL_BASE_DIVM_MASK);
-			val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
-				(sel->n << PLL_BASE_DIVN_SHIFT);
-			BUG_ON(sel->p < 1 || sel->p > 2);
-			if (c->flags & PLLU) {
-				if (sel->p == 1)
-					val |= PLLU_BASE_POST_DIV;
-			} else {
-				if (sel->p == 2)
-					val |= 1 << PLL_BASE_DIVP_SHIFT;
-			}
-			clk_writel(val, c->reg + PLL_BASE);
-
-			if (c->flags & PLL_HAS_CPCON) {
-				val = clk_readl(c->reg + PLL_MISC(c));
-				val &= ~PLL_MISC_CPCON_MASK;
-				val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
-				clk_writel(val, c->reg + PLL_MISC(c));
-			}
-
-			if (c->state == ON)
-				tegra20_pll_clk_enable(hw);
-			return 0;
-		}
-	}
-	return -EINVAL;
-}
-
-static long tegra20_pll_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	const struct clk_pll_freq_table *sel;
-	unsigned long input_rate = *prate;
-	u64 output_rate = *prate;
-	int mul;
-	int div;
-
-	if (c->flags & PLL_FIXED)
-		return c->u.pll.fixed_rate;
-
-	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++)
-		if (sel->input_rate == input_rate && sel->output_rate == rate) {
-			mul = sel->n;
-			div = sel->m * sel->p;
-			break;
-		}
-
-	if (sel->input_rate == 0)
-		return -EINVAL;
-
-	output_rate *= mul;
-	output_rate += div - 1; /* round up */
-	do_div(output_rate, div);
-
-	return output_rate;
-}
-
-struct clk_ops tegra_pll_ops = {
-	.is_enabled = tegra20_pll_clk_is_enabled,
-	.enable = tegra20_pll_clk_enable,
-	.disable = tegra20_pll_clk_disable,
-	.set_rate = tegra20_pll_clk_set_rate,
-	.recalc_rate = tegra20_pll_clk_recalc_rate,
-	.round_rate = tegra20_pll_clk_round_rate,
-};
-
-static void tegra20_pllx_clk_init(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	if (tegra_sku_id == 7)
-		c->max_rate = 750000000;
-}
-
-struct clk_ops tegra_pllx_ops = {
-	.init = tegra20_pllx_clk_init,
-	.is_enabled = tegra20_pll_clk_is_enabled,
-	.enable = tegra20_pll_clk_enable,
-	.disable = tegra20_pll_clk_disable,
-	.set_rate = tegra20_pll_clk_set_rate,
-	.recalc_rate = tegra20_pll_clk_recalc_rate,
-	.round_rate = tegra20_pll_clk_round_rate,
-};
-
-static int tegra20_plle_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
-
-	mdelay(1);
-
-	val = clk_readl(c->reg + PLL_BASE);
-	if (!(val & PLLE_MISC_READY))
-		return -EBUSY;
-
-	val = clk_readl(c->reg + PLL_BASE);
-	val |= PLL_BASE_ENABLE | PLL_BASE_BYPASS;
-	clk_writel(val, c->reg + PLL_BASE);
-
-	return 0;
-}
-
-struct clk_ops tegra_plle_ops = {
-	.is_enabled = tegra20_pll_clk_is_enabled,
-	.enable = tegra20_plle_clk_enable,
-	.set_rate = tegra20_pll_clk_set_rate,
-	.recalc_rate = tegra20_pll_clk_recalc_rate,
-	.round_rate = tegra20_pll_clk_round_rate,
-};
-
-/* Clock divider ops */
-static int tegra20_pll_div_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-
-	val >>= c->reg_shift;
-	c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
-	if (!(val & PLL_OUT_RESET_DISABLE))
-		c->state = OFF;
-	return c->state;
-}
-
-static unsigned long tegra20_pll_div_clk_recalc_rate(struct clk_hw *hw,
-			unsigned long prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = prate;
-	u32 val = clk_readl(c->reg);
-	u32 divu71;
-
-	val >>= c->reg_shift;
-
-	if (c->flags & DIV_U71) {
-		divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
-		c->div = (divu71 + 2);
-		c->mul = 2;
-	} else if (c->flags & DIV_2) {
-		c->div = 2;
-		c->mul = 1;
-	} else {
-		c->div = 1;
-		c->mul = 1;
-	}
-
-	rate *= c->mul;
-	rate += c->div - 1; /* round up */
-	do_div(rate, c->div);
-
-	return rate;
-}
-
-static int tegra20_pll_div_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long flags;
-	u32 new_val;
-	u32 val;
-
-	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
-
-	if (c->flags & DIV_U71) {
-		spin_lock_irqsave(&clock_register_lock, flags);
-		val = clk_readl(c->reg);
-		new_val = val >> c->reg_shift;
-		new_val &= 0xFFFF;
-
-		new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
-
-		val &= ~(0xFFFF << c->reg_shift);
-		val |= new_val << c->reg_shift;
-		clk_writel(val, c->reg);
-		spin_unlock_irqrestore(&clock_register_lock, flags);
-		return 0;
-	} else if (c->flags & DIV_2) {
-		BUG_ON(!(c->flags & PLLD));
-		spin_lock_irqsave(&clock_register_lock, flags);
-		val = clk_readl(c->reg);
-		val &= ~PLLD_MISC_DIV_RST;
-		clk_writel(val, c->reg);
-		spin_unlock_irqrestore(&clock_register_lock, flags);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static void tegra20_pll_div_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long flags;
-	u32 new_val;
-	u32 val;
-
-	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
-
-	if (c->flags & DIV_U71) {
-		spin_lock_irqsave(&clock_register_lock, flags);
-		val = clk_readl(c->reg);
-		new_val = val >> c->reg_shift;
-		new_val &= 0xFFFF;
-
-		new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE);
-
-		val &= ~(0xFFFF << c->reg_shift);
-		val |= new_val << c->reg_shift;
-		clk_writel(val, c->reg);
-		spin_unlock_irqrestore(&clock_register_lock, flags);
-	} else if (c->flags & DIV_2) {
-		BUG_ON(!(c->flags & PLLD));
-		spin_lock_irqsave(&clock_register_lock, flags);
-		val = clk_readl(c->reg);
-		val |= PLLD_MISC_DIV_RST;
-		clk_writel(val, c->reg);
-		spin_unlock_irqrestore(&clock_register_lock, flags);
-	}
-}
-
-static int tegra20_pll_div_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long flags;
-	int divider_u71;
-	u32 new_val;
-	u32 val;
-
-	pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
-
-	if (c->flags & DIV_U71) {
-		divider_u71 = clk_div71_get_divider(parent_rate, rate);
-		if (divider_u71 >= 0) {
-			spin_lock_irqsave(&clock_register_lock, flags);
-			val = clk_readl(c->reg);
-			new_val = val >> c->reg_shift;
-			new_val &= 0xFFFF;
-			if (c->flags & DIV_U71_FIXED)
-				new_val |= PLL_OUT_OVERRIDE;
-			new_val &= ~PLL_OUT_RATIO_MASK;
-			new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT;
-
-			val &= ~(0xFFFF << c->reg_shift);
-			val |= new_val << c->reg_shift;
-			clk_writel(val, c->reg);
-			c->div = divider_u71 + 2;
-			c->mul = 2;
-			spin_unlock_irqrestore(&clock_register_lock, flags);
-			return 0;
-		}
-	} else if (c->flags & DIV_2) {
-		if (parent_rate == rate * 2)
-			return 0;
-	}
-	return -EINVAL;
-}
-
-static long tegra20_pll_div_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long parent_rate = *prate;
-	int divider;
-
-	pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
-
-	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(parent_rate, rate);
-		if (divider < 0)
-			return divider;
-		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
-	} else if (c->flags & DIV_2) {
-		return DIV_ROUND_UP(parent_rate, 2);
-	}
-	return -EINVAL;
-}
-
-struct clk_ops tegra_pll_div_ops = {
-	.is_enabled = tegra20_pll_div_clk_is_enabled,
-	.enable = tegra20_pll_div_clk_enable,
-	.disable = tegra20_pll_div_clk_disable,
-	.set_rate = tegra20_pll_div_clk_set_rate,
-	.round_rate = tegra20_pll_div_clk_round_rate,
-	.recalc_rate = tegra20_pll_div_clk_recalc_rate,
-};
-
-/* Periph clk ops */
-
-static int tegra20_periph_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	c->state = ON;
-
-	if (!c->u.periph.clk_num)
-		goto out;
-
-	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
-			PERIPH_CLK_TO_ENB_BIT(c)))
-		c->state = OFF;
-
-	if (!(c->flags & PERIPH_NO_RESET))
-		if (clk_readl(RST_DEVICES + PERIPH_CLK_TO_ENB_REG(c)) &
-				PERIPH_CLK_TO_ENB_BIT(c))
-			c->state = OFF;
-
-out:
-	return c->state;
-}
-
-static int tegra20_periph_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long flags;
-	u32 val;
-
-	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
-
-	if (!c->u.periph.clk_num)
-		return 0;
-
-	tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
-	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1)
-		return 0;
-
-	spin_lock_irqsave(&clock_register_lock, flags);
-
-	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
-	if (!(c->flags & PERIPH_NO_RESET) && !(c->flags & PERIPH_MANUAL_RESET))
-		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-			RST_DEVICES_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
-	if (c->flags & PERIPH_EMC_ENB) {
-		/* The EMC peripheral clock has 2 extra enable bits */
-		/* FIXME: Do they need to be disabled? */
-		val = clk_readl(c->reg);
-		val |= 0x3 << 24;
-		clk_writel(val, c->reg);
-	}
-
-	spin_unlock_irqrestore(&clock_register_lock, flags);
-
-	return 0;
-}
-
-static void tegra20_periph_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long flags;
-
-	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
-
-	if (!c->u.periph.clk_num)
-		return;
-
-	tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
-
-	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 0)
-		return;
-
-	spin_lock_irqsave(&clock_register_lock, flags);
-
-	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-		CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
-
-	spin_unlock_irqrestore(&clock_register_lock, flags);
-}
-
-void tegra2_periph_clk_reset(struct clk_hw *hw, bool assert)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long base = assert ? RST_DEVICES_SET : RST_DEVICES_CLR;
-
-	pr_debug("%s %s on clock %s\n", __func__,
-		assert ? "assert" : "deassert", __clk_get_name(hw->clk));
-
-	BUG_ON(!c->u.periph.clk_num);
-
-	if (!(c->flags & PERIPH_NO_RESET))
-		clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-			   base + PERIPH_CLK_TO_ENB_SET_REG(c));
-}
-
-static int tegra20_periph_clk_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	u32 mask;
-	u32 shift;
-
-	pr_debug("%s: %s %d\n", __func__, __clk_get_name(hw->clk), index);
-
-	if (c->flags & MUX_PWM) {
-		shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
-		mask = PERIPH_CLK_SOURCE_PWM_MASK;
-	} else {
-		shift = PERIPH_CLK_SOURCE_SHIFT;
-		mask = PERIPH_CLK_SOURCE_MASK;
-	}
-
-	val = clk_readl(c->reg);
-	val &= ~mask;
-	val |= (index) << shift;
-
-	clk_writel(val, c->reg);
-
-	return 0;
-}
-
-static u8 tegra20_periph_clk_get_parent(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-	u32 mask;
-	u32 shift;
-
-	if (c->flags & MUX_PWM) {
-		shift = PERIPH_CLK_SOURCE_PWM_SHIFT;
-		mask = PERIPH_CLK_SOURCE_PWM_MASK;
-	} else {
-		shift = PERIPH_CLK_SOURCE_SHIFT;
-		mask = PERIPH_CLK_SOURCE_MASK;
-	}
-
-	if (c->flags & MUX)
-		return (val & mask) >> shift;
-	else
-		return 0;
-}
-
-static unsigned long tegra20_periph_clk_recalc_rate(struct clk_hw *hw,
-			unsigned long prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long rate = prate;
-	u32 val = clk_readl(c->reg);
-
-	if (c->flags & DIV_U71) {
-		u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
-		c->div = divu71 + 2;
-		c->mul = 2;
-	} else if (c->flags & DIV_U16) {
-		u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
-		c->div = divu16 + 1;
-		c->mul = 1;
-	} else {
-		c->div = 1;
-		c->mul = 1;
-		return rate;
-	}
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-
-	return rate;
-}
-
-static int tegra20_periph_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	int divider;
-
-	val = clk_readl(c->reg);
-
-	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(parent_rate, rate);
-
-		if (divider >= 0) {
-			val = clk_readl(c->reg);
-			val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
-			val |= divider;
-			clk_writel(val, c->reg);
-			c->div = divider + 2;
-			c->mul = 2;
-			return 0;
-		}
-	} else if (c->flags & DIV_U16) {
-		divider = clk_div16_get_divider(parent_rate, rate);
-		if (divider >= 0) {
-			val = clk_readl(c->reg);
-			val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
-			val |= divider;
-			clk_writel(val, c->reg);
-			c->div = divider + 1;
-			c->mul = 1;
-			return 0;
-		}
-	} else if (parent_rate <= rate) {
-		c->div = 1;
-		c->mul = 1;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static long tegra20_periph_clk_round_rate(struct clk_hw *hw,
-	unsigned long rate, unsigned long *prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
-	int divider;
-
-	pr_debug("%s: %s %lu\n", __func__, __clk_get_name(hw->clk), rate);
-
-	if (prate)
-		parent_rate = *prate;
-
-	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(parent_rate, rate);
-		if (divider < 0)
-			return divider;
-
-		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
-	} else if (c->flags & DIV_U16) {
-		divider = clk_div16_get_divider(parent_rate, rate);
-		if (divider < 0)
-			return divider;
-		return DIV_ROUND_UP(parent_rate, divider + 1);
-	}
-	return -EINVAL;
-}
-
-struct clk_ops tegra_periph_clk_ops = {
-	.is_enabled = tegra20_periph_clk_is_enabled,
-	.enable = tegra20_periph_clk_enable,
-	.disable = tegra20_periph_clk_disable,
-	.set_parent = tegra20_periph_clk_set_parent,
-	.get_parent = tegra20_periph_clk_get_parent,
-	.set_rate = tegra20_periph_clk_set_rate,
-	.round_rate = tegra20_periph_clk_round_rate,
-	.recalc_rate = tegra20_periph_clk_recalc_rate,
-};
-
-/* External memory controller clock ops */
-static void tegra20_emc_clk_init(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	c->max_rate = __clk_get_rate(hw->clk);
-}
-
-static long tegra20_emc_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	long emc_rate;
-	long clk_rate;
-
-	/*
-	 * The slowest entry in the EMC clock table that is at least as
-	 * fast as rate.
-	 */
-	emc_rate = tegra_emc_round_rate(rate);
-	if (emc_rate < 0)
-		return c->max_rate;
-
-	/*
-	 * The fastest rate the PLL will generate that is at most the
-	 * requested rate.
-	 */
-	clk_rate = tegra20_periph_clk_round_rate(hw, emc_rate, NULL);
-
-	/*
-	 * If this fails, and emc_rate > clk_rate, it's because the maximum
-	 * rate in the EMC tables is larger than the maximum rate of the EMC
-	 * clock. The EMC clock's max rate is the rate it was running when the
-	 * kernel booted. Such a mismatch is probably due to using the wrong
-	 * BCT, i.e. using a Tegra20 BCT with an EMC table written for Tegra25.
-	 */
-	WARN_ONCE(emc_rate != clk_rate,
-		"emc_rate %ld != clk_rate %ld",
-		emc_rate, clk_rate);
-
-	return emc_rate;
-}
-
-static int tegra20_emc_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	int ret;
-
-	/*
-	 * The Tegra2 memory controller has an interlock with the clock
-	 * block that allows memory shadowed registers to be updated,
-	 * and then transfer them to the main registers at the same
-	 * time as the clock update without glitches.
-	 */
-	ret = tegra_emc_set_rate(rate);
-	if (ret < 0)
-		return ret;
-
-	ret = tegra20_periph_clk_set_rate(hw, rate, parent_rate);
-	udelay(1);
-
-	return ret;
-}
-
-struct clk_ops tegra_emc_clk_ops = {
-	.init = tegra20_emc_clk_init,
-	.is_enabled = tegra20_periph_clk_is_enabled,
-	.enable = tegra20_periph_clk_enable,
-	.disable = tegra20_periph_clk_disable,
-	.set_parent = tegra20_periph_clk_set_parent,
-	.get_parent = tegra20_periph_clk_get_parent,
-	.set_rate = tegra20_emc_clk_set_rate,
-	.round_rate = tegra20_emc_clk_round_rate,
-	.recalc_rate = tegra20_periph_clk_recalc_rate,
-};
-
-/* Clock doubler ops */
-static int tegra20_clk_double_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	c->state = ON;
-
-	if (!c->u.periph.clk_num)
-		goto out;
-
-	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
-			PERIPH_CLK_TO_ENB_BIT(c)))
-		c->state = OFF;
-
-out:
-	return c->state;
-};
-
-static unsigned long tegra20_clk_double_recalc_rate(struct clk_hw *hw,
-			unsigned long prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = prate;
-
-	c->mul = 2;
-	c->div = 1;
-
-	rate *= c->mul;
-	rate += c->div - 1; /* round up */
-	do_div(rate, c->div);
-
-	return rate;
-}
-
-static long tegra20_clk_double_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	unsigned long output_rate = *prate;
-
-	do_div(output_rate, 2);
-	return output_rate;
-}
-
-static int tegra20_clk_double_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	if (rate != 2 * parent_rate)
-		return -EINVAL;
-	return 0;
-}
-
-struct clk_ops tegra_clk_double_ops = {
-	.is_enabled = tegra20_clk_double_is_enabled,
-	.enable = tegra20_periph_clk_enable,
-	.disable = tegra20_periph_clk_disable,
-	.set_rate = tegra20_clk_double_set_rate,
-	.recalc_rate = tegra20_clk_double_recalc_rate,
-	.round_rate = tegra20_clk_double_round_rate,
-};
-
-/* Audio sync clock ops */
-static int tegra20_audio_sync_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-
-	c->state = (val & (1<<4)) ? OFF : ON;
-	return c->state;
-}
-
-static int tegra20_audio_sync_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	clk_writel(0, c->reg);
-	return 0;
-}
-
-static void tegra20_audio_sync_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	clk_writel(1, c->reg);
-}
-
-static u8 tegra20_audio_sync_clk_get_parent(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-	int source;
-
-	source = val & 0xf;
-	return source;
-}
-
-static int tegra20_audio_sync_clk_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	val = clk_readl(c->reg);
-	val &= ~0xf;
-	val |= index;
-
-	clk_writel(val, c->reg);
-
-	return 0;
-}
-
-struct clk_ops tegra_audio_sync_clk_ops = {
-	.is_enabled = tegra20_audio_sync_clk_is_enabled,
-	.enable = tegra20_audio_sync_clk_enable,
-	.disable = tegra20_audio_sync_clk_disable,
-	.set_parent = tegra20_audio_sync_clk_set_parent,
-	.get_parent = tegra20_audio_sync_clk_get_parent,
-};
-
-/* cdev1 and cdev2 (dap_mclk1 and dap_mclk2) ops */
-
-static int tegra20_cdev_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	/* We could un-tristate the cdev1 or cdev2 pingroup here; this is
-	 * currently done in the pinmux code. */
-	c->state = ON;
-
-	BUG_ON(!c->u.periph.clk_num);
-
-	if (!(clk_readl(CLK_OUT_ENB + PERIPH_CLK_TO_ENB_REG(c)) &
-			PERIPH_CLK_TO_ENB_BIT(c)))
-		c->state = OFF;
-	return c->state;
-}
-
-static int tegra20_cdev_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	BUG_ON(!c->u.periph.clk_num);
-
-	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-		CLK_OUT_ENB_SET + PERIPH_CLK_TO_ENB_SET_REG(c));
-	return 0;
-}
-
-static void tegra20_cdev_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	BUG_ON(!c->u.periph.clk_num);
-
-	clk_writel(PERIPH_CLK_TO_ENB_BIT(c),
-		CLK_OUT_ENB_CLR + PERIPH_CLK_TO_ENB_SET_REG(c));
-}
-
-static unsigned long tegra20_cdev_recalc_rate(struct clk_hw *hw,
-			unsigned long prate)
-{
-	return to_clk_tegra(hw)->fixed_rate;
-}
-
-struct clk_ops tegra_cdev_clk_ops = {
-	.is_enabled = tegra20_cdev_clk_is_enabled,
-	.enable = tegra20_cdev_clk_enable,
-	.disable = tegra20_cdev_clk_disable,
-	.recalc_rate = tegra20_cdev_recalc_rate,
-};
-
-/* Tegra20 CPU clock and reset control functions */
-static void tegra20_wait_cpu_in_reset(u32 cpu)
-{
-	unsigned int reg;
-
-	do {
-		reg = readl(reg_clk_base +
-			    TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
-		cpu_relax();
-	} while (!(reg & (1 << cpu)));	/* check CPU been reset or not */
-
-	return;
-}
-
-static void tegra20_put_cpu_in_reset(u32 cpu)
-{
-	writel(CPU_RESET(cpu),
-	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
-	dmb();
-}
-
-static void tegra20_cpu_out_of_reset(u32 cpu)
-{
-	writel(CPU_RESET(cpu),
-	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
-	wmb();
-}
-
-static void tegra20_enable_cpu_clock(u32 cpu)
-{
-	unsigned int reg;
-
-	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-	writel(reg & ~CPU_CLOCK(cpu),
-	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-	barrier();
-	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-}
-
-static void tegra20_disable_cpu_clock(u32 cpu)
-{
-	unsigned int reg;
-
-	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-	writel(reg | CPU_CLOCK(cpu),
-	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-}
-
-static struct tegra_cpu_car_ops tegra20_cpu_car_ops = {
-	.wait_for_reset	= tegra20_wait_cpu_in_reset,
-	.put_in_reset	= tegra20_put_cpu_in_reset,
-	.out_of_reset	= tegra20_cpu_out_of_reset,
-	.enable_clock	= tegra20_enable_cpu_clock,
-	.disable_clock	= tegra20_disable_cpu_clock,
-};
-
-void __init tegra20_cpu_car_ops_init(void)
-{
-	tegra_cpu_car_ops = &tegra20_cpu_car_ops;
-}
diff --git a/arch/arm/mach-tegra/tegra20_clocks.h b/arch/arm/mach-tegra/tegra20_clocks.h
deleted file mode 100644
index 8bfd31b..0000000
--- a/arch/arm/mach-tegra/tegra20_clocks.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __MACH_TEGRA20_CLOCK_H
-#define __MACH_TEGRA20_CLOCK_H
-
-extern struct clk_ops tegra_clk_32k_ops;
-extern struct clk_ops tegra_pll_ops;
-extern struct clk_ops tegra_clk_m_ops;
-extern struct clk_ops tegra_pll_div_ops;
-extern struct clk_ops tegra_pllx_ops;
-extern struct clk_ops tegra_plle_ops;
-extern struct clk_ops tegra_clk_double_ops;
-extern struct clk_ops tegra_cdev_clk_ops;
-extern struct clk_ops tegra_audio_sync_clk_ops;
-extern struct clk_ops tegra_super_ops;
-extern struct clk_ops tegra_cpu_ops;
-extern struct clk_ops tegra_twd_ops;
-extern struct clk_ops tegra_cop_ops;
-extern struct clk_ops tegra_bus_ops;
-extern struct clk_ops tegra_blink_clk_ops;
-extern struct clk_ops tegra_emc_clk_ops;
-extern struct clk_ops tegra_periph_clk_ops;
-extern struct clk_ops tegra_clk_shared_bus_ops;
-
-void tegra2_periph_clk_reset(struct clk_hw *hw, bool assert);
-void tegra2_cop_clk_reset(struct clk_hw *hw, bool assert);
-
-#endif
diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c
deleted file mode 100644
index a23a073..0000000
--- a/arch/arm/mach-tegra/tegra20_clocks_data.c
+++ /dev/null
@@ -1,1143 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra2_clocks.c
- *
- * Copyright (C) 2010 Google, Inc.
- * Copyright (c) 2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * Author:
- *	Colin Cross <ccross@google.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#include <linux/clk-private.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-
-#include "clock.h"
-#include "fuse.h"
-#include "tegra2_emc.h"
-#include "tegra20_clocks.h"
-#include "tegra_cpu_car.h"
-
-/* Clock definitions */
-
-#define DEFINE_CLK_TEGRA(_name, _rate, _ops, _flags,		\
-		   _parent_names, _parents, _parent)		\
-	static struct clk tegra_##_name = {			\
-		.hw = &tegra_##_name##_hw.hw,			\
-		.name = #_name,					\
-		.rate = _rate,					\
-		.ops = _ops,					\
-		.flags = _flags,				\
-		.parent_names = _parent_names,			\
-		.parents = _parents,				\
-		.num_parents = ARRAY_SIZE(_parent_names),	\
-		.parent = _parent,				\
-	};
-
-static struct clk tegra_clk_32k;
-static struct clk_tegra tegra_clk_32k_hw = {
-	.hw = {
-		.clk = &tegra_clk_32k,
-	},
-	.fixed_rate = 32768,
-};
-
-static struct clk tegra_clk_32k = {
-	.name = "clk_32k",
-	.rate = 32768,
-	.ops = &tegra_clk_32k_ops,
-	.hw = &tegra_clk_32k_hw.hw,
-	.flags = CLK_IS_ROOT,
-};
-
-static struct clk tegra_clk_m;
-static struct clk_tegra tegra_clk_m_hw = {
-	.hw = {
-		.clk = &tegra_clk_m,
-	},
-	.flags = ENABLE_ON_INIT,
-	.reg = 0x1fc,
-	.reg_shift = 28,
-	.max_rate = 26000000,
-	.fixed_rate = 0,
-};
-
-static struct clk tegra_clk_m = {
-	.name = "clk_m",
-	.ops = &tegra_clk_m_ops,
-	.hw = &tegra_clk_m_hw.hw,
-	.flags = CLK_IS_ROOT,
-};
-
-#define DEFINE_PLL(_name, _flags, _reg, _max_rate, _input_min,	\
-		   _input_max, _cf_min, _cf_max, _vco_min,	\
-		   _vco_max, _freq_table, _lock_delay, _ops,	\
-		   _fixed_rate, _parent)			\
-	static const char *tegra_##_name##_parent_names[] = {	\
-		#_parent,					\
-	};							\
-	static struct clk *tegra_##_name##_parents[] = {	\
-		&tegra_##_parent,				\
-	};							\
-	static struct clk tegra_##_name;			\
-	static struct clk_tegra tegra_##_name##_hw = {		\
-		.hw = {						\
-			.clk = &tegra_##_name,			\
-		},						\
-		.flags = _flags,				\
-		.reg = _reg,					\
-		.max_rate = _max_rate,				\
-		.u.pll = {					\
-			.input_min = _input_min,		\
-			.input_max = _input_max,		\
-			.cf_min = _cf_min,			\
-			.cf_max = _cf_max,			\
-			.vco_min = _vco_min,			\
-			.vco_max = _vco_max,			\
-			.freq_table = _freq_table,		\
-			.lock_delay = _lock_delay,		\
-			.fixed_rate = _fixed_rate,		\
-		},						\
-	};							\
-	static struct clk tegra_##_name = {			\
-		.name = #_name,					\
-		.ops = &_ops,					\
-		.hw = &tegra_##_name##_hw.hw,			\
-		.parent = &tegra_##_parent,			\
-		.parent_names = tegra_##_name##_parent_names,	\
-		.parents = tegra_##_name##_parents,		\
-		.num_parents = 1,				\
-	};
-
-#define DEFINE_PLL_OUT(_name, _flags, _reg, _reg_shift,		\
-		_max_rate, _ops, _parent, _clk_flags)		\
-	static const char *tegra_##_name##_parent_names[] = {	\
-		#_parent,					\
-	};							\
-	static struct clk *tegra_##_name##_parents[] = {	\
-		&tegra_##_parent,				\
-	};							\
-	static struct clk tegra_##_name;			\
-	static struct clk_tegra tegra_##_name##_hw = {		\
-		.hw = {						\
-			.clk = &tegra_##_name,			\
-		},						\
-		.flags = _flags,				\
-		.reg = _reg,					\
-		.max_rate = _max_rate,				\
-		.reg_shift = _reg_shift,			\
-	};							\
-	static struct clk tegra_##_name = {			\
-		.name = #_name,					\
-		.ops = &tegra_pll_div_ops,			\
-		.hw = &tegra_##_name##_hw.hw,			\
-		.parent = &tegra_##_parent,			\
-		.parent_names = tegra_##_name##_parent_names,	\
-		.parents = tegra_##_name##_parents,		\
-		.num_parents = 1,				\
-		.flags = _clk_flags,				\
-	};
-
-
-static struct clk_pll_freq_table tegra_pll_s_freq_table[] = {
-	{32768, 12000000, 366, 1, 1, 0},
-	{32768, 13000000, 397, 1, 1, 0},
-	{32768, 19200000, 586, 1, 1, 0},
-	{32768, 26000000, 793, 1, 1, 0},
-	{0, 0, 0, 0, 0, 0},
-};
-
-DEFINE_PLL(pll_s, PLL_ALT_MISC_REG, 0xf0, 26000000, 32768, 32768, 0,
-		0, 12000000, 26000000, tegra_pll_s_freq_table, 300,
-		tegra_pll_ops, 0, clk_32k);
-
-static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
-	{ 12000000, 600000000, 600, 12, 1, 8 },
-	{ 13000000, 600000000, 600, 13, 1, 8 },
-	{ 19200000, 600000000, 500, 16, 1, 6 },
-	{ 26000000, 600000000, 600, 26, 1, 8 },
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_c, PLL_HAS_CPCON, 0x80, 600000000, 2000000, 31000000, 1000000,
-		6000000, 20000000, 1400000000, tegra_pll_c_freq_table, 300,
-		tegra_pll_ops, 0, clk_m);
-
-DEFINE_PLL_OUT(pll_c_out1, DIV_U71, 0x84, 0, 600000000,
-		tegra_pll_div_ops, pll_c, 0);
-
-static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
-	{ 12000000, 666000000, 666, 12, 1, 8},
-	{ 13000000, 666000000, 666, 13, 1, 8},
-	{ 19200000, 666000000, 555, 16, 1, 8},
-	{ 26000000, 666000000, 666, 26, 1, 8},
-	{ 12000000, 600000000, 600, 12, 1, 8},
-	{ 13000000, 600000000, 600, 13, 1, 8},
-	{ 19200000, 600000000, 375, 12, 1, 6},
-	{ 26000000, 600000000, 600, 26, 1, 8},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_m, PLL_HAS_CPCON, 0x90, 800000000, 2000000, 31000000, 1000000,
-		6000000, 20000000, 1200000000, tegra_pll_m_freq_table, 300,
-		tegra_pll_ops, 0, clk_m);
-
-DEFINE_PLL_OUT(pll_m_out1, DIV_U71, 0x94, 0, 600000000,
-		tegra_pll_div_ops, pll_m, 0);
-
-static struct clk_pll_freq_table tegra_pll_p_freq_table[] = {
-	{ 12000000, 216000000, 432, 12, 2, 8},
-	{ 13000000, 216000000, 432, 13, 2, 8},
-	{ 19200000, 216000000, 90,   4, 2, 1},
-	{ 26000000, 216000000, 432, 26, 2, 8},
-	{ 12000000, 432000000, 432, 12, 1, 8},
-	{ 13000000, 432000000, 432, 13, 1, 8},
-	{ 19200000, 432000000, 90,   4, 1, 1},
-	{ 26000000, 432000000, 432, 26, 1, 8},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-
-DEFINE_PLL(pll_p, ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON, 0xa0, 432000000,
-		2000000, 31000000, 1000000, 6000000, 20000000, 1400000000,
-		tegra_pll_p_freq_table, 300, tegra_pll_ops, 216000000, clk_m);
-
-DEFINE_PLL_OUT(pll_p_out1, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4, 0,
-		432000000, tegra_pll_div_ops, pll_p, 0);
-DEFINE_PLL_OUT(pll_p_out2, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4, 16,
-		432000000, tegra_pll_div_ops, pll_p, 0);
-DEFINE_PLL_OUT(pll_p_out3, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8, 0,
-		432000000, tegra_pll_div_ops, pll_p, 0);
-DEFINE_PLL_OUT(pll_p_out4, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8, 16,
-		432000000, tegra_pll_div_ops, pll_p, 0);
-
-static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
-	{ 28800000, 56448000, 49, 25, 1, 1},
-	{ 28800000, 73728000, 64, 25, 1, 1},
-	{ 28800000, 24000000,  5,  6, 1, 1},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_a, PLL_HAS_CPCON, 0xb0, 73728000, 2000000, 31000000, 1000000,
-		6000000, 20000000, 1400000000, tegra_pll_a_freq_table, 300,
-		tegra_pll_ops, 0, pll_p_out1);
-
-DEFINE_PLL_OUT(pll_a_out0, DIV_U71, 0xb4, 0, 73728000,
-		tegra_pll_div_ops, pll_a, 0);
-
-static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
-	{ 12000000, 216000000, 216, 12, 1, 4},
-	{ 13000000, 216000000, 216, 13, 1, 4},
-	{ 19200000, 216000000, 135, 12, 1, 3},
-	{ 26000000, 216000000, 216, 26, 1, 4},
-
-	{ 12000000, 297000000,  99,  4, 1, 4 },
-	{ 12000000, 339000000, 113,  4, 1, 4 },
-
-	{ 12000000, 594000000, 594, 12, 1, 8},
-	{ 13000000, 594000000, 594, 13, 1, 8},
-	{ 19200000, 594000000, 495, 16, 1, 8},
-	{ 26000000, 594000000, 594, 26, 1, 8},
-
-	{ 12000000, 616000000, 616, 12, 1, 8},
-
-	{ 12000000, 1000000000, 1000, 12, 1, 12},
-	{ 13000000, 1000000000, 1000, 13, 1, 12},
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 12},
-
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_d, PLL_HAS_CPCON | PLLD, 0xd0, 1000000000, 2000000, 40000000,
-		1000000, 6000000, 40000000, 1000000000, tegra_pll_d_freq_table,
-		1000, tegra_pll_ops, 0, clk_m);
-
-DEFINE_PLL_OUT(pll_d_out0, DIV_2 | PLLD, 0, 0, 500000000,
-		tegra_pll_div_ops, pll_d, CLK_SET_RATE_PARENT);
-
-static struct clk_pll_freq_table tegra_pll_u_freq_table[] = {
-	{ 12000000, 480000000, 960, 12, 2, 0},
-	{ 13000000, 480000000, 960, 13, 2, 0},
-	{ 19200000, 480000000, 200, 4,  2, 0},
-	{ 26000000, 480000000, 960, 26, 2, 0},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_u, PLLU, 0xc0, 480000000, 2000000, 40000000, 1000000, 6000000,
-		48000000, 960000000, tegra_pll_u_freq_table, 1000,
-		tegra_pll_ops, 0, clk_m);
-
-static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
-	/* 1 GHz */
-	{ 12000000, 1000000000, 1000, 12, 1, 12},
-	{ 13000000, 1000000000, 1000, 13, 1, 12},
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 12},
-
-	/* 912 MHz */
-	{ 12000000, 912000000,  912,  12, 1, 12},
-	{ 13000000, 912000000,  912,  13, 1, 12},
-	{ 19200000, 912000000,  760,  16, 1, 8},
-	{ 26000000, 912000000,  912,  26, 1, 12},
-
-	/* 816 MHz */
-	{ 12000000, 816000000,  816,  12, 1, 12},
-	{ 13000000, 816000000,  816,  13, 1, 12},
-	{ 19200000, 816000000,  680,  16, 1, 8},
-	{ 26000000, 816000000,  816,  26, 1, 12},
-
-	/* 760 MHz */
-	{ 12000000, 760000000,  760,  12, 1, 12},
-	{ 13000000, 760000000,  760,  13, 1, 12},
-	{ 19200000, 760000000,  950,  24, 1, 8},
-	{ 26000000, 760000000,  760,  26, 1, 12},
-
-	/* 750 MHz */
-	{ 12000000, 750000000,  750,  12, 1, 12},
-	{ 13000000, 750000000,  750,  13, 1, 12},
-	{ 19200000, 750000000,  625,  16, 1, 8},
-	{ 26000000, 750000000,  750,  26, 1, 12},
-
-	/* 608 MHz */
-	{ 12000000, 608000000,  608,  12, 1, 12},
-	{ 13000000, 608000000,  608,  13, 1, 12},
-	{ 19200000, 608000000,  380,  12, 1, 8},
-	{ 26000000, 608000000,  608,  26, 1, 12},
-
-	/* 456 MHz */
-	{ 12000000, 456000000,  456,  12, 1, 12},
-	{ 13000000, 456000000,  456,  13, 1, 12},
-	{ 19200000, 456000000,  380,  16, 1, 8},
-	{ 26000000, 456000000,  456,  26, 1, 12},
-
-	/* 312 MHz */
-	{ 12000000, 312000000,  312,  12, 1, 12},
-	{ 13000000, 312000000,  312,  13, 1, 12},
-	{ 19200000, 312000000,  260,  16, 1, 8},
-	{ 26000000, 312000000,  312,  26, 1, 12},
-
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_x, PLL_HAS_CPCON | PLL_ALT_MISC_REG, 0xe0, 1000000000, 2000000,
-		31000000, 1000000, 6000000, 20000000, 1200000000,
-		tegra_pll_x_freq_table, 300, tegra_pllx_ops, 0, clk_m);
-
-static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
-	{ 12000000, 100000000,  200,  24, 1, 0 },
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_e, PLL_ALT_MISC_REG, 0xe8, 100000000, 12000000, 12000000, 0, 0,
-		0, 0, tegra_pll_e_freq_table, 0, tegra_plle_ops, 0, clk_m);
-
-static const char *tegra_common_parent_names[] = {
-	"clk_m",
-};
-
-static struct clk *tegra_common_parents[] = {
-	&tegra_clk_m,
-};
-
-static struct clk tegra_clk_d;
-static struct clk_tegra tegra_clk_d_hw = {
-	.hw = {
-		.clk = &tegra_clk_d,
-	},
-	.flags = PERIPH_NO_RESET,
-	.reg = 0x34,
-	.reg_shift = 12,
-	.max_rate = 52000000,
-	.u.periph = {
-		.clk_num = 90,
-	},
-};
-
-static struct clk tegra_clk_d = {
-	.name = "clk_d",
-	.hw = &tegra_clk_d_hw.hw,
-	.ops = &tegra_clk_double_ops,
-	.parent = &tegra_clk_m,
-	.parent_names = tegra_common_parent_names,
-	.parents = tegra_common_parents,
-	.num_parents = ARRAY_SIZE(tegra_common_parent_names),
-};
-
-static struct clk tegra_cdev1;
-static struct clk_tegra tegra_cdev1_hw = {
-	.hw = {
-		.clk = &tegra_cdev1,
-	},
-	.fixed_rate = 26000000,
-	.u.periph = {
-		.clk_num = 94,
-	},
-};
-static struct clk tegra_cdev1 = {
-	.name = "cdev1",
-	.hw = &tegra_cdev1_hw.hw,
-	.ops = &tegra_cdev_clk_ops,
-	.flags = CLK_IS_ROOT,
-};
-
-/* dap_mclk2, belongs to the cdev2 pingroup. */
-static struct clk tegra_cdev2;
-static struct clk_tegra tegra_cdev2_hw = {
-	.hw = {
-		.clk = &tegra_cdev2,
-	},
-	.fixed_rate = 26000000,
-	.u.periph = {
-		.clk_num  = 93,
-	},
-};
-static struct clk tegra_cdev2 = {
-	.name = "cdev2",
-	.hw = &tegra_cdev2_hw.hw,
-	.ops = &tegra_cdev_clk_ops,
-	.flags = CLK_IS_ROOT,
-};
-
-/* initialized before peripheral clocks */
-static struct clk_mux_sel mux_audio_sync_clk[8+1];
-static const struct audio_sources {
-	const char *name;
-	int value;
-} mux_audio_sync_clk_sources[] = {
-	{ .name = "spdif_in", .value = 0 },
-	{ .name = "i2s1", .value = 1 },
-	{ .name = "i2s2", .value = 2 },
-	{ .name = "pll_a_out0", .value = 4 },
-#if 0 /* FIXME: not implemented */
-	{ .name = "ac97", .value = 3 },
-	{ .name = "ext_audio_clk2", .value = 5 },
-	{ .name = "ext_audio_clk1", .value = 6 },
-	{ .name = "ext_vimclk", .value = 7 },
-#endif
-	{ NULL, 0 }
-};
-
-static const char *audio_parent_names[] = {
-	"spdif_in",
-	"i2s1",
-	"i2s2",
-	"dummy",
-	"pll_a_out0",
-	"dummy",
-	"dummy",
-	"dummy",
-};
-
-static struct clk *audio_parents[] = {
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-	NULL,
-};
-
-static struct clk tegra_audio;
-static struct clk_tegra tegra_audio_hw = {
-	.hw = {
-		.clk = &tegra_audio,
-	},
-	.reg = 0x38,
-	.max_rate = 73728000,
-};
-DEFINE_CLK_TEGRA(audio, 0, &tegra_audio_sync_clk_ops, 0, audio_parent_names,
-		audio_parents, NULL);
-
-static const char *audio_2x_parent_names[] = {
-	"audio",
-};
-
-static struct clk *audio_2x_parents[] = {
-	&tegra_audio,
-};
-
-static struct clk tegra_audio_2x;
-static struct clk_tegra tegra_audio_2x_hw = {
-	.hw = {
-		.clk = &tegra_audio_2x,
-	},
-	.flags = PERIPH_NO_RESET,
-	.max_rate = 48000000,
-	.reg = 0x34,
-	.reg_shift = 8,
-	.u.periph = {
-		.clk_num = 89,
-	},
-};
-DEFINE_CLK_TEGRA(audio_2x, 0, &tegra_clk_double_ops, 0, audio_2x_parent_names,
-		audio_2x_parents, &tegra_audio);
-
-static struct clk_lookup tegra_audio_clk_lookups[] = {
-	{ .con_id = "audio", .clk = &tegra_audio },
-	{ .con_id = "audio_2x", .clk = &tegra_audio_2x }
-};
-
-/* This is called after peripheral clocks are initialized, as the
- * audio_sync clock depends on some of the peripheral clocks.
- */
-
-static void init_audio_sync_clock_mux(void)
-{
-	int i;
-	struct clk_mux_sel *sel = mux_audio_sync_clk;
-	const struct audio_sources *src = mux_audio_sync_clk_sources;
-	struct clk_lookup *lookup;
-
-	for (i = 0; src->name; i++, sel++, src++) {
-		sel->input = tegra_get_clock_by_name(src->name);
-		if (!sel->input)
-			pr_err("%s: could not find clk %s\n", __func__,
-				src->name);
-		audio_parents[src->value] = sel->input;
-		sel->value = src->value;
-	}
-
-	lookup = tegra_audio_clk_lookups;
-	for (i = 0; i < ARRAY_SIZE(tegra_audio_clk_lookups); i++, lookup++) {
-		struct clk *c = lookup->clk;
-		struct clk_tegra *clk = to_clk_tegra(c->hw);
-		__clk_init(NULL, c);
-		INIT_LIST_HEAD(&clk->shared_bus_list);
-		clk->lookup.con_id = lookup->con_id;
-		clk->lookup.clk = c;
-		clkdev_add(&clk->lookup);
-		tegra_clk_add(c);
-	}
-}
-
-static const char *mux_cclk[] = {
-	"clk_m",
-	"pll_c",
-	"clk_32k",
-	"pll_m",
-	"pll_p",
-	"pll_p_out4",
-	"pll_p_out3",
-	"clk_d",
-	"pll_x",
-};
-
-
-static struct clk *mux_cclk_p[] = {
-	&tegra_clk_m,
-	&tegra_pll_c,
-	&tegra_clk_32k,
-	&tegra_pll_m,
-	&tegra_pll_p,
-	&tegra_pll_p_out4,
-	&tegra_pll_p_out3,
-	&tegra_clk_d,
-	&tegra_pll_x,
-};
-
-static const char *mux_sclk[] = {
-	"clk_m",
-	"pll_c_out1",
-	"pll_p_out4",
-	"pllp_p_out3",
-	"pll_p_out2",
-	"clk_d",
-	"clk_32k",
-	"pll_m_out1",
-};
-
-static struct clk *mux_sclk_p[] = {
-	&tegra_clk_m,
-	&tegra_pll_c_out1,
-	&tegra_pll_p_out4,
-	&tegra_pll_p_out3,
-	&tegra_pll_p_out2,
-	&tegra_clk_d,
-	&tegra_clk_32k,
-	&tegra_pll_m_out1,
-};
-
-static struct clk tegra_cclk;
-static struct clk_tegra tegra_cclk_hw = {
-	.hw = {
-		.clk = &tegra_cclk,
-	},
-	.reg = 0x20,
-	.max_rate = 1000000000,
-};
-DEFINE_CLK_TEGRA(cclk, 0, &tegra_super_ops, 0, mux_cclk,
-		mux_cclk_p, NULL);
-
-static const char *mux_twd[] = {
-	"cclk",
-};
-
-static struct clk *mux_twd_p[] = {
-	&tegra_cclk,
-};
-
-static struct clk tegra_clk_twd;
-static struct clk_tegra tegra_clk_twd_hw = {
-	.hw = {
-		.clk = &tegra_clk_twd,
-	},
-	.max_rate = 1000000000,
-	.mul = 1,
-	.div = 4,
-};
-
-static struct clk tegra_clk_twd = {
-	.name = "twd",
-	.ops = &tegra_twd_ops,
-	.hw = &tegra_clk_twd_hw.hw,
-	.parent = &tegra_cclk,
-	.parent_names = mux_twd,
-	.parents = mux_twd_p,
-	.num_parents = ARRAY_SIZE(mux_twd),
-};
-
-static struct clk tegra_sclk;
-static struct clk_tegra tegra_sclk_hw = {
-	.hw = {
-		.clk = &tegra_sclk,
-	},
-	.reg = 0x28,
-	.max_rate = 240000000,
-	.min_rate = 120000000,
-};
-DEFINE_CLK_TEGRA(sclk, 0, &tegra_super_ops, 0, mux_sclk,
-		mux_sclk_p, NULL);
-
-static const char *tegra_cop_parent_names[] = {
-	"tegra_sclk",
-};
-
-static struct clk *tegra_cop_parents[] = {
-	&tegra_sclk,
-};
-
-static struct clk tegra_cop;
-static struct clk_tegra tegra_cop_hw = {
-	.hw = {
-		.clk = &tegra_cop,
-	},
-	.max_rate  = 240000000,
-	.reset = &tegra2_cop_clk_reset,
-};
-DEFINE_CLK_TEGRA(cop, 0, &tegra_cop_ops, CLK_SET_RATE_PARENT,
-		tegra_cop_parent_names, tegra_cop_parents, &tegra_sclk);
-
-static const char *tegra_hclk_parent_names[] = {
-	"tegra_sclk",
-};
-
-static struct clk *tegra_hclk_parents[] = {
-	&tegra_sclk,
-};
-
-static struct clk tegra_hclk;
-static struct clk_tegra tegra_hclk_hw = {
-	.hw = {
-		.clk = &tegra_hclk,
-	},
-	.flags = DIV_BUS,
-	.reg = 0x30,
-	.reg_shift = 4,
-	.max_rate = 240000000,
-};
-DEFINE_CLK_TEGRA(hclk, 0, &tegra_bus_ops, 0, tegra_hclk_parent_names,
-		tegra_hclk_parents, &tegra_sclk);
-
-static const char *tegra_pclk_parent_names[] = {
-	"tegra_hclk",
-};
-
-static struct clk *tegra_pclk_parents[] = {
-	&tegra_hclk,
-};
-
-static struct clk tegra_pclk;
-static struct clk_tegra tegra_pclk_hw = {
-	.hw = {
-		.clk = &tegra_pclk,
-	},
-	.flags = DIV_BUS,
-	.reg = 0x30,
-	.reg_shift = 0,
-	.max_rate = 120000000,
-};
-DEFINE_CLK_TEGRA(pclk, 0, &tegra_bus_ops, 0, tegra_pclk_parent_names,
-		tegra_pclk_parents, &tegra_hclk);
-
-static const char *tegra_blink_parent_names[] = {
-	"clk_32k",
-};
-
-static struct clk *tegra_blink_parents[] = {
-	&tegra_clk_32k,
-};
-
-static struct clk tegra_blink;
-static struct clk_tegra tegra_blink_hw = {
-	.hw = {
-		.clk = &tegra_blink,
-	},
-	.reg = 0x40,
-	.max_rate = 32768,
-};
-DEFINE_CLK_TEGRA(blink, 0, &tegra_blink_clk_ops, 0, tegra_blink_parent_names,
-		tegra_blink_parents, &tegra_clk_32k);
-
-static const char *mux_pllm_pllc_pllp_plla[] = {
-	"pll_m",
-	"pll_c",
-	"pll_p",
-	"pll_a_out0",
-};
-
-static struct clk *mux_pllm_pllc_pllp_plla_p[] = {
-	&tegra_pll_m,
-	&tegra_pll_c,
-	&tegra_pll_p,
-	&tegra_pll_a_out0,
-};
-
-static const char *mux_pllm_pllc_pllp_clkm[] = {
-	"pll_m",
-	"pll_c",
-	"pll_p",
-	"clk_m",
-};
-
-static struct clk *mux_pllm_pllc_pllp_clkm_p[] = {
-	&tegra_pll_m,
-	&tegra_pll_c,
-	&tegra_pll_p,
-	&tegra_clk_m,
-};
-
-static const char *mux_pllp_pllc_pllm_clkm[] = {
-	"pll_p",
-	"pll_c",
-	"pll_m",
-	"clk_m",
-};
-
-static struct clk *mux_pllp_pllc_pllm_clkm_p[] = {
-	&tegra_pll_p,
-	&tegra_pll_c,
-	&tegra_pll_m,
-	&tegra_clk_m,
-};
-
-static const char *mux_pllaout0_audio2x_pllp_clkm[] = {
-	"pll_a_out0",
-	"audio_2x",
-	"pll_p",
-	"clk_m",
-};
-
-static struct clk *mux_pllaout0_audio2x_pllp_clkm_p[] = {
-	&tegra_pll_a_out0,
-	&tegra_audio_2x,
-	&tegra_pll_p,
-	&tegra_clk_m,
-};
-
-static const char *mux_pllp_plld_pllc_clkm[] = {
-	"pllp",
-	"pll_d_out0",
-	"pll_c",
-	"clk_m",
-};
-
-static struct clk *mux_pllp_plld_pllc_clkm_p[] = {
-	&tegra_pll_p,
-	&tegra_pll_d_out0,
-	&tegra_pll_c,
-	&tegra_clk_m,
-};
-
-static const char *mux_pllp_pllc_audio_clkm_clk32[] = {
-	"pll_p",
-	"pll_c",
-	"audio",
-	"clk_m",
-	"clk_32k",
-};
-
-static struct clk *mux_pllp_pllc_audio_clkm_clk32_p[] = {
-	&tegra_pll_p,
-	&tegra_pll_c,
-	&tegra_audio,
-	&tegra_clk_m,
-	&tegra_clk_32k,
-};
-
-static const char *mux_pllp_pllc_pllm[] = {
-	"pll_p",
-	"pll_c",
-	"pll_m"
-};
-
-static struct clk *mux_pllp_pllc_pllm_p[] = {
-	&tegra_pll_p,
-	&tegra_pll_c,
-	&tegra_pll_m,
-};
-
-static const char *mux_clk_m[] = {
-	"clk_m",
-};
-
-static struct clk *mux_clk_m_p[] = {
-	&tegra_clk_m,
-};
-
-static const char *mux_pllp_out3[] = {
-	"pll_p_out3",
-};
-
-static struct clk *mux_pllp_out3_p[] = {
-	&tegra_pll_p_out3,
-};
-
-static const char *mux_plld[] = {
-	"pll_d",
-};
-
-static struct clk *mux_plld_p[] = {
-	&tegra_pll_d,
-};
-
-static const char *mux_clk_32k[] = {
-	"clk_32k",
-};
-
-static struct clk *mux_clk_32k_p[] = {
-	&tegra_clk_32k,
-};
-
-static const char *mux_pclk[] = {
-	"pclk",
-};
-
-static struct clk *mux_pclk_p[] = {
-	&tegra_pclk,
-};
-
-static struct clk tegra_emc;
-static struct clk_tegra tegra_emc_hw = {
-	.hw = {
-		.clk = &tegra_emc,
-	},
-	.reg = 0x19c,
-	.max_rate = 800000000,
-	.flags = MUX | DIV_U71 | PERIPH_EMC_ENB,
-	.reset = &tegra2_periph_clk_reset,
-	.u.periph = {
-		.clk_num = 57,
-	},
-};
-DEFINE_CLK_TEGRA(emc, 0, &tegra_emc_clk_ops, 0, mux_pllm_pllc_pllp_clkm,
-		mux_pllm_pllc_pllp_clkm_p, NULL);
-
-#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg,	\
-		_max, _inputs, _flags) 			\
-	static struct clk tegra_##_name;		\
-	static struct clk_tegra tegra_##_name##_hw = {	\
-		.hw = {					\
-			.clk = &tegra_##_name,		\
-		},					\
-		.lookup = {				\
-			.dev_id = _dev,			\
-			.con_id = _con,			\
-		},					\
-		.reg = _reg,				\
-		.flags = _flags,			\
-		.max_rate = _max,			\
-		.u.periph = {				\
-			.clk_num = _clk_num,		\
-		},					\
-		.reset = tegra2_periph_clk_reset,	\
-	};						\
-	static struct clk tegra_##_name = {		\
-		.name = #_name,				\
-		.ops = &tegra_periph_clk_ops,		\
-		.hw = &tegra_##_name##_hw.hw,		\
-		.parent_names = _inputs,		\
-		.parents = _inputs##_p,			\
-		.num_parents = ARRAY_SIZE(_inputs),	\
-	};
-
-PERIPH_CLK(apbdma,	"tegra-apbdma",		NULL,	34,	0,	108000000, mux_pclk,			0);
-PERIPH_CLK(rtc,		"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET);
-PERIPH_CLK(timer,	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0);
-PERIPH_CLK(i2s1,	"tegra20-i2s.0",	NULL,	11,	0x100,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71);
-PERIPH_CLK(i2s2,	"tegra20-i2s.1",	NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71);
-PERIPH_CLK(spdif_out,	"spdif_out",		NULL,	10,	0x108,	100000000, mux_pllaout0_audio2x_pllp_clkm,	MUX | DIV_U71);
-PERIPH_CLK(spdif_in,	"spdif_in",		NULL,	10,	0x10c,	100000000, mux_pllp_pllc_pllm,		MUX | DIV_U71);
-PERIPH_CLK(pwm,		"tegra-pwm",		NULL,	17,	0x110,	432000000, mux_pllp_pllc_audio_clkm_clk32,	MUX | DIV_U71 | MUX_PWM);
-PERIPH_CLK(spi,		"spi",			NULL,	43,	0x114,	40000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(xio,		"xio",			NULL,	45,	0x120,	150000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(twc,		"twc",			NULL,	16,	0x12c,	150000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(sbc1,	"spi_tegra.0",		NULL,	41,	0x134,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(sbc2,	"spi_tegra.1",		NULL,	44,	0x118,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(sbc3,	"spi_tegra.2",		NULL,	46,	0x11c,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(sbc4,	"spi_tegra.3",		NULL,	68,	0x1b4,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(ide,		"ide",			NULL,	25,	0x144,	100000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* requires min voltage */
-PERIPH_CLK(ndflash,	"tegra_nand",		NULL,	13,	0x160,	164000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
-PERIPH_CLK(vfir,	"vfir",			NULL,	7,	0x168,	72000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(sdmmc1,	"sdhci-tegra.0",	NULL,	14,	0x150,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
-PERIPH_CLK(sdmmc2,	"sdhci-tegra.1",	NULL,	9,	0x154,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
-PERIPH_CLK(sdmmc3,	"sdhci-tegra.2",	NULL,	69,	0x1bc,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
-PERIPH_CLK(sdmmc4,	"sdhci-tegra.3",	NULL,	15,	0x164,	52000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
-PERIPH_CLK(vcp,		"tegra-avp",		"vcp",	29,	0,	250000000, mux_clk_m,			0);
-PERIPH_CLK(bsea,	"tegra-avp",		"bsea",	62,	0,	250000000, mux_clk_m,			0);
-PERIPH_CLK(bsev,	"tegra-aes",		"bsev",	63,	0,	250000000, mux_clk_m,			0);
-PERIPH_CLK(vde,		"tegra-avp",		"vde",	61,	0x1c8,	250000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage and process_id */
-PERIPH_CLK(csite,	"csite",		NULL,	73,	0x1d4,	144000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* max rate ??? */
-/* FIXME: what is la? */
-PERIPH_CLK(la,		"la",			NULL,	76,	0x1f8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(owr,		"tegra_w1",		NULL,	71,	0x1cc,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(nor,		"nor",			NULL,	42,	0x1d0,	92000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* requires min voltage */
-PERIPH_CLK(mipi,	"mipi",			NULL,	50,	0x174,	60000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
-PERIPH_CLK(i2c1,	"tegra-i2c.0",		"div-clk", 12,	0x124,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16);
-PERIPH_CLK(i2c2,	"tegra-i2c.1",		"div-clk", 54,	0x198,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16);
-PERIPH_CLK(i2c3,	"tegra-i2c.2",		"div-clk", 67,	0x1b8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16);
-PERIPH_CLK(dvc,		"tegra-i2c.3",		"div-clk", 47,	0x128,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U16);
-PERIPH_CLK(uarta,	"tegra-uart.0",		NULL,	6,	0x178,	600000000, mux_pllp_pllc_pllm_clkm,	MUX);
-PERIPH_CLK(uartb,	"tegra-uart.1",		NULL,	7,	0x17c,	600000000, mux_pllp_pllc_pllm_clkm,	MUX);
-PERIPH_CLK(uartc,	"tegra-uart.2",		NULL,	55,	0x1a0,	600000000, mux_pllp_pllc_pllm_clkm,	MUX);
-PERIPH_CLK(uartd,	"tegra-uart.3",		NULL,	65,	0x1c0,	600000000, mux_pllp_pllc_pllm_clkm,	MUX);
-PERIPH_CLK(uarte,	"tegra-uart.4",		NULL,	66,	0x1c4,	600000000, mux_pllp_pllc_pllm_clkm,	MUX);
-PERIPH_CLK(3d,		"3d",			NULL,	24,	0x158,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_MANUAL_RESET); /* scales with voltage and process_id */
-PERIPH_CLK(2d,		"2d",			NULL,	21,	0x15c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71); /* scales with voltage and process_id */
-PERIPH_CLK(vi,		"tegra_camera",		"vi",	20,	0x148,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71); /* scales with voltage and process_id */
-PERIPH_CLK(vi_sensor,	"tegra_camera",		"vi_sensor",	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET); /* scales with voltage and process_id */
-PERIPH_CLK(epp,		"epp",			NULL,	19,	0x16c,	300000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71); /* scales with voltage and process_id */
-PERIPH_CLK(mpe,		"mpe",			NULL,	60,	0x170,	250000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71); /* scales with voltage and process_id */
-PERIPH_CLK(host1x,	"host1x",		NULL,	28,	0x180,	166000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71); /* scales with voltage and process_id */
-PERIPH_CLK(cve,		"cve",			NULL,	49,	0x140,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
-PERIPH_CLK(tvo,		"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
-PERIPH_CLK(hdmi,	"hdmi",			NULL,	51,	0x18c,	600000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
-PERIPH_CLK(tvdac,	"tvdac",		NULL,	53,	0x194,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
-PERIPH_CLK(disp1,	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_plld_pllc_clkm,	MUX); /* scales with voltage and process_id */
-PERIPH_CLK(disp2,	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_plld_pllc_clkm,	MUX); /* scales with voltage and process_id */
-PERIPH_CLK(usbd,	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
-PERIPH_CLK(usb2,	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
-PERIPH_CLK(usb3,	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
-PERIPH_CLK(dsi,		"dsi",			NULL,	48,	0,	500000000, mux_plld,			0); /* scales with voltage */
-PERIPH_CLK(csi,		"tegra_camera",		"csi",	52,	0,	72000000,  mux_pllp_out3,		0);
-PERIPH_CLK(isp,		"tegra_camera",		"isp",	23,	0,	150000000, mux_clk_m,			0); /* same frequency as VI */
-PERIPH_CLK(csus,	"tegra_camera",		"csus",	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET);
-PERIPH_CLK(pex,		NULL,			"pex",  70,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET);
-PERIPH_CLK(afi,		NULL,			"afi",  72,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET);
-PERIPH_CLK(pcie_xclk,	NULL,		  "pcie_xclk",  74,     0,	26000000,  mux_clk_m,			PERIPH_MANUAL_RESET);
-
-static struct clk *tegra_list_clks[] = {
-	&tegra_apbdma,
-	&tegra_rtc,
-	&tegra_timer,
-	&tegra_i2s1,
-	&tegra_i2s2,
-	&tegra_spdif_out,
-	&tegra_spdif_in,
-	&tegra_pwm,
-	&tegra_spi,
-	&tegra_xio,
-	&tegra_twc,
-	&tegra_sbc1,
-	&tegra_sbc2,
-	&tegra_sbc3,
-	&tegra_sbc4,
-	&tegra_ide,
-	&tegra_ndflash,
-	&tegra_vfir,
-	&tegra_sdmmc1,
-	&tegra_sdmmc2,
-	&tegra_sdmmc3,
-	&tegra_sdmmc4,
-	&tegra_vcp,
-	&tegra_bsea,
-	&tegra_bsev,
-	&tegra_vde,
-	&tegra_csite,
-	&tegra_la,
-	&tegra_owr,
-	&tegra_nor,
-	&tegra_mipi,
-	&tegra_i2c1,
-	&tegra_i2c2,
-	&tegra_i2c3,
-	&tegra_dvc,
-	&tegra_uarta,
-	&tegra_uartb,
-	&tegra_uartc,
-	&tegra_uartd,
-	&tegra_uarte,
-	&tegra_3d,
-	&tegra_2d,
-	&tegra_vi,
-	&tegra_vi_sensor,
-	&tegra_epp,
-	&tegra_mpe,
-	&tegra_host1x,
-	&tegra_cve,
-	&tegra_tvo,
-	&tegra_hdmi,
-	&tegra_tvdac,
-	&tegra_disp1,
-	&tegra_disp2,
-	&tegra_usbd,
-	&tegra_usb2,
-	&tegra_usb3,
-	&tegra_dsi,
-	&tegra_csi,
-	&tegra_isp,
-	&tegra_csus,
-	&tegra_pex,
-	&tegra_afi,
-	&tegra_pcie_xclk,
-};
-
-#define CLK_DUPLICATE(_name, _dev, _con)	\
-	{					\
-		.name	= _name,		\
-		.lookup	= {			\
-			.dev_id	= _dev,		\
-			.con_id	= _con,		\
-		},				\
-	}
-
-/* Some clocks may be used by different drivers depending on the board
- * configuration.  List those here to register them twice in the clock lookup
- * table under two names.
- */
-static struct clk_duplicate tegra_clk_duplicates[] = {
-	CLK_DUPLICATE("uarta",	"serial8250.0",	NULL),
-	CLK_DUPLICATE("uartb",	"serial8250.1",	NULL),
-	CLK_DUPLICATE("uartc",	"serial8250.2",	NULL),
-	CLK_DUPLICATE("uartd",	"serial8250.3",	NULL),
-	CLK_DUPLICATE("uarte",	"serial8250.4",	NULL),
-	CLK_DUPLICATE("usbd",	"utmip-pad",	NULL),
-	CLK_DUPLICATE("usbd",	"tegra-ehci.0",	NULL),
-	CLK_DUPLICATE("usbd",	"tegra-otg",	NULL),
-	CLK_DUPLICATE("2d",	"tegra_grhost",	"gr2d"),
-	CLK_DUPLICATE("3d",	"tegra_grhost",	"gr3d"),
-	CLK_DUPLICATE("epp",	"tegra_grhost",	"epp"),
-	CLK_DUPLICATE("mpe",	"tegra_grhost",	"mpe"),
-	CLK_DUPLICATE("cop",	"tegra-avp",	"cop"),
-	CLK_DUPLICATE("vde",	"tegra-aes",	"vde"),
-	CLK_DUPLICATE("cclk",	NULL,		"cpu"),
-	CLK_DUPLICATE("twd",	"smp_twd",	NULL),
-	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.0", "fast-clk"),
-	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.1", "fast-clk"),
-	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"),
-	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"),
-	CLK_DUPLICATE("pll_p", "tegradc.0", "parent"),
-	CLK_DUPLICATE("pll_p", "tegradc.1", "parent"),
-	CLK_DUPLICATE("pll_d_out0", "hdmi", "parent"),
-};
-
-#define CLK(dev, con, ck)	\
-	{			\
-		.dev_id	= dev,	\
-		.con_id	= con,	\
-		.clk	= ck,	\
-	}
-
-static struct clk *tegra_ptr_clks[] = {
-	&tegra_clk_32k,
-	&tegra_pll_s,
-	&tegra_clk_m,
-	&tegra_pll_m,
-	&tegra_pll_m_out1,
-	&tegra_pll_c,
-	&tegra_pll_c_out1,
-	&tegra_pll_p,
-	&tegra_pll_p_out1,
-	&tegra_pll_p_out2,
-	&tegra_pll_p_out3,
-	&tegra_pll_p_out4,
-	&tegra_pll_a,
-	&tegra_pll_a_out0,
-	&tegra_pll_d,
-	&tegra_pll_d_out0,
-	&tegra_pll_u,
-	&tegra_pll_x,
-	&tegra_pll_e,
-	&tegra_cclk,
-	&tegra_clk_twd,
-	&tegra_sclk,
-	&tegra_hclk,
-	&tegra_pclk,
-	&tegra_clk_d,
-	&tegra_cdev1,
-	&tegra_cdev2,
-	&tegra_blink,
-	&tegra_cop,
-	&tegra_emc,
-};
-
-static void tegra2_init_one_clock(struct clk *c)
-{
-	struct clk_tegra *clk = to_clk_tegra(c->hw);
-	int ret;
-
-	ret = __clk_init(NULL, c);
-	if (ret)
-		pr_err("clk init failed %s\n", __clk_get_name(c));
-
-	INIT_LIST_HEAD(&clk->shared_bus_list);
-	if (!clk->lookup.dev_id && !clk->lookup.con_id)
-		clk->lookup.con_id = c->name;
-	clk->lookup.clk = c;
-	clkdev_add(&clk->lookup);
-	tegra_clk_add(c);
-}
-
-void __init tegra2_init_clocks(void)
-{
-	int i;
-	struct clk *c;
-
-	for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
-		tegra2_init_one_clock(tegra_ptr_clks[i]);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
-		tegra2_init_one_clock(tegra_list_clks[i]);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
-		c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
-		if (!c) {
-			pr_err("%s: Unknown duplicate clock %s\n", __func__,
-				tegra_clk_duplicates[i].name);
-			continue;
-		}
-
-		tegra_clk_duplicates[i].lookup.clk = c;
-		clkdev_add(&tegra_clk_duplicates[i].lookup);
-	}
-
-	init_audio_sync_clock_mux();
-	tegra20_cpu_car_ops_init();
-}
diff --git a/arch/arm/mach-tegra/tegra30_clocks.c b/arch/arm/mach-tegra/tegra30_clocks.c
deleted file mode 100644
index d714777..0000000
--- a/arch/arm/mach-tegra/tegra30_clocks.c
+++ /dev/null
@@ -1,2506 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra30_clocks.c
- *
- * Copyright (c) 2010-2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * 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 of the License.
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
-#include <linux/syscore_ops.h>
-
-#include <asm/clkdev.h>
-
-#include <mach/powergate.h>
-
-#include "clock.h"
-#include "fuse.h"
-#include "iomap.h"
-#include "tegra_cpu_car.h"
-
-#define USE_PLL_LOCK_BITS 0
-
-#define RST_DEVICES_L			0x004
-#define RST_DEVICES_H			0x008
-#define RST_DEVICES_U			0x00C
-#define RST_DEVICES_V			0x358
-#define RST_DEVICES_W			0x35C
-#define RST_DEVICES_SET_L		0x300
-#define RST_DEVICES_CLR_L		0x304
-#define RST_DEVICES_SET_V		0x430
-#define RST_DEVICES_CLR_V		0x434
-#define RST_DEVICES_NUM			5
-
-#define CLK_OUT_ENB_L			0x010
-#define CLK_OUT_ENB_H			0x014
-#define CLK_OUT_ENB_U			0x018
-#define CLK_OUT_ENB_V			0x360
-#define CLK_OUT_ENB_W			0x364
-#define CLK_OUT_ENB_SET_L		0x320
-#define CLK_OUT_ENB_CLR_L		0x324
-#define CLK_OUT_ENB_SET_V		0x440
-#define CLK_OUT_ENB_CLR_V		0x444
-#define CLK_OUT_ENB_NUM			5
-
-#define RST_DEVICES_V_SWR_CPULP_RST_DIS	(0x1 << 1)
-#define CLK_OUT_ENB_V_CLK_ENB_CPULP_EN	(0x1 << 1)
-
-#define PERIPH_CLK_TO_BIT(c)		(1 << (c->u.periph.clk_num % 32))
-#define PERIPH_CLK_TO_RST_REG(c)	\
-	periph_clk_to_reg((c), RST_DEVICES_L, RST_DEVICES_V, 4)
-#define PERIPH_CLK_TO_RST_SET_REG(c)	\
-	periph_clk_to_reg((c), RST_DEVICES_SET_L, RST_DEVICES_SET_V, 8)
-#define PERIPH_CLK_TO_RST_CLR_REG(c)	\
-	periph_clk_to_reg((c), RST_DEVICES_CLR_L, RST_DEVICES_CLR_V, 8)
-
-#define PERIPH_CLK_TO_ENB_REG(c)	\
-	periph_clk_to_reg((c), CLK_OUT_ENB_L, CLK_OUT_ENB_V, 4)
-#define PERIPH_CLK_TO_ENB_SET_REG(c)	\
-	periph_clk_to_reg((c), CLK_OUT_ENB_SET_L, CLK_OUT_ENB_SET_V, 8)
-#define PERIPH_CLK_TO_ENB_CLR_REG(c)	\
-	periph_clk_to_reg((c), CLK_OUT_ENB_CLR_L, CLK_OUT_ENB_CLR_V, 8)
-
-#define CLK_MASK_ARM			0x44
-#define MISC_CLK_ENB			0x48
-
-#define OSC_CTRL			0x50
-#define OSC_CTRL_OSC_FREQ_MASK		(0xF<<28)
-#define OSC_CTRL_OSC_FREQ_13MHZ		(0x0<<28)
-#define OSC_CTRL_OSC_FREQ_19_2MHZ	(0x4<<28)
-#define OSC_CTRL_OSC_FREQ_12MHZ		(0x8<<28)
-#define OSC_CTRL_OSC_FREQ_26MHZ		(0xC<<28)
-#define OSC_CTRL_OSC_FREQ_16_8MHZ	(0x1<<28)
-#define OSC_CTRL_OSC_FREQ_38_4MHZ	(0x5<<28)
-#define OSC_CTRL_OSC_FREQ_48MHZ		(0x9<<28)
-#define OSC_CTRL_MASK			(0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
-
-#define OSC_CTRL_PLL_REF_DIV_MASK	(3<<26)
-#define OSC_CTRL_PLL_REF_DIV_1		(0<<26)
-#define OSC_CTRL_PLL_REF_DIV_2		(1<<26)
-#define OSC_CTRL_PLL_REF_DIV_4		(2<<26)
-
-#define OSC_FREQ_DET			0x58
-#define OSC_FREQ_DET_TRIG		(1<<31)
-
-#define OSC_FREQ_DET_STATUS		0x5C
-#define OSC_FREQ_DET_BUSY		(1<<31)
-#define OSC_FREQ_DET_CNT_MASK		0xFFFF
-
-#define PERIPH_CLK_SOURCE_I2S1		0x100
-#define PERIPH_CLK_SOURCE_EMC		0x19c
-#define PERIPH_CLK_SOURCE_OSC		0x1fc
-#define PERIPH_CLK_SOURCE_NUM1 \
-	((PERIPH_CLK_SOURCE_OSC - PERIPH_CLK_SOURCE_I2S1) / 4)
-
-#define PERIPH_CLK_SOURCE_G3D2		0x3b0
-#define PERIPH_CLK_SOURCE_SE		0x42c
-#define PERIPH_CLK_SOURCE_NUM2 \
-	((PERIPH_CLK_SOURCE_SE - PERIPH_CLK_SOURCE_G3D2) / 4 + 1)
-
-#define AUDIO_DLY_CLK			0x49c
-#define AUDIO_SYNC_CLK_SPDIF		0x4b4
-#define PERIPH_CLK_SOURCE_NUM3 \
-	((AUDIO_SYNC_CLK_SPDIF - AUDIO_DLY_CLK) / 4 + 1)
-
-#define PERIPH_CLK_SOURCE_NUM		(PERIPH_CLK_SOURCE_NUM1 + \
-					 PERIPH_CLK_SOURCE_NUM2 + \
-					 PERIPH_CLK_SOURCE_NUM3)
-
-#define CPU_SOFTRST_CTRL		0x380
-
-#define PERIPH_CLK_SOURCE_DIVU71_MASK	0xFF
-#define PERIPH_CLK_SOURCE_DIVU16_MASK	0xFFFF
-#define PERIPH_CLK_SOURCE_DIV_SHIFT	0
-#define PERIPH_CLK_SOURCE_DIVIDLE_SHIFT	8
-#define PERIPH_CLK_SOURCE_DIVIDLE_VAL	50
-#define PERIPH_CLK_UART_DIV_ENB		(1<<24)
-#define PERIPH_CLK_VI_SEL_EX_SHIFT	24
-#define PERIPH_CLK_VI_SEL_EX_MASK	(0x3<<PERIPH_CLK_VI_SEL_EX_SHIFT)
-#define PERIPH_CLK_NAND_DIV_EX_ENB	(1<<8)
-#define PERIPH_CLK_DTV_POLARITY_INV	(1<<25)
-
-#define AUDIO_SYNC_SOURCE_MASK		0x0F
-#define AUDIO_SYNC_DISABLE_BIT		0x10
-#define AUDIO_SYNC_TAP_NIBBLE_SHIFT(c)	((c->reg_shift - 24) * 4)
-
-#define PLL_BASE			0x0
-#define PLL_BASE_BYPASS			(1<<31)
-#define PLL_BASE_ENABLE			(1<<30)
-#define PLL_BASE_REF_ENABLE		(1<<29)
-#define PLL_BASE_OVERRIDE		(1<<28)
-#define PLL_BASE_LOCK			(1<<27)
-#define PLL_BASE_DIVP_MASK		(0x7<<20)
-#define PLL_BASE_DIVP_SHIFT		20
-#define PLL_BASE_DIVN_MASK		(0x3FF<<8)
-#define PLL_BASE_DIVN_SHIFT		8
-#define PLL_BASE_DIVM_MASK		(0x1F)
-#define PLL_BASE_DIVM_SHIFT		0
-
-#define PLL_OUT_RATIO_MASK		(0xFF<<8)
-#define PLL_OUT_RATIO_SHIFT		8
-#define PLL_OUT_OVERRIDE		(1<<2)
-#define PLL_OUT_CLKEN			(1<<1)
-#define PLL_OUT_RESET_DISABLE		(1<<0)
-
-#define PLL_MISC(c)			\
-	(((c)->flags & PLL_ALT_MISC_REG) ? 0x4 : 0xc)
-#define PLL_MISC_LOCK_ENABLE(c)	\
-	(((c)->flags & (PLLU | PLLD)) ? (1<<22) : (1<<18))
-
-#define PLL_MISC_DCCON_SHIFT		20
-#define PLL_MISC_CPCON_SHIFT		8
-#define PLL_MISC_CPCON_MASK		(0xF<<PLL_MISC_CPCON_SHIFT)
-#define PLL_MISC_LFCON_SHIFT		4
-#define PLL_MISC_LFCON_MASK		(0xF<<PLL_MISC_LFCON_SHIFT)
-#define PLL_MISC_VCOCON_SHIFT		0
-#define PLL_MISC_VCOCON_MASK		(0xF<<PLL_MISC_VCOCON_SHIFT)
-#define PLLD_MISC_CLKENABLE		(1<<30)
-
-#define PLLU_BASE_POST_DIV		(1<<20)
-
-#define PLLD_BASE_DSIB_MUX_SHIFT	25
-#define PLLD_BASE_DSIB_MUX_MASK		(1<<PLLD_BASE_DSIB_MUX_SHIFT)
-#define PLLD_BASE_CSI_CLKENABLE		(1<<26)
-#define PLLD_MISC_DSI_CLKENABLE		(1<<30)
-#define PLLD_MISC_DIV_RST		(1<<23)
-#define PLLD_MISC_DCCON_SHIFT		12
-
-#define PLLDU_LFCON_SET_DIVN		600
-
-/* FIXME: OUT_OF_TABLE_CPCON per pll */
-#define OUT_OF_TABLE_CPCON		0x8
-
-#define SUPER_CLK_MUX			0x00
-#define SUPER_STATE_SHIFT		28
-#define SUPER_STATE_MASK		(0xF << SUPER_STATE_SHIFT)
-#define SUPER_STATE_STANDBY		(0x0 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_IDLE		(0x1 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_RUN			(0x2 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_IRQ			(0x3 << SUPER_STATE_SHIFT)
-#define SUPER_STATE_FIQ			(0x4 << SUPER_STATE_SHIFT)
-#define SUPER_LP_DIV2_BYPASS		(0x1 << 16)
-#define SUPER_SOURCE_MASK		0xF
-#define	SUPER_FIQ_SOURCE_SHIFT		12
-#define	SUPER_IRQ_SOURCE_SHIFT		8
-#define	SUPER_RUN_SOURCE_SHIFT		4
-#define	SUPER_IDLE_SOURCE_SHIFT		0
-
-#define SUPER_CLK_DIVIDER		0x04
-#define SUPER_CLOCK_DIV_U71_SHIFT	16
-#define SUPER_CLOCK_DIV_U71_MASK	(0xff << SUPER_CLOCK_DIV_U71_SHIFT)
-/* guarantees safe cpu backup */
-#define SUPER_CLOCK_DIV_U71_MIN		0x2
-
-#define BUS_CLK_DISABLE			(1<<3)
-#define BUS_CLK_DIV_MASK		0x3
-
-#define PMC_CTRL			0x0
- #define PMC_CTRL_BLINK_ENB		(1 << 7)
-
-#define PMC_DPD_PADS_ORIDE		0x1c
- #define PMC_DPD_PADS_ORIDE_BLINK_ENB	(1 << 20)
-
-#define PMC_BLINK_TIMER_DATA_ON_SHIFT	0
-#define PMC_BLINK_TIMER_DATA_ON_MASK	0x7fff
-#define PMC_BLINK_TIMER_ENB		(1 << 15)
-#define PMC_BLINK_TIMER_DATA_OFF_SHIFT	16
-#define PMC_BLINK_TIMER_DATA_OFF_MASK	0xffff
-
-#define PMC_PLLP_WB0_OVERRIDE				0xf8
-#define PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE		(1 << 12)
-
-#define UTMIP_PLL_CFG2					0x488
-#define UTMIP_PLL_CFG2_STABLE_COUNT(x)			(((x) & 0xfff) << 6)
-#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x)		(((x) & 0x3f) << 18)
-#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN	(1 << 0)
-#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN	(1 << 2)
-#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN	(1 << 4)
-
-#define UTMIP_PLL_CFG1					0x484
-#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x)		(((x) & 0x1f) << 27)
-#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x)		(((x) & 0xfff) << 0)
-#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN	(1 << 14)
-#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN	(1 << 12)
-#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN		(1 << 16)
-
-#define PLLE_BASE_CML_ENABLE		(1<<31)
-#define PLLE_BASE_ENABLE		(1<<30)
-#define PLLE_BASE_DIVCML_SHIFT		24
-#define PLLE_BASE_DIVCML_MASK		(0xf<<PLLE_BASE_DIVCML_SHIFT)
-#define PLLE_BASE_DIVP_SHIFT		16
-#define PLLE_BASE_DIVP_MASK		(0x3f<<PLLE_BASE_DIVP_SHIFT)
-#define PLLE_BASE_DIVN_SHIFT		8
-#define PLLE_BASE_DIVN_MASK		(0xFF<<PLLE_BASE_DIVN_SHIFT)
-#define PLLE_BASE_DIVM_SHIFT		0
-#define PLLE_BASE_DIVM_MASK		(0xFF<<PLLE_BASE_DIVM_SHIFT)
-#define PLLE_BASE_DIV_MASK		\
-	(PLLE_BASE_DIVCML_MASK | PLLE_BASE_DIVP_MASK | \
-	 PLLE_BASE_DIVN_MASK | PLLE_BASE_DIVM_MASK)
-#define PLLE_BASE_DIV(m, n, p, cml)		\
-	 (((cml)<<PLLE_BASE_DIVCML_SHIFT) | ((p)<<PLLE_BASE_DIVP_SHIFT) | \
-	  ((n)<<PLLE_BASE_DIVN_SHIFT) | ((m)<<PLLE_BASE_DIVM_SHIFT))
-
-#define PLLE_MISC_SETUP_BASE_SHIFT	16
-#define PLLE_MISC_SETUP_BASE_MASK	(0xFFFF<<PLLE_MISC_SETUP_BASE_SHIFT)
-#define PLLE_MISC_READY			(1<<15)
-#define PLLE_MISC_LOCK			(1<<11)
-#define PLLE_MISC_LOCK_ENABLE		(1<<9)
-#define PLLE_MISC_SETUP_EX_SHIFT	2
-#define PLLE_MISC_SETUP_EX_MASK		(0x3<<PLLE_MISC_SETUP_EX_SHIFT)
-#define PLLE_MISC_SETUP_MASK		\
-	  (PLLE_MISC_SETUP_BASE_MASK | PLLE_MISC_SETUP_EX_MASK)
-#define PLLE_MISC_SETUP_VALUE		\
-	  ((0x7<<PLLE_MISC_SETUP_BASE_SHIFT) | (0x0<<PLLE_MISC_SETUP_EX_SHIFT))
-
-#define PLLE_SS_CTRL			0x68
-#define	PLLE_SS_INCINTRV_SHIFT		24
-#define	PLLE_SS_INCINTRV_MASK		(0x3f<<PLLE_SS_INCINTRV_SHIFT)
-#define	PLLE_SS_INC_SHIFT		16
-#define	PLLE_SS_INC_MASK		(0xff<<PLLE_SS_INC_SHIFT)
-#define	PLLE_SS_MAX_SHIFT		0
-#define	PLLE_SS_MAX_MASK		(0x1ff<<PLLE_SS_MAX_SHIFT)
-#define PLLE_SS_COEFFICIENTS_MASK	\
-	(PLLE_SS_INCINTRV_MASK | PLLE_SS_INC_MASK | PLLE_SS_MAX_MASK)
-#define PLLE_SS_COEFFICIENTS_12MHZ	\
-	((0x18<<PLLE_SS_INCINTRV_SHIFT) | (0x1<<PLLE_SS_INC_SHIFT) | \
-	 (0x24<<PLLE_SS_MAX_SHIFT))
-#define PLLE_SS_DISABLE			((1<<12) | (1<<11) | (1<<10))
-
-#define PLLE_AUX			0x48c
-#define PLLE_AUX_PLLP_SEL		(1<<2)
-#define PLLE_AUX_CML_SATA_ENABLE	(1<<1)
-#define PLLE_AUX_CML_PCIE_ENABLE	(1<<0)
-
-#define	PMC_SATA_PWRGT			0x1ac
-#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE	(1<<5)
-#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL	(1<<4)
-
-#define ROUND_DIVIDER_UP	0
-#define ROUND_DIVIDER_DOWN	1
-
-/* FIXME: recommended safety delay after lock is detected */
-#define PLL_POST_LOCK_DELAY		100
-
-/* Tegra CPU clock and reset control regs */
-#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX		0x4c
-#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET	0x340
-#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR	0x344
-#define TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR	0x34c
-#define TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS	0x470
-
-#define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
-#define CPU_RESET(cpu)	(0x1111ul << (cpu))
-
-#define CLK_RESET_CCLK_BURST	0x20
-#define CLK_RESET_CCLK_DIVIDER  0x24
-#define CLK_RESET_PLLX_BASE	0xe0
-#define CLK_RESET_PLLX_MISC	0xe4
-
-#define CLK_RESET_SOURCE_CSITE	0x1d4
-
-#define CLK_RESET_CCLK_BURST_POLICY_SHIFT	28
-#define CLK_RESET_CCLK_RUN_POLICY_SHIFT		4
-#define CLK_RESET_CCLK_IDLE_POLICY_SHIFT	0
-#define CLK_RESET_CCLK_IDLE_POLICY		1
-#define CLK_RESET_CCLK_RUN_POLICY		2
-#define CLK_RESET_CCLK_BURST_POLICY_PLLX	8
-
-#ifdef CONFIG_PM_SLEEP
-static struct cpu_clk_suspend_context {
-	u32 pllx_misc;
-	u32 pllx_base;
-
-	u32 cpu_burst;
-	u32 clk_csite_src;
-	u32 cclk_divider;
-} tegra30_cpu_clk_sctx;
-#endif
-
-/**
-* Structure defining the fields for USB UTMI clocks Parameters.
-*/
-struct utmi_clk_param {
-	/* Oscillator Frequency in KHz */
-	u32 osc_frequency;
-	/* UTMIP PLL Enable Delay Count  */
-	u8 enable_delay_count;
-	/* UTMIP PLL Stable count */
-	u8 stable_count;
-	/*  UTMIP PLL Active delay count */
-	u8 active_delay_count;
-	/* UTMIP PLL Xtal frequency count */
-	u8 xtal_freq_count;
-};
-
-static const struct utmi_clk_param utmi_parameters[] = {
-	{
-		.osc_frequency = 13000000,
-		.enable_delay_count = 0x02,
-		.stable_count = 0x33,
-		.active_delay_count = 0x05,
-		.xtal_freq_count = 0x7F
-	},
-	{
-		.osc_frequency = 19200000,
-		.enable_delay_count = 0x03,
-		.stable_count = 0x4B,
-		.active_delay_count = 0x06,
-		.xtal_freq_count = 0xBB},
-	{
-		.osc_frequency = 12000000,
-		.enable_delay_count = 0x02,
-		.stable_count = 0x2F,
-		.active_delay_count = 0x04,
-		.xtal_freq_count = 0x76
-	},
-	{
-		.osc_frequency = 26000000,
-		.enable_delay_count = 0x04,
-		.stable_count = 0x66,
-		.active_delay_count = 0x09,
-		.xtal_freq_count = 0xFE
-	},
-	{
-		.osc_frequency = 16800000,
-		.enable_delay_count = 0x03,
-		.stable_count = 0x41,
-		.active_delay_count = 0x0A,
-		.xtal_freq_count = 0xA4
-	},
-};
-
-static void __iomem *reg_clk_base = IO_ADDRESS(TEGRA_CLK_RESET_BASE);
-static void __iomem *reg_pmc_base = IO_ADDRESS(TEGRA_PMC_BASE);
-static void __iomem *misc_gp_hidrev_base = IO_ADDRESS(TEGRA_APB_MISC_BASE);
-
-#define MISC_GP_HIDREV                  0x804
-
-/*
- * Some peripheral clocks share an enable bit, so refcount the enable bits
- * in registers CLK_ENABLE_L, ... CLK_ENABLE_W
- */
-static int tegra_periph_clk_enable_refcount[CLK_OUT_ENB_NUM * 32];
-
-#define clk_writel(value, reg) \
-	__raw_writel(value, reg_clk_base + (reg))
-#define clk_readl(reg) \
-	__raw_readl(reg_clk_base + (reg))
-#define pmc_writel(value, reg) \
-	__raw_writel(value, reg_pmc_base + (reg))
-#define pmc_readl(reg) \
-	__raw_readl(reg_pmc_base + (reg))
-#define chipid_readl() \
-	__raw_readl(misc_gp_hidrev_base + MISC_GP_HIDREV)
-
-#define clk_writel_delay(value, reg)					\
-	do {								\
-		__raw_writel((value), reg_clk_base + (reg));	\
-		udelay(2);						\
-	} while (0)
-
-static inline int clk_set_div(struct clk_tegra *c, u32 n)
-{
-	struct clk *clk = c->hw.clk;
-
-	return clk_set_rate(clk,
-			(__clk_get_rate(__clk_get_parent(clk)) + n - 1) / n);
-}
-
-static inline u32 periph_clk_to_reg(
-	struct clk_tegra *c, u32 reg_L, u32 reg_V, int offs)
-{
-	u32 reg = c->u.periph.clk_num / 32;
-	BUG_ON(reg >= RST_DEVICES_NUM);
-	if (reg < 3)
-		reg = reg_L + (reg * offs);
-	else
-		reg = reg_V + ((reg - 3) * offs);
-	return reg;
-}
-
-static unsigned long clk_measure_input_freq(void)
-{
-	u32 clock_autodetect;
-	clk_writel(OSC_FREQ_DET_TRIG | 1, OSC_FREQ_DET);
-	do {} while (clk_readl(OSC_FREQ_DET_STATUS) & OSC_FREQ_DET_BUSY);
-	clock_autodetect = clk_readl(OSC_FREQ_DET_STATUS);
-	if (clock_autodetect >= 732 - 3 && clock_autodetect <= 732 + 3) {
-		return 12000000;
-	} else if (clock_autodetect >= 794 - 3 && clock_autodetect <= 794 + 3) {
-		return 13000000;
-	} else if (clock_autodetect >= 1172 - 3 && clock_autodetect <= 1172 + 3) {
-		return 19200000;
-	} else if (clock_autodetect >= 1587 - 3 && clock_autodetect <= 1587 + 3) {
-		return 26000000;
-	} else if (clock_autodetect >= 1025 - 3 && clock_autodetect <= 1025 + 3) {
-		return 16800000;
-	} else if (clock_autodetect >= 2344 - 3 && clock_autodetect <= 2344 + 3) {
-		return 38400000;
-	} else if (clock_autodetect >= 2928 - 3 && clock_autodetect <= 2928 + 3) {
-		return 48000000;
-	} else {
-		pr_err("%s: Unexpected clock autodetect value %d", __func__,
-			clock_autodetect);
-		BUG();
-		return 0;
-	}
-}
-
-static int clk_div71_get_divider(unsigned long parent_rate, unsigned long rate,
-				 u32 flags, u32 round_mode)
-{
-	s64 divider_u71 = parent_rate;
-	if (!rate)
-		return -EINVAL;
-
-	if (!(flags & DIV_U71_INT))
-		divider_u71 *= 2;
-	if (round_mode == ROUND_DIVIDER_UP)
-		divider_u71 += rate - 1;
-	do_div(divider_u71, rate);
-	if (flags & DIV_U71_INT)
-		divider_u71 *= 2;
-
-	if (divider_u71 - 2 < 0)
-		return 0;
-
-	if (divider_u71 - 2 > 255)
-		return -EINVAL;
-
-	return divider_u71 - 2;
-}
-
-static int clk_div16_get_divider(unsigned long parent_rate, unsigned long rate)
-{
-	s64 divider_u16;
-
-	divider_u16 = parent_rate;
-	if (!rate)
-		return -EINVAL;
-	divider_u16 += rate - 1;
-	do_div(divider_u16, rate);
-
-	if (divider_u16 - 1 < 0)
-		return 0;
-
-	if (divider_u16 - 1 > 0xFFFF)
-		return -EINVAL;
-
-	return divider_u16 - 1;
-}
-
-static unsigned long tegra30_clk_fixed_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	return to_clk_tegra(hw)->fixed_rate;
-}
-
-struct clk_ops tegra30_clk_32k_ops = {
-	.recalc_rate = tegra30_clk_fixed_recalc_rate,
-};
-
-/* clk_m functions */
-static unsigned long tegra30_clk_m_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	if (!to_clk_tegra(hw)->fixed_rate)
-		to_clk_tegra(hw)->fixed_rate = clk_measure_input_freq();
-	return to_clk_tegra(hw)->fixed_rate;
-}
-
-static void tegra30_clk_m_init(struct clk_hw *hw)
-{
-	u32 osc_ctrl = clk_readl(OSC_CTRL);
-	u32 auto_clock_control = osc_ctrl & ~OSC_CTRL_OSC_FREQ_MASK;
-	u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK;
-
-	switch (to_clk_tegra(hw)->fixed_rate) {
-	case 12000000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_12MHZ;
-		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
-		break;
-	case 13000000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_13MHZ;
-		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
-		break;
-	case 19200000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_19_2MHZ;
-		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
-		break;
-	case 26000000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_26MHZ;
-		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
-		break;
-	case 16800000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_16_8MHZ;
-		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
-		break;
-	case 38400000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_38_4MHZ;
-		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_2);
-		break;
-	case 48000000:
-		auto_clock_control |= OSC_CTRL_OSC_FREQ_48MHZ;
-		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_4);
-		break;
-	default:
-		pr_err("%s: Unexpected clock rate %ld", __func__,
-				to_clk_tegra(hw)->fixed_rate);
-		BUG();
-	}
-	clk_writel(auto_clock_control, OSC_CTRL);
-}
-
-struct clk_ops tegra30_clk_m_ops = {
-	.init = tegra30_clk_m_init,
-	.recalc_rate = tegra30_clk_m_recalc_rate,
-};
-
-static unsigned long tegra30_clk_m_div_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = parent_rate;
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-
-	return rate;
-}
-
-struct clk_ops tegra_clk_m_div_ops = {
-	.recalc_rate = tegra30_clk_m_div_recalc_rate,
-};
-
-/* PLL reference divider functions */
-static unsigned long tegra30_pll_ref_recalc_rate(struct clk_hw *hw,
-			unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long rate = parent_rate;
-	u32 pll_ref_div = clk_readl(OSC_CTRL) & OSC_CTRL_PLL_REF_DIV_MASK;
-
-	switch (pll_ref_div) {
-	case OSC_CTRL_PLL_REF_DIV_1:
-		c->div = 1;
-		break;
-	case OSC_CTRL_PLL_REF_DIV_2:
-		c->div = 2;
-		break;
-	case OSC_CTRL_PLL_REF_DIV_4:
-		c->div = 4;
-		break;
-	default:
-		pr_err("%s: Invalid pll ref divider %d", __func__, pll_ref_div);
-		BUG();
-	}
-	c->mul = 1;
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-
-	return rate;
-}
-
-struct clk_ops tegra_pll_ref_ops = {
-	.recalc_rate = tegra30_pll_ref_recalc_rate,
-};
-
-/* super clock functions */
-/* "super clocks" on tegra30 have two-stage muxes, fractional 7.1 divider and
- * clock skipping super divider.  We will ignore the clock skipping divider,
- * since we can't lower the voltage when using the clock skip, but we can if
- * we lower the PLL frequency. We will use 7.1 divider for CPU super-clock
- * only when its parent is a fixed rate PLL, since we can't change PLL rate
- * in this case.
- */
-static void tegra30_super_clk_init(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	struct clk_tegra *p =
-			to_clk_tegra(__clk_get_hw(__clk_get_parent(hw->clk)));
-
-	c->state = ON;
-	if (c->flags & DIV_U71) {
-		/* Init safe 7.1 divider value (does not affect PLLX path) */
-		clk_writel(SUPER_CLOCK_DIV_U71_MIN << SUPER_CLOCK_DIV_U71_SHIFT,
-			   c->reg + SUPER_CLK_DIVIDER);
-		c->mul = 2;
-		c->div = 2;
-		if (!(p->flags & PLLX))
-			c->div += SUPER_CLOCK_DIV_U71_MIN;
-	} else
-		clk_writel(0, c->reg + SUPER_CLK_DIVIDER);
-}
-
-static u8 tegra30_super_clk_get_parent(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	int source;
-	int shift;
-
-	val = clk_readl(c->reg + SUPER_CLK_MUX);
-	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
-		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
-	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
-		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
-	source = (val >> shift) & SUPER_SOURCE_MASK;
-	if (c->flags & DIV_2)
-		source |= val & SUPER_LP_DIV2_BYPASS;
-
-	return source;
-}
-
-static int tegra30_super_clk_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	struct clk_tegra *p =
-			to_clk_tegra(__clk_get_hw(clk_get_parent(hw->clk)));
-	u32 val;
-	int shift;
-
-	val = clk_readl(c->reg + SUPER_CLK_MUX);
-	BUG_ON(((val & SUPER_STATE_MASK) != SUPER_STATE_RUN) &&
-		((val & SUPER_STATE_MASK) != SUPER_STATE_IDLE));
-	shift = ((val & SUPER_STATE_MASK) == SUPER_STATE_IDLE) ?
-		SUPER_IDLE_SOURCE_SHIFT : SUPER_RUN_SOURCE_SHIFT;
-
-	/* For LP mode super-clock switch between PLLX direct
-	   and divided-by-2 outputs is allowed only when other
-	   than PLLX clock source is current parent */
-	if ((c->flags & DIV_2) && (p->flags & PLLX) &&
-	    ((index ^ val) & SUPER_LP_DIV2_BYPASS)) {
-		if (p->flags & PLLX)
-			return -EINVAL;
-		val ^= SUPER_LP_DIV2_BYPASS;
-		clk_writel_delay(val, c->reg);
-	}
-	val &= ~(SUPER_SOURCE_MASK << shift);
-	val |= (index & SUPER_SOURCE_MASK) << shift;
-
-	/* 7.1 divider for CPU super-clock does not affect
-	   PLLX path */
-	if (c->flags & DIV_U71) {
-		u32 div = 0;
-		if (!(p->flags & PLLX)) {
-			div = clk_readl(c->reg +
-					SUPER_CLK_DIVIDER);
-			div &= SUPER_CLOCK_DIV_U71_MASK;
-			div >>= SUPER_CLOCK_DIV_U71_SHIFT;
-		}
-		c->div = div + 2;
-		c->mul = 2;
-	}
-	clk_writel_delay(val, c->reg);
-
-	return 0;
-}
-
-/*
- * Do not use super clocks "skippers", since dividing using a clock skipper
- * does not allow the voltage to be scaled down. Instead adjust the rate of
- * the parent clock. This requires that the parent of a super clock have no
- * other children, otherwise the rate will change underneath the other
- * children. Special case: if fixed rate PLL is CPU super clock parent the
- * rate of this PLL can't be changed, and it has many other children. In
- * this case use 7.1 fractional divider to adjust the super clock rate.
- */
-static int tegra30_super_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	struct clk *parent = __clk_get_parent(hw->clk);
-	struct clk_tegra *cparent = to_clk_tegra(__clk_get_hw(parent));
-
-	if ((c->flags & DIV_U71) && (cparent->flags & PLL_FIXED)) {
-		int div = clk_div71_get_divider(parent_rate,
-					rate, c->flags, ROUND_DIVIDER_DOWN);
-		div = max(div, SUPER_CLOCK_DIV_U71_MIN);
-
-		clk_writel(div << SUPER_CLOCK_DIV_U71_SHIFT,
-			   c->reg + SUPER_CLK_DIVIDER);
-		c->div = div + 2;
-		c->mul = 2;
-		return 0;
-	}
-	return 0;
-}
-
-static unsigned long tegra30_super_clk_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = parent_rate;
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-
-	return rate;
-}
-
-static long tegra30_super_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	struct clk *parent = __clk_get_parent(hw->clk);
-	struct clk_tegra *cparent = to_clk_tegra(__clk_get_hw(parent));
-	int mul = 2;
-	int div;
-
-	if ((c->flags & DIV_U71) && (cparent->flags & PLL_FIXED)) {
-		div = clk_div71_get_divider(*prate,
-				rate, c->flags, ROUND_DIVIDER_DOWN);
-		div = max(div, SUPER_CLOCK_DIV_U71_MIN) + 2;
-		rate = *prate * mul;
-		rate += div - 1; /* round up */
-		do_div(rate, c->div);
-
-		return rate;
-	}
-	return *prate;
-}
-
-struct clk_ops tegra30_super_ops = {
-	.init = tegra30_super_clk_init,
-	.set_parent = tegra30_super_clk_set_parent,
-	.get_parent = tegra30_super_clk_get_parent,
-	.recalc_rate = tegra30_super_clk_recalc_rate,
-	.round_rate = tegra30_super_clk_round_rate,
-	.set_rate = tegra30_super_clk_set_rate,
-};
-
-static unsigned long tegra30_twd_clk_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = parent_rate;
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-
-	return rate;
-}
-
-struct clk_ops tegra30_twd_ops = {
-	.recalc_rate = tegra30_twd_clk_recalc_rate,
-};
-
-/* bus clock functions */
-static int tegra30_bus_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-
-	c->state = ((val >> c->reg_shift) & BUS_CLK_DISABLE) ? OFF : ON;
-	return c->state;
-}
-
-static int tegra30_bus_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	val = clk_readl(c->reg);
-	val &= ~(BUS_CLK_DISABLE << c->reg_shift);
-	clk_writel(val, c->reg);
-
-	return 0;
-}
-
-static void tegra30_bus_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	val = clk_readl(c->reg);
-	val |= BUS_CLK_DISABLE << c->reg_shift;
-	clk_writel(val, c->reg);
-}
-
-static unsigned long tegra30_bus_clk_recalc_rate(struct clk_hw *hw,
-			unsigned long prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-	u64 rate = prate;
-
-	c->div = ((val >> c->reg_shift) & BUS_CLK_DIV_MASK) + 1;
-	c->mul = 1;
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-	return rate;
-}
-
-static int tegra30_bus_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	int ret = -EINVAL;
-	u32 val;
-	int i;
-
-	val = clk_readl(c->reg);
-	for (i = 1; i <= 4; i++) {
-		if (rate == parent_rate / i) {
-			val &= ~(BUS_CLK_DIV_MASK << c->reg_shift);
-			val |= (i - 1) << c->reg_shift;
-			clk_writel(val, c->reg);
-			c->div = i;
-			c->mul = 1;
-			ret = 0;
-			break;
-		}
-	}
-
-	return ret;
-}
-
-static long tegra30_bus_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	unsigned long parent_rate = *prate;
-	s64 divider;
-
-	if (rate >= parent_rate)
-		return parent_rate;
-
-	divider = parent_rate;
-	divider += rate - 1;
-	do_div(divider, rate);
-
-	if (divider < 0)
-		return divider;
-
-	if (divider > 4)
-		divider = 4;
-	do_div(parent_rate, divider);
-
-	return parent_rate;
-}
-
-struct clk_ops tegra30_bus_ops = {
-	.is_enabled = tegra30_bus_clk_is_enabled,
-	.enable = tegra30_bus_clk_enable,
-	.disable = tegra30_bus_clk_disable,
-	.set_rate = tegra30_bus_clk_set_rate,
-	.round_rate = tegra30_bus_clk_round_rate,
-	.recalc_rate = tegra30_bus_clk_recalc_rate,
-};
-
-/* Blink output functions */
-static int tegra30_blink_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	val = pmc_readl(PMC_CTRL);
-	c->state = (val & PMC_CTRL_BLINK_ENB) ? ON : OFF;
-	return c->state;
-}
-
-static int tegra30_blink_clk_enable(struct clk_hw *hw)
-{
-	u32 val;
-
-	val = pmc_readl(PMC_DPD_PADS_ORIDE);
-	pmc_writel(val | PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
-
-	val = pmc_readl(PMC_CTRL);
-	pmc_writel(val | PMC_CTRL_BLINK_ENB, PMC_CTRL);
-
-	return 0;
-}
-
-static void tegra30_blink_clk_disable(struct clk_hw *hw)
-{
-	u32 val;
-
-	val = pmc_readl(PMC_CTRL);
-	pmc_writel(val & ~PMC_CTRL_BLINK_ENB, PMC_CTRL);
-
-	val = pmc_readl(PMC_DPD_PADS_ORIDE);
-	pmc_writel(val & ~PMC_DPD_PADS_ORIDE_BLINK_ENB, PMC_DPD_PADS_ORIDE);
-}
-
-static int tegra30_blink_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	if (rate >= parent_rate) {
-		c->div = 1;
-		pmc_writel(0, c->reg);
-	} else {
-		unsigned int on_off;
-		u32 val;
-
-		on_off = DIV_ROUND_UP(parent_rate / 8, rate);
-		c->div = on_off * 8;
-
-		val = (on_off & PMC_BLINK_TIMER_DATA_ON_MASK) <<
-			PMC_BLINK_TIMER_DATA_ON_SHIFT;
-		on_off &= PMC_BLINK_TIMER_DATA_OFF_MASK;
-		on_off <<= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
-		val |= on_off;
-		val |= PMC_BLINK_TIMER_ENB;
-		pmc_writel(val, c->reg);
-	}
-
-	return 0;
-}
-
-static unsigned long tegra30_blink_clk_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = parent_rate;
-	u32 val;
-	u32 mul;
-	u32 div;
-	u32 on_off;
-
-	mul = 1;
-	val = pmc_readl(c->reg);
-
-	if (val & PMC_BLINK_TIMER_ENB) {
-		on_off = (val >> PMC_BLINK_TIMER_DATA_ON_SHIFT) &
-			PMC_BLINK_TIMER_DATA_ON_MASK;
-		val >>= PMC_BLINK_TIMER_DATA_OFF_SHIFT;
-		val &= PMC_BLINK_TIMER_DATA_OFF_MASK;
-		on_off += val;
-		/* each tick in the blink timer is 4 32KHz clocks */
-		div = on_off * 4;
-	} else {
-		div = 1;
-	}
-
-	if (mul != 0 && div != 0) {
-		rate *= mul;
-		rate += div - 1; /* round up */
-		do_div(rate, div);
-	}
-	return rate;
-}
-
-static long tegra30_blink_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	int div;
-	int mul;
-	long round_rate = *prate;
-
-	mul = 1;
-
-	if (rate >= *prate) {
-		div = 1;
-	} else {
-		div = DIV_ROUND_UP(*prate / 8, rate);
-		div *= 8;
-	}
-
-	round_rate *= mul;
-	round_rate += div - 1;
-	do_div(round_rate, div);
-
-	return round_rate;
-}
-
-struct clk_ops tegra30_blink_clk_ops = {
-	.is_enabled = tegra30_blink_clk_is_enabled,
-	.enable = tegra30_blink_clk_enable,
-	.disable = tegra30_blink_clk_disable,
-	.recalc_rate = tegra30_blink_clk_recalc_rate,
-	.round_rate = tegra30_blink_clk_round_rate,
-	.set_rate = tegra30_blink_clk_set_rate,
-};
-
-static void tegra30_utmi_param_configure(struct clk_hw *hw)
-{
-	unsigned long main_rate =
-		__clk_get_rate(__clk_get_parent(__clk_get_parent(hw->clk)));
-	u32 reg;
-	int i;
-
-	for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
-		if (main_rate == utmi_parameters[i].osc_frequency)
-			break;
-	}
-
-	if (i >= ARRAY_SIZE(utmi_parameters)) {
-		pr_err("%s: Unexpected main rate %lu\n", __func__, main_rate);
-		return;
-	}
-
-	reg = clk_readl(UTMIP_PLL_CFG2);
-
-	/* Program UTMIP PLL stable and active counts */
-	/* [FIXME] arclk_rst.h says WRONG! This should be 1ms -> 0x50 Check! */
-	reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
-	reg |= UTMIP_PLL_CFG2_STABLE_COUNT(
-			utmi_parameters[i].stable_count);
-
-	reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
-
-	reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(
-			utmi_parameters[i].active_delay_count);
-
-	/* Remove power downs from UTMIP PLL control bits */
-	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
-	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
-	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
-
-	clk_writel(reg, UTMIP_PLL_CFG2);
-
-	/* Program UTMIP PLL delay and oscillator frequency counts */
-	reg = clk_readl(UTMIP_PLL_CFG1);
-	reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
-
-	reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(
-		utmi_parameters[i].enable_delay_count);
-
-	reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
-	reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(
-		utmi_parameters[i].xtal_freq_count);
-
-	/* Remove power downs from UTMIP PLL control bits */
-	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
-	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
-	reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
-
-	clk_writel(reg, UTMIP_PLL_CFG1);
-}
-
-/* PLL Functions */
-static int tegra30_pll_clk_wait_for_lock(struct clk_tegra *c, u32 lock_reg,
-					 u32 lock_bit)
-{
-	int ret = 0;
-
-#if USE_PLL_LOCK_BITS
-	int i;
-	for (i = 0; i < c->u.pll.lock_delay; i++) {
-		if (clk_readl(lock_reg) & lock_bit) {
-			udelay(PLL_POST_LOCK_DELAY);
-			return 0;
-		}
-		udelay(2);	/* timeout = 2 * lock time */
-	}
-	pr_err("Timed out waiting for lock bit on pll %s",
-					__clk_get_name(hw->clk));
-	ret = -1;
-#else
-	udelay(c->u.pll.lock_delay);
-#endif
-	return ret;
-}
-
-static int tegra30_pll_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg + PLL_BASE);
-
-	c->state = (val & PLL_BASE_ENABLE) ? ON : OFF;
-	return c->state;
-}
-
-static void tegra30_pll_clk_init(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	if (c->flags & PLLU)
-		tegra30_utmi_param_configure(hw);
-}
-
-static int tegra30_pll_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
-
-#if USE_PLL_LOCK_BITS
-	val = clk_readl(c->reg + PLL_MISC(c));
-	val |= PLL_MISC_LOCK_ENABLE(c);
-	clk_writel(val, c->reg + PLL_MISC(c));
-#endif
-	val = clk_readl(c->reg + PLL_BASE);
-	val &= ~PLL_BASE_BYPASS;
-	val |= PLL_BASE_ENABLE;
-	clk_writel(val, c->reg + PLL_BASE);
-
-	if (c->flags & PLLM) {
-		val = pmc_readl(PMC_PLLP_WB0_OVERRIDE);
-		val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
-		pmc_writel(val, PMC_PLLP_WB0_OVERRIDE);
-	}
-
-	tegra30_pll_clk_wait_for_lock(c, c->reg + PLL_BASE, PLL_BASE_LOCK);
-
-	return 0;
-}
-
-static void tegra30_pll_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	pr_debug("%s on clock %s\n", __func__, __clk_get_name(hw->clk));
-
-	val = clk_readl(c->reg);
-	val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
-	clk_writel(val, c->reg);
-
-	if (c->flags & PLLM) {
-		val = pmc_readl(PMC_PLLP_WB0_OVERRIDE);
-		val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
-		pmc_writel(val, PMC_PLLP_WB0_OVERRIDE);
-	}
-}
-
-static int tegra30_pll_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val, p_div, old_base;
-	unsigned long input_rate;
-	const struct clk_pll_freq_table *sel;
-	struct clk_pll_freq_table cfg;
-
-	if (c->flags & PLL_FIXED) {
-		int ret = 0;
-		if (rate != c->u.pll.fixed_rate) {
-			pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
-			       __func__, __clk_get_name(hw->clk),
-				c->u.pll.fixed_rate, rate);
-			ret = -EINVAL;
-		}
-		return ret;
-	}
-
-	if (c->flags & PLLM) {
-		if (rate != __clk_get_rate(hw->clk)) {
-			pr_err("%s: Can not change memory %s rate in flight\n",
-				__func__, __clk_get_name(hw->clk));
-			return -EINVAL;
-		}
-	}
-
-	p_div = 0;
-	input_rate = parent_rate;
-
-	/* Check if the target rate is tabulated */
-	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
-		if (sel->input_rate == input_rate && sel->output_rate == rate) {
-			if (c->flags & PLLU) {
-				BUG_ON(sel->p < 1 || sel->p > 2);
-				if (sel->p == 1)
-					p_div = PLLU_BASE_POST_DIV;
-			} else {
-				BUG_ON(sel->p < 1);
-				for (val = sel->p; val > 1; val >>= 1)
-					p_div++;
-				p_div <<= PLL_BASE_DIVP_SHIFT;
-			}
-			break;
-		}
-	}
-
-	/* Configure out-of-table rate */
-	if (sel->input_rate == 0) {
-		unsigned long cfreq;
-		BUG_ON(c->flags & PLLU);
-		sel = &cfg;
-
-		switch (input_rate) {
-		case 12000000:
-		case 26000000:
-			cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000;
-			break;
-		case 13000000:
-			cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000;
-			break;
-		case 16800000:
-		case 19200000:
-			cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000;
-			break;
-		default:
-			pr_err("%s: Unexpected reference rate %lu\n",
-			       __func__, input_rate);
-			BUG();
-		}
-
-		/* Raise VCO to guarantee 0.5% accuracy */
-		for (cfg.output_rate = rate; cfg.output_rate < 200 * cfreq;
-		      cfg.output_rate <<= 1)
-			p_div++;
-
-		cfg.p = 0x1 << p_div;
-		cfg.m = input_rate / cfreq;
-		cfg.n = cfg.output_rate / cfreq;
-		cfg.cpcon = OUT_OF_TABLE_CPCON;
-
-		if ((cfg.m > (PLL_BASE_DIVM_MASK >> PLL_BASE_DIVM_SHIFT)) ||
-		    (cfg.n > (PLL_BASE_DIVN_MASK >> PLL_BASE_DIVN_SHIFT)) ||
-		    (p_div > (PLL_BASE_DIVP_MASK >> PLL_BASE_DIVP_SHIFT)) ||
-		    (cfg.output_rate > c->u.pll.vco_max)) {
-			pr_err("%s: Failed to set %s out-of-table rate %lu\n",
-			       __func__, __clk_get_name(hw->clk), rate);
-			return -EINVAL;
-		}
-		p_div <<= PLL_BASE_DIVP_SHIFT;
-	}
-
-	c->mul = sel->n;
-	c->div = sel->m * sel->p;
-
-	old_base = val = clk_readl(c->reg + PLL_BASE);
-	val &= ~(PLL_BASE_DIVM_MASK | PLL_BASE_DIVN_MASK |
-		 ((c->flags & PLLU) ? PLLU_BASE_POST_DIV : PLL_BASE_DIVP_MASK));
-	val |= (sel->m << PLL_BASE_DIVM_SHIFT) |
-		(sel->n << PLL_BASE_DIVN_SHIFT) | p_div;
-	if (val == old_base)
-		return 0;
-
-	if (c->state == ON) {
-		tegra30_pll_clk_disable(hw);
-		val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
-	}
-	clk_writel(val, c->reg + PLL_BASE);
-
-	if (c->flags & PLL_HAS_CPCON) {
-		val = clk_readl(c->reg + PLL_MISC(c));
-		val &= ~PLL_MISC_CPCON_MASK;
-		val |= sel->cpcon << PLL_MISC_CPCON_SHIFT;
-		if (c->flags & (PLLU | PLLD)) {
-			val &= ~PLL_MISC_LFCON_MASK;
-			if (sel->n >= PLLDU_LFCON_SET_DIVN)
-				val |= 0x1 << PLL_MISC_LFCON_SHIFT;
-		} else if (c->flags & (PLLX | PLLM)) {
-			val &= ~(0x1 << PLL_MISC_DCCON_SHIFT);
-			if (rate >= (c->u.pll.vco_max >> 1))
-				val |= 0x1 << PLL_MISC_DCCON_SHIFT;
-		}
-		clk_writel(val, c->reg + PLL_MISC(c));
-	}
-
-	if (c->state == ON)
-		tegra30_pll_clk_enable(hw);
-
-	c->u.pll.fixed_rate = rate;
-
-	return 0;
-}
-
-static long tegra30_pll_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long input_rate = *prate;
-	u64 output_rate = *prate;
-	const struct clk_pll_freq_table *sel;
-	struct clk_pll_freq_table cfg;
-	int mul;
-	int div;
-	u32 p_div;
-	u32 val;
-
-	if (c->flags & PLL_FIXED)
-		return c->u.pll.fixed_rate;
-
-	if (c->flags & PLLM)
-		return __clk_get_rate(hw->clk);
-
-	p_div = 0;
-	/* Check if the target rate is tabulated */
-	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
-		if (sel->input_rate == input_rate && sel->output_rate == rate) {
-			if (c->flags & PLLU) {
-				BUG_ON(sel->p < 1 || sel->p > 2);
-				if (sel->p == 1)
-					p_div = PLLU_BASE_POST_DIV;
-			} else {
-				BUG_ON(sel->p < 1);
-				for (val = sel->p; val > 1; val >>= 1)
-					p_div++;
-				p_div <<= PLL_BASE_DIVP_SHIFT;
-			}
-			break;
-		}
-	}
-
-	if (sel->input_rate == 0) {
-		unsigned long cfreq;
-		BUG_ON(c->flags & PLLU);
-		sel = &cfg;
-
-		switch (input_rate) {
-		case 12000000:
-		case 26000000:
-			cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000;
-			break;
-		case 13000000:
-			cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000;
-			break;
-		case 16800000:
-		case 19200000:
-			cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000;
-			break;
-		default:
-			pr_err("%s: Unexpected reference rate %lu\n",
-			       __func__, input_rate);
-			BUG();
-		}
-
-		/* Raise VCO to guarantee 0.5% accuracy */
-		for (cfg.output_rate = rate; cfg.output_rate < 200 * cfreq;
-		      cfg.output_rate <<= 1)
-			p_div++;
-
-		cfg.p = 0x1 << p_div;
-		cfg.m = input_rate / cfreq;
-		cfg.n = cfg.output_rate / cfreq;
-	}
-
-	mul = sel->n;
-	div = sel->m * sel->p;
-
-	output_rate *= mul;
-	output_rate += div - 1; /* round up */
-	do_div(output_rate, div);
-
-	return output_rate;
-}
-
-static unsigned long tegra30_pll_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = parent_rate;
-	u32 val = clk_readl(c->reg + PLL_BASE);
-
-	if (c->flags & PLL_FIXED && !(val & PLL_BASE_OVERRIDE)) {
-		const struct clk_pll_freq_table *sel;
-		for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
-			if (sel->input_rate == parent_rate &&
-				sel->output_rate == c->u.pll.fixed_rate) {
-				c->mul = sel->n;
-				c->div = sel->m * sel->p;
-				break;
-			}
-		}
-		pr_err("Clock %s has unknown fixed frequency\n",
-						__clk_get_name(hw->clk));
-		BUG();
-	} else if (val & PLL_BASE_BYPASS) {
-		c->mul = 1;
-		c->div = 1;
-	} else {
-		c->mul = (val & PLL_BASE_DIVN_MASK) >> PLL_BASE_DIVN_SHIFT;
-		c->div = (val & PLL_BASE_DIVM_MASK) >> PLL_BASE_DIVM_SHIFT;
-		if (c->flags & PLLU)
-			c->div *= (val & PLLU_BASE_POST_DIV) ? 1 : 2;
-		else
-			c->div *= (0x1 << ((val & PLL_BASE_DIVP_MASK) >>
-					PLL_BASE_DIVP_SHIFT));
-	}
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-
-	return rate;
-}
-
-struct clk_ops tegra30_pll_ops = {
-	.is_enabled = tegra30_pll_clk_is_enabled,
-	.init = tegra30_pll_clk_init,
-	.enable = tegra30_pll_clk_enable,
-	.disable = tegra30_pll_clk_disable,
-	.recalc_rate = tegra30_pll_recalc_rate,
-	.round_rate = tegra30_pll_round_rate,
-	.set_rate = tegra30_pll_clk_set_rate,
-};
-
-int tegra30_plld_clk_cfg_ex(struct clk_hw *hw,
-				enum tegra_clk_ex_param p, u32 setting)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val, mask, reg;
-
-	switch (p) {
-	case TEGRA_CLK_PLLD_CSI_OUT_ENB:
-		mask = PLLD_BASE_CSI_CLKENABLE;
-		reg = c->reg + PLL_BASE;
-		break;
-	case TEGRA_CLK_PLLD_DSI_OUT_ENB:
-		mask = PLLD_MISC_DSI_CLKENABLE;
-		reg = c->reg + PLL_MISC(c);
-		break;
-	case TEGRA_CLK_PLLD_MIPI_MUX_SEL:
-		if (!(c->flags & PLL_ALT_MISC_REG)) {
-			mask = PLLD_BASE_DSIB_MUX_MASK;
-			reg = c->reg + PLL_BASE;
-			break;
-		}
-	/* fall through - error since PLLD2 does not have MUX_SEL control */
-	default:
-		return -EINVAL;
-	}
-
-	val = clk_readl(reg);
-	if (setting)
-		val |= mask;
-	else
-		val &= ~mask;
-	clk_writel(val, reg);
-	return 0;
-}
-
-static int tegra30_plle_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	val = clk_readl(c->reg + PLL_BASE);
-	c->state = (val & PLLE_BASE_ENABLE) ? ON : OFF;
-	return c->state;
-}
-
-static void tegra30_plle_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	val = clk_readl(c->reg + PLL_BASE);
-	val &= ~(PLLE_BASE_CML_ENABLE | PLLE_BASE_ENABLE);
-	clk_writel(val, c->reg + PLL_BASE);
-}
-
-static void tegra30_plle_training(struct clk_tegra *c)
-{
-	u32 val;
-
-	/* PLLE is already disabled, and setup cleared;
-	 * create falling edge on PLLE IDDQ input */
-	val = pmc_readl(PMC_SATA_PWRGT);
-	val |= PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
-	pmc_writel(val, PMC_SATA_PWRGT);
-
-	val = pmc_readl(PMC_SATA_PWRGT);
-	val |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
-	pmc_writel(val, PMC_SATA_PWRGT);
-
-	val = pmc_readl(PMC_SATA_PWRGT);
-	val &= ~PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
-	pmc_writel(val, PMC_SATA_PWRGT);
-
-	do {
-		val = clk_readl(c->reg + PLL_MISC(c));
-	} while (!(val & PLLE_MISC_READY));
-}
-
-static int tegra30_plle_configure(struct clk_hw *hw, bool force_training)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	struct clk *parent = __clk_get_parent(hw->clk);
-	const struct clk_pll_freq_table *sel;
-	u32 val;
-
-	unsigned long rate = c->u.pll.fixed_rate;
-	unsigned long input_rate = __clk_get_rate(parent);
-
-	for (sel = c->u.pll.freq_table; sel->input_rate != 0; sel++) {
-		if (sel->input_rate == input_rate && sel->output_rate == rate)
-			break;
-	}
-
-	if (sel->input_rate == 0)
-		return -ENOSYS;
-
-	/* disable PLLE, clear setup fiels */
-	tegra30_plle_clk_disable(hw);
-
-	val = clk_readl(c->reg + PLL_MISC(c));
-	val &= ~(PLLE_MISC_LOCK_ENABLE | PLLE_MISC_SETUP_MASK);
-	clk_writel(val, c->reg + PLL_MISC(c));
-
-	/* training */
-	val = clk_readl(c->reg + PLL_MISC(c));
-	if (force_training || (!(val & PLLE_MISC_READY)))
-		tegra30_plle_training(c);
-
-	/* configure dividers, setup, disable SS */
-	val = clk_readl(c->reg + PLL_BASE);
-	val &= ~PLLE_BASE_DIV_MASK;
-	val |= PLLE_BASE_DIV(sel->m, sel->n, sel->p, sel->cpcon);
-	clk_writel(val, c->reg + PLL_BASE);
-	c->mul = sel->n;
-	c->div = sel->m * sel->p;
-
-	val = clk_readl(c->reg + PLL_MISC(c));
-	val |= PLLE_MISC_SETUP_VALUE;
-	val |= PLLE_MISC_LOCK_ENABLE;
-	clk_writel(val, c->reg + PLL_MISC(c));
-
-	val = clk_readl(PLLE_SS_CTRL);
-	val |= PLLE_SS_DISABLE;
-	clk_writel(val, PLLE_SS_CTRL);
-
-	/* enable and lock PLLE*/
-	val = clk_readl(c->reg + PLL_BASE);
-	val |= (PLLE_BASE_CML_ENABLE | PLLE_BASE_ENABLE);
-	clk_writel(val, c->reg + PLL_BASE);
-
-	tegra30_pll_clk_wait_for_lock(c, c->reg + PLL_MISC(c), PLLE_MISC_LOCK);
-
-	return 0;
-}
-
-static int tegra30_plle_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	return tegra30_plle_configure(hw, !c->set);
-}
-
-static unsigned long tegra30_plle_clk_recalc_rate(struct clk_hw *hw,
-			unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long rate = parent_rate;
-	u32 val;
-
-	val = clk_readl(c->reg + PLL_BASE);
-	c->mul = (val & PLLE_BASE_DIVN_MASK) >> PLLE_BASE_DIVN_SHIFT;
-	c->div = (val & PLLE_BASE_DIVM_MASK) >> PLLE_BASE_DIVM_SHIFT;
-	c->div *= (val & PLLE_BASE_DIVP_MASK) >> PLLE_BASE_DIVP_SHIFT;
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-	return rate;
-}
-
-struct clk_ops tegra30_plle_ops = {
-	.is_enabled = tegra30_plle_clk_is_enabled,
-	.enable = tegra30_plle_clk_enable,
-	.disable = tegra30_plle_clk_disable,
-	.recalc_rate = tegra30_plle_clk_recalc_rate,
-};
-
-/* Clock divider ops */
-static int tegra30_pll_div_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	if (c->flags & DIV_U71) {
-		u32 val = clk_readl(c->reg);
-		val >>= c->reg_shift;
-		c->state = (val & PLL_OUT_CLKEN) ? ON : OFF;
-		if (!(val & PLL_OUT_RESET_DISABLE))
-			c->state = OFF;
-	} else {
-		c->state = ON;
-	}
-	return c->state;
-}
-
-static int tegra30_pll_div_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	u32 new_val;
-
-	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
-	if (c->flags & DIV_U71) {
-		val = clk_readl(c->reg);
-		new_val = val >> c->reg_shift;
-		new_val &= 0xFFFF;
-
-		new_val |= PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE;
-
-		val &= ~(0xFFFF << c->reg_shift);
-		val |= new_val << c->reg_shift;
-		clk_writel_delay(val, c->reg);
-		return 0;
-	} else if (c->flags & DIV_2) {
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static void tegra30_pll_div_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	u32 new_val;
-
-	pr_debug("%s: %s\n", __func__, __clk_get_name(hw->clk));
-	if (c->flags & DIV_U71) {
-		val = clk_readl(c->reg);
-		new_val = val >> c->reg_shift;
-		new_val &= 0xFFFF;
-
-		new_val &= ~(PLL_OUT_CLKEN | PLL_OUT_RESET_DISABLE);
-
-		val &= ~(0xFFFF << c->reg_shift);
-		val |= new_val << c->reg_shift;
-		clk_writel_delay(val, c->reg);
-	}
-}
-
-static int tegra30_pll_div_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	u32 new_val;
-	int divider_u71;
-
-	if (c->flags & DIV_U71) {
-		divider_u71 = clk_div71_get_divider(
-			parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
-		if (divider_u71 >= 0) {
-			val = clk_readl(c->reg);
-			new_val = val >> c->reg_shift;
-			new_val &= 0xFFFF;
-			if (c->flags & DIV_U71_FIXED)
-				new_val |= PLL_OUT_OVERRIDE;
-			new_val &= ~PLL_OUT_RATIO_MASK;
-			new_val |= divider_u71 << PLL_OUT_RATIO_SHIFT;
-
-			val &= ~(0xFFFF << c->reg_shift);
-			val |= new_val << c->reg_shift;
-			clk_writel_delay(val, c->reg);
-			c->div = divider_u71 + 2;
-			c->mul = 2;
-			c->fixed_rate = rate;
-			return 0;
-		}
-	} else if (c->flags & DIV_2) {
-		c->fixed_rate = rate;
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
-static unsigned long tegra30_pll_div_clk_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = parent_rate;
-
-	if (c->flags & DIV_U71) {
-		u32 divu71;
-		u32 val = clk_readl(c->reg);
-		val >>= c->reg_shift;
-
-		divu71 = (val & PLL_OUT_RATIO_MASK) >> PLL_OUT_RATIO_SHIFT;
-		c->div = (divu71 + 2);
-		c->mul = 2;
-	} else if (c->flags & DIV_2) {
-		if (c->flags & (PLLD | PLLX)) {
-			c->div = 2;
-			c->mul = 1;
-		} else
-			BUG();
-	} else {
-		c->div = 1;
-		c->mul = 1;
-	}
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-
-	return rate;
-}
-
-static long tegra30_pll_div_clk_round_rate(struct clk_hw *hw,
-				unsigned long rate, unsigned long *prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
-	int divider;
-
-	if (prate)
-		parent_rate = *prate;
-
-	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(
-			parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
-		if (divider < 0)
-			return divider;
-		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
-	} else if (c->flags & DIV_2) {
-		*prate = rate * 2;
-		return rate;
-	}
-
-	return -EINVAL;
-}
-
-struct clk_ops tegra30_pll_div_ops = {
-	.is_enabled = tegra30_pll_div_clk_is_enabled,
-	.enable = tegra30_pll_div_clk_enable,
-	.disable = tegra30_pll_div_clk_disable,
-	.set_rate = tegra30_pll_div_clk_set_rate,
-	.recalc_rate = tegra30_pll_div_clk_recalc_rate,
-	.round_rate = tegra30_pll_div_clk_round_rate,
-};
-
-/* Periph clk ops */
-static inline u32 periph_clk_source_mask(struct clk_tegra *c)
-{
-	if (c->flags & MUX8)
-		return 7 << 29;
-	else if (c->flags & MUX_PWM)
-		return 3 << 28;
-	else if (c->flags & MUX_CLK_OUT)
-		return 3 << (c->u.periph.clk_num + 4);
-	else if (c->flags & PLLD)
-		return PLLD_BASE_DSIB_MUX_MASK;
-	else
-		return 3 << 30;
-}
-
-static inline u32 periph_clk_source_shift(struct clk_tegra *c)
-{
-	if (c->flags & MUX8)
-		return 29;
-	else if (c->flags & MUX_PWM)
-		return 28;
-	else if (c->flags & MUX_CLK_OUT)
-		return c->u.periph.clk_num + 4;
-	else if (c->flags & PLLD)
-		return PLLD_BASE_DSIB_MUX_SHIFT;
-	else
-		return 30;
-}
-
-static int tegra30_periph_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	c->state = ON;
-	if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c)))
-		c->state = OFF;
-	if (!(c->flags & PERIPH_NO_RESET))
-		if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) & PERIPH_CLK_TO_BIT(c))
-			c->state = OFF;
-	return c->state;
-}
-
-static int tegra30_periph_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	tegra_periph_clk_enable_refcount[c->u.periph.clk_num]++;
-	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 1)
-		return 0;
-
-	clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_SET_REG(c));
-	if (!(c->flags & PERIPH_NO_RESET) &&
-		 !(c->flags & PERIPH_MANUAL_RESET)) {
-		if (clk_readl(PERIPH_CLK_TO_RST_REG(c)) &
-			 PERIPH_CLK_TO_BIT(c)) {
-			udelay(5);	/* reset propagation delay */
-			clk_writel(PERIPH_CLK_TO_BIT(c),
-				 PERIPH_CLK_TO_RST_CLR_REG(c));
-		}
-	}
-	return 0;
-}
-
-static void tegra30_periph_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long val;
-
-	tegra_periph_clk_enable_refcount[c->u.periph.clk_num]--;
-
-	if (tegra_periph_clk_enable_refcount[c->u.periph.clk_num] > 0)
-		return;
-
-	/* If peripheral is in the APB bus then read the APB bus to
-	 * flush the write operation in apb bus. This will avoid the
-	 * peripheral access after disabling clock*/
-	if (c->flags & PERIPH_ON_APB)
-		val = chipid_readl();
-
-	clk_writel_delay(PERIPH_CLK_TO_BIT(c), PERIPH_CLK_TO_ENB_CLR_REG(c));
-}
-
-void tegra30_periph_clk_reset(struct clk_hw *hw, bool assert)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long val;
-
-	if (!(c->flags & PERIPH_NO_RESET)) {
-		if (assert) {
-			/* If peripheral is in the APB bus then read the APB
-			 * bus to flush the write operation in apb bus. This
-			 * will avoid the peripheral access after disabling
-			 * clock */
-			if (c->flags & PERIPH_ON_APB)
-				val = chipid_readl();
-
-			clk_writel(PERIPH_CLK_TO_BIT(c),
-				   PERIPH_CLK_TO_RST_SET_REG(c));
-		} else
-			clk_writel(PERIPH_CLK_TO_BIT(c),
-				   PERIPH_CLK_TO_RST_CLR_REG(c));
-	}
-}
-
-static int tegra30_periph_clk_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	if (!(c->flags & MUX))
-		return (index == 0) ? 0 : (-EINVAL);
-
-	val = clk_readl(c->reg);
-	val &= ~periph_clk_source_mask(c);
-	val |= (index << periph_clk_source_shift(c));
-	clk_writel_delay(val, c->reg);
-	return 0;
-}
-
-static u8 tegra30_periph_clk_get_parent(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-	int source  = (val & periph_clk_source_mask(c)) >>
-					periph_clk_source_shift(c);
-
-	if (!(c->flags & MUX))
-		return 0;
-
-	return source;
-}
-
-static int tegra30_periph_clk_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	int divider;
-
-	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(
-			parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
-		if (divider >= 0) {
-			val = clk_readl(c->reg);
-			val &= ~PERIPH_CLK_SOURCE_DIVU71_MASK;
-			val |= divider;
-			if (c->flags & DIV_U71_UART) {
-				if (divider)
-					val |= PERIPH_CLK_UART_DIV_ENB;
-				else
-					val &= ~PERIPH_CLK_UART_DIV_ENB;
-			}
-			clk_writel_delay(val, c->reg);
-			c->div = divider + 2;
-			c->mul = 2;
-			return 0;
-		}
-	} else if (c->flags & DIV_U16) {
-		divider = clk_div16_get_divider(parent_rate, rate);
-		if (divider >= 0) {
-			val = clk_readl(c->reg);
-			val &= ~PERIPH_CLK_SOURCE_DIVU16_MASK;
-			val |= divider;
-			clk_writel_delay(val, c->reg);
-			c->div = divider + 1;
-			c->mul = 1;
-			return 0;
-		}
-	} else if (parent_rate <= rate) {
-		c->div = 1;
-		c->mul = 1;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static long tegra30_periph_clk_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	unsigned long parent_rate = __clk_get_rate(__clk_get_parent(hw->clk));
-	int divider;
-
-	if (prate)
-		parent_rate = *prate;
-
-	if (c->flags & DIV_U71) {
-		divider = clk_div71_get_divider(
-			parent_rate, rate, c->flags, ROUND_DIVIDER_UP);
-		if (divider < 0)
-			return divider;
-
-		return DIV_ROUND_UP(parent_rate * 2, divider + 2);
-	} else if (c->flags & DIV_U16) {
-		divider = clk_div16_get_divider(parent_rate, rate);
-		if (divider < 0)
-			return divider;
-		return DIV_ROUND_UP(parent_rate, divider + 1);
-	}
-	return -EINVAL;
-}
-
-static unsigned long tegra30_periph_clk_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = parent_rate;
-	u32 val = clk_readl(c->reg);
-
-	if (c->flags & DIV_U71) {
-		u32 divu71 = val & PERIPH_CLK_SOURCE_DIVU71_MASK;
-		if ((c->flags & DIV_U71_UART) &&
-		    (!(val & PERIPH_CLK_UART_DIV_ENB))) {
-			divu71 = 0;
-		}
-		if (c->flags & DIV_U71_IDLE) {
-			val &= ~(PERIPH_CLK_SOURCE_DIVU71_MASK <<
-				PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
-			val |= (PERIPH_CLK_SOURCE_DIVIDLE_VAL <<
-				PERIPH_CLK_SOURCE_DIVIDLE_SHIFT);
-			clk_writel(val, c->reg);
-		}
-		c->div = divu71 + 2;
-		c->mul = 2;
-	} else if (c->flags & DIV_U16) {
-		u32 divu16 = val & PERIPH_CLK_SOURCE_DIVU16_MASK;
-		c->div = divu16 + 1;
-		c->mul = 1;
-	} else {
-		c->div = 1;
-		c->mul = 1;
-	}
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-	return rate;
-}
-
-struct clk_ops tegra30_periph_clk_ops = {
-	.is_enabled = tegra30_periph_clk_is_enabled,
-	.enable = tegra30_periph_clk_enable,
-	.disable = tegra30_periph_clk_disable,
-	.set_parent = tegra30_periph_clk_set_parent,
-	.get_parent = tegra30_periph_clk_get_parent,
-	.set_rate = tegra30_periph_clk_set_rate,
-	.round_rate = tegra30_periph_clk_round_rate,
-	.recalc_rate = tegra30_periph_clk_recalc_rate,
-};
-
-static int tegra30_dsib_clk_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct clk *d = clk_get_sys(NULL, "pll_d");
-	/* The DSIB parent selection bit is in PLLD base register */
-	tegra_clk_cfg_ex(
-		d, TEGRA_CLK_PLLD_MIPI_MUX_SEL, index);
-
-	return 0;
-}
-
-struct clk_ops tegra30_dsib_clk_ops = {
-	.is_enabled = tegra30_periph_clk_is_enabled,
-	.enable			= &tegra30_periph_clk_enable,
-	.disable		= &tegra30_periph_clk_disable,
-	.set_parent		= &tegra30_dsib_clk_set_parent,
-	.get_parent		= &tegra30_periph_clk_get_parent,
-	.set_rate		= &tegra30_periph_clk_set_rate,
-	.round_rate		= &tegra30_periph_clk_round_rate,
-	.recalc_rate		= &tegra30_periph_clk_recalc_rate,
-};
-
-/* Periph extended clock configuration ops */
-int tegra30_vi_clk_cfg_ex(struct clk_hw *hw,
-				enum tegra_clk_ex_param p, u32 setting)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	if (p == TEGRA_CLK_VI_INP_SEL) {
-		u32 val = clk_readl(c->reg);
-		val &= ~PERIPH_CLK_VI_SEL_EX_MASK;
-		val |= (setting << PERIPH_CLK_VI_SEL_EX_SHIFT) &
-			PERIPH_CLK_VI_SEL_EX_MASK;
-		clk_writel(val, c->reg);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-int tegra30_nand_clk_cfg_ex(struct clk_hw *hw,
-				enum tegra_clk_ex_param p, u32 setting)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	if (p == TEGRA_CLK_NAND_PAD_DIV2_ENB) {
-		u32 val = clk_readl(c->reg);
-		if (setting)
-			val |= PERIPH_CLK_NAND_DIV_EX_ENB;
-		else
-			val &= ~PERIPH_CLK_NAND_DIV_EX_ENB;
-		clk_writel(val, c->reg);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-int tegra30_dtv_clk_cfg_ex(struct clk_hw *hw,
-				enum tegra_clk_ex_param p, u32 setting)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	if (p == TEGRA_CLK_DTV_INVERT) {
-		u32 val = clk_readl(c->reg);
-		if (setting)
-			val |= PERIPH_CLK_DTV_POLARITY_INV;
-		else
-			val &= ~PERIPH_CLK_DTV_POLARITY_INV;
-		clk_writel(val, c->reg);
-		return 0;
-	}
-	return -EINVAL;
-}
-
-/* Output clock ops */
-
-static DEFINE_SPINLOCK(clk_out_lock);
-
-static int tegra30_clk_out_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = pmc_readl(c->reg);
-
-	c->state = (val & (0x1 << c->u.periph.clk_num)) ? ON : OFF;
-	c->mul = 1;
-	c->div = 1;
-	return c->state;
-}
-
-static int tegra30_clk_out_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&clk_out_lock, flags);
-	val = pmc_readl(c->reg);
-	val |= (0x1 << c->u.periph.clk_num);
-	pmc_writel(val, c->reg);
-	spin_unlock_irqrestore(&clk_out_lock, flags);
-
-	return 0;
-}
-
-static void tegra30_clk_out_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&clk_out_lock, flags);
-	val = pmc_readl(c->reg);
-	val &= ~(0x1 << c->u.periph.clk_num);
-	pmc_writel(val, c->reg);
-	spin_unlock_irqrestore(&clk_out_lock, flags);
-}
-
-static int tegra30_clk_out_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-	unsigned long flags;
-
-	spin_lock_irqsave(&clk_out_lock, flags);
-	val = pmc_readl(c->reg);
-	val &= ~periph_clk_source_mask(c);
-	val |= (index << periph_clk_source_shift(c));
-	pmc_writel(val, c->reg);
-	spin_unlock_irqrestore(&clk_out_lock, flags);
-
-	return 0;
-}
-
-static u8 tegra30_clk_out_get_parent(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = pmc_readl(c->reg);
-	int source;
-
-	source = (val & periph_clk_source_mask(c)) >>
-				periph_clk_source_shift(c);
-	return source;
-}
-
-struct clk_ops tegra_clk_out_ops = {
-	.is_enabled = tegra30_clk_out_is_enabled,
-	.enable = tegra30_clk_out_enable,
-	.disable = tegra30_clk_out_disable,
-	.set_parent = tegra30_clk_out_set_parent,
-	.get_parent = tegra30_clk_out_get_parent,
-	.recalc_rate = tegra30_clk_fixed_recalc_rate,
-};
-
-/* Clock doubler ops */
-static int tegra30_clk_double_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	c->state = ON;
-	if (!(clk_readl(PERIPH_CLK_TO_ENB_REG(c)) & PERIPH_CLK_TO_BIT(c)))
-		c->state = OFF;
-	return c->state;
-};
-
-static int tegra30_clk_double_set_rate(struct clk_hw *hw, unsigned long rate,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	if (rate == parent_rate) {
-		val = clk_readl(c->reg) | (0x1 << c->reg_shift);
-		clk_writel(val, c->reg);
-		c->mul = 1;
-		c->div = 1;
-		return 0;
-	} else if (rate == 2 * parent_rate) {
-		val = clk_readl(c->reg) & (~(0x1 << c->reg_shift));
-		clk_writel(val, c->reg);
-		c->mul = 2;
-		c->div = 1;
-		return 0;
-	}
-	return -EINVAL;
-}
-
-static unsigned long tegra30_clk_double_recalc_rate(struct clk_hw *hw,
-		unsigned long parent_rate)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u64 rate = parent_rate;
-
-	u32 val = clk_readl(c->reg);
-	c->mul = val & (0x1 << c->reg_shift) ? 1 : 2;
-	c->div = 1;
-
-	if (c->mul != 0 && c->div != 0) {
-		rate *= c->mul;
-		rate += c->div - 1; /* round up */
-		do_div(rate, c->div);
-	}
-
-	return rate;
-}
-
-static long tegra30_clk_double_round_rate(struct clk_hw *hw, unsigned long rate,
-				unsigned long *prate)
-{
-	unsigned long output_rate = *prate;
-
-	do_div(output_rate, 2);
-	return output_rate;
-}
-
-struct clk_ops tegra30_clk_double_ops = {
-	.is_enabled = tegra30_clk_double_is_enabled,
-	.enable = tegra30_periph_clk_enable,
-	.disable = tegra30_periph_clk_disable,
-	.recalc_rate = tegra30_clk_double_recalc_rate,
-	.round_rate = tegra30_clk_double_round_rate,
-	.set_rate = tegra30_clk_double_set_rate,
-};
-
-/* Audio sync clock ops */
-struct clk_ops tegra_sync_source_ops = {
-	.recalc_rate = tegra30_clk_fixed_recalc_rate,
-};
-
-static int tegra30_audio_sync_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-	c->state = (val & AUDIO_SYNC_DISABLE_BIT) ? OFF : ON;
-	return c->state;
-}
-
-static int tegra30_audio_sync_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-	clk_writel((val & (~AUDIO_SYNC_DISABLE_BIT)), c->reg);
-	return 0;
-}
-
-static void tegra30_audio_sync_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-	clk_writel((val | AUDIO_SYNC_DISABLE_BIT), c->reg);
-}
-
-static int tegra30_audio_sync_clk_set_parent(struct clk_hw *hw, u8 index)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val;
-
-	val = clk_readl(c->reg);
-	val &= ~AUDIO_SYNC_SOURCE_MASK;
-	val |= index;
-
-	clk_writel(val, c->reg);
-	return 0;
-}
-
-static u8 tegra30_audio_sync_clk_get_parent(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-	int source;
-
-	source = val & AUDIO_SYNC_SOURCE_MASK;
-	return source;
-}
-
-struct clk_ops tegra30_audio_sync_clk_ops = {
-	.is_enabled = tegra30_audio_sync_clk_is_enabled,
-	.enable = tegra30_audio_sync_clk_enable,
-	.disable = tegra30_audio_sync_clk_disable,
-	.set_parent = tegra30_audio_sync_clk_set_parent,
-	.get_parent = tegra30_audio_sync_clk_get_parent,
-	.recalc_rate = tegra30_clk_fixed_recalc_rate,
-};
-
-/* cml0 (pcie), and cml1 (sata) clock ops */
-static int tegra30_cml_clk_is_enabled(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-	u32 val = clk_readl(c->reg);
-	c->state = val & (0x1 << c->u.periph.clk_num) ? ON : OFF;
-	return c->state;
-}
-
-static int tegra30_cml_clk_enable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	u32 val = clk_readl(c->reg);
-	val |= (0x1 << c->u.periph.clk_num);
-	clk_writel(val, c->reg);
-
-	return 0;
-}
-
-static void tegra30_cml_clk_disable(struct clk_hw *hw)
-{
-	struct clk_tegra *c = to_clk_tegra(hw);
-
-	u32 val = clk_readl(c->reg);
-	val &= ~(0x1 << c->u.periph.clk_num);
-	clk_writel(val, c->reg);
-}
-
-struct clk_ops tegra_cml_clk_ops = {
-	.is_enabled = tegra30_cml_clk_is_enabled,
-	.enable = tegra30_cml_clk_enable,
-	.disable = tegra30_cml_clk_disable,
-	.recalc_rate = tegra30_clk_fixed_recalc_rate,
-};
-
-struct clk_ops tegra_pciex_clk_ops = {
-	.recalc_rate = tegra30_clk_fixed_recalc_rate,
-};
-
-/* Tegra30 CPU clock and reset control functions */
-static void tegra30_wait_cpu_in_reset(u32 cpu)
-{
-	unsigned int reg;
-
-	do {
-		reg = readl(reg_clk_base +
-			    TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
-		cpu_relax();
-	} while (!(reg & (1 << cpu)));	/* check CPU been reset or not */
-
-	return;
-}
-
-static void tegra30_put_cpu_in_reset(u32 cpu)
-{
-	writel(CPU_RESET(cpu),
-	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
-	dmb();
-}
-
-static void tegra30_cpu_out_of_reset(u32 cpu)
-{
-	writel(CPU_RESET(cpu),
-	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
-	wmb();
-}
-
-static void tegra30_enable_cpu_clock(u32 cpu)
-{
-	unsigned int reg;
-
-	writel(CPU_CLOCK(cpu),
-	       reg_clk_base + TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
-	reg = readl(reg_clk_base +
-		    TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
-}
-
-static void tegra30_disable_cpu_clock(u32 cpu)
-{
-
-	unsigned int reg;
-
-	reg = readl(reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-	writel(reg | CPU_CLOCK(cpu),
-	       reg_clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
-}
-
-#ifdef CONFIG_PM_SLEEP
-static bool tegra30_cpu_rail_off_ready(void)
-{
-	unsigned int cpu_rst_status;
-	int cpu_pwr_status;
-
-	cpu_rst_status = readl(reg_clk_base +
-			       TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
-	cpu_pwr_status = tegra_powergate_is_powered(TEGRA_POWERGATE_CPU1) ||
-			 tegra_powergate_is_powered(TEGRA_POWERGATE_CPU2) ||
-			 tegra_powergate_is_powered(TEGRA_POWERGATE_CPU3);
-
-	if (((cpu_rst_status & 0xE) != 0xE) || cpu_pwr_status)
-		return false;
-
-	return true;
-}
-
-static void tegra30_cpu_clock_suspend(void)
-{
-	/* switch coresite to clk_m, save off original source */
-	tegra30_cpu_clk_sctx.clk_csite_src =
-				readl(reg_clk_base + CLK_RESET_SOURCE_CSITE);
-	writel(3<<30, reg_clk_base + CLK_RESET_SOURCE_CSITE);
-
-	tegra30_cpu_clk_sctx.cpu_burst =
-				readl(reg_clk_base + CLK_RESET_CCLK_BURST);
-	tegra30_cpu_clk_sctx.pllx_base =
-				readl(reg_clk_base + CLK_RESET_PLLX_BASE);
-	tegra30_cpu_clk_sctx.pllx_misc =
-				readl(reg_clk_base + CLK_RESET_PLLX_MISC);
-	tegra30_cpu_clk_sctx.cclk_divider =
-				readl(reg_clk_base + CLK_RESET_CCLK_DIVIDER);
-}
-
-static void tegra30_cpu_clock_resume(void)
-{
-	unsigned int reg, policy;
-
-	/* Is CPU complex already running on PLLX? */
-	reg = readl(reg_clk_base + CLK_RESET_CCLK_BURST);
-	policy = (reg >> CLK_RESET_CCLK_BURST_POLICY_SHIFT) & 0xF;
-
-	if (policy == CLK_RESET_CCLK_IDLE_POLICY)
-		reg = (reg >> CLK_RESET_CCLK_IDLE_POLICY_SHIFT) & 0xF;
-	else if (policy == CLK_RESET_CCLK_RUN_POLICY)
-		reg = (reg >> CLK_RESET_CCLK_RUN_POLICY_SHIFT) & 0xF;
-	else
-		BUG();
-
-	if (reg != CLK_RESET_CCLK_BURST_POLICY_PLLX) {
-		/* restore PLLX settings if CPU is on different PLL */
-		writel(tegra30_cpu_clk_sctx.pllx_misc,
-					reg_clk_base + CLK_RESET_PLLX_MISC);
-		writel(tegra30_cpu_clk_sctx.pllx_base,
-					reg_clk_base + CLK_RESET_PLLX_BASE);
-
-		/* wait for PLL stabilization if PLLX was enabled */
-		if (tegra30_cpu_clk_sctx.pllx_base & (1 << 30))
-			udelay(300);
-	}
-
-	/*
-	 * Restore original burst policy setting for calls resulting from CPU
-	 * LP2 in idle or system suspend.
-	 */
-	writel(tegra30_cpu_clk_sctx.cclk_divider,
-					reg_clk_base + CLK_RESET_CCLK_DIVIDER);
-	writel(tegra30_cpu_clk_sctx.cpu_burst,
-					reg_clk_base + CLK_RESET_CCLK_BURST);
-
-	writel(tegra30_cpu_clk_sctx.clk_csite_src,
-					reg_clk_base + CLK_RESET_SOURCE_CSITE);
-}
-#endif
-
-static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
-	.wait_for_reset	= tegra30_wait_cpu_in_reset,
-	.put_in_reset	= tegra30_put_cpu_in_reset,
-	.out_of_reset	= tegra30_cpu_out_of_reset,
-	.enable_clock	= tegra30_enable_cpu_clock,
-	.disable_clock	= tegra30_disable_cpu_clock,
-#ifdef CONFIG_PM_SLEEP
-	.rail_off_ready	= tegra30_cpu_rail_off_ready,
-	.suspend	= tegra30_cpu_clock_suspend,
-	.resume		= tegra30_cpu_clock_resume,
-#endif
-};
-
-void __init tegra30_cpu_car_ops_init(void)
-{
-	tegra_cpu_car_ops = &tegra30_cpu_car_ops;
-}
diff --git a/arch/arm/mach-tegra/tegra30_clocks.h b/arch/arm/mach-tegra/tegra30_clocks.h
deleted file mode 100644
index 7a34adb..0000000
--- a/arch/arm/mach-tegra/tegra30_clocks.h
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
- */
-
-#ifndef __MACH_TEGRA30_CLOCK_H
-#define __MACH_TEGRA30_CLOCK_H
-
-extern struct clk_ops tegra30_clk_32k_ops;
-extern struct clk_ops tegra30_clk_m_ops;
-extern struct clk_ops tegra_clk_m_div_ops;
-extern struct clk_ops tegra_pll_ref_ops;
-extern struct clk_ops tegra30_pll_ops;
-extern struct clk_ops tegra30_pll_div_ops;
-extern struct clk_ops tegra_plld_ops;
-extern struct clk_ops tegra30_plle_ops;
-extern struct clk_ops tegra_cml_clk_ops;
-extern struct clk_ops tegra_pciex_clk_ops;
-extern struct clk_ops tegra_sync_source_ops;
-extern struct clk_ops tegra30_audio_sync_clk_ops;
-extern struct clk_ops tegra30_clk_double_ops;
-extern struct clk_ops tegra_clk_out_ops;
-extern struct clk_ops tegra30_super_ops;
-extern struct clk_ops tegra30_blink_clk_ops;
-extern struct clk_ops tegra30_twd_ops;
-extern struct clk_ops tegra30_bus_ops;
-extern struct clk_ops tegra30_periph_clk_ops;
-extern struct clk_ops tegra30_dsib_clk_ops;
-extern struct clk_ops tegra_nand_clk_ops;
-extern struct clk_ops tegra_vi_clk_ops;
-extern struct clk_ops tegra_dtv_clk_ops;
-extern struct clk_ops tegra_clk_shared_bus_ops;
-
-int tegra30_plld_clk_cfg_ex(struct clk_hw *hw,
-				enum tegra_clk_ex_param p, u32 setting);
-void tegra30_periph_clk_reset(struct clk_hw *hw, bool assert);
-int tegra30_vi_clk_cfg_ex(struct clk_hw *hw,
-				enum tegra_clk_ex_param p, u32 setting);
-int tegra30_nand_clk_cfg_ex(struct clk_hw *hw,
-				enum tegra_clk_ex_param p, u32 setting);
-int tegra30_dtv_clk_cfg_ex(struct clk_hw *hw,
-				enum tegra_clk_ex_param p, u32 setting);
-#endif
diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c
deleted file mode 100644
index 6942c7a..0000000
--- a/arch/arm/mach-tegra/tegra30_clocks_data.c
+++ /dev/null
@@ -1,1425 +0,0 @@
-/*
- * arch/arm/mach-tegra/tegra30_clocks.c
- *
- * Copyright (c) 2010-2012 NVIDIA CORPORATION.  All rights reserved.
- *
- * 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 of the License.
- *
- * 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
- *
- */
-
-#include <linux/clk-private.h>
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/io.h>
-#include <linux/clk.h>
-#include <linux/cpufreq.h>
-
-#include "clock.h"
-#include "fuse.h"
-#include "tegra30_clocks.h"
-#include "tegra_cpu_car.h"
-
-#define DEFINE_CLK_TEGRA(_name, _rate, _ops, _flags,		\
-		   _parent_names, _parents, _parent)		\
-	static struct clk tegra_##_name = {			\
-		.hw = &tegra_##_name##_hw.hw,			\
-		.name = #_name,					\
-		.rate = _rate,					\
-		.ops = _ops,					\
-		.flags = _flags,				\
-		.parent_names = _parent_names,			\
-		.parents = _parents,				\
-		.num_parents = ARRAY_SIZE(_parent_names),	\
-		.parent	= _parent,				\
-	};
-
-static struct clk tegra_clk_32k;
-static struct clk_tegra tegra_clk_32k_hw = {
-	.hw = {
-		.clk = &tegra_clk_32k,
-	},
-	.fixed_rate = 32768,
-};
-static struct clk tegra_clk_32k = {
-	.name = "clk_32k",
-	.hw = &tegra_clk_32k_hw.hw,
-	.ops = &tegra30_clk_32k_ops,
-	.flags = CLK_IS_ROOT,
-};
-
-static struct clk tegra_clk_m;
-static struct clk_tegra tegra_clk_m_hw = {
-	.hw = {
-		.clk = &tegra_clk_m,
-	},
-	.flags = ENABLE_ON_INIT,
-	.reg = 0x1fc,
-	.reg_shift = 28,
-	.max_rate = 48000000,
-};
-static struct clk tegra_clk_m = {
-	.name = "clk_m",
-	.hw = &tegra_clk_m_hw.hw,
-	.ops = &tegra30_clk_m_ops,
-	.flags = CLK_IS_ROOT | CLK_IGNORE_UNUSED,
-};
-
-static const char *clk_m_div_parent_names[] = {
-	"clk_m",
-};
-
-static struct clk *clk_m_div_parents[] = {
-	&tegra_clk_m,
-};
-
-static struct clk tegra_clk_m_div2;
-static struct clk_tegra tegra_clk_m_div2_hw = {
-	.hw = {
-		.clk = &tegra_clk_m_div2,
-	},
-	.mul = 1,
-	.div = 2,
-	.max_rate = 24000000,
-};
-DEFINE_CLK_TEGRA(clk_m_div2, 0, &tegra_clk_m_div_ops, 0,
-		clk_m_div_parent_names, clk_m_div_parents, &tegra_clk_m);
-
-static struct clk tegra_clk_m_div4;
-static struct clk_tegra tegra_clk_m_div4_hw = {
-	.hw = {
-		.clk = &tegra_clk_m_div4,
-	},
-	.mul = 1,
-	.div = 4,
-	.max_rate = 12000000,
-};
-DEFINE_CLK_TEGRA(clk_m_div4, 0, &tegra_clk_m_div_ops, 0,
-		clk_m_div_parent_names, clk_m_div_parents, &tegra_clk_m);
-
-static struct clk tegra_pll_ref;
-static struct clk_tegra tegra_pll_ref_hw = {
-	.hw = {
-		.clk = &tegra_pll_ref,
-	},
-	.flags = ENABLE_ON_INIT,
-	.max_rate = 26000000,
-};
-DEFINE_CLK_TEGRA(pll_ref, 0, &tegra_pll_ref_ops, 0, clk_m_div_parent_names,
-		clk_m_div_parents, &tegra_clk_m);
-
-#define DEFINE_PLL(_name, _flags, _reg, _max_rate, _input_min,	\
-		   _input_max, _cf_min, _cf_max, _vco_min,	\
-		   _vco_max, _freq_table, _lock_delay, _ops,	\
-		   _fixed_rate, _clk_cfg_ex, _parent)		\
-	static struct clk tegra_##_name;			\
-	static const char *_name##_parent_names[] = {		\
-		#_parent,					\
-	};							\
-	static struct clk *_name##_parents[] = {		\
-		&tegra_##_parent,				\
-	};							\
-	static struct clk_tegra tegra_##_name##_hw = {		\
-		.hw = {						\
-			.clk = &tegra_##_name,			\
-		},						\
-		.flags = _flags,				\
-		.reg = _reg,					\
-		.max_rate = _max_rate,				\
-		.u.pll = {					\
-			.input_min = _input_min,		\
-			.input_max = _input_max,		\
-			.cf_min = _cf_min,			\
-			.cf_max = _cf_max,			\
-			.vco_min = _vco_min,			\
-			.vco_max = _vco_max,			\
-			.freq_table = _freq_table,		\
-			.lock_delay = _lock_delay,		\
-			.fixed_rate = _fixed_rate,		\
-		},						\
-		.clk_cfg_ex = _clk_cfg_ex,			\
-	};							\
-	DEFINE_CLK_TEGRA(_name, 0, &_ops, CLK_IGNORE_UNUSED,	\
-			 _name##_parent_names, _name##_parents,	\
-			&tegra_##_parent);
-
-#define DEFINE_PLL_OUT(_name, _flags, _reg, _reg_shift,		\
-		_max_rate, _ops, _parent, _clk_flags)		\
-	static const char *_name##_parent_names[] = {		\
-		#_parent,					\
-	};							\
-	static struct clk *_name##_parents[] = {		\
-		&tegra_##_parent,				\
-	};							\
-	static struct clk tegra_##_name;			\
-	static struct clk_tegra tegra_##_name##_hw = {		\
-		.hw = {						\
-			.clk = &tegra_##_name,			\
-		},						\
-		.flags = _flags,				\
-		.reg = _reg,					\
-		.max_rate = _max_rate,				\
-		.reg_shift = _reg_shift,			\
-	};							\
-	DEFINE_CLK_TEGRA(_name, 0, &tegra30_pll_div_ops,	\
-		_clk_flags,  _name##_parent_names,		\
-		_name##_parents, &tegra_##_parent);
-
-static struct clk_pll_freq_table tegra_pll_c_freq_table[] = {
-	{ 12000000, 1040000000, 520,  6, 1, 8},
-	{ 13000000, 1040000000, 480,  6, 1, 8},
-	{ 16800000, 1040000000, 495,  8, 1, 8},	/* actual: 1039.5 MHz */
-	{ 19200000, 1040000000, 325,  6, 1, 6},
-	{ 26000000, 1040000000, 520, 13, 1, 8},
-
-	{ 12000000, 832000000, 416,  6, 1, 8},
-	{ 13000000, 832000000, 832, 13, 1, 8},
-	{ 16800000, 832000000, 396,  8, 1, 8},	/* actual: 831.6 MHz */
-	{ 19200000, 832000000, 260,  6, 1, 8},
-	{ 26000000, 832000000, 416, 13, 1, 8},
-
-	{ 12000000, 624000000, 624, 12, 1, 8},
-	{ 13000000, 624000000, 624, 13, 1, 8},
-	{ 16800000, 600000000, 520, 14, 1, 8},
-	{ 19200000, 624000000, 520, 16, 1, 8},
-	{ 26000000, 624000000, 624, 26, 1, 8},
-
-	{ 12000000, 600000000, 600, 12, 1, 8},
-	{ 13000000, 600000000, 600, 13, 1, 8},
-	{ 16800000, 600000000, 500, 14, 1, 8},
-	{ 19200000, 600000000, 375, 12, 1, 6},
-	{ 26000000, 600000000, 600, 26, 1, 8},
-
-	{ 12000000, 520000000, 520, 12, 1, 8},
-	{ 13000000, 520000000, 520, 13, 1, 8},
-	{ 16800000, 520000000, 495, 16, 1, 8},	/* actual: 519.75 MHz */
-	{ 19200000, 520000000, 325, 12, 1, 6},
-	{ 26000000, 520000000, 520, 26, 1, 8},
-
-	{ 12000000, 416000000, 416, 12, 1, 8},
-	{ 13000000, 416000000, 416, 13, 1, 8},
-	{ 16800000, 416000000, 396, 16, 1, 8},	/* actual: 415.8 MHz */
-	{ 19200000, 416000000, 260, 12, 1, 6},
-	{ 26000000, 416000000, 416, 26, 1, 8},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_c, PLL_HAS_CPCON, 0x80, 1400000000, 2000000, 31000000, 1000000,
-		6000000, 20000000, 1400000000, tegra_pll_c_freq_table, 300,
-		tegra30_pll_ops, 0, NULL, pll_ref);
-
-DEFINE_PLL_OUT(pll_c_out1, DIV_U71, 0x84, 0, 700000000,
-		tegra30_pll_div_ops, pll_c, CLK_IGNORE_UNUSED);
-
-static struct clk_pll_freq_table tegra_pll_m_freq_table[] = {
-	{ 12000000, 666000000, 666, 12, 1, 8},
-	{ 13000000, 666000000, 666, 13, 1, 8},
-	{ 16800000, 666000000, 555, 14, 1, 8},
-	{ 19200000, 666000000, 555, 16, 1, 8},
-	{ 26000000, 666000000, 666, 26, 1, 8},
-	{ 12000000, 600000000, 600, 12, 1, 8},
-	{ 13000000, 600000000, 600, 13, 1, 8},
-	{ 16800000, 600000000, 500, 14, 1, 8},
-	{ 19200000, 600000000, 375, 12, 1, 6},
-	{ 26000000, 600000000, 600, 26, 1, 8},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_m, PLL_HAS_CPCON | PLLM, 0x90, 800000000, 2000000, 31000000,
-		1000000, 6000000, 20000000, 1200000000, tegra_pll_m_freq_table,
-		300, tegra30_pll_ops, 0, NULL, pll_ref);
-
-DEFINE_PLL_OUT(pll_m_out1, DIV_U71, 0x94, 0, 600000000,
-		tegra30_pll_div_ops, pll_m, CLK_IGNORE_UNUSED);
-
-static struct clk_pll_freq_table tegra_pll_p_freq_table[] = {
-	{ 12000000, 216000000, 432, 12, 2, 8},
-	{ 13000000, 216000000, 432, 13, 2, 8},
-	{ 16800000, 216000000, 360, 14, 2, 8},
-	{ 19200000, 216000000, 360, 16, 2, 8},
-	{ 26000000, 216000000, 432, 26, 2, 8},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_p, ENABLE_ON_INIT | PLL_FIXED | PLL_HAS_CPCON, 0xa0, 432000000,
-		2000000, 31000000, 1000000, 6000000, 20000000, 1400000000,
-		tegra_pll_p_freq_table, 300, tegra30_pll_ops, 408000000, NULL,
-		pll_ref);
-
-DEFINE_PLL_OUT(pll_p_out1, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4,
-		0, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED);
-DEFINE_PLL_OUT(pll_p_out2, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa4,
-		16, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED);
-DEFINE_PLL_OUT(pll_p_out3, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8,
-		0, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED);
-DEFINE_PLL_OUT(pll_p_out4, ENABLE_ON_INIT | DIV_U71 | DIV_U71_FIXED, 0xa8,
-		16, 432000000, tegra30_pll_div_ops, pll_p, CLK_IGNORE_UNUSED);
-
-static struct clk_pll_freq_table tegra_pll_a_freq_table[] = {
-	{ 9600000, 564480000, 294, 5, 1, 4},
-	{ 9600000, 552960000, 288, 5, 1, 4},
-	{ 9600000, 24000000,  5,   2, 1, 1},
-
-	{ 28800000, 56448000, 49, 25, 1, 1},
-	{ 28800000, 73728000, 64, 25, 1, 1},
-	{ 28800000, 24000000,  5,  6, 1, 1},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_a, PLL_HAS_CPCON, 0xb0, 700000000, 2000000, 31000000, 1000000,
-		6000000, 20000000, 1400000000, tegra_pll_a_freq_table,
-		300, tegra30_pll_ops, 0, NULL, pll_p_out1);
-
-DEFINE_PLL_OUT(pll_a_out0, DIV_U71, 0xb4, 0, 100000000, tegra30_pll_div_ops,
-		pll_a, CLK_IGNORE_UNUSED);
-
-static struct clk_pll_freq_table tegra_pll_d_freq_table[] = {
-	{ 12000000, 216000000, 216, 12, 1, 4},
-	{ 13000000, 216000000, 216, 13, 1, 4},
-	{ 16800000, 216000000, 180, 14, 1, 4},
-	{ 19200000, 216000000, 180, 16, 1, 4},
-	{ 26000000, 216000000, 216, 26, 1, 4},
-
-	{ 12000000, 594000000, 594, 12, 1, 8},
-	{ 13000000, 594000000, 594, 13, 1, 8},
-	{ 16800000, 594000000, 495, 14, 1, 8},
-	{ 19200000, 594000000, 495, 16, 1, 8},
-	{ 26000000, 594000000, 594, 26, 1, 8},
-
-	{ 12000000, 1000000000, 1000, 12, 1, 12},
-	{ 13000000, 1000000000, 1000, 13, 1, 12},
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 12},
-
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_d, PLL_HAS_CPCON | PLLD, 0xd0, 1000000000, 2000000, 40000000,
-		1000000, 6000000, 40000000, 1000000000, tegra_pll_d_freq_table,
-		1000, tegra30_pll_ops, 0, tegra30_plld_clk_cfg_ex, pll_ref);
-
-DEFINE_PLL_OUT(pll_d_out0, DIV_2 | PLLD, 0, 0, 500000000, tegra30_pll_div_ops,
-		pll_d, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED);
-
-DEFINE_PLL(pll_d2, PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLD, 0x4b8, 1000000000,
-		2000000, 40000000, 1000000, 6000000, 40000000, 1000000000,
-		tegra_pll_d_freq_table, 1000, tegra30_pll_ops, 0, NULL,
-		pll_ref);
-
-DEFINE_PLL_OUT(pll_d2_out0, DIV_2 | PLLD, 0, 0, 500000000, tegra30_pll_div_ops,
-		pll_d2, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED);
-
-static struct clk_pll_freq_table tegra_pll_u_freq_table[] = {
-	{ 12000000, 480000000, 960, 12, 2, 12},
-	{ 13000000, 480000000, 960, 13, 2, 12},
-	{ 16800000, 480000000, 400, 7,  2, 5},
-	{ 19200000, 480000000, 200, 4,  2, 3},
-	{ 26000000, 480000000, 960, 26, 2, 12},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_u, PLL_HAS_CPCON | PLLU, 0xc0, 480000000, 2000000, 40000000,
-		1000000, 6000000, 48000000, 960000000, tegra_pll_u_freq_table,
-		1000, tegra30_pll_ops, 0, NULL, pll_ref);
-
-static struct clk_pll_freq_table tegra_pll_x_freq_table[] = {
-	/* 1.7 GHz */
-	{ 12000000, 1700000000, 850,  6,  1, 8},
-	{ 13000000, 1700000000, 915,  7,  1, 8},	/* actual: 1699.2 MHz */
-	{ 16800000, 1700000000, 708,  7,  1, 8},	/* actual: 1699.2 MHz */
-	{ 19200000, 1700000000, 885,  10, 1, 8},	/* actual: 1699.2 MHz */
-	{ 26000000, 1700000000, 850,  13, 1, 8},
-
-	/* 1.6 GHz */
-	{ 12000000, 1600000000, 800,  6,  1, 8},
-	{ 13000000, 1600000000, 738,  6,  1, 8},	/* actual: 1599.0 MHz */
-	{ 16800000, 1600000000, 857,  9,  1, 8},	/* actual: 1599.7 MHz */
-	{ 19200000, 1600000000, 500,  6,  1, 8},
-	{ 26000000, 1600000000, 800,  13, 1, 8},
-
-	/* 1.5 GHz */
-	{ 12000000, 1500000000, 750,  6,  1, 8},
-	{ 13000000, 1500000000, 923,  8,  1, 8},	/* actual: 1499.8 MHz */
-	{ 16800000, 1500000000, 625,  7,  1, 8},
-	{ 19200000, 1500000000, 625,  8,  1, 8},
-	{ 26000000, 1500000000, 750,  13, 1, 8},
-
-	/* 1.4 GHz */
-	{ 12000000, 1400000000, 700,  6,  1, 8},
-	{ 13000000, 1400000000, 969,  9,  1, 8},	/* actual: 1399.7 MHz */
-	{ 16800000, 1400000000, 1000, 12, 1, 8},
-	{ 19200000, 1400000000, 875,  12, 1, 8},
-	{ 26000000, 1400000000, 700,  13, 1, 8},
-
-	/* 1.3 GHz */
-	{ 12000000, 1300000000, 975,  9,  1, 8},
-	{ 13000000, 1300000000, 1000, 10, 1, 8},
-	{ 16800000, 1300000000, 928,  12, 1, 8},	/* actual: 1299.2 MHz */
-	{ 19200000, 1300000000, 812,  12, 1, 8},	/* actual: 1299.2 MHz */
-	{ 26000000, 1300000000, 650,  13, 1, 8},
-
-	/* 1.2 GHz */
-	{ 12000000, 1200000000, 1000, 10, 1, 8},
-	{ 13000000, 1200000000, 923,  10, 1, 8},	/* actual: 1199.9 MHz */
-	{ 16800000, 1200000000, 1000, 14, 1, 8},
-	{ 19200000, 1200000000, 1000, 16, 1, 8},
-	{ 26000000, 1200000000, 600,  13, 1, 8},
-
-	/* 1.1 GHz */
-	{ 12000000, 1100000000, 825,  9,  1, 8},
-	{ 13000000, 1100000000, 846,  10, 1, 8},	/* actual: 1099.8 MHz */
-	{ 16800000, 1100000000, 982,  15, 1, 8},	/* actual: 1099.8 MHz */
-	{ 19200000, 1100000000, 859,  15, 1, 8},	/* actual: 1099.5 MHz */
-	{ 26000000, 1100000000, 550,  13, 1, 8},
-
-	/* 1 GHz */
-	{ 12000000, 1000000000, 1000, 12, 1, 8},
-	{ 13000000, 1000000000, 1000, 13, 1, 8},
-	{ 16800000, 1000000000, 833,  14, 1, 8},	/* actual: 999.6 MHz */
-	{ 19200000, 1000000000, 625,  12, 1, 8},
-	{ 26000000, 1000000000, 1000, 26, 1, 8},
-
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_x, PLL_HAS_CPCON | PLL_ALT_MISC_REG | PLLX, 0xe0, 1700000000,
-		2000000, 31000000, 1000000, 6000000, 20000000, 1700000000,
-		tegra_pll_x_freq_table, 300, tegra30_pll_ops, 0, NULL, pll_ref);
-
-DEFINE_PLL_OUT(pll_x_out0, DIV_2 | PLLX, 0, 0, 850000000, tegra30_pll_div_ops,
-		pll_x, CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED);
-
-static struct clk_pll_freq_table tegra_pll_e_freq_table[] = {
-	/* PLLE special case: use cpcon field to store cml divider value */
-	{ 12000000,  100000000, 150, 1,  18, 11},
-	{ 216000000, 100000000, 200, 18, 24, 13},
-	{ 0, 0, 0, 0, 0, 0 },
-};
-
-DEFINE_PLL(pll_e, PLL_ALT_MISC_REG, 0xe8, 100000000, 2000000, 216000000,
-		12000000, 12000000, 1200000000, 2400000000U,
-		tegra_pll_e_freq_table, 300, tegra30_plle_ops, 100000000, NULL,
-		pll_ref);
-
-static const char *mux_plle[] = {
-	"pll_e",
-};
-
-static struct clk *mux_plle_p[] = {
-	&tegra_pll_e,
-};
-
-static struct clk tegra_cml0;
-static struct clk_tegra tegra_cml0_hw = {
-	.hw = {
-		.clk = &tegra_cml0,
-	},
-	.reg = 0x48c,
-	.fixed_rate = 100000000,
-	.u.periph = {
-		.clk_num = 0,
-	},
-};
-DEFINE_CLK_TEGRA(cml0, 0, &tegra_cml_clk_ops, 0, mux_plle,
-		mux_plle_p, &tegra_pll_e);
-
-static struct clk tegra_cml1;
-static struct clk_tegra tegra_cml1_hw = {
-	.hw = {
-		.clk = &tegra_cml1,
-	},
-	.reg = 0x48c,
-	.fixed_rate = 100000000,
-	.u.periph = {
-		.clk_num = 1,
-	},
-};
-DEFINE_CLK_TEGRA(cml1, 0, &tegra_cml_clk_ops, 0, mux_plle,
-		mux_plle_p, &tegra_pll_e);
-
-static struct clk tegra_pciex;
-static struct clk_tegra tegra_pciex_hw = {
-	.hw = {
-		.clk = &tegra_pciex,
-	},
-	.reg = 0x48c,
-	.fixed_rate = 100000000,
-	.reset = tegra30_periph_clk_reset,
-	.u.periph = {
-		.clk_num = 74,
-	},
-};
-DEFINE_CLK_TEGRA(pciex, 0, &tegra_pciex_clk_ops, 0, mux_plle,
-		mux_plle_p, &tegra_pll_e);
-
-#define SYNC_SOURCE(_name)					\
-	static struct clk tegra_##_name##_sync;			\
-	static struct clk_tegra tegra_##_name##_sync_hw = {	\
-		.hw = {						\
-			.clk = &tegra_##_name##_sync,		\
-		},						\
-		.max_rate = 24000000,				\
-		.fixed_rate = 24000000,				\
-	};							\
-	static struct clk tegra_##_name##_sync = {		\
-		.name = #_name "_sync",				\
-		.hw = &tegra_##_name##_sync_hw.hw,		\
-		.ops = &tegra_sync_source_ops,			\
-		.flags = CLK_IS_ROOT,				\
-	};
-
-SYNC_SOURCE(spdif_in);
-SYNC_SOURCE(i2s0);
-SYNC_SOURCE(i2s1);
-SYNC_SOURCE(i2s2);
-SYNC_SOURCE(i2s3);
-SYNC_SOURCE(i2s4);
-SYNC_SOURCE(vimclk);
-
-static struct clk *tegra_sync_source_list[] = {
-	&tegra_spdif_in_sync,
-	&tegra_i2s0_sync,
-	&tegra_i2s1_sync,
-	&tegra_i2s2_sync,
-	&tegra_i2s3_sync,
-	&tegra_i2s4_sync,
-	&tegra_vimclk_sync,
-};
-
-static const char *mux_audio_sync_clk[] = {
-	"spdif_in_sync",
-	"i2s0_sync",
-	"i2s1_sync",
-	"i2s2_sync",
-	"i2s3_sync",
-	"i2s4_sync",
-	"vimclk_sync",
-};
-
-#define AUDIO_SYNC_CLK(_name, _index)				\
-	static struct clk tegra_##_name;			\
-	static struct clk_tegra tegra_##_name##_hw = {		\
-		.hw = {						\
-			.clk = &tegra_##_name,			\
-		},						\
-		.max_rate = 24000000,				\
-		.reg = 0x4A0 + (_index) * 4,			\
-	};							\
-	static struct clk tegra_##_name = {			\
-		.name = #_name,					\
-		.ops = &tegra30_audio_sync_clk_ops,		\
-		.hw = &tegra_##_name##_hw.hw,			\
-		.parent_names = mux_audio_sync_clk,		\
-		.parents = tegra_sync_source_list,		\
-		.num_parents = ARRAY_SIZE(mux_audio_sync_clk),	\
-	};
-
-AUDIO_SYNC_CLK(audio0, 0);
-AUDIO_SYNC_CLK(audio1, 1);
-AUDIO_SYNC_CLK(audio2, 2);
-AUDIO_SYNC_CLK(audio3, 3);
-AUDIO_SYNC_CLK(audio4, 4);
-AUDIO_SYNC_CLK(audio5, 5);
-
-static struct clk *tegra_clk_audio_list[] = {
-	&tegra_audio0,
-	&tegra_audio1,
-	&tegra_audio2,
-	&tegra_audio3,
-	&tegra_audio4,
-	&tegra_audio5,	/* SPDIF */
-};
-
-#define AUDIO_SYNC_2X_CLK(_name, _index)			\
-	static const char *_name##_parent_names[] = {		\
-		"tegra_" #_name,				\
-	};							\
-	static struct clk *_name##_parents[] = {		\
-		&tegra_##_name,					\
-	};							\
-	static struct clk tegra_##_name##_2x;			\
-	static struct clk_tegra tegra_##_name##_2x_hw = {	\
-		.hw = {						\
-			.clk = &tegra_##_name##_2x,		\
-		},						\
-		.flags = PERIPH_NO_RESET,			\
-		.max_rate = 48000000,				\
-		.reg = 0x49C,					\
-		.reg_shift = 24 + (_index),			\
-		.u.periph = {					\
-			.clk_num = 113 + (_index),		\
-		},						\
-	};							\
-	static struct clk tegra_##_name##_2x = {		\
-		.name = #_name "_2x",				\
-		.ops = &tegra30_clk_double_ops,			\
-		.hw = &tegra_##_name##_2x_hw.hw,		\
-		.parent_names = _name##_parent_names,		\
-		.parents = _name##_parents,			\
-		.parent = &tegra_##_name,			\
-		.num_parents = 1,				\
-	};
-
-AUDIO_SYNC_2X_CLK(audio0, 0);
-AUDIO_SYNC_2X_CLK(audio1, 1);
-AUDIO_SYNC_2X_CLK(audio2, 2);
-AUDIO_SYNC_2X_CLK(audio3, 3);
-AUDIO_SYNC_2X_CLK(audio4, 4);
-AUDIO_SYNC_2X_CLK(audio5, 5);	/* SPDIF */
-
-static struct clk *tegra_clk_audio_2x_list[] = {
-	&tegra_audio0_2x,
-	&tegra_audio1_2x,
-	&tegra_audio2_2x,
-	&tegra_audio3_2x,
-	&tegra_audio4_2x,
-	&tegra_audio5_2x,	/* SPDIF */
-};
-
-#define MUX_I2S_SPDIF(_id)					\
-static const char *mux_pllaout0_##_id##_2x_pllp_clkm[] = {	\
-	"pll_a_out0",						\
-	#_id "_2x",						\
-	"pll_p",						\
-	"clk_m",						\
-};								\
-static struct clk *mux_pllaout0_##_id##_2x_pllp_clkm_p[] = {	\
-	&tegra_pll_a_out0,					\
-	&tegra_##_id##_2x,					\
-	&tegra_pll_p,						\
-	&tegra_clk_m,						\
-};
-
-MUX_I2S_SPDIF(audio0);
-MUX_I2S_SPDIF(audio1);
-MUX_I2S_SPDIF(audio2);
-MUX_I2S_SPDIF(audio3);
-MUX_I2S_SPDIF(audio4);
-MUX_I2S_SPDIF(audio5);		/* SPDIF */
-
-static struct clk tegra_extern1;
-static struct clk tegra_extern2;
-static struct clk tegra_extern3;
-
-/* External clock outputs (through PMC) */
-#define MUX_EXTERN_OUT(_id)					\
-static const char *mux_clkm_clkm2_clkm4_extern##_id[] = {	\
-	"clk_m",						\
-	"clk_m_div2",						\
-	"clk_m_div4",						\
-	"extern" #_id,						\
-};								\
-static struct clk *mux_clkm_clkm2_clkm4_extern##_id##_p[] = {	\
-	&tegra_clk_m,						\
-	&tegra_clk_m_div2,					\
-	&tegra_clk_m_div4,					\
-	&tegra_extern##_id,					\
-};
-
-MUX_EXTERN_OUT(1);
-MUX_EXTERN_OUT(2);
-MUX_EXTERN_OUT(3);
-
-#define CLK_OUT_CLK(_name, _index)					\
-	static struct clk tegra_##_name;				\
-	static struct clk_tegra tegra_##_name##_hw = {			\
-		.hw = {							\
-			.clk = &tegra_##_name,				\
-		},							\
-		.lookup = {						\
-			.dev_id	= #_name,				\
-			.con_id	= "extern" #_index,			\
-		},							\
-		.flags = MUX_CLK_OUT,					\
-		.fixed_rate = 216000000,					\
-		.reg = 0x1a8,						\
-		.u.periph = {						\
-			.clk_num = (_index - 1) * 8 + 2,		\
-		},							\
-	};								\
-	static struct clk tegra_##_name = {				\
-		.name = #_name,						\
-		.ops = &tegra_clk_out_ops,				\
-		.hw = &tegra_##_name##_hw.hw,				\
-		.parent_names = mux_clkm_clkm2_clkm4_extern##_index,	\
-		.parents = mux_clkm_clkm2_clkm4_extern##_index##_p,	\
-		.num_parents = ARRAY_SIZE(mux_clkm_clkm2_clkm4_extern##_index),\
-	};
-
-CLK_OUT_CLK(clk_out_1, 1);
-CLK_OUT_CLK(clk_out_2, 2);
-CLK_OUT_CLK(clk_out_3, 3);
-
-static struct clk *tegra_clk_out_list[] = {
-	&tegra_clk_out_1,
-	&tegra_clk_out_2,
-	&tegra_clk_out_3,
-};
-
-static const char *mux_sclk[] = {
-	"clk_m",
-	"pll_c_out1",
-	"pll_p_out4",
-	"pll_p_out3",
-	"pll_p_out2",
-	"dummy",
-	"clk_32k",
-	"pll_m_out1",
-};
-
-static struct clk *mux_sclk_p[] = {
-	&tegra_clk_m,
-	&tegra_pll_c_out1,
-	&tegra_pll_p_out4,
-	&tegra_pll_p_out3,
-	&tegra_pll_p_out2,
-	NULL,
-	&tegra_clk_32k,
-	&tegra_pll_m_out1,
-};
-
-static struct clk tegra_clk_sclk;
-static struct clk_tegra tegra_clk_sclk_hw = {
-	.hw = {
-		.clk = &tegra_clk_sclk,
-	},
-	.reg = 0x28,
-	.max_rate = 334000000,
-	.min_rate = 40000000,
-};
-
-static struct clk tegra_clk_sclk = {
-	.name = "sclk",
-	.ops = &tegra30_super_ops,
-	.hw = &tegra_clk_sclk_hw.hw,
-	.parent_names = mux_sclk,
-	.parents = mux_sclk_p,
-	.num_parents = ARRAY_SIZE(mux_sclk),
-};
-
-static const char *tegra_hclk_parent_names[] = {
-	"tegra_sclk",
-};
-
-static struct clk *tegra_hclk_parents[] = {
-	&tegra_clk_sclk,
-};
-
-static struct clk tegra_hclk;
-static struct clk_tegra tegra_hclk_hw = {
-	.hw = {
-		.clk = &tegra_hclk,
-	},
-	.flags = DIV_BUS,
-	.reg = 0x30,
-	.reg_shift = 4,
-	.max_rate = 378000000,
-	.min_rate = 12000000,
-};
-DEFINE_CLK_TEGRA(hclk, 0, &tegra30_bus_ops, 0, tegra_hclk_parent_names,
-		tegra_hclk_parents, &tegra_clk_sclk);
-
-static const char *tegra_pclk_parent_names[] = {
-	"tegra_hclk",
-};
-
-static struct clk *tegra_pclk_parents[] = {
-	&tegra_hclk,
-};
-
-static struct clk tegra_pclk;
-static struct clk_tegra tegra_pclk_hw = {
-	.hw = {
-		.clk = &tegra_pclk,
-	},
-	.flags = DIV_BUS,
-	.reg = 0x30,
-	.reg_shift = 0,
-	.max_rate = 167000000,
-	.min_rate = 12000000,
-};
-DEFINE_CLK_TEGRA(pclk, 0, &tegra30_bus_ops, 0, tegra_pclk_parent_names,
-		tegra_pclk_parents, &tegra_hclk);
-
-static const char *mux_blink[] = {
-	"clk_32k",
-};
-
-static struct clk *mux_blink_p[] = {
-	&tegra_clk_32k,
-};
-
-static struct clk tegra_clk_blink;
-static struct clk_tegra tegra_clk_blink_hw = {
-	.hw = {
-		.clk = &tegra_clk_blink,
-	},
-	.reg = 0x40,
-	.max_rate = 32768,
-};
-static struct clk tegra_clk_blink = {
-	.name = "blink",
-	.ops = &tegra30_blink_clk_ops,
-	.hw = &tegra_clk_blink_hw.hw,
-	.parent = &tegra_clk_32k,
-	.parent_names = mux_blink,
-	.parents = mux_blink_p,
-	.num_parents = ARRAY_SIZE(mux_blink),
-};
-
-static const char *mux_pllm_pllc_pllp_plla[] = {
-	"pll_m",
-	"pll_c",
-	"pll_p",
-	"pll_a_out0",
-};
-
-static const char *mux_pllp_pllc_pllm_clkm[] = {
-	"pll_p",
-	"pll_c",
-	"pll_m",
-	"clk_m",
-};
-
-static const char *mux_pllp_clkm[] = {
-	"pll_p",
-	"dummy",
-	"dummy",
-	"clk_m",
-};
-
-static const char *mux_pllp_plld_pllc_clkm[] = {
-	"pll_p",
-	"pll_d_out0",
-	"pll_c",
-	"clk_m",
-};
-
-static const char *mux_pllp_pllm_plld_plla_pllc_plld2_clkm[] = {
-	"pll_p",
-	"pll_m",
-	"pll_d_out0",
-	"pll_a_out0",
-	"pll_c",
-	"pll_d2_out0",
-	"clk_m",
-};
-
-static const char *mux_plla_pllc_pllp_clkm[] = {
-	"pll_a_out0",
-	"dummy",
-	"pll_p",
-	"clk_m"
-};
-
-static const char *mux_pllp_pllc_clk32_clkm[] = {
-	"pll_p",
-	"pll_c",
-	"clk_32k",
-	"clk_m",
-};
-
-static const char *mux_pllp_pllc_clkm_clk32[] = {
-	"pll_p",
-	"pll_c",
-	"clk_m",
-	"clk_32k",
-};
-
-static const char *mux_pllp_pllc_pllm[] = {
-	"pll_p",
-	"pll_c",
-	"pll_m",
-};
-
-static const char *mux_clk_m[] = {
-	"clk_m",
-};
-
-static const char *mux_pllp_out3[] = {
-	"pll_p_out3",
-};
-
-static const char *mux_plld_out0[] = {
-	"pll_d_out0",
-};
-
-static const char *mux_plld_out0_plld2_out0[] = {
-	"pll_d_out0",
-	"pll_d2_out0",
-};
-
-static const char *mux_clk_32k[] = {
-	"clk_32k",
-};
-
-static const char *mux_plla_clk32_pllp_clkm_plle[] = {
-	"pll_a_out0",
-	"clk_32k",
-	"pll_p",
-	"clk_m",
-	"pll_e",
-};
-
-static const char *mux_cclk_g[] = {
-	"clk_m",
-	"pll_c",
-	"clk_32k",
-	"pll_m",
-	"pll_p",
-	"pll_p_out4",
-	"pll_p_out3",
-	"dummy",
-	"pll_x",
-};
-
-static struct clk *mux_pllm_pllc_pllp_plla_p[] = {
-	&tegra_pll_m,
-	&tegra_pll_c,
-	&tegra_pll_p,
-	&tegra_pll_a_out0,
-};
-
-static struct clk *mux_pllp_pllc_pllm_clkm_p[] = {
-	&tegra_pll_p,
-	&tegra_pll_c,
-	&tegra_pll_m,
-	&tegra_clk_m,
-};
-
-static struct clk *mux_pllp_clkm_p[] = {
-	&tegra_pll_p,
-	NULL,
-	NULL,
-	&tegra_clk_m,
-};
-
-static struct clk *mux_pllp_plld_pllc_clkm_p[] = {
-	&tegra_pll_p,
-	&tegra_pll_d_out0,
-	&tegra_pll_c,
-	&tegra_clk_m,
-};
-
-static struct clk *mux_pllp_pllm_plld_plla_pllc_plld2_clkm_p[] = {
-	&tegra_pll_p,
-	&tegra_pll_m,
-	&tegra_pll_d_out0,
-	&tegra_pll_a_out0,
-	&tegra_pll_c,
-	&tegra_pll_d2_out0,
-	&tegra_clk_m,
-};
-
-static struct clk *mux_plla_pllc_pllp_clkm_p[] = {
-	&tegra_pll_a_out0,
-	NULL,
-	&tegra_pll_p,
-	&tegra_clk_m,
-};
-
-static struct clk *mux_pllp_pllc_clk32_clkm_p[] = {
-	&tegra_pll_p,
-	&tegra_pll_c,
-	&tegra_clk_32k,
-	&tegra_clk_m,
-};
-
-static struct clk *mux_pllp_pllc_clkm_clk32_p[] = {
-	&tegra_pll_p,
-	&tegra_pll_c,
-	&tegra_clk_m,
-	&tegra_clk_32k,
-};
-
-static struct clk *mux_pllp_pllc_pllm_p[] = {
-	&tegra_pll_p,
-	&tegra_pll_c,
-	&tegra_pll_m,
-};
-
-static struct clk *mux_clk_m_p[] = {
-	&tegra_clk_m,
-};
-
-static struct clk *mux_pllp_out3_p[] = {
-	&tegra_pll_p_out3,
-};
-
-static struct clk *mux_plld_out0_p[] = {
-	&tegra_pll_d_out0,
-};
-
-static struct clk *mux_plld_out0_plld2_out0_p[] = {
-	&tegra_pll_d_out0,
-	&tegra_pll_d2_out0,
-};
-
-static struct clk *mux_clk_32k_p[] = {
-	&tegra_clk_32k,
-};
-
-static struct clk *mux_plla_clk32_pllp_clkm_plle_p[] = {
-	&tegra_pll_a_out0,
-	&tegra_clk_32k,
-	&tegra_pll_p,
-	&tegra_clk_m,
-	&tegra_pll_e,
-};
-
-static struct clk *mux_cclk_g_p[] = {
-	&tegra_clk_m,
-	&tegra_pll_c,
-	&tegra_clk_32k,
-	&tegra_pll_m,
-	&tegra_pll_p,
-	&tegra_pll_p_out4,
-	&tegra_pll_p_out3,
-	NULL,
-	&tegra_pll_x,
-};
-
-static struct clk tegra_clk_cclk_g;
-static struct clk_tegra tegra_clk_cclk_g_hw = {
-	.hw = {
-		.clk = &tegra_clk_cclk_g,
-	},
-	.flags = DIV_U71 | DIV_U71_INT,
-	.reg = 0x368,
-	.max_rate = 1700000000,
-};
-static struct clk tegra_clk_cclk_g = {
-	.name = "cclk_g",
-	.ops = &tegra30_super_ops,
-	.hw = &tegra_clk_cclk_g_hw.hw,
-	.parent_names = mux_cclk_g,
-	.parents = mux_cclk_g_p,
-	.num_parents = ARRAY_SIZE(mux_cclk_g),
-};
-
-static const char *mux_twd[] = {
-	"cclk_g",
-};
-
-static struct clk *mux_twd_p[] = {
-	&tegra_clk_cclk_g,
-};
-
-static struct clk tegra30_clk_twd;
-static struct clk_tegra tegra30_clk_twd_hw = {
-	.hw = {
-		.clk = &tegra30_clk_twd,
-	},
-	.max_rate = 1400000000,
-	.mul = 1,
-	.div = 2,
-};
-
-static struct clk tegra30_clk_twd = {
-	.name = "twd",
-	.ops = &tegra30_twd_ops,
-	.hw = &tegra30_clk_twd_hw.hw,
-	.parent = &tegra_clk_cclk_g,
-	.parent_names = mux_twd,
-	.parents = mux_twd_p,
-	.num_parents = ARRAY_SIZE(mux_twd),
-};
-
-#define PERIPH_CLK(_name, _dev, _con, _clk_num, _reg,	\
-		_max, _inputs, _flags)	 		\
-	static struct clk tegra_##_name;		\
-	static struct clk_tegra tegra_##_name##_hw = {	\
-		.hw = {					\
-			.clk = &tegra_##_name,		\
-		},					\
-		.lookup = {				\
-			.dev_id	= _dev,			\
-			.con_id	= _con,			\
-		},					\
-		.reg = _reg,				\
-		.flags = _flags,			\
-		.max_rate = _max,			\
-		.u.periph = {				\
-			.clk_num = _clk_num,		\
-		},					\
-		.reset = &tegra30_periph_clk_reset,	\
-	};						\
-	static struct clk tegra_##_name = {		\
-		.name = #_name,				\
-		.ops = &tegra30_periph_clk_ops,		\
-		.hw = &tegra_##_name##_hw.hw,		\
-		.parent_names = _inputs,		\
-		.parents = _inputs##_p,			\
-		.num_parents = ARRAY_SIZE(_inputs),	\
-	};
-
-PERIPH_CLK(apbdma,	"tegra-apbdma",		NULL,	34,	0,	26000000,  mux_clk_m,			0);
-PERIPH_CLK(rtc,		"rtc-tegra",		NULL,	4,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET | PERIPH_ON_APB);
-PERIPH_CLK(kbc,		"tegra-kbc",		NULL,	36,	0,	32768,     mux_clk_32k,			PERIPH_NO_RESET | PERIPH_ON_APB);
-PERIPH_CLK(timer,	"timer",		NULL,	5,	0,	26000000,  mux_clk_m,			0);
-PERIPH_CLK(kfuse,	"kfuse-tegra",		NULL,	40,	0,	26000000,  mux_clk_m,			0);
-PERIPH_CLK(fuse,	"fuse-tegra",		"fuse",	39,	0,	26000000,  mux_clk_m,			PERIPH_ON_APB);
-PERIPH_CLK(fuse_burn,	"fuse-tegra",		"fuse_burn",	39,	0,	26000000,  mux_clk_m,		PERIPH_ON_APB);
-PERIPH_CLK(apbif,	"tegra30-ahub",		"apbif", 107,	0,	26000000,  mux_clk_m,			0);
-PERIPH_CLK(i2s0,	"tegra30-i2s.0",	NULL,	30,	0x1d8,	26000000,  mux_pllaout0_audio0_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(i2s1,	"tegra30-i2s.1",	NULL,	11,	0x100,	26000000,  mux_pllaout0_audio1_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(i2s2,	"tegra30-i2s.2",	NULL,	18,	0x104,	26000000,  mux_pllaout0_audio2_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(i2s3,	"tegra30-i2s.3",	NULL,	101,	0x3bc,	26000000,  mux_pllaout0_audio3_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(i2s4,	"tegra30-i2s.4",	NULL,	102,	0x3c0,	26000000,  mux_pllaout0_audio4_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(spdif_out,	"tegra30-spdif",	"spdif_out",	10,	0x108,	100000000, mux_pllaout0_audio5_2x_pllp_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(spdif_in,	"tegra30-spdif",	"spdif_in",	10,	0x10c,	100000000, mux_pllp_pllc_pllm,		MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(pwm,		"tegra-pwm",		NULL,	17,	0x110,	432000000, mux_pllp_pllc_clk32_clkm,	MUX | MUX_PWM | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(d_audio,	"tegra30-ahub",		"d_audio", 106,	0x3d0,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71);
-PERIPH_CLK(dam0,	"tegra30-dam.0",	NULL,	108,	0x3d8,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71);
-PERIPH_CLK(dam1,	"tegra30-dam.1",	NULL,	109,	0x3dc,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71);
-PERIPH_CLK(dam2,	"tegra30-dam.2",	NULL,	110,	0x3e0,	48000000,  mux_plla_pllc_pllp_clkm,	MUX | DIV_U71);
-PERIPH_CLK(hda,		"tegra30-hda",		"hda",	125,	0x428,	108000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(hda2codec_2x,	"tegra30-hda",	"hda2codec",	111,	0x3e4,	48000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(hda2hdmi,	"tegra30-hda",		"hda2hdmi",	128,	0,	48000000,  mux_clk_m,			0);
-PERIPH_CLK(sbc1,	"spi_tegra.0",		NULL,	41,	0x134,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(sbc2,	"spi_tegra.1",		NULL,	44,	0x118,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(sbc3,	"spi_tegra.2",		NULL,	46,	0x11c,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(sbc4,	"spi_tegra.3",		NULL,	68,	0x1b4,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(sbc5,	"spi_tegra.4",		NULL,	104,	0x3c8,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(sbc6,	"spi_tegra.5",		NULL,	105,	0x3cc,	160000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(sata_oob,	"tegra_sata_oob",	NULL,	123,	0x420,	216000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(sata,	"tegra_sata",		NULL,	124,	0x424,	216000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(sata_cold,	"tegra_sata_cold",	NULL,	129,	0,	48000000,  mux_clk_m,			0);
-PERIPH_CLK(ndflash,	"tegra_nand",		NULL,	13,	0x160,	240000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(ndspeed,	"tegra_nand_speed",	NULL,	80,	0x3f8,	240000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(vfir,	"vfir",			NULL,	7,	0x168,	72000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(sdmmc1,	"sdhci-tegra.0",	NULL,	14,	0x150,	208000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
-PERIPH_CLK(sdmmc2,	"sdhci-tegra.1",	NULL,	9,	0x154,	104000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
-PERIPH_CLK(sdmmc3,	"sdhci-tegra.2",	NULL,	69,	0x1bc,	208000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
-PERIPH_CLK(sdmmc4,	"sdhci-tegra.3",	NULL,	15,	0x164,	104000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* scales with voltage */
-PERIPH_CLK(vcp,		"tegra-avp",		"vcp",	29,	0,	250000000, mux_clk_m,			0);
-PERIPH_CLK(bsea,	"tegra-avp",		"bsea",	62,	0,	250000000, mux_clk_m,			0);
-PERIPH_CLK(bsev,	"tegra-aes",		"bsev",	63,	0,	250000000, mux_clk_m,			0);
-PERIPH_CLK(vde,		"vde",			NULL,	61,	0x1c8,	520000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_INT);
-PERIPH_CLK(csite,	"csite",		NULL,	73,	0x1d4,	144000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* max rate ??? */
-PERIPH_CLK(la,		"la",			NULL,	76,	0x1f8,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71);
-PERIPH_CLK(owr,		"tegra_w1",		NULL,	71,	0x1cc,	26000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(nor,		"nor",			NULL,	42,	0x1d0,	127000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71); /* requires min voltage */
-PERIPH_CLK(mipi,	"mipi",			NULL,	50,	0x174,	60000000,  mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | PERIPH_ON_APB); /* scales with voltage */
-PERIPH_CLK(i2c1,	"tegra-i2c.0",		"div-clk", 12,	0x124,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
-PERIPH_CLK(i2c2,	"tegra-i2c.1",		"div-clk", 54,	0x198,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
-PERIPH_CLK(i2c3,	"tegra-i2c.2",		"div-clk", 67,	0x1b8,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
-PERIPH_CLK(i2c4,	"tegra-i2c.3",		"div-clk", 103,	0x3c4,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
-PERIPH_CLK(i2c5,	"tegra-i2c.4",		"div-clk", 47,	0x128,	26000000,  mux_pllp_clkm,		MUX | DIV_U16 | PERIPH_ON_APB);
-PERIPH_CLK(uarta,	"tegra-uart.0",		NULL,	6,	0x178,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB);
-PERIPH_CLK(uartb,	"tegra-uart.1",		NULL,	7,	0x17c,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB);
-PERIPH_CLK(uartc,	"tegra-uart.2",		NULL,	55,	0x1a0,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB);
-PERIPH_CLK(uartd,	"tegra-uart.3",		NULL,	65,	0x1c0,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB);
-PERIPH_CLK(uarte,	"tegra-uart.4",		NULL,	66,	0x1c4,	800000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB);
-PERIPH_CLK(vi,		"tegra_camera",		"vi",	20,	0x148,	425000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT);
-PERIPH_CLK(3d,		"3d",			NULL,	24,	0x158,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET);
-PERIPH_CLK(3d2,		"3d2",			NULL,	98,	0x3b0,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE | PERIPH_MANUAL_RESET);
-PERIPH_CLK(2d,		"2d",			NULL,	21,	0x15c,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT | DIV_U71_IDLE);
-PERIPH_CLK(vi_sensor,	"tegra_camera",		"vi_sensor",	20,	0x1a8,	150000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | PERIPH_NO_RESET);
-PERIPH_CLK(epp,		"epp",			NULL,	19,	0x16c,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT);
-PERIPH_CLK(mpe,		"mpe",			NULL,	60,	0x170,	520000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT);
-PERIPH_CLK(host1x,	"host1x",		NULL,	28,	0x180,	260000000, mux_pllm_pllc_pllp_plla,	MUX | DIV_U71 | DIV_U71_INT);
-PERIPH_CLK(cve,		"cve",			NULL,	49,	0x140,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
-PERIPH_CLK(tvo,		"tvo",			NULL,	49,	0x188,	250000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
-PERIPH_CLK(dtv,		"dtv",			NULL,	79,	0x1dc,	250000000, mux_clk_m,			0);
-PERIPH_CLK(hdmi,	"hdmi",			NULL,	51,	0x18c,	148500000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8 | DIV_U71);
-PERIPH_CLK(tvdac,	"tvdac",		NULL,	53,	0x194,	220000000, mux_pllp_plld_pllc_clkm,	MUX | DIV_U71); /* requires min voltage */
-PERIPH_CLK(disp1,	"tegradc.0",		NULL,	27,	0x138,	600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8);
-PERIPH_CLK(disp2,	"tegradc.1",		NULL,	26,	0x13c,	600000000, mux_pllp_pllm_plld_plla_pllc_plld2_clkm,	MUX | MUX8);
-PERIPH_CLK(usbd,	"fsl-tegra-udc",	NULL,	22,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
-PERIPH_CLK(usb2,	"tegra-ehci.1",		NULL,	58,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
-PERIPH_CLK(usb3,	"tegra-ehci.2",		NULL,	59,	0,	480000000, mux_clk_m,			0); /* requires min voltage */
-PERIPH_CLK(dsia,	"tegradc.0",		"dsia",	48,	0,	500000000, mux_plld_out0,		0);
-PERIPH_CLK(csi,		"tegra_camera",		"csi",	52,	0,	102000000, mux_pllp_out3,		0);
-PERIPH_CLK(isp,		"tegra_camera",		"isp",	23,	0,	150000000, mux_clk_m,			0); /* same frequency as VI */
-PERIPH_CLK(csus,	"tegra_camera",		"csus",	92,	0,	150000000, mux_clk_m,			PERIPH_NO_RESET);
-PERIPH_CLK(tsensor,	"tegra-tsensor",	NULL,	100,	0x3b8,	216000000, mux_pllp_pllc_clkm_clk32,	MUX | DIV_U71);
-PERIPH_CLK(actmon,	"actmon",		NULL,	119,	0x3e8,	216000000, mux_pllp_pllc_clk32_clkm,	MUX | DIV_U71);
-PERIPH_CLK(extern1,	"extern1",		NULL,	120,	0x3ec,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71);
-PERIPH_CLK(extern2,	"extern2",		NULL,	121,	0x3f0,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71);
-PERIPH_CLK(extern3,	"extern3",		NULL,	122,	0x3f4,	216000000, mux_plla_clk32_pllp_clkm_plle,	MUX | MUX8 | DIV_U71);
-PERIPH_CLK(i2cslow,	"i2cslow",		NULL,	81,	0x3fc,	26000000,  mux_pllp_pllc_clk32_clkm,	MUX | DIV_U71 | PERIPH_ON_APB);
-PERIPH_CLK(pcie,	"tegra-pcie",		"pcie",	70,	0,	250000000, mux_clk_m,			0);
-PERIPH_CLK(afi,		"tegra-pcie",		"afi",	72,	0,	250000000, mux_clk_m,			0);
-PERIPH_CLK(se,		"se",			NULL,	127,	0x42c,	520000000, mux_pllp_pllc_pllm_clkm,	MUX | DIV_U71 | DIV_U71_INT);
-
-static struct clk tegra_dsib;
-static struct clk_tegra tegra_dsib_hw = {
-	.hw = {
-		.clk = &tegra_dsib,
-	},
-	.lookup = {
-		.dev_id	= "tegradc.1",
-		.con_id	= "dsib",
-	},
-	.reg = 0xd0,
-	.flags = MUX | PLLD,
-	.max_rate = 500000000,
-	.u.periph = {
-		.clk_num = 82,
-	},
-	.reset = &tegra30_periph_clk_reset,
-};
-static struct clk tegra_dsib = {
-	.name = "dsib",
-	.ops = &tegra30_dsib_clk_ops,
-	.hw = &tegra_dsib_hw.hw,
-	.parent_names = mux_plld_out0_plld2_out0,
-	.parents = mux_plld_out0_plld2_out0_p,
-	.num_parents = ARRAY_SIZE(mux_plld_out0_plld2_out0),
-};
-
-struct clk *tegra_list_clks[] = {
-	&tegra_apbdma,
-	&tegra_rtc,
-	&tegra_kbc,
-	&tegra_timer,
-	&tegra_kfuse,
-	&tegra_fuse,
-	&tegra_fuse_burn,
-	&tegra_apbif,
-	&tegra_i2s0,
-	&tegra_i2s1,
-	&tegra_i2s2,
-	&tegra_i2s3,
-	&tegra_i2s4,
-	&tegra_spdif_out,
-	&tegra_spdif_in,
-	&tegra_pwm,
-	&tegra_d_audio,
-	&tegra_dam0,
-	&tegra_dam1,
-	&tegra_dam2,
-	&tegra_hda,
-	&tegra_hda2codec_2x,
-	&tegra_hda2hdmi,
-	&tegra_sbc1,
-	&tegra_sbc2,
-	&tegra_sbc3,
-	&tegra_sbc4,
-	&tegra_sbc5,
-	&tegra_sbc6,
-	&tegra_sata_oob,
-	&tegra_sata,
-	&tegra_sata_cold,
-	&tegra_ndflash,
-	&tegra_ndspeed,
-	&tegra_vfir,
-	&tegra_sdmmc1,
-	&tegra_sdmmc2,
-	&tegra_sdmmc3,
-	&tegra_sdmmc4,
-	&tegra_vcp,
-	&tegra_bsea,
-	&tegra_bsev,
-	&tegra_vde,
-	&tegra_csite,
-	&tegra_la,
-	&tegra_owr,
-	&tegra_nor,
-	&tegra_mipi,
-	&tegra_i2c1,
-	&tegra_i2c2,
-	&tegra_i2c3,
-	&tegra_i2c4,
-	&tegra_i2c5,
-	&tegra_uarta,
-	&tegra_uartb,
-	&tegra_uartc,
-	&tegra_uartd,
-	&tegra_uarte,
-	&tegra_vi,
-	&tegra_3d,
-	&tegra_3d2,
-	&tegra_2d,
-	&tegra_vi_sensor,
-	&tegra_epp,
-	&tegra_mpe,
-	&tegra_host1x,
-	&tegra_cve,
-	&tegra_tvo,
-	&tegra_dtv,
-	&tegra_hdmi,
-	&tegra_tvdac,
-	&tegra_disp1,
-	&tegra_disp2,
-	&tegra_usbd,
-	&tegra_usb2,
-	&tegra_usb3,
-	&tegra_dsia,
-	&tegra_dsib,
-	&tegra_csi,
-	&tegra_isp,
-	&tegra_csus,
-	&tegra_tsensor,
-	&tegra_actmon,
-	&tegra_extern1,
-	&tegra_extern2,
-	&tegra_extern3,
-	&tegra_i2cslow,
-	&tegra_pcie,
-	&tegra_afi,
-	&tegra_se,
-};
-
-#define CLK_DUPLICATE(_name, _dev, _con)	\
-	{					\
-		.name	= _name,		\
-		.lookup	= {			\
-			.dev_id	= _dev,		\
-			.con_id	= _con,		\
-		},				\
-	}
-
-/* Some clocks may be used by different drivers depending on the board
- * configuration.  List those here to register them twice in the clock lookup
- * table under two names.
- */
-struct clk_duplicate tegra_clk_duplicates[] = {
-	CLK_DUPLICATE("uarta",  "serial8250.0", NULL),
-	CLK_DUPLICATE("uartb",  "serial8250.1", NULL),
-	CLK_DUPLICATE("uartc",  "serial8250.2", NULL),
-	CLK_DUPLICATE("uartd",  "serial8250.3", NULL),
-	CLK_DUPLICATE("uarte",  "serial8250.4", NULL),
-	CLK_DUPLICATE("usbd", "utmip-pad", NULL),
-	CLK_DUPLICATE("usbd", "tegra-ehci.0", NULL),
-	CLK_DUPLICATE("usbd", "tegra-otg", NULL),
-	CLK_DUPLICATE("dsib", "tegradc.0", "dsib"),
-	CLK_DUPLICATE("dsia", "tegradc.1", "dsia"),
-	CLK_DUPLICATE("bsev", "tegra-avp", "bsev"),
-	CLK_DUPLICATE("bsev", "nvavp", "bsev"),
-	CLK_DUPLICATE("vde", "tegra-aes", "vde"),
-	CLK_DUPLICATE("bsea", "tegra-aes", "bsea"),
-	CLK_DUPLICATE("bsea", "nvavp", "bsea"),
-	CLK_DUPLICATE("cml1", "tegra_sata_cml", NULL),
-	CLK_DUPLICATE("cml0", "tegra_pcie", "cml"),
-	CLK_DUPLICATE("pciex", "tegra_pcie", "pciex"),
-	CLK_DUPLICATE("i2c1", "tegra-i2c-slave.0", NULL),
-	CLK_DUPLICATE("i2c2", "tegra-i2c-slave.1", NULL),
-	CLK_DUPLICATE("i2c3", "tegra-i2c-slave.2", NULL),
-	CLK_DUPLICATE("i2c4", "tegra-i2c-slave.3", NULL),
-	CLK_DUPLICATE("i2c5", "tegra-i2c-slave.4", NULL),
-	CLK_DUPLICATE("sbc1", "spi_slave_tegra.0", NULL),
-	CLK_DUPLICATE("sbc2", "spi_slave_tegra.1", NULL),
-	CLK_DUPLICATE("sbc3", "spi_slave_tegra.2", NULL),
-	CLK_DUPLICATE("sbc4", "spi_slave_tegra.3", NULL),
-	CLK_DUPLICATE("sbc5", "spi_slave_tegra.4", NULL),
-	CLK_DUPLICATE("sbc6", "spi_slave_tegra.5", NULL),
-	CLK_DUPLICATE("twd", "smp_twd", NULL),
-	CLK_DUPLICATE("vcp", "nvavp", "vcp"),
-	CLK_DUPLICATE("i2s0", NULL, "i2s0"),
-	CLK_DUPLICATE("i2s1", NULL, "i2s1"),
-	CLK_DUPLICATE("i2s2", NULL, "i2s2"),
-	CLK_DUPLICATE("i2s3", NULL, "i2s3"),
-	CLK_DUPLICATE("i2s4", NULL, "i2s4"),
-	CLK_DUPLICATE("dam0", NULL, "dam0"),
-	CLK_DUPLICATE("dam1", NULL, "dam1"),
-	CLK_DUPLICATE("dam2", NULL, "dam2"),
-	CLK_DUPLICATE("spdif_in", NULL, "spdif_in"),
-	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.0", "fast-clk"),
-	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.1", "fast-clk"),
-	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.2", "fast-clk"),
-	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.3", "fast-clk"),
-	CLK_DUPLICATE("pll_p_out3", "tegra-i2c.4", "fast-clk"),
-	CLK_DUPLICATE("pll_p", "tegradc.0", "parent"),
-	CLK_DUPLICATE("pll_p", "tegradc.1", "parent"),
-	CLK_DUPLICATE("pll_d2_out0", "hdmi", "parent"),
-};
-
-struct clk *tegra_ptr_clks[] = {
-	&tegra_clk_32k,
-	&tegra_clk_m,
-	&tegra_clk_m_div2,
-	&tegra_clk_m_div4,
-	&tegra_pll_ref,
-	&tegra_pll_m,
-	&tegra_pll_m_out1,
-	&tegra_pll_c,
-	&tegra_pll_c_out1,
-	&tegra_pll_p,
-	&tegra_pll_p_out1,
-	&tegra_pll_p_out2,
-	&tegra_pll_p_out3,
-	&tegra_pll_p_out4,
-	&tegra_pll_a,
-	&tegra_pll_a_out0,
-	&tegra_pll_d,
-	&tegra_pll_d_out0,
-	&tegra_pll_d2,
-	&tegra_pll_d2_out0,
-	&tegra_pll_u,
-	&tegra_pll_x,
-	&tegra_pll_x_out0,
-	&tegra_pll_e,
-	&tegra_clk_cclk_g,
-	&tegra_cml0,
-	&tegra_cml1,
-	&tegra_pciex,
-	&tegra_clk_sclk,
-	&tegra_hclk,
-	&tegra_pclk,
-	&tegra_clk_blink,
-	&tegra30_clk_twd,
-};
-
-static void tegra30_init_one_clock(struct clk *c)
-{
-	struct clk_tegra *clk = to_clk_tegra(c->hw);
-	__clk_init(NULL, c);
-	INIT_LIST_HEAD(&clk->shared_bus_list);
-	if (!clk->lookup.dev_id && !clk->lookup.con_id)
-		clk->lookup.con_id = c->name;
-	clk->lookup.clk = c;
-	clkdev_add(&clk->lookup);
-	tegra_clk_add(c);
-}
-
-void __init tegra30_init_clocks(void)
-{
-	int i;
-	struct clk *c;
-
-	for (i = 0; i < ARRAY_SIZE(tegra_ptr_clks); i++)
-		tegra30_init_one_clock(tegra_ptr_clks[i]);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_list_clks); i++)
-		tegra30_init_one_clock(tegra_list_clks[i]);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_duplicates); i++) {
-		c = tegra_get_clock_by_name(tegra_clk_duplicates[i].name);
-		if (!c) {
-			pr_err("%s: Unknown duplicate clock %s\n", __func__,
-				tegra_clk_duplicates[i].name);
-			continue;
-		}
-
-		tegra_clk_duplicates[i].lookup.clk = c;
-		clkdev_add(&tegra_clk_duplicates[i].lookup);
-	}
-
-	for (i = 0; i < ARRAY_SIZE(tegra_sync_source_list); i++)
-		tegra30_init_one_clock(tegra_sync_source_list[i]);
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_list); i++)
-		tegra30_init_one_clock(tegra_clk_audio_list[i]);
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_audio_2x_list); i++)
-		tegra30_init_one_clock(tegra_clk_audio_2x_list[i]);
-
-	for (i = 0; i < ARRAY_SIZE(tegra_clk_out_list); i++)
-		tegra30_init_one_clock(tegra_clk_out_list[i]);
-
-	tegra30_cpu_car_ops_init();
-}
diff --git a/arch/arm/mach-u300/core.c b/arch/arm/mach-u300/core.c
index 4ce77cd..12060ae 100644
--- a/arch/arm/mach-u300/core.c
+++ b/arch/arm/mach-u300/core.c
@@ -31,11 +31,11 @@
 #include <linux/dma-mapping.h>
 #include <linux/platform_data/clk-u300.h>
 #include <linux/platform_data/pinctrl-coh901.h>
+#include <linux/irqchip/arm-vic.h>
 
 #include <asm/types.h>
 #include <asm/setup.h>
 #include <asm/memory.h>
-#include <asm/hardware/vic.h>
 #include <asm/mach/map.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -1779,8 +1779,7 @@
 	.map_io		= u300_map_io,
 	.nr_irqs	= 0,
 	.init_irq	= u300_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &u300_timer,
+	.init_time	= u300_timer_init,
 	.init_machine	= u300_init_machine,
 	.restart	= u300_restart,
 MACHINE_END
diff --git a/arch/arm/mach-u300/timer.c b/arch/arm/mach-u300/timer.c
index 1da10e2..d9e7320 100644
--- a/arch/arm/mach-u300/timer.c
+++ b/arch/arm/mach-u300/timer.c
@@ -349,7 +349,7 @@
 /*
  * This sets up the system timers, clock source and clock event.
  */
-static void __init u300_timer_init(void)
+void __init u300_timer_init(void)
 {
 	struct clk *clk;
 	unsigned long rate;
@@ -413,11 +413,3 @@
 	 * used by hrtimers!
 	 */
 }
-
-/*
- * Very simple system timer that only register the clock event and
- * clock source.
- */
-struct sys_timer u300_timer = {
-	.init		= u300_timer_init,
-};
diff --git a/arch/arm/mach-u300/timer.h b/arch/arm/mach-u300/timer.h
index b5e9791..d34287b 100644
--- a/arch/arm/mach-u300/timer.h
+++ b/arch/arm/mach-u300/timer.h
@@ -1 +1 @@
-extern struct sys_timer u300_timer;
+extern void u300_timer_init(void);
diff --git a/arch/arm/mach-ux500/board-mop500.c b/arch/arm/mach-ux500/board-mop500.c
index d453522..0e928d2 100644
--- a/arch/arm/mach-ux500/board-mop500.c
+++ b/arch/arm/mach-ux500/board-mop500.c
@@ -40,7 +40,6 @@
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
@@ -751,8 +750,7 @@
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
-	.timer		= &ux500_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= ux500_timer_init,
 	.init_machine	= mop500_init_machine,
 	.init_late	= ux500_init_late,
 MACHINE_END
@@ -761,8 +759,7 @@
 	.atag_offset	= 0x100,
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
-	.timer		= &ux500_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= ux500_timer_init,
 	.init_machine	= mop500_init_machine,
 	.init_late	= ux500_init_late,
 MACHINE_END
@@ -772,8 +769,7 @@
 	.smp		= smp_ops(ux500_smp_ops),
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
-	.timer		= &ux500_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= ux500_timer_init,
 	.init_machine	= hrefv60_init_machine,
 	.init_late	= ux500_init_late,
 MACHINE_END
@@ -784,8 +780,7 @@
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
-	.timer		= &ux500_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= ux500_timer_init,
 	.init_machine	= snowball_init_machine,
 	.init_late	= NULL,
 MACHINE_END
diff --git a/arch/arm/mach-ux500/cpu-db8500.c b/arch/arm/mach-ux500/cpu-db8500.c
index 5b286e0..218a6b1 100644
--- a/arch/arm/mach-ux500/cpu-db8500.c
+++ b/arch/arm/mach-ux500/cpu-db8500.c
@@ -27,7 +27,6 @@
 #include <asm/pmu.h>
 #include <asm/mach/map.h>
 #include <asm/mach/arch.h>
-#include <asm/hardware/gic.h>
 
 #include <mach/hardware.h>
 #include <mach/setup.h>
@@ -341,8 +340,7 @@
 	.map_io		= u8500_map_io,
 	.init_irq	= ux500_init_irq,
 	/* we re-use nomadik timer here */
-	.timer		= &ux500_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= ux500_timer_init,
 	.init_machine	= u8500_init_machine,
 	.init_late	= NULL,
 	.dt_compat      = stericsson_dt_platform_compat,
diff --git a/arch/arm/mach-ux500/cpu.c b/arch/arm/mach-ux500/cpu.c
index 721e7b4..5dd90d3 100644
--- a/arch/arm/mach-ux500/cpu.c
+++ b/arch/arm/mach-ux500/cpu.c
@@ -17,9 +17,10 @@
 #include <linux/of.h>
 #include <linux/of_irq.h>
 #include <linux/irq.h>
+#include <linux/irqchip.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/platform_data/clk-ux500.h>
 
-#include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 
 #include <mach/hardware.h>
@@ -42,11 +43,6 @@
  * This feels fragile because it depends on the gpio device getting probed
  * _before_ any device uses the gpio interrupts.
 */
-static const struct of_device_id ux500_dt_irq_match[] = {
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-	{},
-};
-
 void __init ux500_init_irq(void)
 {
 	void __iomem *dist_base;
@@ -62,7 +58,7 @@
 
 #ifdef CONFIG_OF
 	if (of_have_populated_dt())
-		of_irq_init(ux500_dt_irq_match);
+		irqchip_init();
 	else
 #endif
 		gic_init(0, 29, dist_base, cpu_base);
diff --git a/arch/arm/mach-ux500/include/mach/setup.h b/arch/arm/mach-ux500/include/mach/setup.h
index 6be4c4d..bddce2b 100644
--- a/arch/arm/mach-ux500/include/mach/setup.h
+++ b/arch/arm/mach-ux500/include/mach/setup.h
@@ -28,8 +28,7 @@
 struct amba_device;
 extern void __init amba_add_devices(struct amba_device *devs[], int num);
 
-struct sys_timer;
-extern struct sys_timer ux500_timer;
+extern void ux500_timer_init(void);
 
 #define __IO_DEV_DESC(x, sz)	{		\
 	.virtual	= IO_ADDRESS(x),	\
diff --git a/arch/arm/mach-ux500/platsmp.c b/arch/arm/mach-ux500/platsmp.c
index 3db7782..b8adac9 100644
--- a/arch/arm/mach-ux500/platsmp.c
+++ b/arch/arm/mach-ux500/platsmp.c
@@ -16,9 +16,9 @@
 #include <linux/device.h>
 #include <linux/smp.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include <asm/cacheflush.h>
-#include <asm/hardware/gic.h>
 #include <asm/smp_plat.h>
 #include <asm/smp_scu.h>
 #include <mach/hardware.h>
@@ -91,7 +91,7 @@
 	 */
 	write_pen_release(cpu_logical_map(cpu));
 
-	smp_send_reschedule(cpu);
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
@@ -155,8 +155,6 @@
 
 	for (i = 0; i < ncores; i++)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
 
 static void __init ux500_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-ux500/timer.c b/arch/arm/mach-ux500/timer.c
index 875309a..aa2a78a 100644
--- a/arch/arm/mach-ux500/timer.c
+++ b/arch/arm/mach-ux500/timer.c
@@ -46,7 +46,7 @@
 	{ },
 };
 
-static void __init ux500_timer_init(void)
+void __init ux500_timer_init(void)
 {
 	void __iomem *mtu_timer_base;
 	void __iomem *prcmu_timer_base;
@@ -99,14 +99,3 @@
 	clksrc_dbx500_prcmu_init(prcmu_timer_base);
 	ux500_twd_init();
 }
-
-static void ux500_timer_reset(void)
-{
-	nmdk_clkevt_reset();
-	nmdk_clksrc_reset();
-}
-
-struct sys_timer ux500_timer = {
-	.init		= ux500_timer_init,
-	.resume		= ux500_timer_reset,
-};
diff --git a/arch/arm/mach-versatile/core.c b/arch/arm/mach-versatile/core.c
index 5d59294..a42b890 100644
--- a/arch/arm/mach-versatile/core.c
+++ b/arch/arm/mach-versatile/core.c
@@ -32,6 +32,7 @@
 #include <linux/amba/mmci.h>
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
+#include <linux/irqchip/arm-vic.h>
 #include <linux/irqchip/versatile-fpga.h>
 #include <linux/gfp.h>
 #include <linux/clkdev.h>
@@ -40,7 +41,6 @@
 #include <asm/irq.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/icst.h>
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 
 #include <asm/mach/arch.h>
@@ -770,7 +770,7 @@
 /*
  * Set up timer interrupt, and return the current time in seconds.
  */
-static void __init versatile_timer_init(void)
+void __init versatile_timer_init(void)
 {
 	u32 val;
 
@@ -797,8 +797,3 @@
 	sp804_clocksource_init(TIMER3_VA_BASE, "timer3");
 	sp804_clockevents_init(TIMER0_VA_BASE, IRQ_TIMERINT0_1, "timer0");
 }
-
-struct sys_timer versatile_timer = {
-	.init		= versatile_timer_init,
-};
-
diff --git a/arch/arm/mach-versatile/core.h b/arch/arm/mach-versatile/core.h
index 683e607..5c1b87d 100644
--- a/arch/arm/mach-versatile/core.h
+++ b/arch/arm/mach-versatile/core.h
@@ -29,7 +29,7 @@
 extern void __init versatile_init_early(void);
 extern void __init versatile_init_irq(void);
 extern void __init versatile_map_io(void);
-extern struct sys_timer versatile_timer;
+extern void versatile_timer_init(void);
 extern void versatile_restart(char, const char *);
 extern unsigned int mmc_status(struct device *dev);
 #ifdef CONFIG_OF
diff --git a/arch/arm/mach-versatile/versatile_ab.c b/arch/arm/mach-versatile/versatile_ab.c
index 98f6549..1caef10 100644
--- a/arch/arm/mach-versatile/versatile_ab.c
+++ b/arch/arm/mach-versatile/versatile_ab.c
@@ -26,7 +26,6 @@
 
 #include <mach/hardware.h>
 #include <asm/irq.h>
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 
 #include <asm/mach/arch.h>
@@ -39,8 +38,7 @@
 	.map_io		= versatile_map_io,
 	.init_early	= versatile_init_early,
 	.init_irq	= versatile_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &versatile_timer,
+	.init_time	= versatile_timer_init,
 	.init_machine	= versatile_init,
 	.restart	= versatile_restart,
 MACHINE_END
diff --git a/arch/arm/mach-versatile/versatile_dt.c b/arch/arm/mach-versatile/versatile_dt.c
index ae5ad3c..2558f2e 100644
--- a/arch/arm/mach-versatile/versatile_dt.c
+++ b/arch/arm/mach-versatile/versatile_dt.c
@@ -24,7 +24,6 @@
 #include <linux/init.h>
 #include <linux/of_irq.h>
 #include <linux/of_platform.h>
-#include <asm/hardware/vic.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 
@@ -46,8 +45,7 @@
 	.map_io		= versatile_map_io,
 	.init_early	= versatile_init_early,
 	.init_irq	= versatile_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &versatile_timer,
+	.init_time	= versatile_timer_init,
 	.init_machine	= versatile_dt_init,
 	.dt_compat	= versatile_dt_match,
 	.restart	= versatile_restart,
diff --git a/arch/arm/mach-versatile/versatile_pb.c b/arch/arm/mach-versatile/versatile_pb.c
index 1973833..611d140 100644
--- a/arch/arm/mach-versatile/versatile_pb.c
+++ b/arch/arm/mach-versatile/versatile_pb.c
@@ -27,7 +27,6 @@
 #include <linux/io.h>
 
 #include <mach/hardware.h>
-#include <asm/hardware/vic.h>
 #include <asm/irq.h>
 #include <asm/mach-types.h>
 
@@ -107,8 +106,7 @@
 	.map_io		= versatile_map_io,
 	.init_early	= versatile_init_early,
 	.init_irq	= versatile_init_irq,
-	.handle_irq	= vic_handle_irq,
-	.timer		= &versatile_timer,
+	.init_time	= versatile_timer_init,
 	.init_machine	= versatile_pb_init,
 	.restart	= versatile_restart,
 MACHINE_END
diff --git a/arch/arm/mach-vexpress/ct-ca9x4.c b/arch/arm/mach-vexpress/ct-ca9x4.c
index 60838dd..6f34497 100644
--- a/arch/arm/mach-vexpress/ct-ca9x4.c
+++ b/arch/arm/mach-vexpress/ct-ca9x4.c
@@ -10,10 +10,10 @@
 #include <linux/amba/clcd.h>
 #include <linux/clkdev.h>
 #include <linux/vexpress.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/gic.h>
 #include <asm/smp_scu.h>
 #include <asm/smp_twd.h>
 
@@ -182,8 +182,6 @@
 
 	for (i = 0; i < ncores; ++i)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
 
 static void __init ct_ca9x4_smp_enable(unsigned int max_cpus)
diff --git a/arch/arm/mach-vexpress/platsmp.c b/arch/arm/mach-vexpress/platsmp.c
index c5d70de..dc1ace5 100644
--- a/arch/arm/mach-vexpress/platsmp.c
+++ b/arch/arm/mach-vexpress/platsmp.c
@@ -16,7 +16,6 @@
 #include <linux/vexpress.h>
 
 #include <asm/smp_scu.h>
-#include <asm/hardware/gic.h>
 #include <asm/mach/map.h>
 
 #include <mach/motherboard.h>
@@ -128,8 +127,6 @@
 
 	for (i = 0; i < ncores; ++i)
 		set_cpu_possible(i, true);
-
-	set_smp_cross_call(gic_raise_softirq);
 }
 
 static void __init vexpress_dt_smp_prepare_cpus(unsigned int max_cpus)
diff --git a/arch/arm/mach-vexpress/v2m.c b/arch/arm/mach-vexpress/v2m.c
index 011661a..915683c 100644
--- a/arch/arm/mach-vexpress/v2m.c
+++ b/arch/arm/mach-vexpress/v2m.c
@@ -7,6 +7,7 @@
 #include <linux/io.h>
 #include <linux/smp.h>
 #include <linux/init.h>
+#include <linux/irqchip.h>
 #include <linux/of_address.h>
 #include <linux/of_fdt.h>
 #include <linux/of_irq.h>
@@ -30,7 +31,6 @@
 #include <asm/mach/time.h>
 #include <asm/hardware/arm_timer.h>
 #include <asm/hardware/cache-l2x0.h>
-#include <asm/hardware/gic.h>
 #include <asm/hardware/timer-sp.h>
 
 #include <mach/ct-ca9x4.h>
@@ -291,10 +291,6 @@
 	v2m_sp804_init(ioremap(V2M_TIMER01, SZ_4K), IRQ_V2M_TIMER0);
 }
 
-static struct sys_timer v2m_timer = {
-	.init	= v2m_timer_init,
-};
-
 static void __init v2m_init_early(void)
 {
 	if (ct_desc->init_early)
@@ -376,8 +372,7 @@
 	.map_io		= v2m_map_io,
 	.init_early	= v2m_init_early,
 	.init_irq	= v2m_init_irq,
-	.timer		= &v2m_timer,
-	.handle_irq	= gic_handle_irq,
+	.init_time	= v2m_timer_init,
 	.init_machine	= v2m_init,
 	.restart	= vexpress_restart,
 MACHINE_END
@@ -434,16 +429,6 @@
 	}
 }
 
-static  struct of_device_id vexpress_irq_match[] __initdata = {
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-	{}
-};
-
-static void __init v2m_dt_init_irq(void)
-{
-	of_irq_init(vexpress_irq_match);
-}
-
 static void __init v2m_dt_timer_init(void)
 {
 	struct device_node *node = NULL;
@@ -468,10 +453,6 @@
 				24000000);
 }
 
-static struct sys_timer v2m_dt_timer = {
-	.init = v2m_dt_timer_init,
-};
-
 static const struct of_device_id v2m_dt_bus_match[] __initconst = {
 	{ .compatible = "simple-bus", },
 	{ .compatible = "arm,amba-bus", },
@@ -497,9 +478,8 @@
 	.smp		= smp_ops(vexpress_smp_ops),
 	.map_io		= v2m_dt_map_io,
 	.init_early	= v2m_dt_init_early,
-	.init_irq	= v2m_dt_init_irq,
-	.timer		= &v2m_dt_timer,
+	.init_irq	= irqchip_init,
+	.init_time	= v2m_dt_timer_init,
 	.init_machine	= v2m_dt_init,
-	.handle_irq	= gic_handle_irq,
 	.restart	= vexpress_restart,
 MACHINE_END
diff --git a/arch/arm/mach-vt8500/Kconfig b/arch/arm/mach-vt8500/Kconfig
index 2ed0b7d..c0b1c60 100644
--- a/arch/arm/mach-vt8500/Kconfig
+++ b/arch/arm/mach-vt8500/Kconfig
@@ -1,12 +1,34 @@
 config ARCH_VT8500
-	bool "VIA/WonderMedia 85xx" if ARCH_MULTI_V5
-	default ARCH_VT8500_SINGLE
+	bool
 	select ARCH_HAS_CPUFREQ
 	select ARCH_REQUIRE_GPIOLIB
 	select CLKDEV_LOOKUP
-	select CPU_ARM926T
 	select GENERIC_CLOCKEVENTS
 	select GENERIC_GPIO
 	select HAVE_CLK
+	select VT8500_TIMER
 	help
 	  Support for VIA/WonderMedia VT8500/WM85xx System-on-Chip.
+
+config ARCH_WM8505
+	bool "VIA/Wondermedia 85xx and WM8650"
+ 	depends on ARCH_MULTI_V5
+ 	select ARCH_VT8500
+ 	select CPU_ARM926T
+ 	help
+
+config ARCH_WM8750
+	bool "WonderMedia WM8750"
+	depends on ARCH_MULTI_V6
+	select ARCH_VT8500
+	select CPU_V6
+	help
+	  Support for WonderMedia WM8750 System-on-Chip.
+
+config ARCH_WM8850
+	bool "WonderMedia WM8850"
+	depends on ARCH_MULTI_V7
+	select ARCH_VT8500
+	select CPU_V7
+	help
+	  Support for WonderMedia WM8850 System-on-Chip.
diff --git a/arch/arm/mach-vt8500/Makefile b/arch/arm/mach-vt8500/Makefile
index e035251..92ceb24 100644
--- a/arch/arm/mach-vt8500/Makefile
+++ b/arch/arm/mach-vt8500/Makefile
@@ -1 +1 @@
-obj-$(CONFIG_ARCH_VT8500) += irq.o timer.o vt8500.o
+obj-$(CONFIG_ARCH_VT8500) += irq.o vt8500.o
diff --git a/arch/arm/mach-vt8500/common.h b/arch/arm/mach-vt8500/common.h
index 6f2b843..77611a6 100644
--- a/arch/arm/mach-vt8500/common.h
+++ b/arch/arm/mach-vt8500/common.h
@@ -18,7 +18,6 @@
 
 #include <linux/of.h>
 
-void __init vt8500_timer_init(void);
 int __init vt8500_irq_init(struct device_node *node,
 				struct device_node *parent);
 
diff --git a/arch/arm/mach-vt8500/include/mach/debug-macro.S b/arch/arm/mach-vt8500/include/mach/debug-macro.S
deleted file mode 100644
index ca292f2..0000000
--- a/arch/arm/mach-vt8500/include/mach/debug-macro.S
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * arch/arm/mach-vt8500/include/mach/debug-macro.S
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * Debugging macro include header
- *
- * 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.
- *
-*/
-
-	.macro	addruart, rp, rv, tmp
-	mov	\rp,      #0x00200000
-	orr	\rv, \rp, #0xf8000000
-	orr	\rp, \rp, #0xd8000000
-	.endm
-
-	.macro	senduart,rd,rx
-	strb	\rd, [\rx, #0]
-	.endm
-
-	.macro	busyuart,rd,rx
-1001:	ldr	\rd, [\rx, #0x1c]
-	ands	\rd, \rd, #0x2
-	bne	1001b
-	.endm
-
-	.macro	waituart,rd,rx
-	.endm
diff --git a/arch/arm/mach-vt8500/include/mach/timex.h b/arch/arm/mach-vt8500/include/mach/timex.h
deleted file mode 100644
index 8487e4c..0000000
--- a/arch/arm/mach-vt8500/include/mach/timex.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- *  arch/arm/mach-vt8500/include/mach/timex.h
- *
- *  Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#ifndef MACH_TIMEX_H
-#define MACH_TIMEX_H
-
-#define CLOCK_TICK_RATE		(3000000)
-
-#endif /* MACH_TIMEX_H */
diff --git a/arch/arm/mach-vt8500/include/mach/uncompress.h b/arch/arm/mach-vt8500/include/mach/uncompress.h
deleted file mode 100644
index e6e81fd..0000000
--- a/arch/arm/mach-vt8500/include/mach/uncompress.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/* arch/arm/mach-vt8500/include/mach/uncompress.h
- *
- * Copyright (C) 2010 Alexey Charkov <alchark@gmail.com>
- *
- * Based on arch/arm/mach-dove/include/mach/uncompress.h
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * 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.
- *
- */
-
-#define UART0_PHYS	0xd8200000
-#define UART0_ADDR(x)	*(volatile unsigned char *)(UART0_PHYS + x)
-
-static void putc(const char c)
-{
-	while (UART0_ADDR(0x1c) & 0x2)
-		/* Tx busy, wait and poll */;
-
-	UART0_ADDR(0) = c;
-}
-
-static void flush(void)
-{
-}
-
-/*
- * nothing to do
- */
-#define arch_decomp_setup()
-#define arch_decomp_wdog()
diff --git a/arch/arm/mach-vt8500/vt8500.c b/arch/arm/mach-vt8500/vt8500.c
index 3c66d48..6141868 100644
--- a/arch/arm/mach-vt8500/vt8500.c
+++ b/arch/arm/mach-vt8500/vt8500.c
@@ -20,6 +20,7 @@
 
 #include <linux/io.h>
 #include <linux/pm.h>
+#include <linux/vt8500_timer.h>
 
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
@@ -175,21 +176,19 @@
 	of_irq_init(vt8500_irq_match);
 };
 
-static struct sys_timer vt8500_timer = {
-	.init = vt8500_timer_init,
-};
-
 static const char * const vt8500_dt_compat[] = {
 	"via,vt8500",
 	"wm,wm8650",
 	"wm,wm8505",
+	"wm,wm8750",
+	"wm,wm8850",
 };
 
 DT_MACHINE_START(WMT_DT, "VIA/Wondermedia SoC (Device Tree Support)")
 	.dt_compat	= vt8500_dt_compat,
 	.map_io		= vt8500_map_io,
 	.init_irq	= vt8500_init_irq,
-	.timer		= &vt8500_timer,
+	.init_time	= vt8500_timer_init,
 	.init_machine	= vt8500_init,
 	.restart	= vt8500_restart,
 	.handle_irq	= vt8500_handle_irq,
diff --git a/arch/arm/mach-w90x900/mach-nuc910evb.c b/arch/arm/mach-w90x900/mach-nuc910evb.c
index b4243e4..92f1c97 100644
--- a/arch/arm/mach-w90x900/mach-nuc910evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc910evb.c
@@ -37,6 +37,6 @@
 	.map_io		= nuc910evb_map_io,
 	.init_irq	= nuc900_init_irq,
 	.init_machine	= nuc910evb_init,
-	.timer		= &nuc900_timer,
+	.init_time	= nuc900_timer_init,
 	.restart	= nuc9xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-w90x900/mach-nuc950evb.c b/arch/arm/mach-w90x900/mach-nuc950evb.c
index 500fe59..26f7189 100644
--- a/arch/arm/mach-w90x900/mach-nuc950evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc950evb.c
@@ -40,6 +40,6 @@
 	.map_io		= nuc950evb_map_io,
 	.init_irq	= nuc900_init_irq,
 	.init_machine	= nuc950evb_init,
-	.timer		= &nuc900_timer,
+	.init_time	= nuc900_timer_init,
 	.restart	= nuc9xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-w90x900/mach-nuc960evb.c b/arch/arm/mach-w90x900/mach-nuc960evb.c
index cbb3adc..9b4e73f 100644
--- a/arch/arm/mach-w90x900/mach-nuc960evb.c
+++ b/arch/arm/mach-w90x900/mach-nuc960evb.c
@@ -37,6 +37,6 @@
 	.map_io		= nuc960evb_map_io,
 	.init_irq	= nuc900_init_irq,
 	.init_machine	= nuc960evb_init,
-	.timer		= &nuc900_timer,
+	.init_time	= nuc900_timer_init,
 	.restart	= nuc9xx_restart,
 MACHINE_END
diff --git a/arch/arm/mach-w90x900/nuc9xx.h b/arch/arm/mach-w90x900/nuc9xx.h
index 91acb40..88ef4b2 100644
--- a/arch/arm/mach-w90x900/nuc9xx.h
+++ b/arch/arm/mach-w90x900/nuc9xx.h
@@ -15,10 +15,9 @@
  *
  */
 struct map_desc;
-struct sys_timer;
 
 /* core initialisation functions */
 
 extern void nuc900_init_irq(void);
-extern struct sys_timer nuc900_timer;
+extern void nuc900_timer_init(void);
 extern void nuc9xx_restart(char, const char *);
diff --git a/arch/arm/mach-w90x900/time.c b/arch/arm/mach-w90x900/time.c
index b61ab3e..30fbca8 100644
--- a/arch/arm/mach-w90x900/time.c
+++ b/arch/arm/mach-w90x900/time.c
@@ -161,12 +161,8 @@
 		TDR_SHIFT, clocksource_mmio_readl_down);
 }
 
-static void __init nuc900_timer_init(void)
+void __init nuc900_timer_init(void)
 {
 	nuc900_clocksource_init();
 	nuc900_clockevents_init();
 }
-
-struct sys_timer nuc900_timer = {
-	.init		= nuc900_timer_init,
-};
diff --git a/arch/arm/mach-zynq/common.c b/arch/arm/mach-zynq/common.c
index e16d4be..6472a69 100644
--- a/arch/arm/mach-zynq/common.c
+++ b/arch/arm/mach-zynq/common.c
@@ -31,7 +31,6 @@
 #include <asm/mach-types.h>
 #include <asm/page.h>
 #include <asm/pgtable.h>
-#include <asm/hardware/gic.h>
 #include <asm/hardware/cache-l2x0.h>
 
 #include "common.h"
@@ -55,19 +54,6 @@
 	of_platform_bus_probe(NULL, zynq_of_bus_ids, NULL);
 }
 
-static struct of_device_id irq_match[] __initdata = {
-	{ .compatible = "arm,cortex-a9-gic", .data = gic_of_init, },
-	{ }
-};
-
-/**
- * xilinx_irq_init() - Interrupt controller initialization for the GIC.
- */
-static void __init xilinx_irq_init(void)
-{
-	of_irq_init(irq_match);
-}
-
 #define SCU_PERIPH_PHYS		0xF8F00000
 #define SCU_PERIPH_SIZE		SZ_8K
 #define SCU_PERIPH_VIRT		(VMALLOC_END - SCU_PERIPH_SIZE)
@@ -93,13 +79,6 @@
 	xttcpss_timer_init();
 }
 
-/*
- * Instantiate and initialize the system timer structure
- */
-static struct sys_timer xttcpss_sys_timer = {
-	.init		= xilinx_zynq_timer_init,
-};
-
 /**
  * xilinx_map_io() - Create memory mappings needed for early I/O.
  */
@@ -117,9 +96,8 @@
 
 MACHINE_START(XILINX_EP107, "Xilinx Zynq Platform")
 	.map_io		= xilinx_map_io,
-	.init_irq	= xilinx_irq_init,
-	.handle_irq	= gic_handle_irq,
+	.init_irq	= irqchip_init,
 	.init_machine	= xilinx_init_machine,
-	.timer		= &xttcpss_sys_timer,
+	.init_time	= xilinx_zynq_timer_init,
 	.dt_compat	= xilinx_dt_match,
 MACHINE_END
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index 6b2fb87..076c26d 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -774,25 +774,27 @@
 	size_t size, enum dma_data_direction dir,
 	void (*op)(const void *, size_t, int))
 {
+	unsigned long pfn;
+	size_t left = size;
+
+	pfn = page_to_pfn(page) + offset / PAGE_SIZE;
+	offset %= PAGE_SIZE;
+
 	/*
 	 * A single sg entry may refer to multiple physically contiguous
 	 * pages.  But we still need to process highmem pages individually.
 	 * If highmem is not configured then the bulk of this loop gets
 	 * optimized out.
 	 */
-	size_t left = size;
 	do {
 		size_t len = left;
 		void *vaddr;
 
+		page = pfn_to_page(pfn);
+
 		if (PageHighMem(page)) {
-			if (len + offset > PAGE_SIZE) {
-				if (offset >= PAGE_SIZE) {
-					page += offset / PAGE_SIZE;
-					offset %= PAGE_SIZE;
-				}
+			if (len + offset > PAGE_SIZE)
 				len = PAGE_SIZE - offset;
-			}
 			vaddr = kmap_high_get(page);
 			if (vaddr) {
 				vaddr += offset;
@@ -809,7 +811,7 @@
 			op(vaddr, len, dir);
 		}
 		offset = 0;
-		page++;
+		pfn++;
 		left -= len;
 	} while (left);
 }
diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c
index 9f06102..ce328c7 100644
--- a/arch/arm/mm/mmu.c
+++ b/arch/arm/mm/mmu.c
@@ -283,7 +283,7 @@
 	},
 	[MT_MEMORY_SO] = {
 		.prot_pte  = L_PTE_PRESENT | L_PTE_YOUNG | L_PTE_DIRTY |
-				L_PTE_MT_UNCACHED,
+				L_PTE_MT_UNCACHED | L_PTE_XN,
 		.prot_l1   = PMD_TYPE_TABLE,
 		.prot_sect = PMD_TYPE_SECT | PMD_SECT_AP_WRITE | PMD_SECT_S |
 				PMD_SECT_UNCACHED | PMD_SECT_XN,
diff --git a/arch/arm/plat-orion/mpp.c b/arch/arm/plat-orion/mpp.c
index e686fe7..7310bcf 100644
--- a/arch/arm/plat-orion/mpp.c
+++ b/arch/arm/plat-orion/mpp.c
@@ -49,7 +49,7 @@
 					"number (%u)\n", num);
 			continue;
 		}
-		if (variant_mask & !(*mpp_list & variant_mask)) {
+		if (variant_mask && !(*mpp_list & variant_mask)) {
 			printk(KERN_WARNING
 			       "orion_mpp_conf: requested MPP%u config "
 			       "unavailable on this hardware\n", num);
diff --git a/arch/arm/plat-samsung/include/plat/cpu.h b/arch/arm/plat-samsung/include/plat/cpu.h
index b69e11d..37703ef 100644
--- a/arch/arm/plat-samsung/include/plat/cpu.h
+++ b/arch/arm/plat-samsung/include/plat/cpu.h
@@ -194,8 +194,7 @@
 
 /* timer for 2410/2440 */
 
-struct sys_timer;
-extern struct sys_timer s3c24xx_timer;
+extern void s3c24xx_timer_init(void);
 
 extern struct syscore_ops s3c2410_pm_syscore_ops;
 extern struct syscore_ops s3c2412_pm_syscore_ops;
diff --git a/arch/arm/plat-samsung/include/plat/s5p-time.h b/arch/arm/plat-samsung/include/plat/s5p-time.h
index 3a70aeb..9c96f35 100644
--- a/arch/arm/plat-samsung/include/plat/s5p-time.h
+++ b/arch/arm/plat-samsung/include/plat/s5p-time.h
@@ -36,5 +36,5 @@
 
 extern void __init s5p_set_timer_source(enum s5p_timer_mode event,
 					enum s5p_timer_mode source);
-extern	struct sys_timer s5p_timer;
+extern	void s5p_timer_init(void);
 #endif /* __ASM_PLAT_S5P_TIME_H */
diff --git a/arch/arm/plat-samsung/s5p-irq-eint.c b/arch/arm/plat-samsung/s5p-irq-eint.c
index 33bd3f3..faa6516 100644
--- a/arch/arm/plat-samsung/s5p-irq-eint.c
+++ b/arch/arm/plat-samsung/s5p-irq-eint.c
@@ -15,8 +15,7 @@
 #include <linux/io.h>
 #include <linux/device.h>
 #include <linux/gpio.h>
-
-#include <asm/hardware/vic.h>
+#include <linux/irqchip/arm-vic.h>
 
 #include <plat/regs-irqtype.h>
 
diff --git a/arch/arm/plat-samsung/s5p-irq.c b/arch/arm/plat-samsung/s5p-irq.c
index dfb47d6..103e371 100644
--- a/arch/arm/plat-samsung/s5p-irq.c
+++ b/arch/arm/plat-samsung/s5p-irq.c
@@ -13,8 +13,7 @@
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/io.h>
-
-#include <asm/hardware/vic.h>
+#include <linux/irqchip/arm-vic.h>
 
 #include <mach/map.h>
 #include <plat/regs-timer.h>
diff --git a/arch/arm/plat-samsung/s5p-time.c b/arch/arm/plat-samsung/s5p-time.c
index 798268b..e92510c 100644
--- a/arch/arm/plat-samsung/s5p-time.c
+++ b/arch/arm/plat-samsung/s5p-time.c
@@ -386,13 +386,9 @@
 	clk_enable(tin_source);
 }
 
-static void __init s5p_timer_init(void)
+void __init s5p_timer_init(void)
 {
 	s5p_timer_resources();
 	s5p_clockevent_init();
 	s5p_clocksource_init();
 }
-
-struct sys_timer s5p_timer = {
-	.init		= s5p_timer_init,
-};
diff --git a/arch/arm/plat-samsung/time.c b/arch/arm/plat-samsung/time.c
index 60552e2..73defd0 100644
--- a/arch/arm/plat-samsung/time.c
+++ b/arch/arm/plat-samsung/time.c
@@ -27,6 +27,7 @@
 #include <linux/clk.h>
 #include <linux/io.h>
 #include <linux/platform_device.h>
+#include <linux/syscore_ops.h>
 
 #include <asm/mach-types.h>
 
@@ -95,7 +96,7 @@
  * IRQs are disabled before entering here from do_gettimeofday()
  */
 
-static unsigned long s3c2410_gettimeoffset (void)
+static u32 s3c2410_gettimeoffset(void)
 {
 	unsigned long tdone;
 	unsigned long tval;
@@ -120,7 +121,7 @@
 			tdone += timer_startval;
 	}
 
-	return timer_ticks_to_usec(tdone);
+	return timer_ticks_to_usec(tdone) * 1000;
 }
 
 
@@ -271,15 +272,16 @@
 	clk_enable(tin);
 }
 
-static void __init s3c2410_timer_init(void)
+static struct syscore_ops s3c24xx_syscore_ops = {
+	.resume		= s3c2410_timer_setup,
+};
+
+void __init s3c24xx_timer_init(void)
 {
+	arch_gettimeoffset = s3c2410_gettimeoffset;
+
 	s3c2410_timer_resources();
 	s3c2410_timer_setup();
 	setup_irq(IRQ_TIMER4, &s3c2410_timer_irq);
+	register_syscore_ops(&s3c24xx_syscore_ops);
 }
-
-struct sys_timer s3c24xx_timer = {
-	.init		= s3c2410_timer_init,
-	.offset		= s3c2410_gettimeoffset,
-	.resume		= s3c2410_timer_setup
-};
diff --git a/arch/arm/plat-versatile/headsmp.S b/arch/arm/plat-versatile/headsmp.S
index dd703ef..b178d44 100644
--- a/arch/arm/plat-versatile/headsmp.S
+++ b/arch/arm/plat-versatile/headsmp.S
@@ -20,7 +20,7 @@
  */
 ENTRY(versatile_secondary_startup)
 	mrc	p15, 0, r0, c0, c0, 5
-	and	r0, r0, #15
+	bic	r0, #0xff000000
 	adr	r4, 1f
 	ldmia	r4, {r5, r6}
 	sub	r4, r4, r5
diff --git a/arch/arm/plat-versatile/platsmp.c b/arch/arm/plat-versatile/platsmp.c
index 04ca493..f2ac155 100644
--- a/arch/arm/plat-versatile/platsmp.c
+++ b/arch/arm/plat-versatile/platsmp.c
@@ -14,10 +14,10 @@
 #include <linux/device.h>
 #include <linux/jiffies.h>
 #include <linux/smp.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include <asm/cacheflush.h>
 #include <asm/smp_plat.h>
-#include <asm/hardware/gic.h>
 
 /*
  * Write pen_release in a way that is guaranteed to be visible to all
@@ -79,7 +79,7 @@
 	 * the boot monitor to read the system wide flags register,
 	 * and branch to the address found there.
 	 */
-	gic_raise_softirq(cpumask_of(cpu), 0);
+	arch_send_wakeup_ipi_mask(cpumask_of(cpu));
 
 	timeout = jiffies + (1 * HZ);
 	while (time_before(jiffies, timeout)) {
diff --git a/arch/arm/vfp/entry.S b/arch/arm/vfp/entry.S
index cc926c9..323ce1a 100644
--- a/arch/arm/vfp/entry.S
+++ b/arch/arm/vfp/entry.S
@@ -22,7 +22,7 @@
 @  IRQs disabled.
 @
 ENTRY(do_vfp)
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
 	ldr	r4, [r10, #TI_PREEMPT]	@ get preempt count
 	add	r11, r4, #1		@ increment it
 	str	r11, [r10, #TI_PREEMPT]
@@ -35,7 +35,7 @@
 ENDPROC(do_vfp)
 
 ENTRY(vfp_null_entry)
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
 	get_thread_info	r10
 	ldr	r4, [r10, #TI_PREEMPT]	@ get preempt count
 	sub	r11, r4, #1		@ decrement it
@@ -53,7 +53,7 @@
 
 	__INIT
 ENTRY(vfp_testing_entry)
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
 	get_thread_info	r10
 	ldr	r4, [r10, #TI_PREEMPT]	@ get preempt count
 	sub	r11, r4, #1		@ decrement it
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index ea0349f..dd5e56f 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -168,7 +168,7 @@
 					@ else it's one 32-bit instruction, so
 					@ always subtract 4 from the following
 					@ instruction address.
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
 	get_thread_info	r10
 	ldr	r4, [r10, #TI_PREEMPT]	@ get preempt count
 	sub	r11, r4, #1		@ decrement it
@@ -192,7 +192,7 @@
 	@ not recognised by VFP
 
 	DBGSTR	"not VFP"
-#ifdef CONFIG_PREEMPT
+#ifdef CONFIG_PREEMPT_COUNT
 	get_thread_info	r10
 	ldr	r4, [r10, #TI_PREEMPT]	@ get preempt count
 	sub	r11, r4, #1		@ decrement it
diff --git a/arch/arm64/boot/dts/Makefile b/arch/arm64/boot/dts/Makefile
index 801e2d7..32ac0ae 100644
--- a/arch/arm64/boot/dts/Makefile
+++ b/arch/arm64/boot/dts/Makefile
@@ -1,4 +1,5 @@
 targets += dtbs
+targets += $(dtb-y)
 
 dtbs: $(addprefix $(obj)/, $(dtb-y))
 
diff --git a/arch/arm64/include/asm/elf.h b/arch/arm64/include/asm/elf.h
index 07fea29..fe32c0e 100644
--- a/arch/arm64/include/asm/elf.h
+++ b/arch/arm64/include/asm/elf.h
@@ -26,7 +26,10 @@
 
 typedef unsigned long elf_greg_t;
 
-#define ELF_NGREG (sizeof (struct pt_regs) / sizeof(elf_greg_t))
+#define ELF_NGREG (sizeof(struct user_pt_regs) / sizeof(elf_greg_t))
+#define ELF_CORE_COPY_REGS(dest, regs)	\
+	*(struct user_pt_regs *)&(dest) = (regs)->user_regs;
+
 typedef elf_greg_t elf_gregset_t[ELF_NGREG];
 typedef struct user_fpsimd_state elf_fpregset_t;
 
diff --git a/arch/arm64/include/asm/pgtable.h b/arch/arm64/include/asm/pgtable.h
index 64b1339..e333a24 100644
--- a/arch/arm64/include/asm/pgtable.h
+++ b/arch/arm64/include/asm/pgtable.h
@@ -24,7 +24,8 @@
 /*
  * Software defined PTE bits definition.
  */
-#define PTE_VALID		(_AT(pteval_t, 1) << 0)	/* pte_present() check */
+#define PTE_VALID		(_AT(pteval_t, 1) << 0)
+#define PTE_PROT_NONE		(_AT(pteval_t, 1) << 1)	/* only when !PTE_VALID */
 #define PTE_FILE		(_AT(pteval_t, 1) << 2)	/* only when !pte_present() */
 #define PTE_DIRTY		(_AT(pteval_t, 1) << 55)
 #define PTE_SPECIAL		(_AT(pteval_t, 1) << 56)
@@ -60,9 +61,12 @@
 
 extern pgprot_t pgprot_default;
 
-#define _MOD_PROT(p, b)	__pgprot(pgprot_val(p) | (b))
+#define __pgprot_modify(prot,mask,bits) \
+	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
 
-#define PAGE_NONE		_MOD_PROT(pgprot_default, PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define _MOD_PROT(p, b)		__pgprot_modify(p, 0, b)
+
+#define PAGE_NONE		__pgprot_modify(pgprot_default, PTE_TYPE_MASK, PTE_PROT_NONE)
 #define PAGE_SHARED		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
 #define PAGE_SHARED_EXEC	_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN)
 #define PAGE_COPY		_MOD_PROT(pgprot_default, PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
@@ -72,7 +76,7 @@
 #define PAGE_KERNEL		_MOD_PROT(pgprot_default, PTE_PXN | PTE_UXN | PTE_DIRTY)
 #define PAGE_KERNEL_EXEC	_MOD_PROT(pgprot_default, PTE_UXN | PTE_DIRTY)
 
-#define __PAGE_NONE		__pgprot(_PAGE_DEFAULT | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
+#define __PAGE_NONE		__pgprot(((_PAGE_DEFAULT) & ~PTE_TYPE_MASK) | PTE_PROT_NONE)
 #define __PAGE_SHARED		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN)
 #define __PAGE_SHARED_EXEC	__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN)
 #define __PAGE_COPY		__pgprot(_PAGE_DEFAULT | PTE_USER | PTE_NG | PTE_PXN | PTE_UXN | PTE_RDONLY)
@@ -125,16 +129,15 @@
 /*
  * The following only work if pte_present(). Undefined behaviour otherwise.
  */
-#define pte_present(pte)	(pte_val(pte) & PTE_VALID)
+#define pte_present(pte)	(pte_val(pte) & (PTE_VALID | PTE_PROT_NONE))
 #define pte_dirty(pte)		(pte_val(pte) & PTE_DIRTY)
 #define pte_young(pte)		(pte_val(pte) & PTE_AF)
 #define pte_special(pte)	(pte_val(pte) & PTE_SPECIAL)
 #define pte_write(pte)		(!(pte_val(pte) & PTE_RDONLY))
 #define pte_exec(pte)		(!(pte_val(pte) & PTE_UXN))
 
-#define pte_present_exec_user(pte) \
-	((pte_val(pte) & (PTE_VALID | PTE_USER | PTE_UXN)) == \
-	 (PTE_VALID | PTE_USER))
+#define pte_valid_user(pte) \
+	((pte_val(pte) & (PTE_VALID | PTE_USER)) == (PTE_VALID | PTE_USER))
 
 #define PTE_BIT_FUNC(fn,op) \
 static inline pte_t pte_##fn(pte_t pte) { pte_val(pte) op; return pte; }
@@ -157,10 +160,13 @@
 static inline void set_pte_at(struct mm_struct *mm, unsigned long addr,
 			      pte_t *ptep, pte_t pte)
 {
-	if (pte_present_exec_user(pte))
-		__sync_icache_dcache(pte, addr);
-	if (!pte_dirty(pte))
-		pte = pte_wrprotect(pte);
+	if (pte_valid_user(pte)) {
+		if (pte_exec(pte))
+			__sync_icache_dcache(pte, addr);
+		if (!pte_dirty(pte))
+			pte = pte_wrprotect(pte);
+	}
+
 	set_pte(ptep, pte);
 }
 
@@ -170,9 +176,6 @@
 #define pte_huge(pte)		((pte_val(pte) & PTE_TYPE_MASK) == PTE_TYPE_HUGEPAGE)
 #define pte_mkhuge(pte)		(__pte((pte_val(pte) & ~PTE_TYPE_MASK) | PTE_TYPE_HUGEPAGE))
 
-#define __pgprot_modify(prot,mask,bits)		\
-	__pgprot((pgprot_val(prot) & ~(mask)) | (bits))
-
 #define __HAVE_ARCH_PTE_SPECIAL
 
 /*
@@ -264,7 +267,8 @@
 
 static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
 {
-	const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY;
+	const pteval_t mask = PTE_USER | PTE_PXN | PTE_UXN | PTE_RDONLY |
+			      PTE_PROT_NONE | PTE_VALID;
 	pte_val(pte) = (pte_val(pte) & ~mask) | (pgprot_val(newprot) & mask);
 	return pte;
 }
diff --git a/arch/arm64/include/asm/unistd32.h b/arch/arm64/include/asm/unistd32.h
index 5843262..5ef47ba 100644
--- a/arch/arm64/include/asm/unistd32.h
+++ b/arch/arm64/include/asm/unistd32.h
@@ -395,8 +395,13 @@
 __SYSCALL(371, compat_sys_open_by_handle_at)
 __SYSCALL(372, compat_sys_clock_adjtime)
 __SYSCALL(373, sys_syncfs)
+__SYSCALL(374, compat_sys_sendmmsg)
+__SYSCALL(375, sys_setns)
+__SYSCALL(376, compat_sys_process_vm_readv)
+__SYSCALL(377, compat_sys_process_vm_writev)
+__SYSCALL(378, sys_ni_syscall)			/* 378 for kcmp */
 
-#define __NR_compat_syscalls		374
+#define __NR_compat_syscalls		379
 
 /*
  * Compat syscall numbers used by the AArch64 kernel.
diff --git a/arch/arm64/kernel/vdso.c b/arch/arm64/kernel/vdso.c
index c958cb8..6a389dc 100644
--- a/arch/arm64/kernel/vdso.c
+++ b/arch/arm64/kernel/vdso.c
@@ -252,10 +252,6 @@
 
 void update_vsyscall_tz(void)
 {
-	++vdso_data->tb_seq_count;
-	smp_wmb();
 	vdso_data->tz_minuteswest	= sys_tz.tz_minuteswest;
 	vdso_data->tz_dsttime		= sys_tz.tz_dsttime;
-	smp_wmb();
-	++vdso_data->tb_seq_count;
 }
diff --git a/arch/arm64/kernel/vdso/gettimeofday.S b/arch/arm64/kernel/vdso/gettimeofday.S
index 8bf658d..f0a6d10 100644
--- a/arch/arm64/kernel/vdso/gettimeofday.S
+++ b/arch/arm64/kernel/vdso/gettimeofday.S
@@ -73,8 +73,6 @@
 	/* If tz is NULL, return 0. */
 	cbz	x1, 3f
 	ldp	w4, w5, [vdso_data, #VDSO_TZ_MINWEST]
-	seqcnt_read w9
-	seqcnt_check w9, 1b
 	stp	w4, w5, [x1, #TZ_MINWEST]
 3:
 	mov	x0, xzr
diff --git a/arch/blackfin/kernel/time.c b/arch/blackfin/kernel/time.c
index 2310b24..3126b92 100644
--- a/arch/blackfin/kernel/time.c
+++ b/arch/blackfin/kernel/time.c
@@ -85,7 +85,7 @@
 /*
  * Should return useconds since last timer tick
  */
-u32 arch_gettimeoffset(void)
+static u32 blackfin_gettimeoffset(void)
 {
 	unsigned long offset;
 	unsigned long clocks_per_jiffy;
@@ -141,6 +141,10 @@
 
 void __init time_init(void)
 {
+#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
+	arch_gettimeoffset = blackfin_gettimeoffset;
+#endif
+
 #ifdef CONFIG_RTC_DRV_BFIN
 	/* [#2663] hack to filter junk RTC values that would cause
 	 * userspace to have to deal with time values greater than
diff --git a/arch/cris/arch-v10/kernel/time.c b/arch/cris/arch-v10/kernel/time.c
index bcffcb6..fce7c54 100644
--- a/arch/cris/arch-v10/kernel/time.c
+++ b/arch/cris/arch-v10/kernel/time.c
@@ -55,9 +55,9 @@
 	return ns;
 }
 
-unsigned long do_slow_gettimeoffset(void)
+static u32 cris_v10_gettimeoffset(void)
 {
-	unsigned long count;
+	u32 count;
 
 	/* The timer interrupt comes from Etrax timer 0. In order to get
 	 * better precision, we check the current value. It might have
@@ -65,8 +65,8 @@
 	 */
 	count = *R_TIMER0_DATA;
 
-	/* Convert timer value to usec */
-	return (TIMER0_DIV - count) * ((NSEC_PER_SEC/1000)/HZ)/TIMER0_DIV;
+	/* Convert timer value to nsec */
+	return (TIMER0_DIV - count) * (NSEC_PER_SEC/HZ)/TIMER0_DIV;
 }
 
 /* Excerpt from the Etrax100 HSDD about the built-in watchdog:
@@ -191,6 +191,8 @@
 void __init
 time_init(void)
 {	
+	arch_gettimeoffset = cris_v10_gettimeoffset;
+
 	/* probe for the RTC and read it if it exists 
 	 * Before the RTC can be probed the loops_per_usec variable needs 
 	 * to be initialized to make usleep work. A better value for 
diff --git a/arch/cris/kernel/time.c b/arch/cris/kernel/time.c
index 277ffc4..fe6acda 100644
--- a/arch/cris/kernel/time.c
+++ b/arch/cris/kernel/time.c
@@ -39,17 +39,6 @@
 extern unsigned long loops_per_jiffy; /* init/main.c */
 unsigned long loops_per_usec;
 
-
-#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
-extern unsigned long do_slow_gettimeoffset(void);
-static unsigned long (*do_gettimeoffset)(void) = do_slow_gettimeoffset;
-
-u32 arch_gettimeoffset(void)
-{
-       return do_gettimeoffset() * 1000;
-}
-#endif
-
 int set_rtc_mmss(unsigned long nowtime)
 {
 	D(printk(KERN_DEBUG "set_rtc_mmss(%lu)\n", nowtime));
diff --git a/arch/ia64/kernel/ptrace.c b/arch/ia64/kernel/ptrace.c
index 4265ff6..b7a5fff 100644
--- a/arch/ia64/kernel/ptrace.c
+++ b/arch/ia64/kernel/ptrace.c
@@ -672,33 +672,6 @@
 	read_unlock(&tasklist_lock);
 }
 
-static inline int
-thread_matches (struct task_struct *thread, unsigned long addr)
-{
-	unsigned long thread_rbs_end;
-	struct pt_regs *thread_regs;
-
-	if (ptrace_check_attach(thread, 0) < 0)
-		/*
-		 * If the thread is not in an attachable state, we'll
-		 * ignore it.  The net effect is that if ADDR happens
-		 * to overlap with the portion of the thread's
-		 * register backing store that is currently residing
-		 * on the thread's kernel stack, then ptrace() may end
-		 * up accessing a stale value.  But if the thread
-		 * isn't stopped, that's a problem anyhow, so we're
-		 * doing as well as we can...
-		 */
-		return 0;
-
-	thread_regs = task_pt_regs(thread);
-	thread_rbs_end = ia64_get_user_rbs_end(thread, thread_regs, NULL);
-	if (!on_kernel_rbs(addr, thread_regs->ar_bspstore, thread_rbs_end))
-		return 0;
-
-	return 1;	/* looks like we've got a winner */
-}
-
 /*
  * Write f32-f127 back to task->thread.fph if it has been modified.
  */
diff --git a/arch/m32r/kernel/time.c b/arch/m32r/kernel/time.c
index 84dd040..1a15f81 100644
--- a/arch/m32r/kernel/time.c
+++ b/arch/m32r/kernel/time.c
@@ -57,7 +57,7 @@
 
 static unsigned long latch;
 
-u32 arch_gettimeoffset(void)
+static u32 m32r_gettimeoffset(void)
 {
 	unsigned long  elapsed_time = 0;  /* [us] */
 
@@ -165,6 +165,8 @@
 
 void __init time_init(void)
 {
+	arch_gettimeoffset = m32r_gettimeoffset;
+
 #if defined(CONFIG_CHIP_M32102) || defined(CONFIG_CHIP_XNUX2) \
 	|| defined(CONFIG_CHIP_VDEC2) || defined(CONFIG_CHIP_M32700) \
 	|| defined(CONFIG_CHIP_OPSP) || defined(CONFIG_CHIP_M32104)
diff --git a/arch/m68k/amiga/config.c b/arch/m68k/amiga/config.c
index ee01b7a..b819390 100644
--- a/arch/m68k/amiga/config.c
+++ b/arch/m68k/amiga/config.c
@@ -95,7 +95,7 @@
 static void amiga_get_model(char *model);
 static void amiga_get_hardware_list(struct seq_file *m);
 /* amiga specific timer functions */
-static unsigned long amiga_gettimeoffset(void);
+static u32 amiga_gettimeoffset(void);
 extern void amiga_mksound(unsigned int count, unsigned int ticks);
 static void amiga_reset(void);
 extern void amiga_init_sound(void);
@@ -377,7 +377,7 @@
 	mach_init_IRQ        = amiga_init_IRQ;
 	mach_get_model       = amiga_get_model;
 	mach_get_hardware_list = amiga_get_hardware_list;
-	mach_gettimeoffset   = amiga_gettimeoffset;
+	arch_gettimeoffset   = amiga_gettimeoffset;
 
 	/*
 	 * default MAX_DMA=0xffffffff on all machines. If we don't do so, the SCSI
@@ -482,10 +482,10 @@
 #define TICK_SIZE 10000
 
 /* This is always executed with interrupts disabled.  */
-static unsigned long amiga_gettimeoffset(void)
+static u32 amiga_gettimeoffset(void)
 {
 	unsigned short hi, lo, hi2;
-	unsigned long ticks, offset = 0;
+	u32 ticks, offset = 0;
 
 	/* read CIA B timer A current value */
 	hi  = ciab.tahi;
@@ -507,7 +507,7 @@
 	ticks = jiffy_ticks - ticks;
 	ticks = (10000 * ticks) / jiffy_ticks;
 
-	return ticks + offset;
+	return (ticks + offset) * 1000;
 }
 
 static void amiga_reset(void)  __noreturn;
diff --git a/arch/m68k/apollo/config.c b/arch/m68k/apollo/config.c
index f5565d6..3ea56b9 100644
--- a/arch/m68k/apollo/config.c
+++ b/arch/m68k/apollo/config.c
@@ -26,7 +26,7 @@
 
 extern void dn_sched_init(irq_handler_t handler);
 extern void dn_init_IRQ(void);
-extern unsigned long dn_gettimeoffset(void);
+extern u32 dn_gettimeoffset(void);
 extern int dn_dummy_hwclk(int, struct rtc_time *);
 extern int dn_dummy_set_clock_mmss(unsigned long);
 extern void dn_dummy_reset(void);
@@ -151,7 +151,7 @@
 
 	mach_sched_init=dn_sched_init; /* */
 	mach_init_IRQ=dn_init_IRQ;
-	mach_gettimeoffset   = dn_gettimeoffset;
+	arch_gettimeoffset   = dn_gettimeoffset;
 	mach_max_dma_address = 0xffffffff;
 	mach_hwclk           = dn_dummy_hwclk; /* */
 	mach_set_clock_mmss  = dn_dummy_set_clock_mmss; /* */
@@ -203,10 +203,9 @@
 		pr_err("Couldn't register timer interrupt\n");
 }
 
-unsigned long dn_gettimeoffset(void) {
-
+u32 dn_gettimeoffset(void)
+{
 	return 0xdeadbeef;
-
 }
 
 int dn_dummy_hwclk(int op, struct rtc_time *t) {
diff --git a/arch/m68k/atari/config.c b/arch/m68k/atari/config.c
index d8eb327..037c11c 100644
--- a/arch/m68k/atari/config.c
+++ b/arch/m68k/atari/config.c
@@ -74,7 +74,7 @@
 
 /* atari specific timer functions (in time.c) */
 extern void atari_sched_init(irq_handler_t);
-extern unsigned long atari_gettimeoffset (void);
+extern u32 atari_gettimeoffset(void);
 extern int atari_mste_hwclk (int, struct rtc_time *);
 extern int atari_tt_hwclk (int, struct rtc_time *);
 extern int atari_mste_set_clock_mmss (unsigned long);
@@ -204,7 +204,7 @@
 	mach_init_IRQ        = atari_init_IRQ;
 	mach_get_model	 = atari_get_model;
 	mach_get_hardware_list = atari_get_hardware_list;
-	mach_gettimeoffset   = atari_gettimeoffset;
+	arch_gettimeoffset   = atari_gettimeoffset;
 	mach_reset           = atari_reset;
 	mach_max_dma_address = 0xffffff;
 #if defined(CONFIG_INPUT_M68K_BEEP) || defined(CONFIG_INPUT_M68K_BEEP_MODULE)
diff --git a/arch/m68k/atari/time.c b/arch/m68k/atari/time.c
index c0cc68a..da8f981 100644
--- a/arch/m68k/atari/time.c
+++ b/arch/m68k/atari/time.c
@@ -42,9 +42,9 @@
 #define TICK_SIZE 10000
 
 /* This is always executed with interrupts disabled.  */
-unsigned long atari_gettimeoffset (void)
+u32 atari_gettimeoffset(void)
 {
-  unsigned long ticks, offset = 0;
+  u32 ticks, offset = 0;
 
   /* read MFP timer C current value */
   ticks = st_mfp.tim_dt_c;
@@ -57,7 +57,7 @@
   ticks = INT_TICKS - ticks;
   ticks = ticks * 10000L / INT_TICKS;
 
-  return ticks + offset;
+  return (ticks + offset) * 1000;
 }
 
 
diff --git a/arch/m68k/bvme6000/config.c b/arch/m68k/bvme6000/config.c
index 0bf850a..8943aa4 100644
--- a/arch/m68k/bvme6000/config.c
+++ b/arch/m68k/bvme6000/config.c
@@ -38,7 +38,7 @@
 
 static void bvme6000_get_model(char *model);
 extern void bvme6000_sched_init(irq_handler_t handler);
-extern unsigned long bvme6000_gettimeoffset (void);
+extern u32 bvme6000_gettimeoffset(void);
 extern int bvme6000_hwclk (int, struct rtc_time *);
 extern int bvme6000_set_clock_mmss (unsigned long);
 extern void bvme6000_reset (void);
@@ -110,7 +110,7 @@
     mach_max_dma_address = 0xffffffff;
     mach_sched_init      = bvme6000_sched_init;
     mach_init_IRQ        = bvme6000_init_IRQ;
-    mach_gettimeoffset   = bvme6000_gettimeoffset;
+    arch_gettimeoffset   = bvme6000_gettimeoffset;
     mach_hwclk           = bvme6000_hwclk;
     mach_set_clock_mmss	 = bvme6000_set_clock_mmss;
     mach_reset		 = bvme6000_reset;
@@ -216,13 +216,13 @@
  * results...
  */
 
-unsigned long bvme6000_gettimeoffset (void)
+u32 bvme6000_gettimeoffset(void)
 {
     volatile RtcPtr_t rtc = (RtcPtr_t)BVME_RTC_BASE;
     volatile PitRegsPtr pit = (PitRegsPtr)BVME_PIT_BASE;
     unsigned char msr = rtc->msr & 0xc0;
     unsigned char t1int, t1op;
-    unsigned long v = 800000, ov;
+    u32 v = 800000, ov;
 
     rtc->msr = 0;	/* Ensure timer registers accessible */
 
@@ -246,7 +246,7 @@
 	v += 10000;			/* Int pending, + 10ms */
     rtc->msr = msr;
 
-    return v;
+    return v * 1000;
 }
 
 /*
diff --git a/arch/m68k/hp300/config.c b/arch/m68k/hp300/config.c
index bf16af1..b7609f7 100644
--- a/arch/m68k/hp300/config.c
+++ b/arch/m68k/hp300/config.c
@@ -251,7 +251,7 @@
 	mach_sched_init      = hp300_sched_init;
 	mach_init_IRQ        = hp300_init_IRQ;
 	mach_get_model       = hp300_get_model;
-	mach_gettimeoffset   = hp300_gettimeoffset;
+	arch_gettimeoffset   = hp300_gettimeoffset;
 	mach_hwclk	     = hp300_hwclk;
 	mach_get_ss	     = hp300_get_ss;
 	mach_reset           = hp300_reset;
diff --git a/arch/m68k/hp300/time.c b/arch/m68k/hp300/time.c
index 29a71be..749543b 100644
--- a/arch/m68k/hp300/time.c
+++ b/arch/m68k/hp300/time.c
@@ -46,7 +46,7 @@
 	return vector(irq, NULL);
 }
 
-unsigned long hp300_gettimeoffset(void)
+u32 hp300_gettimeoffset(void)
 {
   /* Read current timer 1 value */
   unsigned char lsb, msb1, msb2;
@@ -59,7 +59,7 @@
     /* A carry happened while we were reading.  Read it again */
     lsb = in_8(CLOCKBASE + 7);
   ticks = INTVAL - ((msb2 << 8) | lsb);
-  return (USECS_PER_JIFFY * ticks) / INTVAL;
+  return ((USECS_PER_JIFFY * ticks) / INTVAL) * 1000;
 }
 
 void __init hp300_sched_init(irq_handler_t vector)
diff --git a/arch/m68k/hp300/time.h b/arch/m68k/hp300/time.h
index 7b98242..f5583ec 100644
--- a/arch/m68k/hp300/time.h
+++ b/arch/m68k/hp300/time.h
@@ -1,2 +1,2 @@
 extern void hp300_sched_init(irq_handler_t vector);
-extern unsigned long hp300_gettimeoffset(void);
+extern u32 hp300_gettimeoffset(void);
diff --git a/arch/m68k/include/asm/dma-mapping.h b/arch/m68k/include/asm/dma-mapping.h
index 17f7a45..3e6b844 100644
--- a/arch/m68k/include/asm/dma-mapping.h
+++ b/arch/m68k/include/asm/dma-mapping.h
@@ -21,6 +21,22 @@
 extern void dma_free_coherent(struct device *, size_t,
 			      void *, dma_addr_t);
 
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+				    dma_addr_t *dma_handle, gfp_t flag,
+				    struct dma_attrs *attrs)
+{
+	/* attrs is not supported and ignored */
+	return dma_alloc_coherent(dev, size, dma_handle, flag);
+}
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+				  void *cpu_addr, dma_addr_t dma_handle,
+				  struct dma_attrs *attrs)
+{
+	/* attrs is not supported and ignored */
+	dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
 static inline void *dma_alloc_noncoherent(struct device *dev, size_t size,
 					  dma_addr_t *handle, gfp_t flag)
 {
diff --git a/arch/m68k/include/asm/machdep.h b/arch/m68k/include/asm/machdep.h
index 825c1c8..953ca21 100644
--- a/arch/m68k/include/asm/machdep.h
+++ b/arch/m68k/include/asm/machdep.h
@@ -3,6 +3,7 @@
 
 #include <linux/seq_file.h>
 #include <linux/interrupt.h>
+#include <linux/time.h>
 
 struct pt_regs;
 struct mktime;
@@ -16,7 +17,6 @@
 extern void (*mach_get_model) (char *model);
 extern void (*mach_get_hardware_list) (struct seq_file *m);
 /* machine dependent timer functions */
-extern unsigned long (*mach_gettimeoffset)(void);
 extern int (*mach_hwclk)(int, struct rtc_time*);
 extern unsigned int (*mach_get_ss)(void);
 extern int (*mach_get_rtc_pll)(struct rtc_pll_info *);
diff --git a/arch/m68k/include/asm/pgtable_no.h b/arch/m68k/include/asm/pgtable_no.h
index bf86b29..037028f 100644
--- a/arch/m68k/include/asm/pgtable_no.h
+++ b/arch/m68k/include/asm/pgtable_no.h
@@ -64,6 +64,8 @@
  */
 #define	VMALLOC_START	0
 #define	VMALLOC_END	0xffffffff
+#define	KMAP_START	0
+#define	KMAP_END	0xffffffff
 
 #include <asm-generic/pgtable.h>
 
diff --git a/arch/m68k/include/asm/unistd.h b/arch/m68k/include/asm/unistd.h
index 847994c..f9337f6 100644
--- a/arch/m68k/include/asm/unistd.h
+++ b/arch/m68k/include/asm/unistd.h
@@ -4,7 +4,7 @@
 #include <uapi/asm/unistd.h>
 
 
-#define NR_syscalls		348
+#define NR_syscalls		349
 
 #define __ARCH_WANT_OLD_READDIR
 #define __ARCH_WANT_OLD_STAT
diff --git a/arch/m68k/include/uapi/asm/unistd.h b/arch/m68k/include/uapi/asm/unistd.h
index b94bfbf..625f321 100644
--- a/arch/m68k/include/uapi/asm/unistd.h
+++ b/arch/m68k/include/uapi/asm/unistd.h
@@ -353,5 +353,6 @@
 #define __NR_process_vm_readv	345
 #define __NR_process_vm_writev	346
 #define __NR_kcmp		347
+#define __NR_finit_module	348
 
 #endif /* _UAPI_ASM_M68K_UNISTD_H_ */
diff --git a/arch/m68k/kernel/setup_mm.c b/arch/m68k/kernel/setup_mm.c
index d872ce4..80cfbe5 100644
--- a/arch/m68k/kernel/setup_mm.c
+++ b/arch/m68k/kernel/setup_mm.c
@@ -84,7 +84,6 @@
 void (*mach_get_model) (char *model);
 void (*mach_get_hardware_list) (struct seq_file *m);
 /* machine dependent timer functions */
-unsigned long (*mach_gettimeoffset) (void);
 int (*mach_hwclk) (int, struct rtc_time*);
 EXPORT_SYMBOL(mach_hwclk);
 int (*mach_set_clock_mmss) (unsigned long);
diff --git a/arch/m68k/kernel/syscalltable.S b/arch/m68k/kernel/syscalltable.S
index c30da5b..3f04ea0 100644
--- a/arch/m68k/kernel/syscalltable.S
+++ b/arch/m68k/kernel/syscalltable.S
@@ -368,4 +368,5 @@
 	.long sys_process_vm_readv	/* 345 */
 	.long sys_process_vm_writev
 	.long sys_kcmp
+	.long sys_finit_module
 
diff --git a/arch/m68k/kernel/time.c b/arch/m68k/kernel/time.c
index 5d0bcaa..bea6bcf 100644
--- a/arch/m68k/kernel/time.c
+++ b/arch/m68k/kernel/time.c
@@ -80,18 +80,8 @@
 	}
 }
 
-void __init time_init(void)
-{
-	mach_sched_init(timer_interrupt);
-}
-
 #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
 
-u32 arch_gettimeoffset(void)
-{
-	return mach_gettimeoffset() * 1000;
-}
-
 static int __init rtc_init(void)
 {
 	struct platform_device *pdev;
@@ -106,3 +96,8 @@
 module_init(rtc_init);
 
 #endif /* CONFIG_ARCH_USES_GETTIMEOFFSET */
+
+void __init time_init(void)
+{
+	mach_sched_init(timer_interrupt);
+}
diff --git a/arch/m68k/mac/config.c b/arch/m68k/mac/config.c
index d9f62e0..afb95d5 100644
--- a/arch/m68k/mac/config.c
+++ b/arch/m68k/mac/config.c
@@ -52,7 +52,7 @@
 static unsigned long mac_orig_videoaddr;
 
 /* Mac specific timer functions */
-extern unsigned long mac_gettimeoffset(void);
+extern u32 mac_gettimeoffset(void);
 extern int mac_hwclk(int, struct rtc_time *);
 extern int mac_set_clock_mmss(unsigned long);
 extern void iop_preinit(void);
@@ -177,7 +177,7 @@
 	mach_sched_init = mac_sched_init;
 	mach_init_IRQ = mac_init_IRQ;
 	mach_get_model = mac_get_model;
-	mach_gettimeoffset = mac_gettimeoffset;
+	arch_gettimeoffset = mac_gettimeoffset;
 	mach_hwclk = mac_hwclk;
 	mach_set_clock_mmss = mac_set_clock_mmss;
 	mach_reset = mac_reset;
diff --git a/arch/m68k/mac/via.c b/arch/m68k/mac/via.c
index 2d85662..5d1458b 100644
--- a/arch/m68k/mac/via.c
+++ b/arch/m68k/mac/via.c
@@ -327,7 +327,7 @@
  * TBI: get time offset between scheduling timer ticks
  */
 
-unsigned long mac_gettimeoffset (void)
+u32 mac_gettimeoffset(void)
 {
 	unsigned long ticks, offset = 0;
 
@@ -341,7 +341,7 @@
 	ticks = MAC_CLOCK_TICK - ticks;
 	ticks = ticks * 10000L / MAC_CLOCK_TICK;
 
-	return ticks + offset;
+	return (ticks + offset) * 1000;
 }
 
 /*
diff --git a/arch/m68k/mm/init.c b/arch/m68k/mm/init.c
index f0e05bc..afd8106f 100644
--- a/arch/m68k/mm/init.c
+++ b/arch/m68k/mm/init.c
@@ -39,6 +39,11 @@
 void *empty_zero_page;
 EXPORT_SYMBOL(empty_zero_page);
 
+#if !defined(CONFIG_SUN3) && !defined(CONFIG_COLDFIRE)
+extern void init_pointer_table(unsigned long ptable);
+extern pmd_t *zero_pgtable;
+#endif
+
 #ifdef CONFIG_MMU
 
 pg_data_t pg_data_map[MAX_NUMNODES];
@@ -69,9 +74,6 @@
 	node_set_online(node);
 }
 
-extern void init_pointer_table(unsigned long ptable);
-extern pmd_t *zero_pgtable;
-
 #else /* CONFIG_MMU */
 
 /*
diff --git a/arch/m68k/mvme147/config.c b/arch/m68k/mvme147/config.c
index a41c091..1c62628 100644
--- a/arch/m68k/mvme147/config.c
+++ b/arch/m68k/mvme147/config.c
@@ -37,7 +37,7 @@
 
 static void mvme147_get_model(char *model);
 extern void mvme147_sched_init(irq_handler_t handler);
-extern unsigned long mvme147_gettimeoffset (void);
+extern u32 mvme147_gettimeoffset(void);
 extern int mvme147_hwclk (int, struct rtc_time *);
 extern int mvme147_set_clock_mmss (unsigned long);
 extern void mvme147_reset (void);
@@ -88,7 +88,7 @@
 	mach_max_dma_address	= 0x01000000;
 	mach_sched_init		= mvme147_sched_init;
 	mach_init_IRQ		= mvme147_init_IRQ;
-	mach_gettimeoffset	= mvme147_gettimeoffset;
+	arch_gettimeoffset	= mvme147_gettimeoffset;
 	mach_hwclk		= mvme147_hwclk;
 	mach_set_clock_mmss	= mvme147_set_clock_mmss;
 	mach_reset		= mvme147_reset;
@@ -127,7 +127,7 @@
 
 /* This is always executed with interrupts disabled.  */
 /* XXX There are race hazards in this code XXX */
-unsigned long mvme147_gettimeoffset (void)
+u32 mvme147_gettimeoffset(void)
 {
 	volatile unsigned short *cp = (volatile unsigned short *)0xfffe1012;
 	unsigned short n;
@@ -137,7 +137,7 @@
 		n = *cp;
 
 	n -= PCC_TIMER_PRELOAD;
-	return (unsigned long)n * 25 / 4;
+	return ((unsigned long)n * 25 / 4) * 1000;
 }
 
 static int bcd2int (unsigned char b)
diff --git a/arch/m68k/mvme16x/config.c b/arch/m68k/mvme16x/config.c
index b6d7d8a..080a342 100644
--- a/arch/m68k/mvme16x/config.c
+++ b/arch/m68k/mvme16x/config.c
@@ -43,7 +43,7 @@
 
 static void mvme16x_get_model(char *model);
 extern void mvme16x_sched_init(irq_handler_t handler);
-extern unsigned long mvme16x_gettimeoffset (void);
+extern u32 mvme16x_gettimeoffset(void);
 extern int mvme16x_hwclk (int, struct rtc_time *);
 extern int mvme16x_set_clock_mmss (unsigned long);
 extern void mvme16x_reset (void);
@@ -289,7 +289,7 @@
     mach_max_dma_address = 0xffffffff;
     mach_sched_init      = mvme16x_sched_init;
     mach_init_IRQ        = mvme16x_init_IRQ;
-    mach_gettimeoffset   = mvme16x_gettimeoffset;
+    arch_gettimeoffset   = mvme16x_gettimeoffset;
     mach_hwclk           = mvme16x_hwclk;
     mach_set_clock_mmss	 = mvme16x_set_clock_mmss;
     mach_reset		 = mvme16x_reset;
@@ -405,9 +405,9 @@
 
 
 /* This is always executed with interrupts disabled.  */
-unsigned long mvme16x_gettimeoffset (void)
+u32 mvme16x_gettimeoffset(void)
 {
-    return (*(volatile unsigned long *)0xfff42008);
+    return (*(volatile u32 *)0xfff42008) * 1000;
 }
 
 int bcd2int (unsigned char b)
diff --git a/arch/m68k/q40/config.c b/arch/m68k/q40/config.c
index 1adb5b7..658542b 100644
--- a/arch/m68k/q40/config.c
+++ b/arch/m68k/q40/config.c
@@ -40,7 +40,7 @@
 static void q40_get_model(char *model);
 extern void q40_sched_init(irq_handler_t handler);
 
-static unsigned long q40_gettimeoffset(void);
+static u32 q40_gettimeoffset(void);
 static int q40_hwclk(int, struct rtc_time *);
 static unsigned int q40_get_ss(void);
 static int q40_set_clock_mmss(unsigned long);
@@ -170,7 +170,7 @@
 	mach_sched_init = q40_sched_init;
 
 	mach_init_IRQ = q40_init_IRQ;
-	mach_gettimeoffset = q40_gettimeoffset;
+	arch_gettimeoffset = q40_gettimeoffset;
 	mach_hwclk = q40_hwclk;
 	mach_get_ss = q40_get_ss;
 	mach_get_rtc_pll = q40_get_rtc_pll;
@@ -204,9 +204,9 @@
 }
 
 
-static unsigned long q40_gettimeoffset(void)
+static u32 q40_gettimeoffset(void)
 {
-	return 5000 * (ql_ticks != 0);
+	return 5000 * (ql_ticks != 0) * 1000;
 }
 
 
diff --git a/arch/m68k/sun3/config.c b/arch/m68k/sun3/config.c
index 2ca25bd..f59ec58 100644
--- a/arch/m68k/sun3/config.c
+++ b/arch/m68k/sun3/config.c
@@ -36,7 +36,7 @@
 
 char sun3_reserved_pmeg[SUN3_PMEGS_NUM];
 
-extern unsigned long sun3_gettimeoffset(void);
+extern u32 sun3_gettimeoffset(void);
 static void sun3_sched_init(irq_handler_t handler);
 extern void sun3_get_model (char* model);
 extern int sun3_hwclk(int set, struct rtc_time *t);
@@ -141,7 +141,7 @@
         mach_sched_init      =  sun3_sched_init;
         mach_init_IRQ        =  sun3_init_IRQ;
         mach_reset           =  sun3_reboot;
-	mach_gettimeoffset   =  sun3_gettimeoffset;
+	arch_gettimeoffset   =  sun3_gettimeoffset;
 	mach_get_model	     =  sun3_get_model;
 	mach_hwclk           =  sun3_hwclk;
 	mach_halt	     =  sun3_halt;
diff --git a/arch/m68k/sun3/intersil.c b/arch/m68k/sun3/intersil.c
index 94fe801..889829e 100644
--- a/arch/m68k/sun3/intersil.c
+++ b/arch/m68k/sun3/intersil.c
@@ -23,9 +23,9 @@
 #define START_VAL (INTERSIL_RUN | INTERSIL_INT_ENABLE | INTERSIL_24H_MODE)
 
 /* does this need to be implemented? */
-unsigned long sun3_gettimeoffset(void)
+u32 sun3_gettimeoffset(void)
 {
-  return 1;
+  return 1000;
 }
 
 
diff --git a/arch/m68k/sun3x/config.c b/arch/m68k/sun3x/config.c
index dd306c8..0532d64 100644
--- a/arch/m68k/sun3x/config.c
+++ b/arch/m68k/sun3x/config.c
@@ -48,7 +48,7 @@
 	mach_sched_init      = sun3x_sched_init;
 	mach_init_IRQ        = sun3_init_IRQ;
 
-	mach_gettimeoffset   = sun3x_gettimeoffset;
+	arch_gettimeoffset   = sun3x_gettimeoffset;
 	mach_reset           = sun3x_reboot;
 
 	mach_hwclk           = sun3x_hwclk;
diff --git a/arch/m68k/sun3x/time.c b/arch/m68k/sun3x/time.c
index 1d0a724..c8eb08a 100644
--- a/arch/m68k/sun3x/time.c
+++ b/arch/m68k/sun3x/time.c
@@ -71,7 +71,7 @@
 	return 0;
 }
 /* Not much we can do here */
-unsigned long sun3x_gettimeoffset (void)
+u32 sun3x_gettimeoffset(void)
 {
     return 0L;
 }
diff --git a/arch/m68k/sun3x/time.h b/arch/m68k/sun3x/time.h
index 6909e12..a4f9126 100644
--- a/arch/m68k/sun3x/time.h
+++ b/arch/m68k/sun3x/time.h
@@ -2,7 +2,7 @@
 #define SUN3X_TIME_H
 
 extern int sun3x_hwclk(int set, struct rtc_time *t);
-unsigned long sun3x_gettimeoffset (void);
+u32 sun3x_gettimeoffset(void);
 void sun3x_sched_init(irq_handler_t vector);
 
 struct mostek_dt {
diff --git a/arch/mips/bcm47xx/Kconfig b/arch/mips/bcm47xx/Kconfig
index d7af29f..ba61192 100644
--- a/arch/mips/bcm47xx/Kconfig
+++ b/arch/mips/bcm47xx/Kconfig
@@ -8,8 +8,10 @@
 	select SSB_DRIVER_EXTIF
 	select SSB_EMBEDDED
 	select SSB_B43_PCI_BRIDGE if PCI
+	select SSB_DRIVER_PCICORE if PCI
 	select SSB_PCICORE_HOSTMODE if PCI
 	select SSB_DRIVER_GPIO
+	select GPIOLIB
 	default y
 	help
 	 Add support for old Broadcom BCM47xx boards with Sonics Silicon Backplane support.
@@ -25,6 +27,7 @@
 	select BCMA_HOST_PCI if PCI
 	select BCMA_DRIVER_PCI_HOSTMODE if PCI
 	select BCMA_DRIVER_GPIO
+	select GPIOLIB
 	default y
 	help
 	 Add support for new Broadcom BCM47xx boards with Broadcom specific Advanced Microcontroller Bus.
diff --git a/arch/mips/cavium-octeon/executive/cvmx-l2c.c b/arch/mips/cavium-octeon/executive/cvmx-l2c.c
index 9f883bf..33b7214 100644
--- a/arch/mips/cavium-octeon/executive/cvmx-l2c.c
+++ b/arch/mips/cavium-octeon/executive/cvmx-l2c.c
@@ -30,6 +30,7 @@
  * measurement, and debugging facilities.
  */
 
+#include <linux/compiler.h>
 #include <linux/irqflags.h>
 #include <asm/octeon/cvmx.h>
 #include <asm/octeon/cvmx-l2c.h>
@@ -285,22 +286,22 @@
  */
 static void fault_in(uint64_t addr, int len)
 {
-	volatile char *ptr;
-	volatile char dummy;
+	char *ptr;
+
 	/*
 	 * Adjust addr and length so we get all cache lines even for
 	 * small ranges spanning two cache lines.
 	 */
 	len += addr & CVMX_CACHE_LINE_MASK;
 	addr &= ~CVMX_CACHE_LINE_MASK;
-	ptr = (volatile char *)cvmx_phys_to_ptr(addr);
+	ptr = cvmx_phys_to_ptr(addr);
 	/*
 	 * Invalidate L1 cache to make sure all loads result in data
 	 * being in L2.
 	 */
 	CVMX_DCACHE_INVALIDATE;
 	while (len > 0) {
-		dummy += *ptr;
+		ACCESS_ONCE(*ptr);
 		len -= CVMX_CACHE_LINE_SIZE;
 		ptr += CVMX_CACHE_LINE_SIZE;
 	}
diff --git a/arch/mips/include/asm/dsp.h b/arch/mips/include/asm/dsp.h
index e9bfc08..7bfad05 100644
--- a/arch/mips/include/asm/dsp.h
+++ b/arch/mips/include/asm/dsp.h
@@ -16,7 +16,7 @@
 #include <asm/mipsregs.h>
 
 #define DSP_DEFAULT	0x00000000
-#define DSP_MASK	0x3ff
+#define DSP_MASK	0x3f
 
 #define __enable_dsp_hazard()						\
 do {									\
diff --git a/arch/mips/include/asm/inst.h b/arch/mips/include/asm/inst.h
index ab84064..33c34adb 100644
--- a/arch/mips/include/asm/inst.h
+++ b/arch/mips/include/asm/inst.h
@@ -353,6 +353,7 @@
 	struct u_format u_format;
 	struct c_format c_format;
 	struct r_format r_format;
+	struct p_format p_format;
 	struct f_format f_format;
 	struct ma_format ma_format;
 	struct b_format b_format;
diff --git a/arch/mips/include/asm/mach-pnx833x/war.h b/arch/mips/include/asm/mach-pnx833x/war.h
index edaa06d..e410df4 100644
--- a/arch/mips/include/asm/mach-pnx833x/war.h
+++ b/arch/mips/include/asm/mach-pnx833x/war.h
@@ -21,4 +21,4 @@
 #define R10000_LLSC_WAR			0
 #define MIPS34K_MISSED_ITLB_WAR		0
 
-#endif /* __ASM_MIPS_MACH_PNX8550_WAR_H */
+#endif /* __ASM_MIPS_MACH_PNX833X_WAR_H */
diff --git a/arch/mips/include/asm/pgtable-64.h b/arch/mips/include/asm/pgtable-64.h
index c631910..013d5f7 100644
--- a/arch/mips/include/asm/pgtable-64.h
+++ b/arch/mips/include/asm/pgtable-64.h
@@ -230,6 +230,7 @@
 #else
 #define pte_pfn(x)		((unsigned long)((x).pte >> _PFN_SHIFT))
 #define pfn_pte(pfn, prot)	__pte(((pfn) << _PFN_SHIFT) | pgprot_val(prot))
+#define pfn_pmd(pfn, prot)	__pmd(((pfn) << _PFN_SHIFT) | pgprot_val(prot))
 #endif
 
 #define __pgd_offset(address)	pgd_index(address)
diff --git a/arch/mips/include/uapi/asm/Kbuild b/arch/mips/include/uapi/asm/Kbuild
index a1a0452..77d4fb3 100644
--- a/arch/mips/include/uapi/asm/Kbuild
+++ b/arch/mips/include/uapi/asm/Kbuild
@@ -3,6 +3,7 @@
 
 header-y += auxvec.h
 header-y += bitsperlong.h
+header-y += break.h
 header-y += byteorder.h
 header-y += cachectl.h
 header-y += errno.h
diff --git a/arch/mips/include/asm/break.h b/arch/mips/include/uapi/asm/break.h
similarity index 100%
rename from arch/mips/include/asm/break.h
rename to arch/mips/include/uapi/asm/break.h
diff --git a/arch/mips/kernel/ftrace.c b/arch/mips/kernel/ftrace.c
index 6a2d758..83fa146 100644
--- a/arch/mips/kernel/ftrace.c
+++ b/arch/mips/kernel/ftrace.c
@@ -25,6 +25,12 @@
 #define MCOUNT_OFFSET_INSNS 4
 #endif
 
+/* Arch override because MIPS doesn't need to run this from stop_machine() */
+void arch_ftrace_update_code(int command)
+{
+	ftrace_modify_all_code(command);
+}
+
 /*
  * Check if the address is in kernel space
  *
@@ -89,6 +95,24 @@
 	return 0;
 }
 
+#ifndef CONFIG_64BIT
+static int ftrace_modify_code_2(unsigned long ip, unsigned int new_code1,
+				unsigned int new_code2)
+{
+	int faulted;
+
+	safe_store_code(new_code1, ip, faulted);
+	if (unlikely(faulted))
+		return -EFAULT;
+	ip += 4;
+	safe_store_code(new_code2, ip, faulted);
+	if (unlikely(faulted))
+		return -EFAULT;
+	flush_icache_range(ip, ip + 8); /* original ip + 12 */
+	return 0;
+}
+#endif
+
 /*
  * The details about the calling site of mcount on MIPS
  *
@@ -131,8 +155,18 @@
 	 * needed.
 	 */
 	new = in_kernel_space(ip) ? INSN_NOP : INSN_B_1F;
-
+#ifdef CONFIG_64BIT
 	return ftrace_modify_code(ip, new);
+#else
+	/*
+	 * On 32 bit MIPS platforms, gcc adds a stack adjust
+	 * instruction in the delay slot after the branch to
+	 * mcount and expects mcount to restore the sp on return.
+	 * This is based on a legacy API and does nothing but
+	 * waste instructions so it's being removed at runtime.
+	 */
+	return ftrace_modify_code_2(ip, new, INSN_NOP);
+#endif
 }
 
 int ftrace_make_call(struct dyn_ftrace *rec, unsigned long addr)
diff --git a/arch/mips/kernel/mcount.S b/arch/mips/kernel/mcount.S
index 4c968e7..1658676 100644
--- a/arch/mips/kernel/mcount.S
+++ b/arch/mips/kernel/mcount.S
@@ -46,9 +46,8 @@
 	PTR_L	a5, PT_R9(sp)
 	PTR_L	a6, PT_R10(sp)
 	PTR_L	a7, PT_R11(sp)
-	PTR_ADDIU	sp, PT_SIZE
 #else
-	PTR_ADDIU	sp, (PT_SIZE + 8)
+	PTR_ADDIU	sp, PT_SIZE
 #endif
 .endm
 
@@ -69,7 +68,9 @@
 	.globl _mcount
 _mcount:
 	b	ftrace_stub
-	 nop
+	addiu sp,sp,8
+
+	/* When tracing is activated, it calls ftrace_caller+8 (aka here) */
 	lw	t1, function_trace_stop
 	bnez	t1, ftrace_stub
 	 nop
diff --git a/arch/mips/kernel/vpe.c b/arch/mips/kernel/vpe.c
index eec690a..147cec1 100644
--- a/arch/mips/kernel/vpe.c
+++ b/arch/mips/kernel/vpe.c
@@ -705,7 +705,7 @@
 
 			printk(KERN_WARNING
 			       "VPE loader: TC %d is already in use.\n",
-                               t->index);
+			       v->tc->index);
 			return -ENOEXEC;
 		}
 	} else {
diff --git a/arch/mips/lantiq/irq.c b/arch/mips/lantiq/irq.c
index f36acd1..a7935bf 100644
--- a/arch/mips/lantiq/irq.c
+++ b/arch/mips/lantiq/irq.c
@@ -408,7 +408,7 @@
 #endif
 
 	/* tell oprofile which irq to use */
-	cp0_perfcount_irq = LTQ_PERF_IRQ;
+	cp0_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
 
 	/*
 	 * if the timer irq is not one of the mips irqs we need to
diff --git a/arch/mips/lib/delay.c b/arch/mips/lib/delay.c
index dc81ca8..288f795 100644
--- a/arch/mips/lib/delay.c
+++ b/arch/mips/lib/delay.c
@@ -21,7 +21,7 @@
 	"	.set	noreorder				\n"
 	"	.align	3					\n"
 	"1:	bnez	%0, 1b					\n"
-#if __SIZEOF_LONG__ == 4
+#if BITS_PER_LONG == 32
 	"	subu	%0, 1					\n"
 #else
 	"	dsubu	%0, 1					\n"
diff --git a/arch/mips/mm/ioremap.c b/arch/mips/mm/ioremap.c
index 7657fd2..cacfd31 100644
--- a/arch/mips/mm/ioremap.c
+++ b/arch/mips/mm/ioremap.c
@@ -190,9 +190,3 @@
 
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(__iounmap);
-
-int __virt_addr_valid(const volatile void *kaddr)
-{
-	return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
-}
-EXPORT_SYMBOL_GPL(__virt_addr_valid);
diff --git a/arch/mips/mm/mmap.c b/arch/mips/mm/mmap.c
index d9be754..7e5fe27 100644
--- a/arch/mips/mm/mmap.c
+++ b/arch/mips/mm/mmap.c
@@ -192,3 +192,9 @@
 
 	return ret;
 }
+
+int __virt_addr_valid(const volatile void *kaddr)
+{
+	return pfn_valid(PFN_DOWN(virt_to_phys(kaddr)));
+}
+EXPORT_SYMBOL_GPL(__virt_addr_valid);
diff --git a/arch/mips/netlogic/xlr/setup.c b/arch/mips/netlogic/xlr/setup.c
index 4e7f49d..c5ce699 100644
--- a/arch/mips/netlogic/xlr/setup.c
+++ b/arch/mips/netlogic/xlr/setup.c
@@ -193,8 +193,11 @@
 
 void __init prom_init(void)
 {
-	int i, *argv, *envp;		/* passed as 32 bit ptrs */
+	int *argv, *envp;		/* passed as 32 bit ptrs */
 	struct psb_info *prom_infop;
+#ifdef CONFIG_SMP
+	int i;
+#endif
 
 	/* truncate to 32 bit and sign extend all args */
 	argv = (int *)(long)(int)fw_arg1;
diff --git a/arch/mips/pci/pci-ar71xx.c b/arch/mips/pci/pci-ar71xx.c
index 1552522..6eaa4f2 100644
--- a/arch/mips/pci/pci-ar71xx.c
+++ b/arch/mips/pci/pci-ar71xx.c
@@ -24,7 +24,7 @@
 #include <asm/mach-ath79/pci.h>
 
 #define AR71XX_PCI_MEM_BASE	0x10000000
-#define AR71XX_PCI_MEM_SIZE	0x08000000
+#define AR71XX_PCI_MEM_SIZE	0x07000000
 
 #define AR71XX_PCI_WIN0_OFFS		0x10000000
 #define AR71XX_PCI_WIN1_OFFS		0x11000000
diff --git a/arch/mips/pci/pci-ar724x.c b/arch/mips/pci/pci-ar724x.c
index 86d77a6..c11c75b 100644
--- a/arch/mips/pci/pci-ar724x.c
+++ b/arch/mips/pci/pci-ar724x.c
@@ -21,7 +21,7 @@
 #define AR724X_PCI_CTRL_SIZE	0x100
 
 #define AR724X_PCI_MEM_BASE	0x10000000
-#define AR724X_PCI_MEM_SIZE	0x08000000
+#define AR724X_PCI_MEM_SIZE	0x04000000
 
 #define AR724X_PCI_REG_RESET		0x18
 #define AR724X_PCI_REG_INT_STATUS	0x4c
diff --git a/arch/mn10300/Kconfig b/arch/mn10300/Kconfig
index aa03f2e..e70001c 100644
--- a/arch/mn10300/Kconfig
+++ b/arch/mn10300/Kconfig
@@ -6,6 +6,7 @@
 	select ARCH_WANT_IPC_PARSE_VERSION
 	select HAVE_ARCH_TRACEHOOK
 	select HAVE_ARCH_KGDB
+	select GENERIC_ATOMIC64
 	select HAVE_NMI_WATCHDOG if MN10300_WD_TIMER
 	select GENERIC_CLOCKEVENTS
 	select MODULES_USE_ELF_RELA
diff --git a/arch/parisc/kernel/entry.S b/arch/parisc/kernel/entry.S
index bfb4424..eb7850b 100644
--- a/arch/parisc/kernel/entry.S
+++ b/arch/parisc/kernel/entry.S
@@ -1865,7 +1865,7 @@
 
 	/* Are we being ptraced? */
 	ldw	TASK_FLAGS(%r1),%r19
-	ldi	(_TIF_SINGLESTEP|_TIF_BLOCKSTEP),%r2
+	ldi	_TIF_SYSCALL_TRACE_MASK,%r2
 	and,COND(=)	%r19,%r2,%r0
 	b,n	syscall_restore_rfi
 
@@ -1978,15 +1978,23 @@
 	/* sr2 should be set to zero for userspace syscalls */
 	STREG	%r0,TASK_PT_SR2(%r1)
 
-pt_regs_ok:
 	LDREG	TASK_PT_GR31(%r1),%r2
-	depi	3,31,2,%r2			   /* ensure return to user mode. */
-	STREG	%r2,TASK_PT_IAOQ0(%r1)
+	depi	3,31,2,%r2		   /* ensure return to user mode. */
+	STREG   %r2,TASK_PT_IAOQ0(%r1)
 	ldo	4(%r2),%r2
 	STREG	%r2,TASK_PT_IAOQ1(%r1)
-	copy	%r25,%r16
 	b	intr_restore
-	nop
+	copy	%r25,%r16
+
+pt_regs_ok:
+	LDREG	TASK_PT_IAOQ0(%r1),%r2
+	depi	3,31,2,%r2		   /* ensure return to user mode. */
+	STREG	%r2,TASK_PT_IAOQ0(%r1)
+	LDREG	TASK_PT_IAOQ1(%r1),%r2
+	depi	3,31,2,%r2
+	STREG	%r2,TASK_PT_IAOQ1(%r1)
+	b	intr_restore
+	copy	%r25,%r16
 
 	.import schedule,code
 syscall_do_resched:
diff --git a/arch/parisc/kernel/irq.c b/arch/parisc/kernel/irq.c
index c0b1aff..0299d63 100644
--- a/arch/parisc/kernel/irq.c
+++ b/arch/parisc/kernel/irq.c
@@ -410,11 +410,13 @@
 {
 	local_irq_disable();	/* PARANOID - should already be disabled */
 	mtctl(~0UL, 23);	/* EIRR : clear all pending external intr */
-	claim_cpu_irqs();
 #ifdef CONFIG_SMP
-	if (!cpu_eiem)
+	if (!cpu_eiem) {
+		claim_cpu_irqs();
 		cpu_eiem = EIEM_MASK(IPI_IRQ) | EIEM_MASK(TIMER_IRQ);
+	}
 #else
+	claim_cpu_irqs();
 	cpu_eiem = EIEM_MASK(TIMER_IRQ);
 #endif
         set_eiem(cpu_eiem);	/* EIEM : enable all external intr */
diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c
index 857c2f5..534abd4 100644
--- a/arch/parisc/kernel/ptrace.c
+++ b/arch/parisc/kernel/ptrace.c
@@ -26,7 +26,7 @@
 #include <asm/asm-offsets.h>
 
 /* PSW bits we allow the debugger to modify */
-#define USER_PSW_BITS	(PSW_N | PSW_V | PSW_CB)
+#define USER_PSW_BITS	(PSW_N | PSW_B | PSW_V | PSW_CB)
 
 /*
  * Called by kernel/ptrace.c when detaching..
diff --git a/arch/parisc/kernel/signal.c b/arch/parisc/kernel/signal.c
index 5379969..fd05170 100644
--- a/arch/parisc/kernel/signal.c
+++ b/arch/parisc/kernel/signal.c
@@ -190,8 +190,10 @@
 	DBG(1,"get_sigframe: ka = %#lx, sp = %#lx, frame_size = %#lx\n",
 			(unsigned long)ka, sp, frame_size);
 	
+	/* Align alternate stack and reserve 64 bytes for the signal
+	   handler's frame marker.  */
 	if ((ka->sa.sa_flags & SA_ONSTACK) != 0 && ! sas_ss_flags(sp))
-		sp = current->sas_ss_sp; /* Stacks grow up! */
+		sp = (current->sas_ss_sp + 0x7f) & ~0x3f; /* Stacks grow up! */
 
 	DBG(1,"get_sigframe: Returning sp = %#lx\n", (unsigned long)sp);
 	return (void __user *) sp; /* Stacks grow up.  Fun. */
diff --git a/arch/parisc/math-emu/cnv_float.h b/arch/parisc/math-emu/cnv_float.h
index 9071e09..933423f 100644
--- a/arch/parisc/math-emu/cnv_float.h
+++ b/arch/parisc/math-emu/cnv_float.h
@@ -347,16 +347,15 @@
     Sgl_isinexact_to_fix(sgl_value,exponent)
 
 #define Duint_from_sgl_mantissa(sgl_value,exponent,dresultA,dresultB)	\
-  {Sall(sgl_value) <<= SGL_EXP_LENGTH;  /*  left-justify  */		\
+  {unsigned int val = Sall(sgl_value) << SGL_EXP_LENGTH;		\
     if (exponent <= 31) {						\
-    	Dintp1(dresultA) = 0;						\
-    	Dintp2(dresultB) = (unsigned)Sall(sgl_value) >> (31 - exponent); \
+	Dintp1(dresultA) = 0;						\
+	Dintp2(dresultB) = val >> (31 - exponent);			\
     }									\
     else {								\
-    	Dintp1(dresultA) = Sall(sgl_value) >> (63 - exponent);		\
-    	Dintp2(dresultB) = Sall(sgl_value) << (exponent - 31);		\
+	Dintp1(dresultA) = val >> (63 - exponent);			\
+	Dintp2(dresultB) = exponent <= 62 ? val << (exponent - 31) : 0;	\
     }									\
-    Sall(sgl_value) >>= SGL_EXP_LENGTH;  /* return to original */	\
   }
 
 #define Duint_setzero(dresultA,dresultB) 	\
diff --git a/arch/powerpc/include/uapi/asm/kvm_para.h b/arch/powerpc/include/uapi/asm/kvm_para.h
index ed0e025..e3af328 100644
--- a/arch/powerpc/include/uapi/asm/kvm_para.h
+++ b/arch/powerpc/include/uapi/asm/kvm_para.h
@@ -78,7 +78,7 @@
 
 #define KVM_HCALL_TOKEN(num)     _EV_HCALL_TOKEN(EV_KVM_VENDOR_ID, num)
 
-#include <uapi/asm/epapr_hcalls.h>
+#include <asm/epapr_hcalls.h>
 
 #define KVM_FEATURE_MAGIC_PAGE	1
 
diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S
index d22e73e..e514de5 100644
--- a/arch/powerpc/kernel/entry_32.S
+++ b/arch/powerpc/kernel/entry_32.S
@@ -439,6 +439,8 @@
 ret_from_kernel_thread:
 	REST_NVGPRS(r1)
 	bl	schedule_tail
+	li	r3,0
+	stw	r3,0(r1)
 	mtlr	r14
 	mr	r3,r15
 	PPC440EP_ERR42
diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S
index b310a05..3d990d3 100644
--- a/arch/powerpc/kernel/entry_64.S
+++ b/arch/powerpc/kernel/entry_64.S
@@ -664,6 +664,19 @@
 	ld	r4,TI_FLAGS(r9)
 	andi.	r0,r4,_TIF_NEED_RESCHED
 	bne	1b
+
+	/*
+	 * arch_local_irq_restore() from preempt_schedule_irq above may
+	 * enable hard interrupt but we really should disable interrupts
+	 * when we return from the interrupt, and so that we don't get
+	 * interrupted after loading SRR0/1.
+	 */
+#ifdef CONFIG_PPC_BOOK3E
+	wrteei	0
+#else
+	ld	r10,PACAKMSR(r13) /* Get kernel MSR without EE */
+	mtmsrd	r10,1		  /* Update machine state */
+#endif /* CONFIG_PPC_BOOK3E */
 #endif /* CONFIG_PREEMPT */
 
 	.globl	fast_exc_return_irq
diff --git a/arch/powerpc/kernel/kgdb.c b/arch/powerpc/kernel/kgdb.c
index c470a40..a7bc752 100644
--- a/arch/powerpc/kernel/kgdb.c
+++ b/arch/powerpc/kernel/kgdb.c
@@ -154,12 +154,12 @@
 static int kgdb_singlestep(struct pt_regs *regs)
 {
 	struct thread_info *thread_info, *exception_thread_info;
-	struct thread_info *backup_current_thread_info = \
-		(struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL);
+	struct thread_info *backup_current_thread_info;
 
 	if (user_mode(regs))
 		return 0;
 
+	backup_current_thread_info = (struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL);
 	/*
 	 * On Book E and perhaps other processors, singlestep is handled on
 	 * the critical exception stack.  This causes current_thread_info()
@@ -185,6 +185,7 @@
 		/* Restore current_thread_info lastly. */
 		memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info);
 
+	kfree(backup_current_thread_info);
 	return 1;
 }
 
diff --git a/arch/powerpc/kernel/time.c b/arch/powerpc/kernel/time.c
index 6f6b1cc..127361e 100644
--- a/arch/powerpc/kernel/time.c
+++ b/arch/powerpc/kernel/time.c
@@ -494,10 +494,15 @@
 	set_dec(DECREMENTER_MAX);
 
 	/* Some implementations of hotplug will get timer interrupts while
-	 * offline, just ignore these
+	 * offline, just ignore these and we also need to set
+	 * decrementers_next_tb as MAX to make sure __check_irq_replay
+	 * don't replay timer interrupt when return, otherwise we'll trap
+	 * here infinitely :(
 	 */
-	if (!cpu_online(smp_processor_id()))
+	if (!cpu_online(smp_processor_id())) {
+		*next_tb = ~(u64)0;
 		return;
+	}
 
 	/* Conditionally hard-enable interrupts now that the DEC has been
 	 * bumped to its maximum value
diff --git a/arch/powerpc/kvm/book3s_hv_ras.c b/arch/powerpc/kvm/book3s_hv_ras.c
index 35f3cf0..a353c48 100644
--- a/arch/powerpc/kvm/book3s_hv_ras.c
+++ b/arch/powerpc/kvm/book3s_hv_ras.c
@@ -79,7 +79,9 @@
 static long kvmppc_realmode_mc_power7(struct kvm_vcpu *vcpu)
 {
 	unsigned long srr1 = vcpu->arch.shregs.msr;
+#ifdef CONFIG_PPC_POWERNV
 	struct opal_machine_check_event *opal_evt;
+#endif
 	long handled = 1;
 
 	if (srr1 & SRR1_MC_LDSTERR) {
@@ -117,6 +119,7 @@
 		handled = 0;
 	}
 
+#ifdef CONFIG_PPC_POWERNV
 	/*
 	 * See if OPAL has already handled the condition.
 	 * We assume that if the condition is recovered then OPAL
@@ -131,6 +134,7 @@
 
 	if (handled)
 		opal_evt->in_use = 0;
+#endif
 
 	return handled;
 }
diff --git a/arch/powerpc/kvm/emulate.c b/arch/powerpc/kvm/emulate.c
index b0855e5..9d9cddc 100644
--- a/arch/powerpc/kvm/emulate.c
+++ b/arch/powerpc/kvm/emulate.c
@@ -39,6 +39,7 @@
 #define OP_31_XOP_TRAP      4
 #define OP_31_XOP_LWZX      23
 #define OP_31_XOP_TRAP_64   68
+#define OP_31_XOP_DCBF      86
 #define OP_31_XOP_LBZX      87
 #define OP_31_XOP_STWX      151
 #define OP_31_XOP_STBX      215
@@ -374,6 +375,7 @@
 			emulated = kvmppc_emulate_mtspr(vcpu, sprn, rs);
 			break;
 
+		case OP_31_XOP_DCBF:
 		case OP_31_XOP_DCBI:
 			/* Do nothing. The guest is performing dcbi because
 			 * hardware DMA is not snooped by the dcache, but
diff --git a/arch/powerpc/oprofile/op_model_power4.c b/arch/powerpc/oprofile/op_model_power4.c
index 315f949..f444b94 100644
--- a/arch/powerpc/oprofile/op_model_power4.c
+++ b/arch/powerpc/oprofile/op_model_power4.c
@@ -52,7 +52,7 @@
 	for (pmc = 0; pmc < 4; pmc++) {
 		psel = mmcr1 & (OPROFILE_PM_PMCSEL_MSK
 				<< (OPROFILE_MAX_PMC_NUM - pmc)
-				* OPROFILE_MAX_PMC_NUM);
+				* OPROFILE_PMSEL_FIELD_WIDTH);
 		psel = (psel >> ((OPROFILE_MAX_PMC_NUM - pmc)
 				 * OPROFILE_PMSEL_FIELD_WIDTH)) & ~1ULL;
 		unit = mmcr1 & (OPROFILE_PM_UNIT_MSK
diff --git a/arch/powerpc/platforms/pasemi/cpufreq.c b/arch/powerpc/platforms/pasemi/cpufreq.c
index 95d0017..890f30e 100644
--- a/arch/powerpc/platforms/pasemi/cpufreq.c
+++ b/arch/powerpc/platforms/pasemi/cpufreq.c
@@ -236,6 +236,13 @@
 
 static int pas_cpufreq_cpu_exit(struct cpufreq_policy *policy)
 {
+	/*
+	 * We don't support CPU hotplug. Don't unmap after the system
+	 * has already made it to a running state.
+	 */
+	if (system_state != SYSTEM_BOOTING)
+		return 0;
+
 	if (sdcasr_mapbase)
 		iounmap(sdcasr_mapbase);
 	if (sdcpwr_mapbase)
diff --git a/arch/s390/Makefile b/arch/s390/Makefile
index 4b8e08b..7e3ce78 100644
--- a/arch/s390/Makefile
+++ b/arch/s390/Makefile
@@ -24,8 +24,8 @@
 else
 LD_BFD		:= elf64-s390
 LDFLAGS		:= -m elf64_s390
-KBUILD_AFLAGS_MODULE += -fpic -D__PIC__
-KBUILD_CFLAGS_MODULE += -fpic -D__PIC__
+KBUILD_AFLAGS_MODULE += -fPIC
+KBUILD_CFLAGS_MODULE += -fPIC
 KBUILD_CFLAGS	+= -m64
 KBUILD_AFLAGS	+= -m64
 UTS_MACHINE	:= s390x
diff --git a/arch/s390/include/asm/dma.h b/arch/s390/include/asm/dma.h
index de015d8..bb9bdcd 100644
--- a/arch/s390/include/asm/dma.h
+++ b/arch/s390/include/asm/dma.h
@@ -10,4 +10,10 @@
  */
 #define MAX_DMA_ADDRESS         0x80000000
 
+#ifdef CONFIG_PCI
+extern int isa_dma_bridge_buggy;
+#else
+#define isa_dma_bridge_buggy	(0)
+#endif
+
 #endif /* _ASM_S390_DMA_H */
diff --git a/arch/s390/include/asm/io.h b/arch/s390/include/asm/io.h
index 16c3eb1..27cb321 100644
--- a/arch/s390/include/asm/io.h
+++ b/arch/s390/include/asm/io.h
@@ -85,6 +85,11 @@
 #define __raw_writel	zpci_write_u32
 #define __raw_writeq	zpci_write_u64
 
+#define readb_relaxed	readb
+#define readw_relaxed	readw
+#define readl_relaxed	readl
+#define readq_relaxed	readq
+
 #endif /* CONFIG_PCI */
 
 #include <asm-generic/io.h>
diff --git a/arch/s390/include/asm/irq.h b/arch/s390/include/asm/irq.h
index e6972f8..7def773 100644
--- a/arch/s390/include/asm/irq.h
+++ b/arch/s390/include/asm/irq.h
@@ -2,43 +2,61 @@
 #define _ASM_IRQ_H
 
 #include <linux/hardirq.h>
+#include <linux/percpu.h>
+#include <linux/cache.h>
 #include <linux/types.h>
 
-enum interruption_class {
+enum interruption_main_class {
 	EXTERNAL_INTERRUPT,
 	IO_INTERRUPT,
-	EXTINT_CLK,
-	EXTINT_EXC,
-	EXTINT_EMS,
-	EXTINT_TMR,
-	EXTINT_TLA,
-	EXTINT_PFL,
-	EXTINT_DSD,
-	EXTINT_VRT,
-	EXTINT_SCP,
-	EXTINT_IUC,
-	EXTINT_CMS,
-	EXTINT_CMC,
-	EXTINT_CMR,
-	IOINT_CIO,
-	IOINT_QAI,
-	IOINT_DAS,
-	IOINT_C15,
-	IOINT_C70,
-	IOINT_TAP,
-	IOINT_VMR,
-	IOINT_LCS,
-	IOINT_CLW,
-	IOINT_CTC,
-	IOINT_APB,
-	IOINT_ADM,
-	IOINT_CSC,
-	IOINT_PCI,
-	IOINT_MSI,
-	NMI_NMI,
-	NR_IRQS,
+	NR_IRQS
 };
 
+enum interruption_class {
+	IRQEXT_CLK,
+	IRQEXT_EXC,
+	IRQEXT_EMS,
+	IRQEXT_TMR,
+	IRQEXT_TLA,
+	IRQEXT_PFL,
+	IRQEXT_DSD,
+	IRQEXT_VRT,
+	IRQEXT_SCP,
+	IRQEXT_IUC,
+	IRQEXT_CMS,
+	IRQEXT_CMC,
+	IRQEXT_CMR,
+	IRQIO_CIO,
+	IRQIO_QAI,
+	IRQIO_DAS,
+	IRQIO_C15,
+	IRQIO_C70,
+	IRQIO_TAP,
+	IRQIO_VMR,
+	IRQIO_LCS,
+	IRQIO_CLW,
+	IRQIO_CTC,
+	IRQIO_APB,
+	IRQIO_ADM,
+	IRQIO_CSC,
+	IRQIO_PCI,
+	IRQIO_MSI,
+	NMI_NMI,
+	CPU_RST,
+	NR_ARCH_IRQS
+};
+
+struct irq_stat {
+	unsigned int irqs[NR_ARCH_IRQS];
+};
+
+DECLARE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
+
+static __always_inline void inc_irq_stat(enum interruption_class irq)
+{
+	__get_cpu_var(irq_stat).irqs[irq]++;
+}
+
 struct ext_code {
 	unsigned short subcode;
 	unsigned short code;
diff --git a/arch/s390/include/asm/pgtable.h b/arch/s390/include/asm/pgtable.h
index c928dc1..098adbb 100644
--- a/arch/s390/include/asm/pgtable.h
+++ b/arch/s390/include/asm/pgtable.h
@@ -1365,6 +1365,18 @@
 	__pmd_idte(address, pmdp);
 }
 
+#define __HAVE_ARCH_PMDP_SET_WRPROTECT
+static inline void pmdp_set_wrprotect(struct mm_struct *mm,
+				      unsigned long address, pmd_t *pmdp)
+{
+	pmd_t pmd = *pmdp;
+
+	if (pmd_write(pmd)) {
+		__pmd_idte(address, pmdp);
+		set_pmd_at(mm, address, pmdp, pmd_wrprotect(pmd));
+	}
+}
+
 static inline pmd_t mk_pmd_phys(unsigned long physpage, pgprot_t pgprot)
 {
 	pmd_t __pmd;
@@ -1387,10 +1399,7 @@
 
 static inline unsigned long pmd_pfn(pmd_t pmd)
 {
-	if (pmd_trans_huge(pmd))
-		return pmd_val(pmd) >> HPAGE_SHIFT;
-	else
-		return pmd_val(pmd) >> PAGE_SHIFT;
+	return pmd_val(pmd) >> PAGE_SHIFT;
 }
 #endif /* CONFIG_TRANSPARENT_HUGEPAGE */
 
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
index fba4d66..4c060bb 100644
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -128,4 +128,32 @@
 	return get_clock_xt() - sched_clock_base_cc;
 }
 
+/**
+ * tod_to_ns - convert a TOD format value to nanoseconds
+ * @todval: to be converted TOD format value
+ * Returns: number of nanoseconds that correspond to the TOD format value
+ *
+ * Converting a 64 Bit TOD format value to nanoseconds means that the value
+ * must be divided by 4.096. In order to achieve that we multiply with 125
+ * and divide by 512:
+ *
+ *    ns = (todval * 125) >> 9;
+ *
+ * In order to avoid an overflow with the multiplication we can rewrite this.
+ * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits)
+ * we end up with
+ *
+ *    ns = ((2^32 * th + tl) * 125 ) >> 9;
+ * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9);
+ *
+ */
+static inline unsigned long long tod_to_ns(unsigned long long todval)
+{
+	unsigned long long ns;
+
+	ns = ((todval >> 32) << 23) * 125;
+	ns += ((todval & 0xffffffff) * 125) >> 9;
+	return ns;
+}
+
 #endif
diff --git a/arch/s390/include/uapi/asm/unistd.h b/arch/s390/include/uapi/asm/unistd.h
index 63e6078..864f693 100644
--- a/arch/s390/include/uapi/asm/unistd.h
+++ b/arch/s390/include/uapi/asm/unistd.h
@@ -279,7 +279,8 @@
 #define __NR_process_vm_writev	341
 #define __NR_s390_runtime_instr 342
 #define __NR_kcmp		343
-#define NR_syscalls 344
+#define __NR_finit_module	344
+#define NR_syscalls 345
 
 /* 
  * There are some system calls that are not present on 64 bit, some
diff --git a/arch/s390/kernel/compat_wrapper.S b/arch/s390/kernel/compat_wrapper.S
index 827e094..9b9a805 100644
--- a/arch/s390/kernel/compat_wrapper.S
+++ b/arch/s390/kernel/compat_wrapper.S
@@ -1659,3 +1659,9 @@
 	llgfr	%r5,%r5			# unsigned long
 	llgfr	%r6,%r6			# unsigned long
 	jg	sys_kcmp
+
+ENTRY(sys_finit_module_wrapper)
+	lgfr	%r2,%r2			# int
+	llgtr	%r3,%r3			# const char __user *
+	lgfr	%r4,%r4			# int
+	jg	sys_finit_module
diff --git a/arch/s390/kernel/debug.c b/arch/s390/kernel/debug.c
index ba500d8..4e8215e 100644
--- a/arch/s390/kernel/debug.c
+++ b/arch/s390/kernel/debug.c
@@ -1127,13 +1127,14 @@
 	if (i == DEBUG_MAX_VIEWS) {
 		pr_err("Registering view %s/%s would exceed the maximum "
 		       "number of views %i\n", id->name, view->name, i);
-		debugfs_remove(pde);
 		rc = -1;
 	} else {
 		id->views[i] = view;
 		id->debugfs_entries[i] = pde;
 	}
 	spin_unlock_irqrestore(&id->lock, flags);
+	if (rc)
+		debugfs_remove(pde);
 out:
 	return rc;
 }
@@ -1146,9 +1147,9 @@
 int
 debug_unregister_view(debug_info_t * id, struct debug_view *view)
 {
-	int rc = 0;
-	int i;
+	struct dentry *dentry = NULL;
 	unsigned long flags;
+	int i, rc = 0;
 
 	if (!id)
 		goto out;
@@ -1160,10 +1161,12 @@
 	if (i == DEBUG_MAX_VIEWS)
 		rc = -1;
 	else {
-		debugfs_remove(id->debugfs_entries[i]);
+		dentry = id->debugfs_entries[i];
 		id->views[i] = NULL;
+		id->debugfs_entries[i] = NULL;
 	}
 	spin_unlock_irqrestore(&id->lock, flags);
+	debugfs_remove(dentry);
 out:
 	return rc;
 }
diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c
index bf24293..9df824e 100644
--- a/arch/s390/kernel/irq.c
+++ b/arch/s390/kernel/irq.c
@@ -24,43 +24,65 @@
 #include <asm/irq.h>
 #include "entry.h"
 
+DEFINE_PER_CPU_SHARED_ALIGNED(struct irq_stat, irq_stat);
+EXPORT_PER_CPU_SYMBOL_GPL(irq_stat);
+
 struct irq_class {
 	char *name;
 	char *desc;
 };
 
-static const struct irq_class intrclass_names[] = {
+/*
+ * The list of "main" irq classes on s390. This is the list of interrrupts
+ * that appear both in /proc/stat ("intr" line) and /proc/interrupts.
+ * Historically only external and I/O interrupts have been part of /proc/stat.
+ * We can't add the split external and I/O sub classes since the first field
+ * in the "intr" line in /proc/stat is supposed to be the sum of all other
+ * fields.
+ * Since the external and I/O interrupt fields are already sums we would end
+ * up with having a sum which accounts each interrupt twice.
+ */
+static const struct irq_class irqclass_main_desc[NR_IRQS] = {
 	[EXTERNAL_INTERRUPT] = {.name = "EXT"},
-	[IO_INTERRUPT]	     = {.name = "I/O"},
-	[EXTINT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"},
-	[EXTINT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"},
-	[EXTINT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"},
-	[EXTINT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"},
-	[EXTINT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"},
-	[EXTINT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
-	[EXTINT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"},
-	[EXTINT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"},
-	[EXTINT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"},
-	[EXTINT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"},
-	[EXTINT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
-	[EXTINT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
-	[EXTINT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
-	[IOINT_CIO]  = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
-	[IOINT_QAI]  = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
-	[IOINT_DAS]  = {.name = "DAS", .desc = "[I/O] DASD"},
-	[IOINT_C15]  = {.name = "C15", .desc = "[I/O] 3215"},
-	[IOINT_C70]  = {.name = "C70", .desc = "[I/O] 3270"},
-	[IOINT_TAP]  = {.name = "TAP", .desc = "[I/O] Tape"},
-	[IOINT_VMR]  = {.name = "VMR", .desc = "[I/O] Unit Record Devices"},
-	[IOINT_LCS]  = {.name = "LCS", .desc = "[I/O] LCS"},
-	[IOINT_CLW]  = {.name = "CLW", .desc = "[I/O] CLAW"},
-	[IOINT_CTC]  = {.name = "CTC", .desc = "[I/O] CTC"},
-	[IOINT_APB]  = {.name = "APB", .desc = "[I/O] AP Bus"},
-	[IOINT_ADM]  = {.name = "ADM", .desc = "[I/O] EADM Subchannel"},
-	[IOINT_CSC]  = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"},
-	[IOINT_PCI]  = {.name = "PCI", .desc = "[I/O] PCI Interrupt" },
-	[IOINT_MSI] =  {.name = "MSI", .desc = "[I/O] MSI Interrupt" },
+	[IO_INTERRUPT]	     = {.name = "I/O"}
+};
+
+/*
+ * The list of split external and I/O interrupts that appear only in
+ * /proc/interrupts.
+ * In addition this list contains non external / I/O events like NMIs.
+ */
+static const struct irq_class irqclass_sub_desc[NR_ARCH_IRQS] = {
+	[IRQEXT_CLK] = {.name = "CLK", .desc = "[EXT] Clock Comparator"},
+	[IRQEXT_EXC] = {.name = "EXC", .desc = "[EXT] External Call"},
+	[IRQEXT_EMS] = {.name = "EMS", .desc = "[EXT] Emergency Signal"},
+	[IRQEXT_TMR] = {.name = "TMR", .desc = "[EXT] CPU Timer"},
+	[IRQEXT_TLA] = {.name = "TAL", .desc = "[EXT] Timing Alert"},
+	[IRQEXT_PFL] = {.name = "PFL", .desc = "[EXT] Pseudo Page Fault"},
+	[IRQEXT_DSD] = {.name = "DSD", .desc = "[EXT] DASD Diag"},
+	[IRQEXT_VRT] = {.name = "VRT", .desc = "[EXT] Virtio"},
+	[IRQEXT_SCP] = {.name = "SCP", .desc = "[EXT] Service Call"},
+	[IRQEXT_IUC] = {.name = "IUC", .desc = "[EXT] IUCV"},
+	[IRQEXT_CMS] = {.name = "CMS", .desc = "[EXT] CPU-Measurement: Sampling"},
+	[IRQEXT_CMC] = {.name = "CMC", .desc = "[EXT] CPU-Measurement: Counter"},
+	[IRQEXT_CMR] = {.name = "CMR", .desc = "[EXT] CPU-Measurement: RI"},
+	[IRQIO_CIO]  = {.name = "CIO", .desc = "[I/O] Common I/O Layer Interrupt"},
+	[IRQIO_QAI]  = {.name = "QAI", .desc = "[I/O] QDIO Adapter Interrupt"},
+	[IRQIO_DAS]  = {.name = "DAS", .desc = "[I/O] DASD"},
+	[IRQIO_C15]  = {.name = "C15", .desc = "[I/O] 3215"},
+	[IRQIO_C70]  = {.name = "C70", .desc = "[I/O] 3270"},
+	[IRQIO_TAP]  = {.name = "TAP", .desc = "[I/O] Tape"},
+	[IRQIO_VMR]  = {.name = "VMR", .desc = "[I/O] Unit Record Devices"},
+	[IRQIO_LCS]  = {.name = "LCS", .desc = "[I/O] LCS"},
+	[IRQIO_CLW]  = {.name = "CLW", .desc = "[I/O] CLAW"},
+	[IRQIO_CTC]  = {.name = "CTC", .desc = "[I/O] CTC"},
+	[IRQIO_APB]  = {.name = "APB", .desc = "[I/O] AP Bus"},
+	[IRQIO_ADM]  = {.name = "ADM", .desc = "[I/O] EADM Subchannel"},
+	[IRQIO_CSC]  = {.name = "CSC", .desc = "[I/O] CHSC Subchannel"},
+	[IRQIO_PCI]  = {.name = "PCI", .desc = "[I/O] PCI Interrupt" },
+	[IRQIO_MSI]  = {.name = "MSI", .desc = "[I/O] MSI Interrupt" },
 	[NMI_NMI]    = {.name = "NMI", .desc = "[NMI] Machine Check"},
+	[CPU_RST]    = {.name = "RST", .desc = "[CPU] CPU Restart"},
 };
 
 /*
@@ -68,30 +90,34 @@
  */
 int show_interrupts(struct seq_file *p, void *v)
 {
-	int i = *(loff_t *) v, j;
+	int irq = *(loff_t *) v;
+	int cpu;
 
 	get_online_cpus();
-	if (i == 0) {
+	if (irq == 0) {
 		seq_puts(p, "           ");
-		for_each_online_cpu(j)
-			seq_printf(p, "CPU%d       ",j);
+		for_each_online_cpu(cpu)
+			seq_printf(p, "CPU%d       ", cpu);
 		seq_putc(p, '\n');
 	}
-
-	if (i < NR_IRQS) {
-		seq_printf(p, "%s: ", intrclass_names[i].name);
-#ifndef CONFIG_SMP
-		seq_printf(p, "%10u ", kstat_irqs(i));
-#else
-		for_each_online_cpu(j)
-			seq_printf(p, "%10u ", kstat_cpu(j).irqs[i]);
-#endif
-		if (intrclass_names[i].desc)
-			seq_printf(p, "  %s", intrclass_names[i].desc);
-                seq_putc(p, '\n');
-        }
+	if (irq < NR_IRQS) {
+		seq_printf(p, "%s: ", irqclass_main_desc[irq].name);
+		for_each_online_cpu(cpu)
+			seq_printf(p, "%10u ", kstat_cpu(cpu).irqs[irq]);
+		seq_putc(p, '\n');
+		goto skip_arch_irqs;
+	}
+	for (irq = 0; irq < NR_ARCH_IRQS; irq++) {
+		seq_printf(p, "%s: ", irqclass_sub_desc[irq].name);
+		for_each_online_cpu(cpu)
+			seq_printf(p, "%10u ", per_cpu(irq_stat, cpu).irqs[irq]);
+		if (irqclass_sub_desc[irq].desc)
+			seq_printf(p, "  %s", irqclass_sub_desc[irq].desc);
+		seq_putc(p, '\n');
+	}
+skip_arch_irqs:
 	put_online_cpus();
-        return 0;
+	return 0;
 }
 
 /*
@@ -222,7 +248,7 @@
 		/* Serve timer interrupts first. */
 		clock_comparator_work();
 	}
-	kstat_cpu(smp_processor_id()).irqs[EXTERNAL_INTERRUPT]++;
+	kstat_incr_irqs_this_cpu(EXTERNAL_INTERRUPT, NULL);
 	if (ext_code.code != 0x1004)
 		__get_cpu_var(s390_idle).nohz_delay = 1;
 
diff --git a/arch/s390/kernel/nmi.c b/arch/s390/kernel/nmi.c
index a6daa5c..7918fbe 100644
--- a/arch/s390/kernel/nmi.c
+++ b/arch/s390/kernel/nmi.c
@@ -254,7 +254,7 @@
 	int umode;
 
 	nmi_enter();
-	kstat_cpu(smp_processor_id()).irqs[NMI_NMI]++;
+	inc_irq_stat(NMI_NMI);
 	mci = (struct mci *) &S390_lowcore.mcck_interruption_code;
 	mcck = &__get_cpu_var(cpu_mcck);
 	umode = user_mode(regs);
diff --git a/arch/s390/kernel/perf_cpum_cf.c b/arch/s390/kernel/perf_cpum_cf.c
index c4e7269..86ec744 100644
--- a/arch/s390/kernel/perf_cpum_cf.c
+++ b/arch/s390/kernel/perf_cpum_cf.c
@@ -229,7 +229,7 @@
 	if (!(alert & CPU_MF_INT_CF_MASK))
 		return;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_CMC]++;
+	inc_irq_stat(IRQEXT_CMC);
 	cpuhw = &__get_cpu_var(cpu_hw_events);
 
 	/* Measurement alerts are shared and might happen when the PMU
diff --git a/arch/s390/kernel/runtime_instr.c b/arch/s390/kernel/runtime_instr.c
index 61066f6..077a993 100644
--- a/arch/s390/kernel/runtime_instr.c
+++ b/arch/s390/kernel/runtime_instr.c
@@ -71,7 +71,7 @@
 	if (!(param32 & CPU_MF_INT_RI_MASK))
 		return;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_CMR]++;
+	inc_irq_stat(IRQEXT_CMR);
 
 	if (!current->thread.ri_cb)
 		return;
diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c
index 2568590..a5360de 100644
--- a/arch/s390/kernel/setup.c
+++ b/arch/s390/kernel/setup.c
@@ -16,7 +16,7 @@
 #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
 
 #include <linux/errno.h>
-#include <linux/module.h>
+#include <linux/export.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/memblock.h>
@@ -289,6 +289,7 @@
  * Dummy power off function.
  */
 void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL_GPL(pm_power_off);
 
 static int __init early_parse_mem(char *p)
 {
diff --git a/arch/s390/kernel/smp.c b/arch/s390/kernel/smp.c
index 0b45baa..7433a2f 100644
--- a/arch/s390/kernel/smp.c
+++ b/arch/s390/kernel/smp.c
@@ -433,9 +433,9 @@
 
 	cpu = smp_processor_id();
 	if (ext_code.code == 0x1202)
-		kstat_cpu(cpu).irqs[EXTINT_EXC]++;
+		inc_irq_stat(IRQEXT_EXC);
 	else
-		kstat_cpu(cpu).irqs[EXTINT_EMS]++;
+		inc_irq_stat(IRQEXT_EMS);
 	/*
 	 * handle bit signal external calls
 	 */
@@ -623,9 +623,10 @@
 	return info;
 }
 
-static int smp_add_present_cpu(int cpu);
+static int __cpuinit smp_add_present_cpu(int cpu);
 
-static int __smp_rescan_cpus(struct sclp_cpu_info *info, int sysfs_add)
+static int __cpuinit __smp_rescan_cpus(struct sclp_cpu_info *info,
+				       int sysfs_add)
 {
 	struct pcpu *pcpu;
 	cpumask_t avail;
@@ -708,6 +709,7 @@
 	pfault_init();
 	notify_cpu_starting(smp_processor_id());
 	set_cpu_online(smp_processor_id(), true);
+	inc_irq_stat(CPU_RST);
 	local_irq_enable();
 	/* cpu_idle will call schedule for us */
 	cpu_idle();
@@ -985,7 +987,7 @@
 	return notifier_from_errno(err);
 }
 
-static int smp_add_present_cpu(int cpu)
+static int __cpuinit smp_add_present_cpu(int cpu)
 {
 	struct cpu *c = &pcpu_devices[cpu].cpu;
 	struct device *s = &c->dev;
diff --git a/arch/s390/kernel/syscalls.S b/arch/s390/kernel/syscalls.S
index 4817485..6a6c61f 100644
--- a/arch/s390/kernel/syscalls.S
+++ b/arch/s390/kernel/syscalls.S
@@ -352,3 +352,4 @@
 SYSCALL(sys_process_vm_writev,sys_process_vm_writev,compat_sys_process_vm_writev_wrapper)
 SYSCALL(sys_ni_syscall,sys_s390_runtime_instr,sys_s390_runtime_instr_wrapper)
 SYSCALL(sys_kcmp,sys_kcmp,sys_kcmp_wrapper)
+SYSCALL(sys_finit_module,sys_finit_module,sys_finit_module_wrapper)
diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c
index 7fcd690..a5f4f5a 100644
--- a/arch/s390/kernel/time.c
+++ b/arch/s390/kernel/time.c
@@ -63,7 +63,7 @@
  */
 unsigned long long notrace __kprobes sched_clock(void)
 {
-	return (get_clock_monotonic() * 125) >> 9;
+	return tod_to_ns(get_clock_monotonic());
 }
 
 /*
@@ -168,7 +168,7 @@
 				       unsigned int param32,
 				       unsigned long param64)
 {
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_CLK]++;
+	inc_irq_stat(IRQEXT_CLK);
 	if (S390_lowcore.clock_comparator == -1ULL)
 		set_clock_comparator(S390_lowcore.clock_comparator);
 }
@@ -179,7 +179,7 @@
 static void timing_alert_interrupt(struct ext_code ext_code,
 				   unsigned int param32, unsigned long param64)
 {
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_TLA]++;
+	inc_irq_stat(IRQEXT_TLA);
 	if (param32 & 0x00c40000)
 		etr_timing_alert((struct etr_irq_parm *) &param32);
 	if (param32 & 0x00038000)
diff --git a/arch/s390/kernel/topology.c b/arch/s390/kernel/topology.c
index f1aba87..4b2e3e3 100644
--- a/arch/s390/kernel/topology.c
+++ b/arch/s390/kernel/topology.c
@@ -10,6 +10,7 @@
 #include <linux/bootmem.h>
 #include <linux/cpuset.h>
 #include <linux/device.h>
+#include <linux/export.h>
 #include <linux/kernel.h>
 #include <linux/sched.h>
 #include <linux/init.h>
@@ -42,6 +43,7 @@
 static struct mask_info book_info;
 
 struct cpu_topology_s390 cpu_topology[NR_CPUS];
+EXPORT_SYMBOL_GPL(cpu_topology);
 
 static cpumask_t cpu_group_map(struct mask_info *info, unsigned int cpu)
 {
diff --git a/arch/s390/kvm/interrupt.c b/arch/s390/kvm/interrupt.c
index c30615e..82c481d 100644
--- a/arch/s390/kvm/interrupt.c
+++ b/arch/s390/kvm/interrupt.c
@@ -408,7 +408,7 @@
 		return 0;
 	}
 
-	sltime = ((vcpu->arch.sie_block->ckc - now)*125)>>9;
+	sltime = tod_to_ns(vcpu->arch.sie_block->ckc - now);
 
 	hrtimer_start(&vcpu->arch.ckc_timer, ktime_set (0, sltime) , HRTIMER_MODE_REL);
 	VCPU_EVENT(vcpu, 5, "enabled wait via clock comparator: %llx ns", sltime);
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index c9011bf..f090e81 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -613,7 +613,9 @@
 		kvm_s390_deliver_pending_interrupts(vcpu);
 
 	vcpu->arch.sie_block->icptcode = 0;
+	preempt_disable();
 	kvm_guest_enter();
+	preempt_enable();
 	VCPU_EVENT(vcpu, 6, "entering sie flags %x",
 		   atomic_read(&vcpu->arch.sie_block->cpuflags));
 	trace_kvm_s390_sie_enter(vcpu,
diff --git a/arch/s390/mm/fault.c b/arch/s390/mm/fault.c
index 42601d6..2fb9e63 100644
--- a/arch/s390/mm/fault.c
+++ b/arch/s390/mm/fault.c
@@ -569,7 +569,7 @@
 	subcode = ext_code.subcode;
 	if ((subcode & 0xff00) != __SUBCODE_MASK)
 		return;
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_PFL]++;
+	inc_irq_stat(IRQEXT_PFL);
 	/* Get the token (= pid of the affected task). */
 	pid = sizeof(void *) == 4 ? param32 : param64;
 	rcu_read_lock();
diff --git a/arch/s390/oprofile/hwsampler.c b/arch/s390/oprofile/hwsampler.c
index 0cb385d..b5b2916 100644
--- a/arch/s390/oprofile/hwsampler.c
+++ b/arch/s390/oprofile/hwsampler.c
@@ -233,7 +233,7 @@
 	if (!(param32 & CPU_MF_INT_SF_MASK))
 		return;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_CMS]++;
+	inc_irq_stat(IRQEXT_CMS);
 	atomic_xchg(&cb->ext_params, atomic_read(&cb->ext_params) | param32);
 
 	if (hws_wq)
diff --git a/arch/s390/pci/pci.c b/arch/s390/pci/pci.c
index ff49427..60e0372 100644
--- a/arch/s390/pci/pci.c
+++ b/arch/s390/pci/pci.c
@@ -160,35 +160,6 @@
 }
 EXPORT_SYMBOL_GPL(pci_proc_domain);
 
-/* Store PCI function information block */
-static int zpci_store_fib(struct zpci_dev *zdev, u8 *fc)
-{
-	struct zpci_fib *fib;
-	u8 status, cc;
-
-	fib = (void *) get_zeroed_page(GFP_KERNEL);
-	if (!fib)
-		return -ENOMEM;
-
-	do {
-		cc = __stpcifc(zdev->fh, 0, fib, &status);
-		if (cc == 2) {
-			msleep(ZPCI_INSN_BUSY_DELAY);
-			memset(fib, 0, PAGE_SIZE);
-		}
-	} while (cc == 2);
-
-	if (cc)
-		pr_err_once("%s: cc: %u  status: %u\n",
-			    __func__, cc, status);
-
-	/* Return PCI function controls */
-	*fc = fib->fc;
-
-	free_page((unsigned long) fib);
-	return (cc) ? -EIO : 0;
-}
-
 /* Modify PCI: Register adapter interruptions */
 static int zpci_register_airq(struct zpci_dev *zdev, unsigned int aisb,
 			      u64 aibv)
@@ -469,7 +440,7 @@
 	int rescan = 0, max = aisb_max;
 	struct zdev_irq_map *imap;
 
-	kstat_cpu(smp_processor_id()).irqs[IOINT_PCI]++;
+	inc_irq_stat(IRQIO_PCI);
 	sbit = start;
 
 scan:
@@ -481,7 +452,7 @@
 		/* find vector bit */
 		imap = bucket->imap[sbit];
 		for_each_set_bit_left(mbit, &imap->aibv, imap->msi_vecs) {
-			kstat_cpu(smp_processor_id()).irqs[IOINT_MSI]++;
+			inc_irq_stat(IRQIO_MSI);
 			clear_bit(63 - mbit, &imap->aibv);
 
 			spin_lock(&imap->lock);
diff --git a/arch/s390/pci/pci_dma.c b/arch/s390/pci/pci_dma.c
index 6138468..a547419 100644
--- a/arch/s390/pci/pci_dma.c
+++ b/arch/s390/pci/pci_dma.c
@@ -13,8 +13,6 @@
 #include <linux/pci.h>
 #include <asm/pci_dma.h>
 
-static enum zpci_ioat_dtype zpci_ioat_dt = ZPCI_IOTA_RTTO;
-
 static struct kmem_cache *dma_region_table_cache;
 static struct kmem_cache *dma_page_table_cache;
 
diff --git a/arch/sh/boards/mach-ecovec24/setup.c b/arch/sh/boards/mach-ecovec24/setup.c
index 3fede45..a0fa579 100644
--- a/arch/sh/boards/mach-ecovec24/setup.c
+++ b/arch/sh/boards/mach-ecovec24/setup.c
@@ -70,6 +70,16 @@
  *                                  OFF-ON : MMC
  */
 
+/*
+ * FSI - DA7210
+ *
+ * it needs amixer settings for playing
+ *
+ * amixer set 'HeadPhone' 80
+ * amixer set 'Out Mixer Left DAC Left' on
+ * amixer set 'Out Mixer Right DAC Right' on
+ */
+
 /* Heartbeat */
 static unsigned char led_pos[] = { 0, 1, 2, 3 };
 
diff --git a/arch/sh/include/asm/elf.h b/arch/sh/include/asm/elf.h
index 37924af..bf9f44f 100644
--- a/arch/sh/include/asm/elf.h
+++ b/arch/sh/include/asm/elf.h
@@ -203,9 +203,9 @@
 	if (vdso_enabled)					\
 		NEW_AUX_ENT(AT_SYSINFO_EHDR, VDSO_BASE);	\
 	else							\
-		NEW_AUX_ENT(AT_IGNORE, 0);
+		NEW_AUX_ENT(AT_IGNORE, 0)
 #else
-#define VSYSCALL_AUX_ENT
+#define VSYSCALL_AUX_ENT	NEW_AUX_ENT(AT_IGNORE, 0)
 #endif /* CONFIG_VSYSCALL */
 
 #ifdef CONFIG_SH_FPU
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h
index b1320d5..e699a12 100644
--- a/arch/sh/include/asm/processor_32.h
+++ b/arch/sh/include/asm/processor_32.h
@@ -39,7 +39,7 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE	PAGE_ALIGN(TASK_SIZE / 3)
 
 /*
  * Bit of SR register
diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h
index 1ee8946..1cc7d31 100644
--- a/arch/sh/include/asm/processor_64.h
+++ b/arch/sh/include/asm/processor_64.h
@@ -47,7 +47,7 @@
 /* This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE	(TASK_SIZE / 3)
+#define TASK_UNMAPPED_BASE	PAGE_ALIGN(TASK_SIZE / 3)
 
 /*
  * Bit of SR register
diff --git a/arch/sh/include/uapi/asm/unistd_32.h b/arch/sh/include/uapi/asm/unistd_32.h
index 9e465f2..d13a1d6 100644
--- a/arch/sh/include/uapi/asm/unistd_32.h
+++ b/arch/sh/include/uapi/asm/unistd_32.h
@@ -379,7 +379,8 @@
 #define __NR_process_vm_readv	365
 #define __NR_process_vm_writev	366
 #define __NR_kcmp		367
+#define __NR_finit_module	368
 
-#define NR_syscalls 368
+#define NR_syscalls 369
 
 #endif /* __ASM_SH_UNISTD_32_H */
diff --git a/arch/sh/include/uapi/asm/unistd_64.h b/arch/sh/include/uapi/asm/unistd_64.h
index 8e3a2ed..e6820c8 100644
--- a/arch/sh/include/uapi/asm/unistd_64.h
+++ b/arch/sh/include/uapi/asm/unistd_64.h
@@ -399,7 +399,8 @@
 #define __NR_process_vm_readv	376
 #define __NR_process_vm_writev	377
 #define __NR_kcmp		378
+#define __NR_finit_module	379
 
-#define NR_syscalls 379
+#define NR_syscalls 380
 
 #endif /* __ASM_SH_UNISTD_64_H */
diff --git a/arch/sh/kernel/syscalls_32.S b/arch/sh/kernel/syscalls_32.S
index fe97ae5..734234b 100644
--- a/arch/sh/kernel/syscalls_32.S
+++ b/arch/sh/kernel/syscalls_32.S
@@ -385,3 +385,4 @@
 	.long sys_process_vm_readv	/* 365 */
 	.long sys_process_vm_writev
 	.long sys_kcmp
+	.long sys_finit_module
diff --git a/arch/sh/kernel/syscalls_64.S b/arch/sh/kernel/syscalls_64.S
index 5c7b1c6..579fcb9 100644
--- a/arch/sh/kernel/syscalls_64.S
+++ b/arch/sh/kernel/syscalls_64.S
@@ -405,3 +405,4 @@
 	.long sys_process_vm_readv
 	.long sys_process_vm_writev
 	.long sys_kcmp
+	.long sys_finit_module
diff --git a/arch/sh/lib/mcount.S b/arch/sh/lib/mcount.S
index 60164e6..52aa201 100644
--- a/arch/sh/lib/mcount.S
+++ b/arch/sh/lib/mcount.S
@@ -294,6 +294,8 @@
 	.align 2
 .L_init_thread_union:
 	.long	init_thread_union
+.L_ebss:
+	.long	__bss_stop
 .Lpanic:
 	.long	panic
 .Lpanic_s:
diff --git a/arch/sparc/include/uapi/asm/unistd.h b/arch/sparc/include/uapi/asm/unistd.h
index cac719d..62ced58 100644
--- a/arch/sparc/include/uapi/asm/unistd.h
+++ b/arch/sparc/include/uapi/asm/unistd.h
@@ -407,8 +407,9 @@
 #define __NR_process_vm_writev	339
 #define __NR_kern_features	340
 #define __NR_kcmp		341
+#define __NR_finit_module	342
 
-#define NR_syscalls		342
+#define NR_syscalls		343
 
 /* Bitmask values returned from kern_features system call.  */
 #define KERN_FEATURE_MIXED_MODE_STACK	0x00000001
diff --git a/arch/sparc/kernel/pci.c b/arch/sparc/kernel/pci.c
index 04bacce..baf4366 100644
--- a/arch/sparc/kernel/pci.c
+++ b/arch/sparc/kernel/pci.c
@@ -378,7 +378,8 @@
 /* Cook up fake bus resources for SUNW,simba PCI bridges which lack
  * a proper 'ranges' property.
  */
-static void apb_fake_ranges(struct pci_dev *dev, struct pci_bus *bus,
+static void apb_fake_ranges(struct pci_dev *dev,
+			    struct pci_bus *bus,
 			    struct pci_pbm_info *pbm)
 {
 	struct pci_bus_region region;
@@ -403,13 +404,15 @@
 	pcibios_bus_to_resource(dev, res, &region);
 }
 
-static void pci_of_scan_bus(struct pci_pbm_info *pbm, struct device_node *node,
+static void pci_of_scan_bus(struct pci_pbm_info *pbm,
+			    struct device_node *node,
 			    struct pci_bus *bus);
 
 #define GET_64BIT(prop, i)	((((u64) (prop)[(i)]) << 32) | (prop)[(i)+1])
 
 static void of_scan_pci_bridge(struct pci_pbm_info *pbm,
-			       struct device_node *node, struct pci_dev *dev)
+			       struct device_node *node,
+			       struct pci_dev *dev)
 {
 	struct pci_bus *bus;
 	const u32 *busrange, *ranges;
@@ -500,7 +503,8 @@
 	pci_of_scan_bus(pbm, node, bus);
 }
 
-static void pci_of_scan_bus(struct pci_pbm_info *pbm, struct device_node *node,
+static void pci_of_scan_bus(struct pci_pbm_info *pbm,
+			    struct device_node *node,
 			    struct pci_bus *bus)
 {
 	struct device_node *child;
diff --git a/arch/sparc/kernel/pci_psycho.c b/arch/sparc/kernel/pci_psycho.c
index b852382..c647634 100644
--- a/arch/sparc/kernel/pci_psycho.c
+++ b/arch/sparc/kernel/pci_psycho.c
@@ -366,7 +366,8 @@
 	pci_config_write8(addr, 64);
 }
 
-static void psycho_scan_bus(struct pci_pbm_info *pbm, struct device *parent)
+static void psycho_scan_bus(struct pci_pbm_info *pbm,
+			    struct device *parent)
 {
 	pbm_config_busmastering(pbm);
 	pbm->is_66mhz_capable = 0;
diff --git a/arch/sparc/kernel/pci_sabre.c b/arch/sparc/kernel/pci_sabre.c
index 531186d..6f00d27 100644
--- a/arch/sparc/kernel/pci_sabre.c
+++ b/arch/sparc/kernel/pci_sabre.c
@@ -442,7 +442,8 @@
 	sabre_register_error_handlers(pbm);
 }
 
-static void sabre_pbm_init(struct pci_pbm_info *pbm, struct platform_device *op)
+static void sabre_pbm_init(struct pci_pbm_info *pbm,
+			   struct platform_device *op)
 {
 	psycho_pbm_init_common(pbm, op, "SABRE", PBM_CHIP_TYPE_SABRE);
 	pbm->pci_afsr = pbm->controller_regs + SABRE_PIOAFSR;
diff --git a/arch/sparc/kernel/pci_schizo.c b/arch/sparc/kernel/pci_schizo.c
index 29e8881..8f76f23 100644
--- a/arch/sparc/kernel/pci_schizo.c
+++ b/arch/sparc/kernel/pci_schizo.c
@@ -1306,8 +1306,9 @@
 	}
 }
 
-static int schizo_pbm_init(struct pci_pbm_info *pbm, struct platform_device *op,
-			   u32 portid, int chip_type)
+static int schizo_pbm_init(struct pci_pbm_info *pbm,
+			   struct platform_device *op, u32 portid,
+			   int chip_type)
 {
 	const struct linux_prom64_registers *regs;
 	struct device_node *dp = op->dev.of_node;
diff --git a/arch/sparc/kernel/systbls_32.S b/arch/sparc/kernel/systbls_32.S
index 5147f57..6ac43c3 100644
--- a/arch/sparc/kernel/systbls_32.S
+++ b/arch/sparc/kernel/systbls_32.S
@@ -85,4 +85,4 @@
 /*325*/	.long sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/	.long sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 /*335*/	.long sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
-/*340*/	.long sys_ni_syscall, sys_kcmp
+/*340*/	.long sys_ni_syscall, sys_kcmp, sys_finit_module
diff --git a/arch/sparc/kernel/systbls_64.S b/arch/sparc/kernel/systbls_64.S
index cdbd9b8..1009ecb 100644
--- a/arch/sparc/kernel/systbls_64.S
+++ b/arch/sparc/kernel/systbls_64.S
@@ -86,7 +86,7 @@
 	.word compat_sys_pwritev, compat_sys_rt_tgsigqueueinfo, sys_perf_event_open, compat_sys_recvmmsg, sys_fanotify_init
 /*330*/	.word sys32_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, compat_sys_open_by_handle_at, compat_sys_clock_adjtime
 	.word sys_syncfs, compat_sys_sendmmsg, sys_setns, compat_sys_process_vm_readv, compat_sys_process_vm_writev
-/*340*/	.word sys_kern_features, sys_kcmp
+/*340*/	.word sys_kern_features, sys_kcmp, sys_finit_module
 
 #endif /* CONFIG_COMPAT */
 
@@ -164,4 +164,4 @@
 	.word sys_pwritev, sys_rt_tgsigqueueinfo, sys_perf_event_open, sys_recvmmsg, sys_fanotify_init
 /*330*/	.word sys_fanotify_mark, sys_prlimit64, sys_name_to_handle_at, sys_open_by_handle_at, sys_clock_adjtime
 	.word sys_syncfs, sys_sendmmsg, sys_setns, sys_process_vm_readv, sys_process_vm_writev
-/*340*/	.word sys_kern_features, sys_kcmp
+/*340*/	.word sys_kern_features, sys_kcmp, sys_finit_module
diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 79795af..225543b 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -2138,6 +2138,7 @@
 config OLPC_XO1_SCI
 	bool "OLPC XO-1 SCI extras"
 	depends on OLPC && OLPC_XO1_PM
+	depends on INPUT=y
 	select POWER_SUPPLY
 	select GPIO_CS5535
 	select MFD_CORE
diff --git a/arch/x86/boot/Makefile b/arch/x86/boot/Makefile
index ccce0ed..379814b 100644
--- a/arch/x86/boot/Makefile
+++ b/arch/x86/boot/Makefile
@@ -71,7 +71,7 @@
 $(obj)/bzImage: asflags-y  := $(SVGA_MODE)
 
 quiet_cmd_image = BUILD   $@
-cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin > $@
+cmd_image = $(obj)/tools/build $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/zoffset.h > $@
 
 $(obj)/bzImage: $(obj)/setup.bin $(obj)/vmlinux.bin $(obj)/tools/build FORCE
 	$(call if_changed,image)
@@ -92,7 +92,7 @@
 $(obj)/voffset.h: vmlinux FORCE
 	$(call if_changed,voffset)
 
-sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
+sed-zoffset := -e 's/^\([0-9a-fA-F]*\) . \(startup_32\|startup_64\|efi_pe_entry\|efi_stub_entry\|input_data\|_end\|z_.*\)$$/\#define ZO_\2 0x\1/p'
 
 quiet_cmd_zoffset = ZOFFSET $@
       cmd_zoffset = $(NM) $< | sed -n $(sed-zoffset) > $@
diff --git a/arch/x86/boot/compressed/eboot.c b/arch/x86/boot/compressed/eboot.c
index b1942e2..f8fa411 100644
--- a/arch/x86/boot/compressed/eboot.c
+++ b/arch/x86/boot/compressed/eboot.c
@@ -256,10 +256,10 @@
 	int i;
 	struct setup_data *data;
 
-	data = (struct setup_data *)params->hdr.setup_data;
+	data = (struct setup_data *)(unsigned long)params->hdr.setup_data;
 
 	while (data && data->next)
-		data = (struct setup_data *)data->next;
+		data = (struct setup_data *)(unsigned long)data->next;
 
 	status = efi_call_phys5(sys_table->boottime->locate_handle,
 				EFI_LOCATE_BY_PROTOCOL, &pci_proto,
@@ -295,16 +295,18 @@
 		if (!pci)
 			continue;
 
+#ifdef CONFIG_X86_64
 		status = efi_call_phys4(pci->attributes, pci,
 					EfiPciIoAttributeOperationGet, 0,
 					&attributes);
-
+#else
+		status = efi_call_phys5(pci->attributes, pci,
+					EfiPciIoAttributeOperationGet, 0, 0,
+					&attributes);
+#endif
 		if (status != EFI_SUCCESS)
 			continue;
 
-		if (!attributes & EFI_PCI_IO_ATTRIBUTE_EMBEDDED_ROM)
-			continue;
-
 		if (!pci->romimage || !pci->romsize)
 			continue;
 
@@ -345,9 +347,9 @@
 		memcpy(rom->romdata, pci->romimage, pci->romsize);
 
 		if (data)
-			data->next = (uint64_t)rom;
+			data->next = (unsigned long)rom;
 		else
-			params->hdr.setup_data = (uint64_t)rom;
+			params->hdr.setup_data = (unsigned long)rom;
 
 		data = (struct setup_data *)rom;
 
@@ -432,10 +434,9 @@
 			 * Once we've found a GOP supporting ConOut,
 			 * don't bother looking any further.
 			 */
+			first_gop = gop;
 			if (conout_found)
 				break;
-
-			first_gop = gop;
 		}
 	}
 
diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S
index aa4aaf1..1e3184f 100644
--- a/arch/x86/boot/compressed/head_32.S
+++ b/arch/x86/boot/compressed/head_32.S
@@ -35,11 +35,11 @@
 #ifdef CONFIG_EFI_STUB
 	jmp	preferred_addr
 
-	.balign	0x10
 	/*
 	 * We don't need the return address, so set up the stack so
-	 * efi_main() can find its arugments.
+	 * efi_main() can find its arguments.
 	 */
+ENTRY(efi_pe_entry)
 	add	$0x4, %esp
 
 	call	make_boot_params
@@ -50,8 +50,10 @@
 	pushl	%eax
 	pushl	%esi
 	pushl	%ecx
+	sub	$0x4, %esp
 
-	.org 0x30,0x90
+ENTRY(efi_stub_entry)
+	add	$0x4, %esp
 	call	efi_main
 	cmpl	$0, %eax
 	movl	%eax, %esi
diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S
index 2c4b171..f5d1aaa 100644
--- a/arch/x86/boot/compressed/head_64.S
+++ b/arch/x86/boot/compressed/head_64.S
@@ -201,12 +201,12 @@
 	 */
 #ifdef CONFIG_EFI_STUB
 	/*
-	 * The entry point for the PE/COFF executable is 0x210, so only
-	 * legacy boot loaders will execute this jmp.
+	 * The entry point for the PE/COFF executable is efi_pe_entry, so
+	 * only legacy boot loaders will execute this jmp.
 	 */
 	jmp	preferred_addr
 
-	.org 0x210
+ENTRY(efi_pe_entry)
 	mov	%rcx, %rdi
 	mov	%rdx, %rsi
 	pushq	%rdi
@@ -218,7 +218,7 @@
 	popq	%rsi
 	popq	%rdi
 
-	.org 0x230,0x90
+ENTRY(efi_stub_entry)
 	call	efi_main
 	movq	%rax,%rsi
 	cmpq	$0,%rax
diff --git a/arch/x86/boot/header.S b/arch/x86/boot/header.S
index 8c132a6..944ce59 100644
--- a/arch/x86/boot/header.S
+++ b/arch/x86/boot/header.S
@@ -21,6 +21,7 @@
 #include <asm/e820.h>
 #include <asm/page_types.h>
 #include <asm/setup.h>
+#include <asm/bootparam.h>
 #include "boot.h"
 #include "voffset.h"
 #include "zoffset.h"
@@ -255,6 +256,9 @@
 	# header, from the old boot sector.
 
 	.section ".header", "a"
+	.globl	sentinel
+sentinel:	.byte 0xff, 0xff        /* Used to detect broken loaders */
+
 	.globl	hdr
 hdr:
 setup_sects:	.byte 0			/* Filled in by build.c */
@@ -279,7 +283,7 @@
 	# Part 2 of the header, from the old setup.S
 
 		.ascii	"HdrS"		# header signature
-		.word	0x020b		# header version number (>= 0x0105)
+		.word	0x020c		# header version number (>= 0x0105)
 					# or else old loadlin-1.5 will fail)
 		.globl realmode_swtch
 realmode_swtch:	.word	0, 0		# default_switch, SETUPSEG
@@ -297,13 +301,7 @@
 
 # flags, unused bits must be zero (RFU) bit within loadflags
 loadflags:
-LOADED_HIGH	= 1			# If set, the kernel is loaded high
-CAN_USE_HEAP	= 0x80			# If set, the loader also has set
-					# heap_end_ptr to tell how much
-					# space behind setup.S can be used for
-					# heap purposes.
-					# Only the loader knows what is free
-		.byte	LOADED_HIGH
+		.byte	LOADED_HIGH	# The kernel is to be loaded high
 
 setup_move_size: .word  0x8000		# size to move, when setup is not
 					# loaded at 0x90000. We will move setup
@@ -369,7 +367,23 @@
 relocatable_kernel:    .byte 0
 #endif
 min_alignment:		.byte MIN_KERNEL_ALIGN_LG2	# minimum alignment
-pad3:			.word 0
+
+xloadflags:
+#ifdef CONFIG_X86_64
+# define XLF0 XLF_KERNEL_64			/* 64-bit kernel */
+#else
+# define XLF0 0
+#endif
+#ifdef CONFIG_EFI_STUB
+# ifdef CONFIG_X86_64
+#  define XLF23 XLF_EFI_HANDOVER_64		/* 64-bit EFI handover ok */
+# else
+#  define XLF23 XLF_EFI_HANDOVER_32		/* 32-bit EFI handover ok */
+# endif
+#else
+# define XLF23 0
+#endif
+			.word XLF0 | XLF23
 
 cmdline_size:   .long   COMMAND_LINE_SIZE-1     #length of the command line,
                                                 #added with boot protocol
@@ -397,8 +411,13 @@
 #define INIT_SIZE VO_INIT_SIZE
 #endif
 init_size:		.long INIT_SIZE		# kernel initialization size
-handover_offset:	.long 0x30		# offset to the handover
+handover_offset:
+#ifdef CONFIG_EFI_STUB
+  			.long 0x30		# offset to the handover
 						# protocol entry point
+#else
+			.long 0
+#endif
 
 # End of setup header #####################################################
 
diff --git a/arch/x86/boot/setup.ld b/arch/x86/boot/setup.ld
index 03c0683..96a6c75 100644
--- a/arch/x86/boot/setup.ld
+++ b/arch/x86/boot/setup.ld
@@ -13,7 +13,7 @@
 	.bstext		: { *(.bstext) }
 	.bsdata		: { *(.bsdata) }
 
-	. = 497;
+	. = 495;
 	.header		: { *(.header) }
 	.entrytext	: { *(.entrytext) }
 	.inittext	: { *(.inittext) }
diff --git a/arch/x86/boot/tools/build.c b/arch/x86/boot/tools/build.c
index 4b8e165..94c5446 100644
--- a/arch/x86/boot/tools/build.c
+++ b/arch/x86/boot/tools/build.c
@@ -52,6 +52,10 @@
 
 #define PECOFF_RELOC_RESERVE 0x20
 
+unsigned long efi_stub_entry;
+unsigned long efi_pe_entry;
+unsigned long startup_64;
+
 /*----------------------------------------------------------------------*/
 
 static const u32 crctab32[] = {
@@ -132,7 +136,7 @@
 
 static void usage(void)
 {
-	die("Usage: build setup system [> image]");
+	die("Usage: build setup system [zoffset.h] [> image]");
 }
 
 #ifdef CONFIG_EFI_STUB
@@ -206,30 +210,54 @@
 	 */
 	put_unaligned_le32(file_sz - 512, &buf[pe_header + 0x1c]);
 
-#ifdef CONFIG_X86_32
 	/*
-	 * Address of entry point.
-	 *
-	 * The EFI stub entry point is +16 bytes from the start of
-	 * the .text section.
+	 * Address of entry point for PE/COFF executable
 	 */
-	put_unaligned_le32(text_start + 16, &buf[pe_header + 0x28]);
-#else
-	/*
-	 * Address of entry point. startup_32 is at the beginning and
-	 * the 64-bit entry point (startup_64) is always 512 bytes
-	 * after. The EFI stub entry point is 16 bytes after that, as
-	 * the first instruction allows legacy loaders to jump over
-	 * the EFI stub initialisation
-	 */
-	put_unaligned_le32(text_start + 528, &buf[pe_header + 0x28]);
-#endif /* CONFIG_X86_32 */
+	put_unaligned_le32(text_start + efi_pe_entry, &buf[pe_header + 0x28]);
 
 	update_pecoff_section_header(".text", text_start, text_sz);
 }
 
 #endif /* CONFIG_EFI_STUB */
 
+
+/*
+ * Parse zoffset.h and find the entry points. We could just #include zoffset.h
+ * but that would mean tools/build would have to be rebuilt every time. It's
+ * not as if parsing it is hard...
+ */
+#define PARSE_ZOFS(p, sym) do { \
+	if (!strncmp(p, "#define ZO_" #sym " ", 11+sizeof(#sym)))	\
+		sym = strtoul(p + 11 + sizeof(#sym), NULL, 16);		\
+} while (0)
+
+static void parse_zoffset(char *fname)
+{
+	FILE *file;
+	char *p;
+	int c;
+
+	file = fopen(fname, "r");
+	if (!file)
+		die("Unable to open `%s': %m", fname);
+	c = fread(buf, 1, sizeof(buf) - 1, file);
+	if (ferror(file))
+		die("read-error on `zoffset.h'");
+	buf[c] = 0;
+
+	p = (char *)buf;
+
+	while (p && *p) {
+		PARSE_ZOFS(p, efi_stub_entry);
+		PARSE_ZOFS(p, efi_pe_entry);
+		PARSE_ZOFS(p, startup_64);
+
+		p = strchr(p, '\n');
+		while (p && (*p == '\r' || *p == '\n'))
+			p++;
+	}
+}
+
 int main(int argc, char ** argv)
 {
 	unsigned int i, sz, setup_sectors;
@@ -241,7 +269,19 @@
 	void *kernel;
 	u32 crc = 0xffffffffUL;
 
-	if (argc != 3)
+	/* Defaults for old kernel */
+#ifdef CONFIG_X86_32
+	efi_pe_entry = 0x10;
+	efi_stub_entry = 0x30;
+#else
+	efi_pe_entry = 0x210;
+	efi_stub_entry = 0x230;
+	startup_64 = 0x200;
+#endif
+
+	if (argc == 4)
+		parse_zoffset(argv[3]);
+	else if (argc != 3)
 		usage();
 
 	/* Copy the setup code */
@@ -299,6 +339,11 @@
 
 #ifdef CONFIG_EFI_STUB
 	update_pecoff_text(setup_sectors * 512, sz + i + ((sys_size * 16) - sz));
+
+#ifdef CONFIG_X86_64 /* Yes, this is really how we defined it :( */
+	efi_stub_entry -= 0x200;
+#endif
+	put_unaligned_le32(efi_stub_entry, &buf[0x264]);
 #endif
 
 	crc = partial_crc32(buf, i, crc);
diff --git a/arch/x86/include/asm/efi.h b/arch/x86/include/asm/efi.h
index 6e8fdf5..28677c5 100644
--- a/arch/x86/include/asm/efi.h
+++ b/arch/x86/include/asm/efi.h
@@ -94,6 +94,7 @@
 #endif /* CONFIG_X86_32 */
 
 extern int add_efi_memmap;
+extern unsigned long x86_efi_facility;
 extern void efi_set_executable(efi_memory_desc_t *md, bool executable);
 extern int efi_memblock_x86_reserve_range(void);
 extern void efi_call_phys_prelog(void);
diff --git a/arch/x86/include/asm/uv/uv.h b/arch/x86/include/asm/uv/uv.h
index b47c2a8..062921e 100644
--- a/arch/x86/include/asm/uv/uv.h
+++ b/arch/x86/include/asm/uv/uv.h
@@ -16,7 +16,7 @@
 extern const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
 						 struct mm_struct *mm,
 						 unsigned long start,
-						 unsigned end,
+						 unsigned long end,
 						 unsigned int cpu);
 
 #else	/* X86_UV */
diff --git a/arch/x86/include/uapi/asm/bootparam.h b/arch/x86/include/uapi/asm/bootparam.h
index 92862cd..c15ddaf 100644
--- a/arch/x86/include/uapi/asm/bootparam.h
+++ b/arch/x86/include/uapi/asm/bootparam.h
@@ -1,6 +1,31 @@
 #ifndef _ASM_X86_BOOTPARAM_H
 #define _ASM_X86_BOOTPARAM_H
 
+/* setup_data types */
+#define SETUP_NONE			0
+#define SETUP_E820_EXT			1
+#define SETUP_DTB			2
+#define SETUP_PCI			3
+
+/* ram_size flags */
+#define RAMDISK_IMAGE_START_MASK	0x07FF
+#define RAMDISK_PROMPT_FLAG		0x8000
+#define RAMDISK_LOAD_FLAG		0x4000
+
+/* loadflags */
+#define LOADED_HIGH	(1<<0)
+#define QUIET_FLAG	(1<<5)
+#define KEEP_SEGMENTS	(1<<6)
+#define CAN_USE_HEAP	(1<<7)
+
+/* xloadflags */
+#define XLF_KERNEL_64			(1<<0)
+#define XLF_CAN_BE_LOADED_ABOVE_4G	(1<<1)
+#define XLF_EFI_HANDOVER_32		(1<<2)
+#define XLF_EFI_HANDOVER_64		(1<<3)
+
+#ifndef __ASSEMBLY__
+
 #include <linux/types.h>
 #include <linux/screen_info.h>
 #include <linux/apm_bios.h>
@@ -9,12 +34,6 @@
 #include <asm/ist.h>
 #include <video/edid.h>
 
-/* setup data types */
-#define SETUP_NONE			0
-#define SETUP_E820_EXT			1
-#define SETUP_DTB			2
-#define SETUP_PCI			3
-
 /* extensible setup data list node */
 struct setup_data {
 	__u64 next;
@@ -28,9 +47,6 @@
 	__u16	root_flags;
 	__u32	syssize;
 	__u16	ram_size;
-#define RAMDISK_IMAGE_START_MASK	0x07FF
-#define RAMDISK_PROMPT_FLAG		0x8000
-#define RAMDISK_LOAD_FLAG		0x4000
 	__u16	vid_mode;
 	__u16	root_dev;
 	__u16	boot_flag;
@@ -42,10 +58,6 @@
 	__u16	kernel_version;
 	__u8	type_of_loader;
 	__u8	loadflags;
-#define LOADED_HIGH	(1<<0)
-#define QUIET_FLAG	(1<<5)
-#define KEEP_SEGMENTS	(1<<6)
-#define CAN_USE_HEAP	(1<<7)
 	__u16	setup_move_size;
 	__u32	code32_start;
 	__u32	ramdisk_image;
@@ -58,7 +70,8 @@
 	__u32	initrd_addr_max;
 	__u32	kernel_alignment;
 	__u8	relocatable_kernel;
-	__u8	_pad2[3];
+	__u8	min_alignment;
+	__u16	xloadflags;
 	__u32	cmdline_size;
 	__u32	hardware_subarch;
 	__u64	hardware_subarch_data;
@@ -106,7 +119,10 @@
 	__u8  hd1_info[16];	/* obsolete! */		/* 0x090 */
 	struct sys_desc_table sys_desc_table;		/* 0x0a0 */
 	struct olpc_ofw_header olpc_ofw_header;		/* 0x0b0 */
-	__u8  _pad4[128];				/* 0x0c0 */
+	__u32 ext_ramdisk_image;			/* 0x0c0 */
+	__u32 ext_ramdisk_size;				/* 0x0c4 */
+	__u32 ext_cmd_line_ptr;				/* 0x0c8 */
+	__u8  _pad4[116];				/* 0x0cc */
 	struct edid_info edid_info;			/* 0x140 */
 	struct efi_info efi_info;			/* 0x1c0 */
 	__u32 alt_mem_k;				/* 0x1e0 */
@@ -115,7 +131,20 @@
 	__u8  eddbuf_entries;				/* 0x1e9 */
 	__u8  edd_mbr_sig_buf_entries;			/* 0x1ea */
 	__u8  kbd_status;				/* 0x1eb */
-	__u8  _pad6[5];					/* 0x1ec */
+	__u8  _pad5[3];					/* 0x1ec */
+	/*
+	 * The sentinel is set to a nonzero value (0xff) in header.S.
+	 *
+	 * A bootloader is supposed to only take setup_header and put
+	 * it into a clean boot_params buffer. If it turns out that
+	 * it is clumsy or too generous with the buffer, it most
+	 * probably will pick up the sentinel variable too. The fact
+	 * that this variable then is still 0xff will let kernel
+	 * know that some variables in boot_params are invalid and
+	 * kernel should zero out certain portions of boot_params.
+	 */
+	__u8  sentinel;					/* 0x1ef */
+	__u8  _pad6[1];					/* 0x1f0 */
 	struct setup_header hdr;    /* setup header */	/* 0x1f1 */
 	__u8  _pad7[0x290-0x1f1-sizeof(struct setup_header)];
 	__u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX];	/* 0x290 */
@@ -134,6 +163,6 @@
 	X86_NR_SUBARCHS,
 };
 
-
+#endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_X86_BOOTPARAM_H */
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 4428fd1..6774c17 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -340,9 +340,6 @@
 		/* BTS is currently only allowed for user-mode. */
 		if (!attr->exclude_kernel)
 			return -EOPNOTSUPP;
-
-		if (!attr->exclude_guest)
-			return -EOPNOTSUPP;
 	}
 
 	hwc->config |= config;
@@ -385,9 +382,6 @@
 	if (event->attr.precise_ip) {
 		int precise = 0;
 
-		if (!event->attr.exclude_guest)
-			return -EOPNOTSUPP;
-
 		/* Support for constant skid */
 		if (x86_pmu.pebs_active && !x86_pmu.pebs_broken) {
 			precise++;
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S
index ff84d54..6ed91d9 100644
--- a/arch/x86/kernel/entry_32.S
+++ b/arch/x86/kernel/entry_32.S
@@ -1065,7 +1065,6 @@
 	lea 16(%esp),%esp
 	CFI_ADJUST_CFA_OFFSET -16
 	jz 5f
-	addl $16,%esp
 	jmp iret_exc
 5:	pushl_cfi $-1 /* orig_ax = -1 => not a system call */
 	SAVE_ALL
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 07a7a04..cb3c591 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -1781,6 +1781,7 @@
 	 * Leave room for the "copied" frame
 	 */
 	subq $(5*8), %rsp
+	CFI_ADJUST_CFA_OFFSET 5*8
 
 	/* Copy the stack frame to the Saved frame */
 	.rept 5
@@ -1863,10 +1864,8 @@
 nmi_swapgs:
 	SWAPGS_UNSAFE_STACK
 nmi_restore:
-	RESTORE_ALL 8
-
-	/* Pop the extra iret frame */
-	addq $(5*8), %rsp
+	/* Pop the extra iret frame at once */
+	RESTORE_ALL 6*8
 
 	/* Clear the NMI executing stack variable */
 	movq $0, 5*8(%rsp)
diff --git a/arch/x86/kernel/head_32.S b/arch/x86/kernel/head_32.S
index 8e7f655..c8932c7 100644
--- a/arch/x86/kernel/head_32.S
+++ b/arch/x86/kernel/head_32.S
@@ -300,6 +300,12 @@
 	leal -__PAGE_OFFSET(%ecx),%esp
 
 default_entry:
+#define CR0_STATE	(X86_CR0_PE | X86_CR0_MP | X86_CR0_ET | \
+			 X86_CR0_NE | X86_CR0_WP | X86_CR0_AM | \
+			 X86_CR0_PG)
+	movl $(CR0_STATE & ~X86_CR0_PG),%eax
+	movl %eax,%cr0
+
 /*
  *	New page tables may be in 4Mbyte page mode and may
  *	be using the global pages. 
@@ -364,8 +370,7 @@
  */
 	movl $pa(initial_page_table), %eax
 	movl %eax,%cr3		/* set the page table pointer.. */
-	movl %cr0,%eax
-	orl  $X86_CR0_PG,%eax
+	movl $CR0_STATE,%eax
 	movl %eax,%cr0		/* ..and set paging (PG) bit */
 	ljmp $__BOOT_CS,$1f	/* Clear prefetch and normalize %eip */
 1:
diff --git a/arch/x86/kernel/kvm.c b/arch/x86/kernel/kvm.c
index 08b973f..9c2bd8b 100644
--- a/arch/x86/kernel/kvm.c
+++ b/arch/x86/kernel/kvm.c
@@ -43,6 +43,7 @@
 #include <asm/apicdef.h>
 #include <asm/hypervisor.h>
 #include <asm/kvm_guest.h>
+#include <asm/context_tracking.h>
 
 static int kvmapf = 1;
 
@@ -121,6 +122,8 @@
 	struct kvm_task_sleep_node n, *e;
 	DEFINE_WAIT(wait);
 
+	rcu_irq_enter();
+
 	spin_lock(&b->lock);
 	e = _find_apf_task(b, token);
 	if (e) {
@@ -128,6 +131,8 @@
 		hlist_del(&e->link);
 		kfree(e);
 		spin_unlock(&b->lock);
+
+		rcu_irq_exit();
 		return;
 	}
 
@@ -152,13 +157,16 @@
 			/*
 			 * We cannot reschedule. So halt.
 			 */
+			rcu_irq_exit();
 			native_safe_halt();
+			rcu_irq_enter();
 			local_irq_disable();
 		}
 	}
 	if (!n.halted)
 		finish_wait(&n.wq, &wait);
 
+	rcu_irq_exit();
 	return;
 }
 EXPORT_SYMBOL_GPL(kvm_async_pf_task_wait);
@@ -252,10 +260,10 @@
 		break;
 	case KVM_PV_REASON_PAGE_NOT_PRESENT:
 		/* page is swapped out by the host. */
-		rcu_irq_enter();
+		exception_enter(regs);
 		exit_idle();
 		kvm_async_pf_task_wait((u32)read_cr2());
-		rcu_irq_exit();
+		exception_exit(regs);
 		break;
 	case KVM_PV_REASON_PAGE_READY:
 		rcu_irq_enter();
diff --git a/arch/x86/kernel/msr.c b/arch/x86/kernel/msr.c
index a7c5661..4929502 100644
--- a/arch/x86/kernel/msr.c
+++ b/arch/x86/kernel/msr.c
@@ -174,6 +174,9 @@
 	unsigned int cpu;
 	struct cpuinfo_x86 *c;
 
+	if (!capable(CAP_SYS_RAWIO))
+		return -EPERM;
+
 	cpu = iminor(file->f_path.dentry->d_inode);
 	if (cpu >= nr_cpu_ids || !cpu_online(cpu))
 		return -ENXIO;	/* No such CPU */
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 0f5dec5..872079a 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -56,7 +56,7 @@
 EXPORT_SYMBOL(x86_dma_fallback_dev);
 
 /* Number of entries preallocated for DMA-API debugging */
-#define PREALLOC_DMA_DEBUG_ENTRIES       32768
+#define PREALLOC_DMA_DEBUG_ENTRIES       65536
 
 int dma_set_mask(struct device *dev, u64 mask)
 {
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 4e8ba39..76fa1e9 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -584,7 +584,7 @@
 			break;
 
 		case BOOT_EFI:
-			if (efi_enabled)
+			if (efi_enabled(EFI_RUNTIME_SERVICES))
 				efi.reset_system(reboot_mode ?
 						 EFI_RESET_WARM :
 						 EFI_RESET_COLD,
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 23ddd55..8b24289 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -610,6 +610,83 @@
 
 static unsigned reserve_low = CONFIG_X86_RESERVE_LOW << 10;
 
+static bool __init snb_gfx_workaround_needed(void)
+{
+#ifdef CONFIG_PCI
+	int i;
+	u16 vendor, devid;
+	static const __initconst u16 snb_ids[] = {
+		0x0102,
+		0x0112,
+		0x0122,
+		0x0106,
+		0x0116,
+		0x0126,
+		0x010a,
+	};
+
+	/* Assume no if something weird is going on with PCI */
+	if (!early_pci_allowed())
+		return false;
+
+	vendor = read_pci_config_16(0, 2, 0, PCI_VENDOR_ID);
+	if (vendor != 0x8086)
+		return false;
+
+	devid = read_pci_config_16(0, 2, 0, PCI_DEVICE_ID);
+	for (i = 0; i < ARRAY_SIZE(snb_ids); i++)
+		if (devid == snb_ids[i])
+			return true;
+#endif
+
+	return false;
+}
+
+/*
+ * Sandy Bridge graphics has trouble with certain ranges, exclude
+ * them from allocation.
+ */
+static void __init trim_snb_memory(void)
+{
+	static const __initconst unsigned long bad_pages[] = {
+		0x20050000,
+		0x20110000,
+		0x20130000,
+		0x20138000,
+		0x40004000,
+	};
+	int i;
+
+	if (!snb_gfx_workaround_needed())
+		return;
+
+	printk(KERN_DEBUG "reserving inaccessible SNB gfx pages\n");
+
+	/*
+	 * Reserve all memory below the 1 MB mark that has not
+	 * already been reserved.
+	 */
+	memblock_reserve(0, 1<<20);
+	
+	for (i = 0; i < ARRAY_SIZE(bad_pages); i++) {
+		if (memblock_reserve(bad_pages[i], PAGE_SIZE))
+			printk(KERN_WARNING "failed to reserve 0x%08lx\n",
+			       bad_pages[i]);
+	}
+}
+
+/*
+ * Here we put platform-specific memory range workarounds, i.e.
+ * memory known to be corrupt or otherwise in need to be reserved on
+ * specific platforms.
+ *
+ * If this gets used more widely it could use a real dispatch mechanism.
+ */
+static void __init trim_platform_memory_ranges(void)
+{
+	trim_snb_memory();
+}
+
 static void __init trim_bios_range(void)
 {
 	/*
@@ -630,6 +707,7 @@
 	 * take them out.
 	 */
 	e820_remove_range(BIOS_BEGIN, BIOS_END - BIOS_BEGIN, E820_RAM, 1);
+
 	sanitize_e820_map(e820.map, ARRAY_SIZE(e820.map), &e820.nr_map);
 }
 
@@ -729,15 +807,15 @@
 #ifdef CONFIG_EFI
 	if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
 		     "EL32", 4)) {
-		efi_enabled = 1;
-		efi_64bit = false;
+		set_bit(EFI_BOOT, &x86_efi_facility);
 	} else if (!strncmp((char *)&boot_params.efi_info.efi_loader_signature,
 		     "EL64", 4)) {
-		efi_enabled = 1;
-		efi_64bit = true;
+		set_bit(EFI_BOOT, &x86_efi_facility);
+		set_bit(EFI_64BIT, &x86_efi_facility);
 	}
-	if (efi_enabled && efi_memblock_x86_reserve_range())
-		efi_enabled = 0;
+
+	if (efi_enabled(EFI_BOOT))
+		efi_memblock_x86_reserve_range();
 #endif
 
 	x86_init.oem.arch_setup();
@@ -810,7 +888,7 @@
 
 	finish_e820_parsing();
 
-	if (efi_enabled)
+	if (efi_enabled(EFI_BOOT))
 		efi_init();
 
 	dmi_scan_machine();
@@ -893,7 +971,7 @@
 	 * The EFI specification says that boot service code won't be called
 	 * after ExitBootServices(). This is, in fact, a lie.
 	 */
-	if (efi_enabled)
+	if (efi_enabled(EFI_MEMMAP))
 		efi_reserve_boot_services();
 
 	/* preallocate 4k for mptable mpc */
@@ -908,6 +986,8 @@
 
 	setup_real_mode();
 
+	trim_platform_memory_ranges();
+
 	init_gbpages();
 
 	/* max_pfn_mapped is updated here */
@@ -1034,7 +1114,7 @@
 
 #ifdef CONFIG_VT
 #if defined(CONFIG_VGA_CONSOLE)
-	if (!efi_enabled || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
+	if (!efi_enabled(EFI_BOOT) || (efi_mem_type(0xa0000) != EFI_CONVENTIONAL_MEMORY))
 		conswitchp = &vga_con;
 #elif defined(CONFIG_DUMMY_CONSOLE)
 	conswitchp = &dummy_con;
@@ -1051,14 +1131,14 @@
 	register_refined_jiffies(CLOCK_TICK_RATE);
 
 #ifdef CONFIG_EFI
-	/* Once setup is done above, disable efi_enabled on mismatched
-	 * firmware/kernel archtectures since there is no support for
-	 * runtime services.
+	/* Once setup is done above, unmap the EFI memory map on
+	 * mismatched firmware/kernel archtectures since there is no
+	 * support for runtime services.
 	 */
-	if (efi_enabled && IS_ENABLED(CONFIG_X86_64) != efi_64bit) {
+	if (efi_enabled(EFI_BOOT) &&
+	    IS_ENABLED(CONFIG_X86_64) != efi_enabled(EFI_64BIT)) {
 		pr_info("efi: Setup done, disabling due to 32/64-bit mismatch\n");
 		efi_unmap_memmap();
-		efi_enabled = 0;
 	}
 #endif
 }
diff --git a/arch/x86/kernel/step.c b/arch/x86/kernel/step.c
index cd3b243..9b4d51d 100644
--- a/arch/x86/kernel/step.c
+++ b/arch/x86/kernel/step.c
@@ -165,10 +165,11 @@
 	 * Ensure irq/preemption can't change debugctl in between.
 	 * Note also that both TIF_BLOCKSTEP and debugctl should
 	 * be changed atomically wrt preemption.
-	 * FIXME: this means that set/clear TIF_BLOCKSTEP is simply
-	 * wrong if task != current, SIGKILL can wakeup the stopped
-	 * tracee and set/clear can play with the running task, this
-	 * can confuse the next __switch_to_xtra().
+	 *
+	 * NOTE: this means that set/clear TIF_BLOCKSTEP is only safe if
+	 * task is current or it can't be running, otherwise we can race
+	 * with __switch_to_xtra(). We rely on ptrace_freeze_traced() but
+	 * PTRACE_KILL is not safe.
 	 */
 	local_irq_disable();
 	debugctl = get_debugctlmsr();
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 76f5446..c243b81 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -120,7 +120,7 @@
 };
 
 static struct kvm_shared_msrs_global __read_mostly shared_msrs_global;
-static DEFINE_PER_CPU(struct kvm_shared_msrs, shared_msrs);
+static struct kvm_shared_msrs __percpu *shared_msrs;
 
 struct kvm_stats_debugfs_item debugfs_entries[] = {
 	{ "pf_fixed", VCPU_STAT(pf_fixed) },
@@ -191,10 +191,10 @@
 
 static void shared_msr_update(unsigned slot, u32 msr)
 {
-	struct kvm_shared_msrs *smsr;
 	u64 value;
+	unsigned int cpu = smp_processor_id();
+	struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
 
-	smsr = &__get_cpu_var(shared_msrs);
 	/* only read, and nobody should modify it at this time,
 	 * so don't need lock */
 	if (slot >= shared_msrs_global.nr) {
@@ -226,7 +226,8 @@
 
 void kvm_set_shared_msr(unsigned slot, u64 value, u64 mask)
 {
-	struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs);
+	unsigned int cpu = smp_processor_id();
+	struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
 
 	if (((value ^ smsr->values[slot].curr) & mask) == 0)
 		return;
@@ -242,7 +243,8 @@
 
 static void drop_user_return_notifiers(void *ignore)
 {
-	struct kvm_shared_msrs *smsr = &__get_cpu_var(shared_msrs);
+	unsigned int cpu = smp_processor_id();
+	struct kvm_shared_msrs *smsr = per_cpu_ptr(shared_msrs, cpu);
 
 	if (smsr->registered)
 		kvm_on_user_return(&smsr->urn);
@@ -5233,9 +5235,16 @@
 		goto out;
 	}
 
+	r = -ENOMEM;
+	shared_msrs = alloc_percpu(struct kvm_shared_msrs);
+	if (!shared_msrs) {
+		printk(KERN_ERR "kvm: failed to allocate percpu kvm_shared_msrs\n");
+		goto out;
+	}
+
 	r = kvm_mmu_module_init();
 	if (r)
-		goto out;
+		goto out_free_percpu;
 
 	kvm_set_mmio_spte_mask();
 	kvm_init_msr_list();
@@ -5258,6 +5267,8 @@
 
 	return 0;
 
+out_free_percpu:
+	free_percpu(shared_msrs);
 out:
 	return r;
 }
@@ -5275,6 +5286,7 @@
 #endif
 	kvm_x86_ops = NULL;
 	kvm_mmu_module_exit();
+	free_percpu(shared_msrs);
 }
 
 int kvm_emulate_halt(struct kvm_vcpu *vcpu)
diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c
index ad443914..77cf009 100644
--- a/arch/x86/platform/efi/efi.c
+++ b/arch/x86/platform/efi/efi.c
@@ -51,9 +51,6 @@
 
 #define EFI_DEBUG	1
 
-int efi_enabled;
-EXPORT_SYMBOL(efi_enabled);
-
 struct efi __read_mostly efi = {
 	.mps        = EFI_INVALID_TABLE_ADDR,
 	.acpi       = EFI_INVALID_TABLE_ADDR,
@@ -69,19 +66,28 @@
 
 struct efi_memory_map memmap;
 
-bool efi_64bit;
-
 static struct efi efi_phys __initdata;
 static efi_system_table_t efi_systab __initdata;
 
 static inline bool efi_is_native(void)
 {
-	return IS_ENABLED(CONFIG_X86_64) == efi_64bit;
+	return IS_ENABLED(CONFIG_X86_64) == efi_enabled(EFI_64BIT);
 }
 
+unsigned long x86_efi_facility;
+
+/*
+ * Returns 1 if 'facility' is enabled, 0 otherwise.
+ */
+int efi_enabled(int facility)
+{
+	return test_bit(facility, &x86_efi_facility) != 0;
+}
+EXPORT_SYMBOL(efi_enabled);
+
 static int __init setup_noefi(char *arg)
 {
-	efi_enabled = 0;
+	clear_bit(EFI_BOOT, &x86_efi_facility);
 	return 0;
 }
 early_param("noefi", setup_noefi);
@@ -426,6 +432,7 @@
 
 void __init efi_unmap_memmap(void)
 {
+	clear_bit(EFI_MEMMAP, &x86_efi_facility);
 	if (memmap.map) {
 		early_iounmap(memmap.map, memmap.nr_map * memmap.desc_size);
 		memmap.map = NULL;
@@ -460,7 +467,7 @@
 
 static int __init efi_systab_init(void *phys)
 {
-	if (efi_64bit) {
+	if (efi_enabled(EFI_64BIT)) {
 		efi_system_table_64_t *systab64;
 		u64 tmp = 0;
 
@@ -552,7 +559,7 @@
 	void *config_tables, *tablep;
 	int i, sz;
 
-	if (efi_64bit)
+	if (efi_enabled(EFI_64BIT))
 		sz = sizeof(efi_config_table_64_t);
 	else
 		sz = sizeof(efi_config_table_32_t);
@@ -572,7 +579,7 @@
 		efi_guid_t guid;
 		unsigned long table;
 
-		if (efi_64bit) {
+		if (efi_enabled(EFI_64BIT)) {
 			u64 table64;
 			guid = ((efi_config_table_64_t *)tablep)->guid;
 			table64 = ((efi_config_table_64_t *)tablep)->table;
@@ -684,7 +691,6 @@
 	if (boot_params.efi_info.efi_systab_hi ||
 	    boot_params.efi_info.efi_memmap_hi) {
 		pr_info("Table located above 4GB, disabling EFI.\n");
-		efi_enabled = 0;
 		return;
 	}
 	efi_phys.systab = (efi_system_table_t *)boot_params.efi_info.efi_systab;
@@ -694,10 +700,10 @@
 			  ((__u64)boot_params.efi_info.efi_systab_hi<<32));
 #endif
 
-	if (efi_systab_init(efi_phys.systab)) {
-		efi_enabled = 0;
+	if (efi_systab_init(efi_phys.systab))
 		return;
-	}
+
+	set_bit(EFI_SYSTEM_TABLES, &x86_efi_facility);
 
 	/*
 	 * Show what we know for posterity
@@ -715,10 +721,10 @@
 		efi.systab->hdr.revision >> 16,
 		efi.systab->hdr.revision & 0xffff, vendor);
 
-	if (efi_config_init(efi.systab->tables, efi.systab->nr_tables)) {
-		efi_enabled = 0;
+	if (efi_config_init(efi.systab->tables, efi.systab->nr_tables))
 		return;
-	}
+
+	set_bit(EFI_CONFIG_TABLES, &x86_efi_facility);
 
 	/*
 	 * Note: We currently don't support runtime services on an EFI
@@ -727,15 +733,17 @@
 
 	if (!efi_is_native())
 		pr_info("No EFI runtime due to 32/64-bit mismatch with kernel\n");
-	else if (efi_runtime_init()) {
-		efi_enabled = 0;
-		return;
+	else {
+		if (efi_runtime_init())
+			return;
+		set_bit(EFI_RUNTIME_SERVICES, &x86_efi_facility);
 	}
 
-	if (efi_memmap_init()) {
-		efi_enabled = 0;
+	if (efi_memmap_init())
 		return;
-	}
+
+	set_bit(EFI_MEMMAP, &x86_efi_facility);
+
 #ifdef CONFIG_X86_32
 	if (efi_is_native()) {
 		x86_platform.get_wallclock = efi_get_time;
@@ -941,7 +949,7 @@
 	 *
 	 * Call EFI services through wrapper functions.
 	 */
-	efi.runtime_version = efi_systab.fw_revision;
+	efi.runtime_version = efi_systab.hdr.revision;
 	efi.get_time = virt_efi_get_time;
 	efi.set_time = virt_efi_set_time;
 	efi.get_wakeup_time = virt_efi_get_wakeup_time;
@@ -969,6 +977,9 @@
 	efi_memory_desc_t *md;
 	void *p;
 
+	if (!efi_enabled(EFI_MEMMAP))
+		return 0;
+
 	for (p = memmap.map; p < memmap.map_end; p += memmap.desc_size) {
 		md = p;
 		if ((md->phys_addr <= phys_addr) &&
diff --git a/arch/x86/platform/efi/efi_64.c b/arch/x86/platform/efi/efi_64.c
index 95fd505..2b20038 100644
--- a/arch/x86/platform/efi/efi_64.c
+++ b/arch/x86/platform/efi/efi_64.c
@@ -38,7 +38,7 @@
 #include <asm/cacheflush.h>
 #include <asm/fixmap.h>
 
-static pgd_t save_pgd __initdata;
+static pgd_t *save_pgd __initdata;
 static unsigned long efi_flags __initdata;
 
 static void __init early_code_mapping_set_exec(int executable)
@@ -61,12 +61,20 @@
 void __init efi_call_phys_prelog(void)
 {
 	unsigned long vaddress;
+	int pgd;
+	int n_pgds;
 
 	early_code_mapping_set_exec(1);
 	local_irq_save(efi_flags);
-	vaddress = (unsigned long)__va(0x0UL);
-	save_pgd = *pgd_offset_k(0x0UL);
-	set_pgd(pgd_offset_k(0x0UL), *pgd_offset_k(vaddress));
+
+	n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT), PGDIR_SIZE);
+	save_pgd = kmalloc(n_pgds * sizeof(pgd_t), GFP_KERNEL);
+
+	for (pgd = 0; pgd < n_pgds; pgd++) {
+		save_pgd[pgd] = *pgd_offset_k(pgd * PGDIR_SIZE);
+		vaddress = (unsigned long)__va(pgd * PGDIR_SIZE);
+		set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), *pgd_offset_k(vaddress));
+	}
 	__flush_tlb_all();
 }
 
@@ -75,7 +83,11 @@
 	/*
 	 * After the lock is released, the original page table is restored.
 	 */
-	set_pgd(pgd_offset_k(0x0UL), save_pgd);
+	int pgd;
+	int n_pgds = DIV_ROUND_UP((max_pfn << PAGE_SHIFT) , PGDIR_SIZE);
+	for (pgd = 0; pgd < n_pgds; pgd++)
+		set_pgd(pgd_offset_k(pgd * PGDIR_SIZE), save_pgd[pgd]);
+	kfree(save_pgd);
 	__flush_tlb_all();
 	local_irq_restore(efi_flags);
 	early_code_mapping_set_exec(0);
diff --git a/arch/x86/platform/uv/tlb_uv.c b/arch/x86/platform/uv/tlb_uv.c
index b8b3a37..dbbdca5 100644
--- a/arch/x86/platform/uv/tlb_uv.c
+++ b/arch/x86/platform/uv/tlb_uv.c
@@ -1034,7 +1034,8 @@
  * globally purge translation cache of a virtual address or all TLB's
  * @cpumask: mask of all cpu's in which the address is to be removed
  * @mm: mm_struct containing virtual address range
- * @va: virtual address to be removed (or TLB_FLUSH_ALL for all TLB's on cpu)
+ * @start: start virtual address to be removed from TLB
+ * @end: end virtual address to be remove from TLB
  * @cpu: the current cpu
  *
  * This is the entry point for initiating any UV global TLB shootdown.
@@ -1056,7 +1057,7 @@
  */
 const struct cpumask *uv_flush_tlb_others(const struct cpumask *cpumask,
 				struct mm_struct *mm, unsigned long start,
-				unsigned end, unsigned int cpu)
+				unsigned long end, unsigned int cpu)
 {
 	int locals = 0;
 	int remotes = 0;
@@ -1113,7 +1114,10 @@
 
 	record_send_statistics(stat, locals, hubs, remotes, bau_desc);
 
-	bau_desc->payload.address = start;
+	if (!end || (end - start) <= PAGE_SIZE)
+		bau_desc->payload.address = start;
+	else
+		bau_desc->payload.address = TLB_FLUSH_ALL;
 	bau_desc->payload.sending_cpu = cpu;
 	/*
 	 * uv_flush_send_and_wait returns 0 if all cpu's were messaged,
diff --git a/arch/x86/tools/relocs.c b/arch/x86/tools/relocs.c
index 5a1847d..79d67bd 100644
--- a/arch/x86/tools/relocs.c
+++ b/arch/x86/tools/relocs.c
@@ -814,12 +814,14 @@
 	read_relocs(fp);
 	if (show_absolute_syms) {
 		print_absolute_symbols();
-		return 0;
+		goto out;
 	}
 	if (show_absolute_relocs) {
 		print_absolute_relocs();
-		return 0;
+		goto out;
 	}
 	emit_relocs(as_text, use_real_mode);
+out:
+	fclose(fp);
 	return 0;
 }
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 4f7d259..34bc4ce 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -432,13 +432,6 @@
 	play_dead_common();
 	HYPERVISOR_vcpu_op(VCPUOP_down, smp_processor_id(), NULL);
 	cpu_bringup();
-	/*
-	 * Balance out the preempt calls - as we are running in cpu_idle
-	 * loop which has been called at bootup from cpu_bringup_and_idle.
-	 * The cpucpu_bringup_and_idle called cpu_bringup which made a
-	 * preempt_disable() So this preempt_enable will balance it out.
-	 */
-	preempt_enable();
 }
 
 #else /* !CONFIG_HOTPLUG_CPU */
diff --git a/drivers/acpi/apei/apei-base.c b/drivers/acpi/apei/apei-base.c
index 00a7836..46f80e2 100644
--- a/drivers/acpi/apei/apei-base.c
+++ b/drivers/acpi/apei/apei-base.c
@@ -590,6 +590,9 @@
 	if (bit_width == 32 && bit_offset == 0 && (*paddr & 0x03) == 0 &&
 	    *access_bit_width < 32)
 		*access_bit_width = 32;
+	else if (bit_width == 64 && bit_offset == 0 && (*paddr & 0x07) == 0 &&
+	    *access_bit_width < 64)
+		*access_bit_width = 64;
 
 	if ((bit_width + bit_offset) > *access_bit_width) {
 		pr_warning(FW_BUG APEI_PFX
diff --git a/drivers/acpi/glue.c b/drivers/acpi/glue.c
index 95af6f6..35da181 100644
--- a/drivers/acpi/glue.c
+++ b/drivers/acpi/glue.c
@@ -297,7 +297,7 @@
 	if (!ret) {
 		struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 
-		acpi_get_name(dev->acpi_handle, ACPI_FULL_PATHNAME, &buffer);
+		acpi_get_name(ACPI_HANDLE(dev), ACPI_FULL_PATHNAME, &buffer);
 		DBG("Device %s -> %s\n", dev_name(dev), (char *)buffer.pointer);
 		kfree(buffer.pointer);
 	} else
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 3ff2678..bd22f86 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -250,7 +250,7 @@
 		return acpi_rsdp;
 #endif
 
-	if (efi_enabled) {
+	if (efi_enabled(EFI_CONFIG_TABLES)) {
 		if (efi.acpi20 != EFI_INVALID_TABLE_ADDR)
 			return efi.acpi20;
 		else if (efi.acpi != EFI_INVALID_TABLE_ADDR)
diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c
index f1a5da4..ed9a1cc 100644
--- a/drivers/acpi/processor_idle.c
+++ b/drivers/acpi/processor_idle.c
@@ -958,6 +958,9 @@
 		return -EINVAL;
 	}
 
+	if (!dev)
+		return -EINVAL;
+
 	dev->cpu = pr->id;
 
 	if (max_cstate == 0)
@@ -1149,6 +1152,7 @@
 		}
 
 		/* Populate Updated C-state information */
+		acpi_processor_get_power_info(pr);
 		acpi_processor_setup_cpuidle_states(pr);
 
 		/* Enable all cpuidle devices */
diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c
index 836bfe0..53e7ac9 100644
--- a/drivers/acpi/processor_perflib.c
+++ b/drivers/acpi/processor_perflib.c
@@ -340,6 +340,13 @@
 	if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
 	    || boot_cpu_data.x86 == 0x11) {
 		rdmsr(MSR_AMD_PSTATE_DEF_BASE + index, lo, hi);
+		/*
+		 * MSR C001_0064+:
+		 * Bit 63: PstateEn. Read-write. If set, the P-state is valid.
+		 */
+		if (!(hi & BIT(31)))
+			return;
+
 		fid = lo & 0x3f;
 		did = (lo >> 6) & 7;
 		if (boot_cpu_data.x86 == 0x10)
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index 7862d17..4979127 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -53,6 +53,7 @@
 
 enum {
 	AHCI_PCI_BAR_STA2X11	= 0,
+	AHCI_PCI_BAR_ENMOTUS	= 2,
 	AHCI_PCI_BAR_STANDARD	= 5,
 };
 
@@ -410,6 +411,9 @@
 	{ PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },	/* ASM1061 */
 	{ PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },	/* ASM1062 */
 
+	/* Enmotus */
+	{ PCI_DEVICE(0x1c44, 0x8000), board_ahci },
+
 	/* Generic, PCI class code for AHCI */
 	{ PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
 	  PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci },
@@ -1098,9 +1102,11 @@
 		dev_info(&pdev->dev,
 			 "PDC42819 can only drive SATA devices with this driver\n");
 
-	/* The Connext uses non-standard BAR */
+	/* Both Connext and Enmotus devices use non-standard BARs */
 	if (pdev->vendor == PCI_VENDOR_ID_STMICRO && pdev->device == 0xCC06)
 		ahci_pci_bar = AHCI_PCI_BAR_STA2X11;
+	else if (pdev->vendor == 0x1c44 && pdev->device == 0x8000)
+		ahci_pci_bar = AHCI_PCI_BAR_ENMOTUS;
 
 	/* acquire resources */
 	rc = pcim_enable_device(pdev);
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 320712a..6cd7805 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -1951,13 +1951,13 @@
 	/* Use the nominal value 10 ms if the read MDAT is zero,
 	 * the nominal value of DETO is 20 ms.
 	 */
-	if (dev->sata_settings[ATA_LOG_DEVSLP_VALID] &
+	if (dev->devslp_timing[ATA_LOG_DEVSLP_VALID] &
 	    ATA_LOG_DEVSLP_VALID_MASK) {
-		mdat = dev->sata_settings[ATA_LOG_DEVSLP_MDAT] &
+		mdat = dev->devslp_timing[ATA_LOG_DEVSLP_MDAT] &
 		       ATA_LOG_DEVSLP_MDAT_MASK;
 		if (!mdat)
 			mdat = 10;
-		deto = dev->sata_settings[ATA_LOG_DEVSLP_DETO];
+		deto = dev->devslp_timing[ATA_LOG_DEVSLP_DETO];
 		if (!deto)
 			deto = 20;
 	} else {
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 9e8b99a..46cd3f4 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -2325,24 +2325,28 @@
 			}
 		}
 
-		/* check and mark DevSlp capability */
-		if (ata_id_has_devslp(dev->id))
-			dev->flags |= ATA_DFLAG_DEVSLP;
-
-		/* Obtain SATA Settings page from Identify Device Data Log,
-		 * which contains DevSlp timing variables etc.
-		 * Exclude old devices with ata_id_has_ncq()
+		/* Check and mark DevSlp capability. Get DevSlp timing variables
+		 * from SATA Settings page of Identify Device Data Log.
 		 */
-		if (ata_id_has_ncq(dev->id)) {
+		if (ata_id_has_devslp(dev->id)) {
+			u8 sata_setting[ATA_SECT_SIZE];
+			int i, j;
+
+			dev->flags |= ATA_DFLAG_DEVSLP;
 			err_mask = ata_read_log_page(dev,
 						     ATA_LOG_SATA_ID_DEV_DATA,
 						     ATA_LOG_SATA_SETTINGS,
-						     dev->sata_settings,
+						     sata_setting,
 						     1);
 			if (err_mask)
 				ata_dev_dbg(dev,
 					    "failed to get Identify Device Data, Emask 0x%x\n",
 					    err_mask);
+			else
+				for (i = 0; i < ATA_LOG_DEVSLP_SIZE; i++) {
+					j = ATA_LOG_DEVSLP_OFFSET + i;
+					dev->devslp_timing[i] = sata_setting[j];
+				}
 		}
 
 		dev->cdb_len = 16;
diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
index bf039b0..bcf4437 100644
--- a/drivers/ata/libata-eh.c
+++ b/drivers/ata/libata-eh.c
@@ -2094,7 +2094,7 @@
  */
 static inline int ata_eh_worth_retry(struct ata_queued_cmd *qc)
 {
-	if (qc->flags & AC_ERR_MEDIA)
+	if (qc->err_mask & AC_ERR_MEDIA)
 		return 0;	/* don't retry media errors */
 	if (qc->flags & ATA_QCFLAG_IO)
 		return 1;	/* otherwise retry anything from fs stack */
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 6345294..fb10728 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -224,7 +224,7 @@
 	 * by the cpu device.
 	 *
 	 * Never copy this way of doing things, or you too will be made fun of
-	 * on the linux-kerenl list, you have been warned.
+	 * on the linux-kernel list, you have been warned.
 	 */
 }
 
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index d814603..b392b35 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -305,7 +305,7 @@
 	char *buf;
 
 	size = fw_file_size(file);
-	if (size < 0)
+	if (size <= 0)
 		return false;
 	buf = vmalloc(size);
 	if (!buf)
diff --git a/drivers/base/regmap/regmap-debugfs.c b/drivers/base/regmap/regmap-debugfs.c
index 07aad78..d9a6c94 100644
--- a/drivers/base/regmap/regmap-debugfs.c
+++ b/drivers/base/regmap/regmap-debugfs.c
@@ -56,6 +56,19 @@
 	.llseek = default_llseek,
 };
 
+static void regmap_debugfs_free_dump_cache(struct regmap *map)
+{
+	struct regmap_debugfs_off_cache *c;
+
+	while (!list_empty(&map->debugfs_off_cache)) {
+		c = list_first_entry(&map->debugfs_off_cache,
+				     struct regmap_debugfs_off_cache,
+				     list);
+		list_del(&c->list);
+		kfree(c);
+	}
+}
+
 /*
  * Work out where the start offset maps into register numbers, bearing
  * in mind that we suppress hidden registers.
@@ -91,8 +104,10 @@
 			/* No cache entry?  Start a new one */
 			if (!c) {
 				c = kzalloc(sizeof(*c), GFP_KERNEL);
-				if (!c)
-					break;
+				if (!c) {
+					regmap_debugfs_free_dump_cache(map);
+					return base;
+				}
 				c->min = p;
 				c->base_reg = i;
 			}
@@ -101,14 +116,32 @@
 		}
 	}
 
+	/* Close the last entry off if we didn't scan beyond it */
+	if (c) {
+		c->max = p - 1;
+		list_add_tail(&c->list,
+			      &map->debugfs_off_cache);
+	}
+
+	/*
+	 * This should never happen; we return above if we fail to
+	 * allocate and we should never be in this code if there are
+	 * no registers at all.
+	 */
+	if (list_empty(&map->debugfs_off_cache)) {
+		WARN_ON(list_empty(&map->debugfs_off_cache));
+		return base;
+	}
+
 	/* Find the relevant block */
 	list_for_each_entry(c, &map->debugfs_off_cache, list) {
-		if (*pos >= c->min && *pos <= c->max) {
+		if (from >= c->min && from <= c->max) {
 			*pos = c->min;
 			return c->base_reg;
 		}
 
-		ret = c->max;
+		*pos = c->min;
+		ret = c->base_reg;
 	}
 
 	return ret;
@@ -387,16 +420,8 @@
 
 void regmap_debugfs_exit(struct regmap *map)
 {
-	struct regmap_debugfs_off_cache *c;
-
 	debugfs_remove_recursive(map->debugfs);
-	while (!list_empty(&map->debugfs_off_cache)) {
-		c = list_first_entry(&map->debugfs_off_cache,
-				     struct regmap_debugfs_off_cache,
-				     list);
-		list_del(&c->list);
-		kfree(c);
-	}
+	regmap_debugfs_free_dump_cache(map);
 	kfree(map->debugfs_name);
 }
 
diff --git a/drivers/base/regmap/regmap.c b/drivers/base/regmap/regmap.c
index 42d5cb0..f00b059 100644
--- a/drivers/base/regmap/regmap.c
+++ b/drivers/base/regmap/regmap.c
@@ -1106,7 +1106,7 @@
  * @val_count: Number of registers to write
  *
  * This function is intended to be used for writing a large block of
- * data to be device either in single transfer or multiple transfer.
+ * data to the device either in single transfer or multiple transfer.
  *
  * A value of zero will be returned on success, a negative errno will
  * be returned in error cases.
diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index 9d8409c..8ad21a2 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -889,6 +889,7 @@
 {
 	struct virtio_blk *vblk = vdev->priv;
 	int index = vblk->index;
+	int refc;
 
 	/* Prevent config work handler from accessing the device. */
 	mutex_lock(&vblk->config_lock);
@@ -903,11 +904,15 @@
 
 	flush_work(&vblk->config_work);
 
+	refc = atomic_read(&disk_to_dev(vblk->disk)->kobj.kref.refcount);
 	put_disk(vblk->disk);
 	mempool_destroy(vblk->pool);
 	vdev->config->del_vqs(vdev);
 	kfree(vblk);
-	ida_simple_remove(&vd_index_ida, index);
+
+	/* Only free device id if we don't have any users */
+	if (refc == 1)
+		ida_simple_remove(&vd_index_ida, index);
 }
 
 #ifdef CONFIG_PM
diff --git a/drivers/bluetooth/ath3k.c b/drivers/bluetooth/ath3k.c
index b00000e..33c9a44 100644
--- a/drivers/bluetooth/ath3k.c
+++ b/drivers/bluetooth/ath3k.c
@@ -77,10 +77,15 @@
 	{ USB_DEVICE(0x0CF3, 0x311D) },
 	{ USB_DEVICE(0x13d3, 0x3375) },
 	{ USB_DEVICE(0x04CA, 0x3005) },
+	{ USB_DEVICE(0x04CA, 0x3006) },
+	{ USB_DEVICE(0x04CA, 0x3008) },
 	{ USB_DEVICE(0x13d3, 0x3362) },
 	{ USB_DEVICE(0x0CF3, 0xE004) },
 	{ USB_DEVICE(0x0930, 0x0219) },
 	{ USB_DEVICE(0x0489, 0xe057) },
+	{ USB_DEVICE(0x13d3, 0x3393) },
+	{ USB_DEVICE(0x0489, 0xe04e) },
+	{ USB_DEVICE(0x0489, 0xe056) },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE02C) },
@@ -104,10 +109,15 @@
 	{ USB_DEVICE(0x0cf3, 0x311D), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU22 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c
index a1d4ede..7e351e3 100644
--- a/drivers/bluetooth/btusb.c
+++ b/drivers/bluetooth/btusb.c
@@ -135,10 +135,15 @@
 	{ USB_DEVICE(0x0cf3, 0x311d), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3375), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x04ca, 0x3005), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x04ca, 0x3006), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x04ca, 0x3008), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x13d3, 0x3362), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0cf3, 0xe004), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0930, 0x0219), .driver_info = BTUSB_ATH3012 },
 	{ USB_DEVICE(0x0489, 0xe057), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x13d3, 0x3393), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe04e), .driver_info = BTUSB_ATH3012 },
+	{ USB_DEVICE(0x0489, 0xe056), .driver_info = BTUSB_ATH3012 },
 
 	/* Atheros AR5BBU12 with sflash firmware */
 	{ USB_DEVICE(0x0489, 0xe02c), .driver_info = BTUSB_IGNORE },
diff --git a/drivers/clk/Makefile b/drivers/clk/Makefile
index ee90e87..f0b269a 100644
--- a/drivers/clk/Makefile
+++ b/drivers/clk/Makefile
@@ -22,6 +22,7 @@
 obj-$(CONFIG_ARCH_VT8500)	+= clk-vt8500.o
 obj-$(CONFIG_ARCH_SUNXI)	+= clk-sunxi.o
 obj-$(CONFIG_ARCH_ZYNQ)		+= clk-zynq.o
+obj-$(CONFIG_ARCH_TEGRA)	+= tegra/
 
 # Chip specific
 obj-$(CONFIG_COMMON_CLK_WM831X) += clk-wm831x.o
diff --git a/drivers/clk/clk-bcm2835.c b/drivers/clk/clk-bcm2835.c
index e69991a..792bc57 100644
--- a/drivers/clk/clk-bcm2835.c
+++ b/drivers/clk/clk-bcm2835.c
@@ -20,6 +20,13 @@
 #include <linux/clk-provider.h>
 #include <linux/clkdev.h>
 #include <linux/clk/bcm2835.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+
+static const __initconst struct of_device_id clk_match[] = {
+	{ .compatible = "fixed-clock", .data = of_fixed_clk_setup, },
+	{ }
+};
 
 /*
  * These are fixed clocks. They're probably not all root clocks and it may
@@ -56,4 +63,6 @@
 	ret = clk_register_clkdev(clk, NULL, "20215000.uart");
 	if (ret)
 		pr_err("uart1_pclk alias not registered\n");
+
+	of_clk_init(clk_match);
 }
diff --git a/drivers/clk/mvebu/clk-cpu.c b/drivers/clk/mvebu/clk-cpu.c
index ff004578..9dd2551 100644
--- a/drivers/clk/mvebu/clk-cpu.c
+++ b/drivers/clk/mvebu/clk-cpu.c
@@ -124,7 +124,7 @@
 
 	clks = kzalloc(ncpus * sizeof(*clks), GFP_KERNEL);
 	if (WARN_ON(!clks))
-		return;
+		goto clks_out;
 
 	for_each_node_by_type(dn, "cpu") {
 		struct clk_init_data init;
@@ -134,11 +134,11 @@
 		int cpu, err;
 
 		if (WARN_ON(!clk_name))
-			return;
+			goto bail_out;
 
 		err = of_property_read_u32(dn, "reg", &cpu);
 		if (WARN_ON(err))
-			return;
+			goto bail_out;
 
 		sprintf(clk_name, "cpu%d", cpu);
 		parent_clk = of_clk_get(node, 0);
@@ -167,6 +167,9 @@
 	return;
 bail_out:
 	kfree(clks);
+	while(ncpus--)
+		kfree(cpuclk[ncpus].clk_name);
+clks_out:
 	kfree(cpuclk);
 }
 
diff --git a/drivers/clk/tegra/Makefile b/drivers/clk/tegra/Makefile
new file mode 100644
index 0000000..2b41b0f
--- /dev/null
+++ b/drivers/clk/tegra/Makefile
@@ -0,0 +1,11 @@
+obj-y					+= clk.o
+obj-y					+= clk-audio-sync.o
+obj-y					+= clk-divider.o
+obj-y					+= clk-periph.o
+obj-y					+= clk-periph-gate.o
+obj-y					+= clk-pll.o
+obj-y					+= clk-pll-out.o
+obj-y					+= clk-super.o
+
+obj-$(CONFIG_ARCH_TEGRA_2x_SOC)         += clk-tegra20.o
+obj-$(CONFIG_ARCH_TEGRA_3x_SOC)         += clk-tegra30.o
diff --git a/drivers/clk/tegra/clk-audio-sync.c b/drivers/clk/tegra/clk-audio-sync.c
new file mode 100644
index 0000000..c0f7843
--- /dev/null
+++ b/drivers/clk/tegra/clk-audio-sync.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include "clk.h"
+
+static unsigned long clk_sync_source_recalc_rate(struct clk_hw *hw,
+						 unsigned long parent_rate)
+{
+	struct tegra_clk_sync_source *sync = to_clk_sync_source(hw);
+
+	return sync->rate;
+}
+
+static long clk_sync_source_round_rate(struct clk_hw *hw, unsigned long rate,
+				       unsigned long *prate)
+{
+	struct tegra_clk_sync_source *sync = to_clk_sync_source(hw);
+
+	if (rate > sync->max_rate)
+		return -EINVAL;
+	else
+		return rate;
+}
+
+static int clk_sync_source_set_rate(struct clk_hw *hw, unsigned long rate,
+				    unsigned long parent_rate)
+{
+	struct tegra_clk_sync_source *sync = to_clk_sync_source(hw);
+
+	sync->rate = rate;
+	return 0;
+}
+
+const struct clk_ops tegra_clk_sync_source_ops = {
+	.round_rate = clk_sync_source_round_rate,
+	.set_rate = clk_sync_source_set_rate,
+	.recalc_rate = clk_sync_source_recalc_rate,
+};
+
+struct clk *tegra_clk_register_sync_source(const char *name,
+		unsigned long rate, unsigned long max_rate)
+{
+	struct tegra_clk_sync_source *sync;
+	struct clk_init_data init;
+	struct clk *clk;
+
+	sync = kzalloc(sizeof(*sync), GFP_KERNEL);
+	if (!sync) {
+		pr_err("%s: could not allocate sync source clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	sync->rate = rate;
+	sync->max_rate = max_rate;
+
+	init.ops = &tegra_clk_sync_source_ops;
+	init.name = name;
+	init.flags = CLK_IS_ROOT;
+	init.parent_names = NULL;
+	init.num_parents = 0;
+
+	/* Data in .init is copied by clk_register(), so stack variable OK */
+	sync->hw.init = &init;
+
+	clk = clk_register(NULL, &sync->hw);
+	if (IS_ERR(clk))
+		kfree(sync);
+
+	return clk;
+}
diff --git a/drivers/clk/tegra/clk-divider.c b/drivers/clk/tegra/clk-divider.c
new file mode 100644
index 0000000..4d75b1f
--- /dev/null
+++ b/drivers/clk/tegra/clk-divider.c
@@ -0,0 +1,187 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+
+#include "clk.h"
+
+#define pll_out_override(p) (BIT((p->shift - 6)))
+#define div_mask(d) ((1 << (d->width)) - 1)
+#define get_mul(d) (1 << d->frac_width)
+#define get_max_div(d) div_mask(d)
+
+#define PERIPH_CLK_UART_DIV_ENB BIT(24)
+
+static int get_div(struct tegra_clk_frac_div *divider, unsigned long rate,
+		   unsigned long parent_rate)
+{
+	s64 divider_ux1 = parent_rate;
+	u8 flags = divider->flags;
+	int mul;
+
+	if (!rate)
+		return 0;
+
+	mul = get_mul(divider);
+
+	if (!(flags & TEGRA_DIVIDER_INT))
+		divider_ux1 *= mul;
+
+	if (flags & TEGRA_DIVIDER_ROUND_UP)
+		divider_ux1 += rate - 1;
+
+	do_div(divider_ux1, rate);
+
+	if (flags & TEGRA_DIVIDER_INT)
+		divider_ux1 *= mul;
+
+	divider_ux1 -= mul;
+
+	if (divider_ux1 < 0)
+		return 0;
+
+	if (divider_ux1 > get_max_div(divider))
+		return -EINVAL;
+
+	return divider_ux1;
+}
+
+static unsigned long clk_frac_div_recalc_rate(struct clk_hw *hw,
+					     unsigned long parent_rate)
+{
+	struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+	u32 reg;
+	int div, mul;
+	u64 rate = parent_rate;
+
+	reg = readl_relaxed(divider->reg) >> divider->shift;
+	div = reg & div_mask(divider);
+
+	mul = get_mul(divider);
+	div += mul;
+
+	rate *= mul;
+	rate += div - 1;
+	do_div(rate, div);
+
+	return rate;
+}
+
+static long clk_frac_div_round_rate(struct clk_hw *hw, unsigned long rate,
+				   unsigned long *prate)
+{
+	struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+	int div, mul;
+	unsigned long output_rate = *prate;
+
+	if (!rate)
+		return output_rate;
+
+	div = get_div(divider, rate, output_rate);
+	if (div < 0)
+		return *prate;
+
+	mul = get_mul(divider);
+
+	return DIV_ROUND_UP(output_rate * mul, div + mul);
+}
+
+static int clk_frac_div_set_rate(struct clk_hw *hw, unsigned long rate,
+				unsigned long parent_rate)
+{
+	struct tegra_clk_frac_div *divider = to_clk_frac_div(hw);
+	int div;
+	unsigned long flags = 0;
+	u32 val;
+
+	div = get_div(divider, rate, parent_rate);
+	if (div < 0)
+		return div;
+
+	if (divider->lock)
+		spin_lock_irqsave(divider->lock, flags);
+
+	val = readl_relaxed(divider->reg);
+	val &= ~(div_mask(divider) << divider->shift);
+	val |= div << divider->shift;
+
+	if (divider->flags & TEGRA_DIVIDER_UART) {
+		if (div)
+			val |= PERIPH_CLK_UART_DIV_ENB;
+		else
+			val &= ~PERIPH_CLK_UART_DIV_ENB;
+	}
+
+	if (divider->flags & TEGRA_DIVIDER_FIXED)
+		val |= pll_out_override(divider);
+
+	writel_relaxed(val, divider->reg);
+
+	if (divider->lock)
+		spin_unlock_irqrestore(divider->lock, flags);
+
+	return 0;
+}
+
+const struct clk_ops tegra_clk_frac_div_ops = {
+	.recalc_rate = clk_frac_div_recalc_rate,
+	.set_rate = clk_frac_div_set_rate,
+	.round_rate = clk_frac_div_round_rate,
+};
+
+struct clk *tegra_clk_register_divider(const char *name,
+		const char *parent_name, void __iomem *reg,
+		unsigned long flags, u8 clk_divider_flags, u8 shift, u8 width,
+		u8 frac_width, spinlock_t *lock)
+{
+	struct tegra_clk_frac_div *divider;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	divider = kzalloc(sizeof(*divider), GFP_KERNEL);
+	if (!divider) {
+		pr_err("%s: could not allocate fractional divider clk\n",
+		       __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.ops = &tegra_clk_frac_div_ops;
+	init.flags = flags;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+
+	divider->reg = reg;
+	divider->shift = shift;
+	divider->width = width;
+	divider->frac_width = frac_width;
+	divider->lock = lock;
+	divider->flags = clk_divider_flags;
+
+	/* Data in .init is copied by clk_register(), so stack variable OK */
+	divider->hw.init = &init;
+
+	clk = clk_register(NULL, &divider->hw);
+	if (IS_ERR(clk))
+		kfree(divider);
+
+	return clk;
+}
diff --git a/drivers/clk/tegra/clk-periph-gate.c b/drivers/clk/tegra/clk-periph-gate.c
new file mode 100644
index 0000000..6dd5332
--- /dev/null
+++ b/drivers/clk/tegra/clk-periph-gate.c
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/tegra-soc.h>
+
+#include "clk.h"
+
+static DEFINE_SPINLOCK(periph_ref_lock);
+
+/* Macros to assist peripheral gate clock */
+#define read_enb(gate) \
+	readl_relaxed(gate->clk_base + (gate->regs->enb_reg))
+#define write_enb_set(val, gate) \
+	writel_relaxed(val, gate->clk_base + (gate->regs->enb_set_reg))
+#define write_enb_clr(val, gate) \
+	writel_relaxed(val, gate->clk_base + (gate->regs->enb_clr_reg))
+
+#define read_rst(gate) \
+	readl_relaxed(gate->clk_base + (gate->regs->rst_reg))
+#define write_rst_set(val, gate) \
+	writel_relaxed(val, gate->clk_base + (gate->regs->rst_set_reg))
+#define write_rst_clr(val, gate) \
+	writel_relaxed(val, gate->clk_base + (gate->regs->rst_clr_reg))
+
+#define periph_clk_to_bit(periph) (1 << (gate->clk_num % 32))
+
+/* Peripheral gate clock ops */
+static int clk_periph_is_enabled(struct clk_hw *hw)
+{
+	struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
+	int state = 1;
+
+	if (!(read_enb(gate) & periph_clk_to_bit(gate)))
+		state = 0;
+
+	if (!(gate->flags & TEGRA_PERIPH_NO_RESET))
+		if (read_rst(gate) & periph_clk_to_bit(gate))
+			state = 0;
+
+	return state;
+}
+
+static int clk_periph_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&periph_ref_lock, flags);
+
+	gate->enable_refcnt[gate->clk_num]++;
+	if (gate->enable_refcnt[gate->clk_num] > 1) {
+		spin_unlock_irqrestore(&periph_ref_lock, flags);
+		return 0;
+	}
+
+	write_enb_set(periph_clk_to_bit(gate), gate);
+	udelay(2);
+
+	if (!(gate->flags & TEGRA_PERIPH_NO_RESET) &&
+	    !(gate->flags & TEGRA_PERIPH_MANUAL_RESET)) {
+		if (read_rst(gate) & periph_clk_to_bit(gate)) {
+			udelay(5); /* reset propogation delay */
+			write_rst_clr(periph_clk_to_bit(gate), gate);
+		}
+	}
+
+	spin_unlock_irqrestore(&periph_ref_lock, flags);
+
+	return 0;
+}
+
+static void clk_periph_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_periph_gate *gate = to_clk_periph_gate(hw);
+	unsigned long flags = 0;
+
+	spin_lock_irqsave(&periph_ref_lock, flags);
+
+	gate->enable_refcnt[gate->clk_num]--;
+	if (gate->enable_refcnt[gate->clk_num] > 0) {
+		spin_unlock_irqrestore(&periph_ref_lock, flags);
+		return;
+	}
+
+	/*
+	 * If peripheral is in the APB bus then read the APB bus to
+	 * flush the write operation in apb bus. This will avoid the
+	 * peripheral access after disabling clock
+	 */
+	if (gate->flags & TEGRA_PERIPH_ON_APB)
+		tegra_read_chipid();
+
+	write_enb_clr(periph_clk_to_bit(gate), gate);
+
+	spin_unlock_irqrestore(&periph_ref_lock, flags);
+}
+
+void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert)
+{
+	if (gate->flags & TEGRA_PERIPH_NO_RESET)
+		return;
+
+	if (assert) {
+		/*
+		 * If peripheral is in the APB bus then read the APB bus to
+		 * flush the write operation in apb bus. This will avoid the
+		 * peripheral access after disabling clock
+		 */
+		if (gate->flags & TEGRA_PERIPH_ON_APB)
+			tegra_read_chipid();
+
+		write_rst_set(periph_clk_to_bit(gate), gate);
+	} else {
+		write_rst_clr(periph_clk_to_bit(gate), gate);
+	}
+}
+
+const struct clk_ops tegra_clk_periph_gate_ops = {
+	.is_enabled = clk_periph_is_enabled,
+	.enable = clk_periph_enable,
+	.disable = clk_periph_disable,
+};
+
+struct clk *tegra_clk_register_periph_gate(const char *name,
+		const char *parent_name, u8 gate_flags, void __iomem *clk_base,
+		unsigned long flags, int clk_num,
+		struct tegra_clk_periph_regs *pregs, int *enable_refcnt)
+{
+	struct tegra_clk_periph_gate *gate;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	gate = kzalloc(sizeof(*gate), GFP_KERNEL);
+	if (!gate) {
+		pr_err("%s: could not allocate periph gate clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.flags = flags;
+	init.parent_names = parent_name ? &parent_name : NULL;
+	init.num_parents = parent_name ? 1 : 0;
+	init.ops = &tegra_clk_periph_gate_ops;
+
+	gate->magic = TEGRA_CLK_PERIPH_GATE_MAGIC;
+	gate->clk_base = clk_base;
+	gate->clk_num = clk_num;
+	gate->flags = gate_flags;
+	gate->enable_refcnt = enable_refcnt;
+	gate->regs = pregs;
+
+	/* Data in .init is copied by clk_register(), so stack variable OK */
+	gate->hw.init = &init;
+
+	clk = clk_register(NULL, &gate->hw);
+	if (IS_ERR(clk))
+		kfree(gate);
+
+	return clk;
+}
diff --git a/drivers/clk/tegra/clk-periph.c b/drivers/clk/tegra/clk-periph.c
new file mode 100644
index 0000000..788486e6
--- /dev/null
+++ b/drivers/clk/tegra/clk-periph.c
@@ -0,0 +1,218 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+#include "clk.h"
+
+static u8 clk_periph_get_parent(struct clk_hw *hw)
+{
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	const struct clk_ops *mux_ops = periph->mux_ops;
+	struct clk_hw *mux_hw = &periph->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	return mux_ops->get_parent(mux_hw);
+}
+
+static int clk_periph_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	const struct clk_ops *mux_ops = periph->mux_ops;
+	struct clk_hw *mux_hw = &periph->mux.hw;
+
+	mux_hw->clk = hw->clk;
+
+	return mux_ops->set_parent(mux_hw, index);
+}
+
+static unsigned long clk_periph_recalc_rate(struct clk_hw *hw,
+					    unsigned long parent_rate)
+{
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	const struct clk_ops *div_ops = periph->div_ops;
+	struct clk_hw *div_hw = &periph->divider.hw;
+
+	div_hw->clk = hw->clk;
+
+	return div_ops->recalc_rate(div_hw, parent_rate);
+}
+
+static long clk_periph_round_rate(struct clk_hw *hw, unsigned long rate,
+				  unsigned long *prate)
+{
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	const struct clk_ops *div_ops = periph->div_ops;
+	struct clk_hw *div_hw = &periph->divider.hw;
+
+	div_hw->clk = hw->clk;
+
+	return div_ops->round_rate(div_hw, rate, prate);
+}
+
+static int clk_periph_set_rate(struct clk_hw *hw, unsigned long rate,
+			       unsigned long parent_rate)
+{
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	const struct clk_ops *div_ops = periph->div_ops;
+	struct clk_hw *div_hw = &periph->divider.hw;
+
+	div_hw->clk = hw->clk;
+
+	return div_ops->set_rate(div_hw, rate, parent_rate);
+}
+
+static int clk_periph_is_enabled(struct clk_hw *hw)
+{
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	const struct clk_ops *gate_ops = periph->gate_ops;
+	struct clk_hw *gate_hw = &periph->gate.hw;
+
+	gate_hw->clk = hw->clk;
+
+	return gate_ops->is_enabled(gate_hw);
+}
+
+static int clk_periph_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	const struct clk_ops *gate_ops = periph->gate_ops;
+	struct clk_hw *gate_hw = &periph->gate.hw;
+
+	gate_hw->clk = hw->clk;
+
+	return gate_ops->enable(gate_hw);
+}
+
+static void clk_periph_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	const struct clk_ops *gate_ops = periph->gate_ops;
+	struct clk_hw *gate_hw = &periph->gate.hw;
+
+	gate_ops->disable(gate_hw);
+}
+
+void tegra_periph_reset_deassert(struct clk *c)
+{
+	struct clk_hw *hw = __clk_get_hw(c);
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	struct tegra_clk_periph_gate *gate;
+
+	if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) {
+		gate = to_clk_periph_gate(hw);
+		if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) {
+			WARN_ON(1);
+			return;
+		}
+	} else {
+		gate = &periph->gate;
+	}
+
+	tegra_periph_reset(gate, 0);
+}
+
+void tegra_periph_reset_assert(struct clk *c)
+{
+	struct clk_hw *hw = __clk_get_hw(c);
+	struct tegra_clk_periph *periph = to_clk_periph(hw);
+	struct tegra_clk_periph_gate *gate;
+
+	if (periph->magic != TEGRA_CLK_PERIPH_MAGIC) {
+		gate = to_clk_periph_gate(hw);
+		if (gate->magic != TEGRA_CLK_PERIPH_GATE_MAGIC) {
+			WARN_ON(1);
+			return;
+		}
+	} else {
+		gate = &periph->gate;
+	}
+
+	tegra_periph_reset(gate, 1);
+}
+
+const struct clk_ops tegra_clk_periph_ops = {
+	.get_parent = clk_periph_get_parent,
+	.set_parent = clk_periph_set_parent,
+	.recalc_rate = clk_periph_recalc_rate,
+	.round_rate = clk_periph_round_rate,
+	.set_rate = clk_periph_set_rate,
+	.is_enabled = clk_periph_is_enabled,
+	.enable = clk_periph_enable,
+	.disable = clk_periph_disable,
+};
+
+const struct clk_ops tegra_clk_periph_nodiv_ops = {
+	.get_parent = clk_periph_get_parent,
+	.set_parent = clk_periph_set_parent,
+	.is_enabled = clk_periph_is_enabled,
+	.enable = clk_periph_enable,
+	.disable = clk_periph_disable,
+};
+
+static struct clk *_tegra_clk_register_periph(const char *name,
+			const char **parent_names, int num_parents,
+			struct tegra_clk_periph *periph,
+			void __iomem *clk_base, u32 offset, bool div)
+{
+	struct clk *clk;
+	struct clk_init_data init;
+
+	init.name = name;
+	init.ops = div ? &tegra_clk_periph_ops : &tegra_clk_periph_nodiv_ops;
+	init.flags = div ? 0 : CLK_SET_RATE_PARENT;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+
+	/* Data in .init is copied by clk_register(), so stack variable OK */
+	periph->hw.init = &init;
+	periph->magic = TEGRA_CLK_PERIPH_MAGIC;
+	periph->mux.reg = clk_base + offset;
+	periph->divider.reg = div ? (clk_base + offset) : NULL;
+	periph->gate.clk_base = clk_base;
+
+	clk = clk_register(NULL, &periph->hw);
+	if (IS_ERR(clk))
+		return clk;
+
+	periph->mux.hw.clk = clk;
+	periph->divider.hw.clk = div ? clk : NULL;
+	periph->gate.hw.clk = clk;
+
+	return clk;
+}
+
+struct clk *tegra_clk_register_periph(const char *name,
+		const char **parent_names, int num_parents,
+		struct tegra_clk_periph *periph, void __iomem *clk_base,
+		u32 offset)
+{
+	return _tegra_clk_register_periph(name, parent_names, num_parents,
+			periph, clk_base, offset, true);
+}
+
+struct clk *tegra_clk_register_periph_nodiv(const char *name,
+		const char **parent_names, int num_parents,
+		struct tegra_clk_periph *periph, void __iomem *clk_base,
+		u32 offset)
+{
+	return _tegra_clk_register_periph(name, parent_names, num_parents,
+			periph, clk_base, offset, false);
+}
diff --git a/drivers/clk/tegra/clk-pll-out.c b/drivers/clk/tegra/clk-pll-out.c
new file mode 100644
index 0000000..3598987
--- /dev/null
+++ b/drivers/clk/tegra/clk-pll-out.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+
+#include "clk.h"
+
+#define pll_out_enb(p) (BIT(p->enb_bit_idx))
+#define pll_out_rst(p) (BIT(p->rst_bit_idx))
+
+static int clk_pll_out_is_enabled(struct clk_hw *hw)
+{
+	struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
+	u32 val = readl_relaxed(pll_out->reg);
+	int state;
+
+	state = (val & pll_out_enb(pll_out)) ? 1 : 0;
+	if (!(val & (pll_out_rst(pll_out))))
+		state = 0;
+	return state;
+}
+
+static int clk_pll_out_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
+	unsigned long flags = 0;
+	u32 val;
+
+	if (pll_out->lock)
+		spin_lock_irqsave(pll_out->lock, flags);
+
+	val = readl_relaxed(pll_out->reg);
+
+	val |= (pll_out_enb(pll_out) | pll_out_rst(pll_out));
+
+	writel_relaxed(val, pll_out->reg);
+	udelay(2);
+
+	if (pll_out->lock)
+		spin_unlock_irqrestore(pll_out->lock, flags);
+
+	return 0;
+}
+
+static void clk_pll_out_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll_out *pll_out = to_clk_pll_out(hw);
+	unsigned long flags = 0;
+	u32 val;
+
+	if (pll_out->lock)
+		spin_lock_irqsave(pll_out->lock, flags);
+
+	val = readl_relaxed(pll_out->reg);
+
+	val &= ~(pll_out_enb(pll_out) | pll_out_rst(pll_out));
+
+	writel_relaxed(val, pll_out->reg);
+	udelay(2);
+
+	if (pll_out->lock)
+		spin_unlock_irqrestore(pll_out->lock, flags);
+}
+
+const struct clk_ops tegra_clk_pll_out_ops = {
+	.is_enabled = clk_pll_out_is_enabled,
+	.enable = clk_pll_out_enable,
+	.disable = clk_pll_out_disable,
+};
+
+struct clk *tegra_clk_register_pll_out(const char *name,
+		const char *parent_name, void __iomem *reg, u8 enb_bit_idx,
+		u8 rst_bit_idx, unsigned long flags, u8 pll_out_flags,
+		spinlock_t *lock)
+{
+	struct tegra_clk_pll_out *pll_out;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	pll_out = kzalloc(sizeof(*pll_out), GFP_KERNEL);
+	if (!pll_out)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = &tegra_clk_pll_out_ops;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+	init.flags = flags;
+
+	pll_out->reg = reg;
+	pll_out->enb_bit_idx = enb_bit_idx;
+	pll_out->rst_bit_idx = rst_bit_idx;
+	pll_out->flags = pll_out_flags;
+	pll_out->lock = lock;
+
+	/* Data in .init is copied by clk_register(), so stack variable OK */
+	pll_out->hw.init = &init;
+
+	clk = clk_register(NULL, &pll_out->hw);
+	if (IS_ERR(clk))
+		kfree(pll_out);
+
+	return clk;
+}
diff --git a/drivers/clk/tegra/clk-pll.c b/drivers/clk/tegra/clk-pll.c
new file mode 100644
index 0000000..165f247
--- /dev/null
+++ b/drivers/clk/tegra/clk-pll.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+
+#include "clk.h"
+
+#define PLL_BASE_BYPASS BIT(31)
+#define PLL_BASE_ENABLE BIT(30)
+#define PLL_BASE_REF_ENABLE BIT(29)
+#define PLL_BASE_OVERRIDE BIT(28)
+
+#define PLL_BASE_DIVP_SHIFT 20
+#define PLL_BASE_DIVP_WIDTH 3
+#define PLL_BASE_DIVN_SHIFT 8
+#define PLL_BASE_DIVN_WIDTH 10
+#define PLL_BASE_DIVM_SHIFT 0
+#define PLL_BASE_DIVM_WIDTH 5
+#define PLLU_POST_DIVP_MASK 0x1
+
+#define PLL_MISC_DCCON_SHIFT 20
+#define PLL_MISC_CPCON_SHIFT 8
+#define PLL_MISC_CPCON_WIDTH 4
+#define PLL_MISC_CPCON_MASK ((1 << PLL_MISC_CPCON_WIDTH) - 1)
+#define PLL_MISC_LFCON_SHIFT 4
+#define PLL_MISC_LFCON_WIDTH 4
+#define PLL_MISC_LFCON_MASK ((1 << PLL_MISC_LFCON_WIDTH) - 1)
+#define PLL_MISC_VCOCON_SHIFT 0
+#define PLL_MISC_VCOCON_WIDTH 4
+#define PLL_MISC_VCOCON_MASK ((1 << PLL_MISC_VCOCON_WIDTH) - 1)
+
+#define OUT_OF_TABLE_CPCON 8
+
+#define PMC_PLLP_WB0_OVERRIDE 0xf8
+#define PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE BIT(12)
+#define PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE BIT(11)
+
+#define PLL_POST_LOCK_DELAY 50
+
+#define PLLDU_LFCON_SET_DIVN 600
+
+#define PLLE_BASE_DIVCML_SHIFT 24
+#define PLLE_BASE_DIVCML_WIDTH 4
+#define PLLE_BASE_DIVP_SHIFT 16
+#define PLLE_BASE_DIVP_WIDTH 7
+#define PLLE_BASE_DIVN_SHIFT 8
+#define PLLE_BASE_DIVN_WIDTH 8
+#define PLLE_BASE_DIVM_SHIFT 0
+#define PLLE_BASE_DIVM_WIDTH 8
+
+#define PLLE_MISC_SETUP_BASE_SHIFT 16
+#define PLLE_MISC_SETUP_BASE_MASK (0xffff << PLLE_MISC_SETUP_BASE_SHIFT)
+#define PLLE_MISC_LOCK_ENABLE BIT(9)
+#define PLLE_MISC_READY BIT(15)
+#define PLLE_MISC_SETUP_EX_SHIFT 2
+#define PLLE_MISC_SETUP_EX_MASK (3 << PLLE_MISC_SETUP_EX_SHIFT)
+#define PLLE_MISC_SETUP_MASK (PLLE_MISC_SETUP_BASE_MASK |	\
+			      PLLE_MISC_SETUP_EX_MASK)
+#define PLLE_MISC_SETUP_VALUE (7 << PLLE_MISC_SETUP_BASE_SHIFT)
+
+#define PLLE_SS_CTRL 0x68
+#define PLLE_SS_DISABLE (7 << 10)
+
+#define PMC_SATA_PWRGT 0x1ac
+#define PMC_SATA_PWRGT_PLLE_IDDQ_VALUE BIT(5)
+#define PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL BIT(4)
+
+#define pll_readl(offset, p) readl_relaxed(p->clk_base + offset)
+#define pll_readl_base(p) pll_readl(p->params->base_reg, p)
+#define pll_readl_misc(p) pll_readl(p->params->misc_reg, p)
+
+#define pll_writel(val, offset, p) writel_relaxed(val, p->clk_base + offset)
+#define pll_writel_base(val, p) pll_writel(val, p->params->base_reg, p)
+#define pll_writel_misc(val, p) pll_writel(val, p->params->misc_reg, p)
+
+#define mask(w) ((1 << (w)) - 1)
+#define divm_mask(p) mask(p->divm_width)
+#define divn_mask(p) mask(p->divn_width)
+#define divp_mask(p) (p->flags & TEGRA_PLLU ? PLLU_POST_DIVP_MASK :	\
+		      mask(p->divp_width))
+
+#define divm_max(p) (divm_mask(p))
+#define divn_max(p) (divn_mask(p))
+#define divp_max(p) (1 << (divp_mask(p)))
+
+static void clk_pll_enable_lock(struct tegra_clk_pll *pll)
+{
+	u32 val;
+
+	if (!(pll->flags & TEGRA_PLL_USE_LOCK))
+		return;
+
+	val = pll_readl_misc(pll);
+	val |= BIT(pll->params->lock_enable_bit_idx);
+	pll_writel_misc(val, pll);
+}
+
+static int clk_pll_wait_for_lock(struct tegra_clk_pll *pll,
+				 void __iomem *lock_addr, u32 lock_bit_idx)
+{
+	int i;
+	u32 val;
+
+	if (!(pll->flags & TEGRA_PLL_USE_LOCK)) {
+		udelay(pll->params->lock_delay);
+		return 0;
+	}
+
+	for (i = 0; i < pll->params->lock_delay; i++) {
+		val = readl_relaxed(lock_addr);
+		if (val & BIT(lock_bit_idx)) {
+			udelay(PLL_POST_LOCK_DELAY);
+			return 0;
+		}
+		udelay(2); /* timeout = 2 * lock time */
+	}
+
+	pr_err("%s: Timed out waiting for pll %s lock\n", __func__,
+	       __clk_get_name(pll->hw.clk));
+
+	return -1;
+}
+
+static int clk_pll_is_enabled(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	u32 val;
+
+	if (pll->flags & TEGRA_PLLM) {
+		val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
+		if (val & PMC_PLLP_WB0_OVERRIDE_PLLM_OVERRIDE)
+			return val & PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE ? 1 : 0;
+	}
+
+	val = pll_readl_base(pll);
+
+	return val & PLL_BASE_ENABLE ? 1 : 0;
+}
+
+static int _clk_pll_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	u32 val;
+
+	clk_pll_enable_lock(pll);
+
+	val = pll_readl_base(pll);
+	val &= ~PLL_BASE_BYPASS;
+	val |= PLL_BASE_ENABLE;
+	pll_writel_base(val, pll);
+
+	if (pll->flags & TEGRA_PLLM) {
+		val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
+		val |= PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
+		writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
+	}
+
+	clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->base_reg,
+			      pll->params->lock_bit_idx);
+
+	return 0;
+}
+
+static void _clk_pll_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	u32 val;
+
+	val = pll_readl_base(pll);
+	val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+	pll_writel_base(val, pll);
+
+	if (pll->flags & TEGRA_PLLM) {
+		val = readl_relaxed(pll->pmc + PMC_PLLP_WB0_OVERRIDE);
+		val &= ~PMC_PLLP_WB0_OVERRIDE_PLLM_ENABLE;
+		writel_relaxed(val, pll->pmc + PMC_PLLP_WB0_OVERRIDE);
+	}
+}
+
+static int clk_pll_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+	int ret;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	ret = _clk_pll_enable(hw);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	return ret;
+}
+
+static void clk_pll_disable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	_clk_pll_disable(hw);
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+}
+
+static int _get_table_rate(struct clk_hw *hw,
+			   struct tegra_clk_pll_freq_table *cfg,
+			   unsigned long rate, unsigned long parent_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct tegra_clk_pll_freq_table *sel;
+
+	for (sel = pll->freq_table; sel->input_rate != 0; sel++)
+		if (sel->input_rate == parent_rate &&
+		    sel->output_rate == rate)
+			break;
+
+	if (sel->input_rate == 0)
+		return -EINVAL;
+
+	BUG_ON(sel->p < 1);
+
+	cfg->input_rate = sel->input_rate;
+	cfg->output_rate = sel->output_rate;
+	cfg->m = sel->m;
+	cfg->n = sel->n;
+	cfg->p = sel->p;
+	cfg->cpcon = sel->cpcon;
+
+	return 0;
+}
+
+static int _calc_rate(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
+		      unsigned long rate, unsigned long parent_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long cfreq;
+	u32 p_div = 0;
+
+	switch (parent_rate) {
+	case 12000000:
+	case 26000000:
+		cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2000000;
+		break;
+	case 13000000:
+		cfreq = (rate <= 1000000 * 1000) ? 1000000 : 2600000;
+		break;
+	case 16800000:
+	case 19200000:
+		cfreq = (rate <= 1200000 * 1000) ? 1200000 : 2400000;
+		break;
+	case 9600000:
+	case 28800000:
+		/*
+		 * PLL_P_OUT1 rate is not listed in PLLA table
+		 */
+		cfreq = parent_rate/(parent_rate/1000000);
+		break;
+	default:
+		pr_err("%s Unexpected reference rate %lu\n",
+		       __func__, parent_rate);
+		BUG();
+	}
+
+	/* Raise VCO to guarantee 0.5% accuracy */
+	for (cfg->output_rate = rate; cfg->output_rate < 200 * cfreq;
+	     cfg->output_rate <<= 1)
+		p_div++;
+
+	cfg->p = 1 << p_div;
+	cfg->m = parent_rate / cfreq;
+	cfg->n = cfg->output_rate / cfreq;
+	cfg->cpcon = OUT_OF_TABLE_CPCON;
+
+	if (cfg->m > divm_max(pll) || cfg->n > divn_max(pll) ||
+	    cfg->p > divp_max(pll) || cfg->output_rate > pll->params->vco_max) {
+		pr_err("%s: Failed to set %s rate %lu\n",
+		       __func__, __clk_get_name(hw->clk), rate);
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static int _program_pll(struct clk_hw *hw, struct tegra_clk_pll_freq_table *cfg,
+			unsigned long rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long flags = 0;
+	u32 divp, val, old_base;
+	int state;
+
+	divp = __ffs(cfg->p);
+
+	if (pll->flags & TEGRA_PLLU)
+		divp ^= 1;
+
+	if (pll->lock)
+		spin_lock_irqsave(pll->lock, flags);
+
+	old_base = val = pll_readl_base(pll);
+	val &= ~((divm_mask(pll) << pll->divm_shift) |
+		 (divn_mask(pll) << pll->divn_shift) |
+		 (divp_mask(pll) << pll->divp_shift));
+	val |= ((cfg->m << pll->divm_shift) |
+		(cfg->n << pll->divn_shift) |
+		(divp << pll->divp_shift));
+	if (val == old_base) {
+		if (pll->lock)
+			spin_unlock_irqrestore(pll->lock, flags);
+		return 0;
+	}
+
+	state = clk_pll_is_enabled(hw);
+
+	if (state) {
+		_clk_pll_disable(hw);
+		val &= ~(PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+	}
+	pll_writel_base(val, pll);
+
+	if (pll->flags & TEGRA_PLL_HAS_CPCON) {
+		val = pll_readl_misc(pll);
+		val &= ~(PLL_MISC_CPCON_MASK << PLL_MISC_CPCON_SHIFT);
+		val |= cfg->cpcon << PLL_MISC_CPCON_SHIFT;
+		if (pll->flags & TEGRA_PLL_SET_LFCON) {
+			val &= ~(PLL_MISC_LFCON_MASK << PLL_MISC_LFCON_SHIFT);
+			if (cfg->n >= PLLDU_LFCON_SET_DIVN)
+				val |= 0x1 << PLL_MISC_LFCON_SHIFT;
+		} else if (pll->flags & TEGRA_PLL_SET_DCCON) {
+			val &= ~(0x1 << PLL_MISC_DCCON_SHIFT);
+			if (rate >= (pll->params->vco_max >> 1))
+				val |= 0x1 << PLL_MISC_DCCON_SHIFT;
+		}
+		pll_writel_misc(val, pll);
+	}
+
+	if (pll->lock)
+		spin_unlock_irqrestore(pll->lock, flags);
+
+	if (state)
+		clk_pll_enable(hw);
+
+	return 0;
+}
+
+static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long parent_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct tegra_clk_pll_freq_table cfg;
+
+	if (pll->flags & TEGRA_PLL_FIXED) {
+		if (rate != pll->fixed_rate) {
+			pr_err("%s: Can not change %s fixed rate %lu to %lu\n",
+				__func__, __clk_get_name(hw->clk),
+				pll->fixed_rate, rate);
+			return -EINVAL;
+		}
+		return 0;
+	}
+
+	if (_get_table_rate(hw, &cfg, rate, parent_rate) &&
+	    _calc_rate(hw, &cfg, rate, parent_rate))
+		return -EINVAL;
+
+	return _program_pll(hw, &cfg, rate);
+}
+
+static long clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
+			unsigned long *prate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	struct tegra_clk_pll_freq_table cfg;
+	u64 output_rate = *prate;
+
+	if (pll->flags & TEGRA_PLL_FIXED)
+		return pll->fixed_rate;
+
+	/* PLLM is used for memory; we do not change rate */
+	if (pll->flags & TEGRA_PLLM)
+		return __clk_get_rate(hw->clk);
+
+	if (_get_table_rate(hw, &cfg, rate, *prate) &&
+	    _calc_rate(hw, &cfg, rate, *prate))
+		return -EINVAL;
+
+	output_rate *= cfg.n;
+	do_div(output_rate, cfg.m * cfg.p);
+
+	return output_rate;
+}
+
+static unsigned long clk_pll_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	u32 val = pll_readl_base(pll);
+	u32 divn = 0, divm = 0, divp = 0;
+	u64 rate = parent_rate;
+
+	if (val & PLL_BASE_BYPASS)
+		return parent_rate;
+
+	if ((pll->flags & TEGRA_PLL_FIXED) && !(val & PLL_BASE_OVERRIDE)) {
+		struct tegra_clk_pll_freq_table sel;
+		if (_get_table_rate(hw, &sel, pll->fixed_rate, parent_rate)) {
+			pr_err("Clock %s has unknown fixed frequency\n",
+			       __clk_get_name(hw->clk));
+			BUG();
+		}
+		return pll->fixed_rate;
+	}
+
+	divp = (val >> pll->divp_shift) & (divp_mask(pll));
+	if (pll->flags & TEGRA_PLLU)
+		divp ^= 1;
+
+	divn = (val >> pll->divn_shift) & (divn_mask(pll));
+	divm = (val >> pll->divm_shift) & (divm_mask(pll));
+	divm *= (1 << divp);
+
+	rate *= divn;
+	do_div(rate, divm);
+	return rate;
+}
+
+static int clk_plle_training(struct tegra_clk_pll *pll)
+{
+	u32 val;
+	unsigned long timeout;
+
+	if (!pll->pmc)
+		return -ENOSYS;
+
+	/*
+	 * PLLE is already disabled, and setup cleared;
+	 * create falling edge on PLLE IDDQ input.
+	 */
+	val = readl(pll->pmc + PMC_SATA_PWRGT);
+	val |= PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
+	writel(val, pll->pmc + PMC_SATA_PWRGT);
+
+	val = readl(pll->pmc + PMC_SATA_PWRGT);
+	val |= PMC_SATA_PWRGT_PLLE_IDDQ_SWCTL;
+	writel(val, pll->pmc + PMC_SATA_PWRGT);
+
+	val = readl(pll->pmc + PMC_SATA_PWRGT);
+	val &= ~PMC_SATA_PWRGT_PLLE_IDDQ_VALUE;
+	writel(val, pll->pmc + PMC_SATA_PWRGT);
+
+	val = pll_readl_misc(pll);
+
+	timeout = jiffies + msecs_to_jiffies(100);
+	while (1) {
+		val = pll_readl_misc(pll);
+		if (val & PLLE_MISC_READY)
+			break;
+		if (time_after(jiffies, timeout)) {
+			pr_err("%s: timeout waiting for PLLE\n", __func__);
+			return -EBUSY;
+		}
+		udelay(300);
+	}
+
+	return 0;
+}
+
+static int clk_plle_enable(struct clk_hw *hw)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	unsigned long input_rate = clk_get_rate(clk_get_parent(hw->clk));
+	struct tegra_clk_pll_freq_table sel;
+	u32 val;
+	int err;
+
+	if (_get_table_rate(hw, &sel, pll->fixed_rate, input_rate))
+		return -EINVAL;
+
+	clk_pll_disable(hw);
+
+	val = pll_readl_misc(pll);
+	val &= ~(PLLE_MISC_LOCK_ENABLE | PLLE_MISC_SETUP_MASK);
+	pll_writel_misc(val, pll);
+
+	val = pll_readl_misc(pll);
+	if (!(val & PLLE_MISC_READY)) {
+		err = clk_plle_training(pll);
+		if (err)
+			return err;
+	}
+
+	if (pll->flags & TEGRA_PLLE_CONFIGURE) {
+		/* configure dividers */
+		val = pll_readl_base(pll);
+		val &= ~(divm_mask(pll) | divn_mask(pll) | divp_mask(pll));
+		val &= ~(PLLE_BASE_DIVCML_WIDTH << PLLE_BASE_DIVCML_SHIFT);
+		val |= sel.m << pll->divm_shift;
+		val |= sel.n << pll->divn_shift;
+		val |= sel.p << pll->divp_shift;
+		val |= sel.cpcon << PLLE_BASE_DIVCML_SHIFT;
+		pll_writel_base(val, pll);
+	}
+
+	val = pll_readl_misc(pll);
+	val |= PLLE_MISC_SETUP_VALUE;
+	val |= PLLE_MISC_LOCK_ENABLE;
+	pll_writel_misc(val, pll);
+
+	val = readl(pll->clk_base + PLLE_SS_CTRL);
+	val |= PLLE_SS_DISABLE;
+	writel(val, pll->clk_base + PLLE_SS_CTRL);
+
+	val |= pll_readl_base(pll);
+	val |= (PLL_BASE_BYPASS | PLL_BASE_ENABLE);
+	pll_writel_base(val, pll);
+
+	clk_pll_wait_for_lock(pll, pll->clk_base + pll->params->misc_reg,
+			      pll->params->lock_bit_idx);
+	return 0;
+}
+
+static unsigned long clk_plle_recalc_rate(struct clk_hw *hw,
+					 unsigned long parent_rate)
+{
+	struct tegra_clk_pll *pll = to_clk_pll(hw);
+	u32 val = pll_readl_base(pll);
+	u32 divn = 0, divm = 0, divp = 0;
+	u64 rate = parent_rate;
+
+	divp = (val >> pll->divp_shift) & (divp_mask(pll));
+	divn = (val >> pll->divn_shift) & (divn_mask(pll));
+	divm = (val >> pll->divm_shift) & (divm_mask(pll));
+	divm *= divp;
+
+	rate *= divn;
+	do_div(rate, divm);
+	return rate;
+}
+
+const struct clk_ops tegra_clk_pll_ops = {
+	.is_enabled = clk_pll_is_enabled,
+	.enable = clk_pll_enable,
+	.disable = clk_pll_disable,
+	.recalc_rate = clk_pll_recalc_rate,
+	.round_rate = clk_pll_round_rate,
+	.set_rate = clk_pll_set_rate,
+};
+
+const struct clk_ops tegra_clk_plle_ops = {
+	.recalc_rate = clk_plle_recalc_rate,
+	.is_enabled = clk_pll_is_enabled,
+	.disable = clk_pll_disable,
+	.enable = clk_plle_enable,
+};
+
+static struct clk *_tegra_clk_register_pll(const char *name,
+		const char *parent_name, void __iomem *clk_base,
+		void __iomem *pmc, unsigned long flags,
+		unsigned long fixed_rate,
+		struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock,
+		const struct clk_ops *ops)
+{
+	struct tegra_clk_pll *pll;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+	if (!pll)
+		return ERR_PTR(-ENOMEM);
+
+	init.name = name;
+	init.ops = ops;
+	init.flags = flags;
+	init.parent_names = (parent_name ? &parent_name : NULL);
+	init.num_parents = (parent_name ? 1 : 0);
+
+	pll->clk_base = clk_base;
+	pll->pmc = pmc;
+
+	pll->freq_table = freq_table;
+	pll->params = pll_params;
+	pll->fixed_rate = fixed_rate;
+	pll->flags = pll_flags;
+	pll->lock = lock;
+
+	pll->divp_shift = PLL_BASE_DIVP_SHIFT;
+	pll->divp_width = PLL_BASE_DIVP_WIDTH;
+	pll->divn_shift = PLL_BASE_DIVN_SHIFT;
+	pll->divn_width = PLL_BASE_DIVN_WIDTH;
+	pll->divm_shift = PLL_BASE_DIVM_SHIFT;
+	pll->divm_width = PLL_BASE_DIVM_WIDTH;
+
+	/* Data in .init is copied by clk_register(), so stack variable OK */
+	pll->hw.init = &init;
+
+	clk = clk_register(NULL, &pll->hw);
+	if (IS_ERR(clk))
+		kfree(pll);
+
+	return clk;
+}
+
+struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
+		void __iomem *clk_base, void __iomem *pmc,
+		unsigned long flags, unsigned long fixed_rate,
+		struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+{
+	return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
+			flags, fixed_rate, pll_params, pll_flags, freq_table,
+			lock, &tegra_clk_pll_ops);
+}
+
+struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
+		void __iomem *clk_base, void __iomem *pmc,
+		unsigned long flags, unsigned long fixed_rate,
+		struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock)
+{
+	return _tegra_clk_register_pll(name, parent_name, clk_base, pmc,
+			flags, fixed_rate, pll_params, pll_flags, freq_table,
+			lock, &tegra_clk_plle_ops);
+}
diff --git a/drivers/clk/tegra/clk-super.c b/drivers/clk/tegra/clk-super.c
new file mode 100644
index 0000000..7ad48a8
--- /dev/null
+++ b/drivers/clk/tegra/clk-super.c
@@ -0,0 +1,154 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/clk-provider.h>
+#include <linux/clk.h>
+
+#include "clk.h"
+
+#define SUPER_STATE_IDLE 0
+#define SUPER_STATE_RUN 1
+#define SUPER_STATE_IRQ 2
+#define SUPER_STATE_FIQ 3
+
+#define SUPER_STATE_SHIFT 28
+#define SUPER_STATE_MASK ((BIT(SUPER_STATE_IDLE) | BIT(SUPER_STATE_RUN) | \
+			   BIT(SUPER_STATE_IRQ) | BIT(SUPER_STATE_FIQ))	\
+			  << SUPER_STATE_SHIFT)
+
+#define SUPER_LP_DIV2_BYPASS (1 << 16)
+
+#define super_state(s) (BIT(s) << SUPER_STATE_SHIFT)
+#define super_state_to_src_shift(m, s) ((m->width * s))
+#define super_state_to_src_mask(m) (((1 << m->width) - 1))
+
+static u8 clk_super_get_parent(struct clk_hw *hw)
+{
+	struct tegra_clk_super_mux *mux = to_clk_super_mux(hw);
+	u32 val, state;
+	u8 source, shift;
+
+	val = readl_relaxed(mux->reg);
+
+	state = val & SUPER_STATE_MASK;
+
+	BUG_ON((state != super_state(SUPER_STATE_RUN)) &&
+	       (state != super_state(SUPER_STATE_IDLE)));
+	shift = (state == super_state(SUPER_STATE_IDLE)) ?
+		super_state_to_src_shift(mux, SUPER_STATE_IDLE) :
+		super_state_to_src_shift(mux, SUPER_STATE_RUN);
+
+	source = (val >> shift) & super_state_to_src_mask(mux);
+
+	/*
+	 * If LP_DIV2_BYPASS is not set and PLLX is current parent then
+	 * PLLX/2 is the input source to CCLKLP.
+	 */
+	if ((mux->flags & TEGRA_DIVIDER_2) && !(val & SUPER_LP_DIV2_BYPASS) &&
+	    (source == mux->pllx_index))
+		source = mux->div2_index;
+
+	return source;
+}
+
+static int clk_super_set_parent(struct clk_hw *hw, u8 index)
+{
+	struct tegra_clk_super_mux *mux = to_clk_super_mux(hw);
+	u32 val, state;
+	u8 parent_index, shift;
+
+	val = readl_relaxed(mux->reg);
+	state = val & SUPER_STATE_MASK;
+	BUG_ON((state != super_state(SUPER_STATE_RUN)) &&
+	       (state != super_state(SUPER_STATE_IDLE)));
+	shift = (state == super_state(SUPER_STATE_IDLE)) ?
+		super_state_to_src_shift(mux, SUPER_STATE_IDLE) :
+		super_state_to_src_shift(mux, SUPER_STATE_RUN);
+
+	/*
+	 * For LP mode super-clock switch between PLLX direct
+	 * and divided-by-2 outputs is allowed only when other
+	 * than PLLX clock source is current parent.
+	 */
+	if ((mux->flags & TEGRA_DIVIDER_2) && ((index == mux->div2_index) ||
+					       (index == mux->pllx_index))) {
+		parent_index = clk_super_get_parent(hw);
+		if ((parent_index == mux->div2_index) ||
+		    (parent_index == mux->pllx_index))
+			return -EINVAL;
+
+		val ^= SUPER_LP_DIV2_BYPASS;
+		writel_relaxed(val, mux->reg);
+		udelay(2);
+
+		if (index == mux->div2_index)
+			index = mux->pllx_index;
+	}
+	val &= ~((super_state_to_src_mask(mux)) << shift);
+	val |= (index & (super_state_to_src_mask(mux))) << shift;
+
+	writel_relaxed(val, mux->reg);
+	udelay(2);
+	return 0;
+}
+
+const struct clk_ops tegra_clk_super_ops = {
+	.get_parent = clk_super_get_parent,
+	.set_parent = clk_super_set_parent,
+};
+
+struct clk *tegra_clk_register_super_mux(const char *name,
+		const char **parent_names, u8 num_parents,
+		unsigned long flags, void __iomem *reg, u8 clk_super_flags,
+		u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock)
+{
+	struct tegra_clk_super_mux *super;
+	struct clk *clk;
+	struct clk_init_data init;
+
+	super = kzalloc(sizeof(*super), GFP_KERNEL);
+	if (!super) {
+		pr_err("%s: could not allocate super clk\n", __func__);
+		return ERR_PTR(-ENOMEM);
+	}
+
+	init.name = name;
+	init.ops = &tegra_clk_super_ops;
+	init.flags = flags;
+	init.parent_names = parent_names;
+	init.num_parents = num_parents;
+
+	super->reg = reg;
+	super->pllx_index = pllx_index;
+	super->div2_index = div2_index;
+	super->lock = lock;
+	super->width = width;
+	super->flags = clk_super_flags;
+
+	/* Data in .init is copied by clk_register(), so stack variable OK */
+	super->hw.init = &init;
+
+	clk = clk_register(NULL, &super->hw);
+	if (IS_ERR(clk))
+		kfree(super);
+
+	return clk;
+}
diff --git a/drivers/clk/tegra/clk-tegra20.c b/drivers/clk/tegra/clk-tegra20.c
new file mode 100644
index 0000000..5d41569
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra20.c
@@ -0,0 +1,1349 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/tegra.h>
+#include <linux/delay.h>
+
+#include "clk.h"
+
+#define RST_DEVICES_L 0x004
+#define RST_DEVICES_H 0x008
+#define RST_DEVICES_U 0x00c
+#define RST_DEVICES_SET_L 0x300
+#define RST_DEVICES_CLR_L 0x304
+#define RST_DEVICES_SET_H 0x308
+#define RST_DEVICES_CLR_H 0x30c
+#define RST_DEVICES_SET_U 0x310
+#define RST_DEVICES_CLR_U 0x314
+#define RST_DEVICES_NUM 3
+
+#define CLK_OUT_ENB_L 0x010
+#define CLK_OUT_ENB_H 0x014
+#define CLK_OUT_ENB_U 0x018
+#define CLK_OUT_ENB_SET_L 0x320
+#define CLK_OUT_ENB_CLR_L 0x324
+#define CLK_OUT_ENB_SET_H 0x328
+#define CLK_OUT_ENB_CLR_H 0x32c
+#define CLK_OUT_ENB_SET_U 0x330
+#define CLK_OUT_ENB_CLR_U 0x334
+#define CLK_OUT_ENB_NUM 3
+
+#define OSC_CTRL 0x50
+#define OSC_CTRL_OSC_FREQ_MASK (3<<30)
+#define OSC_CTRL_OSC_FREQ_13MHZ (0<<30)
+#define OSC_CTRL_OSC_FREQ_19_2MHZ (1<<30)
+#define OSC_CTRL_OSC_FREQ_12MHZ (2<<30)
+#define OSC_CTRL_OSC_FREQ_26MHZ (3<<30)
+#define OSC_CTRL_MASK (0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
+
+#define OSC_CTRL_PLL_REF_DIV_MASK (3<<28)
+#define OSC_CTRL_PLL_REF_DIV_1		(0<<28)
+#define OSC_CTRL_PLL_REF_DIV_2		(1<<28)
+#define OSC_CTRL_PLL_REF_DIV_4		(2<<28)
+
+#define OSC_FREQ_DET 0x58
+#define OSC_FREQ_DET_TRIG (1<<31)
+
+#define OSC_FREQ_DET_STATUS 0x5c
+#define OSC_FREQ_DET_BUSY (1<<31)
+#define OSC_FREQ_DET_CNT_MASK 0xFFFF
+
+#define PLLS_BASE 0xf0
+#define PLLS_MISC 0xf4
+#define PLLC_BASE 0x80
+#define PLLC_MISC 0x8c
+#define PLLM_BASE 0x90
+#define PLLM_MISC 0x9c
+#define PLLP_BASE 0xa0
+#define PLLP_MISC 0xac
+#define PLLA_BASE 0xb0
+#define PLLA_MISC 0xbc
+#define PLLU_BASE 0xc0
+#define PLLU_MISC 0xcc
+#define PLLD_BASE 0xd0
+#define PLLD_MISC 0xdc
+#define PLLX_BASE 0xe0
+#define PLLX_MISC 0xe4
+#define PLLE_BASE 0xe8
+#define PLLE_MISC 0xec
+
+#define PLL_BASE_LOCK 27
+#define PLLE_MISC_LOCK 11
+
+#define PLL_MISC_LOCK_ENABLE 18
+#define PLLDU_MISC_LOCK_ENABLE 22
+#define PLLE_MISC_LOCK_ENABLE 9
+
+#define PLLC_OUT 0x84
+#define PLLM_OUT 0x94
+#define PLLP_OUTA 0xa4
+#define PLLP_OUTB 0xa8
+#define PLLA_OUT 0xb4
+
+#define CCLK_BURST_POLICY 0x20
+#define SUPER_CCLK_DIVIDER 0x24
+#define SCLK_BURST_POLICY 0x28
+#define SUPER_SCLK_DIVIDER 0x2c
+#define CLK_SYSTEM_RATE 0x30
+
+#define CCLK_BURST_POLICY_SHIFT	28
+#define CCLK_RUN_POLICY_SHIFT	4
+#define CCLK_IDLE_POLICY_SHIFT	0
+#define CCLK_IDLE_POLICY	1
+#define CCLK_RUN_POLICY		2
+#define CCLK_BURST_POLICY_PLLX	8
+
+#define CLK_SOURCE_I2S1 0x100
+#define CLK_SOURCE_I2S2 0x104
+#define CLK_SOURCE_SPDIF_OUT 0x108
+#define CLK_SOURCE_SPDIF_IN 0x10c
+#define CLK_SOURCE_PWM 0x110
+#define CLK_SOURCE_SPI 0x114
+#define CLK_SOURCE_SBC1 0x134
+#define CLK_SOURCE_SBC2 0x118
+#define CLK_SOURCE_SBC3 0x11c
+#define CLK_SOURCE_SBC4 0x1b4
+#define CLK_SOURCE_XIO 0x120
+#define CLK_SOURCE_TWC 0x12c
+#define CLK_SOURCE_IDE 0x144
+#define CLK_SOURCE_NDFLASH 0x160
+#define CLK_SOURCE_VFIR 0x168
+#define CLK_SOURCE_SDMMC1 0x150
+#define CLK_SOURCE_SDMMC2 0x154
+#define CLK_SOURCE_SDMMC3 0x1bc
+#define CLK_SOURCE_SDMMC4 0x164
+#define CLK_SOURCE_CVE 0x140
+#define CLK_SOURCE_TVO 0x188
+#define CLK_SOURCE_TVDAC 0x194
+#define CLK_SOURCE_HDMI 0x18c
+#define CLK_SOURCE_DISP1 0x138
+#define CLK_SOURCE_DISP2 0x13c
+#define CLK_SOURCE_CSITE 0x1d4
+#define CLK_SOURCE_LA 0x1f8
+#define CLK_SOURCE_OWR 0x1cc
+#define CLK_SOURCE_NOR 0x1d0
+#define CLK_SOURCE_MIPI 0x174
+#define CLK_SOURCE_I2C1 0x124
+#define CLK_SOURCE_I2C2 0x198
+#define CLK_SOURCE_I2C3 0x1b8
+#define CLK_SOURCE_DVC 0x128
+#define CLK_SOURCE_UARTA 0x178
+#define CLK_SOURCE_UARTB 0x17c
+#define CLK_SOURCE_UARTC 0x1a0
+#define CLK_SOURCE_UARTD 0x1c0
+#define CLK_SOURCE_UARTE 0x1c4
+#define CLK_SOURCE_3D 0x158
+#define CLK_SOURCE_2D 0x15c
+#define CLK_SOURCE_MPE 0x170
+#define CLK_SOURCE_EPP 0x16c
+#define CLK_SOURCE_HOST1X 0x180
+#define CLK_SOURCE_VDE 0x1c8
+#define CLK_SOURCE_VI 0x148
+#define CLK_SOURCE_VI_SENSOR 0x1a8
+#define CLK_SOURCE_EMC 0x19c
+
+#define AUDIO_SYNC_CLK 0x38
+
+#define PMC_CTRL 0x0
+#define PMC_CTRL_BLINK_ENB 7
+#define PMC_DPD_PADS_ORIDE 0x1c
+#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
+#define PMC_BLINK_TIMER 0x40
+
+/* Tegra CPU clock and reset control regs */
+#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX		0x4c
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET	0x340
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR	0x344
+
+#define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
+#define CPU_RESET(cpu)	(0x1111ul << (cpu))
+
+#ifdef CONFIG_PM_SLEEP
+static struct cpu_clk_suspend_context {
+	u32 pllx_misc;
+	u32 pllx_base;
+
+	u32 cpu_burst;
+	u32 clk_csite_src;
+	u32 cclk_divider;
+} tegra20_cpu_clk_sctx;
+#endif
+
+static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32];
+
+static void __iomem *clk_base;
+static void __iomem *pmc_base;
+
+static DEFINE_SPINLOCK(pll_div_lock);
+
+#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset,	\
+			    _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,	\
+			30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_ROUND_UP,	\
+			_regs, _clk_num, periph_clk_enb_refcnt,		\
+			_gate_flags, _clk_id)
+
+#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset,	\
+			    _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,	\
+			30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,	\
+			_clk_num, periph_clk_enb_refcnt, _gate_flags,	\
+			_clk_id)
+
+#define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \
+			      _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,	\
+			30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP, _regs, \
+			_clk_num, periph_clk_enb_refcnt, _gate_flags,	\
+			_clk_id)
+
+#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \
+			      _mux_shift, _mux_width, _clk_num, _regs,	\
+			      _gate_flags, _clk_id)			\
+	TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,	\
+			_mux_shift, _mux_width, 0, 0, 0, 0, 0, _regs,	\
+			_clk_num, periph_clk_enb_refcnt, _gate_flags,	\
+			_clk_id)
+
+/* IDs assigned here must be in sync with DT bindings definition
+ * for Tegra20 clocks .
+ */
+enum tegra20_clk {
+	cpu, ac97 = 3, rtc, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1,
+	ndflash, sdmmc1, sdmmc4, twc, pwm, i2s2, epp, gr2d = 21, usbd, isp,
+	gr3d, ide, disp2, disp1, host1x, vcp, cache2 = 31, mem, ahbdma, apbdma,
+	kbc = 36, stat_mon, pmc, fuse, kfuse, sbc1, nor, spi, sbc2, xio, sbc3,
+	dvc, dsi, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2,
+	usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3,
+	pex, owr, afi, csite, pcie_xclk, avpucq = 75, la, irama = 84, iramb,
+	iramc, iramd, cram2, audio_2x, clk_d, csus = 92, cdev1, cdev2,
+	uartb = 96, vfir, spdif_in, spdif_out, vi, vi_sensor, tvo, cve,
+	osc, clk_32k, clk_m, sclk, cclk, hclk, pclk, blink, pll_a, pll_a_out0,
+	pll_c, pll_c_out1, pll_d, pll_d_out0, pll_e, pll_m, pll_m_out1,
+	pll_p, pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_u,
+	pll_x, audio, pll_ref, twd, clk_max,
+};
+
+static struct clk *clks[clk_max];
+static struct clk_onecell_data clk_data;
+
+static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
+	{ 12000000, 600000000, 600, 12, 1, 8 },
+	{ 13000000, 600000000, 600, 13, 1, 8 },
+	{ 19200000, 600000000, 500, 16, 1, 6 },
+	{ 26000000, 600000000, 600, 26, 1, 8 },
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
+	{ 12000000, 666000000, 666, 12, 1, 8},
+	{ 13000000, 666000000, 666, 13, 1, 8},
+	{ 19200000, 666000000, 555, 16, 1, 8},
+	{ 26000000, 666000000, 666, 26, 1, 8},
+	{ 12000000, 600000000, 600, 12, 1, 8},
+	{ 13000000, 600000000, 600, 13, 1, 8},
+	{ 19200000, 600000000, 375, 12, 1, 6},
+	{ 26000000, 600000000, 600, 26, 1, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
+	{ 12000000, 216000000, 432, 12, 2, 8},
+	{ 13000000, 216000000, 432, 13, 2, 8},
+	{ 19200000, 216000000, 90,   4, 2, 1},
+	{ 26000000, 216000000, 432, 26, 2, 8},
+	{ 12000000, 432000000, 432, 12, 1, 8},
+	{ 13000000, 432000000, 432, 13, 1, 8},
+	{ 19200000, 432000000, 90,   4, 1, 1},
+	{ 26000000, 432000000, 432, 26, 1, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
+	{ 28800000, 56448000, 49, 25, 1, 1},
+	{ 28800000, 73728000, 64, 25, 1, 1},
+	{ 28800000, 24000000,  5,  6, 1, 1},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
+	{ 12000000, 216000000, 216, 12, 1, 4},
+	{ 13000000, 216000000, 216, 13, 1, 4},
+	{ 19200000, 216000000, 135, 12, 1, 3},
+	{ 26000000, 216000000, 216, 26, 1, 4},
+
+	{ 12000000, 594000000, 594, 12, 1, 8},
+	{ 13000000, 594000000, 594, 13, 1, 8},
+	{ 19200000, 594000000, 495, 16, 1, 8},
+	{ 26000000, 594000000, 594, 26, 1, 8},
+
+	{ 12000000, 1000000000, 1000, 12, 1, 12},
+	{ 13000000, 1000000000, 1000, 13, 1, 12},
+	{ 19200000, 1000000000, 625,  12, 1, 8},
+	{ 26000000, 1000000000, 1000, 26, 1, 12},
+
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
+	{ 12000000, 480000000, 960, 12, 2, 0},
+	{ 13000000, 480000000, 960, 13, 2, 0},
+	{ 19200000, 480000000, 200, 4,  2, 0},
+	{ 26000000, 480000000, 960, 26, 2, 0},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
+	/* 1 GHz */
+	{ 12000000, 1000000000, 1000, 12, 1, 12},
+	{ 13000000, 1000000000, 1000, 13, 1, 12},
+	{ 19200000, 1000000000, 625,  12, 1, 8},
+	{ 26000000, 1000000000, 1000, 26, 1, 12},
+
+	/* 912 MHz */
+	{ 12000000, 912000000,  912,  12, 1, 12},
+	{ 13000000, 912000000,  912,  13, 1, 12},
+	{ 19200000, 912000000,  760,  16, 1, 8},
+	{ 26000000, 912000000,  912,  26, 1, 12},
+
+	/* 816 MHz */
+	{ 12000000, 816000000,  816,  12, 1, 12},
+	{ 13000000, 816000000,  816,  13, 1, 12},
+	{ 19200000, 816000000,  680,  16, 1, 8},
+	{ 26000000, 816000000,  816,  26, 1, 12},
+
+	/* 760 MHz */
+	{ 12000000, 760000000,  760,  12, 1, 12},
+	{ 13000000, 760000000,  760,  13, 1, 12},
+	{ 19200000, 760000000,  950,  24, 1, 8},
+	{ 26000000, 760000000,  760,  26, 1, 12},
+
+	/* 750 MHz */
+	{ 12000000, 750000000,  750,  12, 1, 12},
+	{ 13000000, 750000000,  750,  13, 1, 12},
+	{ 19200000, 750000000,  625,  16, 1, 8},
+	{ 26000000, 750000000,  750,  26, 1, 12},
+
+	/* 608 MHz */
+	{ 12000000, 608000000,  608,  12, 1, 12},
+	{ 13000000, 608000000,  608,  13, 1, 12},
+	{ 19200000, 608000000,  380,  12, 1, 8},
+	{ 26000000, 608000000,  608,  26, 1, 12},
+
+	/* 456 MHz */
+	{ 12000000, 456000000,  456,  12, 1, 12},
+	{ 13000000, 456000000,  456,  13, 1, 12},
+	{ 19200000, 456000000,  380,  16, 1, 8},
+	{ 26000000, 456000000,  456,  26, 1, 12},
+
+	/* 312 MHz */
+	{ 12000000, 312000000,  312,  12, 1, 12},
+	{ 13000000, 312000000,  312,  13, 1, 12},
+	{ 19200000, 312000000,  260,  16, 1, 8},
+	{ 26000000, 312000000,  312,  26, 1, 12},
+
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
+	{ 12000000, 100000000,  200,  24, 1, 0 },
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+/* PLL parameters */
+static struct tegra_clk_pll_params pll_c_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 20000000,
+	.vco_max = 1400000000,
+	.base_reg = PLLC_BASE,
+	.misc_reg = PLLC_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_m_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 20000000,
+	.vco_max = 1200000000,
+	.base_reg = PLLM_BASE,
+	.misc_reg = PLLM_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_p_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 20000000,
+	.vco_max = 1400000000,
+	.base_reg = PLLP_BASE,
+	.misc_reg = PLLP_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_a_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 20000000,
+	.vco_max = 1400000000,
+	.base_reg = PLLA_BASE,
+	.misc_reg = PLLA_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_d_params = {
+	.input_min = 2000000,
+	.input_max = 40000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 40000000,
+	.vco_max = 1000000000,
+	.base_reg = PLLD_BASE,
+	.misc_reg = PLLD_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+	.lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_params pll_u_params = {
+	.input_min = 2000000,
+	.input_max = 40000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 48000000,
+	.vco_max = 960000000,
+	.base_reg = PLLU_BASE,
+	.misc_reg = PLLU_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+	.lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_params pll_x_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 20000000,
+	.vco_max = 1200000000,
+	.base_reg = PLLX_BASE,
+	.misc_reg = PLLX_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_e_params = {
+	.input_min = 12000000,
+	.input_max = 12000000,
+	.cf_min = 0,
+	.cf_max = 0,
+	.vco_min = 0,
+	.vco_max = 0,
+	.base_reg = PLLE_BASE,
+	.misc_reg = PLLE_MISC,
+	.lock_bit_idx = PLLE_MISC_LOCK,
+	.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
+	.lock_delay = 0,
+};
+
+/* Peripheral clock registers */
+static struct tegra_clk_periph_regs periph_l_regs = {
+	.enb_reg = CLK_OUT_ENB_L,
+	.enb_set_reg = CLK_OUT_ENB_SET_L,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_L,
+	.rst_reg = RST_DEVICES_L,
+	.rst_set_reg = RST_DEVICES_SET_L,
+	.rst_clr_reg = RST_DEVICES_CLR_L,
+};
+
+static struct tegra_clk_periph_regs periph_h_regs = {
+	.enb_reg = CLK_OUT_ENB_H,
+	.enb_set_reg = CLK_OUT_ENB_SET_H,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_H,
+	.rst_reg = RST_DEVICES_H,
+	.rst_set_reg = RST_DEVICES_SET_H,
+	.rst_clr_reg = RST_DEVICES_CLR_H,
+};
+
+static struct tegra_clk_periph_regs periph_u_regs = {
+	.enb_reg = CLK_OUT_ENB_U,
+	.enb_set_reg = CLK_OUT_ENB_SET_U,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_U,
+	.rst_reg = RST_DEVICES_U,
+	.rst_set_reg = RST_DEVICES_SET_U,
+	.rst_clr_reg = RST_DEVICES_CLR_U,
+};
+
+static unsigned long tegra20_clk_measure_input_freq(void)
+{
+	u32 osc_ctrl = readl_relaxed(clk_base + OSC_CTRL);
+	u32 auto_clk_control = osc_ctrl & OSC_CTRL_OSC_FREQ_MASK;
+	u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK;
+	unsigned long input_freq;
+
+	switch (auto_clk_control) {
+	case OSC_CTRL_OSC_FREQ_12MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+		input_freq = 12000000;
+		break;
+	case OSC_CTRL_OSC_FREQ_13MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+		input_freq = 13000000;
+		break;
+	case OSC_CTRL_OSC_FREQ_19_2MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+		input_freq = 19200000;
+		break;
+	case OSC_CTRL_OSC_FREQ_26MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+		input_freq = 26000000;
+		break;
+	default:
+		pr_err("Unexpected clock autodetect value %d",
+		       auto_clk_control);
+		BUG();
+		return 0;
+	}
+
+	return input_freq;
+}
+
+static unsigned int tegra20_get_pll_ref_div(void)
+{
+	u32 pll_ref_div = readl_relaxed(clk_base + OSC_CTRL) &
+		OSC_CTRL_PLL_REF_DIV_MASK;
+
+	switch (pll_ref_div) {
+	case OSC_CTRL_PLL_REF_DIV_1:
+		return 1;
+	case OSC_CTRL_PLL_REF_DIV_2:
+		return 2;
+	case OSC_CTRL_PLL_REF_DIV_4:
+		return 4;
+	default:
+		pr_err("Invalied pll ref divider %d\n", pll_ref_div);
+		BUG();
+	}
+	return 0;
+}
+
+static void tegra20_pll_init(void)
+{
+	struct clk *clk;
+
+	/* PLLC */
+	clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, NULL, 0,
+			    0, &pll_c_params, TEGRA_PLL_HAS_CPCON,
+			    pll_c_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_c", NULL);
+	clks[pll_c] = clk;
+
+	/* PLLC_OUT1 */
+	clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
+				clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
+				clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT,
+				0, NULL);
+	clk_register_clkdev(clk, "pll_c_out1", NULL);
+	clks[pll_c_out1] = clk;
+
+	/* PLLP */
+	clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, NULL, 0,
+			    216000000, &pll_p_params, TEGRA_PLL_FIXED |
+			    TEGRA_PLL_HAS_CPCON, pll_p_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_p", NULL);
+	clks[pll_p] = clk;
+
+	/* PLLP_OUT1 */
+	clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p",
+				clk_base + PLLP_OUTA, 0,
+				TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, &pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div",
+				clk_base + PLLP_OUTA, 1, 0,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out1", NULL);
+	clks[pll_p_out1] = clk;
+
+	/* PLLP_OUT2 */
+	clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
+				clk_base + PLLP_OUTA, 0,
+				TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP,
+				24, 8, 1, &pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
+				clk_base + PLLP_OUTA, 17, 16,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out2", NULL);
+	clks[pll_p_out2] = clk;
+
+	/* PLLP_OUT3 */
+	clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p",
+				clk_base + PLLP_OUTB, 0,
+				TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, &pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div",
+				clk_base + PLLP_OUTB, 1, 0,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out3", NULL);
+	clks[pll_p_out3] = clk;
+
+	/* PLLP_OUT4 */
+	clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p",
+				clk_base + PLLP_OUTB, 0,
+				TEGRA_DIVIDER_FIXED | TEGRA_DIVIDER_ROUND_UP,
+				24, 8, 1, &pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div",
+				clk_base + PLLP_OUTB, 17, 16,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out4", NULL);
+	clks[pll_p_out4] = clk;
+
+	/* PLLM */
+	clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, NULL,
+			    CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
+			    &pll_m_params, TEGRA_PLL_HAS_CPCON,
+			    pll_m_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_m", NULL);
+	clks[pll_m] = clk;
+
+	/* PLLM_OUT1 */
+	clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m",
+				clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
+				clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+				CLK_SET_RATE_PARENT, 0, NULL);
+	clk_register_clkdev(clk, "pll_m_out1", NULL);
+	clks[pll_m_out1] = clk;
+
+	/* PLLX */
+	clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, NULL, 0,
+			    0, &pll_x_params, TEGRA_PLL_HAS_CPCON,
+			    pll_x_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_x", NULL);
+	clks[pll_x] = clk;
+
+	/* PLLU */
+	clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, NULL, 0,
+			    0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON,
+			    pll_u_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_u", NULL);
+	clks[pll_u] = clk;
+
+	/* PLLD */
+	clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, NULL, 0,
+			    0, &pll_d_params, TEGRA_PLL_HAS_CPCON,
+			    pll_d_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_d", NULL);
+	clks[pll_d] = clk;
+
+	/* PLLD_OUT0 */
+	clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll_d_out0", NULL);
+	clks[pll_d_out0] = clk;
+
+	/* PLLA */
+	clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, NULL, 0,
+			    0, &pll_a_params, TEGRA_PLL_HAS_CPCON,
+			    pll_a_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_a", NULL);
+	clks[pll_a] = clk;
+
+	/* PLLA_OUT0 */
+	clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
+				clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
+				clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
+				CLK_SET_RATE_PARENT, 0, NULL);
+	clk_register_clkdev(clk, "pll_a_out0", NULL);
+	clks[pll_a_out0] = clk;
+
+	/* PLLE */
+	clk = tegra_clk_register_plle("pll_e", "pll_ref", clk_base, NULL,
+			     0, 100000000, &pll_e_params,
+			     0, pll_e_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_e", NULL);
+	clks[pll_e] = clk;
+}
+
+static const char *cclk_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+				      "pll_p_cclk", "pll_p_out4_cclk",
+				      "pll_p_out3_cclk", "clk_d", "pll_x" };
+static const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
+				      "pll_p_out3", "pll_p_out2", "clk_d",
+				      "clk_32k", "pll_m_out1" };
+
+static void tegra20_super_clk_init(void)
+{
+	struct clk *clk;
+
+	/*
+	 * DIV_U71 dividers for CCLK, these dividers are used only
+	 * if parent clock is fixed rate.
+	 */
+
+	/*
+	 * Clock input to cclk divided from pll_p using
+	 * U71 divider of cclk.
+	 */
+	clk = tegra_clk_register_divider("pll_p_cclk", "pll_p",
+				clk_base + SUPER_CCLK_DIVIDER, 0,
+				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
+	clk_register_clkdev(clk, "pll_p_cclk", NULL);
+
+	/*
+	 * Clock input to cclk divided from pll_p_out3 using
+	 * U71 divider of cclk.
+	 */
+	clk = tegra_clk_register_divider("pll_p_out3_cclk", "pll_p_out3",
+				clk_base + SUPER_CCLK_DIVIDER, 0,
+				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
+	clk_register_clkdev(clk, "pll_p_out3_cclk", NULL);
+
+	/*
+	 * Clock input to cclk divided from pll_p_out4 using
+	 * U71 divider of cclk.
+	 */
+	clk = tegra_clk_register_divider("pll_p_out4_cclk", "pll_p_out4",
+				clk_base + SUPER_CCLK_DIVIDER, 0,
+				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
+	clk_register_clkdev(clk, "pll_p_out4_cclk", NULL);
+
+	/* CCLK */
+	clk = tegra_clk_register_super_mux("cclk", cclk_parents,
+			      ARRAY_SIZE(cclk_parents), CLK_SET_RATE_PARENT,
+			      clk_base + CCLK_BURST_POLICY, 0, 4, 0, 0, NULL);
+	clk_register_clkdev(clk, "cclk", NULL);
+	clks[cclk] = clk;
+
+	/* SCLK */
+	clk = tegra_clk_register_super_mux("sclk", sclk_parents,
+			      ARRAY_SIZE(sclk_parents), CLK_SET_RATE_PARENT,
+			      clk_base + SCLK_BURST_POLICY, 0, 4, 0, 0, NULL);
+	clk_register_clkdev(clk, "sclk", NULL);
+	clks[sclk] = clk;
+
+	/* HCLK */
+	clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
+				   clk_base + CLK_SYSTEM_RATE, 4, 2, 0, NULL);
+	clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT,
+				clk_base + CLK_SYSTEM_RATE, 7,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "hclk", NULL);
+	clks[hclk] = clk;
+
+	/* PCLK */
+	clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
+				   clk_base + CLK_SYSTEM_RATE, 0, 2, 0, NULL);
+	clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT,
+				clk_base + CLK_SYSTEM_RATE, 3,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "pclk", NULL);
+	clks[pclk] = clk;
+
+	/* twd */
+	clk = clk_register_fixed_factor(NULL, "twd", "cclk", 0, 1, 4);
+	clk_register_clkdev(clk, "twd", NULL);
+	clks[twd] = clk;
+}
+
+static const char *audio_parents[] = {"spdif_in", "i2s1", "i2s2", "unused",
+				      "pll_a_out0", "unused", "unused",
+				      "unused"};
+
+static void __init tegra20_audio_clk_init(void)
+{
+	struct clk *clk;
+
+	/* audio */
+	clk = clk_register_mux(NULL, "audio_mux", audio_parents,
+				ARRAY_SIZE(audio_parents), 0,
+				clk_base + AUDIO_SYNC_CLK, 0, 3, 0, NULL);
+	clk = clk_register_gate(NULL, "audio", "audio_mux", 0,
+				clk_base + AUDIO_SYNC_CLK, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio", NULL);
+	clks[audio] = clk;
+
+	/* audio_2x */
+	clk = clk_register_fixed_factor(NULL, "audio_doubler", "audio",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_periph_gate("audio_2x", "audio_doubler",
+				    TEGRA_PERIPH_NO_RESET, clk_base,
+				    CLK_SET_RATE_PARENT, 89, &periph_u_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio_2x", NULL);
+	clks[audio_2x] = clk;
+
+}
+
+static const char *i2s1_parents[] = {"pll_a_out0", "audio_2x", "pll_p",
+				     "clk_m"};
+static const char *i2s2_parents[] = {"pll_a_out0", "audio_2x", "pll_p",
+				     "clk_m"};
+static const char *spdif_out_parents[] = {"pll_a_out0", "audio_2x", "pll_p",
+					  "clk_m"};
+static const char *spdif_in_parents[] = {"pll_p", "pll_c", "pll_m"};
+static const char *pwm_parents[] = {"pll_p", "pll_c", "audio", "clk_m",
+				    "clk_32k"};
+static const char *mux_pllpcm_clkm[] = {"pll_p", "pll_c", "pll_m", "clk_m"};
+static const char *mux_pllmcpa[] = {"pll_m", "pll_c", "pll_c", "pll_a"};
+static const char *mux_pllpdc_clkm[] = {"pll_p", "pll_d_out0", "pll_c",
+					"clk_m"};
+static const char *mux_pllmcp_clkm[] = {"pll_m", "pll_c", "pll_p", "clk_m"};
+
+static struct tegra_periph_init_data tegra_periph_clk_list[] = {
+	TEGRA_INIT_DATA_MUX("i2s1",	NULL,		"tegra20-i2s.0", i2s1_parents,	    CLK_SOURCE_I2S1,	  11,	&periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1),
+	TEGRA_INIT_DATA_MUX("i2s2",	NULL,		"tegra20-i2s.1", i2s2_parents,	    CLK_SOURCE_I2S2,	  18,	&periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2),
+	TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out",	"tegra20-spdif", spdif_out_parents, CLK_SOURCE_SPDIF_OUT, 10,	&periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out),
+	TEGRA_INIT_DATA_MUX("spdif_in",	"spdif_in",	"tegra20-spdif", spdif_in_parents,  CLK_SOURCE_SPDIF_IN,  10,	&periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in),
+	TEGRA_INIT_DATA_MUX("sbc1",	NULL,		"spi_tegra.0",	 mux_pllpcm_clkm,   CLK_SOURCE_SBC1,	  41,	&periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1),
+	TEGRA_INIT_DATA_MUX("sbc2",	NULL,		"spi_tegra.1",	 mux_pllpcm_clkm,   CLK_SOURCE_SBC2,	  44,	&periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2),
+	TEGRA_INIT_DATA_MUX("sbc3",	NULL,		"spi_tegra.2",	 mux_pllpcm_clkm,   CLK_SOURCE_SBC3,	  46,	&periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3),
+	TEGRA_INIT_DATA_MUX("sbc4",	NULL,		"spi_tegra.3",	 mux_pllpcm_clkm,   CLK_SOURCE_SBC4,	  68,	&periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4),
+	TEGRA_INIT_DATA_MUX("spi",	NULL,		"spi",		 mux_pllpcm_clkm,   CLK_SOURCE_SPI,	  43,	&periph_h_regs, TEGRA_PERIPH_ON_APB, spi),
+	TEGRA_INIT_DATA_MUX("xio",	NULL,		"xio",		 mux_pllpcm_clkm,   CLK_SOURCE_XIO,	  45,	&periph_h_regs, 0, xio),
+	TEGRA_INIT_DATA_MUX("twc",	NULL,		"twc",		 mux_pllpcm_clkm,   CLK_SOURCE_TWC,	  16,	&periph_l_regs, TEGRA_PERIPH_ON_APB, twc),
+	TEGRA_INIT_DATA_MUX("ide",	NULL,		"ide",		 mux_pllpcm_clkm,   CLK_SOURCE_XIO,	  25,	&periph_l_regs, 0, ide),
+	TEGRA_INIT_DATA_MUX("ndflash",	NULL,		"tegra_nand",	 mux_pllpcm_clkm,   CLK_SOURCE_NDFLASH,	  13,	&periph_l_regs, 0, ndflash),
+	TEGRA_INIT_DATA_MUX("vfir",	NULL,		"vfir",		 mux_pllpcm_clkm,   CLK_SOURCE_VFIR,	  7,	&periph_l_regs, TEGRA_PERIPH_ON_APB, vfir),
+	TEGRA_INIT_DATA_MUX("csite",	NULL,		"csite",	 mux_pllpcm_clkm,   CLK_SOURCE_CSITE,	  73,	&periph_u_regs, 0, csite),
+	TEGRA_INIT_DATA_MUX("la",	NULL,		"la",		 mux_pllpcm_clkm,   CLK_SOURCE_LA,	  76,	&periph_u_regs, 0, la),
+	TEGRA_INIT_DATA_MUX("owr",	NULL,		"tegra_w1",	 mux_pllpcm_clkm,   CLK_SOURCE_OWR,	  71,	&periph_u_regs, TEGRA_PERIPH_ON_APB, owr),
+	TEGRA_INIT_DATA_MUX("mipi",	NULL,		"mipi",		 mux_pllpcm_clkm,   CLK_SOURCE_MIPI,	  50,	&periph_h_regs, TEGRA_PERIPH_ON_APB, mipi),
+	TEGRA_INIT_DATA_MUX("vde",	NULL,		"vde",		 mux_pllpcm_clkm,   CLK_SOURCE_VDE,	  61,	&periph_h_regs, 0, vde),
+	TEGRA_INIT_DATA_MUX("vi",	"vi",		"tegra_camera",	 mux_pllmcpa,	    CLK_SOURCE_VI,	  20,	&periph_l_regs, 0, vi),
+	TEGRA_INIT_DATA_MUX("epp",	NULL,		"epp",		 mux_pllmcpa,	    CLK_SOURCE_EPP,	  19,	&periph_l_regs, 0, epp),
+	TEGRA_INIT_DATA_MUX("mpe",	NULL,		"mpe",		 mux_pllmcpa,	    CLK_SOURCE_MPE,	  60,	&periph_h_regs, 0, mpe),
+	TEGRA_INIT_DATA_MUX("host1x",	NULL,		"host1x",	 mux_pllmcpa,	    CLK_SOURCE_HOST1X,	  28,	&periph_l_regs, 0, host1x),
+	TEGRA_INIT_DATA_MUX("3d",	NULL,		"3d",		 mux_pllmcpa,	    CLK_SOURCE_3D,	  24,	&periph_l_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d),
+	TEGRA_INIT_DATA_MUX("2d",	NULL,		"2d",		 mux_pllmcpa,	    CLK_SOURCE_2D,	  21,	&periph_l_regs, 0, gr2d),
+	TEGRA_INIT_DATA_MUX("nor",	NULL,		"tegra-nor",	 mux_pllpcm_clkm,   CLK_SOURCE_NOR,	  42,	&periph_h_regs, 0, nor),
+	TEGRA_INIT_DATA_MUX("sdmmc1",	NULL,		"sdhci-tegra.0", mux_pllpcm_clkm,   CLK_SOURCE_SDMMC1,	  14,	&periph_l_regs, 0, sdmmc1),
+	TEGRA_INIT_DATA_MUX("sdmmc2",	NULL,		"sdhci-tegra.1", mux_pllpcm_clkm,   CLK_SOURCE_SDMMC2,	  9,	&periph_l_regs, 0, sdmmc2),
+	TEGRA_INIT_DATA_MUX("sdmmc3",	NULL,		"sdhci-tegra.2", mux_pllpcm_clkm,   CLK_SOURCE_SDMMC3,	  69,	&periph_u_regs, 0, sdmmc3),
+	TEGRA_INIT_DATA_MUX("sdmmc4",	NULL,		"sdhci-tegra.3", mux_pllpcm_clkm,   CLK_SOURCE_SDMMC4,	  15,	&periph_l_regs, 0, sdmmc4),
+	TEGRA_INIT_DATA_MUX("cve",	NULL,		"cve",		 mux_pllpdc_clkm,   CLK_SOURCE_CVE,	  49,	&periph_h_regs, 0, cve),
+	TEGRA_INIT_DATA_MUX("tvo",	NULL,		"tvo",		 mux_pllpdc_clkm,   CLK_SOURCE_TVO,	  49,	&periph_h_regs, 0, tvo),
+	TEGRA_INIT_DATA_MUX("tvdac",	NULL,		"tvdac",	 mux_pllpdc_clkm,   CLK_SOURCE_TVDAC,	  53,	&periph_h_regs, 0, tvdac),
+	TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor",	"tegra_camera",	 mux_pllmcpa,	    CLK_SOURCE_VI_SENSOR, 20,	&periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
+	TEGRA_INIT_DATA_DIV16("i2c1",	"div-clk",	"tegra-i2c.0",	 mux_pllpcm_clkm,   CLK_SOURCE_I2C1,	  12,	&periph_l_regs, TEGRA_PERIPH_ON_APB, i2c1),
+	TEGRA_INIT_DATA_DIV16("i2c2",	"div-clk",	"tegra-i2c.1",	 mux_pllpcm_clkm,   CLK_SOURCE_I2C2,	  54,	&periph_h_regs, TEGRA_PERIPH_ON_APB, i2c2),
+	TEGRA_INIT_DATA_DIV16("i2c3",	"div-clk",	"tegra-i2c.2",	 mux_pllpcm_clkm,   CLK_SOURCE_I2C3,	  67,	&periph_u_regs,	TEGRA_PERIPH_ON_APB, i2c3),
+	TEGRA_INIT_DATA_DIV16("dvc",	"div-clk",	"tegra-i2c.3",	 mux_pllpcm_clkm,   CLK_SOURCE_DVC,	  47,	&periph_h_regs,	TEGRA_PERIPH_ON_APB, dvc),
+	TEGRA_INIT_DATA_MUX("hdmi",	NULL,		"hdmi",		 mux_pllpdc_clkm,   CLK_SOURCE_HDMI,	  51,	&periph_h_regs,	0, hdmi),
+	TEGRA_INIT_DATA("pwm",		NULL,		"tegra-pwm",	 pwm_parents,	    CLK_SOURCE_PWM,	  28, 3, 0, 0, 8, 1, 0, &periph_l_regs, 17, periph_clk_enb_refcnt, TEGRA_PERIPH_ON_APB, pwm),
+};
+
+static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
+	TEGRA_INIT_DATA_NODIV("uarta",	NULL, "tegra_uart.0", mux_pllpcm_clkm, CLK_SOURCE_UARTA, 30, 2, 6,  &periph_l_regs, TEGRA_PERIPH_ON_APB, uarta),
+	TEGRA_INIT_DATA_NODIV("uartb",	NULL, "tegra_uart.1", mux_pllpcm_clkm, CLK_SOURCE_UARTB, 30, 2, 7,  &periph_l_regs, TEGRA_PERIPH_ON_APB, uartb),
+	TEGRA_INIT_DATA_NODIV("uartc",	NULL, "tegra_uart.2", mux_pllpcm_clkm, CLK_SOURCE_UARTC, 30, 2, 55, &periph_h_regs, TEGRA_PERIPH_ON_APB, uartc),
+	TEGRA_INIT_DATA_NODIV("uartd",	NULL, "tegra_uart.3", mux_pllpcm_clkm, CLK_SOURCE_UARTD, 30, 2, 65, &periph_u_regs, TEGRA_PERIPH_ON_APB, uartd),
+	TEGRA_INIT_DATA_NODIV("uarte",	NULL, "tegra_uart.4", mux_pllpcm_clkm, CLK_SOURCE_UARTE, 30, 2, 66, &periph_u_regs, TEGRA_PERIPH_ON_APB, uarte),
+	TEGRA_INIT_DATA_NODIV("disp1",	NULL, "tegradc.0",    mux_pllpdc_clkm, CLK_SOURCE_DISP1, 30, 2, 27, &periph_l_regs, 0, disp1),
+	TEGRA_INIT_DATA_NODIV("disp2",	NULL, "tegradc.1",    mux_pllpdc_clkm, CLK_SOURCE_DISP2, 30, 2, 26, &periph_l_regs, 0, disp2),
+};
+
+static void __init tegra20_periph_clk_init(void)
+{
+	struct tegra_periph_init_data *data;
+	struct clk *clk;
+	int i;
+
+	/* apbdma */
+	clk = tegra_clk_register_periph_gate("apbdma", "pclk", 0, clk_base,
+				    0, 34, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "tegra-apbdma");
+	clks[apbdma] = clk;
+
+	/* rtc */
+	clk = tegra_clk_register_periph_gate("rtc", "clk_32k",
+				    TEGRA_PERIPH_NO_RESET,
+				    clk_base, 0, 4, &periph_l_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "rtc-tegra");
+	clks[rtc] = clk;
+
+	/* timer */
+	clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base,
+				    0, 5, &periph_l_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "timer");
+	clks[timer] = clk;
+
+	/* kbc */
+	clk = tegra_clk_register_periph_gate("kbc", "clk_32k",
+				    TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB,
+				    clk_base, 0, 36, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "tegra-kbc");
+	clks[kbc] = clk;
+
+	/* csus */
+	clk = tegra_clk_register_periph_gate("csus", "clk_m",
+				    TEGRA_PERIPH_NO_RESET,
+				    clk_base, 0, 92, &periph_u_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "csus", "tengra_camera");
+	clks[csus] = clk;
+
+	/* vcp */
+	clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0,
+				    clk_base, 0, 29, &periph_l_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "vcp", "tegra-avp");
+	clks[vcp] = clk;
+
+	/* bsea */
+	clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0,
+				    clk_base, 0, 62, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "bsea", "tegra-avp");
+	clks[bsea] = clk;
+
+	/* bsev */
+	clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0,
+				    clk_base, 0, 63, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "bsev", "tegra-aes");
+	clks[bsev] = clk;
+
+	/* emc */
+	clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
+			       ARRAY_SIZE(mux_pllmcp_clkm), 0,
+			       clk_base + CLK_SOURCE_EMC,
+			       30, 2, 0, NULL);
+	clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
+				    57, &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "emc", NULL);
+	clks[emc] = clk;
+
+	/* usbd */
+	clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0,
+				    22, &periph_l_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "fsl-tegra-udc");
+	clks[usbd] = clk;
+
+	/* usb2 */
+	clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0,
+				    58, &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "tegra-ehci.1");
+	clks[usb2] = clk;
+
+	/* usb3 */
+	clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0,
+				    59, &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "tegra-ehci.2");
+	clks[usb3] = clk;
+
+	/* dsi */
+	clk = tegra_clk_register_periph_gate("dsi", "pll_d", 0, clk_base, 0,
+				    48, &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "dsi");
+	clks[dsi] = clk;
+
+	/* csi */
+	clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base,
+				    0, 52, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "csi", "tegra_camera");
+	clks[csi] = clk;
+
+	/* isp */
+	clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23,
+				    &periph_l_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "isp", "tegra_camera");
+	clks[isp] = clk;
+
+	/* pex */
+	clk = tegra_clk_register_periph_gate("pex", "clk_m", 0, clk_base, 0, 70,
+				    &periph_u_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "pex", NULL);
+	clks[pex] = clk;
+
+	/* afi */
+	clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72,
+				    &periph_u_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "afi", NULL);
+	clks[afi] = clk;
+
+	/* pcie_xclk */
+	clk = tegra_clk_register_periph_gate("pcie_xclk", "clk_m", 0, clk_base,
+				    0, 74, &periph_u_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "pcie_xclk", NULL);
+	clks[pcie_xclk] = clk;
+
+	/* cdev1 */
+	clk = clk_register_fixed_rate(NULL, "cdev1_fixed", NULL, CLK_IS_ROOT,
+				      26000000);
+	clk = tegra_clk_register_periph_gate("cdev1", "cdev1_fixed", 0,
+				    clk_base, 0, 94, &periph_u_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "cdev1", NULL);
+	clks[cdev1] = clk;
+
+	/* cdev2 */
+	clk = clk_register_fixed_rate(NULL, "cdev2_fixed", NULL, CLK_IS_ROOT,
+				      26000000);
+	clk = tegra_clk_register_periph_gate("cdev2", "cdev2_fixed", 0,
+				    clk_base, 0, 93, &periph_u_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "cdev2", NULL);
+	clks[cdev2] = clk;
+
+	for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
+		data = &tegra_periph_clk_list[i];
+		clk = tegra_clk_register_periph(data->name, data->parent_names,
+				data->num_parents, &data->periph,
+				clk_base, data->offset);
+		clk_register_clkdev(clk, data->con_id, data->dev_id);
+		clks[data->clk_id] = clk;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) {
+		data = &tegra_periph_nodiv_clk_list[i];
+		clk = tegra_clk_register_periph_nodiv(data->name,
+					data->parent_names,
+					data->num_parents, &data->periph,
+					clk_base, data->offset);
+		clk_register_clkdev(clk, data->con_id, data->dev_id);
+		clks[data->clk_id] = clk;
+	}
+}
+
+
+static void __init tegra20_fixed_clk_init(void)
+{
+	struct clk *clk;
+
+	/* clk_32k */
+	clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT,
+				      32768);
+	clk_register_clkdev(clk, "clk_32k", NULL);
+	clks[clk_32k] = clk;
+}
+
+static void __init tegra20_pmc_clk_init(void)
+{
+	struct clk *clk;
+
+	/* blink */
+	writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
+	clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
+				pmc_base + PMC_DPD_PADS_ORIDE,
+				PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
+	clk = clk_register_gate(NULL, "blink", "blink_override", 0,
+				pmc_base + PMC_CTRL,
+				PMC_CTRL_BLINK_ENB, 0, NULL);
+	clk_register_clkdev(clk, "blink", NULL);
+	clks[blink] = clk;
+}
+
+static void __init tegra20_osc_clk_init(void)
+{
+	struct clk *clk;
+	unsigned long input_freq;
+	unsigned int pll_ref_div;
+
+	input_freq = tegra20_clk_measure_input_freq();
+
+	/* clk_m */
+	clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT |
+				      CLK_IGNORE_UNUSED, input_freq);
+	clk_register_clkdev(clk, "clk_m", NULL);
+	clks[clk_m] = clk;
+
+	/* pll_ref */
+	pll_ref_div = tegra20_get_pll_ref_div();
+	clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
+					CLK_SET_RATE_PARENT, 1, pll_ref_div);
+	clk_register_clkdev(clk, "pll_ref", NULL);
+	clks[pll_ref] = clk;
+}
+
+/* Tegra20 CPU clock and reset control functions */
+static void tegra20_wait_cpu_in_reset(u32 cpu)
+{
+	unsigned int reg;
+
+	do {
+		reg = readl(clk_base +
+			    TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+		cpu_relax();
+	} while (!(reg & (1 << cpu)));	/* check CPU been reset or not */
+
+	return;
+}
+
+static void tegra20_put_cpu_in_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+	dmb();
+}
+
+static void tegra20_cpu_out_of_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+	wmb();
+}
+
+static void tegra20_enable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg & ~CPU_CLOCK(cpu),
+	       clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	barrier();
+	reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+static void tegra20_disable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg | CPU_CLOCK(cpu),
+	       clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static bool tegra20_cpu_rail_off_ready(void)
+{
+	unsigned int cpu_rst_status;
+
+	cpu_rst_status = readl(clk_base +
+			       TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+
+	return !!(cpu_rst_status & 0x2);
+}
+
+static void tegra20_cpu_clock_suspend(void)
+{
+	/* switch coresite to clk_m, save off original source */
+	tegra20_cpu_clk_sctx.clk_csite_src =
+				readl(clk_base + CLK_SOURCE_CSITE);
+	writel(3<<30, clk_base + CLK_SOURCE_CSITE);
+
+	tegra20_cpu_clk_sctx.cpu_burst =
+				readl(clk_base + CCLK_BURST_POLICY);
+	tegra20_cpu_clk_sctx.pllx_base =
+				readl(clk_base + PLLX_BASE);
+	tegra20_cpu_clk_sctx.pllx_misc =
+				readl(clk_base + PLLX_MISC);
+	tegra20_cpu_clk_sctx.cclk_divider =
+				readl(clk_base + SUPER_CCLK_DIVIDER);
+}
+
+static void tegra20_cpu_clock_resume(void)
+{
+	unsigned int reg, policy;
+
+	/* Is CPU complex already running on PLLX? */
+	reg = readl(clk_base + CCLK_BURST_POLICY);
+	policy = (reg >> CCLK_BURST_POLICY_SHIFT) & 0xF;
+
+	if (policy == CCLK_IDLE_POLICY)
+		reg = (reg >> CCLK_IDLE_POLICY_SHIFT) & 0xF;
+	else if (policy == CCLK_RUN_POLICY)
+		reg = (reg >> CCLK_RUN_POLICY_SHIFT) & 0xF;
+	else
+		BUG();
+
+	if (reg != CCLK_BURST_POLICY_PLLX) {
+		/* restore PLLX settings if CPU is on different PLL */
+		writel(tegra20_cpu_clk_sctx.pllx_misc,
+					clk_base + PLLX_MISC);
+		writel(tegra20_cpu_clk_sctx.pllx_base,
+					clk_base + PLLX_BASE);
+
+		/* wait for PLL stabilization if PLLX was enabled */
+		if (tegra20_cpu_clk_sctx.pllx_base & (1 << 30))
+			udelay(300);
+	}
+
+	/*
+	 * Restore original burst policy setting for calls resulting from CPU
+	 * LP2 in idle or system suspend.
+	 */
+	writel(tegra20_cpu_clk_sctx.cclk_divider,
+					clk_base + SUPER_CCLK_DIVIDER);
+	writel(tegra20_cpu_clk_sctx.cpu_burst,
+					clk_base + CCLK_BURST_POLICY);
+
+	writel(tegra20_cpu_clk_sctx.clk_csite_src,
+					clk_base + CLK_SOURCE_CSITE);
+}
+#endif
+
+static struct tegra_cpu_car_ops tegra20_cpu_car_ops = {
+	.wait_for_reset	= tegra20_wait_cpu_in_reset,
+	.put_in_reset	= tegra20_put_cpu_in_reset,
+	.out_of_reset	= tegra20_cpu_out_of_reset,
+	.enable_clock	= tegra20_enable_cpu_clock,
+	.disable_clock	= tegra20_disable_cpu_clock,
+#ifdef CONFIG_PM_SLEEP
+	.rail_off_ready = tegra20_cpu_rail_off_ready,
+	.suspend	= tegra20_cpu_clock_suspend,
+	.resume		= tegra20_cpu_clock_resume,
+#endif
+};
+
+static __initdata struct tegra_clk_init_table init_table[] = {
+	{pll_p, clk_max, 216000000, 1},
+	{pll_p_out1, clk_max, 28800000, 1},
+	{pll_p_out2, clk_max, 48000000, 1},
+	{pll_p_out3, clk_max, 72000000, 1},
+	{pll_p_out4, clk_max, 24000000, 1},
+	{pll_c, clk_max, 600000000, 1},
+	{pll_c_out1, clk_max, 120000000, 1},
+	{sclk, pll_c_out1, 0, 1},
+	{hclk, clk_max, 0, 1},
+	{pclk, clk_max, 60000000, 1},
+	{csite, clk_max, 0, 1},
+	{emc, clk_max, 0, 1},
+	{cclk, clk_max, 0, 1},
+	{uarta, pll_p, 0, 1},
+	{uartd, pll_p, 0, 1},
+	{usbd, clk_max, 12000000, 0},
+	{usb2, clk_max, 12000000, 0},
+	{usb3, clk_max, 12000000, 0},
+	{pll_a, clk_max, 56448000, 1},
+	{pll_a_out0, clk_max, 11289600, 1},
+	{cdev1, clk_max, 0, 1},
+	{blink, clk_max, 32768, 1},
+	{i2s1, pll_a_out0, 11289600, 0},
+	{i2s2, pll_a_out0, 11289600, 0},
+	{sdmmc1, pll_p, 48000000, 0},
+	{sdmmc3, pll_p, 48000000, 0},
+	{sdmmc4, pll_p, 48000000, 0},
+	{spi, pll_p, 20000000, 0},
+	{sbc1, pll_p, 100000000, 0},
+	{sbc2, pll_p, 100000000, 0},
+	{sbc3, pll_p, 100000000, 0},
+	{sbc4, pll_p, 100000000, 0},
+	{host1x, pll_c, 150000000, 0},
+	{disp1, pll_p, 600000000, 0},
+	{disp2, pll_p, 600000000, 0},
+	{clk_max, clk_max, 0, 0}, /* This MUST be the last entry */
+};
+
+/*
+ * Some clocks may be used by different drivers depending on the board
+ * configuration.  List those here to register them twice in the clock lookup
+ * table under two names.
+ */
+static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
+	TEGRA_CLK_DUPLICATE(usbd,   "utmip-pad",    NULL),
+	TEGRA_CLK_DUPLICATE(usbd,   "tegra-ehci.0", NULL),
+	TEGRA_CLK_DUPLICATE(usbd,   "tegra-otg",    NULL),
+	TEGRA_CLK_DUPLICATE(cclk,   NULL,           "cpu"),
+	TEGRA_CLK_DUPLICATE(twd,    "smp_twd",      NULL),
+	TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* Must be the last entry */
+};
+
+static const struct of_device_id pmc_match[] __initconst = {
+	{ .compatible = "nvidia,tegra20-pmc" },
+	{},
+};
+
+void __init tegra20_clock_init(struct device_node *np)
+{
+	int i;
+	struct device_node *node;
+
+	clk_base = of_iomap(np, 0);
+	if (!clk_base) {
+		pr_err("Can't map CAR registers\n");
+		BUG();
+	}
+
+	node = of_find_matching_node(NULL, pmc_match);
+	if (!node) {
+		pr_err("Failed to find pmc node\n");
+		BUG();
+	}
+
+	pmc_base = of_iomap(node, 0);
+	if (!pmc_base) {
+		pr_err("Can't map pmc registers\n");
+		BUG();
+	}
+
+	tegra20_osc_clk_init();
+	tegra20_pmc_clk_init();
+	tegra20_fixed_clk_init();
+	tegra20_pll_init();
+	tegra20_super_clk_init();
+	tegra20_periph_clk_init();
+	tegra20_audio_clk_init();
+
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++) {
+		if (IS_ERR(clks[i])) {
+			pr_err("Tegra20 clk %d: register failed with %ld\n",
+			       i, PTR_ERR(clks[i]));
+			BUG();
+		}
+		if (!clks[i])
+			clks[i] = ERR_PTR(-EINVAL);
+	}
+
+	tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max);
+
+	clk_data.clks = clks;
+	clk_data.clk_num = ARRAY_SIZE(clks);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+	tegra_init_from_table(init_table, clks, clk_max);
+
+	tegra_cpu_car_ops = &tegra20_cpu_car_ops;
+}
diff --git a/drivers/clk/tegra/clk-tegra30.c b/drivers/clk/tegra/clk-tegra30.c
new file mode 100644
index 0000000..a163812
--- /dev/null
+++ b/drivers/clk/tegra/clk-tegra30.c
@@ -0,0 +1,1987 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/clk/tegra.h>
+
+#include <mach/powergate.h>
+
+#include "clk.h"
+
+#define RST_DEVICES_L 0x004
+#define RST_DEVICES_H 0x008
+#define RST_DEVICES_U 0x00c
+#define RST_DEVICES_V 0x358
+#define RST_DEVICES_W 0x35c
+#define RST_DEVICES_SET_L 0x300
+#define RST_DEVICES_CLR_L 0x304
+#define RST_DEVICES_SET_H 0x308
+#define RST_DEVICES_CLR_H 0x30c
+#define RST_DEVICES_SET_U 0x310
+#define RST_DEVICES_CLR_U 0x314
+#define RST_DEVICES_SET_V 0x430
+#define RST_DEVICES_CLR_V 0x434
+#define RST_DEVICES_SET_W 0x438
+#define RST_DEVICES_CLR_W 0x43c
+#define RST_DEVICES_NUM 5
+
+#define CLK_OUT_ENB_L 0x010
+#define CLK_OUT_ENB_H 0x014
+#define CLK_OUT_ENB_U 0x018
+#define CLK_OUT_ENB_V 0x360
+#define CLK_OUT_ENB_W 0x364
+#define CLK_OUT_ENB_SET_L 0x320
+#define CLK_OUT_ENB_CLR_L 0x324
+#define CLK_OUT_ENB_SET_H 0x328
+#define CLK_OUT_ENB_CLR_H 0x32c
+#define CLK_OUT_ENB_SET_U 0x330
+#define CLK_OUT_ENB_CLR_U 0x334
+#define CLK_OUT_ENB_SET_V 0x440
+#define CLK_OUT_ENB_CLR_V 0x444
+#define CLK_OUT_ENB_SET_W 0x448
+#define CLK_OUT_ENB_CLR_W 0x44c
+#define CLK_OUT_ENB_NUM 5
+
+#define OSC_CTRL			0x50
+#define OSC_CTRL_OSC_FREQ_MASK		(0xF<<28)
+#define OSC_CTRL_OSC_FREQ_13MHZ		(0X0<<28)
+#define OSC_CTRL_OSC_FREQ_19_2MHZ	(0X4<<28)
+#define OSC_CTRL_OSC_FREQ_12MHZ		(0X8<<28)
+#define OSC_CTRL_OSC_FREQ_26MHZ		(0XC<<28)
+#define OSC_CTRL_OSC_FREQ_16_8MHZ	(0X1<<28)
+#define OSC_CTRL_OSC_FREQ_38_4MHZ	(0X5<<28)
+#define OSC_CTRL_OSC_FREQ_48MHZ		(0X9<<28)
+#define OSC_CTRL_MASK			(0x3f2 | OSC_CTRL_OSC_FREQ_MASK)
+
+#define OSC_CTRL_PLL_REF_DIV_MASK	(3<<26)
+#define OSC_CTRL_PLL_REF_DIV_1		(0<<26)
+#define OSC_CTRL_PLL_REF_DIV_2		(1<<26)
+#define OSC_CTRL_PLL_REF_DIV_4		(2<<26)
+
+#define OSC_FREQ_DET			0x58
+#define OSC_FREQ_DET_TRIG		BIT(31)
+
+#define OSC_FREQ_DET_STATUS		0x5c
+#define OSC_FREQ_DET_BUSY		BIT(31)
+#define OSC_FREQ_DET_CNT_MASK		0xffff
+
+#define CCLKG_BURST_POLICY 0x368
+#define SUPER_CCLKG_DIVIDER 0x36c
+#define CCLKLP_BURST_POLICY 0x370
+#define SUPER_CCLKLP_DIVIDER 0x374
+#define SCLK_BURST_POLICY 0x028
+#define SUPER_SCLK_DIVIDER 0x02c
+
+#define SYSTEM_CLK_RATE 0x030
+
+#define PLLC_BASE 0x80
+#define PLLC_MISC 0x8c
+#define PLLM_BASE 0x90
+#define PLLM_MISC 0x9c
+#define PLLP_BASE 0xa0
+#define PLLP_MISC 0xac
+#define PLLX_BASE 0xe0
+#define PLLX_MISC 0xe4
+#define PLLD_BASE 0xd0
+#define PLLD_MISC 0xdc
+#define PLLD2_BASE 0x4b8
+#define PLLD2_MISC 0x4bc
+#define PLLE_BASE 0xe8
+#define PLLE_MISC 0xec
+#define PLLA_BASE 0xb0
+#define PLLA_MISC 0xbc
+#define PLLU_BASE 0xc0
+#define PLLU_MISC 0xcc
+
+#define PLL_MISC_LOCK_ENABLE 18
+#define PLLDU_MISC_LOCK_ENABLE 22
+#define PLLE_MISC_LOCK_ENABLE 9
+
+#define PLL_BASE_LOCK 27
+#define PLLE_MISC_LOCK 11
+
+#define PLLE_AUX 0x48c
+#define PLLC_OUT 0x84
+#define PLLM_OUT 0x94
+#define PLLP_OUTA 0xa4
+#define PLLP_OUTB 0xa8
+#define PLLA_OUT 0xb4
+
+#define AUDIO_SYNC_CLK_I2S0 0x4a0
+#define AUDIO_SYNC_CLK_I2S1 0x4a4
+#define AUDIO_SYNC_CLK_I2S2 0x4a8
+#define AUDIO_SYNC_CLK_I2S3 0x4ac
+#define AUDIO_SYNC_CLK_I2S4 0x4b0
+#define AUDIO_SYNC_CLK_SPDIF 0x4b4
+
+#define PMC_CLK_OUT_CNTRL 0x1a8
+
+#define CLK_SOURCE_I2S0 0x1d8
+#define CLK_SOURCE_I2S1 0x100
+#define CLK_SOURCE_I2S2 0x104
+#define CLK_SOURCE_I2S3 0x3bc
+#define CLK_SOURCE_I2S4 0x3c0
+#define CLK_SOURCE_SPDIF_OUT 0x108
+#define CLK_SOURCE_SPDIF_IN 0x10c
+#define CLK_SOURCE_PWM 0x110
+#define CLK_SOURCE_D_AUDIO 0x3d0
+#define CLK_SOURCE_DAM0 0x3d8
+#define CLK_SOURCE_DAM1 0x3dc
+#define CLK_SOURCE_DAM2 0x3e0
+#define CLK_SOURCE_HDA 0x428
+#define CLK_SOURCE_HDA2CODEC_2X 0x3e4
+#define CLK_SOURCE_SBC1 0x134
+#define CLK_SOURCE_SBC2 0x118
+#define CLK_SOURCE_SBC3 0x11c
+#define CLK_SOURCE_SBC4 0x1b4
+#define CLK_SOURCE_SBC5 0x3c8
+#define CLK_SOURCE_SBC6 0x3cc
+#define CLK_SOURCE_SATA_OOB 0x420
+#define CLK_SOURCE_SATA 0x424
+#define CLK_SOURCE_NDFLASH 0x160
+#define CLK_SOURCE_NDSPEED 0x3f8
+#define CLK_SOURCE_VFIR 0x168
+#define CLK_SOURCE_SDMMC1 0x150
+#define CLK_SOURCE_SDMMC2 0x154
+#define CLK_SOURCE_SDMMC3 0x1bc
+#define CLK_SOURCE_SDMMC4 0x164
+#define CLK_SOURCE_VDE 0x1c8
+#define CLK_SOURCE_CSITE 0x1d4
+#define CLK_SOURCE_LA 0x1f8
+#define CLK_SOURCE_OWR 0x1cc
+#define CLK_SOURCE_NOR 0x1d0
+#define CLK_SOURCE_MIPI 0x174
+#define CLK_SOURCE_I2C1 0x124
+#define CLK_SOURCE_I2C2 0x198
+#define CLK_SOURCE_I2C3 0x1b8
+#define CLK_SOURCE_I2C4 0x3c4
+#define CLK_SOURCE_I2C5 0x128
+#define CLK_SOURCE_UARTA 0x178
+#define CLK_SOURCE_UARTB 0x17c
+#define CLK_SOURCE_UARTC 0x1a0
+#define CLK_SOURCE_UARTD 0x1c0
+#define CLK_SOURCE_UARTE 0x1c4
+#define CLK_SOURCE_VI 0x148
+#define CLK_SOURCE_VI_SENSOR 0x1a8
+#define CLK_SOURCE_3D 0x158
+#define CLK_SOURCE_3D2 0x3b0
+#define CLK_SOURCE_2D 0x15c
+#define CLK_SOURCE_EPP 0x16c
+#define CLK_SOURCE_MPE 0x170
+#define CLK_SOURCE_HOST1X 0x180
+#define CLK_SOURCE_CVE 0x140
+#define CLK_SOURCE_TVO 0x188
+#define CLK_SOURCE_DTV 0x1dc
+#define CLK_SOURCE_HDMI 0x18c
+#define CLK_SOURCE_TVDAC 0x194
+#define CLK_SOURCE_DISP1 0x138
+#define CLK_SOURCE_DISP2 0x13c
+#define CLK_SOURCE_DSIB 0xd0
+#define CLK_SOURCE_TSENSOR 0x3b8
+#define CLK_SOURCE_ACTMON 0x3e8
+#define CLK_SOURCE_EXTERN1 0x3ec
+#define CLK_SOURCE_EXTERN2 0x3f0
+#define CLK_SOURCE_EXTERN3 0x3f4
+#define CLK_SOURCE_I2CSLOW 0x3fc
+#define CLK_SOURCE_SE 0x42c
+#define CLK_SOURCE_MSELECT 0x3b4
+#define CLK_SOURCE_EMC 0x19c
+
+#define AUDIO_SYNC_DOUBLER 0x49c
+
+#define PMC_CTRL 0
+#define PMC_CTRL_BLINK_ENB 7
+
+#define PMC_DPD_PADS_ORIDE 0x1c
+#define PMC_DPD_PADS_ORIDE_BLINK_ENB 20
+#define PMC_BLINK_TIMER 0x40
+
+#define UTMIP_PLL_CFG2 0x488
+#define UTMIP_PLL_CFG2_STABLE_COUNT(x) (((x) & 0xffff) << 6)
+#define UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(x) (((x) & 0x3f) << 18)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN BIT(0)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN BIT(2)
+#define UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN BIT(4)
+
+#define UTMIP_PLL_CFG1 0x484
+#define UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(x) (((x) & 0x1f) << 6)
+#define UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(x) (((x) & 0xfff) << 0)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN BIT(14)
+#define UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN BIT(12)
+#define UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN BIT(16)
+
+/* Tegra CPU clock and reset control regs */
+#define TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX		0x4c
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET	0x340
+#define TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR	0x344
+#define TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR	0x34c
+#define TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS	0x470
+
+#define CPU_CLOCK(cpu)	(0x1 << (8 + cpu))
+#define CPU_RESET(cpu)	(0x1111ul << (cpu))
+
+#define CLK_RESET_CCLK_BURST	0x20
+#define CLK_RESET_CCLK_DIVIDER	0x24
+#define CLK_RESET_PLLX_BASE	0xe0
+#define CLK_RESET_PLLX_MISC	0xe4
+
+#define CLK_RESET_SOURCE_CSITE	0x1d4
+
+#define CLK_RESET_CCLK_BURST_POLICY_SHIFT	28
+#define CLK_RESET_CCLK_RUN_POLICY_SHIFT		4
+#define CLK_RESET_CCLK_IDLE_POLICY_SHIFT	0
+#define CLK_RESET_CCLK_IDLE_POLICY		1
+#define CLK_RESET_CCLK_RUN_POLICY		2
+#define CLK_RESET_CCLK_BURST_POLICY_PLLX	8
+
+#ifdef CONFIG_PM_SLEEP
+static struct cpu_clk_suspend_context {
+	u32 pllx_misc;
+	u32 pllx_base;
+
+	u32 cpu_burst;
+	u32 clk_csite_src;
+	u32 cclk_divider;
+} tegra30_cpu_clk_sctx;
+#endif
+
+static int periph_clk_enb_refcnt[CLK_OUT_ENB_NUM * 32];
+
+static void __iomem *clk_base;
+static void __iomem *pmc_base;
+static unsigned long input_freq;
+
+static DEFINE_SPINLOCK(clk_doubler_lock);
+static DEFINE_SPINLOCK(clk_out_lock);
+static DEFINE_SPINLOCK(pll_div_lock);
+static DEFINE_SPINLOCK(cml_lock);
+static DEFINE_SPINLOCK(pll_d_lock);
+
+#define TEGRA_INIT_DATA_MUX(_name, _con_id, _dev_id, _parents, _offset,	\
+			    _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,	\
+			30, 2, 0, 0, 8, 1, 0, _regs, _clk_num,		\
+			periph_clk_enb_refcnt, _gate_flags, _clk_id)
+
+#define TEGRA_INIT_DATA_DIV16(_name, _con_id, _dev_id, _parents, _offset, \
+			    _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,	\
+			30, 2, 0, 0, 16, 0, TEGRA_DIVIDER_ROUND_UP,	\
+			_regs, _clk_num, periph_clk_enb_refcnt,		\
+			_gate_flags, _clk_id)
+
+#define TEGRA_INIT_DATA_MUX8(_name, _con_id, _dev_id, _parents, _offset, \
+			     _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,	\
+			29, 3, 0, 0, 8, 1, 0, _regs, _clk_num,		\
+			periph_clk_enb_refcnt, _gate_flags, _clk_id)
+
+#define TEGRA_INIT_DATA_INT(_name, _con_id, _dev_id, _parents, _offset,	\
+			    _clk_num, _regs, _gate_flags, _clk_id)	\
+	TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,	\
+			30, 2, 0, 0, 8, 1, TEGRA_DIVIDER_INT, _regs,	\
+			_clk_num, periph_clk_enb_refcnt, _gate_flags,	\
+			_clk_id)
+
+#define TEGRA_INIT_DATA_UART(_name, _con_id, _dev_id, _parents, _offset,\
+			     _clk_num, _regs, _clk_id)			\
+	TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,	\
+			30, 2, 0, 0, 16, 1, TEGRA_DIVIDER_UART, _regs,	\
+			_clk_num, periph_clk_enb_refcnt, 0, _clk_id)
+
+#define TEGRA_INIT_DATA_NODIV(_name, _con_id, _dev_id, _parents, _offset, \
+			      _mux_shift, _mux_width, _clk_num, _regs,	\
+			      _gate_flags, _clk_id)			\
+	TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parents, _offset,	\
+			_mux_shift, _mux_width, 0, 0, 0, 0, 0, _regs,	\
+			_clk_num, periph_clk_enb_refcnt, _gate_flags,	\
+			_clk_id)
+
+/*
+ * IDs assigned here must be in sync with DT bindings definition
+ * for Tegra30 clocks.
+ */
+enum tegra30_clk {
+	cpu, rtc = 4, timer, uarta, gpio = 8, sdmmc2, i2s1 = 11, i2c1, ndflash,
+	sdmmc1, sdmmc4, pwm = 17, i2s2, epp, gr2d = 21, usbd, isp, gr3d,
+	disp2 = 26, disp1, host1x, vcp, i2s0, cop_cache, mc, ahbdma, apbdma,
+	kbc = 36, statmon, pmc, kfuse = 40, sbc1, nor, sbc2 = 44, sbc3 = 46,
+	i2c5, dsia, mipi = 50, hdmi, csi, tvdac, i2c2, uartc, emc = 57, usb2,
+	usb3, mpe, vde, bsea, bsev, speedo, uartd, uarte, i2c3, sbc4, sdmmc3,
+	pcie, owr, afi, csite, pciex, avpucq, la, dtv = 79, ndspeed, i2c_slow,
+	dsib, irama = 84, iramb, iramc, iramd, cram2, audio_2x = 90, csus = 92,
+	cdev1, cdev2, cpu_g = 96, cpu_lp, gr3d2, mselect, tsensor, i2s3, i2s4,
+	i2c4, sbc5, sbc6, d_audio, apbif, dam0, dam1, dam2, hda2codec_2x,
+	atomics, audio0_2x, audio1_2x, audio2_2x, audio3_2x, audio4_2x,
+	spdif_2x, actmon, extern1, extern2, extern3, sata_oob, sata, hda, se,
+	hda2hdmi, sata_cold, uartb = 160, vfir, spdif_out, spdif_in, vi,
+	vi_sensor, fuse, fuse_burn, cve, tvo, clk_32k, clk_m, clk_m_div2,
+	clk_m_div4, pll_ref, pll_c, pll_c_out1, pll_m, pll_m_out1, pll_p,
+	pll_p_out1, pll_p_out2, pll_p_out3, pll_p_out4, pll_a, pll_a_out0,
+	pll_d, pll_d_out0, pll_d2, pll_d2_out0, pll_u, pll_x, pll_x_out0, pll_e,
+	spdif_in_sync, i2s0_sync, i2s1_sync, i2s2_sync, i2s3_sync, i2s4_sync,
+	vimclk_sync, audio0, audio1, audio2, audio3, audio4, spdif, clk_out_1,
+	clk_out_2, clk_out_3, sclk, blink, cclk_g, cclk_lp, twd, cml0, cml1,
+	i2cslow, hclk, pclk, clk_out_1_mux = 300, clk_max
+};
+
+static struct clk *clks[clk_max];
+static struct clk_onecell_data clk_data;
+
+/*
+ * Structure defining the fields for USB UTMI clocks Parameters.
+ */
+struct utmi_clk_param {
+	/* Oscillator Frequency in KHz */
+	u32 osc_frequency;
+	/* UTMIP PLL Enable Delay Count  */
+	u8 enable_delay_count;
+	/* UTMIP PLL Stable count */
+	u8 stable_count;
+	/*  UTMIP PLL Active delay count */
+	u8 active_delay_count;
+	/* UTMIP PLL Xtal frequency count */
+	u8 xtal_freq_count;
+};
+
+static const struct utmi_clk_param utmi_parameters[] = {
+/*	OSC_FREQUENCY, ENABLE_DLY, STABLE_CNT, ACTIVE_DLY, XTAL_FREQ_CNT */
+	{13000000,     0x02,       0x33,       0x05,       0x7F},
+	{19200000,     0x03,       0x4B,       0x06,       0xBB},
+	{12000000,     0x02,       0x2F,       0x04,       0x76},
+	{26000000,     0x04,       0x66,       0x09,       0xFE},
+	{16800000,     0x03,       0x41,       0x0A,       0xA4},
+};
+
+static struct tegra_clk_pll_freq_table pll_c_freq_table[] = {
+	{ 12000000, 1040000000, 520,  6, 1, 8},
+	{ 13000000, 1040000000, 480,  6, 1, 8},
+	{ 16800000, 1040000000, 495,  8, 1, 8},	/* actual: 1039.5 MHz */
+	{ 19200000, 1040000000, 325,  6, 1, 6},
+	{ 26000000, 1040000000, 520, 13, 1, 8},
+
+	{ 12000000, 832000000, 416,  6, 1, 8},
+	{ 13000000, 832000000, 832, 13, 1, 8},
+	{ 16800000, 832000000, 396,  8, 1, 8},	/* actual: 831.6 MHz */
+	{ 19200000, 832000000, 260,  6, 1, 8},
+	{ 26000000, 832000000, 416, 13, 1, 8},
+
+	{ 12000000, 624000000, 624, 12, 1, 8},
+	{ 13000000, 624000000, 624, 13, 1, 8},
+	{ 16800000, 600000000, 520, 14, 1, 8},
+	{ 19200000, 624000000, 520, 16, 1, 8},
+	{ 26000000, 624000000, 624, 26, 1, 8},
+
+	{ 12000000, 600000000, 600, 12, 1, 8},
+	{ 13000000, 600000000, 600, 13, 1, 8},
+	{ 16800000, 600000000, 500, 14, 1, 8},
+	{ 19200000, 600000000, 375, 12, 1, 6},
+	{ 26000000, 600000000, 600, 26, 1, 8},
+
+	{ 12000000, 520000000, 520, 12, 1, 8},
+	{ 13000000, 520000000, 520, 13, 1, 8},
+	{ 16800000, 520000000, 495, 16, 1, 8},	/* actual: 519.75 MHz */
+	{ 19200000, 520000000, 325, 12, 1, 6},
+	{ 26000000, 520000000, 520, 26, 1, 8},
+
+	{ 12000000, 416000000, 416, 12, 1, 8},
+	{ 13000000, 416000000, 416, 13, 1, 8},
+	{ 16800000, 416000000, 396, 16, 1, 8},	/* actual: 415.8 MHz */
+	{ 19200000, 416000000, 260, 12, 1, 6},
+	{ 26000000, 416000000, 416, 26, 1, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_m_freq_table[] = {
+	{ 12000000, 666000000, 666, 12, 1, 8},
+	{ 13000000, 666000000, 666, 13, 1, 8},
+	{ 16800000, 666000000, 555, 14, 1, 8},
+	{ 19200000, 666000000, 555, 16, 1, 8},
+	{ 26000000, 666000000, 666, 26, 1, 8},
+	{ 12000000, 600000000, 600, 12, 1, 8},
+	{ 13000000, 600000000, 600, 13, 1, 8},
+	{ 16800000, 600000000, 500, 14, 1, 8},
+	{ 19200000, 600000000, 375, 12, 1, 6},
+	{ 26000000, 600000000, 600, 26, 1, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_p_freq_table[] = {
+	{ 12000000, 216000000, 432, 12, 2, 8},
+	{ 13000000, 216000000, 432, 13, 2, 8},
+	{ 16800000, 216000000, 360, 14, 2, 8},
+	{ 19200000, 216000000, 360, 16, 2, 8},
+	{ 26000000, 216000000, 432, 26, 2, 8},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_a_freq_table[] = {
+	{ 9600000, 564480000, 294, 5, 1, 4},
+	{ 9600000, 552960000, 288, 5, 1, 4},
+	{ 9600000, 24000000,  5,   2, 1, 1},
+
+	{ 28800000, 56448000, 49, 25, 1, 1},
+	{ 28800000, 73728000, 64, 25, 1, 1},
+	{ 28800000, 24000000,  5,  6, 1, 1},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_d_freq_table[] = {
+	{ 12000000, 216000000, 216, 12, 1, 4},
+	{ 13000000, 216000000, 216, 13, 1, 4},
+	{ 16800000, 216000000, 180, 14, 1, 4},
+	{ 19200000, 216000000, 180, 16, 1, 4},
+	{ 26000000, 216000000, 216, 26, 1, 4},
+
+	{ 12000000, 594000000, 594, 12, 1, 8},
+	{ 13000000, 594000000, 594, 13, 1, 8},
+	{ 16800000, 594000000, 495, 14, 1, 8},
+	{ 19200000, 594000000, 495, 16, 1, 8},
+	{ 26000000, 594000000, 594, 26, 1, 8},
+
+	{ 12000000, 1000000000, 1000, 12, 1, 12},
+	{ 13000000, 1000000000, 1000, 13, 1, 12},
+	{ 19200000, 1000000000, 625,  12, 1, 8},
+	{ 26000000, 1000000000, 1000, 26, 1, 12},
+
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_u_freq_table[] = {
+	{ 12000000, 480000000, 960, 12, 2, 12},
+	{ 13000000, 480000000, 960, 13, 2, 12},
+	{ 16800000, 480000000, 400, 7,  2, 5},
+	{ 19200000, 480000000, 200, 4,  2, 3},
+	{ 26000000, 480000000, 960, 26, 2, 12},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_x_freq_table[] = {
+	/* 1.7 GHz */
+	{ 12000000, 1700000000, 850,  6,  1, 8},
+	{ 13000000, 1700000000, 915,  7,  1, 8},	/* actual: 1699.2 MHz */
+	{ 16800000, 1700000000, 708,  7,  1, 8},	/* actual: 1699.2 MHz */
+	{ 19200000, 1700000000, 885,  10, 1, 8},	/* actual: 1699.2 MHz */
+	{ 26000000, 1700000000, 850,  13, 1, 8},
+
+	/* 1.6 GHz */
+	{ 12000000, 1600000000, 800,  6,  1, 8},
+	{ 13000000, 1600000000, 738,  6,  1, 8},	/* actual: 1599.0 MHz */
+	{ 16800000, 1600000000, 857,  9,  1, 8},	/* actual: 1599.7 MHz */
+	{ 19200000, 1600000000, 500,  6,  1, 8},
+	{ 26000000, 1600000000, 800,  13, 1, 8},
+
+	/* 1.5 GHz */
+	{ 12000000, 1500000000, 750,  6,  1, 8},
+	{ 13000000, 1500000000, 923,  8,  1, 8},	/* actual: 1499.8 MHz */
+	{ 16800000, 1500000000, 625,  7,  1, 8},
+	{ 19200000, 1500000000, 625,  8,  1, 8},
+	{ 26000000, 1500000000, 750,  13, 1, 8},
+
+	/* 1.4 GHz */
+	{ 12000000, 1400000000, 700,  6,  1, 8},
+	{ 13000000, 1400000000, 969,  9,  1, 8},	/* actual: 1399.7 MHz */
+	{ 16800000, 1400000000, 1000, 12, 1, 8},
+	{ 19200000, 1400000000, 875,  12, 1, 8},
+	{ 26000000, 1400000000, 700,  13, 1, 8},
+
+	/* 1.3 GHz */
+	{ 12000000, 1300000000, 975,  9,  1, 8},
+	{ 13000000, 1300000000, 1000, 10, 1, 8},
+	{ 16800000, 1300000000, 928,  12, 1, 8},	/* actual: 1299.2 MHz */
+	{ 19200000, 1300000000, 812,  12, 1, 8},	/* actual: 1299.2 MHz */
+	{ 26000000, 1300000000, 650,  13, 1, 8},
+
+	/* 1.2 GHz */
+	{ 12000000, 1200000000, 1000, 10, 1, 8},
+	{ 13000000, 1200000000, 923,  10, 1, 8},	/* actual: 1199.9 MHz */
+	{ 16800000, 1200000000, 1000, 14, 1, 8},
+	{ 19200000, 1200000000, 1000, 16, 1, 8},
+	{ 26000000, 1200000000, 600,  13, 1, 8},
+
+	/* 1.1 GHz */
+	{ 12000000, 1100000000, 825,  9,  1, 8},
+	{ 13000000, 1100000000, 846,  10, 1, 8},	/* actual: 1099.8 MHz */
+	{ 16800000, 1100000000, 982,  15, 1, 8},	/* actual: 1099.8 MHz */
+	{ 19200000, 1100000000, 859,  15, 1, 8},	/* actual: 1099.5 MHz */
+	{ 26000000, 1100000000, 550,  13, 1, 8},
+
+	/* 1 GHz */
+	{ 12000000, 1000000000, 1000, 12, 1, 8},
+	{ 13000000, 1000000000, 1000, 13, 1, 8},
+	{ 16800000, 1000000000, 833,  14, 1, 8},	/* actual: 999.6 MHz */
+	{ 19200000, 1000000000, 625,  12, 1, 8},
+	{ 26000000, 1000000000, 1000, 26, 1, 8},
+
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+static struct tegra_clk_pll_freq_table pll_e_freq_table[] = {
+	/* PLLE special case: use cpcon field to store cml divider value */
+	{ 12000000,  100000000, 150, 1,  18, 11},
+	{ 216000000, 100000000, 200, 18, 24, 13},
+	{ 0, 0, 0, 0, 0, 0 },
+};
+
+/* PLL parameters */
+static struct tegra_clk_pll_params pll_c_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 20000000,
+	.vco_max = 1400000000,
+	.base_reg = PLLC_BASE,
+	.misc_reg = PLLC_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_m_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 20000000,
+	.vco_max = 1200000000,
+	.base_reg = PLLM_BASE,
+	.misc_reg = PLLM_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_p_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 20000000,
+	.vco_max = 1400000000,
+	.base_reg = PLLP_BASE,
+	.misc_reg = PLLP_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_a_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 20000000,
+	.vco_max = 1400000000,
+	.base_reg = PLLA_BASE,
+	.misc_reg = PLLA_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_d_params = {
+	.input_min = 2000000,
+	.input_max = 40000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 40000000,
+	.vco_max = 1000000000,
+	.base_reg = PLLD_BASE,
+	.misc_reg = PLLD_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+	.lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_params pll_d2_params = {
+	.input_min = 2000000,
+	.input_max = 40000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 40000000,
+	.vco_max = 1000000000,
+	.base_reg = PLLD2_BASE,
+	.misc_reg = PLLD2_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+	.lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_params pll_u_params = {
+	.input_min = 2000000,
+	.input_max = 40000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 48000000,
+	.vco_max = 960000000,
+	.base_reg = PLLU_BASE,
+	.misc_reg = PLLU_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLLDU_MISC_LOCK_ENABLE,
+	.lock_delay = 1000,
+};
+
+static struct tegra_clk_pll_params pll_x_params = {
+	.input_min = 2000000,
+	.input_max = 31000000,
+	.cf_min = 1000000,
+	.cf_max = 6000000,
+	.vco_min = 20000000,
+	.vco_max = 1700000000,
+	.base_reg = PLLX_BASE,
+	.misc_reg = PLLX_MISC,
+	.lock_bit_idx = PLL_BASE_LOCK,
+	.lock_enable_bit_idx = PLL_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+static struct tegra_clk_pll_params pll_e_params = {
+	.input_min = 12000000,
+	.input_max = 216000000,
+	.cf_min = 12000000,
+	.cf_max = 12000000,
+	.vco_min = 1200000000,
+	.vco_max = 2400000000U,
+	.base_reg = PLLE_BASE,
+	.misc_reg = PLLE_MISC,
+	.lock_bit_idx = PLLE_MISC_LOCK,
+	.lock_enable_bit_idx = PLLE_MISC_LOCK_ENABLE,
+	.lock_delay = 300,
+};
+
+/* Peripheral clock registers */
+static struct tegra_clk_periph_regs periph_l_regs = {
+	.enb_reg = CLK_OUT_ENB_L,
+	.enb_set_reg = CLK_OUT_ENB_SET_L,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_L,
+	.rst_reg = RST_DEVICES_L,
+	.rst_set_reg = RST_DEVICES_SET_L,
+	.rst_clr_reg = RST_DEVICES_CLR_L,
+};
+
+static struct tegra_clk_periph_regs periph_h_regs = {
+	.enb_reg = CLK_OUT_ENB_H,
+	.enb_set_reg = CLK_OUT_ENB_SET_H,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_H,
+	.rst_reg = RST_DEVICES_H,
+	.rst_set_reg = RST_DEVICES_SET_H,
+	.rst_clr_reg = RST_DEVICES_CLR_H,
+};
+
+static struct tegra_clk_periph_regs periph_u_regs = {
+	.enb_reg = CLK_OUT_ENB_U,
+	.enb_set_reg = CLK_OUT_ENB_SET_U,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_U,
+	.rst_reg = RST_DEVICES_U,
+	.rst_set_reg = RST_DEVICES_SET_U,
+	.rst_clr_reg = RST_DEVICES_CLR_U,
+};
+
+static struct tegra_clk_periph_regs periph_v_regs = {
+	.enb_reg = CLK_OUT_ENB_V,
+	.enb_set_reg = CLK_OUT_ENB_SET_V,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_V,
+	.rst_reg = RST_DEVICES_V,
+	.rst_set_reg = RST_DEVICES_SET_V,
+	.rst_clr_reg = RST_DEVICES_CLR_V,
+};
+
+static struct tegra_clk_periph_regs periph_w_regs = {
+	.enb_reg = CLK_OUT_ENB_W,
+	.enb_set_reg = CLK_OUT_ENB_SET_W,
+	.enb_clr_reg = CLK_OUT_ENB_CLR_W,
+	.rst_reg = RST_DEVICES_W,
+	.rst_set_reg = RST_DEVICES_SET_W,
+	.rst_clr_reg = RST_DEVICES_CLR_W,
+};
+
+static void tegra30_clk_measure_input_freq(void)
+{
+	u32 osc_ctrl = readl_relaxed(clk_base + OSC_CTRL);
+	u32 auto_clk_control = osc_ctrl & OSC_CTRL_OSC_FREQ_MASK;
+	u32 pll_ref_div = osc_ctrl & OSC_CTRL_PLL_REF_DIV_MASK;
+
+	switch (auto_clk_control) {
+	case OSC_CTRL_OSC_FREQ_12MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+		input_freq = 12000000;
+		break;
+	case OSC_CTRL_OSC_FREQ_13MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+		input_freq = 13000000;
+		break;
+	case OSC_CTRL_OSC_FREQ_19_2MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+		input_freq = 19200000;
+		break;
+	case OSC_CTRL_OSC_FREQ_26MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+		input_freq = 26000000;
+		break;
+	case OSC_CTRL_OSC_FREQ_16_8MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_1);
+		input_freq = 16800000;
+		break;
+	case OSC_CTRL_OSC_FREQ_38_4MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_2);
+		input_freq = 38400000;
+		break;
+	case OSC_CTRL_OSC_FREQ_48MHZ:
+		BUG_ON(pll_ref_div != OSC_CTRL_PLL_REF_DIV_4);
+		input_freq = 48000000;
+		break;
+	default:
+		pr_err("Unexpected auto clock control value %d",
+			auto_clk_control);
+		BUG();
+		return;
+	}
+}
+
+static unsigned int tegra30_get_pll_ref_div(void)
+{
+	u32 pll_ref_div = readl_relaxed(clk_base + OSC_CTRL) &
+					OSC_CTRL_PLL_REF_DIV_MASK;
+
+	switch (pll_ref_div) {
+	case OSC_CTRL_PLL_REF_DIV_1:
+		return 1;
+	case OSC_CTRL_PLL_REF_DIV_2:
+		return 2;
+	case OSC_CTRL_PLL_REF_DIV_4:
+		return 4;
+	default:
+		pr_err("Invalid pll ref divider %d", pll_ref_div);
+		BUG();
+	}
+	return 0;
+}
+
+static void tegra30_utmi_param_configure(void)
+{
+	u32 reg;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(utmi_parameters); i++) {
+		if (input_freq == utmi_parameters[i].osc_frequency)
+			break;
+	}
+
+	if (i >= ARRAY_SIZE(utmi_parameters)) {
+		pr_err("%s: Unexpected input rate %lu\n", __func__, input_freq);
+		return;
+	}
+
+	reg = readl_relaxed(clk_base + UTMIP_PLL_CFG2);
+
+	/* Program UTMIP PLL stable and active counts */
+	reg &= ~UTMIP_PLL_CFG2_STABLE_COUNT(~0);
+	reg |= UTMIP_PLL_CFG2_STABLE_COUNT(
+			utmi_parameters[i].stable_count);
+
+	reg &= ~UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(~0);
+
+	reg |= UTMIP_PLL_CFG2_ACTIVE_DLY_COUNT(
+			utmi_parameters[i].active_delay_count);
+
+	/* Remove power downs from UTMIP PLL control bits */
+	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_A_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_B_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG2_FORCE_PD_SAMP_C_POWERDOWN;
+
+	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG2);
+
+	/* Program UTMIP PLL delay and oscillator frequency counts */
+	reg = readl_relaxed(clk_base + UTMIP_PLL_CFG1);
+	reg &= ~UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(~0);
+
+	reg |= UTMIP_PLL_CFG1_ENABLE_DLY_COUNT(
+		utmi_parameters[i].enable_delay_count);
+
+	reg &= ~UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(~0);
+	reg |= UTMIP_PLL_CFG1_XTAL_FREQ_COUNT(
+		utmi_parameters[i].xtal_freq_count);
+
+	/* Remove power downs from UTMIP PLL control bits */
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ENABLE_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLL_ACTIVE_POWERDOWN;
+	reg &= ~UTMIP_PLL_CFG1_FORCE_PLLU_POWERDOWN;
+
+	writel_relaxed(reg, clk_base + UTMIP_PLL_CFG1);
+}
+
+static const char *pll_e_parents[] = {"pll_ref", "pll_p"};
+
+static void __init tegra30_pll_init(void)
+{
+	struct clk *clk;
+
+	/* PLLC */
+	clk = tegra_clk_register_pll("pll_c", "pll_ref", clk_base, pmc_base, 0,
+			    0, &pll_c_params,
+			    TEGRA_PLL_HAS_CPCON | TEGRA_PLL_USE_LOCK,
+			    pll_c_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_c", NULL);
+	clks[pll_c] = clk;
+
+	/* PLLC_OUT1 */
+	clk = tegra_clk_register_divider("pll_c_out1_div", "pll_c",
+				clk_base + PLLC_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_c_out1", "pll_c_out1_div",
+				clk_base + PLLC_OUT, 1, 0, CLK_SET_RATE_PARENT,
+				0, NULL);
+	clk_register_clkdev(clk, "pll_c_out1", NULL);
+	clks[pll_c_out1] = clk;
+
+	/* PLLP */
+	clk = tegra_clk_register_pll("pll_p", "pll_ref", clk_base, pmc_base, 0,
+			    408000000, &pll_p_params,
+			    TEGRA_PLL_FIXED | TEGRA_PLL_HAS_CPCON |
+			    TEGRA_PLL_USE_LOCK, pll_p_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_p", NULL);
+	clks[pll_p] = clk;
+
+	/* PLLP_OUT1 */
+	clk = tegra_clk_register_divider("pll_p_out1_div", "pll_p",
+				clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
+				TEGRA_DIVIDER_ROUND_UP, 8, 8, 1,
+				&pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out1", "pll_p_out1_div",
+				clk_base + PLLP_OUTA, 1, 0,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out1", NULL);
+	clks[pll_p_out1] = clk;
+
+	/* PLLP_OUT2 */
+	clk = tegra_clk_register_divider("pll_p_out2_div", "pll_p",
+				clk_base + PLLP_OUTA, 0, TEGRA_DIVIDER_FIXED |
+				TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
+				&pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out2", "pll_p_out2_div",
+				clk_base + PLLP_OUTA, 17, 16,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out2", NULL);
+	clks[pll_p_out2] = clk;
+
+	/* PLLP_OUT3 */
+	clk = tegra_clk_register_divider("pll_p_out3_div", "pll_p",
+				clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
+				TEGRA_DIVIDER_ROUND_UP, 8, 8, 1,
+				&pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out3", "pll_p_out3_div",
+				clk_base + PLLP_OUTB, 1, 0,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out3", NULL);
+	clks[pll_p_out3] = clk;
+
+	/* PLLP_OUT4 */
+	clk = tegra_clk_register_divider("pll_p_out4_div", "pll_p",
+				clk_base + PLLP_OUTB, 0, TEGRA_DIVIDER_FIXED |
+				TEGRA_DIVIDER_ROUND_UP, 24, 8, 1,
+				&pll_div_lock);
+	clk = tegra_clk_register_pll_out("pll_p_out4", "pll_p_out4_div",
+				clk_base + PLLP_OUTB, 17, 16,
+				CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0,
+				&pll_div_lock);
+	clk_register_clkdev(clk, "pll_p_out4", NULL);
+	clks[pll_p_out4] = clk;
+
+	/* PLLM */
+	clk = tegra_clk_register_pll("pll_m", "pll_ref", clk_base, pmc_base,
+			    CLK_IGNORE_UNUSED | CLK_SET_RATE_GATE, 0,
+			    &pll_m_params, TEGRA_PLLM | TEGRA_PLL_HAS_CPCON |
+			    TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK,
+			    pll_m_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_m", NULL);
+	clks[pll_m] = clk;
+
+	/* PLLM_OUT1 */
+	clk = tegra_clk_register_divider("pll_m_out1_div", "pll_m",
+				clk_base + PLLM_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_m_out1", "pll_m_out1_div",
+				clk_base + PLLM_OUT, 1, 0, CLK_IGNORE_UNUSED |
+				CLK_SET_RATE_PARENT, 0, NULL);
+	clk_register_clkdev(clk, "pll_m_out1", NULL);
+	clks[pll_m_out1] = clk;
+
+	/* PLLX */
+	clk = tegra_clk_register_pll("pll_x", "pll_ref", clk_base, pmc_base, 0,
+			    0, &pll_x_params, TEGRA_PLL_HAS_CPCON |
+			    TEGRA_PLL_SET_DCCON | TEGRA_PLL_USE_LOCK,
+			    pll_x_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_x", NULL);
+	clks[pll_x] = clk;
+
+	/* PLLX_OUT0 */
+	clk = clk_register_fixed_factor(NULL, "pll_x_out0", "pll_x",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll_x_out0", NULL);
+	clks[pll_x_out0] = clk;
+
+	/* PLLU */
+	clk = tegra_clk_register_pll("pll_u", "pll_ref", clk_base, pmc_base, 0,
+			    0, &pll_u_params, TEGRA_PLLU | TEGRA_PLL_HAS_CPCON |
+			    TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK,
+			    pll_u_freq_table,
+			    NULL);
+	clk_register_clkdev(clk, "pll_u", NULL);
+	clks[pll_u] = clk;
+
+	tegra30_utmi_param_configure();
+
+	/* PLLD */
+	clk = tegra_clk_register_pll("pll_d", "pll_ref", clk_base, pmc_base, 0,
+			    0, &pll_d_params, TEGRA_PLL_HAS_CPCON |
+			    TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK,
+			    pll_d_freq_table, &pll_d_lock);
+	clk_register_clkdev(clk, "pll_d", NULL);
+	clks[pll_d] = clk;
+
+	/* PLLD_OUT0 */
+	clk = clk_register_fixed_factor(NULL, "pll_d_out0", "pll_d",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll_d_out0", NULL);
+	clks[pll_d_out0] = clk;
+
+	/* PLLD2 */
+	clk = tegra_clk_register_pll("pll_d2", "pll_ref", clk_base, pmc_base, 0,
+			    0, &pll_d2_params, TEGRA_PLL_HAS_CPCON |
+			    TEGRA_PLL_SET_LFCON | TEGRA_PLL_USE_LOCK,
+			    pll_d_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_d2", NULL);
+	clks[pll_d2] = clk;
+
+	/* PLLD2_OUT0 */
+	clk = clk_register_fixed_factor(NULL, "pll_d2_out0", "pll_d2",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "pll_d2_out0", NULL);
+	clks[pll_d2_out0] = clk;
+
+	/* PLLA */
+	clk = tegra_clk_register_pll("pll_a", "pll_p_out1", clk_base, pmc_base,
+			    0, 0, &pll_a_params, TEGRA_PLL_HAS_CPCON |
+			    TEGRA_PLL_USE_LOCK, pll_a_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_a", NULL);
+	clks[pll_a] = clk;
+
+	/* PLLA_OUT0 */
+	clk = tegra_clk_register_divider("pll_a_out0_div", "pll_a",
+				clk_base + PLLA_OUT, 0, TEGRA_DIVIDER_ROUND_UP,
+				8, 8, 1, NULL);
+	clk = tegra_clk_register_pll_out("pll_a_out0", "pll_a_out0_div",
+				clk_base + PLLA_OUT, 1, 0, CLK_IGNORE_UNUSED |
+				CLK_SET_RATE_PARENT, 0, NULL);
+	clk_register_clkdev(clk, "pll_a_out0", NULL);
+	clks[pll_a_out0] = clk;
+
+	/* PLLE */
+	clk = clk_register_mux(NULL, "pll_e_mux", pll_e_parents,
+			       ARRAY_SIZE(pll_e_parents), 0,
+			       clk_base + PLLE_AUX, 2, 1, 0, NULL);
+	clk = tegra_clk_register_plle("pll_e", "pll_e_mux", clk_base, pmc_base,
+			     CLK_GET_RATE_NOCACHE, 100000000, &pll_e_params,
+			     TEGRA_PLLE_CONFIGURE, pll_e_freq_table, NULL);
+	clk_register_clkdev(clk, "pll_e", NULL);
+	clks[pll_e] = clk;
+}
+
+static const char *mux_audio_sync_clk[] = { "spdif_in_sync", "i2s0_sync",
+	"i2s1_sync", "i2s2_sync", "i2s3_sync", "i2s4_sync", "vimclk_sync",};
+static const char *clk_out1_parents[] = { "clk_m", "clk_m_div2",
+					  "clk_m_div4", "extern1", };
+static const char *clk_out2_parents[] = { "clk_m", "clk_m_div2",
+					  "clk_m_div4", "extern2", };
+static const char *clk_out3_parents[] = { "clk_m", "clk_m_div2",
+					  "clk_m_div4", "extern3", };
+
+static void __init tegra30_audio_clk_init(void)
+{
+	struct clk *clk;
+
+	/* spdif_in_sync */
+	clk = tegra_clk_register_sync_source("spdif_in_sync", 24000000,
+					     24000000);
+	clk_register_clkdev(clk, "spdif_in_sync", NULL);
+	clks[spdif_in_sync] = clk;
+
+	/* i2s0_sync */
+	clk = tegra_clk_register_sync_source("i2s0_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "i2s0_sync", NULL);
+	clks[i2s0_sync] = clk;
+
+	/* i2s1_sync */
+	clk = tegra_clk_register_sync_source("i2s1_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "i2s1_sync", NULL);
+	clks[i2s1_sync] = clk;
+
+	/* i2s2_sync */
+	clk = tegra_clk_register_sync_source("i2s2_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "i2s2_sync", NULL);
+	clks[i2s2_sync] = clk;
+
+	/* i2s3_sync */
+	clk = tegra_clk_register_sync_source("i2s3_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "i2s3_sync", NULL);
+	clks[i2s3_sync] = clk;
+
+	/* i2s4_sync */
+	clk = tegra_clk_register_sync_source("i2s4_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "i2s4_sync", NULL);
+	clks[i2s4_sync] = clk;
+
+	/* vimclk_sync */
+	clk = tegra_clk_register_sync_source("vimclk_sync", 24000000, 24000000);
+	clk_register_clkdev(clk, "vimclk_sync", NULL);
+	clks[vimclk_sync] = clk;
+
+	/* audio0 */
+	clk = clk_register_mux(NULL, "audio0_mux", mux_audio_sync_clk,
+				ARRAY_SIZE(mux_audio_sync_clk), 0,
+				clk_base + AUDIO_SYNC_CLK_I2S0, 0, 3, 0, NULL);
+	clk = clk_register_gate(NULL, "audio0", "audio0_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_I2S0, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio0", NULL);
+	clks[audio0] = clk;
+
+	/* audio1 */
+	clk = clk_register_mux(NULL, "audio1_mux", mux_audio_sync_clk,
+				ARRAY_SIZE(mux_audio_sync_clk), 0,
+				clk_base + AUDIO_SYNC_CLK_I2S1, 0, 3, 0, NULL);
+	clk = clk_register_gate(NULL, "audio1", "audio1_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_I2S1, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio1", NULL);
+	clks[audio1] = clk;
+
+	/* audio2 */
+	clk = clk_register_mux(NULL, "audio2_mux", mux_audio_sync_clk,
+				ARRAY_SIZE(mux_audio_sync_clk), 0,
+				clk_base + AUDIO_SYNC_CLK_I2S2, 0, 3, 0, NULL);
+	clk = clk_register_gate(NULL, "audio2", "audio2_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_I2S2, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio2", NULL);
+	clks[audio2] = clk;
+
+	/* audio3 */
+	clk = clk_register_mux(NULL, "audio3_mux", mux_audio_sync_clk,
+				ARRAY_SIZE(mux_audio_sync_clk), 0,
+				clk_base + AUDIO_SYNC_CLK_I2S3, 0, 3, 0, NULL);
+	clk = clk_register_gate(NULL, "audio3", "audio3_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_I2S3, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio3", NULL);
+	clks[audio3] = clk;
+
+	/* audio4 */
+	clk = clk_register_mux(NULL, "audio4_mux", mux_audio_sync_clk,
+				ARRAY_SIZE(mux_audio_sync_clk), 0,
+				clk_base + AUDIO_SYNC_CLK_I2S4, 0, 3, 0, NULL);
+	clk = clk_register_gate(NULL, "audio4", "audio4_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_I2S4, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "audio4", NULL);
+	clks[audio4] = clk;
+
+	/* spdif */
+	clk = clk_register_mux(NULL, "spdif_mux", mux_audio_sync_clk,
+				ARRAY_SIZE(mux_audio_sync_clk), 0,
+				clk_base + AUDIO_SYNC_CLK_SPDIF, 0, 3, 0, NULL);
+	clk = clk_register_gate(NULL, "spdif", "spdif_mux", 0,
+				clk_base + AUDIO_SYNC_CLK_SPDIF, 4,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "spdif", NULL);
+	clks[spdif] = clk;
+
+	/* audio0_2x */
+	clk = clk_register_fixed_factor(NULL, "audio0_doubler", "audio0",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("audio0_div", "audio0_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 24, 1, 0,
+				&clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("audio0_2x", "audio0_div",
+				    TEGRA_PERIPH_NO_RESET, clk_base,
+				    CLK_SET_RATE_PARENT, 113, &periph_v_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio0_2x", NULL);
+	clks[audio0_2x] = clk;
+
+	/* audio1_2x */
+	clk = clk_register_fixed_factor(NULL, "audio1_doubler", "audio1",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("audio1_div", "audio1_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 25, 1, 0,
+				&clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("audio1_2x", "audio1_div",
+				    TEGRA_PERIPH_NO_RESET, clk_base,
+				    CLK_SET_RATE_PARENT, 114, &periph_v_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio1_2x", NULL);
+	clks[audio1_2x] = clk;
+
+	/* audio2_2x */
+	clk = clk_register_fixed_factor(NULL, "audio2_doubler", "audio2",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("audio2_div", "audio2_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 26, 1, 0,
+				&clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("audio2_2x", "audio2_div",
+				    TEGRA_PERIPH_NO_RESET, clk_base,
+				    CLK_SET_RATE_PARENT, 115, &periph_v_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio2_2x", NULL);
+	clks[audio2_2x] = clk;
+
+	/* audio3_2x */
+	clk = clk_register_fixed_factor(NULL, "audio3_doubler", "audio3",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("audio3_div", "audio3_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 27, 1, 0,
+				&clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("audio3_2x", "audio3_div",
+				    TEGRA_PERIPH_NO_RESET, clk_base,
+				    CLK_SET_RATE_PARENT, 116, &periph_v_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio3_2x", NULL);
+	clks[audio3_2x] = clk;
+
+	/* audio4_2x */
+	clk = clk_register_fixed_factor(NULL, "audio4_doubler", "audio4",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("audio4_div", "audio4_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 28, 1, 0,
+				&clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("audio4_2x", "audio4_div",
+				    TEGRA_PERIPH_NO_RESET, clk_base,
+				    CLK_SET_RATE_PARENT, 117, &periph_v_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "audio4_2x", NULL);
+	clks[audio4_2x] = clk;
+
+	/* spdif_2x */
+	clk = clk_register_fixed_factor(NULL, "spdif_doubler", "spdif",
+					CLK_SET_RATE_PARENT, 2, 1);
+	clk = tegra_clk_register_divider("spdif_div", "spdif_doubler",
+				clk_base + AUDIO_SYNC_DOUBLER, 0, 0, 29, 1, 0,
+				&clk_doubler_lock);
+	clk = tegra_clk_register_periph_gate("spdif_2x", "spdif_div",
+				    TEGRA_PERIPH_NO_RESET, clk_base,
+				    CLK_SET_RATE_PARENT, 118, &periph_v_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "spdif_2x", NULL);
+	clks[spdif_2x] = clk;
+}
+
+static void __init tegra30_pmc_clk_init(void)
+{
+	struct clk *clk;
+
+	/* clk_out_1 */
+	clk = clk_register_mux(NULL, "clk_out_1_mux", clk_out1_parents,
+			       ARRAY_SIZE(clk_out1_parents), 0,
+			       pmc_base + PMC_CLK_OUT_CNTRL, 6, 3, 0,
+			       &clk_out_lock);
+	clks[clk_out_1_mux] = clk;
+	clk = clk_register_gate(NULL, "clk_out_1", "clk_out_1_mux", 0,
+				pmc_base + PMC_CLK_OUT_CNTRL, 2, 0,
+				&clk_out_lock);
+	clk_register_clkdev(clk, "extern1", "clk_out_1");
+	clks[clk_out_1] = clk;
+
+	/* clk_out_2 */
+	clk = clk_register_mux(NULL, "clk_out_2_mux", clk_out2_parents,
+			       ARRAY_SIZE(clk_out1_parents), 0,
+			       pmc_base + PMC_CLK_OUT_CNTRL, 14, 3, 0,
+			       &clk_out_lock);
+	clk = clk_register_gate(NULL, "clk_out_2", "clk_out_2_mux", 0,
+				pmc_base + PMC_CLK_OUT_CNTRL, 10, 0,
+				&clk_out_lock);
+	clk_register_clkdev(clk, "extern2", "clk_out_2");
+	clks[clk_out_2] = clk;
+
+	/* clk_out_3 */
+	clk = clk_register_mux(NULL, "clk_out_3_mux", clk_out3_parents,
+			       ARRAY_SIZE(clk_out1_parents), 0,
+			       pmc_base + PMC_CLK_OUT_CNTRL, 22, 3, 0,
+			       &clk_out_lock);
+	clk = clk_register_gate(NULL, "clk_out_3", "clk_out_3_mux", 0,
+				pmc_base + PMC_CLK_OUT_CNTRL, 18, 0,
+				&clk_out_lock);
+	clk_register_clkdev(clk, "extern3", "clk_out_3");
+	clks[clk_out_3] = clk;
+
+	/* blink */
+	writel_relaxed(0, pmc_base + PMC_BLINK_TIMER);
+	clk = clk_register_gate(NULL, "blink_override", "clk_32k", 0,
+				pmc_base + PMC_DPD_PADS_ORIDE,
+				PMC_DPD_PADS_ORIDE_BLINK_ENB, 0, NULL);
+	clk = clk_register_gate(NULL, "blink", "blink_override", 0,
+				pmc_base + PMC_CTRL,
+				PMC_CTRL_BLINK_ENB, 0, NULL);
+	clk_register_clkdev(clk, "blink", NULL);
+	clks[blink] = clk;
+
+}
+
+const char *cclk_g_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+				 "pll_p_cclkg", "pll_p_out4_cclkg",
+				 "pll_p_out3_cclkg", "unused", "pll_x" };
+const char *cclk_lp_parents[] = { "clk_m", "pll_c", "clk_32k", "pll_m",
+				  "pll_p_cclklp", "pll_p_out4_cclklp",
+				  "pll_p_out3_cclklp", "unused", "pll_x",
+				  "pll_x_out0" };
+const char *sclk_parents[] = { "clk_m", "pll_c_out1", "pll_p_out4",
+			       "pll_p_out3", "pll_p_out2", "unused",
+			       "clk_32k", "pll_m_out1" };
+
+static void __init tegra30_super_clk_init(void)
+{
+	struct clk *clk;
+
+	/*
+	 * Clock input to cclk_g divided from pll_p using
+	 * U71 divider of cclk_g.
+	 */
+	clk = tegra_clk_register_divider("pll_p_cclkg", "pll_p",
+				clk_base + SUPER_CCLKG_DIVIDER, 0,
+				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
+	clk_register_clkdev(clk, "pll_p_cclkg", NULL);
+
+	/*
+	 * Clock input to cclk_g divided from pll_p_out3 using
+	 * U71 divider of cclk_g.
+	 */
+	clk = tegra_clk_register_divider("pll_p_out3_cclkg", "pll_p_out3",
+				clk_base + SUPER_CCLKG_DIVIDER, 0,
+				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
+	clk_register_clkdev(clk, "pll_p_out3_cclkg", NULL);
+
+	/*
+	 * Clock input to cclk_g divided from pll_p_out4 using
+	 * U71 divider of cclk_g.
+	 */
+	clk = tegra_clk_register_divider("pll_p_out4_cclkg", "pll_p_out4",
+				clk_base + SUPER_CCLKG_DIVIDER, 0,
+				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
+	clk_register_clkdev(clk, "pll_p_out4_cclkg", NULL);
+
+	/* CCLKG */
+	clk = tegra_clk_register_super_mux("cclk_g", cclk_g_parents,
+				  ARRAY_SIZE(cclk_g_parents),
+				  CLK_SET_RATE_PARENT,
+				  clk_base + CCLKG_BURST_POLICY,
+				  0, 4, 0, 0, NULL);
+	clk_register_clkdev(clk, "cclk_g", NULL);
+	clks[cclk_g] = clk;
+
+	/*
+	 * Clock input to cclk_lp divided from pll_p using
+	 * U71 divider of cclk_lp.
+	 */
+	clk = tegra_clk_register_divider("pll_p_cclklp", "pll_p",
+				clk_base + SUPER_CCLKLP_DIVIDER, 0,
+				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
+	clk_register_clkdev(clk, "pll_p_cclklp", NULL);
+
+	/*
+	 * Clock input to cclk_lp divided from pll_p_out3 using
+	 * U71 divider of cclk_lp.
+	 */
+	clk = tegra_clk_register_divider("pll_p_out3_cclklp", "pll_p_out3",
+				clk_base + SUPER_CCLKG_DIVIDER, 0,
+				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
+	clk_register_clkdev(clk, "pll_p_out3_cclklp", NULL);
+
+	/*
+	 * Clock input to cclk_lp divided from pll_p_out4 using
+	 * U71 divider of cclk_lp.
+	 */
+	clk = tegra_clk_register_divider("pll_p_out4_cclklp", "pll_p_out4",
+				clk_base + SUPER_CCLKLP_DIVIDER, 0,
+				TEGRA_DIVIDER_INT, 16, 8, 1, NULL);
+	clk_register_clkdev(clk, "pll_p_out4_cclklp", NULL);
+
+	/* CCLKLP */
+	clk = tegra_clk_register_super_mux("cclk_lp", cclk_lp_parents,
+				  ARRAY_SIZE(cclk_lp_parents),
+				  CLK_SET_RATE_PARENT,
+				  clk_base + CCLKLP_BURST_POLICY,
+				  TEGRA_DIVIDER_2, 4, 8, 9,
+			      NULL);
+	clk_register_clkdev(clk, "cclk_lp", NULL);
+	clks[cclk_lp] = clk;
+
+	/* SCLK */
+	clk = tegra_clk_register_super_mux("sclk", sclk_parents,
+				  ARRAY_SIZE(sclk_parents),
+				  CLK_SET_RATE_PARENT,
+				  clk_base + SCLK_BURST_POLICY,
+				  0, 4, 0, 0, NULL);
+	clk_register_clkdev(clk, "sclk", NULL);
+	clks[sclk] = clk;
+
+	/* HCLK */
+	clk = clk_register_divider(NULL, "hclk_div", "sclk", 0,
+				   clk_base + SYSTEM_CLK_RATE, 4, 2, 0, NULL);
+	clk = clk_register_gate(NULL, "hclk", "hclk_div", CLK_SET_RATE_PARENT,
+				clk_base + SYSTEM_CLK_RATE, 7,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "hclk", NULL);
+	clks[hclk] = clk;
+
+	/* PCLK */
+	clk = clk_register_divider(NULL, "pclk_div", "hclk", 0,
+				   clk_base + SYSTEM_CLK_RATE, 0, 2, 0, NULL);
+	clk = clk_register_gate(NULL, "pclk", "pclk_div", CLK_SET_RATE_PARENT,
+				clk_base + SYSTEM_CLK_RATE, 3,
+				CLK_GATE_SET_TO_DISABLE, NULL);
+	clk_register_clkdev(clk, "pclk", NULL);
+	clks[pclk] = clk;
+
+	/* twd */
+	clk = clk_register_fixed_factor(NULL, "twd", "cclk_g",
+					CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "twd", NULL);
+	clks[twd] = clk;
+}
+
+static const char *mux_pllacp_clkm[] = { "pll_a_out0", "unused", "pll_p",
+					 "clk_m" };
+static const char *mux_pllpcm_clkm[] = { "pll_p", "pll_c", "pll_m", "clk_m" };
+static const char *mux_pllmcp_clkm[] = { "pll_m", "pll_c", "pll_p", "clk_m" };
+static const char *i2s0_parents[] = { "pll_a_out0", "audio0_2x", "pll_p",
+				      "clk_m" };
+static const char *i2s1_parents[] = { "pll_a_out0", "audio1_2x", "pll_p",
+				      "clk_m" };
+static const char *i2s2_parents[] = { "pll_a_out0", "audio2_2x", "pll_p",
+				      "clk_m" };
+static const char *i2s3_parents[] = { "pll_a_out0", "audio3_2x", "pll_p",
+				      "clk_m" };
+static const char *i2s4_parents[] = { "pll_a_out0", "audio4_2x", "pll_p",
+				      "clk_m" };
+static const char *spdif_out_parents[] = { "pll_a_out0", "spdif_2x", "pll_p",
+					   "clk_m" };
+static const char *spdif_in_parents[] = { "pll_p", "pll_c", "pll_m" };
+static const char *mux_pllpc_clk32k_clkm[] = { "pll_p", "pll_c", "clk_32k",
+					       "clk_m" };
+static const char *mux_pllpc_clkm_clk32k[] = { "pll_p", "pll_c", "clk_m",
+					       "clk_32k" };
+static const char *mux_pllmcpa[] = { "pll_m", "pll_c", "pll_p", "pll_a_out0" };
+static const char *mux_pllpdc_clkm[] = { "pll_p", "pll_d_out0", "pll_c",
+					 "clk_m" };
+static const char *mux_pllp_clkm[] = { "pll_p", "unused", "unused", "clk_m" };
+static const char *mux_pllpmdacd2_clkm[] = { "pll_p", "pll_m", "pll_d_out0",
+					     "pll_a_out0", "pll_c",
+					     "pll_d2_out0", "clk_m" };
+static const char *mux_plla_clk32k_pllp_clkm_plle[] = { "pll_a_out0",
+							"clk_32k", "pll_p",
+							"clk_m", "pll_e" };
+static const char *mux_plld_out0_plld2_out0[] = { "pll_d_out0",
+						  "pll_d2_out0" };
+
+static struct tegra_periph_init_data tegra_periph_clk_list[] = {
+	TEGRA_INIT_DATA_MUX("i2s0",	NULL,		"tegra30-i2s.0",	i2s0_parents,		CLK_SOURCE_I2S0,	30,	&periph_l_regs, TEGRA_PERIPH_ON_APB, i2s0),
+	TEGRA_INIT_DATA_MUX("i2s1",	NULL,		"tegra30-i2s.1",	i2s1_parents,		CLK_SOURCE_I2S1,	11,	&periph_l_regs, TEGRA_PERIPH_ON_APB, i2s1),
+	TEGRA_INIT_DATA_MUX("i2s2",	NULL,		"tegra30-i2s.2",	i2s2_parents,		CLK_SOURCE_I2S2,	18,	&periph_l_regs, TEGRA_PERIPH_ON_APB, i2s2),
+	TEGRA_INIT_DATA_MUX("i2s3",	NULL,		"tegra30-i2s.3",	i2s3_parents,		CLK_SOURCE_I2S3,	101,	&periph_v_regs, TEGRA_PERIPH_ON_APB, i2s3),
+	TEGRA_INIT_DATA_MUX("i2s4",	NULL,		"tegra30-i2s.4",	i2s4_parents,		CLK_SOURCE_I2S4,	102,	&periph_v_regs, TEGRA_PERIPH_ON_APB, i2s4),
+	TEGRA_INIT_DATA_MUX("spdif_out", "spdif_out",	"tegra30-spdif",	spdif_out_parents,	CLK_SOURCE_SPDIF_OUT,	10,	&periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_out),
+	TEGRA_INIT_DATA_MUX("spdif_in",	"spdif_in",	"tegra30-spdif",	spdif_in_parents,	CLK_SOURCE_SPDIF_IN,	10,	&periph_l_regs, TEGRA_PERIPH_ON_APB, spdif_in),
+	TEGRA_INIT_DATA_MUX("d_audio",	"d_audio",	"tegra30-ahub",		mux_pllacp_clkm,	CLK_SOURCE_D_AUDIO,	106,	&periph_v_regs, 0, d_audio),
+	TEGRA_INIT_DATA_MUX("dam0",	NULL,		"tegra30-dam.0",	mux_pllacp_clkm,	CLK_SOURCE_DAM0,	108,	&periph_v_regs, 0, dam0),
+	TEGRA_INIT_DATA_MUX("dam1",	NULL,		"tegra30-dam.1",	mux_pllacp_clkm,	CLK_SOURCE_DAM1,	109,	&periph_v_regs, 0, dam1),
+	TEGRA_INIT_DATA_MUX("dam2",	NULL,		"tegra30-dam.2",	mux_pllacp_clkm,	CLK_SOURCE_DAM2,	110,	&periph_v_regs, 0, dam2),
+	TEGRA_INIT_DATA_MUX("hda",	"hda",		"tegra30-hda",		mux_pllpcm_clkm,	CLK_SOURCE_HDA,		125,	&periph_v_regs, 0, hda),
+	TEGRA_INIT_DATA_MUX("hda2codec_2x", "hda2codec", "tegra30-hda",		mux_pllpcm_clkm,	CLK_SOURCE_HDA2CODEC_2X, 111,	&periph_v_regs, 0, hda2codec_2x),
+	TEGRA_INIT_DATA_MUX("sbc1",	NULL,		"spi_tegra.0",		mux_pllpcm_clkm,	CLK_SOURCE_SBC1,	41,	&periph_h_regs, TEGRA_PERIPH_ON_APB, sbc1),
+	TEGRA_INIT_DATA_MUX("sbc2",	NULL,		"spi_tegra.1",		mux_pllpcm_clkm,	CLK_SOURCE_SBC2,	44,	&periph_h_regs, TEGRA_PERIPH_ON_APB, sbc2),
+	TEGRA_INIT_DATA_MUX("sbc3",	NULL,		"spi_tegra.2",		mux_pllpcm_clkm,	CLK_SOURCE_SBC3,	46,	&periph_h_regs, TEGRA_PERIPH_ON_APB, sbc3),
+	TEGRA_INIT_DATA_MUX("sbc4",	NULL,		"spi_tegra.3",		mux_pllpcm_clkm,	CLK_SOURCE_SBC4,	68,	&periph_u_regs, TEGRA_PERIPH_ON_APB, sbc4),
+	TEGRA_INIT_DATA_MUX("sbc5",	NULL,		"spi_tegra.4",		mux_pllpcm_clkm,	CLK_SOURCE_SBC5,	104,	&periph_v_regs, TEGRA_PERIPH_ON_APB, sbc5),
+	TEGRA_INIT_DATA_MUX("sbc6",	NULL,		"spi_tegra.5",		mux_pllpcm_clkm,	CLK_SOURCE_SBC6,	105,	&periph_v_regs, TEGRA_PERIPH_ON_APB, sbc6),
+	TEGRA_INIT_DATA_MUX("sata_oob",	NULL,		"tegra_sata_oob",	mux_pllpcm_clkm,	CLK_SOURCE_SATA_OOB,	123,	&periph_v_regs, TEGRA_PERIPH_ON_APB, sata_oob),
+	TEGRA_INIT_DATA_MUX("sata",	NULL,		"tegra_sata",		mux_pllpcm_clkm,	CLK_SOURCE_SATA,	124,	&periph_v_regs, TEGRA_PERIPH_ON_APB, sata),
+	TEGRA_INIT_DATA_MUX("ndflash",	NULL,		"tegra_nand",		mux_pllpcm_clkm,	CLK_SOURCE_NDFLASH,	13,	&periph_l_regs, TEGRA_PERIPH_ON_APB, ndflash),
+	TEGRA_INIT_DATA_MUX("ndspeed",	NULL,		"tegra_nand_speed",	mux_pllpcm_clkm,	CLK_SOURCE_NDSPEED,	80,	&periph_u_regs, TEGRA_PERIPH_ON_APB, ndspeed),
+	TEGRA_INIT_DATA_MUX("vfir",	NULL,		"vfir",			mux_pllpcm_clkm,	CLK_SOURCE_VFIR,	7,	&periph_l_regs, TEGRA_PERIPH_ON_APB, vfir),
+	TEGRA_INIT_DATA_MUX("csite",	NULL,		"csite",		mux_pllpcm_clkm,	CLK_SOURCE_CSITE,	73,	&periph_u_regs, TEGRA_PERIPH_ON_APB, csite),
+	TEGRA_INIT_DATA_MUX("la",	NULL,		"la",			mux_pllpcm_clkm,	CLK_SOURCE_LA,		76,	&periph_u_regs, TEGRA_PERIPH_ON_APB, la),
+	TEGRA_INIT_DATA_MUX("owr",	NULL,		"tegra_w1",		mux_pllpcm_clkm,	CLK_SOURCE_OWR,		71,	&periph_u_regs, TEGRA_PERIPH_ON_APB, owr),
+	TEGRA_INIT_DATA_MUX("mipi",	NULL,		"mipi",			mux_pllpcm_clkm,	CLK_SOURCE_MIPI,	50,	&periph_h_regs, TEGRA_PERIPH_ON_APB, mipi),
+	TEGRA_INIT_DATA_MUX("tsensor",	NULL,		"tegra-tsensor",	mux_pllpc_clkm_clk32k,	CLK_SOURCE_TSENSOR,	100,	&periph_v_regs, TEGRA_PERIPH_ON_APB, tsensor),
+	TEGRA_INIT_DATA_MUX("i2cslow",	NULL,		"i2cslow",		mux_pllpc_clk32k_clkm,	CLK_SOURCE_I2CSLOW,	81,	&periph_u_regs, TEGRA_PERIPH_ON_APB, i2cslow),
+	TEGRA_INIT_DATA_INT("vde",	NULL,		"vde",			mux_pllpcm_clkm,	CLK_SOURCE_VDE,		61,	&periph_h_regs, 0, vde),
+	TEGRA_INIT_DATA_INT("vi",	"vi",		"tegra_camera",		mux_pllmcpa,		CLK_SOURCE_VI,		20,	&periph_l_regs, 0, vi),
+	TEGRA_INIT_DATA_INT("epp",	NULL,		"epp",			mux_pllmcpa,		CLK_SOURCE_EPP,		19,	&periph_l_regs, 0, epp),
+	TEGRA_INIT_DATA_INT("mpe",	NULL,		"mpe",			mux_pllmcpa,		CLK_SOURCE_MPE,		60,	&periph_h_regs, 0, mpe),
+	TEGRA_INIT_DATA_INT("host1x",	NULL,		"host1x",		mux_pllmcpa,		CLK_SOURCE_HOST1X,	28,	&periph_l_regs, 0, host1x),
+	TEGRA_INIT_DATA_INT("3d",	NULL,		"3d",			mux_pllmcpa,		CLK_SOURCE_3D,		24,	&periph_l_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d),
+	TEGRA_INIT_DATA_INT("3d2",	NULL,		"3d2",			mux_pllmcpa,		CLK_SOURCE_3D2,		98,	&periph_v_regs, TEGRA_PERIPH_MANUAL_RESET, gr3d2),
+	TEGRA_INIT_DATA_INT("2d",	NULL,		"2d",			mux_pllmcpa,		CLK_SOURCE_2D,		21,	&periph_l_regs, 0, gr2d),
+	TEGRA_INIT_DATA_INT("se",	NULL,		"se",			mux_pllpcm_clkm,	CLK_SOURCE_SE,		127,	&periph_v_regs, 0, se),
+	TEGRA_INIT_DATA_MUX("mselect",	NULL,		"mselect",		mux_pllp_clkm,		CLK_SOURCE_MSELECT,	99,	&periph_v_regs, 0, mselect),
+	TEGRA_INIT_DATA_MUX("nor",	NULL,		"tegra-nor",		mux_pllpcm_clkm,	CLK_SOURCE_NOR,		42,	&periph_h_regs, 0, nor),
+	TEGRA_INIT_DATA_MUX("sdmmc1",	NULL,		"sdhci-tegra.0",	mux_pllpcm_clkm,	CLK_SOURCE_SDMMC1,	14,	&periph_l_regs, 0, sdmmc1),
+	TEGRA_INIT_DATA_MUX("sdmmc2",	NULL,		"sdhci-tegra.1",	mux_pllpcm_clkm,	CLK_SOURCE_SDMMC2,	9,	&periph_l_regs, 0, sdmmc2),
+	TEGRA_INIT_DATA_MUX("sdmmc3",	NULL,		"sdhci-tegra.2",	mux_pllpcm_clkm,	CLK_SOURCE_SDMMC3,	69,	&periph_u_regs, 0, sdmmc3),
+	TEGRA_INIT_DATA_MUX("sdmmc4",	NULL,		"sdhci-tegra.3",	mux_pllpcm_clkm,	CLK_SOURCE_SDMMC4,	15,	&periph_l_regs, 0, sdmmc4),
+	TEGRA_INIT_DATA_MUX("cve",	NULL,		"cve",			mux_pllpdc_clkm,	CLK_SOURCE_CVE,		49,	&periph_h_regs, 0, cve),
+	TEGRA_INIT_DATA_MUX("tvo",	NULL,		"tvo",			mux_pllpdc_clkm,	CLK_SOURCE_TVO,		49,	&periph_h_regs, 0, tvo),
+	TEGRA_INIT_DATA_MUX("tvdac",	NULL,		"tvdac",		mux_pllpdc_clkm,	CLK_SOURCE_TVDAC,	53,	&periph_h_regs, 0, tvdac),
+	TEGRA_INIT_DATA_MUX("actmon",	NULL,		"actmon",		mux_pllpc_clk32k_clkm,	CLK_SOURCE_ACTMON,	119,	&periph_v_regs, 0, actmon),
+	TEGRA_INIT_DATA_MUX("vi_sensor", "vi_sensor",	"tegra_camera",		mux_pllmcpa,		CLK_SOURCE_VI_SENSOR,	20,	&periph_l_regs, TEGRA_PERIPH_NO_RESET, vi_sensor),
+	TEGRA_INIT_DATA_DIV16("i2c1",	"div-clk",	"tegra-i2c.0",		mux_pllp_clkm,		CLK_SOURCE_I2C1,	12,	&periph_l_regs, TEGRA_PERIPH_ON_APB, i2c1),
+	TEGRA_INIT_DATA_DIV16("i2c2",	"div-clk",	"tegra-i2c.1",		mux_pllp_clkm,		CLK_SOURCE_I2C2,	54,	&periph_h_regs, TEGRA_PERIPH_ON_APB, i2c2),
+	TEGRA_INIT_DATA_DIV16("i2c3",	"div-clk",	"tegra-i2c.2",		mux_pllp_clkm,		CLK_SOURCE_I2C3,	67,	&periph_u_regs,	TEGRA_PERIPH_ON_APB, i2c3),
+	TEGRA_INIT_DATA_DIV16("i2c4",	"div-clk",	"tegra-i2c.3",		mux_pllp_clkm,		CLK_SOURCE_I2C4,	103,	&periph_v_regs,	TEGRA_PERIPH_ON_APB, i2c4),
+	TEGRA_INIT_DATA_DIV16("i2c5",	"div-clk",	"tegra-i2c.4",		mux_pllp_clkm,		CLK_SOURCE_I2C5,	47,	&periph_h_regs,	TEGRA_PERIPH_ON_APB, i2c5),
+	TEGRA_INIT_DATA_UART("uarta",	NULL,		"tegra_uart.0",		mux_pllpcm_clkm,	CLK_SOURCE_UARTA,	6,	&periph_l_regs, uarta),
+	TEGRA_INIT_DATA_UART("uartb",	NULL,		"tegra_uart.1",		mux_pllpcm_clkm,	CLK_SOURCE_UARTB,	7,	&periph_l_regs, uartb),
+	TEGRA_INIT_DATA_UART("uartc",	NULL,		"tegra_uart.2",		mux_pllpcm_clkm,	CLK_SOURCE_UARTC,	55,	&periph_h_regs, uartc),
+	TEGRA_INIT_DATA_UART("uartd",	NULL,		"tegra_uart.3",		mux_pllpcm_clkm,	CLK_SOURCE_UARTD,	65,	&periph_u_regs, uartd),
+	TEGRA_INIT_DATA_UART("uarte",	NULL,		"tegra_uart.4",		mux_pllpcm_clkm,	CLK_SOURCE_UARTE,	66,	&periph_u_regs, uarte),
+	TEGRA_INIT_DATA_MUX8("hdmi",	NULL,		"hdmi",			mux_pllpmdacd2_clkm,	CLK_SOURCE_HDMI,	51,	&periph_h_regs,	0, hdmi),
+	TEGRA_INIT_DATA_MUX8("extern1",	NULL,		"extern1",		mux_plla_clk32k_pllp_clkm_plle,	CLK_SOURCE_EXTERN1,	120,	&periph_v_regs,	0, extern1),
+	TEGRA_INIT_DATA_MUX8("extern2",	NULL,		"extern2",		mux_plla_clk32k_pllp_clkm_plle,	CLK_SOURCE_EXTERN2,	121,	&periph_v_regs,	0, extern2),
+	TEGRA_INIT_DATA_MUX8("extern3",	NULL,		"extern3",		mux_plla_clk32k_pllp_clkm_plle,	CLK_SOURCE_EXTERN3,	122,	&periph_v_regs,	0, extern3),
+	TEGRA_INIT_DATA("pwm",		NULL,		"pwm",			mux_pllpc_clk32k_clkm,	CLK_SOURCE_PWM,		28, 2, 0, 0, 8, 1, 0, &periph_l_regs, 17, periph_clk_enb_refcnt, 0, pwm),
+};
+
+static struct tegra_periph_init_data tegra_periph_nodiv_clk_list[] = {
+	TEGRA_INIT_DATA_NODIV("disp1",	NULL, "tegradc.0", mux_pllpmdacd2_clkm,	     CLK_SOURCE_DISP1,	29, 3, 27, &periph_l_regs, 0, disp1),
+	TEGRA_INIT_DATA_NODIV("disp2",	NULL, "tegradc.1", mux_pllpmdacd2_clkm,      CLK_SOURCE_DISP2,	29, 3, 26, &periph_l_regs, 0, disp2),
+	TEGRA_INIT_DATA_NODIV("dsib",	NULL, "tegradc.1", mux_plld_out0_plld2_out0, CLK_SOURCE_DSIB,	25, 1, 82, &periph_u_regs, 0, dsib),
+};
+
+static void __init tegra30_periph_clk_init(void)
+{
+	struct tegra_periph_init_data *data;
+	struct clk *clk;
+	int i;
+
+	/* apbdma */
+	clk = tegra_clk_register_periph_gate("apbdma", "clk_m", 0, clk_base, 0, 34,
+				    &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "tegra-apbdma");
+	clks[apbdma] = clk;
+
+	/* rtc */
+	clk = tegra_clk_register_periph_gate("rtc", "clk_32k",
+				    TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB,
+				    clk_base, 0, 4, &periph_l_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "rtc-tegra");
+	clks[rtc] = clk;
+
+	/* timer */
+	clk = tegra_clk_register_periph_gate("timer", "clk_m", 0, clk_base, 0,
+				    5, &periph_l_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "timer");
+	clks[timer] = clk;
+
+	/* kbc */
+	clk = tegra_clk_register_periph_gate("kbc", "clk_32k",
+				    TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB,
+				    clk_base, 0, 36, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "tegra-kbc");
+	clks[kbc] = clk;
+
+	/* csus */
+	clk = tegra_clk_register_periph_gate("csus", "clk_m",
+				    TEGRA_PERIPH_NO_RESET | TEGRA_PERIPH_ON_APB,
+				    clk_base, 0, 92, &periph_u_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "csus", "tengra_camera");
+	clks[csus] = clk;
+
+	/* vcp */
+	clk = tegra_clk_register_periph_gate("vcp", "clk_m", 0, clk_base, 0, 29,
+				    &periph_l_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "vcp", "tegra-avp");
+	clks[vcp] = clk;
+
+	/* bsea */
+	clk = tegra_clk_register_periph_gate("bsea", "clk_m", 0, clk_base, 0,
+				    62, &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "bsea", "tegra-avp");
+	clks[bsea] = clk;
+
+	/* bsev */
+	clk = tegra_clk_register_periph_gate("bsev", "clk_m", 0, clk_base, 0,
+				    63, &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "bsev", "tegra-aes");
+	clks[bsev] = clk;
+
+	/* usbd */
+	clk = tegra_clk_register_periph_gate("usbd", "clk_m", 0, clk_base, 0,
+				    22, &periph_l_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "fsl-tegra-udc");
+	clks[usbd] = clk;
+
+	/* usb2 */
+	clk = tegra_clk_register_periph_gate("usb2", "clk_m", 0, clk_base, 0,
+				    58, &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "tegra-ehci.1");
+	clks[usb2] = clk;
+
+	/* usb3 */
+	clk = tegra_clk_register_periph_gate("usb3", "clk_m", 0, clk_base, 0,
+				    59, &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "tegra-ehci.2");
+	clks[usb3] = clk;
+
+	/* dsia */
+	clk = tegra_clk_register_periph_gate("dsia", "pll_d_out0", 0, clk_base,
+				    0, 48, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "dsia", "tegradc.0");
+	clks[dsia] = clk;
+
+	/* csi */
+	clk = tegra_clk_register_periph_gate("csi", "pll_p_out3", 0, clk_base,
+				    0, 52, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "csi", "tegra_camera");
+	clks[csi] = clk;
+
+	/* isp */
+	clk = tegra_clk_register_periph_gate("isp", "clk_m", 0, clk_base, 0, 23,
+				    &periph_l_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "isp", "tegra_camera");
+	clks[isp] = clk;
+
+	/* pcie */
+	clk = tegra_clk_register_periph_gate("pcie", "clk_m", 0, clk_base, 0,
+				    70, &periph_u_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "pcie", "tegra-pcie");
+	clks[pcie] = clk;
+
+	/* afi */
+	clk = tegra_clk_register_periph_gate("afi", "clk_m", 0, clk_base, 0, 72,
+				    &periph_u_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "afi", "tegra-pcie");
+	clks[afi] = clk;
+
+	/* kfuse */
+	clk = tegra_clk_register_periph_gate("kfuse", "clk_m",
+				    TEGRA_PERIPH_ON_APB,
+				    clk_base, 0, 40, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "kfuse-tegra");
+	clks[kfuse] = clk;
+
+	/* fuse */
+	clk = tegra_clk_register_periph_gate("fuse", "clk_m",
+				    TEGRA_PERIPH_ON_APB,
+				    clk_base, 0, 39, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "fuse", "fuse-tegra");
+	clks[fuse] = clk;
+
+	/* fuse_burn */
+	clk = tegra_clk_register_periph_gate("fuse_burn", "clk_m",
+				    TEGRA_PERIPH_ON_APB,
+				    clk_base, 0, 39, &periph_h_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "fuse_burn", "fuse-tegra");
+	clks[fuse_burn] = clk;
+
+	/* apbif */
+	clk = tegra_clk_register_periph_gate("apbif", "clk_m", 0,
+				    clk_base, 0, 107, &periph_v_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "apbif", "tegra30-ahub");
+	clks[apbif] = clk;
+
+	/* hda2hdmi */
+	clk = tegra_clk_register_periph_gate("hda2hdmi", "clk_m",
+				    TEGRA_PERIPH_ON_APB,
+				    clk_base, 0, 128, &periph_w_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "hda2hdmi", "tegra30-hda");
+	clks[hda2hdmi] = clk;
+
+	/* sata_cold */
+	clk = tegra_clk_register_periph_gate("sata_cold", "clk_m",
+				    TEGRA_PERIPH_ON_APB,
+				    clk_base, 0, 129, &periph_w_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "tegra_sata_cold");
+	clks[sata_cold] = clk;
+
+	/* dtv */
+	clk = tegra_clk_register_periph_gate("dtv", "clk_m",
+				    TEGRA_PERIPH_ON_APB,
+				    clk_base, 0, 79, &periph_u_regs,
+				    periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, NULL, "dtv");
+	clks[dtv] = clk;
+
+	/* emc */
+	clk = clk_register_mux(NULL, "emc_mux", mux_pllmcp_clkm,
+			       ARRAY_SIZE(mux_pllmcp_clkm), 0,
+			       clk_base + CLK_SOURCE_EMC,
+			       30, 2, 0, NULL);
+	clk = tegra_clk_register_periph_gate("emc", "emc_mux", 0, clk_base, 0,
+				    57, &periph_h_regs, periph_clk_enb_refcnt);
+	clk_register_clkdev(clk, "emc", NULL);
+	clks[emc] = clk;
+
+	for (i = 0; i < ARRAY_SIZE(tegra_periph_clk_list); i++) {
+		data = &tegra_periph_clk_list[i];
+		clk = tegra_clk_register_periph(data->name, data->parent_names,
+				data->num_parents, &data->periph,
+				clk_base, data->offset);
+		clk_register_clkdev(clk, data->con_id, data->dev_id);
+		clks[data->clk_id] = clk;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(tegra_periph_nodiv_clk_list); i++) {
+		data = &tegra_periph_nodiv_clk_list[i];
+		clk = tegra_clk_register_periph_nodiv(data->name,
+					data->parent_names,
+					data->num_parents, &data->periph,
+					clk_base, data->offset);
+		clk_register_clkdev(clk, data->con_id, data->dev_id);
+		clks[data->clk_id] = clk;
+	}
+}
+
+static void __init tegra30_fixed_clk_init(void)
+{
+	struct clk *clk;
+
+	/* clk_32k */
+	clk = clk_register_fixed_rate(NULL, "clk_32k", NULL, CLK_IS_ROOT,
+				32768);
+	clk_register_clkdev(clk, "clk_32k", NULL);
+	clks[clk_32k] = clk;
+
+	/* clk_m_div2 */
+	clk = clk_register_fixed_factor(NULL, "clk_m_div2", "clk_m",
+				CLK_SET_RATE_PARENT, 1, 2);
+	clk_register_clkdev(clk, "clk_m_div2", NULL);
+	clks[clk_m_div2] = clk;
+
+	/* clk_m_div4 */
+	clk = clk_register_fixed_factor(NULL, "clk_m_div4", "clk_m",
+				CLK_SET_RATE_PARENT, 1, 4);
+	clk_register_clkdev(clk, "clk_m_div4", NULL);
+	clks[clk_m_div4] = clk;
+
+	/* cml0 */
+	clk = clk_register_gate(NULL, "cml0", "pll_e", 0, clk_base + PLLE_AUX,
+				0, 0, &cml_lock);
+	clk_register_clkdev(clk, "cml0", NULL);
+	clks[cml0] = clk;
+
+	/* cml1 */
+	clk = clk_register_gate(NULL, "cml1", "pll_e", 0, clk_base + PLLE_AUX,
+				1, 0, &cml_lock);
+	clk_register_clkdev(clk, "cml1", NULL);
+	clks[cml1] = clk;
+
+	/* pciex */
+	clk = clk_register_fixed_rate(NULL, "pciex", "pll_e", 0, 100000000);
+	clk_register_clkdev(clk, "pciex", NULL);
+	clks[pciex] = clk;
+}
+
+static void __init tegra30_osc_clk_init(void)
+{
+	struct clk *clk;
+	unsigned int pll_ref_div;
+
+	tegra30_clk_measure_input_freq();
+
+	/* clk_m */
+	clk = clk_register_fixed_rate(NULL, "clk_m", NULL, CLK_IS_ROOT,
+				input_freq);
+	clk_register_clkdev(clk, "clk_m", NULL);
+	clks[clk_m] = clk;
+
+	/* pll_ref */
+	pll_ref_div = tegra30_get_pll_ref_div();
+	clk = clk_register_fixed_factor(NULL, "pll_ref", "clk_m",
+				CLK_SET_RATE_PARENT, 1, pll_ref_div);
+	clk_register_clkdev(clk, "pll_ref", NULL);
+	clks[pll_ref] = clk;
+}
+
+/* Tegra30 CPU clock and reset control functions */
+static void tegra30_wait_cpu_in_reset(u32 cpu)
+{
+	unsigned int reg;
+
+	do {
+		reg = readl(clk_base +
+			    TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
+		cpu_relax();
+	} while (!(reg & (1 << cpu)));	/* check CPU been reset or not */
+
+	return;
+}
+
+static void tegra30_put_cpu_in_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_SET);
+	dmb();
+}
+
+static void tegra30_cpu_out_of_reset(u32 cpu)
+{
+	writel(CPU_RESET(cpu),
+	       clk_base + TEGRA_CLK_RST_CONTROLLER_RST_CPU_CMPLX_CLR);
+	wmb();
+}
+
+
+static void tegra30_enable_cpu_clock(u32 cpu)
+{
+	unsigned int reg;
+
+	writel(CPU_CLOCK(cpu),
+	       clk_base + TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+	reg = readl(clk_base +
+		    TEGRA30_CLK_RST_CONTROLLER_CLK_CPU_CMPLX_CLR);
+}
+
+static void tegra30_disable_cpu_clock(u32 cpu)
+{
+
+	unsigned int reg;
+
+	reg = readl(clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+	writel(reg | CPU_CLOCK(cpu),
+	       clk_base + TEGRA_CLK_RST_CONTROLLER_CLK_CPU_CMPLX);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static bool tegra30_cpu_rail_off_ready(void)
+{
+	unsigned int cpu_rst_status;
+	int cpu_pwr_status;
+
+	cpu_rst_status = readl(clk_base +
+				TEGRA30_CLK_RST_CONTROLLER_CPU_CMPLX_STATUS);
+	cpu_pwr_status = tegra_powergate_is_powered(TEGRA_POWERGATE_CPU1) ||
+			 tegra_powergate_is_powered(TEGRA_POWERGATE_CPU2) ||
+			 tegra_powergate_is_powered(TEGRA_POWERGATE_CPU3);
+
+	if (((cpu_rst_status & 0xE) != 0xE) || cpu_pwr_status)
+		return false;
+
+	return true;
+}
+
+static void tegra30_cpu_clock_suspend(void)
+{
+	/* switch coresite to clk_m, save off original source */
+	tegra30_cpu_clk_sctx.clk_csite_src =
+				readl(clk_base + CLK_RESET_SOURCE_CSITE);
+	writel(3<<30, clk_base + CLK_RESET_SOURCE_CSITE);
+
+	tegra30_cpu_clk_sctx.cpu_burst =
+				readl(clk_base + CLK_RESET_CCLK_BURST);
+	tegra30_cpu_clk_sctx.pllx_base =
+				readl(clk_base + CLK_RESET_PLLX_BASE);
+	tegra30_cpu_clk_sctx.pllx_misc =
+				readl(clk_base + CLK_RESET_PLLX_MISC);
+	tegra30_cpu_clk_sctx.cclk_divider =
+				readl(clk_base + CLK_RESET_CCLK_DIVIDER);
+}
+
+static void tegra30_cpu_clock_resume(void)
+{
+	unsigned int reg, policy;
+
+	/* Is CPU complex already running on PLLX? */
+	reg = readl(clk_base + CLK_RESET_CCLK_BURST);
+	policy = (reg >> CLK_RESET_CCLK_BURST_POLICY_SHIFT) & 0xF;
+
+	if (policy == CLK_RESET_CCLK_IDLE_POLICY)
+		reg = (reg >> CLK_RESET_CCLK_IDLE_POLICY_SHIFT) & 0xF;
+	else if (policy == CLK_RESET_CCLK_RUN_POLICY)
+		reg = (reg >> CLK_RESET_CCLK_RUN_POLICY_SHIFT) & 0xF;
+	else
+		BUG();
+
+	if (reg != CLK_RESET_CCLK_BURST_POLICY_PLLX) {
+		/* restore PLLX settings if CPU is on different PLL */
+		writel(tegra30_cpu_clk_sctx.pllx_misc,
+					clk_base + CLK_RESET_PLLX_MISC);
+		writel(tegra30_cpu_clk_sctx.pllx_base,
+					clk_base + CLK_RESET_PLLX_BASE);
+
+		/* wait for PLL stabilization if PLLX was enabled */
+		if (tegra30_cpu_clk_sctx.pllx_base & (1 << 30))
+			udelay(300);
+	}
+
+	/*
+	 * Restore original burst policy setting for calls resulting from CPU
+	 * LP2 in idle or system suspend.
+	 */
+	writel(tegra30_cpu_clk_sctx.cclk_divider,
+					clk_base + CLK_RESET_CCLK_DIVIDER);
+	writel(tegra30_cpu_clk_sctx.cpu_burst,
+					clk_base + CLK_RESET_CCLK_BURST);
+
+	writel(tegra30_cpu_clk_sctx.clk_csite_src,
+					clk_base + CLK_RESET_SOURCE_CSITE);
+}
+#endif
+
+static struct tegra_cpu_car_ops tegra30_cpu_car_ops = {
+	.wait_for_reset	= tegra30_wait_cpu_in_reset,
+	.put_in_reset	= tegra30_put_cpu_in_reset,
+	.out_of_reset	= tegra30_cpu_out_of_reset,
+	.enable_clock	= tegra30_enable_cpu_clock,
+	.disable_clock	= tegra30_disable_cpu_clock,
+#ifdef CONFIG_PM_SLEEP
+	.rail_off_ready	= tegra30_cpu_rail_off_ready,
+	.suspend	= tegra30_cpu_clock_suspend,
+	.resume		= tegra30_cpu_clock_resume,
+#endif
+};
+
+static __initdata struct tegra_clk_init_table init_table[] = {
+	{uarta, pll_p, 408000000, 1},
+	{pll_a, clk_max, 564480000, 1},
+	{pll_a_out0, clk_max, 11289600, 1},
+	{extern1, pll_a_out0, 0, 1},
+	{clk_out_1_mux, extern1, 0, 0},
+	{clk_out_1, clk_max, 0, 1},
+	{blink, clk_max, 0, 1},
+	{i2s0, pll_a_out0, 11289600, 0},
+	{i2s1, pll_a_out0, 11289600, 0},
+	{i2s2, pll_a_out0, 11289600, 0},
+	{i2s3, pll_a_out0, 11289600, 0},
+	{i2s4, pll_a_out0, 11289600, 0},
+	{sdmmc1, pll_p, 48000000, 0},
+	{sdmmc2, pll_p, 48000000, 0},
+	{sdmmc3, pll_p, 48000000, 0},
+	{pll_m, clk_max, 0, 1},
+	{pclk, clk_max, 0, 1},
+	{csite, clk_max, 0, 1},
+	{emc, clk_max, 0, 1},
+	{mselect, clk_max, 0, 1},
+	{sbc1, pll_p, 100000000, 0},
+	{sbc2, pll_p, 100000000, 0},
+	{sbc3, pll_p, 100000000, 0},
+	{sbc4, pll_p, 100000000, 0},
+	{sbc5, pll_p, 100000000, 0},
+	{sbc6, pll_p, 100000000, 0},
+	{host1x, pll_c, 150000000, 0},
+	{disp1, pll_p, 600000000, 0},
+	{disp2, pll_p, 600000000, 0},
+	{twd, clk_max, 0, 1},
+	{clk_max, clk_max, 0, 0}, /* This MUST be the last entry. */
+};
+
+/*
+ * Some clocks may be used by different drivers depending on the board
+ * configuration.  List those here to register them twice in the clock lookup
+ * table under two names.
+ */
+static struct tegra_clk_duplicate tegra_clk_duplicates[] = {
+	TEGRA_CLK_DUPLICATE(usbd, "utmip-pad", NULL),
+	TEGRA_CLK_DUPLICATE(usbd, "tegra-ehci.0", NULL),
+	TEGRA_CLK_DUPLICATE(usbd, "tegra-otg", NULL),
+	TEGRA_CLK_DUPLICATE(bsev, "tegra-avp", "bsev"),
+	TEGRA_CLK_DUPLICATE(bsev, "nvavp", "bsev"),
+	TEGRA_CLK_DUPLICATE(vde, "tegra-aes", "vde"),
+	TEGRA_CLK_DUPLICATE(bsea, "tegra-aes", "bsea"),
+	TEGRA_CLK_DUPLICATE(bsea, "nvavp", "bsea"),
+	TEGRA_CLK_DUPLICATE(cml1, "tegra_sata_cml", NULL),
+	TEGRA_CLK_DUPLICATE(cml0, "tegra_pcie", "cml"),
+	TEGRA_CLK_DUPLICATE(pciex, "tegra_pcie", "pciex"),
+	TEGRA_CLK_DUPLICATE(twd, "smp_twd", NULL),
+	TEGRA_CLK_DUPLICATE(vcp, "nvavp", "vcp"),
+	TEGRA_CLK_DUPLICATE(clk_max, NULL, NULL), /* MUST be the last entry */
+};
+
+static const struct of_device_id pmc_match[] __initconst = {
+	{ .compatible = "nvidia,tegra30-pmc" },
+	{},
+};
+
+void __init tegra30_clock_init(struct device_node *np)
+{
+	struct device_node *node;
+	int i;
+
+	clk_base = of_iomap(np, 0);
+	if (!clk_base) {
+		pr_err("ioremap tegra30 CAR failed\n");
+		return;
+	}
+
+	node = of_find_matching_node(NULL, pmc_match);
+	if (!node) {
+		pr_err("Failed to find pmc node\n");
+		BUG();
+	}
+
+	pmc_base = of_iomap(node, 0);
+	if (!pmc_base) {
+		pr_err("Can't map pmc registers\n");
+		BUG();
+	}
+
+	tegra30_osc_clk_init();
+	tegra30_fixed_clk_init();
+	tegra30_pll_init();
+	tegra30_super_clk_init();
+	tegra30_periph_clk_init();
+	tegra30_audio_clk_init();
+	tegra30_pmc_clk_init();
+
+	for (i = 0; i < ARRAY_SIZE(clks); i++) {
+		if (IS_ERR(clks[i])) {
+			pr_err("Tegra30 clk %d: register failed with %ld\n",
+			       i, PTR_ERR(clks[i]));
+			BUG();
+		}
+		if (!clks[i])
+			clks[i] = ERR_PTR(-EINVAL);
+	}
+
+	tegra_init_dup_clks(tegra_clk_duplicates, clks, clk_max);
+
+	clk_data.clks = clks;
+	clk_data.clk_num = ARRAY_SIZE(clks);
+	of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+
+	tegra_init_from_table(init_table, clks, clk_max);
+
+	tegra_cpu_car_ops = &tegra30_cpu_car_ops;
+}
diff --git a/drivers/clk/tegra/clk.c b/drivers/clk/tegra/clk.c
new file mode 100644
index 0000000..a603b9a
--- /dev/null
+++ b/drivers/clk/tegra/clk.c
@@ -0,0 +1,85 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/clk.h>
+#include <linux/clk-provider.h>
+#include <linux/of.h>
+#include <linux/clk/tegra.h>
+
+#include "clk.h"
+
+/* Global data of Tegra CPU CAR ops */
+struct tegra_cpu_car_ops *tegra_cpu_car_ops;
+
+void __init tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
+				struct clk *clks[], int clk_max)
+{
+	struct clk *clk;
+
+	for (; dup_list->clk_id < clk_max; dup_list++) {
+		clk = clks[dup_list->clk_id];
+		dup_list->lookup.clk = clk;
+		clkdev_add(&dup_list->lookup);
+	}
+}
+
+void __init tegra_init_from_table(struct tegra_clk_init_table *tbl,
+				  struct clk *clks[], int clk_max)
+{
+	struct clk *clk;
+
+	for (; tbl->clk_id < clk_max; tbl++) {
+		clk = clks[tbl->clk_id];
+		if (IS_ERR_OR_NULL(clk))
+			return;
+
+		if (tbl->parent_id < clk_max) {
+			struct clk *parent = clks[tbl->parent_id];
+			if (clk_set_parent(clk, parent)) {
+				pr_err("%s: Failed to set parent %s of %s\n",
+				       __func__, __clk_get_name(parent),
+				       __clk_get_name(clk));
+				WARN_ON(1);
+			}
+		}
+
+		if (tbl->rate)
+			if (clk_set_rate(clk, tbl->rate)) {
+				pr_err("%s: Failed to set rate %lu of %s\n",
+				       __func__, tbl->rate,
+				       __clk_get_name(clk));
+				WARN_ON(1);
+			}
+
+		if (tbl->state)
+			if (clk_prepare_enable(clk)) {
+				pr_err("%s: Failed to enable %s\n", __func__,
+				       __clk_get_name(clk));
+				WARN_ON(1);
+			}
+	}
+}
+
+static const struct of_device_id tegra_dt_clk_match[] = {
+	{ .compatible = "nvidia,tegra20-car", .data = tegra20_clock_init },
+	{ .compatible = "nvidia,tegra30-car", .data = tegra30_clock_init },
+	{ }
+};
+
+void __init tegra_clocks_init(void)
+{
+	of_clk_init(tegra_dt_clk_match);
+}
diff --git a/drivers/clk/tegra/clk.h b/drivers/clk/tegra/clk.h
new file mode 100644
index 0000000..0744731
--- /dev/null
+++ b/drivers/clk/tegra/clk.h
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __TEGRA_CLK_H
+#define __TEGRA_CLK_H
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+/**
+ * struct tegra_clk_sync_source - external clock source from codec
+ *
+ * @hw: handle between common and hardware-specific interfaces
+ * @rate: input frequency from source
+ * @max_rate: max rate allowed
+ */
+struct tegra_clk_sync_source {
+	struct		clk_hw hw;
+	unsigned long	rate;
+	unsigned long	max_rate;
+};
+
+#define to_clk_sync_source(_hw)					\
+	container_of(_hw, struct tegra_clk_sync_source, hw)
+
+extern const struct clk_ops tegra_clk_sync_source_ops;
+struct clk *tegra_clk_register_sync_source(const char *name,
+		unsigned long fixed_rate, unsigned long max_rate);
+
+/**
+ * struct tegra_clk_frac_div - fractional divider clock
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register containing divider
+ * @flags:	hardware-specific flags
+ * @shift:	shift to the divider bit field
+ * @width:	width of the divider bit field
+ * @frac_width:	width of the fractional bit field
+ * @lock:	register lock
+ *
+ * Flags:
+ * TEGRA_DIVIDER_ROUND_UP - This flags indicates to round up the divider value.
+ * TEGRA_DIVIDER_FIXED - Fixed rate PLL dividers has addition override bit, this
+ *      flag indicates that this divider is for fixed rate PLL.
+ * TEGRA_DIVIDER_INT - Some modules can not cope with the duty cycle when
+ *      fraction bit is set. This flags indicates to calculate divider for which
+ *      fracton bit will be zero.
+ * TEGRA_DIVIDER_UART - UART module divider has additional enable bit which is
+ *      set when divider value is not 0. This flags indicates that the divider
+ *      is for UART module.
+ */
+struct tegra_clk_frac_div {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		flags;
+	u8		shift;
+	u8		width;
+	u8		frac_width;
+	spinlock_t	*lock;
+};
+
+#define to_clk_frac_div(_hw) container_of(_hw, struct tegra_clk_frac_div, hw)
+
+#define TEGRA_DIVIDER_ROUND_UP BIT(0)
+#define TEGRA_DIVIDER_FIXED BIT(1)
+#define TEGRA_DIVIDER_INT BIT(2)
+#define TEGRA_DIVIDER_UART BIT(3)
+
+extern const struct clk_ops tegra_clk_frac_div_ops;
+struct clk *tegra_clk_register_divider(const char *name,
+		const char *parent_name, void __iomem *reg,
+		unsigned long flags, u8 clk_divider_flags, u8 shift, u8 width,
+		u8 frac_width, spinlock_t *lock);
+
+/*
+ * Tegra PLL:
+ *
+ * In general, there are 3 requirements for each PLL
+ * that SW needs to be comply with.
+ * (1) Input frequency range (REF).
+ * (2) Comparison frequency range (CF). CF = REF/DIVM.
+ * (3) VCO frequency range (VCO).  VCO = CF * DIVN.
+ *
+ * The final PLL output frequency (FO) = VCO >> DIVP.
+ */
+
+/**
+ * struct tegra_clk_pll_freq_table - PLL frequecy table
+ *
+ * @input_rate:		input rate from source
+ * @output_rate:	output rate from PLL for the input rate
+ * @n:			feedback divider
+ * @m:			input divider
+ * @p:			post divider
+ * @cpcon:		charge pump current
+ */
+struct tegra_clk_pll_freq_table {
+	unsigned long	input_rate;
+	unsigned long	output_rate;
+	u16		n;
+	u16		m;
+	u8		p;
+	u8		cpcon;
+};
+
+/**
+ * struct clk_pll_params - PLL parameters
+ *
+ * @input_min:			Minimum input frequency
+ * @input_max:			Maximum input frequency
+ * @cf_min:			Minimum comparison frequency
+ * @cf_max:			Maximum comparison frequency
+ * @vco_min:			Minimum VCO frequency
+ * @vco_max:			Maximum VCO frequency
+ * @base_reg:			PLL base reg offset
+ * @misc_reg:			PLL misc reg offset
+ * @lock_reg:			PLL lock reg offset
+ * @lock_bit_idx:		Bit index for PLL lock status
+ * @lock_enable_bit_idx:	Bit index to enable PLL lock
+ * @lock_delay:			Delay in us if PLL lock is not used
+ */
+struct tegra_clk_pll_params {
+	unsigned long	input_min;
+	unsigned long	input_max;
+	unsigned long	cf_min;
+	unsigned long	cf_max;
+	unsigned long	vco_min;
+	unsigned long	vco_max;
+
+	u32		base_reg;
+	u32		misc_reg;
+	u32		lock_reg;
+	u32		lock_bit_idx;
+	u32		lock_enable_bit_idx;
+	int		lock_delay;
+};
+
+/**
+ * struct tegra_clk_pll - Tegra PLL clock
+ *
+ * @hw:		handle between common and hardware-specifix interfaces
+ * @clk_base:	address of CAR controller
+ * @pmc:	address of PMC, required to read override bits
+ * @freq_table:	array of frequencies supported by PLL
+ * @params:	PLL parameters
+ * @flags:	PLL flags
+ * @fixed_rate:	PLL rate if it is fixed
+ * @lock:	register lock
+ * @divn_shift:	shift to the feedback divider bit field
+ * @divn_width:	width of the feedback divider bit field
+ * @divm_shift:	shift to the input divider bit field
+ * @divm_width:	width of the input divider bit field
+ * @divp_shift:	shift to the post divider bit field
+ * @divp_width:	width of the post divider bit field
+ *
+ * Flags:
+ * TEGRA_PLL_USE_LOCK - This flag indicated to use lock bits for
+ *     PLL locking. If not set it will use lock_delay value to wait.
+ * TEGRA_PLL_HAS_CPCON - This flag indicates that CPCON value needs
+ *     to be programmed to change output frequency of the PLL.
+ * TEGRA_PLL_SET_LFCON - This flag indicates that LFCON value needs
+ *     to be programmed to change output frequency of the PLL.
+ * TEGRA_PLL_SET_DCCON - This flag indicates that DCCON value needs
+ *     to be programmed to change output frequency of the PLL.
+ * TEGRA_PLLU - PLLU has inverted post divider. This flags indicated
+ *     that it is PLLU and invert post divider value.
+ * TEGRA_PLLM - PLLM has additional override settings in PMC. This
+ *     flag indicates that it is PLLM and use override settings.
+ * TEGRA_PLL_FIXED - We are not supposed to change output frequency
+ *     of some plls.
+ * TEGRA_PLLE_CONFIGURE - Configure PLLE when enabling.
+ */
+struct tegra_clk_pll {
+	struct clk_hw	hw;
+	void __iomem	*clk_base;
+	void __iomem	*pmc;
+	u8		flags;
+	unsigned long	fixed_rate;
+	spinlock_t	*lock;
+	u8		divn_shift;
+	u8		divn_width;
+	u8		divm_shift;
+	u8		divm_width;
+	u8		divp_shift;
+	u8		divp_width;
+	struct tegra_clk_pll_freq_table	*freq_table;
+	struct tegra_clk_pll_params	*params;
+};
+
+#define to_clk_pll(_hw) container_of(_hw, struct tegra_clk_pll, hw)
+
+#define TEGRA_PLL_USE_LOCK BIT(0)
+#define TEGRA_PLL_HAS_CPCON BIT(1)
+#define TEGRA_PLL_SET_LFCON BIT(2)
+#define TEGRA_PLL_SET_DCCON BIT(3)
+#define TEGRA_PLLU BIT(4)
+#define TEGRA_PLLM BIT(5)
+#define TEGRA_PLL_FIXED BIT(6)
+#define TEGRA_PLLE_CONFIGURE BIT(7)
+
+extern const struct clk_ops tegra_clk_pll_ops;
+extern const struct clk_ops tegra_clk_plle_ops;
+struct clk *tegra_clk_register_pll(const char *name, const char *parent_name,
+		void __iomem *clk_base, void __iomem *pmc,
+		unsigned long flags, unsigned long fixed_rate,
+		struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
+struct clk *tegra_clk_register_plle(const char *name, const char *parent_name,
+		void __iomem *clk_base, void __iomem *pmc,
+		unsigned long flags, unsigned long fixed_rate,
+		struct tegra_clk_pll_params *pll_params, u8 pll_flags,
+		struct tegra_clk_pll_freq_table *freq_table, spinlock_t *lock);
+
+/**
+ * struct tegra_clk_pll_out - PLL divider down clock
+ *
+ * @hw:			handle between common and hardware-specific interfaces
+ * @reg:		register containing the PLL divider
+ * @enb_bit_idx:	bit to enable/disable PLL divider
+ * @rst_bit_idx:	bit to reset PLL divider
+ * @lock:		register lock
+ * @flags:		hardware-specific flags
+ */
+struct tegra_clk_pll_out {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		enb_bit_idx;
+	u8		rst_bit_idx;
+	spinlock_t	*lock;
+	u8		flags;
+};
+
+#define to_clk_pll_out(_hw) container_of(_hw, struct tegra_clk_pll_out, hw)
+
+extern const struct clk_ops tegra_clk_pll_out_ops;
+struct clk *tegra_clk_register_pll_out(const char *name,
+		const char *parent_name, void __iomem *reg, u8 enb_bit_idx,
+		u8 rst_bit_idx, unsigned long flags, u8 pll_div_flags,
+		spinlock_t *lock);
+
+/**
+ * struct tegra_clk_periph_regs -  Registers controlling peripheral clock
+ *
+ * @enb_reg:		read the enable status
+ * @enb_set_reg:	write 1 to enable clock
+ * @enb_clr_reg:	write 1 to disable clock
+ * @rst_reg:		read the reset status
+ * @rst_set_reg:	write 1 to assert the reset of peripheral
+ * @rst_clr_reg:	write 1 to deassert the reset of peripheral
+ */
+struct tegra_clk_periph_regs {
+	u32 enb_reg;
+	u32 enb_set_reg;
+	u32 enb_clr_reg;
+	u32 rst_reg;
+	u32 rst_set_reg;
+	u32 rst_clr_reg;
+};
+
+/**
+ * struct tegra_clk_periph_gate - peripheral gate clock
+ *
+ * @magic:		magic number to validate type
+ * @hw:			handle between common and hardware-specific interfaces
+ * @clk_base:		address of CAR controller
+ * @regs:		Registers to control the peripheral
+ * @flags:		hardware-specific flags
+ * @clk_num:		Clock number
+ * @enable_refcnt:	array to maintain reference count of the clock
+ *
+ * Flags:
+ * TEGRA_PERIPH_NO_RESET - This flag indicates that reset is not allowed
+ *     for this module.
+ * TEGRA_PERIPH_MANUAL_RESET - This flag indicates not to reset module
+ *     after clock enable and driver for the module is responsible for
+ *     doing reset.
+ * TEGRA_PERIPH_ON_APB - If peripheral is in the APB bus then read the
+ *     bus to flush the write operation in apb bus. This flag indicates
+ *     that this peripheral is in apb bus.
+ */
+struct tegra_clk_periph_gate {
+	u32			magic;
+	struct clk_hw		hw;
+	void __iomem		*clk_base;
+	u8			flags;
+	int			clk_num;
+	int			*enable_refcnt;
+	struct tegra_clk_periph_regs	*regs;
+};
+
+#define to_clk_periph_gate(_hw)					\
+	container_of(_hw, struct tegra_clk_periph_gate, hw)
+
+#define TEGRA_CLK_PERIPH_GATE_MAGIC 0x17760309
+
+#define TEGRA_PERIPH_NO_RESET BIT(0)
+#define TEGRA_PERIPH_MANUAL_RESET BIT(1)
+#define TEGRA_PERIPH_ON_APB BIT(2)
+
+void tegra_periph_reset(struct tegra_clk_periph_gate *gate, bool assert);
+extern const struct clk_ops tegra_clk_periph_gate_ops;
+struct clk *tegra_clk_register_periph_gate(const char *name,
+		const char *parent_name, u8 gate_flags, void __iomem *clk_base,
+		unsigned long flags, int clk_num,
+		struct tegra_clk_periph_regs *pregs, int *enable_refcnt);
+
+/**
+ * struct clk-periph - peripheral clock
+ *
+ * @magic:	magic number to validate type
+ * @hw:		handle between common and hardware-specific interfaces
+ * @mux:	mux clock
+ * @divider:	divider clock
+ * @gate:	gate clock
+ * @mux_ops:	mux clock ops
+ * @div_ops:	divider clock ops
+ * @gate_ops:	gate clock ops
+ */
+struct tegra_clk_periph {
+	u32			magic;
+	struct clk_hw		hw;
+	struct clk_mux		mux;
+	struct tegra_clk_frac_div	divider;
+	struct tegra_clk_periph_gate	gate;
+
+	const struct clk_ops	*mux_ops;
+	const struct clk_ops	*div_ops;
+	const struct clk_ops	*gate_ops;
+};
+
+#define to_clk_periph(_hw) container_of(_hw, struct tegra_clk_periph, hw)
+
+#define TEGRA_CLK_PERIPH_MAGIC 0x18221223
+
+extern const struct clk_ops tegra_clk_periph_ops;
+struct clk *tegra_clk_register_periph(const char *name,
+		const char **parent_names, int num_parents,
+		struct tegra_clk_periph *periph, void __iomem *clk_base,
+		u32 offset);
+struct clk *tegra_clk_register_periph_nodiv(const char *name,
+		const char **parent_names, int num_parents,
+		struct tegra_clk_periph *periph, void __iomem *clk_base,
+		u32 offset);
+
+#define TEGRA_CLK_PERIPH(_mux_shift, _mux_width, _mux_flags,		\
+			 _div_shift, _div_width, _div_frac_width,	\
+			 _div_flags, _clk_num, _enb_refcnt, _regs,	\
+			 _gate_flags)					\
+	{								\
+		.mux = {						\
+			.flags = _mux_flags,				\
+			.shift = _mux_shift,				\
+			.width = _mux_width,				\
+		},							\
+		.divider = {						\
+			.flags = _div_flags,				\
+			.shift = _div_shift,				\
+			.width = _div_width,				\
+			.frac_width = _div_frac_width,			\
+		},							\
+		.gate = {						\
+			.flags = _gate_flags,				\
+			.clk_num = _clk_num,				\
+			.enable_refcnt = _enb_refcnt,			\
+			.regs = _regs,					\
+		},							\
+		.mux_ops = &clk_mux_ops,				\
+		.div_ops = &tegra_clk_frac_div_ops,			\
+		.gate_ops = &tegra_clk_periph_gate_ops,			\
+	}
+
+struct tegra_periph_init_data {
+	const char *name;
+	int clk_id;
+	const char **parent_names;
+	int num_parents;
+	struct tegra_clk_periph periph;
+	u32 offset;
+	const char *con_id;
+	const char *dev_id;
+};
+
+#define TEGRA_INIT_DATA(_name, _con_id, _dev_id, _parent_names, _offset, \
+			_mux_shift, _mux_width, _mux_flags, _div_shift,	\
+			_div_width, _div_frac_width, _div_flags, _regs,	\
+			_clk_num, _enb_refcnt, _gate_flags, _clk_id)	\
+	{								\
+		.name = _name,						\
+		.clk_id = _clk_id,					\
+		.parent_names = _parent_names,				\
+		.num_parents = ARRAY_SIZE(_parent_names),		\
+		.periph = TEGRA_CLK_PERIPH(_mux_shift, _mux_width,	\
+					   _mux_flags, _div_shift,	\
+					   _div_width, _div_frac_width,	\
+					   _div_flags, _clk_num,	\
+					   _enb_refcnt, _regs,		\
+					   _gate_flags),		\
+		.offset = _offset,					\
+		.con_id = _con_id,					\
+		.dev_id = _dev_id,					\
+	}
+
+/**
+ * struct clk_super_mux - super clock
+ *
+ * @hw:		handle between common and hardware-specific interfaces
+ * @reg:	register controlling multiplexer
+ * @width:	width of the multiplexer bit field
+ * @flags:	hardware-specific flags
+ * @div2_index:	bit controlling divide-by-2
+ * @pllx_index:	PLLX index in the parent list
+ * @lock:	register lock
+ *
+ * Flags:
+ * TEGRA_DIVIDER_2 - LP cluster has additional divider. This flag indicates
+ *     that this is LP cluster clock.
+ */
+struct tegra_clk_super_mux {
+	struct clk_hw	hw;
+	void __iomem	*reg;
+	u8		width;
+	u8		flags;
+	u8		div2_index;
+	u8		pllx_index;
+	spinlock_t	*lock;
+};
+
+#define to_clk_super_mux(_hw) container_of(_hw, struct tegra_clk_super_mux, hw)
+
+#define TEGRA_DIVIDER_2 BIT(0)
+
+extern const struct clk_ops tegra_clk_super_ops;
+struct clk *tegra_clk_register_super_mux(const char *name,
+		const char **parent_names, u8 num_parents,
+		unsigned long flags, void __iomem *reg, u8 clk_super_flags,
+		u8 width, u8 pllx_index, u8 div2_index, spinlock_t *lock);
+
+/**
+ * struct clk_init_tabel - clock initialization table
+ * @clk_id:	clock id as mentioned in device tree bindings
+ * @parent_id:	parent clock id as mentioned in device tree bindings
+ * @rate:	rate to set
+ * @state:	enable/disable
+ */
+struct tegra_clk_init_table {
+	unsigned int	clk_id;
+	unsigned int	parent_id;
+	unsigned long	rate;
+	int		state;
+};
+
+/**
+ * struct clk_duplicate - duplicate clocks
+ * @clk_id:	clock id as mentioned in device tree bindings
+ * @lookup:	duplicate lookup entry for the clock
+ */
+struct tegra_clk_duplicate {
+	int			clk_id;
+	struct clk_lookup	lookup;
+};
+
+#define TEGRA_CLK_DUPLICATE(_clk_id, _dev, _con) \
+	{					\
+		.clk_id = _clk_id,		\
+		.lookup = {			\
+			.dev_id = _dev,		\
+			.con_id = _con,		\
+		},				\
+	}
+
+void tegra_init_from_table(struct tegra_clk_init_table *tbl,
+		struct clk *clks[], int clk_max);
+
+void tegra_init_dup_clks(struct tegra_clk_duplicate *dup_list,
+		struct clk *clks[], int clk_max);
+
+#ifdef CONFIG_ARCH_TEGRA_2x_SOC
+void tegra20_clock_init(struct device_node *np);
+#else
+static inline void tegra20_clock_init(struct device_node *np) {}
+#endif /* CONFIG_ARCH_TEGRA_2x_SOC */
+
+#ifdef CONFIG_ARCH_TEGRA_3x_SOC
+void tegra30_clock_init(struct device_node *np);
+#else
+static inline void tegra30_clock_init(struct device_node *np) {}
+#endif /* CONFIG_ARCH_TEGRA_3x_SOC */
+
+#endif /* TEGRA_CLK_H */
diff --git a/drivers/clocksource/Kconfig b/drivers/clocksource/Kconfig
index 7fdcbd3..7d978c1 100644
--- a/drivers/clocksource/Kconfig
+++ b/drivers/clocksource/Kconfig
@@ -1,3 +1,6 @@
+config CLKSRC_OF
+	bool
+
 config CLKSRC_I8253
 	bool
 
@@ -25,6 +28,9 @@
 config SUNXI_TIMER
 	bool
 
+config VT8500_TIMER
+	bool
+
 config CLKSRC_NOMADIK_MTU
 	bool
 	depends on (ARCH_NOMADIK || ARCH_U8500)
diff --git a/drivers/clocksource/Makefile b/drivers/clocksource/Makefile
index f93453d..596c45c 100644
--- a/drivers/clocksource/Makefile
+++ b/drivers/clocksource/Makefile
@@ -1,3 +1,4 @@
+obj-$(CONFIG_CLKSRC_OF)	+= clksrc-of.o
 obj-$(CONFIG_ATMEL_TCB_CLKSRC)	+= tcb_clksrc.o
 obj-$(CONFIG_X86_CYCLONE_TIMER)	+= cyclone.o
 obj-$(CONFIG_X86_PM_TIMER)	+= acpi_pm.o
@@ -16,5 +17,7 @@
 obj-$(CONFIG_ARMADA_370_XP_TIMER)	+= time-armada-370-xp.o
 obj-$(CONFIG_ARCH_BCM2835)	+= bcm2835_timer.o
 obj-$(CONFIG_SUNXI_TIMER)	+= sunxi_timer.o
+obj-$(CONFIG_ARCH_TEGRA)	+= tegra20_timer.o
+obj-$(CONFIG_VT8500_TIMER)	+= vt8500_timer.o
 
 obj-$(CONFIG_CLKSRC_ARM_GENERIC)	+= arm_generic.o
diff --git a/drivers/clocksource/bcm2835_timer.c b/drivers/clocksource/bcm2835_timer.c
index bc19f12..7f796d8f 100644
--- a/drivers/clocksource/bcm2835_timer.c
+++ b/drivers/clocksource/bcm2835_timer.c
@@ -101,7 +101,7 @@
 	{}
 };
 
-static void __init bcm2835_time_init(void)
+void __init bcm2835_timer_init(void)
 {
 	struct device_node *node;
 	void __iomem *base;
@@ -155,7 +155,3 @@
 
 	pr_info("bcm2835: system timer (irq = %d)\n", irq);
 }
-
-struct sys_timer bcm2835_timer = {
-	.init = bcm2835_time_init,
-};
diff --git a/drivers/clocksource/clksrc-of.c b/drivers/clocksource/clksrc-of.c
new file mode 100644
index 0000000..bdabdaa
--- /dev/null
+++ b/drivers/clocksource/clksrc-of.c
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/init.h>
+#include <linux/of.h>
+
+extern struct of_device_id __clksrc_of_table[];
+
+static const struct of_device_id __clksrc_of_table_sentinel
+	__used __section(__clksrc_of_table_end);
+
+void __init clocksource_of_init(void)
+{
+	struct device_node *np;
+	const struct of_device_id *match;
+	void (*init_func)(void);
+
+	for_each_matching_node_and_match(np, __clksrc_of_table, &match) {
+		init_func = match->data;
+		init_func();
+	}
+}
diff --git a/drivers/clocksource/dw_apb_timer_of.c b/drivers/clocksource/dw_apb_timer_of.c
index f7dba5b..ab09ed3 100644
--- a/drivers/clocksource/dw_apb_timer_of.c
+++ b/drivers/clocksource/dw_apb_timer_of.c
@@ -107,7 +107,7 @@
 	{},
 };
 
-static void __init timer_init(void)
+void __init dw_apb_timer_init(void)
 {
 	struct device_node *event_timer, *source_timer;
 
@@ -125,7 +125,3 @@
 
 	init_sched_clock();
 }
-
-struct sys_timer dw_apb_timer = {
-	.init = timer_init,
-};
diff --git a/drivers/clocksource/nomadik-mtu.c b/drivers/clocksource/nomadik-mtu.c
index 8914c3c..025afc6 100644
--- a/drivers/clocksource/nomadik-mtu.c
+++ b/drivers/clocksource/nomadik-mtu.c
@@ -134,12 +134,32 @@
 	}
 }
 
+void nmdk_clksrc_reset(void)
+{
+	/* Disable */
+	writel(0, mtu_base + MTU_CR(0));
+
+	/* ClockSource: configure load and background-load, and fire it up */
+	writel(nmdk_cycle, mtu_base + MTU_LR(0));
+	writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
+
+	writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
+	       mtu_base + MTU_CR(0));
+}
+
+static void nmdk_clkevt_resume(struct clock_event_device *cedev)
+{
+	nmdk_clkevt_reset();
+	nmdk_clksrc_reset();
+}
+
 static struct clock_event_device nmdk_clkevt = {
 	.name		= "mtu_1",
 	.features	= CLOCK_EVT_FEAT_ONESHOT | CLOCK_EVT_FEAT_PERIODIC,
 	.rating		= 200,
 	.set_mode	= nmdk_clkevt_mode,
 	.set_next_event	= nmdk_clkevt_next,
+	.resume		= nmdk_clkevt_resume,
 };
 
 /*
@@ -161,19 +181,6 @@
 	.dev_id		= &nmdk_clkevt,
 };
 
-void nmdk_clksrc_reset(void)
-{
-	/* Disable */
-	writel(0, mtu_base + MTU_CR(0));
-
-	/* ClockSource: configure load and background-load, and fire it up */
-	writel(nmdk_cycle, mtu_base + MTU_LR(0));
-	writel(nmdk_cycle, mtu_base + MTU_BGLR(0));
-
-	writel(clk_prescale | MTU_CRn_32BITS | MTU_CRn_ENA,
-	       mtu_base + MTU_CR(0));
-}
-
 void __init nmdk_timer_init(void __iomem *base, int irq)
 {
 	unsigned long rate;
diff --git a/drivers/clocksource/sunxi_timer.c b/drivers/clocksource/sunxi_timer.c
index f911866..0ce85e2 100644
--- a/drivers/clocksource/sunxi_timer.c
+++ b/drivers/clocksource/sunxi_timer.c
@@ -103,7 +103,7 @@
 	{ }
 };
 
-static void __init sunxi_timer_init(void)
+void __init sunxi_timer_init(void)
 {
 	struct device_node *node;
 	unsigned long rate = 0;
@@ -158,7 +158,3 @@
 	clockevents_config_and_register(&sunxi_clockevent, rate / TIMER_SCAL,
 					0x1, 0xff);
 }
-
-struct sys_timer sunxi_timer = {
-	.init = sunxi_timer_init,
-};
diff --git a/arch/arm/mach-tegra/timer.c b/drivers/clocksource/tegra20_timer.c
similarity index 96%
rename from arch/arm/mach-tegra/timer.c
rename to drivers/clocksource/tegra20_timer.c
index bc86161..0bde03f 100644
--- a/arch/arm/mach-tegra/timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -1,6 +1,4 @@
 /*
- * arch/arch/mach-tegra/timer.c
- *
  * Copyright (C) 2010 Google, Inc.
  *
  * Author:
@@ -33,8 +31,6 @@
 #include <asm/smp_twd.h>
 #include <asm/sched_clock.h>
 
-#include "board.h"
-
 #define RTC_SECONDS            0x08
 #define RTC_SHADOW_SECONDS     0x0c
 #define RTC_MILLISECONDS       0x10
@@ -168,7 +164,7 @@
 	{}
 };
 
-static void __init tegra_init_timer(void)
+static void __init tegra20_init_timer(void)
 {
 	struct device_node *np;
 	struct clk *clk;
@@ -183,7 +179,7 @@
 
 	timer_reg_base = of_iomap(np, 0);
 	if (!timer_reg_base) {
-		pr_err("Can't map timer registers");
+		pr_err("Can't map timer registers\n");
 		BUG();
 	}
 
@@ -268,10 +264,7 @@
 #endif
 	register_persistent_clock(NULL, tegra_read_persistent_clock);
 }
-
-struct sys_timer tegra_sys_timer = {
-	.init = tegra_init_timer,
-};
+CLOCKSOURCE_OF_DECLARE(tegra20, "nvidia,tegra20-timer", tegra20_init_timer);
 
 #ifdef CONFIG_PM
 static u32 usec_config;
diff --git a/arch/arm/mach-vt8500/timer.c b/drivers/clocksource/vt8500_timer.c
similarity index 100%
rename from arch/arm/mach-vt8500/timer.c
rename to drivers/clocksource/vt8500_timer.c
diff --git a/drivers/cpufreq/Kconfig.x86 b/drivers/cpufreq/Kconfig.x86
index 934854a..7227cd7 100644
--- a/drivers/cpufreq/Kconfig.x86
+++ b/drivers/cpufreq/Kconfig.x86
@@ -106,7 +106,7 @@
 config X86_POWERNOW_K8
 	tristate "AMD Opteron/Athlon64 PowerNow!"
 	select CPU_FREQ_TABLE
-	depends on ACPI && ACPI_PROCESSOR
+	depends on ACPI && ACPI_PROCESSOR && X86_ACPI_CPUFREQ
 	help
 	  This adds the CPUFreq driver for K8/early Opteron/Athlon64 processors.
 	  Support for K10 and newer processors is now in acpi-cpufreq.
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 0d048f6..7b0d49d 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -1030,4 +1030,11 @@
 late_initcall(acpi_cpufreq_init);
 module_exit(acpi_cpufreq_exit);
 
+static const struct x86_cpu_id acpi_cpufreq_ids[] = {
+	X86_FEATURE_MATCH(X86_FEATURE_ACPI),
+	X86_FEATURE_MATCH(X86_FEATURE_HW_PSTATE),
+	{}
+};
+MODULE_DEVICE_TABLE(x86cpu, acpi_cpufreq_ids);
+
 MODULE_ALIAS("acpi");
diff --git a/drivers/cpufreq/cpufreq-cpu0.c b/drivers/cpufreq/cpufreq-cpu0.c
index 52bf36d..debc5a7 100644
--- a/drivers/cpufreq/cpufreq-cpu0.c
+++ b/drivers/cpufreq/cpufreq-cpu0.c
@@ -71,12 +71,15 @@
 	}
 
 	if (cpu_reg) {
+		rcu_read_lock();
 		opp = opp_find_freq_ceil(cpu_dev, &freq_Hz);
 		if (IS_ERR(opp)) {
+			rcu_read_unlock();
 			pr_err("failed to find OPP for %ld\n", freq_Hz);
 			return PTR_ERR(opp);
 		}
 		volt = opp_get_voltage(opp);
+		rcu_read_unlock();
 		tol = volt * voltage_tolerance / 100;
 		volt_old = regulator_get_voltage(cpu_reg);
 	}
@@ -236,12 +239,14 @@
 		 */
 		for (i = 0; freq_table[i].frequency != CPUFREQ_TABLE_END; i++)
 			;
+		rcu_read_lock();
 		opp = opp_find_freq_exact(cpu_dev,
 				freq_table[0].frequency * 1000, true);
 		min_uV = opp_get_voltage(opp);
 		opp = opp_find_freq_exact(cpu_dev,
 				freq_table[i-1].frequency * 1000, true);
 		max_uV = opp_get_voltage(opp);
+		rcu_read_unlock();
 		ret = regulator_set_voltage_time(cpu_reg, min_uV, max_uV);
 		if (ret > 0)
 			transition_latency += ret * 1000;
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index 1f3417a..97102b0 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -110,13 +110,16 @@
 	freq = ret;
 
 	if (mpu_reg) {
+		rcu_read_lock();
 		opp = opp_find_freq_ceil(mpu_dev, &freq);
 		if (IS_ERR(opp)) {
+			rcu_read_unlock();
 			dev_err(mpu_dev, "%s: unable to find MPU OPP for %d\n",
 				__func__, freqs.new);
 			return -EINVAL;
 		}
 		volt = opp_get_voltage(opp);
+		rcu_read_unlock();
 		tol = volt * OPP_TOLERANCE / 100;
 		volt_old = regulator_get_voltage(mpu_reg);
 	}
diff --git a/drivers/cpuidle/Kconfig b/drivers/cpuidle/Kconfig
index c4cc27e..071e2c3 100644
--- a/drivers/cpuidle/Kconfig
+++ b/drivers/cpuidle/Kconfig
@@ -39,4 +39,10 @@
 	help
 	  Select this to enable cpuidle on Calxeda processors.
 
+config CPU_IDLE_KIRKWOOD
+	bool "CPU Idle Driver for Kirkwood processors"
+	depends on ARCH_KIRKWOOD
+	help
+	  Select this to enable cpuidle on Kirkwood processors.
+
 endif
diff --git a/drivers/cpuidle/Makefile b/drivers/cpuidle/Makefile
index 03ee874..24c6e7d 100644
--- a/drivers/cpuidle/Makefile
+++ b/drivers/cpuidle/Makefile
@@ -6,3 +6,4 @@
 obj-$(CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED) += coupled.o
 
 obj-$(CONFIG_CPU_IDLE_CALXEDA) += cpuidle-calxeda.o
+obj-$(CONFIG_CPU_IDLE_KIRKWOOD) += cpuidle-kirkwood.o
diff --git a/arch/arm/mach-kirkwood/cpuidle.c b/drivers/cpuidle/cpuidle-kirkwood.c
similarity index 61%
rename from arch/arm/mach-kirkwood/cpuidle.c
rename to drivers/cpuidle/cpuidle-kirkwood.c
index f730467..670aa1e 100644
--- a/arch/arm/mach-kirkwood/cpuidle.c
+++ b/drivers/cpuidle/cpuidle-kirkwood.c
@@ -14,6 +14,7 @@
  */
 
 #include <linux/kernel.h>
+#include <linux/module.h>
 #include <linux/init.h>
 #include <linux/platform_device.h>
 #include <linux/cpuidle.h>
@@ -21,16 +22,17 @@
 #include <linux/export.h>
 #include <asm/proc-fns.h>
 #include <asm/cpuidle.h>
-#include <mach/kirkwood.h>
 
 #define KIRKWOOD_MAX_STATES	2
 
+static void __iomem *ddr_operation_base;
+
 /* Actual code that puts the SoC in different idle states */
 static int kirkwood_enter_idle(struct cpuidle_device *dev,
-				struct cpuidle_driver *drv,
+			       struct cpuidle_driver *drv,
 			       int index)
 {
-	writel(0x7, DDR_OPERATION_BASE);
+	writel(0x7, ddr_operation_base);
 	cpu_do_idle();
 
 	return index;
@@ -51,13 +53,22 @@
 	},
 	.state_count = KIRKWOOD_MAX_STATES,
 };
+static struct cpuidle_device *device;
 
 static DEFINE_PER_CPU(struct cpuidle_device, kirkwood_cpuidle_device);
 
 /* Initialize CPU idle by registering the idle states */
-static int kirkwood_init_cpuidle(void)
+static int kirkwood_cpuidle_probe(struct platform_device *pdev)
 {
-	struct cpuidle_device *device;
+	struct resource *res;
+
+	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (res == NULL)
+		return -EINVAL;
+
+	ddr_operation_base = devm_request_and_ioremap(&pdev->dev, res);
+	if (!ddr_operation_base)
+		return -EADDRNOTAVAIL;
 
 	device = &per_cpu(kirkwood_cpuidle_device, smp_processor_id());
 	device->state_count = KIRKWOOD_MAX_STATES;
@@ -70,4 +81,26 @@
 	return 0;
 }
 
-device_initcall(kirkwood_init_cpuidle);
+int kirkwood_cpuidle_remove(struct platform_device *pdev)
+{
+	cpuidle_unregister_device(device);
+	cpuidle_unregister_driver(&kirkwood_idle_driver);
+
+	return 0;
+}
+
+static struct platform_driver kirkwood_cpuidle_driver = {
+	.probe = kirkwood_cpuidle_probe,
+	.remove = kirkwood_cpuidle_remove,
+	.driver = {
+		   .name = "kirkwood_cpuidle",
+		   .owner = THIS_MODULE,
+		   },
+};
+
+module_platform_driver(kirkwood_cpuidle_driver);
+
+MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
+MODULE_DESCRIPTION("Kirkwood cpu idle driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:kirkwood-cpuidle");
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index fb4a7dd5..e1f6860 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -69,24 +69,15 @@
 {
 	struct cpuidle_device *dev = __this_cpu_read(cpuidle_devices);
 	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(dev);
-	int i, dead_state = -1;
-	int power_usage = INT_MAX;
+	int i;
 
 	if (!drv)
 		return -ENODEV;
 
 	/* Find lowest-power state that supports long-term idle */
-	for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++) {
-		struct cpuidle_state *s = &drv->states[i];
-
-		if (s->power_usage < power_usage && s->enter_dead) {
-			power_usage = s->power_usage;
-			dead_state = i;
-		}
-	}
-
-	if (dead_state != -1)
-		return drv->states[dead_state].enter_dead(dev, dead_state);
+	for (i = drv->state_count - 1; i >= CPUIDLE_DRIVER_STATE_START; i--)
+		if (drv->states[i].enter_dead)
+			return drv->states[i].enter_dead(dev, i);
 
 	return -ENODEV;
 }
diff --git a/drivers/cpuidle/driver.c b/drivers/cpuidle/driver.c
index c2b281a..422c7b6 100644
--- a/drivers/cpuidle/driver.c
+++ b/drivers/cpuidle/driver.c
@@ -19,34 +19,9 @@
 static void __cpuidle_set_cpu_driver(struct cpuidle_driver *drv, int cpu);
 static struct cpuidle_driver * __cpuidle_get_cpu_driver(int cpu);
 
-static void set_power_states(struct cpuidle_driver *drv)
-{
-	int i;
-
-	/*
-	 * cpuidle driver should set the drv->power_specified bit
-	 * before registering if the driver provides
-	 * power_usage numbers.
-	 *
-	 * If power_specified is not set,
-	 * we fill in power_usage with decreasing values as the
-	 * cpuidle code has an implicit assumption that state Cn
-	 * uses less power than C(n-1).
-	 *
-	 * With CONFIG_ARCH_HAS_CPU_RELAX, C0 is already assigned
-	 * an power value of -1.  So we use -2, -3, etc, for other
-	 * c-states.
-	 */
-	for (i = CPUIDLE_DRIVER_STATE_START; i < drv->state_count; i++)
-		drv->states[i].power_usage = -1 - i;
-}
-
 static void __cpuidle_driver_init(struct cpuidle_driver *drv)
 {
 	drv->refcnt = 0;
-
-	if (!drv->power_specified)
-		set_power_states(drv);
 }
 
 static int __cpuidle_register_driver(struct cpuidle_driver *drv, int cpu)
diff --git a/drivers/cpuidle/governors/menu.c b/drivers/cpuidle/governors/menu.c
index 20ea33a..fe343a0 100644
--- a/drivers/cpuidle/governors/menu.c
+++ b/drivers/cpuidle/governors/menu.c
@@ -312,7 +312,6 @@
 {
 	struct menu_device *data = &__get_cpu_var(menu_devices);
 	int latency_req = pm_qos_request(PM_QOS_CPU_DMA_LATENCY);
-	int power_usage = INT_MAX;
 	int i;
 	int multiplier;
 	struct timespec t;
@@ -383,11 +382,8 @@
 		if (s->exit_latency * multiplier > data->predicted_us)
 			continue;
 
-		if (s->power_usage < power_usage) {
-			power_usage = s->power_usage;
-			data->last_state_idx = i;
-			data->exit_us = s->exit_latency;
-		}
+		data->last_state_idx = i;
+		data->exit_us = s->exit_latency;
 	}
 
 	/* not deepest C-state chosen for low predicted residency */
diff --git a/drivers/cpuidle/sysfs.c b/drivers/cpuidle/sysfs.c
index 3409429..428754a 100644
--- a/drivers/cpuidle/sysfs.c
+++ b/drivers/cpuidle/sysfs.c
@@ -374,7 +374,7 @@
 	struct cpuidle_driver *drv = cpuidle_get_cpu_driver(device);
 
 	/* state statistics */
-	for (i = 0; i < drv->state_count; i++) {
+	for (i = 0; i < device->state_count; i++) {
 		kobj = kzalloc(sizeof(struct cpuidle_state_kobj), GFP_KERNEL);
 		if (!kobj)
 			goto error_state;
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 53766f3..3b36797 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -994,6 +994,11 @@
  * @freq:	The frequency given to target function
  * @flags:	Flags handed from devfreq framework.
  *
+ * Locking: This function must be called under rcu_read_lock(). opp is a rcu
+ * protected pointer. The reason for the same is that the opp pointer which is
+ * returned will remain valid for use with opp_get_{voltage, freq} only while
+ * under the locked area. The pointer returned must be used prior to unlocking
+ * with rcu_read_unlock() to maintain the integrity of the pointer.
  */
 struct opp *devfreq_recommended_opp(struct device *dev, unsigned long *freq,
 				    u32 flags)
diff --git a/drivers/devfreq/exynos4_bus.c b/drivers/devfreq/exynos4_bus.c
index 80c745e..46d94e9 100644
--- a/drivers/devfreq/exynos4_bus.c
+++ b/drivers/devfreq/exynos4_bus.c
@@ -73,6 +73,16 @@
 #define EX4210_LV_NUM	(LV_2 + 1)
 #define EX4x12_LV_NUM	(LV_4 + 1)
 
+/**
+ * struct busfreq_opp_info - opp information for bus
+ * @rate:	Frequency in hertz
+ * @volt:	Voltage in microvolts corresponding to this OPP
+ */
+struct busfreq_opp_info {
+	unsigned long rate;
+	unsigned long volt;
+};
+
 struct busfreq_data {
 	enum exynos4_busf_type type;
 	struct device *dev;
@@ -80,7 +90,7 @@
 	bool disabled;
 	struct regulator *vdd_int;
 	struct regulator *vdd_mif; /* Exynos4412/4212 only */
-	struct opp *curr_opp;
+	struct busfreq_opp_info curr_oppinfo;
 	struct exynos4_ppmu dmc[2];
 
 	struct notifier_block pm_notifier;
@@ -296,13 +306,14 @@
 };
 
 
-static int exynos4210_set_busclk(struct busfreq_data *data, struct opp *opp)
+static int exynos4210_set_busclk(struct busfreq_data *data,
+				 struct busfreq_opp_info *oppi)
 {
 	unsigned int index;
 	unsigned int tmp;
 
 	for (index = LV_0; index < EX4210_LV_NUM; index++)
-		if (opp_get_freq(opp) == exynos4210_busclk_table[index].clk)
+		if (oppi->rate == exynos4210_busclk_table[index].clk)
 			break;
 
 	if (index == EX4210_LV_NUM)
@@ -361,13 +372,14 @@
 	return 0;
 }
 
-static int exynos4x12_set_busclk(struct busfreq_data *data, struct opp *opp)
+static int exynos4x12_set_busclk(struct busfreq_data *data,
+				 struct busfreq_opp_info *oppi)
 {
 	unsigned int index;
 	unsigned int tmp;
 
 	for (index = LV_0; index < EX4x12_LV_NUM; index++)
-		if (opp_get_freq(opp) == exynos4x12_mifclk_table[index].clk)
+		if (oppi->rate == exynos4x12_mifclk_table[index].clk)
 			break;
 
 	if (index == EX4x12_LV_NUM)
@@ -576,11 +588,12 @@
 	return -EINVAL;
 }
 
-static int exynos4_bus_setvolt(struct busfreq_data *data, struct opp *opp,
-			       struct opp *oldopp)
+static int exynos4_bus_setvolt(struct busfreq_data *data,
+			       struct busfreq_opp_info *oppi,
+			       struct busfreq_opp_info *oldoppi)
 {
 	int err = 0, tmp;
-	unsigned long volt = opp_get_voltage(opp);
+	unsigned long volt = oppi->volt;
 
 	switch (data->type) {
 	case TYPE_BUSF_EXYNOS4210:
@@ -595,11 +608,11 @@
 		if (err)
 			break;
 
-		tmp = exynos4x12_get_intspec(opp_get_freq(opp));
+		tmp = exynos4x12_get_intspec(oppi->rate);
 		if (tmp < 0) {
 			err = tmp;
 			regulator_set_voltage(data->vdd_mif,
-					      opp_get_voltage(oldopp),
+					      oldoppi->volt,
 					      MAX_SAFEVOLT);
 			break;
 		}
@@ -609,7 +622,7 @@
 		/*  Try to recover */
 		if (err)
 			regulator_set_voltage(data->vdd_mif,
-					      opp_get_voltage(oldopp),
+					      oldoppi->volt,
 					      MAX_SAFEVOLT);
 		break;
 	default:
@@ -626,17 +639,26 @@
 	struct platform_device *pdev = container_of(dev, struct platform_device,
 						    dev);
 	struct busfreq_data *data = platform_get_drvdata(pdev);
-	struct opp *opp = devfreq_recommended_opp(dev, _freq, flags);
-	unsigned long freq = opp_get_freq(opp);
-	unsigned long old_freq = opp_get_freq(data->curr_opp);
+	struct opp *opp;
+	unsigned long freq;
+	unsigned long old_freq = data->curr_oppinfo.rate;
+	struct busfreq_opp_info	new_oppinfo;
 
-	if (IS_ERR(opp))
+	rcu_read_lock();
+	opp = devfreq_recommended_opp(dev, _freq, flags);
+	if (IS_ERR(opp)) {
+		rcu_read_unlock();
 		return PTR_ERR(opp);
+	}
+	new_oppinfo.rate = opp_get_freq(opp);
+	new_oppinfo.volt = opp_get_voltage(opp);
+	rcu_read_unlock();
+	freq = new_oppinfo.rate;
 
 	if (old_freq == freq)
 		return 0;
 
-	dev_dbg(dev, "targetting %lukHz %luuV\n", freq, opp_get_voltage(opp));
+	dev_dbg(dev, "targetting %lukHz %luuV\n", freq, new_oppinfo.volt);
 
 	mutex_lock(&data->lock);
 
@@ -644,17 +666,18 @@
 		goto out;
 
 	if (old_freq < freq)
-		err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+		err = exynos4_bus_setvolt(data, &new_oppinfo,
+					  &data->curr_oppinfo);
 	if (err)
 		goto out;
 
 	if (old_freq != freq) {
 		switch (data->type) {
 		case TYPE_BUSF_EXYNOS4210:
-			err = exynos4210_set_busclk(data, opp);
+			err = exynos4210_set_busclk(data, &new_oppinfo);
 			break;
 		case TYPE_BUSF_EXYNOS4x12:
-			err = exynos4x12_set_busclk(data, opp);
+			err = exynos4x12_set_busclk(data, &new_oppinfo);
 			break;
 		default:
 			err = -EINVAL;
@@ -664,11 +687,12 @@
 		goto out;
 
 	if (old_freq > freq)
-		err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+		err = exynos4_bus_setvolt(data, &new_oppinfo,
+					  &data->curr_oppinfo);
 	if (err)
 		goto out;
 
-	data->curr_opp = opp;
+	data->curr_oppinfo = new_oppinfo;
 out:
 	mutex_unlock(&data->lock);
 	return err;
@@ -702,7 +726,7 @@
 
 	exynos4_read_ppmu(data);
 	busier_dmc = exynos4_get_busier_dmc(data);
-	stat->current_frequency = opp_get_freq(data->curr_opp);
+	stat->current_frequency = data->curr_oppinfo.rate;
 
 	if (busier_dmc)
 		addr = S5P_VA_DMC1;
@@ -933,6 +957,7 @@
 	struct busfreq_data *data = container_of(this, struct busfreq_data,
 						 pm_notifier);
 	struct opp *opp;
+	struct busfreq_opp_info	new_oppinfo;
 	unsigned long maxfreq = ULONG_MAX;
 	int err = 0;
 
@@ -943,18 +968,29 @@
 
 		data->disabled = true;
 
+		rcu_read_lock();
 		opp = opp_find_freq_floor(data->dev, &maxfreq);
+		if (IS_ERR(opp)) {
+			rcu_read_unlock();
+			dev_err(data->dev, "%s: unable to find a min freq\n",
+				__func__);
+			return PTR_ERR(opp);
+		}
+		new_oppinfo.rate = opp_get_freq(opp);
+		new_oppinfo.volt = opp_get_voltage(opp);
+		rcu_read_unlock();
 
-		err = exynos4_bus_setvolt(data, opp, data->curr_opp);
+		err = exynos4_bus_setvolt(data, &new_oppinfo,
+					  &data->curr_oppinfo);
 		if (err)
 			goto unlock;
 
 		switch (data->type) {
 		case TYPE_BUSF_EXYNOS4210:
-			err = exynos4210_set_busclk(data, opp);
+			err = exynos4210_set_busclk(data, &new_oppinfo);
 			break;
 		case TYPE_BUSF_EXYNOS4x12:
-			err = exynos4x12_set_busclk(data, opp);
+			err = exynos4x12_set_busclk(data, &new_oppinfo);
 			break;
 		default:
 			err = -EINVAL;
@@ -962,7 +998,7 @@
 		if (err)
 			goto unlock;
 
-		data->curr_opp = opp;
+		data->curr_oppinfo = new_oppinfo;
 unlock:
 		mutex_unlock(&data->lock);
 		if (err)
@@ -1027,13 +1063,17 @@
 		}
 	}
 
+	rcu_read_lock();
 	opp = opp_find_freq_floor(dev, &exynos4_devfreq_profile.initial_freq);
 	if (IS_ERR(opp)) {
+		rcu_read_unlock();
 		dev_err(dev, "Invalid initial frequency %lu kHz.\n",
 			exynos4_devfreq_profile.initial_freq);
 		return PTR_ERR(opp);
 	}
-	data->curr_opp = opp;
+	data->curr_oppinfo.rate = opp_get_freq(opp);
+	data->curr_oppinfo.volt = opp_get_voltage(opp);
+	rcu_read_unlock();
 
 	platform_set_drvdata(pdev, data);
 
diff --git a/drivers/dma/imx-dma.c b/drivers/dma/imx-dma.c
index dbf0e6f..a7dcf78 100644
--- a/drivers/dma/imx-dma.c
+++ b/drivers/dma/imx-dma.c
@@ -684,9 +684,8 @@
 			break;
 		}
 
-		imxdmac->hw_chaining = 1;
-		if (!imxdma_hw_chain(imxdmac))
-			return -EINVAL;
+		imxdmac->hw_chaining = 0;
+
 		imxdmac->ccr_from_device = (mode | IMX_DMA_TYPE_FIFO) |
 			((IMX_DMA_MEMSIZE_32 | IMX_DMA_TYPE_LINEAR) << 2) |
 			CCR_REN;
diff --git a/drivers/dma/ioat/dma_v3.c b/drivers/dma/ioat/dma_v3.c
index e5fc944..3e9d669 100644
--- a/drivers/dma/ioat/dma_v3.c
+++ b/drivers/dma/ioat/dma_v3.c
@@ -951,7 +951,7 @@
 			goto free_resources;
 		}
 	}
-	dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_TO_DEVICE);
+	dma_sync_single_for_device(dev, dest_dma, PAGE_SIZE, DMA_FROM_DEVICE);
 
 	/* skip validate if the capability is not present */
 	if (!dma_has_cap(DMA_XOR_VAL, dma_chan->device->cap_mask))
diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c
index c39e61b..2a02c11 100644
--- a/drivers/dma/tegra20-apb-dma.c
+++ b/drivers/dma/tegra20-apb-dma.c
@@ -31,8 +31,8 @@
 #include <linux/platform_device.h>
 #include <linux/pm_runtime.h>
 #include <linux/slab.h>
+#include <linux/clk/tegra.h>
 
-#include <mach/clk.h>
 #include "dmaengine.h"
 
 #define TEGRA_APBDMA_GENERAL			0x0
@@ -266,6 +266,7 @@
 		if (async_tx_test_ack(&dma_desc->txd)) {
 			list_del(&dma_desc->node);
 			spin_unlock_irqrestore(&tdc->lock, flags);
+			dma_desc->txd.flags = 0;
 			return dma_desc;
 		}
 	}
@@ -1050,7 +1051,9 @@
 					TEGRA_APBDMA_AHBSEQ_WRAP_SHIFT;
 	ahb_seq |= TEGRA_APBDMA_AHBSEQ_BUS_WIDTH_32;
 
-	csr |= TEGRA_APBDMA_CSR_FLOW | TEGRA_APBDMA_CSR_IE_EOC;
+	csr |= TEGRA_APBDMA_CSR_FLOW;
+	if (flags & DMA_PREP_INTERRUPT)
+		csr |= TEGRA_APBDMA_CSR_IE_EOC;
 	csr |= tdc->dma_sconfig.slave_id << TEGRA_APBDMA_CSR_REQ_SEL_SHIFT;
 
 	apb_seq |= TEGRA_APBDMA_APBSEQ_WRAP_WORD_1;
@@ -1095,7 +1098,8 @@
 		mem += len;
 	}
 	sg_req->last_sg = true;
-	dma_desc->txd.flags = 0;
+	if (flags & DMA_CTRL_ACK)
+		dma_desc->txd.flags = DMA_CTRL_ACK;
 
 	/*
 	 * Make sure that mode should not be conflicting with currently
diff --git a/drivers/edac/edac_mc.c b/drivers/edac/edac_mc.c
index 281f566..d1e9eb1 100644
--- a/drivers/edac/edac_mc.c
+++ b/drivers/edac/edac_mc.c
@@ -340,7 +340,7 @@
 	/*
 	 * Alocate and fill the csrow/channels structs
 	 */
-	mci->csrows = kcalloc(sizeof(*mci->csrows), tot_csrows, GFP_KERNEL);
+	mci->csrows = kcalloc(tot_csrows, sizeof(*mci->csrows), GFP_KERNEL);
 	if (!mci->csrows)
 		goto error;
 	for (row = 0; row < tot_csrows; row++) {
@@ -351,7 +351,7 @@
 		csr->csrow_idx = row;
 		csr->mci = mci;
 		csr->nr_channels = tot_channels;
-		csr->channels = kcalloc(sizeof(*csr->channels), tot_channels,
+		csr->channels = kcalloc(tot_channels, sizeof(*csr->channels),
 					GFP_KERNEL);
 		if (!csr->channels)
 			goto error;
@@ -369,7 +369,7 @@
 	/*
 	 * Allocate and fill the dimm structs
 	 */
-	mci->dimms  = kcalloc(sizeof(*mci->dimms), tot_dimms, GFP_KERNEL);
+	mci->dimms  = kcalloc(tot_dimms, sizeof(*mci->dimms), GFP_KERNEL);
 	if (!mci->dimms)
 		goto error;
 
diff --git a/drivers/edac/edac_pci_sysfs.c b/drivers/edac/edac_pci_sysfs.c
index dc6e905..0056c4d 100644
--- a/drivers/edac/edac_pci_sysfs.c
+++ b/drivers/edac/edac_pci_sysfs.c
@@ -256,7 +256,7 @@
 	struct edac_pci_dev_attribute *edac_pci_dev;
 	edac_pci_dev = (struct edac_pci_dev_attribute *)attr;
 
-	if (edac_pci_dev->show)
+	if (edac_pci_dev->store)
 		return edac_pci_dev->store(edac_pci_dev->value, buffer, count);
 	return -EIO;
 }
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index fd3ae62..982f1f5 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -471,7 +471,7 @@
 	char __iomem *p, *q;
 	int rc;
 
-	if (efi_enabled) {
+	if (efi_enabled(EFI_CONFIG_TABLES)) {
 		if (efi.smbios == EFI_INVALID_TABLE_ADDR)
 			goto error;
 
diff --git a/drivers/firmware/efivars.c b/drivers/firmware/efivars.c
index 7b1c374..f5596db 100644
--- a/drivers/firmware/efivars.c
+++ b/drivers/firmware/efivars.c
@@ -674,7 +674,7 @@
 		err = -EACCES;
 		break;
 	case EFI_NOT_FOUND:
-		err = -ENOENT;
+		err = -EIO;
 		break;
 	default:
 		err = -EINVAL;
@@ -793,6 +793,7 @@
 		spin_unlock(&efivars->lock);
 		efivar_unregister(var);
 		drop_nlink(inode);
+		d_delete(file->f_dentry);
 		dput(file->f_dentry);
 
 	} else {
@@ -994,7 +995,7 @@
 		list_del(&var->list);
 		spin_unlock(&efivars->lock);
 		efivar_unregister(var);
-		drop_nlink(dir);
+		drop_nlink(dentry->d_inode);
 		dput(dentry);
 		return 0;
 	}
@@ -1782,7 +1783,7 @@
 	printk(KERN_INFO "EFI Variables Facility v%s %s\n", EFIVARS_VERSION,
 	       EFIVARS_DATE);
 
-	if (!efi_enabled)
+	if (!efi_enabled(EFI_RUNTIME_SERVICES))
 		return 0;
 
 	/* For now we'll register the efi directory at /sys/firmware/efi */
@@ -1822,7 +1823,7 @@
 static void __exit
 efivars_exit(void)
 {
-	if (efi_enabled) {
+	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
 		unregister_efivars(&__efivars);
 		kobject_put(efi_kobj);
 	}
diff --git a/drivers/firmware/iscsi_ibft_find.c b/drivers/firmware/iscsi_ibft_find.c
index 4da4eb9..2224f1d 100644
--- a/drivers/firmware/iscsi_ibft_find.c
+++ b/drivers/firmware/iscsi_ibft_find.c
@@ -99,7 +99,7 @@
 	/* iBFT 1.03 section 1.4.3.1 mandates that UEFI machines will
 	 * only use ACPI for this */
 
-	if (!efi_enabled)
+	if (!efi_enabled(EFI_BOOT))
 		find_ibft_in_mem();
 
 	if (ibft_addr) {
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 7d9bd94..6819d63 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -547,7 +547,6 @@
 	mvchip->membase = devm_request_and_ioremap(&pdev->dev, res);
 	if (! mvchip->membase) {
 		dev_err(&pdev->dev, "Cannot ioremap\n");
-		kfree(mvchip->chip.label);
 		return -ENOMEM;
 	}
 
@@ -557,14 +556,12 @@
 		res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
 		if (! res) {
 			dev_err(&pdev->dev, "Cannot get memory resource\n");
-			kfree(mvchip->chip.label);
 			return -ENODEV;
 		}
 
 		mvchip->percpu_membase = devm_request_and_ioremap(&pdev->dev, res);
 		if (! mvchip->percpu_membase) {
 			dev_err(&pdev->dev, "Cannot ioremap\n");
-			kfree(mvchip->chip.label);
 			return -ENOMEM;
 		}
 	}
@@ -625,7 +622,6 @@
 	mvchip->irqbase = irq_alloc_descs(-1, 0, ngpios, -1);
 	if (mvchip->irqbase < 0) {
 		dev_err(&pdev->dev, "no irqs\n");
-		kfree(mvchip->chip.label);
 		return -ENOMEM;
 	}
 
@@ -633,7 +629,6 @@
 				    mvchip->membase, handle_level_irq);
 	if (! gc) {
 		dev_err(&pdev->dev, "Cannot allocate generic irq_chip\n");
-		kfree(mvchip->chip.label);
 		return -ENOMEM;
 	}
 
@@ -668,7 +663,6 @@
 		irq_remove_generic_chip(gc, IRQ_MSK(ngpios), IRQ_NOREQUEST,
 					IRQ_LEVEL | IRQ_NOPROBE);
 		kfree(gc);
-		kfree(mvchip->chip.label);
 		return -ENODEV;
 	}
 
diff --git a/drivers/gpio/gpio-samsung.c b/drivers/gpio/gpio-samsung.c
index 01f7fe9..76be7ee 100644
--- a/drivers/gpio/gpio-samsung.c
+++ b/drivers/gpio/gpio-samsung.c
@@ -32,7 +32,6 @@
 
 #include <mach/hardware.h>
 #include <mach/map.h>
-#include <mach/regs-clock.h>
 #include <mach/regs-gpio.h>
 
 #include <plat/cpu.h>
@@ -446,7 +445,7 @@
 };
 #endif
 
-#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_ARCH_EXYNOS5)
+#if defined(CONFIG_ARCH_EXYNOS4) || defined(CONFIG_SOC_EXYNOS5250)
 static struct samsung_gpio_cfg exynos_gpio_cfg = {
 	.set_pull	= exynos_gpio_setpull,
 	.get_pull	= exynos_gpio_getpull,
@@ -2446,7 +2445,7 @@
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_1[] = {
 	{
 		.chip	= {
@@ -2614,7 +2613,7 @@
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_2[] = {
 	{
 		.chip	= {
@@ -2675,7 +2674,7 @@
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_3[] = {
 	{
 		.chip	= {
@@ -2711,7 +2710,7 @@
 };
 #endif
 
-#ifdef CONFIG_ARCH_EXYNOS5
+#ifdef CONFIG_SOC_EXYNOS5250
 static struct samsung_gpio_chip exynos5_gpios_4[] = {
 	{
 		.chip	= {
@@ -3010,7 +3009,7 @@
 	int i, nr_chips;
 	int group = 0;
 
-#ifdef CONFIG_PINCTRL_SAMSUNG
+#if defined(CONFIG_PINCTRL_EXYNOS) || defined(CONFIG_PINCTRL_EXYNOS5440)
 	/*
 	* This gpio driver includes support for device tree support and there
 	* are platforms using it. In order to maintain compatibility with those
@@ -3026,6 +3025,7 @@
 	static const struct of_device_id exynos_pinctrl_ids[] = {
 		{ .compatible = "samsung,pinctrl-exynos4210", },
 		{ .compatible = "samsung,pinctrl-exynos4x12", },
+		{ .compatible = "samsung,pinctrl-exynos5440", },
 	};
 	for_each_matching_node(pctrl_np, exynos_pinctrl_ids)
 		if (pctrl_np && of_device_is_available(pctrl_np))
diff --git a/drivers/gpu/drm/drm_mm.c b/drivers/gpu/drm/drm_mm.c
index 2bf9670..2aa3314 100644
--- a/drivers/gpu/drm/drm_mm.c
+++ b/drivers/gpu/drm/drm_mm.c
@@ -221,11 +221,13 @@
 
 	BUG_ON(!hole_node->hole_follows || node->allocated);
 
-	if (mm->color_adjust)
-		mm->color_adjust(hole_node, color, &adj_start, &adj_end);
-
 	if (adj_start < start)
 		adj_start = start;
+	if (adj_end > end)
+		adj_end = end;
+
+	if (mm->color_adjust)
+		mm->color_adjust(hole_node, color, &adj_start, &adj_end);
 
 	if (alignment) {
 		unsigned tmp = adj_start % alignment;
@@ -506,7 +508,7 @@
 	mm->scan_size = size;
 	mm->scanned_blocks = 0;
 	mm->scan_hit_start = 0;
-	mm->scan_hit_size = 0;
+	mm->scan_hit_end = 0;
 	mm->scan_check_range = 0;
 	mm->prev_scanned_node = NULL;
 }
@@ -533,7 +535,7 @@
 	mm->scan_size = size;
 	mm->scanned_blocks = 0;
 	mm->scan_hit_start = 0;
-	mm->scan_hit_size = 0;
+	mm->scan_hit_end = 0;
 	mm->scan_start = start;
 	mm->scan_end = end;
 	mm->scan_check_range = 1;
@@ -552,8 +554,7 @@
 	struct drm_mm *mm = node->mm;
 	struct drm_mm_node *prev_node;
 	unsigned long hole_start, hole_end;
-	unsigned long adj_start;
-	unsigned long adj_end;
+	unsigned long adj_start, adj_end;
 
 	mm->scanned_blocks++;
 
@@ -570,14 +571,8 @@
 	node->node_list.next = &mm->prev_scanned_node->node_list;
 	mm->prev_scanned_node = node;
 
-	hole_start = drm_mm_hole_node_start(prev_node);
-	hole_end = drm_mm_hole_node_end(prev_node);
-
-	adj_start = hole_start;
-	adj_end = hole_end;
-
-	if (mm->color_adjust)
-		mm->color_adjust(prev_node, mm->scan_color, &adj_start, &adj_end);
+	adj_start = hole_start = drm_mm_hole_node_start(prev_node);
+	adj_end = hole_end = drm_mm_hole_node_end(prev_node);
 
 	if (mm->scan_check_range) {
 		if (adj_start < mm->scan_start)
@@ -586,11 +581,14 @@
 			adj_end = mm->scan_end;
 	}
 
+	if (mm->color_adjust)
+		mm->color_adjust(prev_node, mm->scan_color,
+				 &adj_start, &adj_end);
+
 	if (check_free_hole(adj_start, adj_end,
 			    mm->scan_size, mm->scan_alignment)) {
 		mm->scan_hit_start = hole_start;
-		mm->scan_hit_size = hole_end;
-
+		mm->scan_hit_end = hole_end;
 		return 1;
 	}
 
@@ -626,19 +624,10 @@
 			       node_list);
 
 	prev_node->hole_follows = node->scanned_preceeds_hole;
-	INIT_LIST_HEAD(&node->node_list);
 	list_add(&node->node_list, &prev_node->node_list);
 
-	/* Only need to check for containement because start&size for the
-	 * complete resulting free block (not just the desired part) is
-	 * stored. */
-	if (node->start >= mm->scan_hit_start &&
-	    node->start + node->size
-	    		<= mm->scan_hit_start + mm->scan_hit_size) {
-		return 1;
-	}
-
-	return 0;
+	 return (drm_mm_hole_node_end(node) > mm->scan_hit_start &&
+		 node->start < mm->scan_hit_end);
 }
 EXPORT_SYMBOL(drm_mm_scan_remove_block);
 
diff --git a/drivers/gpu/drm/exynos/Kconfig b/drivers/gpu/drm/exynos/Kconfig
index 1d1f1e5..046bcda 100644
--- a/drivers/gpu/drm/exynos/Kconfig
+++ b/drivers/gpu/drm/exynos/Kconfig
@@ -24,7 +24,7 @@
 
 config DRM_EXYNOS_FIMD
 	bool "Exynos DRM FIMD"
-	depends on DRM_EXYNOS && !FB_S3C
+	depends on DRM_EXYNOS && !FB_S3C && !ARCH_MULTIPLATFORM
 	help
 	  Choose this option if you want to use Exynos FIMD for DRM.
 
@@ -48,7 +48,7 @@
 
 config DRM_EXYNOS_IPP
 	bool "Exynos DRM IPP"
-	depends on DRM_EXYNOS
+	depends on DRM_EXYNOS && !ARCH_MULTIPLATFORM
 	help
 	  Choose this option if you want to use IPP feature for DRM.
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_connector.c b/drivers/gpu/drm/exynos/exynos_drm_connector.c
index ab37437..4c5b685 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_connector.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_connector.c
@@ -18,7 +18,6 @@
 #include "exynos_drm_drv.h"
 #include "exynos_drm_encoder.h"
 
-#define MAX_EDID 256
 #define to_exynos_connector(x)	container_of(x, struct exynos_drm_connector,\
 				drm_connector)
 
@@ -96,7 +95,9 @@
 					to_exynos_connector(connector);
 	struct exynos_drm_manager *manager = exynos_connector->manager;
 	struct exynos_drm_display_ops *display_ops = manager->display_ops;
-	unsigned int count;
+	struct edid *edid = NULL;
+	unsigned int count = 0;
+	int ret;
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
@@ -114,27 +115,21 @@
 	 * because lcd panel has only one mode.
 	 */
 	if (display_ops->get_edid) {
-		int ret;
-		void *edid;
-
-		edid = kzalloc(MAX_EDID, GFP_KERNEL);
-		if (!edid) {
-			DRM_ERROR("failed to allocate edid\n");
-			return 0;
+		edid = display_ops->get_edid(manager->dev, connector);
+		if (IS_ERR_OR_NULL(edid)) {
+			ret = PTR_ERR(edid);
+			edid = NULL;
+			DRM_ERROR("Panel operation get_edid failed %d\n", ret);
+			goto out;
 		}
 
-		ret = display_ops->get_edid(manager->dev, connector,
-						edid, MAX_EDID);
-		if (ret < 0) {
-			DRM_ERROR("failed to get edid data.\n");
-			kfree(edid);
-			edid = NULL;
-			return 0;
+		count = drm_add_edid_modes(connector, edid);
+		if (count < 0) {
+			DRM_ERROR("Add edid modes failed %d\n", count);
+			goto out;
 		}
 
 		drm_mode_connector_update_edid_property(connector, edid);
-		count = drm_add_edid_modes(connector, edid);
-		kfree(edid);
 	} else {
 		struct exynos_drm_panel_info *panel;
 		struct drm_display_mode *mode = drm_mode_create(connector->dev);
@@ -161,6 +156,8 @@
 		count = 1;
 	}
 
+out:
+	kfree(edid);
 	return count;
 }
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
index 9df9771..ba0a3aa 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
@@ -19,6 +19,7 @@
 struct exynos_drm_dmabuf_attachment {
 	struct sg_table sgt;
 	enum dma_data_direction dir;
+	bool is_mapped;
 };
 
 static int exynos_gem_attach_dma_buf(struct dma_buf *dmabuf,
@@ -72,17 +73,10 @@
 
 	DRM_DEBUG_PRIME("%s\n", __FILE__);
 
-	if (WARN_ON(dir == DMA_NONE))
-		return ERR_PTR(-EINVAL);
-
 	/* just return current sgt if already requested. */
-	if (exynos_attach->dir == dir)
+	if (exynos_attach->dir == dir && exynos_attach->is_mapped)
 		return &exynos_attach->sgt;
 
-	/* reattaching is not allowed. */
-	if (WARN_ON(exynos_attach->dir != DMA_NONE))
-		return ERR_PTR(-EBUSY);
-
 	buf = gem_obj->buffer;
 	if (!buf) {
 		DRM_ERROR("buffer is null.\n");
@@ -107,13 +101,17 @@
 		wr = sg_next(wr);
 	}
 
-	nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
-	if (!nents) {
-		DRM_ERROR("failed to map sgl with iommu.\n");
-		sgt = ERR_PTR(-EIO);
-		goto err_unlock;
+	if (dir != DMA_NONE) {
+		nents = dma_map_sg(attach->dev, sgt->sgl, sgt->orig_nents, dir);
+		if (!nents) {
+			DRM_ERROR("failed to map sgl with iommu.\n");
+			sg_free_table(sgt);
+			sgt = ERR_PTR(-EIO);
+			goto err_unlock;
+		}
 	}
 
+	exynos_attach->is_mapped = true;
 	exynos_attach->dir = dir;
 	attach->priv = exynos_attach;
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_drv.h b/drivers/gpu/drm/exynos/exynos_drm_drv.h
index b9e51bc..4606fac7 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_drv.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_drv.h
@@ -148,8 +148,8 @@
 struct exynos_drm_display_ops {
 	enum exynos_drm_output_type type;
 	bool (*is_connected)(struct device *dev);
-	int (*get_edid)(struct device *dev, struct drm_connector *connector,
-				u8 *edid, int len);
+	struct edid *(*get_edid)(struct device *dev,
+			struct drm_connector *connector);
 	void *(*get_panel)(struct device *dev);
 	int (*check_timing)(struct device *dev, void *timing);
 	int (*power_on)(struct device *dev, int mode);
diff --git a/drivers/gpu/drm/exynos/exynos_drm_g2d.c b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
index 36c3905..9a4c08e 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_g2d.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_g2d.c
@@ -324,7 +324,7 @@
 	g2d_userptr = NULL;
 }
 
-dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
+static dma_addr_t *g2d_userptr_get_dma_addr(struct drm_device *drm_dev,
 					unsigned long userptr,
 					unsigned long size,
 					struct drm_file *filp,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
index 850e995..2864453 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.c
@@ -108,18 +108,17 @@
 	return false;
 }
 
-static int drm_hdmi_get_edid(struct device *dev,
-		struct drm_connector *connector, u8 *edid, int len)
+static struct edid *drm_hdmi_get_edid(struct device *dev,
+			struct drm_connector *connector)
 {
 	struct drm_hdmi_context *ctx = to_context(dev);
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
 	if (hdmi_ops && hdmi_ops->get_edid)
-		return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector, edid,
-					  len);
+		return hdmi_ops->get_edid(ctx->hdmi_ctx->ctx, connector);
 
-	return 0;
+	return NULL;
 }
 
 static int drm_hdmi_check_timing(struct device *dev, void *timing)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
index 784a7e9..d80516f 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
+++ b/drivers/gpu/drm/exynos/exynos_drm_hdmi.h
@@ -30,8 +30,8 @@
 struct exynos_hdmi_ops {
 	/* display */
 	bool (*is_connected)(void *ctx);
-	int (*get_edid)(void *ctx, struct drm_connector *connector,
-			u8 *edid, int len);
+	struct edid *(*get_edid)(void *ctx,
+			struct drm_connector *connector);
 	int (*check_timing)(void *ctx, void *timing);
 	int (*power_on)(void *ctx, int mode);
 
diff --git a/drivers/gpu/drm/exynos/exynos_drm_ipp.c b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
index 0bda964..1a55635 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_ipp.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_ipp.c
@@ -869,7 +869,7 @@
 	}
 }
 
-void ipp_handle_cmd_work(struct device *dev,
+static void ipp_handle_cmd_work(struct device *dev,
 		struct exynos_drm_ippdrv *ippdrv,
 		struct drm_exynos_ipp_cmd_work *cmd_work,
 		struct drm_exynos_ipp_cmd_node *c_node)
diff --git a/drivers/gpu/drm/exynos/exynos_drm_rotator.c b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
index e9e83ef..f976e29 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_rotator.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_rotator.c
@@ -734,7 +734,7 @@
 	return 0;
 }
 
-struct rot_limit_table rot_limit_tbl = {
+static struct rot_limit_table rot_limit_tbl = {
 	.ycbcr420_2p = {
 		.min_w = 32,
 		.min_h = 32,
@@ -751,7 +751,7 @@
 	},
 };
 
-struct platform_device_id rotator_driver_ids[] = {
+static struct platform_device_id rotator_driver_ids[] = {
 	{
 		.name		= "exynos-rot",
 		.driver_data	= (unsigned long)&rot_limit_tbl,
diff --git a/drivers/gpu/drm/exynos/exynos_drm_vidi.c b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
index d0ca3c4..13ccbd4 100644
--- a/drivers/gpu/drm/exynos/exynos_drm_vidi.c
+++ b/drivers/gpu/drm/exynos/exynos_drm_vidi.c
@@ -98,10 +98,12 @@
 	return ctx->connected ? true : false;
 }
 
-static int vidi_get_edid(struct device *dev, struct drm_connector *connector,
-				u8 *edid, int len)
+static struct edid *vidi_get_edid(struct device *dev,
+			struct drm_connector *connector)
 {
 	struct vidi_context *ctx = get_vidi_context(dev);
+	struct edid *edid;
+	int edid_len;
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
 
@@ -111,13 +113,18 @@
 	 */
 	if (!ctx->raw_edid) {
 		DRM_DEBUG_KMS("raw_edid is null.\n");
-		return -EFAULT;
+		return ERR_PTR(-EFAULT);
 	}
 
-	memcpy(edid, ctx->raw_edid, min((1 + ctx->raw_edid->extensions)
-					* EDID_LENGTH, len));
+	edid_len = (1 + ctx->raw_edid->extensions) * EDID_LENGTH;
+	edid = kzalloc(edid_len, GFP_KERNEL);
+	if (!edid) {
+		DRM_DEBUG_KMS("failed to allocate edid\n");
+		return ERR_PTR(-ENOMEM);
+	}
 
-	return 0;
+	memcpy(edid, ctx->raw_edid, edid_len);
+	return edid;
 }
 
 static void *vidi_get_panel(struct device *dev)
@@ -514,7 +521,6 @@
 	struct exynos_drm_manager *manager;
 	struct exynos_drm_display_ops *display_ops;
 	struct drm_exynos_vidi_connection *vidi = data;
-	struct edid *raw_edid;
 	int edid_len;
 
 	DRM_DEBUG_KMS("%s\n", __FILE__);
@@ -551,11 +557,11 @@
 	}
 
 	if (vidi->connection) {
-		if (!vidi->edid) {
-			DRM_DEBUG_KMS("edid data is null.\n");
+		struct edid *raw_edid  = (struct edid *)(uint32_t)vidi->edid;
+		if (!drm_edid_is_valid(raw_edid)) {
+			DRM_DEBUG_KMS("edid data is invalid.\n");
 			return -EINVAL;
 		}
-		raw_edid = (struct edid *)(uint32_t)vidi->edid;
 		edid_len = (1 + raw_edid->extensions) * EDID_LENGTH;
 		ctx->raw_edid = kzalloc(edid_len, GFP_KERNEL);
 		if (!ctx->raw_edid) {
diff --git a/drivers/gpu/drm/exynos/exynos_hdmi.c b/drivers/gpu/drm/exynos/exynos_hdmi.c
index 41ff79d..fbab3c4 100644
--- a/drivers/gpu/drm/exynos/exynos_hdmi.c
+++ b/drivers/gpu/drm/exynos/exynos_hdmi.c
@@ -34,7 +34,6 @@
 #include <linux/regulator/consumer.h>
 #include <linux/io.h>
 #include <linux/of_gpio.h>
-#include <plat/gpio-cfg.h>
 
 #include <drm/exynos_drm.h>
 
@@ -98,8 +97,7 @@
 
 	void __iomem			*regs;
 	void				*parent_ctx;
-	int				external_irq;
-	int				internal_irq;
+	int				irq;
 
 	struct i2c_client		*ddc_port;
 	struct i2c_client		*hdmiphy_port;
@@ -1391,8 +1389,7 @@
 	return hdata->hpd;
 }
 
-static int hdmi_get_edid(void *ctx, struct drm_connector *connector,
-				u8 *edid, int len)
+static struct edid *hdmi_get_edid(void *ctx, struct drm_connector *connector)
 {
 	struct edid *raw_edid;
 	struct hdmi_context *hdata = ctx;
@@ -1400,22 +1397,18 @@
 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
 	if (!hdata->ddc_port)
-		return -ENODEV;
+		return ERR_PTR(-ENODEV);
 
 	raw_edid = drm_get_edid(connector, hdata->ddc_port->adapter);
-	if (raw_edid) {
-		hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
-		memcpy(edid, raw_edid, min((1 + raw_edid->extensions)
-					* EDID_LENGTH, len));
-		DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
-			(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
-			raw_edid->width_cm, raw_edid->height_cm);
-		kfree(raw_edid);
-	} else {
-		return -ENODEV;
-	}
+	if (!raw_edid)
+		return ERR_PTR(-ENODEV);
 
-	return 0;
+	hdata->dvi_mode = !drm_detect_hdmi_monitor(raw_edid);
+	DRM_DEBUG_KMS("%s : width[%d] x height[%d]\n",
+		(hdata->dvi_mode ? "dvi monitor" : "hdmi monitor"),
+		raw_edid->width_cm, raw_edid->height_cm);
+
+	return raw_edid;
 }
 
 static int hdmi_v13_check_timing(struct fb_videomode *check_timing)
@@ -1652,16 +1645,16 @@
 
 	/* resetting HDMI core */
 	hdmi_reg_writemask(hdata, reg,  0, HDMI_CORE_SW_RSTOUT);
-	mdelay(10);
+	usleep_range(10000, 12000);
 	hdmi_reg_writemask(hdata, reg, ~0, HDMI_CORE_SW_RSTOUT);
-	mdelay(10);
+	usleep_range(10000, 12000);
 }
 
 static void hdmi_conf_init(struct hdmi_context *hdata)
 {
 	struct hdmi_infoframe infoframe;
 
-	/* disable HPD interrupts */
+	/* disable HPD interrupts from HDMI IP block, use GPIO instead */
 	hdmi_reg_writemask(hdata, HDMI_INTC_CON, 0, HDMI_INTC_EN_GLOBAL |
 		HDMI_INTC_EN_HPD_PLUG | HDMI_INTC_EN_HPD_UNPLUG);
 
@@ -1779,7 +1772,7 @@
 		u32 val = hdmi_reg_read(hdata, HDMI_V13_PHY_STATUS);
 		if (val & HDMI_PHY_STATUS_READY)
 			break;
-		mdelay(1);
+		usleep_range(1000, 2000);
 	}
 	/* steady state not achieved */
 	if (tries == 0) {
@@ -1946,7 +1939,7 @@
 		u32 val = hdmi_reg_read(hdata, HDMI_PHY_STATUS_0);
 		if (val & HDMI_PHY_STATUS_READY)
 			break;
-		mdelay(1);
+		usleep_range(1000, 2000);
 	}
 	/* steady state not achieved */
 	if (tries == 0) {
@@ -1998,9 +1991,9 @@
 
 	/* reset hdmiphy */
 	hdmi_reg_writemask(hdata, reg, ~0, HDMI_PHY_SW_RSTOUT);
-	mdelay(10);
+	usleep_range(10000, 12000);
 	hdmi_reg_writemask(hdata, reg,  0, HDMI_PHY_SW_RSTOUT);
-	mdelay(10);
+	usleep_range(10000, 12000);
 }
 
 static void hdmiphy_poweron(struct hdmi_context *hdata)
@@ -2048,7 +2041,7 @@
 		return;
 	}
 
-	mdelay(10);
+	usleep_range(10000, 12000);
 
 	/* operation mode */
 	operation[0] = 0x1f;
@@ -2170,6 +2163,13 @@
 
 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
+	mutex_lock(&hdata->hdmi_mutex);
+	if (!hdata->powered) {
+		mutex_unlock(&hdata->hdmi_mutex);
+		return;
+	}
+	mutex_unlock(&hdata->hdmi_mutex);
+
 	hdmi_conf_apply(hdata);
 }
 
@@ -2265,7 +2265,7 @@
 	.dpms		= hdmi_dpms,
 };
 
-static irqreturn_t hdmi_external_irq_thread(int irq, void *arg)
+static irqreturn_t hdmi_irq_thread(int irq, void *arg)
 {
 	struct exynos_drm_hdmi_context *ctx = arg;
 	struct hdmi_context *hdata = ctx->ctx;
@@ -2280,31 +2280,6 @@
 	return IRQ_HANDLED;
 }
 
-static irqreturn_t hdmi_internal_irq_thread(int irq, void *arg)
-{
-	struct exynos_drm_hdmi_context *ctx = arg;
-	struct hdmi_context *hdata = ctx->ctx;
-	u32 intc_flag;
-
-	intc_flag = hdmi_reg_read(hdata, HDMI_INTC_FLAG);
-	/* clearing flags for HPD plug/unplug */
-	if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
-		DRM_DEBUG_KMS("unplugged\n");
-		hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
-			HDMI_INTC_FLAG_HPD_UNPLUG);
-	}
-	if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
-		DRM_DEBUG_KMS("plugged\n");
-		hdmi_reg_writemask(hdata, HDMI_INTC_FLAG, ~0,
-			HDMI_INTC_FLAG_HPD_PLUG);
-	}
-
-	if (ctx->drm_dev)
-		drm_helper_hpd_irq_event(ctx->drm_dev);
-
-	return IRQ_HANDLED;
-}
-
 static int hdmi_resources_init(struct hdmi_context *hdata)
 {
 	struct device *dev = hdata->dev;
@@ -2555,39 +2530,24 @@
 
 	hdata->hdmiphy_port = hdmi_hdmiphy;
 
-	hdata->external_irq = gpio_to_irq(hdata->hpd_gpio);
-	if (hdata->external_irq < 0) {
-		DRM_ERROR("failed to get GPIO external irq\n");
-		ret = hdata->external_irq;
-		goto err_hdmiphy;
-	}
-
-	hdata->internal_irq = platform_get_irq(pdev, 0);
-	if (hdata->internal_irq < 0) {
-		DRM_ERROR("failed to get platform internal irq\n");
-		ret = hdata->internal_irq;
+	hdata->irq = gpio_to_irq(hdata->hpd_gpio);
+	if (hdata->irq < 0) {
+		DRM_ERROR("failed to get GPIO irq\n");
+		ret = hdata->irq;
 		goto err_hdmiphy;
 	}
 
 	hdata->hpd = gpio_get_value(hdata->hpd_gpio);
 
-	ret = request_threaded_irq(hdata->external_irq, NULL,
-			hdmi_external_irq_thread, IRQF_TRIGGER_RISING |
+	ret = request_threaded_irq(hdata->irq, NULL,
+			hdmi_irq_thread, IRQF_TRIGGER_RISING |
 			IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
-			"hdmi_external", drm_hdmi_ctx);
+			"hdmi", drm_hdmi_ctx);
 	if (ret) {
-		DRM_ERROR("failed to register hdmi external interrupt\n");
+		DRM_ERROR("failed to register hdmi interrupt\n");
 		goto err_hdmiphy;
 	}
 
-	ret = request_threaded_irq(hdata->internal_irq, NULL,
-			hdmi_internal_irq_thread, IRQF_ONESHOT,
-			"hdmi_internal", drm_hdmi_ctx);
-	if (ret) {
-		DRM_ERROR("failed to register hdmi internal interrupt\n");
-		goto err_free_irq;
-	}
-
 	/* Attach HDMI Driver to common hdmi. */
 	exynos_hdmi_drv_attach(drm_hdmi_ctx);
 
@@ -2598,8 +2558,6 @@
 
 	return 0;
 
-err_free_irq:
-	free_irq(hdata->external_irq, drm_hdmi_ctx);
 err_hdmiphy:
 	i2c_del_driver(&hdmiphy_driver);
 err_ddc:
@@ -2617,8 +2575,7 @@
 
 	pm_runtime_disable(dev);
 
-	free_irq(hdata->internal_irq, hdata);
-	free_irq(hdata->external_irq, hdata);
+	free_irq(hdata->irq, hdata);
 
 
 	/* hdmiphy i2c driver */
@@ -2637,8 +2594,7 @@
 
 	DRM_DEBUG_KMS("[%d] %s\n", __LINE__, __func__);
 
-	disable_irq(hdata->internal_irq);
-	disable_irq(hdata->external_irq);
+	disable_irq(hdata->irq);
 
 	hdata->hpd = false;
 	if (ctx->drm_dev)
@@ -2663,8 +2619,7 @@
 
 	hdata->hpd = gpio_get_value(hdata->hpd_gpio);
 
-	enable_irq(hdata->external_irq);
-	enable_irq(hdata->internal_irq);
+	enable_irq(hdata->irq);
 
 	if (!pm_runtime_suspended(dev)) {
 		DRM_DEBUG_KMS("%s : Already resumed\n", __func__);
diff --git a/drivers/gpu/drm/exynos/exynos_mixer.c b/drivers/gpu/drm/exynos/exynos_mixer.c
index c187ea3..c414584 100644
--- a/drivers/gpu/drm/exynos/exynos_mixer.c
+++ b/drivers/gpu/drm/exynos/exynos_mixer.c
@@ -600,7 +600,7 @@
 		/* waiting until VP_SRESET_PROCESSING is 0 */
 		if (~vp_reg_read(res, VP_SRESET) & VP_SRESET_PROCESSING)
 			break;
-		mdelay(10);
+		usleep_range(10000, 12000);
 	}
 	WARN(tries == 0, "failed to reset Video Processor\n");
 }
@@ -776,6 +776,13 @@
 
 	DRM_DEBUG_KMS("[%d] %s, win: %d\n", __LINE__, __func__, win);
 
+	mutex_lock(&mixer_ctx->mixer_mutex);
+	if (!mixer_ctx->powered) {
+		mutex_unlock(&mixer_ctx->mixer_mutex);
+		return;
+	}
+	mutex_unlock(&mixer_ctx->mixer_mutex);
+
 	if (win > 1 && mixer_ctx->vp_enabled)
 		vp_video_buffer(mixer_ctx, win);
 	else
diff --git a/drivers/gpu/drm/i915/i915_debugfs.c b/drivers/gpu/drm/i915/i915_debugfs.c
index e6a11ca8..9d4a2c2 100644
--- a/drivers/gpu/drm/i915/i915_debugfs.c
+++ b/drivers/gpu/drm/i915/i915_debugfs.c
@@ -30,6 +30,7 @@
 #include <linux/debugfs.h>
 #include <linux/slab.h>
 #include <linux/export.h>
+#include <generated/utsrelease.h>
 #include <drm/drmP.h>
 #include "intel_drv.h"
 #include "intel_ringbuffer.h"
@@ -641,6 +642,7 @@
 	seq_printf(m, "%s command stream:\n", ring_str(ring));
 	seq_printf(m, "  HEAD: 0x%08x\n", error->head[ring]);
 	seq_printf(m, "  TAIL: 0x%08x\n", error->tail[ring]);
+	seq_printf(m, "  CTL: 0x%08x\n", error->ctl[ring]);
 	seq_printf(m, "  ACTHD: 0x%08x\n", error->acthd[ring]);
 	seq_printf(m, "  IPEIR: 0x%08x\n", error->ipeir[ring]);
 	seq_printf(m, "  IPEHR: 0x%08x\n", error->ipehr[ring]);
@@ -689,10 +691,13 @@
 
 	seq_printf(m, "Time: %ld s %ld us\n", error->time.tv_sec,
 		   error->time.tv_usec);
+	seq_printf(m, "Kernel: " UTS_RELEASE);
 	seq_printf(m, "PCI ID: 0x%04x\n", dev->pci_device);
 	seq_printf(m, "EIR: 0x%08x\n", error->eir);
 	seq_printf(m, "IER: 0x%08x\n", error->ier);
 	seq_printf(m, "PGTBL_ER: 0x%08x\n", error->pgtbl_er);
+	seq_printf(m, "FORCEWAKE: 0x%08x\n", error->forcewake);
+	seq_printf(m, "DERRMR: 0x%08x\n", error->derrmr);
 	seq_printf(m, "CCID: 0x%08x\n", error->ccid);
 
 	for (i = 0; i < dev_priv->num_fence_regs; i++)
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index ed30595..12ab3bd 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -188,10 +188,13 @@
 	u32 pgtbl_er;
 	u32 ier;
 	u32 ccid;
+	u32 derrmr;
+	u32 forcewake;
 	bool waiting[I915_NUM_RINGS];
 	u32 pipestat[I915_MAX_PIPES];
 	u32 tail[I915_NUM_RINGS];
 	u32 head[I915_NUM_RINGS];
+	u32 ctl[I915_NUM_RINGS];
 	u32 ipeir[I915_NUM_RINGS];
 	u32 ipehr[I915_NUM_RINGS];
 	u32 instdone[I915_NUM_RINGS];
diff --git a/drivers/gpu/drm/i915/i915_gem.c b/drivers/gpu/drm/i915/i915_gem.c
index da3c82e3..8febea6 100644
--- a/drivers/gpu/drm/i915/i915_gem.c
+++ b/drivers/gpu/drm/i915/i915_gem.c
@@ -1717,7 +1717,8 @@
 }
 
 static long
-i915_gem_purge(struct drm_i915_private *dev_priv, long target)
+__i915_gem_shrink(struct drm_i915_private *dev_priv, long target,
+		  bool purgeable_only)
 {
 	struct drm_i915_gem_object *obj, *next;
 	long count = 0;
@@ -1725,7 +1726,7 @@
 	list_for_each_entry_safe(obj, next,
 				 &dev_priv->mm.unbound_list,
 				 gtt_list) {
-		if (i915_gem_object_is_purgeable(obj) &&
+		if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) &&
 		    i915_gem_object_put_pages(obj) == 0) {
 			count += obj->base.size >> PAGE_SHIFT;
 			if (count >= target)
@@ -1736,7 +1737,7 @@
 	list_for_each_entry_safe(obj, next,
 				 &dev_priv->mm.inactive_list,
 				 mm_list) {
-		if (i915_gem_object_is_purgeable(obj) &&
+		if ((i915_gem_object_is_purgeable(obj) || !purgeable_only) &&
 		    i915_gem_object_unbind(obj) == 0 &&
 		    i915_gem_object_put_pages(obj) == 0) {
 			count += obj->base.size >> PAGE_SHIFT;
@@ -1748,6 +1749,12 @@
 	return count;
 }
 
+static long
+i915_gem_purge(struct drm_i915_private *dev_priv, long target)
+{
+	return __i915_gem_shrink(dev_priv, target, true);
+}
+
 static void
 i915_gem_shrink_all(struct drm_i915_private *dev_priv)
 {
@@ -3522,14 +3529,15 @@
 		goto out;
 	}
 
-	obj->user_pin_count++;
-	obj->pin_filp = file;
-	if (obj->user_pin_count == 1) {
+	if (obj->user_pin_count == 0) {
 		ret = i915_gem_object_pin(obj, args->alignment, true, false);
 		if (ret)
 			goto out;
 	}
 
+	obj->user_pin_count++;
+	obj->pin_filp = file;
+
 	/* XXX - flush the CPU caches for pinned objects
 	 * as the X server doesn't manage domains yet
 	 */
@@ -4395,6 +4403,9 @@
 	if (nr_to_scan) {
 		nr_to_scan -= i915_gem_purge(dev_priv, nr_to_scan);
 		if (nr_to_scan > 0)
+			nr_to_scan -= __i915_gem_shrink(dev_priv, nr_to_scan,
+							false);
+		if (nr_to_scan > 0)
 			i915_gem_shrink_all(dev_priv);
 	}
 
@@ -4402,7 +4413,7 @@
 	list_for_each_entry(obj, &dev_priv->mm.unbound_list, gtt_list)
 		if (obj->pages_pin_count == 0)
 			cnt += obj->base.size >> PAGE_SHIFT;
-	list_for_each_entry(obj, &dev_priv->mm.bound_list, gtt_list)
+	list_for_each_entry(obj, &dev_priv->mm.inactive_list, gtt_list)
 		if (obj->pin_count == 0 && obj->pages_pin_count == 0)
 			cnt += obj->base.size >> PAGE_SHIFT;
 
diff --git a/drivers/gpu/drm/i915/i915_gem_execbuffer.c b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
index d6a994a..26d08bb 100644
--- a/drivers/gpu/drm/i915/i915_gem_execbuffer.c
+++ b/drivers/gpu/drm/i915/i915_gem_execbuffer.c
@@ -539,6 +539,8 @@
 	total = 0;
 	for (i = 0; i < count; i++) {
 		struct drm_i915_gem_relocation_entry __user *user_relocs;
+		u64 invalid_offset = (u64)-1;
+		int j;
 
 		user_relocs = (void __user *)(uintptr_t)exec[i].relocs_ptr;
 
@@ -549,6 +551,25 @@
 			goto err;
 		}
 
+		/* As we do not update the known relocation offsets after
+		 * relocating (due to the complexities in lock handling),
+		 * we need to mark them as invalid now so that we force the
+		 * relocation processing next time. Just in case the target
+		 * object is evicted and then rebound into its old
+		 * presumed_offset before the next execbuffer - if that
+		 * happened we would make the mistake of assuming that the
+		 * relocations were valid.
+		 */
+		for (j = 0; j < exec[i].relocation_count; j++) {
+			if (copy_to_user(&user_relocs[j].presumed_offset,
+					 &invalid_offset,
+					 sizeof(invalid_offset))) {
+				ret = -EFAULT;
+				mutex_lock(&dev->struct_mutex);
+				goto err;
+			}
+		}
+
 		reloc_offset[i] = total;
 		total += exec[i].relocation_count;
 	}
diff --git a/drivers/gpu/drm/i915/i915_irq.c b/drivers/gpu/drm/i915/i915_irq.c
index 2220dec..fe84338 100644
--- a/drivers/gpu/drm/i915/i915_irq.c
+++ b/drivers/gpu/drm/i915/i915_irq.c
@@ -1157,6 +1157,7 @@
 	error->acthd[ring->id] = intel_ring_get_active_head(ring);
 	error->head[ring->id] = I915_READ_HEAD(ring);
 	error->tail[ring->id] = I915_READ_TAIL(ring);
+	error->ctl[ring->id] = I915_READ_CTL(ring);
 
 	error->cpu_ring_head[ring->id] = ring->head;
 	error->cpu_ring_tail[ring->id] = ring->tail;
@@ -1251,6 +1252,16 @@
 	else
 		error->ier = I915_READ(IER);
 
+	if (INTEL_INFO(dev)->gen >= 6)
+		error->derrmr = I915_READ(DERRMR);
+
+	if (IS_VALLEYVIEW(dev))
+		error->forcewake = I915_READ(FORCEWAKE_VLV);
+	else if (INTEL_INFO(dev)->gen >= 7)
+		error->forcewake = I915_READ(FORCEWAKE_MT);
+	else if (INTEL_INFO(dev)->gen == 6)
+		error->forcewake = I915_READ(FORCEWAKE);
+
 	for_each_pipe(pipe)
 		error->pipestat[pipe] = I915_READ(PIPESTAT(pipe));
 
diff --git a/drivers/gpu/drm/i915/i915_reg.h b/drivers/gpu/drm/i915/i915_reg.h
index 186ee5c..59afb7e 100644
--- a/drivers/gpu/drm/i915/i915_reg.h
+++ b/drivers/gpu/drm/i915/i915_reg.h
@@ -512,6 +512,8 @@
 #define GEN7_ERR_INT	0x44040
 #define   ERR_INT_MMIO_UNCLAIMED (1<<13)
 
+#define DERRMR		0x44050
+
 /* GM45+ chicken bits -- debug workaround bits that may be required
  * for various sorts of correct behavior.  The top 16 bits of each are
  * the enables for writing to the corresponding low bit.
@@ -531,6 +533,7 @@
 #define MI_MODE		0x0209c
 # define VS_TIMER_DISPATCH				(1 << 6)
 # define MI_FLUSH_ENABLE				(1 << 12)
+# define ASYNC_FLIP_PERF_DISABLE			(1 << 14)
 
 #define GEN6_GT_MODE	0x20d0
 #define   GEN6_GT_MODE_HI				(1 << 9)
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index a9fb046..da1ad9c 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -8598,19 +8598,30 @@
 {
 	int ret;
 
-	if (obj->tiling_mode == I915_TILING_Y)
+	if (obj->tiling_mode == I915_TILING_Y) {
+		DRM_DEBUG("hardware does not support tiling Y\n");
 		return -EINVAL;
+	}
 
-	if (mode_cmd->pitches[0] & 63)
+	if (mode_cmd->pitches[0] & 63) {
+		DRM_DEBUG("pitch (%d) must be at least 64 byte aligned\n",
+			  mode_cmd->pitches[0]);
 		return -EINVAL;
+	}
 
 	/* FIXME <= Gen4 stride limits are bit unclear */
-	if (mode_cmd->pitches[0] > 32768)
+	if (mode_cmd->pitches[0] > 32768) {
+		DRM_DEBUG("pitch (%d) must be at less than 32768\n",
+			  mode_cmd->pitches[0]);
 		return -EINVAL;
+	}
 
 	if (obj->tiling_mode != I915_TILING_NONE &&
-	    mode_cmd->pitches[0] != obj->stride)
+	    mode_cmd->pitches[0] != obj->stride) {
+		DRM_DEBUG("pitch (%d) must match tiling stride (%d)\n",
+			  mode_cmd->pitches[0], obj->stride);
 		return -EINVAL;
+	}
 
 	/* Reject formats not supported by any plane early. */
 	switch (mode_cmd->pixel_format) {
@@ -8621,8 +8632,10 @@
 		break;
 	case DRM_FORMAT_XRGB1555:
 	case DRM_FORMAT_ARGB1555:
-		if (INTEL_INFO(dev)->gen > 3)
+		if (INTEL_INFO(dev)->gen > 3) {
+			DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
 			return -EINVAL;
+		}
 		break;
 	case DRM_FORMAT_XBGR8888:
 	case DRM_FORMAT_ABGR8888:
@@ -8630,18 +8643,22 @@
 	case DRM_FORMAT_ARGB2101010:
 	case DRM_FORMAT_XBGR2101010:
 	case DRM_FORMAT_ABGR2101010:
-		if (INTEL_INFO(dev)->gen < 4)
+		if (INTEL_INFO(dev)->gen < 4) {
+			DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
 			return -EINVAL;
+		}
 		break;
 	case DRM_FORMAT_YUYV:
 	case DRM_FORMAT_UYVY:
 	case DRM_FORMAT_YVYU:
 	case DRM_FORMAT_VYUY:
-		if (INTEL_INFO(dev)->gen < 6)
+		if (INTEL_INFO(dev)->gen < 5) {
+			DRM_DEBUG("invalid format: 0x%08x\n", mode_cmd->pixel_format);
 			return -EINVAL;
+		}
 		break;
 	default:
-		DRM_DEBUG_KMS("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format);
+		DRM_DEBUG("unsupported pixel format 0x%08x\n", mode_cmd->pixel_format);
 		return -EINVAL;
 	}
 
diff --git a/drivers/gpu/drm/i915/intel_dp.c b/drivers/gpu/drm/i915/intel_dp.c
index 1b63d55..fb3715b 100644
--- a/drivers/gpu/drm/i915/intel_dp.c
+++ b/drivers/gpu/drm/i915/intel_dp.c
@@ -2579,7 +2579,8 @@
 
 static void
 intel_dp_init_panel_power_sequencer(struct drm_device *dev,
-				    struct intel_dp *intel_dp)
+				    struct intel_dp *intel_dp,
+				    struct edp_power_seq *out)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct edp_power_seq cur, vbt, spec, final;
@@ -2650,16 +2651,35 @@
 	intel_dp->panel_power_cycle_delay = get_delay(t11_t12);
 #undef get_delay
 
+	DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
+		      intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
+		      intel_dp->panel_power_cycle_delay);
+
+	DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
+		      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
+
+	if (out)
+		*out = final;
+}
+
+static void
+intel_dp_init_panel_power_sequencer_registers(struct drm_device *dev,
+					      struct intel_dp *intel_dp,
+					      struct edp_power_seq *seq)
+{
+	struct drm_i915_private *dev_priv = dev->dev_private;
+	u32 pp_on, pp_off, pp_div;
+
 	/* And finally store the new values in the power sequencer. */
-	pp_on = (final.t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
-		(final.t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
-	pp_off = (final.t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
-		 (final.t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
+	pp_on = (seq->t1_t3 << PANEL_POWER_UP_DELAY_SHIFT) |
+		(seq->t8 << PANEL_LIGHT_ON_DELAY_SHIFT);
+	pp_off = (seq->t9 << PANEL_LIGHT_OFF_DELAY_SHIFT) |
+		 (seq->t10 << PANEL_POWER_DOWN_DELAY_SHIFT);
 	/* Compute the divisor for the pp clock, simply match the Bspec
 	 * formula. */
 	pp_div = ((100 * intel_pch_rawclk(dev))/2 - 1)
 			<< PP_REFERENCE_DIVIDER_SHIFT;
-	pp_div |= (DIV_ROUND_UP(final.t11_t12, 1000)
+	pp_div |= (DIV_ROUND_UP(seq->t11_t12, 1000)
 			<< PANEL_POWER_CYCLE_DELAY_SHIFT);
 
 	/* Haswell doesn't have any port selection bits for the panel
@@ -2675,14 +2695,6 @@
 	I915_WRITE(PCH_PP_OFF_DELAYS, pp_off);
 	I915_WRITE(PCH_PP_DIVISOR, pp_div);
 
-
-	DRM_DEBUG_KMS("panel power up delay %d, power down delay %d, power cycle delay %d\n",
-		      intel_dp->panel_power_up_delay, intel_dp->panel_power_down_delay,
-		      intel_dp->panel_power_cycle_delay);
-
-	DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
-		      intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
-
 	DRM_DEBUG_KMS("panel power sequencer register settings: PP_ON %#x, PP_OFF %#x, PP_DIV %#x\n",
 		      I915_READ(PCH_PP_ON_DELAYS),
 		      I915_READ(PCH_PP_OFF_DELAYS),
@@ -2699,6 +2711,7 @@
 	struct drm_device *dev = intel_encoder->base.dev;
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	struct drm_display_mode *fixed_mode = NULL;
+	struct edp_power_seq power_seq = { 0 };
 	enum port port = intel_dig_port->port;
 	const char *name = NULL;
 	int type;
@@ -2771,7 +2784,7 @@
 	}
 
 	if (is_edp(intel_dp))
-		intel_dp_init_panel_power_sequencer(dev, intel_dp);
+		intel_dp_init_panel_power_sequencer(dev, intel_dp, &power_seq);
 
 	intel_dp_i2c_init(intel_dp, intel_connector, name);
 
@@ -2798,6 +2811,10 @@
 			return;
 		}
 
+		/* We now know it's not a ghost, init power sequence regs. */
+		intel_dp_init_panel_power_sequencer_registers(dev, intel_dp,
+							      &power_seq);
+
 		ironlake_edp_panel_vdd_on(intel_dp);
 		edid = drm_get_edid(connector, &intel_dp->adapter);
 		if (edid) {
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index b9a660a..17aee74 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -776,14 +776,6 @@
 	},
 	{
 		.callback = intel_no_lvds_dmi_callback,
-		.ident = "ZOTAC ZBOXSD-ID12/ID13",
-		.matches = {
-			DMI_MATCH(DMI_BOARD_VENDOR, "ZOTAC"),
-			DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"),
-		},
-	},
-	{
-		.callback = intel_no_lvds_dmi_callback,
 		.ident = "Gigabyte GA-D525TUD",
 		.matches = {
 			DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c
index e6f54ff..3280cff 100644
--- a/drivers/gpu/drm/i915/intel_pm.c
+++ b/drivers/gpu/drm/i915/intel_pm.c
@@ -44,6 +44,14 @@
  * i915.i915_enable_fbc parameter
  */
 
+static bool intel_crtc_active(struct drm_crtc *crtc)
+{
+	/* Be paranoid as we can arrive here with only partial
+	 * state retrieved from the hardware during setup.
+	 */
+	return to_intel_crtc(crtc)->active && crtc->fb && crtc->mode.clock;
+}
+
 static void i8xx_disable_fbc(struct drm_device *dev)
 {
 	struct drm_i915_private *dev_priv = dev->dev_private;
@@ -405,9 +413,8 @@
 	 *   - going to an unsupported config (interlace, pixel multiply, etc.)
 	 */
 	list_for_each_entry(tmp_crtc, &dev->mode_config.crtc_list, head) {
-		if (to_intel_crtc(tmp_crtc)->active &&
-		    !to_intel_crtc(tmp_crtc)->primary_disabled &&
-		    tmp_crtc->fb) {
+		if (intel_crtc_active(tmp_crtc) &&
+		    !to_intel_crtc(tmp_crtc)->primary_disabled) {
 			if (crtc) {
 				DRM_DEBUG_KMS("more than one pipe active, disabling compression\n");
 				dev_priv->no_fbc_reason = FBC_MULTIPLE_PIPES;
@@ -992,7 +999,7 @@
 	struct drm_crtc *crtc, *enabled = NULL;
 
 	list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
-		if (to_intel_crtc(crtc)->active && crtc->fb) {
+		if (intel_crtc_active(crtc)) {
 			if (enabled)
 				return NULL;
 			enabled = crtc;
@@ -1086,7 +1093,7 @@
 	int entries, tlb_miss;
 
 	crtc = intel_get_crtc_for_plane(dev, plane);
-	if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) {
+	if (!intel_crtc_active(crtc)) {
 		*cursor_wm = cursor->guard_size;
 		*plane_wm = display->guard_size;
 		return false;
@@ -1215,7 +1222,7 @@
 	int entries;
 
 	crtc = intel_get_crtc_for_plane(dev, plane);
-	if (crtc->fb == NULL || !to_intel_crtc(crtc)->active)
+	if (!intel_crtc_active(crtc))
 		return false;
 
 	clock = crtc->mode.clock;	/* VESA DOT Clock */
@@ -1476,7 +1483,7 @@
 
 	fifo_size = dev_priv->display.get_fifo_size(dev, 0);
 	crtc = intel_get_crtc_for_plane(dev, 0);
-	if (to_intel_crtc(crtc)->active && crtc->fb) {
+	if (intel_crtc_active(crtc)) {
 		int cpp = crtc->fb->bits_per_pixel / 8;
 		if (IS_GEN2(dev))
 			cpp = 4;
@@ -1490,7 +1497,7 @@
 
 	fifo_size = dev_priv->display.get_fifo_size(dev, 1);
 	crtc = intel_get_crtc_for_plane(dev, 1);
-	if (to_intel_crtc(crtc)->active && crtc->fb) {
+	if (intel_crtc_active(crtc)) {
 		int cpp = crtc->fb->bits_per_pixel / 8;
 		if (IS_GEN2(dev))
 			cpp = 4;
@@ -2044,7 +2051,7 @@
 	int entries, tlb_miss;
 
 	crtc = intel_get_crtc_for_plane(dev, plane);
-	if (crtc->fb == NULL || !to_intel_crtc(crtc)->active) {
+	if (!intel_crtc_active(crtc)) {
 		*sprite_wm = display->guard_size;
 		return false;
 	}
@@ -4243,7 +4250,8 @@
 static void __gen6_gt_force_wake_mt_reset(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(0xffff));
-	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
+	/* something from same cacheline, but !FORCEWAKE_MT */
+	POSTING_READ(ECOBUS);
 }
 
 static void __gen6_gt_force_wake_mt_get(struct drm_i915_private *dev_priv)
@@ -4260,7 +4268,8 @@
 		DRM_ERROR("Timed out waiting for forcewake old ack to clear.\n");
 
 	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_ENABLE(FORCEWAKE_KERNEL));
-	POSTING_READ(ECOBUS); /* something from same cacheline, but !FORCEWAKE */
+	/* something from same cacheline, but !FORCEWAKE_MT */
+	POSTING_READ(ECOBUS);
 
 	if (wait_for_atomic((I915_READ_NOTRACE(forcewake_ack) & 1),
 			    FORCEWAKE_ACK_TIMEOUT_MS))
@@ -4297,14 +4306,16 @@
 static void __gen6_gt_force_wake_put(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE_NOTRACE(FORCEWAKE, 0);
-	/* gen6_gt_check_fifodbg doubles as the POSTING_READ */
+	/* something from same cacheline, but !FORCEWAKE */
+	POSTING_READ(ECOBUS);
 	gen6_gt_check_fifodbg(dev_priv);
 }
 
 static void __gen6_gt_force_wake_mt_put(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE_NOTRACE(FORCEWAKE_MT, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-	/* gen6_gt_check_fifodbg doubles as the POSTING_READ */
+	/* something from same cacheline, but !FORCEWAKE_MT */
+	POSTING_READ(ECOBUS);
 	gen6_gt_check_fifodbg(dev_priv);
 }
 
@@ -4344,6 +4355,8 @@
 static void vlv_force_wake_reset(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(0xffff));
+	/* something from same cacheline, but !FORCEWAKE_VLV */
+	POSTING_READ(FORCEWAKE_ACK_VLV);
 }
 
 static void vlv_force_wake_get(struct drm_i915_private *dev_priv)
@@ -4364,7 +4377,8 @@
 static void vlv_force_wake_put(struct drm_i915_private *dev_priv)
 {
 	I915_WRITE_NOTRACE(FORCEWAKE_VLV, _MASKED_BIT_DISABLE(FORCEWAKE_KERNEL));
-	/* The below doubles as a POSTING_READ */
+	/* something from same cacheline, but !FORCEWAKE_VLV */
+	POSTING_READ(FORCEWAKE_ACK_VLV);
 	gen6_gt_check_fifodbg(dev_priv);
 }
 
diff --git a/drivers/gpu/drm/i915/intel_ringbuffer.c b/drivers/gpu/drm/i915/intel_ringbuffer.c
index ae253e0..42ff97d 100644
--- a/drivers/gpu/drm/i915/intel_ringbuffer.c
+++ b/drivers/gpu/drm/i915/intel_ringbuffer.c
@@ -505,13 +505,25 @@
 	struct drm_i915_private *dev_priv = dev->dev_private;
 	int ret = init_ring_common(ring);
 
-	if (INTEL_INFO(dev)->gen > 3) {
+	if (INTEL_INFO(dev)->gen > 3)
 		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(VS_TIMER_DISPATCH));
-		if (IS_GEN7(dev))
-			I915_WRITE(GFX_MODE_GEN7,
-				   _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
-				   _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
-	}
+
+	/* We need to disable the AsyncFlip performance optimisations in order
+	 * to use MI_WAIT_FOR_EVENT within the CS. It should already be
+	 * programmed to '1' on all products.
+	 */
+	if (INTEL_INFO(dev)->gen >= 6)
+		I915_WRITE(MI_MODE, _MASKED_BIT_ENABLE(ASYNC_FLIP_PERF_DISABLE));
+
+	/* Required for the hardware to program scanline values for waiting */
+	if (INTEL_INFO(dev)->gen == 6)
+		I915_WRITE(GFX_MODE,
+			   _MASKED_BIT_ENABLE(GFX_TLB_INVALIDATE_ALWAYS));
+
+	if (IS_GEN7(dev))
+		I915_WRITE(GFX_MODE_GEN7,
+			   _MASKED_BIT_DISABLE(GFX_TLB_INVALIDATE_ALWAYS) |
+			   _MASKED_BIT_ENABLE(GFX_REPLAY_MODE));
 
 	if (INTEL_INFO(dev)->gen >= 5) {
 		ret = init_pipe_control(ring);
diff --git a/drivers/gpu/drm/i915/intel_sprite.c b/drivers/gpu/drm/i915/intel_sprite.c
index 827dcd4..d7b060e 100644
--- a/drivers/gpu/drm/i915/intel_sprite.c
+++ b/drivers/gpu/drm/i915/intel_sprite.c
@@ -120,11 +120,10 @@
 	I915_WRITE(SPRSTRIDE(pipe), fb->pitches[0]);
 	I915_WRITE(SPRPOS(pipe), (crtc_y << 16) | crtc_x);
 
-	linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	sprsurf_offset =
 		intel_gen4_compute_offset_xtiled(&x, &y,
-						 fb->bits_per_pixel / 8,
-						 fb->pitches[0]);
+						 pixel_size, fb->pitches[0]);
 	linear_offset -= sprsurf_offset;
 
 	/* HSW consolidates SPRTILEOFF and SPRLINOFF into a single SPROFFSET
@@ -286,11 +285,10 @@
 	I915_WRITE(DVSSTRIDE(pipe), fb->pitches[0]);
 	I915_WRITE(DVSPOS(pipe), (crtc_y << 16) | crtc_x);
 
-	linear_offset = y * fb->pitches[0] + x * (fb->bits_per_pixel / 8);
+	linear_offset = y * fb->pitches[0] + x * pixel_size;
 	dvssurf_offset =
 		intel_gen4_compute_offset_xtiled(&x, &y,
-						 fb->bits_per_pixel / 8,
-						 fb->pitches[0]);
+						 pixel_size, fb->pitches[0]);
 	linear_offset -= dvssurf_offset;
 
 	if (obj->tiling_mode != I915_TILING_NONE)
diff --git a/drivers/gpu/drm/nouveau/core/core/client.c b/drivers/gpu/drm/nouveau/core/core/client.c
index c617f04..8bbb58f 100644
--- a/drivers/gpu/drm/nouveau/core/core/client.c
+++ b/drivers/gpu/drm/nouveau/core/core/client.c
@@ -66,10 +66,8 @@
 
 	ret = nouveau_handle_create(nv_object(client), ~0, ~0,
 				    nv_object(client), &client->root);
-	if (ret) {
-		nouveau_namedb_destroy(&client->base);
+	if (ret)
 		return ret;
-	}
 
 	/* prevent init/fini being called, os in in charge of this */
 	atomic_set(&nv_object(client)->usecount, 2);
diff --git a/drivers/gpu/drm/nouveau/core/core/handle.c b/drivers/gpu/drm/nouveau/core/core/handle.c
index b8d2cbf..264c2b3 100644
--- a/drivers/gpu/drm/nouveau/core/core/handle.c
+++ b/drivers/gpu/drm/nouveau/core/core/handle.c
@@ -109,7 +109,7 @@
 	while (!nv_iclass(namedb, NV_NAMEDB_CLASS))
 		namedb = namedb->parent;
 
-	handle = *phandle = kzalloc(sizeof(*handle), GFP_KERNEL);
+	handle = kzalloc(sizeof(*handle), GFP_KERNEL);
 	if (!handle)
 		return -ENOMEM;
 
@@ -146,6 +146,9 @@
 	}
 
 	hprintk(handle, TRACE, "created\n");
+
+	*phandle = handle;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
index 0f09af1..ca1a7d7 100644
--- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
+++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c
@@ -851,20 +851,23 @@
 	for (i = 0; !(ctrl & (1 << head)) && i < 3; i++)
 		ctrl = nv_rd32(priv, 0x610b5c + (i * 8));
 
-	if (nv_device(priv)->chipset  < 0x90 ||
-	    nv_device(priv)->chipset == 0x92 ||
-	    nv_device(priv)->chipset == 0xa0) {
-		for (i = 0; !(ctrl & (1 << head)) && i < 2; i++)
-			ctrl = nv_rd32(priv, 0x610b74 + (i * 8));
-		i += 3;
-	} else {
-		for (i = 0; !(ctrl & (1 << head)) && i < 4; i++)
-			ctrl = nv_rd32(priv, 0x610798 + (i * 8));
-		i += 3;
+	if (!(ctrl & (1 << head))) {
+		if (nv_device(priv)->chipset  < 0x90 ||
+		    nv_device(priv)->chipset == 0x92 ||
+		    nv_device(priv)->chipset == 0xa0) {
+			for (i = 0; !(ctrl & (1 << head)) && i < 2; i++)
+				ctrl = nv_rd32(priv, 0x610b74 + (i * 8));
+			i += 4;
+		} else {
+			for (i = 0; !(ctrl & (1 << head)) && i < 4; i++)
+				ctrl = nv_rd32(priv, 0x610798 + (i * 8));
+			i += 4;
+		}
 	}
 
 	if (!(ctrl & (1 << head)))
 		return false;
+	i--;
 
 	data = exec_lookup(priv, head, i, ctrl, &dcb, &ver, &hdr, &cnt, &len, &info);
 	if (data) {
@@ -898,20 +901,23 @@
 	for (i = 0; !(ctrl & (1 << head)) && i < 3; i++)
 		ctrl = nv_rd32(priv, 0x610b58 + (i * 8));
 
-	if (nv_device(priv)->chipset  < 0x90 ||
-	    nv_device(priv)->chipset == 0x92 ||
-	    nv_device(priv)->chipset == 0xa0) {
-		for (i = 0; !(ctrl & (1 << head)) && i < 2; i++)
-			ctrl = nv_rd32(priv, 0x610b70 + (i * 8));
-		i += 3;
-	} else {
-		for (i = 0; !(ctrl & (1 << head)) && i < 4; i++)
-			ctrl = nv_rd32(priv, 0x610794 + (i * 8));
-		i += 3;
+	if (!(ctrl & (1 << head))) {
+		if (nv_device(priv)->chipset  < 0x90 ||
+		    nv_device(priv)->chipset == 0x92 ||
+		    nv_device(priv)->chipset == 0xa0) {
+			for (i = 0; !(ctrl & (1 << head)) && i < 2; i++)
+				ctrl = nv_rd32(priv, 0x610b70 + (i * 8));
+			i += 4;
+		} else {
+			for (i = 0; !(ctrl & (1 << head)) && i < 4; i++)
+				ctrl = nv_rd32(priv, 0x610794 + (i * 8));
+			i += 4;
+		}
 	}
 
 	if (!(ctrl & (1 << head)))
 		return 0x0000;
+	i--;
 
 	data = exec_lookup(priv, head, i, ctrl, outp, &ver, &hdr, &cnt, &len, &info1);
 	if (!data)
diff --git a/drivers/gpu/drm/nouveau/core/include/core/client.h b/drivers/gpu/drm/nouveau/core/include/core/client.h
index 0193532..63acc03 100644
--- a/drivers/gpu/drm/nouveau/core/include/core/client.h
+++ b/drivers/gpu/drm/nouveau/core/include/core/client.h
@@ -36,6 +36,9 @@
 
 int  nouveau_client_create_(const char *name, u64 device, const char *cfg,
 			    const char *dbg, int, void **);
+#define nouveau_client_destroy(p)                                              \
+	nouveau_namedb_destroy(&(p)->base)
+
 int  nouveau_client_init(struct nouveau_client *);
 int  nouveau_client_fini(struct nouveau_client *, bool suspend);
 
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h
index c345097..b2f3d4d 100644
--- a/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h
+++ b/drivers/gpu/drm/nouveau/core/include/subdev/bios/pll.h
@@ -38,6 +38,8 @@
 	PLL_UNK42  = 0x42,
 	PLL_VPLL0  = 0x80,
 	PLL_VPLL1  = 0x81,
+	PLL_VPLL2  = 0x82,
+	PLL_VPLL3  = 0x83,
 	PLL_MAX    = 0xff
 };
 
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
index 2917d55..690ed43 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/bios/init.c
@@ -1534,7 +1534,6 @@
 		mdelay(10);
 		init_wr32(init, 0x614100, 0x10000018);
 		init_wr32(init, 0x614900, 0x10000018);
-		return;
 	}
 
 	value = init_rdport(init, port) & mask;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
index f6962c9..7c96262 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/clock/nvc0.c
@@ -52,6 +52,8 @@
 	switch (info.type) {
 	case PLL_VPLL0:
 	case PLL_VPLL1:
+	case PLL_VPLL2:
+	case PLL_VPLL3:
 		nv_mask(priv, info.reg + 0x0c, 0x00000000, 0x00000100);
 		nv_wr32(priv, info.reg + 0x04, (P << 16) | (N << 8) | M);
 		nv_wr32(priv, info.reg + 0x10, fN << 16);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
index 306bdf1..7606ed1 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/fb/nvc0.c
@@ -145,14 +145,14 @@
 	mem->memtype = type;
 	mem->size = size;
 
-	mutex_lock(&mm->mutex);
+	mutex_lock(&pfb->base.mutex);
 	do {
 		if (back)
 			ret = nouveau_mm_tail(mm, 1, size, ncmin, align, &r);
 		else
 			ret = nouveau_mm_head(mm, 1, size, ncmin, align, &r);
 		if (ret) {
-			mutex_unlock(&mm->mutex);
+			mutex_unlock(&pfb->base.mutex);
 			pfb->ram.put(pfb, &mem);
 			return ret;
 		}
@@ -160,7 +160,7 @@
 		list_add_tail(&r->rl_entry, &mem->regions);
 		size -= r->length;
 	} while (size);
-	mutex_unlock(&mm->mutex);
+	mutex_unlock(&pfb->base.mutex);
 
 	r = list_first_entry(&mem->regions, struct nouveau_mm_node, rl_entry);
 	mem->offset = (u64)r->offset << 12;
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c
index 1188227..6565f3d 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/base.c
@@ -40,15 +40,21 @@
 	if (ret)
 		return ret;
 
+	mutex_lock(&imem->base.mutex);
 	list_add(&iobj->head, &imem->list);
+	mutex_unlock(&imem->base.mutex);
 	return 0;
 }
 
 void
 nouveau_instobj_destroy(struct nouveau_instobj *iobj)
 {
-	if (iobj->head.prev)
-		list_del(&iobj->head);
+	struct nouveau_subdev *subdev = nv_subdev(iobj->base.engine);
+
+	mutex_lock(&subdev->mutex);
+	list_del(&iobj->head);
+	mutex_unlock(&subdev->mutex);
+
 	return nouveau_object_destroy(&iobj->base);
 }
 
@@ -88,6 +94,8 @@
 	if (ret)
 		return ret;
 
+	mutex_lock(&imem->base.mutex);
+
 	list_for_each_entry(iobj, &imem->list, head) {
 		if (iobj->suspend) {
 			for (i = 0; i < iobj->size; i += 4)
@@ -97,6 +105,8 @@
 		}
 	}
 
+	mutex_unlock(&imem->base.mutex);
+
 	return 0;
 }
 
@@ -104,17 +114,26 @@
 nouveau_instmem_fini(struct nouveau_instmem *imem, bool suspend)
 {
 	struct nouveau_instobj *iobj;
-	int i;
+	int i, ret = 0;
 
 	if (suspend) {
+		mutex_lock(&imem->base.mutex);
+
 		list_for_each_entry(iobj, &imem->list, head) {
 			iobj->suspend = vmalloc(iobj->size);
-			if (iobj->suspend) {
-				for (i = 0; i < iobj->size; i += 4)
-					iobj->suspend[i / 4] = nv_ro32(iobj, i);
-			} else
-				return -ENOMEM;
+			if (!iobj->suspend) {
+				ret = -ENOMEM;
+				break;
+			}
+
+			for (i = 0; i < iobj->size; i += 4)
+				iobj->suspend[i / 4] = nv_ro32(iobj, i);
 		}
+
+		mutex_unlock(&imem->base.mutex);
+
+		if (ret)
+			return ret;
 	}
 
 	return nouveau_subdev_fini(&imem->base, suspend);
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
index 082c11b..77c67fc 100644
--- a/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
+++ b/drivers/gpu/drm/nouveau/core/subdev/vm/base.c
@@ -352,7 +352,7 @@
 	u64 mm_length = (offset + length) - mm_offset;
 	int ret;
 
-	vm = *pvm = kzalloc(sizeof(*vm), GFP_KERNEL);
+	vm = kzalloc(sizeof(*vm), GFP_KERNEL);
 	if (!vm)
 		return -ENOMEM;
 
@@ -376,6 +376,8 @@
 		return ret;
 	}
 
+	*pvm = vm;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c
index ac340ba..e620ba8 100644
--- a/drivers/gpu/drm/nouveau/nouveau_connector.c
+++ b/drivers/gpu/drm/nouveau/nouveau_connector.c
@@ -127,12 +127,26 @@
 			     struct nouveau_encoder **pnv_encoder)
 {
 	struct drm_device *dev = connector->dev;
+	struct nouveau_connector *nv_connector = nouveau_connector(connector);
 	struct nouveau_drm *drm = nouveau_drm(dev);
+	struct nouveau_gpio *gpio = nouveau_gpio(drm->device);
 	struct nouveau_i2c *i2c = nouveau_i2c(drm->device);
-	int i;
+	struct nouveau_i2c_port *port = NULL;
+	int i, panel = -ENODEV;
+
+	/* eDP panels need powering on by us (if the VBIOS doesn't default it
+	 * to on) before doing any AUX channel transactions.  LVDS panel power
+	 * is handled by the SOR itself, and not required for LVDS DDC.
+	 */
+	if (nv_connector->type == DCB_CONNECTOR_eDP) {
+		panel = gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff);
+		if (panel == 0) {
+			gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1);
+			msleep(300);
+		}
+	}
 
 	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-		struct nouveau_i2c_port *port = NULL;
 		struct nouveau_encoder *nv_encoder;
 		struct drm_mode_object *obj;
 		int id;
@@ -150,11 +164,19 @@
 			port = i2c->find(i2c, nv_encoder->dcb->i2c_index);
 		if (port && nv_probe_i2c(port, 0x50)) {
 			*pnv_encoder = nv_encoder;
-			return port;
+			break;
 		}
+
+		port = NULL;
 	}
 
-	return NULL;
+	/* eDP panel not detected, restore panel power GPIO to previous
+	 * state to avoid confusing the SOR for other output types.
+	 */
+	if (!port && panel == 0)
+		gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, panel);
+
+	return port;
 }
 
 static struct nouveau_encoder *
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c
index e4188f2..508b00a 100644
--- a/drivers/gpu/drm/nouveau/nouveau_display.c
+++ b/drivers/gpu/drm/nouveau/nouveau_display.c
@@ -225,15 +225,6 @@
 	if (ret)
 		return ret;
 
-	/* power on internal panel if it's not already.  the init tables of
-	 * some vbios default this to off for some reason, causing the
-	 * panel to not work after resume
-	 */
-	if (gpio && gpio->get(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff) == 0) {
-		gpio->set(gpio, 0, DCB_GPIO_PANEL_POWER, 0xff, 1);
-		msleep(300);
-	}
-
 	/* enable polling for external displays */
 	drm_kms_helper_poll_enable(dev);
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_drm.c b/drivers/gpu/drm/nouveau/nouveau_drm.c
index 180a45e..8b090f1 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_drm.c
@@ -84,11 +84,16 @@
 	struct nouveau_cli *cli;
 	int ret;
 
+	*pcli = NULL;
 	ret = nouveau_client_create_(name, nouveau_name(pdev), nouveau_config,
 				     nouveau_debug, size, pcli);
 	cli = *pcli;
-	if (ret)
+	if (ret) {
+		if (cli)
+			nouveau_client_destroy(&cli->base);
+		*pcli = NULL;
 		return ret;
+	}
 
 	mutex_init(&cli->mutex);
 	return 0;
diff --git a/drivers/gpu/drm/nouveau/nouveau_fence.h b/drivers/gpu/drm/nouveau/nouveau_fence.h
index bedafd1..cdb83ac 100644
--- a/drivers/gpu/drm/nouveau/nouveau_fence.h
+++ b/drivers/gpu/drm/nouveau/nouveau_fence.h
@@ -60,6 +60,7 @@
 void nv10_fence_context_del(struct nouveau_channel *);
 void nv10_fence_destroy(struct nouveau_drm *);
 int  nv10_fence_create(struct nouveau_drm *);
+void nv17_fence_resume(struct nouveau_drm *drm);
 
 int nv50_fence_create(struct nouveau_drm *);
 int nv84_fence_create(struct nouveau_drm *);
diff --git a/drivers/gpu/drm/nouveau/nv04_dfp.c b/drivers/gpu/drm/nouveau/nv04_dfp.c
index 184cdf8..39ffc07 100644
--- a/drivers/gpu/drm/nouveau/nv04_dfp.c
+++ b/drivers/gpu/drm/nouveau/nv04_dfp.c
@@ -505,7 +505,7 @@
 
 static inline bool is_powersaving_dpms(int mode)
 {
-	return (mode != DRM_MODE_DPMS_ON);
+	return mode != DRM_MODE_DPMS_ON && mode != NV_DPMS_CLEARED;
 }
 
 static void nv04_lvds_dpms(struct drm_encoder *encoder, int mode)
diff --git a/drivers/gpu/drm/nouveau/nv10_fence.c b/drivers/gpu/drm/nouveau/nv10_fence.c
index 7ae7f97..03017f2 100644
--- a/drivers/gpu/drm/nouveau/nv10_fence.c
+++ b/drivers/gpu/drm/nouveau/nv10_fence.c
@@ -162,6 +162,13 @@
 	kfree(priv);
 }
 
+void nv17_fence_resume(struct nouveau_drm *drm)
+{
+	struct nv10_fence_priv *priv = drm->fence;
+
+	nouveau_bo_wr32(priv->bo, 0, priv->sequence);
+}
+
 int
 nv10_fence_create(struct nouveau_drm *drm)
 {
@@ -197,6 +204,7 @@
 		if (ret == 0) {
 			nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
 			priv->base.sync = nv17_fence_sync;
+			priv->base.resume = nv17_fence_resume;
 		}
 	}
 
diff --git a/drivers/gpu/drm/nouveau/nv50_fence.c b/drivers/gpu/drm/nouveau/nv50_fence.c
index c20f272..d889f3a 100644
--- a/drivers/gpu/drm/nouveau/nv50_fence.c
+++ b/drivers/gpu/drm/nouveau/nv50_fence.c
@@ -122,6 +122,7 @@
 	if (ret == 0) {
 		nouveau_bo_wr32(priv->bo, 0x000, 0x00000000);
 		priv->base.sync = nv17_fence_sync;
+		priv->base.resume = nv17_fence_resume;
 	}
 
 	if (ret)
diff --git a/drivers/gpu/drm/radeon/evergreen.c b/drivers/gpu/drm/radeon/evergreen.c
index 061fa0a..4d0e60a 100644
--- a/drivers/gpu/drm/radeon/evergreen.c
+++ b/drivers/gpu/drm/radeon/evergreen.c
@@ -2401,6 +2401,12 @@
 {
 	struct evergreen_mc_save save;
 
+	if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+		reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+	if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+		reset_mask &= ~RADEON_RESET_DMA;
+
 	if (reset_mask == 0)
 		return 0;
 
diff --git a/drivers/gpu/drm/radeon/ni.c b/drivers/gpu/drm/radeon/ni.c
index 896f1cb..835992d 100644
--- a/drivers/gpu/drm/radeon/ni.c
+++ b/drivers/gpu/drm/radeon/ni.c
@@ -1216,7 +1216,7 @@
 int cayman_dma_resume(struct radeon_device *rdev)
 {
 	struct radeon_ring *ring;
-	u32 rb_cntl, dma_cntl;
+	u32 rb_cntl, dma_cntl, ib_cntl;
 	u32 rb_bufsz;
 	u32 reg_offset, wb_offset;
 	int i, r;
@@ -1265,7 +1265,11 @@
 		WREG32(DMA_RB_BASE + reg_offset, ring->gpu_addr >> 8);
 
 		/* enable DMA IBs */
-		WREG32(DMA_IB_CNTL + reg_offset, DMA_IB_ENABLE | CMD_VMID_FORCE);
+		ib_cntl = DMA_IB_ENABLE | CMD_VMID_FORCE;
+#ifdef __BIG_ENDIAN
+		ib_cntl |= DMA_IB_SWAP_ENABLE;
+#endif
+		WREG32(DMA_IB_CNTL + reg_offset, ib_cntl);
 
 		dma_cntl = RREG32(DMA_CNTL + reg_offset);
 		dma_cntl &= ~CTXEMPTY_INT_ENABLE;
@@ -1409,6 +1413,12 @@
 {
 	struct evergreen_mc_save save;
 
+	if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+		reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+	if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+		reset_mask &= ~RADEON_RESET_DMA;
+
 	if (reset_mask == 0)
 		return 0;
 
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c
index 537e259..bc2540b 100644
--- a/drivers/gpu/drm/radeon/r600.c
+++ b/drivers/gpu/drm/radeon/r600.c
@@ -1378,6 +1378,12 @@
 {
 	struct rv515_mc_save save;
 
+	if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+		reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+	if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+		reset_mask &= ~RADEON_RESET_DMA;
+
 	if (reset_mask == 0)
 		return 0;
 
@@ -2307,7 +2313,7 @@
 int r600_dma_resume(struct radeon_device *rdev)
 {
 	struct radeon_ring *ring = &rdev->ring[R600_RING_TYPE_DMA_INDEX];
-	u32 rb_cntl, dma_cntl;
+	u32 rb_cntl, dma_cntl, ib_cntl;
 	u32 rb_bufsz;
 	int r;
 
@@ -2347,7 +2353,11 @@
 	WREG32(DMA_RB_BASE, ring->gpu_addr >> 8);
 
 	/* enable DMA IBs */
-	WREG32(DMA_IB_CNTL, DMA_IB_ENABLE);
+	ib_cntl = DMA_IB_ENABLE;
+#ifdef __BIG_ENDIAN
+	ib_cntl |= DMA_IB_SWAP_ENABLE;
+#endif
+	WREG32(DMA_IB_CNTL, ib_cntl);
 
 	dma_cntl = RREG32(DMA_CNTL);
 	dma_cntl &= ~CTXEMPTY_INT_ENABLE;
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c
index 03191a5..69ec24a 100644
--- a/drivers/gpu/drm/radeon/r600_cs.c
+++ b/drivers/gpu/drm/radeon/r600_cs.c
@@ -2476,8 +2476,10 @@
 	kfree(parser->relocs);
 	for (i = 0; i < parser->nchunks; i++) {
 		kfree(parser->chunks[i].kdata);
-		kfree(parser->chunks[i].kpage[0]);
-		kfree(parser->chunks[i].kpage[1]);
+		if (parser->rdev && (parser->rdev->flags & RADEON_IS_AGP)) {
+			kfree(parser->chunks[i].kpage[0]);
+			kfree(parser->chunks[i].kpage[1]);
+		}
 	}
 	kfree(parser->chunks);
 	kfree(parser->chunks_array);
@@ -2561,16 +2563,16 @@
 	struct radeon_cs_chunk *relocs_chunk;
 	unsigned idx;
 
+	*cs_reloc = NULL;
 	if (p->chunk_relocs_idx == -1) {
 		DRM_ERROR("No relocation chunk !\n");
 		return -EINVAL;
 	}
-	*cs_reloc = NULL;
 	relocs_chunk = &p->chunks[p->chunk_relocs_idx];
 	idx = p->dma_reloc_idx;
-	if (idx >= relocs_chunk->length_dw) {
+	if (idx >= p->nrelocs) {
 		DRM_ERROR("Relocs at %d after relocations chunk end %d !\n",
-			  idx, relocs_chunk->length_dw);
+			  idx, p->nrelocs);
 		return -EINVAL;
 	}
 	*cs_reloc = p->relocs_ptr[idx];
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h
index 34e5230..a08f657 100644
--- a/drivers/gpu/drm/radeon/radeon.h
+++ b/drivers/gpu/drm/radeon/radeon.h
@@ -324,7 +324,6 @@
 	struct list_head		list;
 	/* Protected by tbo.reserved */
 	u32				placements[3];
-	u32				busy_placements[3];
 	struct ttm_placement		placement;
 	struct ttm_buffer_object	tbo;
 	struct ttm_bo_kmap_obj		kmap;
@@ -654,6 +653,8 @@
 	u32			ptr_reg_mask;
 	u32			nop;
 	u32			idx;
+	u64			last_semaphore_signal_addr;
+	u64			last_semaphore_wait_addr;
 };
 
 /*
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c
index 396baba..5407459 100644
--- a/drivers/gpu/drm/radeon/radeon_cs.c
+++ b/drivers/gpu/drm/radeon/radeon_cs.c
@@ -279,13 +279,15 @@
 				  p->chunks[p->chunk_ib_idx].length_dw);
 			return -EINVAL;
 		}
-		if ((p->rdev->flags & RADEON_IS_AGP)) {
+		if (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) {
 			p->chunks[p->chunk_ib_idx].kpage[0] = kmalloc(PAGE_SIZE, GFP_KERNEL);
 			p->chunks[p->chunk_ib_idx].kpage[1] = kmalloc(PAGE_SIZE, GFP_KERNEL);
 			if (p->chunks[p->chunk_ib_idx].kpage[0] == NULL ||
 			    p->chunks[p->chunk_ib_idx].kpage[1] == NULL) {
-				kfree(p->chunks[i].kpage[0]);
-				kfree(p->chunks[i].kpage[1]);
+				kfree(p->chunks[p->chunk_ib_idx].kpage[0]);
+				kfree(p->chunks[p->chunk_ib_idx].kpage[1]);
+				p->chunks[p->chunk_ib_idx].kpage[0] = NULL;
+				p->chunks[p->chunk_ib_idx].kpage[1] = NULL;
 				return -ENOMEM;
 			}
 		}
@@ -583,7 +585,8 @@
 	struct radeon_cs_chunk *ibc = &p->chunks[p->chunk_ib_idx];
 	int i;
 	int size = PAGE_SIZE;
-	bool copy1 = (p->rdev->flags & RADEON_IS_AGP) ? false : true;
+	bool copy1 = (p->rdev && (p->rdev->flags & RADEON_IS_AGP)) ?
+		false : true;
 
 	for (i = ibc->last_copied_page + 1; i < pg_idx; i++) {
 		if (DRM_COPY_FROM_USER(p->ib.ptr + (i * (PAGE_SIZE/4)),
diff --git a/drivers/gpu/drm/radeon/radeon_cursor.c b/drivers/gpu/drm/radeon/radeon_cursor.c
index ad6df62..0d67674 100644
--- a/drivers/gpu/drm/radeon/radeon_cursor.c
+++ b/drivers/gpu/drm/radeon/radeon_cursor.c
@@ -241,7 +241,8 @@
 		y = 0;
 	}
 
-	if (ASIC_IS_AVIVO(rdev)) {
+	/* fixed on DCE6 and newer */
+	if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE6(rdev)) {
 		int i = 0;
 		struct drm_crtc *crtc_p;
 
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c
index edfc54e..0d6562b 100644
--- a/drivers/gpu/drm/radeon/radeon_device.c
+++ b/drivers/gpu/drm/radeon/radeon_device.c
@@ -429,7 +429,8 @@
 {
 	uint32_t reg;
 
-	if (efi_enabled && rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE)
+	if (efi_enabled(EFI_BOOT) &&
+	    rdev->pdev->subsystem_vendor == PCI_VENDOR_ID_APPLE)
 		return false;
 
 	/* first check CRTCs */
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c
index 1da2386..ff3def7 100644
--- a/drivers/gpu/drm/radeon/radeon_display.c
+++ b/drivers/gpu/drm/radeon/radeon_display.c
@@ -1122,7 +1122,7 @@
 	if (ret) {
 		kfree(radeon_fb);
 		drm_gem_object_unreference_unlocked(obj);
-		return NULL;
+		return ERR_PTR(ret);
 	}
 
 	return &radeon_fb->base;
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index dff6cf7..d9bf96e 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -69,9 +69,10 @@
  *   2.26.0 - r600-eg: fix htile size computation
  *   2.27.0 - r600-SI: Add CS ioctl support for async DMA
  *   2.28.0 - r600-eg: Add MEM_WRITE packet support
+ *   2.29.0 - R500 FP16 color clear registers
  */
 #define KMS_DRIVER_MAJOR	2
-#define KMS_DRIVER_MINOR	28
+#define KMS_DRIVER_MINOR	29
 #define KMS_DRIVER_PATCHLEVEL	0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
index f5ba224..62cd512 100644
--- a/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
+++ b/drivers/gpu/drm/radeon/radeon_legacy_encoders.c
@@ -640,6 +640,14 @@
 	enum drm_connector_status found = connector_status_disconnected;
 	bool color = true;
 
+	/* just don't bother on RN50 those chip are often connected to remoting
+	 * console hw and often we get failure to load detect those. So to make
+	 * everyone happy report the encoder as always connected.
+	 */
+	if (ASIC_IS_RN50(rdev)) {
+		return connector_status_connected;
+	}
+
 	/* save the regs we need */
 	vclk_ecp_cntl = RREG32_PLL(RADEON_VCLK_ECP_CNTL);
 	crtc_ext_cntl = RREG32(RADEON_CRTC_EXT_CNTL);
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c
index 883c95d..d3aface 100644
--- a/drivers/gpu/drm/radeon/radeon_object.c
+++ b/drivers/gpu/drm/radeon/radeon_object.c
@@ -84,6 +84,7 @@
 	rbo->placement.fpfn = 0;
 	rbo->placement.lpfn = 0;
 	rbo->placement.placement = rbo->placements;
+	rbo->placement.busy_placement = rbo->placements;
 	if (domain & RADEON_GEM_DOMAIN_VRAM)
 		rbo->placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_UNCACHED |
 					TTM_PL_FLAG_VRAM;
@@ -104,14 +105,6 @@
 	if (!c)
 		rbo->placements[c++] = TTM_PL_MASK_CACHING | TTM_PL_FLAG_SYSTEM;
 	rbo->placement.num_placement = c;
-
-	c = 0;
-	rbo->placement.busy_placement = rbo->busy_placements;
-	if (rbo->rdev->flags & RADEON_IS_AGP) {
-		rbo->busy_placements[c++] = TTM_PL_FLAG_WC | TTM_PL_FLAG_TT;
-	} else {
-		rbo->busy_placements[c++] = TTM_PL_FLAG_CACHED | TTM_PL_FLAG_TT;
-	}
 	rbo->placement.num_busy_placement = c;
 }
 
@@ -357,6 +350,7 @@
 {
 	struct radeon_bo_list *lobj;
 	struct radeon_bo *bo;
+	u32 domain;
 	int r;
 
 	r = ttm_eu_reserve_buffers(head);
@@ -366,9 +360,17 @@
 	list_for_each_entry(lobj, head, tv.head) {
 		bo = lobj->bo;
 		if (!bo->pin_count) {
+			domain = lobj->wdomain ? lobj->wdomain : lobj->rdomain;
+			
+		retry:
+			radeon_ttm_placement_from_domain(bo, domain);
 			r = ttm_bo_validate(&bo->tbo, &bo->placement,
 						true, false);
 			if (unlikely(r)) {
+				if (r != -ERESTARTSYS && domain == RADEON_GEM_DOMAIN_VRAM) {
+					domain |= RADEON_GEM_DOMAIN_GTT;
+					goto retry;
+				}
 				return r;
 			}
 		}
diff --git a/drivers/gpu/drm/radeon/radeon_ring.c b/drivers/gpu/drm/radeon/radeon_ring.c
index 141f2b6..2430d80 100644
--- a/drivers/gpu/drm/radeon/radeon_ring.c
+++ b/drivers/gpu/drm/radeon/radeon_ring.c
@@ -784,6 +784,8 @@
 	}
 	seq_printf(m, "driver's copy of the wptr: 0x%08x [%5d]\n", ring->wptr, ring->wptr);
 	seq_printf(m, "driver's copy of the rptr: 0x%08x [%5d]\n", ring->rptr, ring->rptr);
+	seq_printf(m, "last semaphore signal addr : 0x%016llx\n", ring->last_semaphore_signal_addr);
+	seq_printf(m, "last semaphore wait addr   : 0x%016llx\n", ring->last_semaphore_wait_addr);
 	seq_printf(m, "%u free dwords in ring\n", ring->ring_free_dw);
 	seq_printf(m, "%u dwords in ring\n", count);
 	/* print 8 dw before current rptr as often it's the last executed
diff --git a/drivers/gpu/drm/radeon/radeon_semaphore.c b/drivers/gpu/drm/radeon/radeon_semaphore.c
index 97f3ece..8dcc20f 100644
--- a/drivers/gpu/drm/radeon/radeon_semaphore.c
+++ b/drivers/gpu/drm/radeon/radeon_semaphore.c
@@ -95,6 +95,10 @@
 	/* we assume caller has already allocated space on waiters ring */
 	radeon_semaphore_emit_wait(rdev, waiter, semaphore);
 
+	/* for debugging lockup only, used by sysfs debug files */
+	rdev->ring[signaler].last_semaphore_signal_addr = semaphore->gpu_addr;
+	rdev->ring[waiter].last_semaphore_wait_addr = semaphore->gpu_addr;
+
 	return 0;
 }
 
diff --git a/drivers/gpu/drm/radeon/reg_srcs/rv515 b/drivers/gpu/drm/radeon/reg_srcs/rv515
index 911a8fb..78d5e99 100644
--- a/drivers/gpu/drm/radeon/reg_srcs/rv515
+++ b/drivers/gpu/drm/radeon/reg_srcs/rv515
@@ -324,6 +324,8 @@
 0x46AC US_OUT_FMT_2
 0x46B0 US_OUT_FMT_3
 0x46B4 US_W_FMT
+0x46C0 RB3D_COLOR_CLEAR_VALUE_AR
+0x46C4 RB3D_COLOR_CLEAR_VALUE_GB
 0x4BC0 FG_FOG_BLEND
 0x4BC4 FG_FOG_FACTOR
 0x4BC8 FG_FOG_COLOR_R
diff --git a/drivers/gpu/drm/radeon/si.c b/drivers/gpu/drm/radeon/si.c
index 3240a3d..ae8b482 100644
--- a/drivers/gpu/drm/radeon/si.c
+++ b/drivers/gpu/drm/radeon/si.c
@@ -2215,6 +2215,12 @@
 {
 	struct evergreen_mc_save save;
 
+	if (!(RREG32(GRBM_STATUS) & GUI_ACTIVE))
+		reset_mask &= ~(RADEON_RESET_GFX | RADEON_RESET_COMPUTE);
+
+	if (RREG32(DMA_STATUS_REG) & DMA_IDLE)
+		reset_mask &= ~RADEON_RESET_DMA;
+
 	if (reset_mask == 0)
 		return 0;
 
diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c
index 656b2e3..56813f9 100644
--- a/drivers/gpu/drm/tegra/dc.c
+++ b/drivers/gpu/drm/tegra/dc.c
@@ -12,8 +12,7 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/platform_device.h>
-
-#include <mach/clk.h>
+#include <linux/clk/tegra.h>
 
 #include "drm.h"
 #include "dc.h"
diff --git a/drivers/gpu/drm/tegra/drm.c b/drivers/gpu/drm/tegra/drm.c
index 3a503c9..d980dc7 100644
--- a/drivers/gpu/drm/tegra/drm.c
+++ b/drivers/gpu/drm/tegra/drm.c
@@ -11,7 +11,6 @@
 #include <linux/of_address.h>
 #include <linux/of_platform.h>
 
-#include <mach/clk.h>
 #include <linux/dma-mapping.h>
 #include <asm/dma-iommu.h>
 
diff --git a/drivers/gpu/drm/tegra/hdmi.c b/drivers/gpu/drm/tegra/hdmi.c
index e060c7e..92ad276 100644
--- a/drivers/gpu/drm/tegra/hdmi.c
+++ b/drivers/gpu/drm/tegra/hdmi.c
@@ -14,8 +14,7 @@
 #include <linux/of.h>
 #include <linux/platform_device.h>
 #include <linux/regulator/consumer.h>
-
-#include <mach/clk.h>
+#include <linux/clk/tegra.h>
 
 #include "hdmi.h"
 #include "drm.h"
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c
index 33d20be..52b20b1 100644
--- a/drivers/gpu/drm/ttm/ttm_bo.c
+++ b/drivers/gpu/drm/ttm/ttm_bo.c
@@ -434,6 +434,7 @@
 			bo->mem = tmp_mem;
 			bdev->driver->move_notify(bo, mem);
 			bo->mem = *mem;
+			*mem = tmp_mem;
 		}
 
 		goto out_err;
diff --git a/drivers/gpu/drm/ttm/ttm_bo_util.c b/drivers/gpu/drm/ttm/ttm_bo_util.c
index d73d6e3..44420fc 100644
--- a/drivers/gpu/drm/ttm/ttm_bo_util.c
+++ b/drivers/gpu/drm/ttm/ttm_bo_util.c
@@ -344,8 +344,12 @@
 
 	if (ttm->state == tt_unpopulated) {
 		ret = ttm->bdev->driver->ttm_tt_populate(ttm);
-		if (ret)
+		if (ret) {
+			/* if we fail here don't nuke the mm node
+			 * as the bo still owns it */
+			old_copy.mm_node = NULL;
 			goto out1;
+		}
 	}
 
 	add = 0;
@@ -371,8 +375,11 @@
 						   prot);
 		} else
 			ret = ttm_copy_io_page(new_iomap, old_iomap, page);
-		if (ret)
+		if (ret) {
+			/* failing here, means keep old copy as-is */
+			old_copy.mm_node = NULL;
 			goto out1;
+		}
 	}
 	mb();
 out2:
diff --git a/drivers/gpu/drm/udl/udl_connector.c b/drivers/gpu/drm/udl/udl_connector.c
index 512f44a..fe5cdbcf 100644
--- a/drivers/gpu/drm/udl/udl_connector.c
+++ b/drivers/gpu/drm/udl/udl_connector.c
@@ -22,13 +22,17 @@
 static u8 *udl_get_edid(struct udl_device *udl)
 {
 	u8 *block;
-	char rbuf[3];
+	char *rbuf;
 	int ret, i;
 
 	block = kmalloc(EDID_LENGTH, GFP_KERNEL);
 	if (block == NULL)
 		return NULL;
 
+	rbuf = kmalloc(2, GFP_KERNEL);
+	if (rbuf == NULL)
+		goto error;
+
 	for (i = 0; i < EDID_LENGTH; i++) {
 		ret = usb_control_msg(udl->ddev->usbdev,
 				      usb_rcvctrlpipe(udl->ddev->usbdev, 0), (0x02),
@@ -36,16 +40,17 @@
 				      HZ);
 		if (ret < 1) {
 			DRM_ERROR("Read EDID byte %d failed err %x\n", i, ret);
-			i--;
 			goto error;
 		}
 		block[i] = rbuf[1];
 	}
 
+	kfree(rbuf);
 	return block;
 
 error:
 	kfree(block);
+	kfree(rbuf);
 	return NULL;
 }
 
@@ -57,6 +62,14 @@
 
 	edid = (struct edid *)udl_get_edid(udl);
 
+	/*
+	 * We only read the main block, but if the monitor reports extension
+	 * blocks then the drm edid code expects them to be present, so patch
+	 * the extension count to 0.
+	 */
+	edid->checksum += edid->extensions;
+	edid->extensions = 0;
+
 	drm_mode_connector_update_edid_property(connector, edid);
 	ret = drm_add_edid_modes(connector, edid);
 	kfree(edid);
diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
index 4dfa605..34e2547 100644
--- a/drivers/hid/hid-ids.h
+++ b/drivers/hid/hid-ids.h
@@ -306,6 +306,9 @@
 #define USB_VENDOR_ID_EZKEY		0x0518
 #define USB_DEVICE_ID_BTC_8193		0x0002
 
+#define USB_VENDOR_ID_FORMOSA          0x147a
+#define USB_DEVICE_ID_FORMOSA_IR_RECEIVER      0xe03e
+
 #define USB_VENDOR_ID_FREESCALE		0x15A2
 #define USB_DEVICE_ID_FREESCALE_MX28	0x004F
 
diff --git a/drivers/hid/i2c-hid/i2c-hid.c b/drivers/hid/i2c-hid/i2c-hid.c
index 12e4fdc..e766b56 100644
--- a/drivers/hid/i2c-hid/i2c-hid.c
+++ b/drivers/hid/i2c-hid/i2c-hid.c
@@ -540,13 +540,24 @@
 {
 	struct i2c_client *client = hid->driver_data;
 	int report_id = buf[0];
+	int ret;
 
 	if (report_type == HID_INPUT_REPORT)
 		return -EINVAL;
 
-	return i2c_hid_set_report(client,
+	if (report_id) {
+		buf++;
+		count--;
+	}
+
+	ret = i2c_hid_set_report(client,
 				report_type == HID_FEATURE_REPORT ? 0x03 : 0x02,
 				report_id, buf, count);
+
+	if (report_id && ret >= 0)
+		ret++; /* add report_id to the number of transfered bytes */
+
+	return ret;
 }
 
 static int i2c_hid_parse(struct hid_device *hid)
diff --git a/drivers/hid/usbhid/hid-quirks.c b/drivers/hid/usbhid/hid-quirks.c
index ac9e352..e0e6abf 100644
--- a/drivers/hid/usbhid/hid-quirks.c
+++ b/drivers/hid/usbhid/hid-quirks.c
@@ -70,6 +70,7 @@
 	{ USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+	{ USB_VENDOR_ID_FORMOSA, USB_DEVICE_ID_FORMOSA_IR_RECEIVER, HID_QUIRK_NO_INIT_REPORTS },
 	{ USB_VENDOR_ID_FREESCALE, USB_DEVICE_ID_FREESCALE_MX28, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
 	{ USB_VENDOR_ID_NOVATEK, USB_DEVICE_ID_NOVATEK_MOUSE, HID_QUIRK_NO_INIT_REPORTS },
diff --git a/drivers/hv/hv_balloon.c b/drivers/hv/hv_balloon.c
index f6c0011..dd289fd 100644
--- a/drivers/hv/hv_balloon.c
+++ b/drivers/hv/hv_balloon.c
@@ -403,7 +403,7 @@
  */
 
 struct dm_info_msg {
-	struct dm_info_header header;
+	struct dm_header hdr;
 	__u32 reserved;
 	__u32 info_size;
 	__u8  info[];
@@ -503,13 +503,17 @@
 
 static void process_info(struct hv_dynmem_device *dm, struct dm_info_msg *msg)
 {
-	switch (msg->header.type) {
+	struct dm_info_header *info_hdr;
+
+	info_hdr = (struct dm_info_header *)msg->info;
+
+	switch (info_hdr->type) {
 	case INFO_TYPE_MAX_PAGE_CNT:
 		pr_info("Received INFO_TYPE_MAX_PAGE_CNT\n");
-		pr_info("Data Size is %d\n", msg->header.data_size);
+		pr_info("Data Size is %d\n", info_hdr->data_size);
 		break;
 	default:
-		pr_info("Received Unknown type: %d\n", msg->header.type);
+		pr_info("Received Unknown type: %d\n", info_hdr->type);
 	}
 }
 
@@ -879,7 +883,7 @@
 			balloon_onchannelcallback, dev);
 
 	if (ret)
-		return ret;
+		goto probe_error0;
 
 	dm_device.dev = dev;
 	dm_device.state = DM_INITIALIZING;
@@ -891,7 +895,7 @@
 		 kthread_run(dm_thread_func, &dm_device, "hv_balloon");
 	if (IS_ERR(dm_device.thread)) {
 		ret = PTR_ERR(dm_device.thread);
-		goto probe_error0;
+		goto probe_error1;
 	}
 
 	hv_set_drvdata(dev, &dm_device);
@@ -914,12 +918,12 @@
 				VM_PKT_DATA_INBAND,
 				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 	if (ret)
-		goto probe_error1;
+		goto probe_error2;
 
 	t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
 	if (t == 0) {
 		ret = -ETIMEDOUT;
-		goto probe_error1;
+		goto probe_error2;
 	}
 
 	/*
@@ -928,7 +932,7 @@
 	 */
 	if (dm_device.state == DM_INIT_ERROR) {
 		ret = -ETIMEDOUT;
-		goto probe_error1;
+		goto probe_error2;
 	}
 	/*
 	 * Now submit our capabilities to the host.
@@ -961,12 +965,12 @@
 				VM_PKT_DATA_INBAND,
 				VMBUS_DATA_PACKET_FLAG_COMPLETION_REQUESTED);
 	if (ret)
-		goto probe_error1;
+		goto probe_error2;
 
 	t = wait_for_completion_timeout(&dm_device.host_event, 5*HZ);
 	if (t == 0) {
 		ret = -ETIMEDOUT;
-		goto probe_error1;
+		goto probe_error2;
 	}
 
 	/*
@@ -975,18 +979,20 @@
 	 */
 	if (dm_device.state == DM_INIT_ERROR) {
 		ret = -ETIMEDOUT;
-		goto probe_error1;
+		goto probe_error2;
 	}
 
 	dm_device.state = DM_INITIALIZED;
 
 	return 0;
 
-probe_error1:
+probe_error2:
 	kthread_stop(dm_device.thread);
 
-probe_error0:
+probe_error1:
 	vmbus_close(dev->channel);
+probe_error0:
+	kfree(send_buffer);
 	return ret;
 }
 
@@ -999,6 +1005,7 @@
 
 	vmbus_close(dev->channel);
 	kthread_stop(dm->thread);
+	kfree(send_buffer);
 
 	return 0;
 }
diff --git a/drivers/hwmon/vexpress.c b/drivers/hwmon/vexpress.c
index 86d7f6d..d867e6b 100644
--- a/drivers/hwmon/vexpress.c
+++ b/drivers/hwmon/vexpress.c
@@ -19,6 +19,7 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/module.h>
+#include <linux/of.h>
 #include <linux/of_device.h>
 #include <linux/platform_device.h>
 #include <linux/vexpress.h>
diff --git a/drivers/i2c/busses/i2c-designware-core.c b/drivers/i2c/busses/i2c-designware-core.c
index cbba7db..f5258c2 100644
--- a/drivers/i2c/busses/i2c-designware-core.c
+++ b/drivers/i2c/busses/i2c-designware-core.c
@@ -34,6 +34,7 @@
 #include <linux/io.h>
 #include <linux/pm_runtime.h>
 #include <linux/delay.h>
+#include <linux/module.h>
 #include "i2c-designware-core.h"
 
 /*
@@ -725,3 +726,6 @@
 	return dw_readl(dev, DW_IC_COMP_PARAM_1);
 }
 EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
+
+MODULE_DESCRIPTION("Synopsys DesignWare I2C bus adapter core");
+MODULE_LICENSE("GPL");
diff --git a/drivers/i2c/busses/i2c-mxs.c b/drivers/i2c/busses/i2c-mxs.c
index 1b1a936..d6abaf2 100644
--- a/drivers/i2c/busses/i2c-mxs.c
+++ b/drivers/i2c/busses/i2c-mxs.c
@@ -127,7 +127,7 @@
 	struct device *dev;
 	void __iomem *regs;
 	struct completion cmd_complete;
-	u32 cmd_err;
+	int cmd_err;
 	struct i2c_adapter adapter;
 	const struct mxs_i2c_speed_config *speed;
 
@@ -316,7 +316,7 @@
 	if (msg->len == 0)
 		return -EINVAL;
 
-	init_completion(&i2c->cmd_complete);
+	INIT_COMPLETION(i2c->cmd_complete);
 	i2c->cmd_err = 0;
 
 	ret = mxs_i2c_dma_setup_xfer(adap, msg, flags);
@@ -473,6 +473,8 @@
 	i2c->dev = dev;
 	i2c->speed = &mxs_i2c_95kHz_config;
 
+	init_completion(&i2c->cmd_complete);
+
 	if (dev->of_node) {
 		err = mxs_i2c_get_ofdata(i2c);
 		if (err)
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index 20d41bf..4cc2f05 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -803,7 +803,7 @@
 			if (stat & OMAP_I2C_STAT_AL) {
 				dev_err(dev->dev, "Arbitration lost\n");
 				dev->cmd_err |= OMAP_I2C_STAT_AL;
-				omap_i2c_ack_stat(dev, OMAP_I2C_STAT_NACK);
+				omap_i2c_ack_stat(dev, OMAP_I2C_STAT_AL);
 			}
 
 			return -EIO;
@@ -963,7 +963,7 @@
 				i2c_omap_errata_i207(dev, stat);
 
 			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RDR);
-			break;
+			continue;
 		}
 
 		if (stat & OMAP_I2C_STAT_RRDY) {
@@ -989,7 +989,7 @@
 				break;
 
 			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XDR);
-			break;
+			continue;
 		}
 
 		if (stat & OMAP_I2C_STAT_XRDY) {
diff --git a/drivers/i2c/busses/i2c-sirf.c b/drivers/i2c/busses/i2c-sirf.c
index 3f1818b..e03381a 100644
--- a/drivers/i2c/busses/i2c-sirf.c
+++ b/drivers/i2c/busses/i2c-sirf.c
@@ -12,6 +12,7 @@
 #include <linux/slab.h>
 #include <linux/platform_device.h>
 #include <linux/i2c.h>
+#include <linux/of_i2c.h>
 #include <linux/clk.h>
 #include <linux/err.h>
 #include <linux/io.h>
@@ -328,6 +329,7 @@
 	adap->algo = &i2c_sirfsoc_algo;
 	adap->algo_data = siic;
 
+	adap->dev.of_node = pdev->dev.of_node;
 	adap->dev.parent = &pdev->dev;
 	adap->nr = pdev->id;
 
@@ -371,6 +373,8 @@
 
 	clk_disable(clk);
 
+	of_i2c_register_devices(adap);
+
 	dev_info(&pdev->dev, " I2C adapter ready to operate\n");
 
 	return 0;
diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c
index 7b38877..c7aca35 100644
--- a/drivers/i2c/busses/i2c-tegra.c
+++ b/drivers/i2c/busses/i2c-tegra.c
@@ -29,11 +29,10 @@
 #include <linux/of_i2c.h>
 #include <linux/of_device.h>
 #include <linux/module.h>
+#include <linux/clk/tegra.h>
 
 #include <asm/unaligned.h>
 
-#include <mach/clk.h>
-
 #define TEGRA_I2C_TIMEOUT (msecs_to_jiffies(1000))
 #define BYTES_PER_FIFO_WORD 4
 
diff --git a/drivers/i2c/muxes/i2c-mux-pinctrl.c b/drivers/i2c/muxes/i2c-mux-pinctrl.c
index 1e44d04..a43c0ce 100644
--- a/drivers/i2c/muxes/i2c-mux-pinctrl.c
+++ b/drivers/i2c/muxes/i2c-mux-pinctrl.c
@@ -167,7 +167,7 @@
 	}
 
 	mux->busses = devm_kzalloc(&pdev->dev,
-				   sizeof(mux->busses) * mux->pdata->bus_count,
+				   sizeof(*mux->busses) * mux->pdata->bus_count,
 				   GFP_KERNEL);
 	if (!mux->busses) {
 		dev_err(&pdev->dev, "Cannot allocate busses\n");
diff --git a/drivers/idle/intel_idle.c b/drivers/idle/intel_idle.c
index 4ba384f..2df9414 100644
--- a/drivers/idle/intel_idle.c
+++ b/drivers/idle/intel_idle.c
@@ -448,8 +448,6 @@
 	else
 		on_each_cpu(__setup_broadcast_timer, (void *)true, 1);
 
-	register_cpu_notifier(&cpu_hotplug_notifier);
-
 	pr_debug(PREFIX "v" INTEL_IDLE_VERSION
 		" model 0x%X\n", boot_cpu_data.x86_model);
 
@@ -612,6 +610,7 @@
 			return retval;
 		}
 	}
+	register_cpu_notifier(&cpu_hotplug_notifier);
 
 	return 0;
 }
diff --git a/drivers/iio/accel/Kconfig b/drivers/iio/accel/Kconfig
index fe4bcd7..05e996f 100644
--- a/drivers/iio/accel/Kconfig
+++ b/drivers/iio/accel/Kconfig
@@ -8,6 +8,7 @@
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	select HID_SENSOR_IIO_COMMON
+	select HID_SENSOR_IIO_TRIGGER
 	tristate "HID Accelerometers 3D"
 	help
 	  Say yes here to build support for the HID SENSOR
diff --git a/drivers/iio/adc/ad7266.c b/drivers/iio/adc/ad7266.c
index 4a5f639b..bbad9b9 100644
--- a/drivers/iio/adc/ad7266.c
+++ b/drivers/iio/adc/ad7266.c
@@ -411,7 +411,11 @@
 		if (ret)
 			goto error_put_reg;
 
-		st->vref_uv = regulator_get_voltage(st->reg);
+		ret = regulator_get_voltage(st->reg);
+		if (ret < 0)
+			goto error_disable_reg;
+
+		st->vref_uv = ret;
 	} else {
 		/* Use internal reference */
 		st->vref_uv = 2500000;
diff --git a/drivers/iio/adc/at91_adc.c b/drivers/iio/adc/at91_adc.c
index 04b0135..a526c0e 100644
--- a/drivers/iio/adc/at91_adc.c
+++ b/drivers/iio/adc/at91_adc.c
@@ -80,7 +80,7 @@
 		*timestamp = pf->timestamp;
 	}
 
-	iio_push_to_buffers(indio_dev, (u8 *)st->buffer);
+	iio_push_to_buffers(idev, (u8 *)st->buffer);
 
 	iio_trigger_notify_done(idev->trig);
 
diff --git a/drivers/iio/adc/max1363.c b/drivers/iio/adc/max1363.c
index b5669be..03b25b3 100644
--- a/drivers/iio/adc/max1363.c
+++ b/drivers/iio/adc/max1363.c
@@ -1605,19 +1605,20 @@
 
 	return 0;
 error_free_irq:
-	free_irq(st->client->irq, indio_dev);
+	if (client->irq)
+		free_irq(st->client->irq, indio_dev);
 error_uninit_buffer:
 	iio_buffer_unregister(indio_dev);
 error_cleanup_buffer:
 	max1363_buffer_cleanup(indio_dev);
 error_free_available_scan_masks:
 	kfree(indio_dev->available_scan_masks);
-error_unregister_map:
-	iio_map_array_unregister(indio_dev, client->dev.platform_data);
 error_disable_reg:
 	regulator_disable(st->reg);
 error_put_reg:
 	regulator_put(st->reg);
+error_unregister_map:
+	iio_map_array_unregister(indio_dev, client->dev.platform_data);
 error_free_device:
 	iio_device_free(indio_dev);
 error_out:
@@ -1635,10 +1636,8 @@
 	iio_buffer_unregister(indio_dev);
 	max1363_buffer_cleanup(indio_dev);
 	kfree(indio_dev->available_scan_masks);
-	if (!IS_ERR(st->reg)) {
-		regulator_disable(st->reg);
-		regulator_put(st->reg);
-	}
+	regulator_disable(st->reg);
+	regulator_put(st->reg);
 	iio_map_array_unregister(indio_dev, client->dev.platform_data);
 	iio_device_free(indio_dev);
 
diff --git a/drivers/iio/common/hid-sensors/Kconfig b/drivers/iio/common/hid-sensors/Kconfig
index ae10778..1178121 100644
--- a/drivers/iio/common/hid-sensors/Kconfig
+++ b/drivers/iio/common/hid-sensors/Kconfig
@@ -6,7 +6,7 @@
 config HID_SENSOR_IIO_COMMON
 	tristate "Common modules for all HID Sensor IIO drivers"
 	depends on HID_SENSOR_HUB
-	select IIO_TRIGGER if IIO_BUFFER
+	select HID_SENSOR_IIO_TRIGGER if IIO_BUFFER
 	help
 	  Say yes here to build support for HID sensor to use
 	  HID sensor common processing for attributes and IIO triggers.
@@ -14,6 +14,17 @@
 	  HID sensor drivers, this module contains processing for those
 	  attributes.
 
+config HID_SENSOR_IIO_TRIGGER
+	tristate "Common module (trigger) for all HID Sensor IIO drivers"
+	depends on HID_SENSOR_HUB && HID_SENSOR_IIO_COMMON
+	select IIO_TRIGGER
+	help
+	  Say yes here to build trigger support for HID sensors.
+	  Triggers will be send if all requested attributes were read.
+
+	  If this driver is compiled as a module, it will be named
+	  hid-sensor-trigger.
+
 config HID_SENSOR_ENUM_BASE_QUIRKS
 	bool "ENUM base quirks for HID Sensor IIO drivers"
 	depends on HID_SENSOR_IIO_COMMON
diff --git a/drivers/iio/common/hid-sensors/Makefile b/drivers/iio/common/hid-sensors/Makefile
index 1f463e0..22e7c5a 100644
--- a/drivers/iio/common/hid-sensors/Makefile
+++ b/drivers/iio/common/hid-sensors/Makefile
@@ -3,4 +3,5 @@
 #
 
 obj-$(CONFIG_HID_SENSOR_IIO_COMMON) += hid-sensor-iio-common.o
-hid-sensor-iio-common-y := hid-sensor-attributes.o hid-sensor-trigger.o
+obj-$(CONFIG_HID_SENSOR_IIO_TRIGGER) += hid-sensor-trigger.o
+hid-sensor-iio-common-y := hid-sensor-attributes.o
diff --git a/drivers/iio/dac/ad5380.c b/drivers/iio/dac/ad5380.c
index 6c7898c..483fc37 100644
--- a/drivers/iio/dac/ad5380.c
+++ b/drivers/iio/dac/ad5380.c
@@ -406,7 +406,11 @@
 			goto error_free_reg;
 		}
 
-		st->vref = regulator_get_voltage(st->vref_reg);
+		ret = regulator_get_voltage(st->vref_reg);
+		if (ret < 0)
+			goto error_disable_reg;
+
+		st->vref = ret;
 	} else {
 		st->vref = st->chip_info->int_vref;
 		ctrl |= AD5380_CTRL_INT_VREF_EN;
diff --git a/drivers/iio/dac/ad5446.c b/drivers/iio/dac/ad5446.c
index 29f653d..f5583ae 100644
--- a/drivers/iio/dac/ad5446.c
+++ b/drivers/iio/dac/ad5446.c
@@ -226,7 +226,11 @@
 		if (ret)
 			goto error_put_reg;
 
-		voltage_uv = regulator_get_voltage(reg);
+		ret = regulator_get_voltage(reg);
+		if (ret < 0)
+			goto error_disable_reg;
+
+		voltage_uv = ret;
 	}
 
 	indio_dev = iio_device_alloc(sizeof(*st));
diff --git a/drivers/iio/dac/ad5504.c b/drivers/iio/dac/ad5504.c
index b2a31a0..0661829 100644
--- a/drivers/iio/dac/ad5504.c
+++ b/drivers/iio/dac/ad5504.c
@@ -296,7 +296,11 @@
 		if (ret)
 			goto error_put_reg;
 
-		voltage_uv = regulator_get_voltage(reg);
+		ret = regulator_get_voltage(reg);
+		if (ret < 0)
+			goto error_disable_reg;
+
+		voltage_uv = ret;
 	}
 
 	spi_set_drvdata(spi, indio_dev);
diff --git a/drivers/iio/dac/ad5624r_spi.c b/drivers/iio/dac/ad5624r_spi.c
index e994796..f6e1166 100644
--- a/drivers/iio/dac/ad5624r_spi.c
+++ b/drivers/iio/dac/ad5624r_spi.c
@@ -238,7 +238,11 @@
 		if (ret)
 			goto error_put_reg;
 
-		voltage_uv = regulator_get_voltage(st->reg);
+		ret = regulator_get_voltage(st->reg);
+		if (ret < 0)
+			goto error_disable_reg;
+
+		voltage_uv = ret;
 	}
 
 	spi_set_drvdata(spi, indio_dev);
diff --git a/drivers/iio/dac/ad5686.c b/drivers/iio/dac/ad5686.c
index 36e5138..ca9609d 100644
--- a/drivers/iio/dac/ad5686.c
+++ b/drivers/iio/dac/ad5686.c
@@ -332,7 +332,11 @@
 		if (ret)
 			goto error_put_reg;
 
-		voltage_uv = regulator_get_voltage(st->reg);
+		ret = regulator_get_voltage(st->reg);
+		if (ret < 0)
+			goto error_disable_reg;
+
+		voltage_uv = ret;
 	}
 
 	st->chip_info =
diff --git a/drivers/iio/dac/ad5791.c b/drivers/iio/dac/ad5791.c
index c84180f..6407b54 100644
--- a/drivers/iio/dac/ad5791.c
+++ b/drivers/iio/dac/ad5791.c
@@ -365,7 +365,11 @@
 		if (ret)
 			goto error_put_reg_pos;
 
-		pos_voltage_uv = regulator_get_voltage(st->reg_vdd);
+		ret = regulator_get_voltage(st->reg_vdd);
+		if (ret < 0)
+			goto error_disable_reg_pos;
+
+		pos_voltage_uv = ret;
 	}
 
 	st->reg_vss = regulator_get(&spi->dev, "vss");
@@ -374,7 +378,11 @@
 		if (ret)
 			goto error_put_reg_neg;
 
-		neg_voltage_uv = regulator_get_voltage(st->reg_vss);
+		ret = regulator_get_voltage(st->reg_vss);
+		if (ret < 0)
+			goto error_disable_reg_neg;
+
+		neg_voltage_uv = ret;
 	}
 
 	st->pwr_down = true;
@@ -428,6 +436,7 @@
 	if (!IS_ERR(st->reg_vss))
 		regulator_put(st->reg_vss);
 
+error_disable_reg_pos:
 	if (!IS_ERR(st->reg_vdd))
 		regulator_disable(st->reg_vdd);
 error_put_reg_pos:
diff --git a/drivers/iio/frequency/adf4350.c b/drivers/iio/frequency/adf4350.c
index e5033b4..a884252 100644
--- a/drivers/iio/frequency/adf4350.c
+++ b/drivers/iio/frequency/adf4350.c
@@ -173,7 +173,7 @@
 			} while ((st->r1_mod > ADF4350_MAX_MODULUS) && r_cnt);
 		} while (r_cnt == 0);
 
-		tmp = freq * (u64)st->r1_mod + (st->fpfd > 1);
+		tmp = freq * (u64)st->r1_mod + (st->fpfd >> 1);
 		do_div(tmp, st->fpfd); /* Div round closest (n + d/2)/d */
 		st->r0_fract = do_div(tmp, st->r1_mod);
 		st->r0_int = tmp;
diff --git a/drivers/iio/gyro/Kconfig b/drivers/iio/gyro/Kconfig
index 48ed148..96b68f6 100644
--- a/drivers/iio/gyro/Kconfig
+++ b/drivers/iio/gyro/Kconfig
@@ -17,6 +17,7 @@
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	select HID_SENSOR_IIO_COMMON
+	select HID_SENSOR_IIO_TRIGGER
 	tristate "HID Gyroscope 3D"
 	help
 	  Say yes here to build support for the HID SENSOR
diff --git a/drivers/iio/light/Kconfig b/drivers/iio/light/Kconfig
index 1763c9b..dbf80ab 100644
--- a/drivers/iio/light/Kconfig
+++ b/drivers/iio/light/Kconfig
@@ -47,6 +47,7 @@
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	select HID_SENSOR_IIO_COMMON
+	select HID_SENSOR_IIO_TRIGGER
 	tristate "HID ALS"
 	help
 	  Say yes here to build support for the HID SENSOR
diff --git a/drivers/iio/magnetometer/Kconfig b/drivers/iio/magnetometer/Kconfig
index c1f0cdd..ff11d68 100644
--- a/drivers/iio/magnetometer/Kconfig
+++ b/drivers/iio/magnetometer/Kconfig
@@ -8,6 +8,7 @@
 	select IIO_BUFFER
 	select IIO_TRIGGERED_BUFFER
 	select HID_SENSOR_IIO_COMMON
+	select HID_SENSOR_IIO_TRIGGER
 	tristate "HID Magenetometer 3D"
 	help
 	  Say yes here to build support for the HID SENSOR
diff --git a/drivers/input/keyboard/tegra-kbc.c b/drivers/input/keyboard/tegra-kbc.c
index c76f968..54ac1dc 100644
--- a/drivers/input/keyboard/tegra-kbc.c
+++ b/drivers/input/keyboard/tegra-kbc.c
@@ -30,7 +30,7 @@
 #include <linux/clk.h>
 #include <linux/slab.h>
 #include <linux/input/tegra_kbc.h>
-#include <mach/clk.h>
+#include <linux/clk/tegra.h>
 
 #define KBC_MAX_DEBOUNCE_CNT	0x3ffu
 
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 81837b0..faf10ba 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -975,6 +975,38 @@
 }
 
 /*
+ * Family15h Model 10h-1fh erratum 746 (IOMMU Logging May Stall Translations)
+ * Workaround:
+ *     BIOS should disable L2B micellaneous clock gating by setting
+ *     L2_L2B_CK_GATE_CONTROL[CKGateL2BMiscDisable](D0F2xF4_x90[2]) = 1b
+ */
+static void __init amd_iommu_erratum_746_workaround(struct amd_iommu *iommu)
+{
+	u32 value;
+
+	if ((boot_cpu_data.x86 != 0x15) ||
+	    (boot_cpu_data.x86_model < 0x10) ||
+	    (boot_cpu_data.x86_model > 0x1f))
+		return;
+
+	pci_write_config_dword(iommu->dev, 0xf0, 0x90);
+	pci_read_config_dword(iommu->dev, 0xf4, &value);
+
+	if (value & BIT(2))
+		return;
+
+	/* Select NB indirect register 0x90 and enable writing */
+	pci_write_config_dword(iommu->dev, 0xf0, 0x90 | (1 << 8));
+
+	pci_write_config_dword(iommu->dev, 0xf4, value | 0x4);
+	pr_info("AMD-Vi: Applying erratum 746 workaround for IOMMU at %s\n",
+		dev_name(&iommu->dev->dev));
+
+	/* Clear the enable writing bit */
+	pci_write_config_dword(iommu->dev, 0xf0, 0x90);
+}
+
+/*
  * This function clues the initialization function for one IOMMU
  * together and also allocates the command buffer and programs the
  * hardware. It does NOT enable the IOMMU. This is done afterwards.
@@ -1172,6 +1204,8 @@
 			iommu->stored_l2[i] = iommu_read_l2(iommu, i);
 	}
 
+	amd_iommu_erratum_746_workaround(iommu);
+
 	return pci_enable_device(iommu->dev);
 }
 
diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index b9d0911..eca2801 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -4234,6 +4234,21 @@
 	.pgsize_bitmap	= INTEL_IOMMU_PGSIZES,
 };
 
+static void quirk_iommu_g4x_gfx(struct pci_dev *dev)
+{
+	/* G4x/GM45 integrated gfx dmar support is totally busted. */
+	printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
+	dmar_map_gfx = 0;
+}
+
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e10, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e20, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e30, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e40, quirk_iommu_g4x_gfx);
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e90, quirk_iommu_g4x_gfx);
+
 static void quirk_iommu_rwbf(struct pci_dev *dev)
 {
 	/*
@@ -4242,12 +4257,6 @@
 	 */
 	printk(KERN_INFO "DMAR: Forcing write-buffer flush capability\n");
 	rwbf_quirk = 1;
-
-	/* https://bugzilla.redhat.com/show_bug.cgi?id=538163 */
-	if (dev->revision == 0x07) {
-		printk(KERN_INFO "DMAR: Disabling IOMMU for graphics on this chipset\n");
-		dmar_map_gfx = 0;
-	}
 }
 
 DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_rwbf);
diff --git a/drivers/irqchip/Kconfig b/drivers/irqchip/Kconfig
index 62ca575..a350969 100644
--- a/drivers/irqchip/Kconfig
+++ b/drivers/irqchip/Kconfig
@@ -1,3 +1,30 @@
+config IRQCHIP
+	def_bool y
+	depends on OF_IRQ
+
+config ARM_GIC
+	bool
+	select IRQ_DOMAIN
+	select MULTI_IRQ_HANDLER
+
+config GIC_NON_BANKED
+	bool
+
+config ARM_VIC
+	bool
+	select IRQ_DOMAIN
+	select MULTI_IRQ_HANDLER
+
+config ARM_VIC_NR
+	int
+	default 4 if ARCH_S5PV210
+	default 3 if ARCH_S5PC100
+	default 2
+	depends on ARM_VIC
+	help
+	  The maximum number of VICs available in the system, for
+	  power management.
+
 config VERSATILE_FPGA_IRQ
 	bool
 	select IRQ_DOMAIN
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index bf4609a..0fb8655 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -1,4 +1,8 @@
+obj-$(CONFIG_IRQCHIP)			+= irqchip.o
+
 obj-$(CONFIG_ARCH_BCM2835)		+= irq-bcm2835.o
 obj-$(CONFIG_ARCH_SUNXI)		+= irq-sunxi.o
-obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
 obj-$(CONFIG_ARCH_SPEAR3XX)		+= spear-shirq.o
+obj-$(CONFIG_ARM_GIC)			+= irq-gic.o
+obj-$(CONFIG_ARM_VIC)			+= irq-vic.o
+obj-$(CONFIG_VERSATILE_FPGA_IRQ)	+= irq-versatile-fpga.o
diff --git a/arch/arm/common/gic.c b/drivers/irqchip/irq-gic.c
similarity index 96%
rename from arch/arm/common/gic.c
rename to drivers/irqchip/irq-gic.c
index 36ae03a..69d9a39 100644
--- a/arch/arm/common/gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -38,12 +38,14 @@
 #include <linux/interrupt.h>
 #include <linux/percpu.h>
 #include <linux/slab.h>
+#include <linux/irqchip/arm-gic.h>
 
 #include <asm/irq.h>
 #include <asm/exception.h>
 #include <asm/smp_plat.h>
 #include <asm/mach/irq.h>
-#include <asm/hardware/gic.h>
+
+#include "irqchip.h"
 
 union gic_base {
 	void __iomem *common_base;
@@ -276,7 +278,7 @@
 #define gic_set_wake	NULL
 #endif
 
-asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
+static asmlinkage void __exception_irq_entry gic_handle_irq(struct pt_regs *regs)
 {
 	u32 irqstat, irqnr;
 	struct gic_chip_data *gic = &gic_data[0];
@@ -617,6 +619,27 @@
 }
 #endif
 
+#ifdef CONFIG_SMP
+void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
+{
+	int cpu;
+	unsigned long map = 0;
+
+	/* Convert our logical CPU mask into a physical one. */
+	for_each_cpu(cpu, mask)
+		map |= 1 << cpu_logical_map(cpu);
+
+	/*
+	 * Ensure that stores to Normal memory are visible to the
+	 * other CPUs before issuing the IPI.
+	 */
+	dsb();
+
+	/* this always happens on GIC0 */
+	writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
+}
+#endif
+
 static int gic_irq_domain_map(struct irq_domain *d, unsigned int irq,
 				irq_hw_number_t hw)
 {
@@ -743,6 +766,12 @@
 	if (WARN_ON(!gic->domain))
 		return;
 
+#ifdef CONFIG_SMP
+	set_smp_cross_call(gic_raise_softirq);
+#endif
+
+	set_handle_irq(gic_handle_irq);
+
 	gic_chip.flags |= gic_arch_extn.flags;
 	gic_dist_init(gic);
 	gic_cpu_init(gic);
@@ -756,27 +785,6 @@
 	gic_cpu_init(&gic_data[gic_nr]);
 }
 
-#ifdef CONFIG_SMP
-void gic_raise_softirq(const struct cpumask *mask, unsigned int irq)
-{
-	int cpu;
-	unsigned long map = 0;
-
-	/* Convert our logical CPU mask into a physical one. */
-	for_each_cpu(cpu, mask)
-		map |= gic_cpu_map[cpu];
-
-	/*
-	 * Ensure that stores to Normal memory are visible to the
-	 * other CPUs before issuing the IPI.
-	 */
-	dsb();
-
-	/* this always happens on GIC0 */
-	writel_relaxed(map << 16 | irq, gic_data_dist_base(&gic_data[0]) + GIC_DIST_SOFTINT);
-}
-#endif
-
 #ifdef CONFIG_OF
 static int gic_cnt __initdata = 0;
 
@@ -808,4 +816,9 @@
 	gic_cnt++;
 	return 0;
 }
+IRQCHIP_DECLARE(cortex_a15_gic, "arm,cortex-a15-gic", gic_of_init);
+IRQCHIP_DECLARE(cortex_a9_gic, "arm,cortex-a9-gic", gic_of_init);
+IRQCHIP_DECLARE(msm_8660_qgic, "qcom,msm-8660-qgic", gic_of_init);
+IRQCHIP_DECLARE(msm_qgic2, "qcom,msm-qgic2", gic_of_init);
+
 #endif
diff --git a/arch/arm/common/vic.c b/drivers/irqchip/irq-vic.c
similarity index 91%
rename from arch/arm/common/vic.c
rename to drivers/irqchip/irq-vic.c
index 8f324b9..3cf97aa 100644
--- a/arch/arm/common/vic.c
+++ b/drivers/irqchip/irq-vic.c
@@ -30,10 +30,29 @@
 #include <linux/syscore_ops.h>
 #include <linux/device.h>
 #include <linux/amba/bus.h>
+#include <linux/irqchip/arm-vic.h>
 
 #include <asm/exception.h>
 #include <asm/mach/irq.h>
-#include <asm/hardware/vic.h>
+
+#include "irqchip.h"
+
+#define VIC_IRQ_STATUS			0x00
+#define VIC_FIQ_STATUS			0x04
+#define VIC_INT_SELECT			0x0c	/* 1 = FIQ, 0 = IRQ */
+#define VIC_INT_SOFT			0x18
+#define VIC_INT_SOFT_CLEAR		0x1c
+#define VIC_PROTECT			0x20
+#define VIC_PL190_VECT_ADDR		0x30	/* PL190 only */
+#define VIC_PL190_DEF_VECT_ADDR		0x34	/* PL190 only */
+
+#define VIC_VECT_ADDR0			0x100	/* 0 to 15 (0..31 PL192) */
+#define VIC_VECT_CNTL0			0x200	/* 0 to 15 (0..31 PL192) */
+#define VIC_ITCR			0x300	/* VIC test control register */
+
+#define VIC_VECT_CNTL_ENABLE		(1 << 5)
+
+#define VIC_PL192_VECT_ADDR		0xF00
 
 /**
  * struct vic_device - VIC PM device
@@ -66,6 +85,8 @@
 
 static int vic_id;
 
+static void vic_handle_irq(struct pt_regs *regs);
+
 /**
  * vic_init2 - common initialisation code
  * @base: Base of the VIC.
@@ -182,6 +203,40 @@
 	return 0;
 }
 
+/*
+ * Handle each interrupt in a single VIC.  Returns non-zero if we've
+ * handled at least one interrupt.  This reads the status register
+ * before handling each interrupt, which is necessary given that
+ * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
+ */
+static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
+{
+	u32 stat, irq;
+	int handled = 0;
+
+	while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
+		irq = ffs(stat) - 1;
+		handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
+		handled = 1;
+	}
+
+	return handled;
+}
+
+/*
+ * Keep iterating over all registered VIC's until there are no pending
+ * interrupts.
+ */
+static asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
+{
+	int i, handled;
+
+	do {
+		for (i = 0, handled = 0; i < vic_id; ++i)
+			handled |= handle_one_vic(&vic_devices[i], regs);
+	} while (handled);
+}
+
 static struct irq_domain_ops vic_irqdomain_ops = {
 	.map = vic_irqdomain_map,
 	.xlate = irq_domain_xlate_onetwocell,
@@ -218,6 +273,7 @@
 	v->valid_sources = valid_sources;
 	v->resume_sources = resume_sources;
 	v->irq = irq;
+	set_handle_irq(vic_handle_irq);
 	vic_id++;
 	v->domain = irq_domain_add_simple(node, fls(valid_sources), irq,
 					  &vic_irqdomain_ops, v);
@@ -427,38 +483,7 @@
 
 	return 0;
 }
+IRQCHIP_DECLARE(arm_pl190_vic, "arm,pl190-vic", vic_of_init);
+IRQCHIP_DECLARE(arm_pl192_vic, "arm,pl192-vic", vic_of_init);
+IRQCHIP_DECLARE(arm_versatile_vic, "arm,versatile-vic", vic_of_init);
 #endif /* CONFIG OF */
-
-/*
- * Handle each interrupt in a single VIC.  Returns non-zero if we've
- * handled at least one interrupt.  This reads the status register
- * before handling each interrupt, which is necessary given that
- * handle_IRQ may briefly re-enable interrupts for soft IRQ handling.
- */
-static int handle_one_vic(struct vic_device *vic, struct pt_regs *regs)
-{
-	u32 stat, irq;
-	int handled = 0;
-
-	while ((stat = readl_relaxed(vic->base + VIC_IRQ_STATUS))) {
-		irq = ffs(stat) - 1;
-		handle_IRQ(irq_find_mapping(vic->domain, irq), regs);
-		handled = 1;
-	}
-
-	return handled;
-}
-
-/*
- * Keep iterating over all registered VIC's until there are no pending
- * interrupts.
- */
-asmlinkage void __exception_irq_entry vic_handle_irq(struct pt_regs *regs)
-{
-	int i, handled;
-
-	do {
-		for (i = 0, handled = 0; i < vic_id; ++i)
-			handled |= handle_one_vic(&vic_devices[i], regs);
-	} while (handled);
-}
diff --git a/drivers/irqchip/irqchip.c b/drivers/irqchip/irqchip.c
new file mode 100644
index 0000000..f496afc
--- /dev/null
+++ b/drivers/irqchip/irqchip.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Thomas Petazzoni
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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/init.h>
+#include <linux/of_irq.h>
+
+#include "irqchip.h"
+
+/*
+ * This special of_device_id is the sentinel at the end of the
+ * of_device_id[] array of all irqchips. It is automatically placed at
+ * the end of the array by the linker, thanks to being part of a
+ * special section.
+ */
+static const struct of_device_id
+irqchip_of_match_end __used __section(__irqchip_of_end);
+
+extern struct of_device_id __irqchip_begin[];
+
+void __init irqchip_init(void)
+{
+	of_irq_init(__irqchip_begin);
+}
diff --git a/drivers/irqchip/irqchip.h b/drivers/irqchip/irqchip.h
new file mode 100644
index 0000000..e445ba2
--- /dev/null
+++ b/drivers/irqchip/irqchip.h
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2012 Thomas Petazzoni
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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 _IRQCHIP_H
+#define _IRQCHIP_H
+
+/*
+ * This macro must be used by the different irqchip drivers to declare
+ * the association between their DT compatible string and their
+ * initialization function.
+ *
+ * @name: name that must be unique accross all IRQCHIP_DECLARE of the
+ * same file.
+ * @compstr: compatible string of the irqchip driver
+ * @fn: initialization function
+ */
+#define IRQCHIP_DECLARE(name,compstr,fn)				\
+	static const struct of_device_id irqchip_of_match_##name	\
+	__used __section(__irqchip_of_table)				\
+	= { .compatible = compstr, .data = fn }
+
+#endif
diff --git a/drivers/irqchip/spear-shirq.c b/drivers/irqchip/spear-shirq.c
index 80e1d2f..8527743 100644
--- a/drivers/irqchip/spear-shirq.c
+++ b/drivers/irqchip/spear-shirq.c
@@ -25,6 +25,8 @@
 #include <linux/of_irq.h>
 #include <linux/spinlock.h>
 
+#include "irqchip.h"
+
 static DEFINE_SPINLOCK(lock);
 
 /* spear300 shared irq registers offsets and masks */
@@ -300,6 +302,7 @@
 	return shirq_init(spear300_shirq_blocks,
 			ARRAY_SIZE(spear300_shirq_blocks), np);
 }
+IRQCHIP_DECLARE(spear300_shirq, "st,spear300-shirq", spear300_shirq_of_init);
 
 int __init spear310_shirq_of_init(struct device_node *np,
 		struct device_node *parent)
@@ -307,6 +310,7 @@
 	return shirq_init(spear310_shirq_blocks,
 			ARRAY_SIZE(spear310_shirq_blocks), np);
 }
+IRQCHIP_DECLARE(spear310_shirq, "st,spear310-shirq", spear310_shirq_of_init);
 
 int __init spear320_shirq_of_init(struct device_node *np,
 		struct device_node *parent)
@@ -314,3 +318,4 @@
 	return shirq_init(spear320_shirq_blocks,
 			ARRAY_SIZE(spear320_shirq_blocks), np);
 }
+IRQCHIP_DECLARE(spear320_shirq, "st,spear320-shirq", spear320_shirq_of_init);
diff --git a/drivers/isdn/gigaset/capi.c b/drivers/isdn/gigaset/capi.c
index 68452b7..03a0a01 100644
--- a/drivers/isdn/gigaset/capi.c
+++ b/drivers/isdn/gigaset/capi.c
@@ -248,6 +248,8 @@
 		CAPIMSG_APPID(data), CAPIMSG_MSGID(data), l,
 		CAPIMSG_CONTROL(data));
 	l -= 12;
+	if (l <= 0)
+		return;
 	dbgline = kmalloc(3 * l, GFP_ATOMIC);
 	if (!dbgline)
 		return;
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c
index 3d8984e..9e58dbd 100644
--- a/drivers/md/dm-raid.c
+++ b/drivers/md/dm-raid.c
@@ -340,24 +340,22 @@
 }
 
 /*
- * validate_rebuild_devices
+ * validate_raid_redundancy
  * @rs
  *
- * Determine if the devices specified for rebuild can result in a valid
- * usable array that is capable of rebuilding the given devices.
+ * Determine if there are enough devices in the array that haven't
+ * failed (or are being rebuilt) to form a usable array.
  *
  * Returns: 0 on success, -EINVAL on failure.
  */
-static int validate_rebuild_devices(struct raid_set *rs)
+static int validate_raid_redundancy(struct raid_set *rs)
 {
 	unsigned i, rebuild_cnt = 0;
 	unsigned rebuilds_per_group, copies, d;
 
-	if (!(rs->print_flags & DMPF_REBUILD))
-		return 0;
-
 	for (i = 0; i < rs->md.raid_disks; i++)
-		if (!test_bit(In_sync, &rs->dev[i].rdev.flags))
+		if (!test_bit(In_sync, &rs->dev[i].rdev.flags) ||
+		    !rs->dev[i].rdev.sb_page)
 			rebuild_cnt++;
 
 	switch (rs->raid_type->level) {
@@ -393,27 +391,24 @@
 		 *          A    A    B    B    C
 		 *          C    D    D    E    E
 		 */
-		rebuilds_per_group = 0;
 		for (i = 0; i < rs->md.raid_disks * copies; i++) {
+			if (!(i % copies))
+				rebuilds_per_group = 0;
 			d = i % rs->md.raid_disks;
-			if (!test_bit(In_sync, &rs->dev[d].rdev.flags) &&
+			if ((!rs->dev[d].rdev.sb_page ||
+			     !test_bit(In_sync, &rs->dev[d].rdev.flags)) &&
 			    (++rebuilds_per_group >= copies))
 				goto too_many;
-			if (!((i + 1) % copies))
-				rebuilds_per_group = 0;
 		}
 		break;
 	default:
-		DMERR("The rebuild parameter is not supported for %s",
-		      rs->raid_type->name);
-		rs->ti->error = "Rebuild not supported for this RAID type";
-		return -EINVAL;
+		if (rebuild_cnt)
+			return -EINVAL;
 	}
 
 	return 0;
 
 too_many:
-	rs->ti->error = "Too many rebuild devices specified";
 	return -EINVAL;
 }
 
@@ -664,9 +659,6 @@
 	}
 	rs->md.dev_sectors = sectors_per_dev;
 
-	if (validate_rebuild_devices(rs))
-		return -EINVAL;
-
 	/* Assume there are no metadata devices until the drives are parsed */
 	rs->md.persistent = 0;
 	rs->md.external = 1;
@@ -995,28 +987,10 @@
 static int analyse_superblocks(struct dm_target *ti, struct raid_set *rs)
 {
 	int ret;
-	unsigned redundancy = 0;
 	struct raid_dev *dev;
 	struct md_rdev *rdev, *tmp, *freshest;
 	struct mddev *mddev = &rs->md;
 
-	switch (rs->raid_type->level) {
-	case 1:
-		redundancy = rs->md.raid_disks - 1;
-		break;
-	case 4:
-	case 5:
-	case 6:
-		redundancy = rs->raid_type->parity_devs;
-		break;
-	case 10:
-		redundancy = raid10_md_layout_to_copies(mddev->layout) - 1;
-		break;
-	default:
-		ti->error = "Unknown RAID type";
-		return -EINVAL;
-	}
-
 	freshest = NULL;
 	rdev_for_each_safe(rdev, tmp, mddev) {
 		/*
@@ -1045,44 +1019,43 @@
 			break;
 		default:
 			dev = container_of(rdev, struct raid_dev, rdev);
-			if (redundancy--) {
-				if (dev->meta_dev)
-					dm_put_device(ti, dev->meta_dev);
+			if (dev->meta_dev)
+				dm_put_device(ti, dev->meta_dev);
 
-				dev->meta_dev = NULL;
-				rdev->meta_bdev = NULL;
+			dev->meta_dev = NULL;
+			rdev->meta_bdev = NULL;
 
-				if (rdev->sb_page)
-					put_page(rdev->sb_page);
+			if (rdev->sb_page)
+				put_page(rdev->sb_page);
 
-				rdev->sb_page = NULL;
+			rdev->sb_page = NULL;
 
-				rdev->sb_loaded = 0;
+			rdev->sb_loaded = 0;
 
-				/*
-				 * We might be able to salvage the data device
-				 * even though the meta device has failed.  For
-				 * now, we behave as though '- -' had been
-				 * set for this device in the table.
-				 */
-				if (dev->data_dev)
-					dm_put_device(ti, dev->data_dev);
+			/*
+			 * We might be able to salvage the data device
+			 * even though the meta device has failed.  For
+			 * now, we behave as though '- -' had been
+			 * set for this device in the table.
+			 */
+			if (dev->data_dev)
+				dm_put_device(ti, dev->data_dev);
 
-				dev->data_dev = NULL;
-				rdev->bdev = NULL;
+			dev->data_dev = NULL;
+			rdev->bdev = NULL;
 
-				list_del(&rdev->same_set);
-
-				continue;
-			}
-			ti->error = "Failed to load superblock";
-			return ret;
+			list_del(&rdev->same_set);
 		}
 	}
 
 	if (!freshest)
 		return 0;
 
+	if (validate_raid_redundancy(rs)) {
+		rs->ti->error = "Insufficient redundancy to activate array";
+		return -EINVAL;
+	}
+
 	/*
 	 * Validation of the freshest device provides the source of
 	 * validation for the remaining devices.
@@ -1432,7 +1405,7 @@
 
 static struct target_type raid_target = {
 	.name = "raid",
-	.version = {1, 4, 0},
+	.version = {1, 4, 1},
 	.module = THIS_MODULE,
 	.ctr = raid_ctr,
 	.dtr = raid_dtr,
diff --git a/drivers/md/dm-thin.c b/drivers/md/dm-thin.c
index 675ae52..5409607 100644
--- a/drivers/md/dm-thin.c
+++ b/drivers/md/dm-thin.c
@@ -2746,19 +2746,9 @@
 	return 0;
 }
 
-/*
- * A thin device always inherits its queue limits from its pool.
- */
-static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
-{
-	struct thin_c *tc = ti->private;
-
-	*limits = bdev_get_queue(tc->pool_dev->bdev)->limits;
-}
-
 static struct target_type thin_target = {
 	.name = "thin",
-	.version = {1, 6, 0},
+	.version = {1, 7, 0},
 	.module	= THIS_MODULE,
 	.ctr = thin_ctr,
 	.dtr = thin_dtr,
@@ -2767,7 +2757,6 @@
 	.postsuspend = thin_postsuspend,
 	.status = thin_status,
 	.iterate_devices = thin_iterate_devices,
-	.io_hints = thin_io_hints,
 };
 
 /*----------------------------------------------------------------*/
diff --git a/drivers/md/dm.c b/drivers/md/dm.c
index c72e4d5..314a0e2 100644
--- a/drivers/md/dm.c
+++ b/drivers/md/dm.c
@@ -1188,6 +1188,7 @@
 {
 	struct dm_target *ti;
 	sector_t len;
+	unsigned num_requests;
 
 	do {
 		ti = dm_table_find_target(ci->map, ci->sector);
@@ -1200,7 +1201,8 @@
 		 * reconfiguration might also have changed that since the
 		 * check was performed.
 		 */
-		if (!get_num_requests || !get_num_requests(ti))
+		num_requests = get_num_requests ? get_num_requests(ti) : 0;
+		if (!num_requests)
 			return -EOPNOTSUPP;
 
 		if (is_split_required && !is_split_required(ti))
@@ -1208,7 +1210,7 @@
 		else
 			len = min(ci->sector_count, max_io_len(ci->sector, ti));
 
-		__issue_target_requests(ci, ti, ti->num_discard_requests, len);
+		__issue_target_requests(ci, ti, num_requests, len);
 
 		ci->sector += len;
 	} while (ci->sector_count -= len);
diff --git a/drivers/media/i2c/m5mols/m5mols_core.c b/drivers/media/i2c/m5mols/m5mols_core.c
index 8a8d42fe..d4e7567 100644
--- a/drivers/media/i2c/m5mols/m5mols_core.c
+++ b/drivers/media/i2c/m5mols/m5mols_core.c
@@ -556,7 +556,7 @@
 	mutex_lock(&info->lock);
 
 	format = __find_format(info, fh, fmt->which, info->res_type);
-	if (!format)
+	if (format)
 		fmt->format = *format;
 	else
 		ret = -EINVAL;
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c
index 1cf8293..4a980e0 100644
--- a/drivers/media/platform/coda.c
+++ b/drivers/media/platform/coda.c
@@ -23,8 +23,8 @@
 #include <linux/slab.h>
 #include <linux/videodev2.h>
 #include <linux/of.h>
+#include <linux/platform_data/imx-iram.h>
 
-#include <mach/iram.h>
 #include <media/v4l2-ctrls.h>
 #include <media/v4l2-device.h>
 #include <media/v4l2-ioctl.h>
diff --git a/drivers/media/platform/omap3isp/ispvideo.c b/drivers/media/platform/omap3isp/ispvideo.c
index e0d73a6..8dac175 100644
--- a/drivers/media/platform/omap3isp/ispvideo.c
+++ b/drivers/media/platform/omap3isp/ispvideo.c
@@ -35,9 +35,6 @@
 #include <linux/vmalloc.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
-#include <plat/iommu.h>
-#include <plat/iovmm.h>
-#include <plat/omap-pm.h>
 
 #include "ispvideo.h"
 #include "isp.h"
diff --git a/drivers/media/platform/s5p-fimc/fimc-mdevice.c b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
index 4ab99f3..b4a68ec 100644
--- a/drivers/media/platform/s5p-fimc/fimc-mdevice.c
+++ b/drivers/media/platform/s5p-fimc/fimc-mdevice.c
@@ -593,7 +593,7 @@
 {
 	struct media_entity *source, *sink;
 	unsigned int flags = MEDIA_LNK_FL_ENABLED;
-	int i, ret;
+	int i, ret = 0;
 
 	for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
 		struct fimc_lite *fimc = fmd->fimc_lite[i];
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc.c b/drivers/media/platform/s5p-mfc/s5p_mfc.c
index 379f574..681bc6b 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc.c
@@ -412,62 +412,48 @@
 }
 
 /* Error handling for interrupt */
-static void s5p_mfc_handle_error(struct s5p_mfc_ctx *ctx,
-				 unsigned int reason, unsigned int err)
+static void s5p_mfc_handle_error(struct s5p_mfc_dev *dev,
+		struct s5p_mfc_ctx *ctx, unsigned int reason, unsigned int err)
 {
-	struct s5p_mfc_dev *dev;
 	unsigned long flags;
 
-	/* If no context is available then all necessary
-	 * processing has been done. */
-	if (ctx == NULL)
-		return;
-
-	dev = ctx->dev;
 	mfc_err("Interrupt Error: %08x\n", err);
-	s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
-	wake_up_dev(dev, reason, err);
 
-	/* Error recovery is dependent on the state of context */
-	switch (ctx->state) {
-	case MFCINST_INIT:
-		/* This error had to happen while acquireing instance */
-	case MFCINST_GOT_INST:
-		/* This error had to happen while parsing the header */
-	case MFCINST_HEAD_PARSED:
-		/* This error had to happen while setting dst buffers */
-	case MFCINST_RETURN_INST:
-		/* This error had to happen while releasing instance */
-		clear_work_bit(ctx);
-		wake_up_ctx(ctx, reason, err);
-		if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-			BUG();
-		s5p_mfc_clock_off();
-		ctx->state = MFCINST_ERROR;
-		break;
-	case MFCINST_FINISHING:
-	case MFCINST_FINISHED:
-	case MFCINST_RUNNING:
-		/* It is higly probable that an error occured
-		 * while decoding a frame */
-		clear_work_bit(ctx);
-		ctx->state = MFCINST_ERROR;
-		/* Mark all dst buffers as having an error */
-		spin_lock_irqsave(&dev->irqlock, flags);
-		s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->dst_queue,
-				&ctx->vq_dst);
-		/* Mark all src buffers as having an error */
-		s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue, &ctx->src_queue,
-				&ctx->vq_src);
-		spin_unlock_irqrestore(&dev->irqlock, flags);
-		if (test_and_clear_bit(0, &dev->hw_lock) == 0)
-			BUG();
-		s5p_mfc_clock_off();
-		break;
-	default:
-		mfc_err("Encountered an error interrupt which had not been handled\n");
-		break;
+	if (ctx != NULL) {
+		/* Error recovery is dependent on the state of context */
+		switch (ctx->state) {
+		case MFCINST_RES_CHANGE_INIT:
+		case MFCINST_RES_CHANGE_FLUSH:
+		case MFCINST_RES_CHANGE_END:
+		case MFCINST_FINISHING:
+		case MFCINST_FINISHED:
+		case MFCINST_RUNNING:
+			/* It is higly probable that an error occured
+			 * while decoding a frame */
+			clear_work_bit(ctx);
+			ctx->state = MFCINST_ERROR;
+			/* Mark all dst buffers as having an error */
+			spin_lock_irqsave(&dev->irqlock, flags);
+			s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue,
+						&ctx->dst_queue, &ctx->vq_dst);
+			/* Mark all src buffers as having an error */
+			s5p_mfc_hw_call(dev->mfc_ops, cleanup_queue,
+						&ctx->src_queue, &ctx->vq_src);
+			spin_unlock_irqrestore(&dev->irqlock, flags);
+			wake_up_ctx(ctx, reason, err);
+			break;
+		default:
+			clear_work_bit(ctx);
+			ctx->state = MFCINST_ERROR;
+			wake_up_ctx(ctx, reason, err);
+			break;
+		}
 	}
+	if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+		BUG();
+	s5p_mfc_hw_call(dev->mfc_ops, clear_int_flags, dev);
+	s5p_mfc_clock_off();
+	wake_up_dev(dev, reason, err);
 	return;
 }
 
@@ -632,7 +618,7 @@
 				dev->warn_start)
 			s5p_mfc_handle_frame(ctx, reason, err);
 		else
-			s5p_mfc_handle_error(ctx, reason, err);
+			s5p_mfc_handle_error(dev, ctx, reason, err);
 		clear_bit(0, &dev->enter_suspend);
 		break;
 
diff --git a/drivers/media/usb/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c
index 40ad668..3773a8a 100644
--- a/drivers/media/usb/gspca/kinect.c
+++ b/drivers/media/usb/gspca/kinect.c
@@ -381,6 +381,7 @@
 /* -- module initialisation -- */
 static const struct usb_device_id device_table[] = {
 	{USB_DEVICE(0x045e, 0x02ae)},
+	{USB_DEVICE(0x045e, 0x02bf)},
 	{}
 };
 
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c
index 70511d5..1220340 100644
--- a/drivers/media/usb/gspca/sonixb.c
+++ b/drivers/media/usb/gspca/sonixb.c
@@ -496,7 +496,7 @@
 	}
 }
 
-static void i2c_w(struct gspca_dev *gspca_dev, const __u8 *buffer)
+static void i2c_w(struct gspca_dev *gspca_dev, const u8 *buf)
 {
 	int retry = 60;
 
@@ -504,16 +504,19 @@
 		return;
 
 	/* is i2c ready */
-	reg_w(gspca_dev, 0x08, buffer, 8);
+	reg_w(gspca_dev, 0x08, buf, 8);
 	while (retry--) {
 		if (gspca_dev->usb_err < 0)
 			return;
-		msleep(10);
+		msleep(1);
 		reg_r(gspca_dev, 0x08);
 		if (gspca_dev->usb_buf[0] & 0x04) {
 			if (gspca_dev->usb_buf[0] & 0x08) {
 				dev_err(gspca_dev->v4l2_dev.dev,
-					"i2c write error\n");
+					"i2c error writing %02x %02x %02x %02x"
+					" %02x %02x %02x %02x\n",
+					buf[0], buf[1], buf[2], buf[3],
+					buf[4], buf[5], buf[6], buf[7]);
 				gspca_dev->usb_err = -EIO;
 			}
 			return;
@@ -530,7 +533,7 @@
 	for (;;) {
 		if (gspca_dev->usb_err < 0)
 			return;
-		reg_w(gspca_dev, 0x08, *buffer, 8);
+		i2c_w(gspca_dev, *buffer);
 		len -= 8;
 		if (len <= 0)
 			break;
diff --git a/drivers/media/usb/gspca/sonixj.c b/drivers/media/usb/gspca/sonixj.c
index 5a86047..36307a9 100644
--- a/drivers/media/usb/gspca/sonixj.c
+++ b/drivers/media/usb/gspca/sonixj.c
@@ -1550,6 +1550,7 @@
 			0,
 			gspca_dev->usb_buf, 8,
 			500);
+	msleep(2);
 	if (ret < 0) {
 		pr_err("i2c_w1 err %d\n", ret);
 		gspca_dev->usb_err = ret;
diff --git a/drivers/media/usb/uvc/uvc_ctrl.c b/drivers/media/usb/uvc/uvc_ctrl.c
index 2bb7613..d5baab1 100644
--- a/drivers/media/usb/uvc/uvc_ctrl.c
+++ b/drivers/media/usb/uvc/uvc_ctrl.c
@@ -1431,8 +1431,10 @@
 	int ret;
 
 	ctrl = uvc_find_control(chain, xctrl->id, &mapping);
-	if (ctrl == NULL || (ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR) == 0)
+	if (ctrl == NULL)
 		return -EINVAL;
+	if (!(ctrl->info.flags & UVC_CTRL_FLAG_SET_CUR))
+		return -EACCES;
 
 	/* Clamp out of range values. */
 	switch (mapping->v4l2_type) {
diff --git a/drivers/media/usb/uvc/uvc_v4l2.c b/drivers/media/usb/uvc/uvc_v4l2.c
index f2ee8c6..68d59b5 100644
--- a/drivers/media/usb/uvc/uvc_v4l2.c
+++ b/drivers/media/usb/uvc/uvc_v4l2.c
@@ -657,8 +657,7 @@
 			ret = uvc_ctrl_get(chain, ctrl);
 			if (ret < 0) {
 				uvc_ctrl_rollback(handle);
-				ctrls->error_idx = ret == -ENOENT
-						 ? ctrls->count : i;
+				ctrls->error_idx = i;
 				return ret;
 			}
 		}
@@ -686,8 +685,7 @@
 			ret = uvc_ctrl_set(chain, ctrl);
 			if (ret < 0) {
 				uvc_ctrl_rollback(handle);
-				ctrls->error_idx = (ret == -ENOENT &&
-						    cmd == VIDIOC_S_EXT_CTRLS)
+				ctrls->error_idx = cmd == VIDIOC_S_EXT_CTRLS
 						 ? ctrls->count : i;
 				return ret;
 			}
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 9f81be2..e02c479 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -921,8 +921,10 @@
 		 * In videobuf we use our internal V4l2_planes struct for
 		 * single-planar buffers as well, for simplicity.
 		 */
-		if (V4L2_TYPE_IS_OUTPUT(b->type))
+		if (V4L2_TYPE_IS_OUTPUT(b->type)) {
 			v4l2_planes[0].bytesused = b->bytesused;
+			v4l2_planes[0].data_offset = 0;
+		}
 
 		if (b->memory == V4L2_MEMORY_USERPTR) {
 			v4l2_planes[0].m.userptr = b->m.userptr;
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index 1c0abd4..ff553ba 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -237,6 +237,7 @@
 	depends on I2C=y && GPIOLIB
 	select MFD_CORE
 	select REGMAP_I2C
+	select REGMAP_IRQ
 	select IRQ_DOMAIN
 	help
 	  if you say yes here you get support for the TPS65910 series of
@@ -292,6 +293,7 @@
 	bool "Texas Instruments TWL4030/TWL5030/TWL6030/TPS659x0 Support"
 	depends on I2C=y && GENERIC_HARDIRQS
 	select IRQ_DOMAIN
+	select REGMAP_I2C
 	help
 	  Say yes here if you have TWL4030 / TWL6030 family chip on your board.
 	  This core driver provides register access and IRQ handling
diff --git a/drivers/mfd/ab8500-core.c b/drivers/mfd/ab8500-core.c
index e1650ba..4778bb1 100644
--- a/drivers/mfd/ab8500-core.c
+++ b/drivers/mfd/ab8500-core.c
@@ -19,6 +19,7 @@
 #include <linux/mfd/core.h>
 #include <linux/mfd/abx500.h>
 #include <linux/mfd/abx500/ab8500.h>
+#include <linux/mfd/abx500/ab8500-bm.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/regulator/ab8500.h>
 #include <linux/of.h>
diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c
index bc8a3ed..222c03a 100644
--- a/drivers/mfd/arizona-core.c
+++ b/drivers/mfd/arizona-core.c
@@ -239,7 +239,12 @@
 		return ret;
 	}
 
-	regcache_sync(arizona->regmap);
+	ret = regcache_sync(arizona->regmap);
+	if (ret != 0) {
+		dev_err(arizona->dev, "Failed to restore register cache\n");
+		regulator_disable(arizona->dcvdd);
+		return ret;
+	}
 
 	return 0;
 }
diff --git a/drivers/mfd/arizona-irq.c b/drivers/mfd/arizona-irq.c
index 74713bf..2bec5f0 100644
--- a/drivers/mfd/arizona-irq.c
+++ b/drivers/mfd/arizona-irq.c
@@ -176,14 +176,7 @@
 		aod = &wm5102_aod;
 		irq = &wm5102_irq;
 
-		switch (arizona->rev) {
-		case 0:
-		case 1:
-			ctrlif_error = false;
-			break;
-		default:
-			break;
-		}
+		ctrlif_error = false;
 		break;
 #endif
 #ifdef CONFIG_MFD_WM5110
@@ -191,14 +184,7 @@
 		aod = &wm5110_aod;
 		irq = &wm5110_irq;
 
-		switch (arizona->rev) {
-		case 0:
-		case 1:
-			ctrlif_error = false;
-			break;
-		default:
-			break;
-		}
+		ctrlif_error = false;
 		break;
 #endif
 	default:
diff --git a/drivers/mfd/da9052-i2c.c b/drivers/mfd/da9052-i2c.c
index ac74a4d..885e567 100644
--- a/drivers/mfd/da9052-i2c.c
+++ b/drivers/mfd/da9052-i2c.c
@@ -27,6 +27,66 @@
 #include <linux/of_device.h>
 #endif
 
+/* I2C safe register check */
+static inline bool i2c_safe_reg(unsigned char reg)
+{
+	switch (reg) {
+	case DA9052_STATUS_A_REG:
+	case DA9052_STATUS_B_REG:
+	case DA9052_STATUS_C_REG:
+	case DA9052_STATUS_D_REG:
+	case DA9052_ADC_RES_L_REG:
+	case DA9052_ADC_RES_H_REG:
+	case DA9052_VDD_RES_REG:
+	case DA9052_ICHG_AV_REG:
+	case DA9052_TBAT_RES_REG:
+	case DA9052_ADCIN4_RES_REG:
+	case DA9052_ADCIN5_RES_REG:
+	case DA9052_ADCIN6_RES_REG:
+	case DA9052_TJUNC_RES_REG:
+	case DA9052_TSI_X_MSB_REG:
+	case DA9052_TSI_Y_MSB_REG:
+	case DA9052_TSI_LSB_REG:
+	case DA9052_TSI_Z_MSB_REG:
+		return true;
+	default:
+		return false;
+	}
+}
+
+/*
+ * There is an issue with DA9052 and DA9053_AA/BA/BB PMIC where the PMIC
+ * gets lockup up or fails to respond following a system reset.
+ * This fix is to follow any read or write with a dummy read to a safe
+ * register.
+ */
+int da9052_i2c_fix(struct da9052 *da9052, unsigned char reg)
+{
+	int val;
+
+	switch (da9052->chip_id) {
+	case DA9052:
+	case DA9053_AA:
+	case DA9053_BA:
+	case DA9053_BB:
+		/* A dummy read to a safe register address. */
+	if (!i2c_safe_reg(reg))
+			return regmap_read(da9052->regmap,
+					   DA9052_PARK_REGISTER,
+					   &val);
+		break;
+	default:
+		/*
+		 * For other chips parking of I2C register
+		 * to a safe place is not required.
+		 */
+		break;
+	}
+
+	return 0;
+}
+EXPORT_SYMBOL(da9052_i2c_fix);
+
 static int da9052_i2c_enable_multiwrite(struct da9052 *da9052)
 {
 	int reg_val, ret;
@@ -83,6 +143,7 @@
 
 	da9052->dev = &client->dev;
 	da9052->chip_irq = client->irq;
+	da9052->fix_io = da9052_i2c_fix;
 
 	i2c_set_clientdata(client, da9052);
 
diff --git a/drivers/mfd/db8500-prcmu.c b/drivers/mfd/db8500-prcmu.c
index dc8826d..6fbe1c9 100644
--- a/drivers/mfd/db8500-prcmu.c
+++ b/drivers/mfd/db8500-prcmu.c
@@ -26,13 +26,13 @@
 #include <linux/fs.h>
 #include <linux/platform_device.h>
 #include <linux/uaccess.h>
+#include <linux/irqchip/arm-gic.h>
 #include <linux/mfd/core.h>
 #include <linux/mfd/dbx500-prcmu.h>
 #include <linux/mfd/abx500/ab8500.h>
 #include <linux/regulator/db8500-prcmu.h>
 #include <linux/regulator/machine.h>
 #include <linux/cpufreq.h>
-#include <asm/hardware/gic.h>
 #include <mach/hardware.h>
 #include <mach/irqs.h>
 #include <mach/db8500-regs.h>
@@ -2524,7 +2524,7 @@
 
 		for (n = 0; n < NUM_PRCMU_WAKEUPS; n++) {
 			if (ev & prcmu_irq_bit[n])
-				generic_handle_irq(IRQ_PRCMU_BASE + n);
+				generic_handle_irq(irq_find_mapping(db8500_irq_domain, n));
 		}
 		r = true;
 		break;
@@ -2737,13 +2737,14 @@
 }
 
 static struct irq_domain_ops db8500_irq_ops = {
-        .map    = db8500_irq_map,
-        .xlate  = irq_domain_xlate_twocell,
+	.map    = db8500_irq_map,
+	.xlate  = irq_domain_xlate_twocell,
 };
 
 static int db8500_irq_init(struct device_node *np)
 {
-	int irq_base = -1;
+	int irq_base = 0;
+	int i;
 
 	/* In the device tree case, just take some IRQs */
 	if (!np)
@@ -2758,6 +2759,10 @@
 		return -ENOSYS;
 	}
 
+	/* All wakeups will be used, so create mappings for all */
+	for (i = 0; i < NUM_PRCMU_WAKEUPS; i++)
+		irq_create_mapping(db8500_irq_domain, i);
+
 	return 0;
 }
 
diff --git a/drivers/mfd/max77686.c b/drivers/mfd/max77686.c
index f6878f8..4d73963 100644
--- a/drivers/mfd/max77686.c
+++ b/drivers/mfd/max77686.c
@@ -93,15 +93,6 @@
 	if (max77686 == NULL)
 		return -ENOMEM;
 
-	max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config);
-	if (IS_ERR(max77686->regmap)) {
-		ret = PTR_ERR(max77686->regmap);
-		dev_err(max77686->dev, "Failed to allocate register map: %d\n",
-				ret);
-		kfree(max77686);
-		return ret;
-	}
-
 	i2c_set_clientdata(i2c, max77686);
 	max77686->dev = &i2c->dev;
 	max77686->i2c = i2c;
@@ -111,6 +102,15 @@
 	max77686->irq_gpio = pdata->irq_gpio;
 	max77686->irq = i2c->irq;
 
+	max77686->regmap = regmap_init_i2c(i2c, &max77686_regmap_config);
+	if (IS_ERR(max77686->regmap)) {
+		ret = PTR_ERR(max77686->regmap);
+		dev_err(max77686->dev, "Failed to allocate register map: %d\n",
+				ret);
+		kfree(max77686);
+		return ret;
+	}
+
 	if (regmap_read(max77686->regmap,
 			 MAX77686_REG_DEVICE_ID, &data) < 0) {
 		dev_err(max77686->dev,
diff --git a/drivers/mfd/max77693.c b/drivers/mfd/max77693.c
index cc5155e..9e60fed 100644
--- a/drivers/mfd/max77693.c
+++ b/drivers/mfd/max77693.c
@@ -114,35 +114,37 @@
 	u8 reg_data;
 	int ret = 0;
 
+	if (!pdata) {
+		dev_err(&i2c->dev, "No platform data found.\n");
+		return -EINVAL;
+	}
+
 	max77693 = devm_kzalloc(&i2c->dev,
 			sizeof(struct max77693_dev), GFP_KERNEL);
 	if (max77693 == NULL)
 		return -ENOMEM;
 
-	max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config);
-	if (IS_ERR(max77693->regmap)) {
-		ret = PTR_ERR(max77693->regmap);
-		dev_err(max77693->dev,"failed to allocate register map: %d\n",
-				ret);
-		goto err_regmap;
-	}
-
 	i2c_set_clientdata(i2c, max77693);
 	max77693->dev = &i2c->dev;
 	max77693->i2c = i2c;
 	max77693->irq = i2c->irq;
 	max77693->type = id->driver_data;
 
-	if (!pdata)
-		goto err_regmap;
+	max77693->regmap = devm_regmap_init_i2c(i2c, &max77693_regmap_config);
+	if (IS_ERR(max77693->regmap)) {
+		ret = PTR_ERR(max77693->regmap);
+		dev_err(max77693->dev, "failed to allocate register map: %d\n",
+				ret);
+		return ret;
+	}
 
 	max77693->wakeup = pdata->wakeup;
 
-	if (max77693_read_reg(max77693->regmap,
-				MAX77693_PMIC_REG_PMIC_ID2, &reg_data) < 0) {
+	ret = max77693_read_reg(max77693->regmap, MAX77693_PMIC_REG_PMIC_ID2,
+				&reg_data);
+	if (ret < 0) {
 		dev_err(max77693->dev, "device not found on this channel\n");
-		ret = -ENODEV;
-		goto err_regmap;
+		return ret;
 	} else
 		dev_info(max77693->dev, "device ID: 0x%x\n", reg_data);
 
@@ -163,7 +165,7 @@
 		ret = PTR_ERR(max77693->regmap_muic);
 		dev_err(max77693->dev,
 			"failed to allocate register map: %d\n", ret);
-		goto err_regmap;
+		goto err_regmap_muic;
 	}
 
 	ret = max77693_irq_init(max77693);
@@ -184,9 +186,9 @@
 err_mfd:
 	max77693_irq_exit(max77693);
 err_irq:
+err_regmap_muic:
 	i2c_unregister_device(max77693->muic);
 	i2c_unregister_device(max77693->haptic);
-err_regmap:
 	return ret;
 }
 
diff --git a/drivers/mfd/pcf50633-core.c b/drivers/mfd/pcf50633-core.c
index 64803f1..d115673 100644
--- a/drivers/mfd/pcf50633-core.c
+++ b/drivers/mfd/pcf50633-core.c
@@ -208,6 +208,8 @@
 	if (!pcf)
 		return -ENOMEM;
 
+	i2c_set_clientdata(client, pcf);
+	pcf->dev = &client->dev;
 	pcf->pdata = pdata;
 
 	mutex_init(&pcf->lock);
@@ -219,9 +221,6 @@
 		return ret;
 	}
 
-	i2c_set_clientdata(client, pcf);
-	pcf->dev = &client->dev;
-
 	version = pcf50633_reg_read(pcf, 0);
 	variant = pcf50633_reg_read(pcf, 1);
 	if (version < 0 || variant < 0) {
diff --git a/drivers/mfd/rtl8411.c b/drivers/mfd/rtl8411.c
index 89f046c..3d3b4ad 100644
--- a/drivers/mfd/rtl8411.c
+++ b/drivers/mfd/rtl8411.c
@@ -112,6 +112,21 @@
 			BPP_LDO_POWB, BPP_LDO_SUSPEND);
 }
 
+static int rtl8411_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+	u8 mask, val;
+
+	mask = (BPP_REG_TUNED18 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_MASK;
+	if (voltage == OUTPUT_3V3)
+		val = (BPP_ASIC_3V3 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_3V3;
+	else if (voltage == OUTPUT_1V8)
+		val = (BPP_ASIC_1V8 << BPP_TUNED18_SHIFT_8411) | BPP_PAD_1V8;
+	else
+		return -EINVAL;
+
+	return rtsx_pci_write_register(pcr, LDO_CTL, mask, val);
+}
+
 static unsigned int rtl8411_cd_deglitch(struct rtsx_pcr *pcr)
 {
 	unsigned int card_exist;
@@ -163,6 +178,18 @@
 	return card_exist;
 }
 
+static int rtl8411_conv_clk_and_div_n(int input, int dir)
+{
+	int output;
+
+	if (dir == CLK_TO_DIV_N)
+		output = input * 4 / 5 - 2;
+	else
+		output = (input + 2) * 5 / 4;
+
+	return output;
+}
+
 static const struct pcr_ops rtl8411_pcr_ops = {
 	.extra_init_hw = rtl8411_extra_init_hw,
 	.optimize_phy = NULL,
@@ -172,7 +199,9 @@
 	.disable_auto_blink = rtl8411_disable_auto_blink,
 	.card_power_on = rtl8411_card_power_on,
 	.card_power_off = rtl8411_card_power_off,
+	.switch_output_voltage = rtl8411_switch_output_voltage,
 	.cd_deglitch = rtl8411_cd_deglitch,
+	.conv_clk_and_div_n = rtl8411_conv_clk_and_div_n,
 };
 
 /* SD Pull Control Enable:
diff --git a/drivers/mfd/rts5209.c b/drivers/mfd/rts5209.c
index 283a4f1..98fe0f3 100644
--- a/drivers/mfd/rts5209.c
+++ b/drivers/mfd/rts5209.c
@@ -144,6 +144,25 @@
 	return rtsx_pci_send_cmd(pcr, 100);
 }
 
+static int rts5209_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+	int err;
+
+	if (voltage == OUTPUT_3V3) {
+		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
+		if (err < 0)
+			return err;
+	} else if (voltage == OUTPUT_1V8) {
+		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
+		if (err < 0)
+			return err;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static const struct pcr_ops rts5209_pcr_ops = {
 	.extra_init_hw = rts5209_extra_init_hw,
 	.optimize_phy = rts5209_optimize_phy,
@@ -153,7 +172,9 @@
 	.disable_auto_blink = rts5209_disable_auto_blink,
 	.card_power_on = rts5209_card_power_on,
 	.card_power_off = rts5209_card_power_off,
+	.switch_output_voltage = rts5209_switch_output_voltage,
 	.cd_deglitch = NULL,
+	.conv_clk_and_div_n = NULL,
 };
 
 /* SD Pull Control Enable:
diff --git a/drivers/mfd/rts5229.c b/drivers/mfd/rts5229.c
index b9dbab2..29d889c 100644
--- a/drivers/mfd/rts5229.c
+++ b/drivers/mfd/rts5229.c
@@ -114,6 +114,25 @@
 	return rtsx_pci_send_cmd(pcr, 100);
 }
 
+static int rts5229_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+	int err;
+
+	if (voltage == OUTPUT_3V3) {
+		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
+		if (err < 0)
+			return err;
+	} else if (voltage == OUTPUT_1V8) {
+		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
+		if (err < 0)
+			return err;
+	} else {
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
 static const struct pcr_ops rts5229_pcr_ops = {
 	.extra_init_hw = rts5229_extra_init_hw,
 	.optimize_phy = rts5229_optimize_phy,
@@ -123,7 +142,9 @@
 	.disable_auto_blink = rts5229_disable_auto_blink,
 	.card_power_on = rts5229_card_power_on,
 	.card_power_off = rts5229_card_power_off,
+	.switch_output_voltage = rts5229_switch_output_voltage,
 	.cd_deglitch = NULL,
+	.conv_clk_and_div_n = NULL,
 };
 
 /* SD Pull Control Enable:
diff --git a/drivers/mfd/rtsx_pcr.c b/drivers/mfd/rtsx_pcr.c
index 7a7b0bd..9fc5700 100644
--- a/drivers/mfd/rtsx_pcr.c
+++ b/drivers/mfd/rtsx_pcr.c
@@ -630,7 +630,10 @@
 	if (clk == pcr->cur_clock)
 		return 0;
 
-	N = (u8)(clk - 2);
+	if (pcr->ops->conv_clk_and_div_n)
+		N = (u8)pcr->ops->conv_clk_and_div_n(clk, CLK_TO_DIV_N);
+	else
+		N = (u8)(clk - 2);
 	if ((clk <= 2) || (N > max_N))
 		return -EINVAL;
 
@@ -641,7 +644,14 @@
 	/* Make sure that the SSC clock div_n is equal or greater than min_N */
 	div = CLK_DIV_1;
 	while ((N < min_N) && (div < max_div)) {
-		N = (N + 2) * 2 - 2;
+		if (pcr->ops->conv_clk_and_div_n) {
+			int dbl_clk = pcr->ops->conv_clk_and_div_n(N,
+					DIV_N_TO_CLK) * 2;
+			N = (u8)pcr->ops->conv_clk_and_div_n(dbl_clk,
+					CLK_TO_DIV_N);
+		} else {
+			N = (N + 2) * 2 - 2;
+		}
 		div++;
 	}
 	dev_dbg(&(pcr->pci->dev), "N = %d, div = %d\n", N, div);
@@ -703,6 +713,15 @@
 }
 EXPORT_SYMBOL_GPL(rtsx_pci_card_power_off);
 
+int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage)
+{
+	if (pcr->ops->switch_output_voltage)
+		return pcr->ops->switch_output_voltage(pcr, voltage);
+
+	return 0;
+}
+EXPORT_SYMBOL_GPL(rtsx_pci_switch_output_voltage);
+
 unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr)
 {
 	unsigned int val;
@@ -767,10 +786,10 @@
 
 	spin_unlock_irqrestore(&pcr->lock, flags);
 
-	if (card_detect & SD_EXIST)
+	if ((card_detect & SD_EXIST) && pcr->slots[RTSX_SD_CARD].card_event)
 		pcr->slots[RTSX_SD_CARD].card_event(
 				pcr->slots[RTSX_SD_CARD].p_dev);
-	if (card_detect & MS_EXIST)
+	if ((card_detect & MS_EXIST) && pcr->slots[RTSX_MS_CARD].card_event)
 		pcr->slots[RTSX_MS_CARD].card_event(
 				pcr->slots[RTSX_MS_CARD].p_dev);
 }
diff --git a/drivers/mfd/tc3589x.c b/drivers/mfd/tc3589x.c
index a06d66b..ecc092c 100644
--- a/drivers/mfd/tc3589x.c
+++ b/drivers/mfd/tc3589x.c
@@ -219,25 +219,18 @@
 }
 
 static struct irq_domain_ops tc3589x_irq_ops = {
-        .map    = tc3589x_irq_map,
+	.map    = tc3589x_irq_map,
 	.unmap  = tc3589x_irq_unmap,
-        .xlate  = irq_domain_xlate_twocell,
+	.xlate  = irq_domain_xlate_twocell,
 };
 
 static int tc3589x_irq_init(struct tc3589x *tc3589x, struct device_node *np)
 {
 	int base = tc3589x->irq_base;
 
-	if (base) {
-		tc3589x->domain = irq_domain_add_legacy(
-			NULL, TC3589x_NR_INTERNAL_IRQS, base,
-			0, &tc3589x_irq_ops, tc3589x);
-	}
-	else {
-		tc3589x->domain = irq_domain_add_linear(
-			np, TC3589x_NR_INTERNAL_IRQS,
-			&tc3589x_irq_ops, tc3589x);
-	}
+	tc3589x->domain = irq_domain_add_simple(
+		np, TC3589x_NR_INTERNAL_IRQS, base,
+		&tc3589x_irq_ops, tc3589x);
 
 	if (!tc3589x->domain) {
 		dev_err(tc3589x->dev, "Failed to create irqdomain\n");
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index 4dae241..dd362c1 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -159,7 +159,7 @@
 static int twl4030_write_script(u8 address, struct twl4030_ins *script,
 				       int len)
 {
-	int err;
+	int err = -EINVAL;
 
 	for (; len; len--, address++, script++) {
 		if (len == 1) {
diff --git a/drivers/mfd/vexpress-config.c b/drivers/mfd/vexpress-config.c
index fae15d8..3c1723aa 100644
--- a/drivers/mfd/vexpress-config.c
+++ b/drivers/mfd/vexpress-config.c
@@ -67,6 +67,7 @@
 
 	return bridge;
 }
+EXPORT_SYMBOL(vexpress_config_bridge_register);
 
 void vexpress_config_bridge_unregister(struct vexpress_config_bridge *bridge)
 {
@@ -83,6 +84,7 @@
 	while (!list_empty(&__bridge.transactions))
 		cpu_relax();
 }
+EXPORT_SYMBOL(vexpress_config_bridge_unregister);
 
 
 struct vexpress_config_func {
@@ -142,6 +144,7 @@
 
 	return func;
 }
+EXPORT_SYMBOL(__vexpress_config_func_get);
 
 void vexpress_config_func_put(struct vexpress_config_func *func)
 {
@@ -149,7 +152,7 @@
 	of_node_put(func->bridge->node);
 	kfree(func);
 }
-
+EXPORT_SYMBOL(vexpress_config_func_put);
 
 struct vexpress_config_trans {
 	struct vexpress_config_func *func;
@@ -229,6 +232,7 @@
 
 	complete(&trans->completion);
 }
+EXPORT_SYMBOL(vexpress_config_complete);
 
 int vexpress_config_wait(struct vexpress_config_trans *trans)
 {
@@ -236,7 +240,7 @@
 
 	return trans->status;
 }
-
+EXPORT_SYMBOL(vexpress_config_wait);
 
 int vexpress_config_read(struct vexpress_config_func *func, int offset,
 		u32 *data)
diff --git a/drivers/mfd/vexpress-sysreg.c b/drivers/mfd/vexpress-sysreg.c
index e5d8f63..77048b1 100644
--- a/drivers/mfd/vexpress-sysreg.c
+++ b/drivers/mfd/vexpress-sysreg.c
@@ -313,19 +313,11 @@
 }
 
 
-void __init vexpress_sysreg_early_init(void __iomem *base)
+void __init vexpress_sysreg_setup(struct device_node *node)
 {
-	struct device_node *node = of_find_compatible_node(NULL, NULL,
-			"arm,vexpress-sysreg");
-
-	if (node)
-		base = of_iomap(node, 0);
-
-	if (WARN_ON(!base))
+	if (WARN_ON(!vexpress_sysreg_base))
 		return;
 
-	vexpress_sysreg_base = base;
-
 	if (readl(vexpress_sysreg_base + SYS_MISC) & SYS_MISC_MASTERSITE)
 		vexpress_master_site = VEXPRESS_SITE_DB2;
 	else
@@ -336,9 +328,23 @@
 	WARN_ON(!vexpress_sysreg_config_bridge);
 }
 
+void __init vexpress_sysreg_early_init(void __iomem *base)
+{
+	vexpress_sysreg_base = base;
+	vexpress_sysreg_setup(NULL);
+}
+
 void __init vexpress_sysreg_of_early_init(void)
 {
-	vexpress_sysreg_early_init(NULL);
+	struct device_node *node = of_find_compatible_node(NULL, NULL,
+			"arm,vexpress-sysreg");
+
+	if (node) {
+		vexpress_sysreg_base = of_iomap(node, 0);
+		vexpress_sysreg_setup(node);
+	} else {
+		pr_info("vexpress-sysreg: No Device Tree node found.");
+	}
 }
 
 
@@ -426,9 +432,11 @@
 		return -EBUSY;
 	}
 
-	if (!vexpress_sysreg_base)
+	if (!vexpress_sysreg_base) {
 		vexpress_sysreg_base = devm_ioremap(&pdev->dev, res->start,
 				resource_size(res));
+		vexpress_sysreg_setup(pdev->dev.of_node);
+	}
 
 	if (!vexpress_sysreg_base) {
 		dev_err(&pdev->dev, "Failed to obtain base address!\n");
diff --git a/drivers/mfd/wm5102-tables.c b/drivers/mfd/wm5102-tables.c
index 088872a..1133a64 100644
--- a/drivers/mfd/wm5102-tables.c
+++ b/drivers/mfd/wm5102-tables.c
@@ -1882,7 +1882,7 @@
 	}
 }
 
-#define WM5102_MAX_REGISTER 0x1a8fff
+#define WM5102_MAX_REGISTER 0x1a9800
 
 const struct regmap_config wm5102_spi_regmap = {
 	.reg_bits = 32,
diff --git a/drivers/misc/atmel-ssc.c b/drivers/misc/atmel-ssc.c
index 158da5a..3c09cbb 100644
--- a/drivers/misc/atmel-ssc.c
+++ b/drivers/misc/atmel-ssc.c
@@ -19,6 +19,7 @@
 #include <linux/module.h>
 
 #include <linux/of.h>
+#include <linux/pinctrl/consumer.h>
 
 /* Serialize access to ssc_list and user count */
 static DEFINE_SPINLOCK(user_lock);
@@ -131,6 +132,13 @@
 	struct resource *regs;
 	struct ssc_device *ssc;
 	const struct atmel_ssc_platform_data *plat_dat;
+	struct pinctrl *pinctrl;
+
+	pinctrl = devm_pinctrl_get_select_default(&pdev->dev);
+	if (IS_ERR(pinctrl)) {
+		dev_err(&pdev->dev, "Failed to request pinctrl\n");
+		return PTR_ERR(pinctrl);
+	}
 
 	ssc = devm_kzalloc(&pdev->dev, sizeof(struct ssc_device), GFP_KERNEL);
 	if (!ssc) {
diff --git a/drivers/misc/mei/amthif.c b/drivers/misc/mei/amthif.c
index 18794ae..e40ffd9 100644
--- a/drivers/misc/mei/amthif.c
+++ b/drivers/misc/mei/amthif.c
@@ -187,13 +187,13 @@
 		wait_ret = wait_event_interruptible(dev->iamthif_cl.wait,
 			(cb = mei_amthif_find_read_list_entry(dev, file)));
 
+		/* Locking again the Mutex */
+		mutex_lock(&dev->device_lock);
+
 		if (wait_ret)
 			return -ERESTARTSYS;
 
 		dev_dbg(&dev->pdev->dev, "woke up from sleep\n");
-
-		/* Locking again the Mutex */
-		mutex_lock(&dev->device_lock);
 	}
 
 
diff --git a/drivers/misc/ti-st/st_kim.c b/drivers/misc/ti-st/st_kim.c
index 9ff942a..83269f1 100644
--- a/drivers/misc/ti-st/st_kim.c
+++ b/drivers/misc/ti-st/st_kim.c
@@ -468,6 +468,11 @@
 		if (pdata->chip_enable)
 			pdata->chip_enable(kim_gdata);
 
+		/* Configure BT nShutdown to HIGH state */
+		gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+		mdelay(5);	/* FIXME: a proper toggle */
+		gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
+		mdelay(100);
 		/* re-initialize the completion */
 		INIT_COMPLETION(kim_gdata->ldisc_installed);
 		/* send notification to UIM */
@@ -509,7 +514,8 @@
  *	(b) upon failure to either install ldisc or download firmware.
  *	The function is responsible to (a) notify UIM about un-installation,
  *	(b) flush UART if the ldisc was installed.
- *	(c) invoke platform's chip disabling routine.
+ *	(c) reset BT_EN - pull down nshutdown at the end.
+ *	(d) invoke platform's chip disabling routine.
  */
 long st_kim_stop(void *kim_data)
 {
@@ -541,6 +547,13 @@
 		err = -ETIMEDOUT;
 	}
 
+	/* By default configure BT nShutdown to LOW state */
+	gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+	mdelay(1);
+	gpio_set_value(kim_gdata->nshutdown, GPIO_HIGH);
+	mdelay(1);
+	gpio_set_value(kim_gdata->nshutdown, GPIO_LOW);
+
 	/* platform specific disable */
 	if (pdata->chip_disable)
 		pdata->chip_disable(kim_gdata);
@@ -733,6 +746,20 @@
 	/* refer to itself */
 	kim_gdata->core_data->kim_data = kim_gdata;
 
+	/* Claim the chip enable nShutdown gpio from the system */
+	kim_gdata->nshutdown = pdata->nshutdown_gpio;
+	err = gpio_request(kim_gdata->nshutdown, "kim");
+	if (unlikely(err)) {
+		pr_err(" gpio %ld request failed ", kim_gdata->nshutdown);
+		return err;
+	}
+
+	/* Configure nShutdown GPIO as output=0 */
+	err = gpio_direction_output(kim_gdata->nshutdown, 0);
+	if (unlikely(err)) {
+		pr_err(" unable to configure gpio %ld", kim_gdata->nshutdown);
+		return err;
+	}
 	/* get reference of pdev for request_firmware
 	 */
 	kim_gdata->kim_pdev = pdev;
@@ -779,10 +806,18 @@
 
 static int kim_remove(struct platform_device *pdev)
 {
+	/* free the GPIOs requested */
+	struct ti_st_plat_data	*pdata = pdev->dev.platform_data;
 	struct kim_data_s	*kim_gdata;
 
 	kim_gdata = dev_get_drvdata(&pdev->dev);
 
+	/* Free the Bluetooth/FM/GPIO
+	 * nShutdown gpio from the system
+	 */
+	gpio_free(pdata->nshutdown_gpio);
+	pr_info("nshutdown GPIO Freed");
+
 	debugfs_remove_recursive(kim_debugfs_dir);
 	sysfs_remove_group(&pdev->dev.kobj, &uim_attr_grp);
 	pr_info("sysfs entries removed");
diff --git a/drivers/mmc/host/mvsdio.c b/drivers/mmc/host/mvsdio.c
index de4c20b..f8dd361 100644
--- a/drivers/mmc/host/mvsdio.c
+++ b/drivers/mmc/host/mvsdio.c
@@ -50,8 +50,6 @@
 	struct timer_list timer;
 	struct mmc_host *mmc;
 	struct device *dev;
-	struct resource *res;
-	int irq;
 	struct clk *clk;
 	int gpio_card_detect;
 	int gpio_write_protect;
@@ -718,10 +716,6 @@
 	if (!r || irq < 0 || !mvsd_data)
 		return -ENXIO;
 
-	r = request_mem_region(r->start, SZ_1K, DRIVER_NAME);
-	if (!r)
-		return -EBUSY;
-
 	mmc = mmc_alloc_host(sizeof(struct mvsd_host), &pdev->dev);
 	if (!mmc) {
 		ret = -ENOMEM;
@@ -731,8 +725,8 @@
 	host = mmc_priv(mmc);
 	host->mmc = mmc;
 	host->dev = &pdev->dev;
-	host->res = r;
 	host->base_clock = mvsd_data->clock / 2;
+	host->clk = ERR_PTR(-EINVAL);
 
 	mmc->ops = &mvsd_ops;
 
@@ -752,7 +746,7 @@
 
 	spin_lock_init(&host->lock);
 
-	host->base = ioremap(r->start, SZ_4K);
+	host->base = devm_request_and_ioremap(&pdev->dev, r);
 	if (!host->base) {
 		ret = -ENOMEM;
 		goto out;
@@ -765,44 +759,45 @@
 
 	mvsd_power_down(host);
 
-	ret = request_irq(irq, mvsd_irq, 0, DRIVER_NAME, host);
+	ret = devm_request_irq(&pdev->dev, irq, mvsd_irq, 0, DRIVER_NAME, host);
 	if (ret) {
 		pr_err("%s: cannot assign irq %d\n", DRIVER_NAME, irq);
 		goto out;
-	} else
-		host->irq = irq;
+	}
 
 	/* Not all platforms can gate the clock, so it is not
 	   an error if the clock does not exists. */
-	host->clk = clk_get(&pdev->dev, NULL);
-	if (!IS_ERR(host->clk)) {
+	host->clk = devm_clk_get(&pdev->dev, NULL);
+	if (!IS_ERR(host->clk))
 		clk_prepare_enable(host->clk);
-	}
 
 	if (mvsd_data->gpio_card_detect) {
-		ret = gpio_request(mvsd_data->gpio_card_detect,
-				   DRIVER_NAME " cd");
+		ret = devm_gpio_request_one(&pdev->dev,
+					    mvsd_data->gpio_card_detect,
+					    GPIOF_IN, DRIVER_NAME " cd");
 		if (ret == 0) {
-			gpio_direction_input(mvsd_data->gpio_card_detect);
 			irq = gpio_to_irq(mvsd_data->gpio_card_detect);
-			ret = request_irq(irq, mvsd_card_detect_irq,
-					  IRQ_TYPE_EDGE_RISING | IRQ_TYPE_EDGE_FALLING,
-					  DRIVER_NAME " cd", host);
+			ret = devm_request_irq(&pdev->dev, irq,
+					       mvsd_card_detect_irq,
+					       IRQ_TYPE_EDGE_RISING |
+					       IRQ_TYPE_EDGE_FALLING,
+					       DRIVER_NAME " cd", host);
 			if (ret == 0)
 				host->gpio_card_detect =
 					mvsd_data->gpio_card_detect;
 			else
-				gpio_free(mvsd_data->gpio_card_detect);
+				devm_gpio_free(&pdev->dev,
+					       mvsd_data->gpio_card_detect);
 		}
 	}
 	if (!host->gpio_card_detect)
 		mmc->caps |= MMC_CAP_NEEDS_POLL;
 
 	if (mvsd_data->gpio_write_protect) {
-		ret = gpio_request(mvsd_data->gpio_write_protect,
-				   DRIVER_NAME " wp");
+		ret = devm_gpio_request_one(&pdev->dev,
+					    mvsd_data->gpio_write_protect,
+					    GPIOF_IN, DRIVER_NAME " wp");
 		if (ret == 0) {
-			gpio_direction_input(mvsd_data->gpio_write_protect);
 			host->gpio_write_protect =
 				mvsd_data->gpio_write_protect;
 		}
@@ -824,26 +819,11 @@
 	return 0;
 
 out:
-	if (host) {
-		if (host->irq)
-			free_irq(host->irq, host);
-		if (host->gpio_card_detect) {
-			free_irq(gpio_to_irq(host->gpio_card_detect), host);
-			gpio_free(host->gpio_card_detect);
-		}
-		if (host->gpio_write_protect)
-			gpio_free(host->gpio_write_protect);
-		if (host->base)
-			iounmap(host->base);
-	}
-	if (r)
-		release_resource(r);
-	if (mmc)
-		if (!IS_ERR_OR_NULL(host->clk)) {
+	if (mmc) {
+		if (!IS_ERR(host->clk))
 			clk_disable_unprepare(host->clk);
-			clk_put(host->clk);
-		}
 		mmc_free_host(mmc);
+	}
 
 	return ret;
 }
@@ -852,28 +832,16 @@
 {
 	struct mmc_host *mmc = platform_get_drvdata(pdev);
 
-	if (mmc) {
-		struct mvsd_host *host = mmc_priv(mmc);
+	struct mvsd_host *host = mmc_priv(mmc);
 
-		if (host->gpio_card_detect) {
-			free_irq(gpio_to_irq(host->gpio_card_detect), host);
-			gpio_free(host->gpio_card_detect);
-		}
-		mmc_remove_host(mmc);
-		free_irq(host->irq, host);
-		if (host->gpio_write_protect)
-			gpio_free(host->gpio_write_protect);
-		del_timer_sync(&host->timer);
-		mvsd_power_down(host);
-		iounmap(host->base);
-		release_resource(host->res);
+	mmc_remove_host(mmc);
+	del_timer_sync(&host->timer);
+	mvsd_power_down(host);
 
-		if (!IS_ERR(host->clk)) {
-			clk_disable_unprepare(host->clk);
-			clk_put(host->clk);
-		}
-		mmc_free_host(mmc);
-	}
+	if (!IS_ERR(host->clk))
+		clk_disable_unprepare(host->clk);
+	mmc_free_host(mmc);
+
 	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
diff --git a/drivers/mmc/host/rtsx_pci_sdmmc.c b/drivers/mmc/host/rtsx_pci_sdmmc.c
index 571915d..f74b5ad 100644
--- a/drivers/mmc/host/rtsx_pci_sdmmc.c
+++ b/drivers/mmc/host/rtsx_pci_sdmmc.c
@@ -1060,26 +1060,6 @@
 	return 0;
 }
 
-static int sd_change_bank_voltage(struct realtek_pci_sdmmc *host, u8 voltage)
-{
-	struct rtsx_pcr *pcr = host->pcr;
-	int err;
-
-	if (voltage == SD_IO_3V3) {
-		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4FC0 | 0x24);
-		if (err < 0)
-			return err;
-	} else if (voltage == SD_IO_1V8) {
-		err = rtsx_pci_write_phy_register(pcr, 0x08, 0x4C40 | 0x24);
-		if (err < 0)
-			return err;
-	} else {
-		return -EINVAL;
-	}
-
-	return 0;
-}
-
 static int sdmmc_switch_voltage(struct mmc_host *mmc, struct mmc_ios *ios)
 {
 	struct realtek_pci_sdmmc *host = mmc_priv(mmc);
@@ -1098,11 +1078,11 @@
 	rtsx_pci_start_run(pcr);
 
 	if (ios->signal_voltage == MMC_SIGNAL_VOLTAGE_330)
-		voltage = SD_IO_3V3;
+		voltage = OUTPUT_3V3;
 	else
-		voltage = SD_IO_1V8;
+		voltage = OUTPUT_1V8;
 
-	if (voltage == SD_IO_1V8) {
+	if (voltage == OUTPUT_1V8) {
 		err = rtsx_pci_write_register(pcr,
 				SD30_DRIVE_SEL, 0x07, DRIVER_TYPE_B);
 		if (err < 0)
@@ -1113,11 +1093,11 @@
 			goto out;
 	}
 
-	err = sd_change_bank_voltage(host, voltage);
+	err = rtsx_pci_switch_output_voltage(pcr, voltage);
 	if (err < 0)
 		goto out;
 
-	if (voltage == SD_IO_1V8) {
+	if (voltage == OUTPUT_1V8) {
 		err = sd_wait_voltage_stable_2(host);
 		if (err < 0)
 			goto out;
diff --git a/drivers/net/can/c_can/c_can.c b/drivers/net/can/c_can/c_can.c
index 5233b8f..58607f1 100644
--- a/drivers/net/can/c_can/c_can.c
+++ b/drivers/net/can/c_can/c_can.c
@@ -960,7 +960,7 @@
 		break;
 	case LEC_ACK_ERROR:
 		netdev_dbg(dev, "ack error\n");
-		cf->data[2] |= (CAN_ERR_PROT_LOC_ACK |
+		cf->data[3] |= (CAN_ERR_PROT_LOC_ACK |
 				CAN_ERR_PROT_LOC_ACK_DEL);
 		break;
 	case LEC_BIT1_ERROR:
@@ -973,7 +973,7 @@
 		break;
 	case LEC_CRC_ERROR:
 		netdev_dbg(dev, "CRC error\n");
-		cf->data[2] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
+		cf->data[3] |= (CAN_ERR_PROT_LOC_CRC_SEQ |
 				CAN_ERR_PROT_LOC_CRC_DEL);
 		break;
 	default:
diff --git a/drivers/net/can/pch_can.c b/drivers/net/can/pch_can.c
index 7d17485..5c314a9 100644
--- a/drivers/net/can/pch_can.c
+++ b/drivers/net/can/pch_can.c
@@ -560,7 +560,7 @@
 		stats->rx_errors++;
 		break;
 	case PCH_CRC_ERR:
-		cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ |
+		cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ |
 			       CAN_ERR_PROT_LOC_CRC_DEL;
 		priv->can.can_stats.bus_error++;
 		stats->rx_errors++;
diff --git a/drivers/net/can/ti_hecc.c b/drivers/net/can/ti_hecc.c
index f898c63..300581b 100644
--- a/drivers/net/can/ti_hecc.c
+++ b/drivers/net/can/ti_hecc.c
@@ -746,12 +746,12 @@
 		}
 		if (err_status & HECC_CANES_CRCE) {
 			hecc_set_bit(priv, HECC_CANES, HECC_CANES_CRCE);
-			cf->data[2] |= CAN_ERR_PROT_LOC_CRC_SEQ |
+			cf->data[3] |= CAN_ERR_PROT_LOC_CRC_SEQ |
 					CAN_ERR_PROT_LOC_CRC_DEL;
 		}
 		if (err_status & HECC_CANES_ACKE) {
 			hecc_set_bit(priv, HECC_CANES, HECC_CANES_ACKE);
-			cf->data[2] |= CAN_ERR_PROT_LOC_ACK |
+			cf->data[3] |= CAN_ERR_PROT_LOC_ACK |
 					CAN_ERR_PROT_LOC_ACK_DEL;
 		}
 	}
diff --git a/drivers/net/ethernet/3com/3c574_cs.c b/drivers/net/ethernet/3com/3c574_cs.c
index 66df936..ffd8de2 100644
--- a/drivers/net/ethernet/3com/3c574_cs.c
+++ b/drivers/net/ethernet/3com/3c574_cs.c
@@ -432,7 +432,7 @@
 	netdev_info(dev, "%s at io %#3lx, irq %d, hw_addr %pM\n",
 		    cardname, dev->base_addr, dev->irq, dev->dev_addr);
 	netdev_info(dev, " %dK FIFO split %s Rx:Tx, %sMII interface.\n",
-		    8 << config & Ram_size,
+		    8 << (config & Ram_size),
 		    ram_split[(config & Ram_split) >> Ram_split_shift],
 		    config & Autoselect ? "autoselect " : "");
 
diff --git a/drivers/net/ethernet/adi/Kconfig b/drivers/net/ethernet/adi/Kconfig
index e49c0ef..a948160 100644
--- a/drivers/net/ethernet/adi/Kconfig
+++ b/drivers/net/ethernet/adi/Kconfig
@@ -61,6 +61,7 @@
 
 config BFIN_MAC_USE_HWSTAMP
 	bool "Use IEEE 1588 hwstamp"
+	depends on BFIN_MAC && BF518
 	select PTP_1588_CLOCK
 	default y
 	---help---
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
index 01588b6..f771ddf 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
@@ -80,12 +80,37 @@
 		new_txdata_index = new_max_eth_txqs + FCOE_TXQ_IDX_OFFSET;
 	}
 
-	memcpy(&bp->bnx2x_txq[old_txdata_index],
-	       &bp->bnx2x_txq[new_txdata_index],
+	memcpy(&bp->bnx2x_txq[new_txdata_index],
+	       &bp->bnx2x_txq[old_txdata_index],
 	       sizeof(struct bnx2x_fp_txdata));
 	to_fp->txdata_ptr[0] = &bp->bnx2x_txq[new_txdata_index];
 }
 
+/**
+ * bnx2x_shrink_eth_fp - guarantees fastpath structures stay intact
+ *
+ * @bp:	driver handle
+ * @delta:	number of eth queues which were not allocated
+ */
+static void bnx2x_shrink_eth_fp(struct bnx2x *bp, int delta)
+{
+	int i, cos, old_eth_num = BNX2X_NUM_ETH_QUEUES(bp);
+
+	/* Queue pointer cannot be re-set on an fp-basis, as moving pointer
+	 * backward along the array could cause memory to be overriden
+	 */
+	for (cos = 1; cos < bp->max_cos; cos++) {
+		for (i = 0; i < old_eth_num - delta; i++) {
+			struct bnx2x_fastpath *fp = &bp->fp[i];
+			int new_idx = cos * (old_eth_num - delta) + i;
+
+			memcpy(&bp->bnx2x_txq[new_idx], fp->txdata_ptr[cos],
+			       sizeof(struct bnx2x_fp_txdata));
+			fp->txdata_ptr[cos] = &bp->bnx2x_txq[new_idx];
+		}
+	}
+}
+
 int load_count[2][3] = { {0} }; /* per-path: 0-common, 1-port0, 2-port1 */
 
 /* free skb in the packet ring at pos idx
@@ -3863,6 +3888,7 @@
 		int delta = BNX2X_NUM_ETH_QUEUES(bp) - i;
 
 		WARN_ON(delta < 0);
+		bnx2x_shrink_eth_fp(bp, delta);
 		if (CNIC_SUPPORT(bp))
 			/* move non eth FPs next to last eth FP
 			 * must be done in that order
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
index 277f17e..a427b49 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
@@ -2777,10 +2777,10 @@
 		} else if ((info->flow_type == UDP_V6_FLOW) &&
 			   (bp->rss_conf_obj.udp_rss_v6 != udp_rss_requested)) {
 			bp->rss_conf_obj.udp_rss_v6 = udp_rss_requested;
-			return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);
 			DP(BNX2X_MSG_ETHTOOL,
 			   "rss re-configured, UDP 4-tupple %s\n",
 			   udp_rss_requested ? "enabled" : "disabled");
+			return bnx2x_config_rss_pf(bp, &bp->rss_conf_obj, 0);
 		} else {
 			return 0;
 		}
diff --git a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
index 940ef85..5523da3 100644
--- a/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
+++ b/drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
@@ -127,6 +127,17 @@
 
 struct workqueue_struct *bnx2x_wq;
 
+struct bnx2x_mac_vals {
+	u32 xmac_addr;
+	u32 xmac_val;
+	u32 emac_addr;
+	u32 emac_val;
+	u32 umac_addr;
+	u32 umac_val;
+	u32 bmac_addr;
+	u32 bmac_val[2];
+};
+
 enum bnx2x_board_type {
 	BCM57710 = 0,
 	BCM57711,
@@ -9420,12 +9431,19 @@
 		bnx2x_undi_int_disable_e1h(bp);
 }
 
-static void bnx2x_prev_unload_close_mac(struct bnx2x *bp)
+static void bnx2x_prev_unload_close_mac(struct bnx2x *bp,
+					struct bnx2x_mac_vals *vals)
 {
 	u32 val, base_addr, offset, mask, reset_reg;
 	bool mac_stopped = false;
 	u8 port = BP_PORT(bp);
 
+	/* reset addresses as they also mark which values were changed */
+	vals->bmac_addr = 0;
+	vals->umac_addr = 0;
+	vals->xmac_addr = 0;
+	vals->emac_addr = 0;
+
 	reset_reg = REG_RD(bp, MISC_REG_RESET_REG_2);
 
 	if (!CHIP_IS_E3(bp)) {
@@ -9447,14 +9465,18 @@
 			 */
 			wb_data[0] = REG_RD(bp, base_addr + offset);
 			wb_data[1] = REG_RD(bp, base_addr + offset + 0x4);
+			vals->bmac_addr = base_addr + offset;
+			vals->bmac_val[0] = wb_data[0];
+			vals->bmac_val[1] = wb_data[1];
 			wb_data[0] &= ~BMAC_CONTROL_RX_ENABLE;
-			REG_WR(bp, base_addr + offset, wb_data[0]);
-			REG_WR(bp, base_addr + offset + 0x4, wb_data[1]);
+			REG_WR(bp, vals->bmac_addr, wb_data[0]);
+			REG_WR(bp, vals->bmac_addr + 0x4, wb_data[1]);
 
 		}
 		BNX2X_DEV_INFO("Disable emac Rx\n");
-		REG_WR(bp, NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4, 0);
-
+		vals->emac_addr = NIG_REG_NIG_EMAC0_EN + BP_PORT(bp)*4;
+		vals->emac_val = REG_RD(bp, vals->emac_addr);
+		REG_WR(bp, vals->emac_addr, 0);
 		mac_stopped = true;
 	} else {
 		if (reset_reg & MISC_REGISTERS_RESET_REG_2_XMAC) {
@@ -9465,14 +9487,18 @@
 			       val & ~(1 << 1));
 			REG_WR(bp, base_addr + XMAC_REG_PFC_CTRL_HI,
 			       val | (1 << 1));
-			REG_WR(bp, base_addr + XMAC_REG_CTRL, 0);
+			vals->xmac_addr = base_addr + XMAC_REG_CTRL;
+			vals->xmac_val = REG_RD(bp, vals->xmac_addr);
+			REG_WR(bp, vals->xmac_addr, 0);
 			mac_stopped = true;
 		}
 		mask = MISC_REGISTERS_RESET_REG_2_UMAC0 << port;
 		if (mask & reset_reg) {
 			BNX2X_DEV_INFO("Disable umac Rx\n");
 			base_addr = BP_PORT(bp) ? GRCBASE_UMAC1 : GRCBASE_UMAC0;
-			REG_WR(bp, base_addr + UMAC_REG_COMMAND_CONFIG, 0);
+			vals->umac_addr = base_addr + UMAC_REG_COMMAND_CONFIG;
+			vals->umac_val = REG_RD(bp, vals->umac_addr);
+			REG_WR(bp, vals->umac_addr, 0);
 			mac_stopped = true;
 		}
 	}
@@ -9664,12 +9690,16 @@
 {
 	u32 reset_reg, tmp_reg = 0, rc;
 	bool prev_undi = false;
+	struct bnx2x_mac_vals mac_vals;
+
 	/* It is possible a previous function received 'common' answer,
 	 * but hasn't loaded yet, therefore creating a scenario of
 	 * multiple functions receiving 'common' on the same path.
 	 */
 	BNX2X_DEV_INFO("Common unload Flow\n");
 
+	memset(&mac_vals, 0, sizeof(mac_vals));
+
 	if (bnx2x_prev_is_path_marked(bp))
 		return bnx2x_prev_mcp_done(bp);
 
@@ -9680,7 +9710,10 @@
 		u32 timer_count = 1000;
 
 		/* Close the MAC Rx to prevent BRB from filling up */
-		bnx2x_prev_unload_close_mac(bp);
+		bnx2x_prev_unload_close_mac(bp, &mac_vals);
+
+		/* close LLH filters towards the BRB */
+		bnx2x_set_rx_filter(&bp->link_params, 0);
 
 		/* Check if the UNDI driver was previously loaded
 		 * UNDI driver initializes CID offset for normal bell to 0x7
@@ -9727,6 +9760,17 @@
 	/* No packets are in the pipeline, path is ready for reset */
 	bnx2x_reset_common(bp);
 
+	if (mac_vals.xmac_addr)
+		REG_WR(bp, mac_vals.xmac_addr, mac_vals.xmac_val);
+	if (mac_vals.umac_addr)
+		REG_WR(bp, mac_vals.umac_addr, mac_vals.umac_val);
+	if (mac_vals.emac_addr)
+		REG_WR(bp, mac_vals.emac_addr, mac_vals.emac_val);
+	if (mac_vals.bmac_addr) {
+		REG_WR(bp, mac_vals.bmac_addr, mac_vals.bmac_val[0]);
+		REG_WR(bp, mac_vals.bmac_addr + 4, mac_vals.bmac_val[1]);
+	}
+
 	rc = bnx2x_prev_mark_path(bp, prev_undi);
 	if (rc) {
 		bnx2x_prev_mcp_done(bp);
diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c
index 78ea90c..bdb0869 100644
--- a/drivers/net/ethernet/broadcom/tg3.c
+++ b/drivers/net/ethernet/broadcom/tg3.c
@@ -1283,14 +1283,26 @@
 	return tg3_writephy(tp, MII_TG3_AUX_CTRL, set | reg);
 }
 
-#define TG3_PHY_AUXCTL_SMDSP_ENABLE(tp) \
-	tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
-			     MII_TG3_AUXCTL_ACTL_SMDSP_ENA | \
-			     MII_TG3_AUXCTL_ACTL_TX_6DB)
+static int tg3_phy_toggle_auxctl_smdsp(struct tg3 *tp, bool enable)
+{
+	u32 val;
+	int err;
 
-#define TG3_PHY_AUXCTL_SMDSP_DISABLE(tp) \
-	tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL, \
-			     MII_TG3_AUXCTL_ACTL_TX_6DB);
+	err = tg3_phy_auxctl_read(tp, MII_TG3_AUXCTL_SHDWSEL_AUXCTL, &val);
+
+	if (err)
+		return err;
+	if (enable)
+
+		val |= MII_TG3_AUXCTL_ACTL_SMDSP_ENA;
+	else
+		val &= ~MII_TG3_AUXCTL_ACTL_SMDSP_ENA;
+
+	err = tg3_phy_auxctl_write((tp), MII_TG3_AUXCTL_SHDWSEL_AUXCTL,
+				   val | MII_TG3_AUXCTL_ACTL_TX_6DB);
+
+	return err;
+}
 
 static int tg3_bmcr_reset(struct tg3 *tp)
 {
@@ -2223,7 +2235,7 @@
 
 	otp = tp->phy_otp;
 
-	if (TG3_PHY_AUXCTL_SMDSP_ENABLE(tp))
+	if (tg3_phy_toggle_auxctl_smdsp(tp, true))
 		return;
 
 	phy = ((otp & TG3_OTP_AGCTGT_MASK) >> TG3_OTP_AGCTGT_SHIFT);
@@ -2248,7 +2260,7 @@
 	      ((otp & TG3_OTP_RCOFF_MASK) >> TG3_OTP_RCOFF_SHIFT);
 	tg3_phydsp_write(tp, MII_TG3_DSP_EXP97, phy);
 
-	TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+	tg3_phy_toggle_auxctl_smdsp(tp, false);
 }
 
 static void tg3_phy_eee_adjust(struct tg3 *tp, u32 current_link_up)
@@ -2284,9 +2296,9 @@
 
 	if (!tp->setlpicnt) {
 		if (current_link_up == 1 &&
-		   !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+		   !tg3_phy_toggle_auxctl_smdsp(tp, true)) {
 			tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, 0x0000);
-			TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+			tg3_phy_toggle_auxctl_smdsp(tp, false);
 		}
 
 		val = tr32(TG3_CPMU_EEE_MODE);
@@ -2302,11 +2314,11 @@
 	    (GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5717 ||
 	     GET_ASIC_REV(tp->pci_chip_rev_id) == ASIC_REV_5719 ||
 	     tg3_flag(tp, 57765_CLASS)) &&
-	    !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+	    !tg3_phy_toggle_auxctl_smdsp(tp, true)) {
 		val = MII_TG3_DSP_TAP26_ALNOKO |
 		      MII_TG3_DSP_TAP26_RMRXSTO;
 		tg3_phydsp_write(tp, MII_TG3_DSP_TAP26, val);
-		TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+		tg3_phy_toggle_auxctl_smdsp(tp, false);
 	}
 
 	val = tr32(TG3_CPMU_EEE_MODE);
@@ -2450,7 +2462,7 @@
 		tg3_writephy(tp, MII_CTRL1000,
 			     CTL1000_AS_MASTER | CTL1000_ENABLE_MASTER);
 
-		err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
+		err = tg3_phy_toggle_auxctl_smdsp(tp, true);
 		if (err)
 			return err;
 
@@ -2471,7 +2483,7 @@
 	tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x8200);
 	tg3_writephy(tp, MII_TG3_DSP_CONTROL, 0x0000);
 
-	TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+	tg3_phy_toggle_auxctl_smdsp(tp, false);
 
 	tg3_writephy(tp, MII_CTRL1000, phy9_orig);
 
@@ -2572,10 +2584,10 @@
 
 out:
 	if ((tp->phy_flags & TG3_PHYFLG_ADC_BUG) &&
-	    !TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+	    !tg3_phy_toggle_auxctl_smdsp(tp, true)) {
 		tg3_phydsp_write(tp, 0x201f, 0x2aaa);
 		tg3_phydsp_write(tp, 0x000a, 0x0323);
-		TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+		tg3_phy_toggle_auxctl_smdsp(tp, false);
 	}
 
 	if (tp->phy_flags & TG3_PHYFLG_5704_A0_BUG) {
@@ -2584,14 +2596,14 @@
 	}
 
 	if (tp->phy_flags & TG3_PHYFLG_BER_BUG) {
-		if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+		if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) {
 			tg3_phydsp_write(tp, 0x000a, 0x310b);
 			tg3_phydsp_write(tp, 0x201f, 0x9506);
 			tg3_phydsp_write(tp, 0x401f, 0x14e2);
-			TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+			tg3_phy_toggle_auxctl_smdsp(tp, false);
 		}
 	} else if (tp->phy_flags & TG3_PHYFLG_JITTER_BUG) {
-		if (!TG3_PHY_AUXCTL_SMDSP_ENABLE(tp)) {
+		if (!tg3_phy_toggle_auxctl_smdsp(tp, true)) {
 			tg3_writephy(tp, MII_TG3_DSP_ADDRESS, 0x000a);
 			if (tp->phy_flags & TG3_PHYFLG_ADJUST_TRIM) {
 				tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x110b);
@@ -2600,7 +2612,7 @@
 			} else
 				tg3_writephy(tp, MII_TG3_DSP_RW_PORT, 0x010b);
 
-			TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+			tg3_phy_toggle_auxctl_smdsp(tp, false);
 		}
 	}
 
@@ -4009,7 +4021,7 @@
 	tw32(TG3_CPMU_EEE_MODE,
 	     tr32(TG3_CPMU_EEE_MODE) & ~TG3_CPMU_EEEMD_LPI_ENABLE);
 
-	err = TG3_PHY_AUXCTL_SMDSP_ENABLE(tp);
+	err = tg3_phy_toggle_auxctl_smdsp(tp, true);
 	if (!err) {
 		u32 err2;
 
@@ -4042,7 +4054,7 @@
 						 MII_TG3_DSP_CH34TP2_HIBW01);
 		}
 
-		err2 = TG3_PHY_AUXCTL_SMDSP_DISABLE(tp);
+		err2 = tg3_phy_toggle_auxctl_smdsp(tp, false);
 		if (!err)
 			err = err2;
 	}
@@ -6950,6 +6962,9 @@
 	int i;
 	struct tg3 *tp = netdev_priv(dev);
 
+	if (tg3_irq_sync(tp))
+		return;
+
 	for (i = 0; i < tp->irq_cnt; i++)
 		tg3_interrupt(tp->napi[i].irq_vec, &tp->napi[i]);
 }
@@ -16367,6 +16382,7 @@
 	tp->pm_cap = pm_cap;
 	tp->rx_mode = TG3_DEF_RX_MODE;
 	tp->tx_mode = TG3_DEF_TX_MODE;
+	tp->irq_sync = 1;
 
 	if (tg3_debug > 0)
 		tp->msg_enable = tg3_debug;
diff --git a/drivers/net/ethernet/calxeda/xgmac.c b/drivers/net/ethernet/calxeda/xgmac.c
index b407043..f7f0290 100644
--- a/drivers/net/ethernet/calxeda/xgmac.c
+++ b/drivers/net/ethernet/calxeda/xgmac.c
@@ -548,6 +548,10 @@
 		return -1;
 	}
 
+	/* All frames should fit into a single buffer */
+	if (!(status & RXDESC_FIRST_SEG) || !(status & RXDESC_LAST_SEG))
+		return -1;
+
 	/* Check if packet has checksum already */
 	if ((status & RXDESC_FRAME_TYPE) && (status & RXDESC_EXT_STATUS) &&
 		!(ext_status & RXDESC_IP_PAYLOAD_MASK))
diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
index f0718e1..c306df7 100644
--- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
+++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c
@@ -1994,9 +1994,20 @@
 {
 	const struct port_info *pi = netdev_priv(dev);
 	struct adapter *adap = pi->adapter;
+	struct sge_rspq *q;
+	int i;
+	int r = 0;
 
-	return set_rxq_intr_params(adap, &adap->sge.ethrxq[pi->first_qset].rspq,
-			c->rx_coalesce_usecs, c->rx_max_coalesced_frames);
+	for (i = pi->first_qset; i < pi->first_qset + pi->nqsets; i++) {
+		q = &adap->sge.ethrxq[i].rspq;
+		r = set_rxq_intr_params(adap, q, c->rx_coalesce_usecs,
+			c->rx_max_coalesced_frames);
+		if (r) {
+			dev_err(&dev->dev, "failed to set coalesce %d\n", r);
+			break;
+		}
+	}
+	return r;
 }
 
 static int get_coalesce(struct net_device *dev, struct ethtool_coalesce *c)
diff --git a/drivers/net/ethernet/emulex/benet/be.h b/drivers/net/ethernet/emulex/benet/be.h
index 3bc1912..4eba17b 100644
--- a/drivers/net/ethernet/emulex/benet/be.h
+++ b/drivers/net/ethernet/emulex/benet/be.h
@@ -190,6 +190,7 @@
 
 	u8 idx;			/* array index */
 	u16 tx_budget;
+	u16 spurious_intr;
 	struct napi_struct napi;
 	struct be_adapter *adapter;
 } ____cacheline_aligned_in_smp;
diff --git a/drivers/net/ethernet/emulex/benet/be_main.c b/drivers/net/ethernet/emulex/benet/be_main.c
index 9dca22b..5c99570 100644
--- a/drivers/net/ethernet/emulex/benet/be_main.c
+++ b/drivers/net/ethernet/emulex/benet/be_main.c
@@ -2026,19 +2026,30 @@
 	struct be_adapter *adapter = eqo->adapter;
 	int num_evts = 0;
 
-	/* On Lancer, clear-intr bit of the EQ DB does not work.
-	 * INTx is de-asserted only on notifying num evts.
+	/* IRQ is not expected when NAPI is scheduled as the EQ
+	 * will not be armed.
+	 * But, this can happen on Lancer INTx where it takes
+	 * a while to de-assert INTx or in BE2 where occasionaly
+	 * an interrupt may be raised even when EQ is unarmed.
+	 * If NAPI is already scheduled, then counting & notifying
+	 * events will orphan them.
 	 */
-	if (lancer_chip(adapter))
+	if (napi_schedule_prep(&eqo->napi)) {
 		num_evts = events_get(eqo);
-
-	/* The EQ-notify may not de-assert INTx rightaway, causing
-	 * the ISR to be invoked again. So, return HANDLED even when
-	 * num_evts is zero.
-	 */
+		__napi_schedule(&eqo->napi);
+		if (num_evts)
+			eqo->spurious_intr = 0;
+	}
 	be_eq_notify(adapter, eqo->q.id, false, true, num_evts);
-	napi_schedule(&eqo->napi);
-	return IRQ_HANDLED;
+
+	/* Return IRQ_HANDLED only for the the first spurious intr
+	 * after a valid intr to stop the kernel from branding
+	 * this irq as a bad one!
+	 */
+	if (num_evts || eqo->spurious_intr++ == 0)
+		return IRQ_HANDLED;
+	else
+		return IRQ_NONE;
 }
 
 static irqreturn_t be_msix(int irq, void *dev)
diff --git a/drivers/net/ethernet/intel/ixgbe/Makefile b/drivers/net/ethernet/intel/ixgbe/Makefile
index f3a632b..687c83d 100644
--- a/drivers/net/ethernet/intel/ixgbe/Makefile
+++ b/drivers/net/ethernet/intel/ixgbe/Makefile
@@ -32,7 +32,7 @@
 
 obj-$(CONFIG_IXGBE) += ixgbe.o
 
-ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o ixgbe_debugfs.o\
+ixgbe-objs := ixgbe_main.o ixgbe_common.o ixgbe_ethtool.o \
               ixgbe_82599.o ixgbe_82598.o ixgbe_phy.o ixgbe_sriov.o \
               ixgbe_mbx.o ixgbe_x540.o ixgbe_lib.o ixgbe_ptp.o
 
@@ -40,4 +40,5 @@
                               ixgbe_dcb_82599.o ixgbe_dcb_nl.o
 
 ixgbe-$(CONFIG_IXGBE_HWMON) += ixgbe_sysfs.o
+ixgbe-$(CONFIG_DEBUG_FS) += ixgbe_debugfs.o
 ixgbe-$(CONFIG_FCOE:m=y) += ixgbe_fcoe.o
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
index 50aa546..3504686 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_debugfs.c
@@ -24,9 +24,6 @@
   Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
 
 *******************************************************************************/
-
-#ifdef CONFIG_DEBUG_FS
-
 #include <linux/debugfs.h>
 #include <linux/module.h>
 
@@ -277,5 +274,3 @@
 {
 	debugfs_remove_recursive(ixgbe_dbg_root);
 }
-
-#endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
index 1a751c9..bb9256a 100644
--- a/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
+++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_ptp.c
@@ -660,11 +660,11 @@
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_SYNC:
 		tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
-		tsync_rx_mtrl = IXGBE_RXMTRL_V1_SYNC_MSG;
+		tsync_rx_mtrl |= IXGBE_RXMTRL_V1_SYNC_MSG;
 		break;
 	case HWTSTAMP_FILTER_PTP_V1_L4_DELAY_REQ:
 		tsync_rx_ctl |= IXGBE_TSYNCRXCTL_TYPE_L4_V1;
-		tsync_rx_mtrl = IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
+		tsync_rx_mtrl |= IXGBE_RXMTRL_V1_DELAY_REQ_MSG;
 		break;
 	case HWTSTAMP_FILTER_PTP_V2_EVENT:
 	case HWTSTAMP_FILTER_PTP_V2_L2_EVENT:
diff --git a/drivers/net/ethernet/mellanox/mlx4/en_tx.c b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
index 2b799f4..6771b69 100644
--- a/drivers/net/ethernet/mellanox/mlx4/en_tx.c
+++ b/drivers/net/ethernet/mellanox/mlx4/en_tx.c
@@ -630,10 +630,15 @@
 		ring->tx_csum++;
 	}
 
-	/* Copy dst mac address to wqe */
-	ethh = (struct ethhdr *)skb->data;
-	tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest);
-	tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2));
+	if (mlx4_is_mfunc(mdev->dev) || priv->validate_loopback) {
+		/* Copy dst mac address to wqe. This allows loopback in eSwitch,
+		 * so that VFs and PF can communicate with each other
+		 */
+		ethh = (struct ethhdr *)skb->data;
+		tx_desc->ctrl.srcrb_flags16[0] = get_unaligned((__be16 *)ethh->h_dest);
+		tx_desc->ctrl.imm = get_unaligned((__be32 *)(ethh->h_dest + 2));
+	}
+
 	/* Handle LSO (TSO) packets */
 	if (lso_header_size) {
 		/* Mark opcode as LSO */
diff --git a/drivers/net/ethernet/mellanox/mlx4/main.c b/drivers/net/ethernet/mellanox/mlx4/main.c
index e1bafff..a6542d7 100644
--- a/drivers/net/ethernet/mellanox/mlx4/main.c
+++ b/drivers/net/ethernet/mellanox/mlx4/main.c
@@ -1790,15 +1790,8 @@
 	int i;
 
 	if (msi_x) {
-		/* In multifunction mode each function gets 2 msi-X vectors
-		 * one for data path completions anf the other for asynch events
-		 * or command completions */
-		if (mlx4_is_mfunc(dev)) {
-			nreq = 2;
-		} else {
-			nreq = min_t(int, dev->caps.num_eqs -
-				     dev->caps.reserved_eqs, nreq);
-		}
+		nreq = min_t(int, dev->caps.num_eqs - dev->caps.reserved_eqs,
+			     nreq);
 
 		entries = kcalloc(nreq, sizeof *entries, GFP_KERNEL);
 		if (!entries)
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
index bc165f4..695667d 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_init.c
@@ -144,7 +144,7 @@
 					 buffrag->length, PCI_DMA_TODEVICE);
 			buffrag->dma = 0ULL;
 		}
-		for (j = 0; j < cmd_buf->frag_count; j++) {
+		for (j = 1; j < cmd_buf->frag_count; j++) {
 			buffrag++;
 			if (buffrag->dma) {
 				pci_unmap_page(adapter->pdev, buffrag->dma,
diff --git a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
index 6098fd4a..69e321a 100644
--- a/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
+++ b/drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
@@ -1963,10 +1963,12 @@
 	while (--i >= 0) {
 		nf = &pbuf->frag_array[i+1];
 		pci_unmap_page(pdev, nf->dma, nf->length, PCI_DMA_TODEVICE);
+		nf->dma = 0ULL;
 	}
 
 	nf = &pbuf->frag_array[0];
 	pci_unmap_single(pdev, nf->dma, skb_headlen(skb), PCI_DMA_TODEVICE);
+	nf->dma = 0ULL;
 
 out_err:
 	return -ENOMEM;
diff --git a/drivers/net/ethernet/qlogic/qlge/qlge_main.c b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
index f80cd97..3e73742 100644
--- a/drivers/net/ethernet/qlogic/qlge/qlge_main.c
+++ b/drivers/net/ethernet/qlogic/qlge/qlge_main.c
@@ -4678,7 +4678,7 @@
 	qdev = netdev_priv(ndev);
 	SET_NETDEV_DEV(ndev, &pdev->dev);
 	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM |
-		NETIF_F_TSO | NETIF_F_TSO6 | NETIF_F_TSO_ECN |
+		NETIF_F_TSO | NETIF_F_TSO_ECN |
 		NETIF_F_HW_VLAN_TX | NETIF_F_RXCSUM;
 	ndev->features = ndev->hw_features |
 		NETIF_F_HW_VLAN_RX | NETIF_F_HW_VLAN_FILTER;
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index ed96f30..1170232 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -1826,8 +1826,6 @@
 
 	if (opts2 & RxVlanTag)
 		__vlan_hwaccel_put_tag(skb, swab16(opts2 & 0xffff));
-
-	desc->opts2 = 0;
 }
 
 static int rtl8169_gset_tbi(struct net_device *dev, struct ethtool_cmd *cmd)
@@ -6064,8 +6062,6 @@
 			    !(status & (RxRWT | RxFOVF)) &&
 			    (dev->features & NETIF_F_RXALL))
 				goto process_pkt;
-
-			rtl8169_mark_to_asic(desc, rx_buf_sz);
 		} else {
 			struct sk_buff *skb;
 			dma_addr_t addr;
@@ -6086,16 +6082,14 @@
 			if (unlikely(rtl8169_fragmented_frame(status))) {
 				dev->stats.rx_dropped++;
 				dev->stats.rx_length_errors++;
-				rtl8169_mark_to_asic(desc, rx_buf_sz);
-				continue;
+				goto release_descriptor;
 			}
 
 			skb = rtl8169_try_rx_copy(tp->Rx_databuff[entry],
 						  tp, pkt_size, addr);
-			rtl8169_mark_to_asic(desc, rx_buf_sz);
 			if (!skb) {
 				dev->stats.rx_dropped++;
-				continue;
+				goto release_descriptor;
 			}
 
 			rtl8169_rx_csum(skb, status);
@@ -6111,13 +6105,10 @@
 			tp->rx_stats.bytes += pkt_size;
 			u64_stats_update_end(&tp->rx_stats.syncp);
 		}
-
-		/* Work around for AMD plateform. */
-		if ((desc->opts2 & cpu_to_le32(0xfffe000)) &&
-		    (tp->mac_version == RTL_GIGA_MAC_VER_05)) {
-			desc->opts2 = 0;
-			cur_rx++;
-		}
+release_descriptor:
+		desc->opts2 = 0;
+		wmb();
+		rtl8169_mark_to_asic(desc, rx_buf_sz);
 	}
 
 	count = cur_rx - tp->cur_rx;
diff --git a/drivers/net/ethernet/xilinx/Kconfig b/drivers/net/ethernet/xilinx/Kconfig
index 5778a4a..122d60c 100644
--- a/drivers/net/ethernet/xilinx/Kconfig
+++ b/drivers/net/ethernet/xilinx/Kconfig
@@ -27,7 +27,7 @@
 
 config XILINX_AXI_EMAC
 	tristate "Xilinx 10/100/1000 AXI Ethernet support"
-	depends on (PPC32 || MICROBLAZE)
+	depends on MICROBLAZE
 	select PHYLIB
 	---help---
 	  This driver supports the 10/100/1000 Ethernet from Xilinx for the
diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
index d9f69b8..6f47100 100644
--- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
+++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c
@@ -1590,7 +1590,7 @@
 	lp->rx_irq = irq_of_parse_and_map(np, 1);
 	lp->tx_irq = irq_of_parse_and_map(np, 0);
 	of_node_put(np);
-	if ((lp->rx_irq == NO_IRQ) || (lp->tx_irq == NO_IRQ)) {
+	if ((lp->rx_irq <= 0) || (lp->tx_irq <= 0)) {
 		dev_err(&op->dev, "could not determine irqs\n");
 		ret = -ENOMEM;
 		goto err_iounmap_2;
diff --git a/drivers/net/hyperv/hyperv_net.h b/drivers/net/hyperv/hyperv_net.h
index 5fd6f46..e6fe0d8 100644
--- a/drivers/net/hyperv/hyperv_net.h
+++ b/drivers/net/hyperv/hyperv_net.h
@@ -84,7 +84,7 @@
 };
 
 struct netvsc_device_info {
-	unsigned char mac_adr[6];
+	unsigned char mac_adr[ETH_ALEN];
 	bool link_state;	/* 0 - link up, 1 - link down */
 	int  ring_size;
 };
diff --git a/drivers/net/hyperv/netvsc_drv.c b/drivers/net/hyperv/netvsc_drv.c
index f825a62..8264f0e 100644
--- a/drivers/net/hyperv/netvsc_drv.c
+++ b/drivers/net/hyperv/netvsc_drv.c
@@ -349,7 +349,7 @@
 	struct net_device_context *ndevctx = netdev_priv(ndev);
 	struct hv_device *hdev =  ndevctx->device_ctx;
 	struct sockaddr *addr = p;
-	char save_adr[14];
+	char save_adr[ETH_ALEN];
 	unsigned char save_aatype;
 	int err;
 
diff --git a/drivers/net/loopback.c b/drivers/net/loopback.c
index 81f8f9e..fcbf680 100644
--- a/drivers/net/loopback.c
+++ b/drivers/net/loopback.c
@@ -77,6 +77,11 @@
 
 	skb_orphan(skb);
 
+	/* Before queueing this packet to netif_rx(),
+	 * make sure dst is refcounted.
+	 */
+	skb_dst_force(skb);
+
 	skb->protocol = eth_type_trans(skb, dev);
 
 	/* it's OK to use per_cpu_ptr() because BHs are off */
diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c
index 68a43fe..d3fb97d 100644
--- a/drivers/net/macvlan.c
+++ b/drivers/net/macvlan.c
@@ -822,7 +822,10 @@
 
 static size_t macvlan_get_size(const struct net_device *dev)
 {
-	return nla_total_size(4);
+	return (0
+		+ nla_total_size(4) /* IFLA_MACVLAN_MODE */
+		+ nla_total_size(2) /* IFLA_MACVLAN_FLAGS */
+		);
 }
 
 static int macvlan_fill_info(struct sk_buff *skb,
diff --git a/drivers/net/phy/icplus.c b/drivers/net/phy/icplus.c
index d5199cb..b5ddd50 100644
--- a/drivers/net/phy/icplus.c
+++ b/drivers/net/phy/icplus.c
@@ -36,8 +36,9 @@
 
 /* IP101A/G - IP1001 */
 #define IP10XX_SPEC_CTRL_STATUS		16	/* Spec. Control Register */
+#define IP1001_RXPHASE_SEL		(1<<0)	/* Add delay on RX_CLK */
+#define IP1001_TXPHASE_SEL		(1<<1)	/* Add delay on TX_CLK */
 #define IP1001_SPEC_CTRL_STATUS_2	20	/* IP1001 Spec. Control Reg 2 */
-#define IP1001_PHASE_SEL_MASK		3	/* IP1001 RX/TXPHASE_SEL */
 #define IP1001_APS_ON			11	/* IP1001 APS Mode  bit */
 #define IP101A_G_APS_ON			2	/* IP101A/G APS Mode bit */
 #define IP101A_G_IRQ_CONF_STATUS	0x11	/* Conf Info IRQ & Status Reg */
@@ -138,19 +139,24 @@
 	if (c < 0)
 		return c;
 
-	/* INTR pin used: speed/link/duplex will cause an interrupt */
-	c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT);
-	if (c < 0)
-		return c;
+	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
+	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)) {
 
-	if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
-		/* Additional delay (2ns) used to adjust RX clock phase
-		 * at RGMII interface */
 		c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
 		if (c < 0)
 			return c;
 
-		c |= IP1001_PHASE_SEL_MASK;
+		c &= ~(IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL);
+
+		if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID)
+			c |= (IP1001_RXPHASE_SEL | IP1001_TXPHASE_SEL);
+		else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID)
+			c |= IP1001_RXPHASE_SEL;
+		else if (phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
+			c |= IP1001_TXPHASE_SEL;
+
 		c = phy_write(phydev, IP10XX_SPEC_CTRL_STATUS, c);
 		if (c < 0)
 			return c;
@@ -167,6 +173,11 @@
 	if (c < 0)
 		return c;
 
+	/* INTR pin used: speed/link/duplex will cause an interrupt */
+	c = phy_write(phydev, IP101A_G_IRQ_CONF_STATUS, IP101A_G_IRQ_DEFAULT);
+	if (c < 0)
+		return c;
+
 	/* Enable Auto Power Saving mode */
 	c = phy_read(phydev, IP10XX_SPEC_CTRL_STATUS);
 	c |= IP101A_G_APS_ON;
diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c
index 5d2a3f2..22dec9c 100644
--- a/drivers/net/phy/marvell.c
+++ b/drivers/net/phy/marvell.c
@@ -353,15 +353,6 @@
 	int err;
 	int temp;
 
-	/* Enable Fiber/Copper auto selection */
-	temp = phy_read(phydev, MII_M1111_PHY_EXT_SR);
-	temp &= ~MII_M1111_HWCFG_FIBER_COPPER_AUTO;
-	phy_write(phydev, MII_M1111_PHY_EXT_SR, temp);
-
-	temp = phy_read(phydev, MII_BMCR);
-	temp |= BMCR_RESET;
-	phy_write(phydev, MII_BMCR, temp);
-
 	if ((phydev->interface == PHY_INTERFACE_MODE_RGMII) ||
 	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID) ||
 	    (phydev->interface == PHY_INTERFACE_MODE_RGMII_RXID) ||
diff --git a/drivers/net/tun.c b/drivers/net/tun.c
index fbd106e..cc09b67 100644
--- a/drivers/net/tun.c
+++ b/drivers/net/tun.c
@@ -109,11 +109,11 @@
 	unsigned char	addr[FLT_EXACT_COUNT][ETH_ALEN];
 };
 
-/* 1024 is probably a high enough limit: modern hypervisors seem to support on
- * the order of 100-200 CPUs so this leaves us some breathing space if we want
- * to match a queue per guest CPU.
- */
-#define MAX_TAP_QUEUES 1024
+/* DEFAULT_MAX_NUM_RSS_QUEUES were choosed to let the rx/tx queues allocated for
+ * the netdevice to be fit in one page. So we can make sure the success of
+ * memory allocation. TODO: increase the limit. */
+#define MAX_TAP_QUEUES DEFAULT_MAX_NUM_RSS_QUEUES
+#define MAX_TAP_FLOWS  4096
 
 #define TUN_FLOW_EXPIRE (3 * HZ)
 
@@ -185,6 +185,8 @@
 	unsigned long ageing_time;
 	unsigned int numdisabled;
 	struct list_head disabled;
+	void *security;
+	u32 flow_count;
 };
 
 static inline u32 tun_hashfn(u32 rxhash)
@@ -218,6 +220,7 @@
 		e->queue_index = queue_index;
 		e->tun = tun;
 		hlist_add_head_rcu(&e->hash_link, head);
+		++tun->flow_count;
 	}
 	return e;
 }
@@ -228,6 +231,7 @@
 		  e->rxhash, e->queue_index);
 	hlist_del_rcu(&e->hash_link);
 	kfree_rcu(e, rcu);
+	--tun->flow_count;
 }
 
 static void tun_flow_flush(struct tun_struct *tun)
@@ -317,7 +321,8 @@
 		e->updated = jiffies;
 	} else {
 		spin_lock_bh(&tun->lock);
-		if (!tun_flow_find(head, rxhash))
+		if (!tun_flow_find(head, rxhash) &&
+		    tun->flow_count < MAX_TAP_FLOWS)
 			tun_flow_create(tun, head, rxhash, queue_index);
 
 		if (!timer_pending(&tun->flow_gc_timer))
@@ -404,8 +409,8 @@
 	struct tun_struct *tun;
 	struct net_device *dev;
 
-	tun = rcu_dereference_protected(tfile->tun,
-					lockdep_rtnl_is_held());
+	tun = rtnl_dereference(tfile->tun);
+
 	if (tun) {
 		u16 index = tfile->queue_index;
 		BUG_ON(index >= tun->numqueues);
@@ -414,8 +419,7 @@
 		rcu_assign_pointer(tun->tfiles[index],
 				   tun->tfiles[tun->numqueues - 1]);
 		rcu_assign_pointer(tfile->tun, NULL);
-		ntfile = rcu_dereference_protected(tun->tfiles[index],
-						   lockdep_rtnl_is_held());
+		ntfile = rtnl_dereference(tun->tfiles[index]);
 		ntfile->queue_index = index;
 
 		--tun->numqueues;
@@ -429,8 +433,10 @@
 		/* Drop read queue */
 		skb_queue_purge(&tfile->sk.sk_receive_queue);
 		tun_set_real_num_queues(tun);
-	} else if (tfile->detached && clean)
+	} else if (tfile->detached && clean) {
 		tun = tun_enable_queue(tfile);
+		sock_put(&tfile->sk);
+	}
 
 	if (clean) {
 		if (tun && tun->numqueues == 0 && tun->numdisabled == 0 &&
@@ -458,8 +464,7 @@
 	int i, n = tun->numqueues;
 
 	for (i = 0; i < n; i++) {
-		tfile = rcu_dereference_protected(tun->tfiles[i],
-						  lockdep_rtnl_is_held());
+		tfile = rtnl_dereference(tun->tfiles[i]);
 		BUG_ON(!tfile);
 		wake_up_all(&tfile->wq.wait);
 		rcu_assign_pointer(tfile->tun, NULL);
@@ -469,8 +474,7 @@
 
 	synchronize_net();
 	for (i = 0; i < n; i++) {
-		tfile = rcu_dereference_protected(tun->tfiles[i],
-						  lockdep_rtnl_is_held());
+		tfile = rtnl_dereference(tun->tfiles[i]);
 		/* Drop read queue */
 		skb_queue_purge(&tfile->sk.sk_receive_queue);
 		sock_put(&tfile->sk);
@@ -481,6 +485,9 @@
 		sock_put(&tfile->sk);
 	}
 	BUG_ON(tun->numdisabled != 0);
+
+	if (tun->flags & TUN_PERSIST)
+		module_put(THIS_MODULE);
 }
 
 static int tun_attach(struct tun_struct *tun, struct file *file)
@@ -488,8 +495,12 @@
 	struct tun_file *tfile = file->private_data;
 	int err;
 
+	err = security_tun_dev_attach(tfile->socket.sk, tun->security);
+	if (err < 0)
+		goto out;
+
 	err = -EINVAL;
-	if (rcu_dereference_protected(tfile->tun, lockdep_rtnl_is_held()))
+	if (rtnl_dereference(tfile->tun))
 		goto out;
 
 	err = -EBUSY;
@@ -1371,6 +1382,7 @@
 
 	BUG_ON(!(list_empty(&tun->disabled)));
 	tun_flow_uninit(tun);
+	security_tun_dev_free_security(tun->security);
 	free_netdev(dev);
 }
 
@@ -1544,6 +1556,9 @@
 	struct net_device *dev;
 	int err;
 
+	if (tfile->detached)
+		return -EINVAL;
+
 	dev = __dev_get_by_name(net, ifr->ifr_name);
 	if (dev) {
 		if (ifr->ifr_flags & IFF_TUN_EXCL)
@@ -1557,7 +1572,7 @@
 
 		if (tun_not_capable(tun))
 			return -EPERM;
-		err = security_tun_dev_attach(tfile->socket.sk);
+		err = security_tun_dev_open(tun->security);
 		if (err < 0)
 			return err;
 
@@ -1572,6 +1587,8 @@
 	else {
 		char *name;
 		unsigned long flags = 0;
+		int queues = ifr->ifr_flags & IFF_MULTI_QUEUE ?
+			     MAX_TAP_QUEUES : 1;
 
 		if (!ns_capable(net->user_ns, CAP_NET_ADMIN))
 			return -EPERM;
@@ -1595,8 +1612,8 @@
 			name = ifr->ifr_name;
 
 		dev = alloc_netdev_mqs(sizeof(struct tun_struct), name,
-				       tun_setup,
-				       MAX_TAP_QUEUES, MAX_TAP_QUEUES);
+				       tun_setup, queues, queues);
+
 		if (!dev)
 			return -ENOMEM;
 
@@ -1614,7 +1631,9 @@
 
 		spin_lock_init(&tun->lock);
 
-		security_tun_dev_post_create(&tfile->sk);
+		err = security_tun_dev_alloc_security(&tun->security);
+		if (err < 0)
+			goto err_free_dev;
 
 		tun_net_init(dev);
 
@@ -1738,8 +1757,7 @@
 	struct tun_file *tfile;
 
 	for (i = 0; i < n; i++) {
-		tfile = rcu_dereference_protected(tun->tfiles[i],
-						  lockdep_rtnl_is_held());
+		tfile = rtnl_dereference(tun->tfiles[i]);
 		sk_detach_filter(tfile->socket.sk);
 	}
 
@@ -1752,8 +1770,7 @@
 	struct tun_file *tfile;
 
 	for (i = 0; i < tun->numqueues; i++) {
-		tfile = rcu_dereference_protected(tun->tfiles[i],
-						  lockdep_rtnl_is_held());
+		tfile = rtnl_dereference(tun->tfiles[i]);
 		ret = sk_attach_filter(&tun->fprog, tfile->socket.sk);
 		if (ret) {
 			tun_detach_filter(tun, i);
@@ -1771,8 +1788,7 @@
 	int i;
 
 	for (i = 0; i < tun->numqueues; i++) {
-		tfile = rcu_dereference_protected(tun->tfiles[i],
-						lockdep_rtnl_is_held());
+		tfile = rtnl_dereference(tun->tfiles[i]);
 		tfile->socket.sk->sk_sndbuf = tun->sndbuf;
 	}
 }
@@ -1787,15 +1803,16 @@
 
 	if (ifr->ifr_flags & IFF_ATTACH_QUEUE) {
 		tun = tfile->detached;
-		if (!tun)
+		if (!tun) {
 			ret = -EINVAL;
-		else if (tun_not_capable(tun))
-			ret = -EPERM;
-		else
-			ret = tun_attach(tun, file);
+			goto unlock;
+		}
+		ret = security_tun_dev_attach_queue(tun->security);
+		if (ret < 0)
+			goto unlock;
+		ret = tun_attach(tun, file);
 	} else if (ifr->ifr_flags & IFF_DETACH_QUEUE) {
-		tun = rcu_dereference_protected(tfile->tun,
-						lockdep_rtnl_is_held());
+		tun = rtnl_dereference(tfile->tun);
 		if (!tun || !(tun->flags & TUN_TAP_MQ))
 			ret = -EINVAL;
 		else
@@ -1803,6 +1820,7 @@
 	} else
 		ret = -EINVAL;
 
+unlock:
 	rtnl_unlock();
 	return ret;
 }
@@ -1880,10 +1898,11 @@
 		/* Disable/Enable persist mode. Keep an extra reference to the
 		 * module to prevent the module being unprobed.
 		 */
-		if (arg) {
+		if (arg && !(tun->flags & TUN_PERSIST)) {
 			tun->flags |= TUN_PERSIST;
 			__module_get(THIS_MODULE);
-		} else {
+		}
+		if (!arg && (tun->flags & TUN_PERSIST)) {
 			tun->flags &= ~TUN_PERSIST;
 			module_put(THIS_MODULE);
 		}
diff --git a/drivers/net/usb/cdc_mbim.c b/drivers/net/usb/cdc_mbim.c
index 42f51c7..248d2dc 100644
--- a/drivers/net/usb/cdc_mbim.c
+++ b/drivers/net/usb/cdc_mbim.c
@@ -374,6 +374,21 @@
 	.tx_fixup = cdc_mbim_tx_fixup,
 };
 
+/* MBIM and NCM devices should not need a ZLP after NTBs with
+ * dwNtbOutMaxSize length. This driver_info is for the exceptional
+ * devices requiring it anyway, allowing them to be supported without
+ * forcing the performance penalty on all the sane devices.
+ */
+static const struct driver_info cdc_mbim_info_zlp = {
+	.description = "CDC MBIM",
+	.flags = FLAG_NO_SETINT | FLAG_MULTI_PACKET | FLAG_WWAN | FLAG_SEND_ZLP,
+	.bind = cdc_mbim_bind,
+	.unbind = cdc_mbim_unbind,
+	.manage_power = cdc_mbim_manage_power,
+	.rx_fixup = cdc_mbim_rx_fixup,
+	.tx_fixup = cdc_mbim_tx_fixup,
+};
+
 static const struct usb_device_id mbim_devs[] = {
 	/* This duplicate NCM entry is intentional. MBIM devices can
 	 * be disguised as NCM by default, and this is necessary to
@@ -385,6 +400,10 @@
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
 	  .driver_info = (unsigned long)&cdc_mbim_info,
 	},
+	/* Sierra Wireless MC7710 need ZLPs */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x1199, 0x68a2, USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
+	  .driver_info = (unsigned long)&cdc_mbim_info_zlp,
+	},
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_MBIM, USB_CDC_PROTO_NONE),
 	  .driver_info = (unsigned long)&cdc_mbim_info,
 	},
diff --git a/drivers/net/usb/cdc_ncm.c b/drivers/net/usb/cdc_ncm.c
index 71b6e92..9197b2c 100644
--- a/drivers/net/usb/cdc_ncm.c
+++ b/drivers/net/usb/cdc_ncm.c
@@ -435,6 +435,13 @@
 		len -= temp;
 	}
 
+	/* some buggy devices have an IAD but no CDC Union */
+	if (!ctx->union_desc && intf->intf_assoc && intf->intf_assoc->bInterfaceCount == 2) {
+		ctx->control = intf;
+		ctx->data = usb_ifnum_to_if(dev->udev, intf->cur_altsetting->desc.bInterfaceNumber + 1);
+		dev_dbg(&intf->dev, "CDC Union missing - got slave from IAD\n");
+	}
+
 	/* check if we got everything */
 	if ((ctx->control == NULL) || (ctx->data == NULL) ||
 	    ((!ctx->mbim_desc) && ((ctx->ether_desc == NULL) || (ctx->control != intf))))
@@ -497,7 +504,8 @@
 error2:
 	usb_set_intfdata(ctx->control, NULL);
 	usb_set_intfdata(ctx->data, NULL);
-	usb_driver_release_interface(driver, ctx->data);
+	if (ctx->data != ctx->control)
+		usb_driver_release_interface(driver, ctx->data);
 error:
 	cdc_ncm_free((struct cdc_ncm_ctx *)dev->data[0]);
 	dev->data[0] = 0;
@@ -1155,6 +1163,20 @@
 	.tx_fixup = cdc_ncm_tx_fixup,
 };
 
+/* Same as wwan_info, but with FLAG_NOARP  */
+static const struct driver_info wwan_noarp_info = {
+	.description = "Mobile Broadband Network Device (NO ARP)",
+	.flags = FLAG_POINTTOPOINT | FLAG_NO_SETINT | FLAG_MULTI_PACKET
+			| FLAG_WWAN | FLAG_NOARP,
+	.bind = cdc_ncm_bind,
+	.unbind = cdc_ncm_unbind,
+	.check_connect = cdc_ncm_check_connect,
+	.manage_power = usbnet_manage_power,
+	.status = cdc_ncm_status,
+	.rx_fixup = cdc_ncm_rx_fixup,
+	.tx_fixup = cdc_ncm_tx_fixup,
+};
+
 static const struct usb_device_id cdc_devs[] = {
 	/* Ericsson MBM devices like F5521gw */
 	{ .match_flags = USB_DEVICE_ID_MATCH_INT_INFO
@@ -1194,6 +1216,13 @@
 	  .driver_info = (unsigned long)&wwan_info,
 	},
 
+	/* Infineon(now Intel) HSPA Modem platform */
+	{ USB_DEVICE_AND_INTERFACE_INFO(0x1519, 0x0443,
+		USB_CLASS_COMM,
+		USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
+	  .driver_info = (unsigned long)&wwan_noarp_info,
+	},
+
 	/* Generic CDC-NCM devices */
 	{ USB_INTERFACE_INFO(USB_CLASS_COMM,
 		USB_CDC_SUBCLASS_NCM, USB_CDC_PROTO_NONE),
diff --git a/drivers/net/usb/dm9601.c b/drivers/net/usb/dm9601.c
index 3f554c1..d7e9944 100644
--- a/drivers/net/usb/dm9601.c
+++ b/drivers/net/usb/dm9601.c
@@ -45,6 +45,12 @@
 #define DM_MCAST_ADDR	0x16	/* 8 bytes */
 #define DM_GPR_CTRL	0x1e
 #define DM_GPR_DATA	0x1f
+#define DM_CHIP_ID	0x2c
+#define DM_MODE_CTRL	0x91	/* only on dm9620 */
+
+/* chip id values */
+#define ID_DM9601	0
+#define ID_DM9620	1
 
 #define DM_MAX_MCAST	64
 #define DM_MCAST_SIZE	8
@@ -53,7 +59,6 @@
 #define DM_RX_OVERHEAD	7	/* 3 byte header + 4 byte crc tail */
 #define DM_TIMEOUT	1000
 
-
 static int dm_read(struct usbnet *dev, u8 reg, u16 length, void *data)
 {
 	int err;
@@ -84,32 +89,23 @@
 
 static int dm_write_reg(struct usbnet *dev, u8 reg, u8 value)
 {
-	return usbnet_write_cmd(dev, DM_WRITE_REGS,
+	return usbnet_write_cmd(dev, DM_WRITE_REG,
 				USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
 				value, reg, NULL, 0);
 }
 
-static void dm_write_async_helper(struct usbnet *dev, u8 reg, u8 value,
-				  u16 length, void *data)
+static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
 {
 	usbnet_write_cmd_async(dev, DM_WRITE_REGS,
 			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
-			       value, reg, data, length);
-}
-
-static void dm_write_async(struct usbnet *dev, u8 reg, u16 length, void *data)
-{
-	netdev_dbg(dev->net, "dm_write_async() reg=0x%02x length=%d\n", reg, length);
-
-	dm_write_async_helper(dev, reg, 0, length, data);
+			       0, reg, data, length);
 }
 
 static void dm_write_reg_async(struct usbnet *dev, u8 reg, u8 value)
 {
-	netdev_dbg(dev->net, "dm_write_reg_async() reg=0x%02x value=0x%02x\n",
-		   reg, value);
-
-	dm_write_async_helper(dev, reg, value, 0, NULL);
+	usbnet_write_cmd_async(dev, DM_WRITE_REG,
+			       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+			       value, reg, NULL, 0);
 }
 
 static int dm_read_shared_word(struct usbnet *dev, int phy, u8 reg, __le16 *value)
@@ -358,7 +354,7 @@
 static int dm9601_bind(struct usbnet *dev, struct usb_interface *intf)
 {
 	int ret;
-	u8 mac[ETH_ALEN];
+	u8 mac[ETH_ALEN], id;
 
 	ret = usbnet_get_endpoints(dev, intf);
 	if (ret)
@@ -399,6 +395,24 @@
 		__dm9601_set_mac_address(dev);
 	}
 
+	if (dm_read_reg(dev, DM_CHIP_ID, &id) < 0) {
+		netdev_err(dev->net, "Error reading chip ID\n");
+		ret = -ENODEV;
+		goto out;
+	}
+
+	/* put dm9620 devices in dm9601 mode */
+	if (id == ID_DM9620) {
+		u8 mode;
+
+		if (dm_read_reg(dev, DM_MODE_CTRL, &mode) < 0) {
+			netdev_err(dev->net, "Error reading MODE_CTRL\n");
+			ret = -ENODEV;
+			goto out;
+		}
+		dm_write_reg(dev, DM_MODE_CTRL, mode & 0x7f);
+	}
+
 	/* power up phy */
 	dm_write_reg(dev, DM_GPR_CTRL, 1);
 	dm_write_reg(dev, DM_GPR_DATA, 0);
@@ -581,6 +595,10 @@
 	 USB_DEVICE(0x0a46, 0x9000),	/* DM9000E */
 	 .driver_info = (unsigned long)&dm9601_info,
 	 },
+	{
+	 USB_DEVICE(0x0a46, 0x9620),	/* DM9620 USB to Fast Ethernet Adapter */
+	 .driver_info = (unsigned long)&dm9601_info,
+	 },
 	{},			// END
 };
 
diff --git a/drivers/net/usb/qmi_wwan.c b/drivers/net/usb/qmi_wwan.c
index 6a1ca50..575a583 100644
--- a/drivers/net/usb/qmi_wwan.c
+++ b/drivers/net/usb/qmi_wwan.c
@@ -433,6 +433,7 @@
 	{QMI_FIXED_INTF(0x19d2, 0x0199, 1)},	/* ZTE MF820S */
 	{QMI_FIXED_INTF(0x19d2, 0x0200, 1)},
 	{QMI_FIXED_INTF(0x19d2, 0x0257, 3)},	/* ZTE MF821 */
+	{QMI_FIXED_INTF(0x19d2, 0x0265, 4)},	/* ONDA MT8205 4G LTE */
 	{QMI_FIXED_INTF(0x19d2, 0x0284, 4)},	/* ZTE MF880 */
 	{QMI_FIXED_INTF(0x19d2, 0x0326, 4)},	/* ZTE MF821D */
 	{QMI_FIXED_INTF(0x19d2, 0x1008, 4)},	/* ZTE (Vodafone) K3570-Z */
@@ -459,6 +460,7 @@
 	{QMI_FIXED_INTF(0x1199, 0x68a2, 19)},	/* Sierra Wireless MC7710 in QMI mode */
 	{QMI_FIXED_INTF(0x1199, 0x901c, 8)},    /* Sierra Wireless EM7700 */
 	{QMI_FIXED_INTF(0x1bbb, 0x011e, 4)},	/* Telekom Speedstick LTE II (Alcatel One Touch L100V LTE) */
+	{QMI_FIXED_INTF(0x2357, 0x0201, 4)},	/* TP-LINK HSUPA Modem MA180 */
 
 	/* 4. Gobi 1000 devices */
 	{QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},	/* Acer Gobi Modem Device */
diff --git a/drivers/net/usb/usbnet.c b/drivers/net/usb/usbnet.c
index 3d4bf01..f34b2eb 100644
--- a/drivers/net/usb/usbnet.c
+++ b/drivers/net/usb/usbnet.c
@@ -1448,6 +1448,10 @@
 		if ((dev->driver_info->flags & FLAG_WWAN) != 0)
 			strcpy(net->name, "wwan%d");
 
+		/* devices that cannot do ARP */
+		if ((dev->driver_info->flags & FLAG_NOARP) != 0)
+			net->flags |= IFF_NOARP;
+
 		/* maybe the remote can't receive an Ethernet MTU */
 		if (net->mtu > (dev->hard_mtu - net->hard_header_len))
 			net->mtu = dev->hard_mtu - net->hard_header_len;
diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c
index a6fcf15..35c00c5 100644
--- a/drivers/net/virtio_net.c
+++ b/drivers/net/virtio_net.c
@@ -26,6 +26,7 @@
 #include <linux/scatterlist.h>
 #include <linux/if_vlan.h>
 #include <linux/slab.h>
+#include <linux/cpu.h>
 
 static int napi_weight = 128;
 module_param(napi_weight, int, 0444);
@@ -123,6 +124,12 @@
 
 	/* Does the affinity hint is set for virtqueues? */
 	bool affinity_hint_set;
+
+	/* Per-cpu variable to show the mapping from CPU to virtqueue */
+	int __percpu *vq_index;
+
+	/* CPU hot plug notifier */
+	struct notifier_block nb;
 };
 
 struct skb_vnet_hdr {
@@ -1013,32 +1020,75 @@
 	return 0;
 }
 
-static void virtnet_set_affinity(struct virtnet_info *vi, bool set)
+static void virtnet_clean_affinity(struct virtnet_info *vi, long hcpu)
 {
 	int i;
+	int cpu;
+
+	if (vi->affinity_hint_set) {
+		for (i = 0; i < vi->max_queue_pairs; i++) {
+			virtqueue_set_affinity(vi->rq[i].vq, -1);
+			virtqueue_set_affinity(vi->sq[i].vq, -1);
+		}
+
+		vi->affinity_hint_set = false;
+	}
+
+	i = 0;
+	for_each_online_cpu(cpu) {
+		if (cpu == hcpu) {
+			*per_cpu_ptr(vi->vq_index, cpu) = -1;
+		} else {
+			*per_cpu_ptr(vi->vq_index, cpu) =
+				++i % vi->curr_queue_pairs;
+		}
+	}
+}
+
+static void virtnet_set_affinity(struct virtnet_info *vi)
+{
+	int i;
+	int cpu;
 
 	/* In multiqueue mode, when the number of cpu is equal to the number of
 	 * queue pairs, we let the queue pairs to be private to one cpu by
 	 * setting the affinity hint to eliminate the contention.
 	 */
-	if ((vi->curr_queue_pairs == 1 ||
-	     vi->max_queue_pairs != num_online_cpus()) && set) {
-		if (vi->affinity_hint_set)
-			set = false;
-		else
-			return;
+	if (vi->curr_queue_pairs == 1 ||
+	    vi->max_queue_pairs != num_online_cpus()) {
+		virtnet_clean_affinity(vi, -1);
+		return;
 	}
 
-	for (i = 0; i < vi->max_queue_pairs; i++) {
-		int cpu = set ? i : -1;
+	i = 0;
+	for_each_online_cpu(cpu) {
 		virtqueue_set_affinity(vi->rq[i].vq, cpu);
 		virtqueue_set_affinity(vi->sq[i].vq, cpu);
+		*per_cpu_ptr(vi->vq_index, cpu) = i;
+		i++;
 	}
 
-	if (set)
-		vi->affinity_hint_set = true;
-	else
-		vi->affinity_hint_set = false;
+	vi->affinity_hint_set = true;
+}
+
+static int virtnet_cpu_callback(struct notifier_block *nfb,
+			        unsigned long action, void *hcpu)
+{
+	struct virtnet_info *vi = container_of(nfb, struct virtnet_info, nb);
+
+	switch(action & ~CPU_TASKS_FROZEN) {
+	case CPU_ONLINE:
+	case CPU_DOWN_FAILED:
+	case CPU_DEAD:
+		virtnet_set_affinity(vi);
+		break;
+	case CPU_DOWN_PREPARE:
+		virtnet_clean_affinity(vi, (long)hcpu);
+		break;
+	default:
+		break;
+	}
+	return NOTIFY_OK;
 }
 
 static void virtnet_get_ringparam(struct net_device *dev,
@@ -1082,13 +1132,15 @@
 	if (queue_pairs > vi->max_queue_pairs)
 		return -EINVAL;
 
+	get_online_cpus();
 	err = virtnet_set_queues(vi, queue_pairs);
 	if (!err) {
 		netif_set_real_num_tx_queues(dev, queue_pairs);
 		netif_set_real_num_rx_queues(dev, queue_pairs);
 
-		virtnet_set_affinity(vi, true);
+		virtnet_set_affinity(vi);
 	}
+	put_online_cpus();
 
 	return err;
 }
@@ -1127,12 +1179,19 @@
 
 /* To avoid contending a lock hold by a vcpu who would exit to host, select the
  * txq based on the processor id.
- * TODO: handle cpu hotplug.
  */
 static u16 virtnet_select_queue(struct net_device *dev, struct sk_buff *skb)
 {
-	int txq = skb_rx_queue_recorded(skb) ? skb_get_rx_queue(skb) :
-		  smp_processor_id();
+	int txq;
+	struct virtnet_info *vi = netdev_priv(dev);
+
+	if (skb_rx_queue_recorded(skb)) {
+		txq = skb_get_rx_queue(skb);
+	} else {
+		txq = *__this_cpu_ptr(vi->vq_index);
+		if (txq == -1)
+			txq = 0;
+	}
 
 	while (unlikely(txq >= dev->real_num_tx_queues))
 		txq -= dev->real_num_tx_queues;
@@ -1248,7 +1307,7 @@
 {
 	struct virtio_device *vdev = vi->vdev;
 
-	virtnet_set_affinity(vi, false);
+	virtnet_clean_affinity(vi, -1);
 
 	vdev->config->del_vqs(vdev);
 
@@ -1371,7 +1430,10 @@
 	if (ret)
 		goto err_free;
 
-	virtnet_set_affinity(vi, true);
+	get_online_cpus();
+	virtnet_set_affinity(vi);
+	put_online_cpus();
+
 	return 0;
 
 err_free:
@@ -1453,6 +1515,10 @@
 	if (vi->stats == NULL)
 		goto free;
 
+	vi->vq_index = alloc_percpu(int);
+	if (vi->vq_index == NULL)
+		goto free_stats;
+
 	mutex_init(&vi->config_lock);
 	vi->config_enable = true;
 	INIT_WORK(&vi->config_work, virtnet_config_changed_work);
@@ -1476,7 +1542,7 @@
 	/* Allocate/initialize the rx/tx queues, and invoke find_vqs */
 	err = init_vqs(vi);
 	if (err)
-		goto free_stats;
+		goto free_index;
 
 	netif_set_real_num_tx_queues(dev, 1);
 	netif_set_real_num_rx_queues(dev, 1);
@@ -1499,6 +1565,13 @@
 		}
 	}
 
+	vi->nb.notifier_call = &virtnet_cpu_callback;
+	err = register_hotcpu_notifier(&vi->nb);
+	if (err) {
+		pr_debug("virtio_net: registering cpu notifier failed\n");
+		goto free_recv_bufs;
+	}
+
 	/* Assume link up if device can't report link status,
 	   otherwise get link status from config. */
 	if (virtio_has_feature(vi->vdev, VIRTIO_NET_F_STATUS)) {
@@ -1520,6 +1593,8 @@
 free_vqs:
 	cancel_delayed_work_sync(&vi->refill);
 	virtnet_del_vqs(vi);
+free_index:
+	free_percpu(vi->vq_index);
 free_stats:
 	free_percpu(vi->stats);
 free:
@@ -1543,6 +1618,8 @@
 {
 	struct virtnet_info *vi = vdev->priv;
 
+	unregister_hotcpu_notifier(&vi->nb);
+
 	/* Prevent config work handler from accessing the device. */
 	mutex_lock(&vi->config_lock);
 	vi->config_enable = false;
@@ -1554,6 +1631,7 @@
 
 	flush_work(&vi->config_work);
 
+	free_percpu(vi->vq_index);
 	free_percpu(vi->stats);
 	free_netdev(vi->dev);
 }
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index 1a67a4f..2c02b4e 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -30,5 +30,6 @@
 source "drivers/net/wireless/ath/carl9170/Kconfig"
 source "drivers/net/wireless/ath/ath6kl/Kconfig"
 source "drivers/net/wireless/ath/ar5523/Kconfig"
+source "drivers/net/wireless/ath/wil6210/Kconfig"
 
 endif
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index 1e18621..97b964d 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -3,6 +3,7 @@
 obj-$(CONFIG_CARL9170)		+= carl9170/
 obj-$(CONFIG_ATH6KL)		+= ath6kl/
 obj-$(CONFIG_AR5523)		+= ar5523/
+obj-$(CONFIG_WIL6210)		+= wil6210/
 
 obj-$(CONFIG_ATH_COMMON)	+= ath.o
 
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
index 8b0d8dc..56317b0 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c
@@ -976,6 +976,8 @@
 					  AR_PHY_CL_TAB_1,
 					  AR_PHY_CL_TAB_2 };
 
+	ar9003_hw_set_chain_masks(ah, ah->caps.rx_chainmask, ah->caps.tx_chainmask);
+
 	if (rtt) {
 		if (!ar9003_hw_rtt_restore(ah, chan))
 			run_rtt_cal = true;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index ce19c09..3afc24b 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -586,32 +586,19 @@
 	ath9k_hw_synth_delay(ah, chan, synthDelay);
 }
 
-static void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
+void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx)
 {
-	switch (rx) {
-	case 0x5:
+	if (ah->caps.tx_chainmask == 5 || ah->caps.rx_chainmask == 5)
 		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
 			    AR_PHY_SWAP_ALT_CHAIN);
-	case 0x3:
-	case 0x1:
-	case 0x2:
-	case 0x7:
-		REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
-		REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
-		break;
-	default:
-		break;
-	}
+
+	REG_WRITE(ah, AR_PHY_RX_CHAINMASK, rx);
+	REG_WRITE(ah, AR_PHY_CAL_CHAINMASK, rx);
 
 	if ((ah->caps.hw_caps & ATH9K_HW_CAP_APM) && (tx == 0x7))
-		REG_WRITE(ah, AR_SELFGEN_MASK, 0x3);
-	else
-		REG_WRITE(ah, AR_SELFGEN_MASK, tx);
+		tx = 3;
 
-	if (tx == 0x5) {
-		REG_SET_BIT(ah, AR_PHY_ANALOG_SWAP,
-			    AR_PHY_SWAP_ALT_CHAIN);
-	}
+	REG_WRITE(ah, AR_SELFGEN_MASK, tx);
 }
 
 /*
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 86e26a1..42794c5 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -317,7 +317,6 @@
 	u32 *rxlink;
 	u32 num_pkts;
 	unsigned int rxfilter;
-	spinlock_t rxbuflock;
 	struct list_head rxbuf;
 	struct ath_descdma rxdma;
 	struct ath_buf *rx_bufptr;
@@ -328,7 +327,6 @@
 
 int ath_startrecv(struct ath_softc *sc);
 bool ath_stoprecv(struct ath_softc *sc);
-void ath_flushrecv(struct ath_softc *sc);
 u32 ath_calcrxfilter(struct ath_softc *sc);
 int ath_rx_init(struct ath_softc *sc, int nbufs);
 void ath_rx_cleanup(struct ath_softc *sc);
@@ -646,7 +644,6 @@
 enum sc_op_flags {
 	SC_OP_INVALID,
 	SC_OP_BEACONS,
-	SC_OP_RXFLUSH,
 	SC_OP_ANI_RUN,
 	SC_OP_PRIM_STA_VIF,
 	SC_OP_HW_RESET,
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 531fffd..2ca355e 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -147,6 +147,7 @@
 				 skb->len, DMA_TO_DEVICE);
 		dev_kfree_skb_any(skb);
 		bf->bf_buf_addr = 0;
+		bf->bf_mpdu = NULL;
 	}
 
 	skb = ieee80211_beacon_get(hw, vif);
@@ -359,7 +360,6 @@
 		return;
 
 	bf = ath9k_beacon_generate(sc->hw, vif);
-	WARN_ON(!bf);
 
 	if (sc->beacon.bmisscnt != 0) {
 		ath_dbg(common, BSTUCK, "resume beacon xmit after %u misses\n",
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 13ff9ed..e585fc8 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -861,7 +861,6 @@
 	RXS_ERR("RX-LENGTH-ERR", rx_len_err);
 	RXS_ERR("RX-OOM-ERR", rx_oom_err);
 	RXS_ERR("RX-RATE-ERR", rx_rate_err);
-	RXS_ERR("RX-DROP-RXFLUSH", rx_drop_rxflush);
 	RXS_ERR("RX-TOO-MANY-FRAGS", rx_too_many_frags_err);
 
 	PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 375c3b4..6df2ab6 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -216,7 +216,6 @@
  * @rx_oom_err:  No. of frames dropped due to OOM issues.
  * @rx_rate_err:  No. of frames dropped due to rate errors.
  * @rx_too_many_frags_err:  Frames dropped due to too-many-frags received.
- * @rx_drop_rxflush: No. of frames dropped due to RX-FLUSH.
  * @rx_beacons:  No. of beacons received.
  * @rx_frags:  No. of rx-fragements received.
  */
@@ -235,7 +234,6 @@
 	u32 rx_oom_err;
 	u32 rx_rate_err;
 	u32 rx_too_many_frags_err;
-	u32 rx_drop_rxflush;
 	u32 rx_beacons;
 	u32 rx_frags;
 };
diff --git a/drivers/net/wireless/ath/ath9k/htc_hst.c b/drivers/net/wireless/ath/ath9k/htc_hst.c
index 4a9570d..aac4a40 100644
--- a/drivers/net/wireless/ath/ath9k/htc_hst.c
+++ b/drivers/net/wireless/ath/ath9k/htc_hst.c
@@ -344,6 +344,8 @@
 			endpoint->ep_callbacks.tx(endpoint->ep_callbacks.priv,
 						  skb, htc_hdr->endpoint_id,
 						  txok);
+		} else {
+			kfree_skb(skb);
 		}
 	}
 
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index 7f1a8e9..9d26fc5 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -1066,6 +1066,7 @@
 int ar9003_paprd_init_table(struct ath_hw *ah);
 bool ar9003_paprd_is_done(struct ath_hw *ah);
 bool ar9003_is_paprd_enabled(struct ath_hw *ah);
+void ar9003_hw_set_chain_masks(struct ath_hw *ah, u8 rx, u8 tx);
 
 /* Hardware family op attach helpers */
 void ar5008_hw_attach_phy_ops(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index be30a9a..dd91f8f 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -182,7 +182,7 @@
 	ath_start_ani(sc);
 }
 
-static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx, bool flush)
+static bool ath_prepare_reset(struct ath_softc *sc, bool retry_tx)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	bool ret = true;
@@ -202,14 +202,6 @@
 	if (!ath_drain_all_txq(sc, retry_tx))
 		ret = false;
 
-	if (!flush) {
-		if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
-			ath_rx_tasklet(sc, 1, true);
-		ath_rx_tasklet(sc, 1, false);
-	} else {
-		ath_flushrecv(sc);
-	}
-
 	return ret;
 }
 
@@ -262,11 +254,11 @@
 	struct ath_common *common = ath9k_hw_common(ah);
 	struct ath9k_hw_cal_data *caldata = NULL;
 	bool fastcc = true;
-	bool flush = false;
 	int r;
 
 	__ath_cancel_work(sc);
 
+	tasklet_disable(&sc->intr_tq);
 	spin_lock_bh(&sc->sc_pcu_lock);
 
 	if (!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) {
@@ -276,11 +268,10 @@
 
 	if (!hchan) {
 		fastcc = false;
-		flush = true;
 		hchan = ah->curchan;
 	}
 
-	if (!ath_prepare_reset(sc, retry_tx, flush))
+	if (!ath_prepare_reset(sc, retry_tx))
 		fastcc = false;
 
 	ath_dbg(common, CONFIG, "Reset to %u MHz, HT40: %d fastcc: %d\n",
@@ -302,6 +293,8 @@
 
 out:
 	spin_unlock_bh(&sc->sc_pcu_lock);
+	tasklet_enable(&sc->intr_tq);
+
 	return r;
 }
 
@@ -804,7 +797,7 @@
 		ath9k_hw_cfg_gpio_input(ah, ah->led_pin);
 	}
 
-	ath_prepare_reset(sc, false, true);
+	ath_prepare_reset(sc, false);
 
 	if (sc->rx.frag) {
 		dev_kfree_skb_any(sc->rx.frag);
@@ -1833,6 +1826,9 @@
 
 static bool validate_antenna_mask(struct ath_hw *ah, u32 val)
 {
+	if (AR_SREV_9300_20_OR_LATER(ah))
+		return true;
+
 	switch (val & 0x7) {
 	case 0x1:
 	case 0x3:
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index d4df98a..90752f2 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -254,8 +254,6 @@
 
 static void ath_edma_start_recv(struct ath_softc *sc)
 {
-	spin_lock_bh(&sc->rx.rxbuflock);
-
 	ath9k_hw_rxena(sc->sc_ah);
 
 	ath_rx_addbuffer_edma(sc, ATH9K_RX_QUEUE_HP,
@@ -267,8 +265,6 @@
 	ath_opmode_init(sc);
 
 	ath9k_hw_startpcureceive(sc->sc_ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
-
-	spin_unlock_bh(&sc->rx.rxbuflock);
 }
 
 static void ath_edma_stop_recv(struct ath_softc *sc)
@@ -285,8 +281,6 @@
 	int error = 0;
 
 	spin_lock_init(&sc->sc_pcu_lock);
-	spin_lock_init(&sc->rx.rxbuflock);
-	clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);
 
 	common->rx_bufsize = IEEE80211_MAX_MPDU_LEN / 2 +
 			     sc->sc_ah->caps.rx_status_len;
@@ -447,7 +441,6 @@
 		return 0;
 	}
 
-	spin_lock_bh(&sc->rx.rxbuflock);
 	if (list_empty(&sc->rx.rxbuf))
 		goto start_recv;
 
@@ -468,26 +461,31 @@
 	ath_opmode_init(sc);
 	ath9k_hw_startpcureceive(ah, !!(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL));
 
-	spin_unlock_bh(&sc->rx.rxbuflock);
-
 	return 0;
 }
 
+static void ath_flushrecv(struct ath_softc *sc)
+{
+	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
+		ath_rx_tasklet(sc, 1, true);
+	ath_rx_tasklet(sc, 1, false);
+}
+
 bool ath_stoprecv(struct ath_softc *sc)
 {
 	struct ath_hw *ah = sc->sc_ah;
 	bool stopped, reset = false;
 
-	spin_lock_bh(&sc->rx.rxbuflock);
 	ath9k_hw_abortpcurecv(ah);
 	ath9k_hw_setrxfilter(ah, 0);
 	stopped = ath9k_hw_stopdmarecv(ah, &reset);
 
+	ath_flushrecv(sc);
+
 	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
 		ath_edma_stop_recv(sc);
 	else
 		sc->rx.rxlink = NULL;
-	spin_unlock_bh(&sc->rx.rxbuflock);
 
 	if (!(ah->ah_flags & AH_UNPLUGGED) &&
 	    unlikely(!stopped)) {
@@ -499,15 +497,6 @@
 	return stopped && !reset;
 }
 
-void ath_flushrecv(struct ath_softc *sc)
-{
-	set_bit(SC_OP_RXFLUSH, &sc->sc_flags);
-	if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
-		ath_rx_tasklet(sc, 1, true);
-	ath_rx_tasklet(sc, 1, false);
-	clear_bit(SC_OP_RXFLUSH, &sc->sc_flags);
-}
-
 static bool ath_beacon_dtim_pending_cab(struct sk_buff *skb)
 {
 	/* Check whether the Beacon frame has DTIM indicating buffered bc/mc */
@@ -744,6 +733,7 @@
 			return NULL;
 	}
 
+	list_del(&bf->list);
 	if (!bf->bf_mpdu)
 		return bf;
 
@@ -1059,16 +1049,12 @@
 		dma_type = DMA_FROM_DEVICE;
 
 	qtype = hp ? ATH9K_RX_QUEUE_HP : ATH9K_RX_QUEUE_LP;
-	spin_lock_bh(&sc->rx.rxbuflock);
 
 	tsf = ath9k_hw_gettsf64(ah);
 	tsf_lower = tsf & 0xffffffff;
 
 	do {
 		bool decrypt_error = false;
-		/* If handling rx interrupt and flush is in progress => exit */
-		if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags) && (flush == 0))
-			break;
 
 		memset(&rs, 0, sizeof(rs));
 		if (edma)
@@ -1111,15 +1097,6 @@
 
 		ath_debug_stat_rx(sc, &rs);
 
-		/*
-		 * If we're asked to flush receive queue, directly
-		 * chain it back at the queue without processing it.
-		 */
-		if (test_bit(SC_OP_RXFLUSH, &sc->sc_flags)) {
-			RX_STAT_INC(rx_drop_rxflush);
-			goto requeue_drop_frag;
-		}
-
 		memset(rxs, 0, sizeof(struct ieee80211_rx_status));
 
 		rxs->mactime = (tsf & ~0xffffffffULL) | rs.rs_tstamp;
@@ -1254,19 +1231,18 @@
 			sc->rx.frag = NULL;
 		}
 requeue:
+		list_add_tail(&bf->list, &sc->rx.rxbuf);
+		if (flush)
+			continue;
+
 		if (edma) {
-			list_add_tail(&bf->list, &sc->rx.rxbuf);
 			ath_rx_edma_buf_link(sc, qtype);
 		} else {
-			list_move_tail(&bf->list, &sc->rx.rxbuf);
 			ath_rx_buf_link(sc, bf);
-			if (!flush)
-				ath9k_hw_rxena(ah);
+			ath9k_hw_rxena(ah);
 		}
 	} while (1);
 
-	spin_unlock_bh(&sc->rx.rxbuflock);
-
 	if (!(ah->imask & ATH9K_INT_RXEOL)) {
 		ah->imask |= (ATH9K_INT_RXEOL | ATH9K_INT_RXORN);
 		ath9k_hw_set_interrupts(ah);
diff --git a/drivers/net/wireless/ath/wil6210/Kconfig b/drivers/net/wireless/ath/wil6210/Kconfig
new file mode 100644
index 0000000..bac3d98
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/Kconfig
@@ -0,0 +1,29 @@
+config WIL6210
+	tristate "Wilocity 60g WiFi card wil6210 support"
+	depends on CFG80211
+	depends on PCI
+	default n
+	---help---
+	  This module adds support for wireless adapter based on
+	  wil6210 chip by Wilocity. It supports operation on the
+	  60 GHz band, covered by the IEEE802.11ad standard.
+
+	  http://wireless.kernel.org/en/users/Drivers/wil6210
+
+	  If you choose to build it as a module, it will be called
+	  wil6210
+
+config WIL6210_ISR_COR
+	bool "Use Clear-On-Read mode for ISR registers for wil6210"
+	depends on WIL6210
+	default y
+	---help---
+	  ISR registers on wil6210 chip may operate in either
+	  COR (Clear-On-Read) or W1C (Write-1-to-Clear) mode.
+	  For production code, use COR (say y); is default since
+	  it saves extra target transaction;
+	  For ISR debug, use W1C (say n); is allows to monitor ISR
+	  registers with debugfs. If COR were used, ISR would
+	  self-clear when accessed for debug purposes, it makes
+	  such monitoring impossible.
+	  Say y unless you debug interrupts
diff --git a/drivers/net/wireless/ath/wil6210/Makefile b/drivers/net/wireless/ath/wil6210/Makefile
new file mode 100644
index 0000000..9396dc9
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/Makefile
@@ -0,0 +1,13 @@
+obj-$(CONFIG_WIL6210) += wil6210.o
+
+wil6210-objs := main.o
+wil6210-objs += netdev.o
+wil6210-objs += cfg80211.o
+wil6210-objs += pcie_bus.o
+wil6210-objs += debugfs.o
+wil6210-objs += wmi.o
+wil6210-objs += interrupt.o
+wil6210-objs += txrx.o
+
+subdir-ccflags-y += -Werror
+subdir-ccflags-y += -D__CHECK_ENDIAN__
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
new file mode 100644
index 0000000..116f4e8
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -0,0 +1,573 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/etherdevice.h>
+#include <linux/wireless.h>
+#include <linux/ieee80211.h>
+#include <linux/slab.h>
+#include <linux/version.h>
+#include <net/cfg80211.h>
+
+#include "wil6210.h"
+#include "wmi.h"
+
+#define CHAN60G(_channel, _flags) {				\
+	.band			= IEEE80211_BAND_60GHZ,		\
+	.center_freq		= 56160 + (2160 * (_channel)),	\
+	.hw_value		= (_channel),			\
+	.flags			= (_flags),			\
+	.max_antenna_gain	= 0,				\
+	.max_power		= 40,				\
+}
+
+static struct ieee80211_channel wil_60ghz_channels[] = {
+	CHAN60G(1, 0),
+	CHAN60G(2, 0),
+	CHAN60G(3, 0),
+/* channel 4 not supported yet */
+};
+
+static struct ieee80211_supported_band wil_band_60ghz = {
+	.channels = wil_60ghz_channels,
+	.n_channels = ARRAY_SIZE(wil_60ghz_channels),
+	.ht_cap = {
+		.ht_supported = true,
+		.cap = 0, /* TODO */
+		.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K, /* TODO */
+		.ampdu_density = IEEE80211_HT_MPDU_DENSITY_8, /* TODO */
+		.mcs = {
+				/* MCS 1..12 - SC PHY */
+			.rx_mask = {0xfe, 0x1f}, /* 1..12 */
+			.tx_params = IEEE80211_HT_MCS_TX_DEFINED, /* TODO */
+		},
+	},
+};
+
+static const struct ieee80211_txrx_stypes
+wil_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+	[NL80211_IFTYPE_STATION] = {
+		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+	[NL80211_IFTYPE_AP] = {
+		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+	[NL80211_IFTYPE_P2P_CLIENT] = {
+		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+	[NL80211_IFTYPE_P2P_GO] = {
+		.tx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_RESP >> 4),
+		.rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+		BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+	},
+};
+
+static const u32 wil_cipher_suites[] = {
+	WLAN_CIPHER_SUITE_GCMP,
+};
+
+int wil_iftype_nl2wmi(enum nl80211_iftype type)
+{
+	static const struct {
+		enum nl80211_iftype nl;
+		enum wmi_network_type wmi;
+	} __nl2wmi[] = {
+		{NL80211_IFTYPE_ADHOC,		WMI_NETTYPE_ADHOC},
+		{NL80211_IFTYPE_STATION,	WMI_NETTYPE_INFRA},
+		{NL80211_IFTYPE_AP,		WMI_NETTYPE_AP},
+		{NL80211_IFTYPE_P2P_CLIENT,	WMI_NETTYPE_P2P},
+		{NL80211_IFTYPE_P2P_GO,		WMI_NETTYPE_P2P},
+		{NL80211_IFTYPE_MONITOR,	WMI_NETTYPE_ADHOC}, /* FIXME */
+	};
+	uint i;
+
+	for (i = 0; i < ARRAY_SIZE(__nl2wmi); i++) {
+		if (__nl2wmi[i].nl == type)
+			return __nl2wmi[i].wmi;
+	}
+
+	return -EOPNOTSUPP;
+}
+
+static int wil_cfg80211_get_station(struct wiphy *wiphy,
+				    struct net_device *ndev,
+				    u8 *mac, struct station_info *sinfo)
+{
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	int rc;
+	struct wmi_notify_req_cmd cmd = {
+		.cid = 0,
+		.interval_usec = 0,
+	};
+
+	if (memcmp(mac, wil->dst_addr[0], ETH_ALEN))
+		return -ENOENT;
+
+	/* WMI_NOTIFY_REQ_DONE_EVENTID handler fills wil->stats.bf_mcs */
+	rc = wmi_call(wil, WMI_NOTIFY_REQ_CMDID, &cmd, sizeof(cmd),
+		      WMI_NOTIFY_REQ_DONE_EVENTID, NULL, 0, 20);
+	if (rc)
+		return rc;
+
+	sinfo->generation = wil->sinfo_gen;
+
+	sinfo->filled |= STATION_INFO_TX_BITRATE;
+	sinfo->txrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G;
+	sinfo->txrate.mcs = wil->stats.bf_mcs;
+	sinfo->filled |= STATION_INFO_RX_BITRATE;
+	sinfo->rxrate.flags = RATE_INFO_FLAGS_MCS | RATE_INFO_FLAGS_60G;
+	sinfo->rxrate.mcs = wil->stats.last_mcs_rx;
+
+	if (test_bit(wil_status_fwconnected, &wil->status)) {
+		sinfo->filled |= STATION_INFO_SIGNAL;
+		sinfo->signal = 12; /* TODO: provide real value */
+	}
+
+	return 0;
+}
+
+static int wil_cfg80211_change_iface(struct wiphy *wiphy,
+				     struct net_device *ndev,
+				     enum nl80211_iftype type, u32 *flags,
+				     struct vif_params *params)
+{
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wireless_dev *wdev = wil->wdev;
+
+	switch (type) {
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_P2P_CLIENT:
+	case NL80211_IFTYPE_P2P_GO:
+		break;
+	case NL80211_IFTYPE_MONITOR:
+		if (flags)
+			wil->monitor_flags = *flags;
+		else
+			wil->monitor_flags = 0;
+
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	wdev->iftype = type;
+
+	return 0;
+}
+
+static int wil_cfg80211_scan(struct wiphy *wiphy,
+			     struct cfg80211_scan_request *request)
+{
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wireless_dev *wdev = wil->wdev;
+	struct {
+		struct wmi_start_scan_cmd cmd;
+		u16 chnl[4];
+	} __packed cmd;
+	uint i, n;
+
+	if (wil->scan_request) {
+		wil_err(wil, "Already scanning\n");
+		return -EAGAIN;
+	}
+
+	/* check we are client side */
+	switch (wdev->iftype) {
+	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_P2P_CLIENT:
+		break;
+	default:
+		return -EOPNOTSUPP;
+
+	}
+
+	/* FW don't support scan after connection attempt */
+	if (test_bit(wil_status_dontscan, &wil->status)) {
+		wil_err(wil, "Scan after connect attempt not supported\n");
+		return -EBUSY;
+	}
+
+	wil->scan_request = request;
+
+	memset(&cmd, 0, sizeof(cmd));
+	cmd.cmd.num_channels = 0;
+	n = min(request->n_channels, 4U);
+	for (i = 0; i < n; i++) {
+		int ch = request->channels[i]->hw_value;
+		if (ch == 0) {
+			wil_err(wil,
+				"Scan requested for unknown frequency %dMhz\n",
+				request->channels[i]->center_freq);
+			continue;
+		}
+		/* 0-based channel indexes */
+		cmd.cmd.channel_list[cmd.cmd.num_channels++].channel = ch - 1;
+		wil_dbg(wil, "Scan for ch %d  : %d MHz\n", ch,
+			request->channels[i]->center_freq);
+	}
+
+	return wmi_send(wil, WMI_START_SCAN_CMDID, &cmd, sizeof(cmd.cmd) +
+			cmd.cmd.num_channels * sizeof(cmd.cmd.channel_list[0]));
+}
+
+static int wil_cfg80211_connect(struct wiphy *wiphy,
+				struct net_device *ndev,
+				struct cfg80211_connect_params *sme)
+{
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct cfg80211_bss *bss;
+	struct wmi_connect_cmd conn;
+	const u8 *ssid_eid;
+	const u8 *rsn_eid;
+	int ch;
+	int rc = 0;
+
+	bss = cfg80211_get_bss(wiphy, sme->channel, sme->bssid,
+			       sme->ssid, sme->ssid_len,
+			       WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
+	if (!bss) {
+		wil_err(wil, "Unable to find BSS\n");
+		return -ENOENT;
+	}
+
+	ssid_eid = ieee80211_bss_get_ie(bss, WLAN_EID_SSID);
+	if (!ssid_eid) {
+		wil_err(wil, "No SSID\n");
+		rc = -ENOENT;
+		goto out;
+	}
+
+	rsn_eid = sme->ie ?
+			cfg80211_find_ie(WLAN_EID_RSN, sme->ie, sme->ie_len) :
+			NULL;
+	if (rsn_eid) {
+		if (sme->ie_len > WMI_MAX_IE_LEN) {
+			rc = -ERANGE;
+			wil_err(wil, "IE too large (%td bytes)\n",
+				sme->ie_len);
+			goto out;
+		}
+		/*
+		 * For secure assoc, send:
+		 * (1) WMI_DELETE_CIPHER_KEY_CMD
+		 * (2) WMI_SET_APPIE_CMD
+		 */
+		rc = wmi_del_cipher_key(wil, 0, bss->bssid);
+		if (rc) {
+			wil_err(wil, "WMI_DELETE_CIPHER_KEY_CMD failed\n");
+			goto out;
+		}
+		/* WMI_SET_APPIE_CMD */
+		rc = wmi_set_ie(wil, WMI_FRAME_ASSOC_REQ, sme->ie_len, sme->ie);
+		if (rc) {
+			wil_err(wil, "WMI_SET_APPIE_CMD failed\n");
+			goto out;
+		}
+	}
+
+	/* WMI_CONNECT_CMD */
+	memset(&conn, 0, sizeof(conn));
+	switch (bss->capability & 0x03) {
+	case WLAN_CAPABILITY_DMG_TYPE_AP:
+		conn.network_type = WMI_NETTYPE_INFRA;
+		break;
+	case WLAN_CAPABILITY_DMG_TYPE_PBSS:
+		conn.network_type = WMI_NETTYPE_P2P;
+		break;
+	default:
+		wil_err(wil, "Unsupported BSS type, capability= 0x%04x\n",
+			bss->capability);
+		goto out;
+	}
+	if (rsn_eid) {
+		conn.dot11_auth_mode = WMI_AUTH11_SHARED;
+		conn.auth_mode = WMI_AUTH_WPA2_PSK;
+		conn.pairwise_crypto_type = WMI_CRYPT_AES_GCMP;
+		conn.pairwise_crypto_len = 16;
+	} else {
+		conn.dot11_auth_mode = WMI_AUTH11_OPEN;
+		conn.auth_mode = WMI_AUTH_NONE;
+	}
+
+	conn.ssid_len = min_t(u8, ssid_eid[1], 32);
+	memcpy(conn.ssid, ssid_eid+2, conn.ssid_len);
+
+	ch = bss->channel->hw_value;
+	if (ch == 0) {
+		wil_err(wil, "BSS at unknown frequency %dMhz\n",
+			bss->channel->center_freq);
+		rc = -EOPNOTSUPP;
+		goto out;
+	}
+	conn.channel = ch - 1;
+
+	memcpy(conn.bssid, bss->bssid, 6);
+	memcpy(conn.dst_mac, bss->bssid, 6);
+	/*
+	 * FW don't support scan after connection attempt
+	 */
+	set_bit(wil_status_dontscan, &wil->status);
+
+	rc = wmi_send(wil, WMI_CONNECT_CMDID, &conn, sizeof(conn));
+	if (rc == 0) {
+		/* Connect can take lots of time */
+		mod_timer(&wil->connect_timer,
+			  jiffies + msecs_to_jiffies(2000));
+	}
+
+ out:
+	cfg80211_put_bss(bss);
+
+	return rc;
+}
+
+static int wil_cfg80211_disconnect(struct wiphy *wiphy,
+				   struct net_device *ndev,
+				   u16 reason_code)
+{
+	int rc;
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+	rc = wmi_send(wil, WMI_DISCONNECT_CMDID, NULL, 0);
+
+	return rc;
+}
+
+static int wil_cfg80211_set_channel(struct wiphy *wiphy,
+				    struct cfg80211_chan_def *chandef)
+{
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wireless_dev *wdev = wil->wdev;
+
+	wdev->preset_chandef = *chandef;
+
+	return 0;
+}
+
+static int wil_cfg80211_add_key(struct wiphy *wiphy,
+				struct net_device *ndev,
+				u8 key_index, bool pairwise,
+				const u8 *mac_addr,
+				struct key_params *params)
+{
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+	/* group key is not used */
+	if (!pairwise)
+		return 0;
+
+	return wmi_add_cipher_key(wil, key_index, mac_addr,
+				  params->key_len, params->key);
+}
+
+static int wil_cfg80211_del_key(struct wiphy *wiphy,
+				struct net_device *ndev,
+				u8 key_index, bool pairwise,
+				const u8 *mac_addr)
+{
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+
+	/* group key is not used */
+	if (!pairwise)
+		return 0;
+
+	return wmi_del_cipher_key(wil, key_index, mac_addr);
+}
+
+/* Need to be present or wiphy_new() will WARN */
+static int wil_cfg80211_set_default_key(struct wiphy *wiphy,
+					struct net_device *ndev,
+					u8 key_index, bool unicast,
+					bool multicast)
+{
+	return 0;
+}
+
+static int wil_cfg80211_start_ap(struct wiphy *wiphy,
+				 struct net_device *ndev,
+				 struct cfg80211_ap_settings *info)
+{
+	int rc = 0;
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wireless_dev *wdev = ndev->ieee80211_ptr;
+	struct ieee80211_channel *channel = info->chandef.chan;
+	struct cfg80211_beacon_data *bcon = &info->beacon;
+	u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
+
+	if (!channel) {
+		wil_err(wil, "AP: No channel???\n");
+		return -EINVAL;
+	}
+
+	wil_dbg(wil, "AP on Channel %d %d MHz, %s\n", channel->hw_value,
+		channel->center_freq, info->privacy ? "secure" : "open");
+	print_hex_dump_bytes("SSID ", DUMP_PREFIX_OFFSET,
+			     info->ssid, info->ssid_len);
+
+	rc = wil_reset(wil);
+	if (rc)
+		return rc;
+
+	rc = wmi_set_ssid(wil, info->ssid_len, info->ssid);
+	if (rc)
+		return rc;
+
+	rc = wmi_set_channel(wil, channel->hw_value);
+	if (rc)
+		return rc;
+
+	/* MAC address - pre-requisite for other commands */
+	wmi_set_mac_address(wil, ndev->dev_addr);
+
+	/* IE's */
+	/* bcon 'head IE's are not relevant for 60g band */
+	wmi_set_ie(wil, WMI_FRAME_BEACON, bcon->beacon_ies_len,
+		   bcon->beacon_ies);
+	wmi_set_ie(wil, WMI_FRAME_PROBE_RESP, bcon->proberesp_ies_len,
+		   bcon->proberesp_ies);
+	wmi_set_ie(wil, WMI_FRAME_ASSOC_RESP, bcon->assocresp_ies_len,
+		   bcon->assocresp_ies);
+
+	wil->secure_pcp = info->privacy;
+
+	rc = wmi_set_bcon(wil, info->beacon_interval, wmi_nettype);
+	if (rc)
+		return rc;
+
+	/* Rx VRING. After MAC and beacon */
+	rc = wil_rx_init(wil);
+
+	netif_carrier_on(ndev);
+
+	return rc;
+}
+
+static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
+				struct net_device *ndev)
+{
+	int rc = 0;
+	struct wil6210_priv *wil = wiphy_to_wil(wiphy);
+	struct wireless_dev *wdev = ndev->ieee80211_ptr;
+	u8 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
+
+	/* To stop beaconing, set BI to 0 */
+	rc = wmi_set_bcon(wil, 0, wmi_nettype);
+
+	return rc;
+}
+
+static struct cfg80211_ops wil_cfg80211_ops = {
+	.scan = wil_cfg80211_scan,
+	.connect = wil_cfg80211_connect,
+	.disconnect = wil_cfg80211_disconnect,
+	.change_virtual_intf = wil_cfg80211_change_iface,
+	.get_station = wil_cfg80211_get_station,
+	.set_monitor_channel = wil_cfg80211_set_channel,
+	.add_key = wil_cfg80211_add_key,
+	.del_key = wil_cfg80211_del_key,
+	.set_default_key = wil_cfg80211_set_default_key,
+	/* AP mode */
+	.start_ap = wil_cfg80211_start_ap,
+	.stop_ap = wil_cfg80211_stop_ap,
+};
+
+static void wil_wiphy_init(struct wiphy *wiphy)
+{
+	/* TODO: set real value */
+	wiphy->max_scan_ssids = 10;
+	wiphy->max_num_pmkids = 0 /* TODO: */;
+	wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
+				 BIT(NL80211_IFTYPE_AP) |
+				 BIT(NL80211_IFTYPE_MONITOR);
+	/* TODO: enable P2P when integrated with supplicant:
+	 * BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO)
+	 */
+	wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME |
+			WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD;
+	dev_warn(wiphy_dev(wiphy), "%s : flags = 0x%08x\n",
+		 __func__, wiphy->flags);
+	wiphy->probe_resp_offload =
+		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS |
+		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 |
+		NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P;
+
+	wiphy->bands[IEEE80211_BAND_60GHZ] = &wil_band_60ghz;
+
+	/* TODO: figure this out */
+	wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
+
+	wiphy->cipher_suites = wil_cipher_suites;
+	wiphy->n_cipher_suites = ARRAY_SIZE(wil_cipher_suites);
+	wiphy->mgmt_stypes = wil_mgmt_stypes;
+}
+
+struct wireless_dev *wil_cfg80211_init(struct device *dev)
+{
+	int rc = 0;
+	struct wireless_dev *wdev;
+
+	wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
+	if (!wdev)
+		return ERR_PTR(-ENOMEM);
+
+	wdev->wiphy = wiphy_new(&wil_cfg80211_ops,
+				sizeof(struct wil6210_priv));
+	if (!wdev->wiphy) {
+		rc = -ENOMEM;
+		goto out;
+	}
+
+	set_wiphy_dev(wdev->wiphy, dev);
+	wil_wiphy_init(wdev->wiphy);
+
+	rc = wiphy_register(wdev->wiphy);
+	if (rc < 0)
+		goto out_failed_reg;
+
+	return wdev;
+
+out_failed_reg:
+	wiphy_free(wdev->wiphy);
+out:
+	kfree(wdev);
+
+	return ERR_PTR(rc);
+}
+
+void wil_wdev_free(struct wil6210_priv *wil)
+{
+	struct wireless_dev *wdev = wil_to_wdev(wil);
+
+	if (!wdev)
+		return;
+
+	wiphy_unregister(wdev->wiphy);
+	wiphy_free(wdev->wiphy);
+	kfree(wdev);
+}
diff --git a/drivers/net/wireless/ath/wil6210/dbg_hexdump.h b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h
new file mode 100644
index 0000000..6a315ba
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/dbg_hexdump.h
@@ -0,0 +1,30 @@
+#ifndef WIL_DBG_HEXDUMP_H_
+#define WIL_DBG_HEXDUMP_H_
+
+#if defined(CONFIG_DYNAMIC_DEBUG)
+#define wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize,	\
+			     groupsize, buf, len, ascii)	\
+do {								\
+	DEFINE_DYNAMIC_DEBUG_METADATA(descriptor,		\
+		__builtin_constant_p(prefix_str) ? prefix_str : "hexdump");\
+	if (unlikely(descriptor.flags & _DPRINTK_FLAGS_PRINT))	\
+		print_hex_dump(KERN_DEBUG, prefix_str,		\
+			       prefix_type, rowsize, groupsize,	\
+			       buf, len, ascii);		\
+} while (0)
+
+#define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize,	\
+				 groupsize, buf, len, ascii)		\
+	wil_dynamic_hex_dump(prefix_str, prefix_type, rowsize,		\
+			     groupsize, buf, len, ascii)
+
+#define print_hex_dump_bytes(prefix_str, prefix_type, buf, len)	\
+	wil_dynamic_hex_dump(prefix_str, prefix_type, 16, 1, buf, len, true)
+#else /* defined(CONFIG_DYNAMIC_DEBUG) */
+#define wil_print_hex_dump_debug(prefix_str, prefix_type, rowsize,	\
+				 groupsize, buf, len, ascii)		\
+	print_hex_dump(KERN_DEBUG, prefix_str, prefix_type, rowsize,	\
+		       groupsize, buf, len, ascii)
+#endif /* defined(CONFIG_DYNAMIC_DEBUG) */
+
+#endif /* WIL_DBG_HEXDUMP_H_ */
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
new file mode 100644
index 0000000..65fc968
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -0,0 +1,603 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/debugfs.h>
+#include <linux/seq_file.h>
+#include <linux/pci.h>
+#include <linux/rtnetlink.h>
+
+#include "wil6210.h"
+#include "txrx.h"
+
+/* Nasty hack. Better have per device instances */
+static u32 mem_addr;
+static u32 dbg_txdesc_index;
+
+static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
+			    const char *name, struct vring *vring)
+{
+	void __iomem *x = wmi_addr(wil, vring->hwtail);
+
+	seq_printf(s, "VRING %s = {\n", name);
+	seq_printf(s, "  pa     = 0x%016llx\n", (unsigned long long)vring->pa);
+	seq_printf(s, "  va     = 0x%p\n", vring->va);
+	seq_printf(s, "  size   = %d\n", vring->size);
+	seq_printf(s, "  swtail = %d\n", vring->swtail);
+	seq_printf(s, "  swhead = %d\n", vring->swhead);
+	seq_printf(s, "  hwtail = [0x%08x] -> ", vring->hwtail);
+	if (x)
+		seq_printf(s, "0x%08x\n", ioread32(x));
+	else
+		seq_printf(s, "???\n");
+
+	if (vring->va && (vring->size < 1025)) {
+		uint i;
+		for (i = 0; i < vring->size; i++) {
+			volatile struct vring_tx_desc *d = &vring->va[i].tx;
+			if ((i % 64) == 0 && (i != 0))
+				seq_printf(s, "\n");
+			seq_printf(s, "%s", (d->dma.status & BIT(0)) ?
+					"S" : (vring->ctx[i] ? "H" : "h"));
+		}
+		seq_printf(s, "\n");
+	}
+	seq_printf(s, "}\n");
+}
+
+static int wil_vring_debugfs_show(struct seq_file *s, void *data)
+{
+	uint i;
+	struct wil6210_priv *wil = s->private;
+
+	wil_print_vring(s, wil, "rx", &wil->vring_rx);
+
+	for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
+		struct vring *vring = &(wil->vring_tx[i]);
+		if (vring->va) {
+			char name[10];
+			snprintf(name, sizeof(name), "tx_%2d", i);
+			wil_print_vring(s, wil, name, vring);
+		}
+	}
+
+	return 0;
+}
+
+static int wil_vring_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_vring_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_vring = {
+	.open		= wil_vring_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+
+static void wil_print_ring(struct seq_file *s, const char *prefix,
+			   void __iomem *off)
+{
+	struct wil6210_priv *wil = s->private;
+	struct wil6210_mbox_ring r;
+	int rsize;
+	uint i;
+
+	wil_memcpy_fromio_32(&r, off, sizeof(r));
+	wil_mbox_ring_le2cpus(&r);
+	/*
+	 * we just read memory block from NIC. This memory may be
+	 * garbage. Check validity before using it.
+	 */
+	rsize = r.size / sizeof(struct wil6210_mbox_ring_desc);
+
+	seq_printf(s, "ring %s = {\n", prefix);
+	seq_printf(s, "  base = 0x%08x\n", r.base);
+	seq_printf(s, "  size = 0x%04x bytes -> %d entries\n", r.size, rsize);
+	seq_printf(s, "  tail = 0x%08x\n", r.tail);
+	seq_printf(s, "  head = 0x%08x\n", r.head);
+	seq_printf(s, "  entry size = %d\n", r.entry_size);
+
+	if (r.size % sizeof(struct wil6210_mbox_ring_desc)) {
+		seq_printf(s, "  ??? size is not multiple of %zd, garbage?\n",
+			   sizeof(struct wil6210_mbox_ring_desc));
+		goto out;
+	}
+
+	if (!wmi_addr(wil, r.base) ||
+	    !wmi_addr(wil, r.tail) ||
+	    !wmi_addr(wil, r.head)) {
+		seq_printf(s, "  ??? pointers are garbage?\n");
+		goto out;
+	}
+
+	for (i = 0; i < rsize; i++) {
+		struct wil6210_mbox_ring_desc d;
+		struct wil6210_mbox_hdr hdr;
+		size_t delta = i * sizeof(d);
+		void __iomem *x = wil->csr + HOSTADDR(r.base) + delta;
+
+		wil_memcpy_fromio_32(&d, x, sizeof(d));
+
+		seq_printf(s, "  [%2x] %s %s%s 0x%08x", i,
+			   d.sync ? "F" : "E",
+			   (r.tail - r.base == delta) ? "t" : " ",
+			   (r.head - r.base == delta) ? "h" : " ",
+			   le32_to_cpu(d.addr));
+		if (0 == wmi_read_hdr(wil, d.addr, &hdr)) {
+			u16 len = le16_to_cpu(hdr.len);
+			seq_printf(s, " -> %04x %04x %04x %02x\n",
+				   le16_to_cpu(hdr.seq), len,
+				   le16_to_cpu(hdr.type), hdr.flags);
+			if (len <= MAX_MBOXITEM_SIZE) {
+				int n = 0;
+				unsigned char printbuf[16 * 3 + 2];
+				unsigned char databuf[MAX_MBOXITEM_SIZE];
+				void __iomem *src = wmi_buffer(wil, d.addr) +
+					sizeof(struct wil6210_mbox_hdr);
+				/*
+				 * No need to check @src for validity -
+				 * we already validated @d.addr while
+				 * reading header
+				 */
+				wil_memcpy_fromio_32(databuf, src, len);
+				while (n < len) {
+					int l = min(len - n, 16);
+					hex_dump_to_buffer(databuf + n, l,
+							   16, 1, printbuf,
+							   sizeof(printbuf),
+							   false);
+					seq_printf(s, "      : %s\n", printbuf);
+					n += l;
+				}
+			}
+		} else {
+			seq_printf(s, "\n");
+		}
+	}
+ out:
+	seq_printf(s, "}\n");
+}
+
+static int wil_mbox_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+
+	wil_print_ring(s, "tx", wil->csr + HOST_MBOX +
+		       offsetof(struct wil6210_mbox_ctl, tx));
+	wil_print_ring(s, "rx", wil->csr + HOST_MBOX +
+		       offsetof(struct wil6210_mbox_ctl, rx));
+
+	return 0;
+}
+
+static int wil_mbox_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_mbox_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_mbox = {
+	.open		= wil_mbox_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+
+static int wil_debugfs_iomem_x32_set(void *data, u64 val)
+{
+	iowrite32(val, (void __iomem *)data);
+	wmb(); /* make sure write propagated to HW */
+
+	return 0;
+}
+
+static int wil_debugfs_iomem_x32_get(void *data, u64 *val)
+{
+	*val = ioread32((void __iomem *)data);
+
+	return 0;
+}
+
+DEFINE_SIMPLE_ATTRIBUTE(fops_iomem_x32, wil_debugfs_iomem_x32_get,
+			wil_debugfs_iomem_x32_set, "0x%08llx\n");
+
+static struct dentry *wil_debugfs_create_iomem_x32(const char *name,
+						   mode_t mode,
+						   struct dentry *parent,
+						   void __iomem *value)
+{
+	return debugfs_create_file(name, mode, parent, (void * __force)value,
+				   &fops_iomem_x32);
+}
+
+static int wil6210_debugfs_create_ISR(struct wil6210_priv *wil,
+				      const char *name,
+				      struct dentry *parent, u32 off)
+{
+	struct dentry *d = debugfs_create_dir(name, parent);
+
+	if (IS_ERR_OR_NULL(d))
+		return -ENODEV;
+
+	wil_debugfs_create_iomem_x32("ICC", S_IRUGO | S_IWUSR, d,
+				     wil->csr + off);
+	wil_debugfs_create_iomem_x32("ICR", S_IRUGO | S_IWUSR, d,
+				     wil->csr + off + 4);
+	wil_debugfs_create_iomem_x32("ICM", S_IRUGO | S_IWUSR, d,
+				     wil->csr + off + 8);
+	wil_debugfs_create_iomem_x32("ICS", S_IWUSR, d,
+				     wil->csr + off + 12);
+	wil_debugfs_create_iomem_x32("IMV", S_IRUGO | S_IWUSR, d,
+				     wil->csr + off + 16);
+	wil_debugfs_create_iomem_x32("IMS", S_IWUSR, d,
+				     wil->csr + off + 20);
+	wil_debugfs_create_iomem_x32("IMC", S_IWUSR, d,
+				     wil->csr + off + 24);
+
+	return 0;
+}
+
+static int wil6210_debugfs_create_pseudo_ISR(struct wil6210_priv *wil,
+					     struct dentry *parent)
+{
+	struct dentry *d = debugfs_create_dir("PSEUDO_ISR", parent);
+
+	if (IS_ERR_OR_NULL(d))
+		return -ENODEV;
+
+	wil_debugfs_create_iomem_x32("CAUSE", S_IRUGO, d, wil->csr +
+				     HOSTADDR(RGF_DMA_PSEUDO_CAUSE));
+	wil_debugfs_create_iomem_x32("MASK_SW", S_IRUGO, d, wil->csr +
+				     HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
+	wil_debugfs_create_iomem_x32("MASK_FW", S_IRUGO, d, wil->csr +
+				     HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_FW));
+
+	return 0;
+}
+
+static int wil6210_debugfs_create_ITR_CNT(struct wil6210_priv *wil,
+					  struct dentry *parent)
+{
+	struct dentry *d = debugfs_create_dir("ITR_CNT", parent);
+
+	if (IS_ERR_OR_NULL(d))
+		return -ENODEV;
+
+	wil_debugfs_create_iomem_x32("TRSH", S_IRUGO, d, wil->csr +
+				     HOSTADDR(RGF_DMA_ITR_CNT_TRSH));
+	wil_debugfs_create_iomem_x32("DATA", S_IRUGO, d, wil->csr +
+				     HOSTADDR(RGF_DMA_ITR_CNT_DATA));
+	wil_debugfs_create_iomem_x32("CTL", S_IRUGO, d, wil->csr +
+				     HOSTADDR(RGF_DMA_ITR_CNT_CRL));
+
+	return 0;
+}
+
+static int wil_memread_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+	void __iomem *a = wmi_buffer(wil, cpu_to_le32(mem_addr));
+
+	if (a)
+		seq_printf(s, "[0x%08x] = 0x%08x\n", mem_addr, ioread32(a));
+	else
+		seq_printf(s, "[0x%08x] = INVALID\n", mem_addr);
+
+	return 0;
+}
+
+static int wil_memread_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_memread_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_memread = {
+	.open		= wil_memread_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+
+static int wil_default_open(struct inode *inode, struct file *file)
+{
+	if (inode->i_private)
+		file->private_data = inode->i_private;
+
+	return 0;
+}
+
+static ssize_t wil_read_file_ioblob(struct file *file, char __user *user_buf,
+				size_t count, loff_t *ppos)
+{
+	enum { max_count = 4096 };
+	struct debugfs_blob_wrapper *blob = file->private_data;
+	loff_t pos = *ppos;
+	size_t available = blob->size;
+	void *buf;
+	size_t ret;
+
+	if (pos < 0)
+		return -EINVAL;
+
+	if (pos >= available || !count)
+		return 0;
+
+	if (count > available - pos)
+		count = available - pos;
+	if (count > max_count)
+		count = max_count;
+
+	buf = kmalloc(count, GFP_KERNEL);
+	if (!buf)
+		return -ENOMEM;
+
+	wil_memcpy_fromio_32(buf, (const volatile void __iomem *)blob->data +
+			     pos, count);
+
+	ret = copy_to_user(user_buf, buf, count);
+	kfree(buf);
+	if (ret == count)
+		return -EFAULT;
+
+	count -= ret;
+	*ppos = pos + count;
+
+	return count;
+}
+
+static const struct file_operations fops_ioblob = {
+	.read =		wil_read_file_ioblob,
+	.open =		wil_default_open,
+	.llseek =	default_llseek,
+};
+
+static
+struct dentry *wil_debugfs_create_ioblob(const char *name,
+					 mode_t mode,
+					 struct dentry *parent,
+					 struct debugfs_blob_wrapper *blob)
+{
+	return debugfs_create_file(name, mode, parent, blob, &fops_ioblob);
+}
+/*---reset---*/
+static ssize_t wil_write_file_reset(struct file *file, const char __user *buf,
+				    size_t len, loff_t *ppos)
+{
+	struct wil6210_priv *wil = file->private_data;
+	struct net_device *ndev = wil_to_ndev(wil);
+
+	/**
+	 * BUG:
+	 * this code does NOT sync device state with the rest of system
+	 * use with care, debug only!!!
+	 */
+	rtnl_lock();
+	dev_close(ndev);
+	ndev->flags &= ~IFF_UP;
+	rtnl_unlock();
+	wil_reset(wil);
+
+	return len;
+}
+
+static const struct file_operations fops_reset = {
+	.write = wil_write_file_reset,
+	.open  = wil_default_open,
+};
+/*---------Tx descriptor------------*/
+
+static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+	struct vring *vring = &(wil->vring_tx[0]);
+
+	if (!vring->va) {
+		seq_printf(s, "No Tx VRING\n");
+		return 0;
+	}
+
+	if (dbg_txdesc_index < vring->size) {
+		volatile struct vring_tx_desc *d =
+				&(vring->va[dbg_txdesc_index].tx);
+		volatile u32 *u = (volatile u32 *)d;
+		struct sk_buff *skb = vring->ctx[dbg_txdesc_index];
+
+		seq_printf(s, "Tx[%3d] = {\n", dbg_txdesc_index);
+		seq_printf(s, "  MAC = 0x%08x 0x%08x 0x%08x 0x%08x\n",
+			   u[0], u[1], u[2], u[3]);
+		seq_printf(s, "  DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
+			   u[4], u[5], u[6], u[7]);
+		seq_printf(s, "  SKB = %p\n", skb);
+
+		if (skb) {
+			unsigned char printbuf[16 * 3 + 2];
+			int i = 0;
+			int len = skb_headlen(skb);
+			void *p = skb->data;
+
+			seq_printf(s, "    len = %d\n", len);
+
+			while (i < len) {
+				int l = min(len - i, 16);
+				hex_dump_to_buffer(p + i, l, 16, 1, printbuf,
+						   sizeof(printbuf), false);
+				seq_printf(s, "      : %s\n", printbuf);
+				i += l;
+			}
+		}
+		seq_printf(s, "}\n");
+	} else {
+		seq_printf(s, "TxDesc index (%d) >= size (%d)\n",
+			   dbg_txdesc_index, vring->size);
+	}
+
+	return 0;
+}
+
+static int wil_txdesc_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_txdesc_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_txdesc = {
+	.open		= wil_txdesc_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+
+/*---------beamforming------------*/
+static int wil_bf_debugfs_show(struct seq_file *s, void *data)
+{
+	struct wil6210_priv *wil = s->private;
+	seq_printf(s,
+		   "TSF : 0x%016llx\n"
+		   "TxMCS : %d\n"
+		   "Sectors(rx:tx) my %2d:%2d peer %2d:%2d\n",
+		   wil->stats.tsf, wil->stats.bf_mcs,
+		   wil->stats.my_rx_sector, wil->stats.my_tx_sector,
+		   wil->stats.peer_rx_sector, wil->stats.peer_tx_sector);
+	return 0;
+}
+
+static int wil_bf_seq_open(struct inode *inode, struct file *file)
+{
+	return single_open(file, wil_bf_debugfs_show, inode->i_private);
+}
+
+static const struct file_operations fops_bf = {
+	.open		= wil_bf_seq_open,
+	.release	= single_release,
+	.read		= seq_read,
+	.llseek		= seq_lseek,
+};
+/*---------SSID------------*/
+static ssize_t wil_read_file_ssid(struct file *file, char __user *user_buf,
+				  size_t count, loff_t *ppos)
+{
+	struct wil6210_priv *wil = file->private_data;
+	struct wireless_dev *wdev = wil_to_wdev(wil);
+
+	return simple_read_from_buffer(user_buf, count, ppos,
+				       wdev->ssid, wdev->ssid_len);
+}
+
+static ssize_t wil_write_file_ssid(struct file *file, const char __user *buf,
+				   size_t count, loff_t *ppos)
+{
+	struct wil6210_priv *wil = file->private_data;
+	struct wireless_dev *wdev = wil_to_wdev(wil);
+	struct net_device *ndev = wil_to_ndev(wil);
+
+	if (*ppos != 0) {
+		wil_err(wil, "Unable to set SSID substring from [%d]\n",
+			(int)*ppos);
+		return -EINVAL;
+	}
+
+	if (count > sizeof(wdev->ssid)) {
+		wil_err(wil, "SSID too long, len = %d\n", (int)count);
+		return -EINVAL;
+	}
+	if (netif_running(ndev)) {
+		wil_err(wil, "Unable to change SSID on running interface\n");
+		return -EINVAL;
+	}
+
+	wdev->ssid_len = count;
+	return simple_write_to_buffer(wdev->ssid, wdev->ssid_len, ppos,
+				      buf, count);
+}
+
+static const struct file_operations fops_ssid = {
+	.read = wil_read_file_ssid,
+	.write = wil_write_file_ssid,
+	.open  = wil_default_open,
+};
+
+/*----------------*/
+int wil6210_debugfs_init(struct wil6210_priv *wil)
+{
+	struct dentry *dbg = wil->debug = debugfs_create_dir(WIL_NAME,
+			wil_to_wiphy(wil)->debugfsdir);
+
+	if (IS_ERR_OR_NULL(dbg))
+		return -ENODEV;
+
+	debugfs_create_file("mbox", S_IRUGO, dbg, wil, &fops_mbox);
+	debugfs_create_file("vrings", S_IRUGO, dbg, wil, &fops_vring);
+	debugfs_create_file("txdesc", S_IRUGO, dbg, wil, &fops_txdesc);
+	debugfs_create_u32("txdesc_index", S_IRUGO | S_IWUSR, dbg,
+			   &dbg_txdesc_index);
+	debugfs_create_file("bf", S_IRUGO, dbg, wil, &fops_bf);
+	debugfs_create_file("ssid", S_IRUGO | S_IWUSR, dbg, wil, &fops_ssid);
+	debugfs_create_u32("secure_pcp", S_IRUGO | S_IWUSR, dbg,
+			   &wil->secure_pcp);
+
+	wil6210_debugfs_create_ISR(wil, "USER_ICR", dbg,
+				   HOSTADDR(RGF_USER_USER_ICR));
+	wil6210_debugfs_create_ISR(wil, "DMA_EP_TX_ICR", dbg,
+				   HOSTADDR(RGF_DMA_EP_TX_ICR));
+	wil6210_debugfs_create_ISR(wil, "DMA_EP_RX_ICR", dbg,
+				   HOSTADDR(RGF_DMA_EP_RX_ICR));
+	wil6210_debugfs_create_ISR(wil, "DMA_EP_MISC_ICR", dbg,
+				   HOSTADDR(RGF_DMA_EP_MISC_ICR));
+	wil6210_debugfs_create_pseudo_ISR(wil, dbg);
+	wil6210_debugfs_create_ITR_CNT(wil, dbg);
+
+	debugfs_create_u32("mem_addr", S_IRUGO | S_IWUSR, dbg, &mem_addr);
+	debugfs_create_file("mem_val", S_IRUGO, dbg, wil, &fops_memread);
+
+	debugfs_create_file("reset", S_IWUSR, dbg, wil, &fops_reset);
+
+	wil->rgf_blob.data = (void * __force)wil->csr + 0;
+	wil->rgf_blob.size = 0xa000;
+	wil_debugfs_create_ioblob("blob_rgf", S_IRUGO, dbg, &wil->rgf_blob);
+
+	wil->fw_code_blob.data = (void * __force)wil->csr + 0x40000;
+	wil->fw_code_blob.size = 0x40000;
+	wil_debugfs_create_ioblob("blob_fw_code", S_IRUGO, dbg,
+				  &wil->fw_code_blob);
+
+	wil->fw_data_blob.data = (void * __force)wil->csr + 0x80000;
+	wil->fw_data_blob.size = 0x8000;
+	wil_debugfs_create_ioblob("blob_fw_data", S_IRUGO, dbg,
+				  &wil->fw_data_blob);
+
+	wil->fw_peri_blob.data = (void * __force)wil->csr + 0x88000;
+	wil->fw_peri_blob.size = 0x18000;
+	wil_debugfs_create_ioblob("blob_fw_peri", S_IRUGO, dbg,
+				  &wil->fw_peri_blob);
+
+	wil->uc_code_blob.data = (void * __force)wil->csr + 0xa0000;
+	wil->uc_code_blob.size = 0x10000;
+	wil_debugfs_create_ioblob("blob_uc_code", S_IRUGO, dbg,
+				  &wil->uc_code_blob);
+
+	wil->uc_data_blob.data = (void * __force)wil->csr + 0xb0000;
+	wil->uc_data_blob.size = 0x4000;
+	wil_debugfs_create_ioblob("blob_uc_data", S_IRUGO, dbg,
+				  &wil->uc_data_blob);
+
+	return 0;
+}
+
+void wil6210_debugfs_remove(struct wil6210_priv *wil)
+{
+	debugfs_remove_recursive(wil->debug);
+	wil->debug = NULL;
+}
diff --git a/drivers/net/wireless/ath/wil6210/interrupt.c b/drivers/net/wireless/ath/wil6210/interrupt.c
new file mode 100644
index 0000000..38049da
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/interrupt.c
@@ -0,0 +1,471 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/interrupt.h>
+
+#include "wil6210.h"
+
+/**
+ * Theory of operation:
+ *
+ * There is ISR pseudo-cause register,
+ * dma_rgf->DMA_RGF.PSEUDO_CAUSE.PSEUDO_CAUSE
+ * Its bits represents OR'ed bits from 3 real ISR registers:
+ * TX, RX, and MISC.
+ *
+ * Registers may be configured to either "write 1 to clear" or
+ * "clear on read" mode
+ *
+ * When handling interrupt, one have to mask/unmask interrupts for the
+ * real ISR registers, or hardware may malfunction.
+ *
+ */
+
+#define WIL6210_IRQ_DISABLE	(0xFFFFFFFFUL)
+#define WIL6210_IMC_RX		BIT_DMA_EP_RX_ICR_RX_DONE
+#define WIL6210_IMC_TX		(BIT_DMA_EP_TX_ICR_TX_DONE | \
+				BIT_DMA_EP_TX_ICR_TX_DONE_N(0))
+#define WIL6210_IMC_MISC	(ISR_MISC_FW_READY | ISR_MISC_MBOX_EVT)
+
+#define WIL6210_IRQ_PSEUDO_MASK (u32)(~(BIT_DMA_PSEUDO_CAUSE_RX | \
+					BIT_DMA_PSEUDO_CAUSE_TX | \
+					BIT_DMA_PSEUDO_CAUSE_MISC))
+
+#if defined(CONFIG_WIL6210_ISR_COR)
+/* configure to Clear-On-Read mode */
+#define WIL_ICR_ICC_VALUE	(0xFFFFFFFFUL)
+
+static inline void wil_icr_clear(u32 x, void __iomem *addr)
+{
+
+}
+#else /* defined(CONFIG_WIL6210_ISR_COR) */
+/* configure to Write-1-to-Clear mode */
+#define WIL_ICR_ICC_VALUE	(0UL)
+
+static inline void wil_icr_clear(u32 x, void __iomem *addr)
+{
+	iowrite32(x, addr);
+}
+#endif /* defined(CONFIG_WIL6210_ISR_COR) */
+
+static inline u32 wil_ioread32_and_clear(void __iomem *addr)
+{
+	u32 x = ioread32(addr);
+
+	wil_icr_clear(x, addr);
+
+	return x;
+}
+
+static void wil6210_mask_irq_tx(struct wil6210_priv *wil)
+{
+	iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
+		  HOSTADDR(RGF_DMA_EP_TX_ICR) +
+		  offsetof(struct RGF_ICR, IMS));
+}
+
+static void wil6210_mask_irq_rx(struct wil6210_priv *wil)
+{
+	iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
+		  HOSTADDR(RGF_DMA_EP_RX_ICR) +
+		  offsetof(struct RGF_ICR, IMS));
+}
+
+static void wil6210_mask_irq_misc(struct wil6210_priv *wil)
+{
+	iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
+		  HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+		  offsetof(struct RGF_ICR, IMS));
+}
+
+static void wil6210_mask_irq_pseudo(struct wil6210_priv *wil)
+{
+	wil_dbg_IRQ(wil, "%s()\n", __func__);
+
+	iowrite32(WIL6210_IRQ_DISABLE, wil->csr +
+		  HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
+
+	clear_bit(wil_status_irqen, &wil->status);
+}
+
+static void wil6210_unmask_irq_tx(struct wil6210_priv *wil)
+{
+	iowrite32(WIL6210_IMC_TX, wil->csr +
+		  HOSTADDR(RGF_DMA_EP_TX_ICR) +
+		  offsetof(struct RGF_ICR, IMC));
+}
+
+static void wil6210_unmask_irq_rx(struct wil6210_priv *wil)
+{
+	iowrite32(WIL6210_IMC_RX, wil->csr +
+		  HOSTADDR(RGF_DMA_EP_RX_ICR) +
+		  offsetof(struct RGF_ICR, IMC));
+}
+
+static void wil6210_unmask_irq_misc(struct wil6210_priv *wil)
+{
+	iowrite32(WIL6210_IMC_MISC, wil->csr +
+		  HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+		  offsetof(struct RGF_ICR, IMC));
+}
+
+static void wil6210_unmask_irq_pseudo(struct wil6210_priv *wil)
+{
+	wil_dbg_IRQ(wil, "%s()\n", __func__);
+
+	set_bit(wil_status_irqen, &wil->status);
+
+	iowrite32(WIL6210_IRQ_PSEUDO_MASK, wil->csr +
+		  HOSTADDR(RGF_DMA_PSEUDO_CAUSE_MASK_SW));
+}
+
+void wil6210_disable_irq(struct wil6210_priv *wil)
+{
+	wil_dbg_IRQ(wil, "%s()\n", __func__);
+
+	wil6210_mask_irq_tx(wil);
+	wil6210_mask_irq_rx(wil);
+	wil6210_mask_irq_misc(wil);
+	wil6210_mask_irq_pseudo(wil);
+}
+
+void wil6210_enable_irq(struct wil6210_priv *wil)
+{
+	wil_dbg_IRQ(wil, "%s()\n", __func__);
+
+	iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_RX_ICR) +
+		  offsetof(struct RGF_ICR, ICC));
+	iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_TX_ICR) +
+		  offsetof(struct RGF_ICR, ICC));
+	iowrite32(WIL_ICR_ICC_VALUE, wil->csr + HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+		  offsetof(struct RGF_ICR, ICC));
+
+	wil6210_unmask_irq_pseudo(wil);
+	wil6210_unmask_irq_tx(wil);
+	wil6210_unmask_irq_rx(wil);
+	wil6210_unmask_irq_misc(wil);
+}
+
+static irqreturn_t wil6210_irq_rx(int irq, void *cookie)
+{
+	struct wil6210_priv *wil = cookie;
+	u32 isr = wil_ioread32_and_clear(wil->csr +
+					 HOSTADDR(RGF_DMA_EP_RX_ICR) +
+					 offsetof(struct RGF_ICR, ICR));
+
+	wil_dbg_IRQ(wil, "ISR RX 0x%08x\n", isr);
+
+	if (!isr) {
+		wil_err(wil, "spurious IRQ: RX\n");
+		return IRQ_NONE;
+	}
+
+	wil6210_mask_irq_rx(wil);
+
+	if (isr & BIT_DMA_EP_RX_ICR_RX_DONE) {
+		wil_dbg_IRQ(wil, "RX done\n");
+		isr &= ~BIT_DMA_EP_RX_ICR_RX_DONE;
+		wil_rx_handle(wil);
+	}
+
+	if (isr)
+		wil_err(wil, "un-handled RX ISR bits 0x%08x\n", isr);
+
+	wil6210_unmask_irq_rx(wil);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wil6210_irq_tx(int irq, void *cookie)
+{
+	struct wil6210_priv *wil = cookie;
+	u32 isr = wil_ioread32_and_clear(wil->csr +
+					 HOSTADDR(RGF_DMA_EP_TX_ICR) +
+					 offsetof(struct RGF_ICR, ICR));
+
+	wil_dbg_IRQ(wil, "ISR TX 0x%08x\n", isr);
+
+	if (!isr) {
+		wil_err(wil, "spurious IRQ: TX\n");
+		return IRQ_NONE;
+	}
+
+	wil6210_mask_irq_tx(wil);
+
+	if (isr & BIT_DMA_EP_TX_ICR_TX_DONE) {
+		uint i;
+		wil_dbg_IRQ(wil, "TX done\n");
+		isr &= ~BIT_DMA_EP_TX_ICR_TX_DONE;
+		for (i = 0; i < 24; i++) {
+			u32 mask = BIT_DMA_EP_TX_ICR_TX_DONE_N(i);
+			if (isr & mask) {
+				isr &= ~mask;
+				wil_dbg_IRQ(wil, "TX done(%i)\n", i);
+				wil_tx_complete(wil, i);
+			}
+		}
+	}
+
+	if (isr)
+		wil_err(wil, "un-handled TX ISR bits 0x%08x\n", isr);
+
+	wil6210_unmask_irq_tx(wil);
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t wil6210_irq_misc(int irq, void *cookie)
+{
+	struct wil6210_priv *wil = cookie;
+	u32 isr = wil_ioread32_and_clear(wil->csr +
+					 HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+					 offsetof(struct RGF_ICR, ICR));
+
+	wil_dbg_IRQ(wil, "ISR MISC 0x%08x\n", isr);
+
+	if (!isr) {
+		wil_err(wil, "spurious IRQ: MISC\n");
+		return IRQ_NONE;
+	}
+
+	wil6210_mask_irq_misc(wil);
+
+	if (isr & ISR_MISC_FW_READY) {
+		wil_dbg_IRQ(wil, "IRQ: FW ready\n");
+		/**
+		 * Actual FW ready indicated by the
+		 * WMI_FW_READY_EVENTID
+		 */
+		isr &= ~ISR_MISC_FW_READY;
+	}
+
+	wil->isr_misc = isr;
+
+	if (isr) {
+		return IRQ_WAKE_THREAD;
+	} else {
+		wil6210_unmask_irq_misc(wil);
+		return IRQ_HANDLED;
+	}
+}
+
+static irqreturn_t wil6210_irq_misc_thread(int irq, void *cookie)
+{
+	struct wil6210_priv *wil = cookie;
+	u32 isr = wil->isr_misc;
+
+	wil_dbg_IRQ(wil, "Thread ISR MISC 0x%08x\n", isr);
+
+	if (isr & ISR_MISC_MBOX_EVT) {
+		wil_dbg_IRQ(wil, "MBOX event\n");
+		wmi_recv_cmd(wil);
+		isr &= ~ISR_MISC_MBOX_EVT;
+	}
+
+	if (isr)
+		wil_err(wil, "un-handled MISC ISR bits 0x%08x\n", isr);
+
+	wil->isr_misc = 0;
+
+	wil6210_unmask_irq_misc(wil);
+
+	return IRQ_HANDLED;
+}
+
+/**
+ * thread IRQ handler
+ */
+static irqreturn_t wil6210_thread_irq(int irq, void *cookie)
+{
+	struct wil6210_priv *wil = cookie;
+
+	wil_dbg_IRQ(wil, "Thread IRQ\n");
+	/* Discover real IRQ cause */
+	if (wil->isr_misc)
+		wil6210_irq_misc_thread(irq, cookie);
+
+	wil6210_unmask_irq_pseudo(wil);
+
+	return IRQ_HANDLED;
+}
+
+/* DEBUG
+ * There is subtle bug in hardware that causes IRQ to raise when it should be
+ * masked. It is quite rare and hard to debug.
+ *
+ * Catch irq issue if it happens and print all I can.
+ */
+static int wil6210_debug_irq_mask(struct wil6210_priv *wil, u32 pseudo_cause)
+{
+	if (!test_bit(wil_status_irqen, &wil->status)) {
+		u32 icm_rx = wil_ioread32_and_clear(wil->csr +
+				HOSTADDR(RGF_DMA_EP_RX_ICR) +
+				offsetof(struct RGF_ICR, ICM));
+		u32 icr_rx = wil_ioread32_and_clear(wil->csr +
+				HOSTADDR(RGF_DMA_EP_RX_ICR) +
+				offsetof(struct RGF_ICR, ICR));
+		u32 imv_rx = ioread32(wil->csr +
+				HOSTADDR(RGF_DMA_EP_RX_ICR) +
+				offsetof(struct RGF_ICR, IMV));
+		u32 icm_tx = wil_ioread32_and_clear(wil->csr +
+				HOSTADDR(RGF_DMA_EP_TX_ICR) +
+				offsetof(struct RGF_ICR, ICM));
+		u32 icr_tx = wil_ioread32_and_clear(wil->csr +
+				HOSTADDR(RGF_DMA_EP_TX_ICR) +
+				offsetof(struct RGF_ICR, ICR));
+		u32 imv_tx = ioread32(wil->csr +
+				HOSTADDR(RGF_DMA_EP_TX_ICR) +
+				offsetof(struct RGF_ICR, IMV));
+		u32 icm_misc = wil_ioread32_and_clear(wil->csr +
+				HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+				offsetof(struct RGF_ICR, ICM));
+		u32 icr_misc = wil_ioread32_and_clear(wil->csr +
+				HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+				offsetof(struct RGF_ICR, ICR));
+		u32 imv_misc = ioread32(wil->csr +
+				HOSTADDR(RGF_DMA_EP_MISC_ICR) +
+				offsetof(struct RGF_ICR, IMV));
+		wil_err(wil, "IRQ when it should be masked: pseudo 0x%08x\n"
+				"Rx   icm:icr:imv 0x%08x 0x%08x 0x%08x\n"
+				"Tx   icm:icr:imv 0x%08x 0x%08x 0x%08x\n"
+				"Misc icm:icr:imv 0x%08x 0x%08x 0x%08x\n",
+				pseudo_cause,
+				icm_rx, icr_rx, imv_rx,
+				icm_tx, icr_tx, imv_tx,
+				icm_misc, icr_misc, imv_misc);
+
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+static irqreturn_t wil6210_hardirq(int irq, void *cookie)
+{
+	irqreturn_t rc = IRQ_HANDLED;
+	struct wil6210_priv *wil = cookie;
+	u32 pseudo_cause = ioread32(wil->csr + HOSTADDR(RGF_DMA_PSEUDO_CAUSE));
+
+	/**
+	 * pseudo_cause is Clear-On-Read, no need to ACK
+	 */
+	if ((pseudo_cause == 0) || ((pseudo_cause & 0xff) == 0xff))
+		return IRQ_NONE;
+
+	/* FIXME: IRQ mask debug */
+	if (wil6210_debug_irq_mask(wil, pseudo_cause))
+		return IRQ_NONE;
+
+	wil6210_mask_irq_pseudo(wil);
+
+	/* Discover real IRQ cause
+	 * There are 2 possible phases for every IRQ:
+	 * - hard IRQ handler called right here
+	 * - threaded handler called later
+	 *
+	 * Hard IRQ handler reads and clears ISR.
+	 *
+	 * If threaded handler requested, hard IRQ handler
+	 * returns IRQ_WAKE_THREAD and saves ISR register value
+	 * for the threaded handler use.
+	 *
+	 * voting for wake thread - need at least 1 vote
+	 */
+	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_RX) &&
+	    (wil6210_irq_rx(irq, cookie) == IRQ_WAKE_THREAD))
+		rc = IRQ_WAKE_THREAD;
+
+	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_TX) &&
+	    (wil6210_irq_tx(irq, cookie) == IRQ_WAKE_THREAD))
+		rc = IRQ_WAKE_THREAD;
+
+	if ((pseudo_cause & BIT_DMA_PSEUDO_CAUSE_MISC) &&
+	    (wil6210_irq_misc(irq, cookie) == IRQ_WAKE_THREAD))
+		rc = IRQ_WAKE_THREAD;
+
+	/* if thread is requested, it will unmask IRQ */
+	if (rc != IRQ_WAKE_THREAD)
+		wil6210_unmask_irq_pseudo(wil);
+
+	wil_dbg_IRQ(wil, "Hard IRQ 0x%08x\n", pseudo_cause);
+
+	return rc;
+}
+
+static int wil6210_request_3msi(struct wil6210_priv *wil, int irq)
+{
+	int rc;
+	/*
+	 * IRQ's are in the following order:
+	 * - Tx
+	 * - Rx
+	 * - Misc
+	 */
+
+	rc = request_irq(irq, wil6210_irq_tx, IRQF_SHARED,
+			 WIL_NAME"_tx", wil);
+	if (rc)
+		return rc;
+
+	rc = request_irq(irq + 1, wil6210_irq_rx, IRQF_SHARED,
+			 WIL_NAME"_rx", wil);
+	if (rc)
+		goto free0;
+
+	rc = request_threaded_irq(irq + 2, wil6210_irq_misc,
+				  wil6210_irq_misc_thread,
+				  IRQF_SHARED, WIL_NAME"_misc", wil);
+	if (rc)
+		goto free1;
+
+	return 0;
+	/* error branch */
+free1:
+	free_irq(irq + 1, wil);
+free0:
+	free_irq(irq, wil);
+
+	return rc;
+}
+
+int wil6210_init_irq(struct wil6210_priv *wil, int irq)
+{
+	int rc;
+	if (wil->n_msi == 3)
+		rc = wil6210_request_3msi(wil, irq);
+	else
+		rc = request_threaded_irq(irq, wil6210_hardirq,
+					  wil6210_thread_irq,
+					  wil->n_msi ? 0 : IRQF_SHARED,
+					  WIL_NAME, wil);
+	if (rc)
+		return rc;
+
+	wil6210_enable_irq(wil);
+
+	return 0;
+}
+
+void wil6210_fini_irq(struct wil6210_priv *wil, int irq)
+{
+	wil6210_disable_irq(wil);
+	free_irq(irq, wil);
+	if (wil->n_msi == 3) {
+		free_irq(irq + 1, wil);
+		free_irq(irq + 2, wil);
+	}
+}
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
new file mode 100644
index 0000000..95fcd36
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -0,0 +1,407 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/sched.h>
+#include <linux/ieee80211.h>
+#include <linux/wireless.h>
+#include <linux/slab.h>
+#include <linux/moduleparam.h>
+#include <linux/if_arp.h>
+
+#include "wil6210.h"
+
+/*
+ * Due to a hardware issue,
+ * one has to read/write to/from NIC in 32-bit chunks;
+ * regular memcpy_fromio and siblings will
+ * not work on 64-bit platform - it uses 64-bit transactions
+ *
+ * Force 32-bit transactions to enable NIC on 64-bit platforms
+ *
+ * To avoid byte swap on big endian host, __raw_{read|write}l
+ * should be used - {read|write}l would swap bytes to provide
+ * little endian on PCI value in host endianness.
+ */
+void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
+			  size_t count)
+{
+	u32 *d = dst;
+	const volatile u32 __iomem *s = src;
+
+	/* size_t is unsigned, if (count%4 != 0) it will wrap */
+	for (count += 4; count > 4; count -= 4)
+		*d++ = __raw_readl(s++);
+}
+
+void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
+			size_t count)
+{
+	volatile u32 __iomem *d = dst;
+	const u32 *s = src;
+
+	for (count += 4; count > 4; count -= 4)
+		__raw_writel(*s++, d++);
+}
+
+static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
+{
+	uint i;
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct wireless_dev *wdev = wil->wdev;
+
+	wil_dbg(wil, "%s()\n", __func__);
+
+	wil_link_off(wil);
+	clear_bit(wil_status_fwconnected, &wil->status);
+
+	switch (wdev->sme_state) {
+	case CFG80211_SME_CONNECTED:
+		cfg80211_disconnected(ndev, WLAN_STATUS_UNSPECIFIED_FAILURE,
+				      NULL, 0, GFP_KERNEL);
+		break;
+	case CFG80211_SME_CONNECTING:
+		cfg80211_connect_result(ndev, bssid, NULL, 0, NULL, 0,
+					WLAN_STATUS_UNSPECIFIED_FAILURE,
+					GFP_KERNEL);
+		break;
+	default:
+		;
+	}
+
+	for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++)
+		wil_vring_fini_tx(wil, i);
+}
+
+static void wil_disconnect_worker(struct work_struct *work)
+{
+	struct wil6210_priv *wil = container_of(work,
+			struct wil6210_priv, disconnect_worker);
+
+	_wil6210_disconnect(wil, NULL);
+}
+
+static void wil_connect_timer_fn(ulong x)
+{
+	struct wil6210_priv *wil = (void *)x;
+
+	wil_dbg(wil, "Connect timeout\n");
+
+	/* reschedule to thread context - disconnect won't
+	 * run from atomic context
+	 */
+	schedule_work(&wil->disconnect_worker);
+}
+
+int wil_priv_init(struct wil6210_priv *wil)
+{
+	wil_dbg(wil, "%s()\n", __func__);
+
+	mutex_init(&wil->mutex);
+	mutex_init(&wil->wmi_mutex);
+
+	init_completion(&wil->wmi_ready);
+
+	wil->pending_connect_cid = -1;
+	setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil);
+
+	INIT_WORK(&wil->wmi_connect_worker, wmi_connect_worker);
+	INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
+	INIT_WORK(&wil->wmi_event_worker, wmi_event_worker);
+
+	INIT_LIST_HEAD(&wil->pending_wmi_ev);
+	spin_lock_init(&wil->wmi_ev_lock);
+
+	wil->wmi_wq = create_singlethread_workqueue(WIL_NAME"_wmi");
+	if (!wil->wmi_wq)
+		return -EAGAIN;
+
+	wil->wmi_wq_conn = create_singlethread_workqueue(WIL_NAME"_connect");
+	if (!wil->wmi_wq_conn) {
+		destroy_workqueue(wil->wmi_wq);
+		return -EAGAIN;
+	}
+
+	/* make shadow copy of registers that should not change on run time */
+	wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
+			     sizeof(struct wil6210_mbox_ctl));
+	wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
+	wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
+
+	return 0;
+}
+
+void wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
+{
+	del_timer_sync(&wil->connect_timer);
+	_wil6210_disconnect(wil, bssid);
+}
+
+void wil_priv_deinit(struct wil6210_priv *wil)
+{
+	cancel_work_sync(&wil->disconnect_worker);
+	wil6210_disconnect(wil, NULL);
+	wmi_event_flush(wil);
+	destroy_workqueue(wil->wmi_wq_conn);
+	destroy_workqueue(wil->wmi_wq);
+}
+
+static void wil_target_reset(struct wil6210_priv *wil)
+{
+	wil_dbg(wil, "Resetting...\n");
+
+	/* register write */
+#define W(a, v) iowrite32(v, wil->csr + HOSTADDR(a))
+	/* register set = read, OR, write */
+#define S(a, v) iowrite32(ioread32(wil->csr + HOSTADDR(a)) | v, \
+		wil->csr + HOSTADDR(a))
+
+	/* hpal_perst_from_pad_src_n_mask */
+	S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(6));
+	/* car_perst_rst_src_n_mask */
+	S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT(7));
+
+	W(RGF_USER_MAC_CPU_0,  BIT(1)); /* mac_cpu_man_rst */
+	W(RGF_USER_USER_CPU_0, BIT(1)); /* user_cpu_man_rst */
+
+	msleep(100);
+
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0xFE000000);
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0x0000003F);
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000170);
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0xFFE7FC00);
+
+	msleep(100);
+
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0);
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0);
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_1, 0);
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
+
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_3, 0x00000001);
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_2, 0x00000080);
+	W(RGF_USER_CLKS_CTL_SW_RST_VEC_0, 0);
+
+	msleep(2000);
+
+	W(RGF_USER_USER_CPU_0, BIT(0)); /* user_cpu_man_de_rst */
+
+	msleep(2000);
+
+	wil_dbg(wil, "Reset completed\n");
+
+#undef W
+#undef S
+}
+
+void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
+{
+	le32_to_cpus(&r->base);
+	le16_to_cpus(&r->entry_size);
+	le16_to_cpus(&r->size);
+	le32_to_cpus(&r->tail);
+	le32_to_cpus(&r->head);
+}
+
+static int wil_wait_for_fw_ready(struct wil6210_priv *wil)
+{
+	ulong to = msecs_to_jiffies(1000);
+	ulong left = wait_for_completion_timeout(&wil->wmi_ready, to);
+	if (0 == left) {
+		wil_err(wil, "Firmware not ready\n");
+		return -ETIME;
+	} else {
+		wil_dbg(wil, "FW ready after %d ms\n",
+			jiffies_to_msecs(to-left));
+	}
+	return 0;
+}
+
+/*
+ * We reset all the structures, and we reset the UMAC.
+ * After calling this routine, you're expected to reload
+ * the firmware.
+ */
+int wil_reset(struct wil6210_priv *wil)
+{
+	int rc;
+
+	cancel_work_sync(&wil->disconnect_worker);
+	wil6210_disconnect(wil, NULL);
+
+	wmi_event_flush(wil);
+
+	flush_workqueue(wil->wmi_wq);
+	flush_workqueue(wil->wmi_wq_conn);
+
+	wil6210_disable_irq(wil);
+	wil->status = 0;
+
+	/* TODO: put MAC in reset */
+	wil_target_reset(wil);
+
+	/* init after reset */
+	wil->pending_connect_cid = -1;
+	INIT_COMPLETION(wil->wmi_ready);
+
+	/* make shadow copy of registers that should not change on run time */
+	wil_memcpy_fromio_32(&wil->mbox_ctl, wil->csr + HOST_MBOX,
+			     sizeof(struct wil6210_mbox_ctl));
+	wil_mbox_ring_le2cpus(&wil->mbox_ctl.rx);
+	wil_mbox_ring_le2cpus(&wil->mbox_ctl.tx);
+
+	/* TODO: release MAC reset */
+	wil6210_enable_irq(wil);
+
+	/* we just started MAC, wait for FW ready */
+	rc = wil_wait_for_fw_ready(wil);
+
+	return rc;
+}
+
+
+void wil_link_on(struct wil6210_priv *wil)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+
+	wil_dbg(wil, "%s()\n", __func__);
+
+	netif_carrier_on(ndev);
+	netif_tx_wake_all_queues(ndev);
+}
+
+void wil_link_off(struct wil6210_priv *wil)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+
+	wil_dbg(wil, "%s()\n", __func__);
+
+	netif_tx_stop_all_queues(ndev);
+	netif_carrier_off(ndev);
+}
+
+static int __wil_up(struct wil6210_priv *wil)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct wireless_dev *wdev = wil->wdev;
+	struct ieee80211_channel *channel = wdev->preset_chandef.chan;
+	int rc;
+	int bi;
+	u16 wmi_nettype = wil_iftype_nl2wmi(wdev->iftype);
+
+	rc = wil_reset(wil);
+	if (rc)
+		return rc;
+
+	/* FIXME Firmware works now in PBSS mode(ToDS=0, FromDS=0) */
+	wmi_nettype = wil_iftype_nl2wmi(NL80211_IFTYPE_ADHOC);
+	switch (wdev->iftype) {
+	case NL80211_IFTYPE_STATION:
+		wil_dbg(wil, "type: STATION\n");
+		bi = 0;
+		ndev->type = ARPHRD_ETHER;
+		break;
+	case NL80211_IFTYPE_AP:
+		wil_dbg(wil, "type: AP\n");
+		bi = 100;
+		ndev->type = ARPHRD_ETHER;
+		break;
+	case NL80211_IFTYPE_P2P_CLIENT:
+		wil_dbg(wil, "type: P2P_CLIENT\n");
+		bi = 0;
+		ndev->type = ARPHRD_ETHER;
+		break;
+	case NL80211_IFTYPE_P2P_GO:
+		wil_dbg(wil, "type: P2P_GO\n");
+		bi = 100;
+		ndev->type = ARPHRD_ETHER;
+		break;
+	case NL80211_IFTYPE_MONITOR:
+		wil_dbg(wil, "type: Monitor\n");
+		bi = 0;
+		ndev->type = ARPHRD_IEEE80211_RADIOTAP;
+		/* ARPHRD_IEEE80211 or ARPHRD_IEEE80211_RADIOTAP ? */
+		break;
+	default:
+		return -EOPNOTSUPP;
+	}
+
+	/* Apply profile in the following order: */
+	/* SSID and channel for the AP */
+	switch (wdev->iftype) {
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_P2P_GO:
+		if (wdev->ssid_len == 0) {
+			wil_err(wil, "SSID not set\n");
+			return -EINVAL;
+		}
+		wmi_set_ssid(wil, wdev->ssid_len, wdev->ssid);
+		if (channel)
+			wmi_set_channel(wil, channel->hw_value);
+		break;
+	default:
+		;
+	}
+
+	/* MAC address - pre-requisite for other commands */
+	wmi_set_mac_address(wil, ndev->dev_addr);
+
+	/* Set up beaconing if required. */
+	rc = wmi_set_bcon(wil, bi, wmi_nettype);
+	if (rc)
+		return rc;
+
+	/* Rx VRING. After MAC and beacon */
+	wil_rx_init(wil);
+
+	return 0;
+}
+
+int wil_up(struct wil6210_priv *wil)
+{
+	int rc;
+
+	mutex_lock(&wil->mutex);
+	rc = __wil_up(wil);
+	mutex_unlock(&wil->mutex);
+
+	return rc;
+}
+
+static int __wil_down(struct wil6210_priv *wil)
+{
+	if (wil->scan_request) {
+		cfg80211_scan_done(wil->scan_request, true);
+		wil->scan_request = NULL;
+	}
+
+	wil6210_disconnect(wil, NULL);
+	wil_rx_fini(wil);
+
+	return 0;
+}
+
+int wil_down(struct wil6210_priv *wil)
+{
+	int rc;
+
+	mutex_lock(&wil->mutex);
+	rc = __wil_down(wil);
+	mutex_unlock(&wil->mutex);
+
+	return rc;
+}
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
new file mode 100644
index 0000000..3068b5c
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/slab.h>
+
+#include "wil6210.h"
+
+static int wil_open(struct net_device *ndev)
+{
+	struct wil6210_priv *wil = ndev_to_wil(ndev);
+
+	return wil_up(wil);
+}
+
+static int wil_stop(struct net_device *ndev)
+{
+	struct wil6210_priv *wil = ndev_to_wil(ndev);
+
+	return wil_down(wil);
+}
+
+/*
+ * AC to queue mapping
+ *
+ * AC_VO -> queue 3
+ * AC_VI -> queue 2
+ * AC_BE -> queue 1
+ * AC_BK -> queue 0
+ */
+static u16 wil_select_queue(struct net_device *ndev, struct sk_buff *skb)
+{
+	static const u16 wil_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
+	struct wil6210_priv *wil = ndev_to_wil(ndev);
+	u16 rc;
+
+	skb->priority = cfg80211_classify8021d(skb);
+
+	rc = wil_1d_to_queue[skb->priority];
+
+	wil_dbg_TXRX(wil, "%s() %d -> %d\n", __func__, (int)skb->priority,
+		     (int)rc);
+
+	return rc;
+}
+
+static const struct net_device_ops wil_netdev_ops = {
+	.ndo_open		= wil_open,
+	.ndo_stop		= wil_stop,
+	.ndo_start_xmit		= wil_start_xmit,
+	.ndo_select_queue	= wil_select_queue,
+	.ndo_set_mac_address    = eth_mac_addr,
+	.ndo_validate_addr      = eth_validate_addr,
+};
+
+void *wil_if_alloc(struct device *dev, void __iomem *csr)
+{
+	struct net_device *ndev;
+	struct wireless_dev *wdev;
+	struct wil6210_priv *wil;
+	struct ieee80211_channel *ch;
+	int rc = 0;
+
+	wdev = wil_cfg80211_init(dev);
+	if (IS_ERR(wdev)) {
+		dev_err(dev, "wil_cfg80211_init failed\n");
+		return wdev;
+	}
+
+	wil = wdev_to_wil(wdev);
+	wil->csr = csr;
+	wil->wdev = wdev;
+
+	rc = wil_priv_init(wil);
+	if (rc) {
+		dev_err(dev, "wil_priv_init failed\n");
+		goto out_wdev;
+	}
+
+	wdev->iftype = NL80211_IFTYPE_STATION; /* TODO */
+	/* default monitor channel */
+	ch = wdev->wiphy->bands[IEEE80211_BAND_60GHZ]->channels;
+	cfg80211_chandef_create(&wdev->preset_chandef, ch, NL80211_CHAN_NO_HT);
+
+	ndev = alloc_netdev_mqs(0, "wlan%d", ether_setup, WIL6210_TX_QUEUES, 1);
+	if (!ndev) {
+		dev_err(dev, "alloc_netdev_mqs failed\n");
+		rc = -ENOMEM;
+		goto out_priv;
+	}
+
+	ndev->netdev_ops = &wil_netdev_ops;
+	ndev->ieee80211_ptr = wdev;
+	SET_NETDEV_DEV(ndev, wiphy_dev(wdev->wiphy));
+	wdev->netdev = ndev;
+
+	wil_link_off(wil);
+
+	return wil;
+
+ out_priv:
+	wil_priv_deinit(wil);
+
+ out_wdev:
+	wil_wdev_free(wil);
+
+	return ERR_PTR(rc);
+}
+
+void wil_if_free(struct wil6210_priv *wil)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	if (!ndev)
+		return;
+
+	free_netdev(ndev);
+	wil_priv_deinit(wil);
+	wil_wdev_free(wil);
+}
+
+int wil_if_add(struct wil6210_priv *wil)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	int rc;
+
+	rc = register_netdev(ndev);
+	if (rc < 0) {
+		dev_err(&ndev->dev, "Failed to register netdev: %d\n", rc);
+		return rc;
+	}
+
+	wil_link_off(wil);
+
+	return 0;
+}
+
+void wil_if_remove(struct wil6210_priv *wil)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+
+	unregister_netdev(ndev);
+}
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
new file mode 100644
index 0000000..0fc83ed
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -0,0 +1,223 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/netdevice.h>
+#include <linux/debugfs.h>
+#include <linux/pci.h>
+#include <linux/moduleparam.h>
+
+#include "wil6210.h"
+
+static int use_msi = 1;
+module_param(use_msi, int, S_IRUGO);
+MODULE_PARM_DESC(use_msi,
+		 " Use MSI interrupt: "
+		 "0 - don't, 1 - (default) - single, or 3");
+
+/* Bus ops */
+static int wil_if_pcie_enable(struct wil6210_priv *wil)
+{
+	struct pci_dev *pdev = wil->pdev;
+	int rc;
+
+	pci_set_master(pdev);
+
+	/*
+	 * how many MSI interrupts to request?
+	 */
+	switch (use_msi) {
+	case 3:
+	case 1:
+	case 0:
+		break;
+	default:
+		wil_err(wil, "Invalid use_msi=%d, default to 1\n",
+			use_msi);
+		use_msi = 1;
+	}
+	wil->n_msi = use_msi;
+	if (wil->n_msi) {
+		wil_dbg(wil, "Setup %d MSI interrupts\n", use_msi);
+		rc = pci_enable_msi_block(pdev, wil->n_msi);
+		if (rc && (wil->n_msi == 3)) {
+			wil_err(wil, "3 MSI mode failed, try 1 MSI\n");
+			wil->n_msi = 1;
+			rc = pci_enable_msi_block(pdev, wil->n_msi);
+		}
+		if (rc) {
+			wil_err(wil, "pci_enable_msi failed, use INTx\n");
+			wil->n_msi = 0;
+		}
+	} else {
+		wil_dbg(wil, "MSI interrupts disabled, use INTx\n");
+	}
+
+	rc = wil6210_init_irq(wil, pdev->irq);
+	if (rc)
+		goto stop_master;
+
+	/* need reset here to obtain MAC */
+	rc = wil_reset(wil);
+	if (rc)
+		goto release_irq;
+
+	return 0;
+
+ release_irq:
+	wil6210_fini_irq(wil, pdev->irq);
+	/* safe to call if no MSI */
+	pci_disable_msi(pdev);
+ stop_master:
+	pci_clear_master(pdev);
+	return rc;
+}
+
+static int wil_if_pcie_disable(struct wil6210_priv *wil)
+{
+	struct pci_dev *pdev = wil->pdev;
+
+	pci_clear_master(pdev);
+	/* disable and release IRQ */
+	wil6210_fini_irq(wil, pdev->irq);
+	/* safe to call if no MSI */
+	pci_disable_msi(pdev);
+	/* TODO: disable HW */
+
+	return 0;
+}
+
+static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
+{
+	struct wil6210_priv *wil;
+	struct device *dev = &pdev->dev;
+	void __iomem *csr;
+	int rc;
+
+	/* check HW */
+	dev_info(&pdev->dev, WIL_NAME " device found [%04x:%04x] (rev %x)\n",
+		 (int)pdev->vendor, (int)pdev->device, (int)pdev->revision);
+
+	if (pci_resource_len(pdev, 0) != WIL6210_MEM_SIZE) {
+		dev_err(&pdev->dev, "Not " WIL_NAME "? "
+			"BAR0 size is %lu while expecting %lu\n",
+			(ulong)pci_resource_len(pdev, 0), WIL6210_MEM_SIZE);
+		return -ENODEV;
+	}
+
+	rc = pci_enable_device(pdev);
+	if (rc) {
+		dev_err(&pdev->dev, "pci_enable_device failed\n");
+		return -ENODEV;
+	}
+	/* rollback to err_disable_pdev */
+
+	rc = pci_request_region(pdev, 0, WIL_NAME);
+	if (rc) {
+		dev_err(&pdev->dev, "pci_request_region failed\n");
+		goto err_disable_pdev;
+	}
+	/* rollback to err_release_reg */
+
+	csr = pci_ioremap_bar(pdev, 0);
+	if (!csr) {
+		dev_err(&pdev->dev, "pci_ioremap_bar failed\n");
+		rc = -ENODEV;
+		goto err_release_reg;
+	}
+	/* rollback to err_iounmap */
+	dev_info(&pdev->dev, "CSR at %pR -> %p\n", &pdev->resource[0], csr);
+
+	wil = wil_if_alloc(dev, csr);
+	if (IS_ERR(wil)) {
+		rc = (int)PTR_ERR(wil);
+		dev_err(dev, "wil_if_alloc failed: %d\n", rc);
+		goto err_iounmap;
+	}
+	/* rollback to if_free */
+
+	pci_set_drvdata(pdev, wil);
+	wil->pdev = pdev;
+
+	/* FW should raise IRQ when ready */
+	rc = wil_if_pcie_enable(wil);
+	if (rc) {
+		wil_err(wil, "Enable device failed\n");
+		goto if_free;
+	}
+	/* rollback to bus_disable */
+
+	rc = wil_if_add(wil);
+	if (rc) {
+		wil_err(wil, "wil_if_add failed: %d\n", rc);
+		goto bus_disable;
+	}
+
+	wil6210_debugfs_init(wil);
+
+	/* check FW is alive */
+	wmi_echo(wil);
+
+	return 0;
+
+ bus_disable:
+	wil_if_pcie_disable(wil);
+ if_free:
+	wil_if_free(wil);
+ err_iounmap:
+	pci_iounmap(pdev, csr);
+ err_release_reg:
+	pci_release_region(pdev, 0);
+ err_disable_pdev:
+	pci_disable_device(pdev);
+
+	return rc;
+}
+
+static void wil_pcie_remove(struct pci_dev *pdev)
+{
+	struct wil6210_priv *wil = pci_get_drvdata(pdev);
+
+	wil6210_debugfs_remove(wil);
+	wil_if_pcie_disable(wil);
+	wil_if_remove(wil);
+	wil_if_free(wil);
+	pci_iounmap(pdev, wil->csr);
+	pci_release_region(pdev, 0);
+	pci_disable_device(pdev);
+	pci_set_drvdata(pdev, NULL);
+}
+
+static DEFINE_PCI_DEVICE_TABLE(wil6210_pcie_ids) = {
+	{ PCI_DEVICE(0x1ae9, 0x0301) },
+	{ /* end: all zeroes */	},
+};
+MODULE_DEVICE_TABLE(pci, wil6210_pcie_ids);
+
+static struct pci_driver wil6210_driver = {
+	.probe		= wil_pcie_probe,
+	.remove		= wil_pcie_remove,
+	.id_table	= wil6210_pcie_ids,
+	.name		= WIL_NAME,
+};
+
+module_pci_driver(wil6210_driver);
+
+MODULE_LICENSE("Dual BSD/GPL");
+MODULE_AUTHOR("Qualcomm Atheros <wil6210@qca.qualcomm.com>");
+MODULE_DESCRIPTION("Driver for 60g WiFi WIL6210 card");
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
new file mode 100644
index 0000000..f29c294
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -0,0 +1,871 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/hardirq.h>
+#include <net/ieee80211_radiotap.h>
+#include <linux/if_arp.h>
+#include <linux/moduleparam.h>
+
+#include "wil6210.h"
+#include "wmi.h"
+#include "txrx.h"
+
+static bool rtap_include_phy_info;
+module_param(rtap_include_phy_info, bool, S_IRUGO);
+MODULE_PARM_DESC(rtap_include_phy_info,
+		 " Include PHY info in the radiotap header, default - no");
+
+static inline int wil_vring_is_empty(struct vring *vring)
+{
+	return vring->swhead == vring->swtail;
+}
+
+static inline u32 wil_vring_next_tail(struct vring *vring)
+{
+	return (vring->swtail + 1) % vring->size;
+}
+
+static inline void wil_vring_advance_head(struct vring *vring, int n)
+{
+	vring->swhead = (vring->swhead + n) % vring->size;
+}
+
+static inline int wil_vring_is_full(struct vring *vring)
+{
+	return wil_vring_next_tail(vring) == vring->swhead;
+}
+/*
+ * Available space in Tx Vring
+ */
+static inline int wil_vring_avail_tx(struct vring *vring)
+{
+	u32 swhead = vring->swhead;
+	u32 swtail = vring->swtail;
+	int used = (vring->size + swhead - swtail) % vring->size;
+
+	return vring->size - used - 1;
+}
+
+static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
+{
+	struct device *dev = wil_to_dev(wil);
+	size_t sz = vring->size * sizeof(vring->va[0]);
+	uint i;
+
+	BUILD_BUG_ON(sizeof(vring->va[0]) != 32);
+
+	vring->swhead = 0;
+	vring->swtail = 0;
+	vring->ctx = kzalloc(vring->size * sizeof(vring->ctx[0]), GFP_KERNEL);
+	if (!vring->ctx) {
+		wil_err(wil, "vring_alloc [%d] failed to alloc ctx mem\n",
+			vring->size);
+		vring->va = NULL;
+		return -ENOMEM;
+	}
+	/*
+	 * vring->va should be aligned on its size rounded up to power of 2
+	 * This is granted by the dma_alloc_coherent
+	 */
+	vring->va = dma_alloc_coherent(dev, sz, &vring->pa, GFP_KERNEL);
+	if (!vring->va) {
+		wil_err(wil, "vring_alloc [%d] failed to alloc DMA mem\n",
+			vring->size);
+		kfree(vring->ctx);
+		vring->ctx = NULL;
+		return -ENOMEM;
+	}
+	/* initially, all descriptors are SW owned
+	 * For Tx and Rx, ownership bit is at the same location, thus
+	 * we can use any
+	 */
+	for (i = 0; i < vring->size; i++) {
+		volatile struct vring_tx_desc *d = &(vring->va[i].tx);
+		d->dma.status = TX_DMA_STATUS_DU;
+	}
+
+	wil_dbg(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size,
+		vring->va, (unsigned long long)vring->pa, vring->ctx);
+
+	return 0;
+}
+
+static void wil_vring_free(struct wil6210_priv *wil, struct vring *vring,
+			   int tx)
+{
+	struct device *dev = wil_to_dev(wil);
+	size_t sz = vring->size * sizeof(vring->va[0]);
+
+	while (!wil_vring_is_empty(vring)) {
+		if (tx) {
+			volatile struct vring_tx_desc *d =
+					&vring->va[vring->swtail].tx;
+			dma_addr_t pa = d->dma.addr_low |
+					((u64)d->dma.addr_high << 32);
+			struct sk_buff *skb = vring->ctx[vring->swtail];
+			if (skb) {
+				dma_unmap_single(dev, pa, d->dma.length,
+						 DMA_TO_DEVICE);
+				dev_kfree_skb_any(skb);
+				vring->ctx[vring->swtail] = NULL;
+			} else {
+				dma_unmap_page(dev, pa, d->dma.length,
+					       DMA_TO_DEVICE);
+			}
+			vring->swtail = wil_vring_next_tail(vring);
+		} else { /* rx */
+			volatile struct vring_rx_desc *d =
+					&vring->va[vring->swtail].rx;
+			dma_addr_t pa = d->dma.addr_low |
+					((u64)d->dma.addr_high << 32);
+			struct sk_buff *skb = vring->ctx[vring->swhead];
+			dma_unmap_single(dev, pa, d->dma.length,
+					 DMA_FROM_DEVICE);
+			kfree_skb(skb);
+			wil_vring_advance_head(vring, 1);
+		}
+	}
+	dma_free_coherent(dev, sz, (void *)vring->va, vring->pa);
+	kfree(vring->ctx);
+	vring->pa = 0;
+	vring->va = NULL;
+	vring->ctx = NULL;
+}
+
+/**
+ * Allocate one skb for Rx VRING
+ *
+ * Safe to call from IRQ
+ */
+static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring,
+			       u32 i, int headroom)
+{
+	struct device *dev = wil_to_dev(wil);
+	unsigned int sz = RX_BUF_LEN;
+	volatile struct vring_rx_desc *d = &(vring->va[i].rx);
+	dma_addr_t pa;
+
+	/* TODO align */
+	struct sk_buff *skb = dev_alloc_skb(sz + headroom);
+	if (unlikely(!skb))
+		return -ENOMEM;
+
+	skb_reserve(skb, headroom);
+	skb_put(skb, sz);
+
+	pa = dma_map_single(dev, skb->data, skb->len, DMA_FROM_DEVICE);
+	if (unlikely(dma_mapping_error(dev, pa))) {
+		kfree_skb(skb);
+		return -ENOMEM;
+	}
+
+	d->dma.d0 = BIT(9) | RX_DMA_D0_CMD_DMA_IT;
+	d->dma.addr_low = lower_32_bits(pa);
+	d->dma.addr_high = (u16)upper_32_bits(pa);
+	/* ip_length don't care */
+	/* b11 don't care */
+	/* error don't care */
+	d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
+	d->dma.length = sz;
+	vring->ctx[i] = skb;
+
+	return 0;
+}
+
+/**
+ * Adds radiotap header
+ *
+ * Any error indicated as "Bad FCS"
+ *
+ * Vendor data for 04:ce:14-1 (Wilocity-1) consists of:
+ *  - Rx descriptor: 32 bytes
+ *  - Phy info
+ */
+static void wil_rx_add_radiotap_header(struct wil6210_priv *wil,
+				       struct sk_buff *skb,
+				       volatile struct vring_rx_desc *d)
+{
+	struct wireless_dev *wdev = wil->wdev;
+	struct wil6210_rtap {
+		struct ieee80211_radiotap_header rthdr;
+		/* fields should be in the order of bits in rthdr.it_present */
+		/* flags */
+		u8 flags;
+		/* channel */
+		__le16 chnl_freq __aligned(2);
+		__le16 chnl_flags;
+		/* MCS */
+		u8 mcs_present;
+		u8 mcs_flags;
+		u8 mcs_index;
+	} __packed;
+	struct wil6210_rtap_vendor {
+		struct wil6210_rtap rtap;
+		/* vendor */
+		u8 vendor_oui[3] __aligned(2);
+		u8 vendor_ns;
+		__le16 vendor_skip;
+		u8 vendor_data[0];
+	} __packed;
+	struct wil6210_rtap_vendor *rtap_vendor;
+	int rtap_len = sizeof(struct wil6210_rtap);
+	int phy_length = 0; /* phy info header size, bytes */
+	static char phy_data[128];
+	struct ieee80211_channel *ch = wdev->preset_chandef.chan;
+
+	if (rtap_include_phy_info) {
+		rtap_len = sizeof(*rtap_vendor) + sizeof(*d);
+		/* calculate additional length */
+		if (d->dma.status & RX_DMA_STATUS_PHY_INFO) {
+			/**
+			 * PHY info starts from 8-byte boundary
+			 * there are 8-byte lines, last line may be partially
+			 * written (HW bug), thus FW configures for last line
+			 * to be excessive. Driver skips this last line.
+			 */
+			int len = min_t(int, 8 + sizeof(phy_data),
+					wil_rxdesc_phy_length(d));
+			if (len > 8) {
+				void *p = skb_tail_pointer(skb);
+				void *pa = PTR_ALIGN(p, 8);
+				if (skb_tailroom(skb) >= len + (pa - p)) {
+					phy_length = len - 8;
+					memcpy(phy_data, pa, phy_length);
+				}
+			}
+		}
+		rtap_len += phy_length;
+	}
+
+	if (skb_headroom(skb) < rtap_len &&
+	    pskb_expand_head(skb, rtap_len, 0, GFP_ATOMIC)) {
+		wil_err(wil, "Unable to expand headrom to %d\n", rtap_len);
+		return;
+	}
+
+	rtap_vendor = (void *)skb_push(skb, rtap_len);
+	memset(rtap_vendor, 0, rtap_len);
+
+	rtap_vendor->rtap.rthdr.it_version = PKTHDR_RADIOTAP_VERSION;
+	rtap_vendor->rtap.rthdr.it_len = cpu_to_le16(rtap_len);
+	rtap_vendor->rtap.rthdr.it_present = cpu_to_le32(
+			(1 << IEEE80211_RADIOTAP_FLAGS) |
+			(1 << IEEE80211_RADIOTAP_CHANNEL) |
+			(1 << IEEE80211_RADIOTAP_MCS));
+	if (d->dma.status & RX_DMA_STATUS_ERROR)
+		rtap_vendor->rtap.flags |= IEEE80211_RADIOTAP_F_BADFCS;
+
+	rtap_vendor->rtap.chnl_freq = cpu_to_le16(ch ? ch->center_freq : 58320);
+	rtap_vendor->rtap.chnl_flags = cpu_to_le16(0);
+
+	rtap_vendor->rtap.mcs_present = IEEE80211_RADIOTAP_MCS_HAVE_MCS;
+	rtap_vendor->rtap.mcs_flags = 0;
+	rtap_vendor->rtap.mcs_index = wil_rxdesc_mcs(d);
+
+	if (rtap_include_phy_info) {
+		rtap_vendor->rtap.rthdr.it_present |= cpu_to_le32(1 <<
+				IEEE80211_RADIOTAP_VENDOR_NAMESPACE);
+		/* OUI for Wilocity 04:ce:14 */
+		rtap_vendor->vendor_oui[0] = 0x04;
+		rtap_vendor->vendor_oui[1] = 0xce;
+		rtap_vendor->vendor_oui[2] = 0x14;
+		rtap_vendor->vendor_ns = 1;
+		/* Rx descriptor + PHY data  */
+		rtap_vendor->vendor_skip = cpu_to_le16(sizeof(*d) +
+						       phy_length);
+		memcpy(rtap_vendor->vendor_data, (void *)d, sizeof(*d));
+		memcpy(rtap_vendor->vendor_data + sizeof(*d), phy_data,
+		       phy_length);
+	}
+}
+
+/*
+ * Fast swap in place between 2 registers
+ */
+static void wil_swap_u16(u16 *a, u16 *b)
+{
+	*a ^= *b;
+	*b ^= *a;
+	*a ^= *b;
+}
+
+static void wil_swap_ethaddr(void *data)
+{
+	struct ethhdr *eth = data;
+	u16 *s = (u16 *)eth->h_source;
+	u16 *d = (u16 *)eth->h_dest;
+
+	wil_swap_u16(s++, d++);
+	wil_swap_u16(s++, d++);
+	wil_swap_u16(s, d);
+}
+
+/**
+ * reap 1 frame from @swhead
+ *
+ * Safe to call from IRQ
+ */
+static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil,
+					 struct vring *vring)
+{
+	struct device *dev = wil_to_dev(wil);
+	struct net_device *ndev = wil_to_ndev(wil);
+	volatile struct vring_rx_desc *d;
+	struct sk_buff *skb;
+	dma_addr_t pa;
+	unsigned int sz = RX_BUF_LEN;
+	u8 ftype;
+	u8 ds_bits;
+
+	if (wil_vring_is_empty(vring))
+		return NULL;
+
+	d = &(vring->va[vring->swhead].rx);
+	if (!(d->dma.status & RX_DMA_STATUS_DU)) {
+		/* it is not error, we just reached end of Rx done area */
+		return NULL;
+	}
+
+	pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
+	skb = vring->ctx[vring->swhead];
+	dma_unmap_single(dev, pa, sz, DMA_FROM_DEVICE);
+	skb_trim(skb, d->dma.length);
+
+	wil->stats.last_mcs_rx = wil_rxdesc_mcs(d);
+
+	/* use radiotap header only if required */
+	if (ndev->type == ARPHRD_IEEE80211_RADIOTAP)
+		wil_rx_add_radiotap_header(wil, skb, d);
+
+	wil_dbg_TXRX(wil, "Rx[%3d] : %d bytes\n", vring->swhead, d->dma.length);
+	wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_NONE, 32, 4,
+			  (const void *)d, sizeof(*d), false);
+
+	wil_vring_advance_head(vring, 1);
+
+	/* no extra checks if in sniffer mode */
+	if (ndev->type != ARPHRD_ETHER)
+		return skb;
+	/*
+	 * Non-data frames may be delivered through Rx DMA channel (ex: BAR)
+	 * Driver should recognize it by frame type, that is found
+	 * in Rx descriptor. If type is not data, it is 802.11 frame as is
+	 */
+	ftype = wil_rxdesc_ftype(d) << 2;
+	if (ftype != IEEE80211_FTYPE_DATA) {
+		wil_dbg_TXRX(wil, "Non-data frame ftype 0x%08x\n", ftype);
+		/* TODO: process it */
+		kfree_skb(skb);
+		return NULL;
+	}
+
+	if (skb->len < ETH_HLEN) {
+		wil_err(wil, "Short frame, len = %d\n", skb->len);
+		/* TODO: process it (i.e. BAR) */
+		kfree_skb(skb);
+		return NULL;
+	}
+
+	ds_bits = wil_rxdesc_ds_bits(d);
+	if (ds_bits == 1) {
+		/*
+		 * HW bug - in ToDS mode, i.e. Rx on AP side,
+		 * addresses get swapped
+		 */
+		wil_swap_ethaddr(skb->data);
+	}
+
+	return skb;
+}
+
+/**
+ * allocate and fill up to @count buffers in rx ring
+ * buffers posted at @swtail
+ */
+static int wil_rx_refill(struct wil6210_priv *wil, int count)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct vring *v = &wil->vring_rx;
+	u32 next_tail;
+	int rc = 0;
+	int headroom = ndev->type == ARPHRD_IEEE80211_RADIOTAP ?
+			WIL6210_RTAP_SIZE : 0;
+
+	for (; next_tail = wil_vring_next_tail(v),
+			(next_tail != v->swhead) && (count-- > 0);
+			v->swtail = next_tail) {
+		rc = wil_vring_alloc_skb(wil, v, v->swtail, headroom);
+		if (rc) {
+			wil_err(wil, "Error %d in wil_rx_refill[%d]\n",
+				rc, v->swtail);
+			break;
+		}
+	}
+	iowrite32(v->swtail, wil->csr + HOSTADDR(v->hwtail));
+
+	return rc;
+}
+
+/*
+ * Pass Rx packet to the netif. Update statistics.
+ */
+static void wil_netif_rx_any(struct sk_buff *skb, struct net_device *ndev)
+{
+	int rc;
+	unsigned int len = skb->len;
+
+	if (in_interrupt())
+		rc = netif_rx(skb);
+	else
+		rc = netif_rx_ni(skb);
+
+	if (likely(rc == NET_RX_SUCCESS)) {
+		ndev->stats.rx_packets++;
+		ndev->stats.rx_bytes += len;
+
+	} else {
+		ndev->stats.rx_dropped++;
+	}
+}
+
+/**
+ * Proceed all completed skb's from Rx VRING
+ *
+ * Safe to call from IRQ
+ */
+void wil_rx_handle(struct wil6210_priv *wil)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct vring *v = &wil->vring_rx;
+	struct sk_buff *skb;
+
+	if (!v->va) {
+		wil_err(wil, "Rx IRQ while Rx not yet initialized\n");
+		return;
+	}
+	wil_dbg_TXRX(wil, "%s()\n", __func__);
+	while (NULL != (skb = wil_vring_reap_rx(wil, v))) {
+		wil_hex_dump_TXRX("Rx ", DUMP_PREFIX_OFFSET, 16, 1,
+				  skb->data, skb_headlen(skb), false);
+
+		skb_orphan(skb);
+
+		if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+			skb->dev = ndev;
+			skb_reset_mac_header(skb);
+			skb->ip_summed = CHECKSUM_UNNECESSARY;
+			skb->pkt_type = PACKET_OTHERHOST;
+			skb->protocol = htons(ETH_P_802_2);
+
+		} else {
+			skb->protocol = eth_type_trans(skb, ndev);
+		}
+
+		wil_netif_rx_any(skb, ndev);
+	}
+	wil_rx_refill(wil, v->size);
+}
+
+int wil_rx_init(struct wil6210_priv *wil)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct wireless_dev *wdev = wil->wdev;
+	struct vring *vring = &wil->vring_rx;
+	int rc;
+	struct wmi_cfg_rx_chain_cmd cmd = {
+		.action = WMI_RX_CHAIN_ADD,
+		.rx_sw_ring = {
+			.max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
+		},
+		.mid = 0, /* TODO - what is it? */
+		.decap_trans_type = WMI_DECAP_TYPE_802_3,
+	};
+	struct {
+		struct wil6210_mbox_hdr_wmi wmi;
+		struct wmi_cfg_rx_chain_done_event evt;
+	} __packed evt;
+
+	vring->size = WIL6210_RX_RING_SIZE;
+	rc = wil_vring_alloc(wil, vring);
+	if (rc)
+		return rc;
+
+	cmd.rx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
+	cmd.rx_sw_ring.ring_size = cpu_to_le16(vring->size);
+	if (wdev->iftype == NL80211_IFTYPE_MONITOR) {
+		struct ieee80211_channel *ch = wdev->preset_chandef.chan;
+
+		cmd.sniffer_cfg.mode = cpu_to_le32(WMI_SNIFFER_ON);
+		if (ch)
+			cmd.sniffer_cfg.channel = ch->hw_value - 1;
+		cmd.sniffer_cfg.phy_info_mode =
+			cpu_to_le32(ndev->type == ARPHRD_IEEE80211_RADIOTAP);
+		cmd.sniffer_cfg.phy_support =
+			cpu_to_le32((wil->monitor_flags & MONITOR_FLAG_CONTROL)
+				    ? WMI_SNIFFER_CP : WMI_SNIFFER_DP);
+	}
+	/* typical time for secure PCP is 840ms */
+	rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
+		      WMI_CFG_RX_CHAIN_DONE_EVENTID, &evt, sizeof(evt), 2000);
+	if (rc)
+		goto err_free;
+
+	vring->hwtail = le32_to_cpu(evt.evt.rx_ring_tail_ptr);
+
+	wil_dbg(wil, "Rx init: status %d tail 0x%08x\n",
+		le32_to_cpu(evt.evt.status), vring->hwtail);
+
+	rc = wil_rx_refill(wil, vring->size);
+	if (rc)
+		goto err_free;
+
+	return 0;
+ err_free:
+	wil_vring_free(wil, vring, 0);
+
+	return rc;
+}
+
+void wil_rx_fini(struct wil6210_priv *wil)
+{
+	struct vring *vring = &wil->vring_rx;
+
+	if (vring->va) {
+		int rc;
+		struct wmi_cfg_rx_chain_cmd cmd = {
+			.action = cpu_to_le32(WMI_RX_CHAIN_DEL),
+			.rx_sw_ring = {
+				.max_mpdu_size = cpu_to_le16(RX_BUF_LEN),
+			},
+		};
+		struct {
+			struct wil6210_mbox_hdr_wmi wmi;
+			struct wmi_cfg_rx_chain_done_event cfg;
+		} __packed wmi_rx_cfg_reply;
+
+		rc = wmi_call(wil, WMI_CFG_RX_CHAIN_CMDID, &cmd, sizeof(cmd),
+			      WMI_CFG_RX_CHAIN_DONE_EVENTID,
+			      &wmi_rx_cfg_reply, sizeof(wmi_rx_cfg_reply),
+			      100);
+		wil_vring_free(wil, vring, 0);
+	}
+}
+
+int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
+		      int cid, int tid)
+{
+	int rc;
+	struct wmi_vring_cfg_cmd cmd = {
+		.action = cpu_to_le32(WMI_VRING_CMD_ADD),
+		.vring_cfg = {
+			.tx_sw_ring = {
+				.max_mpdu_size = cpu_to_le16(TX_BUF_LEN),
+			},
+			.ringid = id,
+			.cidxtid = (cid & 0xf) | ((tid & 0xf) << 4),
+			.encap_trans_type = WMI_VRING_ENC_TYPE_802_3,
+			.mac_ctrl = 0,
+			.to_resolution = 0,
+			.agg_max_wsize = 16,
+			.schd_params = {
+				.priority = cpu_to_le16(0),
+				.timeslot_us = cpu_to_le16(0xfff),
+			},
+		},
+	};
+	struct {
+		struct wil6210_mbox_hdr_wmi wmi;
+		struct wmi_vring_cfg_done_event cmd;
+	} __packed reply;
+	struct vring *vring = &wil->vring_tx[id];
+
+	if (vring->va) {
+		wil_err(wil, "Tx ring [%d] already allocated\n", id);
+		rc = -EINVAL;
+		goto out;
+	}
+
+	vring->size = size;
+	rc = wil_vring_alloc(wil, vring);
+	if (rc)
+		goto out;
+
+	cmd.vring_cfg.tx_sw_ring.ring_mem_base = cpu_to_le64(vring->pa);
+	cmd.vring_cfg.tx_sw_ring.ring_size = cpu_to_le16(vring->size);
+
+	rc = wmi_call(wil, WMI_VRING_CFG_CMDID, &cmd, sizeof(cmd),
+		      WMI_VRING_CFG_DONE_EVENTID, &reply, sizeof(reply), 100);
+	if (rc)
+		goto out_free;
+
+	if (reply.cmd.status != WMI_VRING_CFG_SUCCESS) {
+		wil_err(wil, "Tx config failed, status 0x%02x\n",
+			reply.cmd.status);
+		goto out_free;
+	}
+	vring->hwtail = le32_to_cpu(reply.cmd.tx_vring_tail_ptr);
+
+	return 0;
+ out_free:
+	wil_vring_free(wil, vring, 1);
+ out:
+
+	return rc;
+}
+
+void wil_vring_fini_tx(struct wil6210_priv *wil, int id)
+{
+	struct vring *vring = &wil->vring_tx[id];
+
+	if (!vring->va)
+		return;
+
+	wil_vring_free(wil, vring, 1);
+}
+
+static struct vring *wil_find_tx_vring(struct wil6210_priv *wil,
+				       struct sk_buff *skb)
+{
+	struct vring *v = &wil->vring_tx[0];
+
+	if (v->va)
+		return v;
+
+	return NULL;
+}
+
+static int wil_tx_desc_map(volatile struct vring_tx_desc *d,
+			   dma_addr_t pa, u32 len)
+{
+	d->dma.addr_low = lower_32_bits(pa);
+	d->dma.addr_high = (u16)upper_32_bits(pa);
+	d->dma.ip_length = 0;
+	/* 0..6: mac_length; 7:ip_version 0-IP6 1-IP4*/
+	d->dma.b11 = 0/*14 | BIT(7)*/;
+	d->dma.error = 0;
+	d->dma.status = 0; /* BIT(0) should be 0 for HW_OWNED */
+	d->dma.length = len;
+	d->dma.d0 = 0;
+	d->mac.d[0] = 0;
+	d->mac.d[1] = 0;
+	d->mac.d[2] = 0;
+	d->mac.ucode_cmd = 0;
+	/* use dst index 0 */
+	d->mac.d[1] |= BIT(MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS) |
+		       (0 << MAC_CFG_DESC_TX_1_DST_INDEX_POS);
+	/* translation type:  0 - bypass; 1 - 802.3; 2 - native wifi */
+	d->mac.d[2] = BIT(MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS) |
+		      (1 << MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS);
+
+	return 0;
+}
+
+static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
+			struct sk_buff *skb)
+{
+	struct device *dev = wil_to_dev(wil);
+	volatile struct vring_tx_desc *d;
+	u32 swhead = vring->swhead;
+	int avail = wil_vring_avail_tx(vring);
+	int nr_frags = skb_shinfo(skb)->nr_frags;
+	uint f;
+	int vring_index = vring - wil->vring_tx;
+	uint i = swhead;
+	dma_addr_t pa;
+
+	wil_dbg_TXRX(wil, "%s()\n", __func__);
+
+	if (avail < vring->size/8)
+		netif_tx_stop_all_queues(wil_to_ndev(wil));
+	if (avail < 1 + nr_frags) {
+		wil_err(wil, "Tx ring full. No space for %d fragments\n",
+			1 + nr_frags);
+		return -ENOMEM;
+	}
+	d = &(vring->va[i].tx);
+
+	/* FIXME FW can accept only unicast frames for the peer */
+	memcpy(skb->data, wil->dst_addr[vring_index], ETH_ALEN);
+
+	pa = dma_map_single(dev, skb->data,
+			skb_headlen(skb), DMA_TO_DEVICE);
+
+	wil_dbg_TXRX(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb),
+		     skb->data, (unsigned long long)pa);
+	wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_OFFSET, 16, 1,
+			  skb->data, skb_headlen(skb), false);
+
+	if (unlikely(dma_mapping_error(dev, pa)))
+		return -EINVAL;
+	/* 1-st segment */
+	wil_tx_desc_map(d, pa, skb_headlen(skb));
+	d->mac.d[2] |= ((nr_frags + 1) <<
+		       MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS);
+	/* middle segments */
+	for (f = 0; f < nr_frags; f++) {
+		const struct skb_frag_struct *frag =
+				&skb_shinfo(skb)->frags[f];
+		int len = skb_frag_size(frag);
+		i = (swhead + f + 1) % vring->size;
+		d = &(vring->va[i].tx);
+		pa = skb_frag_dma_map(dev, frag, 0, skb_frag_size(frag),
+				DMA_TO_DEVICE);
+		if (unlikely(dma_mapping_error(dev, pa)))
+			goto dma_error;
+		wil_tx_desc_map(d, pa, len);
+		vring->ctx[i] = NULL;
+	}
+	/* for the last seg only */
+	d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_EOP_POS);
+	d->dma.d0 |= BIT(9); /* BUG: undocumented bit */
+	d->dma.d0 |= BIT(DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS);
+	d->dma.d0 |= (vring_index << DMA_CFG_DESC_TX_0_QID_POS);
+
+	wil_hex_dump_TXRX("Tx ", DUMP_PREFIX_NONE, 32, 4,
+			  (const void *)d, sizeof(*d), false);
+
+	/* advance swhead */
+	wil_vring_advance_head(vring, nr_frags + 1);
+	wil_dbg_TXRX(wil, "Tx swhead %d -> %d\n", swhead, vring->swhead);
+	iowrite32(vring->swhead, wil->csr + HOSTADDR(vring->hwtail));
+	/* hold reference to skb
+	 * to prevent skb release before accounting
+	 * in case of immediate "tx done"
+	 */
+	vring->ctx[i] = skb_get(skb);
+
+	return 0;
+ dma_error:
+	/* unmap what we have mapped */
+	/* Note: increment @f to operate with positive index */
+	for (f++; f > 0; f--) {
+		i = (swhead + f) % vring->size;
+		d = &(vring->va[i].tx);
+		d->dma.status = TX_DMA_STATUS_DU;
+		pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
+		if (vring->ctx[i])
+			dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
+		else
+			dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE);
+	}
+
+	return -EINVAL;
+}
+
+
+netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	struct wil6210_priv *wil = ndev_to_wil(ndev);
+	struct vring *vring;
+	int rc;
+
+	wil_dbg_TXRX(wil, "%s()\n", __func__);
+	if (!test_bit(wil_status_fwready, &wil->status)) {
+		wil_err(wil, "FW not ready\n");
+		goto drop;
+	}
+	if (!test_bit(wil_status_fwconnected, &wil->status)) {
+		wil_err(wil, "FW not connected\n");
+		goto drop;
+	}
+	if (wil->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+		wil_err(wil, "Xmit in monitor mode not supported\n");
+		goto drop;
+	}
+	if (skb->protocol == cpu_to_be16(ETH_P_PAE)) {
+		rc = wmi_tx_eapol(wil, skb);
+	} else {
+		/* find vring */
+		vring = wil_find_tx_vring(wil, skb);
+		if (!vring) {
+			wil_err(wil, "No Tx VRING available\n");
+			goto drop;
+		}
+		/* set up vring entry */
+		rc = wil_tx_vring(wil, vring, skb);
+	}
+	switch (rc) {
+	case 0:
+		ndev->stats.tx_packets++;
+		ndev->stats.tx_bytes += skb->len;
+		dev_kfree_skb_any(skb);
+		return NETDEV_TX_OK;
+	case -ENOMEM:
+		return NETDEV_TX_BUSY;
+	default:
+		; /* goto drop; */
+		break;
+	}
+ drop:
+	netif_tx_stop_all_queues(ndev);
+	ndev->stats.tx_dropped++;
+	dev_kfree_skb_any(skb);
+
+	return NET_XMIT_DROP;
+}
+
+/**
+ * Clean up transmitted skb's from the Tx VRING
+ *
+ * Safe to call from IRQ
+ */
+void wil_tx_complete(struct wil6210_priv *wil, int ringid)
+{
+	struct device *dev = wil_to_dev(wil);
+	struct vring *vring = &wil->vring_tx[ringid];
+
+	if (!vring->va) {
+		wil_err(wil, "Tx irq[%d]: vring not initialized\n", ringid);
+		return;
+	}
+
+	wil_dbg_TXRX(wil, "%s(%d)\n", __func__, ringid);
+
+	while (!wil_vring_is_empty(vring)) {
+		volatile struct vring_tx_desc *d = &vring->va[vring->swtail].tx;
+		dma_addr_t pa;
+		struct sk_buff *skb;
+		if (!(d->dma.status & TX_DMA_STATUS_DU))
+			break;
+
+		wil_dbg_TXRX(wil,
+			     "Tx[%3d] : %d bytes, status 0x%02x err 0x%02x\n",
+			     vring->swtail, d->dma.length, d->dma.status,
+			     d->dma.error);
+		wil_hex_dump_TXRX("TxC ", DUMP_PREFIX_NONE, 32, 4,
+				  (const void *)d, sizeof(*d), false);
+
+		pa = d->dma.addr_low | ((u64)d->dma.addr_high << 32);
+		skb = vring->ctx[vring->swtail];
+		if (skb) {
+			dma_unmap_single(dev, pa, d->dma.length, DMA_TO_DEVICE);
+			dev_kfree_skb_any(skb);
+			vring->ctx[vring->swtail] = NULL;
+		} else {
+			dma_unmap_page(dev, pa, d->dma.length, DMA_TO_DEVICE);
+		}
+		d->dma.addr_low = 0;
+		d->dma.addr_high = 0;
+		d->dma.length = 0;
+		d->dma.status = TX_DMA_STATUS_DU;
+		vring->swtail = wil_vring_next_tail(vring);
+	}
+	if (wil_vring_avail_tx(vring) > vring->size/4)
+		netif_tx_wake_all_queues(wil_to_ndev(wil));
+}
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h
new file mode 100644
index 0000000..45a61f5
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/txrx.h
@@ -0,0 +1,362 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef WIL6210_TXRX_H
+#define WIL6210_TXRX_H
+
+#define BUF_SW_OWNED    (1)
+#define BUF_HW_OWNED    (0)
+
+/* size of max. Rx packet */
+#define RX_BUF_LEN      (2048)
+#define TX_BUF_LEN      (2048)
+/* how many bytes to reserve for rtap header? */
+#define WIL6210_RTAP_SIZE (128)
+
+/* Tx/Rx path */
+/*
+ * Tx descriptor - MAC part
+ * [dword 0]
+ * bit  0.. 9 : lifetime_expiry_value:10
+ * bit     10 : interrup_en:1
+ * bit     11 : status_en:1
+ * bit 12..13 : txss_override:2
+ * bit     14 : timestamp_insertion:1
+ * bit     15 : duration_preserve:1
+ * bit 16..21 : reserved0:6
+ * bit 22..26 : mcs_index:5
+ * bit     27 : mcs_en:1
+ * bit 28..29 : reserved1:2
+ * bit     30 : reserved2:1
+ * bit     31 : sn_preserved:1
+ * [dword 1]
+ * bit  0.. 3 : pkt_mode:4
+ * bit      4 : pkt_mode_en:1
+ * bit  5.. 7 : reserved0:3
+ * bit  8..13 : reserved1:6
+ * bit     14 : reserved2:1
+ * bit     15 : ack_policy_en:1
+ * bit 16..19 : dst_index:4
+ * bit     20 : dst_index_en:1
+ * bit 21..22 : ack_policy:2
+ * bit     23 : lifetime_en:1
+ * bit 24..30 : max_retry:7
+ * bit     31 : max_retry_en:1
+ * [dword 2]
+ * bit  0.. 7 : num_of_descriptors:8
+ * bit  8..17 : reserved:10
+ * bit 18..19 : l2_translation_type:2
+ * bit     20 : snap_hdr_insertion_en:1
+ * bit     21 : vlan_removal_en:1
+ * bit 22..31 : reserved0:10
+ * [dword 3]
+ * bit  0.. 31: ucode_cmd:32
+ */
+struct vring_tx_mac {
+	u32 d[3];
+	u32 ucode_cmd;
+} __packed;
+
+/* TX MAC Dword 0 */
+#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_POS 0
+#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_LEN 10
+#define MAC_CFG_DESC_TX_0_LIFETIME_EXPIRY_VALUE_MSK 0x3FF
+
+#define MAC_CFG_DESC_TX_0_INTERRUP_EN_POS 10
+#define MAC_CFG_DESC_TX_0_INTERRUP_EN_LEN 1
+#define MAC_CFG_DESC_TX_0_INTERRUP_EN_MSK 0x400
+
+#define MAC_CFG_DESC_TX_0_STATUS_EN_POS 11
+#define MAC_CFG_DESC_TX_0_STATUS_EN_LEN 1
+#define MAC_CFG_DESC_TX_0_STATUS_EN_MSK 0x800
+
+#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_POS 12
+#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_LEN 2
+#define MAC_CFG_DESC_TX_0_TXSS_OVERRIDE_MSK 0x3000
+
+#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_POS 14
+#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_LEN 1
+#define MAC_CFG_DESC_TX_0_TIMESTAMP_INSERTION_MSK 0x4000
+
+#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_POS 15
+#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_LEN 1
+#define MAC_CFG_DESC_TX_0_DURATION_PRESERVE_MSK 0x8000
+
+#define MAC_CFG_DESC_TX_0_MCS_INDEX_POS 22
+#define MAC_CFG_DESC_TX_0_MCS_INDEX_LEN 5
+#define MAC_CFG_DESC_TX_0_MCS_INDEX_MSK 0x7C00000
+
+#define MAC_CFG_DESC_TX_0_MCS_EN_POS 27
+#define MAC_CFG_DESC_TX_0_MCS_EN_LEN 1
+#define MAC_CFG_DESC_TX_0_MCS_EN_MSK 0x8000000
+
+#define MAC_CFG_DESC_TX_0_SN_PRESERVED_POS 31
+#define MAC_CFG_DESC_TX_0_SN_PRESERVED_LEN 1
+#define MAC_CFG_DESC_TX_0_SN_PRESERVED_MSK 0x80000000
+
+/* TX MAC Dword 1 */
+#define MAC_CFG_DESC_TX_1_PKT_MODE_POS 0
+#define MAC_CFG_DESC_TX_1_PKT_MODE_LEN 4
+#define MAC_CFG_DESC_TX_1_PKT_MODE_MSK 0xF
+
+#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_POS 4
+#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_LEN 1
+#define MAC_CFG_DESC_TX_1_PKT_MODE_EN_MSK 0x10
+
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_POS 15
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_LEN 1
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_EN_MSK 0x8000
+
+#define MAC_CFG_DESC_TX_1_DST_INDEX_POS 16
+#define MAC_CFG_DESC_TX_1_DST_INDEX_LEN 4
+#define MAC_CFG_DESC_TX_1_DST_INDEX_MSK 0xF0000
+
+#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_POS 20
+#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_LEN 1
+#define MAC_CFG_DESC_TX_1_DST_INDEX_EN_MSK 0x100000
+
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_POS 21
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_LEN 2
+#define MAC_CFG_DESC_TX_1_ACK_POLICY_MSK 0x600000
+
+#define MAC_CFG_DESC_TX_1_LIFETIME_EN_POS 23
+#define MAC_CFG_DESC_TX_1_LIFETIME_EN_LEN 1
+#define MAC_CFG_DESC_TX_1_LIFETIME_EN_MSK 0x800000
+
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_POS 24
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_LEN 7
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_MSK 0x7F000000
+
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_POS 31
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_LEN 1
+#define MAC_CFG_DESC_TX_1_MAX_RETRY_EN_MSK 0x80000000
+
+/* TX MAC Dword 2 */
+#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_POS 0
+#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_LEN 8
+#define MAC_CFG_DESC_TX_2_NUM_OF_DESCRIPTORS_MSK 0xFF
+
+#define MAC_CFG_DESC_TX_2_RESERVED_POS 8
+#define MAC_CFG_DESC_TX_2_RESERVED_LEN 10
+#define MAC_CFG_DESC_TX_2_RESERVED_MSK 0x3FF00
+
+#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_POS 18
+#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_LEN 2
+#define MAC_CFG_DESC_TX_2_L2_TRANSLATION_TYPE_MSK 0xC0000
+
+#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_POS 20
+#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_LEN 1
+#define MAC_CFG_DESC_TX_2_SNAP_HDR_INSERTION_EN_MSK 0x100000
+
+#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_POS 21
+#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_LEN 1
+#define MAC_CFG_DESC_TX_2_VLAN_REMOVAL_EN_MSK 0x200000
+
+/* TX MAC Dword 3 */
+#define MAC_CFG_DESC_TX_3_UCODE_CMD_POS 0
+#define MAC_CFG_DESC_TX_3_UCODE_CMD_LEN 32
+#define MAC_CFG_DESC_TX_3_UCODE_CMD_MSK 0xFFFFFFFF
+
+/* TX DMA Dword 0 */
+#define DMA_CFG_DESC_TX_0_L4_LENGTH_POS 0
+#define DMA_CFG_DESC_TX_0_L4_LENGTH_LEN 8
+#define DMA_CFG_DESC_TX_0_L4_LENGTH_MSK 0xFF
+
+#define DMA_CFG_DESC_TX_0_CMD_EOP_POS 8
+#define DMA_CFG_DESC_TX_0_CMD_EOP_LEN 1
+#define DMA_CFG_DESC_TX_0_CMD_EOP_MSK 0x100
+
+#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_POS 10
+#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_LEN 1
+#define DMA_CFG_DESC_TX_0_CMD_DMA_IT_MSK 0x400
+
+#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_POS 11
+#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_LEN 2
+#define DMA_CFG_DESC_TX_0_SEGMENT_BUF_DETAILS_MSK 0x1800
+
+#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_POS 13
+#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_LEN 1
+#define DMA_CFG_DESC_TX_0_TCP_SEG_EN_MSK 0x2000
+
+#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_POS 14
+#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_LEN 1
+#define DMA_CFG_DESC_TX_0_IPV4_CHECKSUM_EN_MSK 0x4000
+
+#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_POS 15
+#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_LEN 1
+#define DMA_CFG_DESC_TX_0_TCP_UDP_CHECKSUM_EN_MSK 0x8000
+
+#define DMA_CFG_DESC_TX_0_QID_POS 16
+#define DMA_CFG_DESC_TX_0_QID_LEN 5
+#define DMA_CFG_DESC_TX_0_QID_MSK 0x1F0000
+
+#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_POS 21
+#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_LEN 1
+#define DMA_CFG_DESC_TX_0_PSEUDO_HEADER_CALC_EN_MSK 0x200000
+
+#define DMA_CFG_DESC_TX_0_L4_TYPE_POS 30
+#define DMA_CFG_DESC_TX_0_L4_TYPE_LEN 2
+#define DMA_CFG_DESC_TX_0_L4_TYPE_MSK 0xC0000000
+
+
+#define TX_DMA_STATUS_DU         BIT(0)
+
+struct vring_tx_dma {
+	u32 d0;
+	u32 addr_low;
+	u16 addr_high;
+	u8  ip_length;
+	u8  b11;       /* 0..6: mac_length; 7:ip_version */
+	u8  error;     /* 0..2: err; 3..7: reserved; */
+	u8  status;    /* 0: used; 1..7; reserved */
+	u16 length;
+} __packed;
+
+/*
+ * Rx descriptor - MAC part
+ * [dword 0]
+ * bit  0.. 3 : tid:4 The QoS (b3-0) TID Field
+ * bit  4.. 6 : connection_id:3 :The Source index that  was found during
+ *  Parsing the TA.  This field is used to  define the source of the packet
+ * bit      7 : reserved:1
+ * bit  8.. 9 : mac_id:2 : The MAC virtual  Ring number (always zero)
+ * bit 10..11 : frame_type:2 : The FC Control  (b3-2) -  MPDU Type
+ *              (management, data, control  and extension)
+ * bit 12..15 : frame_subtype:4 : The FC Control  (b7-4) -  Frame Subtype
+ * bit 16..27 : seq_number:12 The received Sequence number field
+ * bit 28..31 : extended:4 extended subtype
+ * [dword 1]
+ * bit  0.. 3 : reserved
+ * bit  4.. 5 : key_id:2
+ * bit      6 : decrypt_bypass:1
+ * bit      7 : security:1
+ * bit  8.. 9 : ds_bits:2
+ * bit     10 : a_msdu_present:1  from qos header
+ * bit     11 : a_msdu_type:1  from qos header
+ * bit     12 : a_mpdu:1  part of AMPDU aggregation
+ * bit     13 : broadcast:1
+ * bit     14 : mutlicast:1
+ * bit     15 : reserved:1
+ * bit 16..20 : rx_mac_qid:5   The Queue Identifier that the packet
+ *                             is received from
+ * bit 21..24 : mcs:4
+ * bit 25..28 : mic_icr:4
+ * bit 29..31 : reserved:3
+ * [dword 2]
+ * bit  0.. 2 : time_slot:3 The timeslot that the MPDU is received
+ * bit      3 : fc_protocol_ver:1 The FC Control  (b0) - Protocol  Version
+ * bit      4 : fc_order:1 The FC Control (b15) -Order
+ * bit  5.. 7 : qos_ack_policy:3  The QoS (b6-5) ack policy Field
+ * bit      8 : esop:1 The QoS (b4) ESOP field
+ * bit      9 : qos_rdg_more_ppdu:1 The QoS (b9) RDG  field
+ * bit 10..14 : qos_reserved:5 The QoS (b14-10) Reserved  field
+ * bit     15 : qos_ac_constraint:1
+ * bit 16..31 : pn_15_0:16 low 2 bytes of PN
+ * [dword 3]
+ * bit  0..31 : pn_47_16:32 high 4 bytes of PN
+ */
+struct vring_rx_mac {
+	u32 d0;
+	u32 d1;
+	u16 w4;
+	u16 pn_15_0;
+	u32 pn_47_16;
+} __packed;
+
+/*
+ * Rx descriptor - DMA part
+ * [dword 0]
+ * bit  0.. 7 : l4_length:8 layer 4 length
+ * bit  8.. 9 : reserved:2
+ * bit     10 : cmd_dma_it:1
+ * bit 11..15 : reserved:5
+ * bit 16..29 : phy_info_length:14
+ * bit 30..31 : l4_type:2 valid if the L4I bit is set in the status field
+ * [dword 1]
+ * bit  0..31 : addr_low:32 The payload buffer low address
+ * [dword 2]
+ * bit  0..15 : addr_high:16 The payload buffer high address
+ * bit 16..23 : ip_length:8
+ * bit 24..30 : mac_length:7
+ * bit     31 : ip_version:1
+ * [dword 3]
+ *  [byte 12] error
+ *  [byte 13] status
+ * bit      0 : du:1
+ * bit      1 : eop:1
+ * bit      2 : error:1
+ * bit      3 : mi:1
+ * bit      4 : l3_identified:1
+ * bit      5 : l4_identified:1
+ * bit      6 : phy_info_included:1
+ * bit      7 : reserved:1
+ *  [word 7] length
+ *
+ */
+
+#define RX_DMA_D0_CMD_DMA_IT     BIT(10)
+
+#define RX_DMA_STATUS_DU         BIT(0)
+#define RX_DMA_STATUS_ERROR      BIT(2)
+#define RX_DMA_STATUS_PHY_INFO   BIT(6)
+
+struct vring_rx_dma {
+	u32 d0;
+	u32 addr_low;
+	u16 addr_high;
+	u8  ip_length;
+	u8  b11;
+	u8  error;
+	u8  status;
+	u16 length;
+} __packed;
+
+struct vring_tx_desc {
+	struct vring_tx_mac mac;
+	struct vring_tx_dma dma;
+} __packed;
+
+struct vring_rx_desc {
+	struct vring_rx_mac mac;
+	struct vring_rx_dma dma;
+} __packed;
+
+union vring_desc {
+	struct vring_tx_desc tx;
+	struct vring_rx_desc rx;
+} __packed;
+
+static inline int wil_rxdesc_phy_length(volatile struct vring_rx_desc *d)
+{
+	return WIL_GET_BITS(d->dma.d0, 16, 29);
+}
+
+static inline int wil_rxdesc_mcs(volatile struct vring_rx_desc *d)
+{
+	return WIL_GET_BITS(d->mac.d1, 21, 24);
+}
+
+static inline int wil_rxdesc_ds_bits(volatile struct vring_rx_desc *d)
+{
+	return WIL_GET_BITS(d->mac.d1, 8, 9);
+}
+
+static inline int wil_rxdesc_ftype(volatile struct vring_rx_desc *d)
+{
+	return WIL_GET_BITS(d->mac.d0, 10, 11);
+}
+
+#endif /* WIL6210_TXRX_H */
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
new file mode 100644
index 0000000..9bcfffa
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -0,0 +1,363 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef __WIL6210_H__
+#define __WIL6210_H__
+
+#include <linux/netdevice.h>
+#include <linux/wireless.h>
+#include <net/cfg80211.h>
+
+#include "dbg_hexdump.h"
+
+#define WIL_NAME "wil6210"
+
+/**
+ * extract bits [@b0:@b1] (inclusive) from the value @x
+ * it should be @b0 <= @b1, or result is incorrect
+ */
+static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
+{
+	return (x >> b0) & ((1 << (b1 - b0 + 1)) - 1);
+}
+
+#define WIL6210_MEM_SIZE (2*1024*1024UL)
+
+#define WIL6210_TX_QUEUES (4)
+
+#define WIL6210_RX_RING_SIZE (128)
+#define WIL6210_TX_RING_SIZE (128)
+#define WIL6210_MAX_TX_RINGS (24)
+
+/* Hardware definitions begin */
+
+/*
+ * Mapping
+ * RGF File      | Host addr    |  FW addr
+ *               |              |
+ * user_rgf      | 0x000000     | 0x880000
+ *  dma_rgf      | 0x001000     | 0x881000
+ * pcie_rgf      | 0x002000     | 0x882000
+ *               |              |
+ */
+
+/* Where various structures placed in host address space */
+#define WIL6210_FW_HOST_OFF      (0x880000UL)
+
+#define HOSTADDR(fwaddr)        (fwaddr - WIL6210_FW_HOST_OFF)
+
+/*
+ * Interrupt control registers block
+ *
+ * each interrupt controlled by the same bit in all registers
+ */
+struct RGF_ICR {
+	u32 ICC; /* Cause Control, RW: 0 - W1C, 1 - COR */
+	u32 ICR; /* Cause, W1C/COR depending on ICC */
+	u32 ICM; /* Cause masked (ICR & ~IMV), W1C/COR depending on ICC */
+	u32 ICS; /* Cause Set, WO */
+	u32 IMV; /* Mask, RW+S/C */
+	u32 IMS; /* Mask Set, write 1 to set */
+	u32 IMC; /* Mask Clear, write 1 to clear */
+} __packed;
+
+/* registers - FW addresses */
+#define RGF_USER_USER_SCRATCH_PAD	(0x8802bc)
+#define RGF_USER_USER_ICR		(0x880b4c) /* struct RGF_ICR */
+	#define BIT_USER_USER_ICR_SW_INT_2	BIT(18)
+#define RGF_USER_CLKS_CTL_SW_RST_MASK_0	(0x880b14)
+#define RGF_USER_MAC_CPU_0		(0x8801fc)
+#define RGF_USER_USER_CPU_0		(0x8801e0)
+#define RGF_USER_CLKS_CTL_SW_RST_VEC_0	(0x880b04)
+#define RGF_USER_CLKS_CTL_SW_RST_VEC_1	(0x880b08)
+#define RGF_USER_CLKS_CTL_SW_RST_VEC_2	(0x880b0c)
+#define RGF_USER_CLKS_CTL_SW_RST_VEC_3	(0x880b10)
+
+#define RGF_DMA_PSEUDO_CAUSE		(0x881c68)
+#define RGF_DMA_PSEUDO_CAUSE_MASK_SW	(0x881c6c)
+#define RGF_DMA_PSEUDO_CAUSE_MASK_FW	(0x881c70)
+	#define BIT_DMA_PSEUDO_CAUSE_RX		BIT(0)
+	#define BIT_DMA_PSEUDO_CAUSE_TX		BIT(1)
+	#define BIT_DMA_PSEUDO_CAUSE_MISC	BIT(2)
+
+#define RGF_DMA_EP_TX_ICR		(0x881bb4) /* struct RGF_ICR */
+	#define BIT_DMA_EP_TX_ICR_TX_DONE	BIT(0)
+	#define BIT_DMA_EP_TX_ICR_TX_DONE_N(n)	BIT(n+1) /* n = [0..23] */
+#define RGF_DMA_EP_RX_ICR		(0x881bd0) /* struct RGF_ICR */
+	#define BIT_DMA_EP_RX_ICR_RX_DONE	BIT(0)
+#define RGF_DMA_EP_MISC_ICR		(0x881bec) /* struct RGF_ICR */
+	#define BIT_DMA_EP_MISC_ICR_RX_HTRSH	BIT(0)
+	#define BIT_DMA_EP_MISC_ICR_TX_NO_ACT	BIT(1)
+	#define BIT_DMA_EP_MISC_ICR_FW_INT0	BIT(28)
+	#define BIT_DMA_EP_MISC_ICR_FW_INT1	BIT(29)
+
+/* Interrupt moderation control */
+#define RGF_DMA_ITR_CNT_TRSH		(0x881c5c)
+#define RGF_DMA_ITR_CNT_DATA		(0x881c60)
+#define RGF_DMA_ITR_CNT_CRL		(0x881C64)
+	#define BIT_DMA_ITR_CNT_CRL_EN		BIT(0)
+	#define BIT_DMA_ITR_CNT_CRL_EXT_TICK	BIT(1)
+	#define BIT_DMA_ITR_CNT_CRL_FOREVER	BIT(2)
+	#define BIT_DMA_ITR_CNT_CRL_CLR		BIT(3)
+	#define BIT_DMA_ITR_CNT_CRL_REACH_TRSH	BIT(4)
+
+/* popular locations */
+#define HOST_MBOX   HOSTADDR(RGF_USER_USER_SCRATCH_PAD)
+#define HOST_SW_INT (HOSTADDR(RGF_USER_USER_ICR) + \
+	offsetof(struct RGF_ICR, ICS))
+#define SW_INT_MBOX BIT_USER_USER_ICR_SW_INT_2
+
+/* ISR register bits */
+#define ISR_MISC_FW_READY BIT_DMA_EP_MISC_ICR_FW_INT0
+#define ISR_MISC_MBOX_EVT BIT_DMA_EP_MISC_ICR_FW_INT1
+
+/* Hardware definitions end */
+
+struct wil6210_mbox_ring {
+	u32 base;
+	u16 entry_size; /* max. size of mbox entry, incl. all headers */
+	u16 size;
+	u32 tail;
+	u32 head;
+} __packed;
+
+struct wil6210_mbox_ring_desc {
+	__le32 sync;
+	__le32 addr;
+} __packed;
+
+/* at HOST_OFF_WIL6210_MBOX_CTL */
+struct wil6210_mbox_ctl {
+	struct wil6210_mbox_ring tx;
+	struct wil6210_mbox_ring rx;
+} __packed;
+
+struct wil6210_mbox_hdr {
+	__le16 seq;
+	__le16 len; /* payload, bytes after this header */
+	__le16 type;
+	u8 flags;
+	u8 reserved;
+} __packed;
+
+#define WIL_MBOX_HDR_TYPE_WMI (0)
+
+/* max. value for wil6210_mbox_hdr.len */
+#define MAX_MBOXITEM_SIZE   (240)
+
+struct wil6210_mbox_hdr_wmi {
+	u8 reserved0[2];
+	__le16 id;
+	__le16 info1; /* bits [0..3] - device_id, rest - unused */
+	u8 reserved1[2];
+} __packed;
+
+struct pending_wmi_event {
+	struct list_head list;
+	struct {
+		struct wil6210_mbox_hdr hdr;
+		struct wil6210_mbox_hdr_wmi wmi;
+		u8 data[0];
+	} __packed event;
+};
+
+union vring_desc;
+
+struct vring {
+	dma_addr_t pa;
+	volatile union vring_desc *va; /* vring_desc[size], WriteBack by DMA */
+	u16 size; /* number of vring_desc elements */
+	u32 swtail;
+	u32 swhead;
+	u32 hwtail; /* write here to inform hw */
+	void **ctx; /* void *ctx[size] - software context */
+};
+
+enum { /* for wil6210_priv.status */
+	wil_status_fwready = 0,
+	wil_status_fwconnected,
+	wil_status_dontscan,
+	wil_status_irqen, /* FIXME: interrupts enabled - for debug */
+};
+
+struct pci_dev;
+
+struct wil6210_stats {
+	u64 tsf;
+	u32 snr;
+	u16 last_mcs_rx;
+	u16 bf_mcs; /* last BF, used for Tx */
+	u16 my_rx_sector;
+	u16 my_tx_sector;
+	u16 peer_rx_sector;
+	u16 peer_tx_sector;
+};
+
+struct wil6210_priv {
+	struct pci_dev *pdev;
+	int n_msi;
+	struct wireless_dev *wdev;
+	void __iomem *csr;
+	ulong status;
+	/* profile */
+	u32 monitor_flags;
+	u32 secure_pcp; /* create secure PCP? */
+	int sinfo_gen;
+	/* cached ISR registers */
+	u32 isr_misc;
+	/* mailbox related */
+	struct mutex wmi_mutex;
+	struct wil6210_mbox_ctl mbox_ctl;
+	struct completion wmi_ready;
+	u16 wmi_seq;
+	u16 reply_id; /**< wait for this WMI event */
+	void *reply_buf;
+	u16 reply_size;
+	struct workqueue_struct *wmi_wq; /* for deferred calls */
+	struct work_struct wmi_event_worker;
+	struct workqueue_struct *wmi_wq_conn; /* for connect worker */
+	struct work_struct wmi_connect_worker;
+	struct work_struct disconnect_worker;
+	struct timer_list connect_timer;
+	int pending_connect_cid;
+	struct list_head pending_wmi_ev;
+	/*
+	 * protect pending_wmi_ev
+	 * - fill in IRQ from wil6210_irq_misc,
+	 * - consumed in thread by wmi_event_worker
+	 */
+	spinlock_t wmi_ev_lock;
+	/* DMA related */
+	struct vring vring_rx;
+	struct vring vring_tx[WIL6210_MAX_TX_RINGS];
+	u8 dst_addr[WIL6210_MAX_TX_RINGS][ETH_ALEN];
+	/* scan */
+	struct cfg80211_scan_request *scan_request;
+
+	struct mutex mutex; /* for wil6210_priv access in wil_{up|down} */
+	/* statistics */
+	struct wil6210_stats stats;
+	/* debugfs */
+	struct dentry *debug;
+	struct debugfs_blob_wrapper fw_code_blob;
+	struct debugfs_blob_wrapper fw_data_blob;
+	struct debugfs_blob_wrapper fw_peri_blob;
+	struct debugfs_blob_wrapper uc_code_blob;
+	struct debugfs_blob_wrapper uc_data_blob;
+	struct debugfs_blob_wrapper rgf_blob;
+};
+
+#define wil_to_wiphy(i) (i->wdev->wiphy)
+#define wil_to_dev(i) (wiphy_dev(wil_to_wiphy(i)))
+#define wiphy_to_wil(w) (struct wil6210_priv *)(wiphy_priv(w))
+#define wil_to_wdev(i) (i->wdev)
+#define wdev_to_wil(w) (struct wil6210_priv *)(wdev_priv(w))
+#define wil_to_ndev(i) (wil_to_wdev(i)->netdev)
+#define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr))
+
+#define wil_dbg(wil, fmt, arg...) netdev_dbg(wil_to_ndev(wil), fmt, ##arg)
+#define wil_info(wil, fmt, arg...) netdev_info(wil_to_ndev(wil), fmt, ##arg)
+#define wil_err(wil, fmt, arg...) netdev_err(wil_to_ndev(wil), fmt, ##arg)
+
+#define wil_dbg_IRQ(wil, fmt, arg...) wil_dbg(wil, "DBG[ IRQ]" fmt, ##arg)
+#define wil_dbg_TXRX(wil, fmt, arg...) wil_dbg(wil, "DBG[TXRX]" fmt, ##arg)
+#define wil_dbg_WMI(wil, fmt, arg...) wil_dbg(wil, "DBG[ WMI]" fmt, ##arg)
+
+#define wil_hex_dump_TXRX(prefix_str, prefix_type, rowsize,	\
+			  groupsize, buf, len, ascii)		\
+			  wil_print_hex_dump_debug("DBG[TXRX]" prefix_str,\
+					 prefix_type, rowsize,	\
+					 groupsize, buf, len, ascii)
+
+#define wil_hex_dump_WMI(prefix_str, prefix_type, rowsize,	\
+			 groupsize, buf, len, ascii)		\
+			 wil_print_hex_dump_debug("DBG[ WMI]" prefix_str,\
+					prefix_type, rowsize,	\
+					groupsize, buf, len, ascii)
+
+void wil_memcpy_fromio_32(void *dst, const volatile void __iomem *src,
+			  size_t count);
+void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src,
+			size_t count);
+
+void *wil_if_alloc(struct device *dev, void __iomem *csr);
+void wil_if_free(struct wil6210_priv *wil);
+int wil_if_add(struct wil6210_priv *wil);
+void wil_if_remove(struct wil6210_priv *wil);
+int wil_priv_init(struct wil6210_priv *wil);
+void wil_priv_deinit(struct wil6210_priv *wil);
+int wil_reset(struct wil6210_priv *wil);
+void wil_link_on(struct wil6210_priv *wil);
+void wil_link_off(struct wil6210_priv *wil);
+int wil_up(struct wil6210_priv *wil);
+int wil_down(struct wil6210_priv *wil);
+void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r);
+
+void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr);
+void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr);
+int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
+		 struct wil6210_mbox_hdr *hdr);
+int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len);
+void wmi_recv_cmd(struct wil6210_priv *wil);
+int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
+	     u16 reply_id, void *reply, u8 reply_size, int to_msec);
+void wmi_connect_worker(struct work_struct *work);
+void wmi_event_worker(struct work_struct *work);
+void wmi_event_flush(struct wil6210_priv *wil);
+int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid);
+int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid);
+int wmi_set_channel(struct wil6210_priv *wil, int channel);
+int wmi_get_channel(struct wil6210_priv *wil, int *channel);
+int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb);
+int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
+		       const void *mac_addr);
+int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
+		       const void *mac_addr, int key_len, const void *key);
+int wmi_echo(struct wil6210_priv *wil);
+int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie);
+
+int wil6210_init_irq(struct wil6210_priv *wil, int irq);
+void wil6210_fini_irq(struct wil6210_priv *wil, int irq);
+void wil6210_disable_irq(struct wil6210_priv *wil);
+void wil6210_enable_irq(struct wil6210_priv *wil);
+
+int wil6210_debugfs_init(struct wil6210_priv *wil);
+void wil6210_debugfs_remove(struct wil6210_priv *wil);
+
+struct wireless_dev *wil_cfg80211_init(struct device *dev);
+void wil_wdev_free(struct wil6210_priv *wil);
+
+int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
+int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype);
+void wil6210_disconnect(struct wil6210_priv *wil, void *bssid);
+
+int wil_rx_init(struct wil6210_priv *wil);
+void wil_rx_fini(struct wil6210_priv *wil);
+
+/* TX API */
+int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size,
+		      int cid, int tid);
+void wil_vring_fini_tx(struct wil6210_priv *wil, int id);
+
+netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+void wil_tx_complete(struct wil6210_priv *wil, int ringid);
+
+/* RX API */
+void wil_rx_handle(struct wil6210_priv *wil);
+
+int wil_iftype_nl2wmi(enum nl80211_iftype type);
+
+#endif /* __WIL6210_H__ */
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
new file mode 100644
index 0000000..12915f6
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -0,0 +1,975 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/pci.h>
+#include <linux/io.h>
+#include <linux/list.h>
+#include <linux/etherdevice.h>
+
+#include "wil6210.h"
+#include "wmi.h"
+
+/**
+ * WMI event receiving - theory of operations
+ *
+ * When firmware about to report WMI event, it fills memory area
+ * in the mailbox and raises misc. IRQ. Thread interrupt handler invoked for
+ * the misc IRQ, function @wmi_recv_cmd called by thread IRQ handler.
+ *
+ * @wmi_recv_cmd reads event, allocates memory chunk  and attaches it to the
+ * event list @wil->pending_wmi_ev. Then, work queue @wil->wmi_wq wakes up
+ * and handles events within the @wmi_event_worker. Every event get detached
+ * from list, processed and deleted.
+ *
+ * Purpose for this mechanism is to release IRQ thread; otherwise,
+ * if WMI event handling involves another WMI command flow, this 2-nd flow
+ * won't be completed because of blocked IRQ thread.
+ */
+
+/**
+ * Addressing - theory of operations
+ *
+ * There are several buses present on the WIL6210 card.
+ * Same memory areas are visible at different address on
+ * the different busses. There are 3 main bus masters:
+ *  - MAC CPU (ucode)
+ *  - User CPU (firmware)
+ *  - AHB (host)
+ *
+ * On the PCI bus, there is one BAR (BAR0) of 2Mb size, exposing
+ * AHB addresses starting from 0x880000
+ *
+ * Internally, firmware uses addresses that allows faster access but
+ * are invisible from the host. To read from these addresses, alternative
+ * AHB address must be used.
+ *
+ * Memory mapping
+ * Linker address         PCI/Host address
+ *                        0x880000 .. 0xa80000  2Mb BAR0
+ * 0x800000 .. 0x807000   0x900000 .. 0x907000  28k DCCM
+ * 0x840000 .. 0x857000   0x908000 .. 0x91f000  92k PERIPH
+ */
+
+/**
+ * @fw_mapping provides memory remapping table
+ */
+static const struct {
+	u32 from; /* linker address - from, inclusive */
+	u32 to;   /* linker address - to, exclusive */
+	u32 host; /* PCI/Host address - BAR0 + 0x880000 */
+} fw_mapping[] = {
+	{0x000000, 0x040000, 0x8c0000}, /* FW code RAM 256k */
+	{0x800000, 0x808000, 0x900000}, /* FW data RAM 32k */
+	{0x840000, 0x860000, 0x908000}, /* peripheral data RAM 128k/96k used */
+	{0x880000, 0x88a000, 0x880000}, /* various RGF */
+	{0x8c0000, 0x932000, 0x8c0000}, /* trivial mapping for upper area */
+	/*
+	 * 920000..930000 ucode code RAM
+	 * 930000..932000 ucode data RAM
+	 */
+};
+
+/**
+ * return AHB address for given firmware/ucode internal (linker) address
+ * @x - internal address
+ * If address have no valid AHB mapping, return 0
+ */
+static u32 wmi_addr_remap(u32 x)
+{
+	uint i;
+
+	for (i = 0; i < ARRAY_SIZE(fw_mapping); i++) {
+		if ((x >= fw_mapping[i].from) && (x < fw_mapping[i].to))
+			return x + fw_mapping[i].host - fw_mapping[i].from;
+	}
+
+	return 0;
+}
+
+/**
+ * Check address validity for WMI buffer; remap if needed
+ * @ptr - internal (linker) fw/ucode address
+ *
+ * Valid buffer should be DWORD aligned
+ *
+ * return address for accessing buffer from the host;
+ * if buffer is not valid, return NULL.
+ */
+void __iomem *wmi_buffer(struct wil6210_priv *wil, __le32 ptr_)
+{
+	u32 off;
+	u32 ptr = le32_to_cpu(ptr_);
+
+	if (ptr % 4)
+		return NULL;
+
+	ptr = wmi_addr_remap(ptr);
+	if (ptr < WIL6210_FW_HOST_OFF)
+		return NULL;
+
+	off = HOSTADDR(ptr);
+	if (off > WIL6210_MEM_SIZE - 4)
+		return NULL;
+
+	return wil->csr + off;
+}
+
+/**
+ * Check address validity
+ */
+void __iomem *wmi_addr(struct wil6210_priv *wil, u32 ptr)
+{
+	u32 off;
+
+	if (ptr % 4)
+		return NULL;
+
+	if (ptr < WIL6210_FW_HOST_OFF)
+		return NULL;
+
+	off = HOSTADDR(ptr);
+	if (off > WIL6210_MEM_SIZE - 4)
+		return NULL;
+
+	return wil->csr + off;
+}
+
+int wmi_read_hdr(struct wil6210_priv *wil, __le32 ptr,
+		 struct wil6210_mbox_hdr *hdr)
+{
+	void __iomem *src = wmi_buffer(wil, ptr);
+	if (!src)
+		return -EINVAL;
+
+	wil_memcpy_fromio_32(hdr, src, sizeof(*hdr));
+
+	return 0;
+}
+
+static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
+{
+	struct {
+		struct wil6210_mbox_hdr hdr;
+		struct wil6210_mbox_hdr_wmi wmi;
+	} __packed cmd = {
+		.hdr = {
+			.type = WIL_MBOX_HDR_TYPE_WMI,
+			.flags = 0,
+			.len = cpu_to_le16(sizeof(cmd.wmi) + len),
+		},
+		.wmi = {
+			.id = cpu_to_le16(cmdid),
+			.info1 = 0,
+		},
+	};
+	struct wil6210_mbox_ring *r = &wil->mbox_ctl.tx;
+	struct wil6210_mbox_ring_desc d_head;
+	u32 next_head;
+	void __iomem *dst;
+	void __iomem *head = wmi_addr(wil, r->head);
+	uint retry;
+
+	if (sizeof(cmd) + len > r->entry_size) {
+		wil_err(wil, "WMI size too large: %d bytes, max is %d\n",
+			(int)(sizeof(cmd) + len), r->entry_size);
+		return -ERANGE;
+
+	}
+
+	might_sleep();
+
+	if (!test_bit(wil_status_fwready, &wil->status)) {
+		wil_err(wil, "FW not ready\n");
+		return -EAGAIN;
+	}
+
+	if (!head) {
+		wil_err(wil, "WMI head is garbage: 0x%08x\n", r->head);
+		return -EINVAL;
+	}
+	/* read Tx head till it is not busy */
+	for (retry = 5; retry > 0; retry--) {
+		wil_memcpy_fromio_32(&d_head, head, sizeof(d_head));
+		if (d_head.sync == 0)
+			break;
+		msleep(20);
+	}
+	if (d_head.sync != 0) {
+		wil_err(wil, "WMI head busy\n");
+		return -EBUSY;
+	}
+	/* next head */
+	next_head = r->base + ((r->head - r->base + sizeof(d_head)) % r->size);
+	wil_dbg_WMI(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head);
+	/* wait till FW finish with previous command */
+	for (retry = 5; retry > 0; retry--) {
+		r->tail = ioread32(wil->csr + HOST_MBOX +
+				   offsetof(struct wil6210_mbox_ctl, tx.tail));
+		if (next_head != r->tail)
+			break;
+		msleep(20);
+	}
+	if (next_head == r->tail) {
+		wil_err(wil, "WMI ring full\n");
+		return -EBUSY;
+	}
+	dst = wmi_buffer(wil, d_head.addr);
+	if (!dst) {
+		wil_err(wil, "invalid WMI buffer: 0x%08x\n",
+			le32_to_cpu(d_head.addr));
+		return -EINVAL;
+	}
+	cmd.hdr.seq = cpu_to_le16(++wil->wmi_seq);
+	/* set command */
+	wil_dbg_WMI(wil, "WMI command 0x%04x [%d]\n", cmdid, len);
+	wil_hex_dump_WMI("Cmd ", DUMP_PREFIX_OFFSET, 16, 1, &cmd,
+			 sizeof(cmd), true);
+	wil_hex_dump_WMI("cmd ", DUMP_PREFIX_OFFSET, 16, 1, buf,
+			 len, true);
+	wil_memcpy_toio_32(dst, &cmd, sizeof(cmd));
+	wil_memcpy_toio_32(dst + sizeof(cmd), buf, len);
+	/* mark entry as full */
+	iowrite32(1, wil->csr + HOSTADDR(r->head) +
+		  offsetof(struct wil6210_mbox_ring_desc, sync));
+	/* advance next ptr */
+	iowrite32(r->head = next_head, wil->csr + HOST_MBOX +
+		  offsetof(struct wil6210_mbox_ctl, tx.head));
+
+	/* interrupt to FW */
+	iowrite32(SW_INT_MBOX, wil->csr + HOST_SW_INT);
+
+	return 0;
+}
+
+int wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len)
+{
+	int rc;
+
+	mutex_lock(&wil->wmi_mutex);
+	rc = __wmi_send(wil, cmdid, buf, len);
+	mutex_unlock(&wil->wmi_mutex);
+
+	return rc;
+}
+
+/*=== Event handlers ===*/
+static void wmi_evt_ready(struct wil6210_priv *wil, int id, void *d, int len)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct wireless_dev *wdev = wil->wdev;
+	struct wmi_ready_event *evt = d;
+	u32 ver = le32_to_cpu(evt->sw_version);
+
+	wil_dbg_WMI(wil, "FW ver. %d; MAC %pM\n", ver, evt->mac);
+
+	if (!is_valid_ether_addr(ndev->dev_addr)) {
+		memcpy(ndev->dev_addr, evt->mac, ETH_ALEN);
+		memcpy(ndev->perm_addr, evt->mac, ETH_ALEN);
+	}
+	snprintf(wdev->wiphy->fw_version, sizeof(wdev->wiphy->fw_version),
+		 "%d", ver);
+}
+
+static void wmi_evt_fw_ready(struct wil6210_priv *wil, int id, void *d,
+			     int len)
+{
+	wil_dbg_WMI(wil, "WMI: FW ready\n");
+
+	set_bit(wil_status_fwready, &wil->status);
+	/* reuse wmi_ready for the firmware ready indication */
+	complete(&wil->wmi_ready);
+}
+
+static void wmi_evt_rx_mgmt(struct wil6210_priv *wil, int id, void *d, int len)
+{
+	struct wmi_rx_mgmt_packet_event *data = d;
+	struct wiphy *wiphy = wil_to_wiphy(wil);
+	struct ieee80211_mgmt *rx_mgmt_frame =
+			(struct ieee80211_mgmt *)data->payload;
+	int ch_no = data->info.channel+1;
+	u32 freq = ieee80211_channel_to_frequency(ch_no,
+			IEEE80211_BAND_60GHZ);
+	struct ieee80211_channel *channel = ieee80211_get_channel(wiphy, freq);
+	/* TODO convert LE to CPU */
+	s32 signal = 0; /* TODO */
+	__le16 fc = rx_mgmt_frame->frame_control;
+	u32 d_len = le32_to_cpu(data->info.len);
+	u16 d_status = le16_to_cpu(data->info.status);
+
+	wil_dbg_WMI(wil, "MGMT: channel %d MCS %d SNR %d\n",
+		    data->info.channel, data->info.mcs, data->info.snr);
+	wil_dbg_WMI(wil, "status 0x%04x len %d stype %04x\n", d_status, d_len,
+		    le16_to_cpu(data->info.stype));
+	wil_dbg_WMI(wil, "qid %d mid %d cid %d\n",
+		    data->info.qid, data->info.mid, data->info.cid);
+
+	if (!channel) {
+		wil_err(wil, "Frame on unsupported channel\n");
+		return;
+	}
+
+	if (ieee80211_is_beacon(fc) || ieee80211_is_probe_resp(fc)) {
+		struct cfg80211_bss *bss;
+		u64 tsf = le64_to_cpu(rx_mgmt_frame->u.beacon.timestamp);
+		u16 cap = le16_to_cpu(rx_mgmt_frame->u.beacon.capab_info);
+		u16 bi = le16_to_cpu(rx_mgmt_frame->u.beacon.beacon_int);
+		const u8 *ie_buf = rx_mgmt_frame->u.beacon.variable;
+		size_t ie_len = d_len - offsetof(struct ieee80211_mgmt,
+						 u.beacon.variable);
+		wil_dbg_WMI(wil, "Capability info : 0x%04x\n", cap);
+
+		bss = cfg80211_inform_bss(wiphy, channel, rx_mgmt_frame->bssid,
+					  tsf, cap, bi, ie_buf, ie_len,
+					  signal, GFP_KERNEL);
+		if (bss) {
+			wil_dbg_WMI(wil, "Added BSS %pM\n",
+				    rx_mgmt_frame->bssid);
+			cfg80211_put_bss(bss);
+		} else {
+			wil_err(wil, "cfg80211_inform_bss() failed\n");
+		}
+	}
+}
+
+static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
+				  void *d, int len)
+{
+	if (wil->scan_request) {
+		struct wmi_scan_complete_event *data = d;
+		bool aborted = (data->status != 0);
+
+		wil_dbg_WMI(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
+		cfg80211_scan_done(wil->scan_request, aborted);
+		wil->scan_request = NULL;
+	} else {
+		wil_err(wil, "SCAN_COMPLETE while not scanning\n");
+	}
+}
+
+static void wmi_evt_connect(struct wil6210_priv *wil, int id, void *d, int len)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct wireless_dev *wdev = wil->wdev;
+	struct wmi_connect_event *evt = d;
+	int ch; /* channel number */
+	struct station_info sinfo;
+	u8 *assoc_req_ie, *assoc_resp_ie;
+	size_t assoc_req_ielen, assoc_resp_ielen;
+	/* capinfo(u16) + listen_interval(u16) + IEs */
+	const size_t assoc_req_ie_offset = sizeof(u16) * 2;
+	/* capinfo(u16) + status_code(u16) + associd(u16) + IEs */
+	const size_t assoc_resp_ie_offset = sizeof(u16) * 3;
+
+	if (len < sizeof(*evt)) {
+		wil_err(wil, "Connect event too short : %d bytes\n", len);
+		return;
+	}
+	if (len != sizeof(*evt) + evt->beacon_ie_len + evt->assoc_req_len +
+		   evt->assoc_resp_len) {
+		wil_err(wil,
+			"Connect event corrupted : %d != %d + %d + %d + %d\n",
+			len, (int)sizeof(*evt), evt->beacon_ie_len,
+			evt->assoc_req_len, evt->assoc_resp_len);
+		return;
+	}
+	ch = evt->channel + 1;
+	wil_dbg_WMI(wil, "Connect %pM channel [%d] cid %d\n",
+		    evt->bssid, ch, evt->cid);
+	wil_hex_dump_WMI("connect AI : ", DUMP_PREFIX_OFFSET, 16, 1,
+			 evt->assoc_info, len - sizeof(*evt), true);
+
+	/* figure out IE's */
+	assoc_req_ie = &evt->assoc_info[evt->beacon_ie_len +
+					assoc_req_ie_offset];
+	assoc_req_ielen = evt->assoc_req_len - assoc_req_ie_offset;
+	if (evt->assoc_req_len <= assoc_req_ie_offset) {
+		assoc_req_ie = NULL;
+		assoc_req_ielen = 0;
+	}
+
+	assoc_resp_ie = &evt->assoc_info[evt->beacon_ie_len +
+					 evt->assoc_req_len +
+					 assoc_resp_ie_offset];
+	assoc_resp_ielen = evt->assoc_resp_len - assoc_resp_ie_offset;
+	if (evt->assoc_resp_len <= assoc_resp_ie_offset) {
+		assoc_resp_ie = NULL;
+		assoc_resp_ielen = 0;
+	}
+
+	if ((wdev->iftype == NL80211_IFTYPE_STATION) ||
+	    (wdev->iftype == NL80211_IFTYPE_P2P_CLIENT)) {
+		if (wdev->sme_state != CFG80211_SME_CONNECTING) {
+			wil_err(wil, "Not in connecting state\n");
+			return;
+		}
+		del_timer_sync(&wil->connect_timer);
+		cfg80211_connect_result(ndev, evt->bssid,
+					assoc_req_ie, assoc_req_ielen,
+					assoc_resp_ie, assoc_resp_ielen,
+					WLAN_STATUS_SUCCESS, GFP_KERNEL);
+
+	} else if ((wdev->iftype == NL80211_IFTYPE_AP) ||
+		   (wdev->iftype == NL80211_IFTYPE_P2P_GO)) {
+		memset(&sinfo, 0, sizeof(sinfo));
+
+		sinfo.generation = wil->sinfo_gen++;
+
+		if (assoc_req_ie) {
+			sinfo.assoc_req_ies = assoc_req_ie;
+			sinfo.assoc_req_ies_len = assoc_req_ielen;
+			sinfo.filled |= STATION_INFO_ASSOC_REQ_IES;
+		}
+
+		cfg80211_new_sta(ndev, evt->bssid, &sinfo, GFP_KERNEL);
+	}
+	set_bit(wil_status_fwconnected, &wil->status);
+
+	/* FIXME FW can transmit only ucast frames to peer */
+	/* FIXME real ring_id instead of hard coded 0 */
+	memcpy(wil->dst_addr[0], evt->bssid, ETH_ALEN);
+
+	wil->pending_connect_cid = evt->cid;
+	queue_work(wil->wmi_wq_conn, &wil->wmi_connect_worker);
+}
+
+static void wmi_evt_disconnect(struct wil6210_priv *wil, int id,
+			       void *d, int len)
+{
+	struct wmi_disconnect_event *evt = d;
+
+	wil_dbg_WMI(wil, "Disconnect %pM reason %d proto %d wmi\n",
+		    evt->bssid,
+		    evt->protocol_reason_status, evt->disconnect_reason);
+
+	wil->sinfo_gen++;
+
+	wil6210_disconnect(wil, evt->bssid);
+	clear_bit(wil_status_dontscan, &wil->status);
+}
+
+static void wmi_evt_notify(struct wil6210_priv *wil, int id, void *d, int len)
+{
+	struct wmi_notify_req_done_event *evt = d;
+
+	if (len < sizeof(*evt)) {
+		wil_err(wil, "Short NOTIFY event\n");
+		return;
+	}
+
+	wil->stats.tsf = le64_to_cpu(evt->tsf);
+	wil->stats.snr = le32_to_cpu(evt->snr_val);
+	wil->stats.bf_mcs = le16_to_cpu(evt->bf_mcs);
+	wil->stats.my_rx_sector = le16_to_cpu(evt->my_rx_sector);
+	wil->stats.my_tx_sector = le16_to_cpu(evt->my_tx_sector);
+	wil->stats.peer_rx_sector = le16_to_cpu(evt->other_rx_sector);
+	wil->stats.peer_tx_sector = le16_to_cpu(evt->other_tx_sector);
+	wil_dbg_WMI(wil, "Link status, MCS %d TSF 0x%016llx\n"
+		    "BF status 0x%08x SNR 0x%08x\n"
+		    "Tx Tpt %d goodput %d Rx goodput %d\n"
+		    "Sectors(rx:tx) my %d:%d peer %d:%d\n",
+		    wil->stats.bf_mcs, wil->stats.tsf, evt->status,
+		    wil->stats.snr, le32_to_cpu(evt->tx_tpt),
+		    le32_to_cpu(evt->tx_goodput), le32_to_cpu(evt->rx_goodput),
+		    wil->stats.my_rx_sector, wil->stats.my_tx_sector,
+		    wil->stats.peer_rx_sector, wil->stats.peer_tx_sector);
+}
+
+/*
+ * Firmware reports EAPOL frame using WME event.
+ * Reconstruct Ethernet frame and deliver it via normal Rx
+ */
+static void wmi_evt_eapol_rx(struct wil6210_priv *wil, int id,
+			     void *d, int len)
+{
+	struct net_device *ndev = wil_to_ndev(wil);
+	struct wmi_eapol_rx_event *evt = d;
+	u16 eapol_len = le16_to_cpu(evt->eapol_len);
+	int sz = eapol_len + ETH_HLEN;
+	struct sk_buff *skb;
+	struct ethhdr *eth;
+
+	wil_dbg_WMI(wil, "EAPOL len %d from %pM\n", eapol_len,
+		    evt->src_mac);
+
+	if (eapol_len > 196) { /* TODO: revisit size limit */
+		wil_err(wil, "EAPOL too large\n");
+		return;
+	}
+
+	skb = alloc_skb(sz, GFP_KERNEL);
+	if (!skb) {
+		wil_err(wil, "Failed to allocate skb\n");
+		return;
+	}
+	eth = (struct ethhdr *)skb_put(skb, ETH_HLEN);
+	memcpy(eth->h_dest, ndev->dev_addr, ETH_ALEN);
+	memcpy(eth->h_source, evt->src_mac, ETH_ALEN);
+	eth->h_proto = cpu_to_be16(ETH_P_PAE);
+	memcpy(skb_put(skb, eapol_len), evt->eapol, eapol_len);
+	skb->protocol = eth_type_trans(skb, ndev);
+	if (likely(netif_rx_ni(skb) == NET_RX_SUCCESS)) {
+		ndev->stats.rx_packets++;
+		ndev->stats.rx_bytes += skb->len;
+	} else {
+		ndev->stats.rx_dropped++;
+	}
+}
+
+static const struct {
+	int eventid;
+	void (*handler)(struct wil6210_priv *wil, int eventid,
+			void *data, int data_len);
+} wmi_evt_handlers[] = {
+	{WMI_READY_EVENTID,		wmi_evt_ready},
+	{WMI_FW_READY_EVENTID,		wmi_evt_fw_ready},
+	{WMI_RX_MGMT_PACKET_EVENTID,	wmi_evt_rx_mgmt},
+	{WMI_SCAN_COMPLETE_EVENTID,	wmi_evt_scan_complete},
+	{WMI_CONNECT_EVENTID,		wmi_evt_connect},
+	{WMI_DISCONNECT_EVENTID,	wmi_evt_disconnect},
+	{WMI_NOTIFY_REQ_DONE_EVENTID,	wmi_evt_notify},
+	{WMI_EAPOL_RX_EVENTID,		wmi_evt_eapol_rx},
+};
+
+/*
+ * Run in IRQ context
+ * Extract WMI command from mailbox. Queue it to the @wil->pending_wmi_ev
+ * that will be eventually handled by the @wmi_event_worker in the thread
+ * context of thread "wil6210_wmi"
+ */
+void wmi_recv_cmd(struct wil6210_priv *wil)
+{
+	struct wil6210_mbox_ring_desc d_tail;
+	struct wil6210_mbox_hdr hdr;
+	struct wil6210_mbox_ring *r = &wil->mbox_ctl.rx;
+	struct pending_wmi_event *evt;
+	u8 *cmd;
+	void __iomem *src;
+	ulong flags;
+
+	for (;;) {
+		u16 len;
+
+		r->head = ioread32(wil->csr + HOST_MBOX +
+				   offsetof(struct wil6210_mbox_ctl, rx.head));
+		if (r->tail == r->head)
+			return;
+
+		/* read cmd from tail */
+		wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail),
+				     sizeof(struct wil6210_mbox_ring_desc));
+		if (d_tail.sync == 0) {
+			wil_err(wil, "Mbox evt not owned by FW?\n");
+			return;
+		}
+
+		if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
+			wil_err(wil, "Mbox evt at 0x%08x?\n",
+				le32_to_cpu(d_tail.addr));
+			return;
+		}
+
+		len = le16_to_cpu(hdr.len);
+		src = wmi_buffer(wil, d_tail.addr) +
+		      sizeof(struct wil6210_mbox_hdr);
+		evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
+					     event.wmi) + len, 4),
+			      GFP_KERNEL);
+		if (!evt) {
+			wil_err(wil, "kmalloc for WMI event (%d) failed\n",
+				len);
+			return;
+		}
+		evt->event.hdr = hdr;
+		cmd = (void *)&evt->event.wmi;
+		wil_memcpy_fromio_32(cmd, src, len);
+		/* mark entry as empty */
+		iowrite32(0, wil->csr + HOSTADDR(r->tail) +
+			  offsetof(struct wil6210_mbox_ring_desc, sync));
+		/* indicate */
+		wil_dbg_WMI(wil, "Mbox evt %04x %04x %04x %02x\n",
+			    le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
+			    hdr.flags);
+		if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
+		    (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
+			wil_dbg_WMI(wil, "WMI event 0x%04x\n",
+				    evt->event.wmi.id);
+		}
+		wil_hex_dump_WMI("evt ", DUMP_PREFIX_OFFSET, 16, 1,
+				 &evt->event.hdr, sizeof(hdr) + len, true);
+
+		/* advance tail */
+		r->tail = r->base + ((r->tail - r->base +
+			  sizeof(struct wil6210_mbox_ring_desc)) % r->size);
+		iowrite32(r->tail, wil->csr + HOST_MBOX +
+			  offsetof(struct wil6210_mbox_ctl, rx.tail));
+
+		/* add to the pending list */
+		spin_lock_irqsave(&wil->wmi_ev_lock, flags);
+		list_add_tail(&evt->list, &wil->pending_wmi_ev);
+		spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
+		{
+			int q =	queue_work(wil->wmi_wq,
+					   &wil->wmi_event_worker);
+			wil_dbg_WMI(wil, "queue_work -> %d\n", q);
+		}
+	}
+}
+
+int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
+	     u16 reply_id, void *reply, u8 reply_size, int to_msec)
+{
+	int rc;
+	int remain;
+
+	mutex_lock(&wil->wmi_mutex);
+
+	rc = __wmi_send(wil, cmdid, buf, len);
+	if (rc)
+		goto out;
+
+	wil->reply_id = reply_id;
+	wil->reply_buf = reply;
+	wil->reply_size = reply_size;
+	remain = wait_for_completion_timeout(&wil->wmi_ready,
+			msecs_to_jiffies(to_msec));
+	if (0 == remain) {
+		wil_err(wil, "wmi_call(0x%04x->0x%04x) timeout %d msec\n",
+			cmdid, reply_id, to_msec);
+		rc = -ETIME;
+	} else {
+		wil_dbg_WMI(wil,
+			    "wmi_call(0x%04x->0x%04x) completed in %d msec\n",
+			    cmdid, reply_id,
+			    to_msec - jiffies_to_msecs(remain));
+	}
+	wil->reply_id = 0;
+	wil->reply_buf = NULL;
+	wil->reply_size = 0;
+ out:
+	mutex_unlock(&wil->wmi_mutex);
+
+	return rc;
+}
+
+int wmi_echo(struct wil6210_priv *wil)
+{
+	struct wmi_echo_cmd cmd = {
+		.value = cpu_to_le32(0x12345678),
+	};
+
+	return wmi_call(wil, WMI_ECHO_CMDID, &cmd, sizeof(cmd),
+			 WMI_ECHO_RSP_EVENTID, NULL, 0, 20);
+}
+
+int wmi_set_mac_address(struct wil6210_priv *wil, void *addr)
+{
+	struct wmi_set_mac_address_cmd cmd;
+
+	memcpy(cmd.mac, addr, ETH_ALEN);
+
+	wil_dbg_WMI(wil, "Set MAC %pM\n", addr);
+
+	return wmi_send(wil, WMI_SET_MAC_ADDRESS_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_set_bcon(struct wil6210_priv *wil, int bi, u8 wmi_nettype)
+{
+	struct wmi_bcon_ctrl_cmd cmd = {
+		.bcon_interval = cpu_to_le16(bi),
+		.network_type = wmi_nettype,
+		.disable_sec_offload = 1,
+	};
+
+	if (!wil->secure_pcp)
+		cmd.disable_sec = 1;
+
+	return wmi_send(wil, WMI_BCON_CTRL_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_set_ssid(struct wil6210_priv *wil, u8 ssid_len, const void *ssid)
+{
+	struct wmi_set_ssid_cmd cmd = {
+		.ssid_len = cpu_to_le32(ssid_len),
+	};
+
+	if (ssid_len > sizeof(cmd.ssid))
+		return -EINVAL;
+
+	memcpy(cmd.ssid, ssid, ssid_len);
+
+	return wmi_send(wil, WMI_SET_SSID_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_get_ssid(struct wil6210_priv *wil, u8 *ssid_len, void *ssid)
+{
+	int rc;
+	struct {
+		struct wil6210_mbox_hdr_wmi wmi;
+		struct wmi_set_ssid_cmd cmd;
+	} __packed reply;
+	int len; /* reply.cmd.ssid_len in CPU order */
+
+	rc = wmi_call(wil, WMI_GET_SSID_CMDID, NULL, 0, WMI_GET_SSID_EVENTID,
+		      &reply, sizeof(reply), 20);
+	if (rc)
+		return rc;
+
+	len = le32_to_cpu(reply.cmd.ssid_len);
+	if (len > sizeof(reply.cmd.ssid))
+		return -EINVAL;
+
+	*ssid_len = len;
+	memcpy(ssid, reply.cmd.ssid, len);
+
+	return 0;
+}
+
+int wmi_set_channel(struct wil6210_priv *wil, int channel)
+{
+	struct wmi_set_pcp_channel_cmd cmd = {
+		.channel = channel - 1,
+	};
+
+	return wmi_send(wil, WMI_SET_PCP_CHANNEL_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_get_channel(struct wil6210_priv *wil, int *channel)
+{
+	int rc;
+	struct {
+		struct wil6210_mbox_hdr_wmi wmi;
+		struct wmi_set_pcp_channel_cmd cmd;
+	} __packed reply;
+
+	rc = wmi_call(wil, WMI_GET_PCP_CHANNEL_CMDID, NULL, 0,
+		      WMI_GET_PCP_CHANNEL_EVENTID, &reply, sizeof(reply), 20);
+	if (rc)
+		return rc;
+
+	if (reply.cmd.channel > 3)
+		return -EINVAL;
+
+	*channel = reply.cmd.channel + 1;
+
+	return 0;
+}
+
+int wmi_tx_eapol(struct wil6210_priv *wil, struct sk_buff *skb)
+{
+	struct wmi_eapol_tx_cmd *cmd;
+	struct ethhdr *eth;
+	u16 eapol_len = skb->len - ETH_HLEN;
+	void *eapol = skb->data + ETH_HLEN;
+	uint i;
+	int rc;
+
+	skb_set_mac_header(skb, 0);
+	eth = eth_hdr(skb);
+	wil_dbg_WMI(wil, "EAPOL %d bytes to %pM\n", eapol_len, eth->h_dest);
+	for (i = 0; i < ARRAY_SIZE(wil->vring_tx); i++) {
+		if (memcmp(wil->dst_addr[i], eth->h_dest, ETH_ALEN) == 0)
+			goto found_dest;
+	}
+
+	return -EINVAL;
+
+ found_dest:
+	/* find out eapol data & len */
+	cmd = kzalloc(sizeof(*cmd) + eapol_len, GFP_KERNEL);
+	if (!cmd)
+		return -EINVAL;
+
+	memcpy(cmd->dst_mac, eth->h_dest, ETH_ALEN);
+	cmd->eapol_len = cpu_to_le16(eapol_len);
+	memcpy(cmd->eapol, eapol, eapol_len);
+	rc = wmi_send(wil, WMI_EAPOL_TX_CMDID, cmd, sizeof(*cmd) + eapol_len);
+	kfree(cmd);
+
+	return rc;
+}
+
+int wmi_del_cipher_key(struct wil6210_priv *wil, u8 key_index,
+		       const void *mac_addr)
+{
+	struct wmi_delete_cipher_key_cmd cmd = {
+		.key_index = key_index,
+	};
+
+	if (mac_addr)
+		memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
+
+	return wmi_send(wil, WMI_DELETE_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_add_cipher_key(struct wil6210_priv *wil, u8 key_index,
+		       const void *mac_addr, int key_len, const void *key)
+{
+	struct wmi_add_cipher_key_cmd cmd = {
+		.key_index = key_index,
+		.key_usage = WMI_KEY_USE_PAIRWISE,
+		.key_len = key_len,
+	};
+
+	if (!key || (key_len > sizeof(cmd.key)))
+		return -EINVAL;
+
+	memcpy(cmd.key, key, key_len);
+	if (mac_addr)
+		memcpy(cmd.mac, mac_addr, WMI_MAC_LEN);
+
+	return wmi_send(wil, WMI_ADD_CIPHER_KEY_CMDID, &cmd, sizeof(cmd));
+}
+
+int wmi_set_ie(struct wil6210_priv *wil, u8 type, u16 ie_len, const void *ie)
+{
+	int rc;
+	u16 len = sizeof(struct wmi_set_appie_cmd) + ie_len;
+	struct wmi_set_appie_cmd *cmd = kzalloc(len, GFP_KERNEL);
+	if (!cmd) {
+		wil_err(wil, "kmalloc(%d) failed\n", len);
+		return -ENOMEM;
+	}
+
+	cmd->mgmt_frm_type = type;
+	/* BUG: FW API define ieLen as u8. Will fix FW */
+	cmd->ie_len = cpu_to_le16(ie_len);
+	memcpy(cmd->ie_info, ie, ie_len);
+	rc = wmi_send(wil, WMI_SET_APPIE_CMDID, &cmd, len);
+	kfree(cmd);
+
+	return rc;
+}
+
+void wmi_event_flush(struct wil6210_priv *wil)
+{
+	struct pending_wmi_event *evt, *t;
+
+	wil_dbg_WMI(wil, "%s()\n", __func__);
+
+	list_for_each_entry_safe(evt, t, &wil->pending_wmi_ev, list) {
+		list_del(&evt->list);
+		kfree(evt);
+	}
+}
+
+static bool wmi_evt_call_handler(struct wil6210_priv *wil, int id,
+				 void *d, int len)
+{
+	uint i;
+
+	for (i = 0; i < ARRAY_SIZE(wmi_evt_handlers); i++) {
+		if (wmi_evt_handlers[i].eventid == id) {
+			wmi_evt_handlers[i].handler(wil, id, d, len);
+			return true;
+		}
+	}
+
+	return false;
+}
+
+static void wmi_event_handle(struct wil6210_priv *wil,
+			     struct wil6210_mbox_hdr *hdr)
+{
+	u16 len = le16_to_cpu(hdr->len);
+
+	if ((hdr->type == WIL_MBOX_HDR_TYPE_WMI) &&
+	    (len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
+		struct wil6210_mbox_hdr_wmi *wmi = (void *)(&hdr[1]);
+		void *evt_data = (void *)(&wmi[1]);
+		u16 id = le16_to_cpu(wmi->id);
+		/* check if someone waits for this event */
+		if (wil->reply_id && wil->reply_id == id) {
+			if (wil->reply_buf) {
+				memcpy(wil->reply_buf, wmi,
+				       min(len, wil->reply_size));
+			} else {
+				wmi_evt_call_handler(wil, id, evt_data,
+						     len - sizeof(*wmi));
+			}
+			wil_dbg_WMI(wil, "Complete WMI 0x%04x\n", id);
+			complete(&wil->wmi_ready);
+			return;
+		}
+		/* unsolicited event */
+		/* search for handler */
+		if (!wmi_evt_call_handler(wil, id, evt_data,
+					  len - sizeof(*wmi))) {
+			wil_err(wil, "Unhandled event 0x%04x\n", id);
+		}
+	} else {
+		wil_err(wil, "Unknown event type\n");
+		print_hex_dump(KERN_ERR, "evt?? ", DUMP_PREFIX_OFFSET, 16, 1,
+			       hdr, sizeof(*hdr) + len, true);
+	}
+}
+
+/*
+ * Retrieve next WMI event from the pending list
+ */
+static struct list_head *next_wmi_ev(struct wil6210_priv *wil)
+{
+	ulong flags;
+	struct list_head *ret = NULL;
+
+	spin_lock_irqsave(&wil->wmi_ev_lock, flags);
+
+	if (!list_empty(&wil->pending_wmi_ev)) {
+		ret = wil->pending_wmi_ev.next;
+		list_del(ret);
+	}
+
+	spin_unlock_irqrestore(&wil->wmi_ev_lock, flags);
+
+	return ret;
+}
+
+/*
+ * Handler for the WMI events
+ */
+void wmi_event_worker(struct work_struct *work)
+{
+	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
+						 wmi_event_worker);
+	struct pending_wmi_event *evt;
+	struct list_head *lh;
+
+	while ((lh = next_wmi_ev(wil)) != NULL) {
+		evt = list_entry(lh, struct pending_wmi_event, list);
+		wmi_event_handle(wil, &evt->event.hdr);
+		kfree(evt);
+	}
+}
+
+void wmi_connect_worker(struct work_struct *work)
+{
+	int rc;
+	struct wil6210_priv *wil = container_of(work, struct wil6210_priv,
+						wmi_connect_worker);
+
+	if (wil->pending_connect_cid < 0) {
+		wil_err(wil, "No connection pending\n");
+		return;
+	}
+
+	wil_dbg_WMI(wil, "Configure for connection CID %d\n",
+		    wil->pending_connect_cid);
+
+	rc = wil_vring_init_tx(wil, 0, WIL6210_TX_RING_SIZE,
+			       wil->pending_connect_cid, 0);
+	wil->pending_connect_cid = -1;
+	if (rc == 0)
+		wil_link_on(wil);
+}
diff --git a/drivers/net/wireless/ath/wil6210/wmi.h b/drivers/net/wireless/ath/wil6210/wmi.h
new file mode 100644
index 0000000..3bbf875
--- /dev/null
+++ b/drivers/net/wireless/ath/wil6210/wmi.h
@@ -0,0 +1,1116 @@
+/*
+ * Copyright (c) 2012 Qualcomm Atheros, Inc.
+ * Copyright (c) 2006-2012 Wilocity .
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This file contains the definitions of the WMI protocol specified in the
+ * Wireless Module Interface (WMI) for the Wilocity
+ * MARLON 60 Gigabit wireless solution.
+ * It includes definitions of all the commands and events.
+ * Commands are messages from the host to the WM.
+ * Events are messages from the WM to the host.
+ */
+
+#ifndef __WILOCITY_WMI_H__
+#define __WILOCITY_WMI_H__
+
+/* General */
+
+#define WMI_MAC_LEN		(6)
+#define WMI_PROX_RANGE_NUM	(3)
+
+/* List of Commands */
+enum wmi_command_id {
+	WMI_CONNECT_CMDID		= 0x0001,
+	WMI_DISCONNECT_CMDID		= 0x0003,
+	WMI_START_SCAN_CMDID		= 0x0007,
+	WMI_SET_BSS_FILTER_CMDID	= 0x0009,
+	WMI_SET_PROBED_SSID_CMDID	= 0x000a,
+	WMI_SET_LISTEN_INT_CMDID	= 0x000b,
+	WMI_BCON_CTRL_CMDID		= 0x000f,
+	WMI_ADD_CIPHER_KEY_CMDID	= 0x0016,
+	WMI_DELETE_CIPHER_KEY_CMDID	= 0x0017,
+	WMI_SET_APPIE_CMDID		= 0x003f,
+	WMI_GET_APPIE_CMDID		= 0x0040,
+	WMI_SET_WSC_STATUS_CMDID	= 0x0041,
+	WMI_PXMT_RANGE_CFG_CMDID	= 0x0042,
+	WMI_PXMT_SNR2_RANGE_CFG_CMDID	= 0x0043,
+	WMI_FAST_MEM_ACC_MODE_CMDID	= 0x0300,
+	WMI_MEM_READ_CMDID		= 0x0800,
+	WMI_MEM_WR_CMDID		= 0x0801,
+	WMI_ECHO_CMDID			= 0x0803,
+	WMI_DEEP_ECHO_CMDID		= 0x0804,
+	WMI_CONFIG_MAC_CMDID		= 0x0805,
+	WMI_CONFIG_PHY_DEBUG_CMDID	= 0x0806,
+	WMI_ADD_STATION_CMDID		= 0x0807,
+	WMI_ADD_DEBUG_TX_PCKT_CMDID	= 0x0808,
+	WMI_PHY_GET_STATISTICS_CMDID	= 0x0809,
+	WMI_FS_TUNE_CMDID		= 0x080a,
+	WMI_CORR_MEASURE_CMDID		= 0x080b,
+	WMI_TEMP_SENSE_CMDID		= 0x080e,
+	WMI_DC_CALIB_CMDID		= 0x080f,
+	WMI_SEND_TONE_CMDID		= 0x0810,
+	WMI_IQ_TX_CALIB_CMDID		= 0x0811,
+	WMI_IQ_RX_CALIB_CMDID		= 0x0812,
+	WMI_SET_UCODE_IDLE_CMDID	= 0x0813,
+	WMI_SET_WORK_MODE_CMDID		= 0x0815,
+	WMI_LO_LEAKAGE_CALIB_CMDID	= 0x0816,
+	WMI_MARLON_R_ACTIVATE_CMDID	= 0x0817,
+	WMI_MARLON_R_READ_CMDID		= 0x0818,
+	WMI_MARLON_R_WRITE_CMDID	= 0x0819,
+	WMI_MARLON_R_TXRX_SEL_CMDID	= 0x081a,
+	MAC_IO_STATIC_PARAMS_CMDID	= 0x081b,
+	MAC_IO_DYNAMIC_PARAMS_CMDID	= 0x081c,
+	WMI_SILENT_RSSI_CALIB_CMDID	= 0x081d,
+	WMI_CFG_RX_CHAIN_CMDID		= 0x0820,
+	WMI_VRING_CFG_CMDID		= 0x0821,
+	WMI_RX_ON_CMDID			= 0x0822,
+	WMI_VRING_BA_EN_CMDID		= 0x0823,
+	WMI_VRING_BA_DIS_CMDID		= 0x0824,
+	WMI_RCP_ADDBA_RESP_CMDID	= 0x0825,
+	WMI_RCP_DELBA_CMDID		= 0x0826,
+	WMI_SET_SSID_CMDID		= 0x0827,
+	WMI_GET_SSID_CMDID		= 0x0828,
+	WMI_SET_PCP_CHANNEL_CMDID	= 0x0829,
+	WMI_GET_PCP_CHANNEL_CMDID	= 0x082a,
+	WMI_SW_TX_REQ_CMDID		= 0x082b,
+	WMI_RX_OFF_CMDID		= 0x082c,
+	WMI_READ_MAC_RXQ_CMDID		= 0x0830,
+	WMI_READ_MAC_TXQ_CMDID		= 0x0831,
+	WMI_WRITE_MAC_RXQ_CMDID		= 0x0832,
+	WMI_WRITE_MAC_TXQ_CMDID		= 0x0833,
+	WMI_WRITE_MAC_XQ_FIELD_CMDID	= 0x0834,
+	WMI_MLME_PUSH_CMDID		= 0x0835,
+	WMI_BEAMFORMING_MGMT_CMDID	= 0x0836,
+	WMI_BF_TXSS_MGMT_CMDID		= 0x0837,
+	WMI_BF_SM_MGMT_CMDID		= 0x0838,
+	WMI_BF_RXSS_MGMT_CMDID		= 0x0839,
+	WMI_SET_SECTORS_CMDID		= 0x0849,
+	WMI_MAINTAIN_PAUSE_CMDID	= 0x0850,
+	WMI_MAINTAIN_RESUME_CMDID	= 0x0851,
+	WMI_RS_MGMT_CMDID		= 0x0852,
+	WMI_RF_MGMT_CMDID		= 0x0853,
+	/* Performance monitoring commands */
+	WMI_BF_CTRL_CMDID		= 0x0862,
+	WMI_NOTIFY_REQ_CMDID		= 0x0863,
+	WMI_GET_STATUS_CMDID		= 0x0864,
+	WMI_UNIT_TEST_CMDID		= 0x0900,
+	WMI_HICCUP_CMDID		= 0x0901,
+	WMI_FLASH_READ_CMDID		= 0x0902,
+	WMI_FLASH_WRITE_CMDID		= 0x0903,
+	WMI_SECURITY_UNIT_TEST_CMDID	= 0x0904,
+
+	WMI_SET_MAC_ADDRESS_CMDID	= 0xf003,
+	WMI_ABORT_SCAN_CMDID		= 0xf007,
+	WMI_SET_PMK_CMDID		= 0xf028,
+
+	WMI_SET_PROMISCUOUS_MODE_CMDID	= 0xf041,
+	WMI_GET_PMK_CMDID		= 0xf048,
+	WMI_SET_PASSPHRASE_CMDID	= 0xf049,
+	WMI_SEND_ASSOC_RES_CMDID	= 0xf04a,
+	WMI_SET_ASSOC_REQ_RELAY_CMDID	= 0xf04b,
+	WMI_EAPOL_TX_CMDID		= 0xf04c,
+	WMI_MAC_ADDR_REQ_CMDID		= 0xf04d,
+	WMI_FW_VER_CMDID		= 0xf04e,
+};
+
+/*
+ * Commands data structures
+ */
+
+/*
+ * Frame Types
+ */
+enum wmi_mgmt_frame_type {
+	WMI_FRAME_BEACON	= 0,
+	WMI_FRAME_PROBE_REQ	= 1,
+	WMI_FRAME_PROBE_RESP	= 2,
+	WMI_FRAME_ASSOC_REQ	= 3,
+	WMI_FRAME_ASSOC_RESP	= 4,
+	WMI_NUM_MGMT_FRAME,
+};
+
+/*
+ * WMI_CONNECT_CMDID
+ */
+enum wmi_network_type {
+	WMI_NETTYPE_INFRA		= 0x01,
+	WMI_NETTYPE_ADHOC		= 0x02,
+	WMI_NETTYPE_ADHOC_CREATOR	= 0x04,
+	WMI_NETTYPE_AP			= 0x10,
+	WMI_NETTYPE_P2P			= 0x20,
+	WMI_NETTYPE_WBE			= 0x40, /* PCIE over 60g */
+};
+
+enum wmi_dot11_auth_mode {
+	WMI_AUTH11_OPEN			= 0x01,
+	WMI_AUTH11_SHARED		= 0x02,
+	WMI_AUTH11_LEAP			= 0x04,
+	WMI_AUTH11_WSC			= 0x08,
+};
+
+enum wmi_auth_mode {
+	WMI_AUTH_NONE			= 0x01,
+	WMI_AUTH_WPA			= 0x02,
+	WMI_AUTH_WPA2			= 0x04,
+	WMI_AUTH_WPA_PSK		= 0x08,
+	WMI_AUTH_WPA2_PSK		= 0x10,
+	WMI_AUTH_WPA_CCKM		= 0x20,
+	WMI_AUTH_WPA2_CCKM		= 0x40,
+};
+
+enum wmi_crypto_type {
+	WMI_CRYPT_NONE			= 0x01,
+	WMI_CRYPT_WEP			= 0x02,
+	WMI_CRYPT_TKIP			= 0x04,
+	WMI_CRYPT_AES			= 0x08,
+	WMI_CRYPT_AES_GCMP		= 0x20,
+};
+
+
+enum wmi_connect_ctrl_flag_bits {
+	WMI_CONNECT_ASSOC_POLICY_USER		= 0x0001,
+	WMI_CONNECT_SEND_REASSOC		= 0x0002,
+	WMI_CONNECT_IGNORE_WPAx_GROUP_CIPHER	= 0x0004,
+	WMI_CONNECT_PROFILE_MATCH_DONE		= 0x0008,
+	WMI_CONNECT_IGNORE_AAC_BEACON		= 0x0010,
+	WMI_CONNECT_CSA_FOLLOW_BSS		= 0x0020,
+	WMI_CONNECT_DO_WPA_OFFLOAD		= 0x0040,
+	WMI_CONNECT_DO_NOT_DEAUTH		= 0x0080,
+};
+
+#define WMI_MAX_SSID_LEN    (32)
+
+struct wmi_connect_cmd {
+	u8 network_type;
+	u8 dot11_auth_mode;
+	u8 auth_mode;
+	u8 pairwise_crypto_type;
+	u8 pairwise_crypto_len;
+	u8 group_crypto_type;
+	u8 group_crypto_len;
+	u8 ssid_len;
+	u8 ssid[WMI_MAX_SSID_LEN];
+	u8 channel;
+	u8 reserved0;
+	u8 bssid[WMI_MAC_LEN];
+	__le32 ctrl_flags;
+	u8 dst_mac[WMI_MAC_LEN];
+	u8 reserved1[2];
+} __packed;
+
+
+/*
+ * WMI_RECONNECT_CMDID
+ */
+struct wmi_reconnect_cmd {
+	u8 channel;			/* hint */
+	u8 reserved;
+	u8 bssid[WMI_MAC_LEN];		/* mandatory if set */
+} __packed;
+
+
+/*
+ * WMI_SET_PMK_CMDID
+ */
+
+#define WMI_MIN_KEY_INDEX	(0)
+#define WMI_MAX_KEY_INDEX	(3)
+#define WMI_MAX_KEY_LEN		(32)
+#define WMI_PASSPHRASE_LEN	(64)
+#define WMI_PMK_LEN		(32)
+
+struct  wmi_set_pmk_cmd {
+	u8 pmk[WMI_PMK_LEN];
+} __packed;
+
+
+/*
+ * WMI_SET_PASSPHRASE_CMDID
+ */
+struct wmi_set_passphrase_cmd {
+	u8 ssid[WMI_MAX_SSID_LEN];
+	u8 passphrase[WMI_PASSPHRASE_LEN];
+	u8 ssid_len;
+	u8 passphrase_len;
+} __packed;
+
+/*
+ * WMI_ADD_CIPHER_KEY_CMDID
+ */
+enum wmi_key_usage {
+	WMI_KEY_USE_PAIRWISE	= 0,
+	WMI_KEY_USE_GROUP	= 1,
+	WMI_KEY_USE_TX		= 2,  /* default Tx Key - Static WEP only */
+};
+
+struct wmi_add_cipher_key_cmd {
+	u8 key_index;
+	u8 key_type;
+	u8 key_usage;		/* enum wmi_key_usage */
+	u8 key_len;
+	u8 key_rsc[8];		/* key replay sequence counter */
+	u8 key[WMI_MAX_KEY_LEN];
+	u8 key_op_ctrl;		/* Additional Key Control information */
+	u8 mac[WMI_MAC_LEN];
+} __packed;
+
+/*
+ * WMI_DELETE_CIPHER_KEY_CMDID
+ */
+struct wmi_delete_cipher_key_cmd {
+	u8 key_index;
+	u8 mac[WMI_MAC_LEN];
+} __packed;
+
+
+/*
+ * WMI_START_SCAN_CMDID
+ *
+ * Start L1 scan operation
+ *
+ * Returned events:
+ * - WMI_RX_MGMT_PACKET_EVENTID - for every probe resp.
+ * - WMI_SCAN_COMPLETE_EVENTID
+ */
+enum wmi_scan_type {
+	WMI_LONG_SCAN		= 0,
+	WMI_SHORT_SCAN		= 1,
+};
+
+struct wmi_start_scan_cmd {
+	u8 reserved[8];
+	__le32 home_dwell_time;	/* Max duration in the home channel(ms) */
+	__le32 force_scan_interval;	/* Time interval between scans (ms)*/
+	u8 scan_type;		/* wmi_scan_type */
+	u8 num_channels;		/* how many channels follow */
+	struct {
+		u8 channel;
+		u8 reserved;
+	} channel_list[0];	/* channels ID's */
+				/* 0 - 58320 MHz */
+				/* 1 - 60480 MHz */
+				/* 2 - 62640 MHz */
+} __packed;
+
+/*
+ * WMI_SET_PROBED_SSID_CMDID
+ */
+#define MAX_PROBED_SSID_INDEX   (15)
+
+enum wmi_ssid_flag {
+	WMI_SSID_FLAG_DISABLE	= 0,	/* disables entry */
+	WMI_SSID_FLAG_SPECIFIC	= 1,	/* probes specified ssid */
+	WMI_SSID_FLAG_ANY	= 2,	/* probes for any ssid */
+};
+
+struct wmi_probed_ssid_cmd {
+	u8 entry_index;			/* 0 to MAX_PROBED_SSID_INDEX */
+	u8 flag;			/* enum wmi_ssid_flag */
+	u8 ssid_len;
+	u8 ssid[WMI_MAX_SSID_LEN];
+} __packed;
+
+/*
+ * WMI_SET_APPIE_CMDID
+ * Add Application specified IE to a management frame
+ */
+struct wmi_set_appie_cmd {
+	u8 mgmt_frm_type;	/* enum wmi_mgmt_frame_type */
+	u8 reserved;
+	__le16 ie_len;	/* Length of the IE to be added to MGMT frame */
+	u8 ie_info[0];
+} __packed;
+
+#define WMI_MAX_IE_LEN (1024)
+
+struct wmi_pxmt_range_cfg_cmd {
+	u8 dst_mac[WMI_MAC_LEN];
+	__le16 range;
+} __packed;
+
+struct wmi_pxmt_snr2_range_cfg_cmd {
+	s8 snr2range_arr[WMI_PROX_RANGE_NUM-1];
+} __packed;
+
+/*
+ * WMI_RF_MGMT_CMDID
+ */
+enum wmi_rf_mgmt_type {
+	WMI_RF_MGMT_W_DISABLE	= 0,
+	WMI_RF_MGMT_W_ENABLE	= 1,
+	WMI_RF_MGMT_GET_STATUS	= 2,
+};
+
+struct wmi_rf_mgmt_cmd {
+	__le32 rf_mgmt_type;
+} __packed;
+
+/*
+ * WMI_SET_SSID_CMDID
+ */
+struct wmi_set_ssid_cmd {
+	__le32 ssid_len;
+	u8 ssid[WMI_MAX_SSID_LEN];
+} __packed;
+
+/*
+ * WMI_SET_PCP_CHANNEL_CMDID
+ */
+struct wmi_set_pcp_channel_cmd {
+	u8 channel;
+	u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_BCON_CTRL_CMDID
+ */
+struct wmi_bcon_ctrl_cmd {
+	__le16 bcon_interval;
+	__le16 frag_num;
+	__le64 ss_mask;
+	u8 network_type;
+	u8 reserved;
+	u8 disable_sec_offload;
+	u8 disable_sec;
+} __packed;
+
+/*
+ * WMI_SW_TX_REQ_CMDID
+ */
+struct wmi_sw_tx_req_cmd {
+	u8 dst_mac[WMI_MAC_LEN];
+	__le16 len;
+	u8 payload[0];
+} __packed;
+
+/*
+ * WMI_VRING_CFG_CMDID
+ */
+
+struct wmi_sw_ring_cfg {
+	__le64 ring_mem_base;
+	__le16 ring_size;
+	__le16 max_mpdu_size;
+} __packed;
+
+struct wmi_vring_cfg_schd {
+	__le16 priority;
+	__le16 timeslot_us;
+} __packed;
+
+enum wmi_vring_cfg_encap_trans_type {
+	WMI_VRING_ENC_TYPE_802_3		= 0,
+	WMI_VRING_ENC_TYPE_NATIVE_WIFI		= 1,
+};
+
+enum wmi_vring_cfg_ds_cfg {
+	WMI_VRING_DS_PBSS			= 0,
+	WMI_VRING_DS_STATION			= 1,
+	WMI_VRING_DS_AP				= 2,
+	WMI_VRING_DS_ADDR4			= 3,
+};
+
+enum wmi_vring_cfg_nwifi_ds_trans_type {
+	WMI_NWIFI_TX_TRANS_MODE_NO		= 0,
+	WMI_NWIFI_TX_TRANS_MODE_AP2PBSS		= 1,
+	WMI_NWIFI_TX_TRANS_MODE_STA2PBSS	= 2,
+};
+
+enum wmi_vring_cfg_schd_params_priority {
+	WMI_SCH_PRIO_REGULAR			= 0,
+	WMI_SCH_PRIO_HIGH			= 1,
+};
+
+struct wmi_vring_cfg {
+	struct wmi_sw_ring_cfg tx_sw_ring;
+	u8 ringid;				/* 0-23 vrings */
+
+	#define CIDXTID_CID_POS (0)
+	#define CIDXTID_CID_LEN (4)
+	#define CIDXTID_CID_MSK (0xF)
+	#define CIDXTID_TID_POS (4)
+	#define CIDXTID_TID_LEN (4)
+	#define CIDXTID_TID_MSK (0xF0)
+	u8 cidxtid;
+
+	u8 encap_trans_type;
+	u8 ds_cfg;				/* 802.3 DS cfg */
+	u8 nwifi_ds_trans_type;
+
+	#define VRING_CFG_MAC_CTRL_LIFETIME_EN_POS (0)
+	#define VRING_CFG_MAC_CTRL_LIFETIME_EN_LEN (1)
+	#define VRING_CFG_MAC_CTRL_LIFETIME_EN_MSK (0x1)
+	#define VRING_CFG_MAC_CTRL_AGGR_EN_POS (1)
+	#define VRING_CFG_MAC_CTRL_AGGR_EN_LEN (1)
+	#define VRING_CFG_MAC_CTRL_AGGR_EN_MSK (0x2)
+	u8 mac_ctrl;
+
+	#define VRING_CFG_TO_RESOLUTION_VALUE_POS (0)
+	#define VRING_CFG_TO_RESOLUTION_VALUE_LEN (6)
+	#define VRING_CFG_TO_RESOLUTION_VALUE_MSK (0x3F)
+	u8 to_resolution;
+	u8 agg_max_wsize;
+	struct wmi_vring_cfg_schd schd_params;
+} __packed;
+
+enum wmi_vring_cfg_cmd_action {
+	WMI_VRING_CMD_ADD			= 0,
+	WMI_VRING_CMD_MODIFY			= 1,
+	WMI_VRING_CMD_DELETE			= 2,
+};
+
+struct wmi_vring_cfg_cmd {
+	__le32 action;
+	struct wmi_vring_cfg vring_cfg;
+} __packed;
+
+/*
+ * WMI_VRING_BA_EN_CMDID
+ */
+struct wmi_vring_ba_en_cmd {
+	u8 ringid;
+	u8 agg_max_wsize;
+	__le16 ba_timeout;
+} __packed;
+
+/*
+ * WMI_VRING_BA_DIS_CMDID
+ */
+struct wmi_vring_ba_dis_cmd {
+	u8 ringid;
+	u8 reserved;
+	__le16 reason;
+} __packed;
+
+/*
+ * WMI_NOTIFY_REQ_CMDID
+ */
+struct wmi_notify_req_cmd {
+	u8 cid;
+	u8 reserved[3];
+	__le32 interval_usec;
+} __packed;
+
+/*
+ * WMI_CFG_RX_CHAIN_CMDID
+ */
+enum wmi_sniffer_cfg_mode {
+	WMI_SNIFFER_OFF				= 0,
+	WMI_SNIFFER_ON				= 1,
+};
+
+enum wmi_sniffer_cfg_phy_info_mode {
+	WMI_SNIFFER_PHY_INFO_DISABLED		= 0,
+	WMI_SNIFFER_PHY_INFO_ENABLED		= 1,
+};
+
+enum wmi_sniffer_cfg_phy_support {
+	WMI_SNIFFER_CP				= 0,
+	WMI_SNIFFER_DP				= 1,
+	WMI_SNIFFER_BOTH_PHYS			= 2,
+};
+
+struct wmi_sniffer_cfg {
+	__le32 mode;		/* enum wmi_sniffer_cfg_mode */
+	__le32 phy_info_mode;	/* enum wmi_sniffer_cfg_phy_info_mode */
+	__le32 phy_support;	/* enum wmi_sniffer_cfg_phy_support */
+	u8 channel;
+	u8 reserved[3];
+} __packed;
+
+enum wmi_cfg_rx_chain_cmd_action {
+	WMI_RX_CHAIN_ADD			= 0,
+	WMI_RX_CHAIN_DEL			= 1,
+};
+
+enum wmi_cfg_rx_chain_cmd_decap_trans_type {
+	WMI_DECAP_TYPE_802_3			= 0,
+	WMI_DECAP_TYPE_NATIVE_WIFI		= 1,
+};
+
+enum wmi_cfg_rx_chain_cmd_nwifi_ds_trans_type {
+	WMI_NWIFI_RX_TRANS_MODE_NO		= 0,
+	WMI_NWIFI_RX_TRANS_MODE_PBSS2AP		= 1,
+	WMI_NWIFI_RX_TRANS_MODE_PBSS2STA	= 2,
+};
+
+struct wmi_cfg_rx_chain_cmd {
+	__le32 action;
+	struct wmi_sw_ring_cfg rx_sw_ring;
+	u8 mid;
+	u8 decap_trans_type;
+
+	#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_POS (0)
+	#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_LEN (1)
+	#define L2_802_3_OFFLOAD_CTRL_VLAN_TAG_INSERTION_MSK (0x1)
+	u8 l2_802_3_offload_ctrl;
+
+	#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_POS (0)
+	#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_LEN (1)
+	#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_QOS_MSK (0x1)
+	#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_POS (1)
+	#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_LEN (1)
+	#define L2_NWIFI_OFFLOAD_CTRL_REMOVE_PN_MSK (0x2)
+	u8 l2_nwifi_offload_ctrl;
+
+	u8 vlan_id;
+	u8 nwifi_ds_trans_type;
+
+	#define L3_L4_CTRL_IPV4_CHECKSUM_EN_POS (0)
+	#define L3_L4_CTRL_IPV4_CHECKSUM_EN_LEN (1)
+	#define L3_L4_CTRL_IPV4_CHECKSUM_EN_MSK (0x1)
+	#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_POS (1)
+	#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_LEN (1)
+	#define L3_L4_CTRL_TCPIP_CHECKSUM_EN_MSK (0x2)
+	u8 l3_l4_ctrl;
+
+	#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_POS (0)
+	#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_LEN (1)
+	#define RING_CTRL_OVERRIDE_PREFETCH_THRSH_MSK (0x1)
+	#define RING_CTRL_OVERRIDE_WB_THRSH_POS (1)
+	#define RING_CTRL_OVERRIDE_WB_THRSH_LEN (1)
+	#define RING_CTRL_OVERRIDE_WB_THRSH_MSK (0x2)
+	#define RING_CTRL_OVERRIDE_ITR_THRSH_POS (2)
+	#define RING_CTRL_OVERRIDE_ITR_THRSH_LEN (1)
+	#define RING_CTRL_OVERRIDE_ITR_THRSH_MSK (0x4)
+	#define RING_CTRL_OVERRIDE_HOST_THRSH_POS (3)
+	#define RING_CTRL_OVERRIDE_HOST_THRSH_LEN (1)
+	#define RING_CTRL_OVERRIDE_HOST_THRSH_MSK (0x8)
+	u8 ring_ctrl;
+
+	__le16 prefetch_thrsh;
+	__le16 wb_thrsh;
+	__le32 itr_value;
+	__le16 host_thrsh;
+	u8 reserved[2];
+	struct wmi_sniffer_cfg sniffer_cfg;
+} __packed;
+
+/*
+ * WMI_RCP_ADDBA_RESP_CMDID
+ */
+struct wmi_rcp_addba_resp_cmd {
+
+	#define CIDXTID_CID_POS (0)
+	#define CIDXTID_CID_LEN (4)
+	#define CIDXTID_CID_MSK (0xF)
+	#define CIDXTID_TID_POS (4)
+	#define CIDXTID_TID_LEN (4)
+	#define CIDXTID_TID_MSK (0xF0)
+	u8 cidxtid;
+
+	u8 dialog_token;
+	__le16 status_code;
+	__le16 ba_param_set;	/* ieee80211_ba_parameterset field to send */
+	__le16 ba_timeout;
+} __packed;
+
+/*
+ * WMI_RCP_DELBA_CMDID
+ */
+struct wmi_rcp_delba_cmd {
+
+	#define CIDXTID_CID_POS (0)
+	#define CIDXTID_CID_LEN (4)
+	#define CIDXTID_CID_MSK (0xF)
+	#define CIDXTID_TID_POS (4)
+	#define CIDXTID_TID_LEN (4)
+	#define CIDXTID_TID_MSK (0xF0)
+	u8 cidxtid;
+
+	u8 reserved;
+	__le16 reason;
+} __packed;
+
+/*
+ * WMI_RCP_ADDBA_REQ_CMDID
+ */
+struct wmi_rcp_addba_req_cmd {
+
+	#define CIDXTID_CID_POS (0)
+	#define CIDXTID_CID_LEN (4)
+	#define CIDXTID_CID_MSK (0xF)
+	#define CIDXTID_TID_POS (4)
+	#define CIDXTID_TID_LEN (4)
+	#define CIDXTID_TID_MSK (0xF0)
+	u8 cidxtid;
+
+	u8 dialog_token;
+	/* ieee80211_ba_parameterset field as it received */
+	__le16 ba_param_set;
+	__le16 ba_timeout;
+	/* ieee80211_ba_seqstrl field as it received */
+	__le16 ba_seq_ctrl;
+} __packed;
+
+/*
+ * WMI_SET_MAC_ADDRESS_CMDID
+ */
+struct wmi_set_mac_address_cmd {
+	u8 mac[WMI_MAC_LEN];
+	u8 reserved[2];
+} __packed;
+
+
+/*
+* WMI_EAPOL_TX_CMDID
+*/
+struct wmi_eapol_tx_cmd {
+	u8 dst_mac[WMI_MAC_LEN];
+	__le16 eapol_len;
+	u8 eapol[0];
+} __packed;
+
+/*
+ * WMI_ECHO_CMDID
+ *
+ * Check FW is alive
+ *
+ * WMI_DEEP_ECHO_CMDID
+ *
+ * Check FW and ucode are alive
+ *
+ * Returned event: WMI_ECHO_RSP_EVENTID
+ * same event for both commands
+ */
+struct wmi_echo_cmd {
+	__le32 value;
+} __packed;
+
+/*
+ * WMI Events
+ */
+
+/*
+ * List of Events (target to host)
+ */
+enum wmi_event_id {
+	WMI_IMM_RSP_EVENTID			= 0x0000,
+	WMI_READY_EVENTID			= 0x1001,
+	WMI_CONNECT_EVENTID			= 0x1002,
+	WMI_DISCONNECT_EVENTID			= 0x1003,
+	WMI_SCAN_COMPLETE_EVENTID		= 0x100a,
+	WMI_REPORT_STATISTICS_EVENTID		= 0x100b,
+	WMI_RD_MEM_RSP_EVENTID			= 0x1800,
+	WMI_FW_READY_EVENTID			= 0x1801,
+	WMI_EXIT_FAST_MEM_ACC_MODE_EVENTID	= 0x0200,
+	WMI_ECHO_RSP_EVENTID			= 0x1803,
+	WMI_CONFIG_MAC_DONE_EVENTID		= 0x1805,
+	WMI_CONFIG_PHY_DEBUG_DONE_EVENTID	= 0x1806,
+	WMI_ADD_STATION_DONE_EVENTID		= 0x1807,
+	WMI_ADD_DEBUG_TX_PCKT_DONE_EVENTID	= 0x1808,
+	WMI_PHY_GET_STATISTICS_EVENTID		= 0x1809,
+	WMI_FS_TUNE_DONE_EVENTID		= 0x180a,
+	WMI_CORR_MEASURE_DONE_EVENTID		= 0x180b,
+	WMI_TEMP_SENSE_DONE_EVENTID		= 0x180e,
+	WMI_DC_CALIB_DONE_EVENTID		= 0x180f,
+	WMI_IQ_TX_CALIB_DONE_EVENTID		= 0x1811,
+	WMI_IQ_RX_CALIB_DONE_EVENTID		= 0x1812,
+	WMI_SET_WORK_MODE_DONE_EVENTID		= 0x1815,
+	WMI_LO_LEAKAGE_CALIB_DONE_EVENTID	= 0x1816,
+	WMI_MARLON_R_ACTIVATE_DONE_EVENTID	= 0x1817,
+	WMI_MARLON_R_READ_DONE_EVENTID		= 0x1818,
+	WMI_MARLON_R_WRITE_DONE_EVENTID		= 0x1819,
+	WMI_MARLON_R_TXRX_SEL_DONE_EVENTID	= 0x181a,
+	WMI_SILENT_RSSI_CALIB_DONE_EVENTID	= 0x181d,
+
+	WMI_CFG_RX_CHAIN_DONE_EVENTID		= 0x1820,
+	WMI_VRING_CFG_DONE_EVENTID		= 0x1821,
+	WMI_RX_ON_DONE_EVENTID			= 0x1822,
+	WMI_BA_STATUS_EVENTID			= 0x1823,
+	WMI_RCP_ADDBA_REQ_EVENTID		= 0x1824,
+	WMI_ADDBA_RESP_SENT_EVENTID		= 0x1825,
+	WMI_DELBA_EVENTID			= 0x1826,
+	WMI_GET_SSID_EVENTID			= 0x1828,
+	WMI_GET_PCP_CHANNEL_EVENTID		= 0x182a,
+	WMI_SW_TX_COMPLETE_EVENTID		= 0x182b,
+	WMI_RX_OFF_DONE_EVENTID			= 0x182c,
+
+	WMI_READ_MAC_RXQ_EVENTID		= 0x1830,
+	WMI_READ_MAC_TXQ_EVENTID		= 0x1831,
+	WMI_WRITE_MAC_RXQ_EVENTID		= 0x1832,
+	WMI_WRITE_MAC_TXQ_EVENTID		= 0x1833,
+	WMI_WRITE_MAC_XQ_FIELD_EVENTID		= 0x1834,
+
+	WMI_BEAFORMING_MGMT_DONE_EVENTID	= 0x1836,
+	WMI_BF_TXSS_MGMT_DONE_EVENTID		= 0x1837,
+	WMI_BF_RXSS_MGMT_DONE_EVENTID		= 0x1839,
+	WMI_RS_MGMT_DONE_EVENTID		= 0x1852,
+	WMI_RF_MGMT_STATUS_EVENTID		= 0x1853,
+	WMI_BF_SM_MGMT_DONE_EVENTID		= 0x1838,
+	WMI_RX_MGMT_PACKET_EVENTID		= 0x1840,
+
+	/* Performance monitoring events */
+	WMI_DATA_PORT_OPEN_EVENTID		= 0x1860,
+	WMI_WBE_LINKDOWN_EVENTID		= 0x1861,
+
+	WMI_BF_CTRL_DONE_EVENTID		= 0x1862,
+	WMI_NOTIFY_REQ_DONE_EVENTID		= 0x1863,
+	WMI_GET_STATUS_DONE_EVENTID		= 0x1864,
+
+	WMI_UNIT_TEST_EVENTID			= 0x1900,
+	WMI_FLASH_READ_DONE_EVENTID		= 0x1902,
+	WMI_FLASH_WRITE_DONE_EVENTID		= 0x1903,
+
+	WMI_SET_CHANNEL_EVENTID			= 0x9000,
+	WMI_ASSOC_REQ_EVENTID			= 0x9001,
+	WMI_EAPOL_RX_EVENTID			= 0x9002,
+	WMI_MAC_ADDR_RESP_EVENTID		= 0x9003,
+	WMI_FW_VER_EVENTID			= 0x9004,
+};
+
+/*
+ * Events data structures
+ */
+
+/*
+ * WMI_RF_MGMT_STATUS_EVENTID
+ */
+enum wmi_rf_status {
+	WMI_RF_ENABLED			= 0,
+	WMI_RF_DISABLED_HW		= 1,
+	WMI_RF_DISABLED_SW		= 2,
+	WMI_RF_DISABLED_HW_SW		= 3,
+};
+
+struct wmi_rf_mgmt_status_event {
+	__le32 rf_status;
+} __packed;
+
+/*
+ * WMI_GET_STATUS_DONE_EVENTID
+ */
+struct wmi_get_status_done_event {
+	__le32 is_associated;
+	u8 cid;
+	u8 reserved0[3];
+	u8 bssid[WMI_MAC_LEN];
+	u8 channel;
+	u8 reserved1;
+	u8 network_type;
+	u8 reserved2[3];
+	__le32 ssid_len;
+	u8 ssid[WMI_MAX_SSID_LEN];
+	__le32 rf_status;
+	__le32 is_secured;
+} __packed;
+
+/*
+ * WMI_FW_VER_EVENTID
+ */
+struct wmi_fw_ver_event {
+	u8 major;
+	u8 minor;
+	__le16 subminor;
+	__le16 build;
+} __packed;
+
+/*
+* WMI_MAC_ADDR_RESP_EVENTID
+*/
+struct wmi_mac_addr_resp_event {
+	u8 mac[WMI_MAC_LEN];
+	u8 auth_mode;
+	u8 crypt_mode;
+	__le32 offload_mode;
+} __packed;
+
+/*
+* WMI_EAPOL_RX_EVENTID
+*/
+struct wmi_eapol_rx_event {
+	u8 src_mac[WMI_MAC_LEN];
+	__le16 eapol_len;
+	u8 eapol[0];
+} __packed;
+
+/*
+* WMI_READY_EVENTID
+*/
+enum wmi_phy_capability {
+	WMI_11A_CAPABILITY		= 1,
+	WMI_11G_CAPABILITY		= 2,
+	WMI_11AG_CAPABILITY		= 3,
+	WMI_11NA_CAPABILITY		= 4,
+	WMI_11NG_CAPABILITY		= 5,
+	WMI_11NAG_CAPABILITY		= 6,
+	WMI_11AD_CAPABILITY		= 7,
+	WMI_11N_CAPABILITY_OFFSET = WMI_11NA_CAPABILITY - WMI_11A_CAPABILITY,
+};
+
+struct wmi_ready_event {
+	__le32 sw_version;
+	__le32 abi_version;
+	u8 mac[WMI_MAC_LEN];
+	u8 phy_capability;		/* enum wmi_phy_capability */
+	u8 reserved;
+} __packed;
+
+/*
+ * WMI_NOTIFY_REQ_DONE_EVENTID
+ */
+struct wmi_notify_req_done_event {
+	__le32 status;
+	__le64 tsf;
+	__le32 snr_val;
+	__le32 tx_tpt;
+	__le32 tx_goodput;
+	__le32 rx_goodput;
+	__le16 bf_mcs;
+	__le16 my_rx_sector;
+	__le16 my_tx_sector;
+	__le16 other_rx_sector;
+	__le16 other_tx_sector;
+	__le16 range;
+} __packed;
+
+/*
+ * WMI_CONNECT_EVENTID
+ */
+struct wmi_connect_event {
+	u8 channel;
+	u8 reserved0;
+	u8 bssid[WMI_MAC_LEN];
+	__le16 listen_interval;
+	__le16 beacon_interval;
+	u8 network_type;
+	u8 reserved1[3];
+	u8 beacon_ie_len;
+	u8 assoc_req_len;
+	u8 assoc_resp_len;
+	u8 cid;
+	u8 reserved2[3];
+	u8 assoc_info[0];
+} __packed;
+
+/*
+ * WMI_DISCONNECT_EVENTID
+ */
+enum wmi_disconnect_reason {
+	WMI_DIS_REASON_NO_NETWORK_AVAIL		= 1,
+	WMI_DIS_REASON_LOST_LINK		= 2, /* bmiss */
+	WMI_DIS_REASON_DISCONNECT_CMD		= 3,
+	WMI_DIS_REASON_BSS_DISCONNECTED		= 4,
+	WMI_DIS_REASON_AUTH_FAILED		= 5,
+	WMI_DIS_REASON_ASSOC_FAILED		= 6,
+	WMI_DIS_REASON_NO_RESOURCES_AVAIL	= 7,
+	WMI_DIS_REASON_CSERV_DISCONNECT		= 8,
+	WMI_DIS_REASON_INVALID_PROFILE		= 10,
+	WMI_DIS_REASON_DOT11H_CHANNEL_SWITCH	= 11,
+	WMI_DIS_REASON_PROFILE_MISMATCH		= 12,
+	WMI_DIS_REASON_CONNECTION_EVICTED	= 13,
+	WMI_DIS_REASON_IBSS_MERGE		= 14,
+};
+
+struct wmi_disconnect_event {
+	__le16 protocol_reason_status;	/* reason code, see 802.11 spec. */
+	u8 bssid[WMI_MAC_LEN];		/* set if known */
+	u8 disconnect_reason;		/* see wmi_disconnect_reason_e */
+	u8 assoc_resp_len;
+	u8 assoc_info[0];
+} __packed;
+
+/*
+ * WMI_SCAN_COMPLETE_EVENTID
+ */
+struct wmi_scan_complete_event {
+	__le32 status;
+} __packed;
+
+/*
+ * WMI_BA_STATUS_EVENTID
+ */
+enum wmi_vring_ba_status {
+	WMI_BA_AGREED			= 0,
+	WMI_BA_NON_AGREED		= 1,
+};
+
+struct wmi_vring_ba_status_event {
+	__le16 status;
+	u8 reserved[2];
+	u8 ringid;
+	u8 agg_wsize;
+	__le16 ba_timeout;
+} __packed;
+
+/*
+ * WMI_DELBA_EVENTID
+ */
+struct wmi_delba_event {
+
+	#define CIDXTID_CID_POS (0)
+	#define CIDXTID_CID_LEN (4)
+	#define CIDXTID_CID_MSK (0xF)
+	#define CIDXTID_TID_POS (4)
+	#define CIDXTID_TID_LEN (4)
+	#define CIDXTID_TID_MSK (0xF0)
+	u8 cidxtid;
+
+	u8 from_initiator;
+	__le16 reason;
+} __packed;
+
+/*
+ * WMI_VRING_CFG_DONE_EVENTID
+ */
+enum wmi_vring_cfg_done_event_status {
+	WMI_VRING_CFG_SUCCESS		= 0,
+	WMI_VRING_CFG_FAILURE		= 1,
+};
+
+struct wmi_vring_cfg_done_event {
+	u8 ringid;
+	u8 status;
+	u8 reserved[2];
+	__le32 tx_vring_tail_ptr;
+} __packed;
+
+/*
+ * WMI_ADDBA_RESP_SENT_EVENTID
+ */
+enum wmi_rcp_addba_resp_sent_event_status {
+	WMI_ADDBA_SUCCESS		= 0,
+	WMI_ADDBA_FAIL			= 1,
+};
+
+struct wmi_rcp_addba_resp_sent_event {
+
+	#define CIDXTID_CID_POS (0)
+	#define CIDXTID_CID_LEN (4)
+	#define CIDXTID_CID_MSK (0xF)
+	#define CIDXTID_TID_POS (4)
+	#define CIDXTID_TID_LEN (4)
+	#define CIDXTID_TID_MSK (0xF0)
+	u8 cidxtid;
+
+	u8 reserved;
+	__le16 status;
+} __packed;
+
+/*
+ * WMI_RCP_ADDBA_REQ_EVENTID
+ */
+struct wmi_rcp_addba_req_event {
+
+	#define CIDXTID_CID_POS (0)
+	#define CIDXTID_CID_LEN (4)
+	#define CIDXTID_CID_MSK (0xF)
+	#define CIDXTID_TID_POS (4)
+	#define CIDXTID_TID_LEN (4)
+	#define CIDXTID_TID_MSK (0xF0)
+	u8 cidxtid;
+
+	u8 dialog_token;
+	__le16 ba_param_set;	/* ieee80211_ba_parameterset as it received */
+	__le16 ba_timeout;
+	__le16 ba_seq_ctrl;	/* ieee80211_ba_seqstrl field as it received */
+} __packed;
+
+/*
+ * WMI_CFG_RX_CHAIN_DONE_EVENTID
+ */
+enum wmi_cfg_rx_chain_done_event_status {
+	WMI_CFG_RX_CHAIN_SUCCESS	= 1,
+};
+
+struct wmi_cfg_rx_chain_done_event {
+	__le32 rx_ring_tail_ptr;	/* Rx V-Ring Tail pointer */
+	__le32 status;
+} __packed;
+
+/*
+ * WMI_WBE_LINKDOWN_EVENTID
+ */
+enum wmi_wbe_link_down_event_reason {
+	WMI_WBE_REASON_USER_REQUEST	= 0,
+	WMI_WBE_REASON_RX_DISASSOC	= 1,
+	WMI_WBE_REASON_BAD_PHY_LINK	= 2,
+};
+
+struct wmi_wbe_link_down_event {
+	u8 cid;
+	u8 reserved[3];
+	__le32 reason;
+} __packed;
+
+/*
+ * WMI_DATA_PORT_OPEN_EVENTID
+ */
+struct wmi_data_port_open_event {
+	u8 cid;
+	u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_GET_PCP_CHANNEL_EVENTID
+ */
+struct wmi_get_pcp_channel_event {
+	u8 channel;
+	u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_SW_TX_COMPLETE_EVENTID
+ */
+enum wmi_sw_tx_status {
+	WMI_TX_SW_STATUS_SUCCESS		= 0,
+	WMI_TX_SW_STATUS_FAILED_NO_RESOURCES	= 1,
+	WMI_TX_SW_STATUS_FAILED_TX		= 2,
+};
+
+struct wmi_sw_tx_complete_event {
+	u8 status;	/* enum wmi_sw_tx_status */
+	u8 reserved[3];
+} __packed;
+
+/*
+ * WMI_GET_SSID_EVENTID
+ */
+struct wmi_get_ssid_event {
+	__le32 ssid_len;
+	u8 ssid[WMI_MAX_SSID_LEN];
+} __packed;
+
+/*
+ * WMI_RX_MGMT_PACKET_EVENTID
+ */
+struct wmi_rx_mgmt_info {
+	u8 mcs;
+	s8 snr;
+	__le16 range;
+	__le16 stype;
+	__le16 status;
+	__le32 len;
+	u8 qid;
+	u8 mid;
+	u8 cid;
+	u8 channel;	/* From Radio MNGR */
+} __packed;
+
+struct wmi_rx_mgmt_packet_event {
+	struct wmi_rx_mgmt_info info;
+	u8 payload[0];
+} __packed;
+
+/*
+ * WMI_ECHO_RSP_EVENTID
+ */
+struct wmi_echo_event {
+	__le32 echoed_value;
+} __packed;
+
+#endif /* __WILOCITY_WMI_H__ */
diff --git a/drivers/net/wireless/b43/b43.h b/drivers/net/wireless/b43/b43.h
index b298e5d..10e288d 100644
--- a/drivers/net/wireless/b43/b43.h
+++ b/drivers/net/wireless/b43/b43.h
@@ -7,6 +7,7 @@
 #include <linux/hw_random.h>
 #include <linux/bcma/bcma.h>
 #include <linux/ssb/ssb.h>
+#include <linux/completion.h>
 #include <net/mac80211.h>
 
 #include "debugfs.h"
@@ -722,6 +723,10 @@
 struct b43_request_fw_context {
 	/* The device we are requesting the fw for. */
 	struct b43_wldev *dev;
+	/* a completion event structure needed if this call is asynchronous */
+	struct completion fw_load_complete;
+	/* a pointer to the firmware object */
+	const struct firmware *blob;
 	/* The type of firmware to request. */
 	enum b43_firmware_file_type req_type;
 	/* Error messages for each firmware type. */
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 16ab280..806e34c 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -2088,11 +2088,18 @@
 		b43warn(wl, text);
 }
 
+static void b43_fw_cb(const struct firmware *firmware, void *context)
+{
+	struct b43_request_fw_context *ctx = context;
+
+	ctx->blob = firmware;
+	complete(&ctx->fw_load_complete);
+}
+
 int b43_do_request_fw(struct b43_request_fw_context *ctx,
 		      const char *name,
-		      struct b43_firmware_file *fw)
+		      struct b43_firmware_file *fw, bool async)
 {
-	const struct firmware *blob;
 	struct b43_fw_header *hdr;
 	u32 size;
 	int err;
@@ -2131,11 +2138,31 @@
 		B43_WARN_ON(1);
 		return -ENOSYS;
 	}
-	err = request_firmware(&blob, ctx->fwname, ctx->dev->dev->dev);
+	if (async) {
+		/* do this part asynchronously */
+		init_completion(&ctx->fw_load_complete);
+		err = request_firmware_nowait(THIS_MODULE, 1, ctx->fwname,
+					      ctx->dev->dev->dev, GFP_KERNEL,
+					      ctx, b43_fw_cb);
+		if (err < 0) {
+			pr_err("Unable to load firmware\n");
+			return err;
+		}
+		/* stall here until fw ready */
+		wait_for_completion(&ctx->fw_load_complete);
+		if (ctx->blob)
+			goto fw_ready;
+	/* On some ARM systems, the async request will fail, but the next sync
+	 * request works. For this reason, we dall through here
+	 */
+	}
+	err = request_firmware(&ctx->blob, ctx->fwname,
+			       ctx->dev->dev->dev);
 	if (err == -ENOENT) {
 		snprintf(ctx->errors[ctx->req_type],
 			 sizeof(ctx->errors[ctx->req_type]),
-			 "Firmware file \"%s\" not found\n", ctx->fwname);
+			 "Firmware file \"%s\" not found\n",
+			 ctx->fwname);
 		return err;
 	} else if (err) {
 		snprintf(ctx->errors[ctx->req_type],
@@ -2144,14 +2171,15 @@
 			 ctx->fwname, err);
 		return err;
 	}
-	if (blob->size < sizeof(struct b43_fw_header))
+fw_ready:
+	if (ctx->blob->size < sizeof(struct b43_fw_header))
 		goto err_format;
-	hdr = (struct b43_fw_header *)(blob->data);
+	hdr = (struct b43_fw_header *)(ctx->blob->data);
 	switch (hdr->type) {
 	case B43_FW_TYPE_UCODE:
 	case B43_FW_TYPE_PCM:
 		size = be32_to_cpu(hdr->size);
-		if (size != blob->size - sizeof(struct b43_fw_header))
+		if (size != ctx->blob->size - sizeof(struct b43_fw_header))
 			goto err_format;
 		/* fallthrough */
 	case B43_FW_TYPE_IV:
@@ -2162,7 +2190,7 @@
 		goto err_format;
 	}
 
-	fw->data = blob;
+	fw->data = ctx->blob;
 	fw->filename = name;
 	fw->type = ctx->req_type;
 
@@ -2172,7 +2200,7 @@
 	snprintf(ctx->errors[ctx->req_type],
 		 sizeof(ctx->errors[ctx->req_type]),
 		 "Firmware file \"%s\" format error.\n", ctx->fwname);
-	release_firmware(blob);
+	release_firmware(ctx->blob);
 
 	return -EPROTO;
 }
@@ -2223,7 +2251,7 @@
 			goto err_no_ucode;
 		}
 	}
-	err = b43_do_request_fw(ctx, filename, &fw->ucode);
+	err = b43_do_request_fw(ctx, filename, &fw->ucode, true);
 	if (err)
 		goto err_load;
 
@@ -2235,7 +2263,7 @@
 	else
 		goto err_no_pcm;
 	fw->pcm_request_failed = false;
-	err = b43_do_request_fw(ctx, filename, &fw->pcm);
+	err = b43_do_request_fw(ctx, filename, &fw->pcm, false);
 	if (err == -ENOENT) {
 		/* We did not find a PCM file? Not fatal, but
 		 * core rev <= 10 must do without hwcrypto then. */
@@ -2296,7 +2324,7 @@
 	default:
 		goto err_no_initvals;
 	}
-	err = b43_do_request_fw(ctx, filename, &fw->initvals);
+	err = b43_do_request_fw(ctx, filename, &fw->initvals, false);
 	if (err)
 		goto err_load;
 
@@ -2355,7 +2383,7 @@
 	default:
 		goto err_no_initvals;
 	}
-	err = b43_do_request_fw(ctx, filename, &fw->initvals_band);
+	err = b43_do_request_fw(ctx, filename, &fw->initvals_band, false);
 	if (err)
 		goto err_load;
 
diff --git a/drivers/net/wireless/b43/main.h b/drivers/net/wireless/b43/main.h
index 8c684cd..abac25e 100644
--- a/drivers/net/wireless/b43/main.h
+++ b/drivers/net/wireless/b43/main.h
@@ -137,9 +137,8 @@
 
 
 struct b43_request_fw_context;
-int b43_do_request_fw(struct b43_request_fw_context *ctx,
-		      const char *name,
-		      struct b43_firmware_file *fw);
+int b43_do_request_fw(struct b43_request_fw_context *ctx, const char *name,
+		      struct b43_firmware_file *fw, bool async);
 void b43_do_release_fw(struct b43_firmware_file *fw);
 
 #endif /* B43_MAIN_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index 1fbd8ec..0f71d1d 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -1407,9 +1407,10 @@
 #endif
 	t->ms = ms;
 	t->periodic = (bool) periodic;
-	t->set = true;
-
-	atomic_inc(&t->wl->callbacks);
+	if (!t->set) {
+		t->set = true;
+		atomic_inc(&t->wl->callbacks);
+	}
 
 	ieee80211_queue_delayed_work(hw, &t->dly_wrk, msecs_to_jiffies(ms));
 }
diff --git a/drivers/net/wireless/iwlegacy/3945-mac.c b/drivers/net/wireless/iwlegacy/3945-mac.c
index d604b40..3726cd6 100644
--- a/drivers/net/wireless/iwlegacy/3945-mac.c
+++ b/drivers/net/wireless/iwlegacy/3945-mac.c
@@ -3273,7 +3273,7 @@
 
 	if (count) {
 		char *p = buffer;
-		strncpy(buffer, buf, min(sizeof(buffer), count));
+		strlcpy(buffer, buf, sizeof(buffer));
 		channel = simple_strtoul(p, NULL, 0);
 		if (channel)
 			params.channel = channel;
diff --git a/drivers/net/wireless/iwlegacy/common.c b/drivers/net/wireless/iwlegacy/common.c
index 7e16d10..90b8970 100644
--- a/drivers/net/wireless/iwlegacy/common.c
+++ b/drivers/net/wireless/iwlegacy/common.c
@@ -3958,17 +3958,21 @@
 
 	memset(&il->staging, 0, sizeof(il->staging));
 
-	if (!il->vif) {
+	switch (il->iw_mode) {
+	case NL80211_IFTYPE_UNSPECIFIED:
 		il->staging.dev_type = RXON_DEV_TYPE_ESS;
-	} else if (il->vif->type == NL80211_IFTYPE_STATION) {
+		break;
+	case NL80211_IFTYPE_STATION:
 		il->staging.dev_type = RXON_DEV_TYPE_ESS;
 		il->staging.filter_flags = RXON_FILTER_ACCEPT_GRP_MSK;
-	} else if (il->vif->type == NL80211_IFTYPE_ADHOC) {
+		break;
+	case NL80211_IFTYPE_ADHOC:
 		il->staging.dev_type = RXON_DEV_TYPE_IBSS;
 		il->staging.flags = RXON_FLG_SHORT_PREAMBLE_MSK;
 		il->staging.filter_flags =
 		    RXON_FILTER_BCON_AWARE_MSK | RXON_FILTER_ACCEPT_GRP_MSK;
-	} else {
+		break;
+	default:
 		IL_ERR("Unsupported interface type %d\n", il->vif->type);
 		return;
 	}
@@ -4550,8 +4554,7 @@
 EXPORT_SYMBOL(il_mac_add_interface);
 
 static void
-il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif,
-		      bool mode_change)
+il_teardown_interface(struct il_priv *il, struct ieee80211_vif *vif)
 {
 	lockdep_assert_held(&il->mutex);
 
@@ -4560,9 +4563,7 @@
 		il_force_scan_end(il);
 	}
 
-	if (!mode_change)
-		il_set_mode(il);
-
+	il_set_mode(il);
 }
 
 void
@@ -4575,8 +4576,8 @@
 
 	WARN_ON(il->vif != vif);
 	il->vif = NULL;
-
-	il_teardown_interface(il, vif, false);
+	il->iw_mode = NL80211_IFTYPE_UNSPECIFIED;
+	il_teardown_interface(il, vif);
 	memset(il->bssid, 0, ETH_ALEN);
 
 	D_MAC80211("leave\n");
@@ -4685,18 +4686,10 @@
 	}
 
 	/* success */
-	il_teardown_interface(il, vif, true);
 	vif->type = newtype;
 	vif->p2p = false;
-	err = il_set_mode(il);
-	WARN_ON(err);
-	/*
-	 * We've switched internally, but submitting to the
-	 * device may have failed for some reason. Mask this
-	 * error, because otherwise mac80211 will not switch
-	 * (and set the interface type back) and we'll be
-	 * out of sync with it.
-	 */
+	il->iw_mode = newtype;
+	il_teardown_interface(il, vif);
 	err = 0;
 
 out:
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index da21328..31534f7 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -1079,6 +1079,8 @@
 {
 	u16 status = le16_to_cpu(tx_resp->status.status);
 
+	info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+
 	info->status.rates[0].count = tx_resp->failure_frame + 1;
 	info->flags |= iwl_tx_status_to_mac80211(status);
 	iwlagn_hwrate_to_tx_control(priv, le32_to_cpu(tx_resp->rate_n_flags),
@@ -1151,13 +1153,6 @@
 			next_reclaimed = ssn;
 		}
 
-		if (tid != IWL_TID_NON_QOS) {
-			priv->tid_data[sta_id][tid].next_reclaimed =
-				next_reclaimed;
-			IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n",
-						  next_reclaimed);
-		}
-
 		iwl_trans_reclaim(priv->trans, txq_id, ssn, &skbs);
 
 		iwlagn_check_ratid_empty(priv, sta_id, tid);
@@ -1208,11 +1203,28 @@
 			if (!is_agg)
 				iwlagn_non_agg_tx_status(priv, ctx, hdr->addr1);
 
+			/*
+			 * W/A for FW bug - the seq_ctl isn't updated when the
+			 * queues are flushed. Fetch it from the packet itself
+			 */
+			if (!is_agg && status == TX_STATUS_FAIL_FIFO_FLUSHED) {
+				next_reclaimed = le16_to_cpu(hdr->seq_ctrl);
+				next_reclaimed =
+					SEQ_TO_SN(next_reclaimed + 0x10);
+			}
+
 			is_offchannel_skb =
 				(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN);
 			freed++;
 		}
 
+		if (tid != IWL_TID_NON_QOS) {
+			priv->tid_data[sta_id][tid].next_reclaimed =
+				next_reclaimed;
+			IWL_DEBUG_TX_REPLY(priv, "Next reclaimed packet:%d\n",
+					   next_reclaimed);
+		}
+
 		WARN_ON(!is_agg && freed != 1);
 
 		/*
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index dad4c4a..8389cd3 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -1166,6 +1166,7 @@
 	else if (test_bit(STATUS_INT_ENABLED, &trans_pcie->status) &&
 		 !trans_pcie->inta)
 		iwl_enable_interrupts(trans);
+	return IRQ_HANDLED;
 
 none:
 	/* re-enable interrupts here since we don't have anything to service. */
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index a875499..cdb11b3 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -1459,7 +1459,7 @@
 	struct cfg80211_ssid req_ssid;
 	int ret, auth_type = 0;
 	struct cfg80211_bss *bss = NULL;
-	u8 is_scanning_required = 0, config_bands = 0;
+	u8 is_scanning_required = 0;
 
 	memset(&req_ssid, 0, sizeof(struct cfg80211_ssid));
 
@@ -1478,19 +1478,6 @@
 	/* disconnect before try to associate */
 	mwifiex_deauthenticate(priv, NULL);
 
-	if (channel) {
-		if (mode == NL80211_IFTYPE_STATION) {
-			if (channel->band == IEEE80211_BAND_2GHZ)
-				config_bands = BAND_B | BAND_G | BAND_GN;
-			else
-				config_bands = BAND_A | BAND_AN;
-
-			if (!((config_bands | priv->adapter->fw_bands) &
-			      ~priv->adapter->fw_bands))
-				priv->adapter->config_bands = config_bands;
-		}
-	}
-
 	/* As this is new association, clear locally stored
 	 * keys and security related flags */
 	priv->sec_info.wpa_enabled = false;
@@ -1707,9 +1694,9 @@
 
 		if (cfg80211_get_chandef_type(&params->chandef) !=
 						NL80211_CHAN_NO_HT)
-			config_bands |= BAND_GN;
+			config_bands |= BAND_G | BAND_GN;
 	} else {
-		if (cfg80211_get_chandef_type(&params->chandef) !=
+		if (cfg80211_get_chandef_type(&params->chandef) ==
 						NL80211_CHAN_NO_HT)
 			config_bands = BAND_A;
 		else
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index 13fbc4e..b879e13 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -161,7 +161,7 @@
 
 	if (pdev) {
 		card = (struct pcie_service_card *) pci_get_drvdata(pdev);
-		if (!card || card->adapter) {
+		if (!card || !card->adapter) {
 			pr_err("Card or adapter structure is not valid\n");
 			return 0;
 		}
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index cb68256..f542bb8 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -56,7 +56,6 @@
  */
 int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter)
 {
-	bool cancel_flag = false;
 	int status;
 	struct cmd_ctrl_node *cmd_queued;
 
@@ -70,14 +69,11 @@
 	atomic_inc(&adapter->cmd_pending);
 
 	/* Wait for completion */
-	wait_event_interruptible(adapter->cmd_wait_q.wait,
-				 *(cmd_queued->condition));
-	if (!*(cmd_queued->condition))
-		cancel_flag = true;
-
-	if (cancel_flag) {
-		mwifiex_cancel_pending_ioctl(adapter);
-		dev_dbg(adapter->dev, "cmd cancel\n");
+	status = wait_event_interruptible(adapter->cmd_wait_q.wait,
+					  *(cmd_queued->condition));
+	if (status) {
+		dev_err(adapter->dev, "cmd_wait_q terminated: %d\n", status);
+		return status;
 	}
 
 	status = adapter->cmd_wait_q.status;
@@ -287,6 +283,20 @@
 		if (ret)
 			goto done;
 
+		if (bss_desc) {
+			u8 config_bands = 0;
+
+			if (mwifiex_band_to_radio_type((u8) bss_desc->bss_band)
+			    == HostCmd_SCAN_RADIO_TYPE_BG)
+				config_bands = BAND_B | BAND_G | BAND_GN;
+			else
+				config_bands = BAND_A | BAND_AN;
+
+			if (!((config_bands | adapter->fw_bands) &
+			      ~adapter->fw_bands))
+				adapter->config_bands = config_bands;
+		}
+
 		ret = mwifiex_check_network_compatibility(priv, bss_desc);
 		if (ret)
 			goto done;
@@ -496,8 +506,11 @@
 		return false;
 	}
 
-	wait_event_interruptible(adapter->hs_activate_wait_q,
-				 adapter->hs_activate_wait_q_woken);
+	if (wait_event_interruptible(adapter->hs_activate_wait_q,
+				     adapter->hs_activate_wait_q_woken)) {
+		dev_err(adapter->dev, "hs_activate_wait_q terminated\n");
+		return false;
+	}
 
 	return true;
 }
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c
index f221b95..83564d3 100644
--- a/drivers/net/wireless/mwl8k.c
+++ b/drivers/net/wireless/mwl8k.c
@@ -4250,9 +4250,11 @@
 	p->amsdu_enabled = 0;
 
 	rc = mwl8k_post_cmd(hw, &cmd->header);
+	if (!rc)
+		rc = p->station_id;
 	kfree(cmd);
 
-	return rc ? rc : p->station_id;
+	return rc;
 }
 
 static int mwl8k_cmd_update_stadb_del(struct ieee80211_hw *hw,
diff --git a/drivers/net/wireless/rtlwifi/Kconfig b/drivers/net/wireless/rtlwifi/Kconfig
index 21b1bbb..b80bc46 100644
--- a/drivers/net/wireless/rtlwifi/Kconfig
+++ b/drivers/net/wireless/rtlwifi/Kconfig
@@ -57,12 +57,12 @@
 
 config RTLWIFI
 	tristate
-	depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE
+	depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE
 	default m
 
 config RTLWIFI_DEBUG
 	bool "Additional debugging output"
-	depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE
+	depends on RTL8192CE || RTL8192CU || RTL8192SE || RTL8192DE || RTL8723AE
 	default y
 
 config RTL8192C_COMMON
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
index 1d5d360..246e535 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192c/phy_common.c
@@ -692,7 +692,7 @@
 	if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
 		rtl92c_phy_sw_chnl_callback(hw);
 		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
-			 "sw_chnl_inprogress false schdule workitem\n");
+			 "sw_chnl_inprogress false schedule workitem\n");
 		rtlphy->sw_chnl_inprogress = false;
 	} else {
 		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
index 39cc793..3d8536b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/phy.c
@@ -1106,7 +1106,7 @@
 	if (!(is_hal_stop(rtlhal)) && !(RT_CANNOT_IO(hw))) {
 		rtl8723ae_phy_sw_chnl_callback(hw);
 		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
-			 "sw_chnl_inprogress false schdule workitem\n");
+			 "sw_chnl_inprogress false schedule workitem\n");
 		rtlphy->sw_chnl_inprogress = false;
 	} else {
 		RT_TRACE(rtlpriv, COMP_CHAN, DBG_LOUD,
diff --git a/drivers/pci/hotplug/pciehp.h b/drivers/pci/hotplug/pciehp.h
index 26ffd3e..2c113de 100644
--- a/drivers/pci/hotplug/pciehp.h
+++ b/drivers/pci/hotplug/pciehp.h
@@ -44,7 +44,6 @@
 extern int pciehp_poll_time;
 extern bool pciehp_debug;
 extern bool pciehp_force;
-extern struct workqueue_struct *pciehp_wq;
 
 #define dbg(format, arg...)						\
 do {									\
@@ -78,6 +77,7 @@
 	struct hotplug_slot *hotplug_slot;
 	struct delayed_work work;	/* work for button event */
 	struct mutex lock;
+	struct workqueue_struct *wq;
 };
 
 struct event_info {
diff --git a/drivers/pci/hotplug/pciehp_core.c b/drivers/pci/hotplug/pciehp_core.c
index 916bf4f..939bd1d 100644
--- a/drivers/pci/hotplug/pciehp_core.c
+++ b/drivers/pci/hotplug/pciehp_core.c
@@ -42,7 +42,6 @@
 bool pciehp_poll_mode;
 int pciehp_poll_time;
 bool pciehp_force;
-struct workqueue_struct *pciehp_wq;
 
 #define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -340,18 +339,13 @@
 {
 	int retval = 0;
 
-	pciehp_wq = alloc_workqueue("pciehp", 0, 0);
-	if (!pciehp_wq)
-		return -ENOMEM;
-
 	pciehp_firmware_init();
 	retval = pcie_port_service_register(&hpdriver_portdrv);
  	dbg("pcie_port_service_register = %d\n", retval);
   	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
- 	if (retval) {
-		destroy_workqueue(pciehp_wq);
+	if (retval)
 		dbg("Failure to register service\n");
-	}
+
 	return retval;
 }
 
@@ -359,7 +353,6 @@
 {
 	dbg("unload_pciehpd()\n");
 	pcie_port_service_unregister(&hpdriver_portdrv);
-	destroy_workqueue(pciehp_wq);
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
diff --git a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
index 27f4429..38f0186 100644
--- a/drivers/pci/hotplug/pciehp_ctrl.c
+++ b/drivers/pci/hotplug/pciehp_ctrl.c
@@ -49,7 +49,7 @@
 	info->p_slot = p_slot;
 	INIT_WORK(&info->work, interrupt_event_handler);
 
-	queue_work(pciehp_wq, &info->work);
+	queue_work(p_slot->wq, &info->work);
 
 	return 0;
 }
@@ -344,7 +344,7 @@
 		kfree(info);
 		goto out;
 	}
-	queue_work(pciehp_wq, &info->work);
+	queue_work(p_slot->wq, &info->work);
  out:
 	mutex_unlock(&p_slot->lock);
 }
@@ -377,7 +377,7 @@
 		if (ATTN_LED(ctrl))
 			pciehp_set_attention_status(p_slot, 0);
 
-		queue_delayed_work(pciehp_wq, &p_slot->work, 5*HZ);
+		queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
 		break;
 	case BLINKINGOFF_STATE:
 	case BLINKINGON_STATE:
@@ -439,7 +439,7 @@
 	else
 		p_slot->state = POWERON_STATE;
 
-	queue_work(pciehp_wq, &info->work);
+	queue_work(p_slot->wq, &info->work);
 }
 
 static void interrupt_event_handler(struct work_struct *work)
diff --git a/drivers/pci/hotplug/pciehp_hpc.c b/drivers/pci/hotplug/pciehp_hpc.c
index 13b2eaf..5127f3f 100644
--- a/drivers/pci/hotplug/pciehp_hpc.c
+++ b/drivers/pci/hotplug/pciehp_hpc.c
@@ -773,23 +773,32 @@
 static int pcie_init_slot(struct controller *ctrl)
 {
 	struct slot *slot;
+	char name[32];
 
 	slot = kzalloc(sizeof(*slot), GFP_KERNEL);
 	if (!slot)
 		return -ENOMEM;
 
+	snprintf(name, sizeof(name), "pciehp-%u", PSN(ctrl));
+	slot->wq = alloc_workqueue(name, 0, 0);
+	if (!slot->wq)
+		goto abort;
+
 	slot->ctrl = ctrl;
 	mutex_init(&slot->lock);
 	INIT_DELAYED_WORK(&slot->work, pciehp_queue_pushbutton_work);
 	ctrl->slot = slot;
 	return 0;
+abort:
+	kfree(slot);
+	return -ENOMEM;
 }
 
 static void pcie_cleanup_slot(struct controller *ctrl)
 {
 	struct slot *slot = ctrl->slot;
 	cancel_delayed_work(&slot->work);
-	flush_workqueue(pciehp_wq);
+	destroy_workqueue(slot->wq);
 	kfree(slot);
 }
 
diff --git a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
index ca64932..b849f995 100644
--- a/drivers/pci/hotplug/shpchp.h
+++ b/drivers/pci/hotplug/shpchp.h
@@ -46,8 +46,6 @@
 extern bool shpchp_poll_mode;
 extern int shpchp_poll_time;
 extern bool shpchp_debug;
-extern struct workqueue_struct *shpchp_wq;
-extern struct workqueue_struct *shpchp_ordered_wq;
 
 #define dbg(format, arg...)						\
 do {									\
@@ -91,6 +89,7 @@
 	struct list_head	slot_list;
 	struct delayed_work work;	/* work for button event */
 	struct mutex lock;
+	struct workqueue_struct *wq;
 	u8 hp_slot;
 };
 
diff --git a/drivers/pci/hotplug/shpchp_core.c b/drivers/pci/hotplug/shpchp_core.c
index b6de307..3100c52 100644
--- a/drivers/pci/hotplug/shpchp_core.c
+++ b/drivers/pci/hotplug/shpchp_core.c
@@ -39,8 +39,6 @@
 bool shpchp_debug;
 bool shpchp_poll_mode;
 int shpchp_poll_time;
-struct workqueue_struct *shpchp_wq;
-struct workqueue_struct *shpchp_ordered_wq;
 
 #define DRIVER_VERSION	"0.4"
 #define DRIVER_AUTHOR	"Dan Zink <dan.zink@compaq.com>, Greg Kroah-Hartman <greg@kroah.com>, Dely Sy <dely.l.sy@intel.com>"
@@ -129,6 +127,14 @@
 		slot->device = ctrl->slot_device_offset + i;
 		slot->hpc_ops = ctrl->hpc_ops;
 		slot->number = ctrl->first_slot + (ctrl->slot_num_inc * i);
+
+		snprintf(name, sizeof(name), "shpchp-%d", slot->number);
+		slot->wq = alloc_workqueue(name, 0, 0);
+		if (!slot->wq) {
+			retval = -ENOMEM;
+			goto error_info;
+		}
+
 		mutex_init(&slot->lock);
 		INIT_DELAYED_WORK(&slot->work, shpchp_queue_pushbutton_work);
 
@@ -148,7 +154,7 @@
 		if (retval) {
 			ctrl_err(ctrl, "pci_hp_register failed with error %d\n",
 				 retval);
-			goto error_info;
+			goto error_slotwq;
 		}
 
 		get_power_status(hotplug_slot, &info->power_status);
@@ -160,6 +166,8 @@
 	}
 
 	return 0;
+error_slotwq:
+	destroy_workqueue(slot->wq);
 error_info:
 	kfree(info);
 error_hpslot:
@@ -180,8 +188,7 @@
 		slot = list_entry(tmp, struct slot, slot_list);
 		list_del(&slot->slot_list);
 		cancel_delayed_work(&slot->work);
-		flush_workqueue(shpchp_wq);
-		flush_workqueue(shpchp_ordered_wq);
+		destroy_workqueue(slot->wq);
 		pci_hp_deregister(slot->hotplug_slot);
 	}
 }
@@ -364,25 +371,12 @@
 
 static int __init shpcd_init(void)
 {
-	int retval = 0;
-
-	shpchp_wq = alloc_ordered_workqueue("shpchp", 0);
-	if (!shpchp_wq)
-		return -ENOMEM;
-
-	shpchp_ordered_wq = alloc_ordered_workqueue("shpchp_ordered", 0);
-	if (!shpchp_ordered_wq) {
-		destroy_workqueue(shpchp_wq);
-		return -ENOMEM;
-	}
+	int retval;
 
 	retval = pci_register_driver(&shpc_driver);
 	dbg("%s: pci_register_driver = %d\n", __func__, retval);
 	info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
-	if (retval) {
-		destroy_workqueue(shpchp_ordered_wq);
-		destroy_workqueue(shpchp_wq);
-	}
+
 	return retval;
 }
 
@@ -390,8 +384,6 @@
 {
 	dbg("unload_shpchpd()\n");
 	pci_unregister_driver(&shpc_driver);
-	destroy_workqueue(shpchp_ordered_wq);
-	destroy_workqueue(shpchp_wq);
 	info(DRIVER_DESC " version: " DRIVER_VERSION " unloaded\n");
 }
 
diff --git a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
index f9b5a52..5849927 100644
--- a/drivers/pci/hotplug/shpchp_ctrl.c
+++ b/drivers/pci/hotplug/shpchp_ctrl.c
@@ -51,7 +51,7 @@
 	info->p_slot = p_slot;
 	INIT_WORK(&info->work, interrupt_event_handler);
 
-	queue_work(shpchp_wq, &info->work);
+	queue_work(p_slot->wq, &info->work);
 
 	return 0;
 }
@@ -453,7 +453,7 @@
 		kfree(info);
 		goto out;
 	}
-	queue_work(shpchp_ordered_wq, &info->work);
+	queue_work(p_slot->wq, &info->work);
  out:
 	mutex_unlock(&p_slot->lock);
 }
@@ -501,7 +501,7 @@
 		p_slot->hpc_ops->green_led_blink(p_slot);
 		p_slot->hpc_ops->set_attention_status(p_slot, 0);
 
-		queue_delayed_work(shpchp_wq, &p_slot->work, 5*HZ);
+		queue_delayed_work(p_slot->wq, &p_slot->work, 5*HZ);
 		break;
 	case BLINKINGOFF_STATE:
 	case BLINKINGON_STATE:
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index bafd2bb..c18e5bf 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -739,7 +739,7 @@
 /**
  * pci_sriov_set_totalvfs -- reduce the TotalVFs available
  * @dev: the PCI PF device
- * numvfs: number that should be used for TotalVFs supported
+ * @numvfs: number that should be used for TotalVFs supported
  *
  * Should be called from PF driver's probe routine with
  * device's mutex held.
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index 6c8bc58..fde4a32 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -82,4 +82,4 @@
 
 config PCIE_PME
 	def_bool y
-	depends on PCIEPORTBUS && PM_RUNTIME && EXPERIMENTAL && ACPI
+	depends on PCIEPORTBUS && PM_RUNTIME && ACPI
diff --git a/drivers/pci/pcie/aer/aerdrv_core.c b/drivers/pci/pcie/aer/aerdrv_core.c
index 421bbc5..564d97f 100644
--- a/drivers/pci/pcie/aer/aerdrv_core.c
+++ b/drivers/pci/pcie/aer/aerdrv_core.c
@@ -630,6 +630,7 @@
 			continue;
 		}
 		do_recovery(pdev, entry.severity);
+		pci_dev_put(pdev);
 	}
 }
 #endif
diff --git a/drivers/pci/pcie/aspm.c b/drivers/pci/pcie/aspm.c
index b52630b..8474b6a 100644
--- a/drivers/pci/pcie/aspm.c
+++ b/drivers/pci/pcie/aspm.c
@@ -771,6 +771,9 @@
 {
 	struct pci_dev *child;
 
+	if (aspm_force)
+		return;
+
 	/*
 	 * Clear any ASPM setup that the firmware has carried out on this bus
 	 */
diff --git a/drivers/pinctrl/Kconfig b/drivers/pinctrl/Kconfig
index c31aeb0..efaecef 100644
--- a/drivers/pinctrl/Kconfig
+++ b/drivers/pinctrl/Kconfig
@@ -181,7 +181,6 @@
 
 config PINCTRL_SAMSUNG
 	bool
-	depends on OF && GPIOLIB
 	select PINMUX
 	select PINCONF
 
diff --git a/drivers/pinctrl/mvebu/pinctrl-dove.c b/drivers/pinctrl/mvebu/pinctrl-dove.c
index 69aba36..428ea96 100644
--- a/drivers/pinctrl/mvebu/pinctrl-dove.c
+++ b/drivers/pinctrl/mvebu/pinctrl-dove.c
@@ -588,7 +588,7 @@
 {
 	const struct of_device_id *match =
 		of_match_device(dove_pinctrl_of_match, &pdev->dev);
-	pdev->dev.platform_data = match->data;
+	pdev->dev.platform_data = (void *)match->data;
 
 	/*
 	 * General MPP Configuration Register is part of pdma registers.
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
index f12084e..cdd483d 100644
--- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -66,9 +66,9 @@
 		MPP_VAR_FUNCTION(0x5, "sata0", "act",    V(0, 1, 1, 1, 1, 0)),
 		MPP_VAR_FUNCTION(0xb, "lcd", "vsync",    V(0, 0, 0, 0, 1, 0))),
 	MPP_MODE(6,
-		MPP_VAR_FUNCTION(0x0, "sysrst", "out",   V(1, 1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x1, "spi", "mosi",     V(1, 1, 1, 1, 1, 1)),
-		MPP_VAR_FUNCTION(0x2, "ptp", "trig",     V(1, 1, 1, 1, 0, 0))),
+		MPP_VAR_FUNCTION(0x1, "sysrst", "out",   V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x2, "spi", "mosi",     V(1, 1, 1, 1, 1, 1)),
+		MPP_VAR_FUNCTION(0x3, "ptp", "trig",     V(1, 1, 1, 1, 0, 0))),
 	MPP_MODE(7,
 		MPP_VAR_FUNCTION(0x0, "gpo", NULL,       V(1, 1, 1, 1, 1, 1)),
 		MPP_VAR_FUNCTION(0x1, "pex", "rsto",     V(1, 1, 1, 1, 0, 1)),
@@ -458,7 +458,7 @@
 {
 	const struct of_device_id *match =
 		of_match_device(kirkwood_pinctrl_of_match, &pdev->dev);
-	pdev->dev.platform_data = match->data;
+	pdev->dev.platform_data = (void *)match->data;
 	return mvebu_pinctrl_probe(pdev);
 }
 
diff --git a/drivers/pinctrl/pinctrl-exynos5440.c b/drivers/pinctrl/pinctrl-exynos5440.c
index de05b64..1427299 100644
--- a/drivers/pinctrl/pinctrl-exynos5440.c
+++ b/drivers/pinctrl/pinctrl-exynos5440.c
@@ -599,7 +599,7 @@
 }
 
 /* parse the pin numbers listed in the 'samsung,exynos5440-pins' property */
-static int __init exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
+static int exynos5440_pinctrl_parse_dt_pins(struct platform_device *pdev,
 			struct device_node *cfg_np, unsigned int **pin_list,
 			unsigned int *npins)
 {
@@ -630,7 +630,7 @@
  * Parse the information about all the available pin groups and pin functions
  * from device node of the pin-controller.
  */
-static int __init exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
+static int exynos5440_pinctrl_parse_dt(struct platform_device *pdev,
 				struct exynos5440_pinctrl_priv_data *priv)
 {
 	struct device *dev = &pdev->dev;
@@ -723,7 +723,7 @@
 }
 
 /* register the pinctrl interface with the pinctrl subsystem */
-static int __init exynos5440_pinctrl_register(struct platform_device *pdev,
+static int exynos5440_pinctrl_register(struct platform_device *pdev,
 				struct exynos5440_pinctrl_priv_data *priv)
 {
 	struct device *dev = &pdev->dev;
@@ -798,7 +798,7 @@
 }
 
 /* register the gpiolib interface with the gpiolib subsystem */
-static int __init exynos5440_gpiolib_register(struct platform_device *pdev,
+static int exynos5440_gpiolib_register(struct platform_device *pdev,
 				struct exynos5440_pinctrl_priv_data *priv)
 {
 	struct gpio_chip *gc;
@@ -831,7 +831,7 @@
 }
 
 /* unregister the gpiolib interface with the gpiolib subsystem */
-static int __init exynos5440_gpiolib_unregister(struct platform_device *pdev,
+static int exynos5440_gpiolib_unregister(struct platform_device *pdev,
 				struct exynos5440_pinctrl_priv_data *priv)
 {
 	int ret = gpiochip_remove(priv->gc);
diff --git a/drivers/pinctrl/pinctrl-mxs.c b/drivers/pinctrl/pinctrl-mxs.c
index dd227d2..23af9f1 100644
--- a/drivers/pinctrl/pinctrl-mxs.c
+++ b/drivers/pinctrl/pinctrl-mxs.c
@@ -146,7 +146,7 @@
 static void mxs_dt_free_map(struct pinctrl_dev *pctldev,
 			    struct pinctrl_map *map, unsigned num_maps)
 {
-	int i;
+	u32 i;
 
 	for (i = 0; i < num_maps; i++) {
 		if (map[i].type == PIN_MAP_TYPE_MUX_GROUP)
@@ -203,7 +203,7 @@
 	void __iomem *reg;
 	u8 bank, shift;
 	u16 pin;
-	int i;
+	u32 i;
 
 	for (i = 0; i < g->npins; i++) {
 		bank = PINID_TO_BANK(g->pins[i]);
@@ -256,7 +256,7 @@
 	void __iomem *reg;
 	u8 ma, vol, pull, bank, shift;
 	u16 pin;
-	int i;
+	u32 i;
 
 	ma = CONFIG_TO_MA(config);
 	vol = CONFIG_TO_VOL(config);
@@ -345,8 +345,7 @@
 	const char *propname = "fsl,pinmux-ids";
 	char *group;
 	int length = strlen(np->name) + SUFFIX_LEN;
-	int i;
-	u32 val;
+	u32 val, i;
 
 	group = devm_kzalloc(&pdev->dev, length, GFP_KERNEL);
 	if (!group)
diff --git a/drivers/pinctrl/pinctrl-nomadik.c b/drivers/pinctrl/pinctrl-nomadik.c
index 1bb16ff..5767b18 100644
--- a/drivers/pinctrl/pinctrl-nomadik.c
+++ b/drivers/pinctrl/pinctrl-nomadik.c
@@ -676,7 +676,7 @@
 }
 EXPORT_SYMBOL(nmk_gpio_set_mode);
 
-static int nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
+static int __maybe_unused nmk_prcm_gpiocr_get_mode(struct pinctrl_dev *pctldev, int gpio)
 {
 	int i;
 	u16 reg;
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index f6a360b..5c32e88 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -30,7 +30,6 @@
 #define PCS_MUX_BITS_NAME		"pinctrl-single,bits"
 #define PCS_REG_NAME_LEN		((sizeof(unsigned long) * 2) + 1)
 #define PCS_OFF_DISABLED		~0U
-#define PCS_MAX_GPIO_VALUES		2
 
 /**
  * struct pcs_pingroup - pingroups for a function
@@ -78,16 +77,6 @@
 };
 
 /**
- * struct pcs_gpio_range - pinctrl gpio range
- * @range:	subrange of the GPIO number space
- * @gpio_func:	gpio function value in the pinmux register
- */
-struct pcs_gpio_range {
-	struct pinctrl_gpio_range range;
-	int gpio_func;
-};
-
-/**
  * struct pcs_data - wrapper for data needed by pinctrl framework
  * @pa:		pindesc array
  * @cur:	index to current element
@@ -414,26 +403,9 @@
 }
 
 static int pcs_request_gpio(struct pinctrl_dev *pctldev,
-			    struct pinctrl_gpio_range *range, unsigned pin)
+			struct pinctrl_gpio_range *range, unsigned offset)
 {
-	struct pcs_device *pcs = pinctrl_dev_get_drvdata(pctldev);
-	struct pcs_gpio_range *gpio = NULL;
-	int end, mux_bytes;
-	unsigned data;
-
-	gpio = container_of(range, struct pcs_gpio_range, range);
-	end = range->pin_base + range->npins - 1;
-	if (pin < range->pin_base || pin > end) {
-		dev_err(pctldev->dev,
-			"pin %d isn't in the range of %d to %d\n",
-			pin, range->pin_base, end);
-		return -EINVAL;
-	}
-	mux_bytes = pcs->width / BITS_PER_BYTE;
-	data = pcs->read(pcs->base + pin * mux_bytes) & ~pcs->fmask;
-	data |= gpio->gpio_func;
-	pcs->write(data, pcs->base + pin * mux_bytes);
-	return 0;
+	return -ENOTSUPP;
 }
 
 static struct pinmux_ops pcs_pinmux_ops = {
@@ -907,49 +879,6 @@
 
 static struct of_device_id pcs_of_match[];
 
-static int pcs_add_gpio_range(struct device_node *node, struct pcs_device *pcs)
-{
-	struct pcs_gpio_range *gpio;
-	struct device_node *child;
-	struct resource r;
-	const char name[] = "pinctrl-single";
-	u32 gpiores[PCS_MAX_GPIO_VALUES];
-	int ret, i = 0, mux_bytes = 0;
-
-	for_each_child_of_node(node, child) {
-		ret = of_address_to_resource(child, 0, &r);
-		if (ret < 0)
-			continue;
-		memset(gpiores, 0, sizeof(u32) * PCS_MAX_GPIO_VALUES);
-		ret = of_property_read_u32_array(child, "pinctrl-single,gpio",
-						 gpiores, PCS_MAX_GPIO_VALUES);
-		if (ret < 0)
-			continue;
-		gpio = devm_kzalloc(pcs->dev, sizeof(*gpio), GFP_KERNEL);
-		if (!gpio) {
-			dev_err(pcs->dev, "failed to allocate pcs gpio\n");
-			return -ENOMEM;
-		}
-		gpio->range.name = devm_kzalloc(pcs->dev, sizeof(name),
-						GFP_KERNEL);
-		if (!gpio->range.name) {
-			dev_err(pcs->dev, "failed to allocate range name\n");
-			return -ENOMEM;
-		}
-		memcpy((char *)gpio->range.name, name, sizeof(name));
-
-		gpio->range.id = i++;
-		gpio->range.base = gpiores[0];
-		gpio->gpio_func = gpiores[1];
-		mux_bytes = pcs->width / BITS_PER_BYTE;
-		gpio->range.pin_base = (r.start - pcs->res->start) / mux_bytes;
-		gpio->range.npins = (r.end - r.start) / mux_bytes + 1;
-
-		pinctrl_add_gpio_range(pcs->pctl, &gpio->range);
-	}
-	return 0;
-}
-
 static int pcs_probe(struct platform_device *pdev)
 {
 	struct device_node *np = pdev->dev.of_node;
@@ -1046,10 +975,6 @@
 		goto free;
 	}
 
-	ret = pcs_add_gpio_range(np, pcs);
-	if (ret < 0)
-		goto free;
-
 	dev_info(pcs->dev, "%i pins at pa %p size %u\n",
 		 pcs->desc.npins, pcs->base, pcs->size);
 
diff --git a/drivers/platform/x86/acer-wmi.c b/drivers/platform/x86/acer-wmi.c
index 06f4eb7..afed701 100644
--- a/drivers/platform/x86/acer-wmi.c
+++ b/drivers/platform/x86/acer-wmi.c
@@ -125,8 +125,11 @@
 	{KE_IGNORE, 0x63, {KEY_BRIGHTNESSDOWN} },
 	{KE_KEY, 0x64, {KEY_SWITCHVIDEOMODE} },	/* Display Switch */
 	{KE_IGNORE, 0x81, {KEY_SLEEP} },
-	{KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} },	/* Touch Pad On/Off */
+	{KE_KEY, 0x82, {KEY_TOUCHPAD_TOGGLE} },	/* Touch Pad Toggle */
+	{KE_KEY, KEY_TOUCHPAD_ON, {KEY_TOUCHPAD_ON} },
+	{KE_KEY, KEY_TOUCHPAD_OFF, {KEY_TOUCHPAD_OFF} },
 	{KE_IGNORE, 0x83, {KEY_TOUCHPAD_TOGGLE} },
+	{KE_KEY, 0x85, {KEY_TOUCHPAD_TOGGLE} },
 	{KE_END, 0}
 };
 
@@ -147,6 +150,7 @@
 #define ACER_WMID3_GDS_THREEG		(1<<6)	/* 3G */
 #define ACER_WMID3_GDS_WIMAX		(1<<7)	/* WiMAX */
 #define ACER_WMID3_GDS_BLUETOOTH	(1<<11)	/* BT */
+#define ACER_WMID3_GDS_TOUCHPAD		(1<<1)	/* Touchpad */
 
 struct lm_input_params {
 	u8 function_num;        /* Function Number */
@@ -875,7 +879,7 @@
 	struct acpi_buffer input = { (acpi_size) sizeof(u32), (void *)(&in) };
 	struct acpi_buffer result = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *obj;
-	u32 tmp;
+	u32 tmp = 0;
 	acpi_status status;
 
 	status = wmi_evaluate_method(WMID_GUID1, 1, method_id, &input, &result);
@@ -884,14 +888,14 @@
 		return status;
 
 	obj = (union acpi_object *) result.pointer;
-	if (obj && obj->type == ACPI_TYPE_BUFFER &&
-		(obj->buffer.length == sizeof(u32) ||
-		obj->buffer.length == sizeof(u64))) {
-		tmp = *((u32 *) obj->buffer.pointer);
-	} else if (obj->type == ACPI_TYPE_INTEGER) {
-		tmp = (u32) obj->integer.value;
-	} else {
-		tmp = 0;
+	if (obj) {
+		if (obj->type == ACPI_TYPE_BUFFER &&
+			(obj->buffer.length == sizeof(u32) ||
+			obj->buffer.length == sizeof(u64))) {
+			tmp = *((u32 *) obj->buffer.pointer);
+		} else if (obj->type == ACPI_TYPE_INTEGER) {
+			tmp = (u32) obj->integer.value;
+		}
 	}
 
 	if (out)
@@ -1193,12 +1197,14 @@
 		return status;
 
 	obj = (union acpi_object *) out.pointer;
-	if (obj && obj->type == ACPI_TYPE_BUFFER &&
-		(obj->buffer.length == sizeof(u32) ||
-		obj->buffer.length == sizeof(u64))) {
-		devices = *((u32 *) obj->buffer.pointer);
-	} else if (obj->type == ACPI_TYPE_INTEGER) {
-		devices = (u32) obj->integer.value;
+	if (obj) {
+		if (obj->type == ACPI_TYPE_BUFFER &&
+			(obj->buffer.length == sizeof(u32) ||
+			obj->buffer.length == sizeof(u64))) {
+			devices = *((u32 *) obj->buffer.pointer);
+		} else if (obj->type == ACPI_TYPE_INTEGER) {
+			devices = (u32) obj->integer.value;
+		}
 	} else {
 		kfree(out.pointer);
 		return AE_ERROR;
@@ -1676,6 +1682,7 @@
 	acpi_status status;
 	u16 device_state;
 	const struct key_entry *key;
+	u32 scancode;
 
 	status = wmi_get_event_data(value, &response);
 	if (status != AE_OK) {
@@ -1712,6 +1719,7 @@
 			pr_warn("Unknown key number - 0x%x\n",
 				return_value.key_num);
 		} else {
+			scancode = return_value.key_num;
 			switch (key->keycode) {
 			case KEY_WLAN:
 			case KEY_BLUETOOTH:
@@ -1725,9 +1733,11 @@
 					rfkill_set_sw_state(bluetooth_rfkill,
 						!(device_state & ACER_WMID3_GDS_BLUETOOTH));
 				break;
+			case KEY_TOUCHPAD_TOGGLE:
+				scancode = (device_state & ACER_WMID3_GDS_TOUCHPAD) ?
+						KEY_TOUCHPAD_ON : KEY_TOUCHPAD_OFF;
 			}
-			sparse_keymap_report_entry(acer_wmi_input_dev, key,
-						   1, true);
+			sparse_keymap_report_event(acer_wmi_input_dev, scancode, 1, true);
 		}
 		break;
 	case WMID_ACCEL_EVENT:
@@ -1946,12 +1956,14 @@
 		return 0;
 
 	obj = (union acpi_object *) out.pointer;
-	if (obj && obj->type == ACPI_TYPE_BUFFER &&
-		(obj->buffer.length == sizeof(u32) ||
-		obj->buffer.length == sizeof(u64))) {
-		devices = *((u32 *) obj->buffer.pointer);
-	} else if (obj->type == ACPI_TYPE_INTEGER) {
-		devices = (u32) obj->integer.value;
+	if (obj) {
+		if (obj->type == ACPI_TYPE_BUFFER &&
+			(obj->buffer.length == sizeof(u32) ||
+			obj->buffer.length == sizeof(u64))) {
+			devices = *((u32 *) obj->buffer.pointer);
+		} else if (obj->type == ACPI_TYPE_INTEGER) {
+			devices = (u32) obj->integer.value;
+		}
 	}
 
 	kfree(out.pointer);
diff --git a/drivers/platform/x86/asus-laptop.c b/drivers/platform/x86/asus-laptop.c
index ec1d3bc..fcde4e5 100644
--- a/drivers/platform/x86/asus-laptop.c
+++ b/drivers/platform/x86/asus-laptop.c
@@ -860,8 +860,10 @@
 	/*
 	 * The HWRS method return informations about the hardware.
 	 * 0x80 bit is for WLAN, 0x100 for Bluetooth.
+	 * 0x40 for WWAN, 0x10 for WIMAX.
 	 * The significance of others is yet to be found.
-	 * If we don't find the method, we assume the device are present.
+	 * We don't currently use this for device detection, and it
+	 * takes several seconds to run on some systems.
 	 */
 	rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp);
 	if (!ACPI_FAILURE(rv))
@@ -1682,7 +1684,7 @@
 {
 	struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
 	union acpi_object *model = NULL;
-	unsigned long long bsts_result, hwrs_result;
+	unsigned long long bsts_result;
 	char *string = NULL;
 	acpi_status status;
 
@@ -1741,20 +1743,9 @@
 		return -ENOMEM;
 	}
 
-	if (*string)
+	if (string)
 		pr_notice("  %s model detected\n", string);
 
-	/*
-	 * The HWRS method return informations about the hardware.
-	 * 0x80 bit is for WLAN, 0x100 for Bluetooth,
-	 * 0x40 for WWAN, 0x10 for WIMAX.
-	 * The significance of others is yet to be found.
-	 */
-	status =
-	    acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result);
-	if (!ACPI_FAILURE(status))
-		pr_notice("  HWRS returned %x", (int)hwrs_result);
-
 	if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
 		asus->have_rsts = true;
 
diff --git a/drivers/platform/x86/ibm_rtl.c b/drivers/platform/x86/ibm_rtl.c
index 7481146..97c2be1 100644
--- a/drivers/platform/x86/ibm_rtl.c
+++ b/drivers/platform/x86/ibm_rtl.c
@@ -244,7 +244,7 @@
 	if (force)
 		pr_warn("module loaded by force\n");
 	/* first ensure that we are running on IBM HW */
-	else if (efi_enabled || !dmi_check_system(ibm_rtl_dmi_table))
+	else if (efi_enabled(EFI_BOOT) || !dmi_check_system(ibm_rtl_dmi_table))
 		return -ENODEV;
 
 	/* Get the address for the Extended BIOS Data Area */
diff --git a/drivers/platform/x86/samsung-laptop.c b/drivers/platform/x86/samsung-laptop.c
index dd90d15..d1f03005 100644
--- a/drivers/platform/x86/samsung-laptop.c
+++ b/drivers/platform/x86/samsung-laptop.c
@@ -26,6 +26,7 @@
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/ctype.h>
+#include <linux/efi.h>
 #include <acpi/video.h>
 
 /*
@@ -1523,6 +1524,16 @@
 		},
 	 .driver_data = &samsung_broken_acpi_video,
 	},
+	{
+	 .callback = samsung_dmi_matched,
+	 .ident = "N250P",
+	 .matches = {
+		DMI_MATCH(DMI_SYS_VENDOR, "SAMSUNG ELECTRONICS CO., LTD."),
+		DMI_MATCH(DMI_PRODUCT_NAME, "N250P"),
+		DMI_MATCH(DMI_BOARD_NAME, "N250P"),
+		},
+	 .driver_data = &samsung_broken_acpi_video,
+	},
 	{ },
 };
 MODULE_DEVICE_TABLE(dmi, samsung_dmi_table);
@@ -1534,6 +1545,9 @@
 	struct samsung_laptop *samsung;
 	int ret;
 
+	if (efi_enabled(EFI_BOOT))
+		return -ENODEV;
+
 	quirks = &samsung_unknown;
 	if (!force && !dmi_check_system(samsung_dmi_table))
 		return -ENODEV;
diff --git a/drivers/platform/x86/sony-laptop.c b/drivers/platform/x86/sony-laptop.c
index daaddec..b8ad71f 100644
--- a/drivers/platform/x86/sony-laptop.c
+++ b/drivers/platform/x86/sony-laptop.c
@@ -786,28 +786,29 @@
 static int sony_nc_buffer_call(acpi_handle handle, char *name, u64 *value,
 		void *buffer, size_t buflen)
 {
+	int ret = 0;
 	size_t len = len;
 	union acpi_object *object = __call_snc_method(handle, name, value);
 
 	if (!object)
 		return -EINVAL;
 
-	if (object->type == ACPI_TYPE_BUFFER)
+	if (object->type == ACPI_TYPE_BUFFER) {
 		len = MIN(buflen, object->buffer.length);
+		memcpy(buffer, object->buffer.pointer, len);
 
-	else if (object->type == ACPI_TYPE_INTEGER)
+	} else if (object->type == ACPI_TYPE_INTEGER) {
 		len = MIN(buflen, sizeof(object->integer.value));
+		memcpy(buffer, &object->integer.value, len);
 
-	else {
+	} else {
 		pr_warn("Invalid acpi_object: expected 0x%x got 0x%x\n",
 				ACPI_TYPE_BUFFER, object->type);
-		kfree(object);
-		return -EINVAL;
+		ret = -EINVAL;
 	}
 
-	memcpy(buffer, object->buffer.pointer, len);
 	kfree(object);
-	return 0;
+	return ret;
 }
 
 struct sony_nc_handles {
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 0f65b24..2785843 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -1885,9 +1885,15 @@
 	struct regulator_dev	*rdev = regulator->rdev;
 
 	if (rdev->constraints &&
-	    rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE &&
-	    (rdev->desc->n_voltages - rdev->desc->linear_min_sel) > 1)
-		return 1;
+	    (rdev->constraints->valid_ops_mask & REGULATOR_CHANGE_VOLTAGE)) {
+		if (rdev->desc->n_voltages - rdev->desc->linear_min_sel > 1)
+			return 1;
+
+		if (rdev->desc->continuous_voltage_range &&
+		    rdev->constraints->min_uV && rdev->constraints->max_uV &&
+		    rdev->constraints->min_uV != rdev->constraints->max_uV)
+			return 1;
+	}
 
 	return 0;
 }
@@ -3315,7 +3321,8 @@
  * @config: runtime configuration for regulator
  *
  * Called by regulator drivers to register a regulator.
- * Returns 0 on success.
+ * Returns a valid pointer to struct regulator_dev on success
+ * or an ERR_PTR() on error.
  */
 struct regulator_dev *
 regulator_register(const struct regulator_desc *regulator_desc,
diff --git a/drivers/regulator/dbx500-prcmu.c b/drivers/regulator/dbx500-prcmu.c
index 261f3d2..89bd2fa 100644
--- a/drivers/regulator/dbx500-prcmu.c
+++ b/drivers/regulator/dbx500-prcmu.c
@@ -14,6 +14,7 @@
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 
 #include "dbx500-prcmu.h"
 
diff --git a/drivers/regulator/max8997.c b/drivers/regulator/max8997.c
index df0eafb..02be7fc 100644
--- a/drivers/regulator/max8997.c
+++ b/drivers/regulator/max8997.c
@@ -71,26 +71,26 @@
 	int step;
 };
 
-/* Voltage maps in mV */
+/* Voltage maps in uV */
 static const struct voltage_map_desc ldo_voltage_map_desc = {
-	.min = 800,	.max = 3950,	.step = 50,
+	.min = 800000,	.max = 3950000,	.step = 50000,
 }; /* LDO1 ~ 18, 21 all */
 
 static const struct voltage_map_desc buck1245_voltage_map_desc = {
-	.min = 650,	.max = 2225,	.step = 25,
+	.min = 650000,	.max = 2225000,	.step = 25000,
 }; /* Buck1, 2, 4, 5 */
 
 static const struct voltage_map_desc buck37_voltage_map_desc = {
-	.min = 750,	.max = 3900,	.step = 50,
+	.min = 750000,	.max = 3900000,	.step = 50000,
 }; /* Buck3, 7 */
 
-/* current map in mA */
+/* current map in uA */
 static const struct voltage_map_desc charger_current_map_desc = {
-	.min = 200,	.max = 950,	.step = 50,
+	.min = 200000,	.max = 950000,	.step = 50000,
 };
 
 static const struct voltage_map_desc topoff_current_map_desc = {
-	.min = 50,	.max = 200,	.step = 10,
+	.min = 50000,	.max = 200000,	.step = 10000,
 };
 
 static const struct voltage_map_desc *reg_voltage_map[] = {
@@ -194,7 +194,7 @@
 	if (val > desc->max)
 		return -EINVAL;
 
-	return val * 1000;
+	return val;
 }
 
 static int max8997_get_enable_register(struct regulator_dev *rdev,
@@ -485,7 +485,6 @@
 {
 	struct max8997_data *max8997 = rdev_get_drvdata(rdev);
 	struct i2c_client *i2c = max8997->iodev->i2c;
-	int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
 	const struct voltage_map_desc *desc;
 	int rid = rdev_get_id(rdev);
 	int i, reg, shift, mask, ret;
@@ -509,7 +508,7 @@
 
 	desc = reg_voltage_map[rid];
 
-	i = max8997_get_voltage_proper_val(desc, min_vol, max_vol);
+	i = max8997_get_voltage_proper_val(desc, min_uV, max_uV);
 	if (i < 0)
 		return i;
 
@@ -557,7 +556,7 @@
 	case MAX8997_BUCK4:
 	case MAX8997_BUCK5:
 		return DIV_ROUND_UP(desc->step * (new_selector - old_selector),
-				    max8997->ramp_delay);
+				    max8997->ramp_delay * 1000);
 	}
 
 	return 0;
@@ -656,7 +655,6 @@
 	const struct voltage_map_desc *desc;
 	int new_val, new_idx, damage, tmp_val, tmp_idx, tmp_dmg;
 	bool gpio_dvs_mode = false;
-	int min_vol = min_uV / 1000, max_vol = max_uV / 1000;
 
 	if (rid < MAX8997_BUCK1 || rid > MAX8997_BUCK7)
 		return -EINVAL;
@@ -681,7 +679,7 @@
 						selector);
 
 	desc = reg_voltage_map[rid];
-	new_val = max8997_get_voltage_proper_val(desc, min_vol, max_vol);
+	new_val = max8997_get_voltage_proper_val(desc, min_uV, max_uV);
 	if (new_val < 0)
 		return new_val;
 
@@ -1123,8 +1121,8 @@
 		max8997->buck1_vol[i] = ret =
 			max8997_get_voltage_proper_val(
 					&buck1245_voltage_map_desc,
-					pdata->buck1_voltage[i] / 1000,
-					pdata->buck1_voltage[i] / 1000 +
+					pdata->buck1_voltage[i],
+					pdata->buck1_voltage[i] +
 					buck1245_voltage_map_desc.step);
 		if (ret < 0)
 			goto err_out;
@@ -1132,8 +1130,8 @@
 		max8997->buck2_vol[i] = ret =
 			max8997_get_voltage_proper_val(
 					&buck1245_voltage_map_desc,
-					pdata->buck2_voltage[i] / 1000,
-					pdata->buck2_voltage[i] / 1000 +
+					pdata->buck2_voltage[i],
+					pdata->buck2_voltage[i] +
 					buck1245_voltage_map_desc.step);
 		if (ret < 0)
 			goto err_out;
@@ -1141,8 +1139,8 @@
 		max8997->buck5_vol[i] = ret =
 			max8997_get_voltage_proper_val(
 					&buck1245_voltage_map_desc,
-					pdata->buck5_voltage[i] / 1000,
-					pdata->buck5_voltage[i] / 1000 +
+					pdata->buck5_voltage[i],
+					pdata->buck5_voltage[i] +
 					buck1245_voltage_map_desc.step);
 		if (ret < 0)
 			goto err_out;
diff --git a/drivers/regulator/max8998.c b/drivers/regulator/max8998.c
index b821d08..1f0df40 100644
--- a/drivers/regulator/max8998.c
+++ b/drivers/regulator/max8998.c
@@ -51,39 +51,39 @@
 	int step;
 };
 
-/* Voltage maps */
+/* Voltage maps in uV*/
 static const struct voltage_map_desc ldo23_voltage_map_desc = {
-	.min = 800,	.step = 50,	.max = 1300,
+	.min = 800000,	.step = 50000,	.max = 1300000,
 };
 static const struct voltage_map_desc ldo456711_voltage_map_desc = {
-	.min = 1600,	.step = 100,	.max = 3600,
+	.min = 1600000,	.step = 100000,	.max = 3600000,
 };
 static const struct voltage_map_desc ldo8_voltage_map_desc = {
-	.min = 3000,	.step = 100,	.max = 3600,
+	.min = 3000000,	.step = 100000,	.max = 3600000,
 };
 static const struct voltage_map_desc ldo9_voltage_map_desc = {
-	.min = 2800,	.step = 100,	.max = 3100,
+	.min = 2800000,	.step = 100000,	.max = 3100000,
 };
 static const struct voltage_map_desc ldo10_voltage_map_desc = {
-	.min = 950,	.step = 50,	.max = 1300,
+	.min = 95000,	.step = 50000,	.max = 1300000,
 };
 static const struct voltage_map_desc ldo1213_voltage_map_desc = {
-	.min = 800,	.step = 100,	.max = 3300,
+	.min = 800000,	.step = 100000,	.max = 3300000,
 };
 static const struct voltage_map_desc ldo1415_voltage_map_desc = {
-	.min = 1200,	.step = 100,	.max = 3300,
+	.min = 1200000,	.step = 100000,	.max = 3300000,
 };
 static const struct voltage_map_desc ldo1617_voltage_map_desc = {
-	.min = 1600,	.step = 100,	.max = 3600,
+	.min = 1600000,	.step = 100000,	.max = 3600000,
 };
 static const struct voltage_map_desc buck12_voltage_map_desc = {
-	.min = 750,	.step = 25,	.max = 1525,
+	.min = 750000,	.step = 25000,	.max = 1525000,
 };
 static const struct voltage_map_desc buck3_voltage_map_desc = {
-	.min = 1600,	.step = 100,	.max = 3600,
+	.min = 1600000,	.step = 100000,	.max = 3600000,
 };
 static const struct voltage_map_desc buck4_voltage_map_desc = {
-	.min = 800,	.step = 100,	.max = 2300,
+	.min = 800000,	.step = 100000,	.max = 2300000,
 };
 
 static const struct voltage_map_desc *ldo_voltage_map[] = {
@@ -445,9 +445,9 @@
 	if (max8998->iodev->type == TYPE_MAX8998 && !(val & MAX8998_ENRAMP))
 		return 0;
 
-	difference = (new_selector - old_selector) * desc->step;
+	difference = (new_selector - old_selector) * desc->step / 1000;
 	if (difference > 0)
-		return difference / ((val & 0x0f) + 1);
+		return DIV_ROUND_UP(difference, (val & 0x0f) + 1);
 
 	return 0;
 }
@@ -702,7 +702,7 @@
 		i = 0;
 		while (buck12_voltage_map_desc.min +
 		       buck12_voltage_map_desc.step*i
-		       < (pdata->buck1_voltage1 / 1000))
+		       < pdata->buck1_voltage1)
 			i++;
 		max8998->buck1_vol[0] = i;
 		ret = max8998_write_reg(i2c, MAX8998_REG_BUCK1_VOLTAGE1, i);
@@ -713,7 +713,7 @@
 		i = 0;
 		while (buck12_voltage_map_desc.min +
 		       buck12_voltage_map_desc.step*i
-		       < (pdata->buck1_voltage2 / 1000))
+		       < pdata->buck1_voltage2)
 			i++;
 
 		max8998->buck1_vol[1] = i;
@@ -725,7 +725,7 @@
 		i = 0;
 		while (buck12_voltage_map_desc.min +
 		       buck12_voltage_map_desc.step*i
-		       < (pdata->buck1_voltage3 / 1000))
+		       < pdata->buck1_voltage3)
 			i++;
 
 		max8998->buck1_vol[2] = i;
@@ -737,7 +737,7 @@
 		i = 0;
 		while (buck12_voltage_map_desc.min +
 		       buck12_voltage_map_desc.step*i
-		       < (pdata->buck1_voltage4 / 1000))
+		       < pdata->buck1_voltage4)
 			i++;
 
 		max8998->buck1_vol[3] = i;
@@ -763,7 +763,7 @@
 		i = 0;
 		while (buck12_voltage_map_desc.min +
 		       buck12_voltage_map_desc.step*i
-		       < (pdata->buck2_voltage1 / 1000))
+		       < pdata->buck2_voltage1)
 			i++;
 		max8998->buck2_vol[0] = i;
 		ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE1, i);
@@ -774,7 +774,7 @@
 		i = 0;
 		while (buck12_voltage_map_desc.min +
 		       buck12_voltage_map_desc.step*i
-		       < (pdata->buck2_voltage2 / 1000))
+		       < pdata->buck2_voltage2)
 			i++;
 		max8998->buck2_vol[1] = i;
 		ret = max8998_write_reg(i2c, MAX8998_REG_BUCK2_VOLTAGE2, i);
@@ -792,8 +792,8 @@
 			int count = (desc->max - desc->min) / desc->step + 1;
 
 			regulators[index].n_voltages = count;
-			regulators[index].min_uV = desc->min * 1000;
-			regulators[index].uV_step = desc->step * 1000;
+			regulators[index].min_uV = desc->min;
+			regulators[index].uV_step = desc->step;
 		}
 
 		config.dev = max8998->dev;
diff --git a/drivers/regulator/s5m8767.c b/drivers/regulator/s5m8767.c
index 9f991f2..33b65c9 100644
--- a/drivers/regulator/s5m8767.c
+++ b/drivers/regulator/s5m8767.c
@@ -214,7 +214,7 @@
 	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
 	int ret, reg;
 	int mask = 0xc0, enable_ctrl;
-	u8 val;
+	unsigned int val;
 
 	ret = s5m8767_get_register(rdev, &reg, &enable_ctrl);
 	if (ret == -EINVAL)
@@ -306,7 +306,7 @@
 	struct s5m8767_info *s5m8767 = rdev_get_drvdata(rdev);
 	int reg, mask, ret;
 	int reg_id = rdev_get_id(rdev);
-	u8 val;
+	unsigned int val;
 
 	ret = s5m8767_get_voltage_register(rdev, &reg);
 	if (ret)
diff --git a/drivers/regulator/tps80031-regulator.c b/drivers/regulator/tps80031-regulator.c
index b15d711..9019d0e 100644
--- a/drivers/regulator/tps80031-regulator.c
+++ b/drivers/regulator/tps80031-regulator.c
@@ -728,7 +728,7 @@
 			}
 		}
 		rdev = regulator_register(&ri->rinfo->desc, &config);
-		if (IS_ERR_OR_NULL(rdev)) {
+		if (IS_ERR(rdev)) {
 			dev_err(&pdev->dev,
 				"register regulator failed %s\n",
 					ri->rinfo->desc.name);
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 923a9da..20354b4 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -1023,7 +1023,7 @@
 
 config RTC_DRV_MV
 	tristate "Marvell SoC RTC"
-	depends on ARCH_KIRKWOOD || ARCH_DOVE
+	depends on ARCH_KIRKWOOD || ARCH_DOVE || ARCH_MVEBU
 	help
 	  If you say yes here you will get support for the in-chip RTC
 	  that can be found in some of Marvell's SoC devices, such as
diff --git a/drivers/rtc/rtc-da9055.c b/drivers/rtc/rtc-da9055.c
index 96bafc5..8f0dcfe 100644
--- a/drivers/rtc/rtc-da9055.c
+++ b/drivers/rtc/rtc-da9055.c
@@ -227,7 +227,7 @@
 	.alarm_irq_enable = da9055_rtc_alarm_irq_enable,
 };
 
-static int __init da9055_rtc_device_init(struct da9055 *da9055,
+static int da9055_rtc_device_init(struct da9055 *da9055,
 					struct da9055_pdata *pdata)
 {
 	int ret;
diff --git a/drivers/s390/block/dasd_diag.c b/drivers/s390/block/dasd_diag.c
index 9bd5da3..704488d 100644
--- a/drivers/s390/block/dasd_diag.c
+++ b/drivers/s390/block/dasd_diag.c
@@ -248,7 +248,7 @@
 	default:
 		return;
 	}
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_DSD]++;
+	inc_irq_stat(IRQEXT_DSD);
 	if (!ip) {		/* no intparm: unsolicited interrupt */
 		DBF_EVENT(DBF_NOTICE, "%s", "caught unsolicited "
 			      "interrupt");
diff --git a/drivers/s390/block/dasd_eckd.c b/drivers/s390/block/dasd_eckd.c
index 806fe91..e37bc16 100644
--- a/drivers/s390/block/dasd_eckd.c
+++ b/drivers/s390/block/dasd_eckd.c
@@ -4274,7 +4274,7 @@
 	.thaw	     = dasd_generic_restore_device,
 	.restore     = dasd_generic_restore_device,
 	.uc_handler  = dasd_generic_uc_handler,
-	.int_class   = IOINT_DAS,
+	.int_class   = IRQIO_DAS,
 };
 
 /*
diff --git a/drivers/s390/block/dasd_fba.c b/drivers/s390/block/dasd_fba.c
index eb74850..4146985 100644
--- a/drivers/s390/block/dasd_fba.c
+++ b/drivers/s390/block/dasd_fba.c
@@ -78,7 +78,7 @@
 	.freeze      = dasd_generic_pm_freeze,
 	.thaw	     = dasd_generic_restore_device,
 	.restore     = dasd_generic_restore_device,
-	.int_class   = IOINT_DAS,
+	.int_class   = IRQIO_DAS,
 };
 
 static void
diff --git a/drivers/s390/char/con3215.c b/drivers/s390/char/con3215.c
index 4008450..33b7141 100644
--- a/drivers/s390/char/con3215.c
+++ b/drivers/s390/char/con3215.c
@@ -44,6 +44,7 @@
 #define RAW3215_NR_CCWS	    3
 #define RAW3215_TIMEOUT	    HZ/10     /* time for delayed output */
 
+#define RAW3215_FIXED	    1	      /* 3215 console device is not be freed */
 #define RAW3215_WORKING	    4	      /* set if a request is being worked on */
 #define RAW3215_THROTTLED   8	      /* set if reading is disabled */
 #define RAW3215_STOPPED	    16	      /* set if writing is disabled */
@@ -630,7 +631,8 @@
 	DECLARE_WAITQUEUE(wait, current);
 	unsigned long flags;
 
-	if (!(raw->port.flags & ASYNC_INITIALIZED))
+	if (!(raw->port.flags & ASYNC_INITIALIZED) ||
+	    (raw->flags & RAW3215_FIXED))
 		return;
 	/* Wait for outstanding requests, then free irq */
 	spin_lock_irqsave(get_ccwdev_lock(raw->cdev), flags);
@@ -805,7 +807,7 @@
 	.freeze		= &raw3215_pm_stop,
 	.thaw		= &raw3215_pm_start,
 	.restore	= &raw3215_pm_start,
-	.int_class	= IOINT_C15,
+	.int_class	= IRQIO_C15,
 };
 
 #ifdef CONFIG_TN3215_CONSOLE
@@ -927,6 +929,8 @@
 	dev_set_drvdata(&cdev->dev, raw);
 	cdev->handler = raw3215_irq;
 
+	raw->flags |= RAW3215_FIXED;
+
 	/* Request the console irq */
 	if (raw3215_startup(raw) != 0) {
 		raw3215_free_info(raw);
diff --git a/drivers/s390/char/raw3270.c b/drivers/s390/char/raw3270.c
index f3b8bb8..9a6c140 100644
--- a/drivers/s390/char/raw3270.c
+++ b/drivers/s390/char/raw3270.c
@@ -1396,7 +1396,7 @@
 	.freeze		= &raw3270_pm_stop,
 	.thaw		= &raw3270_pm_start,
 	.restore	= &raw3270_pm_start,
-	.int_class	= IOINT_C70,
+	.int_class	= IRQIO_C70,
 };
 
 static int
diff --git a/drivers/s390/char/sclp.c b/drivers/s390/char/sclp.c
index 4fa21f7..12c16a6 100644
--- a/drivers/s390/char/sclp.c
+++ b/drivers/s390/char/sclp.c
@@ -400,7 +400,7 @@
 	u32 finished_sccb;
 	u32 evbuf_pending;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++;
+	inc_irq_stat(IRQEXT_SCP);
 	spin_lock(&sclp_lock);
 	finished_sccb = param32 & 0xfffffff8;
 	evbuf_pending = param32 & 0x3;
@@ -813,7 +813,7 @@
 {
 	u32 finished_sccb;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_SCP]++;
+	inc_irq_stat(IRQEXT_SCP);
 	finished_sccb = param32 & 0xfffffff8;
 	/* Is this the interrupt we are waiting for? */
 	if (finished_sccb == 0)
diff --git a/drivers/s390/char/tape_34xx.c b/drivers/s390/char/tape_34xx.c
index 6ae929c..9aa7970 100644
--- a/drivers/s390/char/tape_34xx.c
+++ b/drivers/s390/char/tape_34xx.c
@@ -1193,7 +1193,7 @@
 	.set_online = tape_34xx_online,
 	.set_offline = tape_generic_offline,
 	.freeze = tape_generic_pm_suspend,
-	.int_class = IOINT_TAP,
+	.int_class = IRQIO_TAP,
 };
 
 static int
diff --git a/drivers/s390/char/tape_3590.c b/drivers/s390/char/tape_3590.c
index 1b0eb49..327cb19 100644
--- a/drivers/s390/char/tape_3590.c
+++ b/drivers/s390/char/tape_3590.c
@@ -1656,7 +1656,7 @@
 	.set_offline = tape_generic_offline,
 	.set_online = tape_3590_online,
 	.freeze = tape_generic_pm_suspend,
-	.int_class = IOINT_TAP,
+	.int_class = IRQIO_TAP,
 };
 
 /*
diff --git a/drivers/s390/char/vmur.c b/drivers/s390/char/vmur.c
index 73bef0b..483f72b 100644
--- a/drivers/s390/char/vmur.c
+++ b/drivers/s390/char/vmur.c
@@ -74,7 +74,7 @@
 	.set_online	= ur_set_online,
 	.set_offline	= ur_set_offline,
 	.freeze		= ur_pm_suspend,
-	.int_class	= IOINT_VMR,
+	.int_class	= IRQIO_VMR,
 };
 
 static DEFINE_MUTEX(vmur_mutex);
diff --git a/drivers/s390/cio/chsc.c b/drivers/s390/cio/chsc.c
index 68e80e2..10729bb 100644
--- a/drivers/s390/cio/chsc.c
+++ b/drivers/s390/cio/chsc.c
@@ -283,7 +283,7 @@
 	u8  ccdf[PAGE_SIZE - 24 - 56];	/* content-code dependent field */
 } __packed;
 
-#define CHSC_SEI_NT0	0ULL
+#define CHSC_SEI_NT0	(1ULL << 63)
 #define CHSC_SEI_NT2	(1ULL << 61)
 
 struct chsc_sei {
@@ -291,7 +291,8 @@
 	u32 reserved1;
 	u64 ntsm;			/* notification type mask */
 	struct chsc_header response;
-	u32 reserved2;
+	u32 :24;
+	u8 nt;
 	union {
 		struct chsc_sei_nt0_area nt0_area;
 		struct chsc_sei_nt2_area nt2_area;
@@ -496,17 +497,17 @@
 				css_schedule_eval_all();
 			}
 
-			switch (sei->ntsm) {
-			case CHSC_SEI_NT0:
+			switch (sei->nt) {
+			case 0:
 				chsc_process_sei_nt0(&sei->u.nt0_area);
-				return 1;
-			case CHSC_SEI_NT2:
+				break;
+			case 2:
 				chsc_process_sei_nt2(&sei->u.nt2_area);
-				return 1;
+				break;
 			default:
-				CIO_CRW_EVENT(2, "chsc: unhandled nt (nt=%08Lx)\n",
-					      sei->ntsm);
-				return 0;
+				CIO_CRW_EVENT(2, "chsc: unhandled nt=%d\n",
+					      sei->nt);
+				break;
 			}
 		} else {
 			CIO_CRW_EVENT(2, "chsc: sei failed (rc=%04x)\n",
@@ -537,15 +538,7 @@
 	sei = sei_page;
 
 	CIO_TRACE_EVENT(2, "prcss");
-
-	/*
-	 * The ntsm does not allow to select NT0 and NT2 together. We need to
-	 * first check for NT2, than additionally for NT0...
-	 */
-#ifdef CONFIG_PCI
-	if (!__chsc_process_crw(sei, CHSC_SEI_NT2))
-#endif
-		__chsc_process_crw(sei, CHSC_SEI_NT0);
+	__chsc_process_crw(sei, CHSC_SEI_NT0 | CHSC_SEI_NT2);
 }
 
 void chsc_chp_online(struct chp_id chpid)
diff --git a/drivers/s390/cio/chsc_sch.c b/drivers/s390/cio/chsc_sch.c
index 8f9a1a3..facdf80 100644
--- a/drivers/s390/cio/chsc_sch.c
+++ b/drivers/s390/cio/chsc_sch.c
@@ -58,7 +58,7 @@
 
 	CHSC_LOG(4, "irb");
 	CHSC_LOG_HEX(4, irb, sizeof(*irb));
-	kstat_cpu(smp_processor_id()).irqs[IOINT_CSC]++;
+	inc_irq_stat(IRQIO_CSC);
 
 	/* Copy irb to provided request and set done. */
 	if (!request) {
diff --git a/drivers/s390/cio/cio.c b/drivers/s390/cio/cio.c
index 8e927b9..c8faf62 100644
--- a/drivers/s390/cio/cio.c
+++ b/drivers/s390/cio/cio.c
@@ -611,7 +611,7 @@
 	tpi_info = (struct tpi_info *)&S390_lowcore.subchannel_id;
 	irb = (struct irb *)&S390_lowcore.irb;
 	do {
-		kstat_cpu(smp_processor_id()).irqs[IO_INTERRUPT]++;
+		kstat_incr_irqs_this_cpu(IO_INTERRUPT, NULL);
 		if (tpi_info->adapter_IO) {
 			do_adapter_IO(tpi_info->isc);
 			continue;
@@ -619,7 +619,7 @@
 		sch = (struct subchannel *)(unsigned long)tpi_info->intparm;
 		if (!sch) {
 			/* Clear pending interrupt condition. */
-			kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+			inc_irq_stat(IRQIO_CIO);
 			tsch(tpi_info->schid, irb);
 			continue;
 		}
@@ -633,9 +633,9 @@
 			if (sch->driver && sch->driver->irq)
 				sch->driver->irq(sch);
 			else
-				kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+				inc_irq_stat(IRQIO_CIO);
 		} else
-			kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+			inc_irq_stat(IRQIO_CIO);
 		spin_unlock(sch->lock);
 		/*
 		 * Are more interrupts pending?
@@ -678,7 +678,7 @@
 	if (sch->driver && sch->driver->irq)
 		sch->driver->irq(sch);
 	else
-		kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+		inc_irq_stat(IRQIO_CIO);
 	if (!irq_context) {
 		irq_exit();
 		_local_bh_enable();
diff --git a/drivers/s390/cio/device.c b/drivers/s390/cio/device.c
index 6995cff..7cd5c68 100644
--- a/drivers/s390/cio/device.c
+++ b/drivers/s390/cio/device.c
@@ -758,7 +758,7 @@
 					struct ccw_device *cdev)
 {
 	cdev->private->cdev = cdev;
-	cdev->private->int_class = IOINT_CIO;
+	cdev->private->int_class = IRQIO_CIO;
 	atomic_set(&cdev->private->onoff, 0);
 	cdev->dev.parent = &sch->dev;
 	cdev->dev.release = ccw_device_release;
@@ -1023,7 +1023,7 @@
 	if (cdev)
 		dev_fsm_event(cdev, DEV_EVENT_INTERRUPT);
 	else
-		kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+		inc_irq_stat(IRQIO_CIO);
 }
 
 void io_subchannel_init_config(struct subchannel *sch)
@@ -1634,7 +1634,7 @@
 	memset(&console_private, 0, sizeof(struct ccw_device_private));
 	console_cdev.private = &console_private;
 	console_private.cdev = &console_cdev;
-	console_private.int_class = IOINT_CIO;
+	console_private.int_class = IRQIO_CIO;
 	ret = ccw_device_console_enable(&console_cdev, sch);
 	if (ret) {
 		cio_release_console();
@@ -1715,13 +1715,13 @@
 	if (cdrv->int_class != 0)
 		cdev->private->int_class = cdrv->int_class;
 	else
-		cdev->private->int_class = IOINT_CIO;
+		cdev->private->int_class = IRQIO_CIO;
 
 	ret = cdrv->probe ? cdrv->probe(cdev) : -ENODEV;
 
 	if (ret) {
 		cdev->drv = NULL;
-		cdev->private->int_class = IOINT_CIO;
+		cdev->private->int_class = IRQIO_CIO;
 		return ret;
 	}
 
@@ -1755,7 +1755,7 @@
 	}
 	ccw_device_set_timeout(cdev, 0);
 	cdev->drv = NULL;
-	cdev->private->int_class = IOINT_CIO;
+	cdev->private->int_class = IRQIO_CIO;
 	return 0;
 }
 
diff --git a/drivers/s390/cio/device.h b/drivers/s390/cio/device.h
index 2e575cf..7d4ecb6 100644
--- a/drivers/s390/cio/device.h
+++ b/drivers/s390/cio/device.h
@@ -61,11 +61,10 @@
 
 	if (dev_event == DEV_EVENT_INTERRUPT) {
 		if (state == DEV_STATE_ONLINE)
-			kstat_cpu(smp_processor_id()).
-				irqs[cdev->private->int_class]++;
+			inc_irq_stat(cdev->private->int_class);
 		else if (state != DEV_STATE_CMFCHANGE &&
 			 state != DEV_STATE_CMFUPDATE)
-			kstat_cpu(smp_processor_id()).irqs[IOINT_CIO]++;
+			inc_irq_stat(IRQIO_CIO);
 	}
 	dev_jumptable[state][dev_event](cdev, dev_event);
 }
diff --git a/drivers/s390/cio/eadm_sch.c b/drivers/s390/cio/eadm_sch.c
index 6c96734..d9eddcb 100644
--- a/drivers/s390/cio/eadm_sch.c
+++ b/drivers/s390/cio/eadm_sch.c
@@ -139,7 +139,7 @@
 	EADM_LOG(6, "irq");
 	EADM_LOG_HEX(6, irb, sizeof(*irb));
 
-	kstat_cpu(smp_processor_id()).irqs[IOINT_ADM]++;
+	inc_irq_stat(IRQIO_ADM);
 
 	if ((scsw->stctl & (SCSW_STCTL_ALERT_STATUS | SCSW_STCTL_STATUS_PEND))
 	    && scsw->eswf == 1 && irb->esw.eadm.erw.r)
diff --git a/drivers/s390/cio/qdio_thinint.c b/drivers/s390/cio/qdio_thinint.c
index bdb394b..bde5255 100644
--- a/drivers/s390/cio/qdio_thinint.c
+++ b/drivers/s390/cio/qdio_thinint.c
@@ -182,7 +182,7 @@
 	struct qdio_q *q;
 
 	last_ai_time = S390_lowcore.int_clock;
-	kstat_cpu(smp_processor_id()).irqs[IOINT_QAI]++;
+	inc_irq_stat(IRQIO_QAI);
 
 	/* protect tiq_list entries, only changed in activate or shutdown */
 	rcu_read_lock();
diff --git a/drivers/s390/crypto/ap_bus.c b/drivers/s390/crypto/ap_bus.c
index 7b865a7..b8b340a 100644
--- a/drivers/s390/crypto/ap_bus.c
+++ b/drivers/s390/crypto/ap_bus.c
@@ -1272,7 +1272,7 @@
 
 static void ap_interrupt_handler(void *unused1, void *unused2)
 {
-	kstat_cpu(smp_processor_id()).irqs[IOINT_APB]++;
+	inc_irq_stat(IRQIO_APB);
 	tasklet_schedule(&ap_tasklet);
 }
 
diff --git a/drivers/s390/kvm/kvm_virtio.c b/drivers/s390/kvm/kvm_virtio.c
index 7dabef6..8491111 100644
--- a/drivers/s390/kvm/kvm_virtio.c
+++ b/drivers/s390/kvm/kvm_virtio.c
@@ -392,7 +392,7 @@
 
 	if ((ext_code.subcode & 0xff00) != VIRTIO_SUBCODE_64)
 		return;
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_VRT]++;
+	inc_irq_stat(IRQEXT_VRT);
 
 	/* The LSB might be overloaded, we have to mask it */
 	vq = (struct virtqueue *)(param64 & ~1UL);
diff --git a/drivers/s390/net/claw.c b/drivers/s390/net/claw.c
index 5c70a65..83bc9c5 100644
--- a/drivers/s390/net/claw.c
+++ b/drivers/s390/net/claw.c
@@ -282,7 +282,7 @@
 	.ids	= claw_ids,
 	.probe	= ccwgroup_probe_ccwdev,
 	.remove	= ccwgroup_remove_ccwdev,
-	.int_class = IOINT_CLW,
+	.int_class = IRQIO_CLW,
 };
 
 static ssize_t claw_driver_group_store(struct device_driver *ddrv,
diff --git a/drivers/s390/net/ctcm_main.c b/drivers/s390/net/ctcm_main.c
index 817b689..676f120 100644
--- a/drivers/s390/net/ctcm_main.c
+++ b/drivers/s390/net/ctcm_main.c
@@ -1755,7 +1755,7 @@
 	.ids	= ctcm_ids,
 	.probe	= ccwgroup_probe_ccwdev,
 	.remove	= ccwgroup_remove_ccwdev,
-	.int_class = IOINT_CTC,
+	.int_class = IRQIO_CTC,
 };
 
 static struct ccwgroup_driver ctcm_group_driver = {
diff --git a/drivers/s390/net/lcs.c b/drivers/s390/net/lcs.c
index 2ca0f1d..c645dc9 100644
--- a/drivers/s390/net/lcs.c
+++ b/drivers/s390/net/lcs.c
@@ -2384,7 +2384,7 @@
 	.ids	= lcs_ids,
 	.probe	= ccwgroup_probe_ccwdev,
 	.remove	= ccwgroup_remove_ccwdev,
-	.int_class = IOINT_LCS,
+	.int_class = IRQIO_LCS,
 };
 
 /**
diff --git a/drivers/scsi/isci/init.c b/drivers/scsi/isci/init.c
index d73fdcf..2839baa 100644
--- a/drivers/scsi/isci/init.c
+++ b/drivers/scsi/isci/init.c
@@ -633,7 +633,7 @@
 		return -ENOMEM;
 	pci_set_drvdata(pdev, pci_info);
 
-	if (efi_enabled)
+	if (efi_enabled(EFI_RUNTIME_SERVICES))
 		orom = isci_get_efi_var(pdev);
 
 	if (!orom)
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
index 5aedcdf..1ebe67c 100644
--- a/drivers/sh/clk/cpg.c
+++ b/drivers/sh/clk/cpg.c
@@ -126,6 +126,12 @@
 
 static int sh_clk_div_enable(struct clk *clk)
 {
+	if (clk->div_mask == SH_CLK_DIV6_MSK) {
+		int ret = sh_clk_div_set_rate(clk, clk->rate);
+		if (ret < 0)
+			return ret;
+	}
+
 	sh_clk_write(sh_clk_read(clk) & ~CPG_CKSTP_BIT, clk);
 	return 0;
 }
diff --git a/drivers/spi/spi-tegra20-sflash.c b/drivers/spi/spi-tegra20-sflash.c
index 448a8cc..e5dce91 100644
--- a/drivers/spi/spi-tegra20-sflash.c
+++ b/drivers/spi/spi-tegra20-sflash.c
@@ -34,7 +34,7 @@
 #include <linux/of_device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi-tegra.h>
-#include <mach/clk.h>
+#include <linux/clk/tegra.h>
 
 #define SPI_COMMAND				0x000
 #define SPI_GO					BIT(30)
@@ -525,7 +525,7 @@
 		goto exit_free_master;
 	}
 
-	tsd->clk = devm_clk_get(&pdev->dev, "spi");
+	tsd->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(tsd->clk)) {
 		dev_err(&pdev->dev, "can not get clock\n");
 		ret = PTR_ERR(tsd->clk);
diff --git a/drivers/spi/spi-tegra20-slink.c b/drivers/spi/spi-tegra20-slink.c
index 651167f..e255e7a 100644
--- a/drivers/spi/spi-tegra20-slink.c
+++ b/drivers/spi/spi-tegra20-slink.c
@@ -35,7 +35,7 @@
 #include <linux/of_device.h>
 #include <linux/spi/spi.h>
 #include <linux/spi/spi-tegra.h>
-#include <mach/clk.h>
+#include <linux/clk/tegra.h>
 
 #define SLINK_COMMAND			0x000
 #define SLINK_BIT_LENGTH(x)		(((x) & 0x1f) << 0)
@@ -1191,7 +1191,7 @@
 		goto exit_free_master;
 	}
 
-	tspi->clk = devm_clk_get(&pdev->dev, "slink");
+	tspi->clk = devm_clk_get(&pdev->dev, NULL);
 	if (IS_ERR(tspi->clk)) {
 		dev_err(&pdev->dev, "can not get clock\n");
 		ret = PTR_ERR(tspi->clk);
diff --git a/drivers/staging/comedi/Kconfig b/drivers/staging/comedi/Kconfig
index 7de2a10..36eec32 100644
--- a/drivers/staging/comedi/Kconfig
+++ b/drivers/staging/comedi/Kconfig
@@ -444,6 +444,7 @@
 
 config COMEDI_NI_AT_A2150
 	tristate "NI AT-A2150 ISA card support"
+	select COMEDI_FC
 	depends on VIRT_TO_BUS
 	---help---
 	  Enable support for National Instruments AT-A2150 cards
diff --git a/drivers/staging/comedi/comedi_fops.c b/drivers/staging/comedi/comedi_fops.c
index b7bba17..9b038e4 100644
--- a/drivers/staging/comedi/comedi_fops.c
+++ b/drivers/staging/comedi/comedi_fops.c
@@ -1549,6 +1549,9 @@
 	if (cmd == COMEDI_DEVCONFIG) {
 		rc = do_devconfig_ioctl(dev,
 					(struct comedi_devconfig __user *)arg);
+		if (rc == 0)
+			/* Evade comedi_auto_unconfig(). */
+			dev_file_info->hardware_device = NULL;
 		goto done;
 	}
 
diff --git a/drivers/staging/comedi/drivers/comedi_test.c b/drivers/staging/comedi/drivers/comedi_test.c
index fb3d093..01de996 100644
--- a/drivers/staging/comedi/drivers/comedi_test.c
+++ b/drivers/staging/comedi/drivers/comedi_test.c
@@ -345,7 +345,7 @@
 	struct waveform_private *devpriv = dev->private;
 
 	devpriv->timer_running = 0;
-	del_timer(&devpriv->timer);
+	del_timer_sync(&devpriv->timer);
 	return 0;
 }
 
diff --git a/drivers/staging/comedi/drivers/ni_pcimio.c b/drivers/staging/comedi/drivers/ni_pcimio.c
index aaac0b2..fd1662b 100644
--- a/drivers/staging/comedi/drivers/ni_pcimio.c
+++ b/drivers/staging/comedi/drivers/ni_pcimio.c
@@ -963,7 +963,7 @@
 	 .ao_range_table = &range_ni_M_625x_ao,
 	 .reg_type = ni_reg_625x,
 	 .ao_unipolar = 0,
-	 .ao_speed = 357,
+	 .ao_speed = 350,
 	 .num_p0_dio_channels = 8,
 	 .caldac = {caldac_none},
 	 .has_8255 = 0,
@@ -982,7 +982,7 @@
 	 .ao_range_table = &range_ni_M_625x_ao,
 	 .reg_type = ni_reg_625x,
 	 .ao_unipolar = 0,
-	 .ao_speed = 357,
+	 .ao_speed = 350,
 	 .num_p0_dio_channels = 8,
 	 .caldac = {caldac_none},
 	 .has_8255 = 0,
@@ -1001,7 +1001,7 @@
 	 .ao_range_table = &range_ni_M_625x_ao,
 	 .reg_type = ni_reg_625x,
 	 .ao_unipolar = 0,
-	 .ao_speed = 357,
+	 .ao_speed = 350,
 	 .num_p0_dio_channels = 8,
 	 .caldac = {caldac_none},
 	 .has_8255 = 0,
@@ -1037,7 +1037,7 @@
 	 .ao_range_table = &range_ni_M_625x_ao,
 	 .reg_type = ni_reg_625x,
 	 .ao_unipolar = 0,
-	 .ao_speed = 357,
+	 .ao_speed = 350,
 	 .num_p0_dio_channels = 32,
 	 .caldac = {caldac_none},
 	 .has_8255 = 0,
@@ -1056,7 +1056,7 @@
 	 .ao_range_table = &range_ni_M_625x_ao,
 	 .reg_type = ni_reg_625x,
 	 .ao_unipolar = 0,
-	 .ao_speed = 357,
+	 .ao_speed = 350,
 	 .num_p0_dio_channels = 32,
 	 .caldac = {caldac_none},
 	 .has_8255 = 0,
@@ -1092,7 +1092,7 @@
 	 .ao_range_table = &range_ni_M_628x_ao,
 	 .reg_type = ni_reg_628x,
 	 .ao_unipolar = 1,
-	 .ao_speed = 357,
+	 .ao_speed = 350,
 	 .num_p0_dio_channels = 8,
 	 .caldac = {caldac_none},
 	 .has_8255 = 0,
@@ -1111,7 +1111,7 @@
 	 .ao_range_table = &range_ni_M_628x_ao,
 	 .reg_type = ni_reg_628x,
 	 .ao_unipolar = 1,
-	 .ao_speed = 357,
+	 .ao_speed = 350,
 	 .num_p0_dio_channels = 8,
 	 .caldac = {caldac_none},
 	 .has_8255 = 0,
@@ -1147,7 +1147,7 @@
 	 .ao_range_table = &range_ni_M_628x_ao,
 	 .reg_type = ni_reg_628x,
 	 .ao_unipolar = 1,
-	 .ao_speed = 357,
+	 .ao_speed = 350,
 	 .num_p0_dio_channels = 32,
 	 .caldac = {caldac_none},
 	 .has_8255 = 0,
diff --git a/drivers/staging/fwserial/Kconfig b/drivers/staging/fwserial/Kconfig
index 580406c..b2f8331 100644
--- a/drivers/staging/fwserial/Kconfig
+++ b/drivers/staging/fwserial/Kconfig
@@ -3,7 +3,9 @@
        depends on FIREWIRE
        help
           This enables TTY over IEEE 1394, providing high-speed serial
-	  connectivity to cabled peers.
+	  connectivity to cabled peers. This driver implements a
+	  ad-hoc transport protocol and is currently limited to
+	  Linux-to-Linux communication.
 
 	  To compile this driver as a module, say M here:  the module will
 	  be called firewire-serial.
diff --git a/drivers/staging/fwserial/TODO b/drivers/staging/fwserial/TODO
index 7269005..8dae8fb 100644
--- a/drivers/staging/fwserial/TODO
+++ b/drivers/staging/fwserial/TODO
@@ -1,5 +1,5 @@
-TODOs
------
+TODOs prior to this driver moving out of staging
+------------------------------------------------
 1. Implement retries for RCODE_BUSY, RCODE_NO_ACK and RCODE_SEND_ERROR
    - I/O is handled asynchronously which presents some issues when error
      conditions occur.
@@ -11,17 +11,9 @@
 -- Issues with firewire stack --
 1. This driver uses the same unregistered vendor id that the firewire core does
      (0xd00d1e). Perhaps this could be exposed as a define in
-     firewire-constants.h?
-2. MAX_ASYNC_PAYLOAD needs to be publicly exposed by core/ohci
-   - otherwise how will this driver know the max size of address window to
-     open for one packet write?
+     firewire.h?
 3. Maybe device_max_receive() and link_speed_to_max_payload() should be
      taken up by the firewire core?
-4. To avoid dropping rx data while still limiting the maximum buffering,
-     the size of the AR context must be known. How to expose this to drivers?
-5. Explore if bigger AR context will reduce RCODE_BUSY responses
-   (or auto-grow to certain max size -- but this would require major surgery
-    as the current AR is contiguously mapped)
 
 -- Issues with TTY core --
   1. Hack for alternate device name scheme
diff --git a/drivers/staging/fwserial/fwserial.c b/drivers/staging/fwserial/fwserial.c
index 61ee290..d03a7f5 100644
--- a/drivers/staging/fwserial/fwserial.c
+++ b/drivers/staging/fwserial/fwserial.c
@@ -179,7 +179,7 @@
 /* Returns the max receive packet size for the given card */
 static inline int device_max_receive(struct fw_device *fw_device)
 {
-	return 1 <<  (clamp_t(int, fw_device->max_rec, 8U, 13U) + 1);
+	return 1 <<  (clamp_t(int, fw_device->max_rec, 8U, 11U) + 1);
 }
 
 static void fwtty_log_tx_error(struct fwtty_port *port, int rcode)
diff --git a/drivers/staging/fwserial/fwserial.h b/drivers/staging/fwserial/fwserial.h
index 8b572ed..caa1c1e 100644
--- a/drivers/staging/fwserial/fwserial.h
+++ b/drivers/staging/fwserial/fwserial.h
@@ -374,10 +374,10 @@
  */
 static inline int link_speed_to_max_payload(unsigned speed)
 {
-	static const int max_async[] = { 307, 614, 1229, 2458, 4916, 9832, };
-	BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_3200);
+	static const int max_async[] = { 307, 614, 1229, 2458, };
+	BUILD_BUG_ON(ARRAY_SIZE(max_async) - 1 != SCODE_800);
 
-	speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_3200);
+	speed = clamp(speed, (unsigned) SCODE_100, (unsigned) SCODE_800);
 	if (limit_bw)
 		return max_async[speed];
 	else
diff --git a/drivers/staging/iio/adc/mxs-lradc.c b/drivers/staging/iio/adc/mxs-lradc.c
index fb31b45..c5ceb9d 100644
--- a/drivers/staging/iio/adc/mxs-lradc.c
+++ b/drivers/staging/iio/adc/mxs-lradc.c
@@ -239,7 +239,7 @@
 	struct mxs_lradc *lradc = iio_priv(iio);
 	const uint32_t chan_value = LRADC_CH_ACCUMULATE |
 		((LRADC_DELAY_TIMER_LOOP - 1) << LRADC_CH_NUM_SAMPLES_OFFSET);
-	int i, j = 0;
+	unsigned int i, j = 0;
 
 	for_each_set_bit(i, iio->active_scan_mask, iio->masklength) {
 		lradc->buffer[j] = readl(lradc->base + LRADC_CH(j));
diff --git a/drivers/staging/iio/gyro/Kconfig b/drivers/staging/iio/gyro/Kconfig
index ea295b2..87979a0 100644
--- a/drivers/staging/iio/gyro/Kconfig
+++ b/drivers/staging/iio/gyro/Kconfig
@@ -27,8 +27,8 @@
 config ADIS16260
 	tristate "Analog Devices ADIS16260 Digital Gyroscope Sensor SPI driver"
 	depends on SPI
-	select IIO_TRIGGER if IIO_BUFFER
-	select IIO_SW_RING if IIO_BUFFER
+	select IIO_ADIS_LIB
+	select IIO_ADIS_LIB_BUFFER if IIO_BUFFER
 	help
 	  Say yes here to build support for Analog Devices ADIS16260 ADIS16265
 	  ADIS16250 ADIS16255 and ADIS16251 programmable digital gyroscope sensors.
diff --git a/drivers/staging/iio/gyro/adis16080_core.c b/drivers/staging/iio/gyro/adis16080_core.c
index 3525a68..41d7350 100644
--- a/drivers/staging/iio/gyro/adis16080_core.c
+++ b/drivers/staging/iio/gyro/adis16080_core.c
@@ -69,7 +69,7 @@
 	ret = spi_read(st->us, st->buf, 2);
 
 	if (ret == 0)
-		*val = ((st->buf[0] & 0xF) << 8) | st->buf[1];
+		*val = sign_extend32(((st->buf[0] & 0xF) << 8) | st->buf[1], 11);
 	mutex_unlock(&st->buf_lock);
 
 	return ret;
diff --git a/drivers/staging/imx-drm/imx-drm-core.c b/drivers/staging/imx-drm/imx-drm-core.c
index ecf0f44..cec19f1 100644
--- a/drivers/staging/imx-drm/imx-drm-core.c
+++ b/drivers/staging/imx-drm/imx-drm-core.c
@@ -584,7 +584,6 @@
 
 	ret = imx_drm_encoder_register(imx_drm_encoder);
 	if (ret) {
-		kfree(imx_drm_encoder);
 		ret = -ENOMEM;
 		goto err_register;
 	}
diff --git a/drivers/staging/imx-drm/ipu-v3/ipu-common.c b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
index 677e665..f7059cd 100644
--- a/drivers/staging/imx-drm/ipu-v3/ipu-common.c
+++ b/drivers/staging/imx-drm/ipu-v3/ipu-common.c
@@ -1104,7 +1104,9 @@
 	if (ret)
 		goto out_failed_irq;
 
-	ipu_reset(ipu);
+	ret = ipu_reset(ipu);
+	if (ret)
+		goto out_failed_reset;
 
 	/* Set MCU_T to divide MCU access window into 2 */
 	ipu_cm_write(ipu, 0x00400000L | (IPU_MCU_T_DEFAULT << 18),
@@ -1129,6 +1131,7 @@
 	ipu_submodules_exit(ipu);
 failed_submodules_init:
 	ipu_irq_exit(ipu);
+out_failed_reset:
 out_failed_irq:
 	clk_disable_unprepare(ipu->clk);
 failed_clk_get:
diff --git a/drivers/staging/imx-drm/ipuv3-crtc.c b/drivers/staging/imx-drm/ipuv3-crtc.c
index 1892006..4b3a019 100644
--- a/drivers/staging/imx-drm/ipuv3-crtc.c
+++ b/drivers/staging/imx-drm/ipuv3-crtc.c
@@ -452,7 +452,7 @@
 	int ret;
 
 	ipu_crtc->ipu_ch = ipu_idmac_get(ipu, pdata->dma[0]);
-	if (IS_ERR_OR_NULL(ipu_crtc->ipu_ch)) {
+	if (IS_ERR(ipu_crtc->ipu_ch)) {
 		ret = PTR_ERR(ipu_crtc->ipu_ch);
 		goto err_out;
 	}
@@ -472,7 +472,7 @@
 	if (pdata->dp >= 0) {
 		ipu_crtc->dp = ipu_dp_get(ipu, pdata->dp);
 		if (IS_ERR(ipu_crtc->dp)) {
-			ret = PTR_ERR(ipu_crtc->ipu_ch);
+			ret = PTR_ERR(ipu_crtc->dp);
 			goto err_out;
 		}
 	}
@@ -548,6 +548,8 @@
 	ipu_crtc->dev = &pdev->dev;
 
 	ret = ipu_crtc_init(ipu_crtc, pdata);
+	if (ret)
+		return ret;
 
 	platform_set_drvdata(pdev, ipu_crtc);
 
diff --git a/drivers/staging/nvec/TODO b/drivers/staging/nvec/TODO
index f950ab8..e5ae42a 100644
--- a/drivers/staging/nvec/TODO
+++ b/drivers/staging/nvec/TODO
@@ -1,9 +1,5 @@
 ToDo list (incomplete, unordered)
 	- add compile as module support
-	- fix clk usage
-	  should not be using clk_get_sys(), but clk_get(&pdev->dev, conn)
-	  where conn is either NULL if the device only has one clock, or
-	  the device specific name if it has multiple clocks.
 	- move half of the nvec init stuff to i2c-tegra.c
 	- move event handling to nvec_events
 	- finish suspend/resume support
diff --git a/drivers/staging/nvec/nvec.c b/drivers/staging/nvec/nvec.c
index 2830946..9417941 100644
--- a/drivers/staging/nvec/nvec.c
+++ b/drivers/staging/nvec/nvec.c
@@ -37,8 +37,7 @@
 #include <linux/slab.h>
 #include <linux/spinlock.h>
 #include <linux/workqueue.h>
-
-#include <mach/clk.h>
+#include <linux/clk/tegra.h>
 
 #include "nvec.h"
 
@@ -771,7 +770,7 @@
 		return -ENODEV;
 	}
 
-	i2c_clk = clk_get_sys("tegra-i2c.2", "div-clk");
+	i2c_clk = clk_get(&pdev->dev, "div-clk");
 	if (IS_ERR(i2c_clk)) {
 		dev_err(nvec->dev, "failed to get controller clock\n");
 		return -ENODEV;
diff --git a/drivers/staging/omapdrm/Makefile b/drivers/staging/omapdrm/Makefile
index 1ca0e00..d85e058 100644
--- a/drivers/staging/omapdrm/Makefile
+++ b/drivers/staging/omapdrm/Makefile
@@ -5,6 +5,7 @@
 
 ccflags-y := -Iinclude/drm -Werror
 omapdrm-y := omap_drv.o \
+	omap_irq.o \
 	omap_debugfs.o \
 	omap_crtc.o \
 	omap_plane.o \
diff --git a/drivers/staging/omapdrm/TODO b/drivers/staging/omapdrm/TODO
index 938c788..abeeb00 100644
--- a/drivers/staging/omapdrm/TODO
+++ b/drivers/staging/omapdrm/TODO
@@ -17,9 +17,6 @@
 . Revisit GEM sync object infrastructure.. TTM has some framework for this
   already.  Possibly this could be refactored out and made more common?
   There should be some way to do this with less wheel-reinvention.
-. Review DSS vs KMS mismatches.  The omap_dss_device is sort of part encoder,
-  part connector.  Which results in a bit of duct tape to fwd calls from
-  encoder to connector.  Possibly this could be done a bit better.
 . Solve PM sequencing on resume.  DMM/TILER must be reloaded before any
   access is made from any component in the system.  Which means on suspend
   CRTC's should be disabled, and on resume the LUT should be reprogrammed
diff --git a/drivers/staging/omapdrm/omap_connector.c b/drivers/staging/omapdrm/omap_connector.c
index 91edb3f..4cc9ee7 100644
--- a/drivers/staging/omapdrm/omap_connector.c
+++ b/drivers/staging/omapdrm/omap_connector.c
@@ -31,9 +31,10 @@
 struct omap_connector {
 	struct drm_connector base;
 	struct omap_dss_device *dssdev;
+	struct drm_encoder *encoder;
 };
 
-static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,
+void copy_timings_omap_to_drm(struct drm_display_mode *mode,
 		struct omap_video_timings *timings)
 {
 	mode->clock = timings->pixel_clock;
@@ -64,7 +65,7 @@
 		mode->flags |= DRM_MODE_FLAG_NVSYNC;
 }
 
-static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
+void copy_timings_drm_to_omap(struct omap_video_timings *timings,
 		struct drm_display_mode *mode)
 {
 	timings->pixel_clock = mode->clock;
@@ -96,48 +97,7 @@
 	timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
 }
 
-static void omap_connector_dpms(struct drm_connector *connector, int mode)
-{
-	struct omap_connector *omap_connector = to_omap_connector(connector);
-	struct omap_dss_device *dssdev = omap_connector->dssdev;
-	int old_dpms;
-
-	DBG("%s: %d", dssdev->name, mode);
-
-	old_dpms = connector->dpms;
-
-	/* from off to on, do from crtc to connector */
-	if (mode < old_dpms)
-		drm_helper_connector_dpms(connector, mode);
-
-	if (mode == DRM_MODE_DPMS_ON) {
-		/* store resume info for suspended displays */
-		switch (dssdev->state) {
-		case OMAP_DSS_DISPLAY_SUSPENDED:
-			dssdev->activate_after_resume = true;
-			break;
-		case OMAP_DSS_DISPLAY_DISABLED: {
-			int ret = dssdev->driver->enable(dssdev);
-			if (ret) {
-				DBG("%s: failed to enable: %d",
-						dssdev->name, ret);
-				dssdev->driver->disable(dssdev);
-			}
-			break;
-		}
-		default:
-			break;
-		}
-	} else {
-		/* TODO */
-	}
-
-	/* from on to off, do from connector to crtc */
-	if (mode > old_dpms)
-		drm_helper_connector_dpms(connector, mode);
-}
-
-enum drm_connector_status omap_connector_detect(
+static enum drm_connector_status omap_connector_detect(
 		struct drm_connector *connector, bool force)
 {
 	struct omap_connector *omap_connector = to_omap_connector(connector);
@@ -164,8 +124,6 @@
 	struct omap_connector *omap_connector = to_omap_connector(connector);
 	struct omap_dss_device *dssdev = omap_connector->dssdev;
 
-	dssdev->driver->disable(dssdev);
-
 	DBG("%s", omap_connector->dssdev->name);
 	drm_sysfs_connector_remove(connector);
 	drm_connector_cleanup(connector);
@@ -261,36 +219,12 @@
 struct drm_encoder *omap_connector_attached_encoder(
 		struct drm_connector *connector)
 {
-	int i;
 	struct omap_connector *omap_connector = to_omap_connector(connector);
-
-	for (i = 0; i < DRM_CONNECTOR_MAX_ENCODER; i++) {
-		struct drm_mode_object *obj;
-
-		if (connector->encoder_ids[i] == 0)
-			break;
-
-		obj = drm_mode_object_find(connector->dev,
-				connector->encoder_ids[i],
-				DRM_MODE_OBJECT_ENCODER);
-
-		if (obj) {
-			struct drm_encoder *encoder = obj_to_encoder(obj);
-			struct omap_overlay_manager *mgr =
-					omap_encoder_get_manager(encoder);
-			DBG("%s: found %s", omap_connector->dssdev->name,
-					mgr->name);
-			return encoder;
-		}
-	}
-
-	DBG("%s: no encoder", omap_connector->dssdev->name);
-
-	return NULL;
+	return omap_connector->encoder;
 }
 
 static const struct drm_connector_funcs omap_connector_funcs = {
-	.dpms = omap_connector_dpms,
+	.dpms = drm_helper_connector_dpms,
 	.detect = omap_connector_detect,
 	.fill_modes = drm_helper_probe_single_connector_modes,
 	.destroy = omap_connector_destroy,
@@ -302,34 +236,6 @@
 	.best_encoder = omap_connector_attached_encoder,
 };
 
-/* called from encoder when mode is set, to propagate settings to the dssdev */
-void omap_connector_mode_set(struct drm_connector *connector,
-		struct drm_display_mode *mode)
-{
-	struct drm_device *dev = connector->dev;
-	struct omap_connector *omap_connector = to_omap_connector(connector);
-	struct omap_dss_device *dssdev = omap_connector->dssdev;
-	struct omap_dss_driver *dssdrv = dssdev->driver;
-	struct omap_video_timings timings = {0};
-
-	copy_timings_drm_to_omap(&timings, mode);
-
-	DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
-			omap_connector->dssdev->name,
-			mode->base.id, mode->name, mode->vrefresh, mode->clock,
-			mode->hdisplay, mode->hsync_start,
-			mode->hsync_end, mode->htotal,
-			mode->vdisplay, mode->vsync_start,
-			mode->vsync_end, mode->vtotal, mode->type, mode->flags);
-
-	if (dssdrv->check_timings(dssdev, &timings)) {
-		dev_err(dev->dev, "could not set timings\n");
-		return;
-	}
-
-	dssdrv->set_timings(dssdev, &timings);
-}
-
 /* flush an area of the framebuffer (in case of manual update display that
  * is not automatically flushed)
  */
@@ -344,7 +250,8 @@
 
 /* initialize connector */
 struct drm_connector *omap_connector_init(struct drm_device *dev,
-		int connector_type, struct omap_dss_device *dssdev)
+		int connector_type, struct omap_dss_device *dssdev,
+		struct drm_encoder *encoder)
 {
 	struct drm_connector *connector = NULL;
 	struct omap_connector *omap_connector;
@@ -360,6 +267,8 @@
 	}
 
 	omap_connector->dssdev = dssdev;
+	omap_connector->encoder = encoder;
+
 	connector = &omap_connector->base;
 
 	drm_connector_init(dev, connector, &omap_connector_funcs,
diff --git a/drivers/staging/omapdrm/omap_crtc.c b/drivers/staging/omapdrm/omap_crtc.c
index d87bd84..5c6ed60 100644
--- a/drivers/staging/omapdrm/omap_crtc.c
+++ b/drivers/staging/omapdrm/omap_crtc.c
@@ -28,19 +28,131 @@
 struct omap_crtc {
 	struct drm_crtc base;
 	struct drm_plane *plane;
+
 	const char *name;
-	int id;
+	int pipe;
+	enum omap_channel channel;
+	struct omap_overlay_manager_info info;
+
+	/*
+	 * Temporary: eventually this will go away, but it is needed
+	 * for now to keep the output's happy.  (They only need
+	 * mgr->id.)  Eventually this will be replaced w/ something
+	 * more common-panel-framework-y
+	 */
+	struct omap_overlay_manager mgr;
+
+	struct omap_video_timings timings;
+	bool enabled;
+	bool full_update;
+
+	struct omap_drm_apply apply;
+
+	struct omap_drm_irq apply_irq;
+	struct omap_drm_irq error_irq;
+
+	/* list of in-progress apply's: */
+	struct list_head pending_applies;
+
+	/* list of queued apply's: */
+	struct list_head queued_applies;
+
+	/* for handling queued and in-progress applies: */
+	struct work_struct apply_work;
 
 	/* if there is a pending flip, these will be non-null: */
 	struct drm_pending_vblank_event *event;
 	struct drm_framebuffer *old_fb;
+
+	/* for handling page flips without caring about what
+	 * the callback is called from.  Possibly we should just
+	 * make omap_gem always call the cb from the worker so
+	 * we don't have to care about this..
+	 *
+	 * XXX maybe fold into apply_work??
+	 */
+	struct work_struct page_flip_work;
 };
 
+/*
+ * Manager-ops, callbacks from output when they need to configure
+ * the upstream part of the video pipe.
+ *
+ * Most of these we can ignore until we add support for command-mode
+ * panels.. for video-mode the crtc-helpers already do an adequate
+ * job of sequencing the setup of the video pipe in the proper order
+ */
+
+/* we can probably ignore these until we support command-mode panels: */
+static void omap_crtc_start_update(struct omap_overlay_manager *mgr)
+{
+}
+
+static int omap_crtc_enable(struct omap_overlay_manager *mgr)
+{
+	return 0;
+}
+
+static void omap_crtc_disable(struct omap_overlay_manager *mgr)
+{
+}
+
+static void omap_crtc_set_timings(struct omap_overlay_manager *mgr,
+		const struct omap_video_timings *timings)
+{
+	struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr);
+	DBG("%s", omap_crtc->name);
+	omap_crtc->timings = *timings;
+	omap_crtc->full_update = true;
+}
+
+static void omap_crtc_set_lcd_config(struct omap_overlay_manager *mgr,
+		const struct dss_lcd_mgr_config *config)
+{
+	struct omap_crtc *omap_crtc = container_of(mgr, struct omap_crtc, mgr);
+	DBG("%s", omap_crtc->name);
+	dispc_mgr_set_lcd_config(omap_crtc->channel, config);
+}
+
+static int omap_crtc_register_framedone_handler(
+		struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data)
+{
+	return 0;
+}
+
+static void omap_crtc_unregister_framedone_handler(
+		struct omap_overlay_manager *mgr,
+		void (*handler)(void *), void *data)
+{
+}
+
+static const struct dss_mgr_ops mgr_ops = {
+		.start_update = omap_crtc_start_update,
+		.enable = omap_crtc_enable,
+		.disable = omap_crtc_disable,
+		.set_timings = omap_crtc_set_timings,
+		.set_lcd_config = omap_crtc_set_lcd_config,
+		.register_framedone_handler = omap_crtc_register_framedone_handler,
+		.unregister_framedone_handler = omap_crtc_unregister_framedone_handler,
+};
+
+/*
+ * CRTC funcs:
+ */
+
 static void omap_crtc_destroy(struct drm_crtc *crtc)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+
+	DBG("%s", omap_crtc->name);
+
+	WARN_ON(omap_crtc->apply_irq.registered);
+	omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
+
 	omap_crtc->plane->funcs->destroy(omap_crtc->plane);
 	drm_crtc_cleanup(crtc);
+
 	kfree(omap_crtc);
 }
 
@@ -48,14 +160,25 @@
 {
 	struct omap_drm_private *priv = crtc->dev->dev_private;
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	bool enabled = (mode == DRM_MODE_DPMS_ON);
 	int i;
 
-	WARN_ON(omap_plane_dpms(omap_crtc->plane, mode));
+	DBG("%s: %d", omap_crtc->name, mode);
 
-	for (i = 0; i < priv->num_planes; i++) {
-		struct drm_plane *plane = priv->planes[i];
-		if (plane->crtc == crtc)
-			WARN_ON(omap_plane_dpms(plane, mode));
+	if (enabled != omap_crtc->enabled) {
+		omap_crtc->enabled = enabled;
+		omap_crtc->full_update = true;
+		omap_crtc_apply(crtc, &omap_crtc->apply);
+
+		/* also enable our private plane: */
+		WARN_ON(omap_plane_dpms(omap_crtc->plane, mode));
+
+		/* and any attached overlay planes: */
+		for (i = 0; i < priv->num_planes; i++) {
+			struct drm_plane *plane = priv->planes[i];
+			if (plane->crtc == crtc)
+				WARN_ON(omap_plane_dpms(plane, mode));
+		}
 	}
 }
 
@@ -73,12 +196,26 @@
 		struct drm_framebuffer *old_fb)
 {
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-	struct drm_plane *plane = omap_crtc->plane;
 
-	return omap_plane_mode_set(plane, crtc, crtc->fb,
+	mode = adjusted_mode;
+
+	DBG("%s: set mode: %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x",
+			omap_crtc->name, mode->base.id, mode->name,
+			mode->vrefresh, mode->clock,
+			mode->hdisplay, mode->hsync_start,
+			mode->hsync_end, mode->htotal,
+			mode->vdisplay, mode->vsync_start,
+			mode->vsync_end, mode->vtotal,
+			mode->type, mode->flags);
+
+	copy_timings_drm_to_omap(&omap_crtc->timings, mode);
+	omap_crtc->full_update = true;
+
+	return omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb,
 			0, 0, mode->hdisplay, mode->vdisplay,
 			x << 16, y << 16,
-			mode->hdisplay << 16, mode->vdisplay << 16);
+			mode->hdisplay << 16, mode->vdisplay << 16,
+			NULL, NULL);
 }
 
 static void omap_crtc_prepare(struct drm_crtc *crtc)
@@ -102,10 +239,11 @@
 	struct drm_plane *plane = omap_crtc->plane;
 	struct drm_display_mode *mode = &crtc->mode;
 
-	return plane->funcs->update_plane(plane, crtc, crtc->fb,
+	return omap_plane_mode_set(plane, crtc, crtc->fb,
 			0, 0, mode->hdisplay, mode->vdisplay,
 			x << 16, y << 16,
-			mode->hdisplay << 16, mode->vdisplay << 16);
+			mode->hdisplay << 16, mode->vdisplay << 16,
+			NULL, NULL);
 }
 
 static void omap_crtc_load_lut(struct drm_crtc *crtc)
@@ -114,61 +252,52 @@
 
 static void vblank_cb(void *arg)
 {
-	static uint32_t sequence;
 	struct drm_crtc *crtc = arg;
 	struct drm_device *dev = crtc->dev;
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-	struct drm_pending_vblank_event *event = omap_crtc->event;
 	unsigned long flags;
-	struct timeval now;
 
-	WARN_ON(!event);
-
-	omap_crtc->event = NULL;
+	spin_lock_irqsave(&dev->event_lock, flags);
 
 	/* wakeup userspace */
-	if (event) {
-		do_gettimeofday(&now);
+	if (omap_crtc->event)
+		drm_send_vblank_event(dev, omap_crtc->pipe, omap_crtc->event);
 
-		spin_lock_irqsave(&dev->event_lock, flags);
-		/* TODO: we can't yet use the vblank time accounting,
-		 * because omapdss lower layer is the one that knows
-		 * the irq # and registers the handler, which more or
-		 * less defeats how drm_irq works.. for now just fake
-		 * the sequence number and use gettimeofday..
-		 *
-		event->event.sequence = drm_vblank_count_and_time(
-				dev, omap_crtc->id, &now);
-		 */
-		event->event.sequence = sequence++;
-		event->event.tv_sec = now.tv_sec;
-		event->event.tv_usec = now.tv_usec;
-		list_add_tail(&event->base.link,
-				&event->base.file_priv->event_list);
-		wake_up_interruptible(&event->base.file_priv->event_wait);
-		spin_unlock_irqrestore(&dev->event_lock, flags);
-	}
+	omap_crtc->event = NULL;
+	omap_crtc->old_fb = NULL;
+
+	spin_unlock_irqrestore(&dev->event_lock, flags);
+}
+
+static void page_flip_worker(struct work_struct *work)
+{
+	struct omap_crtc *omap_crtc =
+			container_of(work, struct omap_crtc, page_flip_work);
+	struct drm_crtc *crtc = &omap_crtc->base;
+	struct drm_device *dev = crtc->dev;
+	struct drm_display_mode *mode = &crtc->mode;
+	struct drm_gem_object *bo;
+
+	mutex_lock(&dev->mode_config.mutex);
+	omap_plane_mode_set(omap_crtc->plane, crtc, crtc->fb,
+			0, 0, mode->hdisplay, mode->vdisplay,
+			crtc->x << 16, crtc->y << 16,
+			mode->hdisplay << 16, mode->vdisplay << 16,
+			vblank_cb, crtc);
+	mutex_unlock(&dev->mode_config.mutex);
+
+	bo = omap_framebuffer_bo(crtc->fb, 0);
+	drm_gem_object_unreference_unlocked(bo);
 }
 
 static void page_flip_cb(void *arg)
 {
 	struct drm_crtc *crtc = arg;
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
-	struct drm_framebuffer *old_fb = omap_crtc->old_fb;
-	struct drm_gem_object *bo;
+	struct omap_drm_private *priv = crtc->dev->dev_private;
 
-	omap_crtc->old_fb = NULL;
-
-	omap_crtc_mode_set_base(crtc, crtc->x, crtc->y, old_fb);
-
-	/* really we'd like to setup the callback atomically w/ setting the
-	 * new scanout buffer to avoid getting stuck waiting an extra vblank
-	 * cycle.. for now go for correctness and later figure out speed..
-	 */
-	omap_plane_on_endwin(omap_crtc->plane, vblank_cb, crtc);
-
-	bo = omap_framebuffer_bo(crtc->fb, 0);
-	drm_gem_object_unreference_unlocked(bo);
+	/* avoid assumptions about what ctxt we are called from: */
+	queue_work(priv->wq, &omap_crtc->page_flip_work);
 }
 
 static int omap_crtc_page_flip_locked(struct drm_crtc *crtc,
@@ -179,14 +308,14 @@
 	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
 	struct drm_gem_object *bo;
 
-	DBG("%d -> %d", crtc->fb ? crtc->fb->base.id : -1, fb->base.id);
+	DBG("%d -> %d (event=%p)", crtc->fb ? crtc->fb->base.id : -1,
+			fb->base.id, event);
 
-	if (omap_crtc->event) {
+	if (omap_crtc->old_fb) {
 		dev_err(dev->dev, "already a pending flip\n");
 		return -EINVAL;
 	}
 
-	omap_crtc->old_fb = crtc->fb;
 	omap_crtc->event = event;
 	crtc->fb = fb;
 
@@ -234,14 +363,244 @@
 	.load_lut = omap_crtc_load_lut,
 };
 
+const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc)
+{
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	return &omap_crtc->timings;
+}
+
+enum omap_channel omap_crtc_channel(struct drm_crtc *crtc)
+{
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	return omap_crtc->channel;
+}
+
+static void omap_crtc_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+{
+	struct omap_crtc *omap_crtc =
+			container_of(irq, struct omap_crtc, error_irq);
+	struct drm_crtc *crtc = &omap_crtc->base;
+	DRM_ERROR("%s: errors: %08x\n", omap_crtc->name, irqstatus);
+	/* avoid getting in a flood, unregister the irq until next vblank */
+	omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
+}
+
+static void omap_crtc_apply_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+{
+	struct omap_crtc *omap_crtc =
+			container_of(irq, struct omap_crtc, apply_irq);
+	struct drm_crtc *crtc = &omap_crtc->base;
+
+	if (!omap_crtc->error_irq.registered)
+		omap_irq_register(crtc->dev, &omap_crtc->error_irq);
+
+	if (!dispc_mgr_go_busy(omap_crtc->channel)) {
+		struct omap_drm_private *priv =
+				crtc->dev->dev_private;
+		DBG("%s: apply done", omap_crtc->name);
+		omap_irq_unregister(crtc->dev, &omap_crtc->apply_irq);
+		queue_work(priv->wq, &omap_crtc->apply_work);
+	}
+}
+
+static void apply_worker(struct work_struct *work)
+{
+	struct omap_crtc *omap_crtc =
+			container_of(work, struct omap_crtc, apply_work);
+	struct drm_crtc *crtc = &omap_crtc->base;
+	struct drm_device *dev = crtc->dev;
+	struct omap_drm_apply *apply, *n;
+	bool need_apply;
+
+	/*
+	 * Synchronize everything on mode_config.mutex, to keep
+	 * the callbacks and list modification all serialized
+	 * with respect to modesetting ioctls from userspace.
+	 */
+	mutex_lock(&dev->mode_config.mutex);
+	dispc_runtime_get();
+
+	/*
+	 * If we are still pending a previous update, wait.. when the
+	 * pending update completes, we get kicked again.
+	 */
+	if (omap_crtc->apply_irq.registered)
+		goto out;
+
+	/* finish up previous apply's: */
+	list_for_each_entry_safe(apply, n,
+			&omap_crtc->pending_applies, pending_node) {
+		apply->post_apply(apply);
+		list_del(&apply->pending_node);
+	}
+
+	need_apply = !list_empty(&omap_crtc->queued_applies);
+
+	/* then handle the next round of of queued apply's: */
+	list_for_each_entry_safe(apply, n,
+			&omap_crtc->queued_applies, queued_node) {
+		apply->pre_apply(apply);
+		list_del(&apply->queued_node);
+		apply->queued = false;
+		list_add_tail(&apply->pending_node,
+				&omap_crtc->pending_applies);
+	}
+
+	if (need_apply) {
+		enum omap_channel channel = omap_crtc->channel;
+
+		DBG("%s: GO", omap_crtc->name);
+
+		if (dispc_mgr_is_enabled(channel)) {
+			omap_irq_register(dev, &omap_crtc->apply_irq);
+			dispc_mgr_go(channel);
+		} else {
+			struct omap_drm_private *priv = dev->dev_private;
+			queue_work(priv->wq, &omap_crtc->apply_work);
+		}
+	}
+
+out:
+	dispc_runtime_put();
+	mutex_unlock(&dev->mode_config.mutex);
+}
+
+int omap_crtc_apply(struct drm_crtc *crtc,
+		struct omap_drm_apply *apply)
+{
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	struct drm_device *dev = crtc->dev;
+
+	WARN_ON(!mutex_is_locked(&dev->mode_config.mutex));
+
+	/* no need to queue it again if it is already queued: */
+	if (apply->queued)
+		return 0;
+
+	apply->queued = true;
+	list_add_tail(&apply->queued_node, &omap_crtc->queued_applies);
+
+	/*
+	 * If there are no currently pending updates, then go ahead and
+	 * kick the worker immediately, otherwise it will run again when
+	 * the current update finishes.
+	 */
+	if (list_empty(&omap_crtc->pending_applies)) {
+		struct omap_drm_private *priv = crtc->dev->dev_private;
+		queue_work(priv->wq, &omap_crtc->apply_work);
+	}
+
+	return 0;
+}
+
+/* called only from apply */
+static void set_enabled(struct drm_crtc *crtc, bool enable)
+{
+	struct drm_device *dev = crtc->dev;
+	struct omap_crtc *omap_crtc = to_omap_crtc(crtc);
+	enum omap_channel channel = omap_crtc->channel;
+	struct omap_irq_wait *wait = NULL;
+
+	if (dispc_mgr_is_enabled(channel) == enable)
+		return;
+
+	/* ignore sync-lost irqs during enable/disable */
+	omap_irq_unregister(crtc->dev, &omap_crtc->error_irq);
+
+	if (dispc_mgr_get_framedone_irq(channel)) {
+		if (!enable) {
+			wait = omap_irq_wait_init(dev,
+					dispc_mgr_get_framedone_irq(channel), 1);
+		}
+	} else {
+		/*
+		 * When we disable digit output, we need to wait until fields
+		 * are done.  Otherwise the DSS is still working, and turning
+		 * off the clocks prevents DSS from going to OFF mode. And when
+		 * enabling, we need to wait for the extra sync losts
+		 */
+		wait = omap_irq_wait_init(dev,
+				dispc_mgr_get_vsync_irq(channel), 2);
+	}
+
+	dispc_mgr_enable(channel, enable);
+
+	if (wait) {
+		int ret = omap_irq_wait(dev, wait, msecs_to_jiffies(100));
+		if (ret) {
+			dev_err(dev->dev, "%s: timeout waiting for %s\n",
+					omap_crtc->name, enable ? "enable" : "disable");
+		}
+	}
+
+	omap_irq_register(crtc->dev, &omap_crtc->error_irq);
+}
+
+static void omap_crtc_pre_apply(struct omap_drm_apply *apply)
+{
+	struct omap_crtc *omap_crtc =
+			container_of(apply, struct omap_crtc, apply);
+	struct drm_crtc *crtc = &omap_crtc->base;
+	struct drm_encoder *encoder = NULL;
+
+	DBG("%s: enabled=%d, full=%d", omap_crtc->name,
+			omap_crtc->enabled, omap_crtc->full_update);
+
+	if (omap_crtc->full_update) {
+		struct omap_drm_private *priv = crtc->dev->dev_private;
+		int i;
+		for (i = 0; i < priv->num_encoders; i++) {
+			if (priv->encoders[i]->crtc == crtc) {
+				encoder = priv->encoders[i];
+				break;
+			}
+		}
+	}
+
+	if (!omap_crtc->enabled) {
+		set_enabled(&omap_crtc->base, false);
+		if (encoder)
+			omap_encoder_set_enabled(encoder, false);
+	} else {
+		if (encoder) {
+			omap_encoder_set_enabled(encoder, false);
+			omap_encoder_update(encoder, &omap_crtc->mgr,
+					&omap_crtc->timings);
+			omap_encoder_set_enabled(encoder, true);
+			omap_crtc->full_update = false;
+		}
+
+		dispc_mgr_setup(omap_crtc->channel, &omap_crtc->info);
+		dispc_mgr_set_timings(omap_crtc->channel,
+				&omap_crtc->timings);
+		set_enabled(&omap_crtc->base, true);
+	}
+
+	omap_crtc->full_update = false;
+}
+
+static void omap_crtc_post_apply(struct omap_drm_apply *apply)
+{
+	/* nothing needed for post-apply */
+}
+
+static const char *channel_names[] = {
+		[OMAP_DSS_CHANNEL_LCD] = "lcd",
+		[OMAP_DSS_CHANNEL_DIGIT] = "tv",
+		[OMAP_DSS_CHANNEL_LCD2] = "lcd2",
+};
+
 /* initialize crtc */
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
-		struct omap_overlay *ovl, int id)
+		struct drm_plane *plane, enum omap_channel channel, int id)
 {
 	struct drm_crtc *crtc = NULL;
-	struct omap_crtc *omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL);
+	struct omap_crtc *omap_crtc;
+	struct omap_overlay_manager_info *info;
 
-	DBG("%s", ovl->name);
+	DBG("%s", channel_names[channel]);
+
+	omap_crtc = kzalloc(sizeof(*omap_crtc), GFP_KERNEL);
 
 	if (!omap_crtc) {
 		dev_err(dev->dev, "could not allocate CRTC\n");
@@ -250,10 +609,40 @@
 
 	crtc = &omap_crtc->base;
 
-	omap_crtc->plane = omap_plane_init(dev, ovl, (1 << id), true);
+	INIT_WORK(&omap_crtc->page_flip_work, page_flip_worker);
+	INIT_WORK(&omap_crtc->apply_work, apply_worker);
+
+	INIT_LIST_HEAD(&omap_crtc->pending_applies);
+	INIT_LIST_HEAD(&omap_crtc->queued_applies);
+
+	omap_crtc->apply.pre_apply  = omap_crtc_pre_apply;
+	omap_crtc->apply.post_apply = omap_crtc_post_apply;
+
+	omap_crtc->apply_irq.irqmask = pipe2vbl(id);
+	omap_crtc->apply_irq.irq = omap_crtc_apply_irq;
+
+	omap_crtc->error_irq.irqmask =
+			dispc_mgr_get_sync_lost_irq(channel);
+	omap_crtc->error_irq.irq = omap_crtc_error_irq;
+	omap_irq_register(dev, &omap_crtc->error_irq);
+
+	omap_crtc->channel = channel;
+	omap_crtc->plane = plane;
 	omap_crtc->plane->crtc = crtc;
-	omap_crtc->name = ovl->name;
-	omap_crtc->id = id;
+	omap_crtc->name = channel_names[channel];
+	omap_crtc->pipe = id;
+
+	/* temporary: */
+	omap_crtc->mgr.id = channel;
+
+	dss_install_mgr_ops(&mgr_ops);
+
+	/* TODO: fix hard-coded setup.. add properties! */
+	info = &omap_crtc->info;
+	info->default_color = 0x00000000;
+	info->trans_key = 0x00000000;
+	info->trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
+	info->trans_enabled = false;
 
 	drm_crtc_init(dev, crtc, &omap_crtc_funcs);
 	drm_crtc_helper_add(crtc, &omap_crtc_helper_funcs);
diff --git a/drivers/staging/omapdrm/omap_drv.c b/drivers/staging/omapdrm/omap_drv.c
index 84943e5..ae5ecc2 100644
--- a/drivers/staging/omapdrm/omap_drv.c
+++ b/drivers/staging/omapdrm/omap_drv.c
@@ -74,319 +74,98 @@
 	}
 }
 
-#if 0 /* enable when dss2 supports hotplug */
-static int omap_drm_notifier(struct notifier_block *nb,
-		unsigned long evt, void *arg)
-{
-	switch (evt) {
-	case OMAP_DSS_SIZE_CHANGE:
-	case OMAP_DSS_HOTPLUG_CONNECT:
-	case OMAP_DSS_HOTPLUG_DISCONNECT: {
-		struct drm_device *dev = drm_device;
-		DBG("hotplug event: evt=%d, dev=%p", evt, dev);
-		if (dev)
-			drm_sysfs_hotplug_event(dev);
-
-		return NOTIFY_OK;
-	}
-	default:  /* don't care about other events for now */
-		return NOTIFY_DONE;
-	}
-}
-#endif
-
-static void dump_video_chains(void)
-{
-	int i;
-
-	DBG("dumping video chains: ");
-	for (i = 0; i < omap_dss_get_num_overlays(); i++) {
-		struct omap_overlay *ovl = omap_dss_get_overlay(i);
-		struct omap_overlay_manager *mgr = ovl->manager;
-		struct omap_dss_device *dssdev = mgr ?
-					mgr->get_device(mgr) : NULL;
-		if (dssdev) {
-			DBG("%d: %s -> %s -> %s", i, ovl->name, mgr->name,
-						dssdev->name);
-		} else if (mgr) {
-			DBG("%d: %s -> %s", i, ovl->name, mgr->name);
-		} else {
-			DBG("%d: %s", i, ovl->name);
-		}
-	}
-}
-
-/* create encoders for each manager */
-static int create_encoder(struct drm_device *dev,
-		struct omap_overlay_manager *mgr)
-{
-	struct omap_drm_private *priv = dev->dev_private;
-	struct drm_encoder *encoder = omap_encoder_init(dev, mgr);
-
-	if (!encoder) {
-		dev_err(dev->dev, "could not create encoder: %s\n",
-				mgr->name);
-		return -ENOMEM;
-	}
-
-	BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders));
-
-	priv->encoders[priv->num_encoders++] = encoder;
-
-	return 0;
-}
-
-/* create connectors for each display device */
-static int create_connector(struct drm_device *dev,
-		struct omap_dss_device *dssdev)
-{
-	struct omap_drm_private *priv = dev->dev_private;
-	static struct notifier_block *notifier;
-	struct drm_connector *connector;
-	int j;
-
-	if (!dssdev->driver) {
-		dev_warn(dev->dev, "%s has no driver.. skipping it\n",
-				dssdev->name);
-		return 0;
-	}
-
-	if (!(dssdev->driver->get_timings ||
-				dssdev->driver->read_edid)) {
-		dev_warn(dev->dev, "%s driver does not support "
-			"get_timings or read_edid.. skipping it!\n",
-			dssdev->name);
-		return 0;
-	}
-
-	connector = omap_connector_init(dev,
-			get_connector_type(dssdev), dssdev);
-
-	if (!connector) {
-		dev_err(dev->dev, "could not create connector: %s\n",
-				dssdev->name);
-		return -ENOMEM;
-	}
-
-	BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors));
-
-	priv->connectors[priv->num_connectors++] = connector;
-
-#if 0 /* enable when dss2 supports hotplug */
-	notifier = kzalloc(sizeof(struct notifier_block), GFP_KERNEL);
-	notifier->notifier_call = omap_drm_notifier;
-	omap_dss_add_notify(dssdev, notifier);
-#else
-	notifier = NULL;
-#endif
-
-	for (j = 0; j < priv->num_encoders; j++) {
-		struct omap_overlay_manager *mgr =
-			omap_encoder_get_manager(priv->encoders[j]);
-		if (mgr->get_device(mgr) == dssdev) {
-			drm_mode_connector_attach_encoder(connector,
-					priv->encoders[j]);
-		}
-	}
-
-	return 0;
-}
-
-/* create up to max_overlays CRTCs mapping to overlays.. by default,
- * connect the overlays to different managers/encoders, giving priority
- * to encoders connected to connectors with a detected connection
- */
-static int create_crtc(struct drm_device *dev, struct omap_overlay *ovl,
-		int *j, unsigned int connected_connectors)
-{
-	struct omap_drm_private *priv = dev->dev_private;
-	struct omap_overlay_manager *mgr = NULL;
-	struct drm_crtc *crtc;
-
-	/* find next best connector, ones with detected connection first
-	 */
-	while (*j < priv->num_connectors && !mgr) {
-		if (connected_connectors & (1 << *j)) {
-			struct drm_encoder *encoder =
-				omap_connector_attached_encoder(
-						priv->connectors[*j]);
-			if (encoder)
-				mgr = omap_encoder_get_manager(encoder);
-
-		}
-		(*j)++;
-	}
-
-	/* if we couldn't find another connected connector, lets start
-	 * looking at the unconnected connectors:
-	 *
-	 * note: it might not be immediately apparent, but thanks to
-	 * the !mgr check in both this loop and the one above, the only
-	 * way to enter this loop is with *j == priv->num_connectors,
-	 * so idx can never go negative.
-	 */
-	while (*j < 2 * priv->num_connectors && !mgr) {
-		int idx = *j - priv->num_connectors;
-		if (!(connected_connectors & (1 << idx))) {
-			struct drm_encoder *encoder =
-				omap_connector_attached_encoder(
-						priv->connectors[idx]);
-			if (encoder)
-				mgr = omap_encoder_get_manager(encoder);
-
-		}
-		(*j)++;
-	}
-
-	crtc = omap_crtc_init(dev, ovl, priv->num_crtcs);
-
-	if (!crtc) {
-		dev_err(dev->dev, "could not create CRTC: %s\n",
-				ovl->name);
-		return -ENOMEM;
-	}
-
-	BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
-
-	priv->crtcs[priv->num_crtcs++] = crtc;
-
-	return 0;
-}
-
-static int create_plane(struct drm_device *dev, struct omap_overlay *ovl,
-		unsigned int possible_crtcs)
-{
-	struct omap_drm_private *priv = dev->dev_private;
-	struct drm_plane *plane =
-			omap_plane_init(dev, ovl, possible_crtcs, false);
-
-	if (!plane) {
-		dev_err(dev->dev, "could not create plane: %s\n",
-				ovl->name);
-		return -ENOMEM;
-	}
-
-	BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
-
-	priv->planes[priv->num_planes++] = plane;
-
-	return 0;
-}
-
-static int match_dev_name(struct omap_dss_device *dssdev, void *data)
-{
-	return !strcmp(dssdev->name, data);
-}
-
-static unsigned int detect_connectors(struct drm_device *dev)
-{
-	struct omap_drm_private *priv = dev->dev_private;
-	unsigned int connected_connectors = 0;
-	int i;
-
-	for (i = 0; i < priv->num_connectors; i++) {
-		struct drm_connector *connector = priv->connectors[i];
-		if (omap_connector_detect(connector, true) ==
-				connector_status_connected) {
-			connected_connectors |= (1 << i);
-		}
-	}
-
-	return connected_connectors;
-}
-
 static int omap_modeset_init(struct drm_device *dev)
 {
-	const struct omap_drm_platform_data *pdata = dev->dev->platform_data;
-	struct omap_kms_platform_data *kms_pdata = NULL;
 	struct omap_drm_private *priv = dev->dev_private;
 	struct omap_dss_device *dssdev = NULL;
-	int i, j;
-	unsigned int connected_connectors = 0;
+	int num_ovls = dss_feat_get_num_ovls();
+	int id;
 
 	drm_mode_config_init(dev);
 
-	if (pdata && pdata->kms_pdata) {
-		kms_pdata = pdata->kms_pdata;
+	omap_drm_irq_install(dev);
 
-		/* if platform data is provided by the board file, use it to
-		 * control which overlays, managers, and devices we own.
-		 */
-		for (i = 0; i < kms_pdata->mgr_cnt; i++) {
-			struct omap_overlay_manager *mgr =
-				omap_dss_get_overlay_manager(
-						kms_pdata->mgr_ids[i]);
-			create_encoder(dev, mgr);
-		}
+	/*
+	 * Create private planes and CRTCs for the last NUM_CRTCs overlay
+	 * plus manager:
+	 */
+	for (id = 0; id < min(num_crtc, num_ovls); id++) {
+		struct drm_plane *plane;
+		struct drm_crtc *crtc;
 
-		for (i = 0; i < kms_pdata->dev_cnt; i++) {
-			struct omap_dss_device *dssdev =
-				omap_dss_find_device(
-					(void *)kms_pdata->dev_names[i],
-					match_dev_name);
-			if (!dssdev) {
-				dev_warn(dev->dev, "no such dssdev: %s\n",
-						kms_pdata->dev_names[i]);
-				continue;
-			}
-			create_connector(dev, dssdev);
-		}
+		plane = omap_plane_init(dev, id, true);
+		crtc = omap_crtc_init(dev, plane, pipe2chan(id), id);
 
-		connected_connectors = detect_connectors(dev);
+		BUG_ON(priv->num_crtcs >= ARRAY_SIZE(priv->crtcs));
+		priv->crtcs[id] = crtc;
+		priv->num_crtcs++;
 
-		j = 0;
-		for (i = 0; i < kms_pdata->ovl_cnt; i++) {
-			struct omap_overlay *ovl =
-				omap_dss_get_overlay(kms_pdata->ovl_ids[i]);
-			create_crtc(dev, ovl, &j, connected_connectors);
-		}
-
-		for (i = 0; i < kms_pdata->pln_cnt; i++) {
-			struct omap_overlay *ovl =
-				omap_dss_get_overlay(kms_pdata->pln_ids[i]);
-			create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
-		}
-	} else {
-		/* otherwise just grab up to CONFIG_DRM_OMAP_NUM_CRTCS and try
-		 * to make educated guesses about everything else
-		 */
-		int max_overlays = min(omap_dss_get_num_overlays(), num_crtc);
-
-		for (i = 0; i < omap_dss_get_num_overlay_managers(); i++)
-			create_encoder(dev, omap_dss_get_overlay_manager(i));
-
-		for_each_dss_dev(dssdev) {
-			create_connector(dev, dssdev);
-		}
-
-		connected_connectors = detect_connectors(dev);
-
-		j = 0;
-		for (i = 0; i < max_overlays; i++) {
-			create_crtc(dev, omap_dss_get_overlay(i),
-					&j, connected_connectors);
-		}
-
-		/* use any remaining overlays as drm planes */
-		for (; i < omap_dss_get_num_overlays(); i++) {
-			struct omap_overlay *ovl = omap_dss_get_overlay(i);
-			create_plane(dev, ovl, (1 << priv->num_crtcs) - 1);
-		}
+		priv->planes[id] = plane;
+		priv->num_planes++;
 	}
 
-	/* for now keep the mapping of CRTCs and encoders static.. */
-	for (i = 0; i < priv->num_encoders; i++) {
-		struct drm_encoder *encoder = priv->encoders[i];
-		struct omap_overlay_manager *mgr =
-				omap_encoder_get_manager(encoder);
+	/*
+	 * Create normal planes for the remaining overlays:
+	 */
+	for (; id < num_ovls; id++) {
+		struct drm_plane *plane = omap_plane_init(dev, id, false);
 
-		encoder->possible_crtcs = (1 << priv->num_crtcs) - 1;
-
-		DBG("%s: possible_crtcs=%08x", mgr->name,
-					encoder->possible_crtcs);
+		BUG_ON(priv->num_planes >= ARRAY_SIZE(priv->planes));
+		priv->planes[priv->num_planes++] = plane;
 	}
 
-	dump_video_chains();
+	for_each_dss_dev(dssdev) {
+		struct drm_connector *connector;
+		struct drm_encoder *encoder;
+
+		if (!dssdev->driver) {
+			dev_warn(dev->dev, "%s has no driver.. skipping it\n",
+					dssdev->name);
+			return 0;
+		}
+
+		if (!(dssdev->driver->get_timings ||
+					dssdev->driver->read_edid)) {
+			dev_warn(dev->dev, "%s driver does not support "
+				"get_timings or read_edid.. skipping it!\n",
+				dssdev->name);
+			return 0;
+		}
+
+		encoder = omap_encoder_init(dev, dssdev);
+
+		if (!encoder) {
+			dev_err(dev->dev, "could not create encoder: %s\n",
+					dssdev->name);
+			return -ENOMEM;
+		}
+
+		connector = omap_connector_init(dev,
+				get_connector_type(dssdev), dssdev, encoder);
+
+		if (!connector) {
+			dev_err(dev->dev, "could not create connector: %s\n",
+					dssdev->name);
+			return -ENOMEM;
+		}
+
+		BUG_ON(priv->num_encoders >= ARRAY_SIZE(priv->encoders));
+		BUG_ON(priv->num_connectors >= ARRAY_SIZE(priv->connectors));
+
+		priv->encoders[priv->num_encoders++] = encoder;
+		priv->connectors[priv->num_connectors++] = connector;
+
+		drm_mode_connector_attach_encoder(connector, encoder);
+
+		/* figure out which crtc's we can connect the encoder to: */
+		encoder->possible_crtcs = 0;
+		for (id = 0; id < priv->num_crtcs; id++) {
+			enum omap_dss_output_id supported_outputs =
+					dss_feat_get_supported_outputs(pipe2chan(id));
+			if (supported_outputs & dssdev->output->id)
+				encoder->possible_crtcs |= (1 << id);
+		}
+	}
 
 	dev->mode_config.min_width = 32;
 	dev->mode_config.min_height = 32;
@@ -450,7 +229,7 @@
 		struct drm_file *file_priv)
 {
 	struct drm_omap_gem_new *args = data;
-	DBG("%p:%p: size=0x%08x, flags=%08x", dev, file_priv,
+	VERB("%p:%p: size=0x%08x, flags=%08x", dev, file_priv,
 			args->size.bytes, args->flags);
 	return omap_gem_new_handle(dev, file_priv, args->size,
 			args->flags, &args->handle);
@@ -510,7 +289,7 @@
 	struct drm_gem_object *obj;
 	int ret = 0;
 
-	DBG("%p:%p: handle=%d", dev, file_priv, args->handle);
+	VERB("%p:%p: handle=%d", dev, file_priv, args->handle);
 
 	obj = drm_gem_object_lookup(dev, file_priv, args->handle);
 	if (!obj)
@@ -565,14 +344,6 @@
 
 	dev->dev_private = priv;
 
-	ret = omapdss_compat_init();
-	if (ret) {
-		dev_err(dev->dev, "coult not init omapdss\n");
-		dev->dev_private = NULL;
-		kfree(priv);
-		return ret;
-	}
-
 	priv->wq = alloc_ordered_workqueue("omapdrm", 0);
 
 	INIT_LIST_HEAD(&priv->obj_list);
@@ -584,10 +355,13 @@
 		dev_err(dev->dev, "omap_modeset_init failed: ret=%d\n", ret);
 		dev->dev_private = NULL;
 		kfree(priv);
-		omapdss_compat_uninit();
 		return ret;
 	}
 
+	ret = drm_vblank_init(dev, priv->num_crtcs);
+	if (ret)
+		dev_warn(dev->dev, "could not init vblank\n");
+
 	priv->fbdev = omap_fbdev_init(dev);
 	if (!priv->fbdev) {
 		dev_warn(dev->dev, "omap_fbdev_init failed\n");
@@ -596,10 +370,6 @@
 
 	drm_kms_helper_poll_init(dev);
 
-	ret = drm_vblank_init(dev, priv->num_crtcs);
-	if (ret)
-		dev_warn(dev->dev, "could not init vblank\n");
-
 	return 0;
 }
 
@@ -609,8 +379,9 @@
 
 	DBG("unload: dev=%p", dev);
 
-	drm_vblank_cleanup(dev);
 	drm_kms_helper_poll_fini(dev);
+	drm_vblank_cleanup(dev);
+	omap_drm_irq_uninstall(dev);
 
 	omap_fbdev_free(dev);
 	omap_modeset_free(dev);
@@ -619,8 +390,6 @@
 	flush_workqueue(priv->wq);
 	destroy_workqueue(priv->wq);
 
-	omapdss_compat_uninit();
-
 	kfree(dev->dev_private);
 	dev->dev_private = NULL;
 
@@ -680,7 +449,9 @@
 		}
 	}
 
+	mutex_lock(&dev->mode_config.mutex);
 	ret = drm_fb_helper_restore_fbdev_mode(priv->fbdev);
+	mutex_unlock(&dev->mode_config.mutex);
 	if (ret)
 		DBG("failed to restore crtc mode");
 }
@@ -695,60 +466,6 @@
 	DBG("postclose: dev=%p, file=%p", dev, file);
 }
 
-/**
- * enable_vblank - enable vblank interrupt events
- * @dev: DRM device
- * @crtc: which irq to enable
- *
- * Enable vblank interrupts for @crtc.  If the device doesn't have
- * a hardware vblank counter, this routine should be a no-op, since
- * interrupts will have to stay on to keep the count accurate.
- *
- * RETURNS
- * Zero on success, appropriate errno if the given @crtc's vblank
- * interrupt cannot be enabled.
- */
-static int dev_enable_vblank(struct drm_device *dev, int crtc)
-{
-	DBG("enable_vblank: dev=%p, crtc=%d", dev, crtc);
-	return 0;
-}
-
-/**
- * disable_vblank - disable vblank interrupt events
- * @dev: DRM device
- * @crtc: which irq to enable
- *
- * Disable vblank interrupts for @crtc.  If the device doesn't have
- * a hardware vblank counter, this routine should be a no-op, since
- * interrupts will have to stay on to keep the count accurate.
- */
-static void dev_disable_vblank(struct drm_device *dev, int crtc)
-{
-	DBG("disable_vblank: dev=%p, crtc=%d", dev, crtc);
-}
-
-static irqreturn_t dev_irq_handler(DRM_IRQ_ARGS)
-{
-	return IRQ_HANDLED;
-}
-
-static void dev_irq_preinstall(struct drm_device *dev)
-{
-	DBG("irq_preinstall: dev=%p", dev);
-}
-
-static int dev_irq_postinstall(struct drm_device *dev)
-{
-	DBG("irq_postinstall: dev=%p", dev);
-	return 0;
-}
-
-static void dev_irq_uninstall(struct drm_device *dev)
-{
-	DBG("irq_uninstall: dev=%p", dev);
-}
-
 static const struct vm_operations_struct omap_gem_vm_ops = {
 	.fault = omap_gem_fault,
 	.open = drm_gem_vm_open,
@@ -778,12 +495,12 @@
 		.preclose = dev_preclose,
 		.postclose = dev_postclose,
 		.get_vblank_counter = drm_vblank_count,
-		.enable_vblank = dev_enable_vblank,
-		.disable_vblank = dev_disable_vblank,
-		.irq_preinstall = dev_irq_preinstall,
-		.irq_postinstall = dev_irq_postinstall,
-		.irq_uninstall = dev_irq_uninstall,
-		.irq_handler = dev_irq_handler,
+		.enable_vblank = omap_irq_enable_vblank,
+		.disable_vblank = omap_irq_disable_vblank,
+		.irq_preinstall = omap_irq_preinstall,
+		.irq_postinstall = omap_irq_postinstall,
+		.irq_uninstall = omap_irq_uninstall,
+		.irq_handler = omap_irq_handler,
 #ifdef CONFIG_DEBUG_FS
 		.debugfs_init = omap_debugfs_init,
 		.debugfs_cleanup = omap_debugfs_cleanup,
diff --git a/drivers/staging/omapdrm/omap_drv.h b/drivers/staging/omapdrm/omap_drv.h
index 1d4aea5..cd1f22b 100644
--- a/drivers/staging/omapdrm/omap_drv.h
+++ b/drivers/staging/omapdrm/omap_drv.h
@@ -28,6 +28,7 @@
 #include <linux/platform_data/omap_drm.h>
 #include "omap_drm.h"
 
+
 #define DBG(fmt, ...) DRM_DEBUG(fmt"\n", ##__VA_ARGS__)
 #define VERB(fmt, ...) if (0) DRM_DEBUG(fmt, ##__VA_ARGS__) /* verbose debug */
 
@@ -39,6 +40,51 @@
  */
 #define MAX_MAPPERS 2
 
+/* parameters which describe (unrotated) coordinates of scanout within a fb: */
+struct omap_drm_window {
+	uint32_t rotation;
+	int32_t  crtc_x, crtc_y;		/* signed because can be offscreen */
+	uint32_t crtc_w, crtc_h;
+	uint32_t src_x, src_y;
+	uint32_t src_w, src_h;
+};
+
+/* Once GO bit is set, we can't make further updates to shadowed registers
+ * until the GO bit is cleared.  So various parts in the kms code that need
+ * to update shadowed registers queue up a pair of callbacks, pre_apply
+ * which is called before setting GO bit, and post_apply that is called
+ * after GO bit is cleared.  The crtc manages the queuing, and everyone
+ * else goes thru omap_crtc_apply() using these callbacks so that the
+ * code which has to deal w/ GO bit state is centralized.
+ */
+struct omap_drm_apply {
+	struct list_head pending_node, queued_node;
+	bool queued;
+	void (*pre_apply)(struct omap_drm_apply *apply);
+	void (*post_apply)(struct omap_drm_apply *apply);
+};
+
+/* For transiently registering for different DSS irqs that various parts
+ * of the KMS code need during setup/configuration.  We these are not
+ * necessarily the same as what drm_vblank_get/put() are requesting, and
+ * the hysteresis in drm_vblank_put() is not necessarily desirable for
+ * internal housekeeping related irq usage.
+ */
+struct omap_drm_irq {
+	struct list_head node;
+	uint32_t irqmask;
+	bool registered;
+	void (*irq)(struct omap_drm_irq *irq, uint32_t irqstatus);
+};
+
+/* For KMS code that needs to wait for a certain # of IRQs:
+ */
+struct omap_irq_wait;
+struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
+		uint32_t irqmask, int count);
+int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
+		unsigned long timeout);
+
 struct omap_drm_private {
 	uint32_t omaprev;
 
@@ -58,6 +104,7 @@
 
 	struct workqueue_struct *wq;
 
+	/* list of GEM objects: */
 	struct list_head obj_list;
 
 	bool has_dmm;
@@ -65,6 +112,11 @@
 	/* properties: */
 	struct drm_property *rotation_prop;
 	struct drm_property *zorder_prop;
+
+	/* irq handling: */
+	struct list_head irq_list;    /* list of omap_drm_irq */
+	uint32_t vblank_mask;         /* irq bits set for userspace vblank */
+	struct omap_drm_irq error_handler;
 };
 
 /* this should probably be in drm-core to standardize amongst drivers */
@@ -75,15 +127,6 @@
 #define DRM_REFLECT_X	4
 #define DRM_REFLECT_Y	5
 
-/* parameters which describe (unrotated) coordinates of scanout within a fb: */
-struct omap_drm_window {
-	uint32_t rotation;
-	int32_t  crtc_x, crtc_y;		/* signed because can be offscreen */
-	uint32_t crtc_w, crtc_h;
-	uint32_t src_x, src_y;
-	uint32_t src_w, src_h;
-};
-
 #ifdef CONFIG_DEBUG_FS
 int omap_debugfs_init(struct drm_minor *minor);
 void omap_debugfs_cleanup(struct drm_minor *minor);
@@ -92,23 +135,36 @@
 void omap_gem_describe_objects(struct list_head *list, struct seq_file *m);
 #endif
 
+int omap_irq_enable_vblank(struct drm_device *dev, int crtc);
+void omap_irq_disable_vblank(struct drm_device *dev, int crtc);
+irqreturn_t omap_irq_handler(DRM_IRQ_ARGS);
+void omap_irq_preinstall(struct drm_device *dev);
+int omap_irq_postinstall(struct drm_device *dev);
+void omap_irq_uninstall(struct drm_device *dev);
+void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq);
+void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq);
+int omap_drm_irq_uninstall(struct drm_device *dev);
+int omap_drm_irq_install(struct drm_device *dev);
+
 struct drm_fb_helper *omap_fbdev_init(struct drm_device *dev);
 void omap_fbdev_free(struct drm_device *dev);
 
+const struct omap_video_timings *omap_crtc_timings(struct drm_crtc *crtc);
+enum omap_channel omap_crtc_channel(struct drm_crtc *crtc);
+int omap_crtc_apply(struct drm_crtc *crtc,
+		struct omap_drm_apply *apply);
 struct drm_crtc *omap_crtc_init(struct drm_device *dev,
-		struct omap_overlay *ovl, int id);
+		struct drm_plane *plane, enum omap_channel channel, int id);
 
 struct drm_plane *omap_plane_init(struct drm_device *dev,
-		struct omap_overlay *ovl, unsigned int possible_crtcs,
-		bool priv);
+		int plane_id, bool private_plane);
 int omap_plane_dpms(struct drm_plane *plane, int mode);
 int omap_plane_mode_set(struct drm_plane *plane,
 		struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		int crtc_x, int crtc_y,
 		unsigned int crtc_w, unsigned int crtc_h,
 		uint32_t src_x, uint32_t src_y,
-		uint32_t src_w, uint32_t src_h);
-void omap_plane_on_endwin(struct drm_plane *plane,
+		uint32_t src_w, uint32_t src_h,
 		void (*fxn)(void *), void *arg);
 void omap_plane_install_properties(struct drm_plane *plane,
 		struct drm_mode_object *obj);
@@ -116,21 +172,25 @@
 		struct drm_property *property, uint64_t val);
 
 struct drm_encoder *omap_encoder_init(struct drm_device *dev,
-		struct omap_overlay_manager *mgr);
-struct omap_overlay_manager *omap_encoder_get_manager(
+		struct omap_dss_device *dssdev);
+int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled);
+int omap_encoder_update(struct drm_encoder *encoder,
+		struct omap_overlay_manager *mgr,
+		struct omap_video_timings *timings);
+
+struct drm_connector *omap_connector_init(struct drm_device *dev,
+		int connector_type, struct omap_dss_device *dssdev,
 		struct drm_encoder *encoder);
 struct drm_encoder *omap_connector_attached_encoder(
 		struct drm_connector *connector);
-enum drm_connector_status omap_connector_detect(
-		struct drm_connector *connector, bool force);
-
-struct drm_connector *omap_connector_init(struct drm_device *dev,
-		int connector_type, struct omap_dss_device *dssdev);
-void omap_connector_mode_set(struct drm_connector *connector,
-		struct drm_display_mode *mode);
 void omap_connector_flush(struct drm_connector *connector,
 		int x, int y, int w, int h);
 
+void copy_timings_omap_to_drm(struct drm_display_mode *mode,
+		struct omap_video_timings *timings);
+void copy_timings_drm_to_omap(struct omap_video_timings *timings,
+		struct drm_display_mode *mode);
+
 uint32_t omap_framebuffer_get_formats(uint32_t *pixel_formats,
 		uint32_t max_formats, enum omap_color_mode supported_modes);
 struct drm_framebuffer *omap_framebuffer_create(struct drm_device *dev,
@@ -207,6 +267,40 @@
 	return ALIGN(pitch, 8 * bytespp);
 }
 
+static inline enum omap_channel pipe2chan(int pipe)
+{
+	int num_mgrs = dss_feat_get_num_mgrs();
+
+	/*
+	 * We usually don't want to create a CRTC for each manager,
+	 * at least not until we have a way to expose private planes
+	 * to userspace.  Otherwise there would not be enough video
+	 * pipes left for drm planes.  The higher #'d managers tend
+	 * to have more features so start in reverse order.
+	 */
+	return num_mgrs - pipe - 1;
+}
+
+/* map crtc to vblank mask */
+static inline uint32_t pipe2vbl(int crtc)
+{
+	enum omap_channel channel = pipe2chan(crtc);
+	return dispc_mgr_get_vsync_irq(channel);
+}
+
+static inline int crtc2pipe(struct drm_device *dev, struct drm_crtc *crtc)
+{
+	struct omap_drm_private *priv = dev->dev_private;
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(priv->crtcs); i++)
+		if (priv->crtcs[i] == crtc)
+			return i;
+
+	BUG();  /* bogus CRTC ptr */
+	return -1;
+}
+
 /* should these be made into common util helpers?
  */
 
diff --git a/drivers/staging/omapdrm/omap_encoder.c b/drivers/staging/omapdrm/omap_encoder.c
index 5341d5e..e053160 100644
--- a/drivers/staging/omapdrm/omap_encoder.c
+++ b/drivers/staging/omapdrm/omap_encoder.c
@@ -22,37 +22,56 @@
 #include "drm_crtc.h"
 #include "drm_crtc_helper.h"
 
+#include <linux/list.h>
+
+
 /*
  * encoder funcs
  */
 
 #define to_omap_encoder(x) container_of(x, struct omap_encoder, base)
 
+/* The encoder and connector both map to same dssdev.. the encoder
+ * handles the 'active' parts, ie. anything the modifies the state
+ * of the hw, and the connector handles the 'read-only' parts, like
+ * detecting connection and reading edid.
+ */
 struct omap_encoder {
 	struct drm_encoder base;
-	struct omap_overlay_manager *mgr;
+	struct omap_dss_device *dssdev;
 };
 
 static void omap_encoder_destroy(struct drm_encoder *encoder)
 {
 	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-	DBG("%s", omap_encoder->mgr->name);
 	drm_encoder_cleanup(encoder);
 	kfree(omap_encoder);
 }
 
+static const struct drm_encoder_funcs omap_encoder_funcs = {
+	.destroy = omap_encoder_destroy,
+};
+
+/*
+ * The CRTC drm_crtc_helper_set_mode() doesn't really give us the right
+ * order.. the easiest way to work around this for now is to make all
+ * the encoder-helper's no-op's and have the omap_crtc code take care
+ * of the sequencing and call us in the right points.
+ *
+ * Eventually to handle connecting CRTCs to different encoders properly,
+ * either the CRTC helpers need to change or we need to replace
+ * drm_crtc_helper_set_mode(), but lets wait until atomic-modeset for
+ * that.
+ */
+
 static void omap_encoder_dpms(struct drm_encoder *encoder, int mode)
 {
-	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-	DBG("%s: %d", omap_encoder->mgr->name, mode);
 }
 
 static bool omap_encoder_mode_fixup(struct drm_encoder *encoder,
 				  const struct drm_display_mode *mode,
 				  struct drm_display_mode *adjusted_mode)
 {
-	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-	DBG("%s", omap_encoder->mgr->name);
 	return true;
 }
 
@@ -60,47 +79,16 @@
 				struct drm_display_mode *mode,
 				struct drm_display_mode *adjusted_mode)
 {
-	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-	struct drm_device *dev = encoder->dev;
-	struct omap_drm_private *priv = dev->dev_private;
-	int i;
-
-	mode = adjusted_mode;
-
-	DBG("%s: set mode: %dx%d", omap_encoder->mgr->name,
-			mode->hdisplay, mode->vdisplay);
-
-	for (i = 0; i < priv->num_connectors; i++) {
-		struct drm_connector *connector = priv->connectors[i];
-		if (connector->encoder == encoder)
-			omap_connector_mode_set(connector, mode);
-
-	}
 }
 
 static void omap_encoder_prepare(struct drm_encoder *encoder)
 {
-	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-	struct drm_encoder_helper_funcs *encoder_funcs =
-				encoder->helper_private;
-	DBG("%s", omap_encoder->mgr->name);
-	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_OFF);
 }
 
 static void omap_encoder_commit(struct drm_encoder *encoder)
 {
-	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-	struct drm_encoder_helper_funcs *encoder_funcs =
-				encoder->helper_private;
-	DBG("%s", omap_encoder->mgr->name);
-	omap_encoder->mgr->apply(omap_encoder->mgr);
-	encoder_funcs->dpms(encoder, DRM_MODE_DPMS_ON);
 }
 
-static const struct drm_encoder_funcs omap_encoder_funcs = {
-	.destroy = omap_encoder_destroy,
-};
-
 static const struct drm_encoder_helper_funcs omap_encoder_helper_funcs = {
 	.dpms = omap_encoder_dpms,
 	.mode_fixup = omap_encoder_mode_fixup,
@@ -109,23 +97,54 @@
 	.commit = omap_encoder_commit,
 };
 
-struct omap_overlay_manager *omap_encoder_get_manager(
-		struct drm_encoder *encoder)
+/*
+ * Instead of relying on the helpers for modeset, the omap_crtc code
+ * calls these functions in the proper sequence.
+ */
+
+int omap_encoder_set_enabled(struct drm_encoder *encoder, bool enabled)
 {
 	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
-	return omap_encoder->mgr;
+	struct omap_dss_device *dssdev = omap_encoder->dssdev;
+	struct omap_dss_driver *dssdrv = dssdev->driver;
+
+	if (enabled) {
+		return dssdrv->enable(dssdev);
+	} else {
+		dssdrv->disable(dssdev);
+		return 0;
+	}
+}
+
+int omap_encoder_update(struct drm_encoder *encoder,
+		struct omap_overlay_manager *mgr,
+		struct omap_video_timings *timings)
+{
+	struct drm_device *dev = encoder->dev;
+	struct omap_encoder *omap_encoder = to_omap_encoder(encoder);
+	struct omap_dss_device *dssdev = omap_encoder->dssdev;
+	struct omap_dss_driver *dssdrv = dssdev->driver;
+	int ret;
+
+	dssdev->output->manager = mgr;
+
+	ret = dssdrv->check_timings(dssdev, timings);
+	if (ret) {
+		dev_err(dev->dev, "could not set timings: %d\n", ret);
+		return ret;
+	}
+
+	dssdrv->set_timings(dssdev, timings);
+
+	return 0;
 }
 
 /* initialize encoder */
 struct drm_encoder *omap_encoder_init(struct drm_device *dev,
-		struct omap_overlay_manager *mgr)
+		struct omap_dss_device *dssdev)
 {
 	struct drm_encoder *encoder = NULL;
 	struct omap_encoder *omap_encoder;
-	struct omap_overlay_manager_info info;
-	int ret;
-
-	DBG("%s", mgr->name);
 
 	omap_encoder = kzalloc(sizeof(*omap_encoder), GFP_KERNEL);
 	if (!omap_encoder) {
@@ -133,33 +152,14 @@
 		goto fail;
 	}
 
-	omap_encoder->mgr = mgr;
+	omap_encoder->dssdev = dssdev;
+
 	encoder = &omap_encoder->base;
 
 	drm_encoder_init(dev, encoder, &omap_encoder_funcs,
 			 DRM_MODE_ENCODER_TMDS);
 	drm_encoder_helper_add(encoder, &omap_encoder_helper_funcs);
 
-	mgr->get_manager_info(mgr, &info);
-
-	/* TODO: fix hard-coded setup.. */
-	info.default_color = 0x00000000;
-	info.trans_key = 0x00000000;
-	info.trans_key_type = OMAP_DSS_COLOR_KEY_GFX_DST;
-	info.trans_enabled = false;
-
-	ret = mgr->set_manager_info(mgr, &info);
-	if (ret) {
-		dev_err(dev->dev, "could not set manager info\n");
-		goto fail;
-	}
-
-	ret = mgr->apply(mgr);
-	if (ret) {
-		dev_err(dev->dev, "could not apply\n");
-		goto fail;
-	}
-
 	return encoder;
 
 fail:
diff --git a/drivers/staging/omapdrm/omap_gem_dmabuf.c b/drivers/staging/omapdrm/omap_gem_dmabuf.c
index ea38400..b6c5b5c 100644
--- a/drivers/staging/omapdrm/omap_gem_dmabuf.c
+++ b/drivers/staging/omapdrm/omap_gem_dmabuf.c
@@ -194,7 +194,7 @@
 struct dma_buf *omap_gem_prime_export(struct drm_device *dev,
 		struct drm_gem_object *obj, int flags)
 {
-	return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, 0600);
+	return dma_buf_export(obj, &omap_dmabuf_ops, obj->size, flags);
 }
 
 struct drm_gem_object *omap_gem_prime_import(struct drm_device *dev,
diff --git a/drivers/staging/omapdrm/omap_irq.c b/drivers/staging/omapdrm/omap_irq.c
new file mode 100644
index 0000000..2629ba7
--- /dev/null
+++ b/drivers/staging/omapdrm/omap_irq.c
@@ -0,0 +1,322 @@
+/*
+ * drivers/staging/omapdrm/omap_irq.c
+ *
+ * Copyright (C) 2012 Texas Instruments
+ * Author: Rob Clark <rob.clark@linaro.org>
+ *
+ * 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.
+ *
+ * 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "omap_drv.h"
+
+static DEFINE_SPINLOCK(list_lock);
+
+static void omap_irq_error_handler(struct omap_drm_irq *irq,
+		uint32_t irqstatus)
+{
+	DRM_ERROR("errors: %08x\n", irqstatus);
+}
+
+/* call with list_lock and dispc runtime held */
+static void omap_irq_update(struct drm_device *dev)
+{
+	struct omap_drm_private *priv = dev->dev_private;
+	struct omap_drm_irq *irq;
+	uint32_t irqmask = priv->vblank_mask;
+
+	BUG_ON(!spin_is_locked(&list_lock));
+
+	list_for_each_entry(irq, &priv->irq_list, node)
+		irqmask |= irq->irqmask;
+
+	DBG("irqmask=%08x", irqmask);
+
+	dispc_write_irqenable(irqmask);
+	dispc_read_irqenable();        /* flush posted write */
+}
+
+void omap_irq_register(struct drm_device *dev, struct omap_drm_irq *irq)
+{
+	struct omap_drm_private *priv = dev->dev_private;
+	unsigned long flags;
+
+	dispc_runtime_get();
+	spin_lock_irqsave(&list_lock, flags);
+
+	if (!WARN_ON(irq->registered)) {
+		irq->registered = true;
+		list_add(&irq->node, &priv->irq_list);
+		omap_irq_update(dev);
+	}
+
+	spin_unlock_irqrestore(&list_lock, flags);
+	dispc_runtime_put();
+}
+
+void omap_irq_unregister(struct drm_device *dev, struct omap_drm_irq *irq)
+{
+	unsigned long flags;
+
+	dispc_runtime_get();
+	spin_lock_irqsave(&list_lock, flags);
+
+	if (!WARN_ON(!irq->registered)) {
+		irq->registered = false;
+		list_del(&irq->node);
+		omap_irq_update(dev);
+	}
+
+	spin_unlock_irqrestore(&list_lock, flags);
+	dispc_runtime_put();
+}
+
+struct omap_irq_wait {
+	struct omap_drm_irq irq;
+	int count;
+};
+
+static DECLARE_WAIT_QUEUE_HEAD(wait_event);
+
+static void wait_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+{
+	struct omap_irq_wait *wait =
+			container_of(irq, struct omap_irq_wait, irq);
+	wait->count--;
+	wake_up_all(&wait_event);
+}
+
+struct omap_irq_wait * omap_irq_wait_init(struct drm_device *dev,
+		uint32_t irqmask, int count)
+{
+	struct omap_irq_wait *wait = kzalloc(sizeof(*wait), GFP_KERNEL);
+	wait->irq.irq = wait_irq;
+	wait->irq.irqmask = irqmask;
+	wait->count = count;
+	omap_irq_register(dev, &wait->irq);
+	return wait;
+}
+
+int omap_irq_wait(struct drm_device *dev, struct omap_irq_wait *wait,
+		unsigned long timeout)
+{
+	int ret = wait_event_timeout(wait_event, (wait->count <= 0), timeout);
+	omap_irq_unregister(dev, &wait->irq);
+	kfree(wait);
+	if (ret == 0)
+		return -1;
+	return 0;
+}
+
+/**
+ * enable_vblank - enable vblank interrupt events
+ * @dev: DRM device
+ * @crtc: which irq to enable
+ *
+ * Enable vblank interrupts for @crtc.  If the device doesn't have
+ * a hardware vblank counter, this routine should be a no-op, since
+ * interrupts will have to stay on to keep the count accurate.
+ *
+ * RETURNS
+ * Zero on success, appropriate errno if the given @crtc's vblank
+ * interrupt cannot be enabled.
+ */
+int omap_irq_enable_vblank(struct drm_device *dev, int crtc)
+{
+	struct omap_drm_private *priv = dev->dev_private;
+	unsigned long flags;
+
+	DBG("dev=%p, crtc=%d", dev, crtc);
+
+	dispc_runtime_get();
+	spin_lock_irqsave(&list_lock, flags);
+	priv->vblank_mask |= pipe2vbl(crtc);
+	omap_irq_update(dev);
+	spin_unlock_irqrestore(&list_lock, flags);
+	dispc_runtime_put();
+
+	return 0;
+}
+
+/**
+ * disable_vblank - disable vblank interrupt events
+ * @dev: DRM device
+ * @crtc: which irq to enable
+ *
+ * Disable vblank interrupts for @crtc.  If the device doesn't have
+ * a hardware vblank counter, this routine should be a no-op, since
+ * interrupts will have to stay on to keep the count accurate.
+ */
+void omap_irq_disable_vblank(struct drm_device *dev, int crtc)
+{
+	struct omap_drm_private *priv = dev->dev_private;
+	unsigned long flags;
+
+	DBG("dev=%p, crtc=%d", dev, crtc);
+
+	dispc_runtime_get();
+	spin_lock_irqsave(&list_lock, flags);
+	priv->vblank_mask &= ~pipe2vbl(crtc);
+	omap_irq_update(dev);
+	spin_unlock_irqrestore(&list_lock, flags);
+	dispc_runtime_put();
+}
+
+irqreturn_t omap_irq_handler(DRM_IRQ_ARGS)
+{
+	struct drm_device *dev = (struct drm_device *) arg;
+	struct omap_drm_private *priv = dev->dev_private;
+	struct omap_drm_irq *handler, *n;
+	unsigned long flags;
+	unsigned int id;
+	u32 irqstatus;
+
+	irqstatus = dispc_read_irqstatus();
+	dispc_clear_irqstatus(irqstatus);
+	dispc_read_irqstatus();        /* flush posted write */
+
+	VERB("irqs: %08x", irqstatus);
+
+	for (id = 0; id < priv->num_crtcs; id++)
+		if (irqstatus & pipe2vbl(id))
+			drm_handle_vblank(dev, id);
+
+	spin_lock_irqsave(&list_lock, flags);
+	list_for_each_entry_safe(handler, n, &priv->irq_list, node) {
+		if (handler->irqmask & irqstatus) {
+			spin_unlock_irqrestore(&list_lock, flags);
+			handler->irq(handler, handler->irqmask & irqstatus);
+			spin_lock_irqsave(&list_lock, flags);
+		}
+	}
+	spin_unlock_irqrestore(&list_lock, flags);
+
+	return IRQ_HANDLED;
+}
+
+void omap_irq_preinstall(struct drm_device *dev)
+{
+	DBG("dev=%p", dev);
+	dispc_runtime_get();
+	dispc_clear_irqstatus(0xffffffff);
+	dispc_runtime_put();
+}
+
+int omap_irq_postinstall(struct drm_device *dev)
+{
+	struct omap_drm_private *priv = dev->dev_private;
+	struct omap_drm_irq *error_handler = &priv->error_handler;
+
+	DBG("dev=%p", dev);
+
+	INIT_LIST_HEAD(&priv->irq_list);
+
+	error_handler->irq = omap_irq_error_handler;
+	error_handler->irqmask = DISPC_IRQ_OCP_ERR;
+
+	/* for now ignore DISPC_IRQ_SYNC_LOST_DIGIT.. really I think
+	 * we just need to ignore it while enabling tv-out
+	 */
+	error_handler->irqmask &= ~DISPC_IRQ_SYNC_LOST_DIGIT;
+
+	omap_irq_register(dev, error_handler);
+
+	return 0;
+}
+
+void omap_irq_uninstall(struct drm_device *dev)
+{
+	DBG("dev=%p", dev);
+	// TODO prolly need to call drm_irq_uninstall() somewhere too
+}
+
+/*
+ * We need a special version, instead of just using drm_irq_install(),
+ * because we need to register the irq via omapdss.  Once omapdss and
+ * omapdrm are merged together we can assign the dispc hwmod data to
+ * ourselves and drop these and just use drm_irq_{install,uninstall}()
+ */
+
+int omap_drm_irq_install(struct drm_device *dev)
+{
+	int ret;
+
+	mutex_lock(&dev->struct_mutex);
+
+	if (dev->irq_enabled) {
+		mutex_unlock(&dev->struct_mutex);
+		return -EBUSY;
+	}
+	dev->irq_enabled = 1;
+	mutex_unlock(&dev->struct_mutex);
+
+	/* Before installing handler */
+	if (dev->driver->irq_preinstall)
+		dev->driver->irq_preinstall(dev);
+
+	ret = dispc_request_irq(dev->driver->irq_handler, dev);
+
+	if (ret < 0) {
+		mutex_lock(&dev->struct_mutex);
+		dev->irq_enabled = 0;
+		mutex_unlock(&dev->struct_mutex);
+		return ret;
+	}
+
+	/* After installing handler */
+	if (dev->driver->irq_postinstall)
+		ret = dev->driver->irq_postinstall(dev);
+
+	if (ret < 0) {
+		mutex_lock(&dev->struct_mutex);
+		dev->irq_enabled = 0;
+		mutex_unlock(&dev->struct_mutex);
+		dispc_free_irq(dev);
+	}
+
+	return ret;
+}
+
+int omap_drm_irq_uninstall(struct drm_device *dev)
+{
+	unsigned long irqflags;
+	int irq_enabled, i;
+
+	mutex_lock(&dev->struct_mutex);
+	irq_enabled = dev->irq_enabled;
+	dev->irq_enabled = 0;
+	mutex_unlock(&dev->struct_mutex);
+
+	/*
+	 * Wake up any waiters so they don't hang.
+	 */
+	if (dev->num_crtcs) {
+		spin_lock_irqsave(&dev->vbl_lock, irqflags);
+		for (i = 0; i < dev->num_crtcs; i++) {
+			DRM_WAKEUP(&dev->vbl_queue[i]);
+			dev->vblank_enabled[i] = 0;
+			dev->last_vblank[i] =
+				dev->driver->get_vblank_counter(dev, i);
+		}
+		spin_unlock_irqrestore(&dev->vbl_lock, irqflags);
+	}
+
+	if (!irq_enabled)
+		return -EINVAL;
+
+	if (dev->driver->irq_uninstall)
+		dev->driver->irq_uninstall(dev);
+
+	dispc_free_irq(dev);
+
+	return 0;
+}
diff --git a/drivers/staging/omapdrm/omap_plane.c b/drivers/staging/omapdrm/omap_plane.c
index 2a8e5ba..bb989d7 100644
--- a/drivers/staging/omapdrm/omap_plane.c
+++ b/drivers/staging/omapdrm/omap_plane.c
@@ -41,12 +41,14 @@
 
 struct omap_plane {
 	struct drm_plane base;
-	struct omap_overlay *ovl;
+	int id;  /* TODO rename omap_plane -> omap_plane_id in omapdss so I can use the enum */
+	const char *name;
 	struct omap_overlay_info info;
+	struct omap_drm_apply apply;
 
 	/* position/orientation of scanout within the fb: */
 	struct omap_drm_window win;
-
+	bool enabled;
 
 	/* last fb that we pinned: */
 	struct drm_framebuffer *pinned_fb;
@@ -54,189 +56,15 @@
 	uint32_t nformats;
 	uint32_t formats[32];
 
-	/* for synchronizing access to unpins fifo */
-	struct mutex unpin_mutex;
+	struct omap_drm_irq error_irq;
 
-	/* set of bo's pending unpin until next END_WIN irq */
+	/* set of bo's pending unpin until next post_apply() */
 	DECLARE_KFIFO_PTR(unpin_fifo, struct drm_gem_object *);
-	int num_unpins, pending_num_unpins;
 
-	/* for deferred unpin when we need to wait for scanout complete irq */
-	struct work_struct work;
-
-	/* callback on next endwin irq */
-	struct callback endwin;
+	// XXX maybe get rid of this and handle vblank in crtc too?
+	struct callback apply_done_cb;
 };
 
-/* map from ovl->id to the irq we are interested in for scanout-done */
-static const uint32_t id2irq[] = {
-		[OMAP_DSS_GFX]    = DISPC_IRQ_GFX_END_WIN,
-		[OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_END_WIN,
-		[OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_END_WIN,
-		[OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_END_WIN,
-};
-
-static void dispc_isr(void *arg, uint32_t mask)
-{
-	struct drm_plane *plane = arg;
-	struct omap_plane *omap_plane = to_omap_plane(plane);
-	struct omap_drm_private *priv = plane->dev->dev_private;
-
-	omap_dispc_unregister_isr(dispc_isr, plane,
-			id2irq[omap_plane->ovl->id]);
-
-	queue_work(priv->wq, &omap_plane->work);
-}
-
-static void unpin_worker(struct work_struct *work)
-{
-	struct omap_plane *omap_plane =
-			container_of(work, struct omap_plane, work);
-	struct callback endwin;
-
-	mutex_lock(&omap_plane->unpin_mutex);
-	DBG("unpinning %d of %d", omap_plane->num_unpins,
-			omap_plane->num_unpins + omap_plane->pending_num_unpins);
-	while (omap_plane->num_unpins > 0) {
-		struct drm_gem_object *bo = NULL;
-		int ret = kfifo_get(&omap_plane->unpin_fifo, &bo);
-		WARN_ON(!ret);
-		omap_gem_put_paddr(bo);
-		drm_gem_object_unreference_unlocked(bo);
-		omap_plane->num_unpins--;
-	}
-	endwin = omap_plane->endwin;
-	omap_plane->endwin.fxn = NULL;
-	mutex_unlock(&omap_plane->unpin_mutex);
-
-	if (endwin.fxn)
-		endwin.fxn(endwin.arg);
-}
-
-static void install_irq(struct drm_plane *plane)
-{
-	struct omap_plane *omap_plane = to_omap_plane(plane);
-	struct omap_overlay *ovl = omap_plane->ovl;
-	int ret;
-
-	ret = omap_dispc_register_isr(dispc_isr, plane, id2irq[ovl->id]);
-
-	/*
-	 * omapdss has upper limit on # of registered irq handlers,
-	 * which we shouldn't hit.. but if we do the limit should
-	 * be raised or bad things happen:
-	 */
-	WARN_ON(ret == -EBUSY);
-}
-
-/* push changes down to dss2 */
-static int commit(struct drm_plane *plane)
-{
-	struct drm_device *dev = plane->dev;
-	struct omap_plane *omap_plane = to_omap_plane(plane);
-	struct omap_overlay *ovl = omap_plane->ovl;
-	struct omap_overlay_info *info = &omap_plane->info;
-	int ret;
-
-	DBG("%s", ovl->name);
-	DBG("%dx%d -> %dx%d (%d)", info->width, info->height, info->out_width,
-			info->out_height, info->screen_width);
-	DBG("%d,%d %08x %08x", info->pos_x, info->pos_y,
-			info->paddr, info->p_uv_addr);
-
-	/* NOTE: do we want to do this at all here, or just wait
-	 * for dpms(ON) since other CRTC's may not have their mode
-	 * set yet, so fb dimensions may still change..
-	 */
-	ret = ovl->set_overlay_info(ovl, info);
-	if (ret) {
-		dev_err(dev->dev, "could not set overlay info\n");
-		return ret;
-	}
-
-	mutex_lock(&omap_plane->unpin_mutex);
-	omap_plane->num_unpins += omap_plane->pending_num_unpins;
-	omap_plane->pending_num_unpins = 0;
-	mutex_unlock(&omap_plane->unpin_mutex);
-
-	/* our encoder doesn't necessarily get a commit() after this, in
-	 * particular in the dpms() and mode_set_base() cases, so force the
-	 * manager to update:
-	 *
-	 * could this be in the encoder somehow?
-	 */
-	if (ovl->manager) {
-		ret = ovl->manager->apply(ovl->manager);
-		if (ret) {
-			dev_err(dev->dev, "could not apply settings\n");
-			return ret;
-		}
-
-		/*
-		 * NOTE: really this should be atomic w/ mgr->apply() but
-		 * omapdss does not expose such an API
-		 */
-		if (omap_plane->num_unpins > 0)
-			install_irq(plane);
-
-	} else {
-		struct omap_drm_private *priv = dev->dev_private;
-		queue_work(priv->wq, &omap_plane->work);
-	}
-
-
-	if (ovl->is_enabled(ovl)) {
-		omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y,
-				info->out_width, info->out_height);
-	}
-
-	return 0;
-}
-
-/* when CRTC that we are attached to has potentially changed, this checks
- * if we are attached to proper manager, and if necessary updates.
- */
-static void update_manager(struct drm_plane *plane)
-{
-	struct omap_drm_private *priv = plane->dev->dev_private;
-	struct omap_plane *omap_plane = to_omap_plane(plane);
-	struct omap_overlay *ovl = omap_plane->ovl;
-	struct omap_overlay_manager *mgr = NULL;
-	int i;
-
-	if (plane->crtc) {
-		for (i = 0; i < priv->num_encoders; i++) {
-			struct drm_encoder *encoder = priv->encoders[i];
-			if (encoder->crtc == plane->crtc) {
-				mgr = omap_encoder_get_manager(encoder);
-				break;
-			}
-		}
-	}
-
-	if (ovl->manager != mgr) {
-		bool enabled = ovl->is_enabled(ovl);
-
-		/* don't switch things around with enabled overlays: */
-		if (enabled)
-			omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
-
-		if (ovl->manager) {
-			DBG("disconnecting %s from %s", ovl->name,
-					ovl->manager->name);
-			ovl->unset_manager(ovl);
-		}
-
-		if (mgr) {
-			DBG("connecting %s to %s", ovl->name, mgr->name);
-			ovl->set_manager(ovl, mgr);
-		}
-
-		if (enabled && mgr)
-			omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
-	}
-}
-
 static void unpin(void *arg, struct drm_gem_object *bo)
 {
 	struct drm_plane *plane = arg;
@@ -244,7 +72,6 @@
 
 	if (kfifo_put(&omap_plane->unpin_fifo,
 			(const struct drm_gem_object **)&bo)) {
-		omap_plane->pending_num_unpins++;
 		/* also hold a ref so it isn't free'd while pinned */
 		drm_gem_object_reference(bo);
 	} else {
@@ -264,13 +91,19 @@
 
 		DBG("%p -> %p", pinned_fb, fb);
 
-		mutex_lock(&omap_plane->unpin_mutex);
+		if (fb)
+			drm_framebuffer_reference(fb);
+
 		ret = omap_framebuffer_replace(pinned_fb, fb, plane, unpin);
-		mutex_unlock(&omap_plane->unpin_mutex);
+
+		if (pinned_fb)
+			drm_framebuffer_unreference(pinned_fb);
 
 		if (ret) {
 			dev_err(plane->dev->dev, "could not swap %p -> %p\n",
 					omap_plane->pinned_fb, fb);
+			if (fb)
+				drm_framebuffer_unreference(fb);
 			omap_plane->pinned_fb = NULL;
 			return ret;
 		}
@@ -281,31 +114,90 @@
 	return 0;
 }
 
-/* update parameters that are dependent on the framebuffer dimensions and
- * position within the fb that this plane scans out from. This is called
- * when framebuffer or x,y base may have changed.
- */
-static void update_scanout(struct drm_plane *plane)
+static void omap_plane_pre_apply(struct omap_drm_apply *apply)
 {
-	struct omap_plane *omap_plane = to_omap_plane(plane);
-	struct omap_overlay_info *info = &omap_plane->info;
+	struct omap_plane *omap_plane =
+			container_of(apply, struct omap_plane, apply);
 	struct omap_drm_window *win = &omap_plane->win;
+	struct drm_plane *plane = &omap_plane->base;
+	struct drm_device *dev = plane->dev;
+	struct omap_overlay_info *info = &omap_plane->info;
+	struct drm_crtc *crtc = plane->crtc;
+	enum omap_channel channel;
+	bool enabled = omap_plane->enabled && crtc;
+	bool ilace, replication;
 	int ret;
 
-	ret = update_pin(plane, plane->fb);
-	if (ret) {
-		dev_err(plane->dev->dev,
-			"could not pin fb: %d\n", ret);
-		omap_plane_dpms(plane, DRM_MODE_DPMS_OFF);
+	DBG("%s, enabled=%d", omap_plane->name, enabled);
+
+	/* if fb has changed, pin new fb: */
+	update_pin(plane, enabled ? plane->fb : NULL);
+
+	if (!enabled) {
+		dispc_ovl_enable(omap_plane->id, false);
 		return;
 	}
 
+	channel = omap_crtc_channel(crtc);
+
+	/* update scanout: */
 	omap_framebuffer_update_scanout(plane->fb, win, info);
 
-	DBG("%s: %d,%d: %08x %08x (%d)", omap_plane->ovl->name,
-			win->src_x, win->src_y,
-			(u32)info->paddr, (u32)info->p_uv_addr,
+	DBG("%dx%d -> %dx%d (%d)", info->width, info->height,
+			info->out_width, info->out_height,
 			info->screen_width);
+	DBG("%d,%d %08x %08x", info->pos_x, info->pos_y,
+			info->paddr, info->p_uv_addr);
+
+	/* TODO: */
+	ilace = false;
+	replication = false;
+
+	/* and finally, update omapdss: */
+	ret = dispc_ovl_setup(omap_plane->id, info,
+			replication, omap_crtc_timings(crtc), false);
+	if (ret) {
+		dev_err(dev->dev, "dispc_ovl_setup failed: %d\n", ret);
+		return;
+	}
+
+	dispc_ovl_enable(omap_plane->id, true);
+	dispc_ovl_set_channel_out(omap_plane->id, channel);
+}
+
+static void omap_plane_post_apply(struct omap_drm_apply *apply)
+{
+	struct omap_plane *omap_plane =
+			container_of(apply, struct omap_plane, apply);
+	struct drm_plane *plane = &omap_plane->base;
+	struct omap_overlay_info *info = &omap_plane->info;
+	struct drm_gem_object *bo = NULL;
+	struct callback cb;
+
+	cb = omap_plane->apply_done_cb;
+	omap_plane->apply_done_cb.fxn = NULL;
+
+	while (kfifo_get(&omap_plane->unpin_fifo, &bo)) {
+		omap_gem_put_paddr(bo);
+		drm_gem_object_unreference_unlocked(bo);
+	}
+
+	if (cb.fxn)
+		cb.fxn(cb.arg);
+
+	if (omap_plane->enabled) {
+		omap_framebuffer_flush(plane->fb, info->pos_x, info->pos_y,
+				info->out_width, info->out_height);
+	}
+}
+
+static int apply(struct drm_plane *plane)
+{
+	if (plane->crtc) {
+		struct omap_plane *omap_plane = to_omap_plane(plane);
+		return omap_crtc_apply(plane->crtc, &omap_plane->apply);
+	}
+	return 0;
 }
 
 int omap_plane_mode_set(struct drm_plane *plane,
@@ -313,7 +205,8 @@
 		int crtc_x, int crtc_y,
 		unsigned int crtc_w, unsigned int crtc_h,
 		uint32_t src_x, uint32_t src_y,
-		uint32_t src_w, uint32_t src_h)
+		uint32_t src_w, uint32_t src_h,
+		void (*fxn)(void *), void *arg)
 {
 	struct omap_plane *omap_plane = to_omap_plane(plane);
 	struct omap_drm_window *win = &omap_plane->win;
@@ -329,17 +222,20 @@
 	win->src_w = src_w >> 16;
 	win->src_h = src_h >> 16;
 
-	/* note: this is done after this fxn returns.. but if we need
-	 * to do a commit/update_scanout, etc before this returns we
-	 * need the current value.
-	 */
+	if (fxn) {
+		/* omap_crtc should ensure that a new page flip
+		 * isn't permitted while there is one pending:
+		 */
+		BUG_ON(omap_plane->apply_done_cb.fxn);
+
+		omap_plane->apply_done_cb.fxn = fxn;
+		omap_plane->apply_done_cb.arg = arg;
+	}
+
 	plane->fb = fb;
 	plane->crtc = crtc;
 
-	update_scanout(plane);
-	update_manager(plane);
-
-	return 0;
+	return apply(plane);
 }
 
 static int omap_plane_update(struct drm_plane *plane,
@@ -349,9 +245,12 @@
 		uint32_t src_x, uint32_t src_y,
 		uint32_t src_w, uint32_t src_h)
 {
-	omap_plane_mode_set(plane, crtc, fb, crtc_x, crtc_y, crtc_w, crtc_h,
-			src_x, src_y, src_w, src_h);
-	return omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
+	struct omap_plane *omap_plane = to_omap_plane(plane);
+	omap_plane->enabled = true;
+	return omap_plane_mode_set(plane, crtc, fb,
+			crtc_x, crtc_y, crtc_w, crtc_h,
+			src_x, src_y, src_w, src_h,
+			NULL, NULL);
 }
 
 static int omap_plane_disable(struct drm_plane *plane)
@@ -364,48 +263,32 @@
 static void omap_plane_destroy(struct drm_plane *plane)
 {
 	struct omap_plane *omap_plane = to_omap_plane(plane);
-	DBG("%s", omap_plane->ovl->name);
+
+	DBG("%s", omap_plane->name);
+
+	omap_irq_unregister(plane->dev, &omap_plane->error_irq);
+
 	omap_plane_disable(plane);
 	drm_plane_cleanup(plane);
-	WARN_ON(omap_plane->pending_num_unpins + omap_plane->num_unpins > 0);
+
+	WARN_ON(!kfifo_is_empty(&omap_plane->unpin_fifo));
 	kfifo_free(&omap_plane->unpin_fifo);
+
 	kfree(omap_plane);
 }
 
 int omap_plane_dpms(struct drm_plane *plane, int mode)
 {
 	struct omap_plane *omap_plane = to_omap_plane(plane);
-	struct omap_overlay *ovl = omap_plane->ovl;
-	int r;
+	bool enabled = (mode == DRM_MODE_DPMS_ON);
+	int ret = 0;
 
-	DBG("%s: %d", omap_plane->ovl->name, mode);
-
-	if (mode == DRM_MODE_DPMS_ON) {
-		update_scanout(plane);
-		r = commit(plane);
-		if (!r)
-			r = ovl->enable(ovl);
-	} else {
-		struct omap_drm_private *priv = plane->dev->dev_private;
-		r = ovl->disable(ovl);
-		update_pin(plane, NULL);
-		queue_work(priv->wq, &omap_plane->work);
+	if (enabled != omap_plane->enabled) {
+		omap_plane->enabled = enabled;
+		ret = apply(plane);
 	}
 
-	return r;
-}
-
-void omap_plane_on_endwin(struct drm_plane *plane,
-		void (*fxn)(void *), void *arg)
-{
-	struct omap_plane *omap_plane = to_omap_plane(plane);
-
-	mutex_lock(&omap_plane->unpin_mutex);
-	omap_plane->endwin.fxn = fxn;
-	omap_plane->endwin.arg = arg;
-	mutex_unlock(&omap_plane->unpin_mutex);
-
-	install_irq(plane);
+	return ret;
 }
 
 /* helper to install properties which are common to planes and crtcs */
@@ -454,25 +337,13 @@
 	int ret = -EINVAL;
 
 	if (property == priv->rotation_prop) {
-		struct omap_overlay *ovl = omap_plane->ovl;
-
-		DBG("%s: rotation: %02x", ovl->name, (uint32_t)val);
+		DBG("%s: rotation: %02x", omap_plane->name, (uint32_t)val);
 		omap_plane->win.rotation = val;
-
-		if (ovl->is_enabled(ovl))
-			ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
-		else
-			ret = 0;
+		ret = apply(plane);
 	} else if (property == priv->zorder_prop) {
-		struct omap_overlay *ovl = omap_plane->ovl;
-
-		DBG("%s: zorder: %d", ovl->name, (uint32_t)val);
+		DBG("%s: zorder: %02x", omap_plane->name, (uint32_t)val);
 		omap_plane->info.zorder = val;
-
-		if (ovl->is_enabled(ovl))
-			ret = omap_plane_dpms(plane, DRM_MODE_DPMS_ON);
-		else
-			ret = 0;
+		ret = apply(plane);
 	}
 
 	return ret;
@@ -485,20 +356,38 @@
 		.set_property = omap_plane_set_property,
 };
 
+static void omap_plane_error_irq(struct omap_drm_irq *irq, uint32_t irqstatus)
+{
+	struct omap_plane *omap_plane =
+			container_of(irq, struct omap_plane, error_irq);
+	DRM_ERROR("%s: errors: %08x\n", omap_plane->name, irqstatus);
+}
+
+static const char *plane_names[] = {
+		[OMAP_DSS_GFX] = "gfx",
+		[OMAP_DSS_VIDEO1] = "vid1",
+		[OMAP_DSS_VIDEO2] = "vid2",
+		[OMAP_DSS_VIDEO3] = "vid3",
+};
+
+static const uint32_t error_irqs[] = {
+		[OMAP_DSS_GFX] = DISPC_IRQ_GFX_FIFO_UNDERFLOW,
+		[OMAP_DSS_VIDEO1] = DISPC_IRQ_VID1_FIFO_UNDERFLOW,
+		[OMAP_DSS_VIDEO2] = DISPC_IRQ_VID2_FIFO_UNDERFLOW,
+		[OMAP_DSS_VIDEO3] = DISPC_IRQ_VID3_FIFO_UNDERFLOW,
+};
+
 /* initialize plane */
 struct drm_plane *omap_plane_init(struct drm_device *dev,
-		struct omap_overlay *ovl, unsigned int possible_crtcs,
-		bool priv)
+		int id, bool private_plane)
 {
+	struct omap_drm_private *priv = dev->dev_private;
 	struct drm_plane *plane = NULL;
 	struct omap_plane *omap_plane;
+	struct omap_overlay_info *info;
 	int ret;
 
-	DBG("%s: possible_crtcs=%08x, priv=%d", ovl->name,
-			possible_crtcs, priv);
-
-	/* friendly reminder to update table for future hw: */
-	WARN_ON(ovl->id >= ARRAY_SIZE(id2irq));
+	DBG("%s: priv=%d", plane_names[id], private_plane);
 
 	omap_plane = kzalloc(sizeof(*omap_plane), GFP_KERNEL);
 	if (!omap_plane) {
@@ -506,47 +395,50 @@
 		goto fail;
 	}
 
-	mutex_init(&omap_plane->unpin_mutex);
-
 	ret = kfifo_alloc(&omap_plane->unpin_fifo, 16, GFP_KERNEL);
 	if (ret) {
 		dev_err(dev->dev, "could not allocate unpin FIFO\n");
 		goto fail;
 	}
 
-	INIT_WORK(&omap_plane->work, unpin_worker);
-
 	omap_plane->nformats = omap_framebuffer_get_formats(
 			omap_plane->formats, ARRAY_SIZE(omap_plane->formats),
-			ovl->supported_modes);
-	omap_plane->ovl = ovl;
+			dss_feat_get_supported_color_modes(id));
+	omap_plane->id = id;
+	omap_plane->name = plane_names[id];
+
 	plane = &omap_plane->base;
 
-	drm_plane_init(dev, plane, possible_crtcs, &omap_plane_funcs,
-			omap_plane->formats, omap_plane->nformats, priv);
+	omap_plane->apply.pre_apply  = omap_plane_pre_apply;
+	omap_plane->apply.post_apply = omap_plane_post_apply;
+
+	omap_plane->error_irq.irqmask = error_irqs[id];
+	omap_plane->error_irq.irq = omap_plane_error_irq;
+	omap_irq_register(dev, &omap_plane->error_irq);
+
+	drm_plane_init(dev, plane, (1 << priv->num_crtcs) - 1, &omap_plane_funcs,
+			omap_plane->formats, omap_plane->nformats, private_plane);
 
 	omap_plane_install_properties(plane, &plane->base);
 
 	/* get our starting configuration, set defaults for parameters
 	 * we don't currently use, etc:
 	 */
-	ovl->get_overlay_info(ovl, &omap_plane->info);
-	omap_plane->info.rotation_type = OMAP_DSS_ROT_DMA;
-	omap_plane->info.rotation = OMAP_DSS_ROT_0;
-	omap_plane->info.global_alpha = 0xff;
-	omap_plane->info.mirror = 0;
+	info = &omap_plane->info;
+	info->rotation_type = OMAP_DSS_ROT_DMA;
+	info->rotation = OMAP_DSS_ROT_0;
+	info->global_alpha = 0xff;
+	info->mirror = 0;
 
 	/* Set defaults depending on whether we are a CRTC or overlay
 	 * layer.
 	 * TODO add ioctl to give userspace an API to change this.. this
 	 * will come in a subsequent patch.
 	 */
-	if (priv)
+	if (private_plane)
 		omap_plane->info.zorder = 0;
 	else
-		omap_plane->info.zorder = ovl->id;
-
-	update_manager(plane);
+		omap_plane->info.zorder = id;
 
 	return plane;
 
diff --git a/drivers/staging/rtl8187se/r8180_core.c b/drivers/staging/rtl8187se/r8180_core.c
index ae38475..d10d75e 100644
--- a/drivers/staging/rtl8187se/r8180_core.c
+++ b/drivers/staging/rtl8187se/r8180_core.c
@@ -937,7 +937,8 @@
 
 		dma_tmp = pci_map_single(pdev, buf, bufsize * sizeof(u8),
 					 PCI_DMA_FROMDEVICE);
-
+		if (pci_dma_mapping_error(pdev, dma_tmp))
+			return -1;
 		if (-1 == buffer_add(&(priv->rxbuffer), buf, dma_tmp,
 			   &(priv->rxbufferhead))) {
 			DMESGE("Unable to allocate mem RX buf");
diff --git a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
index 808aab6..a9d78e9 100644
--- a/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
+++ b/drivers/staging/rtl8192e/rtl8192e/r8192E_dev.c
@@ -1183,6 +1183,8 @@
 						pTxFwInfo->TxRate,
 						cb_desc);
 
+	if (pci_dma_mapping_error(priv->pdev, mapping))
+		RT_TRACE(COMP_ERR, "DMA Mapping error\n");;
 	if (cb_desc->bAMPDUEnable) {
 		pTxFwInfo->AllowAggregation = 1;
 		pTxFwInfo->RxMF = cb_desc->ampdu_factor;
@@ -1280,6 +1282,8 @@
 	dma_addr_t mapping = pci_map_single(priv->pdev, skb->data, skb->len,
 			 PCI_DMA_TODEVICE);
 
+	if (pci_dma_mapping_error(priv->pdev, mapping))
+		RT_TRACE(COMP_ERR, "DMA Mapping error\n");;
 	memset(entry, 0, 12);
 	entry->LINIP = cb_desc->bLastIniPkt;
 	entry->FirstSeg = 1;
diff --git a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
index 1a70f32..4ebf99b 100644
--- a/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
+++ b/drivers/staging/rtl8192e/rtl8192e/rtl_core.c
@@ -2104,7 +2104,10 @@
 						  skb_tail_pointer_rsl(skb),
 						  priv->rxbuffersize,
 						  PCI_DMA_FROMDEVICE);
-
+			if (pci_dma_mapping_error(priv->pdev, *mapping)) {
+				dev_kfree_skb_any(skb);
+				return -1;
+			}
 			entry->BufferAddress = cpu_to_le32(*mapping);
 
 			entry->Length = priv->rxbuffersize;
@@ -2397,7 +2400,11 @@
 						    skb_tail_pointer_rsl(skb),
 						    priv->rxbuffersize,
 						    PCI_DMA_FROMDEVICE);
-
+			if (pci_dma_mapping_error(priv->pdev,
+						  *((dma_addr_t *)skb->cb))) {
+				dev_kfree_skb_any(skb);
+				return;
+			}
 		}
 done:
 		pdesc->BufferAddress = cpu_to_le32(*((dma_addr_t *)skb->cb));
diff --git a/drivers/staging/rtl8712/usb_intf.c b/drivers/staging/rtl8712/usb_intf.c
index 6b73843..a96cd06 100644
--- a/drivers/staging/rtl8712/usb_intf.c
+++ b/drivers/staging/rtl8712/usb_intf.c
@@ -63,6 +63,8 @@
 	{USB_DEVICE(0x0B05, 0x1791)}, /* 11n mode disable */
 	/* Belkin */
 	{USB_DEVICE(0x050D, 0x945A)},
+	/* ISY IWL - Belkin clone */
+	{USB_DEVICE(0x050D, 0x11F1)},
 	/* Corega */
 	{USB_DEVICE(0x07AA, 0x0047)},
 	/* D-Link */
diff --git a/drivers/staging/sb105x/Kconfig b/drivers/staging/sb105x/Kconfig
index ac87c5e..1facad6 100644
--- a/drivers/staging/sb105x/Kconfig
+++ b/drivers/staging/sb105x/Kconfig
@@ -2,6 +2,7 @@
 	tristate "SystemBase PCI Multiport UART"
 	select SERIAL_CORE
 	depends on PCI
+	depends on X86
 	help
 	  A driver for the SystemBase Multi-2/PCI serial card
 
diff --git a/drivers/staging/sb105x/sb_pci_mp.c b/drivers/staging/sb105x/sb_pci_mp.c
index edb2a85..9464f38 100644
--- a/drivers/staging/sb105x/sb_pci_mp.c
+++ b/drivers/staging/sb105x/sb_pci_mp.c
@@ -3054,6 +3054,7 @@
 				sbdev->nr_ports = ((portnum_hex/16)*10) + (portnum_hex % 16);
 			}
 			break;
+#ifdef CONFIG_PARPORT_PC
 		case PCI_DEVICE_ID_MP2S1P :
 			sbdev->nr_ports = 2;
 
@@ -3073,6 +3074,7 @@
 			/* add PC compatible parallel port */
 			parport_pc_probe_port(pcidev->resource[2].start, pcidev->resource[3].start, PARPORT_IRQ_NONE, PARPORT_DMA_NONE, &pcidev->dev, 0);
 			break;
+#endif
 	}
 
 	ret = request_region(sbdev->uart_access_addr, (8*sbdev->nr_ports), sbdev->name);
diff --git a/drivers/staging/speakup/synth.c b/drivers/staging/speakup/synth.c
index df95337..7616f05 100644
--- a/drivers/staging/speakup/synth.c
+++ b/drivers/staging/speakup/synth.c
@@ -342,7 +342,7 @@
 
 	mutex_lock(&spk_mutex);
 	/* First, check if we already have it loaded. */
-	for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++)
+	for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++)
 		if (strcmp(synths[i]->name, synth_name) == 0)
 			synth = synths[i];
 
@@ -423,7 +423,7 @@
 	int i;
 	int status = 0;
 	mutex_lock(&spk_mutex);
-	for (i = 0; synths[i] != NULL && i < MAXSYNTHS; i++)
+	for (i = 0; i < MAXSYNTHS && synths[i] != NULL; i++)
 		/* synth_remove() is responsible for rotating the array down */
 		if (in_synth == synths[i]) {
 			mutex_unlock(&spk_mutex);
diff --git a/drivers/staging/tidspbridge/core/_tiomap.h b/drivers/staging/tidspbridge/core/_tiomap.h
index 543a127..b783bfa 100644
--- a/drivers/staging/tidspbridge/core/_tiomap.h
+++ b/drivers/staging/tidspbridge/core/_tiomap.h
@@ -31,7 +31,7 @@
  * driver should read or write to PRM/CM registers directly; they
  * should rely on OMAP core code to do this.
  */
-#include <mach-omap2/cm2xxx_3xxx.h>
+#include <mach-omap2/cm3xxx.h>
 #include <mach-omap2/prm-regbits-34xx.h>
 #include <mach-omap2/cm-regbits-34xx.h>
 #include <dspbridge/devdefs.h>
diff --git a/drivers/staging/tidspbridge/core/dsp-clock.c b/drivers/staging/tidspbridge/core/dsp-clock.c
index b647207..2f084e18 100644
--- a/drivers/staging/tidspbridge/core/dsp-clock.c
+++ b/drivers/staging/tidspbridge/core/dsp-clock.c
@@ -121,9 +121,13 @@
 	for (i = 0; i < DM_TIMER_CLOCKS; i++)
 		omap_dm_timer_free(timer[i]);
 
+	clk_unprepare(iva2_clk);
 	clk_put(iva2_clk);
+	clk_unprepare(ssi.sst_fck);
 	clk_put(ssi.sst_fck);
+	clk_unprepare(ssi.ssr_fck);
 	clk_put(ssi.ssr_fck);
+	clk_unprepare(ssi.ick);
 	clk_put(ssi.ick);
 }
 
@@ -145,14 +149,21 @@
 	iva2_clk = clk_get(&dspbridge_device.dev, "iva2_ck");
 	if (IS_ERR(iva2_clk))
 		dev_err(bridge, "failed to get iva2 clock %p\n", iva2_clk);
+	else
+		clk_prepare(iva2_clk);
 
 	ssi.sst_fck = clk_get(&dspbridge_device.dev, "ssi_sst_fck");
 	ssi.ssr_fck = clk_get(&dspbridge_device.dev, "ssi_ssr_fck");
 	ssi.ick = clk_get(&dspbridge_device.dev, "ssi_ick");
 
-	if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick))
+	if (IS_ERR(ssi.sst_fck) || IS_ERR(ssi.ssr_fck) || IS_ERR(ssi.ick)) {
 		dev_err(bridge, "failed to get ssi: sst %p, ssr %p, ick %p\n",
 					ssi.sst_fck, ssi.ssr_fck, ssi.ick);
+	} else {
+		clk_prepare(ssi.sst_fck);
+		clk_prepare(ssi.ssr_fck);
+		clk_prepare(ssi.ick);
+	}
 }
 
 /**
diff --git a/drivers/staging/tidspbridge/core/wdt.c b/drivers/staging/tidspbridge/core/wdt.c
index 1dce36f..7ff0e6c 100644
--- a/drivers/staging/tidspbridge/core/wdt.c
+++ b/drivers/staging/tidspbridge/core/wdt.c
@@ -63,11 +63,15 @@
 	dsp_wdt.fclk = clk_get(NULL, "wdt3_fck");
 
 	if (!IS_ERR(dsp_wdt.fclk)) {
+		clk_prepare(dsp_wdt.fclk);
+
 		dsp_wdt.iclk = clk_get(NULL, "wdt3_ick");
 		if (IS_ERR(dsp_wdt.iclk)) {
 			clk_put(dsp_wdt.fclk);
 			dsp_wdt.fclk = NULL;
 			ret = -EFAULT;
+		} else {
+			clk_prepare(dsp_wdt.iclk);
 		}
 	} else
 		ret = -EFAULT;
@@ -95,10 +99,14 @@
 	free_irq(INT_34XX_WDT3_IRQ, &dsp_wdt);
 	tasklet_kill(&dsp_wdt.wdt3_tasklet);
 
-	if (dsp_wdt.fclk)
+	if (dsp_wdt.fclk) {
+		clk_unprepare(dsp_wdt.fclk);
 		clk_put(dsp_wdt.fclk);
-	if (dsp_wdt.iclk)
+	}
+	if (dsp_wdt.iclk) {
+		clk_unprepare(dsp_wdt.iclk);
 		clk_put(dsp_wdt.iclk);
+	}
 
 	dsp_wdt.fclk = NULL;
 	dsp_wdt.iclk = NULL;
diff --git a/drivers/staging/vme/devices/vme_pio2_core.c b/drivers/staging/vme/devices/vme_pio2_core.c
index 0331178..bf73ba2 100644
--- a/drivers/staging/vme/devices/vme_pio2_core.c
+++ b/drivers/staging/vme/devices/vme_pio2_core.c
@@ -162,11 +162,9 @@
 
 static int __init pio2_init(void)
 {
-	int retval = 0;
-
 	if (bus_num == 0) {
 		pr_err("No cards, skipping registration\n");
-		goto err_nocard;
+		return -ENODEV;
 	}
 
 	if (bus_num > PIO2_CARDS_MAX) {
@@ -176,15 +174,7 @@
 	}
 
 	/* Register the PIO2 driver */
-	retval = vme_register_driver(&pio2_driver, bus_num);
-	if (retval != 0)
-		goto err_reg;
-
-	return retval;
-
-err_reg:
-err_nocard:
-	return retval;
+	return  vme_register_driver(&pio2_driver, bus_num);
 }
 
 static int pio2_match(struct vme_dev *vdev)
diff --git a/drivers/staging/vt6656/bssdb.h b/drivers/staging/vt6656/bssdb.h
index 6b2ec39..806cbf7 100644
--- a/drivers/staging/vt6656/bssdb.h
+++ b/drivers/staging/vt6656/bssdb.h
@@ -90,7 +90,6 @@
 } SRSNCapObject, *PSRSNCapObject;
 
 // BSS info(AP)
-#pragma pack(1)
 typedef struct tagKnownBSS {
     // BSS info
     BOOL            bActive;
diff --git a/drivers/staging/vt6656/int.h b/drivers/staging/vt6656/int.h
index 5d8faf9..e0d2b07 100644
--- a/drivers/staging/vt6656/int.h
+++ b/drivers/staging/vt6656/int.h
@@ -34,7 +34,6 @@
 #include "device.h"
 
 /*---------------------  Export Definitions -------------------------*/
-#pragma pack(1)
 typedef struct tagSINTData {
 	BYTE byTSR0;
 	BYTE byPkt0;
diff --git a/drivers/staging/vt6656/iocmd.h b/drivers/staging/vt6656/iocmd.h
index 22710ce..ae6e2d2 100644
--- a/drivers/staging/vt6656/iocmd.h
+++ b/drivers/staging/vt6656/iocmd.h
@@ -95,13 +95,12 @@
 // Ioctl interface structure
 // Command structure
 //
-#pragma pack(1)
 typedef struct tagSCmdRequest {
 	u8 name[16];
 	void	*data;
 	u16	    wResult;
 	u16     wCmdCode;
-} SCmdRequest, *PSCmdRequest;
+} __packed SCmdRequest, *PSCmdRequest;
 
 //
 // Scan
@@ -111,7 +110,7 @@
 
     u8	    ssid[SSID_MAXLEN + 2];
 
-} SCmdScan, *PSCmdScan;
+} __packed SCmdScan, *PSCmdScan;
 
 //
 // BSS Join
@@ -126,7 +125,7 @@
     BOOL    bPSEnable;
     BOOL    bShareKeyAuth;
 
-} SCmdBSSJoin, *PSCmdBSSJoin;
+} __packed SCmdBSSJoin, *PSCmdBSSJoin;
 
 //
 // Zonetype Setting
@@ -137,7 +136,7 @@
  BOOL       bWrite;
  WZONETYPE  ZoneType;
 
-} SCmdZoneTypeSet, *PSCmdZoneTypeSet;
+} __packed SCmdZoneTypeSet, *PSCmdZoneTypeSet;
 
 typedef struct tagSWPAResult {
          char	ifname[100];
@@ -145,7 +144,7 @@
 	u8 key_mgmt;
 	u8 eap_type;
          BOOL authenticated;
-} SWPAResult, *PSWPAResult;
+} __packed SWPAResult, *PSWPAResult;
 
 typedef struct tagSCmdStartAP {
 
@@ -157,7 +156,7 @@
     BOOL    bShareKeyAuth;
     u8      byBasicRate;
 
-} SCmdStartAP, *PSCmdStartAP;
+} __packed SCmdStartAP, *PSCmdStartAP;
 
 typedef struct tagSCmdSetWEP {
 
@@ -167,7 +166,7 @@
     BOOL    bWepKeyAvailable[WEP_NKEYS];
     u32     auWepKeyLength[WEP_NKEYS];
 
-} SCmdSetWEP, *PSCmdSetWEP;
+} __packed SCmdSetWEP, *PSCmdSetWEP;
 
 typedef struct tagSBSSIDItem {
 
@@ -180,14 +179,14 @@
     BOOL    bWEPOn;
     u32     uRSSI;
 
-} SBSSIDItem;
+} __packed SBSSIDItem;
 
 
 typedef struct tagSBSSIDList {
 
 	u32		    uItem;
 	SBSSIDItem	sBSSIDList[0];
-} SBSSIDList, *PSBSSIDList;
+} __packed SBSSIDList, *PSBSSIDList;
 
 
 typedef struct tagSNodeItem {
@@ -208,7 +207,7 @@
     u32            uTxAttempts;
     u16            wFailureRatio;
 
-} SNodeItem;
+} __packed SNodeItem;
 
 
 typedef struct tagSNodeList {
@@ -216,7 +215,7 @@
 	u32		    uItem;
 	SNodeItem	sNodeList[0];
 
-} SNodeList, *PSNodeList;
+} __packed SNodeList, *PSNodeList;
 
 
 typedef struct tagSCmdLinkStatus {
@@ -229,7 +228,7 @@
     u32     uChannel;
     u32     uLinkRate;
 
-} SCmdLinkStatus, *PSCmdLinkStatus;
+} __packed SCmdLinkStatus, *PSCmdLinkStatus;
 
 //
 // 802.11 counter
@@ -247,7 +246,7 @@
     u32 ReceivedFragmentCount;
     u32 MulticastReceivedFrameCount;
     u32 FCSErrorCount;
-} SDot11MIBCount, *PSDot11MIBCount;
+} __packed SDot11MIBCount, *PSDot11MIBCount;
 
 
 
@@ -355,13 +354,13 @@
     u32   ullTxBroadcastBytes[2];
     u32   ullTxMulticastBytes[2];
     u32   ullTxDirectedBytes[2];
-} SStatMIBCount, *PSStatMIBCount;
+} __packed SStatMIBCount, *PSStatMIBCount;
 
 typedef struct tagSCmdValue {
 
     u32     dwValue;
 
-} SCmdValue,  *PSCmdValue;
+} __packed SCmdValue,  *PSCmdValue;
 
 //
 // hostapd & viawget ioctl related
@@ -431,7 +430,7 @@
 			u8 ssid[32];
 		} scan_req;
 	} u;
-};
+} __packed;
 
 /*---------------------  Export Classes  ----------------------------*/
 
diff --git a/drivers/staging/vt6656/iowpa.h b/drivers/staging/vt6656/iowpa.h
index 959c886..2522dde 100644
--- a/drivers/staging/vt6656/iowpa.h
+++ b/drivers/staging/vt6656/iowpa.h
@@ -67,12 +67,11 @@
 
 
 
-#pragma pack(1)
 typedef struct viawget_wpa_header {
 	u8 type;
 	u16 req_ie_len;
 	u16 resp_ie_len;
-} viawget_wpa_header;
+} __packed viawget_wpa_header;
 
 struct viawget_wpa_param {
 	u32 cmd;
@@ -113,9 +112,8 @@
 			u8 *buf;
 		} scan_results;
 	} u;
-};
+} __packed;
 
-#pragma pack(1)
 struct viawget_scan_result {
 	u8 bssid[6];
 	u8 ssid[32];
@@ -130,7 +128,7 @@
 	int noise;
 	int level;
 	int maxrate;
-};
+} __packed;
 
 /*---------------------  Export Classes  ----------------------------*/
 
diff --git a/drivers/staging/wlan-ng/cfg80211.c b/drivers/staging/wlan-ng/cfg80211.c
index 18c06a5..1d31eab 100644
--- a/drivers/staging/wlan-ng/cfg80211.c
+++ b/drivers/staging/wlan-ng/cfg80211.c
@@ -638,8 +638,8 @@
 }
 
 
-int prism2_set_tx_power(struct wiphy *wiphy, enum nl80211_tx_power_setting type,
-			int mbm)
+int prism2_set_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+			enum nl80211_tx_power_setting type, int mbm)
 {
 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
 	wlandevice_t *wlandev = priv->wlandev;
@@ -665,7 +665,8 @@
 	return err;
 }
 
-int prism2_get_tx_power(struct wiphy *wiphy, int *dbm)
+int prism2_get_tx_power(struct wiphy *wiphy, struct wireless_dev *wdev,
+			int *dbm)
 {
 	struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
 	wlandevice_t *wlandev = priv->wlandev;
diff --git a/drivers/staging/wlan-ng/prism2mgmt.c b/drivers/staging/wlan-ng/prism2mgmt.c
index 4efa9bc..89bfd85 100644
--- a/drivers/staging/wlan-ng/prism2mgmt.c
+++ b/drivers/staging/wlan-ng/prism2mgmt.c
@@ -406,7 +406,7 @@
 	/* SSID */
 	req->ssid.status = P80211ENUM_msgitem_status_data_ok;
 	req->ssid.data.len = le16_to_cpu(item->ssid.len);
-	req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_BSSID_LEN);
+	req->ssid.data.len = min_t(u16, req->ssid.data.len, WLAN_SSID_MAXLEN);
 	memcpy(req->ssid.data.data, item->ssid.data, req->ssid.data.len);
 
 	/* supported rates */
diff --git a/drivers/staging/zram/zram_drv.c b/drivers/staging/zram/zram_drv.c
index fb4a7c9..f2a73bd 100644
--- a/drivers/staging/zram/zram_drv.c
+++ b/drivers/staging/zram/zram_drv.c
@@ -265,7 +265,7 @@
 static int zram_bvec_write(struct zram *zram, struct bio_vec *bvec, u32 index,
 			   int offset)
 {
-	int ret;
+	int ret = 0;
 	size_t clen;
 	unsigned long handle;
 	struct page *page;
@@ -286,10 +286,8 @@
 			goto out;
 		}
 		ret = zram_decompress_page(zram, uncmem, index);
-		if (ret) {
-			kfree(uncmem);
+		if (ret)
 			goto out;
-		}
 	}
 
 	/*
@@ -302,16 +300,18 @@
 
 	user_mem = kmap_atomic(page);
 
-	if (is_partial_io(bvec))
+	if (is_partial_io(bvec)) {
 		memcpy(uncmem + offset, user_mem + bvec->bv_offset,
 		       bvec->bv_len);
-	else
+		kunmap_atomic(user_mem);
+		user_mem = NULL;
+	} else {
 		uncmem = user_mem;
+	}
 
 	if (page_zero_filled(uncmem)) {
-		kunmap_atomic(user_mem);
-		if (is_partial_io(bvec))
-			kfree(uncmem);
+		if (!is_partial_io(bvec))
+			kunmap_atomic(user_mem);
 		zram_stat_inc(&zram->stats.pages_zero);
 		zram_set_flag(zram, index, ZRAM_ZERO);
 		ret = 0;
@@ -321,9 +321,11 @@
 	ret = lzo1x_1_compress(uncmem, PAGE_SIZE, src, &clen,
 			       zram->compress_workmem);
 
-	kunmap_atomic(user_mem);
-	if (is_partial_io(bvec))
-			kfree(uncmem);
+	if (!is_partial_io(bvec)) {
+		kunmap_atomic(user_mem);
+		user_mem = NULL;
+		uncmem = NULL;
+	}
 
 	if (unlikely(ret != LZO_E_OK)) {
 		pr_err("Compression failed! err=%d\n", ret);
@@ -332,8 +334,10 @@
 
 	if (unlikely(clen > max_zpage_size)) {
 		zram_stat_inc(&zram->stats.bad_compress);
-		src = uncmem;
 		clen = PAGE_SIZE;
+		src = NULL;
+		if (is_partial_io(bvec))
+			src = uncmem;
 	}
 
 	handle = zs_malloc(zram->mem_pool, clen);
@@ -345,7 +349,11 @@
 	}
 	cmem = zs_map_object(zram->mem_pool, handle, ZS_MM_WO);
 
+	if ((clen == PAGE_SIZE) && !is_partial_io(bvec))
+		src = kmap_atomic(page);
 	memcpy(cmem, src, clen);
+	if ((clen == PAGE_SIZE) && !is_partial_io(bvec))
+		kunmap_atomic(src);
 
 	zs_unmap_object(zram->mem_pool, handle);
 
@@ -358,9 +366,10 @@
 	if (clen <= PAGE_SIZE / 2)
 		zram_stat_inc(&zram->stats.good_compress);
 
-	return 0;
-
 out:
+	if (is_partial_io(bvec))
+		kfree(uncmem);
+
 	if (ret)
 		zram_stat64_inc(zram, &zram->stats.failed_writes);
 	return ret;
diff --git a/drivers/target/iscsi/iscsi_target_erl2.c b/drivers/target/iscsi/iscsi_target_erl2.c
index 9ac4c151..ba6091b 100644
--- a/drivers/target/iscsi/iscsi_target_erl2.c
+++ b/drivers/target/iscsi/iscsi_target_erl2.c
@@ -372,7 +372,7 @@
 		 * made generic here.
 		 */
 		if (!(cmd->cmd_flags & ICF_OOO_CMDSN) && !cmd->immediate_cmd &&
-		     iscsi_sna_gte(cmd->stat_sn, conn->sess->exp_cmd_sn)) {
+		     iscsi_sna_gte(cmd->cmd_sn, conn->sess->exp_cmd_sn)) {
 			list_del(&cmd->i_conn_node);
 			spin_unlock_bh(&conn->cmd_lock);
 			iscsit_free_cmd(cmd);
diff --git a/drivers/target/target_core_alua.c b/drivers/target/target_core_alua.c
index 85140f7..7d4ec02 100644
--- a/drivers/target/target_core_alua.c
+++ b/drivers/target/target_core_alua.c
@@ -212,7 +212,7 @@
 	struct t10_alua_tg_pt_gp_member *tg_pt_gp_mem, *l_tg_pt_gp_mem;
 	unsigned char *buf;
 	unsigned char *ptr;
-	sense_reason_t rc;
+	sense_reason_t rc = TCM_NO_SENSE;
 	u32 len = 4; /* Skip over RESERVED area in header */
 	int alua_access_state, primary = 0;
 	u16 tg_pt_id, rtpi;
diff --git a/drivers/target/target_core_pr.c b/drivers/target/target_core_pr.c
index e35dbf85..8e0290b 100644
--- a/drivers/target/target_core_pr.c
+++ b/drivers/target/target_core_pr.c
@@ -2053,7 +2053,7 @@
 	/* Used for APTPL metadata w/ UNREGISTER */
 	unsigned char *pr_aptpl_buf = NULL;
 	unsigned char isid_buf[PR_REG_ISID_LEN], *isid_ptr = NULL;
-	sense_reason_t ret;
+	sense_reason_t ret = TCM_NO_SENSE;
 	int pr_holder = 0, type;
 
 	if (!se_sess || !se_lun) {
diff --git a/drivers/target/target_core_transport.c b/drivers/target/target_core_transport.c
index c23c76c..bd587b7 100644
--- a/drivers/target/target_core_transport.c
+++ b/drivers/target/target_core_transport.c
@@ -541,9 +541,6 @@
 
 void transport_cmd_finish_abort(struct se_cmd *cmd, int remove)
 {
-	if (!(cmd->se_cmd_flags & SCF_SCSI_TMR_CDB))
-		transport_lun_remove_cmd(cmd);
-
 	if (transport_cmd_check_stop_to_fabric(cmd))
 		return;
 	if (remove)
@@ -1396,6 +1393,8 @@
 
 	se_cmd->se_tmr_req->response = TMR_LUN_DOES_NOT_EXIST;
 	se_cmd->se_tfo->queue_tm_rsp(se_cmd);
+
+	transport_cmd_check_stop_to_fabric(se_cmd);
 }
 
 /**
@@ -1688,6 +1687,7 @@
 	}
 
 	cmd->t_state = TRANSPORT_PROCESSING;
+	cmd->transport_state |= CMD_T_ACTIVE;
 	spin_unlock_irq(&cmd->t_state_lock);
 
 	if (!target_handle_task_attr(cmd))
@@ -2597,6 +2597,16 @@
 	 * SENSE KEY values from include/scsi/scsi.h
 	 */
 	switch (reason) {
+	case TCM_NO_SENSE:
+		/* CURRENT ERROR */
+		buffer[0] = 0x70;
+		buffer[SPC_ADD_SENSE_LEN_OFFSET] = 10;
+		/* Not Ready */
+		buffer[SPC_SENSE_KEY_OFFSET] = NOT_READY;
+		/* NO ADDITIONAL SENSE INFORMATION */
+		buffer[SPC_ASC_KEY_OFFSET] = 0;
+		buffer[SPC_ASCQ_KEY_OFFSET] = 0;
+		break;
 	case TCM_NON_EXISTENT_LUN:
 		/* CURRENT ERROR */
 		buffer[0] = 0x70;
@@ -2743,7 +2753,7 @@
 		/* ILLEGAL REQUEST */
 		buffer[SPC_SENSE_KEY_OFFSET] = ILLEGAL_REQUEST;
 		/* LOGICAL UNIT COMMUNICATION FAILURE */
-		buffer[SPC_ASC_KEY_OFFSET] = 0x80;
+		buffer[SPC_ASC_KEY_OFFSET] = 0x08;
 		break;
 	}
 	/*
@@ -2804,6 +2814,8 @@
 	}
 	cmd->scsi_status = SAM_STAT_TASK_ABORTED;
 
+	transport_lun_remove_cmd(cmd);
+
 	pr_debug("Setting SAM_STAT_TASK_ABORTED status for CDB: 0x%02x,"
 		" ITT: 0x%08x\n", cmd->t_task_cdb[0],
 		cmd->se_tfo->get_task_tag(cmd));
diff --git a/drivers/target/tcm_fc/tfc_sess.c b/drivers/target/tcm_fc/tfc_sess.c
index 12d6fa2..6659dd3 100644
--- a/drivers/target/tcm_fc/tfc_sess.c
+++ b/drivers/target/tcm_fc/tfc_sess.c
@@ -355,11 +355,11 @@
 
 	tport = ft_tport_create(rdata->local_port);
 	if (!tport)
-		return 0;	/* not a target for this local port */
+		goto not_target;	/* not a target for this local port */
 
 	acl = ft_acl_get(tport->tpg, rdata);
 	if (!acl)
-		return 0;
+		goto not_target;	/* no target for this remote */
 
 	if (!rspp)
 		goto fill;
@@ -396,12 +396,18 @@
 
 	/*
 	 * OR in our service parameters with other provider (initiator), if any.
-	 * TBD XXX - indicate RETRY capability?
 	 */
 fill:
 	fcp_parm = ntohl(spp->spp_params);
+	fcp_parm &= ~FCP_SPPF_RETRY;
 	spp->spp_params = htonl(fcp_parm | FCP_SPPF_TARG_FCN);
 	return FC_SPP_RESP_ACK;
+
+not_target:
+	fcp_parm = ntohl(spp->spp_params);
+	fcp_parm &= ~FCP_SPPF_TARG_FCN;
+	spp->spp_params = htonl(fcp_parm);
+	return 0;
 }
 
 /**
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index be6a373..79ff3a5 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -441,6 +441,8 @@
 		return pty_get_pktmode(tty, (int __user *)arg);
 	case TIOCSIG:    /* Send signal to other side of pty */
 		return pty_signal(tty, (int) arg);
+	case TIOCGPTN: /* TTY returns ENOTTY, but glibc expects EINVAL here */
+		return -EINVAL;
 	}
 	return -ENOIOCTLCMD;
 }
diff --git a/drivers/tty/serial/8250/8250.c b/drivers/tty/serial/8250/8250.c
index d085e3a..f932043 100644
--- a/drivers/tty/serial/8250/8250.c
+++ b/drivers/tty/serial/8250/8250.c
@@ -300,6 +300,12 @@
 				  UART_FCR_R_TRIG_00 | UART_FCR_T_TRIG_00,
 		.flags		= UART_CAP_FIFO,
 	},
+	[PORT_BRCM_TRUMANAGE] = {
+		.name		= "TruManage",
+		.fifo_size	= 1,
+		.tx_loadsz	= 1024,
+		.flags		= UART_CAP_HFIFO,
+	},
 	[PORT_8250_CIR] = {
 		.name		= "CIR port"
 	}
@@ -1490,6 +1496,11 @@
 		port->icount.tx++;
 		if (uart_circ_empty(xmit))
 			break;
+		if (up->capabilities & UART_CAP_HFIFO) {
+			if ((serial_port_in(port, UART_LSR) & BOTH_EMPTY) !=
+			    BOTH_EMPTY)
+				break;
+		}
 	} while (--count > 0);
 
 	if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 3b4ea84..12caa12 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -40,6 +40,7 @@
 #define UART_CAP_AFE	(1 << 11)	/* MCR-based hw flow control */
 #define UART_CAP_UUE	(1 << 12)	/* UART needs IER bit 6 set (Xscale) */
 #define UART_CAP_RTOIE	(1 << 13)	/* UART needs IER bit 4 set (Xscale, Tegra) */
+#define UART_CAP_HFIFO	(1 << 14)	/* UART has a "hidden" FIFO */
 
 #define UART_BUG_QUOT	(1 << 0)	/* UART has buggy quot LSB */
 #define UART_BUG_TXEN	(1 << 1)	/* UART has buggy TX IIR status */
diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
index 1d0dba2..096d2ef 100644
--- a/drivers/tty/serial/8250/8250_dw.c
+++ b/drivers/tty/serial/8250/8250_dw.c
@@ -79,7 +79,7 @@
 	} else if ((iir & UART_IIR_BUSY) == UART_IIR_BUSY) {
 		/* Clear the USR and write the LCR again. */
 		(void)p->serial_in(p, UART_USR);
-		p->serial_out(p, d->last_lcr, UART_LCR);
+		p->serial_out(p, UART_LCR, d->last_lcr);
 
 		return 1;
 	}
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 26b9dc0..a27a98e 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -1085,6 +1085,18 @@
 	return setup_port(priv, port, 2, idx * 8, 0);
 }
 
+static int
+pci_brcm_trumanage_setup(struct serial_private *priv,
+			 const struct pciserial_board *board,
+			 struct uart_8250_port *port, int idx)
+{
+	int ret = pci_default_setup(priv, board, port, idx);
+
+	port->port.type = PORT_BRCM_TRUMANAGE;
+	port->port.flags = (port->port.flags | UPF_FIXED_PORT | UPF_FIXED_TYPE);
+	return ret;
+}
+
 static int skip_tx_en_setup(struct serial_private *priv,
 			const struct pciserial_board *board,
 			struct uart_8250_port *port, int idx)
@@ -1301,9 +1313,10 @@
 #define PCI_VENDOR_ID_AGESTAR		0x5372
 #define PCI_DEVICE_ID_AGESTAR_9375	0x6872
 #define PCI_VENDOR_ID_ASIX		0x9710
-#define PCI_DEVICE_ID_COMMTECH_4222PCIE 0x0019
 #define PCI_DEVICE_ID_COMMTECH_4224PCIE	0x0020
 #define PCI_DEVICE_ID_COMMTECH_4228PCIE	0x0021
+#define PCI_DEVICE_ID_COMMTECH_4222PCIE	0x0022
+#define PCI_DEVICE_ID_BROADCOM_TRUMANAGE 0x160a
 
 
 /* Unknown vendors/cards - this should not be in linux/pci_ids.h */
@@ -1954,6 +1967,17 @@
 		.setup		= pci_xr17v35x_setup,
 	},
 	/*
+	 * Broadcom TruManage (NetXtreme)
+	 */
+	{
+		.vendor		= PCI_VENDOR_ID_BROADCOM,
+		.device		= PCI_DEVICE_ID_BROADCOM_TRUMANAGE,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+		.setup		= pci_brcm_trumanage_setup,
+	},
+
+	/*
 	 * Default "match everything" terminator entry
 	 */
 	{
@@ -2148,6 +2172,7 @@
 	pbn_ce4100_1_115200,
 	pbn_omegapci,
 	pbn_NETMOS9900_2s_115200,
+	pbn_brcm_trumanage,
 };
 
 /*
@@ -2246,7 +2271,7 @@
 
 	[pbn_b0_8_1152000_200] = {
 		.flags		= FL_BASE0,
-		.num_ports	= 2,
+		.num_ports	= 8,
 		.base_baud	= 1152000,
 		.uart_offset	= 0x200,
 	},
@@ -2892,6 +2917,12 @@
 		.num_ports	= 2,
 		.base_baud	= 115200,
 	},
+	[pbn_brcm_trumanage] = {
+		.flags		= FL_BASE0,
+		.num_ports	= 1,
+		.reg_shift	= 2,
+		.base_baud	= 115200,
+	},
 };
 
 static const struct pci_device_id blacklist[] = {
@@ -4471,6 +4502,13 @@
 		pbn_omegapci },
 
 	/*
+	 * Broadcom TruManage
+	 */
+	{	PCI_VENDOR_ID_BROADCOM, PCI_DEVICE_ID_BROADCOM_TRUMANAGE,
+		PCI_ANY_ID, PCI_ANY_ID, 0, 0,
+		pbn_brcm_trumanage },
+
+	/*
 	 * AgeStar as-prs2-009
 	 */
 	{	PCI_VENDOR_ID_AGESTAR, PCI_DEVICE_ID_AGESTAR_9375,
diff --git a/drivers/tty/serial/ifx6x60.c b/drivers/tty/serial/ifx6x60.c
index 675d94a..8cb6d8d 100644
--- a/drivers/tty/serial/ifx6x60.c
+++ b/drivers/tty/serial/ifx6x60.c
@@ -637,6 +637,7 @@
 
 	clear_bit(IFX_SPI_STATE_IO_AVAILABLE, &ifx_dev->flags);
 	mrdy_set_low(ifx_dev);
+	del_timer(&ifx_dev->spi_timer);
 	clear_bit(IFX_SPI_STATE_TIMER_PENDING, &ifx_dev->flags);
 	tasklet_kill(&ifx_dev->io_work_tasklet);
 }
@@ -810,7 +811,8 @@
 		ifx_dev->spi_xfer.cs_change = 0;
 		ifx_dev->spi_xfer.speed_hz = ifx_dev->spi_dev->max_speed_hz;
 		/* ifx_dev->spi_xfer.speed_hz = 390625; */
-		ifx_dev->spi_xfer.bits_per_word = spi_bpw;
+		ifx_dev->spi_xfer.bits_per_word =
+			ifx_dev->spi_dev->bits_per_word;
 
 		ifx_dev->spi_xfer.tx_buf = ifx_dev->tx_buffer;
 		ifx_dev->spi_xfer.rx_buf = ifx_dev->rx_buffer;
diff --git a/drivers/tty/serial/mxs-auart.c b/drivers/tty/serial/mxs-auart.c
index 6db23b0..e55615e 100644
--- a/drivers/tty/serial/mxs-auart.c
+++ b/drivers/tty/serial/mxs-auart.c
@@ -253,7 +253,7 @@
 	struct circ_buf *xmit = &s->port.state->xmit;
 
 	if (auart_dma_enabled(s)) {
-		int i = 0;
+		u32 i = 0;
 		int size;
 		void *buffer = s->tx_dma_buf;
 
@@ -412,10 +412,12 @@
 
 	u32 ctrl = readl(u->membase + AUART_CTRL2);
 
-	ctrl &= ~AUART_CTRL2_RTSEN;
+	ctrl &= ~(AUART_CTRL2_RTSEN | AUART_CTRL2_RTS);
 	if (mctrl & TIOCM_RTS) {
 		if (tty_port_cts_enabled(&u->state->port))
 			ctrl |= AUART_CTRL2_RTSEN;
+		else
+			ctrl |= AUART_CTRL2_RTS;
 	}
 
 	s->ctrl = mctrl;
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index 12e5249..e514b3a 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -1006,7 +1006,6 @@
 
 	ucon &= ucon_mask;
 	wr_regl(port, S3C2410_UCON,  ucon | cfg->ucon);
-	wr_regl(port, S3C2410_ULCON, cfg->ulcon);
 
 	/* reset both fifos */
 	wr_regl(port, S3C2410_UFCON, cfg->ufcon | S3C2410_UFCON_RESETBOTH);
diff --git a/drivers/tty/serial/vt8500_serial.c b/drivers/tty/serial/vt8500_serial.c
index 8fd1814..d5ed9f6 100644
--- a/drivers/tty/serial/vt8500_serial.c
+++ b/drivers/tty/serial/vt8500_serial.c
@@ -604,7 +604,7 @@
 	vt8500_port->uart.flags = UPF_IOREMAP | UPF_BOOT_AUTOCONF;
 
 	vt8500_port->clk = of_clk_get(pdev->dev.of_node, 0);
-	if (vt8500_port->clk) {
+	if (!IS_ERR(vt8500_port->clk)) {
 		vt8500_port->uart.uartclk = clk_get_rate(vt8500_port->clk);
 	} else {
 		/* use the default of 24Mhz if not specified and warn */
diff --git a/drivers/usb/Kconfig b/drivers/usb/Kconfig
index 4c90b510..640ae6c 100644
--- a/drivers/usb/Kconfig
+++ b/drivers/usb/Kconfig
@@ -37,6 +37,7 @@
 	default y if ARCH_W90X900
 	default y if ARCH_AT91
 	default y if ARCH_MXC
+	default y if ARCH_MXS
 	default y if ARCH_OMAP3
 	default y if ARCH_CNS3XXX
 	default y if ARCH_VT8500
diff --git a/drivers/usb/chipidea/host.c b/drivers/usb/chipidea/host.c
index caecad9..8e9d312 100644
--- a/drivers/usb/chipidea/host.c
+++ b/drivers/usb/chipidea/host.c
@@ -70,6 +70,9 @@
 	else
 		ci->hcd = hcd;
 
+	if (ci->platdata->flags & CI13XXX_DISABLE_STREAMING)
+		hw_write(ci, OP_USBMODE, USBMODE_CI_SDIS, USBMODE_CI_SDIS);
+
 	return ret;
 }
 
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 8d809a8..2d92cce 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -1602,6 +1602,9 @@
 	{ USB_DEVICE(0x0572, 0x1340), /* Conexant CX93010-2x UCMxx */
 	.driver_info = NO_UNION_NORMAL,
 	},
+	{ USB_DEVICE(0x05f9, 0x4002), /* PSC Scanning, Magellan 800i */
+	.driver_info = NO_UNION_NORMAL,
+	},
 	{ USB_DEVICE(0x1bbb, 0x0003), /* Alcatel OT-I650 */
 	.driver_info = NO_UNION_NORMAL, /* reports zero length descriptor */
 	},
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index a815fd2..957ed2c 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -877,6 +877,60 @@
 	return ret;
 }
 
+static int hub_set_port_link_state(struct usb_hub *hub, int port1,
+			unsigned int link_status)
+{
+	return set_port_feature(hub->hdev,
+			port1 | (link_status << 3),
+			USB_PORT_FEAT_LINK_STATE);
+}
+
+/*
+ * If USB 3.0 ports are placed into the Disabled state, they will no longer
+ * detect any device connects or disconnects.  This is generally not what the
+ * USB core wants, since it expects a disabled port to produce a port status
+ * change event when a new device connects.
+ *
+ * Instead, set the link state to Disabled, wait for the link to settle into
+ * that state, clear any change bits, and then put the port into the RxDetect
+ * state.
+ */
+static int hub_usb3_port_disable(struct usb_hub *hub, int port1)
+{
+	int ret;
+	int total_time;
+	u16 portchange, portstatus;
+
+	if (!hub_is_superspeed(hub->hdev))
+		return -EINVAL;
+
+	ret = hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_SS_DISABLED);
+	if (ret) {
+		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
+				port1, ret);
+		return ret;
+	}
+
+	/* Wait for the link to enter the disabled state. */
+	for (total_time = 0; ; total_time += HUB_DEBOUNCE_STEP) {
+		ret = hub_port_status(hub, port1, &portstatus, &portchange);
+		if (ret < 0)
+			return ret;
+
+		if ((portstatus & USB_PORT_STAT_LINK_STATE) ==
+				USB_SS_PORT_LS_SS_DISABLED)
+			break;
+		if (total_time >= HUB_DEBOUNCE_TIMEOUT)
+			break;
+		msleep(HUB_DEBOUNCE_STEP);
+	}
+	if (total_time >= HUB_DEBOUNCE_TIMEOUT)
+		dev_warn(hub->intfdev, "Could not disable port %d after %d ms\n",
+				port1, total_time);
+
+	return hub_set_port_link_state(hub, port1, USB_SS_PORT_LS_RX_DETECT);
+}
+
 static int hub_port_disable(struct usb_hub *hub, int port1, int set_state)
 {
 	struct usb_device *hdev = hub->hdev;
@@ -885,8 +939,13 @@
 	if (hub->ports[port1 - 1]->child && set_state)
 		usb_set_device_state(hub->ports[port1 - 1]->child,
 				USB_STATE_NOTATTACHED);
-	if (!hub->error && !hub_is_superspeed(hub->hdev))
-		ret = clear_port_feature(hdev, port1, USB_PORT_FEAT_ENABLE);
+	if (!hub->error) {
+		if (hub_is_superspeed(hub->hdev))
+			ret = hub_usb3_port_disable(hub, port1);
+		else
+			ret = clear_port_feature(hdev, port1,
+					USB_PORT_FEAT_ENABLE);
+	}
 	if (ret)
 		dev_err(hub->intfdev, "cannot disable port %d (err = %d)\n",
 				port1, ret);
@@ -2440,7 +2499,7 @@
 #define HUB_SHORT_RESET_TIME	10
 #define HUB_BH_RESET_TIME	50
 #define HUB_LONG_RESET_TIME	200
-#define HUB_RESET_TIMEOUT	500
+#define HUB_RESET_TIMEOUT	800
 
 static int hub_port_reset(struct usb_hub *hub, int port1,
 			struct usb_device *udev, unsigned int delay, bool warm);
@@ -2475,6 +2534,10 @@
 		if (ret < 0)
 			return ret;
 
+		/* The port state is unknown until the reset completes. */
+		if ((portstatus & USB_PORT_STAT_RESET))
+			goto delay;
+
 		/*
 		 * Some buggy devices require a warm reset to be issued even
 		 * when the port appears not to be connected.
@@ -2520,11 +2583,7 @@
 			if ((portchange & USB_PORT_STAT_C_CONNECTION))
 				return -ENOTCONN;
 
-			/* if we`ve finished resetting, then break out of
-			 * the loop
-			 */
-			if (!(portstatus & USB_PORT_STAT_RESET) &&
-			    (portstatus & USB_PORT_STAT_ENABLE)) {
+			if ((portstatus & USB_PORT_STAT_ENABLE)) {
 				if (hub_is_wusb(hub))
 					udev->speed = USB_SPEED_WIRELESS;
 				else if (hub_is_superspeed(hub->hdev))
@@ -2538,10 +2597,15 @@
 				return 0;
 			}
 		} else {
-			if (portchange & USB_PORT_STAT_C_BH_RESET)
-				return 0;
+			if (!(portstatus & USB_PORT_STAT_CONNECTION) ||
+					hub_port_warm_reset_required(hub,
+						portstatus))
+				return -ENOTCONN;
+
+			return 0;
 		}
 
+delay:
 		/* switch to the long delay after two short delay failures */
 		if (delay_time >= 2 * HUB_SHORT_RESET_TIME)
 			delay = HUB_LONG_RESET_TIME;
@@ -2565,14 +2629,11 @@
 			msleep(10 + 40);
 			update_devnum(udev, 0);
 			hcd = bus_to_hcd(udev->bus);
-			if (hcd->driver->reset_device) {
-				*status = hcd->driver->reset_device(hcd, udev);
-				if (*status < 0) {
-					dev_err(&udev->dev, "Cannot reset "
-							"HCD device state\n");
-					break;
-				}
-			}
+			/* The xHC may think the device is already reset,
+			 * so ignore the status.
+			 */
+			if (hcd->driver->reset_device)
+				hcd->driver->reset_device(hcd, udev);
 		}
 		/* FALL THROUGH */
 	case -ENOTCONN:
@@ -2580,16 +2641,16 @@
 		clear_port_feature(hub->hdev,
 				port1, USB_PORT_FEAT_C_RESET);
 		/* FIXME need disconnect() for NOTATTACHED device */
-		if (warm) {
+		if (hub_is_superspeed(hub->hdev)) {
 			clear_port_feature(hub->hdev, port1,
 					USB_PORT_FEAT_C_BH_PORT_RESET);
 			clear_port_feature(hub->hdev, port1,
 					USB_PORT_FEAT_C_PORT_LINK_STATE);
-		} else {
+		}
+		if (!warm)
 			usb_set_device_state(udev, *status
 					? USB_STATE_NOTATTACHED
 					: USB_STATE_DEFAULT);
-		}
 		break;
 	}
 }
@@ -2939,7 +3000,7 @@
 static int finish_port_resume(struct usb_device *udev)
 {
 	int	status = 0;
-	u16	devstatus;
+	u16	devstatus = 0;
 
 	/* caller owns the udev device lock */
 	dev_dbg(&udev->dev, "%s\n",
@@ -2984,7 +3045,13 @@
 	if (status) {
 		dev_dbg(&udev->dev, "gone after usb resume? status %d\n",
 				status);
-	} else if (udev->actconfig) {
+	/*
+	 * There are a few quirky devices which violate the standard
+	 * by claiming to have remote wakeup enabled after a reset,
+	 * which crash if the feature is cleared, hence check for
+	 * udev->reset_resume
+	 */
+	} else if (udev->actconfig && !udev->reset_resume) {
 		le16_to_cpus(&devstatus);
 		if (devstatus & (1 << USB_DEVICE_REMOTE_WAKEUP)) {
 			status = usb_control_msg(udev,
@@ -4638,9 +4705,14 @@
 			 * SS.Inactive state.
 			 */
 			if (hub_port_warm_reset_required(hub, portstatus)) {
+				int status;
+
 				dev_dbg(hub_dev, "warm reset port %d\n", i);
-				hub_port_reset(hub, i, NULL,
+				status = hub_port_reset(hub, i, NULL,
 						HUB_BH_RESET_TIME, true);
+				if (status < 0)
+					hub_port_disable(hub, i, 1);
+				connect_change = 0;
 			}
 
 			if (connect_change)
diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c
index fdefd9c..3113c1d 100644
--- a/drivers/usb/core/quirks.c
+++ b/drivers/usb/core/quirks.c
@@ -43,6 +43,9 @@
 	/* Creative SB Audigy 2 NX */
 	{ USB_DEVICE(0x041e, 0x3020), .driver_info = USB_QUIRK_RESET_RESUME },
 
+	/* Microsoft LifeCam-VX700 v2.0 */
+	{ USB_DEVICE(0x045e, 0x0770), .driver_info = USB_QUIRK_RESET_RESUME },
+
 	/* Logitech Quickcam Fusion */
 	{ USB_DEVICE(0x046d, 0x08c1), .driver_info = USB_QUIRK_RESET_RESUME },
 
diff --git a/drivers/usb/dwc3/debugfs.c b/drivers/usb/dwc3/debugfs.c
index 92604b4..5945aad 100644
--- a/drivers/usb/dwc3/debugfs.c
+++ b/drivers/usb/dwc3/debugfs.c
@@ -56,7 +56,7 @@
 #define dump_register(nm)				\
 {							\
 	.name	= __stringify(nm),			\
-	.offset	= DWC3_ ##nm,				\
+	.offset	= DWC3_ ##nm - DWC3_GLOBALS_REGS_START,	\
 }
 
 static const struct debugfs_reg32 dwc3_regs[] = {
diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
index 2e43b33..2fdd767 100644
--- a/drivers/usb/dwc3/gadget.c
+++ b/drivers/usb/dwc3/gadget.c
@@ -1605,6 +1605,7 @@
 
 		if (epnum == 0 || epnum == 1) {
 			dep->endpoint.maxpacket = 512;
+			dep->endpoint.maxburst = 1;
 			dep->endpoint.ops = &dwc3_gadget_ep0_ops;
 			if (!epnum)
 				dwc->gadget.ep0 = &dep->endpoint;
diff --git a/drivers/usb/gadget/amd5536udc.c b/drivers/usb/gadget/amd5536udc.c
index fc0ec5e..d9f6b93 100644
--- a/drivers/usb/gadget/amd5536udc.c
+++ b/drivers/usb/gadget/amd5536udc.c
@@ -3231,7 +3231,7 @@
 	}
 
 	if (!pdev->irq) {
-		dev_err(&dev->pdev->dev, "irq not set\n");
+		dev_err(&pdev->dev, "irq not set\n");
 		kfree(dev);
 		dev = NULL;
 		retval = -ENODEV;
@@ -3250,7 +3250,7 @@
 	dev->txfifo = (u32 __iomem *)(dev->virt_addr + UDC_TXFIFO_ADDR);
 
 	if (request_irq(pdev->irq, udc_irq, IRQF_SHARED, name, dev) != 0) {
-		dev_dbg(&dev->pdev->dev, "request_irq(%d) fail\n", pdev->irq);
+		dev_dbg(&pdev->dev, "request_irq(%d) fail\n", pdev->irq);
 		kfree(dev);
 		dev = NULL;
 		retval = -EBUSY;
diff --git a/drivers/usb/gadget/dummy_hcd.c b/drivers/usb/gadget/dummy_hcd.c
index 95d584d..8cf0c0f 100644
--- a/drivers/usb/gadget/dummy_hcd.c
+++ b/drivers/usb/gadget/dummy_hcd.c
@@ -130,10 +130,7 @@
 static const char *const ep_name[] = {
 	ep0name,				/* everyone has ep0 */
 
-	/* act like a net2280: high speed, six configurable endpoints */
-	"ep-a", "ep-b", "ep-c", "ep-d", "ep-e", "ep-f",
-
-	/* or like pxa250: fifteen fixed function endpoints */
+	/* act like a pxa250: fifteen fixed function endpoints */
 	"ep1in-bulk", "ep2out-bulk", "ep3in-iso", "ep4out-iso", "ep5in-int",
 	"ep6in-bulk", "ep7out-bulk", "ep8in-iso", "ep9out-iso", "ep10in-int",
 	"ep11in-bulk", "ep12out-bulk", "ep13in-iso", "ep14out-iso",
@@ -141,6 +138,10 @@
 
 	/* or like sa1100: two fixed function endpoints */
 	"ep1out-bulk", "ep2in-bulk",
+
+	/* and now some generic EPs so we have enough in multi config */
+	"ep3out", "ep4in", "ep5out", "ep6out", "ep7in", "ep8out", "ep9in",
+	"ep10out", "ep11out", "ep12in", "ep13out", "ep14in", "ep15out",
 };
 #define DUMMY_ENDPOINTS	ARRAY_SIZE(ep_name)
 
diff --git a/drivers/usb/gadget/f_fs.c b/drivers/usb/gadget/f_fs.c
index 4a6961c..8c2f251 100644
--- a/drivers/usb/gadget/f_fs.c
+++ b/drivers/usb/gadget/f_fs.c
@@ -1153,15 +1153,15 @@
 					pr_err("%s: unmapped value: %lu\n", opts, value);
 					return -EINVAL;
 				}
-			}
-			else if (!memcmp(opts, "gid", 3))
+			} else if (!memcmp(opts, "gid", 3)) {
 				data->perms.gid = make_kgid(current_user_ns(), value);
 				if (!gid_valid(data->perms.gid)) {
 					pr_err("%s: unmapped value: %lu\n", opts, value);
 					return -EINVAL;
 				}
-			else
+			} else {
 				goto invalid;
+			}
 			break;
 
 		default:
diff --git a/drivers/usb/gadget/fsl_mxc_udc.c b/drivers/usb/gadget/fsl_mxc_udc.c
index 1b0f086..d3bd7b0 100644
--- a/drivers/usb/gadget/fsl_mxc_udc.c
+++ b/drivers/usb/gadget/fsl_mxc_udc.c
@@ -18,14 +18,13 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 
-#include <mach/hardware.h>
-
 static struct clk *mxc_ahb_clk;
 static struct clk *mxc_per_clk;
 static struct clk *mxc_ipg_clk;
 
 /* workaround ENGcm09152 for i.MX35 */
-#define USBPHYCTRL_OTGBASE_OFFSET	0x608
+#define MX35_USBPHYCTRL_OFFSET		0x600
+#define USBPHYCTRL_OTGBASE_OFFSET	0x8
 #define USBPHYCTRL_EVDO			(1 << 23)
 
 int fsl_udc_clk_init(struct platform_device *pdev)
@@ -59,7 +58,7 @@
 	clk_prepare_enable(mxc_per_clk);
 
 	/* make sure USB_CLK is running at 60 MHz +/- 1000 Hz */
-	if (!cpu_is_mx51()) {
+	if (!strcmp(pdev->id_entry->name, "imx-udc-mx27")) {
 		freq = clk_get_rate(mxc_per_clk);
 		if (pdata->phy_mode != FSL_USB2_PHY_ULPI &&
 		    (freq < 59999000 || freq > 60001000)) {
@@ -79,27 +78,40 @@
 	return ret;
 }
 
-void fsl_udc_clk_finalize(struct platform_device *pdev)
+int fsl_udc_clk_finalize(struct platform_device *pdev)
 {
 	struct fsl_usb2_platform_data *pdata = pdev->dev.platform_data;
-	if (cpu_is_mx35()) {
-		unsigned int v;
+	int ret = 0;
 
-		/* workaround ENGcm09152 for i.MX35 */
-		if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
-			v = readl(MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-					USBPHYCTRL_OTGBASE_OFFSET));
-			writel(v | USBPHYCTRL_EVDO,
-				MX35_IO_ADDRESS(MX35_USB_BASE_ADDR +
-					USBPHYCTRL_OTGBASE_OFFSET));
+	/* workaround ENGcm09152 for i.MX35 */
+	if (pdata->workaround & FLS_USB2_WORKAROUND_ENGCM09152) {
+		unsigned int v;
+		struct resource *res = platform_get_resource
+			(pdev, IORESOURCE_MEM, 0);
+		void __iomem *phy_regs = ioremap(res->start +
+						MX35_USBPHYCTRL_OFFSET, 512);
+		if (!phy_regs) {
+			dev_err(&pdev->dev, "ioremap for phy address fails\n");
+			ret = -EINVAL;
+			goto ioremap_err;
 		}
+
+		v = readl(phy_regs + USBPHYCTRL_OTGBASE_OFFSET);
+		writel(v | USBPHYCTRL_EVDO,
+			phy_regs + USBPHYCTRL_OTGBASE_OFFSET);
+
+		iounmap(phy_regs);
 	}
 
+
+ioremap_err:
 	/* ULPI transceivers don't need usbpll */
 	if (pdata->phy_mode == FSL_USB2_PHY_ULPI) {
 		clk_disable_unprepare(mxc_per_clk);
 		mxc_per_clk = NULL;
 	}
+
+	return ret;
 }
 
 void fsl_udc_clk_release(void)
diff --git a/drivers/usb/gadget/fsl_udc_core.c b/drivers/usb/gadget/fsl_udc_core.c
index c19f7f1..667275c 100644
--- a/drivers/usb/gadget/fsl_udc_core.c
+++ b/drivers/usb/gadget/fsl_udc_core.c
@@ -41,6 +41,7 @@
 #include <linux/fsl_devices.h>
 #include <linux/dmapool.h>
 #include <linux/delay.h>
+#include <linux/of_device.h>
 
 #include <asm/byteorder.h>
 #include <asm/io.h>
@@ -2438,11 +2439,6 @@
 	unsigned int i;
 	u32 dccparams;
 
-	if (strcmp(pdev->name, driver_name)) {
-		VDBG("Wrong device");
-		return -ENODEV;
-	}
-
 	udc_controller = kzalloc(sizeof(struct fsl_udc), GFP_KERNEL);
 	if (udc_controller == NULL) {
 		ERR("malloc udc failed\n");
@@ -2547,7 +2543,9 @@
 		dr_controller_setup(udc_controller);
 	}
 
-	fsl_udc_clk_finalize(pdev);
+	ret = fsl_udc_clk_finalize(pdev);
+	if (ret)
+		goto err_free_irq;
 
 	/* Setup gadget structure */
 	udc_controller->gadget.ops = &fsl_gadget_ops;
@@ -2756,22 +2754,32 @@
 
 	return fsl_udc_resume(NULL);
 }
-
 /*-------------------------------------------------------------------------
 	Register entry point for the peripheral controller driver
 --------------------------------------------------------------------------*/
-
+static const struct platform_device_id fsl_udc_devtype[] = {
+	{
+		.name = "imx-udc-mx27",
+	}, {
+		.name = "imx-udc-mx51",
+	}, {
+		/* sentinel */
+	}
+};
+MODULE_DEVICE_TABLE(platform, fsl_udc_devtype);
 static struct platform_driver udc_driver = {
-	.remove  = __exit_p(fsl_udc_remove),
+	.remove		= __exit_p(fsl_udc_remove),
+	/* Just for FSL i.mx SoC currently */
+	.id_table	= fsl_udc_devtype,
 	/* these suspend and resume are not usb suspend and resume */
-	.suspend = fsl_udc_suspend,
-	.resume  = fsl_udc_resume,
-	.driver  = {
-		.name = (char *)driver_name,
-		.owner = THIS_MODULE,
-		/* udc suspend/resume called from OTG driver */
-		.suspend = fsl_udc_otg_suspend,
-		.resume  = fsl_udc_otg_resume,
+	.suspend	= fsl_udc_suspend,
+	.resume		= fsl_udc_resume,
+	.driver		= {
+			.name = (char *)driver_name,
+			.owner = THIS_MODULE,
+			/* udc suspend/resume called from OTG driver */
+			.suspend = fsl_udc_otg_suspend,
+			.resume  = fsl_udc_otg_resume,
 	},
 };
 
diff --git a/drivers/usb/gadget/fsl_usb2_udc.h b/drivers/usb/gadget/fsl_usb2_udc.h
index f61a967..c6703bb 100644
--- a/drivers/usb/gadget/fsl_usb2_udc.h
+++ b/drivers/usb/gadget/fsl_usb2_udc.h
@@ -592,15 +592,16 @@
 struct platform_device;
 #ifdef CONFIG_ARCH_MXC
 int fsl_udc_clk_init(struct platform_device *pdev);
-void fsl_udc_clk_finalize(struct platform_device *pdev);
+int fsl_udc_clk_finalize(struct platform_device *pdev);
 void fsl_udc_clk_release(void);
 #else
 static inline int fsl_udc_clk_init(struct platform_device *pdev)
 {
 	return 0;
 }
-static inline void fsl_udc_clk_finalize(struct platform_device *pdev)
+static inline int fsl_udc_clk_finalize(struct platform_device *pdev)
 {
+	return 0;
 }
 static inline void fsl_udc_clk_release(void)
 {
diff --git a/drivers/usb/gadget/mv_udc_core.c b/drivers/usb/gadget/mv_udc_core.c
index 379aac7..6e8b127 100644
--- a/drivers/usb/gadget/mv_udc_core.c
+++ b/drivers/usb/gadget/mv_udc_core.c
@@ -1012,7 +1012,7 @@
 	unsigned int i;
 
 	for (i = 0; i < udc->clknum; i++)
-		clk_enable(udc->clk[i]);
+		clk_prepare_enable(udc->clk[i]);
 }
 
 static void udc_clock_disable(struct mv_udc *udc)
@@ -1020,7 +1020,7 @@
 	unsigned int i;
 
 	for (i = 0; i < udc->clknum; i++)
-		clk_disable(udc->clk[i]);
+		clk_disable_unprepare(udc->clk[i]);
 }
 
 static void udc_stop(struct mv_udc *udc)
diff --git a/drivers/usb/gadget/s3c-hsotg.c b/drivers/usb/gadget/s3c-hsotg.c
index 141971d..439c3f9 100644
--- a/drivers/usb/gadget/s3c-hsotg.c
+++ b/drivers/usb/gadget/s3c-hsotg.c
@@ -3477,12 +3477,11 @@
 /**
  * s3c_hsotg_release - release callback for hsotg device
  * @dev: Device to for which release is called
+ *
+ * Nothing to do as the resource is allocated using devm_ API.
  */
 static void s3c_hsotg_release(struct device *dev)
 {
-	struct s3c_hsotg *hsotg = dev_get_drvdata(dev);
-
-	kfree(hsotg);
 }
 
 /**
diff --git a/drivers/usb/gadget/tcm_usb_gadget.c b/drivers/usb/gadget/tcm_usb_gadget.c
index 4f7f76f..7cacd6a 100644
--- a/drivers/usb/gadget/tcm_usb_gadget.c
+++ b/drivers/usb/gadget/tcm_usb_gadget.c
@@ -1794,9 +1794,10 @@
 	tpg->tpg_nexus = NULL;
 
 	kfree(tv_nexus);
+	ret = 0;
 out:
 	mutex_unlock(&tpg->tpg_mutex);
-	return 0;
+	return ret;
 }
 
 static ssize_t tcm_usbg_tpg_store_nexus(
diff --git a/drivers/usb/gadget/u_serial.c b/drivers/usb/gadget/u_serial.c
index d0f9548..598dcc1 100644
--- a/drivers/usb/gadget/u_serial.c
+++ b/drivers/usb/gadget/u_serial.c
@@ -887,7 +887,7 @@
 	pr_debug("gs_close: ttyGS%d (%p,%p) done!\n",
 			port->port_num, tty, file);
 
-	wake_up_interruptible(&port->port.close_wait);
+	wake_up(&port->port.close_wait);
 exit:
 	spin_unlock_irq(&port->port_lock);
 }
diff --git a/drivers/usb/host/Kconfig b/drivers/usb/host/Kconfig
index d6bb128..3a21c5d 100644
--- a/drivers/usb/host/Kconfig
+++ b/drivers/usb/host/Kconfig
@@ -148,7 +148,7 @@
 	  Variation of ARC USB block used in some Freescale chips.
 
 config USB_EHCI_MXC
-	bool "Support for Freescale i.MX on-chip EHCI USB controller"
+	tristate "Support for Freescale i.MX on-chip EHCI USB controller"
 	depends on USB_EHCI_HCD && ARCH_MXC
 	select USB_EHCI_ROOT_HUB_TT
 	---help---
diff --git a/drivers/usb/host/Makefile b/drivers/usb/host/Makefile
index 1eb4c30..001fbff 100644
--- a/drivers/usb/host/Makefile
+++ b/drivers/usb/host/Makefile
@@ -26,6 +26,7 @@
 obj-$(CONFIG_USB_EHCI_HCD)	+= ehci-hcd.o
 obj-$(CONFIG_USB_EHCI_PCI)	+= ehci-pci.o
 obj-$(CONFIG_USB_EHCI_HCD_PLATFORM)	+= ehci-platform.o
+obj-$(CONFIG_USB_EHCI_MXC)	+= ehci-mxc.o
 
 obj-$(CONFIG_USB_OXU210HP_HCD)	+= oxu210hp-hcd.o
 obj-$(CONFIG_USB_ISP116X_HCD)	+= isp116x-hcd.o
diff --git a/drivers/usb/host/ehci-fsl.c b/drivers/usb/host/ehci-fsl.c
index fd9b542..d81d2fc 100644
--- a/drivers/usb/host/ehci-fsl.c
+++ b/drivers/usb/host/ehci-fsl.c
@@ -230,7 +230,7 @@
 
 	switch (phy_mode) {
 	case FSL_USB2_PHY_ULPI:
-		if (pdata->controller_ver) {
+		if (pdata->have_sysif_regs && pdata->controller_ver) {
 			/* controller version 1.6 or above */
 			setbits32(non_ehci + FSL_SOC_USB_CTRL,
 					ULPI_PHY_CLK_SEL);
@@ -251,7 +251,7 @@
 		portsc |= PORT_PTS_PTW;
 		/* fall through */
 	case FSL_USB2_PHY_UTMI:
-		if (pdata->controller_ver) {
+		if (pdata->have_sysif_regs && pdata->controller_ver) {
 			/* controller version 1.6 or above */
 			setbits32(non_ehci + FSL_SOC_USB_CTRL, UTMI_PHY_EN);
 			mdelay(FSL_UTMI_PHY_DLY);  /* Delay for UTMI PHY CLK to
@@ -267,7 +267,8 @@
 		break;
 	}
 
-	if (pdata->controller_ver && (phy_mode == FSL_USB2_PHY_ULPI)) {
+	if (pdata->have_sysif_regs && pdata->controller_ver &&
+	    (phy_mode == FSL_USB2_PHY_ULPI)) {
 		/* check PHY_CLK_VALID to get phy clk valid */
 		if (!spin_event_timeout(in_be32(non_ehci + FSL_SOC_USB_CTRL) &
 				PHY_CLK_VALID, FSL_USB_PHY_CLK_TIMEOUT, 0)) {
@@ -278,7 +279,7 @@
 
 	ehci_writel(ehci, portsc, &ehci->regs->port_status[port_offset]);
 
-	if (phy_mode != FSL_USB2_PHY_ULPI)
+	if (phy_mode != FSL_USB2_PHY_ULPI && pdata->have_sysif_regs)
 		setbits32(non_ehci + FSL_SOC_USB_CTRL, USB_CTRL_USB_EN);
 
 	return 0;
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c97503b..09537b2 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -74,10 +74,6 @@
 #undef VERBOSE_DEBUG
 #undef EHCI_URB_TRACE
 
-#ifdef DEBUG
-#define EHCI_STATS
-#endif
-
 /* magic numbers that can affect system performance */
 #define	EHCI_TUNE_CERR		3	/* 0-3 qtd retries; 0 == don't stop */
 #define	EHCI_TUNE_RL_HS		4	/* nak throttle; see 4.9 */
@@ -1250,11 +1246,6 @@
 #define	PLATFORM_DRIVER		ehci_fsl_driver
 #endif
 
-#ifdef CONFIG_USB_EHCI_MXC
-#include "ehci-mxc.c"
-#define PLATFORM_DRIVER		ehci_mxc_driver
-#endif
-
 #ifdef CONFIG_USB_EHCI_SH
 #include "ehci-sh.c"
 #define PLATFORM_DRIVER		ehci_hcd_sh_driver
@@ -1352,7 +1343,8 @@
 
 #if !IS_ENABLED(CONFIG_USB_EHCI_PCI) && \
 	!IS_ENABLED(CONFIG_USB_EHCI_HCD_PLATFORM) && \
-	!defined(CONFIG_USB_CHIPIDEA_HOST) && \
+	!IS_ENABLED(CONFIG_USB_CHIPIDEA_HOST) && \
+	!IS_ENABLED(CONFIG_USB_EHCI_MXC) && \
 	!defined(PLATFORM_DRIVER) && \
 	!defined(PS3_SYSTEM_BUS_DRIVER) && \
 	!defined(OF_PLATFORM_DRIVER) && \
diff --git a/drivers/usb/host/ehci-mv.c b/drivers/usb/host/ehci-mv.c
index f7bfc0b..6c56297 100644
--- a/drivers/usb/host/ehci-mv.c
+++ b/drivers/usb/host/ehci-mv.c
@@ -43,7 +43,7 @@
 	unsigned int i;
 
 	for (i = 0; i < ehci_mv->clknum; i++)
-		clk_enable(ehci_mv->clk[i]);
+		clk_prepare_enable(ehci_mv->clk[i]);
 }
 
 static void ehci_clock_disable(struct ehci_hcd_mv *ehci_mv)
@@ -51,7 +51,7 @@
 	unsigned int i;
 
 	for (i = 0; i < ehci_mv->clknum; i++)
-		clk_disable(ehci_mv->clk[i]);
+		clk_disable_unprepare(ehci_mv->clk[i]);
 }
 
 static int mv_ehci_enable(struct ehci_hcd_mv *ehci_mv)
diff --git a/drivers/usb/host/ehci-mxc.c b/drivers/usb/host/ehci-mxc.c
index ec7f5d2..dedb80b 100644
--- a/drivers/usb/host/ehci-mxc.c
+++ b/drivers/usb/host/ehci-mxc.c
@@ -17,75 +17,38 @@
  * Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/io.h>
 #include <linux/platform_device.h>
 #include <linux/clk.h>
 #include <linux/delay.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
 #include <linux/slab.h>
+#include <linux/usb.h>
+#include <linux/usb/hcd.h>
 
 #include <linux/platform_data/usb-ehci-mxc.h>
 
 #include <asm/mach-types.h>
 
+#include "ehci.h"
+
+#define DRIVER_DESC "Freescale On-Chip EHCI Host driver"
+
+static const char hcd_name[] = "ehci-mxc";
+
 #define ULPI_VIEWPORT_OFFSET	0x170
 
 struct ehci_mxc_priv {
 	struct clk *usbclk, *ahbclk, *phyclk;
-	struct usb_hcd *hcd;
 };
 
-/* called during probe() after chip reset completes */
-static int ehci_mxc_setup(struct usb_hcd *hcd)
-{
-	hcd->has_tt = 1;
+static struct hc_driver __read_mostly ehci_mxc_hc_driver;
 
-	return ehci_setup(hcd);
-}
-
-static const struct hc_driver ehci_mxc_hc_driver = {
-	.description = hcd_name,
-	.product_desc = "Freescale On-Chip EHCI Host Controller",
-	.hcd_priv_size = sizeof(struct ehci_hcd),
-
-	/*
-	 * generic hardware linkage
-	 */
-	.irq = ehci_irq,
-	.flags = HCD_USB2 | HCD_MEMORY,
-
-	/*
-	 * basic lifecycle operations
-	 */
-	.reset = ehci_mxc_setup,
-	.start = ehci_run,
-	.stop = ehci_stop,
-	.shutdown = ehci_shutdown,
-
-	/*
-	 * managing i/o requests and associated device resources
-	 */
-	.urb_enqueue = ehci_urb_enqueue,
-	.urb_dequeue = ehci_urb_dequeue,
-	.endpoint_disable = ehci_endpoint_disable,
-	.endpoint_reset = ehci_endpoint_reset,
-
-	/*
-	 * scheduling support
-	 */
-	.get_frame_number = ehci_get_frame,
-
-	/*
-	 * root hub support
-	 */
-	.hub_status_data = ehci_hub_status_data,
-	.hub_control = ehci_hub_control,
-	.bus_suspend = ehci_bus_suspend,
-	.bus_resume = ehci_bus_resume,
-	.relinquish_port = ehci_relinquish_port,
-	.port_handed_over = ehci_port_handed_over,
-
-	.clear_tt_buffer_complete = ehci_clear_tt_buffer_complete,
+static const struct ehci_driver_overrides ehci_mxc_overrides __initdata = {
+	.extra_priv_size =	sizeof(struct ehci_mxc_priv),
 };
 
 static int ehci_mxc_drv_probe(struct platform_device *pdev)
@@ -112,12 +75,6 @@
 	if (!hcd)
 		return -ENOMEM;
 
-	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		ret = -ENOMEM;
-		goto err_alloc;
-	}
-
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
 		dev_err(dev, "Found HC with no register addr. Check setup!\n");
@@ -135,6 +92,10 @@
 		goto err_alloc;
 	}
 
+	hcd->has_tt = 1;
+	ehci = hcd_to_ehci(hcd);
+	priv = (struct ehci_mxc_priv *) ehci->priv;
+
 	/* enable clocks */
 	priv->usbclk = devm_clk_get(&pdev->dev, "ipg");
 	if (IS_ERR(priv->usbclk)) {
@@ -169,8 +130,6 @@
 		mdelay(10);
 	}
 
-	ehci = hcd_to_ehci(hcd);
-
 	/* EHCI registers start at offset 0x100 */
 	ehci->caps = hcd->regs + 0x100;
 	ehci->regs = hcd->regs + 0x100 +
@@ -198,8 +157,7 @@
 		}
 	}
 
-	priv->hcd = hcd;
-	platform_set_drvdata(pdev, priv);
+	platform_set_drvdata(pdev, hcd);
 
 	ret = usb_add_hcd(hcd, irq, IRQF_SHARED);
 	if (ret)
@@ -244,8 +202,11 @@
 static int __exit ehci_mxc_drv_remove(struct platform_device *pdev)
 {
 	struct mxc_usbh_platform_data *pdata = pdev->dev.platform_data;
-	struct ehci_mxc_priv *priv = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = priv->hcd;
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
+	struct ehci_hcd *ehci = hcd_to_ehci(hcd);
+	struct ehci_mxc_priv *priv = (struct ehci_mxc_priv *) ehci->priv;
+
+	usb_remove_hcd(hcd);
 
 	if (pdata && pdata->exit)
 		pdata->exit(pdev);
@@ -253,23 +214,20 @@
 	if (pdata->otg)
 		usb_phy_shutdown(pdata->otg);
 
-	usb_remove_hcd(hcd);
-	usb_put_hcd(hcd);
-	platform_set_drvdata(pdev, NULL);
-
 	clk_disable_unprepare(priv->usbclk);
 	clk_disable_unprepare(priv->ahbclk);
 
 	if (priv->phyclk)
 		clk_disable_unprepare(priv->phyclk);
 
+	usb_put_hcd(hcd);
+	platform_set_drvdata(pdev, NULL);
 	return 0;
 }
 
 static void ehci_mxc_drv_shutdown(struct platform_device *pdev)
 {
-	struct ehci_mxc_priv *priv = platform_get_drvdata(pdev);
-	struct usb_hcd *hcd = priv->hcd;
+	struct usb_hcd *hcd = platform_get_drvdata(pdev);
 
 	if (hcd->driver->shutdown)
 		hcd->driver->shutdown(hcd);
@@ -279,9 +237,31 @@
 
 static struct platform_driver ehci_mxc_driver = {
 	.probe = ehci_mxc_drv_probe,
-	.remove = __exit_p(ehci_mxc_drv_remove),
+	.remove = ehci_mxc_drv_remove,
 	.shutdown = ehci_mxc_drv_shutdown,
 	.driver = {
 		   .name = "mxc-ehci",
 	},
 };
+
+static int __init ehci_mxc_init(void)
+{
+	if (usb_disabled())
+		return -ENODEV;
+
+	pr_info("%s: " DRIVER_DESC "\n", hcd_name);
+
+	ehci_init_driver(&ehci_mxc_hc_driver, &ehci_mxc_overrides);
+	return platform_driver_register(&ehci_mxc_driver);
+}
+module_init(ehci_mxc_init);
+
+static void __exit ehci_mxc_cleanup(void)
+{
+	platform_driver_unregister(&ehci_mxc_driver);
+}
+module_exit(ehci_mxc_cleanup);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Sascha Hauer");
+MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index dabb204..170b939 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -200,6 +200,26 @@
 		break;
 	}
 
+	/* optional debug port, normally in the first BAR */
+	temp = pci_find_capability(pdev, PCI_CAP_ID_DBG);
+	if (temp) {
+		pci_read_config_dword(pdev, temp, &temp);
+		temp >>= 16;
+		if (((temp >> 13) & 7) == 1) {
+			u32 hcs_params = ehci_readl(ehci,
+						    &ehci->caps->hcs_params);
+
+			temp &= 0x1fff;
+			ehci->debug = hcd->regs + temp;
+			temp = ehci_readl(ehci, &ehci->debug->control);
+			ehci_info(ehci, "debug port %d%s\n",
+				  HCS_DEBUG_PORT(hcs_params),
+				  (temp & DBGP_ENABLED) ? " IN USE" : "");
+			if (!(temp & DBGP_ENABLED))
+				ehci->debug = NULL;
+		}
+	}
+
 	retval = ehci_setup(hcd);
 	if (retval)
 		return retval;
@@ -228,25 +248,6 @@
 		break;
 	}
 
-	/* optional debug port, normally in the first BAR */
-	temp = pci_find_capability(pdev, 0x0a);
-	if (temp) {
-		pci_read_config_dword(pdev, temp, &temp);
-		temp >>= 16;
-		if ((temp & (3 << 13)) == (1 << 13)) {
-			temp &= 0x1fff;
-			ehci->debug = hcd->regs + temp;
-			temp = ehci_readl(ehci, &ehci->debug->control);
-			ehci_info(ehci, "debug port %d%s\n",
-				HCS_DEBUG_PORT(ehci->hcs_params),
-				(temp & DBGP_ENABLED)
-					? " IN USE"
-					: "");
-			if (!(temp & DBGP_ENABLED))
-				ehci->debug = NULL;
-		}
-	}
-
 	/* at least the Genesys GL880S needs fixup here */
 	temp = HCS_N_CC(ehci->hcs_params) * HCS_N_PCC(ehci->hcs_params);
 	temp &= 0x0f;
diff --git a/drivers/usb/host/ehci-tegra.c b/drivers/usb/host/ehci-tegra.c
index acf1755..568aecc 100644
--- a/drivers/usb/host/ehci-tegra.c
+++ b/drivers/usb/host/ehci-tegra.c
@@ -2,7 +2,7 @@
  * EHCI-compliant USB host controller driver for NVIDIA Tegra SoCs
  *
  * Copyright (C) 2010 Google, Inc.
- * Copyright (C) 2009 NVIDIA Corporation
+ * Copyright (C) 2009 - 2013 NVIDIA Corporation
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of the GNU General Public License as published by the
@@ -26,23 +26,28 @@
 #include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/pm_runtime.h>
-
+#include <linux/usb/ehci_def.h>
 #include <linux/usb/tegra_usb_phy.h>
 
 #define TEGRA_USB_BASE			0xC5000000
 #define TEGRA_USB2_BASE			0xC5004000
 #define TEGRA_USB3_BASE			0xC5008000
 
+/* PORTSC registers */
+#define TEGRA_USB_PORTSC1			0x184
+#define TEGRA_USB_PORTSC1_PTS(x)	(((x) & 0x3) << 30)
+#define TEGRA_USB_PORTSC1_PHCD	(1 << 23)
+
 #define TEGRA_USB_DMA_ALIGN 32
 
 struct tegra_ehci_hcd {
 	struct ehci_hcd *ehci;
 	struct tegra_usb_phy *phy;
 	struct clk *clk;
-	struct clk *emc_clk;
 	struct usb_phy *transceiver;
 	int host_resumed;
 	int port_resuming;
+	bool needs_double_reset;
 	enum tegra_usb_phy_port_speed port_speed;
 };
 
@@ -50,9 +55,8 @@
 {
 	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
 
-	clk_prepare_enable(tegra->emc_clk);
 	clk_prepare_enable(tegra->clk);
-	usb_phy_set_suspend(&tegra->phy->u_phy, 0);
+	usb_phy_set_suspend(hcd->phy, 0);
 	tegra->host_resumed = 1;
 }
 
@@ -61,9 +65,8 @@
 	struct tegra_ehci_hcd *tegra = dev_get_drvdata(hcd->self.controller);
 
 	tegra->host_resumed = 0;
-	usb_phy_set_suspend(&tegra->phy->u_phy, 1);
+	usb_phy_set_suspend(hcd->phy, 1);
 	clk_disable_unprepare(tegra->clk);
-	clk_disable_unprepare(tegra->emc_clk);
 }
 
 static int tegra_ehci_internal_port_reset(
@@ -156,7 +159,7 @@
 		if (tegra->port_resuming && !(temp & PORT_SUSPEND)) {
 			/* Resume completed, re-enable disconnect detection */
 			tegra->port_resuming = 0;
-			tegra_usb_phy_postresume(tegra->phy);
+			tegra_usb_phy_postresume(hcd->phy);
 		}
 	}
 
@@ -184,7 +187,7 @@
 	}
 
 	/* For USB1 port we need to issue Port Reset twice internally */
-	if (tegra->phy->instance == 0 &&
+	if (tegra->needs_double_reset &&
 	   (typeReq == SetPortFeature && wValue == USB_PORT_FEAT_RESET)) {
 		spin_unlock_irqrestore(&ehci->lock, flags);
 		return tegra_ehci_internal_port_reset(ehci, status_reg);
@@ -209,7 +212,7 @@
 			goto done;
 
 		/* Disable disconnect detection during port resume */
-		tegra_usb_phy_preresume(tegra->phy);
+		tegra_usb_phy_preresume(hcd->phy);
 
 		ehci->reset_done[wIndex-1] = jiffies + msecs_to_jiffies(25);
 
@@ -473,7 +476,7 @@
 	}
 
 	/* Force the phy to keep data lines in suspend state */
-	tegra_ehci_phy_restore_start(tegra->phy, tegra->port_speed);
+	tegra_ehci_phy_restore_start(hcd->phy, tegra->port_speed);
 
 	/* Enable host mode */
 	tdi_reset(ehci);
@@ -540,17 +543,17 @@
 		}
 	}
 
-	tegra_ehci_phy_restore_end(tegra->phy);
+	tegra_ehci_phy_restore_end(hcd->phy);
 	goto done;
 
  restart:
 	if (tegra->port_speed <= TEGRA_USB_PHY_PORT_SPEED_HIGH)
-		tegra_ehci_phy_restore_end(tegra->phy);
+		tegra_ehci_phy_restore_end(hcd->phy);
 
 	tegra_ehci_restart(hcd);
 
  done:
-	tegra_usb_phy_preresume(tegra->phy);
+	tegra_usb_phy_preresume(hcd->phy);
 	tegra->port_resuming = 1;
 	return 0;
 }
@@ -604,6 +607,37 @@
 
 #endif
 
+/* Bits of PORTSC1, which will get cleared by writing 1 into them */
+#define TEGRA_PORTSC1_RWC_BITS (PORT_CSC | PORT_PEC | PORT_OCC)
+
+void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val)
+{
+	unsigned long val;
+	struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
+	void __iomem *base = hcd->regs;
+
+	val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS;
+	val &= ~TEGRA_USB_PORTSC1_PTS(3);
+	val |= TEGRA_USB_PORTSC1_PTS(pts_val & 3);
+	writel(val, base + TEGRA_USB_PORTSC1);
+}
+EXPORT_SYMBOL_GPL(tegra_ehci_set_pts);
+
+void tegra_ehci_set_phcd(struct usb_phy *x, bool enable)
+{
+	unsigned long val;
+	struct usb_hcd *hcd = bus_to_hcd(x->otg->host);
+	void __iomem *base = hcd->regs;
+
+	val = readl(base + TEGRA_USB_PORTSC1) & ~TEGRA_PORTSC1_RWC_BITS;
+	if (enable)
+		val |= TEGRA_USB_PORTSC1_PHCD;
+	else
+		val &= ~TEGRA_USB_PORTSC1_PHCD;
+	writel(val, base + TEGRA_USB_PORTSC1);
+}
+EXPORT_SYMBOL_GPL(tegra_ehci_set_phcd);
+
 static u64 tegra_ehci_dma_mask = DMA_BIT_MASK(32);
 
 static int tegra_ehci_probe(struct platform_device *pdev)
@@ -615,6 +649,7 @@
 	int err = 0;
 	int irq;
 	int instance = pdev->id;
+	struct usb_phy *u_phy;
 
 	pdata = pdev->dev.platform_data;
 	if (!pdata) {
@@ -656,15 +691,8 @@
 	if (err)
 		goto fail_clk;
 
-	tegra->emc_clk = devm_clk_get(&pdev->dev, "emc");
-	if (IS_ERR(tegra->emc_clk)) {
-		dev_err(&pdev->dev, "Can't get emc clock\n");
-		err = PTR_ERR(tegra->emc_clk);
-		goto fail_emc_clk;
-	}
-
-	clk_prepare_enable(tegra->emc_clk);
-	clk_set_rate(tegra->emc_clk, 400000000);
+	tegra->needs_double_reset = of_property_read_bool(pdev->dev.of_node,
+		"nvidia,needs-double-reset");
 
 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!res) {
@@ -712,9 +740,19 @@
 		goto fail_io;
 	}
 
-	usb_phy_init(&tegra->phy->u_phy);
+	hcd->phy = u_phy = &tegra->phy->u_phy;
+	usb_phy_init(hcd->phy);
 
-	err = usb_phy_set_suspend(&tegra->phy->u_phy, 0);
+	u_phy->otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
+			     GFP_KERNEL);
+	if (!u_phy->otg) {
+		dev_err(&pdev->dev, "Failed to alloc memory for otg\n");
+		err = -ENOMEM;
+		goto fail_io;
+	}
+	u_phy->otg->host = hcd_to_bus(hcd);
+
+	err = usb_phy_set_suspend(hcd->phy, 0);
 	if (err) {
 		dev_err(&pdev->dev, "Failed to power on the phy\n");
 		goto fail;
@@ -760,10 +798,8 @@
 	if (!IS_ERR_OR_NULL(tegra->transceiver))
 		otg_set_host(tegra->transceiver->otg, NULL);
 #endif
-	usb_phy_shutdown(&tegra->phy->u_phy);
+	usb_phy_shutdown(hcd->phy);
 fail_io:
-	clk_disable_unprepare(tegra->emc_clk);
-fail_emc_clk:
 	clk_disable_unprepare(tegra->clk);
 fail_clk:
 	usb_put_hcd(hcd);
@@ -784,15 +820,12 @@
 		otg_set_host(tegra->transceiver->otg, NULL);
 #endif
 
+	usb_phy_shutdown(hcd->phy);
 	usb_remove_hcd(hcd);
 	usb_put_hcd(hcd);
 
-	usb_phy_shutdown(&tegra->phy->u_phy);
-
 	clk_disable_unprepare(tegra->clk);
 
-	clk_disable_unprepare(tegra->emc_clk);
-
 	return 0;
 }
 
diff --git a/drivers/usb/host/ehci.h b/drivers/usb/host/ehci.h
index 9dadc71..36c3a82 100644
--- a/drivers/usb/host/ehci.h
+++ b/drivers/usb/host/ehci.h
@@ -38,6 +38,10 @@
 #endif
 
 /* statistics can be kept for tuning/monitoring */
+#ifdef DEBUG
+#define EHCI_STATS
+#endif
+
 struct ehci_stats {
 	/* irq usage */
 	unsigned long		normal;
@@ -221,6 +225,9 @@
 #ifdef DEBUG
 	struct dentry		*debug_dir;
 #endif
+
+	/* platform-specific data -- must come last */
+	unsigned long		priv[0] __aligned(sizeof(s64));
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
diff --git a/drivers/usb/host/fsl-mph-dr-of.c b/drivers/usb/host/fsl-mph-dr-of.c
index 5105127..11e0b79 100644
--- a/drivers/usb/host/fsl-mph-dr-of.c
+++ b/drivers/usb/host/fsl-mph-dr-of.c
@@ -142,6 +142,9 @@
 			return ver;
 	}
 
+	if (of_device_is_compatible(np, "fsl,mpc5121-usb2-dr"))
+		return FSL_USB_VER_OLD;
+
 	if (of_device_is_compatible(np, "fsl-usb2-mph")) {
 		if (of_device_is_compatible(np, "fsl-usb2-mph-v1.6"))
 			ver = FSL_USB_VER_1_6;
diff --git a/drivers/usb/host/imx21-hcd.c b/drivers/usb/host/imx21-hcd.c
index bd6a744..f0ebe8e 100644
--- a/drivers/usb/host/imx21-hcd.c
+++ b/drivers/usb/host/imx21-hcd.c
@@ -58,6 +58,7 @@
 #include <linux/usb.h>
 #include <linux/usb/hcd.h>
 #include <linux/dma-mapping.h>
+#include <linux/module.h>
 
 #include "imx21-hcd.h"
 
diff --git a/drivers/usb/host/ohci-tmio.c b/drivers/usb/host/ohci-tmio.c
index d370245..5e3a6de 100644
--- a/drivers/usb/host/ohci-tmio.c
+++ b/drivers/usb/host/ohci-tmio.c
@@ -128,7 +128,8 @@
 	tmio_iowrite8(2, tmio->ccr + CCR_INTC);
 
 	dev_info(&dev->dev, "revision %d @ 0x%08llx, irq %d\n",
-			tmio_ioread8(tmio->ccr + CCR_REVID), hcd->rsrc_start, hcd->irq);
+			tmio_ioread8(tmio->ccr + CCR_REVID),
+			(u64) hcd->rsrc_start, hcd->irq);
 }
 
 static int ohci_tmio_start(struct usb_hcd *hcd)
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index 4b9e9ab..4f64d24 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -447,6 +447,10 @@
 		return IRQ_NONE;
 	uhci_writew(uhci, status, USBSTS);		/* Clear it */
 
+	spin_lock(&uhci->lock);
+	if (unlikely(!uhci->is_initialized))	/* not yet configured */
+		goto done;
+
 	if (status & ~(USBSTS_USBINT | USBSTS_ERROR | USBSTS_RD)) {
 		if (status & USBSTS_HSE)
 			dev_err(uhci_dev(uhci), "host system error, "
@@ -455,7 +459,6 @@
 			dev_err(uhci_dev(uhci), "host controller process "
 					"error, something bad happened!\n");
 		if (status & USBSTS_HCH) {
-			spin_lock(&uhci->lock);
 			if (uhci->rh_state >= UHCI_RH_RUNNING) {
 				dev_err(uhci_dev(uhci),
 					"host controller halted, "
@@ -473,15 +476,15 @@
 				 * pending unlinks */
 				mod_timer(&hcd->rh_timer, jiffies);
 			}
-			spin_unlock(&uhci->lock);
 		}
 	}
 
-	if (status & USBSTS_RD)
+	if (status & USBSTS_RD) {
+		spin_unlock(&uhci->lock);
 		usb_hcd_poll_rh_status(hcd);
-	else {
-		spin_lock(&uhci->lock);
+	} else {
 		uhci_scan_schedule(uhci);
+ done:
 		spin_unlock(&uhci->lock);
 	}
 
@@ -662,9 +665,9 @@
 	 */
 	mb();
 
+	spin_lock_irq(&uhci->lock);
 	configure_hc(uhci);
 	uhci->is_initialized = 1;
-	spin_lock_irq(&uhci->lock);
 	start_rh(uhci);
 	spin_unlock_irq(&uhci->lock);
 	return 0;
diff --git a/drivers/usb/host/xhci-hub.c b/drivers/usb/host/xhci-hub.c
index a686cf4..6891442 100644
--- a/drivers/usb/host/xhci-hub.c
+++ b/drivers/usb/host/xhci-hub.c
@@ -761,12 +761,39 @@
 			break;
 		case USB_PORT_FEAT_LINK_STATE:
 			temp = xhci_readl(xhci, port_array[wIndex]);
+
+			/* Disable port */
+			if (link_state == USB_SS_PORT_LS_SS_DISABLED) {
+				xhci_dbg(xhci, "Disable port %d\n", wIndex);
+				temp = xhci_port_state_to_neutral(temp);
+				/*
+				 * Clear all change bits, so that we get a new
+				 * connection event.
+				 */
+				temp |= PORT_CSC | PORT_PEC | PORT_WRC |
+					PORT_OCC | PORT_RC | PORT_PLC |
+					PORT_CEC;
+				xhci_writel(xhci, temp | PORT_PE,
+					port_array[wIndex]);
+				temp = xhci_readl(xhci, port_array[wIndex]);
+				break;
+			}
+
+			/* Put link in RxDetect (enable port) */
+			if (link_state == USB_SS_PORT_LS_RX_DETECT) {
+				xhci_dbg(xhci, "Enable port %d\n", wIndex);
+				xhci_set_link_state(xhci, port_array, wIndex,
+						link_state);
+				temp = xhci_readl(xhci, port_array[wIndex]);
+				break;
+			}
+
 			/* Software should not attempt to set
-			 * port link state above '5' (Rx.Detect) and the port
+			 * port link state above '3' (U3) and the port
 			 * must be enabled.
 			 */
 			if ((temp & PORT_PE) == 0 ||
-				(link_state > USB_SS_PORT_LS_RX_DETECT)) {
+				(link_state > USB_SS_PORT_LS_U3)) {
 				xhci_warn(xhci, "Cannot set link state.\n");
 				goto error;
 			}
@@ -957,6 +984,7 @@
 	int max_ports;
 	__le32 __iomem **port_array;
 	struct xhci_bus_state *bus_state;
+	bool reset_change = false;
 
 	max_ports = xhci_get_ports(hcd, &port_array);
 	bus_state = &xhci->bus_state[hcd_index(hcd)];
@@ -988,6 +1016,12 @@
 			buf[(i + 1) / 8] |= 1 << (i + 1) % 8;
 			status = 1;
 		}
+		if ((temp & PORT_RC))
+			reset_change = true;
+	}
+	if (!status && !reset_change) {
+		xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
+		clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 	}
 	spin_unlock_irqrestore(&xhci->lock, flags);
 	return status ? retval : 0;
diff --git a/drivers/usb/host/xhci-mem.c b/drivers/usb/host/xhci-mem.c
index fb51c70..35616ff 100644
--- a/drivers/usb/host/xhci-mem.c
+++ b/drivers/usb/host/xhci-mem.c
@@ -1250,6 +1250,8 @@
 static unsigned int xhci_parse_microframe_interval(struct usb_device *udev,
 		struct usb_host_endpoint *ep)
 {
+	if (ep->desc.bInterval == 0)
+		return 0;
 	return xhci_microframes_to_exponent(udev, ep,
 			ep->desc.bInterval, 0, 15);
 }
diff --git a/drivers/usb/host/xhci-ring.c b/drivers/usb/host/xhci-ring.c
index cbb44b7..59fb5c6 100644
--- a/drivers/usb/host/xhci-ring.c
+++ b/drivers/usb/host/xhci-ring.c
@@ -1725,6 +1725,15 @@
 	if (bogus_port_status)
 		return;
 
+	/*
+	 * xHCI port-status-change events occur when the "or" of all the
+	 * status-change bits in the portsc register changes from 0 to 1.
+	 * New status changes won't cause an event if any other change
+	 * bits are still set.  When an event occurs, switch over to
+	 * polling to avoid losing status changes.
+	 */
+	xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
+	set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
 	spin_unlock(&xhci->lock);
 	/* Pass this up to the core */
 	usb_hcd_poll_rh_status(hcd);
diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index 5c72c43..f1f01a8 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -884,6 +884,11 @@
 			xhci->shared_hcd->state != HC_STATE_SUSPENDED)
 		return -EINVAL;
 
+	/* Don't poll the roothubs on bus suspend. */
+	xhci_dbg(xhci, "%s: stopping port polling.\n", __func__);
+	clear_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+	del_timer_sync(&hcd->rh_timer);
+
 	spin_lock_irq(&xhci->lock);
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &hcd->flags);
 	clear_bit(HCD_FLAG_HW_ACCESSIBLE, &xhci->shared_hcd->flags);
@@ -1069,6 +1074,11 @@
 	if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
 		compliance_mode_recovery_timer_init(xhci);
 
+	/* Re-enable port polling. */
+	xhci_dbg(xhci, "%s: starting port polling.\n", __func__);
+	set_bit(HCD_FLAG_POLL_RH, &hcd->flags);
+	usb_hcd_poll_rh_status(hcd);
+
 	return retval;
 }
 #endif	/* CONFIG_PM */
diff --git a/drivers/usb/misc/usbtest.c b/drivers/usb/misc/usbtest.c
index 7667b12..268148d 100644
--- a/drivers/usb/misc/usbtest.c
+++ b/drivers/usb/misc/usbtest.c
@@ -2179,7 +2179,7 @@
 		if (dev->out_pipe == 0 || !param->length || param->sglen < 4)
 			break;
 		retval = 0;
-		dev_info(&intf->dev, "TEST 17:  unlink from %d queues of "
+		dev_info(&intf->dev, "TEST 24:  unlink from %d queues of "
 				"%d %d-byte writes\n",
 				param->iterations, param->sglen, param->length);
 		for (i = param->iterations; retval == 0 && i > 0; --i) {
diff --git a/drivers/usb/musb/cppi_dma.c b/drivers/usb/musb/cppi_dma.c
index 0968dd7..f522000 100644
--- a/drivers/usb/musb/cppi_dma.c
+++ b/drivers/usb/musb/cppi_dma.c
@@ -105,7 +105,7 @@
 	musb_writel(&tx->tx_complete, 0, ptr);
 }
 
-static void __init cppi_pool_init(struct cppi *cppi, struct cppi_channel *c)
+static void cppi_pool_init(struct cppi *cppi, struct cppi_channel *c)
 {
 	int	j;
 
@@ -150,7 +150,7 @@
 	c->last_processed = NULL;
 }
 
-static int __init cppi_controller_start(struct dma_controller *c)
+static int cppi_controller_start(struct dma_controller *c)
 {
 	struct cppi	*controller;
 	void __iomem	*tibase;
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index f1c6c54..fd34867 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2298,10 +2298,7 @@
 	if (usb_disabled())
 		return 0;
 
-	pr_info("%s: version " MUSB_VERSION ", "
-		"?dma?"
-		", "
-		"otg (peripheral+host)",
+	pr_info("%s: version " MUSB_VERSION ", ?dma?, otg (peripheral+host)\n",
 		musb_driver_name);
 	return platform_driver_register(&musb_driver);
 }
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index e6f2ae8..f7d764d 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -134,6 +134,11 @@
 	DSPS_AM33XX_CONTROL_MODULE_PHYS_1,
 };
 
+#define USBPHY_CM_PWRDN		(1 << 0)
+#define USBPHY_OTG_PWRDN	(1 << 1)
+#define USBPHY_OTGVDET_EN	(1 << 19)
+#define USBPHY_OTGSESSEND_EN	(1 << 20)
+
 /**
  * musb_dsps_phy_control - phy on/off
  * @glue: struct dsps_glue *
diff --git a/drivers/usb/otg/Kconfig b/drivers/usb/otg/Kconfig
index 6223062..37962c9 100644
--- a/drivers/usb/otg/Kconfig
+++ b/drivers/usb/otg/Kconfig
@@ -110,7 +110,7 @@
 
 config FSL_USB2_OTG
 	bool "Freescale USB OTG Transceiver Driver"
-	depends on USB_EHCI_FSL && USB_GADGET_FSL_USB2 && USB_SUSPEND
+	depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_SUSPEND
 	select USB_OTG
 	select USB_OTG_UTILS
 	help
diff --git a/drivers/usb/otg/mv_otg.c b/drivers/usb/otg/mv_otg.c
index 1dd5750..eace975 100644
--- a/drivers/usb/otg/mv_otg.c
+++ b/drivers/usb/otg/mv_otg.c
@@ -240,7 +240,7 @@
 	unsigned int i;
 
 	for (i = 0; i < mvotg->clknum; i++)
-		clk_enable(mvotg->clk[i]);
+		clk_prepare_enable(mvotg->clk[i]);
 }
 
 static void otg_clock_disable(struct mv_otg *mvotg)
@@ -248,7 +248,7 @@
 	unsigned int i;
 
 	for (i = 0; i < mvotg->clknum; i++)
-		clk_disable(mvotg->clk[i]);
+		clk_disable_unprepare(mvotg->clk[i]);
 }
 
 static int mv_otg_enable_internal(struct mv_otg *mvotg)
diff --git a/drivers/usb/phy/tegra_usb_phy.c b/drivers/usb/phy/tegra_usb_phy.c
index 9d13c81..5487d38 100644
--- a/drivers/usb/phy/tegra_usb_phy.c
+++ b/drivers/usb/phy/tegra_usb_phy.c
@@ -24,6 +24,7 @@
 #include <linux/platform_device.h>
 #include <linux/io.h>
 #include <linux/gpio.h>
+#include <linux/of.h>
 #include <linux/of_gpio.h>
 #include <linux/usb/otg.h>
 #include <linux/usb/ulpi.h>
@@ -35,19 +36,6 @@
 
 #define ULPI_VIEWPORT		0x170
 
-#define USB_PORTSC1		0x184
-#define   USB_PORTSC1_PTS(x)	(((x) & 0x3) << 30)
-#define   USB_PORTSC1_PSPD(x)	(((x) & 0x3) << 26)
-#define   USB_PORTSC1_PHCD	(1 << 23)
-#define   USB_PORTSC1_WKOC	(1 << 22)
-#define   USB_PORTSC1_WKDS	(1 << 21)
-#define   USB_PORTSC1_WKCN	(1 << 20)
-#define   USB_PORTSC1_PTC(x)	(((x) & 0xf) << 16)
-#define   USB_PORTSC1_PP	(1 << 12)
-#define   USB_PORTSC1_SUSP	(1 << 7)
-#define   USB_PORTSC1_PE	(1 << 2)
-#define   USB_PORTSC1_CCS	(1 << 0)
-
 #define USB_SUSP_CTRL		0x400
 #define   USB_WAKE_ON_CNNT_EN_DEV	(1 << 3)
 #define   USB_WAKE_ON_DISCON_EN_DEV	(1 << 4)
@@ -208,11 +196,6 @@
 	},
 };
 
-static inline bool phy_is_ulpi(struct tegra_usb_phy *phy)
-{
-	return (phy->instance == 1);
-}
-
 static int utmip_pad_open(struct tegra_usb_phy *phy)
 {
 	phy->pad_clk = clk_get_sys("utmip-pad", NULL);
@@ -221,7 +204,7 @@
 		return PTR_ERR(phy->pad_clk);
 	}
 
-	if (phy->instance == 0) {
+	if (phy->is_legacy_phy) {
 		phy->pad_regs = phy->regs;
 	} else {
 		phy->pad_regs = ioremap(TEGRA_USB_BASE, TEGRA_USB_SIZE);
@@ -236,7 +219,7 @@
 
 static void utmip_pad_close(struct tegra_usb_phy *phy)
 {
-	if (phy->instance != 0)
+	if (!phy->is_legacy_phy)
 		iounmap(phy->pad_regs);
 	clk_put(phy->pad_clk);
 }
@@ -305,7 +288,7 @@
 	unsigned long val;
 	void __iomem *base = phy->regs;
 
-	if (phy->instance == 0) {
+	if (phy->is_legacy_phy) {
 		val = readl(base + USB_SUSP_CTRL);
 		val |= USB_SUSP_SET;
 		writel(val, base + USB_SUSP_CTRL);
@@ -315,13 +298,8 @@
 		val = readl(base + USB_SUSP_CTRL);
 		val &= ~USB_SUSP_SET;
 		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	if (phy->instance == 2) {
-		val = readl(base + USB_PORTSC1);
-		val |= USB_PORTSC1_PHCD;
-		writel(val, base + USB_PORTSC1);
-	}
+	} else
+		tegra_ehci_set_phcd(&phy->u_phy, true);
 
 	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID, 0) < 0)
 		pr_err("%s: timeout waiting for phy to stabilize\n", __func__);
@@ -332,7 +310,7 @@
 	unsigned long val;
 	void __iomem *base = phy->regs;
 
-	if (phy->instance == 0) {
+	if (phy->is_legacy_phy) {
 		val = readl(base + USB_SUSP_CTRL);
 		val |= USB_SUSP_CLR;
 		writel(val, base + USB_SUSP_CTRL);
@@ -342,13 +320,8 @@
 		val = readl(base + USB_SUSP_CTRL);
 		val &= ~USB_SUSP_CLR;
 		writel(val, base + USB_SUSP_CTRL);
-	}
-
-	if (phy->instance == 2) {
-		val = readl(base + USB_PORTSC1);
-		val &= ~USB_PORTSC1_PHCD;
-		writel(val, base + USB_PORTSC1);
-	}
+	} else
+		tegra_ehci_set_phcd(&phy->u_phy, false);
 
 	if (utmi_wait_register(base + USB_SUSP_CTRL, USB_PHY_CLK_VALID,
 						     USB_PHY_CLK_VALID))
@@ -365,7 +338,7 @@
 	val |= UTMIP_RESET;
 	writel(val, base + USB_SUSP_CTRL);
 
-	if (phy->instance == 0) {
+	if (phy->is_legacy_phy) {
 		val = readl(base + USB1_LEGACY_CTRL);
 		val |= USB1_NO_LEGACY_MODE;
 		writel(val, base + USB1_LEGACY_CTRL);
@@ -440,16 +413,14 @@
 	val |= UTMIP_BIAS_PDTRK_COUNT(0x5);
 	writel(val, base + UTMIP_BIAS_CFG1);
 
-	if (phy->instance == 0) {
+	if (phy->is_legacy_phy) {
 		val = readl(base + UTMIP_SPARE_CFG0);
 		if (phy->mode == TEGRA_USB_PHY_MODE_DEVICE)
 			val &= ~FUSE_SETUP_SEL;
 		else
 			val |= FUSE_SETUP_SEL;
 		writel(val, base + UTMIP_SPARE_CFG0);
-	}
-
-	if (phy->instance == 2) {
+	} else {
 		val = readl(base + USB_SUSP_CTRL);
 		val |= UTMIP_PHY_ENABLE;
 		writel(val, base + USB_SUSP_CTRL);
@@ -459,7 +430,7 @@
 	val &= ~UTMIP_RESET;
 	writel(val, base + USB_SUSP_CTRL);
 
-	if (phy->instance == 0) {
+	if (phy->is_legacy_phy) {
 		val = readl(base + USB1_LEGACY_CTRL);
 		val &= ~USB1_VBUS_SENSE_CTL_MASK;
 		val |= USB1_VBUS_SENSE_CTL_A_SESS_VLD;
@@ -472,11 +443,8 @@
 
 	utmi_phy_clk_enable(phy);
 
-	if (phy->instance == 2) {
-		val = readl(base + USB_PORTSC1);
-		val &= ~USB_PORTSC1_PTS(~0);
-		writel(val, base + USB_PORTSC1);
-	}
+	if (!phy->is_legacy_phy)
+		tegra_ehci_set_pts(&phy->u_phy, 0);
 
 	return 0;
 }
@@ -621,10 +589,6 @@
 		return ret;
 	}
 
-	val = readl(base + USB_PORTSC1);
-	val |= USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN;
-	writel(val, base + USB_PORTSC1);
-
 	val = readl(base + USB_SUSP_CTRL);
 	val |= USB_SUSP_CLR;
 	writel(val, base + USB_SUSP_CTRL);
@@ -639,17 +603,8 @@
 
 static int ulpi_phy_power_off(struct tegra_usb_phy *phy)
 {
-	unsigned long val;
-	void __iomem *base = phy->regs;
 	struct tegra_ulpi_config *config = phy->config;
 
-	/* Clear WKCN/WKDS/WKOC wake-on events that can cause the USB
-	 * Controller to immediately bring the ULPI PHY out of low power
-	 */
-	val = readl(base + USB_PORTSC1);
-	val &= ~(USB_PORTSC1_WKOC | USB_PORTSC1_WKDS | USB_PORTSC1_WKCN);
-	writel(val, base + USB_PORTSC1);
-
 	clk_disable(phy->clk);
 	return gpio_direction_output(config->reset_gpio, 0);
 }
@@ -660,7 +615,7 @@
 	struct tegra_ulpi_config *ulpi_config;
 	int err;
 
-	if (phy_is_ulpi(phy)) {
+	if (phy->is_ulpi_phy) {
 		ulpi_config = phy->config;
 		phy->clk = clk_get_sys(NULL, ulpi_config->clk);
 		if (IS_ERR(phy->clk)) {
@@ -698,7 +653,7 @@
 {
 	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
 
-	if (phy_is_ulpi(phy))
+	if (phy->is_ulpi_phy)
 		clk_put(phy->clk);
 	else
 		utmip_pad_close(phy);
@@ -709,7 +664,7 @@
 
 static int tegra_usb_phy_power_on(struct tegra_usb_phy *phy)
 {
-	if (phy_is_ulpi(phy))
+	if (phy->is_ulpi_phy)
 		return ulpi_phy_power_on(phy);
 	else
 		return utmi_phy_power_on(phy);
@@ -717,7 +672,7 @@
 
 static int tegra_usb_phy_power_off(struct tegra_usb_phy *phy)
 {
-	if (phy_is_ulpi(phy))
+	if (phy->is_ulpi_phy)
 		return ulpi_phy_power_off(phy);
 	else
 		return utmi_phy_power_off(phy);
@@ -739,8 +694,9 @@
 	unsigned long parent_rate;
 	int i;
 	int err;
+	struct device_node *np = dev->of_node;
 
-	phy = kmalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL);
+	phy = kzalloc(sizeof(struct tegra_usb_phy), GFP_KERNEL);
 	if (!phy)
 		return ERR_PTR(-ENOMEM);
 
@@ -749,9 +705,16 @@
 	phy->config = config;
 	phy->mode = phy_mode;
 	phy->dev = dev;
+	phy->is_legacy_phy =
+		of_property_read_bool(np, "nvidia,has-legacy-mode");
+	err = of_property_match_string(np, "phy_type", "ulpi");
+	if (err < 0)
+		phy->is_ulpi_phy = false;
+	else
+		phy->is_ulpi_phy = true;
 
 	if (!phy->config) {
-		if (phy_is_ulpi(phy)) {
+		if (phy->is_ulpi_phy) {
 			pr_err("%s: ulpi phy configuration missing", __func__);
 			err = -EINVAL;
 			goto err0;
@@ -796,45 +759,40 @@
 }
 EXPORT_SYMBOL_GPL(tegra_usb_phy_open);
 
-void tegra_usb_phy_preresume(struct tegra_usb_phy *phy)
+void tegra_usb_phy_preresume(struct usb_phy *x)
 {
-	if (!phy_is_ulpi(phy))
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+	if (!phy->is_ulpi_phy)
 		utmi_phy_preresume(phy);
 }
 EXPORT_SYMBOL_GPL(tegra_usb_phy_preresume);
 
-void tegra_usb_phy_postresume(struct tegra_usb_phy *phy)
+void tegra_usb_phy_postresume(struct usb_phy *x)
 {
-	if (!phy_is_ulpi(phy))
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+	if (!phy->is_ulpi_phy)
 		utmi_phy_postresume(phy);
 }
 EXPORT_SYMBOL_GPL(tegra_usb_phy_postresume);
 
-void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
+void tegra_ehci_phy_restore_start(struct usb_phy *x,
 				 enum tegra_usb_phy_port_speed port_speed)
 {
-	if (!phy_is_ulpi(phy))
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+	if (!phy->is_ulpi_phy)
 		utmi_phy_restore_start(phy, port_speed);
 }
 EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_start);
 
-void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy)
+void tegra_ehci_phy_restore_end(struct usb_phy *x)
 {
-	if (!phy_is_ulpi(phy))
+	struct tegra_usb_phy *phy = container_of(x, struct tegra_usb_phy, u_phy);
+
+	if (!phy->is_ulpi_phy)
 		utmi_phy_restore_end(phy);
 }
 EXPORT_SYMBOL_GPL(tegra_ehci_phy_restore_end);
 
-void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy)
-{
-	if (!phy_is_ulpi(phy))
-		utmi_phy_clk_disable(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_disable);
-
-void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy)
-{
-	if (!phy_is_ulpi(phy))
-		utmi_phy_clk_enable(phy);
-}
-EXPORT_SYMBOL_GPL(tegra_usb_phy_clk_enable);
diff --git a/drivers/usb/renesas_usbhs/mod_gadget.c b/drivers/usb/renesas_usbhs/mod_gadget.c
index dd41f61..f2985cd 100644
--- a/drivers/usb/renesas_usbhs/mod_gadget.c
+++ b/drivers/usb/renesas_usbhs/mod_gadget.c
@@ -545,15 +545,6 @@
 	return 0;
 }
 
-static void usbhsg_uep_init(struct usbhsg_gpriv *gpriv)
-{
-	int i;
-	struct usbhsg_uep *uep;
-
-	usbhsg_for_each_uep_with_dcp(uep, gpriv, i)
-		uep->pipe = NULL;
-}
-
 /*
  *
  *		usb_ep_ops
@@ -610,7 +601,12 @@
 {
 	struct usbhsg_uep *uep = usbhsg_ep_to_uep(ep);
 
-	return usbhsg_pipe_disable(uep);
+	usbhsg_pipe_disable(uep);
+
+	uep->pipe->mod_private	= NULL;
+	uep->pipe		= NULL;
+
+	return 0;
 }
 
 static struct usb_request *usbhsg_ep_alloc_request(struct usb_ep *ep,
@@ -761,9 +757,8 @@
 	usbhs_pipe_init(priv,
 			usbhsg_dma_map_ctrl);
 	usbhs_fifo_init(priv);
-	usbhsg_uep_init(gpriv);
 
-	/* dcp init */
+	/* dcp init instead of usbhsg_ep_enable() */
 	dcp->pipe		= usbhs_dcp_malloc(priv);
 	dcp->pipe->mod_private	= dcp;
 	usbhs_pipe_config_update(dcp->pipe, 0, 0, 64);
@@ -825,7 +820,7 @@
 	usbhs_sys_set_test_mode(priv, 0);
 	usbhs_sys_function_ctrl(priv, 0);
 
-	usbhsg_pipe_disable(dcp);
+	usbhsg_ep_disable(&dcp->ep);
 
 	dev_dbg(dev, "stop gadget\n");
 
@@ -998,6 +993,7 @@
 	 */
 	usbhsg_for_each_uep_with_dcp(uep, gpriv, i) {
 		uep->gpriv	= gpriv;
+		uep->pipe	= NULL;
 		snprintf(uep->ep_name, EP_NAME_SIZE, "ep%d", i);
 
 		uep->ep.name		= uep->ep_name;
diff --git a/drivers/usb/renesas_usbhs/mod_host.c b/drivers/usb/renesas_usbhs/mod_host.c
index 3d3cd6c..b868154 100644
--- a/drivers/usb/renesas_usbhs/mod_host.c
+++ b/drivers/usb/renesas_usbhs/mod_host.c
@@ -661,9 +661,10 @@
 		status = -ESHUTDOWN;
 
 	urb->actual_length = pkt->actual;
-	usbhsh_ureq_free(hpriv, ureq);
 
 	usbhsh_endpoint_sequence_save(hpriv, urb, pkt);
+	usbhsh_ureq_free(hpriv, ureq);
+
 	usbhsh_pipe_detach(hpriv, usbhsh_ep_to_uep(urb->ep));
 
 	usb_hcd_unlink_urb_from_ep(hcd, urb);
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index 0a373b3..ba68835 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -875,6 +875,8 @@
 	{ USB_DEVICE(FTDI_VID, FTDI_DISTORTEC_JTAG_LOCK_PICK_PID),
 		.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
 	{ USB_DEVICE(FTDI_VID, FTDI_LUMEL_PD12_PID) },
+	/* Crucible Devices */
+	{ USB_DEVICE(FTDI_VID, FTDI_CT_COMET_PID) },
 	{ },					/* Optional parameter entry */
 	{ }					/* Terminating entry */
 };
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 049b6e7..fa5d560 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -1259,3 +1259,9 @@
  * ATI command output: Cinterion MC55i
  */
 #define FTDI_CINTERION_MC55I_PID	0xA951
+
+/*
+ * Product: Comet Caller ID decoder
+ * Manufacturer: Crucible Technologies
+ */
+#define FTDI_CT_COMET_PID	0x8e08
diff --git a/drivers/usb/serial/io_ti.c b/drivers/usb/serial/io_ti.c
index 58184f3..82afc4d 100644
--- a/drivers/usb/serial/io_ti.c
+++ b/drivers/usb/serial/io_ti.c
@@ -530,6 +530,9 @@
 	wait_queue_t wait;
 	unsigned long flags;
 
+	if (!tty)
+		return;
+
 	if (!timeout)
 		timeout = (HZ * EDGE_CLOSING_WAIT)/100;
 
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index e6f87b7..0d9dac9 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -288,6 +288,7 @@
 #define ALCATEL_VENDOR_ID			0x1bbb
 #define ALCATEL_PRODUCT_X060S_X200		0x0000
 #define ALCATEL_PRODUCT_X220_X500D		0x0017
+#define ALCATEL_PRODUCT_L100V			0x011e
 
 #define PIRELLI_VENDOR_ID			0x1266
 #define PIRELLI_PRODUCT_C100_1			0x1002
@@ -429,9 +430,12 @@
 #define MEDIATEK_VENDOR_ID			0x0e8d
 #define MEDIATEK_PRODUCT_DC_1COM		0x00a0
 #define MEDIATEK_PRODUCT_DC_4COM		0x00a5
+#define MEDIATEK_PRODUCT_DC_4COM2		0x00a7
 #define MEDIATEK_PRODUCT_DC_5COM		0x00a4
 #define MEDIATEK_PRODUCT_7208_1COM		0x7101
 #define MEDIATEK_PRODUCT_7208_2COM		0x7102
+#define MEDIATEK_PRODUCT_7103_2COM		0x7103
+#define MEDIATEK_PRODUCT_7106_2COM		0x7106
 #define MEDIATEK_PRODUCT_FP_1COM		0x0003
 #define MEDIATEK_PRODUCT_FP_2COM		0x0023
 #define MEDIATEK_PRODUCT_FPDC_1COM		0x0043
@@ -441,6 +445,14 @@
 #define CELLIENT_VENDOR_ID			0x2692
 #define CELLIENT_PRODUCT_MEN200			0x9005
 
+/* Hyundai Petatel Inc. products */
+#define PETATEL_VENDOR_ID			0x1ff4
+#define PETATEL_PRODUCT_NP10T			0x600e
+
+/* TP-LINK Incorporated products */
+#define TPLINK_VENDOR_ID			0x2357
+#define TPLINK_PRODUCT_MA180			0x0201
+
 /* some devices interfaces need special handling due to a number of reasons */
 enum option_blacklist_reason {
 		OPTION_BLACKLIST_NONE = 0,
@@ -922,8 +934,10 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0254, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0257, 0xff, 0xff, 0xff), /* ZTE MF821 */
 	  .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff) },
-	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0265, 0xff, 0xff, 0xff), /* ONDA MT8205 */
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
+	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0284, 0xff, 0xff, 0xff), /* ZTE MF880 */
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0317, 0xff, 0xff, 0xff) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x0326, 0xff, 0xff, 0xff),
 	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
@@ -1190,6 +1204,8 @@
 	  .driver_info = (kernel_ulong_t)&alcatel_x200_blacklist
 	},
 	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_X220_X500D) },
+	{ USB_DEVICE(ALCATEL_VENDOR_ID, ALCATEL_PRODUCT_L100V),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ USB_DEVICE(AIRPLUS_VENDOR_ID, AIRPLUS_PRODUCT_MCD650) },
 	{ USB_DEVICE(TLAYTECH_VENDOR_ID, TLAYTECH_PRODUCT_TEU800) },
 	{ USB_DEVICE(LONGCHEER_VENDOR_ID, FOUR_G_SYSTEMS_PRODUCT_W14),
@@ -1294,7 +1310,14 @@
 	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FP_2COM, 0x0a, 0x00, 0x00) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_1COM, 0x0a, 0x00, 0x00) },
 	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_FPDC_2COM, 0x0a, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7103_2COM, 0xff, 0x00, 0x00) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_7106_2COM, 0x02, 0x02, 0x01) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x02, 0x01) },
+	{ USB_DEVICE_AND_INTERFACE_INFO(MEDIATEK_VENDOR_ID, MEDIATEK_PRODUCT_DC_4COM2, 0xff, 0x00, 0x00) },
 	{ USB_DEVICE(CELLIENT_VENDOR_ID, CELLIENT_PRODUCT_MEN200) },
+	{ USB_DEVICE(PETATEL_VENDOR_ID, PETATEL_PRODUCT_NP10T) },
+	{ USB_DEVICE(TPLINK_VENDOR_ID, TPLINK_PRODUCT_MA180),
+	  .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
 	{ } /* Terminating entry */
 };
 MODULE_DEVICE_TABLE(usb, option_ids);
diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c
index 4362d9e..f72323e 100644
--- a/drivers/vfio/pci/vfio_pci_rdwr.c
+++ b/drivers/vfio/pci/vfio_pci_rdwr.c
@@ -240,17 +240,17 @@
 			filled = 1;
 		} else {
 			/* Drop writes, fill reads with FF */
+			filled = min((size_t)(x_end - pos), count);
 			if (!iswrite) {
 				char val = 0xFF;
 				size_t i;
 
-				for (i = 0; i < x_end - pos; i++) {
+				for (i = 0; i < filled; i++) {
 					if (put_user(val, buf + i))
 						goto out;
 				}
 			}
 
-			filled = x_end - pos;
 		}
 
 		count -= filled;
diff --git a/drivers/video/imxfb.c b/drivers/video/imxfb.c
index 1252678..0abf2bf 100644
--- a/drivers/video/imxfb.c
+++ b/drivers/video/imxfb.c
@@ -139,6 +139,7 @@
 	struct clk		*clk_ahb;
 	struct clk		*clk_per;
 	enum imxfb_type		devtype;
+	bool			enabled;
 
 	/*
 	 * These are the addresses we mapped
@@ -536,6 +537,10 @@
 
 static void imxfb_enable_controller(struct imxfb_info *fbi)
 {
+
+	if (fbi->enabled)
+		return;
+
 	pr_debug("Enabling LCD controller\n");
 
 	writel(fbi->screen_dma, fbi->regs + LCDC_SSA);
@@ -556,6 +561,7 @@
 	clk_prepare_enable(fbi->clk_ipg);
 	clk_prepare_enable(fbi->clk_ahb);
 	clk_prepare_enable(fbi->clk_per);
+	fbi->enabled = true;
 
 	if (fbi->backlight_power)
 		fbi->backlight_power(1);
@@ -565,6 +571,9 @@
 
 static void imxfb_disable_controller(struct imxfb_info *fbi)
 {
+	if (!fbi->enabled)
+		return;
+
 	pr_debug("Disabling LCD controller\n");
 
 	if (fbi->backlight_power)
@@ -575,6 +584,7 @@
 	clk_disable_unprepare(fbi->clk_per);
 	clk_disable_unprepare(fbi->clk_ipg);
 	clk_disable_unprepare(fbi->clk_ahb);
+	fbi->enabled = false;
 
 	writel(0, fbi->regs + LCDC_RMCR);
 }
@@ -729,6 +739,8 @@
 
 	memset(fbi, 0, sizeof(struct imxfb_info));
 
+	fbi->devtype = pdev->id_entry->driver_data;
+
 	strlcpy(info->fix.id, IMX_NAME, sizeof(info->fix.id));
 
 	info->fix.type			= FB_TYPE_PACKED_PIXELS;
@@ -789,7 +801,6 @@
 		return -ENOMEM;
 
 	fbi = info->par;
-	fbi->devtype = pdev->id_entry->driver_data;
 
 	if (!fb_mode)
 		fb_mode = pdata->mode[0].mode.name;
diff --git a/drivers/video/ssd1307fb.c b/drivers/video/ssd1307fb.c
index 4d99dd7..395cb6a 100644
--- a/drivers/video/ssd1307fb.c
+++ b/drivers/video/ssd1307fb.c
@@ -145,8 +145,8 @@
 				u32 page_length = SSD1307FB_WIDTH * i;
 				u32 index = page_length + (SSD1307FB_WIDTH * k + j) / 8;
 				u8 byte = *(vmem + index);
-				u8 bit = byte & (1 << (7 - (j % 8)));
-				bit = bit >> (7 - (j % 8));
+				u8 bit = byte & (1 << (j % 8));
+				bit = bit >> (j % 8);
 				buf |= bit << k;
 			}
 			ssd1307fb_write_data(par->client, buf);
diff --git a/drivers/xen/cpu_hotplug.c b/drivers/xen/cpu_hotplug.c
index 4dcfced..084041d 100644
--- a/drivers/xen/cpu_hotplug.c
+++ b/drivers/xen/cpu_hotplug.c
@@ -25,10 +25,10 @@
 static int vcpu_online(unsigned int cpu)
 {
 	int err;
-	char dir[32], state[32];
+	char dir[16], state[16];
 
 	sprintf(dir, "cpu/%u", cpu);
-	err = xenbus_scanf(XBT_NIL, dir, "availability", "%s", state);
+	err = xenbus_scanf(XBT_NIL, dir, "availability", "%15s", state);
 	if (err != 1) {
 		if (!xen_initial_domain())
 			printk(KERN_ERR "XENBUS: Unable to read cpu state\n");
diff --git a/drivers/xen/gntdev.c b/drivers/xen/gntdev.c
index 2e22df2..3c8803f 100644
--- a/drivers/xen/gntdev.c
+++ b/drivers/xen/gntdev.c
@@ -56,10 +56,15 @@
 static atomic_t pages_mapped = ATOMIC_INIT(0);
 
 static int use_ptemod;
+#define populate_freeable_maps use_ptemod
 
 struct gntdev_priv {
+	/* maps with visible offsets in the file descriptor */
 	struct list_head maps;
-	/* lock protects maps from concurrent changes */
+	/* maps that are not visible; will be freed on munmap.
+	 * Only populated if populate_freeable_maps == 1 */
+	struct list_head freeable_maps;
+	/* lock protects maps and freeable_maps */
 	spinlock_t lock;
 	struct mm_struct *mm;
 	struct mmu_notifier mn;
@@ -193,7 +198,7 @@
 	return NULL;
 }
 
-static void gntdev_put_map(struct grant_map *map)
+static void gntdev_put_map(struct gntdev_priv *priv, struct grant_map *map)
 {
 	if (!map)
 		return;
@@ -208,6 +213,12 @@
 		evtchn_put(map->notify.event);
 	}
 
+	if (populate_freeable_maps && priv) {
+		spin_lock(&priv->lock);
+		list_del(&map->next);
+		spin_unlock(&priv->lock);
+	}
+
 	if (map->pages && !use_ptemod)
 		unmap_grant_pages(map, 0, map->count);
 	gntdev_free_map(map);
@@ -301,17 +312,10 @@
 
 	if (map->notify.flags & UNMAP_NOTIFY_CLEAR_BYTE) {
 		int pgno = (map->notify.addr >> PAGE_SHIFT);
-		if (pgno >= offset && pgno < offset + pages && use_ptemod) {
-			void __user *tmp = (void __user *)
-				map->vma->vm_start + map->notify.addr;
-			err = copy_to_user(tmp, &err, 1);
-			if (err)
-				return -EFAULT;
-			map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE;
-		} else if (pgno >= offset && pgno < offset + pages) {
-			uint8_t *tmp = kmap(map->pages[pgno]);
+		if (pgno >= offset && pgno < offset + pages) {
+			/* No need for kmap, pages are in lowmem */
+			uint8_t *tmp = pfn_to_kaddr(page_to_pfn(map->pages[pgno]));
 			tmp[map->notify.addr & (PAGE_SIZE-1)] = 0;
-			kunmap(map->pages[pgno]);
 			map->notify.flags &= ~UNMAP_NOTIFY_CLEAR_BYTE;
 		}
 	}
@@ -376,11 +380,24 @@
 static void gntdev_vma_close(struct vm_area_struct *vma)
 {
 	struct grant_map *map = vma->vm_private_data;
+	struct file *file = vma->vm_file;
+	struct gntdev_priv *priv = file->private_data;
 
 	pr_debug("gntdev_vma_close %p\n", vma);
-	map->vma = NULL;
+	if (use_ptemod) {
+		/* It is possible that an mmu notifier could be running
+		 * concurrently, so take priv->lock to ensure that the vma won't
+		 * vanishing during the unmap_grant_pages call, since we will
+		 * spin here until that completes. Such a concurrent call will
+		 * not do any unmapping, since that has been done prior to
+		 * closing the vma, but it may still iterate the unmap_ops list.
+		 */
+		spin_lock(&priv->lock);
+		map->vma = NULL;
+		spin_unlock(&priv->lock);
+	}
 	vma->vm_private_data = NULL;
-	gntdev_put_map(map);
+	gntdev_put_map(priv, map);
 }
 
 static struct vm_operations_struct gntdev_vmops = {
@@ -390,33 +407,43 @@
 
 /* ------------------------------------------------------------------ */
 
+static void unmap_if_in_range(struct grant_map *map,
+			      unsigned long start, unsigned long end)
+{
+	unsigned long mstart, mend;
+	int err;
+
+	if (!map->vma)
+		return;
+	if (map->vma->vm_start >= end)
+		return;
+	if (map->vma->vm_end <= start)
+		return;
+	mstart = max(start, map->vma->vm_start);
+	mend   = min(end,   map->vma->vm_end);
+	pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n",
+			map->index, map->count,
+			map->vma->vm_start, map->vma->vm_end,
+			start, end, mstart, mend);
+	err = unmap_grant_pages(map,
+				(mstart - map->vma->vm_start) >> PAGE_SHIFT,
+				(mend - mstart) >> PAGE_SHIFT);
+	WARN_ON(err);
+}
+
 static void mn_invl_range_start(struct mmu_notifier *mn,
 				struct mm_struct *mm,
 				unsigned long start, unsigned long end)
 {
 	struct gntdev_priv *priv = container_of(mn, struct gntdev_priv, mn);
 	struct grant_map *map;
-	unsigned long mstart, mend;
-	int err;
 
 	spin_lock(&priv->lock);
 	list_for_each_entry(map, &priv->maps, next) {
-		if (!map->vma)
-			continue;
-		if (map->vma->vm_start >= end)
-			continue;
-		if (map->vma->vm_end <= start)
-			continue;
-		mstart = max(start, map->vma->vm_start);
-		mend   = min(end,   map->vma->vm_end);
-		pr_debug("map %d+%d (%lx %lx), range %lx %lx, mrange %lx %lx\n",
-				map->index, map->count,
-				map->vma->vm_start, map->vma->vm_end,
-				start, end, mstart, mend);
-		err = unmap_grant_pages(map,
-					(mstart - map->vma->vm_start) >> PAGE_SHIFT,
-					(mend - mstart) >> PAGE_SHIFT);
-		WARN_ON(err);
+		unmap_if_in_range(map, start, end);
+	}
+	list_for_each_entry(map, &priv->freeable_maps, next) {
+		unmap_if_in_range(map, start, end);
 	}
 	spin_unlock(&priv->lock);
 }
@@ -445,6 +472,15 @@
 		err = unmap_grant_pages(map, /* offset */ 0, map->count);
 		WARN_ON(err);
 	}
+	list_for_each_entry(map, &priv->freeable_maps, next) {
+		if (!map->vma)
+			continue;
+		pr_debug("map %d+%d (%lx %lx)\n",
+				map->index, map->count,
+				map->vma->vm_start, map->vma->vm_end);
+		err = unmap_grant_pages(map, /* offset */ 0, map->count);
+		WARN_ON(err);
+	}
 	spin_unlock(&priv->lock);
 }
 
@@ -466,6 +502,7 @@
 		return -ENOMEM;
 
 	INIT_LIST_HEAD(&priv->maps);
+	INIT_LIST_HEAD(&priv->freeable_maps);
 	spin_lock_init(&priv->lock);
 
 	if (use_ptemod) {
@@ -500,8 +537,9 @@
 	while (!list_empty(&priv->maps)) {
 		map = list_entry(priv->maps.next, struct grant_map, next);
 		list_del(&map->next);
-		gntdev_put_map(map);
+		gntdev_put_map(NULL /* already removed */, map);
 	}
+	WARN_ON(!list_empty(&priv->freeable_maps));
 
 	if (use_ptemod)
 		mmu_notifier_unregister(&priv->mn, priv->mm);
@@ -529,14 +567,14 @@
 
 	if (unlikely(atomic_add_return(op.count, &pages_mapped) > limit)) {
 		pr_debug("can't map: over limit\n");
-		gntdev_put_map(map);
+		gntdev_put_map(NULL, map);
 		return err;
 	}
 
 	if (copy_from_user(map->grants, &u->refs,
 			   sizeof(map->grants[0]) * op.count) != 0) {
-		gntdev_put_map(map);
-		return err;
+		gntdev_put_map(NULL, map);
+		return -EFAULT;
 	}
 
 	spin_lock(&priv->lock);
@@ -565,11 +603,13 @@
 	map = gntdev_find_map_index(priv, op.index >> PAGE_SHIFT, op.count);
 	if (map) {
 		list_del(&map->next);
+		if (populate_freeable_maps)
+			list_add_tail(&map->next, &priv->freeable_maps);
 		err = 0;
 	}
 	spin_unlock(&priv->lock);
 	if (map)
-		gntdev_put_map(map);
+		gntdev_put_map(priv, map);
 	return err;
 }
 
@@ -579,25 +619,31 @@
 	struct ioctl_gntdev_get_offset_for_vaddr op;
 	struct vm_area_struct *vma;
 	struct grant_map *map;
+	int rv = -EINVAL;
 
 	if (copy_from_user(&op, u, sizeof(op)) != 0)
 		return -EFAULT;
 	pr_debug("priv %p, offset for vaddr %lx\n", priv, (unsigned long)op.vaddr);
 
+	down_read(&current->mm->mmap_sem);
 	vma = find_vma(current->mm, op.vaddr);
 	if (!vma || vma->vm_ops != &gntdev_vmops)
-		return -EINVAL;
+		goto out_unlock;
 
 	map = vma->vm_private_data;
 	if (!map)
-		return -EINVAL;
+		goto out_unlock;
 
 	op.offset = map->index << PAGE_SHIFT;
 	op.count = map->count;
+	rv = 0;
 
-	if (copy_to_user(u, &op, sizeof(op)) != 0)
+ out_unlock:
+	up_read(&current->mm->mmap_sem);
+
+	if (rv == 0 && copy_to_user(u, &op, sizeof(op)) != 0)
 		return -EFAULT;
-	return 0;
+	return rv;
 }
 
 static long gntdev_ioctl_notify(struct gntdev_priv *priv, void __user *u)
@@ -778,7 +824,7 @@
 out_put_map:
 	if (use_ptemod)
 		map->vma = NULL;
-	gntdev_put_map(map);
+	gntdev_put_map(priv, map);
 	return err;
 }
 
diff --git a/drivers/xen/grant-table.c b/drivers/xen/grant-table.c
index 7038de5..157c0ccd 100644
--- a/drivers/xen/grant-table.c
+++ b/drivers/xen/grant-table.c
@@ -56,10 +56,6 @@
 /* External tools reserve first few grant table entries. */
 #define NR_RESERVED_ENTRIES 8
 #define GNTTAB_LIST_END 0xffffffff
-#define GREFS_PER_GRANT_FRAME \
-(grant_table_version == 1 ?                      \
-(PAGE_SIZE / sizeof(struct grant_entry_v1)) :   \
-(PAGE_SIZE / sizeof(union grant_entry_v2)))
 
 static grant_ref_t **gnttab_list;
 static unsigned int nr_grant_frames;
@@ -154,6 +150,7 @@
 static grant_status_t *grstatus;
 
 static int grant_table_version;
+static int grefs_per_grant_frame;
 
 static struct gnttab_free_callback *gnttab_free_callback_list;
 
@@ -767,12 +764,14 @@
 	unsigned int new_nr_grant_frames, extra_entries, i;
 	unsigned int nr_glist_frames, new_nr_glist_frames;
 
-	new_nr_grant_frames = nr_grant_frames + more_frames;
-	extra_entries       = more_frames * GREFS_PER_GRANT_FRAME;
+	BUG_ON(grefs_per_grant_frame == 0);
 
-	nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+	new_nr_grant_frames = nr_grant_frames + more_frames;
+	extra_entries       = more_frames * grefs_per_grant_frame;
+
+	nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
 	new_nr_glist_frames =
-		(new_nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+		(new_nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
 	for (i = nr_glist_frames; i < new_nr_glist_frames; i++) {
 		gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_ATOMIC);
 		if (!gnttab_list[i])
@@ -780,12 +779,12 @@
 	}
 
 
-	for (i = GREFS_PER_GRANT_FRAME * nr_grant_frames;
-	     i < GREFS_PER_GRANT_FRAME * new_nr_grant_frames - 1; i++)
+	for (i = grefs_per_grant_frame * nr_grant_frames;
+	     i < grefs_per_grant_frame * new_nr_grant_frames - 1; i++)
 		gnttab_entry(i) = i + 1;
 
 	gnttab_entry(i) = gnttab_free_head;
-	gnttab_free_head = GREFS_PER_GRANT_FRAME * nr_grant_frames;
+	gnttab_free_head = grefs_per_grant_frame * nr_grant_frames;
 	gnttab_free_count += extra_entries;
 
 	nr_grant_frames = new_nr_grant_frames;
@@ -957,7 +956,8 @@
 
 static unsigned nr_status_frames(unsigned nr_grant_frames)
 {
-	return (nr_grant_frames * GREFS_PER_GRANT_FRAME + SPP - 1) / SPP;
+	BUG_ON(grefs_per_grant_frame == 0);
+	return (nr_grant_frames * grefs_per_grant_frame + SPP - 1) / SPP;
 }
 
 static int gnttab_map_frames_v1(xen_pfn_t *frames, unsigned int nr_gframes)
@@ -1115,6 +1115,7 @@
 	rc = HYPERVISOR_grant_table_op(GNTTABOP_set_version, &gsv, 1);
 	if (rc == 0 && gsv.version == 2) {
 		grant_table_version = 2;
+		grefs_per_grant_frame = PAGE_SIZE / sizeof(union grant_entry_v2);
 		gnttab_interface = &gnttab_v2_ops;
 	} else if (grant_table_version == 2) {
 		/*
@@ -1127,17 +1128,17 @@
 		panic("we need grant tables version 2, but only version 1 is available");
 	} else {
 		grant_table_version = 1;
+		grefs_per_grant_frame = PAGE_SIZE / sizeof(struct grant_entry_v1);
 		gnttab_interface = &gnttab_v1_ops;
 	}
 	printk(KERN_INFO "Grant tables using version %d layout.\n",
 		grant_table_version);
 }
 
-int gnttab_resume(void)
+static int gnttab_setup(void)
 {
 	unsigned int max_nr_gframes;
 
-	gnttab_request_version();
 	max_nr_gframes = gnttab_max_grant_frames();
 	if (max_nr_gframes < nr_grant_frames)
 		return -ENOSYS;
@@ -1160,6 +1161,12 @@
 	return 0;
 }
 
+int gnttab_resume(void)
+{
+	gnttab_request_version();
+	return gnttab_setup();
+}
+
 int gnttab_suspend(void)
 {
 	gnttab_interface->unmap_frames();
@@ -1171,9 +1178,10 @@
 	int rc;
 	unsigned int cur, extra;
 
+	BUG_ON(grefs_per_grant_frame == 0);
 	cur = nr_grant_frames;
-	extra = ((req_entries + (GREFS_PER_GRANT_FRAME-1)) /
-		 GREFS_PER_GRANT_FRAME);
+	extra = ((req_entries + (grefs_per_grant_frame-1)) /
+		 grefs_per_grant_frame);
 	if (cur + extra > gnttab_max_grant_frames())
 		return -ENOSPC;
 
@@ -1191,21 +1199,23 @@
 	unsigned int nr_init_grefs;
 	int ret;
 
+	gnttab_request_version();
 	nr_grant_frames = 1;
 	boot_max_nr_grant_frames = __max_nr_grant_frames();
 
 	/* Determine the maximum number of frames required for the
 	 * grant reference free list on the current hypervisor.
 	 */
+	BUG_ON(grefs_per_grant_frame == 0);
 	max_nr_glist_frames = (boot_max_nr_grant_frames *
-			       GREFS_PER_GRANT_FRAME / RPP);
+			       grefs_per_grant_frame / RPP);
 
 	gnttab_list = kmalloc(max_nr_glist_frames * sizeof(grant_ref_t *),
 			      GFP_KERNEL);
 	if (gnttab_list == NULL)
 		return -ENOMEM;
 
-	nr_glist_frames = (nr_grant_frames * GREFS_PER_GRANT_FRAME + RPP - 1) / RPP;
+	nr_glist_frames = (nr_grant_frames * grefs_per_grant_frame + RPP - 1) / RPP;
 	for (i = 0; i < nr_glist_frames; i++) {
 		gnttab_list[i] = (grant_ref_t *)__get_free_page(GFP_KERNEL);
 		if (gnttab_list[i] == NULL) {
@@ -1214,12 +1224,12 @@
 		}
 	}
 
-	if (gnttab_resume() < 0) {
+	if (gnttab_setup() < 0) {
 		ret = -ENODEV;
 		goto ini_nomem;
 	}
 
-	nr_init_grefs = nr_grant_frames * GREFS_PER_GRANT_FRAME;
+	nr_init_grefs = nr_grant_frames * grefs_per_grant_frame;
 
 	for (i = NR_RESERVED_ENTRIES; i < nr_init_grefs - 1; i++)
 		gnttab_entry(i) = i + 1;
diff --git a/drivers/xen/privcmd.c b/drivers/xen/privcmd.c
index 0bbbccbb..ca2b00e 100644
--- a/drivers/xen/privcmd.c
+++ b/drivers/xen/privcmd.c
@@ -199,9 +199,6 @@
 	LIST_HEAD(pagelist);
 	struct mmap_mfn_state state;
 
-	if (!xen_initial_domain())
-		return -EPERM;
-
 	/* We only support privcmd_ioctl_mmap_batch for auto translated. */
 	if (xen_feature(XENFEAT_auto_translated_physmap))
 		return -ENOSYS;
@@ -261,11 +258,12 @@
 	 *      -ENOENT if at least 1 -ENOENT has happened.
 	 */
 	int global_error;
-	/* An array for individual errors */
-	int *err;
+	int version;
 
 	/* User-space mfn array to store errors in the second pass for V1. */
 	xen_pfn_t __user *user_mfn;
+	/* User-space int array to store errors in the second pass for V2. */
+	int __user *user_err;
 };
 
 /* auto translated dom0 note: if domU being created is PV, then mfn is
@@ -288,7 +286,19 @@
 					 &cur_page);
 
 	/* Store error code for second pass. */
-	*(st->err++) = ret;
+	if (st->version == 1) {
+		if (ret < 0) {
+			/*
+			 * V1 encodes the error codes in the 32bit top nibble of the
+			 * mfn (with its known limitations vis-a-vis 64 bit callers).
+			 */
+			*mfnp |= (ret == -ENOENT) ?
+						PRIVCMD_MMAPBATCH_PAGED_ERROR :
+						PRIVCMD_MMAPBATCH_MFN_ERROR;
+		}
+	} else { /* st->version == 2 */
+		*((int *) mfnp) = ret;
+	}
 
 	/* And see if it affects the global_error. */
 	if (ret < 0) {
@@ -305,20 +315,25 @@
 	return 0;
 }
 
-static int mmap_return_errors_v1(void *data, void *state)
+static int mmap_return_errors(void *data, void *state)
 {
-	xen_pfn_t *mfnp = data;
 	struct mmap_batch_state *st = state;
-	int err = *(st->err++);
 
-	/*
-	 * V1 encodes the error codes in the 32bit top nibble of the
-	 * mfn (with its known limitations vis-a-vis 64 bit callers).
-	 */
-	*mfnp |= (err == -ENOENT) ?
-				PRIVCMD_MMAPBATCH_PAGED_ERROR :
-				PRIVCMD_MMAPBATCH_MFN_ERROR;
-	return __put_user(*mfnp, st->user_mfn++);
+	if (st->version == 1) {
+		xen_pfn_t mfnp = *((xen_pfn_t *) data);
+		if (mfnp & PRIVCMD_MMAPBATCH_MFN_ERROR)
+			return __put_user(mfnp, st->user_mfn++);
+		else
+			st->user_mfn++;
+	} else { /* st->version == 2 */
+		int err = *((int *) data);
+		if (err)
+			return __put_user(err, st->user_err++);
+		else
+			st->user_err++;
+	}
+
+	return 0;
 }
 
 /* Allocate pfns that are then mapped with gmfns from foreign domid. Update
@@ -357,12 +372,8 @@
 	struct vm_area_struct *vma;
 	unsigned long nr_pages;
 	LIST_HEAD(pagelist);
-	int *err_array = NULL;
 	struct mmap_batch_state state;
 
-	if (!xen_initial_domain())
-		return -EPERM;
-
 	switch (version) {
 	case 1:
 		if (copy_from_user(&m, udata, sizeof(struct privcmd_mmapbatch)))
@@ -396,10 +407,12 @@
 		goto out;
 	}
 
-	err_array = kcalloc(m.num, sizeof(int), GFP_KERNEL);
-	if (err_array == NULL) {
-		ret = -ENOMEM;
-		goto out;
+	if (version == 2) {
+		/* Zero error array now to only copy back actual errors. */
+		if (clear_user(m.err, sizeof(int) * m.num)) {
+			ret = -EFAULT;
+			goto out;
+		}
 	}
 
 	down_write(&mm->mmap_sem);
@@ -427,7 +440,7 @@
 	state.va            = m.addr;
 	state.index         = 0;
 	state.global_error  = 0;
-	state.err           = err_array;
+	state.version       = version;
 
 	/* mmap_batch_fn guarantees ret == 0 */
 	BUG_ON(traverse_pages(m.num, sizeof(xen_pfn_t),
@@ -435,21 +448,14 @@
 
 	up_write(&mm->mmap_sem);
 
-	if (version == 1) {
-		if (state.global_error) {
-			/* Write back errors in second pass. */
-			state.user_mfn = (xen_pfn_t *)m.arr;
-			state.err      = err_array;
-			ret = traverse_pages(m.num, sizeof(xen_pfn_t),
-					     &pagelist, mmap_return_errors_v1, &state);
-		} else
-			ret = 0;
-
-	} else if (version == 2) {
-		ret = __copy_to_user(m.err, err_array, m.num * sizeof(int));
-		if (ret)
-			ret = -EFAULT;
-	}
+	if (state.global_error) {
+		/* Write back errors in second pass. */
+		state.user_mfn = (xen_pfn_t *)m.arr;
+		state.user_err = m.err;
+		ret = traverse_pages(m.num, sizeof(xen_pfn_t),
+							 &pagelist, mmap_return_errors, &state);
+	} else
+		ret = 0;
 
 	/* If we have not had any EFAULT-like global errors then set the global
 	 * error to -ENOENT if necessary. */
@@ -457,7 +463,6 @@
 		ret = -ENOENT;
 
 out:
-	kfree(err_array);
 	free_page_list(&pagelist);
 
 	return ret;
diff --git a/drivers/xen/xen-pciback/pciback.h b/drivers/xen/xen-pciback/pciback.h
index a7def01..f72af87 100644
--- a/drivers/xen/xen-pciback/pciback.h
+++ b/drivers/xen/xen-pciback/pciback.h
@@ -124,7 +124,7 @@
 static inline void xen_pcibk_release_pci_dev(struct xen_pcibk_device *pdev,
 					     struct pci_dev *dev)
 {
-	if (xen_pcibk_backend && xen_pcibk_backend->free)
+	if (xen_pcibk_backend && xen_pcibk_backend->release)
 		return xen_pcibk_backend->release(pdev, dev);
 }
 
diff --git a/fs/Kconfig b/fs/Kconfig
index cfe512f..780725a 100644
--- a/fs/Kconfig
+++ b/fs/Kconfig
@@ -68,16 +68,6 @@
 source "fs/autofs4/Kconfig"
 source "fs/fuse/Kconfig"
 
-config CUSE
-	tristate "Character device in Userspace support"
-	depends on FUSE_FS
-	help
-	  This FUSE extension allows character devices to be
-	  implemented in userspace.
-
-	  If you want to develop or use userspace character device
-	  based on CUSE, answer Y or M.
-
 config GENERIC_ACL
 	bool
 	select FS_POSIX_ACL
diff --git a/fs/btrfs/extent-tree.c b/fs/btrfs/extent-tree.c
index 521e9d4..a8b8adc 100644
--- a/fs/btrfs/extent-tree.c
+++ b/fs/btrfs/extent-tree.c
@@ -3997,7 +3997,7 @@
 	 * We make the other tasks wait for the flush only when we can flush
 	 * all things.
 	 */
-	if (ret && flush == BTRFS_RESERVE_FLUSH_ALL) {
+	if (ret && flush != BTRFS_RESERVE_NO_FLUSH) {
 		flushing = true;
 		space_info->flush = 1;
 	}
@@ -5560,7 +5560,7 @@
 	int empty_cluster = 2 * 1024 * 1024;
 	struct btrfs_space_info *space_info;
 	int loop = 0;
-	int index = 0;
+	int index = __get_raid_index(data);
 	int alloc_type = (data & BTRFS_BLOCK_GROUP_DATA) ?
 		RESERVE_ALLOC_NO_ACCOUNT : RESERVE_ALLOC;
 	bool found_uncached_bg = false;
@@ -6788,11 +6788,13 @@
 						       &wc->flags[level]);
 			if (ret < 0) {
 				btrfs_tree_unlock_rw(eb, path->locks[level]);
+				path->locks[level] = 0;
 				return ret;
 			}
 			BUG_ON(wc->refs[level] == 0);
 			if (wc->refs[level] == 1) {
 				btrfs_tree_unlock_rw(eb, path->locks[level]);
+				path->locks[level] = 0;
 				return 1;
 			}
 		}
diff --git a/fs/btrfs/extent_map.c b/fs/btrfs/extent_map.c
index f169d6b..2e8cae6 100644
--- a/fs/btrfs/extent_map.c
+++ b/fs/btrfs/extent_map.c
@@ -171,6 +171,10 @@
 	if (test_bit(EXTENT_FLAG_COMPRESSED, &prev->flags))
 		return 0;
 
+	if (test_bit(EXTENT_FLAG_LOGGING, &prev->flags) ||
+	    test_bit(EXTENT_FLAG_LOGGING, &next->flags))
+		return 0;
+
 	if (extent_map_end(prev) == next->start &&
 	    prev->flags == next->flags &&
 	    prev->bdev == next->bdev &&
@@ -255,7 +259,8 @@
 	if (!em)
 		goto out;
 
-	list_move(&em->list, &tree->modified_extents);
+	if (!test_bit(EXTENT_FLAG_LOGGING, &em->flags))
+		list_move(&em->list, &tree->modified_extents);
 	em->generation = gen;
 	clear_bit(EXTENT_FLAG_PINNED, &em->flags);
 	em->mod_start = em->start;
@@ -280,6 +285,12 @@
 
 }
 
+void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em)
+{
+	clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
+	try_merge_map(tree, em);
+}
+
 /**
  * add_extent_mapping - add new extent map to the extent tree
  * @tree:	tree to insert new map in
diff --git a/fs/btrfs/extent_map.h b/fs/btrfs/extent_map.h
index 922943c..c6598c8 100644
--- a/fs/btrfs/extent_map.h
+++ b/fs/btrfs/extent_map.h
@@ -69,6 +69,7 @@
 int __init extent_map_init(void);
 void extent_map_exit(void);
 int unpin_extent_cache(struct extent_map_tree *tree, u64 start, u64 len, u64 gen);
+void clear_em_logging(struct extent_map_tree *tree, struct extent_map *em);
 struct extent_map *search_extent_mapping(struct extent_map_tree *tree,
 					 u64 start, u64 len);
 #endif
diff --git a/fs/btrfs/file-item.c b/fs/btrfs/file-item.c
index bd38cef..94aa53b 100644
--- a/fs/btrfs/file-item.c
+++ b/fs/btrfs/file-item.c
@@ -460,8 +460,8 @@
 		if (!contig)
 			offset = page_offset(bvec->bv_page) + bvec->bv_offset;
 
-		if (!contig && (offset >= ordered->file_offset + ordered->len ||
-		    offset < ordered->file_offset)) {
+		if (offset >= ordered->file_offset + ordered->len ||
+		    offset < ordered->file_offset) {
 			unsigned long bytes_left;
 			sums->len = this_sum_bytes;
 			this_sum_bytes = 0;
diff --git a/fs/btrfs/file.c b/fs/btrfs/file.c
index 77061bf..f76b1fd 100644
--- a/fs/btrfs/file.c
+++ b/fs/btrfs/file.c
@@ -2241,6 +2241,7 @@
 	if (lockend <= lockstart)
 		lockend = lockstart + root->sectorsize;
 
+	lockend--;
 	len = lockend - lockstart + 1;
 
 	len = max_t(u64, len, root->sectorsize);
@@ -2307,9 +2308,12 @@
 					}
 				}
 
-				*offset = start;
-				free_extent_map(em);
-				break;
+				if (!test_bit(EXTENT_FLAG_PREALLOC,
+					      &em->flags)) {
+					*offset = start;
+					free_extent_map(em);
+					break;
+				}
 			}
 		}
 
diff --git a/fs/btrfs/free-space-cache.c b/fs/btrfs/free-space-cache.c
index 59ea2e4..0be7a87 100644
--- a/fs/btrfs/free-space-cache.c
+++ b/fs/btrfs/free-space-cache.c
@@ -1862,11 +1862,13 @@
 {
 	struct btrfs_free_space_ctl *ctl = block_group->free_space_ctl;
 	struct btrfs_free_space *info;
-	int ret = 0;
+	int ret;
+	bool re_search = false;
 
 	spin_lock(&ctl->tree_lock);
 
 again:
+	ret = 0;
 	if (!bytes)
 		goto out_lock;
 
@@ -1879,17 +1881,17 @@
 		info = tree_search_offset(ctl, offset_to_bitmap(ctl, offset),
 					  1, 0);
 		if (!info) {
-			/* the tree logging code might be calling us before we
-			 * have fully loaded the free space rbtree for this
-			 * block group.  So it is possible the entry won't
-			 * be in the rbtree yet at all.  The caching code
-			 * will make sure not to put it in the rbtree if
-			 * the logging code has pinned it.
+			/*
+			 * If we found a partial bit of our free space in a
+			 * bitmap but then couldn't find the other part this may
+			 * be a problem, so WARN about it.
 			 */
+			WARN_ON(re_search);
 			goto out_lock;
 		}
 	}
 
+	re_search = false;
 	if (!info->bitmap) {
 		unlink_free_space(ctl, info);
 		if (offset == info->offset) {
@@ -1935,8 +1937,10 @@
 	}
 
 	ret = remove_from_bitmap(ctl, info, &offset, &bytes);
-	if (ret == -EAGAIN)
+	if (ret == -EAGAIN) {
+		re_search = true;
 		goto again;
+	}
 	BUG_ON(ret); /* logic error */
 out_lock:
 	spin_unlock(&ctl->tree_lock);
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 16d9e8e..cc93b23 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -88,7 +88,7 @@
 	[S_IFLNK >> S_SHIFT]	= BTRFS_FT_SYMLINK,
 };
 
-static int btrfs_setsize(struct inode *inode, loff_t newsize);
+static int btrfs_setsize(struct inode *inode, struct iattr *attr);
 static int btrfs_truncate(struct inode *inode);
 static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent);
 static noinline int cow_file_range(struct inode *inode,
@@ -2478,6 +2478,18 @@
 				continue;
 			}
 			nr_truncate++;
+
+			/* 1 for the orphan item deletion. */
+			trans = btrfs_start_transaction(root, 1);
+			if (IS_ERR(trans)) {
+				ret = PTR_ERR(trans);
+				goto out;
+			}
+			ret = btrfs_orphan_add(trans, inode);
+			btrfs_end_transaction(trans, root);
+			if (ret)
+				goto out;
+
 			ret = btrfs_truncate(inode);
 		} else {
 			nr_unlink++;
@@ -3665,6 +3677,7 @@
 				block_end - cur_offset, 0);
 		if (IS_ERR(em)) {
 			err = PTR_ERR(em);
+			em = NULL;
 			break;
 		}
 		last_byte = min(extent_map_end(em), block_end);
@@ -3748,16 +3761,27 @@
 	return err;
 }
 
-static int btrfs_setsize(struct inode *inode, loff_t newsize)
+static int btrfs_setsize(struct inode *inode, struct iattr *attr)
 {
 	struct btrfs_root *root = BTRFS_I(inode)->root;
 	struct btrfs_trans_handle *trans;
 	loff_t oldsize = i_size_read(inode);
+	loff_t newsize = attr->ia_size;
+	int mask = attr->ia_valid;
 	int ret;
 
 	if (newsize == oldsize)
 		return 0;
 
+	/*
+	 * The regular truncate() case without ATTR_CTIME and ATTR_MTIME is a
+	 * special case where we need to update the times despite not having
+	 * these flags set.  For all other operations the VFS set these flags
+	 * explicitly if it wants a timestamp update.
+	 */
+	if (newsize != oldsize && (!(mask & (ATTR_CTIME | ATTR_MTIME))))
+		inode->i_ctime = inode->i_mtime = current_fs_time(inode->i_sb);
+
 	if (newsize > oldsize) {
 		truncate_pagecache(inode, oldsize, newsize);
 		ret = btrfs_cont_expand(inode, oldsize, newsize);
@@ -3783,9 +3807,34 @@
 			set_bit(BTRFS_INODE_ORDERED_DATA_CLOSE,
 				&BTRFS_I(inode)->runtime_flags);
 
+		/*
+		 * 1 for the orphan item we're going to add
+		 * 1 for the orphan item deletion.
+		 */
+		trans = btrfs_start_transaction(root, 2);
+		if (IS_ERR(trans))
+			return PTR_ERR(trans);
+
+		/*
+		 * We need to do this in case we fail at _any_ point during the
+		 * actual truncate.  Once we do the truncate_setsize we could
+		 * invalidate pages which forces any outstanding ordered io to
+		 * be instantly completed which will give us extents that need
+		 * to be truncated.  If we fail to get an orphan inode down we
+		 * could have left over extents that were never meant to live,
+		 * so we need to garuntee from this point on that everything
+		 * will be consistent.
+		 */
+		ret = btrfs_orphan_add(trans, inode);
+		btrfs_end_transaction(trans, root);
+		if (ret)
+			return ret;
+
 		/* we don't support swapfiles, so vmtruncate shouldn't fail */
 		truncate_setsize(inode, newsize);
 		ret = btrfs_truncate(inode);
+		if (ret && inode->i_nlink)
+			btrfs_orphan_del(NULL, inode);
 	}
 
 	return ret;
@@ -3805,7 +3854,7 @@
 		return err;
 
 	if (S_ISREG(inode->i_mode) && (attr->ia_valid & ATTR_SIZE)) {
-		err = btrfs_setsize(inode, attr->ia_size);
+		err = btrfs_setsize(inode, attr);
 		if (err)
 			return err;
 	}
@@ -5572,10 +5621,13 @@
 		return em;
 	if (em) {
 		/*
-		 * if our em maps to a hole, there might
-		 * actually be delalloc bytes behind it
+		 * if our em maps to
+		 * -  a hole or
+		 * -  a pre-alloc extent,
+		 * there might actually be delalloc bytes behind it.
 		 */
-		if (em->block_start != EXTENT_MAP_HOLE)
+		if (em->block_start != EXTENT_MAP_HOLE &&
+		    !test_bit(EXTENT_FLAG_PREALLOC, &em->flags))
 			return em;
 		else
 			hole_em = em;
@@ -5657,6 +5709,8 @@
 			 */
 			em->block_start = hole_em->block_start;
 			em->block_len = hole_len;
+			if (test_bit(EXTENT_FLAG_PREALLOC, &hole_em->flags))
+				set_bit(EXTENT_FLAG_PREALLOC, &em->flags);
 		} else {
 			em->start = range_start;
 			em->len = found;
@@ -6915,11 +6969,9 @@
 
 	/*
 	 * 1 for the truncate slack space
-	 * 1 for the orphan item we're going to add
-	 * 1 for the orphan item deletion
 	 * 1 for updating the inode.
 	 */
-	trans = btrfs_start_transaction(root, 4);
+	trans = btrfs_start_transaction(root, 2);
 	if (IS_ERR(trans)) {
 		err = PTR_ERR(trans);
 		goto out;
@@ -6930,12 +6982,6 @@
 				      min_size);
 	BUG_ON(ret);
 
-	ret = btrfs_orphan_add(trans, inode);
-	if (ret) {
-		btrfs_end_transaction(trans, root);
-		goto out;
-	}
-
 	/*
 	 * setattr is responsible for setting the ordered_data_close flag,
 	 * but that is only tested during the last file release.  That
@@ -7004,12 +7050,6 @@
 		ret = btrfs_orphan_del(trans, inode);
 		if (ret)
 			err = ret;
-	} else if (ret && inode->i_nlink > 0) {
-		/*
-		 * Failed to do the truncate, remove us from the in memory
-		 * orphan list.
-		 */
-		ret = btrfs_orphan_del(NULL, inode);
 	}
 
 	if (trans) {
@@ -7531,41 +7571,61 @@
  */
 int btrfs_start_delalloc_inodes(struct btrfs_root *root, int delay_iput)
 {
-	struct list_head *head = &root->fs_info->delalloc_inodes;
 	struct btrfs_inode *binode;
 	struct inode *inode;
 	struct btrfs_delalloc_work *work, *next;
 	struct list_head works;
+	struct list_head splice;
 	int ret = 0;
 
 	if (root->fs_info->sb->s_flags & MS_RDONLY)
 		return -EROFS;
 
 	INIT_LIST_HEAD(&works);
-
+	INIT_LIST_HEAD(&splice);
+again:
 	spin_lock(&root->fs_info->delalloc_lock);
-	while (!list_empty(head)) {
-		binode = list_entry(head->next, struct btrfs_inode,
+	list_splice_init(&root->fs_info->delalloc_inodes, &splice);
+	while (!list_empty(&splice)) {
+		binode = list_entry(splice.next, struct btrfs_inode,
 				    delalloc_inodes);
+
+		list_del_init(&binode->delalloc_inodes);
+
 		inode = igrab(&binode->vfs_inode);
 		if (!inode)
-			list_del_init(&binode->delalloc_inodes);
+			continue;
+
+		list_add_tail(&binode->delalloc_inodes,
+			      &root->fs_info->delalloc_inodes);
 		spin_unlock(&root->fs_info->delalloc_lock);
-		if (inode) {
-			work = btrfs_alloc_delalloc_work(inode, 0, delay_iput);
-			if (!work) {
-				ret = -ENOMEM;
-				goto out;
-			}
-			list_add_tail(&work->list, &works);
-			btrfs_queue_worker(&root->fs_info->flush_workers,
-					   &work->work);
+
+		work = btrfs_alloc_delalloc_work(inode, 0, delay_iput);
+		if (unlikely(!work)) {
+			ret = -ENOMEM;
+			goto out;
 		}
+		list_add_tail(&work->list, &works);
+		btrfs_queue_worker(&root->fs_info->flush_workers,
+				   &work->work);
+
 		cond_resched();
 		spin_lock(&root->fs_info->delalloc_lock);
 	}
 	spin_unlock(&root->fs_info->delalloc_lock);
 
+	list_for_each_entry_safe(work, next, &works, list) {
+		list_del_init(&work->list);
+		btrfs_wait_and_free_delalloc_work(work);
+	}
+
+	spin_lock(&root->fs_info->delalloc_lock);
+	if (!list_empty(&root->fs_info->delalloc_inodes)) {
+		spin_unlock(&root->fs_info->delalloc_lock);
+		goto again;
+	}
+	spin_unlock(&root->fs_info->delalloc_lock);
+
 	/* the filemap_flush will queue IO into the worker threads, but
 	 * we have to make sure the IO is actually started and that
 	 * ordered extents get created before we return
@@ -7578,11 +7638,18 @@
 		    atomic_read(&root->fs_info->async_delalloc_pages) == 0));
 	}
 	atomic_dec(&root->fs_info->async_submit_draining);
+	return 0;
 out:
 	list_for_each_entry_safe(work, next, &works, list) {
 		list_del_init(&work->list);
 		btrfs_wait_and_free_delalloc_work(work);
 	}
+
+	if (!list_empty_careful(&splice)) {
+		spin_lock(&root->fs_info->delalloc_lock);
+		list_splice_tail(&splice, &root->fs_info->delalloc_inodes);
+		spin_unlock(&root->fs_info->delalloc_lock);
+	}
 	return ret;
 }
 
diff --git a/fs/btrfs/ioctl.c b/fs/btrfs/ioctl.c
index 4b45167..5b22d45 100644
--- a/fs/btrfs/ioctl.c
+++ b/fs/btrfs/ioctl.c
@@ -1339,7 +1339,8 @@
 	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
 			1)) {
 		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
-		return -EINPROGRESS;
+		mnt_drop_write_file(file);
+		return -EINVAL;
 	}
 
 	mutex_lock(&root->fs_info->volume_mutex);
@@ -1362,6 +1363,7 @@
 		printk(KERN_INFO "btrfs: resizing devid %llu\n",
 		       (unsigned long long)devid);
 	}
+
 	device = btrfs_find_device(root->fs_info, devid, NULL, NULL);
 	if (!device) {
 		printk(KERN_INFO "btrfs: resizer unable to find device %llu\n",
@@ -1369,9 +1371,10 @@
 		ret = -EINVAL;
 		goto out_free;
 	}
-	if (device->fs_devices && device->fs_devices->seeding) {
+
+	if (!device->writeable) {
 		printk(KERN_INFO "btrfs: resizer unable to apply on "
-		       "seeding device %llu\n",
+		       "readonly device %llu\n",
 		       (unsigned long long)devid);
 		ret = -EINVAL;
 		goto out_free;
@@ -1443,8 +1446,8 @@
 	kfree(vol_args);
 out:
 	mutex_unlock(&root->fs_info->volume_mutex);
-	mnt_drop_write_file(file);
 	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
+	mnt_drop_write_file(file);
 	return ret;
 }
 
@@ -2095,13 +2098,13 @@
 		err = inode_permission(inode, MAY_WRITE | MAY_EXEC);
 		if (err)
 			goto out_dput;
-
-		/* check if subvolume may be deleted by a non-root user */
-		err = btrfs_may_delete(dir, dentry, 1);
-		if (err)
-			goto out_dput;
 	}
 
+	/* check if subvolume may be deleted by a user */
+	err = btrfs_may_delete(dir, dentry, 1);
+	if (err)
+		goto out_dput;
+
 	if (btrfs_ino(inode) != BTRFS_FIRST_FREE_OBJECTID) {
 		err = -EINVAL;
 		goto out_dput;
@@ -2183,19 +2186,20 @@
 	struct btrfs_ioctl_defrag_range_args *range;
 	int ret;
 
-	if (btrfs_root_readonly(root))
-		return -EROFS;
+	ret = mnt_want_write_file(file);
+	if (ret)
+		return ret;
 
 	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
 			1)) {
 		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
-		return -EINPROGRESS;
+		mnt_drop_write_file(file);
+		return -EINVAL;
 	}
-	ret = mnt_want_write_file(file);
-	if (ret) {
-		atomic_set(&root->fs_info->mutually_exclusive_operation_running,
-			   0);
-		return ret;
+
+	if (btrfs_root_readonly(root)) {
+		ret = -EROFS;
+		goto out;
 	}
 
 	switch (inode->i_mode & S_IFMT) {
@@ -2247,8 +2251,8 @@
 		ret = -EINVAL;
 	}
 out:
-	mnt_drop_write_file(file);
 	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
+	mnt_drop_write_file(file);
 	return ret;
 }
 
@@ -2263,7 +2267,7 @@
 	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
 			1)) {
 		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
-		return -EINPROGRESS;
+		return -EINVAL;
 	}
 
 	mutex_lock(&root->fs_info->volume_mutex);
@@ -2300,7 +2304,7 @@
 			1)) {
 		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
 		mnt_drop_write_file(file);
-		return -EINPROGRESS;
+		return -EINVAL;
 	}
 
 	mutex_lock(&root->fs_info->volume_mutex);
@@ -2316,8 +2320,8 @@
 	kfree(vol_args);
 out:
 	mutex_unlock(&root->fs_info->volume_mutex);
-	mnt_drop_write_file(file);
 	atomic_set(&root->fs_info->mutually_exclusive_operation_running, 0);
+	mnt_drop_write_file(file);
 	return ret;
 }
 
@@ -3437,8 +3441,8 @@
 	struct btrfs_fs_info *fs_info = root->fs_info;
 	struct btrfs_ioctl_balance_args *bargs;
 	struct btrfs_balance_control *bctl;
+	bool need_unlock; /* for mut. excl. ops lock */
 	int ret;
-	int need_to_clear_lock = 0;
 
 	if (!capable(CAP_SYS_ADMIN))
 		return -EPERM;
@@ -3447,14 +3451,61 @@
 	if (ret)
 		return ret;
 
-	mutex_lock(&fs_info->volume_mutex);
+again:
+	if (!atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1)) {
+		mutex_lock(&fs_info->volume_mutex);
+		mutex_lock(&fs_info->balance_mutex);
+		need_unlock = true;
+		goto locked;
+	}
+
+	/*
+	 * mut. excl. ops lock is locked.  Three possibilites:
+	 *   (1) some other op is running
+	 *   (2) balance is running
+	 *   (3) balance is paused -- special case (think resume)
+	 */
 	mutex_lock(&fs_info->balance_mutex);
+	if (fs_info->balance_ctl) {
+		/* this is either (2) or (3) */
+		if (!atomic_read(&fs_info->balance_running)) {
+			mutex_unlock(&fs_info->balance_mutex);
+			if (!mutex_trylock(&fs_info->volume_mutex))
+				goto again;
+			mutex_lock(&fs_info->balance_mutex);
+
+			if (fs_info->balance_ctl &&
+			    !atomic_read(&fs_info->balance_running)) {
+				/* this is (3) */
+				need_unlock = false;
+				goto locked;
+			}
+
+			mutex_unlock(&fs_info->balance_mutex);
+			mutex_unlock(&fs_info->volume_mutex);
+			goto again;
+		} else {
+			/* this is (2) */
+			mutex_unlock(&fs_info->balance_mutex);
+			ret = -EINPROGRESS;
+			goto out;
+		}
+	} else {
+		/* this is (1) */
+		mutex_unlock(&fs_info->balance_mutex);
+		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+locked:
+	BUG_ON(!atomic_read(&fs_info->mutually_exclusive_operation_running));
 
 	if (arg) {
 		bargs = memdup_user(arg, sizeof(*bargs));
 		if (IS_ERR(bargs)) {
 			ret = PTR_ERR(bargs);
-			goto out;
+			goto out_unlock;
 		}
 
 		if (bargs->flags & BTRFS_BALANCE_RESUME) {
@@ -3474,13 +3525,10 @@
 		bargs = NULL;
 	}
 
-	if (atomic_xchg(&root->fs_info->mutually_exclusive_operation_running,
-			1)) {
-		pr_info("btrfs: dev add/delete/balance/replace/resize operation in progress\n");
+	if (fs_info->balance_ctl) {
 		ret = -EINPROGRESS;
 		goto out_bargs;
 	}
-	need_to_clear_lock = 1;
 
 	bctl = kzalloc(sizeof(*bctl), GFP_NOFS);
 	if (!bctl) {
@@ -3501,11 +3549,17 @@
 	}
 
 do_balance:
-	ret = btrfs_balance(bctl, bargs);
 	/*
-	 * bctl is freed in __cancel_balance or in free_fs_info if
-	 * restriper was paused all the way until unmount
+	 * Ownership of bctl and mutually_exclusive_operation_running
+	 * goes to to btrfs_balance.  bctl is freed in __cancel_balance,
+	 * or, if restriper was paused all the way until unmount, in
+	 * free_fs_info.  mutually_exclusive_operation_running is
+	 * cleared in __cancel_balance.
 	 */
+	need_unlock = false;
+
+	ret = btrfs_balance(bctl, bargs);
+
 	if (arg) {
 		if (copy_to_user(arg, bargs, sizeof(*bargs)))
 			ret = -EFAULT;
@@ -3513,12 +3567,12 @@
 
 out_bargs:
 	kfree(bargs);
-out:
-	if (need_to_clear_lock)
-		atomic_set(&root->fs_info->mutually_exclusive_operation_running,
-			   0);
+out_unlock:
 	mutex_unlock(&fs_info->balance_mutex);
 	mutex_unlock(&fs_info->volume_mutex);
+	if (need_unlock)
+		atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+out:
 	mnt_drop_write_file(file);
 	return ret;
 }
@@ -3698,6 +3752,11 @@
 		goto drop_write;
 	}
 
+	if (!sa->qgroupid) {
+		ret = -EINVAL;
+		goto out;
+	}
+
 	trans = btrfs_join_transaction(root);
 	if (IS_ERR(trans)) {
 		ret = PTR_ERR(trans);
diff --git a/fs/btrfs/qgroup.c b/fs/btrfs/qgroup.c
index fe9d02c..a5c8562 100644
--- a/fs/btrfs/qgroup.c
+++ b/fs/btrfs/qgroup.c
@@ -379,6 +379,13 @@
 
 		ret = add_relation_rb(fs_info, found_key.objectid,
 				      found_key.offset);
+		if (ret == -ENOENT) {
+			printk(KERN_WARNING
+				"btrfs: orphan qgroup relation 0x%llx->0x%llx\n",
+				(unsigned long long)found_key.objectid,
+				(unsigned long long)found_key.offset);
+			ret = 0;	/* ignore the error */
+		}
 		if (ret)
 			goto out;
 next2:
@@ -956,17 +963,28 @@
 			struct btrfs_fs_info *fs_info, u64 qgroupid)
 {
 	struct btrfs_root *quota_root;
+	struct btrfs_qgroup *qgroup;
 	int ret = 0;
 
 	quota_root = fs_info->quota_root;
 	if (!quota_root)
 		return -EINVAL;
 
+	/* check if there are no relations to this qgroup */
+	spin_lock(&fs_info->qgroup_lock);
+	qgroup = find_qgroup_rb(fs_info, qgroupid);
+	if (qgroup) {
+		if (!list_empty(&qgroup->groups) || !list_empty(&qgroup->members)) {
+			spin_unlock(&fs_info->qgroup_lock);
+			return -EBUSY;
+		}
+	}
+	spin_unlock(&fs_info->qgroup_lock);
+
 	ret = del_qgroup_item(trans, quota_root, qgroupid);
 
 	spin_lock(&fs_info->qgroup_lock);
 	del_qgroup_rb(quota_root->fs_info, qgroupid);
-
 	spin_unlock(&fs_info->qgroup_lock);
 
 	return ret;
diff --git a/fs/btrfs/send.c b/fs/btrfs/send.c
index 5445454..321b7fb 100644
--- a/fs/btrfs/send.c
+++ b/fs/btrfs/send.c
@@ -1814,8 +1814,10 @@
 			(unsigned long)nce->ino);
 	if (!nce_head) {
 		nce_head = kmalloc(sizeof(*nce_head), GFP_NOFS);
-		if (!nce_head)
+		if (!nce_head) {
+			kfree(nce);
 			return -ENOMEM;
+		}
 		INIT_LIST_HEAD(nce_head);
 
 		ret = radix_tree_insert(&sctx->name_cache, nce->ino, nce_head);
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index 99545df..d8982e9 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -267,7 +267,7 @@
 			     function, line, errstr);
 		return;
 	}
-	trans->transaction->aborted = errno;
+	ACCESS_ONCE(trans->transaction->aborted) = errno;
 	__btrfs_std_error(root->fs_info, function, line, errno, NULL);
 }
 /*
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 87fac9a..f154946 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -1468,7 +1468,8 @@
 		goto cleanup_transaction;
 	}
 
-	if (cur_trans->aborted) {
+	/* Stop the commit early if ->aborted is set */
+	if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
 		ret = cur_trans->aborted;
 		goto cleanup_transaction;
 	}
@@ -1574,6 +1575,11 @@
 	wait_event(cur_trans->writer_wait,
 		   atomic_read(&cur_trans->num_writers) == 1);
 
+	/* ->aborted might be set after the previous check, so check it */
+	if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
+		ret = cur_trans->aborted;
+		goto cleanup_transaction;
+	}
 	/*
 	 * the reloc mutex makes sure that we stop
 	 * the balancing code from coming in and moving
@@ -1657,6 +1663,17 @@
 		goto cleanup_transaction;
 	}
 
+	/*
+	 * The tasks which save the space cache and inode cache may also
+	 * update ->aborted, check it.
+	 */
+	if (unlikely(ACCESS_ONCE(cur_trans->aborted))) {
+		ret = cur_trans->aborted;
+		mutex_unlock(&root->fs_info->tree_log_mutex);
+		mutex_unlock(&root->fs_info->reloc_mutex);
+		goto cleanup_transaction;
+	}
+
 	btrfs_prepare_extent_commit(trans, root);
 
 	cur_trans = root->fs_info->running_transaction;
diff --git a/fs/btrfs/tree-log.c b/fs/btrfs/tree-log.c
index 83186c7..9027bb1 100644
--- a/fs/btrfs/tree-log.c
+++ b/fs/btrfs/tree-log.c
@@ -3357,6 +3357,11 @@
 	if (skip_csum)
 		return 0;
 
+	if (em->compress_type) {
+		csum_offset = 0;
+		csum_len = block_len;
+	}
+
 	/* block start is already adjusted for the file extent offset. */
 	ret = btrfs_lookup_csums_range(log->fs_info->csum_root,
 				       em->block_start + csum_offset,
@@ -3410,13 +3415,13 @@
 		em = list_entry(extents.next, struct extent_map, list);
 
 		list_del_init(&em->list);
-		clear_bit(EXTENT_FLAG_LOGGING, &em->flags);
 
 		/*
 		 * If we had an error we just need to delete everybody from our
 		 * private list.
 		 */
 		if (ret) {
+			clear_em_logging(tree, em);
 			free_extent_map(em);
 			continue;
 		}
@@ -3424,8 +3429,9 @@
 		write_unlock(&tree->lock);
 
 		ret = log_one_extent(trans, inode, root, em, path);
-		free_extent_map(em);
 		write_lock(&tree->lock);
+		clear_em_logging(tree, em);
+		free_extent_map(em);
 	}
 	WARN_ON(!list_empty(&extents));
 	write_unlock(&tree->lock);
diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c
index 5cce6aa..15f6efd 100644
--- a/fs/btrfs/volumes.c
+++ b/fs/btrfs/volumes.c
@@ -1431,7 +1431,7 @@
 		}
 	} else {
 		ret = btrfs_get_bdev_and_sb(device_path,
-					    FMODE_READ | FMODE_EXCL,
+					    FMODE_WRITE | FMODE_EXCL,
 					    root->fs_info->bdev_holder, 0,
 					    &bdev, &bh);
 		if (ret)
@@ -2614,7 +2614,14 @@
 	cache = btrfs_lookup_block_group(fs_info, chunk_offset);
 	chunk_used = btrfs_block_group_used(&cache->item);
 
-	user_thresh = div_factor_fine(cache->key.offset, bargs->usage);
+	if (bargs->usage == 0)
+		user_thresh = 0;
+	else if (bargs->usage > 100)
+		user_thresh = cache->key.offset;
+	else
+		user_thresh = div_factor_fine(cache->key.offset,
+					      bargs->usage);
+
 	if (chunk_used < user_thresh)
 		ret = 0;
 
@@ -2959,6 +2966,8 @@
 	unset_balance_control(fs_info);
 	ret = del_balance_item(fs_info->tree_root);
 	BUG_ON(ret);
+
+	atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
 }
 
 void update_ioctl_balance_args(struct btrfs_fs_info *fs_info, int lock,
@@ -3138,8 +3147,10 @@
 out:
 	if (bctl->flags & BTRFS_BALANCE_RESUME)
 		__cancel_balance(fs_info);
-	else
+	else {
 		kfree(bctl);
+		atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
+	}
 	return ret;
 }
 
@@ -3156,7 +3167,6 @@
 		ret = btrfs_balance(fs_info->balance_ctl, NULL);
 	}
 
-	atomic_set(&fs_info->mutually_exclusive_operation_running, 0);
 	mutex_unlock(&fs_info->balance_mutex);
 	mutex_unlock(&fs_info->volume_mutex);
 
@@ -3179,7 +3189,6 @@
 		return 0;
 	}
 
-	WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1));
 	tsk = kthread_run(balance_kthread, fs_info, "btrfs-balance");
 	if (IS_ERR(tsk))
 		return PTR_ERR(tsk);
@@ -3233,6 +3242,8 @@
 	btrfs_balance_sys(leaf, item, &disk_bargs);
 	btrfs_disk_balance_args_to_cpu(&bctl->sys, &disk_bargs);
 
+	WARN_ON(atomic_xchg(&fs_info->mutually_exclusive_operation_running, 1));
+
 	mutex_lock(&fs_info->volume_mutex);
 	mutex_lock(&fs_info->balance_mutex);
 
@@ -3496,7 +3507,7 @@
 	{ 1, 1, 2, 2, 2, 2 /* raid1 */ },
 	{ 1, 2, 1, 1, 1, 2 /* dup */ },
 	{ 1, 1, 0, 2, 1, 1 /* raid0 */ },
-	{ 1, 1, 0, 1, 1, 1 /* single */ },
+	{ 1, 1, 1, 1, 1, 1 /* single */ },
 };
 
 static int __btrfs_alloc_chunk(struct btrfs_trans_handle *trans,
diff --git a/fs/buffer.c b/fs/buffer.c
index c017a2d..7a75c3e 100644
--- a/fs/buffer.c
+++ b/fs/buffer.c
@@ -2935,6 +2935,7 @@
 		void *kaddr = kmap_atomic(bh->b_page);
 		memset(kaddr + bh_offset(bh) + bytes, 0, bh->b_size - bytes);
 		kunmap_atomic(kaddr);
+		flush_dcache_page(bh->b_page);
 	}
 }
 
diff --git a/fs/cifs/cifs_dfs_ref.c b/fs/cifs/cifs_dfs_ref.c
index ce5cbd7..210fce2 100644
--- a/fs/cifs/cifs_dfs_ref.c
+++ b/fs/cifs/cifs_dfs_ref.c
@@ -226,6 +226,8 @@
 compose_mount_options_err:
 	kfree(mountdata);
 	mountdata = ERR_PTR(rc);
+	kfree(*devname);
+	*devname = NULL;
 	goto compose_mount_options_out;
 }
 
diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c
index 17c3643..12b3da3 100644
--- a/fs/cifs/connect.c
+++ b/fs/cifs/connect.c
@@ -1917,7 +1917,7 @@
 	}
 	case AF_INET6: {
 		struct sockaddr_in6 *saddr6 = (struct sockaddr_in6 *)srcaddr;
-		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)&rhs;
+		struct sockaddr_in6 *vaddr6 = (struct sockaddr_in6 *)rhs;
 		return ipv6_addr_equal(&saddr6->sin6_addr, &vaddr6->sin6_addr);
 	}
 	default:
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index 153bb1e..a5f12b7 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -176,7 +176,7 @@
 			opts->uid = uid;
 			break;
 		case Opt_gid:
-			if (match_octal(&args[0], &option))
+			if (match_int(&args[0], &option))
 				return -EINVAL;
 			gid = make_kgid(current_user_ns(), option);
 			if (!gid_valid(gid))
diff --git a/fs/exec.c b/fs/exec.c
index 18c45ca..20df02c 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -434,8 +434,9 @@
 			if (IS_ERR(p))
 				return -EFAULT;
 
-			if (i++ >= max)
+			if (i >= max)
 				return -E2BIG;
+			++i;
 
 			if (fatal_signal_pending(current))
 				return -ERESTARTNOHAND;
diff --git a/fs/f2fs/acl.c b/fs/f2fs/acl.c
index e95b949..137af42 100644
--- a/fs/f2fs/acl.c
+++ b/fs/f2fs/acl.c
@@ -191,15 +191,14 @@
 		retval = f2fs_getxattr(inode, name_index, "", value, retval);
 	}
 
-	if (retval < 0) {
-		if (retval == -ENODATA)
-			acl = NULL;
-		else
-			acl = ERR_PTR(retval);
-	} else {
+	if (retval > 0)
 		acl = f2fs_acl_from_disk(value, retval);
-	}
+	else if (retval == -ENODATA)
+		acl = NULL;
+	else
+		acl = ERR_PTR(retval);
 	kfree(value);
+
 	if (!IS_ERR(acl))
 		set_cached_acl(inode, type, acl);
 
diff --git a/fs/f2fs/checkpoint.c b/fs/f2fs/checkpoint.c
index 6ef36c3..ff3c843 100644
--- a/fs/f2fs/checkpoint.c
+++ b/fs/f2fs/checkpoint.c
@@ -214,7 +214,6 @@
 		goto retry;
 	}
 	new->ino = ino;
-	INIT_LIST_HEAD(&new->list);
 
 	/* add new_oentry into list which is sorted by inode number */
 	if (orphan) {
@@ -772,7 +771,7 @@
 	sbi->n_orphans = 0;
 }
 
-int create_checkpoint_caches(void)
+int __init create_checkpoint_caches(void)
 {
 	orphan_entry_slab = f2fs_kmem_cache_create("f2fs_orphan_entry",
 			sizeof(struct orphan_inode_entry), NULL);
diff --git a/fs/f2fs/data.c b/fs/f2fs/data.c
index 3aa5ce7..7bd22a2 100644
--- a/fs/f2fs/data.c
+++ b/fs/f2fs/data.c
@@ -547,6 +547,15 @@
 
 #define MAX_DESIRED_PAGES_WP	4096
 
+static int __f2fs_writepage(struct page *page, struct writeback_control *wbc,
+			void *data)
+{
+	struct address_space *mapping = data;
+	int ret = mapping->a_ops->writepage(page, wbc);
+	mapping_set_error(mapping, ret);
+	return ret;
+}
+
 static int f2fs_write_data_pages(struct address_space *mapping,
 			    struct writeback_control *wbc)
 {
@@ -563,7 +572,7 @@
 
 	if (!S_ISDIR(inode->i_mode))
 		mutex_lock(&sbi->writepages);
-	ret = generic_writepages(mapping, wbc);
+	ret = write_cache_pages(mapping, wbc, __f2fs_writepage, mapping);
 	if (!S_ISDIR(inode->i_mode))
 		mutex_unlock(&sbi->writepages);
 	f2fs_submit_bio(sbi, DATA, (wbc->sync_mode == WB_SYNC_ALL));
@@ -689,6 +698,11 @@
 	return 0;
 }
 
+static sector_t f2fs_bmap(struct address_space *mapping, sector_t block)
+{
+	return generic_block_bmap(mapping, block, get_data_block_ro);
+}
+
 const struct address_space_operations f2fs_dblock_aops = {
 	.readpage	= f2fs_read_data_page,
 	.readpages	= f2fs_read_data_pages,
@@ -700,4 +714,5 @@
 	.invalidatepage	= f2fs_invalidate_data_page,
 	.releasepage	= f2fs_release_data_page,
 	.direct_IO	= f2fs_direct_IO,
+	.bmap		= f2fs_bmap,
 };
diff --git a/fs/f2fs/debug.c b/fs/f2fs/debug.c
index 0e0380a..c8c3730 100644
--- a/fs/f2fs/debug.c
+++ b/fs/f2fs/debug.c
@@ -26,6 +26,7 @@
 
 static LIST_HEAD(f2fs_stat_list);
 static struct dentry *debugfs_root;
+static DEFINE_MUTEX(f2fs_stat_mutex);
 
 static void update_general_status(struct f2fs_sb_info *sbi)
 {
@@ -180,18 +181,14 @@
 	int i = 0;
 	int j;
 
+	mutex_lock(&f2fs_stat_mutex);
 	list_for_each_entry_safe(si, next, &f2fs_stat_list, stat_list) {
 
-		mutex_lock(&si->stat_lock);
-		if (!si->sbi) {
-			mutex_unlock(&si->stat_lock);
-			continue;
-		}
 		update_general_status(si->sbi);
 
 		seq_printf(s, "\n=====[ partition info. #%d ]=====\n", i++);
-		seq_printf(s, "[SB: 1] [CP: 2] [NAT: %d] [SIT: %d] ",
-			   si->nat_area_segs, si->sit_area_segs);
+		seq_printf(s, "[SB: 1] [CP: 2] [SIT: %d] [NAT: %d] ",
+			   si->sit_area_segs, si->nat_area_segs);
 		seq_printf(s, "[SSA: %d] [MAIN: %d",
 			   si->ssa_area_segs, si->main_area_segs);
 		seq_printf(s, "(OverProv:%d Resv:%d)]\n\n",
@@ -286,8 +283,8 @@
 		seq_printf(s, "\nMemory: %u KB = static: %u + cached: %u\n",
 				(si->base_mem + si->cache_mem) >> 10,
 				si->base_mem >> 10, si->cache_mem >> 10);
-		mutex_unlock(&si->stat_lock);
 	}
+	mutex_unlock(&f2fs_stat_mutex);
 	return 0;
 }
 
@@ -303,7 +300,7 @@
 	.release = single_release,
 };
 
-static int init_stats(struct f2fs_sb_info *sbi)
+int f2fs_build_stats(struct f2fs_sb_info *sbi)
 {
 	struct f2fs_super_block *raw_super = F2FS_RAW_SUPER(sbi);
 	struct f2fs_stat_info *si;
@@ -313,9 +310,6 @@
 		return -ENOMEM;
 
 	si = sbi->stat_info;
-	mutex_init(&si->stat_lock);
-	list_add_tail(&si->stat_list, &f2fs_stat_list);
-
 	si->all_area_segs = le32_to_cpu(raw_super->segment_count);
 	si->sit_area_segs = le32_to_cpu(raw_super->segment_count_sit);
 	si->nat_area_segs = le32_to_cpu(raw_super->segment_count_nat);
@@ -325,21 +319,11 @@
 	si->main_area_zones = si->main_area_sections /
 				le32_to_cpu(raw_super->secs_per_zone);
 	si->sbi = sbi;
-	return 0;
-}
 
-int f2fs_build_stats(struct f2fs_sb_info *sbi)
-{
-	int retval;
+	mutex_lock(&f2fs_stat_mutex);
+	list_add_tail(&si->stat_list, &f2fs_stat_list);
+	mutex_unlock(&f2fs_stat_mutex);
 
-	retval = init_stats(sbi);
-	if (retval)
-		return retval;
-
-	if (!debugfs_root)
-		debugfs_root = debugfs_create_dir("f2fs", NULL);
-
-	debugfs_create_file("status", S_IRUGO, debugfs_root, NULL, &stat_fops);
 	return 0;
 }
 
@@ -347,14 +331,22 @@
 {
 	struct f2fs_stat_info *si = sbi->stat_info;
 
+	mutex_lock(&f2fs_stat_mutex);
 	list_del(&si->stat_list);
-	mutex_lock(&si->stat_lock);
-	si->sbi = NULL;
-	mutex_unlock(&si->stat_lock);
+	mutex_unlock(&f2fs_stat_mutex);
+
 	kfree(sbi->stat_info);
 }
 
-void destroy_root_stats(void)
+void __init f2fs_create_root_stats(void)
+{
+	debugfs_root = debugfs_create_dir("f2fs", NULL);
+	if (debugfs_root)
+		debugfs_create_file("status", S_IRUGO, debugfs_root,
+					 NULL, &stat_fops);
+}
+
+void f2fs_destroy_root_stats(void)
 {
 	debugfs_remove_recursive(debugfs_root);
 	debugfs_root = NULL;
diff --git a/fs/f2fs/dir.c b/fs/f2fs/dir.c
index 951ed52..989980e 100644
--- a/fs/f2fs/dir.c
+++ b/fs/f2fs/dir.c
@@ -503,7 +503,7 @@
 	}
 
 	if (inode) {
-		inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
+		inode->i_ctime = CURRENT_TIME;
 		drop_nlink(inode);
 		if (S_ISDIR(inode->i_mode)) {
 			drop_nlink(inode);
diff --git a/fs/f2fs/f2fs.h b/fs/f2fs/f2fs.h
index 13c6dfb..c8e2d75 100644
--- a/fs/f2fs/f2fs.h
+++ b/fs/f2fs/f2fs.h
@@ -211,11 +211,11 @@
 static inline void set_new_dnode(struct dnode_of_data *dn, struct inode *inode,
 		struct page *ipage, struct page *npage, nid_t nid)
 {
+	memset(dn, 0, sizeof(*dn));
 	dn->inode = inode;
 	dn->inode_page = ipage;
 	dn->node_page = npage;
 	dn->nid = nid;
-	dn->inode_page_locked = 0;
 }
 
 /*
@@ -877,6 +877,8 @@
  * super.c
  */
 int f2fs_sync_fs(struct super_block *, int);
+extern __printf(3, 4)
+void f2fs_msg(struct super_block *, const char *, const char *, ...);
 
 /*
  * hash.c
@@ -912,7 +914,7 @@
 void flush_nat_entries(struct f2fs_sb_info *);
 int build_node_manager(struct f2fs_sb_info *);
 void destroy_node_manager(struct f2fs_sb_info *);
-int create_node_manager_caches(void);
+int __init create_node_manager_caches(void);
 void destroy_node_manager_caches(void);
 
 /*
@@ -964,7 +966,7 @@
 void block_operations(struct f2fs_sb_info *);
 void write_checkpoint(struct f2fs_sb_info *, bool, bool);
 void init_orphan_info(struct f2fs_sb_info *);
-int create_checkpoint_caches(void);
+int __init create_checkpoint_caches(void);
 void destroy_checkpoint_caches(void);
 
 /*
@@ -984,9 +986,9 @@
 int start_gc_thread(struct f2fs_sb_info *);
 void stop_gc_thread(struct f2fs_sb_info *);
 block_t start_bidx_of_node(unsigned int);
-int f2fs_gc(struct f2fs_sb_info *, int);
+int f2fs_gc(struct f2fs_sb_info *);
 void build_gc_manager(struct f2fs_sb_info *);
-int create_gc_caches(void);
+int __init create_gc_caches(void);
 void destroy_gc_caches(void);
 
 /*
@@ -1058,7 +1060,8 @@
 
 int f2fs_build_stats(struct f2fs_sb_info *);
 void f2fs_destroy_stats(struct f2fs_sb_info *);
-void destroy_root_stats(void);
+void __init f2fs_create_root_stats(void);
+void f2fs_destroy_root_stats(void);
 #else
 #define stat_inc_call_count(si)
 #define stat_inc_seg_count(si, type)
@@ -1068,7 +1071,8 @@
 
 static inline int f2fs_build_stats(struct f2fs_sb_info *sbi) { return 0; }
 static inline void f2fs_destroy_stats(struct f2fs_sb_info *sbi) { }
-static inline void destroy_root_stats(void) { }
+static inline void __init f2fs_create_root_stats(void) { }
+static inline void f2fs_destroy_root_stats(void) { }
 #endif
 
 extern const struct file_operations f2fs_dir_operations;
diff --git a/fs/f2fs/file.c b/fs/f2fs/file.c
index 7f9ea92..3191b52 100644
--- a/fs/f2fs/file.c
+++ b/fs/f2fs/file.c
@@ -96,8 +96,9 @@
 }
 
 static const struct vm_operations_struct f2fs_file_vm_ops = {
-	.fault        = filemap_fault,
-	.page_mkwrite = f2fs_vm_page_mkwrite,
+	.fault		= filemap_fault,
+	.page_mkwrite	= f2fs_vm_page_mkwrite,
+	.remap_pages	= generic_file_remap_pages,
 };
 
 static int need_to_sync_dir(struct f2fs_sb_info *sbi, struct inode *inode)
@@ -137,6 +138,9 @@
 	if (ret)
 		return ret;
 
+	/* guarantee free sections for fsync */
+	f2fs_balance_fs(sbi);
+
 	mutex_lock(&inode->i_mutex);
 
 	if (datasync && !(inode->i_state & I_DIRTY_DATASYNC))
@@ -407,6 +411,8 @@
 		struct dnode_of_data dn;
 		struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 
+		f2fs_balance_fs(sbi);
+
 		mutex_lock_op(sbi, DATA_TRUNC);
 		set_new_dnode(&dn, inode, NULL, NULL, 0);
 		err = get_dnode_of_data(&dn, index, RDONLY_NODE);
@@ -534,7 +540,6 @@
 				loff_t offset, loff_t len)
 {
 	struct inode *inode = file->f_path.dentry->d_inode;
-	struct f2fs_sb_info *sbi = F2FS_SB(inode->i_sb);
 	long ret;
 
 	if (mode & ~(FALLOC_FL_KEEP_SIZE | FALLOC_FL_PUNCH_HOLE))
@@ -545,7 +550,10 @@
 	else
 		ret = expand_inode_data(inode, offset, len, mode);
 
-	f2fs_balance_fs(sbi);
+	if (!ret) {
+		inode->i_mtime = inode->i_ctime = CURRENT_TIME;
+		mark_inode_dirty(inode);
+	}
 	return ret;
 }
 
diff --git a/fs/f2fs/gc.c b/fs/f2fs/gc.c
index b0ec721..c386910 100644
--- a/fs/f2fs/gc.c
+++ b/fs/f2fs/gc.c
@@ -78,7 +78,7 @@
 
 		sbi->bg_gc++;
 
-		if (f2fs_gc(sbi, 1) == GC_NONE)
+		if (f2fs_gc(sbi) == GC_NONE)
 			wait_ms = GC_THREAD_NOGC_SLEEP_TIME;
 		else if (wait_ms == GC_THREAD_NOGC_SLEEP_TIME)
 			wait_ms = GC_THREAD_MAX_SLEEP_TIME;
@@ -424,7 +424,11 @@
 }
 
 /*
- * Calculate start block index that this node page contains
+ * Calculate start block index indicating the given node offset.
+ * Be careful, caller should give this node offset only indicating direct node
+ * blocks. If any node offsets, which point the other types of node blocks such
+ * as indirect or double indirect node blocks, are given, it must be a caller's
+ * bug.
  */
 block_t start_bidx_of_node(unsigned int node_ofs)
 {
@@ -651,62 +655,44 @@
 	return ret;
 }
 
-int f2fs_gc(struct f2fs_sb_info *sbi, int nGC)
+int f2fs_gc(struct f2fs_sb_info *sbi)
 {
-	unsigned int segno;
-	int old_free_secs, cur_free_secs;
-	int gc_status, nfree;
 	struct list_head ilist;
+	unsigned int segno, i;
 	int gc_type = BG_GC;
+	int gc_status = GC_NONE;
 
 	INIT_LIST_HEAD(&ilist);
 gc_more:
-	nfree = 0;
-	gc_status = GC_NONE;
+	if (!(sbi->sb->s_flags & MS_ACTIVE))
+		goto stop;
 
 	if (has_not_enough_free_secs(sbi))
-		old_free_secs = reserved_sections(sbi);
-	else
-		old_free_secs = free_sections(sbi);
+		gc_type = FG_GC;
 
-	while (sbi->sb->s_flags & MS_ACTIVE) {
-		int i;
-		if (has_not_enough_free_secs(sbi))
-			gc_type = FG_GC;
+	if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE))
+		goto stop;
 
-		cur_free_secs = free_sections(sbi) + nfree;
-
-		/* We got free space successfully. */
-		if (nGC < cur_free_secs - old_free_secs)
+	for (i = 0; i < sbi->segs_per_sec; i++) {
+		/*
+		 * do_garbage_collect will give us three gc_status:
+		 * GC_ERROR, GC_DONE, and GC_BLOCKED.
+		 * If GC is finished uncleanly, we have to return
+		 * the victim to dirty segment list.
+		 */
+		gc_status = do_garbage_collect(sbi, segno + i, &ilist, gc_type);
+		if (gc_status != GC_DONE)
 			break;
-
-		if (!__get_victim(sbi, &segno, gc_type, NO_CHECK_TYPE))
-			break;
-
-		for (i = 0; i < sbi->segs_per_sec; i++) {
-			/*
-			 * do_garbage_collect will give us three gc_status:
-			 * GC_ERROR, GC_DONE, and GC_BLOCKED.
-			 * If GC is finished uncleanly, we have to return
-			 * the victim to dirty segment list.
-			 */
-			gc_status = do_garbage_collect(sbi, segno + i,
-					&ilist, gc_type);
-			if (gc_status != GC_DONE)
-				goto stop;
-			nfree++;
-		}
 	}
-stop:
-	if (has_not_enough_free_secs(sbi) || gc_status == GC_BLOCKED) {
+	if (has_not_enough_free_secs(sbi)) {
 		write_checkpoint(sbi, (gc_status == GC_BLOCKED), false);
-		if (nfree)
+		if (has_not_enough_free_secs(sbi))
 			goto gc_more;
 	}
+stop:
 	mutex_unlock(&sbi->gc_mutex);
 
 	put_gc_inode(&ilist);
-	BUG_ON(!list_empty(&ilist));
 	return gc_status;
 }
 
@@ -715,7 +701,7 @@
 	DIRTY_I(sbi)->v_ops = &default_v_ops;
 }
 
-int create_gc_caches(void)
+int __init create_gc_caches(void)
 {
 	winode_slab = f2fs_kmem_cache_create("f2fs_gc_inodes",
 			sizeof(struct inode_entry), NULL);
diff --git a/fs/f2fs/inode.c b/fs/f2fs/inode.c
index bf20b4d..7942417 100644
--- a/fs/f2fs/inode.c
+++ b/fs/f2fs/inode.c
@@ -217,6 +217,9 @@
 			inode->i_ino == F2FS_META_INO(sbi))
 		return 0;
 
+	if (wbc)
+		f2fs_balance_fs(sbi);
+
 	node_page = get_node_page(sbi, inode->i_ino);
 	if (IS_ERR(node_page))
 		return PTR_ERR(node_page);
diff --git a/fs/f2fs/node.c b/fs/f2fs/node.c
index 5066bfd..9bda63c 100644
--- a/fs/f2fs/node.c
+++ b/fs/f2fs/node.c
@@ -1124,6 +1124,12 @@
 	return 0;
 }
 
+/*
+ * It is very important to gather dirty pages and write at once, so that we can
+ * submit a big bio without interfering other data writes.
+ * Be default, 512 pages (2MB), a segment size, is quite reasonable.
+ */
+#define COLLECT_DIRTY_NODES	512
 static int f2fs_write_node_pages(struct address_space *mapping,
 			    struct writeback_control *wbc)
 {
@@ -1131,17 +1137,16 @@
 	struct block_device *bdev = sbi->sb->s_bdev;
 	long nr_to_write = wbc->nr_to_write;
 
-	if (wbc->for_kupdate)
-		return 0;
-
-	if (get_pages(sbi, F2FS_DIRTY_NODES) == 0)
-		return 0;
-
+	/* First check balancing cached NAT entries */
 	if (try_to_free_nats(sbi, NAT_ENTRY_PER_BLOCK)) {
 		write_checkpoint(sbi, false, false);
 		return 0;
 	}
 
+	/* collect a number of dirty node pages and write together */
+	if (get_pages(sbi, F2FS_DIRTY_NODES) < COLLECT_DIRTY_NODES)
+		return 0;
+
 	/* if mounting is failed, skip writing node pages */
 	wbc->nr_to_write = bio_get_nr_vecs(bdev);
 	sync_node_pages(sbi, 0, wbc);
@@ -1732,7 +1737,7 @@
 	kfree(nm_i);
 }
 
-int create_node_manager_caches(void)
+int __init create_node_manager_caches(void)
 {
 	nat_entry_slab = f2fs_kmem_cache_create("nat_entry",
 			sizeof(struct nat_entry), NULL);
diff --git a/fs/f2fs/recovery.c b/fs/f2fs/recovery.c
index b571fee..f42e406 100644
--- a/fs/f2fs/recovery.c
+++ b/fs/f2fs/recovery.c
@@ -67,7 +67,7 @@
 		kunmap(page);
 		f2fs_put_page(page, 0);
 	} else {
-		f2fs_add_link(&dent, inode);
+		err = f2fs_add_link(&dent, inode);
 	}
 	iput(dir);
 out:
@@ -151,7 +151,6 @@
 				goto out;
 			}
 
-			INIT_LIST_HEAD(&entry->list);
 			list_add_tail(&entry->list, head);
 			entry->blkaddr = blkaddr;
 		}
@@ -174,10 +173,9 @@
 static void destroy_fsync_dnodes(struct f2fs_sb_info *sbi,
 					struct list_head *head)
 {
-	struct list_head *this;
-	struct fsync_inode_entry *entry;
-	list_for_each(this, head) {
-		entry = list_entry(this, struct fsync_inode_entry, list);
+	struct fsync_inode_entry *entry, *tmp;
+
+	list_for_each_entry_safe(entry, tmp, head, list) {
 		iput(entry->inode);
 		list_del(&entry->list);
 		kmem_cache_free(fsync_entry_slab, entry);
diff --git a/fs/f2fs/segment.c b/fs/f2fs/segment.c
index de62409..4b00990 100644
--- a/fs/f2fs/segment.c
+++ b/fs/f2fs/segment.c
@@ -31,7 +31,7 @@
 	 */
 	if (has_not_enough_free_secs(sbi)) {
 		mutex_lock(&sbi->gc_mutex);
-		f2fs_gc(sbi, 1);
+		f2fs_gc(sbi);
 	}
 }
 
diff --git a/fs/f2fs/super.c b/fs/f2fs/super.c
index 08a94c8..37fad04 100644
--- a/fs/f2fs/super.c
+++ b/fs/f2fs/super.c
@@ -53,6 +53,18 @@
 	{Opt_err, NULL},
 };
 
+void f2fs_msg(struct super_block *sb, const char *level, const char *fmt, ...)
+{
+	struct va_format vaf;
+	va_list args;
+
+	va_start(args, fmt);
+	vaf.fmt = fmt;
+	vaf.va = &args;
+	printk("%sF2FS-fs (%s): %pV\n", level, sb->s_id, &vaf);
+	va_end(args);
+}
+
 static void init_once(void *foo)
 {
 	struct f2fs_inode_info *fi = (struct f2fs_inode_info *) foo;
@@ -125,6 +137,8 @@
 
 	if (sync)
 		write_checkpoint(sbi, false, false);
+	else
+		f2fs_balance_fs(sbi);
 
 	return 0;
 }
@@ -247,7 +261,8 @@
 	.get_parent = f2fs_get_parent,
 };
 
-static int parse_options(struct f2fs_sb_info *sbi, char *options)
+static int parse_options(struct super_block *sb, struct f2fs_sb_info *sbi,
+				char *options)
 {
 	substring_t args[MAX_OPT_ARGS];
 	char *p;
@@ -286,7 +301,8 @@
 			break;
 #else
 		case Opt_nouser_xattr:
-			pr_info("nouser_xattr options not supported\n");
+			f2fs_msg(sb, KERN_INFO,
+				"nouser_xattr options not supported");
 			break;
 #endif
 #ifdef CONFIG_F2FS_FS_POSIX_ACL
@@ -295,7 +311,7 @@
 			break;
 #else
 		case Opt_noacl:
-			pr_info("noacl options not supported\n");
+			f2fs_msg(sb, KERN_INFO, "noacl options not supported");
 			break;
 #endif
 		case Opt_active_logs:
@@ -309,8 +325,9 @@
 			set_opt(sbi, DISABLE_EXT_IDENTIFY);
 			break;
 		default:
-			pr_err("Unrecognized mount option \"%s\" or missing value\n",
-					p);
+			f2fs_msg(sb, KERN_ERR,
+				"Unrecognized mount option \"%s\" or missing value",
+				p);
 			return -EINVAL;
 		}
 	}
@@ -337,23 +354,36 @@
 	return result;
 }
 
-static int sanity_check_raw_super(struct f2fs_super_block *raw_super)
+static int sanity_check_raw_super(struct super_block *sb,
+			struct f2fs_super_block *raw_super)
 {
 	unsigned int blocksize;
 
-	if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic))
+	if (F2FS_SUPER_MAGIC != le32_to_cpu(raw_super->magic)) {
+		f2fs_msg(sb, KERN_INFO,
+			"Magic Mismatch, valid(0x%x) - read(0x%x)",
+			F2FS_SUPER_MAGIC, le32_to_cpu(raw_super->magic));
 		return 1;
+	}
 
 	/* Currently, support only 4KB block size */
 	blocksize = 1 << le32_to_cpu(raw_super->log_blocksize);
-	if (blocksize != PAGE_CACHE_SIZE)
+	if (blocksize != PAGE_CACHE_SIZE) {
+		f2fs_msg(sb, KERN_INFO,
+			"Invalid blocksize (%u), supports only 4KB\n",
+			blocksize);
 		return 1;
+	}
 	if (le32_to_cpu(raw_super->log_sectorsize) !=
-					F2FS_LOG_SECTOR_SIZE)
+					F2FS_LOG_SECTOR_SIZE) {
+		f2fs_msg(sb, KERN_INFO, "Invalid log sectorsize");
 		return 1;
+	}
 	if (le32_to_cpu(raw_super->log_sectors_per_block) !=
-					F2FS_LOG_SECTORS_PER_BLOCK)
+					F2FS_LOG_SECTORS_PER_BLOCK) {
+		f2fs_msg(sb, KERN_INFO, "Invalid log sectors per block");
 		return 1;
+	}
 	return 0;
 }
 
@@ -413,14 +443,17 @@
 	if (!sbi)
 		return -ENOMEM;
 
-	/* set a temporary block size */
-	if (!sb_set_blocksize(sb, F2FS_BLKSIZE))
+	/* set a block size */
+	if (!sb_set_blocksize(sb, F2FS_BLKSIZE)) {
+		f2fs_msg(sb, KERN_ERR, "unable to set blocksize");
 		goto free_sbi;
+	}
 
 	/* read f2fs raw super block */
 	raw_super_buf = sb_bread(sb, 0);
 	if (!raw_super_buf) {
 		err = -EIO;
+		f2fs_msg(sb, KERN_ERR, "unable to read superblock");
 		goto free_sbi;
 	}
 	raw_super = (struct f2fs_super_block *)
@@ -438,12 +471,14 @@
 	set_opt(sbi, POSIX_ACL);
 #endif
 	/* parse mount options */
-	if (parse_options(sbi, (char *)data))
+	if (parse_options(sb, sbi, (char *)data))
 		goto free_sb_buf;
 
 	/* sanity checking of raw super */
-	if (sanity_check_raw_super(raw_super))
+	if (sanity_check_raw_super(sb, raw_super)) {
+		f2fs_msg(sb, KERN_ERR, "Can't find a valid F2FS filesystem");
 		goto free_sb_buf;
+	}
 
 	sb->s_maxbytes = max_file_size(le32_to_cpu(raw_super->log_blocksize));
 	sb->s_max_links = F2FS_LINK_MAX;
@@ -477,18 +512,23 @@
 	/* get an inode for meta space */
 	sbi->meta_inode = f2fs_iget(sb, F2FS_META_INO(sbi));
 	if (IS_ERR(sbi->meta_inode)) {
+		f2fs_msg(sb, KERN_ERR, "Failed to read F2FS meta data inode");
 		err = PTR_ERR(sbi->meta_inode);
 		goto free_sb_buf;
 	}
 
 	err = get_valid_checkpoint(sbi);
-	if (err)
+	if (err) {
+		f2fs_msg(sb, KERN_ERR, "Failed to get valid F2FS checkpoint");
 		goto free_meta_inode;
+	}
 
 	/* sanity checking of checkpoint */
 	err = -EINVAL;
-	if (sanity_check_ckpt(raw_super, sbi->ckpt))
+	if (sanity_check_ckpt(raw_super, sbi->ckpt)) {
+		f2fs_msg(sb, KERN_ERR, "Invalid F2FS checkpoint");
 		goto free_cp;
+	}
 
 	sbi->total_valid_node_count =
 				le32_to_cpu(sbi->ckpt->valid_node_count);
@@ -502,25 +542,28 @@
 	INIT_LIST_HEAD(&sbi->dir_inode_list);
 	spin_lock_init(&sbi->dir_inode_lock);
 
-	/* init super block */
-	if (!sb_set_blocksize(sb, sbi->blocksize))
-		goto free_cp;
-
 	init_orphan_info(sbi);
 
 	/* setup f2fs internal modules */
 	err = build_segment_manager(sbi);
-	if (err)
+	if (err) {
+		f2fs_msg(sb, KERN_ERR,
+			"Failed to initialize F2FS segment manager");
 		goto free_sm;
+	}
 	err = build_node_manager(sbi);
-	if (err)
+	if (err) {
+		f2fs_msg(sb, KERN_ERR,
+			"Failed to initialize F2FS node manager");
 		goto free_nm;
+	}
 
 	build_gc_manager(sbi);
 
 	/* get an inode for node space */
 	sbi->node_inode = f2fs_iget(sb, F2FS_NODE_INO(sbi));
 	if (IS_ERR(sbi->node_inode)) {
+		f2fs_msg(sb, KERN_ERR, "Failed to read node inode");
 		err = PTR_ERR(sbi->node_inode);
 		goto free_nm;
 	}
@@ -533,6 +576,7 @@
 	/* read root inode and dentry */
 	root = f2fs_iget(sb, F2FS_ROOT_INO(sbi));
 	if (IS_ERR(root)) {
+		f2fs_msg(sb, KERN_ERR, "Failed to read root inode");
 		err = PTR_ERR(root);
 		goto free_node_inode;
 	}
@@ -596,7 +640,7 @@
 	.fs_flags	= FS_REQUIRES_DEV,
 };
 
-static int init_inodecache(void)
+static int __init init_inodecache(void)
 {
 	f2fs_inode_cachep = f2fs_kmem_cache_create("f2fs_inode_cache",
 			sizeof(struct f2fs_inode_info), NULL);
@@ -631,14 +675,17 @@
 	err = create_checkpoint_caches();
 	if (err)
 		goto fail;
-	return register_filesystem(&f2fs_fs_type);
+	err = register_filesystem(&f2fs_fs_type);
+	if (err)
+		goto fail;
+	f2fs_create_root_stats();
 fail:
 	return err;
 }
 
 static void __exit exit_f2fs_fs(void)
 {
-	destroy_root_stats();
+	f2fs_destroy_root_stats();
 	unregister_filesystem(&f2fs_fs_type);
 	destroy_checkpoint_caches();
 	destroy_gc_caches();
diff --git a/fs/f2fs/xattr.c b/fs/f2fs/xattr.c
index 940136a..8038c04 100644
--- a/fs/f2fs/xattr.c
+++ b/fs/f2fs/xattr.c
@@ -318,6 +318,8 @@
 	if (name_len > 255 || value_len > MAX_VALUE_LEN)
 		return -ERANGE;
 
+	f2fs_balance_fs(sbi);
+
 	mutex_lock_op(sbi, NODE_NEW);
 	if (!fi->i_xattr_nid) {
 		/* Allocate new attribute block */
diff --git a/fs/fuse/Kconfig b/fs/fuse/Kconfig
index 0cf160a..1b2f6c2 100644
--- a/fs/fuse/Kconfig
+++ b/fs/fuse/Kconfig
@@ -4,12 +4,24 @@
 	  With FUSE it is possible to implement a fully functional filesystem
 	  in a userspace program.
 
-	  There's also companion library: libfuse.  This library along with
-	  utilities is available from the FUSE homepage:
+	  There's also a companion library: libfuse2.  This library is available
+	  from the FUSE homepage:
 	  <http://fuse.sourceforge.net/>
+	  although chances are your distribution already has that library
+	  installed if you've installed the "fuse" package itself.
 
 	  See <file:Documentation/filesystems/fuse.txt> for more information.
 	  See <file:Documentation/Changes> for needed library/utility version.
 
 	  If you want to develop a userspace FS, or if you want to use
 	  a filesystem based on FUSE, answer Y or M.
+
+config CUSE
+	tristate "Character device in Userspace support"
+	depends on FUSE_FS
+	help
+	  This FUSE extension allows character devices to be
+	  implemented in userspace.
+
+	  If you want to develop or use a userspace character device
+	  based on CUSE, answer Y or M.
diff --git a/fs/fuse/cuse.c b/fs/fuse/cuse.c
index ee8d550..e397b67 100644
--- a/fs/fuse/cuse.c
+++ b/fs/fuse/cuse.c
@@ -45,7 +45,6 @@
 #include <linux/miscdevice.h>
 #include <linux/mutex.h>
 #include <linux/slab.h>
-#include <linux/spinlock.h>
 #include <linux/stat.h>
 #include <linux/module.h>
 
@@ -63,7 +62,7 @@
 	bool			unrestricted_ioctl;
 };
 
-static DEFINE_SPINLOCK(cuse_lock);		/* protects cuse_conntbl */
+static DEFINE_MUTEX(cuse_lock);		/* protects registration */
 static struct list_head cuse_conntbl[CUSE_CONNTBL_LEN];
 static struct class *cuse_class;
 
@@ -114,14 +113,14 @@
 	int rc;
 
 	/* look up and get the connection */
-	spin_lock(&cuse_lock);
+	mutex_lock(&cuse_lock);
 	list_for_each_entry(pos, cuse_conntbl_head(devt), list)
 		if (pos->dev->devt == devt) {
 			fuse_conn_get(&pos->fc);
 			cc = pos;
 			break;
 		}
-	spin_unlock(&cuse_lock);
+	mutex_unlock(&cuse_lock);
 
 	/* dead? */
 	if (!cc)
@@ -267,7 +266,7 @@
 static int cuse_parse_devinfo(char *p, size_t len, struct cuse_devinfo *devinfo)
 {
 	char *end = p + len;
-	char *key, *val;
+	char *uninitialized_var(key), *uninitialized_var(val);
 	int rc;
 
 	while (true) {
@@ -305,14 +304,14 @@
  */
 static void cuse_process_init_reply(struct fuse_conn *fc, struct fuse_req *req)
 {
-	struct cuse_conn *cc = fc_to_cc(fc);
+	struct cuse_conn *cc = fc_to_cc(fc), *pos;
 	struct cuse_init_out *arg = req->out.args[0].value;
 	struct page *page = req->pages[0];
 	struct cuse_devinfo devinfo = { };
 	struct device *dev;
 	struct cdev *cdev;
 	dev_t devt;
-	int rc;
+	int rc, i;
 
 	if (req->out.h.error ||
 	    arg->major != FUSE_KERNEL_VERSION || arg->minor < 11) {
@@ -356,15 +355,24 @@
 	dev_set_drvdata(dev, cc);
 	dev_set_name(dev, "%s", devinfo.name);
 
+	mutex_lock(&cuse_lock);
+
+	/* make sure the device-name is unique */
+	for (i = 0; i < CUSE_CONNTBL_LEN; ++i) {
+		list_for_each_entry(pos, &cuse_conntbl[i], list)
+			if (!strcmp(dev_name(pos->dev), dev_name(dev)))
+				goto err_unlock;
+	}
+
 	rc = device_add(dev);
 	if (rc)
-		goto err_device;
+		goto err_unlock;
 
 	/* register cdev */
 	rc = -ENOMEM;
 	cdev = cdev_alloc();
 	if (!cdev)
-		goto err_device;
+		goto err_unlock;
 
 	cdev->owner = THIS_MODULE;
 	cdev->ops = &cuse_frontend_fops;
@@ -377,9 +385,8 @@
 	cc->cdev = cdev;
 
 	/* make the device available */
-	spin_lock(&cuse_lock);
 	list_add(&cc->list, cuse_conntbl_head(devt));
-	spin_unlock(&cuse_lock);
+	mutex_unlock(&cuse_lock);
 
 	/* announce device availability */
 	dev_set_uevent_suppress(dev, 0);
@@ -391,7 +398,8 @@
 
 err_cdev:
 	cdev_del(cdev);
-err_device:
+err_unlock:
+	mutex_unlock(&cuse_lock);
 	put_device(dev);
 err_region:
 	unregister_chrdev_region(devt, 1);
@@ -520,9 +528,9 @@
 	int rc;
 
 	/* remove from the conntbl, no more access from this point on */
-	spin_lock(&cuse_lock);
+	mutex_lock(&cuse_lock);
 	list_del_init(&cc->list);
-	spin_unlock(&cuse_lock);
+	mutex_unlock(&cuse_lock);
 
 	/* remove device */
 	if (cc->dev)
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index c163353..e83351a 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -692,8 +692,6 @@
 	struct page *oldpage = *pagep;
 	struct page *newpage;
 	struct pipe_buffer *buf = cs->pipebufs;
-	struct address_space *mapping;
-	pgoff_t index;
 
 	unlock_request(cs->fc, cs->req);
 	fuse_copy_finish(cs);
@@ -724,9 +722,6 @@
 	if (fuse_check_page(newpage) != 0)
 		goto out_fallback_unlock;
 
-	mapping = oldpage->mapping;
-	index = oldpage->index;
-
 	/*
 	 * This is a new and locked page, it shouldn't be mapped or
 	 * have any special flags on it
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index e21d4d8..f3ab824 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2177,8 +2177,8 @@
 	return ret;
 }
 
-long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
-			    loff_t length)
+static long fuse_file_fallocate(struct file *file, int mode, loff_t offset,
+				loff_t length)
 {
 	struct fuse_file *ff = file->private_data;
 	struct fuse_conn *fc = ff->fc;
@@ -2213,7 +2213,6 @@
 
 	return err;
 }
-EXPORT_SYMBOL_GPL(fuse_file_fallocate);
 
 static const struct file_operations fuse_file_operations = {
 	.llseek		= fuse_file_llseek,
diff --git a/fs/gfs2/lock_dlm.c b/fs/gfs2/lock_dlm.c
index b906ed1..9802de0 100644
--- a/fs/gfs2/lock_dlm.c
+++ b/fs/gfs2/lock_dlm.c
@@ -281,6 +281,7 @@
 {
 	struct gfs2_sbd *sdp = gl->gl_sbd;
 	struct lm_lockstruct *ls = &sdp->sd_lockstruct;
+	int lvb_needs_unlock = 0;
 	int error;
 
 	if (gl->gl_lksb.sb_lkid == 0) {
@@ -294,8 +295,12 @@
 	gfs2_update_request_times(gl);
 
 	/* don't want to skip dlm_unlock writing the lvb when lock is ex */
+
+	if (gl->gl_lksb.sb_lvbptr && (gl->gl_state == LM_ST_EXCLUSIVE))
+		lvb_needs_unlock = 1;
+
 	if (test_bit(SDF_SKIP_DLM_UNLOCK, &sdp->sd_flags) &&
-	    gl->gl_lksb.sb_lvbptr && (gl->gl_state != LM_ST_EXCLUSIVE)) {
+	    !lvb_needs_unlock) {
 		gfs2_glock_free(gl);
 		return;
 	}
diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c
index a286233..81cc7ea 100644
--- a/fs/jbd/journal.c
+++ b/fs/jbd/journal.c
@@ -446,7 +446,8 @@
 	 * currently running transaction (if it exists).  Otherwise,
 	 * the target tid must be an old one.
 	 */
-	if (journal->j_running_transaction &&
+	if (journal->j_commit_request != target &&
+	    journal->j_running_transaction &&
 	    journal->j_running_transaction->t_tid == target) {
 		/*
 		 * We want a new commit: OK, mark the request and wakeup the
diff --git a/fs/nfs/namespace.c b/fs/nfs/namespace.c
index dd057bc..fc8dc20 100644
--- a/fs/nfs/namespace.c
+++ b/fs/nfs/namespace.c
@@ -177,11 +177,31 @@
 	return mnt;
 }
 
+static int
+nfs_namespace_getattr(struct vfsmount *mnt, struct dentry *dentry, struct kstat *stat)
+{
+	if (NFS_FH(dentry->d_inode)->size != 0)
+		return nfs_getattr(mnt, dentry, stat);
+	generic_fillattr(dentry->d_inode, stat);
+	return 0;
+}
+
+static int
+nfs_namespace_setattr(struct dentry *dentry, struct iattr *attr)
+{
+	if (NFS_FH(dentry->d_inode)->size != 0)
+		return nfs_setattr(dentry, attr);
+	return -EACCES;
+}
+
 const struct inode_operations nfs_mountpoint_inode_operations = {
 	.getattr	= nfs_getattr,
+	.setattr	= nfs_setattr,
 };
 
 const struct inode_operations nfs_referral_inode_operations = {
+	.getattr	= nfs_namespace_getattr,
+	.setattr	= nfs_namespace_setattr,
 };
 
 static void nfs_expire_automounts(struct work_struct *work)
diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c
index acc3472..2e9779b 100644
--- a/fs/nfs/nfs4client.c
+++ b/fs/nfs/nfs4client.c
@@ -236,11 +236,10 @@
 	error = nfs4_discover_server_trunking(clp, &old);
 	if (error < 0)
 		goto error;
+	nfs_put_client(clp);
 	if (clp != old) {
 		clp->cl_preserve_clid = true;
-		nfs_put_client(clp);
 		clp = old;
-		atomic_inc(&clp->cl_count);
 	}
 
 	return clp;
@@ -306,7 +305,7 @@
 		.clientid	= new->cl_clientid,
 		.confirm	= new->cl_confirm,
 	};
-	int status;
+	int status = -NFS4ERR_STALE_CLIENTID;
 
 	spin_lock(&nn->nfs_client_lock);
 	list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
@@ -332,40 +331,33 @@
 
 		if (prev)
 			nfs_put_client(prev);
+		prev = pos;
 
 		status = nfs4_proc_setclientid_confirm(pos, &clid, cred);
-		if (status == 0) {
+		switch (status) {
+		case -NFS4ERR_STALE_CLIENTID:
+			break;
+		case 0:
 			nfs4_swap_callback_idents(pos, new);
 
-			nfs_put_client(pos);
+			prev = NULL;
 			*result = pos;
 			dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
 				__func__, pos, atomic_read(&pos->cl_count));
-			return 0;
-		}
-		if (status != -NFS4ERR_STALE_CLIENTID) {
-			nfs_put_client(pos);
-			dprintk("NFS: <-- %s status = %d, no result\n",
-				__func__, status);
-			return status;
+		default:
+			goto out;
 		}
 
 		spin_lock(&nn->nfs_client_lock);
-		prev = pos;
 	}
+	spin_unlock(&nn->nfs_client_lock);
 
-	/*
-	 * No matching nfs_client found.  This should be impossible,
-	 * because the new nfs_client has already been added to
-	 * nfs_client_list by nfs_get_client().
-	 *
-	 * Don't BUG(), since the caller is holding a mutex.
-	 */
+	/* No match found. The server lost our clientid */
+out:
 	if (prev)
 		nfs_put_client(prev);
-	spin_unlock(&nn->nfs_client_lock);
-	pr_err("NFS: %s Error: no matching nfs_client found\n", __func__);
-	return -NFS4ERR_STALE_CLIENTID;
+	dprintk("NFS: <-- %s status = %d\n", __func__, status);
+	return status;
 }
 
 #ifdef CONFIG_NFS_V4_1
@@ -432,7 +424,7 @@
 {
 	struct nfs_net *nn = net_generic(new->cl_net, nfs_net_id);
 	struct nfs_client *pos, *n, *prev = NULL;
-	int error;
+	int status = -NFS4ERR_STALE_CLIENTID;
 
 	spin_lock(&nn->nfs_client_lock);
 	list_for_each_entry_safe(pos, n, &nn->nfs_client_list, cl_share_link) {
@@ -448,14 +440,17 @@
 				nfs_put_client(prev);
 			prev = pos;
 
-			error = nfs_wait_client_init_complete(pos);
-			if (error < 0) {
+			nfs4_schedule_lease_recovery(pos);
+			status = nfs_wait_client_init_complete(pos);
+			if (status < 0) {
 				nfs_put_client(pos);
 				spin_lock(&nn->nfs_client_lock);
 				continue;
 			}
-
+			status = pos->cl_cons_state;
 			spin_lock(&nn->nfs_client_lock);
+			if (status < 0)
+				continue;
 		}
 
 		if (pos->rpc_ops != new->rpc_ops)
@@ -473,6 +468,7 @@
 		if (!nfs4_match_serverowners(pos, new))
 			continue;
 
+		atomic_inc(&pos->cl_count);
 		spin_unlock(&nn->nfs_client_lock);
 		dprintk("NFS: <-- %s using nfs_client = %p ({%d})\n",
 			__func__, pos, atomic_read(&pos->cl_count));
@@ -481,16 +477,10 @@
 		return 0;
 	}
 
-	/*
-	 * No matching nfs_client found.  This should be impossible,
-	 * because the new nfs_client has already been added to
-	 * nfs_client_list by nfs_get_client().
-	 *
-	 * Don't BUG(), since the caller is holding a mutex.
-	 */
+	/* No matching nfs_client found. */
 	spin_unlock(&nn->nfs_client_lock);
-	pr_err("NFS: %s Error: no matching nfs_client found\n", __func__);
-	return -NFS4ERR_STALE_CLIENTID;
+	dprintk("NFS: <-- %s status = %d\n", __func__, status);
+	return status;
 }
 #endif	/* CONFIG_NFS_V4_1 */
 
diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c
index 9448c57..e61f68d 100644
--- a/fs/nfs/nfs4state.c
+++ b/fs/nfs/nfs4state.c
@@ -136,16 +136,11 @@
 	clp->cl_confirm = clid.confirm;
 
 	status = nfs40_walk_client_list(clp, result, cred);
-	switch (status) {
-	case -NFS4ERR_STALE_CLIENTID:
-		set_bit(NFS4CLNT_LEASE_CONFIRM, &clp->cl_state);
-	case 0:
+	if (status == 0) {
 		/* Sustain the lease, even if it's empty.  If the clientid4
 		 * goes stale it's of no use for trunking discovery. */
 		nfs4_schedule_state_renewal(*result);
-		break;
 	}
-
 out:
 	return status;
 }
@@ -1863,6 +1858,7 @@
 	case -ETIMEDOUT:
 	case -EAGAIN:
 		ssleep(1);
+	case -NFS4ERR_STALE_CLIENTID:
 		dprintk("NFS: %s after status %d, retrying\n",
 			__func__, status);
 		goto again;
@@ -2022,8 +2018,18 @@
 	nfs4_begin_drain_session(clp);
 	cred = nfs4_get_exchange_id_cred(clp);
 	status = nfs4_proc_destroy_session(clp->cl_session, cred);
-	if (status && status != -NFS4ERR_BADSESSION &&
-	    status != -NFS4ERR_DEADSESSION) {
+	switch (status) {
+	case 0:
+	case -NFS4ERR_BADSESSION:
+	case -NFS4ERR_DEADSESSION:
+		break;
+	case -NFS4ERR_BACK_CHAN_BUSY:
+	case -NFS4ERR_DELAY:
+		set_bit(NFS4CLNT_SESSION_RESET, &clp->cl_state);
+		status = 0;
+		ssleep(1);
+		goto out;
+	default:
 		status = nfs4_recovery_handle_error(clp, status);
 		goto out;
 	}
diff --git a/fs/nfs/super.c b/fs/nfs/super.c
index 2e7e8c8..b056b16 100644
--- a/fs/nfs/super.c
+++ b/fs/nfs/super.c
@@ -2589,27 +2589,23 @@
 	struct nfs_server *server;
 	struct dentry *mntroot = ERR_PTR(-ENOMEM);
 	struct nfs_subversion *nfs_mod = NFS_SB(data->sb)->nfs_client->cl_nfs_mod;
-	int error;
 
-	dprintk("--> nfs_xdev_mount_common()\n");
+	dprintk("--> nfs_xdev_mount()\n");
 
 	mount_info.mntfh = mount_info.cloned->fh;
 
 	/* create a new volume representation */
 	server = nfs_mod->rpc_ops->clone_server(NFS_SB(data->sb), data->fh, data->fattr, data->authflavor);
-	if (IS_ERR(server)) {
-		error = PTR_ERR(server);
-		goto out_err;
-	}
 
-	mntroot = nfs_fs_mount_common(server, flags, dev_name, &mount_info, nfs_mod);
-	dprintk("<-- nfs_xdev_mount_common() = 0\n");
-out:
+	if (IS_ERR(server))
+		mntroot = ERR_CAST(server);
+	else
+		mntroot = nfs_fs_mount_common(server, flags,
+				dev_name, &mount_info, nfs_mod);
+
+	dprintk("<-- nfs_xdev_mount() = %ld\n",
+			IS_ERR(mntroot) ? PTR_ERR(mntroot) : 0L);
 	return mntroot;
-
-out_err:
-	dprintk("<-- nfs_xdev_mount_common() = %d [error]\n", error);
-	goto out;
 }
 
 #if IS_ENABLED(CONFIG_NFS_V4)
diff --git a/fs/seq_file.c b/fs/seq_file.c
index 9d863fb..f2bc3df 100644
--- a/fs/seq_file.c
+++ b/fs/seq_file.c
@@ -296,7 +296,7 @@
  *	seq_lseek -	->llseek() method for sequential files.
  *	@file: the file in question
  *	@offset: new position
- *	@origin: 0 for absolute, 1 for relative position
+ *	@whence: 0 for absolute, 1 for relative position
  *
  *	Ready-made ->f_op->llseek()
  */
diff --git a/fs/udf/super.c b/fs/udf/super.c
index d44fb56..e9be396 100644
--- a/fs/udf/super.c
+++ b/fs/udf/super.c
@@ -307,7 +307,8 @@
 {
 	struct udf_sb_info *sbi = UDF_SB(sb);
 	int i;
-
+	if (sbi->s_partmaps == NULL)
+		return;
 	for (i = 0; i < sbi->s_partitions; i++)
 		udf_free_partition(&sbi->s_partmaps[i]);
 	kfree(sbi->s_partmaps);
diff --git a/fs/xfs/xfs_aops.c b/fs/xfs/xfs_aops.c
index 4111a40..5f707e5 100644
--- a/fs/xfs/xfs_aops.c
+++ b/fs/xfs/xfs_aops.c
@@ -86,11 +86,11 @@
 	}
 
 	if (ioend->io_iocb) {
+		inode_dio_done(ioend->io_inode);
 		if (ioend->io_isasync) {
 			aio_complete(ioend->io_iocb, ioend->io_error ?
 					ioend->io_error : ioend->io_result, 0);
 		}
-		inode_dio_done(ioend->io_inode);
 	}
 
 	mempool_free(ioend, xfs_ioend_pool);
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 0e92d12..cdb2d33 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -4680,9 +4680,6 @@
 			return error;
 	}
 
-	if (bma->flags & XFS_BMAPI_STACK_SWITCH)
-		bma->stack_switch = 1;
-
 	error = xfs_bmap_alloc(bma);
 	if (error)
 		return error;
@@ -4956,6 +4953,9 @@
 	bma.flist = flist;
 	bma.firstblock = firstblock;
 
+	if (flags & XFS_BMAPI_STACK_SWITCH)
+		bma.stack_switch = 1;
+
 	while (bno < end && n < *nmap) {
 		inhole = eof || bma.got.br_startoff > bno;
 		wasdelay = !inhole && isnullstartblock(bma.got.br_startblock);
diff --git a/fs/xfs/xfs_buf.c b/fs/xfs/xfs_buf.c
index 26673a0..fbbb9eb 100644
--- a/fs/xfs/xfs_buf.c
+++ b/fs/xfs/xfs_buf.c
@@ -175,7 +175,7 @@
 	bp->b_map_count = map_count;
 
 	if (map_count == 1) {
-		bp->b_maps = &bp->b_map;
+		bp->b_maps = &bp->__b_map;
 		return 0;
 	}
 
@@ -193,7 +193,7 @@
 xfs_buf_free_maps(
 	struct xfs_buf	*bp)
 {
-	if (bp->b_maps != &bp->b_map) {
+	if (bp->b_maps != &bp->__b_map) {
 		kmem_free(bp->b_maps);
 		bp->b_maps = NULL;
 	}
@@ -377,8 +377,8 @@
 	}
 
 use_alloc_page:
-	start = BBTOB(bp->b_map.bm_bn) >> PAGE_SHIFT;
-	end = (BBTOB(bp->b_map.bm_bn + bp->b_length) + PAGE_SIZE - 1)
+	start = BBTOB(bp->b_maps[0].bm_bn) >> PAGE_SHIFT;
+	end = (BBTOB(bp->b_maps[0].bm_bn + bp->b_length) + PAGE_SIZE - 1)
 								>> PAGE_SHIFT;
 	page_count = end - start;
 	error = _xfs_buf_get_pages(bp, page_count, flags);
@@ -487,6 +487,7 @@
 	struct rb_node		*parent;
 	xfs_buf_t		*bp;
 	xfs_daddr_t		blkno = map[0].bm_bn;
+	xfs_daddr_t		eofs;
 	int			numblks = 0;
 	int			i;
 
@@ -498,6 +499,23 @@
 	ASSERT(!(numbytes < (1 << btp->bt_sshift)));
 	ASSERT(!(BBTOB(blkno) & (xfs_off_t)btp->bt_smask));
 
+	/*
+	 * Corrupted block numbers can get through to here, unfortunately, so we
+	 * have to check that the buffer falls within the filesystem bounds.
+	 */
+	eofs = XFS_FSB_TO_BB(btp->bt_mount, btp->bt_mount->m_sb.sb_dblocks);
+	if (blkno >= eofs) {
+		/*
+		 * XXX (dgc): we should really be returning EFSCORRUPTED here,
+		 * but none of the higher level infrastructure supports
+		 * returning a specific error on buffer lookup failures.
+		 */
+		xfs_alert(btp->bt_mount,
+			  "%s: Block out of range: block 0x%llx, EOFS 0x%llx ",
+			  __func__, blkno, eofs);
+		return NULL;
+	}
+
 	/* get tree root */
 	pag = xfs_perag_get(btp->bt_mount,
 				xfs_daddr_to_agno(btp->bt_mount, blkno));
@@ -640,7 +658,7 @@
 	xfs_buf_flags_t		flags)
 {
 	ASSERT(!(flags & XBF_WRITE));
-	ASSERT(bp->b_map.bm_bn != XFS_BUF_DADDR_NULL);
+	ASSERT(bp->b_maps[0].bm_bn != XFS_BUF_DADDR_NULL);
 
 	bp->b_flags &= ~(XBF_WRITE | XBF_ASYNC | XBF_READ_AHEAD);
 	bp->b_flags |= flags & (XBF_READ | XBF_ASYNC | XBF_READ_AHEAD);
@@ -1487,6 +1505,8 @@
 	while (!list_empty(&btp->bt_lru)) {
 		bp = list_first_entry(&btp->bt_lru, struct xfs_buf, b_lru);
 		if (atomic_read(&bp->b_hold) > 1) {
+			trace_xfs_buf_wait_buftarg(bp, _RET_IP_);
+			list_move_tail(&bp->b_lru, &btp->bt_lru);
 			spin_unlock(&btp->bt_lru_lock);
 			delay(100);
 			goto restart;
@@ -1709,7 +1729,7 @@
 	struct xfs_buf	*bp = container_of(b, struct xfs_buf, b_list);
 	xfs_daddr_t		diff;
 
-	diff = ap->b_map.bm_bn - bp->b_map.bm_bn;
+	diff = ap->b_maps[0].bm_bn - bp->b_maps[0].bm_bn;
 	if (diff < 0)
 		return -1;
 	if (diff > 0)
diff --git a/fs/xfs/xfs_buf.h b/fs/xfs/xfs_buf.h
index 23f5642..433a12e 100644
--- a/fs/xfs/xfs_buf.h
+++ b/fs/xfs/xfs_buf.h
@@ -151,7 +151,7 @@
 	struct page		**b_pages;	/* array of page pointers */
 	struct page		*b_page_array[XB_PAGES]; /* inline pages */
 	struct xfs_buf_map	*b_maps;	/* compound buffer map */
-	struct xfs_buf_map	b_map;		/* inline compound buffer map */
+	struct xfs_buf_map	__b_map;	/* inline compound buffer map */
 	int			b_map_count;
 	int			b_io_length;	/* IO size in BBs */
 	atomic_t		b_pin_count;	/* pin count */
@@ -330,8 +330,8 @@
  * In future, uncached buffers will pass the block number directly to the io
  * request function and hence these macros will go away at that point.
  */
-#define XFS_BUF_ADDR(bp)		((bp)->b_map.bm_bn)
-#define XFS_BUF_SET_ADDR(bp, bno)	((bp)->b_map.bm_bn = (xfs_daddr_t)(bno))
+#define XFS_BUF_ADDR(bp)		((bp)->b_maps[0].bm_bn)
+#define XFS_BUF_SET_ADDR(bp, bno)	((bp)->b_maps[0].bm_bn = (xfs_daddr_t)(bno))
 
 static inline void xfs_buf_set_ref(struct xfs_buf *bp, int lru_ref)
 {
diff --git a/fs/xfs/xfs_buf_item.c b/fs/xfs/xfs_buf_item.c
index becf4a9..3f9949f 100644
--- a/fs/xfs/xfs_buf_item.c
+++ b/fs/xfs/xfs_buf_item.c
@@ -71,7 +71,7 @@
 		chunk_num = byte >> XFS_BLF_SHIFT;
 		word_num = chunk_num >> BIT_TO_WORD_SHIFT;
 		bit_num = chunk_num & (NBWORD - 1);
-		wordp = &(bip->bli_format.blf_data_map[word_num]);
+		wordp = &(bip->__bli_format.blf_data_map[word_num]);
 		bit_set = *wordp & (1 << bit_num);
 		ASSERT(bit_set);
 		byte++;
@@ -237,7 +237,7 @@
 		 * cancel flag in it.
 		 */
 		trace_xfs_buf_item_size_stale(bip);
-		ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
+		ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
 		return bip->bli_format_count;
 	}
 
@@ -278,7 +278,7 @@
 	uint		buffer_offset;
 
 	/* copy the flags across from the base format item */
-	blfp->blf_flags = bip->bli_format.blf_flags;
+	blfp->blf_flags = bip->__bli_format.blf_flags;
 
 	/*
 	 * Base size is the actual size of the ondisk structure - it reflects
@@ -287,6 +287,17 @@
 	 */
 	base_size = offsetof(struct xfs_buf_log_format, blf_data_map) +
 			(blfp->blf_map_size * sizeof(blfp->blf_data_map[0]));
+
+	nvecs = 0;
+	first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0);
+	if (!(bip->bli_flags & XFS_BLI_STALE) && first_bit == -1) {
+		/*
+		 * If the map is not be dirty in the transaction, mark
+		 * the size as zero and do not advance the vector pointer.
+		 */
+		goto out;
+	}
+
 	vecp->i_addr = blfp;
 	vecp->i_len = base_size;
 	vecp->i_type = XLOG_REG_TYPE_BFORMAT;
@@ -301,15 +312,13 @@
 		 */
 		trace_xfs_buf_item_format_stale(bip);
 		ASSERT(blfp->blf_flags & XFS_BLF_CANCEL);
-		blfp->blf_size = nvecs;
-		return vecp;
+		goto out;
 	}
 
 	/*
 	 * Fill in an iovec for each set of contiguous chunks.
 	 */
-	first_bit = xfs_next_bit(blfp->blf_data_map, blfp->blf_map_size, 0);
-	ASSERT(first_bit != -1);
+
 	last_bit = first_bit;
 	nbits = 1;
 	for (;;) {
@@ -371,7 +380,8 @@
 			nbits++;
 		}
 	}
-	bip->bli_format.blf_size = nvecs;
+out:
+	blfp->blf_size = nvecs;
 	return vecp;
 }
 
@@ -405,7 +415,7 @@
 	if (bip->bli_flags & XFS_BLI_INODE_BUF) {
 		if (!((bip->bli_flags & XFS_BLI_INODE_ALLOC_BUF) &&
 		      xfs_log_item_in_current_chkpt(lip)))
-			bip->bli_format.blf_flags |= XFS_BLF_INODE_BUF;
+			bip->__bli_format.blf_flags |= XFS_BLF_INODE_BUF;
 		bip->bli_flags &= ~XFS_BLI_INODE_BUF;
 	}
 
@@ -485,7 +495,7 @@
 		ASSERT(bip->bli_flags & XFS_BLI_STALE);
 		ASSERT(xfs_buf_islocked(bp));
 		ASSERT(XFS_BUF_ISSTALE(bp));
-		ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
+		ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
 
 		trace_xfs_buf_item_unpin_stale(bip);
 
@@ -601,7 +611,7 @@
 {
 	struct xfs_buf_log_item	*bip = BUF_ITEM(lip);
 	struct xfs_buf		*bp = bip->bli_buf;
-	int			aborted;
+	int			aborted, clean, i;
 	uint			hold;
 
 	/* Clear the buffer's association with this transaction. */
@@ -631,7 +641,7 @@
 	 */
 	if (bip->bli_flags & XFS_BLI_STALE) {
 		trace_xfs_buf_item_unlock_stale(bip);
-		ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
+		ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
 		if (!aborted) {
 			atomic_dec(&bip->bli_refcount);
 			return;
@@ -642,12 +652,27 @@
 
 	/*
 	 * If the buf item isn't tracking any data, free it, otherwise drop the
-	 * reference we hold to it.
+	 * reference we hold to it. If we are aborting the transaction, this may
+	 * be the only reference to the buf item, so we free it anyway
+	 * regardless of whether it is dirty or not. A dirty abort implies a
+	 * shutdown, anyway.
 	 */
-	if (xfs_bitmap_empty(bip->bli_format.blf_data_map,
-			     bip->bli_format.blf_map_size))
+	clean = 1;
+	for (i = 0; i < bip->bli_format_count; i++) {
+		if (!xfs_bitmap_empty(bip->bli_formats[i].blf_data_map,
+			     bip->bli_formats[i].blf_map_size)) {
+			clean = 0;
+			break;
+		}
+	}
+	if (clean)
 		xfs_buf_item_relse(bp);
-	else
+	else if (aborted) {
+		if (atomic_dec_and_test(&bip->bli_refcount)) {
+			ASSERT(XFS_FORCED_SHUTDOWN(lip->li_mountp));
+			xfs_buf_item_relse(bp);
+		}
+	} else
 		atomic_dec(&bip->bli_refcount);
 
 	if (!hold)
@@ -716,7 +741,7 @@
 	bip->bli_format_count = count;
 
 	if (count == 1) {
-		bip->bli_formats = &bip->bli_format;
+		bip->bli_formats = &bip->__bli_format;
 		return 0;
 	}
 
@@ -731,7 +756,7 @@
 xfs_buf_item_free_format(
 	struct xfs_buf_log_item	*bip)
 {
-	if (bip->bli_formats != &bip->bli_format) {
+	if (bip->bli_formats != &bip->__bli_format) {
 		kmem_free(bip->bli_formats);
 		bip->bli_formats = NULL;
 	}
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 6850f49..16def43 100644
--- a/fs/xfs/xfs_buf_item.h
+++ b/fs/xfs/xfs_buf_item.h
@@ -104,7 +104,7 @@
 #endif
 	int			bli_format_count;	/* count of headers */
 	struct xfs_buf_log_format *bli_formats;	/* array of in-log header ptrs */
-	struct xfs_buf_log_format bli_format;	/* embedded in-log header */
+	struct xfs_buf_log_format __bli_format;	/* embedded in-log header */
 } xfs_buf_log_item_t;
 
 void	xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *);
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c
index d0e9c74..a8bd26b 100644
--- a/fs/xfs/xfs_dfrag.c
+++ b/fs/xfs/xfs_dfrag.c
@@ -246,10 +246,10 @@
 		goto out_unlock;
 	}
 
-	error = -filemap_write_and_wait(VFS_I(ip)->i_mapping);
+	error = -filemap_write_and_wait(VFS_I(tip)->i_mapping);
 	if (error)
 		goto out_unlock;
-	truncate_pagecache_range(VFS_I(ip), 0, -1);
+	truncate_pagecache_range(VFS_I(tip), 0, -1);
 
 	/* Verify O_DIRECT for ftmp */
 	if (VN_CACHED(VFS_I(tip)) != 0) {
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c
index 7536faa..12afe07 100644
--- a/fs/xfs/xfs_dir2_block.c
+++ b/fs/xfs/xfs_dir2_block.c
@@ -355,10 +355,12 @@
 	/*
 	 * If need to compact the leaf entries, do it now.
 	 */
-	if (compact)
+	if (compact) {
 		xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog,
 				      &lfloghigh, &lfloglow);
-	else if (btp->stale) {
+		/* recalculate blp post-compaction */
+		blp = xfs_dir2_block_leaf_p(btp);
+	} else if (btp->stale) {
 		/*
 		 * Set leaf logging boundaries to impossible state.
 		 * For the no-stale case they're set explicitly.
diff --git a/fs/xfs/xfs_iomap.c b/fs/xfs/xfs_iomap.c
index add06b4..364818e 100644
--- a/fs/xfs/xfs_iomap.c
+++ b/fs/xfs/xfs_iomap.c
@@ -351,6 +351,15 @@
 		}
 		if (shift)
 			alloc_blocks >>= shift;
+
+		/*
+		 * If we are still trying to allocate more space than is
+		 * available, squash the prealloc hard. This can happen if we
+		 * have a large file on a small filesystem and the above
+		 * lowspace thresholds are smaller than MAXEXTLEN.
+		 */
+		while (alloc_blocks >= freesp)
+			alloc_blocks >>= 4;
 	}
 
 	if (alloc_blocks < mp->m_writeio_blocks)
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c
index da50846..7d6df7c 100644
--- a/fs/xfs/xfs_mount.c
+++ b/fs/xfs/xfs_mount.c
@@ -658,7 +658,7 @@
 		return;
 	}
 	/* quietly fail */
-	xfs_buf_ioerror(bp, EFSCORRUPTED);
+	xfs_buf_ioerror(bp, EWRONGFS);
 }
 
 static void
diff --git a/fs/xfs/xfs_qm_syscalls.c b/fs/xfs/xfs_qm_syscalls.c
index 5f53e75..8a59f85 100644
--- a/fs/xfs/xfs_qm_syscalls.c
+++ b/fs/xfs/xfs_qm_syscalls.c
@@ -784,11 +784,11 @@
 	     (XFS_IS_OQUOTA_ENFORCED(mp) &&
 			(dst->d_flags & (FS_PROJ_QUOTA | FS_GROUP_QUOTA)))) &&
 	    dst->d_id != 0) {
-		if (((int) dst->d_bcount > (int) dst->d_blk_softlimit) &&
+		if ((dst->d_bcount > dst->d_blk_softlimit) &&
 		    (dst->d_blk_softlimit > 0)) {
 			ASSERT(dst->d_btimer != 0);
 		}
-		if (((int) dst->d_icount > (int) dst->d_ino_softlimit) &&
+		if ((dst->d_icount > dst->d_ino_softlimit) &&
 		    (dst->d_ino_softlimit > 0)) {
 			ASSERT(dst->d_itimer != 0);
 		}
diff --git a/fs/xfs/xfs_trace.h b/fs/xfs/xfs_trace.h
index 2e137d4..16a8129 100644
--- a/fs/xfs/xfs_trace.h
+++ b/fs/xfs/xfs_trace.h
@@ -341,6 +341,7 @@
 DEFINE_BUF_EVENT(xfs_buf_item_iodone);
 DEFINE_BUF_EVENT(xfs_buf_item_iodone_async);
 DEFINE_BUF_EVENT(xfs_buf_error_relse);
+DEFINE_BUF_EVENT(xfs_buf_wait_buftarg);
 DEFINE_BUF_EVENT(xfs_trans_read_buf_io);
 DEFINE_BUF_EVENT(xfs_trans_read_buf_shut);
 
diff --git a/fs/xfs/xfs_trans_buf.c b/fs/xfs/xfs_trans_buf.c
index 4fc17d4..3edf5db 100644
--- a/fs/xfs/xfs_trans_buf.c
+++ b/fs/xfs/xfs_trans_buf.c
@@ -93,7 +93,7 @@
 	xfs_buf_item_init(bp, tp->t_mountp);
 	bip = bp->b_fspriv;
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-	ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
+	ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
 	ASSERT(!(bip->bli_flags & XFS_BLI_LOGGED));
 	if (reset_recur)
 		bip->bli_recur = 0;
@@ -432,7 +432,7 @@
 	bip = bp->b_fspriv;
 	ASSERT(bip->bli_item.li_type == XFS_LI_BUF);
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-	ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
+	ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
 	trace_xfs_trans_brelse(bip);
@@ -519,7 +519,7 @@
 	ASSERT(bp->b_transp == tp);
 	ASSERT(bip != NULL);
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-	ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
+	ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
 	bip->bli_flags |= XFS_BLI_HOLD;
@@ -539,7 +539,7 @@
 	ASSERT(bp->b_transp == tp);
 	ASSERT(bip != NULL);
 	ASSERT(!(bip->bli_flags & XFS_BLI_STALE));
-	ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_CANCEL));
+	ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_CANCEL));
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 	ASSERT(bip->bli_flags & XFS_BLI_HOLD);
 
@@ -598,7 +598,7 @@
 		bip->bli_flags &= ~XFS_BLI_STALE;
 		ASSERT(XFS_BUF_ISSTALE(bp));
 		XFS_BUF_UNSTALE(bp);
-		bip->bli_format.blf_flags &= ~XFS_BLF_CANCEL;
+		bip->__bli_format.blf_flags &= ~XFS_BLF_CANCEL;
 	}
 
 	tp->t_flags |= XFS_TRANS_DIRTY;
@@ -643,6 +643,7 @@
 	xfs_buf_t	*bp)
 {
 	xfs_buf_log_item_t	*bip = bp->b_fspriv;
+	int			i;
 
 	ASSERT(bp->b_transp == tp);
 	ASSERT(bip != NULL);
@@ -657,8 +658,8 @@
 		 */
 		ASSERT(XFS_BUF_ISSTALE(bp));
 		ASSERT(!(bip->bli_flags & (XFS_BLI_LOGGED | XFS_BLI_DIRTY)));
-		ASSERT(!(bip->bli_format.blf_flags & XFS_BLF_INODE_BUF));
-		ASSERT(bip->bli_format.blf_flags & XFS_BLF_CANCEL);
+		ASSERT(!(bip->__bli_format.blf_flags & XFS_BLF_INODE_BUF));
+		ASSERT(bip->__bli_format.blf_flags & XFS_BLF_CANCEL);
 		ASSERT(bip->bli_item.li_desc->lid_flags & XFS_LID_DIRTY);
 		ASSERT(tp->t_flags & XFS_TRANS_DIRTY);
 		return;
@@ -668,10 +669,12 @@
 
 	bip->bli_flags |= XFS_BLI_STALE;
 	bip->bli_flags &= ~(XFS_BLI_INODE_BUF | XFS_BLI_LOGGED | XFS_BLI_DIRTY);
-	bip->bli_format.blf_flags &= ~XFS_BLF_INODE_BUF;
-	bip->bli_format.blf_flags |= XFS_BLF_CANCEL;
-	memset((char *)(bip->bli_format.blf_data_map), 0,
-	      (bip->bli_format.blf_map_size * sizeof(uint)));
+	bip->__bli_format.blf_flags &= ~XFS_BLF_INODE_BUF;
+	bip->__bli_format.blf_flags |= XFS_BLF_CANCEL;
+	for (i = 0; i < bip->bli_format_count; i++) {
+		memset(bip->bli_formats[i].blf_data_map, 0,
+		       (bip->bli_formats[i].blf_map_size * sizeof(uint)));
+	}
 	bip->bli_item.li_desc->lid_flags |= XFS_LID_DIRTY;
 	tp->t_flags |= XFS_TRANS_DIRTY;
 }
@@ -775,5 +778,5 @@
 	       type == XFS_BLF_GDQUOT_BUF);
 	ASSERT(atomic_read(&bip->bli_refcount) > 0);
 
-	bip->bli_format.blf_flags |= type;
+	bip->__bli_format.blf_flags |= type;
 }
diff --git a/include/asm-generic/dma-mapping-broken.h b/include/asm-generic/dma-mapping-broken.h
index ccf7b4f..6c32af9 100644
--- a/include/asm-generic/dma-mapping-broken.h
+++ b/include/asm-generic/dma-mapping-broken.h
@@ -16,6 +16,22 @@
 dma_free_coherent(struct device *dev, size_t size, void *cpu_addr,
 		    dma_addr_t dma_handle);
 
+static inline void *dma_alloc_attrs(struct device *dev, size_t size,
+				    dma_addr_t *dma_handle, gfp_t flag,
+				    struct dma_attrs *attrs)
+{
+	/* attrs is not supported and ignored */
+	return dma_alloc_coherent(dev, size, dma_handle, flag);
+}
+
+static inline void dma_free_attrs(struct device *dev, size_t size,
+				  void *cpu_addr, dma_addr_t dma_handle,
+				  struct dma_attrs *attrs)
+{
+	/* attrs is not supported and ignored */
+	dma_free_coherent(dev, size, cpu_addr, dma_handle);
+}
+
 #define dma_alloc_noncoherent(d, s, h, f) dma_alloc_coherent(d, s, h, f)
 #define dma_free_noncoherent(d, s, v, h) dma_free_coherent(d, s, v, h)
 
diff --git a/include/asm-generic/pgtable.h b/include/asm-generic/pgtable.h
index 701beab..5cf680a9 100644
--- a/include/asm-generic/pgtable.h
+++ b/include/asm-generic/pgtable.h
@@ -461,10 +461,8 @@
 	return offset_from_zero_pfn <= (zero_page_mask >> PAGE_SHIFT);
 }
 
-static inline unsigned long my_zero_pfn(unsigned long addr)
-{
-	return page_to_pfn(ZERO_PAGE(addr));
-}
+#define my_zero_pfn(addr)	page_to_pfn(ZERO_PAGE(addr))
+
 #else
 static inline int is_zero_pfn(unsigned long pfn)
 {
diff --git a/include/asm-generic/syscalls.h b/include/asm-generic/syscalls.h
index 58f466f..1db51b8 100644
--- a/include/asm-generic/syscalls.h
+++ b/include/asm-generic/syscalls.h
@@ -21,10 +21,12 @@
 			unsigned long fd, off_t pgoff);
 #endif
 
+#ifndef CONFIG_GENERIC_SIGALTSTACK
 #ifndef sys_sigaltstack
 asmlinkage long sys_sigaltstack(const stack_t __user *, stack_t __user *,
 			struct pt_regs *);
 #endif
+#endif
 
 #ifndef sys_rt_sigreturn
 asmlinkage long sys_rt_sigreturn(struct pt_regs *regs);
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index d1ea7ce..fc62ac5 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -149,6 +149,24 @@
 #define TRACE_SYSCALLS()
 #endif
 
+#ifdef CONFIG_CLKSRC_OF
+#define CLKSRC_OF_TABLES() . = ALIGN(8);				\
+			   VMLINUX_SYMBOL(__clksrc_of_table) = .;	\
+			   *(__clksrc_of_table)				\
+			   *(__clksrc_of_table_end)
+#else
+#define CLKSRC_OF_TABLES()
+#endif
+
+#ifdef CONFIG_IRQCHIP
+#define IRQCHIP_OF_MATCH_TABLE()					\
+	. = ALIGN(8);							\
+	VMLINUX_SYMBOL(__irqchip_begin) = .;				\
+	*(__irqchip_of_table)		  				\
+	*(__irqchip_of_end)
+#else
+#define IRQCHIP_OF_MATCH_TABLE()
+#endif
 
 #define KERNEL_DTB()							\
 	STRUCT_ALIGN();							\
@@ -493,7 +511,9 @@
 	DEV_DISCARD(init.rodata)					\
 	CPU_DISCARD(init.rodata)					\
 	MEM_DISCARD(init.rodata)					\
-	KERNEL_DTB()
+	CLKSRC_OF_TABLES()						\
+	KERNEL_DTB()							\
+	IRQCHIP_OF_MATCH_TABLE()
 
 #define INIT_TEXT							\
 	*(.init.text)							\
diff --git a/include/drm/drm_mm.h b/include/drm/drm_mm.h
index 0f4a366..3527fb3f 100644
--- a/include/drm/drm_mm.h
+++ b/include/drm/drm_mm.h
@@ -70,7 +70,7 @@
 	unsigned long scan_color;
 	unsigned long scan_size;
 	unsigned long scan_hit_start;
-	unsigned scan_hit_size;
+	unsigned long scan_hit_end;
 	unsigned scanned_blocks;
 	unsigned long scan_start;
 	unsigned long scan_end;
diff --git a/include/linux/ata.h b/include/linux/ata.h
index 408da95..8f7a3d6 100644
--- a/include/linux/ata.h
+++ b/include/linux/ata.h
@@ -297,10 +297,12 @@
 	ATA_LOG_SATA_NCQ	= 0x10,
 	ATA_LOG_SATA_ID_DEV_DATA  = 0x30,
 	ATA_LOG_SATA_SETTINGS	  = 0x08,
-	ATA_LOG_DEVSLP_MDAT	  = 0x30,
+	ATA_LOG_DEVSLP_OFFSET	  = 0x30,
+	ATA_LOG_DEVSLP_SIZE	  = 0x08,
+	ATA_LOG_DEVSLP_MDAT	  = 0x00,
 	ATA_LOG_DEVSLP_MDAT_MASK  = 0x1F,
-	ATA_LOG_DEVSLP_DETO	  = 0x31,
-	ATA_LOG_DEVSLP_VALID	  = 0x37,
+	ATA_LOG_DEVSLP_DETO	  = 0x01,
+	ATA_LOG_DEVSLP_VALID	  = 0x07,
 	ATA_LOG_DEVSLP_VALID_MASK = 0x80,
 
 	/* READ/WRITE LONG (obsolete) */
diff --git a/include/linux/audit.h b/include/linux/audit.h
index bce729a..5a6d718 100644
--- a/include/linux/audit.h
+++ b/include/linux/audit.h
@@ -24,6 +24,7 @@
 #define _LINUX_AUDIT_H_
 
 #include <linux/sched.h>
+#include <linux/ptrace.h>
 #include <uapi/linux/audit.h>
 
 struct audit_sig_info {
@@ -157,7 +158,8 @@
 
 static inline void audit_seccomp(unsigned long syscall, long signr, int code)
 {
-	if (unlikely(!audit_dummy_context()))
+	/* Force a record to be reported if a signal was delivered. */
+	if (signr || unlikely(!audit_dummy_context()))
 		__audit_seccomp(syscall, signr, code);
 }
 
diff --git a/include/linux/bcm2835_timer.h b/include/linux/bcm2835_timer.h
index 25680fe..ca17aa8 100644
--- a/include/linux/bcm2835_timer.h
+++ b/include/linux/bcm2835_timer.h
@@ -17,6 +17,6 @@
 
 #include <asm/mach/time.h>
 
-extern struct sys_timer bcm2835_timer;
+extern void bcm2835_timer_init(void);
 
 #endif
diff --git a/arch/arm/mach-tegra/tegra_cpu_car.h b/include/linux/clk/tegra.h
similarity index 91%
rename from arch/arm/mach-tegra/tegra_cpu_car.h
rename to include/linux/clk/tegra.h
index 9764d31..404d6f9 100644
--- a/arch/arm/mach-tegra/tegra_cpu_car.h
+++ b/include/linux/clk/tegra.h
@@ -14,8 +14,10 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
-#ifndef __MACH_TEGRA_CPU_CAR_H
-#define __MACH_TEGRA_CPU_CAR_H
+#ifndef __LINUX_CLK_TEGRA_H_
+#define __LINUX_CLK_TEGRA_H_
+
+#include <linux/clk.h>
 
 /*
  * Tegra CPU clock and reset control ops
@@ -118,7 +120,8 @@
 }
 #endif
 
-void tegra20_cpu_car_ops_init(void);
-void tegra30_cpu_car_ops_init(void);
+void tegra_periph_reset_deassert(struct clk *c);
+void tegra_periph_reset_assert(struct clk *c);
+void tegra_clocks_init(void);
 
-#endif /* __MACH_TEGRA_CPU_CAR_H */
+#endif /* __LINUX_CLK_TEGRA_H_ */
diff --git a/include/linux/clocksource.h b/include/linux/clocksource.h
index 4dceaf8..7944f14 100644
--- a/include/linux/clocksource.h
+++ b/include/linux/clocksource.h
@@ -332,4 +332,13 @@
 
 extern int clocksource_i8253_init(void);
 
+#ifdef CONFIG_CLKSRC_OF
+extern void clocksource_of_init(void);
+
+#define CLOCKSOURCE_OF_DECLARE(name, compat, fn)			\
+	static const struct of_device_id __clksrc_of_table_##name	\
+		__used __section(__clksrc_of_table)			\
+		 = { .compatible = compat, .data = fn };
+#endif
+
 #endif /* _LINUX_CLOCKSOURCE_H */
diff --git a/include/linux/compaction.h b/include/linux/compaction.h
index 6ecb6dc..cc7bdde 100644
--- a/include/linux/compaction.h
+++ b/include/linux/compaction.h
@@ -22,7 +22,7 @@
 extern int fragmentation_index(struct zone *zone, unsigned int order);
 extern unsigned long try_to_compact_pages(struct zonelist *zonelist,
 			int order, gfp_t gfp_mask, nodemask_t *mask,
-			bool sync, bool *contended, struct page **page);
+			bool sync, bool *contended);
 extern int compact_pgdat(pg_data_t *pgdat, int order);
 extern void reset_isolation_suitable(pg_data_t *pgdat);
 extern unsigned long compaction_suitable(struct zone *zone, int order);
@@ -75,7 +75,7 @@
 #else
 static inline unsigned long try_to_compact_pages(struct zonelist *zonelist,
 			int order, gfp_t gfp_mask, nodemask_t *nodemask,
-			bool sync, bool *contended, struct page **page)
+			bool sync, bool *contended)
 {
 	return COMPACT_CONTINUE;
 }
diff --git a/include/linux/cpu_rmap.h b/include/linux/cpu_rmap.h
index ac3bbb5..1739510 100644
--- a/include/linux/cpu_rmap.h
+++ b/include/linux/cpu_rmap.h
@@ -13,9 +13,11 @@
 #include <linux/cpumask.h>
 #include <linux/gfp.h>
 #include <linux/slab.h>
+#include <linux/kref.h>
 
 /**
  * struct cpu_rmap - CPU affinity reverse-map
+ * @refcount: kref for object
  * @size: Number of objects to be reverse-mapped
  * @used: Number of objects added
  * @obj: Pointer to array of object pointers
@@ -23,6 +25,7 @@
  *      based on affinity masks
  */
 struct cpu_rmap {
+	struct kref	refcount;
 	u16		size, used;
 	void		**obj;
 	struct {
@@ -33,15 +36,7 @@
 #define CPU_RMAP_DIST_INF 0xffff
 
 extern struct cpu_rmap *alloc_cpu_rmap(unsigned int size, gfp_t flags);
-
-/**
- * free_cpu_rmap - free CPU affinity reverse-map
- * @rmap: Reverse-map allocated with alloc_cpu_rmap(), or %NULL
- */
-static inline void free_cpu_rmap(struct cpu_rmap *rmap)
-{
-	kfree(rmap);
-}
+extern int cpu_rmap_put(struct cpu_rmap *rmap);
 
 extern int cpu_rmap_add(struct cpu_rmap *rmap, void *obj);
 extern int cpu_rmap_update(struct cpu_rmap *rmap, u16 index,
diff --git a/include/linux/cpuidle.h b/include/linux/cpuidle.h
index 3711b34..24cd1037 100644
--- a/include/linux/cpuidle.h
+++ b/include/linux/cpuidle.h
@@ -126,9 +126,9 @@
 	struct module 		*owner;
 	int                     refcnt;
 
-	unsigned int		power_specified:1;
 	/* set to 1 to use the core cpuidle time keeping (for all states). */
 	unsigned int		en_core_tk_irqen:1;
+	/* states array must be ordered in decreasing power consumption */
 	struct cpuidle_state	states[CPUIDLE_STATE_MAX];
 	int			state_count;
 	int			safe_state_index;
diff --git a/include/linux/dw_apb_timer.h b/include/linux/dw_apb_timer.h
index 1148575..dd755ce 100644
--- a/include/linux/dw_apb_timer.h
+++ b/include/linux/dw_apb_timer.h
@@ -53,5 +53,5 @@
 cycle_t dw_apb_clocksource_read(struct dw_apb_clocksource *dw_cs);
 void dw_apb_clocksource_unregister(struct dw_apb_clocksource *dw_cs);
 
-extern struct sys_timer dw_apb_timer;
+extern void dw_apb_timer_init(void);
 #endif /* __DW_APB_TIMER_H__ */
diff --git a/include/linux/efi.h b/include/linux/efi.h
index 8b84916..7a9498a 100644
--- a/include/linux/efi.h
+++ b/include/linux/efi.h
@@ -618,18 +618,30 @@
 #endif
 
 /*
- * We play games with efi_enabled so that the compiler will, if possible, remove
- * EFI-related code altogether.
+ * We play games with efi_enabled so that the compiler will, if
+ * possible, remove EFI-related code altogether.
  */
+#define EFI_BOOT		0	/* Were we booted from EFI? */
+#define EFI_SYSTEM_TABLES	1	/* Can we use EFI system tables? */
+#define EFI_CONFIG_TABLES	2	/* Can we use EFI config tables? */
+#define EFI_RUNTIME_SERVICES	3	/* Can we use runtime services? */
+#define EFI_MEMMAP		4	/* Can we use EFI memory map? */
+#define EFI_64BIT		5	/* Is the firmware 64-bit? */
+
 #ifdef CONFIG_EFI
 # ifdef CONFIG_X86
-   extern int efi_enabled;
-   extern bool efi_64bit;
+extern int efi_enabled(int facility);
 # else
-#  define efi_enabled 1
+static inline int efi_enabled(int facility)
+{
+	return 1;
+}
 # endif
 #else
-# define efi_enabled 0
+static inline int efi_enabled(int facility)
+{
+	return 0;
+}
 #endif
 
 /*
diff --git a/include/linux/init.h b/include/linux/init.h
index a799273..10ed4f4 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -93,14 +93,6 @@
 
 #define __exit          __section(.exit.text) __exitused __cold notrace
 
-/* Used for HOTPLUG, but that is always enabled now, so just make them noops */
-#define __devinit
-#define __devinitdata
-#define __devinitconst
-#define __devexit
-#define __devexitdata
-#define __devexitconst
-
 /* Used for HOTPLUG_CPU */
 #define __cpuinit        __section(.cpuinit.text) __cold notrace
 #define __cpuinitdata    __section(.cpuinit.data)
@@ -337,18 +329,6 @@
 #define __INITRODATA_OR_MODULE __INITRODATA
 #endif /*CONFIG_MODULES*/
 
-/* Functions marked as __devexit may be discarded at kernel link time, depending
-   on config options.  Newer versions of binutils detect references from
-   retained sections to discarded sections and flag an error.  Pointers to
-   __devexit functions must use __devexit_p(function_name), the wrapper will
-   insert either the function_name or NULL, depending on the config options.
- */
-#if defined(MODULE) || defined(CONFIG_HOTPLUG)
-#define __devexit_p(x) x
-#else
-#define __devexit_p(x) NULL
-#endif
-
 #ifdef MODULE
 #define __exit_p(x) x
 #else
diff --git a/include/linux/interrupt.h b/include/linux/interrupt.h
index 5e4e617..5fa5afe 100644
--- a/include/linux/interrupt.h
+++ b/include/linux/interrupt.h
@@ -268,11 +268,6 @@
 extern int
 irq_set_affinity_notifier(unsigned int irq, struct irq_affinity_notify *notify);
 
-static inline void irq_run_affinity_notifiers(void)
-{
-	flush_scheduled_work();
-}
-
 #else /* CONFIG_SMP */
 
 static inline int irq_set_affinity(unsigned int irq, const struct cpumask *m)
diff --git a/include/linux/irqchip.h b/include/linux/irqchip.h
new file mode 100644
index 0000000..e0006f1
--- /dev/null
+++ b/include/linux/irqchip.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2012 Thomas Petazzoni
+ *
+ * Thomas Petazzoni <thomas.petazzoni@free-electrons.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 _LINUX_IRQCHIP_H
+#define _LINUX_IRQCHIP_H
+
+void irqchip_init(void);
+
+#endif
diff --git a/arch/arm/include/asm/hardware/gic.h b/include/linux/irqchip/arm-gic.h
similarity index 76%
rename from arch/arm/include/asm/hardware/gic.h
rename to include/linux/irqchip/arm-gic.h
index 4b1ce6c..a67ca55 100644
--- a/arch/arm/include/asm/hardware/gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -1,5 +1,5 @@
 /*
- *  arch/arm/include/asm/hardware/gic.h
+ *  include/linux/irqchip/arm-gic.h
  *
  *  Copyright (C) 2002 ARM Limited, All Rights Reserved.
  *
@@ -7,10 +7,8 @@
  * it under the terms of the GNU General Public License version 2 as
  * published by the Free Software Foundation.
  */
-#ifndef __ASM_ARM_HARDWARE_GIC_H
-#define __ASM_ARM_HARDWARE_GIC_H
-
-#include <linux/compiler.h>
+#ifndef __LINUX_IRQCHIP_ARM_GIC_H
+#define __LINUX_IRQCHIP_ARM_GIC_H
 
 #define GIC_CPU_CTRL			0x00
 #define GIC_CPU_PRIMASK			0x04
@@ -32,19 +30,14 @@
 #define GIC_DIST_CONFIG			0xc00
 #define GIC_DIST_SOFTINT		0xf00
 
-#ifndef __ASSEMBLY__
-#include <linux/irqdomain.h>
 struct device_node;
 
 extern struct irq_chip gic_arch_extn;
 
 void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
 		    u32 offset, struct device_node *);
-int gic_of_init(struct device_node *node, struct device_node *parent);
 void gic_secondary_init(unsigned int);
-void gic_handle_irq(struct pt_regs *regs);
 void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
-void gic_raise_softirq(const struct cpumask *mask, unsigned int irq);
 
 static inline void gic_init(unsigned int nr, int start,
 			    void __iomem *dist , void __iomem *cpu)
@@ -53,5 +46,3 @@
 }
 
 #endif
-
-#endif
diff --git a/arch/arm/include/asm/hardware/vic.h b/include/linux/irqchip/arm-vic.h
similarity index 63%
rename from arch/arm/include/asm/hardware/vic.h
rename to include/linux/irqchip/arm-vic.h
index 2bebad3..e3c82dc 100644
--- a/arch/arm/include/asm/hardware/vic.h
+++ b/include/linux/irqchip/arm-vic.h
@@ -20,29 +20,11 @@
 #ifndef __ASM_ARM_HARDWARE_VIC_H
 #define __ASM_ARM_HARDWARE_VIC_H
 
-#define VIC_IRQ_STATUS			0x00
-#define VIC_FIQ_STATUS			0x04
+#include <linux/types.h>
+
 #define VIC_RAW_STATUS			0x08
-#define VIC_INT_SELECT			0x0c	/* 1 = FIQ, 0 = IRQ */
 #define VIC_INT_ENABLE			0x10	/* 1 = enable, 0 = disable */
 #define VIC_INT_ENABLE_CLEAR		0x14
-#define VIC_INT_SOFT			0x18
-#define VIC_INT_SOFT_CLEAR		0x1c
-#define VIC_PROTECT			0x20
-#define VIC_PL190_VECT_ADDR		0x30	/* PL190 only */
-#define VIC_PL190_DEF_VECT_ADDR		0x34	/* PL190 only */
-
-#define VIC_VECT_ADDR0			0x100	/* 0 to 15 (0..31 PL192) */
-#define VIC_VECT_CNTL0			0x200	/* 0 to 15 (0..31 PL192) */
-#define VIC_ITCR			0x300	/* VIC test control register */
-
-#define VIC_VECT_CNTL_ENABLE		(1 << 5)
-
-#define VIC_PL192_VECT_ADDR		0xF00
-
-#ifndef __ASSEMBLY__
-#include <linux/compiler.h>
-#include <linux/types.h>
 
 struct device_node;
 struct pt_regs;
@@ -50,8 +32,5 @@
 void __vic_init(void __iomem *base, int irq_start, u32 vic_sources,
 		u32 resume_sources, struct device_node *node);
 void vic_init(void __iomem *base, unsigned int irq_start, u32 vic_sources, u32 resume_sources);
-int vic_of_init(struct device_node *node, struct device_node *parent);
-void vic_handle_irq(struct pt_regs *regs);
 
-#endif /* __ASSEMBLY__ */
 #endif
diff --git a/include/linux/libata.h b/include/linux/libata.h
index 83ba0ab..649e5f8 100644
--- a/include/linux/libata.h
+++ b/include/linux/libata.h
@@ -652,8 +652,8 @@
 		u32		gscr[SATA_PMP_GSCR_DWORDS]; /* PMP GSCR block */
 	};
 
-	/* Identify Device Data Log (30h), SATA Settings (page 08h) */
-	u8			sata_settings[ATA_SECT_SIZE];
+	/* DEVSLP Timing Variables from Identify Device Data Log */
+	u8			devslp_timing[ATA_LOG_DEVSLP_SIZE];
 
 	/* error history */
 	int			spdn_cnt;
diff --git a/include/linux/lockdep.h b/include/linux/lockdep.h
index 00e4637..2bca44b 100644
--- a/include/linux/lockdep.h
+++ b/include/linux/lockdep.h
@@ -524,14 +524,17 @@
 #ifdef CONFIG_DEBUG_LOCK_ALLOC
 # ifdef CONFIG_PROVE_LOCKING
 #  define rwsem_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 2, NULL, i)
+#  define rwsem_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 2, n, i)
 #  define rwsem_acquire_read(l, s, t, i)	lock_acquire(l, s, t, 1, 2, NULL, i)
 # else
 #  define rwsem_acquire(l, s, t, i)		lock_acquire(l, s, t, 0, 1, NULL, i)
+#  define rwsem_acquire_nest(l, s, t, n, i)	lock_acquire(l, s, t, 0, 1, n, i)
 #  define rwsem_acquire_read(l, s, t, i)	lock_acquire(l, s, t, 1, 1, NULL, i)
 # endif
 # define rwsem_release(l, n, i)			lock_release(l, n, i)
 #else
 # define rwsem_acquire(l, s, t, i)		do { } while (0)
+# define rwsem_acquire_nest(l, s, t, n, i)	do { } while (0)
 # define rwsem_acquire_read(l, s, t, i)		do { } while (0)
 # define rwsem_release(l, n, i)			do { } while (0)
 #endif
diff --git a/include/linux/mfd/abx500.h b/include/linux/mfd/abx500.h
index 2138bd3..e53dcfe 100644
--- a/include/linux/mfd/abx500.h
+++ b/include/linux/mfd/abx500.h
@@ -272,8 +272,6 @@
 	const struct abx500_fg_parameters *fg_params;
 };
 
-extern struct abx500_bm_data ab8500_bm_data;
-
 enum {
 	NTC_EXTERNAL = 0,
 	NTC_INTERNAL,
diff --git a/include/linux/mfd/abx500/ab8500-bm.h b/include/linux/mfd/abx500/ab8500-bm.h
index 44310c9..9bd037d 100644
--- a/include/linux/mfd/abx500/ab8500-bm.h
+++ b/include/linux/mfd/abx500/ab8500-bm.h
@@ -422,7 +422,10 @@
 struct ab8500_btemp;
 struct ab8500_gpadc;
 struct ab8500_fg;
+
 #ifdef CONFIG_AB8500_BM
+extern struct abx500_bm_data ab8500_bm_data;
+
 void ab8500_fg_reinit(void);
 void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA);
 struct ab8500_btemp *ab8500_btemp_get(void);
@@ -434,31 +437,7 @@
 int ab8500_fg_inst_curr_done(struct ab8500_fg *di);
 
 #else
-int ab8500_fg_inst_curr_done(struct ab8500_fg *di)
-{
-}
-static void ab8500_fg_reinit(void)
-{
-}
-static void ab8500_charger_usb_state_changed(u8 bm_usb_state, u16 mA)
-{
-}
-static struct ab8500_btemp *ab8500_btemp_get(void)
-{
-	return NULL;
-}
-static int ab8500_btemp_get_batctrl_temp(struct ab8500_btemp *btemp)
-{
-	return 0;
-}
-struct ab8500_fg *ab8500_fg_get(void)
-{
-	return NULL;
-}
-static int ab8500_fg_inst_curr_blocking(struct ab8500_fg *dev)
-{
-	return -ENODEV;
-}
+static struct abx500_bm_data ab8500_bm_data;
 
 static inline int ab8500_fg_inst_curr_start(struct ab8500_fg *di)
 {
diff --git a/include/linux/mfd/da9052/da9052.h b/include/linux/mfd/da9052/da9052.h
index 86dd93d..786d02e 100644
--- a/include/linux/mfd/da9052/da9052.h
+++ b/include/linux/mfd/da9052/da9052.h
@@ -99,6 +99,9 @@
 	u8 chip_id;
 
 	int chip_irq;
+
+	/* SOC I/O transfer related fixes for DA9052/53 */
+	int (*fix_io) (struct da9052 *da9052, unsigned char reg);
 };
 
 /* ADC API */
@@ -113,32 +116,87 @@
 	ret = regmap_read(da9052->regmap, reg, &val);
 	if (ret < 0)
 		return ret;
+
+	if (da9052->fix_io) {
+		ret = da9052->fix_io(da9052, reg);
+		if (ret < 0)
+			return ret;
+	}
+
 	return val;
 }
 
 static inline int da9052_reg_write(struct da9052 *da9052, unsigned char reg,
 				    unsigned char val)
 {
-	return regmap_write(da9052->regmap, reg, val);
+	int ret;
+
+	ret = regmap_write(da9052->regmap, reg, val);
+	if (ret < 0)
+		return ret;
+
+	if (da9052->fix_io) {
+		ret = da9052->fix_io(da9052, reg);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ret;
 }
 
 static inline int da9052_group_read(struct da9052 *da9052, unsigned char reg,
 				     unsigned reg_cnt, unsigned char *val)
 {
-	return regmap_bulk_read(da9052->regmap, reg, val, reg_cnt);
+	int ret;
+
+	ret = regmap_bulk_read(da9052->regmap, reg, val, reg_cnt);
+	if (ret < 0)
+		return ret;
+
+	if (da9052->fix_io) {
+		ret = da9052->fix_io(da9052, reg);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ret;
 }
 
 static inline int da9052_group_write(struct da9052 *da9052, unsigned char reg,
 				      unsigned reg_cnt, unsigned char *val)
 {
-	return regmap_raw_write(da9052->regmap, reg, val, reg_cnt);
+	int ret;
+
+	ret = regmap_raw_write(da9052->regmap, reg, val, reg_cnt);
+	if (ret < 0)
+		return ret;
+
+	if (da9052->fix_io) {
+		ret = da9052->fix_io(da9052, reg);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ret;
 }
 
 static inline int da9052_reg_update(struct da9052 *da9052, unsigned char reg,
 				     unsigned char bit_mask,
 				     unsigned char reg_val)
 {
-	return regmap_update_bits(da9052->regmap, reg, bit_mask, reg_val);
+	int ret;
+
+	ret = regmap_update_bits(da9052->regmap, reg, bit_mask, reg_val);
+	if (ret < 0)
+		return ret;
+
+	if (da9052->fix_io) {
+		ret = da9052->fix_io(da9052, reg);
+		if (ret < 0)
+			return ret;
+	}
+
+	return ret;
 }
 
 int da9052_device_init(struct da9052 *da9052, u8 chip_id);
diff --git a/include/linux/mfd/da9052/reg.h b/include/linux/mfd/da9052/reg.h
index b97f730..c4dd3a8 100644
--- a/include/linux/mfd/da9052/reg.h
+++ b/include/linux/mfd/da9052/reg.h
@@ -34,6 +34,9 @@
 #define DA9052_STATUS_C_REG		3
 #define DA9052_STATUS_D_REG		4
 
+/* PARK REGISTER */
+#define DA9052_PARK_REGISTER		DA9052_STATUS_D_REG
+
 /* EVENT REGISTERS */
 #define DA9052_EVENT_A_REG		5
 #define DA9052_EVENT_B_REG		6
diff --git a/include/linux/mfd/rtsx_common.h b/include/linux/mfd/rtsx_common.h
index a8d393e..2b13970 100644
--- a/include/linux/mfd/rtsx_common.h
+++ b/include/linux/mfd/rtsx_common.h
@@ -38,6 +38,9 @@
 #define RTSX_SD_CARD			0
 #define RTSX_MS_CARD			1
 
+#define CLK_TO_DIV_N			0
+#define DIV_N_TO_CLK			1
+
 struct platform_device;
 
 struct rtsx_slot {
diff --git a/include/linux/mfd/rtsx_pci.h b/include/linux/mfd/rtsx_pci.h
index 060b721..4b117a3 100644
--- a/include/linux/mfd/rtsx_pci.h
+++ b/include/linux/mfd/rtsx_pci.h
@@ -158,10 +158,9 @@
 #define SG_TRANS_DATA		(0x02 << 4)
 #define SG_LINK_DESC		(0x03 << 4)
 
-/* SD bank voltage */
-#define SD_IO_3V3		0
-#define SD_IO_1V8		1
-
+/* Output voltage */
+#define OUTPUT_3V3		0
+#define OUTPUT_1V8		1
 
 /* Card Clock Enable Register */
 #define SD_CLK_EN			0x04
@@ -201,6 +200,20 @@
 #define CHANGE_CLK			0x01
 
 /* LDO_CTL */
+#define BPP_ASIC_1V7			0x00
+#define BPP_ASIC_1V8			0x01
+#define BPP_ASIC_1V9			0x02
+#define BPP_ASIC_2V0			0x03
+#define BPP_ASIC_2V7			0x04
+#define BPP_ASIC_2V8			0x05
+#define BPP_ASIC_3V2			0x06
+#define BPP_ASIC_3V3			0x07
+#define BPP_REG_TUNED18			0x07
+#define BPP_TUNED18_SHIFT_8402		5
+#define BPP_TUNED18_SHIFT_8411		4
+#define BPP_PAD_MASK			0x04
+#define BPP_PAD_3V3			0x04
+#define BPP_PAD_1V8			0x00
 #define BPP_LDO_POWB			0x03
 #define BPP_LDO_ON			0x00
 #define BPP_LDO_SUSPEND			0x02
@@ -688,7 +701,10 @@
 	int		(*disable_auto_blink)(struct rtsx_pcr *pcr);
 	int		(*card_power_on)(struct rtsx_pcr *pcr, int card);
 	int		(*card_power_off)(struct rtsx_pcr *pcr, int card);
+	int		(*switch_output_voltage)(struct rtsx_pcr *pcr,
+						u8 voltage);
 	unsigned int	(*cd_deglitch)(struct rtsx_pcr *pcr);
+	int		(*conv_clk_and_div_n)(int clk, int dir);
 };
 
 enum PDEV_STAT  {PDEV_STAT_IDLE, PDEV_STAT_RUN};
@@ -783,6 +799,7 @@
 		u8 ssc_depth, bool initial_mode, bool double_clk, bool vpclk);
 int rtsx_pci_card_power_on(struct rtsx_pcr *pcr, int card);
 int rtsx_pci_card_power_off(struct rtsx_pcr *pcr, int card);
+int rtsx_pci_switch_output_voltage(struct rtsx_pcr *pcr, u8 voltage);
 unsigned int rtsx_pci_card_exist(struct rtsx_pcr *pcr);
 void rtsx_pci_complete_unfinished_transfer(struct rtsx_pcr *pcr);
 
diff --git a/include/linux/mm.h b/include/linux/mm.h
index 6320407..66e2f7c 100644
--- a/include/linux/mm.h
+++ b/include/linux/mm.h
@@ -455,7 +455,6 @@
 
 void split_page(struct page *page, unsigned int order);
 int split_free_page(struct page *page);
-int capture_free_page(struct page *page, int alloc_order, int migratetype);
 
 /*
  * Compound pages have a destructor function.  Provide a
diff --git a/include/linux/module.h b/include/linux/module.h
index 7760c6d..1375ee3 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -199,11 +199,11 @@
 	struct module *source, *target;
 };
 
-enum module_state
-{
-	MODULE_STATE_LIVE,
-	MODULE_STATE_COMING,
-	MODULE_STATE_GOING,
+enum module_state {
+	MODULE_STATE_LIVE,	/* Normal state. */
+	MODULE_STATE_COMING,	/* Full formed, running module_init. */
+	MODULE_STATE_GOING,	/* Going away. */
+	MODULE_STATE_UNFORMED,	/* Still setting it up. */
 };
 
 /**
diff --git a/include/linux/netdevice.h b/include/linux/netdevice.h
index c599e47..9ef07d0 100644
--- a/include/linux/netdevice.h
+++ b/include/linux/netdevice.h
@@ -60,6 +60,9 @@
 #define SET_ETHTOOL_OPS(netdev,ops) \
 	( (netdev)->ethtool_ops = (ops) )
 
+extern void netdev_set_default_ethtool_ops(struct net_device *dev,
+					   const struct ethtool_ops *ops);
+
 /* hardware address assignment types */
 #define NET_ADDR_PERM		0	/* address is permanent (default) */
 #define NET_ADDR_RANDOM		1	/* address is generated randomly */
diff --git a/arch/arm/mach-imx/iram.h b/include/linux/platform_data/imx-iram.h
similarity index 100%
rename from arch/arm/mach-imx/iram.h
rename to include/linux/platform_data/imx-iram.h
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 1693775..89573a3 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -45,7 +45,6 @@
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
 extern void ptrace_disable(struct task_struct *);
-extern int ptrace_check_attach(struct task_struct *task, bool ignore_state);
 extern int ptrace_request(struct task_struct *child, long request,
 			  unsigned long addr, unsigned long data);
 extern void ptrace_notify(int exit_code);
diff --git a/include/linux/rbtree_augmented.h b/include/linux/rbtree_augmented.h
index 2ac60c9..fea49b5 100644
--- a/include/linux/rbtree_augmented.h
+++ b/include/linux/rbtree_augmented.h
@@ -123,9 +123,9 @@
 extern void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
 	void (*augment_rotate)(struct rb_node *old, struct rb_node *new));
 
-static __always_inline void
-rb_erase_augmented(struct rb_node *node, struct rb_root *root,
-		   const struct rb_augment_callbacks *augment)
+static __always_inline struct rb_node *
+__rb_erase_augmented(struct rb_node *node, struct rb_root *root,
+		     const struct rb_augment_callbacks *augment)
 {
 	struct rb_node *child = node->rb_right, *tmp = node->rb_left;
 	struct rb_node *parent, *rebalance;
@@ -217,6 +217,14 @@
 	}
 
 	augment->propagate(tmp, NULL);
+	return rebalance;
+}
+
+static __always_inline void
+rb_erase_augmented(struct rb_node *node, struct rb_root *root,
+		   const struct rb_augment_callbacks *augment)
+{
+	struct rb_node *rebalance = __rb_erase_augmented(node, root, augment);
 	if (rebalance)
 		__rb_erase_color(rebalance, root, augment->rotate);
 }
diff --git a/include/linux/rwsem.h b/include/linux/rwsem.h
index 54bd7cd..8da67d6 100644
--- a/include/linux/rwsem.h
+++ b/include/linux/rwsem.h
@@ -125,8 +125,17 @@
  */
 extern void down_read_nested(struct rw_semaphore *sem, int subclass);
 extern void down_write_nested(struct rw_semaphore *sem, int subclass);
+extern void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest_lock);
+
+# define down_write_nest_lock(sem, nest_lock)			\
+do {								\
+	typecheck(struct lockdep_map *, &(nest_lock)->dep_map);	\
+	_down_write_nest_lock(sem, &(nest_lock)->dep_map);	\
+} while (0);
+
 #else
 # define down_read_nested(sem, subclass)		down_read(sem)
+# define down_write_nest_lock(sem, nest_lock)	down_write(sem)
 # define down_write_nested(sem, subclass)	down_write(sem)
 #endif
 
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 206bb08..d2112477 100644
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -1810,6 +1810,7 @@
 #define PF_MEMALLOC	0x00000800	/* Allocating memory */
 #define PF_NPROC_EXCEEDED 0x00001000	/* set_user noticed that RLIMIT_NPROC was exceeded */
 #define PF_USED_MATH	0x00002000	/* if unset the fpu must be initialized before use */
+#define PF_USED_ASYNC	0x00004000	/* used async_schedule*(), used by module init */
 #define PF_NOFREEZE	0x00008000	/* this thread should not be frozen */
 #define PF_FROZEN	0x00010000	/* frozen for system suspend */
 #define PF_FSTRANS	0x00020000	/* inside a filesystem transaction */
@@ -2713,7 +2714,16 @@
 extern void recalc_sigpending_and_wake(struct task_struct *t);
 extern void recalc_sigpending(void);
 
-extern void signal_wake_up(struct task_struct *t, int resume_stopped);
+extern void signal_wake_up_state(struct task_struct *t, unsigned int state);
+
+static inline void signal_wake_up(struct task_struct *t, bool resume)
+{
+	signal_wake_up_state(t, resume ? TASK_WAKEKILL : 0);
+}
+static inline void ptrace_signal_wake_up(struct task_struct *t, bool resume)
+{
+	signal_wake_up_state(t, resume ? __TASK_TRACED : 0);
+}
 
 /*
  * Wrappers for p->thread_info->cpu access. No-op on UP.
diff --git a/include/linux/security.h b/include/linux/security.h
index 0f6afc6..eee7478 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -989,17 +989,29 @@
  *	tells the LSM to decrement the number of secmark labeling rules loaded
  * @req_classify_flow:
  *	Sets the flow's sid to the openreq sid.
+ * @tun_dev_alloc_security:
+ *	This hook allows a module to allocate a security structure for a TUN
+ *	device.
+ *	@security pointer to a security structure pointer.
+ *	Returns a zero on success, negative values on failure.
+ * @tun_dev_free_security:
+ *	This hook allows a module to free the security structure for a TUN
+ *	device.
+ *	@security pointer to the TUN device's security structure
  * @tun_dev_create:
  *	Check permissions prior to creating a new TUN device.
- * @tun_dev_post_create:
- *	This hook allows a module to update or allocate a per-socket security
- *	structure.
- *	@sk contains the newly created sock structure.
+ * @tun_dev_attach_queue:
+ *	Check permissions prior to attaching to a TUN device queue.
+ *	@security pointer to the TUN device's security structure.
  * @tun_dev_attach:
- *	Check permissions prior to attaching to a persistent TUN device.  This
- *	hook can also be used by the module to update any security state
+ *	This hook can be used by the module to update any security state
  *	associated with the TUN device's sock structure.
  *	@sk contains the existing sock structure.
+ *	@security pointer to the TUN device's security structure.
+ * @tun_dev_open:
+ *	This hook can be used by the module to update any security state
+ *	associated with the TUN device's security structure.
+ *	@security pointer to the TUN devices's security structure.
  *
  * Security hooks for XFRM operations.
  *
@@ -1620,9 +1632,12 @@
 	void (*secmark_refcount_inc) (void);
 	void (*secmark_refcount_dec) (void);
 	void (*req_classify_flow) (const struct request_sock *req, struct flowi *fl);
-	int (*tun_dev_create)(void);
-	void (*tun_dev_post_create)(struct sock *sk);
-	int (*tun_dev_attach)(struct sock *sk);
+	int (*tun_dev_alloc_security) (void **security);
+	void (*tun_dev_free_security) (void *security);
+	int (*tun_dev_create) (void);
+	int (*tun_dev_attach_queue) (void *security);
+	int (*tun_dev_attach) (struct sock *sk, void *security);
+	int (*tun_dev_open) (void *security);
 #endif	/* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
@@ -2566,9 +2581,12 @@
 int security_secmark_relabel_packet(u32 secid);
 void security_secmark_refcount_inc(void);
 void security_secmark_refcount_dec(void);
+int security_tun_dev_alloc_security(void **security);
+void security_tun_dev_free_security(void *security);
 int security_tun_dev_create(void);
-void security_tun_dev_post_create(struct sock *sk);
-int security_tun_dev_attach(struct sock *sk);
+int security_tun_dev_attach_queue(void *security);
+int security_tun_dev_attach(struct sock *sk, void *security);
+int security_tun_dev_open(void *security);
 
 #else	/* CONFIG_SECURITY_NETWORK */
 static inline int security_unix_stream_connect(struct sock *sock,
@@ -2733,16 +2751,31 @@
 {
 }
 
+static inline int security_tun_dev_alloc_security(void **security)
+{
+	return 0;
+}
+
+static inline void security_tun_dev_free_security(void *security)
+{
+}
+
 static inline int security_tun_dev_create(void)
 {
 	return 0;
 }
 
-static inline void security_tun_dev_post_create(struct sock *sk)
+static inline int security_tun_dev_attach_queue(void *security)
 {
+	return 0;
 }
 
-static inline int security_tun_dev_attach(struct sock *sk)
+static inline int security_tun_dev_attach(struct sock *sk, void *security)
+{
+	return 0;
+}
+
+static inline int security_tun_dev_open(void *security)
 {
 	return 0;
 }
diff --git a/include/linux/sunxi_timer.h b/include/linux/sunxi_timer.h
index b9165bb..1808178 100644
--- a/include/linux/sunxi_timer.h
+++ b/include/linux/sunxi_timer.h
@@ -19,6 +19,6 @@
 
 #include <asm/mach/time.h>
 
-extern struct sys_timer sunxi_timer;
+void sunxi_timer_init(void);
 
 #endif
diff --git a/include/linux/tegra-soc.h b/include/linux/tegra-soc.h
new file mode 100644
index 0000000..95f611d
--- /dev/null
+++ b/include/linux/tegra-soc.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __LINUX_TEGRA_SOC_H_
+#define __LINUX_TEGRA_SOC_H_
+
+u32 tegra_read_chipid(void);
+
+#endif /* __LINUX_TEGRA_SOC_H_ */
diff --git a/include/linux/time.h b/include/linux/time.h
index 4d358e9..05e32a7 100644
--- a/include/linux/time.h
+++ b/include/linux/time.h
@@ -142,9 +142,7 @@
  * finer then tick granular time.
  */
 #ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
-extern u32 arch_gettimeoffset(void);
-#else
-static inline u32 arch_gettimeoffset(void) { return 0; }
+extern u32 (*arch_gettimeoffset)(void);
 #endif
 
 extern void do_gettimeofday(struct timeval *tv);
diff --git a/include/linux/usb/tegra_usb_phy.h b/include/linux/usb/tegra_usb_phy.h
index 176b1ca..9ebebe9 100644
--- a/include/linux/usb/tegra_usb_phy.h
+++ b/include/linux/usb/tegra_usb_phy.h
@@ -59,22 +59,24 @@
 	struct usb_phy *ulpi;
 	struct usb_phy u_phy;
 	struct device *dev;
+	bool is_legacy_phy;
+	bool is_ulpi_phy;
 };
 
 struct tegra_usb_phy *tegra_usb_phy_open(struct device *dev, int instance,
 	void __iomem *regs, void *config, enum tegra_usb_phy_mode phy_mode);
 
-void tegra_usb_phy_clk_disable(struct tegra_usb_phy *phy);
+void tegra_usb_phy_preresume(struct usb_phy *phy);
 
-void tegra_usb_phy_clk_enable(struct tegra_usb_phy *phy);
+void tegra_usb_phy_postresume(struct usb_phy *phy);
 
-void tegra_usb_phy_preresume(struct tegra_usb_phy *phy);
-
-void tegra_usb_phy_postresume(struct tegra_usb_phy *phy);
-
-void tegra_ehci_phy_restore_start(struct tegra_usb_phy *phy,
+void tegra_ehci_phy_restore_start(struct usb_phy *phy,
 				 enum tegra_usb_phy_port_speed port_speed);
 
-void tegra_ehci_phy_restore_end(struct tegra_usb_phy *phy);
+void tegra_ehci_phy_restore_end(struct usb_phy *phy);
+
+void tegra_ehci_set_pts(struct usb_phy *x, u8 pts_val);
+
+void tegra_ehci_set_phcd(struct usb_phy *x, bool enable);
 
 #endif /* __TEGRA_USB_PHY_H */
diff --git a/include/linux/usb/usbnet.h b/include/linux/usb/usbnet.h
index bd45eb7..5de7a22 100644
--- a/include/linux/usb/usbnet.h
+++ b/include/linux/usb/usbnet.h
@@ -100,6 +100,7 @@
 #define FLAG_LINK_INTR	0x0800		/* updates link (carrier) status */
 
 #define FLAG_POINTTOPOINT 0x1000	/* possibly use "usb%d" names */
+#define FLAG_NOARP	0x2000		/* device can't do ARP */
 
 /*
  * Indicates to usbnet, that USB driver accumulates multiple IP packets.
diff --git a/include/linux/vt8500_timer.h b/include/linux/vt8500_timer.h
new file mode 100644
index 0000000..33b0ee8
--- /dev/null
+++ b/include/linux/vt8500_timer.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright 2012 Tony Prisk <linux@prisktech.co.nz>
+ *
+ * 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.
+ */
+
+#ifndef __VT8500_TIMER_H
+#define __VT8500_TIMER_H
+
+#include <asm/mach/time.h>
+
+void vt8500_timer_init(void);
+
+#endif
diff --git a/include/net/ip.h b/include/net/ip.h
index 0707fb9..a68f838 100644
--- a/include/net/ip.h
+++ b/include/net/ip.h
@@ -143,6 +143,8 @@
 extern int		ip4_datagram_connect(struct sock *sk, 
 					     struct sockaddr *uaddr, int addr_len);
 
+extern void ip4_datagram_release_cb(struct sock *sk);
+
 struct ip_reply_arg {
 	struct kvec iov[1];   
 	int	    flags;
diff --git a/include/net/netfilter/nf_conntrack_core.h b/include/net/netfilter/nf_conntrack_core.h
index d8f5b9f..e98aeb3 100644
--- a/include/net/netfilter/nf_conntrack_core.h
+++ b/include/net/netfilter/nf_conntrack_core.h
@@ -31,6 +31,8 @@
 extern int nf_conntrack_proto_init(struct net *net);
 extern void nf_conntrack_proto_fini(struct net *net);
 
+extern void nf_conntrack_cleanup_end(void);
+
 extern bool
 nf_ct_get_tuple(const struct sk_buff *skb,
 		unsigned int nhoff,
diff --git a/include/sound/cs4271.h b/include/sound/cs4271.h
index 6d9e15e..dd8c48d 100644
--- a/include/sound/cs4271.h
+++ b/include/sound/cs4271.h
@@ -19,7 +19,7 @@
 
 struct cs4271_platform_data {
 	int gpio_nreset;	/* GPIO driving Reset pin, if any */
-	int amutec_eq_bmutec:1;	/* flag to enable AMUTEC=BMUTEC */
+	bool amutec_eq_bmutec;	/* flag to enable AMUTEC=BMUTEC */
 };
 
 #endif /* __CS4271_H */
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 769e27c..bc56738 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -58,8 +58,9 @@
 	.info = snd_soc_info_volsw_range, .get = snd_soc_get_volsw_range, \
 	.put = snd_soc_put_volsw_range, \
 	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = xreg, .shift = xshift, .min = xmin,\
-		 .max = xmax, .platform_max = xmax, .invert = xinvert} }
+		{.reg = xreg, .rreg = xreg, .shift = xshift, \
+		 .rshift = xshift,  .min = xmin, .max = xmax, \
+		 .platform_max = xmax, .invert = xinvert} }
 #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \
 	.access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\
@@ -88,8 +89,9 @@
 	.info = snd_soc_info_volsw_range, \
 	.get = snd_soc_get_volsw_range, .put = snd_soc_put_volsw_range, \
 	.private_value = (unsigned long)&(struct soc_mixer_control) \
-		{.reg = xreg, .shift = xshift, .min = xmin,\
-		 .max = xmax, .platform_max = xmax, .invert = xinvert} }
+		{.reg = xreg, .rreg = xreg, .shift = xshift, \
+		 .rshift = xshift, .min = xmin, .max = xmax, \
+		 .platform_max = xmax, .invert = xinvert} }
 #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \
 {	.iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\
 	.info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \
diff --git a/include/target/target_core_base.h b/include/target/target_core_base.h
index 7cae236..663e34a 100644
--- a/include/target/target_core_base.h
+++ b/include/target/target_core_base.h
@@ -174,6 +174,7 @@
 
 enum tcm_sense_reason_table {
 #define R(x)	(__force sense_reason_t )(x)
+	TCM_NO_SENSE				= R(0x00),
 	TCM_NON_EXISTENT_LUN			= R(0x01),
 	TCM_UNSUPPORTED_SCSI_OPCODE		= R(0x02),
 	TCM_INCORRECT_AMOUNT_OF_DATA		= R(0x03),
diff --git a/include/uapi/linux/audit.h b/include/uapi/linux/audit.h
index 76352ac..9f096f1 100644
--- a/include/uapi/linux/audit.h
+++ b/include/uapi/linux/audit.h
@@ -26,7 +26,6 @@
 
 #include <linux/types.h>
 #include <linux/elf-em.h>
-#include <linux/ptrace.h>
 
 /* The netlink messages for the audit system is divided into blocks:
  * 1000 - 1099 are for commanding the audit system
@@ -106,6 +105,7 @@
 #define AUDIT_MMAP		1323	/* Record showing descriptor and flags in mmap */
 #define AUDIT_NETFILTER_PKT	1324	/* Packets traversing netfilter chains */
 #define AUDIT_NETFILTER_CFG	1325	/* Netfilter chain modifications */
+#define AUDIT_SECCOMP		1326	/* Secure Computing event */
 
 #define AUDIT_AVC		1400	/* SE Linux avc denial or grant */
 #define AUDIT_SELINUX_ERR	1401	/* Internal SE Linux Errors */
diff --git a/include/uapi/linux/serial_core.h b/include/uapi/linux/serial_core.h
index 78f99d9..2c6c85f 100644
--- a/include/uapi/linux/serial_core.h
+++ b/include/uapi/linux/serial_core.h
@@ -50,7 +50,8 @@
 #define PORT_LPC3220	22	/* NXP LPC32xx SoC "Standard" UART */
 #define PORT_8250_CIR	23	/* CIR infrared port, has its own driver */
 #define PORT_XR17V35X	24	/* Exar XR17V35x UARTs */
-#define PORT_MAX_8250	24	/* max port ID */
+#define PORT_BRCM_TRUMANAGE	24
+#define PORT_MAX_8250	25	/* max port ID */
 
 /*
  * ARM specific type numbers.  These are not currently guaranteed
diff --git a/init/Kconfig b/init/Kconfig
index 7d30240..be8b7f5 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -1182,7 +1182,7 @@
 	  Enabling this option will pass "-Os" instead of "-O2" to gcc
 	  resulting in a smaller kernel.
 
-	  If unsure, say Y.
+	  If unsure, say N.
 
 config SYSCTL
 	bool
diff --git a/init/do_mounts_initrd.c b/init/do_mounts_initrd.c
index 5e4ded5..f9acf71 100644
--- a/init/do_mounts_initrd.c
+++ b/init/do_mounts_initrd.c
@@ -36,6 +36,10 @@
 static int init_linuxrc(struct subprocess_info *info, struct cred *new)
 {
 	sys_unshare(CLONE_FS | CLONE_FILES);
+	/* stdin/stdout/stderr for /linuxrc */
+	sys_open("/dev/console", O_RDWR, 0);
+	sys_dup(0);
+	sys_dup(0);
 	/* move initrd over / and chdir/chroot in initrd root */
 	sys_chdir("/root");
 	sys_mount(".", "/", NULL, MS_MOVE, NULL);
diff --git a/init/main.c b/init/main.c
index 85d69df..cee4b5c 100644
--- a/init/main.c
+++ b/init/main.c
@@ -604,7 +604,7 @@
 	pidmap_init();
 	anon_vma_init();
 #ifdef CONFIG_X86
-	if (efi_enabled)
+	if (efi_enabled(EFI_RUNTIME_SERVICES))
 		efi_enter_virtual_mode();
 #endif
 	thread_info_cache_init();
@@ -632,7 +632,7 @@
 	acpi_early_init(); /* before LAPIC and SMP init */
 	sfi_init_late();
 
-	if (efi_enabled) {
+	if (efi_enabled(EFI_RUNTIME_SERVICES)) {
 		efi_late_init();
 		efi_free_boot_services();
 	}
@@ -802,7 +802,7 @@
 		(const char __user *const __user *)envp_init);
 }
 
-static void __init kernel_init_freeable(void);
+static noinline void __init kernel_init_freeable(void);
 
 static int __ref kernel_init(void *unused)
 {
@@ -845,7 +845,7 @@
 	      "See Linux Documentation/init.txt for guidance.");
 }
 
-static void __init kernel_init_freeable(void)
+static noinline void __init kernel_init_freeable(void)
 {
 	/*
 	 * Wait until kthreadd is all set-up.
diff --git a/kernel/async.c b/kernel/async.c
index 9d31183..6f34904 100644
--- a/kernel/async.c
+++ b/kernel/async.c
@@ -86,18 +86,27 @@
  */
 static async_cookie_t  __lowest_in_progress(struct async_domain *running)
 {
+	async_cookie_t first_running = next_cookie;	/* infinity value */
+	async_cookie_t first_pending = next_cookie;	/* ditto */
 	struct async_entry *entry;
 
+	/*
+	 * Both running and pending lists are sorted but not disjoint.
+	 * Take the first cookies from both and return the min.
+	 */
 	if (!list_empty(&running->domain)) {
 		entry = list_first_entry(&running->domain, typeof(*entry), list);
-		return entry->cookie;
+		first_running = entry->cookie;
 	}
 
-	list_for_each_entry(entry, &async_pending, list)
-		if (entry->running == running)
-			return entry->cookie;
+	list_for_each_entry(entry, &async_pending, list) {
+		if (entry->running == running) {
+			first_pending = entry->cookie;
+			break;
+		}
+	}
 
-	return next_cookie;	/* "infinity" value */
+	return min(first_running, first_pending);
 }
 
 static async_cookie_t  lowest_in_progress(struct async_domain *running)
@@ -118,13 +127,17 @@
 {
 	struct async_entry *entry =
 		container_of(work, struct async_entry, work);
+	struct async_entry *pos;
 	unsigned long flags;
 	ktime_t uninitialized_var(calltime), delta, rettime;
 	struct async_domain *running = entry->running;
 
-	/* 1) move self to the running queue */
+	/* 1) move self to the running queue, make sure it stays sorted */
 	spin_lock_irqsave(&async_lock, flags);
-	list_move_tail(&entry->list, &running->domain);
+	list_for_each_entry_reverse(pos, &running->domain, list)
+		if (entry->cookie < pos->cookie)
+			break;
+	list_move_tail(&entry->list, &pos->list);
 	spin_unlock_irqrestore(&async_lock, flags);
 
 	/* 2) run (and print duration) */
@@ -196,6 +209,9 @@
 	atomic_inc(&entry_count);
 	spin_unlock_irqrestore(&async_lock, flags);
 
+	/* mark that this task has queued an async job, used by module init */
+	current->flags |= PF_USED_ASYNC;
+
 	/* schedule for execution */
 	queue_work(system_unbound_wq, &entry->work);
 
diff --git a/kernel/audit.c b/kernel/audit.c
index 40414e9..d596e53 100644
--- a/kernel/audit.c
+++ b/kernel/audit.c
@@ -272,6 +272,8 @@
 	int rc = 0;
 
 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+	if (unlikely(!ab))
+		return rc;
 	audit_log_format(ab, "%s=%d old=%d auid=%u ses=%u", function_name, new,
 			 old, from_kuid(&init_user_ns, loginuid), sessionid);
 	if (sid) {
@@ -619,6 +621,8 @@
 	}
 
 	*ab = audit_log_start(NULL, GFP_KERNEL, msg_type);
+	if (unlikely(!*ab))
+		return rc;
 	audit_log_format(*ab, "pid=%d uid=%u auid=%u ses=%u",
 			 task_tgid_vnr(current),
 			 from_kuid(&init_user_ns, current_uid()),
@@ -1097,6 +1101,23 @@
 	}
 }
 
+/*
+ * Wait for auditd to drain the queue a little
+ */
+static void wait_for_auditd(unsigned long sleep_time)
+{
+	DECLARE_WAITQUEUE(wait, current);
+	set_current_state(TASK_INTERRUPTIBLE);
+	add_wait_queue(&audit_backlog_wait, &wait);
+
+	if (audit_backlog_limit &&
+	    skb_queue_len(&audit_skb_queue) > audit_backlog_limit)
+		schedule_timeout(sleep_time);
+
+	__set_current_state(TASK_RUNNING);
+	remove_wait_queue(&audit_backlog_wait, &wait);
+}
+
 /* Obtain an audit buffer.  This routine does locking to obtain the
  * audit buffer, but then no locking is required for calls to
  * audit_log_*format.  If the tsk is a task that is currently in a
@@ -1142,20 +1163,13 @@
 
 	while (audit_backlog_limit
 	       && skb_queue_len(&audit_skb_queue) > audit_backlog_limit + reserve) {
-		if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time
-		    && time_before(jiffies, timeout_start + audit_backlog_wait_time)) {
+		if (gfp_mask & __GFP_WAIT && audit_backlog_wait_time) {
+			unsigned long sleep_time;
 
-			/* Wait for auditd to drain the queue a little */
-			DECLARE_WAITQUEUE(wait, current);
-			set_current_state(TASK_INTERRUPTIBLE);
-			add_wait_queue(&audit_backlog_wait, &wait);
-
-			if (audit_backlog_limit &&
-			    skb_queue_len(&audit_skb_queue) > audit_backlog_limit)
-				schedule_timeout(timeout_start + audit_backlog_wait_time - jiffies);
-
-			__set_current_state(TASK_RUNNING);
-			remove_wait_queue(&audit_backlog_wait, &wait);
+			sleep_time = timeout_start + audit_backlog_wait_time -
+					jiffies;
+			if ((long)sleep_time > 0)
+				wait_for_auditd(sleep_time);
 			continue;
 		}
 		if (audit_rate_check() && printk_ratelimit())
diff --git a/kernel/audit_tree.c b/kernel/audit_tree.c
index e81175e..642a89c 100644
--- a/kernel/audit_tree.c
+++ b/kernel/audit_tree.c
@@ -449,11 +449,26 @@
 	return 0;
 }
 
+static void audit_log_remove_rule(struct audit_krule *rule)
+{
+	struct audit_buffer *ab;
+
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
+	if (unlikely(!ab))
+		return;
+	audit_log_format(ab, "op=");
+	audit_log_string(ab, "remove rule");
+	audit_log_format(ab, " dir=");
+	audit_log_untrustedstring(ab, rule->tree->pathname);
+	audit_log_key(ab, rule->filterkey);
+	audit_log_format(ab, " list=%d res=1", rule->listnr);
+	audit_log_end(ab);
+}
+
 static void kill_rules(struct audit_tree *tree)
 {
 	struct audit_krule *rule, *next;
 	struct audit_entry *entry;
-	struct audit_buffer *ab;
 
 	list_for_each_entry_safe(rule, next, &tree->rules, rlist) {
 		entry = container_of(rule, struct audit_entry, rule);
@@ -461,14 +476,7 @@
 		list_del_init(&rule->rlist);
 		if (rule->tree) {
 			/* not a half-baked one */
-			ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_CONFIG_CHANGE);
-			audit_log_format(ab, "op=");
-			audit_log_string(ab, "remove rule");
-			audit_log_format(ab, " dir=");
-			audit_log_untrustedstring(ab, rule->tree->pathname);
-			audit_log_key(ab, rule->filterkey);
-			audit_log_format(ab, " list=%d res=1", rule->listnr);
-			audit_log_end(ab);
+			audit_log_remove_rule(rule);
 			rule->tree = NULL;
 			list_del_rcu(&entry->list);
 			list_del(&entry->rule.list);
diff --git a/kernel/audit_watch.c b/kernel/audit_watch.c
index 4a599f6..22831c4 100644
--- a/kernel/audit_watch.c
+++ b/kernel/audit_watch.c
@@ -240,6 +240,8 @@
 	if (audit_enabled) {
 		struct audit_buffer *ab;
 		ab = audit_log_start(NULL, GFP_NOFS, AUDIT_CONFIG_CHANGE);
+		if (unlikely(!ab))
+			return;
 		audit_log_format(ab, "auid=%u ses=%u op=",
 				 from_kuid(&init_user_ns, audit_get_loginuid(current)),
 				 audit_get_sessionid(current));
diff --git a/kernel/auditfilter.c b/kernel/auditfilter.c
index 7f19f23..f9fc54b 100644
--- a/kernel/auditfilter.c
+++ b/kernel/auditfilter.c
@@ -1144,7 +1144,6 @@
  * audit_receive_filter - apply all rules to the specified message type
  * @type: audit message type
  * @pid: target pid for netlink audit messages
- * @uid: target uid for netlink audit messages
  * @seq: netlink audit message sequence (serial) number
  * @data: payload data
  * @datasz: size of payload data
diff --git a/kernel/auditsc.c b/kernel/auditsc.c
index e37e6a1..a371f85 100644
--- a/kernel/auditsc.c
+++ b/kernel/auditsc.c
@@ -1464,14 +1464,14 @@
 			audit_log_end(ab);
 			ab = audit_log_start(context, GFP_KERNEL,
 					     AUDIT_IPC_SET_PERM);
+			if (unlikely(!ab))
+				return;
 			audit_log_format(ab,
 				"qbytes=%lx ouid=%u ogid=%u mode=%#ho",
 				context->ipc.qbytes,
 				context->ipc.perm_uid,
 				context->ipc.perm_gid,
 				context->ipc.perm_mode);
-			if (!ab)
-				return;
 		}
 		break; }
 	case AUDIT_MQ_OPEN: {
@@ -2675,7 +2675,7 @@
 	context->type = AUDIT_MMAP;
 }
 
-static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
+static void audit_log_task(struct audit_buffer *ab)
 {
 	kuid_t auid, uid;
 	kgid_t gid;
@@ -2693,6 +2693,11 @@
 	audit_log_task_context(ab);
 	audit_log_format(ab, " pid=%d comm=", current->pid);
 	audit_log_untrustedstring(ab, current->comm);
+}
+
+static void audit_log_abend(struct audit_buffer *ab, char *reason, long signr)
+{
+	audit_log_task(ab);
 	audit_log_format(ab, " reason=");
 	audit_log_string(ab, reason);
 	audit_log_format(ab, " sig=%ld", signr);
@@ -2715,6 +2720,8 @@
 		return;
 
 	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
+	if (unlikely(!ab))
+		return;
 	audit_log_abend(ab, "memory violation", signr);
 	audit_log_end(ab);
 }
@@ -2723,8 +2730,11 @@
 {
 	struct audit_buffer *ab;
 
-	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_ANOM_ABEND);
-	audit_log_abend(ab, "seccomp", signr);
+	ab = audit_log_start(NULL, GFP_KERNEL, AUDIT_SECCOMP);
+	if (unlikely(!ab))
+		return;
+	audit_log_task(ab);
+	audit_log_format(ab, " sig=%ld", signr);
 	audit_log_format(ab, " syscall=%ld", syscall);
 	audit_log_format(ab, " compat=%d", is_compat_task());
 	audit_log_format(ab, " ip=0x%lx", KSTK_EIP(current));
diff --git a/kernel/compat.c b/kernel/compat.c
index f6150e9..36700e9 100644
--- a/kernel/compat.c
+++ b/kernel/compat.c
@@ -535,9 +535,11 @@
 	return 0;
 }
 
-asmlinkage long
-compat_sys_wait4(compat_pid_t pid, compat_uint_t __user *stat_addr, int options,
-	struct compat_rusage __user *ru)
+COMPAT_SYSCALL_DEFINE4(wait4,
+	compat_pid_t, pid,
+	compat_uint_t __user *, stat_addr,
+	int, options,
+	struct compat_rusage __user *, ru)
 {
 	if (!ru) {
 		return sys_wait4(pid, stat_addr, options, NULL);
@@ -564,9 +566,10 @@
 	}
 }
 
-asmlinkage long compat_sys_waitid(int which, compat_pid_t pid,
-		struct compat_siginfo __user *uinfo, int options,
-		struct compat_rusage __user *uru)
+COMPAT_SYSCALL_DEFINE5(waitid,
+		int, which, compat_pid_t, pid,
+		struct compat_siginfo __user *, uinfo, int, options,
+		struct compat_rusage __user *, uru)
 {
 	siginfo_t info;
 	struct rusage ru;
@@ -584,7 +587,11 @@
 		return ret;
 
 	if (uru) {
-		ret = put_compat_rusage(&ru, uru);
+		/* sys_waitid() overwrites everything in ru */
+		if (COMPAT_USE_64BIT_TIME)
+			ret = copy_to_user(uru, &ru, sizeof(ru));
+		else
+			ret = put_compat_rusage(&ru, uru);
 		if (ret)
 			return ret;
 	}
@@ -994,7 +1001,7 @@
 	sigset_from_compat(&s, &s32);
 
 	if (uts) {
-		if (get_compat_timespec(&t, uts))
+		if (compat_get_timespec(&t, uts))
 			return -EFAULT;
 	}
 
diff --git a/kernel/debug/kdb/kdb_main.c b/kernel/debug/kdb/kdb_main.c
index 4d5f8d5..8875254 100644
--- a/kernel/debug/kdb/kdb_main.c
+++ b/kernel/debug/kdb/kdb_main.c
@@ -1970,6 +1970,8 @@
 
 	kdb_printf("Module                  Size  modstruct     Used by\n");
 	list_for_each_entry(mod, kdb_modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 
 		kdb_printf("%-20s%8u  0x%p ", mod->name,
 			   mod->core_size, (void *)mod);
diff --git a/kernel/fork.c b/kernel/fork.c
index 65ca6d2..c535f33 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -1668,8 +1668,10 @@
 		 int, tls_val)
 #endif
 {
-	return do_fork(clone_flags, newsp, 0,
-		parent_tidptr, child_tidptr);
+	long ret = do_fork(clone_flags, newsp, 0, parent_tidptr, child_tidptr);
+	asmlinkage_protect(5, ret, clone_flags, newsp,
+			parent_tidptr, child_tidptr, tls_val);
+	return ret;
 }
 #endif
 
diff --git a/kernel/module.c b/kernel/module.c
index 250092c..eab0827 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -188,6 +188,7 @@
    ongoing or failed initialization etc. */
 static inline int strong_try_module_get(struct module *mod)
 {
+	BUG_ON(mod && mod->state == MODULE_STATE_UNFORMED);
 	if (mod && mod->state == MODULE_STATE_COMING)
 		return -EBUSY;
 	if (try_module_get(mod))
@@ -343,6 +344,9 @@
 #endif
 		};
 
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
+
 		if (each_symbol_in_section(arr, ARRAY_SIZE(arr), mod, fn, data))
 			return true;
 	}
@@ -450,16 +454,24 @@
 EXPORT_SYMBOL_GPL(find_symbol);
 
 /* Search for module by name: must hold module_mutex. */
-struct module *find_module(const char *name)
+static struct module *find_module_all(const char *name,
+				      bool even_unformed)
 {
 	struct module *mod;
 
 	list_for_each_entry(mod, &modules, list) {
+		if (!even_unformed && mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		if (strcmp(mod->name, name) == 0)
 			return mod;
 	}
 	return NULL;
 }
+
+struct module *find_module(const char *name)
+{
+	return find_module_all(name, false);
+}
 EXPORT_SYMBOL_GPL(find_module);
 
 #ifdef CONFIG_SMP
@@ -525,6 +537,8 @@
 	preempt_disable();
 
 	list_for_each_entry_rcu(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		if (!mod->percpu_size)
 			continue;
 		for_each_possible_cpu(cpu) {
@@ -1048,6 +1062,8 @@
 	case MODULE_STATE_GOING:
 		state = "going";
 		break;
+	default:
+		BUG();
 	}
 	return sprintf(buffer, "%s\n", state);
 }
@@ -1786,6 +1802,8 @@
 
 	mutex_lock(&module_mutex);
 	list_for_each_entry_rcu(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		if ((mod->module_core) && (mod->core_text_size)) {
 			set_page_attributes(mod->module_core,
 						mod->module_core + mod->core_text_size,
@@ -1807,6 +1825,8 @@
 
 	mutex_lock(&module_mutex);
 	list_for_each_entry_rcu(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		if ((mod->module_core) && (mod->core_text_size)) {
 			set_page_attributes(mod->module_core,
 						mod->module_core + mod->core_text_size,
@@ -2527,6 +2547,13 @@
 		err = -EFBIG;
 		goto out;
 	}
+
+	/* Don't hand 0 to vmalloc, it whines. */
+	if (stat.size == 0) {
+		err = -EINVAL;
+		goto out;
+	}
+
 	info->hdr = vmalloc(stat.size);
 	if (!info->hdr) {
 		err = -ENOMEM;
@@ -2990,8 +3017,9 @@
 	bool ret;
 
 	mutex_lock(&module_mutex);
-	mod = find_module(name);
-	ret = !mod || mod->state != MODULE_STATE_COMING;
+	mod = find_module_all(name, true);
+	ret = !mod || mod->state == MODULE_STATE_LIVE
+		|| mod->state == MODULE_STATE_GOING;
 	mutex_unlock(&module_mutex);
 
 	return ret;
@@ -3013,6 +3041,12 @@
 {
 	int ret = 0;
 
+	/*
+	 * We want to find out whether @mod uses async during init.  Clear
+	 * PF_USED_ASYNC.  async_schedule*() will set it.
+	 */
+	current->flags &= ~PF_USED_ASYNC;
+
 	blocking_notifier_call_chain(&module_notify_list,
 			MODULE_STATE_COMING, mod);
 
@@ -3058,8 +3092,25 @@
 	blocking_notifier_call_chain(&module_notify_list,
 				     MODULE_STATE_LIVE, mod);
 
-	/* We need to finish all async code before the module init sequence is done */
-	async_synchronize_full();
+	/*
+	 * We need to finish all async code before the module init sequence
+	 * is done.  This has potential to deadlock.  For example, a newly
+	 * detected block device can trigger request_module() of the
+	 * default iosched from async probing task.  Once userland helper
+	 * reaches here, async_synchronize_full() will wait on the async
+	 * task waiting on request_module() and deadlock.
+	 *
+	 * This deadlock is avoided by perfomring async_synchronize_full()
+	 * iff module init queued any async jobs.  This isn't a full
+	 * solution as it will deadlock the same if module loading from
+	 * async jobs nests more than once; however, due to the various
+	 * constraints, this hack seems to be the best option for now.
+	 * Please refer to the following thread for details.
+	 *
+	 * http://thread.gmane.org/gmane.linux.kernel/1420814
+	 */
+	if (current->flags & PF_USED_ASYNC)
+		async_synchronize_full();
 
 	mutex_lock(&module_mutex);
 	/* Drop initial reference. */
@@ -3113,6 +3164,32 @@
 		goto free_copy;
 	}
 
+	/*
+	 * We try to place it in the list now to make sure it's unique
+	 * before we dedicate too many resources.  In particular,
+	 * temporary percpu memory exhaustion.
+	 */
+	mod->state = MODULE_STATE_UNFORMED;
+again:
+	mutex_lock(&module_mutex);
+	if ((old = find_module_all(mod->name, true)) != NULL) {
+		if (old->state == MODULE_STATE_COMING
+		    || old->state == MODULE_STATE_UNFORMED) {
+			/* Wait in case it fails to load. */
+			mutex_unlock(&module_mutex);
+			err = wait_event_interruptible(module_wq,
+					       finished_loading(mod->name));
+			if (err)
+				goto free_module;
+			goto again;
+		}
+		err = -EEXIST;
+		mutex_unlock(&module_mutex);
+		goto free_module;
+	}
+	list_add_rcu(&mod->list, &modules);
+	mutex_unlock(&module_mutex);
+
 #ifdef CONFIG_MODULE_SIG
 	mod->sig_ok = info->sig_ok;
 	if (!mod->sig_ok)
@@ -3122,7 +3199,7 @@
 	/* Now module is in final location, initialize linked lists, etc. */
 	err = module_unload_init(mod);
 	if (err)
-		goto free_module;
+		goto unlink_mod;
 
 	/* Now we've got everything in the final locations, we can
 	 * find optional sections. */
@@ -3157,54 +3234,33 @@
 		goto free_arch_cleanup;
 	}
 
-	/* Mark state as coming so strong_try_module_get() ignores us. */
-	mod->state = MODULE_STATE_COMING;
-
-	/* Now sew it into the lists so we can get lockdep and oops
-	 * info during argument parsing.  No one should access us, since
-	 * strong_try_module_get() will fail.
-	 * lockdep/oops can run asynchronous, so use the RCU list insertion
-	 * function to insert in a way safe to concurrent readers.
-	 * The mutex protects against concurrent writers.
-	 */
-again:
-	mutex_lock(&module_mutex);
-	if ((old = find_module(mod->name)) != NULL) {
-		if (old->state == MODULE_STATE_COMING) {
-			/* Wait in case it fails to load. */
-			mutex_unlock(&module_mutex);
-			err = wait_event_interruptible(module_wq,
-					       finished_loading(mod->name));
-			if (err)
-				goto free_arch_cleanup;
-			goto again;
-		}
-		err = -EEXIST;
-		goto unlock;
-	}
-
-	/* This has to be done once we're sure module name is unique. */
 	dynamic_debug_setup(info->debug, info->num_debug);
 
-	/* Find duplicate symbols */
+	mutex_lock(&module_mutex);
+	/* Find duplicate symbols (must be called under lock). */
 	err = verify_export_symbols(mod);
 	if (err < 0)
-		goto ddebug;
+		goto ddebug_cleanup;
 
+	/* This relies on module_mutex for list integrity. */
 	module_bug_finalize(info->hdr, info->sechdrs, mod);
-	list_add_rcu(&mod->list, &modules);
+
+	/* Mark state as coming so strong_try_module_get() ignores us,
+	 * but kallsyms etc. can see us. */
+	mod->state = MODULE_STATE_COMING;
+
 	mutex_unlock(&module_mutex);
 
 	/* Module is ready to execute: parsing args may do that. */
 	err = parse_args(mod->name, mod->args, mod->kp, mod->num_kp,
 			 -32768, 32767, &ddebug_dyndbg_module_param_cb);
 	if (err < 0)
-		goto unlink;
+		goto bug_cleanup;
 
 	/* Link in to syfs. */
 	err = mod_sysfs_setup(mod, info, mod->kp, mod->num_kp);
 	if (err < 0)
-		goto unlink;
+		goto bug_cleanup;
 
 	/* Get rid of temporary copy. */
 	free_copy(info);
@@ -3214,16 +3270,13 @@
 
 	return do_init_module(mod);
 
- unlink:
+ bug_cleanup:
+	/* module_bug_cleanup needs module_mutex protection */
 	mutex_lock(&module_mutex);
-	/* Unlink carefully: kallsyms could be walking list. */
-	list_del_rcu(&mod->list);
 	module_bug_cleanup(mod);
-	wake_up_all(&module_wq);
- ddebug:
-	dynamic_debug_remove(info->debug);
- unlock:
+ ddebug_cleanup:
 	mutex_unlock(&module_mutex);
+	dynamic_debug_remove(info->debug);
 	synchronize_sched();
 	kfree(mod->args);
  free_arch_cleanup:
@@ -3232,6 +3285,12 @@
 	free_modinfo(mod);
  free_unload:
 	module_unload_free(mod);
+ unlink_mod:
+	mutex_lock(&module_mutex);
+	/* Unlink carefully: kallsyms could be walking list. */
+	list_del_rcu(&mod->list);
+	wake_up_all(&module_wq);
+	mutex_unlock(&module_mutex);
  free_module:
 	module_deallocate(mod, info);
  free_copy:
@@ -3354,6 +3413,8 @@
 
 	preempt_disable();
 	list_for_each_entry_rcu(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		if (within_module_init(addr, mod) ||
 		    within_module_core(addr, mod)) {
 			if (modname)
@@ -3377,6 +3438,8 @@
 
 	preempt_disable();
 	list_for_each_entry_rcu(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		if (within_module_init(addr, mod) ||
 		    within_module_core(addr, mod)) {
 			const char *sym;
@@ -3401,6 +3464,8 @@
 
 	preempt_disable();
 	list_for_each_entry_rcu(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		if (within_module_init(addr, mod) ||
 		    within_module_core(addr, mod)) {
 			const char *sym;
@@ -3428,6 +3493,8 @@
 
 	preempt_disable();
 	list_for_each_entry_rcu(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		if (symnum < mod->num_symtab) {
 			*value = mod->symtab[symnum].st_value;
 			*type = mod->symtab[symnum].st_info;
@@ -3470,9 +3537,12 @@
 			ret = mod_find_symname(mod, colon+1);
 		*colon = ':';
 	} else {
-		list_for_each_entry_rcu(mod, &modules, list)
+		list_for_each_entry_rcu(mod, &modules, list) {
+			if (mod->state == MODULE_STATE_UNFORMED)
+				continue;
 			if ((ret = mod_find_symname(mod, name)) != 0)
 				break;
+		}
 	}
 	preempt_enable();
 	return ret;
@@ -3487,6 +3557,8 @@
 	int ret;
 
 	list_for_each_entry(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		for (i = 0; i < mod->num_symtab; i++) {
 			ret = fn(data, mod->strtab + mod->symtab[i].st_name,
 				 mod, mod->symtab[i].st_value);
@@ -3502,6 +3574,7 @@
 {
 	int bx = 0;
 
+	BUG_ON(mod->state == MODULE_STATE_UNFORMED);
 	if (mod->taints ||
 	    mod->state == MODULE_STATE_GOING ||
 	    mod->state == MODULE_STATE_COMING) {
@@ -3543,6 +3616,10 @@
 	struct module *mod = list_entry(p, struct module, list);
 	char buf[8];
 
+	/* We always ignore unformed modules. */
+	if (mod->state == MODULE_STATE_UNFORMED)
+		return 0;
+
 	seq_printf(m, "%s %u",
 		   mod->name, mod->init_size + mod->core_size);
 	print_unload_info(m, mod);
@@ -3603,6 +3680,8 @@
 
 	preempt_disable();
 	list_for_each_entry_rcu(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		if (mod->num_exentries == 0)
 			continue;
 
@@ -3651,10 +3730,13 @@
 	if (addr < module_addr_min || addr > module_addr_max)
 		return NULL;
 
-	list_for_each_entry_rcu(mod, &modules, list)
+	list_for_each_entry_rcu(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		if (within_module_core(addr, mod)
 		    || within_module_init(addr, mod))
 			return mod;
+	}
 	return NULL;
 }
 EXPORT_SYMBOL_GPL(__module_address);
@@ -3707,8 +3789,11 @@
 	printk(KERN_DEFAULT "Modules linked in:");
 	/* Most callers should already have preempt disabled, but make sure */
 	preempt_disable();
-	list_for_each_entry_rcu(mod, &modules, list)
+	list_for_each_entry_rcu(mod, &modules, list) {
+		if (mod->state == MODULE_STATE_UNFORMED)
+			continue;
 		printk(" %s%s", mod->name, module_flags(mod, buf));
+	}
 	preempt_enable();
 	if (last_unloaded_module[0])
 		printk(" [last unloaded: %s]", last_unloaded_module);
diff --git a/kernel/printk.c b/kernel/printk.c
index 357f714..267ce78 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -87,12 +87,6 @@
 struct console *console_drivers;
 EXPORT_SYMBOL_GPL(console_drivers);
 
-#ifdef CONFIG_LOCKDEP
-static struct lockdep_map console_lock_dep_map = {
-	.name = "console_lock"
-};
-#endif
-
 /*
  * This is used for debugging the mess that is the VT code by
  * keeping track if we have the console semaphore held. It's
@@ -1924,7 +1918,6 @@
 		return;
 	console_locked = 1;
 	console_may_schedule = 1;
-	mutex_acquire(&console_lock_dep_map, 0, 0, _RET_IP_);
 }
 EXPORT_SYMBOL(console_lock);
 
@@ -1946,7 +1939,6 @@
 	}
 	console_locked = 1;
 	console_may_schedule = 0;
-	mutex_acquire(&console_lock_dep_map, 0, 1, _RET_IP_);
 	return 1;
 }
 EXPORT_SYMBOL(console_trylock);
@@ -2107,7 +2099,6 @@
 		local_irq_restore(flags);
 	}
 	console_locked = 0;
-	mutex_release(&console_lock_dep_map, 1, _RET_IP_);
 
 	/* Release the exclusive_console once it is used */
 	if (unlikely(exclusive_console))
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 1599157..6cbeaae 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -117,11 +117,45 @@
 	 * TASK_KILLABLE sleeps.
 	 */
 	if (child->jobctl & JOBCTL_STOP_PENDING || task_is_traced(child))
-		signal_wake_up(child, task_is_traced(child));
+		ptrace_signal_wake_up(child, true);
 
 	spin_unlock(&child->sighand->siglock);
 }
 
+/* Ensure that nothing can wake it up, even SIGKILL */
+static bool ptrace_freeze_traced(struct task_struct *task)
+{
+	bool ret = false;
+
+	/* Lockless, nobody but us can set this flag */
+	if (task->jobctl & JOBCTL_LISTENING)
+		return ret;
+
+	spin_lock_irq(&task->sighand->siglock);
+	if (task_is_traced(task) && !__fatal_signal_pending(task)) {
+		task->state = __TASK_TRACED;
+		ret = true;
+	}
+	spin_unlock_irq(&task->sighand->siglock);
+
+	return ret;
+}
+
+static void ptrace_unfreeze_traced(struct task_struct *task)
+{
+	if (task->state != __TASK_TRACED)
+		return;
+
+	WARN_ON(!task->ptrace || task->parent != current);
+
+	spin_lock_irq(&task->sighand->siglock);
+	if (__fatal_signal_pending(task))
+		wake_up_state(task, __TASK_TRACED);
+	else
+		task->state = TASK_TRACED;
+	spin_unlock_irq(&task->sighand->siglock);
+}
+
 /**
  * ptrace_check_attach - check whether ptracee is ready for ptrace operation
  * @child: ptracee to check for
@@ -139,7 +173,7 @@
  * RETURNS:
  * 0 on success, -ESRCH if %child is not ready.
  */
-int ptrace_check_attach(struct task_struct *child, bool ignore_state)
+static int ptrace_check_attach(struct task_struct *child, bool ignore_state)
 {
 	int ret = -ESRCH;
 
@@ -151,24 +185,29 @@
 	 * be changed by us so it's not changing right after this.
 	 */
 	read_lock(&tasklist_lock);
-	if ((child->ptrace & PT_PTRACED) && child->parent == current) {
+	if (child->ptrace && child->parent == current) {
+		WARN_ON(child->state == __TASK_TRACED);
 		/*
 		 * child->sighand can't be NULL, release_task()
 		 * does ptrace_unlink() before __exit_signal().
 		 */
-		spin_lock_irq(&child->sighand->siglock);
-		WARN_ON_ONCE(task_is_stopped(child));
-		if (ignore_state || (task_is_traced(child) &&
-				     !(child->jobctl & JOBCTL_LISTENING)))
+		if (ignore_state || ptrace_freeze_traced(child))
 			ret = 0;
-		spin_unlock_irq(&child->sighand->siglock);
 	}
 	read_unlock(&tasklist_lock);
 
-	if (!ret && !ignore_state)
-		ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH;
+	if (!ret && !ignore_state) {
+		if (!wait_task_inactive(child, __TASK_TRACED)) {
+			/*
+			 * This can only happen if may_ptrace_stop() fails and
+			 * ptrace_stop() changes ->state back to TASK_RUNNING,
+			 * so we should not worry about leaking __TASK_TRACED.
+			 */
+			WARN_ON(child->state == __TASK_TRACED);
+			ret = -ESRCH;
+		}
+	}
 
-	/* All systems go.. */
 	return ret;
 }
 
@@ -317,7 +356,7 @@
 	 */
 	if (task_is_stopped(task) &&
 	    task_set_jobctl_pending(task, JOBCTL_TRAP_STOP | JOBCTL_TRAPPING))
-		signal_wake_up(task, 1);
+		signal_wake_up_state(task, __TASK_STOPPED);
 
 	spin_unlock(&task->sighand->siglock);
 
@@ -737,7 +776,7 @@
 		 * tracee into STOP.
 		 */
 		if (likely(task_set_jobctl_pending(child, JOBCTL_TRAP_STOP)))
-			signal_wake_up(child, child->jobctl & JOBCTL_LISTENING);
+			ptrace_signal_wake_up(child, child->jobctl & JOBCTL_LISTENING);
 
 		unlock_task_sighand(child, &flags);
 		ret = 0;
@@ -763,7 +802,7 @@
 			 * start of this trap and now.  Trigger re-trap.
 			 */
 			if (child->jobctl & JOBCTL_TRAP_NOTIFY)
-				signal_wake_up(child, true);
+				ptrace_signal_wake_up(child, true);
 			ret = 0;
 		}
 		unlock_task_sighand(child, &flags);
@@ -900,6 +939,8 @@
 		goto out_put_task_struct;
 
 	ret = arch_ptrace(child, request, addr, data);
+	if (ret || request != PTRACE_DETACH)
+		ptrace_unfreeze_traced(child);
 
  out_put_task_struct:
 	put_task_struct(child);
@@ -1039,8 +1080,11 @@
 
 	ret = ptrace_check_attach(child, request == PTRACE_KILL ||
 				  request == PTRACE_INTERRUPT);
-	if (!ret)
+	if (!ret) {
 		ret = compat_arch_ptrace(child, request, addr, data);
+		if (ret || request != PTRACE_DETACH)
+			ptrace_unfreeze_traced(child);
+	}
 
  out_put_task_struct:
 	put_task_struct(child);
diff --git a/kernel/rwsem.c b/kernel/rwsem.c
index 6850f53..b3c6c3f 100644
--- a/kernel/rwsem.c
+++ b/kernel/rwsem.c
@@ -116,6 +116,16 @@
 
 EXPORT_SYMBOL(down_read_nested);
 
+void _down_write_nest_lock(struct rw_semaphore *sem, struct lockdep_map *nest)
+{
+	might_sleep();
+	rwsem_acquire_nest(&sem->dep_map, 0, 0, nest, _RET_IP_);
+
+	LOCK_CONTENDED(sem, __down_write_trylock, __down_write);
+}
+
+EXPORT_SYMBOL(_down_write_nest_lock);
+
 void down_write_nested(struct rw_semaphore *sem, int subclass)
 {
 	might_sleep();
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 257002c..26058d0 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -1523,7 +1523,8 @@
  */
 int wake_up_process(struct task_struct *p)
 {
-	return try_to_wake_up(p, TASK_ALL, 0);
+	WARN_ON(task_is_stopped_or_traced(p));
+	return try_to_wake_up(p, TASK_NORMAL, 0);
 }
 EXPORT_SYMBOL(wake_up_process);
 
diff --git a/kernel/signal.c b/kernel/signal.c
index 372771e..3d09cf6 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -680,23 +680,17 @@
  * No need to set need_resched since signal event passing
  * goes through ->blocked
  */
-void signal_wake_up(struct task_struct *t, int resume)
+void signal_wake_up_state(struct task_struct *t, unsigned int state)
 {
-	unsigned int mask;
-
 	set_tsk_thread_flag(t, TIF_SIGPENDING);
-
 	/*
-	 * For SIGKILL, we want to wake it up in the stopped/traced/killable
+	 * TASK_WAKEKILL also means wake it up in the stopped/traced/killable
 	 * case. We don't check t->state here because there is a race with it
 	 * executing another processor and just now entering stopped state.
 	 * By using wake_up_state, we ensure the process will wake up and
 	 * handle its death signal.
 	 */
-	mask = TASK_INTERRUPTIBLE;
-	if (resume)
-		mask |= TASK_WAKEKILL;
-	if (!wake_up_state(t, mask))
+	if (!wake_up_state(t, state | TASK_INTERRUPTIBLE))
 		kick_process(t);
 }
 
@@ -844,7 +838,7 @@
 	assert_spin_locked(&t->sighand->siglock);
 
 	task_set_jobctl_pending(t, JOBCTL_TRAP_NOTIFY);
-	signal_wake_up(t, t->jobctl & JOBCTL_LISTENING);
+	ptrace_signal_wake_up(t, t->jobctl & JOBCTL_LISTENING);
 }
 
 /*
@@ -1800,6 +1794,10 @@
 	 * If SIGKILL was already sent before the caller unlocked
 	 * ->siglock we must see ->core_state != NULL. Otherwise it
 	 * is safe to enter schedule().
+	 *
+	 * This is almost outdated, a task with the pending SIGKILL can't
+	 * block in TASK_TRACED. But PTRACE_EVENT_EXIT can be reported
+	 * after SIGKILL was already dequeued.
 	 */
 	if (unlikely(current->mm->core_state) &&
 	    unlikely(current->mm == current->parent->mm))
@@ -1925,6 +1923,7 @@
 		if (gstop_done)
 			do_notify_parent_cldstop(current, false, why);
 
+		/* tasklist protects us from ptrace_freeze_traced() */
 		__set_current_state(TASK_RUNNING);
 		if (clear_code)
 			current->exit_code = 0;
@@ -3116,8 +3115,9 @@
 
 #ifdef CONFIG_COMPAT
 #ifdef CONFIG_GENERIC_SIGALTSTACK
-asmlinkage long compat_sys_sigaltstack(const compat_stack_t __user *uss_ptr,
-				       compat_stack_t __user *uoss_ptr)
+COMPAT_SYSCALL_DEFINE2(sigaltstack,
+			const compat_stack_t __user *, uss_ptr,
+			compat_stack_t __user *, uoss_ptr)
 {
 	stack_t uss, uoss;
 	int ret;
diff --git a/kernel/smp.c b/kernel/smp.c
index 29dd40a..69f38bd 100644
--- a/kernel/smp.c
+++ b/kernel/smp.c
@@ -33,6 +33,7 @@
 	struct call_single_data	csd;
 	atomic_t		refs;
 	cpumask_var_t		cpumask;
+	cpumask_var_t		cpumask_ipi;
 };
 
 static DEFINE_PER_CPU_SHARED_ALIGNED(struct call_function_data, cfd_data);
@@ -56,6 +57,9 @@
 		if (!zalloc_cpumask_var_node(&cfd->cpumask, GFP_KERNEL,
 				cpu_to_node(cpu)))
 			return notifier_from_errno(-ENOMEM);
+		if (!zalloc_cpumask_var_node(&cfd->cpumask_ipi, GFP_KERNEL,
+				cpu_to_node(cpu)))
+			return notifier_from_errno(-ENOMEM);
 		break;
 
 #ifdef CONFIG_HOTPLUG_CPU
@@ -65,6 +69,7 @@
 	case CPU_DEAD:
 	case CPU_DEAD_FROZEN:
 		free_cpumask_var(cfd->cpumask);
+		free_cpumask_var(cfd->cpumask_ipi);
 		break;
 #endif
 	};
@@ -526,6 +531,12 @@
 		return;
 	}
 
+	/*
+	 * After we put an entry into the list, data->cpumask
+	 * may be cleared again when another CPU sends another IPI for
+	 * a SMP function call, so data->cpumask will be zero.
+	 */
+	cpumask_copy(data->cpumask_ipi, data->cpumask);
 	raw_spin_lock_irqsave(&call_function.lock, flags);
 	/*
 	 * Place entry at the _HEAD_ of the list, so that any cpu still
@@ -549,7 +560,7 @@
 	smp_mb();
 
 	/* Send a message to all CPUs in the map */
-	arch_send_call_function_ipi_mask(data->cpumask);
+	arch_send_call_function_ipi_mask(data->cpumask_ipi);
 
 	/* Optionally wait for the CPUs to complete */
 	if (wait)
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index cbc6acb..8ed9346 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -135,6 +135,20 @@
 }
 
 /* Timekeeper helper functions. */
+
+#ifdef CONFIG_ARCH_USES_GETTIMEOFFSET
+u32 (*arch_gettimeoffset)(void);
+
+u32 get_arch_timeoffset(void)
+{
+	if (likely(arch_gettimeoffset))
+		return arch_gettimeoffset();
+	return 0;
+}
+#else
+static inline u32 get_arch_timeoffset(void) { return 0; }
+#endif
+
 static inline s64 timekeeping_get_ns(struct timekeeper *tk)
 {
 	cycle_t cycle_now, cycle_delta;
@@ -151,8 +165,8 @@
 	nsec = cycle_delta * tk->mult + tk->xtime_nsec;
 	nsec >>= tk->shift;
 
-	/* If arch requires, add in gettimeoffset() */
-	return nsec + arch_gettimeoffset();
+	/* If arch requires, add in get_arch_timeoffset() */
+	return nsec + get_arch_timeoffset();
 }
 
 static inline s64 timekeeping_get_ns_raw(struct timekeeper *tk)
@@ -171,8 +185,8 @@
 	/* convert delta to nanoseconds. */
 	nsec = clocksource_cyc2ns(cycle_delta, clock->mult, clock->shift);
 
-	/* If arch requires, add in gettimeoffset() */
-	return nsec + arch_gettimeoffset();
+	/* If arch requires, add in get_arch_timeoffset() */
+	return nsec + get_arch_timeoffset();
 }
 
 static RAW_NOTIFIER_HEAD(pvclock_gtod_chain);
@@ -254,8 +268,8 @@
 
 	tk->xtime_nsec += cycle_delta * tk->mult;
 
-	/* If arch requires, add in gettimeoffset() */
-	tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift;
+	/* If arch requires, add in get_arch_timeoffset() */
+	tk->xtime_nsec += (u64)get_arch_timeoffset() << tk->shift;
 
 	tk_normalize_xtime(tk);
 
diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c
index 3ffe4c5..41473b4 100644
--- a/kernel/trace/ftrace.c
+++ b/kernel/trace/ftrace.c
@@ -3998,7 +3998,7 @@
 
 struct notifier_block ftrace_module_nb = {
 	.notifier_call = ftrace_module_notify,
-	.priority = 0,
+	.priority = INT_MAX,	/* Run before anything that can use kprobes */
 };
 
 extern unsigned long __start_mcount_loc[];
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index e512567..3c13e46 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -2899,6 +2899,8 @@
 	if (copy_from_user(&buf, ubuf, cnt))
 		return -EFAULT;
 
+	buf[cnt] = 0;
+
 	trace_set_options(buf);
 
 	*ppos += cnt;
@@ -3452,7 +3454,7 @@
 			return -EINTR;
 
 		/*
-		 * We block until we read something and tracing is enabled.
+		 * We block until we read something and tracing is disabled.
 		 * We still block if tracing is disabled, but we have never
 		 * read anything. This allows a user to cat this file, and
 		 * then enable tracing. But after we have read something,
@@ -3460,7 +3462,7 @@
 		 *
 		 * iter->pos will be 0 if we haven't read anything.
 		 */
-		if (tracing_is_enabled() && iter->pos)
+		if (!tracing_is_enabled() && iter->pos)
 			break;
 	}
 
@@ -4815,10 +4817,17 @@
 		return ret;
 
 	if (buffer) {
-		if (val)
+		mutex_lock(&trace_types_lock);
+		if (val) {
 			ring_buffer_record_on(buffer);
-		else
+			if (current_trace->start)
+				current_trace->start(tr);
+		} else {
 			ring_buffer_record_off(buffer);
+			if (current_trace->stop)
+				current_trace->stop(tr);
+		}
+		mutex_unlock(&trace_types_lock);
 	}
 
 	(*ppos)++;
diff --git a/lib/bug.c b/lib/bug.c
index a28c141..d0cdf14 100644
--- a/lib/bug.c
+++ b/lib/bug.c
@@ -55,6 +55,7 @@
 }
 
 #ifdef CONFIG_MODULES
+/* Updates are protected by module mutex */
 static LIST_HEAD(module_bug_list);
 
 static const struct bug_entry *module_find_bug(unsigned long bugaddr)
diff --git a/lib/cpu_rmap.c b/lib/cpu_rmap.c
index 145dec5..5fbed5c 100644
--- a/lib/cpu_rmap.c
+++ b/lib/cpu_rmap.c
@@ -45,6 +45,7 @@
 	if (!rmap)
 		return NULL;
 
+	kref_init(&rmap->refcount);
 	rmap->obj = (void **)((char *)rmap + obj_offset);
 
 	/* Initially assign CPUs to objects on a rota, since we have
@@ -63,6 +64,35 @@
 }
 EXPORT_SYMBOL(alloc_cpu_rmap);
 
+/**
+ * cpu_rmap_release - internal reclaiming helper called from kref_put
+ * @ref: kref to struct cpu_rmap
+ */
+static void cpu_rmap_release(struct kref *ref)
+{
+	struct cpu_rmap *rmap = container_of(ref, struct cpu_rmap, refcount);
+	kfree(rmap);
+}
+
+/**
+ * cpu_rmap_get - internal helper to get new ref on a cpu_rmap
+ * @rmap: reverse-map allocated with alloc_cpu_rmap()
+ */
+static inline void cpu_rmap_get(struct cpu_rmap *rmap)
+{
+	kref_get(&rmap->refcount);
+}
+
+/**
+ * cpu_rmap_put - release ref on a cpu_rmap
+ * @rmap: reverse-map allocated with alloc_cpu_rmap()
+ */
+int cpu_rmap_put(struct cpu_rmap *rmap)
+{
+	return kref_put(&rmap->refcount, cpu_rmap_release);
+}
+EXPORT_SYMBOL(cpu_rmap_put);
+
 /* Reevaluate nearest object for given CPU, comparing with the given
  * neighbours at the given distance.
  */
@@ -197,8 +227,7 @@
  * free_irq_cpu_rmap - free a CPU affinity reverse-map used for IRQs
  * @rmap: Reverse-map allocated with alloc_irq_cpu_map(), or %NULL
  *
- * Must be called in process context, before freeing the IRQs, and
- * without holding any locks required by global workqueue items.
+ * Must be called in process context, before freeing the IRQs.
  */
 void free_irq_cpu_rmap(struct cpu_rmap *rmap)
 {
@@ -212,12 +241,18 @@
 		glue = rmap->obj[index];
 		irq_set_affinity_notifier(glue->notify.irq, NULL);
 	}
-	irq_run_affinity_notifiers();
 
-	kfree(rmap);
+	cpu_rmap_put(rmap);
 }
 EXPORT_SYMBOL(free_irq_cpu_rmap);
 
+/**
+ * irq_cpu_rmap_notify - callback for IRQ subsystem when IRQ affinity updated
+ * @notify: struct irq_affinity_notify passed by irq/manage.c
+ * @mask: cpu mask for new SMP affinity
+ *
+ * This is executed in workqueue context.
+ */
 static void
 irq_cpu_rmap_notify(struct irq_affinity_notify *notify, const cpumask_t *mask)
 {
@@ -230,10 +265,16 @@
 		pr_warning("irq_cpu_rmap_notify: update failed: %d\n", rc);
 }
 
+/**
+ * irq_cpu_rmap_release - reclaiming callback for IRQ subsystem
+ * @ref: kref to struct irq_affinity_notify passed by irq/manage.c
+ */
 static void irq_cpu_rmap_release(struct kref *ref)
 {
 	struct irq_glue *glue =
 		container_of(ref, struct irq_glue, notify.kref);
+
+	cpu_rmap_put(glue->rmap);
 	kfree(glue);
 }
 
@@ -258,10 +299,13 @@
 	glue->notify.notify = irq_cpu_rmap_notify;
 	glue->notify.release = irq_cpu_rmap_release;
 	glue->rmap = rmap;
+	cpu_rmap_get(rmap);
 	glue->index = cpu_rmap_add(rmap, glue);
 	rc = irq_set_affinity_notifier(irq, &glue->notify);
-	if (rc)
+	if (rc) {
+		cpu_rmap_put(glue->rmap);
 		kfree(glue);
+	}
 	return rc;
 }
 EXPORT_SYMBOL(irq_cpu_rmap_add);
diff --git a/lib/rbtree.c b/lib/rbtree.c
index 4f56a11..c0e31fe 100644
--- a/lib/rbtree.c
+++ b/lib/rbtree.c
@@ -194,8 +194,12 @@
 	}
 }
 
-__always_inline void
-__rb_erase_color(struct rb_node *parent, struct rb_root *root,
+/*
+ * Inline version for rb_erase() use - we want to be able to inline
+ * and eliminate the dummy_rotate callback there
+ */
+static __always_inline void
+____rb_erase_color(struct rb_node *parent, struct rb_root *root,
 	void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
 {
 	struct rb_node *node = NULL, *sibling, *tmp1, *tmp2;
@@ -355,6 +359,13 @@
 		}
 	}
 }
+
+/* Non-inline version for rb_erase_augmented() use */
+void __rb_erase_color(struct rb_node *parent, struct rb_root *root,
+	void (*augment_rotate)(struct rb_node *old, struct rb_node *new))
+{
+	____rb_erase_color(parent, root, augment_rotate);
+}
 EXPORT_SYMBOL(__rb_erase_color);
 
 /*
@@ -380,7 +391,10 @@
 
 void rb_erase(struct rb_node *node, struct rb_root *root)
 {
-	rb_erase_augmented(node, root, &dummy_callbacks);
+	struct rb_node *rebalance;
+	rebalance = __rb_erase_augmented(node, root, &dummy_callbacks);
+	if (rebalance)
+		____rb_erase_color(rebalance, root, dummy_rotate);
 }
 EXPORT_SYMBOL(rb_erase);
 
diff --git a/mm/bootmem.c b/mm/bootmem.c
index 1324cd7..b93376c 100644
--- a/mm/bootmem.c
+++ b/mm/bootmem.c
@@ -185,10 +185,23 @@
 
 	while (start < end) {
 		unsigned long *map, idx, vec;
+		unsigned shift;
 
 		map = bdata->node_bootmem_map;
 		idx = start - bdata->node_min_pfn;
+		shift = idx & (BITS_PER_LONG - 1);
+		/*
+		 * vec holds at most BITS_PER_LONG map bits,
+		 * bit 0 corresponds to start.
+		 */
 		vec = ~map[idx / BITS_PER_LONG];
+
+		if (shift) {
+			vec >>= shift;
+			if (end - start >= BITS_PER_LONG)
+				vec |= ~map[idx / BITS_PER_LONG + 1] <<
+					(BITS_PER_LONG - shift);
+		}
 		/*
 		 * If we have a properly aligned and fully unreserved
 		 * BITS_PER_LONG block of pages in front of us, free
@@ -201,19 +214,18 @@
 			count += BITS_PER_LONG;
 			start += BITS_PER_LONG;
 		} else {
-			unsigned long off = 0;
+			unsigned long cur = start;
 
-			vec >>= start & (BITS_PER_LONG - 1);
-			while (vec) {
+			start = ALIGN(start + 1, BITS_PER_LONG);
+			while (vec && cur != start) {
 				if (vec & 1) {
-					page = pfn_to_page(start + off);
+					page = pfn_to_page(cur);
 					__free_pages_bootmem(page, 0);
 					count++;
 				}
 				vec >>= 1;
-				off++;
+				++cur;
 			}
-			start = ALIGN(start + 1, BITS_PER_LONG);
 		}
 	}
 
diff --git a/mm/compaction.c b/mm/compaction.c
index 6b807e4..c62bd06 100644
--- a/mm/compaction.c
+++ b/mm/compaction.c
@@ -816,6 +816,7 @@
 static int compact_finished(struct zone *zone,
 			    struct compact_control *cc)
 {
+	unsigned int order;
 	unsigned long watermark;
 
 	if (fatal_signal_pending(current))
@@ -850,22 +851,16 @@
 		return COMPACT_CONTINUE;
 
 	/* Direct compactor: Is a suitable page free? */
-	if (cc->page) {
-		/* Was a suitable page captured? */
-		if (*cc->page)
-			return COMPACT_PARTIAL;
-	} else {
-		unsigned int order;
-		for (order = cc->order; order < MAX_ORDER; order++) {
-			struct free_area *area = &zone->free_area[cc->order];
-			/* Job done if page is free of the right migratetype */
-			if (!list_empty(&area->free_list[cc->migratetype]))
-				return COMPACT_PARTIAL;
+	for (order = cc->order; order < MAX_ORDER; order++) {
+		struct free_area *area = &zone->free_area[order];
 
-			/* Job done if allocation would set block type */
-			if (cc->order >= pageblock_order && area->nr_free)
-				return COMPACT_PARTIAL;
-		}
+		/* Job done if page is free of the right migratetype */
+		if (!list_empty(&area->free_list[cc->migratetype]))
+			return COMPACT_PARTIAL;
+
+		/* Job done if allocation would set block type */
+		if (cc->order >= pageblock_order && area->nr_free)
+			return COMPACT_PARTIAL;
 	}
 
 	return COMPACT_CONTINUE;
@@ -921,60 +916,6 @@
 	return COMPACT_CONTINUE;
 }
 
-static void compact_capture_page(struct compact_control *cc)
-{
-	unsigned long flags;
-	int mtype, mtype_low, mtype_high;
-
-	if (!cc->page || *cc->page)
-		return;
-
-	/*
-	 * For MIGRATE_MOVABLE allocations we capture a suitable page ASAP
-	 * regardless of the migratetype of the freelist is is captured from.
-	 * This is fine because the order for a high-order MIGRATE_MOVABLE
-	 * allocation is typically at least a pageblock size and overall
-	 * fragmentation is not impaired. Other allocation types must
-	 * capture pages from their own migratelist because otherwise they
-	 * could pollute other pageblocks like MIGRATE_MOVABLE with
-	 * difficult to move pages and making fragmentation worse overall.
-	 */
-	if (cc->migratetype == MIGRATE_MOVABLE) {
-		mtype_low = 0;
-		mtype_high = MIGRATE_PCPTYPES;
-	} else {
-		mtype_low = cc->migratetype;
-		mtype_high = cc->migratetype + 1;
-	}
-
-	/* Speculatively examine the free lists without zone lock */
-	for (mtype = mtype_low; mtype < mtype_high; mtype++) {
-		int order;
-		for (order = cc->order; order < MAX_ORDER; order++) {
-			struct page *page;
-			struct free_area *area;
-			area = &(cc->zone->free_area[order]);
-			if (list_empty(&area->free_list[mtype]))
-				continue;
-
-			/* Take the lock and attempt capture of the page */
-			if (!compact_trylock_irqsave(&cc->zone->lock, &flags, cc))
-				return;
-			if (!list_empty(&area->free_list[mtype])) {
-				page = list_entry(area->free_list[mtype].next,
-							struct page, lru);
-				if (capture_free_page(page, cc->order, mtype)) {
-					spin_unlock_irqrestore(&cc->zone->lock,
-									flags);
-					*cc->page = page;
-					return;
-				}
-			}
-			spin_unlock_irqrestore(&cc->zone->lock, flags);
-		}
-	}
-}
-
 static int compact_zone(struct zone *zone, struct compact_control *cc)
 {
 	int ret;
@@ -1054,9 +995,6 @@
 				goto out;
 			}
 		}
-
-		/* Capture a page now if it is a suitable size */
-		compact_capture_page(cc);
 	}
 
 out:
@@ -1069,8 +1007,7 @@
 
 static unsigned long compact_zone_order(struct zone *zone,
 				 int order, gfp_t gfp_mask,
-				 bool sync, bool *contended,
-				 struct page **page)
+				 bool sync, bool *contended)
 {
 	unsigned long ret;
 	struct compact_control cc = {
@@ -1080,7 +1017,6 @@
 		.migratetype = allocflags_to_migratetype(gfp_mask),
 		.zone = zone,
 		.sync = sync,
-		.page = page,
 	};
 	INIT_LIST_HEAD(&cc.freepages);
 	INIT_LIST_HEAD(&cc.migratepages);
@@ -1110,7 +1046,7 @@
  */
 unsigned long try_to_compact_pages(struct zonelist *zonelist,
 			int order, gfp_t gfp_mask, nodemask_t *nodemask,
-			bool sync, bool *contended, struct page **page)
+			bool sync, bool *contended)
 {
 	enum zone_type high_zoneidx = gfp_zone(gfp_mask);
 	int may_enter_fs = gfp_mask & __GFP_FS;
@@ -1136,7 +1072,7 @@
 		int status;
 
 		status = compact_zone_order(zone, order, gfp_mask, sync,
-						contended, page);
+						contended);
 		rc = max(status, rc);
 
 		/* If a normal allocation would succeed, stop compacting */
@@ -1192,7 +1128,6 @@
 	struct compact_control cc = {
 		.order = order,
 		.sync = false,
-		.page = NULL,
 	};
 
 	return __compact_pgdat(pgdat, &cc);
@@ -1203,14 +1138,13 @@
 	struct compact_control cc = {
 		.order = -1,
 		.sync = true,
-		.page = NULL,
 	};
 
 	return __compact_pgdat(NODE_DATA(nid), &cc);
 }
 
 /* Compact all nodes in the system */
-static int compact_nodes(void)
+static void compact_nodes(void)
 {
 	int nid;
 
@@ -1219,8 +1153,6 @@
 
 	for_each_online_node(nid)
 		compact_node(nid);
-
-	return COMPACT_COMPLETE;
 }
 
 /* The written value is actually unused, all memory is compacted */
@@ -1231,7 +1163,7 @@
 			void __user *buffer, size_t *length, loff_t *ppos)
 {
 	if (write)
-		return compact_nodes();
+		compact_nodes();
 
 	return 0;
 }
diff --git a/mm/huge_memory.c b/mm/huge_memory.c
index 9e894ed..6001ee6 100644
--- a/mm/huge_memory.c
+++ b/mm/huge_memory.c
@@ -1819,9 +1819,19 @@
 
 	BUG_ON(is_huge_zero_pfn(page_to_pfn(page)));
 	BUG_ON(!PageAnon(page));
-	anon_vma = page_lock_anon_vma_read(page);
+
+	/*
+	 * The caller does not necessarily hold an mmap_sem that would prevent
+	 * the anon_vma disappearing so we first we take a reference to it
+	 * and then lock the anon_vma for write. This is similar to
+	 * page_lock_anon_vma_read except the write lock is taken to serialise
+	 * against parallel split or collapse operations.
+	 */
+	anon_vma = page_get_anon_vma(page);
 	if (!anon_vma)
 		goto out;
+	anon_vma_lock_write(anon_vma);
+
 	ret = 0;
 	if (!PageCompound(page))
 		goto out_unlock;
@@ -1832,7 +1842,8 @@
 
 	BUG_ON(PageCompound(page));
 out_unlock:
-	page_unlock_anon_vma_read(anon_vma);
+	anon_vma_unlock(anon_vma);
+	put_anon_vma(anon_vma);
 out:
 	return ret;
 }
diff --git a/mm/internal.h b/mm/internal.h
index d597f94..9ba2110 100644
--- a/mm/internal.h
+++ b/mm/internal.h
@@ -135,7 +135,6 @@
 	int migratetype;		/* MOVABLE, RECLAIMABLE etc */
 	struct zone *zone;
 	bool contended;			/* True if a lock was contended */
-	struct page **page;		/* Page captured of requested size */
 };
 
 unsigned long
diff --git a/mm/memblock.c b/mm/memblock.c
index 6259055..88adc8a 100644
--- a/mm/memblock.c
+++ b/mm/memblock.c
@@ -314,7 +314,8 @@
 		}
 
 		this->size += next->size;
-		memmove(next, next + 1, (type->cnt - (i + 1)) * sizeof(*next));
+		/* move forward from next + 1, index of which is i + 2 */
+		memmove(next, next + 1, (type->cnt - (i + 2)) * sizeof(*next));
 		type->cnt--;
 	}
 }
diff --git a/mm/migrate.c b/mm/migrate.c
index 3b676b0..c387786 100644
--- a/mm/migrate.c
+++ b/mm/migrate.c
@@ -1679,9 +1679,21 @@
 	page_xchg_last_nid(new_page, page_last_nid(page));
 
 	isolated = numamigrate_isolate_page(pgdat, page);
-	if (!isolated) {
+
+	/*
+	 * Failing to isolate or a GUP pin prevents migration. The expected
+	 * page count is 2. 1 for anonymous pages without a mapping and 1
+	 * for the callers pin. If the page was isolated, the page will
+	 * need to be put back on the LRU.
+	 */
+	if (!isolated || page_count(page) != 2) {
 		count_vm_events(PGMIGRATE_FAIL, HPAGE_PMD_NR);
 		put_page(new_page);
+		if (isolated) {
+			putback_lru_page(page);
+			isolated = 0;
+			goto out;
+		}
 		goto out_keep_locked;
 	}
 
diff --git a/mm/mmap.c b/mm/mmap.c
index f54b235..35730ee 100644
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -2886,7 +2886,7 @@
 		 * The LSB of head.next can't change from under us
 		 * because we hold the mm_all_locks_mutex.
 		 */
-		down_write(&anon_vma->root->rwsem);
+		down_write_nest_lock(&anon_vma->root->rwsem, &mm->mmap_sem);
 		/*
 		 * We can safely modify head.next after taking the
 		 * anon_vma->root->rwsem. If some other vma in this mm shares
diff --git a/mm/page_alloc.c b/mm/page_alloc.c
index bc6cc0e..df2022f 100644
--- a/mm/page_alloc.c
+++ b/mm/page_alloc.c
@@ -1384,14 +1384,8 @@
 		set_page_refcounted(page + i);
 }
 
-/*
- * Similar to the split_page family of functions except that the page
- * required at the given order and being isolated now to prevent races
- * with parallel allocators
- */
-int capture_free_page(struct page *page, int alloc_order, int migratetype)
+static int __isolate_free_page(struct page *page, unsigned int order)
 {
-	unsigned int order;
 	unsigned long watermark;
 	struct zone *zone;
 	int mt;
@@ -1399,7 +1393,6 @@
 	BUG_ON(!PageBuddy(page));
 
 	zone = page_zone(page);
-	order = page_order(page);
 	mt = get_pageblock_migratetype(page);
 
 	if (mt != MIGRATE_ISOLATE) {
@@ -1408,7 +1401,7 @@
 		if (!zone_watermark_ok(zone, 0, watermark, 0, 0))
 			return 0;
 
-		__mod_zone_freepage_state(zone, -(1UL << alloc_order), mt);
+		__mod_zone_freepage_state(zone, -(1UL << order), mt);
 	}
 
 	/* Remove page from free list */
@@ -1416,11 +1409,7 @@
 	zone->free_area[order].nr_free--;
 	rmv_page_order(page);
 
-	if (alloc_order != order)
-		expand(zone, page, alloc_order, order,
-			&zone->free_area[order], migratetype);
-
-	/* Set the pageblock if the captured page is at least a pageblock */
+	/* Set the pageblock if the isolated page is at least a pageblock */
 	if (order >= pageblock_order - 1) {
 		struct page *endpage = page + (1 << order) - 1;
 		for (; page < endpage; page += pageblock_nr_pages) {
@@ -1431,7 +1420,7 @@
 		}
 	}
 
-	return 1UL << alloc_order;
+	return 1UL << order;
 }
 
 /*
@@ -1449,10 +1438,9 @@
 	unsigned int order;
 	int nr_pages;
 
-	BUG_ON(!PageBuddy(page));
 	order = page_order(page);
 
-	nr_pages = capture_free_page(page, order, 0);
+	nr_pages = __isolate_free_page(page, order);
 	if (!nr_pages)
 		return 0;
 
@@ -2136,8 +2124,6 @@
 	bool *contended_compaction, bool *deferred_compaction,
 	unsigned long *did_some_progress)
 {
-	struct page *page = NULL;
-
 	if (!order)
 		return NULL;
 
@@ -2149,16 +2135,12 @@
 	current->flags |= PF_MEMALLOC;
 	*did_some_progress = try_to_compact_pages(zonelist, order, gfp_mask,
 						nodemask, sync_migration,
-						contended_compaction, &page);
+						contended_compaction);
 	current->flags &= ~PF_MEMALLOC;
 
-	/* If compaction captured a page, prep and use it */
-	if (page) {
-		prep_new_page(page, order, gfp_mask);
-		goto got_page;
-	}
-
 	if (*did_some_progress != COMPACT_SKIPPED) {
+		struct page *page;
+
 		/* Page migration frees to the PCP lists but we want merging */
 		drain_pages(get_cpu());
 		put_cpu();
@@ -2168,7 +2150,6 @@
 				alloc_flags & ~ALLOC_NO_WATERMARKS,
 				preferred_zone, migratetype);
 		if (page) {
-got_page:
 			preferred_zone->compact_blockskip_flush = false;
 			preferred_zone->compact_considered = 0;
 			preferred_zone->compact_defer_shift = 0;
@@ -5604,7 +5585,7 @@
 	pfn &= (PAGES_PER_SECTION-1);
 	return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
 #else
-	pfn = pfn - zone->zone_start_pfn;
+	pfn = pfn - round_down(zone->zone_start_pfn, pageblock_nr_pages);
 	return (pfn >> pageblock_order) * NR_PAGEBLOCK_BITS;
 #endif /* CONFIG_SPARSEMEM */
 }
diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c
index 8e1d89d..183f97a 100644
--- a/net/batman-adv/distributed-arp-table.c
+++ b/net/batman-adv/distributed-arp-table.c
@@ -738,6 +738,7 @@
 	struct arphdr *arphdr;
 	struct ethhdr *ethhdr;
 	__be32 ip_src, ip_dst;
+	uint8_t *hw_src, *hw_dst;
 	uint16_t type = 0;
 
 	/* pull the ethernet header */
@@ -777,9 +778,23 @@
 	ip_src = batadv_arp_ip_src(skb, hdr_size);
 	ip_dst = batadv_arp_ip_dst(skb, hdr_size);
 	if (ipv4_is_loopback(ip_src) || ipv4_is_multicast(ip_src) ||
-	    ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst))
+	    ipv4_is_loopback(ip_dst) || ipv4_is_multicast(ip_dst) ||
+	    ipv4_is_zeronet(ip_src) || ipv4_is_lbcast(ip_src) ||
+	    ipv4_is_zeronet(ip_dst) || ipv4_is_lbcast(ip_dst))
 		goto out;
 
+	hw_src = batadv_arp_hw_src(skb, hdr_size);
+	if (is_zero_ether_addr(hw_src) || is_multicast_ether_addr(hw_src))
+		goto out;
+
+	/* we don't care about the destination MAC address in ARP requests */
+	if (arphdr->ar_op != htons(ARPOP_REQUEST)) {
+		hw_dst = batadv_arp_hw_dst(skb, hdr_size);
+		if (is_zero_ether_addr(hw_dst) ||
+		    is_multicast_ether_addr(hw_dst))
+			goto out;
+	}
+
 	type = ntohs(arphdr->ar_op);
 out:
 	return type;
@@ -1012,6 +1027,8 @@
 	 */
 	ret = !batadv_is_my_client(bat_priv, hw_dst);
 out:
+	if (ret)
+		kfree_skb(skb);
 	/* if ret == false -> packet has to be delivered to the interface */
 	return ret;
 }
diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c
index 596660d..0f78e34 100644
--- a/net/bluetooth/hci_core.c
+++ b/net/bluetooth/hci_core.c
@@ -2810,14 +2810,6 @@
 	if (conn) {
 		hci_conn_enter_active_mode(conn, BT_POWER_FORCE_ACTIVE_OFF);
 
-		hci_dev_lock(hdev);
-		if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
-		    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags))
-			mgmt_device_connected(hdev, &conn->dst, conn->type,
-					      conn->dst_type, 0, NULL, 0,
-					      conn->dev_class);
-		hci_dev_unlock(hdev);
-
 		/* Send to upper protocol */
 		l2cap_recv_acldata(conn, skb, flags);
 		return;
diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c
index 705078a..81b4448 100644
--- a/net/bluetooth/hci_event.c
+++ b/net/bluetooth/hci_event.c
@@ -2688,7 +2688,7 @@
 	if (ev->opcode != HCI_OP_NOP)
 		del_timer(&hdev->cmd_timer);
 
-	if (ev->ncmd) {
+	if (ev->ncmd && !test_bit(HCI_RESET, &hdev->flags)) {
 		atomic_set(&hdev->cmd_cnt, 1);
 		if (!skb_queue_empty(&hdev->cmd_q))
 			queue_work(hdev->workqueue, &hdev->cmd_work);
diff --git a/net/bluetooth/hidp/core.c b/net/bluetooth/hidp/core.c
index b2bcbe2..a7352ff 100644
--- a/net/bluetooth/hidp/core.c
+++ b/net/bluetooth/hidp/core.c
@@ -931,7 +931,7 @@
 	hid->version = req->version;
 	hid->country = req->country;
 
-	strncpy(hid->name, req->name, 128);
+	strncpy(hid->name, req->name, sizeof(req->name) - 1);
 
 	snprintf(hid->phys, sizeof(hid->phys), "%pMR",
 		 &bt_sk(session->ctrl_sock->sk)->src);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 2c78208..22e6583 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -3727,6 +3727,17 @@
 static int l2cap_connect_req(struct l2cap_conn *conn,
 			     struct l2cap_cmd_hdr *cmd, u8 *data)
 {
+	struct hci_dev *hdev = conn->hcon->hdev;
+	struct hci_conn *hcon = conn->hcon;
+
+	hci_dev_lock(hdev);
+	if (test_bit(HCI_MGMT, &hdev->dev_flags) &&
+	    !test_and_set_bit(HCI_CONN_MGMT_CONNECTED, &hcon->flags))
+		mgmt_device_connected(hdev, &hcon->dst, hcon->type,
+				      hcon->dst_type, 0, NULL, 0,
+				      hcon->dev_class);
+	hci_dev_unlock(hdev);
+
 	l2cap_connect(conn, cmd, data, L2CAP_CONN_RSP, 0);
 	return 0;
 }
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index 531a93d..57f250c 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -352,7 +352,7 @@
 
 	case BT_CONNECTED:
 	case BT_CONFIG:
-		if (sco_pi(sk)->conn) {
+		if (sco_pi(sk)->conn->hcon) {
 			sk->sk_state = BT_DISCONN;
 			sco_sock_set_timer(sk, SCO_DISCONN_TIMEOUT);
 			hci_conn_put(sco_pi(sk)->conn->hcon);
diff --git a/net/core/dev.c b/net/core/dev.c
index 515473e..f64e439b 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -6121,6 +6121,14 @@
 
 static const struct ethtool_ops default_ethtool_ops;
 
+void netdev_set_default_ethtool_ops(struct net_device *dev,
+				    const struct ethtool_ops *ops)
+{
+	if (dev->ethtool_ops == &default_ethtool_ops)
+		dev->ethtool_ops = ops;
+}
+EXPORT_SYMBOL_GPL(netdev_set_default_ethtool_ops);
+
 /**
  *	alloc_netdev_mqs - allocate network device
  *	@sizeof_priv:	size of private data to allocate space for
diff --git a/net/core/request_sock.c b/net/core/request_sock.c
index c31d9e8..4425148 100644
--- a/net/core/request_sock.c
+++ b/net/core/request_sock.c
@@ -186,8 +186,6 @@
 	struct fastopen_queue *fastopenq =
 	    inet_csk(lsk)->icsk_accept_queue.fastopenq;
 
-	BUG_ON(!spin_is_locked(&sk->sk_lock.slock) && !sock_owned_by_user(sk));
-
 	tcp_sk(sk)->fastopen_rsk = NULL;
 	spin_lock_bh(&fastopenq->lock);
 	fastopenq->qlen--;
diff --git a/net/core/scm.c b/net/core/scm.c
index 57fb1ee..905dcc6 100644
--- a/net/core/scm.c
+++ b/net/core/scm.c
@@ -35,6 +35,7 @@
 #include <net/sock.h>
 #include <net/compat.h>
 #include <net/scm.h>
+#include <net/cls_cgroup.h>
 
 
 /*
@@ -302,8 +303,10 @@
 		}
 		/* Bump the usage count and install the file. */
 		sock = sock_from_file(fp[i], &err);
-		if (sock)
+		if (sock) {
 			sock_update_netprioidx(sock->sk, current);
+			sock_update_classid(sock->sk, current);
+		}
 		fd_install(new_fd, get_file(fp[i]));
 	}
 
diff --git a/net/core/skbuff.c b/net/core/skbuff.c
index 3ab989b..a9a2ae3 100644
--- a/net/core/skbuff.c
+++ b/net/core/skbuff.c
@@ -1649,7 +1649,7 @@
 
 static struct page *linear_to_page(struct page *page, unsigned int *len,
 				   unsigned int *offset,
-				   struct sk_buff *skb, struct sock *sk)
+				   struct sock *sk)
 {
 	struct page_frag *pfrag = sk_page_frag(sk);
 
@@ -1682,14 +1682,14 @@
 static bool spd_fill_page(struct splice_pipe_desc *spd,
 			  struct pipe_inode_info *pipe, struct page *page,
 			  unsigned int *len, unsigned int offset,
-			  struct sk_buff *skb, bool linear,
+			  bool linear,
 			  struct sock *sk)
 {
 	if (unlikely(spd->nr_pages == MAX_SKB_FRAGS))
 		return true;
 
 	if (linear) {
-		page = linear_to_page(page, len, &offset, skb, sk);
+		page = linear_to_page(page, len, &offset, sk);
 		if (!page)
 			return true;
 	}
@@ -1706,23 +1706,9 @@
 	return false;
 }
 
-static inline void __segment_seek(struct page **page, unsigned int *poff,
-				  unsigned int *plen, unsigned int off)
-{
-	unsigned long n;
-
-	*poff += off;
-	n = *poff / PAGE_SIZE;
-	if (n)
-		*page = nth_page(*page, n);
-
-	*poff = *poff % PAGE_SIZE;
-	*plen -= off;
-}
-
 static bool __splice_segment(struct page *page, unsigned int poff,
 			     unsigned int plen, unsigned int *off,
-			     unsigned int *len, struct sk_buff *skb,
+			     unsigned int *len,
 			     struct splice_pipe_desc *spd, bool linear,
 			     struct sock *sk,
 			     struct pipe_inode_info *pipe)
@@ -1737,23 +1723,19 @@
 	}
 
 	/* ignore any bits we already processed */
-	if (*off) {
-		__segment_seek(&page, &poff, &plen, *off);
-		*off = 0;
-	}
+	poff += *off;
+	plen -= *off;
+	*off = 0;
 
 	do {
 		unsigned int flen = min(*len, plen);
 
-		/* the linear region may spread across several pages  */
-		flen = min_t(unsigned int, flen, PAGE_SIZE - poff);
-
-		if (spd_fill_page(spd, pipe, page, &flen, poff, skb, linear, sk))
+		if (spd_fill_page(spd, pipe, page, &flen, poff,
+				  linear, sk))
 			return true;
-
-		__segment_seek(&page, &poff, &plen, flen);
+		poff += flen;
+		plen -= flen;
 		*len -= flen;
-
 	} while (*len && plen);
 
 	return false;
@@ -1777,7 +1759,7 @@
 	if (__splice_segment(virt_to_page(skb->data),
 			     (unsigned long) skb->data & (PAGE_SIZE - 1),
 			     skb_headlen(skb),
-			     offset, len, skb, spd,
+			     offset, len, spd,
 			     skb_head_is_locked(skb),
 			     sk, pipe))
 		return true;
@@ -1790,7 +1772,7 @@
 
 		if (__splice_segment(skb_frag_page(f),
 				     f->page_offset, skb_frag_size(f),
-				     offset, len, skb, spd, false, sk, pipe))
+				     offset, len, spd, false, sk, pipe))
 			return true;
 	}
 
diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c
index a0d8392..a69b4e4 100644
--- a/net/ipv4/ah4.c
+++ b/net/ipv4/ah4.c
@@ -269,7 +269,11 @@
 	skb->network_header += ah_hlen;
 	memcpy(skb_network_header(skb), work_iph, ihl);
 	__skb_pull(skb, ah_hlen + ihl);
-	skb_set_transport_header(skb, -ihl);
+
+	if (x->props.mode == XFRM_MODE_TUNNEL)
+		skb_reset_transport_header(skb);
+	else
+		skb_set_transport_header(skb, -ihl);
 out:
 	kfree(AH_SKB_CB(skb)->tmp);
 	xfrm_input_resume(skb, err);
@@ -381,7 +385,10 @@
 	skb->network_header += ah_hlen;
 	memcpy(skb_network_header(skb), work_iph, ihl);
 	__skb_pull(skb, ah_hlen + ihl);
-	skb_set_transport_header(skb, -ihl);
+	if (x->props.mode == XFRM_MODE_TUNNEL)
+		skb_reset_transport_header(skb);
+	else
+		skb_set_transport_header(skb, -ihl);
 
 	err = nexthdr;
 
@@ -413,9 +420,12 @@
 	if (!x)
 		return;
 
-	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
+		atomic_inc(&flow_cache_genid);
+		rt_genid_bump(net);
+
 		ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_AH, 0);
-	else
+	} else
 		ipv4_redirect(skb, net, 0, 0, IPPROTO_AH, 0);
 	xfrm_state_put(x);
 }
diff --git a/net/ipv4/datagram.c b/net/ipv4/datagram.c
index 424fafb..b28e863 100644
--- a/net/ipv4/datagram.c
+++ b/net/ipv4/datagram.c
@@ -85,3 +85,28 @@
 	return err;
 }
 EXPORT_SYMBOL(ip4_datagram_connect);
+
+void ip4_datagram_release_cb(struct sock *sk)
+{
+	const struct inet_sock *inet = inet_sk(sk);
+	const struct ip_options_rcu *inet_opt;
+	__be32 daddr = inet->inet_daddr;
+	struct flowi4 fl4;
+	struct rtable *rt;
+
+	if (! __sk_dst_get(sk) || __sk_dst_check(sk, 0))
+		return;
+
+	rcu_read_lock();
+	inet_opt = rcu_dereference(inet->inet_opt);
+	if (inet_opt && inet_opt->opt.srr)
+		daddr = inet_opt->opt.faddr;
+	rt = ip_route_output_ports(sock_net(sk), &fl4, sk, daddr,
+				   inet->inet_saddr, inet->inet_dport,
+				   inet->inet_sport, sk->sk_protocol,
+				   RT_CONN_FLAGS(sk), sk->sk_bound_dev_if);
+	if (!IS_ERR(rt))
+		__sk_dst_set(sk, &rt->dst);
+	rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(ip4_datagram_release_cb);
diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c
index b61e9de..3b4f0cd 100644
--- a/net/ipv4/esp4.c
+++ b/net/ipv4/esp4.c
@@ -346,7 +346,10 @@
 
 	pskb_trim(skb, skb->len - alen - padlen - 2);
 	__skb_pull(skb, hlen);
-	skb_set_transport_header(skb, -ihl);
+	if (x->props.mode == XFRM_MODE_TUNNEL)
+		skb_reset_transport_header(skb);
+	else
+		skb_set_transport_header(skb, -ihl);
 
 	err = nexthdr[1];
 
@@ -499,9 +502,12 @@
 	if (!x)
 		return;
 
-	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
+		atomic_inc(&flow_cache_genid);
+		rt_genid_bump(net);
+
 		ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_ESP, 0);
-	else
+	} else
 		ipv4_redirect(skb, net, 0, 0, IPPROTO_ESP, 0);
 	xfrm_state_put(x);
 }
diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c
index 303012a..e81b1ca 100644
--- a/net/ipv4/ip_gre.c
+++ b/net/ipv4/ip_gre.c
@@ -963,8 +963,12 @@
 			ptr--;
 		}
 		if (tunnel->parms.o_flags&GRE_CSUM) {
+			int offset = skb_transport_offset(skb);
+
 			*ptr = 0;
-			*(__sum16 *)ptr = ip_compute_csum((void *)(iph+1), skb->len - sizeof(struct iphdr));
+			*(__sum16 *)ptr = csum_fold(skb_checksum(skb, offset,
+								 skb->len - offset,
+								 0));
 		}
 	}
 
diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
index 3c9d208..d9c4f11 100644
--- a/net/ipv4/ip_sockglue.c
+++ b/net/ipv4/ip_sockglue.c
@@ -590,7 +590,7 @@
 	case IP_TTL:
 		if (optlen < 1)
 			goto e_inval;
-		if (val != -1 && (val < 0 || val > 255))
+		if (val != -1 && (val < 1 || val > 255))
 			goto e_inval;
 		inet->uc_ttl = val;
 		break;
diff --git a/net/ipv4/ipcomp.c b/net/ipv4/ipcomp.c
index d3ab47e..9a46dae 100644
--- a/net/ipv4/ipcomp.c
+++ b/net/ipv4/ipcomp.c
@@ -47,9 +47,12 @@
 	if (!x)
 		return;
 
-	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH)
+	if (icmp_hdr(skb)->type == ICMP_DEST_UNREACH) {
+		atomic_inc(&flow_cache_genid);
+		rt_genid_bump(net);
+
 		ipv4_update_pmtu(skb, net, info, 0, 0, IPPROTO_COMP, 0);
-	else
+	} else
 		ipv4_redirect(skb, net, 0, 0, IPPROTO_COMP, 0);
 	xfrm_state_put(x);
 }
diff --git a/net/ipv4/ping.c b/net/ipv4/ping.c
index 8f3d054..6f9c072 100644
--- a/net/ipv4/ping.c
+++ b/net/ipv4/ping.c
@@ -738,6 +738,7 @@
 	.recvmsg =	ping_recvmsg,
 	.bind =		ping_bind,
 	.backlog_rcv =	ping_queue_rcv_skb,
+	.release_cb =	ip4_datagram_release_cb,
 	.hash =		ping_v4_hash,
 	.unhash =	ping_v4_unhash,
 	.get_port =	ping_v4_get_port,
diff --git a/net/ipv4/raw.c b/net/ipv4/raw.c
index 73d1e4d..6f08991 100644
--- a/net/ipv4/raw.c
+++ b/net/ipv4/raw.c
@@ -894,6 +894,7 @@
 	.recvmsg	   = raw_recvmsg,
 	.bind		   = raw_bind,
 	.backlog_rcv	   = raw_rcv_skb,
+	.release_cb	   = ip4_datagram_release_cb,
 	.hash		   = raw_hash_sk,
 	.unhash		   = raw_unhash_sk,
 	.obj_size	   = sizeof(struct raw_sock),
diff --git a/net/ipv4/route.c b/net/ipv4/route.c
index 844a9ef..a0fcc47 100644
--- a/net/ipv4/route.c
+++ b/net/ipv4/route.c
@@ -912,6 +912,9 @@
 	struct dst_entry *dst = &rt->dst;
 	struct fib_result res;
 
+	if (dst_metric_locked(dst, RTAX_MTU))
+		return;
+
 	if (dst->dev->mtu < mtu)
 		return;
 
@@ -962,7 +965,7 @@
 }
 EXPORT_SYMBOL_GPL(ipv4_update_pmtu);
 
-void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
+static void __ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
 {
 	const struct iphdr *iph = (const struct iphdr *) skb->data;
 	struct flowi4 fl4;
@@ -975,6 +978,53 @@
 		ip_rt_put(rt);
 	}
 }
+
+void ipv4_sk_update_pmtu(struct sk_buff *skb, struct sock *sk, u32 mtu)
+{
+	const struct iphdr *iph = (const struct iphdr *) skb->data;
+	struct flowi4 fl4;
+	struct rtable *rt;
+	struct dst_entry *dst;
+	bool new = false;
+
+	bh_lock_sock(sk);
+	rt = (struct rtable *) __sk_dst_get(sk);
+
+	if (sock_owned_by_user(sk) || !rt) {
+		__ipv4_sk_update_pmtu(skb, sk, mtu);
+		goto out;
+	}
+
+	__build_flow_key(&fl4, sk, iph, 0, 0, 0, 0, 0);
+
+	if (!__sk_dst_check(sk, 0)) {
+		rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
+		if (IS_ERR(rt))
+			goto out;
+
+		new = true;
+	}
+
+	__ip_rt_update_pmtu((struct rtable *) rt->dst.path, &fl4, mtu);
+
+	dst = dst_check(&rt->dst, 0);
+	if (!dst) {
+		if (new)
+			dst_release(&rt->dst);
+
+		rt = ip_route_output_flow(sock_net(sk), &fl4, sk);
+		if (IS_ERR(rt))
+			goto out;
+
+		new = true;
+	}
+
+	if (new)
+		__sk_dst_set(sk, &rt->dst);
+
+out:
+	bh_unlock_sock(sk);
+}
 EXPORT_SYMBOL_GPL(ipv4_sk_update_pmtu);
 
 void ipv4_redirect(struct sk_buff *skb, struct net *net,
@@ -1120,7 +1170,7 @@
 	if (!mtu || time_after_eq(jiffies, rt->dst.expires))
 		mtu = dst_metric_raw(dst, RTAX_MTU);
 
-	if (mtu && rt_is_output_route(rt))
+	if (mtu)
 		return mtu;
 
 	mtu = dst->dev->mtu;
diff --git a/net/ipv4/tcp.c b/net/ipv4/tcp.c
index 1ca2536..2aa69c8 100644
--- a/net/ipv4/tcp.c
+++ b/net/ipv4/tcp.c
@@ -1428,12 +1428,12 @@
 }
 #endif
 
-static inline struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
+static struct sk_buff *tcp_recv_skb(struct sock *sk, u32 seq, u32 *off)
 {
 	struct sk_buff *skb;
 	u32 offset;
 
-	skb_queue_walk(&sk->sk_receive_queue, skb) {
+	while ((skb = skb_peek(&sk->sk_receive_queue)) != NULL) {
 		offset = seq - TCP_SKB_CB(skb)->seq;
 		if (tcp_hdr(skb)->syn)
 			offset--;
@@ -1441,6 +1441,11 @@
 			*off = offset;
 			return skb;
 		}
+		/* This looks weird, but this can happen if TCP collapsing
+		 * splitted a fat GRO packet, while we released socket lock
+		 * in skb_splice_bits()
+		 */
+		sk_eat_skb(sk, skb, false);
 	}
 	return NULL;
 }
@@ -1482,7 +1487,7 @@
 					break;
 			}
 			used = recv_actor(desc, skb, offset, len);
-			if (used < 0) {
+			if (used <= 0) {
 				if (!copied)
 					copied = used;
 				break;
@@ -1520,8 +1525,10 @@
 	tcp_rcv_space_adjust(sk);
 
 	/* Clean up data we have read: This will do ACK frames. */
-	if (copied > 0)
+	if (copied > 0) {
+		tcp_recv_skb(sk, seq, &offset);
 		tcp_cleanup_rbuf(sk, copied);
+	}
 	return copied;
 }
 EXPORT_SYMBOL(tcp_read_sock);
diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c
index a28e4db..18f97ca 100644
--- a/net/ipv4/tcp_input.c
+++ b/net/ipv4/tcp_input.c
@@ -5543,7 +5543,7 @@
 	if (len < (th->doff << 2) || tcp_checksum_complete_user(sk, skb))
 		goto csum_error;
 
-	if (!th->ack)
+	if (!th->ack && !th->rst)
 		goto discard;
 
 	/*
@@ -5988,7 +5988,7 @@
 			goto discard;
 	}
 
-	if (!th->ack)
+	if (!th->ack && !th->rst)
 		goto discard;
 
 	if (!tcp_validate_incoming(sk, skb, th, 0))
diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
index 54139fa..70b09ef 100644
--- a/net/ipv4/tcp_ipv4.c
+++ b/net/ipv4/tcp_ipv4.c
@@ -369,11 +369,10 @@
 	 * We do take care of PMTU discovery (RFC1191) special case :
 	 * we can receive locally generated ICMP messages while socket is held.
 	 */
-	if (sock_owned_by_user(sk) &&
-	    type != ICMP_DEST_UNREACH &&
-	    code != ICMP_FRAG_NEEDED)
-		NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
-
+	if (sock_owned_by_user(sk)) {
+		if (!(type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED))
+			NET_INC_STATS_BH(net, LINUX_MIB_LOCKDROPPEDICMPS);
+	}
 	if (sk->sk_state == TCP_CLOSE)
 		goto out;
 
diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
index 79c8dbe..1f4d405 100644
--- a/net/ipv4/udp.c
+++ b/net/ipv4/udp.c
@@ -1952,6 +1952,7 @@
 	.recvmsg	   = udp_recvmsg,
 	.sendpage	   = udp_sendpage,
 	.backlog_rcv	   = __udp_queue_rcv_skb,
+	.release_cb	   = ip4_datagram_release_cb,
 	.hash		   = udp_lib_hash,
 	.unhash		   = udp_lib_unhash,
 	.rehash		   = udp_v4_rehash,
diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c
index 408cac4a..420e563 100644
--- a/net/ipv6/addrconf.c
+++ b/net/ipv6/addrconf.c
@@ -154,6 +154,11 @@
 				 unsigned long event);
 static int addrconf_ifdown(struct net_device *dev, int how);
 
+static struct rt6_info *addrconf_get_prefix_route(const struct in6_addr *pfx,
+						  int plen,
+						  const struct net_device *dev,
+						  u32 flags, u32 noflags);
+
 static void addrconf_dad_start(struct inet6_ifaddr *ifp);
 static void addrconf_dad_timer(unsigned long data);
 static void addrconf_dad_completed(struct inet6_ifaddr *ifp);
@@ -250,12 +255,6 @@
 	return !qdisc_tx_is_noop(dev);
 }
 
-/* Check if a route is valid prefix route */
-static inline int addrconf_is_prefix_route(const struct rt6_info *rt)
-{
-	return (rt->rt6i_flags & (RTF_GATEWAY | RTF_DEFAULT)) == 0;
-}
-
 static void addrconf_del_timer(struct inet6_ifaddr *ifp)
 {
 	if (del_timer(&ifp->timer))
@@ -941,17 +940,15 @@
 	if ((ifp->flags & IFA_F_PERMANENT) && onlink < 1) {
 		struct in6_addr prefix;
 		struct rt6_info *rt;
-		struct net *net = dev_net(ifp->idev->dev);
-		struct flowi6 fl6 = {};
 
 		ipv6_addr_prefix(&prefix, &ifp->addr, ifp->prefix_len);
-		fl6.flowi6_oif = ifp->idev->dev->ifindex;
-		fl6.daddr = prefix;
-		rt = (struct rt6_info *)ip6_route_lookup(net, &fl6,
-							 RT6_LOOKUP_F_IFACE);
 
-		if (rt != net->ipv6.ip6_null_entry &&
-		    addrconf_is_prefix_route(rt)) {
+		rt = addrconf_get_prefix_route(&prefix,
+					       ifp->prefix_len,
+					       ifp->idev->dev,
+					       0, RTF_GATEWAY | RTF_DEFAULT);
+
+		if (rt) {
 			if (onlink == 0) {
 				ip6_del_rt(rt);
 				rt = NULL;
@@ -1877,7 +1874,7 @@
 			continue;
 		if ((rt->rt6i_flags & flags) != flags)
 			continue;
-		if ((noflags != 0) && ((rt->rt6i_flags & flags) != 0))
+		if ((rt->rt6i_flags & noflags) != 0)
 			continue;
 		dst_hold(&rt->dst);
 		break;
diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c
index ecc35b9..3842331 100644
--- a/net/ipv6/ah6.c
+++ b/net/ipv6/ah6.c
@@ -472,7 +472,10 @@
 	skb->network_header += ah_hlen;
 	memcpy(skb_network_header(skb), work_iph, hdr_len);
 	__skb_pull(skb, ah_hlen + hdr_len);
-	skb_set_transport_header(skb, -hdr_len);
+	if (x->props.mode == XFRM_MODE_TUNNEL)
+		skb_reset_transport_header(skb);
+	else
+		skb_set_transport_header(skb, -hdr_len);
 out:
 	kfree(AH_SKB_CB(skb)->tmp);
 	xfrm_input_resume(skb, err);
@@ -593,9 +596,13 @@
 
 	skb->network_header += ah_hlen;
 	memcpy(skb_network_header(skb), work_iph, hdr_len);
-	skb->transport_header = skb->network_header;
 	__skb_pull(skb, ah_hlen + hdr_len);
 
+	if (x->props.mode == XFRM_MODE_TUNNEL)
+		skb_reset_transport_header(skb);
+	else
+		skb_set_transport_header(skb, -hdr_len);
+
 	err = nexthdr;
 
 out_free:
diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c
index 282f372..40ffd72 100644
--- a/net/ipv6/esp6.c
+++ b/net/ipv6/esp6.c
@@ -300,7 +300,10 @@
 
 	pskb_trim(skb, skb->len - alen - padlen - 2);
 	__skb_pull(skb, hlen);
-	skb_set_transport_header(skb, -hdr_len);
+	if (x->props.mode == XFRM_MODE_TUNNEL)
+		skb_reset_transport_header(skb);
+	else
+		skb_set_transport_header(skb, -hdr_len);
 
 	err = nexthdr[1];
 
diff --git a/net/ipv6/icmp.c b/net/ipv6/icmp.c
index b4a9fd5..fff5bdd 100644
--- a/net/ipv6/icmp.c
+++ b/net/ipv6/icmp.c
@@ -81,10 +81,22 @@
 	return net->ipv6.icmp_sk[smp_processor_id()];
 }
 
+static void icmpv6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
+		       u8 type, u8 code, int offset, __be32 info)
+{
+	struct net *net = dev_net(skb->dev);
+
+	if (type == ICMPV6_PKT_TOOBIG)
+		ip6_update_pmtu(skb, net, info, 0, 0);
+	else if (type == NDISC_REDIRECT)
+		ip6_redirect(skb, net, 0, 0);
+}
+
 static int icmpv6_rcv(struct sk_buff *skb);
 
 static const struct inet6_protocol icmpv6_protocol = {
 	.handler	=	icmpv6_rcv,
+	.err_handler	=	icmpv6_err,
 	.flags		=	INET6_PROTO_NOPOLICY|INET6_PROTO_FINAL,
 };
 
diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c
index 5552d13..0c7c03d 100644
--- a/net/ipv6/ip6_output.c
+++ b/net/ipv6/ip6_output.c
@@ -1213,10 +1213,10 @@
 		if (dst_allfrag(rt->dst.path))
 			cork->flags |= IPCORK_ALLFRAG;
 		cork->length = 0;
-		exthdrlen = (opt ? opt->opt_flen : 0) - rt->rt6i_nfheader_len;
+		exthdrlen = (opt ? opt->opt_flen : 0);
 		length += exthdrlen;
 		transhdrlen += exthdrlen;
-		dst_exthdrlen = rt->dst.header_len;
+		dst_exthdrlen = rt->dst.header_len - rt->rt6i_nfheader_len;
 	} else {
 		rt = (struct rt6_info *)cork->dst;
 		fl6 = &inet->cork.fl.u.ip6;
diff --git a/net/ipv6/ip6mr.c b/net/ipv6/ip6mr.c
index 26dcdec..8fd154e 100644
--- a/net/ipv6/ip6mr.c
+++ b/net/ipv6/ip6mr.c
@@ -1710,6 +1710,9 @@
 			return -EINVAL;
 		if (get_user(v, (u32 __user *)optval))
 			return -EFAULT;
+		/* "pim6reg%u" should not exceed 16 bytes (IFNAMSIZ) */
+		if (v != RT_TABLE_DEFAULT && v >= 100000000)
+			return -EINVAL;
 		if (sk == mrt->mroute6_sk)
 			return -EBUSY;
 
diff --git a/net/iucv/iucv.c b/net/iucv/iucv.c
index 3ad1f9d..df08250 100644
--- a/net/iucv/iucv.c
+++ b/net/iucv/iucv.c
@@ -1806,7 +1806,7 @@
 	struct iucv_irq_data *p;
 	struct iucv_irq_list *work;
 
-	kstat_cpu(smp_processor_id()).irqs[EXTINT_IUC]++;
+	inc_irq_stat(IRQEXT_IUC);
 	p = iucv_irq_data[smp_processor_id()];
 	if (p->ippathid >= iucv_max_pathid) {
 		WARN_ON(p->ippathid >= iucv_max_pathid);
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5c61677..516fbc9 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -164,7 +164,17 @@
 			sta = sta_info_get(sdata, mac_addr);
 		else
 			sta = sta_info_get_bss(sdata, mac_addr);
-		if (!sta) {
+		/*
+		 * The ASSOC test makes sure the driver is ready to
+		 * receive the key. When wpa_supplicant has roamed
+		 * using FT, it attempts to set the key before
+		 * association has completed, this rejects that attempt
+		 * so it will set the key again after assocation.
+		 *
+		 * TODO: accept the key if we have a station entry and
+		 *       add it to the device after the station.
+		 */
+		if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) {
 			ieee80211_key_free(sdata->local, key);
 			err = -ENOENT;
 			goto out_unlock;
@@ -1009,6 +1019,8 @@
 	if (old_probe_resp)
 		kfree_rcu(old_probe_resp, rcu_head);
 
+	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+		sta_info_flush(local, vlan);
 	sta_info_flush(local, sdata);
 	ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
 
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 53f0312..80e5552 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -4,6 +4,7 @@
 
 #include <linux/nl80211.h>
 #include <linux/export.h>
+#include <linux/rtnetlink.h>
 #include <net/cfg80211.h>
 #include "ieee80211_i.h"
 #include "driver-ops.h"
@@ -197,6 +198,15 @@
 
 	ctx = container_of(conf, struct ieee80211_chanctx, conf);
 
+	if (sdata->vif.type == NL80211_IFTYPE_AP) {
+		struct ieee80211_sub_if_data *vlan;
+
+		/* for the VLAN list */
+		ASSERT_RTNL();
+		list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+			rcu_assign_pointer(vlan->vif.chanctx_conf, NULL);
+	}
+
 	ieee80211_unassign_vif_chanctx(sdata, ctx);
 	if (ctx->refcount == 0)
 		ieee80211_free_chanctx(local, ctx);
@@ -316,6 +326,15 @@
 		goto out;
 	}
 
+	if (sdata->vif.type == NL80211_IFTYPE_AP) {
+		struct ieee80211_sub_if_data *vlan;
+
+		/* for the VLAN list */
+		ASSERT_RTNL();
+		list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+			rcu_assign_pointer(vlan->vif.chanctx_conf, &ctx->conf);
+	}
+
 	ieee80211_recalc_smps_chanctx(local, ctx);
  out:
 	mutex_unlock(&local->chanctx_mtx);
@@ -331,6 +350,25 @@
 	mutex_unlock(&sdata->local->chanctx_mtx);
 }
 
+void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata)
+{
+	struct ieee80211_local *local = sdata->local;
+	struct ieee80211_sub_if_data *ap;
+	struct ieee80211_chanctx_conf *conf;
+
+	if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_AP_VLAN || !sdata->bss))
+		return;
+
+	ap = container_of(sdata->bss, struct ieee80211_sub_if_data, u.ap);
+
+	mutex_lock(&local->chanctx_mtx);
+
+	conf = rcu_dereference_protected(ap->vif.chanctx_conf,
+					 lockdep_is_held(&local->chanctx_mtx));
+	rcu_assign_pointer(sdata->vif.chanctx_conf, conf);
+	mutex_unlock(&local->chanctx_mtx);
+}
+
 void ieee80211_iter_chan_contexts_atomic(
 	struct ieee80211_hw *hw,
 	void (*iter)(struct ieee80211_hw *hw,
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 8881fc7..6b7644e 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -703,8 +703,8 @@
 	sdata_info(sdata,
 		   "No active IBSS STAs - trying to scan for other IBSS networks with same SSID (merge)\n");
 
-	ieee80211_request_internal_scan(sdata,
-			ifibss->ssid, ifibss->ssid_len, NULL);
+	ieee80211_request_ibss_scan(sdata, ifibss->ssid, ifibss->ssid_len,
+				    NULL);
 }
 
 static void ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata)
@@ -802,9 +802,8 @@
 					IEEE80211_SCAN_INTERVAL)) {
 		sdata_info(sdata, "Trigger new scan to find an IBSS to join\n");
 
-		ieee80211_request_internal_scan(sdata,
-				ifibss->ssid, ifibss->ssid_len,
-				ifibss->fixed_channel ? ifibss->channel : NULL);
+		ieee80211_request_ibss_scan(sdata, ifibss->ssid,
+					    ifibss->ssid_len, chan);
 	} else {
 		int interval = IEEE80211_SCAN_INTERVAL;
 
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 42d0d02..2ed065c 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -92,8 +92,6 @@
 
 	u32 device_ts;
 
-	u8 dtim_period;
-
 	bool wmm_used;
 	bool uapsd_supported;
 
@@ -140,7 +138,6 @@
 
 /**
  * enum ieee80211_valid_data_flags - BSS valid data flags
- * @IEEE80211_BSS_VALID_DTIM: DTIM data was gathered from non-corrupt IE
  * @IEEE80211_BSS_VALID_WMM: WMM/UAPSD data was gathered from non-corrupt IE
  * @IEEE80211_BSS_VALID_RATES: Supported rates were gathered from non-corrupt IE
  * @IEEE80211_BSS_VALID_ERP: ERP flag was gathered from non-corrupt IE
@@ -151,7 +148,6 @@
  * beacon/probe response.
  */
 enum ieee80211_bss_valid_data_flags {
-	IEEE80211_BSS_VALID_DTIM		= BIT(0),
 	IEEE80211_BSS_VALID_WMM			= BIT(1),
 	IEEE80211_BSS_VALID_RATES		= BIT(2),
 	IEEE80211_BSS_VALID_ERP			= BIT(3)
@@ -440,6 +436,7 @@
 	unsigned long timers_running; /* used for quiesce/restart */
 	bool powersave; /* powersave requested for this iface */
 	bool broken_ap; /* AP is broken -- turn off powersave */
+	u8 dtim_period;
 	enum ieee80211_smps_mode req_smps, /* requested smps mode */
 				 driver_smps_mode; /* smps mode request */
 
@@ -773,6 +770,10 @@
 		u32 mntr_flags;
 	} u;
 
+	spinlock_t cleanup_stations_lock;
+	struct list_head cleanup_stations;
+	struct work_struct cleanup_stations_wk;
+
 #ifdef CONFIG_MAC80211_DEBUGFS
 	struct {
 		struct dentry *dir;
@@ -1329,9 +1330,9 @@
 
 /* scan/BSS handling */
 void ieee80211_scan_work(struct work_struct *work);
-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
-				    const u8 *ssid, u8 ssid_len,
-				    struct ieee80211_channel *chan);
+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
+				const u8 *ssid, u8 ssid_len,
+				struct ieee80211_channel *chan);
 int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
 			   struct cfg80211_scan_request *req);
 void ieee80211_scan_cancel(struct ieee80211_local *local);
@@ -1357,10 +1358,8 @@
 void ieee80211_sched_scan_stopped_work(struct work_struct *work);
 
 /* off-channel helpers */
-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
-				    bool offchannel_ps_enable);
-void ieee80211_offchannel_return(struct ieee80211_local *local,
-				 bool offchannel_ps_disable);
+void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local);
+void ieee80211_offchannel_return(struct ieee80211_local *local);
 void ieee80211_roc_setup(struct ieee80211_local *local);
 void ieee80211_start_next_roc(struct ieee80211_local *local);
 void ieee80211_roc_purge(struct ieee80211_sub_if_data *sdata);
@@ -1628,6 +1627,7 @@
 			  const struct cfg80211_chan_def *chandef,
 			  enum ieee80211_chanctx_mode mode);
 void ieee80211_vif_release_channel(struct ieee80211_sub_if_data *sdata);
+void ieee80211_vif_vlan_copy_chanctx(struct ieee80211_sub_if_data *sdata);
 
 void ieee80211_recalc_smps_chanctx(struct ieee80211_local *local,
 				   struct ieee80211_chanctx *chanctx);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 09a80b5..8be854e 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -207,17 +207,8 @@
 
 static int ieee80211_change_mtu(struct net_device *dev, int new_mtu)
 {
-	int meshhdrlen;
-	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
-
-	meshhdrlen = (sdata->vif.type == NL80211_IFTYPE_MESH_POINT) ? 5 : 0;
-
-	/* FIX: what would be proper limits for MTU?
-	 * This interface uses 802.3 frames. */
-	if (new_mtu < 256 ||
-	    new_mtu > IEEE80211_MAX_DATA_LEN - 24 - 6 - meshhdrlen) {
+	if (new_mtu < 256 || new_mtu > IEEE80211_MAX_DATA_LEN)
 		return -EINVAL;
-	}
 
 	dev->mtu = new_mtu;
 	return 0;
@@ -586,11 +577,13 @@
 
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_AP_VLAN:
-		/* no need to tell driver, but set carrier */
-		if (rtnl_dereference(sdata->bss->beacon))
+		/* no need to tell driver, but set carrier and chanctx */
+		if (rtnl_dereference(sdata->bss->beacon)) {
+			ieee80211_vif_vlan_copy_chanctx(sdata);
 			netif_carrier_on(dev);
-		else
+		} else {
 			netif_carrier_off(dev);
+		}
 		break;
 	case NL80211_IFTYPE_MONITOR:
 		if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
@@ -839,6 +832,7 @@
 	switch (sdata->vif.type) {
 	case NL80211_IFTYPE_AP_VLAN:
 		list_del(&sdata->u.vlan.list);
+		rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
 		/* no need to tell driver */
 		break;
 	case NL80211_IFTYPE_MONITOR:
@@ -865,20 +859,11 @@
 		cancel_work_sync(&sdata->work);
 		/*
 		 * When we get here, the interface is marked down.
-		 * Call rcu_barrier() to wait both for the RX path
+		 * Call synchronize_rcu() to wait for the RX path
 		 * should it be using the interface and enqueuing
-		 * frames at this very time on another CPU, and
-		 * for the sta free call_rcu callbacks.
+		 * frames at this very time on another CPU.
 		 */
-		rcu_barrier();
-
-		/*
-		 * free_sta_rcu() enqueues a work for the actual
-		 * sta cleanup, so we need to flush it while
-		 * sdata is still valid.
-		 */
-		flush_workqueue(local->workqueue);
-
+		synchronize_rcu();
 		skb_queue_purge(&sdata->skb_queue);
 
 		/*
@@ -1498,6 +1483,15 @@
 	mutex_unlock(&local->iflist_mtx);
 }
 
+static void ieee80211_cleanup_sdata_stas_wk(struct work_struct *wk)
+{
+	struct ieee80211_sub_if_data *sdata;
+
+	sdata = container_of(wk, struct ieee80211_sub_if_data, cleanup_stations_wk);
+
+	ieee80211_cleanup_sdata_stas(sdata);
+}
+
 int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 		     struct wireless_dev **new_wdev, enum nl80211_iftype type,
 		     struct vif_params *params)
@@ -1573,6 +1567,10 @@
 
 	INIT_LIST_HEAD(&sdata->key_list);
 
+	spin_lock_init(&sdata->cleanup_stations_lock);
+	INIT_LIST_HEAD(&sdata->cleanup_stations);
+	INIT_WORK(&sdata->cleanup_stations_wk, ieee80211_cleanup_sdata_stas_wk);
+
 	for (i = 0; i < IEEE80211_NUM_BANDS; i++) {
 		struct ieee80211_supported_band *sband;
 		sband = local->hw.wiphy->bands[i];
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 1bf03f9..649ad51 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -163,7 +163,7 @@
 		return -ENOMEM;
 	sdata->u.mesh.rmc->idx_mask = RMC_BUCKETS - 1;
 	for (i = 0; i < RMC_BUCKETS; i++)
-		INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i].list);
+		INIT_LIST_HEAD(&sdata->u.mesh.rmc->bucket[i]);
 	return 0;
 }
 
@@ -177,7 +177,7 @@
 		return;
 
 	for (i = 0; i < RMC_BUCKETS; i++)
-		list_for_each_entry_safe(p, n, &rmc->bucket[i].list, list) {
+		list_for_each_entry_safe(p, n, &rmc->bucket[i], list) {
 			list_del(&p->list);
 			kmem_cache_free(rm_cache, p);
 		}
@@ -210,7 +210,7 @@
 	/* Don't care about endianness since only match matters */
 	memcpy(&seqnum, &mesh_hdr->seqnum, sizeof(mesh_hdr->seqnum));
 	idx = le32_to_cpu(mesh_hdr->seqnum) & rmc->idx_mask;
-	list_for_each_entry_safe(p, n, &rmc->bucket[idx].list, list) {
+	list_for_each_entry_safe(p, n, &rmc->bucket[idx], list) {
 		++entries;
 		if (time_after(jiffies, p->exp_time) ||
 				(entries == RMC_QUEUE_MAX_LEN)) {
@@ -229,7 +229,7 @@
 	p->seqnum = seqnum;
 	p->exp_time = jiffies + RMC_TIMEOUT;
 	memcpy(p->sa, sa, ETH_ALEN);
-	list_add(&p->list, &rmc->bucket[idx].list);
+	list_add(&p->list, &rmc->bucket[idx]);
 	return 0;
 }
 
diff --git a/net/mac80211/mesh.h b/net/mac80211/mesh.h
index 7c9215f..84c28c6 100644
--- a/net/mac80211/mesh.h
+++ b/net/mac80211/mesh.h
@@ -184,7 +184,7 @@
 };
 
 struct mesh_rmc {
-	struct rmc_entry bucket[RMC_BUCKETS];
+	struct list_head bucket[RMC_BUCKETS];
 	u32 idx_mask;
 };
 
diff --git a/net/mac80211/mesh_hwmp.c b/net/mac80211/mesh_hwmp.c
index 47aeee2..2659e42 100644
--- a/net/mac80211/mesh_hwmp.c
+++ b/net/mac80211/mesh_hwmp.c
@@ -215,6 +215,7 @@
 	skb->priority = 7;
 
 	info->control.vif = &sdata->vif;
+	info->flags |= IEEE80211_TX_INTFL_NEED_TXPROCESSING;
 	ieee80211_set_qos_hdr(sdata, skb);
 }
 
@@ -246,11 +247,13 @@
 		return -EAGAIN;
 
 	skb = dev_alloc_skb(local->tx_headroom +
+			    IEEE80211_ENCRYPT_HEADROOM +
+			    IEEE80211_ENCRYPT_TAILROOM +
 			    hdr_len +
 			    2 + 15 /* PERR IE */);
 	if (!skb)
 		return -1;
-	skb_reserve(skb, local->tx_headroom);
+	skb_reserve(skb, local->tx_headroom + IEEE80211_ENCRYPT_HEADROOM);
 	mgmt = (struct ieee80211_mgmt *) skb_put(skb, hdr_len);
 	memset(mgmt, 0, hdr_len);
 	mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index 7753a9c..a355292 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -1074,12 +1074,8 @@
 		if (beaconint_us > latency) {
 			local->ps_sdata = NULL;
 		} else {
-			struct ieee80211_bss *bss;
 			int maxslp = 1;
-			u8 dtimper;
-
-			bss = (void *)found->u.mgd.associated->priv;
-			dtimper = bss->dtim_period;
+			u8 dtimper = found->u.mgd.dtim_period;
 
 			/* If the TIM IE is invalid, pretend the value is 1 */
 			if (!dtimper)
@@ -1410,10 +1406,17 @@
 
 	ieee80211_led_assoc(local, 1);
 
-	if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD)
-		bss_conf->dtim_period = bss->dtim_period;
-	else
+	if (local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
+		/*
+		 * If the AP is buggy we may get here with no DTIM period
+		 * known, so assume it's 1 which is the only safe assumption
+		 * in that case, although if the TIM IE is broken powersave
+		 * probably just won't work at all.
+		 */
+		bss_conf->dtim_period = sdata->u.mgd.dtim_period ?: 1;
+	} else {
 		bss_conf->dtim_period = 0;
+	}
 
 	bss_conf->assoc = 1;
 
@@ -1562,6 +1565,8 @@
 
 	sdata->u.mgd.timers_running = 0;
 
+	sdata->vif.bss_conf.dtim_period = 0;
+
 	ifmgd->flags = 0;
 	ieee80211_vif_release_channel(sdata);
 }
@@ -2373,11 +2378,18 @@
 	struct ieee80211_channel *channel;
 	bool need_ps = false;
 
-	if (sdata->u.mgd.associated &&
-	    ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) {
-		bss = (void *)sdata->u.mgd.associated->priv;
+	if ((sdata->u.mgd.associated &&
+	     ether_addr_equal(mgmt->bssid, sdata->u.mgd.associated->bssid)) ||
+	    (sdata->u.mgd.assoc_data &&
+	     ether_addr_equal(mgmt->bssid,
+			      sdata->u.mgd.assoc_data->bss->bssid))) {
 		/* not previously set so we may need to recalc */
-		need_ps = !bss->dtim_period;
+		need_ps = sdata->u.mgd.associated && !sdata->u.mgd.dtim_period;
+
+		if (elems->tim && !elems->parse_error) {
+			struct ieee80211_tim_ie *tim_ie = elems->tim;
+			sdata->u.mgd.dtim_period = tim_ie->dtim_period;
+		}
 	}
 
 	if (elems->ds_params && elems->ds_params_len == 1)
@@ -3896,20 +3908,41 @@
 	/* kick off associate process */
 
 	ifmgd->assoc_data = assoc_data;
+	ifmgd->dtim_period = 0;
 
 	err = ieee80211_prep_connection(sdata, req->bss, true);
 	if (err)
 		goto err_clear;
 
-	if (!bss->dtim_period &&
-	    sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
-		/*
-		 * Wait up to one beacon interval ...
-		 * should this be more if we miss one?
-		 */
-		sdata_info(sdata, "waiting for beacon from %pM\n",
-			   ifmgd->bssid);
-		assoc_data->timeout = TU_TO_EXP_TIME(req->bss->beacon_interval);
+	if (sdata->local->hw.flags & IEEE80211_HW_NEED_DTIM_PERIOD) {
+		const struct cfg80211_bss_ies *beacon_ies;
+
+		rcu_read_lock();
+		beacon_ies = rcu_dereference(req->bss->beacon_ies);
+		if (!beacon_ies) {
+			/*
+			 * Wait up to one beacon interval ...
+			 * should this be more if we miss one?
+			 */
+			sdata_info(sdata, "waiting for beacon from %pM\n",
+				   ifmgd->bssid);
+			assoc_data->timeout =
+				TU_TO_EXP_TIME(req->bss->beacon_interval);
+		} else {
+			const u8 *tim_ie = cfg80211_find_ie(WLAN_EID_TIM,
+							    beacon_ies->data,
+							    beacon_ies->len);
+			if (tim_ie && tim_ie[1] >=
+					sizeof(struct ieee80211_tim_ie)) {
+				const struct ieee80211_tim_ie *tim;
+				tim = (void *)(tim_ie + 2);
+				ifmgd->dtim_period = tim->dtim_period;
+			}
+			assoc_data->have_beacon = true;
+			assoc_data->sent_assoc = false;
+			assoc_data->timeout = jiffies;
+		}
+		rcu_read_unlock();
 	} else {
 		assoc_data->have_beacon = true;
 		assoc_data->sent_assoc = false;
diff --git a/net/mac80211/offchannel.c b/net/mac80211/offchannel.c
index a5379ae..a3ad4c3 100644
--- a/net/mac80211/offchannel.c
+++ b/net/mac80211/offchannel.c
@@ -102,8 +102,7 @@
 	ieee80211_sta_reset_conn_monitor(sdata);
 }
 
-void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local,
-				    bool offchannel_ps_enable)
+void ieee80211_offchannel_stop_vifs(struct ieee80211_local *local)
 {
 	struct ieee80211_sub_if_data *sdata;
 
@@ -134,8 +133,7 @@
 
 		if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
 			netif_tx_stop_all_queues(sdata->dev);
-			if (offchannel_ps_enable &&
-			    (sdata->vif.type == NL80211_IFTYPE_STATION) &&
+			if (sdata->vif.type == NL80211_IFTYPE_STATION &&
 			    sdata->u.mgd.associated)
 				ieee80211_offchannel_ps_enable(sdata);
 		}
@@ -143,8 +141,7 @@
 	mutex_unlock(&local->iflist_mtx);
 }
 
-void ieee80211_offchannel_return(struct ieee80211_local *local,
-				 bool offchannel_ps_disable)
+void ieee80211_offchannel_return(struct ieee80211_local *local)
 {
 	struct ieee80211_sub_if_data *sdata;
 
@@ -163,11 +160,9 @@
 			continue;
 
 		/* Tell AP we're back */
-		if (offchannel_ps_disable &&
-		    sdata->vif.type == NL80211_IFTYPE_STATION) {
-			if (sdata->u.mgd.associated)
-				ieee80211_offchannel_ps_disable(sdata);
-		}
+		if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+		    sdata->u.mgd.associated)
+			ieee80211_offchannel_ps_disable(sdata);
 
 		if (sdata->vif.type != NL80211_IFTYPE_MONITOR) {
 			/*
@@ -385,7 +380,7 @@
 			local->tmp_channel = NULL;
 			ieee80211_hw_config(local, 0);
 
-			ieee80211_offchannel_return(local, true);
+			ieee80211_offchannel_return(local);
 		}
 
 		ieee80211_recalc_idle(local);
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c
index 8ed83dc..bf82e69 100644
--- a/net/mac80211/scan.c
+++ b/net/mac80211/scan.c
@@ -113,18 +113,6 @@
 			bss->valid_data |= IEEE80211_BSS_VALID_ERP;
 	}
 
-	if (elems->tim && (!elems->parse_error ||
-			   !(bss->valid_data & IEEE80211_BSS_VALID_DTIM))) {
-		struct ieee80211_tim_ie *tim_ie = elems->tim;
-		bss->dtim_period = tim_ie->dtim_period;
-		if (!elems->parse_error)
-			bss->valid_data |= IEEE80211_BSS_VALID_DTIM;
-	}
-
-	/* If the beacon had no TIM IE, or it was invalid, use 1 */
-	if (beacon && !bss->dtim_period)
-		bss->dtim_period = 1;
-
 	/* replace old supported rates if we get new values */
 	if (!elems->parse_error ||
 	    !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
@@ -304,7 +292,7 @@
 	if (!was_hw_scan) {
 		ieee80211_configure_filter(local);
 		drv_sw_scan_complete(local);
-		ieee80211_offchannel_return(local, true);
+		ieee80211_offchannel_return(local);
 	}
 
 	ieee80211_recalc_idle(local);
@@ -353,7 +341,7 @@
 	local->next_scan_state = SCAN_DECISION;
 	local->scan_channel_idx = 0;
 
-	ieee80211_offchannel_stop_vifs(local, true);
+	ieee80211_offchannel_stop_vifs(local);
 
 	ieee80211_configure_filter(local);
 
@@ -690,12 +678,8 @@
 	local->scan_channel = NULL;
 	ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
 
-	/*
-	 * Re-enable vifs and beaconing.  Leave PS
-	 * in off-channel state..will put that back
-	 * on-channel at the end of scanning.
-	 */
-	ieee80211_offchannel_return(local, false);
+	/* disable PS */
+	ieee80211_offchannel_return(local);
 
 	*next_delay = HZ / 5;
 	/* afterwards, resume scan & go to next channel */
@@ -705,8 +689,7 @@
 static void ieee80211_scan_state_resume(struct ieee80211_local *local,
 					unsigned long *next_delay)
 {
-	/* PS already is in off-channel mode */
-	ieee80211_offchannel_stop_vifs(local, false);
+	ieee80211_offchannel_stop_vifs(local);
 
 	if (local->ops->flush) {
 		drv_flush(local, false);
@@ -832,9 +815,9 @@
 	return res;
 }
 
-int ieee80211_request_internal_scan(struct ieee80211_sub_if_data *sdata,
-				    const u8 *ssid, u8 ssid_len,
-				    struct ieee80211_channel *chan)
+int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
+				const u8 *ssid, u8 ssid_len,
+				struct ieee80211_channel *chan)
 {
 	struct ieee80211_local *local = sdata->local;
 	int ret = -EBUSY;
@@ -848,22 +831,36 @@
 
 	/* fill internal scan request */
 	if (!chan) {
-		int i, nchan = 0;
+		int i, max_n;
+		int n_ch = 0;
 
 		for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
 			if (!local->hw.wiphy->bands[band])
 				continue;
-			for (i = 0;
-			     i < local->hw.wiphy->bands[band]->n_channels;
-			     i++) {
-				local->int_scan_req->channels[nchan] =
+
+			max_n = local->hw.wiphy->bands[band]->n_channels;
+			for (i = 0; i < max_n; i++) {
+				struct ieee80211_channel *tmp_ch =
 				    &local->hw.wiphy->bands[band]->channels[i];
-				nchan++;
+
+				if (tmp_ch->flags & (IEEE80211_CHAN_NO_IBSS |
+						     IEEE80211_CHAN_DISABLED))
+					continue;
+
+				local->int_scan_req->channels[n_ch] = tmp_ch;
+				n_ch++;
 			}
 		}
 
-		local->int_scan_req->n_channels = nchan;
+		if (WARN_ON_ONCE(n_ch == 0))
+			goto unlock;
+
+		local->int_scan_req->n_channels = n_ch;
 	} else {
+		if (WARN_ON_ONCE(chan->flags & (IEEE80211_CHAN_NO_IBSS |
+						IEEE80211_CHAN_DISABLED)))
+			goto unlock;
+
 		local->int_scan_req->channels[0] = chan;
 		local->int_scan_req->n_channels = 1;
 	}
diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c
index f3e5025..ca9fde1 100644
--- a/net/mac80211/sta_info.c
+++ b/net/mac80211/sta_info.c
@@ -91,9 +91,8 @@
 	return -ENOENT;
 }
 
-static void free_sta_work(struct work_struct *wk)
+static void cleanup_single_sta(struct sta_info *sta)
 {
-	struct sta_info *sta = container_of(wk, struct sta_info, free_sta_wk);
 	int ac, i;
 	struct tid_ampdu_tx *tid_tx;
 	struct ieee80211_sub_if_data *sdata = sta->sdata;
@@ -153,11 +152,35 @@
 	sta_info_free(local, sta);
 }
 
+void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata)
+{
+	struct sta_info *sta;
+
+	spin_lock_bh(&sdata->cleanup_stations_lock);
+	while (!list_empty(&sdata->cleanup_stations)) {
+		sta = list_first_entry(&sdata->cleanup_stations,
+				       struct sta_info, list);
+		list_del(&sta->list);
+		spin_unlock_bh(&sdata->cleanup_stations_lock);
+
+		cleanup_single_sta(sta);
+
+		spin_lock_bh(&sdata->cleanup_stations_lock);
+	}
+
+	spin_unlock_bh(&sdata->cleanup_stations_lock);
+}
+
 static void free_sta_rcu(struct rcu_head *h)
 {
 	struct sta_info *sta = container_of(h, struct sta_info, rcu_head);
+	struct ieee80211_sub_if_data *sdata = sta->sdata;
 
-	ieee80211_queue_work(&sta->local->hw, &sta->free_sta_wk);
+	spin_lock(&sdata->cleanup_stations_lock);
+	list_add_tail(&sta->list, &sdata->cleanup_stations);
+	spin_unlock(&sdata->cleanup_stations_lock);
+
+	ieee80211_queue_work(&sdata->local->hw, &sdata->cleanup_stations_wk);
 }
 
 /* protected by RCU */
@@ -310,7 +333,6 @@
 
 	spin_lock_init(&sta->lock);
 	INIT_WORK(&sta->drv_unblock_wk, sta_unblock);
-	INIT_WORK(&sta->free_sta_wk, free_sta_work);
 	INIT_WORK(&sta->ampdu_mlme.work, ieee80211_ba_session_work);
 	mutex_init(&sta->ampdu_mlme.mtx);
 
@@ -862,7 +884,7 @@
 
 void sta_info_stop(struct ieee80211_local *local)
 {
-	del_timer(&local->sta_cleanup);
+	del_timer_sync(&local->sta_cleanup);
 	sta_info_flush(local, NULL);
 }
 
@@ -891,6 +913,20 @@
 	}
 	mutex_unlock(&local->sta_mtx);
 
+	rcu_barrier();
+
+	if (sdata) {
+		ieee80211_cleanup_sdata_stas(sdata);
+		cancel_work_sync(&sdata->cleanup_stations_wk);
+	} else {
+		mutex_lock(&local->iflist_mtx);
+		list_for_each_entry(sdata, &local->interfaces, list) {
+			ieee80211_cleanup_sdata_stas(sdata);
+			cancel_work_sync(&sdata->cleanup_stations_wk);
+		}
+		mutex_unlock(&local->iflist_mtx);
+	}
+
 	return ret;
 }
 
diff --git a/net/mac80211/sta_info.h b/net/mac80211/sta_info.h
index 1489bca..37c1889 100644
--- a/net/mac80211/sta_info.h
+++ b/net/mac80211/sta_info.h
@@ -299,7 +299,6 @@
 	spinlock_t lock;
 
 	struct work_struct drv_unblock_wk;
-	struct work_struct free_sta_wk;
 
 	u16 listen_interval;
 
@@ -563,4 +562,6 @@
 void ieee80211_sta_ps_deliver_poll_response(struct sta_info *sta);
 void ieee80211_sta_ps_deliver_uapsd(struct sta_info *sta);
 
+void ieee80211_cleanup_sdata_stas(struct ieee80211_sub_if_data *sdata);
+
 #endif /* STA_INFO_H */
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index e9eadc4..467c1d1 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -1673,10 +1673,13 @@
 			chanctx_conf =
 				rcu_dereference(tmp_sdata->vif.chanctx_conf);
 	}
-	if (!chanctx_conf)
-		goto fail_rcu;
 
-	chan = chanctx_conf->def.chan;
+	if (chanctx_conf)
+		chan = chanctx_conf->def.chan;
+	else if (!local->use_chanctx)
+		chan = local->_oper_channel;
+	else
+		goto fail_rcu;
 
 	/*
 	 * Frame injection is not allowed if beaconing is not allowed
diff --git a/net/netfilter/nf_conntrack_core.c b/net/netfilter/nf_conntrack_core.c
index 016d95e..e4a0c4f 100644
--- a/net/netfilter/nf_conntrack_core.c
+++ b/net/netfilter/nf_conntrack_core.c
@@ -1376,11 +1376,12 @@
 	synchronize_net();
 	nf_conntrack_proto_fini(net);
 	nf_conntrack_cleanup_net(net);
+}
 
-	if (net_eq(net, &init_net)) {
-		RCU_INIT_POINTER(nf_ct_destroy, NULL);
-		nf_conntrack_cleanup_init_net();
-	}
+void nf_conntrack_cleanup_end(void)
+{
+	RCU_INIT_POINTER(nf_ct_destroy, NULL);
+	nf_conntrack_cleanup_init_net();
 }
 
 void *nf_ct_alloc_hashtable(unsigned int *sizep, int nulls)
diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c
index 363285d..e7185c68 100644
--- a/net/netfilter/nf_conntrack_standalone.c
+++ b/net/netfilter/nf_conntrack_standalone.c
@@ -575,6 +575,7 @@
 static void __exit nf_conntrack_standalone_fini(void)
 {
 	unregister_pernet_subsys(&nf_conntrack_net_ops);
+	nf_conntrack_cleanup_end();
 }
 
 module_init(nf_conntrack_standalone_init);
diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c
index 8d987c3..7b3a9e5 100644
--- a/net/netfilter/x_tables.c
+++ b/net/netfilter/x_tables.c
@@ -345,19 +345,27 @@
 }
 EXPORT_SYMBOL_GPL(xt_find_revision);
 
-static char *textify_hooks(char *buf, size_t size, unsigned int mask)
+static char *
+textify_hooks(char *buf, size_t size, unsigned int mask, uint8_t nfproto)
 {
-	static const char *const names[] = {
+	static const char *const inetbr_names[] = {
 		"PREROUTING", "INPUT", "FORWARD",
 		"OUTPUT", "POSTROUTING", "BROUTING",
 	};
-	unsigned int i;
+	static const char *const arp_names[] = {
+		"INPUT", "FORWARD", "OUTPUT",
+	};
+	const char *const *names;
+	unsigned int i, max;
 	char *p = buf;
 	bool np = false;
 	int res;
 
+	names = (nfproto == NFPROTO_ARP) ? arp_names : inetbr_names;
+	max   = (nfproto == NFPROTO_ARP) ? ARRAY_SIZE(arp_names) :
+	                                   ARRAY_SIZE(inetbr_names);
 	*p = '\0';
-	for (i = 0; i < ARRAY_SIZE(names); ++i) {
+	for (i = 0; i < max; ++i) {
 		if (!(mask & (1 << i)))
 			continue;
 		res = snprintf(p, size, "%s%s", np ? "/" : "", names[i]);
@@ -402,8 +410,10 @@
 		pr_err("%s_tables: %s match: used from hooks %s, but only "
 		       "valid from %s\n",
 		       xt_prefix[par->family], par->match->name,
-		       textify_hooks(used, sizeof(used), par->hook_mask),
-		       textify_hooks(allow, sizeof(allow), par->match->hooks));
+		       textify_hooks(used, sizeof(used), par->hook_mask,
+		                     par->family),
+		       textify_hooks(allow, sizeof(allow), par->match->hooks,
+		                     par->family));
 		return -EINVAL;
 	}
 	if (par->match->proto && (par->match->proto != proto || inv_proto)) {
@@ -575,8 +585,10 @@
 		pr_err("%s_tables: %s target: used from hooks %s, but only "
 		       "usable from %s\n",
 		       xt_prefix[par->family], par->target->name,
-		       textify_hooks(used, sizeof(used), par->hook_mask),
-		       textify_hooks(allow, sizeof(allow), par->target->hooks));
+		       textify_hooks(used, sizeof(used), par->hook_mask,
+		                     par->family),
+		       textify_hooks(allow, sizeof(allow), par->target->hooks,
+		                     par->family));
 		return -EINVAL;
 	}
 	if (par->target->proto && (par->target->proto != proto || inv_proto)) {
diff --git a/net/netfilter/xt_CT.c b/net/netfilter/xt_CT.c
index 2a08430..bde009e 100644
--- a/net/netfilter/xt_CT.c
+++ b/net/netfilter/xt_CT.c
@@ -109,7 +109,7 @@
 	struct xt_ct_target_info *info = par->targinfo;
 	struct nf_conntrack_tuple t;
 	struct nf_conn *ct;
-	int ret;
+	int ret = -EOPNOTSUPP;
 
 	if (info->flags & ~XT_CT_NOTRACK)
 		return -EINVAL;
@@ -247,7 +247,7 @@
 	struct xt_ct_target_info_v1 *info = par->targinfo;
 	struct nf_conntrack_tuple t;
 	struct nf_conn *ct;
-	int ret;
+	int ret = -EOPNOTSUPP;
 
 	if (info->flags & ~XT_CT_NOTRACK)
 		return -EINVAL;
diff --git a/net/sctp/outqueue.c b/net/sctp/outqueue.c
index 379c81d..9bcdbd0 100644
--- a/net/sctp/outqueue.c
+++ b/net/sctp/outqueue.c
@@ -224,7 +224,7 @@
 
 /* Free the outqueue structure and any related pending chunks.
  */
-void sctp_outq_teardown(struct sctp_outq *q)
+static void __sctp_outq_teardown(struct sctp_outq *q)
 {
 	struct sctp_transport *transport;
 	struct list_head *lchunk, *temp;
@@ -277,8 +277,6 @@
 		sctp_chunk_free(chunk);
 	}
 
-	q->error = 0;
-
 	/* Throw away any leftover control chunks. */
 	list_for_each_entry_safe(chunk, tmp, &q->control_chunk_list, list) {
 		list_del_init(&chunk->list);
@@ -286,11 +284,17 @@
 	}
 }
 
+void sctp_outq_teardown(struct sctp_outq *q)
+{
+	__sctp_outq_teardown(q);
+	sctp_outq_init(q->asoc, q);
+}
+
 /* Free the outqueue structure and any related pending chunks.  */
 void sctp_outq_free(struct sctp_outq *q)
 {
 	/* Throw away leftover chunks. */
-	sctp_outq_teardown(q);
+	__sctp_outq_teardown(q);
 
 	/* If we were kmalloc()'d, free the memory.  */
 	if (q->malloced)
diff --git a/net/sctp/sm_statefuns.c b/net/sctp/sm_statefuns.c
index 618ec7e..5131fcf 100644
--- a/net/sctp/sm_statefuns.c
+++ b/net/sctp/sm_statefuns.c
@@ -1779,8 +1779,10 @@
 
 	/* Update the content of current association. */
 	sctp_add_cmd_sf(commands, SCTP_CMD_UPDATE_ASSOC, SCTP_ASOC(new_asoc));
-	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
 	sctp_add_cmd_sf(commands, SCTP_CMD_EVENT_ULP, SCTP_ULPEVENT(ev));
+	sctp_add_cmd_sf(commands, SCTP_CMD_NEW_STATE,
+			SCTP_STATE(SCTP_STATE_ESTABLISHED));
+	sctp_add_cmd_sf(commands, SCTP_CMD_REPLY, SCTP_CHUNK(repl));
 	return SCTP_DISPOSITION_CONSUME;
 
 nomem_ev:
diff --git a/net/sctp/sysctl.c b/net/sctp/sysctl.c
index 043889a..bf3c6e8 100644
--- a/net/sctp/sysctl.c
+++ b/net/sctp/sysctl.c
@@ -366,7 +366,11 @@
 
 void sctp_sysctl_net_unregister(struct net *net)
 {
+	struct ctl_table *table;
+
+	table = net->sctp.sysctl_header->ctl_table_arg;
 	unregister_net_sysctl_table(net->sctp.sysctl_header);
+	kfree(table);
 }
 
 static struct ctl_table_header * sctp_sysctl_header;
diff --git a/net/sunrpc/clnt.c b/net/sunrpc/clnt.c
index 1915ffe..507b5e8 100644
--- a/net/sunrpc/clnt.c
+++ b/net/sunrpc/clnt.c
@@ -555,7 +555,7 @@
  * rpc_clone_client_set_auth - Clone an RPC client structure and set its auth
  *
  * @clnt: RPC client whose parameters are copied
- * @auth: security flavor for new client
+ * @flavor: security flavor for new client
  *
  * Returns a fresh RPC client or an ERR_PTR.
  */
diff --git a/net/sunrpc/sched.c b/net/sunrpc/sched.c
index b4133bd..fb20f25 100644
--- a/net/sunrpc/sched.c
+++ b/net/sunrpc/sched.c
@@ -98,9 +98,25 @@
 	list_add(&task->u.tk_wait.timer_list, &queue->timer_list.list);
 }
 
+static void rpc_rotate_queue_owner(struct rpc_wait_queue *queue)
+{
+	struct list_head *q = &queue->tasks[queue->priority];
+	struct rpc_task *task;
+
+	if (!list_empty(q)) {
+		task = list_first_entry(q, struct rpc_task, u.tk_wait.list);
+		if (task->tk_owner == queue->owner)
+			list_move_tail(&task->u.tk_wait.list, q);
+	}
+}
+
 static void rpc_set_waitqueue_priority(struct rpc_wait_queue *queue, int priority)
 {
-	queue->priority = priority;
+	if (queue->priority != priority) {
+		/* Fairness: rotate the list when changing priority */
+		rpc_rotate_queue_owner(queue);
+		queue->priority = priority;
+	}
 }
 
 static void rpc_set_waitqueue_owner(struct rpc_wait_queue *queue, pid_t pid)
@@ -972,8 +988,7 @@
 
 static void rpc_release_resources_task(struct rpc_task *task)
 {
-	if (task->tk_rqstp)
-		xprt_release(task);
+	xprt_release(task);
 	if (task->tk_msg.rpc_cred) {
 		put_rpccred(task->tk_msg.rpc_cred);
 		task->tk_msg.rpc_cred = NULL;
diff --git a/net/sunrpc/xprt.c b/net/sunrpc/xprt.c
index bd462a5..33811db 100644
--- a/net/sunrpc/xprt.c
+++ b/net/sunrpc/xprt.c
@@ -1136,10 +1136,18 @@
 void xprt_release(struct rpc_task *task)
 {
 	struct rpc_xprt	*xprt;
-	struct rpc_rqst	*req;
+	struct rpc_rqst	*req = task->tk_rqstp;
 
-	if (!(req = task->tk_rqstp))
+	if (req == NULL) {
+		if (task->tk_client) {
+			rcu_read_lock();
+			xprt = rcu_dereference(task->tk_client->cl_xprt);
+			if (xprt->snd_task == task)
+				xprt_release_write(xprt, task);
+			rcu_read_unlock();
+		}
 		return;
+	}
 
 	xprt = req->rq_xprt;
 	if (task->tk_ops->rpc_count_stats != NULL)
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 14d9904..b677eab 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -866,8 +866,7 @@
 		/* allow mac80211 to determine the timeout */
 		wdev->ps_timeout = -1;
 
-		if (!dev->ethtool_ops)
-			dev->ethtool_ops = &cfg80211_ethtool_ops;
+		netdev_set_default_ethtool_ops(dev, &cfg80211_ethtool_ops);
 
 		if ((wdev->iftype == NL80211_IFTYPE_STATION ||
 		     wdev->iftype == NL80211_IFTYPE_P2P_CLIENT ||
diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c
index 41eabc4..07c5857 100644
--- a/net/xfrm/xfrm_policy.c
+++ b/net/xfrm/xfrm_policy.c
@@ -2656,7 +2656,7 @@
 		WARN_ON(!hlist_empty(&net->xfrm.policy_inexact[dir]));
 
 		htab = &net->xfrm.policy_bydst[dir];
-		sz = (htab->hmask + 1);
+		sz = (htab->hmask + 1) * sizeof(struct hlist_head);
 		WARN_ON(!hlist_empty(htab->table));
 		xfrm_hash_free(htab->table, sz);
 	}
diff --git a/net/xfrm/xfrm_replay.c b/net/xfrm/xfrm_replay.c
index 765f6fe..35754cc 100644
--- a/net/xfrm/xfrm_replay.c
+++ b/net/xfrm/xfrm_replay.c
@@ -242,11 +242,13 @@
 	u32 diff;
 	struct xfrm_replay_state_esn *replay_esn = x->replay_esn;
 	u32 seq = ntohl(net_seq);
-	u32 pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+	u32 pos;
 
 	if (!replay_esn->replay_window)
 		return;
 
+	pos = (replay_esn->seq - 1) % replay_esn->replay_window;
+
 	if (seq > replay_esn->seq) {
 		diff = seq - replay_esn->seq;
 
diff --git a/security/capability.c b/security/capability.c
index 0fe5a02..5797750 100644
--- a/security/capability.c
+++ b/security/capability.c
@@ -709,16 +709,31 @@
 {
 }
 
+static int cap_tun_dev_alloc_security(void **security)
+{
+	return 0;
+}
+
+static void cap_tun_dev_free_security(void *security)
+{
+}
+
 static int cap_tun_dev_create(void)
 {
 	return 0;
 }
 
-static void cap_tun_dev_post_create(struct sock *sk)
+static int cap_tun_dev_attach_queue(void *security)
 {
+	return 0;
 }
 
-static int cap_tun_dev_attach(struct sock *sk)
+static int cap_tun_dev_attach(struct sock *sk, void *security)
+{
+	return 0;
+}
+
+static int cap_tun_dev_open(void *security)
 {
 	return 0;
 }
@@ -1050,8 +1065,11 @@
 	set_to_cap_if_null(ops, secmark_refcount_inc);
 	set_to_cap_if_null(ops, secmark_refcount_dec);
 	set_to_cap_if_null(ops, req_classify_flow);
+	set_to_cap_if_null(ops, tun_dev_alloc_security);
+	set_to_cap_if_null(ops, tun_dev_free_security);
 	set_to_cap_if_null(ops, tun_dev_create);
-	set_to_cap_if_null(ops, tun_dev_post_create);
+	set_to_cap_if_null(ops, tun_dev_open);
+	set_to_cap_if_null(ops, tun_dev_attach_queue);
 	set_to_cap_if_null(ops, tun_dev_attach);
 #endif	/* CONFIG_SECURITY_NETWORK */
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/device_cgroup.c b/security/device_cgroup.c
index 19ecc8d..d794abc 100644
--- a/security/device_cgroup.c
+++ b/security/device_cgroup.c
@@ -215,7 +215,9 @@
 	struct dev_cgroup *dev_cgroup;
 
 	dev_cgroup = cgroup_to_devcgroup(cgroup);
+	mutex_lock(&devcgroup_mutex);
 	dev_exception_clean(dev_cgroup);
+	mutex_unlock(&devcgroup_mutex);
 	kfree(dev_cgroup);
 }
 
diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c
index dfb2691..7dd538e 100644
--- a/security/integrity/evm/evm_crypto.c
+++ b/security/integrity/evm/evm_crypto.c
@@ -205,9 +205,9 @@
 		rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_EVM,
 					   &xattr_data,
 					   sizeof(xattr_data), 0);
-	}
-	else if (rc == -ENODATA)
+	} else if (rc == -ENODATA && inode->i_op->removexattr) {
 		rc = inode->i_op->removexattr(dentry, XATTR_NAME_EVM);
+	}
 	return rc;
 }
 
diff --git a/security/security.c b/security/security.c
index daa97f4..7b88c6a 100644
--- a/security/security.c
+++ b/security/security.c
@@ -1254,24 +1254,42 @@
 }
 EXPORT_SYMBOL(security_secmark_refcount_dec);
 
+int security_tun_dev_alloc_security(void **security)
+{
+	return security_ops->tun_dev_alloc_security(security);
+}
+EXPORT_SYMBOL(security_tun_dev_alloc_security);
+
+void security_tun_dev_free_security(void *security)
+{
+	security_ops->tun_dev_free_security(security);
+}
+EXPORT_SYMBOL(security_tun_dev_free_security);
+
 int security_tun_dev_create(void)
 {
 	return security_ops->tun_dev_create();
 }
 EXPORT_SYMBOL(security_tun_dev_create);
 
-void security_tun_dev_post_create(struct sock *sk)
+int security_tun_dev_attach_queue(void *security)
 {
-	return security_ops->tun_dev_post_create(sk);
+	return security_ops->tun_dev_attach_queue(security);
 }
-EXPORT_SYMBOL(security_tun_dev_post_create);
+EXPORT_SYMBOL(security_tun_dev_attach_queue);
 
-int security_tun_dev_attach(struct sock *sk)
+int security_tun_dev_attach(struct sock *sk, void *security)
 {
-	return security_ops->tun_dev_attach(sk);
+	return security_ops->tun_dev_attach(sk, security);
 }
 EXPORT_SYMBOL(security_tun_dev_attach);
 
+int security_tun_dev_open(void *security)
+{
+	return security_ops->tun_dev_open(security);
+}
+EXPORT_SYMBOL(security_tun_dev_open);
+
 #endif	/* CONFIG_SECURITY_NETWORK */
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 61a5336..ef26e96 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -4399,6 +4399,24 @@
 	fl->flowi_secid = req->secid;
 }
 
+static int selinux_tun_dev_alloc_security(void **security)
+{
+	struct tun_security_struct *tunsec;
+
+	tunsec = kzalloc(sizeof(*tunsec), GFP_KERNEL);
+	if (!tunsec)
+		return -ENOMEM;
+	tunsec->sid = current_sid();
+
+	*security = tunsec;
+	return 0;
+}
+
+static void selinux_tun_dev_free_security(void *security)
+{
+	kfree(security);
+}
+
 static int selinux_tun_dev_create(void)
 {
 	u32 sid = current_sid();
@@ -4414,8 +4432,17 @@
 			    NULL);
 }
 
-static void selinux_tun_dev_post_create(struct sock *sk)
+static int selinux_tun_dev_attach_queue(void *security)
 {
+	struct tun_security_struct *tunsec = security;
+
+	return avc_has_perm(current_sid(), tunsec->sid, SECCLASS_TUN_SOCKET,
+			    TUN_SOCKET__ATTACH_QUEUE, NULL);
+}
+
+static int selinux_tun_dev_attach(struct sock *sk, void *security)
+{
+	struct tun_security_struct *tunsec = security;
 	struct sk_security_struct *sksec = sk->sk_security;
 
 	/* we don't currently perform any NetLabel based labeling here and it
@@ -4425,20 +4452,19 @@
 	 * cause confusion to the TUN user that had no idea network labeling
 	 * protocols were being used */
 
-	/* see the comments in selinux_tun_dev_create() about why we don't use
-	 * the sockcreate SID here */
-
-	sksec->sid = current_sid();
+	sksec->sid = tunsec->sid;
 	sksec->sclass = SECCLASS_TUN_SOCKET;
+
+	return 0;
 }
 
-static int selinux_tun_dev_attach(struct sock *sk)
+static int selinux_tun_dev_open(void *security)
 {
-	struct sk_security_struct *sksec = sk->sk_security;
+	struct tun_security_struct *tunsec = security;
 	u32 sid = current_sid();
 	int err;
 
-	err = avc_has_perm(sid, sksec->sid, SECCLASS_TUN_SOCKET,
+	err = avc_has_perm(sid, tunsec->sid, SECCLASS_TUN_SOCKET,
 			   TUN_SOCKET__RELABELFROM, NULL);
 	if (err)
 		return err;
@@ -4446,8 +4472,7 @@
 			   TUN_SOCKET__RELABELTO, NULL);
 	if (err)
 		return err;
-
-	sksec->sid = sid;
+	tunsec->sid = sid;
 
 	return 0;
 }
@@ -5642,9 +5667,12 @@
 	.secmark_refcount_inc =		selinux_secmark_refcount_inc,
 	.secmark_refcount_dec =		selinux_secmark_refcount_dec,
 	.req_classify_flow =		selinux_req_classify_flow,
+	.tun_dev_alloc_security =	selinux_tun_dev_alloc_security,
+	.tun_dev_free_security =	selinux_tun_dev_free_security,
 	.tun_dev_create =		selinux_tun_dev_create,
-	.tun_dev_post_create = 		selinux_tun_dev_post_create,
+	.tun_dev_attach_queue =		selinux_tun_dev_attach_queue,
 	.tun_dev_attach =		selinux_tun_dev_attach,
+	.tun_dev_open =			selinux_tun_dev_open,
 
 #ifdef CONFIG_SECURITY_NETWORK_XFRM
 	.xfrm_policy_alloc_security =	selinux_xfrm_policy_alloc,
diff --git a/security/selinux/include/classmap.h b/security/selinux/include/classmap.h
index df2de54..14d04e6 100644
--- a/security/selinux/include/classmap.h
+++ b/security/selinux/include/classmap.h
@@ -150,6 +150,6 @@
 	    NULL } },
 	{ "kernel_service", { "use_as_override", "create_files_as", NULL } },
 	{ "tun_socket",
-	  { COMMON_SOCK_PERMS, NULL } },
+	  { COMMON_SOCK_PERMS, "attach_queue", NULL } },
 	{ NULL }
   };
diff --git a/security/selinux/include/objsec.h b/security/selinux/include/objsec.h
index 26c7eee..aa47bca 100644
--- a/security/selinux/include/objsec.h
+++ b/security/selinux/include/objsec.h
@@ -110,6 +110,10 @@
 	u16 sclass;			/* sock security class */
 };
 
+struct tun_security_struct {
+	u32 sid;			/* SID for the tun device sockets */
+};
+
 struct key_security_struct {
 	u32 sid;	/* SID of key */
 };
diff --git a/sound/arm/pxa2xx-ac97-lib.c b/sound/arm/pxa2xx-ac97-lib.c
index 6fc0ae9..fff7753 100644
--- a/sound/arm/pxa2xx-ac97-lib.c
+++ b/sound/arm/pxa2xx-ac97-lib.c
@@ -18,6 +18,7 @@
 #include <linux/delay.h>
 #include <linux/module.h>
 #include <linux/io.h>
+#include <linux/gpio.h>
 
 #include <sound/ac97_codec.h>
 #include <sound/pxa2xx-lib.h>
@@ -148,6 +149,8 @@
 
 static inline void pxa_ac97_cold_pxa27x(void)
 {
+	unsigned int timeout;
+
 	GCR &=  GCR_COLD_RST;  /* clear everything but nCRST */
 	GCR &= ~GCR_COLD_RST;  /* then assert nCRST */
 
@@ -157,8 +160,10 @@
 	clk_enable(ac97conf_clk);
 	udelay(5);
 	clk_disable(ac97conf_clk);
-	GCR = GCR_COLD_RST;
-	udelay(50);
+	GCR = GCR_COLD_RST | GCR_WARM_RST;
+	timeout = 100;     /* wait for the codec-ready bit to be set */
+	while (!((GSR | gsr_bits) & (GSR_PCR | GSR_SCR)) && timeout--)
+		mdelay(1);
 }
 #endif
 
@@ -340,8 +345,21 @@
 	}
 
 	if (cpu_is_pxa27x()) {
-		/* Use GPIO 113 as AC97 Reset on Bulverde */
+		/*
+		 * This gpio is needed for a work-around to a bug in the ac97
+		 * controller during warm reset.  The direction and level is set
+		 * here so that it is an output driven high when switching from
+		 * AC97_nRESET alt function to generic gpio.
+		 */
+		ret = gpio_request_one(reset_gpio, GPIOF_OUT_INIT_HIGH,
+				       "pxa27x ac97 reset");
+		if (ret < 0) {
+			pr_err("%s: gpio_request_one() failed: %d\n",
+			       __func__, ret);
+			goto err_conf;
+		}
 		pxa27x_assert_ac97reset(reset_gpio, 0);
+
 		ac97conf_clk = clk_get(&dev->dev, "AC97CONFCLK");
 		if (IS_ERR(ac97conf_clk)) {
 			ret = PTR_ERR(ac97conf_clk);
@@ -384,6 +402,8 @@
 
 void pxa2xx_ac97_hw_remove(struct platform_device *dev)
 {
+	if (cpu_is_pxa27x())
+		gpio_free(reset_gpio);
 	GCR |= GCR_ACLINK_OFF;
 	free_irq(IRQ_AC97, NULL);
 	if (ac97conf_clk) {
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index b8fb0a5..822df97 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -3654,6 +3654,7 @@
 	hda_set_power_state(codec, AC_PWRST_D0);
 	restore_shutup_pins(codec);
 	hda_exec_init_verbs(codec);
+	snd_hda_jack_set_dirty_all(codec);
 	if (codec->patch_ops.resume)
 		codec->patch_ops.resume(codec);
 	else {
@@ -3665,10 +3666,8 @@
 
 	if (codec->jackpoll_interval)
 		hda_jackpoll_work(&codec->jackpoll_work.work);
-	else {
-		snd_hda_jack_set_dirty_all(codec);
+	else
 		snd_hda_jack_report_sync(codec);
-	}
 
 	codec->in_pm = 0;
 	snd_hda_power_down(codec); /* flag down before returning */
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index cca8727..c78286f 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -573,9 +573,12 @@
 #define AZX_DCAPS_PM_RUNTIME	(1 << 26)	/* runtime PM support */
 
 /* quirks for Intel PCH */
-#define AZX_DCAPS_INTEL_PCH \
+#define AZX_DCAPS_INTEL_PCH_NOPM \
 	(AZX_DCAPS_SCH_SNOOP | AZX_DCAPS_BUFSIZE | \
-	 AZX_DCAPS_COUNT_LPIB_DELAY | AZX_DCAPS_PM_RUNTIME)
+	 AZX_DCAPS_COUNT_LPIB_DELAY)
+
+#define AZX_DCAPS_INTEL_PCH \
+	(AZX_DCAPS_INTEL_PCH_NOPM | AZX_DCAPS_PM_RUNTIME)
 
 /* quirks for ATI SB / AMD Hudson */
 #define AZX_DCAPS_PRESET_ATI_SB \
@@ -653,29 +656,43 @@
 #define get_azx_dev(substream) (substream->runtime->private_data)
 
 #ifdef CONFIG_X86
-static void __mark_pages_wc(struct azx *chip, void *addr, size_t size, bool on)
+static void __mark_pages_wc(struct azx *chip, struct snd_dma_buffer *dmab, bool on)
 {
+	int pages;
+
 	if (azx_snoop(chip))
 		return;
-	if (addr && size) {
-		int pages = (size + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	if (!dmab || !dmab->area || !dmab->bytes)
+		return;
+
+#ifdef CONFIG_SND_DMA_SGBUF
+	if (dmab->dev.type == SNDRV_DMA_TYPE_DEV_SG) {
+		struct snd_sg_buf *sgbuf = dmab->private_data;
 		if (on)
-			set_memory_wc((unsigned long)addr, pages);
+			set_pages_array_wc(sgbuf->page_table, sgbuf->pages);
 		else
-			set_memory_wb((unsigned long)addr, pages);
+			set_pages_array_wb(sgbuf->page_table, sgbuf->pages);
+		return;
 	}
+#endif
+
+	pages = (dmab->bytes + PAGE_SIZE - 1) >> PAGE_SHIFT;
+	if (on)
+		set_memory_wc((unsigned long)dmab->area, pages);
+	else
+		set_memory_wb((unsigned long)dmab->area, pages);
 }
 
 static inline void mark_pages_wc(struct azx *chip, struct snd_dma_buffer *buf,
 				 bool on)
 {
-	__mark_pages_wc(chip, buf->area, buf->bytes, on);
+	__mark_pages_wc(chip, buf, on);
 }
 static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
-				   struct snd_pcm_runtime *runtime, bool on)
+				   struct snd_pcm_substream *substream, bool on)
 {
 	if (azx_dev->wc_marked != on) {
-		__mark_pages_wc(chip, runtime->dma_area, runtime->dma_bytes, on);
+		__mark_pages_wc(chip, snd_pcm_get_dma_buf(substream), on);
 		azx_dev->wc_marked = on;
 	}
 }
@@ -686,7 +703,7 @@
 {
 }
 static inline void mark_runtime_wc(struct azx *chip, struct azx_dev *azx_dev,
-				   struct snd_pcm_runtime *runtime, bool on)
+				   struct snd_pcm_substream *substream, bool on)
 {
 }
 #endif
@@ -1965,11 +1982,10 @@
 {
 	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
 	struct azx *chip = apcm->chip;
-	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct azx_dev *azx_dev = get_azx_dev(substream);
 	int ret;
 
-	mark_runtime_wc(chip, azx_dev, runtime, false);
+	mark_runtime_wc(chip, azx_dev, substream, false);
 	azx_dev->bufsize = 0;
 	azx_dev->period_bytes = 0;
 	azx_dev->format_val = 0;
@@ -1977,7 +1993,7 @@
 					params_buffer_bytes(hw_params));
 	if (ret < 0)
 		return ret;
-	mark_runtime_wc(chip, azx_dev, runtime, true);
+	mark_runtime_wc(chip, azx_dev, substream, true);
 	return ret;
 }
 
@@ -1986,7 +2002,6 @@
 	struct azx_pcm *apcm = snd_pcm_substream_chip(substream);
 	struct azx_dev *azx_dev = get_azx_dev(substream);
 	struct azx *chip = apcm->chip;
-	struct snd_pcm_runtime *runtime = substream->runtime;
 	struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream];
 
 	/* reset BDL address */
@@ -1999,7 +2014,7 @@
 
 	snd_hda_codec_cleanup(apcm->codec, hinfo, substream);
 
-	mark_runtime_wc(chip, azx_dev, runtime, false);
+	mark_runtime_wc(chip, azx_dev, substream, false);
 	return snd_pcm_lib_free_pages(substream);
 }
 
@@ -3586,13 +3601,13 @@
 static DEFINE_PCI_DEVICE_TABLE(azx_ids) = {
 	/* CPT */
 	{ PCI_DEVICE(0x8086, 0x1c20),
-	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
 	/* PBG */
 	{ PCI_DEVICE(0x8086, 0x1d20),
-	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
 	/* Panther Point */
 	{ PCI_DEVICE(0x8086, 0x1e20),
-	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
+	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH_NOPM },
 	/* Lynx Point */
 	{ PCI_DEVICE(0x8086, 0x8c20),
 	  .driver_data = AZX_DRIVER_PCH | AZX_DCAPS_INTEL_PCH },
@@ -3610,13 +3625,12 @@
 	/* 5 Series/3400 */
 	{ PCI_DEVICE(0x8086, 0x3b56),
 	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH },
-	/* SCH */
+	/* Poulsbo */
 	{ PCI_DEVICE(0x8086, 0x811b),
-	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Poulsbo */
+	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
+	/* Oaktrail */
 	{ PCI_DEVICE(0x8086, 0x080a),
-	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_SCH_SNOOP |
-	  AZX_DCAPS_BUFSIZE | AZX_DCAPS_POSFIX_LPIB }, /* Oaktrail */
+	  .driver_data = AZX_DRIVER_SCH | AZX_DCAPS_INTEL_PCH_NOPM },
 	/* ICH */
 	{ PCI_DEVICE(0x8086, 0x2668),
 	  .driver_data = AZX_DRIVER_ICH | AZX_DCAPS_OLD_SSYNC |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c
index 60890bf..009b77a 100644
--- a/sound/pci/hda/patch_conexant.c
+++ b/sound/pci/hda/patch_conexant.c
@@ -558,24 +558,12 @@
 	return 0;
 }
 
-#ifdef CONFIG_PM
-static int conexant_suspend(struct hda_codec *codec)
-{
-	snd_hda_shutup_pins(codec);
-	return 0;
-}
-#endif
-
 static const struct hda_codec_ops conexant_patch_ops = {
 	.build_controls = conexant_build_controls,
 	.build_pcms = conexant_build_pcms,
 	.init = conexant_init,
 	.free = conexant_free,
 	.set_power_state = conexant_set_power,
-#ifdef CONFIG_PM
-	.suspend = conexant_suspend,
-#endif
-	.reboot_notify = snd_hda_shutup_pins,
 };
 
 #ifdef CONFIG_SND_HDA_INPUT_BEEP
@@ -4405,10 +4393,6 @@
 	.init = cx_auto_init,
 	.free = conexant_free,
 	.unsol_event = snd_hda_jack_unsol_event,
-#ifdef CONFIG_PM
-	.suspend = conexant_suspend,
-#endif
-	.reboot_notify = snd_hda_shutup_pins,
 };
 
 /*
@@ -4652,6 +4636,12 @@
 	  .patch = patch_conexant_auto },
 	{ .id = 0x14f15111, .name = "CX20753/4",
 	  .patch = patch_conexant_auto },
+	{ .id = 0x14f15113, .name = "CX20755",
+	  .patch = patch_conexant_auto },
+	{ .id = 0x14f15114, .name = "CX20756",
+	  .patch = patch_conexant_auto },
+	{ .id = 0x14f15115, .name = "CX20757",
+	  .patch = patch_conexant_auto },
 	{} /* terminator */
 };
 
@@ -4675,6 +4665,9 @@
 MODULE_ALIAS("snd-hda-codec-id:14f1510f");
 MODULE_ALIAS("snd-hda-codec-id:14f15110");
 MODULE_ALIAS("snd-hda-codec-id:14f15111");
+MODULE_ALIAS("snd-hda-codec-id:14f15113");
+MODULE_ALIAS("snd-hda-codec-id:14f15114");
+MODULE_ALIAS("snd-hda-codec-id:14f15115");
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Conexant HD-audio codec");
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index b6c21ea..807a2aa 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -1502,7 +1502,7 @@
 	ctl_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
 	substream = snd_pcm_chmap_substream(info, ctl_idx);
 	if (!substream || !substream->runtime)
-		return -EBADFD;
+		return 0; /* just for avoiding error from alsactl restore */
 	switch (substream->runtime->status->state) {
 	case SNDRV_PCM_STATE_OPEN:
 	case SNDRV_PCM_STATE_SETUP:
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 71ae23d..5faaad2 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -4694,6 +4694,7 @@
 	SND_PCI_QUIRK(0x1584, 0x9077, "Uniwill P53", ALC880_FIXUP_VOL_KNOB),
 	SND_PCI_QUIRK(0x161f, 0x203d, "W810", ALC880_FIXUP_W810),
 	SND_PCI_QUIRK(0x161f, 0x205d, "Medion Rim 2150", ALC880_FIXUP_MEDION_RIM),
+	SND_PCI_QUIRK(0x1631, 0xe011, "PB 13201056", ALC880_FIXUP_6ST),
 	SND_PCI_QUIRK(0x1734, 0x107c, "FSC F1734", ALC880_FIXUP_F1734),
 	SND_PCI_QUIRK(0x1734, 0x1094, "FSC Amilo M1451G", ALC880_FIXUP_FUJITSU),
 	SND_PCI_QUIRK(0x1734, 0x10ac, "FSC AMILO Xi 1526", ALC880_FIXUP_F1734),
@@ -5708,6 +5709,7 @@
 };
 
 static const struct snd_pci_quirk alc268_fixup_tbl[] = {
+	SND_PCI_QUIRK(0x1025, 0x015b, "Acer AOA 150 (ZG5)", ALC268_FIXUP_INV_DMIC),
 	/* below is codec SSID since multiple Toshiba laptops have the
 	 * same PCI SSID 1179:ff00
 	 */
@@ -5817,6 +5819,9 @@
 	ALC269_TYPE_ALC269VB,
 	ALC269_TYPE_ALC269VC,
 	ALC269_TYPE_ALC269VD,
+	ALC269_TYPE_ALC280,
+	ALC269_TYPE_ALC282,
+	ALC269_TYPE_ALC284,
 };
 
 /*
@@ -5833,10 +5838,13 @@
 	switch (spec->codec_variant) {
 	case ALC269_TYPE_ALC269VA:
 	case ALC269_TYPE_ALC269VC:
+	case ALC269_TYPE_ALC280:
+	case ALC269_TYPE_ALC284:
 		ssids = alc269va_ssids;
 		break;
 	case ALC269_TYPE_ALC269VB:
 	case ALC269_TYPE_ALC269VD:
+	case ALC269_TYPE_ALC282:
 		ssids = alc269_ssids;
 		break;
 	default:
@@ -6245,6 +6253,7 @@
 	SND_PCI_QUIRK(0x1025, 0x0349, "Acer AOD260", ALC269_FIXUP_INV_DMIC),
 	SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_MIC2_MUTE_LED),
 	SND_PCI_QUIRK(0x103c, 0x1972, "HP Pavilion 17", ALC269_FIXUP_MIC1_MUTE_LED),
+	SND_PCI_QUIRK(0x103c, 0x1977, "HP Pavilion 14", ALC269_FIXUP_MIC1_MUTE_LED),
 	SND_PCI_QUIRK(0x1043, 0x1427, "Asus Zenbook UX31E", ALC269VB_FIXUP_DMIC),
 	SND_PCI_QUIRK(0x1043, 0x1517, "Asus Zenbook UX31A", ALC269VB_FIXUP_DMIC),
 	SND_PCI_QUIRK(0x1043, 0x1a13, "Asus G73Jw", ALC269_FIXUP_ASUS_G73JW),
@@ -6259,6 +6268,7 @@
 	SND_PCI_QUIRK(0x104d, 0x9084, "Sony VAIO", ALC275_FIXUP_SONY_HWEQ),
 	SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO),
 	SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z),
+	SND_PCI_QUIRK(0x1025, 0x0740, "Acer AO725", ALC271_FIXUP_HP_GATE_MIC_JACK),
 	SND_PCI_QUIRK(0x1025, 0x0742, "Acer AO756", ALC271_FIXUP_HP_GATE_MIC_JACK),
 	SND_PCI_QUIRK_VENDOR(0x1025, "Acer Aspire", ALC271_FIXUP_DMIC),
 	SND_PCI_QUIRK(0x10cf, 0x1475, "Lifebook", ALC269_FIXUP_LIFEBOOK),
@@ -6400,7 +6410,8 @@
 
 	alc_auto_parse_customize_define(codec);
 
-	if (codec->vendor_id == 0x10ec0269) {
+	switch (codec->vendor_id) {
+	case 0x10ec0269:
 		spec->codec_variant = ALC269_TYPE_ALC269VA;
 		switch (alc_get_coef0(codec) & 0x00f0) {
 		case 0x0010:
@@ -6425,6 +6436,20 @@
 			goto error;
 		spec->init_hook = alc269_fill_coef;
 		alc269_fill_coef(codec);
+		break;
+
+	case 0x10ec0280:
+	case 0x10ec0290:
+		spec->codec_variant = ALC269_TYPE_ALC280;
+		break;
+	case 0x10ec0282:
+	case 0x10ec0283:
+		spec->codec_variant = ALC269_TYPE_ALC282;
+		break;
+	case 0x10ec0284:
+	case 0x10ec0292:
+		spec->codec_variant = ALC269_TYPE_ALC284;
+		break;
 	}
 
 	/* automatic parse from the BIOS config */
@@ -7129,6 +7154,7 @@
 	{ .id = 0x10ec0280, .name = "ALC280", .patch = patch_alc269 },
 	{ .id = 0x10ec0282, .name = "ALC282", .patch = patch_alc269 },
 	{ .id = 0x10ec0283, .name = "ALC283", .patch = patch_alc269 },
+	{ .id = 0x10ec0284, .name = "ALC284", .patch = patch_alc269 },
 	{ .id = 0x10ec0290, .name = "ALC290", .patch = patch_alc269 },
 	{ .id = 0x10ec0292, .name = "ALC292", .patch = patch_alc269 },
 	{ .id = 0x10ec0861, .rev = 0x100340, .name = "ALC660",
diff --git a/sound/pci/rme9652/hdspm.c b/sound/pci/rme9652/hdspm.c
index 6e02e06..223c3d9 100644
--- a/sound/pci/rme9652/hdspm.c
+++ b/sound/pci/rme9652/hdspm.c
@@ -441,6 +441,7 @@
 */
 /* status */
 #define HDSPM_AES32_wcLock	0x0200000
+#define HDSPM_AES32_wcSync	0x0100000
 #define HDSPM_AES32_wcFreq_bit  22
 /* (status >> HDSPM_AES32_wcFreq_bit) & 0xF gives WC frequency (cf function
   HDSPM_bit2freq */
@@ -3467,10 +3468,12 @@
 	switch (hdspm->io_type) {
 	case AES32:
 		status = hdspm_read(hdspm, HDSPM_statusRegister);
-		if (status & HDSPM_wcSync)
-			return 2;
-		else if (status & HDSPM_wcLock)
-			return 1;
+		if (status & HDSPM_AES32_wcLock) {
+			if (status & HDSPM_AES32_wcSync)
+				return 2;
+			else
+				return 1;
+		}
 		return 0;
 		break;
 
@@ -4658,6 +4661,7 @@
 	unsigned int status;
 	unsigned int status2;
 	unsigned int timecode;
+	unsigned int wcLock, wcSync;
 	int pref_syncref;
 	char *autosync_ref;
 	int x;
@@ -4751,8 +4755,11 @@
 
 	snd_iprintf(buffer, "--- Status:\n");
 
+	wcLock = status & HDSPM_AES32_wcLock;
+	wcSync = wcLock && (status & HDSPM_AES32_wcSync);
+
 	snd_iprintf(buffer, "Word: %s  Frequency: %d\n",
-		    (status & HDSPM_AES32_wcLock) ? "Sync   " : "No Lock",
+		    (wcLock) ? (wcSync ? "Sync   " : "Lock   ") : "No Lock",
 		    HDSPM_bit2freq((status >> HDSPM_AES32_wcFreq_bit) & 0xF));
 
 	for (x = 0; x < 8; x++) {
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index adf397b..ef62c43 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -446,15 +446,9 @@
 	case SND_SOC_DAIFMT_DSP_A:
 		mode = 0;
 		break;
-	case SND_SOC_DAIFMT_DSP_B:
-		mode = 1;
-		break;
 	case SND_SOC_DAIFMT_I2S:
 		mode = 2;
 		break;
-	case SND_SOC_DAIFMT_LEFT_J:
-		mode = 3;
-		break;
 	default:
 		arizona_aif_err(dai, "Unsupported DAI format %d\n",
 				fmt & SND_SOC_DAIFMT_FORMAT_MASK);
@@ -691,7 +685,7 @@
 	}
 	sr_val = i;
 
-	lrclk = snd_soc_params_to_bclk(params) / params_rate(params);
+	lrclk = rates[bclk] / params_rate(params);
 
 	arizona_aif_dbg(dai, "BCLK %dHz LRCLK %dHz\n",
 			rates[bclk], rates[bclk] / lrclk);
@@ -714,7 +708,8 @@
 		snd_soc_update_bits(codec, ARIZONA_ASYNC_SAMPLE_RATE_1,
 				    ARIZONA_ASYNC_SAMPLE_RATE_MASK, sr_val);
 		snd_soc_update_bits(codec, base + ARIZONA_AIF_RATE_CTRL,
-				    ARIZONA_AIF1_RATE_MASK, 8);
+				    ARIZONA_AIF1_RATE_MASK,
+				    8 << ARIZONA_AIF1_RATE_SHIFT);
 		break;
 	default:
 		arizona_aif_err(dai, "Invalid clock %d\n", dai_priv->clk);
@@ -1087,6 +1082,9 @@
 			id, ret);
 	}
 
+	regmap_update_bits(arizona->regmap, fll->base + 1,
+			   ARIZONA_FLL1_FREERUN, 0);
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(arizona_init_fll);
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h
index 41dae1e..4deebeb 100644
--- a/sound/soc/codecs/arizona.h
+++ b/sound/soc/codecs/arizona.h
@@ -34,15 +34,15 @@
 
 #define ARIZONA_FLL_SRC_MCLK1      0
 #define ARIZONA_FLL_SRC_MCLK2      1
-#define ARIZONA_FLL_SRC_SLIMCLK    2
-#define ARIZONA_FLL_SRC_FLL1       3
-#define ARIZONA_FLL_SRC_FLL2       4
-#define ARIZONA_FLL_SRC_AIF1BCLK   5
-#define ARIZONA_FLL_SRC_AIF2BCLK   6
-#define ARIZONA_FLL_SRC_AIF3BCLK   7
-#define ARIZONA_FLL_SRC_AIF1LRCLK  8
-#define ARIZONA_FLL_SRC_AIF2LRCLK  9
-#define ARIZONA_FLL_SRC_AIF3LRCLK 10
+#define ARIZONA_FLL_SRC_SLIMCLK    3
+#define ARIZONA_FLL_SRC_FLL1       4
+#define ARIZONA_FLL_SRC_FLL2       5
+#define ARIZONA_FLL_SRC_AIF1BCLK   8
+#define ARIZONA_FLL_SRC_AIF2BCLK   9
+#define ARIZONA_FLL_SRC_AIF3BCLK  10
+#define ARIZONA_FLL_SRC_AIF1LRCLK 12
+#define ARIZONA_FLL_SRC_AIF2LRCLK 13
+#define ARIZONA_FLL_SRC_AIF3LRCLK 14
 
 #define ARIZONA_MIXER_VOL_MASK             0x00FE
 #define ARIZONA_MIXER_VOL_SHIFT                 1
diff --git a/sound/soc/codecs/cs4271.c b/sound/soc/codecs/cs4271.c
index 4f11279..ac8742a 100644
--- a/sound/soc/codecs/cs4271.c
+++ b/sound/soc/codecs/cs4271.c
@@ -474,16 +474,16 @@
 	struct cs4271_platform_data *cs4271plat = codec->dev->platform_data;
 	int ret;
 	int gpio_nreset = -EINVAL;
-	int amutec_eq_bmutec = 0;
+	bool amutec_eq_bmutec = false;
 
 #ifdef CONFIG_OF
 	if (of_match_device(cs4271_dt_ids, codec->dev)) {
 		gpio_nreset = of_get_named_gpio(codec->dev->of_node,
 						"reset-gpio", 0);
 
-		if (!of_get_property(codec->dev->of_node,
+		if (of_get_property(codec->dev->of_node,
 				     "cirrus,amutec-eq-bmutec", NULL))
-			amutec_eq_bmutec = 1;
+			amutec_eq_bmutec = true;
 	}
 #endif
 
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c
index 99bb1c6..9811a54 100644
--- a/sound/soc/codecs/cs42l52.c
+++ b/sound/soc/codecs/cs42l52.c
@@ -737,7 +737,7 @@
 
 static int cs42l52_get_clk(int mclk, int rate)
 {
-	int i, ret = 0;
+	int i, ret = -EINVAL;
 	u_int mclk1, mclk2 = 0;
 
 	for (i = 0; i < ARRAY_SIZE(clk_map_table); i++) {
@@ -749,8 +749,6 @@
 			}
 		}
 	}
-	if (ret > ARRAY_SIZE(clk_map_table))
-		return -EINVAL;
 	return ret;
 }
 
diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c
index d75257d..e19490c 100644
--- a/sound/soc/codecs/lm49453.c
+++ b/sound/soc/codecs/lm49453.c
@@ -111,9 +111,9 @@
 	{ 101, 0x00 },
 	{ 102, 0x00 },
 	{ 103, 0x01 },
-	{ 105, 0x01 },
-	{ 106, 0x00 },
-	{ 107, 0x01 },
+	{ 104, 0x01 },
+	{ 105, 0x00 },
+	{ 106, 0x01 },
 	{ 107, 0x00 },
 	{ 108, 0x00 },
 	{ 109, 0x00 },
@@ -163,56 +163,25 @@
 	{ 184, 0x00 },
 	{ 185, 0x00 },
 	{ 186, 0x00 },
-	{ 189, 0x00 },
+	{ 187, 0x00 },
 	{ 188, 0x00 },
-	{ 194, 0x00 },
-	{ 195, 0x00 },
-	{ 196, 0x00 },
-	{ 197, 0x00 },
-	{ 200, 0x00 },
-	{ 201, 0x00 },
-	{ 202, 0x00 },
-	{ 203, 0x00 },
-	{ 204, 0x00 },
-	{ 205, 0x00 },
-	{ 208, 0x00 },
+	{ 189, 0x00 },
+	{ 208, 0x06 },
 	{ 209, 0x00 },
-	{ 210, 0x00 },
-	{ 211, 0x00 },
-	{ 213, 0x00 },
-	{ 214, 0x00 },
-	{ 215, 0x00 },
-	{ 216, 0x00 },
-	{ 217, 0x00 },
-	{ 218, 0x00 },
-	{ 219, 0x00 },
+	{ 210, 0x08 },
+	{ 211, 0x54 },
+	{ 212, 0x14 },
+	{ 213, 0x0d },
+	{ 214, 0x0d },
+	{ 215, 0x14 },
+	{ 216, 0x60 },
 	{ 221, 0x00 },
 	{ 222, 0x00 },
+	{ 223, 0x00 },
 	{ 224, 0x00 },
-	{ 225, 0x00 },
-	{ 226, 0x00 },
-	{ 227, 0x00 },
-	{ 228, 0x00 },
-	{ 229, 0x00 },
-	{ 230, 0x13 },
-	{ 231, 0x00 },
-	{ 232, 0x80 },
-	{ 233, 0x0C },
-	{ 234, 0xDD },
-	{ 235, 0x00 },
-	{ 236, 0x04 },
-	{ 237, 0x00 },
-	{ 238, 0x00 },
-	{ 239, 0x00 },
-	{ 240, 0x00 },
-	{ 241, 0x00 },
-	{ 242, 0x00 },
-	{ 243, 0x00 },
-	{ 244, 0x00 },
-	{ 245, 0x00 },
 	{ 248, 0x00 },
 	{ 249, 0x00 },
-	{ 254, 0x00 },
+	{ 250, 0x00 },
 	{ 255, 0x00 },
 };
 
@@ -525,36 +494,41 @@
 };
 
 /* TLV Declarations */
-static const DECLARE_TLV_DB_SCALE(digital_tlv, -7650, 150, 1);
-static const DECLARE_TLV_DB_SCALE(port_tlv, 0, 600, 0);
+static const DECLARE_TLV_DB_SCALE(adc_dac_tlv, -7650, 150, 1);
+static const DECLARE_TLV_DB_SCALE(mic_tlv, 0, 200, 1);
+static const DECLARE_TLV_DB_SCALE(port_tlv, -1800, 600, 0);
+static const DECLARE_TLV_DB_SCALE(stn_tlv, -7200, 150, 0);
 
 static const struct snd_kcontrol_new lm49453_sidetone_mixer_controls[] = {
 /* Sidetone supports mono only */
 SOC_DAPM_SINGLE_TLV("Sidetone ADCL Volume", LM49453_P0_STN_VOL_ADCL_REG,
-		     0, 0x3F, 0, digital_tlv),
+		     0, 0x3F, 0, stn_tlv),
 SOC_DAPM_SINGLE_TLV("Sidetone ADCR Volume", LM49453_P0_STN_VOL_ADCR_REG,
-		     0, 0x3F, 0, digital_tlv),
+		     0, 0x3F, 0, stn_tlv),
 SOC_DAPM_SINGLE_TLV("Sidetone DMIC1L Volume", LM49453_P0_STN_VOL_DMIC1L_REG,
-		     0, 0x3F, 0, digital_tlv),
+		     0, 0x3F, 0, stn_tlv),
 SOC_DAPM_SINGLE_TLV("Sidetone DMIC1R Volume", LM49453_P0_STN_VOL_DMIC1R_REG,
-		     0, 0x3F, 0, digital_tlv),
+		     0, 0x3F, 0, stn_tlv),
 SOC_DAPM_SINGLE_TLV("Sidetone DMIC2L Volume", LM49453_P0_STN_VOL_DMIC2L_REG,
-		     0, 0x3F, 0, digital_tlv),
+		     0, 0x3F, 0, stn_tlv),
 SOC_DAPM_SINGLE_TLV("Sidetone DMIC2R Volume", LM49453_P0_STN_VOL_DMIC2R_REG,
-		     0, 0x3F, 0, digital_tlv),
+		     0, 0x3F, 0, stn_tlv),
 };
 
 static const struct snd_kcontrol_new lm49453_snd_controls[] = {
 	/* mic1 and mic2 supports mono only */
-	SOC_SINGLE_TLV("Mic1 Volume", LM49453_P0_ADC_LEVELL_REG, 0, 6,
-			0, digital_tlv),
-	SOC_SINGLE_TLV("Mic2 Volume", LM49453_P0_ADC_LEVELR_REG, 0, 6,
-			0, digital_tlv),
+	SOC_SINGLE_TLV("Mic1 Volume", LM49453_P0_MICL_REG, 0, 15, 0, mic_tlv),
+	SOC_SINGLE_TLV("Mic2 Volume", LM49453_P0_MICR_REG, 0, 15, 0, mic_tlv),
+
+	SOC_SINGLE_TLV("ADCL Volume", LM49453_P0_ADC_LEVELL_REG, 0, 63,
+			0, adc_dac_tlv),
+	SOC_SINGLE_TLV("ADCR Volume", LM49453_P0_ADC_LEVELR_REG, 0, 63,
+			0, adc_dac_tlv),
 
 	SOC_DOUBLE_R_TLV("DMIC1 Volume", LM49453_P0_DMIC1_LEVELL_REG,
-			  LM49453_P0_DMIC1_LEVELR_REG, 0, 6, 0, digital_tlv),
+			  LM49453_P0_DMIC1_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
 	SOC_DOUBLE_R_TLV("DMIC2 Volume", LM49453_P0_DMIC2_LEVELL_REG,
-			  LM49453_P0_DMIC2_LEVELR_REG, 0, 6, 0, digital_tlv),
+			  LM49453_P0_DMIC2_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
 
 	SOC_DAPM_ENUM("Mic2Mode", lm49453_mic2mode_enum),
 	SOC_DAPM_ENUM("DMIC12 SRC", lm49453_dmic12_cfg_enum),
@@ -569,16 +543,16 @@
 					  2, 1, 0),
 
 	SOC_DOUBLE_R_TLV("DAC HP Volume", LM49453_P0_DAC_HP_LEVELL_REG,
-			  LM49453_P0_DAC_HP_LEVELR_REG, 0, 6, 0, digital_tlv),
+			  LM49453_P0_DAC_HP_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
 	SOC_DOUBLE_R_TLV("DAC LO Volume", LM49453_P0_DAC_LO_LEVELL_REG,
-			  LM49453_P0_DAC_LO_LEVELR_REG, 0, 6, 0, digital_tlv),
+			  LM49453_P0_DAC_LO_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
 	SOC_DOUBLE_R_TLV("DAC LS Volume", LM49453_P0_DAC_LS_LEVELL_REG,
-			  LM49453_P0_DAC_LS_LEVELR_REG, 0, 6, 0, digital_tlv),
+			  LM49453_P0_DAC_LS_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
 	SOC_DOUBLE_R_TLV("DAC HA Volume", LM49453_P0_DAC_HA_LEVELL_REG,
-			  LM49453_P0_DAC_HA_LEVELR_REG, 0, 6, 0, digital_tlv),
+			  LM49453_P0_DAC_HA_LEVELR_REG, 0, 63, 0, adc_dac_tlv),
 
 	SOC_SINGLE_TLV("EP Volume", LM49453_P0_DAC_LS_LEVELL_REG,
-			0, 6, 0, digital_tlv),
+			0, 63, 0, adc_dac_tlv),
 
 	SOC_SINGLE_TLV("PORT1_1_RX_LVL Volume", LM49453_P0_PORT1_RX_LVL1_REG,
 			0, 3, 0, port_tlv),
@@ -1218,7 +1192,7 @@
 	}
 
 	snd_soc_update_bits(codec, LM49453_P0_AUDIO_PORT1_BASIC_REG,
-			    LM49453_AUDIO_PORT1_BASIC_FMT_MASK|BIT(1)|BIT(5),
+			    LM49453_AUDIO_PORT1_BASIC_FMT_MASK|BIT(0)|BIT(5),
 			    (aif_val | mode | clk_phase));
 
 	snd_soc_write(codec, LM49453_P0_AUDIO_PORT1_RX_MSB_REG, clk_shift);
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index cb1675c..92bbfec 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -401,7 +401,7 @@
 			5, 1, 0),
 
 	SOC_SINGLE_TLV("Mic Volume", SGTL5000_CHIP_MIC_CTRL,
-			0, 4, 0, mic_gain_tlv),
+			0, 3, 0, mic_gain_tlv),
 };
 
 /* mute the codec used by alsa core */
@@ -1344,7 +1344,7 @@
 			SGTL5000_HP_ZCD_EN |
 			SGTL5000_ADC_ZCD_EN);
 
-	snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 0);
+	snd_soc_write(codec, SGTL5000_CHIP_MIC_CTRL, 2);
 
 	/*
 	 * disable DAP
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c
index ab355c4..40c07be 100644
--- a/sound/soc/codecs/sta529.c
+++ b/sound/soc/codecs/sta529.c
@@ -74,9 +74,10 @@
 				SNDRV_PCM_FMTBIT_S32_LE)
 #define	S2PC_VALUE		0x98
 #define CLOCK_OUT		0x60
-#define LEFT_J_DATA_FORMAT	0x10
-#define I2S_DATA_FORMAT		0x12
-#define RIGHT_J_DATA_FORMAT	0x14
+#define DATA_FORMAT_MSK		0x0E
+#define LEFT_J_DATA_FORMAT	0x00
+#define I2S_DATA_FORMAT		0x02
+#define RIGHT_J_DATA_FORMAT	0x04
 #define CODEC_MUTE_VAL		0x80
 
 #define POWER_CNTLMSAK		0x40
@@ -289,7 +290,7 @@
 		return -EINVAL;
 	}
 
-	snd_soc_update_bits(codec, STA529_S2PCFG0, 0x0D, mode);
+	snd_soc_update_bits(codec, STA529_S2PCFG0, DATA_FORMAT_MSK, mode);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c
index 1cbe88f..12bcae6 100644
--- a/sound/soc/codecs/wm2000.c
+++ b/sound/soc/codecs/wm2000.c
@@ -209,9 +209,9 @@
 
 	ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY);
 	if (wm2000->speech_clarity)
-		ret &= ~WM2000_SPEECH_CLARITY;
-	else
 		ret |= WM2000_SPEECH_CLARITY;
+	else
+		ret &= ~WM2000_SPEECH_CLARITY;
 	wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret);
 
 	wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33);
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c
index afcf31d..d8c65f5 100644
--- a/sound/soc/codecs/wm2200.c
+++ b/sound/soc/codecs/wm2200.c
@@ -1019,8 +1019,6 @@
 	"EQR",
 	"LHPF1",
 	"LHPF2",
-	"LHPF3",
-	"LHPF4",
 	"DSP1.1",
 	"DSP1.2",
 	"DSP1.3",
@@ -1053,7 +1051,6 @@
 	0x25,
 	0x50,   /* EQ */
 	0x51,
-	0x52,
 	0x60,   /* LHPF1 */
 	0x61,   /* LHPF2 */
 	0x68,   /* DSP1 */
@@ -1566,15 +1563,9 @@
 	case SND_SOC_DAIFMT_DSP_A:
 		fmt_val = 0;
 		break;
-	case SND_SOC_DAIFMT_DSP_B:
-		fmt_val = 1;
-		break;
 	case SND_SOC_DAIFMT_I2S:
 		fmt_val = 2;
 		break;
-	case SND_SOC_DAIFMT_LEFT_J:
-		fmt_val = 3;
-		break;
 	default:
 		dev_err(codec->dev, "Unsupported DAI format %d\n",
 			fmt & SND_SOC_DAIFMT_FORMAT_MASK);
@@ -1626,7 +1617,7 @@
 			    WM2200_AIF1TX_LRCLK_MSTR | WM2200_AIF1TX_LRCLK_INV,
 			    lrclk);
 	snd_soc_update_bits(codec, WM2200_AUDIO_IF_1_5,
-			    WM2200_AIF1_FMT_MASK << 1, fmt_val << 1);
+			    WM2200_AIF1_FMT_MASK, fmt_val);
 
 	return 0;
 }
diff --git a/sound/soc/codecs/wm5100.c b/sound/soc/codecs/wm5100.c
index 5a5f369..54397a5 100644
--- a/sound/soc/codecs/wm5100.c
+++ b/sound/soc/codecs/wm5100.c
@@ -1279,15 +1279,9 @@
 	case SND_SOC_DAIFMT_DSP_A:
 		mask = 0;
 		break;
-	case SND_SOC_DAIFMT_DSP_B:
-		mask = 1;
-		break;
 	case SND_SOC_DAIFMT_I2S:
 		mask = 2;
 		break;
-	case SND_SOC_DAIFMT_LEFT_J:
-		mask = 3;
-		break;
 	default:
 		dev_err(codec->dev, "Unsupported DAI format %d\n",
 			fmt & SND_SOC_DAIFMT_FORMAT_MASK);
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c
index 688ade0..1440b3f 100644
--- a/sound/soc/codecs/wm5102.c
+++ b/sound/soc/codecs/wm5102.c
@@ -36,6 +36,9 @@
 struct wm5102_priv {
 	struct arizona_priv core;
 	struct arizona_fll fll[2];
+
+	unsigned int spk_ena:2;
+	unsigned int spk_ena_pending:1;
 };
 
 static DECLARE_TLV_DB_SCALE(ana_tlv, 0, 100, 0);
@@ -787,6 +790,47 @@
 ARIZONA_MIXER_CONTROLS("AIF3TX2", ARIZONA_AIF3TX2MIX_INPUT_1_SOURCE),
 };
 
+static int wm5102_spk_ev(struct snd_soc_dapm_widget *w,
+			 struct snd_kcontrol *kcontrol,
+			 int event)
+{
+	struct snd_soc_codec *codec = w->codec;
+	struct arizona *arizona = dev_get_drvdata(codec->dev->parent);
+	struct wm5102_priv *wm5102 = snd_soc_codec_get_drvdata(codec);
+
+	if (arizona->rev < 1)
+		return 0;
+
+	switch (event) {
+	case SND_SOC_DAPM_PRE_PMU:
+		if (!wm5102->spk_ena) {
+			snd_soc_write(codec, 0x4f5, 0x25a);
+			wm5102->spk_ena_pending = true;
+		}
+		break;
+	case SND_SOC_DAPM_POST_PMU:
+		if (wm5102->spk_ena_pending) {
+			msleep(75);
+			snd_soc_write(codec, 0x4f5, 0xda);
+			wm5102->spk_ena_pending = false;
+			wm5102->spk_ena++;
+		}
+		break;
+	case SND_SOC_DAPM_PRE_PMD:
+		wm5102->spk_ena--;
+		if (!wm5102->spk_ena)
+			snd_soc_write(codec, 0x4f5, 0x25a);
+		break;
+	case SND_SOC_DAPM_POST_PMD:
+		if (!wm5102->spk_ena)
+			snd_soc_write(codec, 0x4f5, 0x0da);
+		break;
+	}
+
+	return 0;
+}
+
+
 ARIZONA_MIXER_ENUMS(EQ1, ARIZONA_EQ1MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(EQ2, ARIZONA_EQ2MIX_INPUT_1_SOURCE);
 ARIZONA_MIXER_ENUMS(EQ3, ARIZONA_EQ3MIX_INPUT_1_SOURCE);
@@ -852,8 +896,7 @@
 
 static const struct soc_enum wm5102_aec_loopback =
 	SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1,
-			      ARIZONA_AEC_LOOPBACK_SRC_SHIFT,
-			      ARIZONA_AEC_LOOPBACK_SRC_MASK,
+			      ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf,
 			      ARRAY_SIZE(wm5102_aec_loopback_texts),
 			      wm5102_aec_loopback_texts,
 			      wm5102_aec_loopback_values);
@@ -1034,10 +1077,10 @@
 		   ARIZONA_OUT3L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("OUT4L", ARIZONA_OUTPUT_ENABLES_1,
-		   ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   ARIZONA_OUT4L_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("OUT4R", ARIZONA_OUTPUT_ENABLES_1,
-		   ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
+		   ARIZONA_OUT4R_ENA_SHIFT, 0, NULL, 0, wm5102_spk_ev,
 		   SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
 SND_SOC_DAPM_PGA_E("OUT5L", ARIZONA_OUTPUT_ENABLES_1,
 		   ARIZONA_OUT5L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev,
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c
index ae80c8c..7a09096 100644
--- a/sound/soc/codecs/wm5110.c
+++ b/sound/soc/codecs/wm5110.c
@@ -344,8 +344,7 @@
 
 static const struct soc_enum wm5110_aec_loopback =
 	SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1,
-			      ARIZONA_AEC_LOOPBACK_SRC_SHIFT,
-			      ARIZONA_AEC_LOOPBACK_SRC_MASK,
+			      ARIZONA_AEC_LOOPBACK_SRC_SHIFT, 0xf,
 			      ARRAY_SIZE(wm5110_aec_loopback_texts),
 			      wm5110_aec_loopback_texts,
 			      wm5110_aec_loopback_values);
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index ffc89fa..b6b6548 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -169,6 +169,7 @@
 	const struct wm_adsp_region *mem;
 	const char *region_name;
 	char *file, *text;
+	void *buf;
 	unsigned int reg;
 	int regions = 0;
 	int ret, offset, type, sizes;
@@ -322,8 +323,18 @@
 		}
 
 		if (reg) {
-			ret = regmap_raw_write(regmap, reg, region->data,
+			buf = kmemdup(region->data, le32_to_cpu(region->len),
+				      GFP_KERNEL | GFP_DMA);
+			if (!buf) {
+				adsp_err(dsp, "Out of memory\n");
+				return -ENOMEM;
+			}
+
+			ret = regmap_raw_write(regmap, reg, buf,
 					       le32_to_cpu(region->len));
+
+			kfree(buf);
+
 			if (ret != 0) {
 				adsp_err(dsp,
 					"%s.%d: Failed to write %d bytes at %d in %s: %d\n",
@@ -359,6 +370,7 @@
 	const char *region_name;
 	int ret, pos, blocks, type, offset, reg;
 	char *file;
+	void *buf;
 
 	file = kzalloc(PAGE_SIZE, GFP_KERNEL);
 	if (file == NULL)
@@ -384,7 +396,7 @@
 	hdr = (void*)&firmware->data[0];
 	if (memcmp(hdr->magic, "WMDR", 4) != 0) {
 		adsp_err(dsp, "%s: invalid magic\n", file);
-		return -EINVAL;
+		goto out_fw;
 	}
 
 	adsp_dbg(dsp, "%s: v%d.%d.%d\n", file,
@@ -426,6 +438,13 @@
 		}
 
 		if (reg) {
+			buf = kmemdup(blk->data, le32_to_cpu(blk->len),
+				      GFP_KERNEL | GFP_DMA);
+			if (!buf) {
+				adsp_err(dsp, "Out of memory\n");
+				return -ENOMEM;
+			}
+
 			ret = regmap_raw_write(regmap, reg, blk->data,
 					       le32_to_cpu(blk->len));
 			if (ret != 0) {
@@ -433,6 +452,8 @@
 					"%s.%d: Failed to write to %x in %s\n",
 					file, blocks, reg, region_name);
 			}
+
+			kfree(buf);
 		}
 
 		pos += le32_to_cpu(blk->len) + sizeof(*blk);
diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 3b98159..a210c8d 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -108,18 +108,13 @@
 config SND_SOC_IMX_SSI
 	tristate
 
-config SND_SOC_IMX_PCM
-	tristate
-
 config SND_SOC_IMX_PCM_FIQ
-	bool
+	tristate
 	select FIQ
-	select SND_SOC_IMX_PCM
 
 config SND_SOC_IMX_PCM_DMA
-	bool
+	tristate
 	select SND_SOC_DMAENGINE_PCM
-	select SND_SOC_IMX_PCM
 
 config SND_SOC_IMX_AUDMUX
 	tristate
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index afd3479..ec14579 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -41,7 +41,10 @@
 obj-$(CONFIG_SND_SOC_IMX_SSI) += snd-soc-imx-ssi.o
 obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o
 
-obj-$(CONFIG_SND_SOC_IMX_PCM) += snd-soc-imx-pcm.o
+obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += snd-soc-imx-pcm-fiq.o
+snd-soc-imx-pcm-fiq-y := imx-pcm-fiq.o imx-pcm.o
+obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += snd-soc-imx-pcm-dma.o
+snd-soc-imx-pcm-dma-y := imx-pcm-dma.o imx-pcm.o
 
 # i.MX Machine Support
 snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o
diff --git a/sound/soc/fsl/imx-pcm.c b/sound/soc/fsl/imx-pcm.c
index d5cd9ef..0c9f188 100644
--- a/sound/soc/fsl/imx-pcm.c
+++ b/sound/soc/fsl/imx-pcm.c
@@ -31,7 +31,6 @@
 			runtime->dma_bytes);
 	return ret;
 }
-EXPORT_SYMBOL_GPL(snd_imx_pcm_mmap);
 
 static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
 {
@@ -80,7 +79,6 @@
 out:
 	return ret;
 }
-EXPORT_SYMBOL_GPL(imx_pcm_new);
 
 void imx_pcm_free(struct snd_pcm *pcm)
 {
@@ -102,7 +100,6 @@
 		buf->area = NULL;
 	}
 }
-EXPORT_SYMBOL_GPL(imx_pcm_free);
 
 MODULE_DESCRIPTION("Freescale i.MX PCM driver");
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 91d592f..2370063 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -1255,6 +1255,8 @@
 	INIT_LIST_HEAD(&rtd->dpcm[SNDRV_PCM_STREAM_CAPTURE].fe_clients);
 	ret = device_add(rtd->dev);
 	if (ret < 0) {
+		/* calling put_device() here to free the rtd->dev */
+		put_device(rtd->dev);
 		dev_err(card->dev,
 			"ASoC: failed to register runtime device: %d\n", ret);
 		return ret;
@@ -1554,7 +1556,7 @@
 	/* unregister the rtd device */
 	if (rtd->dev_registered) {
 		device_remove_file(rtd->dev, &dev_attr_codec_reg);
-		device_del(rtd->dev);
+		device_unregister(rtd->dev);
 		rtd->dev_registered = 0;
 	}
 
@@ -2917,7 +2919,7 @@
 	platform_max = mc->platform_max;
 
 	uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
-	uinfo->count = 1;
+	uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1;
 	uinfo->value.integer.min = 0;
 	uinfo->value.integer.max = platform_max - min;
 
@@ -2941,12 +2943,14 @@
 		(struct soc_mixer_control *)kcontrol->private_value;
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	unsigned int reg = mc->reg;
+	unsigned int rreg = mc->rreg;
 	unsigned int shift = mc->shift;
 	int min = mc->min;
 	int max = mc->max;
 	unsigned int mask = (1 << fls(max)) - 1;
 	unsigned int invert = mc->invert;
 	unsigned int val, val_mask;
+	int ret;
 
 	val = ((ucontrol->value.integer.value[0] + min) & mask);
 	if (invert)
@@ -2954,7 +2958,21 @@
 	val_mask = mask << shift;
 	val = val << shift;
 
-	return snd_soc_update_bits_locked(codec, reg, val_mask, val);
+	ret = snd_soc_update_bits_locked(codec, reg, val_mask, val);
+	if (ret != 0)
+		return ret;
+
+	if (snd_soc_volsw_is_stereo(mc)) {
+		val = ((ucontrol->value.integer.value[1] + min) & mask);
+		if (invert)
+			val = max - val;
+		val_mask = mask << shift;
+		val = val << shift;
+
+		ret = snd_soc_update_bits_locked(codec, rreg, val_mask, val);
+	}
+
+	return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_put_volsw_range);
 
@@ -2974,6 +2992,7 @@
 		(struct soc_mixer_control *)kcontrol->private_value;
 	struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol);
 	unsigned int reg = mc->reg;
+	unsigned int rreg = mc->rreg;
 	unsigned int shift = mc->shift;
 	int min = mc->min;
 	int max = mc->max;
@@ -2988,6 +3007,16 @@
 	ucontrol->value.integer.value[0] =
 		ucontrol->value.integer.value[0] - min;
 
+	if (snd_soc_volsw_is_stereo(mc)) {
+		ucontrol->value.integer.value[1] =
+			(snd_soc_read(codec, rreg) >> shift) & mask;
+		if (invert)
+			ucontrol->value.integer.value[1] =
+				max - ucontrol->value.integer.value[1];
+		ucontrol->value.integer.value[1] =
+			ucontrol->value.integer.value[1] - min;
+	}
+
 	return 0;
 }
 EXPORT_SYMBOL_GPL(snd_soc_get_volsw_range);
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c
index 1e36bc8..258acad 100644
--- a/sound/soc/soc-dapm.c
+++ b/sound/soc/soc-dapm.c
@@ -1023,7 +1023,7 @@
 
 	if (SND_SOC_DAPM_EVENT_ON(event)) {
 		if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
-			ret = regulator_allow_bypass(w->regulator, true);
+			ret = regulator_allow_bypass(w->regulator, false);
 			if (ret != 0)
 				dev_warn(w->dapm->dev,
 					 "ASoC: Failed to bypass %s: %d\n",
@@ -1033,7 +1033,7 @@
 		return regulator_enable(w->regulator);
 	} else {
 		if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
-			ret = regulator_allow_bypass(w->regulator, false);
+			ret = regulator_allow_bypass(w->regulator, true);
 			if (ret != 0)
 				dev_warn(w->dapm->dev,
 					 "ASoC: Failed to unbypass %s: %d\n",
@@ -3039,6 +3039,14 @@
 				w->name, ret);
 			return NULL;
 		}
+
+		if (w->invert & SND_SOC_DAPM_REGULATOR_BYPASS) {
+			ret = regulator_allow_bypass(w->regulator, true);
+			if (ret != 0)
+				dev_warn(w->dapm->dev,
+					 "ASoC: Failed to unbypass %s: %d\n",
+					 w->name, ret);
+		}
 		break;
 	case snd_soc_dapm_clock_supply:
 #ifdef CONFIG_CLKDEV_LOOKUP
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index d7711fc..cf191e6 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1243,6 +1243,7 @@
 		if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_PARAMS) &&
 		    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
 		    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
+		    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
 		    (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
 			continue;
 
diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c
index f354dc3..2355630 100644
--- a/sound/soc/tegra/tegra30_ahub.c
+++ b/sound/soc/tegra/tegra30_ahub.c
@@ -25,7 +25,7 @@
 #include <linux/pm_runtime.h>
 #include <linux/regmap.h>
 #include <linux/slab.h>
-#include <mach/clk.h>
+#include <linux/clk/tegra.h>
 #include <sound/soc.h>
 #include "tegra30_ahub.h"
 
@@ -299,15 +299,6 @@
 	"spdif_in",
 };
 
-struct of_dev_auxdata ahub_auxdata[] = {
-	OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080300, "tegra30-i2s.0", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080400, "tegra30-i2s.1", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080500, "tegra30-i2s.2", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080600, "tegra30-i2s.3", NULL),
-	OF_DEV_AUXDATA("nvidia,tegra30-i2s", 0x70080700, "tegra30-i2s.4", NULL),
-	{}
-};
-
 #define LAST_REG(name) \
 	(TEGRA30_AHUB_##name + \
 	 (TEGRA30_AHUB_##name##_STRIDE * TEGRA30_AHUB_##name##_COUNT) - 4)
@@ -451,7 +442,7 @@
 	 * Ensure that here.
 	 */
 	for (i = 0; i < ARRAY_SIZE(configlink_clocks); i++) {
-		clk = clk_get_sys(NULL, configlink_clocks[i]);
+		clk = clk_get(&pdev->dev, configlink_clocks[i]);
 		if (IS_ERR(clk)) {
 			dev_err(&pdev->dev, "Can't get clock %s\n",
 				configlink_clocks[i]);
@@ -569,8 +560,7 @@
 			goto err_pm_disable;
 	}
 
-	of_platform_populate(pdev->dev.of_node, NULL, ahub_auxdata,
-			     &pdev->dev);
+	of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev);
 
 	return 0;
 
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
index ed4d89c..e90daf8 100644
--- a/sound/usb/mixer.c
+++ b/sound/usb/mixer.c
@@ -1331,16 +1331,23 @@
 		}
 		channels = (hdr->bLength - 7) / csize - 1;
 		bmaControls = hdr->bmaControls;
+		if (hdr->bLength < 7 + csize) {
+			snd_printk(KERN_ERR "usbaudio: unit %u: "
+				   "invalid UAC_FEATURE_UNIT descriptor\n",
+				   unitid);
+			return -EINVAL;
+		}
 	} else {
 		struct uac2_feature_unit_descriptor *ftr = _ftr;
 		csize = 4;
 		channels = (hdr->bLength - 6) / 4 - 1;
 		bmaControls = ftr->bmaControls;
-	}
-
-	if (hdr->bLength < 7 || !csize || hdr->bLength < 7 + csize) {
-		snd_printk(KERN_ERR "usbaudio: unit %u: invalid UAC_FEATURE_UNIT descriptor\n", unitid);
-		return -EINVAL;
+		if (hdr->bLength < 6 + csize) {
+			snd_printk(KERN_ERR "usbaudio: unit %u: "
+				   "invalid UAC_FEATURE_UNIT descriptor\n",
+				   unitid);
+			return -EINVAL;
+		}
 	}
 
 	/* parse the source unit */
diff --git a/sound/usb/mixer_maps.c b/sound/usb/mixer_maps.c
index e71fe55..0e2ed3d 100644
--- a/sound/usb/mixer_maps.c
+++ b/sound/usb/mixer_maps.c
@@ -179,6 +179,15 @@
 	{ 0 } /* terminator */
 };
 
+static struct usbmix_selector_map c400_selectors[] = {
+	{
+		.id = 0x80,
+		.count = 2,
+		.names = (const char*[]) {"Internal", "SPDIF"}
+	},
+	{ 0 } /* terminator */
+};
+
 static struct usbmix_selector_map audigy2nx_selectors[] = {
 	{
 		.id = 14, /* Capture Source */
@@ -367,6 +376,10 @@
 		.map = hercules_usb51_map,
 	},
 	{
+		.id = USB_ID(0x0763, 0x2030),
+		.selector_map = c400_selectors,
+	},
+	{
 		.id = USB_ID(0x08bb, 0x2702),
 		.map = linex_map,
 		.ignore_ctl_error = 1,
diff --git a/sound/usb/mixer_quirks.c b/sound/usb/mixer_quirks.c
index 0422b13..15520de 100644
--- a/sound/usb/mixer_quirks.c
+++ b/sound/usb/mixer_quirks.c
@@ -1206,7 +1206,7 @@
  * are valid they presents mono controls as L and R channels of
  * stereo. So we provide a good mixer here.
  */
-struct std_mono_table ebox44_table[] = {
+static struct std_mono_table ebox44_table[] = {
 	{
 		.unitid = 4,
 		.control = 1,
diff --git a/sound/usb/pcm.c b/sound/usb/pcm.c
index c659310..d82e378 100644
--- a/sound/usb/pcm.c
+++ b/sound/usb/pcm.c
@@ -511,6 +511,16 @@
 	struct snd_usb_substream *sync_subs =
 		&subs->stream->substream[subs->direction ^ 1];
 
+	if (subs->sync_endpoint->type != SND_USB_ENDPOINT_TYPE_DATA ||
+	    !subs->stream)
+		return snd_usb_endpoint_set_params(subs->sync_endpoint,
+						   subs->pcm_format,
+						   subs->channels,
+						   subs->period_bytes,
+						   subs->cur_rate,
+						   subs->cur_audiofmt,
+						   NULL);
+
 	/* Try to find the best matching audioformat. */
 	list_for_each_entry(fp, &sync_subs->fmt_list, list) {
 		int score = match_endpoint_audioformats(fp, subs->cur_audiofmt,
diff --git a/sound/usb/quirks-table.h b/sound/usb/quirks-table.h
index 78e845e..64d25a7 100644
--- a/sound/usb/quirks-table.h
+++ b/sound/usb/quirks-table.h
@@ -2289,7 +2289,7 @@
 					.rate_table = (unsigned int[]) {
 							44100, 48000, 88200, 96000
 					},
-					.clock = 0x81,
+					.clock = 0x80,
 				}
 			},
 			/* Capture */
@@ -2315,7 +2315,7 @@
 					.rate_table = (unsigned int[]) {
 						44100, 48000, 88200, 96000
 					},
-					.clock = 0x81,
+					.clock = 0x80,
 				}
 			},
 			/* MIDI */
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index acc12f0..2c97185 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -387,11 +387,13 @@
 		 * rules
 		 */
 		err = usb_driver_set_configuration(dev, 2);
-		if (err < 0) {
+		if (err < 0)
 			snd_printdd("error usb_driver_set_configuration: %d\n",
 				    err);
-			return -ENODEV;
-		}
+		/* Always return an error, so that we stop creating a device
+		   that will just be destroyed and recreated with a new
+		   configuration */
+		return -ENODEV;
 	} else
 		snd_printk(KERN_INFO "usb-audio: Fast Track Pro config OK\n");
 
@@ -859,6 +861,17 @@
 	if ((le16_to_cpu(ep->chip->dev->descriptor.idVendor) == 0x23ba) &&
 	    ep->type == SND_USB_ENDPOINT_TYPE_SYNC)
 		ep->skip_packets = 4;
+
+	/*
+	 * M-Audio Fast Track C400 - when packets are not skipped, real world
+	 * latency varies by approx. +/- 50 frames (at 96KHz) each time the
+	 * stream is (re)started. When skipping packets 16 at endpoint start
+	 * up, the real world latency is stable within +/- 1 frame (also
+	 * across power cycles).
+	 */
+	if (ep->chip->usb_id == USB_ID(0x0763, 0x2030) &&
+	    ep->type == SND_USB_ENDPOINT_TYPE_DATA)
+		ep->skip_packets = 16;
 }
 
 void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
diff --git a/tools/perf/MANIFEST b/tools/perf/MANIFEST
index 80db3f4..39d4106 100644
--- a/tools/perf/MANIFEST
+++ b/tools/perf/MANIFEST
@@ -11,11 +11,21 @@
 include/linux/swab.h
 arch/*/include/asm/unistd*.h
 arch/*/include/asm/perf_regs.h
+arch/*/include/uapi/asm/unistd*.h
+arch/*/include/uapi/asm/perf_regs.h
 arch/*/lib/memcpy*.S
 arch/*/lib/memset*.S
 include/linux/poison.h
 include/linux/magic.h
 include/linux/hw_breakpoint.h
+include/linux/rbtree_augmented.h
+include/uapi/linux/perf_event.h
+include/uapi/linux/const.h
+include/uapi/linux/swab.h
+include/uapi/linux/hw_breakpoint.h
 arch/x86/include/asm/svm.h
 arch/x86/include/asm/vmx.h
 arch/x86/include/asm/kvm_host.h
+arch/x86/include/uapi/asm/svm.h
+arch/x86/include/uapi/asm/vmx.h
+arch/x86/include/uapi/asm/kvm.h
diff --git a/tools/perf/Makefile b/tools/perf/Makefile
index 891bc77..8ab05e54 100644
--- a/tools/perf/Makefile
+++ b/tools/perf/Makefile
@@ -58,7 +58,7 @@
 				  -e s/arm.*/arm/ -e s/sa110/arm/ \
 				  -e s/s390x/s390/ -e s/parisc64/parisc/ \
 				  -e s/ppc.*/powerpc/ -e s/mips.*/mips/ \
-				  -e s/sh[234].*/sh/ )
+				  -e s/sh[234].*/sh/ -e s/aarch64.*/arm64/ )
 NO_PERF_REGS := 1
 
 CC = $(CROSS_COMPILE)gcc