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