diff options
Diffstat (limited to 'recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch')
-rw-r--r-- | recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch | 1128 |
1 files changed, 964 insertions, 164 deletions
diff --git a/recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch b/recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch index 8488759..811e609 100644 --- a/recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch +++ b/recipes-kernel/linux/files/0016-Quark-GIP-Cypress-I-O-expander-quark.patch @@ -1,22 +1,27 @@ From xxxx Mon Sep 17 00:00:00 2001 From: Josef Ahmad <josef.ahmad@linux.intel.com> -Date: Tue, 25 Feb 2014 12:09:04 +0000 +Date: Mon, 31 Mar 2014 18:03:09 +0100 Subject: [PATCH 16/21] Quark GIP + Cypress I/O expander --- - drivers/mfd/Kconfig | 38 + - drivers/mfd/Makefile | 8 + - drivers/mfd/cy8c9540a.c | 970 ++++++++++++++++++++++++++ - drivers/mfd/intel_qrk_gip.h | 104 +++ - drivers/mfd/intel_qrk_gip_core.c | 335 +++++++++ - drivers/mfd/intel_qrk_gip_gpio.c | 659 ++++++++++++++++++ - drivers/mfd/intel_qrk_gip_i2c.c | 248 +++++++ - drivers/mfd/intel_qrk_gip_pdata.c | 25 + - drivers/mfd/intel_qrk_gip_test.c | 1131 +++++++++++++++++++++++++++++++ + drivers/mfd/Kconfig | 48 ++ + drivers/mfd/Makefile | 10 + + drivers/mfd/cy8c9540a.c | 963 ++++++++++++++++++++++++++ + drivers/mfd/intel_qrk_gip.h | 97 +++ + drivers/mfd/intel_qrk_gip_core.c | 328 +++++++++ + drivers/mfd/intel_qrk_gip_gpio.c | 652 ++++++++++++++++++ + drivers/mfd/intel_qrk_gip_i2c.c | 241 +++++++ + drivers/mfd/intel_qrk_gip_pdata.c | 18 + + drivers/mfd/intel_qrk_gip_test.c | 1124 +++++++++++++++++++++++++++++++ drivers/mfd/lpc_sch.c | 76 ++- - include/linux/mfd/cy8c9540a.h | 38 + - include/linux/mfd/intel_qrk_gip_pdata.h | 32 + - 12 files changed, 3651 insertions(+), 13 deletions(-) + drivers/mfd/pca9685-core.c | 283 ++++++++ + drivers/mfd/pca9685-gpio.c | 108 +++ + drivers/mfd/pca9685-pwm.c | 262 +++++++ + drivers/mfd/pca9685.h | 110 +++ + include/linux/mfd/cy8c9540a.h | 31 + + include/linux/mfd/intel_qrk_gip_pdata.h | 25 + + include/linux/platform_data/pca9685.h | 51 ++ + 17 files changed, 4414 insertions(+), 13 deletions(-) create mode 100644 drivers/mfd/cy8c9540a.c create mode 100644 drivers/mfd/intel_qrk_gip.h create mode 100644 drivers/mfd/intel_qrk_gip_core.c @@ -24,14 +29,19 @@ Subject: [PATCH 16/21] Quark GIP + Cypress I/O expander create mode 100644 drivers/mfd/intel_qrk_gip_i2c.c create mode 100644 drivers/mfd/intel_qrk_gip_pdata.c create mode 100644 drivers/mfd/intel_qrk_gip_test.c + create mode 100644 drivers/mfd/pca9685-core.c + create mode 100644 drivers/mfd/pca9685-gpio.c + create mode 100644 drivers/mfd/pca9685-pwm.c + create mode 100644 drivers/mfd/pca9685.h create mode 100644 include/linux/mfd/cy8c9540a.h create mode 100644 include/linux/mfd/intel_qrk_gip_pdata.h + create mode 100644 include/linux/platform_data/pca9685.h diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig -index ff553ba..b8029bd 100644 +index ff553ba..74358c2 100644 --- a/drivers/mfd/Kconfig +++ b/drivers/mfd/Kconfig -@@ -907,6 +907,44 @@ config MFD_TIMBERDALE +@@ -907,6 +907,54 @@ config MFD_TIMBERDALE The timberdale FPGA can be found on the Intel Atom development board for in-vehicle infontainment, called Russellville. @@ -44,6 +54,16 @@ index ff553ba..b8029bd 100644 + Select this option to enable support for the CY8C9540 I/O expander. + This device provides 40 interrupt-capable GPIOs, 8 PWMs and an EEPROM. + ++config MFD_PCA9685 ++ tristate "NPX Semiconductors PCA9685 (PWM/GPIO) driver" ++ depends on GPIOLIB && I2C && PWM ++ select REGMAP_I2C ++ help ++ NPX PCA9685 I2C-bus PWM controller with GPIO output interface support. ++ The I2C-bus LED controller provides 16-channel, 12-bit PWM Fm+. ++ Additionally, the driver allows the channels to be configured as GPIO ++ interface (output only). ++ +config INTEL_QRK_GIP + tristate "Intel Quark GIP" + depends on PCI && X86 && INTEL_QUARK_X1000_SOC @@ -77,14 +97,16 @@ index ff553ba..b8029bd 100644 tristate "Intel SCH LPC" depends on PCI diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile -index 8b977f8..b17d50c 100644 +index 8b977f8..38706ff 100644 --- a/drivers/mfd/Makefile +++ b/drivers/mfd/Makefile -@@ -123,6 +123,14 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o +@@ -123,6 +123,16 @@ obj-$(CONFIG_MFD_DB8500_PRCMU) += db8500-prcmu.o obj-$(CONFIG_AB8500_CORE) += ab8500-core.o ab8500-sysctrl.o obj-$(CONFIG_MFD_TIMBERDALE) += timberdale.o obj-$(CONFIG_PMIC_ADP5520) += adp5520.o +obj-$(CONFIG_CY8C9540A) += cy8c9540a.o ++pca9685-objs := pca9685-core.o pca9685-gpio.o pca9685-pwm.o ++obj-$(CONFIG_MFD_PCA9685) += pca9685.o +obj-$(CONFIG_INTEL_QRK_GIP) += intel_qrk_gip.o +intel_qrk_gip-objs := intel_qrk_gip_core.o \ + intel_qrk_gip_gpio.o \ @@ -97,28 +119,21 @@ index 8b977f8..b17d50c 100644 obj-$(CONFIG_MFD_RDC321X) += rdc321x-southbridge.o diff --git a/drivers/mfd/cy8c9540a.c b/drivers/mfd/cy8c9540a.c new file mode 100644 -index 0000000..444e5ab +index 0000000..9e3966a --- /dev/null +++ b/drivers/mfd/cy8c9540a.c -@@ -0,0 +1,970 @@ +@@ -0,0 +1,963 @@ +/* + * Copyright(c) 2013 Intel Corporation. + * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of version 2 of the GNU General Public License 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. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. + * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Contact Information: -+ * Intel Corporation ++ * This program is distributed in the hope 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. + */ + +/* @@ -1073,28 +1088,21 @@ index 0000000..444e5ab + diff --git a/drivers/mfd/intel_qrk_gip.h b/drivers/mfd/intel_qrk_gip.h new file mode 100644 -index 0000000..d1e8316 +index 0000000..3dfc487 --- /dev/null +++ b/drivers/mfd/intel_qrk_gip.h -@@ -0,0 +1,104 @@ +@@ -0,0 +1,97 @@ +/* + * Copyright(c) 2013 Intel Corporation. + * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of version 2 of the GNU General Public License 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. + * -+ * Contact Information: -+ * Intel Corporation ++ * This program is distributed in the hope 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. + */ +/* + * Intel Quark GIP (GPIO/I2C) driver @@ -1183,28 +1191,21 @@ index 0000000..d1e8316 +#endif /* __INTEL_QRKGIP_H__ */ diff --git a/drivers/mfd/intel_qrk_gip_core.c b/drivers/mfd/intel_qrk_gip_core.c new file mode 100644 -index 0000000..8b8727b +index 0000000..44209f0 --- /dev/null +++ b/drivers/mfd/intel_qrk_gip_core.c -@@ -0,0 +1,335 @@ +@@ -0,0 +1,328 @@ +/* + * Copyright(c) 2013 Intel Corporation. + * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of version 2 of the GNU General Public License as -+ * published by the Free Software Foundation. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Contact Information: -+ * Intel Corporation ++ * This program is distributed in the hope 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. + */ +/* + * Intel Quark GIP (GPIO/I2C) PCI driver @@ -1524,28 +1525,21 @@ index 0000000..8b8727b +MODULE_LICENSE("Dual BSD/GPL"); diff --git a/drivers/mfd/intel_qrk_gip_gpio.c b/drivers/mfd/intel_qrk_gip_gpio.c new file mode 100644 -index 0000000..ef19e2f +index 0000000..f823957 --- /dev/null +++ b/drivers/mfd/intel_qrk_gip_gpio.c -@@ -0,0 +1,659 @@ +@@ -0,0 +1,652 @@ +/* + * Copyright(c) 2013 Intel Corporation. + * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of version 2 of the GNU General Public License 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. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. + * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Contact Information: -+ * Intel Corporation ++ * This program is distributed in the hope 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. + */ +/* + * Intel Quark GIP (GPIO/I2C) - GPIO-specific PCI and core driver @@ -2189,28 +2183,21 @@ index 0000000..ef19e2f +} diff --git a/drivers/mfd/intel_qrk_gip_i2c.c b/drivers/mfd/intel_qrk_gip_i2c.c new file mode 100644 -index 0000000..9ecbeb5 +index 0000000..08e8f9d --- /dev/null +++ b/drivers/mfd/intel_qrk_gip_i2c.c -@@ -0,0 +1,248 @@ +@@ -0,0 +1,241 @@ +/* + * Copyright(c) 2013 Intel Corporation. + * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of version 2 of the GNU General Public License 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. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. + * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Contact Information: -+ * Intel Corporation ++ * This program is distributed in the hope 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. + */ +/* + * Intel Quark GIP (GPIO/I2C) - I2C-specific PCI driver @@ -2443,28 +2430,21 @@ index 0000000..9ecbeb5 +} diff --git a/drivers/mfd/intel_qrk_gip_pdata.c b/drivers/mfd/intel_qrk_gip_pdata.c new file mode 100644 -index 0000000..a764215 +index 0000000..cc230be --- /dev/null +++ b/drivers/mfd/intel_qrk_gip_pdata.c -@@ -0,0 +1,25 @@ +@@ -0,0 +1,18 @@ +/* + * Copyright(c) 2013 Intel Corporation. + * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of version 2 of the GNU General Public License 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. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. + * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Contact Information: -+ * Intel Corporation ++ * This program is distributed in the hope 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 <linux/module.h> @@ -2474,28 +2454,21 @@ index 0000000..a764215 +EXPORT_SYMBOL_GPL(intel_qrk_gip_get_pdata); diff --git a/drivers/mfd/intel_qrk_gip_test.c b/drivers/mfd/intel_qrk_gip_test.c new file mode 100644 -index 0000000..2b07e9e +index 0000000..e444c81 --- /dev/null +++ b/drivers/mfd/intel_qrk_gip_test.c -@@ -0,0 +1,1131 @@ +@@ -0,0 +1,1124 @@ +/* + * Copyright(c) 2013 Intel Corporation. + * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of version 2 of the GNU General Public License 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. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. + * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. -+ * -+ * Contact Information: -+ * Intel Corporation ++ * This program is distributed in the hope 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. + */ +/* + * Intel Quark GIP (GPIO/I2C) Test module @@ -3735,30 +3708,810 @@ index 5624fcb..4afc687 100644 if (id->device == PCI_DEVICE_ID_INTEL_ITC_LPC || id->device == PCI_DEVICE_ID_INTEL_CENTERTON_ILB) { pci_read_config_dword(dev, WDTBASE, &base_addr_cfg); -diff --git a/include/linux/mfd/cy8c9540a.h b/include/linux/mfd/cy8c9540a.h +diff --git a/drivers/mfd/pca9685-core.c b/drivers/mfd/pca9685-core.c new file mode 100644 -index 0000000..a32c6f0 +index 0000000..11cb8d9 --- /dev/null -+++ b/include/linux/mfd/cy8c9540a.h -@@ -0,0 +1,38 @@ ++++ b/drivers/mfd/pca9685-core.c +@@ -0,0 +1,283 @@ +/* ++ * Driver for NPX PCA9685 I2C-bus PWM controller with GPIO output interface ++ * support. ++ * + * Copyright(c) 2013 Intel Corporation. + * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of version 2 of the GNU General Public License as -+ * published by the Free Software Foundation. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope 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. ++ * ++ * The I2C-bus LED controller provides 16-channel, 12-bit PWM Fm+. ++ * Additionally, the driver allows the channels to be configured as GPIO ++ * interface (output only). ++ */ ++ ++#include <linux/i2c.h> ++#include <linux/module.h> ++#include <linux/pwm.h> ++#include <linux/gpio.h> ++#include <linux/regmap.h> ++#include <linux/slab.h> ++ ++#include "pca9685.h" ++ ++static unsigned int en_invrt; ++module_param(en_invrt, uint, 0); ++MODULE_PARM_DESC(en_invrt, "Enable output logic state inverted mode"); ++ ++static unsigned int en_open_dr; ++module_param(en_open_dr, uint, 0); ++MODULE_PARM_DESC(en_open_dr, ++ "The outputs are configured with an open-drain structure"); ++ ++static int gpio_base = -1; /* requests dynamic ID allocation */ ++module_param(gpio_base, int, 0); ++MODULE_PARM_DESC(gpio_base, "GPIO base number"); ++ ++static unsigned int pwm_period = PWM_PERIOD_DEF; /* PWM clock period */ ++module_param(pwm_period, uint, 0); ++MODULE_PARM_DESC(pwm_period, "PWM clock period (nanoseconds)"); ++ ++static bool pca9685_register_volatile(struct device *dev, unsigned int reg) ++{ ++ if (unlikely(reg == PCA9685_MODE1)) ++ return true; ++ else ++ return false; ++} ++ ++static struct regmap_config pca9685_regmap_i2c_config = { ++ .reg_bits = 8, ++ .val_bits = 8, ++ .max_register = PCA9685_NUMREGS, ++ .volatile_reg = pca9685_register_volatile, ++ .cache_type = REGCACHE_RBTREE, ++}; ++ ++ssize_t pca9685_pwm_period_sysfs_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) ++{ ++ struct pca9685 *pca = dev_get_drvdata(dev); ++ ++ return scnprintf(buf, PAGE_SIZE, "%u\n", pca->pwm_period); ++} ++ ++ssize_t pca9685_pwm_period_sysfs_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ struct pca9685 *pca = dev_get_drvdata(dev); ++ unsigned period_ns; ++ int ret; ++ ++ sscanf(buf, "%u", &period_ns); ++ ++ ret = pca9685_update_prescale(pca, period_ns, true); ++ if (ret) ++ return ret; ++ ++ return count; ++} ++ ++/* Sysfs attribute to allow PWM clock period adjustment at run-time ++ * NOTE: All active channels will switch off momentarily if the ++ * PWM clock period is changed ++ */ ++static DEVICE_ATTR(pwm_period, S_IWUSR | S_IRUGO, ++ pca9685_pwm_period_sysfs_show, ++ pca9685_pwm_period_sysfs_store); ++ ++static int pca9685_probe(struct i2c_client *client, ++ const struct i2c_device_id *id) ++{ ++ struct pca9685_pdata *pdata; ++ struct pca9685 *pca; ++ int ret; ++ int mode2; ++ ++ pca = devm_kzalloc(&client->dev, sizeof(*pca), GFP_KERNEL); ++ if (unlikely(!pca)) ++ return -ENOMEM; ++ ++ pdata = client->dev.platform_data; ++ if (likely(pdata)) { ++ memcpy(pca->chan_mapping, pdata->chan_mapping, ++ ARRAY_SIZE(pca->chan_mapping)); ++ pca->gpio_base = pdata->gpio_base; ++ en_invrt = pdata->en_invrt; ++ en_open_dr = pdata->en_open_dr; ++ } else { ++ dev_warn(&client->dev, ++ "Platform data not provided." ++ "Using default or mod params configuration.\n"); ++ pca->gpio_base = gpio_base; ++ memset(pca->chan_mapping, PWM_CH_UNDEFINED, ++ ARRAY_SIZE(pca->chan_mapping)); ++ } ++ ++ if (unlikely(!i2c_check_functionality(client->adapter, ++ I2C_FUNC_I2C | ++ I2C_FUNC_SMBUS_BYTE_DATA))) { ++ dev_err(&client->dev, ++ "i2c adapter doesn't support required functionality\n"); ++ return -EIO; ++ } ++ ++ pca->regmap = devm_regmap_init_i2c(client, &pca9685_regmap_i2c_config); ++ if (IS_ERR(pca->regmap)) { ++ ret = PTR_ERR(pca->regmap); ++ dev_err(&client->dev, "Failed to initialize register map: %d\n", ++ ret); ++ return ret; ++ } ++ ++ i2c_set_clientdata(client, pca); ++ ++ /* registration of GPIO chip */ ++ pca->gpio_chip.label = "pca9685-gpio"; ++ pca->gpio_chip.owner = THIS_MODULE; ++ pca->gpio_chip.set = pca9685_gpio_set; ++ pca->gpio_chip.get = pca9685_gpio_get; ++ pca->gpio_chip.can_sleep = 1; ++ pca->gpio_chip.ngpio = PCA9685_MAXCHAN; ++ pca->gpio_chip.base = pca->gpio_base; ++ pca->gpio_chip.request = pca9685_gpio_request; ++ pca->gpio_chip.free = pca9685_gpio_free; ++ ++ mutex_init(&pca->lock); ++ ++ ret = gpiochip_add(&pca->gpio_chip); ++ if (unlikely(ret < 0)) { ++ dev_err(&client->dev, "Could not register gpiochip, %d\n", ret); ++ goto err; ++ } ++ ++ /* configure initial PWM settings */ ++ ret = pca9685_init_pwm_regs(pca, pwm_period); ++ if (ret) { ++ pr_err("Failed to initialize PWM registers\n"); ++ goto err_gpiochip; ++ } ++ ++ /* registration of PWM chip */ ++ ++ regmap_read(pca->regmap, PCA9685_MODE2, &mode2); ++ ++ /* update mode2 register */ ++ if (en_invrt) ++ mode2 |= MODE2_INVRT; ++ else ++ mode2 &= ~MODE2_INVRT; ++ ++ if (en_open_dr) ++ mode2 &= ~MODE2_OUTDRV; ++ else ++ mode2 |= MODE2_OUTDRV; ++ ++ regmap_write(pca->regmap, PCA9685_MODE2, mode2); ++ ++ pca->pwm_chip.ops = &pca9685_pwm_ops; ++ /* add an extra channel for ALL_LED */ ++ pca->pwm_chip.npwm = PCA9685_MAXCHAN + 1; ++ pca->pwm_chip.dev = &client->dev; ++ pca->pwm_chip.base = -1; ++ ++ ret = pwmchip_add(&pca->pwm_chip); ++ if (unlikely(ret < 0)) { ++ dev_err(&client->dev, "pwmchip_add failed %d\n", ret); ++ goto err_gpiochip; ++ } ++ ++ /* Also create a sysfs interface, providing a cmd line config option */ ++ ret = sysfs_create_file(&client->dev.kobj, &dev_attr_pwm_period.attr); ++ if (unlikely(ret < 0)) { ++ dev_err(&client->dev, "sysfs_create_file failed %d\n", ret); ++ goto err_pwmchip; ++ } ++ ++ return ret; ++ ++err_pwmchip: ++ if (unlikely(pwmchip_remove(&pca->pwm_chip))) ++ dev_warn(&client->dev, "%s failed\n", "pwmchip_remove()"); ++ ++err_gpiochip: ++ if (unlikely(gpiochip_remove(&pca->gpio_chip))) ++ dev_warn(&client->dev, "%s failed\n", "gpiochip_remove()"); ++err: ++ mutex_destroy(&pca->lock); ++ ++ return ret; ++} ++ ++static int pca9685_remove(struct i2c_client *client) ++{ ++ struct pca9685 *pca = i2c_get_clientdata(client); ++ int ret; ++ ++ regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP, ++ MODE1_SLEEP); ++ ++ ret = gpiochip_remove(&pca->gpio_chip); ++ if (unlikely(ret)) ++ dev_err(&client->dev, "%s failed, %d\n", ++ "gpiochip_remove()", ret); ++ ++ sysfs_remove_file(&client->dev.kobj, &dev_attr_pwm_period.attr); ++ ++ ret = pwmchip_remove(&pca->pwm_chip); ++ if (unlikely(ret)) ++ dev_err(&client->dev, "%s failed, %d\n", ++ "pwmchip_remove()", ret); ++ ++ mutex_destroy(&pca->lock); ++ ++ return ret; ++} ++ ++static const struct i2c_device_id pca9685_id[] = { ++ { "pca9685", 0 }, ++ { /* sentinel */ }, ++}; ++MODULE_DEVICE_TABLE(i2c, pca9685_id); ++ ++static struct i2c_driver pca9685_i2c_driver = { ++ .driver = { ++ .name = "mfd-pca9685", ++ .owner = THIS_MODULE, ++ }, ++ .probe = pca9685_probe, ++ .remove = pca9685_remove, ++ .id_table = pca9685_id, ++}; ++ ++static int __init pca9685_init(void) ++{ ++ if (unlikely((pwm_period < PWM_PERIOD_MIN) || ++ (PWM_PERIOD_MAX < pwm_period))) { ++ pr_err("Invalid PWM period specified (valid range: %d-%d)\n", ++ PWM_PERIOD_MIN, PWM_PERIOD_MAX); ++ return -EINVAL; ++ } ++ ++ return i2c_add_driver(&pca9685_i2c_driver); ++} ++/* register after i2c postcore initcall */ ++subsys_initcall(pca9685_init); ++ ++static void __exit pca9685_exit(void) ++{ ++ i2c_del_driver(&pca9685_i2c_driver); ++} ++module_exit(pca9685_exit); ++ ++MODULE_AUTHOR("Wojciech Ziemba <wojciech.ziemba@emutex.com>"); ++MODULE_DESCRIPTION("NPX Semiconductors PCA9685 (PWM/GPIO) driver"); ++MODULE_LICENSE("GPL"); +diff --git a/drivers/mfd/pca9685-gpio.c b/drivers/mfd/pca9685-gpio.c +new file mode 100644 +index 0000000..7cfff86 +--- /dev/null ++++ b/drivers/mfd/pca9685-gpio.c +@@ -0,0 +1,108 @@ ++/* ++ * Driver for NPX PCA9685 I2C-bus PWM controller with GPIO output interface ++ * support. ++ * ++ * Copyright(c) 2013 Intel Corporation. + * -+ * 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. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. + * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * This program is distributed in the hope 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. + * -+ * Contact Information: -+ * Intel Corporation ++ * The I2C-bus LED controller provides 16-channel, 12-bit PWM Fm+. ++ * Additionally, the driver allows the channels to be configured as GPIO ++ * interface (output only). ++ */ ++ ++#include <linux/device.h> ++#include <linux/module.h> ++#include <linux/gpio.h> ++#include <linux/pwm.h> ++#include <linux/regmap.h> ++ ++#include "pca9685.h" ++ ++static inline struct pca9685 *gpio_to_pca(struct gpio_chip *gpio_chip) ++{ ++ return container_of(gpio_chip, struct pca9685, gpio_chip); ++} ++ ++static inline int is_gpio_allowed(const struct pca9685 *pca, unsigned channel) ++{ ++ return pca->chan_mapping[channel] & PWM_CH_GPIO; ++} ++ ++int pca9685_gpio_request(struct gpio_chip *chip, unsigned offset) ++{ ++ struct pca9685 *pca; ++ struct pwm_device *pwm; ++ int ret = 0; ++ pca = gpio_to_pca(chip); ++ ++ /* validate channel constrains */ ++ if (!is_gpio_allowed(pca, offset)) ++ return -ENODEV; ++ ++ /* return busy if channel is already allocated for pwm */ ++ pwm = &pca->pwm_chip.pwms[offset]; ++ if (test_bit(PWMF_REQUESTED, &pwm->flags)) ++ return -EBUSY; ++ ++ /* clear the on counter */ ++ regmap_write(pca->regmap, LED_N_ON_L(offset), 0x0); ++ regmap_write(pca->regmap, LED_N_ON_H(offset), 0x0); ++ ++ /* clear the off counter */ ++ regmap_write(pca->regmap, LED_N_OFF_L(offset), 0x0); ++ ret = regmap_write(pca->regmap, LED_N_OFF_H(offset), 0x0); ++ ++ clear_sleep_bit(pca); ++ ++ return ret; ++} ++ ++void pca9685_gpio_free(struct gpio_chip *chip, unsigned offset) ++{ ++ struct pca9685 *pca; ++ ++ pca = gpio_to_pca(chip); ++ ++ /* clear the on counter reg */ ++ regmap_write(pca->regmap, LED_N_ON_L(offset), 0x0); ++ regmap_write(pca->regmap, LED_N_ON_H(offset), 0x0); ++ ++ set_sleep_bit(pca); ++ ++ return; ++} ++ ++void pca9685_gpio_set(struct gpio_chip *chip, unsigned offset, int value) ++{ ++ struct pca9685 *pca; ++ ++ pca = gpio_to_pca(chip); ++ ++ /* set the full-on bit */ ++ regmap_write(pca->regmap, LED_N_ON_H(offset), (value << 4) & LED_FULL); ++ ++ return; ++} ++ ++int pca9685_gpio_get(struct gpio_chip *chip, unsigned offset) ++{ ++ struct pca9685 *pca; ++ unsigned int val; ++ ++ pca = gpio_to_pca(chip); ++ ++ /* read the full-on bit */ ++ regmap_read(pca->regmap, LED_N_ON_H(offset), &val); ++ ++ return !!val; ++} ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/mfd/pca9685-pwm.c b/drivers/mfd/pca9685-pwm.c +new file mode 100644 +index 0000000..13f82b8 +--- /dev/null ++++ b/drivers/mfd/pca9685-pwm.c +@@ -0,0 +1,262 @@ ++/* ++ * Driver for NPX PCA9685 I2C-bus PWM controller with GPIO output interface ++ * support. ++ * ++ * Copyright(c) 2013 Intel Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope 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. ++ * ++ * The I2C-bus LED controller provides 16-channel, 12-bit PWM Fm+. ++ * Additionally, the driver allows the channels to be configured as GPIO ++ * interface (output only). ++ */ ++ ++#include <linux/module.h> ++#include <linux/pwm.h> ++#include <linux/gpio.h> ++#include <linux/regmap.h> ++#include <linux/platform_device.h> ++#include <linux/delay.h> ++ ++#include "pca9685.h" ++ ++static inline struct pca9685 *pwm_to_pca(struct pwm_chip *pwm_chip) ++{ ++ return container_of(pwm_chip, struct pca9685, pwm_chip); ++} ++ ++static inline int period_ns_to_prescale(unsigned period_ns) ++{ ++ return (DIV_ROUND_CLOSEST(OSC_CLK_MHZ * period_ns, ++ SAMPLE_RES * 1000)) - 1; ++} ++ ++static inline int is_pwm_allowed(const struct pca9685 *pca, unsigned channel) ++{ ++ return pca->chan_mapping[channel] & PWM_CH_PWM; ++} ++ ++int pca9685_update_prescale(struct pca9685 *pca, unsigned period_ns, ++ bool reconfigure_channels) ++{ ++ int pre_scale, i; ++ struct pwm_device *pwm; ++ unsigned long long duty_scale; ++ unsigned long long new_duty_ns; ++ ++ if (unlikely((period_ns < PWM_PERIOD_MIN) || ++ (PWM_PERIOD_MAX < period_ns))) { ++ pr_err("Invalid PWM period specified (valid range: %d-%d)\n", ++ PWM_PERIOD_MIN, PWM_PERIOD_MAX); ++ return -EINVAL; ++ } ++ ++ mutex_lock(&pca->lock); ++ ++ /* update pre_scale to the closest period */ ++ pre_scale = period_ns_to_prescale(period_ns); ++ /* ensure sleep-mode bit is set ++ * NOTE: All active channels will switch off for at least 500 usecs ++ */ ++ regmap_update_bits(pca->regmap, PCA9685_MODE1, ++ MODE1_SLEEP, MODE1_SLEEP); ++ regmap_write(pca->regmap, PCA9685_PRESCALE, pre_scale); ++ /* clear sleep mode flag if at least 1 channel is active */ ++ if (pca->active_cnt > 0) { ++ regmap_update_bits(pca->regmap, PCA9685_MODE1, ++ MODE1_SLEEP, 0x0); ++ usleep_range(MODE1_RESTART_DELAY, MODE1_RESTART_DELAY * 2); ++ regmap_update_bits(pca->regmap, PCA9685_MODE1, ++ MODE1_RESTART, MODE1_RESTART); ++ } ++ ++ if (reconfigure_channels) { ++ for (i = 0; i < pca->pwm_chip.npwm; i++) { ++ pwm = &pca->pwm_chip.pwms[i]; ++ pwm->period = period_ns; ++ if (pwm->duty_cycle > 0) { ++ /* Scale the rise time to maintain duty cycle */ ++ duty_scale = period_ns; ++ duty_scale *= 1000000; ++ do_div(duty_scale, pca->pwm_period); ++ new_duty_ns = duty_scale * pwm->duty_cycle; ++ do_div(new_duty_ns, 1000000); ++ /* Update the duty_cycle */ ++ pwm_config(pwm, (int)new_duty_ns, pwm->period); ++ } ++ } ++ } ++ pca->pwm_period = period_ns; ++ ++ mutex_unlock(&pca->lock); ++ return 0; ++} ++ ++int pca9685_init_pwm_regs(struct pca9685 *pca, unsigned period_ns) ++{ ++ int ret, chan; ++ ++ /* set MODE1_SLEEP */ ++ ret = regmap_update_bits(pca->regmap, PCA9685_MODE1, ++ MODE1_SLEEP, MODE1_SLEEP); ++ if (unlikely(ret < 0)) ++ return ret; ++ ++ /* configure the initial PWM clock period */ ++ ret = pca9685_update_prescale(pca, period_ns, false); ++ if (unlikely(ret < 0)) ++ return ret; ++ ++ /* reset PWM channel registers to power-on default values */ ++ for (chan = 0; chan < PCA9685_MAXCHAN; chan++) { ++ ret = regmap_write(pca->regmap, LED_N_ON_L(chan), 0); ++ if (unlikely(ret < 0)) ++ return ret; ++ ret = regmap_write(pca->regmap, LED_N_ON_H(chan), 0); ++ if (unlikely(ret < 0)) ++ return ret; ++ ret = regmap_write(pca->regmap, LED_N_OFF_L(chan), 0); ++ if (unlikely(ret < 0)) ++ return ret; ++ ret = regmap_write(pca->regmap, LED_N_OFF_H(chan), LED_FULL); ++ if (unlikely(ret < 0)) ++ return ret; ++ } ++ /* reset ALL_LED registers to power-on default values */ ++ ret = regmap_write(pca->regmap, PCA9685_ALL_LED_ON_L, 0); ++ if (unlikely(ret < 0)) ++ return ret; ++ ret = regmap_write(pca->regmap, PCA9685_ALL_LED_ON_H, 0); ++ if (unlikely(ret < 0)) ++ return ret; ++ ret = regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_L, 0); ++ if (unlikely(ret < 0)) ++ return ret; ++ ret = regmap_write(pca->regmap, PCA9685_ALL_LED_OFF_H, LED_FULL); ++ if (unlikely(ret < 0)) ++ return ret; ++ ++ return ret; ++} ++ ++static int pca9685_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm, ++ int duty_ns, int period_ns) ++{ ++ struct pca9685 *pca = pwm_to_pca(chip); ++ unsigned long long duty; ++ unsigned int reg_on_h, ++ reg_off_l, ++ reg_off_h; ++ int full_off; ++ ++ /* Changing PWM period for a single channel at run-time not allowed. ++ * The PCA9685 PWM clock is shared across all PWM channels ++ */ ++ if (unlikely(period_ns != pwm->period)) ++ return -EPERM; ++ ++ if (unlikely(pwm->hwpwm >= PCA9685_MAXCHAN)) { ++ reg_on_h = PCA9685_ALL_LED_ON_H; ++ reg_off_l = PCA9685_ALL_LED_OFF_L; ++ reg_off_h = PCA9685_ALL_LED_OFF_H; ++ } else { ++ reg_on_h = LED_N_ON_H(pwm->hwpwm); ++ reg_off_l = LED_N_OFF_L(pwm->hwpwm); ++ reg_off_h = LED_N_OFF_H(pwm->hwpwm); ++ } ++ ++ duty = SAMPLE_RES * (unsigned long long)duty_ns; ++ duty = DIV_ROUND_UP_ULL(duty, period_ns); ++ ++ if (duty >= SAMPLE_RES) /* set the LED_FULL bit */ ++ return regmap_write(pca->regmap, reg_on_h, LED_FULL); ++ else /* clear the LED_FULL bit */ ++ regmap_write(pca->regmap, reg_on_h, 0x00); ++ ++ full_off = !test_bit(PWMF_ENABLED, &pwm->flags) << 4; ++ ++ regmap_write(pca->regmap, reg_off_l, (int)duty & 0xff); ++ ++ return regmap_write(pca->regmap, reg_off_h, ++ ((int)duty >> 8 | full_off) & 0x1f); ++} ++ ++static int pca9685_pwm_enable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct pca9685 *pca = pwm_to_pca(chip); ++ int ret; ++ ++ unsigned int reg_off_h; ++ ++ if (unlikely(pwm->hwpwm >= PCA9685_MAXCHAN)) ++ reg_off_h = PCA9685_ALL_LED_OFF_H; ++ else ++ reg_off_h = LED_N_OFF_H(pwm->hwpwm); ++ ++ /* clear the full-off bit */ ++ ret = regmap_update_bits(pca->regmap, reg_off_h, LED_FULL, 0x0); ++ ++ clear_sleep_bit(pca); ++ ++ return ret; ++} ++ ++static void pca9685_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct pca9685 *pca = pwm_to_pca(chip); ++ ++ unsigned int reg_off_h; ++ ++ if (unlikely(pwm->hwpwm >= PCA9685_MAXCHAN)) ++ reg_off_h = PCA9685_ALL_LED_OFF_H; ++ else ++ reg_off_h = LED_N_OFF_H(pwm->hwpwm); ++ ++ /* set the LED_OFF counter. */ ++ regmap_update_bits(pca->regmap, reg_off_h, LED_FULL, LED_FULL); ++ ++ set_sleep_bit(pca); ++ ++ return; ++} ++ ++static int pca9685_pwm_request(struct pwm_chip *chip, struct pwm_device *pwm) ++{ ++ struct pca9685 *pca; ++ struct gpio_chip *gpio_chip; ++ unsigned channel = pwm->hwpwm; ++ ++ pca = pwm_to_pca(chip); ++ ++ /* validate channel constrains */ ++ if (!is_pwm_allowed(pca, channel)) ++ return -ENODEV; ++ ++ /* return busy if channel is already allocated for gpio */ ++ gpio_chip = &pca->gpio_chip; ++ ++ if ((channel < PCA9685_MAXCHAN) && ++ (gpiochip_is_requested(gpio_chip, channel))) ++ return -EBUSY; ++ ++ pwm->period = pca->pwm_period; ++ ++ return 0; ++} ++ ++const struct pwm_ops pca9685_pwm_ops = { ++ .enable = pca9685_pwm_enable, ++ .disable = pca9685_pwm_disable, ++ .config = pca9685_pwm_config, ++ .request = pca9685_pwm_request, ++ .owner = THIS_MODULE, ++}; ++ ++MODULE_LICENSE("GPL"); +diff --git a/drivers/mfd/pca9685.h b/drivers/mfd/pca9685.h +new file mode 100644 +index 0000000..3627097 +--- /dev/null ++++ b/drivers/mfd/pca9685.h +@@ -0,0 +1,110 @@ ++/* ++ * Driver for NPX PCA9685 I2C-bus PWM controller with GPIO output interface ++ * support. ++ * ++ * Copyright(c) 2013 Intel Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope 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. ++ * ++ * The I2C-bus LED controller provides 16-channel, 12-bit PWM Fm+. ++ * Additionally, the driver allows the channels to be configured as GPIO ++ * interface (output only). ++ */ ++ ++#ifndef __LINUX_MFD_PCA9685_H ++#define __LINUX_MFD_PCA9685_H ++ ++#include <linux/mutex.h> ++#include <linux/gpio.h> ++#include <linux/pwm.h> ++#include <linux/platform_data/pca9685.h> ++ ++#define PCA9685_MODE1 0x00 ++#define PCA9685_MODE2 0x01 ++#define PCA9685_SUBADDR1 0x02 ++#define PCA9685_SUBADDR2 0x03 ++#define PCA9685_SUBADDR3 0x04 ++#define PCA9685_LEDX_ON_L 0x06 ++#define PCA9685_LEDX_ON_H 0x07 ++#define PCA9685_LEDX_OFF_L 0x08 ++#define PCA9685_LEDX_OFF_H 0x09 ++ ++#define PCA9685_ALL_LED_ON_L 0xFA ++#define PCA9685_ALL_LED_ON_H 0xFB ++#define PCA9685_ALL_LED_OFF_L 0xFC ++#define PCA9685_ALL_LED_OFF_H 0xFD ++#define PCA9685_PRESCALE 0xFE ++ ++#define PCA9685_NUMREGS 0xFF ++ ++#define LED_FULL (1 << 4) ++#define MODE1_SLEEP (1 << 4) ++#define MODE1_RESTART (1 << 7) ++ ++#define MODE1_RESTART_DELAY 500 ++ ++#define LED_N_ON_H(N) (PCA9685_LEDX_ON_H + (4 * (N))) ++#define LED_N_ON_L(N) (PCA9685_LEDX_ON_L + (4 * (N))) ++#define LED_N_OFF_H(N) (PCA9685_LEDX_OFF_H + (4 * (N))) ++#define LED_N_OFF_L(N) (PCA9685_LEDX_OFF_L + (4 * (N))) ++ ++#define OSC_CLK_MHZ 25 /* 25 MHz */ ++#define SAMPLE_RES 4096 /* 12 bits */ ++#define PWM_PERIOD_MIN 666666 /* ~1525 Hz */ ++#define PWM_PERIOD_MAX 41666666 /* 24 Hz */ ++#define PWM_PERIOD_DEF 5000000 /* default 200 Hz */ ++ ++struct pca9685 { ++ struct gpio_chip gpio_chip; ++ struct pwm_chip pwm_chip; ++ struct regmap *regmap; ++ struct mutex lock; /* mutual exclusion semaphore */ ++ /* Array of channel allocation constrains */ ++ /* add an extra channel for ALL_LED */ ++ u8 chan_mapping[PCA9685_MAXCHAN + 1]; ++ int gpio_base; ++ int active_cnt; ++ int pwm_exported_cnt; ++ int pwm_period; ++}; ++ ++extern const struct pwm_ops pca9685_pwm_ops; ++ ++int pca9685_gpio_request(struct gpio_chip *chip, unsigned offset); ++void pca9685_gpio_free(struct gpio_chip *chip, unsigned offset); ++void pca9685_gpio_set(struct gpio_chip *chip, unsigned offset, int value); ++int pca9685_gpio_get(struct gpio_chip *chip, unsigned offset); ++ ++int pca9685_init_pwm_regs(struct pca9685 *pca, unsigned period_ns); ++int pca9685_update_prescale(struct pca9685 *pca, unsigned period_ns, ++ bool reconfigure_channels); ++ ++static inline void set_sleep_bit(struct pca9685 *pca) ++{ ++ mutex_lock(&pca->lock); ++ /* set sleep mode flag if no more active LED channel*/ ++ if (--pca->active_cnt == 0) ++ regmap_update_bits(pca->regmap, PCA9685_MODE1, MODE1_SLEEP, ++ MODE1_SLEEP); ++ mutex_unlock(&pca->lock); ++} ++ ++static inline void clear_sleep_bit(struct pca9685 *pca) ++{ ++ mutex_lock(&pca->lock); ++ /* clear sleep mode flag if at least 1 LED channel is active */ ++ if (pca->active_cnt++ == 0) ++ regmap_update_bits(pca->regmap, PCA9685_MODE1, ++ MODE1_SLEEP, 0x0); ++ ++ mutex_unlock(&pca->lock); ++} ++ ++#endif /* __LINUX_MFD_PCA9685_H */ +diff --git a/include/linux/mfd/cy8c9540a.h b/include/linux/mfd/cy8c9540a.h +new file mode 100644 +index 0000000..4d79825 +--- /dev/null ++++ b/include/linux/mfd/cy8c9540a.h +@@ -0,0 +1,31 @@ ++/* ++ * Copyright(c) 2013 Intel Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope 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. + */ + +#ifndef LINUX_CY8C9540A_PDATA_H @@ -3781,28 +4534,21 @@ index 0000000..a32c6f0 +#endif diff --git a/include/linux/mfd/intel_qrk_gip_pdata.h b/include/linux/mfd/intel_qrk_gip_pdata.h new file mode 100644 -index 0000000..1378f5c +index 0000000..eab17d9 --- /dev/null +++ b/include/linux/mfd/intel_qrk_gip_pdata.h -@@ -0,0 +1,32 @@ +@@ -0,0 +1,25 @@ +/* + * Copyright(c) 2013 Intel Corporation. + * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of version 2 of the GNU General Public License 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. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. + * -+ * Contact Information: -+ * Intel Corporation ++ * This program is distributed in the hope 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. + */ + +#ifndef LINUX_INTEL_QRK_GIP_DATA_H @@ -3817,6 +4563,60 @@ index 0000000..1378f5c +extern struct intel_qrk_gip_pdata *(*intel_qrk_gip_get_pdata)(void); + +#endif --- -1.7.4.1 - +diff --git a/include/linux/platform_data/pca9685.h b/include/linux/platform_data/pca9685.h +new file mode 100644 +index 0000000..903d30d +--- /dev/null ++++ b/include/linux/platform_data/pca9685.h +@@ -0,0 +1,51 @@ ++/* ++ * Platform data for pca9685 driver ++ * ++ * Copyright(c) 2013 Intel Corporation. ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms and conditions of the GNU General Public License, ++ * version 2, as published by the Free Software Foundation. ++ * ++ * This program is distributed in the hope 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. ++ */ ++ ++#ifndef _PLAT_PCA9685_H_ ++#define _PLAT_PCA9685_H_ ++ ++#define PCA9685_MAXCHAN 16 ++#define MODE2_INVRT (1 << 4) ++#define MODE2_OUTDRV (1 << 2) ++ ++/* PWM channel allocation flags */ ++enum { ++ PWM_CH_DISABLED = 0, ++ PWM_CH_PWM = 1 << 0, ++ PWM_CH_GPIO = 1 << 1, ++ /* allow PWM or GPIO */ ++ PWM_CH_UNDEFINED = PWM_CH_PWM | PWM_CH_GPIO, ++}; ++ ++/** ++ * struct pca9685_pdata - Platform data for pca9685 driver ++ * @chan_mapping: Array of channel allocation constrains ++ * @gpio_base: GPIO base ++ * mode2_flags: mode2 register modification flags: INVRT and OUTDRV ++ **/ ++struct pca9685_pdata { ++ /* Array of channel allocation constrains */ ++ /* add an extra channel for ALL_LED */ ++ u8 chan_mapping[PCA9685_MAXCHAN + 1]; ++ /* GPIO base */ ++ int gpio_base; ++ /* mode2 flags */ ++ u8 en_invrt:1, /* enable output logic state inverted mode */ ++ en_open_dr:1, /* enable if outputs are configured with an ++ open-drain structure */ ++ unused:6; ++}; ++ ++#endif /* _PLAT_PCA9685_H_ */ |