552-ahb_of.patch 8.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. --- a/drivers/net/wireless/ath/ath9k/ahb.c
  2. +++ b/drivers/net/wireless/ath/ath9k/ahb.c
  3. @@ -20,7 +20,15 @@
  4. #include <linux/platform_device.h>
  5. #include <linux/module.h>
  6. #include <linux/mod_devicetable.h>
  7. +#include <linux/of_device.h>
  8. #include "ath9k.h"
  9. +#include <linux/ath9k_platform.h>
  10. +
  11. +#ifdef CONFIG_OF
  12. +#include <asm/mach-ath79/ath79.h>
  13. +#include <asm/mach-ath79/ar71xx_regs.h>
  14. +#include <linux/mtd/mtd.h>
  15. +#endif
  16. static const struct platform_device_id ath9k_platform_id_table[] = {
  17. {
  18. @@ -69,6 +77,242 @@ static const struct ath_bus_ops ath_ahb_
  19. .eeprom_read = ath_ahb_eeprom_read,
  20. };
  21. +#ifdef CONFIG_OF
  22. +
  23. +#define QCA955X_DDR_CTL_CONFIG 0x108
  24. +#define QCA955X_DDR_CTL_CONFIG_ACT_WMAC BIT(23)
  25. +
  26. +static int of_get_wifi_cal(struct device_node *np, struct ath9k_platform_data *pdata)
  27. +{
  28. +#ifdef CONFIG_MTD
  29. + struct device_node *mtd_np = NULL;
  30. + size_t retlen;
  31. + int size, ret;
  32. + struct mtd_info *mtd;
  33. + const char *part;
  34. + const __be32 *list;
  35. + phandle phandle;
  36. +
  37. + list = of_get_property(np, "mtd-cal-data", &size);
  38. + if (!list)
  39. + return 0;
  40. +
  41. + if (size != (2 * sizeof(*list)))
  42. + return 1;
  43. +
  44. + phandle = be32_to_cpup(list++);
  45. + if (phandle)
  46. + mtd_np = of_find_node_by_phandle(phandle);
  47. +
  48. + if (!mtd_np)
  49. + return 1;
  50. +
  51. + part = of_get_property(mtd_np, "label", NULL);
  52. + if (!part)
  53. + part = mtd_np->name;
  54. +
  55. + mtd = get_mtd_device_nm(part);
  56. + if (IS_ERR(mtd))
  57. + return 1;
  58. +
  59. + ret = mtd_read(mtd, be32_to_cpup(list), sizeof(pdata->eeprom_data),
  60. + &retlen, (u8*)pdata->eeprom_data);
  61. + put_mtd_device(mtd);
  62. +
  63. +#endif
  64. + return 0;
  65. +}
  66. +
  67. +static int ar913x_wmac_reset(void)
  68. +{
  69. + ath79_device_reset_set(AR913X_RESET_AMBA2WMAC);
  70. + mdelay(10);
  71. +
  72. + ath79_device_reset_clear(AR913X_RESET_AMBA2WMAC);
  73. + mdelay(10);
  74. +
  75. + return 0;
  76. +}
  77. +
  78. +static int ar933x_wmac_reset(void)
  79. +{
  80. + int retries = 20;
  81. +
  82. + ath79_device_reset_set(AR933X_RESET_WMAC);
  83. + ath79_device_reset_clear(AR933X_RESET_WMAC);
  84. +
  85. + while (1) {
  86. + u32 bootstrap;
  87. +
  88. + bootstrap = ath79_reset_rr(AR933X_RESET_REG_BOOTSTRAP);
  89. + if ((bootstrap & AR933X_BOOTSTRAP_EEPBUSY) == 0)
  90. + return 0;
  91. +
  92. + if (retries-- == 0)
  93. + break;
  94. +
  95. + udelay(10000);
  96. + }
  97. +
  98. + pr_err("ar933x: WMAC reset timed out");
  99. + return -ETIMEDOUT;
  100. +}
  101. +
  102. +static int qca955x_wmac_reset(void)
  103. +{
  104. + int i;
  105. +
  106. + /* Try to wait for WMAC DDR activity to stop */
  107. + for (i = 0; i < 10; i++) {
  108. + if (!(__raw_readl(ath79_ddr_base + QCA955X_DDR_CTL_CONFIG) &
  109. + QCA955X_DDR_CTL_CONFIG_ACT_WMAC))
  110. + break;
  111. +
  112. + udelay(10);
  113. + }
  114. +
  115. + ath79_device_reset_set(QCA955X_RESET_RTC);
  116. + udelay(10);
  117. + ath79_device_reset_clear(QCA955X_RESET_RTC);
  118. + udelay(10);
  119. +
  120. + return 0;
  121. +}
  122. +
  123. +enum {
  124. + AR913X_WMAC = 0,
  125. + AR933X_WMAC,
  126. + AR934X_WMAC,
  127. + QCA953X_WMAC,
  128. + QCA955X_WMAC,
  129. + QCA956X_WMAC,
  130. +};
  131. +
  132. +static int ar9330_get_soc_revision(void)
  133. +{
  134. + if (ath79_soc_rev == 1)
  135. + return ath79_soc_rev;
  136. +
  137. + return 0;
  138. +}
  139. +
  140. +static int ath79_get_soc_revision(void)
  141. +{
  142. + return ath79_soc_rev;
  143. +}
  144. +
  145. +static const struct of_ath_ahb_data {
  146. + u16 dev_id;
  147. + u32 bootstrap_reg;
  148. + u32 bootstrap_ref;
  149. +
  150. + int (*soc_revision)(void);
  151. + int (*wmac_reset)(void);
  152. +} of_ath_ahb_data[] = {
  153. + [AR913X_WMAC] = {
  154. + .dev_id = AR5416_AR9100_DEVID,
  155. + .wmac_reset = ar913x_wmac_reset,
  156. +
  157. + },
  158. + [AR933X_WMAC] = {
  159. + .dev_id = AR9300_DEVID_AR9330,
  160. + .bootstrap_reg = AR933X_RESET_REG_BOOTSTRAP,
  161. + .bootstrap_ref = AR933X_BOOTSTRAP_REF_CLK_40,
  162. + .soc_revision = ar9330_get_soc_revision,
  163. + .wmac_reset = ar933x_wmac_reset,
  164. + },
  165. + [AR934X_WMAC] = {
  166. + .dev_id = AR9300_DEVID_AR9340,
  167. + .bootstrap_reg = AR934X_RESET_REG_BOOTSTRAP,
  168. + .bootstrap_ref = AR934X_BOOTSTRAP_REF_CLK_40,
  169. + .soc_revision = ath79_get_soc_revision,
  170. + },
  171. + [QCA953X_WMAC] = {
  172. + .dev_id = AR9300_DEVID_AR953X,
  173. + .bootstrap_reg = QCA953X_RESET_REG_BOOTSTRAP,
  174. + .bootstrap_ref = QCA953X_BOOTSTRAP_REF_CLK_40,
  175. + .soc_revision = ath79_get_soc_revision,
  176. + },
  177. + [QCA955X_WMAC] = {
  178. + .dev_id = AR9300_DEVID_QCA955X,
  179. + .bootstrap_reg = QCA955X_RESET_REG_BOOTSTRAP,
  180. + .bootstrap_ref = QCA955X_BOOTSTRAP_REF_CLK_40,
  181. + .wmac_reset = qca955x_wmac_reset,
  182. + },
  183. + [QCA956X_WMAC] = {
  184. + .dev_id = AR9300_DEVID_QCA956X,
  185. + .bootstrap_reg = QCA956X_RESET_REG_BOOTSTRAP,
  186. + .bootstrap_ref = QCA956X_BOOTSTRAP_REF_CLK_40,
  187. + .soc_revision = ath79_get_soc_revision,
  188. + },
  189. +};
  190. +
  191. +const struct of_device_id of_ath_ahb_match[] = {
  192. + { .compatible = "qca,ar9130-wmac", .data = &of_ath_ahb_data[AR913X_WMAC] },
  193. + { .compatible = "qca,ar9330-wmac", .data = &of_ath_ahb_data[AR933X_WMAC] },
  194. + { .compatible = "qca,ar9340-wmac", .data = &of_ath_ahb_data[AR934X_WMAC] },
  195. + { .compatible = "qca,qca9530-wmac", .data = &of_ath_ahb_data[QCA953X_WMAC] },
  196. + { .compatible = "qca,qca9550-wmac", .data = &of_ath_ahb_data[QCA955X_WMAC] },
  197. + { .compatible = "qca,qca9560-wmac", .data = &of_ath_ahb_data[QCA956X_WMAC] },
  198. + {},
  199. +};
  200. +MODULE_DEVICE_TABLE(of, of_ath_ahb_match);
  201. +
  202. +static int of_ath_ahb_probe(struct platform_device *pdev)
  203. +{
  204. + struct ath9k_platform_data *pdata;
  205. + const struct of_device_id *match;
  206. + const struct of_ath_ahb_data *data;
  207. + u8 led_pin;
  208. +
  209. + match = of_match_device(of_ath_ahb_match, &pdev->dev);
  210. + data = (const struct of_ath_ahb_data *)match->data;
  211. +
  212. + pdata = dev_get_platdata(&pdev->dev);
  213. +
  214. + if (!of_property_read_u8(pdev->dev.of_node, "qca,led-pin", &led_pin))
  215. + pdata->led_pin = led_pin;
  216. + else
  217. + pdata->led_pin = -1;
  218. +
  219. + if (of_property_read_bool(pdev->dev.of_node, "qca,disable-2ghz"))
  220. + pdata->disable_2ghz = true;
  221. +
  222. + if (of_property_read_bool(pdev->dev.of_node, "qca,disable-5ghz"))
  223. + pdata->disable_5ghz = true;
  224. +
  225. + if (of_property_read_bool(pdev->dev.of_node, "qca,tx-gain-buffalo"))
  226. + pdata->tx_gain_buffalo = true;
  227. +
  228. + if (data->wmac_reset) {
  229. + data->wmac_reset();
  230. + pdata->external_reset = data->wmac_reset;
  231. + }
  232. +
  233. + if (data->dev_id == AR9300_DEVID_AR953X) {
  234. + /*
  235. + * QCA953x only supports 25MHz refclk.
  236. + * Some vendors have an invalid bootstrap option
  237. + * set, which would break the WMAC here.
  238. + */
  239. + pdata->is_clk_25mhz = true;
  240. + } else if (data->bootstrap_reg && data->bootstrap_ref) {
  241. + u32 t = ath79_reset_rr(data->bootstrap_reg);
  242. + if (t & data->bootstrap_ref)
  243. + pdata->is_clk_25mhz = false;
  244. + else
  245. + pdata->is_clk_25mhz = true;
  246. + }
  247. +
  248. + pdata->get_mac_revision = data->soc_revision;
  249. +
  250. + if (of_get_wifi_cal(pdev->dev.of_node, pdata))
  251. + dev_err(&pdev->dev, "failed to load calibration data from mtd device\n");
  252. +
  253. + return data->dev_id;
  254. +}
  255. +#endif
  256. +
  257. static int ath_ahb_probe(struct platform_device *pdev)
  258. {
  259. void __iomem *mem;
  260. @@ -80,6 +324,17 @@ static int ath_ahb_probe(struct platform
  261. int ret = 0;
  262. struct ath_hw *ah;
  263. char hw_name[64];
  264. + u16 dev_id;
  265. +
  266. + if (id)
  267. + dev_id = id->driver_data;
  268. +
  269. +#ifdef CONFIG_OF
  270. + if (pdev->dev.of_node)
  271. + pdev->dev.platform_data = devm_kzalloc(&pdev->dev,
  272. + sizeof(struct ath9k_platform_data),
  273. + GFP_KERNEL);
  274. +#endif
  275. if (!dev_get_platdata(&pdev->dev)) {
  276. dev_err(&pdev->dev, "no platform data specified\n");
  277. @@ -122,13 +377,16 @@ static int ath_ahb_probe(struct platform
  278. sc->mem = mem;
  279. sc->irq = irq;
  280. +#ifdef CONFIG_OF
  281. + dev_id = of_ath_ahb_probe(pdev);
  282. +#endif
  283. ret = request_irq(irq, ath_isr, IRQF_SHARED, "ath9k", sc);
  284. if (ret) {
  285. dev_err(&pdev->dev, "request_irq failed\n");
  286. goto err_free_hw;
  287. }
  288. - ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
  289. + ret = ath9k_init_device(dev_id, sc, &ath_ahb_bus_ops);
  290. if (ret) {
  291. dev_err(&pdev->dev, "failed to initialize device\n");
  292. goto err_irq;
  293. @@ -159,6 +417,9 @@ static int ath_ahb_remove(struct platfor
  294. free_irq(sc->irq, sc);
  295. ieee80211_free_hw(sc->hw);
  296. }
  297. +#ifdef CONFIG_OF
  298. + pdev->dev.platform_data = NULL;
  299. +#endif
  300. return 0;
  301. }
  302. @@ -168,6 +429,9 @@ static struct platform_driver ath_ahb_dr
  303. .remove = ath_ahb_remove,
  304. .driver = {
  305. .name = "ath9k",
  306. +#ifdef CONFIG_OF
  307. + .of_match_table = of_ath_ahb_match,
  308. +#endif
  309. },
  310. .id_table = ath9k_platform_id_table,
  311. };
  312. --- a/drivers/net/wireless/ath/ath9k/ath9k.h
  313. +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
  314. @@ -25,6 +25,7 @@
  315. #include <linux/time.h>
  316. #include <linux/hw_random.h>
  317. #include <linux/gpio/driver.h>
  318. +#include <linux/reset.h>
  319. #include "common.h"
  320. #include "debug.h"
  321. @@ -1024,6 +1025,9 @@ struct ath_softc {
  322. struct ath_hw *sc_ah;
  323. void __iomem *mem;
  324. int irq;
  325. +#ifdef CONFIG_OF
  326. + struct reset_control *reset;
  327. +#endif
  328. spinlock_t sc_serial_rw;
  329. spinlock_t sc_pm_lock;
  330. spinlock_t sc_pcu_lock;