12bbd681bSSubhendu Sekhar Behera /* 22bbd681bSSubhendu Sekhar Behera * Copyright (c) 2003-2015 Broadcom Corporation 32bbd681bSSubhendu Sekhar Behera * 42bbd681bSSubhendu Sekhar Behera * This file is licensed under the terms of the GNU General Public 52bbd681bSSubhendu Sekhar Behera * License version 2. This program is licensed "as is" without any 62bbd681bSSubhendu Sekhar Behera * warranty of any kind, whether express or implied. 72bbd681bSSubhendu Sekhar Behera */ 82bbd681bSSubhendu Sekhar Behera 9748c0bbbSTanmay Jagdale #include <linux/acpi.h> 10c347b8fcSJayachandran C #include <linux/clk.h> 112bbd681bSSubhendu Sekhar Behera #include <linux/completion.h> 122bbd681bSSubhendu Sekhar Behera #include <linux/i2c.h> 1340f4e372SGeorge Cherian #include <linux/i2c-smbus.h> 142bbd681bSSubhendu Sekhar Behera #include <linux/init.h> 152bbd681bSSubhendu Sekhar Behera #include <linux/interrupt.h> 162bbd681bSSubhendu Sekhar Behera #include <linux/io.h> 172bbd681bSSubhendu Sekhar Behera #include <linux/kernel.h> 182bbd681bSSubhendu Sekhar Behera #include <linux/module.h> 192bbd681bSSubhendu Sekhar Behera #include <linux/platform_device.h> 20d3898a78SGeorge Cherian #include <linux/delay.h> 212bbd681bSSubhendu Sekhar Behera 222bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_DIV 0x0 232bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CTRL 0x1 242bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CMD 0x2 252bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_STATUS 0x3 262bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_MTXFIFO 0x4 272bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_MRXFIFO 0x5 282bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_MFIFOCTRL 0x6 292bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_STXFIFO 0x7 302bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_SRXFIFO 0x8 312bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_SFIFOCTRL 0x9 322bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_SLAVEADDR 0xA 332bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_OWNADDR 0xB 342bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_FIFOWCNT 0xC 352bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_INTEN 0xD 362bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_INTST 0xE 372bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_WAITCNT 0xF 382bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_TIMEOUT 0X10 392bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_GENCALLADDR 0x11 402bbd681bSSubhendu Sekhar Behera 41d3898a78SGeorge Cherian #define XLP9XX_I2C_STATUS_BUSY BIT(0) 42d3898a78SGeorge Cherian 432bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CMD_START BIT(7) 442bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CMD_STOP BIT(6) 452bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CMD_READ BIT(5) 462bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CMD_WRITE BIT(4) 472bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CMD_ACK BIT(3) 482bbd681bSSubhendu Sekhar Behera 492bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CTRL_MCTLEN_SHIFT 16 502bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CTRL_MCTLEN_MASK 0xffff0000 512bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CTRL_RST BIT(8) 522bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CTRL_EN BIT(6) 532bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CTRL_MASTER BIT(4) 542bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CTRL_FIFORD BIT(1) 552bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_CTRL_ADDMODE BIT(0) 562bbd681bSSubhendu Sekhar Behera 572bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_INTEN_NACKADDR BIT(25) 582bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_INTEN_SADDR BIT(13) 592bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_INTEN_DATADONE BIT(12) 602bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_INTEN_ARLOST BIT(11) 612bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_INTEN_MFIFOFULL BIT(4) 622bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_INTEN_MFIFOEMTY BIT(3) 632bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_INTEN_MFIFOHI BIT(2) 642bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_INTEN_BUSERR BIT(0) 652bbd681bSSubhendu Sekhar Behera 662bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_MFIFOCTRL_HITH_SHIFT 8 672bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_MFIFOCTRL_LOTH_SHIFT 0 682bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_MFIFOCTRL_RST BIT(16) 692bbd681bSSubhendu Sekhar Behera 702bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_SLAVEADDR_RW BIT(0) 712bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_SLAVEADDR_ADDR_SHIFT 1 722bbd681bSSubhendu Sekhar Behera 732bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_IP_CLK_FREQ 133000000UL 742bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_DEFAULT_FREQ 100000 752bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_HIGH_FREQ 400000 762bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_FIFO_SIZE 0x80U 772bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_TIMEOUT_MS 1000 78d3898a78SGeorge Cherian #define XLP9XX_I2C_BUSY_TIMEOUT 50 792bbd681bSSubhendu Sekhar Behera 802bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_FIFO_WCNT_MASK 0xff 812bbd681bSSubhendu Sekhar Behera #define XLP9XX_I2C_STATUS_ERRMASK (XLP9XX_I2C_INTEN_ARLOST | \ 822bbd681bSSubhendu Sekhar Behera XLP9XX_I2C_INTEN_NACKADDR | XLP9XX_I2C_INTEN_BUSERR) 832bbd681bSSubhendu Sekhar Behera 842bbd681bSSubhendu Sekhar Behera struct xlp9xx_i2c_dev { 852bbd681bSSubhendu Sekhar Behera struct device *dev; 862bbd681bSSubhendu Sekhar Behera struct i2c_adapter adapter; 872bbd681bSSubhendu Sekhar Behera struct completion msg_complete; 8840f4e372SGeorge Cherian struct i2c_smbus_alert_setup alert_data; 8940f4e372SGeorge Cherian struct i2c_client *ara; 902bbd681bSSubhendu Sekhar Behera int irq; 912bbd681bSSubhendu Sekhar Behera bool msg_read; 925515ae11SKamlakant Patel bool len_recv; 935515ae11SKamlakant Patel bool client_pec; 942bbd681bSSubhendu Sekhar Behera u32 __iomem *base; 952bbd681bSSubhendu Sekhar Behera u32 msg_buf_remaining; 962bbd681bSSubhendu Sekhar Behera u32 msg_len; 97c347b8fcSJayachandran C u32 ip_clk_hz; 982bbd681bSSubhendu Sekhar Behera u32 clk_hz; 992bbd681bSSubhendu Sekhar Behera u32 msg_err; 1002bbd681bSSubhendu Sekhar Behera u8 *msg_buf; 1012bbd681bSSubhendu Sekhar Behera }; 1022bbd681bSSubhendu Sekhar Behera 1032bbd681bSSubhendu Sekhar Behera static inline void xlp9xx_write_i2c_reg(struct xlp9xx_i2c_dev *priv, 1042bbd681bSSubhendu Sekhar Behera unsigned long reg, u32 val) 1052bbd681bSSubhendu Sekhar Behera { 1062bbd681bSSubhendu Sekhar Behera writel(val, priv->base + reg); 1072bbd681bSSubhendu Sekhar Behera } 1082bbd681bSSubhendu Sekhar Behera 1092bbd681bSSubhendu Sekhar Behera static inline u32 xlp9xx_read_i2c_reg(struct xlp9xx_i2c_dev *priv, 1102bbd681bSSubhendu Sekhar Behera unsigned long reg) 1112bbd681bSSubhendu Sekhar Behera { 1122bbd681bSSubhendu Sekhar Behera return readl(priv->base + reg); 1132bbd681bSSubhendu Sekhar Behera } 1142bbd681bSSubhendu Sekhar Behera 1152bbd681bSSubhendu Sekhar Behera static void xlp9xx_i2c_mask_irq(struct xlp9xx_i2c_dev *priv, u32 mask) 1162bbd681bSSubhendu Sekhar Behera { 1172bbd681bSSubhendu Sekhar Behera u32 inten; 1182bbd681bSSubhendu Sekhar Behera 1192bbd681bSSubhendu Sekhar Behera inten = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_INTEN) & ~mask; 1202bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTEN, inten); 1212bbd681bSSubhendu Sekhar Behera } 1222bbd681bSSubhendu Sekhar Behera 1232bbd681bSSubhendu Sekhar Behera static void xlp9xx_i2c_unmask_irq(struct xlp9xx_i2c_dev *priv, u32 mask) 1242bbd681bSSubhendu Sekhar Behera { 1252bbd681bSSubhendu Sekhar Behera u32 inten; 1262bbd681bSSubhendu Sekhar Behera 1272bbd681bSSubhendu Sekhar Behera inten = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_INTEN) | mask; 1282bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTEN, inten); 1292bbd681bSSubhendu Sekhar Behera } 1302bbd681bSSubhendu Sekhar Behera 1312bbd681bSSubhendu Sekhar Behera static void xlp9xx_i2c_update_rx_fifo_thres(struct xlp9xx_i2c_dev *priv) 1322bbd681bSSubhendu Sekhar Behera { 1332bbd681bSSubhendu Sekhar Behera u32 thres; 1342bbd681bSSubhendu Sekhar Behera 13541b1d4deSGeorge Cherian if (priv->len_recv) 13641b1d4deSGeorge Cherian /* interrupt after the first read to examine 13741b1d4deSGeorge Cherian * the length byte before proceeding further 13841b1d4deSGeorge Cherian */ 13941b1d4deSGeorge Cherian thres = 1; 14041b1d4deSGeorge Cherian else if (priv->msg_buf_remaining > XLP9XX_I2C_FIFO_SIZE) 14141b1d4deSGeorge Cherian thres = XLP9XX_I2C_FIFO_SIZE; 14241b1d4deSGeorge Cherian else 14341b1d4deSGeorge Cherian thres = priv->msg_buf_remaining; 14441b1d4deSGeorge Cherian 1452bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL, 1462bbd681bSSubhendu Sekhar Behera thres << XLP9XX_I2C_MFIFOCTRL_HITH_SHIFT); 1472bbd681bSSubhendu Sekhar Behera } 1482bbd681bSSubhendu Sekhar Behera 1492bbd681bSSubhendu Sekhar Behera static void xlp9xx_i2c_fill_tx_fifo(struct xlp9xx_i2c_dev *priv) 1502bbd681bSSubhendu Sekhar Behera { 1512bbd681bSSubhendu Sekhar Behera u32 len, i; 1522bbd681bSSubhendu Sekhar Behera u8 *buf = priv->msg_buf; 1532bbd681bSSubhendu Sekhar Behera 1542bbd681bSSubhendu Sekhar Behera len = min(priv->msg_buf_remaining, XLP9XX_I2C_FIFO_SIZE); 1552bbd681bSSubhendu Sekhar Behera for (i = 0; i < len; i++) 1562bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MTXFIFO, buf[i]); 1572bbd681bSSubhendu Sekhar Behera priv->msg_buf_remaining -= len; 1582bbd681bSSubhendu Sekhar Behera priv->msg_buf += len; 1592bbd681bSSubhendu Sekhar Behera } 1602bbd681bSSubhendu Sekhar Behera 1618d504d80SGeorge Cherian static void xlp9xx_i2c_update_rlen(struct xlp9xx_i2c_dev *priv) 1628d504d80SGeorge Cherian { 1638d504d80SGeorge Cherian u32 val, len; 1648d504d80SGeorge Cherian 1658d504d80SGeorge Cherian /* 1668d504d80SGeorge Cherian * Update receive length. Re-read len to get the latest value, 1678d504d80SGeorge Cherian * and then add 4 to have a minimum value that can be safely 1688d504d80SGeorge Cherian * written. This is to account for the byte read above, the 1698d504d80SGeorge Cherian * transfer in progress and any delays in the register I/O 1708d504d80SGeorge Cherian */ 1718d504d80SGeorge Cherian val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL); 1728d504d80SGeorge Cherian len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) & 1738d504d80SGeorge Cherian XLP9XX_I2C_FIFO_WCNT_MASK; 1748d504d80SGeorge Cherian len = max_t(u32, priv->msg_len, len + 4); 17588b4116eSGeorge Cherian if (len >= I2C_SMBUS_BLOCK_MAX + 2) 17688b4116eSGeorge Cherian return; 1778d504d80SGeorge Cherian val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) | 1788d504d80SGeorge Cherian (len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT); 1798d504d80SGeorge Cherian xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val); 1808d504d80SGeorge Cherian } 1818d504d80SGeorge Cherian 1822bbd681bSSubhendu Sekhar Behera static void xlp9xx_i2c_drain_rx_fifo(struct xlp9xx_i2c_dev *priv) 1832bbd681bSSubhendu Sekhar Behera { 1848d504d80SGeorge Cherian u32 len, i; 1855515ae11SKamlakant Patel u8 rlen, *buf = priv->msg_buf; 1862bbd681bSSubhendu Sekhar Behera 1872bbd681bSSubhendu Sekhar Behera len = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_FIFOWCNT) & 1882bbd681bSSubhendu Sekhar Behera XLP9XX_I2C_FIFO_WCNT_MASK; 1895515ae11SKamlakant Patel if (!len) 1905515ae11SKamlakant Patel return; 1915515ae11SKamlakant Patel if (priv->len_recv) { 1925515ae11SKamlakant Patel /* read length byte */ 1935515ae11SKamlakant Patel rlen = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); 19488b4116eSGeorge Cherian if (rlen > I2C_SMBUS_BLOCK_MAX || rlen == 0) { 19588b4116eSGeorge Cherian rlen = 0; /*abort transfer */ 19688b4116eSGeorge Cherian priv->msg_buf_remaining = 0; 19788b4116eSGeorge Cherian priv->msg_len = 0; 19888b4116eSGeorge Cherian } else { 1995515ae11SKamlakant Patel *buf++ = rlen; 2005515ae11SKamlakant Patel if (priv->client_pec) 20188b4116eSGeorge Cherian ++rlen; /* account for error check byte */ 2025515ae11SKamlakant Patel /* update remaining bytes and message length */ 2035515ae11SKamlakant Patel priv->msg_buf_remaining = rlen; 2045515ae11SKamlakant Patel priv->msg_len = rlen + 1; 20588b4116eSGeorge Cherian } 2068d504d80SGeorge Cherian xlp9xx_i2c_update_rlen(priv); 20788b4116eSGeorge Cherian priv->len_recv = false; 20841b1d4deSGeorge Cherian } else { 2092bbd681bSSubhendu Sekhar Behera len = min(priv->msg_buf_remaining, len); 2102bbd681bSSubhendu Sekhar Behera for (i = 0; i < len; i++, buf++) 2112bbd681bSSubhendu Sekhar Behera *buf = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_MRXFIFO); 2122bbd681bSSubhendu Sekhar Behera 2132bbd681bSSubhendu Sekhar Behera priv->msg_buf_remaining -= len; 21441b1d4deSGeorge Cherian } 21541b1d4deSGeorge Cherian 2162bbd681bSSubhendu Sekhar Behera priv->msg_buf = buf; 2172bbd681bSSubhendu Sekhar Behera 2182bbd681bSSubhendu Sekhar Behera if (priv->msg_buf_remaining) 2192bbd681bSSubhendu Sekhar Behera xlp9xx_i2c_update_rx_fifo_thres(priv); 2202bbd681bSSubhendu Sekhar Behera } 2212bbd681bSSubhendu Sekhar Behera 2222bbd681bSSubhendu Sekhar Behera static irqreturn_t xlp9xx_i2c_isr(int irq, void *dev_id) 2232bbd681bSSubhendu Sekhar Behera { 2242bbd681bSSubhendu Sekhar Behera struct xlp9xx_i2c_dev *priv = dev_id; 2252bbd681bSSubhendu Sekhar Behera u32 status; 2262bbd681bSSubhendu Sekhar Behera 2272bbd681bSSubhendu Sekhar Behera status = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_INTST); 2282bbd681bSSubhendu Sekhar Behera if (status == 0) 2292bbd681bSSubhendu Sekhar Behera return IRQ_NONE; 2302bbd681bSSubhendu Sekhar Behera 2312bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTST, status); 2322bbd681bSSubhendu Sekhar Behera if (status & XLP9XX_I2C_STATUS_ERRMASK) { 2332bbd681bSSubhendu Sekhar Behera priv->msg_err = status; 2342bbd681bSSubhendu Sekhar Behera goto xfer_done; 2352bbd681bSSubhendu Sekhar Behera } 2362bbd681bSSubhendu Sekhar Behera 2372bbd681bSSubhendu Sekhar Behera /* SADDR ACK for SMBUS_QUICK */ 2382bbd681bSSubhendu Sekhar Behera if ((status & XLP9XX_I2C_INTEN_SADDR) && (priv->msg_len == 0)) 2392bbd681bSSubhendu Sekhar Behera goto xfer_done; 2402bbd681bSSubhendu Sekhar Behera 2412bbd681bSSubhendu Sekhar Behera if (!priv->msg_read) { 2422bbd681bSSubhendu Sekhar Behera if (status & XLP9XX_I2C_INTEN_MFIFOEMTY) { 2432bbd681bSSubhendu Sekhar Behera /* TX FIFO got empty, fill it up again */ 2442bbd681bSSubhendu Sekhar Behera if (priv->msg_buf_remaining) 2452bbd681bSSubhendu Sekhar Behera xlp9xx_i2c_fill_tx_fifo(priv); 2462bbd681bSSubhendu Sekhar Behera else 2472bbd681bSSubhendu Sekhar Behera xlp9xx_i2c_mask_irq(priv, 2482bbd681bSSubhendu Sekhar Behera XLP9XX_I2C_INTEN_MFIFOEMTY); 2492bbd681bSSubhendu Sekhar Behera } 2502bbd681bSSubhendu Sekhar Behera } else { 2512bbd681bSSubhendu Sekhar Behera if (status & (XLP9XX_I2C_INTEN_DATADONE | 2522bbd681bSSubhendu Sekhar Behera XLP9XX_I2C_INTEN_MFIFOHI)) { 2532bbd681bSSubhendu Sekhar Behera /* data is in FIFO, read it */ 2542bbd681bSSubhendu Sekhar Behera if (priv->msg_buf_remaining) 2552bbd681bSSubhendu Sekhar Behera xlp9xx_i2c_drain_rx_fifo(priv); 2562bbd681bSSubhendu Sekhar Behera } 2572bbd681bSSubhendu Sekhar Behera } 2582bbd681bSSubhendu Sekhar Behera 2592bbd681bSSubhendu Sekhar Behera /* Transfer complete */ 2602bbd681bSSubhendu Sekhar Behera if (status & XLP9XX_I2C_INTEN_DATADONE) 2612bbd681bSSubhendu Sekhar Behera goto xfer_done; 2622bbd681bSSubhendu Sekhar Behera 2632bbd681bSSubhendu Sekhar Behera return IRQ_HANDLED; 2642bbd681bSSubhendu Sekhar Behera 2652bbd681bSSubhendu Sekhar Behera xfer_done: 2662bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTEN, 0); 2672bbd681bSSubhendu Sekhar Behera complete(&priv->msg_complete); 2682bbd681bSSubhendu Sekhar Behera return IRQ_HANDLED; 2692bbd681bSSubhendu Sekhar Behera } 2702bbd681bSSubhendu Sekhar Behera 271d3898a78SGeorge Cherian static int xlp9xx_i2c_check_bus_status(struct xlp9xx_i2c_dev *priv) 272d3898a78SGeorge Cherian { 273d3898a78SGeorge Cherian u32 status; 274d3898a78SGeorge Cherian u32 busy_timeout = XLP9XX_I2C_BUSY_TIMEOUT; 275d3898a78SGeorge Cherian 276d3898a78SGeorge Cherian while (busy_timeout) { 277d3898a78SGeorge Cherian status = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_STATUS); 278d3898a78SGeorge Cherian if ((status & XLP9XX_I2C_STATUS_BUSY) == 0) 279d3898a78SGeorge Cherian break; 280d3898a78SGeorge Cherian 281d3898a78SGeorge Cherian busy_timeout--; 282d3898a78SGeorge Cherian usleep_range(1000, 1100); 283d3898a78SGeorge Cherian } 284d3898a78SGeorge Cherian 285d3898a78SGeorge Cherian if (!busy_timeout) 286d3898a78SGeorge Cherian return -EIO; 287d3898a78SGeorge Cherian 288d3898a78SGeorge Cherian return 0; 289d3898a78SGeorge Cherian } 290d3898a78SGeorge Cherian 2912bbd681bSSubhendu Sekhar Behera static int xlp9xx_i2c_init(struct xlp9xx_i2c_dev *priv) 2922bbd681bSSubhendu Sekhar Behera { 2932bbd681bSSubhendu Sekhar Behera u32 prescale; 2942bbd681bSSubhendu Sekhar Behera 2952bbd681bSSubhendu Sekhar Behera /* 2962bbd681bSSubhendu Sekhar Behera * The controller uses 5 * SCL clock internally. 2972bbd681bSSubhendu Sekhar Behera * So prescale value should be divided by 5. 2982bbd681bSSubhendu Sekhar Behera */ 299c347b8fcSJayachandran C prescale = DIV_ROUND_UP(priv->ip_clk_hz, priv->clk_hz); 3002bbd681bSSubhendu Sekhar Behera prescale = ((prescale - 8) / 5) - 1; 3012bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_RST); 3022bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, XLP9XX_I2C_CTRL_EN | 3032bbd681bSSubhendu Sekhar Behera XLP9XX_I2C_CTRL_MASTER); 3042bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_DIV, prescale); 3052bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTEN, 0); 3062bbd681bSSubhendu Sekhar Behera 3072bbd681bSSubhendu Sekhar Behera return 0; 3082bbd681bSSubhendu Sekhar Behera } 3092bbd681bSSubhendu Sekhar Behera 3102bbd681bSSubhendu Sekhar Behera static int xlp9xx_i2c_xfer_msg(struct xlp9xx_i2c_dev *priv, struct i2c_msg *msg, 3112bbd681bSSubhendu Sekhar Behera int last_msg) 3122bbd681bSSubhendu Sekhar Behera { 3132bbd681bSSubhendu Sekhar Behera unsigned long timeleft; 3145515ae11SKamlakant Patel u32 intr_mask, cmd, val, len; 3152bbd681bSSubhendu Sekhar Behera 3162bbd681bSSubhendu Sekhar Behera priv->msg_buf = msg->buf; 3172bbd681bSSubhendu Sekhar Behera priv->msg_buf_remaining = priv->msg_len = msg->len; 3182bbd681bSSubhendu Sekhar Behera priv->msg_err = 0; 3192bbd681bSSubhendu Sekhar Behera priv->msg_read = (msg->flags & I2C_M_RD); 3202bbd681bSSubhendu Sekhar Behera reinit_completion(&priv->msg_complete); 3212bbd681bSSubhendu Sekhar Behera 3222bbd681bSSubhendu Sekhar Behera /* Reset FIFO */ 3232bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_MFIFOCTRL, 3242bbd681bSSubhendu Sekhar Behera XLP9XX_I2C_MFIFOCTRL_RST); 3252bbd681bSSubhendu Sekhar Behera 3262bbd681bSSubhendu Sekhar Behera /* set slave addr */ 3272bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_SLAVEADDR, 3282bbd681bSSubhendu Sekhar Behera (msg->addr << XLP9XX_I2C_SLAVEADDR_ADDR_SHIFT) | 3292bbd681bSSubhendu Sekhar Behera (priv->msg_read ? XLP9XX_I2C_SLAVEADDR_RW : 0)); 3302bbd681bSSubhendu Sekhar Behera 3312bbd681bSSubhendu Sekhar Behera /* Build control word for transfer */ 3322bbd681bSSubhendu Sekhar Behera val = xlp9xx_read_i2c_reg(priv, XLP9XX_I2C_CTRL); 3332bbd681bSSubhendu Sekhar Behera if (!priv->msg_read) 3342bbd681bSSubhendu Sekhar Behera val &= ~XLP9XX_I2C_CTRL_FIFORD; 3352bbd681bSSubhendu Sekhar Behera else 3362bbd681bSSubhendu Sekhar Behera val |= XLP9XX_I2C_CTRL_FIFORD; /* read */ 3372bbd681bSSubhendu Sekhar Behera 3382bbd681bSSubhendu Sekhar Behera if (msg->flags & I2C_M_TEN) 3392bbd681bSSubhendu Sekhar Behera val |= XLP9XX_I2C_CTRL_ADDMODE; /* 10-bit address mode*/ 3402bbd681bSSubhendu Sekhar Behera else 3412bbd681bSSubhendu Sekhar Behera val &= ~XLP9XX_I2C_CTRL_ADDMODE; 3422bbd681bSSubhendu Sekhar Behera 3435515ae11SKamlakant Patel priv->len_recv = msg->flags & I2C_M_RECV_LEN; 34488b4116eSGeorge Cherian len = priv->len_recv ? I2C_SMBUS_BLOCK_MAX + 2 : msg->len; 3455515ae11SKamlakant Patel priv->client_pec = msg->flags & I2C_CLIENT_PEC; 3465515ae11SKamlakant Patel 34788b4116eSGeorge Cherian /* set FIFO threshold if reading */ 34888b4116eSGeorge Cherian if (priv->msg_read) 34988b4116eSGeorge Cherian xlp9xx_i2c_update_rx_fifo_thres(priv); 35088b4116eSGeorge Cherian 3512bbd681bSSubhendu Sekhar Behera /* set data length to be transferred */ 3522bbd681bSSubhendu Sekhar Behera val = (val & ~XLP9XX_I2C_CTRL_MCTLEN_MASK) | 3535515ae11SKamlakant Patel (len << XLP9XX_I2C_CTRL_MCTLEN_SHIFT); 3542bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, val); 3552bbd681bSSubhendu Sekhar Behera 3562bbd681bSSubhendu Sekhar Behera /* fill fifo during tx */ 3572bbd681bSSubhendu Sekhar Behera if (!priv->msg_read) 3582bbd681bSSubhendu Sekhar Behera xlp9xx_i2c_fill_tx_fifo(priv); 3592bbd681bSSubhendu Sekhar Behera 3602bbd681bSSubhendu Sekhar Behera /* set interrupt mask */ 3612bbd681bSSubhendu Sekhar Behera intr_mask = (XLP9XX_I2C_INTEN_ARLOST | XLP9XX_I2C_INTEN_BUSERR | 3622bbd681bSSubhendu Sekhar Behera XLP9XX_I2C_INTEN_NACKADDR | XLP9XX_I2C_INTEN_DATADONE); 3632bbd681bSSubhendu Sekhar Behera 3642bbd681bSSubhendu Sekhar Behera if (priv->msg_read) { 3652bbd681bSSubhendu Sekhar Behera intr_mask |= XLP9XX_I2C_INTEN_MFIFOHI; 3662bbd681bSSubhendu Sekhar Behera if (msg->len == 0) 3672bbd681bSSubhendu Sekhar Behera intr_mask |= XLP9XX_I2C_INTEN_SADDR; 3682bbd681bSSubhendu Sekhar Behera } else { 3692bbd681bSSubhendu Sekhar Behera if (msg->len == 0) 3702bbd681bSSubhendu Sekhar Behera intr_mask |= XLP9XX_I2C_INTEN_SADDR; 3712bbd681bSSubhendu Sekhar Behera else 3722bbd681bSSubhendu Sekhar Behera intr_mask |= XLP9XX_I2C_INTEN_MFIFOEMTY; 3732bbd681bSSubhendu Sekhar Behera } 3742bbd681bSSubhendu Sekhar Behera xlp9xx_i2c_unmask_irq(priv, intr_mask); 3752bbd681bSSubhendu Sekhar Behera 3762bbd681bSSubhendu Sekhar Behera /* set cmd reg */ 3772bbd681bSSubhendu Sekhar Behera cmd = XLP9XX_I2C_CMD_START; 378e349d7d0SGeorge Cherian if (msg->len) 379e349d7d0SGeorge Cherian cmd |= (priv->msg_read ? 380e349d7d0SGeorge Cherian XLP9XX_I2C_CMD_READ : XLP9XX_I2C_CMD_WRITE); 3812bbd681bSSubhendu Sekhar Behera if (last_msg) 3822bbd681bSSubhendu Sekhar Behera cmd |= XLP9XX_I2C_CMD_STOP; 3832bbd681bSSubhendu Sekhar Behera 3842bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CMD, cmd); 3852bbd681bSSubhendu Sekhar Behera 3862bbd681bSSubhendu Sekhar Behera timeleft = msecs_to_jiffies(XLP9XX_I2C_TIMEOUT_MS); 3872bbd681bSSubhendu Sekhar Behera timeleft = wait_for_completion_timeout(&priv->msg_complete, timeleft); 3882bbd681bSSubhendu Sekhar Behera 389e349d7d0SGeorge Cherian if (priv->msg_err & XLP9XX_I2C_INTEN_BUSERR) { 3902bbd681bSSubhendu Sekhar Behera dev_dbg(priv->dev, "transfer error %x!\n", priv->msg_err); 391e349d7d0SGeorge Cherian xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CMD, XLP9XX_I2C_CMD_STOP); 392e349d7d0SGeorge Cherian return -EIO; 393e349d7d0SGeorge Cherian } else if (priv->msg_err & XLP9XX_I2C_INTEN_NACKADDR) { 394e349d7d0SGeorge Cherian return -ENXIO; 3952bbd681bSSubhendu Sekhar Behera } 3962bbd681bSSubhendu Sekhar Behera 3972bbd681bSSubhendu Sekhar Behera if (timeleft == 0) { 3982bbd681bSSubhendu Sekhar Behera dev_dbg(priv->dev, "i2c transfer timed out!\n"); 3992bbd681bSSubhendu Sekhar Behera xlp9xx_i2c_init(priv); 4002bbd681bSSubhendu Sekhar Behera return -ETIMEDOUT; 4012bbd681bSSubhendu Sekhar Behera } 4022bbd681bSSubhendu Sekhar Behera 4035515ae11SKamlakant Patel /* update msg->len with actual received length */ 40488b4116eSGeorge Cherian if (msg->flags & I2C_M_RECV_LEN) { 40588b4116eSGeorge Cherian if (!priv->msg_len) 40688b4116eSGeorge Cherian return -EPROTO; 4075515ae11SKamlakant Patel msg->len = priv->msg_len; 40888b4116eSGeorge Cherian } 4092bbd681bSSubhendu Sekhar Behera return 0; 4102bbd681bSSubhendu Sekhar Behera } 4112bbd681bSSubhendu Sekhar Behera 4122bbd681bSSubhendu Sekhar Behera static int xlp9xx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, 4132bbd681bSSubhendu Sekhar Behera int num) 4142bbd681bSSubhendu Sekhar Behera { 4152bbd681bSSubhendu Sekhar Behera int i, ret; 4162bbd681bSSubhendu Sekhar Behera struct xlp9xx_i2c_dev *priv = i2c_get_adapdata(adap); 4172bbd681bSSubhendu Sekhar Behera 418d3898a78SGeorge Cherian ret = xlp9xx_i2c_check_bus_status(priv); 419d3898a78SGeorge Cherian if (ret) { 420d3898a78SGeorge Cherian xlp9xx_i2c_init(priv); 421d3898a78SGeorge Cherian ret = xlp9xx_i2c_check_bus_status(priv); 422d3898a78SGeorge Cherian if (ret) 423d3898a78SGeorge Cherian return ret; 424d3898a78SGeorge Cherian } 425d3898a78SGeorge Cherian 4262bbd681bSSubhendu Sekhar Behera for (i = 0; i < num; i++) { 4272bbd681bSSubhendu Sekhar Behera ret = xlp9xx_i2c_xfer_msg(priv, &msgs[i], i == num - 1); 4282bbd681bSSubhendu Sekhar Behera if (ret != 0) 4292bbd681bSSubhendu Sekhar Behera return ret; 4302bbd681bSSubhendu Sekhar Behera } 4312bbd681bSSubhendu Sekhar Behera 4322bbd681bSSubhendu Sekhar Behera return num; 4332bbd681bSSubhendu Sekhar Behera } 4342bbd681bSSubhendu Sekhar Behera 4352bbd681bSSubhendu Sekhar Behera static u32 xlp9xx_i2c_functionality(struct i2c_adapter *adapter) 4362bbd681bSSubhendu Sekhar Behera { 43741b1d4deSGeorge Cherian return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_SMBUS_READ_BLOCK_DATA | 43841b1d4deSGeorge Cherian I2C_FUNC_I2C | I2C_FUNC_10BIT_ADDR; 4392bbd681bSSubhendu Sekhar Behera } 4402bbd681bSSubhendu Sekhar Behera 44192d9d0dfSBhumika Goyal static const struct i2c_algorithm xlp9xx_i2c_algo = { 4422bbd681bSSubhendu Sekhar Behera .master_xfer = xlp9xx_i2c_xfer, 4432bbd681bSSubhendu Sekhar Behera .functionality = xlp9xx_i2c_functionality, 4442bbd681bSSubhendu Sekhar Behera }; 4452bbd681bSSubhendu Sekhar Behera 4462bbd681bSSubhendu Sekhar Behera static int xlp9xx_i2c_get_frequency(struct platform_device *pdev, 4472bbd681bSSubhendu Sekhar Behera struct xlp9xx_i2c_dev *priv) 4482bbd681bSSubhendu Sekhar Behera { 449c347b8fcSJayachandran C struct clk *clk; 4502bbd681bSSubhendu Sekhar Behera u32 freq; 4512bbd681bSSubhendu Sekhar Behera int err; 4522bbd681bSSubhendu Sekhar Behera 453c347b8fcSJayachandran C clk = devm_clk_get(&pdev->dev, NULL); 454c347b8fcSJayachandran C if (IS_ERR(clk)) { 455c347b8fcSJayachandran C priv->ip_clk_hz = XLP9XX_I2C_IP_CLK_FREQ; 456c347b8fcSJayachandran C dev_dbg(&pdev->dev, "using default input frequency %u\n", 457c347b8fcSJayachandran C priv->ip_clk_hz); 458c347b8fcSJayachandran C } else { 459c347b8fcSJayachandran C priv->ip_clk_hz = clk_get_rate(clk); 460c347b8fcSJayachandran C } 461c347b8fcSJayachandran C 462748c0bbbSTanmay Jagdale err = device_property_read_u32(&pdev->dev, "clock-frequency", &freq); 4632bbd681bSSubhendu Sekhar Behera if (err) { 4642bbd681bSSubhendu Sekhar Behera freq = XLP9XX_I2C_DEFAULT_FREQ; 4652bbd681bSSubhendu Sekhar Behera dev_dbg(&pdev->dev, "using default frequency %u\n", freq); 4662bbd681bSSubhendu Sekhar Behera } else if (freq == 0 || freq > XLP9XX_I2C_HIGH_FREQ) { 4672bbd681bSSubhendu Sekhar Behera dev_warn(&pdev->dev, "invalid frequency %u, using default\n", 4682bbd681bSSubhendu Sekhar Behera freq); 4692bbd681bSSubhendu Sekhar Behera freq = XLP9XX_I2C_DEFAULT_FREQ; 4702bbd681bSSubhendu Sekhar Behera } 4712bbd681bSSubhendu Sekhar Behera priv->clk_hz = freq; 4722bbd681bSSubhendu Sekhar Behera 4732bbd681bSSubhendu Sekhar Behera return 0; 4742bbd681bSSubhendu Sekhar Behera } 4752bbd681bSSubhendu Sekhar Behera 47640f4e372SGeorge Cherian static int xlp9xx_i2c_smbus_setup(struct xlp9xx_i2c_dev *priv, 47740f4e372SGeorge Cherian struct platform_device *pdev) 47840f4e372SGeorge Cherian { 47940f4e372SGeorge Cherian if (!priv->alert_data.irq) 48040f4e372SGeorge Cherian return -EINVAL; 48140f4e372SGeorge Cherian 48240f4e372SGeorge Cherian priv->ara = i2c_setup_smbus_alert(&priv->adapter, &priv->alert_data); 48340f4e372SGeorge Cherian if (!priv->ara) 48440f4e372SGeorge Cherian return -ENODEV; 48540f4e372SGeorge Cherian 48640f4e372SGeorge Cherian return 0; 48740f4e372SGeorge Cherian } 48840f4e372SGeorge Cherian 4892bbd681bSSubhendu Sekhar Behera static int xlp9xx_i2c_probe(struct platform_device *pdev) 4902bbd681bSSubhendu Sekhar Behera { 4912bbd681bSSubhendu Sekhar Behera struct xlp9xx_i2c_dev *priv; 4922bbd681bSSubhendu Sekhar Behera struct resource *res; 4932bbd681bSSubhendu Sekhar Behera int err = 0; 4942bbd681bSSubhendu Sekhar Behera 4952bbd681bSSubhendu Sekhar Behera priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); 4962bbd681bSSubhendu Sekhar Behera if (!priv) 4972bbd681bSSubhendu Sekhar Behera return -ENOMEM; 4982bbd681bSSubhendu Sekhar Behera 4992bbd681bSSubhendu Sekhar Behera res = platform_get_resource(pdev, IORESOURCE_MEM, 0); 5002bbd681bSSubhendu Sekhar Behera priv->base = devm_ioremap_resource(&pdev->dev, res); 5012bbd681bSSubhendu Sekhar Behera if (IS_ERR(priv->base)) 5022bbd681bSSubhendu Sekhar Behera return PTR_ERR(priv->base); 5032bbd681bSSubhendu Sekhar Behera 5042bbd681bSSubhendu Sekhar Behera priv->irq = platform_get_irq(pdev, 0); 5052bbd681bSSubhendu Sekhar Behera if (priv->irq <= 0) { 5062bbd681bSSubhendu Sekhar Behera dev_err(&pdev->dev, "invalid irq!\n"); 5072bbd681bSSubhendu Sekhar Behera return priv->irq; 5082bbd681bSSubhendu Sekhar Behera } 50940f4e372SGeorge Cherian /* SMBAlert irq */ 51040f4e372SGeorge Cherian priv->alert_data.irq = platform_get_irq(pdev, 1); 51140f4e372SGeorge Cherian if (priv->alert_data.irq <= 0) 51240f4e372SGeorge Cherian priv->alert_data.irq = 0; 5132bbd681bSSubhendu Sekhar Behera 5142bbd681bSSubhendu Sekhar Behera xlp9xx_i2c_get_frequency(pdev, priv); 5152bbd681bSSubhendu Sekhar Behera xlp9xx_i2c_init(priv); 5162bbd681bSSubhendu Sekhar Behera 5172bbd681bSSubhendu Sekhar Behera err = devm_request_irq(&pdev->dev, priv->irq, xlp9xx_i2c_isr, 0, 5182bbd681bSSubhendu Sekhar Behera pdev->name, priv); 5192bbd681bSSubhendu Sekhar Behera if (err) { 5202bbd681bSSubhendu Sekhar Behera dev_err(&pdev->dev, "IRQ request failed!\n"); 5212bbd681bSSubhendu Sekhar Behera return err; 5222bbd681bSSubhendu Sekhar Behera } 5232bbd681bSSubhendu Sekhar Behera 5242bbd681bSSubhendu Sekhar Behera init_completion(&priv->msg_complete); 5252bbd681bSSubhendu Sekhar Behera priv->adapter.dev.parent = &pdev->dev; 5262bbd681bSSubhendu Sekhar Behera priv->adapter.algo = &xlp9xx_i2c_algo; 527227855b9SGeorge Cherian priv->adapter.class = I2C_CLASS_HWMON; 528254df038STanmay Jagdale ACPI_COMPANION_SET(&priv->adapter.dev, ACPI_COMPANION(&pdev->dev)); 5292bbd681bSSubhendu Sekhar Behera priv->adapter.dev.of_node = pdev->dev.of_node; 5302bbd681bSSubhendu Sekhar Behera priv->dev = &pdev->dev; 5312bbd681bSSubhendu Sekhar Behera 5322bbd681bSSubhendu Sekhar Behera snprintf(priv->adapter.name, sizeof(priv->adapter.name), "xlp9xx-i2c"); 5332bbd681bSSubhendu Sekhar Behera i2c_set_adapdata(&priv->adapter, priv); 5342bbd681bSSubhendu Sekhar Behera 5352bbd681bSSubhendu Sekhar Behera err = i2c_add_adapter(&priv->adapter); 536ea734404SWolfram Sang if (err) 5372bbd681bSSubhendu Sekhar Behera return err; 5382bbd681bSSubhendu Sekhar Behera 53940f4e372SGeorge Cherian err = xlp9xx_i2c_smbus_setup(priv, pdev); 54040f4e372SGeorge Cherian if (err) 54140f4e372SGeorge Cherian dev_dbg(&pdev->dev, "No active SMBus alert %d\n", err); 54240f4e372SGeorge Cherian 5432bbd681bSSubhendu Sekhar Behera platform_set_drvdata(pdev, priv); 5442bbd681bSSubhendu Sekhar Behera dev_dbg(&pdev->dev, "I2C bus:%d added\n", priv->adapter.nr); 5452bbd681bSSubhendu Sekhar Behera 5462bbd681bSSubhendu Sekhar Behera return 0; 5472bbd681bSSubhendu Sekhar Behera } 5482bbd681bSSubhendu Sekhar Behera 5492bbd681bSSubhendu Sekhar Behera static int xlp9xx_i2c_remove(struct platform_device *pdev) 5502bbd681bSSubhendu Sekhar Behera { 5512bbd681bSSubhendu Sekhar Behera struct xlp9xx_i2c_dev *priv; 5522bbd681bSSubhendu Sekhar Behera 5532bbd681bSSubhendu Sekhar Behera priv = platform_get_drvdata(pdev); 5542bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_INTEN, 0); 5552bbd681bSSubhendu Sekhar Behera synchronize_irq(priv->irq); 5562bbd681bSSubhendu Sekhar Behera i2c_del_adapter(&priv->adapter); 5572bbd681bSSubhendu Sekhar Behera xlp9xx_write_i2c_reg(priv, XLP9XX_I2C_CTRL, 0); 5582bbd681bSSubhendu Sekhar Behera 5592bbd681bSSubhendu Sekhar Behera return 0; 5602bbd681bSSubhendu Sekhar Behera } 5612bbd681bSSubhendu Sekhar Behera 5622bbd681bSSubhendu Sekhar Behera static const struct of_device_id xlp9xx_i2c_of_match[] = { 5632bbd681bSSubhendu Sekhar Behera { .compatible = "netlogic,xlp980-i2c", }, 5642bbd681bSSubhendu Sekhar Behera { /* sentinel */ }, 5652bbd681bSSubhendu Sekhar Behera }; 56606e7b10aSJavier Martinez Canillas MODULE_DEVICE_TABLE(of, xlp9xx_i2c_of_match); 5672bbd681bSSubhendu Sekhar Behera 568748c0bbbSTanmay Jagdale #ifdef CONFIG_ACPI 569748c0bbbSTanmay Jagdale static const struct acpi_device_id xlp9xx_i2c_acpi_ids[] = { 570748c0bbbSTanmay Jagdale {"BRCM9007", 0}, 5714165bd4bSJayachandran C {"CAV9007", 0}, 572748c0bbbSTanmay Jagdale {} 573748c0bbbSTanmay Jagdale }; 574748c0bbbSTanmay Jagdale MODULE_DEVICE_TABLE(acpi, xlp9xx_i2c_acpi_ids); 575748c0bbbSTanmay Jagdale #endif 576748c0bbbSTanmay Jagdale 5772bbd681bSSubhendu Sekhar Behera static struct platform_driver xlp9xx_i2c_driver = { 5782bbd681bSSubhendu Sekhar Behera .probe = xlp9xx_i2c_probe, 5792bbd681bSSubhendu Sekhar Behera .remove = xlp9xx_i2c_remove, 5802bbd681bSSubhendu Sekhar Behera .driver = { 5812bbd681bSSubhendu Sekhar Behera .name = "xlp9xx-i2c", 5822bbd681bSSubhendu Sekhar Behera .of_match_table = xlp9xx_i2c_of_match, 583748c0bbbSTanmay Jagdale .acpi_match_table = ACPI_PTR(xlp9xx_i2c_acpi_ids), 5842bbd681bSSubhendu Sekhar Behera }, 5852bbd681bSSubhendu Sekhar Behera }; 5862bbd681bSSubhendu Sekhar Behera 5872bbd681bSSubhendu Sekhar Behera module_platform_driver(xlp9xx_i2c_driver); 5882bbd681bSSubhendu Sekhar Behera 5892bbd681bSSubhendu Sekhar Behera MODULE_AUTHOR("Subhendu Sekhar Behera <sbehera@broadcom.com>"); 5902bbd681bSSubhendu Sekhar Behera MODULE_DESCRIPTION("XLP9XX/5XX I2C Bus Controller Driver"); 5912bbd681bSSubhendu Sekhar Behera MODULE_LICENSE("GPL v2"); 592