blackfin_sram.c 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608
  1. /*
  2. * File: arch/blackfin/mm/blackfin_sram.c
  3. * Based on:
  4. * Author:
  5. *
  6. * Created:
  7. * Description: SRAM driver for Blackfin ADSP-BF5xx
  8. *
  9. * Modified:
  10. * Copyright 2004-2007 Analog Devices Inc.
  11. *
  12. * Bugs: Enter bugs at http://blackfin.uclinux.org/
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License as published by
  16. * the Free Software Foundation; either version 2 of the License, or
  17. * (at your option) any later version.
  18. *
  19. * This program is distributed in the hope that it will be useful,
  20. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  21. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  22. * GNU General Public License for more details.
  23. *
  24. * You should have received a copy of the GNU General Public License
  25. * along with this program; if not, see the file COPYING, or write
  26. * to the Free Software Foundation, Inc.,
  27. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  28. */
  29. #include <linux/autoconf.h>
  30. #include <linux/module.h>
  31. #include <linux/kernel.h>
  32. #include <linux/types.h>
  33. #include <linux/miscdevice.h>
  34. #include <linux/ioport.h>
  35. #include <linux/fcntl.h>
  36. #include <linux/init.h>
  37. #include <linux/poll.h>
  38. #include <linux/proc_fs.h>
  39. #include <linux/spinlock.h>
  40. #include <linux/rtc.h>
  41. #include <asm/blackfin.h>
  42. #include "blackfin_sram.h"
  43. spinlock_t l1sram_lock, l1_data_sram_lock, l1_inst_sram_lock;
  44. #if CONFIG_L1_MAX_PIECE < 16
  45. #undef CONFIG_L1_MAX_PIECE
  46. #define CONFIG_L1_MAX_PIECE 16
  47. #endif
  48. #if CONFIG_L1_MAX_PIECE > 1024
  49. #undef CONFIG_L1_MAX_PIECE
  50. #define CONFIG_L1_MAX_PIECE 1024
  51. #endif
  52. #define SRAM_SLT_NULL 0
  53. #define SRAM_SLT_FREE 1
  54. #define SRAM_SLT_ALLOCATED 2
  55. /* the data structure for L1 scratchpad and DATA SRAM */
  56. struct l1_sram_piece {
  57. void *paddr;
  58. int size;
  59. int flag;
  60. pid_t pid;
  61. };
  62. static struct l1_sram_piece l1_ssram[CONFIG_L1_MAX_PIECE];
  63. #if L1_DATA_A_LENGTH != 0
  64. static struct l1_sram_piece l1_data_A_sram[CONFIG_L1_MAX_PIECE];
  65. #endif
  66. #if L1_DATA_B_LENGTH != 0
  67. static struct l1_sram_piece l1_data_B_sram[CONFIG_L1_MAX_PIECE];
  68. #endif
  69. #if L1_CODE_LENGTH != 0
  70. static struct l1_sram_piece l1_inst_sram[CONFIG_L1_MAX_PIECE];
  71. #endif
  72. /* L1 Scratchpad SRAM initialization function */
  73. void __init l1sram_init(void)
  74. {
  75. printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
  76. L1_SCRATCH_LENGTH >> 10);
  77. memset(&l1_ssram, 0x00, sizeof(l1_ssram));
  78. l1_ssram[0].paddr = (void *)L1_SCRATCH_START;
  79. l1_ssram[0].size = L1_SCRATCH_LENGTH;
  80. l1_ssram[0].flag = SRAM_SLT_FREE;
  81. /* mutex initialize */
  82. spin_lock_init(&l1sram_lock);
  83. }
  84. void __init l1_data_sram_init(void)
  85. {
  86. #if L1_DATA_A_LENGTH != 0
  87. memset(&l1_data_A_sram, 0x00, sizeof(l1_data_A_sram));
  88. l1_data_A_sram[0].paddr = (void *)L1_DATA_A_START +
  89. (_ebss_l1 - _sdata_l1);
  90. l1_data_A_sram[0].size = L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
  91. l1_data_A_sram[0].flag = SRAM_SLT_FREE;
  92. printk(KERN_INFO "Blackfin Data A SRAM: %d KB (%d KB free)\n",
  93. L1_DATA_A_LENGTH >> 10, l1_data_A_sram[0].size >> 10);
  94. #endif
  95. #if L1_DATA_B_LENGTH != 0
  96. memset(&l1_data_B_sram, 0x00, sizeof(l1_data_B_sram));
  97. l1_data_B_sram[0].paddr = (void *)L1_DATA_B_START +
  98. (_ebss_b_l1 - _sdata_b_l1);
  99. l1_data_B_sram[0].size = L1_DATA_B_LENGTH - (_ebss_b_l1 - _sdata_b_l1);
  100. l1_data_B_sram[0].flag = SRAM_SLT_FREE;
  101. printk(KERN_INFO "Blackfin Data B SRAM: %d KB (%d KB free)\n",
  102. L1_DATA_B_LENGTH >> 10, l1_data_B_sram[0].size >> 10);
  103. #endif
  104. /* mutex initialize */
  105. spin_lock_init(&l1_data_sram_lock);
  106. }
  107. void __init l1_inst_sram_init(void)
  108. {
  109. #if L1_CODE_LENGTH != 0
  110. memset(&l1_inst_sram, 0x00, sizeof(l1_inst_sram));
  111. l1_inst_sram[0].paddr = (void *)L1_CODE_START + (_etext_l1 - _stext_l1);
  112. l1_inst_sram[0].size = L1_CODE_LENGTH - (_etext_l1 - _stext_l1);
  113. l1_inst_sram[0].flag = SRAM_SLT_FREE;
  114. printk(KERN_INFO "Blackfin Instruction SRAM: %d KB (%d KB free)\n",
  115. L1_CODE_LENGTH >> 10, l1_inst_sram[0].size >> 10);
  116. #endif
  117. /* mutex initialize */
  118. spin_lock_init(&l1_inst_sram_lock);
  119. }
  120. /* L1 memory allocate function */
  121. static void *_l1_sram_alloc(size_t size, struct l1_sram_piece *pfree, int count)
  122. {
  123. int i, index = 0;
  124. void *addr = NULL;
  125. if (size <= 0)
  126. return NULL;
  127. /* Align the size */
  128. size = (size + 3) & ~3;
  129. /* not use the good method to match the best slot !!! */
  130. /* search an available memory slot */
  131. for (i = 0; i < count; i++) {
  132. if ((pfree[i].flag == SRAM_SLT_FREE)
  133. && (pfree[i].size >= size)) {
  134. addr = pfree[i].paddr;
  135. pfree[i].flag = SRAM_SLT_ALLOCATED;
  136. pfree[i].pid = current->pid;
  137. index = i;
  138. break;
  139. }
  140. }
  141. if (i >= count)
  142. return NULL;
  143. /* updated the NULL memory slot !!! */
  144. if (pfree[i].size > size) {
  145. for (i = 0; i < count; i++) {
  146. if (pfree[i].flag == SRAM_SLT_NULL) {
  147. pfree[i].pid = 0;
  148. pfree[i].flag = SRAM_SLT_FREE;
  149. pfree[i].paddr = addr + size;
  150. pfree[i].size = pfree[index].size - size;
  151. pfree[index].size = size;
  152. break;
  153. }
  154. }
  155. }
  156. return addr;
  157. }
  158. /* Allocate the largest available block. */
  159. static void *_l1_sram_alloc_max(struct l1_sram_piece *pfree, int count,
  160. unsigned long *psize)
  161. {
  162. unsigned long best = 0;
  163. int i, index = -1;
  164. void *addr = NULL;
  165. /* search an available memory slot */
  166. for (i = 0; i < count; i++) {
  167. if (pfree[i].flag == SRAM_SLT_FREE && pfree[i].size > best) {
  168. addr = pfree[i].paddr;
  169. index = i;
  170. best = pfree[i].size;
  171. }
  172. }
  173. if (index < 0)
  174. return NULL;
  175. *psize = best;
  176. pfree[index].pid = current->pid;
  177. pfree[index].flag = SRAM_SLT_ALLOCATED;
  178. return addr;
  179. }
  180. /* L1 memory free function */
  181. static int _l1_sram_free(const void *addr,
  182. struct l1_sram_piece *pfree,
  183. int count)
  184. {
  185. int i, index = 0;
  186. /* search the relevant memory slot */
  187. for (i = 0; i < count; i++) {
  188. if (pfree[i].paddr == addr) {
  189. if (pfree[i].flag != SRAM_SLT_ALLOCATED) {
  190. /* error log */
  191. return -1;
  192. }
  193. index = i;
  194. break;
  195. }
  196. }
  197. if (i >= count)
  198. return -1;
  199. pfree[index].pid = 0;
  200. pfree[index].flag = SRAM_SLT_FREE;
  201. /* link the next address slot */
  202. for (i = 0; i < count; i++) {
  203. if (((pfree[index].paddr + pfree[index].size) == pfree[i].paddr)
  204. && (pfree[i].flag == SRAM_SLT_FREE)) {
  205. pfree[i].pid = 0;
  206. pfree[i].flag = SRAM_SLT_NULL;
  207. pfree[index].size += pfree[i].size;
  208. pfree[index].flag = SRAM_SLT_FREE;
  209. break;
  210. }
  211. }
  212. /* link the last address slot */
  213. for (i = 0; i < count; i++) {
  214. if (((pfree[i].paddr + pfree[i].size) == pfree[index].paddr) &&
  215. (pfree[i].flag == SRAM_SLT_FREE)) {
  216. pfree[index].flag = SRAM_SLT_NULL;
  217. pfree[i].size += pfree[index].size;
  218. break;
  219. }
  220. }
  221. return 0;
  222. }
  223. int sram_free(const void *addr)
  224. {
  225. if (0) {}
  226. #if L1_CODE_LENGTH != 0
  227. else if (addr >= (void *)L1_CODE_START
  228. && addr < (void *)(L1_CODE_START + L1_CODE_LENGTH))
  229. return l1_inst_sram_free(addr);
  230. #endif
  231. #if L1_DATA_A_LENGTH != 0
  232. else if (addr >= (void *)L1_DATA_A_START
  233. && addr < (void *)(L1_DATA_A_START + L1_DATA_A_LENGTH))
  234. return l1_data_A_sram_free(addr);
  235. #endif
  236. #if L1_DATA_B_LENGTH != 0
  237. else if (addr >= (void *)L1_DATA_B_START
  238. && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH))
  239. return l1_data_B_sram_free(addr);
  240. #endif
  241. else
  242. return -1;
  243. }
  244. EXPORT_SYMBOL(sram_free);
  245. void *l1_data_A_sram_alloc(size_t size)
  246. {
  247. unsigned flags;
  248. void *addr = NULL;
  249. /* add mutex operation */
  250. spin_lock_irqsave(&l1_data_sram_lock, flags);
  251. #if L1_DATA_A_LENGTH != 0
  252. addr = _l1_sram_alloc(size, l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
  253. #endif
  254. /* add mutex operation */
  255. spin_unlock_irqrestore(&l1_data_sram_lock, flags);
  256. pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n",
  257. (long unsigned int)addr, size);
  258. return addr;
  259. }
  260. EXPORT_SYMBOL(l1_data_A_sram_alloc);
  261. int l1_data_A_sram_free(const void *addr)
  262. {
  263. unsigned flags;
  264. int ret;
  265. /* add mutex operation */
  266. spin_lock_irqsave(&l1_data_sram_lock, flags);
  267. #if L1_DATA_A_LENGTH != 0
  268. ret = _l1_sram_free(addr,
  269. l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
  270. #else
  271. ret = -1;
  272. #endif
  273. /* add mutex operation */
  274. spin_unlock_irqrestore(&l1_data_sram_lock, flags);
  275. return ret;
  276. }
  277. EXPORT_SYMBOL(l1_data_A_sram_free);
  278. void *l1_data_B_sram_alloc(size_t size)
  279. {
  280. #if L1_DATA_B_LENGTH != 0
  281. unsigned flags;
  282. void *addr;
  283. /* add mutex operation */
  284. spin_lock_irqsave(&l1_data_sram_lock, flags);
  285. addr = _l1_sram_alloc(size, l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
  286. /* add mutex operation */
  287. spin_unlock_irqrestore(&l1_data_sram_lock, flags);
  288. pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n",
  289. (long unsigned int)addr, size);
  290. return addr;
  291. #else
  292. return NULL;
  293. #endif
  294. }
  295. EXPORT_SYMBOL(l1_data_B_sram_alloc);
  296. int l1_data_B_sram_free(const void *addr)
  297. {
  298. #if L1_DATA_B_LENGTH != 0
  299. unsigned flags;
  300. int ret;
  301. /* add mutex operation */
  302. spin_lock_irqsave(&l1_data_sram_lock, flags);
  303. ret = _l1_sram_free(addr, l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
  304. /* add mutex operation */
  305. spin_unlock_irqrestore(&l1_data_sram_lock, flags);
  306. return ret;
  307. #else
  308. return -1;
  309. #endif
  310. }
  311. EXPORT_SYMBOL(l1_data_B_sram_free);
  312. void *l1_data_sram_alloc(size_t size)
  313. {
  314. void *addr = l1_data_A_sram_alloc(size);
  315. if (!addr)
  316. addr = l1_data_B_sram_alloc(size);
  317. return addr;
  318. }
  319. EXPORT_SYMBOL(l1_data_sram_alloc);
  320. void *l1_data_sram_zalloc(size_t size)
  321. {
  322. void *addr = l1_data_sram_alloc(size);
  323. if (addr)
  324. memset(addr, 0x00, size);
  325. return addr;
  326. }
  327. EXPORT_SYMBOL(l1_data_sram_zalloc);
  328. int l1_data_sram_free(const void *addr)
  329. {
  330. int ret;
  331. ret = l1_data_A_sram_free(addr);
  332. if (ret == -1)
  333. ret = l1_data_B_sram_free(addr);
  334. return ret;
  335. }
  336. EXPORT_SYMBOL(l1_data_sram_free);
  337. void *l1_inst_sram_alloc(size_t size)
  338. {
  339. #if L1_DATA_A_LENGTH != 0
  340. unsigned flags;
  341. void *addr;
  342. /* add mutex operation */
  343. spin_lock_irqsave(&l1_inst_sram_lock, flags);
  344. addr = _l1_sram_alloc(size, l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
  345. /* add mutex operation */
  346. spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
  347. pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n",
  348. (long unsigned int)addr, size);
  349. return addr;
  350. #else
  351. return NULL;
  352. #endif
  353. }
  354. EXPORT_SYMBOL(l1_inst_sram_alloc);
  355. int l1_inst_sram_free(const void *addr)
  356. {
  357. #if L1_CODE_LENGTH != 0
  358. unsigned flags;
  359. int ret;
  360. /* add mutex operation */
  361. spin_lock_irqsave(&l1_inst_sram_lock, flags);
  362. ret = _l1_sram_free(addr, l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
  363. /* add mutex operation */
  364. spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
  365. return ret;
  366. #else
  367. return -1;
  368. #endif
  369. }
  370. EXPORT_SYMBOL(l1_inst_sram_free);
  371. /* L1 Scratchpad memory allocate function */
  372. void *l1sram_alloc(size_t size)
  373. {
  374. unsigned flags;
  375. void *addr;
  376. /* add mutex operation */
  377. spin_lock_irqsave(&l1sram_lock, flags);
  378. addr = _l1_sram_alloc(size, l1_ssram, ARRAY_SIZE(l1_ssram));
  379. /* add mutex operation */
  380. spin_unlock_irqrestore(&l1sram_lock, flags);
  381. return addr;
  382. }
  383. /* L1 Scratchpad memory allocate function */
  384. void *l1sram_alloc_max(size_t *psize)
  385. {
  386. unsigned flags;
  387. void *addr;
  388. /* add mutex operation */
  389. spin_lock_irqsave(&l1sram_lock, flags);
  390. addr = _l1_sram_alloc_max(l1_ssram, ARRAY_SIZE(l1_ssram), psize);
  391. /* add mutex operation */
  392. spin_unlock_irqrestore(&l1sram_lock, flags);
  393. return addr;
  394. }
  395. /* L1 Scratchpad memory free function */
  396. int l1sram_free(const void *addr)
  397. {
  398. unsigned flags;
  399. int ret;
  400. /* add mutex operation */
  401. spin_lock_irqsave(&l1sram_lock, flags);
  402. ret = _l1_sram_free(addr, l1_ssram, ARRAY_SIZE(l1_ssram));
  403. /* add mutex operation */
  404. spin_unlock_irqrestore(&l1sram_lock, flags);
  405. return ret;
  406. }
  407. int sram_free_with_lsl(const void *addr)
  408. {
  409. struct sram_list_struct *lsl, **tmp;
  410. struct mm_struct *mm = current->mm;
  411. for (tmp = &mm->context.sram_list; *tmp; tmp = &(*tmp)->next)
  412. if ((*tmp)->addr == addr)
  413. goto found;
  414. return -1;
  415. found:
  416. lsl = *tmp;
  417. sram_free(addr);
  418. *tmp = lsl->next;
  419. kfree(lsl);
  420. return 0;
  421. }
  422. EXPORT_SYMBOL(sram_free_with_lsl);
  423. void *sram_alloc_with_lsl(size_t size, unsigned long flags)
  424. {
  425. void *addr = NULL;
  426. struct sram_list_struct *lsl = NULL;
  427. struct mm_struct *mm = current->mm;
  428. lsl = kzalloc(sizeof(struct sram_list_struct), GFP_KERNEL);
  429. if (!lsl)
  430. return NULL;
  431. if (flags & L1_INST_SRAM)
  432. addr = l1_inst_sram_alloc(size);
  433. if (addr == NULL && (flags & L1_DATA_A_SRAM))
  434. addr = l1_data_A_sram_alloc(size);
  435. if (addr == NULL && (flags & L1_DATA_B_SRAM))
  436. addr = l1_data_B_sram_alloc(size);
  437. if (addr == NULL) {
  438. kfree(lsl);
  439. return NULL;
  440. }
  441. lsl->addr = addr;
  442. lsl->length = size;
  443. lsl->next = mm->context.sram_list;
  444. mm->context.sram_list = lsl;
  445. return addr;
  446. }
  447. EXPORT_SYMBOL(sram_alloc_with_lsl);
  448. #ifdef CONFIG_PROC_FS
  449. /* Once we get a real allocator, we'll throw all of this away.
  450. * Until then, we need some sort of visibility into the L1 alloc.
  451. */
  452. static void _l1sram_proc_read(char *buf, int *len, const char *desc,
  453. struct l1_sram_piece *pfree, const int array_size)
  454. {
  455. int i;
  456. *len += sprintf(&buf[*len], "--- L1 %-14s Size PID State\n", desc);
  457. for (i = 0; i < array_size; ++i) {
  458. const char *alloc_type;
  459. switch (pfree[i].flag) {
  460. case SRAM_SLT_NULL: alloc_type = "NULL"; break;
  461. case SRAM_SLT_FREE: alloc_type = "FREE"; break;
  462. case SRAM_SLT_ALLOCATED: alloc_type = "ALLOCATED"; break;
  463. default: alloc_type = "????"; break;
  464. }
  465. *len += sprintf(&buf[*len], "%p-%p %8i %4i %s\n",
  466. pfree[i].paddr, pfree[i].paddr + pfree[i].size,
  467. pfree[i].size, pfree[i].pid, alloc_type);
  468. }
  469. }
  470. static int l1sram_proc_read(char *buf, char **start, off_t offset, int count,
  471. int *eof, void *data)
  472. {
  473. int len = 0;
  474. _l1sram_proc_read(buf, &len, "Scratchpad",
  475. l1_ssram, ARRAY_SIZE(l1_ssram));
  476. #if L1_DATA_A_LENGTH != 0
  477. _l1sram_proc_read(buf, &len, "Data A",
  478. l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
  479. #endif
  480. #if L1_DATA_B_LENGTH != 0
  481. _l1sram_proc_read(buf, &len, "Data B",
  482. l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
  483. #endif
  484. #if L1_CODE_LENGTH != 0
  485. _l1sram_proc_read(buf, &len, "Instruction",
  486. l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
  487. #endif
  488. return len;
  489. }
  490. static int __init l1sram_proc_init(void)
  491. {
  492. struct proc_dir_entry *ptr;
  493. ptr = create_proc_entry("sram", S_IFREG | S_IRUGO, NULL);
  494. if (!ptr) {
  495. printk(KERN_WARNING "unable to create /proc/sram\n");
  496. return -1;
  497. }
  498. ptr->owner = THIS_MODULE;
  499. ptr->read_proc = l1sram_proc_read;
  500. return 0;
  501. }
  502. late_initcall(l1sram_proc_init);
  503. #endif