1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun * parport-to-butterfly adapter
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Copyright (C) 2005 David Brownell
6*4882a593Smuzhiyun */
7*4882a593Smuzhiyun #include <linux/kernel.h>
8*4882a593Smuzhiyun #include <linux/init.h>
9*4882a593Smuzhiyun #include <linux/delay.h>
10*4882a593Smuzhiyun #include <linux/module.h>
11*4882a593Smuzhiyun #include <linux/device.h>
12*4882a593Smuzhiyun #include <linux/parport.h>
13*4882a593Smuzhiyun
14*4882a593Smuzhiyun #include <linux/sched.h>
15*4882a593Smuzhiyun #include <linux/spi/spi.h>
16*4882a593Smuzhiyun #include <linux/spi/spi_bitbang.h>
17*4882a593Smuzhiyun #include <linux/spi/flash.h>
18*4882a593Smuzhiyun
19*4882a593Smuzhiyun #include <linux/mtd/partitions.h>
20*4882a593Smuzhiyun
21*4882a593Smuzhiyun /*
22*4882a593Smuzhiyun * This uses SPI to talk with an "AVR Butterfly", which is a $US20 card
23*4882a593Smuzhiyun * with a battery powered AVR microcontroller and lots of goodies. You
24*4882a593Smuzhiyun * can use GCC to develop firmware for this.
25*4882a593Smuzhiyun *
26*4882a593Smuzhiyun * See Documentation/spi/butterfly.rst for information about how to build
27*4882a593Smuzhiyun * and use this custom parallel port cable.
28*4882a593Smuzhiyun */
29*4882a593Smuzhiyun
30*4882a593Smuzhiyun /* DATA output bits (pins 2..9 == D0..D7) */
31*4882a593Smuzhiyun #define butterfly_nreset (1 << 1) /* pin 3 */
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define spi_sck_bit (1 << 0) /* pin 2 */
34*4882a593Smuzhiyun #define spi_mosi_bit (1 << 7) /* pin 9 */
35*4882a593Smuzhiyun
36*4882a593Smuzhiyun #define vcc_bits ((1 << 6) | (1 << 5)) /* pins 7, 8 */
37*4882a593Smuzhiyun
38*4882a593Smuzhiyun /* STATUS input bits */
39*4882a593Smuzhiyun #define spi_miso_bit PARPORT_STATUS_BUSY /* pin 11 */
40*4882a593Smuzhiyun
41*4882a593Smuzhiyun /* CONTROL output bits */
42*4882a593Smuzhiyun #define spi_cs_bit PARPORT_CONTROL_SELECT /* pin 17 */
43*4882a593Smuzhiyun
spidev_to_pp(struct spi_device * spi)44*4882a593Smuzhiyun static inline struct butterfly *spidev_to_pp(struct spi_device *spi)
45*4882a593Smuzhiyun {
46*4882a593Smuzhiyun return spi->controller_data;
47*4882a593Smuzhiyun }
48*4882a593Smuzhiyun
49*4882a593Smuzhiyun struct butterfly {
50*4882a593Smuzhiyun /* REVISIT ... for now, this must be first */
51*4882a593Smuzhiyun struct spi_bitbang bitbang;
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun struct parport *port;
54*4882a593Smuzhiyun struct pardevice *pd;
55*4882a593Smuzhiyun
56*4882a593Smuzhiyun u8 lastbyte;
57*4882a593Smuzhiyun
58*4882a593Smuzhiyun struct spi_device *dataflash;
59*4882a593Smuzhiyun struct spi_device *butterfly;
60*4882a593Smuzhiyun struct spi_board_info info[2];
61*4882a593Smuzhiyun
62*4882a593Smuzhiyun };
63*4882a593Smuzhiyun
64*4882a593Smuzhiyun /*----------------------------------------------------------------------*/
65*4882a593Smuzhiyun
66*4882a593Smuzhiyun static inline void
setsck(struct spi_device * spi,int is_on)67*4882a593Smuzhiyun setsck(struct spi_device *spi, int is_on)
68*4882a593Smuzhiyun {
69*4882a593Smuzhiyun struct butterfly *pp = spidev_to_pp(spi);
70*4882a593Smuzhiyun u8 bit, byte = pp->lastbyte;
71*4882a593Smuzhiyun
72*4882a593Smuzhiyun bit = spi_sck_bit;
73*4882a593Smuzhiyun
74*4882a593Smuzhiyun if (is_on)
75*4882a593Smuzhiyun byte |= bit;
76*4882a593Smuzhiyun else
77*4882a593Smuzhiyun byte &= ~bit;
78*4882a593Smuzhiyun parport_write_data(pp->port, byte);
79*4882a593Smuzhiyun pp->lastbyte = byte;
80*4882a593Smuzhiyun }
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun static inline void
setmosi(struct spi_device * spi,int is_on)83*4882a593Smuzhiyun setmosi(struct spi_device *spi, int is_on)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun struct butterfly *pp = spidev_to_pp(spi);
86*4882a593Smuzhiyun u8 bit, byte = pp->lastbyte;
87*4882a593Smuzhiyun
88*4882a593Smuzhiyun bit = spi_mosi_bit;
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun if (is_on)
91*4882a593Smuzhiyun byte |= bit;
92*4882a593Smuzhiyun else
93*4882a593Smuzhiyun byte &= ~bit;
94*4882a593Smuzhiyun parport_write_data(pp->port, byte);
95*4882a593Smuzhiyun pp->lastbyte = byte;
96*4882a593Smuzhiyun }
97*4882a593Smuzhiyun
getmiso(struct spi_device * spi)98*4882a593Smuzhiyun static inline int getmiso(struct spi_device *spi)
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun struct butterfly *pp = spidev_to_pp(spi);
101*4882a593Smuzhiyun int value;
102*4882a593Smuzhiyun u8 bit;
103*4882a593Smuzhiyun
104*4882a593Smuzhiyun bit = spi_miso_bit;
105*4882a593Smuzhiyun
106*4882a593Smuzhiyun /* only STATUS_BUSY is NOT negated */
107*4882a593Smuzhiyun value = !(parport_read_status(pp->port) & bit);
108*4882a593Smuzhiyun return (bit == PARPORT_STATUS_BUSY) ? value : !value;
109*4882a593Smuzhiyun }
110*4882a593Smuzhiyun
butterfly_chipselect(struct spi_device * spi,int value)111*4882a593Smuzhiyun static void butterfly_chipselect(struct spi_device *spi, int value)
112*4882a593Smuzhiyun {
113*4882a593Smuzhiyun struct butterfly *pp = spidev_to_pp(spi);
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun /* set default clock polarity */
116*4882a593Smuzhiyun if (value != BITBANG_CS_INACTIVE)
117*4882a593Smuzhiyun setsck(spi, spi->mode & SPI_CPOL);
118*4882a593Smuzhiyun
119*4882a593Smuzhiyun /* here, value == "activate or not";
120*4882a593Smuzhiyun * most PARPORT_CONTROL_* bits are negated, so we must
121*4882a593Smuzhiyun * morph it to value == "bit value to write in control register"
122*4882a593Smuzhiyun */
123*4882a593Smuzhiyun if (spi_cs_bit == PARPORT_CONTROL_INIT)
124*4882a593Smuzhiyun value = !value;
125*4882a593Smuzhiyun
126*4882a593Smuzhiyun parport_frob_control(pp->port, spi_cs_bit, value ? spi_cs_bit : 0);
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun
129*4882a593Smuzhiyun /* we only needed to implement one mode here, and choose SPI_MODE_0 */
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun #define spidelay(X) do { } while (0)
132*4882a593Smuzhiyun /* #define spidelay ndelay */
133*4882a593Smuzhiyun
134*4882a593Smuzhiyun #include "spi-bitbang-txrx.h"
135*4882a593Smuzhiyun
136*4882a593Smuzhiyun static u32
butterfly_txrx_word_mode0(struct spi_device * spi,unsigned nsecs,u32 word,u8 bits,unsigned flags)137*4882a593Smuzhiyun butterfly_txrx_word_mode0(struct spi_device *spi, unsigned nsecs, u32 word,
138*4882a593Smuzhiyun u8 bits, unsigned flags)
139*4882a593Smuzhiyun {
140*4882a593Smuzhiyun return bitbang_txrx_be_cpha0(spi, nsecs, 0, flags, word, bits);
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun
143*4882a593Smuzhiyun /*----------------------------------------------------------------------*/
144*4882a593Smuzhiyun
145*4882a593Smuzhiyun /* override default partitioning with cmdlinepart */
146*4882a593Smuzhiyun static struct mtd_partition partitions[] = { {
147*4882a593Smuzhiyun /* JFFS2 wants partitions of 4*N blocks for this device,
148*4882a593Smuzhiyun * so sectors 0 and 1 can't be partitions by themselves.
149*4882a593Smuzhiyun */
150*4882a593Smuzhiyun
151*4882a593Smuzhiyun /* sector 0 = 8 pages * 264 bytes/page (1 block)
152*4882a593Smuzhiyun * sector 1 = 248 pages * 264 bytes/page
153*4882a593Smuzhiyun */
154*4882a593Smuzhiyun .name = "bookkeeping", /* 66 KB */
155*4882a593Smuzhiyun .offset = 0,
156*4882a593Smuzhiyun .size = (8 + 248) * 264,
157*4882a593Smuzhiyun /* .mask_flags = MTD_WRITEABLE, */
158*4882a593Smuzhiyun }, {
159*4882a593Smuzhiyun /* sector 2 = 256 pages * 264 bytes/page
160*4882a593Smuzhiyun * sectors 3-5 = 512 pages * 264 bytes/page
161*4882a593Smuzhiyun */
162*4882a593Smuzhiyun .name = "filesystem", /* 462 KB */
163*4882a593Smuzhiyun .offset = MTDPART_OFS_APPEND,
164*4882a593Smuzhiyun .size = MTDPART_SIZ_FULL,
165*4882a593Smuzhiyun } };
166*4882a593Smuzhiyun
167*4882a593Smuzhiyun static struct flash_platform_data flash = {
168*4882a593Smuzhiyun .name = "butterflash",
169*4882a593Smuzhiyun .parts = partitions,
170*4882a593Smuzhiyun .nr_parts = ARRAY_SIZE(partitions),
171*4882a593Smuzhiyun };
172*4882a593Smuzhiyun
173*4882a593Smuzhiyun /* REVISIT remove this ugly global and its "only one" limitation */
174*4882a593Smuzhiyun static struct butterfly *butterfly;
175*4882a593Smuzhiyun
butterfly_attach(struct parport * p)176*4882a593Smuzhiyun static void butterfly_attach(struct parport *p)
177*4882a593Smuzhiyun {
178*4882a593Smuzhiyun struct pardevice *pd;
179*4882a593Smuzhiyun int status;
180*4882a593Smuzhiyun struct butterfly *pp;
181*4882a593Smuzhiyun struct spi_master *master;
182*4882a593Smuzhiyun struct device *dev = p->physport->dev;
183*4882a593Smuzhiyun struct pardev_cb butterfly_cb;
184*4882a593Smuzhiyun
185*4882a593Smuzhiyun if (butterfly || !dev)
186*4882a593Smuzhiyun return;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun /* REVISIT: this just _assumes_ a butterfly is there ... no probe,
189*4882a593Smuzhiyun * and no way to be selective about what it binds to.
190*4882a593Smuzhiyun */
191*4882a593Smuzhiyun
192*4882a593Smuzhiyun master = spi_alloc_master(dev, sizeof(*pp));
193*4882a593Smuzhiyun if (!master) {
194*4882a593Smuzhiyun status = -ENOMEM;
195*4882a593Smuzhiyun goto done;
196*4882a593Smuzhiyun }
197*4882a593Smuzhiyun pp = spi_master_get_devdata(master);
198*4882a593Smuzhiyun
199*4882a593Smuzhiyun /*
200*4882a593Smuzhiyun * SPI and bitbang hookup
201*4882a593Smuzhiyun *
202*4882a593Smuzhiyun * use default setup(), cleanup(), and transfer() methods; and
203*4882a593Smuzhiyun * only bother implementing mode 0. Start it later.
204*4882a593Smuzhiyun */
205*4882a593Smuzhiyun master->bus_num = 42;
206*4882a593Smuzhiyun master->num_chipselect = 2;
207*4882a593Smuzhiyun
208*4882a593Smuzhiyun pp->bitbang.master = master;
209*4882a593Smuzhiyun pp->bitbang.chipselect = butterfly_chipselect;
210*4882a593Smuzhiyun pp->bitbang.txrx_word[SPI_MODE_0] = butterfly_txrx_word_mode0;
211*4882a593Smuzhiyun
212*4882a593Smuzhiyun /*
213*4882a593Smuzhiyun * parport hookup
214*4882a593Smuzhiyun */
215*4882a593Smuzhiyun pp->port = p;
216*4882a593Smuzhiyun memset(&butterfly_cb, 0, sizeof(butterfly_cb));
217*4882a593Smuzhiyun butterfly_cb.private = pp;
218*4882a593Smuzhiyun pd = parport_register_dev_model(p, "spi_butterfly", &butterfly_cb, 0);
219*4882a593Smuzhiyun if (!pd) {
220*4882a593Smuzhiyun status = -ENOMEM;
221*4882a593Smuzhiyun goto clean0;
222*4882a593Smuzhiyun }
223*4882a593Smuzhiyun pp->pd = pd;
224*4882a593Smuzhiyun
225*4882a593Smuzhiyun status = parport_claim(pd);
226*4882a593Smuzhiyun if (status < 0)
227*4882a593Smuzhiyun goto clean1;
228*4882a593Smuzhiyun
229*4882a593Smuzhiyun /*
230*4882a593Smuzhiyun * Butterfly reset, powerup, run firmware
231*4882a593Smuzhiyun */
232*4882a593Smuzhiyun pr_debug("%s: powerup/reset Butterfly\n", p->name);
233*4882a593Smuzhiyun
234*4882a593Smuzhiyun /* nCS for dataflash (this bit is inverted on output) */
235*4882a593Smuzhiyun parport_frob_control(pp->port, spi_cs_bit, 0);
236*4882a593Smuzhiyun
237*4882a593Smuzhiyun /* stabilize power with chip in reset (nRESET), and
238*4882a593Smuzhiyun * spi_sck_bit clear (CPOL=0)
239*4882a593Smuzhiyun */
240*4882a593Smuzhiyun pp->lastbyte |= vcc_bits;
241*4882a593Smuzhiyun parport_write_data(pp->port, pp->lastbyte);
242*4882a593Smuzhiyun msleep(5);
243*4882a593Smuzhiyun
244*4882a593Smuzhiyun /* take it out of reset; assume long reset delay */
245*4882a593Smuzhiyun pp->lastbyte |= butterfly_nreset;
246*4882a593Smuzhiyun parport_write_data(pp->port, pp->lastbyte);
247*4882a593Smuzhiyun msleep(100);
248*4882a593Smuzhiyun
249*4882a593Smuzhiyun /*
250*4882a593Smuzhiyun * Start SPI ... for now, hide that we're two physical busses.
251*4882a593Smuzhiyun */
252*4882a593Smuzhiyun status = spi_bitbang_start(&pp->bitbang);
253*4882a593Smuzhiyun if (status < 0)
254*4882a593Smuzhiyun goto clean2;
255*4882a593Smuzhiyun
256*4882a593Smuzhiyun /* Bus 1 lets us talk to at45db041b (firmware disables AVR SPI), AVR
257*4882a593Smuzhiyun * (firmware resets at45, acts as spi slave) or neither (we ignore
258*4882a593Smuzhiyun * both, AVR uses AT45). Here we expect firmware for the first option.
259*4882a593Smuzhiyun */
260*4882a593Smuzhiyun
261*4882a593Smuzhiyun pp->info[0].max_speed_hz = 15 * 1000 * 1000;
262*4882a593Smuzhiyun strcpy(pp->info[0].modalias, "mtd_dataflash");
263*4882a593Smuzhiyun pp->info[0].platform_data = &flash;
264*4882a593Smuzhiyun pp->info[0].chip_select = 1;
265*4882a593Smuzhiyun pp->info[0].controller_data = pp;
266*4882a593Smuzhiyun pp->dataflash = spi_new_device(pp->bitbang.master, &pp->info[0]);
267*4882a593Smuzhiyun if (pp->dataflash)
268*4882a593Smuzhiyun pr_debug("%s: dataflash at %s\n", p->name,
269*4882a593Smuzhiyun dev_name(&pp->dataflash->dev));
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun pr_info("%s: AVR Butterfly\n", p->name);
272*4882a593Smuzhiyun butterfly = pp;
273*4882a593Smuzhiyun return;
274*4882a593Smuzhiyun
275*4882a593Smuzhiyun clean2:
276*4882a593Smuzhiyun /* turn off VCC */
277*4882a593Smuzhiyun parport_write_data(pp->port, 0);
278*4882a593Smuzhiyun
279*4882a593Smuzhiyun parport_release(pp->pd);
280*4882a593Smuzhiyun clean1:
281*4882a593Smuzhiyun parport_unregister_device(pd);
282*4882a593Smuzhiyun clean0:
283*4882a593Smuzhiyun spi_master_put(pp->bitbang.master);
284*4882a593Smuzhiyun done:
285*4882a593Smuzhiyun pr_debug("%s: butterfly probe, fail %d\n", p->name, status);
286*4882a593Smuzhiyun }
287*4882a593Smuzhiyun
butterfly_detach(struct parport * p)288*4882a593Smuzhiyun static void butterfly_detach(struct parport *p)
289*4882a593Smuzhiyun {
290*4882a593Smuzhiyun struct butterfly *pp;
291*4882a593Smuzhiyun
292*4882a593Smuzhiyun /* FIXME this global is ugly ... but, how to quickly get from
293*4882a593Smuzhiyun * the parport to the "struct butterfly" associated with it?
294*4882a593Smuzhiyun * "old school" driver-internal device lists?
295*4882a593Smuzhiyun */
296*4882a593Smuzhiyun if (!butterfly || butterfly->port != p)
297*4882a593Smuzhiyun return;
298*4882a593Smuzhiyun pp = butterfly;
299*4882a593Smuzhiyun butterfly = NULL;
300*4882a593Smuzhiyun
301*4882a593Smuzhiyun /* stop() unregisters child devices too */
302*4882a593Smuzhiyun spi_bitbang_stop(&pp->bitbang);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun /* turn off VCC */
305*4882a593Smuzhiyun parport_write_data(pp->port, 0);
306*4882a593Smuzhiyun msleep(10);
307*4882a593Smuzhiyun
308*4882a593Smuzhiyun parport_release(pp->pd);
309*4882a593Smuzhiyun parport_unregister_device(pp->pd);
310*4882a593Smuzhiyun
311*4882a593Smuzhiyun spi_master_put(pp->bitbang.master);
312*4882a593Smuzhiyun }
313*4882a593Smuzhiyun
314*4882a593Smuzhiyun static struct parport_driver butterfly_driver = {
315*4882a593Smuzhiyun .name = "spi_butterfly",
316*4882a593Smuzhiyun .match_port = butterfly_attach,
317*4882a593Smuzhiyun .detach = butterfly_detach,
318*4882a593Smuzhiyun .devmodel = true,
319*4882a593Smuzhiyun };
320*4882a593Smuzhiyun
butterfly_init(void)321*4882a593Smuzhiyun static int __init butterfly_init(void)
322*4882a593Smuzhiyun {
323*4882a593Smuzhiyun return parport_register_driver(&butterfly_driver);
324*4882a593Smuzhiyun }
325*4882a593Smuzhiyun device_initcall(butterfly_init);
326*4882a593Smuzhiyun
butterfly_exit(void)327*4882a593Smuzhiyun static void __exit butterfly_exit(void)
328*4882a593Smuzhiyun {
329*4882a593Smuzhiyun parport_unregister_driver(&butterfly_driver);
330*4882a593Smuzhiyun }
331*4882a593Smuzhiyun module_exit(butterfly_exit);
332*4882a593Smuzhiyun
333*4882a593Smuzhiyun MODULE_DESCRIPTION("Parport Adapter driver for AVR Butterfly");
334*4882a593Smuzhiyun MODULE_LICENSE("GPL");
335