fsata.c 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916
  1. /*
  2. * Copyright : (C) 2022 Phytium Information Technology, Inc.
  3. * All Rights Reserved.
  4. *
  5. * This program is OPEN SOURCE software: you can redistribute it and/or modify it
  6. * under the terms of the Phytium Public License as published by the Phytium Technology Co.,Ltd,
  7. * either version 1.0 of the License, or (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,but WITHOUT ANY WARRANTY;
  10. * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
  11. * See the Phytium Public License for more details.
  12. *
  13. *
  14. * FilePath: fsata.c
  15. * Date: 2022-02-10 14:55:11
  16. * LastEditTime: 2022-02-18 09:05:09
  17. * Description:  This files is for sata ctrl function implementation
  18. *
  19. * Modify History:
  20. * Ver   Who        Date         Changes
  21. * ----- ------     --------    --------------------------------------
  22. */
  23. #include <string.h>
  24. #include <stdlib.h>
  25. #include "ftypes.h"
  26. #include "fassert.h"
  27. #include "fcache.h"
  28. #include "fdebug.h"
  29. #include "fsleep.h"
  30. #include "fswap.h"
  31. #include "fsata.h"
  32. #include "fsata_hw.h"
  33. /************************** Constant Definitions *****************************/
  34. /**************************** Type Definitions *******************************/
  35. /***************** Macros (Inline Functions) Definitions *********************/
  36. /************************** Function Prototypes ******************************/
  37. /************************** Variable Definitions *****************************/
  38. #define FSATA_DEBUG_TAG "SATA"
  39. #define FSATA_ERROR(format, ...) FT_DEBUG_PRINT_E(FSATA_DEBUG_TAG, format, ##__VA_ARGS__)
  40. #define FSATA_WARN(format, ...) FT_DEBUG_PRINT_W(FSATA_DEBUG_TAG, format, ##__VA_ARGS__)
  41. #define FSATA_INFO(format, ...) FT_DEBUG_PRINT_I(FSATA_DEBUG_TAG, format, ##__VA_ARGS__)
  42. #define FSATA_DEBUG(format, ...) FT_DEBUG_PRINT_D(FSATA_DEBUG_TAG, format, ##__VA_ARGS__)
  43. #ifndef MAX_SATA_BLOCKS_READ_WRITE
  44. #define MAX_SATA_BLOCKS_READ_WRITE 0x80
  45. #endif
  46. /* Maximum timeouts for each event */
  47. #define WAIT_MS_RESET 1000
  48. #define WAIT_MS_TFD 20000 /* task file data transfer is not busy */
  49. #define WAIT_MS_DATAIO 20000
  50. #define WAIT_MS_LINKUP 200
  51. static FError FSataAhciDataIO(FSataCtrl *instance_p, u8 port, u8 *fis,
  52. int fis_len, u8 *buf, int buf_len, boolean is_ncq, boolean is_write);
  53. /**
  54. * @name: FSataAhciPortBase
  55. * @msg: get port x base address
  56. * @param {uintptr} base_address FSata base address
  57. * @param {u32} port sata port number
  58. * @return {uintptr} port x base address
  59. */
  60. static uintptr FSataAhciPortBase(uintptr base_address, u32 port)
  61. {
  62. return (base_address + 0x100 + (port * 0x80));
  63. }
  64. /**
  65. * @name: FSataWaitCmdCompleted
  66. * @msg: read register status and wait command execution is completed
  67. * @param {uintptr} reg FSata register
  68. * @param {int} timeout_msec wait timeout value
  69. * @param {u32} sign register status flag bit
  70. * @return {int} return 0 if command execute success, return -1 if command execute timeout
  71. */
  72. static int FSataWaitCmdCompleted(uintptr reg, int timeout_msec, u32 sign)
  73. {
  74. int i;
  75. for (i = 0; (FtIn32(reg)& sign) && (i < timeout_msec); i++)
  76. {
  77. fsleep_millisec(1);
  78. }
  79. return (i < timeout_msec) ? 0 : -1;
  80. }
  81. /**
  82. * @name: FSataAhciLinkUp
  83. * @msg: check sata ahci port link status
  84. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance.
  85. * @param {u8} port, port number
  86. * @return {int} return FSATA_SUCCESS if successful, return others if failed
  87. */
  88. static FError FSataAhciLinkUp(FSataCtrl *instance_p, u8 port)
  89. {
  90. u32 reg_val;
  91. int i = 0;
  92. uintptr port_base_addr = instance_p->port[port].port_base_addr;
  93. /*
  94. * Bring up SATA link.
  95. * SATA link bringup time is usually less than 1 ms; only very
  96. * rarely has it taken between 1-2 ms. Never seen it above 2 ms.
  97. */
  98. while (i < WAIT_MS_LINKUP)
  99. {
  100. reg_val = FSATA_READ_REG32(port_base_addr, FSATA_PORT_SCR_STAT);
  101. if ((reg_val & FSATA_PORT_SCR_STAT_DET_MASK) == FSATA_PORT_SCR_STAT_DET_PHYRDY)
  102. return FSATA_SUCCESS;
  103. fsleep_microsec(1000);
  104. i++;
  105. }
  106. return FSATA_ERR_TIMEOUT;
  107. }
  108. /**
  109. * @name: FSataAhciInquiry
  110. * @msg: inquiry sata information
  111. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance.
  112. * @param {u8} port, port number
  113. * @return {FError} return FSATA_SUCCESS if successful, return others if failed
  114. */
  115. static FError FSataAhciInquiry(FSataCtrl *instance_p, u8 port)
  116. {
  117. FASSERT(instance_p != NULL);
  118. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  119. FError ret = FSATA_SUCCESS;
  120. u16 *idbuf;
  121. /* 64位需要预留给内存池更大的空间 */
  122. static u16 tmpid[FSATA_ID_WORDS] __attribute__((aligned(128))) = {0};
  123. u8 fis[20];
  124. /* Preset the FIS */
  125. memset(fis, 0, sizeof(fis));
  126. fis[0] = FSATA_FIS_REG_HOST_TO_DEVICE; /* Register Host to Device FIS */
  127. fis[1] = FSATA_FIS_REG_HOST_TO_DEVICE_C;
  128. fis[2] = FSATA_CMD_IDENTIFY_DEVICE; /* Command byte. */
  129. ret = FSataAhciDataIO(instance_p, port, fis, sizeof(fis),
  130. (u8 *)tmpid, FSATA_ID_WORDS * 2, FALSE, FALSE);
  131. if (ret != FSATA_SUCCESS)
  132. {
  133. FSATA_ERROR("FSataAhciInquiry: command failure. ret = %#x", ret);
  134. return FSATA_ERR_OPERATION;
  135. }
  136. instance_p->ataid[port] = tmpid;
  137. return FSATA_SUCCESS;
  138. }
  139. /**
  140. * @name: FSataIdentityCopy
  141. * @msg: parse sata Identity information to vendor, product, revision
  142. * @param {unsigned char } *dest, pointer to the destination address.
  143. * @param {unsigned char } *src, pointer to the source address.
  144. * @param {u32} len, parse length.
  145. * @return {void}
  146. */
  147. static void FSataIdentityCopy(unsigned char *dest, unsigned char *src, u32 len)
  148. {
  149. FASSERT(dest != NULL);
  150. FASSERT(src != NULL);
  151. FASSERT(len != 0);
  152. u32 start, end;
  153. start = 0;
  154. while (start < len)
  155. {
  156. if (src[start] != 0x20)/* character is not sapce */
  157. break;
  158. start++;
  159. }
  160. end = len - 1;
  161. while (end > start)
  162. {
  163. if (src[end] != 0x20)/* character is not sapce */
  164. break;
  165. end--;
  166. }
  167. for (; start <= end; start++)
  168. *dest ++ = src[start];
  169. *dest = '\0';
  170. }
  171. /**
  172. * @name: FSataIdToSectors
  173. * @msg: parse sata Identity information to capacity.
  174. * @param {u16} *id, pointer to Identity information .
  175. * @return {u64} capacity
  176. */
  177. static u64 FSataIdToSectors(u16 *id)
  178. {
  179. if (FSataIdHasLba(id))
  180. {
  181. if (FSataIdHasLba48(id))
  182. return FSATA_ID_U64(id, FSATA_ID_LBA48_SECTORS);
  183. else
  184. return (u64)(FSATA_ID_U32(id, FSATA_ID_LBA_SECTORS));
  185. }
  186. else
  187. {
  188. return 0;
  189. }
  190. }
  191. /**
  192. * @name: FSataIdStrCopy
  193. * @msg: swap sata Identity information
  194. * @param {u16} *dest, pointer to the destination address.
  195. * @param {u16} *src, pointer to the source address.
  196. * @param {int} len, swap length.
  197. * @return {void}
  198. */
  199. static void FSataIdStrCopy(u16 *dest, u16 *src, int len)
  200. {
  201. int i;
  202. for (i = 0; i < len / 2; i++)
  203. dest[i] = __swab16(src[i]);
  204. }
  205. /**
  206. * @name: FSataBlockToMB
  207. * @msg: Converts the number of blocks in 512 byte to 0.1MB
  208. * @param {unsigned long} block_count, block count.
  209. * @param {unsigned long} mul_by, multiple value.
  210. * @param {int} div_by, divided value.
  211. * @return {unsigned long} convert value
  212. */
  213. static unsigned long FSataBlockToMB(unsigned long block_count, unsigned long mul, int div)
  214. {
  215. unsigned long bc_quot, bc_rem;
  216. /* x * m / d == x / d * m + (x % d) * m / d */
  217. bc_quot = (block_count >> div); /* upper > div bit */
  218. bc_rem = block_count - (bc_quot << div); /* low div bit */
  219. return (bc_quot * mul + ((bc_rem * mul) >> div));
  220. }
  221. /**
  222. * @name: FSataInfoPrint
  223. * @msg: printf sata information
  224. * @param {FSataInfo} *dev_desc, pointer to the FSata information.
  225. * @return {void}
  226. */
  227. void FSataInfoPrint(FSataInfo *dev_desc)
  228. {
  229. unsigned long lba512; /* number of blocks if 512bytes block size */
  230. if (dev_desc->type == FSATA_DEV_TYPE_UNKNOWN)
  231. {
  232. FSATA_INFO("not available");
  233. return;
  234. }
  235. if (dev_desc->if_type == FSATA_IF_TYPE_SCSI)
  236. {
  237. FSATA_INFO("Vendor: %s Prod: %s Rev: %s",
  238. dev_desc->vendor,
  239. dev_desc->product,
  240. dev_desc->revision);
  241. }
  242. if (dev_desc->type == FSATA_DEV_TYPE_HARDDISK)
  243. {
  244. FSATA_INFO("Type: Hard Disk");
  245. }
  246. if ((dev_desc->lba > 0L) && (dev_desc->blksz > 0L))
  247. {
  248. unsigned long mb, mb_quot, mb_rem, gb, gb_quot, gb_rem;
  249. unsigned long lba;
  250. lba = dev_desc->lba;
  251. lba512 = (lba * (dev_desc->blksz / 512));
  252. /* round to 1 digit */
  253. /* 2048 = (1024 * 1024) / 512 MB */
  254. mb = FSataBlockToMB(lba512, 10, 11);
  255. dev_desc->lba512 = lba512;
  256. FSATA_INFO("lba512=%lu, mb=%lu", lba512, mb);
  257. mb_quot = mb / 10;
  258. mb_rem = mb - (10 * mb_quot);
  259. gb = mb / 1024;
  260. gb_quot = gb / 10;
  261. gb_rem = gb - (10 * gb_quot);
  262. FSATA_INFO("Capacity: %lu.%lu MB = %lu.%lu GB (%lu x %lu)",
  263. mb_quot, mb_rem,
  264. gb_quot, gb_rem,
  265. (unsigned long)lba,
  266. dev_desc->blksz);
  267. }
  268. else
  269. {
  270. FSATA_INFO("Capacity: not available");
  271. }
  272. }
  273. /**
  274. * @name: FSataAhciReadCapacity
  275. * @msg: get sata capacity by parse instance_p ataid
  276. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance.
  277. * @param {u8} port, port number
  278. * @param {unsigned long} *capacity, pointer to capacity value
  279. * @param {unsigned long} *blksz, pointer to block size
  280. * @return {FError} return FSATA_SUCCESS if successful, return others if failed
  281. */
  282. static FError FSataAhciReadCapacity(FSataCtrl *instance_p, u8 port,
  283. unsigned long *capacity, unsigned long *blksz)
  284. {
  285. FASSERT(instance_p != NULL);
  286. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  287. FError ret = FSATA_SUCCESS;
  288. u32 transfer_size; /* number of bytes per iteration */
  289. if (!instance_p->ataid[port])
  290. {
  291. FSATA_ERROR("READ CAPACITY10 command failure. "
  292. "\tNo ATA info!\n"
  293. "\tPlease run command INQUIRY first!");
  294. return FSATA_ERR_OPERATION;
  295. }
  296. u64 cap64 = FSataIdToSectors(instance_p->ataid[port]);
  297. if (cap64 > 0x100000000ULL)
  298. cap64 = 0xffffffff;
  299. *capacity = (unsigned long)(cap64);
  300. if (*capacity != 0xffffffff)
  301. {
  302. /* Read capacity (10) was sufficient for this drive. */
  303. *blksz = 512;
  304. return FSATA_SUCCESS;
  305. }
  306. else
  307. {
  308. FSATA_DEBUG("should read capacity 16?");
  309. }
  310. return FSATA_SUCCESS;
  311. }
  312. /**
  313. * @name: FSataAhciReadInfo
  314. * @msg: get sata information
  315. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance.
  316. * @param {u8} port, port number
  317. * @return {FError} return FSATA_SUCCESS if read successful, return others if read failed
  318. */
  319. FError FSataAhciReadInfo(FSataCtrl *instance_p, u8 port)
  320. {
  321. FASSERT(instance_p != NULL);
  322. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  323. uintptr base_addr = instance_p->config.base_addr;
  324. FError ret = FSATA_SUCCESS;
  325. u16 *idbuf;
  326. unsigned long capacity, blksz;
  327. unsigned char info_data[50];
  328. memset(info_data, 0, sizeof(info_data));
  329. ret = FSataAhciInquiry(instance_p, port);
  330. if (ret != FSATA_SUCCESS)
  331. {
  332. FSATA_ERROR("FSataAhciInquiry!");
  333. return FSATA_ERR_OPERATION;
  334. }
  335. /* Parse SATA Information */
  336. idbuf = instance_p->ataid[port];
  337. FSataIdStrCopy((u16 *)&info_data[16], &idbuf[FSATA_ID_PROD], 16);
  338. FSataIdStrCopy((u16 *)&info_data[32], &idbuf[FSATA_ID_FW_REV], 4);
  339. /* is ata device */
  340. if (!((__swab16(idbuf[0]) & FSATA_ID_ATA_DEVICE)))
  341. {
  342. instance_p->port[port].dev_info.type = FSATA_DEV_TYPE_HARDDISK;
  343. memcpy(&info_data[8], "ATA ", 8); /* copy 8 bytes */
  344. }
  345. else
  346. {
  347. instance_p->port[port].dev_info.type = FSATA_DEV_TYPE_UNKNOWN;
  348. }
  349. /* get info for this device */
  350. FSataIdentityCopy((unsigned char *)instance_p->port[port].dev_info.vendor, &info_data[8], 8);
  351. FSataIdentityCopy((unsigned char *)instance_p->port[port].dev_info.product, &info_data[16], 16);
  352. FSataIdentityCopy((unsigned char *)instance_p->port[port].dev_info.revision, &info_data[32], 4);
  353. /* get sata capacity by parse ataid */
  354. ret = FSataAhciReadCapacity(instance_p, port, &capacity, &blksz);
  355. if (ret != FSATA_SUCCESS)
  356. {
  357. FSATA_ERROR("FSataAhciReadCapacity error!");
  358. return FSATA_ERR_OPERATION;
  359. }
  360. instance_p->port[port].dev_info.lba = capacity;
  361. instance_p->port[port].dev_info.blksz = blksz;
  362. instance_p->port[port].dev_info.if_type = FSATA_IF_TYPE_SCSI;
  363. FSataInfoPrint(&(instance_p->port[port].dev_info));
  364. return ret;
  365. }
  366. /**
  367. * @name: FSataAhciReset
  368. * @msg: reset ahci / hba(host bus adapter)
  369. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance
  370. * @return {FError} return FSATA_SUCCESS if successful, return others if failed
  371. */
  372. static FError FSataAhciReset(FSataCtrl *instance_p)
  373. {
  374. FASSERT(instance_p != NULL);
  375. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  376. int i = WAIT_MS_RESET;
  377. uintptr base_addr = instance_p->config.base_addr;
  378. u32 reg_val = 0;
  379. /* read host control register and reset */
  380. reg_val = FSATA_READ_REG32(base_addr, FSATA_HOST_CTL);
  381. if ((reg_val & FSATA_HOST_RESET) == 0)
  382. {
  383. FSATA_SETBIT(base_addr, FSATA_HOST_CTL, FSATA_HOST_RESET);
  384. }
  385. /* reset must complete within 1 millisecond, or the hardware should be considered fried.*/
  386. do
  387. {
  388. fsleep_microsec(1000);
  389. reg_val = FSATA_READ_REG32(base_addr, FSATA_HOST_CTL);
  390. i--;
  391. }
  392. while ((i > 0) && (reg_val & FSATA_HOST_RESET));
  393. if (i == 0)
  394. {
  395. FSATA_ERROR("controller reset failed (0x%x)", reg_val);
  396. return FSATA_ERR_TIMEOUT;
  397. }
  398. return FSATA_SUCCESS;
  399. }
  400. /**
  401. * @name: FSataAhciInit
  402. * @msg: init ahci / hba(host bus adapter)
  403. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance
  404. * @return {FError} return FSATA_SUCCESS if successful, return others if failed
  405. */
  406. FError FSataAhciInit(FSataCtrl *instance_p)
  407. {
  408. FASSERT(instance_p != NULL);
  409. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  410. uintptr base_addr = instance_p->config.base_addr;
  411. FError ret = FSATA_SUCCESS;
  412. u32 i;
  413. uintptr port_base_addr = 0; /* ahci port x base address */
  414. u32 reg_val = 0;
  415. u32 port_num = 0;
  416. /* reset host control */
  417. ret = FSataAhciReset(instance_p);
  418. if (ret != FSATA_SUCCESS)
  419. return ret;
  420. /* ahci enable */
  421. FSATA_WRITE_REG32(base_addr, FSATA_HOST_CTL, FSATA_HOST_AHCI_EN);
  422. FSATA_READ_REG32(base_addr, FSATA_HOST_CTL);
  423. /* read cap.np, set the ports bit which are available for software to use. */
  424. port_num = FSATA_READ_REG32(base_addr, FSATA_HOST_CAP) & FSATA_HOST_CAP_NP_MASK;
  425. FSATA_WRITE_REG32(base_addr, FSATA_HOST_PORTS_IMPL, FSATA_HOST_PORTS_IMPL_MASK(port_num));
  426. /* set instance_p paramameters */
  427. instance_p->n_ports = port_num + 1;
  428. instance_p->port_map = FSATA_READ_REG32(base_addr, FSATA_HOST_PORTS_IMPL);
  429. FSATA_DEBUG("port_map 0x%x n_ports %d", instance_p->port_map, instance_p->n_ports);
  430. for (i = 0; i < instance_p->n_ports; i++)
  431. {
  432. if (!(instance_p->port_map & BIT(i)))
  433. continue;
  434. /* set ports base address */
  435. instance_p->port[i].port_base_addr = FSataAhciPortBase(base_addr, i);
  436. port_base_addr = instance_p->port[i].port_base_addr;
  437. /* make sure port is not active */
  438. reg_val = FSATA_READ_REG32(port_base_addr, FSATA_PORT_CMD);
  439. if (reg_val & (FSATA_PORT_CMD_LIST_ON | FSATA_PORT_CMD_FIS_ON |
  440. FSATA_PORT_CMD_FIS_RX | FSATA_PORT_CMD_START))
  441. {
  442. FSATA_DEBUG("Port %d is active, reg = %#x. Deactivating.", i, reg_val);
  443. reg_val &= ~(FSATA_PORT_CMD_LIST_ON | FSATA_PORT_CMD_FIS_ON |
  444. FSATA_PORT_CMD_FIS_RX | FSATA_PORT_CMD_START);
  445. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_CMD, reg_val);
  446. /* spec says 500 msecs for each bit, so this is slightly incorrect.*/
  447. fsleep_millisec(500);
  448. }
  449. /* Add the spinup command to whatever mode bits may
  450. * already be on in the command register, set not support staggered spin-up */
  451. reg_val = FSATA_READ_REG32(port_base_addr, FSATA_PORT_CMD);
  452. reg_val |= FSATA_PORT_CMD_SPIN_UP;
  453. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_CMD, reg_val);
  454. /* check sata port is linked */
  455. ret = FSataAhciLinkUp(instance_p, i);
  456. if (ret)
  457. {
  458. FSATA_DEBUG("sata host %d, port %d link timeout", instance_p->config.instance_id, i);
  459. continue;
  460. }
  461. else
  462. {
  463. FSATA_DEBUG("sata host %d , port %d link ok.", instance_p->config.instance_id, i) ;
  464. }
  465. /* Clear error status */
  466. reg_val = FSATA_READ_REG32(port_base_addr, FSATA_PORT_SCR_ERR);
  467. if (reg_val)
  468. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_SCR_ERR, reg_val);
  469. /* Device presence detected but Phy communication not established, retry once more */
  470. reg_val = FSATA_READ_REG32(port_base_addr, FSATA_PORT_SCR_STAT) & FSATA_PORT_SCR_STAT_DET_MASK;
  471. if (reg_val == FSATA_PORT_SCR_STAT_DET_COMINIT)
  472. {
  473. FSATA_INFO("sata link %d down, retrying...", i);
  474. i--;
  475. continue;
  476. }
  477. /* Clear error status */
  478. reg_val = FSATA_READ_REG32(port_base_addr, FSATA_PORT_SCR_ERR);
  479. if (reg_val)
  480. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_SCR_ERR, reg_val);
  481. /* clear port irq status */
  482. reg_val = FSATA_READ_REG32(port_base_addr, FSATA_PORT_IRQ_STAT);
  483. if (reg_val)
  484. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_IRQ_STAT, reg_val);
  485. /* clear host corresponding port interrupt status register */
  486. FSATA_WRITE_REG32(base_addr, FSATA_HOST_IRQ_STAT, BIT(i));
  487. /* register linkup ports */
  488. reg_val = FSATA_READ_REG32(port_base_addr, FSATA_PORT_SCR_STAT);
  489. if ((reg_val & FSATA_PORT_SCR_STAT_DET_MASK) == FSATA_PORT_SCR_STAT_DET_PHYRDY)
  490. instance_p->link_port_map |= BIT(i);
  491. }
  492. /* host interrupt enable */
  493. reg_val = FSATA_READ_REG32(base_addr, FSATA_HOST_CTL);
  494. FSATA_WRITE_REG32(base_addr, FSATA_HOST_CTL, reg_val | FSATA_HOST_IRQ_EN);
  495. return FSATA_SUCCESS;
  496. }
  497. /**
  498. * @name: FSataAhciPortStart
  499. * @msg: init ahci port, allocate Port Memory Usage
  500. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance
  501. * @param {u8} port, port number
  502. * @param {uintptr} mem, Memory start address allocated to port
  503. * @return {FError} return FSATA_SUCCESS if successful, return others if failed
  504. */
  505. FError FSataAhciPortStart(FSataCtrl *instance_p, u8 port, uintptr mem)
  506. {
  507. FASSERT(instance_p != NULL);
  508. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  509. FASSERT(mem);
  510. uintptr base_addr = instance_p->config.base_addr;
  511. FError ret = FSATA_SUCCESS;
  512. FSataAhciPorts *port_info = &(instance_p->port[port]);
  513. uintptr port_base_addr = port_info->port_base_addr;
  514. u32 reg_val = FSATA_READ_REG32(port_base_addr, FSATA_PORT_SCR_STAT);
  515. if ((reg_val & FSATA_PORT_SCR_STAT_DET_MASK) != FSATA_PORT_SCR_STAT_DET_PHYRDY)
  516. {
  517. FSATA_ERROR("No Link on host %d port %d!", instance_p->config.instance_id, port);
  518. return FSATA_ERR_OPERATION;
  519. }
  520. memset((void *)mem, 0, FSATA_AHCI_PORT_PRIV_DMA_SZ);
  521. /* First item in chunk of DMA memory: 32 command lists, 32 bytes each in size */
  522. port_info->cmd_list = (FSataAhciCommandList *)(mem);
  523. mem += FSATA_AHCI_CMD_LIST_HEADER_SIZE * FSATA_AHCI_CMD_LIST_HEADER_NUM;
  524. /* Second item: Received-FIS area */
  525. port_info->rx_fis = (FSataAhciRecvFis *)(mem);
  526. mem += FSATA_AHCI_RX_FIS_SZ;
  527. /* Third item: data area for storing a single command and its scatter-gather table */
  528. port_info->cmd_tbl_base_addr = (uintptr)mem;
  529. mem += FSATA_AHCI_CMD_TABLE_HEADER_SIZE;
  530. /* command table prdt */
  531. port_info->cmd_tbl_prdt = (FSataAhciCommandTablePrdt *)mem;
  532. /* set ahci port registers */
  533. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_LST_ADDR,
  534. (uintptr)port_info->cmd_list & FSATA_PORT_CMD_LIST_ADDR_MASK);
  535. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_LST_ADDR_HI, 0);
  536. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_FIS_ADDR,
  537. (uintptr)port_info->rx_fis & FSATA_PORT_CMD_FIS_ADDR_MASK);
  538. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_FIS_ADDR_HI, 0);
  539. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_CMD, FSATA_PORT_CMD_ICC_ACTIVE | FSATA_PORT_CMD_FIS_RX |
  540. FSATA_PORT_CMD_POWER_ON | FSATA_PORT_CMD_SPIN_UP | FSATA_PORT_CMD_START);
  541. /*
  542. * Make sure interface is not busy based on error and status
  543. * information from task file data register before proceeding
  544. */
  545. if (FSataWaitCmdCompleted(port_base_addr + FSATA_PORT_TFDATA, WAIT_MS_TFD, FSATA_BUSY))
  546. {
  547. FSATA_DEBUG("timeout exit!");
  548. return FSATA_ERR_TIMEOUT;
  549. }
  550. instance_p->private_data |= BIT(port);
  551. return ret;
  552. }
  553. /**
  554. * @name: FSataAhciFillCmdTablePrdt
  555. * @msg: allocate ahci command table prdt information
  556. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance
  557. * @param {u8} port, port number
  558. * @param {unsigned char} *buffer, data buffer address
  559. * @param {int} buf_len, data length
  560. * @return {int} return item_count if successful, return -1 if failed
  561. */
  562. static int FSataAhciFillCmdTablePrdt(FSataCtrl *instance_p, u8 port,
  563. unsigned char *buf, int buf_len)
  564. {
  565. FASSERT(instance_p != NULL);
  566. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  567. FSataAhciPorts *port_info = &(instance_p->port[port]);
  568. FSataAhciCommandTablePrdt *command_table_prdt = port_info->cmd_tbl_prdt;
  569. int item_count;
  570. int i;
  571. item_count = ((buf_len - 1) / MAX_DATA_BYTE_COUNT) + 1;
  572. if (item_count > FSATA_AHCI_PRTD_ITEM_NUM)
  573. {
  574. FSATA_ERROR("Too much command table prdt items %d!", item_count);
  575. return -1;
  576. }
  577. for (i = 0; i < item_count; i++)
  578. {
  579. command_table_prdt->addr_low = ((unsigned long) buf + i * MAX_DATA_BYTE_COUNT);
  580. command_table_prdt->addr_high = 0;
  581. command_table_prdt->data_byte = (0x3fffff &
  582. (buf_len < MAX_DATA_BYTE_COUNT
  583. ? (buf_len - 1)
  584. : (MAX_DATA_BYTE_COUNT - 1)));
  585. command_table_prdt++;
  586. buf_len -= MAX_DATA_BYTE_COUNT;
  587. }
  588. return item_count;
  589. }
  590. /**
  591. * @name: FSataAhciFillCmdList
  592. * @msg: allocate ahci command list information
  593. * @param {FSataAhciPorts} *port_info is a pointer to the FSataAhciPorts instance
  594. * @param {u32} description_info, prdtl+flag+cfl
  595. * @return {void}
  596. */
  597. static void FSataAhciFillCmdList(FSataAhciPorts *port_info, u32 description_info)
  598. {
  599. FASSERT(port_info != NULL);
  600. port_info->cmd_list->description_info = description_info;
  601. port_info->cmd_list->status = 0;
  602. port_info->cmd_list->tbl_addr = ((u32)port_info->cmd_tbl_base_addr & FSATA_PORT_CMD_TABLE_ADDR_MASK);
  603. #ifdef __aarch64__
  604. port_info->cmd_list->tbl_addr_hi = (u32)(((port_info->cmd_tbl_base_addr) >> 16) >> 16);
  605. #endif
  606. }
  607. /**
  608. * @name: FSataAhciDataIO
  609. * @msg: transfer ahci command fis and data buffer
  610. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance
  611. * @param {u8} port number
  612. * @param {u8} *fis, command fis buffer
  613. * @param {int} fis_len, command fis length
  614. * @param {u8} *buf, data read/write buffer
  615. * @param {int} buf_len, data length
  616. * @param {u8} is_write, 0-read, 1-write
  617. * @return {FError} return FSATA_SUCCESS if successful, return others if failed
  618. */
  619. static FError FSataAhciDataIO(FSataCtrl *instance_p, u8 port, u8 *fis,
  620. int fis_len, u8 *buf, int buf_len, boolean is_ncq, boolean is_write)
  621. {
  622. FASSERT(instance_p != NULL);
  623. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  624. FASSERT(fis != NULL);
  625. FSataAhciPorts *port_info = &(instance_p->port[port]);
  626. uintptr base_addr = instance_p->config.base_addr;
  627. uintptr port_base_addr = instance_p->port[port].port_base_addr;
  628. if (port >= instance_p->n_ports)
  629. {
  630. FSATA_DEBUG("Invalid port number %d", port);
  631. return FSATA_ERR_INVAILD_PARAMETER;
  632. }
  633. u32 reg_val = FSATA_READ_REG32(port_base_addr, FSATA_PORT_SCR_STAT);
  634. if ((reg_val & FSATA_PORT_SCR_STAT_DET_MASK) != FSATA_PORT_SCR_STAT_DET_PHYRDY)
  635. {
  636. FSATA_ERROR("No Link on host %d port %d!", instance_p->config.instance_id, port);
  637. return FSATA_ERR_OPERATION;
  638. }
  639. /* copy fis command to command table CFIS */
  640. memcpy((unsigned char *)port_info->cmd_tbl_base_addr, fis, fis_len);
  641. /* copy data buffer address to command table prdt item */
  642. int prdt_length = FSataAhciFillCmdTablePrdt(instance_p, port, buf, buf_len);
  643. if (prdt_length == -1)
  644. {
  645. FSATA_ERROR("FSataAhciFillCmdTablePrdt failed, buf_len = %d\n", buf_len);
  646. return FSATA_ERR_INVAILD_PARAMETER;
  647. }
  648. /* command list DW0: PRDTL(buf len) + W/R + CFL(fis len, 4 Byte(Dword) aligned) */
  649. u32 description_info = (prdt_length << 16) | (is_write << 6) | (fis_len >> 2);
  650. /* copy data to command list struct */
  651. FSataAhciFillCmdList(port_info, description_info);
  652. FCacheDCacheFlushRange((unsigned long)port_info->cmd_list, FSATA_AHCI_PORT_PRIV_DMA_SZ);
  653. FCacheDCacheFlushRange((unsigned long)buf, (unsigned long)buf_len);
  654. /* set tag bit in SACT register before write CI register when use native cmd */
  655. if (is_ncq == TRUE)
  656. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_SCR_ACT, FSATA_PORT_SCR_ACT_ENABLE);
  657. /* send cmd */
  658. FSATA_WRITE_REG32(port_base_addr, FSATA_PORT_CMD_ISSUE, FSATA_PORT_CMD_ISSUE_ENABLE);
  659. if (FSataWaitCmdCompleted(port_base_addr + FSATA_PORT_CMD_ISSUE, WAIT_MS_DATAIO, FSATA_PORT_CMD_ISSUE_ENABLE))
  660. {
  661. FSATA_ERROR("timeout exit!");
  662. return FSATA_ERR_TIMEOUT;
  663. }
  664. return FSATA_SUCCESS;
  665. }
  666. /**
  667. * @name: FSataReadWrite
  668. * @msg: read or write sata block data, choose if use ncq
  669. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance
  670. * @param {u8} port, port number
  671. * @param {u32} start, start block
  672. * @param {u32} blk_cnt, block count
  673. * @param {u8} *buffer, data buffer
  674. * @param {boolean} is_ncq, FALSE-not support ncq, TRUE-support ncq
  675. * @param {boolean} is_write, read or write, FALSE-read, TRUE-write
  676. * @return {FError} return FSATA_SUCCESS if successful, return others if failed
  677. */
  678. FError FSataReadWrite(FSataCtrl *instance_p, u8 port, u32 start,
  679. u16 blk_cnt, u8 *buffer, boolean is_ncq, boolean is_write)
  680. {
  681. FASSERT(instance_p != NULL);
  682. FASSERT(instance_p->is_ready == FT_COMPONENT_IS_READY);
  683. FASSERT(blk_cnt);
  684. uintptr base_addr = instance_p->config.base_addr;
  685. FError ret = FSATA_SUCCESS;
  686. u16 now_blocks; /* number of blocks per iteration */
  687. u32 transfer_size; /* number of bytes per iteration */
  688. u8 fis[20];
  689. /* Preset the FIS */
  690. memset(fis, 0, sizeof(fis));
  691. fis[0] = FSATA_FIS_REG_HOST_TO_DEVICE;/* fis type */
  692. fis[1] = FSATA_FIS_REG_HOST_TO_DEVICE_C; /* C and PM Port */
  693. if (is_ncq == FALSE)
  694. fis[2] = is_write ? FSATA_CMD_WRITE_EXT : FSATA_CMD_READ_EXT; /* Command */
  695. else
  696. fis[2] = is_write ? FSATA_CMD_FPDMA_WRITE : FSATA_CMD_FPDMA_READ; /* Command */
  697. while (blk_cnt)
  698. {
  699. now_blocks = min((u16)MAX_SATA_BLOCKS_READ_WRITE, blk_cnt);
  700. transfer_size = FSATA_SECT_SIZE * now_blocks;
  701. if (is_ncq == FALSE)
  702. {
  703. /* FEATURE Reserved */
  704. fis[3] = 0; /* features 7:0 */
  705. fis[11] = 0; /* features 15:8 */
  706. /* LBA of first logical sector to be transferred */
  707. fis[4] = ((start >> 0) & 0xff); /* lba 7:0 */
  708. fis[5] = ((start >> 8) & 0xff); /* lba 15:8 */
  709. fis[6] = ((start >> 16) & 0xff); /* lba 23:16 */
  710. fis[8] = ((start >> 24) & 0xff); /* lba 31:24 */
  711. /* device reg, bit 6 Shall be set to one in read command */
  712. fis[7] = FSATA_CMD_EXT_DEVICE;
  713. /* The number of logical sectors to be transferred. */
  714. fis[12] = (now_blocks >> 0) & 0xff;/* count 7:0 */
  715. fis[13] = (now_blocks >> 8) & 0xff;/* count 15:8 */
  716. }
  717. else
  718. {
  719. /* FEATURE:The number of logical sectors to be transferred. */
  720. fis[3] = (now_blocks >> 0) & 0xff; /* features 7:0 */
  721. fis[11] = (now_blocks >> 8) & 0xff; /* features 15:8 */
  722. /* LBA of first logical sector to be transferred */
  723. fis[4] = ((start >> 0) & 0xff); /* lba 7:0 */
  724. fis[5] = ((start >> 8) & 0xff); /* lba 15:8 */
  725. fis[6] = ((start >> 16) & 0xff); /* lba 23:16 */
  726. fis[8] = ((start >> 24) & 0xff); /* lba 31:24 */
  727. /* device reg, bit 6 Shall be set to one */
  728. fis[7] = FSATA_CMD_EXT_DEVICE;
  729. /* count */
  730. fis[12] = 0;/* count 7:0, NCQ TAG field */
  731. fis[13] = 0;/* count 15:8, Normal priority */
  732. }
  733. ret = FSataAhciDataIO(instance_p, port, fis, sizeof(fis),
  734. buffer, transfer_size, is_ncq, is_write);
  735. if (ret)
  736. {
  737. FSATA_ERROR("scsi_ahci: SCSI command failure. ret = %#x", ret);
  738. return FSATA_ERR_OPERATION;
  739. }
  740. buffer += transfer_size;
  741. blk_cnt -= now_blocks;
  742. start += now_blocks;
  743. }
  744. return ret;
  745. }
  746. /**
  747. * @name: FSataCfgInitialize
  748. * @msg: Initialize Sata ctrl
  749. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance.
  750. * @param {FSataConfig} *input_config_p, Default configuration parameters of FSata
  751. * @return {FError} return FSATA_SUCCESS if successful, return others if failed
  752. */
  753. FError FSataCfgInitialize(FSataCtrl *instance_p, const FSataConfig *input_config_p)
  754. {
  755. FASSERT(instance_p);
  756. /*Set default values and configuration data */
  757. FSataCfgDeInitialize(instance_p);
  758. instance_p->config = *input_config_p;
  759. instance_p->is_ready = FT_COMPONENT_IS_READY;
  760. return FSATA_SUCCESS;
  761. }
  762. /**
  763. * @name: FSataCfgDeInitialize
  764. * @msg: DeInitialization function for the device instance
  765. * @param {FSataCtrl} *instance_p, pointer to the FSataCtrl instance.
  766. * @return {*}
  767. */
  768. void FSataCfgDeInitialize(FSataCtrl *pctrl)
  769. {
  770. FASSERT(pctrl);
  771. pctrl->is_ready = 0;
  772. memset(pctrl, 0, sizeof(*pctrl));
  773. return;
  774. }