/** * mctrl_gpio_set - set gpios according to mctrl state * @gpios: gpios to set * @mctrl: state to set * * Set the gpios according to the mctrl state.
*/ void mctrl_gpio_set(struct mctrl_gpios *gpios, unsignedint mctrl)
{ enum mctrl_gpio_idx i; struct gpio_desc *desc_array[UART_GPIO_MAX];
DECLARE_BITMAP(values, UART_GPIO_MAX); unsignedint count = 0;
if (gpios == NULL) return;
for (i = 0; i < UART_GPIO_MAX; i++) if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) {
desc_array[count] = gpios->gpio[i];
__assign_bit(count, values,
mctrl & mctrl_gpios_desc[i].mctrl);
count++;
}
gpiod_set_array_value(count, desc_array, NULL, values);
}
EXPORT_SYMBOL_GPL(mctrl_gpio_set);
/** * mctrl_gpio_to_gpiod - obtain gpio_desc of modem line index * @gpios: gpios to look into * @gidx: index of the modem line * Returns: the gpio_desc structure associated to the modem line index
*/ struct gpio_desc *mctrl_gpio_to_gpiod(struct mctrl_gpios *gpios, enum mctrl_gpio_idx gidx)
{ if (gpios == NULL) return NULL;
/** * mctrl_gpio_get - update mctrl with the gpios values. * @gpios: gpios to get the info from * @mctrl: mctrl to set * Returns: modified mctrl (the same value as in @mctrl) * * Update mctrl with the gpios values.
*/ unsignedint mctrl_gpio_get(struct mctrl_gpios *gpios, unsignedint *mctrl)
{ enum mctrl_gpio_idx i;
if (gpios == NULL) return *mctrl;
for (i = 0; i < UART_GPIO_MAX; i++) { if (gpios->gpio[i] && !mctrl_gpio_flags_is_dir_out(i)) { if (gpiod_get_value(gpios->gpio[i]))
*mctrl |= mctrl_gpios_desc[i].mctrl; else
*mctrl &= ~mctrl_gpios_desc[i].mctrl;
}
}
for (i = 0; i < UART_GPIO_MAX; i++) { if (gpios->gpio[i] && mctrl_gpio_flags_is_dir_out(i)) { if (gpiod_get_value(gpios->gpio[i]))
*mctrl |= mctrl_gpios_desc[i].mctrl; else
*mctrl &= ~mctrl_gpios_desc[i].mctrl;
}
}
gpios = devm_kzalloc(dev, sizeof(*gpios), GFP_KERNEL); if (!gpios) return ERR_PTR(-ENOMEM);
for (i = 0; i < UART_GPIO_MAX; i++) { char *gpio_str; bool present;
/* Check if GPIO property exists and continue if not */
gpio_str = kasprintf(GFP_KERNEL, "%s-gpios",
mctrl_gpios_desc[i].name); if (!gpio_str) continue;
present = device_property_present(dev, gpio_str);
kfree(gpio_str); if (!present) continue;
/** * mctrl_gpio_init - initialize uart gpios * @port: port to initialize gpios for * @idx: index of the gpio in the @port's device * * This will get the {cts,rts,...}-gpios from device tree if they are present * and request them, set direction etc, and return an allocated structure. * `devm_*` functions are used, so there's no need to explicitly free. * As this sets up the irq handling, make sure to not handle changes to the * gpio input lines in your driver, too.
*/ struct mctrl_gpios *mctrl_gpio_init(struct uart_port *port, unsignedint idx)
{ struct mctrl_gpios *gpios; enum mctrl_gpio_idx i;
gpios = mctrl_gpio_init_noauto(port->dev, idx); if (IS_ERR(gpios)) return gpios;
gpios->port = port;
for (i = 0; i < UART_GPIO_MAX; ++i) { int ret;
if (!gpios->gpio[i] || mctrl_gpio_flags_is_dir_out(i)) continue;
ret = gpiod_to_irq(gpios->gpio[i]); if (ret < 0) {
dev_err(port->dev, "failed to find corresponding irq for %s (idx=%d, err=%d)\n",
mctrl_gpios_desc[i].name, idx, ret); return ERR_PTR(ret);
}
gpios->irq[i] = ret;
/* irqs should only be enabled in .enable_ms */
irq_set_status_flags(gpios->irq[i], IRQ_NOAUTOEN);
ret = devm_request_irq(port->dev, gpios->irq[i],
mctrl_gpio_irq_handle,
IRQ_TYPE_EDGE_BOTH, dev_name(port->dev),
gpios); if (ret) { /* alternatively implement polling */
dev_err(port->dev, "failed to request irq for %s (idx=%d, err=%d)\n",
mctrl_gpios_desc[i].name, idx, ret); return ERR_PTR(ret);
}
}
/** * mctrl_gpio_enable_ms - enable irqs and handling of changes to the ms lines * @gpios: gpios to enable
*/ void mctrl_gpio_enable_ms(struct mctrl_gpios *gpios)
{ enum mctrl_gpio_idx i;
if (gpios == NULL) return;
/* .enable_ms may be called multiple times */ if (gpios->mctrl_on) return;
gpios->mctrl_on = true;
/* get initial status of modem lines GPIOs */
mctrl_gpio_get(gpios, &gpios->mctrl_prev);
for (i = 0; i < UART_GPIO_MAX; ++i) { if (!gpios->irq[i]) continue;
for (i = 0; i < UART_GPIO_MAX; ++i) { if (!gpios->irq[i]) continue;
if (sync)
disable_irq(gpios->irq[i]); else
disable_irq_nosync(gpios->irq[i]);
}
}
/** * mctrl_gpio_disable_ms_sync - disable irqs and handling of changes to the ms * lines, and wait for any pending IRQ to be processed * @gpios: gpios to disable
*/ void mctrl_gpio_disable_ms_sync(struct mctrl_gpios *gpios)
{
mctrl_gpio_disable_ms(gpios, true);
}
EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_sync);
/** * mctrl_gpio_disable_ms_no_sync - disable irqs and handling of changes to the * ms lines, and return immediately * @gpios: gpios to disable
*/ void mctrl_gpio_disable_ms_no_sync(struct mctrl_gpios *gpios)
{
mctrl_gpio_disable_ms(gpios, false);
}
EXPORT_SYMBOL_GPL(mctrl_gpio_disable_ms_no_sync);
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.