ahci_brcmstb.c 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. /*
  2. * Broadcom SATA3 AHCI Controller Driver
  3. *
  4. * Copyright © 2009-2015 Broadcom Corporation
  5. *
  6. * This program is free software; you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation; either version 2, or (at your option)
  9. * any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. */
  16. #include <linux/ahci_platform.h>
  17. #include <linux/compiler.h>
  18. #include <linux/device.h>
  19. #include <linux/init.h>
  20. #include <linux/interrupt.h>
  21. #include <linux/io.h>
  22. #include <linux/kernel.h>
  23. #include <linux/libata.h>
  24. #include <linux/module.h>
  25. #include <linux/of.h>
  26. #include <linux/platform_device.h>
  27. #include <linux/string.h>
  28. #include "ahci.h"
  29. #define DRV_NAME "brcm-ahci"
  30. #define SATA_TOP_CTRL_VERSION 0x0
  31. #define SATA_TOP_CTRL_BUS_CTRL 0x4
  32. #define MMIO_ENDIAN_SHIFT 0 /* CPU->AHCI */
  33. #define DMADESC_ENDIAN_SHIFT 2 /* AHCI->DDR */
  34. #define DMADATA_ENDIAN_SHIFT 4 /* AHCI->DDR */
  35. #define PIODATA_ENDIAN_SHIFT 6
  36. #define ENDIAN_SWAP_NONE 0
  37. #define ENDIAN_SWAP_FULL 2
  38. #define OVERRIDE_HWINIT BIT(16)
  39. #define SATA_TOP_CTRL_TP_CTRL 0x8
  40. #define SATA_TOP_CTRL_PHY_CTRL 0xc
  41. #define SATA_TOP_CTRL_PHY_CTRL_1 0x0
  42. #define SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE BIT(14)
  43. #define SATA_TOP_CTRL_PHY_CTRL_2 0x4
  44. #define SATA_TOP_CTRL_2_SW_RST_MDIOREG BIT(0)
  45. #define SATA_TOP_CTRL_2_SW_RST_OOB BIT(1)
  46. #define SATA_TOP_CTRL_2_SW_RST_RX BIT(2)
  47. #define SATA_TOP_CTRL_2_SW_RST_TX BIT(3)
  48. #define SATA_TOP_CTRL_2_PHY_GLOBAL_RESET BIT(14)
  49. #define SATA_TOP_CTRL_PHY_OFFS 0x8
  50. #define SATA_TOP_MAX_PHYS 2
  51. #define SATA_TOP_CTRL_SATA_TP_OUT 0x1c
  52. #define SATA_TOP_CTRL_CLIENT_INIT_CTRL 0x20
  53. /* On big-endian MIPS, buses are reversed to big endian, so switch them back */
  54. #if defined(CONFIG_MIPS) && defined(__BIG_ENDIAN)
  55. #define DATA_ENDIAN 2 /* AHCI->DDR inbound accesses */
  56. #define MMIO_ENDIAN 2 /* CPU->AHCI outbound accesses */
  57. #else
  58. #define DATA_ENDIAN 0
  59. #define MMIO_ENDIAN 0
  60. #endif
  61. #define BUS_CTRL_ENDIAN_CONF \
  62. ((DATA_ENDIAN << DMADATA_ENDIAN_SHIFT) | \
  63. (DATA_ENDIAN << DMADESC_ENDIAN_SHIFT) | \
  64. (MMIO_ENDIAN << MMIO_ENDIAN_SHIFT))
  65. struct brcm_ahci_priv {
  66. struct device *dev;
  67. void __iomem *top_ctrl;
  68. u32 port_mask;
  69. };
  70. static const struct ata_port_info ahci_brcm_port_info = {
  71. .flags = AHCI_FLAG_COMMON,
  72. .pio_mask = ATA_PIO4,
  73. .udma_mask = ATA_UDMA6,
  74. .port_ops = &ahci_platform_ops,
  75. };
  76. static inline u32 brcm_sata_readreg(void __iomem *addr)
  77. {
  78. /*
  79. * MIPS endianness is configured by boot strap, which also reverses all
  80. * bus endianness (i.e., big-endian CPU + big endian bus ==> native
  81. * endian I/O).
  82. *
  83. * Other architectures (e.g., ARM) either do not support big endian, or
  84. * else leave I/O in little endian mode.
  85. */
  86. if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
  87. return __raw_readl(addr);
  88. else
  89. return readl_relaxed(addr);
  90. }
  91. static inline void brcm_sata_writereg(u32 val, void __iomem *addr)
  92. {
  93. /* See brcm_sata_readreg() comments */
  94. if (IS_ENABLED(CONFIG_MIPS) && IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
  95. __raw_writel(val, addr);
  96. else
  97. writel_relaxed(val, addr);
  98. }
  99. static void brcm_sata_phy_enable(struct brcm_ahci_priv *priv, int port)
  100. {
  101. void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
  102. (port * SATA_TOP_CTRL_PHY_OFFS);
  103. void __iomem *p;
  104. u32 reg;
  105. /* clear PHY_DEFAULT_POWER_STATE */
  106. p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
  107. reg = brcm_sata_readreg(p);
  108. reg &= ~SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;
  109. brcm_sata_writereg(reg, p);
  110. /* reset the PHY digital logic */
  111. p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
  112. reg = brcm_sata_readreg(p);
  113. reg &= ~(SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |
  114. SATA_TOP_CTRL_2_SW_RST_RX);
  115. reg |= SATA_TOP_CTRL_2_SW_RST_TX;
  116. brcm_sata_writereg(reg, p);
  117. reg = brcm_sata_readreg(p);
  118. reg |= SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;
  119. brcm_sata_writereg(reg, p);
  120. reg = brcm_sata_readreg(p);
  121. reg &= ~SATA_TOP_CTRL_2_PHY_GLOBAL_RESET;
  122. brcm_sata_writereg(reg, p);
  123. (void)brcm_sata_readreg(p);
  124. }
  125. static void brcm_sata_phy_disable(struct brcm_ahci_priv *priv, int port)
  126. {
  127. void __iomem *phyctrl = priv->top_ctrl + SATA_TOP_CTRL_PHY_CTRL +
  128. (port * SATA_TOP_CTRL_PHY_OFFS);
  129. void __iomem *p;
  130. u32 reg;
  131. /* power-off the PHY digital logic */
  132. p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_2;
  133. reg = brcm_sata_readreg(p);
  134. reg |= (SATA_TOP_CTRL_2_SW_RST_MDIOREG | SATA_TOP_CTRL_2_SW_RST_OOB |
  135. SATA_TOP_CTRL_2_SW_RST_RX | SATA_TOP_CTRL_2_SW_RST_TX |
  136. SATA_TOP_CTRL_2_PHY_GLOBAL_RESET);
  137. brcm_sata_writereg(reg, p);
  138. /* set PHY_DEFAULT_POWER_STATE */
  139. p = phyctrl + SATA_TOP_CTRL_PHY_CTRL_1;
  140. reg = brcm_sata_readreg(p);
  141. reg |= SATA_TOP_CTRL_1_PHY_DEFAULT_POWER_STATE;
  142. brcm_sata_writereg(reg, p);
  143. }
  144. static void brcm_sata_phys_enable(struct brcm_ahci_priv *priv)
  145. {
  146. int i;
  147. for (i = 0; i < SATA_TOP_MAX_PHYS; i++)
  148. if (priv->port_mask & BIT(i))
  149. brcm_sata_phy_enable(priv, i);
  150. }
  151. static void brcm_sata_phys_disable(struct brcm_ahci_priv *priv)
  152. {
  153. int i;
  154. for (i = 0; i < SATA_TOP_MAX_PHYS; i++)
  155. if (priv->port_mask & BIT(i))
  156. brcm_sata_phy_disable(priv, i);
  157. }
  158. static u32 brcm_ahci_get_portmask(struct platform_device *pdev,
  159. struct brcm_ahci_priv *priv)
  160. {
  161. void __iomem *ahci;
  162. struct resource *res;
  163. u32 impl;
  164. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ahci");
  165. ahci = devm_ioremap_resource(&pdev->dev, res);
  166. if (IS_ERR(ahci))
  167. return 0;
  168. impl = readl(ahci + HOST_PORTS_IMPL);
  169. if (fls(impl) > SATA_TOP_MAX_PHYS)
  170. dev_warn(priv->dev, "warning: more ports than PHYs (%#x)\n",
  171. impl);
  172. else if (!impl)
  173. dev_info(priv->dev, "no ports found\n");
  174. devm_iounmap(&pdev->dev, ahci);
  175. devm_release_mem_region(&pdev->dev, res->start, resource_size(res));
  176. return impl;
  177. }
  178. static void brcm_sata_init(struct brcm_ahci_priv *priv)
  179. {
  180. /* Configure endianness */
  181. brcm_sata_writereg(BUS_CTRL_ENDIAN_CONF,
  182. priv->top_ctrl + SATA_TOP_CTRL_BUS_CTRL);
  183. }
  184. #ifdef CONFIG_PM_SLEEP
  185. static int brcm_ahci_suspend(struct device *dev)
  186. {
  187. struct ata_host *host = dev_get_drvdata(dev);
  188. struct ahci_host_priv *hpriv = host->private_data;
  189. struct brcm_ahci_priv *priv = hpriv->plat_data;
  190. int ret;
  191. ret = ahci_platform_suspend(dev);
  192. brcm_sata_phys_disable(priv);
  193. return ret;
  194. }
  195. static int brcm_ahci_resume(struct device *dev)
  196. {
  197. struct ata_host *host = dev_get_drvdata(dev);
  198. struct ahci_host_priv *hpriv = host->private_data;
  199. struct brcm_ahci_priv *priv = hpriv->plat_data;
  200. brcm_sata_init(priv);
  201. brcm_sata_phys_enable(priv);
  202. return ahci_platform_resume(dev);
  203. }
  204. #endif
  205. static struct scsi_host_template ahci_platform_sht = {
  206. AHCI_SHT(DRV_NAME),
  207. };
  208. static int brcm_ahci_probe(struct platform_device *pdev)
  209. {
  210. struct device *dev = &pdev->dev;
  211. struct brcm_ahci_priv *priv;
  212. struct ahci_host_priv *hpriv;
  213. struct resource *res;
  214. int ret;
  215. priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
  216. if (!priv)
  217. return -ENOMEM;
  218. priv->dev = dev;
  219. res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "top-ctrl");
  220. priv->top_ctrl = devm_ioremap_resource(dev, res);
  221. if (IS_ERR(priv->top_ctrl))
  222. return PTR_ERR(priv->top_ctrl);
  223. brcm_sata_init(priv);
  224. priv->port_mask = brcm_ahci_get_portmask(pdev, priv);
  225. if (!priv->port_mask)
  226. return -ENODEV;
  227. brcm_sata_phys_enable(priv);
  228. hpriv = ahci_platform_get_resources(pdev);
  229. if (IS_ERR(hpriv))
  230. return PTR_ERR(hpriv);
  231. hpriv->plat_data = priv;
  232. ret = ahci_platform_enable_resources(hpriv);
  233. if (ret)
  234. return ret;
  235. ret = ahci_platform_init_host(pdev, hpriv, &ahci_brcm_port_info,
  236. &ahci_platform_sht);
  237. if (ret)
  238. return ret;
  239. dev_info(dev, "Broadcom AHCI SATA3 registered\n");
  240. return 0;
  241. }
  242. static int brcm_ahci_remove(struct platform_device *pdev)
  243. {
  244. struct ata_host *host = dev_get_drvdata(&pdev->dev);
  245. struct ahci_host_priv *hpriv = host->private_data;
  246. struct brcm_ahci_priv *priv = hpriv->plat_data;
  247. int ret;
  248. ret = ata_platform_remove_one(pdev);
  249. if (ret)
  250. return ret;
  251. brcm_sata_phys_disable(priv);
  252. return 0;
  253. }
  254. static const struct of_device_id ahci_of_match[] = {
  255. {.compatible = "brcm,bcm7445-ahci"},
  256. {},
  257. };
  258. MODULE_DEVICE_TABLE(of, ahci_of_match);
  259. static SIMPLE_DEV_PM_OPS(ahci_brcm_pm_ops, brcm_ahci_suspend, brcm_ahci_resume);
  260. static struct platform_driver brcm_ahci_driver = {
  261. .probe = brcm_ahci_probe,
  262. .remove = brcm_ahci_remove,
  263. .driver = {
  264. .name = DRV_NAME,
  265. .of_match_table = ahci_of_match,
  266. .pm = &ahci_brcm_pm_ops,
  267. },
  268. };
  269. module_platform_driver(brcm_ahci_driver);
  270. MODULE_DESCRIPTION("Broadcom SATA3 AHCI Controller Driver");
  271. MODULE_AUTHOR("Brian Norris");
  272. MODULE_LICENSE("GPL");
  273. MODULE_ALIAS("platform:sata-brcmstb");