From patchwork Tue Jun 16 12:11:30 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vaibhav Hiremath X-Patchwork-Id: 484962 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 1DB2B1401DA for ; Tue, 16 Jun 2015 22:11:38 +1000 (AEST) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751207AbbFPMLh (ORCPT ); Tue, 16 Jun 2015 08:11:37 -0400 Received: from mail-pd0-f173.google.com ([209.85.192.173]:35203 "EHLO mail-pd0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752124AbbFPMLg (ORCPT ); Tue, 16 Jun 2015 08:11:36 -0400 Received: by pdbnf5 with SMTP id nf5so13246372pdb.2 for ; Tue, 16 Jun 2015 05:11:36 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:message-id:date:from:user-agent:mime-version:to :cc:subject:references:in-reply-to:content-type :content-transfer-encoding; bh=Ihp3JLfxeMDOrcxTAP68L8ggEMxlSnSmebp+SabOr1k=; b=RrtwKH2VolcdpZeno1d1O2rfJvUjZsqQnCaW4OfPuy04m9i2JuN9e1pQ36LboCJqNV kBtdjw0lJnadPkiVSLwBmXczCnC0lZX/9dTrkCUYry09PG42h/EXP0vW+aosgIMxxvBV e6+0fwTCOlt9Op0jxugbJ1XEMRBfqCmsUhOwcSZEToK7BSuWdW8R+WLCOM35+yfzPlh3 rjA3FliuQk+7JL68UCjh/fvCVDmnureQUCCAHz1WeTd5HNYr5QRh9Ex+xPBviJGbIYhc AZQ9K43RDO3NBG9QXeo6TSDBD0Ecit/LsBHvxX5FlNFYwau+TgZkUKkULsSliv0AJtvr Rhrw== X-Gm-Message-State: ALoCoQmJvKPcBasmmyrzmwxl8UB6ShgpFxgUVlulMQ2uwOQd9wpLnSXapydVuDjyFNwlU9dOB0DY X-Received: by 10.68.179.228 with SMTP id dj4mr57094732pbc.141.1434456695966; Tue, 16 Jun 2015 05:11:35 -0700 (PDT) Received: from [192.168.0.100] ([202.62.77.106]) by mx.google.com with ESMTPSA id ho2sm1229369pbb.14.2015.06.16.05.11.33 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 16 Jun 2015 05:11:34 -0700 (PDT) Message-ID: <55801272.1040006@linaro.org> Date: Tue, 16 Jun 2015 17:41:30 +0530 From: Vaibhav Hiremath User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.7.0 MIME-Version: 1.0 To: Wolfram Sang CC: linux-i2c@vger.kernel.org Subject: Re: [RFC]: Supporting PIO mode of operation in i2c_msg->flags References: <5562EF9D.1090403@linaro.org> <20150611234118.GA1534@katana> <557D6FAF.1050408@linaro.org> <557FE4A9.5030004@linaro.org> <20150616091815.GA1595@katana> In-Reply-To: <20150616091815.GA1595@katana> Sender: linux-i2c-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-i2c@vger.kernel.org On Tuesday 16 June 2015 02:48 PM, Wolfram Sang wrote: > >> Any update on this? > > Not yet. > > a) there was no code to look at > Actually its simple question, whether we can call i2c_transfer in pm_power_off fn, where interupts are disabled and i2c_transfer fn may sleep. Just to illustrate my point, I just quickly created something for you. Correct me if I am wrong here. pm_power_off Usecase: __u8 *buf; /* pointer to msg data */ }; --- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html ===== File: arch/arm64/kernel/process.c void machine_power_off(void) { local_irq_disable(); smp_send_stop(); if (pm_power_off) pm_power_off(); } Dummy pm_power_off Implementation: ===== diff --git a/drivers/i2c/busses/i2c-pxa.c b/drivers/i2c/busses/i2c-pxa.c index 03b70f8..e364a2a 100644 --- a/drivers/i2c/busses/i2c-pxa.c +++ b/drivers/i2c/busses/i2c-pxa.c @@ -1170,7 +1170,10 @@ static int i2c_pxa_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num i2c_pxa_enable(i2c, true); for (i = adap->retries; i >= 0; i--) { - ret = i2c_pxa_do_xfer(i2c, msgs, num); + if (msgs[0].flags & I2C_M_PIO) + ret = i2c_pxa_do_pio_xfer(i2c, msgs, num); + else + ret = i2c_pxa_do_xfer(i2c, msgs, num); if (ret != I2C_RETRY) goto out; diff --git a/drivers/mfd/88pm800.c b/drivers/mfd/88pm800.c index 0464e2d..2d7b11b 100644 --- a/drivers/mfd/88pm800.c +++ b/drivers/mfd/88pm800.c @@ -488,6 +488,52 @@ static void pm800_pages_exit(struct pm80x_chip *chip) i2c_unregister_device(subchip->gpadc_page); } +static struct pm80x_chip *pm80x_chip_g; + +#define PM800_SW_PDOWN (1 << 5) + +static void pm800_power_off(void) +{ + u8 data, buf[2]; + struct i2c_msg msgs[2]; + struct i2c_client *client = pm80x_chip_g->client; + + pr_info("turning off power....\n"); + + /* + * pm_power_off fn get called at the end of machine_power_off(), + * so at this stage the irqs are disabled, so we have to use + * PIO mode of I2C transaction for both read and write. + */ + /* Read register first */ + msgs[0].addr = client->addr; + msgs[0].flags = I2C_M_PIO; + msgs[0].len = 1; + msgs[0].buf = buf; + + msgs[1].addr = client->addr; + msgs[1].flags = I2C_M_RD | I2C_M_PIO; + msgs[1].len = 1; + msgs[1].buf = &data; + + buf[0] = PM800_WAKEUP1; + if ( __i2c_transfer(client->adapter, msgs, 2) < 0) { + pr_err("%s read register fails...\n", __func__); + WARN_ON(1); + } + + /* issue SW power down */ + msgs[0].addr = client->addr; + msgs[0].flags = I2C_M_PIO; + msgs[0].len = 2; + msgs[0].buf[0] = PM800_WAKEUP1; + msgs[0].buf[1] = data | PM800_SW_PDOWN; + if (__i2c_transfer(client->adapter, msgs, 1) < 0) { + pr_err("%s write data fails...\n", __func__); + WARN_ON(1); + } +} + static int device_800_init(struct pm80x_chip *chip, struct pm80x_platform_data *pdata) { @@ -612,6 +658,10 @@ static int pm800_probe(struct i2c_client *client, if (pdata && pdata->plat_config) pdata->plat_config(chip, pdata); + /* keep global copy, required in power_off fn */ + pm80x_chip_g = chip; + pm_power_off = pm800_power_off; + return 0; err_device_init: diff --git a/include/uapi/linux/i2c.h b/include/uapi/linux/i2c.h index 0e949cb..22fda83 100644 --- a/include/uapi/linux/i2c.h +++ b/include/uapi/linux/i2c.h @@ -76,6 +76,7 @@ struct i2c_msg { #define I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ #define I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ +#define I2C_M_PIO 0x0200 /* pio mode of transaction */ __u16 len; /* msg length */