ioremap.c 1.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2004, 2007-2010, 2011-2012 Synopsys, Inc. (www.synopsys.com)
  4. */
  5. #include <linux/vmalloc.h>
  6. #include <linux/init.h>
  7. #include <linux/module.h>
  8. #include <linux/io.h>
  9. #include <linux/mm.h>
  10. #include <linux/cache.h>
  11. static inline bool arc_uncached_addr_space(phys_addr_t paddr)
  12. {
  13. if (is_isa_arcompact()) {
  14. if (paddr >= ARC_UNCACHED_ADDR_SPACE)
  15. return true;
  16. } else if (paddr >= perip_base && paddr <= perip_end) {
  17. return true;
  18. }
  19. return false;
  20. }
  21. void __iomem *ioremap(phys_addr_t paddr, unsigned long size)
  22. {
  23. /*
  24. * If the region is h/w uncached, MMU mapping can be elided as optim
  25. * The cast to u32 is fine as this region can only be inside 4GB
  26. */
  27. if (arc_uncached_addr_space(paddr))
  28. return (void __iomem *)(u32)paddr;
  29. return ioremap_prot(paddr, size,
  30. pgprot_val(pgprot_noncached(PAGE_KERNEL)));
  31. }
  32. EXPORT_SYMBOL(ioremap);
  33. /*
  34. * ioremap with access flags
  35. * Cache semantics wise it is same as ioremap - "forced" uncached.
  36. * However unlike vanilla ioremap which bypasses ARC MMU for addresses in
  37. * ARC hardware uncached region, this one still goes thru the MMU as caller
  38. * might need finer access control (R/W/X)
  39. */
  40. void __iomem *ioremap_prot(phys_addr_t paddr, size_t size,
  41. unsigned long flags)
  42. {
  43. pgprot_t prot = __pgprot(flags);
  44. /* force uncached */
  45. return generic_ioremap_prot(paddr, size, pgprot_noncached(prot));
  46. }
  47. EXPORT_SYMBOL(ioremap_prot);
  48. void iounmap(volatile void __iomem *addr)
  49. {
  50. /* weird double cast to handle phys_addr_t > 32 bits */
  51. if (arc_uncached_addr_space((phys_addr_t)(u32)addr))
  52. return;
  53. generic_iounmap(addr);
  54. }
  55. EXPORT_SYMBOL(iounmap);