/* * These defines will translated the dt binding settings to our internal * settings. They are not necessarily the same value as the register setting. * The actual drive strength current of low, medium and high must be looked up * from the corresponding device datasheet. This value is different for pins * that are even in the same banks. It is also dependent on VCC. * DRIVE_STRENGTH_DEFAULT is just a placeholder to avoid changing the drive * strength when there is no dt config for it.
*/ enum drive_strength_bit {
DRIVE_STRENGTH_BIT_DEF,
DRIVE_STRENGTH_BIT_LOW,
DRIVE_STRENGTH_BIT_MED,
DRIVE_STRENGTH_BIT_HI,
};
/** * struct at91_pmx_func - describes AT91 pinmux functions * @name: the name of this specific function * @groups: corresponding pin groups * @ngroups: the number of groups
*/ struct at91_pmx_func { constchar *name; constchar **groups; unsigned ngroups;
};
/** * struct at91_pmx_pin - describes an At91 pin mux * @bank: the bank of the pin * @pin: the pin number in the @bank * @mux: the mux mode : gpio or periph_x of the pin i.e. alternate function. * @conf: the configuration of the pin: PULL_UP, MULTIDRIVE etc...
*/ struct at91_pmx_pin {
uint32_t bank;
uint32_t pin; enum at91_mux mux; unsignedlong conf;
};
/** * struct at91_pin_group - describes an At91 pin group * @name: the name of this specific pin group * @pins_conf: the mux mode for each pin in this group. The size of this * array is the same as pins. * @pins: an array of discrete physical pins used in this group, taken * from the driver-local pin enumeration space * @npins: the number of pins in this group array, i.e. the number of * elements in .pins so we can iterate over that array
*/ struct at91_pin_group { constchar *name; struct at91_pmx_pin *pins_conf; unsignedint *pins; unsigned npins;
};
/** * struct at91_pinctrl_mux_ops - describes an AT91 mux ops group * on new IP with support for periph C and D the way to mux in * periph A and B has changed * So provide the right call back * if not present means the IP does not support it * @get_periph: return the periph mode configured * @mux_A_periph: mux as periph A * @mux_B_periph: mux as periph B * @mux_C_periph: mux as periph C * @mux_D_periph: mux as periph D * @get_deglitch: get deglitch status * @set_deglitch: enable/disable deglitch * @get_debounce: get debounce status * @set_debounce: enable/disable debounce * @get_pulldown: get pulldown status * @set_pulldown: enable/disable pulldown * @get_schmitt_trig: get schmitt trigger status * @disable_schmitt_trig: disable schmitt trigger * @get_drivestrength: get driver strength * @set_drivestrength: set driver strength * @get_slewrate: get slew rate * @set_slewrate: set slew rate * @irq_type: return irq type
*/ struct at91_pinctrl_mux_ops { enum at91_mux (*get_periph)(void __iomem *pio, unsigned mask); void (*mux_A_periph)(void __iomem *pio, unsigned mask); void (*mux_B_periph)(void __iomem *pio, unsigned mask); void (*mux_C_periph)(void __iomem *pio, unsigned mask); void (*mux_D_periph)(void __iomem *pio, unsigned mask); bool (*get_deglitch)(void __iomem *pio, unsigned pin); void (*set_deglitch)(void __iomem *pio, unsigned mask, bool is_on); bool (*get_debounce)(void __iomem *pio, unsigned pin, u32 *div); void (*set_debounce)(void __iomem *pio, unsigned mask, bool is_on, u32 div); bool (*get_pulldown)(void __iomem *pio, unsigned pin); void (*set_pulldown)(void __iomem *pio, unsigned mask, bool is_on); bool (*get_schmitt_trig)(void __iomem *pio, unsigned pin); void (*disable_schmitt_trig)(void __iomem *pio, unsigned mask); unsigned (*get_drivestrength)(void __iomem *pio, unsigned pin); void (*set_drivestrength)(void __iomem *pio, unsigned pin,
u32 strength); unsigned (*get_slewrate)(void __iomem *pio, unsigned pin); void (*set_slewrate)(void __iomem *pio, unsigned pin, u32 slewrate); /* irq */ int (*irq_type)(struct irq_data *d, unsigned type);
};
/* * first find the group of this node and check if we need to create * config maps for pins
*/
grp = at91_pinctrl_find_group_by_name(info, np->name); if (!grp) {
dev_err(info->dev, "unable to find group for node %pOFn\n",
np); return -EINVAL;
}
staticunsigned two_bit_pin_value_shift_amount(unsignedint pin)
{ /* return the shift value for a pin for "two bit" per pin registers,
* i.e. drive strength */ return 2*((pin >= MAX_NB_GPIO_PER_BANK/2)
? pin - MAX_NB_GPIO_PER_BANK/2 : pin);
}
staticunsigned sama5d3_get_drive_register(unsignedint pin)
{ /* drive strength is split between two registers
* with two bits per pin */ return (pin >= MAX_NB_GPIO_PER_BANK/2)
? SAMA5D3_PIO_DRIVER2 : SAMA5D3_PIO_DRIVER1;
}
staticunsigned at91sam9x5_get_drive_register(unsignedint pin)
{ /* drive strength is split between two registers
* with two bits per pin */ return (pin >= MAX_NB_GPIO_PER_BANK/2)
? AT91SAM9X5_PIO_DRIVER2 : AT91SAM9X5_PIO_DRIVER1;
}
staticvoid at91_mux_sama5d3_set_drivestrength(void __iomem *pio, unsigned pin,
u32 setting)
{ /* do nothing if setting is zero */ if (!setting) return;
/* strength is 1 to 1 with setting for SAMA5 */
set_drive_strength(pio + sama5d3_get_drive_register(pin), pin, setting);
}
staticvoid at91_mux_sam9x5_set_drivestrength(void __iomem *pio, unsigned pin,
u32 setting)
{ /* do nothing if setting is zero */ if (!setting) return;
/* strength is inverse on SAM9x5s with our defines
* 0 = hi, 1 = med, 2 = low, 3 = rsvd */
setting = DRIVE_STRENGTH_BIT_MSK(HI) - setting;
dev_dbg(info->dev, "enable function %s group %s\n",
info->functions[selector].name, info->groups[group].name);
/* first check that all the pins of the group are valid with a valid
* parameter */ for (i = 0; i < npins; i++) {
pin = &pins_conf[i];
ret = pin_check_config(info, info->groups[group].name, i, pin); if (ret) return ret;
}
for (i = 0; i < npins; i++) {
pin = &pins_conf[i];
at91_pin_dbg(info->dev, pin);
pio = pin_to_controller(info, pin->bank);
if (!pio) continue;
mask = pin_to_mask(pin->pin);
at91_mux_disable_interrupt(pio, mask); switch (pin->mux) { case AT91_MUX_GPIO:
at91_mux_gpio_enable(pio, mask, 1); break; case AT91_MUX_PERIPH_A:
info->ops->mux_A_periph(pio, mask); break; case AT91_MUX_PERIPH_B:
info->ops->mux_B_periph(pio, mask); break; case AT91_MUX_PERIPH_C: if (!info->ops->mux_C_periph) return -EINVAL;
info->ops->mux_C_periph(pio, mask); break; case AT91_MUX_PERIPH_D: if (!info->ops->mux_D_periph) return -EINVAL;
info->ops->mux_D_periph(pio, mask); break;
} if (pin->mux)
at91_mux_gpio_disable(pio, mask);
}
for_each_child_of_node(np, child) { if (of_device_is_compatible(child, gpio_compat)) { if (of_device_is_available(child))
info->nactive_banks++;
} else {
info->nfunctions++;
info->ngroups += of_get_child_count(child);
}
}
}
staticint at91_pinctrl_mux_mask(struct at91_pinctrl *info, struct device_node *np)
{ int ret = 0; int size; const __be32 *list;
list = of_get_property(np, "atmel,mux-mask", &size); if (!list) {
dev_err(info->dev, "can not read the mux-mask of %d\n", size); return -EINVAL;
}
size /= sizeof(*list); if (!size || size % gpio_banks) {
dev_err(info->dev, "wrong mux mask array should be by %d\n", gpio_banks); return -EINVAL;
}
info->nmux = size / gpio_banks;
info->mux_mask = devm_kcalloc(info->dev, size, sizeof(u32),
GFP_KERNEL); if (!info->mux_mask) return -ENOMEM;
ret = of_property_read_u32_array(np, "atmel,mux-mask",
info->mux_mask, size); if (ret)
dev_err(info->dev, "can not read the mux-mask of %d\n", size); return ret;
}
staticint at91_pinctrl_parse_groups(struct device_node *np, struct at91_pin_group *grp, struct at91_pinctrl *info, u32 index)
{ struct at91_pmx_pin *pin; int size; const __be32 *list; int i, j;
/* * the binding format is atmel,pins = <bank pin mux CONFIG ...>, * do sanity check and calculate pins number
*/
list = of_get_property(np, "atmel,pins", &size); /* we do not check return since it's safe node passed down */
size /= sizeof(*list); if (!size || size % 4) {
dev_err(info->dev, "wrong pins number or pins and configs should be by 4\n"); return -EINVAL;
}
/* * We need all the GPIO drivers to probe FIRST, or we will not be able * to obtain references to the struct gpio_chip * for them, and we * need this to proceed.
*/ for (i = 0; i < MAX_GPIO_BANKS; i++) if (gpio_chips[i])
ngpio_chips_enabled++;
if (ngpio_chips_enabled < info->nactive_banks) return -EPROBE_DEFER;
ret = at91_pinctrl_mux_mask(info, np); if (ret) return ret;
dev_dbg(dev, "nmux = %d\n", info->nmux);
dev_dbg(dev, "mux-mask\n");
tmp = info->mux_mask; for (i = 0; i < gpio_banks; i++) { for (j = 0; j < info->nmux; j++, tmp++) {
dev_dbg(dev, "%d:%d\t0x%x\n", i, j, tmp[0]);
}
}
platform_set_drvdata(pdev, info);
info->pctl = devm_pinctrl_register(dev, &at91_pinctrl_desc, info); if (IS_ERR(info->pctl)) return dev_err_probe(dev, PTR_ERR(info->pctl), "could not register AT91 pinctrl driver\n");
/* We will handle a range of GPIO pins */ for (i = 0; i < gpio_banks; i++) if (gpio_chips[i]) {
pinctrl_add_gpio_range(info->pctl, &gpio_chips[i]->range);
gpiochip_add_pin_range(&gpio_chips[i]->chip, dev_name(info->pctl->dev), 0,
gpio_chips[i]->range.pin_base, gpio_chips[i]->range.npins);
}
/* Several AIC controller irqs are dispatched through this GPIO handler. * To use any AT91_PIN_* as an externally triggered IRQ, first call * at91_set_gpio_input() then maybe enable its glitch filter. * Then just request_irq() with the pin ID; it works like any ARM IRQ * handler. * First implementation always triggers on rising and falling edges * whereas the newer PIO3 can be additionally configured to trigger on * level, edge with any polarity. * * Alternatively, certain pins may be used directly as IRQ0..IRQ6 after * configuring them with at91_set_a_periph() or at91_set_b_periph(). * IRQ0..IRQ6 should be configurable, e.g. level vs edge triggering.
*/
switch (type) { case IRQ_TYPE_EDGE_RISING:
irq_set_handler_locked(d, handle_simple_irq);
writel_relaxed(mask, pio + PIO_ESR);
writel_relaxed(mask, pio + PIO_REHLSR); break; case IRQ_TYPE_EDGE_FALLING:
irq_set_handler_locked(d, handle_simple_irq);
writel_relaxed(mask, pio + PIO_ESR);
writel_relaxed(mask, pio + PIO_FELLSR); break; case IRQ_TYPE_LEVEL_LOW:
irq_set_handler_locked(d, handle_level_irq);
writel_relaxed(mask, pio + PIO_LSR);
writel_relaxed(mask, pio + PIO_FELLSR); break; case IRQ_TYPE_LEVEL_HIGH:
irq_set_handler_locked(d, handle_level_irq);
writel_relaxed(mask, pio + PIO_LSR);
writel_relaxed(mask, pio + PIO_REHLSR); break; case IRQ_TYPE_EDGE_BOTH: /* * disable additional interrupt modes: * fall back to default behavior
*/
irq_set_handler_locked(d, handle_simple_irq);
writel_relaxed(mask, pio + PIO_AIMDR); return 0; case IRQ_TYPE_NONE: default:
pr_warn("AT91: No type for GPIO irq offset %d\n", d->irq); return -EINVAL;
}
/* enable additional interrupt modes */
writel_relaxed(mask, pio + PIO_AIMER);
return 0;
}
staticvoid gpio_irq_ack(struct irq_data *d)
{ /* the interrupt is already cleared before by reading ISR */
}
at91_chip->backups = readl_relaxed(pio + PIO_IMR);
writel_relaxed(at91_chip->backups, pio + PIO_IDR);
writel_relaxed(at91_chip->wakeups, pio + PIO_IER);
if (!at91_chip->wakeups)
clk_disable_unprepare(at91_chip->clock); else
dev_dbg(dev, "GPIO-%c may wake for %08x\n", 'A' + at91_chip->id, at91_chip->wakeups);
chained_irq_enter(chip, desc); for (;;) { /* Reading ISR acks pending (edge triggered) GPIO interrupts. * When there are none pending, we're finished unless we need * to process multiple banks (like ID_PIOCDE on sam9263).
*/
isr = readl_relaxed(pio + PIO_ISR) & readl_relaxed(pio + PIO_IMR); if (!isr) { if (!at91_gpio->next) break;
at91_gpio = at91_gpio->next;
pio = at91_gpio->regbase;
gpio_chip = &at91_gpio->chip; continue;
}
for_each_set_bit(n, &isr, BITS_PER_LONG)
generic_handle_domain_irq(gpio_chip->irq.domain, n);
}
chained_irq_exit(chip, desc); /* now it may re-trigger */
}
/* Disable irqs of this PIO controller */
writel_relaxed(~0, at91_gpio->regbase + PIO_IDR);
/* * Let the generic code handle this edge IRQ, the chained * handler will perform the actual work of handling the parent * interrupt.
*/
girq = &at91_gpio->chip.irq;
gpio_irq_chip_set_chip(girq, gpio_irqchip);
girq->default_type = IRQ_TYPE_NONE;
girq->handler = handle_edge_irq;
/* * The top level handler handles one bank of GPIOs, except * on some SoC it can handle up to three... * We only set up the handler for the first of the list.
*/
gpiochip_prev = irq_get_handler_data(at91_gpio->pioc_virq); if (!gpiochip_prev) {
girq->parent_handler = gpio_irq_handler;
girq->num_parents = 1;
girq->parents = devm_kcalloc(dev, girq->num_parents, sizeof(*girq->parents),
GFP_KERNEL); if (!girq->parents) return -ENOMEM;
girq->parents[0] = at91_gpio->pioc_virq; return 0;
}
prev = gpiochip_get_data(gpiochip_prev); /* we can only have 2 banks before */ for (i = 0; i < 2; i++) { if (prev->next) {
prev = prev->next;
} else {
prev->next = at91_gpio; return 0;
}
}
return -EINVAL;
}
/* This structure is replicated for each GPIO block allocated at probe time */ staticconststruct gpio_chip at91_gpio_template = {
.request = gpiochip_generic_request,
.free = gpiochip_generic_free,
.get_direction = at91_gpio_get_direction,
.direction_input = at91_gpio_direction_input,
.get = at91_gpio_get,
.direction_output = at91_gpio_direction_output,
.set = at91_gpio_set,
.set_multiple = at91_gpio_set_multiple,
.dbg_show = at91_gpio_dbg_show,
.can_sleep = false,
.ngpio = MAX_NB_GPIO_PER_BANK,
};
at91_chip->clock = devm_clk_get_enabled(dev, NULL); if (IS_ERR(at91_chip->clock)) return dev_err_probe(dev, PTR_ERR(at91_chip->clock), "failed to get clock, ignoring.\n");
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.