pwrseq.c 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. /*
  2. * Copyright (C) 2014 Linaro Ltd
  3. *
  4. * Author: Ulf Hansson <ulf.hansson@linaro.org>
  5. *
  6. * License terms: GNU General Public License (GPL) version 2
  7. *
  8. * MMC power sequence management
  9. */
  10. #include <linux/kernel.h>
  11. #include <linux/platform_device.h>
  12. #include <linux/err.h>
  13. #include <linux/of.h>
  14. #include <linux/of_platform.h>
  15. #include <linux/mmc/host.h>
  16. #include "pwrseq.h"
  17. struct mmc_pwrseq_match {
  18. const char *compatible;
  19. struct mmc_pwrseq *(*alloc)(struct mmc_host *host, struct device *dev);
  20. };
  21. static struct mmc_pwrseq_match pwrseq_match[] = {
  22. {
  23. .compatible = "mmc-pwrseq-simple",
  24. .alloc = mmc_pwrseq_simple_alloc,
  25. }, {
  26. .compatible = "mmc-pwrseq-emmc",
  27. .alloc = mmc_pwrseq_emmc_alloc,
  28. },
  29. };
  30. static struct mmc_pwrseq_match *mmc_pwrseq_find(struct device_node *np)
  31. {
  32. struct mmc_pwrseq_match *match = ERR_PTR(-ENODEV);
  33. int i;
  34. for (i = 0; i < ARRAY_SIZE(pwrseq_match); i++) {
  35. if (of_device_is_compatible(np, pwrseq_match[i].compatible)) {
  36. match = &pwrseq_match[i];
  37. break;
  38. }
  39. }
  40. return match;
  41. }
  42. int mmc_pwrseq_alloc(struct mmc_host *host)
  43. {
  44. struct platform_device *pdev;
  45. struct device_node *np;
  46. struct mmc_pwrseq_match *match;
  47. struct mmc_pwrseq *pwrseq;
  48. int ret = 0;
  49. np = of_parse_phandle(host->parent->of_node, "mmc-pwrseq", 0);
  50. if (!np)
  51. return 0;
  52. pdev = of_find_device_by_node(np);
  53. if (!pdev) {
  54. ret = -ENODEV;
  55. goto err;
  56. }
  57. match = mmc_pwrseq_find(np);
  58. if (IS_ERR(match)) {
  59. ret = PTR_ERR(match);
  60. goto err;
  61. }
  62. pwrseq = match->alloc(host, &pdev->dev);
  63. if (IS_ERR(pwrseq)) {
  64. ret = PTR_ERR(pwrseq);
  65. goto err;
  66. }
  67. host->pwrseq = pwrseq;
  68. dev_info(host->parent, "allocated mmc-pwrseq\n");
  69. err:
  70. of_node_put(np);
  71. return ret;
  72. }
  73. void mmc_pwrseq_pre_power_on(struct mmc_host *host)
  74. {
  75. struct mmc_pwrseq *pwrseq = host->pwrseq;
  76. if (pwrseq && pwrseq->ops && pwrseq->ops->pre_power_on)
  77. pwrseq->ops->pre_power_on(host);
  78. }
  79. void mmc_pwrseq_post_power_on(struct mmc_host *host)
  80. {
  81. struct mmc_pwrseq *pwrseq = host->pwrseq;
  82. if (pwrseq && pwrseq->ops && pwrseq->ops->post_power_on)
  83. pwrseq->ops->post_power_on(host);
  84. }
  85. void mmc_pwrseq_power_off(struct mmc_host *host)
  86. {
  87. struct mmc_pwrseq *pwrseq = host->pwrseq;
  88. if (pwrseq && pwrseq->ops && pwrseq->ops->power_off)
  89. pwrseq->ops->power_off(host);
  90. }
  91. void mmc_pwrseq_free(struct mmc_host *host)
  92. {
  93. struct mmc_pwrseq *pwrseq = host->pwrseq;
  94. if (pwrseq && pwrseq->ops && pwrseq->ops->free)
  95. pwrseq->ops->free(host);
  96. host->pwrseq = NULL;
  97. }