2 * Support code for the SCOOP interface found on various Sharp PDAs
4 * Copyright (c) 2004 Richard Purdie
6 * Based on code written by Sharp/Lineo for 2.4 kernels
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.
14 #include <linux/device.h>
15 #include <linux/string.h>
16 #include <linux/platform_device.h>
18 #include <asm/hardware/scoop.h>
20 #define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
22 /* PCMCIA to Scoop linkage structures for pxa2xx_sharpsl.c
23 There is no easy way to link multiple scoop devices into one
24 single entity for the pxa2xx_pcmcia device */
26 struct scoop_pcmcia_dev
*scoop_devs
;
30 spinlock_t scoop_lock
;
31 unsigned short suspend_clr
;
32 unsigned short suspend_set
;
36 void reset_scoop(struct device
*dev
)
38 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
40 SCOOP_REG(sdev
->base
,SCOOP_MCR
) = 0x0100; // 00
41 SCOOP_REG(sdev
->base
,SCOOP_CDR
) = 0x0000; // 04
42 SCOOP_REG(sdev
->base
,SCOOP_CPR
) = 0x0000; // 0C
43 SCOOP_REG(sdev
->base
,SCOOP_CCR
) = 0x0000; // 10
44 SCOOP_REG(sdev
->base
,SCOOP_IMR
) = 0x0000; // 18
45 SCOOP_REG(sdev
->base
,SCOOP_IRM
) = 0x00FF; // 14
46 SCOOP_REG(sdev
->base
,SCOOP_ISR
) = 0x0000; // 1C
47 SCOOP_REG(sdev
->base
,SCOOP_IRM
) = 0x0000;
50 unsigned short set_scoop_gpio(struct device
*dev
, unsigned short bit
)
52 unsigned short gpio_bit
;
54 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
56 spin_lock_irqsave(&sdev
->scoop_lock
, flag
);
57 gpio_bit
= SCOOP_REG(sdev
->base
, SCOOP_GPWR
) | bit
;
58 SCOOP_REG(sdev
->base
, SCOOP_GPWR
) = gpio_bit
;
59 spin_unlock_irqrestore(&sdev
->scoop_lock
, flag
);
64 unsigned short reset_scoop_gpio(struct device
*dev
, unsigned short bit
)
66 unsigned short gpio_bit
;
68 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
70 spin_lock_irqsave(&sdev
->scoop_lock
, flag
);
71 gpio_bit
= SCOOP_REG(sdev
->base
, SCOOP_GPWR
) & ~bit
;
72 SCOOP_REG(sdev
->base
,SCOOP_GPWR
) = gpio_bit
;
73 spin_unlock_irqrestore(&sdev
->scoop_lock
, flag
);
78 EXPORT_SYMBOL(set_scoop_gpio
);
79 EXPORT_SYMBOL(reset_scoop_gpio
);
81 unsigned short read_scoop_reg(struct device
*dev
, unsigned short reg
)
83 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
84 return SCOOP_REG(sdev
->base
,reg
);
87 void write_scoop_reg(struct device
*dev
, unsigned short reg
, unsigned short data
)
89 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
90 SCOOP_REG(sdev
->base
,reg
)=data
;
93 EXPORT_SYMBOL(reset_scoop
);
94 EXPORT_SYMBOL(read_scoop_reg
);
95 EXPORT_SYMBOL(write_scoop_reg
);
97 static void check_scoop_reg(struct scoop_dev
*sdev
)
101 mcr
= SCOOP_REG(sdev
->base
, SCOOP_MCR
);
102 if ((mcr
& 0x100) == 0)
103 SCOOP_REG(sdev
->base
, SCOOP_MCR
) = 0x0101;
107 static int scoop_suspend(struct device
*dev
, pm_message_t state
)
109 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
111 check_scoop_reg(sdev
);
112 sdev
->scoop_gpwr
= SCOOP_REG(sdev
->base
, SCOOP_GPWR
);
113 SCOOP_REG(sdev
->base
, SCOOP_GPWR
) = (sdev
->scoop_gpwr
& ~sdev
->suspend_clr
) | sdev
->suspend_set
;
118 static int scoop_resume(struct device
*dev
)
120 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
122 check_scoop_reg(sdev
);
123 SCOOP_REG(sdev
->base
,SCOOP_GPWR
) = sdev
->scoop_gpwr
;
128 #define scoop_suspend NULL
129 #define scoop_resume NULL
132 int __init
scoop_probe(struct device
*dev
)
134 struct scoop_dev
*devptr
;
135 struct scoop_config
*inf
;
136 struct platform_device
*pdev
= to_platform_device(dev
);
137 struct resource
*mem
= platform_get_resource(pdev
, IORESOURCE_MEM
, 0);
142 devptr
= kmalloc(sizeof(struct scoop_dev
), GFP_KERNEL
);
147 memset(devptr
, 0, sizeof(struct scoop_dev
));
148 spin_lock_init(&devptr
->scoop_lock
);
150 inf
= dev
->platform_data
;
151 devptr
->base
= ioremap(mem
->start
, mem
->end
- mem
->start
+ 1);
158 dev_set_drvdata(dev
, devptr
);
160 printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem
->start
,(unsigned int)devptr
->base
);
162 SCOOP_REG(devptr
->base
, SCOOP_MCR
) = 0x0140;
164 SCOOP_REG(devptr
->base
, SCOOP_GPCR
) = inf
->io_dir
& 0xffff;
165 SCOOP_REG(devptr
->base
, SCOOP_GPWR
) = inf
->io_out
& 0xffff;
167 devptr
->suspend_clr
= inf
->suspend_clr
;
168 devptr
->suspend_set
= inf
->suspend_set
;
173 static int scoop_remove(struct device
*dev
)
175 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
179 dev_set_drvdata(dev
, NULL
);
184 static struct device_driver scoop_driver
= {
185 .name
= "sharp-scoop",
186 .bus
= &platform_bus_type
,
187 .probe
= scoop_probe
,
188 .remove
= scoop_remove
,
189 .suspend
= scoop_suspend
,
190 .resume
= scoop_resume
,
193 int __init
scoop_init(void)
195 return driver_register(&scoop_driver
);
198 subsys_initcall(scoop_init
);