mail archive of the barebox mailing list
 help / color / mirror / Atom feed
* [PATCH 0/2] mfd: mc13xxx: ADC support
@ 2018-04-06 16:33 Andrey Gusakov
  2018-04-06 16:33 ` [PATCH 1/2] mfd: mc13xxx: add function returning mc13xxx type Andrey Gusakov
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Andrey Gusakov @ 2018-04-06 16:33 UTC (permalink / raw)
  To: barebox; +Cc: andrey.gusakov, cphealy

This set of pathces adds ADC support for MC13783 and MC13892 PMICs.

Andrey Gusakov (2):
  mfd: mc13xxx: add function returning mc13xxx type
  aiodev: mc13xxx: add adc support

 drivers/aiodev/Kconfig       |   6 ++
 drivers/aiodev/Makefile      |   1 +
 drivers/aiodev/mc13xxx_adc.c | 234 +++++++++++++++++++++++++++++++++++++++++++
 drivers/mfd/mc13xxx.c        |  15 +++
 include/mfd/mc13xxx.h        |  19 ++++
 5 files changed, 275 insertions(+)
 create mode 100644 drivers/aiodev/mc13xxx_adc.c

-- 
1.9.1

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] mfd: mc13xxx: add function returning mc13xxx type
  2018-04-06 16:33 [PATCH 0/2] mfd: mc13xxx: ADC support Andrey Gusakov
@ 2018-04-06 16:33 ` Andrey Gusakov
  2018-04-06 16:33 ` [PATCH 2/2] aiodev: mc13xxx: add adc support Andrey Gusakov
  2018-04-10  7:06 ` [PATCH 0/2] mfd: mc13xxx: ADC support Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Andrey Gusakov @ 2018-04-06 16:33 UTC (permalink / raw)
  To: barebox; +Cc: andrey.gusakov, cphealy

Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
---
 drivers/mfd/mc13xxx.c | 12 ++++++++++++
 include/mfd/mc13xxx.h | 10 ++++++++++
 2 files changed, 22 insertions(+)

diff --git a/drivers/mfd/mc13xxx.c b/drivers/mfd/mc13xxx.c
index f6aa922..654313f 100644
--- a/drivers/mfd/mc13xxx.c
+++ b/drivers/mfd/mc13xxx.c
@@ -40,10 +40,12 @@ struct mc13xxx {
 		struct spi_device	*spi;
 	};
 	int				revision;
+	int				type;
 };
 
 struct mc13xxx_devtype {
 	int	(*revision)(struct mc13xxx*);
+	int	type;
 };
 
 #define to_mc13xxx(a)		container_of(a, struct mc13xxx, cdev)
@@ -56,6 +58,12 @@ struct mc13xxx *mc13xxx_get(void)
 }
 EXPORT_SYMBOL(mc13xxx_get);
 
+int mc13xxx_type(struct mc13xxx *mc13xxx)
+{
+	return mc13xxx->type;
+}
+EXPORT_SYMBOL(mc13xxx_type);
+
 int mc13xxx_revision(struct mc13xxx *mc13xxx)
 {
 	return mc13xxx->revision;
@@ -347,6 +355,7 @@ static int __init mc13xxx_probe(struct device_d *dev)
 	}
 
 	mc_dev->revision = rev;
+	mc_dev->type = devtype->type;
 
 	ret = regmap_register_cdev(mc_dev->map, NULL);
 	if (ret)
@@ -360,14 +369,17 @@ static int __init mc13xxx_probe(struct device_d *dev)
 
 static struct mc13xxx_devtype mc13783_devtype = {
 	.revision	= mc13783_revision,
+	.type		= MC13783_TYPE,
 };
 
 static struct mc13xxx_devtype mc13892_devtype = {
 	.revision	= mc13892_revision,
+	.type		= MC13892_TYPE,
 };
 
 static struct mc13xxx_devtype mc34708_devtype = {
 	.revision	= mc34708_revision,
+	.type		= MC34708_TYPE,
 };
 
 static struct platform_device_id mc13xxx_ids[] = {
diff --git a/include/mfd/mc13xxx.h b/include/mfd/mc13xxx.h
index d351c47..66ce2ea 100644
--- a/include/mfd/mc13xxx.h
+++ b/include/mfd/mc13xxx.h
@@ -16,6 +16,10 @@
 
 #define MC13XXX_REG_IDENTIFICATION	0x07
 
+#define MC13783_TYPE			1
+#define MC13892_TYPE			2
+#define MC34708_TYPE			3
+
 #define MC13783_REG_INT_STATUS0		0x00
 #define MC13783_REG_INT_MASK0		0x01
 #define MC13783_REG_INT_SENSE0		0x02
@@ -168,6 +172,7 @@ struct mc13xxx;
 
 #ifdef CONFIG_MFD_MC13XXX
 extern struct mc13xxx *mc13xxx_get(void);
+extern int mc13xxx_type(struct mc13xxx *mc13xxx);
 extern int mc13xxx_revision(struct mc13xxx *mc13xxx);
 extern int mc13xxx_reg_read(struct mc13xxx *mc13xxx, u8 reg, u32 *val);
 extern int mc13xxx_reg_write(struct mc13xxx *mc13xxx, u8 reg, u32 val);
@@ -179,6 +184,11 @@ static inline struct mc13xxx *mc13xxx_get(void)
 	return NULL;
 }
 
+static inline int mc13xxx_type(struct mc13xxx *mc13xxx)
+{
+	return -ENODEV;
+}
+
 static inline int mc13xxx_revision(struct mc13xxx *mc13xxx)
 {
 	return -ENODEV;
-- 
1.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 2/2] aiodev: mc13xxx: add adc support
  2018-04-06 16:33 [PATCH 0/2] mfd: mc13xxx: ADC support Andrey Gusakov
  2018-04-06 16:33 ` [PATCH 1/2] mfd: mc13xxx: add function returning mc13xxx type Andrey Gusakov
@ 2018-04-06 16:33 ` Andrey Gusakov
  2018-04-10  7:06 ` [PATCH 0/2] mfd: mc13xxx: ADC support Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Andrey Gusakov @ 2018-04-06 16:33 UTC (permalink / raw)
  To: barebox; +Cc: andrey.gusakov, cphealy

Signed-off-by: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
---
 drivers/aiodev/Kconfig       |   6 ++
 drivers/aiodev/Makefile      |   1 +
 drivers/aiodev/mc13xxx_adc.c | 234 +++++++++++++++++++++++++++++++++++++++++++
 drivers/mfd/mc13xxx.c        |   3 +
 include/mfd/mc13xxx.h        |   9 ++
 5 files changed, 253 insertions(+)
 create mode 100644 drivers/aiodev/mc13xxx_adc.c

diff --git a/drivers/aiodev/Kconfig b/drivers/aiodev/Kconfig
index 1c5fabe..8bad946 100644
--- a/drivers/aiodev/Kconfig
+++ b/drivers/aiodev/Kconfig
@@ -20,4 +20,10 @@ config LM75
 	help
 	  Support for LM75 and similar devices
 
+config MC13XXX_ADC
+	tristate "MC13XXX ADC driver"
+	depends on MFD_MC13XXX
+	help
+	  Support for MC13783, MC13892, MC34708 ADC
+
 endif
diff --git a/drivers/aiodev/Makefile b/drivers/aiodev/Makefile
index c3d2b08..1dcf6cd 100644
--- a/drivers/aiodev/Makefile
+++ b/drivers/aiodev/Makefile
@@ -2,3 +2,4 @@
 obj-$(CONFIG_AIODEV) += core.o
 obj-$(CONFIG_IMX_THERMAL) += imx_thermal.o
 obj-$(CONFIG_LM75) += lm75.o
+obj-$(CONFIG_MC13XXX_ADC) += mc13xxx_adc.o
diff --git a/drivers/aiodev/mc13xxx_adc.c b/drivers/aiodev/mc13xxx_adc.c
new file mode 100644
index 0000000..4e72048
--- /dev/null
+++ b/drivers/aiodev/mc13xxx_adc.c
@@ -0,0 +1,234 @@
+/*
+ * mc13xxx_adc
+ *
+ * Copyright (c) 2018 Zodiac Inflight Innovation
+ * Author: Andrey Gusakov <andrey.gusakov@cogentembedded.com>
+ * Based on the code of analogous driver from Linux:
+ * Copyright 2004-2007 Freescale Semiconductor, Inc. All Rights Reserved.
+ * Copyright (C) 2009 Sascha Hauer, Pengutronix
+ *
+ * See file CREDITS for list of people who contributed to this
+ * project.
+ *
+ * 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.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include <common.h>
+#include <init.h>
+#include <malloc.h>
+#include <driver.h>
+#include <xfuncs.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <io.h>
+#include <aiodev.h>
+#include <mfd/mc13xxx.h>
+#include <linux/err.h>
+
+#define MC13XXX_ADC0_LICELLCON		(1 << 0)
+#define MC13XXX_ADC0_CHRGICON		(1 << 1)
+#define MC13XXX_ADC0_BATICON		(1 << 2)
+#define MC13XXX_ADC0_BUFEN		(1 << 3)
+#define MC13XXX_ADC0_ADIN7SEL_DIE	(1 << 4)
+#define MC13XXX_ADC0_ADIN7SEL_UID	(2 << 4)
+#define MC13XXX_ADC0_ADREFEN		(1 << 10)
+#define MC13XXX_ADC0_TSMOD0		(1 << 12)
+#define MC13XXX_ADC0_TSMOD1		(1 << 13)
+#define MC13XXX_ADC0_TSMOD2		(1 << 14)
+#define MC13XXX_ADC0_ADINC1		(1 << 16)
+#define MC13XXX_ADC0_ADINC2		(1 << 17)
+
+#define MC13XXX_ADC0_TSMOD_MASK		(MC13XXX_ADC0_TSMOD0 | \
+					MC13XXX_ADC0_TSMOD1 | \
+					MC13XXX_ADC0_TSMOD2)
+
+#define MC13XXX_ADC0_CONFIG_MASK	(MC13XXX_ADC0_TSMOD_MASK | \
+					MC13XXX_ADC0_LICELLCON | \
+					MC13XXX_ADC0_CHRGICON | \
+					MC13XXX_ADC0_BATICON)
+
+#define MC13XXX_ADC1_ADEN		(1 << 0)
+#define MC13XXX_ADC1_RAND		(1 << 1)
+#define MC13XXX_ADC1_ADSEL		(1 << 3)
+#define MC13XXX_ADC1_CHAN0_SHIFT	5
+#define MC13XXX_ADC1_CHAN1_SHIFT	8
+#define MC13XXX_ADC1_ASC		(1 << 20)
+#define MC13XXX_ADC1_ADTRIGIGN		(1 << 21)
+
+struct mc13xx_adc_data {
+	struct mc13xxx *mc_dev;
+
+	struct aiodevice aiodev;
+	struct aiochannel *aiochan;
+};
+
+static inline struct mc13xx_adc_data *
+to_mc13xx_adc_data(struct aiochannel *chan)
+{
+	return container_of(chan->aiodev, struct mc13xx_adc_data, aiodev);
+}
+
+int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx,
+		unsigned int channel, unsigned int *sample)
+{
+	int i;
+	int timeout = 100;
+	u32 adc0, adc1, old_adc0;
+
+	mc13xxx_reg_read(mc13xxx, MC13783_REG_ADC(0), &old_adc0);
+
+	adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 | MC13XXX_ADC0_BUFEN;
+	adc1 = MC13XXX_ADC1_ADEN | MC13XXX_ADC1_ADTRIGIGN | MC13XXX_ADC1_ASC;
+
+	/* Channels mapped through ADIN7:
+	 * 7  - General purpose ADIN7
+	 * 16 - UID
+	 * 17 - Die temperature */
+	if (channel > 7 && channel < 16) {
+		adc1 |= MC13XXX_ADC1_ADSEL;
+	} else if (channel == 16) {
+		adc0 |= MC13XXX_ADC0_ADIN7SEL_UID;
+		channel = 7;
+	} else if (channel == 17) {
+		adc0 |= MC13XXX_ADC0_ADIN7SEL_DIE;
+		channel = 7;
+	}
+
+	adc0 |= old_adc0 & MC13XXX_ADC0_CONFIG_MASK;
+	adc1 |= (channel & 0x7) << MC13XXX_ADC1_CHAN0_SHIFT;
+	adc1 |= MC13XXX_ADC1_RAND;
+
+	mc13xxx_reg_write(mc13xxx, MC13783_REG_ADC(0), adc0);
+	mc13xxx_reg_write(mc13xxx, MC13783_REG_ADC(1), adc1);
+
+	/* wait for completion. ASC will set to zero */
+	do {
+		mc13xxx_reg_read(mc13xxx, MC13783_REG_ADC(1), &adc1);
+	} while ((adc1 & MC13XXX_ADC1_ASC) && (--timeout > 0));
+
+	if (timeout == 0)
+		return -ETIMEDOUT;
+
+	for (i = 0; i < 4; ++i) {
+		mc13xxx_reg_read(mc13xxx,
+			MC13783_REG_ADC(2), &sample[i]);
+	}
+
+	return 0;
+}
+
+static int mc13xx_adc_read(struct aiochannel *chan, int *val)
+{
+	int i;
+	int ret;
+	int mc_type;
+	unsigned int sample[4];
+	struct mc13xx_adc_data *mc13xxx_adc;
+	int acc = 0;
+	int index = chan->index;
+
+	mc13xxx_adc = to_mc13xx_adc_data(chan);
+	mc_type = mc13xxx_type(mc13xxx_adc->mc_dev);
+
+	/* add offset for all 8 channel devices becouse t and UID
+	 * inputs are mapped to channels 16 and 17 */
+	if ((mc_type != MC13783_TYPE) && (chan->index > 7))
+		index += 8;
+
+	ret = mc13xxx_adc_do_conversion(mc13xxx_adc->mc_dev, index, sample);
+	if (ret < 0)
+		goto err;
+
+	for (i = 0; i < 4; i++) {
+		acc += (sample[i] >> 2 & 0x3ff);
+		acc += (sample[i] >> 14 & 0x3ff);
+	}
+	/* div 8 */
+	acc = acc >> 3;
+
+	if (index == 16) {
+		/* UID */
+		if (mc_type == MC13892_TYPE) {
+			/* MC13892 have 1/2 divider
+			 * input range is [0, 4.800V] */
+			acc = DIV_ROUND_CLOSEST(acc * 4800, 1024);
+		} else {
+			/* MC13783 have 0.9 divider
+			 *input range is [0, 2.555V] */
+			acc = DIV_ROUND_CLOSEST(acc * 2555, 1024);
+		}
+	} else if (index == 17) {
+		/* Die temperature */
+		if (mc_type == MC13892_TYPE) {
+			/* MC13892:
+			 * Die Temperature Read Out Code at 25C 680
+			 * Temperature change per LSB +0.4244C */
+			acc = DIV_ROUND_CLOSEST(-2635920 + acc * 4244, 10);
+		} else {
+			/* MC13783:
+			 * Die Temperature Read Out Code at 25C 282
+			 * Temperature change per LSB -1.14C */
+			acc = 346480 - 1140 * acc;
+		}
+	} else {
+		/* GP input
+		 * input range is [0, 2.3V], value has 10 bits */
+		acc = DIV_ROUND_CLOSEST(acc * 2300, 1024);
+	}
+
+	*val = acc;
+err:
+	return ret;
+}
+
+int mc13xxx_adc_probe(struct device_d *dev, struct mc13xxx *mc_dev)
+{
+	int i;
+	int ret;
+	int chans;
+	struct mc13xx_adc_data *mc13xxx_adc;
+
+	mc13xxx_adc = xzalloc(sizeof(*mc13xxx_adc));
+
+	if (mc13xxx_type(mc_dev) == MC13783_TYPE) {
+		/* mc13783 has 16 channels */
+		chans = 16 + 2;
+	} else {
+		chans = 8 + 2;
+	}
+
+	mc13xxx_adc->mc_dev = mc_dev;
+	mc13xxx_adc->aiodev.num_channels = chans;
+	mc13xxx_adc->aiochan = xmalloc(mc13xxx_adc->aiodev.num_channels *
+			sizeof(*mc13xxx_adc->aiochan));
+	mc13xxx_adc->aiodev.hwdev = dev;
+	mc13xxx_adc->aiodev.channels =
+		xmalloc(mc13xxx_adc->aiodev.num_channels *
+			sizeof(mc13xxx_adc->aiodev.channels[0]));
+	/* all channels are voltage inputs, expect last one */
+	for (i = 0; i < chans - 1; i++) {
+		mc13xxx_adc->aiodev.channels[i] = &mc13xxx_adc->aiochan[i];
+		mc13xxx_adc->aiochan[i].unit = "mV";
+	}
+	/* temperature input */
+	mc13xxx_adc->aiodev.channels[i] = &mc13xxx_adc->aiochan[i];
+	mc13xxx_adc->aiochan[i].unit = "mC";
+
+	mc13xxx_adc->aiodev.read = mc13xx_adc_read;
+
+	ret = aiodevice_register(&mc13xxx_adc->aiodev);
+	if (!ret)
+		goto done;
+
+	dev_err(dev, "Failed to register AIODEV: %d\n", ret);
+	kfree(mc13xxx_adc);
+done:
+	return ret;
+}
diff --git a/drivers/mfd/mc13xxx.c b/drivers/mfd/mc13xxx.c
index 654313f..a5877db 100644
--- a/drivers/mfd/mc13xxx.c
+++ b/drivers/mfd/mc13xxx.c
@@ -364,6 +364,9 @@ static int __init mc13xxx_probe(struct device_d *dev)
 	if (mc13xxx_init_callback)
 		mc13xxx_init_callback(mc_dev);
 
+	if (of_property_read_bool(dev->device_node, "fsl,mc13xxx-uses-adc"))
+		mc13xxx_adc_probe(dev, mc_dev);
+
 	return 0;
 }
 
diff --git a/include/mfd/mc13xxx.h b/include/mfd/mc13xxx.h
index 66ce2ea..b389180 100644
--- a/include/mfd/mc13xxx.h
+++ b/include/mfd/mc13xxx.h
@@ -215,4 +215,13 @@ static inline int mc13xxx_register_init_callback(void(*callback)(struct mc13xxx
 }
 #endif
 
+#ifdef CONFIG_MC13XXX_ADC
+int mc13xxx_adc_probe(struct device_d *dev, struct mc13xxx *mc_dev);
+#else
+static inline int mc13xxx_adc_probe(struct device_d *dev, struct mc13xxx *mc_dev)
+{
+	return 0;
+}
+#endif
+
 #endif /* __MFD_MC13XXX_H */
-- 
1.9.1


_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] mfd: mc13xxx: ADC support
  2018-04-06 16:33 [PATCH 0/2] mfd: mc13xxx: ADC support Andrey Gusakov
  2018-04-06 16:33 ` [PATCH 1/2] mfd: mc13xxx: add function returning mc13xxx type Andrey Gusakov
  2018-04-06 16:33 ` [PATCH 2/2] aiodev: mc13xxx: add adc support Andrey Gusakov
@ 2018-04-10  7:06 ` Sascha Hauer
  2 siblings, 0 replies; 4+ messages in thread
From: Sascha Hauer @ 2018-04-10  7:06 UTC (permalink / raw)
  To: Andrey Gusakov; +Cc: barebox, cphealy

Hi Andrey,

On Fri, Apr 06, 2018 at 07:33:22PM +0300, Andrey Gusakov wrote:
> This set of pathces adds ADC support for MC13783 and MC13892 PMICs.

Applied, thanks. Out of curiosity, what do you use the ADCs for?

Sascha

> 
> Andrey Gusakov (2):
>   mfd: mc13xxx: add function returning mc13xxx type
>   aiodev: mc13xxx: add adc support
> 
>  drivers/aiodev/Kconfig       |   6 ++
>  drivers/aiodev/Makefile      |   1 +
>  drivers/aiodev/mc13xxx_adc.c | 234 +++++++++++++++++++++++++++++++++++++++++++
>  drivers/mfd/mc13xxx.c        |  15 +++
>  include/mfd/mc13xxx.h        |  19 ++++
>  5 files changed, 275 insertions(+)
>  create mode 100644 drivers/aiodev/mc13xxx_adc.c
> 
> -- 
> 1.9.1
> 
> _______________________________________________
> barebox mailing list
> barebox@lists.infradead.org
> http://lists.infradead.org/mailman/listinfo/barebox
> 

-- 
Pengutronix e.K.                           |                             |
Industrial Linux Solutions                 | http://www.pengutronix.de/  |
Peiner Str. 6-8, 31137 Hildesheim, Germany | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
barebox@lists.infradead.org
http://lists.infradead.org/mailman/listinfo/barebox

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-04-10  7:06 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-04-06 16:33 [PATCH 0/2] mfd: mc13xxx: ADC support Andrey Gusakov
2018-04-06 16:33 ` [PATCH 1/2] mfd: mc13xxx: add function returning mc13xxx type Andrey Gusakov
2018-04-06 16:33 ` [PATCH 2/2] aiodev: mc13xxx: add adc support Andrey Gusakov
2018-04-10  7:06 ` [PATCH 0/2] mfd: mc13xxx: ADC support Sascha Hauer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox