[linux-yocto] [PATCH 63/87] SPI:pl022:Update driver to support of-platform drivers

Paul Butler butler.paul at gmail.com
Mon May 27 09:56:34 PDT 2013


From: Jiang Lu <lu.jiang at windriver.com>

Since the PPC LSI ACP34xx board implements pl022 spi controller,
Update driver register interface to support ppc of-platform style
driver register interface.

The patch abstract the common code of probe, remove & PM routines
between ARM_AMBA style driver and of-platform driver, then fork
a new drivers for ppc of-platform.

The OF style driver extract device information from device-tree, including
"cell-index", "num-ss-bits", "enalbe-dma" , io address & irq.

Signed-off-by: Jiang Lu <lu.jiang at windriver.com>
---
 drivers/spi/Kconfig     |   2 +-
 drivers/spi/spi-pl022.c | 316 +++++++++++++++++++++++++++++++++++-------------
 2 files changed, 234 insertions(+), 84 deletions(-)

diff --git a/drivers/spi/Kconfig b/drivers/spi/Kconfig
index 00c0240..71a835b 100644
--- a/drivers/spi/Kconfig
+++ b/drivers/spi/Kconfig
@@ -256,7 +256,7 @@ config SPI_ORION
 
 config SPI_PL022
 	tristate "ARM AMBA PL022 SSP controller"
-	depends on ARM_AMBA
+	depends on ARM_AMBA || OF_DEVICE
 	default y if MACH_U300
 	default y if ARCH_REALVIEW
 	default y if INTEGRATOR_IMPD1
diff --git a/drivers/spi/spi-pl022.c b/drivers/spi/spi-pl022.c
index 469eb28..16c58a6 100644
--- a/drivers/spi/spi-pl022.c
+++ b/drivers/spi/spi-pl022.c
@@ -32,7 +32,12 @@
 #include <linux/delay.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#ifdef CONFIG_ARM_AMBA
 #include <linux/amba/bus.h>
+#else
+#include <linux/of_platform.h>
+#include <linux/of.h>
+#endif
 #include <linux/amba/pl022.h>
 #include <linux/io.h>
 #include <linux/slab.h>
@@ -41,6 +46,11 @@
 #include <linux/scatterlist.h>
 #include <linux/pm_runtime.h>
 
+#ifndef CONFIG_ARM_AMBA
+#define writew(b, addr) writel(b, addr)
+#define readw(addr) readl(addr)
+#endif
+
 /*
  * This macro is used to define some register default values.
  * reg is masked with mask, the OR:ed with an (again masked)
@@ -358,7 +368,11 @@ struct vendor_data {
  * @dummypage: a dummy page used for driving data on the bus with DMA
  */
 struct pl022 {
-	struct amba_device		*adev;
+#ifdef CONFIG_ARM_AMBA
+	struct amba_device		*dev;
+#else
+	struct platform_device		*dev;
+#endif
 	struct vendor_data		*vendor;
 	resource_size_t			phybase;
 	void __iomem			*virtbase;
@@ -504,7 +518,7 @@ static int flush(struct pl022 *pl022)
 {
 	unsigned long limit = loops_per_jiffy << 1;
 
-	dev_dbg(&pl022->adev->dev, "flush\n");
+	dev_dbg(&pl022->dev->dev, "flush\n");
 	do {
 		while (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RNE)
 			readw(SSP_DR(pl022->virtbase));
@@ -644,7 +658,7 @@ static void readwriter(struct pl022 *pl022)
 	 * unused RX FIFO fill length, regardless of what the TX
 	 * FIFO status flag indicates.
 	 */
-	dev_dbg(&pl022->adev->dev,
+	dev_dbg(&pl022->dev->dev,
 		"%s, rx: %p, rxend: %p, tx: %p, txend: %p\n",
 		__func__, pl022->rx, pl022->rx_end, pl022->tx, pl022->tx_end);
 
@@ -785,13 +799,13 @@ static void dma_callback(void *data)
 		struct scatterlist *sg;
 		unsigned int i;
 
-		dma_sync_sg_for_cpu(&pl022->adev->dev,
+		dma_sync_sg_for_cpu(&pl022->dev->dev,
 				    pl022->sgt_rx.sgl,
 				    pl022->sgt_rx.nents,
 				    DMA_FROM_DEVICE);
 
 		for_each_sg(pl022->sgt_rx.sgl, sg, pl022->sgt_rx.nents, i) {
-			dev_dbg(&pl022->adev->dev, "SPI RX SG ENTRY: %d", i);
+			dev_dbg(&pl022->dev->dev, "SPI RX SG ENTRY: %d", i);
 			print_hex_dump(KERN_ERR, "SPI RX: ",
 				       DUMP_PREFIX_OFFSET,
 				       16,
@@ -801,7 +815,7 @@ static void dma_callback(void *data)
 				       1);
 		}
 		for_each_sg(pl022->sgt_tx.sgl, sg, pl022->sgt_tx.nents, i) {
-			dev_dbg(&pl022->adev->dev, "SPI TX SG ENTRY: %d", i);
+			dev_dbg(&pl022->dev->dev, "SPI TX SG ENTRY: %d", i);
 			print_hex_dump(KERN_ERR, "SPI TX: ",
 				       DUMP_PREFIX_OFFSET,
 				       16,
@@ -853,7 +867,7 @@ static void setup_dma_scatter(struct pl022 *pl022,
 				    mapbytes, offset_in_page(bufp));
 			bufp += mapbytes;
 			bytesleft -= mapbytes;
-			dev_dbg(&pl022->adev->dev,
+			dev_dbg(&pl022->dev->dev,
 				"set RX/TX target page @ %p, %d bytes, %d left\n",
 				bufp, mapbytes, bytesleft);
 		}
@@ -867,7 +881,7 @@ static void setup_dma_scatter(struct pl022 *pl022,
 			sg_set_page(sg, virt_to_page(pl022->dummypage),
 				    mapbytes, 0);
 			bytesleft -= mapbytes;
-			dev_dbg(&pl022->adev->dev,
+			dev_dbg(&pl022->dev->dev,
 				"set RX/TX to dummy page %d bytes, %d left\n",
 				mapbytes, bytesleft);
 
@@ -996,7 +1010,7 @@ static int configure_dma(struct pl022 *pl022)
 
 	/* Create sglists for the transfers */
 	pages = DIV_ROUND_UP(pl022->cur_transfer->len, PAGE_SIZE);
-	dev_dbg(&pl022->adev->dev, "using %d pages for transfer\n", pages);
+	dev_dbg(&pl022->dev->dev, "using %d pages for transfer\n", pages);
 
 	ret = sg_alloc_table(&pl022->sgt_rx, pages, GFP_ATOMIC);
 	if (ret)
@@ -1085,7 +1099,7 @@ static int __devinit pl022_dma_probe(struct pl022 *pl022)
 					    pl022->master_info->dma_filter,
 					    pl022->master_info->dma_rx_param);
 	if (!pl022->dma_rx_channel) {
-		dev_dbg(&pl022->adev->dev, "no RX DMA channel!\n");
+		dev_dbg(&pl022->dev->dev, "no RX DMA channel!\n");
 		goto err_no_rxchan;
 	}
 
@@ -1093,17 +1107,17 @@ static int __devinit pl022_dma_probe(struct pl022 *pl022)
 					    pl022->master_info->dma_filter,
 					    pl022->master_info->dma_tx_param);
 	if (!pl022->dma_tx_channel) {
-		dev_dbg(&pl022->adev->dev, "no TX DMA channel!\n");
+		dev_dbg(&pl022->dev->dev, "no TX DMA channel!\n");
 		goto err_no_txchan;
 	}
 
 	pl022->dummypage = kmalloc(PAGE_SIZE, GFP_KERNEL);
 	if (!pl022->dummypage) {
-		dev_dbg(&pl022->adev->dev, "no DMA dummypage!\n");
+		dev_dbg(&pl022->dev->dev, "no DMA dummypage!\n");
 		goto err_no_dummypage;
 	}
 
-	dev_info(&pl022->adev->dev, "setup for DMA on RX %s, TX %s\n",
+	dev_info(&pl022->dev->dev, "setup for DMA on RX %s, TX %s\n",
 		 dma_chan_name(pl022->dma_rx_channel),
 		 dma_chan_name(pl022->dma_tx_channel));
 
@@ -1115,7 +1129,7 @@ err_no_txchan:
 	dma_release_channel(pl022->dma_rx_channel);
 	pl022->dma_rx_channel = NULL;
 err_no_rxchan:
-	dev_err(&pl022->adev->dev,
+	dev_err(&pl022->dev->dev,
 			"Failed to work in dma mode, work without dma!\n");
 	return -ENODEV;
 }
@@ -1177,7 +1191,7 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
 	u16 flag = 0;
 
 	if (unlikely(!msg)) {
-		dev_err(&pl022->adev->dev,
+		dev_err(&pl022->dev->dev,
 			"bad message state in interrupt handler");
 		/* Never fail */
 		return IRQ_HANDLED;
@@ -1199,12 +1213,12 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
 		 * Overrun interrupt - bail out since our Data has been
 		 * corrupted
 		 */
-		dev_err(&pl022->adev->dev, "FIFO overrun\n");
+		dev_err(&pl022->dev->dev, "FIFO overrun\n");
 		if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_RFF)
-			dev_err(&pl022->adev->dev,
+			dev_err(&pl022->dev->dev,
 				"RXFIFO is full\n");
 		if (readw(SSP_SR(pl022->virtbase)) & SSP_SR_MASK_TNF)
-			dev_err(&pl022->adev->dev,
+			dev_err(&pl022->dev->dev,
 				"TXFIFO is full\n");
 
 		/*
@@ -1244,7 +1258,7 @@ static irqreturn_t pl022_interrupt_handler(int irq, void *dev_id)
 		       SSP_IMSC(pl022->virtbase));
 		writew(CLEAR_ALL_INTERRUPTS, SSP_ICR(pl022->virtbase));
 		if (unlikely(pl022->rx > pl022->rx_end)) {
-			dev_warn(&pl022->adev->dev, "read %u surplus "
+			dev_warn(&pl022->dev->dev, "read %u surplus "
 				 "bytes (did you request an odd "
 				 "number of bytes on a 16bit bus?)\n",
 				 (u32) (pl022->rx - pl022->rx_end));
@@ -1275,12 +1289,12 @@ static int set_up_next_transfer(struct pl022 *pl022,
 	/* Sanity check the message for this bus width */
 	residue = pl022->cur_transfer->len % pl022->cur_chip->n_bytes;
 	if (unlikely(residue != 0)) {
-		dev_err(&pl022->adev->dev,
+		dev_err(&pl022->dev->dev,
 			"message of %u bytes to transmit but the current "
 			"chip bus has a data width of %u bytes!\n",
 			pl022->cur_transfer->len,
 			pl022->cur_chip->n_bytes);
-		dev_err(&pl022->adev->dev, "skipping this message\n");
+		dev_err(&pl022->dev->dev, "skipping this message\n");
 		return -EIO;
 	}
 	pl022->tx = (void *)transfer->tx_buf;
@@ -1355,7 +1369,7 @@ static void pump_transfers(unsigned long data)
 
 	if (pl022->cur_chip->enable_dma) {
 		if (configure_dma(pl022)) {
-			dev_dbg(&pl022->adev->dev,
+			dev_dbg(&pl022->dev->dev,
 				"configuration of DMA failed, fall back to interrupt mode\n");
 			goto err_config_dma;
 		}
@@ -1390,7 +1404,7 @@ static void do_interrupt_dma_transfer(struct pl022 *pl022)
 	if (pl022->cur_chip->enable_dma) {
 		/* Configure DMA transfer */
 		if (configure_dma(pl022)) {
-			dev_dbg(&pl022->adev->dev,
+			dev_dbg(&pl022->dev->dev,
 				"configuration of DMA failed, fall back to interrupt mode\n");
 			goto err_config_dma;
 		}
@@ -1448,14 +1462,14 @@ static void do_polling_transfer(struct pl022 *pl022)
 		writew((readw(SSP_CR1(pl022->virtbase)) | SSP_CR1_MASK_SSE),
 		       SSP_CR1(pl022->virtbase));
 
-		dev_dbg(&pl022->adev->dev, "polling transfer ongoing ...\n");
+		dev_dbg(&pl022->dev->dev, "polling transfer ongoing ...\n");
 
 		timeout = jiffies + msecs_to_jiffies(SPI_POLLING_TIMEOUT);
 		while (pl022->tx < pl022->tx_end || pl022->rx < pl022->rx_end) {
 			time = jiffies;
 			readwriter(pl022);
 			if (time_after(time, timeout)) {
-				dev_warn(&pl022->adev->dev,
+				dev_warn(&pl022->dev->dev,
 				"%s: timeout!\n", __func__);
 				message->state = STATE_ERROR;
 				goto out;
@@ -1515,7 +1529,7 @@ static int pl022_prepare_transfer_hardware(struct spi_master *master)
 	 * Just make sure we have all we need to run the transfer by syncing
 	 * with the runtime PM framework.
 	 */
-	pm_runtime_get_sync(&pl022->adev->dev);
+	pm_runtime_get_sync(&pl022->dev->dev);
 	return 0;
 }
 
@@ -1528,10 +1542,10 @@ static int pl022_unprepare_transfer_hardware(struct spi_master *master)
 		(~SSP_CR1_MASK_SSE)), SSP_CR1(pl022->virtbase));
 
 	if (pl022->master_info->autosuspend_delay > 0) {
-		pm_runtime_mark_last_busy(&pl022->adev->dev);
-		pm_runtime_put_autosuspend(&pl022->adev->dev);
+		pm_runtime_mark_last_busy(&pl022->dev->dev);
+		pm_runtime_put_autosuspend(&pl022->dev->dev);
 	} else {
-		pm_runtime_put(&pl022->adev->dev);
+		pm_runtime_put(&pl022->dev->dev);
 	}
 
 	return 0;
@@ -1542,27 +1556,27 @@ static int verify_controller_parameters(struct pl022 *pl022,
 {
 	if ((chip_info->iface < SSP_INTERFACE_MOTOROLA_SPI)
 	    || (chip_info->iface > SSP_INTERFACE_UNIDIRECTIONAL)) {
-		dev_err(&pl022->adev->dev,
+		dev_err(&pl022->dev->dev,
 			"interface is configured incorrectly\n");
 		return -EINVAL;
 	}
 	if ((chip_info->iface == SSP_INTERFACE_UNIDIRECTIONAL) &&
 	    (!pl022->vendor->unidir)) {
-		dev_err(&pl022->adev->dev,
+		dev_err(&pl022->dev->dev,
 			"unidirectional mode not supported in this "
 			"hardware version\n");
 		return -EINVAL;
 	}
 	if ((chip_info->hierarchy != SSP_MASTER)
 	    && (chip_info->hierarchy != SSP_SLAVE)) {
-		dev_err(&pl022->adev->dev,
+		dev_err(&pl022->dev->dev,
 			"hierarchy is configured incorrectly\n");
 		return -EINVAL;
 	}
 	if ((chip_info->com_mode != INTERRUPT_TRANSFER)
 	    && (chip_info->com_mode != DMA_TRANSFER)
 	    && (chip_info->com_mode != POLLING_TRANSFER)) {
-		dev_err(&pl022->adev->dev,
+		dev_err(&pl022->dev->dev,
 			"Communication mode is configured incorrectly\n");
 		return -EINVAL;
 	}
@@ -1574,20 +1588,20 @@ static int verify_controller_parameters(struct pl022 *pl022,
 		break;
 	case SSP_RX_16_OR_MORE_ELEM:
 		if (pl022->vendor->fifodepth < 16) {
-			dev_err(&pl022->adev->dev,
+			dev_err(&pl022->dev->dev,
 			"RX FIFO Trigger Level is configured incorrectly\n");
 			return -EINVAL;
 		}
 		break;
 	case SSP_RX_32_OR_MORE_ELEM:
 		if (pl022->vendor->fifodepth < 32) {
-			dev_err(&pl022->adev->dev,
+			dev_err(&pl022->dev->dev,
 			"RX FIFO Trigger Level is configured incorrectly\n");
 			return -EINVAL;
 		}
 		break;
 	default:
-		dev_err(&pl022->adev->dev,
+		dev_err(&pl022->dev->dev,
 			"RX FIFO Trigger Level is configured incorrectly\n");
 		return -EINVAL;
 		break;
@@ -1600,20 +1614,20 @@ static int verify_controller_parameters(struct pl022 *pl022,
 		break;
 	case SSP_TX_16_OR_MORE_EMPTY_LOC:
 		if (pl022->vendor->fifodepth < 16) {
-			dev_err(&pl022->adev->dev,
+			dev_err(&pl022->dev->dev,
 			"TX FIFO Trigger Level is configured incorrectly\n");
 			return -EINVAL;
 		}
 		break;
 	case SSP_TX_32_OR_MORE_EMPTY_LOC:
 		if (pl022->vendor->fifodepth < 32) {
-			dev_err(&pl022->adev->dev,
+			dev_err(&pl022->dev->dev,
 			"TX FIFO Trigger Level is configured incorrectly\n");
 			return -EINVAL;
 		}
 		break;
 	default:
-		dev_err(&pl022->adev->dev,
+		dev_err(&pl022->dev->dev,
 			"TX FIFO Trigger Level is configured incorrectly\n");
 		return -EINVAL;
 		break;
@@ -1621,13 +1635,13 @@ static int verify_controller_parameters(struct pl022 *pl022,
 	if (chip_info->iface == SSP_INTERFACE_NATIONAL_MICROWIRE) {
 		if ((chip_info->ctrl_len < SSP_BITS_4)
 		    || (chip_info->ctrl_len > SSP_BITS_32)) {
-			dev_err(&pl022->adev->dev,
+			dev_err(&pl022->dev->dev,
 				"CTRL LEN is configured incorrectly\n");
 			return -EINVAL;
 		}
 		if ((chip_info->wait_state != SSP_MWIRE_WAIT_ZERO)
 		    && (chip_info->wait_state != SSP_MWIRE_WAIT_ONE)) {
-			dev_err(&pl022->adev->dev,
+			dev_err(&pl022->dev->dev,
 				"Wait State is configured incorrectly\n");
 			return -EINVAL;
 		}
@@ -1637,13 +1651,13 @@ static int verify_controller_parameters(struct pl022 *pl022,
 			     SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
 			    && (chip_info->duplex !=
 				SSP_MICROWIRE_CHANNEL_HALF_DUPLEX)) {
-				dev_err(&pl022->adev->dev,
+				dev_err(&pl022->dev->dev,
 					"Microwire duplex mode is configured incorrectly\n");
 				return -EINVAL;
 			}
 		} else {
 			if (chip_info->duplex != SSP_MICROWIRE_CHANNEL_FULL_DUPLEX)
-				dev_err(&pl022->adev->dev,
+				dev_err(&pl022->dev->dev,
 					"Microwire half duplex mode requested,"
 					" but this is only available in the"
 					" ST version of PL022\n");
@@ -1673,12 +1687,12 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
 	min_tclk = spi_rate(rate, CPSDVR_MAX, SCR_MAX);
 
 	if (freq > max_tclk)
-		dev_warn(&pl022->adev->dev,
+		dev_warn(&pl022->dev->dev,
 			"Max speed that can be programmed is %d Hz, you requested %d\n",
 			max_tclk, freq);
 
 	if (freq < min_tclk) {
-		dev_err(&pl022->adev->dev,
+		dev_err(&pl022->dev->dev,
 			"Requested frequency: %d Hz is less than minimum possible %d Hz\n",
 			freq, min_tclk);
 		return -EINVAL;
@@ -1725,10 +1739,10 @@ static int calculate_effective_freq(struct pl022 *pl022, int freq, struct
 
 	clk_freq->cpsdvsr = (u8) (best_cpsdvsr & 0xFF);
 	clk_freq->scr = (u8) (best_scr & 0xFF);
-	dev_dbg(&pl022->adev->dev,
+	dev_dbg(&pl022->dev->dev,
 		"SSP Target Frequency is: %u, Effective Frequency is %u\n",
 		freq, best_freq);
-	dev_dbg(&pl022->adev->dev, "SSP cpsdvsr = %d, scr = %d\n",
+	dev_dbg(&pl022->dev->dev, "SSP cpsdvsr = %d, scr = %d\n",
 		clk_freq->cpsdvsr, clk_freq->scr);
 
 	return 0;
@@ -1986,19 +2000,19 @@ static void pl022_cleanup(struct spi_device *spi)
 	kfree(chip);
 }
 
-static int __devinit
-pl022_probe(struct amba_device *adev, const struct amba_id *id)
+static int __devinit pl022_probe(
+	struct device *dev,
+	struct vendor_data *vendor,
+	struct resource *res,
+	int irq, struct pl022 **retpl022)
 {
-	struct device *dev = &adev->dev;
-	struct pl022_ssp_controller *platform_info = adev->dev.platform_data;
+	struct pl022_ssp_controller *platform_info = dev->platform_data;
 	struct spi_master *master;
 	struct pl022 *pl022 = NULL;	/*Data for this driver */
 	int status = 0;
 
-	dev_info(&adev->dev,
-		 "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
 	if (platform_info == NULL) {
-		dev_err(&adev->dev, "probe - no platform data supplied\n");
+		dev_err(dev, "probe - no platform data supplied\n");
 		status = -ENODEV;
 		goto err_no_pdata;
 	}
@@ -2006,7 +2020,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	/* Allocate master with space for data */
 	master = spi_alloc_master(dev, sizeof(struct pl022));
 	if (master == NULL) {
-		dev_err(&adev->dev, "probe - cannot alloc SPI master\n");
+		dev_err(dev, "probe - cannot alloc SPI master\n");
 		status = -ENOMEM;
 		goto err_no_master;
 	}
@@ -2014,8 +2028,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	pl022 = spi_master_get_devdata(master);
 	pl022->master = master;
 	pl022->master_info = platform_info;
-	pl022->adev = adev;
-	pl022->vendor = id->data;
+	pl022->vendor = vendor;
 
 	/*
 	 * Bus Number Which has been Assigned to this SSP controller
@@ -2038,37 +2051,37 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	if (pl022->vendor->extended_cr)
 		master->mode_bits |= SPI_LSB_FIRST;
 
-	dev_dbg(&adev->dev, "BUSNO: %d\n", master->bus_num);
+	dev_dbg(dev, "BUSNO: %d\n", master->bus_num);
 
-	status = amba_request_regions(adev, NULL);
-	if (status)
+	if (!request_mem_region(res->start, resource_size(res),
+			dev->driver->name))
 		goto err_no_ioregion;
 
-	pl022->phybase = adev->res.start;
-	pl022->virtbase = ioremap(adev->res.start, resource_size(&adev->res));
+	pl022->phybase = res->start;
+	pl022->virtbase = ioremap(res->start, resource_size(res));
 	if (pl022->virtbase == NULL) {
 		status = -ENOMEM;
 		goto err_no_ioremap;
 	}
-	printk(KERN_INFO "pl022: mapped registers from 0x%08x to %p\n",
-	       adev->res.start, pl022->virtbase);
+	printk(KERN_INFO "pl022: mapped registers from 0x%llx to %p\n",
+	       res->start, pl022->virtbase);
 
-	pl022->clk = clk_get(&adev->dev, NULL);
+	pl022->clk = clk_get(dev, NULL);
 	if (IS_ERR(pl022->clk)) {
 		status = PTR_ERR(pl022->clk);
-		dev_err(&adev->dev, "could not retrieve SSP/SPI bus clock\n");
+		dev_err(dev, "could not retrieve SSP/SPI bus clock\n");
 		goto err_no_clk;
 	}
 
 	status = clk_prepare(pl022->clk);
 	if (status) {
-		dev_err(&adev->dev, "could not prepare SSP/SPI bus clock\n");
+		dev_err(dev, "could not prepare SSP/SPI bus clock\n");
 		goto  err_clk_prep;
 	}
 
 	status = clk_enable(pl022->clk);
 	if (status) {
-		dev_err(&adev->dev, "could not enable SSP/SPI bus clock\n");
+		dev_err(dev, "could not enable SSP/SPI bus clock\n");
 		goto err_no_clk_en;
 	}
 
@@ -2081,10 +2094,10 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	       SSP_CR1(pl022->virtbase));
 	load_ssp_default_config(pl022);
 
-	status = request_irq(adev->irq[0], pl022_interrupt_handler, 0, "pl022",
+	status = request_irq(irq, pl022_interrupt_handler, 0, "pl022",
 			     pl022);
 	if (status < 0) {
-		dev_err(&adev->dev, "probe - cannot get IRQ (%d)\n", status);
+		dev_err(dev, "probe - cannot get IRQ (%d)\n", status);
 		goto err_no_irq;
 	}
 
@@ -2096,18 +2109,21 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	}
 
 	/* Register with the SPI framework */
-	amba_set_drvdata(adev, pl022);
+	dev_set_drvdata(dev, pl022);
 	status = spi_register_master(master);
 	if (status != 0) {
-		dev_err(&adev->dev,
+		dev_err(dev,
 			"probe - problem registering spi master\n");
 		goto err_spi_register;
 	}
 	dev_dbg(dev, "probe succeeded\n");
 
+	if (retpl022)
+		*retpl022 = pl022;
+
 	/* let runtime pm put suspend */
 	if (platform_info->autosuspend_delay > 0) {
-		dev_info(&adev->dev,
+		dev_info(dev,
 			"will use autosuspend for runtime pm, delay %dms\n",
 			platform_info->autosuspend_delay);
 		pm_runtime_set_autosuspend_delay(dev,
@@ -2123,7 +2139,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 	if (platform_info->enable_dma)
 		pl022_dma_remove(pl022);
 
-	free_irq(adev->irq[0], pl022);
+	free_irq(irq, pl022);
  err_no_irq:
 	clk_disable(pl022->clk);
  err_no_clk_en:
@@ -2133,7 +2149,7 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
  err_no_clk:
 	iounmap(pl022->virtbase);
  err_no_ioremap:
-	amba_release_regions(adev);
+	release_mem_region(res->start, resource_size(res));
  err_no_ioregion:
 	spi_master_put(master);
  err_no_master:
@@ -2142,9 +2158,9 @@ pl022_probe(struct amba_device *adev, const struct amba_id *id)
 }
 
 static int __devexit
-pl022_remove(struct amba_device *adev)
+pl022_remove(struct device *dev, struct resource *res, int irq)
 {
-	struct pl022 *pl022 = amba_get_drvdata(adev);
+	struct pl022 *pl022 = dev_get_drvdata(dev);
 
 	if (!pl022)
 		return 0;
@@ -2153,22 +2169,22 @@ pl022_remove(struct amba_device *adev)
 	 * undo pm_runtime_put() in probe.  I assume that we're not
 	 * accessing the primecell here.
 	 */
-	pm_runtime_get_noresume(&adev->dev);
+	pm_runtime_get_noresume(dev);
 
 	load_ssp_default_config(pl022);
 	if (pl022->master_info->enable_dma)
 		pl022_dma_remove(pl022);
 
-	free_irq(adev->irq[0], pl022);
+	free_irq(irq, pl022);
 	clk_disable(pl022->clk);
 	clk_unprepare(pl022->clk);
 	clk_put(pl022->clk);
 	iounmap(pl022->virtbase);
-	amba_release_regions(adev);
+	release_mem_region(res->start, resource_size(res));
 	tasklet_disable(&pl022->pump_transfers);
 	spi_unregister_master(pl022->master);
 	spi_master_put(pl022->master);
-	amba_set_drvdata(adev, NULL);
+	dev_set_drvdata(dev, NULL);
 	return 0;
 }
 
@@ -2238,6 +2254,7 @@ static struct vendor_data vendor_arm = {
 	.loopback = true,
 };
 
+#ifdef CONFIG_ARM_AMBA
 static struct vendor_data vendor_st = {
 	.fifodepth = 32,
 	.max_bpw = 32,
@@ -2265,6 +2282,28 @@ static struct vendor_data vendor_db5500_pl023 = {
 	.loopback = true,
 };
 
+static int __init
+pl022_amba_probe(struct amba_device *adev, struct amba_id *id)
+{
+	struct pl022 *pl022 = NULL;
+	int ret;
+	dev_info(&adev->dev,
+		 "ARM PL022 driver, device ID: 0x%08x\n", adev->periphid);
+	ret = pl022_probe(&adev->dev, id->data,
+		&adev->res, adev->irq[0], &pl022);
+
+	if (ret < 0)
+		return ret;
+	pl022->dev = adev;
+	return 0;
+}
+
+static int __exit
+pl022_amba_remove(struct amba_device *adev)
+{
+	return  pl022_remove(&adev->dev, &adev->res, adev->irq[0]);
+}
+
 static struct amba_id pl022_ids[] = {
 	{
 		/*
@@ -2312,19 +2351,130 @@ static struct amba_driver pl022_driver = {
 		.pm	= &pl022_dev_pm_ops,
 	},
 	.id_table	= pl022_ids,
-	.probe		= pl022_probe,
-	.remove		= __devexit_p(pl022_remove),
+	.probe		= pl022_amba_probe,
+	.remove		= __devexit_p(pl022_amba_remove),
 };
+#else
+static struct of_device_id pl022_match[];
 
+static int __devinit
+pl022_of_probe(struct platform_device *ofdev)
+{
+	struct pl022_ssp_controller *platform_info;
+	int ret = -ENODEV;
+	struct resource r_mem;
+	int irq;
+	struct pl022 *pl022 = NULL;
+	const u32 *prop;
+	int len;
+	struct device_node *of_node = ofdev->dev.of_node;
+	const struct of_device_id *id = of_match_node(pl022_match, of_node);
+	const int *enabled;
+
+	enabled = of_get_property(of_node, "enabled", NULL);
+	if (enabled && !*enabled)
+		return -ENODEV;
+
+	platform_info = kmalloc(sizeof(struct pl022_ssp_controller),
+		GFP_KERNEL);
+	if (!platform_info)
+		return -ENOMEM;
+
+	prop = of_get_property(of_node, "cell-index", &len);
+	if (!prop || len < sizeof(*prop)) {
+		dev_warn(&ofdev->dev, "no 'cell-index' property\n");
+		goto err_data;
+	}
+	platform_info->bus_id = *prop;
+	/* number of slave select bits is required */
+	prop = of_get_property(of_node, "num-ss-bits", &len);
+	if (!prop || len < sizeof(*prop)) {
+		dev_warn(&ofdev->dev, "no 'num-ss-bits' property\n");
+		goto err_data;
+	}
+	platform_info->num_chipselect = *prop;
+	/* number of slave select bits is required */
+	prop = of_get_property(of_node, "enalbe-dma", &len);
+	if (!prop || len < sizeof(*prop))
+		platform_info->enable_dma = 0;
+	platform_info->enable_dma = *prop;
+
+	ofdev->dev.platform_data = platform_info;
+
+	ret = of_address_to_resource(of_node, 0, &r_mem);
+	if (ret) {
+		dev_warn(&ofdev->dev, "invalid address\n");
+		goto err_data;
+	}
+
+	irq = of_irq_to_resource(of_node, 0, NULL);
+
+	ret = pl022_probe(&ofdev->dev, id->data, &r_mem, irq, &pl022);
+
+	if (ret < 0)
+		goto err_data;
+
+	pl022->dev = ofdev;
+	return 0;
+err_data:
+	kfree(platform_info);
+	return ret;
+}
+
+static int __devexit
+pl022_of_remove(struct platform_device *ofdev)
+{
+	struct resource r_mem;
+	int irq;
+	int ret;
+	struct device_node *of_node = ofdev->dev.of_node;
+
+	of_address_to_resource(of_node, 0, &r_mem);
+
+	irq = of_irq_to_resource(of_node, 0, NULL);
+
+	ret = pl022_remove(&ofdev->dev, &r_mem, irq);
+	if (ret)
+		return ret;
+	kfree(ofdev->dev.platform_data);
+	return 0;
+}
+
+static struct of_device_id pl022_match[] = {
+	{
+		.compatible = "acp-ssp",
+		.data = (void *)&vendor_arm,
+	},
+	{ /* end of list */ },
+};
+
+static struct platform_driver pl022_driver = {
+	.driver = {
+		.name	= "ssp-pl022",
+		.pm	= &pl022_dev_pm_ops,
+		.of_match_table = pl022_match,
+	},
+	.probe = pl022_of_probe,
+	.remove = __exit_p(pl022_of_remove),
+};
+#endif
 static int __init pl022_init(void)
 {
+#ifdef CONFIG_ARM_AMBA
 	return amba_driver_register(&pl022_driver);
+#else
+	return platform_driver_register(&pl022_driver);
+#endif
 }
 subsys_initcall(pl022_init);
 
 static void __exit pl022_exit(void)
 {
+#ifdef CONFIG_ARM_AMBA
 	amba_driver_unregister(&pl022_driver);
+#else
+	platform_driver_unregister(&pl022_driver);
+#endif
 }
 module_exit(pl022_exit);
 
-- 
1.8.3




More information about the linux-yocto mailing list