|
@@ -62,15 +62,15 @@
|
|
|
#define SIRFSOC_SPI_TRAN_DAT_FORMAT_12 (1 << 26)
|
|
|
#define SIRFSOC_SPI_TRAN_DAT_FORMAT_16 (2 << 26)
|
|
|
#define SIRFSOC_SPI_TRAN_DAT_FORMAT_32 (3 << 26)
|
|
|
-#define SIRFSOC_SPI_CMD_BYTE_NUM(x) ((x & 3) << 28)
|
|
|
-#define SIRFSOC_SPI_ENA_AUTO_CLR BIT(30)
|
|
|
-#define SIRFSOC_SPI_MUL_DAT_MODE BIT(31)
|
|
|
+#define SIRFSOC_SPI_CMD_BYTE_NUM(x) ((x & 3) << 28)
|
|
|
+#define SIRFSOC_SPI_ENA_AUTO_CLR BIT(30)
|
|
|
+#define SIRFSOC_SPI_MUL_DAT_MODE BIT(31)
|
|
|
|
|
|
/* Interrupt Enable */
|
|
|
-#define SIRFSOC_SPI_RX_DONE_INT_EN BIT(0)
|
|
|
-#define SIRFSOC_SPI_TX_DONE_INT_EN BIT(1)
|
|
|
-#define SIRFSOC_SPI_RX_OFLOW_INT_EN BIT(2)
|
|
|
-#define SIRFSOC_SPI_TX_UFLOW_INT_EN BIT(3)
|
|
|
+#define SIRFSOC_SPI_RX_DONE_INT_EN BIT(0)
|
|
|
+#define SIRFSOC_SPI_TX_DONE_INT_EN BIT(1)
|
|
|
+#define SIRFSOC_SPI_RX_OFLOW_INT_EN BIT(2)
|
|
|
+#define SIRFSOC_SPI_TX_UFLOW_INT_EN BIT(3)
|
|
|
#define SIRFSOC_SPI_RX_IO_DMA_INT_EN BIT(4)
|
|
|
#define SIRFSOC_SPI_TX_IO_DMA_INT_EN BIT(5)
|
|
|
#define SIRFSOC_SPI_RXFIFO_FULL_INT_EN BIT(6)
|
|
@@ -79,7 +79,7 @@
|
|
|
#define SIRFSOC_SPI_TXFIFO_THD_INT_EN BIT(9)
|
|
|
#define SIRFSOC_SPI_FRM_END_INT_EN BIT(10)
|
|
|
|
|
|
-#define SIRFSOC_SPI_INT_MASK_ALL 0x1FFF
|
|
|
+#define SIRFSOC_SPI_INT_MASK_ALL 0x1FFF
|
|
|
|
|
|
/* Interrupt status */
|
|
|
#define SIRFSOC_SPI_RX_DONE BIT(0)
|
|
@@ -170,8 +170,7 @@ struct sirfsoc_spi {
|
|
|
* command model
|
|
|
*/
|
|
|
bool tx_by_cmd;
|
|
|
-
|
|
|
- int chipselect[0];
|
|
|
+ bool hw_cs;
|
|
|
};
|
|
|
|
|
|
static void spi_sirfsoc_rx_word_u8(struct sirfsoc_spi *sspi)
|
|
@@ -304,7 +303,7 @@ static void spi_sirfsoc_dma_fini_callback(void *data)
|
|
|
complete(dma_complete);
|
|
|
}
|
|
|
|
|
|
-static int spi_sirfsoc_cmd_transfer(struct spi_device *spi,
|
|
|
+static void spi_sirfsoc_cmd_transfer(struct spi_device *spi,
|
|
|
struct spi_transfer *t)
|
|
|
{
|
|
|
struct sirfsoc_spi *sspi;
|
|
@@ -328,10 +327,9 @@ static int spi_sirfsoc_cmd_transfer(struct spi_device *spi,
|
|
|
sspi->base + SIRFSOC_SPI_TX_RX_EN);
|
|
|
if (wait_for_completion_timeout(&sspi->tx_done, timeout) == 0) {
|
|
|
dev_err(&spi->dev, "cmd transfer timeout\n");
|
|
|
- return 0;
|
|
|
+ return;
|
|
|
}
|
|
|
-
|
|
|
- return t->len;
|
|
|
+ sspi->left_rx_word -= t->len;
|
|
|
}
|
|
|
|
|
|
static void spi_sirfsoc_dma_transfer(struct spi_device *spi,
|
|
@@ -487,7 +485,7 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
|
|
|
{
|
|
|
struct sirfsoc_spi *sspi = spi_master_get_devdata(spi->master);
|
|
|
|
|
|
- if (sspi->chipselect[spi->chip_select] == 0) {
|
|
|
+ if (sspi->hw_cs) {
|
|
|
u32 regval = readl(sspi->base + SIRFSOC_SPI_CTRL);
|
|
|
switch (value) {
|
|
|
case BITBANG_CS_ACTIVE:
|
|
@@ -505,14 +503,13 @@ static void spi_sirfsoc_chipselect(struct spi_device *spi, int value)
|
|
|
}
|
|
|
writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
|
|
|
} else {
|
|
|
- int gpio = sspi->chipselect[spi->chip_select];
|
|
|
switch (value) {
|
|
|
case BITBANG_CS_ACTIVE:
|
|
|
- gpio_direction_output(gpio,
|
|
|
+ gpio_direction_output(spi->cs_gpio,
|
|
|
spi->mode & SPI_CS_HIGH ? 1 : 0);
|
|
|
break;
|
|
|
case BITBANG_CS_INACTIVE:
|
|
|
- gpio_direction_output(gpio,
|
|
|
+ gpio_direction_output(spi->cs_gpio,
|
|
|
spi->mode & SPI_CS_HIGH ? 0 : 1);
|
|
|
break;
|
|
|
}
|
|
@@ -606,8 +603,8 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|
|
|
sspi->tx_by_cmd = false;
|
|
|
}
|
|
|
/*
|
|
|
- * set spi controller in RISC chipselect mode, we are controlling CS by
|
|
|
- * software BITBANG_CS_ACTIVE and BITBANG_CS_INACTIVE.
|
|
|
+ * it should never set to hardware cs mode because in hardware cs mode,
|
|
|
+ * cs signal can't controlled by driver.
|
|
|
*/
|
|
|
regval |= SIRFSOC_SPI_CS_IO_MODE;
|
|
|
writel(regval, sspi->base + SIRFSOC_SPI_CTRL);
|
|
@@ -630,9 +627,17 @@ spi_sirfsoc_setup_transfer(struct spi_device *spi, struct spi_transfer *t)
|
|
|
|
|
|
static int spi_sirfsoc_setup(struct spi_device *spi)
|
|
|
{
|
|
|
+ struct sirfsoc_spi *sspi;
|
|
|
+
|
|
|
if (!spi->max_speed_hz)
|
|
|
return -EINVAL;
|
|
|
|
|
|
+ sspi = spi_master_get_devdata(spi->master);
|
|
|
+
|
|
|
+ if (spi->cs_gpio == -ENOENT)
|
|
|
+ sspi->hw_cs = true;
|
|
|
+ else
|
|
|
+ sspi->hw_cs = false;
|
|
|
return spi_sirfsoc_setup_transfer(spi, NULL);
|
|
|
}
|
|
|
|
|
@@ -641,19 +646,10 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
|
|
|
struct sirfsoc_spi *sspi;
|
|
|
struct spi_master *master;
|
|
|
struct resource *mem_res;
|
|
|
- int num_cs, cs_gpio, irq;
|
|
|
- int i;
|
|
|
- int ret;
|
|
|
-
|
|
|
- ret = of_property_read_u32(pdev->dev.of_node,
|
|
|
- "sirf,spi-num-chipselects", &num_cs);
|
|
|
- if (ret < 0) {
|
|
|
- dev_err(&pdev->dev, "Unable to get chip select number\n");
|
|
|
- goto err_cs;
|
|
|
- }
|
|
|
+ int irq;
|
|
|
+ int i, ret;
|
|
|
|
|
|
- master = spi_alloc_master(&pdev->dev,
|
|
|
- sizeof(*sspi) + sizeof(int) * num_cs);
|
|
|
+ master = spi_alloc_master(&pdev->dev, sizeof(*sspi));
|
|
|
if (!master) {
|
|
|
dev_err(&pdev->dev, "Unable to allocate SPI master\n");
|
|
|
return -ENOMEM;
|
|
@@ -661,32 +657,6 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
|
|
|
platform_set_drvdata(pdev, master);
|
|
|
sspi = spi_master_get_devdata(master);
|
|
|
|
|
|
- master->num_chipselect = num_cs;
|
|
|
-
|
|
|
- for (i = 0; i < master->num_chipselect; i++) {
|
|
|
- cs_gpio = of_get_named_gpio(pdev->dev.of_node, "cs-gpios", i);
|
|
|
- if (cs_gpio < 0) {
|
|
|
- dev_err(&pdev->dev, "can't get cs gpio from DT\n");
|
|
|
- ret = -ENODEV;
|
|
|
- goto free_master;
|
|
|
- }
|
|
|
-
|
|
|
- sspi->chipselect[i] = cs_gpio;
|
|
|
- if (cs_gpio == 0)
|
|
|
- continue; /* use cs from spi controller */
|
|
|
-
|
|
|
- ret = gpio_request(cs_gpio, DRIVER_NAME);
|
|
|
- if (ret) {
|
|
|
- while (i > 0) {
|
|
|
- i--;
|
|
|
- if (sspi->chipselect[i] > 0)
|
|
|
- gpio_free(sspi->chipselect[i]);
|
|
|
- }
|
|
|
- dev_err(&pdev->dev, "fail to request cs gpios\n");
|
|
|
- goto free_master;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
|
|
sspi->base = devm_ioremap_resource(&pdev->dev, mem_res);
|
|
|
if (IS_ERR(sspi->base)) {
|
|
@@ -756,7 +726,21 @@ static int spi_sirfsoc_probe(struct platform_device *pdev)
|
|
|
ret = spi_bitbang_start(&sspi->bitbang);
|
|
|
if (ret)
|
|
|
goto free_dummypage;
|
|
|
-
|
|
|
+ for (i = 0; master->cs_gpios && i < master->num_chipselect; i++) {
|
|
|
+ if (master->cs_gpios[i] == -ENOENT)
|
|
|
+ continue;
|
|
|
+ if (!gpio_is_valid(master->cs_gpios[i])) {
|
|
|
+ dev_err(&pdev->dev, "no valid gpio\n");
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto free_dummypage;
|
|
|
+ }
|
|
|
+ ret = devm_gpio_request(&pdev->dev,
|
|
|
+ master->cs_gpios[i], DRIVER_NAME);
|
|
|
+ if (ret) {
|
|
|
+ dev_err(&pdev->dev, "failed to request gpio\n");
|
|
|
+ goto free_dummypage;
|
|
|
+ }
|
|
|
+ }
|
|
|
dev_info(&pdev->dev, "registerred, bus number = %d\n", master->bus_num);
|
|
|
|
|
|
return 0;
|
|
@@ -771,7 +755,7 @@ free_rx_dma:
|
|
|
dma_release_channel(sspi->rx_chan);
|
|
|
free_master:
|
|
|
spi_master_put(master);
|
|
|
-err_cs:
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
|
|
@@ -779,16 +763,11 @@ static int spi_sirfsoc_remove(struct platform_device *pdev)
|
|
|
{
|
|
|
struct spi_master *master;
|
|
|
struct sirfsoc_spi *sspi;
|
|
|
- int i;
|
|
|
|
|
|
master = platform_get_drvdata(pdev);
|
|
|
sspi = spi_master_get_devdata(master);
|
|
|
|
|
|
spi_bitbang_stop(&sspi->bitbang);
|
|
|
- for (i = 0; i < master->num_chipselect; i++) {
|
|
|
- if (sspi->chipselect[i] > 0)
|
|
|
- gpio_free(sspi->chipselect[i]);
|
|
|
- }
|
|
|
kfree(sspi->dummypage);
|
|
|
clk_disable_unprepare(sspi->clk);
|
|
|
clk_put(sspi->clk);
|