1 /* 2 * Support code for the SCOOP interface found on various Sharp PDAs 3 * 4 * Copyright (c) 2004 Richard Purdie 5 * 6 * Based on code written by Sharp/Lineo for 2.4 kernels 7 * 8 * This program is free software; you can redistribute it and/or modify 9 * it under the terms of the GNU General Public License version 2 as 10 * published by the Free Software Foundation. 11 * 12 */ 13 14 #include <linux/device.h> 15 #include <asm/io.h> 16 #include <asm/hardware/scoop.h> 17 18 #define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr))) 19 20 /* PCMCIA to Scoop linkage structures for pxa2xx_sharpsl.c 21 There is no easy way to link multiple scoop devices into one 22 single entity for the pxa2xx_pcmcia device */ 23 int scoop_num; 24 struct scoop_pcmcia_dev *scoop_devs; 25 26 struct scoop_dev { 27 void *base; 28 spinlock_t scoop_lock; 29 u32 scoop_gpwr; 30 }; 31 32 void reset_scoop(struct device *dev) 33 { 34 struct scoop_dev *sdev = dev_get_drvdata(dev); 35 36 SCOOP_REG(sdev->base,SCOOP_MCR) = 0x0100; // 00 37 SCOOP_REG(sdev->base,SCOOP_CDR) = 0x0000; // 04 38 SCOOP_REG(sdev->base,SCOOP_CPR) = 0x0000; // 0C 39 SCOOP_REG(sdev->base,SCOOP_CCR) = 0x0000; // 10 40 SCOOP_REG(sdev->base,SCOOP_IMR) = 0x0000; // 18 41 SCOOP_REG(sdev->base,SCOOP_IRM) = 0x00FF; // 14 42 SCOOP_REG(sdev->base,SCOOP_ISR) = 0x0000; // 1C 43 SCOOP_REG(sdev->base,SCOOP_IRM) = 0x0000; 44 } 45 46 unsigned short set_scoop_gpio(struct device *dev, unsigned short bit) 47 { 48 unsigned short gpio_bit; 49 unsigned long flag; 50 struct scoop_dev *sdev = dev_get_drvdata(dev); 51 52 spin_lock_irqsave(&sdev->scoop_lock, flag); 53 gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) | bit; 54 SCOOP_REG(sdev->base, SCOOP_GPWR) = gpio_bit; 55 spin_unlock_irqrestore(&sdev->scoop_lock, flag); 56 57 return gpio_bit; 58 } 59 60 unsigned short reset_scoop_gpio(struct device *dev, unsigned short bit) 61 { 62 unsigned short gpio_bit; 63 unsigned long flag; 64 struct scoop_dev *sdev = dev_get_drvdata(dev); 65 66 spin_lock_irqsave(&sdev->scoop_lock, flag); 67 gpio_bit = SCOOP_REG(sdev->base, SCOOP_GPWR) & ~bit; 68 SCOOP_REG(sdev->base,SCOOP_GPWR) = gpio_bit; 69 spin_unlock_irqrestore(&sdev->scoop_lock, flag); 70 71 return gpio_bit; 72 } 73 74 EXPORT_SYMBOL(set_scoop_gpio); 75 EXPORT_SYMBOL(reset_scoop_gpio); 76 77 unsigned short read_scoop_reg(struct device *dev, unsigned short reg) 78 { 79 struct scoop_dev *sdev = dev_get_drvdata(dev); 80 return SCOOP_REG(sdev->base,reg); 81 } 82 83 void write_scoop_reg(struct device *dev, unsigned short reg, unsigned short data) 84 { 85 struct scoop_dev *sdev = dev_get_drvdata(dev); 86 SCOOP_REG(sdev->base,reg)=data; 87 } 88 89 EXPORT_SYMBOL(reset_scoop); 90 EXPORT_SYMBOL(read_scoop_reg); 91 EXPORT_SYMBOL(write_scoop_reg); 92 93 #ifdef CONFIG_PM 94 static int scoop_suspend(struct device *dev, pm_message_t state, uint32_t level) 95 { 96 if (level == SUSPEND_POWER_DOWN) { 97 struct scoop_dev *sdev = dev_get_drvdata(dev); 98 99 sdev->scoop_gpwr = SCOOP_REG(sdev->base,SCOOP_GPWR); 100 SCOOP_REG(sdev->base,SCOOP_GPWR) = 0; 101 } 102 return 0; 103 } 104 105 static int scoop_resume(struct device *dev, uint32_t level) 106 { 107 if (level == RESUME_POWER_ON) { 108 struct scoop_dev *sdev = dev_get_drvdata(dev); 109 110 SCOOP_REG(sdev->base,SCOOP_GPWR) = sdev->scoop_gpwr; 111 } 112 return 0; 113 } 114 #else 115 #define scoop_suspend NULL 116 #define scoop_resume NULL 117 #endif 118 119 int __init scoop_probe(struct device *dev) 120 { 121 struct scoop_dev *devptr; 122 struct scoop_config *inf; 123 struct platform_device *pdev = to_platform_device(dev); 124 struct resource *mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); 125 126 if (!mem) 127 return -EINVAL; 128 129 devptr = kmalloc(sizeof(struct scoop_dev), GFP_KERNEL); 130 131 if (!devptr) 132 return -ENOMEM; 133 134 memset(devptr, 0, sizeof(struct scoop_dev)); 135 spin_lock_init(&devptr->scoop_lock); 136 137 inf = dev->platform_data; 138 devptr->base = ioremap(mem->start, mem->end - mem->start + 1); 139 140 if (!devptr->base) { 141 kfree(devptr); 142 return -ENOMEM; 143 } 144 145 dev_set_drvdata(dev, devptr); 146 147 printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem->start,(unsigned int)devptr->base); 148 149 SCOOP_REG(devptr->base, SCOOP_MCR) = 0x0140; 150 reset_scoop(dev); 151 SCOOP_REG(devptr->base, SCOOP_GPCR) = inf->io_dir & 0xffff; 152 SCOOP_REG(devptr->base, SCOOP_GPWR) = inf->io_out & 0xffff; 153 154 return 0; 155 } 156 157 static int scoop_remove(struct device *dev) 158 { 159 struct scoop_dev *sdev = dev_get_drvdata(dev); 160 if (sdev) { 161 iounmap(sdev->base); 162 kfree(sdev); 163 dev_set_drvdata(dev, NULL); 164 } 165 return 0; 166 } 167 168 static struct device_driver scoop_driver = { 169 .name = "sharp-scoop", 170 .bus = &platform_bus_type, 171 .probe = scoop_probe, 172 .remove = scoop_remove, 173 .suspend = scoop_suspend, 174 .resume = scoop_resume, 175 }; 176 177 int __init scoop_init(void) 178 { 179 return driver_register(&scoop_driver); 180 } 181 182 subsys_initcall(scoop_init); 183