Add using of functionality provided by CMU - get_rate and register_clock_handler.
Signed-off-by: Maksim Kozlov <m.koz...@samsung.com> --- hw/exynos4210_uart.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 47 insertions(+), 1 deletions(-) diff --git a/hw/exynos4210_uart.c b/hw/exynos4210_uart.c index ccc4780..10581bd 100644 --- a/hw/exynos4210_uart.c +++ b/hw/exynos4210_uart.c @@ -307,6 +307,7 @@ static void exynos4210_uart_update_parameters(Exynos4210UartState *s) uint64_t uclk_rate; if (s->reg[I_(UBRDIV)] == 0) { + PRINT_DEBUG("Baud rate division value is 0\n"); return; } @@ -332,7 +333,23 @@ static void exynos4210_uart_update_parameters(Exynos4210UartState *s) frame_size += data_bits + stop_bits; - uclk_rate = 24000000; + switch (s->channel) { + case 0: + uclk_rate = exynos4210_cmu_get_rate(EXYNOS4210_SCLK_UART0); + break; + case 1: + uclk_rate = exynos4210_cmu_get_rate(EXYNOS4210_SCLK_UART1); + break; + case 2: + uclk_rate = exynos4210_cmu_get_rate(EXYNOS4210_SCLK_UART2); + break; + case 3: + uclk_rate = exynos4210_cmu_get_rate(EXYNOS4210_SCLK_UART3); + break; + default: + hw_error("%s: Incorrect UART channel: %d\n", + __func__, s->channel); + } speed = uclk_rate / ((16 * (s->reg[I_(UBRDIV)]) & 0xffff) + (s->reg[I_(UFRACVAL)] & 0x7) + 16); @@ -348,6 +365,15 @@ static void exynos4210_uart_update_parameters(Exynos4210UartState *s) s->channel, speed, parity, data_bits, stop_bits); } +static void uclk_rate_changed(void *opaque) +{ + Exynos4210UartState *s = opaque; + + PRINT_DEBUG("Clock sclk_uart%d was changed\n", s->channel); + + exynos4210_uart_update_parameters(s); +} + static void exynos4210_uart_write(void *opaque, target_phys_addr_t offset, uint64_t val, unsigned size) { @@ -542,6 +568,7 @@ static void exynos4210_uart_reset(DeviceState *dev) container_of(dev, Exynos4210UartState, busdev.qdev); int regs_number = sizeof(exynos4210_uart_regs)/sizeof(Exynos4210UartReg); int i; + Exynos4210Clock clock_id; for (i = 0; i < regs_number; i++) { s->reg[I_(exynos4210_uart_regs[i].offset)] = @@ -551,6 +578,25 @@ static void exynos4210_uart_reset(DeviceState *dev) fifo_reset(&s->rx); fifo_reset(&s->tx); + switch (s->channel) { + case 0: + clock_id = EXYNOS4210_SCLK_UART0; + break; + case 1: + clock_id = EXYNOS4210_SCLK_UART1; + break; + case 2: + clock_id = EXYNOS4210_SCLK_UART2; + break; + case 3: + clock_id = EXYNOS4210_SCLK_UART3; + break; + default: + hw_error("Wrong channel number: %d.\n", s->channel); + } + + exynos4210_register_clock_handler(uclk_rate_changed, clock_id, s); + PRINT_DEBUG("UART%d: Rx FIFO size: %d\n", s->channel, s->rx.size); } -- 1.7.5.4