Changeset 14524


Ignore:
Timestamp:
2009-02-15T18:16:49+01:00 (7 years ago)
Author:
mb
Message:

ucmb: Put the lowlevel protocol handling into the kernel.

Location:
trunk/package/ucmb/src
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/package/ucmb/src/ucmb.c

    r14478 r14524  
    1717#include <linux/spi/spi_bitbang.h> 
    1818#include <linux/gfp.h> 
     19#include <linux/delay.h> 
    1920 
    2021 
     
    4041}; 
    4142 
     43struct ucmb_message_hdr { 
     44        __le16 magic;           /* UCMB_MAGIC */ 
     45        __le16 len;             /* Payload length (excluding header) */ 
     46} __attribute__((packed)); 
     47 
     48struct ucmb_status { 
     49        __le16 magic;           /* UCMB_MAGIC */ 
     50        __le16 code;            /* enum ucmb_status_code */ 
     51} __attribute__((packed)); 
     52 
     53#define UCMB_MAGIC              0x1337 
     54#define UCMB_MAX_MSG_LEN        0x200 
     55 
     56enum ucmb_status_code { 
     57        UCMB_STAT_OK = 0, 
     58        UCMB_STAT_EPROTO,       /* Protocol format error */ 
     59        UCMB_STAT_ENOMEM,       /* Out of memory */ 
     60        UCMB_STAT_E2BIG,        /* Message too big */ 
     61}; 
     62 
     63 
    4264static int ucmb_spi_busnum_count = 1337; 
    4365 
     
    4668        { //FIXME don't define it here. 
    4769                .name           = "ucmb", 
     70                .gpio_cs        = 3, 
    4871                .gpio_sck       = 0, 
    4972                .gpio_miso      = 1, 
     
    7396}; 
    7497 
     98static int ucmb_status_code_to_errno(enum ucmb_status_code code) 
     99{ 
     100        switch (code) { 
     101        case UCMB_STAT_OK: 
     102                return 0; 
     103        case UCMB_STAT_EPROTO: 
     104                return -EPROTO; 
     105        case UCMB_STAT_ENOMEM: 
     106                return -ENOMEM; 
     107        case UCMB_STAT_E2BIG: 
     108                return -E2BIG; 
     109        } 
     110        return -EBUSY; 
     111} 
     112 
    75113static inline struct ucmb * filp_to_ucmb(struct file *filp) 
    76114{ 
     
    84122        struct ucmb *ucmb = filp_to_ucmb(filp); 
    85123        u8 *buf; 
    86         int err; 
     124        int res, err; 
     125        struct ucmb_message_hdr hdr; 
     126        struct ucmb_status status = { .magic = cpu_to_le16(UCMB_MAGIC), }; 
    87127 
    88128        err = -E2BIG; 
    89129        if (size > PAGE_SIZE) 
     130                goto out; 
     131        if (size > UCMB_MAX_MSG_LEN) 
    90132                goto out; 
    91133 
     
    95137                goto out; 
    96138 
     139        err = spi_read(ucmb->sdev, (u8 *)&hdr, sizeof(hdr)); 
     140        if (err) 
     141                goto out_free; 
     142        err = -EPROTO; 
     143        if (hdr.magic != cpu_to_le16(UCMB_MAGIC)) 
     144                goto out_free; 
     145        err = -ENOBUFS; 
     146        if (size < le16_to_cpu(hdr.len)) 
     147                goto out_free; 
     148        size = le16_to_cpu(hdr.len); 
    97149        err = spi_read(ucmb->sdev, buf, size); 
    98150        if (err) 
     
    101153        err = -EFAULT; 
    102154        if (copy_to_user(user_buf, buf, size)) 
    103                 goto out_free; 
     155                goto out_send_status; 
    104156 
    105157        err = 0; 
    106158 
     159out_send_status: 
     160        status.code = err ? UCMB_STAT_ENOMEM : UCMB_STAT_OK; 
     161        res = spi_write(ucmb->sdev, (u8 *)&status, sizeof(status)); 
     162        if (res && !err) 
     163                err = res; 
    107164out_free: 
    108         __free_page((unsigned long)buf); 
     165        free_page((unsigned long)buf); 
    109166out: 
    110167        return err ? err : size; 
     
    118175        u8 *buf; 
    119176        int err; 
     177        struct ucmb_message_hdr hdr = { .magic = cpu_to_le16(UCMB_MAGIC), }; 
     178        struct ucmb_status status; 
     179        struct spi_transfer spi_hdr_xfer; 
     180        struct spi_transfer spi_data_xfer; 
     181        struct spi_message spi_msg; 
    120182 
    121183        err = -ENOMEM; 
     
    124186                goto out; 
    125187 
    126         size = min(PAGE_SIZE, size); 
     188        size = min_t(size_t, PAGE_SIZE, size); 
     189        size = min_t(size_t, UCMB_MAX_MSG_LEN, size); 
    127190        err = -EFAULT; 
    128191        if (copy_from_user(buf, user_buf, size)) 
    129192                goto out_free; 
    130  
    131         err = spi_write(ucmb->sdev, buf, size); 
     193        hdr.len = cpu_to_le16(size); 
     194 
     195        spi_message_init(&spi_msg); 
     196 
     197        memset(&spi_hdr_xfer, 0, sizeof(spi_hdr_xfer)); 
     198        spi_hdr_xfer.tx_buf = &hdr; 
     199        spi_hdr_xfer.len = sizeof(hdr); 
     200        spi_message_add_tail(&spi_hdr_xfer, &spi_msg); 
     201 
     202        memset(&spi_data_xfer, 0, sizeof(spi_data_xfer)); 
     203        spi_data_xfer.tx_buf = buf; 
     204        spi_data_xfer.len = size; 
     205        spi_message_add_tail(&spi_data_xfer, &spi_msg); 
     206 
     207        /* Send the message, including header. */ 
     208        err = spi_sync(ucmb->sdev, &spi_msg); 
     209        if (err) 
     210                goto out_free; 
     211 
     212        /* The microcontroller deserves some time to process the message. */ 
     213        msleep(1); 
     214 
     215        /* Get the status code. */ 
     216        err = spi_read(ucmb->sdev, (u8 *)&status, sizeof(status)); 
     217        if (err) 
     218                goto out_free; 
     219        err = -EPROTO; 
     220        if (status.magic != cpu_to_le16(UCMB_MAGIC)) 
     221                goto out_free; 
     222        err = ucmb_status_code_to_errno(le16_to_cpu(status.code)); 
     223        if (err) 
     224                goto out_free; 
    132225 
    133226out_free: 
    134         __free_page((unsigned long)buf); 
     227        free_page((unsigned long)buf); 
    135228out: 
    136229        return err ? err : size; 
     
    188281                goto err_unreg_spi_gpio_pdev; 
    189282        } 
    190         ucmb->sdev->max_speed_hz = 5000000; 
     283        ucmb->sdev->max_speed_hz = 500000; 
    191284        ucmb->sdev->chip_select = 0; 
    192285        ucmb->sdev->mode = SPI_MODE_0; 
    193286        strlcpy(ucmb->sdev->modalias, "ucmb", /* We are the SPI driver. */ 
    194287                sizeof(ucmb->sdev->modalias)); 
    195         ucmb->sdev->controller_data = (void *)SPI_GPIO_NO_CHIPSELECT; 
     288        ucmb->sdev->controller_data = (void *)pdata->gpio_cs; 
    196289        err = spi_add_device(ucmb->sdev); 
    197290        if (err) { 
  • trunk/package/ucmb/src/ucmb.h

    r14478 r14524  
    44struct ucmb_platform_data { 
    55        const char *name; 
     6        unsigned long gpio_cs; 
    67        unsigned int gpio_sck; 
    78        unsigned int gpio_miso; 
Note: See TracChangeset for help on using the changeset viewer.