diff mbox series

[12/31] nds32: Device specific operations

Message ID 4e9acf2ec55fb26ddb290ca2d955eeea628e0a77.1510118606.git.green.hu@gmail.com
State Not Applicable, archived
Delegated to: David Miller
Headers show
Series Andes(nds32) Linux Kernel Port | expand

Commit Message

Greentime Hu Nov. 8, 2017, 5:55 a.m. UTC
From: Greentime Hu <greentime@andestech.com>

Signed-off-by: Vincent Chen <vincentc@andestech.com>
Signed-off-by: Greentime Hu <greentime@andestech.com>
---
 arch/nds32/include/asm/io.h |   33 +++++++++++++++++++++
 arch/nds32/mm/ioremap.c     |   67 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 100 insertions(+)
 create mode 100644 arch/nds32/include/asm/io.h
 create mode 100644 arch/nds32/mm/ioremap.c

Comments

Arnd Bergmann Nov. 8, 2017, 9:04 a.m. UTC | #1
On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:

> +
> +#define ioremap(cookie,size)           __ioremap(cookie,size,0,1)
> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
> +#define iounmap(cookie)                        __iounmap(cookie)

> +#include <asm-generic/io.h>

asm-generic/io.h now provides an ioremap_nocache() helper along with
ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
ioremap_nocache definition here. You might also be able to remove
__ioremap and __iounmap, and only provide ioremap/iounmap, plus
the identity macro 'define ioremap ioremap'

> +void __iomem *__ioremap(unsigned long phys_addr, size_t size,
> +                       unsigned long flags, unsigned long align)

The 'align' argument is unused here, and not used on other architectures
either.

> +{
> +       struct vm_struct *area;
> +       unsigned long addr, offset, last_addr;
> +       pgprot_t prot;
> +
> +       /* Don't allow wraparound or zero size */
> +       last_addr = phys_addr + size - 1;
> +       if (!size || last_addr < phys_addr)
> +               return NULL;
> +
> +       /*
> +        * Mappings have to be page-aligned
> +        */
> +       offset = phys_addr & ~PAGE_MASK;
> +       phys_addr &= PAGE_MASK;
> +       size = PAGE_ALIGN(last_addr + 1) - phys_addr;
> +
> +       /*
> +        * Ok, go for it..
> +        */
> +       area = get_vm_area(size, VM_IOREMAP);

Better use get_vm_area_caller here to have the ioremap areas show up
in a more useful form in /proc/vmallocinfo

Please also have a look at what you can do for memremap().

Since you have no cacheable version of ioremap_wb/wt, it will
return an uncached mapping all the time, which is not ideal.

     Arnd
Greentime Hu Nov. 9, 2017, 7:04 a.m. UTC | #2
2017-11-08 17:04 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>
>> +
>> +#define ioremap(cookie,size)           __ioremap(cookie,size,0,1)
>> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
>> +#define iounmap(cookie)                        __iounmap(cookie)
>
>> +#include <asm-generic/io.h>
>
> asm-generic/io.h now provides an ioremap_nocache() helper along with
> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
> ioremap_nocache definition here. You might also be able to remove
> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
> the identity macro 'define ioremap ioremap'

Thanks. I will try to use generic ioremap_nocache() helper in the next
version patch.

>> +void __iomem *__ioremap(unsigned long phys_addr, size_t size,
>> +                       unsigned long flags, unsigned long align)
>
> The 'align' argument is unused here, and not used on other architectures
> either.
>

Thanks. I will remove this argument in the next version patch.

>> +{
>> +       struct vm_struct *area;
>> +       unsigned long addr, offset, last_addr;
>> +       pgprot_t prot;
>> +
>> +       /* Don't allow wraparound or zero size */
>> +       last_addr = phys_addr + size - 1;
>> +       if (!size || last_addr < phys_addr)
>> +               return NULL;
>> +
>> +       /*
>> +        * Mappings have to be page-aligned
>> +        */
>> +       offset = phys_addr & ~PAGE_MASK;
>> +       phys_addr &= PAGE_MASK;
>> +       size = PAGE_ALIGN(last_addr + 1) - phys_addr;
>> +
>> +       /*
>> +        * Ok, go for it..
>> +        */
>> +       area = get_vm_area(size, VM_IOREMAP);
>
> Better use get_vm_area_caller here to have the ioremap areas show up
> in a more useful form in /proc/vmallocinfo

Thanks.
I will use get_vm_area_caller() in the next version patch.

> Please also have a look at what you can do for memremap().
>
> Since you have no cacheable version of ioremap_wb/wt, it will
> return an uncached mapping all the time, which is not ideal.

Thanks.
I will study kernel/memremap.c
Greentime Hu Nov. 10, 2017, 4:07 p.m. UTC | #3
2017-11-09 15:04 GMT+08:00 Greentime Hu <green.hu@gmail.com>:
> 2017-11-08 17:04 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>
>>> +
>>> +#define ioremap(cookie,size)           __ioremap(cookie,size,0,1)
>>> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
>>> +#define iounmap(cookie)                        __iounmap(cookie)
>>
>>> +#include <asm-generic/io.h>
>>
>> asm-generic/io.h now provides an ioremap_nocache() helper along with
>> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
>> ioremap_nocache definition here. You might also be able to remove
>> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
>> the identity macro 'define ioremap ioremap'
>
> Thanks. I will try to use generic ioremap_nocache() helper in the next
> version patch.

I think I can't remove ioremap_nocache definition because it is defined
in asm-generic/io.h with !CONFIG_MMU.
Arnd Bergmann Nov. 10, 2017, 4:14 p.m. UTC | #4
On Fri, Nov 10, 2017 at 5:07 PM, Greentime Hu <green.hu@gmail.com> wrote:
> 2017-11-09 15:04 GMT+08:00 Greentime Hu <green.hu@gmail.com>:
>> 2017-11-08 17:04 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
>>> On Wed, Nov 8, 2017 at 6:55 AM, Greentime Hu <green.hu@gmail.com> wrote:
>>>
>>>> +
>>>> +#define ioremap(cookie,size)           __ioremap(cookie,size,0,1)
>>>> +#define ioremap_nocache(cookie,size)   __ioremap(cookie,size,0,1)
>>>> +#define iounmap(cookie)                        __iounmap(cookie)
>>>
>>>> +#include <asm-generic/io.h>
>>>
>>> asm-generic/io.h now provides an ioremap_nocache() helper along with
>>> ioremap_uc/ioremap_wc/ioremap_wt, so I think you can remove the
>>> ioremap_nocache definition here. You might also be able to remove
>>> __ioremap and __iounmap, and only provide ioremap/iounmap, plus
>>> the identity macro 'define ioremap ioremap'
>>
>> Thanks. I will try to use generic ioremap_nocache() helper in the next
>> version patch.
>
> I think I can't remove ioremap_nocache definition because it is defined
> in asm-generic/io.h with !CONFIG_MMU.

Ah, I see.

Could you move ioremap_nocache/ioremap_uc/ioremap_wc/ioremap_wt
out of that #ifdef, or would that break other architectures?

      Arnd
Greentime Hu Nov. 22, 2017, 10:02 a.m. UTC | #5
2017-11-11 0:14 GMT+08:00 Arnd Bergmann <arnd@arndb.de>:
> Could you move ioremap_nocache/ioremap_uc/ioremap_wc/ioremap_wt
> out of that #ifdef, or would that break other architectures?
>

It seems ok. I just tried arm64, x86 and nds32.

#endif /* CONFIG_MMU */
#ifndef ioremap_nocache
void __iomem *ioremap(phys_addr_t phys_addr, size_t size);
#define ioremap_nocache ioremap_nocache
static inline void __iomem *ioremap_nocache(phys_addr_t offset, size_t size)
{
        return ioremap(offset, size);
}
#endif

#ifndef ioremap_uc
#define ioremap_uc ioremap_uc
static inline void __iomem *ioremap_uc(phys_addr_t offset, size_t size)
{
        return ioremap_nocache(offset, size);
}
#endif

#ifndef ioremap_wc
#define ioremap_wc ioremap_wc
static inline void __iomem *ioremap_wc(phys_addr_t offset, size_t size)
{
        return ioremap_nocache(offset, size);
}
#endif

#ifndef ioremap_wt
#define ioremap_wt ioremap_wt
static inline void __iomem *ioremap_wt(phys_addr_t offset, size_t size)
{
        return ioremap_nocache(offset, size);
}
#endif
diff mbox series

Patch

diff --git a/arch/nds32/include/asm/io.h b/arch/nds32/include/asm/io.h
new file mode 100644
index 0000000..98b3ae9
--- /dev/null
+++ b/arch/nds32/include/asm/io.h
@@ -0,0 +1,33 @@ 
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef __ASM_NDS32_IO_H
+#define __ASM_NDS32_IO_H
+
+#ifdef __KERNEL__
+
+#include <asm-generic/iomap.h>
+extern void __iomem *__ioremap(unsigned long, size_t, unsigned long,
+			       unsigned long);
+extern void __iounmap(void __iomem * addr);
+
+#define ioremap(cookie,size)		__ioremap(cookie,size,0,1)
+#define ioremap_nocache(cookie,size)	__ioremap(cookie,size,0,1)
+#define iounmap(cookie)			__iounmap(cookie)
+#include <asm-generic/io.h>
+
+#endif /* __KERNEL__ */
+#endif /* __ASM_NDS32_IO_H */
diff --git a/arch/nds32/mm/ioremap.c b/arch/nds32/mm/ioremap.c
new file mode 100644
index 0000000..532e6cf
--- /dev/null
+++ b/arch/nds32/mm/ioremap.c
@@ -0,0 +1,67 @@ 
+/*
+ * Copyright (C) 2005-2017 Andes Technology Corporation
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/io.h>
+#include <linux/mm.h>
+#include <asm/pgtable.h>
+
+void __iomem *__ioremap(unsigned long phys_addr, size_t size,
+			unsigned long flags, unsigned long align)
+{
+	struct vm_struct *area;
+	unsigned long addr, offset, last_addr;
+	pgprot_t prot;
+
+	/* Don't allow wraparound or zero size */
+	last_addr = phys_addr + size - 1;
+	if (!size || last_addr < phys_addr)
+		return NULL;
+
+	/*
+	 * Mappings have to be page-aligned
+	 */
+	offset = phys_addr & ~PAGE_MASK;
+	phys_addr &= PAGE_MASK;
+	size = PAGE_ALIGN(last_addr + 1) - phys_addr;
+
+	/*
+	 * Ok, go for it..
+	 */
+	area = get_vm_area(size, VM_IOREMAP);
+	if (!area)
+		return NULL;
+
+	area->phys_addr = phys_addr;
+	addr = (unsigned long)area->addr;
+	prot = __pgprot(_PAGE_V | _PAGE_M_KRW | _PAGE_D |
+			_PAGE_G | _PAGE_C_DEV);
+	if (ioremap_page_range(addr, addr + size, phys_addr, prot)) {
+		vunmap((void *)addr);
+		return NULL;
+	}
+	return (__force void __iomem *)(offset + (char *)addr);
+
+}
+
+EXPORT_SYMBOL(__ioremap);
+
+void __iounmap(void __iomem * addr)
+{
+	vunmap((void *)(PAGE_MASK & (unsigned long)addr));
+}
+
+EXPORT_SYMBOL(__iounmap);