123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803 |
- /* drivers/i2c/busses/i2c-msm.c
- *
- * Copyright (C) 2007 Google, Inc.
- * Copyright (c) 2009, The Linux Foundation. All rights reserved.
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- */
- /* #define DEBUG */
- #include <linux/slab.h>
- #include <linux/clk.h>
- #include <linux/err.h>
- #include <linux/init.h>
- #include <linux/i2c.h>
- #include <linux/interrupt.h>
- #include <linux/irq.h>
- #include <linux/platform_device.h>
- #include <linux/delay.h>
- #include <linux/io.h>
- #include <mach/board.h>
- #include <linux/mutex.h>
- #include <linux/timer.h>
- #include <linux/remote_spinlock.h>
- #include <linux/pm_qos.h>
- #include <linux/gpio.h>
- #include <linux/module.h>
- enum {
- I2C_WRITE_DATA = 0x00,
- I2C_CLK_CTL = 0x04,
- I2C_STATUS = 0x08,
- I2C_READ_DATA = 0x0c,
- I2C_INTERFACE_SELECT = 0x10,
- I2C_WRITE_DATA_DATA_BYTE = 0xff,
- I2C_WRITE_DATA_ADDR_BYTE = 1U << 8,
- I2C_WRITE_DATA_LAST_BYTE = 1U << 9,
- I2C_CLK_CTL_FS_DIVIDER_VALUE = 0xff,
- I2C_CLK_CTL_HS_DIVIDER_VALUE = 7U << 8,
- I2C_STATUS_WR_BUFFER_FULL = 1U << 0,
- I2C_STATUS_RD_BUFFER_FULL = 1U << 1,
- I2C_STATUS_BUS_ERROR = 1U << 2,
- I2C_STATUS_PACKET_NACKED = 1U << 3,
- I2C_STATUS_ARB_LOST = 1U << 4,
- I2C_STATUS_INVALID_WRITE = 1U << 5,
- I2C_STATUS_FAILED = 3U << 6,
- I2C_STATUS_BUS_ACTIVE = 1U << 8,
- I2C_STATUS_BUS_MASTER = 1U << 9,
- I2C_STATUS_ERROR_MASK = 0xfc,
- I2C_INTERFACE_SELECT_INTF_SELECT = 1U << 0,
- I2C_INTERFACE_SELECT_SCL = 1U << 8,
- I2C_INTERFACE_SELECT_SDA = 1U << 9,
- I2C_STATUS_RX_DATA_STATE = 3U << 11,
- I2C_STATUS_LOW_CLK_STATE = 3U << 13,
- };
- struct msm_i2c_dev {
- struct device *dev;
- void __iomem *base; /* virtual */
- int irq;
- struct clk *clk;
- struct i2c_adapter adap_pri;
- struct i2c_adapter adap_aux;
- spinlock_t lock;
- struct i2c_msg *msg;
- int rem;
- int pos;
- int cnt;
- int err;
- int flush_cnt;
- int rd_acked;
- int one_bit_t;
- remote_mutex_t r_lock;
- int suspended;
- struct mutex mlock;
- struct msm_i2c_platform_data *pdata;
- struct timer_list pwr_timer;
- int clk_state;
- void *complete;
- struct pm_qos_request pm_qos_req;
- };
- static void
- msm_i2c_pwr_mgmt(struct msm_i2c_dev *dev, unsigned int state)
- {
- dev->clk_state = state;
- if (state != 0)
- clk_enable(dev->clk);
- else
- clk_disable(dev->clk);
- }
- static void
- msm_i2c_pwr_timer(unsigned long data)
- {
- struct msm_i2c_dev *dev = (struct msm_i2c_dev *) data;
- dev_dbg(dev->dev, "I2C_Power: Inactivity based power management\n");
- if (dev->clk_state == 1)
- msm_i2c_pwr_mgmt(dev, 0);
- }
- #ifdef DEBUG
- static void
- dump_status(uint32_t status)
- {
- printk("STATUS (0x%.8x): ", status);
- if (status & I2C_STATUS_BUS_MASTER)
- printk("MST ");
- if (status & I2C_STATUS_BUS_ACTIVE)
- printk("ACT ");
- if (status & I2C_STATUS_INVALID_WRITE)
- printk("INV_WR ");
- if (status & I2C_STATUS_ARB_LOST)
- printk("ARB_LST ");
- if (status & I2C_STATUS_PACKET_NACKED)
- printk("NAK ");
- if (status & I2C_STATUS_BUS_ERROR)
- printk("BUS_ERR ");
- if (status & I2C_STATUS_RD_BUFFER_FULL)
- printk("RD_FULL ");
- if (status & I2C_STATUS_WR_BUFFER_FULL)
- printk("WR_FULL ");
- if (status & I2C_STATUS_FAILED)
- printk("FAIL 0x%x", (status & I2C_STATUS_FAILED));
- printk("\n");
- }
- #endif
- static irqreturn_t
- msm_i2c_interrupt(int irq, void *devid)
- {
- struct msm_i2c_dev *dev = devid;
- uint32_t status = readl(dev->base + I2C_STATUS);
- int err = 0;
- #ifdef DEBUG
- dump_status(status);
- #endif
- spin_lock(&dev->lock);
- if (!dev->msg) {
- printk(KERN_ERR "%s: IRQ but nothing to do!\n", __func__);
- spin_unlock(&dev->lock);
- return IRQ_HANDLED;
- }
- if (status & I2C_STATUS_ERROR_MASK) {
- err = -EIO;
- goto out_err;
- }
- if (dev->msg->flags & I2C_M_RD) {
- if (status & I2C_STATUS_RD_BUFFER_FULL) {
- /*
- * Theres something in the FIFO.
- * Are we expecting data or flush crap?
- */
- if (dev->cnt) { /* DATA */
- uint8_t *data = &dev->msg->buf[dev->pos];
- /* This is in spin-lock. So there will be no
- * scheduling between reading the second-last
- * byte and writing LAST_BYTE to the controller.
- * So extra read-cycle-clock won't be generated
- * Per I2C MSM HW Specs: Write LAST_BYTE befure
- * reading 2nd last byte
- */
- if (dev->cnt == 2)
- writel(I2C_WRITE_DATA_LAST_BYTE,
- dev->base + I2C_WRITE_DATA);
- *data = readl(dev->base + I2C_READ_DATA);
- dev->cnt--;
- dev->pos++;
- if (dev->msg->len == 1)
- dev->rd_acked = 0;
- if (dev->cnt == 0)
- goto out_complete;
- } else {
- /* Now that extra read-cycle-clocks aren't
- * generated, this becomes error condition
- */
- dev_err(dev->dev,
- "read did not stop, status - %x\n",
- status);
- err = -EIO;
- goto out_err;
- }
- } else if (dev->msg->len == 1 && dev->rd_acked == 0 &&
- ((status & I2C_STATUS_RX_DATA_STATE) ==
- I2C_STATUS_RX_DATA_STATE))
- writel(I2C_WRITE_DATA_LAST_BYTE,
- dev->base + I2C_WRITE_DATA);
- } else {
- uint16_t data;
- if (status & I2C_STATUS_WR_BUFFER_FULL) {
- dev_err(dev->dev,
- "Write buffer full in ISR on write?\n");
- err = -EIO;
- goto out_err;
- }
- if (dev->cnt) {
- /* Ready to take a byte */
- data = dev->msg->buf[dev->pos];
- if (dev->cnt == 1 && dev->rem == 1)
- data |= I2C_WRITE_DATA_LAST_BYTE;
- status = readl(dev->base + I2C_STATUS);
- /*
- * Due to a hardware timing issue, data line setup time
- * may be reduced to less than recommended 250 ns.
- * This happens when next byte is written in a
- * particular window of clock line being low and master
- * not stretching the clock line. Due to setup time
- * violation, some slaves may miss first-bit of data, or
- * misinterprete data as start condition.
- * We introduce delay of just over 1/2 clock cycle to
- * ensure master stretches the clock line thereby
- * avoiding setup time violation. Delay is introduced
- * only if I2C clock FSM is LOW. The delay is not needed
- * if I2C clock FSM is HIGH or FORCED_LOW.
- */
- if ((status & I2C_STATUS_LOW_CLK_STATE) ==
- I2C_STATUS_LOW_CLK_STATE)
- udelay((dev->one_bit_t >> 1) + 1);
- writel(data, dev->base + I2C_WRITE_DATA);
- dev->pos++;
- dev->cnt--;
- } else
- goto out_complete;
- }
- spin_unlock(&dev->lock);
- return IRQ_HANDLED;
- out_err:
- dev->err = err;
- out_complete:
- complete(dev->complete);
- spin_unlock(&dev->lock);
- return IRQ_HANDLED;
- }
- static int
- msm_i2c_poll_writeready(struct msm_i2c_dev *dev)
- {
- uint32_t retries = 0;
- while (retries != 2000) {
- uint32_t status = readl(dev->base + I2C_STATUS);
- if (!(status & I2C_STATUS_WR_BUFFER_FULL))
- return 0;
- if (retries++ > 1000)
- usleep_range(100, 200);
- }
- return -ETIMEDOUT;
- }
- static int
- msm_i2c_poll_notbusy(struct msm_i2c_dev *dev)
- {
- uint32_t retries = 0;
- while (retries != 2000) {
- uint32_t status = readl(dev->base + I2C_STATUS);
- if (!(status & I2C_STATUS_BUS_ACTIVE))
- return 0;
- if (retries++ > 1000)
- usleep_range(100, 200);
- }
- return -ETIMEDOUT;
- }
- static int
- msm_i2c_recover_bus_busy(struct msm_i2c_dev *dev, struct i2c_adapter *adap)
- {
- int i;
- int gpio_clk;
- int gpio_dat;
- uint32_t status = readl(dev->base + I2C_STATUS);
- bool gpio_clk_status = false;
- if (!(status & (I2C_STATUS_BUS_ACTIVE | I2C_STATUS_WR_BUFFER_FULL)))
- return 0;
- dev->pdata->msm_i2c_config_gpio(adap->nr, 0);
- /* Even adapter is primary and Odd adapter is AUX */
- if (adap->nr % 2) {
- gpio_clk = dev->pdata->aux_clk;
- gpio_dat = dev->pdata->aux_dat;
- } else {
- gpio_clk = dev->pdata->pri_clk;
- gpio_dat = dev->pdata->pri_dat;
- }
- disable_irq(dev->irq);
- if (status & I2C_STATUS_RD_BUFFER_FULL) {
- dev_warn(dev->dev, "Read buffer full, status %x, intf %x\n",
- status, readl(dev->base + I2C_INTERFACE_SELECT));
- writel(I2C_WRITE_DATA_LAST_BYTE, dev->base + I2C_WRITE_DATA);
- readl(dev->base + I2C_READ_DATA);
- } else if (status & I2C_STATUS_BUS_MASTER) {
- dev_warn(dev->dev, "Still the bus master, status %x, intf %x\n",
- status, readl(dev->base + I2C_INTERFACE_SELECT));
- writel(I2C_WRITE_DATA_LAST_BYTE | 0xff,
- dev->base + I2C_WRITE_DATA);
- }
- for (i = 0; i < 9; i++) {
- if (gpio_get_value(gpio_dat) && gpio_clk_status)
- break;
- gpio_direction_output(gpio_clk, 0);
- udelay(5);
- gpio_direction_output(gpio_dat, 0);
- udelay(5);
- gpio_direction_input(gpio_clk);
- udelay(5);
- if (!gpio_get_value(gpio_clk))
- usleep_range(20, 30);
- if (!gpio_get_value(gpio_clk))
- msleep(10);
- gpio_clk_status = gpio_get_value(gpio_clk);
- gpio_direction_input(gpio_dat);
- udelay(5);
- }
- dev->pdata->msm_i2c_config_gpio(adap->nr, 1);
- udelay(10);
- status = readl(dev->base + I2C_STATUS);
- if (!(status & I2C_STATUS_BUS_ACTIVE)) {
- dev_info(dev->dev, "Bus busy cleared after %d clock cycles, "
- "status %x, intf %x\n",
- i, status, readl(dev->base + I2C_INTERFACE_SELECT));
- enable_irq(dev->irq);
- return 0;
- }
- dev_err(dev->dev, "Bus still busy, status %x, intf %x\n",
- status, readl(dev->base + I2C_INTERFACE_SELECT));
- enable_irq(dev->irq);
- return -EBUSY;
- }
- static int
- msm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
- {
- DECLARE_COMPLETION_ONSTACK(complete);
- struct msm_i2c_dev *dev = i2c_get_adapdata(adap);
- int ret;
- int rem = num;
- uint16_t addr;
- long timeout;
- unsigned long flags;
- int check_busy = 1;
- del_timer_sync(&dev->pwr_timer);
- mutex_lock(&dev->mlock);
- if (dev->suspended) {
- mutex_unlock(&dev->mlock);
- return -EIO;
- }
- if (dev->clk_state == 0) {
- dev_dbg(dev->dev, "I2C_Power: Enable I2C clock(s)\n");
- msm_i2c_pwr_mgmt(dev, 1);
- }
- /* Don't allow power collapse until we release remote spinlock */
- pm_qos_update_request(&dev->pm_qos_req, dev->pdata->pm_lat);
- if (dev->pdata->rmutex) {
- remote_mutex_lock(&dev->r_lock);
- /* If other processor did some transactions, we may have
- * interrupt pending. Clear it
- */
- irq_get_chip(dev->irq)->irq_ack(irq_get_irq_data(dev->irq));
- }
- if (adap == &dev->adap_pri)
- writel(0, dev->base + I2C_INTERFACE_SELECT);
- else
- writel(I2C_INTERFACE_SELECT_INTF_SELECT,
- dev->base + I2C_INTERFACE_SELECT);
- enable_irq(dev->irq);
- while (rem) {
- addr = msgs->addr << 1;
- if (msgs->flags & I2C_M_RD)
- addr |= 1;
- spin_lock_irqsave(&dev->lock, flags);
- dev->msg = msgs;
- dev->rem = rem;
- dev->pos = 0;
- dev->err = 0;
- dev->flush_cnt = 0;
- dev->cnt = msgs->len;
- dev->complete = &complete;
- spin_unlock_irqrestore(&dev->lock, flags);
- if (check_busy) {
- ret = msm_i2c_poll_notbusy(dev);
- if (ret)
- ret = msm_i2c_recover_bus_busy(dev, adap);
- if (ret) {
- dev_err(dev->dev,
- "Error waiting for notbusy\n");
- goto out_err;
- }
- check_busy = 0;
- }
- if (rem == 1 && msgs->len == 0)
- addr |= I2C_WRITE_DATA_LAST_BYTE;
- /* Wait for WR buffer not full */
- ret = msm_i2c_poll_writeready(dev);
- if (ret) {
- ret = msm_i2c_recover_bus_busy(dev, adap);
- if (ret) {
- dev_err(dev->dev,
- "Error waiting for write ready before addr\n");
- goto out_err;
- }
- }
- /* special case for doing 1 byte read.
- * There should be no scheduling between I2C controller becoming
- * ready to read and writing LAST-BYTE to I2C controller
- * This will avoid potential of I2C controller starting to latch
- * another extra byte.
- */
- if ((msgs->len == 1) && (msgs->flags & I2C_M_RD)) {
- uint32_t retries = 0;
- spin_lock_irqsave(&dev->lock, flags);
- writel(I2C_WRITE_DATA_ADDR_BYTE | addr,
- dev->base + I2C_WRITE_DATA);
- /* Poll for I2C controller going into RX_DATA mode to
- * ensure controller goes into receive mode.
- * Just checking write_buffer_full may not work since
- * there is delay between the write-buffer becoming
- * empty and the slave sending ACK to ensure I2C
- * controller goes in receive mode to receive data.
- */
- while (retries != 2000) {
- uint32_t status = readl(dev->base + I2C_STATUS);
- if ((status & I2C_STATUS_RX_DATA_STATE)
- == I2C_STATUS_RX_DATA_STATE)
- break;
- retries++;
- }
- if (retries >= 2000) {
- dev->rd_acked = 0;
- spin_unlock_irqrestore(&dev->lock, flags);
- /* 1-byte-reads from slow devices in interrupt
- * context
- */
- goto wait_for_int;
- }
- dev->rd_acked = 1;
- writel(I2C_WRITE_DATA_LAST_BYTE,
- dev->base + I2C_WRITE_DATA);
- spin_unlock_irqrestore(&dev->lock, flags);
- } else {
- writel(I2C_WRITE_DATA_ADDR_BYTE | addr,
- dev->base + I2C_WRITE_DATA);
- }
- /* Polling and waiting for write_buffer_empty is not necessary.
- * Even worse, if we do, it can result in invalid status and
- * error if interrupt(s) occur while polling.
- */
- /*
- * Now that we've setup the xfer, the ISR will transfer the data
- * and wake us up with dev->err set if there was an error
- */
- wait_for_int:
- timeout = wait_for_completion_timeout(&complete, HZ);
- if (!timeout) {
- dev_err(dev->dev, "Transaction timed out\n");
- writel(I2C_WRITE_DATA_LAST_BYTE,
- dev->base + I2C_WRITE_DATA);
- msleep(100);
- /* FLUSH */
- readl(dev->base + I2C_READ_DATA);
- readl(dev->base + I2C_STATUS);
- ret = -ETIMEDOUT;
- goto out_err;
- }
- if (dev->err) {
- dev_err(dev->dev,
- "(%04x) Error during data xfer (%d)\n",
- addr, dev->err);
- ret = dev->err;
- goto out_err;
- }
- if (msgs->flags & I2C_M_RD)
- check_busy = 1;
- msgs++;
- rem--;
- }
- ret = num;
- out_err:
- spin_lock_irqsave(&dev->lock, flags);
- dev->complete = NULL;
- dev->msg = NULL;
- dev->rem = 0;
- dev->pos = 0;
- dev->err = 0;
- dev->flush_cnt = 0;
- dev->cnt = 0;
- spin_unlock_irqrestore(&dev->lock, flags);
- disable_irq(dev->irq);
- if (dev->pdata->rmutex)
- remote_mutex_unlock(&dev->r_lock);
- pm_qos_update_request(&dev->pm_qos_req,
- PM_QOS_DEFAULT_VALUE);
- mod_timer(&dev->pwr_timer, (jiffies + 3*HZ));
- mutex_unlock(&dev->mlock);
- return ret;
- }
- static u32
- msm_i2c_func(struct i2c_adapter *adap)
- {
- return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
- }
- static const struct i2c_algorithm msm_i2c_algo = {
- .master_xfer = msm_i2c_xfer,
- .functionality = msm_i2c_func,
- };
- static int
- msm_i2c_probe(struct platform_device *pdev)
- {
- struct msm_i2c_dev *dev;
- struct resource *mem, *irq, *ioarea;
- int ret;
- int fs_div;
- int hs_div;
- int i2c_clk;
- int clk_ctl;
- struct clk *clk;
- struct msm_i2c_platform_data *pdata;
- printk(KERN_INFO "msm_i2c_probe\n");
- /* NOTE: driver uses the static register mapping */
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (!mem) {
- dev_err(&pdev->dev, "no mem resource?\n");
- return -ENODEV;
- }
- irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
- if (!irq) {
- dev_err(&pdev->dev, "no irq resource?\n");
- return -ENODEV;
- }
- ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
- pdev->name);
- if (!ioarea) {
- dev_err(&pdev->dev, "I2C region already claimed\n");
- return -EBUSY;
- }
- clk = clk_get(&pdev->dev, "core_clk");
- if (IS_ERR(clk)) {
- dev_err(&pdev->dev, "Could not get clock\n");
- ret = PTR_ERR(clk);
- goto err_clk_get_failed;
- }
- pdata = pdev->dev.platform_data;
- if (!pdata) {
- dev_err(&pdev->dev, "platform data not initialized\n");
- ret = -ENOSYS;
- goto err_clk_get_failed;
- }
- if (!pdata->msm_i2c_config_gpio) {
- dev_err(&pdev->dev, "config_gpio function not initialized\n");
- ret = -ENOSYS;
- goto err_clk_get_failed;
- }
- /* We support frequencies upto FAST Mode(400KHz) */
- if (pdata->clk_freq <= 0 || pdata->clk_freq > 400000) {
- dev_err(&pdev->dev, "clock frequency not supported\n");
- ret = -EIO;
- goto err_clk_get_failed;
- }
- dev = kzalloc(sizeof(struct msm_i2c_dev), GFP_KERNEL);
- if (!dev) {
- ret = -ENOMEM;
- goto err_alloc_dev_failed;
- }
- dev->dev = &pdev->dev;
- dev->irq = irq->start;
- dev->clk = clk;
- dev->pdata = pdata;
- dev->base = ioremap(mem->start, (mem->end - mem->start) + 1);
- if (!dev->base) {
- ret = -ENOMEM;
- goto err_ioremap_failed;
- }
- dev->one_bit_t = USEC_PER_SEC/pdata->clk_freq;
- spin_lock_init(&dev->lock);
- platform_set_drvdata(pdev, dev);
- BUG_ON(clk_prepare_enable(clk));
- if (pdata->rmutex) {
- struct remote_mutex_id rmid;
- rmid.r_spinlock_id = pdata->rsl_id;
- rmid.delay_us = 10000000/pdata->clk_freq;
- if (remote_mutex_init(&dev->r_lock, &rmid) != 0)
- pdata->rmutex = 0;
- }
- /* I2C_HS_CLK = I2C_CLK/(3*(HS_DIVIDER_VALUE+1) */
- /* I2C_FS_CLK = I2C_CLK/(2*(FS_DIVIDER_VALUE+3) */
- /* FS_DIVIDER_VALUE = ((I2C_CLK / I2C_FS_CLK) / 2) - 3 */
- i2c_clk = 19200000; /* input clock */
- fs_div = ((i2c_clk / pdata->clk_freq) / 2) - 3;
- hs_div = 3;
- clk_ctl = ((hs_div & 0x7) << 8) | (fs_div & 0xff);
- writel(clk_ctl, dev->base + I2C_CLK_CTL);
- printk(KERN_INFO "msm_i2c_probe: clk_ctl %x, %d Hz\n",
- clk_ctl, i2c_clk / (2 * ((clk_ctl & 0xff) + 3)));
- i2c_set_adapdata(&dev->adap_pri, dev);
- dev->adap_pri.algo = &msm_i2c_algo;
- strlcpy(dev->adap_pri.name,
- "MSM I2C adapter-PRI",
- sizeof(dev->adap_pri.name));
- dev->adap_pri.nr = pdev->id;
- ret = i2c_add_numbered_adapter(&dev->adap_pri);
- if (ret) {
- dev_err(&pdev->dev, "Primary i2c_add_adapter failed\n");
- goto err_i2c_add_adapter_failed;
- }
- i2c_set_adapdata(&dev->adap_aux, dev);
- dev->adap_aux.algo = &msm_i2c_algo;
- strlcpy(dev->adap_aux.name,
- "MSM I2C adapter-AUX",
- sizeof(dev->adap_aux.name));
- dev->adap_aux.nr = pdev->id + 1;
- ret = i2c_add_numbered_adapter(&dev->adap_aux);
- if (ret) {
- dev_err(&pdev->dev, "auxiliary i2c_add_adapter failed\n");
- i2c_del_adapter(&dev->adap_pri);
- goto err_i2c_add_adapter_failed;
- }
- ret = request_irq(dev->irq, msm_i2c_interrupt,
- IRQF_TRIGGER_RISING, pdev->name, dev);
- if (ret) {
- dev_err(&pdev->dev, "request_irq failed\n");
- goto err_request_irq_failed;
- }
- pm_qos_add_request(&dev->pm_qos_req, PM_QOS_CPU_DMA_LATENCY,
- PM_QOS_DEFAULT_VALUE);
- disable_irq(dev->irq);
- dev->suspended = 0;
- mutex_init(&dev->mlock);
- dev->clk_state = 0;
- /* Config GPIOs for primary and secondary lines */
- pdata->msm_i2c_config_gpio(dev->adap_pri.nr, 1);
- pdata->msm_i2c_config_gpio(dev->adap_aux.nr, 1);
- clk_disable_unprepare(dev->clk);
- clk_prepare(dev->clk);
- setup_timer(&dev->pwr_timer, msm_i2c_pwr_timer, (unsigned long) dev);
- return 0;
- err_request_irq_failed:
- i2c_del_adapter(&dev->adap_pri);
- i2c_del_adapter(&dev->adap_aux);
- err_i2c_add_adapter_failed:
- clk_disable_unprepare(clk);
- iounmap(dev->base);
- err_ioremap_failed:
- kfree(dev);
- err_alloc_dev_failed:
- clk_put(clk);
- err_clk_get_failed:
- release_mem_region(mem->start, (mem->end - mem->start) + 1);
- return ret;
- }
- static int
- msm_i2c_remove(struct platform_device *pdev)
- {
- struct msm_i2c_dev *dev = platform_get_drvdata(pdev);
- struct resource *mem;
- /* Grab mutex to ensure ongoing transaction is over */
- mutex_lock(&dev->mlock);
- dev->suspended = 1;
- mutex_unlock(&dev->mlock);
- mutex_destroy(&dev->mlock);
- del_timer_sync(&dev->pwr_timer);
- if (dev->clk_state != 0)
- msm_i2c_pwr_mgmt(dev, 0);
- platform_set_drvdata(pdev, NULL);
- pm_qos_remove_request(&dev->pm_qos_req);
- free_irq(dev->irq, dev);
- i2c_del_adapter(&dev->adap_pri);
- i2c_del_adapter(&dev->adap_aux);
- clk_unprepare(dev->clk);
- clk_put(dev->clk);
- iounmap(dev->base);
- kfree(dev);
- mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- if (mem)
- release_mem_region(mem->start, (mem->end - mem->start) + 1);
- return 0;
- }
- static int msm_i2c_suspend(struct platform_device *pdev, pm_message_t state)
- {
- struct msm_i2c_dev *dev = platform_get_drvdata(pdev);
- /* Wait until current transaction finishes
- * Make sure remote lock is released before we suspend
- */
- if (dev) {
- /* Grab mutex to ensure ongoing transaction is over */
- mutex_lock(&dev->mlock);
- dev->suspended = 1;
- mutex_unlock(&dev->mlock);
- del_timer_sync(&dev->pwr_timer);
- if (dev->clk_state != 0)
- msm_i2c_pwr_mgmt(dev, 0);
- clk_unprepare(dev->clk);
- }
- return 0;
- }
- static int msm_i2c_resume(struct platform_device *pdev)
- {
- struct msm_i2c_dev *dev = platform_get_drvdata(pdev);
- clk_prepare(dev->clk);
- dev->suspended = 0;
- return 0;
- }
- static struct platform_driver msm_i2c_driver = {
- .probe = msm_i2c_probe,
- .remove = msm_i2c_remove,
- .suspend = msm_i2c_suspend,
- .resume = msm_i2c_resume,
- .driver = {
- .name = "msm_i2c",
- .owner = THIS_MODULE,
- },
- };
- /* I2C may be needed to bring up other drivers */
- static int __init
- msm_i2c_init_driver(void)
- {
- return platform_driver_register(&msm_i2c_driver);
- }
- subsys_initcall(msm_i2c_init_driver);
- static void __exit msm_i2c_exit_driver(void)
- {
- platform_driver_unregister(&msm_i2c_driver);
- }
- module_exit(msm_i2c_exit_driver);
|