ARM: SoC driver updates

These are changes for drivers that are intimately tied to some SoC
 and for some reason could not get merged through the respective
 subsystem maintainer tree.
 
 This time around, much of this is for at91, with the bulk of it being syscon
 and udc drivers.
 
 Also, there's:
 - coupled cpuidle support for Samsung Exynos4210
 - Renesas 73A0 common-clk work
 - of/platform changes to tear down DMA mappings on device destruction
 - a few updates to the TI Keystone knav code
 -----BEGIN PGP SIGNATURE-----
 Version: GnuPG v1
 
 iQIcBAABAgAGBQJU4upSAAoJEIwa5zzehBx3HkUP/Rc4B1yZChNIFNfVq4dbei6w
 dT9WdFmxOIj2JLeXEypFBiNf1nSHmsxrZe9/IDACz2fYQOnaZZ6/786utUJP/PtC
 2GDJy9cjL2Xh03We3nQp5z6J33XvpEni1t82cOpCl8wLBOQNnkjEks8UvLgi1LHW
 CNLcMm8JtDQ2aB/gRTjzetp9liZluESY5+Mig+loE2F/rzbMbNQDcWDDgUPyIQIS
 1onL+Bad3BnGFdo/+qnkurGc81pxoKiQJty06VWFftzvIwxXhsNjrqls2+KzstAx
 0lLvW1tqaDhXvUBImRM8GgfbldZslsgoFVmgESS9MpPMBNENYrkAiQNvJUnM7kd9
 qHDQNq+zRNsz/k4fVvp/YUp7xEiAo4rLcFmp/dBr535jS2LNyiZnB94q+kXsin/m
 tiyEMx+RWxEHTEHN9WdKE61Ty1RbzOa5UTLSzOKFAkF+m2nvuQsJvb97n19coAq9
 SSsj/wJgesfqrDEegphCDh1fyVxUzlAjjhTAyvPS155WvPzkbxZxuBbSqRuriRKA
 2aCfVne2ELimHAr3LEPgPW2kFBcONHckOGe6MvrTX4zPHU8bb9WIeg+iGdQChnr3
 nclT9jq+ZnQro5XTgUtPtadq100oEXlJbqpAzhd+cJbvgzSNbcWfcgE6kOWqd9uK
 oeWQWFLCdXLmXf9zCwmk
 =T7R2
 -----END PGP SIGNATURE-----

Merge tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc

Pull ARM SoC driver updates from Olof Johansson:
 "These are changes for drivers that are intimately tied to some SoC and
  for some reason could not get merged through the respective subsystem
  maintainer tree.

  This time around, much of this is for at91, with the bulk of it being
  syscon and udc drivers.

  Also, there's:
   - coupled cpuidle support for Samsung Exynos4210
   - Renesas 73A0 common-clk work
   - of/platform changes to tear down DMA mappings on device destruction
   - a few updates to the TI Keystone knav code"

* tag 'drivers-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/arm/arm-soc: (26 commits)
  cpuidle: exynos: add coupled cpuidle support for exynos4210
  ARM: EXYNOS: apply S5P_CENTRAL_SEQ_OPTION fix only when necessary
  soc: ti: knav_qmss_queue: change knav_range_setup_acc_irq to static
  soc: ti: knav_qmss_queue: makefile tweak to build as dynamic module
  pcmcia: at91_cf: depend on !ARCH_MULTIPLATFORM
  soc: ti: knav_qmss_queue: export API calls for use by user driver
  of/platform: teardown DMA mappings on device destruction
  usb: gadget: at91_udc: Allocate udc instance
  usb: gadget: at91_udc: Update DT binding documentation
  usb: gadget: at91_udc: Rework for multi-platform kernel support
  usb: gadget: at91_udc: Simplify probe and remove functions
  usb: gadget: at91_udc: Remove non-DT handling code
  usb: gadget: at91_udc: Document DT clocks and clock-names property
  usb: gadget: at91_udc: Drop uclk clock
  usb: gadget: at91_udc: Fix clock names
  mfd: syscon: Add Atmel SMC binding doc
  mfd: syscon: Add atmel-smc registers definition
  mfd: syscon: Add Atmel Matrix bus DT binding documentation
  mfd: syscon: Add atmel-matrix registers definition
  clk: shmobile: fix sparse NULL pointer warning
  ...
This commit is contained in:
Linus Torvalds 2015-02-17 09:38:59 -08:00
commit 18656782a8
28 changed files with 1570 additions and 268 deletions

View File

@ -0,0 +1,35 @@
These bindings should be considered EXPERIMENTAL for now.
* Renesas SH73A0 Clock Pulse Generator (CPG)
The CPG generates core clocks for the SH73A0 SoC. It includes four PLLs
and several fixed ratio dividers.
Required Properties:
- compatible: Must be "renesas,sh73a0-cpg-clocks"
- reg: Base address and length of the memory resource used by the CPG
- clocks: Reference to the parent clocks ("extal1" and "extal2")
- #clock-cells: Must be 1
- clock-output-names: The names of the clocks. Supported clocks are "main",
"pll0", "pll1", "pll2", "pll3", "dsi0phy", "dsi1phy", "zg", "m3", "b",
"m1", "m2", "z", "zx", and "hp".
Example
-------
cpg_clocks: cpg_clocks@e6150000 {
compatible = "renesas,sh73a0-cpg-clocks";
reg = <0 0xe6150000 0 0x10000>;
clocks = <&extal1_clk>, <&extal2_clk>;
#clock-cells = <1>;
clock-output-names = "main", "pll0", "pll1", "pll2",
"pll3", "dsi0phy", "dsi1phy",
"zg", "m3", "b", "m1", "m2",
"z", "zx", "hp";
};

View File

@ -0,0 +1,24 @@
* Device tree bindings for Atmel Bus Matrix
The Bus Matrix registers are used to configure Atmel SoCs internal bus
behavior (master/slave priorities, undefined burst length type, ...)
Required properties:
- compatible: Should be one of the following
"atmel,at91sam9260-matrix", "syscon"
"atmel,at91sam9261-matrix", "syscon"
"atmel,at91sam9263-matrix", "syscon"
"atmel,at91sam9rl-matrix", "syscon"
"atmel,at91sam9g45-matrix", "syscon"
"atmel,at91sam9n12-matrix", "syscon"
"atmel,at91sam9x5-matrix", "syscon"
"atmel,sama5d3-matrix", "syscon"
- reg: Contains offset/length value of the Bus Matrix
memory region.
Example:
matrix: matrix@ffffec00 {
compatible = "atmel,sama5d3-matrix", "syscon";
reg = <0xffffec00 0x200>;
};

View File

@ -0,0 +1,19 @@
* Device tree bindings for Atmel SMC (Static Memory Controller)
The SMC registers are used to configure Atmel EBI (External Bus Interface)
to interface with standard memory devices (NAND, NOR, SRAM or specialized
devices like FPGAs).
Required properties:
- compatible: Should be one of the following
"atmel,at91sam9260-smc", "syscon"
"atmel,sama5d3-smc", "syscon"
- reg: Contains offset/length value of the SMC memory
region.
Example:
smc: smc@ffffc000 {
compatible = "atmel,sama5d3-smc", "syscon";
reg = <0xffffc000 0x1000>;
};

View File

@ -33,9 +33,17 @@ usb1: ehci@00800000 {
AT91 USB device controller AT91 USB device controller
Required properties: Required properties:
- compatible: Should be "atmel,at91rm9200-udc" - compatible: Should be one of the following
"atmel,at91rm9200-udc"
"atmel,at91sam9260-udc"
"atmel,at91sam9261-udc"
"atmel,at91sam9263-udc"
- reg: Address and length of the register set for the device - reg: Address and length of the register set for the device
- interrupts: Should contain macb interrupt - interrupts: Should contain macb interrupt
- clocks: Should reference the peripheral and the AHB clocks
- clock-names: Should contains two strings
"pclk" for the peripheral clock
"hclk" for the AHB clock
Optional properties: Optional properties:
- atmel,vbus-gpio: If present, specifies a gpio that needs to be - atmel,vbus-gpio: If present, specifies a gpio that needs to be

View File

@ -182,6 +182,10 @@
status = "okay"; status = "okay";
}; };
&extal2_clk {
clock-frequency = <48000000>;
};
&i2c0 { &i2c0 {
status = "okay"; status = "okay";
as3711@40 { as3711@40 {

View File

@ -10,6 +10,7 @@
/include/ "skeleton.dtsi" /include/ "skeleton.dtsi"
#include <dt-bindings/clock/sh73a0-clock.h>
#include <dt-bindings/interrupt-controller/irq.h> #include <dt-bindings/interrupt-controller/irq.h>
/ { / {
@ -71,6 +72,8 @@
renesas,channels-mask = <0x3f>; renesas,channels-mask = <0x3f>;
clocks = <&mstp3_clks SH73A0_CLK_CMT1>;
clock-names = "fck";
status = "disabled"; status = "disabled";
}; };
@ -160,6 +163,7 @@
0 168 IRQ_TYPE_LEVEL_HIGH 0 168 IRQ_TYPE_LEVEL_HIGH
0 169 IRQ_TYPE_LEVEL_HIGH 0 169 IRQ_TYPE_LEVEL_HIGH
0 170 IRQ_TYPE_LEVEL_HIGH>; 0 170 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp1_clks SH73A0_CLK_IIC0>;
status = "disabled"; status = "disabled";
}; };
@ -172,6 +176,7 @@
0 52 IRQ_TYPE_LEVEL_HIGH 0 52 IRQ_TYPE_LEVEL_HIGH
0 53 IRQ_TYPE_LEVEL_HIGH 0 53 IRQ_TYPE_LEVEL_HIGH
0 54 IRQ_TYPE_LEVEL_HIGH>; 0 54 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks SH73A0_CLK_IIC1>;
status = "disabled"; status = "disabled";
}; };
@ -184,6 +189,7 @@
0 172 IRQ_TYPE_LEVEL_HIGH 0 172 IRQ_TYPE_LEVEL_HIGH
0 173 IRQ_TYPE_LEVEL_HIGH 0 173 IRQ_TYPE_LEVEL_HIGH
0 174 IRQ_TYPE_LEVEL_HIGH>; 0 174 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp0_clks SH73A0_CLK_IIC2>;
status = "disabled"; status = "disabled";
}; };
@ -196,6 +202,7 @@
0 184 IRQ_TYPE_LEVEL_HIGH 0 184 IRQ_TYPE_LEVEL_HIGH
0 185 IRQ_TYPE_LEVEL_HIGH 0 185 IRQ_TYPE_LEVEL_HIGH
0 186 IRQ_TYPE_LEVEL_HIGH>; 0 186 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp4_clks SH73A0_CLK_IIC3>;
status = "disabled"; status = "disabled";
}; };
@ -208,6 +215,7 @@
0 188 IRQ_TYPE_LEVEL_HIGH 0 188 IRQ_TYPE_LEVEL_HIGH
0 189 IRQ_TYPE_LEVEL_HIGH 0 189 IRQ_TYPE_LEVEL_HIGH
0 190 IRQ_TYPE_LEVEL_HIGH>; 0 190 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp4_clks SH73A0_CLK_IIC4>;
status = "disabled"; status = "disabled";
}; };
@ -216,6 +224,7 @@
reg = <0xe6bd0000 0x100>; reg = <0xe6bd0000 0x100>;
interrupts = <0 140 IRQ_TYPE_LEVEL_HIGH interrupts = <0 140 IRQ_TYPE_LEVEL_HIGH
0 141 IRQ_TYPE_LEVEL_HIGH>; 0 141 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks SH73A0_CLK_MMCIF0>;
reg-io-width = <4>; reg-io-width = <4>;
status = "disabled"; status = "disabled";
}; };
@ -226,6 +235,7 @@
interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH interrupts = <0 83 IRQ_TYPE_LEVEL_HIGH
0 84 IRQ_TYPE_LEVEL_HIGH 0 84 IRQ_TYPE_LEVEL_HIGH
0 85 IRQ_TYPE_LEVEL_HIGH>; 0 85 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks SH73A0_CLK_SDHI0>;
cap-sd-highspeed; cap-sd-highspeed;
status = "disabled"; status = "disabled";
}; };
@ -236,6 +246,7 @@
reg = <0xee120000 0x100>; reg = <0xee120000 0x100>;
interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH interrupts = <0 88 IRQ_TYPE_LEVEL_HIGH
0 89 IRQ_TYPE_LEVEL_HIGH>; 0 89 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks SH73A0_CLK_SDHI1>;
toshiba,mmc-wrprotect-disable; toshiba,mmc-wrprotect-disable;
cap-sd-highspeed; cap-sd-highspeed;
status = "disabled"; status = "disabled";
@ -246,6 +257,7 @@
reg = <0xee140000 0x100>; reg = <0xee140000 0x100>;
interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH interrupts = <0 104 IRQ_TYPE_LEVEL_HIGH
0 105 IRQ_TYPE_LEVEL_HIGH>; 0 105 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks SH73A0_CLK_SDHI2>;
toshiba,mmc-wrprotect-disable; toshiba,mmc-wrprotect-disable;
cap-sd-highspeed; cap-sd-highspeed;
status = "disabled"; status = "disabled";
@ -255,6 +267,8 @@
compatible = "renesas,scifa-sh73a0", "renesas,scifa"; compatible = "renesas,scifa-sh73a0", "renesas,scifa";
reg = <0xe6c40000 0x100>; reg = <0xe6c40000 0x100>;
interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 72 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp2_clks SH73A0_CLK_SCIFA0>;
clock-names = "sci_ick";
status = "disabled"; status = "disabled";
}; };
@ -262,6 +276,8 @@
compatible = "renesas,scifa-sh73a0", "renesas,scifa"; compatible = "renesas,scifa-sh73a0", "renesas,scifa";
reg = <0xe6c50000 0x100>; reg = <0xe6c50000 0x100>;
interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 73 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp2_clks SH73A0_CLK_SCIFA1>;
clock-names = "sci_ick";
status = "disabled"; status = "disabled";
}; };
@ -269,6 +285,8 @@
compatible = "renesas,scifa-sh73a0", "renesas,scifa"; compatible = "renesas,scifa-sh73a0", "renesas,scifa";
reg = <0xe6c60000 0x100>; reg = <0xe6c60000 0x100>;
interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 74 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp2_clks SH73A0_CLK_SCIFA2>;
clock-names = "sci_ick";
status = "disabled"; status = "disabled";
}; };
@ -276,6 +294,8 @@
compatible = "renesas,scifa-sh73a0", "renesas,scifa"; compatible = "renesas,scifa-sh73a0", "renesas,scifa";
reg = <0xe6c70000 0x100>; reg = <0xe6c70000 0x100>;
interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 75 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp2_clks SH73A0_CLK_SCIFA3>;
clock-names = "sci_ick";
status = "disabled"; status = "disabled";
}; };
@ -283,6 +303,8 @@
compatible = "renesas,scifa-sh73a0", "renesas,scifa"; compatible = "renesas,scifa-sh73a0", "renesas,scifa";
reg = <0xe6c80000 0x100>; reg = <0xe6c80000 0x100>;
interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 78 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp2_clks SH73A0_CLK_SCIFA4>;
clock-names = "sci_ick";
status = "disabled"; status = "disabled";
}; };
@ -290,6 +312,8 @@
compatible = "renesas,scifa-sh73a0", "renesas,scifa"; compatible = "renesas,scifa-sh73a0", "renesas,scifa";
reg = <0xe6cb0000 0x100>; reg = <0xe6cb0000 0x100>;
interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 79 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp2_clks SH73A0_CLK_SCIFA5>;
clock-names = "sci_ick";
status = "disabled"; status = "disabled";
}; };
@ -297,6 +321,8 @@
compatible = "renesas,scifa-sh73a0", "renesas,scifa"; compatible = "renesas,scifa-sh73a0", "renesas,scifa";
reg = <0xe6cc0000 0x100>; reg = <0xe6cc0000 0x100>;
interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 156 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp3_clks SH73A0_CLK_SCIFA6>;
clock-names = "sci_ick";
status = "disabled"; status = "disabled";
}; };
@ -304,6 +330,8 @@
compatible = "renesas,scifa-sh73a0", "renesas,scifa"; compatible = "renesas,scifa-sh73a0", "renesas,scifa";
reg = <0xe6cd0000 0x100>; reg = <0xe6cd0000 0x100>;
interrupts = <0 143 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 143 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp2_clks SH73A0_CLK_SCIFA7>;
clock-names = "sci_ick";
status = "disabled"; status = "disabled";
}; };
@ -311,6 +339,8 @@
compatible = "renesas,scifb-sh73a0", "renesas,scifb"; compatible = "renesas,scifb-sh73a0", "renesas,scifb";
reg = <0xe6c30000 0x100>; reg = <0xe6c30000 0x100>;
interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>; interrupts = <0 80 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&mstp2_clks SH73A0_CLK_SCIFB>;
clock-names = "sci_ick";
status = "disabled"; status = "disabled";
}; };
@ -338,4 +368,332 @@
interrupts = <0 146 0x4>; interrupts = <0 146 0x4>;
status = "disabled"; status = "disabled";
}; };
clocks {
#address-cells = <1>;
#size-cells = <1>;
ranges;
/* External root clocks */
extalr_clk: extalr_clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <32768>;
clock-output-names = "extalr";
};
extal1_clk: extal1_clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <26000000>;
clock-output-names = "extal1";
};
extal2_clk: extal2_clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-output-names = "extal2";
};
extcki_clk: extcki_clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-output-names = "extcki";
};
fsiack_clk: fsiack_clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <0>;
clock-output-names = "fsiack";
};
fsibck_clk: fsibck_clk {
compatible = "fixed-clock";
#clock-cells = <0>;
clock-frequency = <0>;
clock-output-names = "fsibck";
};
/* Special CPG clocks */
cpg_clocks: cpg_clocks@e6150000 {
compatible = "renesas,sh73a0-cpg-clocks";
reg = <0xe6150000 0x10000>;
clocks = <&extal1_clk>, <&extal2_clk>;
#clock-cells = <1>;
clock-output-names = "main", "pll0", "pll1", "pll2",
"pll3", "dsi0phy", "dsi1phy",
"zg", "m3", "b", "m1", "m2",
"z", "zx", "hp";
};
/* Variable factor clocks (DIV6) */
vclk1_clk: vclk1_clk@e6150008 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150008 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "vclk1";
};
vclk2_clk: vclk2_clk@e615000c {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe615000c 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "vclk2";
};
vclk3_clk: vclk3_clk@e615001c {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe615001c 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "vclk3";
};
zb_clk: zb_clk@e6150010 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150010 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "zb";
};
flctl_clk: flctl_clk@e6150014 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150014 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "flctlck";
};
sdhi0_clk: sdhi0_clk@e6150074 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150074 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "sdhi0ck";
};
sdhi1_clk: sdhi1_clk@e6150078 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150078 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "sdhi1ck";
};
sdhi2_clk: sdhi2_clk@e615007c {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe615007c 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "sdhi2ck";
};
fsia_clk: fsia_clk@e6150018 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150018 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "fsia";
};
fsib_clk: fsib_clk@e6150090 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150090 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "fsib";
};
sub_clk: sub_clk@e6150080 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150080 4>;
clocks = <&extal2_clk>;
#clock-cells = <0>;
clock-output-names = "sub";
};
spua_clk: spua_clk@e6150084 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150084 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "spua";
};
spuv_clk: spuv_clk@e6150094 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150094 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "spuv";
};
msu_clk: msu_clk@e6150088 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150088 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "msu";
};
hsi_clk: hsi_clk@e615008c {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe615008c 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "hsi";
};
mfg1_clk: mfg1_clk@e6150098 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150098 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "mfg1";
};
mfg2_clk: mfg2_clk@e615009c {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe615009c 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "mfg2";
};
dsit_clk: dsit_clk@e6150060 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150060 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "dsit";
};
dsi0p_clk: dsi0p_clk@e6150064 {
compatible = "renesas,sh73a0-div6-clock", "renesas,cpg-div6-clock";
reg = <0xe6150064 4>;
clocks = <&pll1_div2_clk>;
#clock-cells = <0>;
clock-output-names = "dsi0pck";
};
/* Fixed factor clocks */
main_div2_clk: main_div2_clk {
compatible = "fixed-factor-clock";
clocks = <&cpg_clocks SH73A0_CLK_MAIN>;
#clock-cells = <0>;
clock-div = <2>;
clock-mult = <1>;
clock-output-names = "main_div2";
};
pll1_div2_clk: pll1_div2_clk {
compatible = "fixed-factor-clock";
clocks = <&cpg_clocks SH73A0_CLK_PLL1>;
#clock-cells = <0>;
clock-div = <2>;
clock-mult = <1>;
clock-output-names = "pll1_div2";
};
pll1_div7_clk: pll1_div7_clk {
compatible = "fixed-factor-clock";
clocks = <&cpg_clocks SH73A0_CLK_PLL1>;
#clock-cells = <0>;
clock-div = <7>;
clock-mult = <1>;
clock-output-names = "pll1_div7";
};
pll1_div13_clk: pll1_div13_clk {
compatible = "fixed-factor-clock";
clocks = <&cpg_clocks SH73A0_CLK_PLL1>;
#clock-cells = <0>;
clock-div = <13>;
clock-mult = <1>;
clock-output-names = "pll1_div13";
};
twd_clk: twd_clk {
compatible = "fixed-factor-clock";
clocks = <&cpg_clocks SH73A0_CLK_Z>;
#clock-cells = <0>;
clock-div = <4>;
clock-mult = <1>;
clock-output-names = "twd";
};
/* Gate clocks */
mstp0_clks: mstp0_clks@e6150130 {
compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
reg = <0xe6150130 4>, <0xe6150030 4>;
clocks = <&cpg_clocks SH73A0_CLK_HP>;
#clock-cells = <1>;
clock-indices = <
SH73A0_CLK_IIC2
>;
clock-output-names =
"iic2";
};
mstp1_clks: mstp1_clks@e6150134 {
compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
reg = <0xe6150134 4>, <0xe6150038 4>;
clocks = <&cpg_clocks SH73A0_CLK_B>,
<&cpg_clocks SH73A0_CLK_B>,
<&cpg_clocks SH73A0_CLK_B>,
<&cpg_clocks SH73A0_CLK_B>,
<&sub_clk>, <&cpg_clocks SH73A0_CLK_B>,
<&cpg_clocks SH73A0_CLK_HP>,
<&cpg_clocks SH73A0_CLK_ZG>,
<&cpg_clocks SH73A0_CLK_B>;
#clock-cells = <1>;
clock-indices = <
SH73A0_CLK_CEU1 SH73A0_CLK_CSI2_RX1
SH73A0_CLK_CEU0 SH73A0_CLK_CSI2_RX0
SH73A0_CLK_TMU0 SH73A0_CLK_DSITX0
SH73A0_CLK_IIC0 SH73A0_CLK_SGX
SH73A0_CLK_LCDC0
>;
clock-output-names =
"ceu1", "csi2_rx1", "ceu0", "csi2_rx0",
"tmu0", "dsitx0", "iic0", "sgx", "lcdc0";
};
mstp2_clks: mstp2_clks@e6150138 {
compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
reg = <0xe6150138 4>, <0xe6150040 4>;
clocks = <&sub_clk>, <&cpg_clocks SH73A0_CLK_HP>,
<&cpg_clocks SH73A0_CLK_HP>, <&sub_clk>,
<&sub_clk>, <&sub_clk>, <&sub_clk>, <&sub_clk>,
<&sub_clk>, <&sub_clk>;
#clock-cells = <1>;
clock-indices = <
SH73A0_CLK_SCIFA7 SH73A0_CLK_SY_DMAC
SH73A0_CLK_MP_DMAC SH73A0_CLK_SCIFA5
SH73A0_CLK_SCIFB SH73A0_CLK_SCIFA0
SH73A0_CLK_SCIFA1 SH73A0_CLK_SCIFA2
SH73A0_CLK_SCIFA3 SH73A0_CLK_SCIFA4
>;
clock-output-names =
"scifa7", "sy_dmac", "mp_dmac", "scifa5",
"scifb", "scifa0", "scifa1", "scifa2",
"scifa3", "scifa4";
};
mstp3_clks: mstp3_clks@e615013c {
compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
reg = <0xe615013c 4>, <0xe6150048 4>;
clocks = <&sub_clk>, <&extalr_clk>,
<&cpg_clocks SH73A0_CLK_HP>, <&sub_clk>,
<&cpg_clocks SH73A0_CLK_HP>,
<&cpg_clocks SH73A0_CLK_HP>, <&flctl_clk>,
<&sdhi0_clk>, <&sdhi1_clk>,
<&cpg_clocks SH73A0_CLK_HP>, <&sdhi2_clk>,
<&main_div2_clk>, <&main_div2_clk>,
<&main_div2_clk>, <&main_div2_clk>,
<&main_div2_clk>;
#clock-cells = <1>;
clock-indices = <
SH73A0_CLK_SCIFA6 SH73A0_CLK_CMT1
SH73A0_CLK_FSI SH73A0_CLK_IRDA
SH73A0_CLK_IIC1 SH73A0_CLK_USB SH73A0_CLK_FLCTL
SH73A0_CLK_SDHI0 SH73A0_CLK_SDHI1
SH73A0_CLK_MMCIF0 SH73A0_CLK_SDHI2
SH73A0_CLK_TPU0 SH73A0_CLK_TPU1
SH73A0_CLK_TPU2 SH73A0_CLK_TPU3
SH73A0_CLK_TPU4
>;
clock-output-names =
"scifa6", "cmt1", "fsi", "irda", "iic1",
"usb", "flctl", "sdhi0", "sdhi1", "mmcif0", "sdhi2",
"tpu0", "tpu1", "tpu2", "tpu3", "tpu4";
};
mstp4_clks: mstp4_clks@e6150140 {
compatible = "renesas,sh73a0-mstp-clocks", "renesas,cpg-mstp-clocks";
reg = <0xe6150140 4>, <0xe615004c 4>;
clocks = <&cpg_clocks SH73A0_CLK_HP>,
<&cpg_clocks SH73A0_CLK_HP>, <&extalr_clk>;
#clock-cells = <1>;
clock-indices = <
SH73A0_CLK_IIC3 SH73A0_CLK_IIC4
SH73A0_CLK_KEYSC
>;
clock-output-names =
"iic3", "iic4", "keysc";
};
};
}; };

View File

@ -13,6 +13,7 @@
#define __ARCH_ARM_MACH_EXYNOS_COMMON_H #define __ARCH_ARM_MACH_EXYNOS_COMMON_H
#include <linux/of.h> #include <linux/of.h>
#include <linux/platform_data/cpuidle-exynos.h>
#define EXYNOS3250_SOC_ID 0xE3472000 #define EXYNOS3250_SOC_ID 0xE3472000
#define EXYNOS3_SOC_MASK 0xFFFFF000 #define EXYNOS3_SOC_MASK 0xFFFFF000
@ -150,8 +151,11 @@ extern void exynos_pm_central_suspend(void);
extern int exynos_pm_central_resume(void); extern int exynos_pm_central_resume(void);
extern void exynos_enter_aftr(void); extern void exynos_enter_aftr(void);
extern struct cpuidle_exynos_data cpuidle_coupled_exynos_data;
extern void s5p_init_cpu(void __iomem *cpuid_addr); extern void s5p_init_cpu(void __iomem *cpuid_addr);
extern unsigned int samsung_rev(void); extern unsigned int samsung_rev(void);
extern void __iomem *cpu_boot_reg_base(void);
static inline void pmu_raw_writel(u32 val, u32 offset) static inline void pmu_raw_writel(u32 val, u32 offset)
{ {

View File

@ -211,6 +211,10 @@ static void __init exynos_dt_machine_init(void)
if (!IS_ENABLED(CONFIG_SMP)) if (!IS_ENABLED(CONFIG_SMP))
exynos_sysram_init(); exynos_sysram_init();
#ifdef CONFIG_ARM_EXYNOS_CPUIDLE
if (of_machine_is_compatible("samsung,exynos4210"))
exynos_cpuidle.dev.platform_data = &cpuidle_coupled_exynos_data;
#endif
if (of_machine_is_compatible("samsung,exynos4210") || if (of_machine_is_compatible("samsung,exynos4210") ||
of_machine_is_compatible("samsung,exynos4212") || of_machine_is_compatible("samsung,exynos4212") ||
(of_machine_is_compatible("samsung,exynos4412") && (of_machine_is_compatible("samsung,exynos4412") &&

View File

@ -194,7 +194,7 @@ int exynos_cluster_power_state(int cluster)
S5P_CORE_LOCAL_PWR_EN); S5P_CORE_LOCAL_PWR_EN);
} }
static inline void __iomem *cpu_boot_reg_base(void) void __iomem *cpu_boot_reg_base(void)
{ {
if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1) if (soc_is_exynos4210() && samsung_rev() == EXYNOS4210_REV_1_1)
return pmu_base_addr + S5P_INFORM5; return pmu_base_addr + S5P_INFORM5;

View File

@ -98,10 +98,6 @@ void exynos_pm_central_suspend(void)
tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION); tmp = pmu_raw_readl(S5P_CENTRAL_SEQ_CONFIGURATION);
tmp &= ~S5P_CENTRAL_LOWPWR_CFG; tmp &= ~S5P_CENTRAL_LOWPWR_CFG;
pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION); pmu_raw_writel(tmp, S5P_CENTRAL_SEQ_CONFIGURATION);
/* Setting SEQ_OPTION register */
pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
S5P_CENTRAL_SEQ_OPTION);
} }
int exynos_pm_central_resume(void) int exynos_pm_central_resume(void)
@ -165,6 +161,13 @@ void exynos_enter_aftr(void)
exynos_pm_central_suspend(); exynos_pm_central_suspend();
if (of_machine_is_compatible("samsung,exynos4212") ||
of_machine_is_compatible("samsung,exynos4412")) {
/* Setting SEQ_OPTION register */
pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
S5P_CENTRAL_SEQ_OPTION);
}
cpu_suspend(0, exynos_aftr_finisher); cpu_suspend(0, exynos_aftr_finisher);
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) { if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) {
@ -177,3 +180,125 @@ void exynos_enter_aftr(void)
cpu_pm_exit(); cpu_pm_exit();
} }
static atomic_t cpu1_wakeup = ATOMIC_INIT(0);
static int exynos_cpu0_enter_aftr(void)
{
int ret = -1;
/*
* If the other cpu is powered on, we have to power it off, because
* the AFTR state won't work otherwise
*/
if (cpu_online(1)) {
/*
* We reach a sync point with the coupled idle state, we know
* the other cpu will power down itself or will abort the
* sequence, let's wait for one of these to happen
*/
while (exynos_cpu_power_state(1)) {
/*
* The other cpu may skip idle and boot back
* up again
*/
if (atomic_read(&cpu1_wakeup))
goto abort;
/*
* The other cpu may bounce through idle and
* boot back up again, getting stuck in the
* boot rom code
*/
if (__raw_readl(cpu_boot_reg_base()) == 0)
goto abort;
cpu_relax();
}
}
exynos_enter_aftr();
ret = 0;
abort:
if (cpu_online(1)) {
/*
* Set the boot vector to something non-zero
*/
__raw_writel(virt_to_phys(exynos_cpu_resume),
cpu_boot_reg_base());
dsb();
/*
* Turn on cpu1 and wait for it to be on
*/
exynos_cpu_power_up(1);
while (exynos_cpu_power_state(1) != S5P_CORE_LOCAL_PWR_EN)
cpu_relax();
while (!atomic_read(&cpu1_wakeup)) {
/*
* Poke cpu1 out of the boot rom
*/
__raw_writel(virt_to_phys(exynos_cpu_resume),
cpu_boot_reg_base());
arch_send_wakeup_ipi_mask(cpumask_of(1));
}
}
return ret;
}
static int exynos_wfi_finisher(unsigned long flags)
{
cpu_do_idle();
return -1;
}
static int exynos_cpu1_powerdown(void)
{
int ret = -1;
/*
* Idle sequence for cpu1
*/
if (cpu_pm_enter())
goto cpu1_aborted;
/*
* Turn off cpu 1
*/
exynos_cpu_power_down(1);
ret = cpu_suspend(0, exynos_wfi_finisher);
cpu_pm_exit();
cpu1_aborted:
dsb();
/*
* Notify cpu 0 that cpu 1 is awake
*/
atomic_set(&cpu1_wakeup, 1);
return ret;
}
static void exynos_pre_enter_aftr(void)
{
__raw_writel(virt_to_phys(exynos_cpu_resume), cpu_boot_reg_base());
}
static void exynos_post_enter_aftr(void)
{
atomic_set(&cpu1_wakeup, 0);
}
struct cpuidle_exynos_data cpuidle_coupled_exynos_data = {
.cpu0_enter_aftr = exynos_cpu0_enter_aftr,
.cpu1_powerdown = exynos_cpu1_powerdown,
.pre_enter_aftr = exynos_pre_enter_aftr,
.post_enter_aftr = exynos_post_enter_aftr,
};

View File

@ -319,6 +319,10 @@ static int exynos_pm_suspend(void)
{ {
exynos_pm_central_suspend(); exynos_pm_central_suspend();
/* Setting SEQ_OPTION register */
pmu_raw_writel(S5P_USE_STANDBY_WFI0 | S5P_USE_STANDBY_WFE0,
S5P_CENTRAL_SEQ_OPTION);
if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9) if (read_cpuid_part() == ARM_CPU_PART_CORTEX_A9)
exynos_cpu_save_register(); exynos_cpu_save_register();

View File

@ -766,7 +766,9 @@ void __init __weak sh73a0_register_twd(void) { }
void __init sh73a0_earlytimer_init(void) void __init sh73a0_earlytimer_init(void)
{ {
shmobile_init_delay(); shmobile_init_delay();
#ifndef CONFIG_COMMON_CLK
sh73a0_clock_init(); sh73a0_clock_init();
#endif
shmobile_earlytimer_init(); shmobile_earlytimer_init();
sh73a0_register_twd(); sh73a0_register_twd();
} }
@ -785,8 +787,9 @@ void __init sh73a0_add_early_devices(void)
void __init sh73a0_add_standard_devices_dt(void) void __init sh73a0_add_standard_devices_dt(void)
{ {
/* clocks are setup late during boot in the case of DT */ /* clocks are setup late during boot in the case of DT */
#ifndef CONFIG_COMMON_CLK
sh73a0_clock_init(); sh73a0_clock_init();
#endif
of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL); of_platform_populate(NULL, of_default_bus_match_table, NULL, NULL);
} }

View File

@ -5,5 +5,6 @@ obj-$(CONFIG_ARCH_R8A7779) += clk-r8a7779.o
obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7790) += clk-rcar-gen2.o
obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7791) += clk-rcar-gen2.o
obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o obj-$(CONFIG_ARCH_R8A7794) += clk-rcar-gen2.o
obj-$(CONFIG_ARCH_SH73A0) += clk-sh73a0.o
obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-div6.o
obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o obj-$(CONFIG_ARCH_SHMOBILE_MULTI) += clk-mstp.o

View File

@ -0,0 +1,218 @@
/*
* sh73a0 Core CPG Clocks
*
* Copyright (C) 2014 Ulrich Hecht
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*/
#include <linux/clk-provider.h>
#include <linux/clkdev.h>
#include <linux/clk/shmobile.h>
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/spinlock.h>
struct sh73a0_cpg {
struct clk_onecell_data data;
spinlock_t lock;
void __iomem *reg;
};
#define CPG_FRQCRA 0x00
#define CPG_FRQCRB 0x04
#define CPG_SD0CKCR 0x74
#define CPG_SD1CKCR 0x78
#define CPG_SD2CKCR 0x7c
#define CPG_PLLECR 0xd0
#define CPG_PLL0CR 0xd8
#define CPG_PLL1CR 0x28
#define CPG_PLL2CR 0x2c
#define CPG_PLL3CR 0xdc
#define CPG_CKSCR 0xc0
#define CPG_DSI0PHYCR 0x6c
#define CPG_DSI1PHYCR 0x70
#define CLK_ENABLE_ON_INIT BIT(0)
struct div4_clk {
const char *name;
const char *parent;
unsigned int reg;
unsigned int shift;
};
static struct div4_clk div4_clks[] = {
{ "zg", "pll0", CPG_FRQCRA, 16 },
{ "m3", "pll1", CPG_FRQCRA, 12 },
{ "b", "pll1", CPG_FRQCRA, 8 },
{ "m1", "pll1", CPG_FRQCRA, 4 },
{ "m2", "pll1", CPG_FRQCRA, 0 },
{ "zx", "pll1", CPG_FRQCRB, 12 },
{ "hp", "pll1", CPG_FRQCRB, 4 },
{ NULL, NULL, 0, 0 },
};
static const struct clk_div_table div4_div_table[] = {
{ 0, 2 }, { 1, 3 }, { 2, 4 }, { 3, 6 }, { 4, 8 }, { 5, 12 },
{ 6, 16 }, { 7, 18 }, { 8, 24 }, { 10, 36 }, { 11, 48 },
{ 12, 7 }, { 0, 0 }
};
static const struct clk_div_table z_div_table[] = {
/* ZSEL == 0 */
{ 0, 1 }, { 1, 1 }, { 2, 1 }, { 3, 1 }, { 4, 1 }, { 5, 1 },
{ 6, 1 }, { 7, 1 }, { 8, 1 }, { 9, 1 }, { 10, 1 }, { 11, 1 },
{ 12, 1 }, { 13, 1 }, { 14, 1 }, { 15, 1 },
/* ZSEL == 1 */
{ 16, 2 }, { 17, 3 }, { 18, 4 }, { 19, 6 }, { 20, 8 }, { 21, 12 },
{ 22, 16 }, { 24, 24 }, { 27, 48 }, { 0, 0 }
};
static struct clk * __init
sh73a0_cpg_register_clock(struct device_node *np, struct sh73a0_cpg *cpg,
const char *name)
{
const struct clk_div_table *table = NULL;
unsigned int shift, reg, width;
const char *parent_name;
unsigned int mult = 1;
unsigned int div = 1;
if (!strcmp(name, "main")) {
/* extal1, extal1_div2, extal2, extal2_div2 */
u32 parent_idx = (clk_readl(cpg->reg + CPG_CKSCR) >> 28) & 3;
parent_name = of_clk_get_parent_name(np, parent_idx >> 1);
div = (parent_idx & 1) + 1;
} else if (!strncmp(name, "pll", 3)) {
void __iomem *enable_reg = cpg->reg;
u32 enable_bit = name[3] - '0';
parent_name = "main";
switch (enable_bit) {
case 0:
enable_reg += CPG_PLL0CR;
break;
case 1:
enable_reg += CPG_PLL1CR;
break;
case 2:
enable_reg += CPG_PLL2CR;
break;
case 3:
enable_reg += CPG_PLL3CR;
break;
default:
return ERR_PTR(-EINVAL);
}
if (clk_readl(cpg->reg + CPG_PLLECR) & BIT(enable_bit)) {
mult = ((clk_readl(enable_reg) >> 24) & 0x3f) + 1;
/* handle CFG bit for PLL1 and PLL2 */
if (enable_bit == 1 || enable_bit == 2)
if (clk_readl(enable_reg) & BIT(20))
mult *= 2;
}
} else if (!strcmp(name, "dsi0phy") || !strcmp(name, "dsi1phy")) {
u32 phy_no = name[3] - '0';
void __iomem *dsi_reg = cpg->reg +
(phy_no ? CPG_DSI1PHYCR : CPG_DSI0PHYCR);
parent_name = phy_no ? "dsi1pck" : "dsi0pck";
mult = __raw_readl(dsi_reg);
if (!(mult & 0x8000))
mult = 1;
else
mult = (mult & 0x3f) + 1;
} else if (!strcmp(name, "z")) {
parent_name = "pll0";
table = z_div_table;
reg = CPG_FRQCRB;
shift = 24;
width = 5;
} else {
struct div4_clk *c;
for (c = div4_clks; c->name; c++) {
if (!strcmp(name, c->name)) {
parent_name = c->parent;
table = div4_div_table;
reg = c->reg;
shift = c->shift;
width = 4;
break;
}
}
if (!c->name)
return ERR_PTR(-EINVAL);
}
if (!table) {
return clk_register_fixed_factor(NULL, name, parent_name, 0,
mult, div);
} else {
return clk_register_divider_table(NULL, name, parent_name, 0,
cpg->reg + reg, shift, width, 0,
table, &cpg->lock);
}
}
static void __init sh73a0_cpg_clocks_init(struct device_node *np)
{
struct sh73a0_cpg *cpg;
struct clk **clks;
unsigned int i;
int num_clks;
num_clks = of_property_count_strings(np, "clock-output-names");
if (num_clks < 0) {
pr_err("%s: failed to count clocks\n", __func__);
return;
}
cpg = kzalloc(sizeof(*cpg), GFP_KERNEL);
clks = kcalloc(num_clks, sizeof(*clks), GFP_KERNEL);
if (cpg == NULL || clks == NULL) {
/* We're leaking memory on purpose, there's no point in cleaning
* up as the system won't boot anyway.
*/
return;
}
spin_lock_init(&cpg->lock);
cpg->data.clks = clks;
cpg->data.clk_num = num_clks;
cpg->reg = of_iomap(np, 0);
if (WARN_ON(cpg->reg == NULL))
return;
/* Set SDHI clocks to a known state */
clk_writel(0x108, cpg->reg + CPG_SD0CKCR);
clk_writel(0x108, cpg->reg + CPG_SD1CKCR);
clk_writel(0x108, cpg->reg + CPG_SD2CKCR);
for (i = 0; i < num_clks; ++i) {
const char *name;
struct clk *clk;
of_property_read_string_index(np, "clock-output-names", i,
&name);
clk = sh73a0_cpg_register_clock(np, cpg, name);
if (IS_ERR(clk))
pr_err("%s: failed to register %s %s clock (%ld)\n",
__func__, np->name, name, PTR_ERR(clk));
else
cpg->data.clks[i] = clk;
}
of_clk_add_provider(np, of_clk_src_onecell_get, &cpg->data);
}
CLK_OF_DECLARE(sh73a0_cpg_clks, "renesas,sh73a0-cpg-clocks",
sh73a0_cpg_clocks_init);

View File

@ -55,6 +55,7 @@ config ARM_AT91_CPUIDLE
config ARM_EXYNOS_CPUIDLE config ARM_EXYNOS_CPUIDLE
bool "Cpu Idle Driver for the Exynos processors" bool "Cpu Idle Driver for the Exynos processors"
depends on ARCH_EXYNOS depends on ARCH_EXYNOS
select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
help help
Select this to enable cpuidle for Exynos processors Select this to enable cpuidle for Exynos processors

View File

@ -1,8 +1,11 @@
/* linux/arch/arm/mach-exynos/cpuidle.c /*
* * Copyright (c) 2011-2014 Samsung Electronics Co., Ltd.
* Copyright (c) 2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com * http://www.samsung.com
* *
* Coupled cpuidle support based on the work of:
* Colin Cross <ccross@android.com>
* Daniel Lezcano <daniel.lezcano@linaro.org>
*
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation. * published by the Free Software Foundation.
@ -13,13 +16,49 @@
#include <linux/export.h> #include <linux/export.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/platform_device.h> #include <linux/platform_device.h>
#include <linux/of.h>
#include <linux/platform_data/cpuidle-exynos.h>
#include <asm/proc-fns.h> #include <asm/proc-fns.h>
#include <asm/suspend.h> #include <asm/suspend.h>
#include <asm/cpuidle.h> #include <asm/cpuidle.h>
static atomic_t exynos_idle_barrier;
static struct cpuidle_exynos_data *exynos_cpuidle_pdata;
static void (*exynos_enter_aftr)(void); static void (*exynos_enter_aftr)(void);
static int exynos_enter_coupled_lowpower(struct cpuidle_device *dev,
struct cpuidle_driver *drv,
int index)
{
int ret;
exynos_cpuidle_pdata->pre_enter_aftr();
/*
* Waiting all cpus to reach this point at the same moment
*/
cpuidle_coupled_parallel_barrier(dev, &exynos_idle_barrier);
/*
* Both cpus will reach this point at the same time
*/
ret = dev->cpu ? exynos_cpuidle_pdata->cpu1_powerdown()
: exynos_cpuidle_pdata->cpu0_enter_aftr();
if (ret)
index = ret;
/*
* Waiting all cpus to finish the power sequence before going further
*/
cpuidle_coupled_parallel_barrier(dev, &exynos_idle_barrier);
exynos_cpuidle_pdata->post_enter_aftr();
return index;
}
static int exynos_enter_lowpower(struct cpuidle_device *dev, static int exynos_enter_lowpower(struct cpuidle_device *dev,
struct cpuidle_driver *drv, struct cpuidle_driver *drv,
int index) int index)
@ -55,13 +94,40 @@ static struct cpuidle_driver exynos_idle_driver = {
.safe_state_index = 0, .safe_state_index = 0,
}; };
static struct cpuidle_driver exynos_coupled_idle_driver = {
.name = "exynos_coupled_idle",
.owner = THIS_MODULE,
.states = {
[0] = ARM_CPUIDLE_WFI_STATE,
[1] = {
.enter = exynos_enter_coupled_lowpower,
.exit_latency = 5000,
.target_residency = 10000,
.flags = CPUIDLE_FLAG_COUPLED |
CPUIDLE_FLAG_TIMER_STOP,
.name = "C1",
.desc = "ARM power down",
},
},
.state_count = 2,
.safe_state_index = 0,
};
static int exynos_cpuidle_probe(struct platform_device *pdev) static int exynos_cpuidle_probe(struct platform_device *pdev)
{ {
int ret; int ret;
exynos_enter_aftr = (void *)(pdev->dev.platform_data); if (of_machine_is_compatible("samsung,exynos4210")) {
exynos_cpuidle_pdata = pdev->dev.platform_data;
ret = cpuidle_register(&exynos_coupled_idle_driver,
cpu_possible_mask);
} else {
exynos_enter_aftr = (void *)(pdev->dev.platform_data);
ret = cpuidle_register(&exynos_idle_driver, NULL);
}
ret = cpuidle_register(&exynos_idle_driver, NULL);
if (ret) { if (ret) {
dev_err(&pdev->dev, "failed to register cpuidle driver\n"); dev_err(&pdev->dev, "failed to register cpuidle driver\n");
return ret; return ret;

View File

@ -526,6 +526,7 @@ static int of_platform_device_destroy(struct device *dev, void *data)
amba_device_unregister(to_amba_device(dev)); amba_device_unregister(to_amba_device(dev));
#endif #endif
of_dma_deconfigure(dev);
of_node_clear_flag(dev->of_node, OF_POPULATED); of_node_clear_flag(dev->of_node, OF_POPULATED);
of_node_clear_flag(dev->of_node, OF_POPULATED_BUS); of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
return 0; return 0;

View File

@ -279,6 +279,7 @@ config BFIN_CFPCMCIA
config AT91_CF config AT91_CF
tristate "AT91 CompactFlash Controller" tristate "AT91 CompactFlash Controller"
depends on PCMCIA && ARCH_AT91 depends on PCMCIA && ARCH_AT91
depends on !ARCH_MULTIPLATFORM
help help
Say Y here to support the CompactFlash controller on AT91 chips. Say Y here to support the CompactFlash controller on AT91 chips.
Or choose M to compile the driver as a module named "at91_cf". Or choose M to compile the driver as a module named "at91_cf".

View File

@ -1,5 +1,6 @@
# #
# TI Keystone SOC drivers # TI Keystone SOC drivers
# #
obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS) += knav_qmss_queue.o knav_qmss_acc.o obj-$(CONFIG_KEYSTONE_NAVIGATOR_QMSS) += knav_qmss.o
knav_qmss-y := knav_qmss_queue.o knav_qmss_acc.o
obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o obj-$(CONFIG_KEYSTONE_NAVIGATOR_DMA) += knav_dma.o

View File

@ -209,7 +209,7 @@ static irqreturn_t knav_acc_int_handler(int irq, void *_instdata)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
int knav_range_setup_acc_irq(struct knav_range_info *range, static int knav_range_setup_acc_irq(struct knav_range_info *range,
int queue, bool enabled) int queue, bool enabled)
{ {
struct knav_device *kdev = range->kdev; struct knav_device *kdev = range->kdev;

View File

@ -626,6 +626,7 @@ int knav_queue_push(void *qhandle, dma_addr_t dma,
atomic_inc(&qh->stats.pushes); atomic_inc(&qh->stats.pushes);
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(knav_queue_push);
/** /**
* knav_queue_pop() - pop data (or descriptor) from the head of a queue * knav_queue_pop() - pop data (or descriptor) from the head of a queue
@ -663,6 +664,7 @@ dma_addr_t knav_queue_pop(void *qhandle, unsigned *size)
atomic_inc(&qh->stats.pops); atomic_inc(&qh->stats.pops);
return dma; return dma;
} }
EXPORT_SYMBOL_GPL(knav_queue_pop);
/* carve out descriptors and push into queue */ /* carve out descriptors and push into queue */
static void kdesc_fill_pool(struct knav_pool *pool) static void kdesc_fill_pool(struct knav_pool *pool)
@ -717,12 +719,14 @@ dma_addr_t knav_pool_desc_virt_to_dma(void *ph, void *virt)
struct knav_pool *pool = ph; struct knav_pool *pool = ph;
return pool->region->dma_start + (virt - pool->region->virt_start); return pool->region->dma_start + (virt - pool->region->virt_start);
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_virt_to_dma);
void *knav_pool_desc_dma_to_virt(void *ph, dma_addr_t dma) void *knav_pool_desc_dma_to_virt(void *ph, dma_addr_t dma)
{ {
struct knav_pool *pool = ph; struct knav_pool *pool = ph;
return pool->region->virt_start + (dma - pool->region->dma_start); return pool->region->virt_start + (dma - pool->region->dma_start);
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_dma_to_virt);
/** /**
* knav_pool_create() - Create a pool of descriptors * knav_pool_create() - Create a pool of descriptors
@ -878,6 +882,7 @@ void *knav_pool_desc_get(void *ph)
data = knav_pool_desc_dma_to_virt(pool, dma); data = knav_pool_desc_dma_to_virt(pool, dma);
return data; return data;
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_get);
/** /**
* knav_pool_desc_put() - return a descriptor to the pool * knav_pool_desc_put() - return a descriptor to the pool
@ -890,6 +895,7 @@ void knav_pool_desc_put(void *ph, void *desc)
dma = knav_pool_desc_virt_to_dma(pool, desc); dma = knav_pool_desc_virt_to_dma(pool, desc);
knav_queue_push(pool->queue, dma, pool->region->desc_size, 0); knav_queue_push(pool->queue, dma, pool->region->desc_size, 0);
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_put);
/** /**
* knav_pool_desc_map() - Map descriptor for DMA transfer * knav_pool_desc_map() - Map descriptor for DMA transfer
@ -916,6 +922,7 @@ int knav_pool_desc_map(void *ph, void *desc, unsigned size,
return 0; return 0;
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_map);
/** /**
* knav_pool_desc_unmap() - Unmap descriptor after DMA transfer * knav_pool_desc_unmap() - Unmap descriptor after DMA transfer
@ -938,6 +945,7 @@ void *knav_pool_desc_unmap(void *ph, dma_addr_t dma, unsigned dma_sz)
prefetch(desc); prefetch(desc);
return desc; return desc;
} }
EXPORT_SYMBOL_GPL(knav_pool_desc_unmap);
/** /**
* knav_pool_count() - Get the number of descriptors in pool. * knav_pool_count() - Get the number of descriptors in pool.
@ -949,6 +957,7 @@ int knav_pool_count(void *ph)
struct knav_pool *pool = ph; struct knav_pool *pool = ph;
return knav_queue_get_count(pool->queue); return knav_queue_get_count(pool->queue);
} }
EXPORT_SYMBOL_GPL(knav_pool_count);
static void knav_queue_setup_region(struct knav_device *kdev, static void knav_queue_setup_region(struct knav_device *kdev,
struct knav_region *region) struct knav_region *region)

View File

@ -32,6 +32,7 @@ menu "USB Peripheral Controller"
config USB_AT91 config USB_AT91
tristate "Atmel AT91 USB Device Port" tristate "Atmel AT91 USB Device Port"
depends on ARCH_AT91 depends on ARCH_AT91
depends on OF || COMPILE_TEST
help help
Many Atmel AT91 processors (such as the AT91RM2000) have a Many Atmel AT91 processors (such as the AT91RM2000) have a
full speed USB Device Port with support for five configurable full speed USB Device Port with support for five configurable

View File

@ -31,16 +31,9 @@
#include <linux/of.h> #include <linux/of.h>
#include <linux/of_gpio.h> #include <linux/of_gpio.h>
#include <linux/platform_data/atmel.h> #include <linux/platform_data/atmel.h>
#include <linux/regmap.h>
#include <asm/byteorder.h> #include <linux/mfd/syscon.h>
#include <mach/hardware.h> #include <linux/mfd/syscon/atmel-matrix.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/gpio.h>
#include <mach/cpu.h>
#include <mach/at91sam9261_matrix.h>
#include <mach/at91_matrix.h>
#include "at91_udc.h" #include "at91_udc.h"
@ -66,7 +59,15 @@
#define DRIVER_VERSION "3 May 2006" #define DRIVER_VERSION "3 May 2006"
static const char driver_name [] = "at91_udc"; static const char driver_name [] = "at91_udc";
static const char ep0name[] = "ep0"; static const char * const ep_names[] = {
"ep0",
"ep1",
"ep2",
"ep3-int",
"ep4",
"ep5",
};
#define ep0name ep_names[0]
#define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000) #define VBUS_POLL_TIMEOUT msecs_to_jiffies(1000)
@ -895,8 +896,6 @@ static void clk_on(struct at91_udc *udc)
return; return;
udc->clocked = 1; udc->clocked = 1;
if (IS_ENABLED(CONFIG_COMMON_CLK))
clk_enable(udc->uclk);
clk_enable(udc->iclk); clk_enable(udc->iclk);
clk_enable(udc->fclk); clk_enable(udc->fclk);
} }
@ -909,8 +908,6 @@ static void clk_off(struct at91_udc *udc)
udc->gadget.speed = USB_SPEED_UNKNOWN; udc->gadget.speed = USB_SPEED_UNKNOWN;
clk_disable(udc->fclk); clk_disable(udc->fclk);
clk_disable(udc->iclk); clk_disable(udc->iclk);
if (IS_ENABLED(CONFIG_COMMON_CLK))
clk_disable(udc->uclk);
} }
/* /*
@ -919,8 +916,6 @@ static void clk_off(struct at91_udc *udc)
*/ */
static void pullup(struct at91_udc *udc, int is_on) static void pullup(struct at91_udc *udc, int is_on)
{ {
int active = !udc->board.pullup_active_low;
if (!udc->enabled || !udc->vbus) if (!udc->enabled || !udc->vbus)
is_on = 0; is_on = 0;
DBG("%sactive\n", is_on ? "" : "in"); DBG("%sactive\n", is_on ? "" : "in");
@ -929,40 +924,15 @@ static void pullup(struct at91_udc *udc, int is_on)
clk_on(udc); clk_on(udc);
at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM); at91_udp_write(udc, AT91_UDP_ICR, AT91_UDP_RXRSM);
at91_udp_write(udc, AT91_UDP_TXVC, 0); at91_udp_write(udc, AT91_UDP_TXVC, 0);
if (cpu_is_at91rm9200())
gpio_set_value(udc->board.pullup_pin, active);
else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
txvc |= AT91_UDP_TXVC_PUON;
at91_udp_write(udc, AT91_UDP_TXVC, txvc);
} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
u32 usbpucr;
usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR);
usbpucr |= AT91_MATRIX_USBPUCR_PUON;
at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr);
}
} else { } else {
stop_activity(udc); stop_activity(udc);
at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM); at91_udp_write(udc, AT91_UDP_IDR, AT91_UDP_RXRSM);
at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
if (cpu_is_at91rm9200())
gpio_set_value(udc->board.pullup_pin, !active);
else if (cpu_is_at91sam9260() || cpu_is_at91sam9263() || cpu_is_at91sam9g20()) {
u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
txvc &= ~AT91_UDP_TXVC_PUON;
at91_udp_write(udc, AT91_UDP_TXVC, txvc);
} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
u32 usbpucr;
usbpucr = at91_matrix_read(AT91_MATRIX_USBPUCR);
usbpucr &= ~AT91_MATRIX_USBPUCR_PUON;
at91_matrix_write(AT91_MATRIX_USBPUCR, usbpucr);
}
clk_off(udc); clk_off(udc);
} }
if (udc->caps && udc->caps->pullup)
udc->caps->pullup(udc, is_on);
} }
/* vbus is here! turn everything on that's ready */ /* vbus is here! turn everything on that's ready */
@ -1535,74 +1505,6 @@ static irqreturn_t at91_udc_irq (int irq, void *_udc)
/*-------------------------------------------------------------------------*/ /*-------------------------------------------------------------------------*/
static struct at91_udc controller = {
.gadget = {
.ops = &at91_udc_ops,
.ep0 = &controller.ep[0].ep,
.name = driver_name,
},
.ep[0] = {
.ep = {
.name = ep0name,
.ops = &at91_ep_ops,
},
.udc = &controller,
.maxpacket = 8,
.int_mask = 1 << 0,
},
.ep[1] = {
.ep = {
.name = "ep1",
.ops = &at91_ep_ops,
},
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 64,
.int_mask = 1 << 1,
},
.ep[2] = {
.ep = {
.name = "ep2",
.ops = &at91_ep_ops,
},
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 64,
.int_mask = 1 << 2,
},
.ep[3] = {
.ep = {
/* could actually do bulk too */
.name = "ep3-int",
.ops = &at91_ep_ops,
},
.udc = &controller,
.maxpacket = 8,
.int_mask = 1 << 3,
},
.ep[4] = {
.ep = {
.name = "ep4",
.ops = &at91_ep_ops,
},
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 256,
.int_mask = 1 << 4,
},
.ep[5] = {
.ep = {
.name = "ep5",
.ops = &at91_ep_ops,
},
.udc = &controller,
.is_pingpong = 1,
.maxpacket = 256,
.int_mask = 1 << 5,
},
/* ep6 and ep7 are also reserved (custom silicon might use them) */
};
static void at91_vbus_update(struct at91_udc *udc, unsigned value) static void at91_vbus_update(struct at91_udc *udc, unsigned value)
{ {
value ^= udc->board.vbus_active_low; value ^= udc->board.vbus_active_low;
@ -1687,12 +1589,202 @@ static void at91udc_shutdown(struct platform_device *dev)
spin_unlock_irqrestore(&udc->lock, flags); spin_unlock_irqrestore(&udc->lock, flags);
} }
static void at91udc_of_init(struct at91_udc *udc, static int at91rm9200_udc_init(struct at91_udc *udc)
struct device_node *np) {
struct at91_ep *ep;
int ret;
int i;
for (i = 0; i < NUM_ENDPOINTS; i++) {
ep = &udc->ep[i];
switch (i) {
case 0:
case 3:
ep->maxpacket = 8;
break;
case 1 ... 2:
ep->maxpacket = 64;
break;
case 4 ... 5:
ep->maxpacket = 256;
break;
}
}
if (!gpio_is_valid(udc->board.pullup_pin)) {
DBG("no D+ pullup?\n");
return -ENODEV;
}
ret = devm_gpio_request(&udc->pdev->dev, udc->board.pullup_pin,
"udc_pullup");
if (ret) {
DBG("D+ pullup is busy\n");
return ret;
}
gpio_direction_output(udc->board.pullup_pin,
udc->board.pullup_active_low);
return 0;
}
static void at91rm9200_udc_pullup(struct at91_udc *udc, int is_on)
{
int active = !udc->board.pullup_active_low;
if (is_on)
gpio_set_value(udc->board.pullup_pin, active);
else
gpio_set_value(udc->board.pullup_pin, !active);
}
static const struct at91_udc_caps at91rm9200_udc_caps = {
.init = at91rm9200_udc_init,
.pullup = at91rm9200_udc_pullup,
};
static int at91sam9260_udc_init(struct at91_udc *udc)
{
struct at91_ep *ep;
int i;
for (i = 0; i < NUM_ENDPOINTS; i++) {
ep = &udc->ep[i];
switch (i) {
case 0 ... 3:
ep->maxpacket = 64;
break;
case 4 ... 5:
ep->maxpacket = 512;
break;
}
}
return 0;
}
static void at91sam9260_udc_pullup(struct at91_udc *udc, int is_on)
{
u32 txvc = at91_udp_read(udc, AT91_UDP_TXVC);
if (is_on)
txvc |= AT91_UDP_TXVC_PUON;
else
txvc &= ~AT91_UDP_TXVC_PUON;
at91_udp_write(udc, AT91_UDP_TXVC, txvc);
}
static const struct at91_udc_caps at91sam9260_udc_caps = {
.init = at91sam9260_udc_init,
.pullup = at91sam9260_udc_pullup,
};
static int at91sam9261_udc_init(struct at91_udc *udc)
{
struct at91_ep *ep;
int i;
for (i = 0; i < NUM_ENDPOINTS; i++) {
ep = &udc->ep[i];
switch (i) {
case 0:
ep->maxpacket = 8;
break;
case 1 ... 3:
ep->maxpacket = 64;
break;
case 4 ... 5:
ep->maxpacket = 256;
break;
}
}
udc->matrix = syscon_regmap_lookup_by_phandle(udc->pdev->dev.of_node,
"atmel,matrix");
if (IS_ERR(udc->matrix))
return PTR_ERR(udc->matrix);
return 0;
}
static void at91sam9261_udc_pullup(struct at91_udc *udc, int is_on)
{
u32 usbpucr = 0;
if (is_on)
usbpucr = AT91_MATRIX_USBPUCR_PUON;
regmap_update_bits(udc->matrix, AT91SAM9261_MATRIX_USBPUCR,
AT91_MATRIX_USBPUCR_PUON, usbpucr);
}
static const struct at91_udc_caps at91sam9261_udc_caps = {
.init = at91sam9261_udc_init,
.pullup = at91sam9261_udc_pullup,
};
static int at91sam9263_udc_init(struct at91_udc *udc)
{
struct at91_ep *ep;
int i;
for (i = 0; i < NUM_ENDPOINTS; i++) {
ep = &udc->ep[i];
switch (i) {
case 0:
case 1:
case 2:
case 3:
ep->maxpacket = 64;
break;
case 4:
case 5:
ep->maxpacket = 256;
break;
}
}
return 0;
}
static const struct at91_udc_caps at91sam9263_udc_caps = {
.init = at91sam9263_udc_init,
.pullup = at91sam9260_udc_pullup,
};
static const struct of_device_id at91_udc_dt_ids[] = {
{
.compatible = "atmel,at91rm9200-udc",
.data = &at91rm9200_udc_caps,
},
{
.compatible = "atmel,at91sam9260-udc",
.data = &at91sam9260_udc_caps,
},
{
.compatible = "atmel,at91sam9261-udc",
.data = &at91sam9261_udc_caps,
},
{
.compatible = "atmel,at91sam9263-udc",
.data = &at91sam9263_udc_caps,
},
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, at91_udc_dt_ids);
static void at91udc_of_init(struct at91_udc *udc, struct device_node *np)
{ {
struct at91_udc_data *board = &udc->board; struct at91_udc_data *board = &udc->board;
u32 val; const struct of_device_id *match;
enum of_gpio_flags flags; enum of_gpio_flags flags;
u32 val;
if (of_property_read_u32(np, "atmel,vbus-polled", &val) == 0) if (of_property_read_u32(np, "atmel,vbus-polled", &val) == 0)
board->vbus_polled = 1; board->vbus_polled = 1;
@ -1705,6 +1797,10 @@ static void at91udc_of_init(struct at91_udc *udc,
&flags); &flags);
board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0; board->pullup_active_low = (flags & OF_GPIO_ACTIVE_LOW) ? 1 : 0;
match = of_match_node(at91_udc_dt_ids, np);
if (match)
udc->caps = match->data;
} }
static int at91udc_probe(struct platform_device *pdev) static int at91udc_probe(struct platform_device *pdev)
@ -1713,97 +1809,67 @@ static int at91udc_probe(struct platform_device *pdev)
struct at91_udc *udc; struct at91_udc *udc;
int retval; int retval;
struct resource *res; struct resource *res;
struct at91_ep *ep;
int i;
if (!dev_get_platdata(dev) && !pdev->dev.of_node) { udc = devm_kzalloc(dev, sizeof(*udc), GFP_KERNEL);
/* small (so we copy it) but critical! */ if (!udc)
DBG("missing platform_data\n"); return -ENOMEM;
return -ENODEV;
}
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (!res)
return -ENXIO;
if (!request_mem_region(res->start, resource_size(res), driver_name)) {
DBG("someone's using UDC memory\n");
return -EBUSY;
}
/* init software state */ /* init software state */
udc = &controller;
udc->gadget.dev.parent = dev; udc->gadget.dev.parent = dev;
if (IS_ENABLED(CONFIG_OF) && pdev->dev.of_node) at91udc_of_init(udc, pdev->dev.of_node);
at91udc_of_init(udc, pdev->dev.of_node);
else
memcpy(&udc->board, dev_get_platdata(dev),
sizeof(struct at91_udc_data));
udc->pdev = pdev; udc->pdev = pdev;
udc->enabled = 0; udc->enabled = 0;
spin_lock_init(&udc->lock); spin_lock_init(&udc->lock);
/* rm9200 needs manual D+ pullup; off by default */ udc->gadget.ops = &at91_udc_ops;
if (cpu_is_at91rm9200()) { udc->gadget.ep0 = &udc->ep[0].ep;
if (!gpio_is_valid(udc->board.pullup_pin)) { udc->gadget.name = driver_name;
DBG("no D+ pullup?\n"); udc->gadget.dev.init_name = "gadget";
retval = -ENODEV;
goto fail0; for (i = 0; i < NUM_ENDPOINTS; i++) {
} ep = &udc->ep[i];
retval = gpio_request(udc->board.pullup_pin, "udc_pullup"); ep->ep.name = ep_names[i];
if (retval) { ep->ep.ops = &at91_ep_ops;
DBG("D+ pullup is busy\n"); ep->udc = udc;
goto fail0; ep->int_mask = BIT(i);
} if (i != 0 && i != 3)
gpio_direction_output(udc->board.pullup_pin, ep->is_pingpong = 1;
udc->board.pullup_active_low);
} }
/* newer chips have more FIFO memory than rm9200 */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
if (cpu_is_at91sam9260() || cpu_is_at91sam9g20()) { udc->udp_baseaddr = devm_ioremap_resource(dev, res);
udc->ep[0].maxpacket = 64; if (IS_ERR(udc->udp_baseaddr))
udc->ep[3].maxpacket = 64; return PTR_ERR(udc->udp_baseaddr);
udc->ep[4].maxpacket = 512;
udc->ep[5].maxpacket = 512;
} else if (cpu_is_at91sam9261() || cpu_is_at91sam9g10()) {
udc->ep[3].maxpacket = 64;
} else if (cpu_is_at91sam9263()) {
udc->ep[0].maxpacket = 64;
udc->ep[3].maxpacket = 64;
}
udc->udp_baseaddr = ioremap(res->start, resource_size(res)); if (udc->caps && udc->caps->init) {
if (!udc->udp_baseaddr) { retval = udc->caps->init(udc);
retval = -ENOMEM; if (retval)
goto fail0a; return retval;
} }
udc_reinit(udc); udc_reinit(udc);
/* get interface and function clocks */ /* get interface and function clocks */
udc->iclk = clk_get(dev, "udc_clk"); udc->iclk = devm_clk_get(dev, "pclk");
udc->fclk = clk_get(dev, "udpck"); if (IS_ERR(udc->iclk))
if (IS_ENABLED(CONFIG_COMMON_CLK)) return PTR_ERR(udc->iclk);
udc->uclk = clk_get(dev, "usb_clk");
if (IS_ERR(udc->iclk) || IS_ERR(udc->fclk) || udc->fclk = devm_clk_get(dev, "hclk");
(IS_ENABLED(CONFIG_COMMON_CLK) && IS_ERR(udc->uclk))) { if (IS_ERR(udc->fclk))
DBG("clocks missing\n"); return PTR_ERR(udc->fclk);
retval = -ENODEV;
goto fail1;
}
/* don't do anything until we have both gadget driver and VBUS */ /* don't do anything until we have both gadget driver and VBUS */
if (IS_ENABLED(CONFIG_COMMON_CLK)) { clk_set_rate(udc->fclk, 48000000);
clk_set_rate(udc->uclk, 48000000);
retval = clk_prepare(udc->uclk);
if (retval)
goto fail1;
}
retval = clk_prepare(udc->fclk); retval = clk_prepare(udc->fclk);
if (retval) if (retval)
goto fail1a; return retval;
retval = clk_prepare_enable(udc->iclk); retval = clk_prepare_enable(udc->iclk);
if (retval) if (retval)
goto fail1b; goto err_unprepare_fclk;
at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS); at91_udp_write(udc, AT91_UDP_TXVC, AT91_UDP_TXVC_TXVDIS);
at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff); at91_udp_write(udc, AT91_UDP_IDR, 0xffffffff);
/* Clear all pending interrupts - UDP may be used by bootloader. */ /* Clear all pending interrupts - UDP may be used by bootloader. */
@ -1812,18 +1878,21 @@ static int at91udc_probe(struct platform_device *pdev)
/* request UDC and maybe VBUS irqs */ /* request UDC and maybe VBUS irqs */
udc->udp_irq = platform_get_irq(pdev, 0); udc->udp_irq = platform_get_irq(pdev, 0);
retval = request_irq(udc->udp_irq, at91_udc_irq, retval = devm_request_irq(dev, udc->udp_irq, at91_udc_irq, 0,
0, driver_name, udc); driver_name, udc);
if (retval < 0) { if (retval) {
DBG("request irq %d failed\n", udc->udp_irq); DBG("request irq %d failed\n", udc->udp_irq);
goto fail1c; goto err_unprepare_iclk;
} }
if (gpio_is_valid(udc->board.vbus_pin)) { if (gpio_is_valid(udc->board.vbus_pin)) {
retval = gpio_request(udc->board.vbus_pin, "udc_vbus"); retval = devm_gpio_request(dev, udc->board.vbus_pin,
if (retval < 0) { "udc_vbus");
if (retval) {
DBG("request vbus pin failed\n"); DBG("request vbus pin failed\n");
goto fail2; goto err_unprepare_iclk;
} }
gpio_direction_input(udc->board.vbus_pin); gpio_direction_input(udc->board.vbus_pin);
/* /*
@ -1840,12 +1909,13 @@ static int at91udc_probe(struct platform_device *pdev)
mod_timer(&udc->vbus_timer, mod_timer(&udc->vbus_timer,
jiffies + VBUS_POLL_TIMEOUT); jiffies + VBUS_POLL_TIMEOUT);
} else { } else {
if (request_irq(gpio_to_irq(udc->board.vbus_pin), retval = devm_request_irq(dev,
at91_vbus_irq, 0, driver_name, udc)) { gpio_to_irq(udc->board.vbus_pin),
at91_vbus_irq, 0, driver_name, udc);
if (retval) {
DBG("request vbus irq %d failed\n", DBG("request vbus irq %d failed\n",
udc->board.vbus_pin); udc->board.vbus_pin);
retval = -EBUSY; goto err_unprepare_iclk;
goto fail3;
} }
} }
} else { } else {
@ -1854,49 +1924,27 @@ static int at91udc_probe(struct platform_device *pdev)
} }
retval = usb_add_gadget_udc(dev, &udc->gadget); retval = usb_add_gadget_udc(dev, &udc->gadget);
if (retval) if (retval)
goto fail4; goto err_unprepare_iclk;
dev_set_drvdata(dev, udc); dev_set_drvdata(dev, udc);
device_init_wakeup(dev, 1); device_init_wakeup(dev, 1);
create_debug_file(udc); create_debug_file(udc);
INFO("%s version %s\n", driver_name, DRIVER_VERSION); INFO("%s version %s\n", driver_name, DRIVER_VERSION);
return 0; return 0;
fail4:
if (gpio_is_valid(udc->board.vbus_pin) && !udc->board.vbus_polled) err_unprepare_iclk:
free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
fail3:
if (gpio_is_valid(udc->board.vbus_pin))
gpio_free(udc->board.vbus_pin);
fail2:
free_irq(udc->udp_irq, udc);
fail1c:
clk_unprepare(udc->iclk); clk_unprepare(udc->iclk);
fail1b: err_unprepare_fclk:
clk_unprepare(udc->fclk); clk_unprepare(udc->fclk);
fail1a:
if (IS_ENABLED(CONFIG_COMMON_CLK))
clk_unprepare(udc->uclk);
fail1:
if (IS_ENABLED(CONFIG_COMMON_CLK) && !IS_ERR(udc->uclk))
clk_put(udc->uclk);
if (!IS_ERR(udc->fclk))
clk_put(udc->fclk);
if (!IS_ERR(udc->iclk))
clk_put(udc->iclk);
iounmap(udc->udp_baseaddr);
fail0a:
if (cpu_is_at91rm9200())
gpio_free(udc->board.pullup_pin);
fail0:
release_mem_region(res->start, resource_size(res));
DBG("%s probe failed, %d\n", driver_name, retval); DBG("%s probe failed, %d\n", driver_name, retval);
return retval; return retval;
} }
static int __exit at91udc_remove(struct platform_device *pdev) static int __exit at91udc_remove(struct platform_device *pdev)
{ {
struct at91_udc *udc = platform_get_drvdata(pdev); struct at91_udc *udc = platform_get_drvdata(pdev);
struct resource *res;
unsigned long flags; unsigned long flags;
DBG("remove\n"); DBG("remove\n");
@ -1911,29 +1959,9 @@ static int __exit at91udc_remove(struct platform_device *pdev)
device_init_wakeup(&pdev->dev, 0); device_init_wakeup(&pdev->dev, 0);
remove_debug_file(udc); remove_debug_file(udc);
if (gpio_is_valid(udc->board.vbus_pin)) {
free_irq(gpio_to_irq(udc->board.vbus_pin), udc);
gpio_free(udc->board.vbus_pin);
}
free_irq(udc->udp_irq, udc);
iounmap(udc->udp_baseaddr);
if (cpu_is_at91rm9200())
gpio_free(udc->board.pullup_pin);
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
release_mem_region(res->start, resource_size(res));
if (IS_ENABLED(CONFIG_COMMON_CLK))
clk_unprepare(udc->uclk);
clk_unprepare(udc->fclk); clk_unprepare(udc->fclk);
clk_unprepare(udc->iclk); clk_unprepare(udc->iclk);
clk_put(udc->iclk);
clk_put(udc->fclk);
if (IS_ENABLED(CONFIG_COMMON_CLK))
clk_put(udc->uclk);
return 0; return 0;
} }
@ -1989,15 +2017,6 @@ static int at91udc_resume(struct platform_device *pdev)
#define at91udc_resume NULL #define at91udc_resume NULL
#endif #endif
#if defined(CONFIG_OF)
static const struct of_device_id at91_udc_dt_ids[] = {
{ .compatible = "atmel,at91rm9200-udc" },
{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, at91_udc_dt_ids);
#endif
static struct platform_driver at91_udc_driver = { static struct platform_driver at91_udc_driver = {
.remove = __exit_p(at91udc_remove), .remove = __exit_p(at91udc_remove),
.shutdown = at91udc_shutdown, .shutdown = at91udc_shutdown,
@ -2005,7 +2024,7 @@ static struct platform_driver at91_udc_driver = {
.resume = at91udc_resume, .resume = at91udc_resume,
.driver = { .driver = {
.name = (char *) driver_name, .name = (char *) driver_name,
.of_match_table = of_match_ptr(at91_udc_dt_ids), .of_match_table = at91_udc_dt_ids,
}, },
}; };

View File

@ -107,6 +107,11 @@ struct at91_ep {
unsigned fifo_bank:1; unsigned fifo_bank:1;
}; };
struct at91_udc_caps {
int (*init)(struct at91_udc *udc);
void (*pullup)(struct at91_udc *udc, int is_on);
};
/* /*
* driver is non-SMP, and just blocks IRQs whenever it needs * driver is non-SMP, and just blocks IRQs whenever it needs
* access protection for chip registers or driver state * access protection for chip registers or driver state
@ -115,6 +120,7 @@ struct at91_udc {
struct usb_gadget gadget; struct usb_gadget gadget;
struct at91_ep ep[NUM_ENDPOINTS]; struct at91_ep ep[NUM_ENDPOINTS];
struct usb_gadget_driver *driver; struct usb_gadget_driver *driver;
const struct at91_udc_caps *caps;
unsigned vbus:1; unsigned vbus:1;
unsigned enabled:1; unsigned enabled:1;
unsigned clocked:1; unsigned clocked:1;
@ -125,7 +131,7 @@ struct at91_udc {
unsigned active_suspend:1; unsigned active_suspend:1;
u8 addr; u8 addr;
struct at91_udc_data board; struct at91_udc_data board;
struct clk *iclk, *fclk, *uclk; struct clk *iclk, *fclk;
struct platform_device *pdev; struct platform_device *pdev;
struct proc_dir_entry *pde; struct proc_dir_entry *pde;
void __iomem *udp_baseaddr; void __iomem *udp_baseaddr;
@ -133,6 +139,7 @@ struct at91_udc {
spinlock_t lock; spinlock_t lock;
struct timer_list vbus_timer; struct timer_list vbus_timer;
struct work_struct vbus_timer_work; struct work_struct vbus_timer_work;
struct regmap *matrix;
}; };
static inline struct at91_udc *to_udc(struct usb_gadget *g) static inline struct at91_udc *to_udc(struct usb_gadget *g)

View File

@ -0,0 +1,79 @@
/*
* Copyright 2014 Ulrich Hecht
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef __DT_BINDINGS_CLOCK_SH73A0_H__
#define __DT_BINDINGS_CLOCK_SH73A0_H__
/* CPG */
#define SH73A0_CLK_MAIN 0
#define SH73A0_CLK_PLL0 1
#define SH73A0_CLK_PLL1 2
#define SH73A0_CLK_PLL2 3
#define SH73A0_CLK_PLL3 4
#define SH73A0_CLK_DSI0PHY 5
#define SH73A0_CLK_DSI1PHY 6
#define SH73A0_CLK_ZG 7
#define SH73A0_CLK_M3 8
#define SH73A0_CLK_B 9
#define SH73A0_CLK_M1 10
#define SH73A0_CLK_M2 11
#define SH73A0_CLK_Z 12
#define SH73A0_CLK_ZX 13
#define SH73A0_CLK_HP 14
/* MSTP0 */
#define SH73A0_CLK_IIC2 1
/* MSTP1 */
#define SH73A0_CLK_CEU1 29
#define SH73A0_CLK_CSI2_RX1 28
#define SH73A0_CLK_CEU0 27
#define SH73A0_CLK_CSI2_RX0 26
#define SH73A0_CLK_TMU0 25
#define SH73A0_CLK_DSITX0 18
#define SH73A0_CLK_IIC0 16
#define SH73A0_CLK_SGX 12
#define SH73A0_CLK_LCDC0 0
/* MSTP2 */
#define SH73A0_CLK_SCIFA7 19
#define SH73A0_CLK_SY_DMAC 18
#define SH73A0_CLK_MP_DMAC 17
#define SH73A0_CLK_SCIFA5 7
#define SH73A0_CLK_SCIFB 6
#define SH73A0_CLK_SCIFA0 4
#define SH73A0_CLK_SCIFA1 3
#define SH73A0_CLK_SCIFA2 2
#define SH73A0_CLK_SCIFA3 1
#define SH73A0_CLK_SCIFA4 0
/* MSTP3 */
#define SH73A0_CLK_SCIFA6 31
#define SH73A0_CLK_CMT1 29
#define SH73A0_CLK_FSI 28
#define SH73A0_CLK_IRDA 25
#define SH73A0_CLK_IIC1 23
#define SH73A0_CLK_USB 22
#define SH73A0_CLK_FLCTL 15
#define SH73A0_CLK_SDHI0 14
#define SH73A0_CLK_SDHI1 13
#define SH73A0_CLK_MMCIF0 12
#define SH73A0_CLK_SDHI2 11
#define SH73A0_CLK_TPU0 4
#define SH73A0_CLK_TPU1 3
#define SH73A0_CLK_TPU2 2
#define SH73A0_CLK_TPU3 1
#define SH73A0_CLK_TPU4 0
/* MSTP4 */
#define SH73A0_CLK_IIC3 11
#define SH73A0_CLK_IIC4 10
#define SH73A0_CLK_KEYSC 3
#endif

View File

@ -0,0 +1,117 @@
/*
* Copyright (C) 2014 Atmel Corporation.
*
* Memory Controllers (MATRIX, EBI) - System peripherals registers.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*/
#ifndef _LINUX_MFD_SYSCON_ATMEL_MATRIX_H
#define _LINUX_MFD_SYSCON_ATMEL_MATRIX_H
#define AT91SAM9260_MATRIX_MCFG 0x00
#define AT91SAM9260_MATRIX_SCFG 0x40
#define AT91SAM9260_MATRIX_PRS 0x80
#define AT91SAM9260_MATRIX_MRCR 0x100
#define AT91SAM9260_MATRIX_EBICSA 0x11c
#define AT91SAM9261_MATRIX_MRCR 0x0
#define AT91SAM9261_MATRIX_SCFG 0x4
#define AT91SAM9261_MATRIX_TCR 0x24
#define AT91SAM9261_MATRIX_EBICSA 0x30
#define AT91SAM9261_MATRIX_USBPUCR 0x34
#define AT91SAM9263_MATRIX_MCFG 0x00
#define AT91SAM9263_MATRIX_SCFG 0x40
#define AT91SAM9263_MATRIX_PRS 0x80
#define AT91SAM9263_MATRIX_MRCR 0x100
#define AT91SAM9263_MATRIX_TCR 0x114
#define AT91SAM9263_MATRIX_EBI0CSA 0x120
#define AT91SAM9263_MATRIX_EBI1CSA 0x124
#define AT91SAM9RL_MATRIX_MCFG 0x00
#define AT91SAM9RL_MATRIX_SCFG 0x40
#define AT91SAM9RL_MATRIX_PRS 0x80
#define AT91SAM9RL_MATRIX_MRCR 0x100
#define AT91SAM9RL_MATRIX_TCR 0x114
#define AT91SAM9RL_MATRIX_EBICSA 0x120
#define AT91SAM9G45_MATRIX_MCFG 0x00
#define AT91SAM9G45_MATRIX_SCFG 0x40
#define AT91SAM9G45_MATRIX_PRS 0x80
#define AT91SAM9G45_MATRIX_MRCR 0x100
#define AT91SAM9G45_MATRIX_TCR 0x110
#define AT91SAM9G45_MATRIX_DDRMPR 0x118
#define AT91SAM9G45_MATRIX_EBICSA 0x128
#define AT91SAM9N12_MATRIX_MCFG 0x00
#define AT91SAM9N12_MATRIX_SCFG 0x40
#define AT91SAM9N12_MATRIX_PRS 0x80
#define AT91SAM9N12_MATRIX_MRCR 0x100
#define AT91SAM9N12_MATRIX_EBICSA 0x118
#define AT91SAM9X5_MATRIX_MCFG 0x00
#define AT91SAM9X5_MATRIX_SCFG 0x40
#define AT91SAM9X5_MATRIX_PRS 0x80
#define AT91SAM9X5_MATRIX_MRCR 0x100
#define AT91SAM9X5_MATRIX_EBICSA 0x120
#define SAMA5D3_MATRIX_MCFG 0x00
#define SAMA5D3_MATRIX_SCFG 0x40
#define SAMA5D3_MATRIX_PRS 0x80
#define SAMA5D3_MATRIX_MRCR 0x100
#define AT91_MATRIX_MCFG(o, x) ((o) + ((x) * 0x4))
#define AT91_MATRIX_ULBT GENMASK(2, 0)
#define AT91_MATRIX_ULBT_INFINITE (0 << 0)
#define AT91_MATRIX_ULBT_SINGLE (1 << 0)
#define AT91_MATRIX_ULBT_FOUR (2 << 0)
#define AT91_MATRIX_ULBT_EIGHT (3 << 0)
#define AT91_MATRIX_ULBT_SIXTEEN (4 << 0)
#define AT91_MATRIX_SCFG(o, x) ((o) + ((x) * 0x4))
#define AT91_MATRIX_SLOT_CYCLE GENMASK(7, 0)
#define AT91_MATRIX_DEFMSTR_TYPE GENMASK(17, 16)
#define AT91_MATRIX_DEFMSTR_TYPE_NONE (0 << 16)
#define AT91_MATRIX_DEFMSTR_TYPE_LAST (1 << 16)
#define AT91_MATRIX_DEFMSTR_TYPE_FIXED (2 << 16)
#define AT91_MATRIX_FIXED_DEFMSTR GENMASK(20, 18)
#define AT91_MATRIX_ARBT GENMASK(25, 24)
#define AT91_MATRIX_ARBT_ROUND_ROBIN (0 << 24)
#define AT91_MATRIX_ARBT_FIXED_PRIORITY (1 << 24)
#define AT91_MATRIX_ITCM_SIZE GENMASK(3, 0)
#define AT91_MATRIX_ITCM_0 (0 << 0)
#define AT91_MATRIX_ITCM_16 (5 << 0)
#define AT91_MATRIX_ITCM_32 (6 << 0)
#define AT91_MATRIX_ITCM_64 (7 << 0)
#define AT91_MATRIX_DTCM_SIZE GENMASK(7, 4)
#define AT91_MATRIX_DTCM_0 (0 << 4)
#define AT91_MATRIX_DTCM_16 (5 << 4)
#define AT91_MATRIX_DTCM_32 (6 << 4)
#define AT91_MATRIX_DTCM_64 (7 << 4)
#define AT91_MATRIX_PRAS(o, x) ((o) + ((x) * 0x8))
#define AT91_MATRIX_PRBS(o, x) ((o) + ((x) * 0x8) + 0x4)
#define AT91_MATRIX_MPR(x) GENMASK(((x) * 0x4) + 1, ((x) * 0x4))
#define AT91_MATRIX_RCB(x) BIT(x)
#define AT91_MATRIX_CSA(cs, val) (val << (cs))
#define AT91_MATRIX_DBPUC BIT(8)
#define AT91_MATRIX_DBPDC BIT(9)
#define AT91_MATRIX_VDDIOMSEL BIT(16)
#define AT91_MATRIX_VDDIOMSEL_1_8V (0 << 16)
#define AT91_MATRIX_VDDIOMSEL_3_3V (1 << 16)
#define AT91_MATRIX_EBI_IOSR BIT(17)
#define AT91_MATRIX_DDR_IOSR BIT(18)
#define AT91_MATRIX_NFD0_SELECT BIT(24)
#define AT91_MATRIX_DDR_MP_EN BIT(25)
#define AT91_MATRIX_EBI_NUM_CS 8
#define AT91_MATRIX_USBPUCR_PUON BIT(30)
#endif /* _LINUX_MFD_SYSCON_ATMEL_MATRIX_H */

View File

@ -0,0 +1,173 @@
/*
* Atmel SMC (Static Memory Controller) register offsets and bit definitions.
*
* Copyright (C) 2014 Atmel
* Copyright (C) 2014 Free Electrons
*
* Author: Boris Brezillon <boris.brezillon@free-electrons.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.
*/
#ifndef _LINUX_MFD_SYSCON_ATMEL_SMC_H_
#define _LINUX_MFD_SYSCON_ATMEL_SMC_H_
#include <linux/kernel.h>
#include <linux/regmap.h>
#define AT91SAM9_SMC_GENERIC 0x00
#define AT91SAM9_SMC_GENERIC_BLK_SZ 0x10
#define SAMA5_SMC_GENERIC 0x600
#define SAMA5_SMC_GENERIC_BLK_SZ 0x14
#define AT91SAM9_SMC_SETUP(o) ((o) + 0x00)
#define AT91SAM9_SMC_NWESETUP(x) (x)
#define AT91SAM9_SMC_NCS_WRSETUP(x) ((x) << 8)
#define AT91SAM9_SMC_NRDSETUP(x) ((x) << 16)
#define AT91SAM9_SMC_NCS_NRDSETUP(x) ((x) << 24)
#define AT91SAM9_SMC_PULSE(o) ((o) + 0x04)
#define AT91SAM9_SMC_NWEPULSE(x) (x)
#define AT91SAM9_SMC_NCS_WRPULSE(x) ((x) << 8)
#define AT91SAM9_SMC_NRDPULSE(x) ((x) << 16)
#define AT91SAM9_SMC_NCS_NRDPULSE(x) ((x) << 24)
#define AT91SAM9_SMC_CYCLE(o) ((o) + 0x08)
#define AT91SAM9_SMC_NWECYCLE(x) (x)
#define AT91SAM9_SMC_NRDCYCLE(x) ((x) << 16)
#define AT91SAM9_SMC_MODE(o) ((o) + 0x0c)
#define SAMA5_SMC_MODE(o) ((o) + 0x10)
#define AT91_SMC_READMODE BIT(0)
#define AT91_SMC_READMODE_NCS (0 << 0)
#define AT91_SMC_READMODE_NRD (1 << 0)
#define AT91_SMC_WRITEMODE BIT(1)
#define AT91_SMC_WRITEMODE_NCS (0 << 1)
#define AT91_SMC_WRITEMODE_NWE (1 << 1)
#define AT91_SMC_EXNWMODE GENMASK(5, 4)
#define AT91_SMC_EXNWMODE_DISABLE (0 << 4)
#define AT91_SMC_EXNWMODE_FROZEN (2 << 4)
#define AT91_SMC_EXNWMODE_READY (3 << 4)
#define AT91_SMC_BAT BIT(8)
#define AT91_SMC_BAT_SELECT (0 << 8)
#define AT91_SMC_BAT_WRITE (1 << 8)
#define AT91_SMC_DBW GENMASK(13, 12)
#define AT91_SMC_DBW_8 (0 << 12)
#define AT91_SMC_DBW_16 (1 << 12)
#define AT91_SMC_DBW_32 (2 << 12)
#define AT91_SMC_TDF GENMASK(19, 16)
#define AT91_SMC_TDF_(x) ((((x) - 1) << 16) & AT91_SMC_TDF)
#define AT91_SMC_TDF_MAX 16
#define AT91_SMC_TDFMODE_OPTIMIZED BIT(20)
#define AT91_SMC_PMEN BIT(24)
#define AT91_SMC_PS GENMASK(29, 28)
#define AT91_SMC_PS_4 (0 << 28)
#define AT91_SMC_PS_8 (1 << 28)
#define AT91_SMC_PS_16 (2 << 28)
#define AT91_SMC_PS_32 (3 << 28)
/*
* This function converts a setup timing expressed in nanoseconds into an
* encoded value that can be written in the SMC_SETUP register.
*
* The following formula is described in atmel datasheets (section
* "SMC Setup Register"):
*
* setup length = (128* SETUP[5] + SETUP[4:0])
*
* where setup length is the timing expressed in cycles.
*/
static inline u32 at91sam9_smc_setup_ns_to_cycles(unsigned int clk_rate,
u32 timing_ns)
{
u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
u32 coded_cycles = 0;
u32 cycles;
cycles = DIV_ROUND_UP(timing_ns, clk_period);
if (cycles / 32) {
coded_cycles |= 1 << 5;
if (cycles < 128)
cycles = 0;
}
coded_cycles |= cycles % 32;
return coded_cycles;
}
/*
* This function converts a pulse timing expressed in nanoseconds into an
* encoded value that can be written in the SMC_PULSE register.
*
* The following formula is described in atmel datasheets (section
* "SMC Pulse Register"):
*
* pulse length = (256* PULSE[6] + PULSE[5:0])
*
* where pulse length is the timing expressed in cycles.
*/
static inline u32 at91sam9_smc_pulse_ns_to_cycles(unsigned int clk_rate,
u32 timing_ns)
{
u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
u32 coded_cycles = 0;
u32 cycles;
cycles = DIV_ROUND_UP(timing_ns, clk_period);
if (cycles / 64) {
coded_cycles |= 1 << 6;
if (cycles < 256)
cycles = 0;
}
coded_cycles |= cycles % 64;
return coded_cycles;
}
/*
* This function converts a cycle timing expressed in nanoseconds into an
* encoded value that can be written in the SMC_CYCLE register.
*
* The following formula is described in atmel datasheets (section
* "SMC Cycle Register"):
*
* cycle length = (CYCLE[8:7]*256 + CYCLE[6:0])
*
* where cycle length is the timing expressed in cycles.
*/
static inline u32 at91sam9_smc_cycle_ns_to_cycles(unsigned int clk_rate,
u32 timing_ns)
{
u32 clk_period = DIV_ROUND_UP(NSEC_PER_SEC, clk_rate);
u32 coded_cycles = 0;
u32 cycles;
cycles = DIV_ROUND_UP(timing_ns, clk_period);
if (cycles / 128) {
coded_cycles = cycles / 256;
cycles %= 256;
if (cycles >= 128) {
coded_cycles++;
cycles = 0;
}
if (coded_cycles > 0x3) {
coded_cycles = 0x3;
cycles = 0x7f;
}
coded_cycles <<= 7;
}
coded_cycles |= cycles % 128;
return coded_cycles;
}
#endif /* _LINUX_MFD_SYSCON_ATMEL_SMC_H_ */

View File

@ -0,0 +1,20 @@
/*
* Copyright (c) 2014 Samsung Electronics Co., Ltd.
* http://www.samsung.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.
*/
#ifndef __CPUIDLE_EXYNOS_H
#define __CPUIDLE_EXYNOS_H
struct cpuidle_exynos_data {
int (*cpu0_enter_aftr)(void);
int (*cpu1_powerdown)(void);
void (*pre_enter_aftr)(void);
void (*post_enter_aftr)(void);
};
#endif