static void __init s3c_serial_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { struct s3c_uart_clksrc clksrc; struct clk *clk; unsigned int ulcon; unsigned int ucon; unsigned int ubrdiv; unsigned int udivslot; unsigned long rate; ulcon = rd_regl(port, S3C_ULCON); ucon = rd_regl(port, S3C_UCON); ubrdiv = rd_regl(port, S3C_UBRDIV); udivslot = rd_regl(port, S3C_UDIVSLOT); dbg("s3c_serial_get_options: port=%p\n" "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x, udivslot=%08x\n", port, ulcon, ucon, ubrdiv, udivslot); if ((ucon & 0xf) != 0) { /* consider the serial port configured if the tx/rx mode set */ switch (ulcon & S3C_LCON_CSMASK) { case S3C_LCON_CS5: *bits = 5; break; case S3C_LCON_CS6: *bits = 6; break; case S3C_LCON_CS7: *bits = 7; break; default: case S3C_LCON_CS8: *bits = 8; break; } switch (ulcon & S3C_LCON_PMASK) { case S3C_LCON_PEVEN: *parity = 'e'; break; case S3C_LCON_PODD: *parity = 'o'; break; case S3C_LCON_PNONE: default: *parity = 'n'; } /* now calculate the baud rate */ s3c_serial_getsource(port, &clksrc); clk = clk_get(port->dev, clksrc.name); if (!IS_ERR(clk) && clk != NULL) rate = clk_get_rate(clk) / clksrc.divisor; else rate = 1; *baud = rate / (16 * (ubrdiv + 1)); dbg("calculated baud %d\n", *baud); } }
static unsigned int s3c_serial_getclk(struct uart_port *port, struct s3c_uart_clksrc **clksrc, struct clk **clk, unsigned int baud, unsigned int *udivslot) { struct s3c_uartcfg *cfg = s3c_port_to_cfg(port); struct s3c_uart_clksrc *clkp; struct baud_calc res[MAX_CLKS]; struct baud_calc *resptr, *best, *sptr; struct clk *uclk1; int i; clkp = cfg->clocks; best = NULL; if (cfg->clocks_size < 2) { if (cfg->clocks_size == 0) clkp = &tmp_clksrc; /* check to see if we're sourcing fclk, and if so we're * going to have to update the clock source */ if (strcmp(clkp->name, "fclk") == 0) { struct s3c_uart_clksrc src; s3c_serial_getsource(port, &src); /* check that the port already using fclk, and if * not, then re-select fclk */ if (strcmp(src.name, clkp->name) == 0) { s3c_serial_setsource(port, clkp); s3c_serial_getsource(port, &src); } clkp->divisor = src.divisor; } if (strcmp(clkp->name, "uclk1") == 0) { uclk1 = clk_get(NULL, clkp->name); clk_set_parent(uclk1, clk_get(NULL, "dout_mpll")); clk_set_rate(uclk1, 133000000); clk_put(uclk1); } s3c_serial_calcbaud(res, port, clkp, baud); best = res; resptr = best + 1; } else { resptr = res; for (i = 0; i < cfg->clocks_size; i++, clkp++) { if (s3c_serial_calcbaud(resptr, port, clkp, baud)) resptr++; } } /* ok, we now need to select the best clock we found */ if (!best) { unsigned int deviation = (1<<30)|((1<<30)-1); int calc_deviation; for (sptr = res; sptr < resptr; sptr++) { calc_deviation = baud - sptr->calc; if (calc_deviation < 0) calc_deviation = -calc_deviation; if (calc_deviation < deviation) { best = sptr; deviation = calc_deviation; } } } /* store results to pass back */ *clksrc = best->clksrc; *clk = best->src; *udivslot = best->udivslot; return best->ubrdiv; }
static unsigned int s3c_serial_getclk(struct uart_port *port, struct s3c24xx_uart_clksrc **clksrc, struct clk **clk, unsigned int baud, unsigned int *slot) { struct s3c2410_uartcfg *cfg = s3c_port_to_cfg(port); struct s3c24xx_uart_clksrc *clkp; struct baud_calc res[MAX_CLKS]; struct baud_calc *resptr, *best, *sptr; int i; clkp = cfg->clocks; best = NULL; if (cfg->clocks_size < 2) { if (cfg->clocks_size == 0) clkp = &tmp_clksrc; /* check to see if we're sourcing fclk, and if so we're * going to have to update the clock source */ if (strcmp(clkp->name, "fclk") == 0) { struct s3c24xx_uart_clksrc src; s3c_serial_getsource(port, &src); /* check that the port already using fclk, and if * not, then re-select fclk */ if (strcmp(src.name, clkp->name) == 0) { s3c_serial_setsource(port, clkp); s3c_serial_getsource(port, &src); } clkp->divisor = src.divisor; } s3c_serial_calcbaud(res, port, clkp, baud); best = res; resptr = best + 1; } else { resptr = res; for (i = 0; i < cfg->clocks_size; i++, clkp++) { if (s3c_serial_calcbaud(resptr, port, clkp, baud)) resptr++; } } /* ok, we now need to select the best clock we found */ if (best==NULL) { unsigned int deviation = (1<<30)|((1<<30)-1); int calc_deviation; best = sptr = res; for (sptr = res; sptr < resptr; sptr++) { printk(KERN_DEBUG "found clk %p (%s) quot %d, calc %d\n", sptr->clksrc, sptr->clksrc->name, sptr->quot, sptr->calc); calc_deviation = baud - sptr->calc; if (calc_deviation < 0) calc_deviation = -calc_deviation; if (calc_deviation < deviation) { best = sptr; deviation = calc_deviation; } } printk(KERN_DEBUG "The best clksrc among candidate clksrc: %p(%s) (deviation: %d bps)\n", best, best->clksrc->name, deviation); } printk(KERN_DEBUG "Selected clock is %p (%s) quot %d, calc %d\n", best->clksrc, best->clksrc->name, best->quot, best->calc); /* store results to pass back */ *clksrc = best->clksrc; *clk = best->src; *slot = best->slot; return best->quot; }