diff options
Diffstat (limited to 'drivers')
-rw-r--r-- | drivers/spi/Kconfig | 1 | ||||
-rw-r--r-- | drivers/spi/pxa2xx_spi.c | 138 |
2 files changed, 53 insertions, 86 deletions
diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig index abf05048c638..aaaea81e412a 100644 --- a/drivers/spi/Kconfig +++ b/drivers/spi/Kconfig | |||
@@ -153,6 +153,7 @@ config SPI_OMAP24XX | |||
153 | config SPI_PXA2XX | 153 | config SPI_PXA2XX |
154 | tristate "PXA2xx SSP SPI master" | 154 | tristate "PXA2xx SSP SPI master" |
155 | depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL | 155 | depends on SPI_MASTER && ARCH_PXA && EXPERIMENTAL |
156 | select PXA_SSP | ||
156 | help | 157 | help |
157 | This enables using a PXA2xx SSP port as a SPI master controller. | 158 | This enables using a PXA2xx SSP port as a SPI master controller. |
158 | The driver can be configured to use any SSP port and additional | 159 | The driver can be configured to use any SSP port and additional |
diff --git a/drivers/spi/pxa2xx_spi.c b/drivers/spi/pxa2xx_spi.c index 0ac0f65f69a1..eb817b8eb024 100644 --- a/drivers/spi/pxa2xx_spi.c +++ b/drivers/spi/pxa2xx_spi.c | |||
@@ -27,6 +27,7 @@ | |||
27 | #include <linux/spi/spi.h> | 27 | #include <linux/spi/spi.h> |
28 | #include <linux/workqueue.h> | 28 | #include <linux/workqueue.h> |
29 | #include <linux/delay.h> | 29 | #include <linux/delay.h> |
30 | #include <linux/clk.h> | ||
30 | 31 | ||
31 | #include <asm/io.h> | 32 | #include <asm/io.h> |
32 | #include <asm/irq.h> | 33 | #include <asm/irq.h> |
@@ -37,6 +38,7 @@ | |||
37 | #include <asm/arch/hardware.h> | 38 | #include <asm/arch/hardware.h> |
38 | #include <asm/arch/pxa-regs.h> | 39 | #include <asm/arch/pxa-regs.h> |
39 | #include <asm/arch/regs-ssp.h> | 40 | #include <asm/arch/regs-ssp.h> |
41 | #include <asm/arch/ssp.h> | ||
40 | #include <asm/arch/pxa2xx_spi.h> | 42 | #include <asm/arch/pxa2xx_spi.h> |
41 | 43 | ||
42 | MODULE_AUTHOR("Stephen Street"); | 44 | MODULE_AUTHOR("Stephen Street"); |
@@ -81,6 +83,9 @@ struct driver_data { | |||
81 | /* Driver model hookup */ | 83 | /* Driver model hookup */ |
82 | struct platform_device *pdev; | 84 | struct platform_device *pdev; |
83 | 85 | ||
86 | /* SSP Info */ | ||
87 | struct ssp_device *ssp; | ||
88 | |||
84 | /* SPI framework hookup */ | 89 | /* SPI framework hookup */ |
85 | enum pxa_ssp_type ssp_type; | 90 | enum pxa_ssp_type ssp_type; |
86 | struct spi_master *master; | 91 | struct spi_master *master; |
@@ -779,6 +784,16 @@ int set_dma_burst_and_threshold(struct chip_data *chip, struct spi_device *spi, | |||
779 | return retval; | 784 | return retval; |
780 | } | 785 | } |
781 | 786 | ||
787 | static unsigned int ssp_get_clk_div(struct ssp_device *ssp, int rate) | ||
788 | { | ||
789 | unsigned long ssp_clk = clk_get_rate(ssp->clk); | ||
790 | |||
791 | if (ssp->type == PXA25x_SSP) | ||
792 | return ((ssp_clk / (2 * rate) - 1) & 0xff) << 8; | ||
793 | else | ||
794 | return ((ssp_clk / rate - 1) & 0xfff) << 8; | ||
795 | } | ||
796 | |||
782 | static void pump_transfers(unsigned long data) | 797 | static void pump_transfers(unsigned long data) |
783 | { | 798 | { |
784 | struct driver_data *drv_data = (struct driver_data *)data; | 799 | struct driver_data *drv_data = (struct driver_data *)data; |
@@ -786,6 +801,7 @@ static void pump_transfers(unsigned long data) | |||
786 | struct spi_transfer *transfer = NULL; | 801 | struct spi_transfer *transfer = NULL; |
787 | struct spi_transfer *previous = NULL; | 802 | struct spi_transfer *previous = NULL; |
788 | struct chip_data *chip = NULL; | 803 | struct chip_data *chip = NULL; |
804 | struct ssp_device *ssp = drv_data->ssp; | ||
789 | void *reg = drv_data->ioaddr; | 805 | void *reg = drv_data->ioaddr; |
790 | u32 clk_div = 0; | 806 | u32 clk_div = 0; |
791 | u8 bits = 0; | 807 | u8 bits = 0; |
@@ -867,12 +883,7 @@ static void pump_transfers(unsigned long data) | |||
867 | if (transfer->bits_per_word) | 883 | if (transfer->bits_per_word) |
868 | bits = transfer->bits_per_word; | 884 | bits = transfer->bits_per_word; |
869 | 885 | ||
870 | if (reg == SSP1_VIRT) | 886 | clk_div = ssp_get_clk_div(ssp, speed); |
871 | clk_div = SSP1_SerClkDiv(speed); | ||
872 | else if (reg == SSP2_VIRT) | ||
873 | clk_div = SSP2_SerClkDiv(speed); | ||
874 | else if (reg == SSP3_VIRT) | ||
875 | clk_div = SSP3_SerClkDiv(speed); | ||
876 | 887 | ||
877 | if (bits <= 8) { | 888 | if (bits <= 8) { |
878 | drv_data->n_bytes = 1; | 889 | drv_data->n_bytes = 1; |
@@ -1075,6 +1086,7 @@ static int setup(struct spi_device *spi) | |||
1075 | struct pxa2xx_spi_chip *chip_info = NULL; | 1086 | struct pxa2xx_spi_chip *chip_info = NULL; |
1076 | struct chip_data *chip; | 1087 | struct chip_data *chip; |
1077 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); | 1088 | struct driver_data *drv_data = spi_master_get_devdata(spi->master); |
1089 | struct ssp_device *ssp = drv_data->ssp; | ||
1078 | unsigned int clk_div; | 1090 | unsigned int clk_div; |
1079 | 1091 | ||
1080 | if (!spi->bits_per_word) | 1092 | if (!spi->bits_per_word) |
@@ -1158,18 +1170,7 @@ static int setup(struct spi_device *spi) | |||
1158 | } | 1170 | } |
1159 | } | 1171 | } |
1160 | 1172 | ||
1161 | if (drv_data->ioaddr == SSP1_VIRT) | 1173 | clk_div = ssp_get_clk_div(ssp, spi->max_speed_hz); |
1162 | clk_div = SSP1_SerClkDiv(spi->max_speed_hz); | ||
1163 | else if (drv_data->ioaddr == SSP2_VIRT) | ||
1164 | clk_div = SSP2_SerClkDiv(spi->max_speed_hz); | ||
1165 | else if (drv_data->ioaddr == SSP3_VIRT) | ||
1166 | clk_div = SSP3_SerClkDiv(spi->max_speed_hz); | ||
1167 | else | ||
1168 | { | ||
1169 | dev_err(&spi->dev, "failed setup: unknown IO address=0x%p\n", | ||
1170 | drv_data->ioaddr); | ||
1171 | return -ENODEV; | ||
1172 | } | ||
1173 | chip->speed_hz = spi->max_speed_hz; | 1174 | chip->speed_hz = spi->max_speed_hz; |
1174 | 1175 | ||
1175 | chip->cr0 = clk_div | 1176 | chip->cr0 = clk_div |
@@ -1184,15 +1185,15 @@ static int setup(struct spi_device *spi) | |||
1184 | 1185 | ||
1185 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ | 1186 | /* NOTE: PXA25x_SSP _could_ use external clocking ... */ |
1186 | if (drv_data->ssp_type != PXA25x_SSP) | 1187 | if (drv_data->ssp_type != PXA25x_SSP) |
1187 | dev_dbg(&spi->dev, "%d bits/word, %d Hz, mode %d\n", | 1188 | dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n", |
1188 | spi->bits_per_word, | 1189 | spi->bits_per_word, |
1189 | (CLOCK_SPEED_HZ) | 1190 | clk_get_rate(ssp->clk) |
1190 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), | 1191 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), |
1191 | spi->mode & 0x3); | 1192 | spi->mode & 0x3); |
1192 | else | 1193 | else |
1193 | dev_dbg(&spi->dev, "%d bits/word, %d Hz, mode %d\n", | 1194 | dev_dbg(&spi->dev, "%d bits/word, %ld Hz, mode %d\n", |
1194 | spi->bits_per_word, | 1195 | spi->bits_per_word, |
1195 | (CLOCK_SPEED_HZ/2) | 1196 | clk_get_rate(ssp->clk) |
1196 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), | 1197 | / (1 + ((chip->cr0 & SSCR0_SCR) >> 8)), |
1197 | spi->mode & 0x3); | 1198 | spi->mode & 0x3); |
1198 | 1199 | ||
@@ -1324,14 +1325,14 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1324 | struct pxa2xx_spi_master *platform_info; | 1325 | struct pxa2xx_spi_master *platform_info; |
1325 | struct spi_master *master; | 1326 | struct spi_master *master; |
1326 | struct driver_data *drv_data = 0; | 1327 | struct driver_data *drv_data = 0; |
1327 | struct resource *memory_resource; | 1328 | struct ssp_device *ssp; |
1328 | int irq; | ||
1329 | int status = 0; | 1329 | int status = 0; |
1330 | 1330 | ||
1331 | platform_info = dev->platform_data; | 1331 | platform_info = dev->platform_data; |
1332 | 1332 | ||
1333 | if (platform_info->ssp_type == SSP_UNDEFINED) { | 1333 | ssp = ssp_request(pdev->id, pdev->name); |
1334 | dev_err(&pdev->dev, "undefined SSP\n"); | 1334 | if (ssp == NULL) { |
1335 | dev_err(&pdev->dev, "failed to request SSP%d\n", pdev->id); | ||
1335 | return -ENODEV; | 1336 | return -ENODEV; |
1336 | } | 1337 | } |
1337 | 1338 | ||
@@ -1339,12 +1340,14 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1339 | master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); | 1340 | master = spi_alloc_master(dev, sizeof(struct driver_data) + 16); |
1340 | if (!master) { | 1341 | if (!master) { |
1341 | dev_err(&pdev->dev, "can not alloc spi_master\n"); | 1342 | dev_err(&pdev->dev, "can not alloc spi_master\n"); |
1343 | ssp_free(ssp); | ||
1342 | return -ENOMEM; | 1344 | return -ENOMEM; |
1343 | } | 1345 | } |
1344 | drv_data = spi_master_get_devdata(master); | 1346 | drv_data = spi_master_get_devdata(master); |
1345 | drv_data->master = master; | 1347 | drv_data->master = master; |
1346 | drv_data->master_info = platform_info; | 1348 | drv_data->master_info = platform_info; |
1347 | drv_data->pdev = pdev; | 1349 | drv_data->pdev = pdev; |
1350 | drv_data->ssp = ssp; | ||
1348 | 1351 | ||
1349 | master->bus_num = pdev->id; | 1352 | master->bus_num = pdev->id; |
1350 | master->num_chipselect = platform_info->num_chipselect; | 1353 | master->num_chipselect = platform_info->num_chipselect; |
@@ -1352,21 +1355,13 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1352 | master->setup = setup; | 1355 | master->setup = setup; |
1353 | master->transfer = transfer; | 1356 | master->transfer = transfer; |
1354 | 1357 | ||
1355 | drv_data->ssp_type = platform_info->ssp_type; | 1358 | drv_data->ssp_type = ssp->type; |
1356 | drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data + | 1359 | drv_data->null_dma_buf = (u32 *)ALIGN((u32)(drv_data + |
1357 | sizeof(struct driver_data)), 8); | 1360 | sizeof(struct driver_data)), 8); |
1358 | 1361 | ||
1359 | /* Setup register addresses */ | 1362 | drv_data->ioaddr = ssp->mmio_base; |
1360 | memory_resource = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1363 | drv_data->ssdr_physical = ssp->phys_base + SSDR; |
1361 | if (!memory_resource) { | 1364 | if (ssp->type == PXA25x_SSP) { |
1362 | dev_err(&pdev->dev, "memory resources not defined\n"); | ||
1363 | status = -ENODEV; | ||
1364 | goto out_error_master_alloc; | ||
1365 | } | ||
1366 | |||
1367 | drv_data->ioaddr = (void *)io_p2v((unsigned long)(memory_resource->start)); | ||
1368 | drv_data->ssdr_physical = memory_resource->start + 0x00000010; | ||
1369 | if (platform_info->ssp_type == PXA25x_SSP) { | ||
1370 | drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE; | 1365 | drv_data->int_cr1 = SSCR1_TIE | SSCR1_RIE; |
1371 | drv_data->dma_cr1 = 0; | 1366 | drv_data->dma_cr1 = 0; |
1372 | drv_data->clear_sr = SSSR_ROR; | 1367 | drv_data->clear_sr = SSSR_ROR; |
@@ -1378,15 +1373,7 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1378 | drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR; | 1373 | drv_data->mask_sr = SSSR_TINT | SSSR_RFS | SSSR_TFS | SSSR_ROR; |
1379 | } | 1374 | } |
1380 | 1375 | ||
1381 | /* Attach to IRQ */ | 1376 | status = request_irq(ssp->irq, ssp_int, 0, dev->bus_id, drv_data); |
1382 | irq = platform_get_irq(pdev, 0); | ||
1383 | if (irq < 0) { | ||
1384 | dev_err(&pdev->dev, "irq resource not defined\n"); | ||
1385 | status = -ENODEV; | ||
1386 | goto out_error_master_alloc; | ||
1387 | } | ||
1388 | |||
1389 | status = request_irq(irq, ssp_int, 0, dev->bus_id, drv_data); | ||
1390 | if (status < 0) { | 1377 | if (status < 0) { |
1391 | dev_err(&pdev->dev, "can not get IRQ\n"); | 1378 | dev_err(&pdev->dev, "can not get IRQ\n"); |
1392 | goto out_error_master_alloc; | 1379 | goto out_error_master_alloc; |
@@ -1419,29 +1406,12 @@ static int __init pxa2xx_spi_probe(struct platform_device *pdev) | |||
1419 | goto out_error_dma_alloc; | 1406 | goto out_error_dma_alloc; |
1420 | } | 1407 | } |
1421 | 1408 | ||
1422 | if (drv_data->ioaddr == SSP1_VIRT) { | 1409 | DRCMR(ssp->drcmr_rx) = DRCMR_MAPVLD | drv_data->rx_channel; |
1423 | DRCMRRXSSDR = DRCMR_MAPVLD | 1410 | DRCMR(ssp->drcmr_tx) = DRCMR_MAPVLD | drv_data->tx_channel; |
1424 | | drv_data->rx_channel; | ||
1425 | DRCMRTXSSDR = DRCMR_MAPVLD | ||
1426 | | drv_data->tx_channel; | ||
1427 | } else if (drv_data->ioaddr == SSP2_VIRT) { | ||
1428 | DRCMRRXSS2DR = DRCMR_MAPVLD | ||
1429 | | drv_data->rx_channel; | ||
1430 | DRCMRTXSS2DR = DRCMR_MAPVLD | ||
1431 | | drv_data->tx_channel; | ||
1432 | } else if (drv_data->ioaddr == SSP3_VIRT) { | ||
1433 | DRCMRRXSS3DR = DRCMR_MAPVLD | ||
1434 | | drv_data->rx_channel; | ||
1435 | DRCMRTXSS3DR = DRCMR_MAPVLD | ||
1436 | | drv_data->tx_channel; | ||
1437 | } else { | ||
1438 | dev_err(dev, "bad SSP type\n"); | ||
1439 | goto out_error_dma_alloc; | ||
1440 | } | ||
1441 | } | 1411 | } |
1442 | 1412 | ||
1443 | /* Enable SOC clock */ | 1413 | /* Enable SOC clock */ |
1444 | pxa_set_cken(platform_info->clock_enable, 1); | 1414 | clk_enable(ssp->clk); |
1445 | 1415 | ||
1446 | /* Load default SSP configuration */ | 1416 | /* Load default SSP configuration */ |
1447 | write_SSCR0(0, drv_data->ioaddr); | 1417 | write_SSCR0(0, drv_data->ioaddr); |
@@ -1480,7 +1450,7 @@ out_error_queue_alloc: | |||
1480 | destroy_queue(drv_data); | 1450 | destroy_queue(drv_data); |
1481 | 1451 | ||
1482 | out_error_clock_enabled: | 1452 | out_error_clock_enabled: |
1483 | pxa_set_cken(platform_info->clock_enable, 0); | 1453 | clk_disable(ssp->clk); |
1484 | 1454 | ||
1485 | out_error_dma_alloc: | 1455 | out_error_dma_alloc: |
1486 | if (drv_data->tx_channel != -1) | 1456 | if (drv_data->tx_channel != -1) |
@@ -1489,17 +1459,18 @@ out_error_dma_alloc: | |||
1489 | pxa_free_dma(drv_data->rx_channel); | 1459 | pxa_free_dma(drv_data->rx_channel); |
1490 | 1460 | ||
1491 | out_error_irq_alloc: | 1461 | out_error_irq_alloc: |
1492 | free_irq(irq, drv_data); | 1462 | free_irq(ssp->irq, drv_data); |
1493 | 1463 | ||
1494 | out_error_master_alloc: | 1464 | out_error_master_alloc: |
1495 | spi_master_put(master); | 1465 | spi_master_put(master); |
1466 | ssp_free(ssp); | ||
1496 | return status; | 1467 | return status; |
1497 | } | 1468 | } |
1498 | 1469 | ||
1499 | static int pxa2xx_spi_remove(struct platform_device *pdev) | 1470 | static int pxa2xx_spi_remove(struct platform_device *pdev) |
1500 | { | 1471 | { |
1501 | struct driver_data *drv_data = platform_get_drvdata(pdev); | 1472 | struct driver_data *drv_data = platform_get_drvdata(pdev); |
1502 | int irq; | 1473 | struct ssp_device *ssp = drv_data->ssp; |
1503 | int status = 0; | 1474 | int status = 0; |
1504 | 1475 | ||
1505 | if (!drv_data) | 1476 | if (!drv_data) |
@@ -1521,28 +1492,21 @@ static int pxa2xx_spi_remove(struct platform_device *pdev) | |||
1521 | 1492 | ||
1522 | /* Disable the SSP at the peripheral and SOC level */ | 1493 | /* Disable the SSP at the peripheral and SOC level */ |
1523 | write_SSCR0(0, drv_data->ioaddr); | 1494 | write_SSCR0(0, drv_data->ioaddr); |
1524 | pxa_set_cken(drv_data->master_info->clock_enable, 0); | 1495 | clk_disable(ssp->clk); |
1525 | 1496 | ||
1526 | /* Release DMA */ | 1497 | /* Release DMA */ |
1527 | if (drv_data->master_info->enable_dma) { | 1498 | if (drv_data->master_info->enable_dma) { |
1528 | if (drv_data->ioaddr == SSP1_VIRT) { | 1499 | DRCMR(ssp->drcmr_rx) = 0; |
1529 | DRCMRRXSSDR = 0; | 1500 | DRCMR(ssp->drcmr_tx) = 0; |
1530 | DRCMRTXSSDR = 0; | ||
1531 | } else if (drv_data->ioaddr == SSP2_VIRT) { | ||
1532 | DRCMRRXSS2DR = 0; | ||
1533 | DRCMRTXSS2DR = 0; | ||
1534 | } else if (drv_data->ioaddr == SSP3_VIRT) { | ||
1535 | DRCMRRXSS3DR = 0; | ||
1536 | DRCMRTXSS3DR = 0; | ||
1537 | } | ||
1538 | pxa_free_dma(drv_data->tx_channel); | 1501 | pxa_free_dma(drv_data->tx_channel); |
1539 | pxa_free_dma(drv_data->rx_channel); | 1502 | pxa_free_dma(drv_data->rx_channel); |
1540 | } | 1503 | } |
1541 | 1504 | ||
1542 | /* Release IRQ */ | 1505 | /* Release IRQ */ |
1543 | irq = platform_get_irq(pdev, 0); | 1506 | free_irq(ssp->irq, drv_data); |
1544 | if (irq >= 0) | 1507 | |
1545 | free_irq(irq, drv_data); | 1508 | /* Release SSP */ |
1509 | ssp_free(ssp); | ||
1546 | 1510 | ||
1547 | /* Disconnect from the SPI framework */ | 1511 | /* Disconnect from the SPI framework */ |
1548 | spi_unregister_master(drv_data->master); | 1512 | spi_unregister_master(drv_data->master); |
@@ -1577,6 +1541,7 @@ static int suspend_devices(struct device *dev, void *pm_message) | |||
1577 | static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state) | 1541 | static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state) |
1578 | { | 1542 | { |
1579 | struct driver_data *drv_data = platform_get_drvdata(pdev); | 1543 | struct driver_data *drv_data = platform_get_drvdata(pdev); |
1544 | struct ssp_device *ssp = drv_data->ssp; | ||
1580 | int status = 0; | 1545 | int status = 0; |
1581 | 1546 | ||
1582 | /* Check all childern for current power state */ | 1547 | /* Check all childern for current power state */ |
@@ -1589,7 +1554,7 @@ static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state) | |||
1589 | if (status != 0) | 1554 | if (status != 0) |
1590 | return status; | 1555 | return status; |
1591 | write_SSCR0(0, drv_data->ioaddr); | 1556 | write_SSCR0(0, drv_data->ioaddr); |
1592 | pxa_set_cken(drv_data->master_info->clock_enable, 0); | 1557 | clk_disable(ssp->clk); |
1593 | 1558 | ||
1594 | return 0; | 1559 | return 0; |
1595 | } | 1560 | } |
@@ -1597,10 +1562,11 @@ static int pxa2xx_spi_suspend(struct platform_device *pdev, pm_message_t state) | |||
1597 | static int pxa2xx_spi_resume(struct platform_device *pdev) | 1562 | static int pxa2xx_spi_resume(struct platform_device *pdev) |
1598 | { | 1563 | { |
1599 | struct driver_data *drv_data = platform_get_drvdata(pdev); | 1564 | struct driver_data *drv_data = platform_get_drvdata(pdev); |
1565 | struct ssp_device *ssp = drv_data->ssp; | ||
1600 | int status = 0; | 1566 | int status = 0; |
1601 | 1567 | ||
1602 | /* Enable the SSP clock */ | 1568 | /* Enable the SSP clock */ |
1603 | pxa_set_cken(drv_data->master_info->clock_enable, 1); | 1569 | clk_disable(ssp->clk); |
1604 | 1570 | ||
1605 | /* Start the queue running */ | 1571 | /* Start the queue running */ |
1606 | status = start_queue(drv_data); | 1572 | status = start_queue(drv_data); |