All of lore.kernel.org
 help / color / mirror / Atom feed
From: Stefan Roese <sr@denx.de>
To: u-boot@lists.denx.de
Subject: [U-Boot] [PATCH] misc: led: Add PCA9551 LED driver
Date: Wed, 11 Mar 2015 09:51:40 +0100	[thread overview]
Message-ID: <1426063900-7267-4-git-send-email-sr@denx.de> (raw)
In-Reply-To: <1426063900-7267-1-git-send-email-sr@denx.de>

This patch adds a driver for the PCA9551 LED controller.

Originated-by: Timo Herbrecher <t.herbrecher@gateware.de>
Signed-off-by: Stefan Roese <sr@denx.de>
---
 drivers/misc/Kconfig       |  14 +++++
 drivers/misc/Makefile      |   1 +
 drivers/misc/pca9551_led.c | 147 +++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 162 insertions(+)
 create mode 100644 drivers/misc/pca9551_led.c

diff --git a/drivers/misc/Kconfig b/drivers/misc/Kconfig
index 36a8f0d..b8884ec 100644
--- a/drivers/misc/Kconfig
+++ b/drivers/misc/Kconfig
@@ -61,3 +61,17 @@ config CONFIG_FSL_SEC_MON
 	  system states.
 	  Security Monitor can be transitioned on any security failures,
 	  like software violations or hardware security violations.
+
+config PCA9551_LED
+	bool "Enable PCA9551 LED driver"
+	depends on TARGET_TQMA6
+	help
+	  Enable driver for PCA9551 LED controller. This controller
+	  is connected via I2C. So I2C needs to be enabled.
+
+config PCA9551_I2C_ADDR
+	hex "I2C address of PCA9551 LED controller"
+	depends on PCA9551_LED
+	default 0x60
+	help
+	  The I2C address of the PCA9551 LED controller.
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index 6028cd4..149e686 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -29,3 +29,4 @@ obj-$(CONFIG_STATUS_LED) += status_led.o
 obj-$(CONFIG_TWL4030_LED) += twl4030_led.o
 obj-$(CONFIG_FSL_IFC) += fsl_ifc.o
 obj-$(CONFIG_FSL_SEC_MON) += fsl_sec_mon.o
+obj-$(CONFIG_PCA9551_LED) += pca9551_led.o
diff --git a/drivers/misc/pca9551_led.c b/drivers/misc/pca9551_led.c
new file mode 100644
index 0000000..273cc53
--- /dev/null
+++ b/drivers/misc/pca9551_led.c
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2015 Stefan Roese <sr@denx.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <i2c.h>
+
+#ifndef CONFIG_PCA9551_I2C_ADDR
+#error "CONFIG_PCA9551_I2C_ADDR not defined!"
+#endif
+
+#define PCA9551_REG_INPUT	0x00	/* Input register (read only) */
+#define PCA9551_REG_PSC0	0x01	/* Frequency prescaler 0 */
+#define PCA9551_REG_PWM0	0x02	/* PWM0 */
+#define PCA9551_REG_PSC1	0x03	/* Frequency prescaler 1 */
+#define PCA9551_REG_PWM1	0x04	/* PWM1 */
+#define PCA9551_REG_LS0		0x05	/* LED0 to LED3 selector */
+#define PCA9551_REG_LS1		0x06	/* LED4 to LED7 selector */
+
+#define PCA9551_CTRL_AI		(1 << 4)	/* Auto-increment flag */
+
+#define PCA9551_LED_STATE_ON		0x00
+#define PCA9551_LED_STATE_OFF		0x01
+#define PCA9551_LED_STATE_BLINK0	0x02
+#define PCA9551_LED_STATE_BLINK1	0x03
+
+struct pca9551_blink_rate {
+	u8 psc;	/* Frequency preescaler, see PCA9551_7.pdf p. 6 */
+	u8 pwm;	/* Pulse width modulation, see PCA9551_7.pdf p. 6 */
+} __packed;
+
+static int freq0, freq1;
+
+static int pca9551_led_get_state(int led, int *state)
+{
+	unsigned int reg;
+	u8 shift, buf;
+
+	if (led < 0 || led > 7) {
+		return -1;
+	} else if (led < 4) {
+		reg = PCA9551_REG_LS0;
+		shift = led << 1;
+	} else {
+		reg = PCA9551_REG_LS1;
+		shift = (led - 4) << 1;
+	}
+
+	if (i2c_read(CONFIG_PCA9551_I2C_ADDR, reg, 1, &buf, 1))
+		return -1;
+
+	*state = (buf >> shift) & 0x03;
+	return 0;
+}
+
+static int pca9551_led_set_state(int led, int state)
+{
+	unsigned int reg;
+	u8 shift, buf, mask;
+
+	if (led < 0 || led > 7) {
+		return -1;
+	} else if (led < 4) {
+		reg = PCA9551_REG_LS0;
+		shift = led << 1;
+	} else {
+		reg = PCA9551_REG_LS1;
+		shift = (led - 4) << 1;
+	}
+	mask = 0x03 << shift;
+
+	if (i2c_read(CONFIG_PCA9551_I2C_ADDR, reg, 1, &buf, 1))
+		return -1;
+
+	buf = (buf & ~mask) | ((state & 0x03) << shift);
+
+	if (i2c_write(CONFIG_PCA9551_I2C_ADDR, reg, 1, &buf, 1))
+		return -1;
+
+	return 0;
+}
+
+static int pca9551_led_set_blink_rate(int idx, struct pca9551_blink_rate rate)
+{
+	unsigned int reg;
+
+	switch (idx) {
+	case 0:
+		reg = PCA9551_REG_PSC0;
+		break;
+	case 1:
+		reg = PCA9551_REG_PSC1;
+		break;
+	default:
+		return -1;
+	}
+	reg |= PCA9551_CTRL_AI;
+
+	if (i2c_write(CONFIG_PCA9551_I2C_ADDR, reg, 1, (u8 *)&rate, 2))
+		return -1;
+
+	return 0;
+}
+
+/*
+ * Functions referenced by cmd_led.c
+ */
+void __led_set(led_id_t mask, int state)
+{
+	if (state == STATUS_LED_OFF)
+		pca9551_led_set_state(mask, PCA9551_LED_STATE_OFF);
+	else
+		pca9551_led_set_state(mask, PCA9551_LED_STATE_ON);
+}
+
+void __led_toggle(led_id_t mask)
+{
+	int state = 0;
+
+	pca9551_led_get_state(mask, &state);
+	pca9551_led_set_state(mask, !state);
+}
+
+void __led_blink(led_id_t mask, int freq)
+{
+	struct pca9551_blink_rate rate;
+	int mode;
+	int blink;
+
+	if ((freq0 == 0) || (freq == freq0)) {
+		blink = 0;
+		mode = PCA9551_LED_STATE_BLINK0;
+		freq0 = freq;
+	} else {
+		blink = 1;
+		mode = PCA9551_LED_STATE_BLINK1;
+		freq1 = freq;
+	}
+
+	rate.psc = ((freq * 38) / 1000) - 1;
+	rate.pwm = 128;		/* 50% duty cycle */
+
+	pca9551_led_set_blink_rate(blink, rate);
+	pca9551_led_set_state(mask, mode);
+}
-- 
2.3.2

  parent reply	other threads:[~2015-03-11  8:51 UTC|newest]

Thread overview: 29+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-03-11  8:51 [U-Boot] [PATCH] autoboot.c: Add feature to stop autobooting via SHA256 encrypted password Stefan Roese
2015-03-11  8:51 ` [U-Boot] [PATCH] bootcount: Add dcache flush to bootcount_store() Stefan Roese
2015-03-11 14:39   ` Tom Rini
2015-03-13 13:48   ` [U-Boot] " Tom Rini
2015-03-13 14:34     ` Tom Rini
2015-03-15 18:30       ` Tom Rini
2015-03-16 15:57         ` York Sun
2015-03-16 17:05           ` Tom Rini
2015-03-16 17:11             ` York Sun
2015-03-16 17:22               ` Tom Rini
2015-03-17  9:00       ` Holger Brunck
2015-03-27 13:18         ` Stefan Roese
2015-03-27 13:42           ` Nitin Garg
2015-03-27 15:07             ` [U-Boot] [RFC] powerpc: add 2 common dcache assembly functions Valentin Longchamp
2015-03-28 18:07               ` Tom Rini
2015-05-05 16:35               ` [U-Boot] [U-Boot, RFC] " York Sun
2015-03-11  8:51 ` [U-Boot] [PATCH] cmd_led: Extend led command to support blinking and more leds Stefan Roese
2015-03-11 14:38   ` Tom Rini
2015-04-23 22:02   ` [U-Boot] " Tom Rini
2015-03-11  8:51 ` Stefan Roese [this message]
2015-03-11 14:40   ` [U-Boot] [PATCH] misc: led: Add PCA9551 LED driver Tom Rini
2015-03-11 14:46   ` Fabio Estevam
2015-03-11 14:36 ` [U-Boot] [PATCH] autoboot.c: Add feature to stop autobooting via SHA256 encrypted password Tom Rini
2015-03-12  8:39   ` Stefan Roese
2015-03-13  2:48   ` Simon Glass
2015-03-13  7:15     ` Stefan Roese
2015-03-23 20:28       ` Simon Glass
2015-05-05 15:06         ` Stefan Roese
2015-05-05 15:12           ` Simon Glass

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1426063900-7267-4-git-send-email-sr@denx.de \
    --to=sr@denx.de \
    --cc=u-boot@lists.denx.de \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.