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; }