Overo用のspiドライバ
/dev/spi-ad
サブCPU基板からSPIでADデータを取得する。
| Revision | 762610c370c52b8589ce580bf4744658fd7be5e0 (tree) |
|---|---|
| Time | 2016-02-29 10:32:11 |
| Author | Naoya Takamura <ntaka206@user...> |
| Commiter | Naoya Takamura |
kernel3.18対応
kernel3.18用に変更した他のspike-adを参考にして変更した
makeではなくbitbakeでbuildするように変更した
SPI速度を500KHz->50KHzに変更
bus_find_device_by_name()で見つけたデバイスをdevice_del()で取り除くようにした
| @@ -1,20 +0,0 @@ | ||
| 1 | -DRIVER = spike-ad | |
| 2 | - | |
| 3 | -ifneq ($(KERNELRELEASE),) | |
| 4 | - obj-m := $(DRIVER).o | |
| 5 | -else | |
| 6 | - PWD := $(shell pwd) | |
| 7 | - | |
| 8 | -default: | |
| 9 | -ifeq ($(strip $(KERNELDIR)),) | |
| 10 | - $(error "KERNELDIR is undefined!") | |
| 11 | -else | |
| 12 | - $(MAKE) -C $(KERNELDIR) M=$(PWD) modules | |
| 13 | -endif | |
| 14 | - | |
| 15 | - | |
| 16 | -clean: | |
| 17 | - rm -rf *~ *.ko *.o *.mod.c modules.order Module.symvers .$(DRIVER)* .tmp_versions | |
| 18 | - | |
| 19 | -endif | |
| 20 | - |
| @@ -0,0 +1,340 @@ | ||
| 1 | + GNU GENERAL PUBLIC LICENSE | |
| 2 | + Version 2, June 1991 | |
| 3 | + | |
| 4 | + Copyright (C) 1989, 1991 Free Software Foundation, Inc. | |
| 5 | + 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 | + <one line to give the program's name and a brief idea of what it does.> | |
| 294 | + Copyright (C) <year> <name of author> | |
| 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 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 | + <signature of Ty Coon>, 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. |
| @@ -0,0 +1,15 @@ | ||
| 1 | +obj-m := spikead.o | |
| 2 | +spikead-y := spike-ad.o | |
| 3 | + | |
| 4 | +SRC := $(shell pwd) | |
| 5 | + | |
| 6 | +all: | |
| 7 | + $(MAKE) -C $(KERNEL_SRC) M=$(SRC) | |
| 8 | + | |
| 9 | +modules_install: | |
| 10 | + $(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install | |
| 11 | + | |
| 12 | +clean: | |
| 13 | + rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c | |
| 14 | + rm -f Module.markers Module.symvers modules.order | |
| 15 | + rm -rf .tmp_versions Modules.symvers |
| @@ -4,9 +4,22 @@ | ||
| 4 | 4 | |
| 5 | 5 | GPIO144 DRDY signal from PIC24@CPU2010 |
| 6 | 6 | SPI2 AD data receive and CMD send for PIC24@CPU2010 |
| 7 | + | |
| 8 | + **** Ver1.1 2016/2 | |
| 9 | + * kernel3.18対応 | |
| 10 | + * kernel3.18用に変更した他のspike-adを参考にして変更した | |
| 11 | + * makeではなくbitbakeでbuildするように変更した | |
| 12 | + * SPI速度を500KHz->50KHzに変更 | |
| 13 | + * bus_find_device_by_name()で見つけたデバイスをdevice_del()で取り除くようにした | |
| 14 | + * | |
| 15 | + * Make方法 | |
| 16 | + * $ cd dev/overo-yocto-2015/ | |
| 17 | + * $ . poky/oe-init-build-env | |
| 18 | + * $ bitbake spike-ad | |
| 7 | 19 | |
| 8 | 20 | Copyright Naoya Takamura, 2011 |
| 9 | 21 | This program based on spike.c |
| 22 | + | |
| 10 | 23 | --------------------------------------------- |
| 11 | 24 | spike.c |
| 12 | 25 |
| @@ -27,8 +40,9 @@ | ||
| 27 | 40 | Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
| 28 | 41 | */ |
| 29 | 42 | |
| 43 | +#include <linux/kernel.h> /* We're doing kernel work */ | |
| 44 | +#include <linux/module.h> /* Specifically, a module */ | |
| 30 | 45 | #include <linux/init.h> |
| 31 | -#include <linux/module.h> | |
| 32 | 46 | #include <linux/fs.h> |
| 33 | 47 | #include <linux/device.h> |
| 34 | 48 | #include <linux/mutex.h> |
| @@ -45,6 +59,8 @@ | ||
| 45 | 59 | #include <linux/wait.h> |
| 46 | 60 | #include <linux/sched.h> |
| 47 | 61 | #include <asm/atomic.h> |
| 62 | +#include <asm/irq.h> | |
| 63 | +#include <linux/hrtimer.h> | |
| 48 | 64 | |
| 49 | 65 | #include "spike-ad.h" |
| 50 | 66 |
| @@ -53,7 +69,8 @@ | ||
| 53 | 69 | |
| 54 | 70 | #define SPI_BUS 1 |
| 55 | 71 | #define SPI_BUS_CS0 0 |
| 56 | -#define SPI_BUS_SPEED 500000 // Hz | |
| 72 | +//#define SPI_BUS_SPEED 500000 // Hz 2us/bit | |
| 73 | +#define SPI_BUS_SPEED 50000 // Hz 20us/bit | |
| 57 | 74 | |
| 58 | 75 | #define SPI_DATA_SIZE (965+1) // $含む PICから受信するデータ長 DMA問題のために+1byteしている |
| 59 | 76 |
| @@ -64,9 +81,13 @@ | ||
| 64 | 81 | #define GPIO_TOGGLE_OUT 145 // Debug用toggle出力 = GPIO145 |
| 65 | 82 | #endif |
| 66 | 83 | |
| 84 | +// SPI受信タイムアウト用タイマ | |
| 85 | +#define SPI_TIMEOUT_SEC 3 | |
| 86 | +#define SPI_TIMEOUT_NS 0 | |
| 87 | + | |
| 67 | 88 | /**** 注意! Version */ |
| 68 | -#define VERSION "1.0" | |
| 69 | -#define MODULE_NAME "spike-ad" | |
| 89 | +#define VERSION "1.1" | |
| 90 | +#define MODULE_NAME "spikead" | |
| 70 | 91 | |
| 71 | 92 | const char this_driver_name[] = MODULE_NAME; |
| 72 | 93 |
| @@ -102,7 +123,7 @@ struct spike_dev { | ||
| 102 | 123 | struct class *class; |
| 103 | 124 | struct spi_device *spi_device; |
| 104 | 125 | char *user_buff; |
| 105 | -// u8 test_data; | |
| 126 | + struct hrtimer timer; | |
| 106 | 127 | }; |
| 107 | 128 | |
| 108 | 129 | static struct spike_dev spike_dev; |
| @@ -111,15 +132,11 @@ static struct spike_dev spike_dev; | ||
| 111 | 132 | typedef struct { |
| 112 | 133 | unsigned long f_version; // 識別用 f_version |
| 113 | 134 | wait_queue_head_t wait; /* read and write queues */ |
| 135 | + struct semaphore finfo_sem; | |
| 114 | 136 | int sleep_mode; // 0: 起きてる 1: 待ち |
| 115 | - int intflag; // 割り込みフラグ 1=割り込み入った | |
| 116 | 137 | } FileInfo; |
| 117 | 138 | |
| 118 | 139 | static FileInfo finfo; |
| 119 | - | |
| 120 | -void spike_tasklet_func(unsigned long data); | |
| 121 | -DECLARE_TASKLET(spike_tasklet, spike_tasklet_func, 0); | |
| 122 | - | |
| 123 | 140 | // |
| 124 | 141 | /**** SPI受信データ リングバッファ ****************************************** |
| 125 | 142 | */ |
| @@ -203,13 +220,46 @@ int ring_full(void) | ||
| 203 | 220 | return 0; |
| 204 | 221 | } |
| 205 | 222 | |
| 206 | - | |
| 223 | +// | |
| 224 | +/**** SPI受信終了ハンドラ ****************************************** | |
| 225 | + */ | |
| 207 | 226 | /* |
| 208 | - spike_queue_spi_write()で開始した | |
| 209 | - spi_async()終了後に呼ばれる | |
| 210 | - つまりSPIでデータを受信完了した状態 | |
| 227 | + SPI受信 Completion Handlerでスケジュールされるタスクレット関数 | |
| 228 | + SPI受信データ処理をする | |
| 211 | 229 | */ |
| 212 | -static void spike_spi_completion_handler(void *arg) | |
| 230 | +void spike_spi_completion_tasklet_func(unsigned long arg) | |
| 231 | +{ | |
| 232 | +//printk(KERN_INFO MODULE_NAME" %s\n", __FUNCTION__); | |
| 233 | + // ここatomic spike_ctl | |
| 234 | + if (down_interruptible(&spike_ctl.cmd_sem)) { | |
| 235 | + return; | |
| 236 | + } | |
| 237 | + spike_ctl.busy = 0; | |
| 238 | + spike_ctl.spi_callbacks++; | |
| 239 | + up(&spike_ctl.cmd_sem); | |
| 240 | + // ここatomic finfo | |
| 241 | + if (down_interruptible(&finfo.finfo_sem)) { | |
| 242 | + return; | |
| 243 | + } | |
| 244 | + // 寝ているものを起こす | |
| 245 | + if (finfo.sleep_mode) { | |
| 246 | + // 待ちを | |
| 247 | + wake_up_interruptible(&(finfo.wait)); // 起こす | |
| 248 | + //printk(KERN_INFO "intsel_interrupt: wakeup %ld\n", fi[i].f_version); | |
| 249 | + // この間でpoll()でsleep_mode=1になるとまずいのでセマフォで保護している。 | |
| 250 | + finfo.sleep_mode = 0; | |
| 251 | + } | |
| 252 | + up(&finfo.finfo_sem); | |
| 253 | +} | |
| 254 | +// タスクレット宣言 | |
| 255 | +DECLARE_TASKLET(spike_spi_completion_tasklet, spike_spi_completion_tasklet_func, 0); | |
| 256 | +/* | |
| 257 | + SPI受信 Completion Handler | |
| 258 | + spike_queue_spi_write()で開始したspi_async()終了後に呼ばれる | |
| 259 | + つまりSPIでデータを受信完了すると呼ばれる | |
| 260 | + Sleep禁止 | |
| 261 | + */ | |
| 262 | +void spike_spi_completion_handler(void *arg) | |
| 213 | 263 | { |
| 214 | 264 | unsigned char *p; |
| 215 | 265 |
| @@ -221,21 +271,24 @@ static void spike_spi_completion_handler(void *arg) | ||
| 221 | 271 | memcpy(p, spike_ctl.rx_buff, SPI_DATA_SIZE); |
| 222 | 272 | // 実際に受信できたデータ長 |
| 223 | 273 | spike_ctl.received_len = spike_ctl.msg.actual_length; |
| 224 | - | |
| 225 | 274 | // 書き込み位置進める |
| 226 | 275 | ring_write_plus(); |
| 227 | 276 | |
| 228 | - // 寝ているものを起こす | |
| 229 | - if (finfo.sleep_mode) { | |
| 230 | - // 待ちを | |
| 231 | - wake_up_interruptible(&(finfo.wait)); // 起こす | |
| 232 | -//printk(KERN_INFO "intsel_interrupt: wakeup %ld\n", fi[i].f_version); | |
| 233 | - finfo.sleep_mode = 0; | |
| 234 | - finfo.intflag = 1; | |
| 235 | - } | |
| 277 | + // SPI受信タイムアウトタイマ停止 | |
| 278 | + hrtimer_cancel(&spike_dev.timer); | |
| 279 | + // DRDY割り込みON | |
| 280 | + // ココでONにするとGPS受信状態が悪い時などにctrl.busy=1のまま割り込みが入ってしまう可能性があるが、busyは参照していないので良しとする | |
| 281 | + enable_irq(spike_ctl.irq); | |
| 282 | + | |
| 283 | + // 後はタスクレットに任せる | |
| 284 | + tasklet_hi_schedule(&spike_spi_completion_tasklet); | |
| 236 | 285 | } |
| 286 | +// | |
| 287 | +/**** DRDY割り込み関係 ****************************************** | |
| 288 | + */ | |
| 237 | 289 | /* |
| 238 | - spi_async()で送信開始 | |
| 290 | + タスクレットから呼ばれる | |
| 291 | + spi_async()で送信開始する | |
| 239 | 292 | 受信データはcallback funcで受ける |
| 240 | 293 | */ |
| 241 | 294 | static int spike_queue_spi_write(void) |
| @@ -243,62 +296,93 @@ static int spike_queue_spi_write(void) | ||
| 243 | 296 | int status; |
| 244 | 297 | unsigned long flags; |
| 245 | 298 | |
| 246 | - // struct spi_messageを初期化 ゼロクリア | |
| 247 | - spi_message_init(&spike_ctl.msg); | |
| 299 | +//printk(KERN_INFO MODULE_NAME" %s\n", __FUNCTION__); | |
| 248 | 300 | |
| 249 | - // Callback関数設定 | |
| 250 | - spike_ctl.msg.complete = spike_spi_completion_handler; | |
| 251 | - spike_ctl.msg.context = NULL; | |
| 252 | - | |
| 253 | - memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE); | |
| 254 | - memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE); | |
| 255 | - | |
| 256 | - if (down_interruptible(&spike_ctl.cmd_sem)) | |
| 301 | +// ここatomic spike_ctl | |
| 302 | + if (down_interruptible(&spike_ctl.cmd_sem)) { | |
| 257 | 303 | return -ERESTARTSYS; |
| 304 | + } | |
| 305 | + // struct spi_messageを初期化 ゼロクリア | |
| 306 | + spi_message_init(&spike_ctl.msg); | |
| 307 | + // Callback関数設定 | |
| 308 | + spike_ctl.msg.complete = spike_spi_completion_handler; | |
| 309 | + spike_ctl.msg.context = NULL; | |
| 310 | + memset(spike_ctl.tx_buff, 0, SPI_BUFF_SIZE); | |
| 311 | + memset(spike_ctl.rx_buff, 0, SPI_BUFF_SIZE); | |
| 258 | 312 | // TXコマンドセット |
| 259 | 313 | memcpy(spike_ctl.tx_buff, spike_ctl.cmd_buf, spike_ctl.cmd_len); |
| 260 | 314 | // TXコマンドクリア |
| 261 | 315 | memset(spike_ctl.cmd_buf, 0, SPI_CMD_MAX); |
| 262 | - up(&spike_ctl.cmd_sem); | |
| 316 | + spike_ctl.transfer.tx_buf = spike_ctl.tx_buff; | |
| 317 | + spike_ctl.transfer.rx_buf = spike_ctl.rx_buff; | |
| 318 | + spike_ctl.transfer.len = SPI_DATA_SIZE; | |
| 263 | 319 | |
| 264 | - spike_ctl.transfer.tx_buf = spike_ctl.tx_buff; | |
| 265 | - spike_ctl.transfer.rx_buf = spike_ctl.rx_buff; | |
| 266 | - spike_ctl.transfer.len = SPI_DATA_SIZE; | |
| 320 | + spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); | |
| 321 | + up(&spike_ctl.cmd_sem); | |
| 322 | + // ここまでatomic | |
| 267 | 323 | |
| 268 | - spi_message_add_tail(&spike_ctl.transfer, &spike_ctl.msg); | |
| 324 | + // DRDY割り込みOFF | |
| 325 | + // PICのバッファにデータがあるとSPI受信中に再度DRDYがLowになり割り込みがかかってしまうため | |
| 326 | + disable_irq(spike_ctl.irq); | |
| 269 | 327 | |
| 328 | + // SpinLock | |
| 270 | 329 | spin_lock_irqsave(&spike_dev.spi_lock, flags); |
| 271 | - | |
| 272 | - if (spike_dev.spi_device) | |
| 273 | - status = spi_async(spike_dev.spi_device, &spike_ctl.msg); | |
| 274 | - else | |
| 275 | - status = -ENODEV; | |
| 276 | - | |
| 330 | + // SPI送受信開始 | |
| 331 | + if (spike_dev.spi_device) | |
| 332 | + status = spi_async(spike_dev.spi_device, &spike_ctl.msg); | |
| 333 | + else | |
| 334 | + status = -ENODEV; | |
| 277 | 335 | spin_unlock_irqrestore(&spike_dev.spi_lock, flags); |
| 278 | 336 | |
| 279 | - if (status == 0) | |
| 337 | + if (status == 0) { | |
| 280 | 338 | spike_ctl.busy = 1; |
| 281 | - | |
| 339 | + // SPI受信タイムアウトタイマスタート | |
| 340 | + hrtimer_start(&spike_dev.timer, | |
| 341 | + ktime_set(SPI_TIMEOUT_SEC, SPI_TIMEOUT_NS), | |
| 342 | + HRTIMER_MODE_REL); | |
| 343 | + return status; | |
| 344 | + } | |
| 345 | + | |
| 346 | + // SPIがエラーなのでDRDY割り込みONに戻す | |
| 347 | + enable_irq(spike_ctl.irq); | |
| 348 | + switch(status) { | |
| 349 | + case -ENODEV: | |
| 350 | + printk(KERN_WARNING "%s %s spi_async()=ENODEV\n", MODULE_NAME, __FUNCTION__); | |
| 351 | + break; | |
| 352 | + case -EBUSY: | |
| 353 | + printk(KERN_WARNING "%s %s spi_async()=EBUSY\n", MODULE_NAME, __FUNCTION__); | |
| 354 | + break; | |
| 355 | + case -EINVAL: | |
| 356 | + printk(KERN_WARNING "%s %s spi_async()=EINVAL\n", MODULE_NAME, __FUNCTION__); | |
| 357 | + break; | |
| 358 | + default: | |
| 359 | + printk(KERN_WARNING "%s %s spi_async()=%d\n", MODULE_NAME, __FUNCTION__, status); | |
| 360 | + break; | |
| 361 | + } | |
| 282 | 362 | return status; |
| 283 | 363 | } |
| 284 | 364 | /* |
| 285 | - Tasklet | |
| 286 | - IRQ Handlerで呼び出される | |
| 365 | + タスクレット | |
| 366 | + IRQ Handlerで呼び出しがスケジュールされる | |
| 287 | 367 | SPI送受信を開始する |
| 288 | 368 | */ |
| 289 | 369 | void spike_tasklet_func(unsigned long data) |
| 290 | 370 | { |
| 291 | 371 | int status; |
| 372 | +//printk(KERN_INFO "%s %s()\n", MODULE_NAME, __FUNCTION__); | |
| 292 | 373 | // SPI送受信開始 |
| 293 | 374 | status = spike_queue_spi_write(); |
| 294 | 375 | if (status) { |
| 295 | 376 | // error |
| 377 | + printk(KERN_ERR "%s %s spike_queue_spi_write()=%d\n", MODULE_NAME, __FUNCTION__, status); | |
| 296 | 378 | } else { |
| 297 | 379 | // ok |
| 298 | 380 | } |
| 299 | 381 | } |
| 382 | +// タスクレット宣言 | |
| 383 | +DECLARE_TASKLET(spike_tasklet, spike_tasklet_func, 0); | |
| 300 | 384 | /* |
| 301 | - DRDY Interrupt Handler | |
| 385 | + DRDY 割り込みハンドラ | |
| 302 | 386 | */ |
| 303 | 387 | static irqreturn_t irq_handler(int irq, void *dev_id) |
| 304 | 388 | { |
| @@ -310,86 +394,30 @@ static irqreturn_t irq_handler(int irq, void *dev_id) | ||
| 310 | 394 | } |
| 311 | 395 | #endif |
| 312 | 396 | // タスクレットにまかせる |
| 313 | - tasklet_schedule(&spike_tasklet); | |
| 397 | + tasklet_hi_schedule(&spike_tasklet); | |
| 314 | 398 | |
| 315 | 399 | return IRQ_HANDLED; |
| 316 | 400 | } |
| 317 | -#if 0 | |
| 318 | -static ssize_t spike_file_read(struct file *filp, char __user *buff, size_t count, | |
| 319 | - loff_t *offp) | |
| 401 | +// | |
| 402 | +/**** High Res. Timer Callback ***************************************** | |
| 403 | + * SPI受信が正常に終了しなかった場合にタイムアウトで呼ばれる | |
| 404 | + * DRDY割り込みを有効にする | |
| 405 | + */ | |
| 406 | +static enum hrtimer_restart spike_timer_callback(struct hrtimer *timer) | |
| 320 | 407 | { |
| 321 | - size_t len; | |
| 322 | - ssize_t status = 0; | |
| 323 | - | |
| 324 | - if (!buff) | |
| 325 | - return -EFAULT; | |
| 326 | - | |
| 327 | - if (*offp > 0) | |
| 328 | - return 0; | |
| 329 | - | |
| 330 | - if (down_interruptible(&spike_dev.fop_sem)) | |
| 331 | - return -ERESTARTSYS; | |
| 332 | - | |
| 333 | -if (spike_ctl.busy) { | |
| 334 | - sprintf(spike_dev.user_buff, "spike_ctl.busy==1\n"); | |
| 335 | - count = strlen(spike_dev.user_buff); | |
| 336 | - up(&spike_dev.fop_sem); | |
| 337 | - return count; | |
| 338 | -} else { | |
| 339 | -//sprintf(spike_dev.user_buff, "DMA\n"); | |
| 340 | - | |
| 341 | - sprintf(spike_dev.user_buff, | |
| 342 | - "Status: %d\nTX: %d %d %d %d\nRX: %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\nCallback=%d DRDY=%d\n", | |
| 343 | - spike_ctl.msg.status, | |
| 344 | - spike_ctl.tx_buff[0], spike_ctl.tx_buff[1], | |
| 345 | - spike_ctl.tx_buff[2], spike_ctl.tx_buff[3], | |
| 346 | - spike_ctl.rx_buff[0], spike_ctl.rx_buff[1], | |
| 347 | - spike_ctl.rx_buff[2], spike_ctl.rx_buff[3], | |
| 348 | - spike_ctl.rx_buff[4], spike_ctl.rx_buff[5], | |
| 349 | - spike_ctl.rx_buff[6], spike_ctl.rx_buff[7], | |
| 350 | - spike_ctl.rx_buff[8], spike_ctl.rx_buff[9], | |
| 351 | - spike_ctl.rx_buff[10], spike_ctl.rx_buff[11], | |
| 352 | - spike_ctl.rx_buff[12], spike_ctl.rx_buff[13], | |
| 353 | - spike_ctl.rx_buff[14], spike_ctl.rx_buff[15], | |
| 354 | - spike_ctl.spi_callbacks, gpio_get_value(GPIO_DRDY_IN)); | |
| 355 | - | |
| 356 | -} | |
| 357 | -// status = spike_do_one_message(); | |
| 358 | -//status = spike_send_cmd(); | |
| 359 | -//status = spike_rcv_data(); | |
| 360 | - | |
| 361 | -#if 0 | |
| 362 | -// SPI送受信開始 | |
| 363 | -status = spike_queue_spi_write(); | |
| 364 | - | |
| 365 | - if (status) { | |
| 366 | - sprintf(spike_dev.user_buff, | |
| 367 | - "spike_do_one_message failed : %d\n", | |
| 368 | - status); | |
| 369 | - } | |
| 370 | - else { | |
| 408 | + // DRDY割り込みON | |
| 409 | + if (spike_ctl.irq > 0) { | |
| 410 | + enable_irq(spike_ctl.irq); | |
| 371 | 411 | } |
| 372 | -#endif | |
| 373 | - | |
| 374 | - len = strlen(spike_dev.user_buff); | |
| 375 | - | |
| 376 | - if (len < count) | |
| 377 | - count = len; | |
| 378 | - | |
| 379 | - if (copy_to_user(buff, spike_dev.user_buff, count)) { | |
| 380 | - printk(KERN_ALERT "spike_read(): copy_to_user() failed\n"); | |
| 381 | - status = -EFAULT; | |
| 382 | - } else { | |
| 383 | - *offp += count; | |
| 384 | - status = count; | |
| 385 | - } | |
| 386 | - | |
| 387 | - up(&spike_dev.fop_sem); | |
| 388 | - | |
| 389 | - return status; | |
| 412 | + printk(KERN_WARNING "%s %s spi rcv timeout\n", MODULE_NAME, __FUNCTION__); | |
| 413 | +//printk(KERN_INFO "timer!\n"); | |
| 414 | + return HRTIMER_NORESTART; | |
| 390 | 415 | } |
| 391 | -#endif | |
| 392 | - | |
| 416 | +// | |
| 417 | +/**** spike file operation ******************************************* | |
| 418 | + * デバイスファイル操作関係 | |
| 419 | + */ | |
| 420 | +// OPEN | |
| 393 | 421 | static int spike_file_open(struct inode *inode, struct file *filp) |
| 394 | 422 | { |
| 395 | 423 | int status = 0; |
| @@ -399,60 +427,72 @@ static int spike_file_open(struct inode *inode, struct file *filp) | ||
| 399 | 427 | if (down_interruptible(&spike_dev.fop_sem)) |
| 400 | 428 | return -ERESTARTSYS; |
| 401 | 429 | |
| 402 | - if (!spike_dev.user_buff) { | |
| 403 | - spike_dev.user_buff = kmalloc(USER_BUFF_SIZE, GFP_KERNEL); | |
| 404 | - if (!spike_dev.user_buff) | |
| 405 | - status = -ENOMEM; | |
| 406 | - } | |
| 407 | - | |
| 408 | - if (finfo.f_version != 0) { | |
| 409 | - printk(KERN_INFO "spike_open: busy\n"); | |
| 410 | - return -EBUSY; | |
| 411 | - } | |
| 430 | + if (!spike_dev.user_buff) { | |
| 431 | + spike_dev.user_buff = kmalloc(USER_BUFF_SIZE, GFP_KERNEL); | |
| 432 | + if (!spike_dev.user_buff) | |
| 433 | + status = -ENOMEM; | |
| 434 | + } | |
| 412 | 435 | |
| 413 | - finfo.f_version = filp->f_version; | |
| 414 | - finfo.sleep_mode = 0; | |
| 415 | - finfo.intflag = 0; | |
| 416 | - init_waitqueue_head(&(finfo.wait)); | |
| 417 | - filp->private_data = (void*)&finfo; // プライベートデータに構造体ポインタ設定 | |
| 436 | + if (finfo.f_version != 0) { | |
| 437 | + printk(KERN_INFO "spike_open: busy\n"); | |
| 438 | + up(&spike_dev.fop_sem); | |
| 439 | + return -EBUSY; | |
| 440 | + } | |
| 418 | 441 | |
| 419 | - ring_clear(); | |
| 442 | + finfo.f_version = filp->f_version; | |
| 443 | + finfo.sleep_mode = 0; | |
| 444 | + init_waitqueue_head(&(finfo.wait)); | |
| 445 | + filp->private_data = (void*)&finfo; // プライベートデータに構造体ポインタ設定 | |
| 420 | 446 | |
| 421 | 447 | up(&spike_dev.fop_sem); |
| 422 | 448 | |
| 449 | + spike_ctl.busy = 0; | |
| 450 | + | |
| 451 | + ring_clear(); | |
| 452 | + | |
| 423 | 453 | return status; |
| 424 | 454 | } |
| 425 | - | |
| 455 | +// CLOSE | |
| 426 | 456 | static int spike_file_close(struct inode * inode, struct file * file) |
| 427 | 457 | { |
| 428 | 458 | // printk(KERN_INFO "spike_close: (%Lu)\n",file->f_version); |
| 429 | 459 | |
| 430 | 460 | ((FileInfo *)(file->private_data))->f_version = 0; |
| 431 | 461 | ((FileInfo *)(file->private_data))->sleep_mode = 0; |
| 432 | - ((FileInfo *)(file->private_data))->intflag = 0; | |
| 433 | 462 | return 0; |
| 434 | 463 | } |
| 435 | - | |
| 464 | +/* | |
| 465 | + * poll | |
| 466 | + */ | |
| 436 | 467 | static unsigned int spike_file_poll(struct file *file, struct poll_table_struct *ptab) |
| 437 | 468 | { |
| 438 | 469 | //printk(KERN_INFO "spike_file_poll: (%ld)\n",file->f_version); |
| 439 | - // 割り込み入っている | |
| 440 | - if ( ((FileInfo *)(file->private_data))->intflag ) { | |
| 441 | - // フラグクリア | |
| 442 | - ((FileInfo *)(file->private_data))->intflag = 0; | |
| 443 | -//printk(KERN_INFO "spike_file_poll: (%ld) interrupted\n",file->f_version); | |
| 444 | - return POLLIN | POLLRDNORM; // 読み込みOK | |
| 445 | - } | |
| 446 | - // 割り込み入っていないので待ち行列に追加する 割り込みハンドラが起こす | |
| 447 | - poll_wait(file, &(((FileInfo *)(file->private_data))->wait), ptab); | |
| 448 | -//printk(KERN_INFO "spike_file_poll: (%ld) poll_wait\n",file->f_version); | |
| 449 | 470 | |
| 450 | - // sleep_mode=寝ている | |
| 451 | - ((FileInfo *)(file->private_data))->sleep_mode = 1; | |
| 471 | + // atomicにしておく | |
| 472 | + if (down_interruptible(&finfo.finfo_sem)) | |
| 473 | + return -ERESTARTSYS; | |
| 474 | + | |
| 475 | + // ringバッファにデータがあれば | |
| 476 | + if (ring_num_get() > 0) { | |
| 477 | + up(&finfo.finfo_sem); | |
| 478 | + return POLLIN | POLLRDNORM; // 読み込みOK | |
| 479 | + } | |
| 480 | + // ココで割り込みが入ってspike_spi_completion_handler()でring write位置が進むとまずい | |
| 481 | + | |
| 482 | + // 待ち行列に追加する 割り込みハンドラが起こす | |
| 483 | + poll_wait(file, &(((FileInfo *)(file->private_data))->wait), ptab); | |
| 484 | + //printk(KERN_INFO "spike_file_poll: (%ld) poll_wait\n",file->f_version); | |
| 485 | + | |
| 486 | + // sleep_mode=寝ている | |
| 487 | + ((FileInfo *)(file->private_data))->sleep_mode = 1; | |
| 488 | + | |
| 489 | + up(&finfo.finfo_sem); | |
| 452 | 490 | |
| 453 | 491 | return 0; |
| 454 | 492 | } |
| 455 | - | |
| 493 | +/* | |
| 494 | + * ioctl | |
| 495 | + */ | |
| 456 | 496 | static long spike_file_ioctl(struct file *file, unsigned int cmd, unsigned long arg) |
| 457 | 497 | { |
| 458 | 498 | int i; |
| @@ -462,26 +502,30 @@ static long spike_file_ioctl(struct file *file, unsigned int cmd, unsigned long | ||
| 462 | 502 | switch(cmd) { |
| 463 | 503 | // SPI送信データ長セット |
| 464 | 504 | case CMD_TX_LEN: |
| 465 | - if (down_interruptible(&spike_ctl.cmd_sem)) | |
| 505 | + // atomic spike_ctl | |
| 506 | + if (down_interruptible(&spike_ctl.cmd_sem)) { | |
| 466 | 507 | return -ERESTARTSYS; |
| 467 | - if (copy_from_user(&spike_ctl.cmd_len, (void *)arg, sizeof(int))) { | |
| 468 | - printk(KERN_ALERT "spike_file_ioctl(): copy_from_user() failed\n"); | |
| 469 | - up(&spike_ctl.cmd_sem); | |
| 470 | - return -EFAULT; | |
| 471 | 508 | } |
| 472 | -//printk(KERN_INFO "spike_file_ioctl: CMD_TX_LEN %d\n", spike_ctl.cmd_len); | |
| 473 | - if (spike_ctl.cmd_len > SPI_CMD_MAX) spike_ctl.cmd_len = SPI_CMD_MAX; | |
| 509 | + if (copy_from_user(&spike_ctl.cmd_len, (void *)arg, sizeof(int))) { | |
| 510 | + printk(KERN_ALERT "spike_file_ioctl(): copy_from_user() failed\n"); | |
| 511 | + up(&spike_ctl.cmd_sem); | |
| 512 | + return -EFAULT; | |
| 513 | + } | |
| 514 | + //printk(KERN_INFO "spike_file_ioctl: CMD_TX_LEN %d\n", spike_ctl.cmd_len); | |
| 515 | + if (spike_ctl.cmd_len > SPI_CMD_MAX) spike_ctl.cmd_len = SPI_CMD_MAX; | |
| 474 | 516 | up(&spike_ctl.cmd_sem); |
| 475 | 517 | return 0; |
| 476 | 518 | // SPI送信データセット |
| 477 | 519 | case CMD_TX_SET: |
| 478 | - if (down_interruptible(&spike_ctl.cmd_sem)) | |
| 520 | + // atomic spike_ctl | |
| 521 | + if (down_interruptible(&spike_ctl.cmd_sem)) { | |
| 479 | 522 | return -ERESTARTSYS; |
| 480 | - if (copy_from_user(&spike_ctl.cmd_buf, (void *)arg, spike_ctl.cmd_len)) { | |
| 481 | - printk(KERN_ALERT "spike_file_ioctl(): copy_from_user() failed\n"); | |
| 482 | - up(&spike_ctl.cmd_sem); | |
| 483 | - return -EFAULT; | |
| 484 | 523 | } |
| 524 | + if (copy_from_user(&spike_ctl.cmd_buf, (void *)arg, spike_ctl.cmd_len)) { | |
| 525 | + printk(KERN_ALERT "spike_file_ioctl(): copy_from_user() failed\n"); | |
| 526 | + up(&spike_ctl.cmd_sem); | |
| 527 | + return -EFAULT; | |
| 528 | + } | |
| 485 | 529 | //printk(KERN_INFO "spike_file_ioctl: CMD_TX_SET %02X %02X %02X %02X\n", spike_ctl.cmd_buf[0], spike_ctl.cmd_buf[1], spike_ctl.cmd_buf[2], spike_ctl.cmd_buf[3]); |
| 486 | 530 | up(&spike_ctl.cmd_sem); |
| 487 | 531 | return 0; |
| @@ -521,7 +565,7 @@ static long spike_file_ioctl(struct file *file, unsigned int cmd, unsigned long | ||
| 521 | 565 | return 0; |
| 522 | 566 | } |
| 523 | 567 | } |
| 524 | - | |
| 568 | +// File Operation構造体初期化 | |
| 525 | 569 | static const struct file_operations spike_fops = { |
| 526 | 570 | .owner = THIS_MODULE, |
| 527 | 571 | // .read = spike_file_read, |
| @@ -530,14 +574,18 @@ static const struct file_operations spike_fops = { | ||
| 530 | 574 | .poll = spike_file_poll, |
| 531 | 575 | .unlocked_ioctl = spike_file_ioctl, |
| 532 | 576 | }; |
| 533 | - | |
| 534 | - | |
| 535 | -static int spike_probe(struct spi_device *spi_device) | |
| 577 | +// | |
| 578 | +/**** spi device operation ******************************************* | |
| 579 | + */ | |
| 580 | +static int spike_probe(struct spi_device *spi) | |
| 536 | 581 | { |
| 537 | 582 | unsigned long flags; |
| 538 | 583 | |
| 584 | +printk(KERN_INFO "%s %s() bus=%d,cs=%d\n", MODULE_NAME, __FUNCTION__, spi->master->bus_num, spi->chip_select); | |
| 585 | + | |
| 586 | + // SpinLock | |
| 539 | 587 | spin_lock_irqsave(&spike_dev.spi_lock, flags); |
| 540 | - spike_dev.spi_device = spi_device; | |
| 588 | + spike_dev.spi_device = spi; | |
| 541 | 589 | spin_unlock_irqrestore(&spike_dev.spi_lock, flags); |
| 542 | 590 | |
| 543 | 591 | return 0; |
| @@ -546,13 +594,31 @@ static int spike_probe(struct spi_device *spi_device) | ||
| 546 | 594 | static int spike_remove(struct spi_device *spi_device) |
| 547 | 595 | { |
| 548 | 596 | unsigned long flags; |
| 597 | +printk(KERN_INFO "%s %s()\n", MODULE_NAME, __FUNCTION__); | |
| 549 | 598 | |
| 599 | + // SPI受信タイムアウトタイマ停止 | |
| 600 | + hrtimer_cancel(&spike_dev.timer); | |
| 601 | + // SpinLock | |
| 550 | 602 | spin_lock_irqsave(&spike_dev.spi_lock, flags); |
| 551 | - spike_dev.spi_device = NULL; | |
| 603 | + spike_dev.spi_device = NULL; | |
| 552 | 604 | spin_unlock_irqrestore(&spike_dev.spi_lock, flags); |
| 553 | 605 | |
| 554 | 606 | return 0; |
| 555 | 607 | } |
| 608 | +// SPI Driver構造体初期化 | |
| 609 | +static struct spi_driver spike_driver = { | |
| 610 | + .driver = { | |
| 611 | + .name = this_driver_name, | |
| 612 | + .owner = THIS_MODULE, | |
| 613 | + }, | |
| 614 | + .probe = spike_probe, | |
| 615 | + .remove = spike_remove, | |
| 616 | +}; | |
| 617 | +// | |
| 618 | +/**** spike_init()関係 ***************************************************** | |
| 619 | + * モジュール初期化 load | |
| 620 | + * モジュール終了 unload | |
| 621 | + */ | |
| 556 | 622 | /* |
| 557 | 623 | SPIデバイスの設定 |
| 558 | 624 | */ |
| @@ -571,72 +637,50 @@ static int __init add_spike_device_to_bus(void) | ||
| 571 | 637 | printk(KERN_ALERT "Missing modprobe omap2_mcspi?\n"); |
| 572 | 638 | return -1; |
| 573 | 639 | } |
| 574 | - | |
| 575 | 640 | spi_device = spi_alloc_device(spi_master); |
| 576 | 641 | if (!spi_device) { |
| 577 | 642 | put_device(&spi_master->dev); |
| 578 | 643 | printk(KERN_ALERT "spi_alloc_device() failed\n"); |
| 579 | 644 | return -1; |
| 580 | 645 | } |
| 581 | - | |
| 646 | + // 使用するCSx設定 | |
| 582 | 647 | spi_device->chip_select = SPI_BUS_CS0; |
| 583 | - | |
| 584 | 648 | /* Check whether this SPI bus.cs is already claimed */ |
| 585 | 649 | snprintf(buff, sizeof(buff), "%s.%u", |
| 586 | 650 | dev_name(&spi_device->master->dev), |
| 587 | 651 | spi_device->chip_select); |
| 588 | - | |
| 589 | 652 | pdev = bus_find_device_by_name(spi_device->dev.bus, NULL, buff); |
| 590 | 653 | if (pdev) { |
| 591 | - /* We are not going to use this spi_device, so free it */ | |
| 654 | + // デバイス取り除く | |
| 655 | + device_del(pdev); | |
| 656 | + } | |
| 657 | + spi_device->max_speed_hz = SPI_BUS_SPEED; | |
| 658 | + spi_device->mode = SPI_MODE_0; | |
| 659 | + spi_device->bits_per_word = 8; | |
| 660 | + spi_device->irq = -1; | |
| 661 | + spi_device->controller_state = NULL; | |
| 662 | + spi_device->controller_data = NULL; | |
| 663 | + strlcpy(spi_device->modalias, this_driver_name, SPI_NAME_SIZE); | |
| 664 | + | |
| 665 | + status = spi_add_device(spi_device); | |
| 666 | + if (status < 0) { | |
| 592 | 667 | spi_dev_put(spi_device); |
| 593 | - | |
| 594 | - /* | |
| 595 | - * There is already a device configured for this bus.cs | |
| 596 | - * It is okay if it us, otherwise complain and fail. | |
| 597 | - */ | |
| 598 | - if (pdev->driver && pdev->driver->name && | |
| 599 | - strcmp(this_driver_name, pdev->driver->name)) { | |
| 600 | - printk(KERN_ALERT | |
| 601 | - "Driver [%s] already registered for %s\n", | |
| 602 | - pdev->driver->name, buff); | |
| 603 | - status = -1; | |
| 604 | - } | |
| 605 | - } else { | |
| 606 | - spi_device->max_speed_hz = SPI_BUS_SPEED; | |
| 607 | - spi_device->mode = SPI_MODE_0; | |
| 608 | - spi_device->bits_per_word = 8; | |
| 609 | - spi_device->irq = -1; | |
| 610 | - spi_device->controller_state = NULL; | |
| 611 | - spi_device->controller_data = NULL; | |
| 612 | - strlcpy(spi_device->modalias, this_driver_name, SPI_NAME_SIZE); | |
| 613 | - | |
| 614 | - status = spi_add_device(spi_device); | |
| 615 | - if (status < 0) { | |
| 616 | - spi_dev_put(spi_device); | |
| 617 | - printk(KERN_ALERT "spi_add_device() failed: %d\n", | |
| 618 | - status); | |
| 619 | - } | |
| 668 | + printk(KERN_ALERT "spi_add_device() failed: %d\n", | |
| 669 | + status); | |
| 620 | 670 | } |
| 621 | - | |
| 622 | 671 | put_device(&spi_master->dev); |
| 623 | 672 | |
| 624 | 673 | return status; |
| 625 | 674 | } |
| 626 | 675 | |
| 627 | -static struct spi_driver spike_driver = { | |
| 628 | - .driver = { | |
| 629 | - .name = this_driver_name, | |
| 630 | - .owner = THIS_MODULE, | |
| 631 | - }, | |
| 632 | - .probe = spike_probe, | |
| 633 | - .remove = __devexit_p(spike_remove), | |
| 634 | -}; | |
| 635 | - | |
| 676 | +/* | |
| 677 | + * spike_ctl初期化 | |
| 678 | + */ | |
| 636 | 679 | static int __init spike_init_spi(void) |
| 637 | 680 | { |
| 638 | 681 | int error; |
| 639 | - | |
| 682 | + | |
| 683 | + spike_ctl.busy = 0; | |
| 640 | 684 | spike_ctl.tx_buff = kmalloc(SPI_BUFF_SIZE, GFP_KERNEL | GFP_DMA); |
| 641 | 685 | if (!spike_ctl.tx_buff) { |
| 642 | 686 | error = -ENOMEM; |
| @@ -648,64 +692,41 @@ static int __init spike_init_spi(void) | ||
| 648 | 692 | error = -ENOMEM; |
| 649 | 693 | goto spike_init_error; |
| 650 | 694 | } |
| 651 | - | |
| 695 | +// probe()関数などをspi driverに登録する | |
| 652 | 696 | error = spi_register_driver(&spike_driver); |
| 653 | 697 | if (error < 0) { |
| 654 | 698 | printk(KERN_ALERT "spi_register_driver() failed %d\n", error); |
| 655 | 699 | goto spike_init_error; |
| 656 | 700 | } |
| 657 | - | |
| 701 | + // SPIデバイス設定 | |
| 658 | 702 | error = add_spike_device_to_bus(); |
| 659 | 703 | if (error < 0) { |
| 660 | 704 | printk(KERN_ALERT "add_spike_to_bus() failed\n"); |
| 661 | 705 | spi_unregister_driver(&spike_driver); |
| 662 | 706 | goto spike_init_error; |
| 663 | 707 | } |
| 664 | -// 一貫性のあるDMAマッピング | |
| 665 | -/* | |
| 666 | -spike_dev.spi_device->dev.coherent_dma_mask = 0xFFFFFFFF; | |
| 667 | - | |
| 668 | -spike_ctl.tx_buff = dma_alloc_coherent(&(spike_dev.spi_device->dev), SPI_BUFF_SIZE, &spike_ctl.tx_dma, GFP_ATOMIC); | |
| 669 | - if (!spike_ctl.tx_buff) { | |
| 670 | - error = -ENOMEM; | |
| 671 | - goto spike_init_error; | |
| 672 | - } | |
| 673 | - | |
| 674 | -// spike_ctl.rx_buff = kmalloc(SPI_BUFF_SIZE, GFP_KERNEL | GFP_DMA); | |
| 675 | -spike_ctl.rx_buff = dma_alloc_coherent(&(spike_dev.spi_device->dev), SPI_BUFF_SIZE, &spike_ctl.rx_dma, GFP_ATOMIC); | |
| 676 | - if (!spike_ctl.rx_buff) { | |
| 677 | - error = -ENOMEM; | |
| 678 | - goto spike_init_error; | |
| 679 | - } | |
| 680 | -*/ | |
| 681 | 708 | |
| 682 | 709 | return 0; |
| 683 | 710 | |
| 684 | 711 | spike_init_error: |
| 685 | - | |
| 686 | 712 | if (spike_ctl.tx_buff) { |
| 687 | 713 | kfree(spike_ctl.tx_buff); |
| 688 | 714 | spike_ctl.tx_buff = 0; |
| 689 | -//dma_free_coherent(&(spike_dev.spi_device->dev), SPI_BUFF_SIZE, spike_ctl.tx_buff, spike_ctl.tx_dma); | |
| 690 | -//spike_ctl.tx_dma = 0; | |
| 691 | 715 | } |
| 692 | - | |
| 693 | 716 | if (spike_ctl.rx_buff) { |
| 694 | 717 | kfree(spike_ctl.rx_buff); |
| 695 | 718 | spike_ctl.rx_buff = 0; |
| 696 | -//dma_free_coherent(&(spike_dev.spi_device->dev), SPI_BUFF_SIZE, spike_ctl.rx_buff, spike_ctl.rx_dma); | |
| 697 | -//spike_ctl.rx_dma = 0; | |
| 698 | 719 | } |
| 699 | - | |
| 700 | 720 | return error; |
| 701 | 721 | } |
| 702 | - | |
| 703 | - | |
| 722 | +/* | |
| 723 | + * spike_dev.devt cdev初期化 | |
| 724 | + */ | |
| 704 | 725 | static int __init spike_init_cdev(void) |
| 705 | 726 | { |
| 706 | 727 | int error; |
| 707 | 728 | |
| 708 | - spike_dev.devt = MKDEV(0, 0); | |
| 729 | + spike_dev.devt = MKDEV(0, 0); // デバイス番号自動割り当て | |
| 709 | 730 | |
| 710 | 731 | error = alloc_chrdev_region(&spike_dev.devt, 0, 1, this_driver_name); |
| 711 | 732 | if (error < 0) { |
| @@ -726,7 +747,10 @@ static int __init spike_init_cdev(void) | ||
| 726 | 747 | |
| 727 | 748 | return 0; |
| 728 | 749 | } |
| 729 | - | |
| 750 | +/* | |
| 751 | + * spike_dev.class 初期化 | |
| 752 | + * デバイスファイル/dev/spikeadX作る | |
| 753 | + */ | |
| 730 | 754 | static int __init spike_init_class(void) |
| 731 | 755 | { |
| 732 | 756 | spike_dev.class = class_create(THIS_MODULE, this_driver_name); |
| @@ -746,13 +770,13 @@ static int __init spike_init_class(void) | ||
| 746 | 770 | |
| 747 | 771 | return 0; |
| 748 | 772 | } |
| 749 | -int spike_init_gpio(void) | |
| 773 | +// GPIO関係初期化 | |
| 774 | +static int spike_init_gpio(void) | |
| 750 | 775 | { |
| 751 | 776 | if (gpio_request(GPIO_DRDY_IN, "GPIO_DRDY_IN")) { |
| 752 | 777 | printk(KERN_ALERT "gpio_request(GPIO_DRDY_IN) failed\n"); |
| 753 | 778 | goto init_gpio_fail_1; |
| 754 | 779 | } |
| 755 | - | |
| 756 | 780 | if (gpio_direction_input(GPIO_DRDY_IN)) { |
| 757 | 781 | printk(KERN_ALERT "gpio_direction_input(GPIO_DRDY_IN) failed\n"); |
| 758 | 782 | goto init_gpio_fail_2; |
| @@ -780,7 +804,6 @@ init_gpio_fail_2: | ||
| 780 | 804 | gpio_free(GPIO_DRDY_IN); |
| 781 | 805 | |
| 782 | 806 | init_gpio_fail_1: |
| 783 | - | |
| 784 | 807 | return -1; |
| 785 | 808 | } |
| 786 | 809 | void spike_free_gpio(void) |
| @@ -790,15 +813,17 @@ void spike_free_gpio(void) | ||
| 790 | 813 | gpio_free(GPIO_TOGGLE_OUT); |
| 791 | 814 | #endif |
| 792 | 815 | } |
| 793 | -int spike_init_irq(void) | |
| 816 | +// DRDY割り込み初期化 | |
| 817 | +static int spike_init_irq(void) | |
| 794 | 818 | { |
| 795 | 819 | int result; |
| 796 | 820 | |
| 797 | - spike_ctl.irq = OMAP_GPIO_IRQ(GPIO_DRDY_IN); | |
| 821 | +// spike_ctl.irq = OMAP_GPIO_IRQ(GPIO_DRDY_IN); | |
| 822 | + spike_ctl.irq = gpio_to_irq(GPIO_DRDY_IN); | |
| 798 | 823 | result = request_irq(spike_ctl.irq, |
| 799 | 824 | irq_handler, |
| 800 | 825 | IRQF_TRIGGER_FALLING, |
| 801 | - "spike", | |
| 826 | + MODULE_NAME, | |
| 802 | 827 | &spike_ctl); |
| 803 | 828 | |
| 804 | 829 | if (result < 0) { |
| @@ -808,41 +833,60 @@ int spike_init_irq(void) | ||
| 808 | 833 | |
| 809 | 834 | return 0; |
| 810 | 835 | } |
| 811 | -void spike_free_irq(void) | |
| 836 | +static void spike_free_irq(void) | |
| 812 | 837 | { |
| 813 | 838 | free_irq(spike_ctl.irq, &spike_ctl); |
| 814 | 839 | } |
| 815 | - | |
| 840 | +/* | |
| 841 | + * モジュール全体の初期化 | |
| 842 | + */ | |
| 816 | 843 | static int __init spike_init(void) |
| 817 | 844 | { |
| 845 | +printk(KERN_INFO "%s %s\n", MODULE_NAME, __FUNCTION__); | |
| 818 | 846 | memset(&spike_dev, 0, sizeof(spike_dev)); |
| 819 | 847 | memset(&spike_ctl, 0, sizeof(spike_ctl)); |
| 820 | 848 | |
| 821 | - sema_init(&spike_dev.fop_sem, 1); | |
| 822 | 849 | spin_lock_init(&spike_dev.spi_lock); |
| 823 | - | |
| 824 | - sema_init(&spike_ctl.cmd_sem, 1); | |
| 850 | + sema_init(&spike_dev.fop_sem, 1); // spike_dev排他アクセス用セマフォ初期化 | |
| 851 | + sema_init(&spike_ctl.cmd_sem, 1); // spike_ctl排他アクセス用セマフォ初期化 | |
| 852 | + sema_init(&finfo.finfo_sem, 1); // finfo排他アクセス用セマフォ初期化 | |
| 825 | 853 | |
| 826 | 854 | finfo.f_version = 0; // 未使用マーク |
| 855 | + | |
| 827 | 856 | // リングバッファ初期化 |
| 828 | 857 | ring_init(); |
| 829 | 858 | |
| 830 | - if (spike_init_cdev() < 0) | |
| 859 | + if (spike_init_cdev() < 0) { | |
| 860 | + printk(KERN_ALERT "call spike_init_cdev() FAILED\n"); | |
| 831 | 861 | goto fail_1; |
| 862 | + } | |
| 832 | 863 | |
| 833 | - if (spike_init_class() < 0) | |
| 864 | +//printk("call spike_init_class()\n"); | |
| 865 | + if (spike_init_class() < 0) { | |
| 866 | + printk(KERN_ALERT "call spike_init_class() FAILED\n"); | |
| 834 | 867 | goto fail_2; |
| 835 | - | |
| 836 | - if (spike_init_spi() < 0) | |
| 868 | + } | |
| 869 | + // spike_ctl初期化 | |
| 870 | +//printk("call spike_init_spi()\n"); | |
| 871 | + if (spike_init_spi() < 0) { | |
| 872 | + printk(KERN_ALERT "call spike_init_spi() FAILED\n"); | |
| 837 | 873 | goto fail_3; |
| 874 | + } | |
| 838 | 875 | // DRDY GPIO144 Input config |
| 839 | - if (spike_init_gpio() < 0) | |
| 876 | +//printk("call spike_init_gpio()\n"); | |
| 877 | + if (spike_init_gpio() < 0) { | |
| 878 | + printk(KERN_ALERT "call spike_init_gpio() FAILED\n"); | |
| 840 | 879 | goto fail_4; |
| 841 | -#if 1 | |
| 880 | + } | |
| 842 | 881 | // DRDY GPIO144 Interrupt config |
| 843 | - if (spike_init_irq() < 0) | |
| 882 | +//printk("call spike_init_irq()\n"); | |
| 883 | + if (spike_init_irq() < 0) { | |
| 884 | + printk(KERN_ALERT "call spike_init_irq() FAILED\n"); | |
| 844 | 885 | goto fail_5; |
| 845 | -#endif | |
| 886 | + } | |
| 887 | + // SPI受信タイムアウト用タイマ | |
| 888 | + hrtimer_init(&spike_dev.timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); | |
| 889 | + spike_dev.timer.function = spike_timer_callback; | |
| 846 | 890 | |
| 847 | 891 | printk(KERN_INFO "%s %s initialized\n", MODULE_NAME, VERSION); |
| 848 | 892 | return 0; |
| @@ -868,16 +912,25 @@ fail_1: | ||
| 868 | 912 | return -1; |
| 869 | 913 | } |
| 870 | 914 | module_init(spike_init); |
| 871 | - | |
| 915 | +/* | |
| 916 | + * モジュール全体の終了処理 | |
| 917 | + */ | |
| 872 | 918 | static void __exit spike_exit(void) |
| 873 | 919 | { |
| 874 | - spi_unregister_device(spike_dev.spi_device); | |
| 875 | - spi_unregister_driver(&spike_driver); | |
| 920 | + // DRDY割り込みOFF | |
| 921 | + disable_irq(spike_ctl.irq); | |
| 922 | +printk(KERN_INFO "%s %s()\n", MODULE_NAME, __FUNCTION__); | |
| 876 | 923 | |
| 877 | -#if 1 | |
| 878 | 924 | spike_free_irq(); |
| 879 | -#endif | |
| 880 | 925 | spike_free_gpio(); |
| 926 | + // 割り込みかからないようにしてからタスクレットkill | |
| 927 | + tasklet_kill(&spike_tasklet); // DRDY割り込み用 | |
| 928 | + tasklet_kill(&spike_spi_completion_tasklet); // SPI受信完了用 | |
| 929 | + | |
| 930 | +//printk(KERN_INFO "spi_unregister_device()\n"); | |
| 931 | + spi_unregister_device(spike_dev.spi_device); // spike_remove()呼ばれる | |
| 932 | +//printk(KERN_INFO "spi_unregister_driver()\n"); | |
| 933 | + spi_unregister_driver(&spike_driver); | |
| 881 | 934 | |
| 882 | 935 | device_destroy(spike_dev.class, spike_dev.devt); |
| 883 | 936 | class_destroy(spike_dev.class); |
| @@ -887,11 +940,9 @@ static void __exit spike_exit(void) | ||
| 887 | 940 | |
| 888 | 941 | if (spike_ctl.tx_buff) |
| 889 | 942 | kfree(spike_ctl.tx_buff); |
| 890 | -//dma_free_coherent(&(spike_dev.spi_device->dev), SPI_BUFF_SIZE, spike_ctl.tx_buff, spike_ctl.tx_dma); | |
| 891 | 943 | |
| 892 | 944 | if (spike_ctl.rx_buff) |
| 893 | 945 | kfree(spike_ctl.rx_buff); |
| 894 | -//dma_free_coherent(&(spike_dev.spi_device->dev), SPI_BUFF_SIZE, spike_ctl.rx_buff, spike_ctl.rx_dma); | |
| 895 | 946 | |
| 896 | 947 | if (spike_dev.user_buff) |
| 897 | 948 | kfree(spike_dev.user_buff); |
| @@ -903,5 +954,5 @@ module_exit(spike_exit); | ||
| 903 | 954 | MODULE_AUTHOR("Naoya Takamura"); |
| 904 | 955 | MODULE_DESCRIPTION("sciLog AD SPI driver based on spike"); |
| 905 | 956 | MODULE_LICENSE("GPL"); |
| 906 | -MODULE_VERSION("1.0"); | |
| 957 | +MODULE_VERSION(VERSION); | |
| 907 | 958 |
| @@ -1,31 +0,0 @@ | ||
| 1 | -if [[ -z "${KERNEL_CROSS_BUILD_ENVIRONMENT_SOURCED}" ]]; then | |
| 2 | - | |
| 3 | - MACHINE=overo | |
| 4 | - | |
| 5 | - # normally OETMP will be ${OVEROTOP}/tmp, but really it is whatever TMPDIR | |
| 6 | - # in ${OVEROTOP}/build/conf/site.conf points to. | |
| 7 | - OETMP=${OVEROTOP}/tmp | |
| 8 | - # OETMP=/oe5 | |
| 9 | - | |
| 10 | - SYSROOTSDIR=${OETMP}/sysroots | |
| 11 | - STAGEDIR=${SYSROOTSDIR}/`uname -m`-linux/usr | |
| 12 | - | |
| 13 | - export KERNELDIR=${SYSROOTSDIR}/${MACHINE}-angstrom-linux-gnueabi/kernel | |
| 14 | - | |
| 15 | - PATH=${PATH}:${STAGEDIR}/bin:${STAGEDIR}/armv7a/bin | |
| 16 | - | |
| 17 | - unset CFLAGS CPPFLAGS CXXFLAGS LDFLAGS MACHINE | |
| 18 | - | |
| 19 | - export ARCH="arm" | |
| 20 | - export CROSS_COMPILE="arm-angstrom-linux-gnueabi-" | |
| 21 | - export CC="arm-angstrom-linux-gnueabi-gcc" | |
| 22 | - export LD="arm-angstrom-linux-gnueabi-ld" | |
| 23 | - export STRIP="arm-angstrom-linux-gnueabi-strip" | |
| 24 | - | |
| 25 | - export KERNEL_CROSS_BUILD_ENVIRONMENT_SOURCED="true" | |
| 26 | - | |
| 27 | - echo "Altered environment for cross building a kernel module with OE tools." | |
| 28 | -else | |
| 29 | - echo "Cross build environment already configured." | |
| 30 | -fi | |
| 31 | - |
| @@ -0,0 +1,20 @@ | ||
| 1 | +SUMMARY = "Example of how to build an external Linux kernel module" | |
| 2 | +LICENSE = "GPLv2" | |
| 3 | +LIC_FILES_CHKSUM = "file://COPYING;md5=12f884d2ae1ff87c09e5b7ccc2c4ca7e" | |
| 4 | +#TOOLCHAIN_TARGET_TASK_append = " kernel-devsrc" | |
| 5 | + | |
| 6 | +inherit module | |
| 7 | + | |
| 8 | +PR = "r0" | |
| 9 | +PV = "1.1" | |
| 10 | + | |
| 11 | +SRC_URI = "file://Makefile \ | |
| 12 | + file://spike-ad.c \ | |
| 13 | + file://spike-ad.h \ | |
| 14 | + file://COPYING \ | |
| 15 | + " | |
| 16 | + | |
| 17 | +S = "${WORKDIR}" | |
| 18 | + | |
| 19 | +# The inherit of module.bbclass will automatically name module packages with | |
| 20 | +# "kernel-module-" prefix as required by the oe-core build environment. |