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>
16 #include <asm/hardware/scoop.h>
18 #define SCOOP_REG(d,adr) (*(volatile unsigned short*)(d +(adr)))
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 */
24 struct scoop_pcmcia_dev
*scoop_devs
;
28 spinlock_t scoop_lock
;
32 void reset_scoop(struct device
*dev
)
34 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
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;
46 unsigned short set_scoop_gpio(struct device
*dev
, unsigned short bit
)
48 unsigned short gpio_bit
;
50 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
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
);
60 unsigned short reset_scoop_gpio(struct device
*dev
, unsigned short bit
)
62 unsigned short gpio_bit
;
64 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
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
);
74 EXPORT_SYMBOL(set_scoop_gpio
);
75 EXPORT_SYMBOL(reset_scoop_gpio
);
77 unsigned short read_scoop_reg(struct device
*dev
, unsigned short reg
)
79 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
80 return SCOOP_REG(sdev
->base
,reg
);
83 void write_scoop_reg(struct device
*dev
, unsigned short reg
, unsigned short data
)
85 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
86 SCOOP_REG(sdev
->base
,reg
)=data
;
89 EXPORT_SYMBOL(reset_scoop
);
90 EXPORT_SYMBOL(read_scoop_reg
);
91 EXPORT_SYMBOL(write_scoop_reg
);
94 static int scoop_suspend(struct device
*dev
, pm_message_t state
, uint32_t level
)
96 if (level
== SUSPEND_POWER_DOWN
) {
97 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
99 sdev
->scoop_gpwr
= SCOOP_REG(sdev
->base
,SCOOP_GPWR
);
100 SCOOP_REG(sdev
->base
,SCOOP_GPWR
) = 0;
105 static int scoop_resume(struct device
*dev
, uint32_t level
)
107 if (level
== RESUME_POWER_ON
) {
108 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
110 SCOOP_REG(sdev
->base
,SCOOP_GPWR
) = sdev
->scoop_gpwr
;
115 #define scoop_suspend NULL
116 #define scoop_resume NULL
119 int __init
scoop_probe(struct device
*dev
)
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);
129 devptr
= kmalloc(sizeof(struct scoop_dev
), GFP_KERNEL
);
134 memset(devptr
, 0, sizeof(struct scoop_dev
));
135 spin_lock_init(&devptr
->scoop_lock
);
137 inf
= dev
->platform_data
;
138 devptr
->base
= ioremap(mem
->start
, mem
->end
- mem
->start
+ 1);
145 dev_set_drvdata(dev
, devptr
);
147 printk("Sharp Scoop Device found at 0x%08x -> 0x%08x\n",(unsigned int)mem
->start
,(unsigned int)devptr
->base
);
149 SCOOP_REG(devptr
->base
, SCOOP_MCR
) = 0x0140;
151 SCOOP_REG(devptr
->base
, SCOOP_GPCR
) = inf
->io_dir
& 0xffff;
152 SCOOP_REG(devptr
->base
, SCOOP_GPWR
) = inf
->io_out
& 0xffff;
157 static int scoop_remove(struct device
*dev
)
159 struct scoop_dev
*sdev
= dev_get_drvdata(dev
);
163 dev_set_drvdata(dev
, NULL
);
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
,
177 int __init
scoop_init(void)
179 return driver_register(&scoop_driver
);
182 subsys_initcall(scoop_init
);