Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /* OMAP SSI driver.
0003  *
0004  * Copyright (C) 2010 Nokia Corporation. All rights reserved.
0005  * Copyright (C) 2014 Sebastian Reichel <sre@kernel.org>
0006  *
0007  * Contact: Carlos Chinea <carlos.chinea@nokia.com>
0008  */
0009 
0010 #include <linux/compiler.h>
0011 #include <linux/err.h>
0012 #include <linux/ioport.h>
0013 #include <linux/io.h>
0014 #include <linux/clk.h>
0015 #include <linux/device.h>
0016 #include <linux/platform_device.h>
0017 #include <linux/dma-mapping.h>
0018 #include <linux/dmaengine.h>
0019 #include <linux/delay.h>
0020 #include <linux/seq_file.h>
0021 #include <linux/scatterlist.h>
0022 #include <linux/interrupt.h>
0023 #include <linux/spinlock.h>
0024 #include <linux/debugfs.h>
0025 #include <linux/pinctrl/consumer.h>
0026 #include <linux/pm_runtime.h>
0027 #include <linux/of_platform.h>
0028 #include <linux/hsi/hsi.h>
0029 #include <linux/idr.h>
0030 
0031 #include "omap_ssi_regs.h"
0032 #include "omap_ssi.h"
0033 
0034 /* For automatically allocated device IDs */
0035 static DEFINE_IDA(platform_omap_ssi_ida);
0036 
0037 #ifdef CONFIG_DEBUG_FS
0038 static int ssi_regs_show(struct seq_file *m, void *p __maybe_unused)
0039 {
0040     struct hsi_controller *ssi = m->private;
0041     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0042     void __iomem *sys = omap_ssi->sys;
0043 
0044     pm_runtime_get_sync(ssi->device.parent);
0045     seq_printf(m, "REVISION\t: 0x%08x\n",  readl(sys + SSI_REVISION_REG));
0046     seq_printf(m, "SYSCONFIG\t: 0x%08x\n", readl(sys + SSI_SYSCONFIG_REG));
0047     seq_printf(m, "SYSSTATUS\t: 0x%08x\n", readl(sys + SSI_SYSSTATUS_REG));
0048     pm_runtime_put(ssi->device.parent);
0049 
0050     return 0;
0051 }
0052 
0053 static int ssi_gdd_regs_show(struct seq_file *m, void *p __maybe_unused)
0054 {
0055     struct hsi_controller *ssi = m->private;
0056     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0057     void __iomem *gdd = omap_ssi->gdd;
0058     void __iomem *sys = omap_ssi->sys;
0059     int lch;
0060 
0061     pm_runtime_get_sync(ssi->device.parent);
0062 
0063     seq_printf(m, "GDD_MPU_STATUS\t: 0x%08x\n",
0064         readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG));
0065     seq_printf(m, "GDD_MPU_ENABLE\t: 0x%08x\n\n",
0066         readl(sys + SSI_GDD_MPU_IRQ_ENABLE_REG));
0067     seq_printf(m, "HW_ID\t\t: 0x%08x\n",
0068                 readl(gdd + SSI_GDD_HW_ID_REG));
0069     seq_printf(m, "PPORT_ID\t: 0x%08x\n",
0070                 readl(gdd + SSI_GDD_PPORT_ID_REG));
0071     seq_printf(m, "MPORT_ID\t: 0x%08x\n",
0072                 readl(gdd + SSI_GDD_MPORT_ID_REG));
0073     seq_printf(m, "TEST\t\t: 0x%08x\n",
0074                 readl(gdd + SSI_GDD_TEST_REG));
0075     seq_printf(m, "GCR\t\t: 0x%08x\n",
0076                 readl(gdd + SSI_GDD_GCR_REG));
0077 
0078     for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
0079         seq_printf(m, "\nGDD LCH %d\n=========\n", lch);
0080         seq_printf(m, "CSDP\t\t: 0x%04x\n",
0081                 readw(gdd + SSI_GDD_CSDP_REG(lch)));
0082         seq_printf(m, "CCR\t\t: 0x%04x\n",
0083                 readw(gdd + SSI_GDD_CCR_REG(lch)));
0084         seq_printf(m, "CICR\t\t: 0x%04x\n",
0085                 readw(gdd + SSI_GDD_CICR_REG(lch)));
0086         seq_printf(m, "CSR\t\t: 0x%04x\n",
0087                 readw(gdd + SSI_GDD_CSR_REG(lch)));
0088         seq_printf(m, "CSSA\t\t: 0x%08x\n",
0089                 readl(gdd + SSI_GDD_CSSA_REG(lch)));
0090         seq_printf(m, "CDSA\t\t: 0x%08x\n",
0091                 readl(gdd + SSI_GDD_CDSA_REG(lch)));
0092         seq_printf(m, "CEN\t\t: 0x%04x\n",
0093                 readw(gdd + SSI_GDD_CEN_REG(lch)));
0094         seq_printf(m, "CSAC\t\t: 0x%04x\n",
0095                 readw(gdd + SSI_GDD_CSAC_REG(lch)));
0096         seq_printf(m, "CDAC\t\t: 0x%04x\n",
0097                 readw(gdd + SSI_GDD_CDAC_REG(lch)));
0098         seq_printf(m, "CLNK_CTRL\t: 0x%04x\n",
0099                 readw(gdd + SSI_GDD_CLNK_CTRL_REG(lch)));
0100     }
0101 
0102     pm_runtime_put(ssi->device.parent);
0103 
0104     return 0;
0105 }
0106 
0107 DEFINE_SHOW_ATTRIBUTE(ssi_regs);
0108 DEFINE_SHOW_ATTRIBUTE(ssi_gdd_regs);
0109 
0110 static int ssi_debug_add_ctrl(struct hsi_controller *ssi)
0111 {
0112     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0113     struct dentry *dir;
0114 
0115     /* SSI controller */
0116     omap_ssi->dir = debugfs_create_dir(dev_name(&ssi->device), NULL);
0117     if (!omap_ssi->dir)
0118         return -ENOMEM;
0119 
0120     debugfs_create_file("regs", S_IRUGO, omap_ssi->dir, ssi,
0121                                 &ssi_regs_fops);
0122     /* SSI GDD (DMA) */
0123     dir = debugfs_create_dir("gdd", omap_ssi->dir);
0124     if (!dir)
0125         goto rback;
0126     debugfs_create_file("regs", S_IRUGO, dir, ssi, &ssi_gdd_regs_fops);
0127 
0128     return 0;
0129 rback:
0130     debugfs_remove_recursive(omap_ssi->dir);
0131 
0132     return -ENOMEM;
0133 }
0134 
0135 static void ssi_debug_remove_ctrl(struct hsi_controller *ssi)
0136 {
0137     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0138 
0139     debugfs_remove_recursive(omap_ssi->dir);
0140 }
0141 #endif /* CONFIG_DEBUG_FS */
0142 
0143 /*
0144  * FIXME: Horrible HACK needed until we remove the useless wakeline test
0145  * in the CMT. To be removed !!!!
0146  */
0147 void ssi_waketest(struct hsi_client *cl, unsigned int enable)
0148 {
0149     struct hsi_port *port = hsi_get_port(cl);
0150     struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
0151     struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
0152     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0153 
0154     omap_port->wktest = !!enable;
0155     if (omap_port->wktest) {
0156         pm_runtime_get_sync(ssi->device.parent);
0157         writel_relaxed(SSI_WAKE(0),
0158                 omap_ssi->sys + SSI_SET_WAKE_REG(port->num));
0159     } else {
0160         writel_relaxed(SSI_WAKE(0),
0161                 omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num));
0162         pm_runtime_put(ssi->device.parent);
0163     }
0164 }
0165 EXPORT_SYMBOL_GPL(ssi_waketest);
0166 
0167 static void ssi_gdd_complete(struct hsi_controller *ssi, unsigned int lch)
0168 {
0169     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0170     struct hsi_msg *msg = omap_ssi->gdd_trn[lch].msg;
0171     struct hsi_port *port = to_hsi_port(msg->cl->device.parent);
0172     struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
0173     unsigned int dir;
0174     u32 csr;
0175     u32 val;
0176 
0177     spin_lock(&omap_ssi->lock);
0178 
0179     val = readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
0180     val &= ~SSI_GDD_LCH(lch);
0181     writel_relaxed(val, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
0182 
0183     if (msg->ttype == HSI_MSG_READ) {
0184         dir = DMA_FROM_DEVICE;
0185         val = SSI_DATAAVAILABLE(msg->channel);
0186         pm_runtime_put(omap_port->pdev);
0187     } else {
0188         dir = DMA_TO_DEVICE;
0189         val = SSI_DATAACCEPT(msg->channel);
0190         /* Keep clocks reference for write pio event */
0191     }
0192     dma_unmap_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents, dir);
0193     csr = readw(omap_ssi->gdd + SSI_GDD_CSR_REG(lch));
0194     omap_ssi->gdd_trn[lch].msg = NULL; /* release GDD lch */
0195     dev_dbg(&port->device, "DMA completed ch %d ttype %d\n",
0196                 msg->channel, msg->ttype);
0197     spin_unlock(&omap_ssi->lock);
0198     if (csr & SSI_CSR_TOUR) { /* Timeout error */
0199         msg->status = HSI_STATUS_ERROR;
0200         msg->actual_len = 0;
0201         spin_lock(&omap_port->lock);
0202         list_del(&msg->link); /* Dequeue msg */
0203         spin_unlock(&omap_port->lock);
0204 
0205         list_add_tail(&msg->link, &omap_port->errqueue);
0206         schedule_delayed_work(&omap_port->errqueue_work, 0);
0207         return;
0208     }
0209     spin_lock(&omap_port->lock);
0210     val |= readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
0211     writel_relaxed(val, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
0212     spin_unlock(&omap_port->lock);
0213 
0214     msg->status = HSI_STATUS_COMPLETED;
0215     msg->actual_len = sg_dma_len(msg->sgt.sgl);
0216 }
0217 
0218 static void ssi_gdd_tasklet(unsigned long dev)
0219 {
0220     struct hsi_controller *ssi = (struct hsi_controller *)dev;
0221     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0222     void __iomem *sys = omap_ssi->sys;
0223     unsigned int lch;
0224     u32 status_reg;
0225 
0226     pm_runtime_get(ssi->device.parent);
0227 
0228     if (!pm_runtime_active(ssi->device.parent)) {
0229         dev_warn(ssi->device.parent, "ssi_gdd_tasklet called without runtime PM!\n");
0230         pm_runtime_put(ssi->device.parent);
0231         return;
0232     }
0233 
0234     status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
0235     for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
0236         if (status_reg & SSI_GDD_LCH(lch))
0237             ssi_gdd_complete(ssi, lch);
0238     }
0239     writel_relaxed(status_reg, sys + SSI_GDD_MPU_IRQ_STATUS_REG);
0240     status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
0241 
0242     pm_runtime_put(ssi->device.parent);
0243 
0244     if (status_reg)
0245         tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
0246     else
0247         enable_irq(omap_ssi->gdd_irq);
0248 
0249 }
0250 
0251 static irqreturn_t ssi_gdd_isr(int irq, void *ssi)
0252 {
0253     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0254 
0255     tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
0256     disable_irq_nosync(irq);
0257 
0258     return IRQ_HANDLED;
0259 }
0260 
0261 static unsigned long ssi_get_clk_rate(struct hsi_controller *ssi)
0262 {
0263     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0264     unsigned long rate = clk_get_rate(omap_ssi->fck);
0265     return rate;
0266 }
0267 
0268 static int ssi_clk_event(struct notifier_block *nb, unsigned long event,
0269                                 void *data)
0270 {
0271     struct omap_ssi_controller *omap_ssi = container_of(nb,
0272                     struct omap_ssi_controller, fck_nb);
0273     struct hsi_controller *ssi = to_hsi_controller(omap_ssi->dev);
0274     struct clk_notifier_data *clk_data = data;
0275     struct omap_ssi_port *omap_port;
0276     int i;
0277 
0278     switch (event) {
0279     case PRE_RATE_CHANGE:
0280         dev_dbg(&ssi->device, "pre rate change\n");
0281 
0282         for (i = 0; i < ssi->num_ports; i++) {
0283             omap_port = omap_ssi->port[i];
0284 
0285             if (!omap_port)
0286                 continue;
0287 
0288             /* Workaround for SWBREAK + CAwake down race in CMT */
0289             disable_irq(omap_port->wake_irq);
0290 
0291             /* stop all ssi communication */
0292             pinctrl_pm_select_idle_state(omap_port->pdev);
0293             udelay(1); /* wait for racing frames */
0294         }
0295 
0296         break;
0297     case ABORT_RATE_CHANGE:
0298         dev_dbg(&ssi->device, "abort rate change\n");
0299         fallthrough;
0300     case POST_RATE_CHANGE:
0301         dev_dbg(&ssi->device, "post rate change (%lu -> %lu)\n",
0302             clk_data->old_rate, clk_data->new_rate);
0303         omap_ssi->fck_rate = DIV_ROUND_CLOSEST(clk_data->new_rate, 1000); /* kHz */
0304 
0305         for (i = 0; i < ssi->num_ports; i++) {
0306             omap_port = omap_ssi->port[i];
0307 
0308             if (!omap_port)
0309                 continue;
0310 
0311             omap_ssi_port_update_fclk(ssi, omap_port);
0312 
0313             /* resume ssi communication */
0314             pinctrl_pm_select_default_state(omap_port->pdev);
0315             enable_irq(omap_port->wake_irq);
0316         }
0317 
0318         break;
0319     default:
0320         break;
0321     }
0322 
0323     return NOTIFY_DONE;
0324 }
0325 
0326 static int ssi_get_iomem(struct platform_device *pd,
0327         const char *name, void __iomem **pbase, dma_addr_t *phy)
0328 {
0329     struct resource *mem;
0330     void __iomem *base;
0331     struct hsi_controller *ssi = platform_get_drvdata(pd);
0332 
0333     mem = platform_get_resource_byname(pd, IORESOURCE_MEM, name);
0334     base = devm_ioremap_resource(&ssi->device, mem);
0335     if (IS_ERR(base))
0336         return PTR_ERR(base);
0337 
0338     *pbase = base;
0339 
0340     if (phy)
0341         *phy = mem->start;
0342 
0343     return 0;
0344 }
0345 
0346 static int ssi_add_controller(struct hsi_controller *ssi,
0347                         struct platform_device *pd)
0348 {
0349     struct omap_ssi_controller *omap_ssi;
0350     int err;
0351 
0352     omap_ssi = devm_kzalloc(&ssi->device, sizeof(*omap_ssi), GFP_KERNEL);
0353     if (!omap_ssi)
0354         return -ENOMEM;
0355 
0356     err = ida_simple_get(&platform_omap_ssi_ida, 0, 0, GFP_KERNEL);
0357     if (err < 0)
0358         return err;
0359     ssi->id = err;
0360 
0361     ssi->owner = THIS_MODULE;
0362     ssi->device.parent = &pd->dev;
0363     dev_set_name(&ssi->device, "ssi%d", ssi->id);
0364     hsi_controller_set_drvdata(ssi, omap_ssi);
0365     omap_ssi->dev = &ssi->device;
0366     err = ssi_get_iomem(pd, "sys", &omap_ssi->sys, NULL);
0367     if (err < 0)
0368         goto out_err;
0369     err = ssi_get_iomem(pd, "gdd", &omap_ssi->gdd, NULL);
0370     if (err < 0)
0371         goto out_err;
0372     err = platform_get_irq_byname(pd, "gdd_mpu");
0373     if (err < 0)
0374         goto out_err;
0375     omap_ssi->gdd_irq = err;
0376     tasklet_init(&omap_ssi->gdd_tasklet, ssi_gdd_tasklet,
0377                             (unsigned long)ssi);
0378     err = devm_request_irq(&ssi->device, omap_ssi->gdd_irq, ssi_gdd_isr,
0379                         0, "gdd_mpu", ssi);
0380     if (err < 0) {
0381         dev_err(&ssi->device, "Request GDD IRQ %d failed (%d)",
0382                             omap_ssi->gdd_irq, err);
0383         goto out_err;
0384     }
0385 
0386     omap_ssi->port = devm_kcalloc(&ssi->device, ssi->num_ports,
0387                       sizeof(*omap_ssi->port), GFP_KERNEL);
0388     if (!omap_ssi->port) {
0389         err = -ENOMEM;
0390         goto out_err;
0391     }
0392 
0393     omap_ssi->fck = devm_clk_get(&ssi->device, "ssi_ssr_fck");
0394     if (IS_ERR(omap_ssi->fck)) {
0395         dev_err(&pd->dev, "Could not acquire clock \"ssi_ssr_fck\": %li\n",
0396             PTR_ERR(omap_ssi->fck));
0397         err = -ENODEV;
0398         goto out_err;
0399     }
0400 
0401     omap_ssi->fck_nb.notifier_call = ssi_clk_event;
0402     omap_ssi->fck_nb.priority = INT_MAX;
0403     clk_notifier_register(omap_ssi->fck, &omap_ssi->fck_nb);
0404 
0405     /* TODO: find register, which can be used to detect context loss */
0406     omap_ssi->get_loss = NULL;
0407 
0408     omap_ssi->max_speed = UINT_MAX;
0409     spin_lock_init(&omap_ssi->lock);
0410     err = hsi_register_controller(ssi);
0411 
0412     if (err < 0)
0413         goto out_err;
0414 
0415     return 0;
0416 
0417 out_err:
0418     ida_simple_remove(&platform_omap_ssi_ida, ssi->id);
0419     return err;
0420 }
0421 
0422 static int ssi_hw_init(struct hsi_controller *ssi)
0423 {
0424     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0425     int err;
0426 
0427     err = pm_runtime_resume_and_get(ssi->device.parent);
0428     if (err < 0) {
0429         dev_err(&ssi->device, "runtime PM failed %d\n", err);
0430         return err;
0431     }
0432     /* Resetting GDD */
0433     writel_relaxed(SSI_SWRESET, omap_ssi->gdd + SSI_GDD_GRST_REG);
0434     /* Get FCK rate in kHz */
0435     omap_ssi->fck_rate = DIV_ROUND_CLOSEST(ssi_get_clk_rate(ssi), 1000);
0436     dev_dbg(&ssi->device, "SSI fck rate %lu kHz\n", omap_ssi->fck_rate);
0437 
0438     writel_relaxed(SSI_CLK_AUTOGATING_ON, omap_ssi->sys + SSI_GDD_GCR_REG);
0439     omap_ssi->gdd_gcr = SSI_CLK_AUTOGATING_ON;
0440     pm_runtime_put_sync(ssi->device.parent);
0441 
0442     return 0;
0443 }
0444 
0445 static void ssi_remove_controller(struct hsi_controller *ssi)
0446 {
0447     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0448     int id = ssi->id;
0449     tasklet_kill(&omap_ssi->gdd_tasklet);
0450     hsi_unregister_controller(ssi);
0451     clk_notifier_unregister(omap_ssi->fck, &omap_ssi->fck_nb);
0452     ida_simple_remove(&platform_omap_ssi_ida, id);
0453 }
0454 
0455 static inline int ssi_of_get_available_ports_count(const struct device_node *np)
0456 {
0457     struct device_node *child;
0458     int num = 0;
0459 
0460     for_each_available_child_of_node(np, child)
0461         if (of_device_is_compatible(child, "ti,omap3-ssi-port"))
0462             num++;
0463 
0464     return num;
0465 }
0466 
0467 static int ssi_remove_ports(struct device *dev, void *c)
0468 {
0469     struct platform_device *pdev = to_platform_device(dev);
0470 
0471     if (!dev->of_node)
0472         return 0;
0473 
0474     of_node_clear_flag(dev->of_node, OF_POPULATED);
0475     of_device_unregister(pdev);
0476 
0477     return 0;
0478 }
0479 
0480 static int ssi_probe(struct platform_device *pd)
0481 {
0482     struct platform_device *childpdev;
0483     struct device_node *np = pd->dev.of_node;
0484     struct device_node *child;
0485     struct hsi_controller *ssi;
0486     int err;
0487     int num_ports;
0488 
0489     if (!np) {
0490         dev_err(&pd->dev, "missing device tree data\n");
0491         return -EINVAL;
0492     }
0493 
0494     num_ports = ssi_of_get_available_ports_count(np);
0495 
0496     ssi = hsi_alloc_controller(num_ports, GFP_KERNEL);
0497     if (!ssi) {
0498         dev_err(&pd->dev, "No memory for controller\n");
0499         return -ENOMEM;
0500     }
0501 
0502     platform_set_drvdata(pd, ssi);
0503 
0504     err = ssi_add_controller(ssi, pd);
0505     if (err < 0)
0506         goto out1;
0507 
0508     pm_runtime_enable(&pd->dev);
0509 
0510     err = ssi_hw_init(ssi);
0511     if (err < 0)
0512         goto out2;
0513 #ifdef CONFIG_DEBUG_FS
0514     err = ssi_debug_add_ctrl(ssi);
0515     if (err < 0)
0516         goto out2;
0517 #endif
0518 
0519     for_each_available_child_of_node(np, child) {
0520         if (!of_device_is_compatible(child, "ti,omap3-ssi-port"))
0521             continue;
0522 
0523         childpdev = of_platform_device_create(child, NULL, &pd->dev);
0524         if (!childpdev) {
0525             err = -ENODEV;
0526             dev_err(&pd->dev, "failed to create ssi controller port\n");
0527             goto out3;
0528         }
0529     }
0530 
0531     dev_info(&pd->dev, "ssi controller %d initialized (%d ports)!\n",
0532         ssi->id, num_ports);
0533     return err;
0534 out3:
0535     device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
0536 out2:
0537     ssi_remove_controller(ssi);
0538 out1:
0539     platform_set_drvdata(pd, NULL);
0540     pm_runtime_disable(&pd->dev);
0541 
0542     return err;
0543 }
0544 
0545 static int ssi_remove(struct platform_device *pd)
0546 {
0547     struct hsi_controller *ssi = platform_get_drvdata(pd);
0548 
0549     /* cleanup of of_platform_populate() call */
0550     device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
0551 
0552 #ifdef CONFIG_DEBUG_FS
0553     ssi_debug_remove_ctrl(ssi);
0554 #endif
0555     ssi_remove_controller(ssi);
0556     platform_set_drvdata(pd, NULL);
0557 
0558     pm_runtime_disable(&pd->dev);
0559 
0560     return 0;
0561 }
0562 
0563 #ifdef CONFIG_PM
0564 static int omap_ssi_runtime_suspend(struct device *dev)
0565 {
0566     struct hsi_controller *ssi = dev_get_drvdata(dev);
0567     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0568 
0569     dev_dbg(dev, "runtime suspend!\n");
0570 
0571     if (omap_ssi->get_loss)
0572         omap_ssi->loss_count =
0573                 omap_ssi->get_loss(ssi->device.parent);
0574 
0575     return 0;
0576 }
0577 
0578 static int omap_ssi_runtime_resume(struct device *dev)
0579 {
0580     struct hsi_controller *ssi = dev_get_drvdata(dev);
0581     struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
0582 
0583     dev_dbg(dev, "runtime resume!\n");
0584 
0585     if ((omap_ssi->get_loss) && (omap_ssi->loss_count ==
0586                 omap_ssi->get_loss(ssi->device.parent)))
0587         return 0;
0588 
0589     writel_relaxed(omap_ssi->gdd_gcr, omap_ssi->gdd + SSI_GDD_GCR_REG);
0590 
0591     return 0;
0592 }
0593 
0594 static const struct dev_pm_ops omap_ssi_pm_ops = {
0595     SET_RUNTIME_PM_OPS(omap_ssi_runtime_suspend, omap_ssi_runtime_resume,
0596         NULL)
0597 };
0598 
0599 #define DEV_PM_OPS     (&omap_ssi_pm_ops)
0600 #else
0601 #define DEV_PM_OPS     NULL
0602 #endif
0603 
0604 #ifdef CONFIG_OF
0605 static const struct of_device_id omap_ssi_of_match[] = {
0606     { .compatible = "ti,omap3-ssi", },
0607     {},
0608 };
0609 MODULE_DEVICE_TABLE(of, omap_ssi_of_match);
0610 #else
0611 #define omap_ssi_of_match NULL
0612 #endif
0613 
0614 static struct platform_driver ssi_pdriver = {
0615     .probe = ssi_probe,
0616     .remove = ssi_remove,
0617     .driver = {
0618         .name   = "omap_ssi",
0619         .pm     = DEV_PM_OPS,
0620         .of_match_table = omap_ssi_of_match,
0621     },
0622 };
0623 
0624 static int __init ssi_init(void) {
0625     int ret;
0626 
0627     ret = platform_driver_register(&ssi_pdriver);
0628     if (ret)
0629         return ret;
0630 
0631     return platform_driver_register(&ssi_port_pdriver);
0632 }
0633 module_init(ssi_init);
0634 
0635 static void __exit ssi_exit(void) {
0636     platform_driver_unregister(&ssi_port_pdriver);
0637     platform_driver_unregister(&ssi_pdriver);
0638 }
0639 module_exit(ssi_exit);
0640 
0641 MODULE_ALIAS("platform:omap_ssi");
0642 MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
0643 MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
0644 MODULE_DESCRIPTION("Synchronous Serial Interface Driver");
0645 MODULE_LICENSE("GPL v2");