static void asc_set_termios(struct uart_port *port, struct ktermios *termios, struct ktermios *old) { struct asc_port *ascport = to_asc_port(port); struct device_node *np = port->dev->of_node; struct gpio_desc *gpiod; unsigned int baud; u32 ctrl_val; tcflag_t cflag; unsigned long flags; /* Update termios to reflect hardware capabilities */ termios->c_cflag &= ~(CMSPAR | (ascport->hw_flow_control ? 0 : CRTSCTS)); port->uartclk = clk_get_rate(ascport->clk); baud = uart_get_baud_rate(port, termios, old, 0, port->uartclk/16); cflag = termios->c_cflag; spin_lock_irqsave(&port->lock, flags); /* read control register */ ctrl_val = asc_in(port, ASC_CTL); /* stop serial port and reset value */ asc_out(port, ASC_CTL, (ctrl_val & ~ASC_CTL_RUN)); ctrl_val = ASC_CTL_RXENABLE | ASC_CTL_FIFOENABLE; /* reset fifo rx & tx */ asc_out(port, ASC_TXRESET, 1); asc_out(port, ASC_RXRESET, 1); /* set character length */ if ((cflag & CSIZE) == CS7) { ctrl_val |= ASC_CTL_MODE_7BIT_PAR; } else { ctrl_val |= (cflag & PARENB) ? ASC_CTL_MODE_8BIT_PAR : ASC_CTL_MODE_8BIT; } /* set stop bit */ ctrl_val |= (cflag & CSTOPB) ? ASC_CTL_STOP_2BIT : ASC_CTL_STOP_1BIT; /* odd parity */ if (cflag & PARODD) ctrl_val |= ASC_CTL_PARITYODD; /* hardware flow control */ if ((cflag & CRTSCTS)) { ctrl_val |= ASC_CTL_CTSENABLE; /* If flow-control selected, stop handling RTS manually */ if (ascport->rts) { devm_gpiod_put(port->dev, ascport->rts); ascport->rts = NULL; pinctrl_select_state(ascport->pinctrl, ascport->states[DEFAULT]); } } else { /* If flow-control disabled, it's safe to handle RTS manually */ if (!ascport->rts && ascport->states[NO_HW_FLOWCTRL]) { pinctrl_select_state(ascport->pinctrl, ascport->states[NO_HW_FLOWCTRL]); gpiod = devm_fwnode_get_gpiod_from_child(port->dev, "rts", &np->fwnode, GPIOD_OUT_LOW, np->name); if (!IS_ERR(gpiod)) ascport->rts = gpiod; } } if ((baud < 19200) && !ascport->force_m1) { asc_out(port, ASC_BAUDRATE, (port->uartclk / (16 * baud))); } else { /* * MODE 1: recommended for high bit rates (above 19.2K) * * baudrate * 16 * 2^16 * ASCBaudRate = ------------------------ * inputclock * * To keep maths inside 64bits, we divide inputclock by 16. */ u64 dividend = (u64)baud * (1 << 16); do_div(dividend, port->uartclk / 16); asc_out(port, ASC_BAUDRATE, dividend); ctrl_val |= ASC_CTL_BAUDMODE; } uart_update_timeout(port, cflag, baud); ascport->port.read_status_mask = ASC_RXBUF_DUMMY_OE; if (termios->c_iflag & INPCK) ascport->port.read_status_mask |= ASC_RXBUF_FE | ASC_RXBUF_PE; if (termios->c_iflag & (IGNBRK | BRKINT | PARMRK)) ascport->port.read_status_mask |= ASC_RXBUF_DUMMY_BE; /* * Characters to ignore */ ascport->port.ignore_status_mask = 0; if (termios->c_iflag & IGNPAR) ascport->port.ignore_status_mask |= ASC_RXBUF_FE | ASC_RXBUF_PE; if (termios->c_iflag & IGNBRK) { ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_BE; /* * If we're ignoring parity and break indicators, * ignore overruns too (for real raw support). */ if (termios->c_iflag & IGNPAR) ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_OE; } /* * Ignore all characters if CREAD is not set. */ if (!(termios->c_cflag & CREAD)) ascport->port.ignore_status_mask |= ASC_RXBUF_DUMMY_RX; /* Set the timeout */ asc_out(port, ASC_TIMEOUT, 20); /* write final value and enable port */ asc_out(port, ASC_CTL, (ctrl_val | ASC_CTL_RUN)); spin_unlock_irqrestore(&port->lock, flags); }
static int gpio_keys_setup_key(struct platform_device *pdev, struct input_dev *input, struct gpio_keys_drvdata *ddata, const struct gpio_keys_button *button, int idx, struct fwnode_handle *child) { const char *desc = button->desc ? button->desc : "gpio_keys"; struct device *dev = &pdev->dev; struct gpio_button_data *bdata = &ddata->data[idx]; irq_handler_t isr; unsigned long irqflags; int irq; int error; bdata->input = input; bdata->button = button; spin_lock_init(&bdata->lock); if (child) { bdata->gpiod = devm_fwnode_get_gpiod_from_child(dev, NULL, child, GPIOD_IN, desc); if (IS_ERR(bdata->gpiod)) { error = PTR_ERR(bdata->gpiod); if (error == -ENOENT) { /* * GPIO is optional, we may be dealing with * purely interrupt-driven setup. */ bdata->gpiod = NULL; } else { if (error != -EPROBE_DEFER) dev_err(dev, "failed to get gpio: %d\n", error); return error; } } } else if (gpio_is_valid(button->gpio)) { /* * Legacy GPIO number, so request the GPIO here and * convert it to descriptor. */ unsigned flags = GPIOF_IN; if (button->active_low) flags |= GPIOF_ACTIVE_LOW; error = devm_gpio_request_one(dev, button->gpio, flags, desc); if (error < 0) { dev_err(dev, "Failed to request GPIO %d, error %d\n", button->gpio, error); return error; } bdata->gpiod = gpio_to_desc(button->gpio); if (!bdata->gpiod) return -EINVAL; } if (bdata->gpiod) { if (button->debounce_interval) { error = gpiod_set_debounce(bdata->gpiod, button->debounce_interval * 1000); /* use timer if gpiolib doesn't provide debounce */ if (error < 0) bdata->software_debounce = button->debounce_interval; } if (button->irq) { bdata->irq = button->irq; } else { irq = gpiod_to_irq(bdata->gpiod); if (irq < 0) { error = irq; dev_err(dev, "Unable to get irq number for GPIO %d, error %d\n", button->gpio, error); return error; } bdata->irq = irq; } INIT_DELAYED_WORK(&bdata->work, gpio_keys_gpio_work_func); isr = gpio_keys_gpio_isr; irqflags = IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING; } else { if (!button->irq) { dev_err(dev, "Found button without gpio or irq\n"); return -EINVAL; } bdata->irq = button->irq; if (button->type && button->type != EV_KEY) { dev_err(dev, "Only EV_KEY allowed for IRQ buttons.\n"); return -EINVAL; } bdata->release_delay = button->debounce_interval; setup_timer(&bdata->release_timer, gpio_keys_irq_timer, (unsigned long)bdata); isr = gpio_keys_irq_isr; irqflags = 0; } bdata->code = &ddata->keymap[idx]; *bdata->code = button->code; input_set_capability(input, button->type ?: EV_KEY, *bdata->code); /* * Install custom action to cancel release timer and * workqueue item. */ error = devm_add_action(dev, gpio_keys_quiesce_key, bdata); if (error) { dev_err(dev, "failed to register quiesce action, error: %d\n", error); return error; } /* * If platform has specified that the button can be disabled, * we don't want it to share the interrupt line. */ if (!button->can_disable) irqflags |= IRQF_SHARED; error = devm_request_any_context_irq(dev, bdata->irq, isr, irqflags, desc, bdata); if (error < 0) { dev_err(dev, "Unable to claim irq %d; error %d\n", bdata->irq, error); return error; } return 0; }