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