/** * @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; }
/** * @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; }