summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRicardo Ribalda Delgado <ricardo.ribalda@gmail.com>2018-10-04 09:01:06 -0400
committerBoris Brezillon <boris.brezillon@bootlin.com>2018-10-08 15:32:49 -0400
commit460cdeca546fc75f2450914c96e701f990396285 (patch)
tree7a610da79206aad6dac00c6ee6a3dd98ef87397d
parent4edc00adfd58768b065204968948c52f5e5b07b1 (diff)
mtd: maps: gpio-addr-flash: Use order instead of size
By using the order of the window instead of the size, we can replace a lot of expensive division and modulus on the code with simple bit operations. Signed-off-by: Ricardo Ribalda Delgado <ricardo.ribalda@gmail.com> Signed-off-by: Boris Brezillon <boris.brezillon@bootlin.com>
-rw-r--r--drivers/mtd/maps/gpio-addr-flash.c39
1 files changed, 21 insertions, 18 deletions
diff --git a/drivers/mtd/maps/gpio-addr-flash.c b/drivers/mtd/maps/gpio-addr-flash.c
index 84404dcc7824..89cc8cce161b 100644
--- a/drivers/mtd/maps/gpio-addr-flash.c
+++ b/drivers/mtd/maps/gpio-addr-flash.c
@@ -25,6 +25,8 @@
25#include <linux/slab.h> 25#include <linux/slab.h>
26#include <linux/types.h> 26#include <linux/types.h>
27 27
28#define win_mask(x) ((BIT(x)) - 1)
29
28#define DRIVER_NAME "gpio-addr-flash" 30#define DRIVER_NAME "gpio-addr-flash"
29 31
30/** 32/**
@@ -34,7 +36,7 @@
34 * @gpio_count: number of GPIOs used to address 36 * @gpio_count: number of GPIOs used to address
35 * @gpio_addrs: array of GPIOs to twiddle 37 * @gpio_addrs: array of GPIOs to twiddle
36 * @gpio_values: cached GPIO values 38 * @gpio_values: cached GPIO values
37 * @win_size: dedicated memory size (if no GPIOs) 39 * @win_order: dedicated memory size (if no GPIOs)
38 */ 40 */
39struct async_state { 41struct async_state {
40 struct mtd_info *mtd; 42 struct mtd_info *mtd;
@@ -42,7 +44,7 @@ struct async_state {
42 size_t gpio_count; 44 size_t gpio_count;
43 unsigned *gpio_addrs; 45 unsigned *gpio_addrs;
44 int *gpio_values; 46 int *gpio_values;
45 unsigned long win_size; 47 unsigned int win_order;
46}; 48};
47#define gf_map_info_to_state(mi) ((struct async_state *)(mi)->map_priv_1) 49#define gf_map_info_to_state(mi) ((struct async_state *)(mi)->map_priv_1)
48 50
@@ -60,7 +62,8 @@ static void gf_set_gpios(struct async_state *state, unsigned long ofs)
60{ 62{
61 size_t i = 0; 63 size_t i = 0;
62 int value; 64 int value;
63 ofs /= state->win_size; 65
66 ofs >>= state->win_order;
64 do { 67 do {
65 value = ofs & (1 << i); 68 value = ofs & (1 << i);
66 if (state->gpio_values[i] != value) { 69 if (state->gpio_values[i] != value) {
@@ -83,7 +86,7 @@ static map_word gf_read(struct map_info *map, unsigned long ofs)
83 86
84 gf_set_gpios(state, ofs); 87 gf_set_gpios(state, ofs);
85 88
86 word = readw(map->virt + (ofs % state->win_size)); 89 word = readw(map->virt + (ofs & win_mask(state->win_order)));
87 test.x[0] = word; 90 test.x[0] = word;
88 return test; 91 return test;
89} 92}
@@ -105,14 +108,14 @@ static void gf_copy_from(struct map_info *map, void *to, unsigned long from, ssi
105 int this_len; 108 int this_len;
106 109
107 while (len) { 110 while (len) {
108 if ((from % state->win_size) + len > state->win_size) 111 this_len = from & win_mask(state->win_order);
109 this_len = state->win_size - (from % state->win_size); 112 this_len = BIT(state->win_order) - this_len;
110 else 113 this_len = min_t(int, len, this_len);
111 this_len = len;
112 114
113 gf_set_gpios(state, from); 115 gf_set_gpios(state, from);
114 memcpy_fromio(to, map->virt + (from % state->win_size), 116 memcpy_fromio(to,
115 this_len); 117 map->virt + (from & win_mask(state->win_order)),
118 this_len);
116 len -= this_len; 119 len -= this_len;
117 from += this_len; 120 from += this_len;
118 to += this_len; 121 to += this_len;
@@ -132,7 +135,7 @@ static void gf_write(struct map_info *map, map_word d1, unsigned long ofs)
132 gf_set_gpios(state, ofs); 135 gf_set_gpios(state, ofs);
133 136
134 d = d1.x[0]; 137 d = d1.x[0];
135 writew(d, map->virt + (ofs % state->win_size)); 138 writew(d, map->virt + (ofs & win_mask(state->win_order)));
136} 139}
137 140
138/** 141/**
@@ -152,13 +155,13 @@ static void gf_copy_to(struct map_info *map, unsigned long to,
152 int this_len; 155 int this_len;
153 156
154 while (len) { 157 while (len) {
155 if ((to % state->win_size) + len > state->win_size) 158 this_len = to & win_mask(state->win_order);
156 this_len = state->win_size - (to % state->win_size); 159 this_len = BIT(state->win_order) - this_len;
157 else 160 this_len = min_t(int, len, this_len);
158 this_len = len;
159 161
160 gf_set_gpios(state, to); 162 gf_set_gpios(state, to);
161 memcpy_toio(map->virt + (to % state->win_size), from, len); 163 memcpy_toio(map->virt + (to & win_mask(state->win_order)),
164 from, len);
162 165
163 len -= this_len; 166 len -= this_len;
164 to += this_len; 167 to += this_len;
@@ -224,7 +227,7 @@ static int gpio_flash_probe(struct platform_device *pdev)
224 state->gpio_count = gpios->end; 227 state->gpio_count = gpios->end;
225 state->gpio_addrs = (void *)(unsigned long)gpios->start; 228 state->gpio_addrs = (void *)(unsigned long)gpios->start;
226 state->gpio_values = (void *)(state + 1); 229 state->gpio_values = (void *)(state + 1);
227 state->win_size = resource_size(memory); 230 state->win_order = get_bitmask_order(resource_size(memory)) - 1;
228 memset(state->gpio_values, 0xff, arr_size); 231 memset(state->gpio_values, 0xff, arr_size);
229 232
230 state->map.name = DRIVER_NAME; 233 state->map.name = DRIVER_NAME;
@@ -233,7 +236,7 @@ static int gpio_flash_probe(struct platform_device *pdev)
233 state->map.write = gf_write; 236 state->map.write = gf_write;
234 state->map.copy_to = gf_copy_to; 237 state->map.copy_to = gf_copy_to;
235 state->map.bankwidth = pdata->width; 238 state->map.bankwidth = pdata->width;
236 state->map.size = state->win_size * (1 << state->gpio_count); 239 state->map.size = BIT(state->win_order + state->gpio_count);
237 state->map.virt = devm_ioremap_resource(&pdev->dev, memory); 240 state->map.virt = devm_ioremap_resource(&pdev->dev, memory);
238 if (IS_ERR(state->map.virt)) 241 if (IS_ERR(state->map.virt))
239 return PTR_ERR(state->map.virt); 242 return PTR_ERR(state->map.virt);