├── .gitignore ├── COPYING ├── Makefile ├── README └── turbomem.c /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.o.d 3 | *.cmd 4 | *.ko 5 | Module.symvers 6 | modules.order 7 | .tmp_versions/ 8 | *.mod.c 9 | *.mod 10 | .*.swp 11 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | GNU GENERAL PUBLIC LICENSE 2 | Version 2, June 1991 3 | 4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc. 5 | 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 6 | Everyone is permitted to copy and distribute verbatim copies 7 | of this license document, but changing it is not allowed. 8 | 9 | Preamble 10 | 11 | The licenses for most software are designed to take away your 12 | freedom to share and change it. By contrast, the GNU General Public 13 | License is intended to guarantee your freedom to share and change free 14 | software--to make sure the software is free for all its users. This 15 | General Public License applies to most of the Free Software 16 | Foundation's software and to any other program whose authors commit to 17 | using it. (Some other Free Software Foundation software is covered by 18 | the GNU Library General Public License instead.) You can apply it to 19 | your programs, too. 20 | 21 | When we speak of free software, we are referring to freedom, not 22 | price. Our General Public Licenses are designed to make sure that you 23 | have the freedom to distribute copies of free software (and charge for 24 | this service if you wish), that you receive source code or can get it 25 | if you want it, that you can change the software or use pieces of it 26 | in new free programs; and that you know you can do these things. 27 | 28 | To protect your rights, we need to make restrictions that forbid 29 | anyone to deny you these rights or to ask you to surrender the rights. 30 | These restrictions translate to certain responsibilities for you if you 31 | distribute copies of the software, or if you modify it. 32 | 33 | For example, if you distribute copies of such a program, whether 34 | gratis or for a fee, you must give the recipients all the rights that 35 | you have. You must make sure that they, too, receive or can get the 36 | source code. And you must show them these terms so they know their 37 | rights. 38 | 39 | We protect your rights with two steps: (1) copyright the software, and 40 | (2) offer you this license which gives you legal permission to copy, 41 | distribute and/or modify the software. 42 | 43 | Also, for each author's protection and ours, we want to make certain 44 | that everyone understands that there is no warranty for this free 45 | software. If the software is modified by someone else and passed on, we 46 | want its recipients to know that what they have is not the original, so 47 | that any problems introduced by others will not reflect on the original 48 | authors' reputations. 49 | 50 | Finally, any free program is threatened constantly by software 51 | patents. We wish to avoid the danger that redistributors of a free 52 | program will individually obtain patent licenses, in effect making the 53 | program proprietary. To prevent this, we have made it clear that any 54 | patent must be licensed for everyone's free use or not licensed at all. 55 | 56 | The precise terms and conditions for copying, distribution and 57 | modification follow. 58 | 59 | GNU GENERAL PUBLIC LICENSE 60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 61 | 62 | 0. This License applies to any program or other work which contains 63 | a notice placed by the copyright holder saying it may be distributed 64 | under the terms of this General Public License. The "Program", below, 65 | refers to any such program or work, and a "work based on the Program" 66 | means either the Program or any derivative work under copyright law: 67 | that is to say, a work containing the Program or a portion of it, 68 | either verbatim or with modifications and/or translated into another 69 | language. (Hereinafter, translation is included without limitation in 70 | the term "modification".) Each licensee is addressed as "you". 71 | 72 | Activities other than copying, distribution and modification are not 73 | covered by this License; they are outside its scope. The act of 74 | running the Program is not restricted, and the output from the Program 75 | is covered only if its contents constitute a work based on the 76 | Program (independent of having been made by running the Program). 77 | Whether that is true depends on what the Program does. 78 | 79 | 1. You may copy and distribute verbatim copies of the Program's 80 | source code as you receive it, in any medium, provided that you 81 | conspicuously and appropriately publish on each copy an appropriate 82 | copyright notice and disclaimer of warranty; keep intact all the 83 | notices that refer to this License and to the absence of any warranty; 84 | and give any other recipients of the Program a copy of this License 85 | along with the Program. 86 | 87 | You may charge a fee for the physical act of transferring a copy, and 88 | you may at your option offer warranty protection in exchange for a fee. 89 | 90 | 2. You may modify your copy or copies of the Program or any portion 91 | of it, thus forming a work based on the Program, and copy and 92 | distribute such modifications or work under the terms of Section 1 93 | above, provided that you also meet all of these conditions: 94 | 95 | a) You must cause the modified files to carry prominent notices 96 | stating that you changed the files and the date of any change. 97 | 98 | b) You must cause any work that you distribute or publish, that in 99 | whole or in part contains or is derived from the Program or any 100 | part thereof, to be licensed as a whole at no charge to all third 101 | parties under the terms of this License. 102 | 103 | c) If the modified program normally reads commands interactively 104 | when run, you must cause it, when started running for such 105 | interactive use in the most ordinary way, to print or display an 106 | announcement including an appropriate copyright notice and a 107 | notice that there is no warranty (or else, saying that you provide 108 | a warranty) and that users may redistribute the program under 109 | these conditions, and telling the user how to view a copy of this 110 | License. (Exception: if the Program itself is interactive but 111 | does not normally print such an announcement, your work based on 112 | the Program is not required to print an announcement.) 113 | 114 | These requirements apply to the modified work as a whole. If 115 | identifiable sections of that work are not derived from the Program, 116 | and can be reasonably considered independent and separate works in 117 | themselves, then this License, and its terms, do not apply to those 118 | sections when you distribute them as separate works. But when you 119 | distribute the same sections as part of a whole which is a work based 120 | on the Program, the distribution of the whole must be on the terms of 121 | this License, whose permissions for other licensees extend to the 122 | entire whole, and thus to each and every part regardless of who wrote it. 123 | 124 | Thus, it is not the intent of this section to claim rights or contest 125 | your rights to work written entirely by you; rather, the intent is to 126 | exercise the right to control the distribution of derivative or 127 | collective works based on the Program. 128 | 129 | In addition, mere aggregation of another work not based on the Program 130 | with the Program (or with a work based on the Program) on a volume of 131 | a storage or distribution medium does not bring the other work under 132 | the scope of this License. 133 | 134 | 3. You may copy and distribute the Program (or a work based on it, 135 | under Section 2) in object code or executable form under the terms of 136 | Sections 1 and 2 above provided that you also do one of the following: 137 | 138 | a) Accompany it with the complete corresponding machine-readable 139 | source code, which must be distributed under the terms of Sections 140 | 1 and 2 above on a medium customarily used for software interchange; or, 141 | 142 | b) Accompany it with a written offer, valid for at least three 143 | years, to give any third party, for a charge no more than your 144 | cost of physically performing source distribution, a complete 145 | machine-readable copy of the corresponding source code, to be 146 | distributed under the terms of Sections 1 and 2 above on a medium 147 | customarily used for software interchange; or, 148 | 149 | c) Accompany it with the information you received as to the offer 150 | to distribute corresponding source code. (This alternative is 151 | allowed only for noncommercial distribution and only if you 152 | received the program in object code or executable form with such 153 | an offer, in accord with Subsection b above.) 154 | 155 | The source code for a work means the preferred form of the work for 156 | making modifications to it. For an executable work, complete source 157 | code means all the source code for all modules it contains, plus any 158 | associated interface definition files, plus the scripts used to 159 | control compilation and installation of the executable. However, as a 160 | special exception, the source code distributed need not include 161 | anything that is normally distributed (in either source or binary 162 | form) with the major components (compiler, kernel, and so on) of the 163 | operating system on which the executable runs, unless that component 164 | itself accompanies the executable. 165 | 166 | If distribution of executable or object code is made by offering 167 | access to copy from a designated place, then offering equivalent 168 | access to copy the source code from the same place counts as 169 | distribution of the source code, even though third parties are not 170 | compelled to copy the source along with the object code. 171 | 172 | 4. You may not copy, modify, sublicense, or distribute the Program 173 | except as expressly provided under this License. Any attempt 174 | otherwise to copy, modify, sublicense or distribute the Program is 175 | void, and will automatically terminate your rights under this License. 176 | However, parties who have received copies, or rights, from you under 177 | this License will not have their licenses terminated so long as such 178 | parties remain in full compliance. 179 | 180 | 5. You are not required to accept this License, since you have not 181 | signed it. However, nothing else grants you permission to modify or 182 | distribute the Program or its derivative works. These actions are 183 | prohibited by law if you do not accept this License. Therefore, by 184 | modifying or distributing the Program (or any work based on the 185 | Program), you indicate your acceptance of this License to do so, and 186 | all its terms and conditions for copying, distributing or modifying 187 | the Program or works based on it. 188 | 189 | 6. Each time you redistribute the Program (or any work based on the 190 | Program), the recipient automatically receives a license from the 191 | original licensor to copy, distribute or modify the Program subject to 192 | these terms and conditions. You may not impose any further 193 | restrictions on the recipients' exercise of the rights granted herein. 194 | You are not responsible for enforcing compliance by third parties to 195 | this License. 196 | 197 | 7. If, as a consequence of a court judgment or allegation of patent 198 | infringement or for any other reason (not limited to patent issues), 199 | conditions are imposed on you (whether by court order, agreement or 200 | otherwise) that contradict the conditions of this License, they do not 201 | excuse you from the conditions of this License. If you cannot 202 | distribute so as to satisfy simultaneously your obligations under this 203 | License and any other pertinent obligations, then as a consequence you 204 | may not distribute the Program at all. For example, if a patent 205 | license would not permit royalty-free redistribution of the Program by 206 | all those who receive copies directly or indirectly through you, then 207 | the only way you could satisfy both it and this License would be to 208 | refrain entirely from distribution of the Program. 209 | 210 | If any portion of this section is held invalid or unenforceable under 211 | any particular circumstance, the balance of the section is intended to 212 | apply and the section as a whole is intended to apply in other 213 | circumstances. 214 | 215 | It is not the purpose of this section to induce you to infringe any 216 | patents or other property right claims or to contest validity of any 217 | such claims; this section has the sole purpose of protecting the 218 | integrity of the free software distribution system, which is 219 | implemented by public license practices. Many people have made 220 | generous contributions to the wide range of software distributed 221 | through that system in reliance on consistent application of that 222 | system; it is up to the author/donor to decide if he or she is willing 223 | to distribute software through any other system and a licensee cannot 224 | impose that choice. 225 | 226 | This section is intended to make thoroughly clear what is believed to 227 | be a consequence of the rest of this License. 228 | 229 | 8. If the distribution and/or use of the Program is restricted in 230 | certain countries either by patents or by copyrighted interfaces, the 231 | original copyright holder who places the Program under this License 232 | may add an explicit geographical distribution limitation excluding 233 | those countries, so that distribution is permitted only in or among 234 | countries not thus excluded. In such case, this License incorporates 235 | the limitation as if written in the body of this License. 236 | 237 | 9. The Free Software Foundation may publish revised and/or new versions 238 | of the General Public License from time to time. Such new versions will 239 | be similar in spirit to the present version, but may differ in detail to 240 | address new problems or concerns. 241 | 242 | Each version is given a distinguishing version number. If the Program 243 | specifies a version number of this License which applies to it and "any 244 | later version", you have the option of following the terms and conditions 245 | either of that version or of any later version published by the Free 246 | Software Foundation. If the Program does not specify a version number of 247 | this License, you may choose any version ever published by the Free Software 248 | Foundation. 249 | 250 | 10. If you wish to incorporate parts of the Program into other free 251 | programs whose distribution conditions are different, write to the author 252 | to ask for permission. For software which is copyrighted by the Free 253 | Software Foundation, write to the Free Software Foundation; we sometimes 254 | make exceptions for this. Our decision will be guided by the two goals 255 | of preserving the free status of all derivatives of our free software and 256 | of promoting the sharing and reuse of software generally. 257 | 258 | NO WARRANTY 259 | 260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN 262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS 266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE 267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 268 | REPAIR OR CORRECTION. 269 | 270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 278 | POSSIBILITY OF SUCH DAMAGES. 279 | 280 | END OF TERMS AND CONDITIONS 281 | 282 | How to Apply These Terms to Your New Programs 283 | 284 | If you develop a new program, and you want it to be of the greatest 285 | possible use to the public, the best way to achieve this is to make it 286 | free software which everyone can redistribute and change under these terms. 287 | 288 | To do so, attach the following notices to the program. It is safest 289 | to attach them to the start of each source file to most effectively 290 | convey the exclusion of warranty; and each file should have at least 291 | the "copyright" line and a pointer to where the full notice is found. 292 | 293 | 294 | Copyright (C) 295 | 296 | This program is free software; you can redistribute it and/or modify 297 | it under the terms of the GNU General Public License as published by 298 | the Free Software Foundation; either version 2 of the License, or 299 | (at your option) any later version. 300 | 301 | This program is distributed in the hope that it will be useful, 302 | but WITHOUT ANY WARRANTY; without even the implied warranty of 303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 304 | GNU General Public License for more details. 305 | 306 | You should have received a copy of the GNU General Public License 307 | along with this program; if not, write to the Free Software 308 | Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 309 | 310 | 311 | Also add information on how to contact you by electronic and paper mail. 312 | 313 | If the program is interactive, make it output a short notice like this 314 | when it starts in an interactive mode: 315 | 316 | Gnomovision version 69, Copyright (C) year name of author 317 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 318 | This is free software, and you are welcome to redistribute it 319 | under certain conditions; type `show c' for details. 320 | 321 | The hypothetical commands `show w' and `show c' should show the appropriate 322 | parts of the General Public License. Of course, the commands you use may 323 | be called something other than `show w' and `show c'; they could even be 324 | mouse-clicks or menu items--whatever suits your program. 325 | 326 | You should also get your employer (if you work as a programmer) or your 327 | school, if any, to sign a "copyright disclaimer" for the program, if 328 | necessary. Here is a sample; alter the names: 329 | 330 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program 331 | `Gnomovision' (which makes passes at compilers) written by James Hacker. 332 | 333 | , 1 April 1989 334 | Ty Coon, President of Vice 335 | 336 | This General Public License does not permit incorporating your program into 337 | proprietary programs. If your program is a subroutine library, you may 338 | consider it more useful to permit linking proprietary applications with the 339 | library. If this is what you want to do, use the GNU Library General 340 | Public License instead of this License. 341 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | obj-m := turbomem.o 2 | 3 | KDIR := /lib/modules/$(shell uname -r)/build 4 | PWD := $(shell pwd) 5 | 6 | default: 7 | $(MAKE) -C $(KDIR) M=$(PWD) modules 8 | 9 | install: 10 | $(MAKE) -C $(KDIR) M=$(PWD) modules_install 11 | 12 | clean: 13 | $(MAKE) -C $(KDIR) M=$(PWD) clean 14 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | turbomem - Linux driver for Intel(R) Turbo Memory Controller 2 | 3 | 4 | This is the development of a reverse-engineered Linux driver for the Intel(R) 5 | Turbo Memory Controller, a mini-PCIe board that contains NAND flash and a 6 | controller chip. This driver will expose the flash memory to the Linux MTD 7 | (Memory Technology Device) layer, which in turn can setup filesystems on top. 8 | 9 | After detecting a compatible device, basic info is logged to dmesg: 10 | turbomem 0000:04:00.0: Found Intel Turbo Memory Controller (rev 11) 11 | turbomem 0000:04:00.0: Device characteristics: 13404, flash size: 2048 MB 12 | 13 | 14 | Current status: 15 | --------------- 16 | Erasing, writing and reading works, bad block handling is done. 17 | Random failures can be seen with the mtd tests. 18 | Device is mountable with ubifs, but data cannot be written/read back reliably. 19 | 20 | How to format and mount: 21 | ------------------------ 22 | 1. Install mtd-utils from http://www.linux-mtd.infradead.org/ 23 | 2. Load MTD support 24 | # modprobe mtd 25 | 3. Load driver (creates /dev/mtd0) 26 | # insmod turbomem.ko 27 | 4. Format device for UBI (only needed first time) 28 | # ubiformat /dev/mtd0 29 | 5. Load UBI support 30 | # modprobe ubi 31 | 6. Attach UBI device to stack (creates /dev/ubi0) 32 | # ubiattach -p /dev/mtd0 33 | 7. Show info about UBI device (only needed first time) 34 | Get size of device for next step 35 | (Amount of available logical eraseblocks, bytes) 36 | # ubinfo /dev/ubi0 37 | 8. Create UBIFS volume on top of ubi0 38 | (creates /dev/ubi0_0, only needed first time) 39 | size = 2037456896 for 2GB. name is required but does not matter 40 | # ubimkvol -s -N /dev/ubi0 41 | 9. Mount UBIFS 42 | # mount -t ubifs /dev/ubi0_0 /mnt/turbomem 43 | 10. Now test reading/writing in your mounted directory 44 | 45 | Notes: 46 | ------ 47 | * When module is loaded, eraseblocks 1-5 will be scanned for a bad block table. 48 | If none is found, all non-reserved eraseblocks will be erased to gather info 49 | on which blocks are bad. The data will be written twice at blocks 1-5. 50 | 51 | * If you use both Linux and Windows on the computer with this card, uninstall 52 | the Turbo Memory driver in Windows before using this driver. Windows and 53 | Linux drivers use different bad block tables and will erase all flash. 54 | 55 | * The supplied Vista driver requires certain SATA controller chips to install 56 | and work. Tests on one newer machine so far indicates the cards do not run 57 | if this chip is missing (card does not show in lspci). Maybe the option ROM 58 | disables the card in this case. 59 | 60 | * This driver is developed using the 2GB version of the board. 61 | It does not work on 1GB boards, and can brick them when erasing to add bad 62 | block table. It has not been tested on 4GB boards. 63 | 64 | 65 | Enjoy, 66 | Erik Ekman 67 | 68 | ================================================================================ 69 | 70 | Example session: 71 | 72 | # modprobe mtd 73 | # insmod turbomem.ko 74 | # mtdinfo /dev/mtd0 75 | mtd0 76 | Name: TurboMemory@0000:04:00.0 77 | Type: nand 78 | Eraseblock size: 262144 bytes, 256.0 KiB 79 | Amount of eraseblocks: 8187 (2146172928 bytes, 2.0 GiB) 80 | Minimum input/output unit size: 4096 bytes 81 | Sub-page size: 4096 bytes 82 | Character device major/minor: 90:0 83 | Bad blocks are allowed: true 84 | Device is writable: true 85 | # flash_erase /dev/mtd0 0 10 86 | Erasing 256 Kibyte @ 240000 -- 100 % complete 87 | # nanddump /dev/mtd0 -l 8192 |hexdump -C 88 | ECC failed: 0 89 | ECC corrected: 0 90 | Number of bad blocks: 0 91 | Number of bbt blocks: 0 92 | Block size 262144, page size 4096, OOB size 0 93 | Dumping data starting at 0x00000000 and ending at 0x00002000... 94 | 00000000 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 95 | * 96 | 00002000 97 | # echo "faaaaao foo foo 22"|nandwrite -p /dev/mtd0 98 | Writing data to block 0 at offset 0x0 99 | # nanddump /dev/mtd0 -l 8192 |hexdump -C 100 | ECC failed: 0 101 | ECC corrected: 0 102 | Number of bad blocks: 0 103 | Number of bbt blocks: 0 104 | Block size 262144, page size 4096, OOB size 0 105 | Dumping data starting at 0x00000000 and ending at 0x00002000... 106 | 00000000 66 61 61 61 61 61 6f 20 66 6f 6f 20 66 6f 6f 20 |faaaaao foo foo | 107 | 00000010 32 32 0a ff ff ff ff ff ff ff ff ff ff ff ff ff |22..............| 108 | 00000020 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff |................| 109 | * 110 | 00002000 111 | # nandtest -l 0x20000000 /dev/mtd0 112 | ECC corrections: 0 113 | ECC failures : 0 114 | Bad blocks : 0 115 | BBT blocks : 0 116 | Bad block at 0x111c0000 117 | Bad block at 0x13140000 118 | Bad block at 0x1d080000 119 | 1ffc0000: checking... 120 | Finished pass 1 successfully 121 | # 122 | 123 | ================================================================================ 124 | 125 | Debugfs interface: 126 | 127 | * /turbomem//orom (read) 128 | Dump the embedded disk-filtering Option ROM 129 | Example: 130 | 131 | # hexdump -C /sys/kernel/debug/turbomem/0000:04:00.0/orom 132 | 00000000 55 aa 18 e9 2a 29 3f 3f 3f 3f 3f 3f 3f 3f 3f 3f |U...*)??????????| 133 | 00000010 3f 3f 3f 3f 3f 3f 3f b9 70 00 20 00 00 00 00 00 |???????.p. .....| 134 | 00000020 24 50 6e 50 01 02 00 00 00 d6 00 00 00 00 40 00 |$PnP..........@.| 135 | 00000030 4c 00 05 80 00 e4 00 00 00 00 00 00 00 00 00 00 |L...............| 136 | 00000040 49 6e 74 65 6c 20 43 6f 72 70 2e 00 49 6e 74 65 |Intel Corp..Inte| 137 | 00000050 6c 28 52 29 20 54 75 72 62 6f 20 4d 65 6d 6f 72 |l(R) Turbo Memor| 138 | 00000060 79 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |y...............| 139 | 00000070 50 43 49 52 86 80 4e 44 00 00 18 00 00 05 80 00 |PCIR..ND........| 140 | 00000080 18 00 ea 03 00 80 00 00 00 00 00 00 00 00 00 00 |................| 141 | 00000090 46 49 4c 54 2e 12 01 01 01 00 0a 00 01 00 ea 03 |FILT............| 142 | .... and so on. 143 | 144 | ================================================================================ 145 | 146 | Speedtest results: 147 | 148 | mtd_speedtest: MTD device: 0 149 | mtd_speedtest: MTD device size 2146172928, eraseblock size 262144, 150 | page size 4096, count of eraseblocks 8187, pages per eraseblock 64, OOB size 0 151 | mtd_test: scanning for bad eraseblocks 152 | mtd_test: scanned 8187 eraseblocks, 17 are bad 153 | mtd_speedtest: testing eraseblock write speed 154 | mtd_speedtest: eraseblock write speed is 11881 KiB/s 155 | mtd_speedtest: testing eraseblock read speed 156 | mtd_speedtest: eraseblock read speed is 31137 KiB/s 157 | mtd_speedtest: testing page write speed 158 | mtd_speedtest: page write speed is 11920 KiB/s 159 | mtd_speedtest: testing page read speed 160 | mtd_speedtest: page read speed is 31045 KiB/s 161 | mtd_speedtest: testing 2 page write speed 162 | mtd_speedtest: 2 page write speed is 11929 KiB/s 163 | mtd_speedtest: testing 2 page read speed 164 | mtd_speedtest: 2 page read speed is 31072 KiB/s 165 | mtd_speedtest: Testing erase speed 166 | mtd_speedtest: erase speed is 494683 KiB/s 167 | mtd_speedtest: Testing 2x multi-block erase speed 168 | mtd_speedtest: 2x multi-block erase speed is 495034 KiB/s 169 | mtd_speedtest: Testing 4x multi-block erase speed 170 | mtd_speedtest: 4x multi-block erase speed is 494683 KiB/s 171 | mtd_speedtest: Testing 8x multi-block erase speed 172 | mtd_speedtest: 8x multi-block erase speed is 494566 KiB/s 173 | mtd_speedtest: Testing 16x multi-block erase speed 174 | mtd_speedtest: 16x multi-block erase speed is 495034 KiB/s 175 | mtd_speedtest: Testing 32x multi-block erase speed 176 | mtd_speedtest: 32x multi-block erase speed is 494683 KiB/s 177 | mtd_speedtest: Testing 64x multi-block erase speed 178 | mtd_speedtest: 64x multi-block erase speed is 495386 KiB/s 179 | mtd_speedtest: finished 180 | 181 | -------------------------------------------------------------------------------- /turbomem.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Driver for Intel(R) Turbo Memory Controller 3 | * 4 | * Copyright (c) 2013-2015 Erik Ekman 5 | * 6 | * This software is licensed under the terms of the GNU General Public 7 | * License version 2, as published by the Free Software Foundation, and 8 | * may be copied, distributed, and modified under those terms. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | * GNU General Public License for more details. 14 | * 15 | */ 16 | 17 | /* 18 | 19 | Observed flash layout of Turbo Memory 2GB board: 20 | 21 | It is addressed by 512 byte sectors. 4kB of flash is available 22 | every 8kB. After 512 sectors (256kB), next available sector 23 | starts at next even 0x1000 address. 24 | 25 | Read can be done on individual sectors. Writes have to be done using 26 | a full 4kB block. Erase is done per 512 sectors. 27 | 28 | Example: 29 | 00000000-00000007 = 4kB 30 | 00000010-00000017 = 4kB 31 | 00000020-00000027 = 4kB 32 | 00000030-00000037 = 4kB 33 | ... 34 | 000003D0-000003D7 = 4kB 35 | 000003E0-000003E7 = 4kB 36 | 000003F0-000003F7 = 4kB 37 | 38 | 00001000-00001007 = 4kB 39 | 00001010-00001017 = 4kB 40 | ... 41 | 000013E0-000013E7 = 4kB 42 | 000013F0-000013F7 = 4kB 43 | 44 | 00002000-00002007 = 4kB 45 | 00002010-00002017 = 4kB 46 | ... 47 | 000023E0-000023E7 = 4kB 48 | 000023F0-000023F7 = 4kB 49 | and so on. 50 | 51 | Erase can be done at address 0x0, 0x1000, 0x2000, 0x3000 and so on. 52 | 53 | The first 256kB contain serial number, option ROM and other data and is kept 54 | as reserved. 55 | 56 | The flash chips mounted on the board are Intel SD74 SLC NAND, which has 57 | 2kB page size, 64byte OOB and rated at 26 MB/s read and 7.5 MB/s write speed. 58 | The 2GB board has 2x JS29F08G08CANC1 while the 1GB board has 2x JS29F04G08AANB1. 59 | The controller chip only allows 4kB pages and manages the OOB data. 60 | 61 | */ 62 | 63 | #include 64 | #include 65 | #include 66 | #include 67 | #include 68 | #include 69 | #include 70 | #include 71 | #include 72 | #include 73 | 74 | static int debug; 75 | module_param(debug, int, 0); 76 | MODULE_PARM_DESC(debug, "Debug mode (1=log all I/O)"); 77 | 78 | #define DBG(fmt, args...) do { if (debug) printk(KERN_DEBUG "turbomem: " fmt, ##args); } while (0) 79 | 80 | #define DRIVER_NAME "turbomem" 81 | #define NAME_SIZE 32 82 | 83 | /* Addressable unit */ 84 | #define NAND_SECTOR_SIZE 512 85 | /* Unit for reads/writes */ 86 | #define NAND_SECTORS_PER_PAGE 8 87 | #define NAND_PAGE_SIZE ((NAND_SECTORS_PER_PAGE)*(NAND_SECTOR_SIZE)) 88 | #define NAND_PAGE_OFFSET(x) ((x) % (NAND_PAGE_SIZE)) 89 | /* Unit for erasing */ 90 | #define NAND_SECTORS_PER_BLOCK 512 91 | #define NAND_BLOCK_SIZE ((NAND_SECTORS_PER_BLOCK)*(NAND_SECTOR_SIZE)) 92 | 93 | #define NUM_SECTORS(x) ((x)/(NAND_SECTOR_SIZE)) 94 | 95 | #define BBT_BLOCKS 4 96 | /* First block is for OROM and things, then bad block tables */ 97 | #define RESERVED_SECTORS ((NAND_SECTORS_PER_BLOCK) * (1 + BBT_BLOCKS)) 98 | 99 | 100 | #define TRANSFER_CMD_ADDR_LOWER_REGISTER (0) 101 | #define TRANSFER_CMD_ADDR_UPPER_REGISTER (4) 102 | 103 | #define COMMAND_REGISTER (0x10) 104 | #define COMMAND_START_DMA (1) 105 | #define COMMAND_RESET (0x100) 106 | 107 | #define STATUS_REGISTER (0x18) 108 | #define STATUS_INTERRUPT_MASK (0x1F) 109 | #define STATUS_BOOTING (0x00010000) 110 | 111 | #define INTERRUPT_CTRL_REGISTER (0x20) 112 | #define INTERRUPT_CTRL_ENABLE_BITS (0x3) 113 | 114 | /* 115 | * There are also other modes: 116 | * Some kind of read: 2 3 (mode 3 maybe better at reading sectors 117 | * written to multiple times?) 118 | * Some kind of write: 5 6 119 | * Unknown: 0x31 +more? 120 | */ 121 | enum iomode { 122 | MODE_READ = 1, 123 | MODE_WRITE = 7, 124 | MODE_ERASE = 0x11, 125 | MODE_NOP = 0x35, 126 | }; 127 | 128 | enum xfer_status { 129 | XFER_QUEUED = 0, 130 | XFER_DONE, 131 | XFER_FAILED, 132 | }; 133 | 134 | struct transferbuf_handle { 135 | /* Virtual address of struct transfer_command buffer */ 136 | void *buf; 137 | /* DMA address to the same buffer, for writing to HW */ 138 | dma_addr_t busaddr; 139 | /* Operation status */ 140 | enum xfer_status status; 141 | /* IRQ completion */ 142 | struct completion completion; 143 | }; 144 | 145 | /* 146 | * This struct is given to the device to initiate a transfer. 147 | * The bus address of it is written to the 64bit register at offset 0. 148 | * Set the lowest bit in register 0x10 to start the transfer. 149 | * A NOP command is usually put at the end of each chain, but this 150 | * is not required. 151 | */ 152 | struct transfer_command { 153 | /* Offset 0000 */ 154 | /* 3 written here initially. After transfer an errorcode will be 155 | * written */ 156 | __le32 result; 157 | /* Offset 0004 */ 158 | /* Flags. Highest bit and lowest bit normally used. Highest bit 159 | * means not executed? */ 160 | __le32 transfer_flags; 161 | /* Offset 0008 */ 162 | /* Bus address of next struct transfer_command buffer. Zero if last. */ 163 | __le64 next_command; 164 | /* Offset 0010 */ 165 | /* Type of operation. Read, write, erase etc. */ 166 | u8 mode; 167 | /* Number of 512b sectors to transfer. For reading: 1-8, writing: 8. 168 | * Set to zero when erasing */ 169 | u8 transfer_size; 170 | u16 reserved1; 171 | /* Offset 0014 */ 172 | /* Sector to start transfer/erase at. */ 173 | __le32 sector_addr; 174 | /* Offset 0018 */ 175 | /* Write same sector here as 'sector_addr' for writing/erasing. */ 176 | __le32 sector_addr2; 177 | /* Offset 001C */ 178 | /* Bus address of databuffer. Used for reads/writes. */ 179 | __le64 data_buffer; 180 | u64 reserved2; 181 | /* Offset 002C */ 182 | /* Bus address of metadata buffer. Unknown contents/size */ 183 | __le64 metadata_buffer; 184 | /* Offset 0034 */ 185 | /* Set to 1 if this is first transfer in the chain */ 186 | u8 first_transfer; 187 | /* Set to 1 if this is last transfer in the chain */ 188 | u8 last_transfer; 189 | /* Set to 1 if data buffer address at offset 001C above is valid */ 190 | u8 data_buffer_valid; 191 | /* Set to 1 if metadata buffer address at offset 002C above is valid */ 192 | u8 metadata_buffer_valid; 193 | u64 reserved3; 194 | /* Offset 0040 */ 195 | /* The windows driver uses this field to link the transfer command 196 | * structs. Addresses are virtual, not used by hardware. */ 197 | u64 virtual_ptr1; 198 | u32 reserved4; 199 | /* Offset 004C */ 200 | __le32 sector_addr3; 201 | /* Offset 0050 */ 202 | u64 virtual_ptr2; 203 | u64 reserved5; 204 | u64 reserved6; 205 | u32 reserved7; 206 | /* Offset 006C */ 207 | u64 virtual_ptr3; 208 | /* Offset 0074 */ 209 | u64 virtual_ptr4; 210 | /* Offset 007C */ 211 | u8 cmd_one; 212 | u8 reserved8; 213 | u16 reserved9; 214 | } __packed; 215 | 216 | /* Value from transfer_command->result */ 217 | enum command_result { 218 | /* When doing IO to nonexisting address */ 219 | RESULT_BAD_ADDRESS = 0x8003, 220 | /* When writing/erasing bad block */ 221 | RESULT_BAD_BLOCK = 0x8004, 222 | /* When reading sector written more than once */ 223 | RESULT_READ_FAILED = 0x8012, 224 | /* When reading erased sector */ 225 | RESULT_READ_ERASED_SECTOR = 0x8FF2, 226 | }; 227 | 228 | /* 229 | * Bad block table will contain 4096 entries for 1GB board, 8192 for 2GB 230 | * and 16384 for 4GB version. It will be stored in two eraseblocks, with one 231 | * primary and the other as mirror. The bbt[] uses one bit per eraseblock, 232 | * so all sizes of the struct will fit in one page (4096 bytes). 233 | */ 234 | struct turbomem_bbt { 235 | u32 magic; 236 | u32 version; 237 | u32 eraseblocks; 238 | u8 bbt[0]; 239 | }; 240 | 241 | struct turbomem_info { 242 | struct device *dev; 243 | struct dentry *debugfs_dir; 244 | struct mtd_info mtd; 245 | char name[NAME_SIZE]; 246 | void __iomem *bar0; 247 | struct dma_pool *dmapool_cmd; 248 | struct mutex lock; 249 | struct transferbuf_handle *curr_transfer; 250 | struct transferbuf_handle *idle_transfer; 251 | u32 irq_statusword; 252 | unsigned int characteristics; 253 | unsigned int flash_sectors; 254 | unsigned int usable_flash_sectors; 255 | struct turbomem_bbt *bbt; 256 | }; 257 | 258 | static struct dentry *debugfs_root; 259 | 260 | static u32 read32(struct turbomem_info *turbomem, u32 offset) 261 | { 262 | // ioread will convert from little endian if required. 263 | return ioread32(turbomem->bar0 + offset); 264 | } 265 | 266 | static void write32(struct turbomem_info *turbomem, u32 offset, u32 value) 267 | { 268 | // ioread will convert to little endian if required. 269 | iowrite32(value, turbomem->bar0 + offset); 270 | } 271 | 272 | static void turbomem_enable_interrupts(struct turbomem_info *turbomem, 273 | bool active) 274 | { 275 | u32 reg; 276 | 277 | reg = read32(turbomem, INTERRUPT_CTRL_REGISTER); 278 | if (active) 279 | reg |= INTERRUPT_CTRL_ENABLE_BITS; 280 | else 281 | reg &= ~INTERRUPT_CTRL_ENABLE_BITS; 282 | 283 | write32(turbomem, INTERRUPT_CTRL_REGISTER, reg); 284 | } 285 | 286 | static void turbomem_calc_sectors(struct turbomem_info *turbomem) 287 | { 288 | unsigned int sectors; 289 | unsigned int reg; 290 | unsigned int limit8, limit14; 291 | unsigned int d; 292 | unsigned int i = 0; 293 | 294 | /* Get device characteristics */ 295 | reg = read32(turbomem, 0x38); 296 | turbomem->characteristics = ((reg & 0xFFFFF) + 0x10000) & 0xFFFFF; 297 | 298 | d = (reg >> 0xC) & 0xF; 299 | do { 300 | i++; 301 | } while (i < d); 302 | limit8 = i << 10; 303 | 304 | d = (reg >> 16) & 0xF; 305 | limit14 = d + 1; 306 | 307 | d = 0x400 << ((turbomem->characteristics >> 0xC) & 0xF); 308 | if (d > limit8) 309 | limit8 = d; 310 | 311 | d = ((turbomem->characteristics >> 0x16) & 0xF); 312 | if (d > limit14) 313 | limit14 = d; 314 | 315 | sectors = (limit8 * limit14) * 512; 316 | 317 | turbomem->flash_sectors = sectors; 318 | /* First 512-sector block is reserved */ 319 | turbomem->usable_flash_sectors = sectors - RESERVED_SECTORS; 320 | } 321 | 322 | static irqreturn_t turbomem_isr(int irq, void *dev) 323 | { 324 | struct turbomem_info *turbomem = dev; 325 | u32 status; 326 | u32 reg; 327 | 328 | status = read32(turbomem, STATUS_REGISTER); 329 | if (status == 0xFFFFFFFF || (status & STATUS_INTERRUPT_MASK) == 0) 330 | return IRQ_NONE; 331 | 332 | turbomem->irq_statusword = status; 333 | turbomem_enable_interrupts(turbomem, 0); 334 | 335 | reg = read32(turbomem, STATUS_REGISTER); 336 | write32(turbomem, STATUS_REGISTER, reg & STATUS_INTERRUPT_MASK); 337 | 338 | if (turbomem->curr_transfer) 339 | complete_all(&turbomem->curr_transfer->completion); 340 | 341 | return IRQ_HANDLED; 342 | } 343 | 344 | /* Both the transfer_command and the transferbuf_handle will be freed. */ 345 | static void turbomem_transferbuf_free(struct turbomem_info *turbomem, 346 | struct transferbuf_handle *transferbuf) 347 | { 348 | dma_pool_free(turbomem->dmapool_cmd, transferbuf->buf, 349 | transferbuf->busaddr); 350 | 351 | kfree(transferbuf); 352 | } 353 | 354 | static void turbomem_write_transfer_to_hw(struct turbomem_info *turbomem, 355 | struct transferbuf_handle *transfer) 356 | { 357 | dma_addr_t busaddr = transfer->busaddr; 358 | 359 | turbomem->curr_transfer = transfer; 360 | write32(turbomem, TRANSFER_CMD_ADDR_UPPER_REGISTER, 361 | (busaddr >> 16 >> 16) & 0xFFFFFFFF); 362 | write32(turbomem, TRANSFER_CMD_ADDR_LOWER_REGISTER, 363 | busaddr & 0xFFFFFFFF); 364 | } 365 | 366 | static void turbomem_setup_idle_transfer(struct turbomem_info *turbomem) 367 | { 368 | struct transfer_command *idle_cmd = turbomem->idle_transfer->buf; 369 | 370 | memset(idle_cmd, 0, sizeof(struct transfer_command)); 371 | idle_cmd->transfer_flags = cpu_to_le32(0x7FFFFFFE); 372 | idle_cmd->mode = MODE_NOP; 373 | idle_cmd->last_transfer = 1; 374 | idle_cmd->cmd_one = 0; 375 | } 376 | 377 | static void turbomem_start_idle_transfer(struct turbomem_info *turbomem) 378 | { 379 | turbomem_setup_idle_transfer(turbomem); 380 | turbomem_write_transfer_to_hw(turbomem, turbomem->idle_transfer); 381 | turbomem_enable_interrupts(turbomem, 1); 382 | } 383 | 384 | static struct transferbuf_handle *turbomem_transferbuf_alloc( 385 | struct turbomem_info *turbomem) 386 | { 387 | struct transferbuf_handle *transferbuf; 388 | 389 | transferbuf = kzalloc(sizeof(*transferbuf), GFP_KERNEL); 390 | if (!transferbuf) 391 | return NULL; 392 | 393 | transferbuf->buf = dma_pool_alloc(turbomem->dmapool_cmd, GFP_KERNEL, 394 | &transferbuf->busaddr); 395 | if (!transferbuf->buf) { 396 | kfree(transferbuf); 397 | return NULL; 398 | } 399 | 400 | memset(transferbuf->buf, 0, sizeof(struct transfer_command)); 401 | init_completion(&transferbuf->completion); 402 | return transferbuf; 403 | } 404 | 405 | static sector_t turbomem_translate_lba(sector_t lba) 406 | { 407 | /* Every other 4kB area is not used */ 408 | sector_t lower = 2 * (lba & 0x1FF); 409 | /* 512 usable sectors appear at even intervals */ 410 | sector_t upper = 0x1000 * (lba >> 9); 411 | 412 | return upper | lower; 413 | } 414 | 415 | static int turbomem_do_io(struct turbomem_info *turbomem, sector_t lba, 416 | int sectors, struct transferbuf_handle *xfer, 417 | dma_addr_t busaddr, enum iomode mode) 418 | { 419 | struct transfer_command *cmd; 420 | 421 | lba = turbomem_translate_lba(lba); 422 | 423 | /* We must have the lock here */ 424 | BUG_ON(mutex_is_locked(&turbomem->lock) == 0); 425 | 426 | /* Setup transfer command */ 427 | cmd = xfer->buf; 428 | cmd->result = cpu_to_le32(3); 429 | cmd->transfer_flags = cpu_to_le32(0x80000001); 430 | cmd->mode = mode; 431 | cmd->transfer_size = cpu_to_le32(sectors); 432 | cmd->sector_addr = cpu_to_le32(lba); 433 | if (mode != MODE_READ) 434 | cmd->sector_addr2 = cpu_to_le32(lba); 435 | cmd->data_buffer = cpu_to_le64(busaddr); 436 | cmd->data_buffer_valid = 1; 437 | 438 | /* Chain idle transfer as next item */ 439 | turbomem_setup_idle_transfer(turbomem); 440 | cmd->next_command = cpu_to_le64( 441 | turbomem->idle_transfer->busaddr); 442 | 443 | /* Mark first job */ 444 | cmd->first_transfer = 1; 445 | 446 | /* Write addr, enable IRQ and DMA */ 447 | turbomem_write_transfer_to_hw(turbomem, xfer); 448 | turbomem_enable_interrupts(turbomem, 1); 449 | write32(turbomem, COMMAND_REGISTER, COMMAND_START_DMA); 450 | 451 | /* Wait for interrupt completion */ 452 | wait_for_completion_io(&xfer->completion); 453 | 454 | if (turbomem->irq_statusword == 1) 455 | /* Transfer completed */ 456 | turbomem->curr_transfer->status = XFER_DONE; 457 | else 458 | /* Transfer failed */ 459 | turbomem->curr_transfer->status = XFER_FAILED; 460 | 461 | /* Setup new idle transfer, will enable interrupts again */ 462 | turbomem_start_idle_transfer(turbomem); 463 | 464 | /* Check error on transfer */ 465 | if (xfer->status != XFER_DONE) 466 | return -EIO; 467 | 468 | return 0; 469 | } 470 | 471 | #define HW_RESET_ATTEMPTS 50 472 | 473 | static int turbomem_hw_init(struct turbomem_info *turbomem) 474 | { 475 | u32 initregs; 476 | u32 reg; 477 | unsigned int i; 478 | 479 | initregs = 0; 480 | for (i = 0; i < 4; i++) 481 | initregs |= read32(turbomem, i*8); 482 | if (initregs) { 483 | for (i = 0; i < 4; i++) { 484 | reg = 0; 485 | if (i == 3) 486 | reg = 0x1F; 487 | write32(turbomem, i*8, reg); 488 | } 489 | initregs = 0; 490 | for (i = 0; i < 4; i++) 491 | initregs |= read32(turbomem, i*8); 492 | if (initregs) { 493 | u32 reg8 = 1 | read32(turbomem, 8); 494 | 495 | write32(turbomem, COMMAND_REGISTER, COMMAND_RESET); 496 | for (i = 0; i < HW_RESET_ATTEMPTS; i++) { 497 | if (i) 498 | msleep(100); 499 | write32(turbomem, 8, reg8); 500 | reg = read32(turbomem, STATUS_REGISTER); 501 | if ((reg & STATUS_BOOTING) == 0) 502 | break; 503 | } 504 | if (i >= HW_RESET_ATTEMPTS) 505 | return -EIO; 506 | } 507 | } 508 | 509 | reg = read32(turbomem, 8); 510 | reg = (reg & 0xFFFFFFFB) | 1; 511 | write32(turbomem, 8, reg); 512 | for (i = 0; i < HW_RESET_ATTEMPTS; i++) { 513 | if (i) 514 | msleep(100); 515 | reg = read32(turbomem, STATUS_REGISTER); 516 | if ((reg & STATUS_BOOTING) == 0) 517 | break; 518 | } 519 | if (i >= HW_RESET_ATTEMPTS) 520 | return -EIO; 521 | 522 | return 0; 523 | } 524 | 525 | static ssize_t turbomem_debugfs_read_orom(struct file *file, 526 | char __user *userbuf, size_t count, loff_t *ppos) 527 | { 528 | struct transferbuf_handle *xfer; 529 | struct turbomem_info *turbomem = file->f_inode->i_private; 530 | dma_addr_t bus4k; 531 | u8 *buf4k; 532 | loff_t offset_backup; 533 | ssize_t retval; 534 | sector_t addr = 0x10 + NUM_SECTORS(*ppos); 535 | 536 | xfer = turbomem_transferbuf_alloc(turbomem); 537 | if (!xfer) 538 | return -ENOMEM; 539 | 540 | buf4k = dma_alloc_coherent(turbomem->dev, NAND_PAGE_SIZE, &bus4k, 541 | GFP_KERNEL); 542 | if (!buf4k) { 543 | turbomem_transferbuf_free(turbomem, xfer); 544 | return -ENOMEM; 545 | } 546 | memset(buf4k, 0, NAND_PAGE_SIZE); 547 | 548 | mutex_lock(&turbomem->lock); 549 | 550 | retval = turbomem_do_io(turbomem, addr, NUM_SECTORS(NAND_PAGE_SIZE), 551 | xfer, bus4k, MODE_READ); 552 | 553 | mutex_unlock(&turbomem->lock); 554 | if (xfer->status == XFER_FAILED) { 555 | /* Found erased page, end of OROM */ 556 | retval = 0; 557 | goto out; 558 | } 559 | 560 | offset_backup = *ppos & 0xFFFF000; 561 | *ppos = NAND_PAGE_OFFSET(*ppos); 562 | retval = simple_read_from_buffer(userbuf, count, ppos, 563 | buf4k, NAND_PAGE_SIZE); 564 | *ppos += offset_backup; 565 | out: 566 | dma_free_coherent(turbomem->dev, NAND_PAGE_SIZE, buf4k, bus4k); 567 | turbomem_transferbuf_free(turbomem, xfer); 568 | return retval; 569 | } 570 | 571 | static const struct file_operations debugfs_orom_fops = { 572 | .read = turbomem_debugfs_read_orom, 573 | }; 574 | 575 | static void turbomem_debugfs_dev_add(struct turbomem_info *turbomem) 576 | { 577 | if (IS_ERR_OR_NULL(debugfs_root)) 578 | return; 579 | turbomem->debugfs_dir = debugfs_create_dir(dev_name(turbomem->dev), 580 | debugfs_root); 581 | 582 | if (IS_ERR_OR_NULL(turbomem->debugfs_dir)) 583 | return; 584 | debugfs_create_file("orom", 0400, turbomem->debugfs_dir, turbomem, 585 | &debugfs_orom_fops); 586 | } 587 | 588 | static void turbomem_debugfs_dev_remove(struct turbomem_info *turbomem) 589 | { 590 | if (IS_ERR_OR_NULL(turbomem->debugfs_dir)) 591 | return; 592 | debugfs_remove_recursive(turbomem->debugfs_dir); 593 | } 594 | 595 | static int turbomem_mtd_exec(struct turbomem_info *turbomem, enum iomode mode, 596 | sector_t lba, int sectors, u_char *buf) 597 | { 598 | struct transferbuf_handle *xfer; 599 | int result; 600 | int length; 601 | dma_addr_t busaddr = 0; 602 | enum dma_data_direction dir = DMA_NONE; 603 | 604 | /* We must have the lock here */ 605 | BUG_ON(mutex_is_locked(&turbomem->lock) == 0); 606 | 607 | length = sectors * NAND_SECTOR_SIZE; 608 | xfer = turbomem_transferbuf_alloc(turbomem); 609 | if (!xfer) 610 | return -ENOMEM; 611 | 612 | if (buf) { 613 | if (mode == MODE_WRITE) 614 | dir = DMA_TO_DEVICE; 615 | else 616 | dir = DMA_FROM_DEVICE; 617 | 618 | busaddr = dma_map_single(turbomem->dev, buf, length, dir); 619 | if (dma_mapping_error(turbomem->dev, busaddr)) { 620 | dev_err(turbomem->dev, "Failed to map DMA buffer\n"); 621 | result = -EIO; 622 | goto out; 623 | } 624 | } else if (mode != MODE_ERASE) { 625 | /* Buffer required if not erasing */ 626 | return -EINVAL; 627 | } 628 | result = turbomem_do_io(turbomem, lba, sectors, xfer, busaddr, mode); 629 | if (busaddr) 630 | dma_unmap_single(turbomem->dev, busaddr, length, dir); 631 | 632 | if (result) { 633 | struct transfer_command *cmd = xfer->buf; 634 | 635 | if (mode == MODE_READ && le32_to_cpu(cmd->result) == 636 | RESULT_READ_ERASED_SECTOR) { 637 | /* Make up erased sector */ 638 | memset(buf, 0xFF, length); 639 | result = 0; 640 | } else { 641 | dev_warn(turbomem->dev, 642 | "IO error: result %08X (lba %08llX op %d)\n", 643 | le32_to_cpu(cmd->result), 644 | (unsigned long long) lba, mode); 645 | } 646 | } 647 | out: 648 | turbomem_transferbuf_free(turbomem, xfer); 649 | return result; 650 | } 651 | 652 | static int turbomem_mtd_erase(struct mtd_info *mtd, struct erase_info *instr) 653 | { 654 | struct turbomem_info *turbomem = mtd->priv; 655 | int result; 656 | u64 pos = instr->addr / NAND_SECTOR_SIZE; 657 | u64 end = (instr->addr + instr->len - 1) / NAND_SECTOR_SIZE; 658 | 659 | DBG("Erase from addr %08llX (sector %08llX) len %llu\n", instr->addr, 660 | pos, instr->len); 661 | mutex_lock(&turbomem->lock); 662 | while (pos <= end) { 663 | DBG("Suberase lba %08llX\n", RESERVED_SECTORS + pos); 664 | result = turbomem_mtd_exec(turbomem, MODE_ERASE, 665 | RESERVED_SECTORS + pos, 0, NULL); 666 | if (result) { 667 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0) 668 | instr->state = MTD_ERASE_FAILED; 669 | #else 670 | result = -EIO; 671 | #endif 672 | instr->fail_addr = pos * NAND_SECTOR_SIZE; 673 | mutex_unlock(&turbomem->lock); 674 | return result; 675 | } 676 | pos += NAND_SECTORS_PER_BLOCK; 677 | } 678 | mutex_unlock(&turbomem->lock); 679 | 680 | #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0) 681 | instr->state = MTD_ERASE_DONE; 682 | mtd_erase_callback(instr); 683 | return 0; 684 | #else 685 | return result; 686 | #endif 687 | } 688 | 689 | static int turbomem_mtd_read(struct mtd_info *mtd, loff_t from, size_t len, 690 | size_t *retlen, u_char *buf) 691 | { 692 | struct turbomem_info *turbomem = mtd->priv; 693 | u_char *tempbuf = NULL; 694 | u_char *readbuf; 695 | size_t bytes_read = 0; 696 | int result = 0; 697 | /* Round to even page */ 698 | unsigned int offset = NAND_PAGE_OFFSET(from); 699 | sector_t lba = NUM_SECTORS(from) & 0xFFFFFFF8; 700 | 701 | DBG("Read len %zu from addr %08llX, sector %08llX\n", len, from, 702 | (unsigned long long) lba); 703 | mutex_lock(&turbomem->lock); 704 | if (offset || NAND_PAGE_OFFSET(len)) { 705 | /* Uneven offset or length, need a bounce buffer */ 706 | tempbuf = kmalloc(NAND_PAGE_SIZE, GFP_KERNEL | GFP_DMA); 707 | if (!tempbuf) { 708 | result = -ENOMEM; 709 | goto out; 710 | } 711 | } 712 | while (bytes_read < len) { 713 | size_t to_read = len - bytes_read; 714 | 715 | if (tempbuf) 716 | readbuf = tempbuf; 717 | else 718 | readbuf = buf; 719 | DBG("Subread %zu bytes to lba %08llX offset %u to %p\n", 720 | to_read, (unsigned long long) lba, offset, readbuf); 721 | /* Read from flash */ 722 | result = turbomem_mtd_exec(turbomem, MODE_READ, 723 | RESERVED_SECTORS + lba, 724 | NUM_SECTORS(NAND_PAGE_SIZE), readbuf); 725 | if (result) { 726 | goto out; 727 | } 728 | if (to_read > NAND_PAGE_SIZE - offset) 729 | to_read = NAND_PAGE_SIZE - offset; 730 | /* Return read data, handle partial request */ 731 | if (tempbuf) { 732 | memcpy(buf, readbuf + offset, to_read); 733 | DBG("Copied %zu bytes to buf %p\n", to_read, buf); 734 | } else { 735 | DBG("Read %zu bytes to buf %p\n", to_read, buf); 736 | } 737 | buf += to_read; 738 | lba += NUM_SECTORS(NAND_PAGE_SIZE); 739 | bytes_read += to_read; 740 | offset = 0; /* Only first read can be misaligned */ 741 | } 742 | out: 743 | kfree(tempbuf); 744 | mutex_unlock(&turbomem->lock); 745 | *retlen = bytes_read; 746 | return result; 747 | } 748 | 749 | static int turbomem_mtd_write(struct mtd_info *mtd, loff_t to, size_t len, 750 | size_t *retlen, const u_char *buf) 751 | { 752 | struct turbomem_info *turbomem = mtd->priv; 753 | int result; 754 | sector_t lba = NUM_SECTORS(to); 755 | size_t bytes_written = 0; 756 | 757 | DBG("Write len %zu to addr %08llX, sector %08llX\n", 758 | len, to, (unsigned long long) lba); 759 | mutex_lock(&turbomem->lock); 760 | /* Write max one page at a time */ 761 | while (bytes_written < len) { 762 | int sectors = NUM_SECTORS(len - bytes_written); 763 | 764 | if (sectors > NUM_SECTORS(NAND_PAGE_SIZE)) 765 | sectors = NUM_SECTORS(NAND_PAGE_SIZE); 766 | DBG("Subwrite %d sectors to lba %08llX\n", sectors, 767 | (unsigned long long) lba); 768 | result = turbomem_mtd_exec(turbomem, MODE_WRITE, 769 | RESERVED_SECTORS + lba, sectors, (u_char *) buf); 770 | if (result) 771 | goto out; 772 | buf += NAND_SECTOR_SIZE * sectors; 773 | bytes_written += NAND_SECTOR_SIZE * sectors; 774 | lba += sectors; 775 | } 776 | out: 777 | mutex_unlock(&turbomem->lock); 778 | *retlen = bytes_written; 779 | return result; 780 | } 781 | 782 | #define BBT_MAGIC_PRIMARY (0xbadb10c0) 783 | #define BBT_MAGIC_MIRROR (0xbadb10c1) 784 | 785 | static int turbomem_read_bbt(struct turbomem_info *turbomem) 786 | { 787 | unsigned int i; 788 | int result; 789 | u8 *buf = kzalloc(NAND_PAGE_SIZE, GFP_KERNEL | GFP_DMA); 790 | struct turbomem_bbt *bbt = NULL; 791 | 792 | if (!buf) 793 | return -ENOMEM; 794 | 795 | mutex_lock(&turbomem->lock); 796 | for (i = NAND_SECTORS_PER_BLOCK; i < RESERVED_SECTORS; 797 | i += NAND_SECTORS_PER_BLOCK) { 798 | result = turbomem_mtd_exec(turbomem, MODE_READ, 799 | i, NAND_SECTORS_PER_PAGE, buf); 800 | if (result) 801 | break; 802 | bbt = (struct turbomem_bbt *) buf; 803 | /* Found a table */ 804 | if (bbt->magic == BBT_MAGIC_PRIMARY || 805 | bbt->magic == BBT_MAGIC_MIRROR) { 806 | turbomem->bbt = bbt; 807 | break; 808 | } 809 | } 810 | mutex_unlock(&turbomem->lock); 811 | 812 | if (turbomem->bbt) 813 | return 0; 814 | 815 | kfree(buf); 816 | if (result) 817 | return result; /* Read error */ 818 | else 819 | return -ENODATA; /* Found no bbt data */ 820 | } 821 | 822 | /* Convert user addr to eraseblock index */ 823 | static unsigned int turbomem_get_eraseblock(loff_t addr) 824 | { 825 | unsigned int sector = RESERVED_SECTORS + (addr / NAND_SECTOR_SIZE); 826 | 827 | return sector / (NAND_SECTORS_PER_BLOCK); 828 | } 829 | 830 | static void turbomem_markbad(struct turbomem_bbt *bbt, unsigned int eb) 831 | { 832 | if (eb > bbt->eraseblocks) 833 | return; 834 | 835 | bbt->bbt[eb / 8] |= (1 << (eb & 7)); 836 | } 837 | 838 | static int turbomem_isbad(struct turbomem_bbt *bbt, unsigned int eb) 839 | { 840 | if (eb > bbt->eraseblocks) 841 | return 0; 842 | 843 | if (bbt->bbt[eb / 8] & (1 << (eb & 7))) 844 | return 1; 845 | return 0; 846 | } 847 | 848 | static int turbomem_count_bad(struct turbomem_bbt *bbt) 849 | { 850 | int i = 0; 851 | int count = 0; 852 | u8 *table = bbt->bbt; 853 | 854 | /* Count number of bad blocks in table */ 855 | while (i < bbt->eraseblocks) { 856 | int pos; 857 | 858 | for (pos = 0; pos < 8; pos++) { 859 | if (*table & (1 << pos)) 860 | count++; 861 | i++; 862 | } 863 | table++; 864 | } 865 | return count; 866 | } 867 | 868 | static int turbomem_format_build_bbt(struct turbomem_info *turbomem) 869 | { 870 | struct turbomem_bbt *bbt = NULL; 871 | unsigned int i; 872 | 873 | bbt = kzalloc(NAND_PAGE_SIZE, GFP_KERNEL | GFP_DMA); 874 | if (!bbt) 875 | return -ENOMEM; 876 | 877 | bbt->magic = BBT_MAGIC_PRIMARY; 878 | bbt->version = 1; 879 | bbt->eraseblocks = turbomem->flash_sectors / NAND_SECTORS_PER_BLOCK; 880 | mutex_lock(&turbomem->lock); 881 | for (i = 0; i < turbomem->usable_flash_sectors; 882 | i += NAND_SECTORS_PER_BLOCK) { 883 | int result; 884 | struct transferbuf_handle *xfer; 885 | 886 | xfer = turbomem_transferbuf_alloc(turbomem); 887 | if (!xfer) { 888 | mutex_unlock(&turbomem->lock); 889 | return -ENOMEM; 890 | } 891 | /* Erase usable flash looking for bad blocks */ 892 | result = turbomem_do_io(turbomem, RESERVED_SECTORS + i, 893 | 0, xfer, 0, MODE_ERASE); 894 | if (result) { 895 | /* Bad block */ 896 | loff_t addr = i * (NAND_SECTOR_SIZE); 897 | unsigned int eb = turbomem_get_eraseblock(addr); 898 | 899 | turbomem_markbad(bbt, eb); 900 | } 901 | turbomem_transferbuf_free(turbomem, xfer); 902 | } 903 | mutex_unlock(&turbomem->lock); 904 | turbomem->bbt = bbt; 905 | return 0; 906 | } 907 | 908 | static int turbomem_save_bbt(struct turbomem_info *turbomem) 909 | { 910 | struct turbomem_bbt *bbt_out; 911 | unsigned int i; 912 | int result; 913 | 914 | bbt_out = kzalloc(NAND_PAGE_SIZE, GFP_KERNEL | GFP_DMA); 915 | if (!bbt_out) 916 | return -ENOMEM; 917 | 918 | memcpy(bbt_out, turbomem->bbt, sizeof(struct turbomem_bbt) + 919 | ((turbomem->flash_sectors / (NAND_SECTORS_PER_BLOCK)) + 7) / 8); 920 | mutex_lock(&turbomem->lock); 921 | for (i = NAND_SECTORS_PER_BLOCK; i < RESERVED_SECTORS; 922 | i += NAND_SECTORS_PER_BLOCK) { 923 | /* Erase new BBT spot */ 924 | result = turbomem_mtd_exec(turbomem, MODE_ERASE, 925 | i, 0, NULL); 926 | if (result == 0) { 927 | /* Write BBT */ 928 | result = turbomem_mtd_exec(turbomem, MODE_WRITE, i, 929 | NAND_SECTORS_PER_PAGE, (u_char *) bbt_out); 930 | } 931 | if (result) { 932 | /* Mark bad in main bbt and this copy */ 933 | turbomem_markbad(turbomem->bbt, 934 | i / NAND_SECTORS_PER_BLOCK); 935 | turbomem_markbad(bbt_out, i / NAND_SECTORS_PER_BLOCK); 936 | continue; 937 | } 938 | /* Erase and write successful */ 939 | if (bbt_out->magic == BBT_MAGIC_PRIMARY) { 940 | dev_info(turbomem->dev, 941 | "Main BBT v%d written at sector %08X\n", 942 | bbt_out->version, i); 943 | bbt_out->magic = BBT_MAGIC_MIRROR; 944 | } else if (bbt_out->magic == BBT_MAGIC_MIRROR) { 945 | dev_info(turbomem->dev, 946 | "Spare BBT v%d written at sector %08X\n", 947 | bbt_out->version, i); 948 | /* All done. */ 949 | mutex_unlock(&turbomem->lock); 950 | return 0; 951 | } 952 | } 953 | mutex_unlock(&turbomem->lock); 954 | 955 | /* Failed to write two copies of BBT */ 956 | return -EIO; 957 | } 958 | 959 | static int turbomem_init_bbt(struct turbomem_info *turbomem) 960 | { 961 | int ret; 962 | 963 | ret = turbomem_read_bbt(turbomem); 964 | if (ret == -ENODATA) { 965 | dev_warn(turbomem->dev, 966 | "No bad block data found, will format and create new!\n"); 967 | ret = turbomem_format_build_bbt(turbomem); 968 | if (ret) 969 | return ret; 970 | ret = turbomem_save_bbt(turbomem); 971 | if (ret) { 972 | kfree(turbomem->bbt); 973 | return ret; 974 | } 975 | } else if (ret) { 976 | dev_err(turbomem->dev, "Failed looking for bad block data\n"); 977 | return ret; 978 | } 979 | dev_info(turbomem->dev, 980 | "Using bad block table version %d, with %d bad blocks\n", 981 | turbomem->bbt->version, turbomem_count_bad(turbomem->bbt)); 982 | return ret; 983 | } 984 | 985 | static int turbomem_mtd_block_isbad(struct mtd_info *mtd, loff_t ofs) 986 | { 987 | struct turbomem_info *turbomem = mtd->priv; 988 | 989 | return turbomem_isbad(turbomem->bbt, turbomem_get_eraseblock(ofs)); 990 | } 991 | 992 | static int turbomem_mtd_block_markbad(struct mtd_info *mtd, loff_t ofs) 993 | { 994 | struct turbomem_info *turbomem = mtd->priv; 995 | 996 | turbomem_markbad(turbomem->bbt, turbomem_get_eraseblock(ofs)); 997 | turbomem->bbt->version++; 998 | return turbomem_save_bbt(turbomem); 999 | } 1000 | 1001 | static int turbomem_setup_mtd(struct turbomem_info *turbomem) 1002 | { 1003 | struct mtd_info *mtd = &turbomem->mtd; 1004 | 1005 | mtd->type = MTD_NANDFLASH; 1006 | mtd->flags = MTD_CAP_NANDFLASH; 1007 | mtd->size = turbomem->usable_flash_sectors * NAND_SECTOR_SIZE; 1008 | mtd->erasesize = NAND_BLOCK_SIZE; 1009 | mtd->writesize = NAND_PAGE_SIZE; 1010 | mtd->writebufsize = NAND_PAGE_SIZE; 1011 | 1012 | mtd->_erase = turbomem_mtd_erase; 1013 | mtd->_read = turbomem_mtd_read; 1014 | mtd->_write = turbomem_mtd_write; 1015 | 1016 | mtd->_block_isbad = turbomem_mtd_block_isbad; 1017 | mtd->_block_markbad = turbomem_mtd_block_markbad; 1018 | 1019 | mtd->owner = THIS_MODULE; 1020 | mtd->name = turbomem->name; 1021 | mtd->priv = turbomem; 1022 | 1023 | return mtd_device_register(mtd, NULL, 0); 1024 | } 1025 | 1026 | static int turbomem_probe(struct pci_dev *dev, const struct pci_device_id *id) 1027 | { 1028 | int ret; 1029 | struct turbomem_info *turbomem; 1030 | 1031 | dev_info(&dev->dev, "Found Intel Turbo Memory Controller (rev %02X)\n", 1032 | dev->revision); 1033 | 1034 | turbomem = kzalloc(sizeof(*turbomem), GFP_KERNEL); 1035 | if (!turbomem) 1036 | return -ENOMEM; 1037 | 1038 | ret = pci_enable_device(dev); 1039 | if (ret) { 1040 | dev_err(&dev->dev, "Unable to request memory region\n"); 1041 | goto fail_have_struct; 1042 | } 1043 | 1044 | pci_set_drvdata(dev, turbomem); 1045 | pci_set_master(dev); 1046 | turbomem->dev = &dev->dev; 1047 | 1048 | ret = pci_request_regions(dev, DRIVER_NAME); 1049 | if (ret) { 1050 | dev_err(&dev->dev, "Unable to request memory region\n"); 1051 | goto fail_enabled; 1052 | } 1053 | 1054 | turbomem->bar0 = pci_iomap(dev, 0, pci_resource_len(dev, 0)); 1055 | if (!turbomem->bar0) { 1056 | dev_err(&dev->dev, "Unable to remap BAR0\n"); 1057 | goto fail_have_regions; 1058 | } 1059 | 1060 | ret = dma_set_mask(turbomem->dev, DMA_BIT_MASK(32)); 1061 | if (ret) { 1062 | dev_err(&dev->dev, "No usable DMA configuration\n"); 1063 | goto fail_have_iomap; 1064 | } 1065 | 1066 | ret = turbomem_hw_init(turbomem); 1067 | if (ret) { 1068 | dev_err(&dev->dev, "Unable to initialize device\n"); 1069 | goto fail_have_iomap; 1070 | } 1071 | 1072 | turbomem_calc_sectors(turbomem); 1073 | 1074 | ret = request_irq(dev->irq, turbomem_isr, IRQF_SHARED, 1075 | DRIVER_NAME, turbomem); 1076 | if (ret) { 1077 | dev_err(&dev->dev, "Unable to request IRQ\n"); 1078 | goto fail_have_iomap; 1079 | } 1080 | 1081 | turbomem->dmapool_cmd = dma_pool_create(DRIVER_NAME "_cmd", &dev->dev, 1082 | sizeof(struct transfer_command), 8, 0); 1083 | if (!turbomem->dmapool_cmd) { 1084 | dev_err(&dev->dev, "Unable to create DMA pool for commands\n"); 1085 | ret = -ENOMEM; 1086 | goto fail_have_irq; 1087 | } 1088 | 1089 | turbomem->idle_transfer = turbomem_transferbuf_alloc(turbomem); 1090 | if (ret) { 1091 | dev_err(&dev->dev, "Unable to allocate idle transfer job\n"); 1092 | goto fail_have_dmapool; 1093 | } 1094 | turbomem_start_idle_transfer(turbomem); 1095 | 1096 | mutex_init(&turbomem->lock); 1097 | 1098 | snprintf(turbomem->name, NAME_SIZE - 1, "TurboMemory@%s", 1099 | dev_name(turbomem->dev)); 1100 | 1101 | dev_info(&dev->dev, "Device characteristics: %05X, flash size: %d MB\n", 1102 | turbomem->characteristics, turbomem->flash_sectors >> 11); 1103 | 1104 | if (turbomem->flash_sectors >> 11 <= 1024) { 1105 | dev_warn(turbomem->dev, "1GB board not supported yet\n" 1106 | "Skipping further initialization to " 1107 | "avoid bricking the card.\n"); 1108 | return 0; 1109 | } 1110 | 1111 | ret = turbomem_init_bbt(turbomem); 1112 | if (ret) { 1113 | dev_err(&dev->dev, "Unable to initialize bad blocks table\n"); 1114 | goto fail_have_idle_transfer; 1115 | } 1116 | 1117 | ret = turbomem_setup_mtd(turbomem); 1118 | if (ret) { 1119 | dev_err(&dev->dev, "Unable to register to MTD layer\n"); 1120 | goto fail_have_bbt; 1121 | } 1122 | 1123 | turbomem_debugfs_dev_add(turbomem); 1124 | 1125 | DBG("Loaded turbomem driver with debug enabled\n"); 1126 | 1127 | return 0; 1128 | 1129 | fail_have_bbt: 1130 | kfree(turbomem->bbt); 1131 | fail_have_idle_transfer: 1132 | if (turbomem->idle_transfer) 1133 | turbomem_transferbuf_free(turbomem, turbomem->idle_transfer); 1134 | fail_have_dmapool: 1135 | dma_pool_destroy(turbomem->dmapool_cmd); 1136 | fail_have_irq: 1137 | free_irq(dev->irq, turbomem); 1138 | fail_have_iomap: 1139 | pci_iounmap(dev, turbomem->bar0); 1140 | fail_have_regions: 1141 | pci_release_regions(dev); 1142 | fail_enabled: 1143 | pci_disable_device(dev); 1144 | fail_have_struct: 1145 | kfree(turbomem); 1146 | return ret; 1147 | } 1148 | 1149 | static void turbomem_remove(struct pci_dev *dev) 1150 | { 1151 | struct turbomem_info *turbomem = pci_get_drvdata(dev); 1152 | 1153 | turbomem_debugfs_dev_remove(turbomem); 1154 | mtd_device_unregister(&turbomem->mtd); 1155 | kfree(turbomem->bbt); 1156 | if (turbomem->idle_transfer) 1157 | turbomem_transferbuf_free(turbomem, turbomem->idle_transfer); 1158 | dma_pool_destroy(turbomem->dmapool_cmd); 1159 | free_irq(dev->irq, turbomem); 1160 | pci_iounmap(dev, turbomem->bar0); 1161 | pci_release_regions(dev); 1162 | pci_disable_device(dev); 1163 | pci_set_drvdata(dev, NULL); 1164 | kfree(turbomem); 1165 | } 1166 | 1167 | static void turbomem_debugfs_init(void) 1168 | { 1169 | debugfs_root = debugfs_create_dir(DRIVER_NAME, NULL); 1170 | } 1171 | 1172 | static void turbomem_debugfs_cleanup(void) 1173 | { 1174 | debugfs_remove_recursive(debugfs_root); 1175 | debugfs_root = NULL; 1176 | } 1177 | 1178 | #ifdef CONFIG_PM 1179 | static void turbomem_pm_complete(struct device *dev) 1180 | { 1181 | struct pci_dev *pdev = to_pci_dev(dev); 1182 | struct turbomem_info *turbomem = pci_get_drvdata(pdev); 1183 | int result; 1184 | 1185 | result = turbomem_hw_init(turbomem); 1186 | 1187 | if (result) 1188 | dev_warn(dev, "Failed to reset board on resume, result = %d\n", 1189 | result); 1190 | } 1191 | 1192 | static const struct dev_pm_ops turbomem_pm_ops = { 1193 | .complete = turbomem_pm_complete, 1194 | }; 1195 | #define TURBOMEM_PM_OPS (&turbomem_pm_ops) 1196 | #else 1197 | #define TURBOMEM_PM_OPS (NULL) 1198 | #endif 1199 | 1200 | #define PCI_DEVICE_ID_INTEL_TURBOMEMORY (0x444e) 1201 | 1202 | static const struct pci_device_id turbomem_ids[] = { 1203 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_TURBOMEMORY), }, 1204 | { 0, } 1205 | }; 1206 | MODULE_DEVICE_TABLE(pci, turbomem_ids); 1207 | 1208 | static struct pci_driver pci_driver = { 1209 | .name = DRIVER_NAME, 1210 | .id_table = turbomem_ids, 1211 | .probe = turbomem_probe, 1212 | .remove = turbomem_remove, 1213 | .driver.pm = TURBOMEM_PM_OPS, 1214 | }; 1215 | 1216 | static int __init turbomem_init(void) 1217 | { 1218 | int retval; 1219 | 1220 | BUILD_BUG_ON(sizeof(struct transfer_command) != 0x80); 1221 | 1222 | turbomem_debugfs_init(); 1223 | 1224 | retval = pci_register_driver(&pci_driver); 1225 | if (retval < 0) { 1226 | turbomem_debugfs_cleanup(); 1227 | return retval; 1228 | } 1229 | 1230 | return 0; 1231 | } 1232 | 1233 | static void __exit turbomem_exit(void) 1234 | { 1235 | pci_unregister_driver(&pci_driver); 1236 | turbomem_debugfs_cleanup(); 1237 | } 1238 | 1239 | MODULE_LICENSE("GPL"); 1240 | MODULE_DESCRIPTION("Intel(R) Turbo Memory Controller driver"); 1241 | MODULE_AUTHOR("Erik Ekman "); 1242 | 1243 | module_init(turbomem_init); 1244 | module_exit(turbomem_exit); 1245 | --------------------------------------------------------------------------------