Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge remote-tracking branch 'scott/next' into next

Merge Freescale updates

+1410 -43
+309
Documentation/devicetree/bindings/powerpc/fsl/interlaken-lac.txt
··· 1 + =============================================================================== 2 + Freescale Interlaken Look-Aside Controller Device Bindings 3 + Copyright 2012 Freescale Semiconductor Inc. 4 + 5 + CONTENTS 6 + - Interlaken Look-Aside Controller (LAC) Node 7 + - Example LAC Node 8 + - Interlaken Look-Aside Controller (LAC) Software Portal Node 9 + - Interlaken Look-Aside Controller (LAC) Software Portal Child Nodes 10 + - Example LAC SWP Node with Child Nodes 11 + 12 + ============================================================================== 13 + Interlaken Look-Aside Controller (LAC) Node 14 + 15 + DESCRIPTION 16 + 17 + The Interlaken is a narrow, high speed channelized chip-to-chip interface. To 18 + facilitate interoperability between a data path device and a look-aside 19 + co-processor, the Interlaken Look-Aside protocol is defined for short 20 + transaction-related transfers. Although based on the Interlaken protocol, 21 + Interlaken Look-Aside is not directly compatible with Interlaken and can be 22 + considered a different operation mode. 23 + 24 + The Interlaken LA controller connects internal platform to Interlaken serial 25 + interface. It accepts LA command through software portals, which are system 26 + memory mapped 4KB spaces. The LA commands are then translated into the 27 + Interlaken control words and data words, which are sent on TX side to TCAM 28 + through SerDes lanes. 29 + 30 + There are two 4KiB spaces defined within the LAC global register memory map. 31 + There is a full register set at 0x0000-0x0FFF (also known as the "hypervisor" 32 + version), and a subset at 0x1000-0x1FFF. The former is a superset of the 33 + latter, and includes certain registers that should not be accessible to 34 + partitioned software. Separate nodes are used for each region, with a phandle 35 + linking the hypervisor node to the normal operating node. 36 + 37 + PROPERTIES 38 + 39 + - compatible 40 + Usage: required 41 + Value type: <string> 42 + Definition: Must include "fsl,interlaken-lac". This represents only 43 + those LAC CCSR registers not protected in partitioned 44 + software. The version of the device is determined by the LAC 45 + IP Block Revision Register (IPBRR0) at offset 0x0BF8. 46 + 47 + Table of correspondences between IPBRR0 values and example 48 + chips: 49 + Value Device 50 + ----------- ------- 51 + 0x02000100 T4240 52 + 53 + The Hypervisor node has a different compatible. It must include 54 + "fsl,interlaken-lac-hv". This node represents the protected 55 + LAC register space and is required except inside a partition 56 + where access to the hypervisor node is to be denied. 57 + 58 + - fsl,non-hv-node 59 + Usage: required in "fsl,interlaken-lac-hv" 60 + Value type: <phandle> 61 + Definition: Points to the non-protected LAC CCSR mapped register space 62 + node. 63 + 64 + - reg 65 + Usage: required 66 + Value type: <prop-encoded-array> 67 + Definition: A standard property. The first resource represents the 68 + Interlaken LAC configuration registers. 69 + 70 + - interrupts: 71 + Usage: required in non-hv node only 72 + Value type: <prop-encoded-array> 73 + Definition: Interrupt mapping for Interlaken LAC error IRQ. 74 + 75 + EXAMPLE 76 + lac: lac@229000 { 77 + compatible = "fsl,interlaken-lac" 78 + reg = <0x229000 0x1000>; 79 + interrupts = <16 2 1 18>; 80 + }; 81 + 82 + lac-hv@228000 { 83 + compatible = "fsl,interlaken-lac-hv" 84 + reg = <0x228000 0x1000>; 85 + fsl,non-hv-node = <&lac>; 86 + }; 87 + 88 + =============================================================================== 89 + Interlaken Look-Aside Controller (LAC) Software Portal Container Node 90 + 91 + DESCRIPTION 92 + The Interlaken Look-Aside Controller (LAC) utilizes Software Portals to accept 93 + Interlaken Look-Aside (ILA) commands. The Interlaken LAC software portal 94 + memory map occupies 128KB of memory space. The software portal memory space is 95 + intended to be cache-enabled. WIMG for each software space is required to be 96 + 0010 if stashing is enabled; otherwise, WIMG can be 0000 or 0010. 97 + 98 + PROPERTIES 99 + 100 + - #address-cells 101 + Usage: required 102 + Value type: <u32> 103 + Definition: A standard property. Must have a value of 1. 104 + 105 + - #size-cells 106 + Usage: required 107 + Value type: <u32> 108 + Definition: A standard property. Must have a value of 1. 109 + 110 + - compatible 111 + Usage: required 112 + Value type: <string> 113 + Definition: Must include "fsl,interlaken-lac-portals" 114 + 115 + - ranges 116 + Usage: required 117 + Value type: <prop-encoded-array> 118 + Definition: A standard property. Specifies the address and length 119 + of the LAC portal memory space. 120 + 121 + =============================================================================== 122 + Interlaken Look-Aside Controller (LAC) Software Portals Child Nodes 123 + 124 + DESCRIPTION 125 + There are up to 24 available software portals with each software portal 126 + requiring 4KB of consecutive memory within the software portal memory mapped 127 + space. 128 + 129 + PROPERTIES 130 + 131 + - compatible 132 + Usage: required 133 + Value type: <string> 134 + Definition: Must include "fsl,interlaken-lac-portal-vX.Y" where X is 135 + the Major version (IP_MJ) found in the LAC IP Block Revision 136 + Register (IPBRR0), at offset 0x0BF8, and Y is the Minor version 137 + (IP_MN). 138 + 139 + Table of correspondences between version values and example chips: 140 + Value Device 141 + ------ ------- 142 + 1.0 T4240 143 + 144 + - reg 145 + Usage: required 146 + Value type: <prop-encoded-array> 147 + Definition: A standard property. The first resource represents the 148 + Interlaken LAC software portal registers. 149 + 150 + - fsl,liodn 151 + Value type: <u32> 152 + Definition: The logical I/O device number (LIODN) for this device. The 153 + LIODN is a number expressed by this device and used to perform 154 + look-ups in the IOMMU (PAMU) address table when performing 155 + DMAs. This property is automatically added by u-boot. 156 + 157 + =============================================================================== 158 + EXAMPLE 159 + 160 + lac-portals { 161 + #address-cells = <0x1>; 162 + #size-cells = <0x1>; 163 + compatible = "fsl,interlaken-lac-portals"; 164 + ranges = <0x0 0xf 0xf4400000 0x20000>; 165 + 166 + lportal0: lac-portal@0 { 167 + compatible = "fsl,interlaken-lac-portal-v1.0"; 168 + fsl,liodn = <0x204>; 169 + reg = <0x0 0x1000>; 170 + }; 171 + 172 + lportal1: lac-portal@1000 { 173 + compatible = "fsl,interlaken-lac-portal-v1.0"; 174 + fsl,liodn = <0x205>; 175 + reg = <0x1000 0x1000>; 176 + }; 177 + 178 + lportal2: lac-portal@2000 { 179 + compatible = "fsl,interlaken-lac-portal-v1.0"; 180 + fsl,liodn = <0x206>; 181 + reg = <0x2000 0x1000>; 182 + }; 183 + 184 + lportal3: lac-portal@3000 { 185 + compatible = "fsl,interlaken-lac-portal-v1.0"; 186 + fsl,liodn = <0x207>; 187 + reg = <0x3000 0x1000>; 188 + }; 189 + 190 + lportal4: lac-portal@4000 { 191 + compatible = "fsl,interlaken-lac-portal-v1.0"; 192 + fsl,liodn = <0x208>; 193 + reg = <0x4000 0x1000>; 194 + }; 195 + 196 + lportal5: lac-portal@5000 { 197 + compatible = "fsl,interlaken-lac-portal-v1.0"; 198 + fsl,liodn = <0x209>; 199 + reg = <0x5000 0x1000>; 200 + }; 201 + 202 + lportal6: lac-portal@6000 { 203 + compatible = "fsl,interlaken-lac-portal-v1.0"; 204 + fsl,liodn = <0x20A>; 205 + reg = <0x6000 0x1000>; 206 + }; 207 + 208 + lportal7: lac-portal@7000 { 209 + compatible = "fsl,interlaken-lac-portal-v1.0"; 210 + fsl,liodn = <0x20B>; 211 + reg = <0x7000 0x1000>; 212 + }; 213 + 214 + lportal8: lac-portal@8000 { 215 + compatible = "fsl,interlaken-lac-portal-v1.0"; 216 + fsl,liodn = <0x20C>; 217 + reg = <0x8000 0x1000>; 218 + }; 219 + 220 + lportal9: lac-portal@9000 { 221 + compatible = "fsl,interlaken-lac-portal-v1.0"; 222 + fsl,liodn = <0x20D>; 223 + reg = <0x9000 0x1000>; 224 + }; 225 + 226 + lportal10: lac-portal@A000 { 227 + compatible = "fsl,interlaken-lac-portal-v1.0"; 228 + fsl,liodn = <0x20E>; 229 + reg = <0xA000 0x1000>; 230 + }; 231 + 232 + lportal11: lac-portal@B000 { 233 + compatible = "fsl,interlaken-lac-portal-v1.0"; 234 + fsl,liodn = <0x20F>; 235 + reg = <0xB000 0x1000>; 236 + }; 237 + 238 + lportal12: lac-portal@C000 { 239 + compatible = "fsl,interlaken-lac-portal-v1.0"; 240 + fsl,liodn = <0x210>; 241 + reg = <0xC000 0x1000>; 242 + }; 243 + 244 + lportal13: lac-portal@D000 { 245 + compatible = "fsl,interlaken-lac-portal-v1.0"; 246 + fsl,liodn = <0x211>; 247 + reg = <0xD000 0x1000>; 248 + }; 249 + 250 + lportal14: lac-portal@E000 { 251 + compatible = "fsl,interlaken-lac-portal-v1.0"; 252 + fsl,liodn = <0x212>; 253 + reg = <0xE000 0x1000>; 254 + }; 255 + 256 + lportal15: lac-portal@F000 { 257 + compatible = "fsl,interlaken-lac-portal-v1.0"; 258 + fsl,liodn = <0x213>; 259 + reg = <0xF000 0x1000>; 260 + }; 261 + 262 + lportal16: lac-portal@10000 { 263 + compatible = "fsl,interlaken-lac-portal-v1.0"; 264 + fsl,liodn = <0x214>; 265 + reg = <0x10000 0x1000>; 266 + }; 267 + 268 + lportal17: lac-portal@11000 { 269 + compatible = "fsl,interlaken-lac-portal-v1.0"; 270 + fsl,liodn = <0x215>; 271 + reg = <0x11000 0x1000>; 272 + }; 273 + 274 + lportal8: lac-portal@1200 { 275 + compatible = "fsl,interlaken-lac-portal-v1.0"; 276 + fsl,liodn = <0x216>; 277 + reg = <0x12000 0x1000>; 278 + }; 279 + 280 + lportal19: lac-portal@13000 { 281 + compatible = "fsl,interlaken-lac-portal-v1.0"; 282 + fsl,liodn = <0x217>; 283 + reg = <0x13000 0x1000>; 284 + }; 285 + 286 + lportal20: lac-portal@14000 { 287 + compatible = "fsl,interlaken-lac-portal-v1.0"; 288 + fsl,liodn = <0x218>; 289 + reg = <0x14000 0x1000>; 290 + }; 291 + 292 + lportal21: lac-portal@15000 { 293 + compatible = "fsl,interlaken-lac-portal-v1.0"; 294 + fsl,liodn = <0x219>; 295 + reg = <0x15000 0x1000>; 296 + }; 297 + 298 + lportal22: lac-portal@16000 { 299 + compatible = "fsl,interlaken-lac-portal-v1.0"; 300 + fsl,liodn = <0x21A>; 301 + reg = <0x16000 0x1000>; 302 + }; 303 + 304 + lportal23: lac-portal@17000 { 305 + compatible = "fsl,interlaken-lac-portal-v1.0"; 306 + fsl,liodn = <0x21B>; 307 + reg = <0x17000 0x1000>; 308 + }; 309 + };
+156
arch/powerpc/boot/dts/fsl/interlaken-lac-portals.dtsi
··· 1 + /* T4240 Interlaken LAC Portal device tree stub with 24 portals. 2 + * 3 + * Copyright 2012 Freescale Semiconductor Inc. 4 + * 5 + * Redistribution and use in source and binary forms, with or without 6 + * modification, are permitted provided that the following conditions are met: 7 + * * Redistributions of source code must retain the above copyright 8 + * notice, this list of conditions and the following disclaimer. 9 + * * Redistributions in binary form must reproduce the above copyright 10 + * notice, this list of conditions and the following disclaimer in the 11 + * documentation and/or other materials provided with the distribution. 12 + * * Neither the name of Freescale Semiconductor nor the 13 + * names of its contributors may be used to endorse or promote products 14 + * derived from this software without specific prior written permission. 15 + * 16 + * 17 + * ALTERNATIVELY, this software may be distributed under the terms of the 18 + * GNU General Public License ("GPL") as published by the Free Software 19 + * Foundation, either version 2 of that License or (at your option) any 20 + * later version. 21 + * 22 + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY 23 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 26 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 29 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 31 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 + */ 33 + 34 + #address-cells = <0x1>; 35 + #size-cells = <0x1>; 36 + compatible = "fsl,interlaken-lac-portals"; 37 + 38 + lportal0: lac-portal@0 { 39 + compatible = "fsl,interlaken-lac-portal-v1.0"; 40 + reg = <0x0 0x1000>; 41 + }; 42 + 43 + lportal1: lac-portal@1000 { 44 + compatible = "fsl,interlaken-lac-portal-v1.0"; 45 + reg = <0x1000 0x1000>; 46 + }; 47 + 48 + lportal2: lac-portal@2000 { 49 + compatible = "fsl,interlaken-lac-portal-v1.0"; 50 + reg = <0x2000 0x1000>; 51 + }; 52 + 53 + lportal3: lac-portal@3000 { 54 + compatible = "fsl,interlaken-lac-portal-v1.0"; 55 + reg = <0x3000 0x1000>; 56 + }; 57 + 58 + lportal4: lac-portal@4000 { 59 + compatible = "fsl,interlaken-lac-portal-v1.0"; 60 + reg = <0x4000 0x1000>; 61 + }; 62 + 63 + lportal5: lac-portal@5000 { 64 + compatible = "fsl,interlaken-lac-portal-v1.0"; 65 + reg = <0x5000 0x1000>; 66 + }; 67 + 68 + lportal6: lac-portal@6000 { 69 + compatible = "fsl,interlaken-lac-portal-v1.0"; 70 + reg = <0x6000 0x1000>; 71 + }; 72 + 73 + lportal7: lac-portal@7000 { 74 + compatible = "fsl,interlaken-lac-portal-v1.0"; 75 + reg = <0x7000 0x1000>; 76 + }; 77 + 78 + lportal8: lac-portal@8000 { 79 + compatible = "fsl,interlaken-lac-portal-v1.0"; 80 + reg = <0x8000 0x1000>; 81 + }; 82 + 83 + lportal9: lac-portal@9000 { 84 + compatible = "fsl,interlaken-lac-portal-v1.0"; 85 + reg = <0x9000 0x1000>; 86 + }; 87 + 88 + lportal10: lac-portal@A000 { 89 + compatible = "fsl,interlaken-lac-portal-v1.0"; 90 + reg = <0xA000 0x1000>; 91 + }; 92 + 93 + lportal11: lac-portal@B000 { 94 + compatible = "fsl,interlaken-lac-portal-v1.0"; 95 + reg = <0xB000 0x1000>; 96 + }; 97 + 98 + lportal12: lac-portal@C000 { 99 + compatible = "fsl,interlaken-lac-portal-v1.0"; 100 + reg = <0xC000 0x1000>; 101 + }; 102 + 103 + lportal13: lac-portal@D000 { 104 + compatible = "fsl,interlaken-lac-portal-v1.0"; 105 + reg = <0xD000 0x1000>; 106 + }; 107 + 108 + lportal14: lac-portal@E000 { 109 + compatible = "fsl,interlaken-lac-portal-v1.0"; 110 + reg = <0xE000 0x1000>; 111 + }; 112 + 113 + lportal15: lac-portal@F000 { 114 + compatible = "fsl,interlaken-lac-portal-v1.0"; 115 + reg = <0xF000 0x1000>; 116 + }; 117 + 118 + lportal16: lac-portal@10000 { 119 + compatible = "fsl,interlaken-lac-portal-v1.0"; 120 + reg = <0x10000 0x1000>; 121 + }; 122 + 123 + lportal17: lac-portal@11000 { 124 + compatible = "fsl,interlaken-lac-portal-v1.0"; 125 + reg = <0x11000 0x1000>; 126 + }; 127 + 128 + lportal18: lac-portal@1200 { 129 + compatible = "fsl,interlaken-lac-portal-v1.0"; 130 + reg = <0x12000 0x1000>; 131 + }; 132 + 133 + lportal19: lac-portal@13000 { 134 + compatible = "fsl,interlaken-lac-portal-v1.0"; 135 + reg = <0x13000 0x1000>; 136 + }; 137 + 138 + lportal20: lac-portal@14000 { 139 + compatible = "fsl,interlaken-lac-portal-v1.0"; 140 + reg = <0x14000 0x1000>; 141 + }; 142 + 143 + lportal21: lac-portal@15000 { 144 + compatible = "fsl,interlaken-lac-portal-v1.0"; 145 + reg = <0x15000 0x1000>; 146 + }; 147 + 148 + lportal22: lac-portal@16000 { 149 + compatible = "fsl,interlaken-lac-portal-v1.0"; 150 + reg = <0x16000 0x1000>; 151 + }; 152 + 153 + lportal23: lac-portal@17000 { 154 + compatible = "fsl,interlaken-lac-portal-v1.0"; 155 + reg = <0x17000 0x1000>; 156 + };
+45
arch/powerpc/boot/dts/fsl/interlaken-lac.dtsi
··· 1 + /* 2 + * T4 Interlaken Look-aside Controller (LAC) device tree stub 3 + * 4 + * Copyright 2012 Freescale Semiconductor Inc. 5 + * 6 + * Redistribution and use in source and binary forms, with or without 7 + * modification, are permitted provided that the following conditions are met: 8 + * * Redistributions of source code must retain the above copyright 9 + * notice, this list of conditions and the following disclaimer. 10 + * * Redistributions in binary form must reproduce the above copyright 11 + * notice, this list of conditions and the following disclaimer in the 12 + * documentation and/or other materials provided with the distribution. 13 + * * Neither the name of Freescale Semiconductor nor the 14 + * names of its contributors may be used to endorse or promote products 15 + * derived from this software without specific prior written permission. 16 + * 17 + * 18 + * ALTERNATIVELY, this software may be distributed under the terms of the 19 + * GNU General Public License ("GPL") as published by the Free Software 20 + * Foundation, either version 2 of that License or (at your option) any 21 + * later version. 22 + * 23 + * THIS SOFTWARE IS PROVIDED BY Freescale Semiconductor "AS IS" AND ANY 24 + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 25 + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 26 + * DISCLAIMED. IN NO EVENT SHALL Freescale Semiconductor BE LIABLE FOR ANY 27 + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 28 + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 30 + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 32 + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 + */ 34 + 35 + lac: lac@229000 { 36 + compatible = "fsl,interlaken-lac"; 37 + reg = <0x229000 0x1000>; 38 + interrupts = <16 2 1 18>; 39 + }; 40 + 41 + lac-hv@228000 { 42 + compatible = "fsl,interlaken-lac-hv"; 43 + reg = <0x228000 0x1000>; 44 + fsl,non-hv-node = <&lac>; 45 + };
+1
arch/powerpc/configs/mpc85xx_smp_defconfig
··· 131 131 CONFIG_FS_ENET=y 132 132 CONFIG_UCC_GETH=y 133 133 CONFIG_GIANFAR=y 134 + CONFIG_E1000E=y 134 135 CONFIG_MARVELL_PHY=y 135 136 CONFIG_DAVICOM_PHY=y 136 137 CONFIG_CICADA_PHY=y
+5
arch/powerpc/include/asm/mpic.h
··· 339 339 #endif 340 340 }; 341 341 342 + extern struct bus_type mpic_subsys; 343 + 342 344 /* 343 345 * MPIC flags (passed to mpic_alloc) 344 346 * ··· 394 392 395 393 #define MPIC_REGSET_STANDARD MPIC_REGSET(0) /* Original MPIC */ 396 394 #define MPIC_REGSET_TSI108 MPIC_REGSET(1) /* Tsi108/109 PIC */ 395 + 396 + /* Get the version of primary MPIC */ 397 + extern u32 fsl_mpic_primary_get_version(void); 397 398 398 399 /* Allocate the controller structure and setup the linux irq descs 399 400 * for the range if interrupts passed in. No HW initialization is
+46
arch/powerpc/include/asm/mpic_timer.h
··· 1 + /* 2 + * arch/powerpc/include/asm/mpic_timer.h 3 + * 4 + * Header file for Mpic Global Timer 5 + * 6 + * Copyright 2013 Freescale Semiconductor, Inc. 7 + * 8 + * Author: Wang Dongsheng <Dongsheng.Wang@freescale.com> 9 + * Li Yang <leoli@freescale.com> 10 + * 11 + * This program is free software; you can redistribute it and/or modify it 12 + * under the terms of the GNU General Public License as published by the 13 + * Free Software Foundation; either version 2 of the License, or (at your 14 + * option) any later version. 15 + */ 16 + 17 + #ifndef __MPIC_TIMER__ 18 + #define __MPIC_TIMER__ 19 + 20 + #include <linux/interrupt.h> 21 + #include <linux/time.h> 22 + 23 + struct mpic_timer { 24 + void *dev; 25 + struct cascade_priv *cascade_handle; 26 + unsigned int num; 27 + unsigned int irq; 28 + }; 29 + 30 + #ifdef CONFIG_MPIC_TIMER 31 + struct mpic_timer *mpic_request_timer(irq_handler_t fn, void *dev, 32 + const struct timeval *time); 33 + void mpic_start_timer(struct mpic_timer *handle); 34 + void mpic_stop_timer(struct mpic_timer *handle); 35 + void mpic_get_remain_time(struct mpic_timer *handle, struct timeval *time); 36 + void mpic_free_timer(struct mpic_timer *handle); 37 + #else 38 + struct mpic_timer *mpic_request_timer(irq_handler_t fn, void *dev, 39 + const struct timeval *time) { return NULL; } 40 + void mpic_start_timer(struct mpic_timer *handle) { } 41 + void mpic_stop_timer(struct mpic_timer *handle) { } 42 + void mpic_get_remain_time(struct mpic_timer *handle, struct timeval *time) { } 43 + void mpic_free_timer(struct mpic_timer *handle) { } 44 + #endif 45 + 46 + #endif
+1 -11
arch/powerpc/platforms/83xx/mcu_mpc8349emitx.c
··· 231 231 .id_table = mcu_ids, 232 232 }; 233 233 234 - static int __init mcu_init(void) 235 - { 236 - return i2c_add_driver(&mcu_driver); 237 - } 238 - module_init(mcu_init); 239 - 240 - static void __exit mcu_exit(void) 241 - { 242 - i2c_del_driver(&mcu_driver); 243 - } 244 - module_exit(mcu_exit); 234 + module_i2c_driver(mcu_driver); 245 235 246 236 MODULE_DESCRIPTION("Power Management and GPIO expander driver for " 247 237 "MPC8349E-mITX-compatible MCU");
-5
arch/powerpc/platforms/85xx/p5020_ds.c
··· 75 75 #ifdef CONFIG_PCI 76 76 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 77 77 #endif 78 - /* coreint doesn't play nice with lazy EE, use legacy mpic for now */ 79 - #ifdef CONFIG_PPC64 80 - .get_irq = mpic_get_irq, 81 - #else 82 78 .get_irq = mpic_get_coreint_irq, 83 - #endif 84 79 .restart = fsl_rstcr_restart, 85 80 .calibrate_decr = generic_calibrate_decr, 86 81 .progress = udbg_progress,
-5
arch/powerpc/platforms/85xx/p5040_ds.c
··· 66 66 #ifdef CONFIG_PCI 67 67 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 68 68 #endif 69 - /* coreint doesn't play nice with lazy EE, use legacy mpic for now */ 70 - #ifdef CONFIG_PPC64 71 - .get_irq = mpic_get_irq, 72 - #else 73 69 .get_irq = mpic_get_coreint_irq, 74 - #endif 75 70 .restart = fsl_rstcr_restart, 76 71 .calibrate_decr = generic_calibrate_decr, 77 72 .progress = udbg_progress,
-5
arch/powerpc/platforms/85xx/t4240_qds.c
··· 75 75 #ifdef CONFIG_PCI 76 76 .pcibios_fixup_bus = fsl_pcibios_fixup_bus, 77 77 #endif 78 - /* coreint doesn't play nice with lazy EE, use legacy mpic for now */ 79 - #ifdef CONFIG_PPC64 80 - .get_irq = mpic_get_irq, 81 - #else 82 78 .get_irq = mpic_get_coreint_irq, 83 - #endif 84 79 .restart = fsl_rstcr_restart, 85 80 .calibrate_decr = generic_calibrate_decr, 86 81 .progress = udbg_progress,
+3 -10
arch/powerpc/platforms/8xx/m8xx_setup.c
··· 219 219 220 220 static void cpm_cascade(unsigned int irq, struct irq_desc *desc) 221 221 { 222 - struct irq_chip *chip; 223 - int cascade_irq; 222 + struct irq_chip *chip = irq_desc_get_chip(desc); 223 + int cascade_irq = cpm_get_irq(); 224 224 225 - if ((cascade_irq = cpm_get_irq()) >= 0) { 226 - struct irq_desc *cdesc = irq_to_desc(cascade_irq); 227 - 225 + if (cascade_irq >= 0) 228 226 generic_handle_irq(cascade_irq); 229 227 230 - chip = irq_desc_get_chip(cdesc); 231 - chip->irq_eoi(&cdesc->irq_data); 232 - } 233 - 234 - chip = irq_desc_get_chip(desc); 235 228 chip->irq_eoi(&desc->irq_data); 236 229 } 237 230
+21
arch/powerpc/platforms/Kconfig
··· 86 86 bool 87 87 default n 88 88 89 + config MPIC_TIMER 90 + bool "MPIC Global Timer" 91 + depends on MPIC && FSL_SOC 92 + default n 93 + help 94 + The MPIC global timer is a hardware timer inside the 95 + Freescale PIC complying with OpenPIC standard. When the 96 + specified interval times out, the hardware timer generates 97 + an interrupt. The driver currently is only tested on fsl 98 + chip, but it can potentially support other global timers 99 + complying with the OpenPIC standard. 100 + 101 + config FSL_MPIC_TIMER_WAKEUP 102 + tristate "Freescale MPIC global timer wakeup driver" 103 + depends on FSL_SOC && MPIC_TIMER && PM 104 + default n 105 + help 106 + The driver provides a way to wake up the system by MPIC 107 + timer. 108 + e.g. "echo 5 > /sys/devices/system/mpic/timer_wakeup" 109 + 89 110 config PPC_EPAPR_HV_PIC 90 111 bool 91 112 default n
+2
arch/powerpc/sysdev/Makefile
··· 4 4 5 5 mpic-msi-obj-$(CONFIG_PCI_MSI) += mpic_msi.o mpic_u3msi.o mpic_pasemi_msi.o 6 6 obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) 7 + obj-$(CONFIG_MPIC_TIMER) += mpic_timer.o 8 + obj-$(CONFIG_FSL_MPIC_TIMER_WAKEUP) += fsl_mpic_timer_wakeup.o 7 9 mpic-msgr-obj-$(CONFIG_MPIC_MSGR) += mpic_msgr.o 8 10 obj-$(CONFIG_MPIC) += mpic.o $(mpic-msi-obj-y) $(mpic-msgr-obj-y) 9 11 obj-$(CONFIG_PPC_EPAPR_HV_PIC) += ehv_pic.o
+161
arch/powerpc/sysdev/fsl_mpic_timer_wakeup.c
··· 1 + /* 2 + * MPIC timer wakeup driver 3 + * 4 + * Copyright 2013 Freescale Semiconductor, Inc. 5 + * 6 + * This program is free software; you can redistribute it and/or modify it 7 + * under the terms of the GNU General Public License as published by the 8 + * Free Software Foundation; either version 2 of the License, or (at your 9 + * option) any later version. 10 + */ 11 + 12 + #include <linux/kernel.h> 13 + #include <linux/slab.h> 14 + #include <linux/errno.h> 15 + #include <linux/module.h> 16 + #include <linux/interrupt.h> 17 + #include <linux/device.h> 18 + 19 + #include <asm/mpic_timer.h> 20 + #include <asm/mpic.h> 21 + 22 + struct fsl_mpic_timer_wakeup { 23 + struct mpic_timer *timer; 24 + struct work_struct free_work; 25 + }; 26 + 27 + static struct fsl_mpic_timer_wakeup *fsl_wakeup; 28 + static DEFINE_MUTEX(sysfs_lock); 29 + 30 + static void fsl_free_resource(struct work_struct *ws) 31 + { 32 + struct fsl_mpic_timer_wakeup *wakeup = 33 + container_of(ws, struct fsl_mpic_timer_wakeup, free_work); 34 + 35 + mutex_lock(&sysfs_lock); 36 + 37 + if (wakeup->timer) { 38 + disable_irq_wake(wakeup->timer->irq); 39 + mpic_free_timer(wakeup->timer); 40 + } 41 + 42 + wakeup->timer = NULL; 43 + mutex_unlock(&sysfs_lock); 44 + } 45 + 46 + static irqreturn_t fsl_mpic_timer_irq(int irq, void *dev_id) 47 + { 48 + struct fsl_mpic_timer_wakeup *wakeup = dev_id; 49 + 50 + schedule_work(&wakeup->free_work); 51 + 52 + return wakeup->timer ? IRQ_HANDLED : IRQ_NONE; 53 + } 54 + 55 + static ssize_t fsl_timer_wakeup_show(struct device *dev, 56 + struct device_attribute *attr, 57 + char *buf) 58 + { 59 + struct timeval interval; 60 + int val = 0; 61 + 62 + mutex_lock(&sysfs_lock); 63 + if (fsl_wakeup->timer) { 64 + mpic_get_remain_time(fsl_wakeup->timer, &interval); 65 + val = interval.tv_sec + 1; 66 + } 67 + mutex_unlock(&sysfs_lock); 68 + 69 + return sprintf(buf, "%d\n", val); 70 + } 71 + 72 + static ssize_t fsl_timer_wakeup_store(struct device *dev, 73 + struct device_attribute *attr, 74 + const char *buf, 75 + size_t count) 76 + { 77 + struct timeval interval; 78 + int ret; 79 + 80 + interval.tv_usec = 0; 81 + if (kstrtol(buf, 0, &interval.tv_sec)) 82 + return -EINVAL; 83 + 84 + mutex_lock(&sysfs_lock); 85 + 86 + if (fsl_wakeup->timer) { 87 + disable_irq_wake(fsl_wakeup->timer->irq); 88 + mpic_free_timer(fsl_wakeup->timer); 89 + fsl_wakeup->timer = NULL; 90 + } 91 + 92 + if (!interval.tv_sec) { 93 + mutex_unlock(&sysfs_lock); 94 + return count; 95 + } 96 + 97 + fsl_wakeup->timer = mpic_request_timer(fsl_mpic_timer_irq, 98 + fsl_wakeup, &interval); 99 + if (!fsl_wakeup->timer) { 100 + mutex_unlock(&sysfs_lock); 101 + return -EINVAL; 102 + } 103 + 104 + ret = enable_irq_wake(fsl_wakeup->timer->irq); 105 + if (ret) { 106 + mpic_free_timer(fsl_wakeup->timer); 107 + fsl_wakeup->timer = NULL; 108 + mutex_unlock(&sysfs_lock); 109 + 110 + return ret; 111 + } 112 + 113 + mpic_start_timer(fsl_wakeup->timer); 114 + 115 + mutex_unlock(&sysfs_lock); 116 + 117 + return count; 118 + } 119 + 120 + static struct device_attribute mpic_attributes = __ATTR(timer_wakeup, 0644, 121 + fsl_timer_wakeup_show, fsl_timer_wakeup_store); 122 + 123 + static int __init fsl_wakeup_sys_init(void) 124 + { 125 + int ret; 126 + 127 + fsl_wakeup = kzalloc(sizeof(struct fsl_mpic_timer_wakeup), GFP_KERNEL); 128 + if (!fsl_wakeup) 129 + return -ENOMEM; 130 + 131 + INIT_WORK(&fsl_wakeup->free_work, fsl_free_resource); 132 + 133 + ret = device_create_file(mpic_subsys.dev_root, &mpic_attributes); 134 + if (ret) 135 + kfree(fsl_wakeup); 136 + 137 + return ret; 138 + } 139 + 140 + static void __exit fsl_wakeup_sys_exit(void) 141 + { 142 + device_remove_file(mpic_subsys.dev_root, &mpic_attributes); 143 + 144 + mutex_lock(&sysfs_lock); 145 + 146 + if (fsl_wakeup->timer) { 147 + disable_irq_wake(fsl_wakeup->timer->irq); 148 + mpic_free_timer(fsl_wakeup->timer); 149 + } 150 + 151 + kfree(fsl_wakeup); 152 + 153 + mutex_unlock(&sysfs_lock); 154 + } 155 + 156 + module_init(fsl_wakeup_sys_init); 157 + module_exit(fsl_wakeup_sys_exit); 158 + 159 + MODULE_DESCRIPTION("Freescale MPIC global timer wakeup driver"); 160 + MODULE_LICENSE("GPL v2"); 161 + MODULE_AUTHOR("Wang Dongsheng <dongsheng.wang@freescale.com>");
+51 -7
arch/powerpc/sysdev/mpic.c
··· 48 48 #define DBG(fmt...) 49 49 #endif 50 50 51 + struct bus_type mpic_subsys = { 52 + .name = "mpic", 53 + .dev_name = "mpic", 54 + }; 55 + EXPORT_SYMBOL_GPL(mpic_subsys); 56 + 51 57 static struct mpic *mpics; 52 58 static struct mpic *mpic_primary; 53 59 static DEFINE_RAW_SPINLOCK(mpic_lock); ··· 926 920 return IRQ_SET_MASK_OK_NOCOPY; 927 921 } 928 922 923 + static int mpic_irq_set_wake(struct irq_data *d, unsigned int on) 924 + { 925 + struct irq_desc *desc = container_of(d, struct irq_desc, irq_data); 926 + struct mpic *mpic = mpic_from_irq_data(d); 927 + 928 + if (!(mpic->flags & MPIC_FSL)) 929 + return -ENXIO; 930 + 931 + if (on) 932 + desc->action->flags |= IRQF_NO_SUSPEND; 933 + else 934 + desc->action->flags &= ~IRQF_NO_SUSPEND; 935 + 936 + return 0; 937 + } 938 + 929 939 void mpic_set_vector(unsigned int virq, unsigned int vector) 930 940 { 931 941 struct mpic *mpic = mpic_from_irq(virq); ··· 979 957 .irq_unmask = mpic_unmask_irq, 980 958 .irq_eoi = mpic_end_irq, 981 959 .irq_set_type = mpic_set_irq_type, 960 + .irq_set_wake = mpic_irq_set_wake, 982 961 }; 983 962 984 963 #ifdef CONFIG_SMP ··· 994 971 .irq_mask = mpic_mask_tm, 995 972 .irq_unmask = mpic_unmask_tm, 996 973 .irq_eoi = mpic_end_irq, 974 + .irq_set_wake = mpic_irq_set_wake, 997 975 }; 998 976 999 977 #ifdef CONFIG_MPIC_U3_HT_IRQS ··· 1197 1173 .xlate = mpic_host_xlate, 1198 1174 }; 1199 1175 1176 + static u32 fsl_mpic_get_version(struct mpic *mpic) 1177 + { 1178 + u32 brr1; 1179 + 1180 + if (!(mpic->flags & MPIC_FSL)) 1181 + return 0; 1182 + 1183 + brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs, 1184 + MPIC_FSL_BRR1); 1185 + 1186 + return brr1 & MPIC_FSL_BRR1_VER; 1187 + } 1188 + 1200 1189 /* 1201 1190 * Exported functions 1202 1191 */ 1192 + 1193 + u32 fsl_mpic_primary_get_version(void) 1194 + { 1195 + struct mpic *mpic = mpic_primary; 1196 + 1197 + if (mpic) 1198 + return fsl_mpic_get_version(mpic); 1199 + 1200 + return 0; 1201 + } 1203 1202 1204 1203 struct mpic * __init mpic_alloc(struct device_node *node, 1205 1204 phys_addr_t phys_addr, ··· 1370 1323 mpic_map(mpic, mpic->paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000); 1371 1324 1372 1325 if (mpic->flags & MPIC_FSL) { 1373 - u32 brr1; 1374 1326 int ret; 1375 1327 1376 1328 /* ··· 1380 1334 mpic_map(mpic, mpic->paddr, &mpic->thiscpuregs, 1381 1335 MPIC_CPU_THISBASE, 0x1000); 1382 1336 1383 - brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs, 1384 - MPIC_FSL_BRR1); 1385 - fsl_version = brr1 & MPIC_FSL_BRR1_VER; 1337 + fsl_version = fsl_mpic_get_version(mpic); 1386 1338 1387 1339 /* Error interrupt mask register (EIMR) is required for 1388 1340 * handling individual device error interrupts. EIMR ··· 1570 1526 mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0xf); 1571 1527 1572 1528 if (mpic->flags & MPIC_FSL) { 1573 - u32 brr1 = _mpic_read(mpic->reg_type, &mpic->thiscpuregs, 1574 - MPIC_FSL_BRR1); 1575 - u32 version = brr1 & MPIC_FSL_BRR1_VER; 1529 + u32 version = fsl_mpic_get_version(mpic); 1576 1530 1577 1531 /* 1578 1532 * Timer group B is present at the latest in MPIC 3.1 (e.g. ··· 2041 1999 static int mpic_init_sys(void) 2042 2000 { 2043 2001 register_syscore_ops(&mpic_syscore_ops); 2002 + subsys_system_register(&mpic_subsys, NULL); 2003 + 2044 2004 return 0; 2045 2005 } 2046 2006
+593
arch/powerpc/sysdev/mpic_timer.c
··· 1 + /* 2 + * MPIC timer driver 3 + * 4 + * Copyright 2013 Freescale Semiconductor, Inc. 5 + * Author: Dongsheng Wang <Dongsheng.Wang@freescale.com> 6 + * Li Yang <leoli@freescale.com> 7 + * 8 + * This program is free software; you can redistribute it and/or modify it 9 + * under the terms of the GNU General Public License as published by the 10 + * Free Software Foundation; either version 2 of the License, or (at your 11 + * option) any later version. 12 + */ 13 + 14 + #include <linux/kernel.h> 15 + #include <linux/init.h> 16 + #include <linux/module.h> 17 + #include <linux/errno.h> 18 + #include <linux/mm.h> 19 + #include <linux/interrupt.h> 20 + #include <linux/slab.h> 21 + #include <linux/of.h> 22 + #include <linux/of_device.h> 23 + #include <linux/syscore_ops.h> 24 + #include <sysdev/fsl_soc.h> 25 + #include <asm/io.h> 26 + 27 + #include <asm/mpic_timer.h> 28 + 29 + #define FSL_GLOBAL_TIMER 0x1 30 + 31 + /* Clock Ratio 32 + * Divide by 64 0x00000300 33 + * Divide by 32 0x00000200 34 + * Divide by 16 0x00000100 35 + * Divide by 8 0x00000000 (Hardware default div) 36 + */ 37 + #define MPIC_TIMER_TCR_CLKDIV 0x00000300 38 + 39 + #define MPIC_TIMER_TCR_ROVR_OFFSET 24 40 + 41 + #define TIMER_STOP 0x80000000 42 + #define TIMERS_PER_GROUP 4 43 + #define MAX_TICKS (~0U >> 1) 44 + #define MAX_TICKS_CASCADE (~0U) 45 + #define TIMER_OFFSET(num) (1 << (TIMERS_PER_GROUP - 1 - num)) 46 + 47 + /* tv_usec should be less than ONE_SECOND, otherwise use tv_sec */ 48 + #define ONE_SECOND 1000000 49 + 50 + struct timer_regs { 51 + u32 gtccr; 52 + u32 res0[3]; 53 + u32 gtbcr; 54 + u32 res1[3]; 55 + u32 gtvpr; 56 + u32 res2[3]; 57 + u32 gtdr; 58 + u32 res3[3]; 59 + }; 60 + 61 + struct cascade_priv { 62 + u32 tcr_value; /* TCR register: CASC & ROVR value */ 63 + unsigned int cascade_map; /* cascade map */ 64 + unsigned int timer_num; /* cascade control timer */ 65 + }; 66 + 67 + struct timer_group_priv { 68 + struct timer_regs __iomem *regs; 69 + struct mpic_timer timer[TIMERS_PER_GROUP]; 70 + struct list_head node; 71 + unsigned int timerfreq; 72 + unsigned int idle; 73 + unsigned int flags; 74 + spinlock_t lock; 75 + void __iomem *group_tcr; 76 + }; 77 + 78 + static struct cascade_priv cascade_timer[] = { 79 + /* cascade timer 0 and 1 */ 80 + {0x1, 0xc, 0x1}, 81 + /* cascade timer 1 and 2 */ 82 + {0x2, 0x6, 0x2}, 83 + /* cascade timer 2 and 3 */ 84 + {0x4, 0x3, 0x3} 85 + }; 86 + 87 + static LIST_HEAD(timer_group_list); 88 + 89 + static void convert_ticks_to_time(struct timer_group_priv *priv, 90 + const u64 ticks, struct timeval *time) 91 + { 92 + u64 tmp_sec; 93 + 94 + time->tv_sec = (__kernel_time_t)div_u64(ticks, priv->timerfreq); 95 + tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq; 96 + 97 + time->tv_usec = (__kernel_suseconds_t) 98 + div_u64((ticks - tmp_sec) * 1000000, priv->timerfreq); 99 + 100 + return; 101 + } 102 + 103 + /* the time set by the user is converted to "ticks" */ 104 + static int convert_time_to_ticks(struct timer_group_priv *priv, 105 + const struct timeval *time, u64 *ticks) 106 + { 107 + u64 max_value; /* prevent u64 overflow */ 108 + u64 tmp = 0; 109 + 110 + u64 tmp_sec; 111 + u64 tmp_ms; 112 + u64 tmp_us; 113 + 114 + max_value = div_u64(ULLONG_MAX, priv->timerfreq); 115 + 116 + if (time->tv_sec > max_value || 117 + (time->tv_sec == max_value && time->tv_usec > 0)) 118 + return -EINVAL; 119 + 120 + tmp_sec = (u64)time->tv_sec * (u64)priv->timerfreq; 121 + tmp += tmp_sec; 122 + 123 + tmp_ms = time->tv_usec / 1000; 124 + tmp_ms = div_u64((u64)tmp_ms * (u64)priv->timerfreq, 1000); 125 + tmp += tmp_ms; 126 + 127 + tmp_us = time->tv_usec % 1000; 128 + tmp_us = div_u64((u64)tmp_us * (u64)priv->timerfreq, 1000000); 129 + tmp += tmp_us; 130 + 131 + *ticks = tmp; 132 + 133 + return 0; 134 + } 135 + 136 + /* detect whether there is a cascade timer available */ 137 + static struct mpic_timer *detect_idle_cascade_timer( 138 + struct timer_group_priv *priv) 139 + { 140 + struct cascade_priv *casc_priv; 141 + unsigned int map; 142 + unsigned int array_size = ARRAY_SIZE(cascade_timer); 143 + unsigned int num; 144 + unsigned int i; 145 + unsigned long flags; 146 + 147 + casc_priv = cascade_timer; 148 + for (i = 0; i < array_size; i++) { 149 + spin_lock_irqsave(&priv->lock, flags); 150 + map = casc_priv->cascade_map & priv->idle; 151 + if (map == casc_priv->cascade_map) { 152 + num = casc_priv->timer_num; 153 + priv->timer[num].cascade_handle = casc_priv; 154 + 155 + /* set timer busy */ 156 + priv->idle &= ~casc_priv->cascade_map; 157 + spin_unlock_irqrestore(&priv->lock, flags); 158 + return &priv->timer[num]; 159 + } 160 + spin_unlock_irqrestore(&priv->lock, flags); 161 + casc_priv++; 162 + } 163 + 164 + return NULL; 165 + } 166 + 167 + static int set_cascade_timer(struct timer_group_priv *priv, u64 ticks, 168 + unsigned int num) 169 + { 170 + struct cascade_priv *casc_priv; 171 + u32 tcr; 172 + u32 tmp_ticks; 173 + u32 rem_ticks; 174 + 175 + /* set group tcr reg for cascade */ 176 + casc_priv = priv->timer[num].cascade_handle; 177 + if (!casc_priv) 178 + return -EINVAL; 179 + 180 + tcr = casc_priv->tcr_value | 181 + (casc_priv->tcr_value << MPIC_TIMER_TCR_ROVR_OFFSET); 182 + setbits32(priv->group_tcr, tcr); 183 + 184 + tmp_ticks = div_u64_rem(ticks, MAX_TICKS_CASCADE, &rem_ticks); 185 + 186 + out_be32(&priv->regs[num].gtccr, 0); 187 + out_be32(&priv->regs[num].gtbcr, tmp_ticks | TIMER_STOP); 188 + 189 + out_be32(&priv->regs[num - 1].gtccr, 0); 190 + out_be32(&priv->regs[num - 1].gtbcr, rem_ticks); 191 + 192 + return 0; 193 + } 194 + 195 + static struct mpic_timer *get_cascade_timer(struct timer_group_priv *priv, 196 + u64 ticks) 197 + { 198 + struct mpic_timer *allocated_timer; 199 + 200 + /* Two cascade timers: Support the maximum time */ 201 + const u64 max_ticks = (u64)MAX_TICKS * (u64)MAX_TICKS_CASCADE; 202 + int ret; 203 + 204 + if (ticks > max_ticks) 205 + return NULL; 206 + 207 + /* detect idle timer */ 208 + allocated_timer = detect_idle_cascade_timer(priv); 209 + if (!allocated_timer) 210 + return NULL; 211 + 212 + /* set ticks to timer */ 213 + ret = set_cascade_timer(priv, ticks, allocated_timer->num); 214 + if (ret < 0) 215 + return NULL; 216 + 217 + return allocated_timer; 218 + } 219 + 220 + static struct mpic_timer *get_timer(const struct timeval *time) 221 + { 222 + struct timer_group_priv *priv; 223 + struct mpic_timer *timer; 224 + 225 + u64 ticks; 226 + unsigned int num; 227 + unsigned int i; 228 + unsigned long flags; 229 + int ret; 230 + 231 + list_for_each_entry(priv, &timer_group_list, node) { 232 + ret = convert_time_to_ticks(priv, time, &ticks); 233 + if (ret < 0) 234 + return NULL; 235 + 236 + if (ticks > MAX_TICKS) { 237 + if (!(priv->flags & FSL_GLOBAL_TIMER)) 238 + return NULL; 239 + 240 + timer = get_cascade_timer(priv, ticks); 241 + if (!timer) 242 + continue; 243 + 244 + return timer; 245 + } 246 + 247 + for (i = 0; i < TIMERS_PER_GROUP; i++) { 248 + /* one timer: Reverse allocation */ 249 + num = TIMERS_PER_GROUP - 1 - i; 250 + spin_lock_irqsave(&priv->lock, flags); 251 + if (priv->idle & (1 << i)) { 252 + /* set timer busy */ 253 + priv->idle &= ~(1 << i); 254 + /* set ticks & stop timer */ 255 + out_be32(&priv->regs[num].gtbcr, 256 + ticks | TIMER_STOP); 257 + out_be32(&priv->regs[num].gtccr, 0); 258 + priv->timer[num].cascade_handle = NULL; 259 + spin_unlock_irqrestore(&priv->lock, flags); 260 + return &priv->timer[num]; 261 + } 262 + spin_unlock_irqrestore(&priv->lock, flags); 263 + } 264 + } 265 + 266 + return NULL; 267 + } 268 + 269 + /** 270 + * mpic_start_timer - start hardware timer 271 + * @handle: the timer to be started. 272 + * 273 + * It will do ->fn(->dev) callback from the hardware interrupt at 274 + * the ->timeval point in the future. 275 + */ 276 + void mpic_start_timer(struct mpic_timer *handle) 277 + { 278 + struct timer_group_priv *priv = container_of(handle, 279 + struct timer_group_priv, timer[handle->num]); 280 + 281 + clrbits32(&priv->regs[handle->num].gtbcr, TIMER_STOP); 282 + } 283 + EXPORT_SYMBOL(mpic_start_timer); 284 + 285 + /** 286 + * mpic_stop_timer - stop hardware timer 287 + * @handle: the timer to be stoped 288 + * 289 + * The timer periodically generates an interrupt. Unless user stops the timer. 290 + */ 291 + void mpic_stop_timer(struct mpic_timer *handle) 292 + { 293 + struct timer_group_priv *priv = container_of(handle, 294 + struct timer_group_priv, timer[handle->num]); 295 + struct cascade_priv *casc_priv; 296 + 297 + setbits32(&priv->regs[handle->num].gtbcr, TIMER_STOP); 298 + 299 + casc_priv = priv->timer[handle->num].cascade_handle; 300 + if (casc_priv) { 301 + out_be32(&priv->regs[handle->num].gtccr, 0); 302 + out_be32(&priv->regs[handle->num - 1].gtccr, 0); 303 + } else { 304 + out_be32(&priv->regs[handle->num].gtccr, 0); 305 + } 306 + } 307 + EXPORT_SYMBOL(mpic_stop_timer); 308 + 309 + /** 310 + * mpic_get_remain_time - get timer time 311 + * @handle: the timer to be selected. 312 + * @time: time for timer 313 + * 314 + * Query timer remaining time. 315 + */ 316 + void mpic_get_remain_time(struct mpic_timer *handle, struct timeval *time) 317 + { 318 + struct timer_group_priv *priv = container_of(handle, 319 + struct timer_group_priv, timer[handle->num]); 320 + struct cascade_priv *casc_priv; 321 + 322 + u64 ticks; 323 + u32 tmp_ticks; 324 + 325 + casc_priv = priv->timer[handle->num].cascade_handle; 326 + if (casc_priv) { 327 + tmp_ticks = in_be32(&priv->regs[handle->num].gtccr); 328 + ticks = ((u64)tmp_ticks & UINT_MAX) * (u64)MAX_TICKS_CASCADE; 329 + tmp_ticks = in_be32(&priv->regs[handle->num - 1].gtccr); 330 + ticks += tmp_ticks; 331 + } else { 332 + ticks = in_be32(&priv->regs[handle->num].gtccr); 333 + } 334 + 335 + convert_ticks_to_time(priv, ticks, time); 336 + } 337 + EXPORT_SYMBOL(mpic_get_remain_time); 338 + 339 + /** 340 + * mpic_free_timer - free hardware timer 341 + * @handle: the timer to be removed. 342 + * 343 + * Free the timer. 344 + * 345 + * Note: can not be used in interrupt context. 346 + */ 347 + void mpic_free_timer(struct mpic_timer *handle) 348 + { 349 + struct timer_group_priv *priv = container_of(handle, 350 + struct timer_group_priv, timer[handle->num]); 351 + 352 + struct cascade_priv *casc_priv; 353 + unsigned long flags; 354 + 355 + mpic_stop_timer(handle); 356 + 357 + casc_priv = priv->timer[handle->num].cascade_handle; 358 + 359 + free_irq(priv->timer[handle->num].irq, priv->timer[handle->num].dev); 360 + 361 + spin_lock_irqsave(&priv->lock, flags); 362 + if (casc_priv) { 363 + u32 tcr; 364 + tcr = casc_priv->tcr_value | (casc_priv->tcr_value << 365 + MPIC_TIMER_TCR_ROVR_OFFSET); 366 + clrbits32(priv->group_tcr, tcr); 367 + priv->idle |= casc_priv->cascade_map; 368 + priv->timer[handle->num].cascade_handle = NULL; 369 + } else { 370 + priv->idle |= TIMER_OFFSET(handle->num); 371 + } 372 + spin_unlock_irqrestore(&priv->lock, flags); 373 + } 374 + EXPORT_SYMBOL(mpic_free_timer); 375 + 376 + /** 377 + * mpic_request_timer - get a hardware timer 378 + * @fn: interrupt handler function 379 + * @dev: callback function of the data 380 + * @time: time for timer 381 + * 382 + * This executes the "request_irq", returning NULL 383 + * else "handle" on success. 384 + */ 385 + struct mpic_timer *mpic_request_timer(irq_handler_t fn, void *dev, 386 + const struct timeval *time) 387 + { 388 + struct mpic_timer *allocated_timer; 389 + int ret; 390 + 391 + if (list_empty(&timer_group_list)) 392 + return NULL; 393 + 394 + if (!(time->tv_sec + time->tv_usec) || 395 + time->tv_sec < 0 || time->tv_usec < 0) 396 + return NULL; 397 + 398 + if (time->tv_usec > ONE_SECOND) 399 + return NULL; 400 + 401 + allocated_timer = get_timer(time); 402 + if (!allocated_timer) 403 + return NULL; 404 + 405 + ret = request_irq(allocated_timer->irq, fn, 406 + IRQF_TRIGGER_LOW, "global-timer", dev); 407 + if (ret) { 408 + mpic_free_timer(allocated_timer); 409 + return NULL; 410 + } 411 + 412 + allocated_timer->dev = dev; 413 + 414 + return allocated_timer; 415 + } 416 + EXPORT_SYMBOL(mpic_request_timer); 417 + 418 + static int timer_group_get_freq(struct device_node *np, 419 + struct timer_group_priv *priv) 420 + { 421 + u32 div; 422 + 423 + if (priv->flags & FSL_GLOBAL_TIMER) { 424 + struct device_node *dn; 425 + 426 + dn = of_find_compatible_node(NULL, NULL, "fsl,mpic"); 427 + if (dn) { 428 + of_property_read_u32(dn, "clock-frequency", 429 + &priv->timerfreq); 430 + of_node_put(dn); 431 + } 432 + } 433 + 434 + if (priv->timerfreq <= 0) 435 + return -EINVAL; 436 + 437 + if (priv->flags & FSL_GLOBAL_TIMER) { 438 + div = (1 << (MPIC_TIMER_TCR_CLKDIV >> 8)) * 8; 439 + priv->timerfreq /= div; 440 + } 441 + 442 + return 0; 443 + } 444 + 445 + static int timer_group_get_irq(struct device_node *np, 446 + struct timer_group_priv *priv) 447 + { 448 + const u32 all_timer[] = { 0, TIMERS_PER_GROUP }; 449 + const u32 *p; 450 + u32 offset; 451 + u32 count; 452 + 453 + unsigned int i; 454 + unsigned int j; 455 + unsigned int irq_index = 0; 456 + unsigned int irq; 457 + int len; 458 + 459 + p = of_get_property(np, "fsl,available-ranges", &len); 460 + if (p && len % (2 * sizeof(u32)) != 0) { 461 + pr_err("%s: malformed available-ranges property.\n", 462 + np->full_name); 463 + return -EINVAL; 464 + } 465 + 466 + if (!p) { 467 + p = all_timer; 468 + len = sizeof(all_timer); 469 + } 470 + 471 + len /= 2 * sizeof(u32); 472 + 473 + for (i = 0; i < len; i++) { 474 + offset = p[i * 2]; 475 + count = p[i * 2 + 1]; 476 + for (j = 0; j < count; j++) { 477 + irq = irq_of_parse_and_map(np, irq_index); 478 + if (!irq) { 479 + pr_err("%s: irq parse and map failed.\n", 480 + np->full_name); 481 + return -EINVAL; 482 + } 483 + 484 + /* Set timer idle */ 485 + priv->idle |= TIMER_OFFSET((offset + j)); 486 + priv->timer[offset + j].irq = irq; 487 + priv->timer[offset + j].num = offset + j; 488 + irq_index++; 489 + } 490 + } 491 + 492 + return 0; 493 + } 494 + 495 + static void timer_group_init(struct device_node *np) 496 + { 497 + struct timer_group_priv *priv; 498 + unsigned int i = 0; 499 + int ret; 500 + 501 + priv = kzalloc(sizeof(struct timer_group_priv), GFP_KERNEL); 502 + if (!priv) { 503 + pr_err("%s: cannot allocate memory for group.\n", 504 + np->full_name); 505 + return; 506 + } 507 + 508 + if (of_device_is_compatible(np, "fsl,mpic-global-timer")) 509 + priv->flags |= FSL_GLOBAL_TIMER; 510 + 511 + priv->regs = of_iomap(np, i++); 512 + if (!priv->regs) { 513 + pr_err("%s: cannot ioremap timer register address.\n", 514 + np->full_name); 515 + goto out; 516 + } 517 + 518 + if (priv->flags & FSL_GLOBAL_TIMER) { 519 + priv->group_tcr = of_iomap(np, i++); 520 + if (!priv->group_tcr) { 521 + pr_err("%s: cannot ioremap tcr address.\n", 522 + np->full_name); 523 + goto out; 524 + } 525 + } 526 + 527 + ret = timer_group_get_freq(np, priv); 528 + if (ret < 0) { 529 + pr_err("%s: cannot get timer frequency.\n", np->full_name); 530 + goto out; 531 + } 532 + 533 + ret = timer_group_get_irq(np, priv); 534 + if (ret < 0) { 535 + pr_err("%s: cannot get timer irqs.\n", np->full_name); 536 + goto out; 537 + } 538 + 539 + spin_lock_init(&priv->lock); 540 + 541 + /* Init FSL timer hardware */ 542 + if (priv->flags & FSL_GLOBAL_TIMER) 543 + setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV); 544 + 545 + list_add_tail(&priv->node, &timer_group_list); 546 + 547 + return; 548 + 549 + out: 550 + if (priv->regs) 551 + iounmap(priv->regs); 552 + 553 + if (priv->group_tcr) 554 + iounmap(priv->group_tcr); 555 + 556 + kfree(priv); 557 + } 558 + 559 + static void mpic_timer_resume(void) 560 + { 561 + struct timer_group_priv *priv; 562 + 563 + list_for_each_entry(priv, &timer_group_list, node) { 564 + /* Init FSL timer hardware */ 565 + if (priv->flags & FSL_GLOBAL_TIMER) 566 + setbits32(priv->group_tcr, MPIC_TIMER_TCR_CLKDIV); 567 + } 568 + } 569 + 570 + static const struct of_device_id mpic_timer_ids[] = { 571 + { .compatible = "fsl,mpic-global-timer", }, 572 + {}, 573 + }; 574 + 575 + static struct syscore_ops mpic_timer_syscore_ops = { 576 + .resume = mpic_timer_resume, 577 + }; 578 + 579 + static int __init mpic_timer_init(void) 580 + { 581 + struct device_node *np = NULL; 582 + 583 + for_each_matching_node(np, mpic_timer_ids) 584 + timer_group_init(np); 585 + 586 + register_syscore_ops(&mpic_timer_syscore_ops); 587 + 588 + if (list_empty(&timer_group_list)) 589 + return -ENODEV; 590 + 591 + return 0; 592 + } 593 + subsys_initcall(mpic_timer_init);
+8
drivers/i2c/busses/i2c-cpm.c
··· 338 338 tptr = 0; 339 339 rptr = 0; 340 340 341 + /* 342 + * If there was a collision in the last i2c transaction, 343 + * Set I2COM_MASTER as it was cleared during collision. 344 + */ 345 + if (in_be16(&tbdf->cbd_sc) & BD_SC_CL) { 346 + out_8(&cpm->i2c_reg->i2com, I2COM_MASTER); 347 + } 348 + 341 349 while (tptr < num) { 342 350 pmsg = &msgs[tptr]; 343 351 dev_dbg(&adap->dev, "R: %d T: %d\n", rptr, tptr);
+8
drivers/watchdog/booke_wdt.c
··· 138 138 val &= ~WDTP_MASK; 139 139 val |= (TCR_WIE|TCR_WRC(WRC_CHIP)|WDTP(booke_wdt_period)); 140 140 141 + #ifdef CONFIG_PPC_BOOK3E_64 142 + /* 143 + * Crit ints are currently broken on PPC64 Book-E, so 144 + * just disable them for now. 145 + */ 146 + val &= ~TCR_WIE; 147 + #endif 148 + 141 149 mtspr(SPRN_TCR, val); 142 150 } 143 151