1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Copyright (c) 2017 Intel Corporation 4 */ 5 6 #include <common.h> 7 #include <dm.h> 8 #include <ns16550.h> 9 #include <serial.h> 10 11 /* 12 * The UART clock is calculated as 13 * 14 * UART clock = XTAL * UART_MUL / UART_DIV 15 * 16 * The baudrate is calculated as 17 * 18 * baud rate = UART clock / UART_PS / DLAB 19 */ 20 #define UART_PS 0x30 21 #define UART_MUL 0x34 22 #define UART_DIV 0x38 23 24 static void mid_writel(struct ns16550_platdata *plat, int offset, int value) 25 { 26 unsigned char *addr; 27 28 offset *= 1 << plat->reg_shift; 29 addr = (unsigned char *)plat->base + offset; 30 31 writel(value, addr + plat->reg_offset); 32 } 33 34 static int mid_serial_probe(struct udevice *dev) 35 { 36 struct ns16550_platdata *plat = dev_get_platdata(dev); 37 38 /* 39 * Initialize fractional divider correctly for Intel Edison 40 * platform. 41 * 42 * For backward compatibility we have to set initial DLAB value 43 * to 16 and speed to 115200 baud, where initial frequency is 44 * 29491200Hz, and XTAL frequency is 38.4MHz. 45 */ 46 mid_writel(plat, UART_MUL, 96); 47 mid_writel(plat, UART_DIV, 125); 48 mid_writel(plat, UART_PS, 16); 49 50 return ns16550_serial_probe(dev); 51 } 52 53 static const struct udevice_id mid_serial_ids[] = { 54 { .compatible = "intel,mid-uart" }, 55 {} 56 }; 57 58 U_BOOT_DRIVER(serial_intel_mid) = { 59 .name = "serial_intel_mid", 60 .id = UCLASS_SERIAL, 61 .of_match = mid_serial_ids, 62 .ofdata_to_platdata = ns16550_serial_ofdata_to_platdata, 63 .platdata_auto_alloc_size = sizeof(struct ns16550_platdata), 64 .priv_auto_alloc_size = sizeof(struct NS16550), 65 .probe = mid_serial_probe, 66 .ops = &ns16550_serial_ops, 67 .flags = DM_FLAG_PRE_RELOC, 68 }; 69