* [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