Date:2011-07-08 05:32:25 (12 years 8 months ago)
Author:Werner Almesberger
Commit:6c17a31f1fc515425221067cb3ece599c09dbc5d
Message:atusb, atben: moved from spi/ to ieee802154/; renamed atusb to spi_atusb

Also made both drivers depend on CONFIG_IEEE802154_AT86RF230
Files: drivers/ieee802154/Kconfig (1 diff)
drivers/ieee802154/Makefile (1 diff)
drivers/ieee802154/spi_atben.c (1 diff)
drivers/ieee802154/spi_atusb.c (1 diff)
drivers/spi/Kconfig (1 diff)
drivers/spi/Makefile (1 diff)
drivers/spi/atusb.c (1 diff)
drivers/spi/spi_atben.c (1 diff)

Change Details

drivers/ieee802154/Kconfig
4848    tristate "AT86RF230 transceiver driver"
4949    depends on SPI
5050
51config SPI_ATBEN
52        tristate "ATBEN 8:10 SPI interface"
53        depends on JZ4740_QI_LB60 && IEEE802154_AT86RF230
54        help
55          Bit-banging SPI driver for the 8:10 interface of the Ben NanoNote
56          when equipped with an ATBEN board.
57
58config SPI_ATUSB
59       tristate "ATUSB SPI interface"
60       depends on USB && SPI && IEEE802154_AT86RF230
61        help
62          SPI-over-USB driver for the ATUSB IEEE 802.15.4 board.
63
5164config IEEE802154_CC2420
5265       tristate "CC2420 driver"
5366       depends on SPI
drivers/ieee802154/Makefile
44obj-$(CONFIG_IEEE802154_AT86RF230) += at86rf230.o
55obj-$(CONFIG_IEEE802154_CC2420) += cc2420.o
66obj-$(CONFIG_IEEE802154_ADF7242) += adf7242.o
7obj-$(CONFIG_SPI_ATUSB) += spi_atusb.o
8obj-$(CONFIG_SPI_ATBEN) += spi_atben.o
79
810ccflags-$(CONFIG_IEEE802154_DRIVER_DEBUG) += -DDEBUG
911ccflags-y += -DCONFIG_FFD
drivers/ieee802154/spi_atben.c
1/*
2 * spi_atben.c - SPI host look-alike for ATBEN
3 *
4 * Written 2011 by Werner Almesberger
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 version 2
8 * as published by the Free Software Foundation.
9 */
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/gpio.h>
15#include <linux/delay.h>
16#include <linux/spi/spi.h>
17#include <linux/spi/at86rf230.h>
18#include <asm/mach-jz4740/base.h>
19
20#include "../ieee802154/at86rf230.h" /* dirty */
21
22
23enum {
24    VDD_OFF = 1 << 2, /* VDD disable, PD02 */
25    MOSI = 1 << 8, /* CMD, PD08 */
26    SLP_TR = 1 << 9, /* CLK, PD09 */
27    MISO = 1 << 10, /* DAT0, PD10 */
28    SCLK = 1 << 11, /* DAT1, PD11 */
29    IRQ = 1 << 12, /* DAT2, PD12 */
30    nSEL = 1 << 13, /* DAT3/CD, PD13 */
31};
32
33#define PDPIN (prv->regs)
34#define PDDATS (prv->regs+0x14)
35#define PDDATC (prv->regs+0x18)
36
37
38struct atben_prv {
39    struct device *dev;
40    void __iomem *regs;
41    struct resource *ioarea;
42    struct at86rf230_platform_data
43                platform_data;
44    /* copy platform_data so that we can adapt .reset_data */
45};
46
47
48/* ----- ATBEN reset ------------------------------------------------------- */
49
50
51static void atben_reset(void *reset_data)
52{
53    struct atben_prv *prv = reset_data;
54    const int charge = nSEL | MOSI | SLP_TR | SCLK;
55    const int discharge = charge | IRQ | MISO;
56
57    dev_info(prv->dev, "atben_reset\n");
58    jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 1 << 2, 1 << 2);
59    jz_gpio_port_direction_output(JZ_GPIO_PORTD(0), discharge);
60    jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 0, discharge);
61    msleep(100); /* let power drop */
62
63    /*
64     * Hack: PD12/DAT2/IRQ is an active-high interrupt input, which is
65     * indicated by setting its direction bit to 1. We thus must not
66     * configure it as an "input".
67     */
68    jz_gpio_port_direction_input(JZ_GPIO_PORTD(0), MISO);
69    jz_gpio_port_set_value(JZ_GPIO_PORTD(0), charge, charge);
70    msleep(10); /* precharge caps */
71
72    jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 0, VDD_OFF | SLP_TR | SCLK);
73    msleep(10);
74}
75
76
77/* ----- SPI transfers ----------------------------------------------------- */
78
79
80static void rx_only(const struct atben_prv *prv, uint8_t *buf, int len)
81{
82    uint8_t v;
83
84    while (len--) {
85        writel(SCLK, PDDATS);
86        v = readl(PDPIN) & MISO ? 0x80 : 0;
87        writel(SCLK, PDDATC);
88
89        #define DO_BIT(m) \
90            writel(SCLK, PDDATS); \
91            if (readl(PDPIN) & MISO) \
92                v |= (m); \
93            writel(SCLK, PDDATC)
94
95        DO_BIT(0x40);
96        DO_BIT(0x20);
97        DO_BIT(0x10);
98        DO_BIT(0x08);
99        DO_BIT(0x04);
100        DO_BIT(0x02);
101        DO_BIT(0x01);
102
103        #undef DO_BIT
104
105        *buf++ = v;
106    }
107}
108
109
110static void tx_only(const struct atben_prv *prv, const uint8_t *buf, int len)
111{
112    uint8_t tv;
113
114    while (len--) {
115        tv = *buf++;
116
117        if (tv & 0x80) {
118            writel(MOSI, PDDATS);
119            goto b6_1;
120        } else {
121            writel(MOSI, PDDATC);
122            goto b6_0;
123        }
124
125        #define DO_BIT(m, this, next) \
126            this##_1: \
127                writel(SCLK, PDDATS); \
128                if (tv & (m)) { \
129                    writel(SCLK, PDDATC); \
130                    goto next##_1; \
131                } else { \
132                    writel(MOSI | SCLK, PDDATC); \
133                    goto next##_0; \
134                } \
135            this##_0: \
136                writel(SCLK, PDDATS); \
137                writel(SCLK, PDDATC); \
138                if (tv & (m)) { \
139                    writel(MOSI, PDDATS); \
140                    goto next##_1; \
141                } else { \
142                    goto next##_0; \
143                }
144
145        DO_BIT(0x40, b6, b5);
146        DO_BIT(0x20, b5, b4);
147        DO_BIT(0x10, b4, b3);
148        DO_BIT(0x08, b3, b2);
149        DO_BIT(0x04, b2, b1);
150        DO_BIT(0x02, b1, b0);
151        DO_BIT(0x01, b0, done);
152
153        #undef DO_BIT
154
155done_1:
156done_0:
157        writel(SCLK, PDDATS);
158        writel(SCLK, PDDATC);
159        writel(SCLK, PDDATC); /* delay to meet t5 timing */
160    }
161}
162
163
164static void bidir(const struct atben_prv *prv, const uint8_t *tx, uint8_t *rx,
165    int len)
166{
167    uint8_t mask, tv, rv;
168
169    while (len--) {
170        tv = *tx++;
171        for (mask = 0x80; mask; mask >>= 1) {
172            if (tv & mask)
173                writel(MOSI, PDDATS);
174            else
175                writel(MOSI, PDDATC);
176            writel(SCLK, PDDATS);
177            if (readl(PDPIN) & MISO)
178                rv |= mask;
179            writel(SCLK, PDDATC);
180        }
181        *rx++ = rv;
182    }
183}
184
185
186static int atben_transfer(struct spi_device *spi, struct spi_message *msg)
187{
188    struct atben_prv *prv = spi_master_get_devdata(spi->master);
189    struct spi_transfer *xfer;
190    const uint8_t *tx;
191    uint8_t *rx;
192
193    if (unlikely(list_empty(&msg->transfers))) {
194        dev_err(prv->dev, "transfer is empty\n");
195        return -EINVAL;
196    }
197
198    msg->actual_length = 0;
199
200    writel(nSEL, PDDATC);
201    list_for_each_entry(xfer, &msg->transfers, transfer_list) {
202        tx = xfer->tx_buf;
203        rx = xfer->rx_buf;
204        msg->actual_length += xfer->len;
205
206        if (!tx)
207            rx_only(prv, rx, xfer->len);
208        else if (!rx)
209            tx_only(prv, tx, xfer->len);
210        else
211            bidir(prv, tx, rx, xfer->len);
212    }
213    writel(nSEL, PDDATS);
214
215    msg->status = 0;
216    msg->complete(msg->context);
217
218    return 0;
219}
220
221static int atben_setup(struct spi_device *spi)
222{
223    return 0;
224}
225
226
227/* ----- SPI master creation/removal --------------------------------------- */
228
229
230const static struct at86rf230_platform_data at86rf230_platform_data = {
231    .rstn = -1,
232    .slp_tr = JZ_GPIO_PORTD(9),
233    .dig2 = -1,
234    .reset = atben_reset,
235    /* set .reset_data later */
236};
237
238static int __devinit atben_probe(struct platform_device *pdev)
239{
240    struct spi_board_info board_info = {
241        .modalias = "at86rf230",
242        /* set .irq later */
243        .chip_select = 0,
244        .bus_num = -1,
245        .max_speed_hz = 8 * 1000 * 1000,
246    };
247
248    struct spi_master *master;
249    struct atben_prv *prv;
250    struct resource *regs;
251    struct spi_device *spi;
252    int err = -ENXIO;
253
254    master = spi_alloc_master(&pdev->dev, sizeof(*prv));
255    if (!master)
256        return -ENOMEM;
257
258    prv = spi_master_get_devdata(master);
259    prv->dev = &pdev->dev;
260    platform_set_drvdata(pdev, spi_master_get(master));
261
262    master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
263    master->bus_num = pdev->id;
264    master->num_chipselect = 1;
265    master->setup = atben_setup;
266    master->transfer = atben_transfer;
267
268    dev_dbg(prv->dev, "Setting up ATBEN SPI\n");
269
270    regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
271    if (!regs) {
272        dev_err(prv->dev, "no IORESOURCE_MEM\n");
273        err = -ENOENT;
274        goto out_master;
275    }
276    prv->ioarea = request_mem_region(regs->start, resource_size(regs),
277                                        pdev->name);
278    if (!prv->ioarea) {
279        dev_err(prv->dev, "can't request ioarea\n");
280        goto out_master;
281    }
282
283    prv->regs = ioremap(regs->start, resource_size(regs));
284    if (!prv->regs) {
285        dev_err(prv->dev, "can't ioremap\n");
286        goto out_ioarea;
287    }
288
289    board_info.irq = platform_get_irq(pdev, 0);
290    if (board_info.irq < 0) {
291        dev_err(prv->dev, "can't get GPIO irq\n");
292        err = -ENOENT;
293        goto out_regs;
294    }
295
296    err = spi_register_master(master);
297    if (err) {
298        dev_err(prv->dev, "can't register master\n");
299        goto out_regs;
300    }
301
302    prv->platform_data = at86rf230_platform_data;
303    prv->platform_data.reset_data = prv;
304    board_info.platform_data = &prv->platform_data;
305
306    spi = spi_new_device(master, &board_info);
307    if (!spi) {
308        dev_err(&pdev->dev, "can't create new device for %s\n",
309            board_info.modalias);
310        err = -ENXIO;
311        goto out_registered;
312    }
313
314    dev_info(&spi->dev, "ATBEN ready for mischief (IRQ %d)\n",
315        board_info.irq);
316
317    return 0;
318
319out_registered:
320    spi_unregister_master(master);
321
322out_regs:
323    iounmap(prv->regs);
324
325out_ioarea:
326    release_resource(prv->ioarea);
327    kfree(prv->ioarea);
328
329out_master:
330    platform_set_drvdata(pdev, NULL);
331    spi_master_put(master);
332
333    return err;
334}
335
336static int __devexit atben_remove(struct platform_device *pdev)
337{
338    struct spi_master *master = platform_get_drvdata(pdev);
339    struct atben_prv *prv = spi_master_get_devdata(master);
340
341// restore GPIOs
342
343    spi_unregister_master(master);
344
345    iounmap(prv->regs);
346
347    release_resource(prv->ioarea);
348    kfree(prv->ioarea);
349
350    platform_set_drvdata(pdev, NULL);
351    spi_master_put(master);
352
353    return 0;
354}
355
356static struct platform_driver atben_driver = {
357    .driver = {
358        .name = "spi_atben",
359        .owner = THIS_MODULE,
360    },
361    .remove = __devexit_p(atben_remove),
362};
363
364static struct resource atben_resources[] = {
365    {
366        .start = JZ4740_GPIO_BASE_ADDR+0x300,
367        .end = JZ4740_GPIO_BASE_ADDR+0x3ff,
368        .flags = IORESOURCE_MEM,
369    },
370    {
371        /* set start and end later */
372        .flags = IORESOURCE_IRQ,
373    },
374};
375
376static struct platform_device atben_device = {
377    .name = "spi_atben",
378    .id = -1,
379    .num_resources = ARRAY_SIZE(atben_resources),
380    .resource = atben_resources,
381};
382
383/*
384 * Registering the platform device just to probe it immediately afterwards
385 * seems a little circuitous. Need to see if there's a better way.
386 *
387 * What we actually should do is this:
388 * - in module init, register the device
389 * - maybe probe as well, but keep the device also if the probe fails
390 * (due to a conflicting driver already occupying the 8:10 slot)
391 * - have a means for user space to kick off driver probing, e.g., when
392 * anything about the 8:10 slot changes
393 */
394
395static int __init atben_init(void)
396{
397    int err;
398
399    err = platform_device_register(&atben_device);
400    if (err)
401        return err;
402
403    atben_resources[1].start = atben_resources[1].end =
404        gpio_to_irq(JZ_GPIO_PORTD(12));
405
406    return platform_driver_probe(&atben_driver, atben_probe);
407}
408
409static void __exit atben_exit(void)
410{
411    platform_driver_unregister(&atben_driver);
412    platform_device_unregister(&atben_device);
413}
414
415module_init(atben_init);
416module_exit(atben_exit);
417
418
419MODULE_DESCRIPTION("ATBEN SPI Controller Driver");
420MODULE_AUTHOR("Werner Almesberger <werner@almesberger.net>");
421MODULE_LICENSE("GPL");
drivers/ieee802154/spi_atusb.c
1/*
2 * atusb - SPI host look-alike for ATSUB
3 *
4 * Copyright (c) 2011 Richard Sharpe <realrichardsharpe@gmail.com>
5 * Copyright (c) 2011 Stefan Schmidt <stefan@datenfreihafen.org>
6 * Copyright (c) 2011 Werner Almesberger <werner@almesberger.net>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2
11 *
12 */
13
14/*
15 * - implement more robust interrupt synchronization
16 * - check URB killing in atusb_disconnect for races
17 * - switch from bulk to interrupt endpoint
18 * - implement buffer read without extra copy
19 * - harmonize indentation style
20 * - mv atusb.c ../ieee802.15.4/spi_atusb.c, or maybe atrf_atusb.c or such
21 * - check module load/unload
22 * - review dev_* severity levels
23 */
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/platform_device.h>
28#include <linux/jiffies.h>
29#include <linux/timer.h>
30#include <linux/interrupt.h>
31#include <linux/usb.h>
32#include <linux/spi/spi.h>
33#include <linux/spi/at86rf230.h>
34
35#include "../ieee802154/at86rf230.h" /* dirty */
36
37
38#define SYNC_TIMEOUT_MS 50 /* assume interrupt has been synced after
39                   waiting this long */
40
41#define VENDOR_ID 0x20b7
42#define PRODUCT_ID 0x1540
43
44/* The devices we work with */
45static const struct usb_device_id atusb_device_table[] = {
46    { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
47    { },
48};
49MODULE_DEVICE_TABLE(usb, atusb_device_table);
50
51#define ATUSB_BUILD_SIZE 256
52struct atusb_local {
53    struct usb_device * udev;
54    /* The interface to the RF part info, if applicable */
55    uint8_t ep0_atusb_major;
56    uint8_t ep0_atusb_minor;
57    uint8_t atusb_hw_type;
58    struct spi_master *master;
59    int slave_irq;
60    struct urb *irq_urb;
61    uint8_t irq_buf; /* receive irq serial here*/
62    uint8_t irq_seen; /* last irq serial from bulk */
63    uint8_t irq_sync; /* last irq serial from WRITE2_SYNC */
64    struct tasklet_struct task; /* interrupt delivery tasklet */
65    struct timer_list timer; /* delay, for interrupt synch */
66    struct at86rf230_platform_data platform_data;
67    /* copy platform_data so that we can adapt .reset_data */
68    struct spi_device *spi;
69// unsigned char buffer[3];
70    unsigned char buffer[260]; /* XXL, just in case */
71    struct spi_message *msg;
72};
73
74/* Commands to our device. Make sure this is synced with the firmware */
75enum atspi_requests {
76    ATUSB_ID = 0x00, /* system status/control grp */
77    ATUSB_BUILD,
78    ATUSB_RESET,
79    ATUSB_RF_RESET = 0x10, /* debug/test group */
80    ATUSB_POLL_INT,
81    ATUSB_TEST, /* atusb-sil only */
82    ATUSB_TIMER,
83    ATUSB_GPIO,
84    ATUSB_SLP_TR,
85    ATUSB_GPIO_CLEANUP,
86    ATUSB_REG_WRITE = 0x20, /* transceiver group */
87    ATUSB_REG_READ,
88    ATUSB_BUF_WRITE,
89    ATUSB_BUF_READ,
90    ATUSB_SRAM_WRITE,
91    ATUSB_SRAM_READ,
92    ATUSB_SPI_WRITE = 0x30, /* SPI group */
93    ATUSB_SPI_READ1,
94    ATUSB_SPI_READ2,
95    ATUSB_SPI_WRITE2_SYNC,
96};
97
98/*
99 * Direction bRequest wValue wIndex wLength
100 *
101 * ->host ATUSB_ID - - 3
102 * ->host ATUSB_BUILD - - #bytes
103 * host-> ATUSB_RESET - - 0
104 *
105 * host-> ATUSB_RF_RESET - - 0
106 * ->host ATUSB_POLL_INT - - 1
107 * host-> ATUSB_TEST - - 0
108 * ->host ATUSB_TIMER - - #bytes (6)
109 * ->host ATUSB_GPIO dir+data mask+p# 3
110 * host-> ATUSB_SLP_TR - - 0
111 * host-> ATUSB_GPIO_CLEANUP - - 0
112 *
113 * host-> ATUSB_REG_WRITE value addr 0
114 * ->host ATUSB_REG_READ - addr 1
115 * host-> ATUSB_BUF_WRITE - - #bytes
116 * ->host ATUSB_BUF_READ - - #bytes
117 * host-> ATUSB_SRAM_WRITE - addr #bytes
118 * ->host ATUSB_SRAM_READ - addr #bytes
119 *
120 * host-> ATUSB_SPI_WRITE byte0 byte1 #bytes
121 * ->host ATUSB_SPI_READ1 byte0 - #bytes
122 * ->host ATUSB_SPI_READ2 byte0 byte1 #bytes
123 * ->host ATUSB_SPI_WRITE2_SYNC byte0 byte1 0/1
124 */
125
126#define ATUSB_FROM_DEV (USB_TYPE_VENDOR | USB_DIR_IN)
127#define ATUSB_TO_DEV (USB_TYPE_VENDOR | USB_DIR_OUT)
128
129
130/* ----- Control transfers ------------------------------------------------- */
131
132
133static int atusb_async_errchk(struct urb *urb)
134{
135    struct atusb_local *atusb = urb->context;
136    struct spi_message *msg = atusb->msg;
137    struct usb_device *dev = atusb->udev;
138
139    if (!urb->status) {
140        dev_dbg(&dev->dev, "atusb_async_errchk OK len %d\n",
141            urb->actual_length);
142        return 0;
143    }
144
145    if (urb->status != -ENOENT && urb->status != -ECONNRESET &&
146        urb->status != -ESHUTDOWN)
147        dev_info(&dev->dev, "atusb_async_errchk FAIL error %d\n",
148            urb->status);
149
150    msg->actual_length = 0;
151
152    return urb->status;
153}
154
155static void atusb_async_finish(struct urb *urb)
156{
157    struct atusb_local *atusb = urb->context;
158    struct spi_message *msg = atusb->msg;
159
160    msg->status = urb->status;
161    msg->complete(msg->context);
162
163    kfree(urb->setup_packet);
164    usb_free_urb(urb);
165}
166
167static void atusb_ctrl_cb(struct urb *urb)
168{
169    atusb_async_errchk(urb);
170    atusb_async_finish(urb);
171}
172
173static void atusb_timer(unsigned long data)
174{
175    struct urb *urb = (void *) data;
176
177    dev_warn(&urb->dev->dev, "atusb_timer\n");
178    atusb_async_finish(urb);
179}
180
181static void atusb_ctrl_cb_sync(struct urb *urb)
182{
183    struct atusb_local *atusb = urb->context;
184
185    /* @@@ needs locking/atomic */
186    if (atusb_async_errchk(urb) || atusb->irq_sync == atusb->irq_seen) {
187        atusb_async_finish(urb);
188        return;
189    }
190
191    BUG_ON(timer_pending(&atusb->timer));
192    atusb->timer.expires = jiffies+msecs_to_jiffies(SYNC_TIMEOUT_MS);
193    atusb->timer.data = (unsigned long) urb;
194    add_timer(&atusb->timer);
195}
196
197static void atusb_read_fb_cb(struct urb *urb)
198{
199    struct atusb_local *atusb = urb->context;
200    struct spi_message *msg = atusb->msg;
201    const struct spi_transfer *xfer;
202    uint8_t *rx;
203
204    if (!atusb_async_errchk(urb)) {
205        BUG_ON(!urb->actual_length);
206
207        xfer = list_first_entry(&msg->transfers, struct spi_transfer,
208            transfer_list);
209        rx = xfer->rx_buf;
210        rx[1] = atusb->buffer[0];
211
212        xfer = list_entry(xfer->transfer_list.next,
213            struct spi_transfer, transfer_list);
214        memcpy(xfer->rx_buf, atusb->buffer+1, urb->actual_length-1);
215    }
216
217    atusb_async_finish(urb);
218}
219
220static int submit_control_msg(struct atusb_local *atusb,
221    __u8 request, __u8 requesttype, __u16 value, __u16 index,
222    void *data, __u16 size, usb_complete_t complete_fn, void *context)
223{
224    struct usb_device *dev = atusb->udev;
225    struct usb_ctrlrequest *req;
226    struct urb *urb;
227    int retval = -ENOMEM;
228
229    req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
230    if (!req)
231        return -ENOMEM;
232
233    req->bRequest = request;
234    req->bRequestType = requesttype;
235    req->wValue = cpu_to_le16(value);
236    req->wIndex = cpu_to_le16(index);
237    req->wLength = cpu_to_le16(size);
238
239    urb = usb_alloc_urb(0, GFP_KERNEL);
240    if (!urb)
241        goto out_nourb;
242
243    usb_fill_control_urb(urb, dev,
244        requesttype == ATUSB_FROM_DEV ?
245          usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0),
246        (unsigned char *) req, data, size, complete_fn, context);
247
248    retval = usb_submit_urb(urb, GFP_KERNEL);
249    if (!retval)
250        return 0;
251    dev_warn(&dev->dev, "failed submitting read urb, error %d",
252        retval);
253    retval = retval == -ENOMEM ? retval : -EIO;
254
255    usb_free_urb(urb);
256out_nourb:
257    kfree(req);
258
259    return retval;
260}
261
262
263/* ----- SPI transfers ----------------------------------------------------- */
264
265
266static int atusb_read1(struct atusb_local *atusb,
267    uint8_t tx, uint8_t *rx, int len)
268{
269    dev_dbg(&atusb->udev->dev, "atusb_read1: tx = 0x%x\n", tx);
270    return submit_control_msg(atusb,
271        ATUSB_SPI_READ1, ATUSB_FROM_DEV, tx, 0,
272        rx, 1, atusb_ctrl_cb, atusb);
273}
274
275static int atusb_read_fb(struct atusb_local *atusb,
276    uint8_t tx, uint8_t *rx0, uint8_t *rx, int len)
277{
278    dev_dbg(&atusb->udev->dev, "atusb_read_fb: tx = 0x%x\n", tx);
279    return submit_control_msg(atusb,
280        ATUSB_SPI_READ1, ATUSB_FROM_DEV, tx, 0,
281        atusb->buffer, len+1, atusb_read_fb_cb, atusb);
282}
283
284static int atusb_write(struct atusb_local *atusb,
285    uint8_t tx0, uint8_t tx1, const uint8_t *tx, int len)
286{
287    dev_dbg(&atusb->udev->dev,
288        "atusb_write: tx0 = 0x%x tx1 = 0x%x\n", tx0, tx1);
289
290    /*
291     * The AT86RF230 driver sometimes requires a transceiver state
292     * transition to be an interrupt barrier. This is the case after
293     * writing FORCE_TX_ON to the TRX_CMD field in the TRX_STATE register.
294     *
295     * Since there is no other means of notification, we just decode the
296     * transfer and do a bit of pattern matching.
297     */
298    if (tx0 == (CMD_REG | CMD_WRITE | RG_TRX_STATE) &&
299        (tx1 & 0x1f) == STATE_FORCE_TX_ON)
300        return submit_control_msg(atusb,
301            ATUSB_SPI_WRITE2_SYNC, ATUSB_FROM_DEV, tx0, tx1,
302             &atusb->irq_sync, 1, atusb_ctrl_cb_sync, atusb);
303    else
304        return submit_control_msg(atusb,
305            ATUSB_SPI_WRITE, ATUSB_TO_DEV, tx0, tx1,
306            (uint8_t *) tx, len, atusb_ctrl_cb, atusb);
307}
308
309static int atusb_transfer(struct spi_device *spi, struct spi_message *msg)
310{
311    struct atusb_local *atusb = spi_master_get_devdata(spi->master);
312    struct spi_transfer *xfer;
313    struct spi_transfer *x[2];
314    int n;
315    const uint8_t *tx;
316    uint8_t *rx;
317    int len;
318    int retval = 0;
319
320    if (unlikely(list_empty(&msg->transfers))) {
321        dev_err(&atusb->udev->dev, "transfer is empty\n");
322        return -EINVAL;
323    }
324
325    atusb->msg = msg;
326
327    /* Classify the request */
328    n = 0;
329    list_for_each_entry(xfer, &msg->transfers, transfer_list) {
330        if (n == ARRAY_SIZE(x)) {
331            dev_err(&atusb->udev->dev, "too many transfers\n");
332            return -EINVAL;
333        }
334        x[n] = xfer;
335        n++;
336    }
337
338    tx = x[0]->tx_buf;
339    rx = x[0]->rx_buf;
340    len = x[0]->len;
341
342    msg->actual_length = len;
343
344    if (!tx || len != 2)
345        goto bad_req;
346    if (n == 1) {
347        if (rx) {
348            dev_dbg(&atusb->udev->dev, "read 1\n");
349            retval = atusb_read1(atusb, tx[0], rx+1, len-1);
350        } else {
351            dev_dbg(&atusb->udev->dev, "write 2\n");
352            /*
353             * Don't take our clock away !! ;-)
354             */
355            if (tx[0] == (CMD_REG | CMD_WRITE | RG_TRX_CTRL_0)) {
356                msg->status = 0;
357                msg->complete(msg->context);
358            } else {
359                retval = atusb_write(atusb,
360                    tx[0], tx[1], NULL, 0);
361            }
362        }
363    } else {
364        if (x[0]->rx_buf) {
365            if (x[1]->tx_buf || !x[1]->rx_buf)
366                goto bad_req;
367            dev_dbg(&atusb->udev->dev, "read 1+\n");
368            retval = atusb_read_fb(atusb, tx[0], rx+1,
369                x[1]->rx_buf, x[1]->len);
370        } else {
371            if (!x[1]->tx_buf ||x[1]->rx_buf)
372                goto bad_req;
373            dev_dbg(&atusb->udev->dev, "write 2+n\n");
374            retval = atusb_write(atusb, tx[0], tx[1],
375                x[1]->tx_buf, x[1]->len);
376        }
377    }
378    return retval;
379
380bad_req:
381    dev_err(&atusb->udev->dev, "unrecognized request:\n");
382    list_for_each_entry(xfer, &msg->transfers, transfer_list)
383        dev_err(&atusb->udev->dev, "%stx %srx len %u\n",
384            xfer->tx_buf ? "" : "!", xfer->rx_buf ? " " : "!",
385            xfer->len);
386    return -EINVAL;
387}
388
389static int atusb_setup(struct spi_device *spi)
390{
391    return 0;
392}
393
394
395/* ----- Interrupt handling ------------------------------------------------ */
396
397
398static void atusb_tasklet(unsigned long data)
399{
400    struct atusb_local *atusb = (void *) data;
401
402    generic_handle_irq(atusb->slave_irq);
403}
404
405static void atusb_irq(struct urb *urb)
406{
407    struct atusb_local *atusb = urb->context;
408
409    dev_dbg(&urb->dev->dev, "atusb_irq (%d), seen %d sync %d\n",
410        urb->status, atusb->irq_buf, atusb->irq_sync);
411    if (!urb->status) {
412        atusb->irq_seen = atusb->irq_buf;
413        if (atusb->irq_sync == atusb->irq_seen &&
414            try_to_del_timer_sync(&atusb->timer) == 1)
415            atusb_async_finish((struct urb *) atusb->timer.data);
416    }
417    usb_free_urb(urb);
418    atusb->irq_urb = NULL;
419    tasklet_schedule(&atusb->task);
420}
421
422static int atusb_arm_interrupt(struct atusb_local *atusb)
423{
424    struct usb_device *dev = atusb->udev;
425    struct urb *urb;
426    int retval = -ENOMEM;
427
428    BUG_ON(atusb->irq_urb);
429
430    dev_vdbg(&dev->dev, "atusb_arm_interrupt\n");
431    urb = usb_alloc_urb(0, GFP_KERNEL);
432    if (!urb) {
433        dev_err(&dev->dev,
434            "atusb_arm_interrupt: usb_alloc_urb failed\n");
435        return -ENOMEM;
436    }
437
438    usb_fill_bulk_urb(urb, dev, usb_rcvbulkpipe(dev, 1),
439        &atusb->irq_buf, 1, atusb_irq, atusb);
440    atusb->irq_urb = urb;
441    retval = usb_submit_urb(urb, GFP_KERNEL);
442    if (!retval)
443        return 0;
444
445    dev_err(&dev->dev, "failed submitting bulk urb, error %d\n", retval);
446    retval = retval == -ENOMEM ? retval : -EIO;
447
448    usb_free_urb(urb);
449
450    return retval;
451}
452
453static void atusb_irq_mask(struct irq_data *data)
454{
455    struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
456
457    dev_vdbg(&atusb->udev->dev, "atusb_irq_mask\n");
458    tasklet_disable_nosync(&atusb->task);
459}
460
461static void atusb_irq_unmask(struct irq_data *data)
462{
463    struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
464
465    dev_vdbg(&atusb->udev->dev, "atusb_irq_unmask\n");
466    tasklet_enable(&atusb->task);
467}
468
469static void atusb_irq_ack(struct irq_data *data)
470{
471    struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
472
473    dev_vdbg(&atusb->udev->dev, "atusb_irq_ack\n");
474    atusb_arm_interrupt(atusb);
475}
476
477static struct irq_chip atusb_irq_chip = {
478    .name = "atusb-slave",
479    .irq_mask = atusb_irq_mask,
480    .irq_unmask = atusb_irq_unmask,
481    .irq_ack = atusb_irq_ack,
482};
483
484
485/* ----- Transceiver reset ------------------------------------------------- */
486
487
488static void atusb_reset(void *reset_data)
489{
490    int retval;
491    struct atusb_local *atusb = reset_data;
492
493    retval = usb_control_msg(atusb->udev,
494        usb_rcvctrlpipe(atusb->udev, 0),
495        ATUSB_RF_RESET, ATUSB_TO_DEV, 0, 0,
496        NULL, 0, 1000);
497    if (retval < 0) {
498        dev_err(&atusb->udev->dev,
499            "%s: error doing reset retval = %d\n",
500            __func__, retval);
501    }
502}
503
504
505/* ----- Firmware version information -------------------------------------- */
506
507
508static int atusb_get_and_show_revision(struct atusb_local *atusb)
509{
510    struct usb_device *dev = atusb->udev;
511    int retval;
512
513    /* Get a couple of the ATMega Firmware values */
514    retval = usb_control_msg(dev,
515        usb_rcvctrlpipe(dev, 0),
516        ATUSB_ID, ATUSB_FROM_DEV, 0, 0,
517        atusb->buffer, 3, 1000);
518    if (retval < 0) {
519        dev_info(&dev->dev,
520            "failed submitting urb for ATUSB_ID, error %d\n", retval);
521        return retval == -ENOMEM ? retval : -EIO;
522    }
523
524    atusb->ep0_atusb_major = atusb->buffer[0];
525    atusb->ep0_atusb_minor = atusb->buffer[1];
526    atusb->atusb_hw_type = atusb->buffer[2];
527    dev_info(&dev->dev,
528        "Firmware: major: %u, minor: %u, hardware type: %u\n",
529        atusb->ep0_atusb_major, atusb->ep0_atusb_minor,
530        atusb->atusb_hw_type);
531
532    return 0;
533}
534
535static int atusb_get_and_show_build(struct atusb_local *atusb)
536{
537    struct usb_device *dev = atusb->udev;
538    char build[ATUSB_BUILD_SIZE+1];
539    int retval;
540
541    retval = usb_control_msg(dev,
542        usb_rcvctrlpipe(atusb->udev, 0),
543        ATUSB_BUILD, ATUSB_FROM_DEV, 0, 0,
544        build, ATUSB_BUILD_SIZE, 1000);
545    if (retval < 0) {
546        dev_err(&dev->dev,
547            "failed submitting urb for ATUSB_BUILD, error %d\n",
548            retval);
549        return retval == -ENOMEM ? retval : -EIO;
550    }
551
552    build[retval] = 0;
553    dev_info(&dev->dev, "Firmware: build %s\n", build);
554
555    return 0;
556}
557
558
559/* ----- Setup ------------------------------------------------------------- */
560
561
562struct at86rf230_platform_data at86rf230_platform_data = {
563    .rstn = -1,
564    .slp_tr = -1,
565    .dig2 = -1,
566    .reset = atusb_reset,
567    /* set .reset_data later */
568};
569
570static int atusb_probe(struct usb_interface *interface,
571            const struct usb_device_id *id)
572{
573    struct spi_board_info board_info = {
574        .modalias = "at86rf230",
575        /* set .irq later */
576        .chip_select = 0,
577        .bus_num = -1,
578        .max_speed_hz = 8 * 1000 * 1000,
579    };
580
581    struct usb_device *udev = interface_to_usbdev(interface);
582    struct atusb_local *atusb = NULL;
583    struct spi_master *master;
584    int retval;
585
586    /*
587     * Ignore all interfaces used for DFU, i.e., everything while in the
588     * boot loader, and interface #1 when in the application.
589     */
590    if (interface->cur_altsetting->desc.bInterfaceClass !=
591        USB_CLASS_VENDOR_SPEC) {
592        dev_dbg(&udev->dev,
593            "Ignoring interface with class 0x%02x\n",
594            interface->cur_altsetting->desc.bInterfaceClass);
595        return -ENODEV;
596    }
597
598    master = spi_alloc_master(&udev->dev, sizeof(*atusb));
599    if (!master)
600        return -ENOMEM;
601
602    atusb = spi_master_get_devdata(master);
603
604    atusb->udev = usb_get_dev(udev);
605    usb_set_intfdata(interface, atusb);
606
607    atusb->master = spi_master_get(master);
608
609    master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
610    master->bus_num = -1;
611    master->num_chipselect = 1;
612    master->setup = atusb_setup;
613    master->transfer = atusb_transfer;
614
615    atusb->slave_irq = irq_alloc_desc(numa_node_id());
616    if (atusb->slave_irq < 0) {
617        dev_err(&udev->dev, "can't allocate slave irq\n");
618        retval = -ENXIO;
619        goto err_free;
620    }
621
622    set_irq_chip_data(atusb->slave_irq, atusb);
623    set_irq_chip_and_handler(atusb->slave_irq, &atusb_irq_chip,
624        handle_level_irq);
625
626    /* FIXME prepare USB IRQ */
627
628    retval = spi_register_master(master);
629    if (retval < 0) {
630        dev_err(&udev->dev, "can't register spi master\n");
631        goto err_slave_irq;
632    }
633
634    atusb->platform_data = at86rf230_platform_data;
635    atusb->platform_data.reset_data = atusb;
636    board_info.platform_data = &atusb->platform_data;
637    board_info.irq = atusb->slave_irq;
638
639    init_timer(&atusb->timer);
640    atusb->timer.function = atusb_timer;
641
642    tasklet_init(&atusb->task, atusb_tasklet, (unsigned long) atusb);
643    tasklet_disable(&atusb->task);
644    atusb_arm_interrupt(atusb);
645
646    if (atusb_get_and_show_revision(atusb) < 0)
647        goto err_master;
648    if (atusb_get_and_show_build(atusb) < 0)
649        goto err_master;
650
651    atusb->spi = spi_new_device(master, &board_info);
652    if (!atusb->spi) {
653        dev_err(&udev->dev, "can't create new device for %s\n",
654            board_info.modalias);
655        goto err_master;
656    }
657
658    dev_info(&atusb->spi->dev,
659        "ATUSB ready for mischief (IRQ %d)\n", board_info.irq);
660
661    return 0;
662
663err_master:
664    /*
665     * If we come here from a partially successful driver initialization,
666     * we don't really know how much it has done. In particular, it may
667     * have triggered an interrupt and thus removed the interrupt URB and
668     * maybe scheduled the tasklet.
669     */
670    tasklet_disable(&atusb->task);
671    if (atusb->irq_urb)
672        usb_kill_urb(atusb->irq_urb);
673    spi_master_put(atusb->master);
674err_slave_irq:
675    set_irq_chained_handler(atusb->slave_irq, NULL);
676    set_irq_chip_data(atusb->slave_irq, NULL);
677    irq_free_desc(atusb->slave_irq);
678err_free:
679    return retval;
680}
681
682static void atusb_disconnect(struct usb_interface *interface)
683{
684    struct atusb_local *atusb = usb_get_intfdata(interface);
685    struct spi_master *master = atusb->master;
686
687    tasklet_disable(&atusb->task);
688    /* @@@ this needs some extra protecion - wa */
689    if (atusb->irq_urb)
690        usb_kill_urb(atusb->irq_urb);
691
692    BUG_ON(timer_pending(&atusb->timer));
693
694    usb_set_intfdata(interface, NULL);
695    usb_put_dev(atusb->udev);
696
697    spi_dev_put(atusb->spi);
698
699    spi_unregister_master(master);
700
701    set_irq_chained_handler(atusb->slave_irq, NULL);
702    set_irq_chip_data(atusb->slave_irq, NULL);
703    irq_free_desc(atusb->slave_irq);
704
705    spi_master_put(master);
706}
707
708void atusb_release(struct device *dev)
709{
710    return;
711}
712
713static struct usb_driver atusb_driver = {
714    .name = "atusb_ben-wpan",
715    .probe = atusb_probe,
716    .disconnect = atusb_disconnect,
717    .id_table = atusb_device_table,
718};
719
720static struct platform_device atusb_device = {
721    .name = "spi_atusb",
722    .id = -1,
723    .dev.release = atusb_release,
724};
725
726static int __init atusb_init(void)
727{
728    int retval;
729
730    retval = platform_device_register(&atusb_device);
731    if (retval)
732        return retval;
733
734    return usb_register(&atusb_driver);
735}
736
737static void __exit atusb_exit(void)
738{
739    usb_deregister(&atusb_driver);
740    platform_device_unregister(&atusb_device);
741}
742
743module_init (atusb_init);
744module_exit (atusb_exit);
745
746MODULE_AUTHOR("Richard Sharpe <realrichardsharpe@gmail.com>");
747MODULE_AUTHOR("Stefan Schmidt <stefan@datenfreihafen.org>");
748MODULE_AUTHOR("Werner Almesberger <werner@almesberger.net>");
749MODULE_DESCRIPTION("ATUSB ben-wpan Driver");
750MODULE_LICENSE("GPL");
drivers/spi/Kconfig
382382    help
383383      SPI driver for Nuvoton NUC900 series ARM SoCs
384384
385config SPI_ATUSB
386       tristate "ATUSB SPI interface"
387       depends on USB && SPI
388    help
389      SPI-over-USB driver for the ATUSB IEEE 802.15.4 board.
390
391config SPI_ATBEN
392    tristate "ATBEN 8:10 SPI interface"
393    depends on JZ4740_QI_LB60 && EXPERIMENTAL
394    help
395      Bit-banging SPI driver for the 8:10 interface of the Ben NanoNote
396      when equipped with an ATBEN board.
397
398385#
399386# Add new SPI master controllers in alphabetical order above this line
400387#
drivers/spi/Makefile
5050obj-$(CONFIG_SPI_SH_MSIOF) += spi_sh_msiof.o
5151obj-$(CONFIG_SPI_STMP3XXX) += spi_stmp.o
5252obj-$(CONFIG_SPI_NUC900) += spi_nuc900.o
53obj-$(CONFIG_SPI_ATUSB) += atusb.o
54obj-$(CONFIG_SPI_ATBEN) += spi_atben.o
5553
5654# special build for s3c24xx spi driver with fiq support
5755spi_s3c24xx_hw-y := spi_s3c24xx.o
drivers/spi/atusb.c
1/*
2 * atusb - SPI host look-alike for ATSUB
3 *
4 * Copyright (c) 2011 Richard Sharpe <realrichardsharpe@gmail.com>
5 * Copyright (c) 2011 Stefan Schmidt <stefan@datenfreihafen.org>
6 * Copyright (c) 2011 Werner Almesberger <werner@almesberger.net>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License as
10 * published by the Free Software Foundation, version 2
11 *
12 */
13
14/*
15 * - implement more robust interrupt synchronization
16 * - check URB killing in atusb_disconnect for races
17 * - switch from bulk to interrupt endpoint
18 * - implement buffer read without extra copy
19 * - harmonize indentation style
20 * - mv atusb.c ../ieee802.15.4/spi_atusb.c, or maybe atrf_atusb.c or such
21 * - check module load/unload
22 * - review dev_* severity levels
23 */
24
25#include <linux/kernel.h>
26#include <linux/module.h>
27#include <linux/platform_device.h>
28#include <linux/jiffies.h>
29#include <linux/timer.h>
30#include <linux/interrupt.h>
31#include <linux/usb.h>
32#include <linux/spi/spi.h>
33#include <linux/spi/at86rf230.h>
34
35#include "../ieee802154/at86rf230.h" /* dirty */
36
37
38#define SYNC_TIMEOUT_MS 50 /* assume interrupt has been synced after
39                   waiting this long */
40
41#define VENDOR_ID 0x20b7
42#define PRODUCT_ID 0x1540
43
44/* The devices we work with */
45static const struct usb_device_id atusb_device_table[] = {
46    { USB_DEVICE(VENDOR_ID, PRODUCT_ID) },
47    { },
48};
49MODULE_DEVICE_TABLE(usb, atusb_device_table);
50
51#define ATUSB_BUILD_SIZE 256
52struct atusb_local {
53    struct usb_device * udev;
54    /* The interface to the RF part info, if applicable */
55    uint8_t ep0_atusb_major;
56    uint8_t ep0_atusb_minor;
57    uint8_t atusb_hw_type;
58    struct spi_master *master;
59    int slave_irq;
60    struct urb *irq_urb;
61    uint8_t irq_buf; /* receive irq serial here*/
62    uint8_t irq_seen; /* last irq serial from bulk */
63    uint8_t irq_sync; /* last irq serial from WRITE2_SYNC */
64    struct tasklet_struct task; /* interrupt delivery tasklet */
65    struct timer_list timer; /* delay, for interrupt synch */
66    struct at86rf230_platform_data platform_data;
67    /* copy platform_data so that we can adapt .reset_data */
68    struct spi_device *spi;
69// unsigned char buffer[3];
70    unsigned char buffer[260]; /* XXL, just in case */
71    struct spi_message *msg;
72};
73
74/* Commands to our device. Make sure this is synced with the firmware */
75enum atspi_requests {
76    ATUSB_ID = 0x00, /* system status/control grp */
77    ATUSB_BUILD,
78    ATUSB_RESET,
79    ATUSB_RF_RESET = 0x10, /* debug/test group */
80    ATUSB_POLL_INT,
81    ATUSB_TEST, /* atusb-sil only */
82    ATUSB_TIMER,
83    ATUSB_GPIO,
84    ATUSB_SLP_TR,
85    ATUSB_GPIO_CLEANUP,
86    ATUSB_REG_WRITE = 0x20, /* transceiver group */
87    ATUSB_REG_READ,
88    ATUSB_BUF_WRITE,
89    ATUSB_BUF_READ,
90    ATUSB_SRAM_WRITE,
91    ATUSB_SRAM_READ,
92    ATUSB_SPI_WRITE = 0x30, /* SPI group */
93    ATUSB_SPI_READ1,
94    ATUSB_SPI_READ2,
95    ATUSB_SPI_WRITE2_SYNC,
96};
97
98/*
99 * Direction bRequest wValue wIndex wLength
100 *
101 * ->host ATUSB_ID - - 3
102 * ->host ATUSB_BUILD - - #bytes
103 * host-> ATUSB_RESET - - 0
104 *
105 * host-> ATUSB_RF_RESET - - 0
106 * ->host ATUSB_POLL_INT - - 1
107 * host-> ATUSB_TEST - - 0
108 * ->host ATUSB_TIMER - - #bytes (6)
109 * ->host ATUSB_GPIO dir+data mask+p# 3
110 * host-> ATUSB_SLP_TR - - 0
111 * host-> ATUSB_GPIO_CLEANUP - - 0
112 *
113 * host-> ATUSB_REG_WRITE value addr 0
114 * ->host ATUSB_REG_READ - addr 1
115 * host-> ATUSB_BUF_WRITE - - #bytes
116 * ->host ATUSB_BUF_READ - - #bytes
117 * host-> ATUSB_SRAM_WRITE - addr #bytes
118 * ->host ATUSB_SRAM_READ - addr #bytes
119 *
120 * host-> ATUSB_SPI_WRITE byte0 byte1 #bytes
121 * ->host ATUSB_SPI_READ1 byte0 - #bytes
122 * ->host ATUSB_SPI_READ2 byte0 byte1 #bytes
123 * ->host ATUSB_SPI_WRITE2_SYNC byte0 byte1 0/1
124 */
125
126#define ATUSB_FROM_DEV (USB_TYPE_VENDOR | USB_DIR_IN)
127#define ATUSB_TO_DEV (USB_TYPE_VENDOR | USB_DIR_OUT)
128
129
130/* ----- Control transfers ------------------------------------------------- */
131
132
133static int atusb_async_errchk(struct urb *urb)
134{
135    struct atusb_local *atusb = urb->context;
136    struct spi_message *msg = atusb->msg;
137    struct usb_device *dev = atusb->udev;
138
139    if (!urb->status) {
140        dev_dbg(&dev->dev, "atusb_async_errchk OK len %d\n",
141            urb->actual_length);
142        return 0;
143    }
144
145    if (urb->status != -ENOENT && urb->status != -ECONNRESET &&
146        urb->status != -ESHUTDOWN)
147        dev_info(&dev->dev, "atusb_async_errchk FAIL error %d\n",
148            urb->status);
149
150    msg->actual_length = 0;
151
152    return urb->status;
153}
154
155static void atusb_async_finish(struct urb *urb)
156{
157    struct atusb_local *atusb = urb->context;
158    struct spi_message *msg = atusb->msg;
159
160    msg->status = urb->status;
161    msg->complete(msg->context);
162
163    kfree(urb->setup_packet);
164    usb_free_urb(urb);
165}
166
167static void atusb_ctrl_cb(struct urb *urb)
168{
169    atusb_async_errchk(urb);
170    atusb_async_finish(urb);
171}
172
173static void atusb_timer(unsigned long data)
174{
175    struct urb *urb = (void *) data;
176
177    dev_warn(&urb->dev->dev, "atusb_timer\n");
178    atusb_async_finish(urb);
179}
180
181static void atusb_ctrl_cb_sync(struct urb *urb)
182{
183    struct atusb_local *atusb = urb->context;
184
185    /* @@@ needs locking/atomic */
186    if (atusb_async_errchk(urb) || atusb->irq_sync == atusb->irq_seen) {
187        atusb_async_finish(urb);
188        return;
189    }
190
191    BUG_ON(timer_pending(&atusb->timer));
192    atusb->timer.expires = jiffies+msecs_to_jiffies(SYNC_TIMEOUT_MS);
193    atusb->timer.data = (unsigned long) urb;
194    add_timer(&atusb->timer);
195}
196
197static void atusb_read_fb_cb(struct urb *urb)
198{
199    struct atusb_local *atusb = urb->context;
200    struct spi_message *msg = atusb->msg;
201    const struct spi_transfer *xfer;
202    uint8_t *rx;
203
204    if (!atusb_async_errchk(urb)) {
205        BUG_ON(!urb->actual_length);
206
207        xfer = list_first_entry(&msg->transfers, struct spi_transfer,
208            transfer_list);
209        rx = xfer->rx_buf;
210        rx[1] = atusb->buffer[0];
211
212        xfer = list_entry(xfer->transfer_list.next,
213            struct spi_transfer, transfer_list);
214        memcpy(xfer->rx_buf, atusb->buffer+1, urb->actual_length-1);
215    }
216
217    atusb_async_finish(urb);
218}
219
220static int submit_control_msg(struct atusb_local *atusb,
221    __u8 request, __u8 requesttype, __u16 value, __u16 index,
222    void *data, __u16 size, usb_complete_t complete_fn, void *context)
223{
224    struct usb_device *dev = atusb->udev;
225    struct usb_ctrlrequest *req;
226    struct urb *urb;
227    int retval = -ENOMEM;
228
229    req = kmalloc(sizeof(struct usb_ctrlrequest), GFP_KERNEL);
230    if (!req)
231        return -ENOMEM;
232
233    req->bRequest = request;
234    req->bRequestType = requesttype;
235    req->wValue = cpu_to_le16(value);
236    req->wIndex = cpu_to_le16(index);
237    req->wLength = cpu_to_le16(size);
238
239    urb = usb_alloc_urb(0, GFP_KERNEL);
240    if (!urb)
241        goto out_nourb;
242
243    usb_fill_control_urb(urb, dev,
244        requesttype == ATUSB_FROM_DEV ?
245          usb_rcvctrlpipe(dev, 0) : usb_sndctrlpipe(dev, 0),
246        (unsigned char *) req, data, size, complete_fn, context);
247
248    retval = usb_submit_urb(urb, GFP_KERNEL);
249    if (!retval)
250        return 0;
251    dev_warn(&dev->dev, "failed submitting read urb, error %d",
252        retval);
253    retval = retval == -ENOMEM ? retval : -EIO;
254
255    usb_free_urb(urb);
256out_nourb:
257    kfree(req);
258
259    return retval;
260}
261
262
263/* ----- SPI transfers ----------------------------------------------------- */
264
265
266static int atusb_read1(struct atusb_local *atusb,
267    uint8_t tx, uint8_t *rx, int len)
268{
269    dev_dbg(&atusb->udev->dev, "atusb_read1: tx = 0x%x\n", tx);
270    return submit_control_msg(atusb,
271        ATUSB_SPI_READ1, ATUSB_FROM_DEV, tx, 0,
272        rx, 1, atusb_ctrl_cb, atusb);
273}
274
275static int atusb_read_fb(struct atusb_local *atusb,
276    uint8_t tx, uint8_t *rx0, uint8_t *rx, int len)
277{
278    dev_dbg(&atusb->udev->dev, "atusb_read_fb: tx = 0x%x\n", tx);
279    return submit_control_msg(atusb,
280        ATUSB_SPI_READ1, ATUSB_FROM_DEV, tx, 0,
281        atusb->buffer, len+1, atusb_read_fb_cb, atusb);
282}
283
284static int atusb_write(struct atusb_local *atusb,
285    uint8_t tx0, uint8_t tx1, const uint8_t *tx, int len)
286{
287    dev_dbg(&atusb->udev->dev,
288        "atusb_write: tx0 = 0x%x tx1 = 0x%x\n", tx0, tx1);
289
290    /*
291     * The AT86RF230 driver sometimes requires a transceiver state
292     * transition to be an interrupt barrier. This is the case after
293     * writing FORCE_TX_ON to the TRX_CMD field in the TRX_STATE register.
294     *
295     * Since there is no other means of notification, we just decode the
296     * transfer and do a bit of pattern matching.
297     */
298    if (tx0 == (CMD_REG | CMD_WRITE | RG_TRX_STATE) &&
299        (tx1 & 0x1f) == STATE_FORCE_TX_ON)
300        return submit_control_msg(atusb,
301            ATUSB_SPI_WRITE2_SYNC, ATUSB_FROM_DEV, tx0, tx1,
302             &atusb->irq_sync, 1, atusb_ctrl_cb_sync, atusb);
303    else
304        return submit_control_msg(atusb,
305            ATUSB_SPI_WRITE, ATUSB_TO_DEV, tx0, tx1,
306            (uint8_t *) tx, len, atusb_ctrl_cb, atusb);
307}
308
309static int atusb_transfer(struct spi_device *spi, struct spi_message *msg)
310{
311    struct atusb_local *atusb = spi_master_get_devdata(spi->master);
312    struct spi_transfer *xfer;
313    struct spi_transfer *x[2];
314    int n;
315    const uint8_t *tx;
316    uint8_t *rx;
317    int len;
318    int retval = 0;
319
320    if (unlikely(list_empty(&msg->transfers))) {
321        dev_err(&atusb->udev->dev, "transfer is empty\n");
322        return -EINVAL;
323    }
324
325    atusb->msg = msg;
326
327    /* Classify the request */
328    n = 0;
329    list_for_each_entry(xfer, &msg->transfers, transfer_list) {
330        if (n == ARRAY_SIZE(x)) {
331            dev_err(&atusb->udev->dev, "too many transfers\n");
332            return -EINVAL;
333        }
334        x[n] = xfer;
335        n++;
336    }
337
338    tx = x[0]->tx_buf;
339    rx = x[0]->rx_buf;
340    len = x[0]->len;
341
342    msg->actual_length = len;
343
344    if (!tx || len != 2)
345        goto bad_req;
346    if (n == 1) {
347        if (rx) {
348            dev_dbg(&atusb->udev->dev, "read 1\n");
349            retval = atusb_read1(atusb, tx[0], rx+1, len-1);
350        } else {
351            dev_dbg(&atusb->udev->dev, "write 2\n");
352            /*
353             * Don't take our clock away !! ;-)
354             */
355            if (tx[0] == (CMD_REG | CMD_WRITE | RG_TRX_CTRL_0)) {
356                msg->status = 0;
357                msg->complete(msg->context);
358            } else {
359                retval = atusb_write(atusb,
360                    tx[0], tx[1], NULL, 0);
361            }
362        }
363    } else {
364        if (x[0]->rx_buf) {
365            if (x[1]->tx_buf || !x[1]->rx_buf)
366                goto bad_req;
367            dev_dbg(&atusb->udev->dev, "read 1+\n");
368            retval = atusb_read_fb(atusb, tx[0], rx+1,
369                x[1]->rx_buf, x[1]->len);
370        } else {
371            if (!x[1]->tx_buf ||x[1]->rx_buf)
372                goto bad_req;
373            dev_dbg(&atusb->udev->dev, "write 2+n\n");
374            retval = atusb_write(atusb, tx[0], tx[1],
375                x[1]->tx_buf, x[1]->len);
376        }
377    }
378    return retval;
379
380bad_req:
381    dev_err(&atusb->udev->dev, "unrecognized request:\n");
382    list_for_each_entry(xfer, &msg->transfers, transfer_list)
383        dev_err(&atusb->udev->dev, "%stx %srx len %u\n",
384            xfer->tx_buf ? "" : "!", xfer->rx_buf ? " " : "!",
385            xfer->len);
386    return -EINVAL;
387}
388
389static int atusb_setup(struct spi_device *spi)
390{
391    return 0;
392}
393
394
395/* ----- Interrupt handling ------------------------------------------------ */
396
397
398static void atusb_tasklet(unsigned long data)
399{
400    struct atusb_local *atusb = (void *) data;
401
402    generic_handle_irq(atusb->slave_irq);
403}
404
405static void atusb_irq(struct urb *urb)
406{
407    struct atusb_local *atusb = urb->context;
408
409    dev_dbg(&urb->dev->dev, "atusb_irq (%d), seen %d sync %d\n",
410        urb->status, atusb->irq_buf, atusb->irq_sync);
411    if (!urb->status) {
412        atusb->irq_seen = atusb->irq_buf;
413        if (atusb->irq_sync == atusb->irq_seen &&
414            try_to_del_timer_sync(&atusb->timer) == 1)
415            atusb_async_finish((struct urb *) atusb->timer.data);
416    }
417    usb_free_urb(urb);
418    atusb->irq_urb = NULL;
419    tasklet_schedule(&atusb->task);
420}
421
422static int atusb_arm_interrupt(struct atusb_local *atusb)
423{
424    struct usb_device *dev = atusb->udev;
425    struct urb *urb;
426    int retval = -ENOMEM;
427
428    BUG_ON(atusb->irq_urb);
429
430    dev_vdbg(&dev->dev, "atusb_arm_interrupt\n");
431    urb = usb_alloc_urb(0, GFP_KERNEL);
432    if (!urb) {
433        dev_err(&dev->dev,
434            "atusb_arm_interrupt: usb_alloc_urb failed\n");
435        return -ENOMEM;
436    }
437
438    usb_fill_bulk_urb(urb, dev, usb_rcvbulkpipe(dev, 1),
439        &atusb->irq_buf, 1, atusb_irq, atusb);
440    atusb->irq_urb = urb;
441    retval = usb_submit_urb(urb, GFP_KERNEL);
442    if (!retval)
443        return 0;
444
445    dev_err(&dev->dev, "failed submitting bulk urb, error %d\n", retval);
446    retval = retval == -ENOMEM ? retval : -EIO;
447
448    usb_free_urb(urb);
449
450    return retval;
451}
452
453static void atusb_irq_mask(struct irq_data *data)
454{
455    struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
456
457    dev_vdbg(&atusb->udev->dev, "atusb_irq_mask\n");
458    tasklet_disable_nosync(&atusb->task);
459}
460
461static void atusb_irq_unmask(struct irq_data *data)
462{
463    struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
464
465    dev_vdbg(&atusb->udev->dev, "atusb_irq_unmask\n");
466    tasklet_enable(&atusb->task);
467}
468
469static void atusb_irq_ack(struct irq_data *data)
470{
471    struct atusb_local *atusb = irq_data_get_irq_chip_data(data);
472
473    dev_vdbg(&atusb->udev->dev, "atusb_irq_ack\n");
474    atusb_arm_interrupt(atusb);
475}
476
477static struct irq_chip atusb_irq_chip = {
478    .name = "atusb-slave",
479    .irq_mask = atusb_irq_mask,
480    .irq_unmask = atusb_irq_unmask,
481    .irq_ack = atusb_irq_ack,
482};
483
484
485/* ----- Transceiver reset ------------------------------------------------- */
486
487
488static void atusb_reset(void *reset_data)
489{
490    int retval;
491    struct atusb_local *atusb = reset_data;
492
493    retval = usb_control_msg(atusb->udev,
494        usb_rcvctrlpipe(atusb->udev, 0),
495        ATUSB_RF_RESET, ATUSB_TO_DEV, 0, 0,
496        NULL, 0, 1000);
497    if (retval < 0) {
498        dev_err(&atusb->udev->dev,
499            "%s: error doing reset retval = %d\n",
500            __func__, retval);
501    }
502}
503
504
505/* ----- Firmware version information -------------------------------------- */
506
507
508static int atusb_get_and_show_revision(struct atusb_local *atusb)
509{
510    struct usb_device *dev = atusb->udev;
511    int retval;
512
513    /* Get a couple of the ATMega Firmware values */
514    retval = usb_control_msg(dev,
515        usb_rcvctrlpipe(dev, 0),
516        ATUSB_ID, ATUSB_FROM_DEV, 0, 0,
517        atusb->buffer, 3, 1000);
518    if (retval < 0) {
519        dev_info(&dev->dev,
520            "failed submitting urb for ATUSB_ID, error %d\n", retval);
521        return retval == -ENOMEM ? retval : -EIO;
522    }
523
524    atusb->ep0_atusb_major = atusb->buffer[0];
525    atusb->ep0_atusb_minor = atusb->buffer[1];
526    atusb->atusb_hw_type = atusb->buffer[2];
527    dev_info(&dev->dev,
528        "Firmware: major: %u, minor: %u, hardware type: %u\n",
529        atusb->ep0_atusb_major, atusb->ep0_atusb_minor,
530        atusb->atusb_hw_type);
531
532    return 0;
533}
534
535static int atusb_get_and_show_build(struct atusb_local *atusb)
536{
537    struct usb_device *dev = atusb->udev;
538    char build[ATUSB_BUILD_SIZE+1];
539    int retval;
540
541    retval = usb_control_msg(dev,
542        usb_rcvctrlpipe(atusb->udev, 0),
543        ATUSB_BUILD, ATUSB_FROM_DEV, 0, 0,
544        build, ATUSB_BUILD_SIZE, 1000);
545    if (retval < 0) {
546        dev_err(&dev->dev,
547            "failed submitting urb for ATUSB_BUILD, error %d\n",
548            retval);
549        return retval == -ENOMEM ? retval : -EIO;
550    }
551
552    build[retval] = 0;
553    dev_info(&dev->dev, "Firmware: build %s\n", build);
554
555    return 0;
556}
557
558
559/* ----- Setup ------------------------------------------------------------- */
560
561
562struct at86rf230_platform_data at86rf230_platform_data = {
563    .rstn = -1,
564    .slp_tr = -1,
565    .dig2 = -1,
566    .reset = atusb_reset,
567    /* set .reset_data later */
568};
569
570static int atusb_probe(struct usb_interface *interface,
571            const struct usb_device_id *id)
572{
573    struct spi_board_info board_info = {
574        .modalias = "at86rf230",
575        /* set .irq later */
576        .chip_select = 0,
577        .bus_num = -1,
578        .max_speed_hz = 8 * 1000 * 1000,
579    };
580
581    struct usb_device *udev = interface_to_usbdev(interface);
582    struct atusb_local *atusb = NULL;
583    struct spi_master *master;
584    int retval;
585
586    /*
587     * Ignore all interfaces used for DFU, i.e., everything while in the
588     * boot loader, and interface #1 when in the application.
589     */
590    if (interface->cur_altsetting->desc.bInterfaceClass !=
591        USB_CLASS_VENDOR_SPEC) {
592        dev_dbg(&udev->dev,
593            "Ignoring interface with class 0x%02x\n",
594            interface->cur_altsetting->desc.bInterfaceClass);
595        return -ENODEV;
596    }
597
598    master = spi_alloc_master(&udev->dev, sizeof(*atusb));
599    if (!master)
600        return -ENOMEM;
601
602    atusb = spi_master_get_devdata(master);
603
604    atusb->udev = usb_get_dev(udev);
605    usb_set_intfdata(interface, atusb);
606
607    atusb->master = spi_master_get(master);
608
609    master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
610    master->bus_num = -1;
611    master->num_chipselect = 1;
612    master->setup = atusb_setup;
613    master->transfer = atusb_transfer;
614
615    atusb->slave_irq = irq_alloc_desc(numa_node_id());
616    if (atusb->slave_irq < 0) {
617        dev_err(&udev->dev, "can't allocate slave irq\n");
618        retval = -ENXIO;
619        goto err_free;
620    }
621
622    set_irq_chip_data(atusb->slave_irq, atusb);
623    set_irq_chip_and_handler(atusb->slave_irq, &atusb_irq_chip,
624        handle_level_irq);
625
626    /* FIXME prepare USB IRQ */
627
628    retval = spi_register_master(master);
629    if (retval < 0) {
630        dev_err(&udev->dev, "can't register spi master\n");
631        goto err_slave_irq;
632    }
633
634    atusb->platform_data = at86rf230_platform_data;
635    atusb->platform_data.reset_data = atusb;
636    board_info.platform_data = &atusb->platform_data;
637    board_info.irq = atusb->slave_irq;
638
639    init_timer(&atusb->timer);
640    atusb->timer.function = atusb_timer;
641
642    tasklet_init(&atusb->task, atusb_tasklet, (unsigned long) atusb);
643    tasklet_disable(&atusb->task);
644    atusb_arm_interrupt(atusb);
645
646    if (atusb_get_and_show_revision(atusb) < 0)
647        goto err_master;
648    if (atusb_get_and_show_build(atusb) < 0)
649        goto err_master;
650
651    atusb->spi = spi_new_device(master, &board_info);
652    if (!atusb->spi) {
653        dev_err(&udev->dev, "can't create new device for %s\n",
654            board_info.modalias);
655        goto err_master;
656    }
657
658    dev_info(&atusb->spi->dev,
659        "ATUSB ready for mischief (IRQ %d)\n", board_info.irq);
660
661    return 0;
662
663err_master:
664    /*
665     * If we come here from a partially successful driver initialization,
666     * we don't really know how much it has done. In particular, it may
667     * have triggered an interrupt and thus removed the interrupt URB and
668     * maybe scheduled the tasklet.
669     */
670    tasklet_disable(&atusb->task);
671    if (atusb->irq_urb)
672        usb_kill_urb(atusb->irq_urb);
673    spi_master_put(atusb->master);
674err_slave_irq:
675    set_irq_chained_handler(atusb->slave_irq, NULL);
676    set_irq_chip_data(atusb->slave_irq, NULL);
677    irq_free_desc(atusb->slave_irq);
678err_free:
679    return retval;
680}
681
682static void atusb_disconnect(struct usb_interface *interface)
683{
684    struct atusb_local *atusb = usb_get_intfdata(interface);
685    struct spi_master *master = atusb->master;
686
687    tasklet_disable(&atusb->task);
688    /* @@@ this needs some extra protecion - wa */
689    if (atusb->irq_urb)
690        usb_kill_urb(atusb->irq_urb);
691
692    BUG_ON(timer_pending(&atusb->timer));
693
694    usb_set_intfdata(interface, NULL);
695    usb_put_dev(atusb->udev);
696
697    spi_dev_put(atusb->spi);
698
699    spi_unregister_master(master);
700
701    set_irq_chained_handler(atusb->slave_irq, NULL);
702    set_irq_chip_data(atusb->slave_irq, NULL);
703    irq_free_desc(atusb->slave_irq);
704
705    spi_master_put(master);
706}
707
708void atusb_release(struct device *dev)
709{
710    return;
711}
712
713static struct usb_driver atusb_driver = {
714    .name = "atusb_ben-wpan",
715    .probe = atusb_probe,
716    .disconnect = atusb_disconnect,
717    .id_table = atusb_device_table,
718};
719
720static struct platform_device atusb_device = {
721    .name = "spi_atusb",
722    .id = -1,
723    .dev.release = atusb_release,
724};
725
726static int __init atusb_init(void)
727{
728    int retval;
729
730    retval = platform_device_register(&atusb_device);
731    if (retval)
732        return retval;
733
734    return usb_register(&atusb_driver);
735}
736
737static void __exit atusb_exit(void)
738{
739    usb_deregister(&atusb_driver);
740    platform_device_unregister(&atusb_device);
741}
742
743module_init (atusb_init);
744module_exit (atusb_exit);
745
746MODULE_AUTHOR("Richard Sharpe <realrichardsharpe@gmail.com>");
747MODULE_AUTHOR("Stefan Schmidt <stefan@datenfreihafen.org>");
748MODULE_AUTHOR("Werner Almesberger <werner@almesberger.net>");
749MODULE_DESCRIPTION("ATUSB ben-wpan Driver");
750MODULE_LICENSE("GPL");
drivers/spi/spi_atben.c
1/*
2 * spi_atben.c - SPI host look-alike for ATBEN
3 *
4 * Written 2011 by Werner Almesberger
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 version 2
8 * as published by the Free Software Foundation.
9 */
10
11#include <linux/kernel.h>
12#include <linux/module.h>
13#include <linux/platform_device.h>
14#include <linux/gpio.h>
15#include <linux/delay.h>
16#include <linux/spi/spi.h>
17#include <linux/spi/at86rf230.h>
18#include <asm/mach-jz4740/base.h>
19
20#include "../ieee802154/at86rf230.h" /* dirty */
21
22
23enum {
24    VDD_OFF = 1 << 2, /* VDD disable, PD02 */
25    MOSI = 1 << 8, /* CMD, PD08 */
26    SLP_TR = 1 << 9, /* CLK, PD09 */
27    MISO = 1 << 10, /* DAT0, PD10 */
28    SCLK = 1 << 11, /* DAT1, PD11 */
29    IRQ = 1 << 12, /* DAT2, PD12 */
30    nSEL = 1 << 13, /* DAT3/CD, PD13 */
31};
32
33#define PDPIN (prv->regs)
34#define PDDATS (prv->regs+0x14)
35#define PDDATC (prv->regs+0x18)
36
37
38struct atben_prv {
39    struct device *dev;
40    void __iomem *regs;
41    struct resource *ioarea;
42    struct at86rf230_platform_data
43                platform_data;
44    /* copy platform_data so that we can adapt .reset_data */
45};
46
47
48/* ----- ATBEN reset ------------------------------------------------------- */
49
50
51static void atben_reset(void *reset_data)
52{
53    struct atben_prv *prv = reset_data;
54    const int charge = nSEL | MOSI | SLP_TR | SCLK;
55    const int discharge = charge | IRQ | MISO;
56
57    dev_info(prv->dev, "atben_reset\n");
58    jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 1 << 2, 1 << 2);
59    jz_gpio_port_direction_output(JZ_GPIO_PORTD(0), discharge);
60    jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 0, discharge);
61    msleep(100); /* let power drop */
62
63    /*
64     * Hack: PD12/DAT2/IRQ is an active-high interrupt input, which is
65     * indicated by setting its direction bit to 1. We thus must not
66     * configure it as an "input".
67     */
68    jz_gpio_port_direction_input(JZ_GPIO_PORTD(0), MISO);
69    jz_gpio_port_set_value(JZ_GPIO_PORTD(0), charge, charge);
70    msleep(10); /* precharge caps */
71
72    jz_gpio_port_set_value(JZ_GPIO_PORTD(0), 0, VDD_OFF | SLP_TR | SCLK);
73    msleep(10);
74}
75
76
77/* ----- SPI transfers ----------------------------------------------------- */
78
79
80static void rx_only(const struct atben_prv *prv, uint8_t *buf, int len)
81{
82    uint8_t v;
83
84    while (len--) {
85        writel(SCLK, PDDATS);
86        v = readl(PDPIN) & MISO ? 0x80 : 0;
87        writel(SCLK, PDDATC);
88
89        #define DO_BIT(m) \
90            writel(SCLK, PDDATS); \
91            if (readl(PDPIN) & MISO) \
92                v |= (m); \
93            writel(SCLK, PDDATC)
94
95        DO_BIT(0x40);
96        DO_BIT(0x20);
97        DO_BIT(0x10);
98        DO_BIT(0x08);
99        DO_BIT(0x04);
100        DO_BIT(0x02);
101        DO_BIT(0x01);
102
103        #undef DO_BIT
104
105        *buf++ = v;
106    }
107}
108
109
110static void tx_only(const struct atben_prv *prv, const uint8_t *buf, int len)
111{
112    uint8_t tv;
113
114    while (len--) {
115        tv = *buf++;
116
117        if (tv & 0x80) {
118            writel(MOSI, PDDATS);
119            goto b6_1;
120        } else {
121            writel(MOSI, PDDATC);
122            goto b6_0;
123        }
124
125        #define DO_BIT(m, this, next) \
126            this##_1: \
127                writel(SCLK, PDDATS); \
128                if (tv & (m)) { \
129                    writel(SCLK, PDDATC); \
130                    goto next##_1; \
131                } else { \
132                    writel(MOSI | SCLK, PDDATC); \
133                    goto next##_0; \
134                } \
135            this##_0: \
136                writel(SCLK, PDDATS); \
137                writel(SCLK, PDDATC); \
138                if (tv & (m)) { \
139                    writel(MOSI, PDDATS); \
140                    goto next##_1; \
141                } else { \
142                    goto next##_0; \
143                }
144
145        DO_BIT(0x40, b6, b5);
146        DO_BIT(0x20, b5, b4);
147        DO_BIT(0x10, b4, b3);
148        DO_BIT(0x08, b3, b2);
149        DO_BIT(0x04, b2, b1);
150        DO_BIT(0x02, b1, b0);
151        DO_BIT(0x01, b0, done);
152
153        #undef DO_BIT
154
155done_1:
156done_0:
157        writel(SCLK, PDDATS);
158        writel(SCLK, PDDATC);
159        writel(SCLK, PDDATC); /* delay to meet t5 timing */
160    }
161}
162
163
164static void bidir(const struct atben_prv *prv, const uint8_t *tx, uint8_t *rx,
165    int len)
166{
167    uint8_t mask, tv, rv;
168
169    while (len--) {
170        tv = *tx++;
171        for (mask = 0x80; mask; mask >>= 1) {
172            if (tv & mask)
173                writel(MOSI, PDDATS);
174            else
175                writel(MOSI, PDDATC);
176            writel(SCLK, PDDATS);
177            if (readl(PDPIN) & MISO)
178                rv |= mask;
179            writel(SCLK, PDDATC);
180        }
181        *rx++ = rv;
182    }
183}
184
185
186static int atben_transfer(struct spi_device *spi, struct spi_message *msg)
187{
188    struct atben_prv *prv = spi_master_get_devdata(spi->master);
189    struct spi_transfer *xfer;
190    const uint8_t *tx;
191    uint8_t *rx;
192
193    if (unlikely(list_empty(&msg->transfers))) {
194        dev_err(prv->dev, "transfer is empty\n");
195        return -EINVAL;
196    }
197
198    msg->actual_length = 0;
199
200    writel(nSEL, PDDATC);
201    list_for_each_entry(xfer, &msg->transfers, transfer_list) {
202        tx = xfer->tx_buf;
203        rx = xfer->rx_buf;
204        msg->actual_length += xfer->len;
205
206        if (!tx)
207            rx_only(prv, rx, xfer->len);
208        else if (!rx)
209            tx_only(prv, tx, xfer->len);
210        else
211            bidir(prv, tx, rx, xfer->len);
212    }
213    writel(nSEL, PDDATS);
214
215    msg->status = 0;
216    msg->complete(msg->context);
217
218    return 0;
219}
220
221static int atben_setup(struct spi_device *spi)
222{
223    return 0;
224}
225
226
227/* ----- SPI master creation/removal --------------------------------------- */
228
229
230const static struct at86rf230_platform_data at86rf230_platform_data = {
231    .rstn = -1,
232    .slp_tr = JZ_GPIO_PORTD(9),
233    .dig2 = -1,
234    .reset = atben_reset,
235    /* set .reset_data later */
236};
237
238static int __devinit atben_probe(struct platform_device *pdev)
239{
240    struct spi_board_info board_info = {
241        .modalias = "at86rf230",
242        /* set .irq later */
243        .chip_select = 0,
244        .bus_num = -1,
245        .max_speed_hz = 8 * 1000 * 1000,
246    };
247
248    struct spi_master *master;
249    struct atben_prv *prv;
250    struct resource *regs;
251    struct spi_device *spi;
252    int err = -ENXIO;
253
254    master = spi_alloc_master(&pdev->dev, sizeof(*prv));
255    if (!master)
256        return -ENOMEM;
257
258    prv = spi_master_get_devdata(master);
259    prv->dev = &pdev->dev;
260    platform_set_drvdata(pdev, spi_master_get(master));
261
262    master->mode_bits = SPI_CPOL | SPI_CPHA | SPI_CS_HIGH;
263    master->bus_num = pdev->id;
264    master->num_chipselect = 1;
265    master->setup = atben_setup;
266    master->transfer = atben_transfer;
267
268    dev_dbg(prv->dev, "Setting up ATBEN SPI\n");
269
270    regs = platform_get_resource(pdev, IORESOURCE_MEM, 0);
271    if (!regs) {
272        dev_err(prv->dev, "no IORESOURCE_MEM\n");
273        err = -ENOENT;
274        goto out_master;
275    }
276    prv->ioarea = request_mem_region(regs->start, resource_size(regs),
277                                        pdev->name);
278    if (!prv->ioarea) {
279        dev_err(prv->dev, "can't request ioarea\n");
280        goto out_master;
281    }
282
283    prv->regs = ioremap(regs->start, resource_size(regs));
284    if (!prv->regs) {
285        dev_err(prv->dev, "can't ioremap\n");
286        goto out_ioarea;
287    }
288
289    board_info.irq = platform_get_irq(pdev, 0);
290    if (board_info.irq < 0) {
291        dev_err(prv->dev, "can't get GPIO irq\n");
292        err = -ENOENT;
293        goto out_regs;
294    }
295
296    err = spi_register_master(master);
297    if (err) {
298        dev_err(prv->dev, "can't register master\n");
299        goto out_regs;
300    }
301
302    prv->platform_data = at86rf230_platform_data;
303    prv->platform_data.reset_data = prv;
304    board_info.platform_data = &prv->platform_data;
305
306    spi = spi_new_device(master, &board_info);
307    if (!spi) {
308        dev_err(&pdev->dev, "can't create new device for %s\n",
309            board_info.modalias);
310        err = -ENXIO;
311        goto out_registered;
312    }
313
314    dev_info(&spi->dev, "ATBEN ready for mischief (IRQ %d)\n",
315        board_info.irq);
316
317    return 0;
318
319out_registered:
320    spi_unregister_master(master);
321
322out_regs:
323    iounmap(prv->regs);
324
325out_ioarea:
326    release_resource(prv->ioarea);
327    kfree(prv->ioarea);
328
329out_master:
330    platform_set_drvdata(pdev, NULL);
331    spi_master_put(master);
332
333    return err;
334}
335
336static int __devexit atben_remove(struct platform_device *pdev)
337{
338    struct spi_master *master = platform_get_drvdata(pdev);
339    struct atben_prv *prv = spi_master_get_devdata(master);
340
341// restore GPIOs
342
343    spi_unregister_master(master);
344
345    iounmap(prv->regs);
346
347    release_resource(prv->ioarea);
348    kfree(prv->ioarea);
349
350    platform_set_drvdata(pdev, NULL);
351    spi_master_put(master);
352
353    return 0;
354}
355
356static struct platform_driver atben_driver = {
357    .driver = {
358        .name = "spi_atben",
359        .owner = THIS_MODULE,
360    },
361    .remove = __devexit_p(atben_remove),
362};
363
364static struct resource atben_resources[] = {
365    {
366        .start = JZ4740_GPIO_BASE_ADDR+0x300,
367        .end = JZ4740_GPIO_BASE_ADDR+0x3ff,
368        .flags = IORESOURCE_MEM,
369    },
370    {
371        /* set start and end later */
372        .flags = IORESOURCE_IRQ,
373    },
374};
375
376static struct platform_device atben_device = {
377    .name = "spi_atben",
378    .id = -1,
379    .num_resources = ARRAY_SIZE(atben_resources),
380    .resource = atben_resources,
381};
382
383/*
384 * Registering the platform device just to probe it immediately afterwards
385 * seems a little circuitous. Need to see if there's a better way.
386 *
387 * What we actually should do is this:
388 * - in module init, register the device
389 * - maybe probe as well, but keep the device also if the probe fails
390 * (due to a conflicting driver already occupying the 8:10 slot)
391 * - have a means for user space to kick off driver probing, e.g., when
392 * anything about the 8:10 slot changes
393 */
394
395static int __init atben_init(void)
396{
397    int err;
398
399    err = platform_device_register(&atben_device);
400    if (err)
401        return err;
402
403    atben_resources[1].start = atben_resources[1].end =
404        gpio_to_irq(JZ_GPIO_PORTD(12));
405
406    return platform_driver_probe(&atben_driver, atben_probe);
407}
408
409static void __exit atben_exit(void)
410{
411    platform_driver_unregister(&atben_driver);
412    platform_device_unregister(&atben_device);
413}
414
415module_init(atben_init);
416module_exit(atben_exit);
417
418
419MODULE_DESCRIPTION("ATBEN SPI Controller Driver");
420MODULE_AUTHOR("Werner Almesberger <werner@almesberger.net>");
421MODULE_LICENSE("GPL");

Archive Download the corresponding diff file



interactive