From patchwork Wed Jun 5 08:34:37 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Alexander Shiyan X-Patchwork-Id: 249137 Return-Path: X-Original-To: incoming-imx@patchwork.ozlabs.org Delivered-To: patchwork-incoming-imx@bilbo.ozlabs.org Received: from casper.infradead.org (casper.infradead.org [IPv6:2001:770:15f::2]) (using TLSv1.2 with cipher DHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id DE4D42C008F for ; Thu, 6 Jun 2013 02:30:40 +1000 (EST) Received: from merlin.infradead.org ([205.233.59.134]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Uk9RV-0006dc-6D; Wed, 05 Jun 2013 08:51:52 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1Uk9JY-0003HX-GD; Wed, 05 Jun 2013 08:43:28 +0000 Received: from smtp8.mail.ru ([94.100.176.53]) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1Uk9BZ-0002CF-GB for linux-arm-kernel@lists.infradead.org; Wed, 05 Jun 2013 08:35:23 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=mail.ru; s=mail2; h=Content-Transfer-Encoding:Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc:To:From; bh=O+TXZ05MI2rMS3nkBQgQyDWUdOZefaKcnHwqOz/MiFc=; b=W6iiOHxntHfANzRf2zrU6idHh9DM623ilgwfo/8YmqtPkuVcWAUTusme1COkBF9kA7+wVKwe2HFmnCw9qm36/CnyWhNyV4OK+AO7R1zhkZQOW8K3FFkrLTpvRJWeqDYVyMHjfWQSqbefsFGOvumTSs7WQHWkaTXVlCzvlk/CAiQ=; Received: from [188.134.40.128] (port=26760 helo=shc.zet) by smtp8.mail.ru with esmtpa (envelope-from ) id 1Uk9BD-0000y8-7K; Wed, 05 Jun 2013 12:34:51 +0400 From: Alexander Shiyan To: linux-arm-kernel@lists.infradead.org Subject: [PATCH v2 2/4] leds: leds-mc13783: Add MC13892 LED support Date: Wed, 5 Jun 2013 12:34:37 +0400 Message-Id: <1370421279-23348-3-git-send-email-shc_work@mail.ru> X-Mailer: git-send-email 1.8.1.5 In-Reply-To: <1370421279-23348-1-git-send-email-shc_work@mail.ru> References: <1370421279-23348-1-git-send-email-shc_work@mail.ru> MIME-Version: 1.0 X-Spam: Not detected X-Mras: Ok X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20130605_043514_555261_A62F6F9E X-CRM114-Status: GOOD ( 15.68 ) X-Spam-Score: -2.0 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.0 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.0 RCVD_IN_DNSWL_NONE RBL: Sender listed at http://www.dnswl.org/, no trust [94.100.176.53 listed in list.dnswl.org] 0.0 FREEMAIL_FROM Sender email is commonly abused enduser mail provider (shc_work[at]mail.ru) -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature Cc: Russell King , Alexander Shiyan , Arnd Bergmann , Bryan Wu , Richard Purdie , Sascha Hauer , Olof Johansson , Shawn Guo , linux-leds@vger.kernel.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+incoming-imx=patchwork.ozlabs.org@lists.infradead.org List-Id: linux-imx-kernel.lists.patchwork.ozlabs.org Signed-off-by: Alexander Shiyan --- drivers/leds/leds-mc13783.c | 134 +++++++++++++++++++++++++++++++++++++++++++- include/linux/mfd/mc13xxx.h | 48 +++++++++++----- 2 files changed, 167 insertions(+), 15 deletions(-) diff --git a/drivers/leds/leds-mc13783.c b/drivers/leds/leds-mc13783.c index 2203bc0..53d7afd 100644 --- a/drivers/leds/leds-mc13783.c +++ b/drivers/leds/leds-mc13783.c @@ -1,5 +1,5 @@ /* - * LEDs driver for Freescale MC13783 + * LEDs driver for Freescale MC13783/MC13982 * * Copyright (C) 2010 Philippe Rétornaz * @@ -49,9 +49,15 @@ struct mc13xxx_led { #define MC13783_LED_C0_ABMODE 11 #define MC13783_LED_C0_ABREF_MASK 0x3 #define MC13783_LED_C0_ABREF 14 +#define MC13892_LED_C0_MD_HI_CURRENT (1 << 1) +#define MC13892_LED_C0_RAMPMD_ENABLE (1 << 2) +#define MC13892_LED_C0_AD_HI_CURRENT (1 << 13) +#define MC13892_LED_C0_RAMPAD_ENABLE (1 << 14) #define MC13XXX_REG_LED_CONTROL_1 52 #define MC13783_LED_C1_TC1HALF_BIT (1 << 18) +#define MC13892_LED_C1_KP_HI_CURRENT (1 << 1) +#define MC13892_LED_C1_RAMPKP_ENABLE (1 << 2) #define MC13XXX_REG_LED_CONTROL_2 53 #define MC13783_LED_C2_BL_P_MASK 0xf @@ -62,10 +68,15 @@ struct mc13xxx_led { #define MC13783_LED_C2_MD_C 0 #define MC13783_LED_C2_AD_C 3 #define MC13783_LED_C2_KP_C 6 +#define MC13892_LED_C2_RAMPR_ENABLE (1 << 2) +#define MC13892_LED_CX_CURRENT_MASK 0x7 +#define MC13892_LED_CX_DUTY_MASK 0x3f +#define MC13892_LED_C2_RAMPG_ENABLE (1 << 14) #define MC13XXX_REG_LED_CONTROL_3 54 #define MC13783_LED_C3_TC_P 6 #define MC13783_LED_C3_TC_P_MASK 0x1f +#define MC13892_LED_C3_RAMPB_ENABLE (1 << 2) #define MC13783_REG_LED_CONTROL_4 55 #define MC13783_REG_LED_CONTROL_5 56 @@ -116,6 +127,34 @@ static void mc13xxx_led_work(struct work_struct *work) value = led->new_brightness >> 3; mask = MC13783_LED_C3_TC_P_MASK; break; + case MC13892_LED_MD: + reg = MC13XXX_REG_LED_CONTROL_0; + mask = MC13892_LED_CX_DUTY_MASK; + shift = 3; + value = led->new_brightness >> 2; + break; + case MC13892_LED_AD: + reg = MC13XXX_REG_LED_CONTROL_0; + mask = MC13892_LED_CX_DUTY_MASK; + shift = 15; + value = led->new_brightness >> 2; + break; + case MC13892_LED_KP: + reg = MC13XXX_REG_LED_CONTROL_1; + mask = MC13892_LED_CX_DUTY_MASK; + shift = 3; + value = led->new_brightness >> 2; + break; + case MC13892_LED_R: + case MC13892_LED_G: + case MC13892_LED_B: + off = led->id - MC13892_LED_R; + bank = off / 2; + reg = MC13XXX_REG_LED_CONTROL_2 + bank; + shift = (off - bank * 2) * 12 + 3; + value = led->new_brightness >> 2; + mask = MC13892_LED_CX_DUTY_MASK; + break; default: BUG(); } @@ -170,6 +209,29 @@ static int mc13xxx_led_setup(struct mc13xxx_led *led, int max_current) shift = ((led->id - MC13783_LED_R1) - bank * 3) * 2; mask = MC13783_LED_Cx_TC_C_MASK; break; + case MC13892_LED_MD: + shift = 9; + mask = MC13892_LED_CX_CURRENT_MASK; + reg = MC13XXX_REG_LED_CONTROL_0; + break; + case MC13892_LED_AD: + shift = 21; + mask = MC13892_LED_CX_CURRENT_MASK; + reg = MC13XXX_REG_LED_CONTROL_0; + break; + case MC13892_LED_KP: + shift = 9; + mask = MC13892_LED_CX_CURRENT_MASK; + reg = MC13XXX_REG_LED_CONTROL_1; + break; + case MC13892_LED_R: + case MC13892_LED_G: + case MC13892_LED_B: + bank = (led->id - MC13892_LED_R) / 2; + reg = MC13XXX_REG_LED_CONTROL_2 + bank; + shift = ((led->id - MC13892_LED_R) - bank * 2) * 12 + 9; + mask = MC13892_LED_CX_CURRENT_MASK; + break; default: BUG(); } @@ -279,6 +341,66 @@ static void mc13783_leds_shutdown(struct platform_device *pdev) mc13xxx_unlock(dev); } +static int mc13892_leds_startup(struct platform_device *pdev) +{ + struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); + struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent); + int ret, reg; + + mc13xxx_lock(dev); + + reg = (pdata->flags & MC13892_LEDMD_HI_CURR) ? + MC13892_LED_C0_MD_HI_CURRENT : 0; + reg |= (pdata->flags & MC13892_LEDMD_RAMP_EN) ? + MC13892_LED_C0_RAMPMD_ENABLE : 0; + reg |= (pdata->flags & MC13892_LEDAD_HI_CURR) ? + MC13892_LED_C0_AD_HI_CURRENT : 0; + reg |= (pdata->flags & MC13892_LEDAD_RAMP_EN) ? + MC13892_LED_C0_RAMPAD_ENABLE : 0; + ret = mc13xxx_reg_write(dev, MC13XXX_REG_LED_CONTROL_0, reg); + if (ret) + goto out; + + reg = (pdata->flags & MC13892_LEDKP_HI_CURR) ? + MC13892_LED_C1_KP_HI_CURRENT : 0; + reg |= (pdata->flags & MC13892_LEDKP_RAMP_EN) ? + MC13892_LED_C1_RAMPKP_ENABLE : 0; + ret = mc13xxx_reg_write(dev, MC13XXX_REG_LED_CONTROL_1, reg); + if (ret) + goto out; + + reg = (pdata->flags & MC13892_LEDR_RAMP_EN) ? + MC13892_LED_C2_RAMPR_ENABLE : 0; + reg |= (pdata->flags & MC13892_LEDG_RAMP_EN) ? + MC13892_LED_C2_RAMPG_ENABLE : 0; + ret = mc13xxx_reg_write(dev, MC13XXX_REG_LED_CONTROL_2, reg); + if (ret) + goto out; + + reg = (pdata->flags & MC13892_LEDB_RAMP_EN) ? + MC13892_LED_C3_RAMPB_ENABLE : 0; + ret = mc13xxx_reg_write(dev, MC13XXX_REG_LED_CONTROL_3, reg); + +out: + mc13xxx_unlock(dev); + + return ret; +} + +static void mc13892_leds_shutdown(struct platform_device *pdev) +{ + struct mc13xxx *dev = dev_get_drvdata(pdev->dev.parent); + + mc13xxx_lock(dev); + + mc13xxx_reg_write(dev, MC13XXX_REG_LED_CONTROL_0, 0); + mc13xxx_reg_write(dev, MC13XXX_REG_LED_CONTROL_1, 0); + mc13xxx_reg_write(dev, MC13XXX_REG_LED_CONTROL_2, 0); + mc13xxx_reg_write(dev, MC13XXX_REG_LED_CONTROL_3, 0); + + mc13xxx_unlock(dev); +} + static int mc13xxx_led_probe(struct platform_device *pdev) { struct mc13xxx_leds_platform_data *pdata = dev_get_platdata(&pdev->dev); @@ -394,8 +516,16 @@ static const struct mc13xxx_led_devtype mc13783_led_devtype = { .leds_shutdown = mc13783_leds_shutdown, }; +static const struct mc13xxx_led_devtype mc13892_led_devtype = { + .led_min = MC13892_LED_MD, + .led_max = MC13892_LED_B, + .leds_startup = mc13892_leds_startup, + .leds_shutdown = mc13892_leds_shutdown, +}; + static const struct platform_device_id mc13xxx_led_id_table[] = { { "mc13783-led", (kernel_ulong_t)&mc13783_led_devtype, }, + { "mc13892-led", (kernel_ulong_t)&mc13892_led_devtype, }, { } }; MODULE_DEVICE_TABLE(platform, mc13xxx_led_id_table); @@ -411,6 +541,6 @@ static struct platform_driver mc13xxx_led_driver = { }; module_platform_driver(mc13xxx_led_driver); -MODULE_DESCRIPTION("LEDs driver for Freescale MC13783 PMIC"); +MODULE_DESCRIPTION("LEDs driver for Freescale MC13XXX PMIC"); MODULE_AUTHOR("Philippe Retornaz "); MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/mc13xxx.h b/include/linux/mfd/mc13xxx.h index fe0e003..8eba95d 100644 --- a/include/linux/mfd/mc13xxx.h +++ b/include/linux/mfd/mc13xxx.h @@ -78,19 +78,30 @@ struct mc13xxx_regulator_platform_data { struct mc13xxx_regulator_init_data *regulators; }; +enum { + /* MC13783 LED IDs */ + MC13783_LED_MD, + MC13783_LED_AD, + MC13783_LED_KP, + MC13783_LED_R1, + MC13783_LED_G1, + MC13783_LED_B1, + MC13783_LED_R2, + MC13783_LED_G2, + MC13783_LED_B2, + MC13783_LED_R3, + MC13783_LED_G3, + MC13783_LED_B3, + /* MC13892 LED IDs */ + MC13892_LED_MD, + MC13892_LED_AD, + MC13892_LED_KP, + MC13892_LED_R, + MC13892_LED_G, + MC13892_LED_B +}; + struct mc13xxx_led_platform_data { -#define MC13783_LED_MD 0 -#define MC13783_LED_AD 1 -#define MC13783_LED_KP 2 -#define MC13783_LED_R1 3 -#define MC13783_LED_G1 4 -#define MC13783_LED_B1 5 -#define MC13783_LED_R2 6 -#define MC13783_LED_G2 7 -#define MC13783_LED_B2 8 -#define MC13783_LED_R3 9 -#define MC13783_LED_G3 10 -#define MC13783_LED_B3 11 int id; const char *name; const char *default_trigger; @@ -103,6 +114,7 @@ struct mc13xxx_leds_platform_data { int num_leds; struct mc13xxx_led_platform_data *led; +/* MC13783 specific */ #define MC13783_LED_TRIODE_MD (1 << 0) #define MC13783_LED_TRIODE_AD (1 << 1) #define MC13783_LED_TRIODE_KP (1 << 2) @@ -113,7 +125,17 @@ struct mc13xxx_leds_platform_data { #define MC13783_LED_TRIODE_TC1 (1 << 7) #define MC13783_LED_TRIODE_TC2 (1 << 8) #define MC13783_LED_TRIODE_TC3 (1 << 9) - int flags; +/* MC13892 specific */ +#define MC13892_LEDMD_HI_CURR (1 << 10) +#define MC13892_LEDMD_RAMP_EN (1 << 11) +#define MC13892_LEDAD_HI_CURR (1 << 12) +#define MC13892_LEDAD_RAMP_EN (1 << 13) +#define MC13892_LEDKP_HI_CURR (1 << 14) +#define MC13892_LEDKP_RAMP_EN (1 << 15) +#define MC13892_LEDR_RAMP_EN (1 << 16) +#define MC13892_LEDG_RAMP_EN (1 << 17) +#define MC13892_LEDB_RAMP_EN (1 << 18) + unsigned int flags; #define MC13783_LED_AB_DISABLED 0 #define MC13783_LED_AB_MD1 1