diff mbox

[8/8] intel_mid_ssp_spi: Implement slave side quirk

Message ID 20110209100932.555.57563.stgit@bob.linux.org.uk (mailing list archive)
State Superseded, archived
Headers show

Commit Message

Alan Cox Feb. 9, 2011, 10:09 a.m. UTC
None
diff mbox

Patch

diff --git a/drivers/spi/intel_mid_ssp_spi.c b/drivers/spi/intel_mid_ssp_spi.c
index 8d7a157..91976af 100644
--- a/drivers/spi/intel_mid_ssp_spi.c
+++ b/drivers/spi/intel_mid_ssp_spi.c
@@ -93,15 +93,13 @@  MODULE_LICENSE("GPL");
 
 #define PNWL_CR1_MASTER_ROLE	0
 #define PNWL_CR1_SLAVE_ROLE	(SSCR1_SFRMDIR | SSCR1_SCLKDIR)
-/* MRST SSP must be slave */
-#define PNWL_CR1_ROLE		PNWL_CR1_MASTER_ROLE
-#define PNWL_CR1(spi, chip)	\
+#define PNWL_CR1(spi, chip, role)	\
 	  ((chip->enable_loopback ? SSCR1_LBM : 0) | \
 	  ((spi->mode & SPI_CPHA) ? SSCR1_SPH : 0) | \
 	  ((spi->mode & SPI_CPOL) ? SSCR1_SPO : 0) | \
 	  SSCR1_SCFR | \
 	  chip->threshold | \
-	  PNWL_CR1_ROLE)
+	  role)
 
 
 
@@ -603,7 +601,7 @@  free_rxchan:
 	dma_release_channel(drv_data->rxchan);
 	if (drv_data->quirks & QUIRKS_SRAM_ADDITIONAL_CPY)
 		intel_mid_ssp_spi_unmap_sram(drv_data);
-		
+
 err_exit:
 	dev_err(&drv_data->pdev->dev, "DMA RX Channel Not available");
 	pci_dev_put(drv_data->dmac1);
@@ -1203,6 +1201,7 @@  static int setup(struct spi_device *spi)
 	uint rx_thres = RX_THRESH_DFLT;
 	u32 clk_div;
 	struct driver_data *drv_data = spi_master_get_devdata(spi->master);
+	int role = PNWL_CR1_MASTER_ROLE;
 
 	if (drv_data->pwrstate == PWRSTATE_OFF) {
 		dev_dbg(&drv_data->pdev->dev, "setup: busy, pwrstate:%d",
@@ -1272,15 +1271,20 @@  static int setup(struct spi_device *spi)
 		set_dma_width(drv_data, spi->bits_per_word);
 	}
 
-	chip->speed_hz = spi->max_speed_hz;
-	clk_div = ssp_get_clk_div(chip->speed_hz);
+	if (drv_data->quirks & QUIRKS_SPI_SLAVE_CLOCK_MODE) {
+		role = PNWL_CR1_SLAVE_ROLE;
+		clk_div = 1;
+	} else {
+		chip->speed_hz = spi->max_speed_hz;
+		clk_div = ssp_get_clk_div(chip->speed_hz);
+	}
 
 	chip->threshold = (SSCR1_RxTresh(rx_thres) & SSCR1_RFT) |
 		(SSCR1_TxTresh(tx_thres) & SSCR1_TFT);
 	chip->bits_per_word = spi->bits_per_word;
 
 	chip->cr0 = PNWL_CR0(clk_div, spi->bits_per_word, spi, chip);
-	chip->cr1 = PNWL_CR1(spi, chip);
+	chip->cr1 = PNWL_CR1(spi, chip, role);
 
 	dev_dbg(&spi->dev,
 		"KHz:%d bpw:%d mode:%d dma:%d poll:%d loop:%d cr0:%x cr1:%x",
@@ -1340,13 +1344,11 @@  static int intel_mid_ssp_spi_probe(struct pci_dev *pdev,
 		dev_info(dev, "No Vendor Specific PCI capability");
 		goto err_abort_probe;
 	}
-	if ((SSP_CFG_GET_MODE(ssp_cfg) != SSP_CFG_SPI_MODE_ID) ||
-		SSP_CFG_IS_SPI_SLAVE(ssp_cfg)) {
+	if (SSP_CFG_GET_MODE(ssp_cfg) != SSP_CFG_SPI_MODE_ID) {
 		dev_info(dev, "Unsupported SSP mode (%02xh)",
 			ssp_cfg);
 		goto err_abort_probe;
 	}
-
 	dev_info(&pdev->dev, "found PCI SSP controller(ID: %04xh:%04xh"
 		" cfg: %02xh)", pdev->vendor, pdev->device, ssp_cfg);
 
@@ -1371,6 +1373,14 @@  static int intel_mid_ssp_spi_probe(struct pci_dev *pdev,
 	drv_data->wq = create_workqueue(DRIVER_NAME);
 	INIT_WORK(&drv_data->resume_transfer_work, resume_transfer_work);
 
+	if (SSP_CFG_IS_SPI_SLAVE(ssp_cfg)) {
+		dev_warn(dev, "Slave clock mode is experimental");
+		drv_data->quirks |= QUIRKS_SPI_SLAVE_CLOCK_MODE;
+		if (drv_data->quirks & QUIRKS_PLATFORM_MRST)
+			drv_data->quirks |= QUIRKS_USE_PM_QOS |
+						QUIRKS_SRAM_ADDITIONAL_CPY;
+	}
+
 	master->mode_bits = SPI_CPOL | SPI_CPHA;
 	master->bus_num = SSP_CFG_GET_SPI_BUS_NB(ssp_cfg);
 	master->num_chipselect = 1;