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