Message ID | 20210430123511.116057-1-robert.marko@sartura.hr (mailing list archive) |
---|---|
State | Not Applicable |
Headers | show |
Series | [1/6] mfd: Add Delta TN48M CPLD driver | expand |
Hi Robert, Am 2021-04-30 14:35, schrieb Robert Marko: > Delta TN48M switches have a Lattice CPLD that serves > multiple purposes including being a GPIO expander. > So lets add the MFD core driver for it. Did you have a look at mfd/simple-mfd-i2c.c? -michael
Hi Robert, I love your patch! Yet something to improve: [auto build test ERROR on lee-mfd/for-mfd-next] [also build test ERROR on hwmon/hwmon-next gpio/for-next v5.12 next-20210506] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Robert-Marko/mfd-Add-Delta-TN48M-CPLD-driver/20210430-203709 base: https://git.kernel.org/pub/scm/linux/kernel/git/lee/mfd.git for-mfd-next config: x86_64-allyesconfig (attached as .config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 reproduce (this is a W=1 build): # https://github.com/0day-ci/linux/commit/4a3a37836c56a383a726a52892d69bfdd1cf5d4c git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Robert-Marko/mfd-Add-Delta-TN48M-CPLD-driver/20210430-203709 git checkout 4a3a37836c56a383a726a52892d69bfdd1cf5d4c # save the attached .config to linux build tree make W=1 W=1 ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): drivers/mfd/tn48m-cpld.c: In function 'hardware_version_show': >> drivers/mfd/tn48m-cpld.c:36:10: error: implicit declaration of function 'FIELD_GET' [-Werror=implicit-function-declaration] 36 | switch (FIELD_GET(HARDWARE_VERSION_MASK, regval)) { | ^~~~~~~~~ cc1: some warnings being treated as errors vim +/FIELD_GET +36 drivers/mfd/tn48m-cpld.c 27 28 static int hardware_version_show(struct seq_file *s, void *data) 29 { 30 struct tn48m_data *priv = s->private; 31 unsigned int regval; 32 char *buf; 33 34 regmap_read(priv->regmap, HARDWARE_VERSION_ID, ®val); 35 > 36 switch (FIELD_GET(HARDWARE_VERSION_MASK, regval)) { 37 case HARDWARE_VERSION_EVT1: 38 buf = "EVT1"; 39 break; 40 case HARDWARE_VERSION_EVT2: 41 buf = "EVT2"; 42 break; 43 case HARDWARE_VERSION_DVT: 44 buf = "DVT"; 45 break; 46 case HARDWARE_VERSION_PVT: 47 buf = "PVT"; 48 break; 49 default: 50 buf = "Unknown"; 51 break; 52 } 53 54 seq_printf(s, "%s\n", buf); 55 56 return 0; 57 } 58 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
On Fri, 30 Apr 2021, Robert Marko wrote: > Delta TN48M switches have a Lattice CPLD that serves > multiple purposes including being a GPIO expander. > So lets add the MFD core driver for it. > > Signed-off-by: Robert Marko <robert.marko@sartura.hr> > --- > drivers/mfd/Kconfig | 13 +++ > drivers/mfd/Makefile | 1 + > drivers/mfd/tn48m-cpld.c | 181 ++++++++++++++++++++++++++++++++++++++ > include/linux/mfd/tn48m.h | 30 +++++++ > 4 files changed, 225 insertions(+) > create mode 100644 drivers/mfd/tn48m-cpld.c > create mode 100644 include/linux/mfd/tn48m.h > > diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig > index b74efa469e90..809041f98d71 100644 > --- a/drivers/mfd/Kconfig > +++ b/drivers/mfd/Kconfig > @@ -297,6 +297,19 @@ config MFD_ASIC3 > This driver supports the ASIC3 multifunction chip found on many > PDAs (mainly iPAQ and HTC based ones) > > +config MFD_TN48M_CPLD > + tristate "Delta Networks TN48M switch CPLD driver" > + depends on I2C > + select MFD_CORE > + select REGMAP_I2C > + help > + Select this option to enable support for Delta Networks TN48M switch > + CPLD. It consists of GPIO and hwmon drivers. > + CPLD provides GPIOS-s for the SFP slots as well as power supply > + related information. > + Driver provides debugfs information about the board model as > + well as hardware and CPLD revision information. No need for every sentence to be it's own paragraphs. Please re-align to be a single chunk. > config PMIC_DA903X > bool "Dialog Semiconductor DA9030/DA9034 PMIC Support" > depends on I2C=y > diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile > index 834f5463af28..974663341f08 100644 > --- a/drivers/mfd/Makefile > +++ b/drivers/mfd/Makefile > @@ -27,6 +27,7 @@ obj-$(CONFIG_MFD_TI_LP87565) += lp87565.o > obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o > obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o > obj-$(CONFIG_MFD_TI_AM335X_TSCADC) += ti_am335x_tscadc.o > +obj-$(CONFIG_MFD_TN48M_CPLD) += tn48m-cpld.o > > obj-$(CONFIG_MFD_STA2X11) += sta2x11-mfd.o > obj-$(CONFIG_MFD_STMPE) += stmpe.o > diff --git a/drivers/mfd/tn48m-cpld.c b/drivers/mfd/tn48m-cpld.c > new file mode 100644 > index 000000000000..b84510fb630a > --- /dev/null > +++ b/drivers/mfd/tn48m-cpld.c > @@ -0,0 +1,181 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Delta TN48M CPLD parent driver > + * > + * Copyright 2020 Sartura Ltd This is out of date. > + * Author: Robert Marko <robert.marko@sartura.hr> > + */ > + > +#include <linux/debugfs.h> > +#include <linux/i2c.h> > +#include <linux/kernel.h> > +#include <linux/mfd/core.h> > +#include <linux/mfd/tn48m.h> > +#include <linux/module.h> > +#include <linux/platform_device.h> > +#include <linux/regmap.h> > +#include <linux/slab.h> > + > +static const struct mfd_cell tn48m_cell[] = {}; Please populate this. Without it, this is not an MFD. > +static const struct regmap_config tn48m_regmap_config = { > + .reg_bits = 8, > + .val_bits = 8, > + .max_register = 0x40, > +}; > + > +static int hardware_version_show(struct seq_file *s, void *data) > +{ > + struct tn48m_data *priv = s->private; > + unsigned int regval; > + char *buf; > + > + regmap_read(priv->regmap, HARDWARE_VERSION_ID, ®val); > + > + switch (FIELD_GET(HARDWARE_VERSION_MASK, regval)) { > + case HARDWARE_VERSION_EVT1: > + buf = "EVT1"; > + break; > + case HARDWARE_VERSION_EVT2: > + buf = "EVT2"; > + break; > + case HARDWARE_VERSION_DVT: > + buf = "DVT"; > + break; > + case HARDWARE_VERSION_PVT: > + buf = "PVT"; > + break; > + default: > + buf = "Unknown"; > + break; > + } > + > + seq_printf(s, "%s\n", buf); > + > + return 0; > +} > + Please drop this '\n'. > +DEFINE_SHOW_ATTRIBUTE(hardware_version); > + > +static int board_id_show(struct seq_file *s, void *data) > +{ > + struct tn48m_data *priv = s->private; > + unsigned int regval; > + char *buf; > + > + regmap_read(priv->regmap, BOARD_ID, ®val); > + > + switch (regval) { > + case BOARD_ID_TN48M: > + buf = "TN48M"; > + break; > + case BOARD_ID_TN48M_P: > + buf = "TN48-P"; > + break; > + default: > + buf = "Unknown"; > + break; > + } > + > + seq_printf(s, "%s\n", buf); > + > + return 0; > +} > + Please drop this '\n'. > +DEFINE_SHOW_ATTRIBUTE(board_id); > + > +static int code_version_show(struct seq_file *s, void *data) > +{ > + struct tn48m_data *priv = s->private; > + unsigned int regval; > + > + regmap_read(priv->regmap, CPLD_CODE_VERSION, ®val); > + > + seq_printf(s, "%d\n", regval); > + > + return 0; > +} > + Please drop this '\n'. > +DEFINE_SHOW_ATTRIBUTE(code_version); > + > +static void tn48m_init_debugfs(struct tn48m_data *data) > +{ > + data->debugfs_dir = debugfs_create_dir(data->client->name, NULL); > + > + debugfs_create_file("hardware_version", > + 0400, > + data->debugfs_dir, > + data, > + &hardware_version_fops); > + > + debugfs_create_file("board_id", > + 0400, > + data->debugfs_dir, > + data, > + &board_id_fops); > + > + debugfs_create_file("code_version", > + 0400, > + data->debugfs_dir, > + data, > + &code_version_fops); > +} Does S/W actually do anything useful with these files? Or are they just there for the sake of it? If the latter, just print them to the kernel log and have done. > +static int tn48m_probe(struct i2c_client *client) > +{ > + struct tn48m_data *data; 'ddata' for both please. > + int ret; > + > + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); > + if (!data) > + return -ENOMEM; > + > + data->client = client; > + data->dev = &client->dev; > + i2c_set_clientdata(client, data); > + > + data->regmap = devm_regmap_init_i2c(client, &tn48m_regmap_config); > + if (IS_ERR(data->regmap)) { > + dev_err(data->dev, "Failed to allocate regmap\n"); > + return PTR_ERR(data->regmap); > + } > + > + ret = devm_mfd_add_devices(data->dev, PLATFORM_DEVID_AUTO, tn48m_cell, > + ARRAY_SIZE(tn48m_cell), NULL, 0, NULL); > + if (ret) > + dev_err(data->dev, "Failed to register sub-devices %d\n", ret); > + > + tn48m_init_debugfs(data); > + > + return ret; > +} > + > +static int tn48m_remove(struct i2c_client *client) > +{ > + struct tn48m_data *data = i2c_get_clientdata(client); > + > + debugfs_remove_recursive(data->debugfs_dir); > + > + return 0; > +} > + > +static const struct of_device_id tn48m_of_match[] = { > + { .compatible = "delta,tn48m-cpld"}, Missing ' ' before the '}'. > + { } > +}; > +MODULE_DEVICE_TABLE(of, tn48m_of_match); > + > +static struct i2c_driver tn48m_driver = { > + .driver = { > + .name = "tn48m-cpld", > + .of_match_table = tn48m_of_match, > + }, > + .probe_new = tn48m_probe, > + .remove = tn48m_remove, > +}; > +module_i2c_driver(tn48m_driver); > + > +MODULE_AUTHOR("Robert Marko <robert.marko@sartura.hr>"); > +MODULE_DESCRIPTION("Delta TN48M CPLD parent driver"); > +MODULE_LICENSE("GPL"); > diff --git a/include/linux/mfd/tn48m.h b/include/linux/mfd/tn48m.h > new file mode 100644 > index 000000000000..551c550efa54 > --- /dev/null > +++ b/include/linux/mfd/tn48m.h > @@ -0,0 +1,30 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +/* > + * Copyright 2020 Sartura Ltd Out of date. > + */ > + > +#ifndef __TN48M_H__ > +#define __TN48M_H__ Better prefix with MFD. > +#include <linux/device.h> > +#include <linux/regmap.h> > + > +#define HARDWARE_VERSION_ID 0x0 > +#define HARDWARE_VERSION_MASK GENMASK(3, 0) > +#define HARDWARE_VERSION_EVT1 0 > +#define HARDWARE_VERSION_EVT2 1 > +#define HARDWARE_VERSION_DVT 2 > +#define HARDWARE_VERSION_PVT 3 > +#define BOARD_ID 0x1 > +#define BOARD_ID_TN48M 0xa > +#define BOARD_ID_TN48M_P 0xb > +#define CPLD_CODE_VERSION 0x2 > + > +struct tn48m_data { > + struct device *dev; > + struct regmap *regmap; > + struct i2c_client *client; You don't need both 'dev' and 'client'. > + struct dentry *debugfs_dir; > +}; > + > +#endif
On Thu, May 6, 2021 at 6:34 PM Michael Walle <michael@walle.cc> wrote: > > Hi Robert, > > Am 2021-04-30 14:35, schrieb Robert Marko: > > Delta TN48M switches have a Lattice CPLD that serves > > multiple purposes including being a GPIO expander. > > So lets add the MFD core driver for it. > > Did you have a look at mfd/simple-mfd-i2c.c? Hi Michael, Yes, that was my first idea but we have a requirement to expose CPLD information via debugfs as there are userspace applications using it. And simple-mfd-i2c does not allow us to do so. Regards, Robert > > -michael
Hi, Am 2021-05-19 13:53, schrieb Robert Marko: > On Thu, May 6, 2021 at 6:34 PM Michael Walle <michael@walle.cc> wrote: >> Am 2021-04-30 14:35, schrieb Robert Marko: >> > Delta TN48M switches have a Lattice CPLD that serves >> > multiple purposes including being a GPIO expander. >> > So lets add the MFD core driver for it. >> >> Did you have a look at mfd/simple-mfd-i2c.c? > > Yes, that was my first idea but we have a requirement to expose CPLD > information via debugfs as there are userspace applications using it. > And simple-mfd-i2c does not allow us to do so. Mh, last time Lee wasn't very fond of having a driver that just populates sub-drivers while doing almost nothing itself. See https://lore.kernel.org/lkml/20200605065709.GD3714@dell/ That being said, I'd also like to expose our CPLD version, but until now haven't found a good solution. -michael
On Wed, 19 May 2021, Michael Walle wrote: > Hi, > > Am 2021-05-19 13:53, schrieb Robert Marko: > > On Thu, May 6, 2021 at 6:34 PM Michael Walle <michael@walle.cc> wrote: > > > Am 2021-04-30 14:35, schrieb Robert Marko: > > > > Delta TN48M switches have a Lattice CPLD that serves > > > > multiple purposes including being a GPIO expander. > > > > So lets add the MFD core driver for it. > > > > > > Did you have a look at mfd/simple-mfd-i2c.c? > > > > Yes, that was my first idea but we have a requirement to expose CPLD > > information via debugfs as there are userspace applications using it. > > And simple-mfd-i2c does not allow us to do so. > > Mh, last time Lee wasn't very fond of having a driver that just populates > sub-drivers while doing almost nothing itself. See > https://lore.kernel.org/lkml/20200605065709.GD3714@dell/ Right. I still feel that way. > That being said, I'd also like to expose our CPLD version, but until now > haven't found a good solution. Why though? Does S/W *need* it?
On Thu, May 20, 2021 at 8:49 AM Lee Jones <lee.jones@linaro.org> wrote: > > On Wed, 19 May 2021, Michael Walle wrote: > > > Hi, > > > > Am 2021-05-19 13:53, schrieb Robert Marko: > > > On Thu, May 6, 2021 at 6:34 PM Michael Walle <michael@walle.cc> wrote: > > > > Am 2021-04-30 14:35, schrieb Robert Marko: > > > > > Delta TN48M switches have a Lattice CPLD that serves > > > > > multiple purposes including being a GPIO expander. > > > > > So lets add the MFD core driver for it. > > > > > > > > Did you have a look at mfd/simple-mfd-i2c.c? > > > > > > Yes, that was my first idea but we have a requirement to expose CPLD > > > information via debugfs as there are userspace applications using it. > > > And simple-mfd-i2c does not allow us to do so. > > > > Mh, last time Lee wasn't very fond of having a driver that just populates > > sub-drivers while doing almost nothing itself. See > > https://lore.kernel.org/lkml/20200605065709.GD3714@dell/ > > Right. I still feel that way. > > > That being said, I'd also like to expose our CPLD version, but until now > > haven't found a good solution. > > Why though? Does S/W *need* it? Because we have userspace S/W that uses it as the same CPLD is in multiple variants of the board but the correct board model is set during manufacturing and we can read it from the CPLD. We also have information about PSU1 and PSU2(Some models only) power good, whether they are present and some other info that I need to expose as these are monitored in userspace. I planned to do that via the hwmon driver but according to Guenther they are not hwmon attributes and I agree. Would it be possible to have a dedicated driver that would only expose the required information via debugfs? Then I could simply use the simple I2C MFD driver with only a GPIO driver on top of it. Regards, Robert > > -- > Lee Jones [李琼斯] > Senior Technical Lead - Developer Services > Linaro.org │ Open source software for Arm SoCs > Follow Linaro: Facebook | Twitter | Blog
On Fri, 21 May 2021, Robert Marko wrote: > On Thu, May 20, 2021 at 8:49 AM Lee Jones <lee.jones@linaro.org> wrote: > > > > On Wed, 19 May 2021, Michael Walle wrote: > > > > > Hi, > > > > > > Am 2021-05-19 13:53, schrieb Robert Marko: > > > > On Thu, May 6, 2021 at 6:34 PM Michael Walle <michael@walle.cc> wrote: > > > > > Am 2021-04-30 14:35, schrieb Robert Marko: > > > > > > Delta TN48M switches have a Lattice CPLD that serves > > > > > > multiple purposes including being a GPIO expander. > > > > > > So lets add the MFD core driver for it. > > > > > > > > > > Did you have a look at mfd/simple-mfd-i2c.c? > > > > > > > > Yes, that was my first idea but we have a requirement to expose CPLD > > > > information via debugfs as there are userspace applications using it. > > > > And simple-mfd-i2c does not allow us to do so. > > > > > > Mh, last time Lee wasn't very fond of having a driver that just populates > > > sub-drivers while doing almost nothing itself. See > > > https://lore.kernel.org/lkml/20200605065709.GD3714@dell/ > > > > Right. I still feel that way. > > > > > That being said, I'd also like to expose our CPLD version, but until now > > > haven't found a good solution. > > > > Why though? Does S/W *need* it? > Because we have userspace S/W that uses it as the same CPLD is in > multiple variants of the board but the correct board model is set during > manufacturing and we can read it from the CPLD. > > We also have information about PSU1 and PSU2(Some models only) > power good, whether they are present and some other info that I need > to expose as these are monitored in userspace. > > I planned to do that via the hwmon driver but according to Guenther they > are not hwmon attributes and I agree. > > Would it be possible to have a dedicated driver that would only expose > the required information via debugfs? > Then I could simply use the simple I2C MFD driver with only a GPIO > driver on top of it. Yes, I was going to suggest that. It should probably live in drivers/misc.
On Fri, May 21, 2021 at 11:04 AM Lee Jones <lee.jones@linaro.org> wrote: > > On Fri, 21 May 2021, Robert Marko wrote: > > > On Thu, May 20, 2021 at 8:49 AM Lee Jones <lee.jones@linaro.org> wrote: > > > > > > On Wed, 19 May 2021, Michael Walle wrote: > > > > > > > Hi, > > > > > > > > Am 2021-05-19 13:53, schrieb Robert Marko: > > > > > On Thu, May 6, 2021 at 6:34 PM Michael Walle <michael@walle.cc> wrote: > > > > > > Am 2021-04-30 14:35, schrieb Robert Marko: > > > > > > > Delta TN48M switches have a Lattice CPLD that serves > > > > > > > multiple purposes including being a GPIO expander. > > > > > > > So lets add the MFD core driver for it. > > > > > > > > > > > > Did you have a look at mfd/simple-mfd-i2c.c? > > > > > > > > > > Yes, that was my first idea but we have a requirement to expose CPLD > > > > > information via debugfs as there are userspace applications using it. > > > > > And simple-mfd-i2c does not allow us to do so. > > > > > > > > Mh, last time Lee wasn't very fond of having a driver that just populates > > > > sub-drivers while doing almost nothing itself. See > > > > https://lore.kernel.org/lkml/20200605065709.GD3714@dell/ > > > > > > Right. I still feel that way. > > > > > > > That being said, I'd also like to expose our CPLD version, but until now > > > > haven't found a good solution. > > > > > > Why though? Does S/W *need* it? > > Because we have userspace S/W that uses it as the same CPLD is in > > multiple variants of the board but the correct board model is set during > > manufacturing and we can read it from the CPLD. > > > > We also have information about PSU1 and PSU2(Some models only) > > power good, whether they are present and some other info that I need > > to expose as these are monitored in userspace. > > > > I planned to do that via the hwmon driver but according to Guenther they > > are not hwmon attributes and I agree. > > > > Would it be possible to have a dedicated driver that would only expose > > the required information via debugfs? > > Then I could simply use the simple I2C MFD driver with only a GPIO > > driver on top of it. > > Yes, I was going to suggest that. > > It should probably live in drivers/misc. OK, that works for me. I will then rework this for v2. Regards, Robert > > -- > Lee Jones [李琼斯] > Senior Technical Lead - Developer Services > Linaro.org │ Open source software for Arm SoCs > Follow Linaro: Facebook | Twitter | Blog
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig index b74efa469e90..809041f98d71 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig @@ -297,6 +297,19 @@ config MFD_ASIC3 This driver supports the ASIC3 multifunction chip found on many PDAs (mainly iPAQ and HTC based ones) +config MFD_TN48M_CPLD + tristate "Delta Networks TN48M switch CPLD driver" + depends on I2C + select MFD_CORE + select REGMAP_I2C + help + Select this option to enable support for Delta Networks TN48M switch + CPLD. It consists of GPIO and hwmon drivers. + CPLD provides GPIOS-s for the SFP slots as well as power supply + related information. + Driver provides debugfs information about the board model as + well as hardware and CPLD revision information. + config PMIC_DA903X bool "Dialog Semiconductor DA9030/DA9034 PMIC Support" depends on I2C=y diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile index 834f5463af28..974663341f08 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile @@ -27,6 +27,7 @@ obj-$(CONFIG_MFD_TI_LP87565) += lp87565.o obj-$(CONFIG_MFD_DAVINCI_VOICECODEC) += davinci_voicecodec.o obj-$(CONFIG_MFD_DM355EVM_MSP) += dm355evm_msp.o obj-$(CONFIG_MFD_TI_AM335X_TSCADC) += ti_am335x_tscadc.o +obj-$(CONFIG_MFD_TN48M_CPLD) += tn48m-cpld.o obj-$(CONFIG_MFD_STA2X11) += sta2x11-mfd.o obj-$(CONFIG_MFD_STMPE) += stmpe.o diff --git a/drivers/mfd/tn48m-cpld.c b/drivers/mfd/tn48m-cpld.c new file mode 100644 index 000000000000..b84510fb630a --- /dev/null +++ b/drivers/mfd/tn48m-cpld.c @@ -0,0 +1,181 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Delta TN48M CPLD parent driver + * + * Copyright 2020 Sartura Ltd + * + * Author: Robert Marko <robert.marko@sartura.hr> + */ + +#include <linux/debugfs.h> +#include <linux/i2c.h> +#include <linux/kernel.h> +#include <linux/mfd/core.h> +#include <linux/mfd/tn48m.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/regmap.h> +#include <linux/slab.h> + +static const struct mfd_cell tn48m_cell[] = {}; + +static const struct regmap_config tn48m_regmap_config = { + .reg_bits = 8, + .val_bits = 8, + .max_register = 0x40, +}; + +static int hardware_version_show(struct seq_file *s, void *data) +{ + struct tn48m_data *priv = s->private; + unsigned int regval; + char *buf; + + regmap_read(priv->regmap, HARDWARE_VERSION_ID, ®val); + + switch (FIELD_GET(HARDWARE_VERSION_MASK, regval)) { + case HARDWARE_VERSION_EVT1: + buf = "EVT1"; + break; + case HARDWARE_VERSION_EVT2: + buf = "EVT2"; + break; + case HARDWARE_VERSION_DVT: + buf = "DVT"; + break; + case HARDWARE_VERSION_PVT: + buf = "PVT"; + break; + default: + buf = "Unknown"; + break; + } + + seq_printf(s, "%s\n", buf); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(hardware_version); + +static int board_id_show(struct seq_file *s, void *data) +{ + struct tn48m_data *priv = s->private; + unsigned int regval; + char *buf; + + regmap_read(priv->regmap, BOARD_ID, ®val); + + switch (regval) { + case BOARD_ID_TN48M: + buf = "TN48M"; + break; + case BOARD_ID_TN48M_P: + buf = "TN48-P"; + break; + default: + buf = "Unknown"; + break; + } + + seq_printf(s, "%s\n", buf); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(board_id); + +static int code_version_show(struct seq_file *s, void *data) +{ + struct tn48m_data *priv = s->private; + unsigned int regval; + + regmap_read(priv->regmap, CPLD_CODE_VERSION, ®val); + + seq_printf(s, "%d\n", regval); + + return 0; +} + +DEFINE_SHOW_ATTRIBUTE(code_version); + +static void tn48m_init_debugfs(struct tn48m_data *data) +{ + data->debugfs_dir = debugfs_create_dir(data->client->name, NULL); + + debugfs_create_file("hardware_version", + 0400, + data->debugfs_dir, + data, + &hardware_version_fops); + + debugfs_create_file("board_id", + 0400, + data->debugfs_dir, + data, + &board_id_fops); + + debugfs_create_file("code_version", + 0400, + data->debugfs_dir, + data, + &code_version_fops); +} + +static int tn48m_probe(struct i2c_client *client) +{ + struct tn48m_data *data; + int ret; + + data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + data->client = client; + data->dev = &client->dev; + i2c_set_clientdata(client, data); + + data->regmap = devm_regmap_init_i2c(client, &tn48m_regmap_config); + if (IS_ERR(data->regmap)) { + dev_err(data->dev, "Failed to allocate regmap\n"); + return PTR_ERR(data->regmap); + } + + ret = devm_mfd_add_devices(data->dev, PLATFORM_DEVID_AUTO, tn48m_cell, + ARRAY_SIZE(tn48m_cell), NULL, 0, NULL); + if (ret) + dev_err(data->dev, "Failed to register sub-devices %d\n", ret); + + tn48m_init_debugfs(data); + + return ret; +} + +static int tn48m_remove(struct i2c_client *client) +{ + struct tn48m_data *data = i2c_get_clientdata(client); + + debugfs_remove_recursive(data->debugfs_dir); + + return 0; +} + +static const struct of_device_id tn48m_of_match[] = { + { .compatible = "delta,tn48m-cpld"}, + { } +}; +MODULE_DEVICE_TABLE(of, tn48m_of_match); + +static struct i2c_driver tn48m_driver = { + .driver = { + .name = "tn48m-cpld", + .of_match_table = tn48m_of_match, + }, + .probe_new = tn48m_probe, + .remove = tn48m_remove, +}; +module_i2c_driver(tn48m_driver); + +MODULE_AUTHOR("Robert Marko <robert.marko@sartura.hr>"); +MODULE_DESCRIPTION("Delta TN48M CPLD parent driver"); +MODULE_LICENSE("GPL"); diff --git a/include/linux/mfd/tn48m.h b/include/linux/mfd/tn48m.h new file mode 100644 index 000000000000..551c550efa54 --- /dev/null +++ b/include/linux/mfd/tn48m.h @@ -0,0 +1,30 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright 2020 Sartura Ltd + */ + +#ifndef __TN48M_H__ +#define __TN48M_H__ + +#include <linux/device.h> +#include <linux/regmap.h> + +#define HARDWARE_VERSION_ID 0x0 +#define HARDWARE_VERSION_MASK GENMASK(3, 0) +#define HARDWARE_VERSION_EVT1 0 +#define HARDWARE_VERSION_EVT2 1 +#define HARDWARE_VERSION_DVT 2 +#define HARDWARE_VERSION_PVT 3 +#define BOARD_ID 0x1 +#define BOARD_ID_TN48M 0xa +#define BOARD_ID_TN48M_P 0xb +#define CPLD_CODE_VERSION 0x2 + +struct tn48m_data { + struct device *dev; + struct regmap *regmap; + struct i2c_client *client; + struct dentry *debugfs_dir; +}; + +#endif
Delta TN48M switches have a Lattice CPLD that serves multiple purposes including being a GPIO expander. So lets add the MFD core driver for it. Signed-off-by: Robert Marko <robert.marko@sartura.hr> --- drivers/mfd/Kconfig | 13 +++ drivers/mfd/Makefile | 1 + drivers/mfd/tn48m-cpld.c | 181 ++++++++++++++++++++++++++++++++++++++ include/linux/mfd/tn48m.h | 30 +++++++ 4 files changed, 225 insertions(+) create mode 100644 drivers/mfd/tn48m-cpld.c create mode 100644 include/linux/mfd/tn48m.h