// SPDX-License-Identifier: GPL-2.0-only /* * linux/drivers/pcmcia/sa1111_generic.c * * We implement the generic parts of a SA1111 PCMCIA driver. This * basically means we handle everything except controlling the * power. Power is machine specific...
*/ #include <linux/module.h> #include <linux/kernel.h> #include <linux/ioport.h> #include <linux/device.h> #include <linux/interrupt.h> #include <linux/init.h> #include <linux/io.h> #include <linux/slab.h>
switch (skt->nr) { case 0:
pccr_skt_mask = PCCR_S0_RST|PCCR_S0_FLT|PCCR_S0_PWAITEN|PCCR_S0_PSE; break;
case 1:
pccr_skt_mask = PCCR_S1_RST|PCCR_S1_FLT|PCCR_S1_PWAITEN|PCCR_S1_PSE; break;
default: return -1;
}
pccr_set_mask = 0;
if (state->Vcc != 0)
pccr_set_mask |= PCCR_S0_PWAITEN|PCCR_S1_PWAITEN; if (state->Vcc == 50)
pccr_set_mask |= PCCR_S0_PSE|PCCR_S1_PSE; if (state->flags & SS_RESET)
pccr_set_mask |= PCCR_S0_RST|PCCR_S1_RST; if (state->flags & SS_OUTPUT_ENA)
pccr_set_mask |= PCCR_S0_FLT|PCCR_S1_FLT;
local_irq_save(flags);
val = readl_relaxed(s->dev->mapbase + PCCR);
val &= ~pccr_skt_mask;
val |= pccr_set_mask & pccr_skt_mask;
writel_relaxed(val, s->dev->mapbase + PCCR);
local_irq_restore(flags);
return 0;
}
int sa1111_pcmcia_add(struct sa1111_dev *dev, struct pcmcia_low_level *ops, int (*add)(struct soc_pcmcia_socket *))
{ struct sa1111_pcmcia_socket *s; struct clk *clk; int i, ret = 0, irqs[NUM_IRQS];
clk = devm_clk_get(&dev->dev, NULL); if (IS_ERR(clk)) return PTR_ERR(clk);
for (i = 0; i < NUM_IRQS; i++) {
irqs[i] = sa1111_get_irq(dev, i); if (irqs[i] <= 0) return irqs[i] ? : -ENXIO;
}
ops->socket_state = sa1111_pcmcia_socket_state;
for (i = 0; i < ops->nr; i++) {
s = kzalloc(sizeof(*s), GFP_KERNEL); if (!s) return -ENOMEM;
ret = add(&s->soc); if (ret == 0) {
s->next = dev_get_drvdata(&dev->dev);
dev_set_drvdata(&dev->dev, s);
} else
kfree(s);
}
return ret;
}
staticint pcmcia_probe(struct sa1111_dev *dev)
{ void __iomem *base; int ret;
ret = sa1111_enable_device(dev); if (ret) return ret;
dev_set_drvdata(&dev->dev, NULL);
if (!request_mem_region(dev->res.start, 512, SA1111_DRIVER_NAME(dev))) {
sa1111_disable_device(dev); return -EBUSY;
}
base = dev->mapbase;
/* * Initialise the suspend state.
*/
writel_relaxed(PCSSR_S0_SLEEP | PCSSR_S1_SLEEP, base + PCSSR);
writel_relaxed(PCCR_S0_FLT | PCCR_S1_FLT, base + PCCR);
ret = -ENODEV; #ifdef CONFIG_SA1100_JORNADA720 if (machine_is_jornada720())
ret = pcmcia_jornada720_init(dev); #endif #ifdef CONFIG_ASSABET_NEPONSET if (machine_is_assabet())
ret = pcmcia_neponset_init(dev); #endif
if (ret) {
release_mem_region(dev->res.start, 512);
sa1111_disable_device(dev);
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.