ftide020.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365
  1. /*
  2. * Faraday FTIDE020 ATA Controller (AHB)
  3. *
  4. * (C) Copyright 2011 Andes Technology
  5. * Greentime Hu <greentime@andestech.com>
  6. * Macpaul Lin <macpaul@andestech.com>
  7. * Kuo-Wei Chou <kwchou@andestech.com>
  8. *
  9. * See file CREDITS for list of people who contributed to this
  10. * project.
  11. *
  12. * This program is free software; you can redistribute it and/or
  13. * modify it under the terms of the GNU General Public License as
  14. * published by the Free Software Foundation; either version 2 of
  15. * the License, or (at your option) any later version.
  16. *
  17. * This program is distributed in the hope that it will be useful,
  18. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  20. * GNU General Public License for more details.
  21. *
  22. * You should have received a copy of the GNU General Public License
  23. * along with this program; if not, write to the Free Software
  24. * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  25. * MA 02111-1307 USA
  26. *
  27. */
  28. /* ftide020.c - ide support functions for the FTIDE020_S controller */
  29. #include <config.h>
  30. #include <common.h>
  31. #include <ata.h>
  32. #include <ide.h>
  33. #include <asm/io.h>
  34. #include <api_public.h>
  35. #include "ftide020.h"
  36. /* base address */
  37. #define FTIDE_BASE CONFIG_SYS_ATA_BASE_ADDR
  38. /*
  39. * data address - The CMD and DATA use the same FIFO in FTIDE020_S
  40. * FTIDE_DATA = CONFIG_SYS_ATA_BASE_ADDR + CONFIG_SYS_ATA_DATA_OFFSET
  41. * = &ftide020->rw_fifo
  42. */
  43. #define FTIDE_DATA (&ftide020->rw_fifo)
  44. /* command and data I/O macros */
  45. /* 0x0 - DATA FIFO */
  46. #define WRITE_DATA(x) outl((x), &ftide020->rw_fifo) /* 0x00 */
  47. #define READ_DATA() inl(&ftide020->rw_fifo) /* 0x00 */
  48. /* 0x04 - R: Status Reg, W: CMD_FIFO */
  49. #define WRITE_CMD(x) outl((x), &ftide020->cmd_fifo) /* 0x04 */
  50. #define READ_STATUS() inl(&ftide020->cmd_fifo) /* 0x04 */
  51. void ftide_set_device(int cx8, int dev)
  52. {
  53. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  54. WRITE_CMD(SET_DEV_CMD | IDE_SET_CX8(cx8) | dev);
  55. }
  56. unsigned char ide_read_register(int dev, unsigned int port)
  57. {
  58. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  59. ftide_set_device(0, dev);
  60. WRITE_CMD(READ_REG_CMD | IDE_REG_CS_READ(CONFIG_IDE_REG_CS) |
  61. IDE_REG_DA_WRITE(port));
  62. return READ_DATA() & 0xff;
  63. }
  64. void ide_write_register(int dev, unsigned int port, unsigned char val)
  65. {
  66. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  67. ftide_set_device(0, dev);
  68. WRITE_CMD(WRITE_REG_CMD | IDE_REG_CS_WRITE(CONFIG_IDE_REG_CS) |
  69. IDE_REG_DA_WRITE(port) | val);
  70. }
  71. void ide_write_data(int dev, ulong *sect_buf, int words)
  72. {
  73. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  74. ftide_set_device(0, dev);
  75. WRITE_CMD(WRITE_DATA_CMD | ((words << 2) - 1));
  76. /* block write */
  77. outsl(FTIDE_DATA, sect_buf, words);
  78. }
  79. void ide_read_data(int dev, ulong *sect_buf, int words)
  80. {
  81. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  82. ftide_set_device(0, dev);
  83. WRITE_CMD(READ_DATA_CMD | ((words << 2) - 1));
  84. /* block read */
  85. insl(FTIDE_DATA, sect_buf, words);
  86. }
  87. void ftide_dfifo_ready(ulong *time)
  88. {
  89. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  90. while (!(READ_STATUS() & STATUS_RFE)) {
  91. if (*time-- == 0)
  92. break;
  93. udelay(100);
  94. }
  95. }
  96. extern ulong ide_bus_offset[CONFIG_SYS_IDE_MAXBUS];
  97. /* Reset_IDE_controller */
  98. static void reset_ide_controller(void)
  99. {
  100. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  101. unsigned int val;
  102. val = inl(&ftide020->cr);
  103. val |= CONTROL_RST;
  104. outl(val, &ftide020->cr);
  105. /* wait until reset OK, this is poor HW design */
  106. mdelay(50);
  107. val &= ~(CONTROL_RST);
  108. outl(val, &ftide020->cr);
  109. mdelay(50);
  110. val |= CONTROL_SRST;
  111. outl(val, &ftide020->cr);
  112. /* wait until reset OK, this is poor HW design */
  113. mdelay(50);
  114. val &= ~(CONTROL_SRST);
  115. outl(val, &ftide020->cr);
  116. /* IORDY enable for PIO, for 2 device */
  117. val |= (CONTROL_IRE0 | CONTROL_IRE1);
  118. outl(val, &ftide020->cr);
  119. }
  120. /* IDE clock frequence */
  121. uint ftide_clock_freq(void)
  122. {
  123. /*
  124. * todo: To aquire dynamic system frequency is dependend on the power
  125. * management unit which the ftide020 is connected to. In current,
  126. * there are only few PMU supports in u-boot.
  127. * So this function is wait for future enhancement.
  128. */
  129. return 100;
  130. }
  131. /* Calculate Timing Registers */
  132. static unsigned int timing_cal(u16 t0, u16 t1, u16 t2, u16 t4)
  133. {
  134. unsigned int val, ahb_ns = 8;
  135. u8 TEOC, T1, T2, T4;
  136. T1 = (u8) (t1 / ahb_ns);
  137. if ((T1 * ahb_ns) == t1)
  138. T1--;
  139. T2 = (u8) (t2 / ahb_ns);
  140. if ((T2 * ahb_ns) == t2)
  141. T2--;
  142. T4 = (u8) (t4 / ahb_ns);
  143. if ((T4 * ahb_ns) == t4)
  144. T4--;
  145. TEOC = (u8) (t0 / ahb_ns);
  146. if ((TEOC * ahb_ns) == t0)
  147. TEOC--;
  148. TEOC = ((TEOC > (T1 + T2 + T4)) ? (TEOC - (T1 + T2 + T4)) : 0);
  149. /*
  150. * Here the fields in data timing registers in PIO mode
  151. * is accessed the same way as command timing registers.
  152. */
  153. val = DT_REG_PIO_T1(T1) |
  154. DT_REG_PIO_T2(T2) |
  155. DT_REG_PIO_T4(T4) |
  156. DT_REG_PIO_TEOC(TEOC);
  157. return val;
  158. }
  159. /* Set Timing Register */
  160. static unsigned int set_mode_timing(u8 dev, u8 id, u8 mode)
  161. {
  162. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  163. u16 t0, t1, t2, t4;
  164. u8 tcyc, tcvs, tmli, tenv, tack, trp;
  165. unsigned int val, sysclk = 8;
  166. if (id >= TATOL_TIMING)
  167. return 0;
  168. sysclk = ftide_clock_freq();
  169. switch (id) {
  170. case CMD_TIMING:
  171. if (mode < REG_MODE) {
  172. t0 = REG_ACCESS_TIMING[REG_T0][mode];
  173. t1 = REG_ACCESS_TIMING[REG_T1][mode];
  174. t2 = REG_ACCESS_TIMING[REG_T2][mode];
  175. t4 = REG_ACCESS_TIMING[REG_T4][mode];
  176. val = timing_cal(t0, t1, t2, t4);
  177. outl(val, (dev ? &ftide020->ctrd1 : &ftide020->ctrd0));
  178. return 1;
  179. } else
  180. return 0;
  181. case PIO_TIMING:
  182. if (mode < PIO_MODE) {
  183. t0 = PIO_ACCESS_TIMING[PIO_T0][mode];
  184. t1 = PIO_ACCESS_TIMING[PIO_T1][mode];
  185. t2 = PIO_ACCESS_TIMING[PIO_T2][mode];
  186. t4 = PIO_ACCESS_TIMING[PIO_T4][mode];
  187. val = timing_cal(t0, t1, t2, t4);
  188. outl(val, (dev ? &ftide020->dtrd1 : &ftide020->dtrd0));
  189. return 1;
  190. } else
  191. return 0;
  192. case DMA_TIMING:
  193. if (mode < UDMA_MODE) {
  194. /*
  195. * 0.999 is ceiling
  196. * for tcyc, tcvs, tmli, tenv, trp, tack
  197. */
  198. tcyc = (u8) (((UDMA_ACCESS_TIMING[UDMA_TCYC][mode] \
  199. * sysclk) + 9990) / 10000);
  200. tcvs = (u8) (((UDMA_ACCESS_TIMING[UDMA_TCVS][mode] \
  201. * sysclk) + 9990) / 10000);
  202. tmli = (u8) (((UDMA_ACCESS_TIMING[UDMA_TMLI][mode] \
  203. * sysclk) + 9990) / 10000);
  204. tenv = (u8) (((UDMA_ACCESS_TIMING[UDMA_TENV][mode] \
  205. * sysclk) + 9990) / 10000);
  206. trp = (u8) (((UDMA_ACCESS_TIMING[UDMA_TRP][mode] \
  207. * sysclk) + 9990) / 10000);
  208. tack = (u8) (((UDMA_ACCESS_TIMING[UDMA_TACK][mode] \
  209. * sysclk) + 9990) / 10000);
  210. val = DT_REG_UDMA_TENV((tenv > 0) ? (tenv - 1) : 0) |
  211. DT_REG_UDMA_TMLI((tmli > 0) ? (tmli - 1) : 0) |
  212. DT_REG_UDMA_TCYC((tcyc > 0) ? (tcyc - 1) : 0) |
  213. DT_REG_UDMA_TACK((tack > 0) ? (tack - 1) : 0) |
  214. DT_REG_UDMA_TCVS((tcvs > 0) ? (tcvs - 1) : 0) |
  215. DT_REG_UDMA_TRP((trp > 0) ? (trp - 1) : 0);
  216. outl(val, (dev ? &ftide020->dtrd1 : &ftide020->dtrd0));
  217. return 1;
  218. } else
  219. return 0;
  220. default:
  221. return 0;
  222. }
  223. }
  224. static void ftide_read_hwrev(void)
  225. {
  226. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  227. unsigned int rev;
  228. rev = inl(&ftide020->revision);
  229. }
  230. static int ftide_controller_probe(void)
  231. {
  232. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  233. unsigned int bak;
  234. bak = inl(&ftide020->ctrd1);
  235. /* probing by using shorter setup time */
  236. outl(CONFIG_CTRD1_PROBE_T1, &ftide020->ctrd1);
  237. if ((inl(&ftide020->ctrd1) & 0xff) != CONFIG_CTRD1_PROBE_T1) {
  238. outl(bak, &ftide020->ctrd1);
  239. return 0;
  240. }
  241. /* probing by using longer setup time */
  242. outl(CONFIG_CTRD1_PROBE_T2, &ftide020->ctrd1);
  243. if ((inl(&ftide020->ctrd1) & 0xff) != CONFIG_CTRD1_PROBE_T2) {
  244. outl(bak, &ftide020->ctrd1);
  245. return 0;
  246. }
  247. outl(bak, &ftide020->ctrd1);
  248. return 1;
  249. }
  250. /* ide_preinit() was migrated from linux driver ide_probe_for_ftide() */
  251. int ide_preinit(void)
  252. {
  253. static struct ftide020_s *ftide020 = (struct ftide020_s *) FTIDE_BASE;
  254. int status;
  255. unsigned int val;
  256. int i;
  257. status = 1;
  258. for (i = 0; i < CONFIG_SYS_IDE_MAXBUS; i++)
  259. ide_bus_offset[i] = -ATA_STATUS;
  260. /* auto-detect IDE controller */
  261. if (ftide_controller_probe()) {
  262. printf("Faraday %s driver version %s\n", FTIDE_IP_NAME,
  263. FTIDE_DRIVER_VERSION);
  264. } else {
  265. printf("Faraday ATA controller not found.\n");
  266. return API_ENODEV;
  267. }
  268. /* check HW IP revision */
  269. ftide_read_hwrev();
  270. /* set FIFO threshold */
  271. outl(((WRITE_FIFO - RX_THRESH) << 16) | RX_THRESH, &ftide020->dmatirr);
  272. /* set Device_0 PIO_4 timing */
  273. set_mode_timing(0, CMD_TIMING, REG_MODE4);
  274. set_mode_timing(0, PIO_TIMING, PIO_MODE4);
  275. /* set Device_1 PIO_4 timing */
  276. set_mode_timing(1, CMD_TIMING, REG_MODE4);
  277. set_mode_timing(1, PIO_TIMING, PIO_MODE4);
  278. /* from E-bios */
  279. /* little endian */
  280. outl(0x0, &ftide020->cr);
  281. mdelay(10);
  282. outl(0x0fff0fff, &ftide020->ahbtr);
  283. mdelay(10);
  284. /* Enable controller Interrupt */
  285. val = inl(&ftide020->cr);
  286. /* Enable: IDE IRQ, IDE Terminate ERROR IRQ, AHB Timeout error IRQ */
  287. val |= (CONTROL_IIE | CONTROL_TERIE | CONTROL_AERIE);
  288. outl(val, &ftide020->cr);
  289. status = 0;
  290. return status;
  291. }
  292. void ide_set_reset(int flag)
  293. {
  294. debug("ide_set_reset()\n");
  295. reset_ide_controller();
  296. return;
  297. }