xref: /linux/arch/arm/mach-sa1100/neponset.c (revision 6ad1b614007c556129989b9f6b020d0d2e058121)
1 /*
2  * linux/arch/arm/mach-sa1100/neponset.c
3  *
4  */
5 #include <linux/kernel.h>
6 #include <linux/init.h>
7 #include <linux/tty.h>
8 #include <linux/ioport.h>
9 #include <linux/serial_core.h>
10 #include <linux/platform_device.h>
11 
12 #include <mach/hardware.h>
13 #include <asm/mach-types.h>
14 #include <asm/irq.h>
15 #include <asm/mach/map.h>
16 #include <asm/mach/irq.h>
17 #include <asm/mach/serial_sa1100.h>
18 #include <mach/assabet.h>
19 #include <mach/neponset.h>
20 #include <asm/hardware/sa1111.h>
21 #include <asm/sizes.h>
22 
23 void neponset_ncr_frob(unsigned int mask, unsigned int val)
24 {
25 	unsigned long flags;
26 
27 	local_irq_save(flags);
28 	NCR_0 = (NCR_0 & ~mask) | val;
29 	local_irq_restore(flags);
30 }
31 
32 /*
33  * Install handler for Neponset IRQ.  Note that we have to loop here
34  * since the ETHERNET and USAR IRQs are level based, and we need to
35  * ensure that the IRQ signal is deasserted before returning.  This
36  * is rather unfortunate.
37  */
38 static void
39 neponset_irq_handler(unsigned int irq, struct irq_desc *desc)
40 {
41 	unsigned int irr;
42 
43 	while (1) {
44 		/*
45 		 * Acknowledge the parent IRQ.
46 		 */
47 		desc->irq_data.chip->irq_ack(&desc->irq_data);
48 
49 		/*
50 		 * Read the interrupt reason register.  Let's have all
51 		 * active IRQ bits high.  Note: there is a typo in the
52 		 * Neponset user's guide for the SA1111 IRR level.
53 		 */
54 		irr = IRR ^ (IRR_ETHERNET | IRR_USAR);
55 
56 		if ((irr & (IRR_ETHERNET | IRR_USAR | IRR_SA1111)) == 0)
57 			break;
58 
59 		/*
60 		 * Since there is no individual mask, we have to
61 		 * mask the parent IRQ.  This is safe, since we'll
62 		 * recheck the register for any pending IRQs.
63 		 */
64 		if (irr & (IRR_ETHERNET | IRR_USAR)) {
65 			desc->irq_data.chip->irq_mask(&desc->irq_data);
66 
67 			/*
68 			 * Ack the interrupt now to prevent re-entering
69 			 * this neponset handler.  Again, this is safe
70 			 * since we'll check the IRR register prior to
71 			 * leaving.
72 			 */
73 			desc->irq_data.chip->irq_ack(&desc->irq_data);
74 
75 			if (irr & IRR_ETHERNET) {
76 				generic_handle_irq(IRQ_NEPONSET_SMC9196);
77 			}
78 
79 			if (irr & IRR_USAR) {
80 				generic_handle_irq(IRQ_NEPONSET_USAR);
81 			}
82 
83 			desc->irq_data.chip->irq_unmask(&desc->irq_data);
84 		}
85 
86 		if (irr & IRR_SA1111) {
87 			generic_handle_irq(IRQ_NEPONSET_SA1111);
88 		}
89 	}
90 }
91 
92 static void neponset_set_mctrl(struct uart_port *port, u_int mctrl)
93 {
94 	u_int mdm_ctl0 = MDM_CTL_0;
95 
96 	if (port->mapbase == _Ser1UTCR0) {
97 		if (mctrl & TIOCM_RTS)
98 			mdm_ctl0 &= ~MDM_CTL0_RTS2;
99 		else
100 			mdm_ctl0 |= MDM_CTL0_RTS2;
101 
102 		if (mctrl & TIOCM_DTR)
103 			mdm_ctl0 &= ~MDM_CTL0_DTR2;
104 		else
105 			mdm_ctl0 |= MDM_CTL0_DTR2;
106 	} else if (port->mapbase == _Ser3UTCR0) {
107 		if (mctrl & TIOCM_RTS)
108 			mdm_ctl0 &= ~MDM_CTL0_RTS1;
109 		else
110 			mdm_ctl0 |= MDM_CTL0_RTS1;
111 
112 		if (mctrl & TIOCM_DTR)
113 			mdm_ctl0 &= ~MDM_CTL0_DTR1;
114 		else
115 			mdm_ctl0 |= MDM_CTL0_DTR1;
116 	}
117 
118 	MDM_CTL_0 = mdm_ctl0;
119 }
120 
121 static u_int neponset_get_mctrl(struct uart_port *port)
122 {
123 	u_int ret = TIOCM_CD | TIOCM_CTS | TIOCM_DSR;
124 	u_int mdm_ctl1 = MDM_CTL_1;
125 
126 	if (port->mapbase == _Ser1UTCR0) {
127 		if (mdm_ctl1 & MDM_CTL1_DCD2)
128 			ret &= ~TIOCM_CD;
129 		if (mdm_ctl1 & MDM_CTL1_CTS2)
130 			ret &= ~TIOCM_CTS;
131 		if (mdm_ctl1 & MDM_CTL1_DSR2)
132 			ret &= ~TIOCM_DSR;
133 	} else if (port->mapbase == _Ser3UTCR0) {
134 		if (mdm_ctl1 & MDM_CTL1_DCD1)
135 			ret &= ~TIOCM_CD;
136 		if (mdm_ctl1 & MDM_CTL1_CTS1)
137 			ret &= ~TIOCM_CTS;
138 		if (mdm_ctl1 & MDM_CTL1_DSR1)
139 			ret &= ~TIOCM_DSR;
140 	}
141 
142 	return ret;
143 }
144 
145 static struct sa1100_port_fns neponset_port_fns __devinitdata = {
146 	.set_mctrl	= neponset_set_mctrl,
147 	.get_mctrl	= neponset_get_mctrl,
148 };
149 
150 /*
151  * Yes, we really do not have any kind of masking or unmasking
152  */
153 static void nochip_noop(struct irq_data *irq)
154 {
155 }
156 
157 static struct irq_chip nochip = {
158 	.name = "neponset",
159 	.irq_ack = nochip_noop,
160 	.irq_mask = nochip_noop,
161 	.irq_unmask = nochip_noop,
162 };
163 
164 static int __devinit neponset_probe(struct platform_device *dev)
165 {
166 	sa1100_register_uart_fns(&neponset_port_fns);
167 
168 	/*
169 	 * Install handler for GPIO25.
170 	 */
171 	irq_set_irq_type(IRQ_GPIO25, IRQ_TYPE_EDGE_RISING);
172 	irq_set_chained_handler(IRQ_GPIO25, neponset_irq_handler);
173 
174 	/*
175 	 * We would set IRQ_GPIO25 to be a wake-up IRQ, but
176 	 * unfortunately something on the Neponset activates
177 	 * this IRQ on sleep (ethernet?)
178 	 */
179 #if 0
180 	enable_irq_wake(IRQ_GPIO25);
181 #endif
182 
183 	/*
184 	 * Setup other Neponset IRQs.  SA1111 will be done by the
185 	 * generic SA1111 code.
186 	 */
187 	irq_set_chip_and_handler(IRQ_NEPONSET_SMC9196, &nochip,
188 		handle_simple_irq);
189 	set_irq_flags(IRQ_NEPONSET_SMC9196, IRQF_VALID | IRQF_PROBE);
190 	irq_set_chip_and_handler(IRQ_NEPONSET_USAR, &nochip,
191 		handle_simple_irq);
192 	set_irq_flags(IRQ_NEPONSET_USAR, IRQF_VALID | IRQF_PROBE);
193 	irq_set_chip(IRQ_NEPONSET_SA1111, &nochip);
194 
195 	/*
196 	 * Disable GPIO 0/1 drivers so the buttons work on the module.
197 	 */
198 	NCR_0 = NCR_GP01_OFF;
199 
200 	return 0;
201 }
202 
203 #ifdef CONFIG_PM
204 
205 /*
206  * LDM power management.
207  */
208 static unsigned int neponset_saved_state;
209 
210 static int neponset_suspend(struct platform_device *dev, pm_message_t state)
211 {
212 	/*
213 	 * Save state.
214 	 */
215 	neponset_saved_state = NCR_0;
216 
217 	return 0;
218 }
219 
220 static int neponset_resume(struct platform_device *dev)
221 {
222 	NCR_0 = neponset_saved_state;
223 
224 	return 0;
225 }
226 
227 #else
228 #define neponset_suspend NULL
229 #define neponset_resume  NULL
230 #endif
231 
232 static struct platform_driver neponset_device_driver = {
233 	.probe		= neponset_probe,
234 	.suspend	= neponset_suspend,
235 	.resume		= neponset_resume,
236 	.driver		= {
237 		.name	= "neponset",
238 	},
239 };
240 
241 static struct resource neponset_resources[] = {
242 	[0] = DEFINE_RES_MEM(0x10000000, 0x08000000),
243 };
244 
245 static struct platform_device neponset_device = {
246 	.name		= "neponset",
247 	.id		= 0,
248 	.num_resources	= ARRAY_SIZE(neponset_resources),
249 	.resource	= neponset_resources,
250 };
251 
252 static struct resource sa1111_resources[] = {
253 	[0] = DEFINE_RES_MEM(0x40000000, SZ_8K),
254 	[1] = DEFINE_RES_IRQ(IRQ_NEPONSET_SA1111),
255 };
256 
257 static struct sa1111_platform_data sa1111_info = {
258 	.irq_base	= IRQ_BOARD_END,
259 };
260 
261 static u64 sa1111_dmamask = 0xffffffffUL;
262 
263 static struct platform_device sa1111_device = {
264 	.name		= "sa1111",
265 	.id		= 0,
266 	.dev		= {
267 		.dma_mask = &sa1111_dmamask,
268 		.coherent_dma_mask = 0xffffffff,
269 		.platform_data = &sa1111_info,
270 	},
271 	.num_resources	= ARRAY_SIZE(sa1111_resources),
272 	.resource	= sa1111_resources,
273 };
274 
275 static struct resource smc91x_resources[] = {
276 	[0] = DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS, 0x02000000, "smc91x-regs"),
277 	[1] = DEFINE_RES_IRQ(IRQ_NEPONSET_SMC9196),
278 	[2] = DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS + 0x02000000,
279 			0x02000000, "smc91x-attrib"),
280 };
281 
282 static struct platform_device smc91x_device = {
283 	.name		= "smc91x",
284 	.id		= 0,
285 	.num_resources	= ARRAY_SIZE(smc91x_resources),
286 	.resource	= smc91x_resources,
287 };
288 
289 static struct platform_device *devices[] __initdata = {
290 	&neponset_device,
291 	&sa1111_device,
292 	&smc91x_device,
293 };
294 
295 extern void sa1110_mb_disable(void);
296 
297 static int __init neponset_init(void)
298 {
299 	platform_driver_register(&neponset_device_driver);
300 
301 	/*
302 	 * The Neponset is only present on the Assabet machine type.
303 	 */
304 	if (!machine_is_assabet())
305 		return -ENODEV;
306 
307 	/*
308 	 * Ensure that the memory bus request/grant signals are setup,
309 	 * and the grant is held in its inactive state, whether or not
310 	 * we actually have a Neponset attached.
311 	 */
312 	sa1110_mb_disable();
313 
314 	if (!machine_has_neponset()) {
315 		printk(KERN_DEBUG "Neponset expansion board not present\n");
316 		return -ENODEV;
317 	}
318 
319 	if (WHOAMI != 0x11) {
320 		printk(KERN_WARNING "Neponset board detected, but "
321 			"wrong ID: %02x\n", WHOAMI);
322 		return -ENODEV;
323 	}
324 
325 	return platform_add_devices(devices, ARRAY_SIZE(devices));
326 }
327 
328 subsys_initcall(neponset_init);
329 
330 static struct map_desc neponset_io_desc[] __initdata = {
331 	{	/* System Registers */
332 		.virtual	=  0xf3000000,
333 		.pfn		= __phys_to_pfn(0x10000000),
334 		.length		= SZ_1M,
335 		.type		= MT_DEVICE
336 	}, {	/* SA-1111 */
337 		.virtual	=  0xf4000000,
338 		.pfn		= __phys_to_pfn(0x40000000),
339 		.length		= SZ_1M,
340 		.type		= MT_DEVICE
341 	}
342 };
343 
344 void __init neponset_map_io(void)
345 {
346 	iotable_init(neponset_io_desc, ARRAY_SIZE(neponset_io_desc));
347 }
348