Don't depend on platform_device. Support spi_device

Historically, bmoca only supported platform devices. In struct
moca_priv_data, it stored a pointer to the instance of struct
platform_device that was passed into the probe routine. This pointer was
necessary because bmoca subsequently used data from the platform_data
structure that is linked from the platform_device structure. This data
included fields like chip_id and rf_band.

The problem with this approach was that there is simply no
platform_device for MoCA cores that are connected over SPI like the
BCM6802/BCM6803. Previously, there was a hack where a fake
platform_device was created for those SPI devices, but this hack became
increasingly difficult to maintain.

Let's get rid of this hack. In case of a platform device, copy these
fields like chip_id and rf_band into struct moca_priv_data so that we
no longer need this fake platform device.

Also, add device tree support for SPI devices.

For compatibility with the DesignWare SPI master controller driver in
the new kernel, we had to merge the two SPI transfers into one.

Change-Id: I42070b531d5414f4dfc32dfdf31caa71b5e34492
diff --git a/3.3/bmoca.c b/3.3/bmoca.c
index 266f17f..5ba01e5 100644
--- a/3.3/bmoca.c
+++ b/3.3/bmoca.c
@@ -193,14 +193,17 @@
 };
 
 struct moca_priv_data {
-	struct platform_device	*pdev;
-	struct device		*dev;
+	struct device		*moca_dev; /* platform_device->dev or
+					      spi_device->dev */
+	struct device		*char_dev; /* formerly dev */
 
 	unsigned int		minor;
 	int			irq;
 	struct work_struct	work;
 	void __iomem		*base;
 	void __iomem		*i2c_base;
+	int			bcm3450_i2c_addr;
+	int			use_dma;
 
 	unsigned int		mbx_offset[2]; /* indexed by MoCA cpu */
 	struct page		*fw_pages[MAX_FW_PAGES];
@@ -247,6 +250,13 @@
 	unsigned int		phy_freq;
 
 	unsigned int		hw_rev;
+	char			enet_name[IFNAMSIZ];
+	unsigned int		enet_id;
+	u32			macaddr_hi;
+	u32			macaddr_lo;
+	u32			chip_id;
+	u32			rf_band;
+	int			devId;
 	struct moca_regs	*regs;
 
 	/* MMP Parameters */
@@ -485,6 +495,7 @@
 static u32 moca_3450_read_i2c(struct moca_priv_data *priv, u8 addr);
 static int moca_get_mbx_offset(struct moca_priv_data *priv);
 static u32 moca_irq_status(struct moca_priv_data *priv, int flush);
+static int moca_generic_probe(struct moca_priv_data *priv);
 
 #define INRANGE(x, a, b)	(((x) >= (a)) && ((x) < (b)))
 
@@ -762,10 +773,10 @@
 		return;
 	}
 
-	pa = dma_map_single(&priv->pdev->dev, src, len, DMA_TO_DEVICE);
+	pa = dma_map_single(priv->moca_dev, src, len, DMA_TO_DEVICE);
 	moca_m2m_xfer(priv, dst_offset + priv->regs->data_mem_offset, (u32)pa,
 		len | M2M_WRITE);
-	dma_unmap_single(&priv->pdev->dev, pa, len, DMA_TO_DEVICE);
+	dma_unmap_single(priv->moca_dev, pa, len, DMA_TO_DEVICE);
 }
 
 static void moca_read_mem(struct moca_priv_data *priv,
@@ -791,7 +802,7 @@
 	int j;
 	uintptr_t addr = priv->regs->data_mem_offset + dst_offset;
 
-	dma_map_sg(&priv->pdev->dev, sg, nents, DMA_TO_DEVICE);
+	dma_map_sg(priv->moca_dev, sg, nents, DMA_TO_DEVICE);
 
 	for (j = 0; j < nents; j++) {
 		moca_m2m_xfer(priv, addr, (u32)sg[j].dma_address,
@@ -800,7 +811,7 @@
 		addr += sg[j].length;
 	}
 
-	dma_unmap_sg(&priv->pdev->dev, sg, nents, DMA_TO_DEVICE);
+	dma_unmap_sg(priv->moca_dev, sg, nents, DMA_TO_DEVICE);
 }
 
 static inline void moca_read_sg(struct moca_priv_data *priv,
@@ -809,7 +820,7 @@
 	int j;
 	uintptr_t addr = priv->regs->data_mem_offset + src_offset;
 
-	dma_map_sg(&priv->pdev->dev, sg, nents, DMA_FROM_DEVICE);
+	dma_map_sg(priv->moca_dev, sg, nents, DMA_FROM_DEVICE);
 
 	for (j = 0; j < nents; j++) {
 		moca_m2m_xfer(priv, (u32)sg[j].dma_address, addr,
@@ -819,7 +830,7 @@
 		SetPageDirty(sg_page(&sg[j]));
 	}
 
-	dma_unmap_sg(&priv->pdev->dev, sg, nents, DMA_FROM_DEVICE);
+	dma_unmap_sg(priv->moca_dev, sg, nents, DMA_FROM_DEVICE);
 }
 
 #define moca_3450_write moca_3450_write_i2c
@@ -1583,23 +1594,19 @@
 static irqreturn_t moca_interrupt(int irq, void *arg)
 {
 	struct moca_priv_data *priv = arg;
-	struct moca_platform_data *pd;
 
-	if (!priv || !priv->enabled || !priv->pdev ||
-			!priv->pdev->dev.platform_data) {
+	if (!priv || !priv->enabled) {
 		printk("moca_interrupt: can't go yet.\n");
 		moca_disable_irq(priv);
 		return IRQ_HANDLED;
 	}
 
 #if MOCA6816
-	pd = (struct moca_platform_data *)priv->pdev->dev.platform_data;
-
 	/*
 	 * If the driver is for an external chip then the work function needs
 	 * to run, otherwise a few interrupts can be handled here
 	 */
-	if (0 == pd->use_spi) {
+	if (0) { /* (0 == priv->use_spi) */
 #else
 	if (1) {
 #endif
@@ -1656,10 +1663,9 @@
 static void moca_3450_write_i2c(struct moca_priv_data *priv, u8 addr, u32 data)
 {
 	struct bsc_regs *bsc = priv->i2c_base;
-	struct moca_platform_data *pd = priv->pdev->dev.platform_data;
 
 	I2C_WR(&bsc->iic_enable, 0);
-	I2C_WR(&bsc->chip_address, pd->bcm3450_i2c_addr << 1);
+	I2C_WR(&bsc->chip_address, priv->bcm3450_i2c_addr << 1);
 	I2C_WR(&bsc->data_in[0], (addr >> 2) | (data << 8));
 	I2C_WR(&bsc->data_in[1], data >> 24);
 	I2C_WR(&bsc->cnt_reg, (5 << 0) | (0 << 6));	/* 5B out, 0B in */
@@ -1673,10 +1679,9 @@
 static u32 moca_3450_read_i2c(struct moca_priv_data *priv, u8 addr)
 {
 	struct bsc_regs *bsc = priv->i2c_base;
-	struct moca_platform_data *pd = priv->pdev->dev.platform_data;
 
 	I2C_WR(&bsc->iic_enable, 0);
-	I2C_WR(&bsc->chip_address, pd->bcm3450_i2c_addr << 1);
+	I2C_WR(&bsc->chip_address, priv->bcm3450_i2c_addr << 1);
 	I2C_WR(&bsc->data_in[0], (addr >> 2));
 	I2C_WR(&bsc->cnt_reg, (1 << 0) | (4 << 6));	/* 1B out then 4B in */
 	I2C_WR(&bsc->ctl_reg, (1 << 4) | (3 << 0));	/* write/read, 390kHz */
@@ -1911,7 +1916,6 @@
 	unsigned long arg)
 {
 	struct moca_kdrv_info_v2 info;
-	struct moca_platform_data *pd = priv->pdev->dev.platform_data;
 
 	memset(&info, 0, sizeof(info));
 	info.version = DRV_VERSION;
@@ -1927,13 +1931,14 @@
 		info.gp1 = priv->running ?
 			MOCA_RD(priv->base + priv->regs->gp1_offset) : 0;
 
-	memcpy(info.enet_name, pd->enet_name, MOCA_IFNAMSIZ);
+	strncpy(info.enet_name, priv->enet_name, sizeof(info.enet_name));
+	info.enet_name[sizeof(info.enet_name)-1] = '\0';
 
-	info.enet_id = pd->enet_id;
-	info.macaddr_hi = pd->macaddr_hi;
-	info.macaddr_lo = pd->macaddr_lo;
-	info.hw_rev = pd->chip_id;
-	info.rf_band = pd->rf_band;
+	info.enet_id = priv->enet_id;
+	info.macaddr_hi = priv->macaddr_hi;
+	info.macaddr_lo = priv->macaddr_lo;
+	info.hw_rev = priv->chip_id;
+	info.rf_band = priv->rf_band;
 
 	if (copy_to_user((void *)arg, &info, sizeof(info)))
 		return -EFAULT;
@@ -1945,7 +1950,6 @@
 	unsigned long arg)
 {
 	struct moca_kdrv_info info;
-	struct moca_platform_data *pd = priv->pdev->dev.platform_data;
 
 	memset(&info, 0, sizeof(info));
 	info.version = DRV_VERSION;
@@ -1964,20 +1968,20 @@
 	info.phy_freq = moca_get_phy_freq(priv);
 
 #if MOCA6816
-	info.device_id = (((struct moca_platform_data *)
-		priv->pdev->dev.platform_data)->devId);
-	moca_read_mac_addr(priv, &pd->macaddr_hi,
-		&pd->macaddr_lo);
+	info.device_id = priv->devId;
+	moca_read_mac_addr(priv, &priv->macaddr_hi,
+		&priv->macaddr_lo);
 #endif
 
-	memcpy(info.enet_name, pd->enet_name, MOCA_IFNAMSIZ);
+	strncpy(info.enet_name, priv->enet_name, sizeof(info.enet_name));
+	info.enet_name[sizeof(info.enet_name)-1] = '\0';
 
-	info.enet_id = pd->enet_id;
-	info.macaddr_hi = pd->macaddr_hi;
-	info.macaddr_lo = pd->macaddr_lo;
-	info.chip_id = pd->chip_id;
-	info.hw_rev = pd->hw_rev;
-	info.rf_band = pd->rf_band;
+	info.enet_id = priv->enet_id;
+	info.macaddr_hi = priv->macaddr_hi;
+	info.macaddr_lo = priv->macaddr_lo;
+	info.chip_id = priv->chip_id;
+	info.hw_rev = priv->hw_rev;
+	info.rf_band = priv->rf_band;
 
 	if (copy_to_user((void *)arg, &info, sizeof(info)))
 		return -EFAULT;
@@ -2084,9 +2088,6 @@
 	struct moca_priv_data *priv = file->private_data;
 	struct moca_start	  start;
 	long ret = -ENOTTY;
-#if MOCA6816
-	struct moca_platform_data *pd = priv->pdev->dev.platform_data;
-#endif
 
 	mutex_lock(&priv->dev_mutex);
 
@@ -2099,8 +2100,8 @@
 		 * When MoCA is configured as WAN interface it will
 		 * get a new MAC address
 		 */
-		moca_read_mac_addr(priv, &pd->macaddr_hi,
-			&pd->macaddr_lo);
+		moca_read_mac_addr(priv, &priv->macaddr_hi,
+			&priv->macaddr_lo);
 #endif
 
 		moca_clk_set_rate(priv->phy_clk, DEFAULT_PHY_CLOCK);
@@ -2151,7 +2152,7 @@
 		break;
 	case MOCA_IOCTL_WOL:
 		priv->wol_enabled = (int)arg;
-		dev_info(priv->dev, "WOL is %s\n",
+		dev_info(priv->char_dev, "WOL is %s\n",
 			priv->wol_enabled ? "enabled" : "disabled");
 		ret = 0;
 		break;
@@ -2415,61 +2416,11 @@
 	.poll =			moca_file_poll,
 };
 
-/*
- * PLATFORM DRIVER
- */
+static int moca_generic_probe(struct moca_priv_data *priv) {
+	int minor;
 
-static int moca_probe(struct platform_device *pdev)
-{
-	struct moca_priv_data *priv;
-	struct resource *mres, *ires = NULL;
-	int minor, err = 0;
-	struct moca_platform_data *pd = pdev->dev.platform_data;
-
-	if (pd->use_spi && !pd->spi) {
-		pr_err("moca: use_spi=1, but no bmoca SPI device found.\n");
-		return -EINVAL;
-	}
-
-	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
-	if (!priv) {
-		printk(KERN_ERR "%s: out of memory\n", __func__);
-		return -ENOMEM;
-	}
-	dev_set_drvdata(&pdev->dev, priv);
-	priv->pdev = pdev;
 	priv->start_time = jiffies;
 
-	priv->clk = moca_clk_get(&pdev->dev, "moca");
-
-	priv->cpu_clk = moca_clk_get(&pdev->dev, "moca-cpu");
-	priv->phy_clk = moca_clk_get(&pdev->dev, "moca-phy");
-
-	priv->hw_rev = pd->hw_rev;
-
-#if MOCA6816
-	if ((pd->hw_rev == HWREV_MOCA_20_ALT) ||
-	    (pd->hw_rev == HWREV_MOCA_20_GEN21) ||
-	    (pd->hw_rev == HWREV_MOCA_20_GEN22) ||
-	    (pd->hw_rev == HWREV_MOCA_20_GEN23))
-		priv->regs = &regs_6802;
-	else
-		priv->regs = &regs_6816;
-#else
-	if (pd->hw_rev == HWREV_MOCA_11_PLUS)
-		priv->regs = &regs_11_plus;
-	else if (pd->hw_rev == HWREV_MOCA_11_LITE)
-		priv->regs = &regs_11_lite;
-	else if (pd->hw_rev == HWREV_MOCA_11)
-		priv->regs = &regs_11;
-	else if ((pd->hw_rev == HWREV_MOCA_20_ALT) ||
-		(pd->hw_rev == HWREV_MOCA_20_GEN21) ||
-		(pd->hw_rev == HWREV_MOCA_20_GEN22))
-		priv->regs = &regs_20;
-	else
-		priv->regs = &regs_11_plus;
-#endif
-
 	init_waitqueue_head(&priv->host_msg_wq);
 	init_waitqueue_head(&priv->core_msg_wq);
 	init_completion(&priv->copy_complete);
@@ -2497,9 +2448,84 @@
 	if (priv->minor == -1) {
 		printk(KERN_ERR "%s: can't allocate minor device\n",
 			__func__);
-		err = -EIO;
-		goto bad;
+		return -EIO;
 	}
+	if (hw_specific_init(priv))
+		return -EIO;
+
+	/* leave core in reset until we get an ioctl */
+	//moca_hw_reset(priv); // moca_hw_init(MOCA_ENABLE) does this anyway
+
+	moca_hw_init(priv, MOCA_ENABLE);
+	moca_disable_irq(priv);
+	moca_msg_reset(priv);
+	moca_hw_init(priv, MOCA_DISABLE);
+
+	minor_tbl[priv->minor] = priv;
+	priv->char_dev = device_create(moca_class, NULL,
+		MKDEV(MOCA_MAJOR, priv->minor), NULL, "bmoca%d", priv->minor);
+	if (IS_ERR(priv->char_dev)) {
+		printk(KERN_WARNING "bmoca: can't register class device\n");
+		priv->char_dev = NULL;
+	}
+
+	moca_enable_irq(priv);
+	if (request_irq(priv->irq, moca_interrupt, 0, "moca", priv) < 0) {
+		printk(KERN_WARNING  "%s: can't request interrupt\n",
+			__func__);
+		return -EIO;
+	}
+
+	return 0;
+}
+
+/*
+ * PLATFORM DRIVER
+ */
+#if !MOCA6816
+static int moca_probe(struct platform_device *pdev)
+{
+	struct moca_priv_data *priv;
+	struct resource *mres, *ires = NULL;
+	int err = 0;
+	struct moca_platform_data *pd = pdev->dev.platform_data;
+
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		printk(KERN_ERR "%s: out of memory\n", __func__);
+		return -ENOMEM;
+	}
+	priv->moca_dev = &pdev->dev;
+	dev_set_drvdata(priv->moca_dev, priv);
+
+	priv->clk = moca_clk_get(priv->moca_dev, "moca");
+
+	priv->cpu_clk = moca_clk_get(priv->moca_dev, "moca-cpu");
+	priv->phy_clk = moca_clk_get(priv->moca_dev, "moca-phy");
+
+	priv->hw_rev = pd->hw_rev;
+	strncpy(priv->enet_name, pd->enet_name, sizeof(priv->enet_name));
+	priv->enet_name[sizeof(priv->enet_name)-1] = '\0';
+	priv->enet_id = pd->enet_id;
+	priv->macaddr_hi = pd->macaddr_hi;
+	priv->macaddr_lo = pd->macaddr_lo;
+	priv->chip_id = pd->chip_id;
+	priv->rf_band = pd->rf_band;
+	priv->use_dma = pd->use_dma;
+	priv->devId = pd->devId;
+
+	if (pd->hw_rev == HWREV_MOCA_11_PLUS)
+		priv->regs = &regs_11_plus;
+	else if (pd->hw_rev == HWREV_MOCA_11_LITE)
+		priv->regs = &regs_11_lite;
+	else if (pd->hw_rev == HWREV_MOCA_11)
+		priv->regs = &regs_11;
+	else if ((pd->hw_rev == HWREV_MOCA_20_ALT) ||
+		(pd->hw_rev == HWREV_MOCA_20_GEN21) ||
+		(pd->hw_rev == HWREV_MOCA_20_GEN22))
+		priv->regs = &regs_20;
+	else
+		priv->regs = &regs_11_plus;
 
 	mres = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	ires = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
@@ -2510,77 +2536,44 @@
 		goto bad;
 	}
 
-#if defined(CONFIG_BCM_6802_MoCA)
-	priv->base = (void *)mres->start;
-	priv->irq = pd->spi->irq;
-	priv->i2c_base = (void *)pd->bcm3450_i2c_base;
-#else
 	priv->base = ioremap(mres->start, mres->end - mres->start + 1);
 	priv->irq = ires->start;
 	priv->i2c_base = ioremap(pd->bcm3450_i2c_base, sizeof(struct bsc_regs));
-#endif
 
-#if MOCA6816
-	moca_read_mac_addr(priv, &pd->macaddr_hi, &pd->macaddr_lo);
-#endif
-	if (hw_specific_init(priv))
-		goto bad;
-
-	/* leave core in reset until we get an ioctl */
-	//moca_hw_reset(priv); // moca_hw_init(MOCA_ENABLE) does this anyway
-
-	moca_hw_init(priv, MOCA_ENABLE);
-	moca_disable_irq(priv);
-	moca_msg_reset(priv);
-	moca_hw_init(priv, MOCA_DISABLE);
+	priv->bcm3450_i2c_addr = pd->bcm3450_i2c_addr;
 
 	printk(KERN_INFO "bmoca: adding minor #%d at base 0x%08llx, IRQ %d, "
 		"I2C 0x%08llx/0x%02x\n", priv->minor,
 		(unsigned long long)mres->start, priv->irq,
-		(unsigned long long)pd->bcm3450_i2c_base, pd->bcm3450_i2c_addr);
+		(unsigned long long)pd->bcm3450_i2c_base, priv->bcm3450_i2c_addr);
 
-	minor_tbl[priv->minor] = priv;
-	priv->dev = device_create(moca_class, NULL,
-		MKDEV(MOCA_MAJOR, priv->minor), NULL, "bmoca%d", priv->minor);
-	if (IS_ERR(priv->dev)) {
-		printk(KERN_WARNING "bmoca: can't register class device\n");
-		priv->dev = NULL;
-	}
 
-	moca_enable_irq(priv);
-	if (request_irq(priv->irq, moca_interrupt, 0, "moca", priv) < 0) {
-		printk(KERN_WARNING  "%s: can't request interrupt\n",
-			__func__);
-		err = -EIO;
+	if ((err = moca_generic_probe(priv))) {
 		goto bad2;
 	}
 
-	if (err)
-		goto bad2;
-
 	return 0;
 
 bad2:
-	if (!pd->use_spi) {
-		if (priv->base)
-			iounmap(priv->base);
-		if (priv->i2c_base)
-			iounmap(priv->i2c_base);
-	}
+	if (priv->base)
+		iounmap(priv->base);
+	if (priv->i2c_base)
+		iounmap(priv->i2c_base);
 bad:
 	kfree(priv);
 	return err;
 }
+#endif
 
+#if !MOCA6816
 static int moca_remove(struct platform_device *pdev)
 {
 	struct moca_priv_data *priv = dev_get_drvdata(&pdev->dev);
-	struct moca_platform_data *pd = pdev->dev.platform_data;
 	struct clk *clk = priv->clk;
 	struct clk *phy_clk = priv->phy_clk;
 	struct clk *cpu_clk = priv->cpu_clk;
 
-	if (priv->dev)
+	if (priv->char_dev)
 		device_destroy(moca_class, MKDEV(MOCA_MAJOR, priv->minor));
 	minor_tbl[priv->minor] = NULL;
 
@@ -2588,10 +2581,9 @@
 	if (priv->irq)
 		free_irq(priv->irq, priv);
 
-	if (!pd->use_spi) {
-		iounmap(priv->i2c_base);
-		iounmap(priv->base);
-	}
+	iounmap(priv->i2c_base);
+	iounmap(priv->base);
+
 	kfree(priv);
 
 	moca_clk_put(clk);
@@ -2600,6 +2592,7 @@
 
 	return 0;
 }
+#endif
 
 #ifdef CONFIG_PM
 static int moca_suspend(struct device *dev)
@@ -2621,6 +2614,7 @@
 
 #endif
 
+#if !MOCA6816
 static struct platform_driver moca_plat_drv = {
 	.probe =		moca_probe,
 	.remove =		moca_remove,
@@ -2632,6 +2626,7 @@
 #endif
 	},
 };
+#endif
 
 static int moca_init(void)
 {
@@ -2651,26 +2646,22 @@
 	}
 
 #if MOCA6816
-	ret = moca_platform_dev_register();
-
+	ret = spi_driver_register();
 	if (ret < 0) {
-		printk(KERN_ERR "bmoca: can't register platform_device\n");
+		printk(KERN_ERR "bmoca: can't register spi_driver\n");
 		goto bad3;
 	}
-#endif
-
+#else
 	ret = platform_driver_register(&moca_plat_drv);
 	if (ret < 0) {
 		printk(KERN_ERR "bmoca: can't register platform_driver\n");
 		goto bad3;
 	}
+#endif
 
 	return 0;
 
 bad3:
-#if MOCA6816
-	moca_platform_dev_unregister();
-#endif
 	class_destroy(moca_class);
 bad2:
 	unregister_chrdev(MOCA_MAJOR, MOCA_CLASS);
@@ -2681,9 +2672,10 @@
 static void moca_exit(void)
 {
 	unregister_chrdev(MOCA_MAJOR, MOCA_CLASS);
-	platform_driver_unregister(&moca_plat_drv);
 #if MOCA6816
-	moca_platform_dev_unregister();
+	spi_driver_unregister();
+#else
+	platform_driver_unregister(&moca_plat_drv);
 #endif
 	class_destroy(moca_class);
 }
diff --git a/bbsi.h b/bbsi.h
index afd051f..976d785 100644
--- a/bbsi.h
+++ b/bbsi.h
@@ -58,7 +58,7 @@
 	enum bbsi_operation_state state;
 	struct spi_device *spi;
 	struct spi_message sm;
-	struct spi_transfer st[2];
+	struct spi_transfer st;
 	/* address on MoCA chip we want to read from/write to */
 	uint32_t addr;
 	/* len must be a multiple of 4 */
@@ -66,8 +66,9 @@
 	uint8_t *data;
 	/* number of bytes already read or written. data_len <= len */
 	size_t data_len;
-	uint8_t tx_buf[8];
-	uint8_t rx_buf[SPI_FIFO_LEN - 2];
+	uint8_t tx_buf[SPI_FIFO_LEN-1];
+	uint8_t rx_buf[SPI_FIFO_LEN-1];
+	uint8_t *rx_data;
 	/* See interpret_data() for a definition of rx_state */
 	int rx_state;
 	struct completion done;
@@ -91,6 +92,7 @@
 	BP_MOCA_RF_BAND_F,
 };
 
+#if 0
 typedef struct BpMocaInfo {
 	int type;
 	int rfBand;
@@ -103,6 +105,7 @@
 		chips[0].rfBand = BP_MOCA_RF_BAND_E;
 	}
 }
+#endif
 
 // TODO(apenwarr): don't make this global.
 //   Or fix the driver to just only enable/disable interrupts at the right
@@ -141,8 +144,8 @@
 	t->tx_buf[2] = READ_RBUS |
 		(burst ? SPECULATIVE_READ_EN : NO_RBUS_ADDR_INC);
 	writel(cpu_to_be32(t->addr), t->tx_buf + 3);
-	t->st[0] = ((struct spi_transfer) { .tx_buf = t->tx_buf, .len = 7 });
-	spi_message_add_tail(&t->st[0], &t->sm);
+	t->st = ((struct spi_transfer) { .tx_buf = t->tx_buf, .len = 7 });
+	spi_message_add_tail(&t->st, &t->sm);
 	ret = spi_async_locked(t->spi, &t->sm);
 	if (ret) {
 		pr_err("%s: spi_async failed with %d\n", __func__, ret);
@@ -160,8 +163,8 @@
 	t->tx_buf[1] = CONFIG_REGISTER_ADDR;
 	t->tx_buf[2] = 0;
 	writel(cpu_to_be32(t->addr), t->tx_buf + 3);
-	t->st[0] = ((struct spi_transfer) { .tx_buf = t->tx_buf, .len = 7 });
-	spi_message_add_tail(&t->st[0], &t->sm);
+	t->st = ((struct spi_transfer) { .tx_buf = t->tx_buf, .len = 7 });
+	spi_message_add_tail(&t->st, &t->sm);
 	ret = spi_async_locked(t->spi, &t->sm);
 	if (ret) {
 		pr_err("%s: spi_async failed with %d\n", __func__, ret);
@@ -177,10 +180,10 @@
 	t->sm.context = t;
 	t->tx_buf[0] = BBSI_COMMAND_BYTE;
 	t->tx_buf[1] = STATUS_REGISTER_ADDR;
-	t->st[0] = ((struct spi_transfer) { .tx_buf = t->tx_buf, .len = 2 });
-	t->st[1] = ((struct spi_transfer) { .rx_buf = t->rx_buf, .len = 1 });
-	spi_message_add_tail(&t->st[0], &t->sm);
-	spi_message_add_tail(&t->st[1], &t->sm);
+	t->tx_buf[2] = 0;
+	t->rx_data = t->rx_buf + 2;
+	t->st = ((struct spi_transfer) { .tx_buf = t->tx_buf, .rx_buf = t->rx_buf, .len = 3 });
+	spi_message_add_tail(&t->st, &t->sm);
 	ret = spi_async_locked(t->spi, &t->sm);
 	if (ret) {
 		pr_err("%s: spi_async failed with %d\n", __func__, ret);
@@ -194,6 +197,7 @@
 	spi_message_init(&t->sm);
 	t->sm.complete = state_machine_read;
 	t->sm.context = t;
+	memset(t->tx_buf, 0, sizeof(t->tx_buf));
 	t->tx_buf[0] = BBSI_COMMAND_BYTE;
 	/* We want to continue reading where we left off. See interpret_data()
 	 * for the definition of t->rx_state */
@@ -202,11 +206,9 @@
 	} else {
 		t->tx_buf[1] = DATA0_REGISTER_ADDR + t->rx_state - 1;
 	}
-	t->st[0] = ((struct spi_transfer) { .tx_buf = t->tx_buf, .len = 2 });
-	t->st[1] = ((struct spi_transfer) { .rx_buf = t->rx_buf,
-			.len = sizeof(t->rx_buf)});
-	spi_message_add_tail(&t->st[0], &t->sm);
-	spi_message_add_tail(&t->st[1], &t->sm);
+	t->rx_data = t->rx_buf + 2;
+	t->st = ((struct spi_transfer) { .tx_buf = t->tx_buf, .rx_buf = t->rx_buf, .len = sizeof(t->rx_buf)});
+	spi_message_add_tail(&t->st, &t->sm);
 	ret = spi_async_locked(t->spi, &t->sm);
 	if (ret) {
 		pr_err("%s: spi_async failed with %d\n", __func__, ret);
@@ -218,17 +220,15 @@
 static int write_data(struct bbsi_operation *t) {
 	int ret;
 	size_t len;
-	len = min(t->len - t->data_len, sizeof(t->rx_buf));
+	len = min(t->len - t->data_len, sizeof(t->tx_buf)-2);
 	spi_message_init(&t->sm);
 	t->sm.complete = state_machine_write;
 	t->sm.context = t;
 	t->tx_buf[0] = BBSI_COMMAND_BYTE | 0x01;
 	t->tx_buf[1] = DATA0_REGISTER_ADDR + (t->data_len & 3);
-	t->st[0] = ((struct spi_transfer) { .tx_buf = t->tx_buf, .len = 2 });
-	t->st[1] = ((struct spi_transfer) { .tx_buf = t->data + t->data_len,
-			.len = len});
-	spi_message_add_tail(&t->st[0], &t->sm);
-	spi_message_add_tail(&t->st[1], &t->sm);
+	memcpy(&t->tx_buf[2], t->data + t->data_len, len);
+	t->st = ((struct spi_transfer) { .tx_buf = t->tx_buf, .len = 2 + len});
+	spi_message_add_tail(&t->st, &t->sm);
 	ret = spi_async_locked(t->spi, &t->sm);
 	if (ret) {
 		pr_err("%s: spi_async failed with %d\n", __func__, ret);
@@ -258,8 +258,7 @@
 	 * stands for STATUS, 1 stands for DATA0, 2 for DATA1 and so on.
 	*/
 	uint8_t *r;
-	r = t->rx_buf;
-	for(r = t->rx_buf;r < t->rx_buf + sizeof(t->rx_buf);r++) {
+	for(r = t->rx_data;r < t->rx_buf + sizeof(t->rx_buf);r++) {
 		if (t->rx_state == 0) {
 			if (*r & STATUS_BUSY)
 				/* t->rx_state stays at 0 because the next byte
@@ -376,14 +375,14 @@
 				bbsi_op_fail(t);
 				return;
 			}
-			if (*t->rx_buf & STATUS_BUSY) {
+			if (*t->rx_data & STATUS_BUSY) {
 				/* Stay in this state */
 				ret = send_pollstatuscmd(t, state_machine_write);
 				if (ret) return;
-			} else if (*t->rx_buf) {
+			} else if (*t->rx_data) {
 				pr_err("rbus error 0x%02x while trying to write %u "
 						"bytes to 0x%08x\n",
-						(unsigned) *t->rx_buf, t->len, t->addr);
+						(unsigned) *t->rx_data, t->len, t->addr);
 				bbsi_op_fail(t);
 			} else {
 				t->state = DONE;
diff --git a/bmoca-6802.c b/bmoca-6802.c
index f641fa8..a65b016 100644
--- a/bmoca-6802.c
+++ b/bmoca-6802.c
@@ -29,6 +29,10 @@
 */
 
 #include "bbsi.h"
+#include <linux/of.h>
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
+#include <linux/gpio/consumer.h>
+#endif
 #include <linux/spi/spi.h>
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
@@ -36,29 +40,12 @@
 typedef unsigned long uintptr_t;
 #endif // LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,30)
 
-#define MOCA_RD(x)    ((((struct moca_platform_data *)priv->pdev->dev.platform_data)->use_spi == 0) ? \
-                       (*((volatile uint32_t *)((unsigned long)(x)))) : \
-                       ((uint32_t)kerSysBcmSpiSlaveReadReg32(((struct moca_platform_data *)priv->pdev->dev.platform_data)->spi, (uint32_t)(x))))
+#define MOCA_RD(x)	(kerSysBcmSpiSlaveReadReg32(to_spi_device(priv->moca_dev), (uint32_t)(x)))
 
-#define MOCA_RD8(x, y) ((((struct moca_platform_data *)priv->pdev->dev.platform_data)->use_spi == 0) ? \
-                        (*(y) = *((volatile unsigned char *)((unsigned long)(x)))) : \
-                        (kerSysBcmSpiSlaveRead(((struct moca_platform_data *)priv->pdev->dev.platform_data)->spi, (unsigned long)(x), y, 1)))
+#define MOCA_WR(x,y)	do { kerSysBcmSpiSlaveWriteReg32(to_spi_device(priv->moca_dev), (uint32_t)(x), (y)); } while(0)
 
-#define MOCA_WR(x,y)   do { ((((struct moca_platform_data *)priv->pdev->dev.platform_data)->use_spi == 0) ? \
-                            (*((volatile uint32_t *)((unsigned long)(x)))) = (y) : \
-                            kerSysBcmSpiSlaveWriteReg32(((struct moca_platform_data *)priv->pdev->dev.platform_data)->spi, (uint32_t)(x), (y))); } while(0)
-
-#define MOCA_WR8(x,y)    do { ((((struct moca_platform_data *)priv->pdev->dev.platform_data)->use_spi == 0) ? \
-                               (*((volatile unsigned char *)((unsigned long)(x)))) = (unsigned char)(y) : \
-                               kerSysBcmSpiSlaveWrite(((struct moca_platform_data *)priv->pdev->dev.platform_data)->spi, (unsigned long)(x), (y), 1)); } while(0)
-
-#define MOCA_WR16(x,y)   do { ((((struct moca_platform_data *)priv->pdev->dev.platform_data)->use_spi == 0) ? \
-                               (*((volatile unsigned short *)((unsigned long)(x)))) = (unsigned short)(y) : \
-                               kerSysBcmSpiSlaveWrite(((struct moca_platform_data *)priv->pdev->dev.platform_data)->spi, (unsigned long)(x), (y), 2)); } while(0)
-
-#define MOCA_WR_BLOCK(addr, src, len) do { kerSysBcmSpiSlaveWriteBuf(((struct moca_platform_data *)priv->pdev->dev.platform_data)->spi, addr, src, len, 4); } while(0)
-#define MOCA_RD_BLOCK(addr, dst, len) do { kerSysBcmSpiSlaveReadBuf(((struct moca_platform_data *)priv->pdev->dev.platform_data)->spi, addr, dst, len, 4); } while(0)
-
+#define MOCA_WR_BLOCK(addr, src, len) do { kerSysBcmSpiSlaveWriteBuf(to_spi_device(priv->moca_dev), addr, src, len, 4); } while(0)
+#define MOCA_RD_BLOCK(addr, dst, len) do { kerSysBcmSpiSlaveReadBuf(to_spi_device(priv->moca_dev), addr, dst, len, 4); } while(0)
 
 #define I2C_RD(x)		MOCA_RD(x)
 #define I2C_WR(x, y)		MOCA_WR(x, y)
@@ -98,95 +85,6 @@
 static uint32_t zone_phy1_bitmask[MOCA_BPCM_NUM]  = { 0x00, 0x00, 0x00, 0x00, 0xFF };
 
 
-static void bogus_release(struct device *dev)
-{
-}
-
-static struct moca_platform_data moca_lan_data = {
-	.macaddr_hi =		0x00000102,
-	.macaddr_lo =		0x03040000,
-
-	.bcm3450_i2c_base =  0x10406200,
-	.bcm3450_i2c_addr =  0x70,
-	.hw_rev  =     HWREV_MOCA_20_GEN22,
-	.rf_band =     MOCA_BAND_EXT_D,
-	.chip_id =     0,
-	.use_dma           = 0,
-	.use_spi           = 1,
-	.devId            = MOCA_DEVICE_ID_UNREGISTERED, // Filled in dynamically
-#ifdef CONFIG_SMP
-	.smp_processor_id = 1,
-#endif
-};
-
-static struct resource moca_lan_resources[] = {
-	[0] = {
-		.start = 0x10600000,
-		.end =   0x107ffd97,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = { /* Not used for 6802, define for bmoca */
-		.start = 0,
-		.end = 0,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct platform_device moca_lan_plat_dev = {
-	.name = "bmoca",
-	.id = 0,
-	.num_resources = ARRAY_SIZE(moca_lan_resources),
-	.resource = moca_lan_resources,
-	.dev = {
-		.platform_data = &moca_lan_data,
-		.release = bogus_release,
-	},
-};
-
-static struct moca_platform_data moca_wan_data = {
-	.macaddr_hi       = 0x00000102,
-	.macaddr_lo       = 0x03040000,
-
-	.bcm3450_i2c_base =  0x10406200,
-	.bcm3450_i2c_addr =  0x70,
-	.hw_rev  = HWREV_MOCA_20_GEN22,
-	.chip_id = 0,
-	
-	.rf_band = MOCA_BAND_EXT_D,
-
-	.use_dma           = 0,
-	.use_spi           = 1,
-	.devId            = MOCA_DEVICE_ID_UNREGISTERED, // Filled in dynamically
-
-#ifdef CONFIG_SMP
-	.smp_processor_id = 1,
-#endif
-};
-
-static struct resource moca_wan_resources[] = {
-	[0] = {
-		.start = 0x10600000,
-		.end =   0x107ffd97,
-		.flags = IORESOURCE_MEM,
-	},
-	[1] = { /* Not used for 6802, define for bmoca */
-		.start = 0,
-		.end = 0,
-		.flags = IORESOURCE_IRQ,
-	}
-};
-
-static struct platform_device moca_wan_plat_dev = {
-	.name          = "bmoca",
-	.id            = 1,
-	.num_resources = ARRAY_SIZE(moca_wan_resources),
-	.resource      = moca_wan_resources,
-	.dev           = {
-		.platform_data = &moca_wan_data,
-		.release       = bogus_release,
-	},
-};
-
 /* MoCA Clock Functions */
 struct clk *moca_clk_get(struct device *dev, const char *id)
 {
@@ -250,24 +148,17 @@
 
 int moca_clk_set_rate(struct clk *clk, unsigned long rate)
 {
-	// The MOCA_RD/MOCA_WR macros need a valid 'priv->pdev->dev'
-	static struct moca_priv_data dummy_priv; 
-	static struct platform_device dummy_pd;
-	struct moca_priv_data *priv = &dummy_priv;
 	struct moca_680x_clk * pclk = (struct moca_680x_clk *) clk;
-	struct moca_platform_data * pMocaData = (struct moca_platform_data *)pclk->dev->platform_data;
+	struct moca_priv_data *priv = dev_get_drvdata(pclk->dev);
 	struct moca_6802c0_clock_params * p_clock_data = &moca_6802c0_clock_params[0];
 	uint32_t i;
 	uint32_t addr;
 	uint32_t data;
 	int ret = -1;
 
-	priv->pdev = &dummy_pd;
-	priv->pdev->dev = *pclk->dev;
-
 	if (pclk->clock_num == MOCA_CPU_CLOCK_NUM)
 	{
-		if ((pMocaData->chip_id & 0xFFFFFFF0) == 0x680200C0)
+		if ((priv->chip_id & 0xFFFFFFF0) == 0x680200C0)
 		{
 			if (rate == 0)
 			{
@@ -337,12 +228,12 @@
 
 static void moca_enable_irq(struct moca_priv_data *priv)
 {
-	kerSysMocaHostIntrEnable(((struct moca_platform_data *)priv->pdev->dev.platform_data)->spi);
+	kerSysMocaHostIntrEnable(to_spi_device(priv->moca_dev));
 }
 
 static void moca_disable_irq(struct moca_priv_data *priv)
 {
-	kerSysMocaHostIntrDisable(((struct moca_platform_data *)priv->pdev->dev.platform_data)->spi);
+	kerSysMocaHostIntrDisable(to_spi_device(priv->moca_dev));
 }
 
 static void moca_pmb_busy_wait(struct moca_priv_data *priv)
@@ -539,7 +430,6 @@
 
 static void moca_gphy_init(struct moca_priv_data *priv)
 {
-	struct moca_platform_data * pMocaData = (struct moca_platform_data *)priv->pdev->dev.platform_data;
 	u32 port_mode;
 	u32 rgmii0_on;
 	u32 rgmii1_on;
@@ -549,7 +439,7 @@
 	rgmii0_on = MOCA_RD(0x1080000c) & 0x1;
 	rgmii1_on = MOCA_RD(0x10800018) & 0x1;
 
-	if ((pMocaData->chip_id & 0xFFFEFFF0) == 0x680200C0)
+	if ((priv->chip_id & 0xFFFEFFF0) == 0x680200C0)
 	{
 		if ((port_mode == 0) ||
 		    ((port_mode == 1) && rgmii0_on) ||
@@ -582,7 +472,6 @@
 	u32 temp;
 	u32 data;
 	u32 count = 0;
-	struct moca_platform_data * pMocaData = (struct moca_platform_data *)priv->pdev->dev.platform_data;
 
 	if (action == MOCA_ENABLE && !priv->enabled) {
 		moca_clk_enable(priv->clk);
@@ -650,7 +539,7 @@
 		moca_pmb_give_cntrl(priv, PMB_GIVE_OWNERSHIP_2_FW);
 			
 		/* Check for 6802/6803 A0 chip only with Xtal mod */
-		if ((pMocaData->chip_id & 0xFFFEFFFF) == 0x680200A0)
+		if ((priv->chip_id & 0xFFFEFFFF) == 0x680200A0)
 		{
 			data = MOCA_RD(0x1040401c);
 			if ((data & 0x7) == 0x2) {
@@ -740,8 +629,8 @@
 	MOCA_SET(0x10404110, 0x10000022);
  
 	/* Set pinmuxing for MoCA IIC control */
-	if (((pMocaData->chip_id & 0xFFFFFFF0) == 0x680200C0) || 
-	    ((pMocaData->chip_id & 0xFFFFFFF0) == 0x680300C0))
+	if (((priv->chip_id & 0xFFFFFFF0) == 0x680200C0) ||
+	    ((priv->chip_id & 0xFFFFFFF0) == 0x680300C0))
 	{
 		MOCA_UNSET(0x10404100, 0xFF);  // pin muxing
 		MOCA_SET(0x10404100, 0x22);  // pin muxing
@@ -798,8 +687,6 @@
 static void moca_write_mem(struct moca_priv_data *priv,
 	uint32_t dst_offset, void *src, unsigned int len)
 {
-	struct moca_platform_data *pd = priv->pdev->dev.platform_data;
-
 	if((dst_offset >= priv->regs->cntl_mem_offset+priv->regs->cntl_mem_size) ||
 		((dst_offset + len) > priv->regs->cntl_mem_offset+priv->regs->cntl_mem_size)) {
 		printk(KERN_WARNING "%s: copy past end of cntl memory: %08x\n",
@@ -807,15 +694,15 @@
 		return;
 	}
 
-	if ( 1 == pd->use_dma )
+	if ( 1 == priv->use_dma )
 	{
 		dma_addr_t pa;
 
-		pa = dma_map_single(&priv->pdev->dev, src, len, DMA_TO_DEVICE);
+		pa = dma_map_single(priv->moca_dev, src, len, DMA_TO_DEVICE);
 		mutex_lock(&priv->copy_mutex);
 		moca_m2m_xfer(priv, dst_offset + priv->regs->data_mem_offset, (uint32_t)pa, len | M2M_WRITE);
 		mutex_unlock(&priv->copy_mutex);
-		dma_unmap_single(&priv->pdev->dev, pa, len, DMA_TO_DEVICE);
+		dma_unmap_single(priv->moca_dev, pa, len, DMA_TO_DEVICE);
 	}
 	else
 	{
@@ -824,7 +711,7 @@
 		int i;
 
 		mutex_lock(&priv->copy_mutex);
-		if (((struct moca_platform_data *)priv->pdev->dev.platform_data)->use_spi == 1)
+		if (1) /* (priv->use_spi == 1) */
 		{
 			src = data;
 			MOCA_WR_BLOCK(addr, src, len);
@@ -843,8 +730,6 @@
 static void moca_read_mem(struct moca_priv_data *priv,
 	void *dst, uint32_t src_offset, unsigned int len)
 {
-	struct moca_platform_data *pd = priv->pdev->dev.platform_data;
-    
 	if((src_offset >= priv->regs->cntl_mem_offset+priv->regs->cntl_mem_size) ||
 		((src_offset + len) > priv->regs->cntl_mem_offset+priv->regs->cntl_mem_size)) {
 		printk(KERN_WARNING "%s: copy past end of cntl memory: %08x\n",
@@ -852,15 +737,15 @@
 		return;
 	}
 
-	if ( 1 == pd->use_dma )
+	if ( 1 == priv->use_dma )
 	{
 		dma_addr_t pa;
 
-		pa = dma_map_single(&priv->pdev->dev, dst, len, DMA_FROM_DEVICE);
+		pa = dma_map_single(priv->moca_dev, dst, len, DMA_FROM_DEVICE);
 		mutex_lock(&priv->copy_mutex);
 		moca_m2m_xfer(priv, (uint32_t)pa, src_offset + priv->regs->data_mem_offset, len | M2M_READ);
 		mutex_unlock(&priv->copy_mutex);
-		dma_unmap_single(&priv->pdev->dev, pa, len, DMA_FROM_DEVICE);
+		dma_unmap_single(priv->moca_dev, pa, len, DMA_FROM_DEVICE);
 	}
 	else
 	{
@@ -869,7 +754,7 @@
 		int i;
 
 		mutex_lock(&priv->copy_mutex);
-		if (((struct moca_platform_data *)priv->pdev->dev.platform_data)->use_spi == 1)
+		if (1) /* (priv->use_spi == 1) */
 		{
 			MOCA_RD_BLOCK((uintptr_t)priv->base + addr, dst, len);
 		}
@@ -887,14 +772,13 @@
 {
 	int j;
 	uintptr_t addr = priv->regs->data_mem_offset + dst_offset;
-	struct moca_platform_data *pd = priv->pdev->dev.platform_data;
 
-	dma_map_sg(&priv->pdev->dev, sg, nents, DMA_TO_DEVICE);
+	dma_map_sg(priv->moca_dev, sg, nents, DMA_TO_DEVICE);
 
 	mutex_lock(&priv->copy_mutex);
 	for(j = 0; j < nents; j++)
 	{
-		if ( 1 == pd->use_dma )
+		if ( 1 == priv->use_dma )
 		{
 		    // printk("XXX copying page %d, PA %08x\n", j, (int)sg[j].dma_address);
 			moca_m2m_xfer(priv, addr, (uint32_t)sg[j].dma_address, 
@@ -912,7 +796,7 @@
 	}
 	mutex_unlock(&priv->copy_mutex);
 
-	dma_unmap_sg(&priv->pdev->dev, sg, nents, DMA_TO_DEVICE);
+	dma_unmap_sg(priv->moca_dev, sg, nents, DMA_TO_DEVICE);
 }
 
 /* NOTE: this function is not tested */
@@ -923,7 +807,7 @@
 	int j;
 	uintptr_t addr = priv->data_mem_offset + src_offset;
 
-	dma_map_sg(&priv->pdev->dev, sg, nents, DMA_FROM_DEVICE);
+	dma_map_sg(priv->moca_dev, sg, nents, DMA_FROM_DEVICE);
 
 	mutex_lock(&priv->copy_mutex);
 	for(j = 0; j < nents; j++) {
@@ -947,25 +831,15 @@
 	}
 	mutex_unlock(&priv->copy_mutex);
 
-	dma_unmap_sg(&priv->pdev->dev, sg, nents, DMA_FROM_DEVICE);
+	dma_unmap_sg(priv->moca_dev, sg, nents, DMA_FROM_DEVICE);
 }
 #endif
 
 static void moca_read_mac_addr(struct moca_priv_data *priv, uint32_t * hi, uint32_t * lo)
 {
 	struct net_device * pdev ;
-	char					 mocaName[7] ;
 
-	if (priv == NULL)
-		sprintf (mocaName, "moca%u", 0) ;
-	else
-		sprintf (mocaName, "moca%u", ((struct moca_platform_data *)priv->pdev->dev.platform_data)->devId) ;
-
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
-	pdev = dev_get_by_name ( &init_net, mocaName ) ;
-#else
-	pdev = dev_get_by_name ( mocaName ) ;
-#endif
+	pdev = dev_get_by_name ( &init_net, priv->enet_name ) ;
 
 	if ((pdev != NULL) && (lo != NULL) && (hi != NULL)) {
 		mac_to_u32(hi, lo, pdev->dev_addr);
@@ -982,7 +856,6 @@
 void moca_get_fc_bits(void * arg, unsigned long *moca_fc_reg)
 {
 	struct moca_priv_data *     priv;
-	struct moca_platform_data * pMocaData;
 	unsigned long               flags;
 
 	if (arg == NULL) {
@@ -990,7 +863,6 @@
 	}
 
 	priv = (struct moca_priv_data *) arg;
-	pMocaData = (struct moca_platform_data *)priv->pdev->dev.platform_data;
 
 	*moca_fc_reg = 0;
 	if (priv != NULL)
@@ -1006,35 +878,116 @@
 
 #endif /* DSL_MOCA */
 
-static int __devinit bmoca_spi_probe(struct spi_device *spi) {
+static int bmoca_spi_probe(struct spi_device *spi) {
 	// TODO(apenwarr): match one spi device to one moca device struct.
 	// I happen to know that right now the system only registers one of
 	// moca_lan or moca_wan, never both, and there is never more than
 	// one moca chip present on our systems, so this is okay for now.
-	uint32_t val = kerSysBcmSpiSlaveReadReg32(spi, 0x10404000);
-	pr_info("bmoca_spi_probe bus=%d chip_select=%d: id=%08x %s\n",
-		spi->master->bus_num, spi->chip_select, val,
-		val != 0 ? "yes" : "no");
-	if (val == 0) return -ENODEV;
-	moca_lan_data.spi = spi;
-	moca_wan_data.spi = spi;
-	return 0; // success
+	struct moca_priv_data *priv;
+	const char *rfb;
+	const char *ifname;
+	int status = 0, i = 0;
+	static const char *const of_rfb[MOCA_BAND_MAX + 1] = MOCA_BAND_NAMES;
+	struct device_node *of_node = spi->dev.of_node;
+	uint32_t chip_family_id;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3,13,0)
+	struct gpio_desc *gpiod_reset;
+
+	gpiod_reset = devm_gpiod_get_optional(&spi->dev, "reset");
+	if (gpiod_reset) {
+		dev_info(&spi->dev, "Resetting MoCA chip through GPIO pin\n");
+		gpiod_direction_output(gpiod_reset, 0);
+		msleep(10);
+		gpiod_set_value(gpiod_reset, 1);
+		msleep(10);
+		gpiod_set_value(gpiod_reset, 0);
+		msleep(210);
+	}
+#endif
+
+	chip_family_id = kerSysBcmSpiSlaveReadReg32(spi, 0x10404000);
+	dev_info(&spi->dev, "bmoca_spi_probe bus=%d chip_select=%d: id=%08x %s\n",
+		spi->master->bus_num, spi->chip_select, chip_family_id,
+		chip_family_id != 0 ? "(valid)" : "(invalid)");
+	if (chip_family_id == 0) return -ENODEV;
+	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
+	if (!priv) {
+		dev_err(&spi->dev, "%s: out of memory\n", __func__);
+		return -ENOMEM;
+	}
+	/* We don't set priv->hw_rev */
+	if ((chip_family_id & 0xFFFF0000) == 0x68020000)
+		priv->regs = &regs_6802;
+	else
+		priv->regs = &regs_6816;
+	priv->moca_dev = &spi->dev;
+	priv->clk = moca_clk_get(priv->moca_dev, "moca");
+	priv->cpu_clk = moca_clk_get(priv->moca_dev, "moca-cpu");
+	priv->phy_clk = moca_clk_get(priv->moca_dev, "moca-phy");
+	status = of_property_read_string(of_node, "if-name", &ifname);
+	if (status) {
+		dev_warn(&spi->dev, "Assuming network interface device name moca0\n");
+		ifname = "moca0";
+	}
+	strncpy(priv->enet_name, ifname, sizeof(priv->enet_name));
+	priv->enet_name[sizeof(priv->enet_name)-1] = '\0';
+	priv->enet_id = ~0UL;
+	priv->macaddr_hi = 0x00000102;
+	priv->macaddr_lo = 0x03040000;
+	/* chip_id is set in hw_specific_init()*/
+	priv->use_dma = 0;
+	priv->devId = 0; /* TODO: Needs to increase */
+	priv->base = (void *) 0x10600000;
+	priv->irq = spi->irq;
+	status = of_property_read_string(of_node, "rf-band", &rfb);
+	if (!status) {
+		for (i = 0; i < MOCA_BAND_MAX; i++) {
+			if (strcmp(rfb, of_rfb[i]) == 0) {
+				priv->rf_band = i;
+				dev_info(&spi->dev, "Using %s(%d) band\n",
+					 of_rfb[i], i);
+				break;
+			}
+		}
+	}
+
+	if (status || i == MOCA_BAND_MAX) {
+		priv->rf_band = 3;
+		dev_warn(&spi->dev, "Defaulting to rf-band %s\n", of_rfb[priv->rf_band]);
+	}
+	/* I2C default values */
+	priv->i2c_base = (void __iomem *) 0x10406200;
+	priv->bcm3450_i2c_addr = 0x70;
+	of_property_read_u32(of_node, "i2c-base", (u32 *) &priv->i2c_base);
+	of_property_read_u32(of_node, "i2c-addr", &priv->bcm3450_i2c_addr);
+	moca_read_mac_addr(priv, &priv->macaddr_hi, &priv->macaddr_lo);
+	return moca_generic_probe(priv);
 }
 
-static int __devexit bmoca_spi_remove(struct spi_device *spi) {
+static int bmoca_spi_remove(struct spi_device *spi) {
 	pr_info("bmoca_spi_remove\n");
-	if (moca_lan_data.spi == spi) moca_lan_data.spi = NULL;
-	if (moca_wan_data.spi == spi) moca_wan_data.spi = NULL;
+	/* TODO */
 	return 0; // success
 }
 
+static const struct of_device_id bmoca_of_match[] = {
+		{
+			.compatible	= "brcm,bcm6802-spi",
+		},
+		{
+			.compatible	= "brcm,bcm6803-spi",
+		},
+		{},
+};
+MODULE_DEVICE_TABLE(of, bmoca_of_match);
 static struct spi_driver bmoca_spi_driver = {
-  .driver = {
-    .name = "bmoca",
-    .owner = THIS_MODULE,
-  },
-  .probe = bmoca_spi_probe,
-  .remove = __devexit_p(bmoca_spi_remove),
+	.driver = {
+		.name = "bmoca",
+		.owner = THIS_MODULE,
+		.of_match_table = of_match_ptr(bmoca_of_match),
+	},
+	.probe = bmoca_spi_probe,
+	.remove = __exit_p(bmoca_spi_remove),
 };
 
 //extern void bcmenet_register_moca_fc_bits_cb(void cb(void *, unsigned long *), int isWan, void * arg);
@@ -1055,16 +1008,13 @@
 static int  hw_specific_init( struct moca_priv_data *priv )
 {
 #ifdef DSL_MOCA
-	struct moca_platform_data *pMocaData;
 	u32 port_mode;
 
-	pMocaData = (struct moca_platform_data *)priv->pdev->dev.platform_data;
-
 	/* fill in the hw_rev field */
-	pMocaData->chip_id = MOCA_RD(0x10404004) + 0xA0;
-	pr_info("read moca chip id: %08x\n", pMocaData->chip_id);
-	if ((pMocaData->chip_id & 0xFFFE0000) != 0x68020000) { /* 6802 or 6803 */
-		printk(KERN_ERR "bmoca: No MoCA chip found\n");
+	priv->chip_id = MOCA_RD(0x10404004) + 0xA0;
+	dev_info(priv->moca_dev, "MoCA chip id: %08x\n", priv->chip_id);
+	if ((priv->chip_id & 0xFFFE0000) != 0x68020000) { /* 6802 or 6803 */
+		dev_err(priv->moca_dev, "No MoCA chip found\n");
 		return -EFAULT;
 	}
 
@@ -1077,7 +1027,7 @@
 
 	/* The definition of PORT_MODE has changed from chip revision B0 to C0
 	 * */
-	if ((pMocaData->chip_id & 0xFFFEFFF0) == 0x680200C0)
+	if ((priv->chip_id & 0xFFFEFFF0) == 0x680200C0)
 		port_mode = 2; /* RGMII_1 <-> GPHY, RGMII_0 <-> MoCA */
 	else
 		port_mode = 3; /* RGMII_0 <-> MoCA */
@@ -1091,7 +1041,7 @@
 	/* Disable UARTs to save power */
 	MOCA_WR(0x10406180, 0x4000); // PM_CONFIG
 
-	if (((pMocaData->chip_id & 0xFFFFFFF0) == 0x680200C0) || ((pMocaData->chip_id & 0xFFFFFFF0) == 0x680300C0))
+	if (((priv->chip_id & 0xFFFFFFF0) == 0x680200C0) || ((priv->chip_id & 0xFFFFFFF0) == 0x680300C0))
 	{
 		priv->i2c_base = NULL; 
 
@@ -1099,7 +1049,7 @@
 		moca_mem_init_680xC0(priv);
 	}
 
-	pMocaData->hw_rev = HWREV_MOCA_20_GEN22;
+	priv->hw_rev = HWREV_MOCA_20_GEN22;
 
 	/* Power down all LEAP memories */
 	MOCA_WR(0x101000e4, 0x6); // CLKGEN_LEAP_TOP_INST_DATA   
@@ -1117,12 +1067,20 @@
 	MOCA_WR(0x101000D4, 0x7); // CLKGEN_LEAP_TOP_INST_CLOCK_DISABLE
 
 //	bcmenet_register_moca_fc_bits_cb(
-//		moca_get_fc_bits, pMocaData->use_spi ? 1 : 0, (void *)priv);
+//		moca_get_fc_bits, priv->use_spi ? 1 : 0, (void *)priv);
 #endif
 
 	return 0;
 }
 
+static int spi_driver_register(void) {
+	return spi_register_driver(&bmoca_spi_driver);
+}
+static void spi_driver_unregister(void) {
+	spi_unregister_driver(&bmoca_spi_driver);
+}
+
+#if 0
 static int moca_platform_dev_register(void)
 {
 	struct moca_platform_data *pMocaData;
@@ -1139,11 +1097,6 @@
 
 	for (i = 0; i < mocaChipNum; i++) {
 		switch (mocaInfo[i].type) {
-			case BP_MOCA_TYPE_WAN:
-				pMocaData = &moca_wan_data;
-				pPlatformDev = &moca_wan_plat_dev;
-				break;
-
 			case BP_MOCA_TYPE_LAN:
 				pMocaData = &moca_lan_data;
 				pPlatformDev = &moca_lan_plat_dev;
@@ -1200,16 +1153,14 @@
 
 	if (moca_lan_data.devId != MOCA_DEVICE_ID_UNREGISTERED)
 		platform_device_unregister(&moca_lan_plat_dev);
-
-	if (moca_wan_data.devId != MOCA_DEVICE_ID_UNREGISTERED)
-		platform_device_unregister(&moca_wan_plat_dev);
 }
+#endif
 
 static void moca_3450_write(struct moca_priv_data *priv, u8 addr, u32 data)
 {
 	/* comment out for now. We don't use i2c on the 63268BHR board */
 #ifdef MOCA_3450_USE_I2C
-	if (((struct moca_platform_data *)priv->pdev->dev.platform_data)->use_spi == 0)
+	if (0) /* (priv->use_spi == 0) */
 		bcm3450_write_reg(addr, data);
 	else
 #endif
@@ -1223,7 +1174,7 @@
 {
 	/* comment out for now. We don't use i2c on the 63268BHR board */
 #ifdef MOCA_3450_USE_I2C
-	if (((struct moca_platform_data *)priv->pdev->dev.platform_data)->use_spi == 0)
+	if (0) /* (priv->use_spi == 0) */
 		return(bcm3450_read_reg(addr));
 	else
 #endif