Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.32-rc3 375 lines 8.5 kB view raw
1/* 2 * Copyright (C) 2007 Atmel Corporation 3 * 4 * Driver for the AT32AP700X PS/2 controller (PSIF). 5 * 6 * This program is free software; you can redistribute it and/or modify it 7 * under the terms of the GNU General Public License version 2 as published 8 * by the Free Software Foundation. 9 */ 10#include <linux/kernel.h> 11#include <linux/module.h> 12#include <linux/device.h> 13#include <linux/init.h> 14#include <linux/serio.h> 15#include <linux/interrupt.h> 16#include <linux/delay.h> 17#include <linux/err.h> 18#include <linux/io.h> 19#include <linux/clk.h> 20#include <linux/platform_device.h> 21 22/* PSIF register offsets */ 23#define PSIF_CR 0x00 24#define PSIF_RHR 0x04 25#define PSIF_THR 0x08 26#define PSIF_SR 0x10 27#define PSIF_IER 0x14 28#define PSIF_IDR 0x18 29#define PSIF_IMR 0x1c 30#define PSIF_PSR 0x24 31 32/* Bitfields in control register. */ 33#define PSIF_CR_RXDIS_OFFSET 1 34#define PSIF_CR_RXDIS_SIZE 1 35#define PSIF_CR_RXEN_OFFSET 0 36#define PSIF_CR_RXEN_SIZE 1 37#define PSIF_CR_SWRST_OFFSET 15 38#define PSIF_CR_SWRST_SIZE 1 39#define PSIF_CR_TXDIS_OFFSET 9 40#define PSIF_CR_TXDIS_SIZE 1 41#define PSIF_CR_TXEN_OFFSET 8 42#define PSIF_CR_TXEN_SIZE 1 43 44/* Bitfields in interrupt disable, enable, mask and status register. */ 45#define PSIF_NACK_OFFSET 8 46#define PSIF_NACK_SIZE 1 47#define PSIF_OVRUN_OFFSET 5 48#define PSIF_OVRUN_SIZE 1 49#define PSIF_PARITY_OFFSET 9 50#define PSIF_PARITY_SIZE 1 51#define PSIF_RXRDY_OFFSET 4 52#define PSIF_RXRDY_SIZE 1 53#define PSIF_TXEMPTY_OFFSET 1 54#define PSIF_TXEMPTY_SIZE 1 55#define PSIF_TXRDY_OFFSET 0 56#define PSIF_TXRDY_SIZE 1 57 58/* Bitfields in prescale register. */ 59#define PSIF_PSR_PRSCV_OFFSET 0 60#define PSIF_PSR_PRSCV_SIZE 12 61 62/* Bitfields in receive hold register. */ 63#define PSIF_RHR_RXDATA_OFFSET 0 64#define PSIF_RHR_RXDATA_SIZE 8 65 66/* Bitfields in transmit hold register. */ 67#define PSIF_THR_TXDATA_OFFSET 0 68#define PSIF_THR_TXDATA_SIZE 8 69 70/* Bit manipulation macros */ 71#define PSIF_BIT(name) \ 72 (1 << PSIF_##name##_OFFSET) 73 74#define PSIF_BF(name, value) \ 75 (((value) & ((1 << PSIF_##name##_SIZE) - 1)) \ 76 << PSIF_##name##_OFFSET) 77 78#define PSIF_BFEXT(name, value) \ 79 (((value) >> PSIF_##name##_OFFSET) \ 80 & ((1 << PSIF_##name##_SIZE) - 1)) 81 82#define PSIF_BFINS(name, value, old) \ 83 (((old) & ~(((1 << PSIF_##name##_SIZE) - 1) \ 84 << PSIF_##name##_OFFSET)) \ 85 | PSIF_BF(name, value)) 86 87/* Register access macros */ 88#define psif_readl(port, reg) \ 89 __raw_readl((port)->regs + PSIF_##reg) 90 91#define psif_writel(port, reg, value) \ 92 __raw_writel((value), (port)->regs + PSIF_##reg) 93 94struct psif { 95 struct platform_device *pdev; 96 struct clk *pclk; 97 struct serio *io; 98 void __iomem *regs; 99 unsigned int irq; 100 unsigned int open; 101 /* Prevent concurrent writes to PSIF THR. */ 102 spinlock_t lock; 103}; 104 105static irqreturn_t psif_interrupt(int irq, void *_ptr) 106{ 107 struct psif *psif = _ptr; 108 int retval = IRQ_NONE; 109 unsigned int io_flags = 0; 110 unsigned long status; 111 112 status = psif_readl(psif, SR); 113 114 if (status & PSIF_BIT(RXRDY)) { 115 unsigned char val = (unsigned char) psif_readl(psif, RHR); 116 117 if (status & PSIF_BIT(PARITY)) 118 io_flags |= SERIO_PARITY; 119 if (status & PSIF_BIT(OVRUN)) 120 dev_err(&psif->pdev->dev, "overrun read error\n"); 121 122 serio_interrupt(psif->io, val, io_flags); 123 124 retval = IRQ_HANDLED; 125 } 126 127 return retval; 128} 129 130static int psif_write(struct serio *io, unsigned char val) 131{ 132 struct psif *psif = io->port_data; 133 unsigned long flags; 134 int timeout = 10; 135 int retval = 0; 136 137 spin_lock_irqsave(&psif->lock, flags); 138 139 while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--) 140 msleep(10); 141 142 if (timeout >= 0) { 143 psif_writel(psif, THR, val); 144 } else { 145 dev_dbg(&psif->pdev->dev, "timeout writing to THR\n"); 146 retval = -EBUSY; 147 } 148 149 spin_unlock_irqrestore(&psif->lock, flags); 150 151 return retval; 152} 153 154static int psif_open(struct serio *io) 155{ 156 struct psif *psif = io->port_data; 157 int retval; 158 159 retval = clk_enable(psif->pclk); 160 if (retval) 161 goto out; 162 163 psif_writel(psif, CR, PSIF_BIT(CR_TXEN) | PSIF_BIT(CR_RXEN)); 164 psif_writel(psif, IER, PSIF_BIT(RXRDY)); 165 166 psif->open = 1; 167out: 168 return retval; 169} 170 171static void psif_close(struct serio *io) 172{ 173 struct psif *psif = io->port_data; 174 175 psif->open = 0; 176 177 psif_writel(psif, IDR, ~0UL); 178 psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS)); 179 180 clk_disable(psif->pclk); 181} 182 183static void psif_set_prescaler(struct psif *psif) 184{ 185 unsigned long prscv; 186 unsigned long rate = clk_get_rate(psif->pclk); 187 188 /* PRSCV = Pulse length (100 us) * PSIF module frequency. */ 189 prscv = 100 * (rate / 1000000UL); 190 191 if (prscv > ((1<<PSIF_PSR_PRSCV_SIZE) - 1)) { 192 prscv = (1<<PSIF_PSR_PRSCV_SIZE) - 1; 193 dev_dbg(&psif->pdev->dev, "pclk too fast, " 194 "prescaler set to max\n"); 195 } 196 197 clk_enable(psif->pclk); 198 psif_writel(psif, PSR, prscv); 199 clk_disable(psif->pclk); 200} 201 202static int __init psif_probe(struct platform_device *pdev) 203{ 204 struct resource *regs; 205 struct psif *psif; 206 struct serio *io; 207 struct clk *pclk; 208 int irq; 209 int ret; 210 211 psif = kzalloc(sizeof(struct psif), GFP_KERNEL); 212 if (!psif) { 213 dev_dbg(&pdev->dev, "out of memory\n"); 214 ret = -ENOMEM; 215 goto out; 216 } 217 psif->pdev = pdev; 218 219 io = kzalloc(sizeof(struct serio), GFP_KERNEL); 220 if (!io) { 221 dev_dbg(&pdev->dev, "out of memory\n"); 222 ret = -ENOMEM; 223 goto out_free_psif; 224 } 225 psif->io = io; 226 227 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 228 if (!regs) { 229 dev_dbg(&pdev->dev, "no mmio resources defined\n"); 230 ret = -ENOMEM; 231 goto out_free_io; 232 } 233 234 psif->regs = ioremap(regs->start, resource_size(regs)); 235 if (!psif->regs) { 236 ret = -ENOMEM; 237 dev_dbg(&pdev->dev, "could not map I/O memory\n"); 238 goto out_free_io; 239 } 240 241 pclk = clk_get(&pdev->dev, "pclk"); 242 if (IS_ERR(pclk)) { 243 dev_dbg(&pdev->dev, "could not get peripheral clock\n"); 244 ret = PTR_ERR(pclk); 245 goto out_iounmap; 246 } 247 psif->pclk = pclk; 248 249 /* Reset the PSIF to enter at a known state. */ 250 ret = clk_enable(pclk); 251 if (ret) { 252 dev_dbg(&pdev->dev, "could not enable pclk\n"); 253 goto out_put_clk; 254 } 255 psif_writel(psif, CR, PSIF_BIT(CR_SWRST)); 256 clk_disable(pclk); 257 258 irq = platform_get_irq(pdev, 0); 259 if (irq < 0) { 260 dev_dbg(&pdev->dev, "could not get irq\n"); 261 ret = -ENXIO; 262 goto out_put_clk; 263 } 264 ret = request_irq(irq, psif_interrupt, IRQF_SHARED, "at32psif", psif); 265 if (ret) { 266 dev_dbg(&pdev->dev, "could not request irq %d\n", irq); 267 goto out_put_clk; 268 } 269 psif->irq = irq; 270 271 io->id.type = SERIO_8042; 272 io->write = psif_write; 273 io->open = psif_open; 274 io->close = psif_close; 275 snprintf(io->name, sizeof(io->name), "AVR32 PS/2 port%d", pdev->id); 276 snprintf(io->phys, sizeof(io->phys), "at32psif/serio%d", pdev->id); 277 io->port_data = psif; 278 io->dev.parent = &pdev->dev; 279 280 psif_set_prescaler(psif); 281 282 spin_lock_init(&psif->lock); 283 serio_register_port(psif->io); 284 platform_set_drvdata(pdev, psif); 285 286 dev_info(&pdev->dev, "Atmel AVR32 PSIF PS/2 driver on 0x%08x irq %d\n", 287 (int)psif->regs, psif->irq); 288 289 return 0; 290 291out_put_clk: 292 clk_put(psif->pclk); 293out_iounmap: 294 iounmap(psif->regs); 295out_free_io: 296 kfree(io); 297out_free_psif: 298 kfree(psif); 299out: 300 return ret; 301} 302 303static int __exit psif_remove(struct platform_device *pdev) 304{ 305 struct psif *psif = platform_get_drvdata(pdev); 306 307 psif_writel(psif, IDR, ~0UL); 308 psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS)); 309 310 serio_unregister_port(psif->io); 311 iounmap(psif->regs); 312 free_irq(psif->irq, psif); 313 clk_put(psif->pclk); 314 kfree(psif); 315 316 platform_set_drvdata(pdev, NULL); 317 318 return 0; 319} 320 321#ifdef CONFIG_PM 322static int psif_suspend(struct platform_device *pdev, pm_message_t state) 323{ 324 struct psif *psif = platform_get_drvdata(pdev); 325 326 if (psif->open) { 327 psif_writel(psif, CR, PSIF_BIT(CR_RXDIS) | PSIF_BIT(CR_TXDIS)); 328 clk_disable(psif->pclk); 329 } 330 331 return 0; 332} 333 334static int psif_resume(struct platform_device *pdev) 335{ 336 struct psif *psif = platform_get_drvdata(pdev); 337 338 if (psif->open) { 339 clk_enable(psif->pclk); 340 psif_set_prescaler(psif); 341 psif_writel(psif, CR, PSIF_BIT(CR_RXEN) | PSIF_BIT(CR_TXEN)); 342 } 343 344 return 0; 345} 346#else 347#define psif_suspend NULL 348#define psif_resume NULL 349#endif 350 351static struct platform_driver psif_driver = { 352 .remove = __exit_p(psif_remove), 353 .driver = { 354 .name = "atmel_psif", 355 }, 356 .suspend = psif_suspend, 357 .resume = psif_resume, 358}; 359 360static int __init psif_init(void) 361{ 362 return platform_driver_probe(&psif_driver, psif_probe); 363} 364 365static void __exit psif_exit(void) 366{ 367 platform_driver_unregister(&psif_driver); 368} 369 370module_init(psif_init); 371module_exit(psif_exit); 372 373MODULE_AUTHOR("Hans-Christian Egtvedt <hans-christian.egtvedt@atmel.com>"); 374MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver"); 375MODULE_LICENSE("GPL");