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

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.18 421 lines 10 kB view raw
1/* 2 * spi_butterfly.c - parport-to-butterfly adapter 3 * 4 * Copyright (C) 2005 David Brownell 5 * 6 * This program is free software; you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation; either version 2 of the License, or 9 * (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19 */ 20#include <linux/kernel.h> 21#include <linux/init.h> 22#include <linux/delay.h> 23#include <linux/platform_device.h> 24#include <linux/parport.h> 25 26#include <linux/spi/spi.h> 27#include <linux/spi/spi_bitbang.h> 28#include <linux/spi/flash.h> 29 30#include <linux/mtd/partitions.h> 31 32 33/* 34 * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card 35 * with a battery powered AVR microcontroller and lots of goodies. You 36 * can use GCC to develop firmware for this. 37 * 38 * See Documentation/spi/butterfly for information about how to build 39 * and use this custom parallel port cable. 40 */ 41 42#undef HAVE_USI /* nyet */ 43 44 45/* DATA output bits (pins 2..9 == D0..D7) */ 46#define butterfly_nreset (1 << 1) /* pin 3 */ 47 48#define spi_sck_bit (1 << 0) /* pin 2 */ 49#define spi_mosi_bit (1 << 7) /* pin 9 */ 50 51#define usi_sck_bit (1 << 3) /* pin 5 */ 52#define usi_mosi_bit (1 << 4) /* pin 6 */ 53 54#define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */ 55 56/* STATUS input bits */ 57#define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */ 58 59#define usi_miso_bit PARPORT_STATUS_PAPEROUT /* pin 12 */ 60 61/* CONTROL output bits */ 62#define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */ 63/* USI uses no chipselect */ 64 65 66 67static inline struct butterfly *spidev_to_pp(struct spi_device *spi) 68{ 69 return spi->controller_data; 70} 71 72static inline int is_usidev(struct spi_device *spi) 73{ 74#ifdef HAVE_USI 75 return spi->chip_select != 1; 76#else 77 return 0; 78#endif 79} 80 81 82struct butterfly { 83 /* REVISIT ... for now, this must be first */ 84 struct spi_bitbang bitbang; 85 86 struct parport *port; 87 struct pardevice *pd; 88 89 u8 lastbyte; 90 91 struct spi_device *dataflash; 92 struct spi_device *butterfly; 93 struct spi_board_info info[2]; 94 95}; 96 97/*----------------------------------------------------------------------*/ 98 99/* 100 * these routines may be slower than necessary because they're hiding 101 * the fact that there are two different SPI busses on this cable: one 102 * to the DataFlash chip (or AVR SPI controller), the other to the 103 * AVR USI controller. 104 */ 105 106static inline void 107setsck(struct spi_device *spi, int is_on) 108{ 109 struct butterfly *pp = spidev_to_pp(spi); 110 u8 bit, byte = pp->lastbyte; 111 112 if (is_usidev(spi)) 113 bit = usi_sck_bit; 114 else 115 bit = spi_sck_bit; 116 117 if (is_on) 118 byte |= bit; 119 else 120 byte &= ~bit; 121 parport_write_data(pp->port, byte); 122 pp->lastbyte = byte; 123} 124 125static inline void 126setmosi(struct spi_device *spi, int is_on) 127{ 128 struct butterfly *pp = spidev_to_pp(spi); 129 u8 bit, byte = pp->lastbyte; 130 131 if (is_usidev(spi)) 132 bit = usi_mosi_bit; 133 else 134 bit = spi_mosi_bit; 135 136 if (is_on) 137 byte |= bit; 138 else 139 byte &= ~bit; 140 parport_write_data(pp->port, byte); 141 pp->lastbyte = byte; 142} 143 144static inline int getmiso(struct spi_device *spi) 145{ 146 struct butterfly *pp = spidev_to_pp(spi); 147 int value; 148 u8 bit; 149 150 if (is_usidev(spi)) 151 bit = usi_miso_bit; 152 else 153 bit = spi_miso_bit; 154 155 /* only STATUS_BUSY is NOT negated */ 156 value = !(parport_read_status(pp->port) & bit); 157 return (bit == PARPORT_STATUS_BUSY) ? value : !value; 158} 159 160static void butterfly_chipselect(struct spi_device *spi, int value) 161{ 162 struct butterfly *pp = spidev_to_pp(spi); 163 164 /* set default clock polarity */ 165 if (value != BITBANG_CS_INACTIVE) 166 setsck(spi, spi->mode & SPI_CPOL); 167 168 /* no chipselect on this USI link config */ 169 if (is_usidev(spi)) 170 return; 171 172 /* here, value == "activate or not"; 173 * most PARPORT_CONTROL_* bits are negated, so we must 174 * morph it to value == "bit value to write in control register" 175 */ 176 if (spi_cs_bit == PARPORT_CONTROL_INIT) 177 value = !value; 178 179 parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0); 180} 181 182 183/* we only needed to implement one mode here, and choose SPI_MODE_0 */ 184 185#define spidelay(X) do{}while(0) 186//#define spidelay ndelay 187 188#define EXPAND_BITBANG_TXRX 189#include <linux/spi/spi_bitbang.h> 190 191static u32 192butterfly_txrx_word_mode0(struct spi_device *spi, 193 unsigned nsecs, 194 u32 word, u8 bits) 195{ 196 return bitbang_txrx_be_cpha0(spi, nsecs, 0, word, bits); 197} 198 199/*----------------------------------------------------------------------*/ 200 201/* override default partitioning with cmdlinepart */ 202static struct mtd_partition partitions[] = { { 203 /* JFFS2 wants partitions of 4*N blocks for this device, 204 * so sectors 0 and 1 can't be partitions by themselves. 205 */ 206 207 /* sector 0 = 8 pages * 264 bytes/page (1 block) 208 * sector 1 = 248 pages * 264 bytes/page 209 */ 210 .name = "bookkeeping", // 66 KB 211 .offset = 0, 212 .size = (8 + 248) * 264, 213// .mask_flags = MTD_WRITEABLE, 214}, { 215 /* sector 2 = 256 pages * 264 bytes/page 216 * sectors 3-5 = 512 pages * 264 bytes/page 217 */ 218 .name = "filesystem", // 462 KB 219 .offset = MTDPART_OFS_APPEND, 220 .size = MTDPART_SIZ_FULL, 221} }; 222 223static struct flash_platform_data flash = { 224 .name = "butterflash", 225 .parts = partitions, 226 .nr_parts = ARRAY_SIZE(partitions), 227}; 228 229 230/* REVISIT remove this ugly global and its "only one" limitation */ 231static struct butterfly *butterfly; 232 233static void butterfly_attach(struct parport *p) 234{ 235 struct pardevice *pd; 236 int status; 237 struct butterfly *pp; 238 struct spi_master *master; 239 struct platform_device *pdev; 240 241 if (butterfly) 242 return; 243 244 /* REVISIT: this just _assumes_ a butterfly is there ... no probe, 245 * and no way to be selective about what it binds to. 246 */ 247 248 /* FIXME where should master->cdev.dev come from? 249 * e.g. /sys/bus/pnp0/00:0b, some PCI thing, etc 250 * setting up a platform device like this is an ugly kluge... 251 */ 252 pdev = platform_device_register_simple("butterfly", -1, NULL, 0); 253 254 master = spi_alloc_master(&pdev->dev, sizeof *pp); 255 if (!master) { 256 status = -ENOMEM; 257 goto done; 258 } 259 pp = spi_master_get_devdata(master); 260 261 /* 262 * SPI and bitbang hookup 263 * 264 * use default setup(), cleanup(), and transfer() methods; and 265 * only bother implementing mode 0. Start it later. 266 */ 267 master->bus_num = 42; 268 master->num_chipselect = 2; 269 270 pp->bitbang.master = spi_master_get(master); 271 pp->bitbang.chipselect = butterfly_chipselect; 272 pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0; 273 274 /* 275 * parport hookup 276 */ 277 pp->port = p; 278 pd = parport_register_device(p, "spi_butterfly", 279 NULL, NULL, NULL, 280 0 /* FLAGS */, pp); 281 if (!pd) { 282 status = -ENOMEM; 283 goto clean0; 284 } 285 pp->pd = pd; 286 287 status = parport_claim(pd); 288 if (status < 0) 289 goto clean1; 290 291 /* 292 * Butterfly reset, powerup, run firmware 293 */ 294 pr_debug("%s: powerup/reset Butterfly\n", p->name); 295 296 /* nCS for dataflash (this bit is inverted on output) */ 297 parport_frob_control(pp->port, spi_cs_bit, 0); 298 299 /* stabilize power with chip in reset (nRESET), and 300 * both spi_sck_bit and usi_sck_bit clear (CPOL=0) 301 */ 302 pp->lastbyte |= vcc_bits; 303 parport_write_data(pp->port, pp->lastbyte); 304 msleep(5); 305 306 /* take it out of reset; assume long reset delay */ 307 pp->lastbyte |= butterfly_nreset; 308 parport_write_data(pp->port, pp->lastbyte); 309 msleep(100); 310 311 312 /* 313 * Start SPI ... for now, hide that we're two physical busses. 314 */ 315 status = spi_bitbang_start(&pp->bitbang); 316 if (status < 0) 317 goto clean2; 318 319 /* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR 320 * (firmware resets at45, acts as spi slave) or neither (we ignore 321 * both, AVR uses AT45). Here we expect firmware for the first option. 322 */ 323 324 pp->info[0].max_speed_hz = 15 * 1000 * 1000; 325 strcpy(pp->info[0].modalias, "mtd_dataflash"); 326 pp->info[0].platform_data = &flash; 327 pp->info[0].chip_select = 1; 328 pp->info[0].controller_data = pp; 329 pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]); 330 if (pp->dataflash) 331 pr_debug("%s: dataflash at %s\n", p->name, 332 pp->dataflash->dev.bus_id); 333 334#ifdef HAVE_USI 335 /* Bus 2 is only for talking to the AVR, and it can work no 336 * matter who masters bus 1; needs appropriate AVR firmware. 337 */ 338 pp->info[1].max_speed_hz = 10 /* ?? */ * 1000 * 1000; 339 strcpy(pp->info[1].modalias, "butterfly"); 340 // pp->info[1].platform_data = ... TBD ... ; 341 pp->info[1].chip_select = 2, 342 pp->info[1].controller_data = pp; 343 pp->butterfly = spi_new_device(pp->bitbang.master, &pp->info[1]); 344 if (pp->butterfly) 345 pr_debug("%s: butterfly at %s\n", p->name, 346 pp->butterfly->dev.bus_id); 347 348 /* FIXME setup ACK for the IRQ line ... */ 349#endif 350 351 // dev_info(_what?_, ...) 352 pr_info("%s: AVR Butterfly\n", p->name); 353 butterfly = pp; 354 return; 355 356clean2: 357 /* turn off VCC */ 358 parport_write_data(pp->port, 0); 359 360 parport_release(pp->pd); 361clean1: 362 parport_unregister_device(pd); 363clean0: 364 (void) spi_master_put(pp->bitbang.master); 365done: 366 platform_device_unregister(pdev); 367 pr_debug("%s: butterfly probe, fail %d\n", p->name, status); 368} 369 370static void butterfly_detach(struct parport *p) 371{ 372 struct butterfly *pp; 373 struct platform_device *pdev; 374 int status; 375 376 /* FIXME this global is ugly ... but, how to quickly get from 377 * the parport to the "struct butterfly" associated with it? 378 * "old school" driver-internal device lists? 379 */ 380 if (!butterfly || butterfly->port != p) 381 return; 382 pp = butterfly; 383 butterfly = NULL; 384 385 /* stop() unregisters child devices too */ 386 pdev = to_platform_device(pp->bitbang.master->cdev.dev); 387 status = spi_bitbang_stop(&pp->bitbang); 388 389 /* turn off VCC */ 390 parport_write_data(pp->port, 0); 391 msleep(10); 392 393 parport_release(pp->pd); 394 parport_unregister_device(pp->pd); 395 396 (void) spi_master_put(pp->bitbang.master); 397 398 platform_device_unregister(pdev); 399} 400 401static struct parport_driver butterfly_driver = { 402 .name = "spi_butterfly", 403 .attach = butterfly_attach, 404 .detach = butterfly_detach, 405}; 406 407 408static int __init butterfly_init(void) 409{ 410 return parport_register_driver(&butterfly_driver); 411} 412device_initcall(butterfly_init); 413 414static void __exit butterfly_exit(void) 415{ 416 parport_unregister_driver(&butterfly_driver); 417} 418module_exit(butterfly_exit); 419 420MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly"); 421MODULE_LICENSE("GPL");