Commit d3a8a252 authored by Alexander Shiyan's avatar Alexander Shiyan Committed by Greg Kroah-Hartman

serial: max310x: Migrate to CLK API

This patch removes "frequency" parameter from MAX310X platform_data
and uses CLK API for getting clock. Clock type (XTAL/OSC) is
determined by clk name.
Signed-off-by: default avatarAlexander Shiyan <shc_work@mail.ru>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 27027a70
...@@ -17,6 +17,7 @@ ...@@ -17,6 +17,7 @@
#include <linux/delay.h> #include <linux/delay.h>
#include <linux/device.h> #include <linux/device.h>
#include <linux/bitops.h> #include <linux/bitops.h>
#include <linux/clk.h>
#include <linux/serial_core.h> #include <linux/serial_core.h>
#include <linux/serial.h> #include <linux/serial.h>
#include <linux/tty.h> #include <linux/tty.h>
...@@ -291,6 +292,7 @@ struct max310x_port { ...@@ -291,6 +292,7 @@ struct max310x_port {
struct max310x_devtype *devtype; struct max310x_devtype *devtype;
struct regmap *regmap; struct regmap *regmap;
struct mutex mutex; struct mutex mutex;
struct clk *clk;
struct max310x_pdata *pdata; struct max310x_pdata *pdata;
int gpio_used; int gpio_used;
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
...@@ -546,18 +548,19 @@ static int max310x_update_best_err(unsigned long f, long *besterr) ...@@ -546,18 +548,19 @@ static int max310x_update_best_err(unsigned long f, long *besterr)
return 1; return 1;
} }
static int max310x_set_ref_clk(struct max310x_port *s) static int max310x_set_ref_clk(struct max310x_port *s, unsigned long freq,
bool xtal)
{ {
unsigned int div, clksrc, pllcfg = 0; unsigned int div, clksrc, pllcfg = 0;
long besterr = -1; long besterr = -1;
unsigned long fdiv, fmul, bestfreq = s->pdata->frequency; unsigned long fdiv, fmul, bestfreq = freq;
/* First, update error without PLL */ /* First, update error without PLL */
max310x_update_best_err(s->pdata->frequency, &besterr); max310x_update_best_err(freq, &besterr);
/* Try all possible PLL dividers */ /* Try all possible PLL dividers */
for (div = 1; (div <= 63) && besterr; div++) { for (div = 1; (div <= 63) && besterr; div++) {
fdiv = DIV_ROUND_CLOSEST(s->pdata->frequency, div); fdiv = DIV_ROUND_CLOSEST(freq, div);
/* Try multiplier 6 */ /* Try multiplier 6 */
fmul = fdiv * 6; fmul = fdiv * 6;
...@@ -590,10 +593,7 @@ static int max310x_set_ref_clk(struct max310x_port *s) ...@@ -590,10 +593,7 @@ static int max310x_set_ref_clk(struct max310x_port *s)
} }
/* Configure clock source */ /* Configure clock source */
if (s->pdata->driver_flags & MAX310X_EXT_CLK) clksrc = xtal ? MAX310X_CLKSRC_CRYST_BIT : MAX310X_CLKSRC_EXTCLK_BIT;
clksrc = MAX310X_CLKSRC_EXTCLK_BIT;
else
clksrc = MAX310X_CLKSRC_CRYST_BIT;
/* Configure PLL */ /* Configure PLL */
if (pllcfg) { if (pllcfg) {
...@@ -605,7 +605,7 @@ static int max310x_set_ref_clk(struct max310x_port *s) ...@@ -605,7 +605,7 @@ static int max310x_set_ref_clk(struct max310x_port *s)
regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc); regmap_write(s->regmap, MAX310X_CLKSRC_REG, clksrc);
/* Wait for crystal */ /* Wait for crystal */
if (pllcfg && !(s->pdata->driver_flags & MAX310X_EXT_CLK)) if (pllcfg && xtal)
msleep(10); msleep(10);
return (int)bestfreq; return (int)bestfreq;
...@@ -1078,9 +1078,11 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip, ...@@ -1078,9 +1078,11 @@ static int max310x_gpio_direction_output(struct gpio_chip *chip,
static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
struct regmap *regmap, int irq) struct regmap *regmap, int irq)
{ {
struct max310x_port *s;
struct max310x_pdata *pdata = dev_get_platdata(dev); struct max310x_pdata *pdata = dev_get_platdata(dev);
int i, ret, uartclk; int i, ret, fmin, fmax, freq, uartclk;
struct clk *clk_osc, *clk_xtal;
struct max310x_port *s;
bool xtal = false;
if (IS_ERR(regmap)) if (IS_ERR(regmap))
return PTR_ERR(regmap); return PTR_ERR(regmap);
...@@ -1098,14 +1100,35 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, ...@@ -1098,14 +1100,35 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
return -ENOMEM; return -ENOMEM;
} }
/* Check input frequency */ clk_osc = devm_clk_get(dev, "osc");
if ((pdata->driver_flags & MAX310X_EXT_CLK) && clk_xtal = devm_clk_get(dev, "xtal");
((pdata->frequency < 500000) || (pdata->frequency > 35000000))) if (!IS_ERR(clk_osc)) {
goto err_freq; s->clk = clk_osc;
/* Check frequency for quartz */ fmin = 500000;
if (!(pdata->driver_flags & MAX310X_EXT_CLK) && fmax = 35000000;
((pdata->frequency < 1000000) || (pdata->frequency > 4000000))) } else if (!IS_ERR(clk_xtal)) {
goto err_freq; s->clk = clk_xtal;
fmin = 1000000;
fmax = 4000000;
xtal = true;
} else if (PTR_ERR(clk_osc) == -EPROBE_DEFER ||
PTR_ERR(clk_xtal) == -EPROBE_DEFER) {
return -EPROBE_DEFER;
} else {
dev_err(dev, "Cannot get clock\n");
return -EINVAL;
}
ret = clk_prepare_enable(s->clk);
if (ret)
return ret;
freq = clk_get_rate(s->clk);
/* Check frequency limits */
if (freq < fmin || freq > fmax) {
ret = -ERANGE;
goto out_clk;
}
s->pdata = pdata; s->pdata = pdata;
s->regmap = regmap; s->regmap = regmap;
...@@ -1117,7 +1140,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, ...@@ -1117,7 +1140,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
/* Check device to ensure we are talking to what we expect */ /* Check device to ensure we are talking to what we expect */
ret = devtype->detect(dev); ret = devtype->detect(dev);
if (ret) if (ret)
return ret; goto out_clk;
for (i = 0; i < devtype->nr; i++) { for (i = 0; i < devtype->nr; i++) {
unsigned int offs = i << 5; unsigned int offs = i << 5;
...@@ -1139,7 +1162,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, ...@@ -1139,7 +1162,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
MAX310X_MODE1_AUTOSLEEP_BIT); MAX310X_MODE1_AUTOSLEEP_BIT);
} }
uartclk = max310x_set_ref_clk(s); uartclk = max310x_set_ref_clk(s, freq, xtal);
dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk); dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
/* Register UART driver */ /* Register UART driver */
...@@ -1151,7 +1174,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, ...@@ -1151,7 +1174,7 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
ret = uart_register_driver(&s->uart); ret = uart_register_driver(&s->uart);
if (ret) { if (ret) {
dev_err(dev, "Registering UART driver failed\n"); dev_err(dev, "Registering UART driver failed\n");
return ret; goto out_clk;
} }
for (i = 0; i < devtype->nr; i++) { for (i = 0; i < devtype->nr; i++) {
...@@ -1208,19 +1231,19 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype, ...@@ -1208,19 +1231,19 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist, ret = devm_request_threaded_irq(dev, irq, NULL, max310x_ist,
IRQF_TRIGGER_FALLING | IRQF_ONESHOT, IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
dev_name(dev), s); dev_name(dev), s);
if (ret) { if (!ret)
return 0;
dev_err(dev, "Unable to reguest IRQ %i\n", irq); dev_err(dev, "Unable to reguest IRQ %i\n", irq);
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
if (s->gpio_used) if (s->gpio_used)
WARN_ON(gpiochip_remove(&s->gpio)); WARN_ON(gpiochip_remove(&s->gpio));
#endif #endif
}
return ret; out_clk:
clk_disable_unprepare(s->clk);
err_freq: return ret;
dev_err(dev, "Frequency parameter incorrect\n");
return -EINVAL;
} }
static int max310x_remove(struct device *dev) static int max310x_remove(struct device *dev)
...@@ -1236,6 +1259,7 @@ static int max310x_remove(struct device *dev) ...@@ -1236,6 +1259,7 @@ static int max310x_remove(struct device *dev)
} }
uart_unregister_driver(&s->uart); uart_unregister_driver(&s->uart);
clk_disable_unprepare(s->clk);
#ifdef CONFIG_GPIOLIB #ifdef CONFIG_GPIOLIB
if (s->gpio_used) if (s->gpio_used)
......
...@@ -20,9 +20,7 @@ ...@@ -20,9 +20,7 @@
* Example board initialization data: * Example board initialization data:
* *
* static struct max310x_pdata max3107_pdata = { * static struct max310x_pdata max3107_pdata = {
* .driver_flags = MAX310X_EXT_CLK,
* .uart_flags[0] = MAX310X_ECHO_SUPRESS | MAX310X_AUTO_DIR_CTRL, * .uart_flags[0] = MAX310X_ECHO_SUPRESS | MAX310X_AUTO_DIR_CTRL,
* .frequency = 3686400,
* .gpio_base = -1, * .gpio_base = -1,
* }; * };
* *
...@@ -41,17 +39,12 @@ ...@@ -41,17 +39,12 @@
/* MAX310X platform data structure */ /* MAX310X platform data structure */
struct max310x_pdata { struct max310x_pdata {
/* Flags global to driver */
const u8 driver_flags;
#define MAX310X_EXT_CLK (0x00000001) /* External clock enable */
/* Flags global to UART port */ /* Flags global to UART port */
const u8 uart_flags[MAX310X_MAX_UARTS]; const u8 uart_flags[MAX310X_MAX_UARTS];
#define MAX310X_ECHO_SUPRESS (0x00000002) /* Enable echo supress */ #define MAX310X_ECHO_SUPRESS (0x00000002) /* Enable echo supress */
#define MAX310X_AUTO_DIR_CTRL (0x00000004) /* Enable Auto direction #define MAX310X_AUTO_DIR_CTRL (0x00000004) /* Enable Auto direction
* control (RS-485) * control (RS-485)
*/ */
/* Frequency (extrenal clock or crystal) */
const int frequency;
/* GPIO base number (can be negative) */ /* GPIO base number (can be negative) */
const int gpio_base; const int gpio_base;
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment