blackfin_sram.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540
  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-2006 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. };
  61. static struct l1_sram_piece l1_ssram[CONFIG_L1_MAX_PIECE];
  62. #if L1_DATA_A_LENGTH != 0
  63. static struct l1_sram_piece l1_data_A_sram[CONFIG_L1_MAX_PIECE];
  64. #endif
  65. #if L1_DATA_B_LENGTH != 0
  66. static struct l1_sram_piece l1_data_B_sram[CONFIG_L1_MAX_PIECE];
  67. #endif
  68. #if L1_CODE_LENGTH != 0
  69. static struct l1_sram_piece l1_inst_sram[CONFIG_L1_MAX_PIECE];
  70. #endif
  71. /* L1 Scratchpad SRAM initialization function */
  72. void l1sram_init(void)
  73. {
  74. printk(KERN_INFO "Blackfin Scratchpad data SRAM: %d KB\n",
  75. L1_SCRATCH_LENGTH >> 10);
  76. memset(&l1_ssram, 0x00, sizeof(l1_ssram));
  77. l1_ssram[0].paddr = (void*)L1_SCRATCH_START;
  78. l1_ssram[0].size = L1_SCRATCH_LENGTH;
  79. l1_ssram[0].flag = SRAM_SLT_FREE;
  80. /* mutex initialize */
  81. spin_lock_init(&l1sram_lock);
  82. }
  83. void l1_data_sram_init(void)
  84. {
  85. #if L1_DATA_A_LENGTH != 0
  86. printk(KERN_INFO "Blackfin DATA_A SRAM: %d KB\n",
  87. L1_DATA_A_LENGTH >> 10);
  88. memset(&l1_data_A_sram, 0x00, sizeof(l1_data_A_sram));
  89. l1_data_A_sram[0].paddr = (void*)L1_DATA_A_START +
  90. (_ebss_l1 - _sdata_l1);
  91. l1_data_A_sram[0].size = L1_DATA_A_LENGTH - (_ebss_l1 - _sdata_l1);
  92. l1_data_A_sram[0].flag = SRAM_SLT_FREE;
  93. #endif
  94. #if L1_DATA_B_LENGTH != 0
  95. printk(KERN_INFO "Blackfin DATA_B SRAM: %d KB\n",
  96. L1_DATA_B_LENGTH >> 10);
  97. memset(&l1_data_B_sram, 0x00, sizeof(l1_data_B_sram));
  98. l1_data_B_sram[0].paddr = (void*)L1_DATA_B_START;
  99. l1_data_B_sram[0].size = L1_DATA_B_LENGTH;
  100. l1_data_B_sram[0].flag = SRAM_SLT_FREE;
  101. #endif
  102. /* mutex initialize */
  103. spin_lock_init(&l1_data_sram_lock);
  104. }
  105. void l1_inst_sram_init(void)
  106. {
  107. #if L1_CODE_LENGTH != 0
  108. printk(KERN_INFO "Blackfin Instruction SRAM: %d KB\n",
  109. L1_CODE_LENGTH >> 10);
  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. #endif
  115. /* mutex initialize */
  116. spin_lock_init(&l1_inst_sram_lock);
  117. }
  118. /* L1 memory allocate function */
  119. static void *_l1_sram_alloc(size_t size, struct l1_sram_piece *pfree, int count)
  120. {
  121. int i, index = 0;
  122. void *addr = NULL;
  123. if (size <= 0)
  124. return NULL;
  125. /* Align the size */
  126. size = (size + 3) & ~3;
  127. /* not use the good method to match the best slot !!! */
  128. /* search an available memeory slot */
  129. for (i = 0; i < count; i++) {
  130. if ((pfree[i].flag == SRAM_SLT_FREE)
  131. && (pfree[i].size >= size)) {
  132. addr = pfree[i].paddr;
  133. pfree[i].flag = SRAM_SLT_ALLOCATED;
  134. index = i;
  135. break;
  136. }
  137. }
  138. if (i >= count)
  139. return NULL;
  140. /* updated the NULL memeory slot !!! */
  141. if (pfree[i].size > size) {
  142. for (i = 0; i < count; i++) {
  143. if (pfree[i].flag == SRAM_SLT_NULL) {
  144. pfree[i].flag = SRAM_SLT_FREE;
  145. pfree[i].paddr = addr + size;
  146. pfree[i].size = pfree[index].size - size;
  147. pfree[index].size = size;
  148. break;
  149. }
  150. }
  151. }
  152. return addr;
  153. }
  154. /* Allocate the largest available block. */
  155. static void *_l1_sram_alloc_max(struct l1_sram_piece *pfree, int count,
  156. unsigned long *psize)
  157. {
  158. unsigned long best = 0;
  159. int i, index = -1;
  160. void *addr = NULL;
  161. /* search an available memeory slot */
  162. for (i = 0; i < count; i++) {
  163. if (pfree[i].flag == SRAM_SLT_FREE && pfree[i].size > best) {
  164. addr = pfree[i].paddr;
  165. index = i;
  166. best = pfree[i].size;
  167. }
  168. }
  169. if (index < 0)
  170. return NULL;
  171. *psize = best;
  172. pfree[index].flag = SRAM_SLT_ALLOCATED;
  173. return addr;
  174. }
  175. /* L1 memory free function */
  176. static int _l1_sram_free(const void *addr,
  177. struct l1_sram_piece *pfree, int count)
  178. {
  179. int i, index = 0;
  180. /* search the relevant memory slot */
  181. for (i = 0; i < count; i++) {
  182. if (pfree[i].paddr == addr) {
  183. if (pfree[i].flag != SRAM_SLT_ALLOCATED) {
  184. /* error log */
  185. return -1;
  186. }
  187. index = i;
  188. break;
  189. }
  190. }
  191. if (i >= count)
  192. return -1;
  193. pfree[index].flag = SRAM_SLT_FREE;
  194. /* link the next address slot */
  195. for (i = 0; i < count; i++) {
  196. if (((pfree[index].paddr + pfree[index].size) == pfree[i].paddr)
  197. && (pfree[i].flag == SRAM_SLT_FREE)) {
  198. pfree[i].flag = SRAM_SLT_NULL;
  199. pfree[index].size += pfree[i].size;
  200. pfree[index].flag = SRAM_SLT_FREE;
  201. break;
  202. }
  203. }
  204. /* link the last address slot */
  205. for (i = 0; i < count; i++) {
  206. if (((pfree[i].paddr + pfree[i].size) == pfree[index].paddr) &&
  207. (pfree[i].flag == SRAM_SLT_FREE)) {
  208. pfree[index].flag = SRAM_SLT_NULL;
  209. pfree[i].size += pfree[index].size;
  210. break;
  211. }
  212. }
  213. return 0;
  214. }
  215. int sram_free(const void *addr)
  216. {
  217. if (0) {}
  218. #if L1_CODE_LENGTH != 0
  219. else if (addr >= (void *)L1_CODE_START
  220. && addr < (void *)(L1_CODE_START + L1_CODE_LENGTH))
  221. return l1_inst_sram_free(addr);
  222. #endif
  223. #if L1_DATA_A_LENGTH != 0
  224. else if (addr >= (void *)L1_DATA_A_START
  225. && addr < (void *)(L1_DATA_A_START + L1_DATA_A_LENGTH))
  226. return l1_data_A_sram_free(addr);
  227. #endif
  228. #if L1_DATA_B_LENGTH != 0
  229. else if (addr >= (void *)L1_DATA_B_START
  230. && addr < (void *)(L1_DATA_B_START + L1_DATA_B_LENGTH))
  231. return l1_data_B_sram_free(addr);
  232. #endif
  233. else
  234. return -1;
  235. }
  236. EXPORT_SYMBOL(sram_free);
  237. void *l1_data_A_sram_alloc(size_t size)
  238. {
  239. unsigned flags;
  240. void *addr = NULL;
  241. /* add mutex operation */
  242. spin_lock_irqsave(&l1_data_sram_lock, flags);
  243. #if L1_DATA_A_LENGTH != 0
  244. addr = _l1_sram_alloc(size, l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
  245. #endif
  246. /* add mutex operation */
  247. spin_unlock_irqrestore(&l1_data_sram_lock, flags);
  248. pr_debug("Allocated address in l1_data_A_sram_alloc is 0x%lx+0x%lx\n",
  249. (long unsigned int)addr, size);
  250. return addr;
  251. }
  252. EXPORT_SYMBOL(l1_data_A_sram_alloc);
  253. int l1_data_A_sram_free(const void *addr)
  254. {
  255. unsigned flags;
  256. int ret;
  257. /* add mutex operation */
  258. spin_lock_irqsave(&l1_data_sram_lock, flags);
  259. #if L1_DATA_A_LENGTH != 0
  260. ret = _l1_sram_free(addr,
  261. l1_data_A_sram, ARRAY_SIZE(l1_data_A_sram));
  262. #else
  263. ret = -1;
  264. #endif
  265. /* add mutex operation */
  266. spin_unlock_irqrestore(&l1_data_sram_lock, flags);
  267. return ret;
  268. }
  269. EXPORT_SYMBOL(l1_data_A_sram_free);
  270. void *l1_data_B_sram_alloc(size_t size)
  271. {
  272. #if L1_DATA_B_LENGTH != 0
  273. unsigned flags;
  274. void *addr;
  275. /* add mutex operation */
  276. spin_lock_irqsave(&l1_data_sram_lock, flags);
  277. addr = _l1_sram_alloc(size, l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
  278. /* add mutex operation */
  279. spin_unlock_irqrestore(&l1_data_sram_lock, flags);
  280. pr_debug("Allocated address in l1_data_B_sram_alloc is 0x%lx+0x%lx\n",
  281. (long unsigned int)addr, size);
  282. return addr;
  283. #else
  284. return NULL;
  285. #endif
  286. }
  287. EXPORT_SYMBOL(l1_data_B_sram_alloc);
  288. int l1_data_B_sram_free(const void *addr)
  289. {
  290. #if L1_DATA_B_LENGTH != 0
  291. unsigned flags;
  292. int ret;
  293. /* add mutex operation */
  294. spin_lock_irqsave(&l1_data_sram_lock, flags);
  295. ret = _l1_sram_free(addr, l1_data_B_sram, ARRAY_SIZE(l1_data_B_sram));
  296. /* add mutex operation */
  297. spin_unlock_irqrestore(&l1_data_sram_lock, flags);
  298. return ret;
  299. #else
  300. return -1;
  301. #endif
  302. }
  303. EXPORT_SYMBOL(l1_data_B_sram_free);
  304. void *l1_data_sram_alloc(size_t size)
  305. {
  306. void *addr = l1_data_A_sram_alloc(size);
  307. if (!addr)
  308. addr = l1_data_B_sram_alloc(size);
  309. return addr;
  310. }
  311. EXPORT_SYMBOL(l1_data_sram_alloc);
  312. void *l1_data_sram_zalloc(size_t size)
  313. {
  314. void *addr = l1_data_sram_alloc(size);
  315. if (addr)
  316. memset(addr, 0x00, size);
  317. return addr;
  318. }
  319. EXPORT_SYMBOL(l1_data_sram_zalloc);
  320. int l1_data_sram_free(const void *addr)
  321. {
  322. int ret;
  323. ret = l1_data_A_sram_free(addr);
  324. if (ret == -1)
  325. ret = l1_data_B_sram_free(addr);
  326. return ret;
  327. }
  328. EXPORT_SYMBOL(l1_data_sram_free);
  329. void *l1_inst_sram_alloc(size_t size)
  330. {
  331. #if L1_DATA_A_LENGTH != 0
  332. unsigned flags;
  333. void *addr;
  334. /* add mutex operation */
  335. spin_lock_irqsave(&l1_inst_sram_lock, flags);
  336. addr = _l1_sram_alloc(size, l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
  337. /* add mutex operation */
  338. spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
  339. pr_debug("Allocated address in l1_inst_sram_alloc is 0x%lx+0x%lx\n",
  340. (long unsigned int)addr, size);
  341. return addr;
  342. #else
  343. return NULL;
  344. #endif
  345. }
  346. EXPORT_SYMBOL(l1_inst_sram_alloc);
  347. int l1_inst_sram_free(const void *addr)
  348. {
  349. #if L1_CODE_LENGTH != 0
  350. unsigned flags;
  351. int ret;
  352. /* add mutex operation */
  353. spin_lock_irqsave(&l1_inst_sram_lock, flags);
  354. ret = _l1_sram_free(addr, l1_inst_sram, ARRAY_SIZE(l1_inst_sram));
  355. /* add mutex operation */
  356. spin_unlock_irqrestore(&l1_inst_sram_lock, flags);
  357. return ret;
  358. #else
  359. return -1;
  360. #endif
  361. }
  362. EXPORT_SYMBOL(l1_inst_sram_free);
  363. /* L1 Scratchpad memory allocate function */
  364. void *l1sram_alloc(size_t size)
  365. {
  366. unsigned flags;
  367. void *addr;
  368. /* add mutex operation */
  369. spin_lock_irqsave(&l1sram_lock, flags);
  370. addr = _l1_sram_alloc(size, l1_ssram, ARRAY_SIZE(l1_ssram));
  371. /* add mutex operation */
  372. spin_unlock_irqrestore(&l1sram_lock, flags);
  373. return addr;
  374. }
  375. /* L1 Scratchpad memory allocate function */
  376. void *l1sram_alloc_max(size_t *psize)
  377. {
  378. unsigned flags;
  379. void *addr;
  380. /* add mutex operation */
  381. spin_lock_irqsave(&l1sram_lock, flags);
  382. addr = _l1_sram_alloc_max(l1_ssram, ARRAY_SIZE(l1_ssram), psize);
  383. /* add mutex operation */
  384. spin_unlock_irqrestore(&l1sram_lock, flags);
  385. return addr;
  386. }
  387. /* L1 Scratchpad memory free function */
  388. int l1sram_free(const void *addr)
  389. {
  390. unsigned flags;
  391. int ret;
  392. /* add mutex operation */
  393. spin_lock_irqsave(&l1sram_lock, flags);
  394. ret = _l1_sram_free(addr, l1_ssram, ARRAY_SIZE(l1_ssram));
  395. /* add mutex operation */
  396. spin_unlock_irqrestore(&l1sram_lock, flags);
  397. return ret;
  398. }
  399. int sram_free_with_lsl(const void *addr)
  400. {
  401. struct sram_list_struct *lsl, **tmp;
  402. struct mm_struct *mm = current->mm;
  403. for (tmp = &mm->context.sram_list; *tmp; tmp = &(*tmp)->next)
  404. if ((*tmp)->addr == addr)
  405. goto found;
  406. return -1;
  407. found:
  408. lsl = *tmp;
  409. sram_free(addr);
  410. *tmp = lsl->next;
  411. kfree(lsl);
  412. return 0;
  413. }
  414. EXPORT_SYMBOL(sram_free_with_lsl);
  415. void *sram_alloc_with_lsl(size_t size, unsigned long flags)
  416. {
  417. void *addr = NULL;
  418. struct sram_list_struct *lsl = NULL;
  419. struct mm_struct *mm = current->mm;
  420. lsl = kmalloc(sizeof(struct sram_list_struct), GFP_KERNEL);
  421. if (!lsl)
  422. return NULL;
  423. memset(lsl, 0, sizeof(*lsl));
  424. if (flags & L1_INST_SRAM)
  425. addr = l1_inst_sram_alloc(size);
  426. if (addr == NULL && (flags & L1_DATA_A_SRAM))
  427. addr = l1_data_A_sram_alloc(size);
  428. if (addr == NULL && (flags & L1_DATA_B_SRAM))
  429. addr = l1_data_B_sram_alloc(size);
  430. if (addr == NULL) {
  431. kfree(lsl);
  432. return NULL;
  433. }
  434. lsl->addr = addr;
  435. lsl->length = size;
  436. lsl->next = mm->context.sram_list;
  437. mm->context.sram_list = lsl;
  438. return addr;
  439. }
  440. EXPORT_SYMBOL(sram_alloc_with_lsl);