omap_ssi_core.c 17 KB

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