Home | History | Annotate | Download | only in stm32_flash
      1 /*
      2  * Copyright (C) 2015 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #include <stdio.h>
     18 #include <stdint.h>
     19 #include <sys/ioctl.h>
     20 #include <linux/spi/spidev.h>
     21 
     22 #include "spi.h"
     23 
     24 uint8_t spi_write_data(handle_t *handle, uint8_t *buffer, int length)
     25 {
     26     spi_handle_t *spi_handle = (spi_handle_t *)handle;
     27     struct spi_ioc_transfer xfer =
     28     {
     29         .len = length + 1,
     30         .tx_buf = (unsigned long)buffer,
     31         .rx_buf = (unsigned long)buffer,
     32         .cs_change = 1,
     33     };
     34 
     35     buffer[length] = checksum(handle, buffer, length);
     36 
     37     if (ioctl(spi_handle->fd, SPI_IOC_MESSAGE(1), &xfer) >= 0)
     38         return buffer[length];
     39     else
     40         return CMD_NACK;
     41 }
     42 
     43 uint8_t spi_write_cmd(handle_t *handle, uint8_t cmd)
     44 {
     45     spi_handle_t *spi_handle = (spi_handle_t *)handle;
     46     uint8_t buffer[] =
     47     {
     48         CMD_SOF,
     49         cmd,
     50         ~cmd
     51     };
     52     struct spi_ioc_transfer xfer =
     53     {
     54         .len = sizeof(buffer),
     55         .tx_buf = (unsigned long)buffer,
     56         .rx_buf = (unsigned long)buffer,
     57         .cs_change = 1,
     58     };
     59 
     60     if (ioctl(spi_handle->fd, SPI_IOC_MESSAGE(1), &xfer) >= 0)
     61         return CMD_ACK;
     62     else
     63         return CMD_NACK;
     64 }
     65 
     66 uint8_t spi_read_data(handle_t *handle, uint8_t *data, int length)
     67 {
     68     spi_handle_t *spi_handle = (spi_handle_t *)handle;
     69     uint8_t buffer[] =
     70     {
     71         0x00
     72     };
     73     struct spi_ioc_transfer xfer[] =
     74     {
     75         {
     76             .len = sizeof(buffer),
     77             .tx_buf = (unsigned long)buffer,
     78             .rx_buf = (unsigned long)buffer,
     79         },
     80         {
     81             .len = length,
     82             .tx_buf = (unsigned long)data,
     83             .rx_buf = (unsigned long)data,
     84             .cs_change = 1,
     85         }
     86     };
     87 
     88     if (ioctl(spi_handle->fd, SPI_IOC_MESSAGE(2), xfer) >= 0)
     89         return CMD_ACK;
     90     else
     91         return CMD_NACK;
     92 }
     93 
     94 uint8_t spi_read_ack(handle_t *handle)
     95 {
     96     spi_handle_t *spi_handle = (spi_handle_t *)handle;
     97     uint16_t timeout = 65535;
     98     uint8_t ret;
     99     uint8_t buffer[] =
    100     {
    101         0x00,
    102     };
    103     struct spi_ioc_transfer xfer =
    104     {
    105         .len = sizeof(buffer),
    106         .tx_buf = (unsigned long)buffer,
    107         .rx_buf = (unsigned long)buffer,
    108         .cs_change = 1,
    109     };
    110 
    111     if (ioctl(spi_handle->fd, SPI_IOC_MESSAGE(1), &xfer) >= 0) {
    112         do {
    113             ioctl(spi_handle->fd, SPI_IOC_MESSAGE(1), &xfer);
    114             timeout --;
    115         } while (buffer[0] != CMD_ACK && buffer[0] != CMD_NACK && timeout > 0);
    116 
    117         if (buffer[0] != CMD_ACK && buffer[0] != CMD_NACK && timeout == 0)
    118             ret = CMD_NACK;
    119         else
    120             ret = buffer[0];
    121         ioctl(spi_handle->fd, SPI_IOC_MESSAGE(1), &xfer);
    122 
    123         return ret;
    124     } else {
    125         return CMD_NACK;
    126     }
    127 }
    128 
    129 uint8_t spi_sync(handle_t *handle)
    130 {
    131     spi_handle_t *spi_handle = (spi_handle_t *)handle;
    132     uint8_t buffer[] =
    133     {
    134         CMD_SOF,
    135     };
    136     struct spi_ioc_transfer xfer =
    137     {
    138         .len = sizeof(buffer),
    139         .tx_buf = (unsigned long)buffer,
    140         .rx_buf = (unsigned long)buffer,
    141         .cs_change = 1,
    142     };
    143 
    144     if (ioctl(spi_handle->fd, SPI_IOC_MESSAGE(1), &xfer) >= 0)
    145         return handle->read_ack(handle);
    146     else
    147         return CMD_NACK;
    148 }
    149 
    150 int spi_init(handle_t *handle)
    151 {
    152     spi_handle_t *spi_handle = (spi_handle_t *)handle;
    153     uint8_t tmp8;
    154     uint32_t tmp32;
    155 
    156     handle->cmd_erase = CMD_ERASE;
    157     handle->cmd_read_memory = CMD_READ_MEMORY;
    158     handle->cmd_write_memory = CMD_WRITE_MEMORY;
    159 
    160     handle->no_extra_sync = 0;
    161 
    162     handle->write_data = spi_write_data;
    163     handle->write_cmd = spi_write_cmd;
    164     handle->read_data = spi_read_data;
    165     handle->read_ack = spi_read_ack;
    166 
    167     tmp8 = SPI_MODE_0;
    168     if (ioctl(spi_handle->fd, SPI_IOC_WR_MODE, &tmp8) < 0) {
    169         perror("Error setting mode");
    170         return -1;
    171     }
    172 
    173     tmp32 = 8000000;
    174     if (ioctl(spi_handle->fd, SPI_IOC_WR_MAX_SPEED_HZ, &tmp32) < 0) {
    175         perror("Error setting speed");
    176         return -1;
    177     }
    178 
    179     tmp8 = 8;
    180     if (ioctl(spi_handle->fd, SPI_IOC_WR_BITS_PER_WORD, &tmp8) < 0) {
    181         perror("Error setting bits per word");
    182         return -1;
    183     }
    184 
    185     if (spi_sync(handle) == CMD_ACK)
    186         return 0;
    187     else
    188         return -1;
    189 }
    190