rt2x00soc.c 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. Copyright (C) 2004 - 2009 Ivo van Doorn <[email protected]>
  4. Copyright (C) 2004 - 2009 Felix Fietkau <[email protected]>
  5. <http://rt2x00.serialmonkey.com>
  6. */
  7. /*
  8. Module: rt2x00soc
  9. Abstract: rt2x00 generic soc device routines.
  10. */
  11. #include <linux/bug.h>
  12. #include <linux/kernel.h>
  13. #include <linux/module.h>
  14. #include <linux/platform_device.h>
  15. #include <linux/slab.h>
  16. #include "rt2x00.h"
  17. #include "rt2x00soc.h"
  18. static void rt2x00soc_free_reg(struct rt2x00_dev *rt2x00dev)
  19. {
  20. kfree(rt2x00dev->rf);
  21. rt2x00dev->rf = NULL;
  22. kfree(rt2x00dev->eeprom);
  23. rt2x00dev->eeprom = NULL;
  24. iounmap(rt2x00dev->csr.base);
  25. }
  26. static int rt2x00soc_alloc_reg(struct rt2x00_dev *rt2x00dev)
  27. {
  28. struct platform_device *pdev = to_platform_device(rt2x00dev->dev);
  29. struct resource *res;
  30. res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
  31. if (!res)
  32. return -ENODEV;
  33. rt2x00dev->csr.base = ioremap(res->start, resource_size(res));
  34. if (!rt2x00dev->csr.base)
  35. return -ENOMEM;
  36. rt2x00dev->eeprom = kzalloc(rt2x00dev->ops->eeprom_size, GFP_KERNEL);
  37. if (!rt2x00dev->eeprom)
  38. goto exit;
  39. rt2x00dev->rf = kzalloc(rt2x00dev->ops->rf_size, GFP_KERNEL);
  40. if (!rt2x00dev->rf)
  41. goto exit;
  42. return 0;
  43. exit:
  44. rt2x00_probe_err("Failed to allocate registers\n");
  45. rt2x00soc_free_reg(rt2x00dev);
  46. return -ENOMEM;
  47. }
  48. int rt2x00soc_probe(struct platform_device *pdev, const struct rt2x00_ops *ops)
  49. {
  50. struct ieee80211_hw *hw;
  51. struct rt2x00_dev *rt2x00dev;
  52. int retval;
  53. hw = ieee80211_alloc_hw(sizeof(struct rt2x00_dev), ops->hw);
  54. if (!hw) {
  55. rt2x00_probe_err("Failed to allocate hardware\n");
  56. return -ENOMEM;
  57. }
  58. platform_set_drvdata(pdev, hw);
  59. rt2x00dev = hw->priv;
  60. rt2x00dev->dev = &pdev->dev;
  61. rt2x00dev->ops = ops;
  62. rt2x00dev->hw = hw;
  63. rt2x00dev->irq = platform_get_irq(pdev, 0);
  64. rt2x00dev->name = pdev->dev.driver->name;
  65. rt2x00dev->clk = clk_get(&pdev->dev, NULL);
  66. if (IS_ERR(rt2x00dev->clk))
  67. rt2x00dev->clk = NULL;
  68. rt2x00_set_chip_intf(rt2x00dev, RT2X00_CHIP_INTF_SOC);
  69. retval = rt2x00soc_alloc_reg(rt2x00dev);
  70. if (retval)
  71. goto exit_free_device;
  72. retval = rt2x00lib_probe_dev(rt2x00dev);
  73. if (retval)
  74. goto exit_free_reg;
  75. return 0;
  76. exit_free_reg:
  77. rt2x00soc_free_reg(rt2x00dev);
  78. exit_free_device:
  79. ieee80211_free_hw(hw);
  80. return retval;
  81. }
  82. EXPORT_SYMBOL_GPL(rt2x00soc_probe);
  83. int rt2x00soc_remove(struct platform_device *pdev)
  84. {
  85. struct ieee80211_hw *hw = platform_get_drvdata(pdev);
  86. struct rt2x00_dev *rt2x00dev = hw->priv;
  87. /*
  88. * Free all allocated data.
  89. */
  90. rt2x00lib_remove_dev(rt2x00dev);
  91. rt2x00soc_free_reg(rt2x00dev);
  92. ieee80211_free_hw(hw);
  93. return 0;
  94. }
  95. EXPORT_SYMBOL_GPL(rt2x00soc_remove);
  96. #ifdef CONFIG_PM
  97. int rt2x00soc_suspend(struct platform_device *pdev, pm_message_t state)
  98. {
  99. struct ieee80211_hw *hw = platform_get_drvdata(pdev);
  100. struct rt2x00_dev *rt2x00dev = hw->priv;
  101. return rt2x00lib_suspend(rt2x00dev);
  102. }
  103. EXPORT_SYMBOL_GPL(rt2x00soc_suspend);
  104. int rt2x00soc_resume(struct platform_device *pdev)
  105. {
  106. struct ieee80211_hw *hw = platform_get_drvdata(pdev);
  107. struct rt2x00_dev *rt2x00dev = hw->priv;
  108. return rt2x00lib_resume(rt2x00dev);
  109. }
  110. EXPORT_SYMBOL_GPL(rt2x00soc_resume);
  111. #endif /* CONFIG_PM */
  112. /*
  113. * rt2x00soc module information.
  114. */
  115. MODULE_AUTHOR(DRV_PROJECT);
  116. MODULE_VERSION(DRV_VERSION);
  117. MODULE_DESCRIPTION("rt2x00 soc library");
  118. MODULE_LICENSE("GPL");