1*1191828fSJohn Linn /* 2*1191828fSJohn Linn * Xilinx XPS PS/2 device driver 3*1191828fSJohn Linn * 4*1191828fSJohn Linn * (c) 2005 MontaVista Software, Inc. 5*1191828fSJohn Linn * (c) 2008 Xilinx, Inc. 6*1191828fSJohn Linn * 7*1191828fSJohn Linn * This program is free software; you can redistribute it and/or modify it 8*1191828fSJohn Linn * under the terms of the GNU General Public License as published by the 9*1191828fSJohn Linn * Free Software Foundation; either version 2 of the License, or (at your 10*1191828fSJohn Linn * option) any later version. 11*1191828fSJohn Linn * 12*1191828fSJohn Linn * You should have received a copy of the GNU General Public License along 13*1191828fSJohn Linn * with this program; if not, write to the Free Software Foundation, Inc., 14*1191828fSJohn Linn * 675 Mass Ave, Cambridge, MA 02139, USA. 15*1191828fSJohn Linn */ 16*1191828fSJohn Linn 17*1191828fSJohn Linn 18*1191828fSJohn Linn #include <linux/module.h> 19*1191828fSJohn Linn #include <linux/serio.h> 20*1191828fSJohn Linn #include <linux/interrupt.h> 21*1191828fSJohn Linn #include <linux/errno.h> 22*1191828fSJohn Linn #include <linux/init.h> 23*1191828fSJohn Linn #include <linux/list.h> 24*1191828fSJohn Linn #include <linux/io.h> 25*1191828fSJohn Linn 26*1191828fSJohn Linn #include <linux/of_device.h> 27*1191828fSJohn Linn #include <linux/of_platform.h> 28*1191828fSJohn Linn 29*1191828fSJohn Linn #define DRIVER_NAME "xilinx_ps2" 30*1191828fSJohn Linn 31*1191828fSJohn Linn /* Register offsets for the xps2 device */ 32*1191828fSJohn Linn #define XPS2_SRST_OFFSET 0x00000000 /* Software Reset register */ 33*1191828fSJohn Linn #define XPS2_STATUS_OFFSET 0x00000004 /* Status register */ 34*1191828fSJohn Linn #define XPS2_RX_DATA_OFFSET 0x00000008 /* Receive Data register */ 35*1191828fSJohn Linn #define XPS2_TX_DATA_OFFSET 0x0000000C /* Transmit Data register */ 36*1191828fSJohn Linn #define XPS2_GIER_OFFSET 0x0000002C /* Global Interrupt Enable reg */ 37*1191828fSJohn Linn #define XPS2_IPISR_OFFSET 0x00000030 /* Interrupt Status register */ 38*1191828fSJohn Linn #define XPS2_IPIER_OFFSET 0x00000038 /* Interrupt Enable register */ 39*1191828fSJohn Linn 40*1191828fSJohn Linn /* Reset Register Bit Definitions */ 41*1191828fSJohn Linn #define XPS2_SRST_RESET 0x0000000A /* Software Reset */ 42*1191828fSJohn Linn 43*1191828fSJohn Linn /* Status Register Bit Positions */ 44*1191828fSJohn Linn #define XPS2_STATUS_RX_FULL 0x00000001 /* Receive Full */ 45*1191828fSJohn Linn #define XPS2_STATUS_TX_FULL 0x00000002 /* Transmit Full */ 46*1191828fSJohn Linn 47*1191828fSJohn Linn /* Bit definitions for ISR/IER registers. Both the registers have the same bit 48*1191828fSJohn Linn * definitions and are only defined once. */ 49*1191828fSJohn Linn #define XPS2_IPIXR_WDT_TOUT 0x00000001 /* Watchdog Timeout Interrupt */ 50*1191828fSJohn Linn #define XPS2_IPIXR_TX_NOACK 0x00000002 /* Transmit No ACK Interrupt */ 51*1191828fSJohn Linn #define XPS2_IPIXR_TX_ACK 0x00000004 /* Transmit ACK (Data) Interrupt */ 52*1191828fSJohn Linn #define XPS2_IPIXR_RX_OVF 0x00000008 /* Receive Overflow Interrupt */ 53*1191828fSJohn Linn #define XPS2_IPIXR_RX_ERR 0x00000010 /* Receive Error Interrupt */ 54*1191828fSJohn Linn #define XPS2_IPIXR_RX_FULL 0x00000020 /* Receive Data Interrupt */ 55*1191828fSJohn Linn 56*1191828fSJohn Linn /* Mask for all the Transmit Interrupts */ 57*1191828fSJohn Linn #define XPS2_IPIXR_TX_ALL (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_TX_ACK) 58*1191828fSJohn Linn 59*1191828fSJohn Linn /* Mask for all the Receive Interrupts */ 60*1191828fSJohn Linn #define XPS2_IPIXR_RX_ALL (XPS2_IPIXR_RX_OVF | XPS2_IPIXR_RX_ERR | \ 61*1191828fSJohn Linn XPS2_IPIXR_RX_FULL) 62*1191828fSJohn Linn 63*1191828fSJohn Linn /* Mask for all the Interrupts */ 64*1191828fSJohn Linn #define XPS2_IPIXR_ALL (XPS2_IPIXR_TX_ALL | XPS2_IPIXR_RX_ALL | \ 65*1191828fSJohn Linn XPS2_IPIXR_WDT_TOUT) 66*1191828fSJohn Linn 67*1191828fSJohn Linn /* Global Interrupt Enable mask */ 68*1191828fSJohn Linn #define XPS2_GIER_GIE_MASK 0x80000000 69*1191828fSJohn Linn 70*1191828fSJohn Linn struct xps2data { 71*1191828fSJohn Linn int irq; 72*1191828fSJohn Linn u32 phys_addr; 73*1191828fSJohn Linn u32 remap_size; 74*1191828fSJohn Linn spinlock_t lock; 75*1191828fSJohn Linn u8 rxb; /* Rx buffer */ 76*1191828fSJohn Linn void __iomem *base_address; /* virt. address of control registers */ 77*1191828fSJohn Linn unsigned int dfl; 78*1191828fSJohn Linn struct serio serio; /* serio */ 79*1191828fSJohn Linn }; 80*1191828fSJohn Linn 81*1191828fSJohn Linn /************************************/ 82*1191828fSJohn Linn /* XPS PS/2 data transmission calls */ 83*1191828fSJohn Linn /************************************/ 84*1191828fSJohn Linn 85*1191828fSJohn Linn /* 86*1191828fSJohn Linn * xps2_recv() will attempt to receive a byte of data from the PS/2 port. 87*1191828fSJohn Linn */ 88*1191828fSJohn Linn static int xps2_recv(struct xps2data *drvdata, u8 *byte) 89*1191828fSJohn Linn { 90*1191828fSJohn Linn u32 sr; 91*1191828fSJohn Linn int status = -1; 92*1191828fSJohn Linn 93*1191828fSJohn Linn /* If there is data available in the PS/2 receiver, read it */ 94*1191828fSJohn Linn sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET); 95*1191828fSJohn Linn if (sr & XPS2_STATUS_RX_FULL) { 96*1191828fSJohn Linn *byte = in_be32(drvdata->base_address + XPS2_RX_DATA_OFFSET); 97*1191828fSJohn Linn status = 0; 98*1191828fSJohn Linn } 99*1191828fSJohn Linn 100*1191828fSJohn Linn return status; 101*1191828fSJohn Linn } 102*1191828fSJohn Linn 103*1191828fSJohn Linn /*********************/ 104*1191828fSJohn Linn /* Interrupt handler */ 105*1191828fSJohn Linn /*********************/ 106*1191828fSJohn Linn static irqreturn_t xps2_interrupt(int irq, void *dev_id) 107*1191828fSJohn Linn { 108*1191828fSJohn Linn struct xps2data *drvdata = dev_id; 109*1191828fSJohn Linn u32 intr_sr; 110*1191828fSJohn Linn u8 c; 111*1191828fSJohn Linn int status; 112*1191828fSJohn Linn 113*1191828fSJohn Linn /* Get the PS/2 interrupts and clear them */ 114*1191828fSJohn Linn intr_sr = in_be32(drvdata->base_address + XPS2_IPISR_OFFSET); 115*1191828fSJohn Linn out_be32(drvdata->base_address + XPS2_IPISR_OFFSET, intr_sr); 116*1191828fSJohn Linn 117*1191828fSJohn Linn /* Check which interrupt is active */ 118*1191828fSJohn Linn if (intr_sr & XPS2_IPIXR_RX_OVF) 119*1191828fSJohn Linn printk(KERN_WARNING "%s: receive overrun error\n", 120*1191828fSJohn Linn drvdata->serio.name); 121*1191828fSJohn Linn 122*1191828fSJohn Linn if (intr_sr & XPS2_IPIXR_RX_ERR) 123*1191828fSJohn Linn drvdata->dfl |= SERIO_PARITY; 124*1191828fSJohn Linn 125*1191828fSJohn Linn if (intr_sr & (XPS2_IPIXR_TX_NOACK | XPS2_IPIXR_WDT_TOUT)) 126*1191828fSJohn Linn drvdata->dfl |= SERIO_TIMEOUT; 127*1191828fSJohn Linn 128*1191828fSJohn Linn if (intr_sr & XPS2_IPIXR_RX_FULL) { 129*1191828fSJohn Linn status = xps2_recv(drvdata, &drvdata->rxb); 130*1191828fSJohn Linn 131*1191828fSJohn Linn /* Error, if a byte is not received */ 132*1191828fSJohn Linn if (status) { 133*1191828fSJohn Linn printk(KERN_ERR 134*1191828fSJohn Linn "%s: wrong rcvd byte count (%d)\n", 135*1191828fSJohn Linn drvdata->serio.name, status); 136*1191828fSJohn Linn } else { 137*1191828fSJohn Linn c = drvdata->rxb; 138*1191828fSJohn Linn serio_interrupt(&drvdata->serio, c, drvdata->dfl); 139*1191828fSJohn Linn drvdata->dfl = 0; 140*1191828fSJohn Linn } 141*1191828fSJohn Linn } 142*1191828fSJohn Linn 143*1191828fSJohn Linn if (intr_sr & XPS2_IPIXR_TX_ACK) 144*1191828fSJohn Linn drvdata->dfl = 0; 145*1191828fSJohn Linn 146*1191828fSJohn Linn return IRQ_HANDLED; 147*1191828fSJohn Linn } 148*1191828fSJohn Linn 149*1191828fSJohn Linn /*******************/ 150*1191828fSJohn Linn /* serio callbacks */ 151*1191828fSJohn Linn /*******************/ 152*1191828fSJohn Linn 153*1191828fSJohn Linn /* 154*1191828fSJohn Linn * sxps2_write() sends a byte out through the PS/2 interface. 155*1191828fSJohn Linn */ 156*1191828fSJohn Linn static int sxps2_write(struct serio *pserio, unsigned char c) 157*1191828fSJohn Linn { 158*1191828fSJohn Linn struct xps2data *drvdata = pserio->port_data; 159*1191828fSJohn Linn unsigned long flags; 160*1191828fSJohn Linn u32 sr; 161*1191828fSJohn Linn int status = -1; 162*1191828fSJohn Linn 163*1191828fSJohn Linn spin_lock_irqsave(&drvdata->lock, flags); 164*1191828fSJohn Linn 165*1191828fSJohn Linn /* If the PS/2 transmitter is empty send a byte of data */ 166*1191828fSJohn Linn sr = in_be32(drvdata->base_address + XPS2_STATUS_OFFSET); 167*1191828fSJohn Linn if (!(sr & XPS2_STATUS_TX_FULL)) { 168*1191828fSJohn Linn out_be32(drvdata->base_address + XPS2_TX_DATA_OFFSET, c); 169*1191828fSJohn Linn status = 0; 170*1191828fSJohn Linn } 171*1191828fSJohn Linn 172*1191828fSJohn Linn spin_unlock_irqrestore(&drvdata->lock, flags); 173*1191828fSJohn Linn 174*1191828fSJohn Linn return status; 175*1191828fSJohn Linn } 176*1191828fSJohn Linn 177*1191828fSJohn Linn /* 178*1191828fSJohn Linn * sxps2_open() is called when a port is open by the higher layer. 179*1191828fSJohn Linn */ 180*1191828fSJohn Linn static int sxps2_open(struct serio *pserio) 181*1191828fSJohn Linn { 182*1191828fSJohn Linn struct xps2data *drvdata = pserio->port_data; 183*1191828fSJohn Linn int retval; 184*1191828fSJohn Linn 185*1191828fSJohn Linn retval = request_irq(drvdata->irq, &xps2_interrupt, 0, 186*1191828fSJohn Linn DRIVER_NAME, drvdata); 187*1191828fSJohn Linn if (retval) { 188*1191828fSJohn Linn printk(KERN_ERR 189*1191828fSJohn Linn "%s: Couldn't allocate interrupt %d\n", 190*1191828fSJohn Linn drvdata->serio.name, drvdata->irq); 191*1191828fSJohn Linn return retval; 192*1191828fSJohn Linn } 193*1191828fSJohn Linn 194*1191828fSJohn Linn /* start reception by enabling the interrupts */ 195*1191828fSJohn Linn out_be32(drvdata->base_address + XPS2_GIER_OFFSET, XPS2_GIER_GIE_MASK); 196*1191828fSJohn Linn out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, XPS2_IPIXR_RX_ALL); 197*1191828fSJohn Linn (void)xps2_recv(drvdata, &drvdata->rxb); 198*1191828fSJohn Linn 199*1191828fSJohn Linn return 0; /* success */ 200*1191828fSJohn Linn } 201*1191828fSJohn Linn 202*1191828fSJohn Linn /* 203*1191828fSJohn Linn * sxps2_close() frees the interrupt. 204*1191828fSJohn Linn */ 205*1191828fSJohn Linn static void sxps2_close(struct serio *pserio) 206*1191828fSJohn Linn { 207*1191828fSJohn Linn struct xps2data *drvdata = pserio->port_data; 208*1191828fSJohn Linn 209*1191828fSJohn Linn /* Disable the PS2 interrupts */ 210*1191828fSJohn Linn out_be32(drvdata->base_address + XPS2_GIER_OFFSET, 0x00); 211*1191828fSJohn Linn out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0x00); 212*1191828fSJohn Linn free_irq(drvdata->irq, drvdata); 213*1191828fSJohn Linn } 214*1191828fSJohn Linn 215*1191828fSJohn Linn /*********************/ 216*1191828fSJohn Linn /* Device setup code */ 217*1191828fSJohn Linn /*********************/ 218*1191828fSJohn Linn 219*1191828fSJohn Linn static int xps2_setup(struct device *dev, struct resource *regs_res, 220*1191828fSJohn Linn struct resource *irq_res) 221*1191828fSJohn Linn { 222*1191828fSJohn Linn struct xps2data *drvdata; 223*1191828fSJohn Linn struct serio *serio; 224*1191828fSJohn Linn unsigned long remap_size; 225*1191828fSJohn Linn int retval; 226*1191828fSJohn Linn 227*1191828fSJohn Linn if (!dev) 228*1191828fSJohn Linn return -EINVAL; 229*1191828fSJohn Linn 230*1191828fSJohn Linn if (!regs_res || !irq_res) { 231*1191828fSJohn Linn dev_err(dev, "IO resource(s) not found\n"); 232*1191828fSJohn Linn return -EINVAL; 233*1191828fSJohn Linn } 234*1191828fSJohn Linn 235*1191828fSJohn Linn drvdata = kzalloc(sizeof(struct xps2data), GFP_KERNEL); 236*1191828fSJohn Linn if (!drvdata) { 237*1191828fSJohn Linn dev_err(dev, "Couldn't allocate device private record\n"); 238*1191828fSJohn Linn return -ENOMEM; 239*1191828fSJohn Linn } 240*1191828fSJohn Linn 241*1191828fSJohn Linn dev_set_drvdata(dev, drvdata); 242*1191828fSJohn Linn 243*1191828fSJohn Linn spin_lock_init(&drvdata->lock); 244*1191828fSJohn Linn drvdata->irq = irq_res->start; 245*1191828fSJohn Linn 246*1191828fSJohn Linn remap_size = regs_res->end - regs_res->start + 1; 247*1191828fSJohn Linn if (!request_mem_region(regs_res->start, remap_size, DRIVER_NAME)) { 248*1191828fSJohn Linn dev_err(dev, "Couldn't lock memory region at 0x%08X\n", 249*1191828fSJohn Linn (unsigned int)regs_res->start); 250*1191828fSJohn Linn retval = -EBUSY; 251*1191828fSJohn Linn goto failed1; 252*1191828fSJohn Linn } 253*1191828fSJohn Linn 254*1191828fSJohn Linn /* Fill in configuration data and add them to the list */ 255*1191828fSJohn Linn drvdata->phys_addr = regs_res->start; 256*1191828fSJohn Linn drvdata->remap_size = remap_size; 257*1191828fSJohn Linn drvdata->base_address = ioremap(regs_res->start, remap_size); 258*1191828fSJohn Linn if (drvdata->base_address == NULL) { 259*1191828fSJohn Linn dev_err(dev, "Couldn't ioremap memory at 0x%08X\n", 260*1191828fSJohn Linn (unsigned int)regs_res->start); 261*1191828fSJohn Linn retval = -EFAULT; 262*1191828fSJohn Linn goto failed2; 263*1191828fSJohn Linn } 264*1191828fSJohn Linn 265*1191828fSJohn Linn /* Disable all the interrupts, just in case */ 266*1191828fSJohn Linn out_be32(drvdata->base_address + XPS2_IPIER_OFFSET, 0); 267*1191828fSJohn Linn 268*1191828fSJohn Linn /* Reset the PS2 device and abort any current transaction, to make sure 269*1191828fSJohn Linn * we have the PS2 in a good state */ 270*1191828fSJohn Linn out_be32(drvdata->base_address + XPS2_SRST_OFFSET, XPS2_SRST_RESET); 271*1191828fSJohn Linn 272*1191828fSJohn Linn dev_info(dev, "Xilinx PS2 at 0x%08X mapped to 0x%08X, irq=%d\n", 273*1191828fSJohn Linn drvdata->phys_addr, (u32)drvdata->base_address, drvdata->irq); 274*1191828fSJohn Linn 275*1191828fSJohn Linn serio = &drvdata->serio; 276*1191828fSJohn Linn serio->id.type = SERIO_8042; 277*1191828fSJohn Linn serio->write = sxps2_write; 278*1191828fSJohn Linn serio->open = sxps2_open; 279*1191828fSJohn Linn serio->close = sxps2_close; 280*1191828fSJohn Linn serio->port_data = drvdata; 281*1191828fSJohn Linn serio->dev.parent = dev; 282*1191828fSJohn Linn snprintf(serio->name, sizeof(serio->name), 283*1191828fSJohn Linn "Xilinx XPS PS/2 at %08X", drvdata->phys_addr); 284*1191828fSJohn Linn snprintf(serio->phys, sizeof(serio->phys), 285*1191828fSJohn Linn "xilinxps2/serio at %08X", drvdata->phys_addr); 286*1191828fSJohn Linn serio_register_port(serio); 287*1191828fSJohn Linn 288*1191828fSJohn Linn return 0; /* success */ 289*1191828fSJohn Linn 290*1191828fSJohn Linn failed2: 291*1191828fSJohn Linn release_mem_region(regs_res->start, remap_size); 292*1191828fSJohn Linn failed1: 293*1191828fSJohn Linn kfree(drvdata); 294*1191828fSJohn Linn dev_set_drvdata(dev, NULL); 295*1191828fSJohn Linn 296*1191828fSJohn Linn return retval; 297*1191828fSJohn Linn } 298*1191828fSJohn Linn 299*1191828fSJohn Linn /***************************/ 300*1191828fSJohn Linn /* OF Platform Bus Support */ 301*1191828fSJohn Linn /***************************/ 302*1191828fSJohn Linn 303*1191828fSJohn Linn static int __devinit xps2_of_probe(struct of_device *ofdev, const struct 304*1191828fSJohn Linn of_device_id * match) 305*1191828fSJohn Linn { 306*1191828fSJohn Linn struct resource r_irq; /* Interrupt resources */ 307*1191828fSJohn Linn struct resource r_mem; /* IO mem resources */ 308*1191828fSJohn Linn int rc = 0; 309*1191828fSJohn Linn 310*1191828fSJohn Linn printk(KERN_INFO "Device Tree Probing \'%s\'\n", 311*1191828fSJohn Linn ofdev->node->name); 312*1191828fSJohn Linn 313*1191828fSJohn Linn /* Get iospace for the device */ 314*1191828fSJohn Linn rc = of_address_to_resource(ofdev->node, 0, &r_mem); 315*1191828fSJohn Linn if (rc) { 316*1191828fSJohn Linn dev_err(&ofdev->dev, "invalid address\n"); 317*1191828fSJohn Linn return rc; 318*1191828fSJohn Linn } 319*1191828fSJohn Linn 320*1191828fSJohn Linn /* Get IRQ for the device */ 321*1191828fSJohn Linn rc = of_irq_to_resource(ofdev->node, 0, &r_irq); 322*1191828fSJohn Linn if (rc == NO_IRQ) { 323*1191828fSJohn Linn dev_err(&ofdev->dev, "no IRQ found\n"); 324*1191828fSJohn Linn return rc; 325*1191828fSJohn Linn } 326*1191828fSJohn Linn 327*1191828fSJohn Linn return xps2_setup(&ofdev->dev, &r_mem, &r_irq); 328*1191828fSJohn Linn } 329*1191828fSJohn Linn 330*1191828fSJohn Linn static int __devexit xps2_of_remove(struct of_device *of_dev) 331*1191828fSJohn Linn { 332*1191828fSJohn Linn struct device *dev = &of_dev->dev; 333*1191828fSJohn Linn struct xps2data *drvdata; 334*1191828fSJohn Linn 335*1191828fSJohn Linn if (!dev) 336*1191828fSJohn Linn return -EINVAL; 337*1191828fSJohn Linn 338*1191828fSJohn Linn drvdata = dev_get_drvdata(dev); 339*1191828fSJohn Linn 340*1191828fSJohn Linn serio_unregister_port(&drvdata->serio); 341*1191828fSJohn Linn iounmap(drvdata->base_address); 342*1191828fSJohn Linn release_mem_region(drvdata->phys_addr, drvdata->remap_size); 343*1191828fSJohn Linn kfree(drvdata); 344*1191828fSJohn Linn 345*1191828fSJohn Linn dev_set_drvdata(dev, NULL); 346*1191828fSJohn Linn 347*1191828fSJohn Linn return 0; /* success */ 348*1191828fSJohn Linn } 349*1191828fSJohn Linn 350*1191828fSJohn Linn /* Match table for of_platform binding */ 351*1191828fSJohn Linn static struct of_device_id xps2_of_match[] __devinitdata = { 352*1191828fSJohn Linn { .compatible = "xlnx,xps-ps2-1.00.a", }, 353*1191828fSJohn Linn { /* end of list */ }, 354*1191828fSJohn Linn }; 355*1191828fSJohn Linn MODULE_DEVICE_TABLE(of, xps2_of_match); 356*1191828fSJohn Linn 357*1191828fSJohn Linn static struct of_platform_driver xps2_of_driver = { 358*1191828fSJohn Linn .name = DRIVER_NAME, 359*1191828fSJohn Linn .match_table = xps2_of_match, 360*1191828fSJohn Linn .probe = xps2_of_probe, 361*1191828fSJohn Linn .remove = __devexit_p(xps2_of_remove), 362*1191828fSJohn Linn }; 363*1191828fSJohn Linn 364*1191828fSJohn Linn static int __init xps2_init(void) 365*1191828fSJohn Linn { 366*1191828fSJohn Linn return of_register_platform_driver(&xps2_of_driver); 367*1191828fSJohn Linn } 368*1191828fSJohn Linn 369*1191828fSJohn Linn static void __exit xps2_cleanup(void) 370*1191828fSJohn Linn { 371*1191828fSJohn Linn of_unregister_platform_driver(&xps2_of_driver); 372*1191828fSJohn Linn } 373*1191828fSJohn Linn 374*1191828fSJohn Linn module_init(xps2_init); 375*1191828fSJohn Linn module_exit(xps2_cleanup); 376*1191828fSJohn Linn 377*1191828fSJohn Linn MODULE_AUTHOR("Xilinx, Inc."); 378*1191828fSJohn Linn MODULE_DESCRIPTION("Xilinx XPS PS/2 driver"); 379*1191828fSJohn Linn MODULE_LICENSE("GPL"); 380*1191828fSJohn Linn 381