Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
navpoint.c
Go to the documentation of this file.
1 /*
2  * Synaptics NavPoint (PXA27x SSP/SPI) driver.
3  *
4  * Copyright (C) 2012 Paul Parsons <[email protected]>
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  */
10 
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
15 #include <linux/clk.h>
16 #include <linux/delay.h>
17 #include <linux/gpio.h>
18 #include <linux/input.h>
19 #include <linux/input/navpoint.h>
20 #include <linux/interrupt.h>
21 #include <linux/mutex.h>
22 #include <linux/pxa2xx_ssp.h>
23 #include <linux/slab.h>
24 
25 /*
26  * Synaptics Modular Embedded Protocol: Module Packet Format.
27  * Module header byte 2:0 = Length (# bytes that follow)
28  * Module header byte 4:3 = Control
29  * Module header byte 7:5 = Module Address
30  */
31 #define HEADER_LENGTH(byte) ((byte) & 0x07)
32 #define HEADER_CONTROL(byte) (((byte) >> 3) & 0x03)
33 #define HEADER_ADDRESS(byte) ((byte) >> 5)
34 
35 struct navpoint {
36  struct ssp_device *ssp;
37  struct input_dev *input;
38  struct device *dev;
39  int gpio;
40  int index;
41  u8 data[1 + HEADER_LENGTH(0xff)];
42 };
43 
44 /*
45  * Initialization values for SSCR0_x, SSCR1_x, SSSR_x.
46  */
47 static const u32 sscr0 = 0
48  | SSCR0_TUM /* TIM = 1; No TUR interrupts */
49  | SSCR0_RIM /* RIM = 1; No ROR interrupts */
50  | SSCR0_SSE /* SSE = 1; SSP enabled */
51  | SSCR0_Motorola /* FRF = 0; Motorola SPI */
52  | SSCR0_DataSize(16) /* DSS = 15; Data size = 16-bit */
53  ;
54 static const u32 sscr1 = 0
55  | SSCR1_SCFR /* SCFR = 1; SSPSCLK only during transfers */
56  | SSCR1_SCLKDIR /* SCLKDIR = 1; Slave mode */
57  | SSCR1_SFRMDIR /* SFRMDIR = 1; Slave mode */
58  | SSCR1_RWOT /* RWOT = 1; Receive without transmit mode */
59  | SSCR1_RxTresh(1) /* RFT = 0; Receive FIFO threshold = 1 */
60  | SSCR1_SPH /* SPH = 1; SSPSCLK inactive 0.5 + 1 cycles */
61  | SSCR1_RIE /* RIE = 1; Receive FIFO interrupt enabled */
62  ;
63 static const u32 sssr = 0
64  | SSSR_BCE /* BCE = 1; Clear BCE */
65  | SSSR_TUR /* TUR = 1; Clear TUR */
66  | SSSR_EOC /* EOC = 1; Clear EOC */
67  | SSSR_TINT /* TINT = 1; Clear TINT */
68  | SSSR_PINT /* PINT = 1; Clear PINT */
69  | SSSR_ROR /* ROR = 1; Clear ROR */
70  ;
71 
72 /*
73  * MEP Query $22: Touchpad Coordinate Range Query is not supported by
74  * the NavPoint module, so sampled values provide the default limits.
75  */
76 #define NAVPOINT_X_MIN 1278
77 #define NAVPOINT_X_MAX 5340
78 #define NAVPOINT_Y_MIN 1572
79 #define NAVPOINT_Y_MAX 4396
80 #define NAVPOINT_PRESSURE_MIN 0
81 #define NAVPOINT_PRESSURE_MAX 255
82 
83 static void navpoint_packet(struct navpoint *navpoint)
84 {
85  int finger;
86  int gesture;
87  int x, y, z;
88 
89  switch (navpoint->data[0]) {
90  case 0xff: /* Garbage (packet?) between reset and Hello packet */
91  case 0x00: /* Module 0, NULL packet */
92  break;
93 
94  case 0x0e: /* Module 0, Absolute packet */
95  finger = (navpoint->data[1] & 0x01);
96  gesture = (navpoint->data[1] & 0x02);
97  x = ((navpoint->data[2] & 0x1f) << 8) | navpoint->data[3];
98  y = ((navpoint->data[4] & 0x1f) << 8) | navpoint->data[5];
99  z = navpoint->data[6];
100  input_report_key(navpoint->input, BTN_TOUCH, finger);
101  input_report_abs(navpoint->input, ABS_X, x);
102  input_report_abs(navpoint->input, ABS_Y, y);
103  input_report_abs(navpoint->input, ABS_PRESSURE, z);
104  input_report_key(navpoint->input, BTN_TOOL_FINGER, finger);
105  input_report_key(navpoint->input, BTN_LEFT, gesture);
106  input_sync(navpoint->input);
107  break;
108 
109  case 0x19: /* Module 0, Hello packet */
110  if ((navpoint->data[1] & 0xf0) == 0x10)
111  break;
112  /* FALLTHROUGH */
113  default:
114  dev_warn(navpoint->dev,
115  "spurious packet: data=0x%02x,0x%02x,...\n",
116  navpoint->data[0], navpoint->data[1]);
117  break;
118  }
119 }
120 
121 static irqreturn_t navpoint_irq(int irq, void *dev_id)
122 {
123  struct navpoint *navpoint = dev_id;
124  struct ssp_device *ssp = navpoint->ssp;
126  u32 status;
127 
128  status = pxa_ssp_read_reg(ssp, SSSR);
129  if (status & sssr) {
130  dev_warn(navpoint->dev,
131  "unexpected interrupt: status=0x%08x\n", status);
132  pxa_ssp_write_reg(ssp, SSSR, (status & sssr));
133  ret = IRQ_HANDLED;
134  }
135 
136  while (status & SSSR_RNE) {
137  u32 data;
138 
139  data = pxa_ssp_read_reg(ssp, SSDR);
140  navpoint->data[navpoint->index + 0] = (data >> 8);
141  navpoint->data[navpoint->index + 1] = data;
142  navpoint->index += 2;
143  if (HEADER_LENGTH(navpoint->data[0]) < navpoint->index) {
144  navpoint_packet(navpoint);
145  navpoint->index = 0;
146  }
147  status = pxa_ssp_read_reg(ssp, SSSR);
148  ret = IRQ_HANDLED;
149  }
150 
151  return ret;
152 }
153 
154 static void navpoint_up(struct navpoint *navpoint)
155 {
156  struct ssp_device *ssp = navpoint->ssp;
157  int timeout;
158 
159  clk_prepare_enable(ssp->clk);
160 
161  pxa_ssp_write_reg(ssp, SSCR1, sscr1);
162  pxa_ssp_write_reg(ssp, SSSR, sssr);
163  pxa_ssp_write_reg(ssp, SSTO, 0);
164  pxa_ssp_write_reg(ssp, SSCR0, sscr0); /* SSCR0_SSE written last */
165 
166  /* Wait until SSP port is ready for slave clock operations */
167  for (timeout = 100; timeout != 0; --timeout) {
168  if (!(pxa_ssp_read_reg(ssp, SSSR) & SSSR_CSS))
169  break;
170  msleep(1);
171  }
172 
173  if (timeout == 0)
174  dev_err(navpoint->dev,
175  "timeout waiting for SSSR[CSS] to clear\n");
176 
177  if (gpio_is_valid(navpoint->gpio))
178  gpio_set_value(navpoint->gpio, 1);
179 }
180 
181 static void navpoint_down(struct navpoint *navpoint)
182 {
183  struct ssp_device *ssp = navpoint->ssp;
184 
185  if (gpio_is_valid(navpoint->gpio))
186  gpio_set_value(navpoint->gpio, 0);
187 
188  pxa_ssp_write_reg(ssp, SSCR0, 0);
189 
190  clk_disable_unprepare(ssp->clk);
191 }
192 
193 static int navpoint_open(struct input_dev *input)
194 {
195  struct navpoint *navpoint = input_get_drvdata(input);
196 
197  navpoint_up(navpoint);
198 
199  return 0;
200 }
201 
202 static void navpoint_close(struct input_dev *input)
203 {
204  struct navpoint *navpoint = input_get_drvdata(input);
205 
206  navpoint_down(navpoint);
207 }
208 
209 static int __devinit navpoint_probe(struct platform_device *pdev)
210 {
211  const struct navpoint_platform_data *pdata =
212  dev_get_platdata(&pdev->dev);
213  struct ssp_device *ssp;
214  struct input_dev *input;
215  struct navpoint *navpoint;
216  int error;
217 
218  if (!pdata) {
219  dev_err(&pdev->dev, "no platform data\n");
220  return -EINVAL;
221  }
222 
223  if (gpio_is_valid(pdata->gpio)) {
224  error = gpio_request_one(pdata->gpio, GPIOF_OUT_INIT_LOW,
225  "SYNAPTICS_ON");
226  if (error)
227  return error;
228  }
229 
230  ssp = pxa_ssp_request(pdata->port, pdev->name);
231  if (!ssp) {
232  error = -ENODEV;
233  goto err_free_gpio;
234  }
235 
236  /* HaRET does not disable devices before jumping into Linux */
237  if (pxa_ssp_read_reg(ssp, SSCR0) & SSCR0_SSE) {
238  pxa_ssp_write_reg(ssp, SSCR0, 0);
239  dev_warn(&pdev->dev, "ssp%d already enabled\n", pdata->port);
240  }
241 
242  navpoint = kzalloc(sizeof(*navpoint), GFP_KERNEL);
243  input = input_allocate_device();
244  if (!navpoint || !input) {
245  error = -ENOMEM;
246  goto err_free_mem;
247  }
248 
249  navpoint->ssp = ssp;
250  navpoint->input = input;
251  navpoint->dev = &pdev->dev;
252  navpoint->gpio = pdata->gpio;
253 
254  input->name = pdev->name;
255  input->dev.parent = &pdev->dev;
256 
257  __set_bit(EV_KEY, input->evbit);
258  __set_bit(EV_ABS, input->evbit);
259  __set_bit(BTN_LEFT, input->keybit);
260  __set_bit(BTN_TOUCH, input->keybit);
261  __set_bit(BTN_TOOL_FINGER, input->keybit);
262 
263  input_set_abs_params(input, ABS_X,
265  input_set_abs_params(input, ABS_Y,
267  input_set_abs_params(input, ABS_PRESSURE,
269  0, 0);
270 
271  input->open = navpoint_open;
272  input->close = navpoint_close;
273 
274  input_set_drvdata(input, navpoint);
275 
276  error = request_irq(ssp->irq, navpoint_irq, 0, pdev->name, navpoint);
277  if (error)
278  goto err_free_mem;
279 
280  error = input_register_device(input);
281  if (error)
282  goto err_free_irq;
283 
284  platform_set_drvdata(pdev, navpoint);
285  dev_dbg(&pdev->dev, "ssp%d, irq %d\n", pdata->port, ssp->irq);
286 
287  return 0;
288 
289 err_free_irq:
290  free_irq(ssp->irq, &pdev->dev);
291 err_free_mem:
292  input_free_device(input);
293  kfree(navpoint);
294  pxa_ssp_free(ssp);
295 err_free_gpio:
296  if (gpio_is_valid(pdata->gpio))
297  gpio_free(pdata->gpio);
298 
299  return error;
300 }
301 
302 static int __devexit navpoint_remove(struct platform_device *pdev)
303 {
304  const struct navpoint_platform_data *pdata =
305  dev_get_platdata(&pdev->dev);
306  struct navpoint *navpoint = platform_get_drvdata(pdev);
307  struct ssp_device *ssp = navpoint->ssp;
308 
309  free_irq(ssp->irq, navpoint);
310 
311  input_unregister_device(navpoint->input);
312  kfree(navpoint);
313 
314  pxa_ssp_free(ssp);
315 
316  if (gpio_is_valid(pdata->gpio))
317  gpio_free(pdata->gpio);
318 
319  return 0;
320 }
321 
322 #ifdef CONFIG_PM_SLEEP
323 static int navpoint_suspend(struct device *dev)
324 {
325  struct platform_device *pdev = to_platform_device(dev);
326  struct navpoint *navpoint = platform_get_drvdata(pdev);
327  struct input_dev *input = navpoint->input;
328 
329  mutex_lock(&input->mutex);
330  if (input->users)
331  navpoint_down(navpoint);
332  mutex_unlock(&input->mutex);
333 
334  return 0;
335 }
336 
337 static int navpoint_resume(struct device *dev)
338 {
339  struct platform_device *pdev = to_platform_device(dev);
340  struct navpoint *navpoint = platform_get_drvdata(pdev);
341  struct input_dev *input = navpoint->input;
342 
343  mutex_lock(&input->mutex);
344  if (input->users)
345  navpoint_up(navpoint);
346  mutex_unlock(&input->mutex);
347 
348  return 0;
349 }
350 #endif
351 
352 static SIMPLE_DEV_PM_OPS(navpoint_pm_ops, navpoint_suspend, navpoint_resume);
353 
354 static struct platform_driver navpoint_driver = {
355  .probe = navpoint_probe,
356  .remove = __devexit_p(navpoint_remove),
357  .driver = {
358  .name = "navpoint",
359  .owner = THIS_MODULE,
360  .pm = &navpoint_pm_ops,
361  },
362 };
363 
364 module_platform_driver(navpoint_driver);
365 
366 MODULE_AUTHOR("Paul Parsons <[email protected]>");
367 MODULE_DESCRIPTION("Synaptics NavPoint (PXA27x SSP/SPI) driver");
368 MODULE_LICENSE("GPL");
369 MODULE_ALIAS("platform:navpoint");