[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20120521082626.GG3710@pengutronix.de>
Date: Mon, 21 May 2012 10:26:26 +0200
From: Uwe Kleine-König
<u.kleine-koenig@...gutronix.de>
To: Bryan Wu <bryan.wu@...onical.com>
Cc: Richard Purdie <rpurdie@...ys.net>, kernel@...gutronix.de,
linux-kernel@...r.kernel.org, linux-leds@...r.kernel.org
Subject: Re: [PATCH] ARM: leds: Add MAX6956 driver
Hi Bryan,
On Mon, May 21, 2012 at 12:50:12PM +0800, Bryan Wu wrote:
> This patch looks quite nice to me, just some comments as below.
\o/
> On Fri, May 18, 2012 at 11:45 PM, Uwe Kleine-König
> <u.kleine-koenig@...gutronix.de> wrote:
> > This adds a driver for Maxim's MAX6956 28-Port LED Display Driver and
> > I/O Expander.
>
> MAX6956 is a MFD for LED + GPIO. and most of this driver are adding an
> new gpiochip driver. Is that possible we split these 2 functions into
> 2 drivers?
IMHO this is only sensible if these functions are seperated in the
register space, too. So yes, it would be possible, but it would make the
led driver just a set of one-line-functions and increase the overall
code size (souce and binary). There are other examples in the tree that
combine LED and GPIO driver in one file. (I used leds-pca9532 as
reference, didn't check the others.)
> > Signed-off-by: Uwe Kleine-König <u.kleine-koenig@...gutronix.de>
> > ---
> > drivers/leds/Kconfig | 10 +
> > drivers/leds/Makefile | 1 +
> > drivers/leds/leds-max6956.c | 359 ++++++++++++++++++++++++++++
> > include/linux/platform_data/leds-max6956.h | 17 ++
> > 4 files changed, 387 insertions(+)
> > create mode 100644 drivers/leds/leds-max6956.c
> > create mode 100644 include/linux/platform_data/leds-max6956.h
> >
> > diff --git a/drivers/leds/leds-max6956.c b/drivers/leds/leds-max6956.c
> > new file mode 100644
> > index 0000000..976ed91
> > --- /dev/null
> > +++ b/drivers/leds/leds-max6956.c
> > @@ -0,0 +1,359 @@
> > +/*
> > + * Maxim 28-Port LED Display Driver and I/O Expander
> > + *
> > + * Copyright (C) 2012 Pengutronix
> > + * Uwe Kleine-Koenig <u.kleine-koenig@...gutronix.de>
> > + *
> > + * This program is free software; you can redistribute it and/or modify it under
> > + * the terms of the GNU General Public License version 2 as published by the
> > + * Free Software Foundation.
> > + *
> > + * Datasheet: http://datasheets.maxim-ic.com/en/ds/MAX6956.pdf
> > + */
> > +
> > +#include <linux/module.h>
> > +#include <linux/i2c.h>
> > +#include <linux/slab.h>
> > +#include <linux/leds.h>
> > +#include <linux/input.h>
> > +#include <linux/mutex.h>
> > +#include <linux/leds-pca9532.h>
>
> I think we need move all these platform data headers into
> include/linux/platform_data/ as you did below. Anyway, I will take
> care of this.
> Wait, why do you need this header file in your driver? I failed to see
> any usage of it here.
It seems I copy and pasted one #include line too much from the pca9532
driver. I'll remove it in v2.
> > +#include <linux/gpio.h>
> > +#include <linux/regmap.h>
> > +
> > +#include <linux/platform_data/leds-max6956.h>
> > +
> > +#define MAX6956_REG_GLOBAL_CURRENT 0x02
> > +#define MAX6956_REG_CONFIGURATION 0x04
> > +#define MAX6956_REG_CONFIGURATION_S 0x01
> > +#define MAX6956_REG_CONFIGURATION_I 0x40
> > +#define MAX6956_REG_CONFIGURATION_M 0x80
> > +#define MAX6956_REG_TRANSITION_DETECT_MASK 0x06
> > +#define MAX6956_REG_DISPLAY_TEST 0x07
> > +/*
> > + * MAX6956_REG_PORT_CONFIGURATION(i) holds the configuration for ports
> > + * 4 * i, 4 * i + 1, ..., 4 * i + 3 for i in [1, ... 7].
> > + */
> > +#define MAX6956_REG_PORT_CONFIGURATION(i) (0x08 + (i))
> > +#define MAX6956_REG_PORT_CONFIGURATION_LED 0x0
> > +#define MAX6956_REG_PORT_CONFIGURATION_GPIOOUT 0x1
> > +#define MAX6956_REG_PORT_CONFIGURATION_GPIOINPULLUP 0x2
> > +#define MAX6956_REG_PORT_CONFIGURATION_GPIOIN 0x3
> > +/*
> > + * MAX6956_REG_CURRENT(i) holds the current for segments 2 * i, 2 * i + 1 for i
> > + * in [2, .. 15].
>
> Looks like it should be [2, ... 15].
right.
> > +static void max6956_led_work(struct work_struct *work)
> > +{
> > + struct max6956_led_ddata *lddata = lddata_from_work(work);
> > + struct led_classdev *led_cdev = &lddata->cdev;
> > +
> > + struct max6956_ddata *ddata = ddata_from_led_cdev(led_cdev);
> > +
> > + BUG_ON(&ddata->leds[lddata->offset] != lddata);
> > +
> > + if (!lddata->brightness) {
> > + regmap_write(ddata->regmap,
> > + MAX6956_REG_PORT(lddata->offset), 0);
> > + } else {
> > + max6956_set_sink_current(ddata, lddata->offset,
> > + lddata->brightness);
> > + regmap_write(ddata->regmap,
> > + MAX6956_REG_PORT(lddata->offset), 1);
> > + }
> > + max6956_portconfig_set(ddata, lddata->offset, 0);
> > +}
> > +
>
> I believe we might need some locking here to protect this critical
> region, like mutex_lock().
Right, I thought about that, too and intended to ask when submitting the
patch. As regmap_update_bits et al. doesn't do locking, I'll add that in
v2.
> > + ddata = devm_kzalloc(&client->dev, sizeof(*ddata), GFP_KERNEL);
> > + if (!ddata) {
> > + dev_err(&client->dev, "Failed to allocate driver private data\n");
> > + return -ENOMEM;
> > + }
> > +
> > + ddata->dev = &client->dev;
> > + ddata->regmap = devm_regmap_init_i2c(client, &max6956_regmap_config);
> > + if (IS_ERR(ddata->regmap)) {
> > + ret = PTR_ERR(ddata->regmap);
> > + dev_err(ddata->dev, "Failed to allocate register map: %d\n",
> > + ret);
> > + return ret;
>
> As Shuah said, no kfree(ddata) here
As Sascha said, it would be wrong to add one.
> > + }
Best regards
Uwe
--
Pengutronix e.K. | Uwe Kleine-König |
Industrial Linux Solutions | http://www.pengutronix.de/ |
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/
Powered by blists - more mailing lists