|
@@ -25,10 +25,118 @@
|
|
|
#include <linux/mic_common.h>
|
|
|
#include <linux/mic_bus.h>
|
|
|
#include "../bus/scif_bus.h"
|
|
|
+#include "../bus/vop_bus.h"
|
|
|
#include "../common/mic_dev.h"
|
|
|
#include "mic_device.h"
|
|
|
#include "mic_smpt.h"
|
|
|
|
|
|
+static inline struct mic_device *vpdev_to_mdev(struct device *dev)
|
|
|
+{
|
|
|
+ return dev_get_drvdata(dev->parent);
|
|
|
+}
|
|
|
+
|
|
|
+static dma_addr_t
|
|
|
+_mic_dma_map_page(struct device *dev, struct page *page,
|
|
|
+ unsigned long offset, size_t size,
|
|
|
+ enum dma_data_direction dir, struct dma_attrs *attrs)
|
|
|
+{
|
|
|
+ void *va = phys_to_virt(page_to_phys(page)) + offset;
|
|
|
+ struct mic_device *mdev = vpdev_to_mdev(dev);
|
|
|
+
|
|
|
+ return mic_map_single(mdev, va, size);
|
|
|
+}
|
|
|
+
|
|
|
+static void _mic_dma_unmap_page(struct device *dev, dma_addr_t dma_addr,
|
|
|
+ size_t size, enum dma_data_direction dir,
|
|
|
+ struct dma_attrs *attrs)
|
|
|
+{
|
|
|
+ struct mic_device *mdev = vpdev_to_mdev(dev);
|
|
|
+
|
|
|
+ mic_unmap_single(mdev, dma_addr, size);
|
|
|
+}
|
|
|
+
|
|
|
+static const struct dma_map_ops _mic_dma_ops = {
|
|
|
+ .map_page = _mic_dma_map_page,
|
|
|
+ .unmap_page = _mic_dma_unmap_page,
|
|
|
+};
|
|
|
+
|
|
|
+static struct mic_irq *
|
|
|
+__mic_request_irq(struct vop_device *vpdev,
|
|
|
+ irqreturn_t (*func)(int irq, void *data),
|
|
|
+ const char *name, void *data, int intr_src)
|
|
|
+{
|
|
|
+ struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
|
|
|
+
|
|
|
+ return mic_request_threaded_irq(mdev, func, NULL, name, data,
|
|
|
+ intr_src, MIC_INTR_DB);
|
|
|
+}
|
|
|
+
|
|
|
+static void __mic_free_irq(struct vop_device *vpdev,
|
|
|
+ struct mic_irq *cookie, void *data)
|
|
|
+{
|
|
|
+ struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
|
|
|
+
|
|
|
+ return mic_free_irq(mdev, cookie, data);
|
|
|
+}
|
|
|
+
|
|
|
+static void __mic_ack_interrupt(struct vop_device *vpdev, int num)
|
|
|
+{
|
|
|
+ struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
|
|
|
+
|
|
|
+ mdev->ops->intr_workarounds(mdev);
|
|
|
+}
|
|
|
+
|
|
|
+static int __mic_next_db(struct vop_device *vpdev)
|
|
|
+{
|
|
|
+ struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
|
|
|
+
|
|
|
+ return mic_next_db(mdev);
|
|
|
+}
|
|
|
+
|
|
|
+static void *__mic_get_dp(struct vop_device *vpdev)
|
|
|
+{
|
|
|
+ struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
|
|
|
+
|
|
|
+ return mdev->dp;
|
|
|
+}
|
|
|
+
|
|
|
+static void __iomem *__mic_get_remote_dp(struct vop_device *vpdev)
|
|
|
+{
|
|
|
+ return NULL;
|
|
|
+}
|
|
|
+
|
|
|
+static void __mic_send_intr(struct vop_device *vpdev, int db)
|
|
|
+{
|
|
|
+ struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
|
|
|
+
|
|
|
+ mdev->ops->send_intr(mdev, db);
|
|
|
+}
|
|
|
+
|
|
|
+static void __iomem *__mic_ioremap(struct vop_device *vpdev,
|
|
|
+ dma_addr_t pa, size_t len)
|
|
|
+{
|
|
|
+ struct mic_device *mdev = vpdev_to_mdev(&vpdev->dev);
|
|
|
+
|
|
|
+ return mdev->aper.va + pa;
|
|
|
+}
|
|
|
+
|
|
|
+static void __mic_iounmap(struct vop_device *vpdev, void __iomem *va)
|
|
|
+{
|
|
|
+ /* nothing to do */
|
|
|
+}
|
|
|
+
|
|
|
+static struct vop_hw_ops vop_hw_ops = {
|
|
|
+ .request_irq = __mic_request_irq,
|
|
|
+ .free_irq = __mic_free_irq,
|
|
|
+ .ack_interrupt = __mic_ack_interrupt,
|
|
|
+ .next_db = __mic_next_db,
|
|
|
+ .get_dp = __mic_get_dp,
|
|
|
+ .get_remote_dp = __mic_get_remote_dp,
|
|
|
+ .send_intr = __mic_send_intr,
|
|
|
+ .ioremap = __mic_ioremap,
|
|
|
+ .iounmap = __mic_iounmap,
|
|
|
+};
|
|
|
+
|
|
|
static inline struct mic_device *scdev_to_mdev(struct scif_hw_dev *scdev)
|
|
|
{
|
|
|
return dev_get_drvdata(scdev->dev.parent);
|
|
@@ -314,7 +422,6 @@ static int mic_request_dma_chans(struct mic_device *mdev)
|
|
|
dma_cap_mask_t mask;
|
|
|
struct dma_chan *chan;
|
|
|
|
|
|
- request_module("mic_x100_dma");
|
|
|
dma_cap_zero(mask);
|
|
|
dma_cap_set(DMA_MEMCPY, mask);
|
|
|
|
|
@@ -386,9 +493,18 @@ static int _mic_start(struct cosm_device *cdev, int id)
|
|
|
goto dma_free;
|
|
|
}
|
|
|
|
|
|
+ mdev->vpdev = vop_register_device(&mdev->pdev->dev,
|
|
|
+ VOP_DEV_TRNSP, &_mic_dma_ops,
|
|
|
+ &vop_hw_ops, id + 1, &mdev->aper,
|
|
|
+ mdev->dma_ch[0]);
|
|
|
+ if (IS_ERR(mdev->vpdev)) {
|
|
|
+ rc = PTR_ERR(mdev->vpdev);
|
|
|
+ goto scif_remove;
|
|
|
+ }
|
|
|
+
|
|
|
rc = mdev->ops->load_mic_fw(mdev, NULL);
|
|
|
if (rc)
|
|
|
- goto scif_remove;
|
|
|
+ goto vop_remove;
|
|
|
mic_smpt_restore(mdev);
|
|
|
mic_intr_restore(mdev);
|
|
|
mdev->intr_ops->enable_interrupts(mdev);
|
|
@@ -396,6 +512,8 @@ static int _mic_start(struct cosm_device *cdev, int id)
|
|
|
mdev->ops->write_spad(mdev, MIC_DPHI_SPAD, mdev->dp_dma_addr >> 32);
|
|
|
mdev->ops->send_firmware_intr(mdev);
|
|
|
goto unlock_ret;
|
|
|
+vop_remove:
|
|
|
+ vop_unregister_device(mdev->vpdev);
|
|
|
scif_remove:
|
|
|
scif_unregister_device(mdev->scdev);
|
|
|
dma_free:
|
|
@@ -422,6 +540,7 @@ static void _mic_stop(struct cosm_device *cdev, bool force)
|
|
|
* will be the first to be registered and the last to be
|
|
|
* unregistered.
|
|
|
*/
|
|
|
+ vop_unregister_device(mdev->vpdev);
|
|
|
scif_unregister_device(mdev->scdev);
|
|
|
mic_free_dma_chans(mdev);
|
|
|
mbus_unregister_device(mdev->dma_mbdev);
|