Commit 74fe93ea authored by Hugo Villeneuve's avatar Hugo Villeneuve Committed by Greg Kroah-Hartman

serial: max310x: use common detect function for all variants

Simplify driver by defining a common function to handle the detection
of all variants.
Reviewed-by: default avatarAndy Shevchenko <andy.shevchenko@gmail.com>
Signed-off-by: default avatarHugo Villeneuve <hvilleneuve@dimonoff.com>
Link: https://lore.kernel.org/r/20240118152213.2644269-14-hugo@hugovil.comSigned-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 08ad4824
......@@ -67,6 +67,7 @@
#define MAX310X_BRGDIVMSB_REG (0x1d) /* Baud rate divisor MSB */
#define MAX310X_CLKSRC_REG (0x1e) /* Clock source */
#define MAX310X_REG_1F (0x1f)
#define MAX310X_EXTREG_START (0x20) /* Only relevant in SPI mode. */
#define MAX310X_REVID_REG MAX310X_REG_1F /* Revision ID */
......@@ -74,9 +75,9 @@
#define MAX310X_GLOBALCMD_REG MAX310X_REG_1F /* Global Command (WO) */
/* Extended registers */
#define MAX310X_SPI_REVID_EXTREG MAX310X_REG_05 /* Revision ID */
#define MAX310X_I2C_REVID_EXTREG (0x25) /* Revision ID */
#define MAX310X_REVID_EXTREG (0x25) /* Revision ID
* (extended addressing space)
*/
/* IRQ register bits */
#define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */
#define MAX310X_IRQ_SPCHR_BIT (1 << 1) /* Special char interrupt */
......@@ -250,8 +251,7 @@
struct max310x_if_cfg {
int (*extended_reg_enable)(struct device *dev, bool enable);
unsigned int rev_id_reg;
u8 rev_id_offset;
};
struct max310x_devtype {
......@@ -260,10 +260,11 @@ struct max310x_devtype {
unsigned short max;
} slave_addr;
int nr;
int (*detect)(struct device *);
void (*power)(struct uart_port *, int);
char name[9];
u8 mode1;
u8 rev_id_val;
u8 rev_id_reg; /* Relevant only if rev_id_val is defined. */
};
struct max310x_one {
......@@ -324,62 +325,52 @@ static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val)
regmap_update_bits(one->regmap, reg, mask, val);
}
static int max3107_detect(struct device *dev)
static int max310x_detect(struct device *dev)
{
struct max310x_port *s = dev_get_drvdata(dev);
unsigned int val = 0;
int ret;
ret = regmap_read(s->regmap, MAX310X_REVID_REG, &val);
if (ret)
return ret;
if (((val & MAX310x_REV_MASK) != MAX3107_REV_ID)) {
dev_err(dev,
"%s ID 0x%02x does not match\n", s->devtype->name, val);
return -ENODEV;
}
/* Check if variant supports REV ID register: */
if (s->devtype->rev_id_val) {
u8 rev_id_reg = s->devtype->rev_id_reg;
return 0;
}
/* Check if REV ID is in extended addressing space: */
if (s->devtype->rev_id_reg >= MAX310X_EXTREG_START) {
ret = s->if_cfg->extended_reg_enable(dev, true);
if (ret)
return ret;
static int max3108_detect(struct device *dev)
{
struct max310x_port *s = dev_get_drvdata(dev);
unsigned int val = 0;
int ret;
/* MAX3108 have not REV ID register, we just check default value
* from clocksource register to make sure everything works.
*/
ret = regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val);
if (ret)
return ret;
if (val != (MAX310X_CLKSRC_EXTCLK_BIT | MAX310X_CLKSRC_PLLBYP_BIT)) {
dev_err(dev, "%s not present\n", s->devtype->name);
return -ENODEV;
}
/* Adjust REV ID extended addressing space address: */
if (s->if_cfg->rev_id_offset)
rev_id_reg -= s->if_cfg->rev_id_offset;
}
return 0;
}
regmap_read(s->regmap, rev_id_reg, &val);
static int max3109_detect(struct device *dev)
{
struct max310x_port *s = dev_get_drvdata(dev);
unsigned int val = 0;
int ret;
if (s->devtype->rev_id_reg >= MAX310X_EXTREG_START) {
ret = s->if_cfg->extended_reg_enable(dev, false);
if (ret)
return ret;
}
ret = s->if_cfg->extended_reg_enable(dev, true);
if (ret)
return ret;
if (((val & MAX310x_REV_MASK) != s->devtype->rev_id_val))
return dev_err_probe(dev, -ENODEV,
"%s ID 0x%02x does not match\n",
s->devtype->name, val);
} else {
/*
* For variant without REV ID register, just check default value
* from clocksource register to make sure everything works.
*/
ret = regmap_read(s->regmap, MAX310X_CLKSRC_REG, &val);
if (ret)
return ret;
regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val);
s->if_cfg->extended_reg_enable(dev, false);
if (((val & MAX310x_REV_MASK) != MAX3109_REV_ID)) {
dev_err(dev,
"%s ID 0x%02x does not match\n", s->devtype->name, val);
return -ENODEV;
if (val != (MAX310X_CLKSRC_EXTCLK_BIT | MAX310X_CLKSRC_PLLBYP_BIT))
return dev_err_probe(dev, -ENODEV,
"%s not present\n",
s->devtype->name);
}
return 0;
......@@ -394,27 +385,6 @@ static void max310x_power(struct uart_port *port, int on)
msleep(50);
}
static int max14830_detect(struct device *dev)
{
struct max310x_port *s = dev_get_drvdata(dev);
unsigned int val = 0;
int ret;
ret = s->if_cfg->extended_reg_enable(dev, true);
if (ret)
return ret;
regmap_read(s->regmap, s->if_cfg->rev_id_reg, &val);
s->if_cfg->extended_reg_enable(dev, false);
if (((val & MAX310x_REV_MASK) != MAX14830_REV_ID)) {
dev_err(dev,
"%s ID 0x%02x does not match\n", s->devtype->name, val);
return -ENODEV;
}
return 0;
}
static void max14830_power(struct uart_port *port, int on)
{
max310x_port_update(port, MAX310X_BRGCFG_REG,
......@@ -428,7 +398,8 @@ static const struct max310x_devtype max3107_devtype = {
.name = "MAX3107",
.nr = 1,
.mode1 = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT,
.detect = max3107_detect,
.rev_id_val = MAX3107_REV_ID,
.rev_id_reg = MAX310X_REVID_REG,
.power = max310x_power,
.slave_addr = {
.min = 0x2c,
......@@ -440,7 +411,8 @@ static const struct max310x_devtype max3108_devtype = {
.name = "MAX3108",
.nr = 1,
.mode1 = MAX310X_MODE1_AUTOSLEEP_BIT,
.detect = max3108_detect,
.rev_id_val = 0, /* Unsupported. */
.rev_id_reg = 0, /* Irrelevant when rev_id_val is not defined. */
.power = max310x_power,
.slave_addr = {
.min = 0x60,
......@@ -452,7 +424,8 @@ static const struct max310x_devtype max3109_devtype = {
.name = "MAX3109",
.nr = 2,
.mode1 = MAX310X_MODE1_AUTOSLEEP_BIT,
.detect = max3109_detect,
.rev_id_val = MAX3109_REV_ID,
.rev_id_reg = MAX310X_REVID_EXTREG,
.power = max310x_power,
.slave_addr = {
.min = 0x60,
......@@ -464,7 +437,8 @@ static const struct max310x_devtype max14830_devtype = {
.name = "MAX14830",
.nr = 4,
.mode1 = MAX310X_MODE1_IRQSEL_BIT,
.detect = max14830_detect,
.rev_id_val = MAX14830_REV_ID,
.rev_id_reg = MAX310X_REVID_EXTREG,
.power = max14830_power,
.slave_addr = {
.min = 0x60,
......@@ -1322,7 +1296,7 @@ static int max310x_probe(struct device *dev, const struct max310x_devtype *devty
dev_set_drvdata(dev, s);
/* Check device to ensure we are talking to what we expect */
ret = devtype->detect(dev);
ret = max310x_detect(dev);
if (ret)
goto out_clk;
......@@ -1501,7 +1475,7 @@ static int max310x_spi_extended_reg_enable(struct device *dev, bool enable)
static const struct max310x_if_cfg __maybe_unused max310x_spi_if_cfg = {
.extended_reg_enable = max310x_spi_extended_reg_enable,
.rev_id_reg = MAX310X_SPI_REVID_EXTREG,
.rev_id_offset = MAX310X_EXTREG_START,
};
static int max310x_spi_probe(struct spi_device *spi)
......@@ -1574,7 +1548,7 @@ static struct regmap_config regcfg_i2c = {
.writeable_reg = max310x_reg_writeable,
.volatile_reg = max310x_reg_volatile,
.precious_reg = max310x_reg_precious,
.max_register = MAX310X_I2C_REVID_EXTREG,
.max_register = MAX310X_REVID_EXTREG,
.writeable_noinc_reg = max310x_reg_noinc,
.readable_noinc_reg = max310x_reg_noinc,
.max_raw_read = MAX310X_FIFO_SIZE,
......@@ -1583,7 +1557,7 @@ static struct regmap_config regcfg_i2c = {
static const struct max310x_if_cfg max310x_i2c_if_cfg = {
.extended_reg_enable = max310x_i2c_extended_reg_enable,
.rev_id_reg = MAX310X_I2C_REVID_EXTREG,
.rev_id_offset = 0, /* No offset in I2C mode. */
};
static unsigned short max310x_i2c_slave_addr(unsigned short addr,
......
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