linux/drivers/hsi/controllers/omap_ssi_core.c
<<
>>
Prefs
   1/* OMAP SSI driver.
   2 *
   3 * Copyright (C) 2010 Nokia Corporation. All rights reserved.
   4 * Copyright (C) 2014 Sebastian Reichel <sre@kernel.org>
   5 *
   6 * Contact: Carlos Chinea <carlos.chinea@nokia.com>
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License
  10 * version 2 as published by the Free Software Foundation.
  11 *
  12 * This program is distributed in the hope that it will be useful, but
  13 * WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU General Public License
  18 * along with this program; if not, write to the Free Software
  19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
  20 * 02110-1301 USA
  21 */
  22
  23#include <linux/compiler.h>
  24#include <linux/err.h>
  25#include <linux/ioport.h>
  26#include <linux/io.h>
  27#include <linux/clk.h>
  28#include <linux/device.h>
  29#include <linux/platform_device.h>
  30#include <linux/dma-mapping.h>
  31#include <linux/dmaengine.h>
  32#include <linux/delay.h>
  33#include <linux/seq_file.h>
  34#include <linux/scatterlist.h>
  35#include <linux/interrupt.h>
  36#include <linux/spinlock.h>
  37#include <linux/debugfs.h>
  38#include <linux/pinctrl/consumer.h>
  39#include <linux/pm_runtime.h>
  40#include <linux/of_platform.h>
  41#include <linux/hsi/hsi.h>
  42#include <linux/idr.h>
  43
  44#include "omap_ssi_regs.h"
  45#include "omap_ssi.h"
  46
  47/* For automatically allocated device IDs */
  48static DEFINE_IDA(platform_omap_ssi_ida);
  49
  50#ifdef CONFIG_DEBUG_FS
  51static int ssi_debug_show(struct seq_file *m, void *p __maybe_unused)
  52{
  53        struct hsi_controller *ssi = m->private;
  54        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
  55        void __iomem *sys = omap_ssi->sys;
  56
  57        pm_runtime_get_sync(ssi->device.parent);
  58        seq_printf(m, "REVISION\t: 0x%08x\n",  readl(sys + SSI_REVISION_REG));
  59        seq_printf(m, "SYSCONFIG\t: 0x%08x\n", readl(sys + SSI_SYSCONFIG_REG));
  60        seq_printf(m, "SYSSTATUS\t: 0x%08x\n", readl(sys + SSI_SYSSTATUS_REG));
  61        pm_runtime_put(ssi->device.parent);
  62
  63        return 0;
  64}
  65
  66static int ssi_debug_gdd_show(struct seq_file *m, void *p __maybe_unused)
  67{
  68        struct hsi_controller *ssi = m->private;
  69        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
  70        void __iomem *gdd = omap_ssi->gdd;
  71        void __iomem *sys = omap_ssi->sys;
  72        int lch;
  73
  74        pm_runtime_get_sync(ssi->device.parent);
  75
  76        seq_printf(m, "GDD_MPU_STATUS\t: 0x%08x\n",
  77                readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG));
  78        seq_printf(m, "GDD_MPU_ENABLE\t: 0x%08x\n\n",
  79                readl(sys + SSI_GDD_MPU_IRQ_ENABLE_REG));
  80        seq_printf(m, "HW_ID\t\t: 0x%08x\n",
  81                                readl(gdd + SSI_GDD_HW_ID_REG));
  82        seq_printf(m, "PPORT_ID\t: 0x%08x\n",
  83                                readl(gdd + SSI_GDD_PPORT_ID_REG));
  84        seq_printf(m, "MPORT_ID\t: 0x%08x\n",
  85                                readl(gdd + SSI_GDD_MPORT_ID_REG));
  86        seq_printf(m, "TEST\t\t: 0x%08x\n",
  87                                readl(gdd + SSI_GDD_TEST_REG));
  88        seq_printf(m, "GCR\t\t: 0x%08x\n",
  89                                readl(gdd + SSI_GDD_GCR_REG));
  90
  91        for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
  92                seq_printf(m, "\nGDD LCH %d\n=========\n", lch);
  93                seq_printf(m, "CSDP\t\t: 0x%04x\n",
  94                                readw(gdd + SSI_GDD_CSDP_REG(lch)));
  95                seq_printf(m, "CCR\t\t: 0x%04x\n",
  96                                readw(gdd + SSI_GDD_CCR_REG(lch)));
  97                seq_printf(m, "CICR\t\t: 0x%04x\n",
  98                                readw(gdd + SSI_GDD_CICR_REG(lch)));
  99                seq_printf(m, "CSR\t\t: 0x%04x\n",
 100                                readw(gdd + SSI_GDD_CSR_REG(lch)));
 101                seq_printf(m, "CSSA\t\t: 0x%08x\n",
 102                                readl(gdd + SSI_GDD_CSSA_REG(lch)));
 103                seq_printf(m, "CDSA\t\t: 0x%08x\n",
 104                                readl(gdd + SSI_GDD_CDSA_REG(lch)));
 105                seq_printf(m, "CEN\t\t: 0x%04x\n",
 106                                readw(gdd + SSI_GDD_CEN_REG(lch)));
 107                seq_printf(m, "CSAC\t\t: 0x%04x\n",
 108                                readw(gdd + SSI_GDD_CSAC_REG(lch)));
 109                seq_printf(m, "CDAC\t\t: 0x%04x\n",
 110                                readw(gdd + SSI_GDD_CDAC_REG(lch)));
 111                seq_printf(m, "CLNK_CTRL\t: 0x%04x\n",
 112                                readw(gdd + SSI_GDD_CLNK_CTRL_REG(lch)));
 113        }
 114
 115        pm_runtime_put(ssi->device.parent);
 116
 117        return 0;
 118}
 119
 120static int ssi_regs_open(struct inode *inode, struct file *file)
 121{
 122        return single_open(file, ssi_debug_show, inode->i_private);
 123}
 124
 125static int ssi_gdd_regs_open(struct inode *inode, struct file *file)
 126{
 127        return single_open(file, ssi_debug_gdd_show, inode->i_private);
 128}
 129
 130static const struct file_operations ssi_regs_fops = {
 131        .open           = ssi_regs_open,
 132        .read           = seq_read,
 133        .llseek         = seq_lseek,
 134        .release        = single_release,
 135};
 136
 137static const struct file_operations ssi_gdd_regs_fops = {
 138        .open           = ssi_gdd_regs_open,
 139        .read           = seq_read,
 140        .llseek         = seq_lseek,
 141        .release        = single_release,
 142};
 143
 144static int ssi_debug_add_ctrl(struct hsi_controller *ssi)
 145{
 146        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 147        struct dentry *dir;
 148
 149        /* SSI controller */
 150        omap_ssi->dir = debugfs_create_dir(dev_name(&ssi->device), NULL);
 151        if (!omap_ssi->dir)
 152                return -ENOMEM;
 153
 154        debugfs_create_file("regs", S_IRUGO, omap_ssi->dir, ssi,
 155                                                                &ssi_regs_fops);
 156        /* SSI GDD (DMA) */
 157        dir = debugfs_create_dir("gdd", omap_ssi->dir);
 158        if (!dir)
 159                goto rback;
 160        debugfs_create_file("regs", S_IRUGO, dir, ssi, &ssi_gdd_regs_fops);
 161
 162        return 0;
 163rback:
 164        debugfs_remove_recursive(omap_ssi->dir);
 165
 166        return -ENOMEM;
 167}
 168
 169static void ssi_debug_remove_ctrl(struct hsi_controller *ssi)
 170{
 171        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 172
 173        debugfs_remove_recursive(omap_ssi->dir);
 174}
 175#endif /* CONFIG_DEBUG_FS */
 176
 177/*
 178 * FIXME: Horrible HACK needed until we remove the useless wakeline test
 179 * in the CMT. To be removed !!!!
 180 */
 181void ssi_waketest(struct hsi_client *cl, unsigned int enable)
 182{
 183        struct hsi_port *port = hsi_get_port(cl);
 184        struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
 185        struct hsi_controller *ssi = to_hsi_controller(port->device.parent);
 186        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 187
 188        omap_port->wktest = !!enable;
 189        if (omap_port->wktest) {
 190                pm_runtime_get_sync(ssi->device.parent);
 191                writel_relaxed(SSI_WAKE(0),
 192                                omap_ssi->sys + SSI_SET_WAKE_REG(port->num));
 193        } else {
 194                writel_relaxed(SSI_WAKE(0),
 195                                omap_ssi->sys + SSI_CLEAR_WAKE_REG(port->num));
 196                pm_runtime_put(ssi->device.parent);
 197        }
 198}
 199EXPORT_SYMBOL_GPL(ssi_waketest);
 200
 201static void ssi_gdd_complete(struct hsi_controller *ssi, unsigned int lch)
 202{
 203        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 204        struct hsi_msg *msg = omap_ssi->gdd_trn[lch].msg;
 205        struct hsi_port *port = to_hsi_port(msg->cl->device.parent);
 206        struct omap_ssi_port *omap_port = hsi_port_drvdata(port);
 207        unsigned int dir;
 208        u32 csr;
 209        u32 val;
 210
 211        spin_lock(&omap_ssi->lock);
 212
 213        val = readl(omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
 214        val &= ~SSI_GDD_LCH(lch);
 215        writel_relaxed(val, omap_ssi->sys + SSI_GDD_MPU_IRQ_ENABLE_REG);
 216
 217        if (msg->ttype == HSI_MSG_READ) {
 218                dir = DMA_FROM_DEVICE;
 219                val = SSI_DATAAVAILABLE(msg->channel);
 220                pm_runtime_put(omap_port->pdev);
 221        } else {
 222                dir = DMA_TO_DEVICE;
 223                val = SSI_DATAACCEPT(msg->channel);
 224                /* Keep clocks reference for write pio event */
 225        }
 226        dma_unmap_sg(&ssi->device, msg->sgt.sgl, msg->sgt.nents, dir);
 227        csr = readw(omap_ssi->gdd + SSI_GDD_CSR_REG(lch));
 228        omap_ssi->gdd_trn[lch].msg = NULL; /* release GDD lch */
 229        dev_dbg(&port->device, "DMA completed ch %d ttype %d\n",
 230                                msg->channel, msg->ttype);
 231        spin_unlock(&omap_ssi->lock);
 232        if (csr & SSI_CSR_TOUR) { /* Timeout error */
 233                msg->status = HSI_STATUS_ERROR;
 234                msg->actual_len = 0;
 235                spin_lock(&omap_port->lock);
 236                list_del(&msg->link); /* Dequeue msg */
 237                spin_unlock(&omap_port->lock);
 238
 239                list_add_tail(&msg->link, &omap_port->errqueue);
 240                schedule_delayed_work(&omap_port->errqueue_work, 0);
 241                return;
 242        }
 243        spin_lock(&omap_port->lock);
 244        val |= readl(omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
 245        writel_relaxed(val, omap_ssi->sys + SSI_MPU_ENABLE_REG(port->num, 0));
 246        spin_unlock(&omap_port->lock);
 247
 248        msg->status = HSI_STATUS_COMPLETED;
 249        msg->actual_len = sg_dma_len(msg->sgt.sgl);
 250}
 251
 252static void ssi_gdd_tasklet(unsigned long dev)
 253{
 254        struct hsi_controller *ssi = (struct hsi_controller *)dev;
 255        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 256        void __iomem *sys = omap_ssi->sys;
 257        unsigned int lch;
 258        u32 status_reg;
 259
 260        pm_runtime_get(ssi->device.parent);
 261
 262        if (!pm_runtime_active(ssi->device.parent)) {
 263                dev_warn(ssi->device.parent, "ssi_gdd_tasklet called without runtime PM!\n");
 264                pm_runtime_put(ssi->device.parent);
 265                return;
 266        }
 267
 268        status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
 269        for (lch = 0; lch < SSI_MAX_GDD_LCH; lch++) {
 270                if (status_reg & SSI_GDD_LCH(lch))
 271                        ssi_gdd_complete(ssi, lch);
 272        }
 273        writel_relaxed(status_reg, sys + SSI_GDD_MPU_IRQ_STATUS_REG);
 274        status_reg = readl(sys + SSI_GDD_MPU_IRQ_STATUS_REG);
 275
 276        pm_runtime_put(ssi->device.parent);
 277
 278        if (status_reg)
 279                tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
 280        else
 281                enable_irq(omap_ssi->gdd_irq);
 282
 283}
 284
 285static irqreturn_t ssi_gdd_isr(int irq, void *ssi)
 286{
 287        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 288
 289        tasklet_hi_schedule(&omap_ssi->gdd_tasklet);
 290        disable_irq_nosync(irq);
 291
 292        return IRQ_HANDLED;
 293}
 294
 295static unsigned long ssi_get_clk_rate(struct hsi_controller *ssi)
 296{
 297        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 298        unsigned long rate = clk_get_rate(omap_ssi->fck);
 299        return rate;
 300}
 301
 302static int ssi_clk_event(struct notifier_block *nb, unsigned long event,
 303                                                                void *data)
 304{
 305        struct omap_ssi_controller *omap_ssi = container_of(nb,
 306                                        struct omap_ssi_controller, fck_nb);
 307        struct hsi_controller *ssi = to_hsi_controller(omap_ssi->dev);
 308        struct clk_notifier_data *clk_data = data;
 309        struct omap_ssi_port *omap_port;
 310        int i;
 311
 312        switch (event) {
 313        case PRE_RATE_CHANGE:
 314                dev_dbg(&ssi->device, "pre rate change\n");
 315
 316                for (i = 0; i < ssi->num_ports; i++) {
 317                        omap_port = omap_ssi->port[i];
 318
 319                        if (!omap_port)
 320                                continue;
 321
 322                        /* Workaround for SWBREAK + CAwake down race in CMT */
 323                        disable_irq(omap_port->wake_irq);
 324
 325                        /* stop all ssi communication */
 326                        pinctrl_pm_select_idle_state(omap_port->pdev);
 327                        udelay(1); /* wait for racing frames */
 328                }
 329
 330                break;
 331        case ABORT_RATE_CHANGE:
 332                dev_dbg(&ssi->device, "abort rate change\n");
 333                /* Fall through */
 334        case POST_RATE_CHANGE:
 335                dev_dbg(&ssi->device, "post rate change (%lu -> %lu)\n",
 336                        clk_data->old_rate, clk_data->new_rate);
 337                omap_ssi->fck_rate = DIV_ROUND_CLOSEST(clk_data->new_rate, 1000); /* kHz */
 338
 339                for (i = 0; i < ssi->num_ports; i++) {
 340                        omap_port = omap_ssi->port[i];
 341
 342                        if (!omap_port)
 343                                continue;
 344
 345                        omap_ssi_port_update_fclk(ssi, omap_port);
 346
 347                        /* resume ssi communication */
 348                        pinctrl_pm_select_default_state(omap_port->pdev);
 349                        enable_irq(omap_port->wake_irq);
 350                }
 351
 352                break;
 353        default:
 354                break;
 355        }
 356
 357        return NOTIFY_DONE;
 358}
 359
 360static int ssi_get_iomem(struct platform_device *pd,
 361                const char *name, void __iomem **pbase, dma_addr_t *phy)
 362{
 363        struct resource *mem;
 364        void __iomem *base;
 365        struct hsi_controller *ssi = platform_get_drvdata(pd);
 366
 367        mem = platform_get_resource_byname(pd, IORESOURCE_MEM, name);
 368        base = devm_ioremap_resource(&ssi->device, mem);
 369        if (IS_ERR(base))
 370                return PTR_ERR(base);
 371
 372        *pbase = base;
 373
 374        if (phy)
 375                *phy = mem->start;
 376
 377        return 0;
 378}
 379
 380static int ssi_add_controller(struct hsi_controller *ssi,
 381                                                struct platform_device *pd)
 382{
 383        struct omap_ssi_controller *omap_ssi;
 384        int err;
 385
 386        omap_ssi = devm_kzalloc(&ssi->device, sizeof(*omap_ssi), GFP_KERNEL);
 387        if (!omap_ssi)
 388                return -ENOMEM;
 389
 390        err = ida_simple_get(&platform_omap_ssi_ida, 0, 0, GFP_KERNEL);
 391        if (err < 0)
 392                goto out_err;
 393        ssi->id = err;
 394
 395        ssi->owner = THIS_MODULE;
 396        ssi->device.parent = &pd->dev;
 397        dev_set_name(&ssi->device, "ssi%d", ssi->id);
 398        hsi_controller_set_drvdata(ssi, omap_ssi);
 399        omap_ssi->dev = &ssi->device;
 400        err = ssi_get_iomem(pd, "sys", &omap_ssi->sys, NULL);
 401        if (err < 0)
 402                goto out_err;
 403        err = ssi_get_iomem(pd, "gdd", &omap_ssi->gdd, NULL);
 404        if (err < 0)
 405                goto out_err;
 406        err = platform_get_irq_byname(pd, "gdd_mpu");
 407        if (err < 0) {
 408                dev_err(&pd->dev, "GDD IRQ resource missing\n");
 409                goto out_err;
 410        }
 411        omap_ssi->gdd_irq = err;
 412        tasklet_init(&omap_ssi->gdd_tasklet, ssi_gdd_tasklet,
 413                                                        (unsigned long)ssi);
 414        err = devm_request_irq(&ssi->device, omap_ssi->gdd_irq, ssi_gdd_isr,
 415                                                0, "gdd_mpu", ssi);
 416        if (err < 0) {
 417                dev_err(&ssi->device, "Request GDD IRQ %d failed (%d)",
 418                                                        omap_ssi->gdd_irq, err);
 419                goto out_err;
 420        }
 421
 422        omap_ssi->port = devm_kcalloc(&ssi->device, ssi->num_ports,
 423                                      sizeof(*omap_ssi->port), GFP_KERNEL);
 424        if (!omap_ssi->port) {
 425                err = -ENOMEM;
 426                goto out_err;
 427        }
 428
 429        omap_ssi->fck = devm_clk_get(&ssi->device, "ssi_ssr_fck");
 430        if (IS_ERR(omap_ssi->fck)) {
 431                dev_err(&pd->dev, "Could not acquire clock \"ssi_ssr_fck\": %li\n",
 432                        PTR_ERR(omap_ssi->fck));
 433                err = -ENODEV;
 434                goto out_err;
 435        }
 436
 437        omap_ssi->fck_nb.notifier_call = ssi_clk_event;
 438        omap_ssi->fck_nb.priority = INT_MAX;
 439        clk_notifier_register(omap_ssi->fck, &omap_ssi->fck_nb);
 440
 441        /* TODO: find register, which can be used to detect context loss */
 442        omap_ssi->get_loss = NULL;
 443
 444        omap_ssi->max_speed = UINT_MAX;
 445        spin_lock_init(&omap_ssi->lock);
 446        err = hsi_register_controller(ssi);
 447
 448        if (err < 0)
 449                goto out_err;
 450
 451        return 0;
 452
 453out_err:
 454        ida_simple_remove(&platform_omap_ssi_ida, ssi->id);
 455        return err;
 456}
 457
 458static int ssi_hw_init(struct hsi_controller *ssi)
 459{
 460        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 461        int err;
 462
 463        err = pm_runtime_get_sync(ssi->device.parent);
 464        if (err < 0) {
 465                dev_err(&ssi->device, "runtime PM failed %d\n", err);
 466                return err;
 467        }
 468        /* Resetting GDD */
 469        writel_relaxed(SSI_SWRESET, omap_ssi->gdd + SSI_GDD_GRST_REG);
 470        /* Get FCK rate in kHz */
 471        omap_ssi->fck_rate = DIV_ROUND_CLOSEST(ssi_get_clk_rate(ssi), 1000);
 472        dev_dbg(&ssi->device, "SSI fck rate %lu kHz\n", omap_ssi->fck_rate);
 473
 474        writel_relaxed(SSI_CLK_AUTOGATING_ON, omap_ssi->sys + SSI_GDD_GCR_REG);
 475        omap_ssi->gdd_gcr = SSI_CLK_AUTOGATING_ON;
 476        pm_runtime_put_sync(ssi->device.parent);
 477
 478        return 0;
 479}
 480
 481static void ssi_remove_controller(struct hsi_controller *ssi)
 482{
 483        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 484        int id = ssi->id;
 485        tasklet_kill(&omap_ssi->gdd_tasklet);
 486        hsi_unregister_controller(ssi);
 487        clk_notifier_unregister(omap_ssi->fck, &omap_ssi->fck_nb);
 488        ida_simple_remove(&platform_omap_ssi_ida, id);
 489}
 490
 491static inline int ssi_of_get_available_ports_count(const struct device_node *np)
 492{
 493        struct device_node *child;
 494        int num = 0;
 495
 496        for_each_available_child_of_node(np, child)
 497                if (of_device_is_compatible(child, "ti,omap3-ssi-port"))
 498                        num++;
 499
 500        return num;
 501}
 502
 503static int ssi_remove_ports(struct device *dev, void *c)
 504{
 505        struct platform_device *pdev = to_platform_device(dev);
 506
 507        if (!dev->of_node)
 508                return 0;
 509
 510        of_node_clear_flag(dev->of_node, OF_POPULATED);
 511        of_device_unregister(pdev);
 512
 513        return 0;
 514}
 515
 516static int ssi_probe(struct platform_device *pd)
 517{
 518        struct platform_device *childpdev;
 519        struct device_node *np = pd->dev.of_node;
 520        struct device_node *child;
 521        struct hsi_controller *ssi;
 522        int err;
 523        int num_ports;
 524
 525        if (!np) {
 526                dev_err(&pd->dev, "missing device tree data\n");
 527                return -EINVAL;
 528        }
 529
 530        num_ports = ssi_of_get_available_ports_count(np);
 531
 532        ssi = hsi_alloc_controller(num_ports, GFP_KERNEL);
 533        if (!ssi) {
 534                dev_err(&pd->dev, "No memory for controller\n");
 535                return -ENOMEM;
 536        }
 537
 538        platform_set_drvdata(pd, ssi);
 539
 540        err = ssi_add_controller(ssi, pd);
 541        if (err < 0)
 542                goto out1;
 543
 544        pm_runtime_enable(&pd->dev);
 545
 546        err = ssi_hw_init(ssi);
 547        if (err < 0)
 548                goto out2;
 549#ifdef CONFIG_DEBUG_FS
 550        err = ssi_debug_add_ctrl(ssi);
 551        if (err < 0)
 552                goto out2;
 553#endif
 554
 555        for_each_available_child_of_node(np, child) {
 556                if (!of_device_is_compatible(child, "ti,omap3-ssi-port"))
 557                        continue;
 558
 559                childpdev = of_platform_device_create(child, NULL, &pd->dev);
 560                if (!childpdev) {
 561                        err = -ENODEV;
 562                        dev_err(&pd->dev, "failed to create ssi controller port\n");
 563                        goto out3;
 564                }
 565        }
 566
 567        dev_info(&pd->dev, "ssi controller %d initialized (%d ports)!\n",
 568                ssi->id, num_ports);
 569        return err;
 570out3:
 571        device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
 572out2:
 573        ssi_remove_controller(ssi);
 574out1:
 575        platform_set_drvdata(pd, NULL);
 576        pm_runtime_disable(&pd->dev);
 577
 578        return err;
 579}
 580
 581static int ssi_remove(struct platform_device *pd)
 582{
 583        struct hsi_controller *ssi = platform_get_drvdata(pd);
 584
 585        /* cleanup of of_platform_populate() call */
 586        device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
 587
 588#ifdef CONFIG_DEBUG_FS
 589        ssi_debug_remove_ctrl(ssi);
 590#endif
 591        ssi_remove_controller(ssi);
 592        platform_set_drvdata(pd, NULL);
 593
 594        pm_runtime_disable(&pd->dev);
 595
 596        return 0;
 597}
 598
 599#ifdef CONFIG_PM
 600static int omap_ssi_runtime_suspend(struct device *dev)
 601{
 602        struct hsi_controller *ssi = dev_get_drvdata(dev);
 603        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 604
 605        dev_dbg(dev, "runtime suspend!\n");
 606
 607        if (omap_ssi->get_loss)
 608                omap_ssi->loss_count =
 609                                omap_ssi->get_loss(ssi->device.parent);
 610
 611        return 0;
 612}
 613
 614static int omap_ssi_runtime_resume(struct device *dev)
 615{
 616        struct hsi_controller *ssi = dev_get_drvdata(dev);
 617        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 618
 619        dev_dbg(dev, "runtime resume!\n");
 620
 621        if ((omap_ssi->get_loss) && (omap_ssi->loss_count ==
 622                                omap_ssi->get_loss(ssi->device.parent)))
 623                return 0;
 624
 625        writel_relaxed(omap_ssi->gdd_gcr, omap_ssi->gdd + SSI_GDD_GCR_REG);
 626
 627        return 0;
 628}
 629
 630static const struct dev_pm_ops omap_ssi_pm_ops = {
 631        SET_RUNTIME_PM_OPS(omap_ssi_runtime_suspend, omap_ssi_runtime_resume,
 632                NULL)
 633};
 634
 635#define DEV_PM_OPS     (&omap_ssi_pm_ops)
 636#else
 637#define DEV_PM_OPS     NULL
 638#endif
 639
 640#ifdef CONFIG_OF
 641static const struct of_device_id omap_ssi_of_match[] = {
 642        { .compatible = "ti,omap3-ssi", },
 643        {},
 644};
 645MODULE_DEVICE_TABLE(of, omap_ssi_of_match);
 646#else
 647#define omap_ssi_of_match NULL
 648#endif
 649
 650static struct platform_driver ssi_pdriver = {
 651        .probe = ssi_probe,
 652        .remove = ssi_remove,
 653        .driver = {
 654                .name   = "omap_ssi",
 655                .pm     = DEV_PM_OPS,
 656                .of_match_table = omap_ssi_of_match,
 657        },
 658};
 659
 660static int __init ssi_init(void) {
 661        int ret;
 662
 663        ret = platform_driver_register(&ssi_pdriver);
 664        if (ret)
 665                return ret;
 666
 667        return platform_driver_register(&ssi_port_pdriver);
 668}
 669module_init(ssi_init);
 670
 671static void __exit ssi_exit(void) {
 672        platform_driver_unregister(&ssi_port_pdriver);
 673        platform_driver_unregister(&ssi_pdriver);
 674}
 675module_exit(ssi_exit);
 676
 677MODULE_ALIAS("platform:omap_ssi");
 678MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
 679MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
 680MODULE_DESCRIPTION("Synchronous Serial Interface Driver");
 681MODULE_LICENSE("GPL v2");
 682