Hi Ken, On 7/23/2010 8:17 AM, Kenneth Heitke wrote: > This bus driver supports the QUP i2c hardware controller in the Qualcomm > MSM SOCs. The Qualcomm Universal Peripheral Engine (QUP) is a general > purpose data path engine with input/output FIFOs and an embedded i2c > mini-core. The driver supports FIFO mode (for low bandwidth applications) > and block mode (interrupt generated for each block-size data transfer). > The driver currently does not support DMA transfers. > > Signed-off-by: Kenneth Heitke <kheitke@xxxxxxxxxxxxxx> Thanks for the posting the driver. > + > +static void > +qup_i2c_pwr_timer(unsigned long data) > +{ > + struct qup_i2c_dev *dev = (struct qup_i2c_dev *) data; > + dev_dbg(dev->dev, "QUP_Power: Inactivity based power management\n"); > + if (dev->clk_state == 1) > + qup_i2c_pwr_mgmt(dev, 0); > +} Why this timer can't be converted to run-time PM functionality? I see this very much related to what we are introducing in the Runtime-PM functionality, isn't it? > + > + if (!pdata->msm_i2c_config_gpio) { > + dev_err(&pdev->dev, "config_gpio function not initialized\n"); > + ret = -ENOSYS; > + goto err_config_failed; > + } I don't agree here. What if I do all the gpio configuration from the bootloader itself, because I know that the device I am working on is production device and don't change its configuration, then why I should provide the pdata hooks from the board files? Please also specify what are the operations we are doing in the msm_i2c_config_gpio? > + > + /* 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"); Which freq? Should we add that freq value in the debug message? > + ret = -EIO; > + goto err_config_failed; > + } > + > + dev = kzalloc(sizeof(struct qup_i2c_dev), GFP_KERNEL); > + if (!dev) { > + ret = -ENOMEM; > + goto err_alloc_dev_failed; > + } > + > + dev->dev = &pdev->dev; > + if (in_irq) > + dev->in_irq = in_irq->start; > + if (out_irq) > + dev->out_irq = out_irq->start; > + dev->err_irq = err_irq->start; > + if (in_irq && out_irq) > + dev->num_irqs = 3; > + else > + dev->num_irqs = 1; > + dev->clk = clk; > + dev->pclk = pclk; > + dev->base = ioremap(qup_mem->start, resource_size(qup_mem)); > + if (!dev->base) { > + ret = -ENOMEM; > + goto err_ioremap_failed; > + } > + > + /* Configure GSBI block to use I2C functionality */ > + dev->gsbi = ioremap(gsbi_mem->start, resource_size(gsbi_mem)); > + if (!dev->gsbi) { > + ret = -ENOMEM; > + goto err_gsbi_failed; > + } > + > + platform_set_drvdata(pdev, dev); > + > + dev->one_bit_t = USEC_PER_SEC/pdata->clk_freq; > + dev->pdata = pdata; > + dev->clk_ctl = 0; > + > + /* > + * We use num_irqs to also indicate if we got 3 interrupts or just 1. > + * If we have just 1, we use err_irq as the general purpose irq > + * and handle the changes in ISR accordingly > + * Per Hardware guidelines, if we have 3 interrupts, they are always > + * edge triggering, and if we have 1, it's always level-triggering > + */ > + if (dev->num_irqs == 3) { > + ret = request_irq(dev->in_irq, qup_i2c_interrupt, > + IRQF_TRIGGER_RISING, "qup_in_intr", dev); > + if (ret) { > + dev_err(&pdev->dev, "request_in_irq failed\n"); > + goto err_request_irq_failed; > + } > + /* > + * We assume out_irq exists if in_irq does since platform > + * configuration either has 3 interrupts assigned to QUP or 1 > + */ > + ret = request_irq(dev->out_irq, qup_i2c_interrupt, > + IRQF_TRIGGER_RISING, "qup_out_intr", dev); > + if (ret) { > + dev_err(&pdev->dev, "request_out_irq failed\n"); > + free_irq(dev->in_irq, dev); > + goto err_request_irq_failed; > + } > + ret = request_irq(dev->err_irq, qup_i2c_interrupt, > + IRQF_TRIGGER_RISING, "qup_err_intr", dev); > + if (ret) { > + dev_err(&pdev->dev, "request_err_irq failed\n"); > + free_irq(dev->out_irq, dev); > + free_irq(dev->in_irq, dev); > + goto err_request_irq_failed; > + } > + } else { > + ret = request_irq(dev->err_irq, qup_i2c_interrupt, > + IRQF_TRIGGER_HIGH, "qup_err_intr", dev); > + if (ret) { > + dev_err(&pdev->dev, "request_err_irq failed\n"); > + goto err_request_irq_failed; > + } > + } > + disable_irq(dev->err_irq); > + if (dev->num_irqs == 3) { > + disable_irq(dev->in_irq); > + disable_irq(dev->out_irq); > + } > + i2c_set_adapdata(&dev->adapter, dev); > + dev->adapter.algo = &qup_i2c_algo; > + strlcpy(dev->adapter.name, > + "QUP I2C adapter", > + sizeof(dev->adapter.name)); > + dev->adapter.nr = pdev->id; > + pdata->msm_i2c_config_gpio(dev->adapter.nr, 1); Why there is no error check here? ---Trilok Soni -- Sent by a consultant of the Qualcomm Innovation Center, Inc. The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum. -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html