static int exynos5422DigitalWrite(int i, enum digital_value_t value) { struct layout_t *pin = NULL; unsigned long addr = 0; uint32_t val = 0; pin = &exynos5422->layout[exynos5422->map[i]]; if(exynos5422->map == NULL) { wiringXLog(LOG_ERR, "The %s %s has not yet been mapped", exynos5422->brand, exynos5422->chip); return -1; } if(exynos5422->fd <= 0 || exynos5422->gpio == NULL) { wiringXLog(LOG_ERR, "The %s %s has not yet been setup by wiringX", exynos5422->brand, exynos5422->chip); return -1; } if(pin->mode != PINMODE_OUTPUT) { wiringXLog(LOG_ERR, "The %s %s GPIO %d is not set to output mode", exynos5422->brand, exynos5422->chip, i); return -1; } addr = (unsigned long)(exynos5422->gpio[pin->addr] + exynos5422->base_offs[pin->addr] + pin->dat.offset); val = soc_readl(addr); if(value == HIGH) { soc_writel(addr, val | (1 << pin->dat.bit)); } else { soc_writel(addr, val & ~(1 << pin->dat.bit)); } return 0; }
static int broadcom2836DigitalWrite(int i, enum digital_value_t value) { struct layout_t *pin = NULL; unsigned long addr = 0; pin = &broadcom2836->layout[broadcom2836->map[i]]; if(broadcom2836->map == NULL) { wiringXLog(LOG_ERR, "The %s %s has not yet been mapped", broadcom2836->brand, broadcom2836->chip); return -1; } if(broadcom2836->fd <= 0 || broadcom2836->gpio == NULL) { wiringXLog(LOG_ERR, "The %s %s has not yet been setup by wiringX", broadcom2836->brand, broadcom2836->chip); return -1; } if(pin->mode != PINMODE_OUTPUT) { wiringXLog(LOG_ERR, "The %s %s GPIO %d is not set to output mode", broadcom2836->brand, broadcom2836->chip, i); return -1; } if(value == HIGH) { addr = (unsigned long)(broadcom2836->gpio[pin->addr] + broadcom2836->base_offs[pin->addr] + pin->set.offset); soc_writel(addr, (1 << pin->set.bit)); } else { addr = (unsigned long)(broadcom2836->gpio[pin->addr] + broadcom2836->base_offs[pin->addr] + pin->clear.offset); soc_writel(addr, (1 << pin->clear.bit)); } return 0; }
static int exynos5422PinMode(int i, enum pinmode_t mode) { struct layout_t *pin = NULL; unsigned long addr = 0; uint32_t val = 0; if(exynos5422->map == NULL) { wiringXLog(LOG_ERR, "The %s %s has not yet been mapped", exynos5422->brand, exynos5422->chip); return -1; } if(exynos5422->fd <= 0 || exynos5422->gpio == NULL) { wiringXLog(LOG_ERR, "The %s %s has not yet been setup by wiringX", exynos5422->brand, exynos5422->chip); return -1; } pin = &exynos5422->layout[exynos5422->map[i]]; addr = (unsigned long)(exynos5422->gpio[pin->addr] + exynos5422->base_offs[pin->addr] + pin->con.offset); pin->mode = mode; val = soc_readl(addr); if(mode == PINMODE_OUTPUT) { val &= ~(0xF << pin->con.bit); val |= (0x1 << pin->con.bit); } else if(mode == PINMODE_INPUT) { val &= ~(0xF << pin->con.bit); } soc_writel(addr, val); return 0; }
static int broadcom2836PinMode(int i, enum pinmode_t mode) { struct layout_t *pin = NULL; unsigned long addr = 0; uint32_t val = 0; if(broadcom2836->map == NULL) { wiringXLog(LOG_ERR, "The %s %s has not yet been mapped", broadcom2836->brand, broadcom2836->chip); return -1; } if(broadcom2836->fd <= 0 || broadcom2836->gpio == NULL) { wiringXLog(LOG_ERR, "The %s %s has not yet been setup by wiringX", broadcom2836->brand, broadcom2836->chip); return -1; } pin = &broadcom2836->layout[broadcom2836->map[i]]; addr = (unsigned long)(broadcom2836->gpio[pin->addr] + broadcom2836->base_offs[pin->addr] + pin->select.offset); pin->mode = mode; val = soc_readl(addr); if(mode == PINMODE_OUTPUT) { val |= (1 << pin->select.bit); } else if(mode == PINMODE_INPUT) { val &= ~(1 << pin->select.bit); } val &= ~(1 << (pin->select.bit+1)); val &= ~(1 << (pin->select.bit+2)); soc_writel(addr, val); return 0; }
static void unmask_megamod(struct irq_data *data) { struct megamod_pic *pic = irq_data_get_irq_chip_data(data); irq_hw_number_t src = irqd_to_hwirq(data); u32 __iomem *evtmask = &pic->regs->evtmask[src / 32]; raw_spin_lock(&pic->lock); soc_writel(soc_readl(evtmask) & ~(1 << (src & 31)), evtmask); raw_spin_unlock(&pic->lock); }
static int get_exception(void) { int i, bit; u32 mask; for (i = 0; i < NR_COMBINERS; i++) { mask = soc_readl(&mm_pic->regs->mexpflag[i]); if (mask) { bit = __ffs(mask); soc_writel(1 << bit, &mm_pic->regs->evtclr[i]); return (i * 32) + bit; } } return -1; }
static void __init set_megamod_mux(struct megamod_pic *pic, int src, int output) { int index, offset; u32 val; if (src < 0 || src >= (NR_COMBINERS * 32)) { pic->output_to_irq[output] = IRQ_UNMAPPED; return; } /* */ index = output / 4; offset = (output & 3) * 8; val = soc_readl(&pic->regs->intmux[index]); val &= ~(0xff << offset); val |= src << offset; soc_writel(val, &pic->regs->intmux[index]); }
static void megamod_irq_cascade(unsigned int irq, struct irq_desc *desc) { struct megamod_cascade_data *cascade; struct megamod_pic *pic; u32 events; int n, idx; cascade = irq_desc_get_handler_data(desc); pic = cascade->pic; idx = cascade->index; while ((events = soc_readl(&pic->regs->mevtflag[idx])) != 0) { n = __ffs(events); irq = irq_linear_revmap(pic->irqhost, idx * 32 + n); soc_writel(1 << n, &pic->regs->evtclr[idx]); generic_handle_irq(irq); } }
static void assert_event(unsigned int val) { soc_writel(val, &mm_pic->regs->evtasrt); }
static struct megamod_pic * __init init_megamod_pic(struct device_node *np) { struct megamod_pic *pic; int i, irq; int mapping[NR_MUX_OUTPUTS]; pr_info("Initializing C64x+ Megamodule PIC\n"); pic = kzalloc(sizeof(struct megamod_pic), GFP_KERNEL); if (!pic) { pr_err("%s: Could not alloc PIC structure.\n", np->full_name); return NULL; } pic->irqhost = irq_domain_add_linear(np, NR_COMBINERS * 32, &megamod_domain_ops, pic); if (!pic->irqhost) { pr_err("%s: Could not alloc host.\n", np->full_name); goto error_free; } pic->irqhost->host_data = pic; raw_spin_lock_init(&pic->lock); pic->regs = of_iomap(np, 0); if (!pic->regs) { pr_err("%s: Could not map registers.\n", np->full_name); goto error_free; } /* */ for (i = 0; i < ARRAY_SIZE(mapping); i++) mapping[i] = IRQ_UNMAPPED; parse_priority_map(pic, mapping, ARRAY_SIZE(mapping)); /* */ for (i = 0; i < NR_COMBINERS; i++) { irq = irq_of_parse_and_map(np, i); if (irq == NO_IRQ) continue; /* */ if (irq < 4 || irq >= NR_PRIORITY_IRQS) { pr_err("%s: combiner-%d virq %d out of range!\n", np->full_name, i, irq); continue; } /* */ mapping[irq - 4] = i; pr_debug("%s: combiner-%d cascading to virq %d\n", np->full_name, i, irq); cascade_data[i].pic = pic; cascade_data[i].index = i; /* */ soc_writel(~0, &pic->regs->evtmask[i]); soc_writel(~0, &pic->regs->evtclr[i]); irq_set_handler_data(irq, &cascade_data[i]); irq_set_chained_handler(irq, megamod_irq_cascade); } /* */ for (i = 0; i < NR_MUX_OUTPUTS; i++) { if (mapping[i] != IRQ_UNMAPPED) { pr_debug("%s: setting mux %d to priority %d\n", np->full_name, mapping[i], i + 4); set_megamod_mux(pic, mapping[i], i); } } return pic; error_free: kfree(pic); return NULL; }
static struct megamod_pic * __init init_megamod_pic(struct device_node *np) { struct megamod_pic *pic; int i, irq; int mapping[NR_MUX_OUTPUTS]; pr_info("Initializing C64x+ Megamodule PIC\n"); pic = kzalloc(sizeof(struct megamod_pic), GFP_KERNEL); if (!pic) { pr_err("%s: Could not alloc PIC structure.\n", np->full_name); return NULL; } pic->irqhost = irq_alloc_host(np, IRQ_HOST_MAP_LINEAR, NR_COMBINERS * 32, &megamod_host_ops, IRQ_UNMAPPED); if (!pic->irqhost) { pr_err("%s: Could not alloc host.\n", np->full_name); goto error_free; } pic->irqhost->host_data = pic; raw_spin_lock_init(&pic->lock); pic->regs = of_iomap(np, 0); if (!pic->regs) { pr_err("%s: Could not map registers.\n", np->full_name); goto error_free; } /* Initialize MUX map */ for (i = 0; i < ARRAY_SIZE(mapping); i++) mapping[i] = IRQ_UNMAPPED; parse_priority_map(pic, mapping, ARRAY_SIZE(mapping)); /* * We can have up to 12 interrupts cascading to the core controller. * These cascades can be from the combined interrupt sources or for * individual interrupt sources. The "interrupts" property only * deals with the cascaded combined interrupts. The individual * interrupts muxed to the core controller use the core controller * as their interrupt parent. */ for (i = 0; i < NR_COMBINERS; i++) { irq = irq_of_parse_and_map(np, i); if (irq == NO_IRQ) continue; /* * We count on the core priority interrupts (4 - 15) being * direct mapped. Check that device tree provided something * in that range. */ if (irq < 4 || irq >= NR_PRIORITY_IRQS) { pr_err("%s: combiner-%d virq %d out of range!\n", np->full_name, i, irq); continue; } /* record the mapping */ mapping[irq - 4] = i; pr_debug("%s: combiner-%d cascading to virq %d\n", np->full_name, i, irq); cascade_data[i].pic = pic; cascade_data[i].index = i; /* mask and clear all events in combiner */ soc_writel(~0, &pic->regs->evtmask[i]); soc_writel(~0, &pic->regs->evtclr[i]); irq_set_handler_data(irq, &cascade_data[i]); irq_set_chained_handler(irq, megamod_irq_cascade); } /* Finally, set up the MUX registers */ for (i = 0; i < NR_MUX_OUTPUTS; i++) { if (mapping[i] != IRQ_UNMAPPED) { pr_debug("%s: setting mux %d to priority %d\n", np->full_name, mapping[i], i + 4); set_megamod_mux(pic, mapping[i], i); } } return pic; error_free: kfree(pic); return NULL; }