static int probe_setup_port(struct fintek_8250 *pdata, struct uart_8250_port *uart) { static const u16 addr[] = {0x4e, 0x2e}; static const u8 keys[] = {0x77, 0xa0, 0x87, 0x67}; struct irq_data *irq_data; bool level_mode = false; int i, j, k, min, max; for (i = 0; i < ARRAY_SIZE(addr); i++) { for (j = 0; j < ARRAY_SIZE(keys); j++) { pdata->base_port = addr[i]; pdata->key = keys[j]; if (fintek_8250_enter_key(addr[i], keys[j])) continue; if (fintek_8250_check_id(pdata) || fintek_8250_get_ldn_range(pdata, &min, &max)) { fintek_8250_exit_key(addr[i]); continue; } for (k = min; k < max; k++) { u16 aux; sio_write_reg(pdata, LDN, k); aux = sio_read_reg(pdata, IO_ADDR1); aux |= sio_read_reg(pdata, IO_ADDR2) << 8; if (aux != uart->port.iobase) continue; pdata->index = k; irq_data = irq_get_irq_data(uart->port.irq); if (irq_data) level_mode = irqd_is_level_type(irq_data); fintek_8250_set_irq_mode(pdata, level_mode); fintek_8250_set_max_fifo(pdata); fintek_8250_goto_highspeed(uart, pdata); fintek_8250_exit_key(addr[i]); return 0; } fintek_8250_exit_key(addr[i]); } } return -ENODEV; }
int fintek_8250_probe(struct uart_8250_port *uart) { struct fintek_8250 *pdata; struct fintek_8250 probe_data; struct irq_data *irq_data = irq_get_irq_data(uart->port.irq); bool level_mode = irqd_is_level_type(irq_data); if (find_base_port(&probe_data, uart->port.iobase)) return -ENODEV; pdata = devm_kzalloc(uart->port.dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) return -ENOMEM; memcpy(pdata, &probe_data, sizeof(probe_data)); uart->port.rs485_config = fintek_8250_rs485_config; uart->port.private_data = pdata; return fintek_8250_set_irq_mode(pdata, level_mode); }