root/drivers/hsi/controllers/omap_ssi_core.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ssi_regs_show
  2. ssi_gdd_regs_show
  3. ssi_debug_add_ctrl
  4. ssi_debug_remove_ctrl
  5. ssi_waketest
  6. ssi_gdd_complete
  7. ssi_gdd_tasklet
  8. ssi_gdd_isr
  9. ssi_get_clk_rate
  10. ssi_clk_event
  11. ssi_get_iomem
  12. ssi_add_controller
  13. ssi_hw_init
  14. ssi_remove_controller
  15. ssi_of_get_available_ports_count
  16. ssi_remove_ports
  17. ssi_probe
  18. ssi_remove
  19. omap_ssi_runtime_suspend
  20. omap_ssi_runtime_resume
  21. ssi_init
  22. ssi_exit

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

/* [<][>][^][v][top][bottom][index][help] */