From patchwork Thu Nov 14 21:02:14 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Tim Kryger X-Patchwork-Id: 21523 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-qe0-f71.google.com (mail-qe0-f71.google.com [209.85.128.71]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 40C1723FBC for ; Thu, 14 Nov 2013 21:02:50 +0000 (UTC) Received: by mail-qe0-f71.google.com with SMTP id 1sf4808903qec.10 for ; Thu, 14 Nov 2013 13:02:49 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:delivered-to:from:to:cc:subject:date:message-id :in-reply-to:references:mime-version:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe:content-type :content-transfer-encoding; bh=HUVPOy+U/zt5yIXOxFKxdZ+kHvLkSni7Dnrb4E/hzHU=; b=SBiCUi3iHbZaIECh/1Lc9oUknljtwJ9aMKRkyajB3vg/1VTpHLOYpGqgGor0rbWs2z nFsgH4hn3SfHAtSoiFQ6LPL5JisOjNslbzGWyRPh4fIMhNw7eF4rDzXP1ELPAQSJv327 UzNhzLSYnmAjsKfIG6MqD8529YsNCQiWIRnhBXj67Oanjac939nXZkc7S3eszHqNW2N9 9C/6Ckim829lgwZBH2vLGZCM4ozn5qAvbPzXrowljK6Z//8Edzr2nRpxTh1g1r2oF0Xa LgLrwqusvreXNMXHeBN5P7Ii9mTg7dc4NgjVPlmx4WfzBHhYue5wptxKSRL96o55If5n xDfQ== X-Gm-Message-State: ALoCoQnej91D7KX9fVhnqWDY+hyO8J5HPJ1NHi4XjRsLhycsrZSJFQgnVE5ymAPfTFR1SKCh0ldS X-Received: by 10.236.21.132 with SMTP id r4mr1900169yhr.7.1384462969692; Thu, 14 Nov 2013 13:02:49 -0800 (PST) X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.27.199 with SMTP id v7ls1214901qeg.85.gmail; Thu, 14 Nov 2013 13:02:49 -0800 (PST) X-Received: by 10.58.44.166 with SMTP id f6mr104438vem.76.1384462969515; Thu, 14 Nov 2013 13:02:49 -0800 (PST) Received: from mail-ve0-f182.google.com (mail-ve0-f182.google.com [209.85.128.182]) by mx.google.com with ESMTPS id cp3si17921235vcb.58.2013.11.14.13.02.49 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Thu, 14 Nov 2013 13:02:49 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.182 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.182; Received: by mail-ve0-f182.google.com with SMTP id pa12so2333920veb.41 for ; Thu, 14 Nov 2013 13:02:49 -0800 (PST) X-Received: by 10.58.255.233 with SMTP id at9mr1965257ved.20.1384462969381; Thu, 14 Nov 2013 13:02:49 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp346046vcz; Thu, 14 Nov 2013 13:02:48 -0800 (PST) X-Received: by 10.182.34.194 with SMTP id b2mr3431952obj.41.1384462968582; Thu, 14 Nov 2013 13:02:48 -0800 (PST) Received: from mms3.broadcom.com (mms3.broadcom.com. [216.31.210.19]) by mx.google.com with ESMTP id rw1si6207789oeb.126.2013.11.14.13.02.47 for ; Thu, 14 Nov 2013 13:02:48 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of tkryger@broadcom.com designates 216.31.210.19 as permitted sender) client-ip=216.31.210.19; Received: from [10.9.208.57] by mms3.broadcom.com with ESMTP (Broadcom SMTP Relay (Email Firewall v6.5)); Thu, 14 Nov 2013 13:01:50 -0800 X-Server-Uuid: B86B6450-0931-4310-942E-F00ED04CA7AF Received: from IRVEXCHSMTP2.corp.ad.broadcom.com (10.9.207.52) by IRVEXCHCAS08.corp.ad.broadcom.com (10.9.208.57) with Microsoft SMTP Server (TLS) id 14.1.438.0; Thu, 14 Nov 2013 13:02:38 -0800 Received: from mail-sj1-12.sj.broadcom.com (10.10.10.20) by IRVEXCHSMTP2.corp.ad.broadcom.com (10.9.207.52) with Microsoft SMTP Server id 14.1.438.0; Thu, 14 Nov 2013 13:02:38 -0800 Received: from mps-infra-lab3.broadcom.com ( mps-infra-lab3.sj.broadcom.com [10.19.114.109]) by mail-sj1-12.sj.broadcom.com (Postfix) with ESMTP id 3C091207CE; Thu, 14 Nov 2013 13:02:38 -0800 (PST) Received: by mps-infra-lab3.broadcom.com (Postfix, from userid 1004) id 0F8E94589F9; Thu, 14 Nov 2013 13:02:38 -0800 (PST) From: "Tim Kryger" To: "Christian Daudt" , "Rob Herring" , "Pawel Moll" , "Mark Rutland" , "Stephen Warren" , "Ian Campbell" , "Rob Landley" , "Wolfram Sang" , "Grant Likely" cc: "Tim Kryger" , "Device Tree List" , "Linux Doc List" , "Linux Kernel Mailing List" , "Linux I2C List" , "Linux ARM Kernel List" , "Linaro Patches List" Subject: [PATCH v2 3/5] i2c: i2c-bcm-kona: Add support for high-speed mode Date: Thu, 14 Nov 2013 13:02:14 -0800 Message-ID: <1384462936-7906-4-git-send-email-tim.kryger@linaro.org> X-Mailer: git-send-email 1.8.0.1 In-Reply-To: <1384462936-7906-1-git-send-email-tim.kryger@linaro.org> References: <1384462936-7906-1-git-send-email-tim.kryger@linaro.org> MIME-Version: 1.0 X-WSS-ID: 7E9BE5B41SC8127047-02-01 X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: tim.kryger@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.182 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Add support for I2C high-speed mode (3.4 MHz). Signed-off-by: Tim Kryger Reviewed-by: Matt Porter Reviewed-by: Markus Mayer --- drivers/i2c/busses/i2c-bcm-kona.c | 115 +++++++++++++++++++++++++++++++++++++- 1 file changed, 114 insertions(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-bcm-kona.c b/drivers/i2c/busses/i2c-bcm-kona.c index acd2b57..7b7b762 100644 --- a/drivers/i2c/busses/i2c-bcm-kona.c +++ b/drivers/i2c/busses/i2c-bcm-kona.c @@ -77,6 +77,9 @@ #define HSTIM_OFFSET 0x00000058 #define HSTIM_HS_MODE_MASK 0x00008000 +#define HSTIM_HS_HOLD_SHIFT 10 +#define HSTIM_HS_HIGH_PHASE_SHIFT 5 +#define HSTIM_HS_SETUP_SHIFT 0 #define PADCTL_OFFSET 0x0000005c #define PADCTL_PAD_OUT_EN_MASK 0x00000004 @@ -91,6 +94,9 @@ #define MAX_TX_FIFO_SIZE 64U /* bytes */ #define STD_EXT_CLK_FREQ 13000000UL +#define HS_EXT_CLK_FREQ 104000000UL + +#define MASTERCODE 0x08 /* Mastercodes are 0000_1xxxb */ #define I2C_TIMEOUT 100 /* msecs */ @@ -108,6 +114,10 @@ enum bus_speed_index { BCM_SPD_1MHZ, }; +enum hs_bus_speed_index { + BCM_SPD_3P4MHZ = 0, +}; + /* Internal divider settings for standard mode, fast mode and fast mode plus */ struct bus_speed_cfg { uint8_t time_m; /* Number of cycles for setup time */ @@ -118,12 +128,30 @@ struct bus_speed_cfg { uint8_t time_div; /* Post-prescale divider */ }; +/* Internal divider settings for high-speed mode */ +struct hs_bus_speed_cfg { + uint8_t hs_hold; /* Number of clock cycles SCL stays low until + the end of bit period */ + uint8_t hs_high_phase; /* Number of clock cycles SCL stays high + before it falls */ + uint8_t hs_setup; /* Number of clock cycles SCL stays low + before it rises */ + uint8_t prescale; /* Prescale divider */ + uint8_t time_p; /* Timing coefficient */ + uint8_t no_div; /* Disable clock divider */ + uint8_t time_div; /* Post-prescale divider */ +}; + static const struct bus_speed_cfg std_cfg_table[] = { [BCM_SPD_100K] = {0x01, 0x01, 0x03, 0x06, 0x00, 0x02}, [BCM_SPD_400K] = {0x05, 0x01, 0x03, 0x05, 0x01, 0x02}, [BCM_SPD_1MHZ] = {0x01, 0x01, 0x03, 0x01, 0x01, 0x03}, }; +static const struct hs_bus_speed_cfg hs_cfg_table[] = { + [BCM_SPD_3P4MHZ] = {0x01, 0x08, 0x14, 0x00, 0x06, 0x01, 0x00}, +}; + struct bcm_kona_i2c_dev { struct device *device; @@ -136,6 +164,7 @@ struct bcm_kona_i2c_dev { struct completion done; const struct bus_speed_cfg *std_cfg; + const struct hs_bus_speed_cfg *hs_cfg; }; static void bcm_kona_i2c_send_cmd_to_ctrl(struct bcm_kona_i2c_dev *dev, @@ -508,6 +537,70 @@ static void bcm_kona_i2c_config_timing(struct bcm_kona_i2c_dev *dev) dev->base + CLKEN_OFFSET); } +static void bcm_kona_i2c_config_timing_hs(struct bcm_kona_i2c_dev *dev) +{ + writel((dev->hs_cfg->prescale << TIM_PRESCALE_SHIFT) | + (dev->hs_cfg->time_p << TIM_P_SHIFT) | + (dev->hs_cfg->no_div << TIM_NO_DIV_SHIFT) | + (dev->hs_cfg->time_div << TIM_DIV_SHIFT), + dev->base + TIM_OFFSET); + + writel((dev->hs_cfg->hs_hold << HSTIM_HS_HOLD_SHIFT) | + (dev->hs_cfg->hs_high_phase << HSTIM_HS_HIGH_PHASE_SHIFT) | + (dev->hs_cfg->hs_setup << HSTIM_HS_SETUP_SHIFT), + dev->base + HSTIM_OFFSET); + + writel(readl(dev->base + HSTIM_OFFSET) | HSTIM_HS_MODE_MASK, + dev->base + HSTIM_OFFSET); +} + +static int bcm_kona_i2c_switch_to_hs(struct bcm_kona_i2c_dev *dev) +{ + int rc; + + /* Send mastercode at standard speed */ + rc = bcm_kona_i2c_write_byte(dev, MASTERCODE, 1); + if (rc < 0) { + pr_err("High speed handshake failed\n"); + return rc; + } + + /* Configure external clock to higher frequency */ + rc = clk_set_rate(dev->external_clk, HS_EXT_CLK_FREQ); + if (rc) { + dev_err(dev->device, "%s: clk_set_rate returned %d\n", + __func__, rc); + return rc; + } + + /* Reconfigure internal dividers */ + bcm_kona_i2c_config_timing_hs(dev); + + /* Send a restart command */ + rc = bcm_kona_send_i2c_cmd(dev, BCM_CMD_RESTART); + if (rc < 0) + dev_err(dev->device, "High speed restart command failed\n"); + + return rc; +} + +static int bcm_kona_i2c_switch_to_std(struct bcm_kona_i2c_dev *dev) +{ + int rc; + + /* Reconfigure internal dividers */ + bcm_kona_i2c_config_timing(dev); + + /* Configure external clock to lower frequency */ + rc = clk_set_rate(dev->external_clk, STD_EXT_CLK_FREQ); + if (rc) { + dev_err(dev->device, "%s: clk_set_rate returned %d\n", + __func__, rc); + } + + return rc; +} + /* Master transfer function */ static int bcm_kona_i2c_xfer(struct i2c_adapter *adapter, struct i2c_msg msgs[], int num) @@ -537,6 +630,13 @@ static int bcm_kona_i2c_xfer(struct i2c_adapter *adapter, goto xfer_disable_pad; } + /* Switch to high speed if applicable */ + if (dev->hs_cfg) { + rc = bcm_kona_i2c_switch_to_hs(dev); + if (rc < 0) + goto xfer_send_stop; + } + /* Loop through all messages */ for (i = 0; i < num; i++) { pmsg = &msgs[i]; @@ -584,6 +684,14 @@ xfer_send_stop: /* Send a STOP command */ bcm_kona_send_i2c_cmd(dev, BCM_CMD_STOP); + /* Return from high speed if applicable */ + if (dev->hs_cfg) { + int hs_rc = bcm_kona_i2c_switch_to_std(dev); + + if (hs_rc) + rc = hs_rc; + } + xfer_disable_pad: /* Disable pad output */ writel(PADCTL_PAD_OUT_EN_MASK, dev->base + PADCTL_OFFSET); @@ -627,9 +735,14 @@ static int bcm_kona_i2c_assign_bus_speed(struct bcm_kona_i2c_dev *dev) case 1000000: dev->std_cfg = &std_cfg_table[BCM_SPD_1MHZ]; break; + case 3400000: + /* Send mastercode at 100k */ + dev->std_cfg = &std_cfg_table[BCM_SPD_100K]; + dev->hs_cfg = &hs_cfg_table[BCM_SPD_3P4MHZ]; + break; default: pr_err("%d hz bus speed not supported\n", bus_speed); - pr_err("Valid speeds are 100khz, 400khz, and 1mhz\n"); + pr_err("Valid speeds are 100khz, 400khz, 1mhz, and 3.4mhz\n"); return -EINVAL; }