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 v4.15-rc3 357 lines 8.3 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#include <linux/slab.h> 22 23/* PSIF register offsets */ 24#define PSIF_CR 0x00 25#define PSIF_RHR 0x04 26#define PSIF_THR 0x08 27#define PSIF_SR 0x10 28#define PSIF_IER 0x14 29#define PSIF_IDR 0x18 30#define PSIF_IMR 0x1c 31#define PSIF_PSR 0x24 32 33/* Bitfields in control register. */ 34#define PSIF_CR_RXDIS_OFFSET 1 35#define PSIF_CR_RXDIS_SIZE 1 36#define PSIF_CR_RXEN_OFFSET 0 37#define PSIF_CR_RXEN_SIZE 1 38#define PSIF_CR_SWRST_OFFSET 15 39#define PSIF_CR_SWRST_SIZE 1 40#define PSIF_CR_TXDIS_OFFSET 9 41#define PSIF_CR_TXDIS_SIZE 1 42#define PSIF_CR_TXEN_OFFSET 8 43#define PSIF_CR_TXEN_SIZE 1 44 45/* Bitfields in interrupt disable, enable, mask and status register. */ 46#define PSIF_NACK_OFFSET 8 47#define PSIF_NACK_SIZE 1 48#define PSIF_OVRUN_OFFSET 5 49#define PSIF_OVRUN_SIZE 1 50#define PSIF_PARITY_OFFSET 9 51#define PSIF_PARITY_SIZE 1 52#define PSIF_RXRDY_OFFSET 4 53#define PSIF_RXRDY_SIZE 1 54#define PSIF_TXEMPTY_OFFSET 1 55#define PSIF_TXEMPTY_SIZE 1 56#define PSIF_TXRDY_OFFSET 0 57#define PSIF_TXRDY_SIZE 1 58 59/* Bitfields in prescale register. */ 60#define PSIF_PSR_PRSCV_OFFSET 0 61#define PSIF_PSR_PRSCV_SIZE 12 62 63/* Bitfields in receive hold register. */ 64#define PSIF_RHR_RXDATA_OFFSET 0 65#define PSIF_RHR_RXDATA_SIZE 8 66 67/* Bitfields in transmit hold register. */ 68#define PSIF_THR_TXDATA_OFFSET 0 69#define PSIF_THR_TXDATA_SIZE 8 70 71/* Bit manipulation macros */ 72#define PSIF_BIT(name) \ 73 (1 << PSIF_##name##_OFFSET) 74 75#define PSIF_BF(name, value) \ 76 (((value) & ((1 << PSIF_##name##_SIZE) - 1)) \ 77 << PSIF_##name##_OFFSET) 78 79#define PSIF_BFEXT(name, value) \ 80 (((value) >> PSIF_##name##_OFFSET) \ 81 & ((1 << PSIF_##name##_SIZE) - 1)) 82 83#define PSIF_BFINS(name, value, old) \ 84 (((old) & ~(((1 << PSIF_##name##_SIZE) - 1) \ 85 << PSIF_##name##_OFFSET)) \ 86 | PSIF_BF(name, value)) 87 88/* Register access macros */ 89#define psif_readl(port, reg) \ 90 __raw_readl((port)->regs + PSIF_##reg) 91 92#define psif_writel(port, reg, value) \ 93 __raw_writel((value), (port)->regs + PSIF_##reg) 94 95struct psif { 96 struct platform_device *pdev; 97 struct clk *pclk; 98 struct serio *io; 99 void __iomem *regs; 100 unsigned int irq; 101 /* Prevent concurrent writes to PSIF THR. */ 102 spinlock_t lock; 103 bool open; 104}; 105 106static irqreturn_t psif_interrupt(int irq, void *_ptr) 107{ 108 struct psif *psif = _ptr; 109 int retval = IRQ_NONE; 110 unsigned int io_flags = 0; 111 unsigned long status; 112 113 status = psif_readl(psif, SR); 114 115 if (status & PSIF_BIT(RXRDY)) { 116 unsigned char val = (unsigned char) psif_readl(psif, RHR); 117 118 if (status & PSIF_BIT(PARITY)) 119 io_flags |= SERIO_PARITY; 120 if (status & PSIF_BIT(OVRUN)) 121 dev_err(&psif->pdev->dev, "overrun read error\n"); 122 123 serio_interrupt(psif->io, val, io_flags); 124 125 retval = IRQ_HANDLED; 126 } 127 128 return retval; 129} 130 131static int psif_write(struct serio *io, unsigned char val) 132{ 133 struct psif *psif = io->port_data; 134 unsigned long flags; 135 int timeout = 10; 136 int retval = 0; 137 138 spin_lock_irqsave(&psif->lock, flags); 139 140 while (!(psif_readl(psif, SR) & PSIF_BIT(TXEMPTY)) && timeout--) 141 udelay(50); 142 143 if (timeout >= 0) { 144 psif_writel(psif, THR, val); 145 } else { 146 dev_dbg(&psif->pdev->dev, "timeout writing to THR\n"); 147 retval = -EBUSY; 148 } 149 150 spin_unlock_irqrestore(&psif->lock, flags); 151 152 return retval; 153} 154 155static int psif_open(struct serio *io) 156{ 157 struct psif *psif = io->port_data; 158 int retval; 159 160 retval = clk_enable(psif->pclk); 161 if (retval) 162 return retval; 163 164 psif_writel(psif, CR, PSIF_BIT(CR_TXEN) | PSIF_BIT(CR_RXEN)); 165 psif_writel(psif, IER, PSIF_BIT(RXRDY)); 166 167 psif->open = true; 168 return retval; 169} 170 171static void psif_close(struct serio *io) 172{ 173 struct psif *psif = io->port_data; 174 175 psif->open = false; 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 return -ENOMEM; 214 psif->pdev = pdev; 215 216 io = kzalloc(sizeof(struct serio), GFP_KERNEL); 217 if (!io) { 218 ret = -ENOMEM; 219 goto out_free_psif; 220 } 221 psif->io = io; 222 223 regs = platform_get_resource(pdev, IORESOURCE_MEM, 0); 224 if (!regs) { 225 dev_dbg(&pdev->dev, "no mmio resources defined\n"); 226 ret = -ENOMEM; 227 goto out_free_io; 228 } 229 230 psif->regs = ioremap(regs->start, resource_size(regs)); 231 if (!psif->regs) { 232 ret = -ENOMEM; 233 dev_dbg(&pdev->dev, "could not map I/O memory\n"); 234 goto out_free_io; 235 } 236 237 pclk = clk_get(&pdev->dev, "pclk"); 238 if (IS_ERR(pclk)) { 239 dev_dbg(&pdev->dev, "could not get peripheral clock\n"); 240 ret = PTR_ERR(pclk); 241 goto out_iounmap; 242 } 243 psif->pclk = pclk; 244 245 /* Reset the PSIF to enter at a known state. */ 246 ret = clk_enable(pclk); 247 if (ret) { 248 dev_dbg(&pdev->dev, "could not enable pclk\n"); 249 goto out_put_clk; 250 } 251 psif_writel(psif, CR, PSIF_BIT(CR_SWRST)); 252 clk_disable(pclk); 253 254 irq = platform_get_irq(pdev, 0); 255 if (irq < 0) { 256 dev_dbg(&pdev->dev, "could not get irq\n"); 257 ret = -ENXIO; 258 goto out_put_clk; 259 } 260 ret = request_irq(irq, psif_interrupt, IRQF_SHARED, "at32psif", psif); 261 if (ret) { 262 dev_dbg(&pdev->dev, "could not request irq %d\n", irq); 263 goto out_put_clk; 264 } 265 psif->irq = irq; 266 267 io->id.type = SERIO_8042; 268 io->write = psif_write; 269 io->open = psif_open; 270 io->close = psif_close; 271 snprintf(io->name, sizeof(io->name), "AVR32 PS/2 port%d", pdev->id); 272 snprintf(io->phys, sizeof(io->phys), "at32psif/serio%d", pdev->id); 273 io->port_data = psif; 274 io->dev.parent = &pdev->dev; 275 276 psif_set_prescaler(psif); 277 278 spin_lock_init(&psif->lock); 279 serio_register_port(psif->io); 280 platform_set_drvdata(pdev, psif); 281 282 dev_info(&pdev->dev, "Atmel AVR32 PSIF PS/2 driver on 0x%08x irq %d\n", 283 (int)psif->regs, psif->irq); 284 285 return 0; 286 287out_put_clk: 288 clk_put(psif->pclk); 289out_iounmap: 290 iounmap(psif->regs); 291out_free_io: 292 kfree(io); 293out_free_psif: 294 kfree(psif); 295 return ret; 296} 297 298static int __exit psif_remove(struct platform_device *pdev) 299{ 300 struct psif *psif = platform_get_drvdata(pdev); 301 302 psif_writel(psif, IDR, ~0UL); 303 psif_writel(psif, CR, PSIF_BIT(CR_TXDIS) | PSIF_BIT(CR_RXDIS)); 304 305 serio_unregister_port(psif->io); 306 iounmap(psif->regs); 307 free_irq(psif->irq, psif); 308 clk_put(psif->pclk); 309 kfree(psif); 310 311 return 0; 312} 313 314#ifdef CONFIG_PM_SLEEP 315static int psif_suspend(struct device *dev) 316{ 317 struct platform_device *pdev = to_platform_device(dev); 318 struct psif *psif = platform_get_drvdata(pdev); 319 320 if (psif->open) { 321 psif_writel(psif, CR, PSIF_BIT(CR_RXDIS) | PSIF_BIT(CR_TXDIS)); 322 clk_disable(psif->pclk); 323 } 324 325 return 0; 326} 327 328static int psif_resume(struct device *dev) 329{ 330 struct platform_device *pdev = to_platform_device(dev); 331 struct psif *psif = platform_get_drvdata(pdev); 332 333 if (psif->open) { 334 clk_enable(psif->pclk); 335 psif_set_prescaler(psif); 336 psif_writel(psif, CR, PSIF_BIT(CR_RXEN) | PSIF_BIT(CR_TXEN)); 337 } 338 339 return 0; 340} 341#endif 342 343static SIMPLE_DEV_PM_OPS(psif_pm_ops, psif_suspend, psif_resume); 344 345static struct platform_driver psif_driver = { 346 .remove = __exit_p(psif_remove), 347 .driver = { 348 .name = "atmel_psif", 349 .pm = &psif_pm_ops, 350 }, 351}; 352 353module_platform_driver_probe(psif_driver, psif_probe); 354 355MODULE_AUTHOR("Hans-Christian Egtvedt <egtvedt@samfundet.no>"); 356MODULE_DESCRIPTION("Atmel AVR32 PSIF PS/2 driver"); 357MODULE_LICENSE("GPL");