2013-04-24 03:29:27

by Chao Xie

[permalink] [raw]
Subject: [PATCH 0/6] input: pxa27x-keypad: enhancement and device tree support

The patches include 3 parts
1. copy members of platform data to device private data
pdata pass when probing the device may be freed after device initialized.
It is not safe to use pdata in other places except probe device. So copy
some useful members from pdata to device private structure.

2. use matrix_keypad for matrix keyes support
3. add device tree support for pxa27x-keypad

Chao Xie (6):
input: pxa27x-keypad: copy members of platform data to device private
data
input: pxa27x-keypad: use matrix_keymap for matrix keyes
arm: mmp: use matrix_keymap for aspenite
arm: mmp: use matrix_keymap for teton_bga
input: pxa27x-keypad: remove the unused members at platform data
input: pxa27x-keypad: add device tree support

.../devicetree/bindings/input/pxa27x-keypad.txt | 60 ++++
arch/arm/mach-mmp/aspenite.c | 10 +-
arch/arm/mach-mmp/teton_bga.c | 8 +-
drivers/input/keyboard/Kconfig | 1 +
drivers/input/keyboard/pxa27x_keypad.c | 320 +++++++++++++++++---
include/linux/platform_data/keypad-pxa27x.h | 3 +-
6 files changed, 346 insertions(+), 56 deletions(-)
create mode 100644 Documentation/devicetree/bindings/input/pxa27x-keypad.txt

--
1.7.4.1


2013-04-24 03:24:18

by Chao Xie

[permalink] [raw]
Subject: [PATCH 1/6] input: pxa27x-keypad: copy members of platform data to device private data

Original driver will directly use platform data when driver is
running.
In fact, the platform data may be freed after system is bootup,
or pointer for platform data is NULL if it has device tree support.
Define the useful members of platform data in device private data.

Signed-off-by: Chao Xie <[email protected]>
---
drivers/input/keyboard/pxa27x_keypad.c | 97 ++++++++++++++++++++-----------
1 files changed, 62 insertions(+), 35 deletions(-)

diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 5330d8f..023243a 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -100,8 +100,6 @@
#define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM)

struct pxa27x_keypad {
- struct pxa27x_keypad_platform_data *pdata;
-
struct clk *clk;
struct input_dev *input_dev;
void __iomem *mmio_base;
@@ -116,15 +114,33 @@ struct pxa27x_keypad {
uint32_t direct_key_state;

unsigned int direct_key_mask;
+
+ /* from platform data */
+ unsigned int matrix_key_rows;
+ unsigned int matrix_key_cols;
+
+ int direct_key_low_active;
+ unsigned int direct_key_num;
+ unsigned int default_direct_key_mask;
+
+ int enable_rotary0;
+ int enable_rotary1;
+
+ unsigned int debounce_interval;
+
+ void (*clear_wakeup_event)(void);
};

-static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
+static int pxa27x_keypad_build_keycode(struct device *dev,
+ struct pxa27x_keypad *keypad,
+ struct pxa27x_keypad_platform_data *pdata,
+ struct input_dev *input_dev)
{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
- struct input_dev *input_dev = keypad->input_dev;
unsigned short keycode;
int i;

+ keypad->matrix_key_rows = pdata->matrix_key_rows;
+ keypad->matrix_key_cols = pdata->matrix_key_cols;
for (i = 0; i < pdata->matrix_key_map_size; i++) {
unsigned int key = pdata->matrix_key_map[i];
unsigned int row = KEY_ROW(key);
@@ -137,12 +153,16 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
__set_bit(keycode, input_dev->keybit);
}

+ keypad->direct_key_low_active = pdata->direct_key_low_active;
+ keypad->direct_key_num = pdata->direct_key_num;
+ keypad->default_direct_key_mask = pdata->direct_key_mask;
for (i = 0; i < pdata->direct_key_num; i++) {
keycode = pdata->direct_key_map[i];
keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode;
__set_bit(keycode, input_dev->keybit);
}

+ keypad->enable_rotary0 = pdata->enable_rotary0;
if (pdata->enable_rotary0) {
if (pdata->rotary0_up_key && pdata->rotary0_down_key) {
keycode = pdata->rotary0_up_key;
@@ -160,6 +180,7 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
}
}

+ keypad->enable_rotary1 = pdata->enable_rotary1;
if (pdata->enable_rotary1) {
if (pdata->rotary1_up_key && pdata->rotary1_down_key) {
keycode = pdata->rotary1_up_key;
@@ -178,11 +199,14 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
}

__clear_bit(KEY_RESERVED, input_dev->keybit);
+
+ keypad->debounce_interval = pdata->debounce_interval;
+
+ return 0;
}

static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
struct input_dev *input_dev = keypad->input_dev;
int row, col, num_keys_pressed = 0;
uint32_t new_state[MAX_MATRIX_KEY_COLS];
@@ -200,8 +224,8 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
row = KPAS_RP(kpas);

/* if invalid row/col, treat as no key pressed */
- if (col >= pdata->matrix_key_cols ||
- row >= pdata->matrix_key_rows)
+ if (col >= keypad->matrix_key_cols ||
+ row >= keypad->matrix_key_rows)
goto scan;

new_state[col] = (1 << row);
@@ -224,7 +248,7 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
new_state[7] = (kpasmkp3 >> 16) & KPASMKP_MKC_MASK;
}
scan:
- for (col = 0; col < pdata->matrix_key_cols; col++) {
+ for (col = 0; col < keypad->matrix_key_cols; col++) {
uint32_t bits_changed;
int code;

@@ -232,7 +256,7 @@ scan:
if (bits_changed == 0)
continue;

- for (row = 0; row < pdata->matrix_key_rows; row++) {
+ for (row = 0; row < keypad->matrix_key_rows; row++) {
if ((bits_changed & (1 << row)) == 0)
continue;

@@ -284,23 +308,21 @@ static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta)

static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad)
{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
uint32_t kprec;

/* read and reset to default count value */
kprec = keypad_readl(KPREC);
keypad_writel(KPREC, DEFAULT_KPREC);

- if (pdata->enable_rotary0)
+ if (keypad->enable_rotary0)
report_rotary_event(keypad, 0, rotary_delta(kprec));

- if (pdata->enable_rotary1)
+ if (keypad->enable_rotary1)
report_rotary_event(keypad, 1, rotary_delta(kprec >> 16));
}

static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
struct input_dev *input_dev = keypad->input_dev;
unsigned int new_state;
uint32_t kpdk, bits_changed;
@@ -308,14 +330,14 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)

kpdk = keypad_readl(KPDK);

- if (pdata->enable_rotary0 || pdata->enable_rotary1)
+ if (keypad->enable_rotary0 || keypad->enable_rotary1)
pxa27x_keypad_scan_rotary(keypad);

/*
* The KPDR_DK only output the key pin level, so it relates to board,
* and low level may be active.
*/
- if (pdata->direct_key_low_active)
+ if (keypad->direct_key_low_active)
new_state = ~KPDK_DK(kpdk) & keypad->direct_key_mask;
else
new_state = KPDK_DK(kpdk) & keypad->direct_key_mask;
@@ -325,7 +347,7 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
if (bits_changed == 0)
return;

- for (i = 0; i < pdata->direct_key_num; i++) {
+ for (i = 0; i < keypad->direct_key_num; i++) {
if (bits_changed & (1 << i)) {
int code = MAX_MATRIX_KEY_NUM + i;

@@ -340,10 +362,9 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)

static void clear_wakeup_event(struct pxa27x_keypad *keypad)
{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;

- if (pdata->clear_wakeup_event)
- (pdata->clear_wakeup_event)();
+ if (keypad->clear_wakeup_event)
+ (keypad->clear_wakeup_event)();
}

static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
@@ -364,7 +385,6 @@ static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)

static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
{
- struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
unsigned int mask = 0, direct_key_num = 0;
unsigned long kpc = 0;

@@ -372,34 +392,34 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
keypad_readl(KPC);

/* enable matrix keys with automatic scan */
- if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
+ if (keypad->matrix_key_rows && keypad->matrix_key_cols) {
kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
- kpc |= KPC_MKRN(pdata->matrix_key_rows) |
- KPC_MKCN(pdata->matrix_key_cols);
+ kpc |= KPC_MKRN(keypad->matrix_key_rows) |
+ KPC_MKCN(keypad->matrix_key_cols);
}

/* enable rotary key, debounce interval same as direct keys */
- if (pdata->enable_rotary0) {
+ if (keypad->enable_rotary0) {
mask |= 0x03;
direct_key_num = 2;
kpc |= KPC_REE0;
}

- if (pdata->enable_rotary1) {
+ if (keypad->enable_rotary1) {
mask |= 0x0c;
direct_key_num = 4;
kpc |= KPC_REE1;
}

- if (pdata->direct_key_num > direct_key_num)
- direct_key_num = pdata->direct_key_num;
+ if (keypad->direct_key_num > direct_key_num)
+ direct_key_num = keypad->direct_key_num;

/*
* Direct keys usage may not start from KP_DKIN0, check the platfrom
* mask data to config the specific.
*/
- if (pdata->direct_key_mask)
- keypad->direct_key_mask = pdata->direct_key_mask;
+ if (keypad->default_direct_key_mask)
+ keypad->direct_key_mask = keypad->default_direct_key_mask;
else
keypad->direct_key_mask = ((1 << direct_key_num) - 1) & ~mask;

@@ -409,7 +429,7 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)

keypad_writel(KPC, kpc | KPC_RE_ZERO_DEB);
keypad_writel(KPREC, DEFAULT_KPREC);
- keypad_writel(KPKDI, pdata->debounce_interval);
+ keypad_writel(KPKDI, keypad->debounce_interval);
}

static int pxa27x_keypad_open(struct input_dev *dev)
@@ -515,7 +535,6 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
goto failed_free;
}

- keypad->pdata = pdata;
keypad->input_dev = input_dev;
keypad->irq = irq;

@@ -555,10 +574,18 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);

- pxa27x_keypad_build_keycode(keypad);
+ if (pdata->clear_wakeup_event)
+ keypad->clear_wakeup_event = pdata->clear_wakeup_event;
+
+ error = pxa27x_keypad_build_keycode(&pdev->dev, keypad, pdata,
+ input_dev);
+ if (error) {
+ dev_err(&pdev->dev, "failed to build keycode\n");
+ goto failed_put_clk;
+ }

- if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) ||
- (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) {
+ if ((keypad->enable_rotary0 && keypad->rotary_rel_code[0] != -1) ||
+ (keypad->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) {
input_dev->evbit[0] |= BIT_MASK(EV_REL);
}

--
1.7.4.1

2013-04-24 03:25:56

by Chao Xie

[permalink] [raw]
Subject: [PATCH 3/6] arm: mmp: use matrix_keymap for aspenite

Signed-off-by: Chao Xie <[email protected]>
---
arch/arm/mach-mmp/aspenite.c | 10 +++++++---
1 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/arch/arm/mach-mmp/aspenite.c b/arch/arm/mach-mmp/aspenite.c
index 9f64d56..1e23346 100644
--- a/arch/arm/mach-mmp/aspenite.c
+++ b/arch/arm/mach-mmp/aspenite.c
@@ -205,7 +205,7 @@ struct pxa168fb_mach_info aspenite_lcd_info = {
.invert_pixclock = 0,
};

-static unsigned int aspenite_matrix_key_map[] = {
+static const unsigned int aspenite_matrix_key_map[] = {
KEY(0, 6, KEY_UP), /* SW 4 */
KEY(0, 7, KEY_DOWN), /* SW 5 */
KEY(1, 6, KEY_LEFT), /* SW 6 */
@@ -214,11 +214,15 @@ static unsigned int aspenite_matrix_key_map[] = {
KEY(4, 7, KEY_ESC), /* SW 9 */
};

+static struct matrix_keymap_data aspenite_matrix_keymap_data = {
+ .keymap = aspenite_matrix_key_map,
+ .keymap_size = ARRAY_SIZE(aspenite_matrix_key_map),
+};
+
static struct pxa27x_keypad_platform_data aspenite_keypad_info __initdata = {
.matrix_key_rows = 5,
.matrix_key_cols = 8,
- .matrix_key_map = aspenite_matrix_key_map,
- .matrix_key_map_size = ARRAY_SIZE(aspenite_matrix_key_map),
+ .matrix_keymap_data = &aspenite_matrix_keymap_data,
.debounce_interval = 30,
};

--
1.7.4.1

2013-04-24 03:26:03

by Chao Xie

[permalink] [raw]
Subject: [PATCH 5/6] input: pxa27x-keypad: remove the unused members at platform data

Now pxa27x-keypad make use matrix_keymap for matrix keyes, so
remove the unused members in platform data.

Signed-off-by: Chao Xie <[email protected]>
---
include/linux/platform_data/keypad-pxa27x.h | 2 --
1 files changed, 0 insertions(+), 2 deletions(-)

diff --git a/include/linux/platform_data/keypad-pxa27x.h b/include/linux/platform_data/keypad-pxa27x.h
index 0db423b..2462556 100644
--- a/include/linux/platform_data/keypad-pxa27x.h
+++ b/include/linux/platform_data/keypad-pxa27x.h
@@ -39,8 +39,6 @@ struct pxa27x_keypad_platform_data {
const struct matrix_keymap_data *matrix_keymap_data;
unsigned int matrix_key_rows;
unsigned int matrix_key_cols;
- unsigned int *matrix_key_map;
- int matrix_key_map_size;

/* direct keys */
int direct_key_num;
--
1.7.4.1

2013-04-24 03:26:10

by Chao Xie

[permalink] [raw]
Subject: [PATCH 6/6] input: pxa27x-keypad: add device tree support

Signed-off-by: Chao Xie <[email protected]>
---
.../devicetree/bindings/input/pxa27x-keypad.txt | 60 ++++++
drivers/input/keyboard/pxa27x_keypad.c | 198 +++++++++++++++++++-
2 files changed, 252 insertions(+), 6 deletions(-)
create mode 100644 Documentation/devicetree/bindings/input/pxa27x-keypad.txt

diff --git a/Documentation/devicetree/bindings/input/pxa27x-keypad.txt b/Documentation/devicetree/bindings/input/pxa27x-keypad.txt
new file mode 100644
index 0000000..f8674f7
--- /dev/null
+++ b/Documentation/devicetree/bindings/input/pxa27x-keypad.txt
@@ -0,0 +1,60 @@
+* Marvell PXA Keypad controller
+
+Required Properties
+- compatible : should be "marvell,pxa27x-keypad"
+- reg : Address and length of the register set for the device
+- interrupts : The interrupt for the keypad controller
+- marvell,debounce-interval : How long time the key will be
+ recognized when it is pressed. It is a u32 value, and bit[31:16]
+ is debounce interval for direct key and bit[15:0] is debounce
+ interval for matrix key. The value is in binary number of 2ms
+
+Optional Properties For Matrix Keyes
+Please refer to matrix-keymap.txt
+
+Optional Properties for Direct Keyes
+- marvell,direct-key-count : How many direct keyes are used.
+- marvell,direct-key-mask : The mask indicates which keyes
+ are used. If bit[X] of the mask is set, the direct key X
+ is used.
+- marvell,direct-key-low-active : Direct key status register
+ tells the level of pins that connects to the direct keyes.
+ When this property is set, it means that when the pin level
+ is low, the key is pressed(active).
+- marvell,direct-key-map : It is a u16 array. Each item indicates
+ the linux key-code for the direct key.
+
+Optional Properties For Rotary
+- marvell,rotary0 : It is a u32 value. Bit[31:16] is the
+ linux key-code for rotary up. Bit[15:0] is the linux key-code
+ for rotary down. It is for rotary 0.
+- marvell,rotary1 : Same as marvell,rotary0. It is for rotary 1.
+- marvell,rotary-rel-key : When rotary is used for relative axes
+ in the device, the value indicates the key-code for relative
+ axes measurement in the device. It is a u32 value. Bit[31:16]
+ is for rotary 1, and Bit[15:0] is for rotary 0.
+
+Examples:
+ keypad: keypad@d4012000 {
+ keypad,num-rows = <3>;
+ keypad,num-columns = <5>;
+ linux,keymap = <0x0000000e /* KEY_BACKSPACE */
+ 0x0001006b /* KEY_END */
+ 0x00020061 /* KEY_RIGHTCTRL */
+ 0x0003000b /* KEY_0 */
+ 0x00040002 /* KEY_1 */
+ 0x0100008b /* KEY_MENU */
+ 0x01010066 /* KEY_HOME */
+ 0x010200e7 /* KEY_SEND */
+ 0x01030009 /* KEY_8 */
+ 0x0104000a /* KEY_9 */
+ 0x02000160 /* KEY_OK */
+ 0x02010003 /* KEY_2 */
+ 0x02020004 /* KEY_3 */
+ 0x02030005 /* KEY_4 */
+ 0x02040006>; /* KEY_5 */
+ marvell,rotary0 = <0x006c0067>; /* KEY_UP & KEY_DOWN */
+ marvell,direct-key-count = <1>;
+ marvell,direct-key-map = <0x001c>;
+ marvell,debounce-interval = <0x001e001e>;
+ };
diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 975b448..a97ce0e 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -131,6 +131,181 @@ struct pxa27x_keypad {
void (*clear_wakeup_event)(void);
};

+static int pxa27x_keypad_matrix_key_parse_dt(struct device *dev,
+ struct pxa27x_keypad *keypad, struct input_dev *input_dev)
+{
+ int ret;
+ u32 rows, cols;
+
+ ret = matrix_keypad_parse_of_params(dev, &rows, &cols);
+ if (ret)
+ return ret;
+
+ if (rows > MAX_MATRIX_KEY_ROWS || cols > MAX_MATRIX_KEY_COLS) {
+ dev_err(dev, "rows or cols exceeds maximum value\n");
+ return -EINVAL;
+ }
+
+ keypad->matrix_key_rows = rows;
+ keypad->matrix_key_cols = cols;
+
+ ret = matrix_keypad_build_keymap(NULL, NULL,
+ keypad->matrix_key_rows,
+ keypad->matrix_key_cols,
+ keypad->keycodes, input_dev);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
+static int pxa27x_keypad_direct_key_parse_dt(struct device *dev,
+ struct pxa27x_keypad *keypad, struct input_dev *input_dev)
+{
+ struct device_node *np = dev->of_node;
+ const __be16 *prop;
+ unsigned short code;
+ int i, ret;
+ unsigned int proplen, size;
+
+ ret = of_property_read_u32(np, "marvell,direct-key-count",
+ &keypad->direct_key_num);
+ if (ret) {
+ /*
+ * If do not have marvel,direct-key-count defined,
+ * it means direct key is not supported.
+ */
+ if (ret == -EINVAL)
+ return 0;
+ return ret;
+ }
+ ret = of_property_read_u32(np, "marvell,direct-key-mask",
+ &keypad->default_direct_key_mask);
+ if (ret && ret != -EINVAL)
+ return ret;
+ /*
+ * If marvell,direct-key-mask is not defined, driver will use
+ * default value. Default value is set when configure the keypad.
+ */
+ else if (ret == -EINVAL)
+ keypad->default_direct_key_mask = 0;
+
+ keypad->direct_key_low_active = of_property_read_bool(np,
+ "marvell,direct-key-low-active");
+
+ prop = of_get_property(np, "marvell,direct-key-map", &proplen);
+ if (!prop)
+ return -EINVAL;
+
+ if (proplen % sizeof(u16))
+ return -EINVAL;
+
+ size = proplen / sizeof(u16);
+
+ /* Only MAX_DIRECT_KEY_NUM is accepted.*/
+ if (size > MAX_DIRECT_KEY_NUM)
+ return -EINVAL;
+
+ for (i = 0; i < size; i++) {
+ code = be16_to_cpup(prop + i);
+ keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = code;
+ __set_bit(code, input_dev->keybit);
+ }
+
+ return 0;
+}
+
+static int pxa27x_keypad_rotary_parse_dt(struct device *dev,
+ struct pxa27x_keypad *keypad, struct input_dev *input_dev)
+{
+ struct device_node *np = dev->of_node;
+ const __be32 *prop;
+ int i, relkey_ret;
+ unsigned int code, proplen;
+ const char *rotaryname[2] = {
+ "marvell,rotary0", "marvell,rotary1"};
+ const char relkeyname[] = {"marvell,rotary-rel-key"};
+
+ relkey_ret = of_property_read_u32(np, relkeyname, &code);
+ /* if can read correct rotary key-code, we do not need this. */
+ if (relkey_ret == 0) {
+ unsigned short relcode;
+
+ /* rotary0 taks lower half, rotary1 taks upper half. */
+ relcode = code & 0xffff;
+ keypad->rotary_rel_code[0] = (code & 0xffff);
+ __set_bit(relcode, input_dev->relbit);
+
+ relcode = code >> 16;
+ keypad->rotary_rel_code[1] = relcode;
+ __set_bit(relcode, input_dev->relbit);
+ }
+
+ for (i = 0; i < 2; i++) {
+ prop = of_get_property(np, rotaryname[i], &proplen);
+ /*
+ * If the prop is not set, it means keypad does not need
+ * initialize the rotaryX.
+ */
+ if (!prop)
+ continue;
+
+ code = be32_to_cpup(prop);
+ /*
+ * Not all up/down key code are valid.
+ * Now we depends on direct-rel-code.
+ */
+ if ((!(code & 0xffff) || !(code >> 16)) && relkey_ret) {
+ return relkey_ret;
+ } else {
+ unsigned int n = MAX_MATRIX_KEY_NUM + (i << 1);
+ unsigned short keycode;
+
+ keycode = code & 0xffff;
+ keypad->keycodes[n] = keycode;
+ __set_bit(keycode, input_dev->keybit);
+
+ keycode = code >> 16;
+ keypad->keycodes[n + 1] = keycode;
+ __set_bit(keycode, input_dev->keybit);
+
+ keypad->rotary_rel_code[i] = -1;
+ }
+ if (i == 0)
+ keypad->enable_rotary0 = 1;
+ else
+ keypad->enable_rotary1 = 1;
+ }
+
+ return 0;
+}
+
+static int pxa27x_keypad_build_keycode_from_dt(struct device *dev,
+ struct pxa27x_keypad *keypad, struct input_dev *input_dev)
+{
+ int ret;
+ struct device_node *np = dev->of_node;
+
+ ret = pxa27x_keypad_matrix_key_parse_dt(dev, keypad, input_dev);
+ if (ret)
+ return ret;
+
+ ret = pxa27x_keypad_direct_key_parse_dt(dev, keypad, input_dev);
+ if (ret)
+ return ret;
+
+ ret = pxa27x_keypad_rotary_parse_dt(dev, keypad, input_dev);
+ if (ret)
+ return ret;
+
+ ret = of_property_read_u32(np, "marvell,debounce-interval",
+ &keypad->debounce_interval);
+ if (ret)
+ return ret;
+
+ return 0;
+}
+
static int pxa27x_keypad_build_keycode(struct device *dev,
struct pxa27x_keypad *keypad,
struct pxa27x_keypad_platform_data *pdata,
@@ -510,15 +685,15 @@ static const struct dev_pm_ops pxa27x_keypad_pm_ops = {
static int pxa27x_keypad_probe(struct platform_device *pdev)
{
struct pxa27x_keypad_platform_data *pdata = pdev->dev.platform_data;
+ struct device_node *np = pdev->dev.of_node;
struct pxa27x_keypad *keypad;
struct input_dev *input_dev;
struct resource *res;
int irq, error;

- if (pdata == NULL) {
- dev_err(&pdev->dev, "no platform data defined\n");
+ /* Driver need build keycode from device tree or pdata */
+ if (!np && !pdata)
return -EINVAL;
- }

irq = platform_get_irq(pdev, 0);
if (irq < 0) {
@@ -579,11 +754,15 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
input_set_capability(input_dev, EV_MSC, MSC_SCAN);

- if (pdata->clear_wakeup_event)
+ if (pdata && pdata->clear_wakeup_event)
keypad->clear_wakeup_event = pdata->clear_wakeup_event;

- error = pxa27x_keypad_build_keycode(&pdev->dev, keypad, pdata,
- input_dev);
+ if (np)
+ error = pxa27x_keypad_build_keycode_from_dt(&pdev->dev, keypad,
+ input_dev);
+ else
+ error = pxa27x_keypad_build_keycode(&pdev->dev, keypad, pdata,
+ input_dev);
if (error) {
dev_err(&pdev->dev, "failed to build keycode\n");
goto failed_put_clk;
@@ -650,11 +829,18 @@ static int pxa27x_keypad_remove(struct platform_device *pdev)
/* work with hotplug and coldplug */
MODULE_ALIAS("platform:pxa27x-keypad");

+static const struct of_device_id pxa27x_keypad_dt_match[] = {
+ { .compatible = "marvell,pxa27x-keypad" },
+ {},
+};
+MODULE_DEVICE_TABLE(of, pxa27x_keypad_dt_match);
+
static struct platform_driver pxa27x_keypad_driver = {
.probe = pxa27x_keypad_probe,
.remove = pxa27x_keypad_remove,
.driver = {
.name = "pxa27x-keypad",
+ .of_match_table = of_match_ptr(pxa27x_keypad_dt_match),
.owner = THIS_MODULE,
#ifdef CONFIG_PM
.pm = &pxa27x_keypad_pm_ops,
--
1.7.4.1

2013-04-24 03:25:59

by Chao Xie

[permalink] [raw]
Subject: [PATCH 4/6] arm: mmp: use matrix_keymap for teton_bga

Signed-off-by: Chao Xie <[email protected]>
---
arch/arm/mach-mmp/teton_bga.c | 8 ++++++--
1 files changed, 6 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-mmp/teton_bga.c b/arch/arm/mach-mmp/teton_bga.c
index 8609967..d8967fa 100644
--- a/arch/arm/mach-mmp/teton_bga.c
+++ b/arch/arm/mach-mmp/teton_bga.c
@@ -56,11 +56,15 @@ static unsigned int teton_bga_matrix_key_map[] = {
KEY(1, 7, KEY_RIGHT),
};

+static struct matrix_keymap_data teton_bga_matrix_keymap_data = {
+ .keymap = teton_bga_matrix_key_map,
+ .keymap_size = ARRAY_SIZE(teton_bga_matrix_key_map),
+};
+
static struct pxa27x_keypad_platform_data teton_bga_keypad_info __initdata = {
.matrix_key_rows = 2,
.matrix_key_cols = 8,
- .matrix_key_map = teton_bga_matrix_key_map,
- .matrix_key_map_size = ARRAY_SIZE(teton_bga_matrix_key_map),
+ .matrix_keymap_data = &teton_bga_matrix_keymap_data,
.debounce_interval = 30,
};

--
1.7.4.1

2013-04-24 03:29:31

by Chao Xie

[permalink] [raw]
Subject: [PATCH 2/6] input: pxa27x-keypad: use matrix_keymap for matrix keyes

pxa27x-keypad includes matrix keyes. Make use of matrix_keymap
for the matrix keyes.

Signed-off-by: Chao Xie <[email protected]>
---
drivers/input/keyboard/Kconfig | 1 +
drivers/input/keyboard/pxa27x_keypad.c | 29 +++++++++++++++-----------
include/linux/platform_data/keypad-pxa27x.h | 1 +
3 files changed, 19 insertions(+), 12 deletions(-)

diff --git a/drivers/input/keyboard/Kconfig b/drivers/input/keyboard/Kconfig
index ac05006..fff3751 100644
--- a/drivers/input/keyboard/Kconfig
+++ b/drivers/input/keyboard/Kconfig
@@ -441,6 +441,7 @@ config KEYBOARD_OPENCORES
config KEYBOARD_PXA27x
tristate "PXA27x/PXA3xx keypad support"
depends on PXA27x || PXA3xx || ARCH_MMP
+ select INPUT_MATRIXKMAP
help
Enable support for PXA27x/PXA3xx keypad controller.

diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
index 023243a..975b448 100644
--- a/drivers/input/keyboard/pxa27x_keypad.c
+++ b/drivers/input/keyboard/pxa27x_keypad.c
@@ -137,22 +137,27 @@ static int pxa27x_keypad_build_keycode(struct device *dev,
struct input_dev *input_dev)
{
unsigned short keycode;
- int i;
+ int ret, i;
+ const struct matrix_keymap_data *keymap_data =
+ pdata ? pdata->matrix_keymap_data : NULL;

keypad->matrix_key_rows = pdata->matrix_key_rows;
keypad->matrix_key_cols = pdata->matrix_key_cols;
- for (i = 0; i < pdata->matrix_key_map_size; i++) {
- unsigned int key = pdata->matrix_key_map[i];
- unsigned int row = KEY_ROW(key);
- unsigned int col = KEY_COL(key);
- unsigned int scancode = MATRIX_SCAN_CODE(row, col,
- MATRIX_ROW_SHIFT);
-
- keycode = KEY_VAL(key);
- keypad->keycodes[scancode] = keycode;
- __set_bit(keycode, input_dev->keybit);
- }

+ ret = matrix_keypad_build_keymap(keymap_data, NULL,
+ keypad->matrix_key_rows,
+ keypad->matrix_key_cols,
+ keypad->keycodes, input_dev);
+ if (ret)
+ return ret;
+
+ /*
+ * The keycodes may not only includes matrix key but also the direct
+ * key or rotary key.
+ */
+ input_dev->keycodemax = ARRAY_SIZE(keypad->keycodes);
+
+ /* For direct key. */
keypad->direct_key_low_active = pdata->direct_key_low_active;
keypad->direct_key_num = pdata->direct_key_num;
keypad->default_direct_key_mask = pdata->direct_key_mask;
diff --git a/include/linux/platform_data/keypad-pxa27x.h b/include/linux/platform_data/keypad-pxa27x.h
index 5ce8d5e6..0db423b 100644
--- a/include/linux/platform_data/keypad-pxa27x.h
+++ b/include/linux/platform_data/keypad-pxa27x.h
@@ -36,6 +36,7 @@
struct pxa27x_keypad_platform_data {

/* code map for the matrix keys */
+ const struct matrix_keymap_data *matrix_keymap_data;
unsigned int matrix_key_rows;
unsigned int matrix_key_cols;
unsigned int *matrix_key_map;
--
1.7.4.1

2013-04-24 08:22:21

by Dmitry Torokhov

[permalink] [raw]
Subject: Re: [PATCH 1/6] input: pxa27x-keypad: copy members of platform data to device private data

Hi Chao,

On Tue, Apr 23, 2013 at 11:20:28PM -0400, Chao Xie wrote:
> Original driver will directly use platform data when driver is
> running.
> In fact, the platform data may be freed after system is bootup,

This statement is not correct, the platform data should be never be
freed, otherwise one can not reload a driver.

> or pointer for platform data is NULL if it has device tree support.
> Define the useful members of platform data in device private data.

Usually people just allocate platform data structure and fill it with DT
data.

Thanks.

>
> Signed-off-by: Chao Xie <[email protected]>
> ---
> drivers/input/keyboard/pxa27x_keypad.c | 97 ++++++++++++++++++++-----------
> 1 files changed, 62 insertions(+), 35 deletions(-)
>
> diff --git a/drivers/input/keyboard/pxa27x_keypad.c b/drivers/input/keyboard/pxa27x_keypad.c
> index 5330d8f..023243a 100644
> --- a/drivers/input/keyboard/pxa27x_keypad.c
> +++ b/drivers/input/keyboard/pxa27x_keypad.c
> @@ -100,8 +100,6 @@
> #define MAX_KEYPAD_KEYS (MAX_MATRIX_KEY_NUM + MAX_DIRECT_KEY_NUM)
>
> struct pxa27x_keypad {
> - struct pxa27x_keypad_platform_data *pdata;
> -
> struct clk *clk;
> struct input_dev *input_dev;
> void __iomem *mmio_base;
> @@ -116,15 +114,33 @@ struct pxa27x_keypad {
> uint32_t direct_key_state;
>
> unsigned int direct_key_mask;
> +
> + /* from platform data */
> + unsigned int matrix_key_rows;
> + unsigned int matrix_key_cols;
> +
> + int direct_key_low_active;
> + unsigned int direct_key_num;
> + unsigned int default_direct_key_mask;
> +
> + int enable_rotary0;
> + int enable_rotary1;
> +
> + unsigned int debounce_interval;
> +
> + void (*clear_wakeup_event)(void);
> };
>
> -static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
> +static int pxa27x_keypad_build_keycode(struct device *dev,
> + struct pxa27x_keypad *keypad,
> + struct pxa27x_keypad_platform_data *pdata,
> + struct input_dev *input_dev)
> {
> - struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
> - struct input_dev *input_dev = keypad->input_dev;
> unsigned short keycode;
> int i;
>
> + keypad->matrix_key_rows = pdata->matrix_key_rows;
> + keypad->matrix_key_cols = pdata->matrix_key_cols;
> for (i = 0; i < pdata->matrix_key_map_size; i++) {
> unsigned int key = pdata->matrix_key_map[i];
> unsigned int row = KEY_ROW(key);
> @@ -137,12 +153,16 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
> __set_bit(keycode, input_dev->keybit);
> }
>
> + keypad->direct_key_low_active = pdata->direct_key_low_active;
> + keypad->direct_key_num = pdata->direct_key_num;
> + keypad->default_direct_key_mask = pdata->direct_key_mask;
> for (i = 0; i < pdata->direct_key_num; i++) {
> keycode = pdata->direct_key_map[i];
> keypad->keycodes[MAX_MATRIX_KEY_NUM + i] = keycode;
> __set_bit(keycode, input_dev->keybit);
> }
>
> + keypad->enable_rotary0 = pdata->enable_rotary0;
> if (pdata->enable_rotary0) {
> if (pdata->rotary0_up_key && pdata->rotary0_down_key) {
> keycode = pdata->rotary0_up_key;
> @@ -160,6 +180,7 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
> }
> }
>
> + keypad->enable_rotary1 = pdata->enable_rotary1;
> if (pdata->enable_rotary1) {
> if (pdata->rotary1_up_key && pdata->rotary1_down_key) {
> keycode = pdata->rotary1_up_key;
> @@ -178,11 +199,14 @@ static void pxa27x_keypad_build_keycode(struct pxa27x_keypad *keypad)
> }
>
> __clear_bit(KEY_RESERVED, input_dev->keybit);
> +
> + keypad->debounce_interval = pdata->debounce_interval;
> +
> + return 0;
> }
>
> static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
> {
> - struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
> struct input_dev *input_dev = keypad->input_dev;
> int row, col, num_keys_pressed = 0;
> uint32_t new_state[MAX_MATRIX_KEY_COLS];
> @@ -200,8 +224,8 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
> row = KPAS_RP(kpas);
>
> /* if invalid row/col, treat as no key pressed */
> - if (col >= pdata->matrix_key_cols ||
> - row >= pdata->matrix_key_rows)
> + if (col >= keypad->matrix_key_cols ||
> + row >= keypad->matrix_key_rows)
> goto scan;
>
> new_state[col] = (1 << row);
> @@ -224,7 +248,7 @@ static void pxa27x_keypad_scan_matrix(struct pxa27x_keypad *keypad)
> new_state[7] = (kpasmkp3 >> 16) & KPASMKP_MKC_MASK;
> }
> scan:
> - for (col = 0; col < pdata->matrix_key_cols; col++) {
> + for (col = 0; col < keypad->matrix_key_cols; col++) {
> uint32_t bits_changed;
> int code;
>
> @@ -232,7 +256,7 @@ scan:
> if (bits_changed == 0)
> continue;
>
> - for (row = 0; row < pdata->matrix_key_rows; row++) {
> + for (row = 0; row < keypad->matrix_key_rows; row++) {
> if ((bits_changed & (1 << row)) == 0)
> continue;
>
> @@ -284,23 +308,21 @@ static void report_rotary_event(struct pxa27x_keypad *keypad, int r, int delta)
>
> static void pxa27x_keypad_scan_rotary(struct pxa27x_keypad *keypad)
> {
> - struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
> uint32_t kprec;
>
> /* read and reset to default count value */
> kprec = keypad_readl(KPREC);
> keypad_writel(KPREC, DEFAULT_KPREC);
>
> - if (pdata->enable_rotary0)
> + if (keypad->enable_rotary0)
> report_rotary_event(keypad, 0, rotary_delta(kprec));
>
> - if (pdata->enable_rotary1)
> + if (keypad->enable_rotary1)
> report_rotary_event(keypad, 1, rotary_delta(kprec >> 16));
> }
>
> static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
> {
> - struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
> struct input_dev *input_dev = keypad->input_dev;
> unsigned int new_state;
> uint32_t kpdk, bits_changed;
> @@ -308,14 +330,14 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
>
> kpdk = keypad_readl(KPDK);
>
> - if (pdata->enable_rotary0 || pdata->enable_rotary1)
> + if (keypad->enable_rotary0 || keypad->enable_rotary1)
> pxa27x_keypad_scan_rotary(keypad);
>
> /*
> * The KPDR_DK only output the key pin level, so it relates to board,
> * and low level may be active.
> */
> - if (pdata->direct_key_low_active)
> + if (keypad->direct_key_low_active)
> new_state = ~KPDK_DK(kpdk) & keypad->direct_key_mask;
> else
> new_state = KPDK_DK(kpdk) & keypad->direct_key_mask;
> @@ -325,7 +347,7 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
> if (bits_changed == 0)
> return;
>
> - for (i = 0; i < pdata->direct_key_num; i++) {
> + for (i = 0; i < keypad->direct_key_num; i++) {
> if (bits_changed & (1 << i)) {
> int code = MAX_MATRIX_KEY_NUM + i;
>
> @@ -340,10 +362,9 @@ static void pxa27x_keypad_scan_direct(struct pxa27x_keypad *keypad)
>
> static void clear_wakeup_event(struct pxa27x_keypad *keypad)
> {
> - struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
>
> - if (pdata->clear_wakeup_event)
> - (pdata->clear_wakeup_event)();
> + if (keypad->clear_wakeup_event)
> + (keypad->clear_wakeup_event)();
> }
>
> static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
> @@ -364,7 +385,6 @@ static irqreturn_t pxa27x_keypad_irq_handler(int irq, void *dev_id)
>
> static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
> {
> - struct pxa27x_keypad_platform_data *pdata = keypad->pdata;
> unsigned int mask = 0, direct_key_num = 0;
> unsigned long kpc = 0;
>
> @@ -372,34 +392,34 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
> keypad_readl(KPC);
>
> /* enable matrix keys with automatic scan */
> - if (pdata->matrix_key_rows && pdata->matrix_key_cols) {
> + if (keypad->matrix_key_rows && keypad->matrix_key_cols) {
> kpc |= KPC_ASACT | KPC_MIE | KPC_ME | KPC_MS_ALL;
> - kpc |= KPC_MKRN(pdata->matrix_key_rows) |
> - KPC_MKCN(pdata->matrix_key_cols);
> + kpc |= KPC_MKRN(keypad->matrix_key_rows) |
> + KPC_MKCN(keypad->matrix_key_cols);
> }
>
> /* enable rotary key, debounce interval same as direct keys */
> - if (pdata->enable_rotary0) {
> + if (keypad->enable_rotary0) {
> mask |= 0x03;
> direct_key_num = 2;
> kpc |= KPC_REE0;
> }
>
> - if (pdata->enable_rotary1) {
> + if (keypad->enable_rotary1) {
> mask |= 0x0c;
> direct_key_num = 4;
> kpc |= KPC_REE1;
> }
>
> - if (pdata->direct_key_num > direct_key_num)
> - direct_key_num = pdata->direct_key_num;
> + if (keypad->direct_key_num > direct_key_num)
> + direct_key_num = keypad->direct_key_num;
>
> /*
> * Direct keys usage may not start from KP_DKIN0, check the platfrom
> * mask data to config the specific.
> */
> - if (pdata->direct_key_mask)
> - keypad->direct_key_mask = pdata->direct_key_mask;
> + if (keypad->default_direct_key_mask)
> + keypad->direct_key_mask = keypad->default_direct_key_mask;
> else
> keypad->direct_key_mask = ((1 << direct_key_num) - 1) & ~mask;
>
> @@ -409,7 +429,7 @@ static void pxa27x_keypad_config(struct pxa27x_keypad *keypad)
>
> keypad_writel(KPC, kpc | KPC_RE_ZERO_DEB);
> keypad_writel(KPREC, DEFAULT_KPREC);
> - keypad_writel(KPKDI, pdata->debounce_interval);
> + keypad_writel(KPKDI, keypad->debounce_interval);
> }
>
> static int pxa27x_keypad_open(struct input_dev *dev)
> @@ -515,7 +535,6 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
> goto failed_free;
> }
>
> - keypad->pdata = pdata;
> keypad->input_dev = input_dev;
> keypad->irq = irq;
>
> @@ -555,10 +574,18 @@ static int pxa27x_keypad_probe(struct platform_device *pdev)
> input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
> input_set_capability(input_dev, EV_MSC, MSC_SCAN);
>
> - pxa27x_keypad_build_keycode(keypad);
> + if (pdata->clear_wakeup_event)
> + keypad->clear_wakeup_event = pdata->clear_wakeup_event;
> +
> + error = pxa27x_keypad_build_keycode(&pdev->dev, keypad, pdata,
> + input_dev);
> + if (error) {
> + dev_err(&pdev->dev, "failed to build keycode\n");
> + goto failed_put_clk;
> + }
>
> - if ((pdata->enable_rotary0 && keypad->rotary_rel_code[0] != -1) ||
> - (pdata->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) {
> + if ((keypad->enable_rotary0 && keypad->rotary_rel_code[0] != -1) ||
> + (keypad->enable_rotary1 && keypad->rotary_rel_code[1] != -1)) {
> input_dev->evbit[0] |= BIT_MASK(EV_REL);
> }
>
> --
> 1.7.4.1
>

--
Dmitry