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                dev_err(&pd->dev, "not enough memory for omap ssi\n");
 389                return -ENOMEM;
 390        }
 391
 392        err = ida_simple_get(&platform_omap_ssi_ida, 0, 0, GFP_KERNEL);
 393        if (err < 0)
 394                goto out_err;
 395        ssi->id = err;
 396
 397        ssi->owner = THIS_MODULE;
 398        ssi->device.parent = &pd->dev;
 399        dev_set_name(&ssi->device, "ssi%d", ssi->id);
 400        hsi_controller_set_drvdata(ssi, omap_ssi);
 401        omap_ssi->dev = &ssi->device;
 402        err = ssi_get_iomem(pd, "sys", &omap_ssi->sys, NULL);
 403        if (err < 0)
 404                goto out_err;
 405        err = ssi_get_iomem(pd, "gdd", &omap_ssi->gdd, NULL);
 406        if (err < 0)
 407                goto out_err;
 408        err = platform_get_irq_byname(pd, "gdd_mpu");
 409        if (err < 0) {
 410                dev_err(&pd->dev, "GDD IRQ resource missing\n");
 411                goto out_err;
 412        }
 413        omap_ssi->gdd_irq = err;
 414        tasklet_init(&omap_ssi->gdd_tasklet, ssi_gdd_tasklet,
 415                                                        (unsigned long)ssi);
 416        err = devm_request_irq(&ssi->device, omap_ssi->gdd_irq, ssi_gdd_isr,
 417                                                0, "gdd_mpu", ssi);
 418        if (err < 0) {
 419                dev_err(&ssi->device, "Request GDD IRQ %d failed (%d)",
 420                                                        omap_ssi->gdd_irq, err);
 421                goto out_err;
 422        }
 423
 424        omap_ssi->port = devm_kzalloc(&ssi->device,
 425                sizeof(struct omap_ssi_port *) * ssi->num_ports, GFP_KERNEL);
 426        if (!omap_ssi->port) {
 427                err = -ENOMEM;
 428                goto out_err;
 429        }
 430
 431        omap_ssi->fck = devm_clk_get(&ssi->device, "ssi_ssr_fck");
 432        if (IS_ERR(omap_ssi->fck)) {
 433                dev_err(&pd->dev, "Could not acquire clock \"ssi_ssr_fck\": %li\n",
 434                        PTR_ERR(omap_ssi->fck));
 435                err = -ENODEV;
 436                goto out_err;
 437        }
 438
 439        omap_ssi->fck_nb.notifier_call = ssi_clk_event;
 440        omap_ssi->fck_nb.priority = INT_MAX;
 441        clk_notifier_register(omap_ssi->fck, &omap_ssi->fck_nb);
 442
 443        /* TODO: find register, which can be used to detect context loss */
 444        omap_ssi->get_loss = NULL;
 445
 446        omap_ssi->max_speed = UINT_MAX;
 447        spin_lock_init(&omap_ssi->lock);
 448        err = hsi_register_controller(ssi);
 449
 450        if (err < 0)
 451                goto out_err;
 452
 453        return 0;
 454
 455out_err:
 456        ida_simple_remove(&platform_omap_ssi_ida, ssi->id);
 457        return err;
 458}
 459
 460static int ssi_hw_init(struct hsi_controller *ssi)
 461{
 462        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 463        int err;
 464
 465        err = pm_runtime_get_sync(ssi->device.parent);
 466        if (err < 0) {
 467                dev_err(&ssi->device, "runtime PM failed %d\n", err);
 468                return err;
 469        }
 470        /* Reseting GDD */
 471        writel_relaxed(SSI_SWRESET, omap_ssi->gdd + SSI_GDD_GRST_REG);
 472        /* Get FCK rate in KHz */
 473        omap_ssi->fck_rate = DIV_ROUND_CLOSEST(ssi_get_clk_rate(ssi), 1000);
 474        dev_dbg(&ssi->device, "SSI fck rate %lu KHz\n", omap_ssi->fck_rate);
 475
 476        writel_relaxed(SSI_CLK_AUTOGATING_ON, omap_ssi->sys + SSI_GDD_GCR_REG);
 477        omap_ssi->gdd_gcr = SSI_CLK_AUTOGATING_ON;
 478        pm_runtime_put_sync(ssi->device.parent);
 479
 480        return 0;
 481}
 482
 483static void ssi_remove_controller(struct hsi_controller *ssi)
 484{
 485        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 486        int id = ssi->id;
 487        tasklet_kill(&omap_ssi->gdd_tasklet);
 488        hsi_unregister_controller(ssi);
 489        clk_notifier_unregister(omap_ssi->fck, &omap_ssi->fck_nb);
 490        ida_simple_remove(&platform_omap_ssi_ida, id);
 491}
 492
 493static inline int ssi_of_get_available_ports_count(const struct device_node *np)
 494{
 495        struct device_node *child;
 496        int num = 0;
 497
 498        for_each_available_child_of_node(np, child)
 499                if (of_device_is_compatible(child, "ti,omap3-ssi-port"))
 500                        num++;
 501
 502        return num;
 503}
 504
 505static int ssi_remove_ports(struct device *dev, void *c)
 506{
 507        struct platform_device *pdev = to_platform_device(dev);
 508
 509        if (!dev->of_node)
 510                return 0;
 511
 512        of_node_clear_flag(dev->of_node, OF_POPULATED);
 513        of_device_unregister(pdev);
 514
 515        return 0;
 516}
 517
 518static int ssi_probe(struct platform_device *pd)
 519{
 520        struct platform_device *childpdev;
 521        struct device_node *np = pd->dev.of_node;
 522        struct device_node *child;
 523        struct hsi_controller *ssi;
 524        int err;
 525        int num_ports;
 526
 527        if (!np) {
 528                dev_err(&pd->dev, "missing device tree data\n");
 529                return -EINVAL;
 530        }
 531
 532        num_ports = ssi_of_get_available_ports_count(np);
 533
 534        ssi = hsi_alloc_controller(num_ports, GFP_KERNEL);
 535        if (!ssi) {
 536                dev_err(&pd->dev, "No memory for controller\n");
 537                return -ENOMEM;
 538        }
 539
 540        platform_set_drvdata(pd, ssi);
 541
 542        err = ssi_add_controller(ssi, pd);
 543        if (err < 0)
 544                goto out1;
 545
 546        pm_runtime_enable(&pd->dev);
 547
 548        err = ssi_hw_init(ssi);
 549        if (err < 0)
 550                goto out2;
 551#ifdef CONFIG_DEBUG_FS
 552        err = ssi_debug_add_ctrl(ssi);
 553        if (err < 0)
 554                goto out2;
 555#endif
 556
 557        for_each_available_child_of_node(np, child) {
 558                if (!of_device_is_compatible(child, "ti,omap3-ssi-port"))
 559                        continue;
 560
 561                childpdev = of_platform_device_create(child, NULL, &pd->dev);
 562                if (!childpdev) {
 563                        err = -ENODEV;
 564                        dev_err(&pd->dev, "failed to create ssi controller port\n");
 565                        goto out3;
 566                }
 567        }
 568
 569        dev_info(&pd->dev, "ssi controller %d initialized (%d ports)!\n",
 570                ssi->id, num_ports);
 571        return err;
 572out3:
 573        device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
 574out2:
 575        ssi_remove_controller(ssi);
 576out1:
 577        platform_set_drvdata(pd, NULL);
 578        pm_runtime_disable(&pd->dev);
 579
 580        return err;
 581}
 582
 583static int ssi_remove(struct platform_device *pd)
 584{
 585        struct hsi_controller *ssi = platform_get_drvdata(pd);
 586
 587        /* cleanup of of_platform_populate() call */
 588        device_for_each_child(&pd->dev, NULL, ssi_remove_ports);
 589
 590#ifdef CONFIG_DEBUG_FS
 591        ssi_debug_remove_ctrl(ssi);
 592#endif
 593        ssi_remove_controller(ssi);
 594        platform_set_drvdata(pd, NULL);
 595
 596        pm_runtime_disable(&pd->dev);
 597
 598        return 0;
 599}
 600
 601#ifdef CONFIG_PM
 602static int omap_ssi_runtime_suspend(struct device *dev)
 603{
 604        struct hsi_controller *ssi = dev_get_drvdata(dev);
 605        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 606
 607        dev_dbg(dev, "runtime suspend!\n");
 608
 609        if (omap_ssi->get_loss)
 610                omap_ssi->loss_count =
 611                                omap_ssi->get_loss(ssi->device.parent);
 612
 613        return 0;
 614}
 615
 616static int omap_ssi_runtime_resume(struct device *dev)
 617{
 618        struct hsi_controller *ssi = dev_get_drvdata(dev);
 619        struct omap_ssi_controller *omap_ssi = hsi_controller_drvdata(ssi);
 620
 621        dev_dbg(dev, "runtime resume!\n");
 622
 623        if ((omap_ssi->get_loss) && (omap_ssi->loss_count ==
 624                                omap_ssi->get_loss(ssi->device.parent)))
 625                return 0;
 626
 627        writel_relaxed(omap_ssi->gdd_gcr, omap_ssi->gdd + SSI_GDD_GCR_REG);
 628
 629        return 0;
 630}
 631
 632static const struct dev_pm_ops omap_ssi_pm_ops = {
 633        SET_RUNTIME_PM_OPS(omap_ssi_runtime_suspend, omap_ssi_runtime_resume,
 634                NULL)
 635};
 636
 637#define DEV_PM_OPS     (&omap_ssi_pm_ops)
 638#else
 639#define DEV_PM_OPS     NULL
 640#endif
 641
 642#ifdef CONFIG_OF
 643static const struct of_device_id omap_ssi_of_match[] = {
 644        { .compatible = "ti,omap3-ssi", },
 645        {},
 646};
 647MODULE_DEVICE_TABLE(of, omap_ssi_of_match);
 648#else
 649#define omap_ssi_of_match NULL
 650#endif
 651
 652static struct platform_driver ssi_pdriver = {
 653        .probe = ssi_probe,
 654        .remove = ssi_remove,
 655        .driver = {
 656                .name   = "omap_ssi",
 657                .pm     = DEV_PM_OPS,
 658                .of_match_table = omap_ssi_of_match,
 659        },
 660};
 661
 662static int __init ssi_init(void) {
 663        int ret;
 664
 665        ret = platform_driver_register(&ssi_pdriver);
 666        if (ret)
 667                return ret;
 668
 669        return platform_driver_register(&ssi_port_pdriver);
 670}
 671module_init(ssi_init);
 672
 673static void __exit ssi_exit(void) {
 674        platform_driver_unregister(&ssi_port_pdriver);
 675        platform_driver_unregister(&ssi_pdriver);
 676}
 677module_exit(ssi_exit);
 678
 679MODULE_ALIAS("platform:omap_ssi");
 680MODULE_AUTHOR("Carlos Chinea <carlos.chinea@nokia.com>");
 681MODULE_AUTHOR("Sebastian Reichel <sre@kernel.org>");
 682MODULE_DESCRIPTION("Synchronous Serial Interface Driver");
 683MODULE_LICENSE("GPL v2");
 684