1 // SPDX-License-Identifier: GPL-2.0
3 * linux/arch/arm/mach-sa1100/neponset.c
6 #include <linux/gpio/driver.h>
7 #include <linux/gpio/gpio-reg.h>
8 #include <linux/gpio/machine.h>
9 #include <linux/init.h>
10 #include <linux/ioport.h>
11 #include <linux/irq.h>
12 #include <linux/kernel.h>
13 #include <linux/module.h>
14 #include <linux/platform_device.h>
16 #include <linux/serial_core.h>
17 #include <linux/slab.h>
18 #include <linux/smc91x.h>
20 #include <asm/mach-types.h>
21 #include <asm/mach/map.h>
22 #include <asm/hardware/sa1111.h>
23 #include <linux/sizes.h>
25 #include <mach/hardware.h>
26 #include <mach/assabet.h>
27 #include <mach/neponset.h>
28 #include <mach/irqs.h>
30 #define NEP_IRQ_SMC91X 0
31 #define NEP_IRQ_USAR 1
32 #define NEP_IRQ_SA1111 2
42 #define MDM_CTL_0 0xb0
43 #define MDM_CTL_1 0xb4
46 #define IRR_ETHERNET (1 << 0)
47 #define IRR_USAR (1 << 1)
48 #define IRR_SA1111 (1 << 2)
51 #define MDM_CTL0_NGPIO 4
52 #define MDM_CTL1_NGPIO 6
55 extern void sa1110_mb_disable(void);
57 #define to_neponset_gpio_chip(x) container_of(x, struct neponset_gpio_chip, gc)
59 static const char *neponset_ncr_names
[] = {
60 "gp01_off", "tp_power", "ms_power", "enet_osc",
61 "spi_kb_wk_up", "a0vpp", "a1vpp"
64 static const char *neponset_mdmctl0_names
[] = {
65 "rts3", "dtr3", "rts1", "dtr1",
68 static const char *neponset_mdmctl1_names
[] = {
69 "cts3", "dsr3", "dcd3", "cts1", "dsr1", "dcd1"
72 static const char *neponset_aud_names
[] = {
73 "sel_1341", "mute_1341",
76 struct neponset_drvdata
{
78 struct platform_device
*sa1111
;
79 struct platform_device
*smc91x
;
81 struct gpio_chip
*gpio
[4];
84 static struct gpiod_lookup_table neponset_uart1_gpio_table
= {
85 .dev_id
= "sa11x0-uart.1",
87 GPIO_LOOKUP("neponset-mdm-ctl0", 2, "rts", GPIO_ACTIVE_LOW
),
88 GPIO_LOOKUP("neponset-mdm-ctl0", 3, "dtr", GPIO_ACTIVE_LOW
),
89 GPIO_LOOKUP("neponset-mdm-ctl1", 3, "cts", GPIO_ACTIVE_LOW
),
90 GPIO_LOOKUP("neponset-mdm-ctl1", 4, "dsr", GPIO_ACTIVE_LOW
),
91 GPIO_LOOKUP("neponset-mdm-ctl1", 5, "dcd", GPIO_ACTIVE_LOW
),
96 static struct gpiod_lookup_table neponset_uart3_gpio_table
= {
97 .dev_id
= "sa11x0-uart.3",
99 GPIO_LOOKUP("neponset-mdm-ctl0", 0, "rts", GPIO_ACTIVE_LOW
),
100 GPIO_LOOKUP("neponset-mdm-ctl0", 1, "dtr", GPIO_ACTIVE_LOW
),
101 GPIO_LOOKUP("neponset-mdm-ctl1", 0, "cts", GPIO_ACTIVE_LOW
),
102 GPIO_LOOKUP("neponset-mdm-ctl1", 1, "dsr", GPIO_ACTIVE_LOW
),
103 GPIO_LOOKUP("neponset-mdm-ctl1", 2, "dcd", GPIO_ACTIVE_LOW
),
108 static struct gpiod_lookup_table neponset_pcmcia_table
= {
111 GPIO_LOOKUP("sa1111", 1, "a0vcc", GPIO_ACTIVE_HIGH
),
112 GPIO_LOOKUP("sa1111", 0, "a1vcc", GPIO_ACTIVE_HIGH
),
113 GPIO_LOOKUP("neponset-ncr", 5, "a0vpp", GPIO_ACTIVE_HIGH
),
114 GPIO_LOOKUP("neponset-ncr", 6, "a1vpp", GPIO_ACTIVE_HIGH
),
115 GPIO_LOOKUP("sa1111", 2, "b0vcc", GPIO_ACTIVE_HIGH
),
116 GPIO_LOOKUP("sa1111", 3, "b1vcc", GPIO_ACTIVE_HIGH
),
121 static struct neponset_drvdata
*nep
;
123 void neponset_ncr_frob(unsigned int mask
, unsigned int val
)
125 struct neponset_drvdata
*n
= nep
;
126 unsigned long m
= mask
, v
= val
;
129 n
->gpio
[0]->set_multiple(n
->gpio
[0], &m
, &v
);
131 WARN(1, "nep unset\n");
133 EXPORT_SYMBOL(neponset_ncr_frob
);
136 * Install handler for Neponset IRQ. Note that we have to loop here
137 * since the ETHERNET and USAR IRQs are level based, and we need to
138 * ensure that the IRQ signal is deasserted before returning. This
139 * is rather unfortunate.
141 static void neponset_irq_handler(struct irq_desc
*desc
)
143 struct neponset_drvdata
*d
= irq_desc_get_handler_data(desc
);
148 * Acknowledge the parent IRQ.
150 desc
->irq_data
.chip
->irq_ack(&desc
->irq_data
);
153 * Read the interrupt reason register. Let's have all
154 * active IRQ bits high. Note: there is a typo in the
155 * Neponset user's guide for the SA1111 IRR level.
157 irr
= readb_relaxed(d
->base
+ IRR
);
158 irr
^= IRR_ETHERNET
| IRR_USAR
;
160 if ((irr
& (IRR_ETHERNET
| IRR_USAR
| IRR_SA1111
)) == 0)
164 * Since there is no individual mask, we have to
165 * mask the parent IRQ. This is safe, since we'll
166 * recheck the register for any pending IRQs.
168 if (irr
& (IRR_ETHERNET
| IRR_USAR
)) {
169 desc
->irq_data
.chip
->irq_mask(&desc
->irq_data
);
172 * Ack the interrupt now to prevent re-entering
173 * this neponset handler. Again, this is safe
174 * since we'll check the IRR register prior to
177 desc
->irq_data
.chip
->irq_ack(&desc
->irq_data
);
179 if (irr
& IRR_ETHERNET
)
180 generic_handle_irq(d
->irq_base
+ NEP_IRQ_SMC91X
);
183 generic_handle_irq(d
->irq_base
+ NEP_IRQ_USAR
);
185 desc
->irq_data
.chip
->irq_unmask(&desc
->irq_data
);
188 if (irr
& IRR_SA1111
)
189 generic_handle_irq(d
->irq_base
+ NEP_IRQ_SA1111
);
193 /* Yes, we really do not have any kind of masking or unmasking */
194 static void nochip_noop(struct irq_data
*irq
)
198 static struct irq_chip nochip
= {
200 .irq_ack
= nochip_noop
,
201 .irq_mask
= nochip_noop
,
202 .irq_unmask
= nochip_noop
,
205 static int neponset_init_gpio(struct gpio_chip
**gcp
,
206 struct device
*dev
, const char *label
, void __iomem
*reg
,
207 unsigned num
, bool in
, const char *const * names
)
209 struct gpio_chip
*gc
;
211 gc
= gpio_reg_init(dev
, reg
, -1, num
, label
, in
? 0xffffffff : 0,
212 readl_relaxed(reg
), names
, NULL
, NULL
);
221 static struct sa1111_platform_data sa1111_info
= {
222 .disable_devs
= SA1111_DEVID_PS2_MSE
,
225 static int neponset_probe(struct platform_device
*dev
)
227 struct neponset_drvdata
*d
;
228 struct resource
*nep_res
, *sa1111_res
, *smc91x_res
;
229 struct resource sa1111_resources
[] = {
230 DEFINE_RES_MEM(0x40000000, SZ_8K
),
231 { .flags
= IORESOURCE_IRQ
},
233 struct platform_device_info sa1111_devinfo
= {
237 .res
= sa1111_resources
,
238 .num_res
= ARRAY_SIZE(sa1111_resources
),
239 .data
= &sa1111_info
,
240 .size_data
= sizeof(sa1111_info
),
241 .dma_mask
= 0xffffffffUL
,
243 struct resource smc91x_resources
[] = {
244 DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS
,
245 0x02000000, "smc91x-regs"),
246 DEFINE_RES_MEM_NAMED(SA1100_CS3_PHYS
+ 0x02000000,
247 0x02000000, "smc91x-attrib"),
248 { .flags
= IORESOURCE_IRQ
},
250 struct smc91x_platdata smc91x_platdata
= {
251 .flags
= SMC91X_USE_8BIT
| SMC91X_IO_SHIFT_2
| SMC91X_NOWAIT
,
253 struct platform_device_info smc91x_devinfo
= {
257 .res
= smc91x_resources
,
258 .num_res
= ARRAY_SIZE(smc91x_resources
),
259 .data
= &smc91x_platdata
,
260 .size_data
= sizeof(smc91x_platdata
),
267 irq
= ret
= platform_get_irq(dev
, 0);
271 nep_res
= platform_get_resource(dev
, IORESOURCE_MEM
, 0);
272 smc91x_res
= platform_get_resource(dev
, IORESOURCE_MEM
, 1);
273 sa1111_res
= platform_get_resource(dev
, IORESOURCE_MEM
, 2);
274 if (!nep_res
|| !smc91x_res
|| !sa1111_res
) {
279 d
= kzalloc(sizeof(*d
), GFP_KERNEL
);
285 d
->base
= ioremap(nep_res
->start
, SZ_4K
);
291 if (readb_relaxed(d
->base
+ WHOAMI
) != 0x11) {
292 dev_warn(&dev
->dev
, "Neponset board detected, but wrong ID: %02x\n",
293 readb_relaxed(d
->base
+ WHOAMI
));
298 ret
= irq_alloc_descs(-1, IRQ_BOARD_START
, NEP_IRQ_NR
, -1);
300 dev_err(&dev
->dev
, "unable to allocate %u irqs: %d\n",
309 irq_set_chip_and_handler(d
->irq_base
+ NEP_IRQ_SMC91X
, &nochip
,
311 irq_clear_status_flags(d
->irq_base
+ NEP_IRQ_SMC91X
, IRQ_NOREQUEST
| IRQ_NOPROBE
);
312 irq_set_chip_and_handler(d
->irq_base
+ NEP_IRQ_USAR
, &nochip
,
314 irq_clear_status_flags(d
->irq_base
+ NEP_IRQ_USAR
, IRQ_NOREQUEST
| IRQ_NOPROBE
);
315 irq_set_chip(d
->irq_base
+ NEP_IRQ_SA1111
, &nochip
);
317 irq_set_irq_type(irq
, IRQ_TYPE_EDGE_RISING
);
318 irq_set_chained_handler_and_data(irq
, neponset_irq_handler
, d
);
320 /* Disable GPIO 0/1 drivers so the buttons work on the Assabet */
321 writeb_relaxed(NCR_GP01_OFF
, d
->base
+ NCR_0
);
323 neponset_init_gpio(&d
->gpio
[0], &dev
->dev
, "neponset-ncr",
324 d
->base
+ NCR_0
, NCR_NGPIO
, false,
326 neponset_init_gpio(&d
->gpio
[1], &dev
->dev
, "neponset-mdm-ctl0",
327 d
->base
+ MDM_CTL_0
, MDM_CTL0_NGPIO
, false,
328 neponset_mdmctl0_names
);
329 neponset_init_gpio(&d
->gpio
[2], &dev
->dev
, "neponset-mdm-ctl1",
330 d
->base
+ MDM_CTL_1
, MDM_CTL1_NGPIO
, true,
331 neponset_mdmctl1_names
);
332 neponset_init_gpio(&d
->gpio
[3], &dev
->dev
, "neponset-aud-ctl",
333 d
->base
+ AUD_CTL
, AUD_NGPIO
, false,
336 gpiod_add_lookup_table(&neponset_uart1_gpio_table
);
337 gpiod_add_lookup_table(&neponset_uart3_gpio_table
);
338 gpiod_add_lookup_table(&neponset_pcmcia_table
);
341 * We would set IRQ_GPIO25 to be a wake-up IRQ, but unfortunately
342 * something on the Neponset activates this IRQ on sleep (eth?)
345 enable_irq_wake(irq
);
348 dev_info(&dev
->dev
, "Neponset daughter board, providing IRQ%u-%u\n",
349 d
->irq_base
, d
->irq_base
+ NEP_IRQ_NR
- 1);
352 /* Ensure that the memory bus request/grant signals are setup */
355 sa1111_resources
[0].parent
= sa1111_res
;
356 sa1111_resources
[1].start
= d
->irq_base
+ NEP_IRQ_SA1111
;
357 sa1111_resources
[1].end
= d
->irq_base
+ NEP_IRQ_SA1111
;
358 d
->sa1111
= platform_device_register_full(&sa1111_devinfo
);
360 smc91x_resources
[0].parent
= smc91x_res
;
361 smc91x_resources
[1].parent
= smc91x_res
;
362 smc91x_resources
[2].start
= d
->irq_base
+ NEP_IRQ_SMC91X
;
363 smc91x_resources
[2].end
= d
->irq_base
+ NEP_IRQ_SMC91X
;
364 d
->smc91x
= platform_device_register_full(&smc91x_devinfo
);
366 platform_set_drvdata(dev
, d
);
379 static int neponset_remove(struct platform_device
*dev
)
381 struct neponset_drvdata
*d
= platform_get_drvdata(dev
);
382 int irq
= platform_get_irq(dev
, 0);
384 if (!IS_ERR(d
->sa1111
))
385 platform_device_unregister(d
->sa1111
);
386 if (!IS_ERR(d
->smc91x
))
387 platform_device_unregister(d
->smc91x
);
389 gpiod_remove_lookup_table(&neponset_pcmcia_table
);
390 gpiod_remove_lookup_table(&neponset_uart3_gpio_table
);
391 gpiod_remove_lookup_table(&neponset_uart1_gpio_table
);
393 irq_set_chained_handler(irq
, NULL
);
394 irq_free_descs(d
->irq_base
, NEP_IRQ_NR
);
402 #ifdef CONFIG_PM_SLEEP
403 static int neponset_resume(struct device
*dev
)
405 struct neponset_drvdata
*d
= dev_get_drvdata(dev
);
408 for (i
= 0; i
< ARRAY_SIZE(d
->gpio
); i
++) {
409 ret
= gpio_reg_resume(d
->gpio
[i
]);
417 static const struct dev_pm_ops neponset_pm_ops
= {
418 .resume_noirq
= neponset_resume
,
419 .restore_noirq
= neponset_resume
,
421 #define PM_OPS &neponset_pm_ops
426 static struct platform_driver neponset_device_driver
= {
427 .probe
= neponset_probe
,
428 .remove
= neponset_remove
,
435 static int __init
neponset_init(void)
437 return platform_driver_register(&neponset_device_driver
);
440 subsys_initcall(neponset_init
);