1 /* 2 * (C) Copyright 2015 3 * Kamil Lulko, <rev13@wp.pl> 4 * 5 * SPDX-License-Identifier: GPL-2.0+ 6 */ 7 8 #include <common.h> 9 #include <asm/io.h> 10 #include <serial.h> 11 #include <asm/arch/stm32.h> 12 13 /* 14 * Set up the usart port 15 */ 16 #if (CONFIG_STM32_USART >= 1) && (CONFIG_STM32_USART <= 6) 17 #define USART_PORT (CONFIG_STM32_USART - 1) 18 #else 19 #define USART_PORT 0 20 #endif 21 /* 22 * Set up the usart base address 23 * 24 * --STM32_USARTD_BASE means default setting 25 */ 26 #define STM32_USART1_BASE (STM32_APB2PERIPH_BASE + 0x1000) 27 #define STM32_USART2_BASE (STM32_APB1PERIPH_BASE + 0x4400) 28 #define STM32_USART3_BASE (STM32_APB1PERIPH_BASE + 0x4800) 29 #define STM32_USART6_BASE (STM32_APB2PERIPH_BASE + 0x1400) 30 #define STM32_USARTD_BASE STM32_USART1_BASE 31 /* 32 * RCC USART specific definitions 33 * 34 * --RCC_ENR_USARTDEN means default setting 35 */ 36 #define RCC_ENR_USART1EN (1 << 4) 37 #define RCC_ENR_USART2EN (1 << 17) 38 #define RCC_ENR_USART3EN (1 << 18) 39 #define RCC_ENR_USART6EN (1 << 5) 40 #define RCC_ENR_USARTDEN RCC_ENR_USART1EN 41 42 struct stm32_serial { 43 u32 sr; 44 u32 dr; 45 u32 brr; 46 u32 cr1; 47 u32 cr2; 48 u32 cr3; 49 u32 gtpr; 50 }; 51 52 #define USART_CR1_RE (1 << 2) 53 #define USART_CR1_TE (1 << 3) 54 #define USART_CR1_UE (1 << 13) 55 56 #define USART_SR_FLAG_RXNE (1 << 5) 57 #define USART_SR_FLAG_TXE (1 << 7) 58 59 #define USART_BRR_F_MASK 0xF 60 #define USART_BRR_M_SHIFT 4 61 #define USART_BRR_M_MASK 0xFFF0 62 63 DECLARE_GLOBAL_DATA_PTR; 64 65 static const unsigned long usart_base[] = { 66 STM32_USART1_BASE, 67 STM32_USART2_BASE, 68 STM32_USART3_BASE, 69 STM32_USARTD_BASE, 70 STM32_USARTD_BASE, 71 STM32_USART6_BASE 72 }; 73 74 static const unsigned long rcc_enr_en[] = { 75 RCC_ENR_USART1EN, 76 RCC_ENR_USART2EN, 77 RCC_ENR_USART3EN, 78 RCC_ENR_USARTDEN, 79 RCC_ENR_USARTDEN, 80 RCC_ENR_USART6EN 81 }; 82 83 static void stm32_serial_setbrg(void) 84 { 85 serial_init(); 86 } 87 88 static int stm32_serial_init(void) 89 { 90 struct stm32_serial *usart = 91 (struct stm32_serial *)usart_base[USART_PORT]; 92 u32 clock, int_div, frac_div, tmp; 93 94 if ((usart_base[USART_PORT] & STM32_BUS_MASK) == 95 STM32_APB1PERIPH_BASE) { 96 setbits_le32(&STM32_RCC->apb1enr, rcc_enr_en[USART_PORT]); 97 clock = clock_get(CLOCK_APB1); 98 } else if ((usart_base[USART_PORT] & STM32_BUS_MASK) == 99 STM32_APB2PERIPH_BASE) { 100 setbits_le32(&STM32_RCC->apb2enr, rcc_enr_en[USART_PORT]); 101 clock = clock_get(CLOCK_APB2); 102 } else { 103 return -1; 104 } 105 106 int_div = (25 * clock) / (4 * gd->baudrate); 107 tmp = ((int_div / 100) << USART_BRR_M_SHIFT) & USART_BRR_M_MASK; 108 frac_div = int_div - (100 * (tmp >> USART_BRR_M_SHIFT)); 109 tmp |= (((frac_div * 16) + 50) / 100) & USART_BRR_F_MASK; 110 111 writel(tmp, &usart->brr); 112 setbits_le32(&usart->cr1, USART_CR1_RE | USART_CR1_TE | USART_CR1_UE); 113 114 return 0; 115 } 116 117 static int stm32_serial_getc(void) 118 { 119 struct stm32_serial *usart = 120 (struct stm32_serial *)usart_base[USART_PORT]; 121 while ((readl(&usart->sr) & USART_SR_FLAG_RXNE) == 0) 122 ; 123 return readl(&usart->dr); 124 } 125 126 static void stm32_serial_putc(const char c) 127 { 128 struct stm32_serial *usart = 129 (struct stm32_serial *)usart_base[USART_PORT]; 130 131 if (c == '\n') 132 stm32_serial_putc('\r'); 133 134 while ((readl(&usart->sr) & USART_SR_FLAG_TXE) == 0) 135 ; 136 writel(c, &usart->dr); 137 } 138 139 static int stm32_serial_tstc(void) 140 { 141 struct stm32_serial *usart = 142 (struct stm32_serial *)usart_base[USART_PORT]; 143 u8 ret; 144 145 ret = readl(&usart->sr) & USART_SR_FLAG_RXNE; 146 return ret; 147 } 148 149 static struct serial_device stm32_serial_drv = { 150 .name = "stm32_serial", 151 .start = stm32_serial_init, 152 .stop = NULL, 153 .setbrg = stm32_serial_setbrg, 154 .putc = stm32_serial_putc, 155 .puts = default_serial_puts, 156 .getc = stm32_serial_getc, 157 .tstc = stm32_serial_tstc, 158 }; 159 160 void stm32_serial_initialize(void) 161 { 162 serial_register(&stm32_serial_drv); 163 } 164 165 __weak struct serial_device *default_serial_console(void) 166 { 167 return &stm32_serial_drv; 168 } 169