Example #1
0
/**
 * @brief Probe SPI device
 *
 * This function is called by the system to register the driver when the system
 * boot up. This function allocates memory for the private SPI device
 * information, and then setup the hardware resource and interrupt handler.
 *
 * @param dev pointer to structure of device data
 * @return 0 on success, negative errno on error
 */
static int tsb_spi_dev_probe(struct device *dev)
{
    struct tsb_spi_info *info = NULL;
    struct device_spi_caps *caps = NULL;
    int ret = 0;

    if (!dev) {
        return -EINVAL;
    }

    info = zalloc(sizeof(*info));
    if (!info) {
        return -ENOMEM;
    }

    info->dev = dev;
    info->state = TSB_SPI_STATE_CLOSED;
    device_set_private(dev, info);

    /* setup spi hardware capabilities */
    caps = &info->caps;
    caps->modes = SPI_MODE_CPHA |
                  SPI_MODE_CPOL |
                  SPI_MODE_CS_HIGH |
                  SPI_MODE_LSB_FIRST |
                  SPI_MODE_LOOP;
    caps->flags = 0; /* Full Duplex */
    caps->bpw = BIT(8-1) | BIT(16-1) | BIT(32-1);
    caps->csnum = 1; /* support 1 chipselect */

    info->chipselect[0] = SPI_CS;
    info->selected = -1; /* select none */
    info->bitexchange = tsb_spi_bitexchange0;

    /* initialize gpio pins */
    tsb_spi_hw_init(dev);

    sem_init(&info->bus, 0, 1);
    sem_init(&info->lock, 0, 1);

    return ret;
}
Example #2
0
/**
 * @brief Open SPI device
 *
 * This function is called when the caller is preparing to use this device
 * driver. This function should be called after probe() function and needs to
 * check whether the driver is already open. If driver was opened, it needs
 * to return an error code to the caller.
 *
 * @param dev pointer to structure of device data
 * @return 0 on success, negative errno on error
 */
static int tsb_spi_dev_open(struct device *dev)
{
    struct tsb_spi_dev_info *info = NULL;
    struct device *spi_board;
    int i;
    int ret = 0;

    /* check input parameter */
    if (!dev || !device_get_private(dev)) {
        return -EINVAL;
    }

    info = device_get_private(dev);

    sem_wait(&info->lock);

    if (info->state != TSB_SPI_STATE_CLOSED) {
        ret = -EBUSY;
        goto err_open;
    }

    /* open all the consecutive slaves we can find */
    info->num_boards = 0;
    for (i = 0; i < SPI_MAX_SLAVES; i++) {
        spi_board = device_open(DEVICE_TYPE_SPI_BOARD_HW, i);
        if (spi_board) {
            info->num_boards++;
            info->dev_spi_board[i] = spi_board;
        } else
            break;
    }

    info->curr_xfer.cs_high = 0;
    info->curr_xfer.bpw = 8;

    ret = tsb_spi_hw_init(info);
    if (ret) {
        goto err_hwinit;
    }
    /* register SPI IRQ number */
    ret = irq_attach(TSB_IRQ_SPI, tsb_spi_irq_handler, NULL);
    if (ret != OK) {
        ret = -EIO;
        goto err_irq;
    }

    up_enable_irq(TSB_IRQ_SPI);

    info->state = TSB_SPI_STATE_OPEN;
    sem_post(&info->lock);
    return ret;

err_irq:
    tsb_spi_hw_deinit(info);
err_hwinit:
    for (i = 0; i < info->num_boards; i++) {
        device_close(info->dev_spi_board[i]);
        info->dev_spi_board[i] = NULL;
    }
err_open:
    sem_post(&info->lock);
    return ret;
}