]> git.karo-electronics.de Git - linux-beck.git/commitdiff
Merge tag 'for-v3.16-rc/omap-fixes-a' of git://git.kernel.org/pub/scm/linux/kernel...
authorTony Lindgren <tony@atomide.com>
Mon, 16 Jun 2014 08:27:40 +0000 (01:27 -0700)
committerTony Lindgren <tony@atomide.com>
Mon, 16 Jun 2014 08:27:40 +0000 (01:27 -0700)
Two OMAP hwmod patches for early v3.16-rc kernels.

There's one OMAP SoC integration fix for the AM43xx SoC, without
which, IP blocks can't be placed into hard-reset.

There is also one OMAP5 SoC data addition patch that should have gone
in for v3.16. Normally I wouldn't send this as part of an -rc series,
since it's not technically a fix. But I'd like to make an exception in
this case because:

- it's intended to go in very early in the v3.16-rc series (or even
pre-rc1);

- it's a fairly small change;

- the impact is limited to a single SoC and a single device;

- the only reason that it didn't go in earlier is because it "slipped
through the cracks," rather than for any technical reason.

Basic build, boot, and PM test logs are available here:

http://www.pwsan.com/omap/testlogs/hwmod-a-v3.16-rc/20140615201307/

49 files changed:
Documentation/devicetree/bindings/clock/sunxi.txt
Documentation/devicetree/bindings/clock/ti/apll.txt
Documentation/devicetree/bindings/clock/ti/dpll.txt
Documentation/devicetree/bindings/clock/ti/dra7-atl.txt [new file with mode: 0644]
Documentation/devicetree/bindings/clock/ti/gate.txt
Documentation/devicetree/bindings/clock/ti/interface.txt
MAINTAINERS
Makefile
arch/arm/boot/dts/dra7xx-clocks.dtsi
arch/arm/boot/dts/omap3-beagle-xm.dts
arch/arm/boot/dts/omap3-evm-common.dtsi
arch/arm/boot/dts/omap3-n900.dts
arch/arm/boot/dts/omap54xx-clocks.dtsi
arch/arm/mach-omap2/clkt2xxx_virt_prcm_set.c
arch/arm/mach-omap2/clock.h
arch/arm/mach-omap2/clock2xxx.h
arch/arm/mach-omap2/dpll3xxx.c
block/blk-core.c
drivers/block/nvme-core.c
drivers/block/nvme-scsi.c
drivers/clk/sunxi/Makefile
drivers/clk/sunxi/clk-a10-hosc.c [new file with mode: 0644]
drivers/clk/sunxi/clk-a20-gmac.c [new file with mode: 0644]
drivers/clk/sunxi/clk-sun6i-apb0-gates.c [new file with mode: 0644]
drivers/clk/sunxi/clk-sun6i-apb0.c [new file with mode: 0644]
drivers/clk/sunxi/clk-sun6i-ar100.c [new file with mode: 0644]
drivers/clk/sunxi/clk-sunxi.c
drivers/clk/ti/Makefile
drivers/clk/ti/apll.c
drivers/clk/ti/clk-2xxx.c [new file with mode: 0644]
drivers/clk/ti/clk-54xx.c
drivers/clk/ti/clk-7xx.c
drivers/clk/ti/clk-dra7-atl.c [new file with mode: 0644]
drivers/clk/ti/dpll.c
drivers/clk/ti/gate.c
drivers/clk/ti/interface.c
drivers/net/vxlan.c
include/dt-bindings/clk/ti-dra7-atl.h [new file with mode: 0644]
include/linux/clk/ti.h
include/linux/netdev_features.h
include/linux/netdevice.h
include/linux/nvme.h
include/linux/skbuff.h
include/net/udp.h
include/uapi/linux/nvme.h
net/core/datagram.c
net/core/skbuff.c
net/ipv4/udp.c
net/sctp/sysctl.c

index a5160d8cbb5f7e1c020e925da23d491ca3b3a0a4..b9ec668bfe6263de85f09ccd2eb06769849c0178 100644 (file)
@@ -20,12 +20,15 @@ Required properties:
        "allwinner,sun5i-a13-ahb-gates-clk" - for the AHB gates on A13
        "allwinner,sun5i-a10s-ahb-gates-clk" - for the AHB gates on A10s
        "allwinner,sun7i-a20-ahb-gates-clk" - for the AHB gates on A20
+       "allwinner,sun6i-a31-ar100-clk" - for the AR100 on A31
        "allwinner,sun6i-a31-ahb1-mux-clk" - for the AHB1 multiplexer on A31
        "allwinner,sun6i-a31-ahb1-gates-clk" - for the AHB1 gates on A31
        "allwinner,sun4i-a10-apb0-clk" - for the APB0 clock
+       "allwinner,sun6i-a31-apb0-clk" - for the APB0 clock on A31
        "allwinner,sun4i-a10-apb0-gates-clk" - for the APB0 gates on A10
        "allwinner,sun5i-a13-apb0-gates-clk" - for the APB0 gates on A13
        "allwinner,sun5i-a10s-apb0-gates-clk" - for the APB0 gates on A10s
+       "allwinner,sun6i-a31-apb0-gates-clk" - for the APB0 gates on A31
        "allwinner,sun7i-a20-apb0-gates-clk" - for the APB0 gates on A20
        "allwinner,sun4i-a10-apb1-clk" - for the APB1 clock
        "allwinner,sun4i-a10-apb1-mux-clk" - for the APB1 clock muxing
@@ -41,6 +44,7 @@ Required properties:
        "allwinner,sun7i-a20-gmac-clk" - for the GMAC clock module on A20/A31
        "allwinner,sun4i-a10-usb-clk" - for usb gates + resets on A10 / A20
        "allwinner,sun5i-a13-usb-clk" - for usb gates + resets on A13
+       "allwinner,sun6i-a31-usb-clk" - for usb gates + resets on A31
 
 Required properties for all clocks:
 - reg : shall be the control register address for the clock.
index 7faf5a68b3beeba44a767836fdeb6dc64653a5b3..ade4dd4c30f0e12804a94845b71ee462e30f1d99 100644 (file)
@@ -14,18 +14,32 @@ a subtype of a DPLL [2], although a simplified one at that.
 [2] Documentation/devicetree/bindings/clock/ti/dpll.txt
 
 Required properties:
-- compatible : shall be "ti,dra7-apll-clock"
+- compatible : shall be "ti,dra7-apll-clock" or "ti,omap2-apll-clock"
 - #clock-cells : from common clock binding; shall be set to 0.
 - clocks : link phandles of parent clocks (clk-ref and clk-bypass)
 - reg : address and length of the register set for controlling the APLL.
   It contains the information of registers in the following order:
-       "control" - contains the control register base address
-       "idlest" - contains the idlest register base address
+       "control" - contains the control register offset
+       "idlest" - contains the idlest register offset
+       "autoidle" - contains the autoidle register offset (OMAP2 only)
+- ti,clock-frequency : static clock frequency for the clock (OMAP2 only)
+- ti,idlest-shift : bit-shift for the idlest field (OMAP2 only)
+- ti,bit-shift : bit-shift for enable and autoidle fields (OMAP2 only)
 
 Examples:
-       apll_pcie_ck: apll_pcie_ck@4a008200 {
+       apll_pcie_ck: apll_pcie_ck {
                #clock-cells = <0>;
                clocks = <&apll_pcie_in_clk_mux>, <&dpll_pcie_ref_ck>;
-               reg = <0x4a00821c 0x4>, <0x4a008220 0x4>;
+               reg = <0x021c>, <0x0220>;
                compatible = "ti,dra7-apll-clock";
        };
+
+       apll96_ck: apll96_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap2-apll-clock";
+               clocks = <&sys_ck>;
+               ti,bit-shift = <2>;
+               ti,idlest-shift = <8>;
+               ti,clock-frequency = <96000000>;
+               reg = <0x0500>, <0x0530>, <0x0520>;
+       };
index 30bfdb7c9f18a7137a5e9e7de12accfb4e82f6f2..df57009ff8e74ff48693220908f3a8f1581e15f9 100644 (file)
@@ -24,12 +24,14 @@ Required properties:
                "ti,omap4-dpll-core-clock",
                "ti,omap4-dpll-m4xen-clock",
                "ti,omap4-dpll-j-type-clock",
+               "ti,omap5-mpu-dpll-clock",
                "ti,am3-dpll-no-gate-clock",
                "ti,am3-dpll-j-type-clock",
                "ti,am3-dpll-no-gate-j-type-clock",
                "ti,am3-dpll-clock",
                "ti,am3-dpll-core-clock",
                "ti,am3-dpll-x2-clock",
+               "ti,omap2-dpll-core-clock",
 
 - #clock-cells : from common clock binding; shall be set to 0.
 - clocks : link phandles of parent clocks, first entry lists reference clock
@@ -41,6 +43,7 @@ Required properties:
        "mult-div1" - contains the multiplier / divider register base address
        "autoidle" - contains the autoidle register base address (optional)
   ti,am3-* dpll types do not have autoidle register
+  ti,omap2-* dpll type does not support idlest / autoidle registers
 
 Optional properties:
 - DPLL mode setting - defining any one or more of the following overrides
@@ -73,3 +76,10 @@ Examples:
                clocks = <&sys_clkin_ck>, <&sys_clkin_ck>;
                reg = <0x90>, <0x5c>, <0x68>;
        };
+
+       dpll_ck: dpll_ck {
+               #clock-cells = <0>;
+               compatible = "ti,omap2-dpll-core-clock";
+               clocks = <&sys_ck>, <&sys_ck>;
+               reg = <0x0500>, <0x0540>;
+       };
diff --git a/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt b/Documentation/devicetree/bindings/clock/ti/dra7-atl.txt
new file mode 100644 (file)
index 0000000..585e8c1
--- /dev/null
@@ -0,0 +1,96 @@
+Device Tree Clock bindings for ATL (Audio Tracking Logic) of DRA7 SoC.
+
+The ATL IP is used to generate clock to be used to synchronize baseband and
+audio codec. A single ATL IP provides four ATL clock instances sharing the same
+functional clock but can be configured to provide different clocks.
+ATL can maintain a clock averages to some desired frequency based on the bws/aws
+signals - can compensate the drift between the two ws signal.
+
+In order to provide the support for ATL and it's output clocks (which can be used
+internally within the SoC or external components) two sets of bindings is needed:
+
+Clock tree binding:
+This binding uses the common clock binding[1].
+To be able to integrate the ATL clocks with DT clock tree.
+Provides ccf level representation of the ATL clocks to be used by drivers.
+Since the clock instances are part of a single IP this binding is used as a node
+for the DT clock tree, the IP driver is needed to handle the actual configuration
+of the IP.
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "ti,dra7-atl-clock"
+- #clock-cells : from common clock binding; shall be set to 0.
+- clocks : link phandles to functional clock of ATL
+
+Binding for the IP driver:
+This binding is used to configure the IP driver which is going to handle the
+configuration of the IP for the ATL clock instances.
+
+Required properties:
+- compatible : shall be "ti,dra7-atl"
+- reg : base address for the ATL IP
+- ti,provided-clocks : List of phandles to the clocks associated with the ATL
+- clocks : link phandles to functional clock of ATL
+- clock-names : Shall be set to "fck"
+- ti,hwmods : Shall be set to "atl"
+
+Optional properties:
+Configuration of ATL instances:
+- atl{0/1/2/3} {
+       - bws : Baseband word select signal selection
+       - aws : Audio word select signal selection
+};
+
+For valid word select signals, see the dt-bindings/clk/ti-dra7-atl.h include
+file.
+
+Examples:
+/* clock bindings for atl provided clocks */
+atl_clkin0_ck: atl_clkin0_ck {
+       #clock-cells = <0>;
+       compatible = "ti,dra7-atl-clock";
+       clocks = <&atl_gfclk_mux>;
+};
+
+atl_clkin1_ck: atl_clkin1_ck {
+       #clock-cells = <0>;
+       compatible = "ti,dra7-atl-clock";
+       clocks = <&atl_gfclk_mux>;
+};
+
+atl_clkin2_ck: atl_clkin2_ck {
+       #clock-cells = <0>;
+       compatible = "ti,dra7-atl-clock";
+       clocks = <&atl_gfclk_mux>;
+};
+
+atl_clkin3_ck: atl_clkin3_ck {
+       #clock-cells = <0>;
+       compatible = "ti,dra7-atl-clock";
+       clocks = <&atl_gfclk_mux>;
+};
+
+/* binding for the IP */
+atl: atl@4843c000 {
+       compatible = "ti,dra7-atl";
+       reg = <0x4843c000 0x3ff>;
+       ti,hwmods = "atl";
+       ti,provided-clocks = <&atl_clkin0_ck>, <&atl_clkin1_ck>,
+                               <&atl_clkin2_ck>, <&atl_clkin3_ck>;
+       clocks = <&atl_gfclk_mux>;
+       clock-names = "fck";
+       status = "disabled";
+};
+
+#include <dt-bindings/clk/ti-dra7-atl.h>
+
+&atl {
+       status = "okay";
+
+       atl2 {
+               bws = <DRA7_ATL_WS_MCASP2_FSX>;
+               aws = <DRA7_ATL_WS_MCASP3_FSX>;
+       };
+};
index 125281aaa4ca0390713d92b6714c135098604b6d..03f8fdee62a7e3e2c559789eb501f9f12d6542a5 100644 (file)
@@ -25,6 +25,11 @@ Required properties:
                          to map clockdomains properly
   "ti,hsdiv-gate-clock" - gate clock with OMAP36xx specific hardware handling,
                          required for a hardware errata
+  "ti,composite-gate-clock" - composite gate clock, to be part of composite
+                             clock
+  "ti,composite-no-wait-gate-clock" - composite gate clock that does not wait
+                                     for clock to be active before returning
+                                     from clk_enable()
 - #clock-cells : from common clock binding; shall be set to 0
 - clocks : link to phandle of parent clock
 - reg : offset for register controlling adjustable gate, not needed for
@@ -41,7 +46,7 @@ Examples:
                #clock-cells = <0>;
                compatible = "ti,gate-clock";
                clocks = <&core_96m_fck>;
-               reg = <0x48004a00 0x4>;
+               reg = <0x0a00>;
                ti,bit-shift = <25>;
        };
 
@@ -57,7 +62,7 @@ Examples:
                #clock-cells = <0>;
                compatible = "ti,dss-gate-clock";
                clocks = <&dpll4_m4x2_ck>;
-               reg = <0x48004e00 0x4>;
+               reg = <0x0e00>;
                ti,bit-shift = <0>;
        };
 
@@ -65,7 +70,7 @@ Examples:
                #clock-cells = <0>;
                compatible = "ti,am35xx-gate-clock";
                clocks = <&ipss_ick>;
-               reg = <0x4800259c 0x4>;
+               reg = <0x059c>;
                ti,bit-shift = <1>;
        };
 
@@ -80,6 +85,22 @@ Examples:
                compatible = "ti,hsdiv-gate-clock";
                clocks = <&dpll4_m2x2_mul_ck>;
                ti,bit-shift = <0x1b>;
-               reg = <0x48004d00 0x4>;
+               reg = <0x0d00>;
                ti,set-bit-to-disable;
        };
+
+       vlynq_gate_fck: vlynq_gate_fck {
+               #clock-cells = <0>;
+               compatible = "ti,composite-gate-clock";
+               clocks = <&core_ck>;
+               ti,bit-shift = <3>;
+               reg = <0x0200>;
+       };
+
+       sys_clkout2_src_gate: sys_clkout2_src_gate {
+               #clock-cells = <0>;
+               compatible = "ti,composite-no-wait-gate-clock";
+               clocks = <&core_ck>;
+               ti,bit-shift = <15>;
+               reg = <0x0070>;
+       };
index 064e8caccac37141428ca2ce0cfaed80fb4daacf..3111a409fea6cebb739a01592874d2c88d56328b 100644 (file)
@@ -21,6 +21,8 @@ Required properties:
   "ti,omap3-dss-interface-clock" - interface clock with DSS specific HW handling
   "ti,omap3-ssi-interface-clock" - interface clock with SSI specific HW handling
   "ti,am35xx-interface-clock" - interface clock with AM35xx specific HW handling
+  "ti,omap2430-interface-clock" - interface clock with OMAP2430 specific HW
+                                 handling
 - #clock-cells : from common clock binding; shall be set to 0
 - clocks : link to phandle of parent clock
 - reg : base address for the control register
index 055f95238d8823a70e18fc33e3c0a407a5a5d123..134483f206e42661947e0bc4b84ef09ab07abd1b 100644 (file)
@@ -2594,7 +2594,7 @@ S:        Supported
 F:     drivers/infiniband/hw/cxgb3/
 
 CXGB4 ETHERNET DRIVER (CXGB4)
-M:     Dimitris Michailidis <dm@chelsio.com>
+M:     Hariprasad S <hariprasad@chelsio.com>
 L:     netdev@vger.kernel.org
 W:     http://www.chelsio.com
 S:     Supported
index 7680d7c707301b7a30368c66e3116ef42fd026b1..97b286128c1e869a2c69bc4a411ea19f6ef74d8b 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 3
-PATCHLEVEL = 15
+PATCHLEVEL = 16
 SUBLEVEL = 0
-EXTRAVERSION =
+EXTRAVERSION = -rc1
 NAME = Shuffling Zombie Juror
 
 # *DOCUMENTATION*
index c7676871d9c0240032261ed40f0db7c431a583d8..b03cfe49d22be4bce3809d606ccec17658f4d07c 100644 (file)
@@ -26,7 +26,7 @@
                clock-frequency = <0>;
        };
 
-       atlclkin3_ck: atlclkin3_ck {
+       atl_clkin3_ck: atl_clkin3_ck {
                #clock-cells = <0>;
                compatible = "fixed-clock";
                clock-frequency = <0>;
 
        dpll_mpu_ck: dpll_mpu_ck {
                #clock-cells = <0>;
-               compatible = "ti,omap4-dpll-clock";
+               compatible = "ti,omap5-mpu-dpll-clock";
                clocks = <&sys_clkin1>, <&mpu_dpll_hs_clk_div>;
                reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>;
        };
        mcasp1_ahclkr_mux: mcasp1_ahclkr_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
-               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <28>;
                reg = <0x0550>;
        };
        mcasp1_ahclkx_mux: mcasp1_ahclkx_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
-               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <24>;
                reg = <0x0550>;
        };
        mcasp2_ahclkr_mux: mcasp2_ahclkr_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
-               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <28>;
                reg = <0x1860>;
        };
        mcasp2_ahclkx_mux: mcasp2_ahclkx_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
-               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <24>;
                reg = <0x1860>;
        };
        mcasp3_ahclkx_mux: mcasp3_ahclkx_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
-               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <24>;
                reg = <0x1868>;
        };
        mcasp4_ahclkx_mux: mcasp4_ahclkx_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
-               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <24>;
                reg = <0x1898>;
        };
        mcasp5_ahclkx_mux: mcasp5_ahclkx_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
-               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <24>;
                reg = <0x1878>;
        };
        mcasp6_ahclkx_mux: mcasp6_ahclkx_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
-               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <24>;
                reg = <0x1904>;
        };
        mcasp7_ahclkx_mux: mcasp7_ahclkx_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
-               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <24>;
                reg = <0x1908>;
        };
        mcasp8_ahclk_mux: mcasp8_ahclk_mux {
                #clock-cells = <0>;
                compatible = "ti,mux-clock";
-               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atlclkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
+               clocks = <&abe_24m_fclk>, <&abe_sys_clk_div>, <&func_24m_clk>, <&atl_clkin3_ck>, <&atl_clkin2_ck>, <&atl_clkin1_ck>, <&atl_clkin0_ck>, <&sys_clkin2>, <&ref_clkin0_ck>, <&ref_clkin1_ck>, <&ref_clkin2_ck>, <&ref_clkin3_ck>, <&mlb_clk>, <&mlbp_clk>;
                ti,bit-shift = <22>;
                reg = <0x1890>;
        };
index cf0be662297e964186c378788ddbdfa00ca80664..1becefce821b5ca59e0d66e330b4e2884db61d57 100644 (file)
                        codec {
                        };
                };
+
+               twl_power: power {
+                       compatible = "ti,twl4030-power-beagleboard-xm", "ti,twl4030-power-idle-osc-off";
+                       ti,use_poweroff;
+               };
        };
 };
 
 };
 
 &uart3 {
+       interrupts-extended = <&intc 74 &omap3_pmx_core OMAP3_UART3_RX>;
        pinctrl-names = "default";
        pinctrl-0 = <&uart3_pins>;
 };
index 8ae8f007c8adcc4ff6c5658d76d6b9080e4bb029..c8747c7f1cc8fb66404639e1eb24a61d28e4e1de 100644 (file)
        gpios = <&twl_gpio 18 GPIO_ACTIVE_LOW>;
 };
 
+&twl {
+       twl_power: power {
+               compatible = "ti,twl4030-power-omap3-evm", "ti,twl4030-power-idle";
+               ti,use_poweroff;
+       };
+};
+
 &i2c2 {
        clock-frequency = <400000>;
 };
index ae8ae3f4f9bfd25870735289c175325d0f9bd440..1fe45d1f75ec8d52aa8dd59a1e344a931fc32576 100644 (file)
                compatible = "ti,twl4030-audio";
                ti,enable-vibra = <1>;
        };
+
+       twl_power: power {
+               compatible = "ti,twl4030-power-n900", "ti,twl4030-power-idle-osc-off";
+               ti,use_poweroff;
+       };
 };
 
 &twl_keypad {
index aeb142ce8e9d34ffa0dd1565a21f2211a8b11917..e67a23b5d7884725290b6348a54a97f3427ccbc3 100644 (file)
 
        dpll_mpu_ck: dpll_mpu_ck {
                #clock-cells = <0>;
-               compatible = "ti,omap4-dpll-clock";
+               compatible = "ti,omap5-mpu-dpll-clock";
                clocks = <&sys_clkin>, <&mpu_dpll_hs_clk_div>;
                reg = <0x0160>, <0x0164>, <0x016c>, <0x0168>;
        };
index b935ed2922d806725cd6916ce18bd429acf8e926..85e0b0c06718f0e8f1127192bfd65d5a2d4210ce 100644 (file)
@@ -208,3 +208,56 @@ void omap2xxx_clkt_vps_late_init(void)
                clk_put(c);
        }
 }
+
+#ifdef CONFIG_OF
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+
+static const struct clk_ops virt_prcm_set_ops = {
+       .recalc_rate    = &omap2_table_mpu_recalc,
+       .set_rate       = &omap2_select_table_rate,
+       .round_rate     = &omap2_round_to_table_rate,
+};
+
+/**
+ * omap2xxx_clkt_vps_init - initialize virt_prcm_set clock
+ *
+ * Does a manual init for the virtual prcm DVFS clock for OMAP2. This
+ * function is called only from omap2 DT clock init, as the virtual
+ * node is not modelled in the DT clock data.
+ */
+void omap2xxx_clkt_vps_init(void)
+{
+       struct clk_init_data init = { NULL };
+       struct clk_hw_omap *hw = NULL;
+       struct clk *clk;
+       const char *parent_name = "mpu_ck";
+       struct clk_lookup *lookup = NULL;
+
+       omap2xxx_clkt_vps_late_init();
+       omap2xxx_clkt_vps_check_bootloader_rates();
+
+       hw = kzalloc(sizeof(*hw), GFP_KERNEL);
+       lookup = kzalloc(sizeof(*lookup), GFP_KERNEL);
+       if (!hw || !lookup)
+               goto cleanup;
+       init.name = "virt_prcm_set";
+       init.ops = &virt_prcm_set_ops;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       hw->hw.init = &init;
+
+       clk = clk_register(NULL, &hw->hw);
+
+       lookup->dev_id = NULL;
+       lookup->con_id = "cpufreq_ck";
+       lookup->clk = clk;
+
+       clkdev_add(lookup);
+       return;
+cleanup:
+       kfree(hw);
+       kfree(lookup);
+}
+#endif
index bda767a9dea862d7223d86d1a59c0b1505e091f9..12f54d428d7c6f3ece2e4c5c6244c8cb9841d194 100644 (file)
@@ -178,17 +178,6 @@ struct clksel {
        const struct clksel_rate *rates;
 };
 
-struct clk_hw_omap_ops {
-       void                    (*find_idlest)(struct clk_hw_omap *oclk,
-                                       void __iomem **idlest_reg,
-                                       u8 *idlest_bit, u8 *idlest_val);
-       void                    (*find_companion)(struct clk_hw_omap *oclk,
-                                       void __iomem **other_reg,
-                                       u8 *other_bit);
-       void                    (*allow_idle)(struct clk_hw_omap *oclk);
-       void                    (*deny_idle)(struct clk_hw_omap *oclk);
-};
-
 unsigned long omap_fixed_divisor_recalc(struct clk_hw *hw,
                                        unsigned long parent_rate);
 
@@ -279,8 +268,6 @@ extern const struct clk_hw_omap_ops clkhwops_omap3430es2_hsotgusb_wait;
 extern const struct clk_hw_omap_ops clkhwops_am35xx_ipss_module_wait;
 extern const struct clk_hw_omap_ops clkhwops_apll54;
 extern const struct clk_hw_omap_ops clkhwops_apll96;
-extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
-extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
 
 /* clksel_rate blocks shared between OMAP44xx and AM33xx */
 extern const struct clksel_rate div_1_0_rates[];
index 539dc08afbbaf3cb93536f600a5bb930b35d7d55..45f41a4116031be4cbb722bc2db63cc33841c31f 100644 (file)
@@ -21,10 +21,6 @@ unsigned long omap2xxx_sys_clk_recalc(struct clk_hw *clk,
                                      unsigned long parent_rate);
 unsigned long omap2_osc_clk_recalc(struct clk_hw *clk,
                                   unsigned long parent_rate);
-unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
-                                   unsigned long parent_rate);
-int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
-                            unsigned long parent_rate);
 void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
 unsigned long omap2_clk_apll54_recalc(struct clk_hw *hw,
                                      unsigned long parent_rate);
index fcd8036af91041750f529c28f99d665dce86a04f..6d7ba37e225735d49e262723bc6927e0e0b52ed1 100644 (file)
@@ -319,6 +319,15 @@ static int omap3_noncore_dpll_program(struct clk_hw_omap *clk, u16 freqsel)
 
        /* Set DPLL multiplier, divider */
        v = omap2_clk_readl(clk, dd->mult_div1_reg);
+
+       /* Handle Duty Cycle Correction */
+       if (dd->dcc_mask) {
+               if (dd->last_rounded_rate >= dd->dcc_rate)
+                       v |= dd->dcc_mask; /* Enable DCC */
+               else
+                       v &= ~dd->dcc_mask; /* Disable DCC */
+       }
+
        v &= ~(dd->mult_mask | dd->div1_mask);
        v |= dd->last_rounded_m << __ffs(dd->mult_mask);
        v |= (dd->last_rounded_n - 1) << __ffs(dd->div1_mask);
index 9aca8c71e70b0bf8d8936462f1517a62da6c8432..f6f6b9af3e3f541e78c8079cbbc7031a09efeb4d 100644 (file)
@@ -43,6 +43,7 @@
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_rq_remap);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_bio_complete);
+EXPORT_TRACEPOINT_SYMBOL_GPL(block_split);
 EXPORT_TRACEPOINT_SYMBOL_GPL(block_unplug);
 
 DEFINE_IDA(blk_queue_ida);
index a842c71dcc211b8f036de693633345492f9a21e6..02351e2171651dc47585d4f5a25a9b5e85d303f3 100644 (file)
  * 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #include <linux/nvme.h>
 #include <scsi/sg.h>
 #include <asm-generic/io-64-nonatomic-lo-hi.h>
 
-#define NVME_Q_DEPTH 1024
+#include <trace/events/block.h>
+
+#define NVME_Q_DEPTH           1024
 #define SQ_SIZE(depth)         (depth * sizeof(struct nvme_command))
 #define CQ_SIZE(depth)         (depth * sizeof(struct nvme_completion))
-#define ADMIN_TIMEOUT  (60 * HZ)
-#define IOD_TIMEOUT    (4 * NVME_IO_TIMEOUT)
+#define ADMIN_TIMEOUT          (admin_timeout * HZ)
+#define IOD_TIMEOUT            (retry_time * HZ)
+
+static unsigned char admin_timeout = 60;
+module_param(admin_timeout, byte, 0644);
+MODULE_PARM_DESC(admin_timeout, "timeout in seconds for admin commands");
 
-unsigned char io_timeout = 30;
-module_param(io_timeout, byte, 0644);
+unsigned char nvme_io_timeout = 30;
+module_param_named(io_timeout, nvme_io_timeout, byte, 0644);
 MODULE_PARM_DESC(io_timeout, "timeout in seconds for I/O");
 
+static unsigned char retry_time = 30;
+module_param(retry_time, byte, 0644);
+MODULE_PARM_DESC(retry_time, "time in seconds to retry failed I/O");
+
 static int nvme_major;
 module_param(nvme_major, int, 0);
 
@@ -67,6 +73,7 @@ static LIST_HEAD(dev_list);
 static struct task_struct *nvme_thread;
 static struct workqueue_struct *nvme_workq;
 static wait_queue_head_t nvme_kthread_wait;
+static struct notifier_block nvme_nb;
 
 static void nvme_reset_failed_dev(struct work_struct *ws);
 
@@ -199,16 +206,13 @@ static int alloc_cmdid_killable(struct nvme_queue *nvmeq, void *ctx,
 #define CMD_CTX_CANCELLED      (0x30C + CMD_CTX_BASE)
 #define CMD_CTX_COMPLETED      (0x310 + CMD_CTX_BASE)
 #define CMD_CTX_INVALID                (0x314 + CMD_CTX_BASE)
-#define CMD_CTX_FLUSH          (0x318 + CMD_CTX_BASE)
-#define CMD_CTX_ABORT          (0x31C + CMD_CTX_BASE)
+#define CMD_CTX_ABORT          (0x318 + CMD_CTX_BASE)
 
 static void special_completion(struct nvme_queue *nvmeq, void *ctx,
                                                struct nvme_completion *cqe)
 {
        if (ctx == CMD_CTX_CANCELLED)
                return;
-       if (ctx == CMD_CTX_FLUSH)
-               return;
        if (ctx == CMD_CTX_ABORT) {
                ++nvmeq->dev->abort_limit;
                return;
@@ -247,8 +251,9 @@ static void *free_cmdid(struct nvme_queue *nvmeq, int cmdid,
        void *ctx;
        struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
 
-       if (cmdid >= nvmeq->q_depth) {
-               *fn = special_completion;
+       if (cmdid >= nvmeq->q_depth || !info[cmdid].fn) {
+               if (fn)
+                       *fn = special_completion;
                return CMD_CTX_INVALID;
        }
        if (fn)
@@ -281,9 +286,17 @@ static struct nvme_queue *raw_nvmeq(struct nvme_dev *dev, int qid)
 
 static struct nvme_queue *get_nvmeq(struct nvme_dev *dev) __acquires(RCU)
 {
+       struct nvme_queue *nvmeq;
        unsigned queue_id = get_cpu_var(*dev->io_queue);
+
        rcu_read_lock();
-       return rcu_dereference(dev->queues[queue_id]);
+       nvmeq = rcu_dereference(dev->queues[queue_id]);
+       if (nvmeq)
+               return nvmeq;
+
+       rcu_read_unlock();
+       put_cpu_var(*dev->io_queue);
+       return NULL;
 }
 
 static void put_nvmeq(struct nvme_queue *nvmeq) __releases(RCU)
@@ -295,8 +308,15 @@ static void put_nvmeq(struct nvme_queue *nvmeq) __releases(RCU)
 static struct nvme_queue *lock_nvmeq(struct nvme_dev *dev, int q_idx)
                                                        __acquires(RCU)
 {
+       struct nvme_queue *nvmeq;
+
        rcu_read_lock();
-       return rcu_dereference(dev->queues[q_idx]);
+       nvmeq = rcu_dereference(dev->queues[q_idx]);
+       if (nvmeq)
+               return nvmeq;
+
+       rcu_read_unlock();
+       return NULL;
 }
 
 static void unlock_nvmeq(struct nvme_queue *nvmeq) __releases(RCU)
@@ -387,25 +407,30 @@ void nvme_free_iod(struct nvme_dev *dev, struct nvme_iod *iod)
 static void nvme_start_io_acct(struct bio *bio)
 {
        struct gendisk *disk = bio->bi_bdev->bd_disk;
-       const int rw = bio_data_dir(bio);
-       int cpu = part_stat_lock();
-       part_round_stats(cpu, &disk->part0);
-       part_stat_inc(cpu, &disk->part0, ios[rw]);
-       part_stat_add(cpu, &disk->part0, sectors[rw], bio_sectors(bio));
-       part_inc_in_flight(&disk->part0, rw);
-       part_stat_unlock();
+       if (blk_queue_io_stat(disk->queue)) {
+               const int rw = bio_data_dir(bio);
+               int cpu = part_stat_lock();
+               part_round_stats(cpu, &disk->part0);
+               part_stat_inc(cpu, &disk->part0, ios[rw]);
+               part_stat_add(cpu, &disk->part0, sectors[rw],
+                                                       bio_sectors(bio));
+               part_inc_in_flight(&disk->part0, rw);
+               part_stat_unlock();
+       }
 }
 
 static void nvme_end_io_acct(struct bio *bio, unsigned long start_time)
 {
        struct gendisk *disk = bio->bi_bdev->bd_disk;
-       const int rw = bio_data_dir(bio);
-       unsigned long duration = jiffies - start_time;
-       int cpu = part_stat_lock();
-       part_stat_add(cpu, &disk->part0, ticks[rw], duration);
-       part_round_stats(cpu, &disk->part0);
-       part_dec_in_flight(&disk->part0, rw);
-       part_stat_unlock();
+       if (blk_queue_io_stat(disk->queue)) {
+               const int rw = bio_data_dir(bio);
+               unsigned long duration = jiffies - start_time;
+               int cpu = part_stat_lock();
+               part_stat_add(cpu, &disk->part0, ticks[rw], duration);
+               part_round_stats(cpu, &disk->part0);
+               part_dec_in_flight(&disk->part0, rw);
+               part_stat_unlock();
+       }
 }
 
 static void bio_completion(struct nvme_queue *nvmeq, void *ctx,
@@ -414,6 +439,7 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx,
        struct nvme_iod *iod = ctx;
        struct bio *bio = iod->private;
        u16 status = le16_to_cpup(&cqe->status) >> 1;
+       int error = 0;
 
        if (unlikely(status)) {
                if (!(status & NVME_SC_DNR ||
@@ -426,6 +452,7 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx,
                        wake_up(&nvmeq->sq_full);
                        return;
                }
+               error = -EIO;
        }
        if (iod->nents) {
                dma_unmap_sg(nvmeq->q_dmadev, iod->sg, iod->nents,
@@ -433,10 +460,9 @@ static void bio_completion(struct nvme_queue *nvmeq, void *ctx,
                nvme_end_io_acct(bio, iod->start_time);
        }
        nvme_free_iod(nvmeq->dev, iod);
-       if (status)
-               bio_endio(bio, -EIO);
-       else
-               bio_endio(bio, 0);
+
+       trace_block_bio_complete(bdev_get_queue(bio->bi_bdev), bio, error);
+       bio_endio(bio, error);
 }
 
 /* length is in bytes.  gfp flags indicates whether we may sleep. */
@@ -525,6 +551,8 @@ static int nvme_split_and_submit(struct bio *bio, struct nvme_queue *nvmeq,
        if (!split)
                return -ENOMEM;
 
+       trace_block_split(bdev_get_queue(bio->bi_bdev), bio,
+                                       split->bi_iter.bi_sector);
        bio_chain(split, bio);
 
        if (!waitqueue_active(&nvmeq->sq_full))
@@ -627,16 +655,6 @@ static int nvme_submit_flush(struct nvme_queue *nvmeq, struct nvme_ns *ns,
        return 0;
 }
 
-int nvme_submit_flush_data(struct nvme_queue *nvmeq, struct nvme_ns *ns)
-{
-       int cmdid = alloc_cmdid(nvmeq, (void *)CMD_CTX_FLUSH,
-                                       special_completion, NVME_IO_TIMEOUT);
-       if (unlikely(cmdid < 0))
-               return cmdid;
-
-       return nvme_submit_flush(nvmeq, ns, cmdid);
-}
-
 static int nvme_submit_iod(struct nvme_queue *nvmeq, struct nvme_iod *iod)
 {
        struct bio *bio = iod->private;
@@ -652,7 +670,7 @@ static int nvme_submit_iod(struct nvme_queue *nvmeq, struct nvme_iod *iod)
 
        if (bio->bi_rw & REQ_DISCARD)
                return nvme_submit_discard(nvmeq, ns, bio, iod, cmdid);
-       if ((bio->bi_rw & REQ_FLUSH) && !iod->nents)
+       if (bio->bi_rw & REQ_FLUSH)
                return nvme_submit_flush(nvmeq, ns, cmdid);
 
        control = 0;
@@ -686,6 +704,26 @@ static int nvme_submit_iod(struct nvme_queue *nvmeq, struct nvme_iod *iod)
        return 0;
 }
 
+static int nvme_split_flush_data(struct nvme_queue *nvmeq, struct bio *bio)
+{
+       struct bio *split = bio_clone(bio, GFP_ATOMIC);
+       if (!split)
+               return -ENOMEM;
+
+       split->bi_iter.bi_size = 0;
+       split->bi_phys_segments = 0;
+       bio->bi_rw &= ~REQ_FLUSH;
+       bio_chain(split, bio);
+
+       if (!waitqueue_active(&nvmeq->sq_full))
+               add_wait_queue(&nvmeq->sq_full, &nvmeq->sq_cong_wait);
+       bio_list_add(&nvmeq->sq_cong, split);
+       bio_list_add(&nvmeq->sq_cong, bio);
+       wake_up_process(nvme_thread);
+
+       return 0;
+}
+
 /*
  * Called with local interrupts disabled and the q_lock held.  May not sleep.
  */
@@ -696,11 +734,8 @@ static int nvme_submit_bio_queue(struct nvme_queue *nvmeq, struct nvme_ns *ns,
        int psegs = bio_phys_segments(ns->queue, bio);
        int result;
 
-       if ((bio->bi_rw & REQ_FLUSH) && psegs) {
-               result = nvme_submit_flush_data(nvmeq, ns);
-               if (result)
-                       return result;
-       }
+       if ((bio->bi_rw & REQ_FLUSH) && psegs)
+               return nvme_split_flush_data(nvmeq, bio);
 
        iod = nvme_alloc_iod(psegs, bio->bi_iter.bi_size, GFP_ATOMIC);
        if (!iod)
@@ -795,7 +830,6 @@ static void nvme_make_request(struct request_queue *q, struct bio *bio)
        int result = -EBUSY;
 
        if (!nvmeq) {
-               put_nvmeq(NULL);
                bio_endio(bio, -EIO);
                return;
        }
@@ -870,10 +904,8 @@ static int nvme_submit_sync_cmd(struct nvme_dev *dev, int q_idx,
        struct nvme_queue *nvmeq;
 
        nvmeq = lock_nvmeq(dev, q_idx);
-       if (!nvmeq) {
-               unlock_nvmeq(nvmeq);
+       if (!nvmeq)
                return -ENODEV;
-       }
 
        cmdinfo.task = current;
        cmdinfo.status = -EINTR;
@@ -898,9 +930,10 @@ static int nvme_submit_sync_cmd(struct nvme_dev *dev, int q_idx,
 
        if (cmdinfo.status == -EINTR) {
                nvmeq = lock_nvmeq(dev, q_idx);
-               if (nvmeq)
+               if (nvmeq) {
                        nvme_abort_command(nvmeq, cmdid);
-               unlock_nvmeq(nvmeq);
+                       unlock_nvmeq(nvmeq);
+               }
                return -EINTR;
        }
 
@@ -1358,7 +1391,8 @@ static int nvme_wait_ready(struct nvme_dev *dev, u64 cap, bool enabled)
                        return -EINTR;
                if (time_after(jiffies, timeout)) {
                        dev_err(&dev->pci_dev->dev,
-                               "Device not ready; aborting initialisation\n");
+                               "Device not ready; aborting %s\n", enabled ?
+                                               "initialisation" : "reset");
                        return -ENODEV;
                }
        }
@@ -1481,7 +1515,11 @@ struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
                goto put_pages;
        }
 
+       err = -ENOMEM;
        iod = nvme_alloc_iod(count, length, GFP_KERNEL);
+       if (!iod)
+               goto put_pages;
+
        sg = iod->sg;
        sg_init_table(sg, count);
        for (i = 0; i < count; i++) {
@@ -1494,7 +1532,6 @@ struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
        sg_mark_end(&sg[i - 1]);
        iod->nents = count;
 
-       err = -ENOMEM;
        nents = dma_map_sg(&dev->pci_dev->dev, sg, count,
                                write ? DMA_TO_DEVICE : DMA_FROM_DEVICE);
        if (!nents)
@@ -1894,6 +1931,8 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, unsigned nsid,
        blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
        if (dev->max_hw_sectors)
                blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors);
+       if (dev->vwc & NVME_CTRL_VWC_PRESENT)
+               blk_queue_flush(ns->queue, REQ_FLUSH | REQ_FUA);
 
        disk->major = nvme_major;
        disk->first_minor = 0;
@@ -2062,8 +2101,13 @@ static int set_queue_count(struct nvme_dev *dev, int count)
 
        status = nvme_set_features(dev, NVME_FEAT_NUM_QUEUES, q_count, 0,
                                                                &result);
-       if (status)
-               return status < 0 ? -EIO : -EBUSY;
+       if (status < 0)
+               return status;
+       if (status > 0) {
+               dev_err(&dev->pci_dev->dev, "Could not set queue count (%d)\n",
+                                                                       status);
+               return -EBUSY;
+       }
        return min(result & 0xffff, result >> 16) + 1;
 }
 
@@ -2072,14 +2116,25 @@ static size_t db_bar_size(struct nvme_dev *dev, unsigned nr_io_queues)
        return 4096 + ((nr_io_queues + 1) * 8 * dev->db_stride);
 }
 
+static void nvme_cpu_workfn(struct work_struct *work)
+{
+       struct nvme_dev *dev = container_of(work, struct nvme_dev, cpu_work);
+       if (dev->initialized)
+               nvme_assign_io_queues(dev);
+}
+
 static int nvme_cpu_notify(struct notifier_block *self,
                                unsigned long action, void *hcpu)
 {
-       struct nvme_dev *dev = container_of(self, struct nvme_dev, nb);
+       struct nvme_dev *dev;
+
        switch (action) {
        case CPU_ONLINE:
        case CPU_DEAD:
-               nvme_assign_io_queues(dev);
+               spin_lock(&dev_list_lock);
+               list_for_each_entry(dev, &dev_list, node)
+                       schedule_work(&dev->cpu_work);
+               spin_unlock(&dev_list_lock);
                break;
        }
        return NOTIFY_OK;
@@ -2148,11 +2203,6 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        nvme_free_queues(dev, nr_io_queues + 1);
        nvme_assign_io_queues(dev);
 
-       dev->nb.notifier_call = &nvme_cpu_notify;
-       result = register_hotcpu_notifier(&dev->nb);
-       if (result)
-               goto free_queues;
-
        return 0;
 
  free_queues:
@@ -2184,6 +2234,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
 
        res = nvme_identify(dev, 0, 1, dma_addr);
        if (res) {
+               dev_err(&pdev->dev, "Identify Controller failed (%d)\n", res);
                res = -EIO;
                goto out;
        }
@@ -2192,6 +2243,7 @@ static int nvme_dev_add(struct nvme_dev *dev)
        nn = le32_to_cpup(&ctrl->nn);
        dev->oncs = le16_to_cpup(&ctrl->oncs);
        dev->abort_limit = ctrl->acl + 1;
+       dev->vwc = ctrl->vwc;
        memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
        memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
        memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
@@ -2450,8 +2502,6 @@ static void nvme_dev_shutdown(struct nvme_dev *dev)
        int i;
 
        dev->initialized = 0;
-       unregister_hotcpu_notifier(&dev->nb);
-
        nvme_dev_list_remove(dev);
 
        if (!dev->bar || (dev->bar && readl(&dev->bar->csts) == -1)) {
@@ -2722,6 +2772,7 @@ static int nvme_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        INIT_LIST_HEAD(&dev->namespaces);
        dev->reset_workfn = nvme_reset_failed_dev;
        INIT_WORK(&dev->reset_work, nvme_reset_workfn);
+       INIT_WORK(&dev->cpu_work, nvme_cpu_workfn);
        dev->pci_dev = pdev;
        pci_set_drvdata(pdev, dev);
        result = nvme_set_instance(dev);
@@ -2801,6 +2852,7 @@ static void nvme_remove(struct pci_dev *pdev)
 
        pci_set_drvdata(pdev, NULL);
        flush_work(&dev->reset_work);
+       flush_work(&dev->cpu_work);
        misc_deregister(&dev->miscdev);
        nvme_dev_remove(dev);
        nvme_dev_shutdown(dev);
@@ -2889,11 +2941,18 @@ static int __init nvme_init(void)
        else if (result > 0)
                nvme_major = result;
 
-       result = pci_register_driver(&nvme_driver);
+       nvme_nb.notifier_call = &nvme_cpu_notify;
+       result = register_hotcpu_notifier(&nvme_nb);
        if (result)
                goto unregister_blkdev;
+
+       result = pci_register_driver(&nvme_driver);
+       if (result)
+               goto unregister_hotcpu;
        return 0;
 
+ unregister_hotcpu:
+       unregister_hotcpu_notifier(&nvme_nb);
  unregister_blkdev:
        unregister_blkdev(nvme_major, "nvme");
  kill_workq:
@@ -2904,9 +2963,11 @@ static int __init nvme_init(void)
 static void __exit nvme_exit(void)
 {
        pci_unregister_driver(&nvme_driver);
+       unregister_hotcpu_notifier(&nvme_nb);
        unregister_blkdev(nvme_major, "nvme");
        destroy_workqueue(nvme_workq);
        BUG_ON(nvme_thread && !IS_ERR(nvme_thread));
+       _nvme_check_size();
 }
 
 MODULE_AUTHOR("Matthew Wilcox <willy@linux.intel.com>");
index 2c3f5be06da1078aa28a1a42e070495d4e761367..a4cd6d691c63569f5e4757d5b32886edd7701815 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * NVM Express device driver
- * Copyright (c) 2011, Intel Corporation.
+ * Copyright (c) 2011-2014, Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
  * 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 /*
@@ -243,8 +239,6 @@ static int sg_version_num = 30534;  /* 2 digits for each component */
 #define READ_CAP_16_RESP_SIZE                          32
 
 /* NVMe Namespace and Command Defines */
-#define NVME_GET_SMART_LOG_PAGE                                0x02
-#define NVME_GET_FEAT_TEMP_THRESH                      0x04
 #define BYTES_TO_DWORDS                                        4
 #define NVME_MAX_FIRMWARE_SLOT                         7
 
@@ -686,6 +680,7 @@ static int nvme_trans_standard_inquiry_page(struct nvme_ns *ns,
        u8 resp_data_format = 0x02;
        u8 protect;
        u8 cmdque = 0x01 << 1;
+       u8 fw_offset = sizeof(dev->firmware_rev);
 
        mem = dma_alloc_coherent(&dev->pci_dev->dev, sizeof(struct nvme_id_ns),
                                &dma_addr, GFP_KERNEL);
@@ -721,7 +716,11 @@ static int nvme_trans_standard_inquiry_page(struct nvme_ns *ns,
        inq_response[7] = cmdque;       /* wbus16=0 | sync=0 | vs=0 */
        strncpy(&inq_response[8], "NVMe    ", 8);
        strncpy(&inq_response[16], dev->model, 16);
-       strncpy(&inq_response[32], dev->firmware_rev, 4);
+
+       while (dev->firmware_rev[fw_offset - 1] == ' ' && fw_offset > 4)
+               fw_offset--;
+       fw_offset -= 4;
+       strncpy(&inq_response[32], dev->firmware_rev + fw_offset, 4);
 
        xfer_len = min(alloc_len, STANDARD_INQUIRY_LENGTH);
        res = nvme_trans_copy_to_user(hdr, inq_response, xfer_len);
@@ -1018,8 +1017,8 @@ static int nvme_trans_log_info_exceptions(struct nvme_ns *ns,
        c.common.opcode = nvme_admin_get_log_page;
        c.common.nsid = cpu_to_le32(0xFFFFFFFF);
        c.common.prp1 = cpu_to_le64(dma_addr);
-       c.common.cdw10[0] = cpu_to_le32(((sizeof(struct nvme_smart_log) /
-                       BYTES_TO_DWORDS) << 16) | NVME_GET_SMART_LOG_PAGE);
+       c.common.cdw10[0] = cpu_to_le32((((sizeof(struct nvme_smart_log) /
+                       BYTES_TO_DWORDS) - 1) << 16) | NVME_LOG_SMART);
        res = nvme_submit_admin_cmd(dev, &c, NULL);
        if (res != NVME_SC_SUCCESS) {
                temp_c = LOG_TEMP_UNKNOWN;
@@ -1086,8 +1085,8 @@ static int nvme_trans_log_temperature(struct nvme_ns *ns, struct sg_io_hdr *hdr,
        c.common.opcode = nvme_admin_get_log_page;
        c.common.nsid = cpu_to_le32(0xFFFFFFFF);
        c.common.prp1 = cpu_to_le64(dma_addr);
-       c.common.cdw10[0] = cpu_to_le32(((sizeof(struct nvme_smart_log) /
-                       BYTES_TO_DWORDS) << 16) | NVME_GET_SMART_LOG_PAGE);
+       c.common.cdw10[0] = cpu_to_le32((((sizeof(struct nvme_smart_log) /
+                       BYTES_TO_DWORDS) - 1) << 16) | NVME_LOG_SMART);
        res = nvme_submit_admin_cmd(dev, &c, NULL);
        if (res != NVME_SC_SUCCESS) {
                temp_c_cur = LOG_TEMP_UNKNOWN;
@@ -1477,7 +1476,7 @@ static int nvme_trans_power_state(struct nvme_ns *ns, struct sg_io_hdr *hdr,
                goto out_dma;
        }
        id_ctrl = mem;
-       lowest_pow_st = id_ctrl->npss - 1;
+       lowest_pow_st = max(POWER_STATE_0, (int)(id_ctrl->npss - 1));
 
        switch (pc) {
        case NVME_POWER_STATE_START_VALID:
@@ -1494,20 +1493,19 @@ static int nvme_trans_power_state(struct nvme_ns *ns, struct sg_io_hdr *hdr,
                break;
        case NVME_POWER_STATE_IDLE:
                /* Action unspecified if POWER CONDITION MODIFIER != [0,1,2] */
-               /* min of desired state and (lps-1) because lps is STOP */
                if (pcmod == 0x0)
-                       ps_desired = min(POWER_STATE_1, (lowest_pow_st - 1));
+                       ps_desired = POWER_STATE_1;
                else if (pcmod == 0x1)
-                       ps_desired = min(POWER_STATE_2, (lowest_pow_st - 1));
+                       ps_desired = POWER_STATE_2;
                else if (pcmod == 0x2)
-                       ps_desired = min(POWER_STATE_3, (lowest_pow_st - 1));
+                       ps_desired = POWER_STATE_3;
                break;
        case NVME_POWER_STATE_STANDBY:
                /* Action unspecified if POWER CONDITION MODIFIER != [0,1] */
                if (pcmod == 0x0)
-                       ps_desired = max(0, (lowest_pow_st - 2));
+                       ps_desired = max(POWER_STATE_0, (lowest_pow_st - 2));
                else if (pcmod == 0x1)
-                       ps_desired = max(0, (lowest_pow_st - 1));
+                       ps_desired = max(POWER_STATE_0, (lowest_pow_st - 1));
                break;
        case NVME_POWER_STATE_LU_CONTROL:
        default:
index b5bac917612c4d41e38ad081919f2204ddbef0e3..762fd64dbd1f1344f0af277b1e6fbb7ed5d5e7a1 100644 (file)
@@ -3,3 +3,7 @@
 #
 
 obj-y += clk-sunxi.o clk-factors.o
+obj-y += clk-a10-hosc.o
+obj-y += clk-a20-gmac.o
+
+obj-$(CONFIG_MFD_SUN6I_PRCM) += clk-sun6i-ar100.o clk-sun6i-apb0.o clk-sun6i-apb0-gates.o
diff --git a/drivers/clk/sunxi/clk-a10-hosc.c b/drivers/clk/sunxi/clk-a10-hosc.c
new file mode 100644 (file)
index 0000000..0481d5d
--- /dev/null
@@ -0,0 +1,73 @@
+/*
+ * Copyright 2013 Emilio López
+ *
+ * Emilio López <emilio@elopez.com.ar>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+
+#define SUNXI_OSC24M_GATE      0
+
+static DEFINE_SPINLOCK(hosc_lock);
+
+static void __init sun4i_osc_clk_setup(struct device_node *node)
+{
+       struct clk *clk;
+       struct clk_fixed_rate *fixed;
+       struct clk_gate *gate;
+       const char *clk_name = node->name;
+       u32 rate;
+
+       if (of_property_read_u32(node, "clock-frequency", &rate))
+               return;
+
+       /* allocate fixed-rate and gate clock structs */
+       fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
+       if (!fixed)
+               return;
+       gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+       if (!gate)
+               goto err_free_fixed;
+
+       of_property_read_string(node, "clock-output-names", &clk_name);
+
+       /* set up gate and fixed rate properties */
+       gate->reg = of_iomap(node, 0);
+       gate->bit_idx = SUNXI_OSC24M_GATE;
+       gate->lock = &hosc_lock;
+       fixed->fixed_rate = rate;
+
+       clk = clk_register_composite(NULL, clk_name,
+                       NULL, 0,
+                       NULL, NULL,
+                       &fixed->hw, &clk_fixed_rate_ops,
+                       &gate->hw, &clk_gate_ops,
+                       CLK_IS_ROOT);
+
+       if (IS_ERR(clk))
+               goto err_free_gate;
+
+       of_clk_add_provider(node, of_clk_src_simple_get, clk);
+       clk_register_clkdev(clk, clk_name, NULL);
+
+       return;
+
+err_free_gate:
+       kfree(gate);
+err_free_fixed:
+       kfree(fixed);
+}
+CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup);
diff --git a/drivers/clk/sunxi/clk-a20-gmac.c b/drivers/clk/sunxi/clk-a20-gmac.c
new file mode 100644 (file)
index 0000000..633ddc4
--- /dev/null
@@ -0,0 +1,119 @@
+/*
+ * Copyright 2013 Emilio López
+ * Emilio López <emilio@elopez.com.ar>
+ *
+ * Copyright 2013 Chen-Yu Tsai
+ * Chen-Yu Tsai <wens@csie.org>
+ *
+ * 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.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/clkdev.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+
+static DEFINE_SPINLOCK(gmac_lock);
+
+/**
+ * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
+ *
+ * This clock looks something like this
+ *                               ________________________
+ *  MII TX clock from PHY >-----|___________    _________|----> to GMAC core
+ *  GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
+ *  Ext. 125MHz RGMII TX clk >--|__divider__/            |
+ *                              |________________________|
+ *
+ * The external 125 MHz reference is optional, i.e. GMAC can use its
+ * internal TX clock just fine. The A31 GMAC clock module does not have
+ * the divider controls for the external reference.
+ *
+ * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
+ * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
+ * select the appropriate source and gate/ungate the output to the PHY.
+ *
+ * Only the GMAC should use this clock. Altering the clock so that it doesn't
+ * match the GMAC's operation parameters will result in the GMAC not being
+ * able to send traffic out. The GMAC driver should set the clock rate and
+ * enable/disable this clock to configure the required state. The clock
+ * driver then responds by auto-reparenting the clock.
+ */
+
+#define SUN7I_A20_GMAC_GPIT    2
+#define SUN7I_A20_GMAC_MASK    0x3
+#define SUN7I_A20_GMAC_PARENTS 2
+
+static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
+{
+       struct clk *clk;
+       struct clk_mux *mux;
+       struct clk_gate *gate;
+       const char *clk_name = node->name;
+       const char *parents[SUN7I_A20_GMAC_PARENTS];
+       void *reg;
+
+       if (of_property_read_string(node, "clock-output-names", &clk_name))
+               return;
+
+       /* allocate mux and gate clock structs */
+       mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
+       if (!mux)
+               return;
+
+       gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
+       if (!gate)
+               goto free_mux;
+
+       /* gmac clock requires exactly 2 parents */
+       parents[0] = of_clk_get_parent_name(node, 0);
+       parents[1] = of_clk_get_parent_name(node, 1);
+       if (!parents[0] || !parents[1])
+               goto free_gate;
+
+       reg = of_iomap(node, 0);
+       if (!reg)
+               goto free_gate;
+
+       /* set up gate and fixed rate properties */
+       gate->reg = reg;
+       gate->bit_idx = SUN7I_A20_GMAC_GPIT;
+       gate->lock = &gmac_lock;
+       mux->reg = reg;
+       mux->mask = SUN7I_A20_GMAC_MASK;
+       mux->flags = CLK_MUX_INDEX_BIT;
+       mux->lock = &gmac_lock;
+
+       clk = clk_register_composite(NULL, clk_name,
+                       parents, SUN7I_A20_GMAC_PARENTS,
+                       &mux->hw, &clk_mux_ops,
+                       NULL, NULL,
+                       &gate->hw, &clk_gate_ops,
+                       0);
+
+       if (IS_ERR(clk))
+               goto iounmap_reg;
+
+       of_clk_add_provider(node, of_clk_src_simple_get, clk);
+       clk_register_clkdev(clk, clk_name, NULL);
+
+       return;
+
+iounmap_reg:
+       iounmap(reg);
+free_gate:
+       kfree(gate);
+free_mux:
+       kfree(mux);
+}
+CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
+               sun7i_a20_gmac_clk_setup);
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0-gates.c b/drivers/clk/sunxi/clk-sun6i-apb0-gates.c
new file mode 100644 (file)
index 0000000..44cd27c
--- /dev/null
@@ -0,0 +1,99 @@
+/*
+ * Copyright (C) 2014 Free Electrons
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * Allwinner A31 APB0 clock gates driver
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define SUN6I_APB0_GATES_MAX_SIZE      32
+
+static int sun6i_a31_apb0_gates_clk_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       struct clk_onecell_data *clk_data;
+       const char *clk_parent;
+       const char *clk_name;
+       struct resource *r;
+       void __iomem *reg;
+       int gate_id;
+       int ngates;
+       int i;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       reg = devm_ioremap_resource(&pdev->dev, r);
+       if (!reg)
+               return PTR_ERR(reg);
+
+       clk_parent = of_clk_get_parent_name(np, 0);
+       if (!clk_parent)
+               return -EINVAL;
+
+       ngates = of_property_count_strings(np, "clock-output-names");
+       if (ngates < 0)
+               return ngates;
+
+       if (!ngates || ngates > SUN6I_APB0_GATES_MAX_SIZE)
+               return -EINVAL;
+
+       clk_data = devm_kzalloc(&pdev->dev, sizeof(struct clk_onecell_data),
+                               GFP_KERNEL);
+       if (!clk_data)
+               return -ENOMEM;
+
+       clk_data->clks = devm_kzalloc(&pdev->dev,
+                                     SUN6I_APB0_GATES_MAX_SIZE *
+                                     sizeof(struct clk *),
+                                     GFP_KERNEL);
+       if (!clk_data->clks)
+               return -ENOMEM;
+
+       for (i = 0; i < ngates; i++) {
+               of_property_read_string_index(np, "clock-output-names",
+                                             i, &clk_name);
+
+               gate_id = i;
+               of_property_read_u32_index(np, "clock-indices", i, &gate_id);
+
+               WARN_ON(gate_id >= SUN6I_APB0_GATES_MAX_SIZE);
+               if (gate_id >= SUN6I_APB0_GATES_MAX_SIZE)
+                       continue;
+
+               clk_data->clks[gate_id] = clk_register_gate(&pdev->dev,
+                                                           clk_name,
+                                                           clk_parent, 0,
+                                                           reg, gate_id,
+                                                           0, NULL);
+               WARN_ON(IS_ERR(clk_data->clks[gate_id]));
+       }
+
+       clk_data->clk_num = ngates;
+
+       return of_clk_add_provider(np, of_clk_src_onecell_get, clk_data);
+}
+
+const struct of_device_id sun6i_a31_apb0_gates_clk_dt_ids[] = {
+       { .compatible = "allwinner,sun6i-a31-apb0-gates-clk" },
+       { /* sentinel */ }
+};
+
+static struct platform_driver sun6i_a31_apb0_gates_clk_driver = {
+       .driver = {
+               .name = "sun6i-a31-apb0-gates-clk",
+               .owner = THIS_MODULE,
+               .of_match_table = sun6i_a31_apb0_gates_clk_dt_ids,
+       },
+       .probe = sun6i_a31_apb0_gates_clk_probe,
+};
+module_platform_driver(sun6i_a31_apb0_gates_clk_driver);
+
+MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A31 APB0 gate clocks driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sunxi/clk-sun6i-apb0.c b/drivers/clk/sunxi/clk-sun6i-apb0.c
new file mode 100644 (file)
index 0000000..11f17c3
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2014 Free Electrons
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * Allwinner A31 APB0 clock driver
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+/*
+ * The APB0 clk has a configurable divisor.
+ *
+ * We must use a clk_div_table and not a regular power of 2
+ * divisor here, because the first 2 values divide the clock
+ * by 2.
+ */
+static const struct clk_div_table sun6i_a31_apb0_divs[] = {
+       { .val = 0, .div = 2, },
+       { .val = 1, .div = 2, },
+       { .val = 2, .div = 4, },
+       { .val = 3, .div = 8, },
+       { /* sentinel */ },
+};
+
+static int sun6i_a31_apb0_clk_probe(struct platform_device *pdev)
+{
+       struct device_node *np = pdev->dev.of_node;
+       const char *clk_name = np->name;
+       const char *clk_parent;
+       struct resource *r;
+       void __iomem *reg;
+       struct clk *clk;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       reg = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(reg))
+               return PTR_ERR(reg);
+
+       clk_parent = of_clk_get_parent_name(np, 0);
+       if (!clk_parent)
+               return -EINVAL;
+
+       of_property_read_string(np, "clock-output-names", &clk_name);
+
+       clk = clk_register_divider_table(&pdev->dev, clk_name, clk_parent,
+                                        0, reg, 0, 2, 0, sun6i_a31_apb0_divs,
+                                        NULL);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       return of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+const struct of_device_id sun6i_a31_apb0_clk_dt_ids[] = {
+       { .compatible = "allwinner,sun6i-a31-apb0-clk" },
+       { /* sentinel */ }
+};
+
+static struct platform_driver sun6i_a31_apb0_clk_driver = {
+       .driver = {
+               .name = "sun6i-a31-apb0-clk",
+               .owner = THIS_MODULE,
+               .of_match_table = sun6i_a31_apb0_clk_dt_ids,
+       },
+       .probe = sun6i_a31_apb0_clk_probe,
+};
+module_platform_driver(sun6i_a31_apb0_clk_driver);
+
+MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A31 APB0 clock Driver");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/sunxi/clk-sun6i-ar100.c b/drivers/clk/sunxi/clk-sun6i-ar100.c
new file mode 100644 (file)
index 0000000..f73cc05
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * Copyright (C) 2014 Free Electrons
+ *
+ * License Terms: GNU General Public License v2
+ * Author: Boris BREZILLON <boris.brezillon@free-electrons.com>
+ *
+ * Allwinner A31 AR100 clock driver
+ *
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/platform_device.h>
+
+#define SUN6I_AR100_MAX_PARENTS                4
+#define SUN6I_AR100_SHIFT_MASK         0x3
+#define SUN6I_AR100_SHIFT_MAX          SUN6I_AR100_SHIFT_MASK
+#define SUN6I_AR100_SHIFT_SHIFT                4
+#define SUN6I_AR100_DIV_MASK           0x1f
+#define SUN6I_AR100_DIV_MAX            (SUN6I_AR100_DIV_MASK + 1)
+#define SUN6I_AR100_DIV_SHIFT          8
+#define SUN6I_AR100_MUX_MASK           0x3
+#define SUN6I_AR100_MUX_SHIFT          16
+
+struct ar100_clk {
+       struct clk_hw hw;
+       void __iomem *reg;
+};
+
+static inline struct ar100_clk *to_ar100_clk(struct clk_hw *hw)
+{
+       return container_of(hw, struct ar100_clk, hw);
+}
+
+static unsigned long ar100_recalc_rate(struct clk_hw *hw,
+                                      unsigned long parent_rate)
+{
+       struct ar100_clk *clk = to_ar100_clk(hw);
+       u32 val = readl(clk->reg);
+       int shift = (val >> SUN6I_AR100_SHIFT_SHIFT) & SUN6I_AR100_SHIFT_MASK;
+       int div = (val >> SUN6I_AR100_DIV_SHIFT) & SUN6I_AR100_DIV_MASK;
+
+       return (parent_rate >> shift) / (div + 1);
+}
+
+static long ar100_determine_rate(struct clk_hw *hw, unsigned long rate,
+                                unsigned long *best_parent_rate,
+                                struct clk **best_parent_clk)
+{
+       int nparents = __clk_get_num_parents(hw->clk);
+       long best_rate = -EINVAL;
+       int i;
+
+       *best_parent_clk = NULL;
+
+       for (i = 0; i < nparents; i++) {
+               unsigned long parent_rate;
+               unsigned long tmp_rate;
+               struct clk *parent;
+               unsigned long div;
+               int shift;
+
+               parent = clk_get_parent_by_index(hw->clk, i);
+               parent_rate = __clk_get_rate(parent);
+               div = DIV_ROUND_UP(parent_rate, rate);
+
+               /*
+                * The AR100 clk contains 2 divisors:
+                * - one power of 2 divisor
+                * - one regular divisor
+                *
+                * First check if we can safely shift (or divide by a power
+                * of 2) without losing precision on the requested rate.
+                */
+               shift = ffs(div) - 1;
+               if (shift > SUN6I_AR100_SHIFT_MAX)
+                       shift = SUN6I_AR100_SHIFT_MAX;
+
+               div >>= shift;
+
+               /*
+                * Then if the divisor is still bigger than what the HW
+                * actually supports, use a bigger shift (or power of 2
+                * divider) value and accept to lose some precision.
+                */
+               while (div > SUN6I_AR100_DIV_MAX) {
+                       shift++;
+                       div >>= 1;
+                       if (shift > SUN6I_AR100_SHIFT_MAX)
+                               break;
+               }
+
+               /*
+                * If the shift value (or power of 2 divider) is bigger
+                * than what the HW actually support, skip this parent.
+                */
+               if (shift > SUN6I_AR100_SHIFT_MAX)
+                       continue;
+
+               tmp_rate = (parent_rate >> shift) / div;
+               if (!*best_parent_clk || tmp_rate > best_rate) {
+                       *best_parent_clk = parent;
+                       *best_parent_rate = parent_rate;
+                       best_rate = tmp_rate;
+               }
+       }
+
+       return best_rate;
+}
+
+static int ar100_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct ar100_clk *clk = to_ar100_clk(hw);
+       u32 val = readl(clk->reg);
+
+       if (index >= SUN6I_AR100_MAX_PARENTS)
+               return -EINVAL;
+
+       val &= ~(SUN6I_AR100_MUX_MASK << SUN6I_AR100_MUX_SHIFT);
+       val |= (index << SUN6I_AR100_MUX_SHIFT);
+       writel(val, clk->reg);
+
+       return 0;
+}
+
+static u8 ar100_get_parent(struct clk_hw *hw)
+{
+       struct ar100_clk *clk = to_ar100_clk(hw);
+       return (readl(clk->reg) >> SUN6I_AR100_MUX_SHIFT) &
+              SUN6I_AR100_MUX_MASK;
+}
+
+static int ar100_set_rate(struct clk_hw *hw, unsigned long rate,
+                         unsigned long parent_rate)
+{
+       unsigned long div = parent_rate / rate;
+       struct ar100_clk *clk = to_ar100_clk(hw);
+       u32 val = readl(clk->reg);
+       int shift;
+
+       if (parent_rate % rate)
+               return -EINVAL;
+
+       shift = ffs(div) - 1;
+       if (shift > SUN6I_AR100_SHIFT_MAX)
+               shift = SUN6I_AR100_SHIFT_MAX;
+
+       div >>= shift;
+
+       if (div > SUN6I_AR100_DIV_MAX)
+               return -EINVAL;
+
+       val &= ~((SUN6I_AR100_SHIFT_MASK << SUN6I_AR100_SHIFT_SHIFT) |
+                (SUN6I_AR100_DIV_MASK << SUN6I_AR100_DIV_SHIFT));
+       val |= (shift << SUN6I_AR100_SHIFT_SHIFT) |
+              (div << SUN6I_AR100_DIV_SHIFT);
+       writel(val, clk->reg);
+
+       return 0;
+}
+
+struct clk_ops ar100_ops = {
+       .recalc_rate = ar100_recalc_rate,
+       .determine_rate = ar100_determine_rate,
+       .set_parent = ar100_set_parent,
+       .get_parent = ar100_get_parent,
+       .set_rate = ar100_set_rate,
+};
+
+static int sun6i_a31_ar100_clk_probe(struct platform_device *pdev)
+{
+       const char *parents[SUN6I_AR100_MAX_PARENTS];
+       struct device_node *np = pdev->dev.of_node;
+       const char *clk_name = np->name;
+       struct clk_init_data init;
+       struct ar100_clk *ar100;
+       struct resource *r;
+       struct clk *clk;
+       int nparents;
+       int i;
+
+       ar100 = devm_kzalloc(&pdev->dev, sizeof(*ar100), GFP_KERNEL);
+       if (!ar100)
+               return -ENOMEM;
+
+       r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       ar100->reg = devm_ioremap_resource(&pdev->dev, r);
+       if (IS_ERR(ar100->reg))
+               return PTR_ERR(ar100->reg);
+
+       nparents = of_clk_get_parent_count(np);
+       if (nparents > SUN6I_AR100_MAX_PARENTS)
+               nparents = SUN6I_AR100_MAX_PARENTS;
+
+       for (i = 0; i < nparents; i++)
+               parents[i] = of_clk_get_parent_name(np, i);
+
+       of_property_read_string(np, "clock-output-names", &clk_name);
+
+       init.name = clk_name;
+       init.ops = &ar100_ops;
+       init.parent_names = parents;
+       init.num_parents = nparents;
+       init.flags = 0;
+
+       ar100->hw.init = &init;
+
+       clk = clk_register(&pdev->dev, &ar100->hw);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       return of_clk_add_provider(np, of_clk_src_simple_get, clk);
+}
+
+const struct of_device_id sun6i_a31_ar100_clk_dt_ids[] = {
+       { .compatible = "allwinner,sun6i-a31-ar100-clk" },
+       { /* sentinel */ }
+};
+
+static struct platform_driver sun6i_a31_ar100_clk_driver = {
+       .driver = {
+               .name = "sun6i-a31-ar100-clk",
+               .owner = THIS_MODULE,
+               .of_match_table = sun6i_a31_ar100_clk_dt_ids,
+       },
+       .probe = sun6i_a31_ar100_clk_probe,
+};
+module_platform_driver(sun6i_a31_ar100_clk_driver);
+
+MODULE_AUTHOR("Boris BREZILLON <boris.brezillon@free-electrons.com>");
+MODULE_DESCRIPTION("Allwinner A31 AR100 clock Driver");
+MODULE_LICENSE("GPL v2");
index 426483422d3d50edb20c3f013668cdacff9bd6d8..fb2ce8440f0ed6cefbc30d361193383f5282a6cd 100644 (file)
@@ -27,63 +27,6 @@ static DEFINE_SPINLOCK(clk_lock);
 /* Maximum number of parents our clocks have */
 #define SUNXI_MAX_PARENTS      5
 
-/**
- * sun4i_osc_clk_setup() - Setup function for gatable oscillator
- */
-
-#define SUNXI_OSC24M_GATE      0
-
-static void __init sun4i_osc_clk_setup(struct device_node *node)
-{
-       struct clk *clk;
-       struct clk_fixed_rate *fixed;
-       struct clk_gate *gate;
-       const char *clk_name = node->name;
-       u32 rate;
-
-       if (of_property_read_u32(node, "clock-frequency", &rate))
-               return;
-
-       /* allocate fixed-rate and gate clock structs */
-       fixed = kzalloc(sizeof(struct clk_fixed_rate), GFP_KERNEL);
-       if (!fixed)
-               return;
-       gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
-       if (!gate)
-               goto err_free_fixed;
-
-       of_property_read_string(node, "clock-output-names", &clk_name);
-
-       /* set up gate and fixed rate properties */
-       gate->reg = of_iomap(node, 0);
-       gate->bit_idx = SUNXI_OSC24M_GATE;
-       gate->lock = &clk_lock;
-       fixed->fixed_rate = rate;
-
-       clk = clk_register_composite(NULL, clk_name,
-                       NULL, 0,
-                       NULL, NULL,
-                       &fixed->hw, &clk_fixed_rate_ops,
-                       &gate->hw, &clk_gate_ops,
-                       CLK_IS_ROOT);
-
-       if (IS_ERR(clk))
-               goto err_free_gate;
-
-       of_clk_add_provider(node, of_clk_src_simple_get, clk);
-       clk_register_clkdev(clk, clk_name, NULL);
-
-       return;
-
-err_free_gate:
-       kfree(gate);
-err_free_fixed:
-       kfree(fixed);
-}
-CLK_OF_DECLARE(sun4i_osc, "allwinner,sun4i-a10-osc-clk", sun4i_osc_clk_setup);
-
-
-
 /**
  * sun4i_get_pll1_factors() - calculates n, k, m, p factors for PLL1
  * PLL1 rate is calculated as follows
@@ -408,104 +351,6 @@ static void sun7i_a20_get_out_factors(u32 *freq, u32 parent_rate,
        *p = calcp;
 }
 
-
-
-/**
- * sun7i_a20_gmac_clk_setup - Setup function for A20/A31 GMAC clock module
- *
- * This clock looks something like this
- *                               ________________________
- *  MII TX clock from PHY >-----|___________    _________|----> to GMAC core
- *  GMAC Int. RGMII TX clk >----|___________\__/__gate---|----> to PHY
- *  Ext. 125MHz RGMII TX clk >--|__divider__/            |
- *                              |________________________|
- *
- * The external 125 MHz reference is optional, i.e. GMAC can use its
- * internal TX clock just fine. The A31 GMAC clock module does not have
- * the divider controls for the external reference.
- *
- * To keep it simple, let the GMAC use either the MII TX clock for MII mode,
- * and its internal TX clock for GMII and RGMII modes. The GMAC driver should
- * select the appropriate source and gate/ungate the output to the PHY.
- *
- * Only the GMAC should use this clock. Altering the clock so that it doesn't
- * match the GMAC's operation parameters will result in the GMAC not being
- * able to send traffic out. The GMAC driver should set the clock rate and
- * enable/disable this clock to configure the required state. The clock
- * driver then responds by auto-reparenting the clock.
- */
-
-#define SUN7I_A20_GMAC_GPIT    2
-#define SUN7I_A20_GMAC_MASK    0x3
-#define SUN7I_A20_GMAC_PARENTS 2
-
-static void __init sun7i_a20_gmac_clk_setup(struct device_node *node)
-{
-       struct clk *clk;
-       struct clk_mux *mux;
-       struct clk_gate *gate;
-       const char *clk_name = node->name;
-       const char *parents[SUN7I_A20_GMAC_PARENTS];
-       void *reg;
-
-       if (of_property_read_string(node, "clock-output-names", &clk_name))
-               return;
-
-       /* allocate mux and gate clock structs */
-       mux = kzalloc(sizeof(struct clk_mux), GFP_KERNEL);
-       if (!mux)
-               return;
-
-       gate = kzalloc(sizeof(struct clk_gate), GFP_KERNEL);
-       if (!gate)
-               goto free_mux;
-
-       /* gmac clock requires exactly 2 parents */
-       parents[0] = of_clk_get_parent_name(node, 0);
-       parents[1] = of_clk_get_parent_name(node, 1);
-       if (!parents[0] || !parents[1])
-               goto free_gate;
-
-       reg = of_iomap(node, 0);
-       if (!reg)
-               goto free_gate;
-
-       /* set up gate and fixed rate properties */
-       gate->reg = reg;
-       gate->bit_idx = SUN7I_A20_GMAC_GPIT;
-       gate->lock = &clk_lock;
-       mux->reg = reg;
-       mux->mask = SUN7I_A20_GMAC_MASK;
-       mux->flags = CLK_MUX_INDEX_BIT;
-       mux->lock = &clk_lock;
-
-       clk = clk_register_composite(NULL, clk_name,
-                       parents, SUN7I_A20_GMAC_PARENTS,
-                       &mux->hw, &clk_mux_ops,
-                       NULL, NULL,
-                       &gate->hw, &clk_gate_ops,
-                       0);
-
-       if (IS_ERR(clk))
-               goto iounmap_reg;
-
-       of_clk_add_provider(node, of_clk_src_simple_get, clk);
-       clk_register_clkdev(clk, clk_name, NULL);
-
-       return;
-
-iounmap_reg:
-       iounmap(reg);
-free_gate:
-       kfree(gate);
-free_mux:
-       kfree(mux);
-}
-CLK_OF_DECLARE(sun7i_a20_gmac, "allwinner,sun7i-a20-gmac-clk",
-               sun7i_a20_gmac_clk_setup);
-
-
-
 /**
  * clk_sunxi_mmc_phase_control() - configures MMC clock phase control
  */
@@ -1009,6 +854,11 @@ static const struct gates_data sun5i_a13_usb_gates_data __initconst = {
        .reset_mask = 0x03,
 };
 
+static const struct gates_data sun6i_a31_usb_gates_data __initconst = {
+       .mask = { BIT(18) | BIT(17) | BIT(16) | BIT(10) | BIT(9) | BIT(8) },
+       .reset_mask = BIT(2) | BIT(1) | BIT(0),
+};
+
 static void __init sunxi_gates_clk_setup(struct device_node *node,
                                         struct gates_data *data)
 {
@@ -1304,6 +1154,7 @@ static const struct of_device_id clk_gates_match[] __initconst = {
        {.compatible = "allwinner,sun6i-a31-apb2-gates-clk", .data = &sun6i_a31_apb2_gates_data,},
        {.compatible = "allwinner,sun4i-a10-usb-clk", .data = &sun4i_a10_usb_gates_data,},
        {.compatible = "allwinner,sun5i-a13-usb-clk", .data = &sun5i_a13_usb_gates_data,},
+       {.compatible = "allwinner,sun6i-a31-usb-clk", .data = &sun6i_a31_usb_gates_data,},
        {}
 };
 
@@ -1321,33 +1172,10 @@ static void __init of_sunxi_table_clock_setup(const struct of_device_id *clk_mat
        }
 }
 
-/**
- * System clock protection
- *
- * By enabling these critical clocks, we prevent their accidental gating
- * by the framework
- */
-static void __init sunxi_clock_protect(void)
+static void __init sunxi_init_clocks(const char *clocks[], int nclocks)
 {
-       struct clk *clk;
-
-       /* memory bus clock - sun5i+ */
-       clk = clk_get(NULL, "mbus");
-       if (!IS_ERR(clk)) {
-               clk_prepare_enable(clk);
-               clk_put(clk);
-       }
-
-       /* DDR clock - sun4i+ */
-       clk = clk_get(NULL, "pll5_ddr");
-       if (!IS_ERR(clk)) {
-               clk_prepare_enable(clk);
-               clk_put(clk);
-       }
-}
+       unsigned int i;
 
-static void __init sunxi_init_clocks(struct device_node *np)
-{
        /* Register factor clocks */
        of_sunxi_table_clock_setup(clk_factors_match, sunxi_factors_clk_setup);
 
@@ -1363,11 +1191,48 @@ static void __init sunxi_init_clocks(struct device_node *np)
        /* Register gate clocks */
        of_sunxi_table_clock_setup(clk_gates_match, sunxi_gates_clk_setup);
 
-       /* Enable core system clocks */
-       sunxi_clock_protect();
+       /* Protect the clocks that needs to stay on */
+       for (i = 0; i < nclocks; i++) {
+               struct clk *clk = clk_get(NULL, clocks[i]);
+
+               if (!IS_ERR(clk))
+                       clk_prepare_enable(clk);
+       }
+}
+
+static const char *sun4i_a10_critical_clocks[] __initdata = {
+       "pll5_ddr",
+};
+
+static void __init sun4i_a10_init_clocks(struct device_node *node)
+{
+       sunxi_init_clocks(sun4i_a10_critical_clocks,
+                         ARRAY_SIZE(sun4i_a10_critical_clocks));
+}
+CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sun4i_a10_init_clocks);
+
+static const char *sun5i_critical_clocks[] __initdata = {
+       "mbus",
+       "pll5_ddr",
+};
+
+static void __init sun5i_init_clocks(struct device_node *node)
+{
+       sunxi_init_clocks(sun5i_critical_clocks,
+                         ARRAY_SIZE(sun5i_critical_clocks));
+}
+CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sun5i_init_clocks);
+CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sun5i_init_clocks);
+CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sun5i_init_clocks);
+
+static const char *sun6i_critical_clocks[] __initdata = {
+       "cpu",
+       "ahb1_sdram",
+};
+
+static void __init sun6i_init_clocks(struct device_node *node)
+{
+       sunxi_init_clocks(sun6i_critical_clocks,
+                         ARRAY_SIZE(sun6i_critical_clocks));
 }
-CLK_OF_DECLARE(sun4i_a10_clk_init, "allwinner,sun4i-a10", sunxi_init_clocks);
-CLK_OF_DECLARE(sun5i_a10s_clk_init, "allwinner,sun5i-a10s", sunxi_init_clocks);
-CLK_OF_DECLARE(sun5i_a13_clk_init, "allwinner,sun5i-a13", sunxi_init_clocks);
-CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sunxi_init_clocks);
-CLK_OF_DECLARE(sun7i_a20_clk_init, "allwinner,sun7i-a20", sunxi_init_clocks);
+CLK_OF_DECLARE(sun6i_a31_clk_init, "allwinner,sun6i-a31", sun6i_init_clocks);
index 4319d4031aa3785de25bfb745f1d514c2690c9c5..ed4d0aaf891639585825344d7460bbfcbc1c81e2 100644 (file)
@@ -3,9 +3,11 @@ obj-y                                  += clk.o autoidle.o clockdomain.o
 clk-common                             = dpll.o composite.o divider.o gate.o \
                                          fixed-factor.o mux.o apll.o
 obj-$(CONFIG_SOC_AM33XX)               += $(clk-common) clk-33xx.o
+obj-$(CONFIG_ARCH_OMAP2)               += $(clk-common) interface.o clk-2xxx.o
 obj-$(CONFIG_ARCH_OMAP3)               += $(clk-common) interface.o clk-3xxx.o
 obj-$(CONFIG_ARCH_OMAP4)               += $(clk-common) clk-44xx.o
 obj-$(CONFIG_SOC_OMAP5)                        += $(clk-common) clk-54xx.o
-obj-$(CONFIG_SOC_DRA7XX)               += $(clk-common) clk-7xx.o
+obj-$(CONFIG_SOC_DRA7XX)               += $(clk-common) clk-7xx.o \
+                                          clk-dra7-atl.o
 obj-$(CONFIG_SOC_AM43XX)               += $(clk-common) clk-43xx.o
 endif
index b986f61f5a7713791d4cbd3abedf56054eab150b..5428c9c547cd97aa64bc826f5bb25d09d0806eb3 100644 (file)
@@ -221,3 +221,184 @@ cleanup:
        kfree(init);
 }
 CLK_OF_DECLARE(dra7_apll_clock, "ti,dra7-apll-clock", of_dra7_apll_setup);
+
+#define OMAP2_EN_APLL_LOCKED   0x3
+#define OMAP2_EN_APLL_STOPPED  0x0
+
+static int omap2_apll_is_enabled(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *ad = clk->dpll_data;
+       u32 v;
+
+       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v &= ad->enable_mask;
+
+       v >>= __ffs(ad->enable_mask);
+
+       return v == OMAP2_EN_APLL_LOCKED ? 1 : 0;
+}
+
+static unsigned long omap2_apll_recalc(struct clk_hw *hw,
+                                      unsigned long parent_rate)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+
+       if (omap2_apll_is_enabled(hw))
+               return clk->fixed_rate;
+
+       return 0;
+}
+
+static int omap2_apll_enable(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *ad = clk->dpll_data;
+       u32 v;
+       int i = 0;
+
+       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v &= ~ad->enable_mask;
+       v |= OMAP2_EN_APLL_LOCKED << __ffs(ad->enable_mask);
+       ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+
+       while (1) {
+               v = ti_clk_ll_ops->clk_readl(ad->idlest_reg);
+               if (v & ad->idlest_mask)
+                       break;
+               if (i > MAX_APLL_WAIT_TRIES)
+                       break;
+               i++;
+               udelay(1);
+       }
+
+       if (i == MAX_APLL_WAIT_TRIES) {
+               pr_warn("%s failed to transition to locked\n",
+                       __clk_get_name(clk->hw.clk));
+               return -EBUSY;
+       }
+
+       return 0;
+}
+
+static void omap2_apll_disable(struct clk_hw *hw)
+{
+       struct clk_hw_omap *clk = to_clk_hw_omap(hw);
+       struct dpll_data *ad = clk->dpll_data;
+       u32 v;
+
+       v = ti_clk_ll_ops->clk_readl(ad->control_reg);
+       v &= ~ad->enable_mask;
+       v |= OMAP2_EN_APLL_STOPPED << __ffs(ad->enable_mask);
+       ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+}
+
+static struct clk_ops omap2_apll_ops = {
+       .enable         = &omap2_apll_enable,
+       .disable        = &omap2_apll_disable,
+       .is_enabled     = &omap2_apll_is_enabled,
+       .recalc_rate    = &omap2_apll_recalc,
+};
+
+static void omap2_apll_set_autoidle(struct clk_hw_omap *clk, u32 val)
+{
+       struct dpll_data *ad = clk->dpll_data;
+       u32 v;
+
+       v = ti_clk_ll_ops->clk_readl(ad->autoidle_reg);
+       v &= ~ad->autoidle_mask;
+       v |= val << __ffs(ad->autoidle_mask);
+       ti_clk_ll_ops->clk_writel(v, ad->control_reg);
+}
+
+#define OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP     0x3
+#define OMAP2_APLL_AUTOIDLE_DISABLE            0x0
+
+static void omap2_apll_allow_idle(struct clk_hw_omap *clk)
+{
+       omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_LOW_POWER_STOP);
+}
+
+static void omap2_apll_deny_idle(struct clk_hw_omap *clk)
+{
+       omap2_apll_set_autoidle(clk, OMAP2_APLL_AUTOIDLE_DISABLE);
+}
+
+static struct clk_hw_omap_ops omap2_apll_hwops = {
+       .allow_idle     = &omap2_apll_allow_idle,
+       .deny_idle      = &omap2_apll_deny_idle,
+};
+
+static void __init of_omap2_apll_setup(struct device_node *node)
+{
+       struct dpll_data *ad = NULL;
+       struct clk_hw_omap *clk_hw = NULL;
+       struct clk_init_data *init = NULL;
+       struct clk *clk;
+       const char *parent_name;
+       u32 val;
+
+       ad = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+       clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+       init = kzalloc(sizeof(*init), GFP_KERNEL);
+
+       if (!ad || !clk_hw || !init)
+               goto cleanup;
+
+       clk_hw->dpll_data = ad;
+       clk_hw->hw.init = init;
+       init->ops = &omap2_apll_ops;
+       init->name = node->name;
+       clk_hw->ops = &omap2_apll_hwops;
+
+       init->num_parents = of_clk_get_parent_count(node);
+       if (init->num_parents != 1) {
+               pr_err("%s must have one parent\n", node->name);
+               goto cleanup;
+       }
+
+       parent_name = of_clk_get_parent_name(node, 0);
+       init->parent_names = &parent_name;
+
+       if (of_property_read_u32(node, "ti,clock-frequency", &val)) {
+               pr_err("%s missing clock-frequency\n", node->name);
+               goto cleanup;
+       }
+       clk_hw->fixed_rate = val;
+
+       if (of_property_read_u32(node, "ti,bit-shift", &val)) {
+               pr_err("%s missing bit-shift\n", node->name);
+               goto cleanup;
+       }
+
+       clk_hw->enable_bit = val;
+       ad->enable_mask = 0x3 << val;
+       ad->autoidle_mask = 0x3 << val;
+
+       if (of_property_read_u32(node, "ti,idlest-shift", &val)) {
+               pr_err("%s missing idlest-shift\n", node->name);
+               goto cleanup;
+       }
+
+       ad->idlest_mask = 1 << val;
+
+       ad->control_reg = ti_clk_get_reg_addr(node, 0);
+       ad->autoidle_reg = ti_clk_get_reg_addr(node, 1);
+       ad->idlest_reg = ti_clk_get_reg_addr(node, 2);
+
+       if (!ad->control_reg || !ad->autoidle_reg || !ad->idlest_reg)
+               goto cleanup;
+
+       clk = clk_register(NULL, &clk_hw->hw);
+       if (!IS_ERR(clk)) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               kfree(init);
+               return;
+       }
+cleanup:
+       kfree(ad);
+       kfree(clk_hw);
+       kfree(init);
+}
+CLK_OF_DECLARE(omap2_apll_clock, "ti,omap2-apll-clock",
+              of_omap2_apll_setup);
diff --git a/drivers/clk/ti/clk-2xxx.c b/drivers/clk/ti/clk-2xxx.c
new file mode 100644 (file)
index 0000000..c808ab3
--- /dev/null
@@ -0,0 +1,256 @@
+/*
+ * OMAP2 Clock init
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc
+ *     Tero Kristo (t-kristo@ti.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 version 2.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <linux/clk-provider.h>
+#include <linux/clk/ti.h>
+
+static struct ti_dt_clk omap2xxx_clks[] = {
+       DT_CLK(NULL, "func_32k_ck", "func_32k_ck"),
+       DT_CLK(NULL, "secure_32k_ck", "secure_32k_ck"),
+       DT_CLK(NULL, "virt_12m_ck", "virt_12m_ck"),
+       DT_CLK(NULL, "virt_13m_ck", "virt_13m_ck"),
+       DT_CLK(NULL, "virt_19200000_ck", "virt_19200000_ck"),
+       DT_CLK(NULL, "virt_26m_ck", "virt_26m_ck"),
+       DT_CLK(NULL, "aplls_clkin_ck", "aplls_clkin_ck"),
+       DT_CLK(NULL, "aplls_clkin_x2_ck", "aplls_clkin_x2_ck"),
+       DT_CLK(NULL, "osc_ck", "osc_ck"),
+       DT_CLK(NULL, "sys_ck", "sys_ck"),
+       DT_CLK(NULL, "alt_ck", "alt_ck"),
+       DT_CLK(NULL, "mcbsp_clks", "mcbsp_clks"),
+       DT_CLK(NULL, "dpll_ck", "dpll_ck"),
+       DT_CLK(NULL, "apll96_ck", "apll96_ck"),
+       DT_CLK(NULL, "apll54_ck", "apll54_ck"),
+       DT_CLK(NULL, "func_54m_ck", "func_54m_ck"),
+       DT_CLK(NULL, "core_ck", "core_ck"),
+       DT_CLK(NULL, "func_96m_ck", "func_96m_ck"),
+       DT_CLK(NULL, "func_48m_ck", "func_48m_ck"),
+       DT_CLK(NULL, "func_12m_ck", "func_12m_ck"),
+       DT_CLK(NULL, "sys_clkout_src", "sys_clkout_src"),
+       DT_CLK(NULL, "sys_clkout", "sys_clkout"),
+       DT_CLK(NULL, "emul_ck", "emul_ck"),
+       DT_CLK(NULL, "mpu_ck", "mpu_ck"),
+       DT_CLK(NULL, "dsp_fck", "dsp_fck"),
+       DT_CLK(NULL, "gfx_3d_fck", "gfx_3d_fck"),
+       DT_CLK(NULL, "gfx_2d_fck", "gfx_2d_fck"),
+       DT_CLK(NULL, "gfx_ick", "gfx_ick"),
+       DT_CLK("omapdss_dss", "ick", "dss_ick"),
+       DT_CLK(NULL, "dss_ick", "dss_ick"),
+       DT_CLK(NULL, "dss1_fck", "dss1_fck"),
+       DT_CLK(NULL, "dss2_fck", "dss2_fck"),
+       DT_CLK(NULL, "dss_54m_fck", "dss_54m_fck"),
+       DT_CLK(NULL, "core_l3_ck", "core_l3_ck"),
+       DT_CLK(NULL, "ssi_fck", "ssi_ssr_sst_fck"),
+       DT_CLK(NULL, "usb_l4_ick", "usb_l4_ick"),
+       DT_CLK(NULL, "l4_ck", "l4_ck"),
+       DT_CLK(NULL, "ssi_l4_ick", "ssi_l4_ick"),
+       DT_CLK(NULL, "gpt1_ick", "gpt1_ick"),
+       DT_CLK(NULL, "gpt1_fck", "gpt1_fck"),
+       DT_CLK(NULL, "gpt2_ick", "gpt2_ick"),
+       DT_CLK(NULL, "gpt2_fck", "gpt2_fck"),
+       DT_CLK(NULL, "gpt3_ick", "gpt3_ick"),
+       DT_CLK(NULL, "gpt3_fck", "gpt3_fck"),
+       DT_CLK(NULL, "gpt4_ick", "gpt4_ick"),
+       DT_CLK(NULL, "gpt4_fck", "gpt4_fck"),
+       DT_CLK(NULL, "gpt5_ick", "gpt5_ick"),
+       DT_CLK(NULL, "gpt5_fck", "gpt5_fck"),
+       DT_CLK(NULL, "gpt6_ick", "gpt6_ick"),
+       DT_CLK(NULL, "gpt6_fck", "gpt6_fck"),
+       DT_CLK(NULL, "gpt7_ick", "gpt7_ick"),
+       DT_CLK(NULL, "gpt7_fck", "gpt7_fck"),
+       DT_CLK(NULL, "gpt8_ick", "gpt8_ick"),
+       DT_CLK(NULL, "gpt8_fck", "gpt8_fck"),
+       DT_CLK(NULL, "gpt9_ick", "gpt9_ick"),
+       DT_CLK(NULL, "gpt9_fck", "gpt9_fck"),
+       DT_CLK(NULL, "gpt10_ick", "gpt10_ick"),
+       DT_CLK(NULL, "gpt10_fck", "gpt10_fck"),
+       DT_CLK(NULL, "gpt11_ick", "gpt11_ick"),
+       DT_CLK(NULL, "gpt11_fck", "gpt11_fck"),
+       DT_CLK(NULL, "gpt12_ick", "gpt12_ick"),
+       DT_CLK(NULL, "gpt12_fck", "gpt12_fck"),
+       DT_CLK("omap-mcbsp.1", "ick", "mcbsp1_ick"),
+       DT_CLK(NULL, "mcbsp1_ick", "mcbsp1_ick"),
+       DT_CLK(NULL, "mcbsp1_fck", "mcbsp1_fck"),
+       DT_CLK("omap-mcbsp.2", "ick", "mcbsp2_ick"),
+       DT_CLK(NULL, "mcbsp2_ick", "mcbsp2_ick"),
+       DT_CLK(NULL, "mcbsp2_fck", "mcbsp2_fck"),
+       DT_CLK("omap2_mcspi.1", "ick", "mcspi1_ick"),
+       DT_CLK(NULL, "mcspi1_ick", "mcspi1_ick"),
+       DT_CLK(NULL, "mcspi1_fck", "mcspi1_fck"),
+       DT_CLK("omap2_mcspi.2", "ick", "mcspi2_ick"),
+       DT_CLK(NULL, "mcspi2_ick", "mcspi2_ick"),
+       DT_CLK(NULL, "mcspi2_fck", "mcspi2_fck"),
+       DT_CLK(NULL, "uart1_ick", "uart1_ick"),
+       DT_CLK(NULL, "uart1_fck", "uart1_fck"),
+       DT_CLK(NULL, "uart2_ick", "uart2_ick"),
+       DT_CLK(NULL, "uart2_fck", "uart2_fck"),
+       DT_CLK(NULL, "uart3_ick", "uart3_ick"),
+       DT_CLK(NULL, "uart3_fck", "uart3_fck"),
+       DT_CLK(NULL, "gpios_ick", "gpios_ick"),
+       DT_CLK(NULL, "gpios_fck", "gpios_fck"),
+       DT_CLK("omap_wdt", "ick", "mpu_wdt_ick"),
+       DT_CLK(NULL, "mpu_wdt_ick", "mpu_wdt_ick"),
+       DT_CLK(NULL, "mpu_wdt_fck", "mpu_wdt_fck"),
+       DT_CLK(NULL, "sync_32k_ick", "sync_32k_ick"),
+       DT_CLK(NULL, "wdt1_ick", "wdt1_ick"),
+       DT_CLK(NULL, "omapctrl_ick", "omapctrl_ick"),
+       DT_CLK("omap24xxcam", "fck", "cam_fck"),
+       DT_CLK(NULL, "cam_fck", "cam_fck"),
+       DT_CLK("omap24xxcam", "ick", "cam_ick"),
+       DT_CLK(NULL, "cam_ick", "cam_ick"),
+       DT_CLK(NULL, "mailboxes_ick", "mailboxes_ick"),
+       DT_CLK(NULL, "wdt4_ick", "wdt4_ick"),
+       DT_CLK(NULL, "wdt4_fck", "wdt4_fck"),
+       DT_CLK(NULL, "mspro_ick", "mspro_ick"),
+       DT_CLK(NULL, "mspro_fck", "mspro_fck"),
+       DT_CLK(NULL, "fac_ick", "fac_ick"),
+       DT_CLK(NULL, "fac_fck", "fac_fck"),
+       DT_CLK("omap_hdq.0", "ick", "hdq_ick"),
+       DT_CLK(NULL, "hdq_ick", "hdq_ick"),
+       DT_CLK("omap_hdq.0", "fck", "hdq_fck"),
+       DT_CLK(NULL, "hdq_fck", "hdq_fck"),
+       DT_CLK("omap_i2c.1", "ick", "i2c1_ick"),
+       DT_CLK(NULL, "i2c1_ick", "i2c1_ick"),
+       DT_CLK("omap_i2c.2", "ick", "i2c2_ick"),
+       DT_CLK(NULL, "i2c2_ick", "i2c2_ick"),
+       DT_CLK(NULL, "gpmc_fck", "gpmc_fck"),
+       DT_CLK(NULL, "sdma_fck", "sdma_fck"),
+       DT_CLK(NULL, "sdma_ick", "sdma_ick"),
+       DT_CLK(NULL, "sdrc_ick", "sdrc_ick"),
+       DT_CLK(NULL, "des_ick", "des_ick"),
+       DT_CLK("omap-sham", "ick", "sha_ick"),
+       DT_CLK(NULL, "sha_ick", "sha_ick"),
+       DT_CLK("omap_rng", "ick", "rng_ick"),
+       DT_CLK(NULL, "rng_ick", "rng_ick"),
+       DT_CLK("omap-aes", "ick", "aes_ick"),
+       DT_CLK(NULL, "aes_ick", "aes_ick"),
+       DT_CLK(NULL, "pka_ick", "pka_ick"),
+       DT_CLK(NULL, "usb_fck", "usb_fck"),
+       DT_CLK(NULL, "timer_32k_ck", "func_32k_ck"),
+       DT_CLK(NULL, "timer_sys_ck", "sys_ck"),
+       DT_CLK(NULL, "timer_ext_ck", "alt_ck"),
+       { .node_name = NULL },
+};
+
+static struct ti_dt_clk omap2420_clks[] = {
+       DT_CLK(NULL, "sys_clkout2_src", "sys_clkout2_src"),
+       DT_CLK(NULL, "sys_clkout2", "sys_clkout2"),
+       DT_CLK(NULL, "dsp_ick", "dsp_ick"),
+       DT_CLK(NULL, "iva1_ifck", "iva1_ifck"),
+       DT_CLK(NULL, "iva1_mpu_int_ifck", "iva1_mpu_int_ifck"),
+       DT_CLK(NULL, "wdt3_ick", "wdt3_ick"),
+       DT_CLK(NULL, "wdt3_fck", "wdt3_fck"),
+       DT_CLK("mmci-omap.0", "ick", "mmc_ick"),
+       DT_CLK(NULL, "mmc_ick", "mmc_ick"),
+       DT_CLK("mmci-omap.0", "fck", "mmc_fck"),
+       DT_CLK(NULL, "mmc_fck", "mmc_fck"),
+       DT_CLK(NULL, "eac_ick", "eac_ick"),
+       DT_CLK(NULL, "eac_fck", "eac_fck"),
+       DT_CLK(NULL, "i2c1_fck", "i2c1_fck"),
+       DT_CLK(NULL, "i2c2_fck", "i2c2_fck"),
+       DT_CLK(NULL, "vlynq_ick", "vlynq_ick"),
+       DT_CLK(NULL, "vlynq_fck", "vlynq_fck"),
+       DT_CLK("musb-hdrc", "fck", "osc_ck"),
+       { .node_name = NULL },
+};
+
+static struct ti_dt_clk omap2430_clks[] = {
+       DT_CLK("twl", "fck", "osc_ck"),
+       DT_CLK(NULL, "iva2_1_ick", "iva2_1_ick"),
+       DT_CLK(NULL, "mdm_ick", "mdm_ick"),
+       DT_CLK(NULL, "mdm_osc_ck", "mdm_osc_ck"),
+       DT_CLK("omap-mcbsp.3", "ick", "mcbsp3_ick"),
+       DT_CLK(NULL, "mcbsp3_ick", "mcbsp3_ick"),
+       DT_CLK(NULL, "mcbsp3_fck", "mcbsp3_fck"),
+       DT_CLK("omap-mcbsp.4", "ick", "mcbsp4_ick"),
+       DT_CLK(NULL, "mcbsp4_ick", "mcbsp4_ick"),
+       DT_CLK(NULL, "mcbsp4_fck", "mcbsp4_fck"),
+       DT_CLK("omap-mcbsp.5", "ick", "mcbsp5_ick"),
+       DT_CLK(NULL, "mcbsp5_ick", "mcbsp5_ick"),
+       DT_CLK(NULL, "mcbsp5_fck", "mcbsp5_fck"),
+       DT_CLK("omap2_mcspi.3", "ick", "mcspi3_ick"),
+       DT_CLK(NULL, "mcspi3_ick", "mcspi3_ick"),
+       DT_CLK(NULL, "mcspi3_fck", "mcspi3_fck"),
+       DT_CLK(NULL, "icr_ick", "icr_ick"),
+       DT_CLK(NULL, "i2chs1_fck", "i2chs1_fck"),
+       DT_CLK(NULL, "i2chs2_fck", "i2chs2_fck"),
+       DT_CLK("musb-omap2430", "ick", "usbhs_ick"),
+       DT_CLK(NULL, "usbhs_ick", "usbhs_ick"),
+       DT_CLK("omap_hsmmc.0", "ick", "mmchs1_ick"),
+       DT_CLK(NULL, "mmchs1_ick", "mmchs1_ick"),
+       DT_CLK(NULL, "mmchs1_fck", "mmchs1_fck"),
+       DT_CLK("omap_hsmmc.1", "ick", "mmchs2_ick"),
+       DT_CLK(NULL, "mmchs2_ick", "mmchs2_ick"),
+       DT_CLK(NULL, "mmchs2_fck", "mmchs2_fck"),
+       DT_CLK(NULL, "gpio5_ick", "gpio5_ick"),
+       DT_CLK(NULL, "gpio5_fck", "gpio5_fck"),
+       DT_CLK(NULL, "mdm_intc_ick", "mdm_intc_ick"),
+       DT_CLK("omap_hsmmc.0", "mmchsdb_fck", "mmchsdb1_fck"),
+       DT_CLK(NULL, "mmchsdb1_fck", "mmchsdb1_fck"),
+       DT_CLK("omap_hsmmc.1", "mmchsdb_fck", "mmchsdb2_fck"),
+       DT_CLK(NULL, "mmchsdb2_fck", "mmchsdb2_fck"),
+       { .node_name = NULL },
+};
+
+static const char *enable_init_clks[] = {
+       "apll96_ck",
+       "apll54_ck",
+       "sync_32k_ick",
+       "omapctrl_ick",
+       "gpmc_fck",
+       "sdrc_ick",
+};
+
+enum {
+       OMAP2_SOC_OMAP2420,
+       OMAP2_SOC_OMAP2430,
+};
+
+static int __init omap2xxx_dt_clk_init(int soc_type)
+{
+       ti_dt_clocks_register(omap2xxx_clks);
+
+       if (soc_type == OMAP2_SOC_OMAP2420)
+               ti_dt_clocks_register(omap2420_clks);
+       else
+               ti_dt_clocks_register(omap2430_clks);
+
+       omap2xxx_clkt_vps_init();
+
+       omap2_clk_disable_autoidle_all();
+
+       omap2_clk_enable_init_clocks(enable_init_clks,
+                                    ARRAY_SIZE(enable_init_clks));
+
+       pr_info("Clocking rate (Crystal/DPLL/MPU): %ld.%01ld/%ld/%ld MHz\n",
+               (clk_get_rate(clk_get_sys(NULL, "sys_ck")) / 1000000),
+               (clk_get_rate(clk_get_sys(NULL, "sys_ck")) / 100000) % 10,
+               (clk_get_rate(clk_get_sys(NULL, "dpll_ck")) / 1000000),
+               (clk_get_rate(clk_get_sys(NULL, "mpu_ck")) / 1000000));
+
+       return 0;
+}
+
+int __init omap2420_dt_clk_init(void)
+{
+       return omap2xxx_dt_clk_init(OMAP2_SOC_OMAP2420);
+}
+
+int __init omap2430_dt_clk_init(void)
+{
+       return omap2xxx_dt_clk_init(OMAP2_SOC_OMAP2430);
+}
index 08f3d1b915b396d393e2a9bf0aa444784f39388d..5e183993e3ec56b926fffd252325000d02566d03 100644 (file)
@@ -240,6 +240,12 @@ int __init omap5xxx_dt_clk_init(void)
        if (rc)
                pr_err("%s: failed to configure ABE DPLL!\n", __func__);
 
+       abe_dpll = clk_get_sys(NULL, "dpll_abe_m2x2_ck");
+       if (!rc)
+               rc = clk_set_rate(abe_dpll, OMAP5_DPLL_ABE_DEFFREQ * 2);
+       if (rc)
+               pr_err("%s: failed to configure ABE m2x2 DPLL!\n", __func__);
+
        usb_dpll = clk_get_sys(NULL, "dpll_usb_ck");
        rc = clk_set_rate(usb_dpll, OMAP5_DPLL_USB_DEFFREQ);
        if (rc)
index f7e40734c819f045caa9be5f5a32c299c7fa3344..e1581335937d274dfddfd502cd5c4c896b305267 100644 (file)
@@ -24,7 +24,7 @@ static struct ti_dt_clk dra7xx_clks[] = {
        DT_CLK(NULL, "atl_clkin0_ck", "atl_clkin0_ck"),
        DT_CLK(NULL, "atl_clkin1_ck", "atl_clkin1_ck"),
        DT_CLK(NULL, "atl_clkin2_ck", "atl_clkin2_ck"),
-       DT_CLK(NULL, "atlclkin3_ck", "atlclkin3_ck"),
+       DT_CLK(NULL, "atl_clkin3_ck", "atl_clkin3_ck"),
        DT_CLK(NULL, "hdmi_clkin_ck", "hdmi_clkin_ck"),
        DT_CLK(NULL, "mlb_clkin_ck", "mlb_clkin_ck"),
        DT_CLK(NULL, "mlbp_clkin_ck", "mlbp_clkin_ck"),
diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c
new file mode 100644 (file)
index 0000000..4a65b41
--- /dev/null
@@ -0,0 +1,312 @@
+/*
+ * DRA7 ATL (Audio Tracking Logic) clock driver
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/clk-provider.h>
+#include <linux/slab.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/pm_runtime.h>
+
+#define DRA7_ATL_INSTANCES     4
+
+#define DRA7_ATL_PPMR_REG(id)          (0x200 + (id * 0x80))
+#define DRA7_ATL_BBSR_REG(id)          (0x204 + (id * 0x80))
+#define DRA7_ATL_ATLCR_REG(id)         (0x208 + (id * 0x80))
+#define DRA7_ATL_SWEN_REG(id)          (0x210 + (id * 0x80))
+#define DRA7_ATL_BWSMUX_REG(id)                (0x214 + (id * 0x80))
+#define DRA7_ATL_AWSMUX_REG(id)                (0x218 + (id * 0x80))
+#define DRA7_ATL_PCLKMUX_REG(id)       (0x21c + (id * 0x80))
+
+#define DRA7_ATL_SWEN                  BIT(0)
+#define DRA7_ATL_DIVIDER_MASK          (0x1f)
+#define DRA7_ATL_PCLKMUX               BIT(0)
+struct dra7_atl_clock_info;
+
+struct dra7_atl_desc {
+       struct clk *clk;
+       struct clk_hw hw;
+       struct dra7_atl_clock_info *cinfo;
+       int id;
+
+       bool probed;            /* the driver for the IP has been loaded */
+       bool valid;             /* configured */
+       bool enabled;
+       u32 bws;                /* Baseband Word Select Mux */
+       u32 aws;                /* Audio Word Select Mux */
+       u32 divider;            /* Cached divider value */
+};
+
+struct dra7_atl_clock_info {
+       struct device *dev;
+       void __iomem *iobase;
+
+       struct dra7_atl_desc *cdesc;
+};
+
+#define to_atl_desc(_hw)       container_of(_hw, struct dra7_atl_desc, hw)
+
+static inline void atl_write(struct dra7_atl_clock_info *cinfo, u32 reg,
+                            u32 val)
+{
+       __raw_writel(val, cinfo->iobase + reg);
+}
+
+static inline int atl_read(struct dra7_atl_clock_info *cinfo, u32 reg)
+{
+       return __raw_readl(cinfo->iobase + reg);
+}
+
+static int atl_clk_enable(struct clk_hw *hw)
+{
+       struct dra7_atl_desc *cdesc = to_atl_desc(hw);
+
+       if (!cdesc->probed)
+               goto out;
+
+       if (unlikely(!cdesc->valid))
+               dev_warn(cdesc->cinfo->dev, "atl%d has not been configured\n",
+                        cdesc->id);
+       pm_runtime_get_sync(cdesc->cinfo->dev);
+
+       atl_write(cdesc->cinfo, DRA7_ATL_ATLCR_REG(cdesc->id),
+                 cdesc->divider - 1);
+       atl_write(cdesc->cinfo, DRA7_ATL_SWEN_REG(cdesc->id), DRA7_ATL_SWEN);
+
+out:
+       cdesc->enabled = true;
+
+       return 0;
+}
+
+static void atl_clk_disable(struct clk_hw *hw)
+{
+       struct dra7_atl_desc *cdesc = to_atl_desc(hw);
+
+       if (!cdesc->probed)
+               goto out;
+
+       atl_write(cdesc->cinfo, DRA7_ATL_SWEN_REG(cdesc->id), 0);
+       pm_runtime_put_sync(cdesc->cinfo->dev);
+
+out:
+       cdesc->enabled = false;
+}
+
+static int atl_clk_is_enabled(struct clk_hw *hw)
+{
+       struct dra7_atl_desc *cdesc = to_atl_desc(hw);
+
+       return cdesc->enabled;
+}
+
+static unsigned long atl_clk_recalc_rate(struct clk_hw *hw,
+                                        unsigned long parent_rate)
+{
+       struct dra7_atl_desc *cdesc = to_atl_desc(hw);
+
+       return parent_rate / cdesc->divider;
+}
+
+static long atl_clk_round_rate(struct clk_hw *hw, unsigned long rate,
+                              unsigned long *parent_rate)
+{
+       unsigned divider;
+
+       divider = (*parent_rate + rate / 2) / rate;
+       if (divider > DRA7_ATL_DIVIDER_MASK + 1)
+               divider = DRA7_ATL_DIVIDER_MASK + 1;
+
+       return *parent_rate / divider;
+}
+
+static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate,
+                           unsigned long parent_rate)
+{
+       struct dra7_atl_desc *cdesc = to_atl_desc(hw);
+       u32 divider;
+
+       divider = ((parent_rate + rate / 2) / rate) - 1;
+       if (divider > DRA7_ATL_DIVIDER_MASK)
+               divider = DRA7_ATL_DIVIDER_MASK;
+
+       cdesc->divider = divider + 1;
+
+       return 0;
+}
+
+const struct clk_ops atl_clk_ops = {
+       .enable         = atl_clk_enable,
+       .disable        = atl_clk_disable,
+       .is_enabled     = atl_clk_is_enabled,
+       .recalc_rate    = atl_clk_recalc_rate,
+       .round_rate     = atl_clk_round_rate,
+       .set_rate       = atl_clk_set_rate,
+};
+
+static void __init of_dra7_atl_clock_setup(struct device_node *node)
+{
+       struct dra7_atl_desc *clk_hw = NULL;
+       struct clk_init_data init = { 0 };
+       const char **parent_names = NULL;
+       struct clk *clk;
+
+       clk_hw = kzalloc(sizeof(*clk_hw), GFP_KERNEL);
+       if (!clk_hw) {
+               pr_err("%s: could not allocate dra7_atl_desc\n", __func__);
+               return;
+       }
+
+       clk_hw->hw.init = &init;
+       clk_hw->divider = 1;
+       init.name = node->name;
+       init.ops = &atl_clk_ops;
+       init.flags = CLK_IGNORE_UNUSED;
+       init.num_parents = of_clk_get_parent_count(node);
+
+       if (init.num_parents != 1) {
+               pr_err("%s: atl clock %s must have 1 parent\n", __func__,
+                      node->name);
+               goto cleanup;
+       }
+
+       parent_names = kzalloc(sizeof(char *), GFP_KERNEL);
+
+       if (!parent_names)
+               goto cleanup;
+
+       parent_names[0] = of_clk_get_parent_name(node, 0);
+
+       init.parent_names = parent_names;
+
+       clk = clk_register(NULL, &clk_hw->hw);
+
+       if (!IS_ERR(clk)) {
+               of_clk_add_provider(node, of_clk_src_simple_get, clk);
+               return;
+       }
+cleanup:
+       kfree(parent_names);
+       kfree(clk_hw);
+}
+CLK_OF_DECLARE(dra7_atl_clock, "ti,dra7-atl-clock", of_dra7_atl_clock_setup);
+
+static int of_dra7_atl_clk_probe(struct platform_device *pdev)
+{
+       struct device_node *node = pdev->dev.of_node;
+       struct dra7_atl_clock_info *cinfo;
+       int i;
+       int ret = 0;
+
+       if (!node)
+               return -ENODEV;
+
+       cinfo = devm_kzalloc(&pdev->dev, sizeof(*cinfo), GFP_KERNEL);
+       if (!cinfo)
+               return -ENOMEM;
+
+       cinfo->iobase = of_iomap(node, 0);
+       cinfo->dev = &pdev->dev;
+       pm_runtime_enable(cinfo->dev);
+
+       pm_runtime_get_sync(cinfo->dev);
+       atl_write(cinfo, DRA7_ATL_PCLKMUX_REG(0), DRA7_ATL_PCLKMUX);
+
+       for (i = 0; i < DRA7_ATL_INSTANCES; i++) {
+               struct device_node *cfg_node;
+               char prop[5];
+               struct dra7_atl_desc *cdesc;
+               struct of_phandle_args clkspec;
+               struct clk *clk;
+               int rc;
+
+               rc = of_parse_phandle_with_args(node, "ti,provided-clocks",
+                                               NULL, i, &clkspec);
+
+               if (rc) {
+                       pr_err("%s: failed to lookup atl clock %d\n", __func__,
+                              i);
+                       return -EINVAL;
+               }
+
+               clk = of_clk_get_from_provider(&clkspec);
+
+               cdesc = to_atl_desc(__clk_get_hw(clk));
+               cdesc->cinfo = cinfo;
+               cdesc->id = i;
+
+               /* Get configuration for the ATL instances */
+               snprintf(prop, sizeof(prop), "atl%u", i);
+               cfg_node = of_find_node_by_name(node, prop);
+               if (cfg_node) {
+                       ret = of_property_read_u32(cfg_node, "bws",
+                                                  &cdesc->bws);
+                       ret |= of_property_read_u32(cfg_node, "aws",
+                                                   &cdesc->aws);
+                       if (!ret) {
+                               cdesc->valid = true;
+                               atl_write(cinfo, DRA7_ATL_BWSMUX_REG(i),
+                                         cdesc->bws);
+                               atl_write(cinfo, DRA7_ATL_AWSMUX_REG(i),
+                                         cdesc->aws);
+                       }
+               }
+
+               cdesc->probed = true;
+               /*
+                * Enable the clock if it has been asked prior to loading the
+                * hw driver
+                */
+               if (cdesc->enabled)
+                       atl_clk_enable(__clk_get_hw(clk));
+       }
+       pm_runtime_put_sync(cinfo->dev);
+
+       return ret;
+}
+
+static int of_dra7_atl_clk_remove(struct platform_device *pdev)
+{
+       pm_runtime_disable(&pdev->dev);
+
+       return 0;
+}
+
+static struct of_device_id of_dra7_atl_clk_match_tbl[] = {
+       { .compatible = "ti,dra7-atl", },
+       {},
+};
+MODULE_DEVICE_TABLE(of, of_dra7_atl_clk_match_tbl);
+
+static struct platform_driver dra7_atl_clk_driver = {
+       .driver = {
+               .name = "dra7-atl",
+               .owner = THIS_MODULE,
+               .of_match_table = of_dra7_atl_clk_match_tbl,
+       },
+       .probe = of_dra7_atl_clk_probe,
+       .remove = of_dra7_atl_clk_remove,
+};
+
+module_platform_driver(dra7_atl_clk_driver);
+
+MODULE_DESCRIPTION("Clock driver for DRA7 Audio Tracking Logic");
+MODULE_ALIAS("platform:dra7-atl-clock");
+MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
+MODULE_LICENSE("GPL v2");
index 7e498a44f97dea25af8db165cde8aac07ba78361..abd956d5f83811b3b53be1d63a708248c0faa6b5 100644 (file)
@@ -25,8 +25,6 @@
 #undef pr_fmt
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
-#define DPLL_HAS_AUTOIDLE      0x1
-
 #if defined(CONFIG_ARCH_OMAP4) || defined(CONFIG_SOC_OMAP5) || \
        defined(CONFIG_SOC_DRA7XX)
 static const struct clk_ops dpll_m4xen_ck_ops = {
@@ -37,21 +35,18 @@ static const struct clk_ops dpll_m4xen_ck_ops = {
        .set_rate       = &omap3_noncore_dpll_set_rate,
        .get_parent     = &omap2_init_dpll_parent,
 };
+#else
+static const struct clk_ops dpll_m4xen_ck_ops = {};
 #endif
 
+#if defined(CONFIG_ARCH_OMAP3) || defined(CONFIG_ARCH_OMAP4) || \
+       defined(CONFIG_SOC_OMAP5) || defined(CONFIG_SOC_DRA7XX) || \
+       defined(CONFIG_SOC_AM33XX) || defined(CONFIG_SOC_AM43XX)
 static const struct clk_ops dpll_core_ck_ops = {
        .recalc_rate    = &omap3_dpll_recalc,
        .get_parent     = &omap2_init_dpll_parent,
 };
 
-#ifdef CONFIG_ARCH_OMAP3
-static const struct clk_ops omap3_dpll_core_ck_ops = {
-       .get_parent     = &omap2_init_dpll_parent,
-       .recalc_rate    = &omap3_dpll_recalc,
-       .round_rate     = &omap2_dpll_round_rate,
-};
-#endif
-
 static const struct clk_ops dpll_ck_ops = {
        .enable         = &omap3_noncore_dpll_enable,
        .disable        = &omap3_noncore_dpll_disable,
@@ -67,6 +62,33 @@ static const struct clk_ops dpll_no_gate_ck_ops = {
        .round_rate     = &omap2_dpll_round_rate,
        .set_rate       = &omap3_noncore_dpll_set_rate,
 };
+#else
+static const struct clk_ops dpll_core_ck_ops = {};
+static const struct clk_ops dpll_ck_ops = {};
+static const struct clk_ops dpll_no_gate_ck_ops = {};
+const struct clk_hw_omap_ops clkhwops_omap3_dpll = {};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP2
+static const struct clk_ops omap2_dpll_core_ck_ops = {
+       .get_parent     = &omap2_init_dpll_parent,
+       .recalc_rate    = &omap2_dpllcore_recalc,
+       .round_rate     = &omap2_dpll_round_rate,
+       .set_rate       = &omap2_reprogram_dpllcore,
+};
+#else
+static const struct clk_ops omap2_dpll_core_ck_ops = {};
+#endif
+
+#ifdef CONFIG_ARCH_OMAP3
+static const struct clk_ops omap3_dpll_core_ck_ops = {
+       .get_parent     = &omap2_init_dpll_parent,
+       .recalc_rate    = &omap3_dpll_recalc,
+       .round_rate     = &omap2_dpll_round_rate,
+};
+#else
+static const struct clk_ops omap3_dpll_core_ck_ops = {};
+#endif
 
 #ifdef CONFIG_ARCH_OMAP3
 static const struct clk_ops omap3_dpll_ck_ops = {
@@ -193,14 +215,12 @@ static void ti_clk_register_dpll_x2(struct device_node *node,
  * @node: device node containing the DPLL info
  * @ops: ops for the DPLL
  * @ddt: DPLL data template to use
- * @init_flags: flags for controlling init types
  *
  * Initializes a DPLL clock from device tree data.
  */
 static void __init of_ti_dpll_setup(struct device_node *node,
                                    const struct clk_ops *ops,
-                                   const struct dpll_data *ddt,
-                                   u8 init_flags)
+                                   const struct dpll_data *ddt)
 {
        struct clk_hw_omap *clk_hw = NULL;
        struct clk_init_data *init = NULL;
@@ -241,13 +261,30 @@ static void __init of_ti_dpll_setup(struct device_node *node,
        init->parent_names = parent_names;
 
        dd->control_reg = ti_clk_get_reg_addr(node, 0);
-       dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
-       dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
 
-       if (!dd->control_reg || !dd->idlest_reg || !dd->mult_div1_reg)
+       /*
+        * Special case for OMAP2 DPLL, register order is different due to
+        * missing idlest_reg, also clkhwops is different. Detected from
+        * missing idlest_mask.
+        */
+       if (!dd->idlest_mask) {
+               dd->mult_div1_reg = ti_clk_get_reg_addr(node, 1);
+#ifdef CONFIG_ARCH_OMAP2
+               clk_hw->ops = &clkhwops_omap2xxx_dpll;
+               omap2xxx_clkt_dpllcore_init(&clk_hw->hw);
+#endif
+       } else {
+               dd->idlest_reg = ti_clk_get_reg_addr(node, 1);
+               if (!dd->idlest_reg)
+                       goto cleanup;
+
+               dd->mult_div1_reg = ti_clk_get_reg_addr(node, 2);
+       }
+
+       if (!dd->control_reg || !dd->mult_div1_reg)
                goto cleanup;
 
-       if (init_flags & DPLL_HAS_AUTOIDLE) {
+       if (dd->autoidle_mask) {
                dd->autoidle_reg = ti_clk_get_reg_addr(node, 3);
                if (!dd->autoidle_reg)
                        goto cleanup;
@@ -310,7 +347,7 @@ static void __init of_ti_omap3_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+       of_ti_dpll_setup(node, &omap3_dpll_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap3_dpll_clock, "ti,omap3-dpll-clock",
               of_ti_omap3_dpll_setup);
@@ -329,7 +366,7 @@ static void __init of_ti_omap3_core_dpll_setup(struct device_node *node)
                .freqsel_mask = 0xf0,
        };
 
-       of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+       of_ti_dpll_setup(node, &omap3_dpll_core_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap3_core_dpll_clock, "ti,omap3-dpll-core-clock",
               of_ti_omap3_core_dpll_setup);
@@ -349,7 +386,7 @@ static void __init of_ti_omap3_per_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+       of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap3_per_dpll_clock, "ti,omap3-dpll-per-clock",
               of_ti_omap3_per_dpll_setup);
@@ -371,7 +408,7 @@ static void __init of_ti_omap3_per_jtype_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_STOP) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+       of_ti_dpll_setup(node, &omap3_dpll_per_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap3_per_jtype_dpll_clock, "ti,omap3-dpll-per-j-type-clock",
               of_ti_omap3_per_jtype_dpll_setup);
@@ -391,11 +428,32 @@ static void __init of_ti_omap4_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &dpll_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+       of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap4_dpll_clock, "ti,omap4-dpll-clock",
               of_ti_omap4_dpll_setup);
 
+static void __init of_ti_omap5_mpu_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .idlest_mask = 0x1,
+               .enable_mask = 0x7,
+               .autoidle_mask = 0x7,
+               .mult_mask = 0x7ff << 8,
+               .div1_mask = 0x7f,
+               .max_multiplier = 2047,
+               .max_divider = 128,
+               .dcc_mask = BIT(22),
+               .dcc_rate = 1400000000, /* DCC beyond 1.4GHz */
+               .min_divider = 1,
+               .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
+       };
+
+       of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
+}
+CLK_OF_DECLARE(of_ti_omap5_mpu_dpll_clock, "ti,omap5-mpu-dpll-clock",
+              of_ti_omap5_mpu_dpll_setup);
+
 static void __init of_ti_omap4_core_dpll_setup(struct device_node *node)
 {
        const struct dpll_data dd = {
@@ -410,7 +468,7 @@ static void __init of_ti_omap4_core_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+       of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap4_core_dpll_clock, "ti,omap4-dpll-core-clock",
               of_ti_omap4_core_dpll_setup);
@@ -433,7 +491,7 @@ static void __init of_ti_omap4_m4xen_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+       of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap4_m4xen_dpll_clock, "ti,omap4-dpll-m4xen-clock",
               of_ti_omap4_m4xen_dpll_setup);
@@ -454,7 +512,7 @@ static void __init of_ti_omap4_jtype_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd, DPLL_HAS_AUTOIDLE);
+       of_ti_dpll_setup(node, &dpll_m4xen_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_omap4_jtype_dpll_clock, "ti,omap4-dpll-j-type-clock",
               of_ti_omap4_jtype_dpll_setup);
@@ -465,7 +523,6 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node)
        const struct dpll_data dd = {
                .idlest_mask = 0x1,
                .enable_mask = 0x7,
-               .autoidle_mask = 0x7,
                .mult_mask = 0x7ff << 8,
                .div1_mask = 0x7f,
                .max_multiplier = 2047,
@@ -474,7 +531,7 @@ static void __init of_ti_am3_no_gate_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0);
+       of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_am3_no_gate_dpll_clock, "ti,am3-dpll-no-gate-clock",
               of_ti_am3_no_gate_dpll_setup);
@@ -484,7 +541,6 @@ static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node)
        const struct dpll_data dd = {
                .idlest_mask = 0x1,
                .enable_mask = 0x7,
-               .autoidle_mask = 0x7,
                .mult_mask = 0x7ff << 8,
                .div1_mask = 0x7f,
                .max_multiplier = 4095,
@@ -494,7 +550,7 @@ static void __init of_ti_am3_jtype_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0);
+       of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_am3_jtype_dpll_clock, "ti,am3-dpll-j-type-clock",
               of_ti_am3_jtype_dpll_setup);
@@ -504,7 +560,6 @@ static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node)
        const struct dpll_data dd = {
                .idlest_mask = 0x1,
                .enable_mask = 0x7,
-               .autoidle_mask = 0x7,
                .mult_mask = 0x7ff << 8,
                .div1_mask = 0x7f,
                .max_multiplier = 2047,
@@ -514,7 +569,7 @@ static void __init of_ti_am3_no_gate_jtype_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd, 0);
+       of_ti_dpll_setup(node, &dpll_no_gate_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_am3_no_gate_jtype_dpll_clock,
               "ti,am3-dpll-no-gate-j-type-clock",
@@ -525,7 +580,6 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node)
        const struct dpll_data dd = {
                .idlest_mask = 0x1,
                .enable_mask = 0x7,
-               .autoidle_mask = 0x7,
                .mult_mask = 0x7ff << 8,
                .div1_mask = 0x7f,
                .max_multiplier = 2047,
@@ -534,7 +588,7 @@ static void __init of_ti_am3_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &dpll_ck_ops, &dd, 0);
+       of_ti_dpll_setup(node, &dpll_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_am3_dpll_clock, "ti,am3-dpll-clock", of_ti_am3_dpll_setup);
 
@@ -543,7 +597,6 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node)
        const struct dpll_data dd = {
                .idlest_mask = 0x1,
                .enable_mask = 0x7,
-               .autoidle_mask = 0x7,
                .mult_mask = 0x7ff << 8,
                .div1_mask = 0x7f,
                .max_multiplier = 2047,
@@ -552,7 +605,22 @@ static void __init of_ti_am3_core_dpll_setup(struct device_node *node)
                .modes = (1 << DPLL_LOW_POWER_BYPASS) | (1 << DPLL_LOCKED),
        };
 
-       of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd, 0);
+       of_ti_dpll_setup(node, &dpll_core_ck_ops, &dd);
 }
 CLK_OF_DECLARE(ti_am3_core_dpll_clock, "ti,am3-dpll-core-clock",
               of_ti_am3_core_dpll_setup);
+
+static void __init of_ti_omap2_core_dpll_setup(struct device_node *node)
+{
+       const struct dpll_data dd = {
+               .enable_mask = 0x3,
+               .mult_mask = 0x3ff << 12,
+               .div1_mask = 0xf << 8,
+               .max_divider = 16,
+               .min_divider = 1,
+       };
+
+       of_ti_dpll_setup(node, &omap2_dpll_core_ck_ops, &dd);
+}
+CLK_OF_DECLARE(ti_omap2_core_dpll_clock, "ti,omap2-dpll-core-clock",
+              of_ti_omap2_core_dpll_setup);
index 58734817d5027956107fef67847f2585a691afdc..b326d2797feb23c0ed84fe52be5b9905102f0234 100644 (file)
@@ -185,7 +185,7 @@ of_ti_composite_no_wait_gate_clk_setup(struct device_node *node)
 CLK_OF_DECLARE(ti_composite_no_wait_gate_clk, "ti,composite-no-wait-gate-clock",
               of_ti_composite_no_wait_gate_clk_setup);
 
-#ifdef CONFIG_ARCH_OMAP3
+#if defined(CONFIG_ARCH_OMAP2) || defined(CONFIG_ARCH_OMAP3)
 static void __init of_ti_composite_interface_clk_setup(struct device_node *node)
 {
        _of_ti_composite_gate_clk_setup(node, &clkhwops_iclk_wait);
index 320a2b168bb20fab7e69f812d4ca6307cb89b28c..9c3e8c4aaa40c0b8a46048bab734286941a77e6b 100644 (file)
@@ -94,6 +94,7 @@ static void __init of_ti_no_wait_interface_clk_setup(struct device_node *node)
 CLK_OF_DECLARE(ti_no_wait_interface_clk, "ti,omap3-no-wait-interface-clock",
               of_ti_no_wait_interface_clk_setup);
 
+#ifdef CONFIG_ARCH_OMAP3
 static void __init of_ti_hsotgusb_interface_clk_setup(struct device_node *node)
 {
        _of_ti_interface_clk_setup(node,
@@ -123,3 +124,13 @@ static void __init of_ti_am35xx_interface_clk_setup(struct device_node *node)
 }
 CLK_OF_DECLARE(ti_am35xx_interface_clk, "ti,am35xx-interface-clock",
               of_ti_am35xx_interface_clk_setup);
+#endif
+
+#ifdef CONFIG_SOC_OMAP2430
+static void __init of_ti_omap2430_interface_clk_setup(struct device_node *node)
+{
+       _of_ti_interface_clk_setup(node, &clkhwops_omap2430_i2chs_wait);
+}
+CLK_OF_DECLARE(ti_omap2430_interface_clk, "ti,omap2430-interface-clock",
+              of_ti_omap2430_interface_clk_setup);
+#endif
index 1610d51dbb5c5621499077114ad0b35cd762d19a..ade33ef82823b230a34890d77af039d8531aefb7 100644 (file)
@@ -1156,15 +1156,7 @@ static int vxlan_udp_encap_recv(struct sock *sk, struct sk_buff *skb)
        if (!vs)
                goto drop;
 
-       /* If the NIC driver gave us an encapsulated packet
-        * with the encapsulation mark, the device checksummed it
-        * for us. Otherwise force the upper layers to verify it.
-        */
-       if ((skb->ip_summed != CHECKSUM_UNNECESSARY && skb->ip_summed != CHECKSUM_PARTIAL) ||
-           !skb->encapsulation)
-               skb->ip_summed = CHECKSUM_NONE;
-
-       skb->encapsulation = 0;
+       skb_pop_rcv_encapsulation(skb);
 
        vs->rcv(vs, skb, vxh->vx_vni);
        return 0;
@@ -1201,6 +1193,7 @@ static void vxlan_rcv(struct vxlan_sock *vs,
        skb_reset_mac_header(skb);
        skb_scrub_packet(skb, !net_eq(vxlan->net, dev_net(vxlan->dev)));
        skb->protocol = eth_type_trans(skb, vxlan->dev);
+       skb_postpull_rcsum(skb, eth_hdr(skb), ETH_HLEN);
 
        /* Ignore packet loops (and multicast echo) */
        if (ether_addr_equal(eth_hdr(skb)->h_source, vxlan->dev->dev_addr))
@@ -2247,9 +2240,9 @@ static void vxlan_setup(struct net_device *dev)
        eth_hw_addr_random(dev);
        ether_setup(dev);
        if (vxlan->default_dst.remote_ip.sa.sa_family == AF_INET6)
-               dev->hard_header_len = ETH_HLEN + VXLAN6_HEADROOM;
+               dev->needed_headroom = ETH_HLEN + VXLAN6_HEADROOM;
        else
-               dev->hard_header_len = ETH_HLEN + VXLAN_HEADROOM;
+               dev->needed_headroom = ETH_HLEN + VXLAN_HEADROOM;
 
        dev->netdev_ops = &vxlan_netdev_ops;
        dev->destructor = free_netdev;
@@ -2646,8 +2639,7 @@ static int vxlan_newlink(struct net *net, struct net_device *dev,
                if (!tb[IFLA_MTU])
                        dev->mtu = lowerdev->mtu - (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
 
-               /* update header length based on lower device */
-               dev->hard_header_len = lowerdev->hard_header_len +
+               dev->needed_headroom = lowerdev->hard_header_len +
                                       (use_ipv6 ? VXLAN6_HEADROOM : VXLAN_HEADROOM);
        } else if (use_ipv6)
                vxlan->flags |= VXLAN_F_IPV6;
diff --git a/include/dt-bindings/clk/ti-dra7-atl.h b/include/dt-bindings/clk/ti-dra7-atl.h
new file mode 100644 (file)
index 0000000..42dd416
--- /dev/null
@@ -0,0 +1,40 @@
+/*
+ * This header provides constants for DRA7 ATL (Audio Tracking Logic)
+ *
+ * The constants defined in this header are used in dts files
+ *
+ * Copyright (C) 2013 Texas Instruments, Inc.
+ *
+ * Peter Ujfalusi <peter.ujfalusi@ti.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed "as is" WITHOUT ANY WARRANTY of any
+ * kind, whether express or implied; without even the implied warranty
+ * of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _DT_BINDINGS_CLK_DRA7_ATL_H
+#define _DT_BINDINGS_CLK_DRA7_ATL_H
+
+#define DRA7_ATL_WS_MCASP1_FSR         0
+#define DRA7_ATL_WS_MCASP1_FSX         1
+#define DRA7_ATL_WS_MCASP2_FSR         2
+#define DRA7_ATL_WS_MCASP2_FSX         3
+#define DRA7_ATL_WS_MCASP3_FSX         4
+#define DRA7_ATL_WS_MCASP4_FSX         5
+#define DRA7_ATL_WS_MCASP5_FSX         6
+#define DRA7_ATL_WS_MCASP6_FSX         7
+#define DRA7_ATL_WS_MCASP7_FSX         8
+#define DRA7_ATL_WS_MCASP8_FSX         9
+#define DRA7_ATL_WS_MCASP8_AHCLKX      10
+#define DRA7_ATL_WS_XREF_CLK3          11
+#define DRA7_ATL_WS_XREF_CLK0          12
+#define DRA7_ATL_WS_XREF_CLK1          13
+#define DRA7_ATL_WS_XREF_CLK2          14
+#define DRA7_ATL_WS_OSC1_X1            15
+
+#endif
index 4a21a872dbbd6423025f1a9253832f228cfe1c48..e8d8a35034a5e81c95e0471d0530f7c87a784db9 100644 (file)
@@ -41,6 +41,8 @@
  * @idlest_reg: register containing the DPLL idle status bitfield
  * @autoidle_mask: mask of the DPLL autoidle mode bitfield in @autoidle_reg
  * @freqsel_mask: mask of the DPLL jitter correction bitfield in @control_reg
+ * @dcc_mask: mask of the DPLL DCC correction bitfield @mult_div1_reg
+ * @dcc_rate: rate atleast which DCC @dcc_mask must be set
  * @idlest_mask: mask of the DPLL idle status bitfield in @idlest_reg
  * @lpmode_mask: mask of the DPLL low-power mode bitfield in @control_reg
  * @m4xen_mask: mask of the DPLL M4X multiplier bitfield in @control_reg
@@ -86,6 +88,8 @@ struct dpll_data {
        u32                     idlest_mask;
        u32                     dco_mask;
        u32                     sddiv_mask;
+       u32                     dcc_mask;
+       unsigned long           dcc_rate;
        u32                     lpmode_mask;
        u32                     m4xen_mask;
        u8                      auto_recal_bit;
@@ -94,7 +98,26 @@ struct dpll_data {
        u8                      flags;
 };
 
-struct clk_hw_omap_ops;
+struct clk_hw_omap;
+
+/**
+ * struct clk_hw_omap_ops - OMAP clk ops
+ * @find_idlest: find idlest register information for a clock
+ * @find_companion: find companion clock register information for a clock,
+ *                 basically converts CM_ICLKEN* <-> CM_FCLKEN*
+ * @allow_idle: enables autoidle hardware functionality for a clock
+ * @deny_idle: prevent autoidle hardware functionality for a clock
+ */
+struct clk_hw_omap_ops {
+       void    (*find_idlest)(struct clk_hw_omap *oclk,
+                              void __iomem **idlest_reg,
+                              u8 *idlest_bit, u8 *idlest_val);
+       void    (*find_companion)(struct clk_hw_omap *oclk,
+                                 void __iomem **other_reg,
+                                 u8 *other_bit);
+       void    (*allow_idle)(struct clk_hw_omap *oclk);
+       void    (*deny_idle)(struct clk_hw_omap *oclk);
+};
 
 /**
  * struct clk_hw_omap - OMAP struct clk
@@ -259,6 +282,12 @@ int omap2_dflt_clk_enable(struct clk_hw *hw);
 void omap2_dflt_clk_disable(struct clk_hw *hw);
 int omap2_dflt_clk_is_enabled(struct clk_hw *hw);
 void omap3_clk_lock_dpll5(void);
+unsigned long omap2_dpllcore_recalc(struct clk_hw *hw,
+                                   unsigned long parent_rate);
+int omap2_reprogram_dpllcore(struct clk_hw *clk, unsigned long rate,
+                            unsigned long parent_rate);
+void omap2xxx_clkt_dpllcore_init(struct clk_hw *hw);
+void omap2xxx_clkt_vps_init(void);
 
 void __iomem *ti_clk_get_reg_addr(struct device_node *node, int index);
 void ti_dt_clocks_register(struct ti_dt_clk *oclks);
@@ -278,6 +307,8 @@ int omap5xxx_dt_clk_init(void);
 int dra7xx_dt_clk_init(void);
 int am33xx_dt_clk_init(void);
 int am43xx_dt_clk_init(void);
+int omap2420_dt_clk_init(void);
+int omap2430_dt_clk_init(void);
 
 #ifdef CONFIG_OF
 void of_ti_clk_allow_autoidle_all(void);
@@ -287,6 +318,8 @@ static inline void of_ti_clk_allow_autoidle_all(void) { }
 static inline void of_ti_clk_deny_autoidle_all(void) { }
 #endif
 
+extern const struct clk_hw_omap_ops clkhwops_omap2xxx_dpll;
+extern const struct clk_hw_omap_ops clkhwops_omap2430_i2chs_wait;
 extern const struct clk_hw_omap_ops clkhwops_omap3_dpll;
 extern const struct clk_hw_omap_ops clkhwops_omap4_dpllmx;
 extern const struct clk_hw_omap_ops clkhwops_wait;
index e5a589435e2b7df943a935b4cf6dfd6c46dd74ed..d99800cbdcf3b7b4029e4b3f325aec6b1e4382dc 100644 (file)
@@ -117,6 +117,7 @@ enum {
 #define NETIF_F_GSO_IPIP       __NETIF_F(GSO_IPIP)
 #define NETIF_F_GSO_SIT                __NETIF_F(GSO_SIT)
 #define NETIF_F_GSO_UDP_TUNNEL __NETIF_F(GSO_UDP_TUNNEL)
+#define NETIF_F_GSO_UDP_TUNNEL_CSUM __NETIF_F(GSO_UDP_TUNNEL_CSUM)
 #define NETIF_F_GSO_MPLS       __NETIF_F(GSO_MPLS)
 #define NETIF_F_HW_VLAN_STAG_FILTER __NETIF_F(HW_VLAN_STAG_FILTER)
 #define NETIF_F_HW_VLAN_STAG_RX        __NETIF_F(HW_VLAN_STAG_RX)
index abe3de1db932a09016d430ff699a993e6761bc83..66f9a04ec27041445afddbb70729b039719387c5 100644 (file)
@@ -3305,6 +3305,13 @@ static inline bool net_gso_ok(netdev_features_t features, int gso_type)
        BUILD_BUG_ON(SKB_GSO_TCP_ECN != (NETIF_F_TSO_ECN >> NETIF_F_GSO_SHIFT));
        BUILD_BUG_ON(SKB_GSO_TCPV6   != (NETIF_F_TSO6 >> NETIF_F_GSO_SHIFT));
        BUILD_BUG_ON(SKB_GSO_FCOE    != (NETIF_F_FSO >> NETIF_F_GSO_SHIFT));
+       BUILD_BUG_ON(SKB_GSO_GRE     != (NETIF_F_GSO_GRE >> NETIF_F_GSO_SHIFT));
+       BUILD_BUG_ON(SKB_GSO_GRE_CSUM != (NETIF_F_GSO_GRE_CSUM >> NETIF_F_GSO_SHIFT));
+       BUILD_BUG_ON(SKB_GSO_IPIP    != (NETIF_F_GSO_IPIP >> NETIF_F_GSO_SHIFT));
+       BUILD_BUG_ON(SKB_GSO_SIT     != (NETIF_F_GSO_SIT >> NETIF_F_GSO_SHIFT));
+       BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL != (NETIF_F_GSO_UDP_TUNNEL >> NETIF_F_GSO_SHIFT));
+       BUILD_BUG_ON(SKB_GSO_UDP_TUNNEL_CSUM != (NETIF_F_GSO_UDP_TUNNEL_CSUM >> NETIF_F_GSO_SHIFT));
+       BUILD_BUG_ON(SKB_GSO_MPLS    != (NETIF_F_GSO_MPLS >> NETIF_F_GSO_SHIFT));
 
        return (features & feature) == feature;
 }
index a50173ca1d729aba84bc00c2572b40a91ec93140..2bf403195c09fd5470cab096409c8ee7c260285f 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Definitions for the NVM Express interface
- * Copyright (c) 2011-2013, Intel Corporation.
+ * Copyright (c) 2011-2014, Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
  * 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #ifndef _LINUX_NVME_H
@@ -66,8 +62,8 @@ enum {
 
 #define NVME_VS(major, minor)  (major << 16 | minor)
 
-extern unsigned char io_timeout;
-#define NVME_IO_TIMEOUT        (io_timeout * HZ)
+extern unsigned char nvme_io_timeout;
+#define NVME_IO_TIMEOUT        (nvme_io_timeout * HZ)
 
 /*
  * Represents an NVM Express device.  Each nvme_dev is a PCI function.
@@ -94,7 +90,7 @@ struct nvme_dev {
        struct miscdevice miscdev;
        work_func_t reset_workfn;
        struct work_struct reset_work;
-       struct notifier_block nb;
+       struct work_struct cpu_work;
        char name[12];
        char serial[20];
        char model[40];
@@ -103,6 +99,7 @@ struct nvme_dev {
        u32 stripe_size;
        u16 oncs;
        u16 abort_limit;
+       u8 vwc;
        u8 initialized;
 };
 
@@ -159,7 +156,6 @@ struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
 void nvme_unmap_user_pages(struct nvme_dev *dev, int write,
                        struct nvme_iod *iod);
 int nvme_submit_io_cmd(struct nvme_dev *, struct nvme_command *, u32 *);
-int nvme_submit_flush_data(struct nvme_queue *nvmeq, struct nvme_ns *ns);
 int nvme_submit_admin_cmd(struct nvme_dev *, struct nvme_command *,
                                                        u32 *result);
 int nvme_identify(struct nvme_dev *, unsigned nsid, unsigned cns,
index 5b5cd3189c985f89a055e35d8d1c67c63879d8fc..ec89301ada418aff749bf924da1b7f63040ac048 100644 (file)
@@ -338,17 +338,18 @@ enum {
 
        SKB_GSO_GRE = 1 << 6,
 
-       SKB_GSO_IPIP = 1 << 7,
+       SKB_GSO_GRE_CSUM = 1 << 7,
 
-       SKB_GSO_SIT = 1 << 8,
+       SKB_GSO_IPIP = 1 << 8,
 
-       SKB_GSO_UDP_TUNNEL = 1 << 9,
+       SKB_GSO_SIT = 1 << 9,
 
-       SKB_GSO_MPLS = 1 << 10,
+       SKB_GSO_UDP_TUNNEL = 1 << 10,
 
        SKB_GSO_UDP_TUNNEL_CSUM = 1 << 11,
 
-       SKB_GSO_GRE_CSUM = 1 << 12,
+       SKB_GSO_MPLS = 1 << 12,
+
 };
 
 #if BITS_PER_LONG > 32
@@ -1853,6 +1854,18 @@ static inline int pskb_network_may_pull(struct sk_buff *skb, unsigned int len)
        return pskb_may_pull(skb, skb_network_offset(skb) + len);
 }
 
+static inline void skb_pop_rcv_encapsulation(struct sk_buff *skb)
+{
+       /* Only continue with checksum unnecessary if device indicated
+        * it is valid across encapsulation (skb->encapsulation was set).
+        */
+       if (skb->ip_summed == CHECKSUM_UNNECESSARY && !skb->encapsulation)
+               skb->ip_summed = CHECKSUM_NONE;
+
+       skb->encapsulation = 0;
+       skb->csum_valid = 0;
+}
+
 /*
  * CPUs often take a performance hit when accessing unaligned memory
  * locations. The actual performance hit varies, it can be small if the
index 2ecfc6e156098dbd37b3763a3040109a19e85810..68a1fefe3dfe46c3fc8f4847fa074fdb237573bb 100644 (file)
@@ -111,7 +111,9 @@ struct sk_buff;
  */
 static inline __sum16 __udp_lib_checksum_complete(struct sk_buff *skb)
 {
-       return __skb_checksum_complete_head(skb, UDP_SKB_CB(skb)->cscov);
+       return (UDP_SKB_CB(skb)->cscov == skb->len ?
+               __skb_checksum_complete(skb) :
+               __skb_checksum_complete_head(skb, UDP_SKB_CB(skb)->cscov));
 }
 
 static inline int udp_lib_checksum_complete(struct sk_buff *skb)
index 096fe1c6f83de5ef80bd56e69b177550c36fc0f3..29a7d8619d8dc2567b1119f30a37e8e247da5dc9 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * Definitions for the NVM Express interface
- * Copyright (c) 2011-2013, Intel Corporation.
+ * Copyright (c) 2011-2014, Intel Corporation.
  *
  * This program is free software; you can redistribute it and/or modify it
  * under the terms and conditions of the GNU General Public License,
  * 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 St - Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #ifndef _UAPI_LINUX_NVME_H
@@ -31,7 +27,12 @@ struct nvme_id_power_state {
        __u8                    read_lat;
        __u8                    write_tput;
        __u8                    write_lat;
-       __u8                    rsvd16[16];
+       __le16                  idle_power;
+       __u8                    idle_scale;
+       __u8                    rsvd19;
+       __le16                  active_power;
+       __u8                    active_work_scale;
+       __u8                    rsvd23[9];
 };
 
 enum {
@@ -49,7 +50,9 @@ struct nvme_id_ctrl {
        __u8                    ieee[3];
        __u8                    mic;
        __u8                    mdts;
-       __u8                    rsvd78[178];
+       __u16                   cntlid;
+       __u32                   ver;
+       __u8                    rsvd84[172];
        __le16                  oacs;
        __u8                    acl;
        __u8                    aerl;
@@ -57,7 +60,11 @@ struct nvme_id_ctrl {
        __u8                    lpa;
        __u8                    elpe;
        __u8                    npss;
-       __u8                    rsvd264[248];
+       __u8                    avscc;
+       __u8                    apsta;
+       __le16                  wctemp;
+       __le16                  cctemp;
+       __u8                    rsvd270[242];
        __u8                    sqes;
        __u8                    cqes;
        __u8                    rsvd514[2];
@@ -68,7 +75,12 @@ struct nvme_id_ctrl {
        __u8                    vwc;
        __le16                  awun;
        __le16                  awupf;
-       __u8                    rsvd530[1518];
+       __u8                    nvscc;
+       __u8                    rsvd531;
+       __le16                  acwu;
+       __u8                    rsvd534[2];
+       __le32                  sgls;
+       __u8                    rsvd540[1508];
        struct nvme_id_power_state      psd[32];
        __u8                    vs[1024];
 };
@@ -77,6 +89,7 @@ enum {
        NVME_CTRL_ONCS_COMPARE                  = 1 << 0,
        NVME_CTRL_ONCS_WRITE_UNCORRECTABLE      = 1 << 1,
        NVME_CTRL_ONCS_DSM                      = 1 << 2,
+       NVME_CTRL_VWC_PRESENT                   = 1 << 0,
 };
 
 struct nvme_lbaf {
@@ -95,7 +108,15 @@ struct nvme_id_ns {
        __u8                    mc;
        __u8                    dpc;
        __u8                    dps;
-       __u8                    rsvd30[98];
+       __u8                    nmic;
+       __u8                    rescap;
+       __u8                    fpi;
+       __u8                    rsvd33;
+       __le16                  nawun;
+       __le16                  nawupf;
+       __le16                  nacwu;
+       __u8                    rsvd40[80];
+       __u8                    eui64[8];
        struct nvme_lbaf        lbaf[16];
        __u8                    rsvd192[192];
        __u8                    vs[3712];
@@ -126,7 +147,10 @@ struct nvme_smart_log {
        __u8                    unsafe_shutdowns[16];
        __u8                    media_errors[16];
        __u8                    num_err_log_entries[16];
-       __u8                    rsvd192[320];
+       __le32                  warning_temp_time;
+       __le32                  critical_comp_time;
+       __le16                  temp_sensor[8];
+       __u8                    rsvd216[296];
 };
 
 enum {
@@ -282,6 +306,10 @@ enum {
        NVME_FEAT_WRITE_ATOMIC  = 0x0a,
        NVME_FEAT_ASYNC_EVENT   = 0x0b,
        NVME_FEAT_SW_PROGRESS   = 0x0c,
+       NVME_LOG_ERROR          = 0x01,
+       NVME_LOG_SMART          = 0x02,
+       NVME_LOG_FW_SLOT        = 0x03,
+       NVME_LOG_RESERVATION    = 0x80,
        NVME_FWACT_REPL         = (0 << 3),
        NVME_FWACT_REPL_ACTV    = (1 << 3),
        NVME_FWACT_ACTV         = (2 << 3),
index 6b1c04ca1d5090410f436fbf74e50813e09634c3..488dd1a825c05b704a26d8c88582454f1745be4c 100644 (file)
@@ -739,22 +739,38 @@ __sum16 __skb_checksum_complete_head(struct sk_buff *skb, int len)
        __sum16 sum;
 
        sum = csum_fold(skb_checksum(skb, 0, len, skb->csum));
-       if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) && !sum &&
-           !skb->csum_complete_sw)
-               netdev_rx_csum_fault(skb->dev);
-
-       /* Save checksum complete for later use */
-       skb->csum = sum;
-       skb->ip_summed = CHECKSUM_COMPLETE;
-       skb->csum_complete_sw = 1;
-
+       if (likely(!sum)) {
+               if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
+                   !skb->csum_complete_sw)
+                       netdev_rx_csum_fault(skb->dev);
+       }
+       skb->csum_valid = !sum;
        return sum;
 }
 EXPORT_SYMBOL(__skb_checksum_complete_head);
 
 __sum16 __skb_checksum_complete(struct sk_buff *skb)
 {
-       return __skb_checksum_complete_head(skb, skb->len);
+       __wsum csum;
+       __sum16 sum;
+
+       csum = skb_checksum(skb, 0, skb->len, 0);
+
+       /* skb->csum holds pseudo checksum */
+       sum = csum_fold(csum_add(skb->csum, csum));
+       if (likely(!sum)) {
+               if (unlikely(skb->ip_summed == CHECKSUM_COMPLETE) &&
+                   !skb->csum_complete_sw)
+                       netdev_rx_csum_fault(skb->dev);
+       }
+
+       /* Save full packet checksum */
+       skb->csum = csum;
+       skb->ip_summed = CHECKSUM_COMPLETE;
+       skb->csum_complete_sw = 1;
+       skb->csum_valid = !sum;
+
+       return sum;
 }
 EXPORT_SYMBOL(__skb_checksum_complete);
 
index bf92824af3f77179e519f73085f6642c32ca61b6..9cd5344fad73466e66c63f04efd4a2600074db4e 100644 (file)
@@ -689,6 +689,9 @@ static void __copy_skb_header(struct sk_buff *new, const struct sk_buff *old)
        new->ooo_okay           = old->ooo_okay;
        new->no_fcs             = old->no_fcs;
        new->encapsulation      = old->encapsulation;
+       new->encap_hdr_csum     = old->encap_hdr_csum;
+       new->csum_valid         = old->csum_valid;
+       new->csum_complete_sw   = old->csum_complete_sw;
 #ifdef CONFIG_XFRM
        new->sp                 = secpath_get(old->sp);
 #endif
index 185ed3e598027a475b6ed62c4a0e9f9838793f4d..d92f94b7e4025dd4779e75e6a75f2de560713778 100644 (file)
@@ -1861,6 +1861,10 @@ static struct sock *__udp4_lib_mcast_demux_lookup(struct net *net,
        unsigned int count, slot = udp_hashfn(net, hnum, udp_table.mask);
        struct udp_hslot *hslot = &udp_table.hash[slot];
 
+       /* Do not bother scanning a too big list */
+       if (hslot->count > 10)
+               return NULL;
+
        rcu_read_lock();
 begin:
        count = 0;
index 7e5eb75549902eeeb2c0c0889daca8ee53317ccf..dcb19592761e3b80b92057ba5b834e568a338ab9 100644 (file)
@@ -34,6 +34,8 @@
  *    Sridhar Samudrala     <sri@us.ibm.com>
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <net/sctp/structs.h>
 #include <net/sctp/sctp.h>
 #include <linux/sysctl.h>
@@ -46,6 +48,11 @@ static int sack_timer_min = 1;
 static int sack_timer_max = 500;
 static int addr_scope_max = 3; /* check sctp_scope_policy_t in include/net/sctp/constants.h for max entries */
 static int rwnd_scale_max = 16;
+static int rto_alpha_min = 0;
+static int rto_beta_min = 0;
+static int rto_alpha_max = 1000;
+static int rto_beta_max = 1000;
+
 static unsigned long max_autoclose_min = 0;
 static unsigned long max_autoclose_max =
        (MAX_SCHEDULE_TIMEOUT / HZ > UINT_MAX)
@@ -64,6 +71,9 @@ static int proc_sctp_do_rto_min(struct ctl_table *ctl, int write,
 static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
                                void __user *buffer, size_t *lenp,
                                loff_t *ppos);
+static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write,
+                                  void __user *buffer, size_t *lenp,
+                                  loff_t *ppos);
 static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
                             void __user *buffer, size_t *lenp,
                             loff_t *ppos);
@@ -126,15 +136,19 @@ static struct ctl_table sctp_net_table[] = {
                .procname       = "rto_alpha_exp_divisor",
                .data           = &init_net.sctp.rto_alpha,
                .maxlen         = sizeof(int),
-               .mode           = 0444,
-               .proc_handler   = proc_dointvec,
+               .mode           = 0644,
+               .proc_handler   = proc_sctp_do_alpha_beta,
+               .extra1         = &rto_alpha_min,
+               .extra2         = &rto_alpha_max,
        },
        {
                .procname       = "rto_beta_exp_divisor",
                .data           = &init_net.sctp.rto_beta,
                .maxlen         = sizeof(int),
-               .mode           = 0444,
-               .proc_handler   = proc_dointvec,
+               .mode           = 0644,
+               .proc_handler   = proc_sctp_do_alpha_beta,
+               .extra1         = &rto_beta_min,
+               .extra2         = &rto_beta_max,
        },
        {
                .procname       = "max_burst",
@@ -403,6 +417,16 @@ static int proc_sctp_do_rto_max(struct ctl_table *ctl, int write,
        return ret;
 }
 
+static int proc_sctp_do_alpha_beta(struct ctl_table *ctl, int write,
+                                  void __user *buffer, size_t *lenp,
+                                  loff_t *ppos)
+{
+       pr_warn_once("Changing rto_alpha or rto_beta may lead to "
+                    "suboptimal rtt/srtt estimations!\n");
+
+       return proc_dointvec_minmax(ctl, write, buffer, lenp, ppos);
+}
+
 static int proc_sctp_do_auth(struct ctl_table *ctl, int write,
                             void __user *buffer, size_t *lenp,
                             loff_t *ppos)