From patchwork Mon Aug 17 22:05:48 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Petr Cvek X-Patchwork-Id: 7027671 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork2.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork2.web.kernel.org (Postfix) with ESMTP id 2892AC05AC for ; Mon, 17 Aug 2015 22:05:09 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 25EA0205EC for ; Mon, 17 Aug 2015 22:05:08 +0000 (UTC) Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.9]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 1B201205E5 for ; Mon, 17 Aug 2015 22:05:07 +0000 (UTC) Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZRSUz-0005X9-9L; Mon, 17 Aug 2015 22:03:21 +0000 Received: from bubo.tul.cz ([2001:718:1c01:16::aa]) by bombadil.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1ZRSUv-00055c-EF for linux-arm-kernel@lists.infradead.org; Mon, 17 Aug 2015 22:03:18 +0000 Received: from [78.80.185.17] (78-80-185-17.tmcz.cz [78.80.185.17]) (using TLSv1 with cipher DHE-RSA-AES128-SHA (128/128 bits)) (No client certificate requested) by bubo.tul.cz (Postfix) with ESMTPSA id D92C31F0002; Tue, 18 Aug 2015 00:02:32 +0200 (CEST) From: Petr Cvek Subject: [PATCH v2 18/21] mfd: htc-pasic3: Prepare driver for leds-pasic3 To: robert.jarzmik@free.fr, philipp.zabel@gmail.com, daniel@zonque.org, haojian.zhuang@gmail.com, sameo@linux.intel.com, lee.jones@linaro.org, cooloney@gmail.com, rpurdie@rpsys.net, j.anaszewski@samsung.com, linux@arm.linux.org.uk, sre@kernel.org, dbaryshkov@gmail.com, dwmw2@infradead.org References: Message-ID: <55D25ABC.1000405@tul.cz> Date: Tue, 18 Aug 2015 00:05:48 +0200 User-Agent: Mozilla/5.0 (X11; Linux i686; rv:38.0) Gecko/20100101 Thunderbird/38.2.0 MIME-Version: 1.0 In-Reply-To: X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20150817_150318_009318_5D495524 X-CRM114-Status: GOOD ( 18.02 ) X-Spam-Score: -2.5 (--) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: linux-arm-kernel@lists.infradead.org, linux-leds@vger.kernel.org, linux-pm@vger.kernel.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.8 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Fix register definitions and prepare structures for new leds-pasic3 driver. Signed-off-by: Petr Cvek --- drivers/mfd/htc-pasic3.c | 54 ++++++++++++++++----------- include/linux/mfd/htc-pasic3.h | 85 +++++++++++++++++++++++++++++++----------- 2 files changed, 97 insertions(+), 42 deletions(-) diff --git a/drivers/mfd/htc-pasic3.c b/drivers/mfd/htc-pasic3.c index e88d4f6..16e156d 100644 --- a/drivers/mfd/htc-pasic3.c +++ b/drivers/mfd/htc-pasic3.c @@ -3,6 +3,9 @@ * * Copyright (C) 2006 Philipp Zabel * + * 2015: Added registers for LED and RESET, see htc-pasic3.h + * -- Petr Cvek + * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; version 2 of the License. @@ -21,15 +24,10 @@ #include #include -struct pasic3_data { - void __iomem *mapping; - unsigned int bus_shift; -}; - #define REG_ADDR 5 #define REG_DATA 6 -#define READ_MODE 0x80 +#define READ_MODE BIT(7) /* * write to a secondary register on the PASIC3 @@ -76,24 +74,36 @@ static struct mfd_cell led_cell __initdata = { static int ds1wm_enable(struct platform_device *pdev) { struct device *dev = pdev->dev.parent; - int c; + struct pasic3_data *asic = platform_get_drvdata(pdev); + unsigned long flags; + u8 c; + + spin_lock_irqsave(&asic->lock, flags); + + c = pasic3_read_register(dev, PASIC3_GPIO); + pasic3_write_register(dev, PASIC3_GPIO, c & ~DS1WM_NEN); - c = pasic3_read_register(dev, 0x28); - pasic3_write_register(dev, 0x28, c & 0x7f); + spin_unlock_irqrestore(&asic->lock, flags); - dev_dbg(dev, "DS1WM OWM_EN low (active) %02x\n", c & 0x7f); + dev_dbg(dev, "DS1WM OWM_EN low (active) %02lx\n", c & ~DS1WM_NEN); return 0; } static int ds1wm_disable(struct platform_device *pdev) { struct device *dev = pdev->dev.parent; - int c; + struct pasic3_data *asic = platform_get_drvdata(pdev); + unsigned long flags; + u8 c; + + spin_lock_irqsave(&asic->lock, flags); + + c = pasic3_read_register(dev, PASIC3_GPIO); + pasic3_write_register(dev, PASIC3_GPIO, c | DS1WM_NEN); - c = pasic3_read_register(dev, 0x28); - pasic3_write_register(dev, 0x28, c | 0x80); + spin_unlock_irqrestore(&asic->lock, flags); - dev_dbg(dev, "DS1WM OWM_EN high (inactive) %02x\n", c | 0x80); + dev_dbg(dev, "DS1WM OWM_EN high (inactive) %02lx\n", c | DS1WM_NEN); return 0; } @@ -130,6 +140,7 @@ static int __init pasic3_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct pasic3_data *asic; struct resource *r; + struct pasic3_leds_pdata *leds_pdata; int ret; int irq = 0; @@ -162,6 +173,8 @@ static int __init pasic3_probe(struct platform_device *pdev) /* calculate bus shift from mem resource */ asic->bus_shift = (resource_size(r) - 5) >> 3; + spin_lock_init(&asic->lock); + if (pdata && pdata->clock_rate) { ds1wm_pdata.clock_rate = pdata->clock_rate; /* the first 5 PASIC3 registers control the DS1WM */ @@ -172,13 +185,12 @@ static int __init pasic3_probe(struct platform_device *pdev) dev_warn(dev, "failed to register DS1WM\n"); } - if (pdata && pdata->led_pdata) { - led_cell.platform_data = pdata->led_pdata; - led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo); - ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, - 0, NULL); - if (ret < 0) - dev_warn(dev, "failed to register LED device\n"); + if (pdata && pdata->pasic3_leds) { + leds_pdata = dev_get_platdata(&pdata->pasic3_leds->dev); + if (leds_pdata) { + leds_pdata->mfd_dev = dev; + platform_device_register(pdata->pasic3_leds); + } } return 0; diff --git a/include/linux/mfd/htc-pasic3.h b/include/linux/mfd/htc-pasic3.h index 3d3ed67..91a27b6 100644 --- a/include/linux/mfd/htc-pasic3.h +++ b/include/linux/mfd/htc-pasic3.h @@ -2,6 +2,7 @@ * HTC PASIC3 driver - LEDs and DS1WM * * Copyright (c) 2007 Philipp Zabel + * Copyright (c) 2015 Petr Cvek * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for @@ -18,37 +19,79 @@ extern void pasic3_write_register(struct device *dev, u32 reg, u8 val); extern u8 pasic3_read_register(struct device *dev, u32 reg); -/* - * mask for registers 0x20,0x21,0x22 - */ -#define PASIC3_MASK_LED0 0x04 -#define PASIC3_MASK_LED1 0x08 -#define PASIC3_MASK_LED2 0x40 +#define PASIC3_CH0_DELAY_ON 0x00 +#define PASIC3_CH0_DELAY_OFF 0x01 +#define PASIC3_CH1_DELAY_ON 0x02 +#define PASIC3_CH1_DELAY_OFF 0x03 +#define PASIC3_CH2_DELAY_ON 0x04 +#define PASIC3_CH2_DELAY_OFF 0x05 +#define PASIC3_DELAY_MASK 0x7f + +#define PASIC3_CH_CONTROL 0x06 +#define R06_CH0_EN BIT(0) +#define R06_CH1_EN BIT(1) +#define R06_CH2_EN BIT(2) +#define R06_CH0_FORCE_ON BIT(3) +#define R06_CH1_FORCE_ON BIT(4) +#define R06_CH2_FORCE_ON BIT(5) /* - * bits in register 0x06 + * pwm_ch0_out | force_on | (bit0 & bit1 & bit2) + * pwm_ch1_out | force_on | (bit0 & bit1 & bit2) + * pwm_ch2_out | force_on | (bit2?bit0:(bit0 & ! bit1)) */ -#define PASIC3_BIT2_LED0 0x08 -#define PASIC3_BIT2_LED1 0x10 -#define PASIC3_BIT2_LED2 0x20 + +#define PASIC3_MASK_A 0x20 +#define PASIC3_MASK_B 0x21 +#define PASIC3_MASK_C 0x22 +#define MASK_CH0 BIT(2) +#define MASK_CH1 BIT(3) +#define MASK_CH2 BIT(6) +#define PASIC3_GPIO 0x28 +#define DS1WM_NEN BIT(7) +#define PASIC3_SYS 0x2a + +/* NORMAL_RST, CAM_PWR_RST and UNKNOWN will autoclear, set STATUS */ +#define NORMAL_RST BIT(0) +#define CAM_PWR_RST BIT(1) +#define UNKNOWN BIT(2) +#define STATUS_NORMAL_RST BIT(4) +#define STATUS_CAM_PWR_RST BIT(5) +#define STATUS_UNKNOWN BIT(6) + +/* FIXME/TODO reset sources */ +#define PASIC3_RST_EN 0x2c +#define EN_NORMAL_RST 0x40 +#define EN_DOOR_RST 0x42 struct pasic3_led { - struct led_classdev led; - unsigned int hw_num; - unsigned int bit2; - unsigned int mask; - struct pasic3_leds_machinfo *pdata; + char name[24]; + char default_trigger[80]; + int hw_num; + u8 bit_blink_en; + u8 bit_force_on; + u8 bit_mask; + u8 reg_delay_on; + u8 reg_delay_off; }; -struct pasic3_leds_machinfo { - unsigned int num_leds; - unsigned int power_gpio; +struct pasic3_leds_pdata { struct pasic3_led *leds; + int num_leds; + int power_gpio; + int power_gpio_users; + struct device *mfd_dev; }; -struct pasic3_platform_data { - struct pasic3_leds_machinfo *led_pdata; - unsigned int clock_rate; +struct pasic3_data { + void __iomem *mapping; + unsigned int bus_shift; + spinlock_t lock; }; +struct pasic3_platform_data { + unsigned int clock_rate; + struct pasic3_led *leds; + struct platform_device *pasic3_leds; +}; #endif