|
@@ -14,9 +14,10 @@
|
|
|
#include <linux/delay.h>
|
|
|
#include <linux/device.h>
|
|
|
#include <linux/gpio/driver.h>
|
|
|
+#include <linux/i2c.h>
|
|
|
#include <linux/module.h>
|
|
|
-#include <linux/of.h>
|
|
|
-#include <linux/of_device.h>
|
|
|
+#include <linux/mod_devicetable.h>
|
|
|
+#include <linux/property.h>
|
|
|
#include <linux/regmap.h>
|
|
|
#include <linux/serial_core.h>
|
|
|
#include <linux/serial.h>
|
|
@@ -72,7 +73,8 @@
|
|
|
#define MAX310X_GLOBALCMD_REG MAX310X_REG_1F /* Global Command (WO) */
|
|
|
|
|
|
/* Extended registers */
|
|
|
-#define MAX310X_REVID_EXTREG MAX310X_REG_05 /* Revision ID */
|
|
|
+#define MAX310X_SPI_REVID_EXTREG MAX310X_REG_05 /* Revision ID */
|
|
|
+#define MAX310X_I2C_REVID_EXTREG (0x25) /* Revision ID */
|
|
|
|
|
|
/* IRQ register bits */
|
|
|
#define MAX310X_IRQ_LSR_BIT (1 << 0) /* LSR interrupt */
|
|
@@ -235,6 +237,10 @@
|
|
|
#define MAX310x_REV_MASK (0xf8)
|
|
|
#define MAX310X_WRITE_BIT 0x80
|
|
|
|
|
|
+/* Port startup definitions */
|
|
|
+#define MAX310X_PORT_STARTUP_WAIT_RETRIES 20 /* Number of retries */
|
|
|
+#define MAX310X_PORT_STARTUP_WAIT_DELAY_MS 10 /* Delay between retries */
|
|
|
+
|
|
|
/* Crystal-related definitions */
|
|
|
#define MAX310X_XTAL_WAIT_RETRIES 20 /* Number of retries */
|
|
|
#define MAX310X_XTAL_WAIT_DELAY_MS 10 /* Delay between retries */
|
|
@@ -249,7 +255,17 @@
|
|
|
#define MAX14830_BRGCFG_CLKDIS_BIT (1 << 6) /* Clock Disable */
|
|
|
#define MAX14830_REV_ID (0xb0)
|
|
|
|
|
|
+struct max310x_if_cfg {
|
|
|
+ int (*extended_reg_enable)(struct device *dev, bool enable);
|
|
|
+
|
|
|
+ unsigned int rev_id_reg;
|
|
|
+};
|
|
|
+
|
|
|
struct max310x_devtype {
|
|
|
+ struct {
|
|
|
+ unsigned short min;
|
|
|
+ unsigned short max;
|
|
|
+ } slave_addr;
|
|
|
char name[9];
|
|
|
int nr;
|
|
|
u8 mode1;
|
|
@@ -262,16 +278,16 @@ struct max310x_one {
|
|
|
struct work_struct tx_work;
|
|
|
struct work_struct md_work;
|
|
|
struct work_struct rs_work;
|
|
|
+ struct regmap *regmap;
|
|
|
|
|
|
- u8 wr_header;
|
|
|
- u8 rd_header;
|
|
|
u8 rx_buf[MAX310X_FIFO_SIZE];
|
|
|
};
|
|
|
#define to_max310x_port(_port) \
|
|
|
container_of(_port, struct max310x_one, port)
|
|
|
|
|
|
struct max310x_port {
|
|
|
- struct max310x_devtype *devtype;
|
|
|
+ const struct max310x_devtype *devtype;
|
|
|
+ const struct max310x_if_cfg *if_cfg;
|
|
|
struct regmap *regmap;
|
|
|
struct clk *clk;
|
|
|
#ifdef CONFIG_GPIOLIB
|
|
@@ -293,26 +309,26 @@ static DECLARE_BITMAP(max310x_lines, MAX310X_UART_NRMAX);
|
|
|
|
|
|
static u8 max310x_port_read(struct uart_port *port, u8 reg)
|
|
|
{
|
|
|
- struct max310x_port *s = dev_get_drvdata(port->dev);
|
|
|
+ struct max310x_one *one = to_max310x_port(port);
|
|
|
unsigned int val = 0;
|
|
|
|
|
|
- regmap_read(s->regmap, port->iobase + reg, &val);
|
|
|
+ regmap_read(one->regmap, reg, &val);
|
|
|
|
|
|
return val;
|
|
|
}
|
|
|
|
|
|
static void max310x_port_write(struct uart_port *port, u8 reg, u8 val)
|
|
|
{
|
|
|
- struct max310x_port *s = dev_get_drvdata(port->dev);
|
|
|
+ struct max310x_one *one = to_max310x_port(port);
|
|
|
|
|
|
- regmap_write(s->regmap, port->iobase + reg, val);
|
|
|
+ regmap_write(one->regmap, reg, val);
|
|
|
}
|
|
|
|
|
|
static void max310x_port_update(struct uart_port *port, u8 reg, u8 mask, u8 val)
|
|
|
{
|
|
|
- struct max310x_port *s = dev_get_drvdata(port->dev);
|
|
|
+ struct max310x_one *one = to_max310x_port(port);
|
|
|
|
|
|
- regmap_update_bits(s->regmap, port->iobase + reg, mask, val);
|
|
|
+ regmap_update_bits(one->regmap, reg, mask, val);
|
|
|
}
|
|
|
|
|
|
static int max3107_detect(struct device *dev)
|
|
@@ -361,13 +377,12 @@ static int max3109_detect(struct device *dev)
|
|
|
unsigned int val = 0;
|
|
|
int ret;
|
|
|
|
|
|
- ret = regmap_write(s->regmap, MAX310X_GLOBALCMD_REG,
|
|
|
- MAX310X_EXTREG_ENBL);
|
|
|
+ ret = s->if_cfg->extended_reg_enable(dev, true);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- regmap_read(s->regmap, MAX310X_REVID_EXTREG, &val);
|
|
|
- regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, MAX310X_EXTREG_DSBL);
|
|
|
+ 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);
|
|
@@ -392,13 +407,12 @@ static int max14830_detect(struct device *dev)
|
|
|
unsigned int val = 0;
|
|
|
int ret;
|
|
|
|
|
|
- ret = regmap_write(s->regmap, MAX310X_GLOBALCMD_REG,
|
|
|
- MAX310X_EXTREG_ENBL);
|
|
|
+ ret = s->if_cfg->extended_reg_enable(dev, true);
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- regmap_read(s->regmap, MAX310X_REVID_EXTREG, &val);
|
|
|
- regmap_write(s->regmap, MAX310X_GLOBALCMD_REG, MAX310X_EXTREG_DSBL);
|
|
|
+ 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);
|
|
@@ -423,6 +437,10 @@ static const struct max310x_devtype max3107_devtype = {
|
|
|
.mode1 = MAX310X_MODE1_AUTOSLEEP_BIT | MAX310X_MODE1_IRQSEL_BIT,
|
|
|
.detect = max3107_detect,
|
|
|
.power = max310x_power,
|
|
|
+ .slave_addr = {
|
|
|
+ .min = 0x2c,
|
|
|
+ .max = 0x2f,
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
static const struct max310x_devtype max3108_devtype = {
|
|
@@ -431,6 +449,10 @@ static const struct max310x_devtype max3108_devtype = {
|
|
|
.mode1 = MAX310X_MODE1_AUTOSLEEP_BIT,
|
|
|
.detect = max3108_detect,
|
|
|
.power = max310x_power,
|
|
|
+ .slave_addr = {
|
|
|
+ .min = 0x60,
|
|
|
+ .max = 0x6f,
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
static const struct max310x_devtype max3109_devtype = {
|
|
@@ -439,6 +461,10 @@ static const struct max310x_devtype max3109_devtype = {
|
|
|
.mode1 = MAX310X_MODE1_AUTOSLEEP_BIT,
|
|
|
.detect = max3109_detect,
|
|
|
.power = max310x_power,
|
|
|
+ .slave_addr = {
|
|
|
+ .min = 0x60,
|
|
|
+ .max = 0x6f,
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
static const struct max310x_devtype max14830_devtype = {
|
|
@@ -447,11 +473,15 @@ static const struct max310x_devtype max14830_devtype = {
|
|
|
.mode1 = MAX310X_MODE1_IRQSEL_BIT,
|
|
|
.detect = max14830_detect,
|
|
|
.power = max14830_power,
|
|
|
+ .slave_addr = {
|
|
|
+ .min = 0x60,
|
|
|
+ .max = 0x6f,
|
|
|
+ },
|
|
|
};
|
|
|
|
|
|
static bool max310x_reg_writeable(struct device *dev, unsigned int reg)
|
|
|
{
|
|
|
- switch (reg & 0x1f) {
|
|
|
+ switch (reg) {
|
|
|
case MAX310X_IRQSTS_REG:
|
|
|
case MAX310X_LSR_IRQSTS_REG:
|
|
|
case MAX310X_SPCHR_IRQSTS_REG:
|
|
@@ -468,7 +498,7 @@ static bool max310x_reg_writeable(struct device *dev, unsigned int reg)
|
|
|
|
|
|
static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
|
|
|
{
|
|
|
- switch (reg & 0x1f) {
|
|
|
+ switch (reg) {
|
|
|
case MAX310X_RHR_REG:
|
|
|
case MAX310X_IRQSTS_REG:
|
|
|
case MAX310X_LSR_IRQSTS_REG:
|
|
@@ -490,7 +520,7 @@ static bool max310x_reg_volatile(struct device *dev, unsigned int reg)
|
|
|
|
|
|
static bool max310x_reg_precious(struct device *dev, unsigned int reg)
|
|
|
{
|
|
|
- switch (reg & 0x1f) {
|
|
|
+ switch (reg) {
|
|
|
case MAX310X_RHR_REG:
|
|
|
case MAX310X_IRQSTS_REG:
|
|
|
case MAX310X_SPCHR_IRQSTS_REG:
|
|
@@ -503,6 +533,11 @@ static bool max310x_reg_precious(struct device *dev, unsigned int reg)
|
|
|
return false;
|
|
|
}
|
|
|
|
|
|
+static bool max310x_reg_noinc(struct device *dev, unsigned int reg)
|
|
|
+{
|
|
|
+ return reg == MAX310X_RHR_REG;
|
|
|
+}
|
|
|
+
|
|
|
static int max310x_set_baud(struct uart_port *port, int baud)
|
|
|
{
|
|
|
unsigned int mode = 0, div = 0, frac = 0, c = 0, F = 0;
|
|
@@ -556,7 +591,7 @@ static int max310x_update_best_err(unsigned long f, long *besterr)
|
|
|
return 1;
|
|
|
}
|
|
|
|
|
|
-static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
|
|
|
+static s32 max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
|
|
|
unsigned long freq, bool xtal)
|
|
|
{
|
|
|
unsigned int div, clksrc, pllcfg = 0;
|
|
@@ -626,40 +661,25 @@ static int max310x_set_ref_clk(struct device *dev, struct max310x_port *s,
|
|
|
} while (!stable && (++try < MAX310X_XTAL_WAIT_RETRIES));
|
|
|
|
|
|
if (!stable)
|
|
|
- dev_warn(dev, "clock is not stable yet\n");
|
|
|
+ return dev_err_probe(dev, -EAGAIN,
|
|
|
+ "clock is not stable\n");
|
|
|
}
|
|
|
|
|
|
- return (int)bestfreq;
|
|
|
+ return bestfreq;
|
|
|
}
|
|
|
|
|
|
static void max310x_batch_write(struct uart_port *port, u8 *txbuf, unsigned int len)
|
|
|
{
|
|
|
struct max310x_one *one = to_max310x_port(port);
|
|
|
- struct spi_transfer xfer[] = {
|
|
|
- {
|
|
|
- .tx_buf = &one->wr_header,
|
|
|
- .len = sizeof(one->wr_header),
|
|
|
- }, {
|
|
|
- .tx_buf = txbuf,
|
|
|
- .len = len,
|
|
|
- }
|
|
|
- };
|
|
|
- spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer));
|
|
|
+
|
|
|
+ regmap_noinc_write(one->regmap, MAX310X_THR_REG, txbuf, len);
|
|
|
}
|
|
|
|
|
|
static void max310x_batch_read(struct uart_port *port, u8 *rxbuf, unsigned int len)
|
|
|
{
|
|
|
struct max310x_one *one = to_max310x_port(port);
|
|
|
- struct spi_transfer xfer[] = {
|
|
|
- {
|
|
|
- .tx_buf = &one->rd_header,
|
|
|
- .len = sizeof(one->rd_header),
|
|
|
- }, {
|
|
|
- .rx_buf = rxbuf,
|
|
|
- .len = len,
|
|
|
- }
|
|
|
- };
|
|
|
- spi_sync_transfer(to_spi_device(port->dev), xfer, ARRAY_SIZE(xfer));
|
|
|
+
|
|
|
+ regmap_noinc_read(one->regmap, MAX310X_RHR_REG, rxbuf, len);
|
|
|
}
|
|
|
|
|
|
static void max310x_handle_rx(struct uart_port *port, unsigned int rxlen)
|
|
@@ -1261,16 +1281,18 @@ static int max310x_gpio_set_config(struct gpio_chip *chip, unsigned int offset,
|
|
|
}
|
|
|
#endif
|
|
|
|
|
|
-static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
|
|
- struct regmap *regmap, int irq)
|
|
|
+static int max310x_probe(struct device *dev, const struct max310x_devtype *devtype,
|
|
|
+ const struct max310x_if_cfg *if_cfg,
|
|
|
+ struct regmap *regmaps[], int irq)
|
|
|
{
|
|
|
- int i, ret, fmin, fmax, freq, uartclk;
|
|
|
- struct clk *clk_osc, *clk_xtal;
|
|
|
+ int i, ret, fmin, fmax, freq;
|
|
|
struct max310x_port *s;
|
|
|
- bool xtal = false;
|
|
|
+ s32 uartclk = 0;
|
|
|
+ bool xtal;
|
|
|
|
|
|
- if (IS_ERR(regmap))
|
|
|
- return PTR_ERR(regmap);
|
|
|
+ for (i = 0; i < devtype->nr; i++)
|
|
|
+ if (IS_ERR(regmaps[i]))
|
|
|
+ return PTR_ERR(regmaps[i]);
|
|
|
|
|
|
/* Alloc port structure */
|
|
|
s = devm_kzalloc(dev, struct_size(s, p, devtype->nr), GFP_KERNEL);
|
|
@@ -1279,23 +1301,20 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- clk_osc = devm_clk_get(dev, "osc");
|
|
|
- clk_xtal = devm_clk_get(dev, "xtal");
|
|
|
- if (!IS_ERR(clk_osc)) {
|
|
|
- s->clk = clk_osc;
|
|
|
- fmin = 500000;
|
|
|
- fmax = 35000000;
|
|
|
- } else if (!IS_ERR(clk_xtal)) {
|
|
|
- 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;
|
|
|
+ /* Always ask for fixed clock rate from a property. */
|
|
|
+ device_property_read_u32(dev, "clock-frequency", &uartclk);
|
|
|
+
|
|
|
+ s->clk = devm_clk_get_optional(dev, "osc");
|
|
|
+ if (IS_ERR(s->clk))
|
|
|
+ return PTR_ERR(s->clk);
|
|
|
+ if (s->clk) {
|
|
|
+ xtal = false;
|
|
|
} else {
|
|
|
- dev_err(dev, "Cannot get clock\n");
|
|
|
- return -EINVAL;
|
|
|
+ s->clk = devm_clk_get_optional(dev, "xtal");
|
|
|
+ if (IS_ERR(s->clk))
|
|
|
+ return PTR_ERR(s->clk);
|
|
|
+
|
|
|
+ xtal = true;
|
|
|
}
|
|
|
|
|
|
ret = clk_prepare_enable(s->clk);
|
|
@@ -1303,14 +1322,31 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
|
|
return ret;
|
|
|
|
|
|
freq = clk_get_rate(s->clk);
|
|
|
+ if (freq == 0)
|
|
|
+ freq = uartclk;
|
|
|
+ if (freq == 0) {
|
|
|
+ dev_err(dev, "Cannot get clock rate\n");
|
|
|
+ ret = -EINVAL;
|
|
|
+ goto out_clk;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (xtal) {
|
|
|
+ fmin = 1000000;
|
|
|
+ fmax = 4000000;
|
|
|
+ } else {
|
|
|
+ fmin = 500000;
|
|
|
+ fmax = 35000000;
|
|
|
+ }
|
|
|
+
|
|
|
/* Check frequency limits */
|
|
|
if (freq < fmin || freq > fmax) {
|
|
|
ret = -ERANGE;
|
|
|
goto out_clk;
|
|
|
}
|
|
|
|
|
|
- s->regmap = regmap;
|
|
|
+ s->regmap = regmaps[0];
|
|
|
s->devtype = devtype;
|
|
|
+ s->if_cfg = if_cfg;
|
|
|
dev_set_drvdata(dev, s);
|
|
|
|
|
|
/* Check device to ensure we are talking to what we expect */
|
|
@@ -1319,25 +1355,38 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
|
|
goto out_clk;
|
|
|
|
|
|
for (i = 0; i < devtype->nr; i++) {
|
|
|
- unsigned int offs = i << 5;
|
|
|
+ bool started = false;
|
|
|
+ unsigned int try = 0, val = 0;
|
|
|
|
|
|
/* Reset port */
|
|
|
- regmap_write(s->regmap, MAX310X_MODE2_REG + offs,
|
|
|
+ regmap_write(regmaps[i], MAX310X_MODE2_REG,
|
|
|
MAX310X_MODE2_RST_BIT);
|
|
|
/* Clear port reset */
|
|
|
- regmap_write(s->regmap, MAX310X_MODE2_REG + offs, 0);
|
|
|
+ regmap_write(regmaps[i], MAX310X_MODE2_REG, 0);
|
|
|
|
|
|
/* Wait for port startup */
|
|
|
do {
|
|
|
- regmap_read(s->regmap,
|
|
|
- MAX310X_BRGDIVLSB_REG + offs, &ret);
|
|
|
- } while (ret != 0x01);
|
|
|
+ msleep(MAX310X_PORT_STARTUP_WAIT_DELAY_MS);
|
|
|
+ regmap_read(regmaps[i], MAX310X_BRGDIVLSB_REG, &val);
|
|
|
|
|
|
- regmap_write(s->regmap, MAX310X_MODE1_REG + offs,
|
|
|
- devtype->mode1);
|
|
|
+ if (val == 0x01)
|
|
|
+ started = true;
|
|
|
+ } while (!started && (++try < MAX310X_PORT_STARTUP_WAIT_RETRIES));
|
|
|
+
|
|
|
+ if (!started) {
|
|
|
+ ret = dev_err_probe(dev, -EAGAIN, "port reset failed\n");
|
|
|
+ goto out_uart;
|
|
|
+ }
|
|
|
+
|
|
|
+ regmap_write(regmaps[i], MAX310X_MODE1_REG, devtype->mode1);
|
|
|
}
|
|
|
|
|
|
uartclk = max310x_set_ref_clk(dev, s, freq, xtal);
|
|
|
+ if (uartclk < 0) {
|
|
|
+ ret = uartclk;
|
|
|
+ goto out_uart;
|
|
|
+ }
|
|
|
+
|
|
|
dev_dbg(dev, "Reference clock set to %i Hz\n", uartclk);
|
|
|
|
|
|
for (i = 0; i < devtype->nr; i++) {
|
|
@@ -1357,11 +1406,13 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
|
|
s->p[i].port.fifosize = MAX310X_FIFO_SIZE;
|
|
|
s->p[i].port.flags = UPF_FIXED_TYPE | UPF_LOW_LATENCY;
|
|
|
s->p[i].port.iotype = UPIO_PORT;
|
|
|
- s->p[i].port.iobase = i * 0x20;
|
|
|
+ s->p[i].port.iobase = i;
|
|
|
s->p[i].port.membase = (void __iomem *)~0;
|
|
|
s->p[i].port.uartclk = uartclk;
|
|
|
s->p[i].port.rs485_config = max310x_rs485_config;
|
|
|
s->p[i].port.ops = &max310x_ops;
|
|
|
+ s->p[i].regmap = regmaps[i];
|
|
|
+
|
|
|
/* Disable all interrupts */
|
|
|
max310x_port_write(&s->p[i].port, MAX310X_IRQEN_REG, 0);
|
|
|
/* Clear IRQ status register */
|
|
@@ -1372,10 +1423,6 @@ static int max310x_probe(struct device *dev, struct max310x_devtype *devtype,
|
|
|
INIT_WORK(&s->p[i].md_work, max310x_md_proc);
|
|
|
/* Initialize queue for changing RS485 mode */
|
|
|
INIT_WORK(&s->p[i].rs_work, max310x_rs_proc);
|
|
|
- /* Initialize SPI-transfer buffers */
|
|
|
- s->p[i].wr_header = (s->p[i].port.iobase + MAX310X_THR_REG) |
|
|
|
- MAX310X_WRITE_BIT;
|
|
|
- s->p[i].rd_header = (s->p[i].port.iobase + MAX310X_RHR_REG);
|
|
|
|
|
|
/* Register port */
|
|
|
ret = uart_add_one_port(&max310x_uart, &s->p[i].port);
|
|
@@ -1462,16 +1509,35 @@ static struct regmap_config regcfg = {
|
|
|
.val_bits = 8,
|
|
|
.write_flag_mask = MAX310X_WRITE_BIT,
|
|
|
.cache_type = REGCACHE_RBTREE,
|
|
|
+ .max_register = MAX310X_REG_1F,
|
|
|
.writeable_reg = max310x_reg_writeable,
|
|
|
.volatile_reg = max310x_reg_volatile,
|
|
|
.precious_reg = max310x_reg_precious,
|
|
|
+ .writeable_noinc_reg = max310x_reg_noinc,
|
|
|
+ .readable_noinc_reg = max310x_reg_noinc,
|
|
|
+ .max_raw_read = MAX310X_FIFO_SIZE,
|
|
|
+ .max_raw_write = MAX310X_FIFO_SIZE,
|
|
|
};
|
|
|
|
|
|
#ifdef CONFIG_SPI_MASTER
|
|
|
+static int max310x_spi_extended_reg_enable(struct device *dev, bool enable)
|
|
|
+{
|
|
|
+ struct max310x_port *s = dev_get_drvdata(dev);
|
|
|
+
|
|
|
+ return regmap_write(s->regmap, MAX310X_GLOBALCMD_REG,
|
|
|
+ enable ? MAX310X_EXTREG_ENBL : MAX310X_EXTREG_DSBL);
|
|
|
+}
|
|
|
+
|
|
|
+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,
|
|
|
+};
|
|
|
+
|
|
|
static int max310x_spi_probe(struct spi_device *spi)
|
|
|
{
|
|
|
- struct max310x_devtype *devtype;
|
|
|
- struct regmap *regmap;
|
|
|
+ const struct max310x_devtype *devtype;
|
|
|
+ struct regmap *regmaps[4];
|
|
|
+ unsigned int i;
|
|
|
int ret;
|
|
|
|
|
|
/* Setup SPI bus */
|
|
@@ -1482,23 +1548,18 @@ static int max310x_spi_probe(struct spi_device *spi)
|
|
|
if (ret)
|
|
|
return ret;
|
|
|
|
|
|
- if (spi->dev.of_node) {
|
|
|
- const struct of_device_id *of_id =
|
|
|
- of_match_device(max310x_dt_ids, &spi->dev);
|
|
|
- if (!of_id)
|
|
|
- return -ENODEV;
|
|
|
-
|
|
|
- devtype = (struct max310x_devtype *)of_id->data;
|
|
|
- } else {
|
|
|
- const struct spi_device_id *id_entry = spi_get_device_id(spi);
|
|
|
+ devtype = device_get_match_data(&spi->dev);
|
|
|
+ if (!devtype)
|
|
|
+ devtype = (struct max310x_devtype *)spi_get_device_id(spi)->driver_data;
|
|
|
|
|
|
- devtype = (struct max310x_devtype *)id_entry->driver_data;
|
|
|
+ for (i = 0; i < devtype->nr; i++) {
|
|
|
+ u8 port_mask = i * 0x20;
|
|
|
+ regcfg.read_flag_mask = port_mask;
|
|
|
+ regcfg.write_flag_mask = port_mask | MAX310X_WRITE_BIT;
|
|
|
+ regmaps[i] = devm_regmap_init_spi(spi, ®cfg);
|
|
|
}
|
|
|
|
|
|
- regcfg.max_register = devtype->nr * 0x20 - 1;
|
|
|
- regmap = devm_regmap_init_spi(spi, ®cfg);
|
|
|
-
|
|
|
- return max310x_probe(&spi->dev, devtype, regmap, spi->irq);
|
|
|
+ return max310x_probe(&spi->dev, devtype, &max310x_spi_if_cfg, regmaps, spi->irq);
|
|
|
}
|
|
|
|
|
|
static int max310x_spi_remove(struct spi_device *spi)
|
|
@@ -1518,7 +1579,7 @@ MODULE_DEVICE_TABLE(spi, max310x_id_table);
|
|
|
static struct spi_driver max310x_spi_driver = {
|
|
|
.driver = {
|
|
|
.name = MAX310X_NAME,
|
|
|
- .of_match_table = of_match_ptr(max310x_dt_ids),
|
|
|
+ .of_match_table = max310x_dt_ids,
|
|
|
.pm = &max310x_pm_ops,
|
|
|
},
|
|
|
.probe = max310x_spi_probe,
|
|
@@ -1527,6 +1588,101 @@ static struct spi_driver max310x_spi_driver = {
|
|
|
};
|
|
|
#endif
|
|
|
|
|
|
+#ifdef CONFIG_I2C
|
|
|
+static int max310x_i2c_extended_reg_enable(struct device *dev, bool enable)
|
|
|
+{
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct regmap_config regcfg_i2c = {
|
|
|
+ .reg_bits = 8,
|
|
|
+ .val_bits = 8,
|
|
|
+ .cache_type = REGCACHE_RBTREE,
|
|
|
+ .writeable_reg = max310x_reg_writeable,
|
|
|
+ .volatile_reg = max310x_reg_volatile,
|
|
|
+ .precious_reg = max310x_reg_precious,
|
|
|
+ .max_register = MAX310X_I2C_REVID_EXTREG,
|
|
|
+ .writeable_noinc_reg = max310x_reg_noinc,
|
|
|
+ .readable_noinc_reg = max310x_reg_noinc,
|
|
|
+ .max_raw_read = MAX310X_FIFO_SIZE,
|
|
|
+ .max_raw_write = MAX310X_FIFO_SIZE,
|
|
|
+};
|
|
|
+
|
|
|
+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,
|
|
|
+};
|
|
|
+
|
|
|
+static unsigned short max310x_i2c_slave_addr(unsigned short addr,
|
|
|
+ unsigned int nr)
|
|
|
+{
|
|
|
+ /*
|
|
|
+ * For MAX14830 and MAX3109, the slave address depends on what the
|
|
|
+ * A0 and A1 pins are tied to.
|
|
|
+ * See Table I2C Address Map of the datasheet.
|
|
|
+ * Based on that table, the following formulas were determined.
|
|
|
+ * UART1 - UART0 = 0x10
|
|
|
+ * UART2 - UART1 = 0x20 + 0x10
|
|
|
+ * UART3 - UART2 = 0x10
|
|
|
+ */
|
|
|
+
|
|
|
+ addr -= nr * 0x10;
|
|
|
+
|
|
|
+ if (nr >= 2)
|
|
|
+ addr -= 0x20;
|
|
|
+
|
|
|
+ return addr;
|
|
|
+}
|
|
|
+
|
|
|
+static int max310x_i2c_probe(struct i2c_client *client)
|
|
|
+{
|
|
|
+ const struct max310x_devtype *devtype =
|
|
|
+ device_get_match_data(&client->dev);
|
|
|
+ struct i2c_client *port_client;
|
|
|
+ struct regmap *regmaps[4];
|
|
|
+ unsigned int i;
|
|
|
+ u8 port_addr;
|
|
|
+
|
|
|
+ if (client->addr < devtype->slave_addr.min ||
|
|
|
+ client->addr > devtype->slave_addr.max)
|
|
|
+ return dev_err_probe(&client->dev, -EINVAL,
|
|
|
+ "Slave addr 0x%x outside of range [0x%x, 0x%x]\n",
|
|
|
+ client->addr, devtype->slave_addr.min,
|
|
|
+ devtype->slave_addr.max);
|
|
|
+
|
|
|
+ regmaps[0] = devm_regmap_init_i2c(client, ®cfg_i2c);
|
|
|
+
|
|
|
+ for (i = 1; i < devtype->nr; i++) {
|
|
|
+ port_addr = max310x_i2c_slave_addr(client->addr, i);
|
|
|
+ port_client = devm_i2c_new_dummy_device(&client->dev,
|
|
|
+ client->adapter,
|
|
|
+ port_addr);
|
|
|
+
|
|
|
+ regmaps[i] = devm_regmap_init_i2c(port_client, ®cfg_i2c);
|
|
|
+ }
|
|
|
+
|
|
|
+ return max310x_probe(&client->dev, devtype, &max310x_i2c_if_cfg,
|
|
|
+ regmaps, client->irq);
|
|
|
+}
|
|
|
+
|
|
|
+static int max310x_i2c_remove(struct i2c_client *client)
|
|
|
+{
|
|
|
+ max310x_remove(&client->dev);
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
+static struct i2c_driver max310x_i2c_driver = {
|
|
|
+ .driver = {
|
|
|
+ .name = MAX310X_NAME,
|
|
|
+ .of_match_table = max310x_dt_ids,
|
|
|
+ .pm = &max310x_pm_ops,
|
|
|
+ },
|
|
|
+ .probe_new = max310x_i2c_probe,
|
|
|
+ .remove = max310x_i2c_remove,
|
|
|
+};
|
|
|
+#endif
|
|
|
+
|
|
|
static int __init max310x_uart_init(void)
|
|
|
{
|
|
|
int ret;
|
|
@@ -1540,15 +1696,35 @@ static int __init max310x_uart_init(void)
|
|
|
#ifdef CONFIG_SPI_MASTER
|
|
|
ret = spi_register_driver(&max310x_spi_driver);
|
|
|
if (ret)
|
|
|
- uart_unregister_driver(&max310x_uart);
|
|
|
+ goto err_spi_register;
|
|
|
+#endif
|
|
|
+
|
|
|
+#ifdef CONFIG_I2C
|
|
|
+ ret = i2c_add_driver(&max310x_i2c_driver);
|
|
|
+ if (ret)
|
|
|
+ goto err_i2c_register;
|
|
|
+#endif
|
|
|
+
|
|
|
+ return 0;
|
|
|
+
|
|
|
+#ifdef CONFIG_I2C
|
|
|
+err_i2c_register:
|
|
|
+ spi_unregister_driver(&max310x_spi_driver);
|
|
|
#endif
|
|
|
|
|
|
+err_spi_register:
|
|
|
+ uart_unregister_driver(&max310x_uart);
|
|
|
+
|
|
|
return ret;
|
|
|
}
|
|
|
module_init(max310x_uart_init);
|
|
|
|
|
|
static void __exit max310x_uart_exit(void)
|
|
|
{
|
|
|
+#ifdef CONFIG_I2C
|
|
|
+ i2c_del_driver(&max310x_i2c_driver);
|
|
|
+#endif
|
|
|
+
|
|
|
#ifdef CONFIG_SPI_MASTER
|
|
|
spi_unregister_driver(&max310x_spi_driver);
|
|
|
#endif
|