diff options
Diffstat (limited to 'arch')
43 files changed, 757 insertions, 62 deletions
diff --git a/arch/powerpc/Kconfig b/arch/powerpc/Kconfig index 587da5e0990f..63c9cafda9c4 100644 --- a/arch/powerpc/Kconfig +++ b/arch/powerpc/Kconfig | |||
| @@ -42,6 +42,9 @@ config GENERIC_HARDIRQS | |||
| 42 | bool | 42 | bool |
| 43 | default y | 43 | default y |
| 44 | 44 | ||
| 45 | config HAVE_GET_USER_PAGES_FAST | ||
| 46 | def_bool PPC64 | ||
| 47 | |||
| 45 | config HAVE_SETUP_PER_CPU_AREA | 48 | config HAVE_SETUP_PER_CPU_AREA |
| 46 | def_bool PPC64 | 49 | def_bool PPC64 |
| 47 | 50 | ||
diff --git a/arch/powerpc/boot/dts/mpc832x_mds.dts b/arch/powerpc/boot/dts/mpc832x_mds.dts index 7345743d3d96..fbc930410ff6 100644 --- a/arch/powerpc/boot/dts/mpc832x_mds.dts +++ b/arch/powerpc/boot/dts/mpc832x_mds.dts | |||
| @@ -68,6 +68,7 @@ | |||
| 68 | #address-cells = <1>; | 68 | #address-cells = <1>; |
| 69 | #size-cells = <1>; | 69 | #size-cells = <1>; |
| 70 | device_type = "soc"; | 70 | device_type = "soc"; |
| 71 | compatible = "simple-bus"; | ||
| 71 | ranges = <0x0 0xe0000000 0x00100000>; | 72 | ranges = <0x0 0xe0000000 0x00100000>; |
| 72 | reg = <0xe0000000 0x00000200>; | 73 | reg = <0xe0000000 0x00000200>; |
| 73 | bus-frequency = <132000000>; | 74 | bus-frequency = <132000000>; |
diff --git a/arch/powerpc/boot/dts/mpc832x_rdb.dts b/arch/powerpc/boot/dts/mpc832x_rdb.dts index e74c045a0f8c..b157d1885a28 100644 --- a/arch/powerpc/boot/dts/mpc832x_rdb.dts +++ b/arch/powerpc/boot/dts/mpc832x_rdb.dts | |||
| @@ -51,6 +51,7 @@ | |||
| 51 | #address-cells = <1>; | 51 | #address-cells = <1>; |
| 52 | #size-cells = <1>; | 52 | #size-cells = <1>; |
| 53 | device_type = "soc"; | 53 | device_type = "soc"; |
| 54 | compatible = "simple-bus"; | ||
| 54 | ranges = <0x0 0xe0000000 0x00100000>; | 55 | ranges = <0x0 0xe0000000 0x00100000>; |
| 55 | reg = <0xe0000000 0x00000200>; | 56 | reg = <0xe0000000 0x00000200>; |
| 56 | bus-frequency = <0>; | 57 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8349emitx.dts b/arch/powerpc/boot/dts/mpc8349emitx.dts index 8dfab5662585..700e076ef3f5 100644 --- a/arch/powerpc/boot/dts/mpc8349emitx.dts +++ b/arch/powerpc/boot/dts/mpc8349emitx.dts | |||
| @@ -52,6 +52,7 @@ | |||
| 52 | #address-cells = <1>; | 52 | #address-cells = <1>; |
| 53 | #size-cells = <1>; | 53 | #size-cells = <1>; |
| 54 | device_type = "soc"; | 54 | device_type = "soc"; |
| 55 | compatible = "simple-bus"; | ||
| 55 | ranges = <0x0 0xe0000000 0x00100000>; | 56 | ranges = <0x0 0xe0000000 0x00100000>; |
| 56 | reg = <0xe0000000 0x00000200>; | 57 | reg = <0xe0000000 0x00000200>; |
| 57 | bus-frequency = <0>; // from bootloader | 58 | bus-frequency = <0>; // from bootloader |
diff --git a/arch/powerpc/boot/dts/mpc8349emitxgp.dts b/arch/powerpc/boot/dts/mpc8349emitxgp.dts index 49ca3497eefb..cdd3063258ea 100644 --- a/arch/powerpc/boot/dts/mpc8349emitxgp.dts +++ b/arch/powerpc/boot/dts/mpc8349emitxgp.dts | |||
| @@ -50,6 +50,7 @@ | |||
| 50 | #address-cells = <1>; | 50 | #address-cells = <1>; |
| 51 | #size-cells = <1>; | 51 | #size-cells = <1>; |
| 52 | device_type = "soc"; | 52 | device_type = "soc"; |
| 53 | compatible = "simple-bus"; | ||
| 53 | ranges = <0x0 0xe0000000 0x00100000>; | 54 | ranges = <0x0 0xe0000000 0x00100000>; |
| 54 | reg = <0xe0000000 0x00000200>; | 55 | reg = <0xe0000000 0x00000200>; |
| 55 | bus-frequency = <0>; // from bootloader | 56 | bus-frequency = <0>; // from bootloader |
diff --git a/arch/powerpc/boot/dts/mpc834x_mds.dts b/arch/powerpc/boot/dts/mpc834x_mds.dts index ba586cb7afbb..783241c00240 100644 --- a/arch/powerpc/boot/dts/mpc834x_mds.dts +++ b/arch/powerpc/boot/dts/mpc834x_mds.dts | |||
| @@ -57,6 +57,7 @@ | |||
| 57 | #address-cells = <1>; | 57 | #address-cells = <1>; |
| 58 | #size-cells = <1>; | 58 | #size-cells = <1>; |
| 59 | device_type = "soc"; | 59 | device_type = "soc"; |
| 60 | compatible = "simple-bus"; | ||
| 60 | ranges = <0x0 0xe0000000 0x00100000>; | 61 | ranges = <0x0 0xe0000000 0x00100000>; |
| 61 | reg = <0xe0000000 0x00000200>; | 62 | reg = <0xe0000000 0x00000200>; |
| 62 | bus-frequency = <0>; | 63 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc836x_mds.dts b/arch/powerpc/boot/dts/mpc836x_mds.dts index 3701dae1ee02..a3b76a709951 100644 --- a/arch/powerpc/boot/dts/mpc836x_mds.dts +++ b/arch/powerpc/boot/dts/mpc836x_mds.dts | |||
| @@ -61,6 +61,7 @@ | |||
| 61 | #address-cells = <1>; | 61 | #address-cells = <1>; |
| 62 | #size-cells = <1>; | 62 | #size-cells = <1>; |
| 63 | device_type = "soc"; | 63 | device_type = "soc"; |
| 64 | compatible = "simple-bus"; | ||
| 64 | ranges = <0x0 0xe0000000 0x00100000>; | 65 | ranges = <0x0 0xe0000000 0x00100000>; |
| 65 | reg = <0xe0000000 0x00000200>; | 66 | reg = <0xe0000000 0x00000200>; |
| 66 | bus-frequency = <264000000>; | 67 | bus-frequency = <264000000>; |
diff --git a/arch/powerpc/boot/dts/mpc836x_rdk.dts b/arch/powerpc/boot/dts/mpc836x_rdk.dts index 8acd1d6577f2..89c9202f8bd7 100644 --- a/arch/powerpc/boot/dts/mpc836x_rdk.dts +++ b/arch/powerpc/boot/dts/mpc836x_rdk.dts | |||
| @@ -149,18 +149,14 @@ | |||
| 149 | }; | 149 | }; |
| 150 | 150 | ||
| 151 | crypto@30000 { | 151 | crypto@30000 { |
| 152 | compatible = "fsl,sec2-crypto"; | 152 | compatible = "fsl,sec2.0"; |
| 153 | reg = <0x30000 0x10000>; | 153 | reg = <0x30000 0x10000>; |
| 154 | interrupts = <11 8>; | 154 | interrupts = <11 0x8>; |
| 155 | interrupt-parent = <&ipic>; | 155 | interrupt-parent = <&ipic>; |
| 156 | num-channels = <4>; | 156 | fsl,num-channels = <4>; |
| 157 | channel-fifo-len = <24>; | 157 | fsl,channel-fifo-len = <24>; |
| 158 | exec-units-mask = <0x7e>; | 158 | fsl,exec-units-mask = <0x7e>; |
| 159 | /* | 159 | fsl,descriptor-types-mask = <0x01010ebf>; |
| 160 | * desc mask is for rev1.x, we need runtime fixup | ||
| 161 | * for >=2.x | ||
| 162 | */ | ||
| 163 | descriptor-types-mask = <0x1010ebf>; | ||
| 164 | }; | 160 | }; |
| 165 | 161 | ||
| 166 | ipic: interrupt-controller@700 { | 162 | ipic: interrupt-controller@700 { |
diff --git a/arch/powerpc/boot/dts/mpc8377_mds.dts b/arch/powerpc/boot/dts/mpc8377_mds.dts index 0a700cb5f611..432782b6d20a 100644 --- a/arch/powerpc/boot/dts/mpc8377_mds.dts +++ b/arch/powerpc/boot/dts/mpc8377_mds.dts | |||
| @@ -117,6 +117,7 @@ | |||
| 117 | #address-cells = <1>; | 117 | #address-cells = <1>; |
| 118 | #size-cells = <1>; | 118 | #size-cells = <1>; |
| 119 | device_type = "soc"; | 119 | device_type = "soc"; |
| 120 | compatible = "simple-bus"; | ||
| 120 | ranges = <0x0 0xe0000000 0x00100000>; | 121 | ranges = <0x0 0xe0000000 0x00100000>; |
| 121 | reg = <0xe0000000 0x00000200>; | 122 | reg = <0xe0000000 0x00000200>; |
| 122 | bus-frequency = <0>; | 123 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8378_mds.dts b/arch/powerpc/boot/dts/mpc8378_mds.dts index 29c8c76a58f7..ed32c8ddafe3 100644 --- a/arch/powerpc/boot/dts/mpc8378_mds.dts +++ b/arch/powerpc/boot/dts/mpc8378_mds.dts | |||
| @@ -117,6 +117,7 @@ | |||
| 117 | #address-cells = <1>; | 117 | #address-cells = <1>; |
| 118 | #size-cells = <1>; | 118 | #size-cells = <1>; |
| 119 | device_type = "soc"; | 119 | device_type = "soc"; |
| 120 | compatible = "simple-bus"; | ||
| 120 | ranges = <0x0 0xe0000000 0x00100000>; | 121 | ranges = <0x0 0xe0000000 0x00100000>; |
| 121 | reg = <0xe0000000 0x00000200>; | 122 | reg = <0xe0000000 0x00000200>; |
| 122 | bus-frequency = <0>; | 123 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8379_mds.dts b/arch/powerpc/boot/dts/mpc8379_mds.dts index d641a8985ea3..f4db9ed4a301 100644 --- a/arch/powerpc/boot/dts/mpc8379_mds.dts +++ b/arch/powerpc/boot/dts/mpc8379_mds.dts | |||
| @@ -117,6 +117,7 @@ | |||
| 117 | #address-cells = <1>; | 117 | #address-cells = <1>; |
| 118 | #size-cells = <1>; | 118 | #size-cells = <1>; |
| 119 | device_type = "soc"; | 119 | device_type = "soc"; |
| 120 | compatible = "simple-bus"; | ||
| 120 | ranges = <0x0 0xe0000000 0x00100000>; | 121 | ranges = <0x0 0xe0000000 0x00100000>; |
| 121 | reg = <0xe0000000 0x00000200>; | 122 | reg = <0xe0000000 0x00000200>; |
| 122 | bus-frequency = <0>; | 123 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8536ds.dts b/arch/powerpc/boot/dts/mpc8536ds.dts index 02cfa24a1695..1505d6855eff 100644 --- a/arch/powerpc/boot/dts/mpc8536ds.dts +++ b/arch/powerpc/boot/dts/mpc8536ds.dts | |||
| @@ -49,6 +49,7 @@ | |||
| 49 | #address-cells = <1>; | 49 | #address-cells = <1>; |
| 50 | #size-cells = <1>; | 50 | #size-cells = <1>; |
| 51 | device_type = "soc"; | 51 | device_type = "soc"; |
| 52 | compatible = "simple-bus"; | ||
| 52 | ranges = <0x0 0xffe00000 0x100000>; | 53 | ranges = <0x0 0xffe00000 0x100000>; |
| 53 | reg = <0xffe00000 0x1000>; | 54 | reg = <0xffe00000 0x1000>; |
| 54 | bus-frequency = <0>; // Filled out by uboot. | 55 | bus-frequency = <0>; // Filled out by uboot. |
diff --git a/arch/powerpc/boot/dts/mpc8540ads.dts b/arch/powerpc/boot/dts/mpc8540ads.dts index f2273a872b11..9568bfaff8f7 100644 --- a/arch/powerpc/boot/dts/mpc8540ads.dts +++ b/arch/powerpc/boot/dts/mpc8540ads.dts | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #address-cells = <1>; | 53 | #address-cells = <1>; |
| 54 | #size-cells = <1>; | 54 | #size-cells = <1>; |
| 55 | device_type = "soc"; | 55 | device_type = "soc"; |
| 56 | compatible = "simple-bus"; | ||
| 56 | ranges = <0x0 0xe0000000 0x100000>; | 57 | ranges = <0x0 0xe0000000 0x100000>; |
| 57 | reg = <0xe0000000 0x100000>; // CCSRBAR 1M | 58 | reg = <0xe0000000 0x100000>; // CCSRBAR 1M |
| 58 | bus-frequency = <0>; | 59 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8541cds.dts b/arch/powerpc/boot/dts/mpc8541cds.dts index c4469f19ff82..6480f4fd96e0 100644 --- a/arch/powerpc/boot/dts/mpc8541cds.dts +++ b/arch/powerpc/boot/dts/mpc8541cds.dts | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #address-cells = <1>; | 53 | #address-cells = <1>; |
| 54 | #size-cells = <1>; | 54 | #size-cells = <1>; |
| 55 | device_type = "soc"; | 55 | device_type = "soc"; |
| 56 | compatible = "simple-bus"; | ||
| 56 | ranges = <0x0 0xe0000000 0x100000>; | 57 | ranges = <0x0 0xe0000000 0x100000>; |
| 57 | reg = <0xe0000000 0x1000>; // CCSRBAR 1M | 58 | reg = <0xe0000000 0x1000>; // CCSRBAR 1M |
| 58 | bus-frequency = <0>; | 59 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8544ds.dts b/arch/powerpc/boot/dts/mpc8544ds.dts index 7d3829d3495e..f1fb20737e3e 100644 --- a/arch/powerpc/boot/dts/mpc8544ds.dts +++ b/arch/powerpc/boot/dts/mpc8544ds.dts | |||
| @@ -54,6 +54,7 @@ | |||
| 54 | #address-cells = <1>; | 54 | #address-cells = <1>; |
| 55 | #size-cells = <1>; | 55 | #size-cells = <1>; |
| 56 | device_type = "soc"; | 56 | device_type = "soc"; |
| 57 | compatible = "simple-bus"; | ||
| 57 | 58 | ||
| 58 | ranges = <0x0 0xe0000000 0x100000>; | 59 | ranges = <0x0 0xe0000000 0x100000>; |
| 59 | reg = <0xe0000000 0x1000>; // CCSRBAR 1M | 60 | reg = <0xe0000000 0x1000>; // CCSRBAR 1M |
diff --git a/arch/powerpc/boot/dts/mpc8548cds.dts b/arch/powerpc/boot/dts/mpc8548cds.dts index d84466bb7eca..431b496270dc 100644 --- a/arch/powerpc/boot/dts/mpc8548cds.dts +++ b/arch/powerpc/boot/dts/mpc8548cds.dts | |||
| @@ -58,6 +58,7 @@ | |||
| 58 | #address-cells = <1>; | 58 | #address-cells = <1>; |
| 59 | #size-cells = <1>; | 59 | #size-cells = <1>; |
| 60 | device_type = "soc"; | 60 | device_type = "soc"; |
| 61 | compatible = "simple-bus"; | ||
| 61 | ranges = <0x0 0xe0000000 0x100000>; | 62 | ranges = <0x0 0xe0000000 0x100000>; |
| 62 | reg = <0xe0000000 0x1000>; // CCSRBAR | 63 | reg = <0xe0000000 0x1000>; // CCSRBAR |
| 63 | bus-frequency = <0>; | 64 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8555cds.dts b/arch/powerpc/boot/dts/mpc8555cds.dts index e03a78006283..d833a5c4f476 100644 --- a/arch/powerpc/boot/dts/mpc8555cds.dts +++ b/arch/powerpc/boot/dts/mpc8555cds.dts | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #address-cells = <1>; | 53 | #address-cells = <1>; |
| 54 | #size-cells = <1>; | 54 | #size-cells = <1>; |
| 55 | device_type = "soc"; | 55 | device_type = "soc"; |
| 56 | compatible = "simple-bus"; | ||
| 56 | ranges = <0x0 0xe0000000 0x100000>; | 57 | ranges = <0x0 0xe0000000 0x100000>; |
| 57 | reg = <0xe0000000 0x1000>; // CCSRBAR 1M | 58 | reg = <0xe0000000 0x1000>; // CCSRBAR 1M |
| 58 | bus-frequency = <0>; | 59 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8560ads.dts b/arch/powerpc/boot/dts/mpc8560ads.dts index ba8159de040b..4d1f2f284094 100644 --- a/arch/powerpc/boot/dts/mpc8560ads.dts +++ b/arch/powerpc/boot/dts/mpc8560ads.dts | |||
| @@ -53,6 +53,7 @@ | |||
| 53 | #address-cells = <1>; | 53 | #address-cells = <1>; |
| 54 | #size-cells = <1>; | 54 | #size-cells = <1>; |
| 55 | device_type = "soc"; | 55 | device_type = "soc"; |
| 56 | compatible = "simple-bus"; | ||
| 56 | ranges = <0x0 0xe0000000 0x100000>; | 57 | ranges = <0x0 0xe0000000 0x100000>; |
| 57 | reg = <0xe0000000 0x200>; | 58 | reg = <0xe0000000 0x200>; |
| 58 | bus-frequency = <330000000>; | 59 | bus-frequency = <330000000>; |
diff --git a/arch/powerpc/boot/dts/mpc8568mds.dts b/arch/powerpc/boot/dts/mpc8568mds.dts index 9c30a34821dc..a15f10343f53 100644 --- a/arch/powerpc/boot/dts/mpc8568mds.dts +++ b/arch/powerpc/boot/dts/mpc8568mds.dts | |||
| @@ -60,6 +60,7 @@ | |||
| 60 | #address-cells = <1>; | 60 | #address-cells = <1>; |
| 61 | #size-cells = <1>; | 61 | #size-cells = <1>; |
| 62 | device_type = "soc"; | 62 | device_type = "soc"; |
| 63 | compatible = "simple-bus"; | ||
| 63 | ranges = <0x0 0xe0000000 0x100000>; | 64 | ranges = <0x0 0xe0000000 0x100000>; |
| 64 | reg = <0xe0000000 0x1000>; | 65 | reg = <0xe0000000 0x1000>; |
| 65 | bus-frequency = <0>; | 66 | bus-frequency = <0>; |
diff --git a/arch/powerpc/boot/dts/mpc8572ds.dts b/arch/powerpc/boot/dts/mpc8572ds.dts index 08c61e3daecc..e124dd18fb5a 100644 --- a/arch/powerpc/boot/dts/mpc8572ds.dts +++ b/arch/powerpc/boot/dts/mpc8572ds.dts | |||
| @@ -68,6 +68,7 @@ | |||
| 68 | #address-cells = <1>; | 68 | #address-cells = <1>; |
| 69 | #size-cells = <1>; | 69 | #size-cells = <1>; |
| 70 | device_type = "soc"; | 70 | device_type = "soc"; |
| 71 | compatible = "simple-bus"; | ||
| 71 | ranges = <0x0 0xffe00000 0x100000>; | 72 | ranges = <0x0 0xffe00000 0x100000>; |
| 72 | reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed | 73 | reg = <0xffe00000 0x1000>; // CCSRBAR & soc regs, remove once parse code for immrbase fixed |
| 73 | bus-frequency = <0>; // Filled out by uboot. | 74 | bus-frequency = <0>; // Filled out by uboot. |
diff --git a/arch/powerpc/kernel/lparcfg.c b/arch/powerpc/kernel/lparcfg.c index 9f856a0c3e38..1a09719c7628 100644 --- a/arch/powerpc/kernel/lparcfg.c +++ b/arch/powerpc/kernel/lparcfg.c | |||
| @@ -636,10 +636,6 @@ static ssize_t lparcfg_write(struct file *file, const char __user * buf, | |||
| 636 | retval = -EIO; | 636 | retval = -EIO; |
| 637 | } else if (retval == H_PARAMETER) { | 637 | } else if (retval == H_PARAMETER) { |
| 638 | retval = -EINVAL; | 638 | retval = -EINVAL; |
| 639 | } else { | ||
| 640 | printk(KERN_WARNING "%s: received unknown hv return code %ld", | ||
| 641 | __func__, retval); | ||
| 642 | retval = -EIO; | ||
| 643 | } | 639 | } |
| 644 | 640 | ||
| 645 | return retval; | 641 | return retval; |
diff --git a/arch/powerpc/kernel/ptrace.c b/arch/powerpc/kernel/ptrace.c index 6b66cd85b433..3635be61f899 100644 --- a/arch/powerpc/kernel/ptrace.c +++ b/arch/powerpc/kernel/ptrace.c | |||
| @@ -375,7 +375,7 @@ static int vsr_get(struct task_struct *target, const struct user_regset *regset, | |||
| 375 | flush_vsx_to_thread(target); | 375 | flush_vsx_to_thread(target); |
| 376 | 376 | ||
| 377 | for (i = 0; i < 32 ; i++) | 377 | for (i = 0; i < 32 ; i++) |
| 378 | buf[i] = current->thread.fpr[i][TS_VSRLOWOFFSET]; | 378 | buf[i] = target->thread.fpr[i][TS_VSRLOWOFFSET]; |
| 379 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, | 379 | ret = user_regset_copyout(&pos, &count, &kbuf, &ubuf, |
| 380 | buf, 0, 32 * sizeof(double)); | 380 | buf, 0, 32 * sizeof(double)); |
| 381 | 381 | ||
| @@ -394,7 +394,7 @@ static int vsr_set(struct task_struct *target, const struct user_regset *regset, | |||
| 394 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, | 394 | ret = user_regset_copyin(&pos, &count, &kbuf, &ubuf, |
| 395 | buf, 0, 32 * sizeof(double)); | 395 | buf, 0, 32 * sizeof(double)); |
| 396 | for (i = 0; i < 32 ; i++) | 396 | for (i = 0; i < 32 ; i++) |
| 397 | current->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i]; | 397 | target->thread.fpr[i][TS_VSRLOWOFFSET] = buf[i]; |
| 398 | 398 | ||
| 399 | 399 | ||
| 400 | return ret; | 400 | return ret; |
| @@ -975,15 +975,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
| 975 | case PTRACE_GETVSRREGS: | 975 | case PTRACE_GETVSRREGS: |
| 976 | return copy_regset_to_user(child, &user_ppc_native_view, | 976 | return copy_regset_to_user(child, &user_ppc_native_view, |
| 977 | REGSET_VSX, | 977 | REGSET_VSX, |
| 978 | 0, (32 * sizeof(vector128) + | 978 | 0, 32 * sizeof(double), |
| 979 | sizeof(u32)), | ||
| 980 | (void __user *) data); | 979 | (void __user *) data); |
| 981 | 980 | ||
| 982 | case PTRACE_SETVSRREGS: | 981 | case PTRACE_SETVSRREGS: |
| 983 | return copy_regset_from_user(child, &user_ppc_native_view, | 982 | return copy_regset_from_user(child, &user_ppc_native_view, |
| 984 | REGSET_VSX, | 983 | REGSET_VSX, |
| 985 | 0, (32 * sizeof(vector128) + | 984 | 0, 32 * sizeof(double), |
| 986 | sizeof(u32)), | ||
| 987 | (const void __user *) data); | 985 | (const void __user *) data); |
| 988 | #endif | 986 | #endif |
| 989 | #ifdef CONFIG_SPE | 987 | #ifdef CONFIG_SPE |
diff --git a/arch/powerpc/kernel/ptrace32.c b/arch/powerpc/kernel/ptrace32.c index 67bf1a1e7e14..197d49c790ad 100644 --- a/arch/powerpc/kernel/ptrace32.c +++ b/arch/powerpc/kernel/ptrace32.c | |||
| @@ -294,6 +294,8 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request, | |||
| 294 | case PTRACE_SETFPREGS: | 294 | case PTRACE_SETFPREGS: |
| 295 | case PTRACE_GETVRREGS: | 295 | case PTRACE_GETVRREGS: |
| 296 | case PTRACE_SETVRREGS: | 296 | case PTRACE_SETVRREGS: |
| 297 | case PTRACE_GETVSRREGS: | ||
| 298 | case PTRACE_SETVSRREGS: | ||
| 297 | case PTRACE_GETREGS64: | 299 | case PTRACE_GETREGS64: |
| 298 | case PTRACE_SETREGS64: | 300 | case PTRACE_SETREGS64: |
| 299 | case PPC_PTRACE_GETFPREGS: | 301 | case PPC_PTRACE_GETFPREGS: |
diff --git a/arch/powerpc/mm/Makefile b/arch/powerpc/mm/Makefile index 1c00e0196f6c..e7392b45a5ef 100644 --- a/arch/powerpc/mm/Makefile +++ b/arch/powerpc/mm/Makefile | |||
| @@ -12,7 +12,8 @@ obj-y := fault.o mem.o \ | |||
| 12 | mmu_context_$(CONFIG_WORD_SIZE).o | 12 | mmu_context_$(CONFIG_WORD_SIZE).o |
| 13 | hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o | 13 | hash-$(CONFIG_PPC_NATIVE) := hash_native_64.o |
| 14 | obj-$(CONFIG_PPC64) += hash_utils_64.o \ | 14 | obj-$(CONFIG_PPC64) += hash_utils_64.o \ |
| 15 | slb_low.o slb.o stab.o mmap.o $(hash-y) | 15 | slb_low.o slb.o stab.o \ |
| 16 | gup.o mmap.o $(hash-y) | ||
| 16 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o | 17 | obj-$(CONFIG_PPC_STD_MMU_32) += ppc_mmu_32.o |
| 17 | obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \ | 18 | obj-$(CONFIG_PPC_STD_MMU) += hash_low_$(CONFIG_WORD_SIZE).o \ |
| 18 | tlb_$(CONFIG_WORD_SIZE).o | 19 | tlb_$(CONFIG_WORD_SIZE).o |
diff --git a/arch/powerpc/mm/gup.c b/arch/powerpc/mm/gup.c new file mode 100644 index 000000000000..9fdf4d6335e4 --- /dev/null +++ b/arch/powerpc/mm/gup.c | |||
| @@ -0,0 +1,280 @@ | |||
| 1 | /* | ||
| 2 | * Lockless get_user_pages_fast for powerpc | ||
| 3 | * | ||
| 4 | * Copyright (C) 2008 Nick Piggin | ||
| 5 | * Copyright (C) 2008 Novell Inc. | ||
| 6 | */ | ||
| 7 | #undef DEBUG | ||
| 8 | |||
| 9 | #include <linux/sched.h> | ||
| 10 | #include <linux/mm.h> | ||
| 11 | #include <linux/hugetlb.h> | ||
| 12 | #include <linux/vmstat.h> | ||
| 13 | #include <linux/pagemap.h> | ||
| 14 | #include <linux/rwsem.h> | ||
| 15 | #include <asm/pgtable.h> | ||
| 16 | |||
| 17 | /* | ||
| 18 | * The performance critical leaf functions are made noinline otherwise gcc | ||
| 19 | * inlines everything into a single function which results in too much | ||
| 20 | * register pressure. | ||
| 21 | */ | ||
| 22 | static noinline int gup_pte_range(pmd_t pmd, unsigned long addr, | ||
| 23 | unsigned long end, int write, struct page **pages, int *nr) | ||
| 24 | { | ||
| 25 | unsigned long mask, result; | ||
| 26 | pte_t *ptep; | ||
| 27 | |||
| 28 | result = _PAGE_PRESENT|_PAGE_USER; | ||
| 29 | if (write) | ||
| 30 | result |= _PAGE_RW; | ||
| 31 | mask = result | _PAGE_SPECIAL; | ||
| 32 | |||
| 33 | ptep = pte_offset_kernel(&pmd, addr); | ||
| 34 | do { | ||
| 35 | pte_t pte = *ptep; | ||
| 36 | struct page *page; | ||
| 37 | |||
| 38 | if ((pte_val(pte) & mask) != result) | ||
| 39 | return 0; | ||
| 40 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | ||
| 41 | page = pte_page(pte); | ||
| 42 | if (!page_cache_get_speculative(page)) | ||
| 43 | return 0; | ||
| 44 | if (unlikely(pte != *ptep)) { | ||
| 45 | put_page(page); | ||
| 46 | return 0; | ||
| 47 | } | ||
| 48 | pages[*nr] = page; | ||
| 49 | (*nr)++; | ||
| 50 | |||
| 51 | } while (ptep++, addr += PAGE_SIZE, addr != end); | ||
| 52 | |||
| 53 | return 1; | ||
| 54 | } | ||
| 55 | |||
| 56 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 57 | static noinline int gup_huge_pte(pte_t *ptep, struct hstate *hstate, | ||
| 58 | unsigned long *addr, unsigned long end, | ||
| 59 | int write, struct page **pages, int *nr) | ||
| 60 | { | ||
| 61 | unsigned long mask; | ||
| 62 | unsigned long pte_end; | ||
| 63 | struct page *head, *page; | ||
| 64 | pte_t pte; | ||
| 65 | int refs; | ||
| 66 | |||
| 67 | pte_end = (*addr + huge_page_size(hstate)) & huge_page_mask(hstate); | ||
| 68 | if (pte_end < end) | ||
| 69 | end = pte_end; | ||
| 70 | |||
| 71 | pte = *ptep; | ||
| 72 | mask = _PAGE_PRESENT|_PAGE_USER; | ||
| 73 | if (write) | ||
| 74 | mask |= _PAGE_RW; | ||
| 75 | if ((pte_val(pte) & mask) != mask) | ||
| 76 | return 0; | ||
| 77 | /* hugepages are never "special" */ | ||
| 78 | VM_BUG_ON(!pfn_valid(pte_pfn(pte))); | ||
| 79 | |||
| 80 | refs = 0; | ||
| 81 | head = pte_page(pte); | ||
| 82 | page = head + ((*addr & ~huge_page_mask(hstate)) >> PAGE_SHIFT); | ||
| 83 | do { | ||
| 84 | VM_BUG_ON(compound_head(page) != head); | ||
| 85 | pages[*nr] = page; | ||
| 86 | (*nr)++; | ||
| 87 | page++; | ||
| 88 | refs++; | ||
| 89 | } while (*addr += PAGE_SIZE, *addr != end); | ||
| 90 | |||
| 91 | if (!page_cache_add_speculative(head, refs)) { | ||
| 92 | *nr -= refs; | ||
| 93 | return 0; | ||
| 94 | } | ||
| 95 | if (unlikely(pte != *ptep)) { | ||
| 96 | /* Could be optimized better */ | ||
| 97 | while (*nr) { | ||
| 98 | put_page(page); | ||
| 99 | (*nr)--; | ||
| 100 | } | ||
| 101 | } | ||
| 102 | |||
| 103 | return 1; | ||
| 104 | } | ||
| 105 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
| 106 | |||
| 107 | static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end, | ||
| 108 | int write, struct page **pages, int *nr) | ||
| 109 | { | ||
| 110 | unsigned long next; | ||
| 111 | pmd_t *pmdp; | ||
| 112 | |||
| 113 | pmdp = pmd_offset(&pud, addr); | ||
| 114 | do { | ||
| 115 | pmd_t pmd = *pmdp; | ||
| 116 | |||
| 117 | next = pmd_addr_end(addr, end); | ||
| 118 | if (pmd_none(pmd)) | ||
| 119 | return 0; | ||
| 120 | if (!gup_pte_range(pmd, addr, next, write, pages, nr)) | ||
| 121 | return 0; | ||
| 122 | } while (pmdp++, addr = next, addr != end); | ||
| 123 | |||
| 124 | return 1; | ||
| 125 | } | ||
| 126 | |||
| 127 | static int gup_pud_range(pgd_t pgd, unsigned long addr, unsigned long end, | ||
| 128 | int write, struct page **pages, int *nr) | ||
| 129 | { | ||
| 130 | unsigned long next; | ||
| 131 | pud_t *pudp; | ||
| 132 | |||
| 133 | pudp = pud_offset(&pgd, addr); | ||
| 134 | do { | ||
| 135 | pud_t pud = *pudp; | ||
| 136 | |||
| 137 | next = pud_addr_end(addr, end); | ||
| 138 | if (pud_none(pud)) | ||
| 139 | return 0; | ||
| 140 | if (!gup_pmd_range(pud, addr, next, write, pages, nr)) | ||
| 141 | return 0; | ||
| 142 | } while (pudp++, addr = next, addr != end); | ||
| 143 | |||
| 144 | return 1; | ||
| 145 | } | ||
| 146 | |||
| 147 | int get_user_pages_fast(unsigned long start, int nr_pages, int write, | ||
| 148 | struct page **pages) | ||
| 149 | { | ||
| 150 | struct mm_struct *mm = current->mm; | ||
| 151 | unsigned long addr, len, end; | ||
| 152 | unsigned long next; | ||
| 153 | pgd_t *pgdp; | ||
| 154 | int psize, nr = 0; | ||
| 155 | unsigned int shift; | ||
| 156 | |||
| 157 | pr_debug("%s(%lx,%x,%s)\n", __func__, start, nr_pages, write ? "write" : "read"); | ||
| 158 | |||
| 159 | start &= PAGE_MASK; | ||
| 160 | addr = start; | ||
| 161 | len = (unsigned long) nr_pages << PAGE_SHIFT; | ||
| 162 | end = start + len; | ||
| 163 | |||
| 164 | if (unlikely(!access_ok(write ? VERIFY_WRITE : VERIFY_READ, | ||
| 165 | start, len))) | ||
| 166 | goto slow_irqon; | ||
| 167 | |||
| 168 | pr_debug(" aligned: %lx .. %lx\n", start, end); | ||
| 169 | |||
| 170 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 171 | /* We bail out on slice boundary crossing when hugetlb is | ||
| 172 | * enabled in order to not have to deal with two different | ||
| 173 | * page table formats | ||
| 174 | */ | ||
| 175 | if (addr < SLICE_LOW_TOP) { | ||
| 176 | if (end > SLICE_LOW_TOP) | ||
| 177 | goto slow_irqon; | ||
| 178 | |||
| 179 | if (unlikely(GET_LOW_SLICE_INDEX(addr) != | ||
| 180 | GET_LOW_SLICE_INDEX(end - 1))) | ||
| 181 | goto slow_irqon; | ||
| 182 | } else { | ||
| 183 | if (unlikely(GET_HIGH_SLICE_INDEX(addr) != | ||
| 184 | GET_HIGH_SLICE_INDEX(end - 1))) | ||
| 185 | goto slow_irqon; | ||
| 186 | } | ||
| 187 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
| 188 | |||
| 189 | /* | ||
| 190 | * XXX: batch / limit 'nr', to avoid large irq off latency | ||
| 191 | * needs some instrumenting to determine the common sizes used by | ||
| 192 | * important workloads (eg. DB2), and whether limiting the batch size | ||
| 193 | * will decrease performance. | ||
| 194 | * | ||
| 195 | * It seems like we're in the clear for the moment. Direct-IO is | ||
| 196 | * the main guy that batches up lots of get_user_pages, and even | ||
| 197 | * they are limited to 64-at-a-time which is not so many. | ||
| 198 | */ | ||
| 199 | /* | ||
| 200 | * This doesn't prevent pagetable teardown, but does prevent | ||
| 201 | * the pagetables from being freed on powerpc. | ||
| 202 | * | ||
| 203 | * So long as we atomically load page table pointers versus teardown, | ||
| 204 | * we can follow the address down to the the page and take a ref on it. | ||
| 205 | */ | ||
| 206 | local_irq_disable(); | ||
| 207 | |||
| 208 | psize = get_slice_psize(mm, addr); | ||
| 209 | shift = mmu_psize_defs[psize].shift; | ||
| 210 | |||
| 211 | #ifdef CONFIG_HUGETLB_PAGE | ||
| 212 | if (unlikely(mmu_huge_psizes[psize])) { | ||
| 213 | pte_t *ptep; | ||
| 214 | unsigned long a = addr; | ||
| 215 | unsigned long sz = ((1UL) << shift); | ||
| 216 | struct hstate *hstate = size_to_hstate(sz); | ||
| 217 | |||
| 218 | BUG_ON(!hstate); | ||
| 219 | /* | ||
| 220 | * XXX: could be optimized to avoid hstate | ||
| 221 | * lookup entirely (just use shift) | ||
| 222 | */ | ||
| 223 | |||
| 224 | do { | ||
| 225 | VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, a)].shift); | ||
| 226 | ptep = huge_pte_offset(mm, a); | ||
| 227 | pr_debug(" %016lx: huge ptep %p\n", a, ptep); | ||
| 228 | if (!ptep || !gup_huge_pte(ptep, hstate, &a, end, write, pages, | ||
| 229 | &nr)) | ||
| 230 | goto slow; | ||
| 231 | } while (a != end); | ||
| 232 | } else | ||
| 233 | #endif /* CONFIG_HUGETLB_PAGE */ | ||
| 234 | { | ||
| 235 | pgdp = pgd_offset(mm, addr); | ||
| 236 | do { | ||
| 237 | pgd_t pgd = *pgdp; | ||
| 238 | |||
| 239 | VM_BUG_ON(shift != mmu_psize_defs[get_slice_psize(mm, addr)].shift); | ||
| 240 | pr_debug(" %016lx: normal pgd %p\n", addr, (void *)pgd); | ||
| 241 | next = pgd_addr_end(addr, end); | ||
| 242 | if (pgd_none(pgd)) | ||
| 243 | goto slow; | ||
| 244 | if (!gup_pud_range(pgd, addr, next, write, pages, &nr)) | ||
| 245 | goto slow; | ||
| 246 | } while (pgdp++, addr = next, addr != end); | ||
| 247 | } | ||
| 248 | local_irq_enable(); | ||
| 249 | |||
| 250 | VM_BUG_ON(nr != (end - start) >> PAGE_SHIFT); | ||
| 251 | return nr; | ||
| 252 | |||
| 253 | { | ||
| 254 | int ret; | ||
| 255 | |||
| 256 | slow: | ||
| 257 | local_irq_enable(); | ||
| 258 | slow_irqon: | ||
| 259 | pr_debug(" slow path ! nr = %d\n", nr); | ||
| 260 | |||
| 261 | /* Try to get the remaining pages with get_user_pages */ | ||
| 262 | start += nr << PAGE_SHIFT; | ||
| 263 | pages += nr; | ||
| 264 | |||
| 265 | down_read(&mm->mmap_sem); | ||
| 266 | ret = get_user_pages(current, mm, start, | ||
| 267 | (end - start) >> PAGE_SHIFT, write, 0, pages, NULL); | ||
| 268 | up_read(&mm->mmap_sem); | ||
| 269 | |||
| 270 | /* Have to be a bit careful with return values */ | ||
| 271 | if (nr > 0) { | ||
| 272 | if (ret < 0) | ||
| 273 | ret = nr; | ||
| 274 | else | ||
| 275 | ret += nr; | ||
| 276 | } | ||
| 277 | |||
| 278 | return ret; | ||
| 279 | } | ||
| 280 | } | ||
diff --git a/arch/powerpc/platforms/83xx/mpc832x_mds.c b/arch/powerpc/platforms/83xx/mpc832x_mds.c index dd4be4aee314..ec43477caa63 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc832x_mds.c | |||
| @@ -105,6 +105,7 @@ static void __init mpc832x_sys_setup_arch(void) | |||
| 105 | static struct of_device_id mpc832x_ids[] = { | 105 | static struct of_device_id mpc832x_ids[] = { |
| 106 | { .type = "soc", }, | 106 | { .type = "soc", }, |
| 107 | { .compatible = "soc", }, | 107 | { .compatible = "soc", }, |
| 108 | { .compatible = "simple-bus", }, | ||
| 108 | { .type = "qe", }, | 109 | { .type = "qe", }, |
| 109 | { .compatible = "fsl,qe", }, | 110 | { .compatible = "fsl,qe", }, |
| 110 | {}, | 111 | {}, |
diff --git a/arch/powerpc/platforms/83xx/mpc832x_rdb.c b/arch/powerpc/platforms/83xx/mpc832x_rdb.c index f049d692d4c8..0300268ce5b8 100644 --- a/arch/powerpc/platforms/83xx/mpc832x_rdb.c +++ b/arch/powerpc/platforms/83xx/mpc832x_rdb.c | |||
| @@ -115,6 +115,7 @@ static void __init mpc832x_rdb_setup_arch(void) | |||
| 115 | static struct of_device_id mpc832x_ids[] = { | 115 | static struct of_device_id mpc832x_ids[] = { |
| 116 | { .type = "soc", }, | 116 | { .type = "soc", }, |
| 117 | { .compatible = "soc", }, | 117 | { .compatible = "soc", }, |
| 118 | { .compatible = "simple-bus", }, | ||
| 118 | { .type = "qe", }, | 119 | { .type = "qe", }, |
| 119 | { .compatible = "fsl,qe", }, | 120 | { .compatible = "fsl,qe", }, |
| 120 | {}, | 121 | {}, |
diff --git a/arch/powerpc/platforms/83xx/mpc834x_itx.c b/arch/powerpc/platforms/83xx/mpc834x_itx.c index 7301d77a08ee..76092d37c7d9 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_itx.c +++ b/arch/powerpc/platforms/83xx/mpc834x_itx.c | |||
| @@ -41,6 +41,7 @@ | |||
| 41 | 41 | ||
| 42 | static struct of_device_id __initdata mpc834x_itx_ids[] = { | 42 | static struct of_device_id __initdata mpc834x_itx_ids[] = { |
| 43 | { .compatible = "fsl,pq2pro-localbus", }, | 43 | { .compatible = "fsl,pq2pro-localbus", }, |
| 44 | { .compatible = "simple-bus", }, | ||
| 44 | {}, | 45 | {}, |
| 45 | }; | 46 | }; |
| 46 | 47 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc834x_mds.c b/arch/powerpc/platforms/83xx/mpc834x_mds.c index 30d509aa9f08..fc3f2ed1f3e9 100644 --- a/arch/powerpc/platforms/83xx/mpc834x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc834x_mds.c | |||
| @@ -111,6 +111,7 @@ static void __init mpc834x_mds_init_IRQ(void) | |||
| 111 | static struct of_device_id mpc834x_ids[] = { | 111 | static struct of_device_id mpc834x_ids[] = { |
| 112 | { .type = "soc", }, | 112 | { .type = "soc", }, |
| 113 | { .compatible = "soc", }, | 113 | { .compatible = "soc", }, |
| 114 | { .compatible = "simple-bus", }, | ||
| 114 | {}, | 115 | {}, |
| 115 | }; | 116 | }; |
| 116 | 117 | ||
diff --git a/arch/powerpc/platforms/83xx/mpc836x_mds.c b/arch/powerpc/platforms/83xx/mpc836x_mds.c index 75b80e836576..9d46e5bdd101 100644 --- a/arch/powerpc/platforms/83xx/mpc836x_mds.c +++ b/arch/powerpc/platforms/83xx/mpc836x_mds.c | |||
| @@ -136,6 +136,7 @@ static void __init mpc836x_mds_setup_arch(void) | |||
| 136 | static struct of_device_id mpc836x_ids[] = { | 136 | static struct of_device_id mpc836x_ids[] = { |
| 137 | { .type = "soc", }, | 137 | { .type = "soc", }, |
| 138 | { .compatible = "soc", }, | 138 | { .compatible = "soc", }, |
| 139 | { .compatible = "simple-bus", }, | ||
| 139 | { .type = "qe", }, | 140 | { .type = "qe", }, |
| 140 | { .compatible = "fsl,qe", }, | 141 | { .compatible = "fsl,qe", }, |
| 141 | {}, | 142 | {}, |
diff --git a/arch/powerpc/platforms/83xx/sbc834x.c b/arch/powerpc/platforms/83xx/sbc834x.c index fc21f5c15bab..156c4e218009 100644 --- a/arch/powerpc/platforms/83xx/sbc834x.c +++ b/arch/powerpc/platforms/83xx/sbc834x.c | |||
| @@ -83,6 +83,7 @@ static void __init sbc834x_init_IRQ(void) | |||
| 83 | static struct __initdata of_device_id sbc834x_ids[] = { | 83 | static struct __initdata of_device_id sbc834x_ids[] = { |
| 84 | { .type = "soc", }, | 84 | { .type = "soc", }, |
| 85 | { .compatible = "soc", }, | 85 | { .compatible = "soc", }, |
| 86 | { .compatible = "simple-bus", }, | ||
| 86 | {}, | 87 | {}, |
| 87 | }; | 88 | }; |
| 88 | 89 | ||
diff --git a/arch/powerpc/platforms/85xx/ksi8560.c b/arch/powerpc/platforms/85xx/ksi8560.c index 2145adeb220c..8a3b117b6ce2 100644 --- a/arch/powerpc/platforms/85xx/ksi8560.c +++ b/arch/powerpc/platforms/85xx/ksi8560.c | |||
| @@ -222,6 +222,7 @@ static void ksi8560_show_cpuinfo(struct seq_file *m) | |||
| 222 | 222 | ||
| 223 | static struct of_device_id __initdata of_bus_ids[] = { | 223 | static struct of_device_id __initdata of_bus_ids[] = { |
| 224 | { .type = "soc", }, | 224 | { .type = "soc", }, |
| 225 | { .type = "simple-bus", }, | ||
| 225 | { .name = "cpm", }, | 226 | { .name = "cpm", }, |
| 226 | { .name = "localbus", }, | 227 | { .name = "localbus", }, |
| 227 | {}, | 228 | {}, |
diff --git a/arch/powerpc/platforms/85xx/mpc8536_ds.c b/arch/powerpc/platforms/85xx/mpc8536_ds.c index 6b846aa1ced9..1bf5aefdfeb1 100644 --- a/arch/powerpc/platforms/85xx/mpc8536_ds.c +++ b/arch/powerpc/platforms/85xx/mpc8536_ds.c | |||
| @@ -91,6 +91,7 @@ static void __init mpc8536_ds_setup_arch(void) | |||
| 91 | static struct of_device_id __initdata mpc8536_ds_ids[] = { | 91 | static struct of_device_id __initdata mpc8536_ds_ids[] = { |
| 92 | { .type = "soc", }, | 92 | { .type = "soc", }, |
| 93 | { .compatible = "soc", }, | 93 | { .compatible = "soc", }, |
| 94 | { .compatible = "simple-bus", }, | ||
| 94 | {}, | 95 | {}, |
| 95 | }; | 96 | }; |
| 96 | 97 | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ads.c b/arch/powerpc/platforms/85xx/mpc85xx_ads.c index ba498d6f2d02..d17807a6b89a 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ads.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ads.c | |||
| @@ -230,6 +230,7 @@ static struct of_device_id __initdata of_bus_ids[] = { | |||
| 230 | { .type = "soc", }, | 230 | { .type = "soc", }, |
| 231 | { .name = "cpm", }, | 231 | { .name = "cpm", }, |
| 232 | { .name = "localbus", }, | 232 | { .name = "localbus", }, |
| 233 | { .compatible = "simple-bus", }, | ||
| 233 | {}, | 234 | {}, |
| 234 | }; | 235 | }; |
| 235 | 236 | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_ds.c b/arch/powerpc/platforms/85xx/mpc85xx_ds.c index 00c535806647..483b65cbabae 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_ds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_ds.c | |||
| @@ -186,6 +186,7 @@ static int __init mpc8544_ds_probe(void) | |||
| 186 | static struct of_device_id __initdata mpc85xxds_ids[] = { | 186 | static struct of_device_id __initdata mpc85xxds_ids[] = { |
| 187 | { .type = "soc", }, | 187 | { .type = "soc", }, |
| 188 | { .compatible = "soc", }, | 188 | { .compatible = "soc", }, |
| 189 | { .compatible = "simple-bus", }, | ||
| 189 | {}, | 190 | {}, |
| 190 | }; | 191 | }; |
| 191 | 192 | ||
diff --git a/arch/powerpc/platforms/85xx/mpc85xx_mds.c b/arch/powerpc/platforms/85xx/mpc85xx_mds.c index 43a459f63e31..2494c5155919 100644 --- a/arch/powerpc/platforms/85xx/mpc85xx_mds.c +++ b/arch/powerpc/platforms/85xx/mpc85xx_mds.c | |||
| @@ -260,6 +260,7 @@ machine_arch_initcall(mpc85xx_mds, board_fixups); | |||
| 260 | static struct of_device_id mpc85xx_ids[] = { | 260 | static struct of_device_id mpc85xx_ids[] = { |
| 261 | { .type = "soc", }, | 261 | { .type = "soc", }, |
| 262 | { .compatible = "soc", }, | 262 | { .compatible = "soc", }, |
| 263 | { .compatible = "simple-bus", }, | ||
| 263 | { .type = "qe", }, | 264 | { .type = "qe", }, |
| 264 | { .compatible = "fsl,qe", }, | 265 | { .compatible = "fsl,qe", }, |
| 265 | {}, | 266 | {}, |
diff --git a/arch/powerpc/platforms/85xx/sbc8560.c b/arch/powerpc/platforms/85xx/sbc8560.c index 2c580cd24e4f..6509ade71668 100644 --- a/arch/powerpc/platforms/85xx/sbc8560.c +++ b/arch/powerpc/platforms/85xx/sbc8560.c | |||
| @@ -217,6 +217,7 @@ static struct of_device_id __initdata of_bus_ids[] = { | |||
| 217 | { .type = "soc", }, | 217 | { .type = "soc", }, |
| 218 | { .name = "cpm", }, | 218 | { .name = "cpm", }, |
| 219 | { .name = "localbus", }, | 219 | { .name = "localbus", }, |
| 220 | { .compatible = "simple-bus", }, | ||
| 220 | {}, | 221 | {}, |
| 221 | }; | 222 | }; |
| 222 | 223 | ||
diff --git a/arch/powerpc/platforms/8xx/Kconfig b/arch/powerpc/platforms/8xx/Kconfig index 6fc849e51e48..71d7562e190b 100644 --- a/arch/powerpc/platforms/8xx/Kconfig +++ b/arch/powerpc/platforms/8xx/Kconfig | |||
| @@ -105,6 +105,16 @@ config 8xx_COPYBACK | |||
| 105 | 105 | ||
| 106 | If in doubt, say Y here. | 106 | If in doubt, say Y here. |
| 107 | 107 | ||
| 108 | config 8xx_GPIO | ||
| 109 | bool "GPIO API Support" | ||
| 110 | select GENERIC_GPIO | ||
| 111 | select ARCH_REQUIRE_GPIOLIB | ||
| 112 | help | ||
| 113 | Saying Y here will cause the ports on an MPC8xx processor to be used | ||
| 114 | with the GPIO API. If you say N here, the kernel needs less memory. | ||
| 115 | |||
| 116 | If in doubt, say Y here. | ||
| 117 | |||
| 108 | config 8xx_CPU6 | 118 | config 8xx_CPU6 |
| 109 | bool "CPU6 Silicon Errata (860 Pre Rev. C)" | 119 | bool "CPU6 Silicon Errata (860 Pre Rev. C)" |
| 110 | help | 120 | help |
diff --git a/arch/powerpc/platforms/Kconfig b/arch/powerpc/platforms/Kconfig index 1d0968775c0a..4c900efa164e 100644 --- a/arch/powerpc/platforms/Kconfig +++ b/arch/powerpc/platforms/Kconfig | |||
| @@ -254,6 +254,8 @@ config CPM2 | |||
| 254 | select CPM | 254 | select CPM |
| 255 | select PPC_LIB_RHEAP | 255 | select PPC_LIB_RHEAP |
| 256 | select PPC_PCI_CHOICE | 256 | select PPC_PCI_CHOICE |
| 257 | select ARCH_REQUIRE_GPIOLIB | ||
| 258 | select GENERIC_GPIO | ||
| 257 | help | 259 | help |
| 258 | The CPM2 (Communications Processor Module) is a coprocessor on | 260 | The CPM2 (Communications Processor Module) is a coprocessor on |
| 259 | embedded CPUs made by Freescale. Selecting this option means that | 261 | embedded CPUs made by Freescale. Selecting this option means that |
| @@ -281,6 +283,7 @@ config FSL_ULI1575 | |||
| 281 | 283 | ||
| 282 | config CPM | 284 | config CPM |
| 283 | bool | 285 | bool |
| 286 | select PPC_CLOCK | ||
| 284 | 287 | ||
| 285 | config OF_RTC | 288 | config OF_RTC |
| 286 | bool | 289 | bool |
diff --git a/arch/powerpc/sysdev/cpm1.c b/arch/powerpc/sysdev/cpm1.c index 661df42830b9..4a04823e8423 100644 --- a/arch/powerpc/sysdev/cpm1.c +++ b/arch/powerpc/sysdev/cpm1.c | |||
| @@ -30,6 +30,7 @@ | |||
| 30 | #include <linux/interrupt.h> | 30 | #include <linux/interrupt.h> |
| 31 | #include <linux/irq.h> | 31 | #include <linux/irq.h> |
| 32 | #include <linux/module.h> | 32 | #include <linux/module.h> |
| 33 | #include <linux/spinlock.h> | ||
| 33 | #include <asm/page.h> | 34 | #include <asm/page.h> |
| 34 | #include <asm/pgtable.h> | 35 | #include <asm/pgtable.h> |
| 35 | #include <asm/8xx_immap.h> | 36 | #include <asm/8xx_immap.h> |
| @@ -42,6 +43,10 @@ | |||
| 42 | 43 | ||
| 43 | #include <asm/fs_pd.h> | 44 | #include <asm/fs_pd.h> |
| 44 | 45 | ||
| 46 | #ifdef CONFIG_8xx_GPIO | ||
| 47 | #include <linux/of_gpio.h> | ||
| 48 | #endif | ||
| 49 | |||
| 45 | #define CPM_MAP_SIZE (0x4000) | 50 | #define CPM_MAP_SIZE (0x4000) |
| 46 | 51 | ||
| 47 | cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */ | 52 | cpm8xx_t __iomem *cpmp; /* Pointer to comm processor space */ |
| @@ -290,20 +295,24 @@ struct cpm_ioport16 { | |||
| 290 | __be16 res[3]; | 295 | __be16 res[3]; |
| 291 | }; | 296 | }; |
| 292 | 297 | ||
| 293 | struct cpm_ioport32 { | 298 | struct cpm_ioport32b { |
| 294 | __be32 dir, par, sor; | 299 | __be32 dir, par, odr, dat; |
| 300 | }; | ||
| 301 | |||
| 302 | struct cpm_ioport32e { | ||
| 303 | __be32 dir, par, sor, odr, dat; | ||
| 295 | }; | 304 | }; |
| 296 | 305 | ||
| 297 | static void cpm1_set_pin32(int port, int pin, int flags) | 306 | static void cpm1_set_pin32(int port, int pin, int flags) |
| 298 | { | 307 | { |
| 299 | struct cpm_ioport32 __iomem *iop; | 308 | struct cpm_ioport32e __iomem *iop; |
| 300 | pin = 1 << (31 - pin); | 309 | pin = 1 << (31 - pin); |
| 301 | 310 | ||
| 302 | if (port == CPM_PORTB) | 311 | if (port == CPM_PORTB) |
| 303 | iop = (struct cpm_ioport32 __iomem *) | 312 | iop = (struct cpm_ioport32e __iomem *) |
| 304 | &mpc8xx_immr->im_cpm.cp_pbdir; | 313 | &mpc8xx_immr->im_cpm.cp_pbdir; |
| 305 | else | 314 | else |
| 306 | iop = (struct cpm_ioport32 __iomem *) | 315 | iop = (struct cpm_ioport32e __iomem *) |
| 307 | &mpc8xx_immr->im_cpm.cp_pedir; | 316 | &mpc8xx_immr->im_cpm.cp_pedir; |
| 308 | 317 | ||
| 309 | if (flags & CPM_PIN_OUTPUT) | 318 | if (flags & CPM_PIN_OUTPUT) |
| @@ -498,3 +507,251 @@ int cpm1_clk_setup(enum cpm_clk_target target, int clock, int mode) | |||
| 498 | 507 | ||
| 499 | return 0; | 508 | return 0; |
| 500 | } | 509 | } |
| 510 | |||
| 511 | /* | ||
| 512 | * GPIO LIB API implementation | ||
| 513 | */ | ||
| 514 | #ifdef CONFIG_8xx_GPIO | ||
| 515 | |||
| 516 | struct cpm1_gpio16_chip { | ||
| 517 | struct of_mm_gpio_chip mm_gc; | ||
| 518 | spinlock_t lock; | ||
| 519 | |||
| 520 | /* shadowed data register to clear/set bits safely */ | ||
| 521 | u16 cpdata; | ||
| 522 | }; | ||
| 523 | |||
| 524 | static inline struct cpm1_gpio16_chip * | ||
| 525 | to_cpm1_gpio16_chip(struct of_mm_gpio_chip *mm_gc) | ||
| 526 | { | ||
| 527 | return container_of(mm_gc, struct cpm1_gpio16_chip, mm_gc); | ||
| 528 | } | ||
| 529 | |||
| 530 | static void cpm1_gpio16_save_regs(struct of_mm_gpio_chip *mm_gc) | ||
| 531 | { | ||
| 532 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); | ||
| 533 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | ||
| 534 | |||
| 535 | cpm1_gc->cpdata = in_be16(&iop->dat); | ||
| 536 | } | ||
| 537 | |||
| 538 | static int cpm1_gpio16_get(struct gpio_chip *gc, unsigned int gpio) | ||
| 539 | { | ||
| 540 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 541 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | ||
| 542 | u16 pin_mask; | ||
| 543 | |||
| 544 | pin_mask = 1 << (15 - gpio); | ||
| 545 | |||
| 546 | return !!(in_be16(&iop->dat) & pin_mask); | ||
| 547 | } | ||
| 548 | |||
| 549 | static void cpm1_gpio16_set(struct gpio_chip *gc, unsigned int gpio, int value) | ||
| 550 | { | ||
| 551 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 552 | struct cpm1_gpio16_chip *cpm1_gc = to_cpm1_gpio16_chip(mm_gc); | ||
| 553 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | ||
| 554 | unsigned long flags; | ||
| 555 | u16 pin_mask = 1 << (15 - gpio); | ||
| 556 | |||
| 557 | spin_lock_irqsave(&cpm1_gc->lock, flags); | ||
| 558 | |||
| 559 | if (value) | ||
| 560 | cpm1_gc->cpdata |= pin_mask; | ||
| 561 | else | ||
| 562 | cpm1_gc->cpdata &= ~pin_mask; | ||
| 563 | |||
| 564 | out_be16(&iop->dat, cpm1_gc->cpdata); | ||
| 565 | |||
| 566 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); | ||
| 567 | } | ||
| 568 | |||
| 569 | static int cpm1_gpio16_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 570 | { | ||
| 571 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 572 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | ||
| 573 | u16 pin_mask; | ||
| 574 | |||
| 575 | pin_mask = 1 << (15 - gpio); | ||
| 576 | |||
| 577 | setbits16(&iop->dir, pin_mask); | ||
| 578 | |||
| 579 | cpm1_gpio16_set(gc, gpio, val); | ||
| 580 | |||
| 581 | return 0; | ||
| 582 | } | ||
| 583 | |||
| 584 | static int cpm1_gpio16_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
| 585 | { | ||
| 586 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 587 | struct cpm_ioport16 __iomem *iop = mm_gc->regs; | ||
| 588 | u16 pin_mask; | ||
| 589 | |||
| 590 | pin_mask = 1 << (15 - gpio); | ||
| 591 | |||
| 592 | clrbits16(&iop->dir, pin_mask); | ||
| 593 | |||
| 594 | return 0; | ||
| 595 | } | ||
| 596 | |||
| 597 | int cpm1_gpiochip_add16(struct device_node *np) | ||
| 598 | { | ||
| 599 | struct cpm1_gpio16_chip *cpm1_gc; | ||
| 600 | struct of_mm_gpio_chip *mm_gc; | ||
| 601 | struct of_gpio_chip *of_gc; | ||
| 602 | struct gpio_chip *gc; | ||
| 603 | |||
| 604 | cpm1_gc = kzalloc(sizeof(*cpm1_gc), GFP_KERNEL); | ||
| 605 | if (!cpm1_gc) | ||
| 606 | return -ENOMEM; | ||
| 607 | |||
| 608 | spin_lock_init(&cpm1_gc->lock); | ||
| 609 | |||
| 610 | mm_gc = &cpm1_gc->mm_gc; | ||
| 611 | of_gc = &mm_gc->of_gc; | ||
| 612 | gc = &of_gc->gc; | ||
| 613 | |||
| 614 | mm_gc->save_regs = cpm1_gpio16_save_regs; | ||
| 615 | of_gc->gpio_cells = 2; | ||
| 616 | gc->ngpio = 16; | ||
| 617 | gc->direction_input = cpm1_gpio16_dir_in; | ||
| 618 | gc->direction_output = cpm1_gpio16_dir_out; | ||
| 619 | gc->get = cpm1_gpio16_get; | ||
| 620 | gc->set = cpm1_gpio16_set; | ||
| 621 | |||
| 622 | return of_mm_gpiochip_add(np, mm_gc); | ||
| 623 | } | ||
| 624 | |||
| 625 | struct cpm1_gpio32_chip { | ||
| 626 | struct of_mm_gpio_chip mm_gc; | ||
| 627 | spinlock_t lock; | ||
| 628 | |||
| 629 | /* shadowed data register to clear/set bits safely */ | ||
| 630 | u32 cpdata; | ||
| 631 | }; | ||
| 632 | |||
| 633 | static inline struct cpm1_gpio32_chip * | ||
| 634 | to_cpm1_gpio32_chip(struct of_mm_gpio_chip *mm_gc) | ||
| 635 | { | ||
| 636 | return container_of(mm_gc, struct cpm1_gpio32_chip, mm_gc); | ||
| 637 | } | ||
| 638 | |||
| 639 | static void cpm1_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc) | ||
| 640 | { | ||
| 641 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); | ||
| 642 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | ||
| 643 | |||
| 644 | cpm1_gc->cpdata = in_be32(&iop->dat); | ||
| 645 | } | ||
| 646 | |||
| 647 | static int cpm1_gpio32_get(struct gpio_chip *gc, unsigned int gpio) | ||
| 648 | { | ||
| 649 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 650 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | ||
| 651 | u32 pin_mask; | ||
| 652 | |||
| 653 | pin_mask = 1 << (31 - gpio); | ||
| 654 | |||
| 655 | return !!(in_be32(&iop->dat) & pin_mask); | ||
| 656 | } | ||
| 657 | |||
| 658 | static void cpm1_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) | ||
| 659 | { | ||
| 660 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 661 | struct cpm1_gpio32_chip *cpm1_gc = to_cpm1_gpio32_chip(mm_gc); | ||
| 662 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | ||
| 663 | unsigned long flags; | ||
| 664 | u32 pin_mask = 1 << (31 - gpio); | ||
| 665 | |||
| 666 | spin_lock_irqsave(&cpm1_gc->lock, flags); | ||
| 667 | |||
| 668 | if (value) | ||
| 669 | cpm1_gc->cpdata |= pin_mask; | ||
| 670 | else | ||
| 671 | cpm1_gc->cpdata &= ~pin_mask; | ||
| 672 | |||
| 673 | out_be32(&iop->dat, cpm1_gc->cpdata); | ||
| 674 | |||
| 675 | spin_unlock_irqrestore(&cpm1_gc->lock, flags); | ||
| 676 | } | ||
| 677 | |||
| 678 | static int cpm1_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 679 | { | ||
| 680 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 681 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | ||
| 682 | u32 pin_mask; | ||
| 683 | |||
| 684 | pin_mask = 1 << (31 - gpio); | ||
| 685 | |||
| 686 | setbits32(&iop->dir, pin_mask); | ||
| 687 | |||
| 688 | cpm1_gpio32_set(gc, gpio, val); | ||
| 689 | |||
| 690 | return 0; | ||
| 691 | } | ||
| 692 | |||
| 693 | static int cpm1_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
| 694 | { | ||
| 695 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 696 | struct cpm_ioport32b __iomem *iop = mm_gc->regs; | ||
| 697 | u32 pin_mask; | ||
| 698 | |||
| 699 | pin_mask = 1 << (31 - gpio); | ||
| 700 | |||
| 701 | clrbits32(&iop->dir, pin_mask); | ||
| 702 | |||
| 703 | return 0; | ||
| 704 | } | ||
| 705 | |||
| 706 | int cpm1_gpiochip_add32(struct device_node *np) | ||
| 707 | { | ||
| 708 | struct cpm1_gpio32_chip *cpm1_gc; | ||
| 709 | struct of_mm_gpio_chip *mm_gc; | ||
| 710 | struct of_gpio_chip *of_gc; | ||
| 711 | struct gpio_chip *gc; | ||
| 712 | |||
| 713 | cpm1_gc = kzalloc(sizeof(*cpm1_gc), GFP_KERNEL); | ||
| 714 | if (!cpm1_gc) | ||
| 715 | return -ENOMEM; | ||
| 716 | |||
| 717 | spin_lock_init(&cpm1_gc->lock); | ||
| 718 | |||
| 719 | mm_gc = &cpm1_gc->mm_gc; | ||
| 720 | of_gc = &mm_gc->of_gc; | ||
| 721 | gc = &of_gc->gc; | ||
| 722 | |||
| 723 | mm_gc->save_regs = cpm1_gpio32_save_regs; | ||
| 724 | of_gc->gpio_cells = 2; | ||
| 725 | gc->ngpio = 32; | ||
| 726 | gc->direction_input = cpm1_gpio32_dir_in; | ||
| 727 | gc->direction_output = cpm1_gpio32_dir_out; | ||
| 728 | gc->get = cpm1_gpio32_get; | ||
| 729 | gc->set = cpm1_gpio32_set; | ||
| 730 | |||
| 731 | return of_mm_gpiochip_add(np, mm_gc); | ||
| 732 | } | ||
| 733 | |||
| 734 | static int cpm_init_par_io(void) | ||
| 735 | { | ||
| 736 | struct device_node *np; | ||
| 737 | |||
| 738 | for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-a") | ||
| 739 | cpm1_gpiochip_add16(np); | ||
| 740 | |||
| 741 | for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-b") | ||
| 742 | cpm1_gpiochip_add32(np); | ||
| 743 | |||
| 744 | for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-c") | ||
| 745 | cpm1_gpiochip_add16(np); | ||
| 746 | |||
| 747 | for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-d") | ||
| 748 | cpm1_gpiochip_add16(np); | ||
| 749 | |||
| 750 | /* Port E uses CPM2 layout */ | ||
| 751 | for_each_compatible_node(np, NULL, "fsl,cpm1-pario-bank-e") | ||
| 752 | cpm2_gpiochip_add32(np); | ||
| 753 | return 0; | ||
| 754 | } | ||
| 755 | arch_initcall(cpm_init_par_io); | ||
| 756 | |||
| 757 | #endif /* CONFIG_8xx_GPIO */ | ||
diff --git a/arch/powerpc/sysdev/cpm2.c b/arch/powerpc/sysdev/cpm2.c index 5a6c5dfc53ef..f1c3395633b9 100644 --- a/arch/powerpc/sysdev/cpm2.c +++ b/arch/powerpc/sysdev/cpm2.c | |||
| @@ -115,16 +115,10 @@ EXPORT_SYMBOL(cpm_command); | |||
| 115 | * Baud rate clocks are zero-based in the driver code (as that maps | 115 | * Baud rate clocks are zero-based in the driver code (as that maps |
| 116 | * to port numbers). Documentation uses 1-based numbering. | 116 | * to port numbers). Documentation uses 1-based numbering. |
| 117 | */ | 117 | */ |
| 118 | #define BRG_INT_CLK (get_brgfreq()) | 118 | void __cpm2_setbrg(uint brg, uint rate, uint clk, int div16, int src) |
| 119 | #define BRG_UART_CLK (BRG_INT_CLK/16) | ||
| 120 | |||
| 121 | /* This function is used by UARTS, or anything else that uses a 16x | ||
| 122 | * oversampled clock. | ||
| 123 | */ | ||
| 124 | void | ||
| 125 | cpm_setbrg(uint brg, uint rate) | ||
| 126 | { | 119 | { |
| 127 | u32 __iomem *bp; | 120 | u32 __iomem *bp; |
| 121 | u32 val; | ||
| 128 | 122 | ||
| 129 | /* This is good enough to get SMCs running..... | 123 | /* This is good enough to get SMCs running..... |
| 130 | */ | 124 | */ |
| @@ -135,34 +129,14 @@ cpm_setbrg(uint brg, uint rate) | |||
| 135 | brg -= 4; | 129 | brg -= 4; |
| 136 | } | 130 | } |
| 137 | bp += brg; | 131 | bp += brg; |
| 138 | out_be32(bp, (((BRG_UART_CLK / rate) - 1) << 1) | CPM_BRG_EN); | 132 | val = (((clk / rate) - 1) << 1) | CPM_BRG_EN | src; |
| 139 | |||
| 140 | cpm2_unmap(bp); | ||
| 141 | } | ||
| 142 | |||
| 143 | /* This function is used to set high speed synchronous baud rate | ||
| 144 | * clocks. | ||
| 145 | */ | ||
| 146 | void | ||
| 147 | cpm2_fastbrg(uint brg, uint rate, int div16) | ||
| 148 | { | ||
| 149 | u32 __iomem *bp; | ||
| 150 | u32 val; | ||
| 151 | |||
| 152 | if (brg < 4) { | ||
| 153 | bp = cpm2_map_size(im_brgc1, 16); | ||
| 154 | } else { | ||
| 155 | bp = cpm2_map_size(im_brgc5, 16); | ||
| 156 | brg -= 4; | ||
| 157 | } | ||
| 158 | bp += brg; | ||
| 159 | val = ((BRG_INT_CLK / rate) << 1) | CPM_BRG_EN; | ||
| 160 | if (div16) | 133 | if (div16) |
| 161 | val |= CPM_BRG_DIV16; | 134 | val |= CPM_BRG_DIV16; |
| 162 | 135 | ||
| 163 | out_be32(bp, val); | 136 | out_be32(bp, val); |
| 164 | cpm2_unmap(bp); | 137 | cpm2_unmap(bp); |
| 165 | } | 138 | } |
| 139 | EXPORT_SYMBOL(__cpm2_setbrg); | ||
| 166 | 140 | ||
| 167 | int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode) | 141 | int cpm2_clk_setup(enum cpm_clk_target target, int clock, int mode) |
| 168 | { | 142 | { |
| @@ -377,3 +351,14 @@ void cpm2_set_pin(int port, int pin, int flags) | |||
| 377 | else | 351 | else |
| 378 | clrbits32(&iop[port].odr, pin); | 352 | clrbits32(&iop[port].odr, pin); |
| 379 | } | 353 | } |
| 354 | |||
| 355 | static int cpm_init_par_io(void) | ||
| 356 | { | ||
| 357 | struct device_node *np; | ||
| 358 | |||
| 359 | for_each_compatible_node(np, NULL, "fsl,cpm2-pario-bank") | ||
| 360 | cpm2_gpiochip_add32(np); | ||
| 361 | return 0; | ||
| 362 | } | ||
| 363 | arch_initcall(cpm_init_par_io); | ||
| 364 | |||
diff --git a/arch/powerpc/sysdev/cpm_common.c b/arch/powerpc/sysdev/cpm_common.c index e4b7296acb2c..53da8a079f96 100644 --- a/arch/powerpc/sysdev/cpm_common.c +++ b/arch/powerpc/sysdev/cpm_common.c | |||
| @@ -19,6 +19,8 @@ | |||
| 19 | 19 | ||
| 20 | #include <linux/init.h> | 20 | #include <linux/init.h> |
| 21 | #include <linux/of_device.h> | 21 | #include <linux/of_device.h> |
| 22 | #include <linux/spinlock.h> | ||
| 23 | #include <linux/of.h> | ||
| 22 | 24 | ||
| 23 | #include <asm/udbg.h> | 25 | #include <asm/udbg.h> |
| 24 | #include <asm/io.h> | 26 | #include <asm/io.h> |
| @@ -28,6 +30,10 @@ | |||
| 28 | 30 | ||
| 29 | #include <mm/mmu_decl.h> | 31 | #include <mm/mmu_decl.h> |
| 30 | 32 | ||
| 33 | #if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO) | ||
| 34 | #include <linux/of_gpio.h> | ||
| 35 | #endif | ||
| 36 | |||
| 31 | #ifdef CONFIG_PPC_EARLY_DEBUG_CPM | 37 | #ifdef CONFIG_PPC_EARLY_DEBUG_CPM |
| 32 | static u32 __iomem *cpm_udbg_txdesc = | 38 | static u32 __iomem *cpm_udbg_txdesc = |
| 33 | (u32 __iomem __force *)CONFIG_PPC_EARLY_DEBUG_CPM_ADDR; | 39 | (u32 __iomem __force *)CONFIG_PPC_EARLY_DEBUG_CPM_ADDR; |
| @@ -207,3 +213,120 @@ dma_addr_t cpm_muram_dma(void __iomem *addr) | |||
| 207 | return muram_pbase + ((u8 __iomem *)addr - muram_vbase); | 213 | return muram_pbase + ((u8 __iomem *)addr - muram_vbase); |
| 208 | } | 214 | } |
| 209 | EXPORT_SYMBOL(cpm_muram_dma); | 215 | EXPORT_SYMBOL(cpm_muram_dma); |
| 216 | |||
| 217 | #if defined(CONFIG_CPM2) || defined(CONFIG_8xx_GPIO) | ||
| 218 | |||
| 219 | struct cpm2_ioports { | ||
| 220 | u32 dir, par, sor, odr, dat; | ||
| 221 | u32 res[3]; | ||
| 222 | }; | ||
| 223 | |||
| 224 | struct cpm2_gpio32_chip { | ||
| 225 | struct of_mm_gpio_chip mm_gc; | ||
| 226 | spinlock_t lock; | ||
| 227 | |||
| 228 | /* shadowed data register to clear/set bits safely */ | ||
| 229 | u32 cpdata; | ||
| 230 | }; | ||
| 231 | |||
| 232 | static inline struct cpm2_gpio32_chip * | ||
| 233 | to_cpm2_gpio32_chip(struct of_mm_gpio_chip *mm_gc) | ||
| 234 | { | ||
| 235 | return container_of(mm_gc, struct cpm2_gpio32_chip, mm_gc); | ||
| 236 | } | ||
| 237 | |||
| 238 | static void cpm2_gpio32_save_regs(struct of_mm_gpio_chip *mm_gc) | ||
| 239 | { | ||
| 240 | struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); | ||
| 241 | struct cpm2_ioports __iomem *iop = mm_gc->regs; | ||
| 242 | |||
| 243 | cpm2_gc->cpdata = in_be32(&iop->dat); | ||
| 244 | } | ||
| 245 | |||
| 246 | static int cpm2_gpio32_get(struct gpio_chip *gc, unsigned int gpio) | ||
| 247 | { | ||
| 248 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 249 | struct cpm2_ioports __iomem *iop = mm_gc->regs; | ||
| 250 | u32 pin_mask; | ||
| 251 | |||
| 252 | pin_mask = 1 << (31 - gpio); | ||
| 253 | |||
| 254 | return !!(in_be32(&iop->dat) & pin_mask); | ||
| 255 | } | ||
| 256 | |||
| 257 | static void cpm2_gpio32_set(struct gpio_chip *gc, unsigned int gpio, int value) | ||
| 258 | { | ||
| 259 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 260 | struct cpm2_gpio32_chip *cpm2_gc = to_cpm2_gpio32_chip(mm_gc); | ||
| 261 | struct cpm2_ioports __iomem *iop = mm_gc->regs; | ||
| 262 | unsigned long flags; | ||
| 263 | u32 pin_mask = 1 << (31 - gpio); | ||
| 264 | |||
| 265 | spin_lock_irqsave(&cpm2_gc->lock, flags); | ||
| 266 | |||
| 267 | if (value) | ||
| 268 | cpm2_gc->cpdata |= pin_mask; | ||
| 269 | else | ||
| 270 | cpm2_gc->cpdata &= ~pin_mask; | ||
| 271 | |||
| 272 | out_be32(&iop->dat, cpm2_gc->cpdata); | ||
| 273 | |||
| 274 | spin_unlock_irqrestore(&cpm2_gc->lock, flags); | ||
| 275 | } | ||
| 276 | |||
| 277 | static int cpm2_gpio32_dir_out(struct gpio_chip *gc, unsigned int gpio, int val) | ||
| 278 | { | ||
| 279 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 280 | struct cpm2_ioports __iomem *iop = mm_gc->regs; | ||
| 281 | u32 pin_mask; | ||
| 282 | |||
| 283 | pin_mask = 1 << (31 - gpio); | ||
| 284 | |||
| 285 | setbits32(&iop->dir, pin_mask); | ||
| 286 | |||
| 287 | cpm2_gpio32_set(gc, gpio, val); | ||
| 288 | |||
| 289 | return 0; | ||
| 290 | } | ||
| 291 | |||
| 292 | static int cpm2_gpio32_dir_in(struct gpio_chip *gc, unsigned int gpio) | ||
| 293 | { | ||
| 294 | struct of_mm_gpio_chip *mm_gc = to_of_mm_gpio_chip(gc); | ||
| 295 | struct cpm2_ioports __iomem *iop = mm_gc->regs; | ||
| 296 | u32 pin_mask; | ||
| 297 | |||
| 298 | pin_mask = 1 << (31 - gpio); | ||
| 299 | |||
| 300 | clrbits32(&iop->dir, pin_mask); | ||
| 301 | |||
| 302 | return 0; | ||
| 303 | } | ||
| 304 | |||
| 305 | int cpm2_gpiochip_add32(struct device_node *np) | ||
| 306 | { | ||
| 307 | struct cpm2_gpio32_chip *cpm2_gc; | ||
| 308 | struct of_mm_gpio_chip *mm_gc; | ||
| 309 | struct of_gpio_chip *of_gc; | ||
| 310 | struct gpio_chip *gc; | ||
| 311 | |||
| 312 | cpm2_gc = kzalloc(sizeof(*cpm2_gc), GFP_KERNEL); | ||
| 313 | if (!cpm2_gc) | ||
| 314 | return -ENOMEM; | ||
| 315 | |||
| 316 | spin_lock_init(&cpm2_gc->lock); | ||
| 317 | |||
| 318 | mm_gc = &cpm2_gc->mm_gc; | ||
| 319 | of_gc = &mm_gc->of_gc; | ||
| 320 | gc = &of_gc->gc; | ||
| 321 | |||
| 322 | mm_gc->save_regs = cpm2_gpio32_save_regs; | ||
| 323 | of_gc->gpio_cells = 2; | ||
| 324 | gc->ngpio = 32; | ||
| 325 | gc->direction_input = cpm2_gpio32_dir_in; | ||
| 326 | gc->direction_output = cpm2_gpio32_dir_out; | ||
| 327 | gc->get = cpm2_gpio32_get; | ||
| 328 | gc->set = cpm2_gpio32_set; | ||
| 329 | |||
| 330 | return of_mm_gpiochip_add(np, mm_gc); | ||
| 331 | } | ||
| 332 | #endif /* CONFIG_CPM2 || CONFIG_8xx_GPIO */ | ||
diff --git a/arch/powerpc/sysdev/rtc_cmos_setup.c b/arch/powerpc/sysdev/rtc_cmos_setup.c index c09ddc0dbeb3..c1879ebfd4f4 100644 --- a/arch/powerpc/sysdev/rtc_cmos_setup.c +++ b/arch/powerpc/sysdev/rtc_cmos_setup.c | |||
| @@ -21,6 +21,7 @@ static int __init add_rtc(void) | |||
| 21 | struct device_node *np; | 21 | struct device_node *np; |
| 22 | struct platform_device *pd; | 22 | struct platform_device *pd; |
| 23 | struct resource res[2]; | 23 | struct resource res[2]; |
| 24 | unsigned int num_res = 1; | ||
| 24 | int ret; | 25 | int ret; |
| 25 | 26 | ||
| 26 | memset(&res, 0, sizeof(res)); | 27 | memset(&res, 0, sizeof(res)); |
| @@ -41,14 +42,24 @@ static int __init add_rtc(void) | |||
| 41 | if (res[0].start != RTC_PORT(0)) | 42 | if (res[0].start != RTC_PORT(0)) |
| 42 | return -EINVAL; | 43 | return -EINVAL; |
| 43 | 44 | ||
| 44 | /* Use a fixed interrupt value of 8 since on PPC if we are using this | 45 | np = of_find_compatible_node(NULL, NULL, "chrp,iic"); |
| 45 | * its off an i8259 which we ensure has interrupt numbers 0..15. */ | 46 | if (!np) |
| 46 | res[1].start = 8; | 47 | np = of_find_compatible_node(NULL, NULL, "pnpPNP,000"); |
| 47 | res[1].end = 8; | 48 | if (np) { |
| 48 | res[1].flags = IORESOURCE_IRQ; | 49 | of_node_put(np); |
| 50 | /* | ||
| 51 | * Use a fixed interrupt value of 8 since on PPC if we are | ||
| 52 | * using this its off an i8259 which we ensure has interrupt | ||
| 53 | * numbers 0..15. | ||
| 54 | */ | ||
| 55 | res[1].start = 8; | ||
| 56 | res[1].end = 8; | ||
| 57 | res[1].flags = IORESOURCE_IRQ; | ||
| 58 | num_res++; | ||
| 59 | } | ||
| 49 | 60 | ||
| 50 | pd = platform_device_register_simple("rtc_cmos", -1, | 61 | pd = platform_device_register_simple("rtc_cmos", -1, |
| 51 | &res[0], 2); | 62 | &res[0], num_res); |
| 52 | 63 | ||
| 53 | if (IS_ERR(pd)) | 64 | if (IS_ERR(pd)) |
| 54 | return PTR_ERR(pd); | 65 | return PTR_ERR(pd); |
