Re: [PATCH v1 13/19] zsmalloc: factor page chain functionality out

2016-03-11 Thread xuyiping



On 2016/3/11 15:30, Minchan Kim wrote:

For migration, we need to create sub-page chain of zspage
dynamically so this patch factors it out from alloc_zspage.

As a minor refactoring, it makes OBJ_ALLOCATED_TAG assign
more clear in obj_malloc(it could be another patch but it's
trivial so I want to put together in this patch).

Signed-off-by: Minchan Kim 
---
  mm/zsmalloc.c | 78 ++-
  1 file changed, 45 insertions(+), 33 deletions(-)

diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index bfc6a048afac..f86f8aaeb902 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -977,7 +977,9 @@ static void init_zspage(struct size_class *class, struct 
page *first_page)
unsigned long off = 0;
struct page *page = first_page;

-   VM_BUG_ON_PAGE(!is_first_page(first_page), first_page);
+   first_page->freelist = NULL;
+   INIT_LIST_HEAD(_page->lru);
+   set_zspage_inuse(first_page, 0);

while (page) {
struct page *next_page;
@@ -1022,13 +1024,44 @@ static void init_zspage(struct size_class *class, 
struct page *first_page)
set_freeobj(first_page, 0);
  }

+static void create_page_chain(struct page *pages[], int nr_pages)
+{
+   int i;
+   struct page *page;
+   struct page *prev_page = NULL;
+   struct page *first_page = NULL;
+
+   for (i = 0; i < nr_pages; i++) {
+   page = pages[i];
+
+   INIT_LIST_HEAD(>lru);
+   if (i == 0) {
+   SetPagePrivate(page);
+   set_page_private(page, 0);
+   first_page = page;
+   }
+
+   if (i == 1)
+   set_page_private(first_page, (unsigned long)page);
+   if (i >= 1)
+   set_page_private(page, (unsigned long)first_page);
+   if (i >= 2)
+   list_add(>lru, _page->lru);
+   if (i == nr_pages - 1)
+   SetPagePrivate2(page);
+
+   prev_page = page;
+   }
+}
+
  /*
   * Allocate a zspage for the given size class
   */
  static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
  {
-   int i, error;
+   int i;
struct page *first_page = NULL, *uninitialized_var(prev_page);
+   struct page *pages[ZS_MAX_PAGES_PER_ZSPAGE];

/*
 * Allocate individual pages and link them together as:
@@ -1041,43 +1074,23 @@ static struct page *alloc_zspage(struct size_class 
*class, gfp_t flags)


*uninitialized_var(prev_page) in alloc_zspage is not in use more.


 * (i.e. no other sub-page has this flag set) and PG_private_2 to
 * identify the last page.
 */
-   error = -ENOMEM;
for (i = 0; i < class->pages_per_zspage; i++) {
struct page *page;

page = alloc_page(flags);
-   if (!page)
-   goto cleanup;
-
-   INIT_LIST_HEAD(>lru);
-   if (i == 0) {   /* first page */
-   page->freelist = NULL;
-   SetPagePrivate(page);
-   set_page_private(page, 0);
-   first_page = page;
-   set_zspage_inuse(page, 0);
+   if (!page) {
+   while (--i >= 0)
+   __free_page(pages[i]);
+   return NULL;
}
-   if (i == 1)
-   set_page_private(first_page, (unsigned long)page);
-   if (i >= 1)
-   set_page_private(page, (unsigned long)first_page);
-   if (i >= 2)
-   list_add(>lru, _page->lru);
-   if (i == class->pages_per_zspage - 1)/* last page */
-   SetPagePrivate2(page);
-   prev_page = page;
+
+   pages[i] = page;
}

+   create_page_chain(pages, class->pages_per_zspage);
+   first_page = pages[0];
init_zspage(class, first_page);

-   error = 0; /* Success */
-
-cleanup:
-   if (unlikely(error) && first_page) {
-   free_zspage(first_page);
-   first_page = NULL;
-   }
-
return first_page;
  }

@@ -1419,7 +1432,6 @@ static unsigned long obj_malloc(struct size_class *class,
unsigned long m_offset;
void *vaddr;

-   handle |= OBJ_ALLOCATED_TAG;
obj = get_freeobj(first_page);
objidx_to_page_and_ofs(class, first_page, obj,
_page, _offset);
@@ -1429,10 +1441,10 @@ static unsigned long obj_malloc(struct size_class 
*class,
set_freeobj(first_page, link->next >> OBJ_ALLOCATED_TAG);
if (!class->huge)
/* record handle in the header of allocated chunk */
-   link->handle = handle;
+   link->handle = handle | OBJ_ALLOCATED_TAG;

Re: [PATCH v1 13/19] zsmalloc: factor page chain functionality out

2016-03-11 Thread xuyiping



On 2016/3/11 15:30, Minchan Kim wrote:

For migration, we need to create sub-page chain of zspage
dynamically so this patch factors it out from alloc_zspage.

As a minor refactoring, it makes OBJ_ALLOCATED_TAG assign
more clear in obj_malloc(it could be another patch but it's
trivial so I want to put together in this patch).

Signed-off-by: Minchan Kim 
---
  mm/zsmalloc.c | 78 ++-
  1 file changed, 45 insertions(+), 33 deletions(-)

diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index bfc6a048afac..f86f8aaeb902 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -977,7 +977,9 @@ static void init_zspage(struct size_class *class, struct 
page *first_page)
unsigned long off = 0;
struct page *page = first_page;

-   VM_BUG_ON_PAGE(!is_first_page(first_page), first_page);
+   first_page->freelist = NULL;
+   INIT_LIST_HEAD(_page->lru);
+   set_zspage_inuse(first_page, 0);

while (page) {
struct page *next_page;
@@ -1022,13 +1024,44 @@ static void init_zspage(struct size_class *class, 
struct page *first_page)
set_freeobj(first_page, 0);
  }

+static void create_page_chain(struct page *pages[], int nr_pages)
+{
+   int i;
+   struct page *page;
+   struct page *prev_page = NULL;
+   struct page *first_page = NULL;
+
+   for (i = 0; i < nr_pages; i++) {
+   page = pages[i];
+
+   INIT_LIST_HEAD(>lru);
+   if (i == 0) {
+   SetPagePrivate(page);
+   set_page_private(page, 0);
+   first_page = page;
+   }
+
+   if (i == 1)
+   set_page_private(first_page, (unsigned long)page);
+   if (i >= 1)
+   set_page_private(page, (unsigned long)first_page);
+   if (i >= 2)
+   list_add(>lru, _page->lru);
+   if (i == nr_pages - 1)
+   SetPagePrivate2(page);
+
+   prev_page = page;
+   }
+}
+
  /*
   * Allocate a zspage for the given size class
   */
  static struct page *alloc_zspage(struct size_class *class, gfp_t flags)
  {
-   int i, error;
+   int i;
struct page *first_page = NULL, *uninitialized_var(prev_page);
+   struct page *pages[ZS_MAX_PAGES_PER_ZSPAGE];

/*
 * Allocate individual pages and link them together as:
@@ -1041,43 +1074,23 @@ static struct page *alloc_zspage(struct size_class 
*class, gfp_t flags)


*uninitialized_var(prev_page) in alloc_zspage is not in use more.


 * (i.e. no other sub-page has this flag set) and PG_private_2 to
 * identify the last page.
 */
-   error = -ENOMEM;
for (i = 0; i < class->pages_per_zspage; i++) {
struct page *page;

page = alloc_page(flags);
-   if (!page)
-   goto cleanup;
-
-   INIT_LIST_HEAD(>lru);
-   if (i == 0) {   /* first page */
-   page->freelist = NULL;
-   SetPagePrivate(page);
-   set_page_private(page, 0);
-   first_page = page;
-   set_zspage_inuse(page, 0);
+   if (!page) {
+   while (--i >= 0)
+   __free_page(pages[i]);
+   return NULL;
}
-   if (i == 1)
-   set_page_private(first_page, (unsigned long)page);
-   if (i >= 1)
-   set_page_private(page, (unsigned long)first_page);
-   if (i >= 2)
-   list_add(>lru, _page->lru);
-   if (i == class->pages_per_zspage - 1)/* last page */
-   SetPagePrivate2(page);
-   prev_page = page;
+
+   pages[i] = page;
}

+   create_page_chain(pages, class->pages_per_zspage);
+   first_page = pages[0];
init_zspage(class, first_page);

-   error = 0; /* Success */
-
-cleanup:
-   if (unlikely(error) && first_page) {
-   free_zspage(first_page);
-   first_page = NULL;
-   }
-
return first_page;
  }

@@ -1419,7 +1432,6 @@ static unsigned long obj_malloc(struct size_class *class,
unsigned long m_offset;
void *vaddr;

-   handle |= OBJ_ALLOCATED_TAG;
obj = get_freeobj(first_page);
objidx_to_page_and_ofs(class, first_page, obj,
_page, _offset);
@@ -1429,10 +1441,10 @@ static unsigned long obj_malloc(struct size_class 
*class,
set_freeobj(first_page, link->next >> OBJ_ALLOCATED_TAG);
if (!class->huge)
/* record handle in the header of allocated chunk */
-   link->handle = handle;
+   link->handle = handle | OBJ_ALLOCATED_TAG;
else
   

Re: [PATCH v1 09/19] zsmalloc: keep max_object in size_class

2016-03-11 Thread xuyiping



On 2016/3/11 15:30, Minchan Kim wrote:

Every zspage in a size_class has same number of max objects so
we could move it to a size_class.

Signed-off-by: Minchan Kim 
---
  mm/zsmalloc.c | 29 ++---
  1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index b4fb11831acb..ca663c82c1fc 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -32,8 +32,6 @@
   *page->freelist: points to the first free object in zspage.
   *Free objects are linked together using in-place
   *metadata.
- * page->objects: maximum number of objects we can store in this
- * zspage (class->zspage_order * PAGE_SIZE / class->size)
   *page->lru: links together first pages of various zspages.
   *Basically forming list of zspages in a fullness group.
   *page->mapping: class index and fullness group of the zspage
@@ -211,6 +209,7 @@ struct size_class {
 * of ZS_ALIGN.
 */
int size;
+   int objs_per_zspage;
unsigned int index;

struct zs_size_stat stats;
@@ -622,21 +621,22 @@ static inline void zs_pool_stat_destroy(struct zs_pool 
*pool)
   * the pool (not yet implemented). This function returns fullness
   * status of the given page.
   */
-static enum fullness_group get_fullness_group(struct page *first_page)
+static enum fullness_group get_fullness_group(struct size_class *class,
+   struct page *first_page)
  {
-   int inuse, max_objects;
+   int inuse, objs_per_zspage;
enum fullness_group fg;

VM_BUG_ON_PAGE(!is_first_page(first_page), first_page);

inuse = first_page->inuse;
-   max_objects = first_page->objects;
+   objs_per_zspage = class->objs_per_zspage;

if (inuse == 0)
fg = ZS_EMPTY;
-   else if (inuse == max_objects)
+   else if (inuse == objs_per_zspage)
fg = ZS_FULL;
-   else if (inuse <= 3 * max_objects / fullness_threshold_frac)
+   else if (inuse <= 3 * objs_per_zspage / fullness_threshold_frac)
fg = ZS_ALMOST_EMPTY;
else
fg = ZS_ALMOST_FULL;
@@ -723,7 +723,7 @@ static enum fullness_group fix_fullness_group(struct 
size_class *class,
enum fullness_group currfg, newfg;

get_zspage_mapping(first_page, _idx, );
-   newfg = get_fullness_group(first_page);
+   newfg = get_fullness_group(class, first_page);
if (newfg == currfg)
goto out;

@@ -1003,9 +1003,6 @@ static struct page *alloc_zspage(struct size_class 
*class, gfp_t flags)
init_zspage(class, first_page);

first_page->freelist = location_to_obj(first_page, 0);
-   /* Maximum number of objects we can store in this zspage */
-   first_page->objects = class->pages_per_zspage * PAGE_SIZE / class->size;
-
error = 0; /* Success */

  cleanup:
@@ -1235,11 +1232,11 @@ static bool can_merge(struct size_class *prev, int 
size, int pages_per_zspage)
return true;
  }

-static bool zspage_full(struct page *first_page)
+static bool zspage_full(struct size_class *class, struct page *first_page)
  {
VM_BUG_ON_PAGE(!is_first_page(first_page), first_page);

-   return first_page->inuse == first_page->objects;
+   return first_page->inuse == class->objs_per_zspage;
  }

  unsigned long zs_get_total_pages(struct zs_pool *pool)
@@ -1625,7 +1622,7 @@ static int migrate_zspage(struct zs_pool *pool, struct 
size_class *class,
}

/* Stop if there is no more space */
-   if (zspage_full(d_page)) {
+   if (zspage_full(class, d_page)) {
unpin_tag(handle);
ret = -ENOMEM;
break;
@@ -1684,7 +1681,7 @@ static enum fullness_group putback_zspage(struct zs_pool 
*pool,
  {
enum fullness_group fullness;

-   fullness = get_fullness_group(first_page);
+   fullness = get_fullness_group(class, first_page);
insert_zspage(class, fullness, first_page);
set_zspage_mapping(first_page, class->index, fullness);

@@ -1933,6 +1930,8 @@ struct zs_pool *zs_create_pool(const char *name, gfp_t 
flags)
class->size = size;
class->index = i;
class->pages_per_zspage = pages_per_zspage;
+   class->objs_per_zspage = class->pages_per_zspage *
+   PAGE_SIZE / class->size;
if (pages_per_zspage == 1 &&
get_maxobj_per_zspage(size, pages_per_zspage) == 1)
class->huge = true;


computes the "objs_per_zspage" twice here.

class->objs_per_zspage = get_maxobj_per_zspage(size,
pages_per_zspage);
if (pages_per_zspage == 1 && class->objs_per_zspage ==1)
  

Re: [PATCH v1 09/19] zsmalloc: keep max_object in size_class

2016-03-11 Thread xuyiping



On 2016/3/11 15:30, Minchan Kim wrote:

Every zspage in a size_class has same number of max objects so
we could move it to a size_class.

Signed-off-by: Minchan Kim 
---
  mm/zsmalloc.c | 29 ++---
  1 file changed, 14 insertions(+), 15 deletions(-)

diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index b4fb11831acb..ca663c82c1fc 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -32,8 +32,6 @@
   *page->freelist: points to the first free object in zspage.
   *Free objects are linked together using in-place
   *metadata.
- * page->objects: maximum number of objects we can store in this
- * zspage (class->zspage_order * PAGE_SIZE / class->size)
   *page->lru: links together first pages of various zspages.
   *Basically forming list of zspages in a fullness group.
   *page->mapping: class index and fullness group of the zspage
@@ -211,6 +209,7 @@ struct size_class {
 * of ZS_ALIGN.
 */
int size;
+   int objs_per_zspage;
unsigned int index;

struct zs_size_stat stats;
@@ -622,21 +621,22 @@ static inline void zs_pool_stat_destroy(struct zs_pool 
*pool)
   * the pool (not yet implemented). This function returns fullness
   * status of the given page.
   */
-static enum fullness_group get_fullness_group(struct page *first_page)
+static enum fullness_group get_fullness_group(struct size_class *class,
+   struct page *first_page)
  {
-   int inuse, max_objects;
+   int inuse, objs_per_zspage;
enum fullness_group fg;

VM_BUG_ON_PAGE(!is_first_page(first_page), first_page);

inuse = first_page->inuse;
-   max_objects = first_page->objects;
+   objs_per_zspage = class->objs_per_zspage;

if (inuse == 0)
fg = ZS_EMPTY;
-   else if (inuse == max_objects)
+   else if (inuse == objs_per_zspage)
fg = ZS_FULL;
-   else if (inuse <= 3 * max_objects / fullness_threshold_frac)
+   else if (inuse <= 3 * objs_per_zspage / fullness_threshold_frac)
fg = ZS_ALMOST_EMPTY;
else
fg = ZS_ALMOST_FULL;
@@ -723,7 +723,7 @@ static enum fullness_group fix_fullness_group(struct 
size_class *class,
enum fullness_group currfg, newfg;

get_zspage_mapping(first_page, _idx, );
-   newfg = get_fullness_group(first_page);
+   newfg = get_fullness_group(class, first_page);
if (newfg == currfg)
goto out;

@@ -1003,9 +1003,6 @@ static struct page *alloc_zspage(struct size_class 
*class, gfp_t flags)
init_zspage(class, first_page);

first_page->freelist = location_to_obj(first_page, 0);
-   /* Maximum number of objects we can store in this zspage */
-   first_page->objects = class->pages_per_zspage * PAGE_SIZE / class->size;
-
error = 0; /* Success */

  cleanup:
@@ -1235,11 +1232,11 @@ static bool can_merge(struct size_class *prev, int 
size, int pages_per_zspage)
return true;
  }

-static bool zspage_full(struct page *first_page)
+static bool zspage_full(struct size_class *class, struct page *first_page)
  {
VM_BUG_ON_PAGE(!is_first_page(first_page), first_page);

-   return first_page->inuse == first_page->objects;
+   return first_page->inuse == class->objs_per_zspage;
  }

  unsigned long zs_get_total_pages(struct zs_pool *pool)
@@ -1625,7 +1622,7 @@ static int migrate_zspage(struct zs_pool *pool, struct 
size_class *class,
}

/* Stop if there is no more space */
-   if (zspage_full(d_page)) {
+   if (zspage_full(class, d_page)) {
unpin_tag(handle);
ret = -ENOMEM;
break;
@@ -1684,7 +1681,7 @@ static enum fullness_group putback_zspage(struct zs_pool 
*pool,
  {
enum fullness_group fullness;

-   fullness = get_fullness_group(first_page);
+   fullness = get_fullness_group(class, first_page);
insert_zspage(class, fullness, first_page);
set_zspage_mapping(first_page, class->index, fullness);

@@ -1933,6 +1930,8 @@ struct zs_pool *zs_create_pool(const char *name, gfp_t 
flags)
class->size = size;
class->index = i;
class->pages_per_zspage = pages_per_zspage;
+   class->objs_per_zspage = class->pages_per_zspage *
+   PAGE_SIZE / class->size;
if (pages_per_zspage == 1 &&
get_maxobj_per_zspage(size, pages_per_zspage) == 1)
class->huge = true;


computes the "objs_per_zspage" twice here.

class->objs_per_zspage = get_maxobj_per_zspage(size,
pages_per_zspage);
if (pages_per_zspage == 1 && class->objs_per_zspage ==1)
  

Re: [PATCH] zsmalloc: drop unused member 'mapping_area->huge'

2016-02-16 Thread xuyiping

HI, Sergery

On 2016/2/17 10:26, Sergey Senozhatsky wrote:

Hello,

On (02/17/16 09:56), YiPing Xu wrote:

  static int create_handle_cache(struct zs_pool *pool)
@@ -1127,11 +1126,9 @@ static void __zs_unmap_object(struct mapping_area *area,
goto out;

buf = area->vm_buf;
-   if (!area->huge) {
-   buf = buf + ZS_HANDLE_SIZE;
-   size -= ZS_HANDLE_SIZE;
-   off += ZS_HANDLE_SIZE;
-   }
+   buf = buf + ZS_HANDLE_SIZE;
+   size -= ZS_HANDLE_SIZE;
+   off += ZS_HANDLE_SIZE;

sizes[0] = PAGE_SIZE - off;
sizes[1] = size - sizes[0];



hm, indeed.

shouldn't it depend on class->huge?

void *zs_map_object()
{


if (off + class->size <= PAGE_SIZE) {

for huge object, the code will get into this branch, there is no more 
huge object process in __zs_map_object.


/* this object is contained entirely within a page */
area->vm_addr = kmap_atomic(page);
ret = area->vm_addr + off;
goto out;
}



void *ret = __zs_map_object(area, pages, off, class->size);

if (!class->huge)
ret += ZS_HANDLE_SIZE;  /* area->vm_buf + ZS_HANDLE_SIZE */

return ret;
}


void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
{
..

area = this_cpu_ptr(_map_area);
if (off + class->size <= PAGE_SIZE)

for huge object, the code will get into this branch, so, in 
__zs_unmap_object there is no depend on class->huge.


it is a little implicated here.

kunmap_atomic(area->vm_addr);
else {
struct page *pages[2];

pages[0] = page;
pages[1] = get_next_page(page);
BUG_ON(!pages[1]);

__zs_unmap_object(area, pages, off, class->size);
}

..
}



static void __zs_unmap_object(struct mapping_area *area...)
{
char *buf = area->vm_buf;

/* handle is in page->private for class->huge */

buf = buf + ZS_HANDLE_SIZE;
size -= ZS_HANDLE_SIZE;
off += ZS_HANDLE_SIZE;

memcpy(..);
}

-ss

.





Re: [PATCH] zsmalloc: drop unused member 'mapping_area->huge'

2016-02-16 Thread xuyiping

HI, Sergery

On 2016/2/17 10:26, Sergey Senozhatsky wrote:

Hello,

On (02/17/16 09:56), YiPing Xu wrote:

  static int create_handle_cache(struct zs_pool *pool)
@@ -1127,11 +1126,9 @@ static void __zs_unmap_object(struct mapping_area *area,
goto out;

buf = area->vm_buf;
-   if (!area->huge) {
-   buf = buf + ZS_HANDLE_SIZE;
-   size -= ZS_HANDLE_SIZE;
-   off += ZS_HANDLE_SIZE;
-   }
+   buf = buf + ZS_HANDLE_SIZE;
+   size -= ZS_HANDLE_SIZE;
+   off += ZS_HANDLE_SIZE;

sizes[0] = PAGE_SIZE - off;
sizes[1] = size - sizes[0];



hm, indeed.

shouldn't it depend on class->huge?

void *zs_map_object()
{


if (off + class->size <= PAGE_SIZE) {

for huge object, the code will get into this branch, there is no more 
huge object process in __zs_map_object.


/* this object is contained entirely within a page */
area->vm_addr = kmap_atomic(page);
ret = area->vm_addr + off;
goto out;
}



void *ret = __zs_map_object(area, pages, off, class->size);

if (!class->huge)
ret += ZS_HANDLE_SIZE;  /* area->vm_buf + ZS_HANDLE_SIZE */

return ret;
}


void zs_unmap_object(struct zs_pool *pool, unsigned long handle)
{
..

area = this_cpu_ptr(_map_area);
if (off + class->size <= PAGE_SIZE)

for huge object, the code will get into this branch, so, in 
__zs_unmap_object there is no depend on class->huge.


it is a little implicated here.

kunmap_atomic(area->vm_addr);
else {
struct page *pages[2];

pages[0] = page;
pages[1] = get_next_page(page);
BUG_ON(!pages[1]);

__zs_unmap_object(area, pages, off, class->size);
}

..
}



static void __zs_unmap_object(struct mapping_area *area...)
{
char *buf = area->vm_buf;

/* handle is in page->private for class->huge */

buf = buf + ZS_HANDLE_SIZE;
size -= ZS_HANDLE_SIZE;
off += ZS_HANDLE_SIZE;

memcpy(..);
}

-ss

.





Re: [PATCH 2/3] staging: android: ion: Add ion driver for Hi6220 SoC platform

2015-10-09 Thread xuyiping



On 2015/10/8 15:55, Chen Feng wrote:

Signed-off-by: Chen Feng 
Signed-off-by: Yu Dongbin 
---
  drivers/staging/android/ion/Kconfig|   7 +
  drivers/staging/android/ion/Makefile   |   1 +
  drivers/staging/android/ion/hisilicon/Kconfig  |   5 +
  drivers/staging/android/ion/hisilicon/Makefile |   1 +
  drivers/staging/android/ion/hisilicon/hi6220_ion.c | 201 +
  5 files changed, 215 insertions(+)
  create mode 100644 drivers/staging/android/ion/hisilicon/Kconfig
  create mode 100644 drivers/staging/android/ion/hisilicon/Makefile
  create mode 100644 drivers/staging/android/ion/hisilicon/hi6220_ion.c

diff --git a/drivers/staging/android/ion/Kconfig 
b/drivers/staging/android/ion/Kconfig
index 3452346..19c1572 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -33,3 +33,10 @@ config ION_TEGRA
help
  Choose this option if you wish to use ion on an nVidia Tegra.

+config ION_HISI
+   tristate "Ion for Hisilicon"
+   depends on ARCH_HISI && ION
+   help
+ Choose this option if you wish to use ion on Hisilicon Platform.
+
+source "drivers/staging/android/ion/hisilicon/Kconfig"
diff --git a/drivers/staging/android/ion/Makefile 
b/drivers/staging/android/ion/Makefile
index b56fd2b..18cc2aa 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -7,4 +7,5 @@ endif

  obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o
  obj-$(CONFIG_ION_TEGRA) += tegra/
+obj-$(CONFIG_ION_HISI) += hisilicon/

diff --git a/drivers/staging/android/ion/hisilicon/Kconfig 
b/drivers/staging/android/ion/hisilicon/Kconfig
new file mode 100644
index 000..2b4bd07
--- /dev/null
+++ b/drivers/staging/android/ion/hisilicon/Kconfig
@@ -0,0 +1,5 @@
+config HI6220_ION
+bool "Hi6220 ION Driver"
+depends on ARCH_HISI && ION
+help
+  Build the Hisilicon Hi6220 ion driver.
diff --git a/drivers/staging/android/ion/hisilicon/Makefile 
b/drivers/staging/android/ion/hisilicon/Makefile
new file mode 100644
index 000..2a89414
--- /dev/null
+++ b/drivers/staging/android/ion/hisilicon/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_HI6220_ION) += hi6220_ion.o
diff --git a/drivers/staging/android/ion/hisilicon/hi6220_ion.c 
b/drivers/staging/android/ion/hisilicon/hi6220_ion.c
new file mode 100644
index 000..b7d39b8
--- /dev/null
+++ b/drivers/staging/android/ion/hisilicon/hi6220_ion.c
@@ -0,0 +1,201 @@
+#define pr_fmt(fmt) "Ion: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../ion_priv.h"
+#include "../ion.h"
+
+struct hi6220_ion_type_table {
+   const char *name;
+   enum ion_heap_type type;
+};
+
+static struct hi6220_ion_type_table ion_type_table[] = {
+   {"ion_system", ION_HEAP_TYPE_SYSTEM},
+   {"ion_system_contig", ION_HEAP_TYPE_SYSTEM_CONTIG},
+   {"ion_carveout", ION_HEAP_TYPE_CARVEOUT},
+   {"ion_chunk", ION_HEAP_TYPE_CHUNK},
+   {"ion_dma", ION_HEAP_TYPE_DMA},
+   {"ion_custom", ION_HEAP_TYPE_CUSTOM},
+};
+
+static struct ion_device *idev;
+static int num_heaps;
+static struct ion_heap **heaps;
+static struct ion_platform_heap **heaps_data;
+
+static int get_type_by_name(const char *name, enum ion_heap_type *type)
+{
+   int i, n;
+
+   n = ARRAY_SIZE(ion_type_table);
+   for (i = 0; i < n; i++) {
+   if (strncmp(name, ion_type_table[i].name, strlen(name)))
+   continue;
+
+   *type = ion_type_table[i].type;
+   return 0;
+   }
+
+   return -1;
+}
+
+static int hi6220_set_platform_data(struct platform_device *pdev)
+{
+   unsigned int base;
+   unsigned int size;
+   unsigned int id;
+   const char *heap_name;
+   const char *type_name;
+   enum ion_heap_type type;
+   int ret;
+   struct device_node *np;
+   struct ion_platform_heap *p_data;
+   const struct device_node *dt_node = pdev->dev.of_node;
+   int index = 0;
+
+   for_each_child_of_node(dt_node, np)
+   num_heaps++;


indentation


+   heaps_data = devm_kzalloc(>dev,
+ sizeof(struct ion_platform_heap *) * 
num_heaps,
+ GFP_KERNEL);


check the result of malloc


+   for_each_child_of_node(dt_node, np) {
+   p_data = devm_kzalloc(>dev,
+ sizeof(struct ion_platform_heap),
+ GFP_KERNEL);


check the result of malloc


+   ret = of_property_read_string(np, "heap-name", _name);
+   if (ret < 0) {
+   pr_err("check the name of node %s\n", np->name);
+   continue;
+   }
+
+   ret = of_property_read_u32(np, "heap-id", );
+   if (ret < 0) {
+   pr_err("check the id %s\n", 

Re: [PATCH 2/3] staging: android: ion: Add ion driver for Hi6220 SoC platform

2015-10-09 Thread xuyiping



On 2015/10/8 15:55, Chen Feng wrote:

Signed-off-by: Chen Feng 
Signed-off-by: Yu Dongbin 
---
  drivers/staging/android/ion/Kconfig|   7 +
  drivers/staging/android/ion/Makefile   |   1 +
  drivers/staging/android/ion/hisilicon/Kconfig  |   5 +
  drivers/staging/android/ion/hisilicon/Makefile |   1 +
  drivers/staging/android/ion/hisilicon/hi6220_ion.c | 201 +
  5 files changed, 215 insertions(+)
  create mode 100644 drivers/staging/android/ion/hisilicon/Kconfig
  create mode 100644 drivers/staging/android/ion/hisilicon/Makefile
  create mode 100644 drivers/staging/android/ion/hisilicon/hi6220_ion.c

diff --git a/drivers/staging/android/ion/Kconfig 
b/drivers/staging/android/ion/Kconfig
index 3452346..19c1572 100644
--- a/drivers/staging/android/ion/Kconfig
+++ b/drivers/staging/android/ion/Kconfig
@@ -33,3 +33,10 @@ config ION_TEGRA
help
  Choose this option if you wish to use ion on an nVidia Tegra.

+config ION_HISI
+   tristate "Ion for Hisilicon"
+   depends on ARCH_HISI && ION
+   help
+ Choose this option if you wish to use ion on Hisilicon Platform.
+
+source "drivers/staging/android/ion/hisilicon/Kconfig"
diff --git a/drivers/staging/android/ion/Makefile 
b/drivers/staging/android/ion/Makefile
index b56fd2b..18cc2aa 100644
--- a/drivers/staging/android/ion/Makefile
+++ b/drivers/staging/android/ion/Makefile
@@ -7,4 +7,5 @@ endif

  obj-$(CONFIG_ION_DUMMY) += ion_dummy_driver.o
  obj-$(CONFIG_ION_TEGRA) += tegra/
+obj-$(CONFIG_ION_HISI) += hisilicon/

diff --git a/drivers/staging/android/ion/hisilicon/Kconfig 
b/drivers/staging/android/ion/hisilicon/Kconfig
new file mode 100644
index 000..2b4bd07
--- /dev/null
+++ b/drivers/staging/android/ion/hisilicon/Kconfig
@@ -0,0 +1,5 @@
+config HI6220_ION
+bool "Hi6220 ION Driver"
+depends on ARCH_HISI && ION
+help
+  Build the Hisilicon Hi6220 ion driver.
diff --git a/drivers/staging/android/ion/hisilicon/Makefile 
b/drivers/staging/android/ion/hisilicon/Makefile
new file mode 100644
index 000..2a89414
--- /dev/null
+++ b/drivers/staging/android/ion/hisilicon/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_HI6220_ION) += hi6220_ion.o
diff --git a/drivers/staging/android/ion/hisilicon/hi6220_ion.c 
b/drivers/staging/android/ion/hisilicon/hi6220_ion.c
new file mode 100644
index 000..b7d39b8
--- /dev/null
+++ b/drivers/staging/android/ion/hisilicon/hi6220_ion.c
@@ -0,0 +1,201 @@
+#define pr_fmt(fmt) "Ion: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "../ion_priv.h"
+#include "../ion.h"
+
+struct hi6220_ion_type_table {
+   const char *name;
+   enum ion_heap_type type;
+};
+
+static struct hi6220_ion_type_table ion_type_table[] = {
+   {"ion_system", ION_HEAP_TYPE_SYSTEM},
+   {"ion_system_contig", ION_HEAP_TYPE_SYSTEM_CONTIG},
+   {"ion_carveout", ION_HEAP_TYPE_CARVEOUT},
+   {"ion_chunk", ION_HEAP_TYPE_CHUNK},
+   {"ion_dma", ION_HEAP_TYPE_DMA},
+   {"ion_custom", ION_HEAP_TYPE_CUSTOM},
+};
+
+static struct ion_device *idev;
+static int num_heaps;
+static struct ion_heap **heaps;
+static struct ion_platform_heap **heaps_data;
+
+static int get_type_by_name(const char *name, enum ion_heap_type *type)
+{
+   int i, n;
+
+   n = ARRAY_SIZE(ion_type_table);
+   for (i = 0; i < n; i++) {
+   if (strncmp(name, ion_type_table[i].name, strlen(name)))
+   continue;
+
+   *type = ion_type_table[i].type;
+   return 0;
+   }
+
+   return -1;
+}
+
+static int hi6220_set_platform_data(struct platform_device *pdev)
+{
+   unsigned int base;
+   unsigned int size;
+   unsigned int id;
+   const char *heap_name;
+   const char *type_name;
+   enum ion_heap_type type;
+   int ret;
+   struct device_node *np;
+   struct ion_platform_heap *p_data;
+   const struct device_node *dt_node = pdev->dev.of_node;
+   int index = 0;
+
+   for_each_child_of_node(dt_node, np)
+   num_heaps++;


indentation


+   heaps_data = devm_kzalloc(>dev,
+ sizeof(struct ion_platform_heap *) * 
num_heaps,
+ GFP_KERNEL);


check the result of malloc


+   for_each_child_of_node(dt_node, np) {
+   p_data = devm_kzalloc(>dev,
+ sizeof(struct ion_platform_heap),
+ GFP_KERNEL);


check the result of malloc


+   ret = of_property_read_string(np, "heap-name", _name);
+   if (ret < 0) {
+   pr_err("check the name of node %s\n", np->name);
+   continue;
+   }
+
+   ret = of_property_read_u32(np, "heap-id", );
+   if (ret < 0) {
+ 

Re: [PATCH V3 3/3] reset: hi6220: Reset driver for hisilicon hi6220 SoC

2015-09-15 Thread xuyiping



On 2015/9/15 11:58, Chen Feng wrote:

Add reset driver for hi6220-hikey board,this driver supply deassert
of IP. on hi6220 SoC.

Signed-off-by: Chen Feng 
---
  drivers/reset/Kconfig  |   1 +
  drivers/reset/Makefile |   1 +
  drivers/reset/hisilicon/Kconfig|   5 ++
  drivers/reset/hisilicon/Makefile   |   1 +
  drivers/reset/hisilicon/hi6220_reset.c | 121 +
  5 files changed, 129 insertions(+)
  create mode 100644 drivers/reset/hisilicon/Kconfig
  create mode 100644 drivers/reset/hisilicon/Makefile
  create mode 100644 drivers/reset/hisilicon/hi6220_reset.c

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 0615f50..df37212 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -13,3 +13,4 @@ menuconfig RESET_CONTROLLER
  If unsure, say no.

  source "drivers/reset/sti/Kconfig"
+source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 157d421..331d7b2 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
  obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
  obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
  obj-$(CONFIG_ARCH_STI) += sti/
+obj-$(CONFIG_ARCH_HISI) += hisilicon/
diff --git a/drivers/reset/hisilicon/Kconfig b/drivers/reset/hisilicon/Kconfig
new file mode 100644
index 000..26bf95a
--- /dev/null
+++ b/drivers/reset/hisilicon/Kconfig
@@ -0,0 +1,5 @@
+config COMMON_RESET_HI6220
+   tristate "Hi6220 Reset Driver"
+   depends on (ARCH_HISI && RESET_CONTROLLER)
+   help
+ Build the Hisilicon Hi6220 reset driver.
diff --git a/drivers/reset/hisilicon/Makefile b/drivers/reset/hisilicon/Makefile
new file mode 100644
index 000..c932f86
--- /dev/null
+++ b/drivers/reset/hisilicon/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_COMMON_RESET_HI6220) += hi6220_reset.o
diff --git a/drivers/reset/hisilicon/hi6220_reset.c 
b/drivers/reset/hisilicon/hi6220_reset.c
new file mode 100644
index 000..3d3de94
--- /dev/null
+++ b/drivers/reset/hisilicon/hi6220_reset.c
@@ -0,0 +1,121 @@
+/*
+ * Hisilicon Hi6220 reset controller driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Feng Chen 
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ASSET_OFFSET0x300
+#define DEASSET_OFFSET  0x304
+
+#define to_reset_data(x) container_of(x, struct hi6220_reset_data, rc_dev)
+
+struct hi6220_reset_data {
+   spinlock_t  reset_lock; /*device spin-lock*/


it looks useless


+   void __iomem*asset_base;
+   void __iomem*deasset_base;
+   struct reset_controller_dev rc_dev;
+};
+
+static int hi6220_reset_assert(struct reset_controller_dev *rc_dev,
+  unsigned long idx)
+{
+   struct hi6220_reset_data *data = to_reset_data(rc_dev);
+
+   unsigned long flags;
+   int bank = idx >> 8;
+   int offset = idx & 0xff;
+
+   spin_lock_irqsave(>reset_lock, flags);
+
+   writel(BIT(offset), data->asset_base + (bank * 0x10));
+
+   spin_unlock_irqrestore(>reset_lock, flags);
+
+   return 0;
+}
+
+static int hi6220_reset_deassert(struct reset_controller_dev *rc_dev,
+unsigned long idx)
+{
+   struct hi6220_reset_data *data = to_reset_data(rc_dev);
+
+   unsigned long flags;
+   int bank = idx >> 8;
+   int offset = idx & 0xff;
+
+   spin_lock_irqsave(>reset_lock, flags);
+
+   writel(BIT(offset), data->deasset_base + (bank * 0x10));
+
+   spin_unlock_irqrestore(>reset_lock, flags);
+
+   return 0;
+}
+
+static struct reset_control_ops hi6220_reset_ops = {
+   .assert = hi6220_reset_assert,
+   .deassert = hi6220_reset_deassert,
+};
+
+static int hi6220_reset_probe(struct platform_device *pdev)
+{
+   struct hi6220_reset_data *data;
+   struct resource *res;
+   void __iomem *src_base;
+
+   data = devm_kzalloc(>dev, sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   src_base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(src_base))
+   return PTR_ERR(src_base);
+
+   spin_lock_init(>reset_lock);
+
+   data->asset_base = src_base + ASSET_OFFSET;
+   data->deasset_base = src_base + DEASSET_OFFSET;
+   data->rc_dev.nr_resets = SZ_4K;


use the max index of the reset bit


+   data->rc_dev.ops = _reset_ops;
+   data->rc_dev.of_node = pdev->dev.of_node;
+
+   reset_controller_register(>rc_dev);
+
+   return 0;
+}
+
+static const struct 

Re: [PATCH V3 3/3] reset: hi6220: Reset driver for hisilicon hi6220 SoC

2015-09-15 Thread xuyiping



On 2015/9/15 11:58, Chen Feng wrote:

Add reset driver for hi6220-hikey board,this driver supply deassert
of IP. on hi6220 SoC.

Signed-off-by: Chen Feng 
---
  drivers/reset/Kconfig  |   1 +
  drivers/reset/Makefile |   1 +
  drivers/reset/hisilicon/Kconfig|   5 ++
  drivers/reset/hisilicon/Makefile   |   1 +
  drivers/reset/hisilicon/hi6220_reset.c | 121 +
  5 files changed, 129 insertions(+)
  create mode 100644 drivers/reset/hisilicon/Kconfig
  create mode 100644 drivers/reset/hisilicon/Makefile
  create mode 100644 drivers/reset/hisilicon/hi6220_reset.c

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 0615f50..df37212 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -13,3 +13,4 @@ menuconfig RESET_CONTROLLER
  If unsure, say no.

  source "drivers/reset/sti/Kconfig"
+source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 157d421..331d7b2 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
  obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
  obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
  obj-$(CONFIG_ARCH_STI) += sti/
+obj-$(CONFIG_ARCH_HISI) += hisilicon/
diff --git a/drivers/reset/hisilicon/Kconfig b/drivers/reset/hisilicon/Kconfig
new file mode 100644
index 000..26bf95a
--- /dev/null
+++ b/drivers/reset/hisilicon/Kconfig
@@ -0,0 +1,5 @@
+config COMMON_RESET_HI6220
+   tristate "Hi6220 Reset Driver"
+   depends on (ARCH_HISI && RESET_CONTROLLER)
+   help
+ Build the Hisilicon Hi6220 reset driver.
diff --git a/drivers/reset/hisilicon/Makefile b/drivers/reset/hisilicon/Makefile
new file mode 100644
index 000..c932f86
--- /dev/null
+++ b/drivers/reset/hisilicon/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_COMMON_RESET_HI6220) += hi6220_reset.o
diff --git a/drivers/reset/hisilicon/hi6220_reset.c 
b/drivers/reset/hisilicon/hi6220_reset.c
new file mode 100644
index 000..3d3de94
--- /dev/null
+++ b/drivers/reset/hisilicon/hi6220_reset.c
@@ -0,0 +1,121 @@
+/*
+ * Hisilicon Hi6220 reset controller driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Feng Chen 
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ASSET_OFFSET0x300
+#define DEASSET_OFFSET  0x304
+
+#define to_reset_data(x) container_of(x, struct hi6220_reset_data, rc_dev)
+
+struct hi6220_reset_data {
+   spinlock_t  reset_lock; /*device spin-lock*/


it looks useless


+   void __iomem*asset_base;
+   void __iomem*deasset_base;
+   struct reset_controller_dev rc_dev;
+};
+
+static int hi6220_reset_assert(struct reset_controller_dev *rc_dev,
+  unsigned long idx)
+{
+   struct hi6220_reset_data *data = to_reset_data(rc_dev);
+
+   unsigned long flags;
+   int bank = idx >> 8;
+   int offset = idx & 0xff;
+
+   spin_lock_irqsave(>reset_lock, flags);
+
+   writel(BIT(offset), data->asset_base + (bank * 0x10));
+
+   spin_unlock_irqrestore(>reset_lock, flags);
+
+   return 0;
+}
+
+static int hi6220_reset_deassert(struct reset_controller_dev *rc_dev,
+unsigned long idx)
+{
+   struct hi6220_reset_data *data = to_reset_data(rc_dev);
+
+   unsigned long flags;
+   int bank = idx >> 8;
+   int offset = idx & 0xff;
+
+   spin_lock_irqsave(>reset_lock, flags);
+
+   writel(BIT(offset), data->deasset_base + (bank * 0x10));
+
+   spin_unlock_irqrestore(>reset_lock, flags);
+
+   return 0;
+}
+
+static struct reset_control_ops hi6220_reset_ops = {
+   .assert = hi6220_reset_assert,
+   .deassert = hi6220_reset_deassert,
+};
+
+static int hi6220_reset_probe(struct platform_device *pdev)
+{
+   struct hi6220_reset_data *data;
+   struct resource *res;
+   void __iomem *src_base;
+
+   data = devm_kzalloc(>dev, sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+   src_base = devm_ioremap_resource(>dev, res);
+   if (IS_ERR(src_base))
+   return PTR_ERR(src_base);
+
+   spin_lock_init(>reset_lock);
+
+   data->asset_base = src_base + ASSET_OFFSET;
+   data->deasset_base = src_base + DEASSET_OFFSET;
+   data->rc_dev.nr_resets = SZ_4K;


use the max index of the reset bit


+   data->rc_dev.ops = _reset_ops;
+   data->rc_dev.of_node = pdev->dev.of_node;
+
+   reset_controller_register(>rc_dev);
+
+  

Re: [PATCH V2 3/3] reset: hi6220: Reset driver for hisilicon hi6220 SoC

2015-09-12 Thread xuyiping



On 2015/9/11 16:18, Chen Feng wrote:

Add reset driver for hi6220-hikey board,this driver supply deassert
of IP. on hi6220 SoC.

Signed-off-by: Chen Feng 
---
  drivers/reset/Kconfig  |   1 +
  drivers/reset/Makefile |   1 +
  drivers/reset/hisilicon/Kconfig|   5 ++
  drivers/reset/hisilicon/Makefile   |   1 +
  drivers/reset/hisilicon/hi6220_reset.c | 118 +
  5 files changed, 126 insertions(+)
  create mode 100644 drivers/reset/hisilicon/Kconfig
  create mode 100644 drivers/reset/hisilicon/Makefile
  create mode 100644 drivers/reset/hisilicon/hi6220_reset.c

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 0615f50..df37212 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -13,3 +13,4 @@ menuconfig RESET_CONTROLLER
  If unsure, say no.

  source "drivers/reset/sti/Kconfig"
+source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 157d421..331d7b2 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
  obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
  obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
  obj-$(CONFIG_ARCH_STI) += sti/
+obj-$(CONFIG_ARCH_HISI) += hisilicon/
diff --git a/drivers/reset/hisilicon/Kconfig b/drivers/reset/hisilicon/Kconfig
new file mode 100644
index 000..26bf95a
--- /dev/null
+++ b/drivers/reset/hisilicon/Kconfig
@@ -0,0 +1,5 @@
+config COMMON_RESET_HI6220
+   tristate "Hi6220 Reset Driver"
+   depends on (ARCH_HISI && RESET_CONTROLLER)
+   help
+ Build the Hisilicon Hi6220 reset driver.
diff --git a/drivers/reset/hisilicon/Makefile b/drivers/reset/hisilicon/Makefile
new file mode 100644
index 000..c932f86
--- /dev/null
+++ b/drivers/reset/hisilicon/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_COMMON_RESET_HI6220) += hi6220_reset.o
diff --git a/drivers/reset/hisilicon/hi6220_reset.c 
b/drivers/reset/hisilicon/hi6220_reset.c
new file mode 100644
index 000..097133d
--- /dev/null
+++ b/drivers/reset/hisilicon/hi6220_reset.c
@@ -0,0 +1,118 @@
+/*
+ * Hisilicon Hi6220 reset controller driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Feng Chen 
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ASSET_OFFSET0x300
+#define DEASSET_OFFSET  0x304
+
+struct hi6220_reset_data {
+   spinlock_t  reset_lock; /*device spin-lock*/
+   void __iomem*src_base;
+   void __iomem*asset_base;
+   void __iomem*deasset_base;
+   struct reset_controller_dev rc_dev;
+};
+
+static int hi6220_reset_assert(struct reset_controller_dev *rc_dev,
+  unsigned long idx)
+{
+   struct hi6220_reset_data *data = container_of(rc_dev,
+   struct hi6220_reset_data,
+   rc_dev);
+
+   unsigned long flags;
+   int bank = idx >> 8;
+   int offset = idx & 0xff;
+
+   spin_lock_irqsave(>reset_lock, flags);


the spin_lock looks useless.

it is not a "read and write" register.


+   writel(BIT(offset), data->asset_base + (bank * 0x10));
+
+   spin_unlock_irqrestore(>reset_lock, flags);
+
+   return 0;
+}
+
+static int hi6220_reset_deassert(struct reset_controller_dev *rc_dev,
+unsigned long idx)
+{
+   struct hi6220_reset_data *data = container_of(rc_dev,
+   struct hi6220_reset_data,
+   rc_dev);
+
+   unsigned long flags;
+   int bank = idx >> 8;
+   int offset = idx & 0xff;


no need to check the idx scope ?


+   spin_lock_irqsave(>reset_lock, flags);
+
+   writel(BIT(offset), data->deasset_base + (bank * 0x10));
+
+   spin_unlock_irqrestore(>reset_lock, flags);
+
+   return 0;
+}
+
+static struct reset_control_ops hi6220_reset_ops = {
+   .assert = hi6220_reset_assert,
+   .deassert = hi6220_reset_deassert,
+};
+
+static int __init hi6220_reset_init(void)
+{
+   int ret;
+   struct device_node *np;
+   struct hi6220_reset_data *data;
+
+   data = kzalloc(sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   np = of_find_compatible_node(NULL, NULL, "hisilicon,hi6220_reset_ctl");
+   if (!np) {
+   ret = -ENXIO;
+   goto err_alloc;
+   }
+   spin_lock_init(>reset_lock);
+   data->src_base = of_iomap(np, 0);
+   if (!data->src_base) {
+   ret = -ENOMEM;
+   goto err_alloc;
+   }
+
+   data->asset_base = 

Re: [PATCH V2 3/3] reset: hi6220: Reset driver for hisilicon hi6220 SoC

2015-09-12 Thread xuyiping



On 2015/9/11 16:18, Chen Feng wrote:

Add reset driver for hi6220-hikey board,this driver supply deassert
of IP. on hi6220 SoC.

Signed-off-by: Chen Feng 
---
  drivers/reset/Kconfig  |   1 +
  drivers/reset/Makefile |   1 +
  drivers/reset/hisilicon/Kconfig|   5 ++
  drivers/reset/hisilicon/Makefile   |   1 +
  drivers/reset/hisilicon/hi6220_reset.c | 118 +
  5 files changed, 126 insertions(+)
  create mode 100644 drivers/reset/hisilicon/Kconfig
  create mode 100644 drivers/reset/hisilicon/Makefile
  create mode 100644 drivers/reset/hisilicon/hi6220_reset.c

diff --git a/drivers/reset/Kconfig b/drivers/reset/Kconfig
index 0615f50..df37212 100644
--- a/drivers/reset/Kconfig
+++ b/drivers/reset/Kconfig
@@ -13,3 +13,4 @@ menuconfig RESET_CONTROLLER
  If unsure, say no.

  source "drivers/reset/sti/Kconfig"
+source "drivers/reset/hisilicon/Kconfig"
diff --git a/drivers/reset/Makefile b/drivers/reset/Makefile
index 157d421..331d7b2 100644
--- a/drivers/reset/Makefile
+++ b/drivers/reset/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_ARCH_SOCFPGA) += reset-socfpga.o
  obj-$(CONFIG_ARCH_BERLIN) += reset-berlin.o
  obj-$(CONFIG_ARCH_SUNXI) += reset-sunxi.o
  obj-$(CONFIG_ARCH_STI) += sti/
+obj-$(CONFIG_ARCH_HISI) += hisilicon/
diff --git a/drivers/reset/hisilicon/Kconfig b/drivers/reset/hisilicon/Kconfig
new file mode 100644
index 000..26bf95a
--- /dev/null
+++ b/drivers/reset/hisilicon/Kconfig
@@ -0,0 +1,5 @@
+config COMMON_RESET_HI6220
+   tristate "Hi6220 Reset Driver"
+   depends on (ARCH_HISI && RESET_CONTROLLER)
+   help
+ Build the Hisilicon Hi6220 reset driver.
diff --git a/drivers/reset/hisilicon/Makefile b/drivers/reset/hisilicon/Makefile
new file mode 100644
index 000..c932f86
--- /dev/null
+++ b/drivers/reset/hisilicon/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_COMMON_RESET_HI6220) += hi6220_reset.o
diff --git a/drivers/reset/hisilicon/hi6220_reset.c 
b/drivers/reset/hisilicon/hi6220_reset.c
new file mode 100644
index 000..097133d
--- /dev/null
+++ b/drivers/reset/hisilicon/hi6220_reset.c
@@ -0,0 +1,118 @@
+/*
+ * Hisilicon Hi6220 reset controller driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Feng Chen 
+ *
+ * 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.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define ASSET_OFFSET0x300
+#define DEASSET_OFFSET  0x304
+
+struct hi6220_reset_data {
+   spinlock_t  reset_lock; /*device spin-lock*/
+   void __iomem*src_base;
+   void __iomem*asset_base;
+   void __iomem*deasset_base;
+   struct reset_controller_dev rc_dev;
+};
+
+static int hi6220_reset_assert(struct reset_controller_dev *rc_dev,
+  unsigned long idx)
+{
+   struct hi6220_reset_data *data = container_of(rc_dev,
+   struct hi6220_reset_data,
+   rc_dev);
+
+   unsigned long flags;
+   int bank = idx >> 8;
+   int offset = idx & 0xff;
+
+   spin_lock_irqsave(>reset_lock, flags);


the spin_lock looks useless.

it is not a "read and write" register.


+   writel(BIT(offset), data->asset_base + (bank * 0x10));
+
+   spin_unlock_irqrestore(>reset_lock, flags);
+
+   return 0;
+}
+
+static int hi6220_reset_deassert(struct reset_controller_dev *rc_dev,
+unsigned long idx)
+{
+   struct hi6220_reset_data *data = container_of(rc_dev,
+   struct hi6220_reset_data,
+   rc_dev);
+
+   unsigned long flags;
+   int bank = idx >> 8;
+   int offset = idx & 0xff;


no need to check the idx scope ?


+   spin_lock_irqsave(>reset_lock, flags);
+
+   writel(BIT(offset), data->deasset_base + (bank * 0x10));
+
+   spin_unlock_irqrestore(>reset_lock, flags);
+
+   return 0;
+}
+
+static struct reset_control_ops hi6220_reset_ops = {
+   .assert = hi6220_reset_assert,
+   .deassert = hi6220_reset_deassert,
+};
+
+static int __init hi6220_reset_init(void)
+{
+   int ret;
+   struct device_node *np;
+   struct hi6220_reset_data *data;
+
+   data = kzalloc(sizeof(*data), GFP_KERNEL);
+   if (!data)
+   return -ENOMEM;
+
+   np = of_find_compatible_node(NULL, NULL, "hisilicon,hi6220_reset_ctl");
+   if (!np) {
+   ret = -ENXIO;
+   goto err_alloc;
+   }
+   spin_lock_init(>reset_lock);
+   data->src_base = of_iomap(np, 0);
+   if (!data->src_base) {
+   ret = -ENOMEM;
+   goto