summaryrefslogtreecommitdiff
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/acpi/pci_irq.c10
-rw-r--r--drivers/base/Kconfig4
-rw-r--r--drivers/base/base.h2
-rw-r--r--drivers/base/cpu.c30
-rw-r--r--drivers/char/hw_random/atmel-rng.c12
-rw-r--r--drivers/char/hw_random/n2-drv.c13
-rw-r--r--drivers/char/hw_random/octeon-rng.c13
-rw-r--r--drivers/char/hw_random/pasemi-rng.c12
-rw-r--r--drivers/char/hw_random/picoxcell-rng.c12
-rw-r--r--drivers/char/hw_random/ppc4xx-rng.c12
-rw-r--r--drivers/char/hw_random/timeriomem-rng.c13
-rw-r--r--drivers/char/tpm/Kconfig2
-rw-r--r--drivers/char/tpm/tpm.c137
-rw-r--r--drivers/char/tpm/tpm.h9
-rw-r--r--drivers/char/tpm/tpm_tis.c84
-rw-r--r--drivers/cpufreq/Kconfig.arm15
-rw-r--r--drivers/cpufreq/Makefile2
-rw-r--r--drivers/cpufreq/cpufreq.c3
-rw-r--r--drivers/cpufreq/cpufreq_ondemand.c3
-rw-r--r--drivers/cpufreq/cpufreq_userspace.c8
-rw-r--r--drivers/cpufreq/exynos-cpufreq.c290
-rw-r--r--drivers/cpufreq/exynos4210-cpufreq.c643
-rw-r--r--drivers/cpufreq/omap-cpufreq.c274
-rw-r--r--drivers/cpufreq/powernow-k8.c47
-rw-r--r--drivers/cpufreq/s3c64xx-cpufreq.c35
-rw-r--r--drivers/crypto/amcc/crypto4xx_core.c13
-rw-r--r--drivers/crypto/caam/caamalg.c67
-rw-r--r--drivers/crypto/caam/compat.h1
-rw-r--r--drivers/crypto/caam/ctrl.c26
-rw-r--r--drivers/crypto/caam/desc.h2265
-rw-r--r--drivers/crypto/caam/desc_constr.h7
-rw-r--r--drivers/crypto/caam/regs.h1
-rw-r--r--drivers/crypto/mv_cesa.c12
-rw-r--r--drivers/crypto/picoxcell_crypto.c16
-rw-r--r--drivers/crypto/s5p-sss.c13
-rw-r--r--drivers/crypto/talitos.c493
-rw-r--r--drivers/crypto/talitos.h45
-rw-r--r--drivers/firmware/Kconfig12
-rw-r--r--drivers/firmware/Makefile1
-rw-r--r--drivers/firmware/sigma.c153
-rw-r--r--drivers/hid/hid-wacom.c16
-rw-r--r--drivers/hid/hid-wiimote-core.c10
-rw-r--r--drivers/md/md.c6
-rw-r--r--drivers/md/raid1.c11
-rw-r--r--drivers/mfd/Kconfig1
-rw-r--r--drivers/mfd/Makefile2
-rw-r--r--drivers/mfd/max8925-core.c15
-rw-r--r--drivers/mfd/wm8994-core.c158
-rw-r--r--drivers/mfd/wm8994-irq.c206
-rw-r--r--drivers/mfd/wm8994-regmap.c1238
-rw-r--r--drivers/mfd/wm8994.h25
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/srom.c31
-rw-r--r--drivers/parisc/dino.c47
-rw-r--r--drivers/parisc/lba_pci.c72
-rw-r--r--drivers/pci/access.c76
-rw-r--r--drivers/pci/ats.c17
-rw-r--r--drivers/pci/bus.c32
-rw-r--r--drivers/pci/iov.c16
-rw-r--r--drivers/pci/msi.c43
-rw-r--r--drivers/pci/pci-driver.c3
-rw-r--r--drivers/pci/pci.c153
-rw-r--r--drivers/pci/pci.h10
-rw-r--r--drivers/pci/pcie/Kconfig2
-rw-r--r--drivers/pci/probe.c68
-rw-r--r--drivers/pci/remove.c10
-rw-r--r--drivers/pci/setup-res.c6
-rw-r--r--drivers/platform/x86/Kconfig2
-rw-r--r--drivers/pnp/quirks.c42
-rw-r--r--drivers/power/Kconfig32
-rw-r--r--drivers/power/Makefile5
-rw-r--r--drivers/power/bq27x00_battery.c210
-rw-r--r--drivers/power/charger-manager.c1072
-rw-r--r--drivers/power/collie_battery.c55
-rw-r--r--drivers/power/da9030_battery.c13
-rw-r--r--drivers/power/da9052-battery.c664
-rw-r--r--drivers/power/ds2760_battery.c19
-rw-r--r--drivers/power/ds2780_battery.c18
-rw-r--r--drivers/power/gpio-charger.c12
-rw-r--r--drivers/power/intel_mid_battery.c13
-rw-r--r--drivers/power/isp1704_charger.c14
-rw-r--r--drivers/power/jz4740-battery.c14
-rw-r--r--drivers/power/lp8727_charger.c494
-rw-r--r--drivers/power/max17042_battery.c94
-rw-r--r--drivers/power/max8903_charger.c14
-rw-r--r--drivers/power/max8925_power.c75
-rw-r--r--drivers/power/max8997_charger.c4
-rw-r--r--drivers/power/max8998_charger.c14
-rw-r--r--drivers/power/olpc_battery.c75
-rw-r--r--drivers/power/pcf50633-charger.c12
-rw-r--r--drivers/power/pda_power.c89
-rw-r--r--drivers/power/power_supply_core.c19
-rw-r--r--drivers/power/power_supply_sysfs.c12
-rw-r--r--drivers/power/s3c_adc_battery.c37
-rw-r--r--drivers/power/sbs-battery.c (renamed from drivers/power/bq20z75.c)481
-rw-r--r--drivers/power/tosa_battery.c79
-rw-r--r--drivers/power/wm831x_backup.c12
-rw-r--r--drivers/power/wm831x_power.c56
-rw-r--r--drivers/power/wm8350_power.c12
-rw-r--r--drivers/power/wm97xx_battery.c20
-rw-r--r--drivers/power/z2_battery.c4
-rw-r--r--drivers/rtc/Kconfig6
-rw-r--r--drivers/scsi/ipr.c67
-rw-r--r--drivers/scsi/ipr.h1
-rw-r--r--drivers/sh/Makefile9
-rw-r--r--drivers/sh/clk/core.c9
-rw-r--r--drivers/sh/clk/cpg.c79
-rw-r--r--drivers/sh/pfc.c273
-rw-r--r--drivers/tty/serial/sh-sci.c183
-rw-r--r--drivers/tty/serial/sh-sci.h4
-rw-r--r--drivers/uio/uio_pci_generic.c78
110 files changed, 8034 insertions, 3547 deletions
diff --git a/drivers/acpi/pci_irq.c b/drivers/acpi/pci_irq.c
index 7f9eba9a0b02..0eefa12e648c 100644
--- a/drivers/acpi/pci_irq.c
+++ b/drivers/acpi/pci_irq.c
@@ -487,10 +487,10 @@ int acpi_pci_irq_enable(struct pci_dev *dev)
else
link_desc[0] = '\0';
- dev_info(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
- pin_name(pin), link_desc, gsi,
- (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
- (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
+ dev_dbg(&dev->dev, "PCI INT %c%s -> GSI %u (%s, %s) -> IRQ %d\n",
+ pin_name(pin), link_desc, gsi,
+ (triggering == ACPI_LEVEL_SENSITIVE) ? "level" : "edge",
+ (polarity == ACPI_ACTIVE_LOW) ? "low" : "high", dev->irq);
return 0;
}
@@ -524,6 +524,6 @@ void acpi_pci_irq_disable(struct pci_dev *dev)
* (e.g. PCI_UNDEFINED_IRQ).
*/
- dev_info(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
+ dev_dbg(&dev->dev, "PCI INT %c disabled\n", pin_name(pin));
acpi_unregister_gsi(gsi);
}
diff --git a/drivers/base/Kconfig b/drivers/base/Kconfig
index e95c67edb2cb..fcbec8ac134d 100644
--- a/drivers/base/Kconfig
+++ b/drivers/base/Kconfig
@@ -172,6 +172,10 @@ config SYS_HYPERVISOR
bool
default n
+config GENERIC_CPU_DEVICES
+ bool
+ default n
+
source "drivers/base/regmap/Kconfig"
config DMA_SHARED_BUFFER
diff --git a/drivers/base/base.h b/drivers/base/base.h
index 7a6ae4228761..b858dfd9a37c 100644
--- a/drivers/base/base.h
+++ b/drivers/base/base.h
@@ -94,7 +94,7 @@ extern int hypervisor_init(void);
static inline int hypervisor_init(void) { return 0; }
#endif
extern int platform_bus_init(void);
-extern int cpu_dev_init(void);
+extern void cpu_dev_init(void);
extern int bus_add_device(struct device *dev);
extern void bus_probe_device(struct device *dev);
diff --git a/drivers/base/cpu.c b/drivers/base/cpu.c
index 9a5578efbc93..db87e78d7459 100644
--- a/drivers/base/cpu.c
+++ b/drivers/base/cpu.c
@@ -2,6 +2,7 @@
* CPU subsystem support
*/
+#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/init.h>
#include <linux/sched.h>
@@ -10,6 +11,7 @@
#include <linux/device.h>
#include <linux/node.h>
#include <linux/gfp.h>
+#include <linux/percpu.h>
#include "base.h"
@@ -274,16 +276,30 @@ bool cpu_is_hotpluggable(unsigned cpu)
}
EXPORT_SYMBOL_GPL(cpu_is_hotpluggable);
-int __init cpu_dev_init(void)
+#ifdef CONFIG_GENERIC_CPU_DEVICES
+static DEFINE_PER_CPU(struct cpu, cpu_devices);
+#endif
+
+static void __init cpu_dev_register_generic(void)
+{
+#ifdef CONFIG_GENERIC_CPU_DEVICES
+ int i;
+
+ for_each_possible_cpu(i) {
+ if (register_cpu(&per_cpu(cpu_devices, i), i))
+ panic("Failed to register CPU device");
+ }
+#endif
+}
+
+void __init cpu_dev_init(void)
{
- int err;
+ if (subsys_system_register(&cpu_subsys, cpu_root_attr_groups))
+ panic("Failed to register CPU subsystem");
- err = subsys_system_register(&cpu_subsys, cpu_root_attr_groups);
- if (err)
- return err;
+ cpu_dev_register_generic();
#if defined(CONFIG_SCHED_MC) || defined(CONFIG_SCHED_SMT)
- err = sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
+ sched_create_sysfs_power_savings_entries(cpu_subsys.dev_root);
#endif
- return err;
}
diff --git a/drivers/char/hw_random/atmel-rng.c b/drivers/char/hw_random/atmel-rng.c
index 241df2e76aba..f518b99f53f5 100644
--- a/drivers/char/hw_random/atmel-rng.c
+++ b/drivers/char/hw_random/atmel-rng.c
@@ -141,17 +141,7 @@ static struct platform_driver atmel_trng_driver = {
},
};
-static int __init atmel_trng_init(void)
-{
- return platform_driver_register(&atmel_trng_driver);
-}
-module_init(atmel_trng_init);
-
-static void __exit atmel_trng_exit(void)
-{
- platform_driver_unregister(&atmel_trng_driver);
-}
-module_exit(atmel_trng_exit);
+module_platform_driver(atmel_trng_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Peter Korsgaard <jacmet@sunsite.dk>");
diff --git a/drivers/char/hw_random/n2-drv.c b/drivers/char/hw_random/n2-drv.c
index c3de70de00d4..ebd48f0135da 100644
--- a/drivers/char/hw_random/n2-drv.c
+++ b/drivers/char/hw_random/n2-drv.c
@@ -770,15 +770,4 @@ static struct platform_driver n2rng_driver = {
.remove = __devexit_p(n2rng_remove),
};
-static int __init n2rng_init(void)
-{
- return platform_driver_register(&n2rng_driver);
-}
-
-static void __exit n2rng_exit(void)
-{
- platform_driver_unregister(&n2rng_driver);
-}
-
-module_init(n2rng_init);
-module_exit(n2rng_exit);
+module_platform_driver(n2rng_driver);
diff --git a/drivers/char/hw_random/octeon-rng.c b/drivers/char/hw_random/octeon-rng.c
index 9cd0feca318c..0943edc782a1 100644
--- a/drivers/char/hw_random/octeon-rng.c
+++ b/drivers/char/hw_random/octeon-rng.c
@@ -131,18 +131,7 @@ static struct platform_driver octeon_rng_driver = {
.remove = __exit_p(octeon_rng_remove),
};
-static int __init octeon_rng_mod_init(void)
-{
- return platform_driver_register(&octeon_rng_driver);
-}
-
-static void __exit octeon_rng_mod_exit(void)
-{
- platform_driver_unregister(&octeon_rng_driver);
-}
-
-module_init(octeon_rng_mod_init);
-module_exit(octeon_rng_mod_exit);
+module_platform_driver(octeon_rng_driver);
MODULE_AUTHOR("David Daney");
MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/pasemi-rng.c b/drivers/char/hw_random/pasemi-rng.c
index 1d504815e6db..3a632673aed5 100644
--- a/drivers/char/hw_random/pasemi-rng.c
+++ b/drivers/char/hw_random/pasemi-rng.c
@@ -148,17 +148,7 @@ static struct platform_driver rng_driver = {
.remove = rng_remove,
};
-static int __init rng_init(void)
-{
- return platform_driver_register(&rng_driver);
-}
-module_init(rng_init);
-
-static void __exit rng_exit(void)
-{
- platform_driver_unregister(&rng_driver);
-}
-module_exit(rng_exit);
+module_platform_driver(rng_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Egor Martovetsky <egor@pasemi.com>");
diff --git a/drivers/char/hw_random/picoxcell-rng.c b/drivers/char/hw_random/picoxcell-rng.c
index 990d55a5e3e8..97bd891422c7 100644
--- a/drivers/char/hw_random/picoxcell-rng.c
+++ b/drivers/char/hw_random/picoxcell-rng.c
@@ -191,17 +191,7 @@ static struct platform_driver picoxcell_trng_driver = {
},
};
-static int __init picoxcell_trng_init(void)
-{
- return platform_driver_register(&picoxcell_trng_driver);
-}
-module_init(picoxcell_trng_init);
-
-static void __exit picoxcell_trng_exit(void)
-{
- platform_driver_unregister(&picoxcell_trng_driver);
-}
-module_exit(picoxcell_trng_exit);
+module_platform_driver(picoxcell_trng_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jamie Iles");
diff --git a/drivers/char/hw_random/ppc4xx-rng.c b/drivers/char/hw_random/ppc4xx-rng.c
index b8afa6a4ff67..c51762c13031 100644
--- a/drivers/char/hw_random/ppc4xx-rng.c
+++ b/drivers/char/hw_random/ppc4xx-rng.c
@@ -139,17 +139,7 @@ static struct platform_driver ppc4xx_rng_driver = {
.remove = ppc4xx_rng_remove,
};
-static int __init ppc4xx_rng_init(void)
-{
- return platform_driver_register(&ppc4xx_rng_driver);
-}
-module_init(ppc4xx_rng_init);
-
-static void __exit ppc4xx_rng_exit(void)
-{
- platform_driver_unregister(&ppc4xx_rng_driver);
-}
-module_exit(ppc4xx_rng_exit);
+module_platform_driver(ppc4xx_rng_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Josh Boyer <jwboyer@linux.vnet.ibm.com>");
diff --git a/drivers/char/hw_random/timeriomem-rng.c b/drivers/char/hw_random/timeriomem-rng.c
index a8428e6f64a9..f1a1618db1fb 100644
--- a/drivers/char/hw_random/timeriomem-rng.c
+++ b/drivers/char/hw_random/timeriomem-rng.c
@@ -149,18 +149,7 @@ static struct platform_driver timeriomem_rng_driver = {
.remove = __devexit_p(timeriomem_rng_remove),
};
-static int __init timeriomem_rng_init(void)
-{
- return platform_driver_register(&timeriomem_rng_driver);
-}
-
-static void __exit timeriomem_rng_exit(void)
-{
- platform_driver_unregister(&timeriomem_rng_driver);
-}
-
-module_init(timeriomem_rng_init);
-module_exit(timeriomem_rng_exit);
+module_platform_driver(timeriomem_rng_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Alexander Clouter <alex@digriz.org.uk>");
diff --git a/drivers/char/tpm/Kconfig b/drivers/char/tpm/Kconfig
index fa567f1158c2..7fc75e47e6d0 100644
--- a/drivers/char/tpm/Kconfig
+++ b/drivers/char/tpm/Kconfig
@@ -27,6 +27,7 @@ if TCG_TPM
config TCG_TIS
tristate "TPM Interface Specification 1.2 Interface"
+ depends on X86
---help---
If you have a TPM security chip that is compliant with the
TCG TIS 1.2 TPM specification say Yes and it will be accessible
@@ -35,6 +36,7 @@ config TCG_TIS
config TCG_NSC
tristate "National Semiconductor TPM Interface"
+ depends on X86
---help---
If you have a TPM security chip from National Semiconductor
say Yes and it will be accessible from within Linux. To
diff --git a/drivers/char/tpm/tpm.c b/drivers/char/tpm/tpm.c
index 361a1dff8f77..6a8771f47a55 100644
--- a/drivers/char/tpm/tpm.c
+++ b/drivers/char/tpm/tpm.c
@@ -27,6 +27,7 @@
#include <linux/slab.h>
#include <linux/mutex.h>
#include <linux/spinlock.h>
+#include <linux/freezer.h>
#include "tpm.h"
@@ -440,7 +441,6 @@ out:
}
#define TPM_DIGEST_SIZE 20
-#define TPM_ERROR_SIZE 10
#define TPM_RET_CODE_IDX 6
enum tpm_capabilities {
@@ -469,12 +469,14 @@ static ssize_t transmit_cmd(struct tpm_chip *chip, struct tpm_cmd_t *cmd,
len = tpm_transmit(chip,(u8 *) cmd, len);
if (len < 0)
return len;
- if (len == TPM_ERROR_SIZE) {
- err = be32_to_cpu(cmd->header.out.return_code);
- dev_dbg(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
- return err;
- }
- return 0;
+ else if (len < TPM_HEADER_SIZE)
+ return -EFAULT;
+
+ err = be32_to_cpu(cmd->header.out.return_code);
+ if (err != 0)
+ dev_err(chip->dev, "A TPM error (%d) occurred %s\n", err, desc);
+
+ return err;
}
#define TPM_INTERNAL_RESULT_SIZE 200
@@ -530,7 +532,7 @@ void tpm_gen_interrupt(struct tpm_chip *chip)
}
EXPORT_SYMBOL_GPL(tpm_gen_interrupt);
-void tpm_get_timeouts(struct tpm_chip *chip)
+int tpm_get_timeouts(struct tpm_chip *chip)
{
struct tpm_cmd_t tpm_cmd;
struct timeout_t *timeout_cap;
@@ -552,7 +554,7 @@ void tpm_get_timeouts(struct tpm_chip *chip)
if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
be32_to_cpu(tpm_cmd.header.out.length)
!= sizeof(tpm_cmd.header.out) + sizeof(u32) + 4 * sizeof(u32))
- return;
+ return -EINVAL;
timeout_cap = &tpm_cmd.params.getcap_out.cap.timeout;
/* Don't overwrite default if value is 0 */
@@ -583,12 +585,12 @@ duration:
rc = transmit_cmd(chip, &tpm_cmd, TPM_INTERNAL_RESULT_SIZE,
"attempting to determine the durations");
if (rc)
- return;
+ return rc;
if (be32_to_cpu(tpm_cmd.header.out.return_code) != 0 ||
be32_to_cpu(tpm_cmd.header.out.length)
!= sizeof(tpm_cmd.header.out) + sizeof(u32) + 3 * sizeof(u32))
- return;
+ return -EINVAL;
duration_cap = &tpm_cmd.params.getcap_out.cap.duration;
chip->vendor.duration[TPM_SHORT] =
@@ -610,20 +612,36 @@ duration:
chip->vendor.duration_adjusted = true;
dev_info(chip->dev, "Adjusting TPM timeout parameters.");
}
+ return 0;
}
EXPORT_SYMBOL_GPL(tpm_get_timeouts);
-void tpm_continue_selftest(struct tpm_chip *chip)
+#define TPM_ORD_CONTINUE_SELFTEST 83
+#define CONTINUE_SELFTEST_RESULT_SIZE 10
+
+static struct tpm_input_header continue_selftest_header = {
+ .tag = TPM_TAG_RQU_COMMAND,
+ .length = cpu_to_be32(10),
+ .ordinal = cpu_to_be32(TPM_ORD_CONTINUE_SELFTEST),
+};
+
+/**
+ * tpm_continue_selftest -- run TPM's selftest
+ * @chip: TPM chip to use
+ *
+ * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
+ * a TPM error code.
+ */
+static int tpm_continue_selftest(struct tpm_chip *chip)
{
- u8 data[] = {
- 0, 193, /* TPM_TAG_RQU_COMMAND */
- 0, 0, 0, 10, /* length */
- 0, 0, 0, 83, /* TPM_ORD_ContinueSelfTest */
- };
+ int rc;
+ struct tpm_cmd_t cmd;
- tpm_transmit(chip, data, sizeof(data));
+ cmd.header.in = continue_selftest_header;
+ rc = transmit_cmd(chip, &cmd, CONTINUE_SELFTEST_RESULT_SIZE,
+ "continue selftest");
+ return rc;
}
-EXPORT_SYMBOL_GPL(tpm_continue_selftest);
ssize_t tpm_show_enabled(struct device * dev, struct device_attribute * attr,
char *buf)
@@ -718,7 +736,7 @@ static struct tpm_input_header pcrread_header = {
.ordinal = TPM_ORDINAL_PCRREAD
};
-int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
+static int __tpm_pcr_read(struct tpm_chip *chip, int pcr_idx, u8 *res_buf)
{
int rc;
struct tpm_cmd_t cmd;
@@ -798,6 +816,45 @@ int tpm_pcr_extend(u32 chip_num, int pcr_idx, const u8 *hash)
}
EXPORT_SYMBOL_GPL(tpm_pcr_extend);
+/**
+ * tpm_do_selftest - have the TPM continue its selftest and wait until it
+ * can receive further commands
+ * @chip: TPM chip to use
+ *
+ * Returns 0 on success, < 0 in case of fatal error or a value > 0 representing
+ * a TPM error code.
+ */
+int tpm_do_selftest(struct tpm_chip *chip)
+{
+ int rc;
+ u8 digest[TPM_DIGEST_SIZE];
+ unsigned int loops;
+ unsigned int delay_msec = 1000;
+ unsigned long duration;
+
+ duration = tpm_calc_ordinal_duration(chip,
+ TPM_ORD_CONTINUE_SELFTEST);
+
+ loops = jiffies_to_msecs(duration) / delay_msec;
+
+ rc = tpm_continue_selftest(chip);
+ /* This may fail if there was no TPM driver during a suspend/resume
+ * cycle; some may return 10 (BAD_ORDINAL), others 28 (FAILEDSELFTEST)
+ */
+ if (rc)
+ return rc;
+
+ do {
+ rc = __tpm_pcr_read(chip, 0, digest);
+ if (rc != TPM_WARN_DOING_SELFTEST)
+ return rc;
+ msleep(delay_msec);
+ } while (--loops > 0);
+
+ return rc;
+}
+EXPORT_SYMBOL_GPL(tpm_do_selftest);
+
int tpm_send(u32 chip_num, void *cmd, size_t buflen)
{
struct tpm_chip *chip;
@@ -1005,6 +1062,46 @@ ssize_t tpm_store_cancel(struct device *dev, struct device_attribute *attr,
}
EXPORT_SYMBOL_GPL(tpm_store_cancel);
+int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
+ wait_queue_head_t *queue)
+{
+ unsigned long stop;
+ long rc;
+ u8 status;
+
+ /* check current status */
+ status = chip->vendor.status(chip);
+ if ((status & mask) == mask)
+ return 0;
+
+ stop = jiffies + timeout;
+
+ if (chip->vendor.irq) {
+again:
+ timeout = stop - jiffies;
+ if ((long)timeout <= 0)
+ return -ETIME;
+ rc = wait_event_interruptible_timeout(*queue,
+ ((chip->vendor.status(chip)
+ & mask) == mask),
+ timeout);
+ if (rc > 0)
+ return 0;
+ if (rc == -ERESTARTSYS && freezing(current)) {
+ clear_thread_flag(TIF_SIGPENDING);
+ goto again;
+ }
+ } else {
+ do {
+ msleep(TPM_TIMEOUT);
+ status = chip->vendor.status(chip);
+ if ((status & mask) == mask)
+ return 0;
+ } while (time_before(jiffies, stop));
+ }
+ return -ETIME;
+}
+EXPORT_SYMBOL_GPL(wait_for_tpm_stat);
/*
* Device file system interface to the TPM
*
diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
index 9c4163cfa3ce..8c1df302fbb6 100644
--- a/drivers/char/tpm/tpm.h
+++ b/drivers/char/tpm/tpm.h
@@ -38,6 +38,8 @@ enum tpm_addr {
TPM_ADDR = 0x4E,
};
+#define TPM_WARN_DOING_SELFTEST 0x802
+#define TPM_HEADER_SIZE 10
extern ssize_t tpm_show_pubek(struct device *, struct device_attribute *attr,
char *);
extern ssize_t tpm_show_pcrs(struct device *, struct device_attribute *attr,
@@ -279,9 +281,9 @@ struct tpm_cmd_t {
ssize_t tpm_getcap(struct device *, __be32, cap_t *, const char *);
-extern void tpm_get_timeouts(struct tpm_chip *);
+extern int tpm_get_timeouts(struct tpm_chip *);
extern void tpm_gen_interrupt(struct tpm_chip *);
-extern void tpm_continue_selftest(struct tpm_chip *);
+extern int tpm_do_selftest(struct tpm_chip *);
extern unsigned long tpm_calc_ordinal_duration(struct tpm_chip *, u32);
extern struct tpm_chip* tpm_register_hardware(struct device *,
const struct tpm_vendor_specific *);
@@ -294,7 +296,8 @@ extern ssize_t tpm_read(struct file *, char __user *, size_t, loff_t *);
extern void tpm_remove_hardware(struct device *);
extern int tpm_pm_suspend(struct device *, pm_message_t);
extern int tpm_pm_resume(struct device *);
-
+extern int wait_for_tpm_stat(struct tpm_chip *, u8, unsigned long,
+ wait_queue_head_t *);
#ifdef CONFIG_ACPI
extern struct dentry ** tpm_bios_log_setup(char *);
extern void tpm_bios_log_teardown(struct dentry **);
diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
index 3f4051a7c5a7..10cc44ceb5d1 100644
--- a/drivers/char/tpm/tpm_tis.c
+++ b/drivers/char/tpm/tpm_tis.c
@@ -29,8 +29,6 @@
#include <linux/freezer.h>
#include "tpm.h"
-#define TPM_HEADER_SIZE 10
-
enum tis_access {
TPM_ACCESS_VALID = 0x80,
TPM_ACCESS_ACTIVE_LOCALITY = 0x20,
@@ -193,54 +191,14 @@ static int get_burstcount(struct tpm_chip *chip)
return -EBUSY;
}
-static int wait_for_stat(struct tpm_chip *chip, u8 mask, unsigned long timeout,
- wait_queue_head_t *queue)
-{
- unsigned long stop;
- long rc;
- u8 status;
-
- /* check current status */
- status = tpm_tis_status(chip);
- if ((status & mask) == mask)
- return 0;
-
- stop = jiffies + timeout;
-
- if (chip->vendor.irq) {
-again:
- timeout = stop - jiffies;
- if ((long)timeout <= 0)
- return -ETIME;
- rc = wait_event_interruptible_timeout(*queue,
- ((tpm_tis_status
- (chip) & mask) ==
- mask), timeout);
- if (rc > 0)
- return 0;
- if (rc == -ERESTARTSYS && freezing(current)) {
- clear_thread_flag(TIF_SIGPENDING);
- goto again;
- }
- } else {
- do {
- msleep(TPM_TIMEOUT);
- status = tpm_tis_status(chip);
- if ((status & mask) == mask)
- return 0;
- } while (time_before(jiffies, stop));
- }
- return -ETIME;
-}
-
static int recv_data(struct tpm_chip *chip, u8 *buf, size_t count)
{
int size = 0, burstcnt;
while (size < count &&
- wait_for_stat(chip,
- TPM_STS_DATA_AVAIL | TPM_STS_VALID,
- chip->vendor.timeout_c,
- &chip->vendor.read_queue)
+ wait_for_tpm_stat(chip,
+ TPM_STS_DATA_AVAIL | TPM_STS_VALID,
+ chip->vendor.timeout_c,
+ &chip->vendor.read_queue)
== 0) {
burstcnt = get_burstcount(chip);
for (; burstcnt > 0 && size < count; burstcnt--)
@@ -282,8 +240,8 @@ static int tpm_tis_recv(struct tpm_chip *chip, u8 *buf, size_t count)
goto out;
}
- wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
- &chip->vendor.int_queue);
+ wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
status = tpm_tis_status(chip);
if (status & TPM_STS_DATA_AVAIL) { /* retry? */
dev_err(chip->dev, "Error left over data\n");
@@ -317,7 +275,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
status = tpm_tis_status(chip);
if ((status & TPM_STS_COMMAND_READY) == 0) {
tpm_tis_ready(chip);
- if (wait_for_stat
+ if (wait_for_tpm_stat
(chip, TPM_STS_COMMAND_READY, chip->vendor.timeout_b,
&chip->vendor.int_queue) < 0) {
rc = -ETIME;
@@ -333,8 +291,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
count++;
}
- wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
- &chip->vendor.int_queue);
+ wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
status = tpm_tis_status(chip);
if (!itpm && (status & TPM_STS_DATA_EXPECT) == 0) {
rc = -EIO;
@@ -345,8 +303,8 @@ static int tpm_tis_send_data(struct tpm_chip *chip, u8 *buf, size_t len)
/* write last byte */
iowrite8(buf[count],
chip->vendor.iobase + TPM_DATA_FIFO(chip->vendor.locality));
- wait_for_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
- &chip->vendor.int_queue);
+ wait_for_tpm_stat(chip, TPM_STS_VALID, chip->vendor.timeout_c,
+ &chip->vendor.int_queue);
status = tpm_tis_status(chip);
if ((status & TPM_STS_DATA_EXPECT) != 0) {
rc = -EIO;
@@ -381,7 +339,7 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
if (chip->vendor.irq) {
ordinal = be32_to_cpu(*((__be32 *) (buf + 6)));
- if (wait_for_stat
+ if (wait_for_tpm_stat
(chip, TPM_STS_DATA_AVAIL | TPM_STS_VALID,
tpm_calc_ordinal_duration(chip, ordinal),
&chip->vendor.read_queue) < 0) {
@@ -432,6 +390,9 @@ static int probe_itpm(struct tpm_chip *chip)
out:
itpm = rem_itpm;
tpm_tis_ready(chip);
+ /* some TPMs need a break here otherwise they will not work
+ * correctly on the immediately subsequent command */
+ msleep(chip->vendor.timeout_b);
release_locality(chip, chip->vendor.locality, 0);
return rc;
@@ -614,7 +575,17 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
dev_dbg(dev, "\tData Avail Int Support\n");
/* get the timeouts before testing for irqs */
- tpm_get_timeouts(chip);
+ if (tpm_get_timeouts(chip)) {
+ dev_err(dev, "Could not get TPM timeouts and durations\n");
+ rc = -ENODEV;
+ goto out_err;
+ }
+
+ if (tpm_do_selftest(chip)) {
+ dev_err(dev, "TPM self test failed\n");
+ rc = -ENODEV;
+ goto out_err;
+ }
/* INTERRUPT Setup */
init_waitqueue_head(&chip->vendor.read_queue);
@@ -722,7 +693,6 @@ static int tpm_tis_init(struct device *dev, resource_size_t start,
list_add(&chip->vendor.list, &tis_chips);
spin_unlock(&tis_lock);
- tpm_continue_selftest(chip);
return 0;
out_err:
@@ -790,7 +760,7 @@ static int tpm_tis_pnp_resume(struct pnp_dev *dev)
ret = tpm_pm_resume(&dev->dev);
if (!ret)
- tpm_continue_selftest(chip);
+ tpm_do_selftest(chip);
return ret;
}
diff --git a/drivers/cpufreq/Kconfig.arm b/drivers/cpufreq/Kconfig.arm
index 72a0044c1baa..e0664fed018a 100644
--- a/drivers/cpufreq/Kconfig.arm
+++ b/drivers/cpufreq/Kconfig.arm
@@ -21,12 +21,19 @@ config ARM_S5PV210_CPUFREQ
If in doubt, say N.
+config ARM_EXYNOS_CPUFREQ
+ bool "SAMSUNG EXYNOS SoCs"
+ depends on ARCH_EXYNOS
+ select ARM_EXYNOS4210_CPUFREQ if CPU_EXYNOS4210
+ default y
+ help
+ This adds the CPUFreq driver common part for Samsung
+ EXYNOS SoCs.
+
+ If in doubt, say N.
+
config ARM_EXYNOS4210_CPUFREQ
bool "Samsung EXYNOS4210"
- depends on CPU_EXYNOS4210
- default y
help
This adds the CPUFreq driver for Samsung EXYNOS4210
SoC (S5PV310 or S5PC210).
-
- If in doubt, say N.
diff --git a/drivers/cpufreq/Makefile b/drivers/cpufreq/Makefile
index a48bc02cd765..ac000fa76bbb 100644
--- a/drivers/cpufreq/Makefile
+++ b/drivers/cpufreq/Makefile
@@ -42,7 +42,9 @@ obj-$(CONFIG_X86_CPUFREQ_NFORCE2) += cpufreq-nforce2.o
obj-$(CONFIG_UX500_SOC_DB8500) += db8500-cpufreq.o
obj-$(CONFIG_ARM_S3C64XX_CPUFREQ) += s3c64xx-cpufreq.o
obj-$(CONFIG_ARM_S5PV210_CPUFREQ) += s5pv210-cpufreq.o
+obj-$(CONFIG_ARM_EXYNOS_CPUFREQ) += exynos-cpufreq.o
obj-$(CONFIG_ARM_EXYNOS4210_CPUFREQ) += exynos4210-cpufreq.o
+obj-$(CONFIG_ARCH_OMAP2PLUS) += omap-cpufreq.o
##################################################################################
# PowerPC platform drivers
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 8c2df3499da7..622013fb7890 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -204,8 +204,7 @@ static void adjust_jiffies(unsigned long val, struct cpufreq_freqs *ci)
pr_debug("saving %lu as reference value for loops_per_jiffy; "
"freq is %u kHz\n", l_p_j_ref, l_p_j_ref_freq);
}
- if ((val == CPUFREQ_PRECHANGE && ci->old < ci->new) ||
- (val == CPUFREQ_POSTCHANGE && ci->old > ci->new) ||
+ if ((val == CPUFREQ_POSTCHANGE && ci->old != ci->new) ||
(val == CPUFREQ_RESUMECHANGE || val == CPUFREQ_SUSPENDCHANGE)) {
loops_per_jiffy = cpufreq_scale(l_p_j_ref, l_p_j_ref_freq,
ci->new);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 3d679eee70a1..c3e0652520a1 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -713,11 +713,10 @@ static int cpufreq_governor_dbs(struct cpufreq_policy *policy,
static int __init cpufreq_gov_dbs_init(void)
{
- cputime64_t wall;
u64 idle_time;
int cpu = get_cpu();
- idle_time = get_cpu_idle_time_us(cpu, &wall);
+ idle_time = get_cpu_idle_time_us(cpu, NULL);
put_cpu();
if (idle_time != -1ULL) {
/* Idle micro accounting is supported. Use finer thresholds */
diff --git a/drivers/cpufreq/cpufreq_userspace.c b/drivers/cpufreq/cpufreq_userspace.c
index f231015904c0..bedac1aa9be3 100644
--- a/drivers/cpufreq/cpufreq_userspace.c
+++ b/drivers/cpufreq/cpufreq_userspace.c
@@ -47,9 +47,11 @@ userspace_cpufreq_notifier(struct notifier_block *nb, unsigned long val,
if (!per_cpu(cpu_is_managed, freq->cpu))
return 0;
- pr_debug("saving cpu_cur_freq of cpu %u to be %u kHz\n",
- freq->cpu, freq->new);
- per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
+ if (val == CPUFREQ_POSTCHANGE) {
+ pr_debug("saving cpu_cur_freq of cpu %u to be %u kHz\n",
+ freq->cpu, freq->new);
+ per_cpu(cpu_cur_freq, freq->cpu) = freq->new;
+ }
return 0;
}
diff --git a/drivers/cpufreq/exynos-cpufreq.c b/drivers/cpufreq/exynos-cpufreq.c
new file mode 100644
index 000000000000..5467879ea07d
--- /dev/null
+++ b/drivers/cpufreq/exynos-cpufreq.c
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
+ * http://www.samsung.com
+ *
+ * EXYNOS - CPU frequency scaling support for EXYNOS series
+ *
+ * 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.
+*/
+
+#include <linux/kernel.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/regulator/consumer.h>
+#include <linux/cpufreq.h>
+#include <linux/suspend.h>
+
+#include <mach/cpufreq.h>
+
+#include <plat/cpu.h>
+
+static struct exynos_dvfs_info *exynos_info;
+
+static struct regulator *arm_regulator;
+static struct cpufreq_freqs freqs;
+
+static unsigned int locking_frequency;
+static bool frequency_locked;
+static DEFINE_MUTEX(cpufreq_lock);
+
+int exynos_verify_speed(struct cpufreq_policy *policy)
+{
+ return cpufreq_frequency_table_verify(policy,
+ exynos_info->freq_table);
+}
+
+unsigned int exynos_getspeed(unsigned int cpu)
+{
+ return clk_get_rate(exynos_info->cpu_clk) / 1000;
+}
+
+static int exynos_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned int index, old_index;
+ unsigned int arm_volt, safe_arm_volt = 0;
+ int ret = 0;
+ struct cpufreq_frequency_table *freq_table = exynos_info->freq_table;
+ unsigned int *volt_table = exynos_info->volt_table;
+ unsigned int mpll_freq_khz = exynos_info->mpll_freq_khz;
+
+ mutex_lock(&cpufreq_lock);
+
+ freqs.old = policy->cur;
+
+ if (frequency_locked && target_freq != locking_frequency) {
+ ret = -EAGAIN;
+ goto out;
+ }
+
+ if (cpufreq_frequency_table_target(policy, freq_table,
+ freqs.old, relation, &old_index)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (cpufreq_frequency_table_target(policy, freq_table,
+ target_freq, relation, &index)) {
+ ret = -EINVAL;
+ goto out;
+ }
+
+ freqs.new = freq_table[index].frequency;
+ freqs.cpu = policy->cpu;
+
+ /*
+ * ARM clock source will be changed APLL to MPLL temporary
+ * To support this level, need to control regulator for
+ * required voltage level
+ */
+ if (exynos_info->need_apll_change != NULL) {
+ if (exynos_info->need_apll_change(old_index, index) &&
+ (freq_table[index].frequency < mpll_freq_khz) &&
+ (freq_table[old_index].frequency < mpll_freq_khz))
+ safe_arm_volt = volt_table[exynos_info->pll_safe_idx];
+ }
+ arm_volt = volt_table[index];
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+
+ /* When the new frequency is higher than current frequency */
+ if ((freqs.new > freqs.old) && !safe_arm_volt) {
+ /* Firstly, voltage up to increase frequency */
+ regulator_set_voltage(arm_regulator, arm_volt,
+ arm_volt);
+ }
+
+ if (safe_arm_volt)
+ regulator_set_voltage(arm_regulator, safe_arm_volt,
+ safe_arm_volt);
+ if (freqs.new != freqs.old)
+ exynos_info->set_freq(old_index, index);
+
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+
+ /* When the new frequency is lower than current frequency */
+ if ((freqs.new < freqs.old) ||
+ ((freqs.new > freqs.old) && safe_arm_volt)) {
+ /* down the voltage after frequency change */
+ regulator_set_voltage(arm_regulator, arm_volt,
+ arm_volt);
+ }
+
+out:
+ mutex_unlock(&cpufreq_lock);
+
+ return ret;
+}
+
+#ifdef CONFIG_PM
+static int exynos_cpufreq_suspend(struct cpufreq_policy *policy)
+{
+ return 0;
+}
+
+static int exynos_cpufreq_resume(struct cpufreq_policy *policy)
+{
+ return 0;
+}
+#endif
+
+/**
+ * exynos_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
+ * context
+ * @notifier
+ * @pm_event
+ * @v
+ *
+ * While frequency_locked == true, target() ignores every frequency but
+ * locking_frequency. The locking_frequency value is the initial frequency,
+ * which is set by the bootloader. In order to eliminate possible
+ * inconsistency in clock values, we save and restore frequencies during
+ * suspend and resume and block CPUFREQ activities. Note that the standard
+ * suspend/resume cannot be used as they are too deep (syscore_ops) for
+ * regulator actions.
+ */
+static int exynos_cpufreq_pm_notifier(struct notifier_block *notifier,
+ unsigned long pm_event, void *v)
+{
+ struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
+ static unsigned int saved_frequency;
+ unsigned int temp;
+
+ mutex_lock(&cpufreq_lock);
+ switch (pm_event) {
+ case PM_SUSPEND_PREPARE:
+ if (frequency_locked)
+ goto out;
+
+ frequency_locked = true;
+
+ if (locking_frequency) {
+ saved_frequency = exynos_getspeed(0);
+
+ mutex_unlock(&cpufreq_lock);
+ exynos_target(policy, locking_frequency,
+ CPUFREQ_RELATION_H);
+ mutex_lock(&cpufreq_lock);
+ }
+ break;
+
+ case PM_POST_SUSPEND:
+ if (saved_frequency) {
+ /*
+ * While frequency_locked, only locking_frequency
+ * is valid for target(). In order to use
+ * saved_frequency while keeping frequency_locked,
+ * we temporarly overwrite locking_frequency.
+ */
+ temp = locking_frequency;
+ locking_frequency = saved_frequency;
+
+ mutex_unlock(&cpufreq_lock);
+ exynos_target(policy, locking_frequency,
+ CPUFREQ_RELATION_H);
+ mutex_lock(&cpufreq_lock);
+
+ locking_frequency = temp;
+ }
+ frequency_locked = false;
+ break;
+ }
+out:
+ mutex_unlock(&cpufreq_lock);
+
+ return NOTIFY_OK;
+}
+
+static struct notifier_block exynos_cpufreq_nb = {
+ .notifier_call = exynos_cpufreq_pm_notifier,
+};
+
+static int exynos_cpufreq_cpu_init(struct cpufreq_policy *policy)
+{
+ policy->cur = policy->min = policy->max = exynos_getspeed(policy->cpu);
+
+ cpufreq_frequency_table_get_attr(exynos_info->freq_table, policy->cpu);
+
+ /* set the transition latency value */
+ policy->cpuinfo.transition_latency = 100000;
+
+ /*
+ * EXYNOS4 multi-core processors has 2 cores
+ * that the frequency cannot be set independently.
+ * Each cpu is bound to the same speed.
+ * So the affected cpu is all of the cpus.
+ */
+ if (num_online_cpus() == 1) {
+ cpumask_copy(policy->related_cpus, cpu_possible_mask);
+ cpumask_copy(policy->cpus, cpu_online_mask);
+ } else {
+ cpumask_setall(policy->cpus);
+ }
+
+ return cpufreq_frequency_table_cpuinfo(policy, exynos_info->freq_table);
+}
+
+static struct cpufreq_driver exynos_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = exynos_verify_speed,
+ .target = exynos_target,
+ .get = exynos_getspeed,
+ .init = exynos_cpufreq_cpu_init,
+ .name = "exynos_cpufreq",
+#ifdef CONFIG_PM
+ .suspend = exynos_cpufreq_suspend,
+ .resume = exynos_cpufreq_resume,
+#endif
+};
+
+static int __init exynos_cpufreq_init(void)
+{
+ int ret = -EINVAL;
+
+ exynos_info = kzalloc(sizeof(struct exynos_dvfs_info), GFP_KERNEL);
+ if (!exynos_info)
+ return -ENOMEM;
+
+ if (soc_is_exynos4210())
+ ret = exynos4210_cpufreq_init(exynos_info);
+ else
+ pr_err("%s: CPU type not found\n", __func__);
+
+ if (ret)
+ goto err_vdd_arm;
+
+ if (exynos_info->set_freq == NULL) {
+ pr_err("%s: No set_freq function (ERR)\n", __func__);
+ goto err_vdd_arm;
+ }
+
+ arm_regulator = regulator_get(NULL, "vdd_arm");
+ if (IS_ERR(arm_regulator)) {
+ pr_err("%s: failed to get resource vdd_arm\n", __func__);
+ goto err_vdd_arm;
+ }
+
+ register_pm_notifier(&exynos_cpufreq_nb);
+
+ if (cpufreq_register_driver(&exynos_driver)) {
+ pr_err("%s: failed to register cpufreq driver\n", __func__);
+ goto err_cpufreq;
+ }
+
+ return 0;
+err_cpufreq:
+ unregister_pm_notifier(&exynos_cpufreq_nb);
+
+ if (!IS_ERR(arm_regulator))
+ regulator_put(arm_regulator);
+err_vdd_arm:
+ kfree(exynos_info);
+ pr_debug("%s: failed initialization\n", __func__);
+ return -EINVAL;
+}
+late_initcall(exynos_cpufreq_init);
diff --git a/drivers/cpufreq/exynos4210-cpufreq.c b/drivers/cpufreq/exynos4210-cpufreq.c
index ab9741fab92e..065da5b702f1 100644
--- a/drivers/cpufreq/exynos4210-cpufreq.c
+++ b/drivers/cpufreq/exynos4210-cpufreq.c
@@ -2,61 +2,52 @@
* Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
* http://www.samsung.com
*
- * EXYNOS4 - CPU frequency scaling support
+ * EXYNOS4210 - CPU frequency scaling support
*
* 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.
*/
-#include <linux/types.h>
+#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/err.h>
#include <linux/clk.h>
#include <linux/io.h>
#include <linux/slab.h>
-#include <linux/regulator/consumer.h>
#include <linux/cpufreq.h>
-#include <linux/notifier.h>
-#include <linux/suspend.h>
-#include <mach/map.h>
#include <mach/regs-clock.h>
-#include <mach/regs-mem.h>
+#include <mach/cpufreq.h>
-#include <plat/clock.h>
-#include <plat/pm.h>
+#define CPUFREQ_LEVEL_END L5
+
+static int max_support_idx = L0;
+static int min_support_idx = (CPUFREQ_LEVEL_END - 1);
static struct clk *cpu_clk;
static struct clk *moutcore;
static struct clk *mout_mpll;
static struct clk *mout_apll;
-static struct regulator *arm_regulator;
-static struct regulator *int_regulator;
-
-static struct cpufreq_freqs freqs;
-static unsigned int memtype;
-
-static unsigned int locking_frequency;
-static bool frequency_locked;
-static DEFINE_MUTEX(cpufreq_lock);
-
-enum exynos4_memory_type {
- DDR2 = 4,
- LPDDR2,
- DDR3,
+struct cpufreq_clkdiv {
+ unsigned int index;
+ unsigned int clkdiv;
};
-enum cpufreq_level_index {
- L0, L1, L2, L3, CPUFREQ_LEVEL_END,
+static unsigned int exynos4210_volt_table[CPUFREQ_LEVEL_END] = {
+ 1250000, 1150000, 1050000, 975000, 950000,
};
-static struct cpufreq_frequency_table exynos4_freq_table[] = {
- {L0, 1000*1000},
- {L1, 800*1000},
- {L2, 400*1000},
- {L3, 100*1000},
+
+static struct cpufreq_clkdiv exynos4210_clkdiv_table[CPUFREQ_LEVEL_END];
+
+static struct cpufreq_frequency_table exynos4210_freq_table[] = {
+ {L0, 1200*1000},
+ {L1, 1000*1000},
+ {L2, 800*1000},
+ {L3, 500*1000},
+ {L4, 200*1000},
{0, CPUFREQ_TABLE_END},
};
@@ -67,17 +58,20 @@ static unsigned int clkdiv_cpu0[CPUFREQ_LEVEL_END][7] = {
* DIVATB, DIVPCLK_DBG, DIVAPLL }
*/
- /* ARM L0: 1000MHz */
- { 0, 3, 7, 3, 3, 0, 1 },
+ /* ARM L0: 1200MHz */
+ { 0, 3, 7, 3, 4, 1, 7 },
- /* ARM L1: 800MHz */
- { 0, 3, 7, 3, 3, 0, 1 },
+ /* ARM L1: 1000MHz */
+ { 0, 3, 7, 3, 4, 1, 7 },
- /* ARM L2: 400MHz */
- { 0, 1, 3, 1, 3, 0, 1 },
+ /* ARM L2: 800MHz */
+ { 0, 3, 7, 3, 3, 1, 7 },
- /* ARM L3: 100MHz */
- { 0, 0, 1, 0, 3, 1, 1 },
+ /* ARM L3: 500MHz */
+ { 0, 3, 7, 3, 3, 1, 7 },
+
+ /* ARM L4: 200MHz */
+ { 0, 1, 3, 1, 3, 1, 0 },
};
static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
@@ -86,147 +80,46 @@ static unsigned int clkdiv_cpu1[CPUFREQ_LEVEL_END][2] = {
* { DIVCOPY, DIVHPM }
*/
- /* ARM L0: 1000MHz */
- { 3, 0 },
+ /* ARM L0: 1200MHz */
+ { 5, 0 },
- /* ARM L1: 800MHz */
- { 3, 0 },
+ /* ARM L1: 1000MHz */
+ { 4, 0 },
- /* ARM L2: 400MHz */
+ /* ARM L2: 800MHz */
{ 3, 0 },
- /* ARM L3: 100MHz */
+ /* ARM L3: 500MHz */
{ 3, 0 },
-};
-
-static unsigned int clkdiv_dmc0[CPUFREQ_LEVEL_END][8] = {
- /*
- * Clock divider value for following
- * { DIVACP, DIVACP_PCLK, DIVDPHY, DIVDMC, DIVDMCD
- * DIVDMCP, DIVCOPY2, DIVCORE_TIMERS }
- */
-
- /* DMC L0: 400MHz */
- { 3, 1, 1, 1, 1, 1, 3, 1 },
-
- /* DMC L1: 400MHz */
- { 3, 1, 1, 1, 1, 1, 3, 1 },
-
- /* DMC L2: 266.7MHz */
- { 7, 1, 1, 2, 1, 1, 3, 1 },
-
- /* DMC L3: 200MHz */
- { 7, 1, 1, 3, 1, 1, 3, 1 },
-};
-
-static unsigned int clkdiv_top[CPUFREQ_LEVEL_END][5] = {
- /*
- * Clock divider value for following
- * { DIVACLK200, DIVACLK100, DIVACLK160, DIVACLK133, DIVONENAND }
- */
- /* ACLK200 L0: 200MHz */
- { 3, 7, 4, 5, 1 },
-
- /* ACLK200 L1: 200MHz */
- { 3, 7, 4, 5, 1 },
-
- /* ACLK200 L2: 160MHz */
- { 4, 7, 5, 7, 1 },
-
- /* ACLK200 L3: 133.3MHz */
- { 5, 7, 7, 7, 1 },
-};
-
-static unsigned int clkdiv_lr_bus[CPUFREQ_LEVEL_END][2] = {
- /*
- * Clock divider value for following
- * { DIVGDL/R, DIVGPL/R }
- */
-
- /* ACLK_GDL/R L0: 200MHz */
- { 3, 1 },
-
- /* ACLK_GDL/R L1: 200MHz */
- { 3, 1 },
-
- /* ACLK_GDL/R L2: 160MHz */
- { 4, 1 },
-
- /* ACLK_GDL/R L3: 133.3MHz */
- { 5, 1 },
-};
-
-struct cpufreq_voltage_table {
- unsigned int index; /* any */
- unsigned int arm_volt; /* uV */
- unsigned int int_volt;
+ /* ARM L4: 200MHz */
+ { 3, 0 },
};
-static struct cpufreq_voltage_table exynos4_volt_table[CPUFREQ_LEVEL_END] = {
- {
- .index = L0,
- .arm_volt = 1200000,
- .int_volt = 1100000,
- }, {
- .index = L1,
- .arm_volt = 1100000,
- .int_volt = 1100000,
- }, {
- .index = L2,
- .arm_volt = 1000000,
- .int_volt = 1000000,
- }, {
- .index = L3,
- .arm_volt = 900000,
- .int_volt = 1000000,
- },
-};
+static unsigned int exynos4210_apll_pms_table[CPUFREQ_LEVEL_END] = {
+ /* APLL FOUT L0: 1200MHz */
+ ((150 << 16) | (3 << 8) | 1),
-static unsigned int exynos4_apll_pms_table[CPUFREQ_LEVEL_END] = {
- /* APLL FOUT L0: 1000MHz */
+ /* APLL FOUT L1: 1000MHz */
((250 << 16) | (6 << 8) | 1),
- /* APLL FOUT L1: 800MHz */
+ /* APLL FOUT L2: 800MHz */
((200 << 16) | (6 << 8) | 1),
- /* APLL FOUT L2 : 400MHz */
- ((200 << 16) | (6 << 8) | 2),
+ /* APLL FOUT L3: 500MHz */
+ ((250 << 16) | (6 << 8) | 2),
- /* APLL FOUT L3: 100MHz */
- ((200 << 16) | (6 << 8) | 4),
+ /* APLL FOUT L4: 200MHz */
+ ((200 << 16) | (6 << 8) | 3),
};
-static int exynos4_verify_speed(struct cpufreq_policy *policy)
-{
- return cpufreq_frequency_table_verify(policy, exynos4_freq_table);
-}
-
-static unsigned int exynos4_getspeed(unsigned int cpu)
-{
- return clk_get_rate(cpu_clk) / 1000;
-}
-
-static void exynos4_set_clkdiv(unsigned int div_index)
+static void exynos4210_set_clkdiv(unsigned int div_index)
{
unsigned int tmp;
/* Change Divider - CPU0 */
- tmp = __raw_readl(S5P_CLKDIV_CPU);
-
- tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK | S5P_CLKDIV_CPU0_COREM0_MASK |
- S5P_CLKDIV_CPU0_COREM1_MASK | S5P_CLKDIV_CPU0_PERIPH_MASK |
- S5P_CLKDIV_CPU0_ATB_MASK | S5P_CLKDIV_CPU0_PCLKDBG_MASK |
- S5P_CLKDIV_CPU0_APLL_MASK);
-
- tmp |= ((clkdiv_cpu0[div_index][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
- (clkdiv_cpu0[div_index][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
- (clkdiv_cpu0[div_index][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
- (clkdiv_cpu0[div_index][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
- (clkdiv_cpu0[div_index][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
- (clkdiv_cpu0[div_index][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
- (clkdiv_cpu0[div_index][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
+ tmp = exynos4210_clkdiv_table[div_index].clkdiv;
__raw_writel(tmp, S5P_CLKDIV_CPU);
@@ -248,83 +141,9 @@ static void exynos4_set_clkdiv(unsigned int div_index)
do {
tmp = __raw_readl(S5P_CLKDIV_STATCPU1);
} while (tmp & 0x11);
-
- /* Change Divider - DMC0 */
-
- tmp = __raw_readl(S5P_CLKDIV_DMC0);
-
- tmp &= ~(S5P_CLKDIV_DMC0_ACP_MASK | S5P_CLKDIV_DMC0_ACPPCLK_MASK |
- S5P_CLKDIV_DMC0_DPHY_MASK | S5P_CLKDIV_DMC0_DMC_MASK |
- S5P_CLKDIV_DMC0_DMCD_MASK | S5P_CLKDIV_DMC0_DMCP_MASK |
- S5P_CLKDIV_DMC0_COPY2_MASK | S5P_CLKDIV_DMC0_CORETI_MASK);
-
- tmp |= ((clkdiv_dmc0[div_index][0] << S5P_CLKDIV_DMC0_ACP_SHIFT) |
- (clkdiv_dmc0[div_index][1] << S5P_CLKDIV_DMC0_ACPPCLK_SHIFT) |
- (clkdiv_dmc0[div_index][2] << S5P_CLKDIV_DMC0_DPHY_SHIFT) |
- (clkdiv_dmc0[div_index][3] << S5P_CLKDIV_DMC0_DMC_SHIFT) |
- (clkdiv_dmc0[div_index][4] << S5P_CLKDIV_DMC0_DMCD_SHIFT) |
- (clkdiv_dmc0[div_index][5] << S5P_CLKDIV_DMC0_DMCP_SHIFT) |
- (clkdiv_dmc0[div_index][6] << S5P_CLKDIV_DMC0_COPY2_SHIFT) |
- (clkdiv_dmc0[div_index][7] << S5P_CLKDIV_DMC0_CORETI_SHIFT));
-
- __raw_writel(tmp, S5P_CLKDIV_DMC0);
-
- do {
- tmp = __raw_readl(S5P_CLKDIV_STAT_DMC0);
- } while (tmp & 0x11111111);
-
- /* Change Divider - TOP */
-
- tmp = __raw_readl(S5P_CLKDIV_TOP);
-
- tmp &= ~(S5P_CLKDIV_TOP_ACLK200_MASK | S5P_CLKDIV_TOP_ACLK100_MASK |
- S5P_CLKDIV_TOP_ACLK160_MASK | S5P_CLKDIV_TOP_ACLK133_MASK |
- S5P_CLKDIV_TOP_ONENAND_MASK);
-
- tmp |= ((clkdiv_top[div_index][0] << S5P_CLKDIV_TOP_ACLK200_SHIFT) |
- (clkdiv_top[div_index][1] << S5P_CLKDIV_TOP_ACLK100_SHIFT) |
- (clkdiv_top[div_index][2] << S5P_CLKDIV_TOP_ACLK160_SHIFT) |
- (clkdiv_top[div_index][3] << S5P_CLKDIV_TOP_ACLK133_SHIFT) |
- (clkdiv_top[div_index][4] << S5P_CLKDIV_TOP_ONENAND_SHIFT));
-
- __raw_writel(tmp, S5P_CLKDIV_TOP);
-
- do {
- tmp = __raw_readl(S5P_CLKDIV_STAT_TOP);
- } while (tmp & 0x11111);
-
- /* Change Divider - LEFTBUS */
-
- tmp = __raw_readl(S5P_CLKDIV_LEFTBUS);
-
- tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
- tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
- (clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
- __raw_writel(tmp, S5P_CLKDIV_LEFTBUS);
-
- do {
- tmp = __raw_readl(S5P_CLKDIV_STAT_LEFTBUS);
- } while (tmp & 0x11);
-
- /* Change Divider - RIGHTBUS */
-
- tmp = __raw_readl(S5P_CLKDIV_RIGHTBUS);
-
- tmp &= ~(S5P_CLKDIV_BUS_GDLR_MASK | S5P_CLKDIV_BUS_GPLR_MASK);
-
- tmp |= ((clkdiv_lr_bus[div_index][0] << S5P_CLKDIV_BUS_GDLR_SHIFT) |
- (clkdiv_lr_bus[div_index][1] << S5P_CLKDIV_BUS_GPLR_SHIFT));
-
- __raw_writel(tmp, S5P_CLKDIV_RIGHTBUS);
-
- do {
- tmp = __raw_readl(S5P_CLKDIV_STAT_RIGHTBUS);
- } while (tmp & 0x11);
}
-static void exynos4_set_apll(unsigned int index)
+static void exynos4210_set_apll(unsigned int index)
{
unsigned int tmp;
@@ -343,7 +162,7 @@ static void exynos4_set_apll(unsigned int index)
/* 3. Change PLL PMS values */
tmp = __raw_readl(S5P_APLL_CON0);
tmp &= ~((0x3ff << 16) | (0x3f << 8) | (0x7 << 0));
- tmp |= exynos4_apll_pms_table[index];
+ tmp |= exynos4210_apll_pms_table[index];
__raw_writel(tmp, S5P_APLL_CON0);
/* 4. wait_lock_time */
@@ -360,328 +179,126 @@ static void exynos4_set_apll(unsigned int index)
} while (tmp != (0x1 << S5P_CLKSRC_CPU_MUXCORE_SHIFT));
}
-static void exynos4_set_frequency(unsigned int old_index, unsigned int new_index)
+bool exynos4210_pms_change(unsigned int old_index, unsigned int new_index)
+{
+ unsigned int old_pm = (exynos4210_apll_pms_table[old_index] >> 8);
+ unsigned int new_pm = (exynos4210_apll_pms_table[new_index] >> 8);
+
+ return (old_pm == new_pm) ? 0 : 1;
+}
+
+static void exynos4210_set_frequency(unsigned int old_index,
+ unsigned int new_index)
{
unsigned int tmp;
if (old_index > new_index) {
- /* The frequency changing to L0 needs to change apll */
- if (freqs.new == exynos4_freq_table[L0].frequency) {
- /* 1. Change the system clock divider values */
- exynos4_set_clkdiv(new_index);
-
- /* 2. Change the apll m,p,s value */
- exynos4_set_apll(new_index);
- } else {
+ if (!exynos4210_pms_change(old_index, new_index)) {
/* 1. Change the system clock divider values */
- exynos4_set_clkdiv(new_index);
+ exynos4210_set_clkdiv(new_index);
/* 2. Change just s value in apll m,p,s value */
tmp = __raw_readl(S5P_APLL_CON0);
tmp &= ~(0x7 << 0);
- tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
+ tmp |= (exynos4210_apll_pms_table[new_index] & 0x7);
__raw_writel(tmp, S5P_APLL_CON0);
- }
- }
-
- else if (old_index < new_index) {
- /* The frequency changing from L0 needs to change apll */
- if (freqs.old == exynos4_freq_table[L0].frequency) {
- /* 1. Change the apll m,p,s value */
- exynos4_set_apll(new_index);
-
- /* 2. Change the system clock divider values */
- exynos4_set_clkdiv(new_index);
} else {
+ /* Clock Configuration Procedure */
+ /* 1. Change the system clock divider values */
+ exynos4210_set_clkdiv(new_index);
+ /* 2. Change the apll m,p,s value */
+ exynos4210_set_apll(new_index);
+ }
+ } else if (old_index < new_index) {
+ if (!exynos4210_pms_change(old_index, new_index)) {
/* 1. Change just s value in apll m,p,s value */
tmp = __raw_readl(S5P_APLL_CON0);
tmp &= ~(0x7 << 0);
- tmp |= (exynos4_apll_pms_table[new_index] & 0x7);
+ tmp |= (exynos4210_apll_pms_table[new_index] & 0x7);
__raw_writel(tmp, S5P_APLL_CON0);
/* 2. Change the system clock divider values */
- exynos4_set_clkdiv(new_index);
+ exynos4210_set_clkdiv(new_index);
+ } else {
+ /* Clock Configuration Procedure */
+ /* 1. Change the apll m,p,s value */
+ exynos4210_set_apll(new_index);
+ /* 2. Change the system clock divider values */
+ exynos4210_set_clkdiv(new_index);
}
}
}
-static int exynos4_target(struct cpufreq_policy *policy,
- unsigned int target_freq,
- unsigned int relation)
-{
- unsigned int index, old_index;
- unsigned int arm_volt, int_volt;
- int err = -EINVAL;
-
- freqs.old = exynos4_getspeed(policy->cpu);
-
- mutex_lock(&cpufreq_lock);
-
- if (frequency_locked && target_freq != locking_frequency) {
- err = -EAGAIN;
- goto out;
- }
-
- if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
- freqs.old, relation, &old_index))
- goto out;
-
- if (cpufreq_frequency_table_target(policy, exynos4_freq_table,
- target_freq, relation, &index))
- goto out;
-
- err = 0;
-
- freqs.new = exynos4_freq_table[index].frequency;
- freqs.cpu = policy->cpu;
-
- if (freqs.new == freqs.old)
- goto out;
-
- /* get the voltage value */
- arm_volt = exynos4_volt_table[index].arm_volt;
- int_volt = exynos4_volt_table[index].int_volt;
-
- cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
-
- /* control regulator */
- if (freqs.new > freqs.old) {
- /* Voltage up */
- regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
- regulator_set_voltage(int_regulator, int_volt, int_volt);
- }
-
- /* Clock Configuration Procedure */
- exynos4_set_frequency(old_index, index);
-
- /* control regulator */
- if (freqs.new < freqs.old) {
- /* Voltage down */
- regulator_set_voltage(arm_regulator, arm_volt, arm_volt);
- regulator_set_voltage(int_regulator, int_volt, int_volt);
- }
-
- cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
-
-out:
- mutex_unlock(&cpufreq_lock);
- return err;
-}
-
-#ifdef CONFIG_PM
-/*
- * These suspend/resume are used as syscore_ops, it is already too
- * late to set regulator voltages at this stage.
- */
-static int exynos4_cpufreq_suspend(struct cpufreq_policy *policy)
-{
- return 0;
-}
-
-static int exynos4_cpufreq_resume(struct cpufreq_policy *policy)
+int exynos4210_cpufreq_init(struct exynos_dvfs_info *info)
{
- return 0;
-}
-#endif
-
-/**
- * exynos4_cpufreq_pm_notifier - block CPUFREQ's activities in suspend-resume
- * context
- * @notifier
- * @pm_event
- * @v
- *
- * While frequency_locked == true, target() ignores every frequency but
- * locking_frequency. The locking_frequency value is the initial frequency,
- * which is set by the bootloader. In order to eliminate possible
- * inconsistency in clock values, we save and restore frequencies during
- * suspend and resume and block CPUFREQ activities. Note that the standard
- * suspend/resume cannot be used as they are too deep (syscore_ops) for
- * regulator actions.
- */
-static int exynos4_cpufreq_pm_notifier(struct notifier_block *notifier,
- unsigned long pm_event, void *v)
-{
- struct cpufreq_policy *policy = cpufreq_cpu_get(0); /* boot CPU */
- static unsigned int saved_frequency;
- unsigned int temp;
-
- mutex_lock(&cpufreq_lock);
- switch (pm_event) {
- case PM_SUSPEND_PREPARE:
- if (frequency_locked)
- goto out;
- frequency_locked = true;
-
- if (locking_frequency) {
- saved_frequency = exynos4_getspeed(0);
-
- mutex_unlock(&cpufreq_lock);
- exynos4_target(policy, locking_frequency,
- CPUFREQ_RELATION_H);
- mutex_lock(&cpufreq_lock);
- }
-
- break;
- case PM_POST_SUSPEND:
-
- if (saved_frequency) {
- /*
- * While frequency_locked, only locking_frequency
- * is valid for target(). In order to use
- * saved_frequency while keeping frequency_locked,
- * we temporarly overwrite locking_frequency.
- */
- temp = locking_frequency;
- locking_frequency = saved_frequency;
-
- mutex_unlock(&cpufreq_lock);
- exynos4_target(policy, locking_frequency,
- CPUFREQ_RELATION_H);
- mutex_lock(&cpufreq_lock);
-
- locking_frequency = temp;
- }
-
- frequency_locked = false;
- break;
- }
-out:
- mutex_unlock(&cpufreq_lock);
-
- return NOTIFY_OK;
-}
-
-static struct notifier_block exynos4_cpufreq_nb = {
- .notifier_call = exynos4_cpufreq_pm_notifier,
-};
-
-static int exynos4_cpufreq_cpu_init(struct cpufreq_policy *policy)
-{
- int ret;
-
- policy->cur = policy->min = policy->max = exynos4_getspeed(policy->cpu);
-
- cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
-
- /* set the transition latency value */
- policy->cpuinfo.transition_latency = 100000;
-
- /*
- * EXYNOS4 multi-core processors has 2 cores
- * that the frequency cannot be set independently.
- * Each cpu is bound to the same speed.
- * So the affected cpu is all of the cpus.
- */
- cpumask_setall(policy->cpus);
-
- ret = cpufreq_frequency_table_cpuinfo(policy, exynos4_freq_table);
- if (ret)
- return ret;
-
- cpufreq_frequency_table_get_attr(exynos4_freq_table, policy->cpu);
-
- return 0;
-}
-
-static int exynos4_cpufreq_cpu_exit(struct cpufreq_policy *policy)
-{
- cpufreq_frequency_table_put_attr(policy->cpu);
- return 0;
-}
-
-static struct freq_attr *exynos4_cpufreq_attr[] = {
- &cpufreq_freq_attr_scaling_available_freqs,
- NULL,
-};
-
-static struct cpufreq_driver exynos4_driver = {
- .flags = CPUFREQ_STICKY,
- .verify = exynos4_verify_speed,
- .target = exynos4_target,
- .get = exynos4_getspeed,
- .init = exynos4_cpufreq_cpu_init,
- .exit = exynos4_cpufreq_cpu_exit,
- .name = "exynos4_cpufreq",
- .attr = exynos4_cpufreq_attr,
-#ifdef CONFIG_PM
- .suspend = exynos4_cpufreq_suspend,
- .resume = exynos4_cpufreq_resume,
-#endif
-};
+ int i;
+ unsigned int tmp;
+ unsigned long rate;
-static int __init exynos4_cpufreq_init(void)
-{
cpu_clk = clk_get(NULL, "armclk");
if (IS_ERR(cpu_clk))
return PTR_ERR(cpu_clk);
- locking_frequency = exynos4_getspeed(0);
-
moutcore = clk_get(NULL, "moutcore");
if (IS_ERR(moutcore))
- goto out;
+ goto err_moutcore;
mout_mpll = clk_get(NULL, "mout_mpll");
if (IS_ERR(mout_mpll))
- goto out;
+ goto err_mout_mpll;
+
+ rate = clk_get_rate(mout_mpll) / 1000;
mout_apll = clk_get(NULL, "mout_apll");
if (IS_ERR(mout_apll))
- goto out;
+ goto err_mout_apll;
- arm_regulator = regulator_get(NULL, "vdd_arm");
- if (IS_ERR(arm_regulator)) {
- printk(KERN_ERR "failed to get resource %s\n", "vdd_arm");
- goto out;
- }
+ tmp = __raw_readl(S5P_CLKDIV_CPU);
- int_regulator = regulator_get(NULL, "vdd_int");
- if (IS_ERR(int_regulator)) {
- printk(KERN_ERR "failed to get resource %s\n", "vdd_int");
- goto out;
+ for (i = L0; i < CPUFREQ_LEVEL_END; i++) {
+ tmp &= ~(S5P_CLKDIV_CPU0_CORE_MASK |
+ S5P_CLKDIV_CPU0_COREM0_MASK |
+ S5P_CLKDIV_CPU0_COREM1_MASK |
+ S5P_CLKDIV_CPU0_PERIPH_MASK |
+ S5P_CLKDIV_CPU0_ATB_MASK |
+ S5P_CLKDIV_CPU0_PCLKDBG_MASK |
+ S5P_CLKDIV_CPU0_APLL_MASK);
+
+ tmp |= ((clkdiv_cpu0[i][0] << S5P_CLKDIV_CPU0_CORE_SHIFT) |
+ (clkdiv_cpu0[i][1] << S5P_CLKDIV_CPU0_COREM0_SHIFT) |
+ (clkdiv_cpu0[i][2] << S5P_CLKDIV_CPU0_COREM1_SHIFT) |
+ (clkdiv_cpu0[i][3] << S5P_CLKDIV_CPU0_PERIPH_SHIFT) |
+ (clkdiv_cpu0[i][4] << S5P_CLKDIV_CPU0_ATB_SHIFT) |
+ (clkdiv_cpu0[i][5] << S5P_CLKDIV_CPU0_PCLKDBG_SHIFT) |
+ (clkdiv_cpu0[i][6] << S5P_CLKDIV_CPU0_APLL_SHIFT));
+
+ exynos4210_clkdiv_table[i].clkdiv = tmp;
}
- /*
- * Check DRAM type.
- * Because DVFS level is different according to DRAM type.
- */
- memtype = __raw_readl(S5P_VA_DMC0 + S5P_DMC0_MEMCON_OFFSET);
- memtype = (memtype >> S5P_DMC0_MEMTYPE_SHIFT);
- memtype &= S5P_DMC0_MEMTYPE_MASK;
-
- if ((memtype < DDR2) && (memtype > DDR3)) {
- printk(KERN_ERR "%s: wrong memtype= 0x%x\n", __func__, memtype);
- goto out;
- } else {
- printk(KERN_DEBUG "%s: memtype= 0x%x\n", __func__, memtype);
- }
-
- register_pm_notifier(&exynos4_cpufreq_nb);
-
- return cpufreq_register_driver(&exynos4_driver);
-
-out:
- if (!IS_ERR(cpu_clk))
- clk_put(cpu_clk);
+ info->mpll_freq_khz = rate;
+ info->pm_lock_idx = L2;
+ info->pll_safe_idx = L2;
+ info->max_support_idx = max_support_idx;
+ info->min_support_idx = min_support_idx;
+ info->cpu_clk = cpu_clk;
+ info->volt_table = exynos4210_volt_table;
+ info->freq_table = exynos4210_freq_table;
+ info->set_freq = exynos4210_set_frequency;
+ info->need_apll_change = exynos4210_pms_change;
- if (!IS_ERR(moutcore))
- clk_put(moutcore);
+ return 0;
+err_mout_apll:
if (!IS_ERR(mout_mpll))
clk_put(mout_mpll);
+err_mout_mpll:
+ if (!IS_ERR(moutcore))
+ clk_put(moutcore);
+err_moutcore:
+ if (!IS_ERR(cpu_clk))
+ clk_put(cpu_clk);
- if (!IS_ERR(mout_apll))
- clk_put(mout_apll);
-
- if (!IS_ERR(arm_regulator))
- regulator_put(arm_regulator);
-
- if (!IS_ERR(int_regulator))
- regulator_put(int_regulator);
-
- printk(KERN_ERR "%s: failed initialization\n", __func__);
-
+ pr_debug("%s: failed initialization\n", __func__);
return -EINVAL;
}
-late_initcall(exynos4_cpufreq_init);
+EXPORT_SYMBOL(exynos4210_cpufreq_init);
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
new file mode 100644
index 000000000000..5d04c57aae30
--- /dev/null
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -0,0 +1,274 @@
+/*
+ * CPU frequency scaling for OMAP using OPP information
+ *
+ * Copyright (C) 2005 Nokia Corporation
+ * Written by Tony Lindgren <tony@atomide.com>
+ *
+ * Based on cpu-sa1110.c, Copyright (C) 2001 Russell King
+ *
+ * Copyright (C) 2007-2011 Texas Instruments, Inc.
+ * - OMAP3/4 support by Rajendra Nayak, Santosh Shilimkar
+ *
+ * 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.
+ */
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/cpufreq.h>
+#include <linux/delay.h>
+#include <linux/init.h>
+#include <linux/err.h>
+#include <linux/clk.h>
+#include <linux/io.h>
+#include <linux/opp.h>
+#include <linux/cpu.h>
+#include <linux/module.h>
+
+#include <asm/system.h>
+#include <asm/smp_plat.h>
+#include <asm/cpu.h>
+
+#include <plat/clock.h>
+#include <plat/omap-pm.h>
+#include <plat/common.h>
+#include <plat/omap_device.h>
+
+#include <mach/hardware.h>
+
+#ifdef CONFIG_SMP
+struct lpj_info {
+ unsigned long ref;
+ unsigned int freq;
+};
+
+static DEFINE_PER_CPU(struct lpj_info, lpj_ref);
+static struct lpj_info global_lpj_ref;
+#endif
+
+static struct cpufreq_frequency_table *freq_table;
+static atomic_t freq_table_users = ATOMIC_INIT(0);
+static struct clk *mpu_clk;
+static char *mpu_clk_name;
+static struct device *mpu_dev;
+
+static int omap_verify_speed(struct cpufreq_policy *policy)
+{
+ if (!freq_table)
+ return -EINVAL;
+ return cpufreq_frequency_table_verify(policy, freq_table);
+}
+
+static unsigned int omap_getspeed(unsigned int cpu)
+{
+ unsigned long rate;
+
+ if (cpu >= NR_CPUS)
+ return 0;
+
+ rate = clk_get_rate(mpu_clk) / 1000;
+ return rate;
+}
+
+static int omap_target(struct cpufreq_policy *policy,
+ unsigned int target_freq,
+ unsigned int relation)
+{
+ unsigned int i;
+ int ret = 0;
+ struct cpufreq_freqs freqs;
+
+ if (!freq_table) {
+ dev_err(mpu_dev, "%s: cpu%d: no freq table!\n", __func__,
+ policy->cpu);
+ return -EINVAL;
+ }
+
+ ret = cpufreq_frequency_table_target(policy, freq_table, target_freq,
+ relation, &i);
+ if (ret) {
+ dev_dbg(mpu_dev, "%s: cpu%d: no freq match for %d(ret=%d)\n",
+ __func__, policy->cpu, target_freq, ret);
+ return ret;
+ }
+ freqs.new = freq_table[i].frequency;
+ if (!freqs.new) {
+ dev_err(mpu_dev, "%s: cpu%d: no match for freq %d\n", __func__,
+ policy->cpu, target_freq);
+ return -EINVAL;
+ }
+
+ freqs.old = omap_getspeed(policy->cpu);
+ freqs.cpu = policy->cpu;
+
+ if (freqs.old == freqs.new && policy->cur == freqs.new)
+ return ret;
+
+ /* notifiers */
+ for_each_cpu(i, policy->cpus) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
+ }
+
+#ifdef CONFIG_CPU_FREQ_DEBUG
+ pr_info("cpufreq-omap: transition: %u --> %u\n", freqs.old, freqs.new);
+#endif
+
+ ret = clk_set_rate(mpu_clk, freqs.new * 1000);
+ freqs.new = omap_getspeed(policy->cpu);
+
+#ifdef CONFIG_SMP
+ /*
+ * Note that loops_per_jiffy is not updated on SMP systems in
+ * cpufreq driver. So, update the per-CPU loops_per_jiffy value
+ * on frequency transition. We need to update all dependent CPUs.
+ */
+ for_each_cpu(i, policy->cpus) {
+ struct lpj_info *lpj = &per_cpu(lpj_ref, i);
+ if (!lpj->freq) {
+ lpj->ref = per_cpu(cpu_data, i).loops_per_jiffy;
+ lpj->freq = freqs.old;
+ }
+
+ per_cpu(cpu_data, i).loops_per_jiffy =
+ cpufreq_scale(lpj->ref, lpj->freq, freqs.new);
+ }
+
+ /* And don't forget to adjust the global one */
+ if (!global_lpj_ref.freq) {
+ global_lpj_ref.ref = loops_per_jiffy;
+ global_lpj_ref.freq = freqs.old;
+ }
+ loops_per_jiffy = cpufreq_scale(global_lpj_ref.ref, global_lpj_ref.freq,
+ freqs.new);
+#endif
+
+ /* notifiers */
+ for_each_cpu(i, policy->cpus) {
+ freqs.cpu = i;
+ cpufreq_notify_transition(&freqs, CPUFREQ_POSTCHANGE);
+ }
+
+ return ret;
+}
+
+static inline void freq_table_free(void)
+{
+ if (atomic_dec_and_test(&freq_table_users))
+ opp_free_cpufreq_table(mpu_dev, &freq_table);
+}
+
+static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
+{
+ int result = 0;
+
+ mpu_clk = clk_get(NULL, mpu_clk_name);
+ if (IS_ERR(mpu_clk))
+ return PTR_ERR(mpu_clk);
+
+ if (policy->cpu >= NR_CPUS) {
+ result = -EINVAL;
+ goto fail_ck;
+ }
+
+ policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
+
+ if (atomic_inc_return(&freq_table_users) == 1)
+ result = opp_init_cpufreq_table(mpu_dev, &freq_table);
+
+ if (result) {
+ dev_err(mpu_dev, "%s: cpu%d: failed creating freq table[%d]\n",
+ __func__, policy->cpu, result);
+ goto fail_ck;
+ }
+
+ result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
+ if (result)
+ goto fail_table;
+
+ cpufreq_frequency_table_get_attr(freq_table, policy->cpu);
+
+ policy->min = policy->cpuinfo.min_freq;
+ policy->max = policy->cpuinfo.max_freq;
+ policy->cur = omap_getspeed(policy->cpu);
+
+ /*
+ * On OMAP SMP configuartion, both processors share the voltage
+ * and clock. So both CPUs needs to be scaled together and hence
+ * needs software co-ordination. Use cpufreq affected_cpus
+ * interface to handle this scenario. Additional is_smp() check
+ * is to keep SMP_ON_UP build working.
+ */
+ if (is_smp()) {
+ policy->shared_type = CPUFREQ_SHARED_TYPE_ANY;
+ cpumask_setall(policy->cpus);
+ }
+
+ /* FIXME: what's the actual transition time? */
+ policy->cpuinfo.transition_latency = 300 * 1000;
+
+ return 0;
+
+fail_table:
+ freq_table_free();
+fail_ck:
+ clk_put(mpu_clk);
+ return result;
+}
+
+static int omap_cpu_exit(struct cpufreq_policy *policy)
+{
+ freq_table_free();
+ clk_put(mpu_clk);
+ return 0;
+}
+
+static struct freq_attr *omap_cpufreq_attr[] = {
+ &cpufreq_freq_attr_scaling_available_freqs,
+ NULL,
+};
+
+static struct cpufreq_driver omap_driver = {
+ .flags = CPUFREQ_STICKY,
+ .verify = omap_verify_speed,
+ .target = omap_target,
+ .get = omap_getspeed,
+ .init = omap_cpu_init,
+ .exit = omap_cpu_exit,
+ .name = "omap",
+ .attr = omap_cpufreq_attr,
+};
+
+static int __init omap_cpufreq_init(void)
+{
+ if (cpu_is_omap24xx())
+ mpu_clk_name = "virt_prcm_set";
+ else if (cpu_is_omap34xx())
+ mpu_clk_name = "dpll1_ck";
+ else if (cpu_is_omap44xx())
+ mpu_clk_name = "dpll_mpu_ck";
+
+ if (!mpu_clk_name) {
+ pr_err("%s: unsupported Silicon?\n", __func__);
+ return -EINVAL;
+ }
+
+ mpu_dev = omap_device_get_by_hwmod_name("mpu");
+ if (!mpu_dev) {
+ pr_warning("%s: unable to get the mpu device\n", __func__);
+ return -EINVAL;
+ }
+
+ return cpufreq_register_driver(&omap_driver);
+}
+
+static void __exit omap_cpufreq_exit(void)
+{
+ cpufreq_unregister_driver(&omap_driver);
+}
+
+MODULE_DESCRIPTION("cpufreq driver for OMAP SoCs");
+MODULE_LICENSE("GPL");
+module_init(omap_cpufreq_init);
+module_exit(omap_cpufreq_exit);
diff --git a/drivers/cpufreq/powernow-k8.c b/drivers/cpufreq/powernow-k8.c
index bce576d7478e..8f9b2ceeec85 100644
--- a/drivers/cpufreq/powernow-k8.c
+++ b/drivers/cpufreq/powernow-k8.c
@@ -1,10 +1,11 @@
/*
- * (c) 2003-2010 Advanced Micro Devices, Inc.
+ * (c) 2003-2012 Advanced Micro Devices, Inc.
* Your use of this code is subject to the terms and conditions of the
* GNU general public license version 2. See "COPYING" or
* http://www.gnu.org/licenses/gpl.html
*
- * Support : mark.langsdorf@amd.com
+ * Maintainer:
+ * Andreas Herrmann <andreas.herrmann3@amd.com>
*
* Based on the powernow-k7.c module written by Dave Jones.
* (C) 2003 Dave Jones on behalf of SuSE Labs
@@ -16,12 +17,14 @@
* Valuable input gratefully received from Dave Jones, Pavel Machek,
* Dominik Brodowski, Jacob Shin, and others.
* Originally developed by Paul Devriendt.
- * Processor information obtained from Chapter 9 (Power and Thermal Management)
- * of the "BIOS and Kernel Developer's Guide for the AMD Athlon 64 and AMD
- * Opteron Processors" available for download from www.amd.com
*
- * Tables for specific CPUs can be inferred from
- * http://www.amd.com/us-en/assets/content_type/white_papers_and_tech_docs/30430.pdf
+ * Processor information obtained from Chapter 9 (Power and Thermal
+ * Management) of the "BIOS and Kernel Developer's Guide (BKDG) for
+ * the AMD Athlon 64 and AMD Opteron Processors" and section "2.x
+ * Power Management" in BKDGs for newer AMD CPU families.
+ *
+ * Tables for specific CPUs can be inferred from AMD's processor
+ * power and thermal data sheets, (e.g. 30417.pdf, 30430.pdf, 43375.pdf)
*/
#include <linux/kernel.h>
@@ -54,6 +57,9 @@ static DEFINE_PER_CPU(struct powernow_k8_data *, powernow_data);
static int cpu_family = CPU_OPTERON;
+/* array to map SW pstate number to acpi state */
+static u32 ps_to_as[8];
+
/* core performance boost */
static bool cpb_capable, cpb_enabled;
static struct msr __percpu *msrs;
@@ -80,9 +86,9 @@ static u32 find_khz_freq_from_fid(u32 fid)
}
static u32 find_khz_freq_from_pstate(struct cpufreq_frequency_table *data,
- u32 pstate)
+ u32 pstate)
{
- return data[pstate].frequency;
+ return data[ps_to_as[pstate]].frequency;
}
/* Return the vco fid for an input fid
@@ -926,23 +932,27 @@ static int fill_powernow_table_pstate(struct powernow_k8_data *data,
invalidate_entry(powernow_table, i);
continue;
}
- rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
- if (!(hi & HW_PSTATE_VALID_MASK)) {
- pr_debug("invalid pstate %d, ignoring\n", index);
- invalidate_entry(powernow_table, i);
- continue;
- }
- powernow_table[i].index = index;
+ ps_to_as[index] = i;
/* Frequency may be rounded for these */
if ((boot_cpu_data.x86 == 0x10 && boot_cpu_data.x86_model < 10)
|| boot_cpu_data.x86 == 0x11) {
+
+ rdmsr(MSR_PSTATE_DEF_BASE + index, lo, hi);
+ if (!(hi & HW_PSTATE_VALID_MASK)) {
+ pr_debug("invalid pstate %d, ignoring\n", index);
+ invalidate_entry(powernow_table, i);
+ continue;
+ }
+
powernow_table[i].frequency =
freq_from_fid_did(lo & 0x3f, (lo >> 6) & 7);
} else
powernow_table[i].frequency =
data->acpi_data.states[i].core_frequency * 1000;
+
+ powernow_table[i].index = index;
}
return 0;
}
@@ -1189,7 +1199,8 @@ static int powernowk8_target(struct cpufreq_policy *pol,
powernow_k8_acpi_pst_values(data, newstate);
if (cpu_family == CPU_HW_PSTATE)
- ret = transition_frequency_pstate(data, newstate);
+ ret = transition_frequency_pstate(data,
+ data->powernow_table[newstate].index);
else
ret = transition_frequency_fidvid(data, newstate);
if (ret) {
@@ -1202,7 +1213,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
if (cpu_family == CPU_HW_PSTATE)
pol->cur = find_khz_freq_from_pstate(data->powernow_table,
- newstate);
+ data->powernow_table[newstate].index);
else
pol->cur = find_khz_freq_from_fid(data->currfid);
ret = 0;
diff --git a/drivers/cpufreq/s3c64xx-cpufreq.c b/drivers/cpufreq/s3c64xx-cpufreq.c
index 3475f65aeec6..a5e72cb5f53c 100644
--- a/drivers/cpufreq/s3c64xx-cpufreq.c
+++ b/drivers/cpufreq/s3c64xx-cpufreq.c
@@ -8,6 +8,8 @@
* published by the Free Software Foundation.
*/
+#define pr_fmt(fmt) "cpufreq: " fmt
+
#include <linux/kernel.h>
#include <linux/types.h>
#include <linux/init.h>
@@ -91,7 +93,7 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
if (freqs.old == freqs.new)
return 0;
- pr_debug("cpufreq: Transition %d-%dkHz\n", freqs.old, freqs.new);
+ pr_debug("Transition %d-%dkHz\n", freqs.old, freqs.new);
cpufreq_notify_transition(&freqs, CPUFREQ_PRECHANGE);
@@ -101,7 +103,7 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
dvfs->vddarm_min,
dvfs->vddarm_max);
if (ret != 0) {
- pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
+ pr_err("Failed to set VDDARM for %dkHz: %d\n",
freqs.new, ret);
goto err;
}
@@ -110,7 +112,7 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
ret = clk_set_rate(armclk, freqs.new * 1000);
if (ret < 0) {
- pr_err("cpufreq: Failed to set rate %dkHz: %d\n",
+ pr_err("Failed to set rate %dkHz: %d\n",
freqs.new, ret);
goto err;
}
@@ -123,14 +125,14 @@ static int s3c64xx_cpufreq_set_target(struct cpufreq_policy *policy,
dvfs->vddarm_min,
dvfs->vddarm_max);
if (ret != 0) {
- pr_err("cpufreq: Failed to set VDDARM for %dkHz: %d\n",
+ pr_err("Failed to set VDDARM for %dkHz: %d\n",
freqs.new, ret);
goto err_clk;
}
}
#endif
- pr_debug("cpufreq: Set actual frequency %lukHz\n",
+ pr_debug("Set actual frequency %lukHz\n",
clk_get_rate(armclk) / 1000);
return 0;
@@ -153,7 +155,7 @@ static void __init s3c64xx_cpufreq_config_regulator(void)
count = regulator_count_voltages(vddarm);
if (count < 0) {
- pr_err("cpufreq: Unable to check supported voltages\n");
+ pr_err("Unable to check supported voltages\n");
}
freq = s3c64xx_freq_table;
@@ -171,7 +173,7 @@ static void __init s3c64xx_cpufreq_config_regulator(void)
}
if (!found) {
- pr_debug("cpufreq: %dkHz unsupported by regulator\n",
+ pr_debug("%dkHz unsupported by regulator\n",
freq->frequency);
freq->frequency = CPUFREQ_ENTRY_INVALID;
}
@@ -194,13 +196,13 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
return -EINVAL;
if (s3c64xx_freq_table == NULL) {
- pr_err("cpufreq: No frequency information for this CPU\n");
+ pr_err("No frequency information for this CPU\n");
return -ENODEV;
}
armclk = clk_get(NULL, "armclk");
if (IS_ERR(armclk)) {
- pr_err("cpufreq: Unable to obtain ARMCLK: %ld\n",
+ pr_err("Unable to obtain ARMCLK: %ld\n",
PTR_ERR(armclk));
return PTR_ERR(armclk);
}
@@ -209,12 +211,19 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
vddarm = regulator_get(NULL, "vddarm");
if (IS_ERR(vddarm)) {
ret = PTR_ERR(vddarm);
- pr_err("cpufreq: Failed to obtain VDDARM: %d\n", ret);
- pr_err("cpufreq: Only frequency scaling available\n");
+ pr_err("Failed to obtain VDDARM: %d\n", ret);
+ pr_err("Only frequency scaling available\n");
vddarm = NULL;
} else {
s3c64xx_cpufreq_config_regulator();
}
+
+ vddint = regulator_get(NULL, "vddint");
+ if (IS_ERR(vddint)) {
+ ret = PTR_ERR(vddint);
+ pr_err("Failed to obtain VDDINT: %d\n", ret);
+ vddint = NULL;
+ }
#endif
freq = s3c64xx_freq_table;
@@ -225,7 +234,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
r = clk_round_rate(armclk, freq->frequency * 1000);
r /= 1000;
if (r != freq->frequency) {
- pr_debug("cpufreq: %dkHz unsupported by clock\n",
+ pr_debug("%dkHz unsupported by clock\n",
freq->frequency);
freq->frequency = CPUFREQ_ENTRY_INVALID;
}
@@ -248,7 +257,7 @@ static int s3c64xx_cpufreq_driver_init(struct cpufreq_policy *policy)
ret = cpufreq_frequency_table_cpuinfo(policy, s3c64xx_freq_table);
if (ret != 0) {
- pr_err("cpufreq: Failed to configure frequency table: %d\n",
+ pr_err("Failed to configure frequency table: %d\n",
ret);
regulator_put(vddarm);
clk_put(armclk);
diff --git a/drivers/crypto/amcc/crypto4xx_core.c b/drivers/crypto/amcc/crypto4xx_core.c
index 1d103f997dc2..13f8e1a14988 100644
--- a/drivers/crypto/amcc/crypto4xx_core.c
+++ b/drivers/crypto/amcc/crypto4xx_core.c
@@ -1292,18 +1292,7 @@ static struct platform_driver crypto4xx_driver = {
.remove = crypto4xx_remove,
};
-static int __init crypto4xx_init(void)
-{
- return platform_driver_register(&crypto4xx_driver);
-}
-
-static void __exit crypto4xx_exit(void)
-{
- platform_driver_unregister(&crypto4xx_driver);
-}
-
-module_init(crypto4xx_init);
-module_exit(crypto4xx_exit);
+module_platform_driver(crypto4xx_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("James Hsiao <jhsiao@amcc.com>");
diff --git a/drivers/crypto/caam/caamalg.c b/drivers/crypto/caam/caamalg.c
index 4159265b453b..e73cf2e8110a 100644
--- a/drivers/crypto/caam/caamalg.c
+++ b/drivers/crypto/caam/caamalg.c
@@ -113,7 +113,7 @@ static inline void append_dec_shr_done(u32 *desc)
jump_cmd = append_jump(desc, JUMP_CLASS_CLASS1 | JUMP_TEST_ALL);
set_jump_tgt_here(desc, jump_cmd);
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
}
/*
@@ -213,7 +213,7 @@ static void init_sh_desc_key_aead(u32 *desc, struct caam_ctx *ctx,
set_jump_tgt_here(desc, key_jump_cmd);
/* Propagate errors from shared to job descriptor */
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
}
static int aead_set_sh_desc(struct crypto_aead *aead)
@@ -310,7 +310,7 @@ static int aead_set_sh_desc(struct crypto_aead *aead)
/* Only propagate error immediately if shared */
jump_cmd = append_jump(desc, JUMP_TEST_ALL);
set_jump_tgt_here(desc, key_jump_cmd);
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
set_jump_tgt_here(desc, jump_cmd);
/* Class 2 operation */
@@ -683,7 +683,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
set_jump_tgt_here(desc, key_jump_cmd);
/* Propagate errors from shared to job descriptor */
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
/* Load iv */
append_cmd(desc, CMD_SEQ_LOAD | LDST_SRCDST_BYTE_CONTEXT |
@@ -724,7 +724,7 @@ static int ablkcipher_setkey(struct crypto_ablkcipher *ablkcipher,
/* For aead, only propagate error immediately if shared */
jump_cmd = append_jump(desc, JUMP_TEST_ALL);
set_jump_tgt_here(desc, key_jump_cmd);
- append_cmd(desc, SET_OK_PROP_ERRORS | CMD_LOAD);
+ append_cmd(desc, SET_OK_NO_PROP_ERRORS | CMD_LOAD);
set_jump_tgt_here(desc, jump_cmd);
/* load IV */
@@ -1806,6 +1806,25 @@ struct caam_alg_template {
static struct caam_alg_template driver_algs[] = {
/* single-pass ipsec_esp descriptor */
{
+ .name = "authenc(hmac(md5),cbc(aes))",
+ .driver_name = "authenc-hmac-md5-cbc-aes-caam",
+ .blocksize = AES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = AES_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_AES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha1),cbc(aes))",
.driver_name = "authenc-hmac-sha1-cbc-aes-caam",
.blocksize = AES_BLOCK_SIZE,
@@ -1865,6 +1884,25 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(md5),cbc(des3_ede))",
+ .driver_name = "authenc-hmac-md5-cbc-des3_ede-caam",
+ .blocksize = DES3_EDE_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES3_EDE_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_3DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha1),cbc(des3_ede))",
.driver_name = "authenc-hmac-sha1-cbc-des3_ede-caam",
.blocksize = DES3_EDE_BLOCK_SIZE,
@@ -1924,6 +1962,25 @@ static struct caam_alg_template driver_algs[] = {
.alg_op = OP_ALG_ALGSEL_SHA512 | OP_ALG_AAI_HMAC,
},
{
+ .name = "authenc(hmac(md5),cbc(des))",
+ .driver_name = "authenc-hmac-md5-cbc-des-caam",
+ .blocksize = DES_BLOCK_SIZE,
+ .type = CRYPTO_ALG_TYPE_AEAD,
+ .template_aead = {
+ .setkey = aead_setkey,
+ .setauthsize = aead_setauthsize,
+ .encrypt = aead_encrypt,
+ .decrypt = aead_decrypt,
+ .givencrypt = aead_givencrypt,
+ .geniv = "<built-in>",
+ .ivsize = DES_BLOCK_SIZE,
+ .maxauthsize = MD5_DIGEST_SIZE,
+ },
+ .class1_alg_type = OP_ALG_ALGSEL_DES | OP_ALG_AAI_CBC,
+ .class2_alg_type = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC_PRECOMP,
+ .alg_op = OP_ALG_ALGSEL_MD5 | OP_ALG_AAI_HMAC,
+ },
+ {
.name = "authenc(hmac(sha1),cbc(des))",
.driver_name = "authenc-hmac-sha1-cbc-des-caam",
.blocksize = DES_BLOCK_SIZE,
diff --git a/drivers/crypto/caam/compat.h b/drivers/crypto/caam/compat.h
index d38f2afaa966..a63bc65fae86 100644
--- a/drivers/crypto/caam/compat.h
+++ b/drivers/crypto/caam/compat.h
@@ -28,6 +28,7 @@
#include <crypto/aes.h>
#include <crypto/des.h>
#include <crypto/sha.h>
+#include <crypto/md5.h>
#include <crypto/aead.h>
#include <crypto/authenc.h>
#include <crypto/scatterwalk.h>
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 73988bb7322a..8ae3ba2a160d 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -52,8 +52,6 @@ static int caam_probe(struct platform_device *pdev)
struct caam_ctrl __iomem *ctrl;
struct caam_full __iomem *topregs;
struct caam_drv_private *ctrlpriv;
- struct caam_deco **deco;
- u32 deconum;
#ifdef CONFIG_DEBUG_FS
struct caam_perfmon *perfmon;
#endif
@@ -92,17 +90,6 @@ static int caam_probe(struct platform_device *pdev)
if (sizeof(dma_addr_t) == sizeof(u64))
dma_set_mask(dev, DMA_BIT_MASK(36));
- /* Find out how many DECOs are present */
- deconum = (rd_reg64(&topregs->ctrl.perfmon.cha_num) &
- CHA_NUM_DECONUM_MASK) >> CHA_NUM_DECONUM_SHIFT;
-
- ctrlpriv->deco = kmalloc(deconum * sizeof(struct caam_deco *),
- GFP_KERNEL);
-
- deco = (struct caam_deco __force **)&topregs->deco;
- for (d = 0; d < deconum; d++)
- ctrlpriv->deco[d] = deco[d];
-
/*
* Detect and enable JobRs
* First, find out how many ring spec'ed, allocate references
@@ -253,18 +240,7 @@ static struct platform_driver caam_driver = {
.remove = __devexit_p(caam_remove),
};
-static int __init caam_base_init(void)
-{
- return platform_driver_register(&caam_driver);
-}
-
-static void __exit caam_base_exit(void)
-{
- return platform_driver_unregister(&caam_driver);
-}
-
-module_init(caam_base_init);
-module_exit(caam_base_exit);
+module_platform_driver(caam_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("FSL CAAM request backend");
diff --git a/drivers/crypto/caam/desc.h b/drivers/crypto/caam/desc.h
index 974a75842da9..a17c2958dab1 100644
--- a/drivers/crypto/caam/desc.h
+++ b/drivers/crypto/caam/desc.h
@@ -9,7 +9,7 @@
#define DESC_H
/* Max size of any CAAM descriptor in 32-bit words, inclusive of header */
-#define MAX_CAAM_DESCSIZE 64
+#define MAX_CAAM_DESCSIZE 64
/* Block size of any entity covered/uncovered with a KEK/TKEK */
#define KEK_BLOCKSIZE 16
@@ -18,38 +18,38 @@
* Supported descriptor command types as they show up
* inside a descriptor command word.
*/
-#define CMD_SHIFT 27
-#define CMD_MASK 0xf8000000
-
-#define CMD_KEY (0x00 << CMD_SHIFT)
-#define CMD_SEQ_KEY (0x01 << CMD_SHIFT)
-#define CMD_LOAD (0x02 << CMD_SHIFT)
-#define CMD_SEQ_LOAD (0x03 << CMD_SHIFT)
-#define CMD_FIFO_LOAD (0x04 << CMD_SHIFT)
-#define CMD_SEQ_FIFO_LOAD (0x05 << CMD_SHIFT)
-#define CMD_STORE (0x0a << CMD_SHIFT)
-#define CMD_SEQ_STORE (0x0b << CMD_SHIFT)
-#define CMD_FIFO_STORE (0x0c << CMD_SHIFT)
-#define CMD_SEQ_FIFO_STORE (0x0d << CMD_SHIFT)
-#define CMD_MOVE_LEN (0x0e << CMD_SHIFT)
-#define CMD_MOVE (0x0f << CMD_SHIFT)
-#define CMD_OPERATION (0x10 << CMD_SHIFT)
-#define CMD_SIGNATURE (0x12 << CMD_SHIFT)
-#define CMD_JUMP (0x14 << CMD_SHIFT)
-#define CMD_MATH (0x15 << CMD_SHIFT)
-#define CMD_DESC_HDR (0x16 << CMD_SHIFT)
-#define CMD_SHARED_DESC_HDR (0x17 << CMD_SHIFT)
-#define CMD_SEQ_IN_PTR (0x1e << CMD_SHIFT)
-#define CMD_SEQ_OUT_PTR (0x1f << CMD_SHIFT)
+#define CMD_SHIFT 27
+#define CMD_MASK 0xf8000000
+
+#define CMD_KEY (0x00 << CMD_SHIFT)
+#define CMD_SEQ_KEY (0x01 << CMD_SHIFT)
+#define CMD_LOAD (0x02 << CMD_SHIFT)
+#define CMD_SEQ_LOAD (0x03 << CMD_SHIFT)
+#define CMD_FIFO_LOAD (0x04 << CMD_SHIFT)
+#define CMD_SEQ_FIFO_LOAD (0x05 << CMD_SHIFT)
+#define CMD_STORE (0x0a << CMD_SHIFT)
+#define CMD_SEQ_STORE (0x0b << CMD_SHIFT)
+#define CMD_FIFO_STORE (0x0c << CMD_SHIFT)
+#define CMD_SEQ_FIFO_STORE (0x0d << CMD_SHIFT)
+#define CMD_MOVE_LEN (0x0e << CMD_SHIFT)
+#define CMD_MOVE (0x0f << CMD_SHIFT)
+#define CMD_OPERATION (0x10 << CMD_SHIFT)
+#define CMD_SIGNATURE (0x12 << CMD_SHIFT)
+#define CMD_JUMP (0x14 << CMD_SHIFT)
+#define CMD_MATH (0x15 << CMD_SHIFT)
+#define CMD_DESC_HDR (0x16 << CMD_SHIFT)
+#define CMD_SHARED_DESC_HDR (0x17 << CMD_SHIFT)
+#define CMD_SEQ_IN_PTR (0x1e << CMD_SHIFT)
+#define CMD_SEQ_OUT_PTR (0x1f << CMD_SHIFT)
/* General-purpose class selector for all commands */
-#define CLASS_SHIFT 25
-#define CLASS_MASK (0x03 << CLASS_SHIFT)
+#define CLASS_SHIFT 25
+#define CLASS_MASK (0x03 << CLASS_SHIFT)
-#define CLASS_NONE (0x00 << CLASS_SHIFT)
-#define CLASS_1 (0x01 << CLASS_SHIFT)
-#define CLASS_2 (0x02 << CLASS_SHIFT)
-#define CLASS_BOTH (0x03 << CLASS_SHIFT)
+#define CLASS_NONE (0x00 << CLASS_SHIFT)
+#define CLASS_1 (0x01 << CLASS_SHIFT)
+#define CLASS_2 (0x02 << CLASS_SHIFT)
+#define CLASS_BOTH (0x03 << CLASS_SHIFT)
/*
* Descriptor header command constructs
@@ -60,82 +60,82 @@
* Do Not Run - marks a descriptor inexecutable if there was
* a preceding error somewhere
*/
-#define HDR_DNR 0x01000000
+#define HDR_DNR 0x01000000
/*
* ONE - should always be set. Combination of ONE (always
* set) and ZRO (always clear) forms an endianness sanity check
*/
-#define HDR_ONE 0x00800000
-#define HDR_ZRO 0x00008000
+#define HDR_ONE 0x00800000
+#define HDR_ZRO 0x00008000
/* Start Index or SharedDesc Length */
-#define HDR_START_IDX_MASK 0x3f
-#define HDR_START_IDX_SHIFT 16
+#define HDR_START_IDX_MASK 0x3f
+#define HDR_START_IDX_SHIFT 16
/* If shared descriptor header, 6-bit length */
-#define HDR_DESCLEN_SHR_MASK 0x3f
+#define HDR_DESCLEN_SHR_MASK 0x3f
/* If non-shared header, 7-bit length */
-#define HDR_DESCLEN_MASK 0x7f
+#define HDR_DESCLEN_MASK 0x7f
/* This is a TrustedDesc (if not SharedDesc) */
-#define HDR_TRUSTED 0x00004000
+#define HDR_TRUSTED 0x00004000
/* Make into TrustedDesc (if not SharedDesc) */
-#define HDR_MAKE_TRUSTED 0x00002000
+#define HDR_MAKE_TRUSTED 0x00002000
/* Save context if self-shared (if SharedDesc) */
-#define HDR_SAVECTX 0x00001000
+#define HDR_SAVECTX 0x00001000
/* Next item points to SharedDesc */
-#define HDR_SHARED 0x00001000
+#define HDR_SHARED 0x00001000
/*
* Reverse Execution Order - execute JobDesc first, then
* execute SharedDesc (normally SharedDesc goes first).
*/
-#define HDR_REVERSE 0x00000800
+#define HDR_REVERSE 0x00000800
/* Propogate DNR property to SharedDesc */
-#define HDR_PROP_DNR 0x00000800
+#define HDR_PROP_DNR 0x00000800
/* JobDesc/SharedDesc share property */
-#define HDR_SD_SHARE_MASK 0x03
-#define HDR_SD_SHARE_SHIFT 8
-#define HDR_JD_SHARE_MASK 0x07
-#define HDR_JD_SHARE_SHIFT 8
+#define HDR_SD_SHARE_MASK 0x03
+#define HDR_SD_SHARE_SHIFT 8
+#define HDR_JD_SHARE_MASK 0x07
+#define HDR_JD_SHARE_SHIFT 8
-#define HDR_SHARE_NEVER (0x00 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_WAIT (0x01 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_SERIAL (0x02 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_ALWAYS (0x03 << HDR_SD_SHARE_SHIFT)
-#define HDR_SHARE_DEFER (0x04 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_NEVER (0x00 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_WAIT (0x01 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_SERIAL (0x02 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_ALWAYS (0x03 << HDR_SD_SHARE_SHIFT)
+#define HDR_SHARE_DEFER (0x04 << HDR_SD_SHARE_SHIFT)
/* JobDesc/SharedDesc descriptor length */
-#define HDR_JD_LENGTH_MASK 0x7f
-#define HDR_SD_LENGTH_MASK 0x3f
+#define HDR_JD_LENGTH_MASK 0x7f
+#define HDR_SD_LENGTH_MASK 0x3f
/*
* KEY/SEQ_KEY Command Constructs
*/
-/* Key Destination Class: 01 = Class 1, 02 - Class 2 */
-#define KEY_DEST_CLASS_SHIFT 25 /* use CLASS_1 or CLASS_2 */
-#define KEY_DEST_CLASS_MASK (0x03 << KEY_DEST_CLASS_SHIFT)
+/* Key Destination Class: 01 = Class 1, 02 - Class 2 */
+#define KEY_DEST_CLASS_SHIFT 25 /* use CLASS_1 or CLASS_2 */
+#define KEY_DEST_CLASS_MASK (0x03 << KEY_DEST_CLASS_SHIFT)
/* Scatter-Gather Table/Variable Length Field */
-#define KEY_SGF 0x01000000
-#define KEY_VLF 0x01000000
+#define KEY_SGF 0x01000000
+#define KEY_VLF 0x01000000
/* Immediate - Key follows command in the descriptor */
-#define KEY_IMM 0x00800000
+#define KEY_IMM 0x00800000
/*
* Encrypted - Key is encrypted either with the KEK, or
* with the TDKEK if TK is set
*/
-#define KEY_ENC 0x00400000
+#define KEY_ENC 0x00400000
/*
* No Write Back - Do not allow key to be FIFO STOREd
@@ -156,16 +156,16 @@
* KDEST - Key Destination: 0 - class key register,
* 1 - PKHA 'e', 2 - AFHA Sbox, 3 - MDHA split-key
*/
-#define KEY_DEST_SHIFT 16
-#define KEY_DEST_MASK (0x03 << KEY_DEST_SHIFT)
+#define KEY_DEST_SHIFT 16
+#define KEY_DEST_MASK (0x03 << KEY_DEST_SHIFT)
-#define KEY_DEST_CLASS_REG (0x00 << KEY_DEST_SHIFT)
-#define KEY_DEST_PKHA_E (0x01 << KEY_DEST_SHIFT)
-#define KEY_DEST_AFHA_SBOX (0x02 << KEY_DEST_SHIFT)
-#define KEY_DEST_MDHA_SPLIT (0x03 << KEY_DEST_SHIFT)
+#define KEY_DEST_CLASS_REG (0x00 << KEY_DEST_SHIFT)
+#define KEY_DEST_PKHA_E (0x01 << KEY_DEST_SHIFT)
+#define KEY_DEST_AFHA_SBOX (0x02 << KEY_DEST_SHIFT)
+#define KEY_DEST_MDHA_SPLIT (0x03 << KEY_DEST_SHIFT)
/* Length in bytes */
-#define KEY_LENGTH_MASK 0x000003ff
+#define KEY_LENGTH_MASK 0x000003ff
/*
* LOAD/SEQ_LOAD/STORE/SEQ_STORE Command Constructs
@@ -175,25 +175,25 @@
* Load/Store Destination: 0 = class independent CCB,
* 1 = class 1 CCB, 2 = class 2 CCB, 3 = DECO
*/
-#define LDST_CLASS_SHIFT 25
-#define LDST_CLASS_MASK (0x03 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_IND_CCB (0x00 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_1_CCB (0x01 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_2_CCB (0x02 << LDST_CLASS_SHIFT)
-#define LDST_CLASS_DECO (0x03 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_SHIFT 25
+#define LDST_CLASS_MASK (0x03 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_IND_CCB (0x00 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_1_CCB (0x01 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_2_CCB (0x02 << LDST_CLASS_SHIFT)
+#define LDST_CLASS_DECO (0x03 << LDST_CLASS_SHIFT)
/* Scatter-Gather Table/Variable Length Field */
-#define LDST_SGF 0x01000000
+#define LDST_SGF 0x01000000
#define LDST_VLF LDST_SGF
-/* Immediate - Key follows this command in descriptor */
-#define LDST_IMM_MASK 1
-#define LDST_IMM_SHIFT 23
-#define LDST_IMM (LDST_IMM_MASK << LDST_IMM_SHIFT)
+/* Immediate - Key follows this command in descriptor */
+#define LDST_IMM_MASK 1
+#define LDST_IMM_SHIFT 23
+#define LDST_IMM (LDST_IMM_MASK << LDST_IMM_SHIFT)
-/* SRC/DST - Destination for LOAD, Source for STORE */
-#define LDST_SRCDST_SHIFT 16
-#define LDST_SRCDST_MASK (0x7f << LDST_SRCDST_SHIFT)
+/* SRC/DST - Destination for LOAD, Source for STORE */
+#define LDST_SRCDST_SHIFT 16
+#define LDST_SRCDST_MASK (0x7f << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_BYTE_CONTEXT (0x20 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_BYTE_KEY (0x40 << LDST_SRCDST_SHIFT)
@@ -205,64 +205,64 @@
#define LDST_SRCDST_WORD_DATASZ_REG (0x02 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_ICVSZ_REG (0x03 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_CHACTRL (0x06 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECOCTRL (0x06 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECOCTRL (0x06 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_IRQCTRL (0x07 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_PCLOVRD (0x07 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_PCLOVRD (0x07 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_CLRW (0x08 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH0 (0x08 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH0 (0x08 << LDST_SRCDST_SHIFT)
#define LDST_SRCDST_WORD_STAT (0x09 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH1 (0x09 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH2 (0x0a << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_AAD_SZ (0x0b << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DECO_MATH3 (0x0b << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_CLASS1_ICV_SZ (0x0c << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_ALTDS_CLASS1 (0x0f << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_A_SZ (0x10 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_B_SZ (0x11 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_N_SZ (0x12 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_PKHA_E_SZ (0x13 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_DESCBUF (0x40 << LDST_SRCDST_SHIFT)
-#define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT)
-
-/* Offset in source/destination */
-#define LDST_OFFSET_SHIFT 8
-#define LDST_OFFSET_MASK (0xff << LDST_OFFSET_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH1 (0x09 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH2 (0x0a << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_AAD_SZ (0x0b << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DECO_MATH3 (0x0b << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_CLASS1_ICV_SZ (0x0c << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_ALTDS_CLASS1 (0x0f << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_A_SZ (0x10 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_B_SZ (0x11 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_N_SZ (0x12 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_PKHA_E_SZ (0x13 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_DESCBUF (0x40 << LDST_SRCDST_SHIFT)
+#define LDST_SRCDST_WORD_INFO_FIFO (0x7a << LDST_SRCDST_SHIFT)
+
+/* Offset in source/destination */
+#define LDST_OFFSET_SHIFT 8
+#define LDST_OFFSET_MASK (0xff << LDST_OFFSET_SHIFT)
/* LDOFF definitions used when DST = LDST_SRCDST_WORD_DECOCTRL */
/* These could also be shifted by LDST_OFFSET_SHIFT - this reads better */
-#define LDOFF_CHG_SHARE_SHIFT 0
-#define LDOFF_CHG_SHARE_MASK (0x3 << LDOFF_CHG_SHARE_SHIFT)
-#define LDOFF_CHG_SHARE_NEVER (0x1 << LDOFF_CHG_SHARE_SHIFT)
-#define LDOFF_CHG_SHARE_OK_NO_PROP (0x2 << LDOFF_CHG_SHARE_SHIFT)
-#define LDOFF_CHG_SHARE_OK_PROP (0x3 << LDOFF_CHG_SHARE_SHIFT)
-
-#define LDOFF_ENABLE_AUTO_NFIFO (1 << 2)
-#define LDOFF_DISABLE_AUTO_NFIFO (1 << 3)
-
-#define LDOFF_CHG_NONSEQLIODN_SHIFT 4
-#define LDOFF_CHG_NONSEQLIODN_MASK (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-#define LDOFF_CHG_NONSEQLIODN_SEQ (0x1 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-#define LDOFF_CHG_NONSEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-#define LDOFF_CHG_NONSEQLIODN_TRUSTED (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
-
-#define LDOFF_CHG_SEQLIODN_SHIFT 6
-#define LDOFF_CHG_SEQLIODN_MASK (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
-#define LDOFF_CHG_SEQLIODN_SEQ (0x1 << LDOFF_CHG_SEQLIODN_SHIFT)
-#define LDOFF_CHG_SEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_SEQLIODN_SHIFT)
-#define LDOFF_CHG_SEQLIODN_TRUSTED (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
-
-/* Data length in bytes */
-#define LDST_LEN_SHIFT 0
-#define LDST_LEN_MASK (0xff << LDST_LEN_SHIFT)
+#define LDOFF_CHG_SHARE_SHIFT 0
+#define LDOFF_CHG_SHARE_MASK (0x3 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_NEVER (0x1 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_OK_PROP (0x2 << LDOFF_CHG_SHARE_SHIFT)
+#define LDOFF_CHG_SHARE_OK_NO_PROP (0x3 << LDOFF_CHG_SHARE_SHIFT)
+
+#define LDOFF_ENABLE_AUTO_NFIFO (1 << 2)
+#define LDOFF_DISABLE_AUTO_NFIFO (1 << 3)
+
+#define LDOFF_CHG_NONSEQLIODN_SHIFT 4
+#define LDOFF_CHG_NONSEQLIODN_MASK (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_SEQ (0x1 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+#define LDOFF_CHG_NONSEQLIODN_TRUSTED (0x3 << LDOFF_CHG_NONSEQLIODN_SHIFT)
+
+#define LDOFF_CHG_SEQLIODN_SHIFT 6
+#define LDOFF_CHG_SEQLIODN_MASK (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_SEQ (0x1 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_NON_SEQ (0x2 << LDOFF_CHG_SEQLIODN_SHIFT)
+#define LDOFF_CHG_SEQLIODN_TRUSTED (0x3 << LDOFF_CHG_SEQLIODN_SHIFT)
+
+/* Data length in bytes */
+#define LDST_LEN_SHIFT 0
+#define LDST_LEN_MASK (0xff << LDST_LEN_SHIFT)
/* Special Length definitions when dst=deco-ctrl */
-#define LDLEN_ENABLE_OSL_COUNT (1 << 7)
-#define LDLEN_RST_CHA_OFIFO_PTR (1 << 6)
-#define LDLEN_RST_OFIFO (1 << 5)
-#define LDLEN_SET_OFIFO_OFF_VALID (1 << 4)
-#define LDLEN_SET_OFIFO_OFF_RSVD (1 << 3)
-#define LDLEN_SET_OFIFO_OFFSET_SHIFT 0
-#define LDLEN_SET_OFIFO_OFFSET_MASK (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT)
+#define LDLEN_ENABLE_OSL_COUNT (1 << 7)
+#define LDLEN_RST_CHA_OFIFO_PTR (1 << 6)
+#define LDLEN_RST_OFIFO (1 << 5)
+#define LDLEN_SET_OFIFO_OFF_VALID (1 << 4)
+#define LDLEN_SET_OFIFO_OFF_RSVD (1 << 3)
+#define LDLEN_SET_OFIFO_OFFSET_SHIFT 0
+#define LDLEN_SET_OFIFO_OFFSET_MASK (3 << LDLEN_SET_OFIFO_OFFSET_SHIFT)
/*
* FIFO_LOAD/FIFO_STORE/SEQ_FIFO_LOAD/SEQ_FIFO_STORE
@@ -274,808 +274,808 @@
* 1 = Load for Class1, 2 = Load for Class2, 3 = Load both
* Store Source: 0 = normal, 1 = Class1key, 2 = Class2key
*/
-#define FIFOLD_CLASS_SHIFT 25
-#define FIFOLD_CLASS_MASK (0x03 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_SKIP (0x00 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_CLASS1 (0x01 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_CLASS2 (0x02 << FIFOLD_CLASS_SHIFT)
-#define FIFOLD_CLASS_BOTH (0x03 << FIFOLD_CLASS_SHIFT)
-
-#define FIFOST_CLASS_SHIFT 25
-#define FIFOST_CLASS_MASK (0x03 << FIFOST_CLASS_SHIFT)
-#define FIFOST_CLASS_NORMAL (0x00 << FIFOST_CLASS_SHIFT)
-#define FIFOST_CLASS_CLASS1KEY (0x01 << FIFOST_CLASS_SHIFT)
-#define FIFOST_CLASS_CLASS2KEY (0x02 << FIFOST_CLASS_SHIFT)
+#define FIFOLD_CLASS_SHIFT 25
+#define FIFOLD_CLASS_MASK (0x03 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_SKIP (0x00 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_CLASS1 (0x01 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_CLASS2 (0x02 << FIFOLD_CLASS_SHIFT)
+#define FIFOLD_CLASS_BOTH (0x03 << FIFOLD_CLASS_SHIFT)
+
+#define FIFOST_CLASS_SHIFT 25
+#define FIFOST_CLASS_MASK (0x03 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_NORMAL (0x00 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_CLASS1KEY (0x01 << FIFOST_CLASS_SHIFT)
+#define FIFOST_CLASS_CLASS2KEY (0x02 << FIFOST_CLASS_SHIFT)
/*
* Scatter-Gather Table/Variable Length Field
* If set for FIFO_LOAD, refers to a SG table. Within
* SEQ_FIFO_LOAD, is variable input sequence
*/
-#define FIFOLDST_SGF_SHIFT 24
-#define FIFOLDST_SGF_MASK (1 << FIFOLDST_SGF_SHIFT)
-#define FIFOLDST_VLF_MASK (1 << FIFOLDST_SGF_SHIFT)
-#define FIFOLDST_SGF (1 << FIFOLDST_SGF_SHIFT)
-#define FIFOLDST_VLF (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_SGF_SHIFT 24
+#define FIFOLDST_SGF_MASK (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_VLF_MASK (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_SGF (1 << FIFOLDST_SGF_SHIFT)
+#define FIFOLDST_VLF (1 << FIFOLDST_SGF_SHIFT)
/* Immediate - Data follows command in descriptor */
-#define FIFOLD_IMM_SHIFT 23
-#define FIFOLD_IMM_MASK (1 << FIFOLD_IMM_SHIFT)
-#define FIFOLD_IMM (1 << FIFOLD_IMM_SHIFT)
+#define FIFOLD_IMM_SHIFT 23
+#define FIFOLD_IMM_MASK (1 << FIFOLD_IMM_SHIFT)
+#define FIFOLD_IMM (1 << FIFOLD_IMM_SHIFT)
/* Continue - Not the last FIFO store to come */
-#define FIFOST_CONT_SHIFT 23
-#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
-#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
+#define FIFOST_CONT_SHIFT 23
+#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
+#define FIFOST_CONT_MASK (1 << FIFOST_CONT_SHIFT)
/*
* Extended Length - use 32-bit extended length that
* follows the pointer field. Illegal with IMM set
*/
-#define FIFOLDST_EXT_SHIFT 22
-#define FIFOLDST_EXT_MASK (1 << FIFOLDST_EXT_SHIFT)
-#define FIFOLDST_EXT (1 << FIFOLDST_EXT_SHIFT)
+#define FIFOLDST_EXT_SHIFT 22
+#define FIFOLDST_EXT_MASK (1 << FIFOLDST_EXT_SHIFT)
+#define FIFOLDST_EXT (1 << FIFOLDST_EXT_SHIFT)
/* Input data type.*/
-#define FIFOLD_TYPE_SHIFT 16
-#define FIFOLD_CONT_TYPE_SHIFT 19 /* shift past last-flush bits */
-#define FIFOLD_TYPE_MASK (0x3f << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_SHIFT 16
+#define FIFOLD_CONT_TYPE_SHIFT 19 /* shift past last-flush bits */
+#define FIFOLD_TYPE_MASK (0x3f << FIFOLD_TYPE_SHIFT)
/* PK types */
-#define FIFOLD_TYPE_PK (0x00 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_MASK (0x30 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_MASK (0x30 << FIFOLD_TYPE_SHIFT)
#define FIFOLD_TYPE_PK_TYPEMASK (0x0f << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A0 (0x00 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A1 (0x01 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A2 (0x02 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A3 (0x03 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B0 (0x04 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B1 (0x05 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B2 (0x06 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B3 (0x07 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_N (0x08 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_A (0x0c << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_PK_B (0x0d << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A0 (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A1 (0x01 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A2 (0x02 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A3 (0x03 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B0 (0x04 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B1 (0x05 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B2 (0x06 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B3 (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_N (0x08 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_A (0x0c << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_PK_B (0x0d << FIFOLD_TYPE_SHIFT)
/* Other types. Need to OR in last/flush bits as desired */
-#define FIFOLD_TYPE_MSG_MASK (0x38 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_MSG (0x10 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_MSG1OUT2 (0x18 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_IV (0x20 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_BITDATA (0x28 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_AAD (0x30 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_ICV (0x38 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG_MASK (0x38 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG (0x10 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_MSG1OUT2 (0x18 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_IV (0x20 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_BITDATA (0x28 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_AAD (0x30 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_ICV (0x38 << FIFOLD_TYPE_SHIFT)
/* Last/Flush bits for use with "other" types above */
-#define FIFOLD_TYPE_ACT_MASK (0x07 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_NOACTION (0x00 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_FLUSH1 (0x01 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LAST1 (0x02 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LAST2FLUSH (0x03 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LAST2 (0x04 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_ACT_MASK (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_NOACTION (0x00 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_FLUSH1 (0x01 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST1 (0x02 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST2FLUSH (0x03 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LAST2 (0x04 << FIFOLD_TYPE_SHIFT)
#define FIFOLD_TYPE_LAST2FLUSH1 (0x05 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LASTBOTH (0x06 << FIFOLD_TYPE_SHIFT)
-#define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LASTBOTH (0x06 << FIFOLD_TYPE_SHIFT)
+#define FIFOLD_TYPE_LASTBOTHFL (0x07 << FIFOLD_TYPE_SHIFT)
-#define FIFOLDST_LEN_MASK 0xffff
-#define FIFOLDST_EXT_LEN_MASK 0xffffffff
+#define FIFOLDST_LEN_MASK 0xffff
+#define FIFOLDST_EXT_LEN_MASK 0xffffffff
/* Output data types */
-#define FIFOST_TYPE_SHIFT 16
-#define FIFOST_TYPE_MASK (0x3f << FIFOST_TYPE_SHIFT)
-
-#define FIFOST_TYPE_PKHA_A0 (0x00 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A1 (0x01 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A2 (0x02 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A3 (0x03 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B0 (0x04 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B1 (0x05 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B2 (0x06 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B3 (0x07 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_N (0x08 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_A (0x0c << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_B (0x0d << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SHIFT 16
+#define FIFOST_TYPE_MASK (0x3f << FIFOST_TYPE_SHIFT)
+
+#define FIFOST_TYPE_PKHA_A0 (0x00 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A1 (0x01 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A2 (0x02 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A3 (0x03 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B0 (0x04 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B1 (0x05 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B2 (0x06 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B3 (0x07 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_N (0x08 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_A (0x0c << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_B (0x0d << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_AF_SBOX_JKEK (0x10 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_AF_SBOX_TKEK (0x21 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_E_JKEK (0x22 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_PKHA_E_TKEK (0x23 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_KEY_KEK (0x24 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_KEY_TKEK (0x25 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_SPLIT_KEK (0x26 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_SPLIT_TKEK (0x27 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_OUTFIFO_KEK (0x28 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_E_JKEK (0x22 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_PKHA_E_TKEK (0x23 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_KEY_KEK (0x24 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_KEY_TKEK (0x25 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SPLIT_KEK (0x26 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SPLIT_TKEK (0x27 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_OUTFIFO_KEK (0x28 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_OUTFIFO_TKEK (0x29 << FIFOST_TYPE_SHIFT)
#define FIFOST_TYPE_MESSAGE_DATA (0x30 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_RNGSTORE (0x34 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_RNGFIFO (0x35 << FIFOST_TYPE_SHIFT)
-#define FIFOST_TYPE_SKIP (0x3f << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_RNGSTORE (0x34 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_RNGFIFO (0x35 << FIFOST_TYPE_SHIFT)
+#define FIFOST_TYPE_SKIP (0x3f << FIFOST_TYPE_SHIFT)
/*
* OPERATION Command Constructs
*/
/* Operation type selectors - OP TYPE */
-#define OP_TYPE_SHIFT 24
-#define OP_TYPE_MASK (0x07 << OP_TYPE_SHIFT)
+#define OP_TYPE_SHIFT 24
+#define OP_TYPE_MASK (0x07 << OP_TYPE_SHIFT)
-#define OP_TYPE_UNI_PROTOCOL (0x00 << OP_TYPE_SHIFT)
-#define OP_TYPE_PK (0x01 << OP_TYPE_SHIFT)
-#define OP_TYPE_CLASS1_ALG (0x02 << OP_TYPE_SHIFT)
-#define OP_TYPE_CLASS2_ALG (0x04 << OP_TYPE_SHIFT)
-#define OP_TYPE_DECAP_PROTOCOL (0x06 << OP_TYPE_SHIFT)
-#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT)
+#define OP_TYPE_UNI_PROTOCOL (0x00 << OP_TYPE_SHIFT)
+#define OP_TYPE_PK (0x01 << OP_TYPE_SHIFT)
+#define OP_TYPE_CLASS1_ALG (0x02 << OP_TYPE_SHIFT)
+#define OP_TYPE_CLASS2_ALG (0x04 << OP_TYPE_SHIFT)
+#define OP_TYPE_DECAP_PROTOCOL (0x06 << OP_TYPE_SHIFT)
+#define OP_TYPE_ENCAP_PROTOCOL (0x07 << OP_TYPE_SHIFT)
/* ProtocolID selectors - PROTID */
-#define OP_PCLID_SHIFT 16
-#define OP_PCLID_MASK (0xff << 16)
+#define OP_PCLID_SHIFT 16
+#define OP_PCLID_MASK (0xff << 16)
/* Assuming OP_TYPE = OP_TYPE_UNI_PROTOCOL */
-#define OP_PCLID_IKEV1_PRF (0x01 << OP_PCLID_SHIFT)
-#define OP_PCLID_IKEV2_PRF (0x02 << OP_PCLID_SHIFT)
-#define OP_PCLID_SSL30_PRF (0x08 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS10_PRF (0x09 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS11_PRF (0x0a << OP_PCLID_SHIFT)
-#define OP_PCLID_DTLS10_PRF (0x0c << OP_PCLID_SHIFT)
-#define OP_PCLID_PRF (0x06 << OP_PCLID_SHIFT)
-#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT)
-#define OP_PCLID_SECRETKEY (0x11 << OP_PCLID_SHIFT)
-#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
-#define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT)
-#define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT)
+#define OP_PCLID_IKEV1_PRF (0x01 << OP_PCLID_SHIFT)
+#define OP_PCLID_IKEV2_PRF (0x02 << OP_PCLID_SHIFT)
+#define OP_PCLID_SSL30_PRF (0x08 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS10_PRF (0x09 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS11_PRF (0x0a << OP_PCLID_SHIFT)
+#define OP_PCLID_DTLS10_PRF (0x0c << OP_PCLID_SHIFT)
+#define OP_PCLID_PRF (0x06 << OP_PCLID_SHIFT)
+#define OP_PCLID_BLOB (0x0d << OP_PCLID_SHIFT)
+#define OP_PCLID_SECRETKEY (0x11 << OP_PCLID_SHIFT)
+#define OP_PCLID_PUBLICKEYPAIR (0x14 << OP_PCLID_SHIFT)
+#define OP_PCLID_DSASIGN (0x15 << OP_PCLID_SHIFT)
+#define OP_PCLID_DSAVERIFY (0x16 << OP_PCLID_SHIFT)
/* Assuming OP_TYPE = OP_TYPE_DECAP_PROTOCOL/ENCAP_PROTOCOL */
-#define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT)
-#define OP_PCLID_SRTP (0x02 << OP_PCLID_SHIFT)
-#define OP_PCLID_MACSEC (0x03 << OP_PCLID_SHIFT)
-#define OP_PCLID_WIFI (0x04 << OP_PCLID_SHIFT)
-#define OP_PCLID_WIMAX (0x05 << OP_PCLID_SHIFT)
-#define OP_PCLID_SSL30 (0x08 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS10 (0x09 << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS11 (0x0a << OP_PCLID_SHIFT)
-#define OP_PCLID_TLS12 (0x0b << OP_PCLID_SHIFT)
-#define OP_PCLID_DTLS (0x0c << OP_PCLID_SHIFT)
+#define OP_PCLID_IPSEC (0x01 << OP_PCLID_SHIFT)
+#define OP_PCLID_SRTP (0x02 << OP_PCLID_SHIFT)
+#define OP_PCLID_MACSEC (0x03 << OP_PCLID_SHIFT)
+#define OP_PCLID_WIFI (0x04 << OP_PCLID_SHIFT)
+#define OP_PCLID_WIMAX (0x05 << OP_PCLID_SHIFT)
+#define OP_PCLID_SSL30 (0x08 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS10 (0x09 << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS11 (0x0a << OP_PCLID_SHIFT)
+#define OP_PCLID_TLS12 (0x0b << OP_PCLID_SHIFT)
+#define OP_PCLID_DTLS (0x0c << OP_PCLID_SHIFT)
/*
* ProtocolInfo selectors
*/
-#define OP_PCLINFO_MASK 0xffff
+#define OP_PCLINFO_MASK 0xffff
/* for OP_PCLID_IPSEC */
-#define OP_PCL_IPSEC_CIPHER_MASK 0xff00
-#define OP_PCL_IPSEC_AUTH_MASK 0x00ff
-
-#define OP_PCL_IPSEC_DES_IV64 0x0100
-#define OP_PCL_IPSEC_DES 0x0200
-#define OP_PCL_IPSEC_3DES 0x0300
-#define OP_PCL_IPSEC_AES_CBC 0x0c00
-#define OP_PCL_IPSEC_AES_CTR 0x0d00
-#define OP_PCL_IPSEC_AES_XTS 0x1600
-#define OP_PCL_IPSEC_AES_CCM8 0x0e00
-#define OP_PCL_IPSEC_AES_CCM12 0x0f00
-#define OP_PCL_IPSEC_AES_CCM16 0x1000
-#define OP_PCL_IPSEC_AES_GCM8 0x1200
-#define OP_PCL_IPSEC_AES_GCM12 0x1300
-#define OP_PCL_IPSEC_AES_GCM16 0x1400
-
-#define OP_PCL_IPSEC_HMAC_NULL 0x0000
-#define OP_PCL_IPSEC_HMAC_MD5_96 0x0001
-#define OP_PCL_IPSEC_HMAC_SHA1_96 0x0002
-#define OP_PCL_IPSEC_AES_XCBC_MAC_96 0x0005
-#define OP_PCL_IPSEC_HMAC_MD5_128 0x0006
-#define OP_PCL_IPSEC_HMAC_SHA1_160 0x0007
-#define OP_PCL_IPSEC_HMAC_SHA2_256_128 0x000c
-#define OP_PCL_IPSEC_HMAC_SHA2_384_192 0x000d
-#define OP_PCL_IPSEC_HMAC_SHA2_512_256 0x000e
+#define OP_PCL_IPSEC_CIPHER_MASK 0xff00
+#define OP_PCL_IPSEC_AUTH_MASK 0x00ff
+
+#define OP_PCL_IPSEC_DES_IV64 0x0100
+#define OP_PCL_IPSEC_DES 0x0200
+#define OP_PCL_IPSEC_3DES 0x0300
+#define OP_PCL_IPSEC_AES_CBC 0x0c00
+#define OP_PCL_IPSEC_AES_CTR 0x0d00
+#define OP_PCL_IPSEC_AES_XTS 0x1600
+#define OP_PCL_IPSEC_AES_CCM8 0x0e00
+#define OP_PCL_IPSEC_AES_CCM12 0x0f00
+#define OP_PCL_IPSEC_AES_CCM16 0x1000
+#define OP_PCL_IPSEC_AES_GCM8 0x1200
+#define OP_PCL_IPSEC_AES_GCM12 0x1300
+#define OP_PCL_IPSEC_AES_GCM16 0x1400
+
+#define OP_PCL_IPSEC_HMAC_NULL 0x0000
+#define OP_PCL_IPSEC_HMAC_MD5_96 0x0001
+#define OP_PCL_IPSEC_HMAC_SHA1_96 0x0002
+#define OP_PCL_IPSEC_AES_XCBC_MAC_96 0x0005
+#define OP_PCL_IPSEC_HMAC_MD5_128 0x0006
+#define OP_PCL_IPSEC_HMAC_SHA1_160 0x0007
+#define OP_PCL_IPSEC_HMAC_SHA2_256_128 0x000c
+#define OP_PCL_IPSEC_HMAC_SHA2_384_192 0x000d
+#define OP_PCL_IPSEC_HMAC_SHA2_512_256 0x000e
/* For SRTP - OP_PCLID_SRTP */
-#define OP_PCL_SRTP_CIPHER_MASK 0xff00
-#define OP_PCL_SRTP_AUTH_MASK 0x00ff
+#define OP_PCL_SRTP_CIPHER_MASK 0xff00
+#define OP_PCL_SRTP_AUTH_MASK 0x00ff
-#define OP_PCL_SRTP_AES_CTR 0x0d00
+#define OP_PCL_SRTP_AES_CTR 0x0d00
-#define OP_PCL_SRTP_HMAC_SHA1_160 0x0007
+#define OP_PCL_SRTP_HMAC_SHA1_160 0x0007
/* For SSL 3.0 - OP_PCLID_SSL30 */
-#define OP_PCL_SSL30_AES_128_CBC_SHA 0x002f
-#define OP_PCL_SSL30_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_SSL30_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_SSL30_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_SSL30_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_SSL30_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_SSL30_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_SSL30_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_SSL30_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_SSL30_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_SSL30_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_SSL30_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_SSL30_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_SSL30_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_SSL30_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_SSL30_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_SSL30_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_SSL30_AES_256_CBC_SHA 0x0035
-#define OP_PCL_SSL30_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_SSL30_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_SSL30_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_SSL30_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_SSL30_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_SSL30_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_SSL30_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_SSL30_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_SSL30_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_SSL30_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_SSL30_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_SSL30_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_SSL30_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_SSL30_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_SSL30_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_SSL30_AES_256_CBC_SHA_17 0xc022
-
-#define OP_PCL_SSL30_3DES_EDE_CBC_MD5 0x0023
-
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_SSL30_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_SSL30_DES_CBC_MD5 0x0022
-
-#define OP_PCL_SSL30_DES40_CBC_SHA 0x0008
-#define OP_PCL_SSL30_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_SSL30_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_SSL30_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_SSL30_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_SSL30_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_SSL30_DES40_CBC_SHA_7 0x0026
-
-#define OP_PCL_SSL30_DES_CBC_SHA 0x001e
-#define OP_PCL_SSL30_DES_CBC_SHA_2 0x0009
-#define OP_PCL_SSL30_DES_CBC_SHA_3 0x000c
-#define OP_PCL_SSL30_DES_CBC_SHA_4 0x000f
-#define OP_PCL_SSL30_DES_CBC_SHA_5 0x0012
-#define OP_PCL_SSL30_DES_CBC_SHA_6 0x0015
-#define OP_PCL_SSL30_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_SSL30_RC4_128_MD5 0x0024
-#define OP_PCL_SSL30_RC4_128_MD5_2 0x0004
-#define OP_PCL_SSL30_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_SSL30_RC4_40_MD5 0x002b
-#define OP_PCL_SSL30_RC4_40_MD5_2 0x0003
-#define OP_PCL_SSL30_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_SSL30_RC4_128_SHA 0x0020
-#define OP_PCL_SSL30_RC4_128_SHA_2 0x008a
-#define OP_PCL_SSL30_RC4_128_SHA_3 0x008e
-#define OP_PCL_SSL30_RC4_128_SHA_4 0x0092
-#define OP_PCL_SSL30_RC4_128_SHA_5 0x0005
-#define OP_PCL_SSL30_RC4_128_SHA_6 0xc002
-#define OP_PCL_SSL30_RC4_128_SHA_7 0xc007
-#define OP_PCL_SSL30_RC4_128_SHA_8 0xc00c
-#define OP_PCL_SSL30_RC4_128_SHA_9 0xc011
-#define OP_PCL_SSL30_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_SSL30_RC4_40_SHA 0x0028
+#define OP_PCL_SSL30_AES_128_CBC_SHA 0x002f
+#define OP_PCL_SSL30_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_SSL30_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_SSL30_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_SSL30_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_SSL30_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_SSL30_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_SSL30_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_SSL30_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_SSL30_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_SSL30_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_SSL30_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_SSL30_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_SSL30_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_SSL30_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_SSL30_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_SSL30_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_SSL30_AES_256_CBC_SHA 0x0035
+#define OP_PCL_SSL30_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_SSL30_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_SSL30_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_SSL30_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_SSL30_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_SSL30_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_SSL30_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_SSL30_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_SSL30_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_SSL30_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_SSL30_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_SSL30_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_SSL30_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_SSL30_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_SSL30_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_SSL30_AES_256_CBC_SHA_17 0xc022
+
+#define OP_PCL_SSL30_3DES_EDE_CBC_MD5 0x0023
+
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_SSL30_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_SSL30_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_SSL30_DES_CBC_MD5 0x0022
+
+#define OP_PCL_SSL30_DES40_CBC_SHA 0x0008
+#define OP_PCL_SSL30_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_SSL30_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_SSL30_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_SSL30_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_SSL30_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_SSL30_DES40_CBC_SHA_7 0x0026
+
+#define OP_PCL_SSL30_DES_CBC_SHA 0x001e
+#define OP_PCL_SSL30_DES_CBC_SHA_2 0x0009
+#define OP_PCL_SSL30_DES_CBC_SHA_3 0x000c
+#define OP_PCL_SSL30_DES_CBC_SHA_4 0x000f
+#define OP_PCL_SSL30_DES_CBC_SHA_5 0x0012
+#define OP_PCL_SSL30_DES_CBC_SHA_6 0x0015
+#define OP_PCL_SSL30_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_SSL30_RC4_128_MD5 0x0024
+#define OP_PCL_SSL30_RC4_128_MD5_2 0x0004
+#define OP_PCL_SSL30_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_SSL30_RC4_40_MD5 0x002b
+#define OP_PCL_SSL30_RC4_40_MD5_2 0x0003
+#define OP_PCL_SSL30_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_SSL30_RC4_128_SHA 0x0020
+#define OP_PCL_SSL30_RC4_128_SHA_2 0x008a
+#define OP_PCL_SSL30_RC4_128_SHA_3 0x008e
+#define OP_PCL_SSL30_RC4_128_SHA_4 0x0092
+#define OP_PCL_SSL30_RC4_128_SHA_5 0x0005
+#define OP_PCL_SSL30_RC4_128_SHA_6 0xc002
+#define OP_PCL_SSL30_RC4_128_SHA_7 0xc007
+#define OP_PCL_SSL30_RC4_128_SHA_8 0xc00c
+#define OP_PCL_SSL30_RC4_128_SHA_9 0xc011
+#define OP_PCL_SSL30_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_SSL30_RC4_40_SHA 0x0028
/* For TLS 1.0 - OP_PCLID_TLS10 */
-#define OP_PCL_TLS10_AES_128_CBC_SHA 0x002f
-#define OP_PCL_TLS10_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_TLS10_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_TLS10_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_TLS10_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_TLS10_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_TLS10_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_TLS10_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_TLS10_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_TLS10_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_TLS10_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_TLS10_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_TLS10_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_TLS10_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_TLS10_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_TLS10_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_TLS10_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_TLS10_AES_256_CBC_SHA 0x0035
-#define OP_PCL_TLS10_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_TLS10_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_TLS10_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_TLS10_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_TLS10_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_TLS10_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_TLS10_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_TLS10_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_TLS10_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_TLS10_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_TLS10_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_TLS10_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_TLS10_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_TLS10_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_TLS10_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_TLS10_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_TLS10_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_TLS10_DES_CBC_MD5 0x0022
-
-#define OP_PCL_TLS10_DES40_CBC_SHA 0x0008
-#define OP_PCL_TLS10_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_TLS10_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_TLS10_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_TLS10_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_TLS10_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_TLS10_DES40_CBC_SHA_7 0x0026
-
-
-#define OP_PCL_TLS10_DES_CBC_SHA 0x001e
-#define OP_PCL_TLS10_DES_CBC_SHA_2 0x0009
-#define OP_PCL_TLS10_DES_CBC_SHA_3 0x000c
-#define OP_PCL_TLS10_DES_CBC_SHA_4 0x000f
-#define OP_PCL_TLS10_DES_CBC_SHA_5 0x0012
-#define OP_PCL_TLS10_DES_CBC_SHA_6 0x0015
-#define OP_PCL_TLS10_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_TLS10_RC4_128_MD5 0x0024
-#define OP_PCL_TLS10_RC4_128_MD5_2 0x0004
-#define OP_PCL_TLS10_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_TLS10_RC4_40_MD5 0x002b
-#define OP_PCL_TLS10_RC4_40_MD5_2 0x0003
-#define OP_PCL_TLS10_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_TLS10_RC4_128_SHA 0x0020
-#define OP_PCL_TLS10_RC4_128_SHA_2 0x008a
-#define OP_PCL_TLS10_RC4_128_SHA_3 0x008e
-#define OP_PCL_TLS10_RC4_128_SHA_4 0x0092
-#define OP_PCL_TLS10_RC4_128_SHA_5 0x0005
-#define OP_PCL_TLS10_RC4_128_SHA_6 0xc002
-#define OP_PCL_TLS10_RC4_128_SHA_7 0xc007
-#define OP_PCL_TLS10_RC4_128_SHA_8 0xc00c
-#define OP_PCL_TLS10_RC4_128_SHA_9 0xc011
-#define OP_PCL_TLS10_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_TLS10_RC4_40_SHA 0x0028
-
-#define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_TLS10_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_TLS10_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_TLS10_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_TLS10_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_TLS10_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_TLS10_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_TLS10_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_TLS10_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_TLS10_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_TLS10_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_TLS10_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_TLS10_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_TLS10_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_TLS10_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_TLS10_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_TLS10_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_TLS10_AES_128_CBC_SHA 0x002f
+#define OP_PCL_TLS10_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_TLS10_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_TLS10_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_TLS10_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_TLS10_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_TLS10_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_TLS10_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_TLS10_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_TLS10_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_TLS10_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_TLS10_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_TLS10_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_TLS10_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_TLS10_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_TLS10_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_TLS10_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_TLS10_AES_256_CBC_SHA 0x0035
+#define OP_PCL_TLS10_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_TLS10_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_TLS10_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_TLS10_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_TLS10_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_TLS10_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_TLS10_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_TLS10_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_TLS10_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_TLS10_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_TLS10_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_TLS10_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_TLS10_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_TLS10_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_TLS10_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_TLS10_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_TLS10_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_TLS10_DES_CBC_MD5 0x0022
+
+#define OP_PCL_TLS10_DES40_CBC_SHA 0x0008
+#define OP_PCL_TLS10_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_TLS10_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_TLS10_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_TLS10_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_TLS10_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_TLS10_DES40_CBC_SHA_7 0x0026
+
+
+#define OP_PCL_TLS10_DES_CBC_SHA 0x001e
+#define OP_PCL_TLS10_DES_CBC_SHA_2 0x0009
+#define OP_PCL_TLS10_DES_CBC_SHA_3 0x000c
+#define OP_PCL_TLS10_DES_CBC_SHA_4 0x000f
+#define OP_PCL_TLS10_DES_CBC_SHA_5 0x0012
+#define OP_PCL_TLS10_DES_CBC_SHA_6 0x0015
+#define OP_PCL_TLS10_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_TLS10_RC4_128_MD5 0x0024
+#define OP_PCL_TLS10_RC4_128_MD5_2 0x0004
+#define OP_PCL_TLS10_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_TLS10_RC4_40_MD5 0x002b
+#define OP_PCL_TLS10_RC4_40_MD5_2 0x0003
+#define OP_PCL_TLS10_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_TLS10_RC4_128_SHA 0x0020
+#define OP_PCL_TLS10_RC4_128_SHA_2 0x008a
+#define OP_PCL_TLS10_RC4_128_SHA_3 0x008e
+#define OP_PCL_TLS10_RC4_128_SHA_4 0x0092
+#define OP_PCL_TLS10_RC4_128_SHA_5 0x0005
+#define OP_PCL_TLS10_RC4_128_SHA_6 0xc002
+#define OP_PCL_TLS10_RC4_128_SHA_7 0xc007
+#define OP_PCL_TLS10_RC4_128_SHA_8 0xc00c
+#define OP_PCL_TLS10_RC4_128_SHA_9 0xc011
+#define OP_PCL_TLS10_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_TLS10_RC4_40_SHA 0x0028
+
+#define OP_PCL_TLS10_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_TLS10_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_TLS10_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_TLS10_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_TLS10_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_TLS10_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_TLS10_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_TLS10_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_TLS10_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_TLS10_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_TLS10_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_TLS10_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_TLS10_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_TLS10_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_TLS10_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_TLS10_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_TLS10_AES_256_CBC_SHA512 0xff65
/* For TLS 1.1 - OP_PCLID_TLS11 */
-#define OP_PCL_TLS11_AES_128_CBC_SHA 0x002f
-#define OP_PCL_TLS11_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_TLS11_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_TLS11_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_TLS11_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_TLS11_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_TLS11_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_TLS11_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_TLS11_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_TLS11_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_TLS11_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_TLS11_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_TLS11_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_TLS11_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_TLS11_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_TLS11_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_TLS11_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_TLS11_AES_256_CBC_SHA 0x0035
-#define OP_PCL_TLS11_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_TLS11_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_TLS11_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_TLS11_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_TLS11_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_TLS11_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_TLS11_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_TLS11_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_TLS11_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_TLS11_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_TLS11_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_TLS11_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_TLS11_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_TLS11_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_TLS11_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_TLS11_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_TLS11_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_TLS11_DES_CBC_MD5 0x0022
-
-#define OP_PCL_TLS11_DES40_CBC_SHA 0x0008
-#define OP_PCL_TLS11_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_TLS11_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_TLS11_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_TLS11_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_TLS11_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_TLS11_DES40_CBC_SHA_7 0x0026
-
-#define OP_PCL_TLS11_DES_CBC_SHA 0x001e
-#define OP_PCL_TLS11_DES_CBC_SHA_2 0x0009
-#define OP_PCL_TLS11_DES_CBC_SHA_3 0x000c
-#define OP_PCL_TLS11_DES_CBC_SHA_4 0x000f
-#define OP_PCL_TLS11_DES_CBC_SHA_5 0x0012
-#define OP_PCL_TLS11_DES_CBC_SHA_6 0x0015
-#define OP_PCL_TLS11_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_TLS11_RC4_128_MD5 0x0024
-#define OP_PCL_TLS11_RC4_128_MD5_2 0x0004
-#define OP_PCL_TLS11_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_TLS11_RC4_40_MD5 0x002b
-#define OP_PCL_TLS11_RC4_40_MD5_2 0x0003
-#define OP_PCL_TLS11_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_TLS11_RC4_128_SHA 0x0020
-#define OP_PCL_TLS11_RC4_128_SHA_2 0x008a
-#define OP_PCL_TLS11_RC4_128_SHA_3 0x008e
-#define OP_PCL_TLS11_RC4_128_SHA_4 0x0092
-#define OP_PCL_TLS11_RC4_128_SHA_5 0x0005
-#define OP_PCL_TLS11_RC4_128_SHA_6 0xc002
-#define OP_PCL_TLS11_RC4_128_SHA_7 0xc007
-#define OP_PCL_TLS11_RC4_128_SHA_8 0xc00c
-#define OP_PCL_TLS11_RC4_128_SHA_9 0xc011
-#define OP_PCL_TLS11_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_TLS11_RC4_40_SHA 0x0028
-
-#define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_TLS11_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_TLS11_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_TLS11_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_TLS11_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_TLS11_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_TLS11_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_TLS11_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_TLS11_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_TLS11_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_TLS11_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_TLS11_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_TLS11_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_TLS11_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_TLS11_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_TLS11_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_TLS11_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_TLS11_AES_128_CBC_SHA 0x002f
+#define OP_PCL_TLS11_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_TLS11_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_TLS11_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_TLS11_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_TLS11_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_TLS11_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_TLS11_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_TLS11_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_TLS11_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_TLS11_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_TLS11_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_TLS11_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_TLS11_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_TLS11_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_TLS11_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_TLS11_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_TLS11_AES_256_CBC_SHA 0x0035
+#define OP_PCL_TLS11_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_TLS11_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_TLS11_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_TLS11_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_TLS11_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_TLS11_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_TLS11_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_TLS11_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_TLS11_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_TLS11_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_TLS11_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_TLS11_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_TLS11_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_TLS11_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_TLS11_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_TLS11_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_TLS11_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_TLS11_DES_CBC_MD5 0x0022
+
+#define OP_PCL_TLS11_DES40_CBC_SHA 0x0008
+#define OP_PCL_TLS11_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_TLS11_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_TLS11_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_TLS11_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_TLS11_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_TLS11_DES40_CBC_SHA_7 0x0026
+
+#define OP_PCL_TLS11_DES_CBC_SHA 0x001e
+#define OP_PCL_TLS11_DES_CBC_SHA_2 0x0009
+#define OP_PCL_TLS11_DES_CBC_SHA_3 0x000c
+#define OP_PCL_TLS11_DES_CBC_SHA_4 0x000f
+#define OP_PCL_TLS11_DES_CBC_SHA_5 0x0012
+#define OP_PCL_TLS11_DES_CBC_SHA_6 0x0015
+#define OP_PCL_TLS11_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_TLS11_RC4_128_MD5 0x0024
+#define OP_PCL_TLS11_RC4_128_MD5_2 0x0004
+#define OP_PCL_TLS11_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_TLS11_RC4_40_MD5 0x002b
+#define OP_PCL_TLS11_RC4_40_MD5_2 0x0003
+#define OP_PCL_TLS11_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_TLS11_RC4_128_SHA 0x0020
+#define OP_PCL_TLS11_RC4_128_SHA_2 0x008a
+#define OP_PCL_TLS11_RC4_128_SHA_3 0x008e
+#define OP_PCL_TLS11_RC4_128_SHA_4 0x0092
+#define OP_PCL_TLS11_RC4_128_SHA_5 0x0005
+#define OP_PCL_TLS11_RC4_128_SHA_6 0xc002
+#define OP_PCL_TLS11_RC4_128_SHA_7 0xc007
+#define OP_PCL_TLS11_RC4_128_SHA_8 0xc00c
+#define OP_PCL_TLS11_RC4_128_SHA_9 0xc011
+#define OP_PCL_TLS11_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_TLS11_RC4_40_SHA 0x0028
+
+#define OP_PCL_TLS11_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_TLS11_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_TLS11_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_TLS11_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_TLS11_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_TLS11_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_TLS11_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_TLS11_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_TLS11_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_TLS11_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_TLS11_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_TLS11_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_TLS11_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_TLS11_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_TLS11_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_TLS11_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_TLS11_AES_256_CBC_SHA512 0xff65
/* For TLS 1.2 - OP_PCLID_TLS12 */
-#define OP_PCL_TLS12_AES_128_CBC_SHA 0x002f
-#define OP_PCL_TLS12_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_TLS12_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_TLS12_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_TLS12_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_TLS12_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_TLS12_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_TLS12_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_TLS12_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_TLS12_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_TLS12_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_TLS12_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_TLS12_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_TLS12_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_TLS12_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_TLS12_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_TLS12_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_TLS12_AES_256_CBC_SHA 0x0035
-#define OP_PCL_TLS12_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_TLS12_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_TLS12_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_TLS12_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_TLS12_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_TLS12_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_TLS12_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_TLS12_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_TLS12_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_TLS12_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_TLS12_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_TLS12_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_TLS12_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_TLS12_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_TLS12_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_TLS12_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_TLS12_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_TLS12_DES_CBC_MD5 0x0022
-
-#define OP_PCL_TLS12_DES40_CBC_SHA 0x0008
-#define OP_PCL_TLS12_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_TLS12_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_TLS12_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_TLS12_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_TLS12_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_TLS12_DES40_CBC_SHA_7 0x0026
-
-#define OP_PCL_TLS12_DES_CBC_SHA 0x001e
-#define OP_PCL_TLS12_DES_CBC_SHA_2 0x0009
-#define OP_PCL_TLS12_DES_CBC_SHA_3 0x000c
-#define OP_PCL_TLS12_DES_CBC_SHA_4 0x000f
-#define OP_PCL_TLS12_DES_CBC_SHA_5 0x0012
-#define OP_PCL_TLS12_DES_CBC_SHA_6 0x0015
-#define OP_PCL_TLS12_DES_CBC_SHA_7 0x001a
-
-#define OP_PCL_TLS12_RC4_128_MD5 0x0024
-#define OP_PCL_TLS12_RC4_128_MD5_2 0x0004
-#define OP_PCL_TLS12_RC4_128_MD5_3 0x0018
-
-#define OP_PCL_TLS12_RC4_40_MD5 0x002b
-#define OP_PCL_TLS12_RC4_40_MD5_2 0x0003
-#define OP_PCL_TLS12_RC4_40_MD5_3 0x0017
-
-#define OP_PCL_TLS12_RC4_128_SHA 0x0020
-#define OP_PCL_TLS12_RC4_128_SHA_2 0x008a
-#define OP_PCL_TLS12_RC4_128_SHA_3 0x008e
-#define OP_PCL_TLS12_RC4_128_SHA_4 0x0092
-#define OP_PCL_TLS12_RC4_128_SHA_5 0x0005
-#define OP_PCL_TLS12_RC4_128_SHA_6 0xc002
-#define OP_PCL_TLS12_RC4_128_SHA_7 0xc007
-#define OP_PCL_TLS12_RC4_128_SHA_8 0xc00c
-#define OP_PCL_TLS12_RC4_128_SHA_9 0xc011
-#define OP_PCL_TLS12_RC4_128_SHA_10 0xc016
-
-#define OP_PCL_TLS12_RC4_40_SHA 0x0028
-
-/* #define OP_PCL_TLS12_AES_128_CBC_SHA256 0x003c */
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_2 0x003e
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_3 0x003f
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_4 0x0040
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_5 0x0067
-#define OP_PCL_TLS12_AES_128_CBC_SHA256_6 0x006c
-
-/* #define OP_PCL_TLS12_AES_256_CBC_SHA256 0x003d */
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_2 0x0068
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_3 0x0069
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_4 0x006a
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_5 0x006b
-#define OP_PCL_TLS12_AES_256_CBC_SHA256_6 0x006d
+#define OP_PCL_TLS12_AES_128_CBC_SHA 0x002f
+#define OP_PCL_TLS12_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_TLS12_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_TLS12_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_TLS12_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_TLS12_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_TLS12_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_TLS12_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_TLS12_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_TLS12_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_TLS12_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_TLS12_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_TLS12_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_TLS12_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_TLS12_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_TLS12_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_TLS12_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_TLS12_AES_256_CBC_SHA 0x0035
+#define OP_PCL_TLS12_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_TLS12_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_TLS12_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_TLS12_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_TLS12_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_TLS12_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_TLS12_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_TLS12_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_TLS12_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_TLS12_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_TLS12_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_TLS12_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_TLS12_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_TLS12_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_TLS12_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_TLS12_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_TLS12_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_TLS12_DES_CBC_MD5 0x0022
+
+#define OP_PCL_TLS12_DES40_CBC_SHA 0x0008
+#define OP_PCL_TLS12_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_TLS12_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_TLS12_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_TLS12_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_TLS12_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_TLS12_DES40_CBC_SHA_7 0x0026
+
+#define OP_PCL_TLS12_DES_CBC_SHA 0x001e
+#define OP_PCL_TLS12_DES_CBC_SHA_2 0x0009
+#define OP_PCL_TLS12_DES_CBC_SHA_3 0x000c
+#define OP_PCL_TLS12_DES_CBC_SHA_4 0x000f
+#define OP_PCL_TLS12_DES_CBC_SHA_5 0x0012
+#define OP_PCL_TLS12_DES_CBC_SHA_6 0x0015
+#define OP_PCL_TLS12_DES_CBC_SHA_7 0x001a
+
+#define OP_PCL_TLS12_RC4_128_MD5 0x0024
+#define OP_PCL_TLS12_RC4_128_MD5_2 0x0004
+#define OP_PCL_TLS12_RC4_128_MD5_3 0x0018
+
+#define OP_PCL_TLS12_RC4_40_MD5 0x002b
+#define OP_PCL_TLS12_RC4_40_MD5_2 0x0003
+#define OP_PCL_TLS12_RC4_40_MD5_3 0x0017
+
+#define OP_PCL_TLS12_RC4_128_SHA 0x0020
+#define OP_PCL_TLS12_RC4_128_SHA_2 0x008a
+#define OP_PCL_TLS12_RC4_128_SHA_3 0x008e
+#define OP_PCL_TLS12_RC4_128_SHA_4 0x0092
+#define OP_PCL_TLS12_RC4_128_SHA_5 0x0005
+#define OP_PCL_TLS12_RC4_128_SHA_6 0xc002
+#define OP_PCL_TLS12_RC4_128_SHA_7 0xc007
+#define OP_PCL_TLS12_RC4_128_SHA_8 0xc00c
+#define OP_PCL_TLS12_RC4_128_SHA_9 0xc011
+#define OP_PCL_TLS12_RC4_128_SHA_10 0xc016
+
+#define OP_PCL_TLS12_RC4_40_SHA 0x0028
+
+/* #define OP_PCL_TLS12_AES_128_CBC_SHA256 0x003c */
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_2 0x003e
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_3 0x003f
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_4 0x0040
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_5 0x0067
+#define OP_PCL_TLS12_AES_128_CBC_SHA256_6 0x006c
+
+/* #define OP_PCL_TLS12_AES_256_CBC_SHA256 0x003d */
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_2 0x0068
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_3 0x0069
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_4 0x006a
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_5 0x006b
+#define OP_PCL_TLS12_AES_256_CBC_SHA256_6 0x006d
/* AEAD_AES_xxx_CCM/GCM remain to be defined... */
-#define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_TLS12_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_TLS12_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_TLS12_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_TLS12_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_TLS12_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_TLS12_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_TLS12_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_TLS12_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_TLS12_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_TLS12_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_TLS12_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_TLS12_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_TLS12_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_TLS12_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_TLS12_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_TLS12_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_TLS12_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_TLS12_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_TLS12_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_TLS12_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_TLS12_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_TLS12_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_TLS12_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_TLS12_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_TLS12_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_TLS12_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_TLS12_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_TLS12_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_TLS12_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_TLS12_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_TLS12_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_TLS12_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_TLS12_AES_256_CBC_SHA512 0xff65
/* For DTLS - OP_PCLID_DTLS */
-#define OP_PCL_DTLS_AES_128_CBC_SHA 0x002f
-#define OP_PCL_DTLS_AES_128_CBC_SHA_2 0x0030
-#define OP_PCL_DTLS_AES_128_CBC_SHA_3 0x0031
-#define OP_PCL_DTLS_AES_128_CBC_SHA_4 0x0032
-#define OP_PCL_DTLS_AES_128_CBC_SHA_5 0x0033
-#define OP_PCL_DTLS_AES_128_CBC_SHA_6 0x0034
-#define OP_PCL_DTLS_AES_128_CBC_SHA_7 0x008c
-#define OP_PCL_DTLS_AES_128_CBC_SHA_8 0x0090
-#define OP_PCL_DTLS_AES_128_CBC_SHA_9 0x0094
-#define OP_PCL_DTLS_AES_128_CBC_SHA_10 0xc004
-#define OP_PCL_DTLS_AES_128_CBC_SHA_11 0xc009
-#define OP_PCL_DTLS_AES_128_CBC_SHA_12 0xc00e
-#define OP_PCL_DTLS_AES_128_CBC_SHA_13 0xc013
-#define OP_PCL_DTLS_AES_128_CBC_SHA_14 0xc018
-#define OP_PCL_DTLS_AES_128_CBC_SHA_15 0xc01d
-#define OP_PCL_DTLS_AES_128_CBC_SHA_16 0xc01e
-#define OP_PCL_DTLS_AES_128_CBC_SHA_17 0xc01f
-
-#define OP_PCL_DTLS_AES_256_CBC_SHA 0x0035
-#define OP_PCL_DTLS_AES_256_CBC_SHA_2 0x0036
-#define OP_PCL_DTLS_AES_256_CBC_SHA_3 0x0037
-#define OP_PCL_DTLS_AES_256_CBC_SHA_4 0x0038
-#define OP_PCL_DTLS_AES_256_CBC_SHA_5 0x0039
-#define OP_PCL_DTLS_AES_256_CBC_SHA_6 0x003a
-#define OP_PCL_DTLS_AES_256_CBC_SHA_7 0x008d
-#define OP_PCL_DTLS_AES_256_CBC_SHA_8 0x0091
-#define OP_PCL_DTLS_AES_256_CBC_SHA_9 0x0095
-#define OP_PCL_DTLS_AES_256_CBC_SHA_10 0xc005
-#define OP_PCL_DTLS_AES_256_CBC_SHA_11 0xc00a
-#define OP_PCL_DTLS_AES_256_CBC_SHA_12 0xc00f
-#define OP_PCL_DTLS_AES_256_CBC_SHA_13 0xc014
-#define OP_PCL_DTLS_AES_256_CBC_SHA_14 0xc019
-#define OP_PCL_DTLS_AES_256_CBC_SHA_15 0xc020
-#define OP_PCL_DTLS_AES_256_CBC_SHA_16 0xc021
-#define OP_PCL_DTLS_AES_256_CBC_SHA_17 0xc022
-
-/* #define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0x0023 */
-
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA 0x001f
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_2 0x008b
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_3 0x008f
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_4 0x0093
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_5 0x000a
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_6 0x000d
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_7 0x0010
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_8 0x0013
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_9 0x0016
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_10 0x001b
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_11 0xc003
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_12 0xc008
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_13 0xc00d
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_14 0xc012
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_15 0xc017
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_16 0xc01a
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_17 0xc01b
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_18 0xc01c
-
-#define OP_PCL_DTLS_DES40_CBC_MD5 0x0029
-
-#define OP_PCL_DTLS_DES_CBC_MD5 0x0022
-
-#define OP_PCL_DTLS_DES40_CBC_SHA 0x0008
-#define OP_PCL_DTLS_DES40_CBC_SHA_2 0x000b
-#define OP_PCL_DTLS_DES40_CBC_SHA_3 0x000e
-#define OP_PCL_DTLS_DES40_CBC_SHA_4 0x0011
-#define OP_PCL_DTLS_DES40_CBC_SHA_5 0x0014
-#define OP_PCL_DTLS_DES40_CBC_SHA_6 0x0019
-#define OP_PCL_DTLS_DES40_CBC_SHA_7 0x0026
-
-
-#define OP_PCL_DTLS_DES_CBC_SHA 0x001e
-#define OP_PCL_DTLS_DES_CBC_SHA_2 0x0009
-#define OP_PCL_DTLS_DES_CBC_SHA_3 0x000c
-#define OP_PCL_DTLS_DES_CBC_SHA_4 0x000f
-#define OP_PCL_DTLS_DES_CBC_SHA_5 0x0012
-#define OP_PCL_DTLS_DES_CBC_SHA_6 0x0015
-#define OP_PCL_DTLS_DES_CBC_SHA_7 0x001a
-
-
-#define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0xff23
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA160 0xff30
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA224 0xff34
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA256 0xff36
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA384 0xff33
-#define OP_PCL_DTLS_3DES_EDE_CBC_SHA512 0xff35
-#define OP_PCL_DTLS_AES_128_CBC_SHA160 0xff80
-#define OP_PCL_DTLS_AES_128_CBC_SHA224 0xff84
-#define OP_PCL_DTLS_AES_128_CBC_SHA256 0xff86
-#define OP_PCL_DTLS_AES_128_CBC_SHA384 0xff83
-#define OP_PCL_DTLS_AES_128_CBC_SHA512 0xff85
-#define OP_PCL_DTLS_AES_192_CBC_SHA160 0xff20
-#define OP_PCL_DTLS_AES_192_CBC_SHA224 0xff24
-#define OP_PCL_DTLS_AES_192_CBC_SHA256 0xff26
-#define OP_PCL_DTLS_AES_192_CBC_SHA384 0xff23
-#define OP_PCL_DTLS_AES_192_CBC_SHA512 0xff25
-#define OP_PCL_DTLS_AES_256_CBC_SHA160 0xff60
-#define OP_PCL_DTLS_AES_256_CBC_SHA224 0xff64
-#define OP_PCL_DTLS_AES_256_CBC_SHA256 0xff66
-#define OP_PCL_DTLS_AES_256_CBC_SHA384 0xff63
-#define OP_PCL_DTLS_AES_256_CBC_SHA512 0xff65
+#define OP_PCL_DTLS_AES_128_CBC_SHA 0x002f
+#define OP_PCL_DTLS_AES_128_CBC_SHA_2 0x0030
+#define OP_PCL_DTLS_AES_128_CBC_SHA_3 0x0031
+#define OP_PCL_DTLS_AES_128_CBC_SHA_4 0x0032
+#define OP_PCL_DTLS_AES_128_CBC_SHA_5 0x0033
+#define OP_PCL_DTLS_AES_128_CBC_SHA_6 0x0034
+#define OP_PCL_DTLS_AES_128_CBC_SHA_7 0x008c
+#define OP_PCL_DTLS_AES_128_CBC_SHA_8 0x0090
+#define OP_PCL_DTLS_AES_128_CBC_SHA_9 0x0094
+#define OP_PCL_DTLS_AES_128_CBC_SHA_10 0xc004
+#define OP_PCL_DTLS_AES_128_CBC_SHA_11 0xc009
+#define OP_PCL_DTLS_AES_128_CBC_SHA_12 0xc00e
+#define OP_PCL_DTLS_AES_128_CBC_SHA_13 0xc013
+#define OP_PCL_DTLS_AES_128_CBC_SHA_14 0xc018
+#define OP_PCL_DTLS_AES_128_CBC_SHA_15 0xc01d
+#define OP_PCL_DTLS_AES_128_CBC_SHA_16 0xc01e
+#define OP_PCL_DTLS_AES_128_CBC_SHA_17 0xc01f
+
+#define OP_PCL_DTLS_AES_256_CBC_SHA 0x0035
+#define OP_PCL_DTLS_AES_256_CBC_SHA_2 0x0036
+#define OP_PCL_DTLS_AES_256_CBC_SHA_3 0x0037
+#define OP_PCL_DTLS_AES_256_CBC_SHA_4 0x0038
+#define OP_PCL_DTLS_AES_256_CBC_SHA_5 0x0039
+#define OP_PCL_DTLS_AES_256_CBC_SHA_6 0x003a
+#define OP_PCL_DTLS_AES_256_CBC_SHA_7 0x008d
+#define OP_PCL_DTLS_AES_256_CBC_SHA_8 0x0091
+#define OP_PCL_DTLS_AES_256_CBC_SHA_9 0x0095
+#define OP_PCL_DTLS_AES_256_CBC_SHA_10 0xc005
+#define OP_PCL_DTLS_AES_256_CBC_SHA_11 0xc00a
+#define OP_PCL_DTLS_AES_256_CBC_SHA_12 0xc00f
+#define OP_PCL_DTLS_AES_256_CBC_SHA_13 0xc014
+#define OP_PCL_DTLS_AES_256_CBC_SHA_14 0xc019
+#define OP_PCL_DTLS_AES_256_CBC_SHA_15 0xc020
+#define OP_PCL_DTLS_AES_256_CBC_SHA_16 0xc021
+#define OP_PCL_DTLS_AES_256_CBC_SHA_17 0xc022
+
+/* #define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0x0023 */
+
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA 0x001f
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_2 0x008b
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_3 0x008f
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_4 0x0093
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_5 0x000a
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_6 0x000d
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_7 0x0010
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_8 0x0013
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_9 0x0016
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_10 0x001b
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_11 0xc003
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_12 0xc008
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_13 0xc00d
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_14 0xc012
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_15 0xc017
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_16 0xc01a
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_17 0xc01b
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA_18 0xc01c
+
+#define OP_PCL_DTLS_DES40_CBC_MD5 0x0029
+
+#define OP_PCL_DTLS_DES_CBC_MD5 0x0022
+
+#define OP_PCL_DTLS_DES40_CBC_SHA 0x0008
+#define OP_PCL_DTLS_DES40_CBC_SHA_2 0x000b
+#define OP_PCL_DTLS_DES40_CBC_SHA_3 0x000e
+#define OP_PCL_DTLS_DES40_CBC_SHA_4 0x0011
+#define OP_PCL_DTLS_DES40_CBC_SHA_5 0x0014
+#define OP_PCL_DTLS_DES40_CBC_SHA_6 0x0019
+#define OP_PCL_DTLS_DES40_CBC_SHA_7 0x0026
+
+
+#define OP_PCL_DTLS_DES_CBC_SHA 0x001e
+#define OP_PCL_DTLS_DES_CBC_SHA_2 0x0009
+#define OP_PCL_DTLS_DES_CBC_SHA_3 0x000c
+#define OP_PCL_DTLS_DES_CBC_SHA_4 0x000f
+#define OP_PCL_DTLS_DES_CBC_SHA_5 0x0012
+#define OP_PCL_DTLS_DES_CBC_SHA_6 0x0015
+#define OP_PCL_DTLS_DES_CBC_SHA_7 0x001a
+
+
+#define OP_PCL_DTLS_3DES_EDE_CBC_MD5 0xff23
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA160 0xff30
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA224 0xff34
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA256 0xff36
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA384 0xff33
+#define OP_PCL_DTLS_3DES_EDE_CBC_SHA512 0xff35
+#define OP_PCL_DTLS_AES_128_CBC_SHA160 0xff80
+#define OP_PCL_DTLS_AES_128_CBC_SHA224 0xff84
+#define OP_PCL_DTLS_AES_128_CBC_SHA256 0xff86
+#define OP_PCL_DTLS_AES_128_CBC_SHA384 0xff83
+#define OP_PCL_DTLS_AES_128_CBC_SHA512 0xff85
+#define OP_PCL_DTLS_AES_192_CBC_SHA160 0xff20
+#define OP_PCL_DTLS_AES_192_CBC_SHA224 0xff24
+#define OP_PCL_DTLS_AES_192_CBC_SHA256 0xff26
+#define OP_PCL_DTLS_AES_192_CBC_SHA384 0xff23
+#define OP_PCL_DTLS_AES_192_CBC_SHA512 0xff25
+#define OP_PCL_DTLS_AES_256_CBC_SHA160 0xff60
+#define OP_PCL_DTLS_AES_256_CBC_SHA224 0xff64
+#define OP_PCL_DTLS_AES_256_CBC_SHA256 0xff66
+#define OP_PCL_DTLS_AES_256_CBC_SHA384 0xff63
+#define OP_PCL_DTLS_AES_256_CBC_SHA512 0xff65
/* 802.16 WiMAX protinfos */
-#define OP_PCL_WIMAX_OFDM 0x0201
-#define OP_PCL_WIMAX_OFDMA 0x0231
+#define OP_PCL_WIMAX_OFDM 0x0201
+#define OP_PCL_WIMAX_OFDMA 0x0231
/* 802.11 WiFi protinfos */
-#define OP_PCL_WIFI 0xac04
+#define OP_PCL_WIFI 0xac04
/* MacSec protinfos */
-#define OP_PCL_MACSEC 0x0001
+#define OP_PCL_MACSEC 0x0001
/* PKI unidirectional protocol protinfo bits */
-#define OP_PCL_PKPROT_TEST 0x0008
-#define OP_PCL_PKPROT_DECRYPT 0x0004
-#define OP_PCL_PKPROT_ECC 0x0002
-#define OP_PCL_PKPROT_F2M 0x0001
+#define OP_PCL_PKPROT_TEST 0x0008
+#define OP_PCL_PKPROT_DECRYPT 0x0004
+#define OP_PCL_PKPROT_ECC 0x0002
+#define OP_PCL_PKPROT_F2M 0x0001
/* For non-protocol/alg-only op commands */
#define OP_ALG_TYPE_SHIFT 24
@@ -1181,114 +1181,114 @@
#define OP_ALG_ENCRYPT 1
/* PKHA algorithm type set */
-#define OP_ALG_PK 0x00800000
-#define OP_ALG_PK_FUN_MASK 0x3f /* clrmem, modmath, or cpymem */
+#define OP_ALG_PK 0x00800000
+#define OP_ALG_PK_FUN_MASK 0x3f /* clrmem, modmath, or cpymem */
/* PKHA mode clear memory functions */
-#define OP_ALG_PKMODE_A_RAM 0x80000
-#define OP_ALG_PKMODE_B_RAM 0x40000
-#define OP_ALG_PKMODE_E_RAM 0x20000
-#define OP_ALG_PKMODE_N_RAM 0x10000
-#define OP_ALG_PKMODE_CLEARMEM 0x00001
+#define OP_ALG_PKMODE_A_RAM 0x80000
+#define OP_ALG_PKMODE_B_RAM 0x40000
+#define OP_ALG_PKMODE_E_RAM 0x20000
+#define OP_ALG_PKMODE_N_RAM 0x10000
+#define OP_ALG_PKMODE_CLEARMEM 0x00001
/* PKHA mode modular-arithmetic functions */
-#define OP_ALG_PKMODE_MOD_IN_MONTY 0x80000
-#define OP_ALG_PKMODE_MOD_OUT_MONTY 0x40000
-#define OP_ALG_PKMODE_MOD_F2M 0x20000
-#define OP_ALG_PKMODE_MOD_R2_IN 0x10000
-#define OP_ALG_PKMODE_PRJECTV 0x00800
-#define OP_ALG_PKMODE_TIME_EQ 0x400
-#define OP_ALG_PKMODE_OUT_B 0x000
-#define OP_ALG_PKMODE_OUT_A 0x100
-#define OP_ALG_PKMODE_MOD_ADD 0x002
-#define OP_ALG_PKMODE_MOD_SUB_AB 0x003
-#define OP_ALG_PKMODE_MOD_SUB_BA 0x004
-#define OP_ALG_PKMODE_MOD_MULT 0x005
-#define OP_ALG_PKMODE_MOD_EXPO 0x006
-#define OP_ALG_PKMODE_MOD_REDUCT 0x007
-#define OP_ALG_PKMODE_MOD_INV 0x008
-#define OP_ALG_PKMODE_MOD_ECC_ADD 0x009
-#define OP_ALG_PKMODE_MOD_ECC_DBL 0x00a
-#define OP_ALG_PKMODE_MOD_ECC_MULT 0x00b
-#define OP_ALG_PKMODE_MOD_MONT_CNST 0x00c
-#define OP_ALG_PKMODE_MOD_CRT_CNST 0x00d
-#define OP_ALG_PKMODE_MOD_GCD 0x00e
-#define OP_ALG_PKMODE_MOD_PRIMALITY 0x00f
+#define OP_ALG_PKMODE_MOD_IN_MONTY 0x80000
+#define OP_ALG_PKMODE_MOD_OUT_MONTY 0x40000
+#define OP_ALG_PKMODE_MOD_F2M 0x20000
+#define OP_ALG_PKMODE_MOD_R2_IN 0x10000
+#define OP_ALG_PKMODE_PRJECTV 0x00800
+#define OP_ALG_PKMODE_TIME_EQ 0x400
+#define OP_ALG_PKMODE_OUT_B 0x000
+#define OP_ALG_PKMODE_OUT_A 0x100
+#define OP_ALG_PKMODE_MOD_ADD 0x002
+#define OP_ALG_PKMODE_MOD_SUB_AB 0x003
+#define OP_ALG_PKMODE_MOD_SUB_BA 0x004
+#define OP_ALG_PKMODE_MOD_MULT 0x005
+#define OP_ALG_PKMODE_MOD_EXPO 0x006
+#define OP_ALG_PKMODE_MOD_REDUCT 0x007
+#define OP_ALG_PKMODE_MOD_INV 0x008
+#define OP_ALG_PKMODE_MOD_ECC_ADD 0x009
+#define OP_ALG_PKMODE_MOD_ECC_DBL 0x00a
+#define OP_ALG_PKMODE_MOD_ECC_MULT 0x00b
+#define OP_ALG_PKMODE_MOD_MONT_CNST 0x00c
+#define OP_ALG_PKMODE_MOD_CRT_CNST 0x00d
+#define OP_ALG_PKMODE_MOD_GCD 0x00e
+#define OP_ALG_PKMODE_MOD_PRIMALITY 0x00f
/* PKHA mode copy-memory functions */
-#define OP_ALG_PKMODE_SRC_REG_SHIFT 13
-#define OP_ALG_PKMODE_SRC_REG_MASK (7 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_SHIFT 10
-#define OP_ALG_PKMODE_DST_REG_MASK (7 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_SHIFT 8
-#define OP_ALG_PKMODE_SRC_SEG_MASK (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_SHIFT 6
-#define OP_ALG_PKMODE_DST_SEG_MASK (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-
-#define OP_ALG_PKMODE_SRC_REG_A (0 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_REG_B (1 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_REG_N (3 << OP_ALG_PKMODE_SRC_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_A (0 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_B (1 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_E (2 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_DST_REG_N (3 << OP_ALG_PKMODE_DST_REG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_0 (0 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_1 (1 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_2 (2 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_SRC_SEG_3 (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_0 (0 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_1 (1 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_2 (2 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_DST_SEG_3 (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
-#define OP_ALG_PKMODE_CPYMEM_N_SZ 0x80
-#define OP_ALG_PKMODE_CPYMEM_SRC_SZ 0x81
+#define OP_ALG_PKMODE_SRC_REG_SHIFT 13
+#define OP_ALG_PKMODE_SRC_REG_MASK (7 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_SHIFT 10
+#define OP_ALG_PKMODE_DST_REG_MASK (7 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_SHIFT 8
+#define OP_ALG_PKMODE_SRC_SEG_MASK (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_SHIFT 6
+#define OP_ALG_PKMODE_DST_SEG_MASK (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+
+#define OP_ALG_PKMODE_SRC_REG_A (0 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_REG_B (1 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_REG_N (3 << OP_ALG_PKMODE_SRC_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_A (0 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_B (1 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_E (2 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_DST_REG_N (3 << OP_ALG_PKMODE_DST_REG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_0 (0 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_1 (1 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_2 (2 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_SRC_SEG_3 (3 << OP_ALG_PKMODE_SRC_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_0 (0 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_1 (1 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_2 (2 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_DST_SEG_3 (3 << OP_ALG_PKMODE_DST_SEG_SHIFT)
+#define OP_ALG_PKMODE_CPYMEM_N_SZ 0x80
+#define OP_ALG_PKMODE_CPYMEM_SRC_SZ 0x81
/*
* SEQ_IN_PTR Command Constructs
*/
/* Release Buffers */
-#define SQIN_RBS 0x04000000
+#define SQIN_RBS 0x04000000
/* Sequence pointer is really a descriptor */
-#define SQIN_INL 0x02000000
+#define SQIN_INL 0x02000000
/* Sequence pointer is a scatter-gather table */
-#define SQIN_SGF 0x01000000
+#define SQIN_SGF 0x01000000
/* Appends to a previous pointer */
-#define SQIN_PRE 0x00800000
+#define SQIN_PRE 0x00800000
/* Use extended length following pointer */
-#define SQIN_EXT 0x00400000
+#define SQIN_EXT 0x00400000
/* Restore sequence with pointer/length */
-#define SQIN_RTO 0x00200000
+#define SQIN_RTO 0x00200000
/* Replace job descriptor */
-#define SQIN_RJD 0x00100000
+#define SQIN_RJD 0x00100000
-#define SQIN_LEN_SHIFT 0
-#define SQIN_LEN_MASK (0xffff << SQIN_LEN_SHIFT)
+#define SQIN_LEN_SHIFT 0
+#define SQIN_LEN_MASK (0xffff << SQIN_LEN_SHIFT)
/*
* SEQ_OUT_PTR Command Constructs
*/
/* Sequence pointer is a scatter-gather table */
-#define SQOUT_SGF 0x01000000
+#define SQOUT_SGF 0x01000000
/* Appends to a previous pointer */
-#define SQOUT_PRE 0x00800000
+#define SQOUT_PRE 0x00800000
/* Restore sequence with pointer/length */
-#define SQOUT_RTO 0x00200000
+#define SQOUT_RTO 0x00200000
/* Use extended length following pointer */
-#define SQOUT_EXT 0x00400000
+#define SQOUT_EXT 0x00400000
-#define SQOUT_LEN_SHIFT 0
-#define SQOUT_LEN_MASK (0xffff << SQOUT_LEN_SHIFT)
+#define SQOUT_LEN_SHIFT 0
+#define SQOUT_LEN_MASK (0xffff << SQOUT_LEN_SHIFT)
/*
@@ -1296,196 +1296,196 @@
*/
/* TYPE field is all that's relevant */
-#define SIGN_TYPE_SHIFT 16
-#define SIGN_TYPE_MASK (0x0f << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_SHIFT 16
+#define SIGN_TYPE_MASK (0x0f << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_FINAL (0x00 << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_FINAL (0x00 << SIGN_TYPE_SHIFT)
#define SIGN_TYPE_FINAL_RESTORE (0x01 << SIGN_TYPE_SHIFT)
#define SIGN_TYPE_FINAL_NONZERO (0x02 << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_IMM_2 (0x0a << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_IMM_3 (0x0b << SIGN_TYPE_SHIFT)
-#define SIGN_TYPE_IMM_4 (0x0c << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_IMM_2 (0x0a << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_IMM_3 (0x0b << SIGN_TYPE_SHIFT)
+#define SIGN_TYPE_IMM_4 (0x0c << SIGN_TYPE_SHIFT)
/*
* MOVE Command Constructs
*/
-#define MOVE_AUX_SHIFT 25
-#define MOVE_AUX_MASK (3 << MOVE_AUX_SHIFT)
-#define MOVE_AUX_MS (2 << MOVE_AUX_SHIFT)
-#define MOVE_AUX_LS (1 << MOVE_AUX_SHIFT)
-
-#define MOVE_WAITCOMP_SHIFT 24
-#define MOVE_WAITCOMP_MASK (1 << MOVE_WAITCOMP_SHIFT)
-#define MOVE_WAITCOMP (1 << MOVE_WAITCOMP_SHIFT)
-
-#define MOVE_SRC_SHIFT 20
-#define MOVE_SRC_MASK (0x0f << MOVE_SRC_SHIFT)
-#define MOVE_SRC_CLASS1CTX (0x00 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_CLASS2CTX (0x01 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_OUTFIFO (0x02 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_DESCBUF (0x03 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH0 (0x04 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH1 (0x05 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH2 (0x06 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_MATH3 (0x07 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_INFIFO (0x08 << MOVE_SRC_SHIFT)
-#define MOVE_SRC_INFIFO_CL (0x09 << MOVE_SRC_SHIFT)
-
-#define MOVE_DEST_SHIFT 16
-#define MOVE_DEST_MASK (0x0f << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS1CTX (0x00 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS2CTX (0x01 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_OUTFIFO (0x02 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_DESCBUF (0x03 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH0 (0x04 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH1 (0x05 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH2 (0x06 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_MATH3 (0x07 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT)
-#define MOVE_DEST_PK_A (0x0c << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS1KEY (0x0d << MOVE_DEST_SHIFT)
-#define MOVE_DEST_CLASS2KEY (0x0e << MOVE_DEST_SHIFT)
-
-#define MOVE_OFFSET_SHIFT 8
-#define MOVE_OFFSET_MASK (0xff << MOVE_OFFSET_SHIFT)
-
-#define MOVE_LEN_SHIFT 0
-#define MOVE_LEN_MASK (0xff << MOVE_LEN_SHIFT)
-
-#define MOVELEN_MRSEL_SHIFT 0
-#define MOVELEN_MRSEL_MASK (0x3 << MOVE_LEN_SHIFT)
+#define MOVE_AUX_SHIFT 25
+#define MOVE_AUX_MASK (3 << MOVE_AUX_SHIFT)
+#define MOVE_AUX_MS (2 << MOVE_AUX_SHIFT)
+#define MOVE_AUX_LS (1 << MOVE_AUX_SHIFT)
+
+#define MOVE_WAITCOMP_SHIFT 24
+#define MOVE_WAITCOMP_MASK (1 << MOVE_WAITCOMP_SHIFT)
+#define MOVE_WAITCOMP (1 << MOVE_WAITCOMP_SHIFT)
+
+#define MOVE_SRC_SHIFT 20
+#define MOVE_SRC_MASK (0x0f << MOVE_SRC_SHIFT)
+#define MOVE_SRC_CLASS1CTX (0x00 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_CLASS2CTX (0x01 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_OUTFIFO (0x02 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_DESCBUF (0x03 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH0 (0x04 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH1 (0x05 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH2 (0x06 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_MATH3 (0x07 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_INFIFO (0x08 << MOVE_SRC_SHIFT)
+#define MOVE_SRC_INFIFO_CL (0x09 << MOVE_SRC_SHIFT)
+
+#define MOVE_DEST_SHIFT 16
+#define MOVE_DEST_MASK (0x0f << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1CTX (0x00 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2CTX (0x01 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_OUTFIFO (0x02 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_DESCBUF (0x03 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH0 (0x04 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH1 (0x05 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH2 (0x06 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_MATH3 (0x07 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1INFIFO (0x08 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2INFIFO (0x09 << MOVE_DEST_SHIFT)
+#define MOVE_DEST_PK_A (0x0c << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS1KEY (0x0d << MOVE_DEST_SHIFT)
+#define MOVE_DEST_CLASS2KEY (0x0e << MOVE_DEST_SHIFT)
+
+#define MOVE_OFFSET_SHIFT 8
+#define MOVE_OFFSET_MASK (0xff << MOVE_OFFSET_SHIFT)
+
+#define MOVE_LEN_SHIFT 0
+#define MOVE_LEN_MASK (0xff << MOVE_LEN_SHIFT)
+
+#define MOVELEN_MRSEL_SHIFT 0
+#define MOVELEN_MRSEL_MASK (0x3 << MOVE_LEN_SHIFT)
/*
* MATH Command Constructs
*/
-#define MATH_IFB_SHIFT 26
-#define MATH_IFB_MASK (1 << MATH_IFB_SHIFT)
-#define MATH_IFB (1 << MATH_IFB_SHIFT)
+#define MATH_IFB_SHIFT 26
+#define MATH_IFB_MASK (1 << MATH_IFB_SHIFT)
+#define MATH_IFB (1 << MATH_IFB_SHIFT)
-#define MATH_NFU_SHIFT 25
-#define MATH_NFU_MASK (1 << MATH_NFU_SHIFT)
-#define MATH_NFU (1 << MATH_NFU_SHIFT)
+#define MATH_NFU_SHIFT 25
+#define MATH_NFU_MASK (1 << MATH_NFU_SHIFT)
+#define MATH_NFU (1 << MATH_NFU_SHIFT)
-#define MATH_STL_SHIFT 24
-#define MATH_STL_MASK (1 << MATH_STL_SHIFT)
-#define MATH_STL (1 << MATH_STL_SHIFT)
+#define MATH_STL_SHIFT 24
+#define MATH_STL_MASK (1 << MATH_STL_SHIFT)
+#define MATH_STL (1 << MATH_STL_SHIFT)
/* Function selectors */
-#define MATH_FUN_SHIFT 20
-#define MATH_FUN_MASK (0x0f << MATH_FUN_SHIFT)
-#define MATH_FUN_ADD (0x00 << MATH_FUN_SHIFT)
-#define MATH_FUN_ADDC (0x01 << MATH_FUN_SHIFT)
-#define MATH_FUN_SUB (0x02 << MATH_FUN_SHIFT)
-#define MATH_FUN_SUBB (0x03 << MATH_FUN_SHIFT)
-#define MATH_FUN_OR (0x04 << MATH_FUN_SHIFT)
-#define MATH_FUN_AND (0x05 << MATH_FUN_SHIFT)
-#define MATH_FUN_XOR (0x06 << MATH_FUN_SHIFT)
-#define MATH_FUN_LSHIFT (0x07 << MATH_FUN_SHIFT)
-#define MATH_FUN_RSHIFT (0x08 << MATH_FUN_SHIFT)
-#define MATH_FUN_SHLD (0x09 << MATH_FUN_SHIFT)
-#define MATH_FUN_ZBYT (0x0a << MATH_FUN_SHIFT)
+#define MATH_FUN_SHIFT 20
+#define MATH_FUN_MASK (0x0f << MATH_FUN_SHIFT)
+#define MATH_FUN_ADD (0x00 << MATH_FUN_SHIFT)
+#define MATH_FUN_ADDC (0x01 << MATH_FUN_SHIFT)
+#define MATH_FUN_SUB (0x02 << MATH_FUN_SHIFT)
+#define MATH_FUN_SUBB (0x03 << MATH_FUN_SHIFT)
+#define MATH_FUN_OR (0x04 << MATH_FUN_SHIFT)
+#define MATH_FUN_AND (0x05 << MATH_FUN_SHIFT)
+#define MATH_FUN_XOR (0x06 << MATH_FUN_SHIFT)
+#define MATH_FUN_LSHIFT (0x07 << MATH_FUN_SHIFT)
+#define MATH_FUN_RSHIFT (0x08 << MATH_FUN_SHIFT)
+#define MATH_FUN_SHLD (0x09 << MATH_FUN_SHIFT)
+#define MATH_FUN_ZBYT (0x0a << MATH_FUN_SHIFT)
/* Source 0 selectors */
-#define MATH_SRC0_SHIFT 16
-#define MATH_SRC0_MASK (0x0f << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG0 (0x00 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG1 (0x01 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG2 (0x02 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_REG3 (0x03 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_IMM (0x04 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_SEQINLEN (0x08 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_SEQOUTLEN (0x09 << MATH_SRC0_SHIFT)
-#define MATH_SRC0_VARSEQINLEN (0x0a << MATH_SRC0_SHIFT)
-#define MATH_SRC0_VARSEQOUTLEN (0x0b << MATH_SRC0_SHIFT)
-#define MATH_SRC0_ZERO (0x0c << MATH_SRC0_SHIFT)
+#define MATH_SRC0_SHIFT 16
+#define MATH_SRC0_MASK (0x0f << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG0 (0x00 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG1 (0x01 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG2 (0x02 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_REG3 (0x03 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_IMM (0x04 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_SEQINLEN (0x08 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_SEQOUTLEN (0x09 << MATH_SRC0_SHIFT)
+#define MATH_SRC0_VARSEQINLEN (0x0a << MATH_SRC0_SHIFT)
+#define MATH_SRC0_VARSEQOUTLEN (0x0b << MATH_SRC0_SHIFT)
+#define MATH_SRC0_ZERO (0x0c << MATH_SRC0_SHIFT)
/* Source 1 selectors */
-#define MATH_SRC1_SHIFT 12
-#define MATH_SRC1_MASK (0x0f << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG0 (0x00 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG1 (0x01 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT)
-#define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT)
-#define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT)
-#define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT)
+#define MATH_SRC1_SHIFT 12
+#define MATH_SRC1_MASK (0x0f << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG0 (0x00 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG1 (0x01 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG2 (0x02 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_REG3 (0x03 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_IMM (0x04 << MATH_SRC1_SHIFT)
+#define MATH_SRC1_INFIFO (0x0a << MATH_SRC1_SHIFT)
+#define MATH_SRC1_OUTFIFO (0x0b << MATH_SRC1_SHIFT)
+#define MATH_SRC1_ONE (0x0c << MATH_SRC1_SHIFT)
/* Destination selectors */
-#define MATH_DEST_SHIFT 8
-#define MATH_DEST_MASK (0x0f << MATH_DEST_SHIFT)
-#define MATH_DEST_REG0 (0x00 << MATH_DEST_SHIFT)
-#define MATH_DEST_REG1 (0x01 << MATH_DEST_SHIFT)
-#define MATH_DEST_REG2 (0x02 << MATH_DEST_SHIFT)
-#define MATH_DEST_REG3 (0x03 << MATH_DEST_SHIFT)
-#define MATH_DEST_SEQINLEN (0x08 << MATH_DEST_SHIFT)
-#define MATH_DEST_SEQOUTLEN (0x09 << MATH_DEST_SHIFT)
-#define MATH_DEST_VARSEQINLEN (0x0a << MATH_DEST_SHIFT)
-#define MATH_DEST_VARSEQOUTLEN (0x0b << MATH_DEST_SHIFT)
-#define MATH_DEST_NONE (0x0f << MATH_DEST_SHIFT)
+#define MATH_DEST_SHIFT 8
+#define MATH_DEST_MASK (0x0f << MATH_DEST_SHIFT)
+#define MATH_DEST_REG0 (0x00 << MATH_DEST_SHIFT)
+#define MATH_DEST_REG1 (0x01 << MATH_DEST_SHIFT)
+#define MATH_DEST_REG2 (0x02 << MATH_DEST_SHIFT)
+#define MATH_DEST_REG3 (0x03 << MATH_DEST_SHIFT)
+#define MATH_DEST_SEQINLEN (0x08 << MATH_DEST_SHIFT)
+#define MATH_DEST_SEQOUTLEN (0x09 << MATH_DEST_SHIFT)
+#define MATH_DEST_VARSEQINLEN (0x0a << MATH_DEST_SHIFT)
+#define MATH_DEST_VARSEQOUTLEN (0x0b << MATH_DEST_SHIFT)
+#define MATH_DEST_NONE (0x0f << MATH_DEST_SHIFT)
/* Length selectors */
-#define MATH_LEN_SHIFT 0
-#define MATH_LEN_MASK (0x0f << MATH_LEN_SHIFT)
-#define MATH_LEN_1BYTE 0x01
-#define MATH_LEN_2BYTE 0x02
-#define MATH_LEN_4BYTE 0x04
-#define MATH_LEN_8BYTE 0x08
+#define MATH_LEN_SHIFT 0
+#define MATH_LEN_MASK (0x0f << MATH_LEN_SHIFT)
+#define MATH_LEN_1BYTE 0x01
+#define MATH_LEN_2BYTE 0x02
+#define MATH_LEN_4BYTE 0x04
+#define MATH_LEN_8BYTE 0x08
/*
* JUMP Command Constructs
*/
-#define JUMP_CLASS_SHIFT 25
+#define JUMP_CLASS_SHIFT 25
#define JUMP_CLASS_MASK (3 << JUMP_CLASS_SHIFT)
#define JUMP_CLASS_NONE 0
#define JUMP_CLASS_CLASS1 (1 << JUMP_CLASS_SHIFT)
#define JUMP_CLASS_CLASS2 (2 << JUMP_CLASS_SHIFT)
#define JUMP_CLASS_BOTH (3 << JUMP_CLASS_SHIFT)
-#define JUMP_JSL_SHIFT 24
-#define JUMP_JSL_MASK (1 << JUMP_JSL_SHIFT)
-#define JUMP_JSL (1 << JUMP_JSL_SHIFT)
+#define JUMP_JSL_SHIFT 24
+#define JUMP_JSL_MASK (1 << JUMP_JSL_SHIFT)
+#define JUMP_JSL (1 << JUMP_JSL_SHIFT)
-#define JUMP_TYPE_SHIFT 22
-#define JUMP_TYPE_MASK (0x03 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_LOCAL (0x00 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_NONLOCAL (0x01 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_HALT (0x02 << JUMP_TYPE_SHIFT)
-#define JUMP_TYPE_HALT_USER (0x03 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_SHIFT 22
+#define JUMP_TYPE_MASK (0x03 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_LOCAL (0x00 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_NONLOCAL (0x01 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_HALT (0x02 << JUMP_TYPE_SHIFT)
+#define JUMP_TYPE_HALT_USER (0x03 << JUMP_TYPE_SHIFT)
-#define JUMP_TEST_SHIFT 16
-#define JUMP_TEST_MASK (0x03 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_ALL (0x00 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_INVALL (0x01 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_ANY (0x02 << JUMP_TEST_SHIFT)
-#define JUMP_TEST_INVANY (0x03 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_SHIFT 16
+#define JUMP_TEST_MASK (0x03 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_ALL (0x00 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_INVALL (0x01 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_ANY (0x02 << JUMP_TEST_SHIFT)
+#define JUMP_TEST_INVANY (0x03 << JUMP_TEST_SHIFT)
/* Condition codes. JSL bit is factored in */
-#define JUMP_COND_SHIFT 8
-#define JUMP_COND_MASK (0x100ff << JUMP_COND_SHIFT)
-#define JUMP_COND_PK_0 (0x80 << JUMP_COND_SHIFT)
-#define JUMP_COND_PK_GCD_1 (0x40 << JUMP_COND_SHIFT)
-#define JUMP_COND_PK_PRIME (0x20 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_N (0x08 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_Z (0x04 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_C (0x02 << JUMP_COND_SHIFT)
-#define JUMP_COND_MATH_NV (0x01 << JUMP_COND_SHIFT)
-
-#define JUMP_COND_JRP ((0x80 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_SHRD ((0x40 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_SELF ((0x20 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_CALM ((0x10 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NIP ((0x08 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NIFP ((0x04 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NOP ((0x02 << JUMP_COND_SHIFT) | JUMP_JSL)
-#define JUMP_COND_NCP ((0x01 << JUMP_COND_SHIFT) | JUMP_JSL)
-
-#define JUMP_OFFSET_SHIFT 0
-#define JUMP_OFFSET_MASK (0xff << JUMP_OFFSET_SHIFT)
+#define JUMP_COND_SHIFT 8
+#define JUMP_COND_MASK (0x100ff << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_0 (0x80 << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_GCD_1 (0x40 << JUMP_COND_SHIFT)
+#define JUMP_COND_PK_PRIME (0x20 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_N (0x08 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_Z (0x04 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_C (0x02 << JUMP_COND_SHIFT)
+#define JUMP_COND_MATH_NV (0x01 << JUMP_COND_SHIFT)
+
+#define JUMP_COND_JRP ((0x80 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_SHRD ((0x40 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_SELF ((0x20 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_CALM ((0x10 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NIP ((0x08 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NIFP ((0x04 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NOP ((0x02 << JUMP_COND_SHIFT) | JUMP_JSL)
+#define JUMP_COND_NCP ((0x01 << JUMP_COND_SHIFT) | JUMP_JSL)
+
+#define JUMP_OFFSET_SHIFT 0
+#define JUMP_OFFSET_MASK (0xff << JUMP_OFFSET_SHIFT)
/*
* NFIFO ENTRY
@@ -1500,20 +1500,20 @@
#define NFIFOENTRY_DEST_BOTH (3 << NFIFOENTRY_DEST_SHIFT)
#define NFIFOENTRY_LC2_SHIFT 29
-#define NFIFOENTRY_LC2_MASK (1 << NFIFOENTRY_LC2_SHIFT)
-#define NFIFOENTRY_LC2 (1 << NFIFOENTRY_LC2_SHIFT)
+#define NFIFOENTRY_LC2_MASK (1 << NFIFOENTRY_LC2_SHIFT)
+#define NFIFOENTRY_LC2 (1 << NFIFOENTRY_LC2_SHIFT)
#define NFIFOENTRY_LC1_SHIFT 28
-#define NFIFOENTRY_LC1_MASK (1 << NFIFOENTRY_LC1_SHIFT)
-#define NFIFOENTRY_LC1 (1 << NFIFOENTRY_LC1_SHIFT)
+#define NFIFOENTRY_LC1_MASK (1 << NFIFOENTRY_LC1_SHIFT)
+#define NFIFOENTRY_LC1 (1 << NFIFOENTRY_LC1_SHIFT)
#define NFIFOENTRY_FC2_SHIFT 27
-#define NFIFOENTRY_FC2_MASK (1 << NFIFOENTRY_FC2_SHIFT)
-#define NFIFOENTRY_FC2 (1 << NFIFOENTRY_FC2_SHIFT)
+#define NFIFOENTRY_FC2_MASK (1 << NFIFOENTRY_FC2_SHIFT)
+#define NFIFOENTRY_FC2 (1 << NFIFOENTRY_FC2_SHIFT)
#define NFIFOENTRY_FC1_SHIFT 26
-#define NFIFOENTRY_FC1_MASK (1 << NFIFOENTRY_FC1_SHIFT)
-#define NFIFOENTRY_FC1 (1 << NFIFOENTRY_FC1_SHIFT)
+#define NFIFOENTRY_FC1_MASK (1 << NFIFOENTRY_FC1_SHIFT)
+#define NFIFOENTRY_FC1 (1 << NFIFOENTRY_FC1_SHIFT)
#define NFIFOENTRY_STYPE_SHIFT 24
#define NFIFOENTRY_STYPE_MASK (3 << NFIFOENTRY_STYPE_SHIFT)
@@ -1525,60 +1525,59 @@
#define NFIFOENTRY_DTYPE_SHIFT 20
#define NFIFOENTRY_DTYPE_MASK (0xF << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_SBOX (0x0 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_AAD (0x1 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_IV (0x2 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_SAD (0x3 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_ICV (0xA << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_SKIP (0xE << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_MSG (0xF << NFIFOENTRY_DTYPE_SHIFT)
-
-#define NFIFOENTRY_DTYPE_PK_A0 (0x0 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A1 (0x1 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A2 (0x2 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A3 (0x3 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B0 (0x4 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B1 (0x5 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B2 (0x6 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B3 (0x7 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_N (0x8 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_E (0x9 << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_A (0xC << NFIFOENTRY_DTYPE_SHIFT)
-#define NFIFOENTRY_DTYPE_PK_B (0xD << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_SBOX (0x0 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_AAD (0x1 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_IV (0x2 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_SAD (0x3 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_ICV (0xA << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_SKIP (0xE << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_MSG (0xF << NFIFOENTRY_DTYPE_SHIFT)
+
+#define NFIFOENTRY_DTYPE_PK_A0 (0x0 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A1 (0x1 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A2 (0x2 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A3 (0x3 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B0 (0x4 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B1 (0x5 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B2 (0x6 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B3 (0x7 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_N (0x8 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_E (0x9 << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_A (0xC << NFIFOENTRY_DTYPE_SHIFT)
+#define NFIFOENTRY_DTYPE_PK_B (0xD << NFIFOENTRY_DTYPE_SHIFT)
#define NFIFOENTRY_BND_SHIFT 19
-#define NFIFOENTRY_BND_MASK (1 << NFIFOENTRY_BND_SHIFT)
-#define NFIFOENTRY_BND (1 << NFIFOENTRY_BND_SHIFT)
+#define NFIFOENTRY_BND_MASK (1 << NFIFOENTRY_BND_SHIFT)
+#define NFIFOENTRY_BND (1 << NFIFOENTRY_BND_SHIFT)
#define NFIFOENTRY_PTYPE_SHIFT 16
#define NFIFOENTRY_PTYPE_MASK (0x7 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_ZEROS (0x0 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND_NOZEROS (0x1 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_INCREMENT (0x2 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND (0x3 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_ZEROS_NZ (0x4 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND_NZ_LZ (0x5 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_N (0x6 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_PTYPE_RND_NZ_N (0x7 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_ZEROS (0x0 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND_NOZEROS (0x1 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_INCREMENT (0x2 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND (0x3 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_ZEROS_NZ (0x4 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND_NZ_LZ (0x5 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_N (0x6 << NFIFOENTRY_PTYPE_SHIFT)
+#define NFIFOENTRY_PTYPE_RND_NZ_N (0x7 << NFIFOENTRY_PTYPE_SHIFT)
-#define NFIFOENTRY_OC_SHIFT 15
-#define NFIFOENTRY_OC_MASK (1 << NFIFOENTRY_OC_SHIFT)
-#define NFIFOENTRY_OC (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_OC_SHIFT 15
+#define NFIFOENTRY_OC_MASK (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_OC (1 << NFIFOENTRY_OC_SHIFT)
#define NFIFOENTRY_AST_SHIFT 14
-#define NFIFOENTRY_AST_MASK (1 << NFIFOENTRY_OC_SHIFT)
-#define NFIFOENTRY_AST (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_AST_MASK (1 << NFIFOENTRY_OC_SHIFT)
+#define NFIFOENTRY_AST (1 << NFIFOENTRY_OC_SHIFT)
-#define NFIFOENTRY_BM_SHIFT 11
-#define NFIFOENTRY_BM_MASK (1 << NFIFOENTRY_BM_SHIFT)
-#define NFIFOENTRY_BM (1 << NFIFOENTRY_BM_SHIFT)
-
-#define NFIFOENTRY_PS_SHIFT 10
-#define NFIFOENTRY_PS_MASK (1 << NFIFOENTRY_PS_SHIFT)
-#define NFIFOENTRY_PS (1 << NFIFOENTRY_PS_SHIFT)
+#define NFIFOENTRY_BM_SHIFT 11
+#define NFIFOENTRY_BM_MASK (1 << NFIFOENTRY_BM_SHIFT)
+#define NFIFOENTRY_BM (1 << NFIFOENTRY_BM_SHIFT)
+#define NFIFOENTRY_PS_SHIFT 10
+#define NFIFOENTRY_PS_MASK (1 << NFIFOENTRY_PS_SHIFT)
+#define NFIFOENTRY_PS (1 << NFIFOENTRY_PS_SHIFT)
#define NFIFOENTRY_DLEN_SHIFT 0
#define NFIFOENTRY_DLEN_MASK (0xFFF << NFIFOENTRY_DLEN_SHIFT)
@@ -1591,15 +1590,15 @@
*/
/* IPSec ESP CBC Encap/Decap Options */
-#define PDBOPTS_ESPCBC_ARSNONE 0x00 /* no antireplay window */
-#define PDBOPTS_ESPCBC_ARS32 0x40 /* 32-entry antireplay window */
-#define PDBOPTS_ESPCBC_ARS64 0xc0 /* 64-entry antireplay window */
-#define PDBOPTS_ESPCBC_IVSRC 0x20 /* IV comes from internal random gen */
-#define PDBOPTS_ESPCBC_ESN 0x10 /* extended sequence included */
-#define PDBOPTS_ESPCBC_OUTFMT 0x08 /* output only decapsulation (decap) */
-#define PDBOPTS_ESPCBC_IPHDRSRC 0x08 /* IP header comes from PDB (encap) */
-#define PDBOPTS_ESPCBC_INCIPHDR 0x04 /* Prepend IP header to output frame */
-#define PDBOPTS_ESPCBC_IPVSN 0x02 /* process IPv6 header */
-#define PDBOPTS_ESPCBC_TUNNEL 0x01 /* tunnel mode next-header byte */
+#define PDBOPTS_ESPCBC_ARSNONE 0x00 /* no antireplay window */
+#define PDBOPTS_ESPCBC_ARS32 0x40 /* 32-entry antireplay window */
+#define PDBOPTS_ESPCBC_ARS64 0xc0 /* 64-entry antireplay window */
+#define PDBOPTS_ESPCBC_IVSRC 0x20 /* IV comes from internal random gen */
+#define PDBOPTS_ESPCBC_ESN 0x10 /* extended sequence included */
+#define PDBOPTS_ESPCBC_OUTFMT 0x08 /* output only decapsulation (decap) */
+#define PDBOPTS_ESPCBC_IPHDRSRC 0x08 /* IP header comes from PDB (encap) */
+#define PDBOPTS_ESPCBC_INCIPHDR 0x04 /* Prepend IP header to output frame */
+#define PDBOPTS_ESPCBC_IPVSN 0x02 /* process IPv6 header */
+#define PDBOPTS_ESPCBC_TUNNEL 0x01 /* tunnel mode next-header byte */
#endif /* DESC_H */
diff --git a/drivers/crypto/caam/desc_constr.h b/drivers/crypto/caam/desc_constr.h
index 0991323cf3fd..348b882275f0 100644
--- a/drivers/crypto/caam/desc_constr.h
+++ b/drivers/crypto/caam/desc_constr.h
@@ -18,9 +18,10 @@
#define PRINT_POS
#endif
-#define SET_OK_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
- LDST_SRCDST_WORD_DECOCTRL | \
- (LDOFF_CHG_SHARE_OK_PROP << LDST_OFFSET_SHIFT))
+#define SET_OK_NO_PROP_ERRORS (IMMEDIATE | LDST_CLASS_DECO | \
+ LDST_SRCDST_WORD_DECOCTRL | \
+ (LDOFF_CHG_SHARE_OK_NO_PROP << \
+ LDST_OFFSET_SHIFT))
#define DISABLE_AUTO_INFO_FIFO (IMMEDIATE | LDST_CLASS_DECO | \
LDST_SRCDST_WORD_DECOCTRL | \
(LDOFF_DISABLE_AUTO_NFIFO << LDST_OFFSET_SHIFT))
diff --git a/drivers/crypto/caam/regs.h b/drivers/crypto/caam/regs.h
index aee394e39056..e9f7a70cdd5e 100644
--- a/drivers/crypto/caam/regs.h
+++ b/drivers/crypto/caam/regs.h
@@ -657,7 +657,6 @@ struct caam_full {
u64 rsvd[512];
struct caam_assurance assure;
struct caam_queue_if qi;
- struct caam_deco *deco;
};
#endif /* REGS_H */
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index dcd8babae9eb..597235a2f8f9 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
@@ -1128,17 +1128,7 @@ static struct platform_driver marvell_crypto = {
};
MODULE_ALIAS("platform:mv_crypto");
-static int __init mv_crypto_init(void)
-{
- return platform_driver_register(&marvell_crypto);
-}
-module_init(mv_crypto_init);
-
-static void __exit mv_crypto_exit(void)
-{
- platform_driver_unregister(&marvell_crypto);
-}
-module_exit(mv_crypto_exit);
+module_platform_driver(marvell_crypto);
MODULE_AUTHOR("Sebastian Andrzej Siewior <sebastian@breakpoint.cc>");
MODULE_DESCRIPTION("Support for Marvell's cryptographic engine");
diff --git a/drivers/crypto/picoxcell_crypto.c b/drivers/crypto/picoxcell_crypto.c
index a2b553eabbdb..58480d009324 100644
--- a/drivers/crypto/picoxcell_crypto.c
+++ b/drivers/crypto/picoxcell_crypto.c
@@ -873,7 +873,7 @@ static int spacc_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
* request for any other size (192 bits) then we need to do a software
* fallback.
*/
- if ((len != AES_KEYSIZE_128 || len != AES_KEYSIZE_256) &&
+ if (len != AES_KEYSIZE_128 && len != AES_KEYSIZE_256 &&
ctx->sw_cipher) {
/*
* Set the fallback transform to use the same request flags as
@@ -886,7 +886,7 @@ static int spacc_aes_setkey(struct crypto_ablkcipher *cipher, const u8 *key,
err = crypto_ablkcipher_setkey(ctx->sw_cipher, key, len);
if (err)
goto sw_setkey_failed;
- } else if ((len != AES_KEYSIZE_128 || len != AES_KEYSIZE_256) &&
+ } else if (len != AES_KEYSIZE_128 && len != AES_KEYSIZE_256 &&
!ctx->sw_cipher)
err = -EINVAL;
@@ -1854,17 +1854,7 @@ static struct platform_driver spacc_driver = {
.id_table = spacc_id_table,
};
-static int __init spacc_init(void)
-{
- return platform_driver_register(&spacc_driver);
-}
-module_init(spacc_init);
-
-static void __exit spacc_exit(void)
-{
- platform_driver_unregister(&spacc_driver);
-}
-module_exit(spacc_exit);
+module_platform_driver(spacc_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Jamie Iles");
diff --git a/drivers/crypto/s5p-sss.c b/drivers/crypto/s5p-sss.c
index 8115417a1c93..3376bca200fc 100644
--- a/drivers/crypto/s5p-sss.c
+++ b/drivers/crypto/s5p-sss.c
@@ -683,18 +683,7 @@ static struct platform_driver s5p_aes_crypto = {
},
};
-static int __init s5p_aes_mod_init(void)
-{
- return platform_driver_register(&s5p_aes_crypto);
-}
-
-static void __exit s5p_aes_mod_exit(void)
-{
- platform_driver_unregister(&s5p_aes_crypto);
-}
-
-module_init(s5p_aes_mod_init);
-module_exit(s5p_aes_mod_exit);
+module_platform_driver(s5p_aes_crypto);
MODULE_DESCRIPTION("S5PV210 AES hw acceleration support.");
MODULE_LICENSE("GPL v2");
diff --git a/drivers/crypto/talitos.c b/drivers/crypto/talitos.c
index dbe76b5df9cf..2d8c78901686 100644
--- a/drivers/crypto/talitos.c
+++ b/drivers/crypto/talitos.c
@@ -99,6 +99,8 @@ struct talitos_request {
/* per-channel fifo management */
struct talitos_channel {
+ void __iomem *reg;
+
/* request fifo */
struct talitos_request *fifo;
@@ -120,7 +122,7 @@ struct talitos_private {
struct device *dev;
struct platform_device *ofdev;
void __iomem *reg;
- int irq;
+ int irq[2];
/* SEC version geometry (from device tree node) */
unsigned int num_channels;
@@ -144,7 +146,7 @@ struct talitos_private {
atomic_t last_chan ____cacheline_aligned;
/* request callback tasklet */
- struct tasklet_struct done_task;
+ struct tasklet_struct done_task[2];
/* list of registered algorithms */
struct list_head alg_list;
@@ -157,6 +159,7 @@ struct talitos_private {
#define TALITOS_FTR_SRC_LINK_TBL_LEN_INCLUDES_EXTENT 0x00000001
#define TALITOS_FTR_HW_AUTH_CHECK 0x00000002
#define TALITOS_FTR_SHA224_HWINIT 0x00000004
+#define TALITOS_FTR_HMAC_OK 0x00000008
static void to_talitos_ptr(struct talitos_ptr *talitos_ptr, dma_addr_t dma_addr)
{
@@ -196,9 +199,9 @@ static int reset_channel(struct device *dev, int ch)
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
- setbits32(priv->reg + TALITOS_CCCR(ch), TALITOS_CCCR_RESET);
+ setbits32(priv->chan[ch].reg + TALITOS_CCCR, TALITOS_CCCR_RESET);
- while ((in_be32(priv->reg + TALITOS_CCCR(ch)) & TALITOS_CCCR_RESET)
+ while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) & TALITOS_CCCR_RESET)
&& --timeout)
cpu_relax();
@@ -208,12 +211,12 @@ static int reset_channel(struct device *dev, int ch)
}
/* set 36-bit addressing, done writeback enable and done IRQ enable */
- setbits32(priv->reg + TALITOS_CCCR_LO(ch), TALITOS_CCCR_LO_EAE |
+ setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, TALITOS_CCCR_LO_EAE |
TALITOS_CCCR_LO_CDWE | TALITOS_CCCR_LO_CDIE);
/* and ICCR writeback, if available */
if (priv->features & TALITOS_FTR_HW_AUTH_CHECK)
- setbits32(priv->reg + TALITOS_CCCR_LO(ch),
+ setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO,
TALITOS_CCCR_LO_IWSE);
return 0;
@@ -223,13 +226,19 @@ static int reset_device(struct device *dev)
{
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
+ u32 mcr = TALITOS_MCR_SWR;
- setbits32(priv->reg + TALITOS_MCR, TALITOS_MCR_SWR);
+ setbits32(priv->reg + TALITOS_MCR, mcr);
while ((in_be32(priv->reg + TALITOS_MCR) & TALITOS_MCR_SWR)
&& --timeout)
cpu_relax();
+ if (priv->irq[1]) {
+ mcr = TALITOS_MCR_RCA1 | TALITOS_MCR_RCA3;
+ setbits32(priv->reg + TALITOS_MCR, mcr);
+ }
+
if (timeout == 0) {
dev_err(dev, "failed to reset device\n");
return -EIO;
@@ -327,8 +336,9 @@ static int talitos_submit(struct device *dev, int ch, struct talitos_desc *desc,
/* GO! */
wmb();
- out_be32(priv->reg + TALITOS_FF(ch), upper_32_bits(request->dma_desc));
- out_be32(priv->reg + TALITOS_FF_LO(ch),
+ out_be32(priv->chan[ch].reg + TALITOS_FF,
+ upper_32_bits(request->dma_desc));
+ out_be32(priv->chan[ch].reg + TALITOS_FF_LO,
lower_32_bits(request->dma_desc));
spin_unlock_irqrestore(&priv->chan[ch].head_lock, flags);
@@ -397,21 +407,32 @@ static void flush_channel(struct device *dev, int ch, int error, int reset_ch)
/*
* process completed requests for channels that have done status
*/
-static void talitos_done(unsigned long data)
-{
- struct device *dev = (struct device *)data;
- struct talitos_private *priv = dev_get_drvdata(dev);
- int ch;
-
- for (ch = 0; ch < priv->num_channels; ch++)
- flush_channel(dev, ch, 0, 0);
-
- /* At this point, all completed channels have been processed.
- * Unmask done interrupts for channels completed later on.
- */
- setbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_INIT);
- setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT);
+#define DEF_TALITOS_DONE(name, ch_done_mask) \
+static void talitos_done_##name(unsigned long data) \
+{ \
+ struct device *dev = (struct device *)data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ \
+ if (ch_done_mask & 1) \
+ flush_channel(dev, 0, 0, 0); \
+ if (priv->num_channels == 1) \
+ goto out; \
+ if (ch_done_mask & (1 << 2)) \
+ flush_channel(dev, 1, 0, 0); \
+ if (ch_done_mask & (1 << 4)) \
+ flush_channel(dev, 2, 0, 0); \
+ if (ch_done_mask & (1 << 6)) \
+ flush_channel(dev, 3, 0, 0); \
+ \
+out: \
+ /* At this point, all completed channels have been processed */ \
+ /* Unmask done interrupts for channels completed later on. */ \
+ setbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
+ setbits32(priv->reg + TALITOS_IMR_LO, TALITOS_IMR_LO_INIT); \
}
+DEF_TALITOS_DONE(4ch, TALITOS_ISR_4CHDONE)
+DEF_TALITOS_DONE(ch0_2, TALITOS_ISR_CH_0_2_DONE)
+DEF_TALITOS_DONE(ch1_3, TALITOS_ISR_CH_1_3_DONE)
/*
* locate current (offending) descriptor
@@ -422,7 +443,7 @@ static u32 current_desc_hdr(struct device *dev, int ch)
int tail = priv->chan[ch].tail;
dma_addr_t cur_desc;
- cur_desc = in_be32(priv->reg + TALITOS_CDPR_LO(ch));
+ cur_desc = in_be32(priv->chan[ch].reg + TALITOS_CDPR_LO);
while (priv->chan[ch].fifo[tail].dma_desc != cur_desc) {
tail = (tail + 1) & (priv->fifo_len - 1);
@@ -444,7 +465,7 @@ static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
int i;
if (!desc_hdr)
- desc_hdr = in_be32(priv->reg + TALITOS_DESCBUF(ch));
+ desc_hdr = in_be32(priv->chan[ch].reg + TALITOS_DESCBUF);
switch (desc_hdr & DESC_HDR_SEL0_MASK) {
case DESC_HDR_SEL0_AFEU:
@@ -506,16 +527,15 @@ static void report_eu_error(struct device *dev, int ch, u32 desc_hdr)
for (i = 0; i < 8; i++)
dev_err(dev, "DESCBUF 0x%08x_%08x\n",
- in_be32(priv->reg + TALITOS_DESCBUF(ch) + 8*i),
- in_be32(priv->reg + TALITOS_DESCBUF_LO(ch) + 8*i));
+ in_be32(priv->chan[ch].reg + TALITOS_DESCBUF + 8*i),
+ in_be32(priv->chan[ch].reg + TALITOS_DESCBUF_LO + 8*i));
}
/*
* recover from error interrupts
*/
-static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
+static void talitos_error(struct device *dev, u32 isr, u32 isr_lo)
{
- struct device *dev = (struct device *)data;
struct talitos_private *priv = dev_get_drvdata(dev);
unsigned int timeout = TALITOS_TIMEOUT;
int ch, error, reset_dev = 0, reset_ch = 0;
@@ -528,8 +548,8 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
error = -EINVAL;
- v = in_be32(priv->reg + TALITOS_CCPSR(ch));
- v_lo = in_be32(priv->reg + TALITOS_CCPSR_LO(ch));
+ v = in_be32(priv->chan[ch].reg + TALITOS_CCPSR);
+ v_lo = in_be32(priv->chan[ch].reg + TALITOS_CCPSR_LO);
if (v_lo & TALITOS_CCPSR_LO_DOF) {
dev_err(dev, "double fetch fifo overflow error\n");
@@ -567,10 +587,10 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
if (reset_ch) {
reset_channel(dev, ch);
} else {
- setbits32(priv->reg + TALITOS_CCCR(ch),
+ setbits32(priv->chan[ch].reg + TALITOS_CCCR,
TALITOS_CCCR_CONT);
- setbits32(priv->reg + TALITOS_CCCR_LO(ch), 0);
- while ((in_be32(priv->reg + TALITOS_CCCR(ch)) &
+ setbits32(priv->chan[ch].reg + TALITOS_CCCR_LO, 0);
+ while ((in_be32(priv->chan[ch].reg + TALITOS_CCCR) &
TALITOS_CCCR_CONT) && --timeout)
cpu_relax();
if (timeout == 0) {
@@ -580,7 +600,7 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
}
}
}
- if (reset_dev || isr & ~TALITOS_ISR_CHERR || isr_lo) {
+ if (reset_dev || isr & ~TALITOS_ISR_4CHERR || isr_lo) {
dev_err(dev, "done overflow, internal time out, or rngu error: "
"ISR 0x%08x_%08x\n", isr, isr_lo);
@@ -593,30 +613,35 @@ static void talitos_error(unsigned long data, u32 isr, u32 isr_lo)
}
}
-static irqreturn_t talitos_interrupt(int irq, void *data)
-{
- struct device *dev = data;
- struct talitos_private *priv = dev_get_drvdata(dev);
- u32 isr, isr_lo;
-
- isr = in_be32(priv->reg + TALITOS_ISR);
- isr_lo = in_be32(priv->reg + TALITOS_ISR_LO);
- /* Acknowledge interrupt */
- out_be32(priv->reg + TALITOS_ICR, isr);
- out_be32(priv->reg + TALITOS_ICR_LO, isr_lo);
-
- if (unlikely((isr & ~TALITOS_ISR_CHDONE) || isr_lo))
- talitos_error((unsigned long)data, isr, isr_lo);
- else
- if (likely(isr & TALITOS_ISR_CHDONE)) {
- /* mask further done interrupts. */
- clrbits32(priv->reg + TALITOS_IMR, TALITOS_IMR_DONE);
- /* done_task will unmask done interrupts at exit */
- tasklet_schedule(&priv->done_task);
- }
-
- return (isr || isr_lo) ? IRQ_HANDLED : IRQ_NONE;
+#define DEF_TALITOS_INTERRUPT(name, ch_done_mask, ch_err_mask, tlet) \
+static irqreturn_t talitos_interrupt_##name(int irq, void *data) \
+{ \
+ struct device *dev = data; \
+ struct talitos_private *priv = dev_get_drvdata(dev); \
+ u32 isr, isr_lo; \
+ \
+ isr = in_be32(priv->reg + TALITOS_ISR); \
+ isr_lo = in_be32(priv->reg + TALITOS_ISR_LO); \
+ /* Acknowledge interrupt */ \
+ out_be32(priv->reg + TALITOS_ICR, isr & (ch_done_mask | ch_err_mask)); \
+ out_be32(priv->reg + TALITOS_ICR_LO, isr_lo); \
+ \
+ if (unlikely((isr & ~TALITOS_ISR_4CHDONE) & ch_err_mask || isr_lo)) \
+ talitos_error(dev, isr, isr_lo); \
+ else \
+ if (likely(isr & ch_done_mask)) { \
+ /* mask further done interrupts. */ \
+ clrbits32(priv->reg + TALITOS_IMR, ch_done_mask); \
+ /* done_task will unmask done interrupts at exit */ \
+ tasklet_schedule(&priv->done_task[tlet]); \
+ } \
+ \
+ return (isr & (ch_done_mask | ch_err_mask) || isr_lo) ? IRQ_HANDLED : \
+ IRQ_NONE; \
}
+DEF_TALITOS_INTERRUPT(4ch, TALITOS_ISR_4CHDONE, TALITOS_ISR_4CHERR, 0)
+DEF_TALITOS_INTERRUPT(ch0_2, TALITOS_ISR_CH_0_2_DONE, TALITOS_ISR_CH_0_2_ERR, 0)
+DEF_TALITOS_INTERRUPT(ch1_3, TALITOS_ISR_CH_1_3_DONE, TALITOS_ISR_CH_1_3_ERR, 1)
/*
* hwrng
@@ -1874,6 +1899,97 @@ static int ahash_digest(struct ahash_request *areq)
return ahash_process_req(areq, areq->nbytes);
}
+struct keyhash_result {
+ struct completion completion;
+ int err;
+};
+
+static void keyhash_complete(struct crypto_async_request *req, int err)
+{
+ struct keyhash_result *res = req->data;
+
+ if (err == -EINPROGRESS)
+ return;
+
+ res->err = err;
+ complete(&res->completion);
+}
+
+static int keyhash(struct crypto_ahash *tfm, const u8 *key, unsigned int keylen,
+ u8 *hash)
+{
+ struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
+
+ struct scatterlist sg[1];
+ struct ahash_request *req;
+ struct keyhash_result hresult;
+ int ret;
+
+ init_completion(&hresult.completion);
+
+ req = ahash_request_alloc(tfm, GFP_KERNEL);
+ if (!req)
+ return -ENOMEM;
+
+ /* Keep tfm keylen == 0 during hash of the long key */
+ ctx->keylen = 0;
+ ahash_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ keyhash_complete, &hresult);
+
+ sg_init_one(&sg[0], key, keylen);
+
+ ahash_request_set_crypt(req, sg, hash, keylen);
+ ret = crypto_ahash_digest(req);
+ switch (ret) {
+ case 0:
+ break;
+ case -EINPROGRESS:
+ case -EBUSY:
+ ret = wait_for_completion_interruptible(
+ &hresult.completion);
+ if (!ret)
+ ret = hresult.err;
+ break;
+ default:
+ break;
+ }
+ ahash_request_free(req);
+
+ return ret;
+}
+
+static int ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
+ unsigned int keylen)
+{
+ struct talitos_ctx *ctx = crypto_tfm_ctx(crypto_ahash_tfm(tfm));
+ unsigned int blocksize =
+ crypto_tfm_alg_blocksize(crypto_ahash_tfm(tfm));
+ unsigned int digestsize = crypto_ahash_digestsize(tfm);
+ unsigned int keysize = keylen;
+ u8 hash[SHA512_DIGEST_SIZE];
+ int ret;
+
+ if (keylen <= blocksize)
+ memcpy(ctx->key, key, keysize);
+ else {
+ /* Must get the hash of the long key */
+ ret = keyhash(tfm, key, keylen, hash);
+
+ if (ret) {
+ crypto_ahash_set_flags(tfm, CRYPTO_TFM_RES_BAD_KEY_LEN);
+ return -EINVAL;
+ }
+
+ keysize = digestsize;
+ memcpy(ctx->key, hash, digestsize);
+ }
+
+ ctx->keylen = keysize;
+
+ return 0;
+}
+
+
struct talitos_alg_template {
u32 type;
union {
@@ -2217,6 +2333,138 @@ static struct talitos_alg_template driver_algs[] = {
DESC_HDR_SEL0_MDEUB |
DESC_HDR_MODE0_MDEUB_SHA512,
},
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = MD5_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(md5)",
+ .cra_driver_name = "hmac-md5-talitos",
+ .cra_blocksize = MD5_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUA |
+ DESC_HDR_MODE0_MDEU_MD5,
+ },
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = SHA1_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(sha1)",
+ .cra_driver_name = "hmac-sha1-talitos",
+ .cra_blocksize = SHA1_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUA |
+ DESC_HDR_MODE0_MDEU_SHA1,
+ },
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = SHA224_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(sha224)",
+ .cra_driver_name = "hmac-sha224-talitos",
+ .cra_blocksize = SHA224_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUA |
+ DESC_HDR_MODE0_MDEU_SHA224,
+ },
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = SHA256_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(sha256)",
+ .cra_driver_name = "hmac-sha256-talitos",
+ .cra_blocksize = SHA256_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUA |
+ DESC_HDR_MODE0_MDEU_SHA256,
+ },
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = SHA384_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(sha384)",
+ .cra_driver_name = "hmac-sha384-talitos",
+ .cra_blocksize = SHA384_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUB |
+ DESC_HDR_MODE0_MDEUB_SHA384,
+ },
+ { .type = CRYPTO_ALG_TYPE_AHASH,
+ .alg.hash = {
+ .init = ahash_init,
+ .update = ahash_update,
+ .final = ahash_final,
+ .finup = ahash_finup,
+ .digest = ahash_digest,
+ .setkey = ahash_setkey,
+ .halg.digestsize = SHA512_DIGEST_SIZE,
+ .halg.base = {
+ .cra_name = "hmac(sha512)",
+ .cra_driver_name = "hmac-sha512-talitos",
+ .cra_blocksize = SHA512_BLOCK_SIZE,
+ .cra_flags = CRYPTO_ALG_TYPE_AHASH |
+ CRYPTO_ALG_ASYNC,
+ .cra_type = &crypto_ahash_type
+ }
+ },
+ .desc_hdr_template = DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
+ DESC_HDR_SEL0_MDEUB |
+ DESC_HDR_MODE0_MDEUB_SHA512,
+ }
};
struct talitos_crypto_alg {
@@ -2331,12 +2579,15 @@ static int talitos_remove(struct platform_device *ofdev)
kfree(priv->chan);
- if (priv->irq != NO_IRQ) {
- free_irq(priv->irq, dev);
- irq_dispose_mapping(priv->irq);
- }
+ for (i = 0; i < 2; i++)
+ if (priv->irq[i]) {
+ free_irq(priv->irq[i], dev);
+ irq_dispose_mapping(priv->irq[i]);
+ }
- tasklet_kill(&priv->done_task);
+ tasklet_kill(&priv->done_task[0]);
+ if (priv->irq[1])
+ tasklet_kill(&priv->done_task[1]);
iounmap(priv->reg);
@@ -2373,8 +2624,14 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
case CRYPTO_ALG_TYPE_AHASH:
alg = &t_alg->algt.alg.hash.halg.base;
alg->cra_init = talitos_cra_init_ahash;
+ if (!(priv->features & TALITOS_FTR_HMAC_OK) &&
+ !strncmp(alg->cra_name, "hmac", 4)) {
+ kfree(t_alg);
+ return ERR_PTR(-ENOTSUPP);
+ }
if (!(priv->features & TALITOS_FTR_SHA224_HWINIT) &&
- !strcmp(alg->cra_name, "sha224")) {
+ (!strcmp(alg->cra_name, "sha224") ||
+ !strcmp(alg->cra_name, "hmac(sha224)"))) {
t_alg->algt.alg.hash.init = ahash_init_sha224_swinit;
t_alg->algt.desc_hdr_template =
DESC_HDR_TYPE_COMMON_NONSNOOP_NO_AFEU |
@@ -2397,6 +2654,54 @@ static struct talitos_crypto_alg *talitos_alg_alloc(struct device *dev,
return t_alg;
}
+static int talitos_probe_irq(struct platform_device *ofdev)
+{
+ struct device *dev = &ofdev->dev;
+ struct device_node *np = ofdev->dev.of_node;
+ struct talitos_private *priv = dev_get_drvdata(dev);
+ int err;
+
+ priv->irq[0] = irq_of_parse_and_map(np, 0);
+ if (!priv->irq[0]) {
+ dev_err(dev, "failed to map irq\n");
+ return -EINVAL;
+ }
+
+ priv->irq[1] = irq_of_parse_and_map(np, 1);
+
+ /* get the primary irq line */
+ if (!priv->irq[1]) {
+ err = request_irq(priv->irq[0], talitos_interrupt_4ch, 0,
+ dev_driver_string(dev), dev);
+ goto primary_out;
+ }
+
+ err = request_irq(priv->irq[0], talitos_interrupt_ch0_2, 0,
+ dev_driver_string(dev), dev);
+ if (err)
+ goto primary_out;
+
+ /* get the secondary irq line */
+ err = request_irq(priv->irq[1], talitos_interrupt_ch1_3, 0,
+ dev_driver_string(dev), dev);
+ if (err) {
+ dev_err(dev, "failed to request secondary irq\n");
+ irq_dispose_mapping(priv->irq[1]);
+ priv->irq[1] = 0;
+ }
+
+ return err;
+
+primary_out:
+ if (err) {
+ dev_err(dev, "failed to request primary irq\n");
+ irq_dispose_mapping(priv->irq[0]);
+ priv->irq[0] = 0;
+ }
+
+ return err;
+}
+
static int talitos_probe(struct platform_device *ofdev)
{
struct device *dev = &ofdev->dev;
@@ -2413,28 +2718,22 @@ static int talitos_probe(struct platform_device *ofdev)
priv->ofdev = ofdev;
- tasklet_init(&priv->done_task, talitos_done, (unsigned long)dev);
-
- INIT_LIST_HEAD(&priv->alg_list);
-
- priv->irq = irq_of_parse_and_map(np, 0);
-
- if (priv->irq == NO_IRQ) {
- dev_err(dev, "failed to map irq\n");
- err = -EINVAL;
+ err = talitos_probe_irq(ofdev);
+ if (err)
goto err_out;
- }
- /* get the irq line */
- err = request_irq(priv->irq, talitos_interrupt, 0,
- dev_driver_string(dev), dev);
- if (err) {
- dev_err(dev, "failed to request irq %d\n", priv->irq);
- irq_dispose_mapping(priv->irq);
- priv->irq = NO_IRQ;
- goto err_out;
+ if (!priv->irq[1]) {
+ tasklet_init(&priv->done_task[0], talitos_done_4ch,
+ (unsigned long)dev);
+ } else {
+ tasklet_init(&priv->done_task[0], talitos_done_ch0_2,
+ (unsigned long)dev);
+ tasklet_init(&priv->done_task[1], talitos_done_ch1_3,
+ (unsigned long)dev);
}
+ INIT_LIST_HEAD(&priv->alg_list);
+
priv->reg = of_iomap(np, 0);
if (!priv->reg) {
dev_err(dev, "failed to of_iomap\n");
@@ -2471,7 +2770,8 @@ static int talitos_probe(struct platform_device *ofdev)
if (of_device_is_compatible(np, "fsl,sec2.1"))
priv->features |= TALITOS_FTR_HW_AUTH_CHECK |
- TALITOS_FTR_SHA224_HWINIT;
+ TALITOS_FTR_SHA224_HWINIT |
+ TALITOS_FTR_HMAC_OK;
priv->chan = kzalloc(sizeof(struct talitos_channel) *
priv->num_channels, GFP_KERNEL);
@@ -2482,6 +2782,12 @@ static int talitos_probe(struct platform_device *ofdev)
}
for (i = 0; i < priv->num_channels; i++) {
+ priv->chan[i].reg = priv->reg + TALITOS_CH_STRIDE * (i + 1);
+ if (!priv->irq[1] || !(i & 1))
+ priv->chan[i].reg += TALITOS_CH_BASE_OFFSET;
+ }
+
+ for (i = 0; i < priv->num_channels; i++) {
spin_lock_init(&priv->chan[i].head_lock);
spin_lock_init(&priv->chan[i].tail_lock);
}
@@ -2530,6 +2836,8 @@ static int talitos_probe(struct platform_device *ofdev)
t_alg = talitos_alg_alloc(dev, &driver_algs[i]);
if (IS_ERR(t_alg)) {
err = PTR_ERR(t_alg);
+ if (err == -ENOTSUPP)
+ continue;
goto err_out;
}
@@ -2551,12 +2859,13 @@ static int talitos_probe(struct platform_device *ofdev)
dev_err(dev, "%s alg registration failed\n",
name);
kfree(t_alg);
- } else {
+ } else
list_add_tail(&t_alg->entry, &priv->alg_list);
- dev_info(dev, "%s\n", name);
- }
}
}
+ if (!list_empty(&priv->alg_list))
+ dev_info(dev, "%s algorithms registered in /proc/crypto\n",
+ (char *)of_get_property(np, "compatible", NULL));
return 0;
@@ -2584,17 +2893,7 @@ static struct platform_driver talitos_driver = {
.remove = talitos_remove,
};
-static int __init talitos_init(void)
-{
- return platform_driver_register(&talitos_driver);
-}
-module_init(talitos_init);
-
-static void __exit talitos_exit(void)
-{
- platform_driver_unregister(&talitos_driver);
-}
-module_exit(talitos_exit);
+module_platform_driver(talitos_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Kim Phillips <kim.phillips@freescale.com>");
diff --git a/drivers/crypto/talitos.h b/drivers/crypto/talitos.h
index 0b746aca4587..3c173954ef29 100644
--- a/drivers/crypto/talitos.h
+++ b/drivers/crypto/talitos.h
@@ -1,7 +1,7 @@
/*
* Freescale SEC (talitos) device register and descriptor header defines
*
- * Copyright (c) 2006-2010 Freescale Semiconductor, Inc.
+ * Copyright (c) 2006-2011 Freescale Semiconductor, Inc.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -34,28 +34,37 @@
/* global register offset addresses */
#define TALITOS_MCR 0x1030 /* master control register */
-#define TALITOS_MCR_LO 0x1038
+#define TALITOS_MCR_RCA0 (1 << 15) /* remap channel 0 */
+#define TALITOS_MCR_RCA1 (1 << 14) /* remap channel 1 */
+#define TALITOS_MCR_RCA2 (1 << 13) /* remap channel 2 */
+#define TALITOS_MCR_RCA3 (1 << 12) /* remap channel 3 */
#define TALITOS_MCR_SWR 0x1 /* s/w reset */
+#define TALITOS_MCR_LO 0x1034
#define TALITOS_IMR 0x1008 /* interrupt mask register */
#define TALITOS_IMR_INIT 0x100ff /* enable channel IRQs */
#define TALITOS_IMR_DONE 0x00055 /* done IRQs */
#define TALITOS_IMR_LO 0x100C
#define TALITOS_IMR_LO_INIT 0x20000 /* allow RNGU error IRQs */
#define TALITOS_ISR 0x1010 /* interrupt status register */
-#define TALITOS_ISR_CHERR 0xaa /* channel errors mask */
-#define TALITOS_ISR_CHDONE 0x55 /* channel done mask */
+#define TALITOS_ISR_4CHERR 0xaa /* 4 channel errors mask */
+#define TALITOS_ISR_4CHDONE 0x55 /* 4 channel done mask */
+#define TALITOS_ISR_CH_0_2_ERR 0x22 /* channels 0, 2 errors mask */
+#define TALITOS_ISR_CH_0_2_DONE 0x11 /* channels 0, 2 done mask */
+#define TALITOS_ISR_CH_1_3_ERR 0x88 /* channels 1, 3 errors mask */
+#define TALITOS_ISR_CH_1_3_DONE 0x44 /* channels 1, 3 done mask */
#define TALITOS_ISR_LO 0x1014
#define TALITOS_ICR 0x1018 /* interrupt clear register */
#define TALITOS_ICR_LO 0x101C
/* channel register address stride */
+#define TALITOS_CH_BASE_OFFSET 0x1000 /* default channel map base */
#define TALITOS_CH_STRIDE 0x100
/* channel configuration register */
-#define TALITOS_CCCR(ch) (ch * TALITOS_CH_STRIDE + 0x1108)
+#define TALITOS_CCCR 0x8
#define TALITOS_CCCR_CONT 0x2 /* channel continue */
#define TALITOS_CCCR_RESET 0x1 /* channel reset */
-#define TALITOS_CCCR_LO(ch) (ch * TALITOS_CH_STRIDE + 0x110c)
+#define TALITOS_CCCR_LO 0xc
#define TALITOS_CCCR_LO_IWSE 0x80 /* chan. ICCR writeback enab. */
#define TALITOS_CCCR_LO_EAE 0x20 /* extended address enable */
#define TALITOS_CCCR_LO_CDWE 0x10 /* chan. done writeback enab. */
@@ -63,8 +72,8 @@
#define TALITOS_CCCR_LO_CDIE 0x2 /* channel done IRQ enable */
/* CCPSR: channel pointer status register */
-#define TALITOS_CCPSR(ch) (ch * TALITOS_CH_STRIDE + 0x1110)
-#define TALITOS_CCPSR_LO(ch) (ch * TALITOS_CH_STRIDE + 0x1114)
+#define TALITOS_CCPSR 0x10
+#define TALITOS_CCPSR_LO 0x14
#define TALITOS_CCPSR_LO_DOF 0x8000 /* double FF write oflow error */
#define TALITOS_CCPSR_LO_SOF 0x4000 /* single FF write oflow error */
#define TALITOS_CCPSR_LO_MDTE 0x2000 /* master data transfer error */
@@ -79,24 +88,24 @@
#define TALITOS_CCPSR_LO_SRL 0x0010 /* scatter return/length error */
/* channel fetch fifo register */
-#define TALITOS_FF(ch) (ch * TALITOS_CH_STRIDE + 0x1148)
-#define TALITOS_FF_LO(ch) (ch * TALITOS_CH_STRIDE + 0x114c)
+#define TALITOS_FF 0x48
+#define TALITOS_FF_LO 0x4c
/* current descriptor pointer register */
-#define TALITOS_CDPR(ch) (ch * TALITOS_CH_STRIDE + 0x1140)
-#define TALITOS_CDPR_LO(ch) (ch * TALITOS_CH_STRIDE + 0x1144)
+#define TALITOS_CDPR 0x40
+#define TALITOS_CDPR_LO 0x44
/* descriptor buffer register */
-#define TALITOS_DESCBUF(ch) (ch * TALITOS_CH_STRIDE + 0x1180)
-#define TALITOS_DESCBUF_LO(ch) (ch * TALITOS_CH_STRIDE + 0x1184)
+#define TALITOS_DESCBUF 0x80
+#define TALITOS_DESCBUF_LO 0x84
/* gather link table */
-#define TALITOS_GATHER(ch) (ch * TALITOS_CH_STRIDE + 0x11c0)
-#define TALITOS_GATHER_LO(ch) (ch * TALITOS_CH_STRIDE + 0x11c4)
+#define TALITOS_GATHER 0xc0
+#define TALITOS_GATHER_LO 0xc4
/* scatter link table */
-#define TALITOS_SCATTER(ch) (ch * TALITOS_CH_STRIDE + 0x11e0)
-#define TALITOS_SCATTER_LO(ch) (ch * TALITOS_CH_STRIDE + 0x11e4)
+#define TALITOS_SCATTER 0xe0
+#define TALITOS_SCATTER_LO 0xe4
/* execution unit interrupt status registers */
#define TALITOS_DEUISR 0x2030 /* DES unit */
diff --git a/drivers/firmware/Kconfig b/drivers/firmware/Kconfig
index efba163595db..9b00072a020f 100644
--- a/drivers/firmware/Kconfig
+++ b/drivers/firmware/Kconfig
@@ -145,18 +145,6 @@ config ISCSI_IBFT
detect iSCSI boot parameters dynamically during system boot, say Y.
Otherwise, say N.
-config SIGMA
- tristate "SigmaStudio firmware loader"
- depends on I2C
- select CRC32
- default n
- help
- Enable helper functions for working with Analog Devices SigmaDSP
- parts and binary firmwares produced by Analog Devices SigmaStudio.
-
- If unsure, say N here. Drivers that need these helpers will select
- this option automatically.
-
source "drivers/firmware/google/Kconfig"
endmenu
diff --git a/drivers/firmware/Makefile b/drivers/firmware/Makefile
index 47338c979126..5a7e27399729 100644
--- a/drivers/firmware/Makefile
+++ b/drivers/firmware/Makefile
@@ -12,6 +12,5 @@ obj-$(CONFIG_DMIID) += dmi-id.o
obj-$(CONFIG_ISCSI_IBFT_FIND) += iscsi_ibft_find.o
obj-$(CONFIG_ISCSI_IBFT) += iscsi_ibft.o
obj-$(CONFIG_FIRMWARE_MEMMAP) += memmap.o
-obj-$(CONFIG_SIGMA) += sigma.o
obj-$(CONFIG_GOOGLE_FIRMWARE) += google/
diff --git a/drivers/firmware/sigma.c b/drivers/firmware/sigma.c
deleted file mode 100644
index 1eedb6f7fdab..000000000000
--- a/drivers/firmware/sigma.c
+++ /dev/null
@@ -1,153 +0,0 @@
-/*
- * Load Analog Devices SigmaStudio firmware files
- *
- * Copyright 2009-2011 Analog Devices Inc.
- *
- * Licensed under the GPL-2 or later.
- */
-
-#include <linux/crc32.h>
-#include <linux/delay.h>
-#include <linux/firmware.h>
-#include <linux/kernel.h>
-#include <linux/i2c.h>
-#include <linux/module.h>
-#include <linux/sigma.h>
-
-static size_t sigma_action_size(struct sigma_action *sa)
-{
- size_t payload = 0;
-
- switch (sa->instr) {
- case SIGMA_ACTION_WRITEXBYTES:
- case SIGMA_ACTION_WRITESINGLE:
- case SIGMA_ACTION_WRITESAFELOAD:
- payload = sigma_action_len(sa);
- break;
- default:
- break;
- }
-
- payload = ALIGN(payload, 2);
-
- return payload + sizeof(struct sigma_action);
-}
-
-/*
- * Returns a negative error value in case of an error, 0 if processing of
- * the firmware should be stopped after this action, 1 otherwise.
- */
-static int
-process_sigma_action(struct i2c_client *client, struct sigma_action *sa)
-{
- size_t len = sigma_action_len(sa);
- int ret;
-
- pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
- sa->instr, sa->addr, len);
-
- switch (sa->instr) {
- case SIGMA_ACTION_WRITEXBYTES:
- case SIGMA_ACTION_WRITESINGLE:
- case SIGMA_ACTION_WRITESAFELOAD:
- ret = i2c_master_send(client, (void *)&sa->addr, len);
- if (ret < 0)
- return -EINVAL;
- break;
- case SIGMA_ACTION_DELAY:
- udelay(len);
- len = 0;
- break;
- case SIGMA_ACTION_END:
- return 0;
- default:
- return -EINVAL;
- }
-
- return 1;
-}
-
-static int
-process_sigma_actions(struct i2c_client *client, struct sigma_firmware *ssfw)
-{
- struct sigma_action *sa;
- size_t size;
- int ret;
-
- while (ssfw->pos + sizeof(*sa) <= ssfw->fw->size) {
- sa = (struct sigma_action *)(ssfw->fw->data + ssfw->pos);
-
- size = sigma_action_size(sa);
- ssfw->pos += size;
- if (ssfw->pos > ssfw->fw->size || size == 0)
- break;
-
- ret = process_sigma_action(client, sa);
-
- pr_debug("%s: action returned %i\n", __func__, ret);
-
- if (ret <= 0)
- return ret;
- }
-
- if (ssfw->pos != ssfw->fw->size)
- return -EINVAL;
-
- return 0;
-}
-
-int process_sigma_firmware(struct i2c_client *client, const char *name)
-{
- int ret;
- struct sigma_firmware_header *ssfw_head;
- struct sigma_firmware ssfw;
- const struct firmware *fw;
- u32 crc;
-
- pr_debug("%s: loading firmware %s\n", __func__, name);
-
- /* first load the blob */
- ret = request_firmware(&fw, name, &client->dev);
- if (ret) {
- pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
- return ret;
- }
- ssfw.fw = fw;
-
- /* then verify the header */
- ret = -EINVAL;
-
- /*
- * Reject too small or unreasonable large files. The upper limit has been
- * chosen a bit arbitrarily, but it should be enough for all practical
- * purposes and having the limit makes it easier to avoid integer
- * overflows later in the loading process.
- */
- if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000)
- goto done;
-
- ssfw_head = (void *)fw->data;
- if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic)))
- goto done;
-
- crc = crc32(0, fw->data + sizeof(*ssfw_head),
- fw->size - sizeof(*ssfw_head));
- pr_debug("%s: crc=%x\n", __func__, crc);
- if (crc != le32_to_cpu(ssfw_head->crc))
- goto done;
-
- ssfw.pos = sizeof(*ssfw_head);
-
- /* finally process all of the actions */
- ret = process_sigma_actions(client, &ssfw);
-
- done:
- release_firmware(fw);
-
- pr_debug("%s: loaded %s\n", __func__, name);
-
- return ret;
-}
-EXPORT_SYMBOL(process_sigma_firmware);
-
-MODULE_LICENSE("GPL");
diff --git a/drivers/hid/hid-wacom.c b/drivers/hid/hid-wacom.c
index f2183486a9b6..b47e58b52d9f 100644
--- a/drivers/hid/hid-wacom.c
+++ b/drivers/hid/hid-wacom.c
@@ -49,12 +49,14 @@ static unsigned short batcap[8] = { 1, 15, 25, 35, 50, 70, 100, 0 };
static enum power_supply_property wacom_battery_props[] = {
POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_CAPACITY
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_SCOPE,
};
static enum power_supply_property wacom_ac_props[] = {
POWER_SUPPLY_PROP_PRESENT,
- POWER_SUPPLY_PROP_ONLINE
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_SCOPE,
};
static int wacom_battery_get_property(struct power_supply *psy,
@@ -70,6 +72,9 @@ static int wacom_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_PRESENT:
val->intval = 1;
break;
+ case POWER_SUPPLY_PROP_SCOPE:
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ break;
case POWER_SUPPLY_PROP_CAPACITY:
/* show 100% battery capacity when charging */
if (power_state == 0)
@@ -101,6 +106,9 @@ static int wacom_ac_get_property(struct power_supply *psy,
else
val->intval = 0;
break;
+ case POWER_SUPPLY_PROP_SCOPE:
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ break;
default:
ret = -EINVAL;
break;
@@ -523,6 +531,8 @@ static int wacom_probe(struct hid_device *hdev,
wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wdata->battery.use_for_apm = 0;
+ power_supply_powers(&wdata->battery, &hdev->dev);
+
ret = power_supply_register(&hdev->dev, &wdata->battery);
if (ret) {
hid_warn(hdev, "can't create sysfs battery attribute, err: %d\n",
@@ -537,6 +547,8 @@ static int wacom_probe(struct hid_device *hdev,
wdata->ac.type = POWER_SUPPLY_TYPE_MAINS;
wdata->ac.use_for_apm = 0;
+ power_supply_powers(&wdata->battery, &hdev->dev);
+
ret = power_supply_register(&hdev->dev, &wdata->ac);
if (ret) {
hid_warn(hdev,
diff --git a/drivers/hid/hid-wiimote-core.c b/drivers/hid/hid-wiimote-core.c
index 61881b35c670..fc253b472f9d 100644
--- a/drivers/hid/hid-wiimote-core.c
+++ b/drivers/hid/hid-wiimote-core.c
@@ -52,7 +52,8 @@ static __u16 wiiproto_keymap[] = {
};
static enum power_supply_property wiimote_battery_props[] = {
- POWER_SUPPLY_PROP_CAPACITY
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_SCOPE,
};
static ssize_t wiimote_hid_send(struct hid_device *hdev, __u8 *buffer,
@@ -402,6 +403,11 @@ static int wiimote_battery_get_property(struct power_supply *psy,
int ret = 0, state;
unsigned long flags;
+ if (psp == POWER_SUPPLY_PROP_SCOPE) {
+ val->intval = POWER_SUPPLY_SCOPE_DEVICE;
+ return 0;
+ }
+
ret = wiimote_cmd_acquire(wdata);
if (ret)
return ret;
@@ -1220,6 +1226,8 @@ static int wiimote_hid_probe(struct hid_device *hdev,
wdata->battery.type = POWER_SUPPLY_TYPE_BATTERY;
wdata->battery.use_for_apm = 0;
+ power_supply_powers(&wdata->battery, &hdev->dev);
+
ret = power_supply_register(&wdata->hdev->dev, &wdata->battery);
if (ret) {
hid_err(hdev, "Cannot register battery device\n");
diff --git a/drivers/md/md.c b/drivers/md/md.c
index ca8527fe77eb..da52acb60f52 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -7382,6 +7382,7 @@ static int remove_and_add_spares(struct mddev *mddev)
{
struct md_rdev *rdev;
int spares = 0;
+ int removed = 0;
mddev->curr_resync_completed = 0;
@@ -7395,8 +7396,13 @@ static int remove_and_add_spares(struct mddev *mddev)
mddev, rdev) == 0) {
sysfs_unlink_rdev(mddev, rdev);
rdev->raid_disk = -1;
+ removed++;
}
}
+ if (removed)
+ sysfs_notify(&mddev->kobj, NULL,
+ "degraded");
+
list_for_each_entry(rdev, &mddev->disks, same_set) {
if (rdev->raid_disk >= 0 &&
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index cc24f0cb7ee3..a368db2431a5 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -531,8 +531,17 @@ static int read_balance(struct r1conf *conf, struct r1bio *r1_bio, int *max_sect
if (test_bit(WriteMostly, &rdev->flags)) {
/* Don't balance among write-mostly, just
* use the first as a last resort */
- if (best_disk < 0)
+ if (best_disk < 0) {
+ if (is_badblock(rdev, this_sector, sectors,
+ &first_bad, &bad_sectors)) {
+ if (first_bad < this_sector)
+ /* Cannot use this */
+ continue;
+ best_good_sectors = first_bad - this_sector;
+ } else
+ best_good_sectors = sectors;
best_disk = disk;
+ }
continue;
}
/* This is a reasonable device to use. It might
diff --git a/drivers/mfd/Kconfig b/drivers/mfd/Kconfig
index c8322eefc865..053208d31fb9 100644
--- a/drivers/mfd/Kconfig
+++ b/drivers/mfd/Kconfig
@@ -505,6 +505,7 @@ config MFD_WM8994
bool "Support Wolfson Microelectronics WM8994"
select MFD_CORE
select REGMAP_I2C
+ select REGMAP_IRQ
depends on I2C=y && GENERIC_HARDIRQS
help
The WM8994 is a highly integrated hi-fi CODEC designed for
diff --git a/drivers/mfd/Makefile b/drivers/mfd/Makefile
index d5f574306c7f..47591fc7d0d2 100644
--- a/drivers/mfd/Makefile
+++ b/drivers/mfd/Makefile
@@ -31,7 +31,7 @@ wm8350-objs := wm8350-core.o wm8350-regmap.o wm8350-gpio.o
wm8350-objs += wm8350-irq.o
obj-$(CONFIG_MFD_WM8350) += wm8350.o
obj-$(CONFIG_MFD_WM8350_I2C) += wm8350-i2c.o
-obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o
+obj-$(CONFIG_MFD_WM8994) += wm8994-core.o wm8994-irq.o wm8994-regmap.o
obj-$(CONFIG_TPS6105X) += tps6105x.o
obj-$(CONFIG_TPS65010) += tps65010.o
diff --git a/drivers/mfd/max8925-core.c b/drivers/mfd/max8925-core.c
index e1e59c92f758..ca881efedf75 100644
--- a/drivers/mfd/max8925-core.c
+++ b/drivers/mfd/max8925-core.c
@@ -210,21 +210,6 @@ static struct max8925_irq_data max8925_irqs[] = {
.mask_reg = MAX8925_CHG_IRQ1_MASK,
.offs = 1 << 2,
},
- [MAX8925_IRQ_VCHG_USB_OVP] = {
- .reg = MAX8925_CHG_IRQ1,
- .mask_reg = MAX8925_CHG_IRQ1_MASK,
- .offs = 1 << 3,
- },
- [MAX8925_IRQ_VCHG_USB_F] = {
- .reg = MAX8925_CHG_IRQ1,
- .mask_reg = MAX8925_CHG_IRQ1_MASK,
- .offs = 1 << 4,
- },
- [MAX8925_IRQ_VCHG_USB_R] = {
- .reg = MAX8925_CHG_IRQ1,
- .mask_reg = MAX8925_CHG_IRQ1_MASK,
- .offs = 1 << 5,
- },
[MAX8925_IRQ_VCHG_THM_OK_R] = {
.reg = MAX8925_CHG_IRQ2,
.mask_reg = MAX8925_CHG_IRQ2_MASK,
diff --git a/drivers/mfd/wm8994-core.c b/drivers/mfd/wm8994-core.c
index 61894fced8ea..f117e7fb9321 100644
--- a/drivers/mfd/wm8994-core.c
+++ b/drivers/mfd/wm8994-core.c
@@ -28,11 +28,7 @@
#include <linux/mfd/wm8994/pdata.h>
#include <linux/mfd/wm8994/registers.h>
-static int wm8994_read(struct wm8994 *wm8994, unsigned short reg,
- int bytes, void *dest)
-{
- return regmap_raw_read(wm8994->regmap, reg, dest, bytes);
-}
+#include "wm8994.h"
/**
* wm8994_reg_read: Read a single WM8994 register.
@@ -68,12 +64,6 @@ int wm8994_bulk_read(struct wm8994 *wm8994, unsigned short reg,
return regmap_bulk_read(wm8994->regmap, reg, buf, count);
}
-static int wm8994_write(struct wm8994 *wm8994, unsigned short reg,
- int bytes, const void *src)
-{
- return regmap_raw_write(wm8994->regmap, reg, src, bytes);
-}
-
/**
* wm8994_reg_write: Write a single WM8994 register.
*
@@ -252,6 +242,20 @@ static int wm8994_suspend(struct device *dev)
break;
}
+ switch (wm8994->type) {
+ case WM1811:
+ ret = wm8994_reg_read(wm8994, WM8994_ANTIPOP_2);
+ if (ret < 0) {
+ dev_err(dev, "Failed to read jackdet: %d\n", ret);
+ } else if (ret & WM1811_JACKDET_MODE_MASK) {
+ dev_dbg(dev, "CODEC still active, ignoring suspend\n");
+ return 0;
+ }
+ break;
+ default:
+ break;
+ }
+
/* Disable LDO pulldowns while the device is suspended if we
* don't know that something will be driving them. */
if (!wm8994->ldo_ena_always_driven)
@@ -259,25 +263,14 @@ static int wm8994_suspend(struct device *dev)
WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD);
- /* GPIO configuration state is saved here since we may be configuring
- * the GPIO alternate functions even if we're not using the gpiolib
- * driver for them.
- */
- ret = wm8994_read(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
- &wm8994->gpio_regs);
- if (ret < 0)
- dev_err(dev, "Failed to save GPIO registers: %d\n", ret);
-
- /* For similar reasons we also stash the regulator states */
- ret = wm8994_read(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
- &wm8994->ldo_regs);
- if (ret < 0)
- dev_err(dev, "Failed to save LDO registers: %d\n", ret);
-
/* Explicitly put the device into reset in case regulators
* don't get disabled in order to ensure consistent restart.
*/
- wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET, 0x8994);
+ wm8994_reg_write(wm8994, WM8994_SOFTWARE_RESET,
+ wm8994_reg_read(wm8994, WM8994_SOFTWARE_RESET));
+
+ regcache_cache_only(wm8994->regmap, true);
+ regcache_mark_dirty(wm8994->regmap);
wm8994->suspended = true;
@@ -294,7 +287,7 @@ static int wm8994_suspend(struct device *dev)
static int wm8994_resume(struct device *dev)
{
struct wm8994 *wm8994 = dev_get_drvdata(dev);
- int ret, i;
+ int ret;
/* We may have lied to the PM core about suspending */
if (!wm8994->suspended)
@@ -307,27 +300,13 @@ static int wm8994_resume(struct device *dev)
return ret;
}
- /* Write register at a time as we use the cache on the CPU so store
- * it in native endian.
- */
- for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
- ret = wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK
- + i, wm8994->irq_masks_cur[i]);
- if (ret < 0)
- dev_err(dev, "Failed to restore interrupt masks: %d\n",
- ret);
+ regcache_cache_only(wm8994->regmap, false);
+ ret = regcache_sync(wm8994->regmap);
+ if (ret != 0) {
+ dev_err(dev, "Failed to restore register map: %d\n", ret);
+ goto err_enable;
}
- ret = wm8994_write(wm8994, WM8994_LDO_1, WM8994_NUM_LDO_REGS * 2,
- &wm8994->ldo_regs);
- if (ret < 0)
- dev_err(dev, "Failed to restore LDO registers: %d\n", ret);
-
- ret = wm8994_write(wm8994, WM8994_GPIO_1, WM8994_NUM_GPIO_REGS * 2,
- &wm8994->gpio_regs);
- if (ret < 0)
- dev_err(dev, "Failed to restore GPIO registers: %d\n", ret);
-
/* Disable LDO pulldowns while the device is active */
wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
@@ -336,6 +315,11 @@ static int wm8994_resume(struct device *dev)
wm8994->suspended = false;
return 0;
+
+err_enable:
+ regulator_bulk_disable(wm8994->num_supplies, wm8994->supplies);
+
+ return ret;
}
#endif
@@ -361,19 +345,16 @@ static int wm8994_ldo_in_use(struct wm8994_pdata *pdata, int ldo)
}
#endif
-static struct regmap_config wm8994_regmap_config = {
- .reg_bits = 16,
- .val_bits = 16,
-};
-
/*
* Instantiate the generic non-control parts of the device.
*/
static int wm8994_device_init(struct wm8994 *wm8994, int irq)
{
struct wm8994_pdata *pdata = wm8994->dev->platform_data;
+ struct regmap_config *regmap_config;
const char *devname;
int ret, i;
+ int pulls = 0;
dev_set_drvdata(wm8994->dev, wm8994);
@@ -402,9 +383,9 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
goto err_regmap;
}
- wm8994->supplies = kzalloc(sizeof(struct regulator_bulk_data) *
- wm8994->num_supplies,
- GFP_KERNEL);
+ wm8994->supplies = devm_kzalloc(wm8994->dev,
+ sizeof(struct regulator_bulk_data) *
+ wm8994->num_supplies, GFP_KERNEL);
if (!wm8994->supplies) {
ret = -ENOMEM;
goto err_regmap;
@@ -432,7 +413,7 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
wm8994->supplies);
if (ret != 0) {
dev_err(wm8994->dev, "Failed to get supplies: %d\n", ret);
- goto err_supplies;
+ goto err_regmap;
}
ret = regulator_bulk_enable(wm8994->num_supplies,
@@ -482,25 +463,54 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
ret);
goto err_enable;
}
+ wm8994->revision = ret;
switch (wm8994->type) {
case WM8994:
- switch (ret) {
+ switch (wm8994->revision) {
case 0:
case 1:
dev_warn(wm8994->dev,
"revision %c not fully supported\n",
- 'A' + ret);
+ 'A' + wm8994->revision);
break;
default:
break;
}
break;
+ case WM1811:
+ /* Revision C did not change the relevant layer */
+ if (wm8994->revision > 1)
+ wm8994->revision++;
+ break;
default:
break;
}
- dev_info(wm8994->dev, "%s revision %c\n", devname, 'A' + ret);
+ dev_info(wm8994->dev, "%s revision %c\n", devname,
+ 'A' + wm8994->revision);
+
+ switch (wm8994->type) {
+ case WM1811:
+ regmap_config = &wm1811_regmap_config;
+ break;
+ case WM8994:
+ regmap_config = &wm8994_regmap_config;
+ break;
+ case WM8958:
+ regmap_config = &wm8958_regmap_config;
+ break;
+ default:
+ dev_err(wm8994->dev, "Unknown device type %d\n", wm8994->type);
+ return -EINVAL;
+ }
+
+ ret = regmap_reinit_cache(wm8994->regmap, regmap_config);
+ if (ret != 0) {
+ dev_err(wm8994->dev, "Failed to reinit register cache: %d\n",
+ ret);
+ return ret;
+ }
if (pdata) {
wm8994->irq_base = pdata->irq_base;
@@ -516,12 +526,16 @@ static int wm8994_device_init(struct wm8994 *wm8994, int irq)
}
wm8994->ldo_ena_always_driven = pdata->ldo_ena_always_driven;
+
+ if (pdata->spkmode_pu)
+ pulls |= WM8994_SPKMODE_PU;
}
- /* Disable LDO pulldowns while the device is active */
+ /* Disable unneeded pulls */
wm8994_set_bits(wm8994, WM8994_PULL_CONTROL_2,
- WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD,
- 0);
+ WM8994_LDO1ENA_PD | WM8994_LDO2ENA_PD |
+ WM8994_SPKMODE_PU | WM8994_CSNADDR_PD,
+ pulls);
/* In some system designs where the regulators are not in use,
* we can achieve a small reduction in leakage currents by
@@ -560,12 +574,9 @@ err_enable:
wm8994->supplies);
err_get:
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
-err_supplies:
- kfree(wm8994->supplies);
err_regmap:
regmap_exit(wm8994->regmap);
mfd_remove_devices(wm8994->dev);
- kfree(wm8994);
return ret;
}
@@ -577,18 +588,24 @@ static void wm8994_device_exit(struct wm8994 *wm8994)
regulator_bulk_disable(wm8994->num_supplies,
wm8994->supplies);
regulator_bulk_free(wm8994->num_supplies, wm8994->supplies);
- kfree(wm8994->supplies);
regmap_exit(wm8994->regmap);
- kfree(wm8994);
}
+static const struct of_device_id wm8994_of_match[] = {
+ { .compatible = "wlf,wm1811", },
+ { .compatible = "wlf,wm8994", },
+ { .compatible = "wlf,wm8958", },
+ { }
+};
+MODULE_DEVICE_TABLE(of, wm8994_of_match);
+
static int wm8994_i2c_probe(struct i2c_client *i2c,
const struct i2c_device_id *id)
{
struct wm8994 *wm8994;
int ret;
- wm8994 = kzalloc(sizeof(struct wm8994), GFP_KERNEL);
+ wm8994 = devm_kzalloc(&i2c->dev, sizeof(struct wm8994), GFP_KERNEL);
if (wm8994 == NULL)
return -ENOMEM;
@@ -597,12 +614,11 @@ static int wm8994_i2c_probe(struct i2c_client *i2c,
wm8994->irq = i2c->irq;
wm8994->type = id->driver_data;
- wm8994->regmap = regmap_init_i2c(i2c, &wm8994_regmap_config);
+ wm8994->regmap = regmap_init_i2c(i2c, &wm8994_base_regmap_config);
if (IS_ERR(wm8994->regmap)) {
ret = PTR_ERR(wm8994->regmap);
dev_err(wm8994->dev, "Failed to allocate register map: %d\n",
ret);
- kfree(wm8994);
return ret;
}
@@ -620,6 +636,7 @@ static int wm8994_i2c_remove(struct i2c_client *i2c)
static const struct i2c_device_id wm8994_i2c_id[] = {
{ "wm1811", WM1811 },
+ { "wm1811a", WM1811 },
{ "wm8994", WM8994 },
{ "wm8958", WM8958 },
{ }
@@ -634,6 +651,7 @@ static struct i2c_driver wm8994_i2c_driver = {
.name = "wm8994",
.owner = THIS_MODULE,
.pm = &wm8994_pm_ops,
+ .of_match_table = wm8994_of_match,
},
.probe = wm8994_i2c_probe,
.remove = wm8994_i2c_remove,
diff --git a/drivers/mfd/wm8994-irq.c b/drivers/mfd/wm8994-irq.c
index d682f7bd112c..46b20c445ecf 100644
--- a/drivers/mfd/wm8994-irq.c
+++ b/drivers/mfd/wm8994-irq.c
@@ -18,248 +18,127 @@
#include <linux/irq.h>
#include <linux/mfd/core.h>
#include <linux/interrupt.h>
+#include <linux/regmap.h>
#include <linux/mfd/wm8994/core.h>
#include <linux/mfd/wm8994/registers.h>
#include <linux/delay.h>
-struct wm8994_irq_data {
- int reg;
- int mask;
-};
-
-static struct wm8994_irq_data wm8994_irqs[] = {
+static struct regmap_irq wm8994_irqs[] = {
[WM8994_IRQ_TEMP_SHUT] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_TEMP_SHUT_EINT,
},
[WM8994_IRQ_MIC1_DET] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_MIC1_DET_EINT,
},
[WM8994_IRQ_MIC1_SHRT] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_MIC1_SHRT_EINT,
},
[WM8994_IRQ_MIC2_DET] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_MIC2_DET_EINT,
},
[WM8994_IRQ_MIC2_SHRT] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_MIC2_SHRT_EINT,
},
[WM8994_IRQ_FLL1_LOCK] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_FLL1_LOCK_EINT,
},
[WM8994_IRQ_FLL2_LOCK] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_FLL2_LOCK_EINT,
},
[WM8994_IRQ_SRC1_LOCK] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_SRC1_LOCK_EINT,
},
[WM8994_IRQ_SRC2_LOCK] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_SRC2_LOCK_EINT,
},
[WM8994_IRQ_AIF1DRC1_SIG_DET] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_AIF1DRC1_SIG_DET,
},
[WM8994_IRQ_AIF1DRC2_SIG_DET] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_AIF1DRC2_SIG_DET_EINT,
},
[WM8994_IRQ_AIF2DRC_SIG_DET] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_AIF2DRC_SIG_DET_EINT,
},
[WM8994_IRQ_FIFOS_ERR] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_FIFOS_ERR_EINT,
},
[WM8994_IRQ_WSEQ_DONE] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_WSEQ_DONE_EINT,
},
[WM8994_IRQ_DCS_DONE] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_DCS_DONE_EINT,
},
[WM8994_IRQ_TEMP_WARN] = {
- .reg = 2,
+ .reg_offset = 1,
.mask = WM8994_TEMP_WARN_EINT,
},
[WM8994_IRQ_GPIO(1)] = {
- .reg = 1,
.mask = WM8994_GP1_EINT,
},
[WM8994_IRQ_GPIO(2)] = {
- .reg = 1,
.mask = WM8994_GP2_EINT,
},
[WM8994_IRQ_GPIO(3)] = {
- .reg = 1,
.mask = WM8994_GP3_EINT,
},
[WM8994_IRQ_GPIO(4)] = {
- .reg = 1,
.mask = WM8994_GP4_EINT,
},
[WM8994_IRQ_GPIO(5)] = {
- .reg = 1,
.mask = WM8994_GP5_EINT,
},
[WM8994_IRQ_GPIO(6)] = {
- .reg = 1,
.mask = WM8994_GP6_EINT,
},
[WM8994_IRQ_GPIO(7)] = {
- .reg = 1,
.mask = WM8994_GP7_EINT,
},
[WM8994_IRQ_GPIO(8)] = {
- .reg = 1,
.mask = WM8994_GP8_EINT,
},
[WM8994_IRQ_GPIO(9)] = {
- .reg = 1,
.mask = WM8994_GP8_EINT,
},
[WM8994_IRQ_GPIO(10)] = {
- .reg = 1,
.mask = WM8994_GP10_EINT,
},
[WM8994_IRQ_GPIO(11)] = {
- .reg = 1,
.mask = WM8994_GP11_EINT,
},
};
-static inline int irq_data_to_status_reg(struct wm8994_irq_data *irq_data)
-{
- return WM8994_INTERRUPT_STATUS_1 - 1 + irq_data->reg;
-}
-
-static inline int irq_data_to_mask_reg(struct wm8994_irq_data *irq_data)
-{
- return WM8994_INTERRUPT_STATUS_1_MASK - 1 + irq_data->reg;
-}
-
-static inline struct wm8994_irq_data *irq_to_wm8994_irq(struct wm8994 *wm8994,
- int irq)
-{
- return &wm8994_irqs[irq - wm8994->irq_base];
-}
-
-static void wm8994_irq_lock(struct irq_data *data)
-{
- struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
-
- mutex_lock(&wm8994->irq_lock);
-}
-
-static void wm8994_irq_sync_unlock(struct irq_data *data)
-{
- struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
- int i;
-
- for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
- /* If there's been a change in the mask write it back
- * to the hardware. */
- if (wm8994->irq_masks_cur[i] != wm8994->irq_masks_cache[i]) {
- wm8994->irq_masks_cache[i] = wm8994->irq_masks_cur[i];
- wm8994_reg_write(wm8994,
- WM8994_INTERRUPT_STATUS_1_MASK + i,
- wm8994->irq_masks_cur[i]);
- }
- }
-
- mutex_unlock(&wm8994->irq_lock);
-}
-
-static void wm8994_irq_enable(struct irq_data *data)
-{
- struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
- struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
- data->irq);
-
- wm8994->irq_masks_cur[irq_data->reg - 1] &= ~irq_data->mask;
-}
-
-static void wm8994_irq_disable(struct irq_data *data)
-{
- struct wm8994 *wm8994 = irq_data_get_irq_chip_data(data);
- struct wm8994_irq_data *irq_data = irq_to_wm8994_irq(wm8994,
- data->irq);
-
- wm8994->irq_masks_cur[irq_data->reg - 1] |= irq_data->mask;
-}
+static struct regmap_irq_chip wm8994_irq_chip = {
+ .name = "wm8994",
+ .irqs = wm8994_irqs,
+ .num_irqs = ARRAY_SIZE(wm8994_irqs),
-static struct irq_chip wm8994_irq_chip = {
- .name = "wm8994",
- .irq_bus_lock = wm8994_irq_lock,
- .irq_bus_sync_unlock = wm8994_irq_sync_unlock,
- .irq_disable = wm8994_irq_disable,
- .irq_enable = wm8994_irq_enable,
+ .num_regs = 2,
+ .status_base = WM8994_INTERRUPT_STATUS_1,
+ .mask_base = WM8994_INTERRUPT_STATUS_1_MASK,
+ .ack_base = WM8994_INTERRUPT_STATUS_1,
};
-/* The processing of the primary interrupt occurs in a thread so that
- * we can interact with the device over I2C or SPI. */
-static irqreturn_t wm8994_irq_thread(int irq, void *data)
-{
- struct wm8994 *wm8994 = data;
- unsigned int i;
- u16 status[WM8994_NUM_IRQ_REGS];
- int ret;
-
- ret = wm8994_bulk_read(wm8994, WM8994_INTERRUPT_STATUS_1,
- WM8994_NUM_IRQ_REGS, status);
- if (ret < 0) {
- dev_err(wm8994->dev, "Failed to read interrupt status: %d\n",
- ret);
- return IRQ_NONE;
- }
-
- /* Bit swap and apply masking */
- for (i = 0; i < WM8994_NUM_IRQ_REGS; i++) {
- status[i] = be16_to_cpu(status[i]);
- status[i] &= ~wm8994->irq_masks_cur[i];
- }
-
- /* Ack any unmasked IRQs */
- for (i = 0; i < ARRAY_SIZE(status); i++) {
- if (status[i])
- wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1 + i,
- status[i]);
- }
-
- /* Report */
- for (i = 0; i < ARRAY_SIZE(wm8994_irqs); i++) {
- if (status[wm8994_irqs[i].reg - 1] & wm8994_irqs[i].mask)
- handle_nested_irq(wm8994->irq_base + i);
- }
-
- return IRQ_HANDLED;
-}
-
int wm8994_irq_init(struct wm8994 *wm8994)
{
- int i, cur_irq, ret;
-
- mutex_init(&wm8994->irq_lock);
-
- /* Mask the individual interrupt sources */
- for (i = 0; i < ARRAY_SIZE(wm8994->irq_masks_cur); i++) {
- wm8994->irq_masks_cur[i] = 0xffff;
- wm8994->irq_masks_cache[i] = 0xffff;
- wm8994_reg_write(wm8994, WM8994_INTERRUPT_STATUS_1_MASK + i,
- 0xffff);
- }
+ int ret;
if (!wm8994->irq) {
dev_warn(wm8994->dev,
@@ -274,30 +153,12 @@ int wm8994_irq_init(struct wm8994 *wm8994)
return 0;
}
- /* Register them with genirq */
- for (cur_irq = wm8994->irq_base;
- cur_irq < ARRAY_SIZE(wm8994_irqs) + wm8994->irq_base;
- cur_irq++) {
- irq_set_chip_data(cur_irq, wm8994);
- irq_set_chip_and_handler(cur_irq, &wm8994_irq_chip,
- handle_edge_irq);
- irq_set_nested_thread(cur_irq, 1);
-
- /* ARM needs us to explicitly flag the IRQ as valid
- * and will set them noprobe when we do so. */
-#ifdef CONFIG_ARM
- set_irq_flags(cur_irq, IRQF_VALID);
-#else
- irq_set_noprobe(cur_irq);
-#endif
- }
-
- ret = request_threaded_irq(wm8994->irq, NULL, wm8994_irq_thread,
- IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
- "wm8994", wm8994);
+ ret = regmap_add_irq_chip(wm8994->regmap, wm8994->irq,
+ IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
+ wm8994->irq_base, &wm8994_irq_chip,
+ &wm8994->irq_data);
if (ret != 0) {
- dev_err(wm8994->dev, "Failed to request IRQ %d: %d\n",
- wm8994->irq, ret);
+ dev_err(wm8994->dev, "Failed to register IRQ chip: %d\n", ret);
return ret;
}
@@ -309,6 +170,5 @@ int wm8994_irq_init(struct wm8994 *wm8994)
void wm8994_irq_exit(struct wm8994 *wm8994)
{
- if (wm8994->irq)
- free_irq(wm8994->irq, wm8994);
+ regmap_del_irq_chip(wm8994->irq, wm8994->irq_data);
}
diff --git a/drivers/mfd/wm8994-regmap.c b/drivers/mfd/wm8994-regmap.c
new file mode 100644
index 000000000000..c598ae69b8ff
--- /dev/null
+++ b/drivers/mfd/wm8994-regmap.c
@@ -0,0 +1,1238 @@
+/*
+ * wm8994-regmap.c -- Register map data for WM8994 series devices
+ *
+ * Copyright 2011 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#include <linux/mfd/wm8994/core.h>
+#include <linux/mfd/wm8994/registers.h>
+#include <linux/regmap.h>
+
+#include "wm8994.h"
+
+static struct reg_default wm1811_defaults[] = {
+ { 0x0000, 0x1811 }, /* R0 - Software Reset */
+ { 0x0001, 0x0000 }, /* R1 - Power Management (1) */
+ { 0x0002, 0x6000 }, /* R2 - Power Management (2) */
+ { 0x0003, 0x0000 }, /* R3 - Power Management (3) */
+ { 0x0004, 0x0000 }, /* R4 - Power Management (4) */
+ { 0x0005, 0x0000 }, /* R5 - Power Management (5) */
+ { 0x0006, 0x0000 }, /* R6 - Power Management (6) */
+ { 0x0015, 0x0000 }, /* R21 - Input Mixer (1) */
+ { 0x0018, 0x008B }, /* R24 - Left Line Input 1&2 Volume */
+ { 0x0019, 0x008B }, /* R25 - Left Line Input 3&4 Volume */
+ { 0x001A, 0x008B }, /* R26 - Right Line Input 1&2 Volume */
+ { 0x001B, 0x008B }, /* R27 - Right Line Input 3&4 Volume */
+ { 0x001C, 0x006D }, /* R28 - Left Output Volume */
+ { 0x001D, 0x006D }, /* R29 - Right Output Volume */
+ { 0x001E, 0x0066 }, /* R30 - Line Outputs Volume */
+ { 0x001F, 0x0020 }, /* R31 - HPOUT2 Volume */
+ { 0x0020, 0x0079 }, /* R32 - Left OPGA Volume */
+ { 0x0021, 0x0079 }, /* R33 - Right OPGA Volume */
+ { 0x0022, 0x0003 }, /* R34 - SPKMIXL Attenuation */
+ { 0x0023, 0x0003 }, /* R35 - SPKMIXR Attenuation */
+ { 0x0024, 0x0011 }, /* R36 - SPKOUT Mixers */
+ { 0x0025, 0x0140 }, /* R37 - ClassD */
+ { 0x0026, 0x0079 }, /* R38 - Speaker Volume Left */
+ { 0x0027, 0x0079 }, /* R39 - Speaker Volume Right */
+ { 0x0028, 0x0000 }, /* R40 - Input Mixer (2) */
+ { 0x0029, 0x0000 }, /* R41 - Input Mixer (3) */
+ { 0x002A, 0x0000 }, /* R42 - Input Mixer (4) */
+ { 0x002B, 0x0000 }, /* R43 - Input Mixer (5) */
+ { 0x002C, 0x0000 }, /* R44 - Input Mixer (6) */
+ { 0x002D, 0x0000 }, /* R45 - Output Mixer (1) */
+ { 0x002E, 0x0000 }, /* R46 - Output Mixer (2) */
+ { 0x002F, 0x0000 }, /* R47 - Output Mixer (3) */
+ { 0x0030, 0x0000 }, /* R48 - Output Mixer (4) */
+ { 0x0031, 0x0000 }, /* R49 - Output Mixer (5) */
+ { 0x0032, 0x0000 }, /* R50 - Output Mixer (6) */
+ { 0x0033, 0x0000 }, /* R51 - HPOUT2 Mixer */
+ { 0x0034, 0x0000 }, /* R52 - Line Mixer (1) */
+ { 0x0035, 0x0000 }, /* R53 - Line Mixer (2) */
+ { 0x0036, 0x0000 }, /* R54 - Speaker Mixer */
+ { 0x0037, 0x0000 }, /* R55 - Additional Control */
+ { 0x0038, 0x0000 }, /* R56 - AntiPOP (1) */
+ { 0x0039, 0x0180 }, /* R57 - AntiPOP (2) */
+ { 0x003B, 0x000D }, /* R59 - LDO 1 */
+ { 0x003C, 0x0003 }, /* R60 - LDO 2 */
+ { 0x003D, 0x0039 }, /* R61 - MICBIAS1 */
+ { 0x003E, 0x0039 }, /* R62 - MICBIAS2 */
+ { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */
+ { 0x004D, 0xAB19 }, /* R77 - Charge Pump (2) */
+ { 0x0051, 0x0004 }, /* R81 - Class W (1) */
+ { 0x0054, 0x0000 }, /* R84 - DC Servo (1) */
+ { 0x0055, 0x054A }, /* R85 - DC Servo (2) */
+ { 0x0058, 0x0000 }, /* R88 - DC Servo Readback */
+ { 0x0059, 0x0000 }, /* R89 - DC Servo (4) */
+ { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */
+ { 0x00C5, 0x0000 }, /* R197 - Class D Test (5) */
+ { 0x00D0, 0x7600 }, /* R208 - Mic Detect 1 */
+ { 0x00D1, 0x007F }, /* R209 - Mic Detect 2 */
+ { 0x00D2, 0x0000 }, /* R210 - Mic Detect 3 */
+ { 0x0100, 0x0100 }, /* R256 - Chip Revision */
+ { 0x0101, 0x8004 }, /* R257 - Control Interface */
+ { 0x0200, 0x0000 }, /* R512 - AIF1 Clocking (1) */
+ { 0x0201, 0x0000 }, /* R513 - AIF1 Clocking (2) */
+ { 0x0204, 0x0000 }, /* R516 - AIF2 Clocking (1) */
+ { 0x0205, 0x0000 }, /* R517 - AIF2 Clocking (2) */
+ { 0x0208, 0x0000 }, /* R520 - Clocking (1) */
+ { 0x0209, 0x0000 }, /* R521 - Clocking (2) */
+ { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */
+ { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */
+ { 0x0212, 0x0000 }, /* R530 - Rate Status */
+ { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */
+ { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */
+ { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */
+ { 0x0223, 0x0000 }, /* R547 - FLL1 Control (4) */
+ { 0x0224, 0x0C80 }, /* R548 - FLL1 Control (5) */
+ { 0x0226, 0x0000 }, /* R550 - FLL1 EFS 1 */
+ { 0x0227, 0x0006 }, /* R551 - FLL1 EFS 2 */
+ { 0x0240, 0x0000 }, /* R576 - FLL2Control (1) */
+ { 0x0241, 0x0000 }, /* R577 - FLL2Control (2) */
+ { 0x0242, 0x0000 }, /* R578 - FLL2Control (3) */
+ { 0x0243, 0x0000 }, /* R579 - FLL2 Control (4) */
+ { 0x0244, 0x0C80 }, /* R580 - FLL2Control (5) */
+ { 0x0246, 0x0000 }, /* R582 - FLL2 EFS 1 */
+ { 0x0247, 0x0006 }, /* R583 - FLL2 EFS 2 */
+ { 0x0300, 0x4050 }, /* R768 - AIF1 Control (1) */
+ { 0x0301, 0x4000 }, /* R769 - AIF1 Control (2) */
+ { 0x0302, 0x0000 }, /* R770 - AIF1 Master/Slave */
+ { 0x0303, 0x0040 }, /* R771 - AIF1 BCLK */
+ { 0x0304, 0x0040 }, /* R772 - AIF1ADC LRCLK */
+ { 0x0305, 0x0040 }, /* R773 - AIF1DAC LRCLK */
+ { 0x0306, 0x0004 }, /* R774 - AIF1DAC Data */
+ { 0x0307, 0x0100 }, /* R775 - AIF1ADC Data */
+ { 0x0310, 0x4050 }, /* R784 - AIF2 Control (1) */
+ { 0x0311, 0x4000 }, /* R785 - AIF2 Control (2) */
+ { 0x0312, 0x0000 }, /* R786 - AIF2 Master/Slave */
+ { 0x0313, 0x0040 }, /* R787 - AIF2 BCLK */
+ { 0x0314, 0x0040 }, /* R788 - AIF2ADC LRCLK */
+ { 0x0315, 0x0040 }, /* R789 - AIF2DAC LRCLK */
+ { 0x0316, 0x0000 }, /* R790 - AIF2DAC Data */
+ { 0x0317, 0x0000 }, /* R791 - AIF2ADC Data */
+ { 0x0318, 0x0003 }, /* R792 - AIF2TX Control */
+ { 0x0320, 0x0040 }, /* R800 - AIF3 Control (1) */
+ { 0x0321, 0x0000 }, /* R801 - AIF3 Control (2) */
+ { 0x0322, 0x0000 }, /* R802 - AIF3DAC Data */
+ { 0x0323, 0x0000 }, /* R803 - AIF3ADC Data */
+ { 0x0400, 0x00C0 }, /* R1024 - AIF1 ADC1 Left Volume */
+ { 0x0401, 0x00C0 }, /* R1025 - AIF1 ADC1 Right Volume */
+ { 0x0402, 0x00C0 }, /* R1026 - AIF1 DAC1 Left Volume */
+ { 0x0403, 0x00C0 }, /* R1027 - AIF1 DAC1 Right Volume */
+ { 0x0410, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */
+ { 0x0420, 0x0200 }, /* R1056 - AIF1 DAC1 Filters (1) */
+ { 0x0421, 0x0010 }, /* R1057 - AIF1 DAC1 Filters (2) */
+ { 0x0430, 0x0068 }, /* R1072 - AIF1 DAC1 Noise Gate */
+ { 0x0440, 0x0098 }, /* R1088 - AIF1 DRC1 (1) */
+ { 0x0441, 0x0845 }, /* R1089 - AIF1 DRC1 (2) */
+ { 0x0442, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */
+ { 0x0443, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */
+ { 0x0444, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */
+ { 0x0480, 0x6318 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
+ { 0x0481, 0x6300 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
+ { 0x0482, 0x0FCA }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
+ { 0x0483, 0x0400 }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
+ { 0x0484, 0x00D8 }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
+ { 0x0485, 0x1EB5 }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
+ { 0x0486, 0xF145 }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
+ { 0x0487, 0x0B75 }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
+ { 0x0488, 0x01C5 }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
+ { 0x0489, 0x1C58 }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
+ { 0x048A, 0xF373 }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
+ { 0x048B, 0x0A54 }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
+ { 0x048C, 0x0558 }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
+ { 0x048D, 0x168E }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
+ { 0x048E, 0xF829 }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
+ { 0x048F, 0x07AD }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
+ { 0x0490, 0x1103 }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
+ { 0x0491, 0x0564 }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
+ { 0x0492, 0x0559 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
+ { 0x0493, 0x4000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
+ { 0x0494, 0x0000 }, /* R1172 - AIF1 DAC1 EQ Band 1 C */
+ { 0x0500, 0x00C0 }, /* R1280 - AIF2 ADC Left Volume */
+ { 0x0501, 0x00C0 }, /* R1281 - AIF2 ADC Right Volume */
+ { 0x0502, 0x00C0 }, /* R1282 - AIF2 DAC Left Volume */
+ { 0x0503, 0x00C0 }, /* R1283 - AIF2 DAC Right Volume */
+ { 0x0510, 0x0000 }, /* R1296 - AIF2 ADC Filters */
+ { 0x0520, 0x0200 }, /* R1312 - AIF2 DAC Filters (1) */
+ { 0x0521, 0x0010 }, /* R1313 - AIF2 DAC Filters (2) */
+ { 0x0530, 0x0068 }, /* R1328 - AIF2 DAC Noise Gate */
+ { 0x0540, 0x0098 }, /* R1344 - AIF2 DRC (1) */
+ { 0x0541, 0x0845 }, /* R1345 - AIF2 DRC (2) */
+ { 0x0542, 0x0000 }, /* R1346 - AIF2 DRC (3) */
+ { 0x0543, 0x0000 }, /* R1347 - AIF2 DRC (4) */
+ { 0x0544, 0x0000 }, /* R1348 - AIF2 DRC (5) */
+ { 0x0580, 0x6318 }, /* R1408 - AIF2 EQ Gains (1) */
+ { 0x0581, 0x6300 }, /* R1409 - AIF2 EQ Gains (2) */
+ { 0x0582, 0x0FCA }, /* R1410 - AIF2 EQ Band 1 A */
+ { 0x0583, 0x0400 }, /* R1411 - AIF2 EQ Band 1 B */
+ { 0x0584, 0x00D8 }, /* R1412 - AIF2 EQ Band 1 PG */
+ { 0x0585, 0x1EB5 }, /* R1413 - AIF2 EQ Band 2 A */
+ { 0x0586, 0xF145 }, /* R1414 - AIF2 EQ Band 2 B */
+ { 0x0587, 0x0B75 }, /* R1415 - AIF2 EQ Band 2 C */
+ { 0x0588, 0x01C5 }, /* R1416 - AIF2 EQ Band 2 PG */
+ { 0x0589, 0x1C58 }, /* R1417 - AIF2 EQ Band 3 A */
+ { 0x058A, 0xF373 }, /* R1418 - AIF2 EQ Band 3 B */
+ { 0x058B, 0x0A54 }, /* R1419 - AIF2 EQ Band 3 C */
+ { 0x058C, 0x0558 }, /* R1420 - AIF2 EQ Band 3 PG */
+ { 0x058D, 0x168E }, /* R1421 - AIF2 EQ Band 4 A */
+ { 0x058E, 0xF829 }, /* R1422 - AIF2 EQ Band 4 B */
+ { 0x058F, 0x07AD }, /* R1423 - AIF2 EQ Band 4 C */
+ { 0x0590, 0x1103 }, /* R1424 - AIF2 EQ Band 4 PG */
+ { 0x0591, 0x0564 }, /* R1425 - AIF2 EQ Band 5 A */
+ { 0x0592, 0x0559 }, /* R1426 - AIF2 EQ Band 5 B */
+ { 0x0593, 0x4000 }, /* R1427 - AIF2 EQ Band 5 PG */
+ { 0x0594, 0x0000 }, /* R1428 - AIF2 EQ Band 1 C */
+ { 0x0600, 0x0000 }, /* R1536 - DAC1 Mixer Volumes */
+ { 0x0601, 0x0000 }, /* R1537 - DAC1 Left Mixer Routing */
+ { 0x0602, 0x0000 }, /* R1538 - DAC1 Right Mixer Routing */
+ { 0x0603, 0x0000 }, /* R1539 - AIF2ADC Mixer Volumes */
+ { 0x0604, 0x0000 }, /* R1540 - AIF2ADC Left Mixer Routing */
+ { 0x0605, 0x0000 }, /* R1541 - AIF2ADC Right Mixer Routing */
+ { 0x0606, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
+ { 0x0607, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
+ { 0x0610, 0x02C0 }, /* R1552 - DAC1 Left Volume */
+ { 0x0611, 0x02C0 }, /* R1553 - DAC1 Right Volume */
+ { 0x0612, 0x02C0 }, /* R1554 - AIF2TX Left Volume */
+ { 0x0613, 0x02C0 }, /* R1555 - AIF2TX Right Volume */
+ { 0x0614, 0x0000 }, /* R1556 - DAC Softmute */
+ { 0x0620, 0x0002 }, /* R1568 - Oversampling */
+ { 0x0621, 0x0000 }, /* R1569 - Sidetone */
+ { 0x0700, 0x8100 }, /* R1792 - GPIO 1 */
+ { 0x0701, 0xA101 }, /* R1793 - Pull Control (MCLK2) */
+ { 0x0702, 0xA101 }, /* R1794 - Pull Control (BCLK2) */
+ { 0x0703, 0xA101 }, /* R1795 - Pull Control (DACLRCLK2) */
+ { 0x0704, 0xA101 }, /* R1796 - Pull Control (DACDAT2) */
+ { 0x0707, 0xA101 }, /* R1799 - GPIO 8 */
+ { 0x0708, 0xA101 }, /* R1800 - GPIO 9 */
+ { 0x0709, 0xA101 }, /* R1801 - GPIO 10 */
+ { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */
+ { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */
+ { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */
+ { 0x0730, 0x0000 }, /* R1840 - Interrupt Status 1 */
+ { 0x0731, 0x0000 }, /* R1841 - Interrupt Status 2 */
+ { 0x0732, 0x0000 }, /* R1842 - Interrupt Raw Status 2 */
+ { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */
+ { 0x0739, 0xDFEF }, /* R1849 - Interrupt Status 2 Mask */
+ { 0x0740, 0x0000 }, /* R1856 - Interrupt Control */
+ { 0x0748, 0x003F }, /* R1864 - IRQ Debounce */
+};
+
+static struct reg_default wm8994_defaults[] = {
+ { 0x0000, 0x8994 }, /* R0 - Software Reset */
+ { 0x0001, 0x0000 }, /* R1 - Power Management (1) */
+ { 0x0002, 0x6000 }, /* R2 - Power Management (2) */
+ { 0x0003, 0x0000 }, /* R3 - Power Management (3) */
+ { 0x0004, 0x0000 }, /* R4 - Power Management (4) */
+ { 0x0005, 0x0000 }, /* R5 - Power Management (5) */
+ { 0x0006, 0x0000 }, /* R6 - Power Management (6) */
+ { 0x0015, 0x0000 }, /* R21 - Input Mixer (1) */
+ { 0x0018, 0x008B }, /* R24 - Left Line Input 1&2 Volume */
+ { 0x0019, 0x008B }, /* R25 - Left Line Input 3&4 Volume */
+ { 0x001A, 0x008B }, /* R26 - Right Line Input 1&2 Volume */
+ { 0x001B, 0x008B }, /* R27 - Right Line Input 3&4 Volume */
+ { 0x001C, 0x006D }, /* R28 - Left Output Volume */
+ { 0x001D, 0x006D }, /* R29 - Right Output Volume */
+ { 0x001E, 0x0066 }, /* R30 - Line Outputs Volume */
+ { 0x001F, 0x0020 }, /* R31 - HPOUT2 Volume */
+ { 0x0020, 0x0079 }, /* R32 - Left OPGA Volume */
+ { 0x0021, 0x0079 }, /* R33 - Right OPGA Volume */
+ { 0x0022, 0x0003 }, /* R34 - SPKMIXL Attenuation */
+ { 0x0023, 0x0003 }, /* R35 - SPKMIXR Attenuation */
+ { 0x0024, 0x0011 }, /* R36 - SPKOUT Mixers */
+ { 0x0025, 0x0140 }, /* R37 - ClassD */
+ { 0x0026, 0x0079 }, /* R38 - Speaker Volume Left */
+ { 0x0027, 0x0079 }, /* R39 - Speaker Volume Right */
+ { 0x0028, 0x0000 }, /* R40 - Input Mixer (2) */
+ { 0x0029, 0x0000 }, /* R41 - Input Mixer (3) */
+ { 0x002A, 0x0000 }, /* R42 - Input Mixer (4) */
+ { 0x002B, 0x0000 }, /* R43 - Input Mixer (5) */
+ { 0x002C, 0x0000 }, /* R44 - Input Mixer (6) */
+ { 0x002D, 0x0000 }, /* R45 - Output Mixer (1) */
+ { 0x002E, 0x0000 }, /* R46 - Output Mixer (2) */
+ { 0x002F, 0x0000 }, /* R47 - Output Mixer (3) */
+ { 0x0030, 0x0000 }, /* R48 - Output Mixer (4) */
+ { 0x0031, 0x0000 }, /* R49 - Output Mixer (5) */
+ { 0x0032, 0x0000 }, /* R50 - Output Mixer (6) */
+ { 0x0033, 0x0000 }, /* R51 - HPOUT2 Mixer */
+ { 0x0034, 0x0000 }, /* R52 - Line Mixer (1) */
+ { 0x0035, 0x0000 }, /* R53 - Line Mixer (2) */
+ { 0x0036, 0x0000 }, /* R54 - Speaker Mixer */
+ { 0x0037, 0x0000 }, /* R55 - Additional Control */
+ { 0x0038, 0x0000 }, /* R56 - AntiPOP (1) */
+ { 0x0039, 0x0000 }, /* R57 - AntiPOP (2) */
+ { 0x003A, 0x0000 }, /* R58 - MICBIAS */
+ { 0x003B, 0x000D }, /* R59 - LDO 1 */
+ { 0x003C, 0x0003 }, /* R60 - LDO 2 */
+ { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */
+ { 0x0051, 0x0004 }, /* R81 - Class W (1) */
+ { 0x0054, 0x0000 }, /* R84 - DC Servo (1) */
+ { 0x0055, 0x054A }, /* R85 - DC Servo (2) */
+ { 0x0057, 0x0000 }, /* R87 - DC Servo (4) */
+ { 0x0058, 0x0000 }, /* R88 - DC Servo Readback */
+ { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */
+ { 0x0100, 0x0003 }, /* R256 - Chip Revision */
+ { 0x0101, 0x8004 }, /* R257 - Control Interface */
+ { 0x0110, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */
+ { 0x0111, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */
+ { 0x0200, 0x0000 }, /* R512 - AIF1 Clocking (1) */
+ { 0x0201, 0x0000 }, /* R513 - AIF1 Clocking (2) */
+ { 0x0204, 0x0000 }, /* R516 - AIF2 Clocking (1) */
+ { 0x0205, 0x0000 }, /* R517 - AIF2 Clocking (2) */
+ { 0x0208, 0x0000 }, /* R520 - Clocking (1) */
+ { 0x0209, 0x0000 }, /* R521 - Clocking (2) */
+ { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */
+ { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */
+ { 0x0212, 0x0000 }, /* R530 - Rate Status */
+ { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */
+ { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */
+ { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */
+ { 0x0223, 0x0000 }, /* R547 - FLL1 Control (4) */
+ { 0x0224, 0x0C80 }, /* R548 - FLL1 Control (5) */
+ { 0x0240, 0x0000 }, /* R576 - FLL2 Control (1) */
+ { 0x0241, 0x0000 }, /* R577 - FLL2 Control (2) */
+ { 0x0242, 0x0000 }, /* R578 - FLL2 Control (3) */
+ { 0x0243, 0x0000 }, /* R579 - FLL2 Control (4) */
+ { 0x0244, 0x0C80 }, /* R580 - FLL2 Control (5) */
+ { 0x0300, 0x4050 }, /* R768 - AIF1 Control (1) */
+ { 0x0301, 0x4000 }, /* R769 - AIF1 Control (2) */
+ { 0x0302, 0x0000 }, /* R770 - AIF1 Master/Slave */
+ { 0x0303, 0x0040 }, /* R771 - AIF1 BCLK */
+ { 0x0304, 0x0040 }, /* R772 - AIF1ADC LRCLK */
+ { 0x0305, 0x0040 }, /* R773 - AIF1DAC LRCLK */
+ { 0x0306, 0x0004 }, /* R774 - AIF1DAC Data */
+ { 0x0307, 0x0100 }, /* R775 - AIF1ADC Data */
+ { 0x0310, 0x4050 }, /* R784 - AIF2 Control (1) */
+ { 0x0311, 0x4000 }, /* R785 - AIF2 Control (2) */
+ { 0x0312, 0x0000 }, /* R786 - AIF2 Master/Slave */
+ { 0x0313, 0x0040 }, /* R787 - AIF2 BCLK */
+ { 0x0314, 0x0040 }, /* R788 - AIF2ADC LRCLK */
+ { 0x0315, 0x0040 }, /* R789 - AIF2DAC LRCLK */
+ { 0x0316, 0x0000 }, /* R790 - AIF2DAC Data */
+ { 0x0317, 0x0000 }, /* R791 - AIF2ADC Data */
+ { 0x0400, 0x00C0 }, /* R1024 - AIF1 ADC1 Left Volume */
+ { 0x0401, 0x00C0 }, /* R1025 - AIF1 ADC1 Right Volume */
+ { 0x0402, 0x00C0 }, /* R1026 - AIF1 DAC1 Left Volume */
+ { 0x0403, 0x00C0 }, /* R1027 - AIF1 DAC1 Right Volume */
+ { 0x0404, 0x00C0 }, /* R1028 - AIF1 ADC2 Left Volume */
+ { 0x0405, 0x00C0 }, /* R1029 - AIF1 ADC2 Right Volume */
+ { 0x0406, 0x00C0 }, /* R1030 - AIF1 DAC2 Left Volume */
+ { 0x0407, 0x00C0 }, /* R1031 - AIF1 DAC2 Right Volume */
+ { 0x0410, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */
+ { 0x0411, 0x0000 }, /* R1041 - AIF1 ADC2 Filters */
+ { 0x0420, 0x0200 }, /* R1056 - AIF1 DAC1 Filters (1) */
+ { 0x0421, 0x0010 }, /* R1057 - AIF1 DAC1 Filters (2) */
+ { 0x0422, 0x0200 }, /* R1058 - AIF1 DAC2 Filters (1) */
+ { 0x0423, 0x0010 }, /* R1059 - AIF1 DAC2 Filters (2) */
+ { 0x0440, 0x0098 }, /* R1088 - AIF1 DRC1 (1) */
+ { 0x0441, 0x0845 }, /* R1089 - AIF1 DRC1 (2) */
+ { 0x0442, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */
+ { 0x0443, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */
+ { 0x0444, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */
+ { 0x0450, 0x0098 }, /* R1104 - AIF1 DRC2 (1) */
+ { 0x0451, 0x0845 }, /* R1105 - AIF1 DRC2 (2) */
+ { 0x0452, 0x0000 }, /* R1106 - AIF1 DRC2 (3) */
+ { 0x0453, 0x0000 }, /* R1107 - AIF1 DRC2 (4) */
+ { 0x0454, 0x0000 }, /* R1108 - AIF1 DRC2 (5) */
+ { 0x0480, 0x6318 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
+ { 0x0481, 0x6300 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
+ { 0x0482, 0x0FCA }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
+ { 0x0483, 0x0400 }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
+ { 0x0484, 0x00D8 }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
+ { 0x0485, 0x1EB5 }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
+ { 0x0486, 0xF145 }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
+ { 0x0487, 0x0B75 }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
+ { 0x0488, 0x01C5 }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
+ { 0x0489, 0x1C58 }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
+ { 0x048A, 0xF373 }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
+ { 0x048B, 0x0A54 }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
+ { 0x048C, 0x0558 }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
+ { 0x048D, 0x168E }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
+ { 0x048E, 0xF829 }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
+ { 0x048F, 0x07AD }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
+ { 0x0490, 0x1103 }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
+ { 0x0491, 0x0564 }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
+ { 0x0492, 0x0559 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
+ { 0x0493, 0x4000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
+ { 0x04A0, 0x6318 }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
+ { 0x04A1, 0x6300 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
+ { 0x04A2, 0x0FCA }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
+ { 0x04A3, 0x0400 }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
+ { 0x04A4, 0x00D8 }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
+ { 0x04A5, 0x1EB5 }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
+ { 0x04A6, 0xF145 }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
+ { 0x04A7, 0x0B75 }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
+ { 0x04A8, 0x01C5 }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
+ { 0x04A9, 0x1C58 }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
+ { 0x04AA, 0xF373 }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
+ { 0x04AB, 0x0A54 }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
+ { 0x04AC, 0x0558 }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
+ { 0x04AD, 0x168E }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
+ { 0x04AE, 0xF829 }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
+ { 0x04AF, 0x07AD }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
+ { 0x04B0, 0x1103 }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
+ { 0x04B1, 0x0564 }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
+ { 0x04B2, 0x0559 }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
+ { 0x04B3, 0x4000 }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
+ { 0x0500, 0x00C0 }, /* R1280 - AIF2 ADC Left Volume */
+ { 0x0501, 0x00C0 }, /* R1281 - AIF2 ADC Right Volume */
+ { 0x0502, 0x00C0 }, /* R1282 - AIF2 DAC Left Volume */
+ { 0x0503, 0x00C0 }, /* R1283 - AIF2 DAC Right Volume */
+ { 0x0510, 0x0000 }, /* R1296 - AIF2 ADC Filters */
+ { 0x0520, 0x0200 }, /* R1312 - AIF2 DAC Filters (1) */
+ { 0x0521, 0x0010 }, /* R1313 - AIF2 DAC Filters (2) */
+ { 0x0540, 0x0098 }, /* R1344 - AIF2 DRC (1) */
+ { 0x0541, 0x0845 }, /* R1345 - AIF2 DRC (2) */
+ { 0x0542, 0x0000 }, /* R1346 - AIF2 DRC (3) */
+ { 0x0543, 0x0000 }, /* R1347 - AIF2 DRC (4) */
+ { 0x0544, 0x0000 }, /* R1348 - AIF2 DRC (5) */
+ { 0x0580, 0x6318 }, /* R1408 - AIF2 EQ Gains (1) */
+ { 0x0581, 0x6300 }, /* R1409 - AIF2 EQ Gains (2) */
+ { 0x0582, 0x0FCA }, /* R1410 - AIF2 EQ Band 1 A */
+ { 0x0583, 0x0400 }, /* R1411 - AIF2 EQ Band 1 B */
+ { 0x0584, 0x00D8 }, /* R1412 - AIF2 EQ Band 1 PG */
+ { 0x0585, 0x1EB5 }, /* R1413 - AIF2 EQ Band 2 A */
+ { 0x0586, 0xF145 }, /* R1414 - AIF2 EQ Band 2 B */
+ { 0x0587, 0x0B75 }, /* R1415 - AIF2 EQ Band 2 C */
+ { 0x0588, 0x01C5 }, /* R1416 - AIF2 EQ Band 2 PG */
+ { 0x0589, 0x1C58 }, /* R1417 - AIF2 EQ Band 3 A */
+ { 0x058A, 0xF373 }, /* R1418 - AIF2 EQ Band 3 B */
+ { 0x058B, 0x0A54 }, /* R1419 - AIF2 EQ Band 3 C */
+ { 0x058C, 0x0558 }, /* R1420 - AIF2 EQ Band 3 PG */
+ { 0x058D, 0x168E }, /* R1421 - AIF2 EQ Band 4 A */
+ { 0x058E, 0xF829 }, /* R1422 - AIF2 EQ Band 4 B */
+ { 0x058F, 0x07AD }, /* R1423 - AIF2 EQ Band 4 C */
+ { 0x0590, 0x1103 }, /* R1424 - AIF2 EQ Band 4 PG */
+ { 0x0591, 0x0564 }, /* R1425 - AIF2 EQ Band 5 A */
+ { 0x0592, 0x0559 }, /* R1426 - AIF2 EQ Band 5 B */
+ { 0x0593, 0x4000 }, /* R1427 - AIF2 EQ Band 5 PG */
+ { 0x0600, 0x0000 }, /* R1536 - DAC1 Mixer Volumes */
+ { 0x0601, 0x0000 }, /* R1537 - DAC1 Left Mixer Routing */
+ { 0x0602, 0x0000 }, /* R1538 - DAC1 Right Mixer Routing */
+ { 0x0603, 0x0000 }, /* R1539 - DAC2 Mixer Volumes */
+ { 0x0604, 0x0000 }, /* R1540 - DAC2 Left Mixer Routing */
+ { 0x0605, 0x0000 }, /* R1541 - DAC2 Right Mixer Routing */
+ { 0x0606, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
+ { 0x0607, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
+ { 0x0608, 0x0000 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
+ { 0x0609, 0x0000 }, /* R1545 - AIF1 ADC2 Right mixer Routing */
+ { 0x0610, 0x02C0 }, /* R1552 - DAC1 Left Volume */
+ { 0x0611, 0x02C0 }, /* R1553 - DAC1 Right Volume */
+ { 0x0612, 0x02C0 }, /* R1554 - DAC2 Left Volume */
+ { 0x0613, 0x02C0 }, /* R1555 - DAC2 Right Volume */
+ { 0x0614, 0x0000 }, /* R1556 - DAC Softmute */
+ { 0x0620, 0x0002 }, /* R1568 - Oversampling */
+ { 0x0621, 0x0000 }, /* R1569 - Sidetone */
+ { 0x0700, 0x8100 }, /* R1792 - GPIO 1 */
+ { 0x0701, 0xA101 }, /* R1793 - GPIO 2 */
+ { 0x0702, 0xA101 }, /* R1794 - GPIO 3 */
+ { 0x0703, 0xA101 }, /* R1795 - GPIO 4 */
+ { 0x0704, 0xA101 }, /* R1796 - GPIO 5 */
+ { 0x0705, 0xA101 }, /* R1797 - GPIO 6 */
+ { 0x0706, 0xA101 }, /* R1798 - GPIO 7 */
+ { 0x0707, 0xA101 }, /* R1799 - GPIO 8 */
+ { 0x0708, 0xA101 }, /* R1800 - GPIO 9 */
+ { 0x0709, 0xA101 }, /* R1801 - GPIO 10 */
+ { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */
+ { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */
+ { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */
+ { 0x0730, 0x0000 }, /* R1840 - Interrupt Status 1 */
+ { 0x0731, 0x0000 }, /* R1841 - Interrupt Status 2 */
+ { 0x0732, 0x0000 }, /* R1842 - Interrupt Raw Status 2 */
+ { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */
+ { 0x0739, 0xFFFF }, /* R1849 - Interrupt Status 2 Mask */
+ { 0x0740, 0x0000 }, /* R1856 - Interrupt Control */
+ { 0x0748, 0x003F }, /* R1864 - IRQ Debounce */
+};
+
+static struct reg_default wm8958_defaults[] = {
+ { 0x0000, 0x8958 }, /* R0 - Software Reset */
+ { 0x0001, 0x0000 }, /* R1 - Power Management (1) */
+ { 0x0002, 0x6000 }, /* R2 - Power Management (2) */
+ { 0x0003, 0x0000 }, /* R3 - Power Management (3) */
+ { 0x0004, 0x0000 }, /* R4 - Power Management (4) */
+ { 0x0005, 0x0000 }, /* R5 - Power Management (5) */
+ { 0x0006, 0x0000 }, /* R6 - Power Management (6) */
+ { 0x0015, 0x0000 }, /* R21 - Input Mixer (1) */
+ { 0x0018, 0x008B }, /* R24 - Left Line Input 1&2 Volume */
+ { 0x0019, 0x008B }, /* R25 - Left Line Input 3&4 Volume */
+ { 0x001A, 0x008B }, /* R26 - Right Line Input 1&2 Volume */
+ { 0x001B, 0x008B }, /* R27 - Right Line Input 3&4 Volume */
+ { 0x001C, 0x006D }, /* R28 - Left Output Volume */
+ { 0x001D, 0x006D }, /* R29 - Right Output Volume */
+ { 0x001E, 0x0066 }, /* R30 - Line Outputs Volume */
+ { 0x001F, 0x0020 }, /* R31 - HPOUT2 Volume */
+ { 0x0020, 0x0079 }, /* R32 - Left OPGA Volume */
+ { 0x0021, 0x0079 }, /* R33 - Right OPGA Volume */
+ { 0x0022, 0x0003 }, /* R34 - SPKMIXL Attenuation */
+ { 0x0023, 0x0003 }, /* R35 - SPKMIXR Attenuation */
+ { 0x0024, 0x0011 }, /* R36 - SPKOUT Mixers */
+ { 0x0025, 0x0140 }, /* R37 - ClassD */
+ { 0x0026, 0x0079 }, /* R38 - Speaker Volume Left */
+ { 0x0027, 0x0079 }, /* R39 - Speaker Volume Right */
+ { 0x0028, 0x0000 }, /* R40 - Input Mixer (2) */
+ { 0x0029, 0x0000 }, /* R41 - Input Mixer (3) */
+ { 0x002A, 0x0000 }, /* R42 - Input Mixer (4) */
+ { 0x002B, 0x0000 }, /* R43 - Input Mixer (5) */
+ { 0x002C, 0x0000 }, /* R44 - Input Mixer (6) */
+ { 0x002D, 0x0000 }, /* R45 - Output Mixer (1) */
+ { 0x002E, 0x0000 }, /* R46 - Output Mixer (2) */
+ { 0x002F, 0x0000 }, /* R47 - Output Mixer (3) */
+ { 0x0030, 0x0000 }, /* R48 - Output Mixer (4) */
+ { 0x0031, 0x0000 }, /* R49 - Output Mixer (5) */
+ { 0x0032, 0x0000 }, /* R50 - Output Mixer (6) */
+ { 0x0033, 0x0000 }, /* R51 - HPOUT2 Mixer */
+ { 0x0034, 0x0000 }, /* R52 - Line Mixer (1) */
+ { 0x0035, 0x0000 }, /* R53 - Line Mixer (2) */
+ { 0x0036, 0x0000 }, /* R54 - Speaker Mixer */
+ { 0x0037, 0x0000 }, /* R55 - Additional Control */
+ { 0x0038, 0x0000 }, /* R56 - AntiPOP (1) */
+ { 0x0039, 0x0180 }, /* R57 - AntiPOP (2) */
+ { 0x003B, 0x000D }, /* R59 - LDO 1 */
+ { 0x003C, 0x0005 }, /* R60 - LDO 2 */
+ { 0x003D, 0x0039 }, /* R61 - MICBIAS1 */
+ { 0x003E, 0x0039 }, /* R62 - MICBIAS2 */
+ { 0x004C, 0x1F25 }, /* R76 - Charge Pump (1) */
+ { 0x004D, 0xAB19 }, /* R77 - Charge Pump (2) */
+ { 0x0051, 0x0004 }, /* R81 - Class W (1) */
+ { 0x0055, 0x054A }, /* R85 - DC Servo (2) */
+ { 0x0057, 0x0000 }, /* R87 - DC Servo (4) */
+ { 0x0060, 0x0000 }, /* R96 - Analogue HP (1) */
+ { 0x00C5, 0x0000 }, /* R197 - Class D Test (5) */
+ { 0x00D0, 0x5600 }, /* R208 - Mic Detect 1 */
+ { 0x00D1, 0x007F }, /* R209 - Mic Detect 2 */
+ { 0x0101, 0x8004 }, /* R257 - Control Interface */
+ { 0x0110, 0x0000 }, /* R272 - Write Sequencer Ctrl (1) */
+ { 0x0111, 0x0000 }, /* R273 - Write Sequencer Ctrl (2) */
+ { 0x0200, 0x0000 }, /* R512 - AIF1 Clocking (1) */
+ { 0x0201, 0x0000 }, /* R513 - AIF1 Clocking (2) */
+ { 0x0204, 0x0000 }, /* R516 - AIF2 Clocking (1) */
+ { 0x0205, 0x0000 }, /* R517 - AIF2 Clocking (2) */
+ { 0x0208, 0x0000 }, /* R520 - Clocking (1) */
+ { 0x0209, 0x0000 }, /* R521 - Clocking (2) */
+ { 0x0210, 0x0083 }, /* R528 - AIF1 Rate */
+ { 0x0211, 0x0083 }, /* R529 - AIF2 Rate */
+ { 0x0220, 0x0000 }, /* R544 - FLL1 Control (1) */
+ { 0x0221, 0x0000 }, /* R545 - FLL1 Control (2) */
+ { 0x0222, 0x0000 }, /* R546 - FLL1 Control (3) */
+ { 0x0223, 0x0000 }, /* R547 - FLL1 Control (4) */
+ { 0x0224, 0x0C80 }, /* R548 - FLL1 Control (5) */
+ { 0x0226, 0x0000 }, /* R550 - FLL1 EFS 1 */
+ { 0x0227, 0x0006 }, /* R551 - FLL1 EFS 2 */
+ { 0x0240, 0x0000 }, /* R576 - FLL2Control (1) */
+ { 0x0241, 0x0000 }, /* R577 - FLL2Control (2) */
+ { 0x0242, 0x0000 }, /* R578 - FLL2Control (3) */
+ { 0x0243, 0x0000 }, /* R579 - FLL2 Control (4) */
+ { 0x0244, 0x0C80 }, /* R580 - FLL2Control (5) */
+ { 0x0246, 0x0000 }, /* R582 - FLL2 EFS 1 */
+ { 0x0247, 0x0006 }, /* R583 - FLL2 EFS 2 */
+ { 0x0300, 0x4050 }, /* R768 - AIF1 Control (1) */
+ { 0x0301, 0x4000 }, /* R769 - AIF1 Control (2) */
+ { 0x0302, 0x0000 }, /* R770 - AIF1 Master/Slave */
+ { 0x0303, 0x0040 }, /* R771 - AIF1 BCLK */
+ { 0x0304, 0x0040 }, /* R772 - AIF1ADC LRCLK */
+ { 0x0305, 0x0040 }, /* R773 - AIF1DAC LRCLK */
+ { 0x0306, 0x0004 }, /* R774 - AIF1DAC Data */
+ { 0x0307, 0x0100 }, /* R775 - AIF1ADC Data */
+ { 0x0310, 0x4053 }, /* R784 - AIF2 Control (1) */
+ { 0x0311, 0x4000 }, /* R785 - AIF2 Control (2) */
+ { 0x0312, 0x0000 }, /* R786 - AIF2 Master/Slave */
+ { 0x0313, 0x0040 }, /* R787 - AIF2 BCLK */
+ { 0x0314, 0x0040 }, /* R788 - AIF2ADC LRCLK */
+ { 0x0315, 0x0040 }, /* R789 - AIF2DAC LRCLK */
+ { 0x0316, 0x0000 }, /* R790 - AIF2DAC Data */
+ { 0x0317, 0x0000 }, /* R791 - AIF2ADC Data */
+ { 0x0320, 0x0040 }, /* R800 - AIF3 Control (1) */
+ { 0x0321, 0x0000 }, /* R801 - AIF3 Control (2) */
+ { 0x0322, 0x0000 }, /* R802 - AIF3DAC Data */
+ { 0x0323, 0x0000 }, /* R803 - AIF3ADC Data */
+ { 0x0400, 0x00C0 }, /* R1024 - AIF1 ADC1 Left Volume */
+ { 0x0401, 0x00C0 }, /* R1025 - AIF1 ADC1 Right Volume */
+ { 0x0402, 0x00C0 }, /* R1026 - AIF1 DAC1 Left Volume */
+ { 0x0403, 0x00C0 }, /* R1027 - AIF1 DAC1 Right Volume */
+ { 0x0404, 0x00C0 }, /* R1028 - AIF1 ADC2 Left Volume */
+ { 0x0405, 0x00C0 }, /* R1029 - AIF1 ADC2 Right Volume */
+ { 0x0406, 0x00C0 }, /* R1030 - AIF1 DAC2 Left Volume */
+ { 0x0407, 0x00C0 }, /* R1031 - AIF1 DAC2 Right Volume */
+ { 0x0410, 0x0000 }, /* R1040 - AIF1 ADC1 Filters */
+ { 0x0411, 0x0000 }, /* R1041 - AIF1 ADC2 Filters */
+ { 0x0420, 0x0200 }, /* R1056 - AIF1 DAC1 Filters (1) */
+ { 0x0421, 0x0010 }, /* R1057 - AIF1 DAC1 Filters (2) */
+ { 0x0422, 0x0200 }, /* R1058 - AIF1 DAC2 Filters (1) */
+ { 0x0423, 0x0010 }, /* R1059 - AIF1 DAC2 Filters (2) */
+ { 0x0430, 0x0068 }, /* R1072 - AIF1 DAC1 Noise Gate */
+ { 0x0431, 0x0068 }, /* R1073 - AIF1 DAC2 Noise Gate */
+ { 0x0440, 0x0098 }, /* R1088 - AIF1 DRC1 (1) */
+ { 0x0441, 0x0845 }, /* R1089 - AIF1 DRC1 (2) */
+ { 0x0442, 0x0000 }, /* R1090 - AIF1 DRC1 (3) */
+ { 0x0443, 0x0000 }, /* R1091 - AIF1 DRC1 (4) */
+ { 0x0444, 0x0000 }, /* R1092 - AIF1 DRC1 (5) */
+ { 0x0450, 0x0098 }, /* R1104 - AIF1 DRC2 (1) */
+ { 0x0451, 0x0845 }, /* R1105 - AIF1 DRC2 (2) */
+ { 0x0452, 0x0000 }, /* R1106 - AIF1 DRC2 (3) */
+ { 0x0453, 0x0000 }, /* R1107 - AIF1 DRC2 (4) */
+ { 0x0454, 0x0000 }, /* R1108 - AIF1 DRC2 (5) */
+ { 0x0480, 0x6318 }, /* R1152 - AIF1 DAC1 EQ Gains (1) */
+ { 0x0481, 0x6300 }, /* R1153 - AIF1 DAC1 EQ Gains (2) */
+ { 0x0482, 0x0FCA }, /* R1154 - AIF1 DAC1 EQ Band 1 A */
+ { 0x0483, 0x0400 }, /* R1155 - AIF1 DAC1 EQ Band 1 B */
+ { 0x0484, 0x00D8 }, /* R1156 - AIF1 DAC1 EQ Band 1 PG */
+ { 0x0485, 0x1EB5 }, /* R1157 - AIF1 DAC1 EQ Band 2 A */
+ { 0x0486, 0xF145 }, /* R1158 - AIF1 DAC1 EQ Band 2 B */
+ { 0x0487, 0x0B75 }, /* R1159 - AIF1 DAC1 EQ Band 2 C */
+ { 0x0488, 0x01C5 }, /* R1160 - AIF1 DAC1 EQ Band 2 PG */
+ { 0x0489, 0x1C58 }, /* R1161 - AIF1 DAC1 EQ Band 3 A */
+ { 0x048A, 0xF373 }, /* R1162 - AIF1 DAC1 EQ Band 3 B */
+ { 0x048B, 0x0A54 }, /* R1163 - AIF1 DAC1 EQ Band 3 C */
+ { 0x048C, 0x0558 }, /* R1164 - AIF1 DAC1 EQ Band 3 PG */
+ { 0x048D, 0x168E }, /* R1165 - AIF1 DAC1 EQ Band 4 A */
+ { 0x048E, 0xF829 }, /* R1166 - AIF1 DAC1 EQ Band 4 B */
+ { 0x048F, 0x07AD }, /* R1167 - AIF1 DAC1 EQ Band 4 C */
+ { 0x0490, 0x1103 }, /* R1168 - AIF1 DAC1 EQ Band 4 PG */
+ { 0x0491, 0x0564 }, /* R1169 - AIF1 DAC1 EQ Band 5 A */
+ { 0x0492, 0x0559 }, /* R1170 - AIF1 DAC1 EQ Band 5 B */
+ { 0x0493, 0x4000 }, /* R1171 - AIF1 DAC1 EQ Band 5 PG */
+ { 0x0494, 0x0000 }, /* R1172 - AIF1 DAC1 EQ Band 1 C */
+ { 0x04A0, 0x6318 }, /* R1184 - AIF1 DAC2 EQ Gains (1) */
+ { 0x04A1, 0x6300 }, /* R1185 - AIF1 DAC2 EQ Gains (2) */
+ { 0x04A2, 0x0FCA }, /* R1186 - AIF1 DAC2 EQ Band 1 A */
+ { 0x04A3, 0x0400 }, /* R1187 - AIF1 DAC2 EQ Band 1 B */
+ { 0x04A4, 0x00D8 }, /* R1188 - AIF1 DAC2 EQ Band 1 PG */
+ { 0x04A5, 0x1EB5 }, /* R1189 - AIF1 DAC2 EQ Band 2 A */
+ { 0x04A6, 0xF145 }, /* R1190 - AIF1 DAC2 EQ Band 2 B */
+ { 0x04A7, 0x0B75 }, /* R1191 - AIF1 DAC2 EQ Band 2 C */
+ { 0x04A8, 0x01C5 }, /* R1192 - AIF1 DAC2 EQ Band 2 PG */
+ { 0x04A9, 0x1C58 }, /* R1193 - AIF1 DAC2 EQ Band 3 A */
+ { 0x04AA, 0xF373 }, /* R1194 - AIF1 DAC2 EQ Band 3 B */
+ { 0x04AB, 0x0A54 }, /* R1195 - AIF1 DAC2 EQ Band 3 C */
+ { 0x04AC, 0x0558 }, /* R1196 - AIF1 DAC2 EQ Band 3 PG */
+ { 0x04AD, 0x168E }, /* R1197 - AIF1 DAC2 EQ Band 4 A */
+ { 0x04AE, 0xF829 }, /* R1198 - AIF1 DAC2 EQ Band 4 B */
+ { 0x04AF, 0x07AD }, /* R1199 - AIF1 DAC2 EQ Band 4 C */
+ { 0x04B0, 0x1103 }, /* R1200 - AIF1 DAC2 EQ Band 4 PG */
+ { 0x04B1, 0x0564 }, /* R1201 - AIF1 DAC2 EQ Band 5 A */
+ { 0x04B2, 0x0559 }, /* R1202 - AIF1 DAC2 EQ Band 5 B */
+ { 0x04B3, 0x4000 }, /* R1203 - AIF1 DAC2 EQ Band 5 PG */
+ { 0x04B4, 0x0000 }, /* R1204 - AIF1 DAC2EQ Band 1 C */
+ { 0x0500, 0x00C0 }, /* R1280 - AIF2 ADC Left Volume */
+ { 0x0501, 0x00C0 }, /* R1281 - AIF2 ADC Right Volume */
+ { 0x0502, 0x00C0 }, /* R1282 - AIF2 DAC Left Volume */
+ { 0x0503, 0x00C0 }, /* R1283 - AIF2 DAC Right Volume */
+ { 0x0510, 0x0000 }, /* R1296 - AIF2 ADC Filters */
+ { 0x0520, 0x0200 }, /* R1312 - AIF2 DAC Filters (1) */
+ { 0x0521, 0x0010 }, /* R1313 - AIF2 DAC Filters (2) */
+ { 0x0530, 0x0068 }, /* R1328 - AIF2 DAC Noise Gate */
+ { 0x0540, 0x0098 }, /* R1344 - AIF2 DRC (1) */
+ { 0x0541, 0x0845 }, /* R1345 - AIF2 DRC (2) */
+ { 0x0542, 0x0000 }, /* R1346 - AIF2 DRC (3) */
+ { 0x0543, 0x0000 }, /* R1347 - AIF2 DRC (4) */
+ { 0x0544, 0x0000 }, /* R1348 - AIF2 DRC (5) */
+ { 0x0580, 0x6318 }, /* R1408 - AIF2 EQ Gains (1) */
+ { 0x0581, 0x6300 }, /* R1409 - AIF2 EQ Gains (2) */
+ { 0x0582, 0x0FCA }, /* R1410 - AIF2 EQ Band 1 A */
+ { 0x0583, 0x0400 }, /* R1411 - AIF2 EQ Band 1 B */
+ { 0x0584, 0x00D8 }, /* R1412 - AIF2 EQ Band 1 PG */
+ { 0x0585, 0x1EB5 }, /* R1413 - AIF2 EQ Band 2 A */
+ { 0x0586, 0xF145 }, /* R1414 - AIF2 EQ Band 2 B */
+ { 0x0587, 0x0B75 }, /* R1415 - AIF2 EQ Band 2 C */
+ { 0x0588, 0x01C5 }, /* R1416 - AIF2 EQ Band 2 PG */
+ { 0x0589, 0x1C58 }, /* R1417 - AIF2 EQ Band 3 A */
+ { 0x058A, 0xF373 }, /* R1418 - AIF2 EQ Band 3 B */
+ { 0x058B, 0x0A54 }, /* R1419 - AIF2 EQ Band 3 C */
+ { 0x058C, 0x0558 }, /* R1420 - AIF2 EQ Band 3 PG */
+ { 0x058D, 0x168E }, /* R1421 - AIF2 EQ Band 4 A */
+ { 0x058E, 0xF829 }, /* R1422 - AIF2 EQ Band 4 B */
+ { 0x058F, 0x07AD }, /* R1423 - AIF2 EQ Band 4 C */
+ { 0x0590, 0x1103 }, /* R1424 - AIF2 EQ Band 4 PG */
+ { 0x0591, 0x0564 }, /* R1425 - AIF2 EQ Band 5 A */
+ { 0x0592, 0x0559 }, /* R1426 - AIF2 EQ Band 5 B */
+ { 0x0593, 0x4000 }, /* R1427 - AIF2 EQ Band 5 PG */
+ { 0x0594, 0x0000 }, /* R1428 - AIF2 EQ Band 1 C */
+ { 0x0600, 0x0000 }, /* R1536 - DAC1 Mixer Volumes */
+ { 0x0601, 0x0000 }, /* R1537 - DAC1 Left Mixer Routing */
+ { 0x0602, 0x0000 }, /* R1538 - DAC1 Right Mixer Routing */
+ { 0x0603, 0x0000 }, /* R1539 - DAC2 Mixer Volumes */
+ { 0x0604, 0x0000 }, /* R1540 - DAC2 Left Mixer Routing */
+ { 0x0605, 0x0000 }, /* R1541 - DAC2 Right Mixer Routing */
+ { 0x0606, 0x0000 }, /* R1542 - AIF1 ADC1 Left Mixer Routing */
+ { 0x0607, 0x0000 }, /* R1543 - AIF1 ADC1 Right Mixer Routing */
+ { 0x0608, 0x0000 }, /* R1544 - AIF1 ADC2 Left Mixer Routing */
+ { 0x0609, 0x0000 }, /* R1545 - AIF1 ADC2 Right mixer Routing */
+ { 0x0610, 0x02C0 }, /* R1552 - DAC1 Left Volume */
+ { 0x0611, 0x02C0 }, /* R1553 - DAC1 Right Volume */
+ { 0x0612, 0x02C0 }, /* R1554 - DAC2 Left Volume */
+ { 0x0613, 0x02C0 }, /* R1555 - DAC2 Right Volume */
+ { 0x0614, 0x0000 }, /* R1556 - DAC Softmute */
+ { 0x0620, 0x0002 }, /* R1568 - Oversampling */
+ { 0x0621, 0x0000 }, /* R1569 - Sidetone */
+ { 0x0700, 0x8100 }, /* R1792 - GPIO 1 */
+ { 0x0701, 0xA101 }, /* R1793 - Pull Control (MCLK2) */
+ { 0x0702, 0xA101 }, /* R1794 - Pull Control (BCLK2) */
+ { 0x0703, 0xA101 }, /* R1795 - Pull Control (DACLRCLK2) */
+ { 0x0704, 0xA101 }, /* R1796 - Pull Control (DACDAT2) */
+ { 0x0705, 0xA101 }, /* R1797 - GPIO 6 */
+ { 0x0707, 0xA101 }, /* R1799 - GPIO 8 */
+ { 0x0708, 0xA101 }, /* R1800 - GPIO 9 */
+ { 0x0709, 0xA101 }, /* R1801 - GPIO 10 */
+ { 0x070A, 0xA101 }, /* R1802 - GPIO 11 */
+ { 0x0720, 0x0000 }, /* R1824 - Pull Control (1) */
+ { 0x0721, 0x0156 }, /* R1825 - Pull Control (2) */
+ { 0x0738, 0x07FF }, /* R1848 - Interrupt Status 1 Mask */
+ { 0x0739, 0xFFEF }, /* R1849 - Interrupt Status 2 Mask */
+ { 0x0740, 0x0000 }, /* R1856 - Interrupt Control */
+ { 0x0748, 0x003F }, /* R1864 - IRQ Debounce */
+ { 0x0900, 0x1C00 }, /* R2304 - DSP2_Program */
+ { 0x0901, 0x0000 }, /* R2305 - DSP2_Config */
+ { 0x0A0D, 0x0000 }, /* R2573 - DSP2_ExecControl */
+ { 0x2400, 0x003F }, /* R9216 - MBC Band 1 K (1) */
+ { 0x2401, 0x8BD8 }, /* R9217 - MBC Band 1 K (2) */
+ { 0x2402, 0x0032 }, /* R9218 - MBC Band 1 N1 (1) */
+ { 0x2403, 0xF52D }, /* R9219 - MBC Band 1 N1 (2) */
+ { 0x2404, 0x0065 }, /* R9220 - MBC Band 1 N2 (1) */
+ { 0x2405, 0xAC8C }, /* R9221 - MBC Band 1 N2 (2) */
+ { 0x2406, 0x006B }, /* R9222 - MBC Band 1 N3 (1) */
+ { 0x2407, 0xE087 }, /* R9223 - MBC Band 1 N3 (2) */
+ { 0x2408, 0x0072 }, /* R9224 - MBC Band 1 N4 (1) */
+ { 0x2409, 0x1483 }, /* R9225 - MBC Band 1 N4 (2) */
+ { 0x240A, 0x0072 }, /* R9226 - MBC Band 1 N5 (1) */
+ { 0x240B, 0x1483 }, /* R9227 - MBC Band 1 N5 (2) */
+ { 0x240C, 0x0043 }, /* R9228 - MBC Band 1 X1 (1) */
+ { 0x240D, 0x3525 }, /* R9229 - MBC Band 1 X1 (2) */
+ { 0x240E, 0x0006 }, /* R9230 - MBC Band 1 X2 (1) */
+ { 0x240F, 0x6A4A }, /* R9231 - MBC Band 1 X2 (2) */
+ { 0x2410, 0x0043 }, /* R9232 - MBC Band 1 X3 (1) */
+ { 0x2411, 0x6079 }, /* R9233 - MBC Band 1 X3 (2) */
+ { 0x2412, 0x000C }, /* R9234 - MBC Band 1 Attack (1) */
+ { 0x2413, 0xCCCD }, /* R9235 - MBC Band 1 Attack (2) */
+ { 0x2414, 0x0000 }, /* R9236 - MBC Band 1 Decay (1) */
+ { 0x2415, 0x0800 }, /* R9237 - MBC Band 1 Decay (2) */
+ { 0x2416, 0x003F }, /* R9238 - MBC Band 2 K (1) */
+ { 0x2417, 0x8BD8 }, /* R9239 - MBC Band 2 K (2) */
+ { 0x2418, 0x0032 }, /* R9240 - MBC Band 2 N1 (1) */
+ { 0x2419, 0xF52D }, /* R9241 - MBC Band 2 N1 (2) */
+ { 0x241A, 0x0065 }, /* R9242 - MBC Band 2 N2 (1) */
+ { 0x241B, 0xAC8C }, /* R9243 - MBC Band 2 N2 (2) */
+ { 0x241C, 0x006B }, /* R9244 - MBC Band 2 N3 (1) */
+ { 0x241D, 0xE087 }, /* R9245 - MBC Band 2 N3 (2) */
+ { 0x241E, 0x0072 }, /* R9246 - MBC Band 2 N4 (1) */
+ { 0x241F, 0x1483 }, /* R9247 - MBC Band 2 N4 (2) */
+ { 0x2420, 0x0072 }, /* R9248 - MBC Band 2 N5 (1) */
+ { 0x2421, 0x1483 }, /* R9249 - MBC Band 2 N5 (2) */
+ { 0x2422, 0x0043 }, /* R9250 - MBC Band 2 X1 (1) */
+ { 0x2423, 0x3525 }, /* R9251 - MBC Band 2 X1 (2) */
+ { 0x2424, 0x0006 }, /* R9252 - MBC Band 2 X2 (1) */
+ { 0x2425, 0x6A4A }, /* R9253 - MBC Band 2 X2 (2) */
+ { 0x2426, 0x0043 }, /* R9254 - MBC Band 2 X3 (1) */
+ { 0x2427, 0x6079 }, /* R9255 - MBC Band 2 X3 (2) */
+ { 0x2428, 0x000C }, /* R9256 - MBC Band 2 Attack (1) */
+ { 0x2429, 0xCCCD }, /* R9257 - MBC Band 2 Attack (2) */
+ { 0x242A, 0x0000 }, /* R9258 - MBC Band 2 Decay (1) */
+ { 0x242B, 0x0800 }, /* R9259 - MBC Band 2 Decay (2) */
+ { 0x242C, 0x005A }, /* R9260 - MBC_B2_PG2 (1) */
+ { 0x242D, 0x7EFA }, /* R9261 - MBC_B2_PG2 (2) */
+ { 0x242E, 0x005A }, /* R9262 - MBC_B1_PG2 (1) */
+ { 0x242F, 0x7EFA }, /* R9263 - MBC_B1_PG2 (2) */
+ { 0x2600, 0x00A7 }, /* R9728 - MBC Crossover (1) */
+ { 0x2601, 0x0D1C }, /* R9729 - MBC Crossover (2) */
+ { 0x2602, 0x0083 }, /* R9730 - MBC HPF (1) */
+ { 0x2603, 0x98AD }, /* R9731 - MBC HPF (2) */
+ { 0x2606, 0x0008 }, /* R9734 - MBC LPF (1) */
+ { 0x2607, 0xE7A2 }, /* R9735 - MBC LPF (2) */
+ { 0x260A, 0x0055 }, /* R9738 - MBC RMS Limit (1) */
+ { 0x260B, 0x8C4B }, /* R9739 - MBC RMS Limit (2) */
+};
+
+static bool wm1811_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8994_SOFTWARE_RESET:
+ case WM8994_POWER_MANAGEMENT_1:
+ case WM8994_POWER_MANAGEMENT_2:
+ case WM8994_POWER_MANAGEMENT_3:
+ case WM8994_POWER_MANAGEMENT_4:
+ case WM8994_POWER_MANAGEMENT_5:
+ case WM8994_POWER_MANAGEMENT_6:
+ case WM8994_INPUT_MIXER_1:
+ case WM8994_LEFT_LINE_INPUT_1_2_VOLUME:
+ case WM8994_LEFT_LINE_INPUT_3_4_VOLUME:
+ case WM8994_RIGHT_LINE_INPUT_1_2_VOLUME:
+ case WM8994_RIGHT_LINE_INPUT_3_4_VOLUME:
+ case WM8994_LEFT_OUTPUT_VOLUME:
+ case WM8994_RIGHT_OUTPUT_VOLUME:
+ case WM8994_LINE_OUTPUTS_VOLUME:
+ case WM8994_HPOUT2_VOLUME:
+ case WM8994_LEFT_OPGA_VOLUME:
+ case WM8994_RIGHT_OPGA_VOLUME:
+ case WM8994_SPKMIXL_ATTENUATION:
+ case WM8994_SPKMIXR_ATTENUATION:
+ case WM8994_SPKOUT_MIXERS:
+ case WM8994_CLASSD:
+ case WM8994_SPEAKER_VOLUME_LEFT:
+ case WM8994_SPEAKER_VOLUME_RIGHT:
+ case WM8994_INPUT_MIXER_2:
+ case WM8994_INPUT_MIXER_3:
+ case WM8994_INPUT_MIXER_4:
+ case WM8994_INPUT_MIXER_5:
+ case WM8994_INPUT_MIXER_6:
+ case WM8994_OUTPUT_MIXER_1:
+ case WM8994_OUTPUT_MIXER_2:
+ case WM8994_OUTPUT_MIXER_3:
+ case WM8994_OUTPUT_MIXER_4:
+ case WM8994_OUTPUT_MIXER_5:
+ case WM8994_OUTPUT_MIXER_6:
+ case WM8994_HPOUT2_MIXER:
+ case WM8994_LINE_MIXER_1:
+ case WM8994_LINE_MIXER_2:
+ case WM8994_SPEAKER_MIXER:
+ case WM8994_ADDITIONAL_CONTROL:
+ case WM8994_ANTIPOP_1:
+ case WM8994_ANTIPOP_2:
+ case WM8994_LDO_1:
+ case WM8994_LDO_2:
+ case WM8958_MICBIAS1:
+ case WM8958_MICBIAS2:
+ case WM8994_CHARGE_PUMP_1:
+ case WM8958_CHARGE_PUMP_2:
+ case WM8994_CLASS_W_1:
+ case WM8994_DC_SERVO_1:
+ case WM8994_DC_SERVO_2:
+ case WM8994_DC_SERVO_READBACK:
+ case WM8994_DC_SERVO_4:
+ case WM8994_ANALOGUE_HP_1:
+ case WM8958_MIC_DETECT_1:
+ case WM8958_MIC_DETECT_2:
+ case WM8958_MIC_DETECT_3:
+ case WM8994_CHIP_REVISION:
+ case WM8994_CONTROL_INTERFACE:
+ case WM8994_AIF1_CLOCKING_1:
+ case WM8994_AIF1_CLOCKING_2:
+ case WM8994_AIF2_CLOCKING_1:
+ case WM8994_AIF2_CLOCKING_2:
+ case WM8994_CLOCKING_1:
+ case WM8994_CLOCKING_2:
+ case WM8994_AIF1_RATE:
+ case WM8994_AIF2_RATE:
+ case WM8994_RATE_STATUS:
+ case WM8994_FLL1_CONTROL_1:
+ case WM8994_FLL1_CONTROL_2:
+ case WM8994_FLL1_CONTROL_3:
+ case WM8994_FLL1_CONTROL_4:
+ case WM8994_FLL1_CONTROL_5:
+ case WM8958_FLL1_EFS_1:
+ case WM8958_FLL1_EFS_2:
+ case WM8994_FLL2_CONTROL_1:
+ case WM8994_FLL2_CONTROL_2:
+ case WM8994_FLL2_CONTROL_3:
+ case WM8994_FLL2_CONTROL_4:
+ case WM8994_FLL2_CONTROL_5:
+ case WM8958_FLL2_EFS_1:
+ case WM8958_FLL2_EFS_2:
+ case WM8994_AIF1_CONTROL_1:
+ case WM8994_AIF1_CONTROL_2:
+ case WM8994_AIF1_MASTER_SLAVE:
+ case WM8994_AIF1_BCLK:
+ case WM8994_AIF1ADC_LRCLK:
+ case WM8994_AIF1DAC_LRCLK:
+ case WM8994_AIF1DAC_DATA:
+ case WM8994_AIF1ADC_DATA:
+ case WM8994_AIF2_CONTROL_1:
+ case WM8994_AIF2_CONTROL_2:
+ case WM8994_AIF2_MASTER_SLAVE:
+ case WM8994_AIF2_BCLK:
+ case WM8994_AIF2ADC_LRCLK:
+ case WM8994_AIF2DAC_LRCLK:
+ case WM8994_AIF2DAC_DATA:
+ case WM8994_AIF2ADC_DATA:
+ case WM1811_AIF2TX_CONTROL:
+ case WM8958_AIF3_CONTROL_1:
+ case WM8958_AIF3_CONTROL_2:
+ case WM8958_AIF3DAC_DATA:
+ case WM8958_AIF3ADC_DATA:
+ case WM8994_AIF1_ADC1_LEFT_VOLUME:
+ case WM8994_AIF1_ADC1_RIGHT_VOLUME:
+ case WM8994_AIF1_DAC1_LEFT_VOLUME:
+ case WM8994_AIF1_DAC1_RIGHT_VOLUME:
+ case WM8994_AIF1_ADC1_FILTERS:
+ case WM8994_AIF1_DAC1_FILTERS_1:
+ case WM8994_AIF1_DAC1_FILTERS_2:
+ case WM8958_AIF1_DAC1_NOISE_GATE:
+ case WM8994_AIF1_DRC1_1:
+ case WM8994_AIF1_DRC1_2:
+ case WM8994_AIF1_DRC1_3:
+ case WM8994_AIF1_DRC1_4:
+ case WM8994_AIF1_DRC1_5:
+ case WM8994_AIF1_DAC1_EQ_GAINS_1:
+ case WM8994_AIF1_DAC1_EQ_GAINS_2:
+ case WM8994_AIF1_DAC1_EQ_BAND_1_A:
+ case WM8994_AIF1_DAC1_EQ_BAND_1_B:
+ case WM8994_AIF1_DAC1_EQ_BAND_1_PG:
+ case WM8994_AIF1_DAC1_EQ_BAND_2_A:
+ case WM8994_AIF1_DAC1_EQ_BAND_2_B:
+ case WM8994_AIF1_DAC1_EQ_BAND_2_C:
+ case WM8994_AIF1_DAC1_EQ_BAND_2_PG:
+ case WM8994_AIF1_DAC1_EQ_BAND_3_A:
+ case WM8994_AIF1_DAC1_EQ_BAND_3_B:
+ case WM8994_AIF1_DAC1_EQ_BAND_3_C:
+ case WM8994_AIF1_DAC1_EQ_BAND_3_PG:
+ case WM8994_AIF1_DAC1_EQ_BAND_4_A:
+ case WM8994_AIF1_DAC1_EQ_BAND_4_B:
+ case WM8994_AIF1_DAC1_EQ_BAND_4_C:
+ case WM8994_AIF1_DAC1_EQ_BAND_4_PG:
+ case WM8994_AIF1_DAC1_EQ_BAND_5_A:
+ case WM8994_AIF1_DAC1_EQ_BAND_5_B:
+ case WM8994_AIF1_DAC1_EQ_BAND_5_PG:
+ case WM8994_AIF1_DAC1_EQ_BAND_1_C:
+ case WM8994_AIF2_ADC_LEFT_VOLUME:
+ case WM8994_AIF2_ADC_RIGHT_VOLUME:
+ case WM8994_AIF2_DAC_LEFT_VOLUME:
+ case WM8994_AIF2_DAC_RIGHT_VOLUME:
+ case WM8994_AIF2_ADC_FILTERS:
+ case WM8994_AIF2_DAC_FILTERS_1:
+ case WM8994_AIF2_DAC_FILTERS_2:
+ case WM8958_AIF2_DAC_NOISE_GATE:
+ case WM8994_AIF2_DRC_1:
+ case WM8994_AIF2_DRC_2:
+ case WM8994_AIF2_DRC_3:
+ case WM8994_AIF2_DRC_4:
+ case WM8994_AIF2_DRC_5:
+ case WM8994_AIF2_EQ_GAINS_1:
+ case WM8994_AIF2_EQ_GAINS_2:
+ case WM8994_AIF2_EQ_BAND_1_A:
+ case WM8994_AIF2_EQ_BAND_1_B:
+ case WM8994_AIF2_EQ_BAND_1_PG:
+ case WM8994_AIF2_EQ_BAND_2_A:
+ case WM8994_AIF2_EQ_BAND_2_B:
+ case WM8994_AIF2_EQ_BAND_2_C:
+ case WM8994_AIF2_EQ_BAND_2_PG:
+ case WM8994_AIF2_EQ_BAND_3_A:
+ case WM8994_AIF2_EQ_BAND_3_B:
+ case WM8994_AIF2_EQ_BAND_3_C:
+ case WM8994_AIF2_EQ_BAND_3_PG:
+ case WM8994_AIF2_EQ_BAND_4_A:
+ case WM8994_AIF2_EQ_BAND_4_B:
+ case WM8994_AIF2_EQ_BAND_4_C:
+ case WM8994_AIF2_EQ_BAND_4_PG:
+ case WM8994_AIF2_EQ_BAND_5_A:
+ case WM8994_AIF2_EQ_BAND_5_B:
+ case WM8994_AIF2_EQ_BAND_5_PG:
+ case WM8994_AIF2_EQ_BAND_1_C:
+ case WM8994_DAC1_MIXER_VOLUMES:
+ case WM8994_DAC1_LEFT_MIXER_ROUTING:
+ case WM8994_DAC1_RIGHT_MIXER_ROUTING:
+ case WM8994_DAC2_MIXER_VOLUMES:
+ case WM8994_DAC2_LEFT_MIXER_ROUTING:
+ case WM8994_DAC2_RIGHT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC1_LEFT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC1_RIGHT_MIXER_ROUTING:
+ case WM8994_DAC1_LEFT_VOLUME:
+ case WM8994_DAC1_RIGHT_VOLUME:
+ case WM8994_DAC2_LEFT_VOLUME:
+ case WM8994_DAC2_RIGHT_VOLUME:
+ case WM8994_DAC_SOFTMUTE:
+ case WM8994_OVERSAMPLING:
+ case WM8994_SIDETONE:
+ case WM8994_GPIO_1:
+ case WM8994_GPIO_2:
+ case WM8994_GPIO_3:
+ case WM8994_GPIO_4:
+ case WM8994_GPIO_5:
+ case WM8994_GPIO_6:
+ case WM8994_GPIO_8:
+ case WM8994_GPIO_9:
+ case WM8994_GPIO_10:
+ case WM8994_GPIO_11:
+ case WM8994_PULL_CONTROL_1:
+ case WM8994_PULL_CONTROL_2:
+ case WM8994_INTERRUPT_STATUS_1:
+ case WM8994_INTERRUPT_STATUS_2:
+ case WM8994_INTERRUPT_RAW_STATUS_2:
+ case WM8994_INTERRUPT_STATUS_1_MASK:
+ case WM8994_INTERRUPT_STATUS_2_MASK:
+ case WM8994_INTERRUPT_CONTROL:
+ case WM8994_IRQ_DEBOUNCE:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm8994_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8994_DC_SERVO_READBACK:
+ case WM8994_WRITE_SEQUENCER_CTRL_1:
+ case WM8994_WRITE_SEQUENCER_CTRL_2:
+ case WM8994_AIF1_ADC2_LEFT_VOLUME:
+ case WM8994_AIF1_ADC2_RIGHT_VOLUME:
+ case WM8994_AIF1_DAC2_LEFT_VOLUME:
+ case WM8994_AIF1_DAC2_RIGHT_VOLUME:
+ case WM8994_AIF1_ADC2_FILTERS:
+ case WM8994_AIF1_DAC2_FILTERS_1:
+ case WM8994_AIF1_DAC2_FILTERS_2:
+ case WM8958_AIF1_DAC2_NOISE_GATE:
+ case WM8994_AIF1_DRC2_1:
+ case WM8994_AIF1_DRC2_2:
+ case WM8994_AIF1_DRC2_3:
+ case WM8994_AIF1_DRC2_4:
+ case WM8994_AIF1_DRC2_5:
+ case WM8994_AIF1_DAC2_EQ_GAINS_1:
+ case WM8994_AIF1_DAC2_EQ_GAINS_2:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_2_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_3_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_C:
+ case WM8994_AIF1_DAC2_EQ_BAND_4_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_A:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_B:
+ case WM8994_AIF1_DAC2_EQ_BAND_5_PG:
+ case WM8994_AIF1_DAC2_EQ_BAND_1_C:
+ case WM8994_DAC2_MIXER_VOLUMES:
+ case WM8994_DAC2_LEFT_MIXER_ROUTING:
+ case WM8994_DAC2_RIGHT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC2_LEFT_MIXER_ROUTING:
+ case WM8994_AIF1_ADC2_RIGHT_MIXER_ROUTING:
+ case WM8994_DAC2_LEFT_VOLUME:
+ case WM8994_DAC2_RIGHT_VOLUME:
+ return true;
+ default:
+ return wm1811_readable_register(dev, reg);
+ }
+}
+
+static bool wm8958_readable_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8958_DSP2_PROGRAM:
+ case WM8958_DSP2_CONFIG:
+ case WM8958_DSP2_MAGICNUM:
+ case WM8958_DSP2_RELEASEYEAR:
+ case WM8958_DSP2_RELEASEMONTHDAY:
+ case WM8958_DSP2_RELEASETIME:
+ case WM8958_DSP2_VERMAJMIN:
+ case WM8958_DSP2_VERBUILD:
+ case WM8958_DSP2_TESTREG:
+ case WM8958_DSP2_XORREG:
+ case WM8958_DSP2_SHIFTMAXX:
+ case WM8958_DSP2_SHIFTMAXY:
+ case WM8958_DSP2_SHIFTMAXZ:
+ case WM8958_DSP2_SHIFTMAXEXTLO:
+ case WM8958_DSP2_AESSELECT:
+ case WM8958_DSP2_EXECCONTROL:
+ case WM8958_DSP2_SAMPLEBREAK:
+ case WM8958_DSP2_COUNTBREAK:
+ case WM8958_DSP2_INTSTATUS:
+ case WM8958_DSP2_EVENTSTATUS:
+ case WM8958_DSP2_INTMASK:
+ case WM8958_DSP2_CONFIGDWIDTH:
+ case WM8958_DSP2_CONFIGINSTR:
+ case WM8958_DSP2_CONFIGDMEM:
+ case WM8958_DSP2_CONFIGDELAYS:
+ case WM8958_DSP2_CONFIGNUMIO:
+ case WM8958_DSP2_CONFIGEXTDEPTH:
+ case WM8958_DSP2_CONFIGMULTIPLIER:
+ case WM8958_DSP2_CONFIGCTRLDWIDTH:
+ case WM8958_DSP2_CONFIGPIPELINE:
+ case WM8958_DSP2_SHIFTMAXEXTHI:
+ case WM8958_DSP2_SWVERSIONREG:
+ case WM8958_DSP2_CONFIGXMEM:
+ case WM8958_DSP2_CONFIGYMEM:
+ case WM8958_DSP2_CONFIGZMEM:
+ case WM8958_FW_BUILD_1:
+ case WM8958_FW_BUILD_0:
+ case WM8958_FW_ID_1:
+ case WM8958_FW_ID_0:
+ case WM8958_FW_MAJOR_1:
+ case WM8958_FW_MAJOR_0:
+ case WM8958_FW_MINOR_1:
+ case WM8958_FW_MINOR_0:
+ case WM8958_FW_PATCH_1:
+ case WM8958_FW_PATCH_0:
+ case WM8958_MBC_BAND_1_K_1:
+ case WM8958_MBC_BAND_1_K_2:
+ case WM8958_MBC_BAND_1_N1_1:
+ case WM8958_MBC_BAND_1_N1_2:
+ case WM8958_MBC_BAND_1_N2_1:
+ case WM8958_MBC_BAND_1_N2_2:
+ case WM8958_MBC_BAND_1_N3_1:
+ case WM8958_MBC_BAND_1_N3_2:
+ case WM8958_MBC_BAND_1_N4_1:
+ case WM8958_MBC_BAND_1_N4_2:
+ case WM8958_MBC_BAND_1_N5_1:
+ case WM8958_MBC_BAND_1_N5_2:
+ case WM8958_MBC_BAND_1_X1_1:
+ case WM8958_MBC_BAND_1_X1_2:
+ case WM8958_MBC_BAND_1_X2_1:
+ case WM8958_MBC_BAND_1_X2_2:
+ case WM8958_MBC_BAND_1_X3_1:
+ case WM8958_MBC_BAND_1_X3_2:
+ case WM8958_MBC_BAND_1_ATTACK_1:
+ case WM8958_MBC_BAND_1_ATTACK_2:
+ case WM8958_MBC_BAND_1_DECAY_1:
+ case WM8958_MBC_BAND_1_DECAY_2:
+ case WM8958_MBC_BAND_2_K_1:
+ case WM8958_MBC_BAND_2_K_2:
+ case WM8958_MBC_BAND_2_N1_1:
+ case WM8958_MBC_BAND_2_N1_2:
+ case WM8958_MBC_BAND_2_N2_1:
+ case WM8958_MBC_BAND_2_N2_2:
+ case WM8958_MBC_BAND_2_N3_1:
+ case WM8958_MBC_BAND_2_N3_2:
+ case WM8958_MBC_BAND_2_N4_1:
+ case WM8958_MBC_BAND_2_N4_2:
+ case WM8958_MBC_BAND_2_N5_1:
+ case WM8958_MBC_BAND_2_N5_2:
+ case WM8958_MBC_BAND_2_X1_1:
+ case WM8958_MBC_BAND_2_X1_2:
+ case WM8958_MBC_BAND_2_X2_1:
+ case WM8958_MBC_BAND_2_X2_2:
+ case WM8958_MBC_BAND_2_X3_1:
+ case WM8958_MBC_BAND_2_X3_2:
+ case WM8958_MBC_BAND_2_ATTACK_1:
+ case WM8958_MBC_BAND_2_ATTACK_2:
+ case WM8958_MBC_BAND_2_DECAY_1:
+ case WM8958_MBC_BAND_2_DECAY_2:
+ case WM8958_MBC_B2_PG2_1:
+ case WM8958_MBC_B2_PG2_2:
+ case WM8958_MBC_B1_PG2_1:
+ case WM8958_MBC_B1_PG2_2:
+ case WM8958_MBC_CROSSOVER_1:
+ case WM8958_MBC_CROSSOVER_2:
+ case WM8958_MBC_HPF_1:
+ case WM8958_MBC_HPF_2:
+ case WM8958_MBC_LPF_1:
+ case WM8958_MBC_LPF_2:
+ case WM8958_MBC_RMS_LIMIT_1:
+ case WM8958_MBC_RMS_LIMIT_2:
+ return true;
+ default:
+ return wm8994_readable_register(dev, reg);
+ }
+}
+
+static bool wm8994_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8994_SOFTWARE_RESET:
+ case WM8994_DC_SERVO_1:
+ case WM8994_DC_SERVO_READBACK:
+ case WM8994_RATE_STATUS:
+ case WM8958_MIC_DETECT_3:
+ case WM8994_DC_SERVO_4E:
+ case WM8994_CHIP_REVISION:
+ case WM8994_INTERRUPT_STATUS_1:
+ case WM8994_INTERRUPT_STATUS_2:
+ return true;
+ default:
+ return false;
+ }
+}
+
+static bool wm1811_volatile_register(struct device *dev, unsigned int reg)
+{
+ struct wm8994 *wm8994 = dev_get_drvdata(dev);
+
+ switch (reg) {
+ case WM8994_GPIO_6:
+ if (wm8994->revision > 1)
+ return true;
+ else
+ return false;
+ default:
+ return wm8994_volatile_register(dev, reg);
+ }
+}
+
+static bool wm8958_volatile_register(struct device *dev, unsigned int reg)
+{
+ switch (reg) {
+ case WM8958_DSP2_MAGICNUM:
+ case WM8958_DSP2_RELEASEYEAR:
+ case WM8958_DSP2_RELEASEMONTHDAY:
+ case WM8958_DSP2_RELEASETIME:
+ case WM8958_DSP2_VERMAJMIN:
+ case WM8958_DSP2_VERBUILD:
+ case WM8958_DSP2_EXECCONTROL:
+ case WM8958_DSP2_SWVERSIONREG:
+ case WM8958_DSP2_CONFIGXMEM:
+ case WM8958_DSP2_CONFIGYMEM:
+ case WM8958_DSP2_CONFIGZMEM:
+ case WM8958_FW_BUILD_1:
+ case WM8958_FW_BUILD_0:
+ case WM8958_FW_ID_1:
+ case WM8958_FW_ID_0:
+ case WM8958_FW_MAJOR_1:
+ case WM8958_FW_MAJOR_0:
+ case WM8958_FW_MINOR_1:
+ case WM8958_FW_MINOR_0:
+ case WM8958_FW_PATCH_1:
+ case WM8958_FW_PATCH_0:
+ return true;
+ default:
+ return wm8994_volatile_register(dev, reg);
+ }
+}
+
+struct regmap_config wm1811_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .cache_type = REGCACHE_RBTREE,
+
+ .reg_defaults = wm1811_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm1811_defaults),
+
+ .max_register = WM8994_MAX_REGISTER,
+ .volatile_reg = wm1811_volatile_register,
+ .readable_reg = wm1811_readable_register,
+};
+
+struct regmap_config wm8994_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .cache_type = REGCACHE_RBTREE,
+
+ .reg_defaults = wm8994_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8994_defaults),
+
+ .max_register = WM8994_MAX_REGISTER,
+ .volatile_reg = wm8994_volatile_register,
+ .readable_reg = wm8994_readable_register,
+};
+
+struct regmap_config wm8958_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+
+ .cache_type = REGCACHE_RBTREE,
+
+ .reg_defaults = wm8958_defaults,
+ .num_reg_defaults = ARRAY_SIZE(wm8958_defaults),
+
+ .max_register = WM8994_MAX_REGISTER,
+ .volatile_reg = wm8958_volatile_register,
+ .readable_reg = wm8958_readable_register,
+};
+
+struct regmap_config wm8994_base_regmap_config = {
+ .reg_bits = 16,
+ .val_bits = 16,
+};
diff --git a/drivers/mfd/wm8994.h b/drivers/mfd/wm8994.h
new file mode 100644
index 000000000000..6f39a84eeadf
--- /dev/null
+++ b/drivers/mfd/wm8994.h
@@ -0,0 +1,25 @@
+/*
+ * wm8994.h -- WM8994 MFD internals
+ *
+ * Copyright 2011 Wolfson Microelectronics PLC.
+ *
+ * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
+ */
+
+#ifndef __MFD_WM8994_H__
+#define __MFD_WM8994_H__
+
+#include <linux/regmap.h>
+
+extern struct regmap_config wm1811_regmap_config;
+extern struct regmap_config wm8994_regmap_config;
+extern struct regmap_config wm8958_regmap_config;
+extern struct regmap_config wm8994_base_regmap_config;
+
+#endif
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/srom.c b/drivers/net/wireless/brcm80211/brcmsmac/srom.c
index 61092156755e..563743643038 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/srom.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/srom.c
@@ -764,6 +764,22 @@ _initvars_srom_pci(u8 sromrev, u16 *srom, struct list_head *var_list)
}
/*
+ * The crc check is done on a little-endian array, we need
+ * to switch the bytes around before checking crc (and
+ * then switch it back).
+ */
+static int do_crc_check(u16 *buf, unsigned nwords)
+{
+ u8 crc;
+
+ cpu_to_le16_buf(buf, nwords);
+ crc = crc8(brcms_srom_crc8_table, (void *)buf, nwords << 1, CRC8_INIT_VALUE);
+ le16_to_cpu_buf(buf, nwords);
+
+ return crc == CRC8_GOOD_VALUE(brcms_srom_crc8_table);
+}
+
+/*
* Read in and validate sprom.
* Return 0 on success, nonzero on error.
*/
@@ -772,8 +788,6 @@ sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
{
int err = 0;
uint i;
- u8 *bbuf = (u8 *)buf; /* byte buffer */
- uint nbytes = nwords << 1;
struct bcma_device *core;
uint sprom_offset;
@@ -786,9 +800,9 @@ sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
sprom_offset = CHIPCREGOFFS(sromotp);
}
- /* read the sprom in bytes */
- for (i = 0; i < nbytes; i++)
- bbuf[i] = bcma_read8(core, sprom_offset+i);
+ /* read the sprom */
+ for (i = 0; i < nwords; i++)
+ buf[i] = bcma_read16(core, sprom_offset+i*2);
if (buf[0] == 0xffff)
/*
@@ -798,13 +812,8 @@ sprom_read_pci(struct si_pub *sih, u16 *buf, uint nwords, bool check_crc)
*/
return -ENODATA;
- if (check_crc &&
- crc8(brcms_srom_crc8_table, bbuf, nbytes, CRC8_INIT_VALUE) !=
- CRC8_GOOD_VALUE(brcms_srom_crc8_table))
+ if (check_crc && !do_crc_check(buf, nwords))
err = -EIO;
- else
- /* now correct the endianness of the byte array */
- le16_to_cpu_buf(buf, nwords);
return err;
}
diff --git a/drivers/parisc/dino.c b/drivers/parisc/dino.c
index bcd5d54b7d4d..7ff10c1e8664 100644
--- a/drivers/parisc/dino.c
+++ b/drivers/parisc/dino.c
@@ -562,19 +562,6 @@ dino_fixup_bus(struct pci_bus *bus)
/* Firmware doesn't set up card-mode dino, so we have to */
if (is_card_dino(&dino_dev->hba.dev->id)) {
dino_card_setup(bus, dino_dev->hba.base_addr);
- } else if(bus->parent == NULL) {
- /* must have a dino above it, reparent the resources
- * into the dino window */
- int i;
- struct resource *res = &dino_dev->hba.lmmio_space;
-
- bus->resource[0] = &(dino_dev->hba.io_space);
- for(i = 0; i < DINO_MAX_LMMIO_RESOURCES; i++) {
- if(res[i].flags == 0)
- break;
- bus->resource[i+1] = &res[i];
- }
-
} else if (bus->parent) {
int i;
@@ -927,6 +914,7 @@ static int __init dino_probe(struct parisc_device *dev)
const char *version = "unknown";
char *name;
int is_cujo = 0;
+ LIST_HEAD(resources);
struct pci_bus *bus;
unsigned long hpa = dev->hpa.start;
@@ -1003,26 +991,37 @@ static int __init dino_probe(struct parisc_device *dev)
dev->dev.platform_data = dino_dev;
+ pci_add_resource(&resources, &dino_dev->hba.io_space);
+ if (dino_dev->hba.lmmio_space.flags)
+ pci_add_resource(&resources, &dino_dev->hba.lmmio_space);
+ if (dino_dev->hba.elmmio_space.flags)
+ pci_add_resource(&resources, &dino_dev->hba.elmmio_space);
+ if (dino_dev->hba.gmmio_space.flags)
+ pci_add_resource(&resources, &dino_dev->hba.gmmio_space);
+
/*
** It's not used to avoid chicken/egg problems
** with configuration accessor functions.
*/
- dino_dev->hba.hba_bus = bus = pci_scan_bus_parented(&dev->dev,
- dino_current_bus, &dino_cfg_ops, NULL);
-
- if(bus) {
- /* This code *depends* on scanning being single threaded
- * if it isn't, this global bus number count will fail
- */
- dino_current_bus = bus->subordinate + 1;
- pci_bus_assign_resources(bus);
- pci_bus_add_devices(bus);
- } else {
+ dino_dev->hba.hba_bus = bus = pci_create_root_bus(&dev->dev,
+ dino_current_bus, &dino_cfg_ops, NULL, &resources);
+ if (!bus) {
printk(KERN_ERR "ERROR: failed to scan PCI bus on %s (duplicate bus number %d?)\n",
dev_name(&dev->dev), dino_current_bus);
+ pci_free_resource_list(&resources);
/* increment the bus number in case of duplicates */
dino_current_bus++;
+ return 0;
}
+
+ bus->subordinate = pci_scan_child_bus(bus);
+
+ /* This code *depends* on scanning being single threaded
+ * if it isn't, this global bus number count will fail
+ */
+ dino_current_bus = bus->subordinate + 1;
+ pci_bus_assign_resources(bus);
+ pci_bus_add_devices(bus);
return 0;
}
diff --git a/drivers/parisc/lba_pci.c b/drivers/parisc/lba_pci.c
index 3aeb3279c92a..d5f3d753a108 100644
--- a/drivers/parisc/lba_pci.c
+++ b/drivers/parisc/lba_pci.c
@@ -653,7 +653,7 @@ lba_fixup_bus(struct pci_bus *bus)
}
} else {
/* Host-PCI Bridge */
- int err, i;
+ int err;
DBG("lba_fixup_bus() %s [%lx/%lx]/%lx\n",
ldev->hba.io_space.name,
@@ -669,9 +669,6 @@ lba_fixup_bus(struct pci_bus *bus)
lba_dump_res(&ioport_resource, 2);
BUG();
}
- /* advertize Host bridge resources to PCI bus */
- bus->resource[0] = &(ldev->hba.io_space);
- i = 1;
if (ldev->hba.elmmio_space.start) {
err = request_resource(&iomem_resource,
@@ -685,35 +682,17 @@ lba_fixup_bus(struct pci_bus *bus)
/* lba_dump_res(&iomem_resource, 2); */
/* BUG(); */
- } else
- bus->resource[i++] = &(ldev->hba.elmmio_space);
+ }
}
-
- /* Overlaps with elmmio can (and should) fail here.
- * We will prune (or ignore) the distributed range.
- *
- * FIXME: SBA code should register all elmmio ranges first.
- * that would take care of elmmio ranges routed
- * to a different rope (already discovered) from
- * getting registered *after* LBA code has already
- * registered it's distributed lmmio range.
- */
- if (truncate_pat_collision(&iomem_resource,
- &(ldev->hba.lmmio_space))) {
-
- printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
- (long)ldev->hba.lmmio_space.start,
- (long)ldev->hba.lmmio_space.end);
- } else {
+ if (ldev->hba.lmmio_space.flags) {
err = request_resource(&iomem_resource, &(ldev->hba.lmmio_space));
if (err < 0) {
printk(KERN_ERR "FAILED: lba_fixup_bus() request for "
"lmmio_space [%lx/%lx]\n",
(long)ldev->hba.lmmio_space.start,
(long)ldev->hba.lmmio_space.end);
- } else
- bus->resource[i++] = &(ldev->hba.lmmio_space);
+ }
}
#ifdef CONFIG_64BIT
@@ -728,7 +707,6 @@ lba_fixup_bus(struct pci_bus *bus)
lba_dump_res(&iomem_resource, 2);
BUG();
}
- bus->resource[i++] = &(ldev->hba.gmmio_space);
}
#endif
@@ -1404,6 +1382,7 @@ static int __init
lba_driver_probe(struct parisc_device *dev)
{
struct lba_device *lba_dev;
+ LIST_HEAD(resources);
struct pci_bus *lba_bus;
struct pci_ops *cfg_ops;
u32 func_class;
@@ -1518,10 +1497,41 @@ lba_driver_probe(struct parisc_device *dev)
if (lba_dev->hba.bus_num.start < lba_next_bus)
lba_dev->hba.bus_num.start = lba_next_bus;
+ /* Overlaps with elmmio can (and should) fail here.
+ * We will prune (or ignore) the distributed range.
+ *
+ * FIXME: SBA code should register all elmmio ranges first.
+ * that would take care of elmmio ranges routed
+ * to a different rope (already discovered) from
+ * getting registered *after* LBA code has already
+ * registered it's distributed lmmio range.
+ */
+ if (truncate_pat_collision(&iomem_resource,
+ &(lba_dev->hba.lmmio_space))) {
+ printk(KERN_WARNING "LBA: lmmio_space [%lx/%lx] duplicate!\n",
+ (long)lba_dev->hba.lmmio_space.start,
+ (long)lba_dev->hba.lmmio_space.end);
+ lba_dev->hba.lmmio_space.flags = 0;
+ }
+
+ pci_add_resource(&resources, &lba_dev->hba.io_space);
+ if (lba_dev->hba.elmmio_space.start)
+ pci_add_resource(&resources, &lba_dev->hba.elmmio_space);
+ if (lba_dev->hba.lmmio_space.flags)
+ pci_add_resource(&resources, &lba_dev->hba.lmmio_space);
+ if (lba_dev->hba.gmmio_space.flags)
+ pci_add_resource(&resources, &lba_dev->hba.gmmio_space);
+
dev->dev.platform_data = lba_dev;
lba_bus = lba_dev->hba.hba_bus =
- pci_scan_bus_parented(&dev->dev, lba_dev->hba.bus_num.start,
- cfg_ops, NULL);
+ pci_create_root_bus(&dev->dev, lba_dev->hba.bus_num.start,
+ cfg_ops, NULL, &resources);
+ if (!lba_bus) {
+ pci_free_resource_list(&resources);
+ return 0;
+ }
+
+ lba_bus->subordinate = pci_scan_child_bus(lba_bus);
/* This is in lieu of calling pci_assign_unassigned_resources() */
if (is_pdc_pat()) {
@@ -1551,10 +1561,8 @@ lba_driver_probe(struct parisc_device *dev)
lba_dev->flags |= LBA_FLAG_SKIP_PROBE;
}
- if (lba_bus) {
- lba_next_bus = lba_bus->subordinate + 1;
- pci_bus_add_devices(lba_bus);
- }
+ lba_next_bus = lba_bus->subordinate + 1;
+ pci_bus_add_devices(lba_bus);
/* Whew! Finally done! Tell services we got this one covered. */
return 0;
diff --git a/drivers/pci/access.c b/drivers/pci/access.c
index fdaa42aac7c6..2a581642c237 100644
--- a/drivers/pci/access.c
+++ b/drivers/pci/access.c
@@ -13,7 +13,7 @@
* configuration space.
*/
-static DEFINE_RAW_SPINLOCK(pci_lock);
+DEFINE_RAW_SPINLOCK(pci_lock);
/*
* Wrappers for all PCI configuration access functions. They just check
@@ -127,20 +127,20 @@ EXPORT_SYMBOL(pci_write_vpd);
* We have a bit per device to indicate it's blocked and a global wait queue
* for callers to sleep on until devices are unblocked.
*/
-static DECLARE_WAIT_QUEUE_HEAD(pci_ucfg_wait);
+static DECLARE_WAIT_QUEUE_HEAD(pci_cfg_wait);
-static noinline void pci_wait_ucfg(struct pci_dev *dev)
+static noinline void pci_wait_cfg(struct pci_dev *dev)
{
DECLARE_WAITQUEUE(wait, current);
- __add_wait_queue(&pci_ucfg_wait, &wait);
+ __add_wait_queue(&pci_cfg_wait, &wait);
do {
set_current_state(TASK_UNINTERRUPTIBLE);
raw_spin_unlock_irq(&pci_lock);
schedule();
raw_spin_lock_irq(&pci_lock);
- } while (dev->block_ucfg_access);
- __remove_wait_queue(&pci_ucfg_wait, &wait);
+ } while (dev->block_cfg_access);
+ __remove_wait_queue(&pci_cfg_wait, &wait);
}
/* Returns 0 on success, negative values indicate error. */
@@ -153,7 +153,8 @@ int pci_user_read_config_##size \
if (PCI_##size##_BAD) \
return -EINVAL; \
raw_spin_lock_irq(&pci_lock); \
- if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \
+ if (unlikely(dev->block_cfg_access)) \
+ pci_wait_cfg(dev); \
ret = dev->bus->ops->read(dev->bus, dev->devfn, \
pos, sizeof(type), &data); \
raw_spin_unlock_irq(&pci_lock); \
@@ -172,7 +173,8 @@ int pci_user_write_config_##size \
if (PCI_##size##_BAD) \
return -EINVAL; \
raw_spin_lock_irq(&pci_lock); \
- if (unlikely(dev->block_ucfg_access)) pci_wait_ucfg(dev); \
+ if (unlikely(dev->block_cfg_access)) \
+ pci_wait_cfg(dev); \
ret = dev->bus->ops->write(dev->bus, dev->devfn, \
pos, sizeof(type), val); \
raw_spin_unlock_irq(&pci_lock); \
@@ -401,36 +403,56 @@ int pci_vpd_truncate(struct pci_dev *dev, size_t size)
EXPORT_SYMBOL(pci_vpd_truncate);
/**
- * pci_block_user_cfg_access - Block userspace PCI config reads/writes
+ * pci_cfg_access_lock - Lock PCI config reads/writes
* @dev: pci device struct
*
- * When user access is blocked, any reads or writes to config space will
- * sleep until access is unblocked again. We don't allow nesting of
- * block/unblock calls.
+ * When access is locked, any userspace reads or writes to config
+ * space and concurrent lock requests will sleep until access is
+ * allowed via pci_cfg_access_unlocked again.
*/
-void pci_block_user_cfg_access(struct pci_dev *dev)
+void pci_cfg_access_lock(struct pci_dev *dev)
+{
+ might_sleep();
+
+ raw_spin_lock_irq(&pci_lock);
+ if (dev->block_cfg_access)
+ pci_wait_cfg(dev);
+ dev->block_cfg_access = 1;
+ raw_spin_unlock_irq(&pci_lock);
+}
+EXPORT_SYMBOL_GPL(pci_cfg_access_lock);
+
+/**
+ * pci_cfg_access_trylock - try to lock PCI config reads/writes
+ * @dev: pci device struct
+ *
+ * Same as pci_cfg_access_lock, but will return 0 if access is
+ * already locked, 1 otherwise. This function can be used from
+ * atomic contexts.
+ */
+bool pci_cfg_access_trylock(struct pci_dev *dev)
{
unsigned long flags;
- int was_blocked;
+ bool locked = true;
raw_spin_lock_irqsave(&pci_lock, flags);
- was_blocked = dev->block_ucfg_access;
- dev->block_ucfg_access = 1;
+ if (dev->block_cfg_access)
+ locked = false;
+ else
+ dev->block_cfg_access = 1;
raw_spin_unlock_irqrestore(&pci_lock, flags);
- /* If we BUG() inside the pci_lock, we're guaranteed to hose
- * the machine */
- BUG_ON(was_blocked);
+ return locked;
}
-EXPORT_SYMBOL_GPL(pci_block_user_cfg_access);
+EXPORT_SYMBOL_GPL(pci_cfg_access_trylock);
/**
- * pci_unblock_user_cfg_access - Unblock userspace PCI config reads/writes
+ * pci_cfg_access_unlock - Unlock PCI config reads/writes
* @dev: pci device struct
*
- * This function allows userspace PCI config accesses to resume.
+ * This function allows PCI config accesses to resume.
*/
-void pci_unblock_user_cfg_access(struct pci_dev *dev)
+void pci_cfg_access_unlock(struct pci_dev *dev)
{
unsigned long flags;
@@ -438,10 +460,10 @@ void pci_unblock_user_cfg_access(struct pci_dev *dev)
/* This indicates a problem in the caller, but we don't need
* to kill them, unlike a double-block above. */
- WARN_ON(!dev->block_ucfg_access);
+ WARN_ON(!dev->block_cfg_access);
- dev->block_ucfg_access = 0;
- wake_up_all(&pci_ucfg_wait);
+ dev->block_cfg_access = 0;
+ wake_up_all(&pci_cfg_wait);
raw_spin_unlock_irqrestore(&pci_lock, flags);
}
-EXPORT_SYMBOL_GPL(pci_unblock_user_cfg_access);
+EXPORT_SYMBOL_GPL(pci_cfg_access_unlock);
diff --git a/drivers/pci/ats.c b/drivers/pci/ats.c
index 9dd90b30f91a..95655d7c0d0b 100644
--- a/drivers/pci/ats.c
+++ b/drivers/pci/ats.c
@@ -128,6 +128,23 @@ void pci_disable_ats(struct pci_dev *dev)
}
EXPORT_SYMBOL_GPL(pci_disable_ats);
+void pci_restore_ats_state(struct pci_dev *dev)
+{
+ u16 ctrl;
+
+ if (!pci_ats_enabled(dev))
+ return;
+ if (!pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ATS))
+ BUG();
+
+ ctrl = PCI_ATS_CTRL_ENABLE;
+ if (!dev->is_virtfn)
+ ctrl |= PCI_ATS_CTRL_STU(dev->ats->stu - PCI_ATS_MIN_STU);
+
+ pci_write_config_word(dev, dev->ats->pos + PCI_ATS_CTRL, ctrl);
+}
+EXPORT_SYMBOL_GPL(pci_restore_ats_state);
+
/**
* pci_ats_queue_depth - query the ATS Invalidate Queue Depth
* @dev: the PCI device
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index 1e2ad92a4752..398f5d859791 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -18,6 +18,32 @@
#include "pci.h"
+void pci_add_resource(struct list_head *resources, struct resource *res)
+{
+ struct pci_bus_resource *bus_res;
+
+ bus_res = kzalloc(sizeof(struct pci_bus_resource), GFP_KERNEL);
+ if (!bus_res) {
+ printk(KERN_ERR "PCI: can't add bus resource %pR\n", res);
+ return;
+ }
+
+ bus_res->res = res;
+ list_add_tail(&bus_res->list, resources);
+}
+EXPORT_SYMBOL(pci_add_resource);
+
+void pci_free_resource_list(struct list_head *resources)
+{
+ struct pci_bus_resource *bus_res, *tmp;
+
+ list_for_each_entry_safe(bus_res, tmp, resources, list) {
+ list_del(&bus_res->list);
+ kfree(bus_res);
+ }
+}
+EXPORT_SYMBOL(pci_free_resource_list);
+
void pci_bus_add_resource(struct pci_bus *bus, struct resource *res,
unsigned int flags)
{
@@ -52,16 +78,12 @@ EXPORT_SYMBOL_GPL(pci_bus_resource_n);
void pci_bus_remove_resources(struct pci_bus *bus)
{
- struct pci_bus_resource *bus_res, *tmp;
int i;
for (i = 0; i < PCI_BRIDGE_RESOURCE_NUM; i++)
bus->resource[i] = NULL;
- list_for_each_entry_safe(bus_res, tmp, &bus->resources, list) {
- list_del(&bus_res->list);
- kfree(bus_res);
- }
+ pci_free_resource_list(&bus->resources);
}
/**
diff --git a/drivers/pci/iov.c b/drivers/pci/iov.c
index 1969a3ee3058..0321fa3b4226 100644
--- a/drivers/pci/iov.c
+++ b/drivers/pci/iov.c
@@ -347,11 +347,13 @@ static int sriov_enable(struct pci_dev *dev, int nr_virtfn)
return rc;
}
+ pci_write_config_dword(dev, iov->pos + PCI_SRIOV_SYS_PGSIZE, iov->pgsz);
+
iov->ctrl |= PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE;
- pci_block_user_cfg_access(dev);
+ pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
msleep(100);
- pci_unblock_user_cfg_access(dev);
+ pci_cfg_access_unlock(dev);
iov->initial = initial;
if (nr_virtfn < initial)
@@ -379,10 +381,10 @@ failed:
virtfn_remove(dev, j, 0);
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
- pci_block_user_cfg_access(dev);
+ pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
ssleep(1);
- pci_unblock_user_cfg_access(dev);
+ pci_cfg_access_unlock(dev);
if (iov->link != dev->devfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link");
@@ -405,10 +407,10 @@ static void sriov_disable(struct pci_dev *dev)
virtfn_remove(dev, i, 0);
iov->ctrl &= ~(PCI_SRIOV_CTRL_VFE | PCI_SRIOV_CTRL_MSE);
- pci_block_user_cfg_access(dev);
+ pci_cfg_access_lock(dev);
pci_write_config_word(dev, iov->pos + PCI_SRIOV_CTRL, iov->ctrl);
ssleep(1);
- pci_unblock_user_cfg_access(dev);
+ pci_cfg_access_unlock(dev);
if (iov->link != dev->devfn)
sysfs_remove_link(&dev->dev.kobj, "dep_link");
@@ -452,7 +454,6 @@ static int sriov_init(struct pci_dev *dev, int pos)
found:
pci_write_config_word(dev, pos + PCI_SRIOV_CTRL, ctrl);
- pci_write_config_word(dev, pos + PCI_SRIOV_NUM_VF, total);
pci_read_config_word(dev, pos + PCI_SRIOV_VF_OFFSET, &offset);
pci_read_config_word(dev, pos + PCI_SRIOV_VF_STRIDE, &stride);
if (!offset || (total > 1 && !stride))
@@ -465,7 +466,6 @@ found:
return -EIO;
pgsz &= ~(pgsz - 1);
- pci_write_config_dword(dev, pos + PCI_SRIOV_SYS_PGSIZE, pgsz);
nres = 0;
for (i = 0; i < PCI_SRIOV_NUM_BARS; i++) {
diff --git a/drivers/pci/msi.c b/drivers/pci/msi.c
index 337e16ab4a92..a825d78fd0aa 100644
--- a/drivers/pci/msi.c
+++ b/drivers/pci/msi.c
@@ -86,6 +86,31 @@ void default_teardown_msi_irqs(struct pci_dev *dev)
}
#endif
+#ifndef arch_restore_msi_irqs
+# define arch_restore_msi_irqs default_restore_msi_irqs
+# define HAVE_DEFAULT_MSI_RESTORE_IRQS
+#endif
+
+#ifdef HAVE_DEFAULT_MSI_RESTORE_IRQS
+void default_restore_msi_irqs(struct pci_dev *dev, int irq)
+{
+ struct msi_desc *entry;
+
+ entry = NULL;
+ if (dev->msix_enabled) {
+ list_for_each_entry(entry, &dev->msi_list, list) {
+ if (irq == entry->irq)
+ break;
+ }
+ } else if (dev->msi_enabled) {
+ entry = irq_get_msi_desc(irq);
+ }
+
+ if (entry)
+ write_msi_msg(irq, &entry->msg);
+}
+#endif
+
static void msi_set_enable(struct pci_dev *dev, int pos, int enable)
{
u16 control;
@@ -323,8 +348,18 @@ static void free_msi_irqs(struct pci_dev *dev)
if (list_is_last(&entry->list, &dev->msi_list))
iounmap(entry->mask_base);
}
- kobject_del(&entry->kobj);
- kobject_put(&entry->kobj);
+
+ /*
+ * Its possible that we get into this path
+ * When populate_msi_sysfs fails, which means the entries
+ * were not registered with sysfs. In that case don't
+ * unregister them.
+ */
+ if (entry->kobj.parent) {
+ kobject_del(&entry->kobj);
+ kobject_put(&entry->kobj);
+ }
+
list_del(&entry->list);
kfree(entry);
}
@@ -362,7 +397,7 @@ static void __pci_restore_msi_state(struct pci_dev *dev)
pci_intx_for_msi(dev, 0);
msi_set_enable(dev, pos, 0);
- write_msi_msg(dev->irq, &entry->msg);
+ arch_restore_msi_irqs(dev, dev->irq);
pci_read_config_word(dev, pos + PCI_MSI_FLAGS, &control);
msi_mask_irq(entry, msi_capable_mask(control), entry->masked);
@@ -390,7 +425,7 @@ static void __pci_restore_msix_state(struct pci_dev *dev)
pci_write_config_word(dev, pos + PCI_MSIX_FLAGS, control);
list_for_each_entry(entry, &dev->msi_list, list) {
- write_msi_msg(entry->irq, &entry->msg);
+ arch_restore_msi_irqs(dev, entry->irq);
msix_mask_irq(entry, entry->masked);
}
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 12d1e81a8abe..3623d65f8b86 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -604,7 +604,8 @@ static bool pci_has_legacy_pm_support(struct pci_dev *pci_dev)
* supported as well. Drivers are supposed to support either the
* former, or the latter, but not both at the same time.
*/
- WARN_ON(ret && drv->driver.pm);
+ WARN(ret && drv->driver.pm, "driver %s device %04x:%04x\n",
+ drv->name, pci_dev->vendor, pci_dev->device);
return ret;
}
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 6d4a5319148d..97fff785e97e 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -88,6 +88,12 @@ enum pcie_bus_config_types pcie_bus_config = PCIE_BUS_TUNE_OFF;
u8 pci_dfl_cache_line_size __devinitdata = L1_CACHE_BYTES >> 2;
u8 pci_cache_line_size;
+/*
+ * If we set up a device for bus mastering, we need to check the latency
+ * timer as certain BIOSes forget to set it properly.
+ */
+unsigned int pcibios_max_latency = 255;
+
/**
* pci_bus_max_busnr - returns maximum PCI bus number of given bus' children
* @bus: pointer to PCI bus structure to search
@@ -959,6 +965,7 @@ void pci_restore_state(struct pci_dev *dev)
/* PCI Express register must be restored first */
pci_restore_pcie_state(dev);
+ pci_restore_ats_state(dev);
/*
* The Base Address register should be programmed before the command
@@ -967,7 +974,7 @@ void pci_restore_state(struct pci_dev *dev)
for (i = 15; i >= 0; i--) {
pci_read_config_dword(dev, i * 4, &val);
if (val != dev->saved_config_space[i]) {
- dev_printk(KERN_DEBUG, &dev->dev, "restoring config "
+ dev_dbg(&dev->dev, "restoring config "
"space at offset %#x (was %#x, writing %#x)\n",
i, val, (int)dev->saved_config_space[i]);
pci_write_config_dword(dev,i * 4,
@@ -1536,8 +1543,7 @@ void pci_pme_active(struct pci_dev *dev, bool enable)
}
out:
- dev_printk(KERN_DEBUG, &dev->dev, "PME# %s\n",
- enable ? "enabled" : "disabled");
+ dev_dbg(&dev->dev, "PME# %s\n", enable ? "enabled" : "disabled");
}
/**
@@ -2596,6 +2602,33 @@ static void __pci_set_master(struct pci_dev *dev, bool enable)
}
/**
+ * pcibios_set_master - enable PCI bus-mastering for device dev
+ * @dev: the PCI device to enable
+ *
+ * Enables PCI bus-mastering for the device. This is the default
+ * implementation. Architecture specific implementations can override
+ * this if necessary.
+ */
+void __weak pcibios_set_master(struct pci_dev *dev)
+{
+ u8 lat;
+
+ /* The latency timer doesn't apply to PCIe (either Type 0 or Type 1) */
+ if (pci_is_pcie(dev))
+ return;
+
+ pci_read_config_byte(dev, PCI_LATENCY_TIMER, &lat);
+ if (lat < 16)
+ lat = (64 <= pcibios_max_latency) ? 64 : pcibios_max_latency;
+ else if (lat > pcibios_max_latency)
+ lat = pcibios_max_latency;
+ else
+ return;
+ dev_printk(KERN_DEBUG, &dev->dev, "setting latency timer to %d\n", lat);
+ pci_write_config_byte(dev, PCI_LATENCY_TIMER, lat);
+}
+
+/**
* pci_set_master - enables bus-mastering for device dev
* @dev: the PCI device to enable
*
@@ -2768,6 +2801,116 @@ pci_intx(struct pci_dev *pdev, int enable)
}
/**
+ * pci_intx_mask_supported - probe for INTx masking support
+ * @pdev: the PCI device to operate on
+ *
+ * Check if the device dev support INTx masking via the config space
+ * command word.
+ */
+bool pci_intx_mask_supported(struct pci_dev *dev)
+{
+ bool mask_supported = false;
+ u16 orig, new;
+
+ pci_cfg_access_lock(dev);
+
+ pci_read_config_word(dev, PCI_COMMAND, &orig);
+ pci_write_config_word(dev, PCI_COMMAND,
+ orig ^ PCI_COMMAND_INTX_DISABLE);
+ pci_read_config_word(dev, PCI_COMMAND, &new);
+
+ /*
+ * There's no way to protect against hardware bugs or detect them
+ * reliably, but as long as we know what the value should be, let's
+ * go ahead and check it.
+ */
+ if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
+ dev_err(&dev->dev, "Command register changed from "
+ "0x%x to 0x%x: driver or hardware bug?\n", orig, new);
+ } else if ((new ^ orig) & PCI_COMMAND_INTX_DISABLE) {
+ mask_supported = true;
+ pci_write_config_word(dev, PCI_COMMAND, orig);
+ }
+
+ pci_cfg_access_unlock(dev);
+ return mask_supported;
+}
+EXPORT_SYMBOL_GPL(pci_intx_mask_supported);
+
+static bool pci_check_and_set_intx_mask(struct pci_dev *dev, bool mask)
+{
+ struct pci_bus *bus = dev->bus;
+ bool mask_updated = true;
+ u32 cmd_status_dword;
+ u16 origcmd, newcmd;
+ unsigned long flags;
+ bool irq_pending;
+
+ /*
+ * We do a single dword read to retrieve both command and status.
+ * Document assumptions that make this possible.
+ */
+ BUILD_BUG_ON(PCI_COMMAND % 4);
+ BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
+
+ raw_spin_lock_irqsave(&pci_lock, flags);
+
+ bus->ops->read(bus, dev->devfn, PCI_COMMAND, 4, &cmd_status_dword);
+
+ irq_pending = (cmd_status_dword >> 16) & PCI_STATUS_INTERRUPT;
+
+ /*
+ * Check interrupt status register to see whether our device
+ * triggered the interrupt (when masking) or the next IRQ is
+ * already pending (when unmasking).
+ */
+ if (mask != irq_pending) {
+ mask_updated = false;
+ goto done;
+ }
+
+ origcmd = cmd_status_dword;
+ newcmd = origcmd & ~PCI_COMMAND_INTX_DISABLE;
+ if (mask)
+ newcmd |= PCI_COMMAND_INTX_DISABLE;
+ if (newcmd != origcmd)
+ bus->ops->write(bus, dev->devfn, PCI_COMMAND, 2, newcmd);
+
+done:
+ raw_spin_unlock_irqrestore(&pci_lock, flags);
+
+ return mask_updated;
+}
+
+/**
+ * pci_check_and_mask_intx - mask INTx on pending interrupt
+ * @pdev: the PCI device to operate on
+ *
+ * Check if the device dev has its INTx line asserted, mask it and
+ * return true in that case. False is returned if not interrupt was
+ * pending.
+ */
+bool pci_check_and_mask_intx(struct pci_dev *dev)
+{
+ return pci_check_and_set_intx_mask(dev, true);
+}
+EXPORT_SYMBOL_GPL(pci_check_and_mask_intx);
+
+/**
+ * pci_check_and_mask_intx - unmask INTx of no interrupt is pending
+ * @pdev: the PCI device to operate on
+ *
+ * Check if the device dev has its INTx line asserted, unmask it if not
+ * and return true. False is returned and the mask remains active if
+ * there was still an interrupt pending.
+ */
+bool pci_check_and_unmask_intx(struct pci_dev *dev)
+{
+ return pci_check_and_set_intx_mask(dev, false);
+}
+EXPORT_SYMBOL_GPL(pci_check_and_unmask_intx);
+
+/**
* pci_msi_off - disables any msi or msix capabilities
* @dev: the PCI device to operate on
*
@@ -2965,7 +3108,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
might_sleep();
if (!probe) {
- pci_block_user_cfg_access(dev);
+ pci_cfg_access_lock(dev);
/* block PM suspend, driver probe, etc. */
device_lock(&dev->dev);
}
@@ -2990,7 +3133,7 @@ static int pci_dev_reset(struct pci_dev *dev, int probe)
done:
if (!probe) {
device_unlock(&dev->dev);
- pci_unblock_user_cfg_access(dev);
+ pci_cfg_access_unlock(dev);
}
return rc;
diff --git a/drivers/pci/pci.h b/drivers/pci/pci.h
index b74084e9ca12..1009a5e88e53 100644
--- a/drivers/pci/pci.h
+++ b/drivers/pci/pci.h
@@ -136,6 +136,8 @@ static inline void pci_remove_legacy_files(struct pci_bus *bus) { return; }
/* Lock for read/write access to pci device and bus lists */
extern struct rw_semaphore pci_bus_sem;
+extern raw_spinlock_t pci_lock;
+
extern unsigned int pci_pm_d3_delay;
#ifdef CONFIG_PCI_MSI
@@ -249,6 +251,14 @@ struct pci_sriov {
u8 __iomem *mstate; /* VF Migration State Array */
};
+#ifdef CONFIG_PCI_ATS
+extern void pci_restore_ats_state(struct pci_dev *dev);
+#else
+static inline void pci_restore_ats_state(struct pci_dev *dev)
+{
+}
+#endif /* CONFIG_PCI_ATS */
+
#ifdef CONFIG_PCI_IOV
extern int pci_iov_init(struct pci_dev *dev);
extern void pci_iov_release(struct pci_dev *dev);
diff --git a/drivers/pci/pcie/Kconfig b/drivers/pci/pcie/Kconfig
index dc29348264c6..72962cc92e0a 100644
--- a/drivers/pci/pcie/Kconfig
+++ b/drivers/pci/pcie/Kconfig
@@ -39,7 +39,7 @@ config PCIEASPM
Power Management) and Clock Power Management. ASPM supports
state L0/L0s/L1.
- ASPM is initially set up the the firmware. With this option enabled,
+ ASPM is initially set up by the firmware. With this option enabled,
Linux can modify this state in order to disable ASPM on known-bad
hardware or configurations and enable it when known-safe.
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index 04e74f485714..7cc9e2f0f47c 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -1522,19 +1522,21 @@ unsigned int __devinit pci_scan_child_bus(struct pci_bus *bus)
return max;
}
-struct pci_bus * pci_create_bus(struct device *parent,
- int bus, struct pci_ops *ops, void *sysdata)
+struct pci_bus *pci_create_root_bus(struct device *parent, int bus,
+ struct pci_ops *ops, void *sysdata, struct list_head *resources)
{
- int error;
+ int error, i;
struct pci_bus *b, *b2;
struct device *dev;
+ struct pci_bus_resource *bus_res, *n;
+ struct resource *res;
b = pci_alloc_bus();
if (!b)
return NULL;
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
- if (!dev){
+ if (!dev) {
kfree(b);
return NULL;
}
@@ -1577,8 +1579,20 @@ struct pci_bus * pci_create_bus(struct device *parent,
pci_create_legacy_files(b);
b->number = b->secondary = bus;
- b->resource[0] = &ioport_resource;
- b->resource[1] = &iomem_resource;
+
+ /* Add initial resources to the bus */
+ list_for_each_entry_safe(bus_res, n, resources, list)
+ list_move_tail(&bus_res->list, &b->resources);
+
+ if (parent)
+ dev_info(parent, "PCI host bridge to bus %s\n", dev_name(&b->dev));
+ else
+ printk(KERN_INFO "PCI host bridge to bus %s\n", dev_name(&b->dev));
+
+ pci_bus_for_each_resource(b, res, i) {
+ if (res)
+ dev_info(&b->dev, "root bus resource %pR\n", res);
+ }
return b;
@@ -1594,18 +1608,58 @@ err_out:
return NULL;
}
+struct pci_bus * __devinit pci_scan_root_bus(struct device *parent, int bus,
+ struct pci_ops *ops, void *sysdata, struct list_head *resources)
+{
+ struct pci_bus *b;
+
+ b = pci_create_root_bus(parent, bus, ops, sysdata, resources);
+ if (!b)
+ return NULL;
+
+ b->subordinate = pci_scan_child_bus(b);
+ pci_bus_add_devices(b);
+ return b;
+}
+EXPORT_SYMBOL(pci_scan_root_bus);
+
+/* Deprecated; use pci_scan_root_bus() instead */
struct pci_bus * __devinit pci_scan_bus_parented(struct device *parent,
int bus, struct pci_ops *ops, void *sysdata)
{
+ LIST_HEAD(resources);
struct pci_bus *b;
- b = pci_create_bus(parent, bus, ops, sysdata);
+ pci_add_resource(&resources, &ioport_resource);
+ pci_add_resource(&resources, &iomem_resource);
+ b = pci_create_root_bus(parent, bus, ops, sysdata, &resources);
if (b)
b->subordinate = pci_scan_child_bus(b);
+ else
+ pci_free_resource_list(&resources);
return b;
}
EXPORT_SYMBOL(pci_scan_bus_parented);
+struct pci_bus * __devinit pci_scan_bus(int bus, struct pci_ops *ops,
+ void *sysdata)
+{
+ LIST_HEAD(resources);
+ struct pci_bus *b;
+
+ pci_add_resource(&resources, &ioport_resource);
+ pci_add_resource(&resources, &iomem_resource);
+ b = pci_create_root_bus(NULL, bus, ops, sysdata, &resources);
+ if (b) {
+ b->subordinate = pci_scan_child_bus(b);
+ pci_bus_add_devices(b);
+ } else {
+ pci_free_resource_list(&resources);
+ }
+ return b;
+}
+EXPORT_SYMBOL(pci_scan_bus);
+
#ifdef CONFIG_HOTPLUG
/**
* pci_rescan_bus - scan a PCI bus for devices.
diff --git a/drivers/pci/remove.c b/drivers/pci/remove.c
index 7f87beed35ac..6def3624c688 100644
--- a/drivers/pci/remove.c
+++ b/drivers/pci/remove.c
@@ -89,9 +89,8 @@ EXPORT_SYMBOL(pci_remove_bus);
* device lists, remove the /proc entry, and notify userspace
* (/sbin/hotplug).
*/
-void pci_remove_bus_device(struct pci_dev *dev)
+static void __pci_remove_bus_device(struct pci_dev *dev)
{
- pci_stop_bus_device(dev);
if (dev->subordinate) {
struct pci_bus *b = dev->subordinate;
@@ -102,6 +101,11 @@ void pci_remove_bus_device(struct pci_dev *dev)
pci_destroy_dev(dev);
}
+void pci_remove_bus_device(struct pci_dev *dev)
+{
+ pci_stop_bus_device(dev);
+ __pci_remove_bus_device(dev);
+}
/**
* pci_remove_behind_bridge - remove all devices behind a PCI bridge
@@ -117,7 +121,7 @@ void pci_remove_behind_bridge(struct pci_dev *dev)
if (dev->subordinate)
list_for_each_safe(l, n, &dev->subordinate->devices)
- pci_remove_bus_device(pci_dev_b(l));
+ __pci_remove_bus_device(pci_dev_b(l));
}
static void pci_stop_bus_devices(struct pci_bus *bus)
diff --git a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
index 5717509becbe..b66bfdbd21f7 100644
--- a/drivers/pci/setup-res.c
+++ b/drivers/pci/setup-res.c
@@ -85,9 +85,9 @@ void pci_update_resource(struct pci_dev *dev, int resno)
}
}
res->flags &= ~IORESOURCE_UNSET;
- dev_info(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
- resno, res, (unsigned long long)region.start,
- (unsigned long long)region.end);
+ dev_dbg(&dev->dev, "BAR %d: set to %pR (PCI address [%#llx-%#llx])\n",
+ resno, res, (unsigned long long)region.start,
+ (unsigned long long)region.end);
}
int pci_claim_resource(struct pci_dev *dev, int resource)
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 7f43cf86d776..f995e6e2f78c 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -639,7 +639,7 @@ config ACPI_CMPC
config INTEL_SCU_IPC
bool "Intel SCU IPC Support"
- depends on X86_MRST
+ depends on X86_INTEL_MID
default y
---help---
IPC is used to bridge the communications between kernel and SCU on
diff --git a/drivers/pnp/quirks.c b/drivers/pnp/quirks.c
index dfbd5a6cc58b..258fef272ea7 100644
--- a/drivers/pnp/quirks.c
+++ b/drivers/pnp/quirks.c
@@ -295,6 +295,45 @@ static void quirk_system_pci_resources(struct pnp_dev *dev)
}
}
+#ifdef CONFIG_AMD_NB
+
+#include <asm/amd_nb.h>
+
+static void quirk_amd_mmconfig_area(struct pnp_dev *dev)
+{
+ resource_size_t start, end;
+ struct pnp_resource *pnp_res;
+ struct resource *res;
+ struct resource mmconfig_res, *mmconfig;
+
+ mmconfig = amd_get_mmconfig_range(&mmconfig_res);
+ if (!mmconfig)
+ return;
+
+ list_for_each_entry(pnp_res, &dev->resources, list) {
+ res = &pnp_res->res;
+ if (res->end < mmconfig->start || res->start > mmconfig->end ||
+ (res->start == mmconfig->start && res->end == mmconfig->end))
+ continue;
+
+ dev_info(&dev->dev, FW_BUG
+ "%pR covers only part of AMD MMCONFIG area %pR; adding more reservations\n",
+ res, mmconfig);
+ if (mmconfig->start < res->start) {
+ start = mmconfig->start;
+ end = res->start - 1;
+ pnp_add_mem_resource(dev, start, end, 0);
+ }
+ if (mmconfig->end > res->end) {
+ start = res->end + 1;
+ end = mmconfig->end;
+ pnp_add_mem_resource(dev, start, end, 0);
+ }
+ break;
+ }
+}
+#endif
+
/*
* PnP Quirks
* Cards or devices that need some tweaking due to incomplete resource info
@@ -322,6 +361,9 @@ static struct pnp_fixup pnp_fixups[] = {
/* PnP resources that might overlap PCI BARs */
{"PNP0c01", quirk_system_pci_resources},
{"PNP0c02", quirk_system_pci_resources},
+#ifdef CONFIG_AMD_NB
+ {"PNP0c01", quirk_amd_mmconfig_area},
+#endif
{""}
};
diff --git a/drivers/power/Kconfig b/drivers/power/Kconfig
index 9f88641e67f9..3a8daf858742 100644
--- a/drivers/power/Kconfig
+++ b/drivers/power/Kconfig
@@ -116,12 +116,12 @@ config BATTERY_WM97XX
help
Say Y to enable support for battery measured by WM97xx aux port.
-config BATTERY_BQ20Z75
- tristate "TI BQ20z75 gas gauge"
+config BATTERY_SBS
+ tristate "SBS Compliant gas gauge"
depends on I2C
help
- Say Y to include support for TI BQ20z75 SBS-compliant
- gas gauge and protection IC.
+ Say Y to include support for SBS battery driver for SBS-compliant
+ gas gauges.
config BATTERY_BQ27x00
tristate "BQ27x00 battery driver"
@@ -150,6 +150,14 @@ config BATTERY_DA9030
Say Y here to enable support for batteries charger integrated into
DA9030 PMIC.
+config BATTERY_DA9052
+ tristate "Dialog DA9052 Battery"
+ depends on PMIC_DA9052
+ depends on BROKEN
+ help
+ Say Y here to enable support for batteries charger integrated into
+ DA9052 PMIC.
+
config BATTERY_MAX17040
tristate "Maxim MAX17040 Fuel Gauge"
depends on I2C
@@ -226,6 +234,12 @@ config CHARGER_TWL4030
help
Say Y here to enable support for TWL4030 Battery Charge Interface.
+config CHARGER_LP8727
+ tristate "National Semiconductor LP8727 charger driver"
+ depends on I2C
+ help
+ Say Y here to enable support for LP8727 Charger Driver.
+
config CHARGER_GPIO
tristate "GPIO charger"
depends on GPIOLIB
@@ -236,6 +250,16 @@ config CHARGER_GPIO
This driver can be build as a module. If so, the module will be
called gpio-charger.
+config CHARGER_MANAGER
+ bool "Battery charger manager for multiple chargers"
+ depends on REGULATOR && RTC_CLASS
+ help
+ Say Y to enable charger-manager support, which allows multiple
+ chargers attached to a battery and multiple batteries attached to a
+ system. The charger-manager also can monitor charging status in
+ runtime and in suspend-to-RAM by waking up the system periodically
+ with help of suspend_again support.
+
config CHARGER_MAX8997
tristate "Maxim MAX8997/MAX8966 PMIC battery charger driver"
depends on MFD_MAX8997 && REGULATOR_MAX8997
diff --git a/drivers/power/Makefile b/drivers/power/Makefile
index b4af13dd8b66..e429008eaf10 100644
--- a/drivers/power/Makefile
+++ b/drivers/power/Makefile
@@ -22,9 +22,10 @@ obj-$(CONFIG_BATTERY_OLPC) += olpc_battery.o
obj-$(CONFIG_BATTERY_TOSA) += tosa_battery.o
obj-$(CONFIG_BATTERY_COLLIE) += collie_battery.o
obj-$(CONFIG_BATTERY_WM97XX) += wm97xx_battery.o
-obj-$(CONFIG_BATTERY_BQ20Z75) += bq20z75.o
+obj-$(CONFIG_BATTERY_SBS) += sbs-battery.o
obj-$(CONFIG_BATTERY_BQ27x00) += bq27x00_battery.o
obj-$(CONFIG_BATTERY_DA9030) += da9030_battery.o
+obj-$(CONFIG_BATTERY_DA9052) += da9052-battery.o
obj-$(CONFIG_BATTERY_MAX17040) += max17040_battery.o
obj-$(CONFIG_BATTERY_MAX17042) += max17042_battery.o
obj-$(CONFIG_BATTERY_Z2) += z2_battery.o
@@ -35,6 +36,8 @@ obj-$(CONFIG_BATTERY_INTEL_MID) += intel_mid_battery.o
obj-$(CONFIG_CHARGER_ISP1704) += isp1704_charger.o
obj-$(CONFIG_CHARGER_MAX8903) += max8903_charger.o
obj-$(CONFIG_CHARGER_TWL4030) += twl4030_charger.o
+obj-$(CONFIG_CHARGER_LP8727) += lp8727_charger.o
obj-$(CONFIG_CHARGER_GPIO) += gpio-charger.o
+obj-$(CONFIG_CHARGER_MANAGER) += charger-manager.o
obj-$(CONFIG_CHARGER_MAX8997) += max8997_charger.o
obj-$(CONFIG_CHARGER_MAX8998) += max8998_charger.o
diff --git a/drivers/power/bq27x00_battery.c b/drivers/power/bq27x00_battery.c
index bb16f5b7e167..98bf5676318d 100644
--- a/drivers/power/bq27x00_battery.c
+++ b/drivers/power/bq27x00_battery.c
@@ -54,13 +54,19 @@
#define BQ27000_REG_RSOC 0x0B /* Relative State-of-Charge */
#define BQ27000_REG_ILMD 0x76 /* Initial last measured discharge */
-#define BQ27000_FLAG_CHGS BIT(7)
+#define BQ27000_FLAG_EDVF BIT(0) /* Final End-of-Discharge-Voltage flag */
+#define BQ27000_FLAG_EDV1 BIT(1) /* First End-of-Discharge-Voltage flag */
+#define BQ27000_FLAG_CI BIT(4) /* Capacity Inaccurate flag */
#define BQ27000_FLAG_FC BIT(5)
+#define BQ27000_FLAG_CHGS BIT(7) /* Charge state flag */
#define BQ27500_REG_SOC 0x2C
#define BQ27500_REG_DCAP 0x3C /* Design capacity */
-#define BQ27500_FLAG_DSC BIT(0)
-#define BQ27500_FLAG_FC BIT(9)
+#define BQ27500_FLAG_DSG BIT(0) /* Discharging */
+#define BQ27500_FLAG_SOCF BIT(1) /* State-of-Charge threshold final */
+#define BQ27500_FLAG_SOC1 BIT(2) /* State-of-Charge threshold 1 */
+#define BQ27500_FLAG_CHG BIT(8) /* Charging */
+#define BQ27500_FLAG_FC BIT(9) /* Fully charged */
#define BQ27000_RS 20 /* Resistor sense */
@@ -79,9 +85,8 @@ struct bq27x00_reg_cache {
int charge_full;
int cycle_count;
int capacity;
+ int energy;
int flags;
-
- int current_now;
};
struct bq27x00_device_info {
@@ -108,6 +113,7 @@ static enum power_supply_property bq27x00_battery_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_CURRENT_NOW,
POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_CAPACITY_LEVEL,
POWER_SUPPLY_PROP_TEMP,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW,
POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG,
@@ -149,7 +155,7 @@ static int bq27x00_battery_read_rsoc(struct bq27x00_device_info *di)
rsoc = bq27x00_read(di, BQ27000_REG_RSOC, true);
if (rsoc < 0)
- dev_err(di->dev, "error reading relative State-of-Charge\n");
+ dev_dbg(di->dev, "error reading relative State-of-Charge\n");
return rsoc;
}
@@ -164,7 +170,8 @@ static int bq27x00_battery_read_charge(struct bq27x00_device_info *di, u8 reg)
charge = bq27x00_read(di, reg, false);
if (charge < 0) {
- dev_err(di->dev, "error reading nominal available capacity\n");
+ dev_dbg(di->dev, "error reading charge register %02x: %d\n",
+ reg, charge);
return charge;
}
@@ -208,7 +215,7 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
ilmd = bq27x00_read(di, BQ27000_REG_ILMD, true);
if (ilmd < 0) {
- dev_err(di->dev, "error reading initial last measured discharge\n");
+ dev_dbg(di->dev, "error reading initial last measured discharge\n");
return ilmd;
}
@@ -221,6 +228,50 @@ static int bq27x00_battery_read_ilmd(struct bq27x00_device_info *di)
}
/*
+ * Return the battery Available energy in µWh
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_read_energy(struct bq27x00_device_info *di)
+{
+ int ae;
+
+ ae = bq27x00_read(di, BQ27x00_REG_AE, false);
+ if (ae < 0) {
+ dev_dbg(di->dev, "error reading available energy\n");
+ return ae;
+ }
+
+ if (di->chip == BQ27500)
+ ae *= 1000;
+ else
+ ae = ae * 29200 / BQ27000_RS;
+
+ return ae;
+}
+
+/*
+ * Return the battery temperature in tenths of degree Celsius
+ * Or < 0 if something fails.
+ */
+static int bq27x00_battery_read_temperature(struct bq27x00_device_info *di)
+{
+ int temp;
+
+ temp = bq27x00_read(di, BQ27x00_REG_TEMP, false);
+ if (temp < 0) {
+ dev_err(di->dev, "error reading temperature\n");
+ return temp;
+ }
+
+ if (di->chip == BQ27500)
+ temp -= 2731;
+ else
+ temp = ((temp * 5) - 5463) / 2;
+
+ return temp;
+}
+
+/*
* Return the battery Cycle count total
* Or < 0 if something fails.
*/
@@ -245,7 +296,8 @@ static int bq27x00_battery_read_time(struct bq27x00_device_info *di, u8 reg)
tval = bq27x00_read(di, reg, false);
if (tval < 0) {
- dev_err(di->dev, "error reading register %02x: %d\n", reg, tval);
+ dev_dbg(di->dev, "error reading time register %02x: %d\n",
+ reg, tval);
return tval;
}
@@ -262,25 +314,31 @@ static void bq27x00_update(struct bq27x00_device_info *di)
cache.flags = bq27x00_read(di, BQ27x00_REG_FLAGS, is_bq27500);
if (cache.flags >= 0) {
- cache.capacity = bq27x00_battery_read_rsoc(di);
- cache.temperature = bq27x00_read(di, BQ27x00_REG_TEMP, false);
- cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
- cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
- cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
- cache.charge_full = bq27x00_battery_read_lmd(di);
+ if (!is_bq27500 && (cache.flags & BQ27000_FLAG_CI)) {
+ dev_info(di->dev, "battery is not calibrated! ignoring capacity values\n");
+ cache.capacity = -ENODATA;
+ cache.energy = -ENODATA;
+ cache.time_to_empty = -ENODATA;
+ cache.time_to_empty_avg = -ENODATA;
+ cache.time_to_full = -ENODATA;
+ cache.charge_full = -ENODATA;
+ } else {
+ cache.capacity = bq27x00_battery_read_rsoc(di);
+ cache.energy = bq27x00_battery_read_energy(di);
+ cache.time_to_empty = bq27x00_battery_read_time(di, BQ27x00_REG_TTE);
+ cache.time_to_empty_avg = bq27x00_battery_read_time(di, BQ27x00_REG_TTECP);
+ cache.time_to_full = bq27x00_battery_read_time(di, BQ27x00_REG_TTF);
+ cache.charge_full = bq27x00_battery_read_lmd(di);
+ }
+ cache.temperature = bq27x00_battery_read_temperature(di);
cache.cycle_count = bq27x00_battery_read_cyct(di);
- if (!is_bq27500)
- cache.current_now = bq27x00_read(di, BQ27x00_REG_AI, false);
-
/* We only have to read charge design full once */
if (di->charge_design_full <= 0)
di->charge_design_full = bq27x00_battery_read_ilmd(di);
}
- /* Ignore current_now which is a snapshot of the current battery state
- * and is likely to be different even between two consecutive reads */
- if (memcmp(&di->cache, &cache, sizeof(cache) - sizeof(int)) != 0) {
+ if (memcmp(&di->cache, &cache, sizeof(cache)) != 0) {
di->cache = cache;
power_supply_changed(&di->bat);
}
@@ -302,25 +360,6 @@ static void bq27x00_battery_poll(struct work_struct *work)
}
}
-
-/*
- * Return the battery temperature in tenths of degree Celsius
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_temperature(struct bq27x00_device_info *di,
- union power_supply_propval *val)
-{
- if (di->cache.temperature < 0)
- return di->cache.temperature;
-
- if (di->chip == BQ27500)
- val->intval = di->cache.temperature - 2731;
- else
- val->intval = ((di->cache.temperature * 5) - 5463) / 2;
-
- return 0;
-}
-
/*
* Return the battery average current in µA
* Note that current can be negative signed as well
@@ -330,20 +369,20 @@ static int bq27x00_battery_current(struct bq27x00_device_info *di,
union power_supply_propval *val)
{
int curr;
+ int flags;
- if (di->chip == BQ27500)
- curr = bq27x00_read(di, BQ27x00_REG_AI, false);
- else
- curr = di->cache.current_now;
-
- if (curr < 0)
+ curr = bq27x00_read(di, BQ27x00_REG_AI, false);
+ if (curr < 0) {
+ dev_err(di->dev, "error reading current\n");
return curr;
+ }
if (di->chip == BQ27500) {
/* bq27500 returns signed value */
val->intval = (int)((s16)curr) * 1000;
} else {
- if (di->cache.flags & BQ27000_FLAG_CHGS) {
+ flags = bq27x00_read(di, BQ27x00_REG_FLAGS, false);
+ if (flags & BQ27000_FLAG_CHGS) {
dev_dbg(di->dev, "negative current!\n");
curr = -curr;
}
@@ -362,10 +401,14 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
if (di->chip == BQ27500) {
if (di->cache.flags & BQ27500_FLAG_FC)
status = POWER_SUPPLY_STATUS_FULL;
- else if (di->cache.flags & BQ27500_FLAG_DSC)
+ else if (di->cache.flags & BQ27500_FLAG_DSG)
status = POWER_SUPPLY_STATUS_DISCHARGING;
- else
+ else if (di->cache.flags & BQ27500_FLAG_CHG)
status = POWER_SUPPLY_STATUS_CHARGING;
+ else if (power_supply_am_i_supplied(&di->bat))
+ status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else
+ status = POWER_SUPPLY_STATUS_UNKNOWN;
} else {
if (di->cache.flags & BQ27000_FLAG_FC)
status = POWER_SUPPLY_STATUS_FULL;
@@ -382,50 +425,56 @@ static int bq27x00_battery_status(struct bq27x00_device_info *di,
return 0;
}
-/*
- * Return the battery Voltage in milivolts
- * Or < 0 if something fails.
- */
-static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
+static int bq27x00_battery_capacity_level(struct bq27x00_device_info *di,
union power_supply_propval *val)
{
- int volt;
+ int level;
- volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
- if (volt < 0)
- return volt;
+ if (di->chip == BQ27500) {
+ if (di->cache.flags & BQ27500_FLAG_FC)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (di->cache.flags & BQ27500_FLAG_SOC1)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else if (di->cache.flags & BQ27500_FLAG_SOCF)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+ else
+ level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ } else {
+ if (di->cache.flags & BQ27000_FLAG_FC)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_FULL;
+ else if (di->cache.flags & BQ27000_FLAG_EDV1)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_LOW;
+ else if (di->cache.flags & BQ27000_FLAG_EDVF)
+ level = POWER_SUPPLY_CAPACITY_LEVEL_CRITICAL;
+ else
+ level = POWER_SUPPLY_CAPACITY_LEVEL_NORMAL;
+ }
- val->intval = volt * 1000;
+ val->intval = level;
return 0;
}
/*
- * Return the battery Available energy in µWh
+ * Return the battery Voltage in milivolts
* Or < 0 if something fails.
*/
-static int bq27x00_battery_energy(struct bq27x00_device_info *di,
+static int bq27x00_battery_voltage(struct bq27x00_device_info *di,
union power_supply_propval *val)
{
- int ae;
+ int volt;
- ae = bq27x00_read(di, BQ27x00_REG_AE, false);
- if (ae < 0) {
- dev_err(di->dev, "error reading available energy\n");
- return ae;
+ volt = bq27x00_read(di, BQ27x00_REG_VOLT, false);
+ if (volt < 0) {
+ dev_err(di->dev, "error reading voltage\n");
+ return volt;
}
- if (di->chip == BQ27500)
- ae *= 1000;
- else
- ae = ae * 29200 / BQ27000_RS;
-
- val->intval = ae;
+ val->intval = volt * 1000;
return 0;
}
-
static int bq27x00_simple_value(int value,
union power_supply_propval *val)
{
@@ -473,8 +522,11 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CAPACITY:
ret = bq27x00_simple_value(di->cache.capacity, val);
break;
+ case POWER_SUPPLY_PROP_CAPACITY_LEVEL:
+ ret = bq27x00_battery_capacity_level(di, val);
+ break;
case POWER_SUPPLY_PROP_TEMP:
- ret = bq27x00_battery_temperature(di, val);
+ ret = bq27x00_simple_value(di->cache.temperature, val);
break;
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_NOW:
ret = bq27x00_simple_value(di->cache.time_to_empty, val);
@@ -501,7 +553,7 @@ static int bq27x00_battery_get_property(struct power_supply *psy,
ret = bq27x00_simple_value(di->cache.cycle_count, val);
break;
case POWER_SUPPLY_PROP_ENERGY_NOW:
- ret = bq27x00_battery_energy(di, val);
+ ret = bq27x00_simple_value(di->cache.energy, val);
break;
default:
return -EINVAL;
@@ -546,6 +598,14 @@ static int bq27x00_powersupply_init(struct bq27x00_device_info *di)
static void bq27x00_powersupply_unregister(struct bq27x00_device_info *di)
{
+ /*
+ * power_supply_unregister call bq27x00_battery_get_property which
+ * call bq27x00_battery_poll.
+ * Make sure that bq27x00_battery_poll will not call
+ * schedule_delayed_work again after unregister (which cause OOPS).
+ */
+ poll_interval = 0;
+
cancel_delayed_work_sync(&di->work);
power_supply_unregister(&di->bat);
diff --git a/drivers/power/charger-manager.c b/drivers/power/charger-manager.c
new file mode 100644
index 000000000000..0378d019efae
--- /dev/null
+++ b/drivers/power/charger-manager.c
@@ -0,0 +1,1072 @@
+/*
+ * Copyright (C) 2011 Samsung Electronics Co., Ltd.
+ * MyungJoo Ham <myungjoo.ham@samsung.com>
+ *
+ * This driver enables to monitor battery health and control charger
+ * during suspend-to-mem.
+ * Charger manager depends on other devices. register this later than
+ * the depending devices.
+ *
+ * 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.
+**/
+
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <linux/rtc.h>
+#include <linux/slab.h>
+#include <linux/workqueue.h>
+#include <linux/platform_device.h>
+#include <linux/power/charger-manager.h>
+#include <linux/regulator/consumer.h>
+
+/*
+ * Regard CM_JIFFIES_SMALL jiffies is small enough to ignore for
+ * delayed works so that we can run delayed works with CM_JIFFIES_SMALL
+ * without any delays.
+ */
+#define CM_JIFFIES_SMALL (2)
+
+/* If y is valid (> 0) and smaller than x, do x = y */
+#define CM_MIN_VALID(x, y) x = (((y > 0) && ((x) > (y))) ? (y) : (x))
+
+/*
+ * Regard CM_RTC_SMALL (sec) is small enough to ignore error in invoking
+ * rtc alarm. It should be 2 or larger
+ */
+#define CM_RTC_SMALL (2)
+
+#define UEVENT_BUF_SIZE 32
+
+static LIST_HEAD(cm_list);
+static DEFINE_MUTEX(cm_list_mtx);
+
+/* About in-suspend (suspend-again) monitoring */
+static struct rtc_device *rtc_dev;
+/*
+ * Backup RTC alarm
+ * Save the wakeup alarm before entering suspend-to-RAM
+ */
+static struct rtc_wkalrm rtc_wkalarm_save;
+/* Backup RTC alarm time in terms of seconds since 01-01-1970 00:00:00 */
+static unsigned long rtc_wkalarm_save_time;
+static bool cm_suspended;
+static bool cm_rtc_set;
+static unsigned long cm_suspend_duration_ms;
+
+/* Global charger-manager description */
+static struct charger_global_desc *g_desc; /* init with setup_charger_manager */
+
+/**
+ * is_batt_present - See if the battery presents in place.
+ * @cm: the Charger Manager representing the battery.
+ */
+static bool is_batt_present(struct charger_manager *cm)
+{
+ union power_supply_propval val;
+ bool present = false;
+ int i, ret;
+
+ switch (cm->desc->battery_present) {
+ case CM_FUEL_GAUGE:
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_PRESENT, &val);
+ if (ret == 0 && val.intval)
+ present = true;
+ break;
+ case CM_CHARGER_STAT:
+ for (i = 0; cm->charger_stat[i]; i++) {
+ ret = cm->charger_stat[i]->get_property(
+ cm->charger_stat[i],
+ POWER_SUPPLY_PROP_PRESENT, &val);
+ if (ret == 0 && val.intval) {
+ present = true;
+ break;
+ }
+ }
+ break;
+ }
+
+ return present;
+}
+
+/**
+ * is_ext_pwr_online - See if an external power source is attached to charge
+ * @cm: the Charger Manager representing the battery.
+ *
+ * Returns true if at least one of the chargers of the battery has an external
+ * power source attached to charge the battery regardless of whether it is
+ * actually charging or not.
+ */
+static bool is_ext_pwr_online(struct charger_manager *cm)
+{
+ union power_supply_propval val;
+ bool online = false;
+ int i, ret;
+
+ /* If at least one of them has one, it's yes. */
+ for (i = 0; cm->charger_stat[i]; i++) {
+ ret = cm->charger_stat[i]->get_property(
+ cm->charger_stat[i],
+ POWER_SUPPLY_PROP_ONLINE, &val);
+ if (ret == 0 && val.intval) {
+ online = true;
+ break;
+ }
+ }
+
+ return online;
+}
+
+/**
+ * get_batt_uV - Get the voltage level of the battery
+ * @cm: the Charger Manager representing the battery.
+ * @uV: the voltage level returned.
+ *
+ * Returns 0 if there is no error.
+ * Returns a negative value on error.
+ */
+static int get_batt_uV(struct charger_manager *cm, int *uV)
+{
+ union power_supply_propval val;
+ int ret;
+
+ if (cm->fuel_gauge)
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW, &val);
+ else
+ return -ENODEV;
+
+ if (ret)
+ return ret;
+
+ *uV = val.intval;
+ return 0;
+}
+
+/**
+ * is_charging - Returns true if the battery is being charged.
+ * @cm: the Charger Manager representing the battery.
+ */
+static bool is_charging(struct charger_manager *cm)
+{
+ int i, ret;
+ bool charging = false;
+ union power_supply_propval val;
+
+ /* If there is no battery, it cannot be charged */
+ if (!is_batt_present(cm))
+ return false;
+
+ /* If at least one of the charger is charging, return yes */
+ for (i = 0; cm->charger_stat[i]; i++) {
+ /* 1. The charger sholuld not be DISABLED */
+ if (cm->emergency_stop)
+ continue;
+ if (!cm->charger_enabled)
+ continue;
+
+ /* 2. The charger should be online (ext-power) */
+ ret = cm->charger_stat[i]->get_property(
+ cm->charger_stat[i],
+ POWER_SUPPLY_PROP_ONLINE, &val);
+ if (ret) {
+ dev_warn(cm->dev, "Cannot read ONLINE value from %s.\n",
+ cm->desc->psy_charger_stat[i]);
+ continue;
+ }
+ if (val.intval == 0)
+ continue;
+
+ /*
+ * 3. The charger should not be FULL, DISCHARGING,
+ * or NOT_CHARGING.
+ */
+ ret = cm->charger_stat[i]->get_property(
+ cm->charger_stat[i],
+ POWER_SUPPLY_PROP_STATUS, &val);
+ if (ret) {
+ dev_warn(cm->dev, "Cannot read STATUS value from %s.\n",
+ cm->desc->psy_charger_stat[i]);
+ continue;
+ }
+ if (val.intval == POWER_SUPPLY_STATUS_FULL ||
+ val.intval == POWER_SUPPLY_STATUS_DISCHARGING ||
+ val.intval == POWER_SUPPLY_STATUS_NOT_CHARGING)
+ continue;
+
+ /* Then, this is charging. */
+ charging = true;
+ break;
+ }
+
+ return charging;
+}
+
+/**
+ * is_polling_required - Return true if need to continue polling for this CM.
+ * @cm: the Charger Manager representing the battery.
+ */
+static bool is_polling_required(struct charger_manager *cm)
+{
+ switch (cm->desc->polling_mode) {
+ case CM_POLL_DISABLE:
+ return false;
+ case CM_POLL_ALWAYS:
+ return true;
+ case CM_POLL_EXTERNAL_POWER_ONLY:
+ return is_ext_pwr_online(cm);
+ case CM_POLL_CHARGING_ONLY:
+ return is_charging(cm);
+ default:
+ dev_warn(cm->dev, "Incorrect polling_mode (%d)\n",
+ cm->desc->polling_mode);
+ }
+
+ return false;
+}
+
+/**
+ * try_charger_enable - Enable/Disable chargers altogether
+ * @cm: the Charger Manager representing the battery.
+ * @enable: true: enable / false: disable
+ *
+ * Note that Charger Manager keeps the charger enabled regardless whether
+ * the charger is charging or not (because battery is full or no external
+ * power source exists) except when CM needs to disable chargers forcibly
+ * bacause of emergency causes; when the battery is overheated or too cold.
+ */
+static int try_charger_enable(struct charger_manager *cm, bool enable)
+{
+ int err = 0, i;
+ struct charger_desc *desc = cm->desc;
+
+ /* Ignore if it's redundent command */
+ if (enable && cm->charger_enabled)
+ return 0;
+ if (!enable && !cm->charger_enabled)
+ return 0;
+
+ if (enable) {
+ if (cm->emergency_stop)
+ return -EAGAIN;
+ err = regulator_bulk_enable(desc->num_charger_regulators,
+ desc->charger_regulators);
+ } else {
+ /*
+ * Abnormal battery state - Stop charging forcibly,
+ * even if charger was enabled at the other places
+ */
+ err = regulator_bulk_disable(desc->num_charger_regulators,
+ desc->charger_regulators);
+
+ for (i = 0; i < desc->num_charger_regulators; i++) {
+ if (regulator_is_enabled(
+ desc->charger_regulators[i].consumer)) {
+ regulator_force_disable(
+ desc->charger_regulators[i].consumer);
+ dev_warn(cm->dev,
+ "Disable regulator(%s) forcibly.\n",
+ desc->charger_regulators[i].supply);
+ }
+ }
+ }
+
+ if (!err)
+ cm->charger_enabled = enable;
+
+ return err;
+}
+
+/**
+ * uevent_notify - Let users know something has changed.
+ * @cm: the Charger Manager representing the battery.
+ * @event: the event string.
+ *
+ * If @event is null, it implies that uevent_notify is called
+ * by resume function. When called in the resume function, cm_suspended
+ * should be already reset to false in order to let uevent_notify
+ * notify the recent event during the suspend to users. While
+ * suspended, uevent_notify does not notify users, but tracks
+ * events so that uevent_notify can notify users later after resumed.
+ */
+static void uevent_notify(struct charger_manager *cm, const char *event)
+{
+ static char env_str[UEVENT_BUF_SIZE + 1] = "";
+ static char env_str_save[UEVENT_BUF_SIZE + 1] = "";
+
+ if (cm_suspended) {
+ /* Nothing in suspended-event buffer */
+ if (env_str_save[0] == 0) {
+ if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
+ return; /* status not changed */
+ strncpy(env_str_save, event, UEVENT_BUF_SIZE);
+ return;
+ }
+
+ if (!strncmp(env_str_save, event, UEVENT_BUF_SIZE))
+ return; /* Duplicated. */
+ else
+ strncpy(env_str_save, event, UEVENT_BUF_SIZE);
+
+ return;
+ }
+
+ if (event == NULL) {
+ /* No messages pending */
+ if (!env_str_save[0])
+ return;
+
+ strncpy(env_str, env_str_save, UEVENT_BUF_SIZE);
+ kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE);
+ env_str_save[0] = 0;
+
+ return;
+ }
+
+ /* status not changed */
+ if (!strncmp(env_str, event, UEVENT_BUF_SIZE))
+ return;
+
+ /* save the status and notify the update */
+ strncpy(env_str, event, UEVENT_BUF_SIZE);
+ kobject_uevent(&cm->dev->kobj, KOBJ_CHANGE);
+
+ dev_info(cm->dev, event);
+}
+
+/**
+ * _cm_monitor - Monitor the temperature and return true for exceptions.
+ * @cm: the Charger Manager representing the battery.
+ *
+ * Returns true if there is an event to notify for the battery.
+ * (True if the status of "emergency_stop" changes)
+ */
+static bool _cm_monitor(struct charger_manager *cm)
+{
+ struct charger_desc *desc = cm->desc;
+ int temp = desc->temperature_out_of_range(&cm->last_temp_mC);
+
+ dev_dbg(cm->dev, "monitoring (%2.2d.%3.3dC)\n",
+ cm->last_temp_mC / 1000, cm->last_temp_mC % 1000);
+
+ /* It has been stopped or charging already */
+ if (!!temp == !!cm->emergency_stop)
+ return false;
+
+ if (temp) {
+ cm->emergency_stop = temp;
+ if (!try_charger_enable(cm, false)) {
+ if (temp > 0)
+ uevent_notify(cm, "OVERHEAT");
+ else
+ uevent_notify(cm, "COLD");
+ }
+ } else {
+ cm->emergency_stop = 0;
+ if (!try_charger_enable(cm, true))
+ uevent_notify(cm, "CHARGING");
+ }
+
+ return true;
+}
+
+/**
+ * cm_monitor - Monitor every battery.
+ *
+ * Returns true if there is an event to notify from any of the batteries.
+ * (True if the status of "emergency_stop" changes)
+ */
+static bool cm_monitor(void)
+{
+ bool stop = false;
+ struct charger_manager *cm;
+
+ mutex_lock(&cm_list_mtx);
+
+ list_for_each_entry(cm, &cm_list, entry)
+ stop = stop || _cm_monitor(cm);
+
+ mutex_unlock(&cm_list_mtx);
+
+ return stop;
+}
+
+static int charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct charger_manager *cm = container_of(psy,
+ struct charger_manager, charger_psy);
+ struct charger_desc *desc = cm->desc;
+ int i, ret = 0, uV;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (is_charging(cm))
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (is_ext_pwr_online(cm))
+ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ if (cm->emergency_stop > 0)
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ else if (cm->emergency_stop < 0)
+ val->intval = POWER_SUPPLY_HEALTH_COLD;
+ else
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ if (is_batt_present(cm))
+ val->intval = 1;
+ else
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ ret = get_batt_uV(cm, &i);
+ val->intval = i;
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_NOW:
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CURRENT_NOW, val);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ /* in thenth of centigrade */
+ if (cm->last_temp_mC == INT_MIN)
+ desc->temperature_out_of_range(&cm->last_temp_mC);
+ val->intval = cm->last_temp_mC / 100;
+ if (!desc->measure_battery_temp)
+ ret = -ENODEV;
+ break;
+ case POWER_SUPPLY_PROP_TEMP_AMBIENT:
+ /* in thenth of centigrade */
+ if (cm->last_temp_mC == INT_MIN)
+ desc->temperature_out_of_range(&cm->last_temp_mC);
+ val->intval = cm->last_temp_mC / 100;
+ if (desc->measure_battery_temp)
+ ret = -ENODEV;
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ if (!cm->fuel_gauge) {
+ ret = -ENODEV;
+ break;
+ }
+
+ if (!is_batt_present(cm)) {
+ /* There is no battery. Assume 100% */
+ val->intval = 100;
+ break;
+ }
+
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CAPACITY, val);
+ if (ret)
+ break;
+
+ if (val->intval > 100) {
+ val->intval = 100;
+ break;
+ }
+ if (val->intval < 0)
+ val->intval = 0;
+
+ /* Do not adjust SOC when charging: voltage is overrated */
+ if (is_charging(cm))
+ break;
+
+ /*
+ * If the capacity value is inconsistent, calibrate it base on
+ * the battery voltage values and the thresholds given as desc
+ */
+ ret = get_batt_uV(cm, &uV);
+ if (ret) {
+ /* Voltage information not available. No calibration */
+ ret = 0;
+ break;
+ }
+
+ if (desc->fullbatt_uV > 0 && uV >= desc->fullbatt_uV &&
+ !is_charging(cm)) {
+ val->intval = 100;
+ break;
+ }
+
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ if (is_ext_pwr_online(cm))
+ val->intval = 1;
+ else
+ val->intval = 0;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_FULL:
+ if (cm->fuel_gauge) {
+ if (cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CHARGE_FULL, val) == 0)
+ break;
+ }
+
+ if (is_ext_pwr_online(cm)) {
+ /* Not full if it's charging. */
+ if (is_charging(cm)) {
+ val->intval = 0;
+ break;
+ }
+ /*
+ * Full if it's powered but not charging andi
+ * not forced stop by emergency
+ */
+ if (!cm->emergency_stop) {
+ val->intval = 1;
+ break;
+ }
+ }
+
+ /* Full if it's over the fullbatt voltage */
+ ret = get_batt_uV(cm, &uV);
+ if (!ret && desc->fullbatt_uV > 0 && uV >= desc->fullbatt_uV &&
+ !is_charging(cm)) {
+ val->intval = 1;
+ break;
+ }
+
+ /* Full if the cap is 100 */
+ if (cm->fuel_gauge) {
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CAPACITY, val);
+ if (!ret && val->intval >= 100 && !is_charging(cm)) {
+ val->intval = 1;
+ break;
+ }
+ }
+
+ val->intval = 0;
+ ret = 0;
+ break;
+ case POWER_SUPPLY_PROP_CHARGE_NOW:
+ if (is_charging(cm)) {
+ ret = cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CHARGE_NOW,
+ val);
+ if (ret) {
+ val->intval = 1;
+ ret = 0;
+ } else {
+ /* If CHARGE_NOW is supplied, use it */
+ val->intval = (val->intval > 0) ?
+ val->intval : 1;
+ }
+ } else {
+ val->intval = 0;
+ }
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+#define NUM_CHARGER_PSY_OPTIONAL (4)
+static enum power_supply_property default_charger_props[] = {
+ /* Guaranteed to provide */
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_CHARGE_FULL,
+ /*
+ * Optional properties are:
+ * POWER_SUPPLY_PROP_CHARGE_NOW,
+ * POWER_SUPPLY_PROP_CURRENT_NOW,
+ * POWER_SUPPLY_PROP_TEMP, and
+ * POWER_SUPPLY_PROP_TEMP_AMBIENT,
+ */
+};
+
+static struct power_supply psy_default = {
+ .name = "battery",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = default_charger_props,
+ .num_properties = ARRAY_SIZE(default_charger_props),
+ .get_property = charger_get_property,
+};
+
+/**
+ * cm_setup_timer - For in-suspend monitoring setup wakeup alarm
+ * for suspend_again.
+ *
+ * Returns true if the alarm is set for Charger Manager to use.
+ * Returns false if
+ * cm_setup_timer fails to set an alarm,
+ * cm_setup_timer does not need to set an alarm for Charger Manager,
+ * or an alarm previously configured is to be used.
+ */
+static bool cm_setup_timer(void)
+{
+ struct charger_manager *cm;
+ unsigned int wakeup_ms = UINT_MAX;
+ bool ret = false;
+
+ mutex_lock(&cm_list_mtx);
+
+ list_for_each_entry(cm, &cm_list, entry) {
+ /* Skip if polling is not required for this CM */
+ if (!is_polling_required(cm) && !cm->emergency_stop)
+ continue;
+ if (cm->desc->polling_interval_ms == 0)
+ continue;
+ CM_MIN_VALID(wakeup_ms, cm->desc->polling_interval_ms);
+ }
+
+ mutex_unlock(&cm_list_mtx);
+
+ if (wakeup_ms < UINT_MAX && wakeup_ms > 0) {
+ pr_info("Charger Manager wakeup timer: %u ms.\n", wakeup_ms);
+ if (rtc_dev) {
+ struct rtc_wkalrm tmp;
+ unsigned long time, now;
+ unsigned long add = DIV_ROUND_UP(wakeup_ms, 1000);
+
+ /*
+ * Set alarm with the polling interval (wakeup_ms)
+ * except when rtc_wkalarm_save comes first.
+ * However, the alarm time should be NOW +
+ * CM_RTC_SMALL or later.
+ */
+ tmp.enabled = 1;
+ rtc_read_time(rtc_dev, &tmp.time);
+ rtc_tm_to_time(&tmp.time, &now);
+ if (add < CM_RTC_SMALL)
+ add = CM_RTC_SMALL;
+ time = now + add;
+
+ ret = true;
+
+ if (rtc_wkalarm_save.enabled &&
+ rtc_wkalarm_save_time &&
+ rtc_wkalarm_save_time < time) {
+ if (rtc_wkalarm_save_time < now + CM_RTC_SMALL)
+ time = now + CM_RTC_SMALL;
+ else
+ time = rtc_wkalarm_save_time;
+
+ /* The timer is not appointed by CM */
+ ret = false;
+ }
+
+ pr_info("Waking up after %lu secs.\n",
+ time - now);
+
+ rtc_time_to_tm(time, &tmp.time);
+ rtc_set_alarm(rtc_dev, &tmp);
+ cm_suspend_duration_ms += wakeup_ms;
+ return ret;
+ }
+ }
+
+ if (rtc_dev)
+ rtc_set_alarm(rtc_dev, &rtc_wkalarm_save);
+ return false;
+}
+
+/**
+ * cm_suspend_again - Determine whether suspend again or not
+ *
+ * Returns true if the system should be suspended again
+ * Returns false if the system should be woken up
+ */
+bool cm_suspend_again(void)
+{
+ struct charger_manager *cm;
+ bool ret = false;
+
+ if (!g_desc || !g_desc->rtc_only_wakeup || !g_desc->rtc_only_wakeup() ||
+ !cm_rtc_set)
+ return false;
+
+ if (cm_monitor())
+ goto out;
+
+ ret = true;
+ mutex_lock(&cm_list_mtx);
+ list_for_each_entry(cm, &cm_list, entry) {
+ if (cm->status_save_ext_pwr_inserted != is_ext_pwr_online(cm) ||
+ cm->status_save_batt != is_batt_present(cm))
+ ret = false;
+ }
+ mutex_unlock(&cm_list_mtx);
+
+ cm_rtc_set = cm_setup_timer();
+out:
+ /* It's about the time when the non-CM appointed timer goes off */
+ if (rtc_wkalarm_save.enabled) {
+ unsigned long now;
+ struct rtc_time tmp;
+
+ rtc_read_time(rtc_dev, &tmp);
+ rtc_tm_to_time(&tmp, &now);
+
+ if (rtc_wkalarm_save_time &&
+ now + CM_RTC_SMALL >= rtc_wkalarm_save_time)
+ return false;
+ }
+ return ret;
+}
+EXPORT_SYMBOL_GPL(cm_suspend_again);
+
+/**
+ * setup_charger_manager - initialize charger_global_desc data
+ * @gd: pointer to instance of charger_global_desc
+ */
+int setup_charger_manager(struct charger_global_desc *gd)
+{
+ if (!gd)
+ return -EINVAL;
+
+ if (rtc_dev)
+ rtc_class_close(rtc_dev);
+ rtc_dev = NULL;
+ g_desc = NULL;
+
+ if (!gd->rtc_only_wakeup) {
+ pr_err("The callback rtc_only_wakeup is not given.\n");
+ return -EINVAL;
+ }
+
+ if (gd->rtc_name) {
+ rtc_dev = rtc_class_open(gd->rtc_name);
+ if (IS_ERR_OR_NULL(rtc_dev)) {
+ rtc_dev = NULL;
+ /* Retry at probe. RTC may be not registered yet */
+ }
+ } else {
+ pr_warn("No wakeup timer is given for charger manager."
+ "In-suspend monitoring won't work.\n");
+ }
+
+ g_desc = gd;
+ return 0;
+}
+EXPORT_SYMBOL_GPL(setup_charger_manager);
+
+static int charger_manager_probe(struct platform_device *pdev)
+{
+ struct charger_desc *desc = dev_get_platdata(&pdev->dev);
+ struct charger_manager *cm;
+ int ret = 0, i = 0;
+ union power_supply_propval val;
+
+ if (g_desc && !rtc_dev && g_desc->rtc_name) {
+ rtc_dev = rtc_class_open(g_desc->rtc_name);
+ if (IS_ERR_OR_NULL(rtc_dev)) {
+ rtc_dev = NULL;
+ dev_err(&pdev->dev, "Cannot get RTC %s.\n",
+ g_desc->rtc_name);
+ ret = -ENODEV;
+ goto err_alloc;
+ }
+ }
+
+ if (!desc) {
+ dev_err(&pdev->dev, "No platform data (desc) found.\n");
+ ret = -ENODEV;
+ goto err_alloc;
+ }
+
+ cm = kzalloc(sizeof(struct charger_manager), GFP_KERNEL);
+ if (!cm) {
+ dev_err(&pdev->dev, "Cannot allocate memory.\n");
+ ret = -ENOMEM;
+ goto err_alloc;
+ }
+
+ /* Basic Values. Unspecified are Null or 0 */
+ cm->dev = &pdev->dev;
+ cm->desc = kzalloc(sizeof(struct charger_desc), GFP_KERNEL);
+ if (!cm->desc) {
+ dev_err(&pdev->dev, "Cannot allocate memory.\n");
+ ret = -ENOMEM;
+ goto err_alloc_desc;
+ }
+ memcpy(cm->desc, desc, sizeof(struct charger_desc));
+ cm->last_temp_mC = INT_MIN; /* denotes "unmeasured, yet" */
+
+ if (!desc->charger_regulators || desc->num_charger_regulators < 1) {
+ ret = -EINVAL;
+ dev_err(&pdev->dev, "charger_regulators undefined.\n");
+ goto err_no_charger;
+ }
+
+ if (!desc->psy_charger_stat || !desc->psy_charger_stat[0]) {
+ dev_err(&pdev->dev, "No power supply defined.\n");
+ ret = -EINVAL;
+ goto err_no_charger_stat;
+ }
+
+ /* Counting index only */
+ while (desc->psy_charger_stat[i])
+ i++;
+
+ cm->charger_stat = kzalloc(sizeof(struct power_supply *) * (i + 1),
+ GFP_KERNEL);
+ if (!cm->charger_stat) {
+ ret = -ENOMEM;
+ goto err_no_charger_stat;
+ }
+
+ for (i = 0; desc->psy_charger_stat[i]; i++) {
+ cm->charger_stat[i] = power_supply_get_by_name(
+ desc->psy_charger_stat[i]);
+ if (!cm->charger_stat[i]) {
+ dev_err(&pdev->dev, "Cannot find power supply "
+ "\"%s\"\n",
+ desc->psy_charger_stat[i]);
+ ret = -ENODEV;
+ goto err_chg_stat;
+ }
+ }
+
+ cm->fuel_gauge = power_supply_get_by_name(desc->psy_fuel_gauge);
+ if (!cm->fuel_gauge) {
+ dev_err(&pdev->dev, "Cannot find power supply \"%s\"\n",
+ desc->psy_fuel_gauge);
+ ret = -ENODEV;
+ goto err_chg_stat;
+ }
+
+ if (desc->polling_interval_ms == 0 ||
+ msecs_to_jiffies(desc->polling_interval_ms) <= CM_JIFFIES_SMALL) {
+ dev_err(&pdev->dev, "polling_interval_ms is too small\n");
+ ret = -EINVAL;
+ goto err_chg_stat;
+ }
+
+ if (!desc->temperature_out_of_range) {
+ dev_err(&pdev->dev, "there is no temperature_out_of_range\n");
+ ret = -EINVAL;
+ goto err_chg_stat;
+ }
+
+ platform_set_drvdata(pdev, cm);
+
+ memcpy(&cm->charger_psy, &psy_default,
+ sizeof(psy_default));
+ if (!desc->psy_name) {
+ strncpy(cm->psy_name_buf, psy_default.name,
+ PSY_NAME_MAX);
+ } else {
+ strncpy(cm->psy_name_buf, desc->psy_name, PSY_NAME_MAX);
+ }
+ cm->charger_psy.name = cm->psy_name_buf;
+
+ /* Allocate for psy properties because they may vary */
+ cm->charger_psy.properties = kzalloc(sizeof(enum power_supply_property)
+ * (ARRAY_SIZE(default_charger_props) +
+ NUM_CHARGER_PSY_OPTIONAL),
+ GFP_KERNEL);
+ if (!cm->charger_psy.properties) {
+ dev_err(&pdev->dev, "Cannot allocate for psy properties.\n");
+ ret = -ENOMEM;
+ goto err_chg_stat;
+ }
+ memcpy(cm->charger_psy.properties, default_charger_props,
+ sizeof(enum power_supply_property) *
+ ARRAY_SIZE(default_charger_props));
+ cm->charger_psy.num_properties = psy_default.num_properties;
+
+ /* Find which optional psy-properties are available */
+ if (!cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CHARGE_NOW, &val)) {
+ cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ POWER_SUPPLY_PROP_CHARGE_NOW;
+ cm->charger_psy.num_properties++;
+ }
+ if (!cm->fuel_gauge->get_property(cm->fuel_gauge,
+ POWER_SUPPLY_PROP_CURRENT_NOW,
+ &val)) {
+ cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ POWER_SUPPLY_PROP_CURRENT_NOW;
+ cm->charger_psy.num_properties++;
+ }
+ if (!desc->measure_battery_temp) {
+ cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ POWER_SUPPLY_PROP_TEMP_AMBIENT;
+ cm->charger_psy.num_properties++;
+ }
+ if (desc->measure_battery_temp) {
+ cm->charger_psy.properties[cm->charger_psy.num_properties] =
+ POWER_SUPPLY_PROP_TEMP;
+ cm->charger_psy.num_properties++;
+ }
+
+ ret = power_supply_register(NULL, &cm->charger_psy);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot register charger-manager with"
+ " name \"%s\".\n", cm->charger_psy.name);
+ goto err_register;
+ }
+
+ ret = regulator_bulk_get(&pdev->dev, desc->num_charger_regulators,
+ desc->charger_regulators);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot get charger regulators.\n");
+ goto err_bulk_get;
+ }
+
+ ret = try_charger_enable(cm, true);
+ if (ret) {
+ dev_err(&pdev->dev, "Cannot enable charger regulators\n");
+ goto err_chg_enable;
+ }
+
+ /* Add to the list */
+ mutex_lock(&cm_list_mtx);
+ list_add(&cm->entry, &cm_list);
+ mutex_unlock(&cm_list_mtx);
+
+ return 0;
+
+err_chg_enable:
+ if (desc->charger_regulators)
+ regulator_bulk_free(desc->num_charger_regulators,
+ desc->charger_regulators);
+err_bulk_get:
+ power_supply_unregister(&cm->charger_psy);
+err_register:
+ kfree(cm->charger_psy.properties);
+err_chg_stat:
+ kfree(cm->charger_stat);
+err_no_charger_stat:
+err_no_charger:
+ kfree(cm->desc);
+err_alloc_desc:
+ kfree(cm);
+err_alloc:
+ return ret;
+}
+
+static int __devexit charger_manager_remove(struct platform_device *pdev)
+{
+ struct charger_manager *cm = platform_get_drvdata(pdev);
+ struct charger_desc *desc = cm->desc;
+
+ /* Remove from the list */
+ mutex_lock(&cm_list_mtx);
+ list_del(&cm->entry);
+ mutex_unlock(&cm_list_mtx);
+
+ if (desc->charger_regulators)
+ regulator_bulk_free(desc->num_charger_regulators,
+ desc->charger_regulators);
+
+ power_supply_unregister(&cm->charger_psy);
+ kfree(cm->charger_psy.properties);
+ kfree(cm->charger_stat);
+ kfree(cm->desc);
+ kfree(cm);
+
+ return 0;
+}
+
+const struct platform_device_id charger_manager_id[] = {
+ { "charger-manager", 0 },
+ { },
+};
+
+static int cm_suspend_prepare(struct device *dev)
+{
+ struct platform_device *pdev = container_of(dev, struct platform_device,
+ dev);
+ struct charger_manager *cm = platform_get_drvdata(pdev);
+
+ if (!cm_suspended) {
+ if (rtc_dev) {
+ struct rtc_time tmp;
+ unsigned long now;
+
+ rtc_read_alarm(rtc_dev, &rtc_wkalarm_save);
+ rtc_read_time(rtc_dev, &tmp);
+
+ if (rtc_wkalarm_save.enabled) {
+ rtc_tm_to_time(&rtc_wkalarm_save.time,
+ &rtc_wkalarm_save_time);
+ rtc_tm_to_time(&tmp, &now);
+ if (now > rtc_wkalarm_save_time)
+ rtc_wkalarm_save_time = 0;
+ } else {
+ rtc_wkalarm_save_time = 0;
+ }
+ }
+ cm_suspended = true;
+ }
+
+ cm->status_save_ext_pwr_inserted = is_ext_pwr_online(cm);
+ cm->status_save_batt = is_batt_present(cm);
+
+ if (!cm_rtc_set) {
+ cm_suspend_duration_ms = 0;
+ cm_rtc_set = cm_setup_timer();
+ }
+
+ return 0;
+}
+
+static void cm_suspend_complete(struct device *dev)
+{
+ struct platform_device *pdev = container_of(dev, struct platform_device,
+ dev);
+ struct charger_manager *cm = platform_get_drvdata(pdev);
+
+ if (cm_suspended) {
+ if (rtc_dev) {
+ struct rtc_wkalrm tmp;
+
+ rtc_read_alarm(rtc_dev, &tmp);
+ rtc_wkalarm_save.pending = tmp.pending;
+ rtc_set_alarm(rtc_dev, &rtc_wkalarm_save);
+ }
+ cm_suspended = false;
+ cm_rtc_set = false;
+ }
+
+ uevent_notify(cm, NULL);
+}
+
+static const struct dev_pm_ops charger_manager_pm = {
+ .prepare = cm_suspend_prepare,
+ .complete = cm_suspend_complete,
+};
+
+static struct platform_driver charger_manager_driver = {
+ .driver = {
+ .name = "charger-manager",
+ .owner = THIS_MODULE,
+ .pm = &charger_manager_pm,
+ },
+ .probe = charger_manager_probe,
+ .remove = __devexit_p(charger_manager_remove),
+ .id_table = charger_manager_id,
+};
+
+static int __init charger_manager_init(void)
+{
+ return platform_driver_register(&charger_manager_driver);
+}
+late_initcall(charger_manager_init);
+
+static void __exit charger_manager_cleanup(void)
+{
+ platform_driver_unregister(&charger_manager_driver);
+}
+module_exit(charger_manager_cleanup);
+
+MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
+MODULE_DESCRIPTION("Charger Manager");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("charger-manager");
diff --git a/drivers/power/collie_battery.c b/drivers/power/collie_battery.c
index 548d263b1ad0..74c6b23aeabf 100644
--- a/drivers/power/collie_battery.c
+++ b/drivers/power/collie_battery.c
@@ -146,7 +146,7 @@ static void collie_bat_external_power_changed(struct power_supply *psy)
static irqreturn_t collie_bat_gpio_isr(int irq, void *data)
{
- pr_info("collie_bat_gpio irq: %d\n", gpio_get_value(irq_to_gpio(irq)));
+ pr_info("collie_bat_gpio irq\n");
schedule_work(&bat_work);
return IRQ_HANDLED;
}
@@ -277,18 +277,13 @@ static struct collie_bat collie_bat_bu = {
.adc_temp_divider = -1,
};
-static struct {
- int gpio;
- char *name;
- bool output;
- int value;
-} gpios[] = {
- { COLLIE_GPIO_CO, "main battery full", 0, 0 },
- { COLLIE_GPIO_MAIN_BAT_LOW, "main battery low", 0, 0 },
- { COLLIE_GPIO_CHARGE_ON, "main charge on", 1, 0 },
- { COLLIE_GPIO_MBAT_ON, "main battery", 1, 0 },
- { COLLIE_GPIO_TMP_ON, "main battery temp", 1, 0 },
- { COLLIE_GPIO_BBAT_ON, "backup battery", 1, 0 },
+static struct gpio collie_batt_gpios[] = {
+ { COLLIE_GPIO_CO, GPIOF_IN, "main battery full" },
+ { COLLIE_GPIO_MAIN_BAT_LOW, GPIOF_IN, "main battery low" },
+ { COLLIE_GPIO_CHARGE_ON, GPIOF_OUT_INIT_LOW, "main charge on" },
+ { COLLIE_GPIO_MBAT_ON, GPIOF_OUT_INIT_LOW, "main battery" },
+ { COLLIE_GPIO_TMP_ON, GPIOF_OUT_INIT_LOW, "main battery temp" },
+ { COLLIE_GPIO_BBAT_ON, GPIOF_OUT_INIT_LOW, "backup battery" },
};
#ifdef CONFIG_PM
@@ -313,29 +308,16 @@ static int collie_bat_resume(struct ucb1x00_dev *dev)
static int __devinit collie_bat_probe(struct ucb1x00_dev *dev)
{
int ret;
- int i;
if (!machine_is_collie())
return -ENODEV;
ucb = dev->ucb;
- for (i = 0; i < ARRAY_SIZE(gpios); i++) {
- ret = gpio_request(gpios[i].gpio, gpios[i].name);
- if (ret) {
- i--;
- goto err_gpio;
- }
-
- if (gpios[i].output)
- ret = gpio_direction_output(gpios[i].gpio,
- gpios[i].value);
- else
- ret = gpio_direction_input(gpios[i].gpio);
-
- if (ret)
- goto err_gpio;
- }
+ ret = gpio_request_array(collie_batt_gpios,
+ ARRAY_SIZE(collie_batt_gpios));
+ if (ret)
+ return ret;
mutex_init(&collie_bat_main.work_lock);
@@ -363,19 +345,12 @@ err_psy_reg_main:
/* see comment in collie_bat_remove */
cancel_work_sync(&bat_work);
-
- i--;
-err_gpio:
- for (; i >= 0; i--)
- gpio_free(gpios[i].gpio);
-
+ gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios));
return ret;
}
static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
{
- int i;
-
free_irq(gpio_to_irq(COLLIE_GPIO_CO), &collie_bat_main);
power_supply_unregister(&collie_bat_bu.psy);
@@ -387,9 +362,7 @@ static void __devexit collie_bat_remove(struct ucb1x00_dev *dev)
* unregistered now.
*/
cancel_work_sync(&bat_work);
-
- for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--)
- gpio_free(gpios[i].gpio);
+ gpio_free_array(collie_batt_gpios, ARRAY_SIZE(collie_batt_gpios));
}
static struct ucb1x00_driver collie_bat_driver = {
diff --git a/drivers/power/da9030_battery.c b/drivers/power/da9030_battery.c
index d2c793cf6765..3fd3e95d2b85 100644
--- a/drivers/power/da9030_battery.c
+++ b/drivers/power/da9030_battery.c
@@ -588,18 +588,7 @@ static struct platform_driver da903x_battery_driver = {
.remove = da9030_battery_remove,
};
-static int da903x_battery_init(void)
-{
- return platform_driver_register(&da903x_battery_driver);
-}
-
-static void da903x_battery_exit(void)
-{
- platform_driver_unregister(&da903x_battery_driver);
-}
-
-module_init(da903x_battery_init);
-module_exit(da903x_battery_exit);
+module_platform_driver(da903x_battery_driver);
MODULE_DESCRIPTION("DA9030 battery charger driver");
MODULE_AUTHOR("Mike Rapoport, CompuLab");
diff --git a/drivers/power/da9052-battery.c b/drivers/power/da9052-battery.c
new file mode 100644
index 000000000000..e8ea47a53dee
--- /dev/null
+++ b/drivers/power/da9052-battery.c
@@ -0,0 +1,664 @@
+/*
+ * Batttery Driver for Dialog DA9052 PMICs
+ *
+ * Copyright(c) 2011 Dialog Semiconductor Ltd.
+ *
+ * Author: David Dajun Chen <dchen@diasemi.com>
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/delay.h>
+#include <linux/freezer.h>
+#include <linux/fs.h>
+#include <linux/jiffies.h>
+#include <linux/module.h>
+#include <linux/timer.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/power_supply.h>
+
+#include <linux/mfd/da9052/da9052.h>
+#include <linux/mfd/da9052/pdata.h>
+#include <linux/mfd/da9052/reg.h>
+
+/* STATIC CONFIGURATION */
+#define DA9052_BAT_CUTOFF_VOLT 2800
+#define DA9052_BAT_TSH 62000
+#define DA9052_BAT_LOW_CAP 4
+#define DA9052_AVG_SZ 4
+#define DA9052_VC_TBL_SZ 68
+#define DA9052_VC_TBL_REF_SZ 3
+
+#define DA9052_ISET_USB_MASK 0x0F
+#define DA9052_CHG_USB_ILIM_MASK 0x40
+#define DA9052_CHG_LIM_COLS 16
+
+#define DA9052_MEAN(x, y) ((x + y) / 2)
+
+enum charger_type_enum {
+ DA9052_NOCHARGER = 1,
+ DA9052_CHARGER,
+};
+
+static const u16 da9052_chg_current_lim[2][DA9052_CHG_LIM_COLS] = {
+ {70, 80, 90, 100, 110, 120, 400, 450,
+ 500, 550, 600, 650, 700, 900, 1100, 1300},
+ {80, 90, 100, 110, 120, 400, 450, 500,
+ 550, 600, 800, 1000, 1200, 1400, 1600, 1800},
+};
+
+static const u16 vc_tbl_ref[3] = {10, 25, 40};
+/* Lookup table for voltage vs capacity */
+static u32 const vc_tbl[3][68][2] = {
+ /* For temperature 10 degree Celsius */
+ {
+ {4082, 100}, {4036, 98},
+ {4020, 96}, {4008, 95},
+ {3997, 93}, {3983, 91},
+ {3964, 90}, {3943, 88},
+ {3926, 87}, {3912, 85},
+ {3900, 84}, {3890, 82},
+ {3881, 80}, {3873, 79},
+ {3865, 77}, {3857, 76},
+ {3848, 74}, {3839, 73},
+ {3829, 71}, {3820, 70},
+ {3811, 68}, {3802, 67},
+ {3794, 65}, {3785, 64},
+ {3778, 62}, {3770, 61},
+ {3763, 59}, {3756, 58},
+ {3750, 56}, {3744, 55},
+ {3738, 53}, {3732, 52},
+ {3727, 50}, {3722, 49},
+ {3717, 47}, {3712, 46},
+ {3708, 44}, {3703, 43},
+ {3700, 41}, {3696, 40},
+ {3693, 38}, {3691, 37},
+ {3688, 35}, {3686, 34},
+ {3683, 32}, {3681, 31},
+ {3678, 29}, {3675, 28},
+ {3672, 26}, {3669, 25},
+ {3665, 23}, {3661, 22},
+ {3656, 21}, {3651, 19},
+ {3645, 18}, {3639, 16},
+ {3631, 15}, {3622, 13},
+ {3611, 12}, {3600, 10},
+ {3587, 9}, {3572, 7},
+ {3548, 6}, {3503, 5},
+ {3420, 3}, {3268, 2},
+ {2992, 1}, {2746, 0}
+ },
+ /* For temperature 25 degree Celsius */
+ {
+ {4102, 100}, {4065, 98},
+ {4048, 96}, {4034, 95},
+ {4021, 93}, {4011, 92},
+ {4001, 90}, {3986, 88},
+ {3968, 87}, {3952, 85},
+ {3938, 84}, {3926, 82},
+ {3916, 81}, {3908, 79},
+ {3900, 77}, {3892, 76},
+ {3883, 74}, {3874, 73},
+ {3864, 71}, {3855, 70},
+ {3846, 68}, {3836, 67},
+ {3827, 65}, {3819, 64},
+ {3810, 62}, {3801, 61},
+ {3793, 59}, {3786, 58},
+ {3778, 56}, {3772, 55},
+ {3765, 53}, {3759, 52},
+ {3754, 50}, {3748, 49},
+ {3743, 47}, {3738, 46},
+ {3733, 44}, {3728, 43},
+ {3724, 41}, {3720, 40},
+ {3716, 38}, {3712, 37},
+ {3709, 35}, {3706, 34},
+ {3703, 33}, {3701, 31},
+ {3698, 30}, {3696, 28},
+ {3693, 27}, {3690, 25},
+ {3687, 24}, {3683, 22},
+ {3680, 21}, {3675, 19},
+ {3671, 18}, {3666, 17},
+ {3660, 15}, {3654, 14},
+ {3647, 12}, {3639, 11},
+ {3630, 9}, {3621, 8},
+ {3613, 6}, {3606, 5},
+ {3597, 4}, {3582, 2},
+ {3546, 1}, {2747, 0}
+ },
+ /* For temperature 40 degree Celsius */
+ {
+ {4114, 100}, {4081, 98},
+ {4065, 96}, {4050, 95},
+ {4036, 93}, {4024, 92},
+ {4013, 90}, {4002, 88},
+ {3990, 87}, {3976, 85},
+ {3962, 84}, {3950, 82},
+ {3939, 81}, {3930, 79},
+ {3921, 77}, {3912, 76},
+ {3902, 74}, {3893, 73},
+ {3883, 71}, {3874, 70},
+ {3865, 68}, {3856, 67},
+ {3847, 65}, {3838, 64},
+ {3829, 62}, {3820, 61},
+ {3812, 59}, {3803, 58},
+ {3795, 56}, {3787, 55},
+ {3780, 53}, {3773, 52},
+ {3767, 50}, {3761, 49},
+ {3756, 47}, {3751, 46},
+ {3746, 44}, {3741, 43},
+ {3736, 41}, {3732, 40},
+ {3728, 38}, {3724, 37},
+ {3720, 35}, {3716, 34},
+ {3713, 33}, {3710, 31},
+ {3707, 30}, {3704, 28},
+ {3701, 27}, {3698, 25},
+ {3695, 24}, {3691, 22},
+ {3686, 21}, {3681, 19},
+ {3676, 18}, {3671, 17},
+ {3666, 15}, {3661, 14},
+ {3655, 12}, {3648, 11},
+ {3640, 9}, {3632, 8},
+ {3622, 6}, {3616, 5},
+ {3611, 4}, {3604, 2},
+ {3594, 1}, {2747, 0}
+ }
+};
+
+struct da9052_battery {
+ struct da9052 *da9052;
+ struct power_supply psy;
+ struct notifier_block nb;
+ int charger_type;
+ int status;
+ int health;
+};
+
+static inline int volt_reg_to_mV(int value)
+{
+ return ((value * 1000) / 512) + 2500;
+}
+
+static inline int ichg_reg_to_mA(int value)
+{
+ return (value * 3900) / 1000;
+}
+
+static int da9052_read_chgend_current(struct da9052_battery *bat,
+ int *current_mA)
+{
+ int ret;
+
+ if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING)
+ return -EINVAL;
+
+ ret = da9052_reg_read(bat->da9052, DA9052_ICHG_END_REG);
+ if (ret < 0)
+ return ret;
+
+ *current_mA = ichg_reg_to_mA(ret & DA9052_ICHGEND_ICHGEND);
+
+ return 0;
+}
+
+static int da9052_read_chg_current(struct da9052_battery *bat, int *current_mA)
+{
+ int ret;
+
+ if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING)
+ return -EINVAL;
+
+ ret = da9052_reg_read(bat->da9052, DA9052_ICHG_AV_REG);
+ if (ret < 0)
+ return ret;
+
+ *current_mA = ichg_reg_to_mA(ret & DA9052_ICHGAV_ICHGAV);
+
+ return 0;
+}
+
+static int da9052_bat_check_status(struct da9052_battery *bat, int *status)
+{
+ u8 v[2] = {0, 0};
+ u8 bat_status;
+ u8 chg_end;
+ int ret;
+ int chg_current;
+ int chg_end_current;
+ bool dcinsel;
+ bool dcindet;
+ bool vbussel;
+ bool vbusdet;
+ bool dc;
+ bool vbus;
+
+ ret = da9052_group_read(bat->da9052, DA9052_STATUS_A_REG, 2, v);
+ if (ret < 0)
+ return ret;
+
+ bat_status = v[0];
+ chg_end = v[1];
+
+ dcinsel = bat_status & DA9052_STATUSA_DCINSEL;
+ dcindet = bat_status & DA9052_STATUSA_DCINDET;
+ vbussel = bat_status & DA9052_STATUSA_VBUSSEL;
+ vbusdet = bat_status & DA9052_STATUSA_VBUSDET;
+ dc = dcinsel && dcindet;
+ vbus = vbussel && vbusdet;
+
+ /* Preference to WALL(DCIN) charger unit */
+ if (dc || vbus) {
+ bat->charger_type = DA9052_CHARGER;
+
+ /* If charging end flag is set and Charging current is greater
+ * than charging end limit then battery is charging
+ */
+ if ((chg_end & DA9052_STATUSB_CHGEND) != 0) {
+ ret = da9052_read_chg_current(bat, &chg_current);
+ if (ret < 0)
+ return ret;
+ ret = da9052_read_chgend_current(bat, &chg_end_current);
+ if (ret < 0)
+ return ret;
+
+ if (chg_current >= chg_end_current)
+ bat->status = POWER_SUPPLY_STATUS_CHARGING;
+ else
+ bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ /* If Charging end flag is cleared then battery is
+ * charging
+ */
+ bat->status = POWER_SUPPLY_STATUS_CHARGING;
+ }
+ } else if (dcindet || vbusdet) {
+ bat->charger_type = DA9052_CHARGER;
+ bat->status = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ } else {
+ bat->charger_type = DA9052_NOCHARGER;
+ bat->status = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+
+ if (status != NULL)
+ *status = bat->status;
+ return 0;
+}
+
+static int da9052_bat_read_volt(struct da9052_battery *bat, int *volt_mV)
+{
+ int volt;
+
+ volt = da9052_adc_manual_read(bat->da9052, DA9052_ADC_MAN_MUXSEL_VBAT);
+ if (volt < 0)
+ return volt;
+
+ *volt_mV = volt_reg_to_mV(volt);
+
+ return 0;
+}
+
+static int da9052_bat_check_presence(struct da9052_battery *bat, int *illegal)
+{
+ int bat_temp;
+
+ bat_temp = da9052_adc_read_temp(bat->da9052);
+ if (bat_temp < 0)
+ return bat_temp;
+
+ if (bat_temp > DA9052_BAT_TSH)
+ *illegal = 1;
+ else
+ *illegal = 0;
+
+ return 0;
+}
+
+static int da9052_bat_interpolate(int vbat_lower, int vbat_upper,
+ int level_lower, int level_upper,
+ int bat_voltage)
+{
+ int tmp;
+
+ tmp = ((level_upper - level_lower) * 1000) / (vbat_upper - vbat_lower);
+ tmp = level_lower + (((bat_voltage - vbat_lower) * tmp) / 1000);
+
+ return tmp;
+}
+
+unsigned char da9052_determine_vc_tbl_index(unsigned char adc_temp)
+{
+ int i;
+
+ if (adc_temp <= vc_tbl_ref[0])
+ return 0;
+
+ if (adc_temp > vc_tbl_ref[DA9052_VC_TBL_REF_SZ - 1])
+ return DA9052_VC_TBL_REF_SZ - 1;
+
+ for (i = 0; i < DA9052_VC_TBL_REF_SZ; i++) {
+ if ((adc_temp > vc_tbl_ref[i]) &&
+ (adc_temp <= DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1])))
+ return i;
+ if ((adc_temp > DA9052_MEAN(vc_tbl_ref[i], vc_tbl_ref[i + 1]))
+ && (adc_temp <= vc_tbl_ref[i]))
+ return i + 1;
+ }
+}
+
+static int da9052_bat_read_capacity(struct da9052_battery *bat, int *capacity)
+{
+ int adc_temp;
+ int bat_voltage;
+ int vbat_lower;
+ int vbat_upper;
+ int level_upper;
+ int level_lower;
+ int ret;
+ int flag;
+ int i = 0;
+ int j;
+
+ ret = da9052_bat_read_volt(bat, &bat_voltage);
+ if (ret < 0)
+ return ret;
+
+ adc_temp = da9052_adc_read_temp(bat->da9052);
+ if (adc_temp < 0)
+ return adc_temp;
+
+ i = da9052_determine_vc_tbl_index(adc_temp);
+
+ if (bat_voltage >= vc_tbl[i][0][0]) {
+ *capacity = 100;
+ return 0;
+ }
+ if (bat_voltage <= vc_tbl[i][DA9052_VC_TBL_SZ - 1][0]) {
+ *capacity = 0;
+ return 0;
+ }
+ flag = 0;
+
+ for (j = 0; j < (DA9052_VC_TBL_SZ-1); j++) {
+ if ((bat_voltage <= vc_tbl[i][j][0]) &&
+ (bat_voltage >= vc_tbl[i][j + 1][0])) {
+ vbat_upper = vc_tbl[i][j][0];
+ vbat_lower = vc_tbl[i][j + 1][0];
+ level_upper = vc_tbl[i][j][1];
+ level_lower = vc_tbl[i][j + 1][1];
+ flag = 1;
+ break;
+ }
+ }
+ if (!flag)
+ return -EIO;
+
+ *capacity = da9052_bat_interpolate(vbat_lower, vbat_upper, level_lower,
+ level_upper, bat_voltage);
+
+ return 0;
+}
+
+static int da9052_bat_check_health(struct da9052_battery *bat, int *health)
+{
+ int ret;
+ int bat_illegal;
+ int capacity;
+
+ ret = da9052_bat_check_presence(bat, &bat_illegal);
+ if (ret < 0)
+ return ret;
+
+ if (bat_illegal) {
+ bat->health = POWER_SUPPLY_HEALTH_UNKNOWN;
+ return 0;
+ }
+
+ if (bat->health != POWER_SUPPLY_HEALTH_OVERHEAT) {
+ ret = da9052_bat_read_capacity(bat, &capacity);
+ if (ret < 0)
+ return ret;
+ if (capacity < DA9052_BAT_LOW_CAP)
+ bat->health = POWER_SUPPLY_HEALTH_DEAD;
+ else
+ bat->health = POWER_SUPPLY_HEALTH_GOOD;
+ }
+
+ *health = bat->health;
+
+ return 0;
+}
+
+static irqreturn_t da9052_bat_irq(int irq, void *data)
+{
+ struct da9052_battery *bat = data;
+
+ irq -= bat->da9052->irq_base;
+
+ if (irq == DA9052_IRQ_CHGEND)
+ bat->status = POWER_SUPPLY_STATUS_FULL;
+ else
+ da9052_bat_check_status(bat, NULL);
+
+ if (irq == DA9052_IRQ_CHGEND || irq == DA9052_IRQ_DCIN ||
+ irq == DA9052_IRQ_VBUS || irq == DA9052_IRQ_TBAT) {
+ power_supply_changed(&bat->psy);
+ }
+
+ return IRQ_HANDLED;
+}
+
+static int da9052_USB_current_notifier(struct notifier_block *nb,
+ unsigned long events, void *data)
+{
+ u8 row;
+ u8 col;
+ int *current_mA = data;
+ int ret;
+ struct da9052_battery *bat = container_of(nb, struct da9052_battery,
+ nb);
+
+ if (bat->status == POWER_SUPPLY_STATUS_DISCHARGING)
+ return -EPERM;
+
+ ret = da9052_reg_read(bat->da9052, DA9052_CHGBUCK_REG);
+ if (ret & DA9052_CHG_USB_ILIM_MASK)
+ return -EPERM;
+
+ if (bat->da9052->chip_id == DA9052)
+ row = 0;
+ else
+ row = 1;
+
+ if (*current_mA < da9052_chg_current_lim[row][0] ||
+ *current_mA > da9052_chg_current_lim[row][DA9052_CHG_LIM_COLS - 1])
+ return -EINVAL;
+
+ for (col = 0; col <= DA9052_CHG_LIM_COLS - 1 ; col++) {
+ if (*current_mA <= da9052_chg_current_lim[row][col])
+ break;
+ }
+
+ return da9052_reg_update(bat->da9052, DA9052_ISET_REG,
+ DA9052_ISET_USB_MASK, col);
+}
+
+static int da9052_bat_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ int ret;
+ int illegal;
+ struct da9052_battery *bat = container_of(psy, struct da9052_battery,
+ psy);
+
+ ret = da9052_bat_check_presence(bat, &illegal);
+ if (ret < 0)
+ return ret;
+
+ if (illegal && psp != POWER_SUPPLY_PROP_PRESENT)
+ return -ENODEV;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ ret = da9052_bat_check_status(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_ONLINE:
+ val->intval =
+ (bat->charger_type == DA9052_NOCHARGER) ? 0 : 1;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ ret = da9052_bat_check_presence(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ ret = da9052_bat_check_health(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
+ val->intval = DA9052_BAT_CUTOFF_VOLT * 1000;
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_AVG:
+ ret = da9052_bat_read_volt(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CURRENT_AVG:
+ ret = da9052_read_chg_current(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ ret = da9052_bat_read_capacity(bat, &val->intval);
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ val->intval = da9052_adc_read_temp(bat->da9052);
+ ret = val->intval;
+ break;
+ case POWER_SUPPLY_PROP_TECHNOLOGY:
+ val->intval = POWER_SUPPLY_TECHNOLOGY_LION;
+ break;
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+static enum power_supply_property da9052_bat_props[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_ONLINE,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN,
+ POWER_SUPPLY_PROP_VOLTAGE_AVG,
+ POWER_SUPPLY_PROP_CURRENT_AVG,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_TEMP,
+ POWER_SUPPLY_PROP_TECHNOLOGY,
+};
+
+static struct power_supply template_battery = {
+ .name = "da9052-bat",
+ .type = POWER_SUPPLY_TYPE_BATTERY,
+ .properties = da9052_bat_props,
+ .num_properties = ARRAY_SIZE(da9052_bat_props),
+ .get_property = da9052_bat_get_property,
+};
+
+static const char *const da9052_bat_irqs[] = {
+ "BATT TEMP",
+ "DCIN DET",
+ "DCIN REM",
+ "VBUS DET",
+ "VBUS REM",
+ "CHG END",
+};
+
+static s32 __devinit da9052_bat_probe(struct platform_device *pdev)
+{
+ struct da9052_pdata *pdata;
+ struct da9052_battery *bat;
+ int ret;
+ int irq;
+ int i;
+
+ bat = kzalloc(sizeof(struct da9052_battery), GFP_KERNEL);
+ if (!bat)
+ return -ENOMEM;
+
+ bat->da9052 = dev_get_drvdata(pdev->dev.parent);
+ bat->psy = template_battery;
+ bat->charger_type = DA9052_NOCHARGER;
+ bat->status = POWER_SUPPLY_STATUS_UNKNOWN;
+ bat->health = POWER_SUPPLY_HEALTH_UNKNOWN;
+ bat->nb.notifier_call = da9052_USB_current_notifier;
+
+ pdata = bat->da9052->dev->platform_data;
+ if (pdata != NULL && pdata->use_for_apm)
+ bat->psy.use_for_apm = pdata->use_for_apm;
+ else
+ bat->psy.use_for_apm = 1;
+
+ for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
+ irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
+ ret = request_threaded_irq(bat->da9052->irq_base + irq,
+ NULL, da9052_bat_irq,
+ IRQF_TRIGGER_LOW | IRQF_ONESHOT,
+ da9052_bat_irqs[i], bat);
+ if (ret != 0) {
+ dev_err(bat->da9052->dev,
+ "DA9052 failed to request %s IRQ %d: %d\n",
+ da9052_bat_irqs[i], irq, ret);
+ goto err;
+ }
+ }
+
+ ret = power_supply_register(&pdev->dev, &bat->psy);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ for (; i >= 0; i--) {
+ irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
+ free_irq(bat->da9052->irq_base + irq, bat);
+ }
+ kfree(bat);
+ return ret;
+}
+static int __devexit da9052_bat_remove(struct platform_device *pdev)
+{
+ int i;
+ int irq;
+ struct da9052_battery *bat = platform_get_drvdata(pdev);
+
+ for (i = 0; i < ARRAY_SIZE(da9052_bat_irqs); i++) {
+ irq = platform_get_irq_byname(pdev, da9052_bat_irqs[i]);
+ free_irq(bat->da9052->irq_base + irq, bat);
+ }
+ power_supply_unregister(&bat->psy);
+
+ return 0;
+}
+
+static struct platform_driver da9052_bat_driver = {
+ .probe = da9052_bat_probe,
+ .remove = __devexit_p(da9052_bat_remove),
+ .driver = {
+ .name = "da9052-bat",
+ .owner = THIS_MODULE,
+ },
+};
+
+static int __init da9052_bat_init(void)
+{
+ return platform_driver_register(&da9052_bat_driver);
+}
+module_init(da9052_bat_init);
+
+static void __exit da9052_bat_exit(void)
+{
+ platform_driver_unregister(&da9052_bat_driver);
+}
+module_exit(da9052_bat_exit);
+
+MODULE_DESCRIPTION("DA9052 BAT Device Driver");
+MODULE_AUTHOR("David Dajun Chen <dchen@diasemi.com>");
+MODULE_LICENSE("GPL");
+MODULE_ALIAS("platform:da9052-bat");
diff --git a/drivers/power/ds2760_battery.c b/drivers/power/ds2760_battery.c
index f2c9cc33c0f9..545874b1df9e 100644
--- a/drivers/power/ds2760_battery.c
+++ b/drivers/power/ds2760_battery.c
@@ -95,7 +95,11 @@ static int rated_capacities[] = {
2880, /* Samsung */
2880, /* BYD */
2880, /* Lishen */
- 2880 /* NEC */
+ 2880, /* NEC */
+#ifdef CONFIG_MACH_H4700
+ 0,
+ 3600, /* HP iPAQ hx4700 3.7V 3600mAh (359114-001) */
+#endif
};
/* array is level at temps 0°C, 10°C, 20°C, 30°C, 40°C
@@ -637,18 +641,7 @@ static struct platform_driver ds2760_battery_driver = {
.resume = ds2760_battery_resume,
};
-static int __init ds2760_battery_init(void)
-{
- return platform_driver_register(&ds2760_battery_driver);
-}
-
-static void __exit ds2760_battery_exit(void)
-{
- platform_driver_unregister(&ds2760_battery_driver);
-}
-
-module_init(ds2760_battery_init);
-module_exit(ds2760_battery_exit);
+module_platform_driver(ds2760_battery_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Szabolcs Gyurko <szabolcs.gyurko@tlt.hu>, "
diff --git a/drivers/power/ds2780_battery.c b/drivers/power/ds2780_battery.c
index 91a783d72360..de31cae1ba53 100644
--- a/drivers/power/ds2780_battery.c
+++ b/drivers/power/ds2780_battery.c
@@ -841,29 +841,17 @@ static int __devexit ds2780_battery_remove(struct platform_device *pdev)
return 0;
}
-MODULE_ALIAS("platform:ds2780-battery");
-
static struct platform_driver ds2780_battery_driver = {
.driver = {
.name = "ds2780-battery",
},
.probe = ds2780_battery_probe,
- .remove = ds2780_battery_remove,
+ .remove = __devexit_p(ds2780_battery_remove),
};
-static int __init ds2780_battery_init(void)
-{
- return platform_driver_register(&ds2780_battery_driver);
-}
-
-static void __exit ds2780_battery_exit(void)
-{
- platform_driver_unregister(&ds2780_battery_driver);
-}
-
-module_init(ds2780_battery_init);
-module_exit(ds2780_battery_exit);
+module_platform_driver(ds2780_battery_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Clifton Barnes <cabarnes@indesign-llc.com>");
MODULE_DESCRIPTION("Maxim/Dallas DS2780 Stand-Alone Fuel Gauage IC driver");
+MODULE_ALIAS("platform:ds2780-battery");
diff --git a/drivers/power/gpio-charger.c b/drivers/power/gpio-charger.c
index a64b8854cfd5..8672c9177dd7 100644
--- a/drivers/power/gpio-charger.c
+++ b/drivers/power/gpio-charger.c
@@ -185,17 +185,7 @@ static struct platform_driver gpio_charger_driver = {
},
};
-static int __init gpio_charger_init(void)
-{
- return platform_driver_register(&gpio_charger_driver);
-}
-module_init(gpio_charger_init);
-
-static void __exit gpio_charger_exit(void)
-{
- platform_driver_unregister(&gpio_charger_driver);
-}
-module_exit(gpio_charger_exit);
+module_platform_driver(gpio_charger_driver);
MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
MODULE_DESCRIPTION("Driver for chargers which report their online status through a GPIO");
diff --git a/drivers/power/intel_mid_battery.c b/drivers/power/intel_mid_battery.c
index 01fa671ec97f..d09649706bd3 100644
--- a/drivers/power/intel_mid_battery.c
+++ b/drivers/power/intel_mid_battery.c
@@ -779,18 +779,7 @@ static struct platform_driver platform_pmic_battery_driver = {
.remove = __devexit_p(platform_pmic_battery_remove),
};
-static int __init platform_pmic_battery_module_init(void)
-{
- return platform_driver_register(&platform_pmic_battery_driver);
-}
-
-static void __exit platform_pmic_battery_module_exit(void)
-{
- platform_driver_unregister(&platform_pmic_battery_driver);
-}
-
-module_init(platform_pmic_battery_module_init);
-module_exit(platform_pmic_battery_module_exit);
+module_platform_driver(platform_pmic_battery_driver);
MODULE_AUTHOR("Nithish Mahalingam <nithish.mahalingam@intel.com>");
MODULE_DESCRIPTION("Intel Moorestown PMIC Battery Driver");
diff --git a/drivers/power/isp1704_charger.c b/drivers/power/isp1704_charger.c
index f6d72b402a8e..b806667b59ae 100644
--- a/drivers/power/isp1704_charger.c
+++ b/drivers/power/isp1704_charger.c
@@ -79,7 +79,7 @@ static void isp1704_charger_set_power(struct isp1704_charger *isp, bool on)
{
struct isp1704_charger_data *board = isp->dev->platform_data;
- if (board->set_power)
+ if (board && board->set_power)
board->set_power(on);
}
@@ -494,17 +494,7 @@ static struct platform_driver isp1704_charger_driver = {
.remove = __devexit_p(isp1704_charger_remove),
};
-static int __init isp1704_charger_init(void)
-{
- return platform_driver_register(&isp1704_charger_driver);
-}
-module_init(isp1704_charger_init);
-
-static void __exit isp1704_charger_exit(void)
-{
- platform_driver_unregister(&isp1704_charger_driver);
-}
-module_exit(isp1704_charger_exit);
+module_platform_driver(isp1704_charger_driver);
MODULE_ALIAS("platform:isp1704_charger");
MODULE_AUTHOR("Nokia Corporation");
diff --git a/drivers/power/jz4740-battery.c b/drivers/power/jz4740-battery.c
index 763f894ed188..8dbc7bfaab14 100644
--- a/drivers/power/jz4740-battery.c
+++ b/drivers/power/jz4740-battery.c
@@ -67,7 +67,7 @@ static irqreturn_t jz_battery_irq_handler(int irq, void *devid)
static long jz_battery_read_voltage(struct jz_battery *battery)
{
- unsigned long t;
+ long t;
unsigned long val;
long voltage;
@@ -441,17 +441,7 @@ static struct platform_driver jz_battery_driver = {
},
};
-static int __init jz_battery_init(void)
-{
- return platform_driver_register(&jz_battery_driver);
-}
-module_init(jz_battery_init);
-
-static void __exit jz_battery_exit(void)
-{
- platform_driver_unregister(&jz_battery_driver);
-}
-module_exit(jz_battery_exit);
+module_platform_driver(jz_battery_driver);
MODULE_ALIAS("platform:jz4740-battery");
MODULE_LICENSE("GPL");
diff --git a/drivers/power/lp8727_charger.c b/drivers/power/lp8727_charger.c
new file mode 100644
index 000000000000..b15b575c070c
--- /dev/null
+++ b/drivers/power/lp8727_charger.c
@@ -0,0 +1,494 @@
+/*
+ * Driver for LP8727 Micro/Mini USB IC with intergrated charger
+ *
+ * Copyright (C) 2011 National Semiconductor
+ *
+ * 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.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/i2c.h>
+#include <linux/power_supply.h>
+#include <linux/lp8727.h>
+
+#define DEBOUNCE_MSEC 270
+
+/* Registers */
+#define CTRL1 0x1
+#define CTRL2 0x2
+#define SWCTRL 0x3
+#define INT1 0x4
+#define INT2 0x5
+#define STATUS1 0x6
+#define STATUS2 0x7
+#define CHGCTRL2 0x9
+
+/* CTRL1 register */
+#define CP_EN (1 << 0)
+#define ADC_EN (1 << 1)
+#define ID200_EN (1 << 4)
+
+/* CTRL2 register */
+#define CHGDET_EN (1 << 1)
+#define INT_EN (1 << 6)
+
+/* SWCTRL register */
+#define SW_DM1_DM (0x0 << 0)
+#define SW_DM1_U1 (0x1 << 0)
+#define SW_DM1_HiZ (0x7 << 0)
+#define SW_DP2_DP (0x0 << 3)
+#define SW_DP2_U2 (0x1 << 3)
+#define SW_DP2_HiZ (0x7 << 3)
+
+/* INT1 register */
+#define IDNO (0xF << 0)
+#define VBUS (1 << 4)
+
+/* STATUS1 register */
+#define CHGSTAT (3 << 4)
+#define CHPORT (1 << 6)
+#define DCPORT (1 << 7)
+
+/* STATUS2 register */
+#define TEMP_STAT (3 << 5)
+
+enum lp8727_dev_id {
+ ID_NONE,
+ ID_TA,
+ ID_DEDICATED_CHG,
+ ID_USB_CHG,
+ ID_USB_DS,
+ ID_MAX,
+};
+
+enum lp8727_chg_stat {
+ PRECHG,
+ CC,
+ CV,
+ EOC,
+};
+
+struct lp8727_psy {
+ struct power_supply ac;
+ struct power_supply usb;
+ struct power_supply batt;
+};
+
+struct lp8727_chg {
+ struct device *dev;
+ struct i2c_client *client;
+ struct mutex xfer_lock;
+ struct delayed_work work;
+ struct workqueue_struct *irqthread;
+ struct lp8727_platform_data *pdata;
+ struct lp8727_psy *psy;
+ struct lp8727_chg_param *chg_parm;
+ enum lp8727_dev_id devid;
+};
+
+static int lp8727_i2c_read(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
+{
+ s32 ret;
+
+ mutex_lock(&pchg->xfer_lock);
+ ret = i2c_smbus_read_i2c_block_data(pchg->client, reg, len, data);
+ mutex_unlock(&pchg->xfer_lock);
+
+ return (ret != len) ? -EIO : 0;
+}
+
+static int lp8727_i2c_write(struct lp8727_chg *pchg, u8 reg, u8 *data, u8 len)
+{
+ s32 ret;
+
+ mutex_lock(&pchg->xfer_lock);
+ ret = i2c_smbus_write_i2c_block_data(pchg->client, reg, len, data);
+ mutex_unlock(&pchg->xfer_lock);
+
+ return ret;
+}
+
+static inline int lp8727_i2c_read_byte(struct lp8727_chg *pchg, u8 reg,
+ u8 *data)
+{
+ return lp8727_i2c_read(pchg, reg, data, 1);
+}
+
+static inline int lp8727_i2c_write_byte(struct lp8727_chg *pchg, u8 reg,
+ u8 *data)
+{
+ return lp8727_i2c_write(pchg, reg, data, 1);
+}
+
+static int lp8727_is_charger_attached(const char *name, int id)
+{
+ if (name) {
+ if (!strcmp(name, "ac"))
+ return (id == ID_TA || id == ID_DEDICATED_CHG) ? 1 : 0;
+ else if (!strcmp(name, "usb"))
+ return (id == ID_USB_CHG) ? 1 : 0;
+ }
+
+ return (id >= ID_TA && id <= ID_USB_CHG) ? 1 : 0;
+}
+
+static void lp8727_init_device(struct lp8727_chg *pchg)
+{
+ u8 val;
+
+ val = ID200_EN | ADC_EN | CP_EN;
+ if (lp8727_i2c_write_byte(pchg, CTRL1, &val))
+ dev_err(pchg->dev, "i2c write err : addr=0x%.2x\n", CTRL1);
+
+ val = INT_EN | CHGDET_EN;
+ if (lp8727_i2c_write_byte(pchg, CTRL2, &val))
+ dev_err(pchg->dev, "i2c write err : addr=0x%.2x\n", CTRL2);
+}
+
+static int lp8727_is_dedicated_charger(struct lp8727_chg *pchg)
+{
+ u8 val;
+ lp8727_i2c_read_byte(pchg, STATUS1, &val);
+ return (val & DCPORT);
+}
+
+static int lp8727_is_usb_charger(struct lp8727_chg *pchg)
+{
+ u8 val;
+ lp8727_i2c_read_byte(pchg, STATUS1, &val);
+ return (val & CHPORT);
+}
+
+static void lp8727_ctrl_switch(struct lp8727_chg *pchg, u8 sw)
+{
+ u8 val = sw;
+ lp8727_i2c_write_byte(pchg, SWCTRL, &val);
+}
+
+static void lp8727_id_detection(struct lp8727_chg *pchg, u8 id, int vbusin)
+{
+ u8 devid = ID_NONE;
+ u8 swctrl = SW_DM1_HiZ | SW_DP2_HiZ;
+
+ switch (id) {
+ case 0x5:
+ devid = ID_TA;
+ pchg->chg_parm = &pchg->pdata->ac;
+ break;
+ case 0xB:
+ if (lp8727_is_dedicated_charger(pchg)) {
+ pchg->chg_parm = &pchg->pdata->ac;
+ devid = ID_DEDICATED_CHG;
+ } else if (lp8727_is_usb_charger(pchg)) {
+ pchg->chg_parm = &pchg->pdata->usb;
+ devid = ID_USB_CHG;
+ swctrl = SW_DM1_DM | SW_DP2_DP;
+ } else if (vbusin) {
+ devid = ID_USB_DS;
+ swctrl = SW_DM1_DM | SW_DP2_DP;
+ }
+ break;
+ default:
+ devid = ID_NONE;
+ pchg->chg_parm = NULL;
+ break;
+ }
+
+ pchg->devid = devid;
+ lp8727_ctrl_switch(pchg, swctrl);
+}
+
+static void lp8727_enable_chgdet(struct lp8727_chg *pchg)
+{
+ u8 val;
+
+ lp8727_i2c_read_byte(pchg, CTRL2, &val);
+ val |= CHGDET_EN;
+ lp8727_i2c_write_byte(pchg, CTRL2, &val);
+}
+
+static void lp8727_delayed_func(struct work_struct *_work)
+{
+ u8 intstat[2], idno, vbus;
+ struct lp8727_chg *pchg =
+ container_of(_work, struct lp8727_chg, work.work);
+
+ if (lp8727_i2c_read(pchg, INT1, intstat, 2)) {
+ dev_err(pchg->dev, "can not read INT registers\n");
+ return;
+ }
+
+ idno = intstat[0] & IDNO;
+ vbus = intstat[0] & VBUS;
+
+ lp8727_id_detection(pchg, idno, vbus);
+ lp8727_enable_chgdet(pchg);
+
+ power_supply_changed(&pchg->psy->ac);
+ power_supply_changed(&pchg->psy->usb);
+ power_supply_changed(&pchg->psy->batt);
+}
+
+static irqreturn_t lp8727_isr_func(int irq, void *ptr)
+{
+ struct lp8727_chg *pchg = ptr;
+ unsigned long delay = msecs_to_jiffies(DEBOUNCE_MSEC);
+
+ queue_delayed_work(pchg->irqthread, &pchg->work, delay);
+
+ return IRQ_HANDLED;
+}
+
+static void lp8727_intr_config(struct lp8727_chg *pchg)
+{
+ INIT_DELAYED_WORK(&pchg->work, lp8727_delayed_func);
+
+ pchg->irqthread = create_singlethread_workqueue("lp8727-irqthd");
+ if (!pchg->irqthread)
+ dev_err(pchg->dev, "can not create thread for lp8727\n");
+
+ if (request_threaded_irq(pchg->client->irq,
+ NULL,
+ lp8727_isr_func,
+ IRQF_TRIGGER_FALLING, "lp8727_irq", pchg)) {
+ dev_err(pchg->dev, "lp8727 irq can not be registered\n");
+ }
+}
+
+static enum power_supply_property lp8727_charger_prop[] = {
+ POWER_SUPPLY_PROP_ONLINE,
+};
+
+static enum power_supply_property lp8727_battery_prop[] = {
+ POWER_SUPPLY_PROP_STATUS,
+ POWER_SUPPLY_PROP_HEALTH,
+ POWER_SUPPLY_PROP_PRESENT,
+ POWER_SUPPLY_PROP_VOLTAGE_NOW,
+ POWER_SUPPLY_PROP_CAPACITY,
+ POWER_SUPPLY_PROP_TEMP,
+};
+
+static char *battery_supplied_to[] = {
+ "main_batt",
+};
+
+static int lp8727_charger_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
+
+ if (psp == POWER_SUPPLY_PROP_ONLINE)
+ val->intval = lp8727_is_charger_attached(psy->name,
+ pchg->devid);
+
+ return 0;
+}
+
+static int lp8727_battery_get_property(struct power_supply *psy,
+ enum power_supply_property psp,
+ union power_supply_propval *val)
+{
+ struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
+ u8 read;
+
+ switch (psp) {
+ case POWER_SUPPLY_PROP_STATUS:
+ if (lp8727_is_charger_attached(psy->name, pchg->devid)) {
+ lp8727_i2c_read_byte(pchg, STATUS1, &read);
+ if (((read & CHGSTAT) >> 4) == EOC)
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+ else
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ } else {
+ val->intval = POWER_SUPPLY_STATUS_DISCHARGING;
+ }
+ break;
+ case POWER_SUPPLY_PROP_HEALTH:
+ lp8727_i2c_read_byte(pchg, STATUS2, &read);
+ read = (read & TEMP_STAT) >> 5;
+ if (read >= 0x1 && read <= 0x3)
+ val->intval = POWER_SUPPLY_HEALTH_OVERHEAT;
+ else
+ val->intval = POWER_SUPPLY_HEALTH_GOOD;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ if (pchg->pdata->get_batt_present)
+ val->intval = pchg->pdata->get_batt_present();
+ break;
+ case POWER_SUPPLY_PROP_VOLTAGE_NOW:
+ if (pchg->pdata->get_batt_level)
+ val->intval = pchg->pdata->get_batt_level();
+ break;
+ case POWER_SUPPLY_PROP_CAPACITY:
+ if (pchg->pdata->get_batt_capacity)
+ val->intval = pchg->pdata->get_batt_capacity();
+ break;
+ case POWER_SUPPLY_PROP_TEMP:
+ if (pchg->pdata->get_batt_temp)
+ val->intval = pchg->pdata->get_batt_temp();
+ break;
+ default:
+ break;
+ }
+
+ return 0;
+}
+
+static void lp8727_charger_changed(struct power_supply *psy)
+{
+ struct lp8727_chg *pchg = dev_get_drvdata(psy->dev->parent);
+ u8 val;
+ u8 eoc_level, ichg;
+
+ if (lp8727_is_charger_attached(psy->name, pchg->devid)) {
+ if (pchg->chg_parm) {
+ eoc_level = pchg->chg_parm->eoc_level;
+ ichg = pchg->chg_parm->ichg;
+ val = (ichg << 4) | eoc_level;
+ lp8727_i2c_write_byte(pchg, CHGCTRL2, &val);
+ }
+ }
+}
+
+static int lp8727_register_psy(struct lp8727_chg *pchg)
+{
+ struct lp8727_psy *psy;
+
+ psy = kzalloc(sizeof(*psy), GFP_KERNEL);
+ if (!psy)
+ goto err_mem;
+
+ pchg->psy = psy;
+
+ psy->ac.name = "ac";
+ psy->ac.type = POWER_SUPPLY_TYPE_MAINS;
+ psy->ac.properties = lp8727_charger_prop;
+ psy->ac.num_properties = ARRAY_SIZE(lp8727_charger_prop);
+ psy->ac.get_property = lp8727_charger_get_property;
+ psy->ac.supplied_to = battery_supplied_to;
+ psy->ac.num_supplicants = ARRAY_SIZE(battery_supplied_to);
+
+ if (power_supply_register(pchg->dev, &psy->ac))
+ goto err_psy;
+
+ psy->usb.name = "usb";
+ psy->usb.type = POWER_SUPPLY_TYPE_USB;
+ psy->usb.properties = lp8727_charger_prop;
+ psy->usb.num_properties = ARRAY_SIZE(lp8727_charger_prop);
+ psy->usb.get_property = lp8727_charger_get_property;
+ psy->usb.supplied_to = battery_supplied_to;
+ psy->usb.num_supplicants = ARRAY_SIZE(battery_supplied_to);
+
+ if (power_supply_register(pchg->dev, &psy->usb))
+ goto err_psy;
+
+ psy->batt.name = "main_batt";
+ psy->batt.type = POWER_SUPPLY_TYPE_BATTERY;
+ psy->batt.properties = lp8727_battery_prop;
+ psy->batt.num_properties = ARRAY_SIZE(lp8727_battery_prop);
+ psy->batt.get_property = lp8727_battery_get_property;
+ psy->batt.external_power_changed = lp8727_charger_changed;
+
+ if (power_supply_register(pchg->dev, &psy->batt))
+ goto err_psy;
+
+ return 0;
+
+err_mem:
+ return -ENOMEM;
+err_psy:
+ kfree(psy);
+ return -EPERM;
+}
+
+static void lp8727_unregister_psy(struct lp8727_chg *pchg)
+{
+ struct lp8727_psy *psy = pchg->psy;
+
+ if (!psy)
+ return;
+
+ power_supply_unregister(&psy->ac);
+ power_supply_unregister(&psy->usb);
+ power_supply_unregister(&psy->batt);
+ kfree(psy);
+}
+
+static int lp8727_probe(struct i2c_client *cl, const struct i2c_device_id *id)
+{
+ struct lp8727_chg *pchg;
+ int ret;
+
+ if (!i2c_check_functionality(cl->adapter, I2C_FUNC_SMBUS_I2C_BLOCK))
+ return -EIO;
+
+ pchg = kzalloc(sizeof(*pchg), GFP_KERNEL);
+ if (!pchg)
+ return -ENOMEM;
+
+ pchg->client = cl;
+ pchg->dev = &cl->dev;
+ pchg->pdata = cl->dev.platform_data;
+ i2c_set_clientdata(cl, pchg);
+
+ mutex_init(&pchg->xfer_lock);
+
+ lp8727_init_device(pchg);
+ lp8727_intr_config(pchg);
+
+ ret = lp8727_register_psy(pchg);
+ if (ret)
+ dev_err(pchg->dev,
+ "can not register power supplies. err=%d", ret);
+
+ return 0;
+}
+
+static int __devexit lp8727_remove(struct i2c_client *cl)
+{
+ struct lp8727_chg *pchg = i2c_get_clientdata(cl);
+
+ lp8727_unregister_psy(pchg);
+ free_irq(pchg->client->irq, pchg);
+ flush_workqueue(pchg->irqthread);
+ destroy_workqueue(pchg->irqthread);
+ kfree(pchg);
+ return 0;
+}
+
+static const struct i2c_device_id lp8727_ids[] = {
+ {"lp8727", 0},
+};
+
+static struct i2c_driver lp8727_driver = {
+ .driver = {
+ .name = "lp8727",
+ },
+ .probe = lp8727_probe,
+ .remove = __devexit_p(lp8727_remove),
+ .id_table = lp8727_ids,
+};
+
+static int __init lp8727_init(void)
+{
+ return i2c_add_driver(&lp8727_driver);
+}
+
+static void __exit lp8727_exit(void)
+{
+ i2c_del_driver(&lp8727_driver);
+}
+
+module_init(lp8727_init);
+module_exit(lp8727_exit);
+
+MODULE_DESCRIPTION("National Semiconductor LP8727 charger driver");
+MODULE_AUTHOR
+ ("Woogyom Kim <milo.kim@ti.com>, Daniel Jeong <daniel.jeong@ti.com>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/power/max17042_battery.c b/drivers/power/max17042_battery.c
index 9f0183c73076..86acee2f9889 100644
--- a/drivers/power/max17042_battery.c
+++ b/drivers/power/max17042_battery.c
@@ -85,55 +85,79 @@ static int max17042_get_property(struct power_supply *psy,
{
struct max17042_chip *chip = container_of(psy,
struct max17042_chip, battery);
+ int ret;
switch (psp) {
case POWER_SUPPLY_PROP_PRESENT:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_STATUS);
- if (val->intval & MAX17042_STATUS_BattAbsent)
+ ret = max17042_read_reg(chip->client, MAX17042_STATUS);
+ if (ret < 0)
+ return ret;
+
+ if (ret & MAX17042_STATUS_BattAbsent)
val->intval = 0;
else
val->intval = 1;
break;
case POWER_SUPPLY_PROP_CYCLE_COUNT:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_Cycles);
+ ret = max17042_read_reg(chip->client, MAX17042_Cycles);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
break;
case POWER_SUPPLY_PROP_VOLTAGE_MAX:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_MinMaxVolt);
- val->intval >>= 8;
+ ret = max17042_read_reg(chip->client, MAX17042_MinMaxVolt);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret >> 8;
val->intval *= 20000; /* Units of LSB = 20mV */
break;
case POWER_SUPPLY_PROP_VOLTAGE_MIN_DESIGN:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_V_empty);
- val->intval >>= 7;
+ ret = max17042_read_reg(chip->client, MAX17042_V_empty);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret >> 7;
val->intval *= 10000; /* Units of LSB = 10mV */
break;
case POWER_SUPPLY_PROP_VOLTAGE_NOW:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_VCELL) * 83; /* 1000 / 12 = 83 */
+ ret = max17042_read_reg(chip->client, MAX17042_VCELL);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret * 625 / 8;
break;
case POWER_SUPPLY_PROP_VOLTAGE_AVG:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_AvgVCELL) * 83;
+ ret = max17042_read_reg(chip->client, MAX17042_AvgVCELL);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret * 625 / 8;
break;
case POWER_SUPPLY_PROP_CAPACITY:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_SOC) / 256;
+ ret = max17042_read_reg(chip->client, MAX17042_SOC);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret >> 8;
break;
case POWER_SUPPLY_PROP_CHARGE_FULL:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_RepSOC);
- if ((val->intval / 256) >= MAX17042_BATTERY_FULL)
+ ret = max17042_read_reg(chip->client, MAX17042_RepSOC);
+ if (ret < 0)
+ return ret;
+
+ if ((ret >> 8) >= MAX17042_BATTERY_FULL)
val->intval = 1;
- else if (val->intval >= 0)
+ else if (ret >= 0)
val->intval = 0;
break;
case POWER_SUPPLY_PROP_TEMP:
- val->intval = max17042_read_reg(chip->client,
- MAX17042_TEMP);
+ ret = max17042_read_reg(chip->client, MAX17042_TEMP);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
/* The value is signed. */
if (val->intval & 0x8000) {
val->intval = (0x7fff & ~val->intval) + 1;
@@ -145,24 +169,30 @@ static int max17042_get_property(struct power_supply *psy,
break;
case POWER_SUPPLY_PROP_CURRENT_NOW:
if (chip->pdata->enable_current_sense) {
- val->intval = max17042_read_reg(chip->client,
- MAX17042_Current);
+ ret = max17042_read_reg(chip->client, MAX17042_Current);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
if (val->intval & 0x8000) {
/* Negative */
val->intval = ~val->intval & 0x7fff;
val->intval++;
val->intval *= -1;
}
- val->intval >>= 4;
- val->intval *= 1000000 * 25 / chip->pdata->r_sns;
+ val->intval *= 1562500 / chip->pdata->r_sns;
} else {
return -EINVAL;
}
break;
case POWER_SUPPLY_PROP_CURRENT_AVG:
if (chip->pdata->enable_current_sense) {
- val->intval = max17042_read_reg(chip->client,
- MAX17042_AvgCurrent);
+ ret = max17042_read_reg(chip->client,
+ MAX17042_AvgCurrent);
+ if (ret < 0)
+ return ret;
+
+ val->intval = ret;
if (val->intval & 0x8000) {
/* Negative */
val->intval = ~val->intval & 0x7fff;
@@ -210,6 +240,9 @@ static int __devinit max17042_probe(struct i2c_client *client,
if (!chip->pdata->enable_current_sense)
chip->battery.num_properties -= 2;
+ if (chip->pdata->r_sns == 0)
+ chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
+
ret = power_supply_register(&client->dev, &chip->battery);
if (ret) {
dev_err(&client->dev, "failed: power supply register\n");
@@ -226,9 +259,6 @@ static int __devinit max17042_probe(struct i2c_client *client,
max17042_write_reg(client, MAX17042_CGAIN, 0x0000);
max17042_write_reg(client, MAX17042_MiscCFG, 0x0003);
max17042_write_reg(client, MAX17042_LearnCFG, 0x0007);
- } else {
- if (chip->pdata->r_sns == 0)
- chip->pdata->r_sns = MAX17042_DEFAULT_SNS_RESISTOR;
}
return 0;
diff --git a/drivers/power/max8903_charger.c b/drivers/power/max8903_charger.c
index 2595145f3bff..3e23f43e98af 100644
--- a/drivers/power/max8903_charger.c
+++ b/drivers/power/max8903_charger.c
@@ -374,19 +374,9 @@ static struct platform_driver max8903_driver = {
},
};
-static int __init max8903_init(void)
-{
- return platform_driver_register(&max8903_driver);
-}
-module_init(max8903_init);
-
-static void __exit max8903_exit(void)
-{
- platform_driver_unregister(&max8903_driver);
-}
-module_exit(max8903_exit);
+module_platform_driver(max8903_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("MAX8903 Charger Driver");
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
-MODULE_ALIAS("max8903-charger");
+MODULE_ALIAS("platform:max8903-charger");
diff --git a/drivers/power/max8925_power.c b/drivers/power/max8925_power.c
index a70e16d3a3dc..daa333bd7ebb 100644
--- a/drivers/power/max8925_power.c
+++ b/drivers/power/max8925_power.c
@@ -78,6 +78,8 @@ struct max8925_power_info {
unsigned batt_detect:1; /* detecing MB by ID pin */
unsigned topoff_threshold:2;
unsigned fast_charge:3;
+ unsigned no_temp_support:1;
+ unsigned no_insert_detect:1;
int (*set_charger) (int);
};
@@ -116,17 +118,7 @@ static irqreturn_t max8925_charger_handler(int irq, void *data)
case MAX8925_IRQ_VCHG_DC_F:
info->ac_online = 0;
__set_charger(info, 0);
- dev_dbg(chip->dev, "Adapter is removal\n");
- break;
- case MAX8925_IRQ_VCHG_USB_R:
- info->usb_online = 1;
- __set_charger(info, 1);
- dev_dbg(chip->dev, "USB inserted\n");
- break;
- case MAX8925_IRQ_VCHG_USB_F:
- info->usb_online = 0;
- __set_charger(info, 0);
- dev_dbg(chip->dev, "USB is removal\n");
+ dev_dbg(chip->dev, "Adapter removed\n");
break;
case MAX8925_IRQ_VCHG_THM_OK_F:
/* Battery is not ready yet */
@@ -168,27 +160,33 @@ static irqreturn_t max8925_charger_handler(int irq, void *data)
static int start_measure(struct max8925_power_info *info, int type)
{
unsigned char buf[2] = {0, 0};
+ int meas_cmd;
int meas_reg = 0, ret;
switch (type) {
case MEASURE_VCHG:
+ meas_cmd = MAX8925_CMD_VCHG;
meas_reg = MAX8925_ADC_VCHG;
break;
case MEASURE_VBBATT:
+ meas_cmd = MAX8925_CMD_VBBATT;
meas_reg = MAX8925_ADC_VBBATT;
break;
case MEASURE_VMBATT:
+ meas_cmd = MAX8925_CMD_VMBATT;
meas_reg = MAX8925_ADC_VMBATT;
break;
case MEASURE_ISNS:
+ meas_cmd = MAX8925_CMD_ISNS;
meas_reg = MAX8925_ADC_ISNS;
break;
default:
return -EINVAL;
}
+ max8925_reg_write(info->adc, meas_cmd, 0);
max8925_bulk_read(info->adc, meas_reg, 2, buf);
- ret = (buf[0] << 4) | (buf[1] >> 4);
+ ret = ((buf[0]<<8) | buf[1]) >> 4;
return ret;
}
@@ -208,7 +206,7 @@ static int max8925_ac_get_prop(struct power_supply *psy,
if (info->ac_online) {
ret = start_measure(info, MEASURE_VCHG);
if (ret >= 0) {
- val->intval = ret << 1; /* unit is mV */
+ val->intval = ret * 2000; /* unit is uV */
goto out;
}
}
@@ -242,7 +240,7 @@ static int max8925_usb_get_prop(struct power_supply *psy,
if (info->usb_online) {
ret = start_measure(info, MEASURE_VCHG);
if (ret >= 0) {
- val->intval = ret << 1; /* unit is mV */
+ val->intval = ret * 2000; /* unit is uV */
goto out;
}
}
@@ -266,7 +264,6 @@ static int max8925_bat_get_prop(struct power_supply *psy,
union power_supply_propval *val)
{
struct max8925_power_info *info = dev_get_drvdata(psy->dev->parent);
- long long int tmp = 0;
int ret = 0;
switch (psp) {
@@ -277,7 +274,7 @@ static int max8925_bat_get_prop(struct power_supply *psy,
if (info->bat_online) {
ret = start_measure(info, MEASURE_VMBATT);
if (ret >= 0) {
- val->intval = ret << 1; /* unit is mV */
+ val->intval = ret * 2000; /* unit is uV */
ret = 0;
break;
}
@@ -288,8 +285,8 @@ static int max8925_bat_get_prop(struct power_supply *psy,
if (info->bat_online) {
ret = start_measure(info, MEASURE_ISNS);
if (ret >= 0) {
- tmp = (long long int)ret * 6250 / 4096 - 3125;
- ret = (int)tmp;
+ /* assume r_sns is 0.02 */
+ ret = ((ret * 6250) - 3125) /* uA */;
val->intval = 0;
if (ret > 0)
val->intval = ret; /* unit is mA */
@@ -365,13 +362,14 @@ static __devinit int max8925_init_charger(struct max8925_chip *chip,
int ret;
REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_OVP, "ac-ovp");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_OVP, "usb-ovp");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_F, "usb-remove");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_USB_R, "usb-insert");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range");
- REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
+ if (!info->no_insert_detect) {
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_F, "ac-remove");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_DC_R, "ac-insert");
+ }
+ if (!info->no_temp_support) {
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_R, "batt-temp-in-range");
+ REQUEST_IRQ(MAX8925_IRQ_VCHG_THM_OK_F, "batt-temp-out-range");
+ }
REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_F, "vsys-high");
REQUEST_IRQ(MAX8925_IRQ_VCHG_SYSLOW_R, "vsys-low");
REQUEST_IRQ(MAX8925_IRQ_VCHG_RST, "charger-reset");
@@ -379,9 +377,15 @@ static __devinit int max8925_init_charger(struct max8925_chip *chip,
REQUEST_IRQ(MAX8925_IRQ_VCHG_TOPOFF, "charger-topoff");
REQUEST_IRQ(MAX8925_IRQ_VCHG_TMR_FAULT, "charger-timer-expire");
- info->ac_online = 0;
info->usb_online = 0;
info->bat_online = 0;
+
+ /* check for power - can miss interrupt at boot time */
+ if (start_measure(info, MEASURE_VCHG) * 2000 > 500000)
+ info->ac_online = 1;
+ else
+ info->ac_online = 0;
+
ret = max8925_reg_read(info->gpm, MAX8925_CHG_STATUS);
if (ret >= 0) {
/*
@@ -449,6 +453,8 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
info->ac.properties = max8925_ac_props;
info->ac.num_properties = ARRAY_SIZE(max8925_ac_props);
info->ac.get_property = max8925_ac_get_prop;
+ info->ac.supplied_to = pdata->supplied_to;
+ info->ac.num_supplicants = pdata->num_supplicants;
ret = power_supply_register(&pdev->dev, &info->ac);
if (ret)
goto out;
@@ -459,6 +465,9 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
info->usb.properties = max8925_usb_props;
info->usb.num_properties = ARRAY_SIZE(max8925_usb_props);
info->usb.get_property = max8925_usb_get_prop;
+ info->usb.supplied_to = pdata->supplied_to;
+ info->usb.num_supplicants = pdata->num_supplicants;
+
ret = power_supply_register(&pdev->dev, &info->usb);
if (ret)
goto out_usb;
@@ -478,6 +487,8 @@ static __devinit int max8925_power_probe(struct platform_device *pdev)
info->topoff_threshold = pdata->topoff_threshold;
info->fast_charge = pdata->fast_charge;
info->set_charger = pdata->set_charger;
+ info->no_temp_support = pdata->no_temp_support;
+ info->no_insert_detect = pdata->no_insert_detect;
max8925_init_charger(chip, info);
return 0;
@@ -512,17 +523,7 @@ static struct platform_driver max8925_power_driver = {
},
};
-static int __init max8925_power_init(void)
-{
- return platform_driver_register(&max8925_power_driver);
-}
-module_init(max8925_power_init);
-
-static void __exit max8925_power_exit(void)
-{
- platform_driver_unregister(&max8925_power_driver);
-}
-module_exit(max8925_power_exit);
+module_platform_driver(max8925_power_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Power supply driver for MAX8925");
diff --git a/drivers/power/max8997_charger.c b/drivers/power/max8997_charger.c
index a23317d75c5a..6e88c5d026b9 100644
--- a/drivers/power/max8997_charger.c
+++ b/drivers/power/max8997_charger.c
@@ -19,7 +19,6 @@
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <linux/module.h>
#include <linux/err.h>
#include <linux/module.h>
#include <linux/slab.h>
@@ -98,7 +97,7 @@ static __devinit int max8997_battery_probe(struct platform_device *pdev)
return -EINVAL;
if (pdata->eoc_mA) {
- u8 val = (pdata->eoc_mA - 50) / 10;
+ int val = (pdata->eoc_mA - 50) / 10;
if (val < 0)
val = 0;
if (val > 0xf)
@@ -179,6 +178,7 @@ static int __devexit max8997_battery_remove(struct platform_device *pdev)
static const struct platform_device_id max8997_battery_id[] = {
{ "max8997-battery", 0 },
+ { }
};
static struct platform_driver max8997_battery_driver = {
diff --git a/drivers/power/max8998_charger.c b/drivers/power/max8998_charger.c
index 93e3bb47a3a8..9b3f2bf56e70 100644
--- a/drivers/power/max8998_charger.c
+++ b/drivers/power/max8998_charger.c
@@ -154,6 +154,7 @@ static __devinit int max8998_battery_probe(struct platform_device *pdev)
case 0:
dev_dbg(max8998->dev,
"Full Timeout not set: leave it unchanged.\n");
+ break;
default:
dev_err(max8998->dev, "Invalid Full Timeout value\n");
ret = -EINVAL;
@@ -190,6 +191,7 @@ static int __devexit max8998_battery_remove(struct platform_device *pdev)
static const struct platform_device_id max8998_battery_id[] = {
{ "max8998-battery", TYPE_MAX8998 },
+ { }
};
static struct platform_driver max8998_battery_driver = {
@@ -202,17 +204,7 @@ static struct platform_driver max8998_battery_driver = {
.id_table = max8998_battery_id,
};
-static int __init max8998_battery_init(void)
-{
- return platform_driver_register(&max8998_battery_driver);
-}
-module_init(max8998_battery_init);
-
-static void __exit max8998_battery_cleanup(void)
-{
- platform_driver_unregister(&max8998_battery_driver);
-}
-module_exit(max8998_battery_cleanup);
+module_platform_driver(max8998_battery_driver);
MODULE_DESCRIPTION("MAXIM 8998 battery control driver");
MODULE_AUTHOR("MyungJoo Ham <myungjoo.ham@samsung.com>");
diff --git a/drivers/power/olpc_battery.c b/drivers/power/olpc_battery.c
index 0b0ff3a936a6..7385092f9bc8 100644
--- a/drivers/power/olpc_battery.c
+++ b/drivers/power/olpc_battery.c
@@ -519,29 +519,35 @@ static struct device_attribute olpc_bat_error = {
* Initialisation
*********************************************************************/
-static struct platform_device *bat_pdev;
-
static struct power_supply olpc_bat = {
+ .name = "olpc-battery",
.get_property = olpc_bat_get_property,
.use_for_apm = 1,
};
-void olpc_battery_trigger_uevent(unsigned long cause)
+static int olpc_battery_suspend(struct platform_device *pdev,
+ pm_message_t state)
{
- if (cause & EC_SCI_SRC_ACPWR)
- kobject_uevent(&olpc_ac.dev->kobj, KOBJ_CHANGE);
- if (cause & (EC_SCI_SRC_BATERR|EC_SCI_SRC_BATSOC|EC_SCI_SRC_BATTERY))
- kobject_uevent(&olpc_bat.dev->kobj, KOBJ_CHANGE);
+ if (device_may_wakeup(olpc_ac.dev))
+ olpc_ec_wakeup_set(EC_SCI_SRC_ACPWR);
+ else
+ olpc_ec_wakeup_clear(EC_SCI_SRC_ACPWR);
+
+ if (device_may_wakeup(olpc_bat.dev))
+ olpc_ec_wakeup_set(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC
+ | EC_SCI_SRC_BATERR);
+ else
+ olpc_ec_wakeup_clear(EC_SCI_SRC_BATTERY | EC_SCI_SRC_BATSOC
+ | EC_SCI_SRC_BATERR);
+
+ return 0;
}
-static int __init olpc_bat_init(void)
+static int __devinit olpc_battery_probe(struct platform_device *pdev)
{
- int ret = 0;
+ int ret;
uint8_t status;
- if (!olpc_platform_info.ecver)
- return -ENXIO;
-
/*
* We've seen a number of EC protocol changes; this driver requires
* the latest EC protocol, supported by 0x44 and above.
@@ -558,15 +564,10 @@ static int __init olpc_bat_init(void)
/* Ignore the status. It doesn't actually matter */
- bat_pdev = platform_device_register_simple("olpc-battery", 0, NULL, 0);
- if (IS_ERR(bat_pdev))
- return PTR_ERR(bat_pdev);
-
- ret = power_supply_register(&bat_pdev->dev, &olpc_ac);
+ ret = power_supply_register(&pdev->dev, &olpc_ac);
if (ret)
- goto ac_failed;
+ return ret;
- olpc_bat.name = bat_pdev->name;
if (olpc_board_at_least(olpc_board_pre(0xd0))) { /* XO-1.5 */
olpc_bat.properties = olpc_xo15_bat_props;
olpc_bat.num_properties = ARRAY_SIZE(olpc_xo15_bat_props);
@@ -575,7 +576,7 @@ static int __init olpc_bat_init(void)
olpc_bat.num_properties = ARRAY_SIZE(olpc_xo1_bat_props);
}
- ret = power_supply_register(&bat_pdev->dev, &olpc_bat);
+ ret = power_supply_register(&pdev->dev, &olpc_bat);
if (ret)
goto battery_failed;
@@ -587,7 +588,12 @@ static int __init olpc_bat_init(void)
if (ret)
goto error_failed;
- goto success;
+ if (olpc_ec_wakeup_available()) {
+ device_set_wakeup_capable(olpc_ac.dev, true);
+ device_set_wakeup_capable(olpc_bat.dev, true);
+ }
+
+ return 0;
error_failed:
device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
@@ -595,23 +601,36 @@ eeprom_failed:
power_supply_unregister(&olpc_bat);
battery_failed:
power_supply_unregister(&olpc_ac);
-ac_failed:
- platform_device_unregister(bat_pdev);
-success:
return ret;
}
-static void __exit olpc_bat_exit(void)
+static int __devexit olpc_battery_remove(struct platform_device *pdev)
{
device_remove_file(olpc_bat.dev, &olpc_bat_error);
device_remove_bin_file(olpc_bat.dev, &olpc_bat_eeprom);
power_supply_unregister(&olpc_bat);
power_supply_unregister(&olpc_ac);
- platform_device_unregister(bat_pdev);
+ return 0;
}
-module_init(olpc_bat_init);
-module_exit(olpc_bat_exit);
+static const struct of_device_id olpc_battery_ids[] __devinitconst = {
+ { .compatible = "olpc,xo1-battery" },
+ {}
+};
+MODULE_DEVICE_TABLE(of, olpc_battery_ids);
+
+static struct platform_driver olpc_battery_driver = {
+ .driver = {
+ .name = "olpc-battery",
+ .owner = THIS_MODULE,
+ .of_match_table = olpc_battery_ids,
+ },
+ .probe = olpc_battery_probe,
+ .remove = __devexit_p(olpc_battery_remove),
+ .suspend = olpc_battery_suspend,
+};
+
+module_platform_driver(olpc_battery_driver);
MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>");
MODULE_LICENSE("GPL");
diff --git a/drivers/power/pcf50633-charger.c b/drivers/power/pcf50633-charger.c
index 4fa52e1781a2..3d1e9efb6f53 100644
--- a/drivers/power/pcf50633-charger.c
+++ b/drivers/power/pcf50633-charger.c
@@ -474,17 +474,7 @@ static struct platform_driver pcf50633_mbc_driver = {
.remove = __devexit_p(pcf50633_mbc_remove),
};
-static int __init pcf50633_mbc_init(void)
-{
- return platform_driver_register(&pcf50633_mbc_driver);
-}
-module_init(pcf50633_mbc_init);
-
-static void __exit pcf50633_mbc_exit(void)
-{
- platform_driver_unregister(&pcf50633_mbc_driver);
-}
-module_exit(pcf50633_mbc_exit);
+module_platform_driver(pcf50633_mbc_driver);
MODULE_AUTHOR("Balaji Rao <balajirrao@openmoko.org>");
MODULE_DESCRIPTION("PCF50633 mbc driver");
diff --git a/drivers/power/pda_power.c b/drivers/power/pda_power.c
index 69f8aa3a6a4b..fd49689738af 100644
--- a/drivers/power/pda_power.c
+++ b/drivers/power/pda_power.c
@@ -14,6 +14,7 @@
#include <linux/platform_device.h>
#include <linux/err.h>
#include <linux/interrupt.h>
+#include <linux/notifier.h>
#include <linux/power_supply.h>
#include <linux/pda_power.h>
#include <linux/regulator/consumer.h>
@@ -40,7 +41,9 @@ static int polling;
#ifdef CONFIG_USB_OTG_UTILS
static struct otg_transceiver *transceiver;
+static struct notifier_block otg_nb;
#endif
+
static struct regulator *ac_draw;
enum {
@@ -222,7 +225,42 @@ static void polling_timer_func(unsigned long unused)
#ifdef CONFIG_USB_OTG_UTILS
static int otg_is_usb_online(void)
{
- return (transceiver->state == OTG_STATE_B_PERIPHERAL);
+ return (transceiver->last_event == USB_EVENT_VBUS ||
+ transceiver->last_event == USB_EVENT_ENUMERATED);
+}
+
+static int otg_is_ac_online(void)
+{
+ return (transceiver->last_event == USB_EVENT_CHARGER);
+}
+
+static int otg_handle_notification(struct notifier_block *nb,
+ unsigned long event, void *unused)
+{
+ switch (event) {
+ case USB_EVENT_CHARGER:
+ ac_status = PDA_PSY_TO_CHANGE;
+ break;
+ case USB_EVENT_VBUS:
+ case USB_EVENT_ENUMERATED:
+ usb_status = PDA_PSY_TO_CHANGE;
+ break;
+ case USB_EVENT_NONE:
+ ac_status = PDA_PSY_TO_CHANGE;
+ usb_status = PDA_PSY_TO_CHANGE;
+ break;
+ default:
+ return NOTIFY_OK;
+ }
+
+ /*
+ * Wait a bit before reading ac/usb line status and setting charger,
+ * because ac/usb status readings may lag from irq.
+ */
+ mod_timer(&charger_timer,
+ jiffies + msecs_to_jiffies(pdata->wait_for_status));
+
+ return NOTIFY_OK;
}
#endif
@@ -282,6 +320,16 @@ static int pda_power_probe(struct platform_device *pdev)
ret = PTR_ERR(ac_draw);
}
+#ifdef CONFIG_USB_OTG_UTILS
+ transceiver = otg_get_transceiver();
+ if (transceiver && !pdata->is_usb_online) {
+ pdata->is_usb_online = otg_is_usb_online;
+ }
+ if (transceiver && !pdata->is_ac_online) {
+ pdata->is_ac_online = otg_is_ac_online;
+ }
+#endif
+
if (pdata->is_ac_online) {
ret = power_supply_register(&pdev->dev, &pda_psy_ac);
if (ret) {
@@ -303,13 +351,6 @@ static int pda_power_probe(struct platform_device *pdev)
}
}
-#ifdef CONFIG_USB_OTG_UTILS
- transceiver = otg_get_transceiver();
- if (transceiver && !pdata->is_usb_online) {
- pdata->is_usb_online = otg_is_usb_online;
- }
-#endif
-
if (pdata->is_usb_online) {
ret = power_supply_register(&pdev->dev, &pda_psy_usb);
if (ret) {
@@ -331,6 +372,18 @@ static int pda_power_probe(struct platform_device *pdev)
}
}
+#ifdef CONFIG_USB_OTG_UTILS
+ if (transceiver && pdata->use_otg_notifier) {
+ otg_nb.notifier_call = otg_handle_notification;
+ ret = otg_register_notifier(transceiver, &otg_nb);
+ if (ret) {
+ dev_err(dev, "failure to register otg notifier\n");
+ goto otg_reg_notifier_failed;
+ }
+ polling = 0;
+ }
+#endif
+
if (polling) {
dev_dbg(dev, "will poll for status\n");
setup_timer(&polling_timer, polling_timer_func, 0);
@@ -343,6 +396,11 @@ static int pda_power_probe(struct platform_device *pdev)
return 0;
+#ifdef CONFIG_USB_OTG_UTILS
+otg_reg_notifier_failed:
+ if (pdata->is_usb_online && usb_irq)
+ free_irq(usb_irq->start, &pda_psy_usb);
+#endif
usb_irq_failed:
if (pdata->is_usb_online)
power_supply_unregister(&pda_psy_usb);
@@ -440,8 +498,6 @@ static int pda_power_resume(struct platform_device *pdev)
#define pda_power_resume NULL
#endif /* CONFIG_PM */
-MODULE_ALIAS("platform:pda-power");
-
static struct platform_driver pda_power_pdrv = {
.driver = {
.name = "pda-power",
@@ -452,17 +508,8 @@ static struct platform_driver pda_power_pdrv = {
.resume = pda_power_resume,
};
-static int __init pda_power_init(void)
-{
- return platform_driver_register(&pda_power_pdrv);
-}
+module_platform_driver(pda_power_pdrv);
-static void __exit pda_power_exit(void)
-{
- platform_driver_unregister(&pda_power_pdrv);
-}
-
-module_init(pda_power_init);
-module_exit(pda_power_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Anton Vorontsov <cbou@mail.ru>");
+MODULE_ALIAS("platform:pda-power");
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 329b46b2327d..6ad612726785 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -98,7 +98,9 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
{
union power_supply_propval ret = {0,};
struct power_supply *psy = dev_get_drvdata(dev);
+ unsigned int *count = data;
+ (*count)++;
if (psy->type != POWER_SUPPLY_TYPE_BATTERY) {
if (psy->get_property(psy, POWER_SUPPLY_PROP_ONLINE, &ret))
return 0;
@@ -111,10 +113,18 @@ static int __power_supply_is_system_supplied(struct device *dev, void *data)
int power_supply_is_system_supplied(void)
{
int error;
+ unsigned int count = 0;
- error = class_for_each_device(power_supply_class, NULL, NULL,
+ error = class_for_each_device(power_supply_class, NULL, &count,
__power_supply_is_system_supplied);
+ /*
+ * If no power class device was found at all, most probably we are
+ * running on a desktop system, so assume we are on mains power.
+ */
+ if (count == 0)
+ return 1;
+
return error;
}
EXPORT_SYMBOL_GPL(power_supply_is_system_supplied);
@@ -147,6 +157,12 @@ struct power_supply *power_supply_get_by_name(char *name)
}
EXPORT_SYMBOL_GPL(power_supply_get_by_name);
+int power_supply_powers(struct power_supply *psy, struct device *dev)
+{
+ return sysfs_create_link(&psy->dev->kobj, &dev->kobj, "powers");
+}
+EXPORT_SYMBOL_GPL(power_supply_powers);
+
static void power_supply_dev_release(struct device *dev)
{
pr_debug("device: '%s': %s\n", dev_name(dev), __func__);
@@ -202,6 +218,7 @@ EXPORT_SYMBOL_GPL(power_supply_register);
void power_supply_unregister(struct power_supply *psy)
{
cancel_work_sync(&psy->changed_work);
+ sysfs_remove_link(&psy->dev->kobj, "powers");
power_supply_remove_triggers(psy);
device_unregister(psy->dev);
}
diff --git a/drivers/power/power_supply_sysfs.c b/drivers/power/power_supply_sysfs.c
index e95cd657dac2..b52b57ca3084 100644
--- a/drivers/power/power_supply_sysfs.c
+++ b/drivers/power/power_supply_sysfs.c
@@ -43,7 +43,7 @@ static ssize_t power_supply_show_property(struct device *dev,
struct device_attribute *attr,
char *buf) {
static char *type_text[] = {
- "Battery", "UPS", "Mains", "USB",
+ "Unknown", "Battery", "UPS", "Mains", "USB",
"USB_DCP", "USB_CDP", "USB_ACA"
};
static char *status_text[] = {
@@ -63,6 +63,9 @@ static ssize_t power_supply_show_property(struct device *dev,
static char *capacity_level_text[] = {
"Unknown", "Critical", "Low", "Normal", "High", "Full"
};
+ static char *scope_text[] = {
+ "Unknown", "System", "Device"
+ };
ssize_t ret = 0;
struct power_supply *psy = dev_get_drvdata(dev);
const ptrdiff_t off = attr - power_supply_attrs;
@@ -78,8 +81,8 @@ static ssize_t power_supply_show_property(struct device *dev,
dev_dbg(dev, "driver has no data for `%s' property\n",
attr->attr.name);
else if (ret != -ENODEV)
- dev_err(dev, "driver failed to report `%s' property\n",
- attr->attr.name);
+ dev_err(dev, "driver failed to report `%s' property: %zd\n",
+ attr->attr.name, ret);
return ret;
}
@@ -95,6 +98,8 @@ static ssize_t power_supply_show_property(struct device *dev,
return sprintf(buf, "%s\n", capacity_level_text[value.intval]);
else if (off == POWER_SUPPLY_PROP_TYPE)
return sprintf(buf, "%s\n", type_text[value.intval]);
+ else if (off == POWER_SUPPLY_PROP_SCOPE)
+ return sprintf(buf, "%s\n", scope_text[value.intval]);
else if (off >= POWER_SUPPLY_PROP_MODEL_NAME)
return sprintf(buf, "%s\n", value.strval);
@@ -167,6 +172,7 @@ static struct device_attribute power_supply_attrs[] = {
POWER_SUPPLY_ATTR(time_to_full_now),
POWER_SUPPLY_ATTR(time_to_full_avg),
POWER_SUPPLY_ATTR(type),
+ POWER_SUPPLY_ATTR(scope),
/* Properties of type `const char *' */
POWER_SUPPLY_ATTR(model_name),
POWER_SUPPLY_ATTR(manufacturer),
diff --git a/drivers/power/s3c_adc_battery.c b/drivers/power/s3c_adc_battery.c
index d32d0d70f9ba..8b804a566756 100644
--- a/drivers/power/s3c_adc_battery.c
+++ b/drivers/power/s3c_adc_battery.c
@@ -47,6 +47,22 @@ static void s3c_adc_bat_ext_power_changed(struct power_supply *psy)
msecs_to_jiffies(JITTER_DELAY));
}
+static int gather_samples(struct s3c_adc_client *client, int num, int channel)
+{
+ int value, i;
+
+ /* default to 1 if nothing is set */
+ if (num < 1)
+ num = 1;
+
+ value = 0;
+ for (i = 0; i < num; i++)
+ value += s3c_adc_read(client, channel);
+ value /= num;
+
+ return value;
+}
+
static enum power_supply_property s3c_adc_backup_bat_props[] = {
POWER_SUPPLY_PROP_VOLTAGE_NOW,
POWER_SUPPLY_PROP_VOLTAGE_MIN,
@@ -67,7 +83,8 @@ static int s3c_adc_backup_bat_get_property(struct power_supply *psy,
if (bat->volt_value < 0 ||
jiffies_to_msecs(jiffies - bat->timestamp) >
BAT_POLL_INTERVAL) {
- bat->volt_value = s3c_adc_read(bat->client,
+ bat->volt_value = gather_samples(bat->client,
+ bat->pdata->backup_volt_samples,
bat->pdata->backup_volt_channel);
bat->volt_value *= bat->pdata->backup_volt_mult;
bat->timestamp = jiffies;
@@ -139,9 +156,11 @@ static int s3c_adc_bat_get_property(struct power_supply *psy,
if (bat->volt_value < 0 || bat->cur_value < 0 ||
jiffies_to_msecs(jiffies - bat->timestamp) >
BAT_POLL_INTERVAL) {
- bat->volt_value = s3c_adc_read(bat->client,
+ bat->volt_value = gather_samples(bat->client,
+ bat->pdata->volt_samples,
bat->pdata->volt_channel) * bat->pdata->volt_mult;
- bat->cur_value = s3c_adc_read(bat->client,
+ bat->cur_value = gather_samples(bat->client,
+ bat->pdata->current_samples,
bat->pdata->current_channel) * bat->pdata->current_mult;
bat->timestamp = jiffies;
}
@@ -421,17 +440,7 @@ static struct platform_driver s3c_adc_bat_driver = {
.resume = s3c_adc_bat_resume,
};
-static int __init s3c_adc_bat_init(void)
-{
- return platform_driver_register(&s3c_adc_bat_driver);
-}
-module_init(s3c_adc_bat_init);
-
-static void __exit s3c_adc_bat_exit(void)
-{
- platform_driver_unregister(&s3c_adc_bat_driver);
-}
-module_exit(s3c_adc_bat_exit);
+module_platform_driver(s3c_adc_bat_driver);
MODULE_AUTHOR("Vasily Khoruzhick <anarsoul@gmail.com>");
MODULE_DESCRIPTION("iPAQ H1930/H1940/RX1950 battery controller driver");
diff --git a/drivers/power/bq20z75.c b/drivers/power/sbs-battery.c
index 9c5e5beda3a8..9ff8af069da6 100644
--- a/drivers/power/bq20z75.c
+++ b/drivers/power/sbs-battery.c
@@ -1,5 +1,5 @@
/*
- * Gas Gauge driver for TI's BQ20Z75
+ * Gas Gauge driver for SBS Compliant Batteries
*
* Copyright (c) 2010, NVIDIA Corporation.
*
@@ -28,7 +28,7 @@
#include <linux/interrupt.h>
#include <linux/gpio.h>
-#include <linux/power/bq20z75.h>
+#include <linux/power/sbs-battery.h>
enum {
REG_MANUFACTURER_DATA,
@@ -53,7 +53,7 @@ enum {
/* Battery Mode defines */
#define BATTERY_MODE_OFFSET 0x03
#define BATTERY_MODE_MASK 0x8000
-enum bq20z75_battery_mode {
+enum sbs_battery_mode {
BATTERY_MODE_AMPS,
BATTERY_MODE_WATTS
};
@@ -67,62 +67,56 @@ enum bq20z75_battery_mode {
#define BATTERY_FULL_CHARGED 0x20
#define BATTERY_FULL_DISCHARGED 0x10
-#define BQ20Z75_DATA(_psp, _addr, _min_value, _max_value) { \
+#define SBS_DATA(_psp, _addr, _min_value, _max_value) { \
.psp = _psp, \
.addr = _addr, \
.min_value = _min_value, \
.max_value = _max_value, \
}
-static const struct bq20z75_device_data {
+static const struct chip_data {
enum power_supply_property psp;
u8 addr;
int min_value;
int max_value;
-} bq20z75_data[] = {
+} sbs_data[] = {
[REG_MANUFACTURER_DATA] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_PRESENT, 0x00, 0, 65535),
[REG_TEMPERATURE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_TEMP, 0x08, 0, 65535),
[REG_VOLTAGE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000),
+ SBS_DATA(POWER_SUPPLY_PROP_VOLTAGE_NOW, 0x09, 0, 20000),
[REG_CURRENT] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768,
- 32767),
+ SBS_DATA(POWER_SUPPLY_PROP_CURRENT_NOW, 0x0A, -32768, 32767),
[REG_CAPACITY] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
+ SBS_DATA(POWER_SUPPLY_PROP_CAPACITY, 0x0E, 0, 100),
[REG_REMAINING_CAPACITY] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_ENERGY_NOW, 0x0F, 0, 65535),
[REG_REMAINING_CAPACITY_CHARGE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_CHARGE_NOW, 0x0F, 0, 65535),
[REG_FULL_CHARGE_CAPACITY] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_ENERGY_FULL, 0x10, 0, 65535),
[REG_FULL_CHARGE_CAPACITY_CHARGE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_CHARGE_FULL, 0x10, 0, 65535),
[REG_TIME_TO_EMPTY] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0,
- 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG, 0x12, 0, 65535),
[REG_TIME_TO_FULL] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0,
- 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_TIME_TO_FULL_AVG, 0x13, 0, 65535),
[REG_STATUS] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_STATUS, 0x16, 0, 65535),
[REG_CYCLE_COUNT] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CYCLE_COUNT, 0x17, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_CYCLE_COUNT, 0x17, 0, 65535),
[REG_DESIGN_CAPACITY] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0,
- 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN, 0x18, 0, 65535),
[REG_DESIGN_CAPACITY_CHARGE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0,
- 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN, 0x18, 0, 65535),
[REG_DESIGN_VOLTAGE] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0,
- 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN, 0x19, 0, 65535),
[REG_SERIAL_NUMBER] =
- BQ20Z75_DATA(POWER_SUPPLY_PROP_SERIAL_NUMBER, 0x1C, 0, 65535),
+ SBS_DATA(POWER_SUPPLY_PROP_SERIAL_NUMBER, 0x1C, 0, 65535),
};
-static enum power_supply_property bq20z75_properties[] = {
+static enum power_supply_property sbs_properties[] = {
POWER_SUPPLY_PROP_STATUS,
POWER_SUPPLY_PROP_HEALTH,
POWER_SUPPLY_PROP_PRESENT,
@@ -144,10 +138,10 @@ static enum power_supply_property bq20z75_properties[] = {
POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN,
};
-struct bq20z75_info {
+struct sbs_info {
struct i2c_client *client;
struct power_supply power_supply;
- struct bq20z75_platform_data *pdata;
+ struct sbs_platform_data *pdata;
bool is_present;
bool gpio_detect;
bool enable_detection;
@@ -158,14 +152,14 @@ struct bq20z75_info {
int ignore_changes;
};
-static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
+static int sbs_read_word_data(struct i2c_client *client, u8 address)
{
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret = 0;
int retries = 1;
- if (bq20z75_device->pdata)
- retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1);
+ if (chip->pdata)
+ retries = max(chip->pdata->i2c_retry_count + 1, 1);
while (retries > 0) {
ret = i2c_smbus_read_word_data(client, address);
@@ -184,15 +178,15 @@ static int bq20z75_read_word_data(struct i2c_client *client, u8 address)
return le16_to_cpu(ret);
}
-static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
+static int sbs_write_word_data(struct i2c_client *client, u8 address,
u16 value)
{
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret = 0;
int retries = 1;
- if (bq20z75_device->pdata)
- retries = max(bq20z75_device->pdata->i2c_retry_count + 1, 1);
+ if (chip->pdata)
+ retries = max(chip->pdata->i2c_retry_count + 1, 1);
while (retries > 0) {
ret = i2c_smbus_write_word_data(client, address,
@@ -212,44 +206,41 @@ static int bq20z75_write_word_data(struct i2c_client *client, u8 address,
return 0;
}
-static int bq20z75_get_battery_presence_and_health(
+static int sbs_get_battery_presence_and_health(
struct i2c_client *client, enum power_supply_property psp,
union power_supply_propval *val)
{
s32 ret;
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
if (psp == POWER_SUPPLY_PROP_PRESENT &&
- bq20z75_device->gpio_detect) {
- ret = gpio_get_value(
- bq20z75_device->pdata->battery_detect);
- if (ret == bq20z75_device->pdata->battery_detect_present)
+ chip->gpio_detect) {
+ ret = gpio_get_value(chip->pdata->battery_detect);
+ if (ret == chip->pdata->battery_detect_present)
val->intval = 1;
else
val->intval = 0;
- bq20z75_device->is_present = val->intval;
+ chip->is_present = val->intval;
return ret;
}
/* Write to ManufacturerAccess with
* ManufacturerAccess command and then
* read the status */
- ret = bq20z75_write_word_data(client,
- bq20z75_data[REG_MANUFACTURER_DATA].addr,
- MANUFACTURER_ACCESS_STATUS);
+ ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
+ MANUFACTURER_ACCESS_STATUS);
if (ret < 0) {
if (psp == POWER_SUPPLY_PROP_PRESENT)
val->intval = 0; /* battery removed */
return ret;
}
- ret = bq20z75_read_word_data(client,
- bq20z75_data[REG_MANUFACTURER_DATA].addr);
+ ret = sbs_read_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr);
if (ret < 0)
return ret;
- if (ret < bq20z75_data[REG_MANUFACTURER_DATA].min_value ||
- ret > bq20z75_data[REG_MANUFACTURER_DATA].max_value) {
+ if (ret < sbs_data[REG_MANUFACTURER_DATA].min_value ||
+ ret > sbs_data[REG_MANUFACTURER_DATA].max_value) {
val->intval = 0;
return 0;
}
@@ -279,24 +270,23 @@ static int bq20z75_get_battery_presence_and_health(
return 0;
}
-static int bq20z75_get_battery_property(struct i2c_client *client,
+static int sbs_get_battery_property(struct i2c_client *client,
int reg_offset, enum power_supply_property psp,
union power_supply_propval *val)
{
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret;
- ret = bq20z75_read_word_data(client,
- bq20z75_data[reg_offset].addr);
+ ret = sbs_read_word_data(client, sbs_data[reg_offset].addr);
if (ret < 0)
return ret;
/* returned values are 16 bit */
- if (bq20z75_data[reg_offset].min_value < 0)
+ if (sbs_data[reg_offset].min_value < 0)
ret = (s16)ret;
- if (ret >= bq20z75_data[reg_offset].min_value &&
- ret <= bq20z75_data[reg_offset].max_value) {
+ if (ret >= sbs_data[reg_offset].min_value &&
+ ret <= sbs_data[reg_offset].max_value) {
val->intval = ret;
if (psp != POWER_SUPPLY_PROP_STATUS)
return 0;
@@ -310,12 +300,12 @@ static int bq20z75_get_battery_property(struct i2c_client *client,
else
val->intval = POWER_SUPPLY_STATUS_CHARGING;
- if (bq20z75_device->poll_time == 0)
- bq20z75_device->last_state = val->intval;
- else if (bq20z75_device->last_state != val->intval) {
- cancel_delayed_work_sync(&bq20z75_device->work);
- power_supply_changed(&bq20z75_device->power_supply);
- bq20z75_device->poll_time = 0;
+ if (chip->poll_time == 0)
+ chip->last_state = val->intval;
+ else if (chip->last_state != val->intval) {
+ cancel_delayed_work_sync(&chip->work);
+ power_supply_changed(&chip->power_supply);
+ chip->poll_time = 0;
}
} else {
if (psp == POWER_SUPPLY_PROP_STATUS)
@@ -327,7 +317,7 @@ static int bq20z75_get_battery_property(struct i2c_client *client,
return 0;
}
-static void bq20z75_unit_adjustment(struct i2c_client *client,
+static void sbs_unit_adjustment(struct i2c_client *client,
enum power_supply_property psp, union power_supply_propval *val)
{
#define BASE_UNIT_CONVERSION 1000
@@ -338,7 +328,7 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
case POWER_SUPPLY_PROP_ENERGY_NOW:
case POWER_SUPPLY_PROP_ENERGY_FULL:
case POWER_SUPPLY_PROP_ENERGY_FULL_DESIGN:
- /* bq20z75 provides energy in units of 10mWh.
+ /* sbs provides energy in units of 10mWh.
* Convert to µWh
*/
val->intval *= BATTERY_MODE_CAP_MULT_WATT;
@@ -354,7 +344,7 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
break;
case POWER_SUPPLY_PROP_TEMP:
- /* bq20z75 provides battery temperature in 0.1K
+ /* sbs provides battery temperature in 0.1K
* so convert it to 0.1°C
*/
val->intval -= TEMP_KELVIN_TO_CELSIUS;
@@ -362,7 +352,7 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
- /* bq20z75 provides time to empty and time to full in minutes.
+ /* sbs provides time to empty and time to full in minutes.
* Convert to seconds
*/
val->intval *= TIME_UNIT_CONVERSION;
@@ -374,13 +364,12 @@ static void bq20z75_unit_adjustment(struct i2c_client *client,
}
}
-static enum bq20z75_battery_mode
-bq20z75_set_battery_mode(struct i2c_client *client,
- enum bq20z75_battery_mode mode)
+static enum sbs_battery_mode sbs_set_battery_mode(struct i2c_client *client,
+ enum sbs_battery_mode mode)
{
int ret, original_val;
- original_val = bq20z75_read_word_data(client, BATTERY_MODE_OFFSET);
+ original_val = sbs_read_word_data(client, BATTERY_MODE_OFFSET);
if (original_val < 0)
return original_val;
@@ -392,68 +381,67 @@ bq20z75_set_battery_mode(struct i2c_client *client,
else
ret = original_val | BATTERY_MODE_MASK;
- ret = bq20z75_write_word_data(client, BATTERY_MODE_OFFSET, ret);
+ ret = sbs_write_word_data(client, BATTERY_MODE_OFFSET, ret);
if (ret < 0)
return ret;
return original_val & BATTERY_MODE_MASK;
}
-static int bq20z75_get_battery_capacity(struct i2c_client *client,
+static int sbs_get_battery_capacity(struct i2c_client *client,
int reg_offset, enum power_supply_property psp,
union power_supply_propval *val)
{
s32 ret;
- enum bq20z75_battery_mode mode = BATTERY_MODE_WATTS;
+ enum sbs_battery_mode mode = BATTERY_MODE_WATTS;
if (power_supply_is_amp_property(psp))
mode = BATTERY_MODE_AMPS;
- mode = bq20z75_set_battery_mode(client, mode);
+ mode = sbs_set_battery_mode(client, mode);
if (mode < 0)
return mode;
- ret = bq20z75_read_word_data(client, bq20z75_data[reg_offset].addr);
+ ret = sbs_read_word_data(client, sbs_data[reg_offset].addr);
if (ret < 0)
return ret;
if (psp == POWER_SUPPLY_PROP_CAPACITY) {
- /* bq20z75 spec says that this can be >100 %
+ /* sbs spec says that this can be >100 %
* even if max value is 100 % */
val->intval = min(ret, 100);
} else
val->intval = ret;
- ret = bq20z75_set_battery_mode(client, mode);
+ ret = sbs_set_battery_mode(client, mode);
if (ret < 0)
return ret;
return 0;
}
-static char bq20z75_serial[5];
-static int bq20z75_get_battery_serial_number(struct i2c_client *client,
+static char sbs_serial[5];
+static int sbs_get_battery_serial_number(struct i2c_client *client,
union power_supply_propval *val)
{
int ret;
- ret = bq20z75_read_word_data(client,
- bq20z75_data[REG_SERIAL_NUMBER].addr);
+ ret = sbs_read_word_data(client, sbs_data[REG_SERIAL_NUMBER].addr);
if (ret < 0)
return ret;
- ret = sprintf(bq20z75_serial, "%04x", ret);
- val->strval = bq20z75_serial;
+ ret = sprintf(sbs_serial, "%04x", ret);
+ val->strval = sbs_serial;
return 0;
}
-static int bq20z75_get_property_index(struct i2c_client *client,
+static int sbs_get_property_index(struct i2c_client *client,
enum power_supply_property psp)
{
int count;
- for (count = 0; count < ARRAY_SIZE(bq20z75_data); count++)
- if (psp == bq20z75_data[count].psp)
+ for (count = 0; count < ARRAY_SIZE(sbs_data); count++)
+ if (psp == sbs_data[count].psp)
return count;
dev_warn(&client->dev,
@@ -462,19 +450,19 @@ static int bq20z75_get_property_index(struct i2c_client *client,
return -EINVAL;
}
-static int bq20z75_get_property(struct power_supply *psy,
+static int sbs_get_property(struct power_supply *psy,
enum power_supply_property psp,
union power_supply_propval *val)
{
int ret = 0;
- struct bq20z75_info *bq20z75_device = container_of(psy,
- struct bq20z75_info, power_supply);
- struct i2c_client *client = bq20z75_device->client;
+ struct sbs_info *chip = container_of(psy,
+ struct sbs_info, power_supply);
+ struct i2c_client *client = chip->client;
switch (psp) {
case POWER_SUPPLY_PROP_PRESENT:
case POWER_SUPPLY_PROP_HEALTH:
- ret = bq20z75_get_battery_presence_and_health(client, psp, val);
+ ret = sbs_get_battery_presence_and_health(client, psp, val);
if (psp == POWER_SUPPLY_PROP_PRESENT)
return 0;
break;
@@ -490,15 +478,15 @@ static int bq20z75_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_CHARGE_FULL:
case POWER_SUPPLY_PROP_CHARGE_FULL_DESIGN:
case POWER_SUPPLY_PROP_CAPACITY:
- ret = bq20z75_get_property_index(client, psp);
+ ret = sbs_get_property_index(client, psp);
if (ret < 0)
break;
- ret = bq20z75_get_battery_capacity(client, ret, psp, val);
+ ret = sbs_get_battery_capacity(client, ret, psp, val);
break;
case POWER_SUPPLY_PROP_SERIAL_NUMBER:
- ret = bq20z75_get_battery_serial_number(client, val);
+ ret = sbs_get_battery_serial_number(client, val);
break;
case POWER_SUPPLY_PROP_STATUS:
@@ -509,11 +497,11 @@ static int bq20z75_get_property(struct power_supply *psy,
case POWER_SUPPLY_PROP_TIME_TO_EMPTY_AVG:
case POWER_SUPPLY_PROP_TIME_TO_FULL_AVG:
case POWER_SUPPLY_PROP_VOLTAGE_MAX_DESIGN:
- ret = bq20z75_get_property_index(client, psp);
+ ret = sbs_get_property_index(client, psp);
if (ret < 0)
break;
- ret = bq20z75_get_battery_property(client, ret, psp, val);
+ ret = sbs_get_battery_property(client, ret, psp, val);
break;
default:
@@ -522,25 +510,25 @@ static int bq20z75_get_property(struct power_supply *psy,
return -EINVAL;
}
- if (!bq20z75_device->enable_detection)
+ if (!chip->enable_detection)
goto done;
- if (!bq20z75_device->gpio_detect &&
- bq20z75_device->is_present != (ret >= 0)) {
- bq20z75_device->is_present = (ret >= 0);
- power_supply_changed(&bq20z75_device->power_supply);
+ if (!chip->gpio_detect &&
+ chip->is_present != (ret >= 0)) {
+ chip->is_present = (ret >= 0);
+ power_supply_changed(&chip->power_supply);
}
done:
if (!ret) {
/* Convert units to match requirements for power supply class */
- bq20z75_unit_adjustment(client, psp, val);
+ sbs_unit_adjustment(client, psp, val);
}
dev_dbg(&client->dev,
"%s: property = %d, value = %x\n", __func__, psp, val->intval);
- if (ret && bq20z75_device->is_present)
+ if (ret && chip->is_present)
return ret;
/* battery not present, so return NODATA for properties */
@@ -550,7 +538,7 @@ done:
return 0;
}
-static irqreturn_t bq20z75_irq(int irq, void *devid)
+static irqreturn_t sbs_irq(int irq, void *devid)
{
struct power_supply *battery = devid;
@@ -559,36 +547,35 @@ static irqreturn_t bq20z75_irq(int irq, void *devid)
return IRQ_HANDLED;
}
-static void bq20z75_external_power_changed(struct power_supply *psy)
+static void sbs_external_power_changed(struct power_supply *psy)
{
- struct bq20z75_info *bq20z75_device;
+ struct sbs_info *chip;
- bq20z75_device = container_of(psy, struct bq20z75_info, power_supply);
+ chip = container_of(psy, struct sbs_info, power_supply);
- if (bq20z75_device->ignore_changes > 0) {
- bq20z75_device->ignore_changes--;
+ if (chip->ignore_changes > 0) {
+ chip->ignore_changes--;
return;
}
/* cancel outstanding work */
- cancel_delayed_work_sync(&bq20z75_device->work);
+ cancel_delayed_work_sync(&chip->work);
- schedule_delayed_work(&bq20z75_device->work, HZ);
- bq20z75_device->poll_time = bq20z75_device->pdata->poll_retry_count;
+ schedule_delayed_work(&chip->work, HZ);
+ chip->poll_time = chip->pdata->poll_retry_count;
}
-static void bq20z75_delayed_work(struct work_struct *work)
+static void sbs_delayed_work(struct work_struct *work)
{
- struct bq20z75_info *bq20z75_device;
+ struct sbs_info *chip;
s32 ret;
- bq20z75_device = container_of(work, struct bq20z75_info, work.work);
+ chip = container_of(work, struct sbs_info, work.work);
- ret = bq20z75_read_word_data(bq20z75_device->client,
- bq20z75_data[REG_STATUS].addr);
+ ret = sbs_read_word_data(chip->client, sbs_data[REG_STATUS].addr);
/* if the read failed, give up on this work */
if (ret < 0) {
- bq20z75_device->poll_time = 0;
+ chip->poll_time = 0;
return;
}
@@ -601,62 +588,145 @@ static void bq20z75_delayed_work(struct work_struct *work)
else
ret = POWER_SUPPLY_STATUS_CHARGING;
- if (bq20z75_device->last_state != ret) {
- bq20z75_device->poll_time = 0;
- power_supply_changed(&bq20z75_device->power_supply);
+ if (chip->last_state != ret) {
+ chip->poll_time = 0;
+ power_supply_changed(&chip->power_supply);
return;
}
- if (bq20z75_device->poll_time > 0) {
- schedule_delayed_work(&bq20z75_device->work, HZ);
- bq20z75_device->poll_time--;
+ if (chip->poll_time > 0) {
+ schedule_delayed_work(&chip->work, HZ);
+ chip->poll_time--;
return;
}
}
-static int __devinit bq20z75_probe(struct i2c_client *client,
+#if defined(CONFIG_OF)
+
+#include <linux/of_device.h>
+#include <linux/of_gpio.h>
+
+static const struct of_device_id sbs_dt_ids[] = {
+ { .compatible = "sbs,sbs-battery" },
+ { .compatible = "ti,bq20z75" },
+ { }
+};
+MODULE_DEVICE_TABLE(of, sbs_dt_ids);
+
+static struct sbs_platform_data *sbs_of_populate_pdata(
+ struct i2c_client *client)
+{
+ struct device_node *of_node = client->dev.of_node;
+ struct sbs_platform_data *pdata = client->dev.platform_data;
+ enum of_gpio_flags gpio_flags;
+ int rc;
+ u32 prop;
+
+ /* verify this driver matches this device */
+ if (!of_node)
+ return NULL;
+
+ /* if platform data is set, honor it */
+ if (pdata)
+ return pdata;
+
+ /* first make sure at least one property is set, otherwise
+ * it won't change behavior from running without pdata.
+ */
+ if (!of_get_property(of_node, "sbs,i2c-retry-count", NULL) &&
+ !of_get_property(of_node, "sbs,poll-retry-count", NULL) &&
+ !of_get_property(of_node, "sbs,battery-detect-gpios", NULL))
+ goto of_out;
+
+ pdata = devm_kzalloc(&client->dev, sizeof(struct sbs_platform_data),
+ GFP_KERNEL);
+ if (!pdata)
+ goto of_out;
+
+ rc = of_property_read_u32(of_node, "sbs,i2c-retry-count", &prop);
+ if (!rc)
+ pdata->i2c_retry_count = prop;
+
+ rc = of_property_read_u32(of_node, "sbs,poll-retry-count", &prop);
+ if (!rc)
+ pdata->poll_retry_count = prop;
+
+ if (!of_get_property(of_node, "sbs,battery-detect-gpios", NULL)) {
+ pdata->battery_detect = -1;
+ goto of_out;
+ }
+
+ pdata->battery_detect = of_get_named_gpio_flags(of_node,
+ "sbs,battery-detect-gpios", 0, &gpio_flags);
+
+ if (gpio_flags & OF_GPIO_ACTIVE_LOW)
+ pdata->battery_detect_present = 0;
+ else
+ pdata->battery_detect_present = 1;
+
+of_out:
+ return pdata;
+}
+#else
+#define sbs_dt_ids NULL
+static struct sbs_platform_data *sbs_of_populate_pdata(
+ struct i2c_client *client)
+{
+ return client->dev.platform_data;
+}
+#endif
+
+static int __devinit sbs_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- struct bq20z75_info *bq20z75_device;
- struct bq20z75_platform_data *pdata = client->dev.platform_data;
+ struct sbs_info *chip;
+ struct sbs_platform_data *pdata = client->dev.platform_data;
int rc;
int irq;
+ char *name;
- bq20z75_device = kzalloc(sizeof(struct bq20z75_info), GFP_KERNEL);
- if (!bq20z75_device)
+ name = kasprintf(GFP_KERNEL, "sbs-%s", dev_name(&client->dev));
+ if (!name) {
+ dev_err(&client->dev, "Failed to allocate device name\n");
return -ENOMEM;
+ }
+
+ chip = kzalloc(sizeof(struct sbs_info), GFP_KERNEL);
+ if (!chip) {
+ rc = -ENOMEM;
+ goto exit_free_name;
+ }
- bq20z75_device->client = client;
- bq20z75_device->enable_detection = false;
- bq20z75_device->gpio_detect = false;
- bq20z75_device->power_supply.name = "battery";
- bq20z75_device->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
- bq20z75_device->power_supply.properties = bq20z75_properties;
- bq20z75_device->power_supply.num_properties =
- ARRAY_SIZE(bq20z75_properties);
- bq20z75_device->power_supply.get_property = bq20z75_get_property;
+ chip->client = client;
+ chip->enable_detection = false;
+ chip->gpio_detect = false;
+ chip->power_supply.name = name;
+ chip->power_supply.type = POWER_SUPPLY_TYPE_BATTERY;
+ chip->power_supply.properties = sbs_properties;
+ chip->power_supply.num_properties = ARRAY_SIZE(sbs_properties);
+ chip->power_supply.get_property = sbs_get_property;
/* ignore first notification of external change, it is generated
* from the power_supply_register call back
*/
- bq20z75_device->ignore_changes = 1;
- bq20z75_device->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
- bq20z75_device->power_supply.external_power_changed =
- bq20z75_external_power_changed;
+ chip->ignore_changes = 1;
+ chip->last_state = POWER_SUPPLY_STATUS_UNKNOWN;
+ chip->power_supply.external_power_changed = sbs_external_power_changed;
+
+ pdata = sbs_of_populate_pdata(client);
if (pdata) {
- bq20z75_device->gpio_detect =
- gpio_is_valid(pdata->battery_detect);
- bq20z75_device->pdata = pdata;
+ chip->gpio_detect = gpio_is_valid(pdata->battery_detect);
+ chip->pdata = pdata;
}
- i2c_set_clientdata(client, bq20z75_device);
+ i2c_set_clientdata(client, chip);
- if (!bq20z75_device->gpio_detect)
+ if (!chip->gpio_detect)
goto skip_gpio;
rc = gpio_request(pdata->battery_detect, dev_name(&client->dev));
if (rc) {
dev_warn(&client->dev, "Failed to request gpio: %d\n", rc);
- bq20z75_device->gpio_detect = false;
+ chip->gpio_detect = false;
goto skip_gpio;
}
@@ -664,7 +734,7 @@ static int __devinit bq20z75_probe(struct i2c_client *client,
if (rc) {
dev_warn(&client->dev, "Failed to get gpio as input: %d\n", rc);
gpio_free(pdata->battery_detect);
- bq20z75_device->gpio_detect = false;
+ chip->gpio_detect = false;
goto skip_gpio;
}
@@ -672,25 +742,25 @@ static int __devinit bq20z75_probe(struct i2c_client *client,
if (irq <= 0) {
dev_warn(&client->dev, "Failed to get gpio as irq: %d\n", irq);
gpio_free(pdata->battery_detect);
- bq20z75_device->gpio_detect = false;
+ chip->gpio_detect = false;
goto skip_gpio;
}
- rc = request_irq(irq, bq20z75_irq,
+ rc = request_irq(irq, sbs_irq,
IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING,
- dev_name(&client->dev), &bq20z75_device->power_supply);
+ dev_name(&client->dev), &chip->power_supply);
if (rc) {
dev_warn(&client->dev, "Failed to request irq: %d\n", rc);
gpio_free(pdata->battery_detect);
- bq20z75_device->gpio_detect = false;
+ chip->gpio_detect = false;
goto skip_gpio;
}
- bq20z75_device->irq = irq;
+ chip->irq = irq;
skip_gpio:
- rc = power_supply_register(&client->dev, &bq20z75_device->power_supply);
+ rc = power_supply_register(&client->dev, &chip->power_supply);
if (rc) {
dev_err(&client->dev,
"%s: Failed to register power supply\n", __func__);
@@ -700,95 +770,100 @@ skip_gpio:
dev_info(&client->dev,
"%s: battery gas gauge device registered\n", client->name);
- INIT_DELAYED_WORK(&bq20z75_device->work, bq20z75_delayed_work);
+ INIT_DELAYED_WORK(&chip->work, sbs_delayed_work);
- bq20z75_device->enable_detection = true;
+ chip->enable_detection = true;
return 0;
exit_psupply:
- if (bq20z75_device->irq)
- free_irq(bq20z75_device->irq, &bq20z75_device->power_supply);
- if (bq20z75_device->gpio_detect)
+ if (chip->irq)
+ free_irq(chip->irq, &chip->power_supply);
+ if (chip->gpio_detect)
gpio_free(pdata->battery_detect);
- kfree(bq20z75_device);
+ kfree(chip);
+
+exit_free_name:
+ kfree(name);
return rc;
}
-static int __devexit bq20z75_remove(struct i2c_client *client)
+static int __devexit sbs_remove(struct i2c_client *client)
{
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
- if (bq20z75_device->irq)
- free_irq(bq20z75_device->irq, &bq20z75_device->power_supply);
- if (bq20z75_device->gpio_detect)
- gpio_free(bq20z75_device->pdata->battery_detect);
+ if (chip->irq)
+ free_irq(chip->irq, &chip->power_supply);
+ if (chip->gpio_detect)
+ gpio_free(chip->pdata->battery_detect);
- power_supply_unregister(&bq20z75_device->power_supply);
+ power_supply_unregister(&chip->power_supply);
- cancel_delayed_work_sync(&bq20z75_device->work);
+ cancel_delayed_work_sync(&chip->work);
- kfree(bq20z75_device);
- bq20z75_device = NULL;
+ kfree(chip->power_supply.name);
+ kfree(chip);
+ chip = NULL;
return 0;
}
#if defined CONFIG_PM
-static int bq20z75_suspend(struct i2c_client *client,
+static int sbs_suspend(struct i2c_client *client,
pm_message_t state)
{
- struct bq20z75_info *bq20z75_device = i2c_get_clientdata(client);
+ struct sbs_info *chip = i2c_get_clientdata(client);
s32 ret;
- if (bq20z75_device->poll_time > 0)
- cancel_delayed_work_sync(&bq20z75_device->work);
+ if (chip->poll_time > 0)
+ cancel_delayed_work_sync(&chip->work);
/* write to manufacturer access with sleep command */
- ret = bq20z75_write_word_data(client,
- bq20z75_data[REG_MANUFACTURER_DATA].addr,
+ ret = sbs_write_word_data(client, sbs_data[REG_MANUFACTURER_DATA].addr,
MANUFACTURER_ACCESS_SLEEP);
- if (bq20z75_device->is_present && ret < 0)
+ if (chip->is_present && ret < 0)
return ret;
return 0;
}
#else
-#define bq20z75_suspend NULL
+#define sbs_suspend NULL
#endif
-/* any smbus transaction will wake up bq20z75 */
-#define bq20z75_resume NULL
+/* any smbus transaction will wake up sbs */
+#define sbs_resume NULL
-static const struct i2c_device_id bq20z75_id[] = {
+static const struct i2c_device_id sbs_id[] = {
{ "bq20z75", 0 },
+ { "sbs-battery", 1 },
{}
};
-MODULE_DEVICE_TABLE(i2c, bq20z75_id);
-
-static struct i2c_driver bq20z75_battery_driver = {
- .probe = bq20z75_probe,
- .remove = __devexit_p(bq20z75_remove),
- .suspend = bq20z75_suspend,
- .resume = bq20z75_resume,
- .id_table = bq20z75_id,
+MODULE_DEVICE_TABLE(i2c, sbs_id);
+
+static struct i2c_driver sbs_battery_driver = {
+ .probe = sbs_probe,
+ .remove = __devexit_p(sbs_remove),
+ .suspend = sbs_suspend,
+ .resume = sbs_resume,
+ .id_table = sbs_id,
.driver = {
- .name = "bq20z75-battery",
+ .name = "sbs-battery",
+ .of_match_table = sbs_dt_ids,
},
};
-static int __init bq20z75_battery_init(void)
+static int __init sbs_battery_init(void)
{
- return i2c_add_driver(&bq20z75_battery_driver);
+ return i2c_add_driver(&sbs_battery_driver);
}
-module_init(bq20z75_battery_init);
+module_init(sbs_battery_init);
-static void __exit bq20z75_battery_exit(void)
+static void __exit sbs_battery_exit(void)
{
- i2c_del_driver(&bq20z75_battery_driver);
+ i2c_del_driver(&sbs_battery_driver);
}
-module_exit(bq20z75_battery_exit);
+module_exit(sbs_battery_exit);
-MODULE_DESCRIPTION("BQ20z75 battery monitor driver");
+MODULE_DESCRIPTION("SBS battery monitor driver");
MODULE_LICENSE("GPL");
diff --git a/drivers/power/tosa_battery.c b/drivers/power/tosa_battery.c
index 53f0d3524fcd..28bbe7e094e3 100644
--- a/drivers/power/tosa_battery.c
+++ b/drivers/power/tosa_battery.c
@@ -307,25 +307,20 @@ static struct tosa_bat tosa_bat_bu = {
.adc_temp_divider = -1,
};
-static struct {
- int gpio;
- char *name;
- bool output;
- int value;
-} gpios[] = {
- { TOSA_GPIO_CHARGE_OFF, "main charge off", 1, 1 },
- { TOSA_GPIO_CHARGE_OFF_JC, "jacket charge off", 1, 1 },
- { TOSA_GPIO_BAT_SW_ON, "battery switch", 1, 0 },
- { TOSA_GPIO_BAT0_V_ON, "main battery", 1, 0 },
- { TOSA_GPIO_BAT1_V_ON, "jacket battery", 1, 0 },
- { TOSA_GPIO_BAT1_TH_ON, "main battery temp", 1, 0 },
- { TOSA_GPIO_BAT0_TH_ON, "jacket battery temp", 1, 0 },
- { TOSA_GPIO_BU_CHRG_ON, "backup battery", 1, 0 },
- { TOSA_GPIO_BAT0_CRG, "main battery full", 0, 0 },
- { TOSA_GPIO_BAT1_CRG, "jacket battery full", 0, 0 },
- { TOSA_GPIO_BAT0_LOW, "main battery low", 0, 0 },
- { TOSA_GPIO_BAT1_LOW, "jacket battery low", 0, 0 },
- { TOSA_GPIO_JACKET_DETECT, "jacket detect", 0, 0 },
+static struct gpio tosa_bat_gpios[] = {
+ { TOSA_GPIO_CHARGE_OFF, GPIOF_OUT_INIT_HIGH, "main charge off" },
+ { TOSA_GPIO_CHARGE_OFF_JC, GPIOF_OUT_INIT_HIGH, "jacket charge off" },
+ { TOSA_GPIO_BAT_SW_ON, GPIOF_OUT_INIT_LOW, "battery switch" },
+ { TOSA_GPIO_BAT0_V_ON, GPIOF_OUT_INIT_LOW, "main battery" },
+ { TOSA_GPIO_BAT1_V_ON, GPIOF_OUT_INIT_LOW, "jacket battery" },
+ { TOSA_GPIO_BAT1_TH_ON, GPIOF_OUT_INIT_LOW, "main battery temp" },
+ { TOSA_GPIO_BAT0_TH_ON, GPIOF_OUT_INIT_LOW, "jacket battery temp" },
+ { TOSA_GPIO_BU_CHRG_ON, GPIOF_OUT_INIT_LOW, "backup battery" },
+ { TOSA_GPIO_BAT0_CRG, GPIOF_IN, "main battery full" },
+ { TOSA_GPIO_BAT1_CRG, GPIOF_IN, "jacket battery full" },
+ { TOSA_GPIO_BAT0_LOW, GPIOF_IN, "main battery low" },
+ { TOSA_GPIO_BAT1_LOW, GPIOF_IN, "jacket battery low" },
+ { TOSA_GPIO_JACKET_DETECT, GPIOF_IN, "jacket detect" },
};
#ifdef CONFIG_PM
@@ -350,27 +345,13 @@ static int tosa_bat_resume(struct platform_device *dev)
static int __devinit tosa_bat_probe(struct platform_device *dev)
{
int ret;
- int i;
if (!machine_is_tosa())
return -ENODEV;
- for (i = 0; i < ARRAY_SIZE(gpios); i++) {
- ret = gpio_request(gpios[i].gpio, gpios[i].name);
- if (ret) {
- i--;
- goto err_gpio;
- }
-
- if (gpios[i].output)
- ret = gpio_direction_output(gpios[i].gpio,
- gpios[i].value);
- else
- ret = gpio_direction_input(gpios[i].gpio);
-
- if (ret)
- goto err_gpio;
- }
+ ret = gpio_request_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
+ if (ret)
+ return ret;
mutex_init(&tosa_bat_main.work_lock);
mutex_init(&tosa_bat_jacket.work_lock);
@@ -424,18 +405,12 @@ err_psy_reg_main:
/* see comment in tosa_bat_remove */
cancel_work_sync(&bat_work);
- i--;
-err_gpio:
- for (; i >= 0; i--)
- gpio_free(gpios[i].gpio);
-
+ gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
return ret;
}
static int __devexit tosa_bat_remove(struct platform_device *dev)
{
- int i;
-
free_irq(gpio_to_irq(TOSA_GPIO_JACKET_DETECT), &tosa_bat_jacket);
free_irq(gpio_to_irq(TOSA_GPIO_BAT1_CRG), &tosa_bat_jacket);
free_irq(gpio_to_irq(TOSA_GPIO_BAT0_CRG), &tosa_bat_main);
@@ -450,10 +425,7 @@ static int __devexit tosa_bat_remove(struct platform_device *dev)
* unregistered now.
*/
cancel_work_sync(&bat_work);
-
- for (i = ARRAY_SIZE(gpios) - 1; i >= 0; i--)
- gpio_free(gpios[i].gpio);
-
+ gpio_free_array(tosa_bat_gpios, ARRAY_SIZE(tosa_bat_gpios));
return 0;
}
@@ -466,18 +438,7 @@ static struct platform_driver tosa_bat_driver = {
.resume = tosa_bat_resume,
};
-static int __init tosa_bat_init(void)
-{
- return platform_driver_register(&tosa_bat_driver);
-}
-
-static void __exit tosa_bat_exit(void)
-{
- platform_driver_unregister(&tosa_bat_driver);
-}
-
-module_init(tosa_bat_init);
-module_exit(tosa_bat_exit);
+module_platform_driver(tosa_bat_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Dmitry Baryshkov");
diff --git a/drivers/power/wm831x_backup.c b/drivers/power/wm831x_backup.c
index e648cbea1e6a..6243e6975126 100644
--- a/drivers/power/wm831x_backup.c
+++ b/drivers/power/wm831x_backup.c
@@ -226,17 +226,7 @@ static struct platform_driver wm831x_backup_driver = {
},
};
-static int __init wm831x_backup_init(void)
-{
- return platform_driver_register(&wm831x_backup_driver);
-}
-module_init(wm831x_backup_init);
-
-static void __exit wm831x_backup_exit(void)
-{
- platform_driver_unregister(&wm831x_backup_driver);
-}
-module_exit(wm831x_backup_exit);
+module_platform_driver(wm831x_backup_driver);
MODULE_DESCRIPTION("Backup battery charger driver for WM831x PMICs");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/power/wm831x_power.c b/drivers/power/wm831x_power.c
index 6cc2ca6427f3..987332b71d8d 100644
--- a/drivers/power/wm831x_power.c
+++ b/drivers/power/wm831x_power.c
@@ -27,6 +27,7 @@ struct wm831x_power {
char wall_name[20];
char usb_name[20];
char battery_name[20];
+ bool have_battery;
};
static int wm831x_power_check_online(struct wm831x *wm831x, int supply,
@@ -449,7 +450,8 @@ static irqreturn_t wm831x_bat_irq(int irq, void *data)
/* The battery charger is autonomous so we don't need to do
* anything except kick user space */
- power_supply_changed(&wm831x_power->battery);
+ if (wm831x_power->have_battery)
+ power_supply_changed(&wm831x_power->battery);
return IRQ_HANDLED;
}
@@ -479,7 +481,8 @@ static irqreturn_t wm831x_pwr_src_irq(int irq, void *data)
dev_dbg(wm831x->dev, "Power source changed\n");
/* Just notify for everything - little harm in overnotifying. */
- power_supply_changed(&wm831x_power->battery);
+ if (wm831x_power->have_battery)
+ power_supply_changed(&wm831x_power->battery);
power_supply_changed(&wm831x_power->usb);
power_supply_changed(&wm831x_power->wall);
@@ -537,15 +540,6 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
if (ret)
goto err_kmalloc;
- battery->name = power->battery_name;
- battery->properties = wm831x_bat_props;
- battery->num_properties = ARRAY_SIZE(wm831x_bat_props);
- battery->get_property = wm831x_bat_get_prop;
- battery->use_for_apm = 1;
- ret = power_supply_register(&pdev->dev, battery);
- if (ret)
- goto err_wall;
-
usb->name = power->usb_name,
usb->type = POWER_SUPPLY_TYPE_USB;
usb->properties = wm831x_usb_props;
@@ -553,7 +547,23 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
usb->get_property = wm831x_usb_get_prop;
ret = power_supply_register(&pdev->dev, usb);
if (ret)
- goto err_battery;
+ goto err_wall;
+
+ ret = wm831x_reg_read(wm831x, WM831X_CHARGER_CONTROL_1);
+ if (ret < 0)
+ goto err_wall;
+ power->have_battery = ret & WM831X_CHG_ENA;
+
+ if (power->have_battery) {
+ battery->name = power->battery_name;
+ battery->properties = wm831x_bat_props;
+ battery->num_properties = ARRAY_SIZE(wm831x_bat_props);
+ battery->get_property = wm831x_bat_get_prop;
+ battery->use_for_apm = 1;
+ ret = power_supply_register(&pdev->dev, battery);
+ if (ret)
+ goto err_usb;
+ }
irq = platform_get_irq_byname(pdev, "SYSLO");
ret = request_threaded_irq(irq, NULL, wm831x_syslo_irq,
@@ -562,7 +572,7 @@ static __devinit int wm831x_power_probe(struct platform_device *pdev)
if (ret != 0) {
dev_err(&pdev->dev, "Failed to request SYSLO IRQ %d: %d\n",
irq, ret);
- goto err_usb;
+ goto err_battery;
}
irq = platform_get_irq_byname(pdev, "PWR SRC");
@@ -601,10 +611,11 @@ err_bat_irq:
err_syslo:
irq = platform_get_irq_byname(pdev, "SYSLO");
free_irq(irq, power);
+err_battery:
+ if (power->have_battery)
+ power_supply_unregister(battery);
err_usb:
power_supply_unregister(usb);
-err_battery:
- power_supply_unregister(battery);
err_wall:
power_supply_unregister(wall);
err_kmalloc:
@@ -628,7 +639,8 @@ static __devexit int wm831x_power_remove(struct platform_device *pdev)
irq = platform_get_irq_byname(pdev, "SYSLO");
free_irq(irq, wm831x_power);
- power_supply_unregister(&wm831x_power->battery);
+ if (wm831x_power->have_battery)
+ power_supply_unregister(&wm831x_power->battery);
power_supply_unregister(&wm831x_power->wall);
power_supply_unregister(&wm831x_power->usb);
kfree(wm831x_power);
@@ -643,17 +655,7 @@ static struct platform_driver wm831x_power_driver = {
},
};
-static int __init wm831x_power_init(void)
-{
- return platform_driver_register(&wm831x_power_driver);
-}
-module_init(wm831x_power_init);
-
-static void __exit wm831x_power_exit(void)
-{
- platform_driver_unregister(&wm831x_power_driver);
-}
-module_exit(wm831x_power_exit);
+module_platform_driver(wm831x_power_driver);
MODULE_DESCRIPTION("Power supply driver for WM831x PMICs");
MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
diff --git a/drivers/power/wm8350_power.c b/drivers/power/wm8350_power.c
index 0693902d6151..fae04d384657 100644
--- a/drivers/power/wm8350_power.c
+++ b/drivers/power/wm8350_power.c
@@ -522,17 +522,7 @@ static struct platform_driver wm8350_power_driver = {
},
};
-static int __init wm8350_power_init(void)
-{
- return platform_driver_register(&wm8350_power_driver);
-}
-module_init(wm8350_power_init);
-
-static void __exit wm8350_power_exit(void)
-{
- platform_driver_unregister(&wm8350_power_driver);
-}
-module_exit(wm8350_power_exit);
+module_platform_driver(wm8350_power_driver);
MODULE_LICENSE("GPL");
MODULE_DESCRIPTION("Power supply driver for WM8350");
diff --git a/drivers/power/wm97xx_battery.c b/drivers/power/wm97xx_battery.c
index 156559e56fa5..d2d4c08c681c 100644
--- a/drivers/power/wm97xx_battery.c
+++ b/drivers/power/wm97xx_battery.c
@@ -25,9 +25,8 @@
#include <linux/irq.h>
#include <linux/slab.h>
-static DEFINE_MUTEX(bat_lock);
static struct work_struct bat_work;
-static struct mutex work_lock;
+static DEFINE_MUTEX(work_lock);
static int bat_status = POWER_SUPPLY_STATUS_UNKNOWN;
static enum power_supply_property *prop;
@@ -181,8 +180,6 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
if (dev->id != -1)
return -EINVAL;
- mutex_init(&work_lock);
-
if (!pdata) {
dev_err(&dev->dev, "No platform_data supplied\n");
return -EINVAL;
@@ -196,7 +193,7 @@ static int __devinit wm97xx_bat_probe(struct platform_device *dev)
if (ret)
goto err2;
ret = request_irq(gpio_to_irq(pdata->charge_gpio),
- wm97xx_chrg_irq, IRQF_DISABLED,
+ wm97xx_chrg_irq, 0,
"AC Detect", dev);
if (ret)
goto err2;
@@ -291,18 +288,7 @@ static struct platform_driver wm97xx_bat_driver = {
.remove = __devexit_p(wm97xx_bat_remove),
};
-static int __init wm97xx_bat_init(void)
-{
- return platform_driver_register(&wm97xx_bat_driver);
-}
-
-static void __exit wm97xx_bat_exit(void)
-{
- platform_driver_unregister(&wm97xx_bat_driver);
-}
-
-module_init(wm97xx_bat_init);
-module_exit(wm97xx_bat_exit);
+module_platform_driver(wm97xx_bat_driver);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Marek Vasut <marek.vasut@gmail.com>");
diff --git a/drivers/power/z2_battery.c b/drivers/power/z2_battery.c
index d119c38b3ff6..636ebb2a0e80 100644
--- a/drivers/power/z2_battery.c
+++ b/drivers/power/z2_battery.c
@@ -218,7 +218,7 @@ static int __devinit z2_batt_probe(struct i2c_client *client,
irq_set_irq_type(gpio_to_irq(info->charge_gpio),
IRQ_TYPE_EDGE_BOTH);
ret = request_irq(gpio_to_irq(info->charge_gpio),
- z2_charge_switch_irq, IRQF_DISABLED,
+ z2_charge_switch_irq, 0,
"AC Detect", charger);
if (ret)
goto err3;
@@ -313,7 +313,7 @@ static struct i2c_driver z2_batt_driver = {
.pm = Z2_BATTERY_PM_OPS
},
.probe = z2_batt_probe,
- .remove = z2_batt_remove,
+ .remove = __devexit_p(z2_batt_remove),
.id_table = z2_batt_id,
};
diff --git a/drivers/rtc/Kconfig b/drivers/rtc/Kconfig
index 877cf6fdcf24..e19a4031f45e 100644
--- a/drivers/rtc/Kconfig
+++ b/drivers/rtc/Kconfig
@@ -498,9 +498,9 @@ config RTC_DRV_CMOS
will be called rtc-cmos.
config RTC_DRV_VRTC
- tristate "Virtual RTC for Moorestown platforms"
- depends on X86_MRST
- default y if X86_MRST
+ tristate "Virtual RTC for Intel MID platforms"
+ depends on X86_INTEL_MID
+ default y if X86_INTEL_MID
help
Say "yes" here to get direct support for the real time clock
diff --git a/drivers/scsi/ipr.c b/drivers/scsi/ipr.c
index fd860d952b28..67b169b7a5be 100644
--- a/drivers/scsi/ipr.c
+++ b/drivers/scsi/ipr.c
@@ -7638,8 +7638,12 @@ static int ipr_reset_restore_cfg_space(struct ipr_cmnd *ipr_cmd)
**/
static int ipr_reset_bist_done(struct ipr_cmnd *ipr_cmd)
{
+ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+
ENTER;
- pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
+ if (ioa_cfg->cfg_locked)
+ pci_cfg_access_unlock(ioa_cfg->pdev);
+ ioa_cfg->cfg_locked = 0;
ipr_cmd->job_step = ipr_reset_restore_cfg_space;
LEAVE;
return IPR_RC_JOB_CONTINUE;
@@ -7660,8 +7664,6 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
int rc = PCIBIOS_SUCCESSFUL;
ENTER;
- pci_block_user_cfg_access(ioa_cfg->pdev);
-
if (ioa_cfg->ipr_chip->bist_method == IPR_MMIO)
writel(IPR_UPROCI_SIS64_START_BIST,
ioa_cfg->regs.set_uproc_interrupt_reg32);
@@ -7673,7 +7675,9 @@ static int ipr_reset_start_bist(struct ipr_cmnd *ipr_cmd)
ipr_reset_start_timer(ipr_cmd, IPR_WAIT_FOR_BIST_TIMEOUT);
rc = IPR_RC_JOB_RETURN;
} else {
- pci_unblock_user_cfg_access(ipr_cmd->ioa_cfg->pdev);
+ if (ioa_cfg->cfg_locked)
+ pci_cfg_access_unlock(ipr_cmd->ioa_cfg->pdev);
+ ioa_cfg->cfg_locked = 0;
ipr_cmd->s.ioasa.hdr.ioasc = cpu_to_be32(IPR_IOASC_PCI_ACCESS_ERROR);
rc = IPR_RC_JOB_CONTINUE;
}
@@ -7716,7 +7720,6 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
struct pci_dev *pdev = ioa_cfg->pdev;
ENTER;
- pci_block_user_cfg_access(pdev);
pci_set_pcie_reset_state(pdev, pcie_warm_reset);
ipr_cmd->job_step = ipr_reset_slot_reset_done;
ipr_reset_start_timer(ipr_cmd, IPR_PCI_RESET_TIMEOUT);
@@ -7725,6 +7728,56 @@ static int ipr_reset_slot_reset(struct ipr_cmnd *ipr_cmd)
}
/**
+ * ipr_reset_block_config_access_wait - Wait for permission to block config access
+ * @ipr_cmd: ipr command struct
+ *
+ * Description: This attempts to block config access to the IOA.
+ *
+ * Return value:
+ * IPR_RC_JOB_CONTINUE / IPR_RC_JOB_RETURN
+ **/
+static int ipr_reset_block_config_access_wait(struct ipr_cmnd *ipr_cmd)
+{
+ struct ipr_ioa_cfg *ioa_cfg = ipr_cmd->ioa_cfg;
+ int rc = IPR_RC_JOB_CONTINUE;
+
+ if (pci_cfg_access_trylock(ioa_cfg->pdev)) {
+ ioa_cfg->cfg_locked = 1;
+ ipr_cmd->job_step = ioa_cfg->reset;
+ } else {
+ if (ipr_cmd->u.time_left) {
+ rc = IPR_RC_JOB_RETURN;
+ ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
+ ipr_reset_start_timer(ipr_cmd,
+ IPR_CHECK_FOR_RESET_TIMEOUT);
+ } else {
+ ipr_cmd->job_step = ioa_cfg->reset;
+ dev_err(&ioa_cfg->pdev->dev,
+ "Timed out waiting to lock config access. Resetting anyway.\n");
+ }
+ }
+
+ return rc;
+}
+
+/**
+ * ipr_reset_block_config_access - Block config access to the IOA
+ * @ipr_cmd: ipr command struct
+ *
+ * Description: This attempts to block config access to the IOA
+ *
+ * Return value:
+ * IPR_RC_JOB_CONTINUE
+ **/
+static int ipr_reset_block_config_access(struct ipr_cmnd *ipr_cmd)
+{
+ ipr_cmd->ioa_cfg->cfg_locked = 0;
+ ipr_cmd->job_step = ipr_reset_block_config_access_wait;
+ ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;
+ return IPR_RC_JOB_CONTINUE;
+}
+
+/**
* ipr_reset_allowed - Query whether or not IOA can be reset
* @ioa_cfg: ioa config struct
*
@@ -7763,7 +7816,7 @@ static int ipr_reset_wait_to_start_bist(struct ipr_cmnd *ipr_cmd)
ipr_cmd->u.time_left -= IPR_CHECK_FOR_RESET_TIMEOUT;
ipr_reset_start_timer(ipr_cmd, IPR_CHECK_FOR_RESET_TIMEOUT);
} else {
- ipr_cmd->job_step = ioa_cfg->reset;
+ ipr_cmd->job_step = ipr_reset_block_config_access;
rc = IPR_RC_JOB_CONTINUE;
}
@@ -7796,7 +7849,7 @@ static int ipr_reset_alert(struct ipr_cmnd *ipr_cmd)
writel(IPR_UPROCI_RESET_ALERT, ioa_cfg->regs.set_uproc_interrupt_reg32);
ipr_cmd->job_step = ipr_reset_wait_to_start_bist;
} else {
- ipr_cmd->job_step = ioa_cfg->reset;
+ ipr_cmd->job_step = ipr_reset_block_config_access;
}
ipr_cmd->u.time_left = IPR_WAIT_FOR_RESET_TIMEOUT;
diff --git a/drivers/scsi/ipr.h b/drivers/scsi/ipr.h
index ac84736c1b9c..b13f9cc12279 100644
--- a/drivers/scsi/ipr.h
+++ b/drivers/scsi/ipr.h
@@ -1387,6 +1387,7 @@ struct ipr_ioa_cfg {
u8 msi_received:1;
u8 sis64:1;
u8 dump_timeout:1;
+ u8 cfg_locked:1;
u8 revid;
diff --git a/drivers/sh/Makefile b/drivers/sh/Makefile
index 67e272ab1623..7139ad2f2086 100644
--- a/drivers/sh/Makefile
+++ b/drivers/sh/Makefile
@@ -7,11 +7,4 @@ obj-$(CONFIG_HAVE_CLK) += clk/
obj-$(CONFIG_MAPLE) += maple/
obj-$(CONFIG_SUPERHYWAY) += superhyway/
obj-$(CONFIG_GENERIC_GPIO) += pfc.o
-
-#
-# For the moment we only use this framework for ARM-based SH/R-Mobile
-# platforms and generic SH. SH-based SH-Mobile platforms are still using
-# an older framework that is pending up-porting, at which point this
-# special casing can go away.
-#
-obj-$(CONFIG_SUPERH)$(CONFIG_ARCH_SHMOBILE) += pm_runtime.o
+obj-y += pm_runtime.o
diff --git a/drivers/sh/clk/core.c b/drivers/sh/clk/core.c
index db257a35e71a..7715de2629c1 100644
--- a/drivers/sh/clk/core.c
+++ b/drivers/sh/clk/core.c
@@ -355,7 +355,7 @@ static int clk_establish_mapping(struct clk *clk)
*/
if (!clk->parent) {
clk->mapping = &dummy_mapping;
- return 0;
+ goto out;
}
/*
@@ -384,6 +384,9 @@ static int clk_establish_mapping(struct clk *clk)
}
clk->mapping = mapping;
+out:
+ clk->mapped_reg = clk->mapping->base;
+ clk->mapped_reg += (phys_addr_t)clk->enable_reg - clk->mapping->phys;
return 0;
}
@@ -402,10 +405,12 @@ static void clk_teardown_mapping(struct clk *clk)
/* Nothing to do */
if (mapping == &dummy_mapping)
- return;
+ goto out;
kref_put(&mapping->ref, clk_destroy_mapping);
clk->mapping = NULL;
+out:
+ clk->mapped_reg = NULL;
}
int clk_register(struct clk *clk)
diff --git a/drivers/sh/clk/cpg.c b/drivers/sh/clk/cpg.c
index 82dd6fb17838..45fee368b092 100644
--- a/drivers/sh/clk/cpg.c
+++ b/drivers/sh/clk/cpg.c
@@ -15,15 +15,15 @@
static int sh_clk_mstp32_enable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << clk->enable_bit),
- clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << clk->enable_bit),
+ clk->mapped_reg);
return 0;
}
static void sh_clk_mstp32_disable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) | (1 << clk->enable_bit),
- clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) | (1 << clk->enable_bit),
+ clk->mapped_reg);
}
static struct clk_ops sh_clk_mstp32_clk_ops = {
@@ -72,7 +72,7 @@ static unsigned long sh_clk_div6_recalc(struct clk *clk)
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
table, NULL);
- idx = __raw_readl(clk->enable_reg) & 0x003f;
+ idx = ioread32(clk->mapped_reg) & 0x003f;
return clk->freq_table[idx].frequency;
}
@@ -98,10 +98,10 @@ static int sh_clk_div6_set_parent(struct clk *clk, struct clk *parent)
if (ret < 0)
return ret;
- value = __raw_readl(clk->enable_reg) &
+ value = ioread32(clk->mapped_reg) &
~(((1 << clk->src_width) - 1) << clk->src_shift);
- __raw_writel(value | (i << clk->src_shift), clk->enable_reg);
+ iowrite32(value | (i << clk->src_shift), clk->mapped_reg);
/* Rebuild the frequency table */
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -119,10 +119,10 @@ static int sh_clk_div6_set_rate(struct clk *clk, unsigned long rate)
if (idx < 0)
return idx;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~0x3f;
value |= idx;
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
return 0;
}
@@ -133,9 +133,9 @@ static int sh_clk_div6_enable(struct clk *clk)
ret = sh_clk_div6_set_rate(clk, clk->rate);
if (ret == 0) {
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~0x100; /* clear stop bit to enable clock */
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
}
return ret;
}
@@ -144,10 +144,10 @@ static void sh_clk_div6_disable(struct clk *clk)
{
unsigned long value;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value |= 0x100; /* stop clock */
value |= 0x3f; /* VDIV bits must be non-zero, overwrite divider */
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
}
static struct clk_ops sh_clk_div6_clk_ops = {
@@ -167,6 +167,38 @@ static struct clk_ops sh_clk_div6_reparent_clk_ops = {
.set_parent = sh_clk_div6_set_parent,
};
+static int __init sh_clk_init_parent(struct clk *clk)
+{
+ u32 val;
+
+ if (clk->parent)
+ return 0;
+
+ if (!clk->parent_table || !clk->parent_num)
+ return 0;
+
+ if (!clk->src_width) {
+ pr_err("sh_clk_init_parent: cannot select parent clock\n");
+ return -EINVAL;
+ }
+
+ val = (ioread32(clk->mapped_reg) >> clk->src_shift);
+ val &= (1 << clk->src_width) - 1;
+
+ if (val >= clk->parent_num) {
+ pr_err("sh_clk_init_parent: parent table size failed\n");
+ return -EINVAL;
+ }
+
+ clk->parent = clk->parent_table[val];
+ if (!clk->parent) {
+ pr_err("sh_clk_init_parent: unable to set parent");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
struct clk_ops *ops)
{
@@ -190,8 +222,11 @@ static int __init sh_clk_div6_register_ops(struct clk *clks, int nr,
clkp->ops = ops;
clkp->freq_table = freq_table + (k * freq_table_size);
clkp->freq_table[nr_divs].frequency = CPUFREQ_TABLE_END;
-
ret = clk_register(clkp);
+ if (ret < 0)
+ break;
+
+ ret = sh_clk_init_parent(clkp);
}
return ret;
@@ -217,7 +252,7 @@ static unsigned long sh_clk_div4_recalc(struct clk *clk)
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
table, &clk->arch_flags);
- idx = (__raw_readl(clk->enable_reg) >> clk->enable_bit) & 0x000f;
+ idx = (ioread32(clk->mapped_reg) >> clk->enable_bit) & 0x000f;
return clk->freq_table[idx].frequency;
}
@@ -235,15 +270,15 @@ static int sh_clk_div4_set_parent(struct clk *clk, struct clk *parent)
*/
if (parent->flags & CLK_ENABLE_ON_INIT)
- value = __raw_readl(clk->enable_reg) & ~(1 << 7);
+ value = ioread32(clk->mapped_reg) & ~(1 << 7);
else
- value = __raw_readl(clk->enable_reg) | (1 << 7);
+ value = ioread32(clk->mapped_reg) | (1 << 7);
ret = clk_reparent(clk, parent);
if (ret < 0)
return ret;
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
/* Rebiuld the frequency table */
clk_rate_table_build(clk, clk->freq_table, table->nr_divisors,
@@ -260,10 +295,10 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
if (idx < 0)
return idx;
- value = __raw_readl(clk->enable_reg);
+ value = ioread32(clk->mapped_reg);
value &= ~(0xf << clk->enable_bit);
value |= (idx << clk->enable_bit);
- __raw_writel(value, clk->enable_reg);
+ iowrite32(value, clk->mapped_reg);
if (d4t->kick)
d4t->kick(clk);
@@ -273,13 +308,13 @@ static int sh_clk_div4_set_rate(struct clk *clk, unsigned long rate)
static int sh_clk_div4_enable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) & ~(1 << 8), clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) & ~(1 << 8), clk->mapped_reg);
return 0;
}
static void sh_clk_div4_disable(struct clk *clk)
{
- __raw_writel(__raw_readl(clk->enable_reg) | (1 << 8), clk->enable_reg);
+ iowrite32(ioread32(clk->mapped_reg) | (1 << 8), clk->mapped_reg);
}
static struct clk_ops sh_clk_div4_clk_ops = {
diff --git a/drivers/sh/pfc.c b/drivers/sh/pfc.c
index e67fe170d8d5..522c6c46d1be 100644
--- a/drivers/sh/pfc.c
+++ b/drivers/sh/pfc.c
@@ -19,6 +19,75 @@
#include <linux/irq.h>
#include <linux/bitops.h>
#include <linux/gpio.h>
+#include <linux/slab.h>
+#include <linux/ioport.h>
+
+static void pfc_iounmap(struct pinmux_info *pip)
+{
+ int k;
+
+ for (k = 0; k < pip->num_resources; k++)
+ if (pip->window[k].virt)
+ iounmap(pip->window[k].virt);
+
+ kfree(pip->window);
+ pip->window = NULL;
+}
+
+static int pfc_ioremap(struct pinmux_info *pip)
+{
+ struct resource *res;
+ int k;
+
+ if (!pip->num_resources)
+ return 0;
+
+ pip->window = kzalloc(pip->num_resources * sizeof(*pip->window),
+ GFP_NOWAIT);
+ if (!pip->window)
+ goto err1;
+
+ for (k = 0; k < pip->num_resources; k++) {
+ res = pip->resource + k;
+ WARN_ON(resource_type(res) != IORESOURCE_MEM);
+ pip->window[k].phys = res->start;
+ pip->window[k].size = resource_size(res);
+ pip->window[k].virt = ioremap_nocache(res->start,
+ resource_size(res));
+ if (!pip->window[k].virt)
+ goto err2;
+ }
+
+ return 0;
+
+err2:
+ pfc_iounmap(pip);
+err1:
+ return -1;
+}
+
+static void __iomem *pfc_phys_to_virt(struct pinmux_info *pip,
+ unsigned long address)
+{
+ struct pfc_window *window;
+ int k;
+
+ /* scan through physical windows and convert address */
+ for (k = 0; k < pip->num_resources; k++) {
+ window = pip->window + k;
+
+ if (address < window->phys)
+ continue;
+
+ if (address >= (window->phys + window->size))
+ continue;
+
+ return window->virt + (address - window->phys);
+ }
+
+ /* no windows defined, register must be 1:1 mapped virt:phys */
+ return (void __iomem *)address;
+}
static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
{
@@ -31,41 +100,54 @@ static int enum_in_range(pinmux_enum_t enum_id, struct pinmux_range *r)
return 1;
}
-static unsigned long gpio_read_raw_reg(unsigned long reg,
+static unsigned long gpio_read_raw_reg(void __iomem *mapped_reg,
unsigned long reg_width)
{
switch (reg_width) {
case 8:
- return __raw_readb(reg);
+ return ioread8(mapped_reg);
case 16:
- return __raw_readw(reg);
+ return ioread16(mapped_reg);
case 32:
- return __raw_readl(reg);
+ return ioread32(mapped_reg);
}
BUG();
return 0;
}
-static void gpio_write_raw_reg(unsigned long reg,
+static void gpio_write_raw_reg(void __iomem *mapped_reg,
unsigned long reg_width,
unsigned long data)
{
switch (reg_width) {
case 8:
- __raw_writeb(data, reg);
+ iowrite8(data, mapped_reg);
return;
case 16:
- __raw_writew(data, reg);
+ iowrite16(data, mapped_reg);
return;
case 32:
- __raw_writel(data, reg);
+ iowrite32(data, mapped_reg);
return;
}
BUG();
}
+static int gpio_read_bit(struct pinmux_data_reg *dr,
+ unsigned long in_pos)
+{
+ unsigned long pos;
+
+ pos = dr->reg_width - (in_pos + 1);
+
+ pr_debug("read_bit: addr = %lx, pos = %ld, "
+ "r_width = %ld\n", dr->reg, pos, dr->reg_width);
+
+ return (gpio_read_raw_reg(dr->mapped_reg, dr->reg_width) >> pos) & 1;
+}
+
static void gpio_write_bit(struct pinmux_data_reg *dr,
unsigned long in_pos, unsigned long value)
{
@@ -82,53 +164,72 @@ static void gpio_write_bit(struct pinmux_data_reg *dr,
else
clear_bit(pos, &dr->reg_shadow);
- gpio_write_raw_reg(dr->reg, dr->reg_width, dr->reg_shadow);
+ gpio_write_raw_reg(dr->mapped_reg, dr->reg_width, dr->reg_shadow);
}
-static int gpio_read_reg(unsigned long reg, unsigned long reg_width,
- unsigned long field_width, unsigned long in_pos)
+static void config_reg_helper(struct pinmux_info *gpioc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long in_pos,
+ void __iomem **mapped_regp,
+ unsigned long *maskp,
+ unsigned long *posp)
{
- unsigned long data, mask, pos;
+ int k;
+
+ *mapped_regp = pfc_phys_to_virt(gpioc, crp->reg);
- data = 0;
- mask = (1 << field_width) - 1;
- pos = reg_width - ((in_pos + 1) * field_width);
+ if (crp->field_width) {
+ *maskp = (1 << crp->field_width) - 1;
+ *posp = crp->reg_width - ((in_pos + 1) * crp->field_width);
+ } else {
+ *maskp = (1 << crp->var_field_width[in_pos]) - 1;
+ *posp = crp->reg_width;
+ for (k = 0; k <= in_pos; k++)
+ *posp -= crp->var_field_width[k];
+ }
+}
- pr_debug("read_reg: addr = %lx, pos = %ld, "
+static int read_config_reg(struct pinmux_info *gpioc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long field)
+{
+ void __iomem *mapped_reg;
+ unsigned long mask, pos;
+
+ config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
+
+ pr_debug("read_reg: addr = %lx, field = %ld, "
"r_width = %ld, f_width = %ld\n",
- reg, pos, reg_width, field_width);
+ crp->reg, field, crp->reg_width, crp->field_width);
- data = gpio_read_raw_reg(reg, reg_width);
- return (data >> pos) & mask;
+ return (gpio_read_raw_reg(mapped_reg, crp->reg_width) >> pos) & mask;
}
-static void gpio_write_reg(unsigned long reg, unsigned long reg_width,
- unsigned long field_width, unsigned long in_pos,
- unsigned long value)
+static void write_config_reg(struct pinmux_info *gpioc,
+ struct pinmux_cfg_reg *crp,
+ unsigned long field, unsigned long value)
{
- unsigned long mask, pos;
+ void __iomem *mapped_reg;
+ unsigned long mask, pos, data;
- mask = (1 << field_width) - 1;
- pos = reg_width - ((in_pos + 1) * field_width);
+ config_reg_helper(gpioc, crp, field, &mapped_reg, &mask, &pos);
- pr_debug("write_reg addr = %lx, value = %ld, pos = %ld, "
+ pr_debug("write_reg addr = %lx, value = %ld, field = %ld, "
"r_width = %ld, f_width = %ld\n",
- reg, value, pos, reg_width, field_width);
+ crp->reg, value, field, crp->reg_width, crp->field_width);
mask = ~(mask << pos);
value = value << pos;
- switch (reg_width) {
- case 8:
- __raw_writeb((__raw_readb(reg) & mask) | value, reg);
- break;
- case 16:
- __raw_writew((__raw_readw(reg) & mask) | value, reg);
- break;
- case 32:
- __raw_writel((__raw_readl(reg) & mask) | value, reg);
- break;
- }
+ data = gpio_read_raw_reg(mapped_reg, crp->reg_width);
+ data &= mask;
+ data |= value;
+
+ if (gpioc->unlock_reg)
+ gpio_write_raw_reg(pfc_phys_to_virt(gpioc, gpioc->unlock_reg),
+ 32, ~data);
+
+ gpio_write_raw_reg(mapped_reg, crp->reg_width, data);
}
static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
@@ -147,6 +248,8 @@ static int setup_data_reg(struct pinmux_info *gpioc, unsigned gpio)
if (!data_reg->reg_width)
break;
+ data_reg->mapped_reg = pfc_phys_to_virt(gpioc, data_reg->reg);
+
for (n = 0; n < data_reg->reg_width; n++) {
if (data_reg->enum_ids[n] == gpiop->enum_id) {
gpiop->flags &= ~PINMUX_FLAG_DREG;
@@ -179,7 +282,8 @@ static void setup_data_regs(struct pinmux_info *gpioc)
if (!drp->reg_width)
break;
- drp->reg_shadow = gpio_read_raw_reg(drp->reg, drp->reg_width);
+ drp->reg_shadow = gpio_read_raw_reg(drp->mapped_reg,
+ drp->reg_width);
k++;
}
}
@@ -201,12 +305,13 @@ static int get_data_reg(struct pinmux_info *gpioc, unsigned gpio,
}
static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
- struct pinmux_cfg_reg **crp, int *indexp,
+ struct pinmux_cfg_reg **crp,
+ int *fieldp, int *valuep,
unsigned long **cntp)
{
struct pinmux_cfg_reg *config_reg;
- unsigned long r_width, f_width;
- int k, n;
+ unsigned long r_width, f_width, curr_width, ncomb;
+ int k, m, n, pos, bit_pos;
k = 0;
while (1) {
@@ -217,13 +322,27 @@ static int get_config_reg(struct pinmux_info *gpioc, pinmux_enum_t enum_id,
if (!r_width)
break;
- for (n = 0; n < (r_width / f_width) * (1 << f_width); n++) {
- if (config_reg->enum_ids[n] == enum_id) {
- *crp = config_reg;
- *indexp = n;
- *cntp = &config_reg->cnt[n / (1 << f_width)];
- return 0;
+
+ pos = 0;
+ m = 0;
+ for (bit_pos = 0; bit_pos < r_width; bit_pos += curr_width) {
+ if (f_width)
+ curr_width = f_width;
+ else
+ curr_width = config_reg->var_field_width[m];
+
+ ncomb = 1 << curr_width;
+ for (n = 0; n < ncomb; n++) {
+ if (config_reg->enum_ids[pos + n] == enum_id) {
+ *crp = config_reg;
+ *fieldp = m;
+ *valuep = n;
+ *cntp = &config_reg->cnt[m];
+ return 0;
+ }
}
+ pos += ncomb;
+ m++;
}
k++;
}
@@ -261,36 +380,6 @@ static int get_gpio_enum_id(struct pinmux_info *gpioc, unsigned gpio,
return -1;
}
-static void write_config_reg(struct pinmux_info *gpioc,
- struct pinmux_cfg_reg *crp,
- int index)
-{
- unsigned long ncomb, pos, value;
-
- ncomb = 1 << crp->field_width;
- pos = index / ncomb;
- value = index % ncomb;
-
- gpio_write_reg(crp->reg, crp->reg_width, crp->field_width, pos, value);
-}
-
-static int check_config_reg(struct pinmux_info *gpioc,
- struct pinmux_cfg_reg *crp,
- int index)
-{
- unsigned long ncomb, pos, value;
-
- ncomb = 1 << crp->field_width;
- pos = index / ncomb;
- value = index % ncomb;
-
- if (gpio_read_reg(crp->reg, crp->reg_width,
- crp->field_width, pos) == value)
- return 0;
-
- return -1;
-}
-
enum { GPIO_CFG_DRYRUN, GPIO_CFG_REQ, GPIO_CFG_FREE };
static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
@@ -299,7 +388,7 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
struct pinmux_cfg_reg *cr = NULL;
pinmux_enum_t enum_id;
struct pinmux_range *range;
- int in_range, pos, index;
+ int in_range, pos, field, value;
unsigned long *cntp;
switch (pinmux_type) {
@@ -330,7 +419,8 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
pos = 0;
enum_id = 0;
- index = 0;
+ field = 0;
+ value = 0;
while (1) {
pos = get_gpio_enum_id(gpioc, gpio, pos, &enum_id);
if (pos <= 0)
@@ -377,17 +467,19 @@ static int pinmux_config_gpio(struct pinmux_info *gpioc, unsigned gpio,
if (!in_range)
continue;
- if (get_config_reg(gpioc, enum_id, &cr, &index, &cntp) != 0)
+ if (get_config_reg(gpioc, enum_id, &cr,
+ &field, &value, &cntp) != 0)
goto out_err;
switch (cfg_mode) {
case GPIO_CFG_DRYRUN:
- if (!*cntp || !check_config_reg(gpioc, cr, index))
+ if (!*cntp ||
+ (read_config_reg(gpioc, cr, field) != value))
continue;
break;
case GPIO_CFG_REQ:
- write_config_reg(gpioc, cr, index);
+ write_config_reg(gpioc, cr, field, value);
*cntp = *cntp + 1;
break;
@@ -564,7 +656,7 @@ static int sh_gpio_get_value(struct pinmux_info *gpioc, unsigned gpio)
if (!gpioc || get_data_reg(gpioc, gpio, &dr, &bit) != 0)
return -EINVAL;
- return gpio_read_reg(dr->reg, dr->reg_width, 1, bit);
+ return gpio_read_bit(dr, bit);
}
static int sh_gpio_get(struct gpio_chip *chip, unsigned offset)
@@ -606,10 +698,15 @@ static int sh_gpio_to_irq(struct gpio_chip *chip, unsigned offset)
int register_pinmux(struct pinmux_info *pip)
{
struct gpio_chip *chip = &pip->chip;
+ int ret;
pr_info("%s handling gpio %d -> %d\n",
pip->name, pip->first_gpio, pip->last_gpio);
+ ret = pfc_ioremap(pip);
+ if (ret < 0)
+ return ret;
+
setup_data_regs(pip);
chip->request = sh_gpio_request;
@@ -627,12 +724,16 @@ int register_pinmux(struct pinmux_info *pip)
chip->base = pip->first_gpio;
chip->ngpio = (pip->last_gpio - pip->first_gpio) + 1;
- return gpiochip_add(chip);
+ ret = gpiochip_add(chip);
+ if (ret < 0)
+ pfc_iounmap(pip);
+
+ return ret;
}
int unregister_pinmux(struct pinmux_info *pip)
{
pr_info("%s deregistering\n", pip->name);
-
+ pfc_iounmap(pip);
return gpiochip_remove(&pip->chip);
}
diff --git a/drivers/tty/serial/sh-sci.c b/drivers/tty/serial/sh-sci.c
index aff9d612dff0..9e62349b3d9f 100644
--- a/drivers/tty/serial/sh-sci.c
+++ b/drivers/tty/serial/sh-sci.c
@@ -50,6 +50,7 @@
#include <linux/dma-mapping.h>
#include <linux/scatterlist.h>
#include <linux/slab.h>
+#include <linux/gpio.h>
#ifdef CONFIG_SUPERH
#include <asm/sh_bios.h>
@@ -73,6 +74,7 @@ struct sci_port {
struct clk *fclk;
char *irqstr[SCIx_NR_IRQS];
+ char *gpiostr[SCIx_NR_FNS];
struct dma_chan *chan_tx;
struct dma_chan *chan_rx;
@@ -474,8 +476,15 @@ static void sci_init_pins(struct uart_port *port, unsigned int cflag)
if (!reg->size)
return;
- if (!(cflag & CRTSCTS))
- sci_out(port, SCSPTR, 0x0080); /* Set RTS = 1 */
+ if ((s->cfg->capabilities & SCIx_HAVE_RTSCTS) &&
+ ((!(cflag & CRTSCTS)))) {
+ unsigned short status;
+
+ status = sci_in(port, SCSPTR);
+ status &= ~SCSPTR_CTSIO;
+ status |= SCSPTR_RTSIO;
+ sci_out(port, SCSPTR, status); /* Set RTS = 1 */
+ }
}
static int sci_txfill(struct uart_port *port)
@@ -621,6 +630,7 @@ static void sci_receive_chars(struct uart_port *port)
} else {
for (i = 0; i < count; i++) {
char c = sci_in(port, SCxRDR);
+
status = sci_in(port, SCxSR);
#if defined(CONFIG_CPU_SH3)
/* Skip "chars" during break */
@@ -649,9 +659,11 @@ static void sci_receive_chars(struct uart_port *port)
/* Store data and status */
if (status & SCxSR_FER(port)) {
flag = TTY_FRAME;
+ port->icount.frame++;
dev_notice(port->dev, "frame error\n");
} else if (status & SCxSR_PER(port)) {
flag = TTY_PARITY;
+ port->icount.parity++;
dev_notice(port->dev, "parity error\n");
} else
flag = TTY_NORMAL;
@@ -723,6 +735,8 @@ static int sci_handle_errors(struct uart_port *port)
*/
if (s->cfg->overrun_bit != SCIx_NOT_SUPPORTED) {
if (status & (1 << s->cfg->overrun_bit)) {
+ port->icount.overrun++;
+
/* overrun error */
if (tty_insert_flip_char(tty, 0, TTY_OVERRUN))
copied++;
@@ -737,6 +751,8 @@ static int sci_handle_errors(struct uart_port *port)
struct sci_port *sci_port = to_sci_port(port);
if (!sci_port->break_flag) {
+ port->icount.brk++;
+
sci_port->break_flag = 1;
sci_schedule_break_timer(sci_port);
@@ -752,6 +768,8 @@ static int sci_handle_errors(struct uart_port *port)
} else {
/* frame error */
+ port->icount.frame++;
+
if (tty_insert_flip_char(tty, 0, TTY_FRAME))
copied++;
@@ -761,6 +779,8 @@ static int sci_handle_errors(struct uart_port *port)
if (status & SCxSR_PER(port)) {
/* parity error */
+ port->icount.parity++;
+
if (tty_insert_flip_char(tty, 0, TTY_PARITY))
copied++;
@@ -787,6 +807,8 @@ static int sci_handle_fifo_overrun(struct uart_port *port)
if ((sci_in(port, SCLSR) & (1 << s->cfg->overrun_bit))) {
sci_out(port, SCLSR, 0);
+ port->icount.overrun++;
+
tty_insert_flip_char(tty, 0, TTY_OVERRUN);
tty_flip_buffer_push(tty);
@@ -812,6 +834,9 @@ static int sci_handle_breaks(struct uart_port *port)
/* Debounce break */
s->break_flag = 1;
#endif
+
+ port->icount.brk++;
+
/* Notify of BREAK */
if (tty_insert_flip_char(tty, 0, TTY_BREAK))
copied++;
@@ -1082,6 +1107,67 @@ static void sci_free_irq(struct sci_port *port)
}
}
+static const char *sci_gpio_names[SCIx_NR_FNS] = {
+ "sck", "rxd", "txd", "cts", "rts",
+};
+
+static const char *sci_gpio_str(unsigned int index)
+{
+ return sci_gpio_names[index];
+}
+
+static void __devinit sci_init_gpios(struct sci_port *port)
+{
+ struct uart_port *up = &port->port;
+ int i;
+
+ if (!port->cfg)
+ return;
+
+ for (i = 0; i < SCIx_NR_FNS; i++) {
+ const char *desc;
+ int ret;
+
+ if (!port->cfg->gpios[i])
+ continue;
+
+ desc = sci_gpio_str(i);
+
+ port->gpiostr[i] = kasprintf(GFP_KERNEL, "%s:%s",
+ dev_name(up->dev), desc);
+
+ /*
+ * If we've failed the allocation, we can still continue
+ * on with a NULL string.
+ */
+ if (!port->gpiostr[i])
+ dev_notice(up->dev, "%s string allocation failure\n",
+ desc);
+
+ ret = gpio_request(port->cfg->gpios[i], port->gpiostr[i]);
+ if (unlikely(ret != 0)) {
+ dev_notice(up->dev, "failed %s gpio request\n", desc);
+
+ /*
+ * If we can't get the GPIO for whatever reason,
+ * no point in keeping the verbose string around.
+ */
+ kfree(port->gpiostr[i]);
+ }
+ }
+}
+
+static void sci_free_gpios(struct sci_port *port)
+{
+ int i;
+
+ for (i = 0; i < SCIx_NR_FNS; i++)
+ if (port->cfg->gpios[i]) {
+ gpio_free(port->cfg->gpios[i]);
+ kfree(port->gpiostr[i]);
+ }
+}
+
static unsigned int sci_tx_empty(struct uart_port *port)
{
unsigned short status = sci_in(port, SCxSR);
@@ -1090,19 +1176,39 @@ static unsigned int sci_tx_empty(struct uart_port *port)
return (status & SCxSR_TEND(port)) && !in_tx_fifo ? TIOCSER_TEMT : 0;
}
+/*
+ * Modem control is a bit of a mixed bag for SCI(F) ports. Generally
+ * CTS/RTS is supported in hardware by at least one port and controlled
+ * via SCSPTR (SCxPCR for SCIFA/B parts), or external pins (presently
+ * handled via the ->init_pins() op, which is a bit of a one-way street,
+ * lacking any ability to defer pin control -- this will later be
+ * converted over to the GPIO framework).
+ *
+ * Other modes (such as loopback) are supported generically on certain
+ * port types, but not others. For these it's sufficient to test for the
+ * existence of the support register and simply ignore the port type.
+ */
static void sci_set_mctrl(struct uart_port *port, unsigned int mctrl)
{
- /* This routine is used for seting signals of: DTR, DCD, CTS/RTS */
- /* We use SCIF's hardware for CTS/RTS, so don't need any for that. */
- /* If you have signals for DTR and DCD, please implement here. */
+ if (mctrl & TIOCM_LOOP) {
+ struct plat_sci_reg *reg;
+
+ /*
+ * Standard loopback mode for SCFCR ports.
+ */
+ reg = sci_getreg(port, SCFCR);
+ if (reg->size)
+ sci_out(port, SCFCR, sci_in(port, SCFCR) | 1);
+ }
}
static unsigned int sci_get_mctrl(struct uart_port *port)
{
- /* This routine is used for getting signals of: DTR, DCD, DSR, RI,
- and CTS/RTS */
-
- return TIOCM_DTR | TIOCM_RTS | TIOCM_CTS | TIOCM_DSR;
+ /*
+ * CTS/RTS is handled in hardware when supported, while nothing
+ * else is wired up. Keep it simple and simply assert DSR/CAR.
+ */
+ return TIOCM_DSR | TIOCM_CAR;
}
#ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -1449,12 +1555,17 @@ static void sci_stop_rx(struct uart_port *port)
static void sci_enable_ms(struct uart_port *port)
{
- /* Nothing here yet .. */
+ /*
+ * Not supported by hardware, always a nop.
+ */
}
static void sci_break_ctl(struct uart_port *port, int break_state)
{
- /* Nothing here yet .. */
+ /*
+ * Not supported by hardware. Most parts couple break and rx
+ * interrupts together, with break detection always enabled.
+ */
}
#ifdef CONFIG_SERIAL_SH_SCI_DMA
@@ -1652,6 +1763,7 @@ static unsigned int sci_scbrr_calc(unsigned int algo_id, unsigned int bps,
static void sci_reset(struct uart_port *port)
{
+ struct plat_sci_reg *reg;
unsigned int status;
do {
@@ -1660,7 +1772,8 @@ static void sci_reset(struct uart_port *port)
sci_out(port, SCSCR, 0x00); /* TE=0, RE=0, CKE1=0 */
- if (port->type != PORT_SCI)
+ reg = sci_getreg(port, SCFCR);
+ if (reg->size)
sci_out(port, SCFCR, SCFCR_RFRST | SCFCR_TFRST);
}
@@ -1668,9 +1781,9 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
struct ktermios *old)
{
struct sci_port *s = to_sci_port(port);
+ struct plat_sci_reg *reg;
unsigned int baud, smr_val, max_baud;
int t = -1;
- u16 scfcr = 0;
/*
* earlyprintk comes here early on with port->uartclk set to zero.
@@ -1720,7 +1833,27 @@ static void sci_set_termios(struct uart_port *port, struct ktermios *termios,
}
sci_init_pins(port, termios->c_cflag);
- sci_out(port, SCFCR, scfcr | ((termios->c_cflag & CRTSCTS) ? SCFCR_MCE : 0));
+
+ reg = sci_getreg(port, SCFCR);
+ if (reg->size) {
+ unsigned short ctrl = sci_in(port, SCFCR);
+
+ if (s->cfg->capabilities & SCIx_HAVE_RTSCTS) {
+ if (termios->c_cflag & CRTSCTS)
+ ctrl |= SCFCR_MCE;
+ else
+ ctrl &= ~SCFCR_MCE;
+ }
+
+ /*
+ * As we've done a sci_reset() above, ensure we don't
+ * interfere with the FIFOs while toggling MCE. As the
+ * reset values could still be set, simply mask them out.
+ */
+ ctrl &= ~(SCFCR_RFRST | SCFCR_TFRST);
+
+ sci_out(port, SCFCR, ctrl);
+ }
sci_out(port, SCSCR, s->cfg->scscr);
@@ -1892,6 +2025,8 @@ static int __devinit sci_init_single(struct platform_device *dev,
struct uart_port *port = &sci_port->port;
int ret;
+ sci_port->cfg = p;
+
port->ops = &sci_uart_ops;
port->iotype = UPIO_MEM;
port->line = index;
@@ -1937,6 +2072,8 @@ static int __devinit sci_init_single(struct platform_device *dev,
port->dev = &dev->dev;
+ sci_init_gpios(sci_port);
+
pm_runtime_irq_safe(&dev->dev);
pm_runtime_enable(&dev->dev);
}
@@ -1971,8 +2108,6 @@ static int __devinit sci_init_single(struct platform_device *dev,
p->error_mask |= (1 << p->overrun_bit);
}
- sci_port->cfg = p;
-
port->mapbase = p->mapbase;
port->type = p->type;
port->flags = p->flags;
@@ -2113,9 +2248,16 @@ static int sci_runtime_suspend(struct device *dev)
struct uart_port *port = &sci_port->port;
if (uart_console(port)) {
+ struct plat_sci_reg *reg;
+
sci_port->saved_smr = sci_in(port, SCSMR);
sci_port->saved_brr = sci_in(port, SCBRR);
- sci_port->saved_fcr = sci_in(port, SCFCR);
+
+ reg = sci_getreg(port, SCFCR);
+ if (reg->size)
+ sci_port->saved_fcr = sci_in(port, SCFCR);
+ else
+ sci_port->saved_fcr = 0;
}
return 0;
}
@@ -2129,7 +2271,10 @@ static int sci_runtime_resume(struct device *dev)
sci_reset(port);
sci_out(port, SCSMR, sci_port->saved_smr);
sci_out(port, SCBRR, sci_port->saved_brr);
- sci_out(port, SCFCR, sci_port->saved_fcr);
+
+ if (sci_port->saved_fcr)
+ sci_out(port, SCFCR, sci_port->saved_fcr);
+
sci_out(port, SCSCR, sci_port->cfg->scscr);
}
return 0;
@@ -2169,6 +2314,8 @@ static int sci_remove(struct platform_device *dev)
cpufreq_unregister_notifier(&port->freq_transition,
CPUFREQ_TRANSITION_NOTIFIER);
+ sci_free_gpios(port);
+
uart_remove_one_port(&sci_uart_driver, &port->port);
clk_put(port->iclk);
diff --git a/drivers/tty/serial/sh-sci.h b/drivers/tty/serial/sh-sci.h
index e9bed038aa1f..a1a2d364f92b 100644
--- a/drivers/tty/serial/sh-sci.h
+++ b/drivers/tty/serial/sh-sci.h
@@ -17,7 +17,9 @@
defined(CONFIG_ARCH_SH73A0) || \
defined(CONFIG_ARCH_SH7367) || \
defined(CONFIG_ARCH_SH7377) || \
- defined(CONFIG_ARCH_SH7372)
+ defined(CONFIG_ARCH_SH7372) || \
+ defined(CONFIG_ARCH_R8A7740)
+
# define SCxSR_RDxF_CLEAR(port) (sci_in(port, SCxSR) & 0xfffc)
# define SCxSR_ERROR_CLEAR(port) (sci_in(port, SCxSR) & 0xfd73)
# define SCxSR_TDxE_CLEAR(port) (sci_in(port, SCxSR) & 0xffdf)
diff --git a/drivers/uio/uio_pci_generic.c b/drivers/uio/uio_pci_generic.c
index 02bd47bdee1c..0bd08ef2b394 100644
--- a/drivers/uio/uio_pci_generic.c
+++ b/drivers/uio/uio_pci_generic.c
@@ -45,77 +45,12 @@ to_uio_pci_generic_dev(struct uio_info *info)
static irqreturn_t irqhandler(int irq, struct uio_info *info)
{
struct uio_pci_generic_dev *gdev = to_uio_pci_generic_dev(info);
- struct pci_dev *pdev = gdev->pdev;
- irqreturn_t ret = IRQ_NONE;
- u32 cmd_status_dword;
- u16 origcmd, newcmd, status;
-
- /* We do a single dword read to retrieve both command and status.
- * Document assumptions that make this possible. */
- BUILD_BUG_ON(PCI_COMMAND % 4);
- BUILD_BUG_ON(PCI_COMMAND + 2 != PCI_STATUS);
-
- pci_block_user_cfg_access(pdev);
-
- /* Read both command and status registers in a single 32-bit operation.
- * Note: we could cache the value for command and move the status read
- * out of the lock if there was a way to get notified of user changes
- * to command register through sysfs. Should be good for shared irqs. */
- pci_read_config_dword(pdev, PCI_COMMAND, &cmd_status_dword);
- origcmd = cmd_status_dword;
- status = cmd_status_dword >> 16;
-
- /* Check interrupt status register to see whether our device
- * triggered the interrupt. */
- if (!(status & PCI_STATUS_INTERRUPT))
- goto done;
-
- /* We triggered the interrupt, disable it. */
- newcmd = origcmd | PCI_COMMAND_INTX_DISABLE;
- if (newcmd != origcmd)
- pci_write_config_word(pdev, PCI_COMMAND, newcmd);
- /* UIO core will signal the user process. */
- ret = IRQ_HANDLED;
-done:
-
- pci_unblock_user_cfg_access(pdev);
- return ret;
-}
+ if (!pci_check_and_mask_intx(gdev->pdev))
+ return IRQ_NONE;
-/* Verify that the device supports Interrupt Disable bit in command register,
- * per PCI 2.3, by flipping this bit and reading it back: this bit was readonly
- * in PCI 2.2. */
-static int __devinit verify_pci_2_3(struct pci_dev *pdev)
-{
- u16 orig, new;
- int err = 0;
-
- pci_block_user_cfg_access(pdev);
- pci_read_config_word(pdev, PCI_COMMAND, &orig);
- pci_write_config_word(pdev, PCI_COMMAND,
- orig ^ PCI_COMMAND_INTX_DISABLE);
- pci_read_config_word(pdev, PCI_COMMAND, &new);
- /* There's no way to protect against
- * hardware bugs or detect them reliably, but as long as we know
- * what the value should be, let's go ahead and check it. */
- if ((new ^ orig) & ~PCI_COMMAND_INTX_DISABLE) {
- err = -EBUSY;
- dev_err(&pdev->dev, "Command changed from 0x%x to 0x%x: "
- "driver or HW bug?\n", orig, new);
- goto err;
- }
- if (!((new ^ orig) & PCI_COMMAND_INTX_DISABLE)) {
- dev_warn(&pdev->dev, "Device does not support "
- "disabling interrupts: unable to bind.\n");
- err = -ENODEV;
- goto err;
- }
- /* Now restore the original value. */
- pci_write_config_word(pdev, PCI_COMMAND, orig);
-err:
- pci_unblock_user_cfg_access(pdev);
- return err;
+ /* UIO core will signal the user process. */
+ return IRQ_HANDLED;
}
static int __devinit probe(struct pci_dev *pdev,
@@ -138,9 +73,10 @@ static int __devinit probe(struct pci_dev *pdev,
return -ENODEV;
}
- err = verify_pci_2_3(pdev);
- if (err)
+ if (!pci_intx_mask_supported(pdev)) {
+ err = -ENODEV;
goto err_verify;
+ }
gdev = kzalloc(sizeof(struct uio_pci_generic_dev), GFP_KERNEL);
if (!gdev) {