Commit 4bcec913 authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc

Pull more powerpc bits from Ben Herrenschmidt:
 "Here are a few more powerpc bits for this merge window.  The bulk is
  made of two pull requests from Scott and Anatolij that I had missed
  previously (they arrived while I was away).  Since both their branches
  are in -next independently, and the content has been around for a
  little while, they can still go in.

  The rest is mostly bug and regression fixes, a small series of
  cleanups to our pseries cpuidle code (including moving it to the right
  place), and one new cpuidle bakend for the powernv platform.  I also
  wired up the new sched_attr syscalls"

* 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/benh/powerpc: (37 commits)
  powerpc: Wire up sched_setattr and sched_getattr syscalls
  powerpc/hugetlb: Replace __get_cpu_var with get_cpu_var
  powerpc: Make sure "cache" directory is removed when offlining cpu
  powerpc/mm: Fix mmap errno when MAP_FIXED is set and mapping exceeds the allowed address space
  powerpc/powernv/cpuidle: Back-end cpuidle driver for powernv platform.
  powerpc/pseries/cpuidle: smt-snooze-delay cleanup.
  powerpc/pseries/cpuidle: Remove MAX_IDLE_STATE macro.
  powerpc/pseries/cpuidle: Make cpuidle-pseries backend driver a non-module.
  powerpc/pseries/cpuidle: Use cpuidle_register() for initialisation.
  powerpc/pseries/cpuidle: Move processor_idle.c to drivers/cpuidle.
  powerpc: Fix 32-bit frames for signals delivered when transactional
  powerpc/iommu: Fix initialisation of DART iommu table
  powerpc/numa: Fix decimal permissions
  powerpc/mm: Fix compile error of pgtable-ppc64.h
  powerpc: Fix hw breakpoints on !HAVE_HW_BREAKPOINT configurations
  clk: corenet: Adds the clock binding
  powerpc/booke64: Guard e6500 tlb handler with CONFIG_PPC_FSL_BOOK3E
  powerpc/512x: dts: add MPC5125 clock specs
  powerpc/512x: clk: support MPC5121/5123/5125 SoC variants
  powerpc/512x: clk: enforce even SDHC divider values
  ...
parents 03c7287d f878f843
* Clock Block on Freescale CoreNet Platforms
Freescale CoreNet chips take primary clocking input from the external
SYSCLK signal. The SYSCLK input (frequency) is multiplied using
multiple phase locked loops (PLL) to create a variety of frequencies
which can then be passed to a variety of internal logic, including
cores and peripheral IP blocks.
Please refer to the Reference Manual for details.
1. Clock Block Binding
Required properties:
- compatible: Should contain a specific clock block compatible string
and a single chassis clock compatible string.
Clock block strings include, but not limited to, one of the:
* "fsl,p2041-clockgen"
* "fsl,p3041-clockgen"
* "fsl,p4080-clockgen"
* "fsl,p5020-clockgen"
* "fsl,p5040-clockgen"
* "fsl,t4240-clockgen"
* "fsl,b4420-clockgen"
* "fsl,b4860-clockgen"
Chassis clock strings include:
* "fsl,qoriq-clockgen-1.0": for chassis 1.0 clocks
* "fsl,qoriq-clockgen-2.0": for chassis 2.0 clocks
- reg: Describes the address of the device's resources within the
address space defined by its parent bus, and resource zero
represents the clock register set
- clock-frequency: Input system clock frequency
Recommended properties:
- ranges: Allows valid translation between child's address space and
parent's. Must be present if the device has sub-nodes.
- #address-cells: Specifies the number of cells used to represent
physical base addresses. Must be present if the device has
sub-nodes and set to 1 if present
- #size-cells: Specifies the number of cells used to represent
the size of an address. Must be present if the device has
sub-nodes and set to 1 if present
2. Clock Provider/Consumer Binding
Most of the bindings are from the common clock binding[1].
[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
Required properties:
- compatible : Should include one of the following:
* "fsl,qoriq-core-pll-1.0" for core PLL clocks (v1.0)
* "fsl,qoriq-core-pll-2.0" for core PLL clocks (v2.0)
* "fsl,qoriq-core-mux-1.0" for core mux clocks (v1.0)
* "fsl,qoriq-core-mux-2.0" for core mux clocks (v2.0)
* "fsl,qoriq-sysclk-1.0": for input system clock (v1.0).
It takes parent's clock-frequency as its clock.
* "fsl,qoriq-sysclk-2.0": for input system clock (v2.0).
It takes parent's clock-frequency as its clock.
- #clock-cells: From common clock binding. The number of cells in a
clock-specifier. Should be <0> for "fsl,qoriq-sysclk-[1,2].0"
clocks, or <1> for "fsl,qoriq-core-pll-[1,2].0" clocks.
For "fsl,qoriq-core-pll-[1,2].0" clocks, the single
clock-specifier cell may take the following values:
* 0 - equal to the PLL frequency
* 1 - equal to the PLL frequency divided by 2
* 2 - equal to the PLL frequency divided by 4
Recommended properties:
- clocks: Should be the phandle of input parent clock
- clock-names: From common clock binding, indicates the clock name
- clock-output-names: From common clock binding, indicates the names of
output clocks
- reg: Should be the offset and length of clock block base address.
The length should be 4.
Example for clock block and clock provider:
/ {
clockgen: global-utilities@e1000 {
compatible = "fsl,p5020-clockgen", "fsl,qoriq-clockgen-1.0";
ranges = <0x0 0xe1000 0x1000>;
clock-frequency = <133333333>;
reg = <0xe1000 0x1000>;
#address-cells = <1>;
#size-cells = <1>;
sysclk: sysclk {
#clock-cells = <0>;
compatible = "fsl,qoriq-sysclk-1.0";
clock-output-names = "sysclk";
}
pll0: pll0@800 {
#clock-cells = <1>;
reg = <0x800 0x4>;
compatible = "fsl,qoriq-core-pll-1.0";
clocks = <&sysclk>;
clock-output-names = "pll0", "pll0-div2";
};
pll1: pll1@820 {
#clock-cells = <1>;
reg = <0x820 0x4>;
compatible = "fsl,qoriq-core-pll-1.0";
clocks = <&sysclk>;
clock-output-names = "pll1", "pll1-div2";
};
mux0: mux0@0 {
#clock-cells = <0>;
reg = <0x0 0x4>;
compatible = "fsl,qoriq-core-mux-1.0";
clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>;
clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2";
clock-output-names = "cmux0";
};
mux1: mux1@20 {
#clock-cells = <0>;
reg = <0x20 0x4>;
compatible = "fsl,qoriq-core-mux-1.0";
clocks = <&pll0 0>, <&pll0 1>, <&pll1 0>, <&pll1 1>;
clock-names = "pll0", "pll0-div2", "pll1", "pll1-div2";
clock-output-names = "cmux1";
};
};
}
Example for clock consumer:
/ {
cpu0: PowerPC,e5500@0 {
...
clocks = <&mux0>;
...
};
}
...@@ -532,6 +532,7 @@ config PPC_16K_PAGES ...@@ -532,6 +532,7 @@ config PPC_16K_PAGES
config PPC_64K_PAGES config PPC_64K_PAGES
bool "64k page size" if 44x || PPC_STD_MMU_64 || PPC_BOOK3E_64 bool "64k page size" if 44x || PPC_STD_MMU_64 || PPC_BOOK3E_64
depends on !PPC_FSL_BOOK3E
select PPC_HAS_HASH_64K if PPC_STD_MMU_64 select PPC_HAS_HASH_64K if PPC_STD_MMU_64
config PPC_256K_PAGES config PPC_256K_PAGES
...@@ -1045,11 +1046,6 @@ config KEYS_COMPAT ...@@ -1045,11 +1046,6 @@ config KEYS_COMPAT
source "crypto/Kconfig" source "crypto/Kconfig"
config PPC_CLOCK
bool
default n
select HAVE_CLK
config PPC_LIB_RHEAP config PPC_LIB_RHEAP
bool bool
......
...@@ -139,7 +139,14 @@ &gpio_pic 11 0 /* done */ ...@@ -139,7 +139,14 @@ &gpio_pic 11 0 /* done */
}; };
}; };
clocks {
osc {
clock-frequency = <25000000>;
};
};
soc@80000000 { soc@80000000 {
bus-frequency = <80000000>; /* 80 MHz ips bus */
clock@f00 { clock@f00 {
compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock"; compatible = "fsl,mpc5121rev2-clock", "fsl,mpc5121-clock";
......
...@@ -9,6 +9,8 @@ ...@@ -9,6 +9,8 @@
* option) any later version. * option) any later version.
*/ */
#include <dt-bindings/clock/mpc512x-clock.h>
/dts-v1/; /dts-v1/;
/ { / {
...@@ -49,6 +51,10 @@ mbx@20000000 { ...@@ -49,6 +51,10 @@ mbx@20000000 {
compatible = "fsl,mpc5121-mbx"; compatible = "fsl,mpc5121-mbx";
reg = <0x20000000 0x4000>; reg = <0x20000000 0x4000>;
interrupts = <66 0x8>; interrupts = <66 0x8>;
clocks = <&clks MPC512x_CLK_MBX_BUS>,
<&clks MPC512x_CLK_MBX_3D>,
<&clks MPC512x_CLK_MBX>;
clock-names = "mbx-bus", "mbx-3d", "mbx";
}; };
sram@30000000 { sram@30000000 {
...@@ -62,6 +68,8 @@ nfc@40000000 { ...@@ -62,6 +68,8 @@ nfc@40000000 {
interrupts = <6 8>; interrupts = <6 8>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <1>; #size-cells = <1>;
clocks = <&clks MPC512x_CLK_NFC>;
clock-names = "ipg";
}; };
localbus@80000020 { localbus@80000020 {
...@@ -73,6 +81,17 @@ localbus@80000020 { ...@@ -73,6 +81,17 @@ localbus@80000020 {
ranges = <0x0 0x0 0xfc000000 0x04000000>; ranges = <0x0 0x0 0xfc000000 0x04000000>;
}; };
clocks {
#address-cells = <1>;
#size-cells = <0>;
osc: osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <33000000>;
};
};
soc@80000000 { soc@80000000 {
compatible = "fsl,mpc5121-immr"; compatible = "fsl,mpc5121-immr";
#address-cells = <1>; #address-cells = <1>;
...@@ -117,9 +136,12 @@ reset@e00 { ...@@ -117,9 +136,12 @@ reset@e00 {
}; };
/* Clock control */ /* Clock control */
clock@f00 { clks: clock@f00 {
compatible = "fsl,mpc5121-clock"; compatible = "fsl,mpc5121-clock";
reg = <0xf00 0x100>; reg = <0xf00 0x100>;
#clock-cells = <1>;
clocks = <&osc>;
clock-names = "osc";
}; };
/* Power Management Controller */ /* Power Management Controller */
...@@ -139,12 +161,24 @@ can@1300 { ...@@ -139,12 +161,24 @@ can@1300 {
compatible = "fsl,mpc5121-mscan"; compatible = "fsl,mpc5121-mscan";
reg = <0x1300 0x80>; reg = <0x1300 0x80>;
interrupts = <12 0x8>; interrupts = <12 0x8>;
clocks = <&clks MPC512x_CLK_BDLC>,
<&clks MPC512x_CLK_IPS>,
<&clks MPC512x_CLK_SYS>,
<&clks MPC512x_CLK_REF>,
<&clks MPC512x_CLK_MSCAN0_MCLK>;
clock-names = "ipg", "ips", "sys", "ref", "mclk";
}; };
can@1380 { can@1380 {
compatible = "fsl,mpc5121-mscan"; compatible = "fsl,mpc5121-mscan";
reg = <0x1380 0x80>; reg = <0x1380 0x80>;
interrupts = <13 0x8>; interrupts = <13 0x8>;
clocks = <&clks MPC512x_CLK_BDLC>,
<&clks MPC512x_CLK_IPS>,
<&clks MPC512x_CLK_SYS>,
<&clks MPC512x_CLK_REF>,
<&clks MPC512x_CLK_MSCAN1_MCLK>;
clock-names = "ipg", "ips", "sys", "ref", "mclk";
}; };
sdhc@1500 { sdhc@1500 {
...@@ -153,6 +187,9 @@ sdhc@1500 { ...@@ -153,6 +187,9 @@ sdhc@1500 {
interrupts = <8 0x8>; interrupts = <8 0x8>;
dmas = <&dma0 30>; dmas = <&dma0 30>;
dma-names = "rx-tx"; dma-names = "rx-tx";
clocks = <&clks MPC512x_CLK_IPS>,
<&clks MPC512x_CLK_SDHC>;
clock-names = "ipg", "per";
}; };
i2c@1700 { i2c@1700 {
...@@ -161,6 +198,8 @@ i2c@1700 { ...@@ -161,6 +198,8 @@ i2c@1700 {
compatible = "fsl,mpc5121-i2c", "fsl-i2c"; compatible = "fsl,mpc5121-i2c", "fsl-i2c";
reg = <0x1700 0x20>; reg = <0x1700 0x20>;
interrupts = <9 0x8>; interrupts = <9 0x8>;
clocks = <&clks MPC512x_CLK_I2C>;
clock-names = "ipg";
}; };
i2c@1720 { i2c@1720 {
...@@ -169,6 +208,8 @@ i2c@1720 { ...@@ -169,6 +208,8 @@ i2c@1720 {
compatible = "fsl,mpc5121-i2c", "fsl-i2c"; compatible = "fsl,mpc5121-i2c", "fsl-i2c";
reg = <0x1720 0x20>; reg = <0x1720 0x20>;
interrupts = <10 0x8>; interrupts = <10 0x8>;
clocks = <&clks MPC512x_CLK_I2C>;
clock-names = "ipg";
}; };
i2c@1740 { i2c@1740 {
...@@ -177,6 +218,8 @@ i2c@1740 { ...@@ -177,6 +218,8 @@ i2c@1740 {
compatible = "fsl,mpc5121-i2c", "fsl-i2c"; compatible = "fsl,mpc5121-i2c", "fsl-i2c";
reg = <0x1740 0x20>; reg = <0x1740 0x20>;
interrupts = <11 0x8>; interrupts = <11 0x8>;
clocks = <&clks MPC512x_CLK_I2C>;
clock-names = "ipg";
}; };
i2ccontrol@1760 { i2ccontrol@1760 {
...@@ -188,30 +231,48 @@ axe@2000 { ...@@ -188,30 +231,48 @@ axe@2000 {
compatible = "fsl,mpc5121-axe"; compatible = "fsl,mpc5121-axe";
reg = <0x2000 0x100>; reg = <0x2000 0x100>;
interrupts = <42 0x8>; interrupts = <42 0x8>;
clocks = <&clks MPC512x_CLK_AXE>;
clock-names = "ipg";
}; };
display@2100 { display@2100 {
compatible = "fsl,mpc5121-diu"; compatible = "fsl,mpc5121-diu";
reg = <0x2100 0x100>; reg = <0x2100 0x100>;
interrupts = <64 0x8>; interrupts = <64 0x8>;
clocks = <&clks MPC512x_CLK_DIU>;
clock-names = "ipg";
}; };
can@2300 { can@2300 {
compatible = "fsl,mpc5121-mscan"; compatible = "fsl,mpc5121-mscan";
reg = <0x2300 0x80>; reg = <0x2300 0x80>;
interrupts = <90 0x8>; interrupts = <90 0x8>;
clocks = <&clks MPC512x_CLK_BDLC>,
<&clks MPC512x_CLK_IPS>,
<&clks MPC512x_CLK_SYS>,
<&clks MPC512x_CLK_REF>,
<&clks MPC512x_CLK_MSCAN2_MCLK>;
clock-names = "ipg", "ips", "sys", "ref", "mclk";
}; };
can@2380 { can@2380 {
compatible = "fsl,mpc5121-mscan"; compatible = "fsl,mpc5121-mscan";
reg = <0x2380 0x80>; reg = <0x2380 0x80>;
interrupts = <91 0x8>; interrupts = <91 0x8>;
clocks = <&clks MPC512x_CLK_BDLC>,
<&clks MPC512x_CLK_IPS>,
<&clks MPC512x_CLK_SYS>,
<&clks MPC512x_CLK_REF>,
<&clks MPC512x_CLK_MSCAN3_MCLK>;
clock-names = "ipg", "ips", "sys", "ref", "mclk";
}; };
viu@2400 { viu@2400 {
compatible = "fsl,mpc5121-viu"; compatible = "fsl,mpc5121-viu";
reg = <0x2400 0x400>; reg = <0x2400 0x400>;
interrupts = <67 0x8>; interrupts = <67 0x8>;
clocks = <&clks MPC512x_CLK_VIU>;
clock-names = "ipg";
}; };
mdio@2800 { mdio@2800 {
...@@ -219,6 +280,8 @@ mdio@2800 { ...@@ -219,6 +280,8 @@ mdio@2800 {
reg = <0x2800 0x800>; reg = <0x2800 0x800>;
#address-cells = <1>; #address-cells = <1>;
#size-cells = <0>; #size-cells = <0>;
clocks = <&clks MPC512x_CLK_FEC>;
clock-names = "per";
}; };
eth0: ethernet@2800 { eth0: ethernet@2800 {
...@@ -227,6 +290,8 @@ eth0: ethernet@2800 { ...@@ -227,6 +290,8 @@ eth0: ethernet@2800 {
reg = <0x2800 0x800>; reg = <0x2800 0x800>;
local-mac-address = [ 00 00 00 00 00 00 ]; local-mac-address = [ 00 00 00 00 00 00 ];
interrupts = <4 0x8>; interrupts = <4 0x8>;
clocks = <&clks MPC512x_CLK_FEC>;
clock-names = "per";
}; };
/* USB1 using external ULPI PHY */ /* USB1 using external ULPI PHY */
...@@ -238,6 +303,8 @@ usb@3000 { ...@@ -238,6 +303,8 @@ usb@3000 {
interrupts = <43 0x8>; interrupts = <43 0x8>;
dr_mode = "otg"; dr_mode = "otg";
phy_type = "ulpi"; phy_type = "ulpi";
clocks = <&clks MPC512x_CLK_USB1>;
clock-names = "ipg";
}; };
/* USB0 using internal UTMI PHY */ /* USB0 using internal UTMI PHY */
...@@ -249,6 +316,8 @@ usb@4000 { ...@@ -249,6 +316,8 @@ usb@4000 {
interrupts = <44 0x8>; interrupts = <44 0x8>;
dr_mode = "otg"; dr_mode = "otg";
phy_type = "utmi_wide"; phy_type = "utmi_wide";
clocks = <&clks MPC512x_CLK_USB2>;
clock-names = "ipg";
}; };
/* IO control */ /* IO control */
...@@ -267,6 +336,8 @@ pata@10200 { ...@@ -267,6 +336,8 @@ pata@10200 {
compatible = "fsl,mpc5121-pata"; compatible = "fsl,mpc5121-pata";
reg = <0x10200 0x100>; reg = <0x10200 0x100>;
interrupts = <5 0x8>; interrupts = <5 0x8>;
clocks = <&clks MPC512x_CLK_PATA>;
clock-names = "ipg";
}; };
/* 512x PSCs are not 52xx PSC compatible */ /* 512x PSCs are not 52xx PSC compatible */
...@@ -278,6 +349,9 @@ psc@11000 { ...@@ -278,6 +349,9 @@ psc@11000 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC0>,
<&clks MPC512x_CLK_PSC0_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC1 */ /* PSC1 */
...@@ -287,6 +361,9 @@ psc@11100 { ...@@ -287,6 +361,9 @@ psc@11100 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC1>,
<&clks MPC512x_CLK_PSC1_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC2 */ /* PSC2 */
...@@ -296,6 +373,9 @@ psc@11200 { ...@@ -296,6 +373,9 @@ psc@11200 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC2>,
<&clks MPC512x_CLK_PSC2_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC3 */ /* PSC3 */
...@@ -305,6 +385,9 @@ psc@11300 { ...@@ -305,6 +385,9 @@ psc@11300 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC3>,
<&clks MPC512x_CLK_PSC3_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC4 */ /* PSC4 */
...@@ -314,6 +397,9 @@ psc@11400 { ...@@ -314,6 +397,9 @@ psc@11400 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC4>,
<&clks MPC512x_CLK_PSC4_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC5 */ /* PSC5 */
...@@ -323,6 +409,9 @@ psc@11500 { ...@@ -323,6 +409,9 @@ psc@11500 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC5>,
<&clks MPC512x_CLK_PSC5_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC6 */ /* PSC6 */
...@@ -332,6 +421,9 @@ psc@11600 { ...@@ -332,6 +421,9 @@ psc@11600 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC6>,
<&clks MPC512x_CLK_PSC6_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC7 */ /* PSC7 */
...@@ -341,6 +433,9 @@ psc@11700 { ...@@ -341,6 +433,9 @@ psc@11700 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC7>,
<&clks MPC512x_CLK_PSC7_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC8 */ /* PSC8 */
...@@ -350,6 +445,9 @@ psc@11800 { ...@@ -350,6 +445,9 @@ psc@11800 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC8>,
<&clks MPC512x_CLK_PSC8_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC9 */ /* PSC9 */
...@@ -359,6 +457,9 @@ psc@11900 { ...@@ -359,6 +457,9 @@ psc@11900 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC9>,
<&clks MPC512x_CLK_PSC9_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC10 */ /* PSC10 */
...@@ -368,6 +469,9 @@ psc@11a00 { ...@@ -368,6 +469,9 @@ psc@11a00 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC10>,
<&clks MPC512x_CLK_PSC10_MCLK>;
clock-names = "ipg", "mclk";
}; };
/* PSC11 */ /* PSC11 */
...@@ -377,12 +481,17 @@ psc@11b00 { ...@@ -377,12 +481,17 @@ psc@11b00 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC11>,
<&clks MPC512x_CLK_PSC11_MCLK>;
clock-names = "ipg", "mclk";
}; };
pscfifo@11f00 { pscfifo@11f00 {
compatible = "fsl,mpc5121-psc-fifo"; compatible = "fsl,mpc5121-psc-fifo";
reg = <0x11f00 0x100>; reg = <0x11f00 0x100>;
interrupts = <40 0x8>; interrupts = <40 0x8>;
clocks = <&clks MPC512x_CLK_PSC_FIFO>;
clock-names = "ipg";
}; };
dma0: dma@14000 { dma0: dma@14000 {
...@@ -400,6 +509,8 @@ pci: pci@80008500 { ...@@ -400,6 +509,8 @@ pci: pci@80008500 {
#address-cells = <3>; #address-cells = <3>;
#size-cells = <2>; #size-cells = <2>;
#interrupt-cells = <1>; #interrupt-cells = <1>;
clocks = <&clks MPC512x_CLK_PCI>;
clock-names = "ipg";
reg = <0x80008500 0x100 /* internal registers */ reg = <0x80008500 0x100 /* internal registers */
0x80008300 0x8>; /* config space access registers */ 0x80008300 0x8>; /* config space access registers */
......
...@@ -12,6 +12,8 @@ ...@@ -12,6 +12,8 @@
* option) any later version. * option) any later version.
*/ */
#include <dt-bindings/clock/mpc512x-clock.h>
/dts-v1/; /dts-v1/;
/ { / {
...@@ -54,6 +56,17 @@ sram@30000000 { ...@@ -54,6 +56,17 @@ sram@30000000 {
reg = <0x30000000 0x08000>; // 32K at 0x30000000 reg = <0x30000000 0x08000>; // 32K at 0x30000000
}; };
clocks {
#address-cells = <1>;
#size-cells = <0>;
osc: osc {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <33000000>;
};
};
soc@80000000 { soc@80000000 {
compatible = "fsl,mpc5121-immr"; compatible = "fsl,mpc5121-immr";
#address-cells = <1>; #address-cells = <1>;
...@@ -87,9 +100,12 @@ reset@e00 { // Reset module ...@@ -87,9 +100,12 @@ reset@e00 { // Reset module
reg = <0xe00 0x100>; reg = <0xe00 0x100>;
}; };
clock@f00 { // Clock control clks: clock@f00 { // Clock control
compatible = "fsl,mpc5121-clock"; compatible = "fsl,mpc5121-clock";
reg = <0xf00 0x100>; reg = <0xf00 0x100>;
#clock-cells = <1>;
clocks = <&osc>;
clock-names = "osc";
}; };
pmc@1000{ // Power Management Controller pmc@1000{ // Power Management Controller
...@@ -114,18 +130,33 @@ can@1300 { // CAN rev.2 ...@@ -114,18 +130,33 @@ can@1300 { // CAN rev.2
compatible = "fsl,mpc5121-mscan"; compatible = "fsl,mpc5121-mscan";
interrupts = <12 0x8>; interrupts = <12 0x8>;
reg = <0x1300 0x80>; reg = <0x1300 0x80>;
clocks = <&clks MPC512x_CLK_BDLC>,
<&clks MPC512x_CLK_IPS>,
<&clks MPC512x_CLK_SYS>,
<&clks MPC512x_CLK_REF>,
<&clks MPC512x_CLK_MSCAN0_MCLK>;
clock-names = "ipg", "ips", "sys", "ref", "mclk";
}; };
can@1380 { can@1380 {
compatible = "fsl,mpc5121-mscan"; compatible = "fsl,mpc5121-mscan";
interrupts = <13 0x8>; interrupts = <13 0x8>;
reg = <0x1380 0x80>; reg = <0x1380 0x80>;
clocks = <&clks MPC512x_CLK_BDLC>,
<&clks MPC512x_CLK_IPS>,
<&clks MPC512x_CLK_SYS>,
<&clks MPC512x_CLK_REF>,
<&clks MPC512x_CLK_MSCAN1_MCLK>;
clock-names = "ipg", "ips", "sys", "ref", "mclk";
}; };
sdhc@1500 { sdhc@1500 {
compatible = "fsl,mpc5121-sdhc"; compatible = "fsl,mpc5121-sdhc";
interrupts = <8 0x8>; interrupts = <8 0x8>;
reg = <0x1500 0x100>; reg = <0x1500 0x100>;
clocks = <&clks MPC512x_CLK_IPS>,
<&clks MPC512x_CLK_SDHC>;
clock-names = "ipg", "per";
}; };
i2c@1700 { i2c@1700 {
...@@ -134,6 +165,8 @@ i2c@1700 { ...@@ -134,6 +165,8 @@ i2c@1700 {
compatible = "fsl,mpc5121-i2c", "fsl-i2c"; compatible = "fsl,mpc5121-i2c", "fsl-i2c";
reg = <0x1700 0x20>; reg = <0x1700 0x20>;
interrupts = <0x9 0x8>; interrupts = <0x9 0x8>;
clocks = <&clks MPC512x_CLK_I2C>;
clock-names = "ipg";
}; };
i2c@1720 { i2c@1720 {
...@@ -142,6 +175,8 @@ i2c@1720 { ...@@ -142,6 +175,8 @@ i2c@1720 {
compatible = "fsl,mpc5121-i2c", "fsl-i2c"; compatible = "fsl,mpc5121-i2c", "fsl-i2c";
reg = <0x1720 0x20>; reg = <0x1720 0x20>;
interrupts = <0xa 0x8>; interrupts = <0xa 0x8>;
clocks = <&clks MPC512x_CLK_I2C>;
clock-names = "ipg";
}; };
i2c@1740 { i2c@1740 {
...@@ -150,6 +185,8 @@ i2c@1740 { ...@@ -150,6 +185,8 @@ i2c@1740 {
compatible = "fsl,mpc5121-i2c", "fsl-i2c"; compatible = "fsl,mpc5121-i2c", "fsl-i2c";
reg = <0x1740 0x20>; reg = <0x1740 0x20>;
interrupts = <0xb 0x8>; interrupts = <0xb 0x8>;
clocks = <&clks MPC512x_CLK_I2C>;
clock-names = "ipg";
}; };
i2ccontrol@1760 { i2ccontrol@1760 {
...@@ -161,6 +198,8 @@ diu@2100 { ...@@ -161,6 +198,8 @@ diu@2100 {
compatible = "fsl,mpc5121-diu"; compatible = "fsl,mpc5121-diu";
reg = <0x2100 0x100>; reg = <0x2100 0x100>;
interrupts = <64 0x8>; interrupts = <64 0x8>;
clocks = <&clks MPC512x_CLK_DIU>;
clock-names = "ipg";
}; };
mdio@2800 { mdio@2800 {
...@@ -180,6 +219,8 @@ eth0: ethernet@2800 { ...@@ -180,6 +219,8 @@ eth0: ethernet@2800 {
interrupts = <4 0x8>; interrupts = <4 0x8>;
phy-handle = < &phy0 >; phy-handle = < &phy0 >;
phy-connection-type = "rmii"; phy-connection-type = "rmii";
clocks = <&clks MPC512x_CLK_FEC>;
clock-names = "per";
}; };
// IO control // IO control
...@@ -200,6 +241,8 @@ usb@3000 { ...@@ -200,6 +241,8 @@ usb@3000 {
interrupts = <43 0x8>; interrupts = <43 0x8>;
dr_mode = "host"; dr_mode = "host";
phy_type = "ulpi"; phy_type = "ulpi";
clocks = <&clks MPC512x_CLK_USB1>;
clock-names = "ipg";
status = "disabled"; status = "disabled";
}; };
...@@ -211,6 +254,9 @@ serial@11100 { ...@@ -211,6 +254,9 @@ serial@11100 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC1>,
<&clks MPC512x_CLK_PSC1_MCLK>;
clock-names = "ipg", "mclk";
}; };
// PSC9 uart1 aka ttyPSC1 // PSC9 uart1 aka ttyPSC1
...@@ -220,12 +266,17 @@ serial@11900 { ...@@ -220,12 +266,17 @@ serial@11900 {
interrupts = <40 0x8>; interrupts = <40 0x8>;
fsl,rx-fifo-size = <16>; fsl,rx-fifo-size = <16>;
fsl,tx-fifo-size = <16>; fsl,tx-fifo-size = <16>;
clocks = <&clks MPC512x_CLK_PSC9>,
<&clks MPC512x_CLK_PSC9_MCLK>;
clock-names = "ipg", "mclk";
}; };
pscfifo@11f00 { pscfifo@11f00 {
compatible = "fsl,mpc5121-psc-fifo"; compatible = "fsl,mpc5121-psc-fifo";
reg = <0x11f00 0x100>; reg = <0x11f00 0x100>;
interrupts = <40 0x8>; interrupts = <40 0x8>;
clocks = <&clks MPC512x_CLK_PSC_FIFO>;
clock-names = "ipg";
}; };
dma@14000 { dma@14000 {
......
#ifndef __ASM_POWERPC_CLK_INTERFACE_H
#define __ASM_POWERPC_CLK_INTERFACE_H
#include <linux/clk.h>
struct clk_interface {
struct clk* (*clk_get) (struct device *dev, const char *id);
int (*clk_enable) (struct clk *clk);
void (*clk_disable) (struct clk *clk);
unsigned long (*clk_get_rate) (struct clk *clk);
void (*clk_put) (struct clk *clk);
long (*clk_round_rate) (struct clk *clk, unsigned long rate);
int (*clk_set_rate) (struct clk *clk, unsigned long rate);
int (*clk_set_parent) (struct clk *clk, struct clk *parent);
struct clk* (*clk_get_parent) (struct clk *clk);
};
extern struct clk_interface clk_functions;
#endif /* __ASM_POWERPC_CLK_INTERFACE_H */
...@@ -37,7 +37,12 @@ struct mpc512x_ccm { ...@@ -37,7 +37,12 @@ struct mpc512x_ccm {
u32 cccr; /* CFM Clock Control Register */ u32 cccr; /* CFM Clock Control Register */
u32 dccr; /* DIU Clock Control Register */ u32 dccr; /* DIU Clock Control Register */
u32 mscan_ccr[4]; /* MSCAN Clock Control Registers */ u32 mscan_ccr[4]; /* MSCAN Clock Control Registers */
u8 res[0x98]; /* Reserved */ u32 out_ccr[4]; /* OUT CLK Configure Registers */
u32 rsv0[2]; /* Reserved */
u32 scfr3; /* System Clock Frequency Register 3 */
u32 rsv1[3]; /* Reserved */
u32 spll_lock_cnt; /* System PLL Lock Counter */
u8 res[0x6c]; /* Reserved */
}; };
/* /*
......
...@@ -560,9 +560,9 @@ extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address, ...@@ -560,9 +560,9 @@ extern void pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
pmd_t *pmdp); pmd_t *pmdp);
#define pmd_move_must_withdraw pmd_move_must_withdraw #define pmd_move_must_withdraw pmd_move_must_withdraw
typedef struct spinlock spinlock_t; struct spinlock;
static inline int pmd_move_must_withdraw(spinlock_t *new_pmd_ptl, static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
spinlock_t *old_pmd_ptl) struct spinlock *old_pmd_ptl)
{ {
/* /*
* Archs like ppc64 use pgtable to store per pmd * Archs like ppc64 use pgtable to store per pmd
......
...@@ -450,13 +450,6 @@ enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF}; ...@@ -450,13 +450,6 @@ enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
extern int powersave_nap; /* set if nap mode can be used in idle loop */ extern int powersave_nap; /* set if nap mode can be used in idle loop */
extern void power7_nap(void); extern void power7_nap(void);
#ifdef CONFIG_PSERIES_IDLE
extern void update_smt_snooze_delay(int cpu, int residency);
#else
static inline void update_smt_snooze_delay(int cpu, int residency) {}
#endif
extern void flush_instruction_cache(void); extern void flush_instruction_cache(void);
extern void hard_reset_now(void); extern void hard_reset_now(void);
extern void poweroff_now(void); extern void poweroff_now(void);
......
...@@ -359,3 +359,5 @@ COMPAT_SYS(process_vm_readv) ...@@ -359,3 +359,5 @@ COMPAT_SYS(process_vm_readv)
COMPAT_SYS(process_vm_writev) COMPAT_SYS(process_vm_writev)
SYSCALL(finit_module) SYSCALL(finit_module)
SYSCALL(ni_syscall) /* sys_kcmp */ SYSCALL(ni_syscall) /* sys_kcmp */
SYSCALL_SPU(sched_setattr)
SYSCALL_SPU(sched_getattr)
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
#include <uapi/asm/unistd.h> #include <uapi/asm/unistd.h>
#define __NR_syscalls 355 #define __NR_syscalls 357
#define __NR__exit __NR_exit #define __NR__exit __NR_exit
#define NR_syscalls __NR_syscalls #define NR_syscalls __NR_syscalls
......
...@@ -377,6 +377,7 @@ ...@@ -377,6 +377,7 @@
#define __NR_process_vm_writev 352 #define __NR_process_vm_writev 352
#define __NR_finit_module 353 #define __NR_finit_module 353
#define __NR_kcmp 354 #define __NR_kcmp 354
#define __NR_sched_setattr 355
#define __NR_sched_getattr 356
#endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */ #endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
...@@ -48,7 +48,6 @@ obj-$(CONFIG_ALTIVEC) += vecemu.o ...@@ -48,7 +48,6 @@ obj-$(CONFIG_ALTIVEC) += vecemu.o
obj-$(CONFIG_PPC_970_NAP) += idle_power4.o obj-$(CONFIG_PPC_970_NAP) += idle_power4.o
obj-$(CONFIG_PPC_P7_NAP) += idle_power7.o obj-$(CONFIG_PPC_P7_NAP) += idle_power7.o
obj-$(CONFIG_PPC_OF) += of_platform.o prom_parse.o obj-$(CONFIG_PPC_OF) += of_platform.o prom_parse.o
obj-$(CONFIG_PPC_CLOCK) += clock.o
procfs-y := proc_powerpc.o procfs-y := proc_powerpc.o
obj-$(CONFIG_PROC_FS) += $(procfs-y) obj-$(CONFIG_PROC_FS) += $(procfs-y)
rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o rtaspci-$(CONFIG_PPC64)-$(CONFIG_PCI) := rtas_pci.o
......
...@@ -793,6 +793,9 @@ static void remove_cache_dir(struct cache_dir *cache_dir) ...@@ -793,6 +793,9 @@ static void remove_cache_dir(struct cache_dir *cache_dir)
{ {
remove_index_dirs(cache_dir); remove_index_dirs(cache_dir);
/* Remove cache dir from sysfs */
kobject_del(cache_dir->kobj);
kobject_put(cache_dir->kobj); kobject_put(cache_dir->kobj);
kfree(cache_dir); kfree(cache_dir);
......
/*
* Dummy clk implementations for powerpc.
* These need to be overridden in platform code.
*/
#include <linux/clk.h>
#include <linux/err.h>
#include <linux/errno.h>
#include <linux/export.h>
#include <asm/clk_interface.h>
struct clk_interface clk_functions;
struct clk *clk_get(struct device *dev, const char *id)
{
if (clk_functions.clk_get)
return clk_functions.clk_get(dev, id);
return ERR_PTR(-ENOSYS);
}
EXPORT_SYMBOL(clk_get);
void clk_put(struct clk *clk)
{
if (clk_functions.clk_put)
clk_functions.clk_put(clk);
}
EXPORT_SYMBOL(clk_put);
int clk_enable(struct clk *clk)
{
if (clk_functions.clk_enable)
return clk_functions.clk_enable(clk);
return -ENOSYS;
}
EXPORT_SYMBOL(clk_enable);
void clk_disable(struct clk *clk)
{
if (clk_functions.clk_disable)
clk_functions.clk_disable(clk);
}
EXPORT_SYMBOL(clk_disable);
unsigned long clk_get_rate(struct clk *clk)
{
if (clk_functions.clk_get_rate)
return clk_functions.clk_get_rate(clk);
return 0;
}
EXPORT_SYMBOL(clk_get_rate);
long clk_round_rate(struct clk *clk, unsigned long rate)
{
if (clk_functions.clk_round_rate)
return clk_functions.clk_round_rate(clk, rate);
return -ENOSYS;
}
EXPORT_SYMBOL(clk_round_rate);
int clk_set_rate(struct clk *clk, unsigned long rate)
{
if (clk_functions.clk_set_rate)
return clk_functions.clk_set_rate(clk, rate);
return -ENOSYS;
}
EXPORT_SYMBOL(clk_set_rate);
struct clk *clk_get_parent(struct clk *clk)
{
if (clk_functions.clk_get_parent)
return clk_functions.clk_get_parent(clk);
return ERR_PTR(-ENOSYS);
}
EXPORT_SYMBOL(clk_get_parent);
int clk_set_parent(struct clk *clk, struct clk *parent)
{
if (clk_functions.clk_set_parent)
return clk_functions.clk_set_parent(clk, parent);
return -ENOSYS;
}
EXPORT_SYMBOL(clk_set_parent);
...@@ -811,7 +811,7 @@ struct task_struct *__switch_to(struct task_struct *prev, ...@@ -811,7 +811,7 @@ struct task_struct *__switch_to(struct task_struct *prev,
* schedule DABR * schedule DABR
*/ */
#ifndef CONFIG_HAVE_HW_BREAKPOINT #ifndef CONFIG_HAVE_HW_BREAKPOINT
if (unlikely(hw_brk_match(&__get_cpu_var(current_brk), &new->thread.hw_brk))) if (unlikely(!hw_brk_match(&__get_cpu_var(current_brk), &new->thread.hw_brk)))
set_breakpoint(&new->thread.hw_brk); set_breakpoint(&new->thread.hw_brk);
#endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* CONFIG_HAVE_HW_BREAKPOINT */
#endif #endif
......
...@@ -1022,29 +1022,24 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka, ...@@ -1022,29 +1022,24 @@ int handle_rt_signal32(unsigned long sig, struct k_sigaction *ka,
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM #ifdef CONFIG_PPC_TRANSACTIONAL_MEM
tm_frame = &rt_sf->uc_transact.uc_mcontext; tm_frame = &rt_sf->uc_transact.uc_mcontext;
if (MSR_TM_ACTIVE(regs->msr)) { if (MSR_TM_ACTIVE(regs->msr)) {
if (__put_user((unsigned long)&rt_sf->uc_transact,
&rt_sf->uc.uc_link) ||
__put_user((unsigned long)tm_frame,
&rt_sf->uc_transact.uc_regs))
goto badframe;
if (save_tm_user_regs(regs, frame, tm_frame, sigret)) if (save_tm_user_regs(regs, frame, tm_frame, sigret))
goto badframe; goto badframe;
} }
else else
#endif #endif
{ {
if (__put_user(0, &rt_sf->uc.uc_link))
goto badframe;
if (save_user_regs(regs, frame, tm_frame, sigret, 1)) if (save_user_regs(regs, frame, tm_frame, sigret, 1))
goto badframe; goto badframe;
} }
regs->link = tramp; regs->link = tramp;
#ifdef CONFIG_PPC_TRANSACTIONAL_MEM
if (MSR_TM_ACTIVE(regs->msr)) {
if (__put_user((unsigned long)&rt_sf->uc_transact,
&rt_sf->uc.uc_link)
|| __put_user((unsigned long)tm_frame, &rt_sf->uc_transact.uc_regs))
goto badframe;
}
else
#endif
if (__put_user(0, &rt_sf->uc.uc_link))
goto badframe;
current->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */ current->thread.fp_state.fpscr = 0; /* turn off all fp exceptions */
/* create a stack frame for the caller of the handler */ /* create a stack frame for the caller of the handler */
......
...@@ -51,8 +51,6 @@ static ssize_t store_smt_snooze_delay(struct device *dev, ...@@ -51,8 +51,6 @@ static ssize_t store_smt_snooze_delay(struct device *dev,
return -EINVAL; return -EINVAL;
per_cpu(smt_snooze_delay, cpu->dev.id) = snooze; per_cpu(smt_snooze_delay, cpu->dev.id) = snooze;
update_smt_snooze_delay(cpu->dev.id, snooze);
return count; return count;
} }
......
...@@ -472,12 +472,13 @@ static void hugepd_free(struct mmu_gather *tlb, void *hugepte) ...@@ -472,12 +472,13 @@ static void hugepd_free(struct mmu_gather *tlb, void *hugepte)
{ {
struct hugepd_freelist **batchp; struct hugepd_freelist **batchp;
batchp = &__get_cpu_var(hugepd_freelist_cur); batchp = &get_cpu_var(hugepd_freelist_cur);
if (atomic_read(&tlb->mm->mm_users) < 2 || if (atomic_read(&tlb->mm->mm_users) < 2 ||
cpumask_equal(mm_cpumask(tlb->mm), cpumask_equal(mm_cpumask(tlb->mm),
cpumask_of(smp_processor_id()))) { cpumask_of(smp_processor_id()))) {
kmem_cache_free(hugepte_cache, hugepte); kmem_cache_free(hugepte_cache, hugepte);
put_cpu_var(hugepd_freelist_cur);
return; return;
} }
...@@ -491,6 +492,7 @@ static void hugepd_free(struct mmu_gather *tlb, void *hugepte) ...@@ -491,6 +492,7 @@ static void hugepd_free(struct mmu_gather *tlb, void *hugepte)
call_rcu_sched(&(*batchp)->rcu, hugepd_free_rcu_callback); call_rcu_sched(&(*batchp)->rcu, hugepd_free_rcu_callback);
*batchp = NULL; *batchp = NULL;
} }
put_cpu_var(hugepd_freelist_cur);
} }
#endif #endif
......
...@@ -1785,7 +1785,7 @@ static const struct file_operations topology_ops = { ...@@ -1785,7 +1785,7 @@ static const struct file_operations topology_ops = {
static int topology_update_init(void) static int topology_update_init(void)
{ {
start_topology_update(); start_topology_update();
proc_create("powerpc/topology_updates", 644, NULL, &topology_ops); proc_create("powerpc/topology_updates", 0644, NULL, &topology_ops);
return 0; return 0;
} }
......
...@@ -408,7 +408,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len, ...@@ -408,7 +408,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
if (fixed && (addr & ((1ul << pshift) - 1))) if (fixed && (addr & ((1ul << pshift) - 1)))
return -EINVAL; return -EINVAL;
if (fixed && addr > (mm->task_size - len)) if (fixed && addr > (mm->task_size - len))
return -EINVAL; return -ENOMEM;
/* If hint, make sure it matches our alignment restrictions */ /* If hint, make sure it matches our alignment restrictions */
if (!fixed && addr) { if (!fixed && addr) {
......
...@@ -240,6 +240,7 @@ itlb_miss_fault_bolted: ...@@ -240,6 +240,7 @@ itlb_miss_fault_bolted:
beq tlb_miss_common_bolted beq tlb_miss_common_bolted
b itlb_miss_kernel_bolted b itlb_miss_kernel_bolted
#ifdef CONFIG_PPC_FSL_BOOK3E
/* /*
* TLB miss handling for e6500 and derivatives, using hardware tablewalk. * TLB miss handling for e6500 and derivatives, using hardware tablewalk.
* *
...@@ -409,7 +410,7 @@ itlb_miss_fault_e6500: ...@@ -409,7 +410,7 @@ itlb_miss_fault_e6500:
TLB_MISS_STATS_I(MMSTAT_TLB_MISS_NORM_FAULT) TLB_MISS_STATS_I(MMSTAT_TLB_MISS_NORM_FAULT)
tlb_epilog_bolted tlb_epilog_bolted
b exc_instruction_storage_book3e b exc_instruction_storage_book3e
#endif /* CONFIG_PPC_FSL_BOOK3E */
/********************************************************************** /**********************************************************************
* * * *
......
...@@ -557,10 +557,12 @@ static void setup_mmu_htw(void) ...@@ -557,10 +557,12 @@ static void setup_mmu_htw(void)
patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e); patch_exception(0x1c0, exc_data_tlb_miss_htw_book3e);
patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e); patch_exception(0x1e0, exc_instruction_tlb_miss_htw_book3e);
break; break;
#ifdef CONFIG_PPC_FSL_BOOK3E
case PPC_HTW_E6500: case PPC_HTW_E6500:
patch_exception(0x1c0, exc_data_tlb_miss_e6500_book3e); patch_exception(0x1c0, exc_data_tlb_miss_e6500_book3e);
patch_exception(0x1e0, exc_instruction_tlb_miss_e6500_book3e); patch_exception(0x1e0, exc_instruction_tlb_miss_e6500_book3e);
break; break;
#endif
} }
pr_info("MMU: Book3E HW tablewalk %s\n", pr_info("MMU: Book3E HW tablewalk %s\n",
book3e_htw_mode != PPC_HTW_NONE ? "enabled" : "not supported"); book3e_htw_mode != PPC_HTW_NONE ? "enabled" : "not supported");
......
config PPC_MPC512x config PPC_MPC512x
bool "512x-based boards" bool "512x-based boards"
depends on 6xx depends on 6xx
select COMMON_CLK
select FSL_SOC select FSL_SOC
select IPIC select IPIC
select PPC_CLOCK
select PPC_PCI_CHOICE select PPC_PCI_CHOICE
select FSL_PCI if PCI select FSL_PCI if PCI
select ARCH_WANT_OPTIONAL_GPIOLIB select ARCH_WANT_OPTIONAL_GPIOLIB
......
# #
# Makefile for the Freescale PowerPC 512x linux kernel. # Makefile for the Freescale PowerPC 512x linux kernel.
# #
obj-y += clock.o mpc512x_shared.o obj-$(CONFIG_COMMON_CLK) += clock-commonclk.o
obj-y += mpc512x_shared.o
obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o obj-$(CONFIG_MPC5121_ADS) += mpc5121_ads.o mpc5121_ads_cpld.o
obj-$(CONFIG_MPC512x_GENERIC) += mpc512x_generic.o obj-$(CONFIG_MPC512x_GENERIC) += mpc512x_generic.o
obj-$(CONFIG_PDM360NG) += pdm360ng.o obj-$(CONFIG_PDM360NG) += pdm360ng.o
This diff is collapsed.
This diff is collapsed.
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
* (at your option) any later version. * (at your option) any later version.
*/ */
#include <linux/clk.h>
#include <linux/kernel.h> #include <linux/kernel.h>
#include <linux/io.h> #include <linux/io.h>
#include <linux/irq.h> #include <linux/irq.h>
...@@ -68,98 +69,112 @@ struct fsl_diu_shared_fb { ...@@ -68,98 +69,112 @@ struct fsl_diu_shared_fb {
bool in_use; bool in_use;
}; };
#define DIU_DIV_MASK 0x000000ff /* receives a pixel clock spec in pico seconds, adjusts the DIU clock rate */
static void mpc512x_set_pixel_clock(unsigned int pixclock) static void mpc512x_set_pixel_clock(unsigned int pixclock)
{ {
unsigned long bestval, bestfreq, speed, busfreq;
unsigned long minpixclock, maxpixclock, pixval;
struct mpc512x_ccm __iomem *ccm;
struct device_node *np; struct device_node *np;
u32 temp; struct clk *clk_diu;
long err; unsigned long epsilon, minpixclock, maxpixclock;
int i; unsigned long offset, want, got, delta;
np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-clock"); /* lookup and enable the DIU clock */
np = of_find_compatible_node(NULL, NULL, "fsl,mpc5121-diu");
if (!np) { if (!np) {
pr_err("Can't find clock control module.\n"); pr_err("Could not find DIU device tree node.\n");
return; return;
} }
clk_diu = of_clk_get(np, 0);
ccm = of_iomap(np, 0); if (IS_ERR(clk_diu)) {
/* backwards compat with device trees that lack clock specs */
clk_diu = clk_get_sys(np->name, "ipg");
}
of_node_put(np); of_node_put(np);
if (!ccm) { if (IS_ERR(clk_diu)) {
pr_err("Can't map clock control module reg.\n"); pr_err("Could not lookup DIU clock.\n");
return; return;
} }
if (clk_prepare_enable(clk_diu)) {
np = of_find_node_by_type(NULL, "cpu"); pr_err("Could not enable DIU clock.\n");
if (np) {
const unsigned int *prop =
of_get_property(np, "bus-frequency", NULL);
of_node_put(np);
if (prop) {
busfreq = *prop;
} else {
pr_err("Can't get bus-frequency property\n");
return;
}
} else {
pr_err("Can't find 'cpu' node.\n");
return; return;
} }
/* Pixel Clock configuration */ /*
pr_debug("DIU: Bus Frequency = %lu\n", busfreq); * convert the picoseconds spec into the desired clock rate,
speed = busfreq * 4; /* DIU_DIV ratio is 4 * CSB_CLK / DIU_CLK */ * determine the acceptable clock range for the monitor (+/- 5%),
* do the calculation in steps to avoid integer overflow
/* Calculate the pixel clock with the smallest error */ */
/* calculate the following in steps to avoid overflow */ pr_debug("DIU pixclock in ps - %u\n", pixclock);
pr_debug("DIU pixclock in ps - %d\n", pixclock); pixclock = (1000000000 / pixclock) * 1000;
temp = (1000000000 / pixclock) * 1000; pr_debug("DIU pixclock freq - %u\n", pixclock);
pixclock = temp; epsilon = pixclock / 20; /* pixclock * 0.05 */
pr_debug("DIU pixclock freq - %u\n", pixclock); pr_debug("DIU deviation - %lu\n", epsilon);
minpixclock = pixclock - epsilon;
temp = temp / 20; /* pixclock * 0.05 */ maxpixclock = pixclock + epsilon;
pr_debug("deviation = %d\n", temp); pr_debug("DIU minpixclock - %lu\n", minpixclock);
minpixclock = pixclock - temp; pr_debug("DIU maxpixclock - %lu\n", maxpixclock);
maxpixclock = pixclock + temp;
pr_debug("DIU minpixclock - %lu\n", minpixclock); /*
pr_debug("DIU maxpixclock - %lu\n", maxpixclock); * check whether the DIU supports the desired pixel clock
pixval = speed/pixclock; *
pr_debug("DIU pixval = %lu\n", pixval); * - simply request the desired clock and see what the
* platform's clock driver will make of it, assuming that it
err = LONG_MAX; * will setup the best approximation of the requested value
bestval = pixval; * - try other candidate frequencies in the order of decreasing
pr_debug("DIU bestval = %lu\n", bestval); * preference (i.e. with increasing distance from the desired
* pixel clock, and checking the lower frequency before the
bestfreq = 0; * higher frequency to not overload the hardware) until the
for (i = -1; i <= 1; i++) { * first match is found -- any potential subsequent match
temp = speed / (pixval+i); * would only be as good as the former match or typically
pr_debug("DIU test pixval i=%d, pixval=%lu, temp freq. = %u\n", * would be less preferrable
i, pixval, temp); *
if ((temp < minpixclock) || (temp > maxpixclock)) * the offset increment of pixelclock divided by 64 is an
pr_debug("DIU exceeds monitor range (%lu to %lu)\n", * arbitrary choice -- it's simple to calculate, in the typical
minpixclock, maxpixclock); * case we expect the first check to succeed already, in the
else if (abs(temp - pixclock) < err) { * worst case seven frequencies get tested (the exact center and
pr_debug("Entered the else if block %d\n", i); * three more values each to the left and to the right) before
err = abs(temp - pixclock); * the 5% tolerance window is exceeded, resulting in fast enough
bestval = pixval + i; * execution yet high enough probability of finding a suitable
bestfreq = temp; * value, while the error rate will be in the order of single
} * percents
*/
for (offset = 0; offset <= epsilon; offset += pixclock / 64) {
want = pixclock - offset;
pr_debug("DIU checking clock - %lu\n", want);
clk_set_rate(clk_diu, want);
got = clk_get_rate(clk_diu);
delta = abs(pixclock - got);
if (delta < epsilon)
break;
if (!offset)
continue;
want = pixclock + offset;
pr_debug("DIU checking clock - %lu\n", want);
clk_set_rate(clk_diu, want);
got = clk_get_rate(clk_diu);
delta = abs(pixclock - got);
if (delta < epsilon)
break;
} }
if (offset <= epsilon) {
pr_debug("DIU clock accepted - %lu\n", want);
pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
pixclock, got, delta, epsilon);
return;
}
pr_warn("DIU pixclock auto search unsuccessful\n");
pr_debug("DIU chose = %lx\n", bestval); /*
pr_debug("DIU error = %ld\n NomPixClk ", err); * what is the most appropriate action to take when the search
pr_debug("DIU: Best Freq = %lx\n", bestfreq); * for an available pixel clock which is acceptable to the
/* Modify DIU_DIV in CCM SCFR1 */ * monitor has failed? disable the DIU (clock) or just provide
temp = in_be32(&ccm->scfr1); * a "best effort"? we go with the latter
pr_debug("DIU: Current value of SCFR1: 0x%08x\n", temp); */
temp &= ~DIU_DIV_MASK; pr_warn("DIU pixclock best effort fallback (backend's choice)\n");
temp |= (bestval & DIU_DIV_MASK); clk_set_rate(clk_diu, pixclock);
out_be32(&ccm->scfr1, temp); got = clk_get_rate(clk_diu);
pr_debug("DIU: Modified value of SCFR1: 0x%08x\n", temp); delta = abs(pixclock - got);
iounmap(ccm); pr_debug("DIU pixclock want %u, got %lu, delta %lu, eps %lu\n",
pixclock, got, delta, epsilon);
} }
static enum fsl_diu_monitor_port static enum fsl_diu_monitor_port
......
config PPC_MPC52xx config PPC_MPC52xx
bool "52xx-based boards" bool "52xx-based boards"
depends on 6xx depends on 6xx
select PPC_CLOCK select COMMON_CLK
select PPC_PCI_CHOICE select PPC_PCI_CHOICE
config PPC_MPC5200_SIMPLE config PPC_MPC5200_SIMPLE
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <linux/of_fdt.h> #include <linux/of_fdt.h>
#include <linux/interrupt.h> #include <linux/interrupt.h>
#include <linux/bug.h> #include <linux/bug.h>
#include <linux/cpuidle.h>
#include <asm/machdep.h> #include <asm/machdep.h>
#include <asm/firmware.h> #include <asm/firmware.h>
...@@ -216,6 +217,16 @@ static int __init pnv_probe(void) ...@@ -216,6 +217,16 @@ static int __init pnv_probe(void)
return 1; return 1;
} }
void powernv_idle(void)
{
/* Hook to cpuidle framework if available, else
* call on default platform idle code
*/
if (cpuidle_idle_call()) {
power7_idle();
}
}
define_machine(powernv) { define_machine(powernv) {
.name = "PowerNV", .name = "PowerNV",
.probe = pnv_probe, .probe = pnv_probe,
...@@ -225,7 +236,7 @@ define_machine(powernv) { ...@@ -225,7 +236,7 @@ define_machine(powernv) {
.show_cpuinfo = pnv_show_cpuinfo, .show_cpuinfo = pnv_show_cpuinfo,
.progress = pnv_progress, .progress = pnv_progress,
.machine_shutdown = pnv_shutdown, .machine_shutdown = pnv_shutdown,
.power_save = power7_idle, .power_save = powernv_idle,
.calibrate_decr = generic_calibrate_decr, .calibrate_decr = generic_calibrate_decr,
#ifdef CONFIG_KEXEC #ifdef CONFIG_KEXEC
.kexec_cpu_down = pnv_kexec_cpu_down, .kexec_cpu_down = pnv_kexec_cpu_down,
......
...@@ -119,12 +119,3 @@ config DTL ...@@ -119,12 +119,3 @@ config DTL
which are accessible through a debugfs file. which are accessible through a debugfs file.
Say N if you are unsure. Say N if you are unsure.
config PSERIES_IDLE
bool "Cpuidle driver for pSeries platforms"
depends on CPU_IDLE
depends on PPC_PSERIES
default y
help
Select this option to enable processor idle state management
through cpuidle subsystem.
...@@ -21,7 +21,6 @@ obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o ...@@ -21,7 +21,6 @@ obj-$(CONFIG_HCALL_STATS) += hvCall_inst.o
obj-$(CONFIG_CMM) += cmm.o obj-$(CONFIG_CMM) += cmm.o
obj-$(CONFIG_DTL) += dtl.o obj-$(CONFIG_DTL) += dtl.o
obj-$(CONFIG_IO_EVENT_IRQ) += io_event_irq.o obj-$(CONFIG_IO_EVENT_IRQ) += io_event_irq.o
obj-$(CONFIG_PSERIES_IDLE) += processor_idle.o
obj-$(CONFIG_LPARCFG) += lparcfg.o obj-$(CONFIG_LPARCFG) += lparcfg.o
ifeq ($(CONFIG_PPC_PSERIES),y) ifeq ($(CONFIG_PPC_PSERIES),y)
......
...@@ -292,6 +292,7 @@ static void iommu_table_dart_setup(void) ...@@ -292,6 +292,7 @@ static void iommu_table_dart_setup(void)
iommu_table_dart.it_offset = 0; iommu_table_dart.it_offset = 0;
/* it_size is in number of entries */ /* it_size is in number of entries */
iommu_table_dart.it_size = dart_tablesize / sizeof(u32); iommu_table_dart.it_size = dart_tablesize / sizeof(u32);
iommu_table_dart.it_page_shift = IOMMU_PAGE_SHIFT_4K;
/* Initialize the common IOMMU code */ /* Initialize the common IOMMU code */
iommu_table_dart.it_base = (unsigned long)dart_vbase; iommu_table_dart.it_base = (unsigned long)dart_vbase;
......
...@@ -35,6 +35,11 @@ depends on ARM ...@@ -35,6 +35,11 @@ depends on ARM
source "drivers/cpuidle/Kconfig.arm" source "drivers/cpuidle/Kconfig.arm"
endmenu endmenu
menu "POWERPC CPU Idle Drivers"
depends on PPC
source "drivers/cpuidle/Kconfig.powerpc"
endmenu
endif endif
config ARCH_NEEDS_CPU_IDLE_COUPLED config ARCH_NEEDS_CPU_IDLE_COUPLED
......
#
# POWERPC CPU Idle Drivers
#
config PSERIES_CPUIDLE
bool "Cpuidle driver for pSeries platforms"
depends on CPU_IDLE
depends on PPC_PSERIES
default y
help
Select this option to enable processor idle state management
through cpuidle subsystem.
config POWERNV_CPUIDLE
bool "Cpuidle driver for powernv platforms"
depends on CPU_IDLE
depends on PPC_POWERNV
default y
help
Select this option to enable processor idle state management
through cpuidle subsystem.
...@@ -13,3 +13,8 @@ obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o ...@@ -13,3 +13,8 @@ obj-$(CONFIG_ARM_KIRKWOOD_CPUIDLE) += cpuidle-kirkwood.o
obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o obj-$(CONFIG_ARM_ZYNQ_CPUIDLE) += cpuidle-zynq.o
obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o obj-$(CONFIG_ARM_U8500_CPUIDLE) += cpuidle-ux500.o
obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o obj-$(CONFIG_ARM_AT91_CPUIDLE) += cpuidle-at91.o
###############################################################################
# POWERPC drivers
obj-$(CONFIG_PSERIES_CPUIDLE) += cpuidle-pseries.o
obj-$(CONFIG_POWERNV_CPUIDLE) += cpuidle-powernv.o
/*
* cpuidle-powernv - idle state cpuidle driver.
* Adapted from drivers/cpuidle/cpuidle-pseries
*
*/
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/moduleparam.h>
#include <linux/cpuidle.h>
#include <linux/cpu.h>
#include <linux/notifier.h>
#include <asm/machdep.h>
#include <asm/firmware.h>
struct cpuidle_driver powernv_idle_driver = {
.name = "powernv_idle",
.owner = THIS_MODULE,
};
static int max_idle_state;
static struct cpuidle_state *cpuidle_state_table;
static int snooze_loop(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG);
while (!need_resched()) {
HMT_low();
HMT_very_low();
}
HMT_medium();
clear_thread_flag(TIF_POLLING_NRFLAG);
smp_mb();
return index;
}
static int nap_loop(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
power7_idle();
return index;
}
/*
* States for dedicated partition case.
*/
static struct cpuidle_state powernv_states[] = {
{ /* Snooze */
.name = "snooze",
.desc = "snooze",
.flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 0,
.target_residency = 0,
.enter = &snooze_loop },
{ /* NAP */
.name = "NAP",
.desc = "NAP",
.flags = CPUIDLE_FLAG_TIME_VALID,
.exit_latency = 10,
.target_residency = 100,
.enter = &nap_loop },
};
static int powernv_cpuidle_add_cpu_notifier(struct notifier_block *n,
unsigned long action, void *hcpu)
{
int hotcpu = (unsigned long)hcpu;
struct cpuidle_device *dev =
per_cpu(cpuidle_devices, hotcpu);
if (dev && cpuidle_get_driver()) {
switch (action) {
case CPU_ONLINE:
case CPU_ONLINE_FROZEN:
cpuidle_pause_and_lock();
cpuidle_enable_device(dev);
cpuidle_resume_and_unlock();
break;
case CPU_DEAD:
case CPU_DEAD_FROZEN:
cpuidle_pause_and_lock();
cpuidle_disable_device(dev);
cpuidle_resume_and_unlock();
break;
default:
return NOTIFY_DONE;
}
}
return NOTIFY_OK;
}
static struct notifier_block setup_hotplug_notifier = {
.notifier_call = powernv_cpuidle_add_cpu_notifier,
};
/*
* powernv_cpuidle_driver_init()
*/
static int powernv_cpuidle_driver_init(void)
{
int idle_state;
struct cpuidle_driver *drv = &powernv_idle_driver;
drv->state_count = 0;
for (idle_state = 0; idle_state < max_idle_state; ++idle_state) {
/* Is the state not enabled? */
if (cpuidle_state_table[idle_state].enter == NULL)
continue;
drv->states[drv->state_count] = /* structure copy */
cpuidle_state_table[idle_state];
drv->state_count += 1;
}
return 0;
}
/*
* powernv_idle_probe()
* Choose state table for shared versus dedicated partition
*/
static int powernv_idle_probe(void)
{
if (cpuidle_disable != IDLE_NO_OVERRIDE)
return -ENODEV;
if (firmware_has_feature(FW_FEATURE_OPALv3)) {
cpuidle_state_table = powernv_states;
max_idle_state = ARRAY_SIZE(powernv_states);
} else
return -ENODEV;
return 0;
}
static int __init powernv_processor_idle_init(void)
{
int retval;
retval = powernv_idle_probe();
if (retval)
return retval;
powernv_cpuidle_driver_init();
retval = cpuidle_register(&powernv_idle_driver, NULL);
if (retval) {
printk(KERN_DEBUG "Registration of powernv driver failed.\n");
return retval;
}
register_cpu_notifier(&setup_hotplug_notifier);
printk(KERN_DEBUG "powernv_idle_driver registered\n");
return 0;
}
device_initcall(powernv_processor_idle_init);
/* /*
* processor_idle - idle state cpuidle driver. * cpuidle-pseries - idle state cpuidle driver.
* Adapted from drivers/idle/intel_idle.c and * Adapted from drivers/idle/intel_idle.c and
* drivers/acpi/processor_idle.c * drivers/acpi/processor_idle.c
* *
...@@ -24,9 +24,7 @@ struct cpuidle_driver pseries_idle_driver = { ...@@ -24,9 +24,7 @@ struct cpuidle_driver pseries_idle_driver = {
.owner = THIS_MODULE, .owner = THIS_MODULE,
}; };
#define MAX_IDLE_STATE_COUNT 2 static int max_idle_state;
static int max_idle_state = MAX_IDLE_STATE_COUNT - 1;
static struct cpuidle_state *cpuidle_state_table; static struct cpuidle_state *cpuidle_state_table;
static inline void idle_loop_prolog(unsigned long *in_purr) static inline void idle_loop_prolog(unsigned long *in_purr)
...@@ -54,13 +52,12 @@ static int snooze_loop(struct cpuidle_device *dev, ...@@ -54,13 +52,12 @@ static int snooze_loop(struct cpuidle_device *dev,
int index) int index)
{ {
unsigned long in_purr; unsigned long in_purr;
int cpu = dev->cpu;
idle_loop_prolog(&in_purr); idle_loop_prolog(&in_purr);
local_irq_enable(); local_irq_enable();
set_thread_flag(TIF_POLLING_NRFLAG); set_thread_flag(TIF_POLLING_NRFLAG);
while ((!need_resched()) && cpu_online(cpu)) { while (!need_resched()) {
HMT_low(); HMT_low();
HMT_very_low(); HMT_very_low();
} }
...@@ -135,7 +132,7 @@ static int shared_cede_loop(struct cpuidle_device *dev, ...@@ -135,7 +132,7 @@ static int shared_cede_loop(struct cpuidle_device *dev,
/* /*
* States for dedicated partition case. * States for dedicated partition case.
*/ */
static struct cpuidle_state dedicated_states[MAX_IDLE_STATE_COUNT] = { static struct cpuidle_state dedicated_states[] = {
{ /* Snooze */ { /* Snooze */
.name = "snooze", .name = "snooze",
.desc = "snooze", .desc = "snooze",
...@@ -155,7 +152,7 @@ static struct cpuidle_state dedicated_states[MAX_IDLE_STATE_COUNT] = { ...@@ -155,7 +152,7 @@ static struct cpuidle_state dedicated_states[MAX_IDLE_STATE_COUNT] = {
/* /*
* States for shared partition case. * States for shared partition case.
*/ */
static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = { static struct cpuidle_state shared_states[] = {
{ /* Shared Cede */ { /* Shared Cede */
.name = "Shared Cede", .name = "Shared Cede",
.desc = "Shared Cede", .desc = "Shared Cede",
...@@ -165,29 +162,12 @@ static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = { ...@@ -165,29 +162,12 @@ static struct cpuidle_state shared_states[MAX_IDLE_STATE_COUNT] = {
.enter = &shared_cede_loop }, .enter = &shared_cede_loop },
}; };
void update_smt_snooze_delay(int cpu, int residency)
{
struct cpuidle_driver *drv = cpuidle_get_driver();
struct cpuidle_device *dev = per_cpu(cpuidle_devices, cpu);
if (cpuidle_state_table != dedicated_states)
return;
if (residency < 0) {
/* Disable the Nap state on that cpu */
if (dev)
dev->states_usage[1].disable = 1;
} else
if (drv)
drv->states[1].target_residency = residency;
}
static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n, static int pseries_cpuidle_add_cpu_notifier(struct notifier_block *n,
unsigned long action, void *hcpu) unsigned long action, void *hcpu)
{ {
int hotcpu = (unsigned long)hcpu; int hotcpu = (unsigned long)hcpu;
struct cpuidle_device *dev = struct cpuidle_device *dev =
per_cpu_ptr(cpuidle_devices, hotcpu); per_cpu(cpuidle_devices, hotcpu);
if (dev && cpuidle_get_driver()) { if (dev && cpuidle_get_driver()) {
switch (action) { switch (action) {
...@@ -226,12 +206,8 @@ static int pseries_cpuidle_driver_init(void) ...@@ -226,12 +206,8 @@ static int pseries_cpuidle_driver_init(void)
drv->state_count = 0; drv->state_count = 0;
for (idle_state = 0; idle_state < MAX_IDLE_STATE_COUNT; ++idle_state) { for (idle_state = 0; idle_state < max_idle_state; ++idle_state) {
/* Is the state not enabled? */
if (idle_state > max_idle_state)
break;
/* is the state not enabled? */
if (cpuidle_state_table[idle_state].enter == NULL) if (cpuidle_state_table[idle_state].enter == NULL)
continue; continue;
...@@ -251,21 +227,19 @@ static int pseries_cpuidle_driver_init(void) ...@@ -251,21 +227,19 @@ static int pseries_cpuidle_driver_init(void)
static int pseries_idle_probe(void) static int pseries_idle_probe(void)
{ {
if (!firmware_has_feature(FW_FEATURE_SPLPAR))
return -ENODEV;
if (cpuidle_disable != IDLE_NO_OVERRIDE) if (cpuidle_disable != IDLE_NO_OVERRIDE)
return -ENODEV; return -ENODEV;
if (max_idle_state == 0) { if (firmware_has_feature(FW_FEATURE_SPLPAR)) {
printk(KERN_DEBUG "pseries processor idle disabled.\n"); if (lppaca_shared_proc(get_lppaca())) {
return -EPERM; cpuidle_state_table = shared_states;
} max_idle_state = ARRAY_SIZE(shared_states);
} else {
if (lppaca_shared_proc(get_lppaca())) cpuidle_state_table = dedicated_states;
cpuidle_state_table = shared_states; max_idle_state = ARRAY_SIZE(dedicated_states);
else }
cpuidle_state_table = dedicated_states; } else
return -ENODEV;
return 0; return 0;
} }
...@@ -287,22 +261,7 @@ static int __init pseries_processor_idle_init(void) ...@@ -287,22 +261,7 @@ static int __init pseries_processor_idle_init(void)
register_cpu_notifier(&setup_hotplug_notifier); register_cpu_notifier(&setup_hotplug_notifier);
printk(KERN_DEBUG "pseries_idle_driver registered\n"); printk(KERN_DEBUG "pseries_idle_driver registered\n");
return 0; return 0;
} }
static void __exit pseries_processor_idle_exit(void) device_initcall(pseries_processor_idle_init);
{
unregister_cpu_notifier(&setup_hotplug_notifier);
cpuidle_unregister(&pseries_idle_driver);
return;
}
module_init(pseries_processor_idle_init);
module_exit(pseries_processor_idle_exit);
MODULE_AUTHOR("Deepthi Dharwar <deepthi@linux.vnet.ibm.com>");
MODULE_DESCRIPTION("Cpuidle driver for POWER");
MODULE_LICENSE("GPL");
...@@ -1580,7 +1580,7 @@ static int viu_of_probe(struct platform_device *op) ...@@ -1580,7 +1580,7 @@ static int viu_of_probe(struct platform_device *op)
} }
/* enable VIU clock */ /* enable VIU clock */
clk = devm_clk_get(&op->dev, "viu_clk"); clk = devm_clk_get(&op->dev, "ipg");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&op->dev, "failed to lookup the clock!\n"); dev_err(&op->dev, "failed to lookup the clock!\n");
ret = PTR_ERR(clk); ret = PTR_ERR(clk);
......
...@@ -729,7 +729,7 @@ static int mpc5121_nfc_probe(struct platform_device *op) ...@@ -729,7 +729,7 @@ static int mpc5121_nfc_probe(struct platform_device *op)
of_node_put(rootnode); of_node_put(rootnode);
/* Enable NFC clock */ /* Enable NFC clock */
clk = devm_clk_get(dev, "nfc_clk"); clk = devm_clk_get(dev, "ipg");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(dev, "Unable to acquire NFC clock!\n"); dev_err(dev, "Unable to acquire NFC clock!\n");
retval = PTR_ERR(clk); retval = PTR_ERR(clk);
......
...@@ -108,135 +108,170 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev, ...@@ -108,135 +108,170 @@ static u32 mpc52xx_can_get_clock(struct platform_device *ofdev,
#endif /* CONFIG_PPC_MPC52xx */ #endif /* CONFIG_PPC_MPC52xx */
#ifdef CONFIG_PPC_MPC512x #ifdef CONFIG_PPC_MPC512x
struct mpc512x_clockctl {
u32 spmr; /* System PLL Mode Reg */
u32 sccr[2]; /* System Clk Ctrl Reg 1 & 2 */
u32 scfr1; /* System Clk Freq Reg 1 */
u32 scfr2; /* System Clk Freq Reg 2 */
u32 reserved;
u32 bcr; /* Bread Crumb Reg */
u32 pccr[12]; /* PSC Clk Ctrl Reg 0-11 */
u32 spccr; /* SPDIF Clk Ctrl Reg */
u32 cccr; /* CFM Clk Ctrl Reg */
u32 dccr; /* DIU Clk Cnfg Reg */
u32 mccr[4]; /* MSCAN Clk Ctrl Reg 1-3 */
};
static struct of_device_id mpc512x_clock_ids[] = {
{ .compatible = "fsl,mpc5121-clock", },
{}
};
static u32 mpc512x_can_get_clock(struct platform_device *ofdev, static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
const char *clock_name, int *mscan_clksrc) const char *clock_source, int *mscan_clksrc)
{ {
struct mpc512x_clockctl __iomem *clockctl; struct device_node *np;
struct device_node *np_clock; u32 clockdiv;
struct clk *sys_clk, *ref_clk; enum {
int plen, clockidx, clocksrc = -1; CLK_FROM_AUTO,
u32 sys_freq, val, clockdiv = 1, freq = 0; CLK_FROM_IPS,
const u32 *pval; CLK_FROM_SYS,
CLK_FROM_REF,
np_clock = of_find_matching_node(NULL, mpc512x_clock_ids); } clk_from;
if (!np_clock) { struct clk *clk_in, *clk_can;
dev_err(&ofdev->dev, "couldn't find clock node\n"); unsigned long freq_calc;
return 0; struct mscan_priv *priv;
} struct clk *clk_ipg;
clockctl = of_iomap(np_clock, 0);
if (!clockctl) {
dev_err(&ofdev->dev, "couldn't map clock registers\n");
goto exit_put;
}
/* Determine the MSCAN device index from the peripheral's /* the caller passed in the clock source spec that was read from
* physical address. Register address offsets against the * the device tree, get the optional clock divider as well
* IMMR base are: 0x1300, 0x1380, 0x2300, 0x2380
*/ */
pval = of_get_property(ofdev->dev.of_node, "reg", &plen); np = ofdev->dev.of_node;
BUG_ON(!pval || plen < sizeof(*pval)); clockdiv = 1;
clockidx = (*pval & 0x80) ? 1 : 0; of_property_read_u32(np, "fsl,mscan-clock-divider", &clockdiv);
if (*pval & 0x2000) dev_dbg(&ofdev->dev, "device tree specs: clk src[%s] div[%d]\n",
clockidx += 2; clock_source ? clock_source : "<NULL>", clockdiv);
/* when clock-source is 'ip', the CANCTL1[CLKSRC] bit needs to
* get set, and the 'ips' clock is the input to the MSCAN
* component
*
* for clock-source values of 'ref' or 'sys' the CANCTL1[CLKSRC]
* bit needs to get cleared, an optional clock-divider may have
* been specified (the default value is 1), the appropriate
* MSCAN related MCLK is the input to the MSCAN component
*
* in the absence of a clock-source spec, first an optimal clock
* gets determined based on the 'sys' clock, if that fails the
* 'ref' clock is used
*/
clk_from = CLK_FROM_AUTO;
if (clock_source) {
/* interpret the device tree's spec for the clock source */
if (!strcmp(clock_source, "ip"))
clk_from = CLK_FROM_IPS;
else if (!strcmp(clock_source, "sys"))
clk_from = CLK_FROM_SYS;
else if (!strcmp(clock_source, "ref"))
clk_from = CLK_FROM_REF;
else
goto err_invalid;
dev_dbg(&ofdev->dev, "got a clk source spec[%d]\n", clk_from);
}
if (clk_from == CLK_FROM_AUTO) {
/* no spec so far, try the 'sys' clock; round to the
* next MHz and see if we can get a multiple of 16MHz
*/
dev_dbg(&ofdev->dev, "no clk source spec, trying SYS\n");
clk_in = devm_clk_get(&ofdev->dev, "sys");
if (IS_ERR(clk_in))
goto err_notavail;
freq_calc = clk_get_rate(clk_in);
freq_calc += 499999;
freq_calc /= 1000000;
freq_calc *= 1000000;
if ((freq_calc % 16000000) == 0) {
clk_from = CLK_FROM_SYS;
clockdiv = freq_calc / 16000000;
dev_dbg(&ofdev->dev,
"clk fit, sys[%lu] div[%d] freq[%lu]\n",
freq_calc, clockdiv, freq_calc / clockdiv);
}
}
if (clk_from == CLK_FROM_AUTO) {
/* no spec so far, use the 'ref' clock */
dev_dbg(&ofdev->dev, "no clk source spec, trying REF\n");
clk_in = devm_clk_get(&ofdev->dev, "ref");
if (IS_ERR(clk_in))
goto err_notavail;
clk_from = CLK_FROM_REF;
freq_calc = clk_get_rate(clk_in);
dev_dbg(&ofdev->dev,
"clk fit, ref[%lu] (no div) freq[%lu]\n",
freq_calc, freq_calc);
}
/* /* select IPS or MCLK as the MSCAN input (returned to the caller),
* Clock source and divider selection: 3 different clock sources * setup the MCLK mux source and rate if applicable, apply the
* can be selected: "ip", "ref" or "sys". For the latter two, a * optionally specified or derived above divider, and determine
* clock divider can be defined as well. If the clock source is * the actual resulting clock rate to return to the caller
* not specified by the device tree, we first try to find an
* optimal CAN source clock based on the system clock. If that
* is not posslible, the reference clock will be used.
*/ */
if (clock_name && !strcmp(clock_name, "ip")) { switch (clk_from) {
case CLK_FROM_IPS:
clk_can = devm_clk_get(&ofdev->dev, "ips");
if (IS_ERR(clk_can))
goto err_notavail;
priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
priv->clk_can = clk_can;
freq_calc = clk_get_rate(clk_can);
*mscan_clksrc = MSCAN_CLKSRC_IPS; *mscan_clksrc = MSCAN_CLKSRC_IPS;
freq = mpc5xxx_get_bus_frequency(ofdev->dev.of_node); dev_dbg(&ofdev->dev, "clk from IPS, clksrc[%d] freq[%lu]\n",
} else { *mscan_clksrc, freq_calc);
break;
case CLK_FROM_SYS:
case CLK_FROM_REF:
clk_can = devm_clk_get(&ofdev->dev, "mclk");
if (IS_ERR(clk_can))
goto err_notavail;
priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
priv->clk_can = clk_can;
if (clk_from == CLK_FROM_SYS)
clk_in = devm_clk_get(&ofdev->dev, "sys");
if (clk_from == CLK_FROM_REF)
clk_in = devm_clk_get(&ofdev->dev, "ref");
if (IS_ERR(clk_in))
goto err_notavail;
clk_set_parent(clk_can, clk_in);
freq_calc = clk_get_rate(clk_in);
freq_calc /= clockdiv;
clk_set_rate(clk_can, freq_calc);
freq_calc = clk_get_rate(clk_can);
*mscan_clksrc = MSCAN_CLKSRC_BUS; *mscan_clksrc = MSCAN_CLKSRC_BUS;
dev_dbg(&ofdev->dev, "clk from MCLK, clksrc[%d] freq[%lu]\n",
pval = of_get_property(ofdev->dev.of_node, *mscan_clksrc, freq_calc);
"fsl,mscan-clock-divider", &plen); break;
if (pval && plen == sizeof(*pval)) default:
clockdiv = *pval; goto err_invalid;
if (!clockdiv)
clockdiv = 1;
if (!clock_name || !strcmp(clock_name, "sys")) {
sys_clk = devm_clk_get(&ofdev->dev, "sys_clk");
if (IS_ERR(sys_clk)) {
dev_err(&ofdev->dev, "couldn't get sys_clk\n");
goto exit_unmap;
}
/* Get and round up/down sys clock rate */
sys_freq = 1000000 *
((clk_get_rate(sys_clk) + 499999) / 1000000);
if (!clock_name) {
/* A multiple of 16 MHz would be optimal */
if ((sys_freq % 16000000) == 0) {
clocksrc = 0;
clockdiv = sys_freq / 16000000;
freq = sys_freq / clockdiv;
}
} else {
clocksrc = 0;
freq = sys_freq / clockdiv;
}
}
if (clocksrc < 0) {
ref_clk = devm_clk_get(&ofdev->dev, "ref_clk");
if (IS_ERR(ref_clk)) {
dev_err(&ofdev->dev, "couldn't get ref_clk\n");
goto exit_unmap;
}
clocksrc = 1;
freq = clk_get_rate(ref_clk) / clockdiv;
}
} }
/* Disable clock */ /* the above clk_can item is used for the bitrate, access to
out_be32(&clockctl->mccr[clockidx], 0x0); * the peripheral's register set needs the clk_ipg item
if (clocksrc >= 0) { */
/* Set source and divider */ clk_ipg = devm_clk_get(&ofdev->dev, "ipg");
val = (clocksrc << 14) | ((clockdiv - 1) << 17); if (IS_ERR(clk_ipg))
out_be32(&clockctl->mccr[clockidx], val); goto err_notavail_ipg;
/* Enable clock */ if (clk_prepare_enable(clk_ipg))
out_be32(&clockctl->mccr[clockidx], val | 0x10000); goto err_notavail_ipg;
} priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
priv->clk_ipg = clk_ipg;
/* return the determined clock source rate */
return freq_calc;
err_invalid:
dev_err(&ofdev->dev, "invalid clock source specification\n");
/* clock source rate could not get determined */
return 0;
/* Enable MSCAN clock domain */ err_notavail:
val = in_be32(&clockctl->sccr[1]); dev_err(&ofdev->dev, "cannot acquire or setup bitrate clock source\n");
if (!(val & (1 << 25))) /* clock source rate could not get determined */
out_be32(&clockctl->sccr[1], val | (1 << 25)); return 0;
dev_dbg(&ofdev->dev, "using '%s' with frequency divider %d\n", err_notavail_ipg:
*mscan_clksrc == MSCAN_CLKSRC_IPS ? "ips_clk" : dev_err(&ofdev->dev, "cannot acquire or setup register clock\n");
clocksrc == 1 ? "ref_clk" : "sys_clk", clockdiv); /* clock source rate could not get determined */
return 0;
}
exit_unmap: static void mpc512x_can_put_clock(struct platform_device *ofdev)
iounmap(clockctl); {
exit_put: struct mscan_priv *priv;
of_node_put(np_clock);
return freq; priv = netdev_priv(dev_get_drvdata(&ofdev->dev));
if (priv->clk_ipg)
clk_disable_unprepare(priv->clk_ipg);
} }
#else /* !CONFIG_PPC_MPC512x */ #else /* !CONFIG_PPC_MPC512x */
static u32 mpc512x_can_get_clock(struct platform_device *ofdev, static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
...@@ -244,6 +279,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev, ...@@ -244,6 +279,7 @@ static u32 mpc512x_can_get_clock(struct platform_device *ofdev,
{ {
return 0; return 0;
} }
#define mpc512x_can_put_clock NULL
#endif /* CONFIG_PPC_MPC512x */ #endif /* CONFIG_PPC_MPC512x */
static const struct of_device_id mpc5xxx_can_table[]; static const struct of_device_id mpc5xxx_can_table[];
...@@ -385,11 +421,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev) ...@@ -385,11 +421,13 @@ static int mpc5xxx_can_resume(struct platform_device *ofdev)
static const struct mpc5xxx_can_data mpc5200_can_data = { static const struct mpc5xxx_can_data mpc5200_can_data = {
.type = MSCAN_TYPE_MPC5200, .type = MSCAN_TYPE_MPC5200,
.get_clock = mpc52xx_can_get_clock, .get_clock = mpc52xx_can_get_clock,
/* .put_clock not applicable */
}; };
static const struct mpc5xxx_can_data mpc5121_can_data = { static const struct mpc5xxx_can_data mpc5121_can_data = {
.type = MSCAN_TYPE_MPC5121, .type = MSCAN_TYPE_MPC5121,
.get_clock = mpc512x_can_get_clock, .get_clock = mpc512x_can_get_clock,
.put_clock = mpc512x_can_put_clock,
}; };
static const struct of_device_id mpc5xxx_can_table[] = { static const struct of_device_id mpc5xxx_can_table[] = {
......
...@@ -40,6 +40,7 @@ struct mpc512x_psc_spi { ...@@ -40,6 +40,7 @@ struct mpc512x_psc_spi {
unsigned int irq; unsigned int irq;
u8 bits_per_word; u8 bits_per_word;
struct clk *clk_mclk; struct clk *clk_mclk;
struct clk *clk_ipg;
u32 mclk_rate; u32 mclk_rate;
struct completion txisrdone; struct completion txisrdone;
...@@ -475,8 +476,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, ...@@ -475,8 +476,6 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
struct spi_master *master; struct spi_master *master;
int ret; int ret;
void *tempp; void *tempp;
int psc_num;
char clk_name[16];
struct clk *clk; struct clk *clk;
master = spi_alloc_master(dev, sizeof *mps); master = spi_alloc_master(dev, sizeof *mps);
...@@ -519,9 +518,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, ...@@ -519,9 +518,7 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
goto free_master; goto free_master;
init_completion(&mps->txisrdone); init_completion(&mps->txisrdone);
psc_num = master->bus_num; clk = devm_clk_get(dev, "mclk");
snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
clk = devm_clk_get(dev, clk_name);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
ret = PTR_ERR(clk); ret = PTR_ERR(clk);
goto free_master; goto free_master;
...@@ -532,17 +529,29 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr, ...@@ -532,17 +529,29 @@ static int mpc512x_psc_spi_do_probe(struct device *dev, u32 regaddr,
mps->clk_mclk = clk; mps->clk_mclk = clk;
mps->mclk_rate = clk_get_rate(clk); mps->mclk_rate = clk_get_rate(clk);
clk = devm_clk_get(dev, "ipg");
if (IS_ERR(clk)) {
ret = PTR_ERR(clk);
goto free_mclk_clock;
}
ret = clk_prepare_enable(clk);
if (ret)
goto free_mclk_clock;
mps->clk_ipg = clk;
ret = mpc512x_psc_spi_port_config(master, mps); ret = mpc512x_psc_spi_port_config(master, mps);
if (ret < 0) if (ret < 0)
goto free_clock; goto free_ipg_clock;
ret = devm_spi_register_master(dev, master); ret = devm_spi_register_master(dev, master);
if (ret < 0) if (ret < 0)
goto free_clock; goto free_ipg_clock;
return ret; return ret;
free_clock: free_ipg_clock:
clk_disable_unprepare(mps->clk_ipg);
free_mclk_clock:
clk_disable_unprepare(mps->clk_mclk); clk_disable_unprepare(mps->clk_mclk);
free_master: free_master:
spi_master_put(master); spi_master_put(master);
...@@ -556,6 +565,7 @@ static int mpc512x_psc_spi_do_remove(struct device *dev) ...@@ -556,6 +565,7 @@ static int mpc512x_psc_spi_do_remove(struct device *dev)
struct mpc512x_psc_spi *mps = spi_master_get_devdata(master); struct mpc512x_psc_spi *mps = spi_master_get_devdata(master);
clk_disable_unprepare(mps->clk_mclk); clk_disable_unprepare(mps->clk_mclk);
clk_disable_unprepare(mps->clk_ipg);
return 0; return 0;
} }
......
...@@ -421,6 +421,7 @@ struct psc_fifoc { ...@@ -421,6 +421,7 @@ struct psc_fifoc {
static struct psc_fifoc __iomem *psc_fifoc; static struct psc_fifoc __iomem *psc_fifoc;
static unsigned int psc_fifoc_irq; static unsigned int psc_fifoc_irq;
static struct clk *psc_fifoc_clk;
static void mpc512x_psc_fifo_init(struct uart_port *port) static void mpc512x_psc_fifo_init(struct uart_port *port)
{ {
...@@ -568,36 +569,73 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port, ...@@ -568,36 +569,73 @@ static unsigned int mpc512x_psc_set_baudrate(struct uart_port *port,
/* Init PSC FIFO Controller */ /* Init PSC FIFO Controller */
static int __init mpc512x_psc_fifoc_init(void) static int __init mpc512x_psc_fifoc_init(void)
{ {
int err;
struct device_node *np; struct device_node *np;
struct clk *clk;
/* default error code, potentially overwritten by clock calls */
err = -ENODEV;
np = of_find_compatible_node(NULL, NULL, np = of_find_compatible_node(NULL, NULL,
"fsl,mpc5121-psc-fifo"); "fsl,mpc5121-psc-fifo");
if (!np) { if (!np) {
pr_err("%s: Can't find FIFOC node\n", __func__); pr_err("%s: Can't find FIFOC node\n", __func__);
return -ENODEV; goto out_err;
} }
clk = of_clk_get(np, 0);
if (IS_ERR(clk)) {
/* backwards compat with device trees that lack clock specs */
clk = clk_get_sys(np->name, "ipg");
}
if (IS_ERR(clk)) {
pr_err("%s: Can't lookup FIFO clock\n", __func__);
err = PTR_ERR(clk);
goto out_ofnode_put;
}
if (clk_prepare_enable(clk)) {
pr_err("%s: Can't enable FIFO clock\n", __func__);
clk_put(clk);
goto out_ofnode_put;
}
psc_fifoc_clk = clk;
psc_fifoc = of_iomap(np, 0); psc_fifoc = of_iomap(np, 0);
if (!psc_fifoc) { if (!psc_fifoc) {
pr_err("%s: Can't map FIFOC\n", __func__); pr_err("%s: Can't map FIFOC\n", __func__);
of_node_put(np); goto out_clk_disable;
return -ENODEV;
} }
psc_fifoc_irq = irq_of_parse_and_map(np, 0); psc_fifoc_irq = irq_of_parse_and_map(np, 0);
of_node_put(np);
if (psc_fifoc_irq == 0) { if (psc_fifoc_irq == 0) {
pr_err("%s: Can't get FIFOC irq\n", __func__); pr_err("%s: Can't get FIFOC irq\n", __func__);
iounmap(psc_fifoc); goto out_unmap;
return -ENODEV;
} }
of_node_put(np);
return 0; return 0;
out_unmap:
iounmap(psc_fifoc);
out_clk_disable:
clk_disable_unprepare(psc_fifoc_clk);
clk_put(psc_fifoc_clk);
out_ofnode_put:
of_node_put(np);
out_err:
return err;
} }
static void __exit mpc512x_psc_fifoc_uninit(void) static void __exit mpc512x_psc_fifoc_uninit(void)
{ {
iounmap(psc_fifoc); iounmap(psc_fifoc);
/* disable the clock, errors are not fatal */
if (psc_fifoc_clk) {
clk_disable_unprepare(psc_fifoc_clk);
clk_put(psc_fifoc_clk);
psc_fifoc_clk = NULL;
}
} }
/* 512x specific interrupt handler. The caller holds the port lock */ /* 512x specific interrupt handler. The caller holds the port lock */
...@@ -619,29 +657,55 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port) ...@@ -619,29 +657,55 @@ static irqreturn_t mpc512x_psc_handle_irq(struct uart_port *port)
} }
static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM]; static struct clk *psc_mclk_clk[MPC52xx_PSC_MAXNUM];
static struct clk *psc_ipg_clk[MPC52xx_PSC_MAXNUM];
/* called from within the .request_port() callback (allocation) */ /* called from within the .request_port() callback (allocation) */
static int mpc512x_psc_alloc_clock(struct uart_port *port) static int mpc512x_psc_alloc_clock(struct uart_port *port)
{ {
int psc_num; int psc_num;
char clk_name[16];
struct clk *clk; struct clk *clk;
int err; int err;
psc_num = (port->mapbase & 0xf00) >> 8; psc_num = (port->mapbase & 0xf00) >> 8;
snprintf(clk_name, sizeof(clk_name), "psc%d_mclk", psc_num);
clk = devm_clk_get(port->dev, clk_name); clk = devm_clk_get(port->dev, "mclk");
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(port->dev, "Failed to get MCLK!\n"); dev_err(port->dev, "Failed to get MCLK!\n");
return PTR_ERR(clk); err = PTR_ERR(clk);
goto out_err;
} }
err = clk_prepare_enable(clk); err = clk_prepare_enable(clk);
if (err) { if (err) {
dev_err(port->dev, "Failed to enable MCLK!\n"); dev_err(port->dev, "Failed to enable MCLK!\n");
return err; goto out_err;
} }
psc_mclk_clk[psc_num] = clk; psc_mclk_clk[psc_num] = clk;
clk = devm_clk_get(port->dev, "ipg");
if (IS_ERR(clk)) {
dev_err(port->dev, "Failed to get IPG clock!\n");
err = PTR_ERR(clk);
goto out_err;
}
err = clk_prepare_enable(clk);
if (err) {
dev_err(port->dev, "Failed to enable IPG clock!\n");
goto out_err;
}
psc_ipg_clk[psc_num] = clk;
return 0; return 0;
out_err:
if (psc_mclk_clk[psc_num]) {
clk_disable_unprepare(psc_mclk_clk[psc_num]);
psc_mclk_clk[psc_num] = NULL;
}
if (psc_ipg_clk[psc_num]) {
clk_disable_unprepare(psc_ipg_clk[psc_num]);
psc_ipg_clk[psc_num] = NULL;
}
return err;
} }
/* called from within the .release_port() callback (release) */ /* called from within the .release_port() callback (release) */
...@@ -656,6 +720,10 @@ static void mpc512x_psc_relse_clock(struct uart_port *port) ...@@ -656,6 +720,10 @@ static void mpc512x_psc_relse_clock(struct uart_port *port)
clk_disable_unprepare(clk); clk_disable_unprepare(clk);
psc_mclk_clk[psc_num] = NULL; psc_mclk_clk[psc_num] = NULL;
} }
if (psc_ipg_clk[psc_num]) {
clk_disable_unprepare(psc_ipg_clk[psc_num]);
psc_ipg_clk[psc_num] = NULL;
}
} }
/* implementation of the .clock() callback (enable/disable) */ /* implementation of the .clock() callback (enable/disable) */
......
...@@ -261,19 +261,8 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev) ...@@ -261,19 +261,8 @@ int fsl_usb2_mpc5121_init(struct platform_device *pdev)
struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev); struct fsl_usb2_platform_data *pdata = dev_get_platdata(&pdev->dev);
struct clk *clk; struct clk *clk;
int err; int err;
char clk_name[10];
int base, clk_num;
base = pdev->resource->start & 0xf000;
if (base == 0x3000)
clk_num = 1;
else if (base == 0x4000)
clk_num = 2;
else
return -ENODEV;
snprintf(clk_name, sizeof(clk_name), "usb%d_clk", clk_num); clk = devm_clk_get(pdev->dev.parent, "ipg");
clk = devm_clk_get(pdev->dev.parent, clk_name);
if (IS_ERR(clk)) { if (IS_ERR(clk)) {
dev_err(&pdev->dev, "failed to get clk\n"); dev_err(&pdev->dev, "failed to get clk\n");
return PTR_ERR(clk); return PTR_ERR(clk);
......
/*
* This header provides constants for MPC512x clock specs in DT bindings.
*/
#ifndef _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
#define _DT_BINDINGS_CLOCK_MPC512x_CLOCK_H
#define MPC512x_CLK_DUMMY 0
#define MPC512x_CLK_REF 1
#define MPC512x_CLK_SYS 2
#define MPC512x_CLK_DIU 3
#define MPC512x_CLK_VIU 4
#define MPC512x_CLK_CSB 5
#define MPC512x_CLK_E300 6
#define MPC512x_CLK_IPS 7
#define MPC512x_CLK_FEC 8
#define MPC512x_CLK_SATA 9
#define MPC512x_CLK_PATA 10
#define MPC512x_CLK_NFC 11
#define MPC512x_CLK_LPC 12
#define MPC512x_CLK_MBX_BUS 13
#define MPC512x_CLK_MBX 14
#define MPC512x_CLK_MBX_3D 15
#define MPC512x_CLK_AXE 16
#define MPC512x_CLK_USB1 17
#define MPC512x_CLK_USB2 18
#define MPC512x_CLK_I2C 19
#define MPC512x_CLK_MSCAN0_MCLK 20
#define MPC512x_CLK_MSCAN1_MCLK 21
#define MPC512x_CLK_MSCAN2_MCLK 22
#define MPC512x_CLK_MSCAN3_MCLK 23
#define MPC512x_CLK_BDLC 24
#define MPC512x_CLK_SDHC 25
#define MPC512x_CLK_PCI 26
#define MPC512x_CLK_PSC_MCLK_IN 27
#define MPC512x_CLK_SPDIF_TX 28
#define MPC512x_CLK_SPDIF_RX 29
#define MPC512x_CLK_SPDIF_MCLK 30
#define MPC512x_CLK_SPDIF 31
#define MPC512x_CLK_AC97 32
#define MPC512x_CLK_PSC0_MCLK 33
#define MPC512x_CLK_PSC1_MCLK 34
#define MPC512x_CLK_PSC2_MCLK 35
#define MPC512x_CLK_PSC3_MCLK 36
#define MPC512x_CLK_PSC4_MCLK 37
#define MPC512x_CLK_PSC5_MCLK 38
#define MPC512x_CLK_PSC6_MCLK 39
#define MPC512x_CLK_PSC7_MCLK 40
#define MPC512x_CLK_PSC8_MCLK 41
#define MPC512x_CLK_PSC9_MCLK 42
#define MPC512x_CLK_PSC10_MCLK 43
#define MPC512x_CLK_PSC11_MCLK 44
#define MPC512x_CLK_PSC_FIFO 45
#define MPC512x_CLK_PSC0 46
#define MPC512x_CLK_PSC1 47
#define MPC512x_CLK_PSC2 48
#define MPC512x_CLK_PSC3 49
#define MPC512x_CLK_PSC4 50
#define MPC512x_CLK_PSC5 51
#define MPC512x_CLK_PSC6 52
#define MPC512x_CLK_PSC7 53
#define MPC512x_CLK_PSC8 54
#define MPC512x_CLK_PSC9 55
#define MPC512x_CLK_PSC10 56
#define MPC512x_CLK_PSC11 57
#define MPC512x_CLK_SDHC2 58
#define MPC512x_CLK_FEC2 59
#define MPC512x_CLK_OUT0_CLK 60
#define MPC512x_CLK_OUT1_CLK 61
#define MPC512x_CLK_OUT2_CLK 62
#define MPC512x_CLK_OUT3_CLK 63
#define MPC512x_CLK_CAN_CLK_IN 64
#define MPC512x_CLK_LAST_PUBLIC 64
#endif
...@@ -544,6 +544,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np, ...@@ -544,6 +544,20 @@ static inline const char *of_clk_get_parent_name(struct device_node *np,
* for improved portability across platforms * for improved portability across platforms
*/ */
#if IS_ENABLED(CONFIG_PPC)
static inline u32 clk_readl(u32 __iomem *reg)
{
return ioread32be(reg);
}
static inline void clk_writel(u32 val, u32 __iomem *reg)
{
iowrite32be(val, reg);
}
#else /* platform dependent I/O accessors */
static inline u32 clk_readl(u32 __iomem *reg) static inline u32 clk_readl(u32 __iomem *reg)
{ {
return readl(reg); return readl(reg);
...@@ -554,5 +568,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg) ...@@ -554,5 +568,7 @@ static inline void clk_writel(u32 val, u32 __iomem *reg)
writel(val, reg); writel(val, reg);
} }
#endif /* platform dependent I/O accessors */
#endif /* CONFIG_COMMON_CLK */ #endif /* CONFIG_COMMON_CLK */
#endif /* CLK_PROVIDER_H */ #endif /* CLK_PROVIDER_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment