_dinsdale

sys/arm/freescal/imx/imx6_ahci.c

Jul 19th, 2017
205
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.66 KB | None | 0 0
  1. /*-
  2. * Copyright (c) 2017 Rogiel Sulzbach <rogiel@allogica.com>
  3. * All rights reserved.
  4. *
  5. * Redistribution and use in source and binary forms, with or without
  6. * modification, are permitted provided that the following conditions
  7. * are met:
  8. * 1. Redistributions of source code must retain the above copyright
  9. * notice, this list of conditions and the following disclaimer.
  10. * 2. Redistributions in binary form must reproduce the above copyright
  11. * notice, this list of conditions and the following disclaimer in the
  12. * documentation and/or other materials provided with the distribution.
  13. *
  14. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  15. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  18. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  19. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  20. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  21. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  22. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  23. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  24. * SUCH DAMAGE.
  25. */
  26.  
  27. #include <sys/cdefs.h>
  28.  
  29. __FBSDID("$FreeBSD$");
  30.  
  31. #include <sys/param.h>
  32. #include <sys/systm.h>
  33. #include <sys/bus.h>
  34. #include <sys/rman.h>
  35. #include <sys/kernel.h>
  36. #include <sys/module.h>
  37.  
  38. #include <machine/bus.h>
  39. #include <dev/ofw/ofw_bus.h>
  40. #include <dev/ofw/ofw_bus_subr.h>
  41.  
  42. #include <dev/ahci/ahci.h>
  43. #include <arm/freescale/imx/imx_iomuxreg.h>
  44. #include <arm/freescale/imx/imx_iomuxvar.h>
  45. #include <arm/freescale/imx/imx_ccmvar.h>
  46. #include <arm/freescale/imx/imx6_ccmvar.h>
  47.  
  48. #define SATA_P0PHYCR 0x00000178
  49. #define SATA_P0PHYCR_CR_READ (1 << 19)
  50. #define SATA_P0PHYCR_CR_WRITE (1 << 18)
  51. #define SATA_P0PHYCR_CR_CAP_DATA (1 << 17)
  52. #define SATA_P0PHYCR_CR_CAP_ADDR (1 << 16)
  53. #define SATA_P0PHYCR_CR_DATA_IN(v) ((v) & 0xffff)
  54. #define SATA_P0PHYSR 0x0000017c
  55. #define SATA_P0PHYSR_CR_ACK (1 << 18)
  56. #define SATA_P0PHYSR_CR_DATA_OUT(v) ((v) & 0xffff)
  57.  
  58. #define SATA_TIMER1MS 0x000000e0
  59.  
  60. /* phy registers */
  61. #define SATA_PHY_CLOCK_RESET 0x7f3f
  62. #define SATA_PHY_CLOCK_RESET_RST (1 << 0)
  63.  
  64. #define SATA_PHY_LANE0_OUT_STAT 0x2003
  65. #define SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE (1 << 1)
  66.  
  67. //imx6_ahci_phy_ctrl(struct ahci_controller* sc, uint32_t bitmask, int on)
  68. static int
  69. imx6_ahci_phy_ctrl(struct ahci_controller* sc, uint32_t bitmask, bool on)
  70. {
  71. uint32_t v;
  72. int timeout;
  73.  
  74. v = ATA_INL(sc->r_mem, SATA_P0PHYCR);
  75. if (on) {
  76. v |= bitmask;
  77. } else {
  78. v &= ~bitmask;
  79. }
  80. ATA_OUTL(sc->r_mem, SATA_P0PHYCR, v);
  81.  
  82. for (timeout = 5000; timeout > 0; --timeout) {
  83. v = ATA_INL(sc->r_mem, SATA_P0PHYSR);
  84. //if (!!(v & SATA_P0PHYSR_CR_ACK) == !!on) {
  85. if ((v & SATA_P0PHYSR_CR_ACK) == on) {
  86. break;
  87. }
  88. DELAY(100);
  89. }
  90.  
  91. if(timeout > 0) {
  92. return 0;
  93. }
  94.  
  95. return ETIMEDOUT;
  96. }
  97.  
  98. static int
  99. imx6_ahci_phy_addr(struct ahci_controller* sc, uint32_t addr)
  100. {
  101. int error;
  102.  
  103. DELAY(100);
  104. ATA_OUTL(sc->r_mem, SATA_P0PHYCR, addr);
  105.  
  106. error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, true);
  107. if (error != 0) {
  108. device_printf(sc->dev, "%s: timeout on SATA_P0PHYCR_CR_CAP_ADDR=1\n", __FUNCTION__);
  109. return error;
  110. }
  111.  
  112. error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, false);
  113. if (error != 0) {
  114. device_printf(sc->dev, "%s: timeout on SATA_P0PHYCR_CR_CAP_ADDR=0\n", __FUNCTION__);
  115. return error;
  116. }
  117.  
  118. return 0;
  119. }
  120.  
  121. static int
  122. imx6_ahci_phy_write(struct ahci_controller* sc, uint32_t addr,
  123. uint16_t data)
  124. {
  125. int error;
  126.  
  127. error = imx6_ahci_phy_addr(sc, addr);
  128. if (error != 0) {
  129. device_printf(sc->dev, "%s: error on imx6_ahci_phy_addr\n", __FUNCTION__);
  130. return error;
  131. }
  132.  
  133. ATA_OUTL(sc->r_mem, SATA_P0PHYCR, data);
  134.  
  135. error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, true);
  136. if (error != 0) {
  137. device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_CAP_DATA=1\n", __FUNCTION__);
  138. return error;
  139. }
  140. if (imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, false) != 0) {
  141. device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_CAP_DATA=0\n", __FUNCTION__);
  142. return error;
  143. }
  144.  
  145. if ((addr == SATA_PHY_CLOCK_RESET) && data) {
  146. /* we can't check ACK after RESET */
  147. ATA_OUTL(sc->r_mem, SATA_P0PHYCR,
  148. SATA_P0PHYCR_CR_DATA_IN(data) | SATA_P0PHYCR_CR_WRITE);
  149. return 0;
  150. }
  151.  
  152. error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, true);
  153. if (error != 0) {
  154. device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_WRITE=1\n", __FUNCTION__);
  155. return error;
  156. }
  157.  
  158. error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, false);
  159. if (error != 0) {
  160. device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_WRITE=0\n", __FUNCTION__);
  161. return error;
  162. }
  163.  
  164. return 0;
  165. }
  166.  
  167. static int
  168. imx6_ahci_phy_read(struct ahci_controller* sc, uint32_t addr)
  169. {
  170. int error;
  171. uint32_t v;
  172.  
  173. error = imx6_ahci_phy_addr(sc, addr);
  174. if (error != 0) {
  175. device_printf(sc->dev, "%s: error on imx6_ahci_phy_addr\n", __FUNCTION__);
  176. return error;
  177. }
  178.  
  179. error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, true);
  180. if (error != 0) {
  181. device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_READ=1\n", __FUNCTION__);
  182. return error;
  183. }
  184.  
  185. v = ATA_INL(sc->r_mem, SATA_P0PHYSR);
  186.  
  187. error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, false);
  188. if (error != 0) {
  189. device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_READ=0\n", __FUNCTION__);
  190. return error;
  191. }
  192.  
  193. return SATA_P0PHYSR_CR_DATA_OUT(v);
  194. }
  195.  
  196. static int
  197. imx6_ahci_probe(device_t dev)
  198. {
  199. if (!ofw_bus_status_okay(dev))
  200. return (ENXIO);
  201. if (!ofw_bus_is_compatible(dev, "fsl,imx6q-ahci"))
  202. return (ENXIO);
  203.  
  204. device_set_desc(dev, "i.MX6 Integrated AHCI controller");
  205.  
  206. return (BUS_PROBE_DEFAULT);
  207. }
  208.  
  209. static int
  210. imx6_ahci_attach(device_t dev)
  211. {
  212. struct ahci_controller* ctlr;
  213. uint32_t v;
  214. int error, pllstat, timeout;
  215.  
  216. /*
  217. * Init the device PHY
  218. */
  219. ctlr = device_get_softc(dev);
  220.  
  221. error = imx6_ccm_sataphy_enable();
  222. if (error != 0) {
  223. device_printf(dev, "time out resetting AHCI PHY\n");
  224. return error;
  225. }
  226.  
  227. ctlr->vendorid = 0;
  228. ctlr->deviceid = 0;
  229. ctlr->subvendorid = 0;
  230. ctlr->subdeviceid = 0;
  231. ctlr->numirqs = 1;
  232. ctlr->r_rid = 0;
  233.  
  234. if ((ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  235. &ctlr->r_rid, RF_ACTIVE)) != NULL)
  236. return (ENXIO);
  237.  
  238. v = imx_iomux_gpr_get(IOMUX_GPR13);
  239. v &= ~(IOMUX_GPR13_SATA_PHY_8(7) |
  240. IOMUX_GPR13_SATA_PHY_7(0x1f) |
  241. IOMUX_GPR13_SATA_PHY_6(7) |
  242. IOMUX_GPR13_SATA_SPEED(1) |
  243. IOMUX_GPR13_SATA_PHY_5(1) |
  244. IOMUX_GPR13_SATA_PHY_4(7) |
  245. IOMUX_GPR13_SATA_PHY_3(0xf) |
  246. IOMUX_GPR13_SATA_PHY_2(0x1f) |
  247. IOMUX_GPR13_SATA_PHY_1(1) |
  248. IOMUX_GPR13_SATA_PHY_0(1));
  249. /* setting */
  250. v |= IOMUX_GPR13_SATA_PHY_8(5) | /* Rx 3.0db */
  251. IOMUX_GPR13_SATA_PHY_7(0x12) | /* Rx SATA2m */
  252. IOMUX_GPR13_SATA_PHY_6(3) | /* Rx DPLL mode */
  253. IOMUX_GPR13_SATA_SPEED(1) | /* 3.0GHz */
  254. IOMUX_GPR13_SATA_PHY_5(0) | /* SpreadSpectram */
  255. IOMUX_GPR13_SATA_PHY_4(4) | /* Tx Attenuation 9/16 */
  256. IOMUX_GPR13_SATA_PHY_3(0) | /* Tx Boost 0db */
  257. IOMUX_GPR13_SATA_PHY_2(0x11) | /* Tx Level 1.104V */
  258. IOMUX_GPR13_SATA_PHY_1(1); /* PLL clock enable */
  259.  
  260. imx_iomux_gpr_set(IOMUX_GPR13, v);
  261.  
  262. /* phy reset */
  263. error = imx6_ahci_phy_write(ctlr, SATA_PHY_CLOCK_RESET,
  264. SATA_PHY_CLOCK_RESET_RST);
  265. if (error != 0) {
  266. device_printf(dev, "cannot reset PHY\n");
  267. goto fail;
  268. }
  269.  
  270. for (timeout = 50; timeout > 0; --timeout) {
  271. DELAY(100);
  272. pllstat = imx6_ahci_phy_read(ctlr, SATA_PHY_LANE0_OUT_STAT);
  273. if (pllstat < 0) {
  274. device_printf(dev, "cannot read LANE0 status\n");
  275. break;
  276. }
  277. if (pllstat & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE)
  278. break;
  279. }
  280.  
  281. if (timeout <= 0) {
  282. device_printf(dev, "time out reading LANE0 status\n");
  283. error = ETIMEDOUT;
  284. goto fail;
  285. }
  286.  
  287. /* Support Staggered Spin-up */
  288. v = ATA_INL(ctlr->r_mem, AHCI_CAP);
  289. ATA_OUTL(ctlr->r_mem, AHCI_CAP, v | AHCI_CAP_SSS);
  290.  
  291. /* Ports Implemented. must set 1 */
  292. v = ATA_INL(ctlr->r_mem, AHCI_PI);
  293. ATA_OUTL(ctlr->r_mem, AHCI_PI, v | (1 << 0));
  294.  
  295. /* set 1ms-timer = AHB clock / 1000 */
  296. ATA_OUTL(ctlr->r_mem, SATA_TIMER1MS,
  297. imx_ccm_ahb_hz() / 1000);
  298.  
  299. /*
  300. * Note: ahci_attach will release ctlr->r_mem on errors automatically
  301. */
  302. return (ahci_attach(dev));
  303.  
  304. fail:
  305. bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
  306. return error;
  307. }
  308.  
  309. static int
  310. imx6_ahci_detach(device_t dev)
  311. {
  312. return (ahci_detach(dev));
  313. }
  314.  
  315. devclass_t ahci_devclass;
  316.  
  317. static device_method_t imx6_ahci_ata_methods[] = {
  318. /* device probe, attach and detach methods */
  319. DEVMETHOD(device_probe, imx6_ahci_probe),
  320. DEVMETHOD(device_attach, imx6_ahci_attach),
  321. DEVMETHOD(device_detach, imx6_ahci_detach),
  322.  
  323. /* ahci bus methods */
  324. DEVMETHOD(bus_print_child, ahci_print_child),
  325. DEVMETHOD(bus_alloc_resource, ahci_alloc_resource),
  326. DEVMETHOD(bus_release_resource, ahci_release_resource),
  327. DEVMETHOD(bus_setup_intr, ahci_setup_intr),
  328. DEVMETHOD(bus_teardown_intr, ahci_teardown_intr),
  329. DEVMETHOD(bus_child_location_str, ahci_child_location_str),
  330.  
  331. DEVMETHOD_END
  332. };
  333.  
  334. static driver_t ahci_ata_driver = {
  335. "ahci",
  336. imx6_ahci_ata_methods,
  337. sizeof(struct ahci_controller)
  338. };
  339.  
  340. DRIVER_MODULE(ahci, simplebus, ahci_ata_driver, ahci_devclass, 0, 0);
Add Comment
Please, Sign In to add comment