ahci_sunxi.c 7.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Allwinner sunxi AHCI SATA platform driver
  4. * Copyright 2013 Olliver Schinagl <oliver@schinagl.nl>
  5. * Copyright 2014 Hans de Goede <hdegoede@redhat.com>
  6. *
  7. * based on the AHCI SATA platform driver by Jeff Garzik and Anton Vorontsov
  8. * Based on code from Allwinner Technology Co., Ltd. <www.allwinnertech.com>,
  9. * Daniel Wang <danielwang@allwinnertech.com>
  10. */
  11. #include <linux/ahci_platform.h>
  12. #include <linux/clk.h>
  13. #include <linux/errno.h>
  14. #include <linux/kernel.h>
  15. #include <linux/module.h>
  16. #include <linux/of_device.h>
  17. #include <linux/platform_device.h>
  18. #include <linux/regulator/consumer.h>
  19. #include "ahci.h"
  20. #define DRV_NAME "ahci-sunxi"
  21. /* Insmod parameters */
  22. static bool enable_pmp;
  23. module_param(enable_pmp, bool, 0);
  24. MODULE_PARM_DESC(enable_pmp,
  25. "Enable support for sata port multipliers, only use if you use a pmp!");
  26. #define AHCI_BISTAFR 0x00a0
  27. #define AHCI_BISTCR 0x00a4
  28. #define AHCI_BISTFCTR 0x00a8
  29. #define AHCI_BISTSR 0x00ac
  30. #define AHCI_BISTDECR 0x00b0
  31. #define AHCI_DIAGNR0 0x00b4
  32. #define AHCI_DIAGNR1 0x00b8
  33. #define AHCI_OOBR 0x00bc
  34. #define AHCI_PHYCS0R 0x00c0
  35. #define AHCI_PHYCS1R 0x00c4
  36. #define AHCI_PHYCS2R 0x00c8
  37. #define AHCI_TIMER1MS 0x00e0
  38. #define AHCI_GPARAM1R 0x00e8
  39. #define AHCI_GPARAM2R 0x00ec
  40. #define AHCI_PPARAMR 0x00f0
  41. #define AHCI_TESTR 0x00f4
  42. #define AHCI_VERSIONR 0x00f8
  43. #define AHCI_IDR 0x00fc
  44. #define AHCI_RWCR 0x00fc
  45. #define AHCI_P0DMACR 0x0170
  46. #define AHCI_P0PHYCR 0x0178
  47. #define AHCI_P0PHYSR 0x017c
  48. static void sunxi_clrbits(void __iomem *reg, u32 clr_val)
  49. {
  50. u32 reg_val;
  51. reg_val = readl(reg);
  52. reg_val &= ~(clr_val);
  53. writel(reg_val, reg);
  54. }
  55. static void sunxi_setbits(void __iomem *reg, u32 set_val)
  56. {
  57. u32 reg_val;
  58. reg_val = readl(reg);
  59. reg_val |= set_val;
  60. writel(reg_val, reg);
  61. }
  62. static void sunxi_clrsetbits(void __iomem *reg, u32 clr_val, u32 set_val)
  63. {
  64. u32 reg_val;
  65. reg_val = readl(reg);
  66. reg_val &= ~(clr_val);
  67. reg_val |= set_val;
  68. writel(reg_val, reg);
  69. }
  70. static u32 sunxi_getbits(void __iomem *reg, u8 mask, u8 shift)
  71. {
  72. return (readl(reg) >> shift) & mask;
  73. }
  74. static int ahci_sunxi_phy_init(struct device *dev, void __iomem *reg_base)
  75. {
  76. u32 reg_val;
  77. int timeout;
  78. /* This magic is from the original code */
  79. writel(0, reg_base + AHCI_RWCR);
  80. msleep(5);
  81. sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(19));
  82. sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
  83. (0x7 << 24),
  84. (0x5 << 24) | BIT(23) | BIT(18));
  85. sunxi_clrsetbits(reg_base + AHCI_PHYCS1R,
  86. (0x3 << 16) | (0x1f << 8) | (0x3 << 6),
  87. (0x2 << 16) | (0x6 << 8) | (0x2 << 6));
  88. sunxi_setbits(reg_base + AHCI_PHYCS1R, BIT(28) | BIT(15));
  89. sunxi_clrbits(reg_base + AHCI_PHYCS1R, BIT(19));
  90. sunxi_clrsetbits(reg_base + AHCI_PHYCS0R,
  91. (0x7 << 20), (0x3 << 20));
  92. sunxi_clrsetbits(reg_base + AHCI_PHYCS2R,
  93. (0x1f << 5), (0x19 << 5));
  94. msleep(5);
  95. sunxi_setbits(reg_base + AHCI_PHYCS0R, (0x1 << 19));
  96. timeout = 250; /* Power up takes aprox 50 us */
  97. do {
  98. reg_val = sunxi_getbits(reg_base + AHCI_PHYCS0R, 0x7, 28);
  99. if (reg_val == 0x02)
  100. break;
  101. if (--timeout == 0) {
  102. dev_err(dev, "PHY power up failed.\n");
  103. return -EIO;
  104. }
  105. udelay(1);
  106. } while (1);
  107. sunxi_setbits(reg_base + AHCI_PHYCS2R, (0x1 << 24));
  108. timeout = 100; /* Calibration takes aprox 10 us */
  109. do {
  110. reg_val = sunxi_getbits(reg_base + AHCI_PHYCS2R, 0x1, 24);
  111. if (reg_val == 0x00)
  112. break;
  113. if (--timeout == 0) {
  114. dev_err(dev, "PHY calibration failed.\n");
  115. return -EIO;
  116. }
  117. udelay(1);
  118. } while (1);
  119. msleep(15);
  120. writel(0x7, reg_base + AHCI_RWCR);
  121. return 0;
  122. }
  123. static void ahci_sunxi_start_engine(struct ata_port *ap)
  124. {
  125. void __iomem *port_mmio = ahci_port_base(ap);
  126. struct ahci_host_priv *hpriv = ap->host->private_data;
  127. /* Setup DMA before DMA start
  128. *
  129. * NOTE: A similar SoC with SATA/AHCI by Texas Instruments documents
  130. * this Vendor Specific Port (P0DMACR, aka PxDMACR) in its
  131. * User's Guide document (TMS320C674x/OMAP-L1x Processor
  132. * Serial ATA (SATA) Controller, Literature Number: SPRUGJ8C,
  133. * March 2011, Chapter 4.33 Port DMA Control Register (P0DMACR),
  134. * p.68, https://www.ti.com/lit/ug/sprugj8c/sprugj8c.pdf)
  135. * as equivalent to the following struct:
  136. *
  137. * struct AHCI_P0DMACR_t
  138. * {
  139. * unsigned TXTS : 4;
  140. * unsigned RXTS : 4;
  141. * unsigned TXABL : 4;
  142. * unsigned RXABL : 4;
  143. * unsigned Reserved : 16;
  144. * };
  145. *
  146. * TXTS: Transmit Transaction Size (TX_TRANSACTION_SIZE).
  147. * This field defines the DMA transaction size in DWORDs for
  148. * transmit (system bus read, device write) operation. [...]
  149. *
  150. * RXTS: Receive Transaction Size (RX_TRANSACTION_SIZE).
  151. * This field defines the Port DMA transaction size in DWORDs
  152. * for receive (system bus write, device read) operation. [...]
  153. *
  154. * TXABL: Transmit Burst Limit.
  155. * This field allows software to limit the VBUSP master read
  156. * burst size. [...]
  157. *
  158. * RXABL: Receive Burst Limit.
  159. * Allows software to limit the VBUSP master write burst
  160. * size. [...]
  161. *
  162. * Reserved: Reserved.
  163. *
  164. *
  165. * NOTE: According to the above document, the following alternative
  166. * to the code below could perhaps be a better option
  167. * (or preparation) for possible further improvements later:
  168. * sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ffff,
  169. * 0x00000033);
  170. */
  171. sunxi_clrsetbits(hpriv->mmio + AHCI_P0DMACR, 0x0000ffff, 0x00004433);
  172. /* Start DMA */
  173. sunxi_setbits(port_mmio + PORT_CMD, PORT_CMD_START);
  174. }
  175. static const struct ata_port_info ahci_sunxi_port_info = {
  176. .flags = AHCI_FLAG_COMMON | ATA_FLAG_NCQ | ATA_FLAG_NO_DIPM,
  177. .pio_mask = ATA_PIO4,
  178. .udma_mask = ATA_UDMA6,
  179. .port_ops = &ahci_platform_ops,
  180. };
  181. static struct scsi_host_template ahci_platform_sht = {
  182. AHCI_SHT(DRV_NAME),
  183. };
  184. static int ahci_sunxi_probe(struct platform_device *pdev)
  185. {
  186. struct device *dev = &pdev->dev;
  187. struct ahci_host_priv *hpriv;
  188. int rc;
  189. hpriv = ahci_platform_get_resources(pdev, AHCI_PLATFORM_GET_RESETS);
  190. if (IS_ERR(hpriv))
  191. return PTR_ERR(hpriv);
  192. hpriv->start_engine = ahci_sunxi_start_engine;
  193. rc = ahci_platform_enable_resources(hpriv);
  194. if (rc)
  195. return rc;
  196. rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
  197. if (rc)
  198. goto disable_resources;
  199. hpriv->flags = AHCI_HFLAG_32BIT_ONLY | AHCI_HFLAG_NO_MSI |
  200. AHCI_HFLAG_YES_NCQ;
  201. /*
  202. * The sunxi sata controller seems to be unable to successfully do a
  203. * soft reset if no pmp is attached, so disable pmp use unless
  204. * requested, otherwise directly attached disks do not work.
  205. */
  206. if (!enable_pmp)
  207. hpriv->flags |= AHCI_HFLAG_NO_PMP;
  208. rc = ahci_platform_init_host(pdev, hpriv, &ahci_sunxi_port_info,
  209. &ahci_platform_sht);
  210. if (rc)
  211. goto disable_resources;
  212. return 0;
  213. disable_resources:
  214. ahci_platform_disable_resources(hpriv);
  215. return rc;
  216. }
  217. #ifdef CONFIG_PM_SLEEP
  218. static int ahci_sunxi_resume(struct device *dev)
  219. {
  220. struct ata_host *host = dev_get_drvdata(dev);
  221. struct ahci_host_priv *hpriv = host->private_data;
  222. int rc;
  223. rc = ahci_platform_enable_resources(hpriv);
  224. if (rc)
  225. return rc;
  226. rc = ahci_sunxi_phy_init(dev, hpriv->mmio);
  227. if (rc)
  228. goto disable_resources;
  229. rc = ahci_platform_resume_host(dev);
  230. if (rc)
  231. goto disable_resources;
  232. return 0;
  233. disable_resources:
  234. ahci_platform_disable_resources(hpriv);
  235. return rc;
  236. }
  237. #endif
  238. static SIMPLE_DEV_PM_OPS(ahci_sunxi_pm_ops, ahci_platform_suspend,
  239. ahci_sunxi_resume);
  240. static const struct of_device_id ahci_sunxi_of_match[] = {
  241. { .compatible = "allwinner,sun4i-a10-ahci", },
  242. { .compatible = "allwinner,sun8i-r40-ahci", },
  243. { },
  244. };
  245. MODULE_DEVICE_TABLE(of, ahci_sunxi_of_match);
  246. static struct platform_driver ahci_sunxi_driver = {
  247. .probe = ahci_sunxi_probe,
  248. .remove = ata_platform_remove_one,
  249. .driver = {
  250. .name = DRV_NAME,
  251. .of_match_table = ahci_sunxi_of_match,
  252. .pm = &ahci_sunxi_pm_ops,
  253. },
  254. };
  255. module_platform_driver(ahci_sunxi_driver);
  256. MODULE_DESCRIPTION("Allwinner sunxi AHCI SATA driver");
  257. MODULE_AUTHOR("Olliver Schinagl <oliver@schinagl.nl>");
  258. MODULE_LICENSE("GPL");